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.

663 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: doinst.cpp
  8. //
  9. // History: Aug. 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 <setupapi.h>
  16. #include <advpub.h>
  17. #include "resource.h"
  18. #include "dscsetup.h"
  19. #include "wizard.h"
  20. #include "doinst.h"
  21. extern SInstallVariables g_sInstVar;
  22. // do installation
  23. DWORD DoInstallation(HWND hWnd)
  24. {
  25. if(g_sInstVar.m_nSetupResult == SETUP_SUCCESS)
  26. {
  27. // set the fake progressbar for DCOM and WAB nstall
  28. g_sInstVar.m_uTimerID = SetTimer(hWnd,
  29. 1,
  30. 1000, // 1 seconds
  31. Timer1Proc);
  32. // do the custom action of NTLMv2
  33. if(!DoEncSChannel())
  34. g_sInstVar.m_nSetupResult = SETUP_ERROR;
  35. // stop the fake progressbar
  36. if(g_sInstVar.m_uTimerID)
  37. KillTimer(hWnd, g_sInstVar.m_uTimerID);
  38. // install adsi
  39. if (!LaunchProcess(STR_INSTALL_ADSI))
  40. {
  41. g_sInstVar.m_nSetupResult = SETUP_ERROR;
  42. }
  43. // install dsclient
  44. if(g_sInstVar.m_nSetupResult == SETUP_SUCCESS)
  45. g_sInstVar.m_nSetupResult = LaunchINFInstall(hWnd);
  46. }
  47. return g_sInstVar.m_nSetupResult;
  48. }
  49. VOID CALLBACK Timer1Proc(HWND hwnd, // handle of window for timer messages
  50. UINT uMsg, // WM_TIMER message
  51. UINT idEvent, // timer identifier
  52. DWORD dwTime) // current system time
  53. {
  54. static int nCount = 0;
  55. if(nCount > 100)
  56. nCount = 100;
  57. // set the fake progressbar
  58. SendMessage (g_sInstVar.m_hProgress, PBM_SETPOS, (WPARAM) nCount, 0);
  59. nCount ++;
  60. }
  61. // This routine will do an installation based on those settings
  62. // using the setupapi.dll
  63. INT LaunchINFInstall( HWND hWnd )
  64. {
  65. TCHAR szInfFileName[MAX_PATH + 1];
  66. TCHAR szInstallSection[MAX_TITLE];
  67. BOOL bResult = FALSE;
  68. // Context for my call back routine
  69. HSPFILEQ hFileQueue;
  70. HINF hInf;
  71. PVOID pDefaultContext;
  72. //
  73. // Get inf handle
  74. // must know where the inf is located
  75. // SetupOpenInfFile will only look in windows\inf by default
  76. //
  77. // ISSUE-2002/03/12-JeffJon-Bad use of dangerous API. m_szSourcePath may
  78. // not be NULL terminated and/or it may be larger than the size allocated
  79. // for szInfFileName
  80. lstrcpy(szInfFileName, g_sInstVar.m_szSourcePath);
  81. // ISSUE-2002/03/12-JeffJon-Bad use of dangerous API. m_szSourcePath + STR_DSCLIENT_INF
  82. // may be larger than szInfFileName
  83. lstrcat(szInfFileName, STR_DSCLIENT_INF);
  84. hInf = SetupOpenInfFile(szInfFileName, // If path,needs full path, else looks in %windir%\inf
  85. NULL, // Inf Type, matches Class in [Version] section SetupClass=SAMPLE
  86. INF_STYLE_WIN4, // or INF_STYLE_OLDNT
  87. NULL); // Line where error occurs if inf is has a problem
  88. if (hInf == INVALID_HANDLE_VALUE)
  89. return SETUP_ERROR;
  90. //
  91. // Create a Setup file queue and initialize the default Setup
  92. // queue callback routine.
  93. //
  94. hFileQueue = SetupOpenFileQueue();
  95. if(hFileQueue == INVALID_HANDLE_VALUE)
  96. {
  97. SetupCloseInfFile(hInf);
  98. return SETUP_ERROR;
  99. }
  100. // using SetupInitDefaultQueueCallback.
  101. SendMessage (g_sInstVar.m_hProgress, PBM_SETPOS, (WPARAM) 0, 0);
  102. pDefaultContext = SetupInitDefaultQueueCallbackEx(hWnd, // HWND of owner window
  103. NULL, // HWND of alternate progress dialog which receives
  104. 0, // Message sent to above window indicating a progress message
  105. 0, // DWORD Reserved
  106. NULL); // PVOID Reserved
  107. if(!pDefaultContext)
  108. {
  109. // Close the queue and the inf file and return
  110. SetupCloseFileQueue(hFileQueue);
  111. SetupCloseInfFile(hInf);
  112. return SETUP_ERROR;
  113. }
  114. // ISSUE-2002/03/12-JeffJon-Bad use of dangerous API. At minimum should
  115. // use an n version so as not to exceed szInstallSection. szInstallSection
  116. // was not initialized with zeros
  117. lstrcpy (szInstallSection, STR_INSTALL_SECTIONNT4);
  118. //
  119. // Queue file operations and commit the queue.
  120. //
  121. bResult = SetupInstallFilesFromInfSection(hInf, // HINF that has the directory ids set above
  122. NULL, // layout.inf if you have one, this a convient
  123. hFileQueue, // Queue to add files to
  124. szInstallSection, // SectionName,
  125. g_sInstVar.m_szSourcePath, // Path where the source files are located
  126. SP_COPY_NEWER );
  127. //
  128. // All the files for each component are now in one queue
  129. // now we commit it to start the copy ui, this way the
  130. // user has one long copy progress dialog--and for a big install
  131. // can go get the cup of coffee
  132. if(bResult)
  133. bResult = SetupCommitFileQueue(hWnd, // Owner
  134. hFileQueue, // Queue with the file list
  135. QueueCallbackProc, // This is our handler, it calls the default for us
  136. pDefaultContext); // Pointer to resources allocated with SetupInitDefaultQueueCallback/Ex
  137. if (!bResult || (g_sInstVar.m_nSetupResult == SETUP_CANCEL))
  138. {
  139. SetupTermDefaultQueueCallback(pDefaultContext);
  140. SetupCloseFileQueue(hFileQueue);
  141. SetupCloseInfFile(hInf);
  142. if(g_sInstVar.m_nSetupResult == SETUP_CANCEL)
  143. return SETUP_CANCEL;
  144. else
  145. return SETUP_ERROR;
  146. }
  147. //
  148. // NOTE: you can do the entire install
  149. // for a section with this api but in this case
  150. // we build the file list conditionally and
  151. // do only out ProductInstall section for registy stuff
  152. // Also using SPINST_FILES will do the files
  153. // as above but only one section at a time
  154. // so the progress bar would keep completing and starting over
  155. // SPINST_ALL does files, registry and inis
  156. //
  157. bResult = SetupInstallFromInfSection(hWnd,
  158. hInf,
  159. szInstallSection,
  160. SPINST_INIFILES | SPINST_REGISTRY,
  161. HKEY_LOCAL_MACHINE,
  162. NULL, //m_szSourcePath, // Path where the source files are located
  163. 0, //SP_COPY_NEWER,
  164. NULL, //(PSP_FILE_CALLBACK) QueueCallbackProc,
  165. NULL, //&MyInstallData,
  166. NULL,
  167. NULL);
  168. //
  169. // We're done so free the context, close the queue,
  170. // and release the inf handle
  171. //
  172. SetupTermDefaultQueueCallback(pDefaultContext);
  173. SetupCloseFileQueue(hFileQueue);
  174. SetupCloseInfFile(hInf);
  175. if (g_sInstVar.m_bSysDlls)
  176. {
  177. //
  178. // register OCX file
  179. //
  180. if(!RegisterOCX())
  181. {
  182. return SETUP_ERROR;
  183. }
  184. }
  185. //
  186. // The custom registry action after dsclient.inf by Chandana Surlu
  187. //
  188. DoDsclientReg();
  189. SendMessage (g_sInstVar.m_hProgress, PBM_SETPOS, (WPARAM) 100, 0);
  190. InstallFinish(FALSE);
  191. return SETUP_SUCCESS;
  192. }
  193. /*---------------------------------------------------------------------*/
  194. /*---------------------------------------------------------------------*/
  195. UINT CALLBACK QueueCallbackProc(PVOID pDefaultContext,
  196. UINT Notification,
  197. UINT_PTR Param1,
  198. UINT_PTR Param2)
  199. {
  200. static INT snFilesCopied;
  201. // synchronizing user cancel
  202. // REVIEWED-2002/03/12-JeffJon-We want to allow the exception to propogate
  203. // out.
  204. EnterCriticalSection(&g_sInstVar.m_oCriticalSection);
  205. LeaveCriticalSection(&g_sInstVar.m_oCriticalSection);
  206. //instaniate dialog first time
  207. if (g_sInstVar.m_nSetupResult == SETUP_CANCEL)
  208. {
  209. SetLastError (ERROR_CANCELLED);
  210. return FILEOP_ABORT;
  211. }
  212. switch (Notification)
  213. {
  214. case SPFILENOTIFY_STARTQUEUE:
  215. case SPFILENOTIFY_ENDQUEUE:
  216. return FILEOP_DOIT;
  217. case SPFILENOTIFY_STARTCOPY:
  218. // update file name item
  219. SetWindowText(g_sInstVar.m_hFileNameItem,
  220. ((PFILEPATHS) Param1)->Target);
  221. break;
  222. case SPFILENOTIFY_ENDCOPY:
  223. snFilesCopied++;
  224. // update dialog file progress with message
  225. if ((snFilesCopied + 1)>= NUM_FILES_TOTAL)
  226. {
  227. SendMessage (g_sInstVar.m_hProgress,
  228. PBM_SETPOS,
  229. (WPARAM) 100,
  230. 0);
  231. }
  232. else
  233. {
  234. SendMessage (g_sInstVar.m_hProgress,
  235. PBM_SETPOS,
  236. (WPARAM) ((float)snFilesCopied /
  237. (float)NUM_FILES_TOTAL * 100),
  238. 0);
  239. }
  240. break;
  241. default:
  242. break;
  243. }
  244. return SetupDefaultQueueCallback(pDefaultContext,
  245. Notification,
  246. Param1,
  247. Param2);
  248. }
  249. VOID InstallFinish(BOOL nShow)
  250. {
  251. // ISSUE-2002/03/12-JeffJon-Should call WinExec with
  252. // the full path to the exe
  253. if(nShow)
  254. WinExec("grpconv -o", SW_SHOWNORMAL);
  255. else
  256. WinExec("grpconv -o", SW_HIDE);
  257. }
  258. // launch Inf file to install this component
  259. BOOL LaunchProcess(LPTSTR lpCommandLine)
  260. {
  261. BOOL bResult = FALSE;
  262. STARTUPINFO si;
  263. PROCESS_INFORMATION pi;
  264. // its console window will be invisible to the user.
  265. ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
  266. ZeroMemory(&si,sizeof(STARTUPINFO));
  267. si.cb = sizeof (STARTUPINFO);
  268. si.dwFlags = STARTF_USESHOWWINDOW;
  269. si.wShowWindow = SW_HIDE; // HideWindow
  270. // ISSUE-2002/03/12-JeffJon-Should call CreateProcess with
  271. // the full path to the exe
  272. if(CreateProcess( NULL,
  273. lpCommandLine,
  274. NULL,
  275. NULL,
  276. FALSE,
  277. 0,
  278. NULL,
  279. NULL,
  280. &si,
  281. &pi ) )
  282. {
  283. // wait to finish the runing setup process
  284. WaitForSingleObject(pi.hProcess,INFINITE);
  285. // close process handle
  286. if (pi.hProcess && pi.hProcess != INVALID_HANDLE_VALUE)
  287. {
  288. CloseHandle (pi.hProcess) ;
  289. }
  290. if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
  291. {
  292. CloseHandle (pi.hThread) ;
  293. }
  294. bResult = TRUE;
  295. }
  296. return bResult;
  297. }
  298. // register OCX file
  299. BOOL RegisterOCX()
  300. {
  301. TCHAR szSystem[MAX_PATH + 1];
  302. TCHAR szTemp[MAX_PATH + 1];
  303. TCHAR szCmdline[MAX_PATH + 1];
  304. BOOL bSuccess = TRUE;
  305. if(!GetSystemDirectory(szSystem, MAX_PATH))
  306. return FALSE;
  307. // ISSUE-2002/03/12-JeffJon-Bad use of dangerous API.
  308. // Should consider using the strsafe inline APIs
  309. wsprintf(szTemp,
  310. TEXT("%s%s%s"),
  311. szSystem,
  312. STR_REGISTER_REGSVR32_S_EXE,
  313. szSystem);
  314. //
  315. // REVIEW_JEFFJON : we are not going to register it here
  316. // Instead we are going to set the RunOnce regkey
  317. // to register the dlls on reboot
  318. //
  319. if (g_sInstVar.m_bWabInst)
  320. {
  321. // register dsfolder.dll
  322. // ISSUE-2002/03/12-JeffJon-Bad use of dangerous API.
  323. // Should consider using the strsafe inline APIs
  324. wsprintf(szCmdline,
  325. TEXT("%s%s %s%s %s%s %s%s %s%s"),
  326. szTemp,
  327. STR_REGISTER_DSFOLDER_DLL,
  328. szSystem,
  329. STR_REGISTER_DSUIEXT_DLL,
  330. szSystem,
  331. STR_REGISTER_DSQUERY_DLL,
  332. szSystem,
  333. STR_REGISTER_CMNQUERY_DLL,
  334. szSystem,
  335. STR_REGISTER_DSPROP_DLL);
  336. ULONG WinError = 0;
  337. HKEY RunOnceKey = NULL;
  338. ULONG Size = 0;
  339. ULONG Type = REG_SZ;
  340. DWORD dwDisp = 0;
  341. // open reg key
  342. WinError = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  343. RUNONCE_KEY,
  344. 0,
  345. NULL,
  346. REG_OPTION_NON_VOLATILE,
  347. KEY_ALL_ACCESS,
  348. NULL,
  349. &RunOnceKey,
  350. &dwDisp);
  351. if (WinError == ERROR_SUCCESS)
  352. {
  353. UINT BufferSize = strlen(szCmdline);
  354. BufferSize++;
  355. WinError = RegSetValueEx( RunOnceKey,
  356. REG_DSUI_VALUE,
  357. 0,
  358. Type,
  359. (PUCHAR)szCmdline,
  360. BufferSize);
  361. if (WinError != ERROR_SUCCESS && bSuccess)
  362. {
  363. bSuccess = FALSE;
  364. }
  365. //
  366. // Run wabinst.exe
  367. //
  368. // ISSUE-2002/03/12-JeffJon-Bad use of dangerous API.
  369. // Should consider using the strsafe inline APIs
  370. wsprintf(szCmdline,
  371. TEXT("%s%s"),
  372. szSystem,
  373. STR_RUN_WABINST_EXE);
  374. if (!LaunchProcess(szCmdline))
  375. {
  376. bSuccess = FALSE;
  377. }
  378. }
  379. else
  380. {
  381. bSuccess = FALSE;
  382. }
  383. if (RunOnceKey)
  384. {
  385. RegCloseKey(RunOnceKey);
  386. }
  387. }
  388. return bSuccess;
  389. }
  390. // The custom registry action after dsclient.inf by Chandana Surlu
  391. VOID DoDsclientReg()
  392. {
  393. ULONG WinError = 0;
  394. HKEY ProvidersKey = NULL;
  395. ULONG Size = 0;
  396. ULONG Type = REG_SZ;
  397. ULONG BufferSize = 0;
  398. LPSTR StringToBeWritten = NULL;
  399. DWORD dwDisp;
  400. BOOL bSuccess = FALSE;
  401. // open reg key
  402. WinError = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  403. SECURITY_PROVIDERS_KEY,
  404. 0,
  405. NULL,
  406. REG_OPTION_NON_VOLATILE,
  407. KEY_ALL_ACCESS,
  408. NULL,
  409. &ProvidersKey,
  410. &dwDisp);
  411. if (WinError != ERROR_SUCCESS)
  412. {
  413. if (WinError == ERROR_FILE_NOT_FOUND)
  414. {
  415. BufferSize = sizeof(NEGOTIAT);
  416. StringToBeWritten= (LPSTR) LocalAlloc(0,BufferSize);
  417. if (StringToBeWritten)
  418. {
  419. // ISSUE-2002/03/12-JeffJon-Bad use of dangerous API.
  420. // Should consider using the strsafe inline APIs
  421. strcpy (StringToBeWritten, NEGOTIAT);
  422. bSuccess = TRUE;
  423. }
  424. }
  425. }
  426. else
  427. {
  428. WinError = RegQueryValueEx(ProvidersKey,
  429. SECURITY_PROVIDERS_VALUE,
  430. 0,
  431. &Type,
  432. NULL,
  433. &Size);
  434. if ( WinError == ERROR_SUCCESS)
  435. {
  436. BufferSize = Size + sizeof(COMMA_BLANK) + sizeof(NEGOTIAT);
  437. StringToBeWritten= (LPSTR) LocalAlloc(0,BufferSize);
  438. if (StringToBeWritten)
  439. {
  440. WinError = RegQueryValueEx(ProvidersKey,
  441. SECURITY_PROVIDERS_VALUE,
  442. 0,
  443. &Type,
  444. (PUCHAR) StringToBeWritten,
  445. &Size);
  446. if ( WinError == ERROR_SUCCESS)
  447. {
  448. if (NULL == strstr(StringToBeWritten, NEGOTIAT))
  449. {
  450. // ISSUE-2002/03/12-JeffJon-Bad use of dangerous API.
  451. // Should consider using the strsafe inline APIs
  452. strcat (StringToBeWritten, COMMA_BLANK);
  453. strcat (StringToBeWritten, NEGOTIAT);
  454. bSuccess = TRUE;
  455. }
  456. }
  457. }
  458. }
  459. else if (WinError == ERROR_FILE_NOT_FOUND)
  460. {
  461. BufferSize = sizeof(NEGOTIAT) + sizeof(CHAR);
  462. StringToBeWritten= (LPSTR) LocalAlloc(0,BufferSize);
  463. if (StringToBeWritten)
  464. {
  465. // ISSUE-2002/03/12-JeffJon-Bad use of dangerous API.
  466. // Should consider using the strsafe inline APIs
  467. strcpy (StringToBeWritten, NEGOTIAT);
  468. Type = REG_SZ;
  469. bSuccess = TRUE;
  470. }
  471. }
  472. }
  473. if(bSuccess)
  474. {
  475. BufferSize = strlen(StringToBeWritten);
  476. BufferSize++;
  477. WinError = RegSetValueEx( ProvidersKey,
  478. SECURITY_PROVIDERS_VALUE,
  479. 0,
  480. Type,
  481. (PUCHAR)StringToBeWritten,
  482. BufferSize);
  483. }
  484. if (ProvidersKey)
  485. {
  486. RegCloseKey(ProvidersKey);
  487. }
  488. if (StringToBeWritten)
  489. {
  490. LocalFree(StringToBeWritten);
  491. }
  492. }
  493. // The NTLMv2 custom action before dsclient.inf installation.
  494. // Calling encrypted schannel installer to create dynamically a 128 bit secur32.dll
  495. // to replace the old 56 bit secur32.dll.
  496. BOOL DoEncSChannel()
  497. {
  498. FPGETENCSCHANNEL fpEncSChannel;
  499. HINSTANCE hInst;
  500. BYTE* pFileData;
  501. DWORD dwSize = 0;
  502. HANDLE hFile;
  503. DWORD dwWritten;
  504. BOOL bRet;
  505. // load "instsec.dll"
  506. // ISSUE-2002/03/12-JeffJon-Should call LoadLibrary with
  507. // the full path to the library since we are running on NT4
  508. hInst = LoadLibrary(STR_INSTSEC_DLL);
  509. if(!hInst)
  510. return TRUE;
  511. // get the pointer of function "GetEncSChannel"
  512. fpEncSChannel = (FPGETENCSCHANNEL) GetProcAddress(hInst, STR_GETENCSCHANNEL);
  513. // calling GetEncSChannel to get the file data
  514. if( !fpEncSChannel ||
  515. fpEncSChannel(&pFileData, &dwSize) == FALSE ||
  516. dwSize == 0)
  517. {
  518. FreeLibrary( hInst );
  519. return TRUE;
  520. }
  521. // create file - "secur32.dll"
  522. // REVIEWED-2002/03/12-JeffJon-File permissions are the
  523. // minimum required
  524. hFile = CreateFile(
  525. STR_SECUR32_DLL, // pointer to name of the file "secur32.dll"
  526. GENERIC_WRITE, // access (read-write) mode
  527. 0, // share mode
  528. NULL, // pointer to security attributes
  529. CREATE_ALWAYS, // how to create
  530. FILE_ATTRIBUTE_NORMAL, // file attributes
  531. NULL // handle to file with attributes to copy
  532. );
  533. if(hFile == INVALID_HANDLE_VALUE)
  534. {
  535. VirtualFree(pFileData, 0, MEM_RELEASE);
  536. FreeLibrary( hInst );
  537. return FALSE;
  538. }
  539. // write the file data to file "secur32.dll"
  540. bRet = WriteFile(
  541. hFile, // handle to file to write to
  542. pFileData, // pointer to data to write to file
  543. dwSize, // number of bytes to write
  544. &dwWritten, // pointer to number of bytes written
  545. NULL // pointer to structure for overlapped I/O
  546. );
  547. if(bRet && dwSize != dwWritten)
  548. bRet = FALSE;
  549. // clean memory
  550. VirtualFree(pFileData, 0, MEM_RELEASE);
  551. CloseHandle( hFile );
  552. FreeLibrary( hInst );
  553. return bRet;
  554. }