home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 March / CMCD0304.ISO / Software / Freeware / Programare / nullsoft / nsis20.exe / Contrib / VPatch / Source / Plugin / vpatchdll.c next >
C/C++ Source or Header  |  2003-11-12  |  7KB  |  274 lines

  1. #define WIN32_LEAN_AND_MEAN
  2. #include <windows.h>
  3. #include "..\..\..\ExDLL\exdll.h"
  4.  
  5. int DoPatch(HANDLE hPatch, HANDLE hSource, HANDLE hDest);
  6. void strcopy(char *tgt, const char *src);
  7. char* chop_arg(char **args);
  8.  
  9. #define PATCH_SUCCESS    0
  10. #define PATCH_ERROR        1
  11. #define PATCH_CORRUPT    2
  12. #define PATCH_NOMATCH    3
  13. #define PATCH_UPTODATE    4
  14. #define FILE_ERR_PATCH    5
  15. #define FILE_ERR_SOURCE    6
  16. #define FILE_ERR_DEST    7
  17.  
  18. HINSTANCE g_hInstance;
  19.  
  20. HWND g_hwndParent;
  21.  
  22. void __declspec(dllexport) vpatchfile(HWND hwndParent, int string_size, 
  23.                                       char *variables, stack_t **stacktop)
  24. {
  25.   g_hwndParent=hwndParent;
  26.  
  27.   EXDLL_INIT();
  28.  
  29.  
  30.   // note if you want parameters from the stack, pop them off in order.
  31.   // i.e. if you are called via exdll::myFunction file.dat poop.dat
  32.   // calling popstring() the first time would give you file.dat,
  33.   // and the second time would give you poop.dat. 
  34.   // you should empty the stack of your parameters, and ONLY your
  35.   // parameters.
  36.  
  37.   // do your stuff here
  38.   {
  39.       static char source[1024];
  40.     static char dest[1024];
  41.     static char exename[1024];
  42.     HANDLE hPatch, hSource, hDest;
  43.     int result;
  44.  
  45.     popstring(exename);
  46.     popstring(source);
  47.     popstring(dest);
  48.  
  49.     hPatch = CreateFile(exename, GENERIC_READ, FILE_SHARE_READ, NULL,
  50.                                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  51.     if (hPatch == INVALID_HANDLE_VALUE) {
  52.         pushstring("Unable to open patch file");
  53.         return;
  54.     }
  55.  
  56.     hSource = CreateFile(source, GENERIC_READ, FILE_SHARE_READ, NULL,
  57.                                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  58.     if (hSource == INVALID_HANDLE_VALUE) {
  59.         pushstring("Unable to open source file");
  60.         return;
  61.     }
  62.     
  63.     hDest = CreateFile(dest, GENERIC_READ | GENERIC_WRITE, 0, NULL,
  64.                                     CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  65.     if (hDest == INVALID_HANDLE_VALUE) {
  66.         pushstring("Unable to open output file");
  67.         return;
  68.     }
  69.         
  70.     result = DoPatch(hPatch, hSource, hDest);
  71.  
  72.     CloseHandle(hDest);
  73.     CloseHandle(hSource);
  74.     CloseHandle(hPatch);
  75.  
  76.     if ((result != PATCH_SUCCESS)) {
  77.         if (result == PATCH_ERROR)
  78.             pushstring("An error occured while patching");
  79.         else if (result == PATCH_CORRUPT)
  80.             pushstring("Patch data is invalid or corrupt");
  81.         else if (result == PATCH_NOMATCH)
  82.             pushstring("No suitable patches were found");
  83.         else if (result == PATCH_UPTODATE)
  84.             pushstring("OK, new version already installed");
  85.         DeleteFile(dest);
  86.     } else {
  87.         pushstring("OK");
  88.     }
  89.     
  90.     return;
  91.   }
  92. }
  93.  
  94.  
  95.  
  96. BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
  97. {
  98.   g_hInstance=hInst;
  99.     return TRUE;
  100. }
  101.  
  102.  
  103.  
  104. UINT CRCTable[256];
  105. BOOL bInitCRC = FALSE;
  106.  
  107. _inline void InitCRC() {
  108.     int i, j; unsigned long c;
  109.     for (c = i = 0; i < 256; c = ++i) {
  110.         for (j = 0; j < 8; j++) {
  111.             if (c & 1)    c = (c>>1) ^ 0xEDB88320;
  112.             else        c >>= 1;
  113.         }
  114.         CRCTable[i] = c;
  115.     }
  116.     bInitCRC = TRUE;
  117. }
  118.  
  119. #define CRCBLOCKSIZE    4096
  120.  
  121. BOOL FileCRC(HANDLE hFile, DWORD *crc) {
  122.     static BYTE crcblock[CRCBLOCKSIZE];
  123.     DWORD read;
  124.     BYTE *p;
  125.  
  126.     UINT c = 0xFFFFFFFF;
  127.     if (bInitCRC == FALSE)
  128.         InitCRC();
  129.   
  130.     SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
  131.     do {
  132.         if (ReadFile(hFile, crcblock, CRCBLOCKSIZE, &read, NULL) == FALSE)
  133.             return FALSE;
  134.         for (p = crcblock; p < crcblock + read; p++)
  135.             c = CRCTable[(c & 0xFF) ^ *p] ^ (c >> 8);
  136.     } while (read);
  137.     
  138.     *crc = (c ^ 0xFFFFFFFF);
  139.  
  140.     return TRUE;
  141. }
  142.  
  143. #define BLOCKSIZE    16384
  144.  
  145. int DoPatch(HANDLE hPatch, HANDLE hSource, HANDLE hDest) {
  146.  
  147.     static char block[BLOCKSIZE];
  148.     
  149.     unsigned long temp = 0;
  150.     unsigned long read;
  151.     unsigned long source_crc = 0;
  152.     unsigned long patch_dest_crc = 0;
  153.     long patches = 0;
  154.     int already_uptodate = 0;
  155.     // special 'addition' for the dll: since the patch file is now
  156.     // in a seperate file, the VPAT header might be right at the start
  157.     // of the file, and a pointer at the end of the file is probably missing
  158.     // (because all patch generator versions don't append it, the linker/gui
  159.     //  does this).
  160.     SetFilePointer(hPatch, 0, NULL, FILE_BEGIN);
  161.     ReadFile(hPatch, &temp, 4, &read, NULL);
  162.     // it's not at the start of file -> there must be a pointer at the end of
  163.     // file then
  164.     if (temp != 0x54415056) {
  165.         SetFilePointer(hPatch, -4, NULL, FILE_END);
  166.         ReadFile(hPatch, &temp, 4, &read, NULL);
  167.     
  168.         SetFilePointer(hPatch, temp, NULL, FILE_BEGIN);
  169.         ReadFile(hPatch, &temp, 4, &read, NULL);
  170.         if (temp != 0x54415056)
  171.             return PATCH_CORRUPT;
  172.     }
  173.  
  174.     if (!FileCRC(hSource, &source_crc))
  175.         return PATCH_ERROR;
  176.  
  177.     
  178.     ReadFile(hPatch, &patches, 4, &read, NULL);
  179.  
  180.     while (patches--) {
  181.         long patch_blocks = 0, patch_size = 0;
  182.         unsigned long patch_source_crc = 0;
  183.  
  184.         ReadFile(hPatch, &patch_blocks, 4, &read, NULL);
  185.         ReadFile(hPatch, &patch_source_crc, 4, &read, NULL);
  186.         ReadFile(hPatch, &patch_dest_crc, 4, &read, NULL);
  187.         ReadFile(hPatch, &patch_size, 4, &read, NULL);
  188.     
  189.         //added by Koen - check to see if it's already up-to-date for some patch (so
  190.         //we can tell NSIS this isn't an error, but we already have the latest version)
  191.         if (source_crc == patch_dest_crc) {
  192.             already_uptodate = 1;
  193.         }
  194.  
  195.         if (source_crc == patch_source_crc) {
  196.             while (patch_blocks--) {
  197.                 unsigned char blocktype = 0;
  198.                 unsigned long blocksize = 0;
  199.                 ReadFile(hPatch, &blocktype, 1, &read, NULL);
  200.  
  201.                 switch (blocktype) {
  202.                 case 1:
  203.                 case 2:
  204.                 case 3:
  205.                     if (blocktype == 1)
  206.                         { unsigned char x; blocksize = ReadFile(hPatch,&x,1,&read,NULL)? x:0; }
  207.                     else if (blocktype == 2)
  208.                         { unsigned short x; blocksize = ReadFile(hPatch,&x,2,&read,NULL)? x:0; }
  209.                     else
  210.                         { unsigned long x; blocksize = ReadFile(hPatch,&x,4,&read,NULL)? x:0; }
  211.  
  212.                     if (!blocksize || !ReadFile(hPatch, &temp, 4, &read, NULL) || read != 4)
  213.                         return PATCH_CORRUPT;
  214.     
  215.                     SetFilePointer(hSource, temp, 0, FILE_BEGIN);
  216.  
  217.                     do {
  218.                         ReadFile(hSource, block, min(BLOCKSIZE, blocksize), &read, NULL);
  219.                         WriteFile(hDest, block, read, &temp, NULL);
  220.                         if (temp != min(BLOCKSIZE, blocksize))
  221.                             return PATCH_ERROR;
  222.                         blocksize -= temp;
  223.                     } while (temp);
  224.  
  225.                     break;
  226.  
  227.                 case 5:
  228.                 case 6:
  229.                 case 7:
  230.                     if (blocktype == 5)
  231.                         { unsigned char x; blocksize = ReadFile(hPatch,&x,1,&read,NULL)? x:0; }
  232.                     else if (blocktype == 6)
  233.                         { unsigned short x; blocksize = ReadFile(hPatch,&x,2,&read,NULL)? x:0; }
  234.                     else
  235.                         { unsigned long x; blocksize = ReadFile(hPatch,&x,4,&read,NULL)? x:0; }
  236.  
  237.                     if (!blocksize)
  238.                         return PATCH_CORRUPT;
  239.                     
  240.                     do {
  241.                         ReadFile(hPatch, block, min(BLOCKSIZE, blocksize), &read, NULL);
  242.                         WriteFile(hDest, block, read, &temp, NULL);
  243.                         if (temp != min(BLOCKSIZE, blocksize))
  244.                             return PATCH_ERROR;
  245.                         blocksize -= temp;
  246.                     } while (temp);
  247.  
  248.                     break;
  249.  
  250.                 default:
  251.                     return PATCH_CORRUPT;
  252.                 }
  253.             }
  254.             {
  255.             unsigned long dest_crc = 0;
  256.             FileCRC(hDest, &dest_crc);
  257.             if (dest_crc != patch_dest_crc)
  258.                 return PATCH_ERROR;
  259.  
  260.             return PATCH_SUCCESS;
  261.             }
  262.         } else {
  263.             SetFilePointer(hPatch, patch_size, NULL, FILE_CURRENT);
  264.         }
  265.     }
  266.     
  267.     //added by Koen - if already up to date, it doesn't matter that we didn't match
  268.     if(already_uptodate) {
  269.       return PATCH_UPTODATE;    
  270.     } else {
  271.       return PATCH_NOMATCH;
  272.     }
  273. }
  274.