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.

649 lines
17 KiB

  1. //+------------------------------------------------------------------
  2. //
  3. // Project: Windows NT4 DS Client Setup Wizard
  4. //
  5. // Purpose: Installs the Windows NT4 DS Client Files
  6. //
  7. // File: dscsetup.cpp
  8. //
  9. // History: March 1998 Zeyong Xu Created
  10. // Jan 2000 Jeff Jones (JeffJon) Modified
  11. // - changed to be an NT setup
  12. //
  13. //------------------------------------------------------------------
  14. #include <windows.h>
  15. #include <prsht.h>
  16. #include <setupapi.h>
  17. #include <tchar.h>
  18. #include <stdlib.h>
  19. #include "resource.h"
  20. #include "dscsetup.h"
  21. #include "wizard.h"
  22. #include "doinst.h"
  23. SInstallVariables g_sInstVar;
  24. // DllMain Entry
  25. BOOL APIENTRY DllMain( HINSTANCE hInstance,
  26. DWORD ul_reason_for_call,
  27. LPVOID lpReserved
  28. )
  29. {
  30. switch (ul_reason_for_call)
  31. {
  32. case DLL_PROCESS_ATTACH:
  33. case DLL_THREAD_ATTACH:
  34. case DLL_THREAD_DETACH:
  35. case DLL_PROCESS_DETACH:
  36. break;
  37. }
  38. return TRUE;
  39. }
  40. // This is an exported function.
  41. DWORD WINAPI DoDscSetup(LPCSTR lpCmdLine)
  42. {
  43. // initialize the variables of installation
  44. InitVariables();
  45. ParseCmdline(const_cast<PSTR>(lpCmdLine));
  46. //
  47. // Go through setup if we are installing with anything but
  48. // the /a flag
  49. //
  50. if (g_sInstVar.m_bSysDlls || g_sInstVar.m_bWabInst)
  51. {
  52. // create objects
  53. if(!CreateObjects())
  54. return SETUP_ERROR;
  55. // Launch setup wizard
  56. if(!DSCSetupWizard())
  57. {
  58. TCHAR szMessage[MAX_MESSAGE + 1];
  59. TCHAR szTitle[MAX_TITLE + 1];
  60. LoadString(g_sInstVar.m_hInstance,
  61. IDS_ERROR_WIZARD,
  62. szMessage,
  63. MAX_MESSAGE);
  64. LoadString(g_sInstVar.m_hInstance,
  65. IDS_ERROR_TITLE,
  66. szTitle,
  67. MAX_TITLE);
  68. // display a error message - Failure to load Setup Wizard
  69. MessageBox(NULL,
  70. szMessage, // address of text in message box
  71. szTitle, // address of title of message box
  72. MB_OK | MB_TOPMOST | MB_ICONERROR); // style of message box
  73. g_sInstVar.m_nSetupResult = SETUP_ERROR;
  74. }
  75. // destroy objects
  76. DestroyObjects();
  77. if(g_sInstVar.m_nSetupResult == SETUP_SUCCESS &&
  78. !g_sInstVar.m_bQuietMode
  79. #ifdef MERRILL_LYNCH
  80. && !g_sInstVar.m_bNoReboot
  81. #endif
  82. )
  83. {
  84. // prompt reboot
  85. SetupPromptReboot(NULL, // optional, handle to a file queue
  86. NULL, // parent window of this dialog box
  87. FALSE); // optional, do not prompt user);
  88. }
  89. else if(g_sInstVar.m_nSetupResult == SETUP_SUCCESS &&
  90. g_sInstVar.m_bQuietMode
  91. #ifdef MERRILL_LYNCH
  92. && !g_sInstVar.m_bNoReboot
  93. #endif
  94. )
  95. {
  96. HANDLE htoken = INVALID_HANDLE_VALUE;
  97. do
  98. {
  99. // twiddle our process privileges to enable SE_SHUTDOWN_NAME
  100. HRESULT hr = OpenProcessToken(GetCurrentProcess(),
  101. TOKEN_ADJUST_PRIVILEGES,
  102. &htoken);
  103. if (FAILED(hr))
  104. {
  105. break;
  106. }
  107. LUID luid;
  108. memset(&luid, 0, sizeof(luid));
  109. hr = LookupPrivilegeValue(0, SE_SHUTDOWN_NAME, &luid);
  110. if (FAILED(hr))
  111. {
  112. break;
  113. }
  114. TOKEN_PRIVILEGES privs;
  115. memset(&privs, 0, sizeof(privs));
  116. privs.PrivilegeCount = 1;
  117. privs.Privileges[0].Luid = luid;
  118. privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  119. hr = AdjustTokenPrivileges(htoken, 0, &privs, 0, 0, 0);
  120. if (FAILED(hr))
  121. {
  122. break;
  123. }
  124. hr = ExitWindowsEx(EWX_REBOOT, 0);
  125. if (FAILED(hr))
  126. {
  127. break;
  128. }
  129. }
  130. while (0);
  131. if (htoken != INVALID_HANDLE_VALUE)
  132. {
  133. CloseHandle(htoken);
  134. }
  135. }
  136. }
  137. else
  138. {
  139. //
  140. // Setup was run with the /a flag. This means we
  141. // don't want to show the UI and let the adsix86.inf
  142. // handle the install for us
  143. //
  144. if (!LaunchProcess(STR_INSTALL_ADSIWREMOVE))
  145. {
  146. g_sInstVar.m_nSetupResult = SETUP_ERROR;
  147. }
  148. }
  149. return g_sInstVar.m_nSetupResult;
  150. }
  151. VOID ParseCmdline(LPSTR lpCmdLine)
  152. {
  153. PCTSTR ptszTok = _tcstok(lpCmdLine, _T(" "));
  154. do
  155. {
  156. if (ptszTok != NULL)
  157. {
  158. if (_tcsicmp(ptszTok, _T("/q")) == 0)
  159. {
  160. g_sInstVar.m_bQuietMode = TRUE;
  161. }
  162. if (_tcsicmp(ptszTok, _T("/a")) == 0)
  163. {
  164. g_sInstVar.m_bWabInst = FALSE;
  165. g_sInstVar.m_bSysDlls = FALSE;
  166. }
  167. if (_tcsicmp(ptszTok, _T("/d")) == 0)
  168. {
  169. g_sInstVar.m_bWabInst = FALSE;
  170. }
  171. #ifdef MERRILL_LYNCH
  172. if (_tcsicmp(ptszTok, _T("/n")) == 0)
  173. {
  174. g_sInstVar.m_bNoReboot = TRUE;
  175. }
  176. #endif
  177. }
  178. ptszTok = _tcstok(NULL, _T(" "));
  179. } while (ptszTok != NULL);
  180. }
  181. // initialize the variables of installation
  182. VOID InitVariables()
  183. {
  184. g_sInstVar.m_hInstance = GetModuleHandle(STR_DLL_NAME);
  185. g_sInstVar.m_hInstallThread = NULL;
  186. g_sInstVar.m_uTimerID = 0;
  187. g_sInstVar.m_hBigBoldFont = NULL;
  188. g_sInstVar.m_hProgress = NULL;
  189. g_sInstVar.m_hFileNameItem = NULL;
  190. g_sInstVar.m_bDCOMInstalled = FALSE;
  191. g_sInstVar.m_bQuietMode = FALSE;
  192. g_sInstVar.m_bWabInst = TRUE;
  193. g_sInstVar.m_bSysDlls = TRUE;
  194. #ifdef MERRILL_LYNCH
  195. g_sInstVar.m_bNoReboot = FALSE;
  196. #endif
  197. g_sInstVar.m_nSetupResult = SETUP_SUCCESS;
  198. // get source path
  199. GetModuleFileName(g_sInstVar.m_hInstance,
  200. g_sInstVar.m_szSourcePath,
  201. MAX_PATH);
  202. *(_tcsrchr(g_sInstVar.m_szSourcePath, CHAR_BACKSLASH) + 1) = TEXT('\0'); // Strip setup.exe off path
  203. }
  204. // start setup wizard
  205. BOOL DSCSetupWizard()
  206. {
  207. PROPSHEETHEADER psh;
  208. PROPSHEETPAGE psPage[SIZE_WIZARD_PAGE];
  209. int i = 0;
  210. //
  211. // Setup the Welcome page
  212. //
  213. i=0;
  214. ZeroMemory(&psPage[i],sizeof(PROPSHEETPAGE));
  215. psPage[i].dwSize = sizeof(PROPSHEETPAGE);
  216. psPage[i].dwFlags = PSP_USETITLE | PSP_HIDEHEADER;
  217. psPage[i].hInstance = g_sInstVar.m_hInstance;
  218. psPage[i].pszTemplate = MAKEINTRESOURCE(IDD_WELCOME);
  219. psPage[i].pfnDlgProc = (DLGPROC) WelcomeDialogProc;
  220. psPage[i].lParam = (LPARAM) 0;
  221. psPage[i].pszTitle = MAKEINTRESOURCE(IDS_WIZARD_TITLE);
  222. /* ntbug#337931: remove license page
  223. //
  224. // Setup the License Page
  225. //
  226. i++;
  227. ZeroMemory(&psPage[i],sizeof(PROPSHEETPAGE));
  228. psPage[i].dwSize = sizeof(PROPSHEETPAGE);
  229. psPage[i].dwFlags = PSP_USETITLE |
  230. PSP_USEHEADERTITLE |
  231. PSP_USEHEADERSUBTITLE;
  232. psPage[i].hInstance = g_sInstVar.m_hInstance;
  233. psPage[i].pszTemplate = MAKEINTRESOURCE(IDD_LICENSE);
  234. psPage[i].pfnDlgProc = (DLGPROC) LicenseDialogProc;
  235. psPage[i].lParam = (LPARAM) 0;
  236. psPage[i].pszTitle = MAKEINTRESOURCE(IDS_WIZARD_TITLE);
  237. psPage[i].pszHeaderTitle = MAKEINTRESOURCE(IDS_HEADERTITLE_LICENSE);
  238. psPage[i].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_HEADERSUBTITLE_LICENSE);
  239. */
  240. //
  241. // Setup the Select Page
  242. //
  243. i++;
  244. ZeroMemory(&psPage[i],sizeof(PROPSHEETPAGE));
  245. psPage[i].dwSize = sizeof(PROPSHEETPAGE);
  246. psPage[i].dwFlags = PSP_USETITLE |
  247. PSP_USEHEADERTITLE |
  248. PSP_USEHEADERSUBTITLE;
  249. psPage[i].hInstance = g_sInstVar.m_hInstance;
  250. psPage[i].pszTemplate = MAKEINTRESOURCE(IDD_CONFIRM);
  251. psPage[i].pfnDlgProc = (DLGPROC) ConfirmDialogProc;
  252. psPage[i].lParam = (LPARAM) 0;
  253. psPage[i].pszTitle = MAKEINTRESOURCE(IDS_WIZARD_TITLE);
  254. psPage[i].pszHeaderTitle = MAKEINTRESOURCE(IDS_HEADERTITLE_CONFIRM);
  255. psPage[i].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_HEADERSUBTITLE_CONFIRM);
  256. //
  257. // Setup the Confirm Page
  258. //
  259. i++;
  260. ZeroMemory(&psPage[i],sizeof(PROPSHEETPAGE));
  261. psPage[i].dwSize = sizeof(PROPSHEETPAGE);
  262. psPage[i].dwFlags = PSP_USETITLE |
  263. PSP_USEHEADERTITLE |
  264. PSP_USEHEADERSUBTITLE;
  265. psPage[i].hInstance = g_sInstVar.m_hInstance;
  266. psPage[i].pszTemplate = MAKEINTRESOURCE(IDD_INSTALL);
  267. psPage[i].pfnDlgProc = (DLGPROC) InstallDialogProc;
  268. psPage[i].lParam = (LPARAM) 0;
  269. psPage[i].pszTitle = MAKEINTRESOURCE(IDS_WIZARD_TITLE);
  270. psPage[i].pszHeaderTitle = MAKEINTRESOURCE(IDS_HEADERTITLE_INSTALL);
  271. psPage[i].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_HEADERSUBTITLE_INSTALL);
  272. //
  273. // Setup the Completion page
  274. //
  275. i++;
  276. ZeroMemory(&psPage[i],sizeof(PROPSHEETPAGE));
  277. psPage[i].dwSize = sizeof(PROPSHEETPAGE);
  278. psPage[i].dwFlags = PSP_USETITLE | PSP_HIDEHEADER;
  279. psPage[i].hInstance = g_sInstVar.m_hInstance;
  280. psPage[i].pszTemplate = MAKEINTRESOURCE(IDD_COMPLETION);
  281. psPage[i].pfnDlgProc = (DLGPROC) CompletionDialogProc;
  282. psPage[i].lParam = (LPARAM) 0;
  283. psPage[i].pszTitle = MAKEINTRESOURCE(IDS_WIZARD_TITLE);
  284. //
  285. // Setup the wizard
  286. //
  287. ZeroMemory(&psh,sizeof(PROPSHEETHEADER));
  288. psh.dwSize = sizeof(PROPSHEETHEADER);
  289. // Windows 98 with 16 color display mode crashes when PSH_STRETCHWATERMARK flag is on.
  290. psh.dwFlags = PSH_USEICONID |
  291. PSH_PROPSHEETPAGE |
  292. PSH_WIZARD97 |
  293. PSH_WATERMARK |
  294. PSH_HEADER; // | PSH_STRETCHWATERMARK;
  295. psh.pszIcon = MAKEINTRESOURCE(IDI_ICON_APP);
  296. psh.hInstance = g_sInstVar.m_hInstance;
  297. psh.pszCaption = MAKEINTRESOURCE(IDS_WIZARD_TITLE);;
  298. psh.nStartPage = 0;
  299. psh.nPages = SIZE_WIZARD_PAGE;
  300. psh.ppsp = (LPCPROPSHEETPAGE) &psPage;
  301. //
  302. // Run the wizard
  303. //
  304. if(g_sInstVar.m_bQuietMode)
  305. {
  306. if(!CheckDiskSpace())
  307. return FALSE;
  308. psh.nStartPage = 2;
  309. }
  310. else
  311. psh.nStartPage = 0;
  312. if( PropertySheet(&psh) < 0 ) // failure to load wizard
  313. {
  314. return FALSE;
  315. }
  316. //
  317. // Because SetWindowLongPtr(hWnd, DWL_MSGRESULT, IDD_COMPLETION)
  318. // doesn't work on Win95 (when users click Cancel, the wizard can't
  319. // be routed to the Completion page), I added the following code to
  320. // open the Completion page
  321. //
  322. if(!g_sInstVar.m_bQuietMode)
  323. {
  324. psh.nStartPage = 3;
  325. if( PropertySheet(&psh) < 0 ) // failure to load wizard
  326. {
  327. return FALSE;
  328. }
  329. }
  330. return TRUE;
  331. }
  332. // check for DCOM installed
  333. void CheckDCOMInstalled()
  334. {
  335. HKEY hSubKey;
  336. // check if IE 4.0 has been installed
  337. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT,
  338. STR_DCOM_REGKEY,
  339. 0,
  340. KEY_READ,
  341. &hSubKey) )
  342. {
  343. g_sInstVar.m_bDCOMInstalled = TRUE;
  344. RegCloseKey(hSubKey);
  345. }
  346. }
  347. // gets Disk Free space
  348. DWORD64 SetupGetDiskFreeSpace()
  349. {
  350. DWORD dwSectorsPerCluster;
  351. DWORD dwBytesPerSector;
  352. DWORD dwNumberOfFreeClusters;
  353. DWORD dwTotalNumberOfClusters;
  354. DWORD64 d64FreeSpace = 0;
  355. TCHAR szPathName[MAX_PATH + 1]; // address of root path
  356. if(GetSystemDirectory(szPathName, // address of buffer for system directory
  357. MAX_PATH)) // size of directory buffer);
  358. {
  359. if ( szPathName[1] == TEXT(':'))
  360. {
  361. // this is a drive letter
  362. // assume it is of for d:backslash
  363. szPathName[3] = TEXT('\0');
  364. //get free space, GetDiskFreeSpaceEx() don't support in older Win95
  365. if (GetDiskFreeSpace(szPathName, // address of root path
  366. &dwSectorsPerCluster, // address of sectors per cluster
  367. &dwBytesPerSector, // address of bytes per sector
  368. &dwNumberOfFreeClusters, // address of number of free clusters
  369. &dwTotalNumberOfClusters)) // address of total number of clusters
  370. {
  371. // calc total size
  372. d64FreeSpace = DWORD64(dwSectorsPerCluster)
  373. * dwBytesPerSector
  374. * dwNumberOfFreeClusters;
  375. }
  376. }
  377. }
  378. return d64FreeSpace;
  379. }
  380. // check if DSClient has been installed
  381. BOOL CheckDSClientInstalled()
  382. {
  383. HKEY hSubKey;
  384. BOOL bResult = FALSE;
  385. // open reg key of DS Client
  386. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  387. STR_DSCLIENT_REGKEY,
  388. 0,
  389. KEY_ALL_ACCESS,
  390. &hSubKey) )
  391. {
  392. bResult = TRUE;
  393. RegCloseKey(hSubKey);
  394. }
  395. return bResult;
  396. }
  397. /* ntbug#337931: remove license page
  398. // load "License Agreement" text from license file
  399. BOOL LoadLicenseFile(HWND hDlg)
  400. {
  401. BOOL bReturn = FALSE;
  402. TCHAR szTitle[MAX_TITLE + 1];
  403. TCHAR szTempBuffer[MAX_MESSAGE + 1];
  404. TCHAR szLicenseFile[MAX_PATH + 1];
  405. TCHAR szReturnTextBuffer[MAX_MESSAGE + 1];
  406. LPTSTR lpszLicenseText = NULL;
  407. HANDLE hFile;
  408. DWORD dwNumberOfBytesRead, dwFileSize;
  409. //
  410. // Determine where we are installing from
  411. // and specific the license file there
  412. //
  413. lstrcpy(szLicenseFile, g_sInstVar.m_szSourcePath);
  414. lstrcat(szLicenseFile, STR_LICENSEFILE);
  415. // Open License file
  416. hFile = CreateFile(szLicenseFile, // pointer to name of the file
  417. GENERIC_READ, // access (read-write) mode
  418. FILE_SHARE_READ, // share mode
  419. NULL, // pointer to security descriptor
  420. OPEN_EXISTING, // how to create
  421. FILE_ATTRIBUTE_NORMAL, // file attributes
  422. NULL); // handle to file with attributes to copy
  423. if(INVALID_HANDLE_VALUE != hFile)
  424. {
  425. // Read License file into string
  426. // setup memory, get file size in bytes
  427. dwFileSize = GetFileSize (hFile, NULL) ;
  428. if (dwFileSize != 0xFFFFFFFF)
  429. {
  430. // this program is for Win98/95, it will work in MBCS not UNICODE
  431. // this code is for ANSI US version, license.txt file uses the single byte character set(ANSI)
  432. // if doing locolization, license.txt file should use the double byte character set(DBCS/MBCS)
  433. lpszLicenseText = (LPTSTR) calloc (dwFileSize + sizeof(TCHAR),
  434. sizeof(BYTE));
  435. }
  436. if(lpszLicenseText)
  437. {
  438. //read file
  439. if (ReadFile(hFile, // handle of file to read
  440. lpszLicenseText, // address of buffer that receives data
  441. dwFileSize, // number of bytes to read
  442. &dwNumberOfBytesRead, // address of number of bytes read
  443. NULL)) // address of structure for data
  444. {
  445. // display license on dialog
  446. SetDlgItemText(hDlg, IDC_LICENSE_TEXT, lpszLicenseText);
  447. bReturn = TRUE;
  448. }
  449. // so free the memory
  450. free(lpszLicenseText);
  451. }
  452. //close file handle
  453. CloseHandle(hFile);
  454. }
  455. if(!bReturn)
  456. {
  457. // load string
  458. LoadString(g_sInstVar.m_hInstance,
  459. IDS_ERROR_TITLE,
  460. szTitle,
  461. MAX_TITLE);
  462. LoadString(g_sInstVar.m_hInstance,
  463. IDS_ERROR_LICENSEFILE,
  464. szTempBuffer,
  465. MAX_MESSAGE);
  466. wsprintf(szReturnTextBuffer,
  467. TEXT("%s %s"),
  468. szTempBuffer,
  469. szLicenseFile);
  470. MessageBox(hDlg,
  471. szReturnTextBuffer,
  472. szTitle,
  473. MB_OK | MB_TOPMOST | MB_ICONERROR);
  474. }
  475. return bReturn;
  476. }
  477. */
  478. // check disk space
  479. BOOL CheckDiskSpace()
  480. {
  481. BOOL bResult = TRUE;
  482. TCHAR szString[MAX_MESSAGE + MAX_TITLE + 1];
  483. TCHAR szTitle[MAX_TITLE + 1];
  484. TCHAR szMessage[MAX_MESSAGE + 1];
  485. if(SIZE_TOTAL*MB_TO_BYTE > SetupGetDiskFreeSpace())
  486. {
  487. // load string
  488. LoadString(g_sInstVar.m_hInstance,
  489. IDS_ERROR_NODISKSPACE,
  490. szMessage,
  491. MAX_MESSAGE);
  492. LoadString(g_sInstVar.m_hInstance,
  493. IDS_ERROR_TITLE,
  494. szTitle,
  495. MAX_TITLE);
  496. wsprintf(szString,
  497. TEXT("%s %d MB."),
  498. szMessage,
  499. SIZE_TOTAL);
  500. MessageBox(NULL,
  501. szString,
  502. szTitle,
  503. MB_OK | MB_TOPMOST | MB_ICONERROR);
  504. bResult = FALSE;
  505. }
  506. return bResult;
  507. }
  508. // create objects
  509. BOOL CreateObjects()
  510. {
  511. try
  512. {
  513. // initialize the synchronizing object
  514. InitializeCriticalSection(&g_sInstVar.m_oCriticalSection);
  515. }
  516. catch(...)
  517. {
  518. return FALSE;
  519. }
  520. // create a 12 pt big font
  521. CreateBigFont();
  522. return TRUE;
  523. }
  524. // destroy objects
  525. VOID DestroyObjects()
  526. {
  527. // wait to finish the runing setup process
  528. if(g_sInstVar.m_hInstallThread)
  529. {
  530. // wait the installation thread to finish
  531. WaitForSingleObject(g_sInstVar.m_hInstallThread,INFINITE);
  532. CloseHandle(g_sInstVar.m_hInstallThread);
  533. }
  534. // delete the synchronizing object
  535. DeleteCriticalSection(&g_sInstVar.m_oCriticalSection);
  536. //Frees up the space used by loading the fonts
  537. if( g_sInstVar.m_hBigBoldFont )
  538. {
  539. DeleteObject( g_sInstVar.m_hBigBoldFont );
  540. }
  541. }
  542. //create a big font for dialog title
  543. VOID CreateBigFont()
  544. {
  545. NONCLIENTMETRICS ncm;
  546. LOGFONT BigBoldLogFont;
  547. HDC hdc;
  548. // Create the fonts we need based on the dialog font
  549. ZeroMemory(&ncm,sizeof(NONCLIENTMETRICS));
  550. ncm.cbSize = sizeof(NONCLIENTMETRICS);
  551. SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
  552. BigBoldLogFont = ncm.lfMessageFont;
  553. BigBoldLogFont.lfWeight = FW_BOLD;
  554. hdc = GetDC(NULL);
  555. if( hdc )
  556. {
  557. BigBoldLogFont.lfHeight = 0 -
  558. (GetDeviceCaps(hdc,LOGPIXELSY) *
  559. SIZE_TITLE_FONT /
  560. 72);
  561. g_sInstVar.m_hBigBoldFont = CreateFontIndirect(&BigBoldLogFont);
  562. ReleaseDC(NULL,hdc);
  563. }
  564. }