Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

384 lines
8.8 KiB

  1. //
  2. // Setup.C
  3. //
  4. // Copyright (C) Microsoft, 1994,1995 All Rights Reserved.
  5. //
  6. // History:
  7. // ral 5/23/94 - First pass
  8. // 3/20/95 [stevecat] - NT port & real clean up, unicode, etc.
  9. //
  10. //
  11. #include "priv.h"
  12. #include "appwiz.h"
  13. void _inline InitSetupWiz(HWND hDlg, LPARAM lParam)
  14. {
  15. InitWizSheet(hDlg, lParam, 0);
  16. }
  17. //
  18. // Loads the specified resource ID string and replaces all ';' characters
  19. // with NULL. The end of the string will be doubly null-teminated.
  20. //
  21. BOOL LoadAndStrip(int id, LPTSTR lpsz, int cbstr)
  22. {
  23. ASSERT(lpsz);
  24. ASSERT(cbstr != 0);
  25. if (!LoadString(g_hinst, id, lpsz, cbstr-1))
  26. {
  27. return FALSE;
  28. }
  29. else
  30. {
  31. while (*lpsz)
  32. {
  33. if (*lpsz == TEXT('@'))
  34. {
  35. *lpsz = 0;
  36. lpsz++;
  37. }
  38. else
  39. {
  40. lpsz = CharNext(lpsz);
  41. }
  42. }
  43. *(lpsz+1) = 0;
  44. return TRUE;
  45. }
  46. }
  47. //
  48. // Skips to the first charcter of the next string in a list of null-terminated
  49. // strings. The caller should check to see if the pointer returned points to
  50. // a null. If so, the end of the table has been reached.
  51. //
  52. LPTSTR SkipStr(LPTSTR lpsz)
  53. {
  54. while (*lpsz)
  55. {
  56. lpsz = CharNext(lpsz);
  57. }
  58. lpsz++;
  59. return(lpsz);
  60. }
  61. void SetStaticStr(HWND hCtl, int id)
  62. {
  63. TCHAR szText[MAX_PATH];
  64. LoadString(g_hinst, id, szText, ARRAYSIZE(szText));
  65. Static_SetText(hCtl, szText);
  66. }
  67. void FreeIcon(HWND hDlg)
  68. {
  69. HICON hicon = Static_SetIcon(GetDlgItem(hDlg, IDC_SEARCHICON), NULL);
  70. if (hicon)
  71. {
  72. DestroyIcon(hicon);
  73. }
  74. }
  75. //
  76. // ProgramExists returns TRUE if the specified file exists. This function
  77. // accepts wildcards, and if a file matches the specified name then
  78. // the file name buffer will be updated to the actual name of the first
  79. // matching file. This allows FindBestSetupPrg to pass in *setup to find
  80. // programs such as WPSETUP.EXE.
  81. //
  82. // This function assumes that szFindName is of size MAX_PATH.
  83. //
  84. BOOL ProgramExists(LPTSTR lpszFindName)
  85. {
  86. HANDLE hfind;
  87. WIN32_FIND_DATA fd;
  88. hfind = FindFirstFile(lpszFindName, &fd);
  89. if (hfind == INVALID_HANDLE_VALUE)
  90. {
  91. return(FALSE);
  92. }
  93. FindClose(hfind);
  94. lstrcpy(lpszFindName+3, fd.cFileName);
  95. return(TRUE);
  96. }
  97. //
  98. // This function searches for the "best" setup program. Once a windows app
  99. // with the appropriate name is found it stops. If it finds a install/setup
  100. // program that is a DOS program, it remembers the first one, but continues
  101. // searching for a Windows setup program.
  102. // Games like Math Rabbit have a DOS Install.Exe and a Windows Setup.Exe.
  103. //
  104. BOOL FindBestSetupPrg(LPTSTR lpszExeName, LPTSTR lpszDriveRoot, LPTSTR lpszSpecialCase,
  105. LPTSTR lpszAppNames, LPTSTR lpszExtensions)
  106. {
  107. LPTSTR lpszCurApp, lpszCurExt;
  108. TCHAR szThisOne[MAX_PATH];
  109. *lpszExeName = 0;
  110. //
  111. // Look for special-case programs first
  112. //
  113. lpszCurApp = lpszSpecialCase;
  114. while(*lpszCurApp)
  115. {
  116. lstrcpy(szThisOne, lpszDriveRoot);
  117. lstrcat(szThisOne, lpszCurApp);
  118. if (ProgramExists(szThisOne))
  119. {
  120. lstrcpy(lpszExeName, szThisOne);
  121. return(TRUE);
  122. }
  123. lpszCurApp = SkipStr(lpszCurApp);
  124. }
  125. //
  126. // Now look for generic setup program names
  127. //
  128. lpszCurApp = lpszAppNames;
  129. while (*lpszCurApp)
  130. {
  131. lpszCurExt = lpszExtensions;
  132. while (*lpszCurExt)
  133. {
  134. lstrcpy(szThisOne, lpszDriveRoot);
  135. lstrcat(szThisOne, lpszCurApp);
  136. lstrcat(szThisOne, TEXT("."));
  137. lstrcat(szThisOne, lpszCurExt);
  138. if (ProgramExists(szThisOne))
  139. {
  140. BOOL fIsWinApp = HIWORD(SHGetFileInfo(szThisOne, 0, NULL,
  141. 0, SHGFI_EXETYPE)) > 0;
  142. if (*lpszExeName == 0 || fIsWinApp)
  143. {
  144. lstrcpy(lpszExeName, szThisOne);
  145. }
  146. if (fIsWinApp)
  147. {
  148. return(TRUE);
  149. }
  150. }
  151. lpszCurExt = SkipStr(lpszCurExt);
  152. }
  153. lpszCurApp = SkipStr(lpszCurApp);
  154. }
  155. return(*lpszExeName != 0);
  156. }
  157. //
  158. // Gets information about the specified file/drive root and sets the
  159. // icon and description fields in the dialog.
  160. //
  161. void _inline UpdateFileInfo(LPWIZDATA lpwd, LPTSTR lpszFileName)
  162. {
  163. HWND hKiddie;
  164. HICON hOldIcon;
  165. SHFILEINFO fi;
  166. DWORD_PTR pdwRes;
  167. pdwRes = SHGetFileInfo(lpszFileName, 0, &fi, sizeof(fi),
  168. SHGFI_ICON | SHGFI_DISPLAYNAME | SHGFI_LARGEICON);
  169. if (pdwRes)
  170. {
  171. hKiddie = GetDlgItem(lpwd->hwnd, IDC_SEARCHICON);
  172. hOldIcon = Static_SetIcon(hKiddie, fi.hIcon);
  173. if (hOldIcon)
  174. {
  175. DestroyIcon(hOldIcon);
  176. }
  177. UpdateWindow(hKiddie);
  178. hKiddie = GetDlgItem(lpwd->hwnd, IDC_SEARCHNAME);
  179. Static_SetText(hKiddie, fi.szDisplayName);
  180. UpdateWindow(hKiddie);
  181. }
  182. }
  183. //
  184. // Search for the setup program
  185. //
  186. BOOL SetupNextPressed(LPWIZDATA lpwd)
  187. {
  188. int iDrive, iDrvType;
  189. BOOL fFoundExe = FALSE;
  190. HWND hMainMsg = GetDlgItem(lpwd->hwnd, IDC_SETUPMSG);
  191. HWND hSetupName = GetDlgItem(lpwd->hwnd, IDC_SEARCHNAME);
  192. TCHAR szAppNames[MAX_PATH];
  193. TCHAR szExtensions[100];
  194. TCHAR szSpecialCase[MAX_PATH];
  195. TCHAR szDriveRoot[4];
  196. HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  197. //BOOL fFoundDisk = FALSE;
  198. lpwd->szExeName[0] = 0; // Reset any existing name
  199. SetStaticStr(hMainMsg, IDS_SEARCHING);
  200. LoadAndStrip(IDS_SETUPPRGNAMES, szAppNames, ARRAYSIZE(szAppNames));
  201. LoadAndStrip(IDS_EXTENSIONS, szExtensions, ARRAYSIZE(szExtensions));
  202. LoadAndStrip(IDS_SPECIALCASE, szSpecialCase, ARRAYSIZE(szSpecialCase));
  203. for (iDrive = 0; (!fFoundExe) && (iDrive < 26); iDrive++)
  204. {
  205. iDrvType = DriveType(iDrive);
  206. if ((iDrvType == DRIVE_REMOVABLE) || (iDrvType == DRIVE_CDROM))
  207. {
  208. PathBuildRoot(szDriveRoot, iDrive);
  209. UpdateFileInfo(lpwd, szDriveRoot);
  210. if (PathFileExists(szDriveRoot))
  211. {
  212. //fFoundDisk = TRUE;
  213. fFoundExe = FindBestSetupPrg(lpwd->szExeName, szDriveRoot,
  214. szSpecialCase,
  215. szAppNames, szExtensions);
  216. }
  217. }
  218. }
  219. FreeIcon(lpwd->hwnd);
  220. SetCursor(hcurOld);
  221. return(fFoundExe);
  222. }
  223. void SetupSetToDefault(LPWIZDATA lpwd)
  224. {
  225. SetStaticStr(GetDlgItem(lpwd->hwnd, IDC_SETUPMSG), IDS_INSERTDISK);
  226. Static_SetText(GetDlgItem(lpwd->hwnd, IDC_SEARCHNAME), NULL);
  227. FreeIcon(lpwd->hwnd);
  228. PropSheet_SetWizButtons(GetParent(lpwd->hwnd), PSWIZB_NEXT);
  229. //
  230. // To make sure that the next button always has the focus, we post
  231. // this message that sets the wiz buttons AFTER we're active. We have
  232. // to do the one above to make sure that Back is disabled to avoid any
  233. // random window where the back button could be hit.
  234. //
  235. PostMessage(lpwd->hwnd, WMPRIV_POKEFOCUS, 0, 0);
  236. }
  237. BOOL_PTR CALLBACK SetupDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
  238. {
  239. NMHDR FAR *lpnm = NULL;
  240. LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  241. LPWIZDATA lpwd = NULL;
  242. if (lpPropSheet)
  243. {
  244. lpwd = (LPWIZDATA)lpPropSheet->lParam;
  245. }
  246. switch(message)
  247. {
  248. case WM_NOTIFY:
  249. lpnm = (NMHDR FAR *)lParam;
  250. if(lpnm)
  251. {
  252. switch(lpnm->code)
  253. {
  254. case PSN_SETACTIVE:
  255. if(lpwd)
  256. {
  257. lpwd->hwnd = hDlg;
  258. SetupSetToDefault(lpwd);
  259. }
  260. break;
  261. case PSN_WIZNEXT:
  262. if(lpwd)
  263. {
  264. SetupNextPressed(lpwd);
  265. SetDlgMsgResult(hDlg, WM_NOTIFY, 0);
  266. }
  267. break;
  268. case PSN_RESET:
  269. if(lpwd)
  270. {
  271. CleanUpWizData(lpwd);
  272. }
  273. break;
  274. default:
  275. return FALSE;
  276. }
  277. }
  278. break;
  279. case WMPRIV_POKEFOCUS:
  280. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
  281. break;
  282. case WM_INITDIALOG:
  283. InitSetupWiz(hDlg, lParam);
  284. break;
  285. case WM_DESTROY:
  286. FreeIcon(hDlg);
  287. break;
  288. default:
  289. return FALSE;
  290. } // end of switch on message
  291. return TRUE;
  292. } // SetupdlgProc