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.

1852 lines
42 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. security.cxx
  5. Abstract:
  6. This module contains the code necessary to implement secure DCOM data
  7. transfers on-the-wire. It includes the implementation of the "hooked"
  8. (call_as) methods from IMSAdminBase.
  9. Author:
  10. Keith Moore (keithmo) 17-Feb-1997
  11. Revision History:
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <ole2.h>
  17. #include <windows.h>
  18. #include <dbgutil.h>
  19. #include <iadmw.h>
  20. #include <icrypt.hxx>
  21. #include <secdat.hxx>
  22. #include <secpriv.h>
  23. //
  24. // Private constants.
  25. //
  26. #define ALLOC_MEM(cb) (LPVOID)::LocalAlloc( LPTR, (cb) )
  27. #define FREE_MEM(ptr) (VOID)::LocalFree( (HLOCAL)(ptr) )
  28. #if DBG
  29. BOOL g_fEnableSecureChannel = TRUE;
  30. #define ENABLE_SECURE_CHANNEL g_fEnableSecureChannel
  31. #else
  32. #define ENABLE_SECURE_CHANNEL TRUE
  33. #endif
  34. BOOL g_fStopOnKeyset = TRUE;
  35. //
  36. // Private prototypes.
  37. //
  38. VOID
  39. CalculateGetAllBufferAttributes(
  40. IN PMETADATA_GETALL_RECORD Data,
  41. IN DWORD NumEntries,
  42. OUT DWORD * TotalBufferLength,
  43. OUT BOOL * IsBufferSecure
  44. );
  45. HRESULT
  46. STDMETHODCALLTYPE
  47. IMSAdminBaseW_SetData_Proxy(
  48. IMSAdminBaseW __RPC_FAR * This,
  49. /* [in] */ METADATA_HANDLE hMDHandle,
  50. /* [string][in][unique] */ LPCWSTR pszMDPath,
  51. /* [in] */ PMETADATA_RECORD pmdrMDData
  52. )
  53. /*++
  54. Routine Description:
  55. Set a data object.
  56. Arguments:
  57. hMDHandle - open handle
  58. pszMDPath - path of the meta object with which this data is associated
  59. pmdrMDData - data to set
  60. Return Value:
  61. Status.
  62. --*/
  63. {
  64. HRESULT result;
  65. ADM_SECURE_DATA * secureData;
  66. IIS_CRYPTO_STORAGE * sendCrypto;
  67. PIIS_CRYPTO_BLOB dataBlob;
  68. METADATA_RECORD capturedRecord = {0};
  69. //
  70. // Setup locals so we know how to cleanup on exit.
  71. //
  72. secureData = NULL;
  73. sendCrypto = NULL;
  74. dataBlob = NULL;
  75. result = NO_ERROR;
  76. //
  77. // Trap the case of a null METADATA_RECORD
  78. //
  79. if( pmdrMDData == NULL )
  80. {
  81. result = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
  82. goto cleanup;
  83. }
  84. //
  85. // Capture the METADATA_RECORD so we can muck with it.
  86. //
  87. __try {
  88. capturedRecord = *pmdrMDData;
  89. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  90. result = HRESULT_FROM_NT( GetExceptionCode() );
  91. }
  92. if( FAILED(result) ) {
  93. goto cleanup;
  94. }
  95. //
  96. // If this is a secure data item, then encrypt the data before
  97. // sending.
  98. //
  99. #if DBG
  100. if( ENABLE_SECURE_CHANNEL &&
  101. (capturedRecord.dwMDAttributes & METADATA_SECURE) &&
  102. ((PVOID)capturedRecord.pbMDData != NULL) ) {
  103. #else
  104. if( (capturedRecord.dwMDAttributes & METADATA_SECURE) &&
  105. ((PVOID)capturedRecord.pbMDData != NULL) ) {
  106. #endif
  107. //
  108. // Find an ADM_SECURE_DATA object for "This".
  109. //
  110. secureData = ADM_SECURE_DATA::FindOrAddAndReferenceClientSecureData( This );
  111. if( secureData == NULL ) {
  112. result = MD_ERROR_SECURE_CHANNEL_FAILURE;
  113. goto cleanup;
  114. }
  115. //
  116. // Get the appropriate crypto storage object. This will perform
  117. // key exchange if necessary.
  118. //
  119. result = secureData->GetClientSendCryptoStorage( &sendCrypto,
  120. This );
  121. DBG_ASSERT( SUCCEEDED( result ) || !g_fStopOnKeyset );
  122. if( FAILED(result) ) {
  123. goto cleanup;
  124. }
  125. //
  126. // Protect ourselves from malicious users.
  127. //
  128. __try {
  129. //
  130. // Encrypt the data.
  131. //
  132. result = sendCrypto->EncryptData(
  133. &dataBlob,
  134. (PVOID)capturedRecord.pbMDData,
  135. capturedRecord.dwMDDataLen,
  136. 0 // dwRegType
  137. );
  138. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  139. result = HRESULT_FROM_NT(GetExceptionCode());
  140. }
  141. DBG_ASSERT( SUCCEEDED( result ) || !g_fStopOnKeyset );
  142. if( FAILED(result) ) {
  143. goto cleanup;
  144. }
  145. //
  146. // Update the fields of the captured metadata record so the
  147. // RPC runtime will send the data to the server.
  148. //
  149. capturedRecord.pbMDData = (PBYTE)dataBlob;
  150. capturedRecord.dwMDDataLen = IISCryptoGetBlobLength( dataBlob );
  151. }
  152. //
  153. // Call through to the "real" remoted API to get this over to the
  154. // server.
  155. //
  156. result = IMSAdminBaseW_R_SetData_Proxy(
  157. This,
  158. hMDHandle,
  159. pszMDPath,
  160. &capturedRecord
  161. );
  162. cleanup:
  163. DBG_ASSERT( !g_fStopOnKeyset ||
  164. ( ( result != NTE_BAD_KEYSET ) &&
  165. ( result != NTE_KEYSET_NOT_DEF ) &&
  166. ( result != NTE_KEYSET_ENTRY_BAD ) &&
  167. ( result != NTE_BAD_KEYSET_PARAM ) ) );
  168. if( dataBlob != NULL ) {
  169. IISCryptoFreeBlob( dataBlob );
  170. }
  171. if( secureData != NULL ) {
  172. secureData->Dereference();
  173. }
  174. return result;
  175. } // IMSAdminBaseW_SetData_Proxy
  176. HRESULT
  177. STDMETHODCALLTYPE
  178. IMSAdminBaseW_SetData_Stub(
  179. IMSAdminBaseW __RPC_FAR * This,
  180. /* [in] */ METADATA_HANDLE hMDHandle,
  181. /* [string][in][unique] */ LPCWSTR pszMDPath,
  182. /* [in] */ PMETADATA_RECORD pmdrMDData
  183. )
  184. /*++
  185. Routine Description:
  186. Set a data object.
  187. Arguments:
  188. hMDHandle - open handle
  189. pszMDPath - path of the meta object with which this data is associated
  190. pmdrMDData - data to set
  191. Return Value:
  192. Status.
  193. --*/
  194. {
  195. HRESULT result;
  196. ADM_SECURE_DATA * secureData;
  197. IIS_CRYPTO_STORAGE * recvCrypto;
  198. METADATA_RECORD capturedRecord;
  199. DWORD clearDataType;
  200. //
  201. // Setup locals so we know how to cleanup on exit.
  202. //
  203. secureData = NULL;
  204. recvCrypto = NULL;
  205. result = NO_ERROR;
  206. //
  207. // Capture the metadata record so we can muck with it.
  208. //
  209. capturedRecord = *pmdrMDData;
  210. //
  211. // If this is a secure data item, then decrypt the data before
  212. // passing it to the actual implementation object.
  213. //
  214. #if DBG
  215. if( ENABLE_SECURE_CHANNEL &&
  216. (capturedRecord.dwMDAttributes & METADATA_SECURE) &&
  217. (capturedRecord.pbMDData != NULL) ) {
  218. #else
  219. if( (capturedRecord.dwMDAttributes & METADATA_SECURE) &&
  220. (capturedRecord.pbMDData != NULL) ) {
  221. #endif
  222. //
  223. // Find an ADM_SECURE_DATA object for "This".
  224. //
  225. secureData = ADM_SECURE_DATA::FindAndReferenceServerSecureData(
  226. This,
  227. TRUE // CreateIfNotFound
  228. );
  229. if( secureData == NULL ) {
  230. result = MD_ERROR_SECURE_CHANNEL_FAILURE;
  231. goto cleanup;
  232. }
  233. //
  234. // Get the appropriate crypto storage object.
  235. //
  236. result = secureData->GetServerReceiveCryptoStorage( &recvCrypto );
  237. DBG_ASSERT( SUCCEEDED( result ) || !g_fStopOnKeyset );
  238. if ( FAILED(result) ) {
  239. goto cleanup;
  240. }
  241. //
  242. // Decrypt the data, then replace the pointer in the metadata
  243. // record.
  244. //
  245. result = recvCrypto->DecryptData(
  246. (PVOID *)&capturedRecord.pbMDData,
  247. &capturedRecord.dwMDDataLen,
  248. &clearDataType,
  249. (PIIS_CRYPTO_BLOB)capturedRecord.pbMDData
  250. );
  251. DBG_ASSERT( SUCCEEDED( result ) || !g_fStopOnKeyset );
  252. if( FAILED(result) ) {
  253. goto cleanup;
  254. }
  255. }
  256. //
  257. // Call through to the "real" server stub to set the data.
  258. //
  259. result = This->SetData(
  260. hMDHandle,
  261. pszMDPath,
  262. &capturedRecord
  263. );
  264. cleanup:
  265. DBG_ASSERT( !g_fStopOnKeyset ||
  266. ( ( result != NTE_BAD_KEYSET ) &&
  267. ( result != NTE_KEYSET_NOT_DEF ) &&
  268. ( result != NTE_KEYSET_ENTRY_BAD ) &&
  269. ( result != NTE_BAD_KEYSET_PARAM ) ) );
  270. if( secureData != NULL ) {
  271. secureData->Dereference();
  272. }
  273. return result;
  274. } // IMSAdminBaseW_SetData_Stub
  275. HRESULT
  276. STDMETHODCALLTYPE
  277. IMSAdminBaseW_GetData_Proxy(
  278. IMSAdminBaseW __RPC_FAR * This,
  279. /* [in] */ METADATA_HANDLE hMDHandle,
  280. /* [string][in][unique] */ LPCWSTR pszMDPath,
  281. /* [out][in] */ PMETADATA_RECORD pmdrMDData,
  282. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen
  283. )
  284. /*++
  285. Routine Description:
  286. Get one metadata value
  287. Arguments:
  288. hMDHandle - open handle
  289. pszMDPath - path of the meta object with which this data is associated
  290. pmdrMDData - data structure
  291. pdwMDRequiredDataLen - updated with required length
  292. Return Value:
  293. Status.
  294. --*/
  295. {
  296. HRESULT result;
  297. ADM_SECURE_DATA * secureData;
  298. IIS_CRYPTO_STORAGE * recvCrypto;
  299. IIS_CRYPTO_BLOB *dataBlob;
  300. METADATA_RECORD capturedRecord;
  301. PVOID dataBuffer;
  302. DWORD dataBufferLength;
  303. DWORD dataBufferType;
  304. //
  305. // Setup locals so we know how to cleanup on exit.
  306. //
  307. secureData = NULL;
  308. recvCrypto = NULL;
  309. dataBlob = NULL;
  310. //
  311. // Trap the case of a null METADATA_RECORD
  312. //
  313. if( pmdrMDData == NULL )
  314. {
  315. result = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
  316. goto cleanup;
  317. }
  318. //
  319. // Find an ADM_SECURE_DATA object for "This".
  320. //
  321. secureData = ADM_SECURE_DATA::FindOrAddAndReferenceClientSecureData( This );
  322. if( secureData == NULL ) {
  323. result = MD_ERROR_SECURE_CHANNEL_FAILURE;
  324. goto cleanup;
  325. }
  326. //
  327. // Get the appropriate crypto storage object. This will perform
  328. // key exchange if necessary.
  329. //
  330. result = secureData->GetClientReceiveCryptoStorage( &recvCrypto,
  331. This );
  332. if( FAILED(result) ) {
  333. goto cleanup;
  334. }
  335. //
  336. // Capture the METADATA_RECORD so we can muck with it.
  337. //
  338. __try {
  339. capturedRecord = *pmdrMDData;
  340. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  341. result = HRESULT_FROM_NT( GetExceptionCode() );
  342. }
  343. if( FAILED(result) ) {
  344. goto cleanup;
  345. }
  346. //
  347. // Call through to the "real" remoted API to get the data from
  348. // the server. Note that we set the data pointer to NULL before
  349. // calling the remoted API. This prevents the RPC runtime from
  350. // sending plaintext data over to the server.
  351. //
  352. capturedRecord.pbMDData = NULL;
  353. result = IMSAdminBaseW_R_GetData_Proxy(
  354. This,
  355. hMDHandle,
  356. pszMDPath,
  357. &capturedRecord,
  358. pdwMDRequiredDataLen,
  359. &dataBlob
  360. );
  361. if( FAILED(result) ) {
  362. goto cleanup;
  363. }
  364. //
  365. // Decrypt the data if necessary. This method properly handles
  366. // cleartext (unencrypted) blobs.
  367. //
  368. result = recvCrypto->DecryptData(
  369. &dataBuffer,
  370. &dataBufferLength,
  371. &dataBufferType,
  372. dataBlob
  373. );
  374. if( FAILED(result) ) {
  375. goto cleanup;
  376. }
  377. //
  378. // Copy it back to the user.
  379. //
  380. __try {
  381. if( pmdrMDData->dwMDDataLen >= dataBufferLength ) {
  382. RtlCopyMemory(
  383. pmdrMDData->pbMDData,
  384. dataBuffer,
  385. dataBufferLength
  386. );
  387. pmdrMDData->dwMDDataLen = dataBufferLength;
  388. pmdrMDData->dwMDIdentifier = capturedRecord.dwMDIdentifier;
  389. pmdrMDData->dwMDAttributes = capturedRecord.dwMDAttributes;
  390. pmdrMDData->dwMDUserType = capturedRecord.dwMDUserType;
  391. pmdrMDData->dwMDDataType = capturedRecord.dwMDDataType;
  392. pmdrMDData->dwMDDataTag = capturedRecord.dwMDDataTag;
  393. } else {
  394. *pdwMDRequiredDataLen = dataBufferLength;
  395. result = RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER );
  396. }
  397. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  398. result = HRESULT_FROM_NT( GetExceptionCode() );
  399. }
  400. if( FAILED(result) ) {
  401. goto cleanup;
  402. }
  403. cleanup:
  404. if( secureData != NULL ) {
  405. secureData->Dereference();
  406. }
  407. if( dataBlob != NULL ) {
  408. ::IISCryptoFreeBlob( dataBlob );
  409. }
  410. return result;
  411. } // IMSAdminBaseW_GetData_Proxy
  412. HRESULT
  413. STDMETHODCALLTYPE
  414. IMSAdminBaseW_GetData_Stub(
  415. IMSAdminBaseW __RPC_FAR * This,
  416. /* [in] */ METADATA_HANDLE hMDHandle,
  417. /* [string][in][unique] */ LPCWSTR pszMDPath,
  418. /* [out][in] */ PMETADATA_RECORD pmdrMDData,
  419. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen,
  420. /* [out] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *__RPC_FAR *ppDataBlob
  421. )
  422. /*++
  423. Routine Description:
  424. Get one metadata value
  425. Arguments:
  426. hMDHandle - open handle
  427. pszMDPath - path of the meta object with which this data is associated
  428. pmdrMDData - data structure
  429. pdwMDRequiredDataLen - updated with required length
  430. ppDataBlob - Receives a blob for the encrypted data.
  431. Return Value:
  432. Status.
  433. --*/
  434. {
  435. HRESULT result;
  436. ADM_SECURE_DATA * secureData;
  437. IIS_CRYPTO_STORAGE * sendCrypto;
  438. IIS_CRYPTO_BLOB *dataBlob;
  439. PVOID dataBuffer;
  440. //
  441. // Setup locals so we know how to cleanup on exit.
  442. //
  443. secureData = NULL;
  444. sendCrypto = NULL;
  445. dataBuffer = NULL;
  446. dataBlob = NULL;
  447. //
  448. // Allocate a temporary memory block for the meta data. Use the
  449. // same size as the user passed into the API.
  450. //
  451. dataBuffer = ALLOC_MEM( pmdrMDData->dwMDDataLen );
  452. if( dataBuffer == NULL ) {
  453. result = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  454. goto cleanup;
  455. }
  456. pmdrMDData->pbMDData = (PBYTE)dataBuffer;
  457. //
  458. // Call through to the "real" server stub to get the data.
  459. //
  460. result = This->GetData(
  461. hMDHandle,
  462. pszMDPath,
  463. pmdrMDData,
  464. pdwMDRequiredDataLen
  465. );
  466. if( FAILED(result) ) {
  467. goto cleanup;
  468. }
  469. //
  470. // If this is a secure data item, then we'll need to encrypt it
  471. // before returning it to the client. Otherwise, we'll build a
  472. // cleartext blob to contain the data.
  473. //
  474. #if DBG
  475. if( ENABLE_SECURE_CHANNEL &&
  476. pmdrMDData->dwMDAttributes & METADATA_SECURE ) {
  477. #else
  478. if( pmdrMDData->dwMDAttributes & METADATA_SECURE ) {
  479. #endif
  480. //
  481. // Find an ADM_SECURE_DATA object for "This".
  482. //
  483. secureData = ADM_SECURE_DATA::FindAndReferenceServerSecureData(
  484. This,
  485. TRUE // CreateIfNotFound
  486. );
  487. if( secureData == NULL ) {
  488. result = MD_ERROR_SECURE_CHANNEL_FAILURE;
  489. goto cleanup;
  490. }
  491. //
  492. // Get the appropriate crypto storage object.
  493. //
  494. result = secureData->GetServerSendCryptoStorage( &sendCrypto );
  495. if( FAILED(result) ) {
  496. goto cleanup;
  497. }
  498. //
  499. // Encrypt the data.
  500. //
  501. result = sendCrypto->EncryptData(
  502. &dataBlob,
  503. (PVOID)pmdrMDData->pbMDData,
  504. pmdrMDData->dwMDDataLen,
  505. 0
  506. );
  507. if( FAILED(result) ) {
  508. goto cleanup;
  509. }
  510. } else {
  511. result = ::IISCryptoCreateCleartextBlob(
  512. &dataBlob,
  513. (PVOID)pmdrMDData->pbMDData,
  514. pmdrMDData->dwMDDataLen
  515. );
  516. if( FAILED(result) ) {
  517. goto cleanup;
  518. }
  519. }
  520. //
  521. // Success!
  522. //
  523. DBG_ASSERT( SUCCEEDED(result) );
  524. *ppDataBlob = dataBlob;
  525. cleanup:
  526. //
  527. // NULL the data pointer in the METADATA_RECORD so the RPC runtime
  528. // won't send the plaintext data back to the client.
  529. //
  530. pmdrMDData->pbMDData = NULL;
  531. if( secureData != NULL ) {
  532. secureData->Dereference();
  533. }
  534. if( dataBuffer != NULL ) {
  535. FREE_MEM( dataBuffer );
  536. }
  537. if( FAILED(result) && dataBlob != NULL ) {
  538. ::IISCryptoFreeBlob( dataBlob );
  539. }
  540. return result;
  541. } // IMSAdminBaseW_GetData_Stub
  542. HRESULT
  543. STDMETHODCALLTYPE
  544. IMSAdminBaseW_EnumData_Proxy(
  545. IMSAdminBaseW __RPC_FAR * This,
  546. /* [in] */ METADATA_HANDLE hMDHandle,
  547. /* [string][in][unique] */ LPCWSTR pszMDPath,
  548. /* [out][in] */ PMETADATA_RECORD pmdrMDData,
  549. /* [in] */ DWORD dwMDEnumDataIndex,
  550. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen
  551. )
  552. /*++
  553. Routine Description:
  554. Enumerate properties of object.
  555. Arguments:
  556. hMDHandle - open handle
  557. pszMDPath - path of the meta object with which this data is associated
  558. pmdrMDData - data structure
  559. pdwMDRequiredDataLen - updated with required length
  560. Return Value:
  561. Status.
  562. --*/
  563. {
  564. HRESULT result;
  565. ADM_SECURE_DATA * secureData;
  566. IIS_CRYPTO_STORAGE * recvCrypto;
  567. IIS_CRYPTO_BLOB *dataBlob;
  568. METADATA_RECORD capturedRecord;
  569. PVOID dataBuffer;
  570. DWORD dataBufferLength;
  571. DWORD dataBufferType;
  572. //
  573. // Setup locals so we know how to cleanup on exit.
  574. //
  575. secureData = NULL;
  576. recvCrypto = NULL;
  577. dataBlob = NULL;
  578. //
  579. // Trap the case of a null METADATA_RECORD
  580. //
  581. if( pmdrMDData == NULL )
  582. {
  583. result = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
  584. goto cleanup;
  585. }
  586. //
  587. // Find an ADM_SECURE_DATA object for "This".
  588. //
  589. secureData = ADM_SECURE_DATA::FindOrAddAndReferenceClientSecureData( This );
  590. if( secureData == NULL ) {
  591. result = MD_ERROR_SECURE_CHANNEL_FAILURE;
  592. goto cleanup;
  593. }
  594. //
  595. // Get the appropriate crypto storage object. This will perform
  596. // key exchange if necessary.
  597. //
  598. result = secureData->GetClientReceiveCryptoStorage( &recvCrypto,
  599. This );
  600. if( FAILED(result) ) {
  601. goto cleanup;
  602. }
  603. //
  604. // Capture the METADATA_RECORD so we can muck with it.
  605. //
  606. __try {
  607. capturedRecord = *pmdrMDData;
  608. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  609. result = HRESULT_FROM_NT( GetExceptionCode() );
  610. }
  611. if( FAILED(result) ) {
  612. goto cleanup;
  613. }
  614. //
  615. // Call through to the "real" remoted API to get the data from
  616. // the server. Note that we set the data pointer to NULL before
  617. // calling the remoted API. This prevents the RPC runtime from
  618. // sending plaintext data over to the server.
  619. //
  620. capturedRecord.pbMDData = NULL;
  621. result = IMSAdminBaseW_R_EnumData_Proxy(
  622. This,
  623. hMDHandle,
  624. pszMDPath,
  625. &capturedRecord,
  626. dwMDEnumDataIndex,
  627. pdwMDRequiredDataLen,
  628. &dataBlob
  629. );
  630. if( FAILED(result) ) {
  631. goto cleanup;
  632. }
  633. //
  634. // Decrypt the data if necessary. This method properly handles
  635. // cleartext (unencrypted) blobs.
  636. //
  637. result = recvCrypto->DecryptData(
  638. &dataBuffer,
  639. &dataBufferLength,
  640. &dataBufferType,
  641. dataBlob
  642. );
  643. if( FAILED(result) ) {
  644. goto cleanup;
  645. }
  646. //
  647. // Copy it back to the user.
  648. //
  649. __try {
  650. if( pmdrMDData->dwMDDataLen >= dataBufferLength ) {
  651. RtlCopyMemory(
  652. pmdrMDData->pbMDData,
  653. dataBuffer,
  654. dataBufferLength
  655. );
  656. pmdrMDData->dwMDDataLen = dataBufferLength;
  657. pmdrMDData->dwMDIdentifier = capturedRecord.dwMDIdentifier;
  658. pmdrMDData->dwMDAttributes = capturedRecord.dwMDAttributes;
  659. pmdrMDData->dwMDUserType = capturedRecord.dwMDUserType;
  660. pmdrMDData->dwMDDataType = capturedRecord.dwMDDataType;
  661. pmdrMDData->dwMDDataTag = capturedRecord.dwMDDataTag;
  662. } else {
  663. *pdwMDRequiredDataLen = dataBufferLength;
  664. result = RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER );
  665. }
  666. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  667. result = HRESULT_FROM_NT( GetExceptionCode() );
  668. }
  669. if( FAILED(result) ) {
  670. goto cleanup;
  671. }
  672. cleanup:
  673. if( secureData != NULL ) {
  674. secureData->Dereference();
  675. }
  676. if( dataBlob != NULL ) {
  677. ::IISCryptoFreeBlob( dataBlob );
  678. }
  679. return result;
  680. } // IMSAdminBaseW_EnumData_Proxy
  681. HRESULT
  682. STDMETHODCALLTYPE
  683. IMSAdminBaseW_EnumData_Stub(
  684. IMSAdminBaseW __RPC_FAR * This,
  685. /* [in] */ METADATA_HANDLE hMDHandle,
  686. /* [string][in][unique] */ LPCWSTR pszMDPath,
  687. /* [out][in] */ PMETADATA_RECORD pmdrMDData,
  688. /* [in] */ DWORD dwMDEnumDataIndex,
  689. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen,
  690. /* [out] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *__RPC_FAR *ppDataBlob
  691. )
  692. /*++
  693. Routine Description:
  694. Enumerate properties of object.
  695. Arguments:
  696. hMDHandle - open handle
  697. pszMDPath - path of the meta object with which this data is associated
  698. pmdrMDData - data structure
  699. pdwMDRequiredDataLen - updated with required length
  700. ppDataBlob - Receives a blob for the encrypted data.
  701. Return Value:
  702. Status.
  703. --*/
  704. {
  705. HRESULT result;
  706. ADM_SECURE_DATA * secureData;
  707. IIS_CRYPTO_STORAGE * sendCrypto;
  708. IIS_CRYPTO_BLOB *dataBlob;
  709. PVOID dataBuffer;
  710. //
  711. // Setup locals so we know how to cleanup on exit.
  712. //
  713. secureData = NULL;
  714. sendCrypto = NULL;
  715. dataBuffer = NULL;
  716. dataBlob = NULL;
  717. //
  718. // Allocate a temporary memory block for the meta data. Use the
  719. // same size as the user passed into the API.
  720. //
  721. dataBuffer = ALLOC_MEM( pmdrMDData->dwMDDataLen );
  722. if( dataBuffer == NULL ) {
  723. result = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  724. goto cleanup;
  725. }
  726. pmdrMDData->pbMDData = (PBYTE)dataBuffer;
  727. //
  728. // Call through to the "real" server stub to get the data.
  729. //
  730. result = This->EnumData(
  731. hMDHandle,
  732. pszMDPath,
  733. pmdrMDData,
  734. dwMDEnumDataIndex,
  735. pdwMDRequiredDataLen
  736. );
  737. if( FAILED(result) ) {
  738. goto cleanup;
  739. }
  740. //
  741. // If this is a secure data item, then we'll need to encrypt it
  742. // before returning it to the client. Otherwise, we'll build a
  743. // cleartext blob to contain the data.
  744. //
  745. #if DBG
  746. if( ENABLE_SECURE_CHANNEL &&
  747. pmdrMDData->dwMDAttributes & METADATA_SECURE ) {
  748. #else
  749. if( pmdrMDData->dwMDAttributes & METADATA_SECURE ) {
  750. #endif
  751. //
  752. // Find an ADM_SECURE_DATA object for "This".
  753. //
  754. secureData = ADM_SECURE_DATA::FindAndReferenceServerSecureData(
  755. This,
  756. TRUE // CreateIfNotFound
  757. );
  758. if( secureData == NULL ) {
  759. result = MD_ERROR_SECURE_CHANNEL_FAILURE;
  760. goto cleanup;
  761. }
  762. //
  763. // Get the appropriate crypto storage object.
  764. //
  765. result = secureData->GetServerSendCryptoStorage( &sendCrypto );
  766. if( FAILED(result) ) {
  767. goto cleanup;
  768. }
  769. //
  770. // Encrypt the data.
  771. //
  772. result = sendCrypto->EncryptData(
  773. &dataBlob,
  774. (PVOID)pmdrMDData->pbMDData,
  775. pmdrMDData->dwMDDataLen,
  776. 0
  777. );
  778. if( FAILED(result) ) {
  779. goto cleanup;
  780. }
  781. } else {
  782. result = ::IISCryptoCreateCleartextBlob(
  783. &dataBlob,
  784. (PVOID)pmdrMDData->pbMDData,
  785. pmdrMDData->dwMDDataLen
  786. );
  787. if( FAILED(result) ) {
  788. goto cleanup;
  789. }
  790. }
  791. //
  792. // Success!
  793. //
  794. DBG_ASSERT( SUCCEEDED(result) );
  795. *ppDataBlob = dataBlob;
  796. cleanup:
  797. //
  798. // NULL the data pointer in the METADATA_RECORD so the RPC runtime
  799. // won't send the plaintext data back to the client.
  800. //
  801. pmdrMDData->pbMDData = NULL;
  802. if( secureData != NULL ) {
  803. secureData->Dereference();
  804. }
  805. if( dataBuffer != NULL ) {
  806. FREE_MEM( dataBuffer );
  807. }
  808. if( FAILED(result) && dataBlob != NULL ) {
  809. ::IISCryptoFreeBlob( dataBlob );
  810. }
  811. return result;
  812. } // IMSAdminBaseW_EnumData_Stub
  813. HRESULT
  814. STDMETHODCALLTYPE
  815. IMSAdminBaseW_GetAllData_Proxy(
  816. IMSAdminBaseW __RPC_FAR * This,
  817. /* [in] */ METADATA_HANDLE hMDHandle,
  818. /* [string][in][unique] */ LPCWSTR pszMDPath,
  819. /* [in] */ DWORD dwMDAttributes,
  820. /* [in] */ DWORD dwMDUserType,
  821. /* [in] */ DWORD dwMDDataType,
  822. /* [out] */ DWORD __RPC_FAR *pdwMDNumDataEntries,
  823. /* [out] */ DWORD __RPC_FAR *pdwMDDataSetNumber,
  824. /* [in] */ DWORD dwMDBufferSize,
  825. /* [size_is][out] */ unsigned char __RPC_FAR *pbBuffer,
  826. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize
  827. )
  828. /*++
  829. Routine Description:
  830. Gets all data associated with a Meta Object
  831. Arguments:
  832. hMDHandle - open handle
  833. pszMDPath - path of the meta object with which this data is associated
  834. dwMDAttributes - flags for the data
  835. dwMDUserType - user Type for the data
  836. dwMDDataType - type of the data
  837. pdwMDNumDataEntries - number of entries copied to Buffer
  838. pdwMDDataSetNumber - number associated with this data set
  839. dwMDBufferSize - size in bytes of buffer
  840. pbBuffer - buffer to store the data
  841. pdwMDRequiredBufferSize - updated with required length of buffer
  842. Return Value:
  843. Status.
  844. --*/
  845. {
  846. HRESULT result;
  847. ADM_SECURE_DATA * secureData;
  848. IIS_CRYPTO_STORAGE * recvCrypto;
  849. IIS_CRYPTO_BLOB *dataBlob;
  850. PVOID dataBuffer;
  851. DWORD dataBufferLength;
  852. DWORD dataBufferType;
  853. //
  854. // Setup locals so we know how to cleanup on exit.
  855. //
  856. secureData = NULL;
  857. recvCrypto = NULL;
  858. dataBlob = NULL;
  859. //
  860. // Find an ADM_SECURE_DATA object for "This".
  861. //
  862. secureData = ADM_SECURE_DATA::FindOrAddAndReferenceClientSecureData( This );
  863. if( secureData == NULL ) {
  864. result = MD_ERROR_SECURE_CHANNEL_FAILURE;
  865. goto cleanup;
  866. }
  867. //
  868. // Get the appropriate crypto storage object. This will perform
  869. // key exchange if necessary.
  870. //
  871. result = secureData->GetClientReceiveCryptoStorage( &recvCrypto,
  872. This );
  873. if( FAILED(result) ) {
  874. goto cleanup;
  875. }
  876. //
  877. // Call through to the "real" remoted API to get the data from
  878. // the server.
  879. //
  880. result = IMSAdminBaseW_R_GetAllData_Proxy(
  881. This,
  882. hMDHandle,
  883. pszMDPath,
  884. dwMDAttributes,
  885. dwMDUserType,
  886. dwMDDataType,
  887. pdwMDNumDataEntries,
  888. pdwMDDataSetNumber,
  889. dwMDBufferSize,
  890. pdwMDRequiredBufferSize,
  891. &dataBlob
  892. );
  893. if( FAILED(result) ) {
  894. goto cleanup;
  895. }
  896. //
  897. // Decrypt the data if necessary. This method properly handles
  898. // cleartext (unencrypted) blobs.
  899. //
  900. result = recvCrypto->DecryptData(
  901. &dataBuffer,
  902. &dataBufferLength,
  903. &dataBufferType,
  904. dataBlob
  905. );
  906. if( FAILED(result) ) {
  907. goto cleanup;
  908. }
  909. //
  910. // Copy it back to the user.
  911. //
  912. __try {
  913. if( dwMDBufferSize >= dataBufferLength ) {
  914. RtlCopyMemory(
  915. pbBuffer,
  916. dataBuffer,
  917. dataBufferLength
  918. );
  919. } else {
  920. *pdwMDRequiredBufferSize = dataBufferLength;
  921. result = RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER );
  922. }
  923. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  924. result = HRESULT_FROM_NT( GetExceptionCode() );
  925. }
  926. if( FAILED(result) ) {
  927. goto cleanup;
  928. }
  929. cleanup:
  930. if( secureData != NULL ) {
  931. secureData->Dereference();
  932. }
  933. if( dataBlob != NULL ) {
  934. ::IISCryptoFreeBlob( dataBlob );
  935. }
  936. return result;
  937. } // IMSAdminBaseW_GetAllData_Proxy
  938. HRESULT
  939. STDMETHODCALLTYPE
  940. IMSAdminBaseW_GetAllData_Stub(
  941. IMSAdminBaseW __RPC_FAR * This,
  942. /* [in] */ METADATA_HANDLE hMDHandle,
  943. /* [string][in][unique] */ LPCWSTR pszMDPath,
  944. /* [in] */ DWORD dwMDAttributes,
  945. /* [in] */ DWORD dwMDUserType,
  946. /* [in] */ DWORD dwMDDataType,
  947. /* [out] */ DWORD __RPC_FAR *pdwMDNumDataEntries,
  948. /* [out] */ DWORD __RPC_FAR *pdwMDDataSetNumber,
  949. /* [in] */ DWORD dwMDBufferSize,
  950. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize,
  951. /* [out] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *__RPC_FAR *ppDataBlob
  952. )
  953. /*++
  954. Routine Description:
  955. Gets all data associated with a Meta Object
  956. Arguments:
  957. hMDHandle - open handle
  958. pszMDPath - path of the meta object with which this data is associated
  959. dwMDAttributes - flags for the data
  960. dwMDUserType - user Type for the data
  961. dwMDDataType - type of the data
  962. pdwMDNumDataEntries - number of entries copied to Buffer
  963. pdwMDDataSetNumber - number associated with this data set
  964. dwMDBufferSize - size in bytes of buffer
  965. pdwMDRequiredBufferSize - updated with required length of buffer
  966. ppDataBlob - Receives a blob for the encrypted data.
  967. Return Value:
  968. Status.
  969. --*/
  970. {
  971. HRESULT result;
  972. ADM_SECURE_DATA * secureData;
  973. IIS_CRYPTO_STORAGE * sendCrypto;
  974. IIS_CRYPTO_BLOB *dataBlob;
  975. PVOID dataBuffer;
  976. DWORD getAllBufferLength;
  977. BOOL getAllBufferIsSecure;
  978. //
  979. // Setup locals so we know how to cleanup on exit.
  980. //
  981. secureData = NULL;
  982. sendCrypto = NULL;
  983. dataBuffer = NULL;
  984. dataBlob = NULL;
  985. //
  986. // Allocate a temporary memory block for the meta data. Use the
  987. // same size as the user passed into the API.
  988. //
  989. dataBuffer = ALLOC_MEM( dwMDBufferSize );
  990. if( dataBuffer == NULL ) {
  991. result = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  992. goto cleanup;
  993. }
  994. //
  995. // Call through to the "real" server stub to get the data.
  996. //
  997. result = This->GetAllData(
  998. hMDHandle,
  999. pszMDPath,
  1000. dwMDAttributes,
  1001. dwMDUserType,
  1002. dwMDDataType,
  1003. pdwMDNumDataEntries,
  1004. pdwMDDataSetNumber,
  1005. dwMDBufferSize,
  1006. (PBYTE)dataBuffer,
  1007. pdwMDRequiredBufferSize
  1008. );
  1009. if( FAILED(result) ) {
  1010. goto cleanup;
  1011. }
  1012. //
  1013. // Compute the total size of the METADATA_GETALL_RECORD. Also
  1014. // take this opportunity to determine if any of the data items
  1015. // within the record are marked as secure. We'll encrypt the
  1016. // entire record if any entry is secure.
  1017. //
  1018. CalculateGetAllBufferAttributes(
  1019. (PMETADATA_GETALL_RECORD)dataBuffer,
  1020. *pdwMDNumDataEntries,
  1021. &getAllBufferLength,
  1022. &getAllBufferIsSecure
  1023. );
  1024. //
  1025. // Encrypt if necessary.
  1026. //
  1027. if( getAllBufferIsSecure ) {
  1028. //
  1029. // Find an ADM_SECURE_DATA object for "This".
  1030. //
  1031. secureData = ADM_SECURE_DATA::FindAndReferenceServerSecureData(
  1032. This,
  1033. TRUE // CreateIfNotFound
  1034. );
  1035. if( secureData == NULL ) {
  1036. result = MD_ERROR_SECURE_CHANNEL_FAILURE;
  1037. goto cleanup;
  1038. }
  1039. //
  1040. // Get the appropriate crypto storage object.
  1041. //
  1042. result = secureData->GetServerSendCryptoStorage( &sendCrypto );
  1043. if( FAILED(result) ) {
  1044. goto cleanup;
  1045. }
  1046. //
  1047. // Encrypt the data.
  1048. //
  1049. result = sendCrypto->EncryptData(
  1050. &dataBlob,
  1051. dataBuffer,
  1052. getAllBufferLength,
  1053. 0
  1054. );
  1055. if( FAILED(result) ) {
  1056. goto cleanup;
  1057. }
  1058. } else {
  1059. result = ::IISCryptoCreateCleartextBlob(
  1060. &dataBlob,
  1061. dataBuffer,
  1062. getAllBufferLength
  1063. );
  1064. if( FAILED(result) ) {
  1065. goto cleanup;
  1066. }
  1067. }
  1068. //
  1069. // Success!
  1070. //
  1071. DBG_ASSERT( SUCCEEDED(result) );
  1072. *ppDataBlob = dataBlob;
  1073. cleanup:
  1074. if( secureData != NULL ) {
  1075. secureData->Dereference();
  1076. }
  1077. if( dataBuffer != NULL ) {
  1078. FREE_MEM( dataBuffer );
  1079. }
  1080. if( FAILED(result) && dataBlob != NULL ) {
  1081. ::IISCryptoFreeBlob( dataBlob );
  1082. }
  1083. return result;
  1084. } // IMSAdminBaseW_GetAllData_Stub
  1085. HRESULT
  1086. STDMETHODCALLTYPE
  1087. IMSAdminBaseW_GetServerGuid_Proxy(
  1088. IMSAdminBaseW __RPC_FAR *
  1089. )
  1090. {
  1091. return E_FAIL;
  1092. } // IMSAdminBaseW_GetServerGuid_Proxy
  1093. HRESULT
  1094. STDMETHODCALLTYPE
  1095. IMSAdminBaseW_GetServerGuid_Stub(
  1096. IMSAdminBaseW __RPC_FAR * This,
  1097. /* [out] */ GUID __RPC_FAR *pServerGuid)
  1098. {
  1099. ADM_SECURE_DATA * secureData;
  1100. //
  1101. // Find an ADM_SECURE_DATA object for "This".
  1102. //
  1103. secureData = ADM_SECURE_DATA::FindAndReferenceServerSecureData(
  1104. This,
  1105. TRUE // CreateIfNotFound
  1106. );
  1107. if( secureData == NULL ) {
  1108. return MD_ERROR_SECURE_CHANNEL_FAILURE;
  1109. }
  1110. *pServerGuid = secureData->GetGuid();
  1111. secureData->Dereference();
  1112. return ERROR_SUCCESS;
  1113. }
  1114. HRESULT
  1115. STDMETHODCALLTYPE
  1116. IMSAdminBaseW_KeyExchangePhase1_Proxy(
  1117. IMSAdminBaseW __RPC_FAR *
  1118. )
  1119. {
  1120. return E_FAIL;
  1121. } // IMSAdminBaseW_KeyExchangePhase1_Proxy
  1122. HRESULT
  1123. STDMETHODCALLTYPE
  1124. IMSAdminBaseW_KeyExchangePhase1_Stub(
  1125. IMSAdminBaseW __RPC_FAR * This,
  1126. /* [in][unique] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *pClientKeyExchangeKeyBlob,
  1127. /* [in][unique] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *pClientSignatureKeyBlob,
  1128. /* [out] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *__RPC_FAR *ppServerKeyExchangeKeyBlob,
  1129. /* [out] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *__RPC_FAR *ppServerSignatureKeyBlob,
  1130. /* [out] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *__RPC_FAR *ppServerSessionKeyBlob
  1131. )
  1132. {
  1133. HRESULT result;
  1134. ADM_SECURE_DATA * secureData;
  1135. //
  1136. // Find an ADM_SECURE_DATA object for "This".
  1137. //
  1138. secureData = ADM_SECURE_DATA::FindAndReferenceServerSecureData(
  1139. This,
  1140. TRUE // CreateIfNotFound
  1141. );
  1142. if( secureData == NULL ) {
  1143. return MD_ERROR_SECURE_CHANNEL_FAILURE;
  1144. }
  1145. //
  1146. // Do the phase 1 server-side key exchange.
  1147. //
  1148. result = secureData->DoServerSideKeyExchangePhase1(
  1149. pClientKeyExchangeKeyBlob,
  1150. pClientSignatureKeyBlob,
  1151. ppServerKeyExchangeKeyBlob,
  1152. ppServerSignatureKeyBlob,
  1153. ppServerSessionKeyBlob
  1154. );
  1155. secureData->Dereference();
  1156. return result;
  1157. } // IMSAdminBaseW_KeyExchangePhase1_Stub
  1158. HRESULT
  1159. STDMETHODCALLTYPE
  1160. IMSAdminBaseW_KeyExchangePhase2_Proxy(
  1161. IMSAdminBaseW __RPC_FAR *
  1162. )
  1163. {
  1164. return E_FAIL;
  1165. } // IMSAdminBaseW_KeyExchangePhase2_Proxy
  1166. HRESULT
  1167. STDMETHODCALLTYPE
  1168. IMSAdminBaseW_KeyExchangePhase2_Stub(
  1169. IMSAdminBaseW __RPC_FAR * This,
  1170. /* [in][unique] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *pClientSessionKeyBlob,
  1171. /* [in][unique] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *pClientHashBlob,
  1172. /* [out] */ struct _IIS_CRYPTO_BLOB __RPC_FAR *__RPC_FAR *ppServerHashBlob
  1173. )
  1174. {
  1175. HRESULT result;
  1176. ADM_SECURE_DATA * secureData;
  1177. //
  1178. // Find an ADM_SECURE_DATA object for "This".
  1179. //
  1180. secureData = ADM_SECURE_DATA::FindAndReferenceServerSecureData(
  1181. This,
  1182. FALSE // CreateIfNotFound
  1183. );
  1184. if( secureData == NULL ) {
  1185. return MD_ERROR_SECURE_CHANNEL_FAILURE;
  1186. }
  1187. //
  1188. // Do the phase 2 server-side key exchange.
  1189. //
  1190. result = secureData->DoServerSideKeyExchangePhase2(
  1191. pClientSessionKeyBlob,
  1192. pClientHashBlob,
  1193. ppServerHashBlob
  1194. );
  1195. secureData->Dereference();
  1196. return result;
  1197. } // IMSAdminBaseW_KeyExchangePhase2_Stub
  1198. VOID
  1199. CalculateGetAllBufferAttributes(
  1200. IN PMETADATA_GETALL_RECORD Data,
  1201. IN DWORD NumEntries,
  1202. OUT DWORD * TotalBufferLength,
  1203. OUT BOOL * IsBufferSecure
  1204. )
  1205. /*++
  1206. Routine Description:
  1207. This routine performs three major functions:
  1208. 1. It calculates the total size of the METADATA_GETALL_RECORD,
  1209. including all data.
  1210. 2. It determines if any of the METADATA_GETALL_RECORDs are marked
  1211. as secure.
  1212. Arguments:
  1213. Data - Pointer to the METADATA_GETALL_RECORD buffer.
  1214. NumEntries - The number of entries in the buffer.
  1215. TotalBufferLength - Receives the total buffer length.
  1216. IsBufferSecure - Receives TRUE if any of the entries are marked secure.
  1217. Return Value:
  1218. None.
  1219. --*/
  1220. {
  1221. PMETADATA_GETALL_RECORD scan;
  1222. DWORD i;
  1223. DWORD_PTR usedBufferLength;
  1224. DWORD_PTR nextOffset;
  1225. BOOL isSecure;
  1226. //
  1227. // Setup.
  1228. //
  1229. usedBufferLength = NumEntries * sizeof(METADATA_GETALL_RECORD);
  1230. isSecure = FALSE;
  1231. //
  1232. // Scan the entries, accumulating the total data length.
  1233. //
  1234. // Because the individual data entries may be padded. We will
  1235. // consider the amount of buffer used to be the highest offset
  1236. // + the length of that record's data.
  1237. //
  1238. // While we're at it, determine if any are marked as secure.
  1239. //
  1240. for( scan = Data, i = NumEntries ; i > 0 ; scan++, i-- ) {
  1241. nextOffset = scan->dwMDDataOffset + scan->dwMDDataLen;
  1242. if( nextOffset > usedBufferLength ) {
  1243. usedBufferLength = nextOffset;
  1244. }
  1245. if( scan->dwMDAttributes & METADATA_SECURE ) {
  1246. isSecure = ENABLE_SECURE_CHANNEL;
  1247. }
  1248. }
  1249. *TotalBufferLength = static_cast<DWORD>(usedBufferLength);
  1250. *IsBufferSecure = isSecure;
  1251. } // CalculateGetAllBufferAttributes
  1252. VOID
  1253. WINAPI
  1254. ReleaseObjectSecurityContextW(
  1255. IUnknown * Object
  1256. )
  1257. /*++
  1258. Routine Description:
  1259. Releases any security context associated with the specified object.
  1260. Arguments:
  1261. Object - The object.
  1262. Return Value:
  1263. None.
  1264. --*/
  1265. {
  1266. ADM_SECURE_DATA * data;
  1267. //
  1268. // Find the data associated with the object.
  1269. //
  1270. data = ADM_SECURE_DATA::FindAndReferenceServerSecureData(
  1271. Object,
  1272. FALSE // CreateIfNotFound
  1273. );
  1274. if( data != NULL ) {
  1275. //
  1276. // Dereference the secure data object *twice*, once
  1277. // to remove the reference added above, and once to
  1278. // remove the "active" reference.
  1279. //
  1280. data->Dereference();
  1281. data->Dereference();
  1282. }
  1283. else {
  1284. ADM_GUID_MAP *pguidmapData;
  1285. pguidmapData = ADM_GUID_MAP::FindAndReferenceGuidMap( Object );
  1286. if( pguidmapData == NULL ) {
  1287. #if 0 // stop whining
  1288. DBGPRINTF((
  1289. DBG_CONTEXT,
  1290. "ReleaseObjectSecurityContextW: cannot find data for %08lx\n",
  1291. Object
  1292. ));
  1293. #endif // stop whining
  1294. }
  1295. else {
  1296. //
  1297. // Dereference the secure data object *twice*, once
  1298. // to remove the reference added above, and once to
  1299. // remove the "active" reference.
  1300. //
  1301. pguidmapData->Dereference();
  1302. pguidmapData->Dereference();
  1303. }
  1304. }
  1305. } // ReleaseObjectSecurityContextW
  1306. extern "C" {
  1307. ULONG
  1308. STDMETHODCALLTYPE
  1309. Hooked_IUnknown_Release_Proxy(
  1310. IUnknown __RPC_FAR * This
  1311. )
  1312. /*++
  1313. Routine Description:
  1314. This is the hooked IUnknown::Release() method (see IADMXP.C for
  1315. details).
  1316. Arguments:
  1317. This - The object being released.
  1318. Return Value:
  1319. ULONG - The updated reference count.
  1320. --*/
  1321. {
  1322. ULONG result;
  1323. //
  1324. // AddRef and Release to find out if this is the final release. If so,
  1325. // destroy any security context associated with this object.
  1326. // This must be done before the final Release, to avoid a window
  1327. // between the object getting freed and the security info getting
  1328. // removed from the lists.
  1329. //
  1330. IUnknown_AddRef_Proxy( This );
  1331. result = IUnknown_Release_Proxy( This );
  1332. if( result == 1 ) {
  1333. ReleaseObjectSecurityContextW( This );
  1334. }
  1335. //
  1336. // Call the original release method.
  1337. //
  1338. result = IUnknown_Release_Proxy( This );
  1339. return result;
  1340. } // Hooked_IUnknown_Release_Proxy
  1341. } // extern "C"