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.

1971 lines
44 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. salemlib.cpp
  5. Abstract:
  6. All Salem related function, this library is shared by termsrv.dll
  7. and salem sessmgr.exe
  8. Author:
  9. HueiWang 4/26/2000
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <ntlsa.h>
  15. #include <windows.h>
  16. #include <ntlsapi.h>
  17. #include <stdio.h>
  18. #include <rpc.h>
  19. #include <rpcdce.h>
  20. #include <wincrypt.h>
  21. #include <regapi.h>
  22. #include "winsta.h"
  23. #include "tsremdsk.h"
  24. #include "base64.h"
  25. #ifdef AllocMemory
  26. #undef AllocMemory
  27. #undef FreeMemory
  28. #endif
  29. #define AllocMemory(size) LocalAlloc(LPTR, size)
  30. #define FreeMemory(ptr) LocalFree(ptr)
  31. //
  32. // Global Crypto provider
  33. //
  34. HCRYPTPROV gm_hCryptProv = NULL; // Crypto provider
  35. //
  36. // CryptEncrypt()/CryptDecrypt() not thread safe
  37. //
  38. HANDLE gm_hMutex = NULL;
  39. extern DWORD
  40. StoreKeyWithLSA(
  41. IN PWCHAR pwszKeyName,
  42. IN BYTE * pbKey,
  43. IN DWORD cbKey
  44. );
  45. extern DWORD
  46. RetrieveKeyFromLSA(
  47. IN PWCHAR pwszKeyName,
  48. OUT PBYTE * ppbKey,
  49. OUT DWORD * pcbKey
  50. );
  51. void
  52. EncryptUnlock();
  53. DWORD
  54. EncryptLock();
  55. void
  56. InitLsaString(
  57. IN OUT PLSA_UNICODE_STRING LsaString,
  58. IN LPWSTR String
  59. )
  60. /*++
  61. Routine Description:
  62. Initialize LSA unicode string.
  63. Parameters:
  64. LsaString : Pointer to LSA_UNICODE_STRING to be initialized.
  65. String : String to initialize LsaString.
  66. Returns:
  67. None.
  68. Note:
  69. Refer to LSA_UNICODE_STRING
  70. --*/
  71. {
  72. DWORD StringLength;
  73. if( NULL == String )
  74. {
  75. LsaString->Buffer = NULL;
  76. LsaString->Length = 0;
  77. LsaString->MaximumLength = 0;
  78. return;
  79. }
  80. StringLength = lstrlenW( String );
  81. LsaString->Buffer = String;
  82. LsaString->Length = ( USHORT ) StringLength * sizeof( WCHAR );
  83. LsaString->MaximumLength=( USHORT )( StringLength + 1 ) * sizeof( WCHAR );
  84. }
  85. DWORD
  86. OpenPolicy(
  87. IN LPWSTR ServerName,
  88. IN DWORD DesiredAccess,
  89. OUT PLSA_HANDLE PolicyHandle
  90. )
  91. /*++
  92. Routine Description:
  93. Create/return a LSA policy handle.
  94. Parameters:
  95. ServerName : Name of server, refer to LsaOpenPolicy().
  96. DesiredAccess : Desired access level, refer to LsaOpenPolicy().
  97. PolicyHandle : Return PLSA_HANDLE.
  98. Returns:
  99. ERROR_SUCCESS or LSA error code
  100. --*/
  101. {
  102. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  103. LSA_UNICODE_STRING ServerString;
  104. PLSA_UNICODE_STRING Server;
  105. //
  106. // Always initialize the object attributes to all zeroes.
  107. //
  108. ZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
  109. if( NULL != ServerName )
  110. {
  111. //
  112. // Make a LSA_UNICODE_STRING out of the LPWSTR passed in
  113. //
  114. InitLsaString( &ServerString, ServerName );
  115. Server = &ServerString;
  116. }
  117. else
  118. {
  119. Server = NULL;
  120. }
  121. //
  122. // Attempt to open the policy.
  123. //
  124. return( LsaOpenPolicy(
  125. Server,
  126. &ObjectAttributes,
  127. DesiredAccess,
  128. PolicyHandle ) );
  129. }
  130. DWORD
  131. StoreKeyWithLSA(
  132. IN PWCHAR pwszKeyName,
  133. IN BYTE * pbKey,
  134. IN DWORD cbKey
  135. )
  136. /*++
  137. Routine Description:
  138. Save private data to LSA.
  139. Parameters:
  140. pwszKeyName : Name of the key this data going to be stored under.
  141. pbKey : Binary data to be saved.
  142. cbKey : Size of binary data.
  143. Returns:
  144. ERROR_SUCCESS
  145. ERROR_INVALID_PARAMETER.
  146. LSA return code
  147. --*/
  148. {
  149. LSA_HANDLE PolicyHandle;
  150. UNICODE_STRING SecretKeyName;
  151. UNICODE_STRING SecretData;
  152. DWORD Status;
  153. if( ( NULL == pwszKeyName ) )
  154. {
  155. return( ERROR_INVALID_PARAMETER );
  156. }
  157. //
  158. // setup the UNICODE_STRINGs for the call.
  159. //
  160. InitLsaString(
  161. &SecretKeyName,
  162. pwszKeyName
  163. );
  164. SecretData.Buffer = ( LPWSTR )pbKey;
  165. SecretData.Length = ( USHORT )cbKey;
  166. SecretData.MaximumLength = ( USHORT )cbKey;
  167. Status = OpenPolicy(
  168. NULL,
  169. POLICY_CREATE_SECRET,
  170. &PolicyHandle
  171. );
  172. if( Status != ERROR_SUCCESS )
  173. {
  174. return LsaNtStatusToWinError(Status);
  175. }
  176. Status = LsaStorePrivateData(
  177. PolicyHandle,
  178. &SecretKeyName,
  179. &SecretData
  180. );
  181. LsaClose(PolicyHandle);
  182. return LsaNtStatusToWinError(Status);
  183. }
  184. DWORD
  185. RetrieveKeyFromLSA(
  186. IN PWCHAR pwszKeyName,
  187. OUT PBYTE * ppbKey,
  188. OUT DWORD * pcbKey
  189. )
  190. /*++
  191. Routine Description:
  192. Retrieve private data previously stored with StoreKeyWithLSA().
  193. Parameters:
  194. pwszKeyName : Name of the key.
  195. ppbKey : Pointer to PBYTE to receive binary data.
  196. pcbKey : Size of binary data.
  197. Returns:
  198. ERROR_SUCCESS
  199. ERROR_INVALID_PARAMETER.
  200. ERROR_FILE_NOT_FOUND
  201. LSA return code
  202. --*/
  203. {
  204. LSA_HANDLE PolicyHandle;
  205. UNICODE_STRING SecretKeyName;
  206. UNICODE_STRING *pSecretData;
  207. DWORD Status;
  208. if( ( NULL == pwszKeyName ) || ( NULL == ppbKey ) || ( NULL == pcbKey ) )
  209. {
  210. SetLastError( ERROR_INVALID_PARAMETER );
  211. return( ERROR_INVALID_PARAMETER );
  212. }
  213. //
  214. // setup the UNICODE_STRINGs for the call.
  215. //
  216. InitLsaString(
  217. &SecretKeyName,
  218. pwszKeyName
  219. );
  220. Status = OpenPolicy(
  221. NULL,
  222. POLICY_GET_PRIVATE_INFORMATION,
  223. &PolicyHandle
  224. );
  225. if( Status != ERROR_SUCCESS )
  226. {
  227. SetLastError( LsaNtStatusToWinError(Status) );
  228. return GetLastError();
  229. }
  230. Status = LsaRetrievePrivateData(
  231. PolicyHandle,
  232. &SecretKeyName,
  233. &pSecretData
  234. );
  235. LsaClose( PolicyHandle );
  236. if( Status != ERROR_SUCCESS )
  237. {
  238. SetLastError( LsaNtStatusToWinError(Status) );
  239. return GetLastError();
  240. }
  241. if(pSecretData != NULL && pSecretData->Length)
  242. {
  243. *ppbKey = (LPBYTE)AllocMemory( pSecretData->Length );
  244. if( *ppbKey )
  245. {
  246. *pcbKey = pSecretData->Length;
  247. CopyMemory( *ppbKey, pSecretData->Buffer, pSecretData->Length );
  248. Status = ERROR_SUCCESS;
  249. }
  250. else
  251. {
  252. Status = GetLastError();
  253. }
  254. }
  255. else
  256. {
  257. Status = ERROR_FILE_NOT_FOUND;
  258. SetLastError( Status );
  259. *pcbKey = 0;
  260. *ppbKey = NULL;
  261. }
  262. if (pSecretData != NULL) {
  263. SecureZeroMemory( pSecretData->Buffer, pSecretData->Length );
  264. LsaFreeMemory( pSecretData );
  265. }
  266. return Status;
  267. }
  268. DWORD
  269. TSSetEncryptionKey(
  270. IN PBYTE pbData,
  271. IN DWORD cbData
  272. )
  273. /*++
  274. Routine Description:
  275. Cache random password that use to deriving encryption cycle key.
  276. Parameters:
  277. pbData :
  278. cbData :
  279. Returns:
  280. ERROR_SUCCESS or error code
  281. --*/
  282. {
  283. DWORD status;
  284. if( !pbData || cbData == 0 )
  285. {
  286. status = ERROR_INVALID_PARAMETER;
  287. goto CLEANUPANDEXIT;
  288. }
  289. status = EncryptLock();
  290. if( ERROR_SUCCESS == status )
  291. {
  292. //
  293. // Load password to derive session encryption key from LSA
  294. //
  295. status = StoreKeyWithLSA(
  296. SALEMHELPASSISTANTACCOUNT_ENCRYPTIONKEY,
  297. pbData,
  298. cbData
  299. );
  300. EncryptUnlock();
  301. }
  302. CLEANUPANDEXIT:
  303. return status;
  304. }
  305. DWORD
  306. TSGetEncryptionKey(
  307. OUT PBYTE* ppbData,
  308. OUT DWORD* pcbData
  309. )
  310. /*++
  311. Routine Description:
  312. Cache random password that use to deriving encryption cycle key.
  313. Parameters:
  314. pbData :
  315. cbData :
  316. Returns:
  317. ERROR_SUCCESS or error code
  318. --*/
  319. {
  320. DWORD status;
  321. if( !ppbData || !pcbData )
  322. {
  323. status = ERROR_INVALID_PARAMETER;
  324. goto CLEANUPANDEXIT;
  325. }
  326. status = EncryptLock();
  327. if( ERROR_SUCCESS == status )
  328. {
  329. //
  330. // Load password to derive session encryption key from LSA
  331. //
  332. status = RetrieveKeyFromLSA(
  333. SALEMHELPASSISTANTACCOUNT_ENCRYPTIONKEY,
  334. ppbData,
  335. pcbData
  336. );
  337. EncryptUnlock();
  338. }
  339. CLEANUPANDEXIT:
  340. return status;
  341. }
  342. DWORD
  343. TSGetHelpAssistantAccountPassword(
  344. OUT LPWSTR* ppszAccPwd
  345. )
  346. /*++
  347. --*/
  348. {
  349. DWORD cbHelpAccPwd = 0;
  350. DWORD Status;
  351. Status = RetrieveKeyFromLSA(
  352. SALEMHELPASSISTANTACCOUNT_PASSWORDKEY,
  353. (PBYTE *)ppszAccPwd,
  354. &cbHelpAccPwd
  355. );
  356. if( ERROR_SUCCESS != Status )
  357. {
  358. // password is not set, assuming no help
  359. Status = ERROR_INVALID_ACCESS;
  360. }
  361. return Status;
  362. }
  363. DWORD
  364. TSGetHelpAssistantAccountName(
  365. OUT LPWSTR* ppszAccDomain,
  366. OUT LPWSTR* ppszAcctName
  367. )
  368. /*++
  369. Routine Description:
  370. Get HelpAssistant account name.
  371. Parameters:
  372. ppszAcctName : Pointer to LPWSTR to receive account name, use LocalFree()
  373. to free the buffer.
  374. Returns:
  375. ERROR_SUCCESS or error code
  376. --*/
  377. {
  378. LPWSTR pszHelpAcctName = NULL;
  379. LPWSTR pszHelpAcctDomain = NULL;
  380. DWORD cbHelpAcctName = 0;
  381. DWORD cbHelpAcctDomain = 0;
  382. SID_NAME_USE sidUse;
  383. DWORD Status;
  384. BOOL bSuccess;
  385. PSID pLsaHelpAccSid = NULL;
  386. DWORD cbLsaHelpAccSid = 0;
  387. //
  388. // Retrieve HelpAccount SID we cached in LSA
  389. Status = RetrieveKeyFromLSA(
  390. SALEMHELPASSISTANTACCOUNT_SIDKEY,
  391. (PBYTE *)&pLsaHelpAccSid,
  392. &cbLsaHelpAccSid
  393. );
  394. if( ERROR_SUCCESS != Status )
  395. {
  396. // Salem is not installed or not active on this machine
  397. goto CLEANUPANDEXIT;
  398. }
  399. //
  400. // Lookup account name from SID
  401. //
  402. bSuccess = LookupAccountSid(
  403. NULL,
  404. pLsaHelpAccSid,
  405. NULL,
  406. &cbHelpAcctName,
  407. NULL,
  408. &cbHelpAcctDomain,
  409. &sidUse
  410. );
  411. if( bSuccess == FALSE && ERROR_NONE_MAPPED == GetLastError() )
  412. {
  413. // Can't retrieve either because network error or account
  414. // does not exist, error out.
  415. Status = ERROR_FILE_NOT_FOUND;
  416. goto CLEANUPANDEXIT;
  417. }
  418. pszHelpAcctName = (LPTSTR)AllocMemory( (cbHelpAcctName+1)*sizeof(WCHAR) );
  419. pszHelpAcctDomain = (LPTSTR)AllocMemory( (cbHelpAcctDomain+1)*sizeof(WCHAR) );
  420. if( NULL == pszHelpAcctName || NULL == pszHelpAcctDomain )
  421. {
  422. Status = ERROR_OUTOFMEMORY;
  423. goto CLEANUPANDEXIT;
  424. }
  425. bSuccess = LookupAccountSid(
  426. NULL,
  427. pLsaHelpAccSid,
  428. pszHelpAcctName,
  429. &cbHelpAcctName,
  430. pszHelpAcctDomain,
  431. &cbHelpAcctDomain,
  432. &sidUse
  433. );
  434. if( FALSE == bSuccess )
  435. {
  436. Status = GetLastError();
  437. goto CLEANUPANDEXIT;
  438. }
  439. *ppszAcctName = pszHelpAcctName;
  440. *ppszAccDomain = pszHelpAcctDomain;
  441. // don't free account name.
  442. pszHelpAcctName = NULL;
  443. pszHelpAcctDomain = NULL;
  444. CLEANUPANDEXIT:
  445. if( NULL != pLsaHelpAccSid )
  446. {
  447. SecureZeroMemory( pLsaHelpAccSid, cbLsaHelpAccSid );
  448. FreeMemory( pLsaHelpAccSid );
  449. }
  450. if( NULL != pszHelpAcctDomain )
  451. {
  452. FreeMemory( pszHelpAcctDomain );
  453. }
  454. if( NULL != pszHelpAcctName )
  455. {
  456. FreeMemory(pszHelpAcctName);
  457. }
  458. return Status;
  459. }
  460. BOOL
  461. TSIsMachineInHelpMode()
  462. /*++
  463. Routine Description:
  464. Return if machine is in GetHelp mode
  465. Parameters:
  466. None.
  467. Returns:
  468. TRUE/FALSE
  469. --*/
  470. {
  471. //
  472. // machine can only be in help mode if we have some
  473. // password to derive session encryption key, if
  474. // no pending help session exist, sessmgr will end
  475. // encryption cycle.
  476. return TSHelpAssistantInEncryptionCycle();
  477. }
  478. ////////////////////////////////////////////////////////////////////////////
  479. DWORD
  480. EncryptLock()
  481. /*++
  482. Routine Description:
  483. Acquire encryption/decryption routine lock.
  484. Parameters:
  485. None.
  486. Returns:
  487. None.
  488. --*/
  489. {
  490. DWORD dwStatus;
  491. ASSERT( NULL != gm_hMutex );
  492. if( gm_hMutex )
  493. {
  494. dwStatus = WaitForSingleObject( gm_hMutex, INFINITE );
  495. ASSERT( WAIT_FAILED != dwStatus );
  496. }
  497. else
  498. {
  499. dwStatus = ERROR_INTERNAL_ERROR;
  500. }
  501. return dwStatus;
  502. }
  503. void
  504. EncryptUnlock()
  505. /*++
  506. Routine Description:
  507. Release encryption/decryption routine lock.
  508. Parameters:
  509. None.
  510. Returns:
  511. None.
  512. --*/
  513. {
  514. BOOL bSuccess;
  515. bSuccess = ReleaseMutex( gm_hMutex );
  516. ASSERT( TRUE == bSuccess );
  517. }
  518. LPTSTR
  519. GenerateEncryptionPassword()
  520. /*++
  521. Routine Description:
  522. Generate a random password to derive encryption key.
  523. Parameters:
  524. N/A
  525. Returns:
  526. NULL or random password, GetLastError() to
  527. retrieve detail error.
  528. Note:
  529. Use UUID as password to derive encryption key.
  530. --*/
  531. {
  532. RPC_STATUS rpcStatus;
  533. UUID uuid;
  534. LPTSTR pszUuidString = NULL;
  535. rpcStatus = UuidCreate( &uuid );
  536. if( rpcStatus == RPC_S_OK || rpcStatus == RPC_S_UUID_LOCAL_ONLY ||
  537. rpcStatus == RPC_S_UUID_NO_ADDRESS )
  538. {
  539. rpcStatus = UuidToString( &uuid, &pszUuidString );
  540. }
  541. return pszUuidString;
  542. }
  543. BOOL
  544. TSHelpAssistantInEncryptionCycle()
  545. {
  546. LPTSTR pszEncryptKey = NULL;
  547. DWORD cbEncryptKey = 0;
  548. DWORD dwStatus;
  549. dwStatus = EncryptLock();
  550. if( ERROR_SUCCESS == dwStatus )
  551. {
  552. //
  553. // Sessmgr will reset encryption password to NULL
  554. // if there is no help pending
  555. //
  556. dwStatus = RetrieveKeyFromLSA(
  557. SALEMHELPASSISTANTACCOUNT_ENCRYPTIONKEY,
  558. (PBYTE *)&pszEncryptKey,
  559. &cbEncryptKey
  560. );
  561. if( NULL != pszEncryptKey )
  562. {
  563. SecureZeroMemory( pszEncryptKey , cbEncryptKey );
  564. FreeMemory( pszEncryptKey );
  565. }
  566. EncryptUnlock();
  567. }
  568. return ERROR_SUCCESS == dwStatus;
  569. }
  570. DWORD
  571. TSHelpAssistantBeginEncryptionCycle()
  572. {
  573. DWORD dwStatus;
  574. LPTSTR pszKey = NULL;
  575. DWORD cbKey;
  576. ASSERT( NULL != gm_hMutex );
  577. dwStatus = EncryptLock();
  578. if( ERROR_SUCCESS == dwStatus )
  579. {
  580. //
  581. // Generate a random password for deriving encryption key
  582. //
  583. pszKey = GenerateEncryptionPassword();
  584. if( NULL != pszKey )
  585. {
  586. //
  587. // Store key deriving password into LSA
  588. //
  589. dwStatus = StoreKeyWithLSA(
  590. SALEMHELPASSISTANTACCOUNT_ENCRYPTIONKEY,
  591. (PBYTE)pszKey,
  592. (lstrlenW(pszKey)+1) * sizeof(WCHAR)
  593. );
  594. }
  595. else
  596. {
  597. dwStatus = GetLastError();
  598. }
  599. EncryptUnlock();
  600. }
  601. if( ERROR_SUCCESS == dwStatus )
  602. {
  603. HKEY Handle = NULL;
  604. DWORD dwInHelpMode = 1;
  605. dwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  606. KEY_READ | KEY_SET_VALUE, &Handle );
  607. if ( dwStatus == ERROR_SUCCESS )
  608. {
  609. dwStatus = RegSetValueEx(Handle,REG_MACHINE_IN_HELP_MODE,
  610. 0,REG_DWORD,(const BYTE *)&dwInHelpMode,
  611. sizeof(dwInHelpMode));
  612. }
  613. if(Handle)
  614. {
  615. RegCloseKey(Handle);
  616. }
  617. ASSERT( ERROR_SUCCESS == dwStatus );
  618. }
  619. if( NULL != pszKey )
  620. {
  621. // string is generated by UuidToString()
  622. SecureZeroMemory( pszKey , lstrlenW( pszKey ) * sizeof(WCHAR) );
  623. RpcStringFree( &pszKey );
  624. }
  625. return dwStatus;
  626. }
  627. DWORD
  628. TSHelpAssisantEndEncryptionCycle()
  629. /*++
  630. Routine Description:
  631. End an encryption cycle, a cycle is defined between first help
  632. created in help session manager to last pending help been resolved.
  633. Parameters:
  634. N/A
  635. Returns:
  636. ERROR_SUCCESS or LSA error code
  637. --*/
  638. {
  639. DWORD dwStatus;
  640. ASSERT( NULL != gm_hMutex );
  641. dwStatus = EncryptLock();
  642. if( ERROR_SUCCESS == dwStatus )
  643. {
  644. dwStatus = StoreKeyWithLSA(
  645. SALEMHELPASSISTANTACCOUNT_ENCRYPTIONKEY,
  646. (PBYTE)NULL,
  647. 0
  648. );
  649. EncryptUnlock();
  650. }
  651. if( ERROR_SUCCESS == dwStatus ) // should we not always do it?
  652. {
  653. HKEY Handle = NULL;
  654. DWORD dwInHelpMode = 0;
  655. dwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  656. KEY_READ | KEY_SET_VALUE, &Handle );
  657. if ( dwStatus == ERROR_SUCCESS )
  658. {
  659. dwStatus = RegSetValueEx(Handle,REG_MACHINE_IN_HELP_MODE,
  660. 0,REG_DWORD,(const BYTE *)&dwInHelpMode,
  661. sizeof(dwInHelpMode));
  662. }
  663. if(Handle)
  664. {
  665. RegCloseKey(Handle);
  666. }
  667. ASSERT( ERROR_SUCCESS == dwStatus );
  668. }
  669. return dwStatus;
  670. }
  671. HCRYPTKEY
  672. CreateEncryptDecryptKey(
  673. IN LPCTSTR pszEncryptPrefix,
  674. IN LPCTSTR pszPassword
  675. )
  676. /*++
  677. Routine Description:
  678. CreateEncryptDecryptKey() derive a session encryption/decryption
  679. key from password string.
  680. Parameters:
  681. pszEncryptPrefix : Optional string to be concatenated with password string to derives
  682. an encryption key.
  683. pszPassword : Pointer to password string to derives a session encryption
  684. decryption key.
  685. Returns:
  686. ERROR_SUCCESS or error code.
  687. Note:
  688. Caller must invoke EncryptLock();
  689. --*/
  690. {
  691. DWORD dwStatus = ERROR_SUCCESS;
  692. HCRYPTHASH hCryptHash = NULL;
  693. HCRYPTKEY hCryptKey = NULL;
  694. BOOL bStatus;
  695. LPTSTR pszEncryptKey = NULL;
  696. ASSERT( NULL != pszPassword );
  697. ASSERT( NULL != gm_hCryptProv );
  698. if( NULL != pszPassword && NULL != gm_hCryptProv )
  699. {
  700. if( pszEncryptPrefix )
  701. {
  702. pszEncryptKey = (LPTSTR)AllocMemory( (lstrlen(pszEncryptPrefix) + lstrlen(pszPassword) + 1) * sizeof(TCHAR) );
  703. if( NULL == pszEncryptKey )
  704. {
  705. // Out of memory, can't continue.
  706. goto CLEANUPANDEXIT;
  707. }
  708. lstrcpy( pszEncryptKey, pszEncryptPrefix );
  709. lstrcat( pszEncryptKey, pszPassword );
  710. }
  711. //
  712. // Derives a session key for encryption/decryption.
  713. //
  714. bStatus = CryptCreateHash(
  715. gm_hCryptProv,
  716. CALG_MD5,
  717. 0,
  718. 0,
  719. &hCryptHash
  720. );
  721. if( FALSE == bStatus )
  722. {
  723. dwStatus = GetLastError();
  724. ASSERT(FALSE);
  725. goto CLEANUPANDEXIT;
  726. }
  727. if( pszEncryptKey )
  728. {
  729. bStatus = CryptHashData(
  730. hCryptHash,
  731. (BYTE *)pszEncryptKey,
  732. lstrlen(pszEncryptKey) * sizeof(TCHAR),
  733. 0
  734. );
  735. }
  736. else
  737. {
  738. bStatus = CryptHashData(
  739. hCryptHash,
  740. (BYTE *)pszPassword,
  741. lstrlen(pszPassword) * sizeof(TCHAR),
  742. 0
  743. );
  744. }
  745. if( FALSE == bStatus )
  746. {
  747. dwStatus = GetLastError();
  748. ASSERT(FALSE);
  749. goto CLEANUPANDEXIT;
  750. }
  751. //
  752. // derive a session key for encrypt/decrypt
  753. //
  754. bStatus = CryptDeriveKey(
  755. gm_hCryptProv,
  756. ENCRYPT_ALGORITHM,
  757. hCryptHash,
  758. 0,
  759. &hCryptKey
  760. );
  761. if( FALSE == bStatus )
  762. {
  763. dwStatus = GetLastError();
  764. ASSERT(FALSE);
  765. }
  766. }
  767. else
  768. {
  769. SetLastError( dwStatus = ERROR_INVALID_PARAMETER );
  770. }
  771. CLEANUPANDEXIT:
  772. if( NULL != hCryptHash )
  773. {
  774. (void)CryptDestroyHash( hCryptHash );
  775. }
  776. if( NULL != pszEncryptKey )
  777. {
  778. SecureZeroMemory( pszEncryptKey , lstrlen( pszEncryptKey ) * sizeof( TCHAR ) );
  779. FreeMemory( pszEncryptKey );
  780. }
  781. return hCryptKey;
  782. }
  783. DWORD
  784. EnsureCryptoProviderCreated()
  785. {
  786. BOOL bStatus;
  787. DWORD dwStatus = ERROR_SUCCESS;
  788. dwStatus = EncryptLock();
  789. if( ERROR_SUCCESS == dwStatus )
  790. {
  791. //
  792. // Acquire a global Crypto provider
  793. //
  794. if( NULL == gm_hCryptProv )
  795. {
  796. bStatus = CryptAcquireContext(
  797. &gm_hCryptProv,
  798. HELPASSISTANT_CRYPT_CONTAINER,
  799. MS_DEF_PROV,
  800. PROV_RSA_FULL,
  801. 0
  802. );
  803. if( FALSE == bStatus )
  804. {
  805. // Create a container if not exists.
  806. bStatus = CryptAcquireContext(
  807. &gm_hCryptProv,
  808. HELPASSISTANT_CRYPT_CONTAINER,
  809. MS_DEF_PROV,
  810. PROV_RSA_FULL,
  811. CRYPT_NEWKEYSET
  812. );
  813. if( FALSE == bStatus )
  814. {
  815. dwStatus = GetLastError();
  816. ASSERT(FALSE);
  817. }
  818. }
  819. }
  820. EncryptUnlock();
  821. }
  822. return dwStatus;
  823. }
  824. HCRYPTKEY
  825. GetEncryptionCycleKey(
  826. IN LPCTSTR pszEncryptPrefix
  827. )
  828. /*++
  829. Routine Description:
  830. Create a encryption/decryption key for current encryption
  831. cycle, function first load password to derive session encryption
  832. key from LSA and invoke CryptAPI to create the session encryption
  833. key. If password is not in LSA, function return error.
  834. Parameters:
  835. None.
  836. Returns:
  837. Handle to session encryption key, NULL if error, use GetLastError to
  838. to retrieve detail error code.
  839. Note:
  840. Caller must invoke EncryptLock();
  841. --*/
  842. {
  843. LPTSTR pszEncryptKey;
  844. DWORD cbEncryptKey;
  845. DWORD dwStatus;
  846. HCRYPTKEY hCryptKey = NULL;
  847. //
  848. // Load password to derive session encryption key from LSA
  849. //
  850. dwStatus = RetrieveKeyFromLSA(
  851. SALEMHELPASSISTANTACCOUNT_ENCRYPTIONKEY,
  852. (PBYTE *)&pszEncryptKey,
  853. &cbEncryptKey
  854. );
  855. if( ERROR_SUCCESS == dwStatus )
  856. {
  857. //
  858. // Make sure global crypto provider exists.
  859. //
  860. dwStatus = EnsureCryptoProviderCreated();
  861. if( ERROR_SUCCESS == dwStatus )
  862. {
  863. //
  864. // Create the session encryption key.
  865. //
  866. hCryptKey = CreateEncryptDecryptKey( pszEncryptPrefix, pszEncryptKey );
  867. }
  868. SecureZeroMemory( pszEncryptKey , lstrlen( pszEncryptKey ) * sizeof( TCHAR ) );
  869. FreeMemory( pszEncryptKey );
  870. }
  871. return hCryptKey;
  872. }
  873. VOID
  874. TSHelpAssistantEndEncryptionLib()
  875. {
  876. //
  877. // ignore error code, this is only for shutdown
  878. //
  879. if( NULL != gm_hCryptProv )
  880. {
  881. CryptReleaseContext( gm_hCryptProv, 0 );
  882. gm_hCryptProv = NULL;
  883. }
  884. if( NULL != gm_hMutex )
  885. {
  886. ReleaseMutex( gm_hMutex );
  887. }
  888. return;
  889. }
  890. DWORD
  891. TSHelpAssistantInitializeEncryptionLib()
  892. /*++
  893. Routine Description:
  894. Initialize encryption/decryption library
  895. Parameters:
  896. None.
  897. Returns:
  898. ERROR_SUCCESS or error code.
  899. --*/
  900. {
  901. DWORD dwStatus = ERROR_SUCCESS;
  902. BOOL bStatus;
  903. LPTSTR pszEncryptKey;
  904. DWORD cbEncryptKey;
  905. ASSERT( NULL == gm_hCryptProv );
  906. ASSERT( NULL == gm_hMutex );
  907. //
  908. // Create a global mutex
  909. //
  910. gm_hMutex = CreateMutex(
  911. NULL,
  912. FALSE,
  913. SALEMHELPASSISTANTACCOUNT_ENCRYPTMUTEX
  914. );
  915. if( NULL == gm_hMutex )
  916. {
  917. dwStatus = GetLastError();
  918. ASSERT( NULL != gm_hMutex );
  919. }
  920. return dwStatus;
  921. }
  922. DWORD
  923. TSHelpAssistantEncryptData(
  924. IN LPCWSTR pszEncryptPrefixKey,
  925. IN OUT PBYTE pbData,
  926. IN OUT DWORD* pcbData
  927. )
  928. /*++
  929. Routine Description:
  930. Encrypt binary data, called must have invoked
  931. TSHelpAssistantInitializeEncryptionLib() and
  932. TSHelpAssistantBeginEncryptionCycle().
  933. Parameters:
  934. pbData : Pointer to binary data to be encrypted.
  935. pcbData : Size of binary data to be encrypted.
  936. Returns:
  937. ERROR_SUCCESS or error code.
  938. Note:
  939. Caller need to free ppbEncryptedData via LocalFree().
  940. --*/
  941. {
  942. DWORD dwStatus = ERROR_SUCCESS;
  943. BOOL bStatus;
  944. HCRYPTKEY hCryptKey = NULL;
  945. EXCEPTION_RECORD ExceptionCode;
  946. DWORD cbBufSize = *pcbData;
  947. dwStatus = EncryptLock();
  948. if( ERROR_SUCCESS == dwStatus )
  949. {
  950. //
  951. // Retrieve current cycle encryption key
  952. //
  953. hCryptKey = GetEncryptionCycleKey(pszEncryptPrefixKey);
  954. if( NULL == hCryptKey )
  955. {
  956. dwStatus = GetLastError();
  957. EncryptUnlock();
  958. goto CLEANUPANDEXIT;
  959. }
  960. //
  961. // Encrypt the data, not thread safe.
  962. //
  963. __try{
  964. // Stream cipher - same buffer size
  965. bStatus = CryptEncrypt(
  966. hCryptKey,
  967. NULL,
  968. TRUE,
  969. 0,
  970. pbData, // buffer to be encrypted
  971. pcbData, // buffer size
  972. cbBufSize // number of byte to be encrypt
  973. );
  974. if( FALSE == bStatus )
  975. {
  976. dwStatus = GetLastError();
  977. }
  978. }
  979. __except(
  980. ExceptionCode = *(GetExceptionInformation())->ExceptionRecord,
  981. EXCEPTION_EXECUTE_HANDLER )
  982. {
  983. bStatus = FALSE;
  984. dwStatus = ExceptionCode.ExceptionCode;
  985. }
  986. EncryptUnlock();
  987. //
  988. // Using stream cipher, has to be same size.
  989. //
  990. ASSERT( cbBufSize == *pcbData );
  991. }
  992. CLEANUPANDEXIT:
  993. if( NULL != hCryptKey )
  994. {
  995. CryptDestroyKey( hCryptKey );
  996. }
  997. return dwStatus;
  998. }
  999. DWORD
  1000. TSHelpAssistantDecryptData(
  1001. IN LPCWSTR pszEncryptPrefixKey,
  1002. IN OUT PBYTE pbData,
  1003. IN OUT DWORD* pcbData
  1004. )
  1005. /*++
  1006. Routine Description:
  1007. Decrypt data previously encrypted using TSHelpAssistantEncryptBase64EncodeData().
  1008. Parameters:
  1009. pbData : Stream of binary data to be decoded/decrypted.
  1010. pcbData : Size of data in bytes to be decrypted/decoded.
  1011. Returns:
  1012. ERROR_SUCCESS or error code
  1013. --*/
  1014. {
  1015. DWORD dwStatus = ERROR_SUCCESS;
  1016. BOOL bStatus;
  1017. HCRYPTKEY hCryptKey = NULL;
  1018. EXCEPTION_RECORD ExceptionCode;
  1019. DWORD dwBufSize = *pcbData;
  1020. dwStatus = EncryptLock();
  1021. if( ERROR_SUCCESS == dwStatus )
  1022. {
  1023. //
  1024. // Retrieve session encryption key for this encryption cycle.
  1025. //
  1026. hCryptKey = GetEncryptionCycleKey(pszEncryptPrefixKey);
  1027. if( NULL == hCryptKey )
  1028. {
  1029. dwStatus = GetLastError();
  1030. EncryptUnlock();
  1031. goto CLEANUPANDEXIT;
  1032. }
  1033. __try {
  1034. // Stream cipher - same buffer size
  1035. bStatus = CryptDecrypt(
  1036. hCryptKey,
  1037. NULL,
  1038. TRUE,
  1039. 0,
  1040. pbData,
  1041. pcbData
  1042. );
  1043. if( FALSE == bStatus )
  1044. {
  1045. dwStatus = GetLastError();
  1046. }
  1047. }
  1048. __except(
  1049. ExceptionCode = *(GetExceptionInformation())->ExceptionRecord,
  1050. EXCEPTION_EXECUTE_HANDLER )
  1051. {
  1052. bStatus = FALSE;
  1053. dwStatus = ExceptionCode.ExceptionCode;
  1054. }
  1055. EncryptUnlock();
  1056. //
  1057. // Stream cipher, same buffer size
  1058. ASSERT( dwBufSize == *pcbData );
  1059. }
  1060. CLEANUPANDEXIT:
  1061. if( NULL != hCryptKey )
  1062. {
  1063. CryptDestroyKey( hCryptKey );
  1064. }
  1065. return dwStatus;
  1066. }
  1067. BOOL
  1068. TSIsMachinePolicyAllowHelp()
  1069. /*++
  1070. Routine Description:
  1071. Check if 'GetHelp' is enabled on local machine, routine first query
  1072. system policy registry key, if policy is not set, then read salem
  1073. specific registry. Default to 'enable' is registry value does not
  1074. exist.
  1075. Parameters:
  1076. None.
  1077. Returns:
  1078. TRUE/FALSE
  1079. --*/
  1080. {
  1081. return RegIsMachinePolicyAllowHelp();
  1082. }
  1083. BOOL
  1084. TSIsMachineInSystemRestore()
  1085. /*+=
  1086. Routine Description:
  1087. Check if our special reg. value exist that indicate system restore
  1088. has rebooted machine.
  1089. Parameters:
  1090. None.
  1091. Returns:
  1092. TRUE/FALSE
  1093. --*/
  1094. {
  1095. DWORD dwStatus;
  1096. HKEY hKey = NULL;
  1097. DWORD cbData;
  1098. DWORD value;
  1099. DWORD type;
  1100. BOOL bInSystemRestore = FALSE;
  1101. dwStatus = RegOpenKeyEx(
  1102. HKEY_LOCAL_MACHINE,
  1103. REG_CONTROL_REMDSK L"\\" REG_CONTROL_HELPSESSIONENTRY,
  1104. 0,
  1105. KEY_ALL_ACCESS,
  1106. &hKey
  1107. );
  1108. if( ERROR_SUCCESS != dwStatus )
  1109. {
  1110. goto CLEANUPANDEXIT;
  1111. }
  1112. cbData = sizeof(value);
  1113. value = 0;
  1114. dwStatus = RegQueryValueEx(
  1115. hKey,
  1116. REG_VALUE_SYSTEMRESTORE,
  1117. 0,
  1118. &type,
  1119. (LPBYTE)&value,
  1120. &cbData
  1121. );
  1122. if( ERROR_SUCCESS == dwStatus && type == REG_DWORD && value == 1 )
  1123. {
  1124. bInSystemRestore = TRUE;
  1125. }
  1126. CLEANUPANDEXIT:
  1127. if( NULL != hKey )
  1128. {
  1129. RegCloseKey(hKey);
  1130. }
  1131. return bInSystemRestore;
  1132. }
  1133. DWORD
  1134. TSSystemRestoreCacheValues()
  1135. /*++
  1136. Routine Description:
  1137. Cache necessary LSA data that we use in Salem for system restore.
  1138. Parameters:
  1139. None.
  1140. Returns:
  1141. ERROR_SUCCESS or error code.
  1142. Note:
  1143. We can't cache HelpAssistant account SID as
  1144. 1) System restore will restore all user account.
  1145. 2) System restore also restore our LSA SID key.
  1146. since our account is created at setup time, account has to
  1147. match SID we cached.
  1148. --*/
  1149. {
  1150. DWORD dwStatus;
  1151. DWORD dwSize;
  1152. DWORD dwValue;
  1153. PBYTE pbData = NULL;
  1154. HKEY hCacheKey = NULL;
  1155. HKEY hRegControlKey = NULL;
  1156. DWORD dwType;
  1157. DWORD dwEncryptionDataSize = 0;
  1158. //
  1159. // Check if we just start up after rebooted from system restore.
  1160. //
  1161. dwStatus = RegOpenKeyEx(
  1162. HKEY_LOCAL_MACHINE,
  1163. REG_CONTROL_REMDSK L"\\" REG_CONTROL_HELPSESSIONENTRY,
  1164. 0,
  1165. KEY_ALL_ACCESS,
  1166. &hCacheKey
  1167. );
  1168. if( ERROR_SUCCESS != dwStatus )
  1169. {
  1170. // This registry key is created at setup time so must exist.
  1171. ASSERT(FALSE);
  1172. dwStatus = ERROR_INTERNAL_ERROR;
  1173. goto CLEANUPANDEXIT;
  1174. }
  1175. //
  1176. // Mark that we are in system restore.
  1177. //
  1178. dwSize = sizeof(dwValue);
  1179. dwValue = 1;
  1180. dwStatus = RegSetValueEx(
  1181. hCacheKey,
  1182. REG_VALUE_SYSTEMRESTORE,
  1183. 0,
  1184. REG_DWORD,
  1185. (LPBYTE)&dwValue,
  1186. dwSize
  1187. );
  1188. //
  1189. // Cache encryption cycle key.
  1190. //
  1191. dwStatus = TSGetEncryptionKey( &pbData, &dwEncryptionDataSize );
  1192. if( ERROR_SUCCESS != dwStatus )
  1193. {
  1194. goto CLEANUPANDEXIT;
  1195. }
  1196. dwStatus = RegSetValueEx(
  1197. hCacheKey,
  1198. REG_VALUE_SYSTEMRESTORE_ENCRYPTIONKEY,
  1199. 0,
  1200. REG_BINARY,
  1201. pbData,
  1202. dwEncryptionDataSize
  1203. );
  1204. //
  1205. // Cache fAllowToGetHelp
  1206. //
  1207. dwStatus = RegOpenKeyEx(
  1208. HKEY_LOCAL_MACHINE,
  1209. REG_CONTROL_TSERVER,
  1210. 0,
  1211. KEY_READ,
  1212. &hRegControlKey
  1213. );
  1214. if( ERROR_SUCCESS != dwStatus )
  1215. {
  1216. goto CLEANUPANDEXIT;
  1217. }
  1218. dwSize = sizeof(dwValue);
  1219. dwValue = 0;
  1220. dwType = 0;
  1221. dwStatus = RegQueryValueEx(
  1222. hRegControlKey,
  1223. POLICY_TS_REMDSK_ALLOWTOGETHELP,
  1224. 0,
  1225. &dwType,
  1226. (PBYTE)&dwValue,
  1227. &dwSize
  1228. );
  1229. // Key does not exist, assume no help is allow.
  1230. if( ERROR_SUCCESS != dwStatus || dwType != REG_DWORD )
  1231. {
  1232. dwValue = 0;
  1233. }
  1234. dwStatus = RegSetValueEx(
  1235. hCacheKey,
  1236. REG_VALUE_SYSTEMRESTORE_ALLOWTOGETHELP,
  1237. 0,
  1238. REG_DWORD,
  1239. (PBYTE)&dwValue,
  1240. dwSize
  1241. );
  1242. //
  1243. // Cache fInHelpMode
  1244. //
  1245. dwSize = sizeof(dwValue);
  1246. dwValue = 0;
  1247. dwType = 0;
  1248. dwStatus = RegQueryValueEx(
  1249. hRegControlKey,
  1250. REG_MACHINE_IN_HELP_MODE,
  1251. 0,
  1252. &dwType,
  1253. (PBYTE)&dwValue,
  1254. &dwSize
  1255. );
  1256. // Key does not exist, assume No help
  1257. if( ERROR_SUCCESS != dwStatus || dwType != REG_DWORD )
  1258. {
  1259. dwValue = 0;
  1260. }
  1261. dwStatus = RegSetValueEx(
  1262. hCacheKey,
  1263. REG_VALUE_SYSTEMRESTORE_INHELPMODE,
  1264. 0,
  1265. REG_DWORD,
  1266. (PBYTE)&dwValue,
  1267. dwSize
  1268. );
  1269. CLEANUPANDEXIT:
  1270. if( NULL != hCacheKey )
  1271. {
  1272. RegCloseKey( hCacheKey );
  1273. }
  1274. if( NULL != hRegControlKey )
  1275. {
  1276. RegCloseKey( hRegControlKey );
  1277. }
  1278. if( NULL != pbData )
  1279. {
  1280. SecureZeroMemory( pbData , dwEncryptionDataSize );
  1281. LocalFree( pbData );
  1282. }
  1283. return dwStatus;
  1284. }
  1285. DWORD
  1286. TSSystemRestoreResetValues()
  1287. /*++
  1288. Routine Description:
  1289. Reset necessary LSA data that we use in Salem for system restore.
  1290. Parameters:
  1291. None.
  1292. Returns:
  1293. ERROR_SUCCESS or error code.
  1294. --*/
  1295. {
  1296. DWORD dwStatus;
  1297. PBYTE pbData = NULL;
  1298. DWORD dwSize;
  1299. DWORD dwType;
  1300. DWORD dwValue;
  1301. HKEY hRegControlKey = NULL;
  1302. HKEY hCacheKey = NULL;
  1303. DWORD dwEncryptionDataSize = 0;
  1304. //
  1305. // Check if we just start up after rebooted from system restore.
  1306. //
  1307. dwStatus = RegOpenKeyEx(
  1308. HKEY_LOCAL_MACHINE,
  1309. REG_CONTROL_REMDSK L"\\" REG_CONTROL_HELPSESSIONENTRY,
  1310. 0,
  1311. KEY_ALL_ACCESS,
  1312. &hCacheKey
  1313. );
  1314. if( ERROR_SUCCESS != dwStatus )
  1315. {
  1316. // This registry key is created at setup time so must exist.
  1317. ASSERT(FALSE);
  1318. dwStatus = ERROR_INTERNAL_ERROR;
  1319. goto CLEANUPANDEXIT;
  1320. }
  1321. //
  1322. // Restore necessary LSA values.
  1323. //
  1324. dwStatus = RegQueryValueEx(
  1325. hCacheKey,
  1326. REG_VALUE_SYSTEMRESTORE_ENCRYPTIONKEY,
  1327. 0,
  1328. &dwType,
  1329. NULL,
  1330. &dwEncryptionDataSize
  1331. );
  1332. if( ERROR_SUCCESS != dwStatus || dwType != REG_BINARY )
  1333. {
  1334. goto CLEANUPANDEXIT;
  1335. }
  1336. pbData = (PBYTE) LocalAlloc( LPTR, dwEncryptionDataSize );
  1337. if( NULL == pbData )
  1338. {
  1339. dwStatus = GetLastError();
  1340. goto CLEANUPANDEXIT;
  1341. }
  1342. // Restore encryption key
  1343. dwStatus = RegQueryValueEx(
  1344. hCacheKey,
  1345. REG_VALUE_SYSTEMRESTORE_ENCRYPTIONKEY,
  1346. 0,
  1347. &dwType,
  1348. pbData,
  1349. &dwEncryptionDataSize
  1350. );
  1351. if( ERROR_SUCCESS != dwStatus )
  1352. {
  1353. goto CLEANUPANDEXIT;
  1354. }
  1355. dwStatus = TSSetEncryptionKey(pbData, dwEncryptionDataSize );
  1356. //
  1357. // Reset fAllowToGetHelp
  1358. //
  1359. dwStatus = RegOpenKeyEx(
  1360. HKEY_LOCAL_MACHINE,
  1361. REG_CONTROL_TSERVER,
  1362. 0,
  1363. KEY_READ | KEY_SET_VALUE,
  1364. &hRegControlKey
  1365. );
  1366. if( ERROR_SUCCESS != dwStatus )
  1367. {
  1368. goto CLEANUPANDEXIT;
  1369. }
  1370. dwSize = sizeof(dwValue);
  1371. dwValue = 0;
  1372. dwType = 0;
  1373. dwStatus = RegQueryValueEx(
  1374. hCacheKey,
  1375. REG_VALUE_SYSTEMRESTORE_ALLOWTOGETHELP,
  1376. 0,
  1377. &dwType,
  1378. (PBYTE)&dwValue,
  1379. &dwSize
  1380. );
  1381. // Key does not exist, assume no help is allow.
  1382. if( ERROR_SUCCESS != dwStatus || dwType != REG_DWORD )
  1383. {
  1384. dwValue = 0;
  1385. }
  1386. dwStatus = RegSetValueEx(
  1387. hRegControlKey,
  1388. POLICY_TS_REMDSK_ALLOWTOGETHELP,
  1389. 0,
  1390. REG_DWORD,
  1391. (PBYTE)&dwValue,
  1392. dwSize
  1393. );
  1394. //
  1395. // Reset fInHelpMode
  1396. //
  1397. dwSize = sizeof(dwValue);
  1398. dwValue = 0;
  1399. dwType = 0;
  1400. dwStatus = RegQueryValueEx(
  1401. hCacheKey,
  1402. REG_VALUE_SYSTEMRESTORE_INHELPMODE,
  1403. 0,
  1404. &dwType,
  1405. (PBYTE)&dwValue,
  1406. &dwSize
  1407. );
  1408. // Key does not exist, assume not in help
  1409. if( ERROR_SUCCESS != dwStatus || dwType != REG_DWORD )
  1410. {
  1411. dwValue = 0;
  1412. }
  1413. dwStatus = RegSetValueEx(
  1414. hRegControlKey,
  1415. REG_MACHINE_IN_HELP_MODE,
  1416. 0,
  1417. REG_DWORD,
  1418. (PBYTE)&dwValue,
  1419. dwSize
  1420. );
  1421. CLEANUPANDEXIT:
  1422. if( NULL != pbData )
  1423. {
  1424. SecureZeroMemory( pbData , dwEncryptionDataSize );
  1425. LocalFree(pbData);
  1426. }
  1427. if( NULL != hCacheKey )
  1428. {
  1429. RegDeleteValue( hCacheKey, REG_VALUE_SYSTEMRESTORE_ENCRYPTIONKEY );
  1430. RegDeleteValue( hCacheKey, REG_VALUE_SYSTEMRESTORE );
  1431. RegDeleteValue( hCacheKey, REG_VALUE_SYSTEMRESTORE_ALLOWTOGETHELP );
  1432. RegDeleteValue( hCacheKey, REG_VALUE_SYSTEMRESTORE_INHELPMODE );
  1433. RegCloseKey( hCacheKey );
  1434. }
  1435. if( NULL != hRegControlKey )
  1436. {
  1437. RegCloseKey( hRegControlKey );
  1438. }
  1439. return dwStatus;
  1440. }
  1441. BOOL
  1442. TSIsFireWallPortsOpen()
  1443. /*++
  1444. Routine Description:
  1445. Checks DirectPlayNatHelp regkeys to see any entries exist. This could
  1446. mean that entries are active or stale. The caller must update the
  1447. DPHUPNP server status to remove stale entries.
  1448. Parameters:
  1449. None.
  1450. Returns:
  1451. ERROR_SUCCESS or error code.
  1452. --*/
  1453. {
  1454. DWORD dwStatus;
  1455. BOOL fPortEntryFound = FALSE;
  1456. TCHAR szValueNameBuffer[ MAX_PATH ];
  1457. DWORD cbValueNameCharCount = MAX_PATH;
  1458. HKEY hKey = NULL;
  1459. // check to see if values exist under regkey ActiveFirewallMappings
  1460. dwStatus = RegOpenKeyEx(
  1461. HKEY_LOCAL_MACHINE ,
  1462. L"Software\\Microsoft\\DirectPlayNATHelp\\DPNHUPnP\\ActiveFirewallMappings",
  1463. 0,
  1464. KEY_READ,
  1465. &hKey );
  1466. if( dwStatus == ERROR_SUCCESS )
  1467. {
  1468. // see if there is at least one entry under this key
  1469. dwStatus = RegEnumValue(
  1470. hKey ,
  1471. 0 , // first item
  1472. &szValueNameBuffer[0] ,
  1473. &cbValueNameCharCount ,
  1474. NULL , // reserved
  1475. NULL , // type is not required
  1476. NULL , // data is not required - pass in NULL
  1477. NULL // size of data not required
  1478. );
  1479. // an error such as ERROR_NO_MORE_ITEMS would mean that there are no
  1480. // items under this key and fPortEntryFound should be set to FALSE
  1481. if( dwStatus == ERROR_SUCCESS )
  1482. {
  1483. fPortEntryFound = TRUE;
  1484. }
  1485. RegCloseKey( hKey );
  1486. }
  1487. // no need to check secondary registry key if we have entries in the
  1488. // first key
  1489. if( !fPortEntryFound )
  1490. {
  1491. // check to see if values exist under this key ActiveNATMappings
  1492. dwStatus = RegOpenKeyEx(
  1493. HKEY_LOCAL_MACHINE ,
  1494. L"Software\\Microsoft\\DirectPlayNATHelp\\DPNHUPnP\\ActiveNATMappings",
  1495. 0,
  1496. KEY_READ,
  1497. &hKey );
  1498. if( dwStatus == ERROR_SUCCESS )
  1499. {
  1500. // see if there is at least one entry under this key
  1501. dwStatus = RegEnumValue(
  1502. hKey ,
  1503. 0 , // first item
  1504. &szValueNameBuffer[0] ,
  1505. &cbValueNameCharCount ,
  1506. NULL , // reserved
  1507. NULL , // type is not required
  1508. NULL , // data is not required - pass in NULL
  1509. NULL // size of data not required
  1510. );
  1511. if( dwStatus == ERROR_SUCCESS )
  1512. {
  1513. fPortEntryFound = TRUE;
  1514. }
  1515. RegCloseKey( hKey );
  1516. }
  1517. }
  1518. return fPortEntryFound;
  1519. }