views:

40

answers:

2

I have a C program which has a function call that is defined in windows.h (which I have included), however, when I try and compile it with gcc, I get the error:

warning: implicit declaration of function `LockWorkStation'

I looked at the MSDN documentation and I see that this function is the User32 library file, and I was wondering how I would go about linking that to my file.

+4  A: 

LockWorkstation is available on Windows 2000 and up. You have to declare the version of Windows you are targeting. Make it look like this:

#define _WIN32_WINNT 0x500
#include <windows.h>
Hans Passant
+1 for the difference between BUILD and TARGET
Ben Voigt
+1  A: 

I have the same problem with gcc - but this is not a linker error. The message means that there is no prototype for the function in winuser.h, or more accurately the compiler can't find such a prototype. That is because the relevant bit of winuser.h looks like this:

#if (_WIN32_WINNT >= 0x0500)
WINUSERAPI BOOL WINAPI LockWorkStation(void);
#endif

In other words, you need a version of Windows >= 5 (i.e Win2K) to use this function. I'm currently trying this on Win2K and it doesn't work, which indicates the macro is not being set correctly. I don't do much "real" Windows programming these days, so I'm not sure why that should be.

Edit: In fact, a bit of experiment indicates that gcc thinks the Windows version of Win2K (on my installation at least) is 0x0400.

Further: Actually, the macro _WIN32_WINNT is (as the leading underscore suggests) a reserved name in C and C++, and should not be defined in user code. Defining the macro WINVER seems to have the same effect, and is (conceptually at least) more portable. This code compiles on my gcc installation:

#define WINVER 0x0500
#include <windows.h>
int main() {
    LockWorkStation();
}
anon
Compilers on Windows by default maximize portability of the output, rather than optimizing for the current platform. So gcc doesn't mistakenly think that Win2k is 0x0400, rather it assumes that you want to produce code that can run on WinNT 4.0 or Win95, until you tell it otherwise.
Ben Voigt
@Ben Your thoughts on my latest edit would be appreciated.
anon
@Neil: You're absolutely right that setting WINVER is preferable to setting _WIN32_WINNT, although in some cases both had to be set (e.g. for functions available in WinNT 4.0 but not Win9x, you had to use _WIN32_WINNT). Since WINVER = 0x0500, all Windows SKUs are NT-based so WINVER is enough. Your answer still suggests that WINVER is auto-detected from the version of Windows hosting the compiler, and this is not correct.
Ben Voigt
@Ben Thinking about it, *some* version of Windows is being assumed, which seems wrong. It would seem to be sensible for WINVER (or whatever) to be undefined and for it to be so to cause a compilation error - not difficult to arrange - to force you to specify the level of compatibility you want. I certainly didn't particularly want to be NT4 compatible. But thanks for your very helpful info!
anon