ReactOS 0.4.16-dev-109-gf4cb10f
mspatcha_main.c
Go to the documentation of this file.
1/*
2 * PatchAPI
3 *
4 * Copyright 2011 David Hedberg for CodeWeavers
5 * Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#define WIN32_NO_STATUS
23#include "windef.h"
24#include "winbase.h"
25#include "winnls.h"
26#include "ndk/rtlfuncs.h"
27#include "patchapi.h"
28#include "lzx.h"
29#include "wine/debug.h"
30
31static const char szHexString[] = "0123456789abcdef";
32#define SIGNATURE_MIN_SIZE 9
33
34#define UNKNOWN_FLAGS_COMBINATION 0x00c40001
35
36
38
39
40typedef struct _SAFE_READ
41{
46
47
58{
59 if (pRead->Ptr + sizeof(BYTE) <= (pRead->Root + pRead->Size))
60 {
61 BYTE Value = *(PBYTE)pRead->Ptr;
62 pRead->Ptr += sizeof(BYTE);
63 return Value;
64 }
65 pRead->Ptr = pRead->Root + pRead->Size;
66 return 0;
67}
68
79{
80 if (pRead->Ptr + sizeof(USHORT) <= (pRead->Root + pRead->Size))
81 {
82 USHORT Value = *(PUSHORT)pRead->Ptr;
83 pRead->Ptr += sizeof(USHORT);
84 return Value;
85 }
86 pRead->Ptr = pRead->Root + pRead->Size;
87 return 0;
88}
89
100{
101 if (pRead->Ptr + sizeof(DWORD) <= (pRead->Root + pRead->Size))
102 {
103 DWORD Value = *(PDWORD)pRead->Ptr;
104 pRead->Ptr += sizeof(DWORD);
105 return Value;
106 }
107 pRead->Ptr = pRead->Root + pRead->Size;
108 return 0;
109}
110
121{
122 UINT Result = 0, offset;
123
124 for (offset = 0; offset < 32; offset += 7)
125 {
126 DWORD val = ReadByte(pRead);
127 Result |= ((val & 0x7f) << offset);
128 if (val & 0x80)
129 break;
130 }
131
132 return Result;
133}
134
135
146{
147 INT Result = 0, offset;
148
149 for (offset = 0; offset < 32; offset += 6)
150 {
151 INT val = (INT)(DWORD)ReadByte(pRead);
152 Result |= ((val & 0x3f) << offset);
153 if (val & 0x80)
154 {
155 if (val & 0x40)
156 Result *= -1;
157 break;
158 }
159 }
160
161 return Result;
162}
163
164
165typedef struct _PATCH_HEADER
166{
168
171
174
177 DWORD DataSize; // Payload after the patch header
178
180
181
195{
196 HANDLE hMap;
197 PVOID pView;
198
201 if (hMap != INVALID_HANDLE_VALUE)
202 {
203 pView = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
204 CloseHandle(hMap);
205 return pView;
206 }
207
208 return NULL;
209}
210
211
212/*****************************************************
213 * DllMain (MSPATCHA.@)
214 */
216{
217 switch (fdwReason)
218 {
221 break;
222 }
223
224 return TRUE;
225}
226
227/*****************************************************
228 * ApplyPatchToFileA (MSPATCHA.1)
229 */
231{
232 BOOL ret = FALSE;
233 HANDLE hPatch, hOld, hNew;
234
237 if (hPatch != INVALID_HANDLE_VALUE)
238 {
241 if (hOld != INVALID_HANDLE_VALUE)
242 {
245 if (hNew != INVALID_HANDLE_VALUE)
246 {
247 ret = ApplyPatchToFileByHandles(hPatch, hOld, hNew, apply_flags);
248 CloseHandle(hNew);
249 }
250 CloseHandle(hOld);
251 }
252 CloseHandle(hPatch);
253 }
254
255 return ret;
256}
257
258
273{
274 DWORD Crc, Unknown;
275 int Delta;
276
277 ZeroMemory(Header, sizeof(*Header));
278
279 /* Validate the patch */
280 Crc = RtlComputeCrc32(0, Patch->Root, Patch->Size);
281 if (Crc != ~0)
282 return ERROR_PATCH_CORRUPT;
283
284 if (ReadDWord(Patch) != '91AP')
286
287 /* Read the flags, warn about an unknown combination */
288 Header->Flags = ReadDWord(Patch);
290 ERR("Unknown flags: 0x%x, patch will most likely fail\n", Header->Flags ^ UNKNOWN_FLAGS_COMBINATION);
291
292 /* 0x5bb3284e, 0x5bb33562, 0x5bb357b1 */
294 TRACE("Unknown: 0x%x\n", Unknown);
295
296 Header->OutputSize = DecodeDWord(Patch);
297 Header->OutputCrc = ReadDWord(Patch);
298
300 if (Unknown != 1)
301 ERR("Field after CRC is not 1 but %u\n", Unknown);
302
304 Header->OldSize = Header->OutputSize + Delta;
305 Header->OldCrc = ReadDWord(Patch);
306
308 if (Unknown != 0)
309 ERR("Field1 after OldCrc is not 0 but %u\n", Unknown);
310
312 if (Unknown != 0)
313 ERR("Field2 after OldCrc is not 0 but %u\n", Unknown);
314
315 Header->DataSize = DecodeDWord(Patch);
316 /* Remaining data, minus the CRC appended */
317 if (Header->DataSize != (Patch->Size - (Patch->Ptr - Patch->Root) - sizeof(DWORD)))
318 {
319 ERR("Unable to read header, check previous logging!\n");
321 }
322 return STATUS_SUCCESS;
323}
324
341{
342 SAFE_READ NewFile;
343 HANDLE hMap;
344 USHORT BlockSize;
346 struct LZXstate* state;
347 int lzxResult;
348
349 hMap = CreateFileMappingW(new_file, NULL, PAGE_READWRITE, 0, Header->OutputSize, NULL);
350 if (hMap == INVALID_HANDLE_VALUE)
352
353 NewFile.Root = NewFile.Ptr = MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0);
354 CloseHandle(hMap);
355 NewFile.Size = Header->OutputSize;
356
357 if (!NewFile.Root)
359
360 /* At this point Patch->Ptr should point to the payload */
361 BlockSize = ReadUShort(Patch);
362
363 /* This window size does not work on all files (for example, MS SQL Express 2008 setup) */
364 state = LZXinit(17);
365 if (state)
366 {
367 lzxResult = LZXdecompress(state, Patch->Ptr, NewFile.Ptr, BlockSize, NewFile.Size);
369
370 if (lzxResult == DECR_OK)
372 else
374 }
375 else
376 {
378 }
379
380 UnmapViewOfFile(NewFile.Root);
381 return dwStatus;
382}
383
384
385/*****************************************************
386 * ApplyPatchToFileByHandles (MSPATCHA.2)
387 */
389{
390 SAFE_READ Patch, OldFile;
393
394 Patch.Root = Patch.Ptr = MapFile(patch_file, &Patch.Size);
395 if (!Patch.Root)
396 {
398 return FALSE;
399 }
400
401 /* Let's decode the header */
404 {
407 return FALSE;
408 }
409
410 OldFile.Root = OldFile.Ptr = MapFile(old_file, &OldFile.Size);
411 if (OldFile.Root)
412 {
413 DWORD dwCrc;
414
415 /* Verify the input file */
416 dwCrc = RtlComputeCrc32(0, OldFile.Root, OldFile.Size);
417 if (OldFile.Size == Header.OldSize && dwCrc == Header.OldCrc)
418 {
419 if (apply_flags & APPLY_OPTION_TEST_ONLY)
421 else
423 }
424 else
425 {
427 }
428 UnmapViewOfFile(OldFile.Root);
429 }
430 else
431 {
435 }
436
439 return dwStatus == STATUS_SUCCESS;
440}
441
442/*****************************************************
443 * ApplyPatchToFileW (MSPATCHA.6)
444 */
446{
447 BOOL ret = FALSE;
448 HANDLE hPatch, hOld, hNew;
449
452 if (hPatch != INVALID_HANDLE_VALUE)
453 {
456 if (hOld != INVALID_HANDLE_VALUE)
457 {
460 if (hNew != INVALID_HANDLE_VALUE)
461 {
462 ret = ApplyPatchToFileByHandles(hPatch, hOld, hNew, apply_flags);
463 CloseHandle(hNew);
464 }
465 CloseHandle(hOld);
466 }
467 CloseHandle(hPatch);
468 }
469
470 return ret;
471}
472
473/*****************************************************
474 * GetFilePatchSignatureA (MSPATCHA.7)
475 */
477 PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count,
479{
480 BOOL ret = FALSE;
482
486 {
487 ret = GetFilePatchSignatureByHandle(hFile, flags, data, ignore_range_count, ignore_range,
488 retain_range_count, retain_range, bufsize, buffer);
490 }
491
492 return ret;
493}
494
495/*****************************************************
496 * GetFilePatchSignatureA (MSPATCHA.7)
497 */
499 PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count,
501{
502 BOOL ret = FALSE;
503 DWORD dwSize, ulCrc;
504 PBYTE pData;
505
506 if (flags)
507 FIXME("Unhandled flags 0x%x\n", flags);
508 if (ignore_range_count)
509 FIXME("Unhandled ignore_range_count %u\n", ignore_range_count);
510 if (retain_range_count)
511 FIXME("Unhandled ignore_range_count %u\n", retain_range_count);
512
513 if ((pData = MapFile(hFile, &dwSize)))
514 {
515 if (dwSize >= 2 && *(PWORD)pData == IMAGE_DOS_SIGNATURE)
516 {
517 FIXME("Potentially unimplemented case, normalized signature\n");
518 }
519
520 ulCrc = RtlComputeCrc32(0, pData, dwSize);
522 {
523 char *pBuffer = buffer;
524 pBuffer[8] = '\0';
525 for (dwSize = 0; dwSize < 8; ++dwSize)
526 {
527 pBuffer[7 - dwSize] = szHexString[ulCrc & 0xf];
528 ulCrc >>= 4;
529 }
530 ret = TRUE;
531 }
533
536 }
537
538 return ret;
539}
540
541/*****************************************************
542 * GetFilePatchSignatureW (MSPATCHA.9)
543 */
545 PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count,
547{
548 CHAR LocalBuf[SIGNATURE_MIN_SIZE];
549 BOOL ret = FALSE;
551
555 {
556 ret = GetFilePatchSignatureByHandle(hFile, flags, data, ignore_range_count, ignore_range,
557 retain_range_count, retain_range, sizeof(LocalBuf), LocalBuf);
559
560 if (bufsize < (SIGNATURE_MIN_SIZE * sizeof(WCHAR)))
561 {
563 return FALSE;
564 }
565 if (ret)
566 {
567 MultiByteToWideChar(CP_ACP, 0, LocalBuf, -1, buffer, bufsize / sizeof(WCHAR));
568 }
569 }
570
571 return ret;
572}
573
574/*****************************************************
575 * TestApplyPatchToFileA (MSPATCHA.10)
576 */
578{
579 BOOL ret = FALSE;
580 HANDLE hPatch, hOld;
581
584 if (hPatch != INVALID_HANDLE_VALUE)
585 {
588 if (hOld != INVALID_HANDLE_VALUE)
589 {
590 ret = TestApplyPatchToFileByHandles(hPatch, hOld, apply_flags);
591 CloseHandle(hOld);
592 }
593 CloseHandle(hPatch);
594 }
595
596 return ret;
597}
598
599/*****************************************************
600 * TestApplyPatchToFileByHandles (MSPATCHA.11)
601 */
603{
605}
606
607/*****************************************************
608 * TestApplyPatchToFileW (MSPATCHA.12)
609 */
611{
612 BOOL ret = FALSE;
613 HANDLE hPatch, hOld;
614
617 if (hPatch != INVALID_HANDLE_VALUE)
618 {
621 if (hOld != INVALID_HANDLE_VALUE)
622 {
623 ret = TestApplyPatchToFileByHandles(hPatch, hOld, apply_flags);
624 CloseHandle(hOld);
625 }
626 CloseHandle(hPatch);
627 }
628
629 return ret;
630}
static int state
Definition: maze.c:121
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
Definition: Header.h:9
Definition: patch.h:62
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define DECR_OK
Definition: mszip.h:79
#define CloseHandle
Definition: compat.h:739
#define PAGE_READONLY
Definition: compat.h:138
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define RtlComputeCrc32
Definition: compat.h:810
#define UnmapViewOfFile
Definition: compat.h:746
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:744
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GENERIC_READ
Definition: compat.h:135
#define CreateFileW
Definition: compat.h:741
#define FILE_MAP_READ
Definition: compat.h:776
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define MapViewOfFile
Definition: compat.h:745
#define MultiByteToWideChar
Definition: compat.h:110
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
static UINT patch_file(MSIPACKAGE *package, MSIFILEPATCH *patch)
Definition: files.c:704
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint buffer
Definition: glext.h:5915
GLbitfield flags
Definition: glext.h:7161
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
GLintptr offset
Definition: glext.h:5920
@ Unknown
Definition: i8042prt.h:114
const char * filename
Definition: ioapi.h:137
void LZXteardown(struct LZXstate *pState)
Definition: lzx.c:209
int LZXdecompress(struct LZXstate *pState, unsigned char *inpos, unsigned char *outpos, int inlen, int outlen)
Definition: lzx.c:461
struct LZXstate * LZXinit(int wndsize)
Definition: lzx.c:172
static IN DWORD IN LPVOID lpvReserved
#define CREATE_ALWAYS
Definition: disk.h:72
#define FILE_FLAG_SEQUENTIAL_SCAN
Definition: disk.h:43
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static const char szHexString[]
Definition: mspatcha_main.c:31
BOOL WINAPI ApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, LPCSTR new_file, ULONG apply_flags)
BOOL WINAPI GetFilePatchSignatureW(LPCWSTR filename, 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)
static PBYTE MapFile(HANDLE hFile, DWORD *dwSize)
BOOL WINAPI ApplyPatchToFileByHandles(HANDLE patch_file, HANDLE old_file, HANDLE new_file, ULONG apply_flags)
BOOL WINAPI TestApplyPatchToFileByHandles(HANDLE patch_file, HANDLE old_file, ULONG apply_flags)
struct _SAFE_READ SAFE_READ
#define SIGNATURE_MIN_SIZE
Definition: mspatcha_main.c:32
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
USHORT ReadUShort(PSAFE_READ pRead)
Definition: mspatcha_main.c:78
BOOL WINAPI TestApplyPatchToFileW(LPCWSTR patch_file, LPCWSTR old_file, ULONG apply_flags)
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)
struct _PATCH_HEADER PATCH_HEADER
BOOL WINAPI GetFilePatchSignatureA(LPCSTR filename, 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 WINAPI TestApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, ULONG apply_flags)
DWORD DecodeDWord(PSAFE_READ pRead)
DWORD CreateNewFileFromPatch(PATCH_HEADER *Header, SAFE_READ *Patch, HANDLE new_file)
DWORD ReadDWord(PSAFE_READ pRead)
Definition: mspatcha_main.c:99
BOOL WINAPI ApplyPatchToFileW(LPCWSTR patch_file, LPCWSTR old_file, LPCWSTR new_file, ULONG apply_flags)
DWORD ParseHeader(SAFE_READ *Patch, PATCH_HEADER *Header)
INT DecodeInt(PSAFE_READ pRead)
BYTE ReadByte(PSAFE_READ pRead)
Definition: mspatcha_main.c:57
#define UNKNOWN_FLAGS_COMBINATION
Definition: mspatcha_main.c:34
struct _SAFE_READ * PSAFE_READ
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define GENERIC_WRITE
Definition: nt_native.h:90
#define ERROR_PATCH_NOT_AVAILABLE
Definition: patchapi.h:40
#define ERROR_PATCH_WRONG_FILE
Definition: patchapi.h:38
#define ERROR_PATCH_DECODE_FAILURE
Definition: patchapi.h:35
#define ERROR_PATCH_CORRUPT
Definition: patchapi.h:36
#define APPLY_OPTION_TEST_ONLY
Definition: patchapi.h:28
WORD * PWORD
Definition: pedump.c:67
BYTE * PBYTE
Definition: pedump.c:66
DWORD * PDWORD
Definition: pedump.c:68
unsigned short USHORT
Definition: pedump.c:61
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
#define INT
Definition: polytest.cpp:20
DWORD dwStatus
Definition: mediaobj.idl:95
PVOID pBuffer
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE(s)
Definition: solgame.cpp:4
DWORD ImageTimeStamp
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
int32_t INT
Definition: typedefs.h:58
uint16_t * PUSHORT
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
int ret
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define ZeroMemory
Definition: winbase.h:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FILE_MAP_WRITE
Definition: winbase.h:154
#define WINAPI
Definition: msvc.h:6
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
static ULONG Delta
Definition: xboxvideo.c:33
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193