Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use Visual Studio 2010's C++ compiler with Visual Studio 2008's C++ Runtime Library?

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:

  • Windows 2000
  • Windows XP RTM
  • Windows XP SP1

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?

like image 901
Billy ONeal Avatar asked Mar 20 '10 19:03

Billy ONeal


People also ask

Can I use a different compiler in Visual Studio?

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.

Does Visual Studio have a compiler for C?

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.

What version of C does Visual Studio use?

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.


3 Answers

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 typedefs 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.

like image 182
AshleysBrain Avatar answered Oct 20 '22 05:10

AshleysBrain


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.

Background

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.

like image 20
Suma Avatar answered Oct 20 '22 04:10

Suma


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
like image 11
snemarch Avatar answered Oct 20 '22 05:10

snemarch