+void findfiles(char*path, int*pos, char*data, int len, char del)
+{
+ WIN32_FIND_DATA findFileData;
+ HANDLE hFind = FindFirstFile(concatPaths(path, "*"), &findFileData);
+ if(hFind == INVALID_HANDLE_VALUE)
+ return;
+ do {
+ if(findFileData.cFileName[0] == '.' &&
+ (findFileData.cFileName[0] == '.' || findFileData.cFileName == '\0'))
+ continue;
+ char*f = concatPaths(path, findFileData.cFileName);
+ if(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ findfiles(f, pos, data, len, del);
+ if(del) {
+ RemoveDirectory(f);
+ }
+ } else {
+ int l = strlen(f);
+ if(data) {
+ if(*pos+l <= len) {
+ memcpy(&data[*pos], f, l);(*pos)+=l;
+ data[(*pos)++] = '\r';
+ data[(*pos)++] = '\n';
+ }
+ } else {
+ (*pos) += l+2;
+ }
+ if(del) {
+ DeleteFile(f);
+ }
+ }
+ } while(FindNextFile(hFind, &findFileData));
+ FindClose(hFind);
+}
+
+BOOL CALLBACK PropertySheetFunc6(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ if(message == WM_INITDIALOG) {
+ SendDlgItemMessage(hwnd, IDC_DELETEEXTRA, BM_SETCHECK, config_deleteextra, 0);
+
+ int len = 0;
+
+ findfiles(install_path, &len, 0, 0, 0);
+ char*data = malloc(len);
+ int pos = 0;
+ findfiles(install_path, &pos, data, len, 0);
+
+ SetDlgItemText(hwnd, IDC_FILELIST, data);
+ }
+ if(message == WM_COMMAND) {
+ if((wParam&0xffff) == IDC_DELETEEXTRA) {
+ config_deleteextra = SendDlgItemMessage(hwnd, IDC_DELETEEXTRA, BM_GETCHECK, 0, 0);
+ config_deleteextra ^=1;
+ SendDlgItemMessage(hwnd, IDC_DELETEEXTRA, BM_SETCHECK, config_deleteextra, 0);
+ return 0;
+ }
+ }
+ if(message == WM_NOTIFY && (((LPNMHDR)lParam)->code == PSN_WIZNEXT)) {
+ if(config_deleteextra) {
+ int pos = 0;
+ findfiles(install_path, &pos, 0, 0, 1);
+ }
+ }
+ return PropertySheetFuncCommon(hwnd, message, wParam, lParam, PSWIZB_NEXT);
+}
+
+BOOL CALLBACK PropertySheetFunc7(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ if(message == WM_INITDIALOG) {
+ // ...
+ }
+ return PropertySheetFuncCommon(hwnd, message, wParam, lParam, PSWIZB_FINISH);
+}
+#endif
+
+#ifndef PSP_HIDEHEADER
+#define PSP_HIDEHEADER 2048
+#endif
+
+typedef struct _wizardpage {
+ DLGPROC function;
+ int resource;
+} wizardpage_t;
+
+void runPropertySheet(HWND parent)
+{
+ PROPSHEETHEADER sheet;
+
+ wizardpage_t wpage[5] = {
+#ifndef DEINSTALL
+ {PropertySheetFunc1, IDD_LICENSE},
+ {PropertySheetFunc2, IDD_INSTALLDIR},
+ {PropertySheetFunc3, IDD_PROGRESS},
+ {PropertySheetFunc4, IDD_FINISH},
+#else
+ {PropertySheetFunc5, IDD_SURE},
+ {PropertySheetFunc6, IDD_EXTRAFILES},
+ {PropertySheetFunc7, IDD_DEINSTALLED},
+#endif
+ };
+ int num = sizeof(wpage)/sizeof(wpage[0]);
+ HPROPSHEETPAGE pages[num];
+ int t;
+ for(t=0;t<num;t++) {
+ PROPSHEETPAGE page;
+ memset(&page, 0, sizeof(PROPSHEETPAGE));
+ page.dwSize = sizeof(PROPSHEETPAGE);
+ page.dwFlags = PSP_DEFAULT|PSP_HIDEHEADER;
+ page.hInstance = me;
+ page.pfnDlgProc = wpage[t].function;
+ page.pszTemplate = MAKEINTRESOURCE(wpage[t].resource);
+ pages[t] = CreatePropertySheetPage(&page);
+ }
+
+ memset(&sheet, 0, sizeof(PROPSHEETHEADER));
+ sheet.dwSize = sizeof(PROPSHEETHEADER);
+ sheet.hInstance = me;
+ sheet.hwndParent = parent;
+ sheet.phpage = pages;
+ sheet.dwFlags = PSH_WIZARD;
+ sheet.nPages = num;
+ PropertySheet(&sheet);
+}
+
+#ifdef DEINSTALL
+
+static void remove_self()
+{
+ char exename[MAX_PATH];
+ char batname[MAX_PATH];
+ FILE *fp;
+
+ GetModuleFileName(NULL, exename, sizeof(exename));
+ sprintf(batname, "%s.bat", exename);
+ fp = fopen(batname, "w");
+ fprintf(fp, ":Repeat\n");
+ fprintf(fp, "del \"%s\"\n", exename);
+ fprintf(fp, "if exist \"%s\" goto Repeat\n", exename);
+ fprintf(fp, "del \"%s\"\n", batname);
+ fclose(fp);
+
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ memset(&si, 0, sizeof(si));
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+ si.cb = sizeof(si);
+ if (CreateProcess(NULL, batname, NULL, NULL, FALSE,
+ CREATE_SUSPENDED | IDLE_PRIORITY_CLASS,
+ NULL, "\\", &si, &pi)) {
+ SetThreadPriority(pi.hThread, THREAD_PRIORITY_IDLE);
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
+ CloseHandle(pi.hProcess);
+ ResumeThread(pi.hThread);
+ CloseHandle(pi.hThread);
+ }
+
+}
+
+int WINAPI WinMain(HINSTANCE _me,HINSTANCE hPrevInst,LPSTR lpszArgs, int nWinMode)
+{
+ me = _me;
+ sprintf(registry_path, "Software\\%s\\%s\\InstallPath", SOFTWARE_DOMAIN, SOFTWARE_NAME);
+
+ HWND background = 0;
+ logo = LoadBitmap(me, "LOGO");
+
+ install_path = getRegistryEntry(registry_path);
+ if(!install_path || !install_path[0]) {
+ MessageBox(0, "Couldn't find software installation directory- did you run the deinstallation twice?", INSTALLER_NAME, MB_OK);
+ return 1;
+ }
+
+ CoInitialize(0);
+ InitCommonControls();
+
+ runPropertySheet(background);
+
+ remove_self();
+ return 0;
+}
+#else
+int WINAPI WinMain(HINSTANCE _me,HINSTANCE hPrevInst,LPSTR lpszArgs, int nWinMode)
+{
+ me = _me;
+ WNDCLASSEX wcl_background;
+ wcl_background.hInstance = me;
+ wcl_background.lpfnWndProc = WindowFunc;
+ wcl_background.lpszClassName= INSTALLER_NAME;
+ wcl_background.style = CS_HREDRAW | CS_VREDRAW;
+ wcl_background.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wcl_background.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+ wcl_background.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcl_background.lpszMenuName = NULL; //no menu
+ wcl_background.cbClsExtra = 0;
+ wcl_background.cbWndExtra = 0;
+ wcl_background.hbrBackground= CreateSolidBrush(RGB(0, 0, 128));
+ wcl_background.cbSize = sizeof(WNDCLASSEX);
+
+ sprintf(registry_path, "Software\\%s\\%s\\InstallPath", SOFTWARE_DOMAIN, SOFTWARE_NAME);
+
+ HINSTANCE shell32 = LoadLibrary("shell32.dll");
+ if(!shell32) {
+ MessageBox(0, "Could not load shell32.dll", INSTALLER_NAME, MB_OK);
+ return 1;
+ }
+ f_SHGetSpecialFolderPath = (HRESULT (WINAPI*)(HWND,LPTSTR,int,BOOL))GetProcAddress(shell32, "SHGetSpecialFolderPathA");
+ if(!f_SHGetSpecialFolderPath) {
+ MessageBox(0, "Could not load shell32.dll", INSTALLER_NAME, MB_OK);
+ return 1;
+ }
+
+ HRESULT coret = CoInitialize(NULL);
+ if(FAILED(coret)) {
+ MessageBox(0, "Could not initialize COM interface", INSTALLER_NAME, MB_OK);
+ return 1;
+ }
+
+ path_programfiles[0] = 0;
+ f_SHGetSpecialFolderPath(NULL, path_programfiles, CSIDL_PROGRAM_FILES, 0);
+
+ if(!RegisterClassEx(&wcl_background)) {
+ MessageBox(0, "Could not register window background class", INSTALLER_NAME, MB_OK);
+ return 1;
+ }
+
+ HWND background = CreateWindow(wcl_background.lpszClassName, INSTALLER_NAME,
+ 0, 0, 0,
+ GetSystemMetrics(SM_CXFULLSCREEN),
+ GetSystemMetrics(SM_CYFULLSCREEN),
+ NULL, NULL, me,
+ (void*)"background");
+
+ if(!background) {
+ MessageBox(0, "Could not create installation background window", INSTALLER_NAME, MB_OK);
+ return 1;
+ }
+
+ ShowWindow(background, SW_SHOWMAXIMIZED);
+ SetForegroundWindow(background);
+ UpdateWindow(background);
+
+ logo = LoadBitmap(me, "LOGO");
+
+ install_path = getRegistryEntry(registry_path);
+ if(!install_path || !install_path[0]) {
+ if(path_programfiles[0]) {
+ install_path = concatPaths(path_programfiles, SOFTWARE_NAME);
+ } else {
+ install_path = concatPaths("c:\\", SOFTWARE_NAME);
+ }
+ }
+
+ InitCommonControls();
+
+ runPropertySheet(background);
+ return 0;
+}
+#endif