Tuesday, June 05, 2012

C/C++ EXEs and DLLs created by Visual Studio 2008 don't run on Windows 4.0 (ie, NT4 and Win9x)

Louis Solomon / SteelBytes

Written 22/Apr/08
Revised 23/Apr/08 typo's and comment about link.exe/editbin.exe, and the 'quick notes'
Added Link 25/Aug/08 My command line tool that patches compiled code ExeVersion
Added Link 27/Aug/08 other related work LegacyExtender

Here is the result of my exploring this problem ... YMMV :-)

Part 1 (NT4 and Win9x): the required OS version flags in the .exe header are set to 5.0. Can you use Link.exe's or EditBin.exe's /SUBSYSTEM switch to fix this? No, as they don't let you set a value less then 5.0 on both the OS and SubSystem fields (using older version of EditBin from some older version of VS/VC/SDK apparently works). Solution is to patch 'em back to 4.0, here is some code that will do that

HANDLE hfile = CreateFile(argv[1],GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,0,NULL);
if (hfile!=INVALID_HANDLE_VALUE)
{
HANDLE hmapping = CreateFileMapping(hfile,0,PAGE_READWRITE,0,0,0);
if (hmapping)
{
BYTE *file_base = (BYTE *)MapViewOfFileEx(hmapping,FILE_MAP_ALL_ACCESS,0,0,0,0);
if (file_base)
{
IMAGE_OPTIONAL_HEADER *ioh = (IMAGE_OPTIONAL_HEADER *)(file_base + ((IMAGE_DOS_HEADER *)file_base)->e_lfanew + 4 + sizeof(IMAGE_FILE_HEADER));
ioh->MajorOperatingSystemVersion = 4;
ioh->MinorOperatingSystemVersion = 0;
ioh->MajorSubsystemVersion = 4;
ioh->MinorSubsystemVersion = 0;
UnmapViewOfFile(file_base);
}
CloseHandle(hmapping);
}
CloseHandle(hfile);
}

Part 2 (Win9x): the CRT uses the Unicode / Widechar version of GetModuleHandle() in it's internal _crt_waiting_on_module_handle(). Here is a replacement that doesn't

extern "C" __declspec(noinline) HMODULE __cdecl _crt_waiting_on_module_handle(LPCWSTR szModuleName)
{
#define INCR_WAIT                          1000
#define _MAX_WAIT_MALLOC_CRT 60000
    char szModuleNameA[MAX_PATH];
    WideCharToMultiByte(CP_ACP,0,szModuleName,-1,szModuleNameA,_countof(szModuleNameA),NULL,NULL);
    unsigned long nWaitTime = INCR_WAIT;
    HMODULE hMod = GetModuleHandleA(szModuleNameA);

QR: Inline image 1

Posted via email from Jasper-Net