Process Hacker Discussion Forum

 
wfunction
Member
Posts: 147
Joined: 19 Mar 2011 20:17

Linking Dynamically to msvcrt.dll

22 Mar 2011 10:12

If you don't already have the Windows 2003 Server Driver Development Kit, download and install it. You will need the XP and Windows 2003 x64 libraries. (I believe this is the current link but I'm not sure: http://download.microsoft.com/download/ ... sa_ddk.iso) I'll assume you installed it to C:\WinDDK\3790.1830.

Warning

Do not download a newer version! If you do, you'll introduce dependencies on newer versions of msvcrt.dll that won't work on Windows XP.

Heres a tutorial for making Process Hacker link dynamically to msvcrt.dll.

1. Open the project in Visual Studio 2010. Go to the Project Settings for the Process Hacker project, and then select "Release" configuration on All Platforms. (I've personally found it easier to leave the debug build untouched, but I think you can also change that one if you want to, provided that you also make some other changes on your own.)
* Under C/C++ Code Generation, change the Runtime Library to the default, then press Apply. (It should switch to Multithreaded DLL.)
* Change the Buffer Security Check to No. (this may not be required; I don't remember.)

2. Under C/C++ Command Line (Additional Options), type in: /QIfist

3. Switch the platform to Win32:
* Under VC++ Directories, add these directories to the Library Directories path, before everything else:
C:\WinDDK\3790.1830\lib\crt\i386
C:\WinDDK\3790.1830\lib\wxp\i386
* Under Linker->Input, add BufferOverflow.lib as a dependency.

4. Switch the platform to x64:
* Under VC++ Directories, add these directories to the Library Directories path, before everything else:
C:\WinDDK\3790.1830\lib\crt\amd64
C:\WinDDK\3790.1830\lib\wnet\amd64

5. Press OK; you're done with the configuration. Now time to modify the source files. :)

6. Inside the source files, do a Find/Replace for the function names below, and replace the patterns by hand. There should be somewhere between 3 to 10 of each, so replacing them by hand shouldn't be hard (regular expressions might break them, but you could try):
wcscpy_s(<dest>, <len>, <source>)      ---->     wcsncpy(<dest>, <source>, <len>)
wcsncpy_s(<dest>, <len>, <source>, _TRUNCATE)      ---->     wcsncpy(<dest>, <source>, <len>)
Now it's time for the risky changes. I don't recommend these for international users, because it can mess up decimal points and other such locale issues. Furthermore, until I find a better way, some of these are hacks... so if they're called concurrently, they can break! I haven't had problems with them yet, but they definitely need more investigation/fixing.

7. Change all instances of wcstok_s to remove the context parameter. So, wcstok_s(line, delims, &context) should become wcstok(line, delims), wcstok_s(NULL, delims, &context) should become wcstok(NULL, delims), etc. (This is risky if the code turns out to depend on it! I haven't verified it well!)

8. Find the lines saying:
if (PhpFormatDecimalSeparator != '.')
	PhpFormatUserLocale = _create_locale(LC_ALL, "");
and comment them both out. (They can cause locale problems in some situations, be aware.)

9. Add these to support.c (this should be a non-breaking change):
const IID IID_IFileDialog = { 0x42F85136, 0xDB7E, 0x439C, 0x85, 0xF1, 0xE4, 0x07, 0x5D, 0x13, 0x5F, 0xC8 };
const IID CLSID_FileSaveDialog = { 0xC0B4E2F3, 0xBA21, 0x4773, 0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B };
const IID CLSID_FileOpenDialog = { 0xDC1C5A9C, 0xE88A, 0x4dde, 0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7 };
10. Add these to the file format.c (at your own risks :P):
static errno_t __cdecl _cfltcvt_l(double *arg, char *buffer, size_t sizeInBytes, int format, int precision, int caps, _locale_t plocinfo)
{ sprintf(buffer, "%.*f", precision, *arg); return 0; }
static void __cdecl _cropzeros_l(char *buf, _locale_t locale)
{
	// This is REALLY ugly and I don't even know if it works for international users, but I tried. You might have Unicode problems and such, so be careful...
	char zero[64];
	char* pZero;
	int l = sprintf(zero, "%0.1f", 0);
	pZero = &zero[1];
	l--;
	if (l > 0)
	{
		size_t end = strlen(buf);
		while (end > l && buf[end - 1] == pZero[l - 1] && strncmp(&buf[end - l], pZero, l) != 0) { end--; }
		if (end == 0 || strncmp(&buf[end - l], pZero, l) == 0) { buf[end - l] = '\0'; }
	}
}
11. In baseup.c, add this concurrency-unsafe code, and perform a global replacement of qsort_s with myqsort_s:
typedef int (__cdecl * Comparator)(void*, const void *, const void *);
static Comparator staticComparator;
static void* staticComparatorContext;
int __cdecl staticComparatorCaller(const void * a, const void * b)
{ return staticComparator(staticComparatorContext, a, b); }
int myqsort_s(void* base, size_t count, size_t elemSize, Comparator comparator, void* context)
{
	staticComparator = comparator;
	staticComparatorContext = context;
	qsort(base, count, elemSize, &staticComparatorCaller);
	return 0; //I return a value because I was trying to avoid declaring this function (since the default return type is int), but you can make this void too
}
12. Add these definitions:
typedef int (__cdecl * Comparator)(void*, const void *, const void *);
int myqsort_s(void* base, size_t count, size_t elemSize, Comparator comparator, void* context);
to any appropriate parts of the source as needed. I didn't know which would be the best header file to put them in, so put them wherever you think will make them accessible to the everywhere that originally called qsort_s.

Now compile in Release mode and hope for the best. :)
 
frank
Member
Posts: 6
Joined: 14 May 2014 22:36
OS: windows 7

Re: Linking Dynamically to msvcrt.dll

15 May 2014 17:21

Wonder why the newer versions would not work on XP?