[PATCH 2/3] mspatcha: Implement GetFilePatchSignature functions.
Jeff Smith
whydoubt at gmail.com
Fri May 22 11:21:35 CDT 2020
Signed-off-by: Jeff Smith <whydoubt at gmail.com>
---
dlls/mspatcha/mspatcha_main.c | 46 +++++++++----
dlls/mspatcha/signature.c | 117 ++++++++++++++++++++++++++++++++
dlls/mspatcha/signature.h | 15 ++++
dlls/mspatcha/tests/signature.c | 68 +++++++++++++++++++
include/patchapi.h | 1 +
5 files changed, 235 insertions(+), 12 deletions(-)
diff --git a/dlls/mspatcha/mspatcha_main.c b/dlls/mspatcha/mspatcha_main.c
index 34dc46b216..bda761adfe 100644
--- a/dlls/mspatcha/mspatcha_main.c
+++ b/dlls/mspatcha/mspatcha_main.c
@@ -231,10 +231,19 @@ 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, LPSTR buffer)
{
- FIXME("stub - %s, %x, %p, %u, %p, %u, %p, %u, %p\n", debugstr_a(filename), flags, data,
+ BOOL ret;
+ WCHAR *filenameW;
+
+ TRACE("%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;
+
+ if (!(filenameW = strdupAW(filename)))
+ return FALSE;
+ ret = get_patch_signature(filenameW, flags, ignore_range_count, ignore_range,
+ retain_range_count, retain_range, bufsize, buffer);
+
+ HeapFree(GetProcessHeap(), 0, filenameW);
+ return ret;
}
/*****************************************************
@@ -244,10 +253,21 @@ 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, LPWSTR buffer)
{
- FIXME("stub - %s, %x, %p, %u, %p, %u, %p, %u, %p\n", debugstr_w(filename), flags, data,
+ BOOL ret;
+ LPSTR abuffer;
+
+ TRACE("%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;
+
+ if (!(abuffer = HeapAlloc(GetProcessHeap(), 0, bufsize / 2)))
+ return FALSE;
+ ret = get_patch_signature(filename, flags, ignore_range_count, ignore_range,
+ retain_range_count, retain_range, bufsize / 2, abuffer);
+ if (ret)
+ MultiByteToWideChar(CP_ACP, 0, abuffer, -1, buffer, bufsize);
+
+ HeapFree(GetProcessHeap(), 0, abuffer);
+ return ret;
}
/*****************************************************
@@ -257,10 +277,11 @@ BOOL WINAPI GetFilePatchSignatureByHandle(HANDLE handle, ULONG flags, PVOID opti
PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count,
PPATCH_RETAIN_RANGE retain_range, ULONG bufsize, LPSTR buffer)
{
- FIXME("stub - %p, %x, %p, %u, %p, %u, %p, %u, %p\n", handle, flags, options,
+ TRACE("%p, %x, %p, %u, %p, %u, %p, %u, %p\n", handle, flags, options,
ignore_range_count, ignore_range, retain_range_count, retain_range, bufsize, buffer);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+
+ return get_patch_signature_by_handle(handle, flags, ignore_range_count, ignore_range,
+ retain_range_count, retain_range, bufsize, buffer);
}
/*****************************************************
@@ -271,10 +292,11 @@ BOOL WINAPI GetFilePatchSignatureByBuffer(PBYTE file_buf, ULONG file_size, ULONG
ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range,
ULONG bufsize, LPSTR buffer)
{
- FIXME("stub - %p, %u, %x, %p, %u, %p, %u, %p, %u, %p\n", file_buf, file_size, flags, options,
+ TRACE("%p, %u, %x, %p, %u, %p, %u, %p, %u, %p\n", file_buf, file_size, flags, options,
ignore_range_count, ignore_range, retain_range_count, retain_range, bufsize, buffer);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+
+ return get_patch_signature_by_buffer(file_buf, file_size, flags, ignore_range_count, ignore_range,
+ retain_range_count, retain_range, bufsize, buffer);
}
/*****************************************************
diff --git a/dlls/mspatcha/signature.c b/dlls/mspatcha/signature.c
index 6f6c085de7..434615b8c4 100644
--- a/dlls/mspatcha/signature.c
+++ b/dlls/mspatcha/signature.c
@@ -19,14 +19,131 @@
*/
#include <stdarg.h>
+#include <stdlib.h>
#include "windef.h"
+#include "winternl.h"
#include "wine/heap.h"
#include "patchapi.h"
#include "signature.h"
+typedef struct
+{
+ unsigned int i[2];
+ unsigned int buf[4];
+ unsigned char in[64];
+ unsigned char digest[16];
+} MD5_CTX;
+
+extern VOID WINAPI MD5Init( MD5_CTX *);
+extern VOID WINAPI MD5Update( MD5_CTX *, const unsigned char *, unsigned int );
+extern VOID WINAPI MD5Final( MD5_CTX *);
+
+BOOL get_patch_signature(LPCWSTR filename, ULONG flags,
+ ULONG ignore_range_count, PPATCH_IGNORE_RANGE ignore_range,
+ ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range,
+ ULONG bufsize, LPSTR buffer)
+{
+ HANDLE file_handle;
+ BOOL res;
+ DWORD err = ERROR_SUCCESS;
+
+ file_handle = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if (file_handle == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ res = get_patch_signature_by_handle(file_handle, flags, ignore_range_count, ignore_range,
+ retain_range_count, retain_range, bufsize, buffer);
+
+ err = GetLastError();
+ CloseHandle(file_handle);
+ SetLastError(err);
+
+ return res;
+}
+
+BOOL get_patch_signature_by_handle(HANDLE file_handle, ULONG flags,
+ ULONG ignore_range_count, PPATCH_IGNORE_RANGE ignore_range,
+ ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range,
+ ULONG bufsize, LPSTR buffer)
+{
+ LPVOID file_buf;
+ LARGE_INTEGER file_size;
+ DWORD err;
+ BOOL res;
+
+ if (file_handle == INVALID_HANDLE_VALUE)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ file_size.QuadPart = 0;
+ if (!GetFileSizeEx(file_handle, &file_size))
+ return FALSE;
+
+ file_buf = heap_alloc(file_size.QuadPart);
+ if (!file_buf)
+ return FALSE;
+
+ res = ReadFile(file_handle, file_buf, file_size.QuadPart, NULL, NULL);
+ if (res)
+ res = get_patch_signature_by_buffer(file_buf, file_size.QuadPart, flags,
+ ignore_range_count, ignore_range, retain_range_count, retain_range, bufsize, buffer);
+
+ err = GetLastError();
+ heap_free(file_buf);
+ SetLastError(err);
+
+ return res;
+}
+
+BOOL get_patch_signature_by_buffer(PVOID file_buffer, ULONG file_size, ULONG flags,
+ ULONG ignore_range_count, PPATCH_IGNORE_RANGE ignore_range,
+ ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range,
+ ULONG bufsize, LPSTR buffer)
+{
+ if (!normalize_for_patch_signature(file_buffer, file_size, flags, 0x10000000, 0x10000000,
+ ignore_range_count, ignore_range, retain_range_count, retain_range))
+ return FALSE;
+
+ if (flags & PATCH_OPTION_SIGNATURE_MD5)
+ {
+ static const char hex[16] = "0123456789abcdef";
+ MD5_CTX ctx;
+ UINT i;
+
+ MD5Init(&ctx);
+ MD5Update(&ctx, file_buffer, file_size);
+ MD5Final(&ctx);
+
+ if (bufsize < 33)
+ goto insufficient_buffer;
+ for (i = 0; i < 16; i++)
+ {
+ buffer[i*2] = hex[ctx.digest[i] >> 4];
+ buffer[i*2+1] = hex[ctx.digest[i] & 0xf];
+ }
+ buffer[32] = 0;
+ }
+ else
+ {
+ DWORD crc = RtlComputeCrc32(0, file_buffer, file_size);
+
+ if (bufsize < 9)
+ goto insufficient_buffer;
+ _ltoa(crc, buffer, 16);
+ }
+
+ return TRUE;
+
+insufficient_buffer:
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+}
+
/*
* Check for PE32 signatures and return file offset if found.
*/
diff --git a/dlls/mspatcha/signature.h b/dlls/mspatcha/signature.h
index b55ab84b7c..fb18f7e288 100644
--- a/dlls/mspatcha/signature.h
+++ b/dlls/mspatcha/signature.h
@@ -18,6 +18,21 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+BOOL get_patch_signature(LPCWSTR filename, ULONG flags,
+ ULONG ignore_range_count, PPATCH_IGNORE_RANGE ignore_range,
+ ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range,
+ ULONG bufsize, LPSTR buffer);
+
+BOOL get_patch_signature_by_handle(HANDLE file_handle, ULONG flags,
+ ULONG ignore_range_count, PPATCH_IGNORE_RANGE ignore_range,
+ ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range,
+ ULONG bufsize, LPSTR buffer);
+
+BOOL get_patch_signature_by_buffer(PVOID file_buffer, ULONG file_size, ULONG flags,
+ ULONG ignore_range_count, PPATCH_IGNORE_RANGE ignore_range,
+ ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range,
+ ULONG bufsize, LPSTR buffer);
+
DWORD get_pe_offset(LPCVOID file_buffer, ULONG file_size);
BOOL normalize_pe(PVOID file_buffer, ULONG file_size, DWORD pe_offset,
diff --git a/dlls/mspatcha/tests/signature.c b/dlls/mspatcha/tests/signature.c
index bd2f9dc8be..ad570ef735 100644
--- a/dlls/mspatcha/tests/signature.c
+++ b/dlls/mspatcha/tests/signature.c
@@ -24,6 +24,8 @@
static BOOL (WINAPI *pNormalizeFileForPatchSignature)(PVOID, ULONG, ULONG, PATCH_OPTION_DATA*, ULONG,
ULONG, ULONG, PPATCH_IGNORE_RANGE, ULONG, PPATCH_RETAIN_RANGE);
+static BOOL (WINAPI *pGetFilePatchSignatureByBuffer)(PBYTE, ULONG, ULONG, PVOID, ULONG,
+ PPATCH_IGNORE_RANGE, ULONG, PPATCH_RETAIN_RANGE, ULONG, LPSTR);
static BYTE array[1024];
@@ -36,6 +38,7 @@ static BOOL init_function_pointers(void)
return FALSE;
}
pNormalizeFileForPatchSignature = (void *)GetProcAddress(mspatcha, "NormalizeFileForPatchSignature");
+ pGetFilePatchSignatureByBuffer = (void *)GetProcAddress(mspatcha, "GetFilePatchSignatureByBuffer");
return TRUE;
}
@@ -307,6 +310,70 @@ static void test_normalize_rebase(void)
image_base_initial, header->OptionalHeader.ImageBase);
}
+static void test_signature_by_buffer(void)
+{
+ PIMAGE_NT_HEADERS32 header;
+ BOOL result;
+ DWORD err;
+ char buf[33];
+
+ if (!pGetFilePatchSignatureByBuffer)
+ return;
+
+ /* Test CRC32 signature */
+ memset(array, 0xcc, 8);
+ buf[0] = '\0';
+ result = pGetFilePatchSignatureByBuffer(array, 8, 0, NULL, 0, NULL, 0, NULL, 9, buf);
+ ok(result == TRUE, "Expected %d, got %d\n", TRUE, result);
+ ok(!strcmp(buf, "58ea8bb8"), "Expected %s, got %s\n", "58ea8bb8", buf);
+
+ /* Test MD5 signature w/ insufficient buffer */
+ memset(array, 0xcc, 8);
+ buf[0] = '\0';
+ SetLastError(0xdeadbeef);
+ result = pGetFilePatchSignatureByBuffer(array, 8, 0, NULL, 0, NULL, 0, NULL, 8, buf);
+ err = GetLastError();
+ ok(result == FALSE, "Expected %d, got %d\n", FALSE, result);
+ ok(err == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %#x\n", err);
+ ok(!buf[0], "Got unexpected %s\n", buf);
+
+ /* Test MD5 signature */
+ memset(array, 0xcc, 8);
+ buf[0] = '\0';
+ result = pGetFilePatchSignatureByBuffer(array, 8, PATCH_OPTION_SIGNATURE_MD5, NULL,
+ 0, NULL, 0, NULL, 33, buf);
+ ok(result == TRUE, "Expected %d, got %d\n", TRUE, result);
+ ok(!strcmp(buf, "7bffa66e1c861fcbf38426d134508908"), "Expected %s, got %s\n",
+ "7bffa66e1c861fcbf38426d134508908", buf);
+
+ /* Test MD5 signature w/ insufficient buffer */
+ memset(array, 0xcc, 8);
+ buf[0] = '\0';
+ SetLastError(0xdeadbeef);
+ result = pGetFilePatchSignatureByBuffer(array, 8, PATCH_OPTION_SIGNATURE_MD5, NULL,
+ 0, NULL, 0, NULL, 32, buf);
+ err = GetLastError();
+ ok(result == FALSE, "Expected %d, got %d\n", FALSE, result);
+ ok(err == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %#x\n", err);
+ ok(!buf[0], "Got unexpected %s\n", buf);
+
+ /* Test signature of PE32 executable image */
+ memset(array, 0, 1024);
+ setup_pe_with_sections(array, &header, NULL);
+ header->FileHeader.TimeDateStamp = 0xdeadbeef;
+ header->OptionalHeader.CheckSum = 0xdeadbeef;
+ header->OptionalHeader.ImageBase = 0x400000;
+ result = pGetFilePatchSignatureByBuffer(array, 1024, 0, NULL, 0, NULL, 0, NULL, 9, buf);
+ ok(result == TRUE, "Expected %d, got %d\n", TRUE, result);
+ ok(!strcmp(buf, "f953f764"), "Expected %s, got %s\n", "f953f764", buf);
+ ok(header->FileHeader.TimeDateStamp == 0x10000000, "Expected %#x, got %#x\n",
+ 0x10000000, header->FileHeader.TimeDateStamp);
+ ok(header->OptionalHeader.CheckSum == 0x9dd2, "Expected %#x, got %#x\n",
+ 0x9dd2, header->OptionalHeader.CheckSum);
+ ok(header->OptionalHeader.ImageBase == 0x10000000, "Expected %#x, got %#x\n",
+ 0x10000000, header->OptionalHeader.ImageBase);
+}
+
START_TEST(signature)
{
if (!init_function_pointers())
@@ -316,4 +383,5 @@ START_TEST(signature)
test_normalize_retain_range();
test_normalize_flags();
test_normalize_rebase();
+ test_signature_by_buffer();
}
diff --git a/include/patchapi.h b/include/patchapi.h
index 1ccdf9dec7..9540154568 100644
--- a/include/patchapi.h
+++ b/include/patchapi.h
@@ -36,6 +36,7 @@ extern "C" {
#define PATCH_OPTION_NO_CHECKSUM 0x00200000
#define PATCH_OPTION_NO_RESTIMEFIX 0x00400000
#define PATCH_OPTION_NO_TIMESTAMP 0x00800000
+#define PATCH_OPTION_SIGNATURE_MD5 0x01000000
#define PATCH_OPTION_INTERLEAVE_FILES 0x40000000
#define PATCH_OPTION_RESERVED1 0x80000000
--
2.23.0
More information about the wine-devel
mailing list