2

I am a Java, Python programmer trying to fiddle with C++. I have following code snippet -

#include <windows.h>

bool IsInsideVMWare()
{
  bool rc = true;

  __try
  {
    __asm
    {
      push   edx
      push   ecx
      push   ebx

      mov    eax, 'VMXh'
      mov    ebx, 0 // any value but not the MAGIC VALUE
      mov    ecx, 10 // get VMWare version
      mov    edx, 'VX' // port number

      in     eax, dx // read port
                     // on return EAX returns the VERSION
      cmp    ebx, 'VMXh' // is it a reply from VMWare?
      setz   [rc] // set return value

      pop    ebx
      pop    ecx
      pop    edx
    }
  }
  __except(EXCEPTION_EXECUTE_HANDLER)
  {
    rc = false;
  }

  return rc;
}

I am getting following compile error -

__try' undeclared (first use this function) __except' undeclared (first use this function)

What does that vague message even mean? Because try is undeclared I should try to use it first??

Edit:

IDE - Codeblocks

Compiler - GCC

Kshitiz Sharma
  • 17,947
  • 26
  • 98
  • 169
  • 4
    Which compiler are you using? Because these "keywords" are an [extension](http://msdn.microsoft.com/en-us/library/zazxh1a9.aspx) of the Visual C++ line of of C compilers, no other compiler I know of have them. Also note that they are extensions of the **C** programming language, and are not meant to be used in C++ programs. – Some programmer dude Aug 07 '13 at 11:11
  • That vague message means your compiler thinks __try is a variable and you didn't declare it. I'm no expert in c++ but shouldn't a try be just "try" instead of "__try"? Don't know how to fix it, but might point you to the right direction. – caiocpricci2 Aug 07 '13 at 11:11
  • 1
    it means "first use IN this function" – fuenfundachtzig Aug 07 '13 at 11:11
  • BTW This post http://stackoverflow.com/questions/12513209/try-and-exception-portability suggests __try doesn't exist on gcc. It could be wrong, I don't know. Where did you get the code from? – doctorlove Aug 07 '13 at 11:16
  • It means you should compile it with VC++ IDE on Windows. – SChepurin Aug 07 '13 at 11:20
  • 2
    In the error message, "use" is a noun, not a verb. It's saying that it first encountered `__try` at that line, and won't repeat the message if it sees it again. – Pete Becker Aug 07 '13 at 12:06

5 Answers5

7

This code RELIES on the Microsoft specific functionality of __try and __except. There is no other way to solve this, as doing an IN instruction from a user-mode process in Windows will normally fail. In VMWare, any such operation is intercepted by the VMWare VMM (Virtual Machine Monitor, sometimes also called Hypervisor). It then checks the special values in some registers and "accepts" the instruction with a new value in ebx to indicate that "Yes, I'm a VMWare system". If you run this on a plain old Windows system, it will get an General Protection Fault for trying to use a IO-port that isn't available to the application [in general, IO ports aren't availbe to the user-mode application code].

You need to compile this using a Microsoft compiler (and with the suitable "enable exception handling" flag set - sorry, can't remember what that flag is, but it will tell you if it's not on that it's wrong). GCC doesn't support this feature.

However, you can test for VMWare using the CPUID instruction instead of using IN. This will work much better in a GCC compiler, as it will not fault the processor if there is no VM present [For the pedants: As long as the processor is later than some version of 486 from the 1990's]. Instead, it will just not give the right values in the registers (no change to the register values). You may need to write a cpuid inline assembler function, but that shouldn't be too difficult to google up.

See this KB-article on VMwares site: http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458

Alternatively, if you really insist on using Windows Structured exception handling, you can do it yourself:

   push handler   // Save address of your handler. 
   push fs:[0]    // Save address of any previous handler
   mov  fs:[0], esp    // Save pointer to current exception record. 

   ...    // all the stuff setting registers, doing IN, etc. 

   jmp  cleanup

handler:
   mov  [rc], 0       // Set "rc= false". 

cleanup:
   pop  fs:[0]
   add  esp, 4   // Remove handler

(Note, I just wrote that from a bit of googling - it's a LONG time since I used anything like that on Windows, so it may not work)

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
5

__try is an SEH thing. See previous questions here and here
I think you need to #include <excpt.h> for windows
The "first use" message means that's the first time you've used it.
try and catch are different as the links explain.

Community
  • 1
  • 1
doctorlove
  • 18,872
  • 2
  • 46
  • 62
  • Including `excpt.h` does not work. Is there any other way to make it work other than compiling it with VC++? I assume MS must provide the implementation of `__try` in some library. Couldn't I just include it and make it work? – Kshitiz Sharma Aug 07 '13 at 11:28
  • I posted a link in the comments - you are using gcc, and I said that worked for windows. Why not just the proper C++ try and catch instead? – doctorlove Aug 07 '13 at 11:29
  • 1
    Because C++ catch block will not catch exceptions generated by assembly instructions. – Kshitiz Sharma Aug 07 '13 at 11:31
  • Fair point - see Mats answer. This code is probably designed for use with a Windows compiler. You might want a difference book/whatever for gcc. – doctorlove Aug 07 '13 at 11:33
  • @KshitizSharma: I have just expanded my answer with "how to do your own __try __except in assembler - although I would suggest the CPUID variant is a better choice. – Mats Petersson Aug 07 '13 at 12:01
  • @MatsPetersson And thank you for that. Although with my level of C++ it might take rest of the day to understand everything you said. – Kshitiz Sharma Aug 07 '13 at 12:04
1

The symbols __try and __except are undeclared, the compiler is not able to resolve them.
You should read your compiler's documentation on the usage of such keywords (if they exit at all).
C++ gives you try and catch keywords for this purpose, try

bool IsInsideVMWare()
{
  bool rc = true;

  try
  {
    __asm
    {
      ...
    }
  }
  catch(...) //catch all possible exceptions
  {
    rc = false;
  }

  return rc;
}

Remember, though, that C++ has no deep runtime as do Python or Java! So there are only a few runtime-exceptions.

Little article from MSDN.

bash.d
  • 13,029
  • 3
  • 29
  • 42
  • 3
    Except that ONLY works if you have something that translates the machine instruction exception to a C++ type exception, and I doubt that exists. – Mats Petersson Aug 07 '13 at 11:17
  • Agreed! I don't believe there is much of a chance for this, either. It's just I used `...` to not point out a special type of ecxeption. – bash.d Aug 07 '13 at 11:19
1

Isn't C++ exceptions use the try{}catch{} blocks? Refer to http://www.cplusplus.com/doc/tutorial/exceptions/

if you use __try, your C++ compiler will probably think it is a function, hence the error message.

or you could do #define __try try macros maybe! :)

Also, what compiler are you using? If you are using GCC, I think you might also need to fix the clobberlist of inline assembly to make sure GCC doesnt overoptimize it.

Levente Kurusa
  • 1,858
  • 14
  • 18
-3

I am no coder, but I got around this simply by defining these before they were called.

define __try

define __except

heh presto worked. code I was running needed another ';' which was reported, added that and it works.

hope this helps, as nothing else I saw did. :)

Community
  • 1
  • 1
Lex
  • 1