close all open file handles when one of them fail to open
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3649 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
776eb349c0
commit
eb0e1fa14d
2 changed files with 198 additions and 195 deletions
|
@ -6,14 +6,14 @@ int DoPatch(HANDLE hPatch, HANDLE hSource, HANDLE hDest);
|
||||||
void strcopy(char *tgt, const char *src);
|
void strcopy(char *tgt, const char *src);
|
||||||
char* chop_arg(char **args);
|
char* chop_arg(char **args);
|
||||||
|
|
||||||
#define PATCH_SUCCESS 0
|
#define PATCH_SUCCESS 0
|
||||||
#define PATCH_ERROR 1
|
#define PATCH_ERROR 1
|
||||||
#define PATCH_CORRUPT 2
|
#define PATCH_CORRUPT 2
|
||||||
#define PATCH_NOMATCH 3
|
#define PATCH_NOMATCH 3
|
||||||
#define PATCH_UPTODATE 4
|
#define PATCH_UPTODATE 4
|
||||||
#define FILE_ERR_PATCH 5
|
#define FILE_ERR_PATCH 5
|
||||||
#define FILE_ERR_SOURCE 6
|
#define FILE_ERR_SOURCE 6
|
||||||
#define FILE_ERR_DEST 7
|
#define FILE_ERR_DEST 7
|
||||||
|
|
||||||
HINSTANCE g_hInstance;
|
HINSTANCE g_hInstance;
|
||||||
|
|
||||||
|
@ -36,58 +36,61 @@ void __declspec(dllexport) vpatchfile(HWND hwndParent, int string_size,
|
||||||
|
|
||||||
// do your stuff here
|
// do your stuff here
|
||||||
{
|
{
|
||||||
static char source[1024];
|
static char source[1024];
|
||||||
static char dest[1024];
|
static char dest[1024];
|
||||||
static char exename[1024];
|
static char exename[1024];
|
||||||
HANDLE hPatch, hSource, hDest;
|
HANDLE hPatch, hSource, hDest;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
popstring(exename);
|
popstring(exename);
|
||||||
popstring(source);
|
popstring(source);
|
||||||
popstring(dest);
|
popstring(dest);
|
||||||
|
|
||||||
hPatch = CreateFile(exename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
hPatch = CreateFile(exename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
if (hPatch == INVALID_HANDLE_VALUE) {
|
if (hPatch == INVALID_HANDLE_VALUE) {
|
||||||
pushstring("Unable to open patch file");
|
pushstring("Unable to open patch file");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hSource = CreateFile(source, GENERIC_READ, FILE_SHARE_READ, NULL,
|
hSource = CreateFile(source, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
if (hSource == INVALID_HANDLE_VALUE) {
|
if (hSource == INVALID_HANDLE_VALUE) {
|
||||||
pushstring("Unable to open source file");
|
CloseHandle(hPatch);
|
||||||
return;
|
pushstring("Unable to open source file");
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
hDest = CreateFile(dest, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
|
||||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
hDest = CreateFile(dest, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||||
if (hDest == INVALID_HANDLE_VALUE) {
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
pushstring("Unable to open output file");
|
if (hDest == INVALID_HANDLE_VALUE) {
|
||||||
return;
|
CloseHandle(hPatch);
|
||||||
}
|
CloseHandle(hSource);
|
||||||
|
pushstring("Unable to open output file");
|
||||||
result = DoPatch(hPatch, hSource, hDest);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = DoPatch(hPatch, hSource, hDest);
|
||||||
|
|
||||||
CloseHandle(hDest);
|
CloseHandle(hDest);
|
||||||
CloseHandle(hSource);
|
CloseHandle(hSource);
|
||||||
CloseHandle(hPatch);
|
CloseHandle(hPatch);
|
||||||
|
|
||||||
if ((result != PATCH_SUCCESS)) {
|
if ((result != PATCH_SUCCESS)) {
|
||||||
if (result == PATCH_ERROR)
|
if (result == PATCH_ERROR)
|
||||||
pushstring("An error occured while patching");
|
pushstring("An error occured while patching");
|
||||||
else if (result == PATCH_CORRUPT)
|
else if (result == PATCH_CORRUPT)
|
||||||
pushstring("Patch data is invalid or corrupt");
|
pushstring("Patch data is invalid or corrupt");
|
||||||
else if (result == PATCH_NOMATCH)
|
else if (result == PATCH_NOMATCH)
|
||||||
pushstring("No suitable patches were found");
|
pushstring("No suitable patches were found");
|
||||||
else if (result == PATCH_UPTODATE)
|
else if (result == PATCH_UPTODATE)
|
||||||
pushstring("OK, new version already installed");
|
pushstring("OK, new version already installed");
|
||||||
DeleteFile(dest);
|
DeleteFile(dest);
|
||||||
} else {
|
} else {
|
||||||
pushstring("OK");
|
pushstring("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +99,7 @@ void __declspec(dllexport) vpatchfile(HWND hwndParent, int string_size,
|
||||||
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
||||||
{
|
{
|
||||||
g_hInstance=hInst;
|
g_hInstance=hInst;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,169 +108,169 @@ UINT CRCTable[256];
|
||||||
BOOL bInitCRC = FALSE;
|
BOOL bInitCRC = FALSE;
|
||||||
|
|
||||||
_inline void InitCRC() {
|
_inline void InitCRC() {
|
||||||
int i, j; unsigned long c;
|
int i, j; unsigned long c;
|
||||||
for (c = i = 0; i < 256; c = ++i) {
|
for (c = i = 0; i < 256; c = ++i) {
|
||||||
for (j = 0; j < 8; j++) {
|
for (j = 0; j < 8; j++) {
|
||||||
if (c & 1) c = (c>>1) ^ 0xEDB88320;
|
if (c & 1) c = (c>>1) ^ 0xEDB88320;
|
||||||
else c >>= 1;
|
else c >>= 1;
|
||||||
}
|
}
|
||||||
CRCTable[i] = c;
|
CRCTable[i] = c;
|
||||||
}
|
}
|
||||||
bInitCRC = TRUE;
|
bInitCRC = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CRCBLOCKSIZE 4096
|
#define CRCBLOCKSIZE 4096
|
||||||
|
|
||||||
BOOL FileCRC(HANDLE hFile, DWORD *crc) {
|
BOOL FileCRC(HANDLE hFile, DWORD *crc) {
|
||||||
static BYTE crcblock[CRCBLOCKSIZE];
|
static BYTE crcblock[CRCBLOCKSIZE];
|
||||||
DWORD read;
|
DWORD read;
|
||||||
BYTE *p;
|
BYTE *p;
|
||||||
|
|
||||||
UINT c = 0xFFFFFFFF;
|
UINT c = 0xFFFFFFFF;
|
||||||
if (bInitCRC == FALSE)
|
if (bInitCRC == FALSE)
|
||||||
InitCRC();
|
InitCRC();
|
||||||
|
|
||||||
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
|
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
|
||||||
do {
|
do {
|
||||||
if (ReadFile(hFile, crcblock, CRCBLOCKSIZE, &read, NULL) == FALSE)
|
if (ReadFile(hFile, crcblock, CRCBLOCKSIZE, &read, NULL) == FALSE)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
for (p = crcblock; p < crcblock + read; p++)
|
for (p = crcblock; p < crcblock + read; p++)
|
||||||
c = CRCTable[(c & 0xFF) ^ *p] ^ (c >> 8);
|
c = CRCTable[(c & 0xFF) ^ *p] ^ (c >> 8);
|
||||||
} while (read);
|
} while (read);
|
||||||
|
|
||||||
*crc = (c ^ 0xFFFFFFFF);
|
|
||||||
|
|
||||||
return TRUE;
|
*crc = (c ^ 0xFFFFFFFF);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BLOCKSIZE 16384
|
#define BLOCKSIZE 16384
|
||||||
|
|
||||||
int DoPatch(HANDLE hPatch, HANDLE hSource, HANDLE hDest) {
|
int DoPatch(HANDLE hPatch, HANDLE hSource, HANDLE hDest) {
|
||||||
|
|
||||||
static char block[BLOCKSIZE];
|
static char block[BLOCKSIZE];
|
||||||
|
|
||||||
unsigned long temp = 0;
|
unsigned long temp = 0;
|
||||||
unsigned long read;
|
unsigned long read;
|
||||||
unsigned long source_crc = 0;
|
unsigned long source_crc = 0;
|
||||||
unsigned long patch_dest_crc = 0;
|
unsigned long patch_dest_crc = 0;
|
||||||
long patches = 0;
|
long patches = 0;
|
||||||
int already_uptodate = 0;
|
int already_uptodate = 0;
|
||||||
// special 'addition' for the dll: since the patch file is now
|
// special 'addition' for the dll: since the patch file is now
|
||||||
// in a seperate file, the VPAT header might be right at the start
|
// in a seperate file, the VPAT header might be right at the start
|
||||||
// of the file, and a pointer at the end of the file is probably missing
|
// of the file, and a pointer at the end of the file is probably missing
|
||||||
// (because all patch generator versions don't append it, the linker/gui
|
// (because all patch generator versions don't append it, the linker/gui
|
||||||
// does this).
|
// does this).
|
||||||
SetFilePointer(hPatch, 0, NULL, FILE_BEGIN);
|
SetFilePointer(hPatch, 0, NULL, FILE_BEGIN);
|
||||||
ReadFile(hPatch, &temp, 4, &read, NULL);
|
ReadFile(hPatch, &temp, 4, &read, NULL);
|
||||||
// it's not at the start of file -> there must be a pointer at the end of
|
// it's not at the start of file -> there must be a pointer at the end of
|
||||||
// file then
|
// file then
|
||||||
if (temp != 0x54415056) {
|
if (temp != 0x54415056) {
|
||||||
SetFilePointer(hPatch, -4, NULL, FILE_END);
|
SetFilePointer(hPatch, -4, NULL, FILE_END);
|
||||||
ReadFile(hPatch, &temp, 4, &read, NULL);
|
ReadFile(hPatch, &temp, 4, &read, NULL);
|
||||||
|
|
||||||
SetFilePointer(hPatch, temp, NULL, FILE_BEGIN);
|
SetFilePointer(hPatch, temp, NULL, FILE_BEGIN);
|
||||||
ReadFile(hPatch, &temp, 4, &read, NULL);
|
ReadFile(hPatch, &temp, 4, &read, NULL);
|
||||||
if (temp != 0x54415056)
|
if (temp != 0x54415056)
|
||||||
return PATCH_CORRUPT;
|
return PATCH_CORRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FileCRC(hSource, &source_crc))
|
||||||
|
return PATCH_ERROR;
|
||||||
|
|
||||||
|
|
||||||
|
ReadFile(hPatch, &patches, 4, &read, NULL);
|
||||||
|
|
||||||
|
while (patches--) {
|
||||||
|
long patch_blocks = 0, patch_size = 0;
|
||||||
|
unsigned long patch_source_crc = 0;
|
||||||
|
|
||||||
|
ReadFile(hPatch, &patch_blocks, 4, &read, NULL);
|
||||||
|
ReadFile(hPatch, &patch_source_crc, 4, &read, NULL);
|
||||||
|
ReadFile(hPatch, &patch_dest_crc, 4, &read, NULL);
|
||||||
|
ReadFile(hPatch, &patch_size, 4, &read, NULL);
|
||||||
|
|
||||||
|
//added by Koen - check to see if it's already up-to-date for some patch (so
|
||||||
|
//we can tell NSIS this isn't an error, but we already have the latest version)
|
||||||
|
if (source_crc == patch_dest_crc) {
|
||||||
|
already_uptodate = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FileCRC(hSource, &source_crc))
|
if (source_crc == patch_source_crc) {
|
||||||
return PATCH_ERROR;
|
while (patch_blocks--) {
|
||||||
|
unsigned char blocktype = 0;
|
||||||
|
unsigned long blocksize = 0;
|
||||||
|
ReadFile(hPatch, &blocktype, 1, &read, NULL);
|
||||||
|
|
||||||
|
switch (blocktype) {
|
||||||
ReadFile(hPatch, &patches, 4, &read, NULL);
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
if (blocktype == 1)
|
||||||
|
{ unsigned char x; blocksize = ReadFile(hPatch,&x,1,&read,NULL)? x:0; }
|
||||||
|
else if (blocktype == 2)
|
||||||
|
{ unsigned short x; blocksize = ReadFile(hPatch,&x,2,&read,NULL)? x:0; }
|
||||||
|
else
|
||||||
|
{ unsigned long x; blocksize = ReadFile(hPatch,&x,4,&read,NULL)? x:0; }
|
||||||
|
|
||||||
while (patches--) {
|
if (!blocksize || !ReadFile(hPatch, &temp, 4, &read, NULL) || read != 4)
|
||||||
long patch_blocks = 0, patch_size = 0;
|
return PATCH_CORRUPT;
|
||||||
unsigned long patch_source_crc = 0;
|
|
||||||
|
|
||||||
ReadFile(hPatch, &patch_blocks, 4, &read, NULL);
|
|
||||||
ReadFile(hPatch, &patch_source_crc, 4, &read, NULL);
|
|
||||||
ReadFile(hPatch, &patch_dest_crc, 4, &read, NULL);
|
|
||||||
ReadFile(hPatch, &patch_size, 4, &read, NULL);
|
|
||||||
|
|
||||||
//added by Koen - check to see if it's already up-to-date for some patch (so
|
SetFilePointer(hSource, temp, 0, FILE_BEGIN);
|
||||||
//we can tell NSIS this isn't an error, but we already have the latest version)
|
|
||||||
if (source_crc == patch_dest_crc) {
|
|
||||||
already_uptodate = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source_crc == patch_source_crc) {
|
do {
|
||||||
while (patch_blocks--) {
|
ReadFile(hSource, block, min(BLOCKSIZE, blocksize), &read, NULL);
|
||||||
unsigned char blocktype = 0;
|
WriteFile(hDest, block, read, &temp, NULL);
|
||||||
unsigned long blocksize = 0;
|
if (temp != min(BLOCKSIZE, blocksize))
|
||||||
ReadFile(hPatch, &blocktype, 1, &read, NULL);
|
return PATCH_ERROR;
|
||||||
|
blocksize -= temp;
|
||||||
|
} while (temp);
|
||||||
|
|
||||||
switch (blocktype) {
|
break;
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
if (blocktype == 1)
|
|
||||||
{ unsigned char x; blocksize = ReadFile(hPatch,&x,1,&read,NULL)? x:0; }
|
|
||||||
else if (blocktype == 2)
|
|
||||||
{ unsigned short x; blocksize = ReadFile(hPatch,&x,2,&read,NULL)? x:0; }
|
|
||||||
else
|
|
||||||
{ unsigned long x; blocksize = ReadFile(hPatch,&x,4,&read,NULL)? x:0; }
|
|
||||||
|
|
||||||
if (!blocksize || !ReadFile(hPatch, &temp, 4, &read, NULL) || read != 4)
|
case 5:
|
||||||
return PATCH_CORRUPT;
|
case 6:
|
||||||
|
case 7:
|
||||||
SetFilePointer(hSource, temp, 0, FILE_BEGIN);
|
if (blocktype == 5)
|
||||||
|
{ unsigned char x; blocksize = ReadFile(hPatch,&x,1,&read,NULL)? x:0; }
|
||||||
|
else if (blocktype == 6)
|
||||||
|
{ unsigned short x; blocksize = ReadFile(hPatch,&x,2,&read,NULL)? x:0; }
|
||||||
|
else
|
||||||
|
{ unsigned long x; blocksize = ReadFile(hPatch,&x,4,&read,NULL)? x:0; }
|
||||||
|
|
||||||
do {
|
if (!blocksize)
|
||||||
ReadFile(hSource, block, min(BLOCKSIZE, blocksize), &read, NULL);
|
return PATCH_CORRUPT;
|
||||||
WriteFile(hDest, block, read, &temp, NULL);
|
|
||||||
if (temp != min(BLOCKSIZE, blocksize))
|
do {
|
||||||
return PATCH_ERROR;
|
ReadFile(hPatch, block, min(BLOCKSIZE, blocksize), &read, NULL);
|
||||||
blocksize -= temp;
|
WriteFile(hDest, block, read, &temp, NULL);
|
||||||
} while (temp);
|
if (temp != min(BLOCKSIZE, blocksize))
|
||||||
|
return PATCH_ERROR;
|
||||||
|
blocksize -= temp;
|
||||||
|
} while (temp);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
default:
|
||||||
case 6:
|
return PATCH_CORRUPT;
|
||||||
case 7:
|
}
|
||||||
if (blocktype == 5)
|
}
|
||||||
{ unsigned char x; blocksize = ReadFile(hPatch,&x,1,&read,NULL)? x:0; }
|
{
|
||||||
else if (blocktype == 6)
|
unsigned long dest_crc = 0;
|
||||||
{ unsigned short x; blocksize = ReadFile(hPatch,&x,2,&read,NULL)? x:0; }
|
FileCRC(hDest, &dest_crc);
|
||||||
else
|
if (dest_crc != patch_dest_crc)
|
||||||
{ unsigned long x; blocksize = ReadFile(hPatch,&x,4,&read,NULL)? x:0; }
|
return PATCH_ERROR;
|
||||||
|
|
||||||
if (!blocksize)
|
return PATCH_SUCCESS;
|
||||||
return PATCH_CORRUPT;
|
}
|
||||||
|
} else {
|
||||||
do {
|
SetFilePointer(hPatch, patch_size, NULL, FILE_CURRENT);
|
||||||
ReadFile(hPatch, block, min(BLOCKSIZE, blocksize), &read, NULL);
|
}
|
||||||
WriteFile(hDest, block, read, &temp, NULL);
|
}
|
||||||
if (temp != min(BLOCKSIZE, blocksize))
|
|
||||||
return PATCH_ERROR;
|
//added by Koen - if already up to date, it doesn't matter that we didn't match
|
||||||
blocksize -= temp;
|
if(already_uptodate) {
|
||||||
} while (temp);
|
return PATCH_UPTODATE;
|
||||||
|
} else {
|
||||||
break;
|
return PATCH_NOMATCH;
|
||||||
|
}
|
||||||
default:
|
|
||||||
return PATCH_CORRUPT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
unsigned long dest_crc = 0;
|
|
||||||
FileCRC(hDest, &dest_crc);
|
|
||||||
if (dest_crc != patch_dest_crc)
|
|
||||||
return PATCH_ERROR;
|
|
||||||
|
|
||||||
return PATCH_SUCCESS;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SetFilePointer(hPatch, patch_size, NULL, FILE_CURRENT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//added by Koen - if already up to date, it doesn't matter that we didn't match
|
|
||||||
if(already_uptodate) {
|
|
||||||
return PATCH_UPTODATE;
|
|
||||||
} else {
|
|
||||||
return PATCH_NOMATCH;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue