' ########################################################################################
' Microsoft Windows
' File: PatchApi.inc
' Contents: Interface for creating and applying patches to files
' Copyright (c) 2011 Jos? Roca
' Portions Copyright (c) Microsoft Corporation.
' All Rights Reserved.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#IF NOT %DEF(PBX_PatchApi_PBI)
#DEFINE PBX_PatchApi_PBI
%EQUATE `PATCHAPI_INC = 1
#INCLUDE ONCE "Core/Windows.inc"
'//
'// The following constants can be combined and used as the OptionFlags
'// parameter in the patch creation apis.
'//
%EQUATE `PATCH_OPTION_USE_BEST = &H00000000 ' // auto choose best (slower)
%EQUATE `PATCH_OPTION_USE_LZX_BEST = &H00000003 ' // auto choose best of LZX A/B (but not large)
%EQUATE `PATCH_OPTION_USE_LZX_A = &H00000001 ' // normal
%EQUATE `PATCH_OPTION_USE_LZX_B = &H00000002 ' // better on some x86 binaries
%EQUATE `PATCH_OPTION_USE_LZX_LARGE = &H00000004 ' // better support for large files (requires 5.1 or higher applyer)
%EQUATE `PATCH_OPTION_NO_BINDFIX = &H00010000 ' // PE bound imports
%EQUATE `PATCH_OPTION_NO_LOCKFIX = &H00020000 ' // PE smashed locks
%EQUATE `PATCH_OPTION_NO_REBASE = &H00040000 ' // PE rebased image
%EQUATE `PATCH_OPTION_FAIL_IF_SAME_FILE = &H00080000 ' // don't create if same
%EQUATE `PATCH_OPTION_FAIL_IF_BIGGER = &H00100000 ' // fail if patch is larger than simply compressing new file (slower)
%EQUATE `PATCH_OPTION_NO_CHECKSUM = &H00200000 ' // PE checksum zero
%EQUATE `PATCH_OPTION_NO_RESTIMEFIX = &H00400000 ' // PE resource timestamps
%EQUATE `PATCH_OPTION_NO_TIMESTAMP = &H00800000 ' // don't store new file timestamp in patch
%EQUATE `PATCH_OPTION_SIGNATURE_MD5 = &H01000000 ' // use MD5 instead of CRC (reserved for future support)
%EQUATE `PATCH_OPTION_INTERLEAVE_FILES = &H40000000 ' // better support for large files (requires 5.2 or higher applyer)
%EQUATE `PATCH_OPTION_RESERVED1 = &H80000000 ' // (used internally)
%EQUATE `PATCH_OPTION_VALID_FLAGS = &HC0FF0007
' //
' // The following flags are used with PATCH_OPTION_DATA SymbolOptionFlags:
' //
%EQUATE `PATCH_SYMBOL_NO_IMAGEHLP = &H00000001 ' // don't use imagehlp.dll
%EQUATE `PATCH_SYMBOL_NO_FAILURES = &H00000002 ' // don't fail patch due to imagehlp failures
%EQUATE `PATCH_SYMBOL_UNDECORATED_TOO = &H00000004 ' // after matching decorated symbols, try to match remaining by undecorated names
%EQUATE `PATCH_SYMBOL_RESERVED1 = &H80000000 ' // (used internally)
' //
' // The following flags are used with PATCH_OPTION_DATA ExtendedOptionFlags:
' //
%EQUATE `PATCH_TRANSFORM_PE_RESOURCE_2 = &H00000100 ' // better handling of PE resources (requires 5.2 or higher applyer)
%EQUATE `PATCH_TRANSFORM_PE_IRELOC_2 = &H00000200 ' // better handling of PE stripped relocs (requires 5.2 or higher applyer)
' //
' // The following constants can be combined and used as the ApplyOptionFlags
' // parameter in the patch apply and test apis.
' //
%EQUATE `APPLY_OPTION_FAIL_IF_EXACT = &H00000001 ' // don't copy new file
%EQUATE `APPLY_OPTION_FAIL_IF_CLOSE = &H00000002 ' // differ by rebase, bind
%EQUATE `APPLY_OPTION_TEST_ONLY = &H00000004 ' // don't create new file
%EQUATE `APPLY_OPTION_VALID_FLAGS = &H00000007
' //
' // In addition to standard Win32 error codes, the following error codes may
' // be returned via GetLastError() when one of the patch APIs fails.
' //
%EQUATE `ERROR_PATCH_ENCODE_FAILURE = &HC00E3101 ' // create
%EQUATE `ERROR_PATCH_INVALID_OPTIONS = &HC00E3102 ' // create
%EQUATE `ERROR_PATCH_SAME_FILE = &HC00E3103 ' // create
%EQUATE `ERROR_PATCH_RETAIN_RANGES_DIFFER = &HC00E3104 ' // create
%EQUATE `ERROR_PATCH_BIGGER_THAN_COMPRESSED = &HC00E3105 ' // create
%EQUATE `ERROR_PATCH_IMAGEHLP_FAILURE = &HC00E3106 ' // create
%EQUATE `ERROR_PATCH_DECODE_FAILURE = &HC00E4101 ' // apply
%EQUATE `ERROR_PATCH_CORRUPT = &HC00E4102 ' // apply
%EQUATE `ERROR_PATCH_NEWER_FORMAT = &HC00E4103 ' // apply
%EQUATE `ERROR_PATCH_WRONG_FILE = &HC00E4104 ' // apply
%EQUATE `ERROR_PATCH_NOT_NECESSARY = &HC00E4105 ' // apply
%EQUATE `ERROR_PATCH_NOT_AVAILABLE = &HC00E4106 ' // apply
'typedef BOOL (CALLBACK PATCH_PROGRESS_CALLBACK)(
' PVOID CallbackContext,
' ULONG CurrentPosition,
' ULONG MaximumPosition
' );
'typedef PATCH_PROGRESS_CALLBACK *PPATCH_PROGRESS_CALLBACK;
'FUNCTION PATCH_PROGRESS_CALLBACK ( ' BYVAL CallbackContext AS DWORD ' , BYVAL CurrentPosition AS DWORD ' , BYVAL MaximumPosition AS DWORD ' ) AS LONG
'typedef BOOL (CALLBACK PATCH_SYMLOAD_CALLBACK)(
' IN ULONG WhichFile, ' // 0 for new file, 1 for first old file, etc
' IN LPCSTR SymbolFileName,
' IN ULONG SymType, ' // see SYM_TYPE in imagehlp.h
' IN ULONG SymbolFileCheckSum,
' IN ULONG SymbolFileTimeDate,
' IN ULONG ImageFileCheckSum,
' IN ULONG ImageFileTimeDate,
' IN PVOID CallbackContext
' );
'typedef PATCH_SYMLOAD_CALLBACK *PPATCH_SYMLOAD_CALLBACK;
'FUNCTION PATCH_SYMLOAD_CALLBACK ( ' BYVAL WhichFile AS DWORD ' , BYREF SymbolFileName AS ASCIIZ ' , BYVAL SymType AS DWORD ' , BYVAL SymbolFileCheckSum AS DWORD ' , BYVAL SymbolFileTimeDate AS DWORD ' , BYVAL ImageFileCheckSum AS DWORD ' , BYVAL ImageFileTimeDate AS DWORD ' , BYVAL CallbackContext AS DWORD ' ) AS LONG
' // Size = 8 bytes
TYPE PATCH_IGNORE_RANGE DWORD
 OffsetInOldFile AS DWORD ' ULONG
 LengthInBytes AS DWORD ' ULONG
END TYPE
' // Size = 12 bytes
TYPE PATCH_RETAIN_RANGE DWORD
 OffsetInOldFile AS DWORD ' ULONG
 LengthInBytes AS DWORD ' ULONG
 OffsetInNewFile AS DWORD ' ULONG
END TYPE
' // Size = 24 bytes
TYPE PATCH_OLD_FILE_INFO_A DWORD
 SizeOfThisStruct AS DWORD ' ULONG
 OldFileName AS ASCIIZ PTR
 IgnoreRangeCount AS DWORD ' ULONG // maximum 255
 IgnoreRangeArray AS PATCH_IGNORE_RANGE PTR ' PPATCH_IGNORE_RANGE
 RetainRangeCount AS DWORD ' ULONG // maximum 255
 RetainRangeArray AS PATCH_RETAIN_RANGE PTR ' PPATCH_RETAIN_RANGE
END TYPE
MACRO PATCH_OLD_FILE_INFO = PATCH_OLD_FILE_INFO_A
' // Size = 24 bytes
TYPE PATCH_OLD_FILE_INFO_W DWORD
 SizeOfThisStruct AS DWORD ' ULONG
 OldFileName AS WSTRINGZ PTR
 IgnoreRangeCount AS DWORD ' ULONG // maximum 255
 IgnoreRangeArray AS PATCH_IGNORE_RANGE PTR ' PPATCH_IGNORE_RANGE
 RetainRangeCount AS DWORD ' ULONG // maximum 255
 RetainRangeArray AS PATCH_RETAIN_RANGE PTR ' PPATCH_RETAIN_RANGE
END TYPE
' // Size = 24 bytes
TYPE PATCH_OLD_FILE_INFO_H DWORD
 SizeOfThisStruct AS DWORD ' ULONG
 OldFileHandle AS DWORD
 IgnoreRangeCount AS DWORD ' ULONG // maximum 255
 IgnoreRangeArray AS PATCH_IGNORE_RANGE PTR ' PPATCH_IGNORE_RANGE
 RetainRangeCount AS DWORD ' ULONG // maximum 255
 RetainRangeArray AS PATCH_RETAIN_RANGE PTR ' PPATCH_RETAIN_RANGE
END TYPE
' // Size = 12 bytes
TYPE PATCH_INTERLEAVE_MAP_RANGE DWORD
 OldOffset AS DWORD ' ULONG
 OldLength AS DWORD ' ULONG
 NewLength AS DWORD ' ULONG // NewOffset implied by sum of previous NewLengths
END TYPE
' // Size = 16 bytes
TYPE PATCH_INTERLEAVE_MAP DWORD
 CountRanges AS DWORD ' ULONG
 Range(0) AS PATCH_INTERLEAVE_MAP_RANGE ' // Variable length (CountRanges)
END TYPE
' // Size = 36 bytes
TYPE PATCH_OPTION_DATA DWORD
 SizeOfThisStruct AS DWORD ' ULONG
 SymbolOptionFlags AS DWORD ' ULONG // PATCH_SYMBOL_xxx flags
 NewFileSymbolPath AS ASCIIZ PTR ' LPCSTR // always ANSI, never Unicode
 OldFileSymbolPathArray AS ASCIIZ PTR ' LPCSTR* // array[ OldFileCount ]
 ExtendedOptionFlags AS DWORD ' ULONG
 SymLoadCallback AS DWORD ' PPATCH_SYMLOAD_CALLBACK
 SymLoadContext AS DWORD
 InterleaveMapArray AS PATCH_INTERLEAVE_MAP PTR ' PPATCH_INTERLEAVE_MAP* // array[ OldFileCount ] (requires 5.2 or higher applyer)
 MaxLzxWindowSize AS DWORD ' ULONG // limit memory requirements (requires 5.2 or higher applyer)
END TYPE
' //
' // Note that PATCH_OPTION_DATA contains LPCSTR paths, and no LPCWSTR (Unicode)
' // path argument is available, even when used with one of the Unicode APIs
' // such as CreatePatchFileW. This is because the underlying system services
' // for symbol file handling (IMAGEHLP.DLL) only support ANSI file/path names.
' //
' //
' // A note about PATCH_RETAIN_RANGE specifiers with multiple old files:
' //
' // Each old version file must have the same RetainRangeCount, and the same
' // retain range LengthInBytes and OffsetInNewFile values in the same order.
' // Only the OffsetInOldFile values can differ between old files for retain
' // ranges.
' //
' //
' // The following prototypes are interface for creating patches from files.
' //
DECLARE FUNCTION CreatePatchFileA LIB "mspatchc.dll" ALIAS "CreatePatchFileA" ( BYREF OldFileName AS ASCIIZ , BYREF NewFileName AS ASCIIZ , BYREF PatchFileName AS ASCIIZ , BYVAL OptionFlags AS QUAD , BYREF PATCH_OPTION_DATA ) AS LONG
DECLARE FUNCTION CreatePatchFileW LIB "mspatchc.dll" ALIAS "CreatePatchFileW" ( BYREF OldFileName AS WSTRINGZ
 , BYREF NewFileName AS WSTRINGZ
 , BYREF PatchFileName AS WSTRINGZ
 , BYVAL OptionFlags AS DWORD
 , BYREF OptionData AS PATCH_OPTION_DATA
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO CreatePatchFile = CreatePatchFileW
#ELSE
 MACRO CreatePatchFile = CreatePatchFileA
#ENDIF
DECLARE FUNCTION CreatePatchFileByHandles LIB "mspatchc.dll" ALIAS "CreatePatchFileByHandles" ( BYVAL OldFileHandle AS QUAD , BYVAL NewFileHandle AS QUAD , BYVAL PatchFileHandle AS QUAD , BYVAL OptionFlags AS QUAD , BYREF OptionData AS PATCH_OPTION_DATA ) AS LONG
DECLARE FUNCTION CreatePatchFileExA LIB "mspatchc.dll" ALIAS "CreatePatchFileExA" ( BYVAL OldFileCount AS QUAD
 , BYREF OldFileInfoArray AS PATCH_OLD_FILE_INFO_A
 , BYREF NewFileName AS ASCIIZ
 , BYREF PatchFileName AS ASCIIZ
 , BYVAL OptionFlags AS DWORD
 , BYREF OptionData AS PATCH_OPTION_DATA
 , BYVAL ProgressCallback AS DWORD
 , BYVAL CallbackContext AS DWORD
 ) AS LONG
DECLARE FUNCTION CreatePatchFileExW LIB "mspatchc.dll" ALIAS "CreatePatchFileExW" ( BYVAL OldFileCount AS DWORD
 , BYREF OldFileInfoArray AS PATCH_OLD_FILE_INFO_W
 , BYREF NewFileName AS WSTRINGZ
 , BYREF PatchFileName AS WSTRINGZ
 , BYVAL OptionFlags AS DWORD
 , BYREF OptionData AS PATCH_OPTION_DATA
 , BYVAL ProgressCallback AS DWORD
 , BYVAL CallbackContext AS DWORD
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO CreatePatchFileEx = CreatePatchFileExW
#ELSE
 MACRO CreatePatchFileEx = CreatePatchFileExA
#ENDIF
DECLARE FUNCTION CreatePatchFileByHandlesEx LIB "mspatchc.dll" ALIAS "CreatePatchFileByHandlesEx" ( BYVAL OldFileCount AS QUAD , BYREF OldFileInfoArray AS PATCH_OLD_FILE_INFO_H , BYVAL NewFileHandle AS QUAD , BYVAL PatchFileHandle AS QUAD , BYVAL OptionFlags AS QUAD , BYREF OptionData AS PATCH_OPTION_DATA , BYVAL ProgressCallback AS QUAD , BYVAL CallbackContext AS QUAD ) AS LONG
DECLARE FUNCTION ExtractPatchHeaderToFileA LIB "mspatchc.dll" ALIAS "ExtractPatchHeaderToFileA" ( BYREF PatchFileName AS ASCIIZ
 , BYREF PatchHeaderFileName AS ASCIIZ
 ) AS LONG
DECLARE FUNCTION ExtractPatchHeaderToFileW LIB "mspatchc.dll" ALIAS "ExtractPatchHeaderToFileW" ( BYREF PatchFileName AS WSTRINGZ
 , BYREF PatchHeaderFileName AS WSTRINGZ
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO ExtractPatchHeaderToFile = ExtractPatchHeaderToFileW
#ELSE
 MACRO ExtractPatchHeaderToFile = ExtractPatchHeaderToFileA
#ENDIF
DECLARE FUNCTION ExtractPatchHeaderToFileByHandles LIB "mspatchc.dll" ALIAS "ExtractPatchHeaderToFileByHandles" ( BYVAL PatchFileHandle AS QUAD , BYVAL PatchHeaderFileHandle AS QUAD ) AS LONG
' //
' // The following prototypes are interface for creating new file from old file
' // and patch file. Note that it is possible for the TestApply API to succeed
' // but the actual Apply to fail since the TestApply only verifies that the
' // old file has the correct CRC without actually applying the patch. The
' // TestApply API only requires the patch header portion of the patch file,
' // but its CRC must be corrected.
' //
DECLARE FUNCTION TestApplyPatchToFileA LIB "mspatcha.dll" ALIAS "TestApplyPatchToFileA" ( BYREF PatchFileName AS ASCIIZ , BYREF OldFileName AS ASCIIZ , BYVAL ApplyOptionFlags AS QUAD ) AS LONG
DECLARE FUNCTION TestApplyPatchToFileW LIB "mspatcha.dll" ALIAS "TestApplyPatchToFileW" ( BYREF PatchFileName AS WSTRINGZ
 , BYREF OldFileName AS WSTRINGZ
 , BYVAL ApplyOptionFlags AS DWORD
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO TestApplyPatchToFile = TestApplyPatchToFileW
#ELSE
 MACRO TestApplyPatchToFile = TestApplyPatchToFileA
#ENDIF
DECLARE FUNCTION TestApplyPatchToFileByHandles LIB "mspatcha.dll" ALIAS "TestApplyPatchToFileByHandles" ( BYVAL PatchFileHandle AS QUAD , BYVAL OldFileHandle AS QUAD , BYVAL ApplyOptionFlags AS QUAD ) AS LONG
DECLARE FUNCTION TestApplyPatchToFileByBuffers LIB "mspatcha.dll" ALIAS "TestApplyPatchToFileByBuffers" ( BYVAL PatchFileBuffer AS BYTE PTR
 , BYVAL PatchFileSize AS DWORD
 , BYVAL OldFileBuffer AS BYTE PTR
 , BYVAL OldFileSize AS DWORD
 , BYREF NewFileSize AS DWORD
 , BYVAL ApplyOptionFlags As DWORD
 ) AS LONG
DECLARE FUNCTION ApplyPatchToFileA LIB "mspatcha.dll" ALIAS "ApplyPatchToFileA" ( BYREF PatchFileName AS ASCIIZ
 , BYREF OldFileName AS ASCIIZ
 , BYREF NewFileName AS ASCIIZ
 , BYVAL ApplyOptionFlags AS DWORD
 ) AS LONG
DECLARE FUNCTION ApplyPatchToFileW LIB "mspatcha.dll" ALIAS "ApplyPatchToFileW" ( BYREF PatchFileName AS WSTRINGZ
 , BYREF OldFileName AS WSTRINGZ
 , BYREF NewFileName AS WSTRINGZ
 , BYVAL ApplyOptionFlags AS DWORD
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO ApplyPatchToFile = ApplyPatchToFileW
#ELSE
 MACRO ApplyPatchToFile = ApplyPatchToFileA
#ENDIF
DECLARE FUNCTION ApplyPatchToFileByHandles LIB "mspatcha.dll" ALIAS "ApplyPatchToFileByHandles" ( BYVAL PatchFileHandle AS QUAD , BYVAL OldFileHandle AS QUAD , BYVAL NewFileHandle AS QUAD , BYVAL ApplyOptionFlags AS QUAD ) AS LONG
DECLARE FUNCTION ApplyPatchToFileExA LIB "mspatcha.dll" ALIAS "ApplyPatchToFileExA" ( BYREF PatchFileName AS ASCIIZ
 , BYREF OldFileName AS ASCIIZ
 , BYREF NewFileName AS ASCIIZ
 , BYVAL ApplyOptionFlags AS DWORD
 , BYVAL ProgressCallback AS DWORD
 , BYVAL CallbackContext AS DWORD
 ) AS LONG
DECLARE FUNCTION ApplyPatchToFileExW LIB "mspatcha.dll" ALIAS "ApplyPatchToFileExW" ( BYVAL PatchFileName AS DWORD
 , BYVAL OldFileName AS DWORD
 , BYVAL NewFileName AS DWORD
 , BYVAL ApplyOptionFlags AS DWORD
 , BYVAL ProgressCallback AS DWORD
 , BYVAL CallbackContext AS DWORD
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO ApplyPatchToFileEx = ApplyPatchToFileExW
#ELSE
 MACRO ApplyPatchToFileEx = ApplyPatchToFileExA
#ENDIF
DECLARE FUNCTION ApplyPatchToFileByHandlesEx LIB "mspatcha.dll" ALIAS "ApplyPatchToFileByHandlesEx" ( BYVAL PatchFileHandle AS QUAD , BYVAL OldFileHandle AS QUAD , BYVAL NewFileHandle AS QUAD , BYVAL ApplyOptionFlags AS QUAD , BYVAL ProgressCallback AS QUAD , BYVAL CallbackContext AS QUAD ) AS LONG
DECLARE FUNCTION ApplyPatchToFileByBuffers LIB "mspatcha.dll" ALIAS "ApplyPatchToFileByBuffers" ( BYVAL PatchFileMapped AS BYTE PTR
 , BYVAL PatchFileSize AS DWORD
 , BYVAL OldFileMapped AS BYTE PTR
 , BYVAL OldFileSize AS DWORD
 , BYVAL NewFileBuffer AS BYTE PTR
 , BYVAL NewFileBufferSize AS DWORD
 , BYREF NewFileActualSize AS DWORD
 , BYREF NewFileTime AS FILETIME
 , BYVAL ApplyOptionFlags AS DWORD
 , BYVAL ProgressCallback AS DWORD
 , BYVAL CallbackContext AS DWORD
 ) AS LONG
' //
' // If *NewFileBuffer is NULL, and APPLY_OPTION_TEST_ONLY is not specified,
' // and the function succeeds (returns TRUE), and size of new file is non-zero,
' // *NewFileBuffer will be set to a VirtualAlloc buffer of the required size,
' // and it will be the caller's responsibility to VirtualFree this buffer.
' // NewFileBufferSize is ignored when *NewFileBuffer is NULL.
' //
' // If *NewFileBuffer is non-NULL, and APPLY_OPTION_TEST_ONLY is not specified,
' // NewFileBufferSize specifies the size of caller-supplied *NewFileBuffer
' // buffer. If required size exceeds NewFileBufferSize, function will fail
' // (return FALSE), *NewFileActualSize will be set to required size, and
' // GetLastError will return ERROR_INSUFFICIENT_BUFFER.
' //
' // If ApplyOptionFlags APPLY_OPTION_TEST_ONLY is specified, NewFileBuffer
' // and NewFileBufferSize are ignored, and *NewFileActualSize will be set to
' // required buffer size. If APPLY_OPTION_TEST_ONLY is not specified, then
' // NewFileBuffer must be non-NULL (*NewFileBuffer may be NULL).
' //
' // NewFileTime is optional. If non-NULL, the value returned will either be
' // non-zero to indicate the new file time as specified in the patch, or zero
' // to indicate that file time was not stored inside the patch.
' //
' //
' // The following prototypes provide a unique patch "signature" for a given
' // file. Consider the case where you have a new foo.dll and the machines
' // to be updated with the new foo.dll may have one of three different old
' // foo.dll files. Rather than creating a single large patch file that can
' // update any of the three older foo.dll files, three separate smaller patch
' // files can be created and identified according to the patch signature of the
' // old file. Then the patch applyer application can determine at runtime
' // which of the three foo.dll patch files is necessary given the specific
' // foo.dll to be updated. If patch files are being downloaded over a slow
' // network connection (internet over a modem), this signature scheme provides
' // a mechanism for choosing the correct single patch file to download at
' // application time thus decreasing total bytes necessary to download.
' //
DECLARE FUNCTION GetFilePatchSignatureA LIB "mspatcha.dll" ALIAS "GetFilePatchSignatureA" ( BYREF FileName AS ASCIIZ , BYVAL OptionFlags AS QUAD , BYVAL OptionData AS QUAD , BYVAL IgnoreRangeCount AS QUAD , BYREF IgnoreRangeArray AS PATCH_IGNORE_RANGE , BYVAL RetainRangeCount AS QUAD , BYREF RetainRangeArray AS PATCH_RETAIN_RANGE , BYVAL SignatureBufferSize AS QUAD , BYREF SignatureBuffer AS ASCIIZ ) AS LONG
DECLARE FUNCTION GetFilePatchSignatureW LIB "mspatcha.dll" ALIAS "GetFilePatchSignatureW" ( BYREF FileName AS WSTRINGZ
 , BYVAL OptionFlags AS DWORD
 , BYVAL OptionData AS DWORD
 , BYVAL IgnoreRangeCount AS DWORD
 , BYREF IgnoreRangeArray AS PATCH_IGNORE_RANGE
 , BYVAL RetainRangeCount AS DWORD
 , BYREF RetainRangeArray AS PATCH_RETAIN_RANGE
 , BYVAL SignatureBufferSize AS DWORD
 , BYREF SignatureBuffer AS WSTRINGZ
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO GetFilePatchSignature = GetFilePatchSignatureW
#ELSE
 MACRO GetFilePatchSignature = GetFilePatchSignatureA
#ENDIF
DECLARE FUNCTION GetFilePatchSignatureByHandle LIB "mspatcha.dll" ALIAS "GetFilePatchSignatureByHandle" ( BYVAL FileHandle AS QUAD , BYVAL OptionFlags AS QUAD , BYVAL OptionData AS QUAD , BYVAL IgnoreRangeCount AS QUAD , BYREF IgnoreRangeArray AS PATCH_IGNORE_RANGE , BYVAL RetainRangeCount AS QUAD , BYREF RetainRangeArray AS PATCH_RETAIN_RANGE , BYVAL SignatureBufferSize AS QUAD , BYREF SignatureBuffer AS ASCIIZ ) AS LONG
DECLARE FUNCTION GetFilePatchSignatureByBuffer LIB "mspatcha.dll" ALIAS "GetFilePatchSignatureByBuffer" ( BYVAL FileBufferWritable AS BYTE PTR
 , BYVAL FileSize AS DWORD
 , BYVAL OptionFlags AS DWORD
 , BYVAL OptionData AS DWORD
 , BYVAL IgnoreRangeCount AS DWORD
 , BYREF IgnoreRangeArray AS PATCH_IGNORE_RANGE
 , BYVAL RetainRangeCount AS DWORD
 , BYREF RetainRangeArray AS PATCH_RETAIN_RANGE
 , BYVAL SignatureBufferSize AS DWORD
 , BYREF SignatureBuffer AS ASCIIZ
 ) AS LONG
' //
' // As an alternative to requesting the signature, some applications might use
' // NormalizeFileForPatchSignature to render a stream that can be hashed
' // by other means than CRC or MD5 provided by the signature APIs. This API
' // returns 0 for failure (GetLastError returns additional info), 1 to indicate
' // the buffer did not require any modifications for normalization, or 2 to
' // indicate that the buffer was modified in the process of normalization.
' //
DECLARE FUNCTION NormalizeFileForPatchSignature LIB "mspatcha.dll" ALIAS "NormalizeFileForPatchSignature" ( BYVAL FileBuffer AS QUAD , BYVAL FileSize AS QUAD , BYVAL OptionFlags AS QUAD , BYREF OptionData AS PATCH_OPTION_DATA , BYVAL NewFileCoffBase AS QUAD , BYVAL NewFileCoffTime AS QUAD , BYVAL IgnoreRangeCount AS QUAD , BYREF IgnoreRangeArray AS PATCH_IGNORE_RANGE , BYVAL RetainRangeCount AS QUAD , BYREF RetainRangeArray AS PATCH_RETAIN_RANGE ) AS LONG ' INT
#ENDIF
