home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 March / CMCD0304.ISO / Software / Freeware / Programare / nullsoft / nsis20.exe / Source / exehead / fileform.c < prev    next >
C/C++ Source or Header  |  2004-01-30  |  15KB  |  555 lines

  1. #include "../Platform.h"
  2. #include "fileform.h"
  3. #include "util.h"
  4. #include "state.h"
  5. #include "resource.h"
  6. #include "lang.h"
  7. #include "ui.h"
  8. #include "exec.h"
  9.  
  10. #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
  11. #ifdef NSIS_COMPRESS_USE_ZLIB
  12. #include "../zlib/zlib.h"
  13. #endif
  14.  
  15. #ifdef NSIS_COMPRESS_USE_LZMA
  16. #include "../7zip/lzmaNSIS.h"
  17. #define z_stream CLZMAState
  18. #define inflateInit(x) lzmaInit(x)
  19. #define inflateReset(x) lzmaInit(x)
  20. #define inflate(x) lzmaDecompress(x)
  21. #define Z_OK 0
  22. #define Z_STREAM_END 1
  23. #endif
  24.  
  25. #ifdef NSIS_COMPRESS_USE_BZIP2
  26. #include "../bzip2/bzlib.h"
  27.  
  28. #define z_stream DState
  29. #define inflateInit(x) BZ2_bzDecompressInit(x)
  30. #define inflateReset(x) BZ2_bzDecompressInit(x)
  31.  
  32. #define inflate(x) BZ2_bzDecompress(x)
  33. #define Z_OK BZ_OK
  34. #define Z_STREAM_END BZ_STREAM_END
  35. #endif//NSIS_COMPRESS_USE_BZIP2
  36. #endif//NSIS_CONFIG_COMPRESSION_SUPPORT
  37.  
  38. struct block_header g_blocks[BLOCKS_NUM];
  39. header *g_header;
  40. int g_flags;
  41. int g_filehdrsize;
  42. int g_is_uninstaller;
  43.  
  44. HANDLE g_db_hFile;
  45.  
  46. #if defined(NSIS_CONFIG_COMPRESSION_SUPPORT) && defined(NSIS_COMPRESS_WHOLE)
  47. HANDLE dbd_hFile=INVALID_HANDLE_VALUE;
  48. static int dbd_size, dbd_pos, dbd_srcpos, dbd_fulllen;
  49. #endif//NSIS_COMPRESS_WHOLE
  50.  
  51. static int m_length;
  52. static int m_pos;
  53.  
  54. #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
  55. #if defined(NSIS_CONFIG_CRC_SUPPORT) || defined(NSIS_COMPRESS_WHOLE)
  56. BOOL CALLBACK verProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  57. {
  58.   static char *msg;
  59.   if (uMsg == WM_INITDIALOG)
  60.   {
  61.     SetTimer(hwndDlg,1,250,NULL);
  62.     msg = (char *) lParam;
  63.     uMsg = WM_TIMER;
  64.   }
  65.   if (uMsg == WM_TIMER
  66. #ifdef NSIS_COMPRESS_WHOLE
  67.     || (!msg && uMsg == WM_DESTROY)
  68. #endif
  69.     )
  70.   {
  71.     static char bt[64];
  72.     int percent=MulDiv(min(m_pos,m_length),100,m_length);
  73. #ifdef NSIS_COMPRESS_WHOLE
  74.     if (msg)
  75. #endif
  76.     {
  77.       wsprintf(bt,msg,percent);
  78.  
  79.       my_SetWindowText(hwndDlg,bt);
  80.       my_SetDialogItemText(hwndDlg,IDC_STR,bt);
  81.  
  82.       ShowWindow(hwndDlg, SW_SHOW);
  83.     }
  84.  
  85. #ifdef NSIS_COMPRESS_WHOLE
  86.     if (ui_st_updateflag & 1)
  87.     {
  88.       wsprintf(bt, "... %d%%", percent);
  89.       update_status_text(0, bt);
  90.     }
  91. #endif
  92.   }
  93.   return 0;
  94. }
  95. #endif//NSIS_CONFIG_CRC_SUPPORT || NSIS_COMPRESS_WHOLE
  96. #endif//NSIS_CONFIG_VISIBLE_SUPPORT
  97.  
  98. #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
  99. static z_stream g_inflate_stream;
  100. #endif
  101.  
  102. extern unsigned long NSISCALL CRC32(unsigned long crc, const unsigned char *buf, unsigned int len);
  103.  
  104. const char * NSISCALL loadHeaders(int cl_flags)
  105. {
  106. #ifdef NSIS_CONFIG_CRC_SUPPORT
  107. #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
  108.   HWND hwnd = 0;
  109.   unsigned int verify_time = GetTickCount() + 1000;
  110. #endif
  111.   int crc = 0;
  112.   int do_crc = 0;
  113. #endif//NSIS_CONFIG_CRC_SUPPORT
  114.   int left;
  115.  
  116.   void *data;
  117.   firstheader h;
  118.   header *header;
  119.  
  120.   HANDLE db_hFile;
  121.  
  122.   GetModuleFileName(g_hInstance, state_exe_directory, NSIS_MAX_STRLEN);
  123.  
  124.   g_db_hFile = db_hFile = myOpenFile(state_exe_directory, GENERIC_READ, OPEN_EXISTING);
  125.   if (db_hFile == INVALID_HANDLE_VALUE)
  126.   {
  127.     return _LANG_CANTOPENSELF;
  128.   }
  129.  
  130.   // make state_exe_directory point to dir, not full exe.
  131.  
  132.   trimslashtoend(state_exe_directory);
  133.  
  134.   left = m_length = GetFileSize(db_hFile,NULL);
  135.   while (left > 0)
  136.   {
  137.     static char temp[32768];
  138.     DWORD l = min(left, (g_filehdrsize ? 32768 : 512));
  139.     if (!ReadSelfFile(temp, l))
  140.     {
  141. #if defined(NSIS_CONFIG_CRC_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT)
  142.       if (hwnd) DestroyWindow(hwnd);
  143. #endif//NSIS_CONFIG_CRC_SUPPORT
  144.       return _LANG_INVALIDCRC;
  145.     }
  146.  
  147.     if (!g_filehdrsize)
  148.     {
  149.       mini_memcpy(&h, temp, sizeof(firstheader));
  150.       if (
  151.            (h.flags & (~FH_FLAGS_MASK)) == 0 &&
  152.            h.siginfo == FH_SIG &&
  153.            h.nsinst[2] == FH_INT3 &&
  154.            h.nsinst[1] == FH_INT2 &&
  155.            h.nsinst[0] == FH_INT1
  156.          )
  157.       {
  158.         if (h.length_of_all_following_data > left)
  159.           return _LANG_INVALIDCRC;
  160.  
  161.         g_filehdrsize = m_pos;
  162.  
  163. #if defined(NSIS_CONFIG_CRC_SUPPORT) || (defined(NSIS_CONFIG_SILENT_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT))
  164.         cl_flags |= h.flags;
  165. #endif
  166.  
  167. #ifdef NSIS_CONFIG_CRC_SUPPORT
  168.         if ((cl_flags & FH_FLAGS_FORCE_CRC) == 0)
  169.         {
  170.           if (cl_flags & FH_FLAGS_NO_CRC)
  171.             break;
  172.         }
  173.  
  174.         do_crc++;
  175.  
  176. #ifndef NSIS_CONFIG_CRC_ANAL
  177.         left = h.length_of_all_following_data - 4;
  178.         // end crc checking at crc :) this means you can tack shit on the end and it'll still work.
  179. #else //!NSIS_CONFIG_CRC_ANAL
  180.         left -= 4;
  181. #endif//NSIS_CONFIG_CRC_ANAL
  182.         // this is in case the end part is < 512 bytes.
  183.         if (l > (DWORD)left) l=(DWORD)left;
  184.  
  185. #else//!NSIS_CONFIG_CRC_SUPPORT
  186.         // no crc support, no need to keep on reading
  187.         break;
  188. #endif//!NSIS_CONFIG_CRC_SUPPORT
  189.       }
  190.     }
  191. #ifdef NSIS_CONFIG_CRC_SUPPORT
  192.  
  193. #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
  194.  
  195. #ifdef NSIS_CONFIG_SILENT_SUPPORT
  196.     else if ((cl_flags & FH_FLAGS_SILENT) == 0)
  197. #endif//NSIS_CONFIG_SILENT_SUPPORT
  198.     {
  199.       if (hwnd)
  200.       {
  201.         MSG msg;
  202.         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
  203.       }
  204.       else if (GetTickCount() > verify_time)
  205.         hwnd = CreateDialogParam(
  206.           g_hInstance,
  207.           MAKEINTRESOURCE(IDD_VERIFY),
  208.           0,
  209.           verProc,
  210.           (LPARAM)_LANG_VERIFYINGINST
  211.         );
  212.     }
  213. #endif//NSIS_CONFIG_VISIBLE_SUPPORT
  214.  
  215. #ifndef NSIS_CONFIG_CRC_ANAL
  216.     if (left < m_length)
  217. #endif//NSIS_CONFIG_CRC_ANAL
  218.       crc = CRC32(crc, temp, l);
  219.  
  220. #endif//NSIS_CONFIG_CRC_SUPPORT
  221.     m_pos += l;
  222.     left -= l;
  223.   }
  224. #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
  225. #ifdef NSIS_CONFIG_CRC_SUPPORT
  226.   if (hwnd)
  227.   {
  228.     DestroyWindow(hwnd);
  229.   }
  230. #endif//NSIS_CONFIG_CRC_SUPPORT
  231. #endif//NSIS_CONFIG_VISIBLE_SUPPORT
  232.   if (!g_filehdrsize)
  233.     return _LANG_INVALIDCRC;
  234.  
  235. #ifdef NSIS_CONFIG_CRC_SUPPORT
  236.   if (do_crc)
  237.   {
  238.     int fcrc;
  239.     SetSelfFilePointer(m_pos);
  240.     if (!ReadSelfFile(&fcrc, sizeof(int)) || crc != fcrc)
  241.       return _LANG_INVALIDCRC;
  242.   }
  243. #endif//NSIS_CONFIG_CRC_SUPPORT
  244.  
  245.   data = (void *)my_GlobalAlloc(h.length_of_header);
  246.  
  247. #ifdef NSIS_COMPRESS_WHOLE
  248.   inflateReset(&g_inflate_stream);
  249.  
  250.   {
  251.     char fno[MAX_PATH];
  252.     my_GetTempFileName(fno, state_temp_dir);
  253.     dbd_hFile=CreateFile(fno,GENERIC_WRITE|GENERIC_READ,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE,NULL);
  254.     if (dbd_hFile == INVALID_HANDLE_VALUE)
  255.       return _LANG_ERRORWRITINGTEMP;
  256.   }
  257.   dbd_srcpos = SetSelfFilePointer(g_filehdrsize + sizeof(firstheader));
  258. #ifdef NSIS_CONFIG_CRC_SUPPORT
  259.   dbd_fulllen = dbd_srcpos - sizeof(h) + h.length_of_all_following_data - ((cl_flags & FH_FLAGS_NO_CRC) ? 0 : sizeof(int));
  260. #else
  261.   dbd_fulllen = dbd_srcpos - sizeof(h) + h.length_of_all_following_data;
  262. #endif//NSIS_CONFIG_CRC_SUPPORT
  263. #else
  264.   SetSelfFilePointer(g_filehdrsize + sizeof(firstheader));
  265. #endif//NSIS_COMPRESS_WHOLE
  266.  
  267.   if (GetCompressedDataFromDataBlockToMemory(-1, data, h.length_of_header) != h.length_of_header)
  268.   {
  269.     GlobalFree((HGLOBAL)data);
  270.     return _LANG_INVALIDCRC;
  271.   }
  272.  
  273.   header = g_header = data;
  274.  
  275. #ifdef NSIS_CONFIG_SILENT_SUPPORT
  276.   if (cl_flags & FH_FLAGS_SILENT)
  277.     header->flags |= CH_FLAGS_SILENT;
  278.  
  279.   g_exec_flags.silent = header->flags & (CH_FLAGS_SILENT | CH_FLAGS_SILENT_LOG);
  280. #endif
  281.  
  282.   g_flags = header->flags;
  283.  
  284. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  285.   if (h.flags & FH_FLAGS_UNINSTALL)
  286.     g_is_uninstaller++;
  287. #endif
  288.  
  289.   // set offsets to real memory offsets rather than installer's header offset
  290.   left = BLOCKS_NUM;
  291.   while (left--)
  292.     header->blocks[left].offset += (int)data;
  293.  
  294. #ifdef NSIS_COMPRESS_WHOLE
  295.   header->blocks[NB_DATA].offset = dbd_pos;
  296. #else
  297.   header->blocks[NB_DATA].offset = SetFilePointer(db_hFile,0,NULL,FILE_CURRENT);
  298. #endif
  299.  
  300.   mini_memcpy(&g_blocks, &header->blocks, sizeof(g_blocks));
  301.  
  302.   return 0;
  303. }
  304.  
  305. #define IBUFSIZE 16384
  306. #define OBUFSIZE 32768
  307.  
  308. // returns -3 if compression error/eof/etc
  309.  
  310. #if !defined(NSIS_COMPRESS_WHOLE) || !defined(NSIS_CONFIG_COMPRESSION_SUPPORT)
  311.  
  312. int NSISCALL _dodecomp(int offset, HANDLE hFileOut, char *outbuf, int outbuflen)
  313. {
  314.   static char inbuffer[IBUFSIZE+OBUFSIZE];
  315.   char *outbuffer;
  316.   int outbuffer_len=outbuf?outbuflen:OBUFSIZE;
  317.   int retval=0;
  318.   int input_len;
  319.  
  320.   outbuffer = outbuf?outbuf:(inbuffer+IBUFSIZE);
  321.  
  322.   if (offset>=0)
  323.   {
  324.     SetSelfFilePointer(g_blocks[NB_DATA].offset+offset);
  325.   }
  326.  
  327.   if (!ReadSelfFile((LPVOID)&input_len,sizeof(int))) return -3;
  328.  
  329. #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
  330.   if (input_len & 0x80000000) // compressed
  331.   {
  332.     char progress[64];
  333.     int input_len_total;
  334.     DWORD ltc = GetTickCount(), tc;
  335.  
  336.     inflateReset(&g_inflate_stream);
  337.     input_len_total = input_len &= 0x7fffffff; // take off top bit.
  338.  
  339.     while (input_len > 0)
  340.     {
  341.       int l=min(input_len,IBUFSIZE);
  342.       int err;
  343.  
  344.       if (!ReadSelfFile((LPVOID)inbuffer,l))
  345.         return -3;
  346.  
  347.       g_inflate_stream.next_in = inbuffer;
  348.       g_inflate_stream.avail_in = l;
  349.       input_len-=l;
  350.  
  351.       for (;;)
  352.       {
  353.         int u;
  354.  
  355. #ifdef NSIS_COMPRESS_USE_LZMA
  356.         // lzma decompressor doesn't like to stay dry
  357.         if (!g_inflate_stream.avail_in && input_len)
  358.           break;
  359. #endif
  360.  
  361.         g_inflate_stream.next_out = outbuffer;
  362.         g_inflate_stream.avail_out = (unsigned int)outbuffer_len;
  363.  
  364.         err=inflate(&g_inflate_stream);
  365.  
  366.         if (err<0) return -4;
  367.  
  368.         u=(char*)g_inflate_stream.next_out - outbuffer;
  369.  
  370.         tc = GetTickCount();
  371.         if (ui_st_updateflag & 1 && (tc - ltc > 200 || !input_len))
  372.         {
  373.           wsprintf(progress, "... %d%%", MulDiv(input_len_total - input_len, 100, input_len_total));
  374.           update_status_text(0, progress);
  375.           ltc = tc;
  376.         }
  377.  
  378.         // if there's no output, more input is needed
  379.         if (!u)
  380.           break;
  381.  
  382.         if (!outbuf)
  383.         {
  384.           DWORD r;
  385.           if (!WriteFile(hFileOut,outbuffer,u,&r,NULL) || (int)r != u) return -2;
  386.           retval+=u;
  387.         }
  388.         else
  389.         {
  390.           retval+=u;
  391.           outbuffer_len-=u;
  392.           outbuffer=g_inflate_stream.next_out;
  393.           if (outbuffer_len < 1) return retval;
  394.         }
  395.         if (err==Z_STREAM_END) return retval;
  396.       }
  397.     }
  398.   }
  399.   else
  400. #endif//NSIS_CONFIG_COMPRESSION_SUPPORT
  401.   {
  402.     if (!outbuf)
  403.     {
  404.       while (input_len > 0)
  405.       {
  406.         DWORD l=min(input_len,outbuffer_len);
  407.         DWORD t;
  408.         if (!ReadSelfFile((LPVOID)inbuffer,l)) return -3;
  409.         if (!WriteFile(hFileOut,inbuffer,l,&t,NULL) || l!=t) return -2;
  410.         retval+=l;
  411.         input_len-=l;
  412.       }
  413.     }
  414.     else
  415.     {
  416.       int l=min(input_len,outbuflen);
  417.       if (!ReadSelfFile((LPVOID)outbuf,l)) return -3;
  418.       retval=l;
  419.     }
  420.   }
  421.   return retval;
  422. }
  423. #else//NSIS_COMPRESS_WHOLE
  424.  
  425. static char _inbuffer[IBUFSIZE];
  426. static char _outbuffer[OBUFSIZE];
  427. extern int m_length;
  428. extern int m_pos;
  429. extern BOOL CALLBACK verProc(HWND, UINT, WPARAM, LPARAM);
  430. extern BOOL CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);
  431. static int NSISCALL __ensuredata(int amount)
  432. {
  433.   HWND hwnd=NULL;
  434.   unsigned int verify_time=GetTickCount()+500;
  435.   int needed=amount-(dbd_size-dbd_pos);
  436.   if (needed>0)
  437.   {
  438.     SetSelfFilePointer(dbd_srcpos);
  439.     SetFilePointer(dbd_hFile,dbd_size,NULL,FILE_BEGIN);
  440.     m_length=needed;
  441.     m_pos=0;
  442.     for (;;)
  443.     {
  444.       int err;
  445.       int l=min(IBUFSIZE,dbd_fulllen-dbd_srcpos);
  446.       if (!ReadSelfFile((LPVOID)_inbuffer,l)) return -1;
  447.       dbd_srcpos+=l;
  448.       g_inflate_stream.next_in=_inbuffer;
  449.       g_inflate_stream.avail_in=l;
  450.       do
  451.       {
  452.         DWORD r,t;
  453. #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
  454.         if (g_header)
  455. #ifdef NSIS_CONFIG_SILENT_SUPPORT
  456.           if (!g_exec_flags.silent)
  457. #endif
  458.           {
  459.             if (hwnd) {
  460.               MSG msg;
  461.               m_pos=m_length-(amount-(dbd_size-dbd_pos));
  462.               while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) DispatchMessage(&msg);
  463.             }
  464.             else if (GetTickCount() > verify_time)
  465.               hwnd = CreateDialogParam(
  466.                 g_hInstance,
  467.                 MAKEINTRESOURCE(IDD_VERIFY),
  468.                 0,
  469.                 verProc,
  470.                 g_hwnd ? 0 : (LPARAM)_LANG_UNPACKING
  471.               );
  472.           }
  473. #endif//NSIS_CONFIG_VISIBLE_SUPPORT
  474.         g_inflate_stream.next_out=_outbuffer;
  475.         g_inflate_stream.avail_out=OBUFSIZE;
  476.         err=inflate(&g_inflate_stream);
  477.         if (err<0)
  478.         {
  479.           return -3;
  480.         }
  481.         r=g_inflate_stream.next_out-_outbuffer;
  482.         if (r)
  483.         {
  484.           if (!WriteFile(dbd_hFile,_outbuffer,r,&t,NULL) || r != t)
  485.           {
  486.             return -2;
  487.           }
  488.           dbd_size+=r;
  489.         }
  490.         else if (g_inflate_stream.avail_in || !l) return -3;
  491.         else break;
  492.       }
  493.       while (g_inflate_stream.avail_in);
  494.       if (amount-(dbd_size-dbd_pos) <= 0) break;
  495.     }
  496.     SetFilePointer(dbd_hFile,dbd_pos,NULL,FILE_BEGIN);
  497.   }
  498.   if (hwnd) DestroyWindow(hwnd);
  499.   return 0;
  500. }
  501.  
  502.  
  503. int NSISCALL _dodecomp(int offset, HANDLE hFileOut, char *outbuf, int outbuflen)
  504. {
  505.   DWORD r;
  506.   int input_len;
  507.   int retval;
  508.   if (offset>=0)
  509.   {
  510.     dbd_pos=g_blocks[NB_DATA].offset+offset;
  511.     SetFilePointer(dbd_hFile,dbd_pos,NULL,FILE_BEGIN);
  512.   }
  513.   retval=__ensuredata(sizeof(int));
  514.   if (retval<0) return retval;
  515.  
  516.   if (!ReadFile(dbd_hFile,(LPVOID)&input_len,sizeof(int),&r,NULL) || r!=sizeof(int)) return -3;
  517.   dbd_pos+=sizeof(int);
  518.  
  519.   retval=__ensuredata(input_len);
  520.   if (retval < 0) return retval;
  521.  
  522.   if (!outbuf)
  523.   {
  524.     while (input_len > 0)
  525.     {
  526.       DWORD t;
  527.       DWORD l=min(input_len,IBUFSIZE);
  528.       if (!ReadFile(dbd_hFile,(LPVOID)_inbuffer,l,&r,NULL) || l != r) return -3;
  529.       if (!WriteFile(hFileOut,_inbuffer,r,&t,NULL) || t != l) return -2;
  530.       retval+=r;
  531.       input_len-=r;
  532.       dbd_pos+=r;
  533.     }
  534.   }
  535.   else
  536.   {
  537.     if (!ReadFile(dbd_hFile,(LPVOID)outbuf,min(input_len,outbuflen),&r,NULL)) return -3;
  538.     retval=r;
  539.     dbd_pos+=r;
  540.   }
  541.   return retval;
  542. }
  543. #endif//NSIS_COMPRESS_WHOLE
  544.  
  545. BOOL NSISCALL ReadSelfFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead)
  546. {
  547.   DWORD rd;
  548.   return ReadFile(g_db_hFile,lpBuffer,nNumberOfBytesToRead,&rd,NULL) && (rd == nNumberOfBytesToRead);
  549. }
  550.  
  551. DWORD NSISCALL SetSelfFilePointer(LONG lDistanceToMove)
  552. {
  553.   return SetFilePointer(g_db_hFile,lDistanceToMove,NULL,FILE_BEGIN);
  554. }
  555.