From 33e3a69a7fedc75a3cc988412494233d6b84967a Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Sun, 2 Dec 2018 19:14:16 +0100 Subject: [PATCH] [MSPATCHA] Implement GetFilePatchSignature functions --- dll/win32/mspatcha/mspatcha.spec | 10 +- dll/win32/mspatcha/mspatcha_main.c | 250 ++++++++++++++++++++++++----- 2 files changed, 211 insertions(+), 49 deletions(-) diff --git a/dll/win32/mspatcha/mspatcha.spec b/dll/win32/mspatcha/mspatcha.spec index 08231e0d6f4..cf3d7d68709 100644 --- a/dll/win32/mspatcha/mspatcha.spec +++ b/dll/win32/mspatcha/mspatcha.spec @@ -1,12 +1,12 @@ 1 stdcall ApplyPatchToFileA(str str str long) -2 stdcall -stub ApplyPatchToFileByHandles(ptr ptr ptr long) +2 stdcall ApplyPatchToFileByHandles(ptr ptr ptr long) 3 stub ApplyPatchToFileByHandlesEx 4 stub ApplyPatchToFileExA 5 stub ApplyPatchToFileExW 6 stdcall ApplyPatchToFileW(wstr wstr wstr long) 7 stdcall GetFilePatchSignatureA(str long ptr long ptr long ptr long ptr) -8 stdcall -stub GetFilePatchSignatureByHandle(ptr long ptr long ptr long ptr long ptr) +8 stdcall GetFilePatchSignatureByHandle(ptr long ptr long ptr long ptr long ptr) 9 stdcall GetFilePatchSignatureW(wstr long ptr long ptr long ptr long ptr) -10 stdcall -stub TestApplyPatchToFileA(str str long) -11 stdcall -stub TestApplyPatchToFileByHandles(ptr ptr long) -12 stdcall -stub TestApplyPatchToFileW(wstr wstr long) +10 stdcall TestApplyPatchToFileA(str str long) +11 stdcall TestApplyPatchToFileByHandles(ptr ptr long) +12 stdcall TestApplyPatchToFileW(wstr wstr long) diff --git a/dll/win32/mspatcha/mspatcha_main.c b/dll/win32/mspatcha/mspatcha_main.c index 8dc4403d13d..4ad198873ed 100644 --- a/dll/win32/mspatcha/mspatcha_main.c +++ b/dll/win32/mspatcha/mspatcha_main.c @@ -18,16 +18,17 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" - -#include - +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" #include "winnls.h" +#include "ndk/rtlfuncs.h" #include "patchapi.h" #include "wine/debug.h" +static const char szHexString[] = "0123456789abcdef"; +#define SIGNATURE_MIN_SIZE 9 + WINE_DEFAULT_DEBUG_CHANNEL(mspatcha); /***************************************************** @@ -49,55 +50,77 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return TRUE; } -static inline WCHAR *strdupAW( const char *src ) -{ - WCHAR *dst = NULL; - if (src) - { - int len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 ); - if ((dst = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) - MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len ); - } - return dst; -} - /***************************************************** * ApplyPatchToFileA (MSPATCHA.1) */ BOOL WINAPI ApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, LPCSTR new_file, ULONG apply_flags) { - BOOL ret; - WCHAR *patch_fileW, *new_fileW, *old_fileW = NULL; + BOOL ret = FALSE; + HANDLE hPatch, hOld, hNew; - if (!(patch_fileW = strdupAW( patch_file ))) return FALSE; - if (old_file && !(old_fileW = strdupAW( old_file ))) + hPatch = CreateFileA(patch_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hPatch != INVALID_HANDLE_VALUE) { - HeapFree( GetProcessHeap(), 0, patch_fileW ); - return FALSE; + hOld = CreateFileA(old_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hOld != INVALID_HANDLE_VALUE) + { + hNew = CreateFileA(new_file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (hNew != INVALID_HANDLE_VALUE) + { + ret = ApplyPatchToFileByHandles(hPatch, hOld, hNew, apply_flags); + CloseHandle(hNew); + } + CloseHandle(hOld); + } + CloseHandle(hPatch); } - if (!(new_fileW = strdupAW( new_file ))) - { - HeapFree( GetProcessHeap(), 0, patch_fileW ); - HeapFree( GetProcessHeap(), 0, old_fileW ); - return FALSE; - } - ret = ApplyPatchToFileW( patch_fileW, old_fileW, new_fileW, apply_flags ); - HeapFree( GetProcessHeap(), 0, patch_fileW ); - HeapFree( GetProcessHeap(), 0, old_fileW ); - HeapFree( GetProcessHeap(), 0, new_fileW ); + return ret; } +/***************************************************** + * ApplyPatchToFileByHandles (MSPATCHA.2) + */ +BOOL WINAPI ApplyPatchToFileByHandles(HANDLE patch_file, HANDLE old_file, HANDLE new_file, ULONG apply_flags) +{ + FIXME("stub - %p, %p, %p, %08x\n", patch_file, old_file, new_file, apply_flags); + + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + /***************************************************** * ApplyPatchToFileW (MSPATCHA.6) */ BOOL WINAPI ApplyPatchToFileW(LPCWSTR patch_file, LPCWSTR old_file, LPCWSTR new_file, ULONG apply_flags) { - FIXME("stub - %s, %s, %s, %08x\n", debugstr_w(patch_file), debugstr_w(old_file), - debugstr_w(new_file), apply_flags); + BOOL ret = FALSE; + HANDLE hPatch, hOld, hNew; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + hPatch = CreateFileW(patch_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hPatch != INVALID_HANDLE_VALUE) + { + hOld = CreateFileW(old_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hOld != INVALID_HANDLE_VALUE) + { + hNew = CreateFileW(new_file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (hNew != INVALID_HANDLE_VALUE) + { + ret = ApplyPatchToFileByHandles(hPatch, hOld, hNew, apply_flags); + CloseHandle(hNew); + } + CloseHandle(hOld); + } + CloseHandle(hPatch); + } + + return ret; } /***************************************************** @@ -107,10 +130,71 @@ BOOL WINAPI GetFilePatchSignatureA(LPCSTR filename, ULONG flags, PVOID data, ULO PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range, ULONG bufsize, PVOID buffer) { - FIXME("stub - %s, %x, %p, %u, %p, %u, %p, %u, %p\n", debugstr_a(filename), flags, data, - ignore_range_count, ignore_range, retain_range_count, retain_range, bufsize, buffer); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + BOOL ret = FALSE; + HANDLE hFile; + + hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hFile != INVALID_HANDLE_VALUE) + { + ret = GetFilePatchSignatureByHandle(hFile, flags, data, ignore_range_count, ignore_range, + retain_range_count, retain_range, bufsize, buffer); + CloseHandle(hFile); + } + + return ret; +} + +/***************************************************** + * GetFilePatchSignatureA (MSPATCHA.7) + */ +BOOL WINAPI GetFilePatchSignatureByHandle(HANDLE hFile, ULONG flags, PVOID data, ULONG ignore_range_count, + PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count, + PPATCH_RETAIN_RANGE retain_range, ULONG bufsize, PVOID buffer) +{ + BOOL ret = FALSE; + HANDLE hMap; + DWORD dwSize, ulCrc; + PVOID pView; + + if (flags) + FIXME("Unhandled flags 0x%x\n", flags); + if (ignore_range_count) + FIXME("Unhandled ignore_range_count %u\n", ignore_range_count); + if (retain_range_count) + FIXME("Unhandled ignore_range_count %u\n", retain_range_count); + + dwSize = GetFileSize(hFile, NULL); + hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if (hMap != INVALID_HANDLE_VALUE) + { + pView = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); + CloseHandle(hMap); + + if (dwSize >= 2 && *(PWORD)pView == IMAGE_DOS_SIGNATURE) + { + FIXME("Potentially unimplemented case, normalized signature\n"); + } + + ulCrc = RtlComputeCrc32(0, pView, dwSize); + if (bufsize >= SIGNATURE_MIN_SIZE) + { + char *pBuffer = buffer; + pBuffer[8] = '\0'; + for (dwSize = 0; dwSize < 8; ++dwSize) + { + pBuffer[7 - dwSize] = szHexString[ulCrc & 0xf]; + ulCrc >>= 4; + } + ret = TRUE; + } + UnmapViewOfFile(pView); + + if (bufsize < SIGNATURE_MIN_SIZE) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + } + + return ret; } /***************************************************** @@ -120,8 +204,86 @@ BOOL WINAPI GetFilePatchSignatureW(LPCWSTR filename, ULONG flags, PVOID data, UL PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range, ULONG bufsize, PVOID buffer) { - FIXME("stub - %s, %x, %p, %u, %p, %u, %p, %u, %p\n", debugstr_w(filename), flags, data, - ignore_range_count, ignore_range, retain_range_count, retain_range, bufsize, buffer); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + CHAR LocalBuf[SIGNATURE_MIN_SIZE]; + BOOL ret = FALSE; + HANDLE hFile; + + hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hFile != INVALID_HANDLE_VALUE) + { + ret = GetFilePatchSignatureByHandle(hFile, flags, data, ignore_range_count, ignore_range, + retain_range_count, retain_range, sizeof(LocalBuf), LocalBuf); + CloseHandle(hFile); + + if (bufsize < (SIGNATURE_MIN_SIZE * sizeof(WCHAR))) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + if (ret) + { + MultiByteToWideChar(CP_ACP, 0, LocalBuf, -1, buffer, bufsize / sizeof(WCHAR)); + } + } + + return ret; +} + +/***************************************************** + * TestApplyPatchToFileA (MSPATCHA.10) + */ +BOOL WINAPI TestApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, ULONG apply_flags) +{ + BOOL ret = FALSE; + HANDLE hPatch, hOld; + + hPatch = CreateFileA(patch_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hPatch != INVALID_HANDLE_VALUE) + { + hOld = CreateFileA(old_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hOld != INVALID_HANDLE_VALUE) + { + ret = TestApplyPatchToFileByHandles(hPatch, hOld, apply_flags); + CloseHandle(hOld); + } + CloseHandle(hPatch); + } + + return ret; +} + +/***************************************************** + * TestApplyPatchToFileByHandles (MSPATCHA.11) + */ +BOOL WINAPI TestApplyPatchToFileByHandles(HANDLE patch_file, HANDLE old_file, ULONG apply_flags) +{ + return ApplyPatchToFileByHandles(patch_file, old_file, INVALID_HANDLE_VALUE, apply_flags | APPLY_OPTION_TEST_ONLY); +} + +/***************************************************** + * TestApplyPatchToFileW (MSPATCHA.12) + */ +BOOL WINAPI TestApplyPatchToFileW(LPCWSTR patch_file, LPCWSTR old_file, ULONG apply_flags) +{ + BOOL ret = FALSE; + HANDLE hPatch, hOld; + + hPatch = CreateFileW(patch_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hPatch != INVALID_HANDLE_VALUE) + { + hOld = CreateFileW(old_file, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (hOld != INVALID_HANDLE_VALUE) + { + ret = TestApplyPatchToFileByHandles(hPatch, hOld, apply_flags); + CloseHandle(hOld); + } + CloseHandle(hPatch); + } + + return ret; }