mirror of
https://github.com/reactos/reactos.git
synced 2024-07-03 03:04:22 +00:00
290 lines
9.8 KiB
C
290 lines
9.8 KiB
C
/*
|
|
* PatchAPI
|
|
*
|
|
* Copyright 2011 David Hedberg for CodeWeavers
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#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);
|
|
|
|
/*****************************************************
|
|
* DllMain (MSPATCHA.@)
|
|
*/
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|
{
|
|
TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
|
|
|
|
switch (fdwReason)
|
|
{
|
|
case DLL_WINE_PREATTACH:
|
|
return FALSE; /* prefer native version */
|
|
case DLL_PROCESS_ATTACH:
|
|
DisableThreadLibraryCalls(hinstDLL);
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*****************************************************
|
|
* ApplyPatchToFileA (MSPATCHA.1)
|
|
*/
|
|
BOOL WINAPI ApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, LPCSTR new_file, ULONG apply_flags)
|
|
{
|
|
BOOL ret = FALSE;
|
|
HANDLE hPatch, hOld, hNew;
|
|
|
|
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)
|
|
{
|
|
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);
|
|
}
|
|
|
|
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)
|
|
{
|
|
BOOL ret = FALSE;
|
|
HANDLE hPatch, hOld, hNew;
|
|
|
|
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;
|
|
}
|
|
|
|
/*****************************************************
|
|
* GetFilePatchSignatureA (MSPATCHA.7)
|
|
*/
|
|
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 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;
|
|
}
|
|
|
|
/*****************************************************
|
|
* GetFilePatchSignatureW (MSPATCHA.9)
|
|
*/
|
|
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)
|
|
{
|
|
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;
|
|
}
|