@@ -325,7 +325,8 @@ struct VM {
325325 MUTEX,
326326 EXTREME,
327327 NO_MEMO,
328- WIN_HYPERV_DEFAULT
328+ WIN_HYPERV_DEFAULT,
329+ MULTIPLE
329330 };
330331private:
331332 static constexpr u8 enum_size = __LINE__ - enum_line_start - 4 ; // get enum size
@@ -576,18 +577,6 @@ struct VM {
576577 qnx = " QNXQVMBSQG " ,
577578 virtapple = " VirtualApple" ;
578579
579- #if (CPP >= 17)
580- constexpr std::array<std::string_view, 13 > IDs{
581- #else
582- std::array<std::string, 13 > IDs {
583- #endif
584- bhyve, kvm, qemu,
585- hyperv, parallels, parallels,
586- parallels2, vmware, vbox,
587- xen, acrn, qnx,
588- virtapple
589- };
590-
591580 auto cpuid_thingy = [](const u32 p_leaf, u32 * regs, std::size_t start = 0 , std::size_t end = 4 ) -> bool {
592581 u32 x[4 ]{};
593582 cpu::cpuid (x[0 ], x[1 ], x[2 ], x[3 ], p_leaf);
@@ -611,36 +600,44 @@ struct VM {
611600 return str;
612601 };
613602
614- std::stringstream ss;
615- ss << strconvert (sig_reg[0 ]);
616- ss << strconvert (sig_reg[1 ]);
617- ss << strconvert (sig_reg[2 ]);
603+ std::stringstream ss1;
604+ std::stringstream ss2;
605+
606+ ss1 << strconvert (sig_reg[0 ]);
607+ ss1 << strconvert (sig_reg[1 ]);
608+ ss1 << strconvert (sig_reg[2 ]);
618609
619- brand = ss.str ();
610+ ss2 << strconvert (sig_reg[0 ]);
611+ ss2 << strconvert (sig_reg[2 ]);
612+ ss2 << strconvert (sig_reg[1 ]);
620613
621- debug (technique_name, brand);
614+ std::string brand1 = ss1.str ();
615+ std::string brand2 = ss2.str ();
616+
617+ debug (technique_name, brand1);
618+ debug (technique_name, brand2);
622619
623620#if (CPP < 17)
624621 // bypass compiler warning about unused parameter, ignore this
625622 UNUSED (technique_name);
626623#endif
627624
628- const bool found = ( std::find ( std::begin (IDs), std::end (IDs), brand) != std::end (IDs)) ;
629-
630- if (found ) {
631- if (brand == qemu) { return core::add (QEMU); }
632- if (brand == vmware) { return core::add (VMWARE); }
633- if (brand == vbox) { return core::add (VBOX); }
634- if (brand == bhyve) { return core::add (BHYVE); }
635- if (brand == kvm) { return core::add (KVM); }
636- if (brand == xta) { return core::add (MSXTA); }
637- if (brand == parallels) { return core::add (PARALLELS); }
638- if (brand == parallels2) { return core::add (PARALLELS); }
639- if (brand == xen) { return core::add (XEN); }
640- if (brand == acrn) { return core::add (ACRN); }
641- if (brand == qnx) { return core::add (QNX); }
642- if (brand == virtapple) { return core::add (VAPPLE); }
643- if (brand == hyperv) {
625+ const std::vector< std::string> brand_streams = { brand1, brand2 } ;
626+
627+ for ( const auto &tmp_brand : brand_streams ) {
628+ if (tmp_brand == qemu) { return core::add (QEMU); }
629+ if (tmp_brand == vmware) { return core::add (VMWARE); }
630+ if (tmp_brand == vbox) { return core::add (VBOX); }
631+ if (tmp_brand == bhyve) { return core::add (BHYVE); }
632+ if (tmp_brand == kvm) { return core::add (KVM); }
633+ if (tmp_brand == xta) { return core::add (MSXTA); }
634+ if (tmp_brand == parallels) { return core::add (PARALLELS); }
635+ if (tmp_brand == parallels2) { return core::add (PARALLELS); }
636+ if (tmp_brand == xen) { return core::add (XEN); }
637+ if (tmp_brand == acrn) { return core::add (ACRN); }
638+ if (tmp_brand == qnx) { return core::add (QNX); }
639+ if (tmp_brand == virtapple) { return core::add (VAPPLE); }
640+ if (tmp_brand == hyperv) {
644641 bool tmp = core::add (VPC);
645642 UNUSED (tmp);
646643 return core::add (HYPERV);
@@ -654,7 +651,7 @@ struct VM {
654651 * but the Wikipedia article on CPUID says it's
655652 * "KVMKVMKVM\0\0\0", like wtf????
656653 */
657- if (util::find (brand , " KVM" )) {
654+ if (util::find (brand1, " KVM " ) || util::find (brand2 , " KVM" )) {
658655 return core::add (KVM);
659656 }
660657
@@ -5695,7 +5692,7 @@ struct VM {
56955692#endif
56965693 ss << " . Consult the documentation's flag handler for VM::check()" ;
56975694 throw std::invalid_argument (std::string (text) + ss.str ());
5698- };
5695+ };
56995696
57005697 if (p_flag > enum_size) {
57015698 throw_error (" Flag argument must be a valid" );
@@ -5708,7 +5705,7 @@ struct VM {
57085705 if (
57095706 (p_flag == NO_MEMO) || \
57105707 (p_flag == EXTREME)
5711- ) {
5708+ ) {
57125709 throw_error (" Flag argument must be a technique flag and not a settings flag" );
57135710 }
57145711
@@ -5723,7 +5720,7 @@ struct VM {
57235720
57245721 auto it = core::table.find (p_flag);
57255722
5726- if (/* VMAWARE_UNLIKELY */ (it == core::table.end ())) {
5723+ if ((it == core::table.end ())) {
57275724 throw_error (" Flag is not known" );
57285725 }
57295726
@@ -5738,72 +5735,55 @@ struct VM {
57385735
57395736 /* *
57405737 * @brief Fetch the VM brand
5741- * @param any combination of flags, can be optional
5738+ * @param either nothing or VM::MULTIPLE
57425739 * @return std::string
57435740 * @returns VMware, VirtualBox, KVM, bhyve, QEMU, Microsoft Hyper-V, Microsoft x86-to-ARM, Parallels, Xen HVM, ACRN, QNX hypervisor, Hybrid Analysis, Sandboxie, Docker, Wine, Virtual Apple, Virtual PC, Unknown
57445741 * @link https://github.com/kernelwernel/VMAware/blob/main/docs/documentation.md#vmbrand
57455742 */
5746- [[nodiscard]] static std::string brand (const flagset p_flags = DEFAULT ) {
5743+ [[nodiscard]] static std::string brand (u8 is_multiple = false ) {
57475744 {
57485745 // this is added to set the brand scoreboard table
5749- u16 tmp = core::run_all (p_flags );
5746+ u16 tmp = core::run_all (DEFAULT );
57505747 UNUSED (tmp);
57515748 }
57525749
5753- const char * current_brand = " " ;
5754-
5755- // fetch the brand with the most points in the scoreboard
5756- #if (CPP >= 20)
5757- auto it = std::ranges::max_element (core::brand_scoreboard, {},
5758- [](const auto & pair) {
5759- return pair.second ;
5760- }
5761- );
5750+ #define brands core::brand_scoreboard
57625751
5763- if (it != core::brand_scoreboard.end ()) {
5764- if (
5765- std::none_of (core::brand_scoreboard.cbegin (), core::brand_scoreboard.cend (),
5766- [](const auto & pair) {
5767- return pair.second ;
5768- }
5769- )
5770- ) {
5771- current_brand = " Unknown" ;
5772- }
5773- else {
5774- current_brand = it->first ;
5775- }
5752+ #ifdef __VMAWARE_DEBUG__
5753+ for (const auto p : brands) {
5754+ debug (" scoreboard: " , (int )p.second , " : " , p.first );
57765755 }
5777- else {
5778- current_brand = " Unknown" ;
5756+ #endif
5757+
5758+ if (is_multiple == VM::MULTIPLE) {
5759+ is_multiple = true ;
5760+ } else if (is_multiple != 0 ) {
5761+ throw std::invalid_argument (" Flag for VM::brand() must either be empty or VM::MULTIPLE. Consult the documentation's flag handler for VM::check()" );
57795762 }
5780- #else
5781- #if (MSVC)
5782- int max = 0 ;
5783- #else
5784- u8 max = 0 ;
5785- #endif
57865763
5787- #if (CPP >= 17)
5788- for (const auto & [brand, points] : core::brand_scoreboard) {
5764+ const char * current_brand = " " ;
5765+ i32 max = 0 ;
5766+
5767+ // both do the same thing
5768+ #if (CPP >= 17)
5769+ for (const auto & [brand, points] : brands) {
57895770 if (points > max) {
57905771 current_brand = brand;
57915772 max = points;
57925773 }
57935774 }
5794- #else
5795- for (auto it = core::brand_scoreboard .cbegin (); it != core::brand_scoreboard .cend (); ++it) {
5775+ #else
5776+ for (auto it = brands .cbegin (); it != brands .cend (); ++it) {
57965777 if (it->second > max) {
57975778 current_brand = it->first ;
57985779 max = it->second ;
57995780 }
58005781 }
5801- #endif
5782+ #endif
58025783
58035784 if (max == 0 ) {
5804- current_brand = " Unknown" ;
5785+ return " Unknown" ;
58055786 }
5806- #endif
58075787
58085788 // goofy ass C++11 and C++14 linker error workaround
58095789#if (CPP <= 14)
@@ -5832,23 +5812,17 @@ struct VM {
58325812 constexpr const char * TMP_HYPERV = VM::HYPERV;
58335813#endif
58345814
5835- #define brands core::brand_scoreboard
5836-
58375815 if (
58385816 brands.at (TMP_QEMU) > 0 &&
58395817 brands.at (TMP_KVM) > 0
58405818 ) {
58415819 current_brand = " QEMU+KVM" ;
5842- }
5843-
5844- if (
5820+ } else if (
58455821 brands.at (TMP_VPC) > 0 &&
58465822 brands.at (TMP_HYPERV) > 0
58475823 ) {
58485824 current_brand = " Microsoft Virtual PC/Hyper-V" ;
5849- }
5850-
5851- if (brands.at (TMP_VMWARE) > 0 ) {
5825+ } else if (brands.at (TMP_VMWARE) > 0 ) {
58525826 if (brands.at (TMP_EXPRESS) > 0 ) {
58535827 current_brand = TMP_EXPRESS;
58545828 } else if (brands.at (TMP_ESX) > 0 ) {
@@ -5858,13 +5832,30 @@ struct VM {
58585832 } else if (brands.at (TMP_WORKSTATION) > 0 ) {
58595833 current_brand = TMP_WORKSTATION;
58605834 }
5861- }
5835+ } else if (is_multiple) {
5836+ std::vector<std::string> potential_brands;
58625837
5863- #ifdef __VMAWARE_DEBUG__
5864- for (const auto p : brands) {
5865- debug (" scoreboard: " , (int )p.second , " : " , p.first );
5838+ for (auto it = brands.cbegin (); it != brands.cend (); ++it) {
5839+ const u8 points = it->second ;
5840+ const std::string brand = it->first ;
5841+
5842+ if (points > 0 ) {
5843+ potential_brands.push_back (brand);
5844+ }
5845+ }
5846+
5847+ std::stringstream ss;
5848+ u8 i = 1 ;
5849+
5850+ ss << potential_brands.front ();
5851+
5852+ for (; i < potential_brands.size (); i++) {
5853+ ss << " or " ;
5854+ ss << potential_brands.at (i);
5855+ }
5856+
5857+ return ss.str ();
58665858 }
5867- #endif
58685859
58695860 return current_brand;
58705861 }
@@ -6003,6 +5994,7 @@ VM::flagset VM::DEFAULT = []() -> flagset {
60035994 tmp.flip (NO_MEMO);
60045995 tmp.flip (CURSOR);
60055996 tmp.flip (WIN_HYPERV_DEFAULT);
5997+ tmp.flip (MULTIPLE);
60065998 return tmp;
60075999}();
60086000
0 commit comments