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:
kichik 2004-09-07 19:50:13 +00:00
parent 776eb349c0
commit eb0e1fa14d
2 changed files with 198 additions and 195 deletions

View file

@ -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.