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.

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