mspatcha_main.c 10.1 KB
Newer Older
David Hedberg's avatar
David Hedberg committed
1 2 3 4
/*
 * PatchAPI
 *
 * Copyright 2011 David Hedberg for CodeWeavers
5
 * Copyright 2019 Conor McCarthy (implementations)
David Hedberg's avatar
David Hedberg committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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
20 21 22 23 24 25 26 27 28 29
 *
 * 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.
David Hedberg's avatar
David Hedberg committed
30 31 32 33 34 35
 */

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
36 37
#include "winnls.h"
#include "patchapi.h"
David Hedberg's avatar
David Hedberg committed
38 39
#include "wine/debug.h"

40 41
#include "pa19.h"

David Hedberg's avatar
David Hedberg committed
42 43 44
WINE_DEFAULT_DEBUG_CHANNEL(mspatcha);


45
static WCHAR *strdupAW(const char *src)
46 47 48 49
{
    WCHAR *dst = NULL;
    if (src)
    {
50 51 52
        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);
53 54 55 56 57
    }
    return dst;
}

/*****************************************************
58
 *    TestApplyPatchToFileA (MSPATCHA.@)
59
 */
60
BOOL WINAPI TestApplyPatchToFileA(LPCSTR patch_file, LPCSTR old_file, ULONG apply_flags)
61 62
{
    BOOL ret;
63
    WCHAR *patch_fileW, *old_fileW = NULL;
64

65 66
    if (!(patch_fileW = strdupAW(patch_file))) return FALSE;
    if (old_file && !(old_fileW = strdupAW(old_file)))
67
    {
68
        HeapFree(GetProcessHeap(), 0, patch_fileW);
69 70
        return FALSE;
    }
71 72 73
    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);
74 75 76
    return ret;
}

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
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;
}

David Hedberg's avatar
David Hedberg committed
107
/*****************************************************
108
 *    ApplyPatchToFileExA (MSPATCHA.@)
David Hedberg's avatar
David Hedberg committed
109
 */
110 111
BOOL WINAPI ApplyPatchToFileExA(LPCSTR patch_file, LPCSTR old_file, LPCSTR new_file, ULONG apply_flags,
    PPATCH_PROGRESS_CALLBACK progress_fn, PVOID progress_ctx)
David Hedberg's avatar
David Hedberg committed
112
{
113 114 115 116 117 118 119
    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;
David Hedberg's avatar
David Hedberg committed
120

121 122 123 124 125 126 127 128 129 130
    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;
David Hedberg's avatar
David Hedberg committed
131
}
132 133

/*****************************************************
134
 *    ApplyPatchToFileA (MSPATCHA.@)
135
 */
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
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)
179
{
180 181
    return apply_patch_to_file_by_handles(patch_file_hndl, old_file_hndl, new_file_hndl,
        apply_option_flags, progress_fn, progress_ctx, FALSE);
182 183 184
}

/*****************************************************
185
 *    ApplyPatchToFileByBuffers (MSPATCHA.@)
186
 */
187 188 189 190 191 192
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)
193
{
194 195 196 197 198 199 200 201 202 203 204 205
    /* 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;
206
}
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272

/*****************************************************
 *    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;
}