Click here to Skip to main content
15,886,199 members
Articles / Programming Languages / ASM

Loading Win32/64 DLLs "manually" without LoadLibrary()

Rate me:
Please Sign up or sign in to vote.
4.97/5 (31 votes)
8 Mar 2014CPOL5 min read 255.4K   8.1K   107  
How to load DLLs by allocating memory and loading the DLL from file/memory and then relocating/importing.
// A very-very basic CRT lib.
#include "MiniCRT.h"

#if MINICRT_ENABLED

#include <intrin.h>
#pragma intrinsic(__movsb)


int __cdecl printf(const char* format, ...)
{
	int len, max_len;
	DWORD written;
	char buf[0x100];
	va_list args;

	va_start(args, format);
	len = wvsprintfA(buf, format, args);
	va_end(args);

	max_len = (int)sizeof(buf)-1;
	len = len < max_len ? len : max_len;
	buf[len] = 0;

	WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), buf, (DWORD)len, &written, NULL);
	return len;
}

void* __cdecl operator new(size_t size)
{
	void* p = LocalAlloc(LMEM_FIXED, (SIZE_T)size);
	ASSERT(p);
	return p;
}

void __cdecl operator delete(void* p)
{
	if (p)
		VERIFY_FALSE(LocalFree((HLOCAL)p));
}



#pragma section(".CRT$XCA",long,read)
#pragma data_seg(push, crtxc, ".CRT$XCA")
CrtInitFunc __static_init_func_array_begin[] = { 0 };
#pragma data_seg(pop, crtxc)

#pragma section(".CRT$XCZ",long,read)
#pragma data_seg(push, crtxc, ".CRT$XCZ")
CrtInitFunc __static_init_func_array_end[] = { 0 };
#pragma data_seg(pop, crtxc)

static void StaticInitialization()
{
	for (CrtInitFunc* pinit_func=__static_init_func_array_begin+1; pinit_func<__static_init_func_array_end; ++pinit_func)
	{
		if (*pinit_func)
			(*pinit_func)();
	}
}

// TODO
static CrtInitFunc* g_AtExit = NULL;
static size_t g_AtExitCapacity = 0;
static size_t g_AtExitCount = 0;

static void StaticDeinitialization()
{
	for (size_t i=g_AtExitCount; i--; )
		g_AtExit[i]();
	delete[] g_AtExit;
}


int __cdecl atexit(CrtInitFunc func)
{
	if (!func)
		return 0;
	if (g_AtExitCount >= g_AtExitCapacity)
	{
		g_AtExitCapacity = g_AtExitCapacity ? g_AtExitCapacity*2 : 1;
		CrtInitFunc* new_atexits = new CrtInitFunc[g_AtExitCapacity];
		if (g_AtExitCount)
		{
			__movsb((unsigned char*)new_atexits, (unsigned char*)g_AtExit, g_AtExitCount*sizeof(CrtInitFunc));
			delete[] g_AtExit;
		}
		g_AtExit = new_atexits;
	}
	g_AtExit[g_AtExitCount++] = func;
	return 0;
}

#if ASSERT_ACTIVE
void __assert(const char* condition, const char* file, int line, const char* function)
{
	printf("%s(%d) in function %s: ASSERTION FAILED: %s\n", file, line, function, condition);
	char buf[0x100];
	wsprintfA(buf, "file: %s\nline: %d\nfunction: %s\n\nASSERT(%s)\n\nYes==break No==Continue", file, line, function, condition);
	if (IDYES == MessageBoxA(NULL, buf, "ASSERTION FAILED!", MB_YESNO|MB_ICONEXCLAMATION))
		__debugbreak();
}
#endif

int __cdecl _purecall()
{
	printf("Pure virtual function call!\n");
	MessageBoxA(NULL, "Pure virtual function call!", "Runtime error!", MB_OK|MB_ICONEXCLAMATION);
	__debugbreak();
	ExitProcess(1);
}

void __cdecl MiniCRTStartup()
{
	StaticInitialization();
}

void __cdecl MiniCRTCleanup()
{
	StaticDeinitialization();
}

BOOL WINAPI MiniCRTDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
	// With manual DLL loading you can not use DLL_THREAD_ATTACH and DLL_THREAD_DETACH.
	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		MiniCRTStartup();
		break;
	case DLL_PROCESS_DETACH:
		MiniCRTCleanup();
		break;
	default:
		break;
	}
	return TRUE;
}

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions