home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 October / Chip_2001-10_cd1.bin / zkuste / delphi / nastroje / d23456 / NSIS.EXE / Source / exehead / Ui.c < prev    next >
C/C++ Source or Header  |  2001-06-05  |  30KB  |  969 lines

  1. #include <windows.h>
  2. #include <shlobj.h>
  3. #include "resource.h"
  4.  
  5. #include "fileform.h"
  6. #include "state.h"
  7. #include "util.h"
  8. #include "ui.h"
  9. #include "libc.h"
  10. #include "exec.h"
  11.  
  12. #define LB_ICONWIDTH 20
  13. #define LB_ICONHEIGHT 20
  14.  
  15. extern const char *verstr;
  16. char g_autoclose;
  17.  
  18. static char g_tmp[4096];
  19.  
  20. // sent to the last child window to tell it that the install thread is done
  21. #define WM_NOTIFY_INSTPROC_DONE (WM_USER+0x4)
  22.  
  23. // sent to the outer window to tell it to go to the next inner window
  24. #define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8)
  25.  
  26. // update message used by DirProc and SelProc for space display
  27. #define WM_IN_UPDATEMSG (WM_USER+0xf)
  28.  
  29. static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 
  30. static BOOL CALLBACK DialogProcUninstall(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 
  31. static int CALLBACK WINAPI BrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
  32. static BOOL CALLBACK LicenseProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 
  33. static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 
  34. static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 
  35. static BOOL CALLBACK InstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 
  36. static BOOL CALLBACK UninstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 
  37. static DWORD WINAPI install_thread(LPVOID p);
  38.  
  39.  
  40. HWND bgWnd_Init(HINSTANCE hInstance, char *title, int color1, int color2, int);
  41.  
  42. int g_show_details;
  43. HWND insthwnd, insthwnd2,insthwndbutton;
  44. static char *g_space_requiredstr="Space required: ";
  45.  
  46. header *g_inst_header;
  47. section *g_inst_section;
  48. entry *g_inst_entry;
  49. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  50. uninstall_header *g_inst_uninstheader;
  51. #endif
  52.  
  53. static int m_page,m_abort;
  54. static HWND m_curwnd;
  55. static int m_whichcfg;
  56.  
  57. #ifdef NSIS_CONFIG_LOG
  58. static void build_g_logfile()
  59. {
  60.   char *p=g_log_file;
  61.   lstrcpy(g_log_file,state_install_directory);
  62.   if (g_log_file[0])
  63.   {
  64.     while (*p) p++;
  65.     if (p[-1] != '\\') *p++='\\';
  66.   }
  67.   lstrcpy(p,"install.log");
  68. }
  69. #endif
  70.  
  71.  
  72. int ui_doinstall(void)
  73. {
  74. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  75.   if (g_inst_uninstheader)
  76.   {
  77.     HWND h=GetDesktopWindow();
  78.     wsprintf(g_caption,"%s Uninstall",GetStringFromStringTab(g_inst_uninstheader->name_ptr));
  79. #ifdef NSIS_SUPPORT_BGBG
  80.     if (g_inst_uninstheader->bg_color1 != -1)
  81.     {
  82.       h=bgWnd_Init(g_hInstance,g_caption,g_inst_uninstheader->bg_color1,g_inst_uninstheader->bg_color2,g_inst_uninstheader->bg_textcolor);
  83.     }
  84. #endif
  85.     return DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_INST),h,DialogProcUninstall);
  86.   }
  87. #endif
  88.   g_autoclose=g_inst_header->auto_close;
  89.   {
  90.     static char buf[1024];
  91.     int st=0;
  92.  
  93.     if (!is_valid_instpath(state_install_directory)) 
  94.     {
  95.       if (GetStringFromStringTab(g_inst_header->install_reg_key_ptr)[0])
  96.       {
  97.         HKEY hKey;
  98.             if ( RegOpenKeyEx((HKEY)g_inst_header->install_reg_rootkey,GetStringFromStringTab(g_inst_header->install_reg_key_ptr),0,KEY_READ,&hKey) == ERROR_SUCCESS)
  99.         {
  100.                 int l = sizeof(buf);
  101.                 int t=REG_SZ;
  102.           if (RegQueryValueEx(hKey,GetStringFromStringTab(g_inst_header->install_reg_value_ptr),NULL,&t,buf,&l ) == ERROR_SUCCESS && t == REG_SZ && buf[0])
  103.                 {
  104.             char tmp[5];
  105.             char *e;
  106.             char *p=buf;
  107.             while (*p && *p != '\"') p++;
  108.             if (*p)
  109.             {
  110.               char *p2=++p;
  111.               while (*p2 && *p2 != '\"') p2++;
  112.               if (*p2)
  113.               {
  114.                 *p2=0;
  115.               }
  116.               else p=buf;
  117.             }
  118.             else p=buf; 
  119.             // p is the path now, check for .exe extension
  120.             e=p;
  121.             while (*e) e++;
  122.             while (e>p && *e != '.' && *e != '\\') e--;
  123.             mini_memcpy(tmp,e,4);
  124.             tmp[4]=0;           
  125.             if (!lstrcmpi(tmp,".exe"))        // check extension
  126.             {
  127.               DWORD d;
  128.               e[4]=0;
  129.               d=GetFileAttributes(p);               // get the file attributes
  130.               if (d == (DWORD)-1 || !(d&FILE_ATTRIBUTE_DIRECTORY)) // if not exists, or not directory, then remove suffix
  131.               {
  132.                 while (e>p && *e != '\\') e--;
  133.                 if (*e == '\\') *e=0;
  134.               }
  135.             }
  136.             lstrcpy(state_install_directory,p);
  137.           }
  138.                 RegCloseKey(hKey);
  139.         }
  140.       }
  141.  
  142.     }
  143.     if (!is_valid_instpath(state_install_directory)) 
  144.     {
  145.       state_install_directory[0]=0;
  146.       process_string_fromtab(buf,g_inst_header->install_directory_ptr);
  147.       lstrcpy(state_install_directory,buf);
  148.     }
  149.  
  150.     lstrcpy(g_caption,GetStringFromStringTab(g_inst_header->caption_ptr));
  151. #ifdef NSIS_CONFIG_LOG
  152.     if (g_inst_header->silent_install==2) 
  153.     {
  154.       build_g_logfile();
  155.       log_dolog=1;
  156.     }
  157. #endif
  158.  
  159.     if (!g_inst_header->silent_install) 
  160.     {
  161.       HWND h=GetDesktopWindow();
  162. #ifdef NSIS_SUPPORT_BGBG
  163.       if (g_inst_header->bg_color1 != -1)
  164.       {
  165.         h=bgWnd_Init(g_hInstance,g_caption,g_inst_header->bg_color1,g_inst_header->bg_color2,g_inst_header->bg_textcolor);
  166.       }
  167. #endif
  168.       g_hwnd=h;
  169.       if (ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onInit,NULL)) return 1;
  170.       g_hwnd=NULL;
  171.       return DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_INST),h,DialogProc);
  172.     }
  173.     else 
  174.     {      
  175.       if (ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onInit,NULL)) return 1;
  176.       if (install_thread(NULL))
  177.       {
  178.         ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onInstFailed,NULL);
  179.         return 1;
  180.       }
  181.       ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onInstSuccess,NULL);
  182.       return 0;
  183.     }
  184.   }
  185. }
  186.  
  187. static int CALLBACK WINAPI BrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  188. {
  189.     if (uMsg==BFFM_INITIALIZED)
  190.     {
  191.         GetDlgItemText((HWND)lpData,IDC_DIR,g_tmp,sizeof(g_tmp));
  192.         SendMessage(hwnd,BFFM_SETSELECTION,(WPARAM)1,(LPARAM)g_tmp);
  193.     }
  194.     return 0;
  195. }
  196.  
  197.  
  198. static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  199. {
  200.     static HICON hIcon;
  201.   if (uMsg == WM_DESTROY && hIcon) { DeleteObject(hIcon); hIcon=0; }
  202.   if (uMsg == WM_INITDIALOG || uMsg == WM_NOTIFY_OUTER_NEXT)
  203.     {
  204.     int backenabled=0,iscp=0,islp=0;
  205.     int delta=(uMsg == WM_NOTIFY_OUTER_NEXT)?wParam:0;
  206.     int x;
  207.     static struct 
  208.     {
  209.       char *id;
  210.       WNDPROC proc;
  211.       char *s;
  212.     }
  213.     windows[4]=
  214.     {
  215.       {MAKEINTRESOURCE(IDD_LICENSE),LicenseProc,"License Agreement"},
  216.       {MAKEINTRESOURCE(IDD_SELCOM),SelProc,"Installation Options"},
  217.       {MAKEINTRESOURCE(IDD_DIR),DirProc,"Installation Directory"},
  218.       {MAKEINTRESOURCE(IDD_INSTFILES),InstProc,"Installing Files"},
  219.     };
  220.     if (uMsg == WM_INITDIALOG)
  221.     {
  222.       g_hwnd=hwndDlg;
  223.       SetDlgItemText(hwndDlg,IDC_VERSTR,verstr);
  224.           hIcon=LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_ICON2));
  225.           SetClassLong(hwndDlg,GCL_HICON,(long)hIcon);
  226.     }
  227.     if (GetStringFromStringTab(g_inst_header->licensetext_ptr)[0] && 
  228.         GetStringFromStringTab(g_inst_header->licensedata_ptr)[0]) islp++;
  229.     if (GetStringFromStringTab(g_inst_header->componenttext_ptr)[0])
  230.       for (x = 1; x < g_inst_header->num_sections && !iscp; x ++)
  231.       {
  232.         char c=GetStringFromStringTab(g_inst_section[x].name_ptr)[0];
  233.         if (c && c != '-') iscp++;
  234.       }
  235.    
  236.     m_page+=delta;
  237.     if (m_page < 0) m_page=0;
  238.     if (!delta) delta++;
  239.  
  240.     if (m_page==0 && !islp) m_page++;
  241.     if (m_page==1 && !iscp) m_page+=delta;
  242.     if (m_page == 2 && (!GetStringFromStringTab(g_inst_header->text_ptr)[0] ||
  243.          (g_inst_header->no_show_dirpage && 
  244.           is_valid_instpath(state_install_directory) && 
  245.           !ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onVerifyInstDir,NULL)))
  246.       ) m_page+=delta;
  247.  
  248.     if (m_page==1&&islp) backenabled++;
  249.     if (m_page==2&&(islp||iscp)) backenabled++;
  250.  
  251.     if (m_page>3) ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onInstSuccess,NULL);
  252.  
  253.     if (m_curwnd) DestroyWindow(m_curwnd);
  254.     m_curwnd=0;
  255.  
  256.     if (m_page < 0 || m_page > 3)
  257.     {
  258.       EndDialog(hwndDlg,0);
  259.     }
  260.     else
  261.     {
  262.       wsprintf(g_tmp,"%s: %s",g_caption,windows[m_page].s);
  263.       SetWindowText(hwndDlg,g_tmp);
  264.       m_curwnd=CreateDialog(g_hInstance,windows[m_page].id,hwndDlg,windows[m_page].proc); 
  265.           if (m_curwnd) 
  266.       {
  267.               RECT r;
  268.         GetWindowRect(GetDlgItem(hwndDlg,IDC_CHILDRECT),&r);
  269.               ScreenToClient(hwndDlg,(LPPOINT)&r);
  270.               SetWindowPos(m_curwnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  271.               ShowWindow(m_curwnd,SW_SHOWNA);
  272.         EnableWindow(GetDlgItem(hwndDlg,IDC_BACK),backenabled);
  273.           } 
  274.       SetFocus(GetDlgItem(hwndDlg,IDOK));
  275.     }
  276.   }
  277.   if (uMsg == WM_COMMAND)
  278.   {
  279.     int id=LOWORD(wParam);
  280.  
  281.     if (id == IDOK && m_curwnd)
  282.     {
  283.       SendMessage(hwndDlg,WM_NOTIFY_OUTER_NEXT,1,0);
  284.     }
  285.         if (id == IDC_BACK && m_curwnd && m_page>0)
  286.     {
  287.       SendMessage(hwndDlg,WM_NOTIFY_OUTER_NEXT,-1,0);
  288.     }
  289.       if (id == IDCANCEL )
  290.     {
  291.       if (m_abort)
  292.       {
  293.         ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onInstFailed,NULL);        
  294.                EndDialog(hwndDlg,2);
  295.       }
  296.       else
  297.       {
  298.         if (!ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onUserAbort,NULL))
  299.         {
  300.                  EndDialog(hwndDlg,1);
  301.         }
  302.       }
  303.         }
  304.     }
  305.   if (uMsg == WM_CLOSE)
  306.   {
  307.     if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDCANCEL)) && IsWindowEnabled(GetDlgItem(hwndDlg,IDOK)))
  308.       SendMessage(hwndDlg,WM_COMMAND,IDOK,0);
  309.   }
  310.     return 0;
  311. }
  312.  
  313. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  314. static BOOL CALLBACK DialogProcUninstall(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  315. {
  316.     static HICON hIcon;
  317.   if (uMsg == WM_DESTROY && hIcon) { DeleteObject(hIcon); hIcon=0; }
  318.   if (uMsg == WM_INITDIALOG || uMsg == WM_NOTIFY_OUTER_NEXT)
  319.     {
  320.     static struct 
  321.     {
  322.       char *id;
  323.       WNDPROC proc;
  324.       char *s;
  325.     }
  326.     windows[2]=
  327.     {
  328.       {MAKEINTRESOURCE(IDD_UNINST),UninstProc,"Confirmation"},
  329.       {MAKEINTRESOURCE(IDD_INSTFILES),InstProc,"Uninstalling Files"},
  330.     };
  331.     if (uMsg == WM_INITDIALOG)
  332.     {
  333.       SetDlgItemText(hwndDlg,IDC_VERSTR,verstr);
  334.       g_hwnd=hwndDlg;
  335.           hIcon=LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_ICON2));
  336.           SetClassLong(hwndDlg,GCL_HICON,(long)hIcon);
  337.       EnableWindow(GetDlgItem(hwndDlg,IDC_BACK),0);
  338.     }
  339.     else m_page++;
  340.     if (m_curwnd) DestroyWindow(m_curwnd);
  341.     m_curwnd=0;
  342.     if (m_page < 0 || m_page > 1)
  343.     {
  344.       EndDialog(hwndDlg,0);
  345.     }
  346.     else
  347.     {
  348.       m_curwnd=CreateDialog(g_hInstance,windows[m_page].id,hwndDlg,windows[m_page].proc); 
  349.       wsprintf(g_tmp,"%s: %s",g_caption,windows[m_page].s);
  350.       SetWindowText(hwndDlg,g_tmp);
  351.     }
  352.         if (m_curwnd) 
  353.     {
  354.             RECT r;
  355.       GetWindowRect(GetDlgItem(hwndDlg,IDC_CHILDRECT),&r);
  356.             ScreenToClient(hwndDlg,(LPPOINT)&r);
  357.             SetWindowPos(m_curwnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  358.             ShowWindow(m_curwnd,SW_SHOWNA);
  359.         } 
  360.     SetFocus(GetDlgItem(hwndDlg,IDOK));
  361.   }
  362.   if (uMsg == WM_COMMAND)
  363.   {
  364.     if (LOWORD(wParam) == IDOK && m_curwnd)
  365.     {
  366.       SendMessage(hwndDlg,WM_NOTIFY_OUTER_NEXT,1,0);
  367.     }
  368.       if (LOWORD(wParam) == IDCANCEL)
  369.     {
  370.            EndDialog(hwndDlg,2);
  371.         }
  372.     }
  373.   if (uMsg == WM_CLOSE)
  374.   {
  375.     if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDCANCEL)) && IsWindowEnabled(GetDlgItem(hwndDlg,IDOK)))
  376.       SendMessage(hwndDlg,WM_COMMAND,IDOK,0);
  377.   }
  378.     return 0;
  379. }
  380. #endif
  381.  
  382.  
  383.  
  384.  
  385. static BOOL CALLBACK LicenseProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  386. {
  387.   if (uMsg == WM_INITDIALOG)
  388.   {    
  389.     SetDlgItemText(hwndDlg,IDC_EDIT1,GetStringFromStringTab(g_inst_header->licensedata_ptr));
  390.     SetDlgItemText(hwndDlg,IDC_INTROTEXT,GetStringFromStringTab(g_inst_header->licensetext_ptr));
  391.   }
  392.   if (uMsg == WM_CLOSE) SendMessage(GetParent(hwndDlg),WM_CLOSE,0,0);
  393.   return 0;
  394. }
  395.  
  396. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  397. static BOOL CALLBACK UninstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  398. {
  399.   if (uMsg == WM_INITDIALOG)
  400.   {
  401.     SetDlgItemText(hwndDlg,IDC_UNINSTFROM,"Uninstalling from:");
  402.     SetDlgItemText(hwndDlg,IDC_INTROTEXT,GetStringFromStringTab(g_inst_uninstheader->uninstalltext_ptr));
  403.     SetDlgItemText(hwndDlg,IDC_EDIT1,state_install_directory);
  404.   }
  405.   return 0;
  406. }
  407. #endif
  408.  
  409.  
  410. static void inttosizestr(int kb, char *str)
  411. {
  412.   while (*str) str++;
  413.   if (kb < 1024) wsprintf(str,"%dKB",kb);
  414.   else if (kb < 1024*1024) wsprintf(str,"%dMB",kb>>10);
  415.   else wsprintf(str,"%dGB+",kb>>20);
  416. }
  417.  
  418. static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  419. {
  420.   if (uMsg == WM_DESTROY)
  421.   {
  422.     GetDlgItemText(hwndDlg,IDC_DIR,state_install_directory,1024);
  423. #ifdef NSIS_CONFIG_LOG
  424.     build_g_logfile();
  425.     log_dolog = !!IsDlgButtonChecked(hwndDlg,IDC_CHECK1);
  426. #endif
  427.   }
  428.   if (uMsg == WM_INITDIALOG)
  429.   {
  430.     char str[256];
  431. #ifdef NSIS_CONFIG_LOG
  432.     if (GetAsyncKeyState(VK_SHIFT)&0x8000) 
  433.     {
  434.       HWND h=GetDlgItem(hwndDlg,IDC_CHECK1);
  435.       SetWindowText(h,"Log install process");
  436.       ShowWindow(h,SW_SHOWNA);
  437.     }
  438. #endif
  439.     SetDlgItemText(hwndDlg,IDC_DIR,state_install_directory);
  440.     SetDlgItemText(hwndDlg,IDC_INTROTEXT,GetStringFromStringTab(g_inst_header->text_ptr));
  441.     SetDlgItemText(hwndDlg,IDC_BROWSE,"Browse...");
  442.     wsprintf(str,"Select the directory to install %s in:",GetStringFromStringTab(g_inst_header->name_ptr));
  443.     SetDlgItemText(hwndDlg,IDC_SELDIRTEXT,str);
  444.     SendMessage(hwndDlg,WM_IN_UPDATEMSG,0,0);
  445.   }
  446.   if (uMsg == WM_COMMAND)
  447.   {
  448.     int id=LOWORD(wParam);
  449.     if (id == IDC_DIR && HIWORD(wParam) == EN_CHANGE)
  450.     {
  451.       SendMessage(hwndDlg,WM_IN_UPDATEMSG,0,0);
  452.     }
  453.         if (id == IDC_BROWSE)
  454.         {
  455.             char name[1024];
  456.       char str[1024];
  457.       BROWSEINFO bi={0,};
  458.             ITEMIDLIST *idlist;
  459.             GetDlgItemText(hwndDlg,IDC_DIR,name,1024);
  460.             GetDlgItemText(hwndDlg,IDC_SELDIRTEXT,str,1024);
  461.             bi.hwndOwner = hwndDlg;
  462.             bi.pszDisplayName = name;
  463.             bi.lpfn=BrowseCallbackProc;
  464.             bi.lParam=(LPARAM)hwndDlg;
  465.             bi.lpszTitle = str;
  466.             bi.ulFlags = BIF_RETURNONLYFSDIRS;
  467.             idlist = SHBrowseForFolder( &bi );
  468.             if (idlist) 
  469.       {
  470.         char *post_str;
  471.         char *p;
  472.         IMalloc *m;
  473.                 SHGetPathFromIDList( idlist, name );        
  474.         SHGetMalloc(&m);
  475.         if (m)
  476.         {
  477.           m->lpVtbl->Free(m,idlist);
  478.           m->lpVtbl->Release(m);
  479.         }
  480.         p=post_str=GetStringFromStringTab(g_inst_header->install_directory_ptr);
  481.         while (*p) p++;
  482.         while (p >= post_str && *p != '\\') p--;               
  483.         if (p >= post_str && *++p)
  484.         {
  485.           post_str=p;
  486.           p=name+lstrlen(name)-lstrlen(post_str);
  487.           if (p <= name || p[-1]!='\\' || lstrcmpi(p,post_str))
  488.           {
  489.             if (name[lstrlen(name)-1]!='\\') lstrcat(name,"\\");
  490.             lstrcat(name,post_str);
  491.           }
  492.         }
  493.  
  494.                 SetDlgItemText(hwndDlg,IDC_DIR,name);
  495.         uMsg = WM_IN_UPDATEMSG;
  496.             }
  497.         }
  498.   }
  499.   if (uMsg == WM_IN_UPDATEMSG)
  500.   {
  501.     static char s[1024];
  502.     int is_valid_path;
  503.     int x;
  504.     int total=0, available=-1;
  505.     DWORD spc,bps,fc,tc;
  506.     GetDlgItemText(hwndDlg,IDC_DIR,state_install_directory,1024);
  507.     is_valid_path=is_valid_instpath(state_install_directory);
  508.  
  509.     mini_memcpy(s,state_install_directory,sizeof(s));
  510.     s[sizeof(s)-1]=0;
  511.     if (s[1] == ':') s[3]=0;
  512.     else if (s[0] == '\\' && s[1] == '\\') // \\ path
  513.     {
  514.       if (s[lstrlen(s)-1]!='\\') 
  515.         lstrcat(s,"\\");
  516.     }
  517.  
  518.     if (GetDiskFreeSpace(s,&spc,&bps,&fc,&tc))
  519.     {
  520.       DWORD r;
  521.       DWORD v=0x7fffffff;
  522.       r=bps*spc*(fc>>10);
  523.       if (!r) r=(bps*spc*fc)>>10;
  524.       if (r > v) r=v;
  525.       available=(int)r;
  526.     }
  527.     for (x = 0; x < g_inst_header->num_sections; x ++)
  528.     {
  529.       if (!x || !GetStringFromStringTab(g_inst_section[x].name_ptr)[0]||g_inst_section[x].default_state&0x80000000)
  530.        total+=g_inst_section[x].size_kb;
  531.     }
  532.     lstrcpy(s,g_space_requiredstr);
  533.     inttosizestr(total,s);
  534.     SetDlgItemText(hwndDlg,IDC_SPACEREQUIRED,s);
  535.     if (available != -1)
  536.     {
  537.       lstrcpy(s,"Space available: ");
  538.       inttosizestr(available,s);
  539.       SetDlgItemText(hwndDlg,IDC_SPACEAVAILABLE,s);
  540.     }
  541.     else
  542.       SetDlgItemText(hwndDlg,IDC_SPACEAVAILABLE,"");
  543.  
  544.     EnableWindow(GetDlgItem(GetParent(hwndDlg),IDOK),
  545.       is_valid_path && (available >= total || available == -1) &&
  546.       !ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onVerifyInstDir,NULL));
  547.   }
  548.   return 0;
  549. }
  550.  
  551. static HBITMAP hBMcheck[2];
  552.  
  553. static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  554. {
  555.   HWND hwndCombo1 = GetDlgItem(hwndDlg,IDC_COMBO1);
  556.   HWND hwndList1 = GetDlgItem(hwndDlg,IDC_LIST1);
  557.   if (uMsg == WM_INITDIALOG)
  558.   {
  559.     hBMcheck[0]=LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP1)); 
  560.     hBMcheck[1]=LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP2)); 
  561.     SetDlgItemText(hwndDlg,IDC_INTROTEXT,GetStringFromStringTab(g_inst_header->componenttext_ptr));
  562.     if (!GetStringFromStringTab(g_inst_header->install_types_ptr[0])[0])
  563.     {
  564.       ShowWindow(hwndCombo1,SW_HIDE);
  565.       SetDlgItemText(hwndDlg,IDC_TEXT2,"Select components to install:");
  566.     }
  567.     else
  568.     {
  569.       int x;
  570.       SetDlgItemText(hwndDlg,IDC_TEXT1,"Select the type of install:");
  571.       if (!g_inst_header->no_custom_instmode_flag) SetDlgItemText(hwndDlg,IDC_TEXT2,"Or, select the optional components you wish to install:");     
  572.       for (x = 0; x < MAX_INST_TYPES && GetStringFromStringTab(g_inst_header->install_types_ptr[x])[0]; x ++)
  573.       {
  574.         SendMessage(hwndCombo1,CB_ADDSTRING,0,(LPARAM)GetStringFromStringTab(g_inst_header->install_types_ptr[x]));
  575.       }
  576.       if (!g_inst_header->no_custom_instmode_flag) SendMessage(hwndCombo1,CB_ADDSTRING,0,(LPARAM)"Custom");
  577.       SendMessage(hwndCombo1,CB_SETCURSEL,m_whichcfg,0);
  578.     }
  579.     {
  580.       int x;
  581.       int a=0;
  582.  
  583.       for (x = 0; x < g_inst_header->num_sections; x ++)
  584.       {
  585.         if (GetStringFromStringTab(g_inst_section[x].name_ptr)[0])
  586.         {
  587.           SendMessage(hwndList1,LB_ADDSTRING,0,(LPARAM)GetStringFromStringTab(g_inst_section[x].name_ptr));
  588.           if (!x || (g_inst_section[x].default_state & (0x80000000|(1<<m_whichcfg))) 
  589.               || !GetStringFromStringTab(g_inst_header->install_types_ptr[0])[0])
  590.             SendMessage(hwndList1,LB_SETSEL,TRUE,a);
  591.           a++;
  592.         }
  593.       }
  594.       SendDlgItemMessage(hwndDlg,IDC_LIST1,WM_VSCROLL,SB_TOP,0);
  595.     }
  596.     SendMessage(hwndDlg,WM_IN_UPDATEMSG,0,0);
  597.   }
  598.   if (uMsg == WM_COMMAND)
  599.   {
  600.     int id=LOWORD(wParam),code=HIWORD(wParam);
  601.     if (id == IDC_LIST1 && code==LBN_SELCHANGE)
  602.     {
  603.       int r,l=SendMessage(hwndCombo1,CB_GETCOUNT,0,0)-1;
  604.  
  605.       if (g_inst_header->no_custom_instmode_flag) 
  606.       {
  607.         int a=0;
  608.         int x;
  609.         for (x = 0; x < g_inst_header->num_sections; x ++)
  610.         {
  611.           char c=GetStringFromStringTab(g_inst_section[x].name_ptr)[0];
  612.           if (c)
  613.           {
  614.             if (x && c != '-')
  615.             {
  616.               if (!(g_inst_section[x].default_state&(1<<m_whichcfg)) != !SendMessage(hwndList1,LB_GETSEL,a,0)) 
  617.               {
  618.                 SendMessage(hwndList1,LB_SETSEL,(g_inst_section[x].default_state>>m_whichcfg)&1,a);
  619.               }
  620.             }
  621.             a++;
  622.           }
  623.         }
  624.       }
  625.  
  626.       for (r = 0; r < l; r ++)
  627.       {
  628.         int a=0;
  629.         int x;
  630.         for (x = 0; x < g_inst_header->num_sections; x ++)
  631.         {
  632.           char c=GetStringFromStringTab(g_inst_section[x].name_ptr)[0];
  633.           if (c)
  634.           {
  635.             if (x && c != '-')
  636.             {
  637.               if (!(g_inst_section[x].default_state&(1<<r)) != !SendMessage(hwndList1,LB_GETSEL,a,0)) break;
  638.             }
  639.             a++;
  640.           }
  641.         }
  642.         if (x == g_inst_header->num_sections) break;
  643.       }
  644.  
  645.       SendMessage(hwndCombo1,CB_SETCURSEL,r,0);
  646.       m_whichcfg=r;
  647.     
  648.       uMsg=WM_IN_UPDATEMSG;
  649.     }
  650.     if (id == IDC_COMBO1 && code==CBN_SELCHANGE)
  651.     {
  652.       int t=SendMessage(hwndCombo1,CB_GETCURSEL,0,0);
  653.       if (t != CB_ERR)
  654.       {
  655.         m_whichcfg=t;
  656.         if (g_inst_header->no_custom_instmode_flag || 
  657.           t != SendMessage(hwndCombo1,CB_GETCOUNT,0,0)-1)
  658.         {
  659.           int x,a=0;
  660.           for (x = 0; x < g_inst_header->num_sections; x ++)
  661.           {
  662.             if (GetStringFromStringTab(g_inst_section[x].name_ptr)[0])
  663.             {
  664.               SendMessage(hwndList1,LB_SETSEL,(!x||(g_inst_section[x].default_state & (1<<t))),a);
  665.               a++;
  666.             }
  667.           }
  668.           SendMessage(hwndList1,WM_VSCROLL,SB_TOP,0);
  669.         }
  670.         uMsg=WM_IN_UPDATEMSG;
  671.       }
  672.     }
  673.   }
  674.   if (uMsg == WM_DESTROY)
  675.   {
  676.     int x,a=0;
  677.     for (x = 0; x < g_inst_header->num_sections; x ++)
  678.     {
  679.       if (!GetStringFromStringTab(g_inst_section[x].name_ptr)[0] ||
  680.           SendDlgItemMessage(hwndDlg,IDC_LIST1,LB_GETSEL,a++,0) ||
  681.           !x)
  682.         g_inst_section[x].default_state|=0x80000000;
  683.       else
  684.         g_inst_section[x].default_state&=~0x80000000;
  685.     }  
  686.     DeleteObject(hBMcheck[0]);
  687.     DeleteObject(hBMcheck[1]);
  688.   }
  689.   if (uMsg == WM_IN_UPDATEMSG)
  690.   {
  691.     int x;
  692.     int a=0;
  693.     int total=0;
  694.     char s[128];
  695.     for (x = 0; x < g_inst_header->num_sections; x ++)
  696.     {
  697.       if (!GetStringFromStringTab(g_inst_section[x].name_ptr)[0] ||
  698.           SendDlgItemMessage(hwndDlg,IDC_LIST1,LB_GETSEL,a++,0) || !x)
  699.         total+=g_inst_section[x].size_kb;
  700.     }
  701.     lstrcpy(s,g_space_requiredstr);
  702.     inttosizestr(total,s);
  703.     SetDlgItemText(hwndDlg,IDC_SPACEREQUIRED,s);
  704.   }
  705.   if (uMsg == WM_MEASUREITEM)
  706.   {
  707.     LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam; 
  708.     char text[64];
  709.     SendDlgItemMessage(hwndDlg,IDC_LIST1,LB_GETTEXT,lpmis->itemID,(LPARAM)text);
  710.     lpmis->itemHeight = (text[0]=='-')?5:LB_ICONHEIGHT; 
  711.     return TRUE; 
  712.   }
  713.   if (uMsg == WM_CTLCOLORLISTBOX)
  714.   {
  715.     SetTextColor((HDC)wParam,GetNearestColor((HDC)wParam,RGB(0,0,0)));
  716.     SetBkColor((HDC)wParam,RGB(255,255,255));
  717.     return (int)GetStockObject(WHITE_BRUSH);
  718.   }
  719.   if (uMsg == WM_DRAWITEM)
  720.   {
  721.     LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam; 
  722.  
  723.     if (lpdis->itemID != -1) 
  724.     {
  725.       if (lpdis->itemAction == ODA_SELECT || lpdis->itemAction == ODA_DRAWENTIRE)
  726.       {
  727.         TEXTMETRIC tm;
  728.         int y;
  729.  
  730.         HBITMAP oldbm;
  731.         HDC memdc;
  732.  
  733.         SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, (LPARAM) g_tmp); 
  734.  
  735.         if (g_tmp[0]!='-')
  736.         {
  737.           GetTextMetrics(lpdis->hDC, &tm); 
  738.  
  739.           y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tm.tmHeight) / 2; 
  740.  
  741.           TextOut(lpdis->hDC, LB_ICONWIDTH + 2, y, g_tmp, lstrlen(g_tmp)); 
  742.  
  743.           memdc=CreateCompatibleDC(lpdis->hDC);
  744.           oldbm=SelectObject(memdc,hBMcheck[!((lpdis->itemState & ODS_SELECTED)||(!lpdis->itemID&&GetStringFromStringTab(g_inst_section[0].name_ptr)[0]))]);
  745.           BitBlt(lpdis->hDC,lpdis->rcItem.left,lpdis->rcItem.top,LB_ICONWIDTH,LB_ICONHEIGHT,memdc,0,0,SRCCOPY);
  746.           SelectObject(memdc,oldbm);
  747.           DeleteObject(memdc);
  748.         }
  749.         else
  750.         {
  751.           HPEN oldpen;
  752.           HPEN pen;
  753.           HDC memdc;
  754.           int w=lpdis->rcItem.right-lpdis->rcItem.left;
  755.           y=lpdis->rcItem.top/2+lpdis->rcItem.bottom/2;
  756.           memdc=lpdis->hDC;
  757.           pen=CreatePen(PS_SOLID,0,RGB(192,192,192));
  758.           oldpen=SelectObject(memdc,pen);
  759.           MoveToEx(memdc,lpdis->rcItem.left+w/8,y,NULL);
  760.           LineTo(memdc,lpdis->rcItem.right-w/8,y);
  761.           SelectObject(memdc,oldpen);
  762.           DeleteObject(pen);
  763.         }
  764.       }
  765.     } 
  766.     return TRUE; 
  767.   }
  768.   return 0;
  769. }
  770.  
  771.  
  772. void update_status_text(char *text1, char *text2)
  773. {
  774.   if (insthwnd||insthwnd2)
  775.   {
  776.     static char buf[4096]; // different thread, must use private buf.
  777.     if (lstrlen(text1)+lstrlen(text2) >= sizeof(buf)) return;
  778.  
  779.     lstrcpy(buf,text1);
  780.     lstrcat(buf,text2);
  781.     if (insthwnd) 
  782.     {
  783.       SendMessage(insthwnd,LB_ADDSTRING,(WPARAM)0,(LPARAM)buf);
  784.       if (IsWindowVisible(insthwnd)) SendMessage(insthwnd,WM_VSCROLL,SB_BOTTOM,0);
  785.     }
  786.     if (insthwnd2) SetWindowText(insthwnd2,buf);
  787.   }
  788. }
  789.  
  790.  
  791. static DWORD WINAPI install_thread(LPVOID p)
  792. {
  793.   HWND hwndDlg=(HWND)p;
  794.   int m_inst_sec=0;
  795. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  796.   if (!g_inst_header) 
  797.   {
  798.     ExecuteCodeSegment(g_inst_entry,g_inst_uninstheader->code,hwndDlg?GetDlgItem(hwndDlg,IDC_PROGRESS1):0);
  799.   }
  800.   else
  801.   {
  802. #endif
  803.     while (m_inst_sec<g_inst_header->num_sections && !m_abort)
  804.     {
  805.       if (g_inst_section[m_inst_sec].default_state&0x80000000 || 
  806.           g_inst_header->silent_install) 
  807.       {
  808.         log_printf2("Section: \"%s\"",GetStringFromStringTab(g_inst_section[m_inst_sec].name_ptr));
  809.         if (ExecuteCodeSegment(g_inst_entry,g_inst_section[m_inst_sec].code,hwndDlg?GetDlgItem(hwndDlg,IDC_PROGRESS1):0)) m_abort++;
  810.       }
  811.       else
  812.       {
  813.         log_printf2("Skipping section: \"%s\"",GetStringFromStringTab(g_inst_section[m_inst_sec].name_ptr));
  814.       }
  815.       m_inst_sec++;
  816.     }
  817. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  818.     if (!m_abort && g_inst_header) 
  819.     {
  820.       if (g_inst_header->uninstdata_offset != -1)
  821.       {
  822.         int ret=-666;
  823.         char *p=GetStringFromStringTab(g_inst_header->uninstall_exe_name_ptr);
  824.         static char buf[1024];
  825.         HANDLE hFile;
  826.       
  827.         lstrcpy(buf,state_install_directory);
  828.         if (buf[lstrlen(buf)-1]!='\\') lstrcat(buf,"\\");
  829.         lstrcat(buf,p);
  830.  
  831.         hFile=CreateFile(buf,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
  832.         if (hFile != INVALID_HANDLE_VALUE)
  833.         {
  834.           char *filebuf;
  835.           DWORD l;
  836.           filebuf=(char *)GlobalAlloc(GMEM_FIXED,g_filehdrsize);
  837.           if (filebuf)
  838.           {
  839.             int fixoffs=0;
  840.             SetFilePointer(g_db_hFile,0,NULL,FILE_BEGIN);
  841.             ReadFile(g_db_hFile,filebuf,g_filehdrsize,&l,NULL);
  842.             if (g_inst_header->uninstexehead_iconoffset > 0)
  843.             {
  844.               GetCompressedDataFromDataBlockToMemory(g_inst_header->uninstdata_offset,
  845.                 filebuf+g_inst_header->uninstexehead_iconoffset,766-ICO_HDRSKIP);
  846.             }
  847.             WriteFile(hFile,filebuf,g_filehdrsize,&l,NULL);
  848.             GlobalFree(filebuf);
  849.             ret=GetCompressedDataFromDataBlock(-1,hFile);         
  850.           }
  851.           CloseHandle(hFile);
  852.         }
  853.         log_printf3("created uninstaller: %d, \"%s\"",ret,buf);
  854.         if (ret < 0)
  855.         {
  856.           update_status_text("Error creating: ",p);
  857.           DeleteFile(buf);
  858.         }
  859.         else
  860.           update_status_text("Created uninstaller: ",p);
  861.       }
  862.     }
  863.   }
  864. #endif
  865.   if (hwndDlg) SendMessage(hwndDlg,WM_NOTIFY_INSTPROC_DONE,m_abort,0);
  866.   return m_abort;
  867. }
  868.  
  869. static BOOL CALLBACK InstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  870. {
  871.   static HBRUSH hBrush;
  872.   static int lb_bg,lb_fg;
  873.   if (uMsg == WM_DESTROY && hBrush) DeleteObject(hBrush);
  874.   if (uMsg == WM_INITDIALOG)
  875.   {
  876.     DWORD id;
  877.     HWND hwnd;
  878.     int num;
  879.     int x;
  880.     LOGBRUSH lb;
  881.     lb.lbStyle=BS_SOLID;
  882.  
  883.     insthwndbutton=GetDlgItem(hwndDlg,IDC_SHOWDETAILS);
  884.     SetWindowText(insthwndbutton,"Show details");
  885.     insthwnd2=GetDlgItem(hwndDlg,IDC_PROGRESSTEXT);
  886.     insthwnd=GetDlgItem(hwndDlg,IDC_LIST1);
  887.     if (g_inst_header)
  888.     {
  889.       log_printf3("New install of \"%s\" to \"%s\"",GetStringFromStringTab(g_inst_header->name_ptr),state_install_directory);
  890.       num=0;
  891.       for (x = 0; x < g_inst_header->num_sections; x ++)
  892.       {
  893.         if (g_inst_section[x].default_state&0x80000000) num+=g_inst_section[x].code[1]-g_inst_section[x].code[0];
  894.       }
  895.       g_show_details=g_inst_header->show_details;
  896.       if (g_inst_header->show_details)
  897.       {
  898.         ShowWindow(insthwndbutton,SW_HIDE);
  899.         if (g_inst_header->show_details != 2) ShowWindow(insthwnd,SW_SHOWNA);
  900.       }
  901.       lb.lbColor=g_inst_header->lb_bg;
  902.       lb_bg=g_inst_header->lb_bg;
  903.       lb_fg=g_inst_header->lb_fg;
  904.     }
  905. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  906.     else 
  907.     {
  908.       num=g_inst_uninstheader->code[1]-g_inst_uninstheader->code[0];
  909.       lb.lbColor=g_inst_uninstheader->lb_bg;
  910.       lb_bg=g_inst_uninstheader->lb_bg;
  911.       lb_fg=g_inst_uninstheader->lb_fg;
  912.     }
  913. #endif
  914.     if (lb_fg != -1) hBrush=CreateBrushIndirect(&lb);
  915.  
  916.     hwnd=GetDlgItem(hwndDlg,IDC_PROGRESS1);
  917.       SendMessage(hwnd,PBM_SETRANGE,0,MAKELPARAM(0,num));
  918.       SendMessage(hwnd,PBM_SETPOS,0,0);       
  919.  
  920.     hwnd=GetParent(hwndDlg);
  921.     EnableWindow(GetDlgItem(hwnd,IDC_BACK),0);
  922.     EnableWindow(GetDlgItem(hwnd,IDOK),0);
  923.     EnableWindow(GetDlgItem(hwnd,IDCANCEL),0);
  924.  
  925.     CloseHandle(CreateThread(NULL,0,install_thread,(LPVOID)hwndDlg,0,&id));
  926.   }
  927.   if (uMsg == WM_CTLCOLORLISTBOX && lb_fg != -1)
  928.   {
  929.     SetTextColor((HDC)wParam,GetNearestColor((HDC)wParam,lb_fg));
  930.     SetBkColor((HDC)wParam,lb_bg);
  931.     return (int)hBrush;
  932.   }
  933.   if (uMsg == WM_COMMAND && LOWORD(wParam) == IDC_SHOWDETAILS)
  934.   {
  935.     ShowWindow(GetDlgItem(hwndDlg,IDC_SHOWDETAILS),SW_HIDE);
  936.     SendMessage(insthwnd,WM_VSCROLL,SB_BOTTOM,0);
  937.     ShowWindow(insthwnd,SW_SHOWNA);
  938.   }
  939.   if (uMsg == WM_NOTIFY_INSTPROC_DONE)
  940.   {
  941.     if (!wParam)
  942.     {
  943.       HWND h2=GetParent(hwndDlg);
  944.       HWND h=GetDlgItem(h2,IDOK);
  945.       EnableWindow(h,1);
  946.       if (!g_inst_header || !g_autoclose)
  947.       {
  948.         ShowWindow(g_hwnd,SW_SHOWNA);
  949.         lstrcat(g_caption,": Completed");
  950.         SetWindowText(h2,g_caption);
  951.         update_status_text("Completed","");
  952.         SetWindowText(h,"Close");
  953.         SetFocus(h);
  954.       }
  955.       else
  956.       {
  957.         SendMessage(GetParent(hwndDlg),WM_NOTIFY_OUTER_NEXT,1,0);
  958.       }
  959.     }
  960.     else
  961.     {
  962.       HWND h=GetDlgItem(GetParent(hwndDlg),IDCANCEL);
  963.       EnableWindow(h,1);
  964.       SetFocus(h);
  965.     }
  966.   }
  967.   return 0;
  968. }
  969.