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.

653 lines
20 KiB

  1. //=================================================================
  2. //
  3. // AdvApi32Api.cpp
  4. //
  5. // Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved
  6. //
  7. //=================================================================
  8. #include "precomp.h"
  9. #include <cominit.h>
  10. #include "AdvApi32Api.h"
  11. #include "DllWrapperCreatorReg.h"
  12. // {15E4C152-D051-11d2-911F-0060081A46FD}
  13. static const GUID g_guidAdvApi32Api =
  14. {0x15e4c152, 0xd051, 0x11d2, {0x91, 0x1f, 0x0, 0x60, 0x8, 0x1a, 0x46, 0xfd}};
  15. static const TCHAR g_tstrAdvApi32[] = _T("ADVAPI32.DLL");
  16. /******************************************************************************
  17. * Register this class with the CResourceManager.
  18. *****************************************************************************/
  19. CDllApiWraprCreatrReg<CAdvApi32Api, &g_guidAdvApi32Api, g_tstrAdvApi32> MyRegisteredAdvApi32Wrapper;
  20. /******************************************************************************
  21. * Constructor
  22. ******************************************************************************/
  23. CAdvApi32Api::CAdvApi32Api(LPCTSTR a_tstrWrappedDllName)
  24. : CDllWrapperBase(a_tstrWrappedDllName),
  25. m_pfnLsaEnumerateTrustedDomains(NULL),
  26. m_pfnLsaQueryInformationPolicy(NULL),
  27. m_pfnLsaNtStatusToWinError(NULL),
  28. m_pfnLsaFreeMemory(NULL),
  29. m_pfnLsaOpenPolicy(NULL),
  30. m_pfnLsaClose(NULL),
  31. m_pfnSetNamedSecurityInfoW(NULL),
  32. m_pfnGetNamedSecurityInfoW(NULL),
  33. m_pfnQueryServiceStatusEx(NULL),
  34. m_pfnDuplicateTokenEx(NULL),
  35. m_pfnSetSecurityDescriptorControl(NULL),
  36. m_pfnConvertToAutoInheritPrivateObjectSecurity(NULL),
  37. m_pfnDestroyPrivateObjectSecurity(NULL),
  38. m_pfnSetNamedSecurityInfoEx(NULL),
  39. m_pfnGetExplicitEntriesFromAcl(NULL),
  40. m_pfnCheckTokenMembership(NULL),
  41. m_pfnAddAccessAllowedObjectAce(NULL),
  42. m_pfnAddAccessDeniedObjectAce(NULL),
  43. m_pfnAddAuditAccessObjectAce(NULL),
  44. m_pfnGetEffectiveRightsFromAclW(NULL)
  45. {
  46. }
  47. /******************************************************************************
  48. * Destructor
  49. ******************************************************************************/
  50. CAdvApi32Api::~CAdvApi32Api()
  51. {
  52. }
  53. /******************************************************************************
  54. * Initialization function to check that we obtained function addresses.
  55. * Init should fail only if the minimum set of functions was not available;
  56. * functions added in later versions may or may not be present - it is the
  57. * client's responsibility in such cases to check, in their code, for the
  58. * version of the dll before trying to call such functions. Not doing so
  59. * when the function is not present will result in an AV.
  60. *
  61. * The Init function is called by the WrapperCreatorRegistation class.
  62. ******************************************************************************/
  63. bool CAdvApi32Api::Init()
  64. {
  65. bool fRet = LoadLibrary();
  66. if(fRet)
  67. {
  68. m_pfnLsaEnumerateTrustedDomains = (PFN_LSA_ENUMERATE_TRUSTED_DOMAINS)
  69. GetProcAddress("LsaEnumerateTrustedDomains");
  70. m_pfnLsaQueryInformationPolicy = (PFN_LSA_QUERY_INFORMATION_POLICY)
  71. GetProcAddress("LsaQueryInformationPolicy");
  72. m_pfnLsaNtStatusToWinError = (PFN_LSA_NT_STATUS_TO_WIN_ERROR)
  73. GetProcAddress("LsaNtStatusToWinError");
  74. m_pfnLsaFreeMemory = (PFN_LSA_FREE_MEMORY)
  75. GetProcAddress("LsaFreeMemory");
  76. m_pfnLsaOpenPolicy = (PFN_LSA_OPEN_POLICY)
  77. GetProcAddress("LsaOpenPolicy");
  78. m_pfnLsaClose = (PFN_LSA_CLOSE) GetProcAddress("LsaClose");
  79. #ifdef NTONLY
  80. // These functions are only on NT 4 and later
  81. m_pfnQueryServiceStatusEx = (PFN_QUERY_SERVICE_STATUS_EX)
  82. GetProcAddress("QueryServiceStatusEx");
  83. m_pfnDuplicateTokenEx = (PFN_DUPLICATE_TOKEN_EX)
  84. GetProcAddress("DuplicateTokenEx");
  85. // These functions is only on NT 5 or later only
  86. m_pfnSetSecurityDescriptorControl = (PFN_SET_SECURITY_DESCRIPTOR_CONTROL)
  87. GetProcAddress("SetSecurityDescriptorControl");
  88. m_pfnConvertToAutoInheritPrivateObjectSecurity = (PFN_CONVERT_TO_AUTO_INHERIT_PRIVATE_OBJECT_SECURITY)
  89. GetProcAddress("ConvertToAutoInheritPrivateObjectSecurity");
  90. m_pfnDestroyPrivateObjectSecurity = (PFN_DESTROY_PRIVATE_OBJECT_SECURITY)
  91. GetProcAddress("DestroyPrivateObjectSecurity");
  92. m_pfnCheckTokenMembership = (PFN_CHECK_TOKEN_MEMBERSHIP)
  93. GetProcAddress("CheckTokenMembership");
  94. m_pfnAddAccessAllowedObjectAce = (PFN_ADD_ACCESS_ALLOWED_OBJECT_ACE)
  95. GetProcAddress("AddAccessAllowedObjectAce");
  96. m_pfnAddAccessDeniedObjectAce = (PFN_ADD_ACCESS_DENIED_OBJECT_ACE)
  97. GetProcAddress("AddAccessDeniedObjectAce");
  98. m_pfnAddAuditAccessObjectAce = (PFN_ADD_AUDIT_ACCESS_OBJECT_ACE)
  99. GetProcAddress("AddAuditAccessObjectAce");
  100. #if ((defined UNICODE) || (defined _UNICODE))
  101. m_pfnSetNamedSecurityInfoW = (PFN_SET_NAMED_SECURITY_INFO_W)
  102. GetProcAddress("SetNamedSecurityInfoW");
  103. m_pfnGetNamedSecurityInfoW = (PFN_GET_NAMED_SECURITY_INFO_W)
  104. GetProcAddress("GetNamedSecurityInfoW");
  105. m_pfnSetNamedSecurityInfoEx = (PFN_SET_NAMED_SECURITY_INFO_EX)
  106. GetProcAddress("SetNamedSecurityInfoExW");
  107. m_pfnGetExplicitEntriesFromAcl = (PFN_GET_EXPLICIT_ENTRIES_FROM_ACL)
  108. GetProcAddress("GetExplicitEntriesFromAclW");
  109. m_pfnGetEffectiveRightsFromAclW = (PFN_GET_EFFECTIVE_RIGHTS_FROM_ACL_W)
  110. GetProcAddress("GetEffectiveRightsFromAclW");
  111. #else
  112. m_pfnSetNamedSecurityInfoEx = (PFN_SET_NAMED_SECURITY_INFO_EX)
  113. GetProcAddress("SetNamedSecurityInfoExA");
  114. m_pfnGetExplicitEntriesFromAcl = (PFN_GET_EXPLICIT_ENTRIES_FROM_ACL)
  115. GetProcAddress("GetExplicitEntriesFromAclA");
  116. #endif
  117. #endif
  118. // These functions are considered essential to all versions of this
  119. // dll; therefore, if any are not found, return false.
  120. if(m_pfnLsaEnumerateTrustedDomains == NULL ||
  121. m_pfnLsaQueryInformationPolicy == NULL ||
  122. m_pfnLsaNtStatusToWinError == NULL ||
  123. m_pfnLsaFreeMemory == NULL ||
  124. m_pfnLsaOpenPolicy == NULL ||
  125. m_pfnLsaClose == NULL)
  126. {
  127. fRet = false;
  128. LogErrorMessage(L"Failed find entrypoint in AdvApi32Api");
  129. }
  130. }
  131. return fRet;
  132. }
  133. /******************************************************************************
  134. * Member functions wrapping AdvApi32 api functions. Add new functions here
  135. * as required.
  136. ******************************************************************************/
  137. NTSTATUS CAdvApi32Api::LsaEnumerateTrustedDomains
  138. (
  139. LSA_HANDLE a_PolicyHandle,
  140. PLSA_ENUMERATION_HANDLE a_EnumerationContext,
  141. PVOID *a_Buffer,
  142. ULONG a_PreferedMaximumLength,
  143. PULONG a_CountReturned
  144. )
  145. {
  146. return m_pfnLsaEnumerateTrustedDomains(a_PolicyHandle, a_EnumerationContext,
  147. a_Buffer, a_PreferedMaximumLength,
  148. a_CountReturned);
  149. }
  150. NTSTATUS CAdvApi32Api::LsaQueryInformationPolicy
  151. (
  152. LSA_HANDLE a_PolicyHandle,
  153. POLICY_INFORMATION_CLASS a_InformationClass,
  154. PVOID *a_Buffer
  155. )
  156. {
  157. return m_pfnLsaQueryInformationPolicy(a_PolicyHandle, a_InformationClass,
  158. a_Buffer);
  159. }
  160. NTSTATUS CAdvApi32Api::LsaNtStatusToWinError
  161. (
  162. NTSTATUS a_Status
  163. )
  164. {
  165. return m_pfnLsaNtStatusToWinError(a_Status);
  166. }
  167. NTSTATUS CAdvApi32Api::LsaFreeMemory
  168. (
  169. PVOID a_Buffer
  170. )
  171. {
  172. return m_pfnLsaFreeMemory(a_Buffer);
  173. }
  174. NTSTATUS CAdvApi32Api::LsaOpenPolicy
  175. (
  176. PLSA_UNICODE_STRING a_SystemName,
  177. PLSA_OBJECT_ATTRIBUTES a_ObjectAttributes,
  178. ACCESS_MASK a_DesiredAccess,
  179. PLSA_HANDLE a_PolicyHandle
  180. )
  181. {
  182. return m_pfnLsaOpenPolicy(a_SystemName, a_ObjectAttributes,
  183. a_DesiredAccess, a_PolicyHandle);
  184. }
  185. NTSTATUS CAdvApi32Api::LsaClose
  186. (
  187. LSA_HANDLE a_ObjectHandle
  188. )
  189. {
  190. return m_pfnLsaClose(a_ObjectHandle);
  191. }
  192. bool CAdvApi32Api::SetNamedSecurityInfoW
  193. (
  194. IN LPWSTR a_pObjectName,
  195. IN SE_OBJECT_TYPE a_ObjectType,
  196. IN SECURITY_INFORMATION a_SecurityInfo,
  197. IN PSID a_psidOowner,
  198. IN PSID a_psidGroup,
  199. IN PACL a_pDacl,
  200. IN PACL a_pSacl,
  201. DWORD *a_dwRetval
  202. )
  203. {
  204. bool t_fExists = false;
  205. if(m_pfnSetNamedSecurityInfoW != NULL)
  206. {
  207. DWORD t_dwTemp = m_pfnSetNamedSecurityInfoW(a_pObjectName,
  208. a_ObjectType,
  209. a_SecurityInfo,
  210. a_psidOowner,
  211. a_psidGroup,
  212. a_pDacl,
  213. a_pSacl);
  214. t_fExists = true;
  215. if(a_dwRetval != NULL)
  216. {
  217. *a_dwRetval = t_dwTemp;
  218. }
  219. }
  220. return t_fExists;
  221. }
  222. bool CAdvApi32Api::GetNamedSecurityInfoW
  223. (
  224. LPWSTR a_pObjectName,
  225. SE_OBJECT_TYPE a_ObjectType,
  226. SECURITY_INFORMATION a_SecurityInfo,
  227. PSID *a_ppsidOowner,
  228. PSID *a_ppsidGroup,
  229. PACL *a_ppDacl,
  230. PACL *a_ppSacl,
  231. PSECURITY_DESCRIPTOR *a_ppSecurityDescriptor,
  232. DWORD *a_dwRetval
  233. )
  234. {
  235. bool t_fExists = false;
  236. if(m_pfnGetNamedSecurityInfoW != NULL)
  237. {
  238. DWORD t_dwTemp;
  239. {
  240. t_dwTemp = m_pfnGetNamedSecurityInfoW(a_pObjectName,
  241. a_ObjectType,
  242. a_SecurityInfo,
  243. a_ppsidOowner,
  244. a_ppsidGroup,
  245. a_ppDacl,
  246. a_ppSacl,
  247. a_ppSecurityDescriptor);
  248. }
  249. t_fExists = true;
  250. if(a_dwRetval != NULL)
  251. {
  252. *a_dwRetval = t_dwTemp;
  253. }
  254. }
  255. return t_fExists;
  256. }
  257. bool CAdvApi32Api::QueryServiceStatusEx
  258. (
  259. SC_HANDLE a_hService,
  260. SC_STATUS_TYPE a_InfoLevel,
  261. LPBYTE a_lpBuffer,
  262. DWORD a_cbBufSize,
  263. LPDWORD a_pcbBytesNeeded,
  264. BOOL *a_fRetval
  265. )
  266. {
  267. bool t_fExists = false;
  268. if(m_pfnQueryServiceStatusEx != NULL)
  269. {
  270. BOOL t_fTemp = m_pfnQueryServiceStatusEx(a_hService,
  271. a_InfoLevel,
  272. a_lpBuffer,
  273. a_cbBufSize,
  274. a_pcbBytesNeeded);
  275. t_fExists = true;
  276. if(a_fRetval != NULL)
  277. {
  278. *a_fRetval = t_fTemp;
  279. }
  280. }
  281. return t_fExists;
  282. }
  283. bool CAdvApi32Api::DuplicateTokenEx
  284. (
  285. HANDLE a_h, // handle to token to duplicate
  286. DWORD a_dw, // access rights of new token
  287. LPSECURITY_ATTRIBUTES a_lpsa, // security attributes of the new token
  288. SECURITY_IMPERSONATION_LEVEL a_sil, // impersonation level of new token
  289. TOKEN_TYPE a_tt, // primary or impersonation token
  290. PHANDLE a_ph, // handle to duplicated token
  291. BOOL *a_fRetval // encapsulated function return value
  292. )
  293. {
  294. bool t_fExists = false;
  295. if(m_pfnDuplicateTokenEx != NULL)
  296. {
  297. BOOL t_fTemp = m_pfnDuplicateTokenEx(a_h, a_dw, a_lpsa,
  298. a_sil, a_tt, a_ph);
  299. t_fExists = true;
  300. if(a_fRetval != NULL)
  301. {
  302. *a_fRetval = t_fTemp;
  303. }
  304. }
  305. return t_fExists;
  306. }
  307. bool CAdvApi32Api::SetSecurityDescriptorControl
  308. (
  309. PSECURITY_DESCRIPTOR a_pSecurityDescriptor,
  310. SECURITY_DESCRIPTOR_CONTROL a_ControlBitsOfInterest,
  311. SECURITY_DESCRIPTOR_CONTROL a_ControlBitsToSet,
  312. BOOL *a_fRetval
  313. )
  314. {
  315. bool t_fExists = false;
  316. if(m_pfnSetSecurityDescriptorControl != NULL)
  317. {
  318. BOOL t_fTemp = m_pfnSetSecurityDescriptorControl(a_pSecurityDescriptor,
  319. a_ControlBitsOfInterest,
  320. a_ControlBitsToSet);
  321. t_fExists = true;
  322. if(a_fRetval != NULL)
  323. {
  324. *a_fRetval = t_fTemp;
  325. }
  326. }
  327. return t_fExists;
  328. }
  329. bool CAdvApi32Api::ConvertToAutoInheritPrivateObjectSecurity
  330. (
  331. PSECURITY_DESCRIPTOR a_ParentDescriptor,
  332. PSECURITY_DESCRIPTOR a_CurrentSecurityDescriptor,
  333. PSECURITY_DESCRIPTOR *a_NewSecurityDescriptor,
  334. GUID *a_ObjectType,
  335. BOOLEAN a_IsDirectoryObject,
  336. PGENERIC_MAPPING a_GenericMapping,
  337. BOOL *a_fRetval
  338. )
  339. {
  340. bool t_fExists = false;
  341. if(m_pfnConvertToAutoInheritPrivateObjectSecurity != NULL)
  342. {
  343. BOOL t_fTemp = m_pfnConvertToAutoInheritPrivateObjectSecurity(a_ParentDescriptor,
  344. a_CurrentSecurityDescriptor,
  345. a_NewSecurityDescriptor,
  346. a_ObjectType,
  347. a_IsDirectoryObject,
  348. a_GenericMapping);
  349. t_fExists = true;
  350. if(a_fRetval != NULL)
  351. {
  352. *a_fRetval = t_fTemp;
  353. }
  354. }
  355. return t_fExists;
  356. }
  357. bool CAdvApi32Api::DestroyPrivateObjectSecurity
  358. (
  359. PSECURITY_DESCRIPTOR *a_ObjectDescriptor,
  360. BOOL *a_fRetval
  361. )
  362. {
  363. bool t_fExists = false;
  364. if(m_pfnDestroyPrivateObjectSecurity != NULL)
  365. {
  366. BOOL t_fTemp = m_pfnDestroyPrivateObjectSecurity(a_ObjectDescriptor);
  367. t_fExists = true;
  368. if(a_fRetval != NULL)
  369. {
  370. *a_fRetval = t_fTemp;
  371. }
  372. }
  373. return t_fExists;
  374. }
  375. bool CAdvApi32Api::SetNamedSecurityInfoEx
  376. (
  377. LPCTSTR a_lpObject,
  378. SE_OBJECT_TYPE a_ObjectType,
  379. SECURITY_INFORMATION a_SecurityInfo,
  380. LPCTSTR a_lpProvider,
  381. PACTRL_ACCESS a_pAccessList,
  382. PACTRL_AUDIT a_pAuditList,
  383. LPTSTR a_lpOwner,
  384. LPTSTR a_lpGroup,
  385. PACTRL_OVERLAPPED a_pOverlapped,
  386. DWORD *a_dwRetval
  387. )
  388. {
  389. bool t_fExists = false;
  390. if(m_pfnSetNamedSecurityInfoEx != NULL)
  391. {
  392. DWORD t_dwTemp = m_pfnSetNamedSecurityInfoEx(a_lpObject,a_ObjectType,
  393. a_SecurityInfo,a_lpProvider,
  394. a_pAccessList,a_pAuditList,
  395. a_lpOwner,a_lpGroup,
  396. a_pOverlapped);
  397. t_fExists = true;
  398. if(a_dwRetval != NULL)
  399. {
  400. *a_dwRetval = t_dwTemp;
  401. }
  402. }
  403. return t_fExists;
  404. }
  405. bool CAdvApi32Api::GetExplicitEntriesFromAcl
  406. (
  407. PACL a_pacl,
  408. PULONG a_pcCountOfExplicitEntries,
  409. PEXPLICIT_ACCESS *a_pListOfExplicitEntries,
  410. DWORD *a_dwRetval
  411. )
  412. {
  413. bool t_fExists = false;
  414. if(m_pfnGetExplicitEntriesFromAcl != NULL)
  415. {
  416. DWORD t_dwTemp = m_pfnGetExplicitEntriesFromAcl(a_pacl,
  417. a_pcCountOfExplicitEntries,
  418. a_pListOfExplicitEntries);
  419. t_fExists = true;
  420. if(a_dwRetval != NULL)
  421. {
  422. *a_dwRetval = t_dwTemp;
  423. }
  424. }
  425. return t_fExists;
  426. }
  427. bool CAdvApi32Api::CheckTokenMembership
  428. (
  429. HANDLE a_hTokenHandle OPTIONAL,
  430. PSID a_pSidToCheck,
  431. PBOOL a_pfIsMember,
  432. BOOL *a_fRetval
  433. )
  434. {
  435. bool t_fExists = false;
  436. if(m_pfnCheckTokenMembership)
  437. {
  438. t_fExists = true;
  439. BOOL t_fRet = m_pfnCheckTokenMembership(a_hTokenHandle,
  440. a_pSidToCheck,
  441. a_pfIsMember);
  442. if(a_fRetval)
  443. {
  444. *a_fRetval = t_fRet;
  445. }
  446. }
  447. return t_fExists ;
  448. }
  449. bool CAdvApi32Api::AddAccessAllowedObjectAce
  450. (
  451. PACL a_pAcl,
  452. DWORD a_dwAceRevision,
  453. DWORD a_AceFlags,
  454. DWORD a_AccessMask,
  455. GUID *a_ObjectTypeGuid,
  456. GUID *a_InheritedObjectTypeGuid,
  457. PSID a_pSid,
  458. BOOL *a_fRetval
  459. )
  460. {
  461. bool t_fExists = false;
  462. if(m_pfnAddAccessAllowedObjectAce != NULL)
  463. {
  464. BOOL t_fTemp = m_pfnAddAccessAllowedObjectAce(a_pAcl,
  465. a_dwAceRevision,
  466. a_AceFlags,
  467. a_AccessMask,
  468. a_ObjectTypeGuid,
  469. a_InheritedObjectTypeGuid,
  470. a_pSid);
  471. t_fExists = true;
  472. if(a_fRetval != NULL)
  473. {
  474. *a_fRetval = t_fTemp;
  475. }
  476. }
  477. return t_fExists;
  478. }
  479. bool CAdvApi32Api::AddAccessDeniedObjectAce
  480. (
  481. PACL a_pAcl,
  482. DWORD a_dwAceRevision,
  483. DWORD a_AceFlags,
  484. DWORD a_AccessMask,
  485. GUID *a_ObjectTypeGuid,
  486. GUID *a_InheritedObjectTypeGuid,
  487. PSID a_pSid,
  488. BOOL *a_fRetval
  489. )
  490. {
  491. bool t_fExists = false;
  492. if(m_pfnAddAccessDeniedObjectAce != NULL)
  493. {
  494. BOOL t_fTemp = m_pfnAddAccessDeniedObjectAce(a_pAcl,
  495. a_dwAceRevision,
  496. a_AceFlags,
  497. a_AccessMask,
  498. a_ObjectTypeGuid,
  499. a_InheritedObjectTypeGuid,
  500. a_pSid);
  501. t_fExists = true;
  502. if(a_fRetval != NULL)
  503. {
  504. *a_fRetval = t_fTemp;
  505. }
  506. }
  507. return t_fExists;
  508. }
  509. bool CAdvApi32Api::AddAuditAccessObjectAce
  510. (
  511. PACL a_pAcl,
  512. DWORD a_dwAceRevision,
  513. DWORD a_AceFlags,
  514. DWORD a_AccessMask,
  515. GUID *a_ObjectTypeGuid,
  516. GUID *a_InheritedObjectTypeGuid,
  517. PSID a_pSid,
  518. BOOL a_bAuditSuccess,
  519. BOOL a_bAuditFailure,
  520. BOOL *a_fRetval
  521. )
  522. {
  523. bool t_fExists = false;
  524. if(m_pfnAddAuditAccessObjectAce != NULL)
  525. {
  526. BOOL t_fTemp = m_pfnAddAuditAccessObjectAce(a_pAcl,
  527. a_dwAceRevision,
  528. a_AceFlags,
  529. a_AccessMask,
  530. a_ObjectTypeGuid,
  531. a_InheritedObjectTypeGuid,
  532. a_pSid,
  533. a_bAuditSuccess,
  534. a_bAuditFailure);
  535. t_fExists = true;
  536. if(a_fRetval != NULL)
  537. {
  538. *a_fRetval = t_fTemp;
  539. }
  540. }
  541. return t_fExists;
  542. }
  543. bool CAdvApi32Api::GetEffectiveRightsFromAclW
  544. (
  545. PACL a_pacl,
  546. PTRUSTEE_W a_pTrustee,
  547. PACCESS_MASK a_pAccessRights,
  548. DWORD *a_dwRetval
  549. )
  550. {
  551. bool t_fExists = false;
  552. if(m_pfnGetEffectiveRightsFromAclW != NULL)
  553. {
  554. DWORD t_dwTemp;
  555. {
  556. t_dwTemp = m_pfnGetEffectiveRightsFromAclW(a_pacl,
  557. a_pTrustee,
  558. a_pAccessRights);
  559. }
  560. t_fExists = true;
  561. if(a_dwRetval != NULL)
  562. {
  563. *a_dwRetval = t_dwTemp;
  564. }
  565. }
  566. return t_fExists;
  567. }