Leaked source code of windows server 2003
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.

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