/* * PROJECT: ReactOS api tests * LICENSE: GPLv2+ - See COPYING in the top level directory * PURPOSE: Test for LdrRelocateImage behavior with a clash on a system module * PROGRAMMER: Mark Jansen */ #include #define WIN32_NO_STATUS #include #include #include /* Full size: 1536 bytes ------------------------------------- #include int __stdcall MessageBeeP(int); void* _start() { MessageBeeP(0); MessageBeep(0); ExitProcess(GetModuleHandleA("user32.dll")); } ------------------------------------- tcc -nostdlib -shared dll.c -o user33.dll -Wl,-image-base=0x76E90000 ------------------------------------- */ static unsigned char exe_data[471] = { 0xD4, 0xB1, 0x00, 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x82, 0x04, 0x00, 0x30, 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x38, 0x2D, 0x01, 0x10, 0x40, 0x04, 0x38, 0x19, 0x30, 0x80, 0x00, 0x70, 0x0E, 0x1F, 0x00, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 0x21, 0xB8, 0x00, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x00, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x00, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x00, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x00, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x80, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, 0x24, 0x04, 0xB0, 0x80, 0x50, 0x45, 0x00, 0x00, 0x4C, 0x01, 0x02, 0x04, 0x0D, 0x01, 0x03, 0x06, 0xE0, 0x00, 0x0F, 0x03, 0x0B, 0x01, 0x06, 0xD9, 0x0A, 0x13, 0x00, 0x10, 0x00, 0x0E, 0x01, 0x03, 0x20, 0x01, 0x16, 0x00, 0x9D, 0x9F, 0x01, 0x0B, 0x00, 0x36, 0x01, 0xB7, 0x01, 0x11, 0x05, 0x07, 0x00, 0x30, 0x00, 0x0D, 0xD1, 0x00, 0x17, 0x14, 0x71, 0x00, 0x02, 0xD7, 0x00, 0x01, 0x38, 0x01, 0x2B, 0xAF, 0x06, 0x07, 0x02, 0x11, 0x01, 0x32, 0x02, 0x03, 0x10, 0x80, 0x27, 0x50, 0x86, 0x06, 0x15, 0x47, 0x04, 0x60, 0x80, 0x2B, 0x1C, 0x18, 0x27, 0x2E, 0x74, 0x65, 0xB4, 0x78, 0x74, 0x80, 0x0F, 0x58, 0x81, 0x11, 0x84, 0x65, 0x00, 0x80, 0x5B, 0x07, 0x01, 0x07, 0x85, 0x01, 0x00, 0x21, 0x60, 0x2E, 0x64, 0x61, 0x74, 0xFA, 0x61, 0x01, 0x08, 0x01, 0x00, 0x02, 0x00, 0x08, 0x82, 0x11, 0x06, 0x76, 0x01, 0x0C, 0x34, 0x00, 0x00, 0x80, 0x86, 0xC0, 0x83, 0x04, 0xAF, 0x02, 0x55, 0x89, 0x28, 0xE5, 0x81, 0xEC, 0x81, 0x0D, 0x90, 0x42, 0x7E, 0x50, 0xE8, 0x0E, 0x23, 0x00, 0x03, 0x84, 0x02, 0x81, 0x1B, 0xB8, 0x00, 0x20, 0x40, 0x10, 0x00, 0x50, 0xE8, 0x1D, 0x40, 0x05, 0x50, 0xE8, 0x1F, 0x09, 0x40, 0x01, 0xC9, 0xC3, 0x00, 0x01, 0x00, 0x00, 0xFF, 0x25, 0x56, 0x60, 0x00, 0x06, 0xC1, 0x01, 0x68, 0xC4, 0x01, 0x70, 0xC4, 0x01, 0x74, 0xFF, 0xC2, 0x01, 0x02, 0x09, 0x3F, 0x01, 0x7F, 0x10, 0x7F, 0x10, 0x7F, 0x10, 0x7F, 0x10, 0x7F, 0x10, 0x01, 0x54, 0x10, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x68, 0x64, 0x6C, 0x6C, 0x03, 0x04, 0x7C, 0x81, 0x3E, 0x64, 0x05, 0x98, 0xAB, 0x60, 0x01, 0xE1, 0x58, 0x84, 0x68, 0x02, 0xB4, 0x60, 0x01, 0x68, 0x60, 0x00, 0xA6, 0x8C, 0x60, 0x00, 0xC4, 0x04, 0x00, 0xCD, 0x60, 0x01, 0x70, 0xE8, 0x01, 0xAB, 0xE5, 0x02, 0xE1, 0x00, 0xA3, 0xE4, 0x02, 0xBF, 0xE4, 0x00, 0xDA, 0xE0, 0x00, 0x2E, 0xED, 0x64, 0x01, 0x79, 0x03, 0xE2, 0x12, 0x33, 0xE4, 0x12, 0x5F, 0x4D, 0x00, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x65, 0x60, 0x65, 0x50, 0x40, 0x34, 0x00, 0x6A, 0x16, 0x47, 0x03, 0x70, 0x80, 0x00, 0x6B, 0x65, 0x72, 0x6E, 0x65, 0x6C, 0xC6, 0x19, 0x00, 0x47, 0x65, 0x74, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x00, 0x65, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x41, 0x01, 0xE0, 0x11, 0x45, 0x78, 0x69, 0x74, 0x50, 0x72, 0x6F, 0xFE, 0x63, 0xE0, 0x09, 0xA1, 0x13, 0x7F, 0x00, 0x3F, 0x04, 0x3F, 0x04, 0x3F, 0x04, 0x3F, 0x04, 0x07, 0x3F, 0x04, 0x3F, 0x04, 0x31, 0x04 }; /* Full size: 1536 bytes ------------------------------------- #include #define DLL_EXPORT __declspec(dllexport) DLL_EXPORT int __stdcall MessageBeeP(int a) { return a; } int __stdcall _dllstart(void *base, unsigned long reason, void *reserved) { return 1; } ------------------------------------- tcc -nostdlib main.c user33.def -lkernel32 -luser32 -lmsvcrt -o tiny.exe ------------------------------------- */ static unsigned char dll_data[361] = { 0x64, 0xB1, 0x00, 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x82, 0x04, 0x00, 0x30, 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x38, 0x2D, 0x01, 0x10, 0x40, 0x04, 0x38, 0x19, 0x30, 0x80, 0x00, 0x70, 0x0E, 0x1F, 0x00, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 0x21, 0xB8, 0x00, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x00, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x00, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x00, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x00, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x80, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, 0x24, 0x04, 0xB0, 0x80, 0x50, 0x45, 0x00, 0x00, 0x4C, 0x01, 0x02, 0x04, 0x0D, 0x01, 0x03, 0x06, 0xE0, 0x00, 0x0E, 0x23, 0x0B, 0x01, 0x06, 0x59, 0x0A, 0x13, 0x16, 0x10, 0x00, 0x0E, 0x01, 0x03, 0x20, 0x01, 0x16, 0xE9, 0x7C, 0x76, 0x00, 0x01, 0x0B, 0x00, 0x36, 0x01, 0xB7, 0x01, 0x11, 0x05, 0x07, 0x00, 0xF6, 0x30, 0x00, 0x0D, 0x00, 0x17, 0x4B, 0x00, 0x27, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x28, 0x4F, 0x01, 0x2B, 0x01, 0x30, 0x02, 0x07, 0x02, 0x11, 0x00, 0x00, 0x00, 0x1F, 0x4C, 0x83, 0x00, 0x1D, 0x75, 0x02, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x00, 0x3E, 0x3B, 0x01, 0x57, 0x85, 0x65, 0x00, 0x03, 0x58, 0x06, 0x49, 0x00, 0x51, 0x60, 0x2E, 0xD0, 0x64, 0x61, 0x74, 0x61, 0x80, 0x08, 0x60, 0x81, 0x0A, 0x00, 0x08, 0xA7, 0x82, 0x11, 0x06, 0x76, 0x01, 0x0A, 0x00, 0x00, 0x80, 0xD5, 0xC0, 0x83, 0x04, 0x41, 0xAF, 0x02, 0x55, 0x89, 0xE5, 0x81, 0xEC, 0x81, 0x0D, 0x90, 0x10, 0x8B, 0x45, 0x08, 0xE9, 0x01, 0x02, 0xC9, 0xC2, 0x04, 0xB2, 0x00, 0x47, 0x05, 0xB8, 0x01, 0xC0, 0x04, 0xC4, 0x05, 0x0C, 0x81, 0x07, 0xFF, 0xFF, 0x00, 0x7F, 0x10, 0x7F, 0x10, 0x7F, 0x10, 0x7F, 0x10, 0x7F, 0x10, 0x7F, 0x10, 0x4A, 0x10, 0xAE, 0x32, 0xE0, 0x4B, 0xC1, 0x3D, 0x65, 0x00, 0x28, 0xE0, 0x01, 0x2C, 0x60, 0x00, 0x2A, 0x30, 0x60, 0x00, 0x00, 0x60, 0x67, 0x3D, 0xE1, 0x00, 0x00, 0x75, 0x00, 0x73, 0x65, 0x72, 0x33, 0x33, 0x2E, 0x64, 0x6C, 0x00, 0x6C, 0x00, 0x5F, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x00, 0x67, 0x65, 0x42, 0x65, 0x65, 0x50, 0x40, 0x34, 0xFF, 0xBF, 0x11, 0x3F, 0x04, 0x3F, 0x04, 0x3F, 0x04, 0x3F, 0x04, 0x3F, 0x04, 0x3F, 0x04, 0x3F, 0x04, 0x1F, 0x3F, 0x04, 0x3F, 0x04, 0x3F, 0x04, 0x3F, 0x04, 0x3A, 0x04, 0x3A, 0x04 }; static BOOL WriteRawFile(const WCHAR* FileName, const unsigned char* Data, DWORD Size) { BOOL Success; DWORD dwWritten; HANDLE Handle = CreateFileW(FileName, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, 0, NULL); if (Handle == INVALID_HANDLE_VALUE) { skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError()); return FALSE; } Success = WriteFile(Handle, Data, Size, &dwWritten, NULL); ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError()); ok(dwWritten == Size, "WriteFile wrote %lu bytes instead of %lu\n", dwWritten, Size); CloseHandle(Handle); return Success && (dwWritten == Size); } //PBYTE workspace = NULL; static BOOL WriteExeFile(const WCHAR* FileName) { unsigned char Data[1536]; DWORD final_size; if (!NT_SUCCESS(RtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, Data, sizeof(Data), exe_data, sizeof(exe_data), &final_size))) { skip("Unable to decompress\n"); return FALSE; } if (final_size != sizeof(Data)) { skip("Wrong final size: %lu\n", final_size); return FALSE; } return WriteRawFile(FileName, Data, sizeof(Data)); } static BOOL WriteDllFile(const WCHAR* FileName, DWORD dwBaseAddress) { unsigned char Data[1536]; DWORD final_size; if (!NT_SUCCESS(RtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, Data, sizeof(Data), dll_data, sizeof(dll_data), &final_size))) { skip("Unable to decompress\n"); return FALSE; } if (final_size != sizeof(Data)) { skip("Wrong final size: %lu\n", final_size); return FALSE; } if (dwBaseAddress) { /* ImageBase */ PDWORD Ptr = (PDWORD)&Data[0xB4]; ok_hex(*Ptr, 0x76E90000); *Ptr = dwBaseAddress; } return WriteRawFile(FileName, Data, sizeof(Data)); } START_TEST(LdrRelocateImage) { WCHAR ExePath[MAX_PATH]; WCHAR DllPath[MAX_PATH]; WCHAR TempPath[MAX_PATH]; HMODULE User32; BOOL Success; STARTUPINFOW si = {sizeof(si)}; PROCESS_INFORMATION pi; DWORD dwWait; UINT oldMode; GetTempPathW(_countof(ExePath), ExePath); GetTempPathW(_countof(DllPath), DllPath); GetTempPathW(_countof(TempPath), TempPath); wcscat(ExePath, L"\\tiny.exe"); wcscat(DllPath, L"\\user33.dll"); User32 = LoadLibraryA("user32.dll"); FreeLibrary(User32); if (!WriteExeFile(ExePath)) return; if (!WriteDllFile(DllPath, (DWORD)User32)) { ok(DeleteFileW(ExePath), "DeleteFile failed (err:0x%lx)\n", GetLastError()); return; } si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; oldMode = SetErrorMode(SEM_FAILCRITICALERRORS); Success = CreateProcessW(NULL, ExePath, NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT, NULL, TempPath, &si, &pi); ok(Success, "Expected CreateProcess to succeed (err:0x%lx)\n", GetLastError()); if (Success) { dwWait = WaitForSingleObject(pi.hProcess, 100); if (dwWait == WAIT_OBJECT_0) { DWORD dwExit = 0; GetExitCodeProcess(pi.hProcess, &dwExit); ok(dwExit == (DWORD)User32, "Expected proc exit %lx, got %lx\n", (DWORD)User32, dwExit); GetExitCodeThread(pi.hThread, &dwExit); ok(dwExit == (DWORD)User32, "Expected thrd exit %lx, got %lx\n", (DWORD)User32, dwExit); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } else { ok(0, "Process still running\n"); TerminateProcess(pi.hProcess, 0); } } SetErrorMode(oldMode); ok(DeleteFileW(ExePath), "DeleteFile failed (err:0x%lx)\n", GetLastError()); ok(DeleteFileW(DllPath), "DeleteFile failed (err:0x%lx)\n", GetLastError()); }