wine-wine/dlls/mspatcha/mspatcha_main.c

291 lines
11 KiB
C

/*
* PatchAPI
*
* Copyright 2011 David Hedberg for CodeWeavers
* Copyright 2019 Conor McCarthy (implementations)
*
* 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
*
* TODO
* - Special processing of 32-bit executables is not supported, so this
* version cannot patch 32-bit .exe and .dll files. See pa19.c for details.
* - Implement interleaved decoding when PATCH_OPTION_INTERLEAVE_FILES was
* used or the old file exceeds the lzxd window size.
* - APPLY_OPTION_FAIL_IF_CLOSE is ignored. Normalization of 32-bit PE files
* is required for checking this.
* - GetFilePatchSignature* and NormalizeFileForPatchSignature require a
* solution to the above 32-bit exe problem.
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "patchapi.h"
#include "wine/debug.h"
#include "pa19.h"
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;
}
static 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;
}
/*****************************************************
* TestApplyPatchToFileA (MSPATCHA.@)
*/
BOOL WINAPI TestApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, ULONG apply_flags)
{
BOOL ret;
WCHAR *patch_fileW, *old_fileW = NULL;
if (!(patch_fileW = strdupAW(patch_file))) return FALSE;
if (old_file && !(old_fileW = strdupAW(old_file)))
{
HeapFree(GetProcessHeap(), 0, patch_fileW);
return FALSE;
}
ret = apply_patch_to_file(patch_fileW, old_fileW, NULL, apply_flags, NULL, NULL, TRUE);
HeapFree(GetProcessHeap(), 0, patch_fileW);
HeapFree(GetProcessHeap(), 0, old_fileW);
return ret;
}
BOOL WINAPI TestApplyPatchToFileW(LPCWSTR patch_file_name, LPCWSTR old_file_name, ULONG apply_option_flags)
{
return apply_patch_to_file(patch_file_name, old_file_name, NULL, apply_option_flags, NULL, NULL, TRUE);
}
BOOL WINAPI TestApplyPatchToFileByHandles(HANDLE patch_file_hndl, HANDLE old_file_hndl, ULONG apply_option_flags)
{
return apply_patch_to_file_by_handles(patch_file_hndl, old_file_hndl, NULL,
apply_option_flags, NULL, NULL, TRUE);
}
BOOL WINAPI TestApplyPatchToFileByBuffers(BYTE *patch_file_buf, ULONG patch_file_size,
BYTE *old_file_buf, ULONG old_file_size,
ULONG* new_file_size,
ULONG apply_option_flags)
{
/* NOTE: windows preserves last error on success for this function, but no apps are known to depend on it */
DWORD err = apply_patch_to_file_by_buffers(patch_file_buf, patch_file_size,
old_file_buf, old_file_size,
NULL, 0, new_file_size, NULL,
apply_option_flags,
NULL, NULL,
TRUE);
SetLastError(err);
return err == ERROR_SUCCESS;
}
/*****************************************************
* ApplyPatchToFileExA (MSPATCHA.@)
*/
BOOL WINAPI ApplyPatchToFileExA(LPCSTR patch_file, LPCSTR old_file, LPCSTR new_file, ULONG apply_flags,
PPATCH_PROGRESS_CALLBACK progress_fn, PVOID progress_ctx)
{
BOOL ret = FALSE;
WCHAR *patch_fileW, *new_fileW, *old_fileW = NULL;
if (!(patch_fileW = strdupAW(patch_file))) return FALSE;
if (old_file && !(old_fileW = strdupAW(old_file)))
goto free_wstrs;
if (!(new_fileW = strdupAW(new_file)))
goto free_wstrs;
ret = apply_patch_to_file(patch_fileW, old_fileW, new_fileW, apply_flags, progress_fn, progress_ctx, FALSE);
HeapFree(GetProcessHeap(), 0, new_fileW);
free_wstrs:
HeapFree(GetProcessHeap(), 0, patch_fileW);
HeapFree(GetProcessHeap(), 0, old_fileW);
return ret;
}
/*****************************************************
* ApplyPatchToFileA (MSPATCHA.@)
*/
BOOL WINAPI ApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, LPCSTR new_file, ULONG apply_flags)
{
return ApplyPatchToFileExA(patch_file, old_file, new_file, apply_flags, NULL, NULL);
}
/*****************************************************
* ApplyPatchToFileW (MSPATCHA.@)
*/
BOOL WINAPI ApplyPatchToFileW(LPCWSTR patch_file_name, LPCWSTR old_file_name, LPCWSTR new_file_name,
ULONG apply_option_flags)
{
return apply_patch_to_file(patch_file_name, old_file_name, new_file_name, apply_option_flags,
NULL, NULL, FALSE);
}
/*****************************************************
* ApplyPatchToFileByHandles (MSPATCHA.@)
*/
BOOL WINAPI ApplyPatchToFileByHandles(HANDLE patch_file_hndl, HANDLE old_file_hndl, HANDLE new_file_hndl,
ULONG apply_option_flags)
{
return apply_patch_to_file_by_handles(patch_file_hndl, old_file_hndl, new_file_hndl,
apply_option_flags, NULL, NULL, FALSE);
}
/*****************************************************
* ApplyPatchToFileExW (MSPATCHA.@)
*/
BOOL WINAPI ApplyPatchToFileExW(LPCWSTR patch_file_name, LPCWSTR old_file_name, LPCWSTR new_file_name,
ULONG apply_option_flags,
PPATCH_PROGRESS_CALLBACK progress_fn, PVOID progress_ctx)
{
return apply_patch_to_file(patch_file_name, old_file_name, new_file_name, apply_option_flags,
progress_fn, progress_ctx, FALSE);
}
/*****************************************************
* ApplyPatchToFileByHandlesEx (MSPATCHA.@)
*/
BOOL WINAPI ApplyPatchToFileByHandlesEx(HANDLE patch_file_hndl, HANDLE old_file_hndl, HANDLE new_file_hndl,
ULONG apply_option_flags,
PPATCH_PROGRESS_CALLBACK progress_fn,
PVOID progress_ctx)
{
return apply_patch_to_file_by_handles(patch_file_hndl, old_file_hndl, new_file_hndl,
apply_option_flags, progress_fn, progress_ctx, FALSE);
}
/*****************************************************
* ApplyPatchToFileByBuffers (MSPATCHA.@)
*/
BOOL WINAPI ApplyPatchToFileByBuffers(PBYTE patch_file_view, ULONG patch_file_size,
PBYTE old_file_view, ULONG old_file_size,
PBYTE* new_file_buf, ULONG new_file_buf_size, ULONG* new_file_size,
FILETIME* new_file_time,
ULONG apply_option_flags,
PPATCH_PROGRESS_CALLBACK progress_fn, PVOID progress_ctx)
{
/* NOTE: windows preserves last error on success for this function, but no apps are known to depend on it */
DWORD err = apply_patch_to_file_by_buffers(patch_file_view, patch_file_size,
old_file_view, old_file_size,
new_file_buf, new_file_buf_size, new_file_size, new_file_time,
apply_option_flags,
progress_fn, progress_ctx,
FALSE);
SetLastError(err);
return err == ERROR_SUCCESS;
}
/*****************************************************
* GetFilePatchSignatureA (MSPATCHA.@)
*/
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, LPSTR 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;
}
/*****************************************************
* GetFilePatchSignatureW (MSPATCHA.@)
*/
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, LPWSTR 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;
}
/*****************************************************
* GetFilePatchSignatureByHandle (MSPATCHA.@)
*/
BOOL WINAPI GetFilePatchSignatureByHandle(HANDLE handle, ULONG flags, PVOID options, ULONG ignore_range_count,
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,
ignore_range_count, ignore_range, retain_range_count, retain_range, bufsize, buffer);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*****************************************************
* GetFilePatchSignatureByBuffer (MSPATCHA.@)
*/
BOOL WINAPI GetFilePatchSignatureByBuffer(PBYTE file_buf, ULONG file_size, ULONG flags, PVOID options,
ULONG ignore_range_count, PPATCH_IGNORE_RANGE ignore_range,
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,
ignore_range_count, ignore_range, retain_range_count, retain_range, bufsize, buffer);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*****************************************************
* NormalizeFileForPatchSignature (MSPATCHA.@)
*/
INT WINAPI NormalizeFileForPatchSignature(PVOID file_buffer, ULONG file_size, ULONG flags, PATCH_OPTION_DATA *options,
ULONG new_coff_base, ULONG new_coff_time, ULONG ignore_range_count, PPATCH_IGNORE_RANGE ignore_range,
ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range)
{
FIXME("stub - %p, %u, %x, %p, %u, %u, %u, %p, %u, %p\n", file_buffer, file_size, flags, options, new_coff_base,
new_coff_time, ignore_range_count, ignore_range, retain_range_count, retain_range);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}