I have an application that needs to operate on Windows 2000. I'd also like to use Visual Studio 2010 (mainly because of the change in the definition of the auto
keyword). However, I'm in a bit of a bind because I need the app to be able to operate on older OS's, namely:
Visual Studio 2010's runtime library depends on the EncodePointer / DecodePointer
API which was introduced in Windows XP SP2.
If using the alternate runtime library is possible, will this break code that relies on C++0x features added in VS2010, like std::regex
?
You can select the compiler and corresponding toolset that will be used to build a project with the “Platform Toolset” property under General Configuration Properties for C++ projects. Any installed compilers that are applicable to your project type will be listed in the “Platform Toolset” dropdown.
The Visual Studio build tools include a C compiler that you can use to create everything from basic console programs to full Windows Desktop applications, mobile apps, and more.
In versions of Visual Studio 2019 before version 16.11, /std:c++latest is required to enable all the compiler and standard library features of C++20. For a list of supported language and library features, see What's New for C++ in Visual Studio.
The very simplest solution is just to set the Platform Toolset in project settings in VS2010 to v900, which will use the Visual Studio 2008 libraries and compiler. This also means you lose C++0x features like auto
, but to be honest, working around that with some typedef
s is probably easier than building your own version of the CRT or other more complicated solutions. Alternatively, just use VS2008! I don't know if there are other C++0x features that are critical to your application though, you didn't mention - other than std::regex
, which I think is still in the v900 toolset under the technical report 1 namespace (std::tr1::regex
).
Just from the impression I get, I would predict the inconvenience of getting the VS2010 libraries to run on XP SP1 is greater than the convenience of C++0x features, so overall it wouldn't be worth it.
You cannot use 2008 CRT, but you can prevent the new functions DecodePointer/EncodePointer to be linked from the kernel. It is quite easy to replace the new functions with stubs.
One might attempt following: Place code like this in your main.cpp source:
extern "C" {
void *__stdcall _imp__DecodePointer(void *x) {return x;}
void *__stdcall _imp__EncodePointer(void *x) {return x;}
};
The above does not work. While the basic idea is sound, the execution needs to be a little bit different. As described by snemarch in comment and another answer, __imp__
cannot be the function call, only the pointer to it. As it seems not possible to generate the pointer directly by the compiler, you need to assemble the following code with MASM and link against the produced object file.
.model flat
.data
__imp__EncodePointer@4 dd dummy
__imp__DecodePointer@4 dd dummy
EXTERNDEF __imp__EncodePointer@4 : DWORD
EXTERNDEF __imp__DecodePointer@4 : DWORD
.code
dummy proc
mov eax, [esp+4]
ret 4
dummy endp
end
The symbols from a project have preference against any symbols from libraries. DLL libraries are linked using .lib parts, which contain only __imp__
"vectors" jumping into the real functions. By replacing __imp__
"vectors" you do not touch the DLL linking, you replace the .lib part. I have verified there is no more any dependency of the exe on DecodePointer / EncodePointer.
Statically linked library brings only used functionality into the application. It is possible to find which particular CRT function bring in those new API using linker verbose progress output:
Found __imp__EncodePointer@4
Referenced in LIBCMT.lib(crtmboxw.obj)
Referenced in LIBCMT.lib(invarg.obj)
Referenced in LIBCMT.lib(handler.obj)
Referenced in LIBCMT.lib(onexit.obj)
Referenced in LIBCMT.lib(cmiscdat.obj)
Referenced in LIBCMT.lib(tidtable.obj)
Referenced in LIBCMT.lib(hooks.obj)
Referenced in LIBCMT.lib(winsig.obj)
Referenced in LIBCMT.lib(rand_s.obj)
Found __imp__DecodePointer@4
// ... same list, only order differs ...
This shows the new APIs are used in some of the CRT to provide more security for some functions which are deemed to provide frequent attack vectors.
With some effort it would be possible to use LoadLibrary / GetProcAddress to provide the real functionality where OS offers is, but I do not think it would really bring anything. The runtime functions which use DecodePointer / EncodePointer do not really need it to provide any encoding, all they need is the encoding to by symmetric. You do not really need the enhanced security (VS 2008 runtime would not give it to you either).
I hope there are no other obstacles waiting for you - I do not have an access to Win2k or XP pre SP2 system, therefore I am unable to try. If there are any exe header flags preventing even attempting to launch the exe on such systems, they should be easy to change.
Suma's solution looked pretty promising, but it doesn't work: the __imp__*@4
symbols need to be pointers to functions, rather than the functions themselves. Unfortunately, I don't know how to make Visual C++ spit out a pointer with that kind of name generation... (well, __declspec(naked)
combined with __stdcall
does the trick, but then I don't know how to emit a pointer).
If using an assembler at build-time is OK, the solution is pretty trivial - assemble the following code with FASM and link against the produced object file, and presto - no EncodePointer/DecodePointer references in the exe:
use32
format ms coff
section ".data" data
public __imp__DecodePointer@4
__imp__DecodePointer@4 dd dummy
public __imp__EncodePointer@4
__imp__EncodePointer@4 dd dummy
section ".text" code
dummy:
mov eax, [esp+4]
retn 4
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With