Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

581 lines
15 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_UTILITY);
  3. /*
  4. * regkey.cpp
  5. *
  6. * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY
  7. *
  8. * Abstract:
  9. * This is the implementation file for the class CRegKeyContainer. This
  10. * class manages the data associated with a Registry Key. Registry Key's
  11. * are used to identify resources held in the application registry and
  12. * consist of a Session Key and a resource ID octet string. The
  13. * CRegKeyContainer class uses a CSessKeyContainer container to maintain the
  14. * session key data internally. A Rogue Wave string object is used to
  15. * hold the resource ID octet string.
  16. *
  17. * Protected Instance Variables:
  18. * m_InternalRegKey
  19. * Structure used to hold the registry key data internally.
  20. * m_RegKeyPDU
  21. * Storage for the "PDU" form of the registry key.
  22. * m_fValidRegKeyPDU
  23. * Flag indicating that memory has been allocated to hold the internal
  24. * "PDU" registry key.
  25. * m_cbDataSize
  26. * Variable holding the size of the memory which will be required to
  27. * hold any data referenced by the "API" GCCRegistryKey structure.
  28. *
  29. * Caveats:
  30. * None.
  31. *
  32. * Author:
  33. * jbo
  34. */
  35. #include "regkey.h"
  36. /*
  37. * This macro is used to ensure that the Resource ID contained in the Registry
  38. * Key does not violate the imposed ASN.1 constraint.
  39. */
  40. #define MAXIMUM_RESOURCE_ID_LENGTH 64
  41. /*
  42. * CRegKeyContainer()
  43. *
  44. * Public Function Description:
  45. * This constructor is used to create a CRegKeyContainer object from
  46. * an "API" GCCRegistryKey.
  47. */
  48. CRegKeyContainer::
  49. CRegKeyContainer(PGCCRegistryKey registry_key, PGCCError pRetCode)
  50. :
  51. CRefCount(MAKE_STAMP_ID('R','e','g','K')),
  52. m_fValidRegKeyPDU(FALSE),
  53. m_cbDataSize(0)
  54. {
  55. GCCError rc = GCC_NO_ERROR;
  56. /*
  57. * Initialize instance variables.
  58. */
  59. ::ZeroMemory(&m_InternalRegKey, sizeof(m_InternalRegKey));
  60. ::ZeroMemory(&m_RegKeyPDU, sizeof(m_RegKeyPDU));
  61. /*
  62. * Check to make sure the resource ID string does not violate the imposed
  63. * ASN.1 constraint.
  64. */
  65. if (registry_key->resource_id.length > MAXIMUM_RESOURCE_ID_LENGTH)
  66. {
  67. ERROR_OUT(("CRegKeyContainer::CRegKeyContainer: Error: resource ID exceeds allowable length"));
  68. rc = GCC_BAD_REGISTRY_KEY;
  69. goto MyExit;
  70. }
  71. /*
  72. * Save the Session Key portion of the Registry Key in the internal
  73. * structure by creating a new CSessKeyContainer object. Check to make
  74. * sure the object is successfully created.
  75. */
  76. DBG_SAVE_FILE_LINE
  77. m_InternalRegKey.session_key = new CSessKeyContainer(&registry_key->session_key, &rc);
  78. if (m_InternalRegKey.session_key == NULL)
  79. {
  80. ERROR_OUT(("CRegKeyContainer::CRegKeyContainer: Error creating new CSessKeyContainer"));
  81. rc = GCC_ALLOCATION_FAILURE;
  82. goto MyExit;
  83. }
  84. else if (rc == GCC_BAD_SESSION_KEY)
  85. {
  86. rc = GCC_BAD_REGISTRY_KEY;
  87. goto MyExit;
  88. }
  89. /*
  90. * Save the resource ID if the CSessKeyContainer was successfully created.
  91. */
  92. if (NULL == (m_InternalRegKey.poszResourceID = ::My_strdupO2(
  93. registry_key->resource_id.value,
  94. registry_key->resource_id.length)))
  95. {
  96. ERROR_OUT(("CRegKeyContainer::CRegKeyContainer: Error creating resource id"));
  97. rc = GCC_ALLOCATION_FAILURE;
  98. // goto MyExit;
  99. }
  100. MyExit:
  101. *pRetCode = rc;
  102. }
  103. /*
  104. * CRegKeyContainer()
  105. *
  106. * Public Function Description:
  107. * This constructor is used to create a CRegKeyContainer object from
  108. * a "PDU" RegistryKey.
  109. */
  110. CRegKeyContainer::
  111. CRegKeyContainer(PRegistryKey registry_key, PGCCError pRetCode)
  112. :
  113. CRefCount(MAKE_STAMP_ID('R','e','g','K')),
  114. m_fValidRegKeyPDU(FALSE),
  115. m_cbDataSize(0)
  116. {
  117. GCCError rc = GCC_NO_ERROR;
  118. /*
  119. * Initialize instance variables.
  120. */
  121. ::ZeroMemory(&m_InternalRegKey, sizeof(m_InternalRegKey));
  122. ::ZeroMemory(&m_RegKeyPDU, sizeof(m_RegKeyPDU));
  123. /*
  124. * Save the Session Key portion of the Registry Key in the internal
  125. * structure by creating a new CSessKeyContainer object. Check to make sure
  126. * the object is successfully created.
  127. */
  128. DBG_SAVE_FILE_LINE
  129. m_InternalRegKey.session_key = new CSessKeyContainer(&registry_key->session_key, &rc);
  130. if ((m_InternalRegKey.session_key == NULL) || (rc != GCC_NO_ERROR))
  131. {
  132. ERROR_OUT(("CRegKeyContainer::CRegKeyContainer: Error creating new CSessKeyContainer"));
  133. rc = GCC_ALLOCATION_FAILURE;
  134. goto MyExit;
  135. }
  136. /*
  137. * Save the resource ID if the CSessKeyContainer was successfully created.
  138. */
  139. if (NULL == (m_InternalRegKey.poszResourceID = ::My_strdupO2(
  140. registry_key->resource_id.value,
  141. registry_key->resource_id.length)))
  142. {
  143. ERROR_OUT(("CRegKeyContainer::CRegKeyContainer: Error creating resource id"));
  144. rc = GCC_ALLOCATION_FAILURE;
  145. // goto MyExit;
  146. }
  147. MyExit:
  148. *pRetCode = rc;
  149. }
  150. /*
  151. * CRegKeyContainer()
  152. *
  153. * Public Function Description:
  154. * This copy constructor is used to create a new CRegKeyContainer object
  155. * from another CRegKeyContainer object.
  156. */
  157. CRegKeyContainer::
  158. CRegKeyContainer(CRegKeyContainer *registry_key, PGCCError pRetCode)
  159. :
  160. CRefCount(MAKE_STAMP_ID('R','e','g','K')),
  161. m_fValidRegKeyPDU(FALSE),
  162. m_cbDataSize(0)
  163. {
  164. GCCError rc = GCC_NO_ERROR;
  165. /*
  166. * Initialize instance variables.
  167. */
  168. ::ZeroMemory(&m_InternalRegKey, sizeof(m_InternalRegKey));
  169. ::ZeroMemory(&m_RegKeyPDU, sizeof(m_RegKeyPDU));
  170. /*
  171. * Copy the Session Key portion of the Registry Key using the copy
  172. * constructor of the CSessKeyContainer class. Check to make sure the
  173. * CSessKeyContainer object is successfully created.
  174. */
  175. DBG_SAVE_FILE_LINE
  176. m_InternalRegKey.session_key = new CSessKeyContainer(registry_key->m_InternalRegKey.session_key, &rc);
  177. if ((m_InternalRegKey.session_key == NULL) || (rc != GCC_NO_ERROR))
  178. {
  179. ERROR_OUT(("CRegKeyContainer::CRegKeyContainer: Error creating new CSessKeyContainer"));
  180. rc = GCC_ALLOCATION_FAILURE;
  181. goto MyExit;
  182. }
  183. /*
  184. * Save the resource ID if the CSessKeyContainer was saved correctly.
  185. * Store the resource ID in a Rogue Wave string container.
  186. */
  187. if (NULL == (m_InternalRegKey.poszResourceID = ::My_strdupO(
  188. registry_key->m_InternalRegKey.poszResourceID)))
  189. {
  190. ERROR_OUT(("CRegKeyContainer::CRegKeyContainer: Error creating new resource id"));
  191. rc = GCC_ALLOCATION_FAILURE;
  192. // goto MyExit;
  193. }
  194. MyExit:
  195. *pRetCode = rc;
  196. }
  197. /*
  198. * ~CRegKeyContainer()
  199. *
  200. * Public Function Description
  201. * The CRegKeyContainer destructor is responsible for freeing any memory
  202. * allocated to hold the registry key data.
  203. *
  204. */
  205. CRegKeyContainer::
  206. ~CRegKeyContainer(void)
  207. {
  208. /*
  209. * If "PDU" data has been allocated for this object, free it now.
  210. */
  211. if (m_fValidRegKeyPDU)
  212. {
  213. FreeRegistryKeyDataPDU();
  214. }
  215. /*
  216. * Delete any registry key data held internally.
  217. */
  218. if (NULL != m_InternalRegKey.session_key)
  219. {
  220. m_InternalRegKey.session_key->Release();
  221. }
  222. delete m_InternalRegKey.poszResourceID;
  223. }
  224. /*
  225. * LockRegistryKeyData ()
  226. *
  227. * Public Function Description:
  228. * This routine locks the registry key data and determines the amount of
  229. * memory referenced by the "API" registry key structure.
  230. */
  231. UINT CRegKeyContainer::
  232. LockRegistryKeyData(void)
  233. {
  234. /*
  235. * If this is the first time this routine is called, determine the size of
  236. * the memory required to hold the data referenced by the registry key
  237. * structure. Otherwise, just increment the lock count.
  238. */
  239. if (Lock() == 1)
  240. {
  241. /*
  242. * Lock the data for the session key by using the "Lock" routine of
  243. * the internal CSessKeyContainer object. Determine the amount of memory
  244. * necessary to hold the data referenced by the "API" registry key
  245. * structure. The referenced data consists of data for the object key
  246. * as well as data for the resource ID octet string. The sizes for
  247. * both of these memory blocks are rounded to occupy an even multiple
  248. * of four-byte blocks, with the session key block being rounded at a
  249. * lower level. The pointers to the internal objects were validated in
  250. * the constructor.
  251. */
  252. m_cbDataSize = m_InternalRegKey.session_key->LockSessionKeyData();
  253. m_cbDataSize += m_InternalRegKey.poszResourceID->length;
  254. m_cbDataSize = ROUNDTOBOUNDARY(m_cbDataSize);
  255. }
  256. return m_cbDataSize;
  257. }
  258. /*
  259. * GetGCCRegistryKeyData ()
  260. *
  261. * Public Function Description:
  262. * This routine retrieves registry key data in the form of an "API"
  263. * GCCRegistryKey. This routine is called after "locking" the registry
  264. * key data.
  265. */
  266. UINT CRegKeyContainer::
  267. GetGCCRegistryKeyData(PGCCRegistryKey registry_key, LPBYTE memory)
  268. {
  269. UINT cbDataSizeToRet = 0;
  270. /*
  271. * If the registry key data has been locked, fill in the output structure
  272. * and the data referenced by the structure. Call the "Get" routine for the
  273. * SessionKey to fill in the session key data.
  274. */
  275. if (GetLockCount() > 0)
  276. {
  277. UINT session_key_data_length;
  278. LPBYTE data_memory = memory;
  279. /*
  280. * Fill in the output parameter which indicates the amount of memory
  281. * used to hold all of the data associated with the registry key.
  282. */
  283. cbDataSizeToRet = m_cbDataSize;
  284. session_key_data_length = m_InternalRegKey.session_key->
  285. GetGCCSessionKeyData(&registry_key->session_key, data_memory);
  286. data_memory += session_key_data_length;
  287. /*
  288. * Move the memory pointer past the session key data. The length of
  289. * the session key data is rounded to a four-byte boundary by the
  290. * lower level routines. Set the resource ID octet string length
  291. * and pointer and copy the octet string data into the memory block
  292. * from the internal Rogue Wave string.
  293. */
  294. registry_key->resource_id.value = data_memory;
  295. registry_key->resource_id.length = m_InternalRegKey.poszResourceID->length;
  296. ::CopyMemory(data_memory, m_InternalRegKey.poszResourceID->value,
  297. m_InternalRegKey.poszResourceID->length);
  298. }
  299. else
  300. {
  301. ERROR_OUT(("CRegKeyContainer::GetGCCRegistryKeyData Error Data Not Locked"));
  302. }
  303. return cbDataSizeToRet;
  304. }
  305. /*
  306. * UnlockRegistryKeyData ()
  307. *
  308. * Public Function Description:
  309. * This routine decrements the lock count and frees the memory associated
  310. * with the "API" registry key once the lock count reaches zero.
  311. */
  312. void CRegKeyContainer::
  313. UnLockRegistryKeyData(void)
  314. {
  315. if (Unlock(FALSE) == 0)
  316. {
  317. /*
  318. * Unlock the data associated with the internal CSessKeyContainer.
  319. */
  320. if (m_InternalRegKey.session_key != NULL)
  321. {
  322. m_InternalRegKey.session_key->UnLockSessionKeyData();
  323. }
  324. }
  325. // we have to call Release() because we used Unlock(FALSE)
  326. Release();
  327. }
  328. /*
  329. * GetRegistryKeyDataPDU ()
  330. *
  331. * Public Function Description:
  332. * This routine converts the registry key from it's internal form of a
  333. * REG_KEY structure into the "PDU" form which can be passed in
  334. * to the ASN.1 encoder. A pointer to a "PDU" "RegistryKey" structure is
  335. * returned.
  336. */
  337. GCCError CRegKeyContainer::
  338. GetRegistryKeyDataPDU(PRegistryKey registry_key)
  339. {
  340. GCCError rc = GCC_NO_ERROR;
  341. /*
  342. * If this is the first time that PDU data has been requested then we must
  343. * fill in the internal PDU structure and copy it into the structure pointed
  344. * to by the output parameter. On subsequent calls to "GetPDU" we can just
  345. * copy the internal PDU structure into the structure pointed to by the
  346. * output parameter.
  347. */
  348. if (m_fValidRegKeyPDU == FALSE)
  349. {
  350. m_fValidRegKeyPDU = TRUE;
  351. /*
  352. * Fill in the "PDU" registry key from the internal structure.
  353. */
  354. if (m_InternalRegKey.session_key != NULL)
  355. {
  356. /*
  357. * Fill in the session key portion of the registry key by using the
  358. * "Get" routine of the internal CSessKeyContainer object.
  359. */
  360. rc = m_InternalRegKey.session_key->GetSessionKeyDataPDU(&m_RegKeyPDU.session_key);
  361. }
  362. else
  363. {
  364. rc = GCC_ALLOCATION_FAILURE;
  365. }
  366. if (rc == GCC_NO_ERROR)
  367. {
  368. /*
  369. * Fill in the "PDU" resource ID if no error has occurred.
  370. */
  371. ::CopyMemory(m_RegKeyPDU.resource_id.value,
  372. m_InternalRegKey.poszResourceID->value,
  373. m_InternalRegKey.poszResourceID->length);
  374. m_RegKeyPDU.resource_id.length = m_InternalRegKey.poszResourceID->length;
  375. }
  376. }
  377. /*
  378. * Copy the internal PDU structure into the structure pointed to by the
  379. * output parameter.
  380. */
  381. *registry_key = m_RegKeyPDU;
  382. return rc;
  383. }
  384. /*
  385. * FreeRegistryKeyDataPDU ()
  386. *
  387. * Public Function Description:
  388. * This routine is used to free the registry key data held internally in
  389. * the "PDU" form of a "RegistryKey".
  390. */
  391. void CRegKeyContainer::
  392. FreeRegistryKeyDataPDU(void)
  393. {
  394. if (m_fValidRegKeyPDU)
  395. {
  396. /*
  397. * Set the flag indicating that PDU registry key data is no longer
  398. * allocated.
  399. */
  400. m_fValidRegKeyPDU = FALSE;
  401. if (m_InternalRegKey.session_key != NULL)
  402. {
  403. m_InternalRegKey.session_key->FreeSessionKeyDataPDU();
  404. }
  405. else
  406. {
  407. ERROR_OUT(("CRegKeyContainer::FreeRegistryKeyDataPDU: Bad internal pointer"));
  408. }
  409. }
  410. }
  411. GCCError CRegKeyContainer::
  412. CreateRegistryKeyData(PGCCRegistryKey *ppRegKey)
  413. {
  414. GCCError rc;
  415. DebugEntry(CRegKeyContainer::CreateRegistryKeyData);
  416. /*
  417. ** Here we calculate the length of the bulk data. This
  418. ** includes the registry key and registry item. These objects are
  419. ** "locked" in order to determine how much bulk memory they will
  420. ** occupy.
  421. */
  422. UINT cbKeySize = ROUNDTOBOUNDARY(sizeof(GCCRegistryKey));
  423. UINT cbDataSize = LockRegistryKeyData() + cbKeySize;
  424. LPBYTE pData;
  425. DBG_SAVE_FILE_LINE
  426. if (NULL != (pData = new BYTE[cbDataSize]))
  427. {
  428. *ppRegKey = (PGCCRegistryKey) pData;
  429. ::ZeroMemory(pData, cbKeySize);
  430. pData += cbKeySize;
  431. GetGCCRegistryKeyData(*ppRegKey, pData);
  432. rc = GCC_NO_ERROR;
  433. }
  434. else
  435. {
  436. ERROR_OUT(("CRegKeyContainer::CreateRegistryKeyData: can't create GCCRegistryKey"));
  437. rc = GCC_ALLOCATION_FAILURE;
  438. }
  439. // UnLock the registry key since it is no longer needed
  440. UnLockRegistryKeyData();
  441. DebugExitINT(CRegKeyContainer::CreateRegistryKeyData, rc);
  442. return rc;
  443. }
  444. /*
  445. * IsThisYourSessionKey ()
  446. *
  447. * Public Function Description:
  448. * This routine determines whether this registry key holds the specified
  449. * session key.
  450. */
  451. BOOL CRegKeyContainer::
  452. IsThisYourSessionKey(CSessKeyContainer *session_key)
  453. {
  454. BOOL fRet = FALSE;
  455. CSessKeyContainer *session_key_data;
  456. GCCError rc2;
  457. DBG_SAVE_FILE_LINE
  458. session_key_data = new CSessKeyContainer(session_key, &rc2);
  459. if ((session_key_data != NULL) && (rc2 == GCC_NO_ERROR))
  460. {
  461. if (*session_key_data == *m_InternalRegKey.session_key)
  462. {
  463. fRet = TRUE;
  464. }
  465. }
  466. else
  467. {
  468. ERROR_OUT(("CRegKeyContainer::IsThisYourSessionKey: Error creating new CSessKeyContainer"));
  469. }
  470. if (NULL != session_key_data)
  471. {
  472. session_key_data->Release();
  473. }
  474. return fRet;
  475. }
  476. /*
  477. * GetSessionKey ()
  478. *
  479. * Public Function Description:
  480. * This routine is used to retrieve the session key which is held within
  481. * this registry key. The session key is returned in the form of a
  482. * CSessKeyContainer container object.
  483. */
  484. /*
  485. * operator== ()
  486. *
  487. * Public Function Description:
  488. * This routine is used to determine whether or not two registry keys are
  489. * equal in value.
  490. */
  491. BOOL operator==(const CRegKeyContainer& registry_key_1, const CRegKeyContainer& registry_key_2)
  492. {
  493. BOOL fRet = FALSE;
  494. if ((registry_key_1.m_InternalRegKey.session_key != NULL) &&
  495. (registry_key_2.m_InternalRegKey.session_key != NULL))
  496. {
  497. if (*registry_key_1.m_InternalRegKey.session_key ==
  498. *registry_key_2.m_InternalRegKey.session_key)
  499. {
  500. if (0 == My_strcmpO(registry_key_1.m_InternalRegKey.poszResourceID,
  501. registry_key_2.m_InternalRegKey.poszResourceID))
  502. {
  503. fRet = TRUE;
  504. }
  505. }
  506. }
  507. return fRet;
  508. }