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.

1146 lines
38 KiB

  1. // PwdMsi.cpp : Defines the entry point for the DLL application.
  2. //
  3. #include "stdafx.h"
  4. #include <winuser.h>
  5. #include <stdio.h>
  6. #include <lm.h>
  7. #include <msi.h>
  8. #include <msiquery.h>
  9. #include <comdef.h>
  10. #include <commdlg.h>
  11. #include <Dsgetdc.h>
  12. #include <eh.h>
  13. #include "pwdfuncs.h"
  14. #include "ADMTCrypt.h"
  15. #include "PwdMsi.h"
  16. bool b3DESNotInstalled = false;
  17. bool bPESFileFound = false;
  18. bool bPasswordNeeded = false;
  19. HWND installWnd = 0;
  20. BOOL APIENTRY DllMain( HANDLE hModule,
  21. DWORD ul_reason_for_call,
  22. LPVOID lpReserved
  23. )
  24. {
  25. switch (ul_reason_for_call)
  26. {
  27. case DLL_PROCESS_ATTACH:
  28. case DLL_THREAD_ATTACH:
  29. case DLL_THREAD_DETACH:
  30. case DLL_PROCESS_DETACH:
  31. break;
  32. }
  33. return TRUE;
  34. }
  35. // This is the constructor of a class that has been exported.
  36. // see PwdMsi.h for the class definition
  37. CPwdMsi::CPwdMsi()
  38. {
  39. return;
  40. }
  41. void LoadOLEAUT32OnNT4()
  42. {
  43. static BOOL bDone = FALSE;
  44. static HMODULE hDllOleAut32 = NULL;
  45. BOOL bIsNT4 = FALSE;
  46. // only do this once
  47. if (!bDone)
  48. {
  49. bDone = TRUE;
  50. // test OS version
  51. DWORD rc = NERR_Success;
  52. SERVER_INFO_101 * servInfo = NULL;
  53. // Check version info
  54. rc = NetServerGetInfo(NULL, 101, (LPBYTE *)&servInfo);
  55. if (rc == NERR_Success)
  56. {
  57. bIsNT4 = (servInfo->sv101_version_major < 5) ? TRUE : FALSE;
  58. NetApiBufferFree(servInfo);
  59. }
  60. // if it is NT4, load oleaut32.dll
  61. if (bIsNT4)
  62. {
  63. hDllOleAut32 = LoadLibrary(L"oleaut32.dll");
  64. }
  65. }
  66. }
  67. /*********************************************************************
  68. * *
  69. * Written by: Paul Thompson *
  70. * Date: 25 JAN 2001 *
  71. * *
  72. * This function is a callback function used by GetWndFromInstall*
  73. * to compare titles and store the found HWND globally. *
  74. * *
  75. *********************************************************************/
  76. //BEGIN CheckTitle
  77. BOOL CALLBACK CheckTitle(HWND hwnd, LPARAM lParam)
  78. {
  79. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  80. // greater than zero
  81. LoadOLEAUT32OnNT4();
  82. /* local variables */
  83. WCHAR sText[MAX_PATH];
  84. WCHAR * pTitle;
  85. BOOL bSuccess;
  86. int len;
  87. /* function body */
  88. pTitle = (WCHAR*)lParam; //get the title to compare
  89. //get the title of this window
  90. len = GetWindowText(hwnd, sText, MAX_PATH);
  91. if ((len) && (pTitle))
  92. {
  93. if (wcsstr(sText, pTitle))
  94. {
  95. installWnd = hwnd;
  96. return FALSE;
  97. }
  98. }
  99. return TRUE;
  100. }
  101. //END CheckTitle
  102. /*********************************************************************
  103. * *
  104. * Written by: Paul Thompson *
  105. * Date: 25 JAN 2001 *
  106. * *
  107. * This function is responsible for getting the HWND of the *
  108. * current installation to be used to display a MessageBox tied to *
  109. * the install GUI. *
  110. * *
  111. *********************************************************************/
  112. //BEGIN GetWndFromInstall
  113. void GetWndFromInstall(MSIHANDLE hInstall)
  114. {
  115. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  116. // greater than zero
  117. LoadOLEAUT32OnNT4();
  118. /* local variables */
  119. WCHAR szPropName[MAX_PATH];
  120. UINT lret = ERROR_SUCCESS;
  121. WCHAR sTitle[MAX_PATH];
  122. DWORD nCount = MAX_PATH;
  123. /* function body */
  124. //get the installation's title
  125. wcscpy(szPropName, L"ProductName");
  126. lret = MsiGetProperty(hInstall, szPropName, sTitle, &nCount);
  127. if (lret != ERROR_SUCCESS)
  128. wcscpy(sTitle, L"ADMT Password Migration DLL");
  129. //get the window handle for the install GUI
  130. EnumChildWindows(NULL, CheckTitle, (LPARAM)sTitle);
  131. if (!installWnd)
  132. installWnd = GetForegroundWindow();
  133. }
  134. //END GetWndFromInstall
  135. /*********************************************************************
  136. * *
  137. * Written by: Paul Thompson *
  138. * Date: 11 DEC 2000 *
  139. * *
  140. * This function is responsible for retrieving a password *
  141. * encryption key from the given path. *
  142. * *
  143. *********************************************************************/
  144. //BEGIN RetrieveAndStorePwdKey
  145. bool RetrieveAndStorePwdKey(WCHAR * sPwd, _bstr_t sPath)
  146. {
  147. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  148. // greater than zero
  149. LoadOLEAUT32OnNT4();
  150. /* local variables */
  151. bool bRetrieved = false;
  152. WCHAR * pDrive;
  153. HANDLE hFile;
  154. WIN32_FIND_DATA fDat;
  155. _variant_t varData;
  156. /* function body */
  157. hFile = FindFirstFile((WCHAR*)sPath, &fDat);
  158. //if found, retrieve and store the key
  159. if (hFile != INVALID_HANDLE_VALUE)
  160. {
  161. FindClose(hFile);
  162. try
  163. {
  164. bPESFileFound = true;
  165. //get the data
  166. varData = GetDataFromFloppy((WCHAR*)sPath);
  167. if (varData.vt == (VT_UI1 | VT_ARRAY))
  168. {
  169. long uUBound;
  170. LPBYTE pByte = NULL;
  171. SafeArrayAccessData(varData.parray,(void**)&pByte);
  172. BYTE byteKey = pByte[0];
  173. SafeArrayUnaccessData(varData.parray);
  174. //the first byte tells us if this key is password encrypted
  175. //if password needed, return and have install display the UI
  176. if (byteKey != 0)
  177. {
  178. if (sPwd)
  179. {
  180. //try saving the key with this password
  181. try
  182. {
  183. CSourceCrypt aCryptObj; //create a crypt object
  184. //try to store the key. If fails, it throws a com error caught below
  185. aCryptObj.ImportEncryptionKey(varData, sPwd);
  186. bRetrieved = true;
  187. }
  188. catch (_com_error& ce)
  189. {
  190. //if HES not installed, set flag
  191. if (ce.Error() == NTE_KEYSET_NOT_DEF)
  192. b3DESNotInstalled = true;
  193. }
  194. }
  195. else
  196. bPasswordNeeded = true;
  197. }
  198. else
  199. {
  200. bPasswordNeeded = false;
  201. try
  202. {
  203. CSourceCrypt aCryptObj; //create a crypt object
  204. //try to store the key. If fails, it throws a com error caught below
  205. aCryptObj.ImportEncryptionKey(varData, NULL);
  206. bRetrieved = true;
  207. }
  208. catch (_com_error& ce)
  209. {
  210. //if HES not installed, set flag
  211. if (ce.Error() == NTE_KEYSET_NOT_DEF)
  212. b3DESNotInstalled = true;
  213. }
  214. }
  215. }
  216. }
  217. catch (...)
  218. {
  219. }
  220. }
  221. return bRetrieved;
  222. }
  223. //END RetrieveAndStorePwdKey
  224. /**********************
  225. * exported functions *
  226. **********************/
  227. /*********************************************************************
  228. * *
  229. * Written by: Paul Thompson *
  230. * Date: 12 SEPT 2000 *
  231. * *
  232. * This function is responsible for adding the PWMIG dll name to *
  233. * the Multi-string value "Notification Packages" under the Lsa key. *
  234. * *
  235. *********************************************************************/
  236. //BEGIN IsDC
  237. PWDMSI_API UINT __stdcall IsDC(MSIHANDLE hInstall)
  238. {
  239. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  240. // greater than zero
  241. LoadOLEAUT32OnNT4();
  242. /* local constants */
  243. const WCHAR sDCValue[2] = L"1";
  244. /* local variables */
  245. bool bDC = false;
  246. DWORD dwLevel = 101;
  247. LPSERVER_INFO_101 pBuf = NULL;
  248. NET_API_STATUS nStatus;
  249. WCHAR szPropName[MAX_PATH] = L"DC";
  250. UINT lret = ERROR_SUCCESS;
  251. /* function body */
  252. nStatus = NetServerGetInfo(NULL,
  253. dwLevel,
  254. (LPBYTE *)&pBuf);
  255. if (nStatus == NERR_Success)
  256. {
  257. //
  258. // Check for the type of server.
  259. //
  260. if ((pBuf->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
  261. (pBuf->sv101_type & SV_TYPE_DOMAIN_BAKCTRL))
  262. bDC = true;
  263. NetApiBufferFree(pBuf);
  264. }
  265. if (bDC)
  266. lret = MsiSetProperty(hInstall, szPropName, sDCValue);
  267. return lret;
  268. }
  269. //END IsDC
  270. /*********************************************************************
  271. * *
  272. * Written by: Paul Thompson *
  273. * Date: 12 SEPT 2000 *
  274. * *
  275. * This function is responsible for displaying a message box. *
  276. * *
  277. *********************************************************************/
  278. //BEGIN DisplayExiting
  279. PWDMSI_API UINT __stdcall DisplayExiting(MSIHANDLE hInstall)
  280. {
  281. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  282. // greater than zero
  283. LoadOLEAUT32OnNT4();
  284. /* local variables */
  285. WCHAR sPropName[MAX_PATH];
  286. UINT lret = ERROR_SUCCESS;
  287. WCHAR sTitle[MAX_PATH];
  288. WCHAR sMsg[MAX_PATH];
  289. DWORD nCount = MAX_PATH;
  290. bool bMsgGot = false;
  291. /* function body */
  292. //get the DC property
  293. wcscpy(sPropName, L"DC");
  294. //if this is not a DC, get its messages
  295. if (MsiGetProperty(hInstall, sPropName, sMsg, &nCount) == ERROR_SUCCESS)
  296. {
  297. if (!wcscmp(sMsg, L"0"))
  298. {
  299. //get the leave messagebox msg string and title for not being a DC
  300. wcscpy(sPropName, L"DCLeaveMsg");
  301. nCount = MAX_PATH;
  302. lret = MsiGetProperty(hInstall, sPropName, sMsg, &nCount);
  303. if (lret != ERROR_SUCCESS)
  304. wcscpy(sMsg, L"ADMT's Password Migration Filter DLL can only be installed on a DC, PDC, or BDC!");
  305. wcscpy(sPropName, L"DCLeaveTitle");
  306. nCount = MAX_PATH;
  307. lret = MsiGetProperty(hInstall, sPropName, sTitle, &nCount);
  308. if (lret != ERROR_SUCCESS)
  309. wcscpy(sTitle, L"Invalid Machine!");
  310. bMsgGot = true;
  311. }
  312. }
  313. //if this is a DC then see if the High Encryption pack was not installed
  314. if (!bMsgGot)
  315. {
  316. //get the HES flag property
  317. wcscpy(sPropName, L"b3DESNotInstalled");
  318. nCount = MAX_PATH;
  319. //if HEP is not installed, get its messages
  320. if (MsiGetProperty(hInstall, sPropName, sMsg, &nCount) == ERROR_SUCCESS)
  321. {
  322. if (!wcscmp(sMsg, L"1"))
  323. {
  324. //get the leave messagebox msg string and title for not getting a key
  325. wcscpy(sPropName, L"HEPLeaveMsg");
  326. nCount = MAX_PATH;
  327. lret = MsiGetProperty(hInstall, sPropName, sMsg, &nCount);
  328. if (lret != ERROR_SUCCESS)
  329. {
  330. wcscpy(sMsg, L"The high encryption pack has not been installed on this machine. ADMT's ");
  331. wcscat(sMsg, L"Password Migration Filter DLL will not install without the high encryption pack.");
  332. }
  333. wcscpy(sPropName, L"HEPLeaveTitle");
  334. nCount = MAX_PATH;
  335. lret = MsiGetProperty(hInstall, sPropName, sTitle, &nCount);
  336. if (lret != ERROR_SUCCESS)
  337. wcscpy(sTitle, L"High Encryption Pack Required!");
  338. bMsgGot = true;
  339. }
  340. }
  341. }
  342. /* //see if an encryption key file was not found on a local drive
  343. if (!bMsgGot)
  344. {
  345. //get the File flag property
  346. wcscpy(sPropName, L"bPESFileNotFound");
  347. nCount = MAX_PATH;
  348. //if file not found, get its messages
  349. if (MsiGetProperty(hInstall, sPropName, sMsg, &nCount) == ERROR_SUCCESS)
  350. {
  351. if (!wcscmp(sMsg, L"1"))
  352. {
  353. //get the leave messagebox msg string and title for not getting a key
  354. wcscpy(sPropName, L"PESLeaveMsg");
  355. nCount = MAX_PATH;
  356. lret = MsiGetProperty(hInstall, sPropName, sMsg, &nCount);
  357. if (lret != ERROR_SUCCESS)
  358. {
  359. wcscpy(sMsg, L"An encryption key file (.pes) could not be found on any of the floppy drives.");
  360. }
  361. wcscpy(sPropName, L"PESLeaveTitle");
  362. nCount = MAX_PATH;
  363. lret = MsiGetProperty(hInstall, sPropName, sTitle, &nCount);
  364. if (lret != ERROR_SUCCESS)
  365. wcscpy(sTitle, L"File Not Found!");
  366. bMsgGot = true;
  367. }
  368. }
  369. }
  370. */
  371. //else password was bad
  372. if (!bMsgGot)
  373. {
  374. //get the leave messagebox msg string and title for not getting a key
  375. wcscpy(sPropName, L"PwdLeaveMsg");
  376. nCount = MAX_PATH;
  377. lret = MsiGetProperty(hInstall, sPropName, sMsg, &nCount);
  378. if (lret != ERROR_SUCCESS)
  379. {
  380. wcscpy(sMsg, L"The supplied password does not match this encryption key's password. ADMT's ");
  381. wcscat(sMsg, L"Password Migration Filter DLL will not install without a valid encryption key.");
  382. }
  383. wcscpy(sPropName, L"PwdLeaveTitle");
  384. nCount = MAX_PATH;
  385. lret = MsiGetProperty(hInstall, sPropName, sTitle, &nCount);
  386. if (lret != ERROR_SUCCESS)
  387. wcscpy(sTitle, L"Invalid Password!");
  388. }
  389. GetWndFromInstall(hInstall);
  390. MessageBox(installWnd, sMsg, sTitle, MB_ICONSTOP | MB_OK);
  391. return lret;
  392. }
  393. //END DisplayExiting
  394. /*********************************************************************
  395. * *
  396. * Written by: Paul Thompson *
  397. * Date: 20 SEPT 2000 *
  398. * *
  399. * This function is responsible for trying to delete any files, *
  400. * that will be installed, that may have been left around by previous*
  401. * installations. *
  402. * *
  403. *********************************************************************/
  404. //BEGIN DeleteOldFiles
  405. PWDMSI_API UINT __stdcall DeleteOldFiles(MSIHANDLE hInstall)
  406. {
  407. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  408. // greater than zero
  409. LoadOLEAUT32OnNT4();
  410. /* local constants */
  411. const int GETENVVAR_ERROR = 0; //this indicates an error from the "GetEnvironmentVariable" function
  412. /* local variables */
  413. WCHAR systemdir[MAX_PATH];
  414. WCHAR filename[MAX_PATH];
  415. int length;
  416. UINT lret = ERROR_SUCCESS;
  417. /* function body */
  418. //try deleting previously installed files
  419. length = GetEnvironmentVariable( L"windir", systemdir, MAX_PATH);
  420. if (length != GETENVVAR_ERROR)
  421. {
  422. wcscat(systemdir, L"\\system32\\"); //go from windir to winsysdir
  423. wcscpy(filename, systemdir);
  424. wcscat(filename, L"PwMig.dll");
  425. DeleteFile(filename);
  426. wcscpy(filename, systemdir);
  427. wcscat(filename, L"mschapp.dll");
  428. DeleteFile(filename);
  429. }
  430. return lret;
  431. }
  432. //END DeleteOldFiles
  433. /*********************************************************************
  434. * *
  435. * Written by: Paul Thompson *
  436. * Date: 6 DEC 2000 *
  437. * *
  438. * This function is responsible for displaying the necessary *
  439. * dialogs to prompt for and retrieve a password encryption key off *
  440. * of a floppy disk. This key is placed on a floppy disk via a *
  441. * command line option on the ADMT machine. *
  442. * *
  443. *********************************************************************/
  444. //BEGIN GetInstallEncryptionKey
  445. PWDMSI_API UINT __stdcall GetInstallEncryptionKey(MSIHANDLE hInstall)
  446. {
  447. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  448. // greater than zero
  449. LoadOLEAUT32OnNT4();
  450. /* local constants */
  451. const int ADRIVE_SIZE = 3; //length of a drive in the string (i.e "a:\")
  452. /* local variables */
  453. UINT lret = ERROR_SUCCESS;
  454. WCHAR szPropName[MAX_PATH];
  455. WCHAR sTitle[MAX_PATH];
  456. WCHAR sMsg[MAX_PATH];
  457. WCHAR sTemp[MAX_PATH];
  458. DWORD nCount = MAX_PATH;
  459. int nRet;
  460. bool bRetrieved = false;
  461. WCHAR sRetrieved[2] = L"0";
  462. WCHAR sFlagSet[2] = L"1";
  463. WCHAR sFlagClear[2] = L"0";
  464. _bstr_t sDrives;
  465. _bstr_t sPath;
  466. WCHAR sADrive[ADRIVE_SIZE+1];
  467. /* function body */
  468. //if no path to file, return
  469. wcscpy(szPropName, L"SENCRYPTIONFILEPATH");
  470. lret = MsiGetProperty(hInstall, szPropName, sMsg, &nCount);
  471. if (lret != ERROR_SUCCESS)
  472. return lret;
  473. sPath = sMsg; //save the given path
  474. _wcslwr(sMsg); // convert the path to lower case for later comparison
  475. //get the drive of the given path
  476. wcsncpy(sADrive, sMsg, ADRIVE_SIZE);
  477. sADrive[ADRIVE_SIZE] = L'\0';
  478. //enumerate all local drives
  479. sDrives = EnumLocalDrives();
  480. _wcslwr(sDrives); // convert local drives to lower case for later comparison
  481. //if the given file is not on a local drive, set a flag and return
  482. WCHAR* pFound = wcsstr(sDrives, sADrive);
  483. if ((!pFound) || (wcslen(sADrive) == 0) || (wcsstr(sMsg, L".pes") == NULL))
  484. {
  485. //set the bad path flag
  486. wcscpy(szPropName, L"bBadKeyPath");
  487. lret = MsiSetProperty(hInstall, szPropName, sFlagSet);
  488. //if starts with "\\" then tell them it must be a local drive
  489. if ((!pFound) && (wcsstr(sMsg, L"\\\\") == sMsg))
  490. {
  491. //get the bad path messagebox msg string and title
  492. wcscpy(szPropName, L"BadDriveMsg");
  493. nCount = MAX_PATH;
  494. lret = MsiGetProperty(hInstall, szPropName, sMsg, &nCount);
  495. if (lret != ERROR_SUCCESS)
  496. {
  497. wcscpy(sMsg, L"The given path is not on a local drive and is therefore invalid.");
  498. wcscat(sMsg, L" Please supply the path to a valid encryption key file on a local drive.");
  499. }
  500. wcscpy(szPropName, L"BadPathTitle");
  501. nCount = MAX_PATH;
  502. lret = MsiGetProperty(hInstall, szPropName, sTitle, &nCount);
  503. if (lret != ERROR_SUCCESS)
  504. wcscpy(sTitle, L"Invalid Local Drive!");
  505. }
  506. //else if the given file does end with ".pes", tell them it must
  507. else if ((pFound) && (wcsstr(sMsg, L".pes") == NULL))
  508. {
  509. //get the bad file extension messagebox msg string
  510. wcscpy(szPropName, L"BadFileExtMsg");
  511. nCount = MAX_PATH;
  512. lret = MsiGetProperty(hInstall, szPropName, sMsg, &nCount);
  513. if (lret != ERROR_SUCCESS)
  514. {
  515. wcscpy(sMsg, L"The given file must be a valid encryption key file ending with the \".pes\" extension.");
  516. }
  517. wcscpy(szPropName, L"BadFileExtTitle");
  518. nCount = MAX_PATH;
  519. lret = MsiGetProperty(hInstall, szPropName, sTitle, &nCount);
  520. if (lret != ERROR_SUCCESS)
  521. wcscpy(sTitle, L"Invalid File Extension!");
  522. }
  523. //else, tell them it is not a local drive
  524. else
  525. {
  526. //get the bad path messagebox msg string and title
  527. wcscpy(szPropName, L"BadPathMsg");
  528. nCount = MAX_PATH;
  529. lret = MsiGetProperty(hInstall, szPropName, sTemp, &nCount);
  530. if (lret != ERROR_SUCCESS)
  531. {
  532. wcscpy(sTemp, L"The given drive, %s, is not a local drive and is therefore invalid.");
  533. wcscat(sTemp, L" Please supply the path to a valid encryption key file on a local drive.");
  534. }
  535. swprintf(sMsg, sTemp, sADrive);
  536. wcscpy(szPropName, L"BadPathTitle");
  537. nCount = MAX_PATH;
  538. lret = MsiGetProperty(hInstall, szPropName, sTitle, &nCount);
  539. if (lret != ERROR_SUCCESS)
  540. wcscpy(sTitle, L"Invalid Local Drive!");
  541. }
  542. GetWndFromInstall(hInstall);
  543. MessageBox(installWnd, sMsg, sTitle, MB_ICONSTOP | MB_OK);
  544. return lret;
  545. }
  546. else
  547. {
  548. //else clear the bad path flag
  549. wcscpy(szPropName, L"bBadKeyPath");
  550. lret = MsiSetProperty(hInstall, szPropName, sFlagClear);
  551. }
  552. //try to retrieve the encryption key
  553. if (RetrieveAndStorePwdKey(NULL, sPath))
  554. wcscpy(sRetrieved, L"1");
  555. else if (bPasswordNeeded)
  556. {
  557. wcscpy(szPropName, L"bPwdNeeded");
  558. lret = MsiSetProperty(hInstall, szPropName, sFlagSet);
  559. }
  560. //set the key retrieved flag
  561. wcscpy(szPropName, L"bKeyRetrieved");
  562. lret = MsiSetProperty(hInstall, szPropName, sRetrieved);
  563. //if file not found at the given path, prompt the user for a new one
  564. if (!bPESFileFound)
  565. {
  566. //set the bad path flag
  567. wcscpy(szPropName, L"bBadKeyPath");
  568. lret = MsiSetProperty(hInstall, szPropName, sFlagSet);
  569. //get the bad path messagebox msg string and title
  570. wcscpy(szPropName, L"PESLeaveMsg");
  571. nCount = MAX_PATH;
  572. lret = MsiGetProperty(hInstall, szPropName, sTemp, &nCount);
  573. if (lret != ERROR_SUCCESS)
  574. {
  575. wcscpy(sTemp, L"The given encryption key file, %s, could not be found.");
  576. wcscat(sTemp, L" Please enter the path to a valid encryption key file.");
  577. }
  578. swprintf(sMsg, sTemp, (WCHAR*)sPath);
  579. wcscpy(szPropName, L"PESLeaveTitle");
  580. nCount = MAX_PATH;
  581. lret = MsiGetProperty(hInstall, szPropName, sTitle, &nCount);
  582. if (lret != ERROR_SUCCESS)
  583. wcscpy(sTitle, L"File Not Found!");
  584. GetWndFromInstall(hInstall);
  585. MessageBox(installWnd, sMsg, sTitle, MB_ICONSTOP | MB_OK);
  586. return lret;
  587. }
  588. //if HES is not installed, set that flag
  589. if (b3DESNotInstalled)
  590. {
  591. wcscpy(szPropName, L"b3DESNotInstalled");
  592. lret = MsiSetProperty(hInstall, szPropName, sFlagSet);
  593. }
  594. return lret;
  595. }
  596. //END GetInstallEncryptionKey
  597. /*********************************************************************
  598. * *
  599. * Written by: Paul Thompson *
  600. * Date: 12 SEPT 2000 *
  601. * *
  602. * This function is used by the installation routine and is *
  603. * responsible for adding the PWMIG dll name to the Multi-string *
  604. * value "Notification Packages" under the Lsa key. *
  605. * *
  606. *********************************************************************/
  607. //BEGIN AddToLsaNotificationPkgValue
  608. PWDMSI_API UINT __stdcall AddToLsaNotificationPkgValue(MSIHANDLE hInstall)
  609. {
  610. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  611. // greater than zero
  612. LoadOLEAUT32OnNT4();
  613. /* local constants */
  614. const WCHAR sLsaKey[40] = L"SYSTEM\\CurrentControlSet\\Control\\Lsa";
  615. const WCHAR sLsaValue[25] = L"Notification Packages";
  616. const WCHAR sNewAddition[10] = L"PWMIG";
  617. /* local variables */
  618. bool bSuccess = false;
  619. bool bFound = false;
  620. bool bAlreadyThere = false;
  621. DWORD rc;
  622. DWORD type;
  623. HKEY hKey;
  624. WCHAR sString[MAX_PATH];
  625. DWORD len = sizeof(sString);
  626. WCHAR sTemp[MAX_PATH];
  627. int currentPos = 0;
  628. UINT lret = ERROR_SUCCESS;
  629. /* function body */
  630. //open the Lsa registry key
  631. rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  632. sLsaKey,
  633. 0,
  634. KEY_ALL_ACCESS,
  635. &hKey);
  636. if (rc == ERROR_SUCCESS)
  637. {
  638. //get the current value string
  639. rc = RegQueryValueEx(hKey, sLsaValue, NULL, &type, (LPBYTE)sString, &len);
  640. if ((rc == ERROR_SUCCESS) && (type == REG_MULTI_SZ))
  641. {
  642. sString[MAX_PATH - 1] = L'\0';
  643. //copy each string in the multi-string until the end is reached
  644. while (!bFound)
  645. {
  646. if (!wcscmp(sString+currentPos, sNewAddition))
  647. bAlreadyThere = true;
  648. wcscpy(sTemp+currentPos, sString+currentPos);
  649. currentPos += wcslen(sTemp+currentPos) + 1;
  650. if (sString[currentPos] == L'\0')
  651. bFound = true;
  652. }
  653. if (!bAlreadyThere)
  654. {
  655. //now add our new text and terminate the string
  656. wcscpy(sTemp+currentPos, sNewAddition);
  657. currentPos += wcslen(sNewAddition) + 1;
  658. sTemp[currentPos] = L'\0';
  659. //save the new value in the registry
  660. len = (currentPos + 1) * sizeof(WCHAR);
  661. rc = RegSetValueEx(hKey, sLsaValue, 0, type, (LPBYTE)sTemp, len);
  662. if (rc == ERROR_SUCCESS)
  663. bSuccess = true;
  664. }
  665. }
  666. RegCloseKey(hKey);
  667. }
  668. //tell installer we want to reboot
  669. MsiSetMode(hInstall, MSIRUNMODE_REBOOTATEND, TRUE);
  670. return lret;
  671. }
  672. //END AddToLsaNotificationPkgValue
  673. /*********************************************************************
  674. * *
  675. * Written by: Paul Thompson *
  676. * Date: 12 SEPT 2000 *
  677. * *
  678. * This function is used by the installation routine and is *
  679. * responsible for deleting the PWMIG dll name from the Multi-string *
  680. * value "Notification Packages" under the Lsa key. *
  681. * *
  682. *********************************************************************/
  683. //BEGIN DeleteFromLsaNotificationPkgValue
  684. PWDMSI_API UINT __stdcall DeleteFromLsaNotificationPkgValue(MSIHANDLE hInstall)
  685. {
  686. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  687. // greater than zero
  688. LoadOLEAUT32OnNT4();
  689. /* local constants */
  690. const WCHAR sLsaKey[40] = L"SYSTEM\\CurrentControlSet\\Control\\Lsa";
  691. const WCHAR sLsaValue[25] = L"Notification Packages";
  692. const WCHAR sNewAddition[10] = L"PWMIG";
  693. /* local variables */
  694. bool bSuccess = false;
  695. DWORD rc;
  696. DWORD type;
  697. HKEY hKey;
  698. WCHAR sString[MAX_PATH];
  699. DWORD len = sizeof(sString);
  700. WCHAR sTemp[MAX_PATH];
  701. int currentPos = 0;
  702. int tempPos = 0;
  703. UINT lret = ERROR_SUCCESS;
  704. /* function body */
  705. //open the Lsa registry key
  706. rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  707. sLsaKey,
  708. 0,
  709. KEY_ALL_ACCESS,
  710. &hKey);
  711. if (rc == ERROR_SUCCESS)
  712. {
  713. //get the current value string
  714. rc = RegQueryValueEx(hKey, sLsaValue, NULL, &type, (LPBYTE)sString, &len);
  715. if ((rc == ERROR_SUCCESS) && (type == REG_MULTI_SZ))
  716. {
  717. sString[MAX_PATH - 1] = L'\0';
  718. //copy each string in the multi-string until the desired string
  719. while (sString[currentPos] != L'\0')
  720. {
  721. //if not string wanted, copy to destination string
  722. if (wcscmp(sString+currentPos, sNewAddition))
  723. {
  724. wcscpy(sTemp+tempPos, sString+currentPos);
  725. tempPos += wcslen(sString+currentPos) + 1;
  726. currentPos += wcslen(sString+currentPos) + 1;
  727. }
  728. else //else this is our string, skip it
  729. {
  730. currentPos += wcslen(sString+currentPos) + 1;
  731. }
  732. }
  733. //add the ending NULL
  734. sTemp[tempPos] = L'\0';
  735. //save the new value in the registry
  736. len = (tempPos + 1) * sizeof(WCHAR);
  737. rc = RegSetValueEx(hKey, sLsaValue, 0, type, (LPBYTE)sTemp, len);
  738. if (rc == ERROR_SUCCESS)
  739. bSuccess = true;
  740. }
  741. RegCloseKey(hKey);
  742. }
  743. //tell installer we want to reboot
  744. MsiSetMode(hInstall, MSIRUNMODE_REBOOTATEND, TRUE);
  745. return lret;
  746. }
  747. //END DeleteFromLsaNotificationPkgValue
  748. /*********************************************************************
  749. * *
  750. * Written by: Paul Thompson *
  751. * Date: 23 JAN 2001 *
  752. * *
  753. * This function is responsible for displaying the necessary *
  754. * dialogs to prompt for and retrieve a password encryption key off *
  755. * of a floppy disk. This key is placed on a floppy disk via a *
  756. * command line option on the ADMT machine. *
  757. * *
  758. *********************************************************************/
  759. //BEGIN FinishWithPassword
  760. PWDMSI_API UINT __stdcall FinishWithPassword(MSIHANDLE hInstall)
  761. {
  762. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  763. // greater than zero
  764. LoadOLEAUT32OnNT4();
  765. /* local variables */
  766. UINT lret = ERROR_SUCCESS;
  767. WCHAR szPropName[MAX_PATH];
  768. WCHAR sPwd[MAX_PATH];
  769. WCHAR sMsg[MAX_PATH];
  770. DWORD nCount = MAX_PATH;
  771. _bstr_t sPath;
  772. WCHAR sFlagSet[2] = L"1";
  773. /* function body */
  774. //get the password to try
  775. wcscpy(szPropName, L"sKeyPassword");
  776. lret = MsiGetProperty(hInstall, szPropName, sPwd, &nCount);
  777. if (lret != ERROR_SUCCESS)
  778. return lret;
  779. //if no path to file, return
  780. nCount = MAX_PATH;
  781. wcscpy(szPropName, L"SENCRYPTIONFILEPATH");
  782. lret = MsiGetProperty(hInstall, szPropName, sMsg, &nCount);
  783. if (lret != ERROR_SUCCESS)
  784. return lret;
  785. sPath = sMsg; //save the given path
  786. //try saving the key with this password
  787. if (RetrieveAndStorePwdKey(sPwd, sPath))
  788. {
  789. wcscpy(szPropName, L"bKeyRetrieved");
  790. lret = MsiSetProperty(hInstall, szPropName, sFlagSet);
  791. }
  792. //if HES is not installed, set that flag
  793. if (b3DESNotInstalled)
  794. {
  795. wcscpy(szPropName, L"b3DESNotInstalled");
  796. lret = MsiSetProperty(hInstall, szPropName, sFlagSet);
  797. }
  798. /* //if file not found on the floppy, set that flag
  799. if (!bPESFileFound)
  800. {
  801. wcscpy(szPropName, L"bPESFileNotFound");
  802. lret = MsiSetProperty(hInstall, szPropName, sFlagSet);
  803. }
  804. */
  805. return lret;
  806. }
  807. //END FinishWithPassword
  808. /*********************************************************************
  809. * *
  810. * Written by: Paul Thompson *
  811. * Date: 24 JAN 2001 *
  812. * *
  813. * This function is responsible for displaying a MesasgeBox *
  814. * the user that the passwords did not match. *
  815. * *
  816. *********************************************************************/
  817. //BEGIN PwdsDontMatch
  818. PWDMSI_API UINT __stdcall PwdsDontMatch(MSIHANDLE hInstall)
  819. {
  820. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  821. // greater than zero
  822. LoadOLEAUT32OnNT4();
  823. /* local variables */
  824. UINT lret = ERROR_SUCCESS;
  825. WCHAR szPropName[MAX_PATH];
  826. WCHAR sMsg[MAX_PATH];
  827. WCHAR sTitle[MAX_PATH];
  828. DWORD nCount = MAX_PATH;
  829. WCHAR sEmpty[2] = L"";
  830. /* function body */
  831. //get the message to display
  832. wcscpy(szPropName, L"PwdMatchMsg");
  833. lret = MsiGetProperty(hInstall, szPropName, sMsg, &nCount);
  834. if (lret != ERROR_SUCCESS)
  835. wcscpy(sMsg, L"The passwords entered do not match each other. Please try again!");
  836. //get the title string
  837. nCount = MAX_PATH;
  838. wcscpy(szPropName, L"PwdMatchTitle");
  839. lret = MsiGetProperty(hInstall, szPropName, sTitle, &nCount);
  840. if (lret != ERROR_SUCCESS)
  841. wcscpy(sTitle, L"Password Mismatch");
  842. GetWndFromInstall(hInstall);
  843. MessageBox(installWnd, sMsg, sTitle, MB_ICONSTOP | MB_OKCANCEL);
  844. return lret;
  845. }
  846. //END PwdsDontMatch
  847. /*********************************************************************
  848. * *
  849. * Written by: Paul Thompson *
  850. * Date: 28 MAR 2001 *
  851. * *
  852. * This function is responsible for displaying a browse dialog to*
  853. * aid the install user in finding a password encryption key file, *
  854. * which has a .PES extension. *
  855. * *
  856. *********************************************************************/
  857. //BEGIN BrowseForEncryptionKey
  858. PWDMSI_API UINT __stdcall BrowseForEncryptionKey(MSIHANDLE hInstall)
  859. {
  860. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  861. // greater than zero
  862. LoadOLEAUT32OnNT4();
  863. /* local variables */
  864. UINT lret = ERROR_SUCCESS;
  865. WCHAR szPropName[MAX_PATH];
  866. WCHAR sMsg[2*MAX_PATH];
  867. WCHAR sFile[2*MAX_PATH];
  868. DWORD nCount = 2*MAX_PATH;
  869. _bstr_t sPath = L"";
  870. int nRet;
  871. OPENFILENAME ofn;
  872. HANDLE hFile;
  873. WCHAR sFilter[MAX_PATH];
  874. bool bFile, bFolder = false;
  875. /* function body */
  876. //get the starting location
  877. wcscpy(szPropName, L"SENCRYPTIONFILEPATH");
  878. lret = MsiGetProperty(hInstall, szPropName, sMsg, &nCount);
  879. if (lret != ERROR_SUCCESS)
  880. {
  881. wcscpy(sMsg, L"");
  882. bFile = false;
  883. }
  884. else
  885. {
  886. WCHAR* pFound = wcsstr(sMsg, L".pes");
  887. if (pFound)
  888. bFile = true;
  889. else
  890. {
  891. WCHAR* pFound = wcsrchr(sMsg, L'\\');
  892. if (pFound)
  893. {
  894. // *pFound = L'\0';
  895. bFolder = true;
  896. }
  897. bFile = false;
  898. }
  899. }
  900. //get a handle to the install
  901. GetWndFromInstall(hInstall);
  902. // Initialize OPENFILENAME
  903. ZeroMemory(&ofn, sizeof(OPENFILENAME));
  904. ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
  905. ofn.hwndOwner = installWnd;
  906. if (bFile)
  907. ofn.lpstrFile = sMsg;
  908. else
  909. {
  910. wcscpy(sFile, L"");
  911. ofn.lpstrFile = sFile;
  912. }
  913. if (bFolder)
  914. ofn.lpstrInitialDir = sMsg;
  915. ofn.nMaxFile = 2*MAX_PATH;
  916. ofn.lpstrFilter = L"Password Encryption Files (*.pes)\0*.pes\0";
  917. ofn.nFilterIndex = 0;
  918. ofn.lpstrFileTitle = NULL;
  919. ofn.nMaxFileTitle = 0;
  920. ofn.lpstrInitialDir = NULL;
  921. ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_LONGNAMES |
  922. OFN_NONETWORKBUTTON;
  923. // Display the Open dialog box.
  924. if (GetOpenFileName(&ofn))
  925. {
  926. //get the given file path
  927. sPath = ofn.lpstrFile;
  928. //set the filepath property
  929. wcscpy(szPropName, L"sFilePath");
  930. lret = MsiSetProperty(hInstall, szPropName, sPath);
  931. }
  932. return lret;
  933. }
  934. //END BrowseForEncryptionKey
  935. /*********************************************************************
  936. * *
  937. * Written by: Paul Thompson *
  938. * Date: 28 MAR 2001 *
  939. * *
  940. * This function is responsible for setting the *
  941. * "sEncryptionFilePath" property to a default location. If the *
  942. * property is not "None" then we will not set the property. *
  943. * *
  944. *********************************************************************/
  945. //BEGIN GetDefaultPathToEncryptionKey
  946. PWDMSI_API UINT __stdcall GetDefaultPathToEncryptionKey(MSIHANDLE hInstall)
  947. {
  948. // call LoadOLEAUT32OnNT4 to keep ref count of OLEAUT32
  949. // greater than zero
  950. LoadOLEAUT32OnNT4();
  951. /* local constants */
  952. const WCHAR TOKENS[3] = L",\0";
  953. /* local variables */
  954. _bstr_t sFloppies;
  955. WCHAR * pDrive;
  956. HANDLE hFile;
  957. WIN32_FIND_DATA fDat;
  958. _bstr_t sPath;
  959. _bstr_t sPathSaved = L"";
  960. _bstr_t sDrive = L"";
  961. int ndx = 0;
  962. int ndx2 = 0;
  963. UINT lret = ERROR_SUCCESS;
  964. WCHAR szPropName[MAX_PATH];
  965. WCHAR sMsg[2*MAX_PATH];
  966. DWORD nCount = 2*MAX_PATH;
  967. /* function body */
  968. //if already set don't get again
  969. wcscpy(szPropName, L"SENCRYPTIONFILEPATH");
  970. lret = MsiGetProperty(hInstall, szPropName, sMsg, &nCount);
  971. if ((lret == ERROR_SUCCESS) && (wcscmp(sMsg, L"None")))
  972. return lret;
  973. //enumerate all local drives
  974. sDrive = EnumLocalDrives();
  975. //check each drive for the file
  976. pDrive = wcstok((WCHAR*)sDrive, TOKENS);
  977. while (pDrive != NULL)
  978. {
  979. if (ndx == 0)
  980. sPathSaved = pDrive;
  981. ndx++;
  982. //see if a .pes file is on this drive
  983. sPath = pDrive;
  984. sPath += L"*.pes";
  985. hFile = FindFirstFile((WCHAR*)sPath, &fDat);
  986. //if found, store the file path
  987. if (hFile != INVALID_HANDLE_VALUE)
  988. {
  989. FindClose(hFile);
  990. //get the data
  991. sPath = pDrive;
  992. sPath += fDat.cFileName;
  993. if (ndx2 == 0)
  994. sPathSaved = sPath;
  995. ndx2++;
  996. }
  997. //get the next drive
  998. pDrive = wcstok(NULL, TOKENS);
  999. }
  1000. //set the filepath property
  1001. wcscpy(szPropName, L"SENCRYPTIONFILEPATH");
  1002. lret = MsiSetProperty(hInstall, szPropName, sPathSaved);
  1003. return lret;
  1004. }
  1005. //END GetDefaultPathToEncryptionKey