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.

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