Build my application for a previous Windows platform - c++

Background
I'm writing a C++ app using VS2015 on WIN 7. This app will run on all windows OS greater than equal to XP.
Through out my code, I use lots of WINAPI calls.
I wish to prevent, at compile time, the usage of API that are not defined in win XP.
Motivation
At some point, I used function RegDeleteKeyEx function without noticing that this API is NOT available in win XP
Solution
So, I follow this post: Modifying WINVER and _WIN32_WINNT and declared this:
#include <winsdkver.h>
#define _WIN32_WINNT 0x0501
#define WINVER 0x0501
in file targetver.h
I was hoping that after this fix, when I compile my project that contains usage of RegDeleteKeyEx function, I will get compilation error.
But I didn't.
QA
I tried looking for other, new WINAPI in vista, and just added a call to GetTickCount64 function. when compiling, I got this:
error C3861: 'GetTickCount64': identifier not found
which confirmed my solution.
Question
I've noticed that for RegDeleteKeyEx function, the Minimum supported client is Windows Vista, Windows XP Professional x64 Edition
However, my app will run in XP 32 as well.
How may I enforce compilation error in such use case?

Unfortunately, as I can see in "winreg.h", there is no conditional compilation of RegDeleteKeyEx (other than RegDeleteKey). So there is no (easy) way to trigger compilation error in this case.
The only option (for the regular statical DLL loading) would be to create your own wrapper over winreg.h (or windows.h) which would handle the version check (and e.g. #undef RegDeleteKeyEx in the corresponding cases).
Sometimes this kind of stuff is also solved using dynamic DLL loading (LoadLibrary / GetProcAdress) where you can check the presence of the particular function on the current version of Windows, where the application runs (so you could for example create a RegDeleteKey wrapper which would call RegDeleteKeyEx on the windows versions which support it and RegDeleteKey if run under versions which don't). The check of the feature presence is then done at runtime, so the program can run on any version of system and still use the newest features on the versions which support them (and doesn't have DLL "unresolved import" loading issues on the lower versions which do not support the feature).

Related

C++ compile time macros to detect windows os

Are there any C++ compile time macros which exists to detect which Windows OS the code is being compiled on. I basically want to support certain functions only on Win7. So I am interested in doing something like this
#if <os_macro> = WIN7
// This function would do something valid only on Win7 builds.
bool myfunction {
// do something here
}
#else
// This function would typically return false, since its not supported on OS below win7
bool myfunction {
return false;
}
#endif
Is there any other better way to do this?
The OS that it's getting compiled on is not all that important; what matters more is the OS that the code is running on, which you obviously cannot detect at compile time. But if you want your code to run on older versions of Windows, you can set WINVER and _WIN32_WINNT to certain values, which will cause newer functions not to be available etc. (just search the Windows header files for where those macros get tested to get an idea).
To test for functionality at runtime, use GetProcAddress (and possibly also LoadLibrary, if it's in a newer DLL) to test if the function is available. If it is, call it, if not, don't.
See also the predefined macros used by the Visual Studio compiler if you want to detect the compiler version etc.
There are a set of standard windows header macros to tell you the exact version of the OS
There are certain things that do require knowing which OS version at compile time.
For example import "winhttp.dll" will compile under Windows 7, but cause compile time error (C1083) under Windows 10.
But if you switch to import "winhttpcom.dll". It would compile under Windows 10 but fail under Windows 7.
So an OS macro is needed here to import appropriate dll.
At least with MS VC++, WIN32, _WIN32, and _WIN32_WINNT, for starters. Unless you need to control it at compile time, you might consider using something like GetVersionEx to detect at run-time, so the same build runs on older versions, but takes advantage of new features when they're available.
My response is 10 yrs late but posting the answer for upcoming yrs.
For detecting the version c/c++ compiler version can be used. Suitable macro is mentioned below:
_MSC_VER
_MSC_FULL_VER
Reference: MS macros
My two cents for people that want to compile / include differently between CONSOLE and WIN32 App under visual Studio (2017) in my case.
You you use wizard to create a Console App, You will have:
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
under:
If You use wizard for win32 GUI App:
WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
so NO _CONSOLE.
so You can write:
#ifdef _CONSOLE
// for Console
#else
// for GUI
#endif // _CONSOLE
int main()
{
#ifdef _CONSOLE
// for Console
#else
// for GUI
#endif // _CONSOLE
return 0;
}

Tool for determining version of Win32 APIs used by C++ code?

I'm modifying a large C++ project whose first release was Windows 7-only to work on Vista and XP.
The main work will be to change the W7 API calls to use GetProcAddress at runtime (to avoid static linking with methods that are not available on the other platforms), and so I'm wondering if there are any tools that can help identify which calls need to be changed -- hopefully by examining the C++ code itself.
Failing that, would it be best to try building the project against an older Windows SDK? -- for example: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=6510
#define WINVER 0x501
Now everything that is newer than Windows XP will cause a compilation error.
Replace everything that causes an error until none remain.
If you have some sed-fu, you can probably write a filter that directly finds all #if WINVER > 0x501 blocks in the windows headers, but for me, this is a bit out of my scope :-)
I would open your binaries using the depends.exe tool (either from your VS install or from here) under WinXP and Vista to see which functions can't be statically linked under these OSes. These would be the functions which your binary is using, but which are missing in older releases of the OS. You'll have to deal with them somehow: either implement them by yourself, replace them with something else or disable some of the functionality of your app.

Why _WIN32_WINNT == 0x400 in Qt Creator on Windows 7 machine?

I'm using Qt Creator 2.0.1 based on Qt 4.7.0 (32 bit). The OS is Windows 7 Ultimate (32 bit).
I'd like to restart Windows using the following function call:
ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_MAJOR_SYSTEM |
SHTDN_REASON_MINOR_NETWORK_CONNECTIVITY);
I've added windows.h and reason.h in the source code and added libuser32 in the LIBS section of *.pro file.
After compiling the code, Qt Creator issues an error saying SHTDN_REASON_MAJOR_SYSTEM and SHTDN_REASON_MINOR_NETWORK_CONNECTIVITY are not define in the scope.
I looked into reason.h file that comes with mingw. I found the #defines are inside an #if:
#if (_WIN32_WINNT >= 0x0501)
I looked into the value of _WIN32_WINNT which appears to be 1024 (0x400).
I understand this represents some kind of version number and those #defines should be compiled after a specific version. But why _WIN32_WINNT is so low on Windows 7? How can I use those #defines? I do not want to put direct values instead of SHTDN_REASON_MAJOR_SYSTEM and SHTDN_REASON_MINOR_NETWORK_CONNECTIVITY.
The value of _WIN32_WINNT indicates the version of the Win32 API you're targeting at runtime. It has nothing to do with the version of the OS you happen to be using while doing the build.
If you set this to a higher value before including the API header files more API functions and definitions will become available, but making use of those functions may cause your application to refuse to run on previous versions of Windows. Typically, you want to use the lowest value that you can get away with.
It's safe to use #define values from higher API versions as long as you check for errors from Win32 functions indicating that the value is not supported. Using Win32 functions, however, will cause your application to fail on startup with errors like "DLL import not found".
When you use the Windows SDK, you can specify which versions of Windows your code can run on. The preprocessor macros WINVER and _WIN32_WINNT specify the minimum operating system version your code supports.
When you upgrade an older project, you may need to update your WINVER or _WIN32_WINNT macros. If they're assigned values for an unsupported version of Windows, you may see compilation errors related to these macros.
from:https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=vs-2019

Procedure entry point InitializeConditionVariable could not be located in kernel32.dll

I am running producer consumer problem( using windows thread ).It compiling successfully but on running it showing following error
The procedure entry point InitializeConditionVariable could not located in the dynamic library Kernel32.dll.
can u tell what would be reason
That's an API function that is only available in Vista and up. I would guess that you are running this code on XP.
To avoid accidentally using API functions that are only available in later versions of Windows, you'll want to define the _WIN32_WINNT macro:
#define _WIN32_WINNT 0x502 // Designed to run on Windows XP SP2 and up
#include <windows.h>
If you don't set it then it typically defaults to 0x600 on later versions of the Windows SDK, selecting Vista as the target operating system. Btw, you'll probably have to give up on condition variables. There isn't enough detail in your question to offer a suitable replacement. Code that uses mutexes instead shouldn't be hard to find.
InitializeConditionVariable and the related condition-variable APIs are only available on Windows Vista onwards. You could use Boost.Thread to provide a condition variable implementation which works on Windows XP. I wrote an article on my blog about how to use that for a producer/consumer queue.

how do i turn my program into something i can install?

how do i turn my VC++ 2008 program into something i can get to run on other computers. i have tryed using the .exe it makes in the debug but it will say that im missing some files and lists all of my .cpp file names and .h files(if i use it on other computers). i wanted something so i could encrypt my files because one of them is about encrypting passwords/other stuff so i can't have someone just open my files. also i would very much like someway to make them accept the terms and conditions so they can't sue me if they lose something, that would be very very nice. ^^
i only have Microsoft virtual c++ 2008 express edition that i got from their web site.
o also if i make something on windows 7 will it run in xp or vista?
You generally can't and almost never should distribute debug builds to client machines. At least three reasons.
Client machines will not have the debug versions of your dependant libraries, like the VC runtime (msvcrtd.dll), so they won't be able to run your app.
When compiling in debug, your code will in many ways run unoptimized. For one thing, you don't let an optimizing compiler optimize when you compile in debug, so it will run slower and/or fatter. For another, there are debug version of things like operator new which allocate much more than you ask for, which is used in runtime integrity checking etc. So your program runs fatter & slower once more.
When you compile in debug it is easier to reverse-engineer your code.
UPDATE:
And to answer your question if a Win7-compiled app will run on XP/Vista, the answer is 'yes' so long as you don't use any Win7 features.
You will need the redist pack for the binary to run on another machine (if it does not already have the pack installed).
You need to make a Deployment Project that generates an MSI, but I'm not sure your Express edition does that. As for encryption, compilation doesn't do that, and nothing stops people from disassembling your code. Finally, you probably should not be writing your own encryption algorithms, since most people get those wrong most of the time. Use something out of the box.
if you are compiling using .NET 3.5 in Win 7 it should work in xp and vista as well
(provided .NET 3.5 framework is installed on them).
The first part is already answered (release build, include redistributable C++ DLLs).
The second part, running on Vista/XP is not that trivial.
If you write a pure C++ program, it will run on XP and Vista, unconditionally. But once you include <windows.h>, you introduce a dependency on a minimum Windows version. The default today is still XP. That means that you cannot use any Vista or W7 feature directly, and therefore your program can run on XP.
But if you #define WINVER 0x0600 before including <windows.h>, then you can use Vista-specific functions. The price you pay for using those Vista functions is that your program won't start on XP anymore. Similarly, #define WINVER 0x0601 also gives you access to Windows 7 functions, on top of the XP and Vista functions. And again, using a Windows 7 function stops you from running on XP or Vista.
There are some tricks that allow you to use Windows 7 functions if available. Basically, they all boil down to calling GetProcAddress("some_windows7_function") and somehow handling the case where it returns NULL.