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.

1803 lines
39 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. ptutil.cpp
  5. Abstract:
  6. Implementation of Plug terminal registration classes.
  7. --*/
  8. #include "stdafx.h"
  9. #include "PTUtil.h"
  10. #include "manager.h"
  11. ///////////////////////////////////////////
  12. // CPTUtil implementation
  13. //
  14. HRESULT CPTUtil::RecursiveDeleteKey(
  15. IN HKEY hKey,
  16. IN BSTR bstrKeyChild
  17. )
  18. {
  19. LOG((MSP_TRACE, "CPTUtil::RecursiveDeleteKey - enter"));
  20. //
  21. // Validates the arguments
  22. //
  23. if( NULL == hKey )
  24. {
  25. LOG((MSP_TRACE, "CPTUtil::RecursiveDeleteKey exit -"
  26. "hKey was NULL"));
  27. return S_OK;
  28. }
  29. if( IsBadStringPtr( bstrKeyChild, (UINT)-1))
  30. {
  31. LOG((MSP_ERROR, "CPTUtil::RecursiveDeleteKey exit - "
  32. "bstrKeyChild invalid, returns E_INVALIDARG"));
  33. return E_INVALIDARG;
  34. }
  35. //
  36. // Open the child key
  37. //
  38. HKEY hKeyChild;
  39. LONG lResult = RegOpenKeyEx(
  40. hKey,
  41. bstrKeyChild,
  42. 0,
  43. KEY_ALL_ACCESS,
  44. &hKeyChild);
  45. if( ERROR_SUCCESS != lResult )
  46. {
  47. LOG((MSP_ERROR, "CPTUtil::RecursiveDeleteKey exit - "
  48. "RegOpenKeyEx failed, returns E_UNEXPECTED"));
  49. return E_UNEXPECTED;
  50. }
  51. //
  52. // Enumerate the descendents
  53. //
  54. FILETIME time;
  55. TCHAR szBuffer[PTKEY_MAXSIZE];
  56. DWORD dwSize = PTKEY_MAXSIZE;
  57. while( RegEnumKeyEx(
  58. hKeyChild,
  59. 0,
  60. szBuffer,
  61. &dwSize,
  62. NULL,
  63. NULL,
  64. NULL,
  65. &time) == ERROR_SUCCESS)
  66. {
  67. //
  68. // Put the child name into a BSTR
  69. //
  70. BSTR bstrChild = SysAllocString(szBuffer);
  71. if( IsBadStringPtr( bstrChild, (UINT)(-1)) )
  72. {
  73. RegCloseKey(hKeyChild);
  74. LOG((MSP_ERROR, "CPTUtil::RecursiveDeleteKey exit - "
  75. "SysAllocString failed, return E_OUTOFMEMORY"));
  76. return E_OUTOFMEMORY;
  77. }
  78. //
  79. // Delete the child
  80. //
  81. HRESULT hr;
  82. hr = RecursiveDeleteKey(hKeyChild, bstrChild);
  83. //
  84. // Clean-up bstrChild
  85. //
  86. SysFreeString(bstrChild);
  87. if( FAILED(hr) )
  88. {
  89. RegFlushKey(hKeyChild);
  90. RegCloseKey(hKeyChild);
  91. LOG((MSP_ERROR, "CPTUtil::RecursiveDeleteKey exit - "
  92. "RecursiveDeleteKey failed, returns 0%08x", hr));
  93. return hr;
  94. }
  95. //
  96. // Reset the buffer size
  97. //
  98. dwSize = PTKEY_MAXSIZE;
  99. }
  100. //
  101. // Close the child
  102. //
  103. RegFlushKey(hKeyChild);
  104. RegCloseKey(hKeyChild);
  105. HRESULT hr;
  106. hr = RegDeleteKey( hKey, bstrKeyChild);
  107. RegFlushKey( hKey );
  108. LOG((MSP_TRACE, "CPTUtil::RecursiveDeleteKey - exit 0x%08x", hr));
  109. return hr;
  110. }
  111. HRESULT CPTUtil::ListTerminalSuperclasses(
  112. OUT CLSID** ppSuperclasses,
  113. OUT DWORD* pdwCount
  114. )
  115. {
  116. LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - enter"));
  117. //
  118. // Validates argument
  119. //
  120. if( TM_IsBadWritePtr( ppSuperclasses, sizeof(CLSID*)) )
  121. {
  122. LOG((MSP_ERROR, "CPTUtil::ListTerminalSuperclasses exit -"
  123. "pClasses invalid, returns E_POINTER"));
  124. return E_POINTER;
  125. }
  126. if( TM_IsBadWritePtr( pdwCount, sizeof(DWORD)) )
  127. {
  128. LOG((MSP_ERROR, "CPTUtil::ListTerminalSuperclasses exit -"
  129. "pClasses invalid, returns E_POINTER"));
  130. return E_POINTER;
  131. }
  132. //
  133. // Initialize the output arguments
  134. //
  135. *ppSuperclasses = NULL;
  136. *pdwCount = 0;
  137. //
  138. // Get the key path for terminal class
  139. //
  140. WCHAR szKey[ 256 ];
  141. wsprintf( szKey, L"%s", PTKEY_TERMINALS );
  142. LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - "
  143. "TerminalsKey is %s", szKey));
  144. //
  145. // Open the terminal class key
  146. //
  147. HKEY hKey;
  148. LONG lResult = RegOpenKeyEx(
  149. HKEY_LOCAL_MACHINE,
  150. szKey,
  151. 0,
  152. KEY_READ,
  153. &hKey);
  154. //
  155. // Validates registry operation
  156. //
  157. if( ERROR_SUCCESS != lResult )
  158. {
  159. LOG((MSP_ERROR, "CPTUtil::ListTerminalSuperclasses exit - "
  160. "RegOpenKeyEx failed, returns E_UNEXPECTED"));
  161. return E_UNEXPECTED;
  162. }
  163. //
  164. // Create the buffer for the CLSIDs
  165. //
  166. DWORD dwArraySize = 8;
  167. CLSID* pCLSIDs = new CLSID[ dwArraySize ];
  168. if( pCLSIDs == NULL )
  169. {
  170. // Clean-up hKey
  171. RegCloseKey( hKey );
  172. LOG((MSP_ERROR, "CPTUtil::ListTerminalSuperclasses exit - "
  173. "new operator failed, returns E_OUTOFMEMORY"));
  174. return E_OUTOFMEMORY;
  175. }
  176. //
  177. // Enumerate the descendents
  178. //
  179. HRESULT hr = S_OK; // The error code
  180. FILETIME time; // We need this in RegEnumKeyEx
  181. TCHAR szBuffer[PTKEY_MAXSIZE]; // Buffer
  182. DWORD dwSize = PTKEY_MAXSIZE; // Buffer size
  183. DWORD dwChildKey = 0; // Child key index from the registry
  184. DWORD dwCLSIDIndex = 0; // CLSID index into the array
  185. while( RegEnumKeyEx(
  186. hKey,
  187. dwChildKey,
  188. szBuffer,
  189. &dwSize,
  190. NULL,
  191. NULL,
  192. NULL,
  193. &time) == ERROR_SUCCESS)
  194. {
  195. LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - "
  196. "we read the buffer: %s", szBuffer));
  197. // Prepare for the next child key
  198. dwChildKey++;
  199. dwSize = PTKEY_MAXSIZE;
  200. // Try to get the CLSID from this key
  201. CLSID clsid = CLSID_NULL;
  202. HRESULT hr = CLSIDFromString( szBuffer, &clsid);
  203. if( FAILED(hr) )
  204. {
  205. // Go to the next child key
  206. continue;
  207. }
  208. // Have we enougth space for this element?
  209. if( dwArraySize <= dwCLSIDIndex )
  210. {
  211. LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - "
  212. "we have to increase the buffer size"));
  213. // We have to increase the space, double the size
  214. dwArraySize *= 2;
  215. CLSID* pNewCLSIDs = new CLSID[ dwArraySize ];
  216. if( pNewCLSIDs == NULL )
  217. {
  218. hr = E_OUTOFMEMORY;
  219. break;
  220. }
  221. // Copies into the new buffer the old buffer
  222. memcpy( pNewCLSIDs, pCLSIDs, sizeof(CLSID)*dwArraySize/2);
  223. // Delete the old array
  224. delete[] pCLSIDs;
  225. // Set the new array to the old pointer
  226. pCLSIDs = pNewCLSIDs;
  227. }
  228. // We set the item into the CLSID array
  229. pCLSIDs[ dwCLSIDIndex] = clsid;
  230. dwCLSIDIndex++;
  231. }
  232. //
  233. // Clean-up hKey
  234. //
  235. RegCloseKey( hKey );
  236. if( FAILED(hr) )
  237. {
  238. // Clean-up
  239. delete[] pCLSIDs;
  240. LOG((MSP_ERROR, "CPTUtil::ListTerminalSuperclasses exit - "
  241. "failed, returns 0x%08x", hr));
  242. return hr;
  243. }
  244. //
  245. // Set the returning values
  246. //
  247. *ppSuperclasses = pCLSIDs;
  248. *pdwCount = dwCLSIDIndex;
  249. LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - exit"));
  250. return S_OK;
  251. }
  252. HRESULT CPTUtil::SearchForTerminal(
  253. IN IID iidTerminal,
  254. IN DWORD dwMediaType,
  255. IN TERMINAL_DIRECTION Direction,
  256. OUT CPTTerminal* pTerminal
  257. )
  258. {
  259. LOG((MSP_TRACE, "CPTUtil::SearchForTerminal - enter"));
  260. //
  261. // Get the plug-in terminal superclasses
  262. //
  263. CLSID* pSuperclasses = NULL;
  264. DWORD dwSuperclasses = 0;
  265. HRESULT hr = E_FAIL;
  266. hr = ListTerminalSuperclasses(
  267. &pSuperclasses,
  268. &dwSuperclasses
  269. );
  270. if( FAILED(hr) )
  271. {
  272. LOG((MSP_ERROR, "CPTUtil::SearchForTerminal - exit "
  273. "ListTerminalSuperclasses failed, returns 0x%08x", hr));
  274. return hr;
  275. }
  276. //
  277. // Enumerate the plug-in terminal superclasses
  278. //
  279. for( DWORD dwSuperclass = 0; dwSuperclass < dwSuperclasses; dwSuperclass++)
  280. {
  281. //
  282. // If we want a exact terminal (Exact) or just first matching
  283. // terminal from this superclass
  284. //
  285. BOOL bPTExact = (pSuperclasses[dwSuperclass] != iidTerminal);
  286. //
  287. // Get the terminal
  288. //
  289. hr = FindTerminal(
  290. pSuperclasses[dwSuperclass],
  291. bPTExact ? iidTerminal : CLSID_NULL,
  292. dwMediaType,
  293. Direction,
  294. bPTExact,
  295. pTerminal);
  296. if( FAILED(hr))
  297. {
  298. if( !bPTExact)
  299. {
  300. //
  301. // We had to find a terminal in this terminal class
  302. // sorry!!!
  303. break;
  304. }
  305. }
  306. else
  307. {
  308. //
  309. // cool! we found it
  310. //
  311. break;
  312. }
  313. }
  314. //
  315. // Clean-up superclasses array, bstrTermialGUID
  316. //
  317. delete[] pSuperclasses;
  318. //
  319. // Return
  320. //
  321. LOG((MSP_TRACE, "CPTUtil::SearchForTerminal - exit 0x%08x", hr));
  322. return hr;
  323. }
  324. HRESULT CPTUtil::FindTerminal(
  325. IN CLSID clsidSuperclass,
  326. IN CLSID clsidTerminal,
  327. IN DWORD dwMediaType,
  328. IN TERMINAL_DIRECTION Direction,
  329. IN BOOL bExact,
  330. OUT CPTTerminal* pTerminal)
  331. {
  332. LOG((MSP_TRACE, "CPTUtil::FindTerminal - exit"));
  333. //
  334. // Terminal class object
  335. //
  336. CPTSuperclass Superclass;
  337. Superclass.m_clsidSuperclass = clsidSuperclass;
  338. //
  339. // The terminals array
  340. //
  341. CLSID* pTerminals = NULL;
  342. DWORD dwTerminals = 0;
  343. HRESULT hr = E_FAIL;
  344. //
  345. // Lists the terminals for a specific terminal class
  346. //
  347. hr = Superclass.ListTerminalClasses(
  348. dwMediaType,
  349. &pTerminals,
  350. &dwTerminals
  351. );
  352. if( FAILED(hr) )
  353. {
  354. LOG((MSP_ERROR, "CPTUtil::FindTerminal - exit "
  355. "ListTerminalSuperclasses failed, returns 0x%08x", hr));
  356. return hr;
  357. }
  358. //
  359. // Enumerate terminals
  360. //
  361. hr = E_FAIL;
  362. for( DWORD dwTerminal = 0; dwTerminal < dwTerminals; dwTerminal++)
  363. {
  364. //
  365. // CPTTerminal object from registry
  366. //
  367. CPTTerminal Terminal;
  368. Terminal.m_clsidTerminalClass = pTerminals[dwTerminal];
  369. hr = Terminal.Get( clsidSuperclass );
  370. if( FAILED(hr) )
  371. {
  372. continue;
  373. }
  374. //
  375. // try to log the name of the terminal that we are looking at
  376. //
  377. if (NULL != Terminal.m_bstrName)
  378. {
  379. //
  380. // log the name
  381. //
  382. LOG((MSP_TRACE, "CPTUtil::FindTerminal - checking terminal %S", Terminal.m_bstrName));
  383. }
  384. else
  385. {
  386. //
  387. // no name?? strange, but not much we can do...
  388. //
  389. LOG((MSP_TRACE, "CPTUtil::FindTerminal - terminal name is unavaliable"));
  390. }
  391. //
  392. // Is matching
  393. //
  394. if( (dwMediaType & Terminal.m_dwMediaTypes) == 0 )
  395. {
  396. LOG((MSP_TRACE, "CPTUtil::FindTerminal - MediaType unmatched"));
  397. hr = E_FAIL;
  398. continue;
  399. }
  400. //
  401. // map TERMINAL_DIRECTION values to OR'able TMGR_DIRECTION values
  402. //
  403. DWORD dwRegistryDirection = 0;
  404. if (Direction == TD_RENDER)
  405. {
  406. dwRegistryDirection = TMGR_TD_RENDER;
  407. }
  408. else if (Direction == TD_CAPTURE)
  409. {
  410. dwRegistryDirection = TMGR_TD_CAPTURE;
  411. }
  412. else
  413. {
  414. //
  415. // should not happen, really
  416. //
  417. LOG((MSP_ERROR, "CPTUtil::FindTerminal - bad direction value %lx", Direction));
  418. hr = E_FAIL;
  419. //
  420. // this is strange, so debug to see how we got here
  421. //
  422. TM_ASSERT(FALSE);
  423. break;
  424. }
  425. //
  426. // requested direction -- is it one of the directions supported by this terminal?
  427. //
  428. if ((dwRegistryDirection & Terminal.m_dwDirections) == 0)
  429. {
  430. LOG((MSP_TRACE, "CPTUtil::FindTerminal - Direction unmatched"));
  431. hr = E_FAIL;
  432. continue;
  433. }
  434. if( bExact )
  435. {
  436. if( Terminal.m_clsidTerminalClass != clsidTerminal )
  437. {
  438. LOG((MSP_TRACE, "CPTUtil::FindTerminal - PublicCLSID unmatched"));
  439. hr = E_FAIL;
  440. continue;
  441. }
  442. }
  443. if( SUCCEEDED(hr) )
  444. {
  445. LOG((MSP_TRACE, "CPTUtil::FindTerminal - find a matching"));
  446. *pTerminal = Terminal;
  447. break;
  448. }
  449. }
  450. //
  451. // Clean-up the safearray
  452. //
  453. delete[] pTerminals;
  454. //
  455. // Return
  456. //
  457. LOG((MSP_TRACE, "CPTUtil::FindTerminal - exit 0x%08x", hr));
  458. return hr;
  459. }
  460. HRESULT CPTUtil::ListTerminalClasses(
  461. IN DWORD dwMediaTypes,
  462. OUT CLSID** ppTerminalsClasses,
  463. OUT DWORD* pdwCount
  464. )
  465. {
  466. LOG((MSP_TRACE, "CPTUtil::ListTerminalClasses - enter"));
  467. //
  468. // reset the output arguments
  469. //
  470. *ppTerminalsClasses = NULL;
  471. *pdwCount = 0;
  472. //
  473. // Get all terminal classes
  474. //
  475. HRESULT hr = E_FAIL;
  476. CLSID* pSuperclasses = NULL;
  477. DWORD dwSuperclasses = 0;
  478. hr = ListTerminalSuperclasses(
  479. &pSuperclasses,
  480. &dwSuperclasses
  481. );
  482. if( FAILED(hr) )
  483. {
  484. LOG((MSP_ERROR, "CPTUtil::ListTerminalClasses - exit "
  485. "ListTerminalSuperclasses failed, returns 0x%08x", hr));
  486. return hr;
  487. }
  488. DWORD dwArraySize = 8;
  489. CLSID* pTerminals = new CLSID[ dwArraySize];
  490. DWORD dwIndex = 0;
  491. if( pTerminals == NULL )
  492. {
  493. // Cleanup
  494. delete[] pSuperclasses;
  495. LOG((MSP_ERROR, "CPTUtil::ListTerminalClasses - exit "
  496. "new operator failed, returns E_OUTOFMEMORY"));
  497. return E_OUTOFMEMORY;
  498. }
  499. //
  500. // Enumerate all superclasses
  501. //
  502. for( DWORD dwSuperclass = 0; dwSuperclass < dwSuperclasses; dwSuperclass++)
  503. {
  504. //
  505. // List the terminals for this class
  506. //
  507. CPTSuperclass Superclass;
  508. Superclass.m_clsidSuperclass = pSuperclasses[dwSuperclass];
  509. CLSID* pLocalTerminals = NULL;
  510. DWORD dwLocalTerminals = 0;
  511. hr = Superclass.ListTerminalClasses(
  512. 0,
  513. &pLocalTerminals,
  514. &dwLocalTerminals
  515. );
  516. if( FAILED(hr) )
  517. {
  518. hr = S_OK;
  519. LOG((MSP_TRACE, "CPTUtil::ListTerminalClasses - "
  520. "ListTerminalSuperclasses failed"));
  521. continue;
  522. }
  523. //
  524. // Increase the array room if it's necessary
  525. //
  526. if( dwArraySize <= dwIndex + dwLocalTerminals)
  527. {
  528. CLSID* pOldTerminals = pTerminals;
  529. // Create the new buffer
  530. dwArraySize *= 2;
  531. pTerminals = new CLSID[dwArraySize];
  532. if( pTerminals == NULL )
  533. {
  534. // Clean-up
  535. delete[] pLocalTerminals;
  536. //
  537. // Recover the old list of terminals
  538. //
  539. pTerminals = pOldTerminals;
  540. LOG((MSP_TRACE, "CPTUtil::ListTerminalClasses - "
  541. "new operator failed"));
  542. break;
  543. }
  544. // Copies the old one into the new one
  545. memcpy( pTerminals, pOldTerminals, sizeof(CLSID) * dwArraySize/2);
  546. // Delete old terminals
  547. delete[] pOldTerminals;
  548. }
  549. //
  550. // Add the terminals into terminals array
  551. //
  552. for( DWORD dwTerminal = 0; dwTerminal < dwLocalTerminals; dwTerminal++)
  553. {
  554. //
  555. // MediaTypes is right?
  556. //
  557. CPTTerminal Terminal;
  558. Terminal.m_clsidTerminalClass = pLocalTerminals[dwTerminal];
  559. hr = Terminal.Get( pSuperclasses[dwSuperclass] );
  560. if( FAILED(hr) )
  561. {
  562. hr = S_OK;
  563. LOG((MSP_TRACE, "CPTUtil::ListTerminalClasses - "
  564. "GetTerminal failed"));
  565. continue;
  566. }
  567. if( 0 == (dwMediaTypes & Terminal.m_dwMediaTypes) )
  568. {
  569. LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - "
  570. "wrong mediatype"));
  571. continue;
  572. }
  573. //
  574. // Add public clasid to the base safearray
  575. //
  576. pTerminals[dwIndex] = pLocalTerminals[dwTerminal];
  577. dwIndex++;
  578. }
  579. // Clean-up
  580. delete[] pLocalTerminals;
  581. }
  582. // Clean-up
  583. delete[] pSuperclasses;
  584. //
  585. // Return values
  586. //
  587. if( SUCCEEDED(hr) )
  588. {
  589. *ppTerminalsClasses = pTerminals;
  590. *pdwCount = dwIndex;
  591. }
  592. LOG((MSP_TRACE, "CPTUtil::ListTerminalSuperclasses - exit 0x%08x", hr));
  593. return hr;
  594. }
  595. ///////////////////////////////////////////
  596. // CPTTerminal Implementation
  597. //
  598. // Constructor/destructor
  599. CPTTerminal::CPTTerminal()
  600. {
  601. LOG((MSP_TRACE, "CPTTerminal::CPTTerminal - enter"));
  602. m_bstrName = NULL;
  603. m_bstrCompany = NULL;
  604. m_bstrVersion = NULL;
  605. m_clsidTerminalClass = CLSID_NULL;
  606. m_clsidCOM = CLSID_NULL;
  607. //
  608. // initialize with invalid direction and media type -- there is no other
  609. // good default
  610. //
  611. m_dwDirections = 0;
  612. m_dwMediaTypes = 0;
  613. LOG((MSP_TRACE, "CPTTerminal::CPTTerminal - exit"));
  614. }
  615. CPTTerminal::~CPTTerminal()
  616. {
  617. LOG((MSP_TRACE, "CPTTerminal::~CPTTerminal - enter"));
  618. if(m_bstrName)
  619. SysFreeString( m_bstrName );
  620. if( m_bstrCompany)
  621. SysFreeString( m_bstrCompany );
  622. if( m_bstrVersion)
  623. SysFreeString( m_bstrVersion );
  624. LOG((MSP_TRACE, "CPTTerminal::~CPTTerminal - exit"));
  625. }
  626. // CPTTerminal methods
  627. HRESULT CPTTerminal::Add(
  628. IN CLSID clsidSuperclass
  629. )
  630. {
  631. LOG((MSP_TRACE, "CPTTerminal::Add - enter"));
  632. //
  633. // we should have a valid media type
  634. //
  635. if ( !IsValidAggregatedMediaType(m_dwMediaTypes) )
  636. {
  637. LOG((MSP_ERROR, "CPTTerminal::Add exit -"
  638. "media type is not valid %lx. return TAPI_E_INVALIDMEDIATYPE",
  639. m_dwMediaTypes));
  640. return TAPI_E_INVALIDMEDIATYPE;
  641. }
  642. //
  643. // we should have a valid direction
  644. //
  645. if ( ( TMGR_TD_CAPTURE != m_dwDirections ) &&
  646. ( TMGR_TD_RENDER != m_dwDirections ) &&
  647. ( TMGR_TD_BOTH != m_dwDirections ) )
  648. {
  649. LOG((MSP_ERROR, "CPTTerminal::Add exit - "
  650. "direction is not valid %lx. return TAPI_E_INVALIDDIRECTION",
  651. TAPI_E_INVALIDDIRECTION));
  652. return TAPI_E_INVALIDDIRECTION;
  653. }
  654. //
  655. // We determine the terminal path into registry
  656. //
  657. LPOLESTR lpszSuperclass = NULL;
  658. LPOLESTR lpszTerminalClass = NULL;
  659. HRESULT hr = E_FAIL;
  660. hr = StringFromCLSID( clsidSuperclass, &lpszSuperclass );
  661. if( FAILED(hr) )
  662. {
  663. LOG((MSP_ERROR, "CPTTerminal::Add exit -"
  664. "StringFromCLSID for Superclass failed, returns 0x%08x", hr));
  665. return hr;
  666. }
  667. hr = StringFromCLSID( m_clsidTerminalClass, &lpszTerminalClass );
  668. if( FAILED(hr) )
  669. {
  670. CoTaskMemFree( lpszSuperclass );
  671. LOG((MSP_ERROR, "CPTTerminal::Add exit -"
  672. "StringFromCLSID for Superclass failed, returns 0x%08x", hr));
  673. return hr;
  674. }
  675. WCHAR szKey[PTKEY_MAXSIZE];
  676. WCHAR szKeySuperclass[PTKEY_MAXSIZE];
  677. wsprintf( szKey, TEXT("%s\\%s\\%s"),
  678. PTKEY_TERMINALS,
  679. lpszSuperclass,
  680. lpszTerminalClass
  681. );
  682. wsprintf( szKeySuperclass, TEXT("%s\\%s"),
  683. PTKEY_TERMINALS,
  684. lpszSuperclass);
  685. // Clean-up, we need later the TerminalClass
  686. CoTaskMemFree( lpszSuperclass );
  687. CoTaskMemFree( lpszTerminalClass );
  688. //
  689. // Try to see if the superclass key exist
  690. //
  691. HKEY hKeySuperclass = NULL;
  692. long lResult;
  693. lResult = RegOpenKey(
  694. HKEY_LOCAL_MACHINE,
  695. szKeySuperclass,
  696. &hKeySuperclass);
  697. if( ERROR_SUCCESS != lResult )
  698. {
  699. // We don't have the superclass
  700. LOG((MSP_ERROR, "CPTTerminal::Add exit -"
  701. "RegOpenKey for superclass failed, returns E_FAIL"));
  702. return E_FAIL;
  703. }
  704. RegCloseKey( hKeySuperclass );
  705. //
  706. // Open or create key
  707. //
  708. HKEY hKey = NULL;
  709. lResult = RegCreateKeyEx(
  710. HKEY_LOCAL_MACHINE,
  711. szKey,
  712. 0,
  713. NULL,
  714. REG_OPTION_NON_VOLATILE,
  715. KEY_ALL_ACCESS,
  716. NULL,
  717. &hKey,
  718. NULL);
  719. //
  720. // Validates registry operation
  721. //
  722. if( ERROR_SUCCESS != lResult )
  723. {
  724. LOG((MSP_ERROR, "CPTTerminal::Add exit -"
  725. "RegCreateKeyEx failed, returns E_UNEXPECTED"));
  726. return E_UNEXPECTED;
  727. }
  728. //
  729. // Edit terminal name
  730. //
  731. if( !IsBadStringPtr(m_bstrName, (UINT)-1) )
  732. {
  733. lResult = RegSetValueEx(
  734. hKey,
  735. PTKEY_NAME,
  736. 0,
  737. REG_SZ,
  738. (BYTE *)m_bstrName,
  739. (SysStringLen( m_bstrName) + 1) * sizeof(WCHAR)
  740. );
  741. }
  742. //
  743. // Edit company name
  744. //
  745. if( !IsBadStringPtr(m_bstrCompany, (UINT)-1) )
  746. {
  747. lResult = RegSetValueEx(
  748. hKey,
  749. PTKEY_COMPANY,
  750. 0,
  751. REG_SZ,
  752. (BYTE *)m_bstrCompany,
  753. (SysStringLen( m_bstrCompany) + 1) * sizeof(WCHAR)
  754. );
  755. }
  756. //
  757. // Edit terminal version
  758. //
  759. if( !IsBadStringPtr(m_bstrVersion, (UINT)-1) )
  760. {
  761. lResult = RegSetValueEx(
  762. hKey,
  763. PTKEY_VERSION,
  764. 0,
  765. REG_SZ,
  766. (BYTE *)m_bstrVersion,
  767. (SysStringLen( m_bstrVersion) + 1) * sizeof(WCHAR)
  768. );
  769. }
  770. //
  771. // Edit terminal CLSID create
  772. //
  773. if( m_clsidCOM != CLSID_NULL )
  774. {
  775. LPOLESTR lpszCOM = NULL;
  776. hr = StringFromCLSID( m_clsidCOM, &lpszCOM );
  777. if( SUCCEEDED(hr) )
  778. {
  779. lResult = RegSetValueEx(
  780. hKey,
  781. PTKEY_CLSIDCREATE,
  782. 0,
  783. REG_SZ,
  784. (BYTE *)lpszCOM,
  785. (wcslen( lpszCOM) + 1) * sizeof(WCHAR)
  786. );
  787. // Clean-up
  788. CoTaskMemFree( lpszCOM );
  789. }
  790. }
  791. //
  792. // Edit terminal directions
  793. //
  794. lResult = RegSetValueEx(
  795. hKey,
  796. PTKEY_DIRECTIONS,
  797. 0,
  798. REG_DWORD,
  799. (BYTE *)&m_dwDirections,
  800. sizeof( m_dwDirections )
  801. );
  802. //
  803. // Edit terminal mediatypes
  804. //
  805. lResult = RegSetValueEx(
  806. hKey,
  807. PTKEY_MEDIATYPES,
  808. 0,
  809. REG_DWORD,
  810. (BYTE *)&m_dwMediaTypes,
  811. sizeof( m_dwMediaTypes )
  812. );
  813. //
  814. // Clean-up hKey
  815. //
  816. RegFlushKey( hKey );
  817. RegCloseKey( hKey );
  818. LOG((MSP_TRACE, "CPTTerminal::Add - exit"));
  819. return S_OK;
  820. }
  821. HRESULT CPTTerminal::Delete(
  822. IN CLSID clsidSuperclass
  823. )
  824. {
  825. LOG((MSP_TRACE, "CPTTerminal::Delete - enter"));
  826. //
  827. // We determine the terminal path into registry
  828. //
  829. LPOLESTR lpszSuperclass = NULL;
  830. LPOLESTR lpszTerminalClass = NULL;
  831. HRESULT hr = E_FAIL;
  832. hr = StringFromCLSID( clsidSuperclass, &lpszSuperclass );
  833. if( FAILED(hr) )
  834. {
  835. LOG((MSP_ERROR, "CPTTerminal::Delete exit -"
  836. "StringFromCLSID for Superclass failed, returns 0x%08x", hr));
  837. return hr;
  838. }
  839. hr = StringFromCLSID( m_clsidTerminalClass, &lpszTerminalClass );
  840. if( FAILED(hr) )
  841. {
  842. CoTaskMemFree( lpszSuperclass );
  843. LOG((MSP_ERROR, "CPTTerminal::Delete exit -"
  844. "StringFromCLSID for Superclass failed, returns 0x%08x", hr));
  845. return hr;
  846. }
  847. WCHAR szKey[PTKEY_MAXSIZE];
  848. wsprintf( szKey, TEXT("%s\\%s\\%s"),
  849. PTKEY_TERMINALS,
  850. lpszSuperclass,
  851. lpszTerminalClass
  852. );
  853. // Clean-up, we need later the TerminalClass
  854. CoTaskMemFree( lpszSuperclass );
  855. CoTaskMemFree( lpszTerminalClass );
  856. //
  857. // Remove key
  858. //
  859. hr = CPTUtil::RecursiveDeleteKey(
  860. HKEY_LOCAL_MACHINE,
  861. szKey
  862. );
  863. //
  864. // Return value
  865. //
  866. LOG((MSP_TRACE, "CPTTerminal::Delete - exit (0x%08x)", hr));
  867. return hr;
  868. }
  869. HRESULT CPTTerminal::Get(
  870. IN CLSID clsidSuperclass
  871. )
  872. {
  873. LOG((MSP_TRACE, "CPTTerminal::Get - enter"));
  874. //
  875. // Reset members
  876. //
  877. if(m_bstrName)
  878. {
  879. SysFreeString( m_bstrName );
  880. m_bstrName = NULL;
  881. }
  882. if( m_bstrCompany)
  883. {
  884. SysFreeString( m_bstrCompany );
  885. m_bstrCompany = NULL;
  886. }
  887. if( m_bstrVersion)
  888. {
  889. SysFreeString( m_bstrVersion );
  890. m_bstrVersion = NULL;
  891. }
  892. m_clsidCOM = CLSID_NULL;
  893. //
  894. // initialize with invalid direction and media type
  895. //
  896. m_dwDirections = 0;
  897. m_dwMediaTypes = 0;
  898. //
  899. // We determine the terminal path into registry
  900. //
  901. LPOLESTR lpszSuperclass = NULL;
  902. LPOLESTR lpszTerminalClass = NULL;
  903. HRESULT hr = E_FAIL;
  904. hr = StringFromCLSID( clsidSuperclass, &lpszSuperclass );
  905. if( FAILED(hr) )
  906. {
  907. LOG((MSP_ERROR, "CPTTerminal::Get exit -"
  908. "StringFromCLSID for Superclass failed, returns 0x%08x", hr));
  909. return hr;
  910. }
  911. hr = StringFromCLSID( m_clsidTerminalClass, &lpszTerminalClass );
  912. if( FAILED(hr) )
  913. {
  914. CoTaskMemFree( lpszSuperclass );
  915. LOG((MSP_ERROR, "CPTTerminal::Get exit -"
  916. "StringFromCLSID for Superclass failed, returns 0x%08x", hr));
  917. return hr;
  918. }
  919. WCHAR szKey[PTKEY_MAXSIZE];
  920. wsprintf( szKey, TEXT("%s\\%s\\%s"),
  921. PTKEY_TERMINALS,
  922. lpszSuperclass,
  923. lpszTerminalClass
  924. );
  925. // Clean-up, we need later the TerminalClass
  926. CoTaskMemFree( lpszSuperclass );
  927. CoTaskMemFree( lpszTerminalClass );
  928. //
  929. // Open terminal key
  930. //
  931. HKEY hKey = NULL;
  932. LONG lResult;
  933. lResult = RegOpenKeyEx(
  934. HKEY_LOCAL_MACHINE,
  935. szKey,
  936. 0,
  937. KEY_QUERY_VALUE,
  938. &hKey);
  939. //
  940. // Validates registry operation
  941. //
  942. if( ERROR_SUCCESS != lResult )
  943. {
  944. LOG((MSP_ERROR, "CPTTerminal::Get exit -"
  945. "RegOpenKeyEx failed, returns E_UNEXPECTED"));
  946. return E_UNEXPECTED;
  947. }
  948. //
  949. // Query for name
  950. //
  951. TCHAR szBuffer[PTKEY_MAXSIZE];
  952. DWORD dwSize = PTKEY_MAXSIZE * sizeof( TCHAR );
  953. DWORD dwType = REG_SZ;
  954. lResult = RegQueryValueEx(
  955. hKey,
  956. PTKEY_NAME,
  957. 0,
  958. &dwType,
  959. (LPBYTE)szBuffer,
  960. &dwSize);
  961. if( ERROR_SUCCESS == lResult )
  962. {
  963. m_bstrName = SysAllocString( szBuffer );
  964. }
  965. //
  966. // Query for company
  967. //
  968. dwSize = PTKEY_MAXSIZE * sizeof( TCHAR );
  969. dwType = REG_SZ;
  970. lResult = RegQueryValueEx(
  971. hKey,
  972. PTKEY_COMPANY,
  973. 0,
  974. &dwType,
  975. (LPBYTE)szBuffer,
  976. &dwSize);
  977. if( ERROR_SUCCESS == lResult )
  978. {
  979. m_bstrCompany = SysAllocString( szBuffer );
  980. }
  981. //
  982. // Query for version
  983. //
  984. dwSize = PTKEY_MAXSIZE * sizeof( TCHAR );
  985. dwType = REG_SZ;
  986. lResult = RegQueryValueEx(
  987. hKey,
  988. PTKEY_VERSION,
  989. 0,
  990. &dwType,
  991. (LPBYTE)szBuffer,
  992. &dwSize);
  993. if( ERROR_SUCCESS == lResult )
  994. {
  995. m_bstrVersion = SysAllocString( szBuffer );
  996. }
  997. //
  998. // Query for CLSID create
  999. //
  1000. dwSize = PTKEY_MAXSIZE * sizeof( TCHAR );
  1001. dwType = REG_SZ;
  1002. lResult = RegQueryValueEx(
  1003. hKey,
  1004. PTKEY_CLSIDCREATE,
  1005. 0,
  1006. &dwType,
  1007. (LPBYTE)szBuffer,
  1008. &dwSize);
  1009. if( ERROR_SUCCESS == lResult )
  1010. {
  1011. HRESULT hr = CLSIDFromString( szBuffer, &m_clsidCOM);
  1012. if( FAILED(hr) )
  1013. {
  1014. m_clsidCOM = CLSID_NULL;
  1015. }
  1016. }
  1017. //
  1018. // Query for directions
  1019. //
  1020. dwType = REG_DWORD;
  1021. DWORD dwValue = 0;
  1022. dwSize = sizeof( dwValue );
  1023. lResult = RegQueryValueEx(
  1024. hKey,
  1025. PTKEY_DIRECTIONS,
  1026. 0,
  1027. &dwType,
  1028. (LPBYTE)&dwValue,
  1029. &dwSize);
  1030. if( ERROR_SUCCESS == lResult )
  1031. {
  1032. m_dwDirections = dwValue;
  1033. }
  1034. //
  1035. // Query for media types
  1036. //
  1037. dwSize = sizeof( dwValue );
  1038. dwType = REG_DWORD;
  1039. dwValue = 0;
  1040. lResult = RegQueryValueEx(
  1041. hKey,
  1042. PTKEY_MEDIATYPES,
  1043. 0,
  1044. &dwType,
  1045. (LPBYTE)&dwValue,
  1046. &dwSize);
  1047. if( ERROR_SUCCESS == lResult )
  1048. {
  1049. m_dwMediaTypes = dwValue;
  1050. }
  1051. //
  1052. // Clean-up hKey
  1053. //
  1054. RegCloseKey( hKey );
  1055. LOG((MSP_TRACE, "CPTTerminal::Get - exit"));
  1056. return S_OK;
  1057. }
  1058. ///////////////////////////////////////////
  1059. // CPTSuperclass Implementation
  1060. //
  1061. // Constructor/Destructor
  1062. CPTSuperclass::CPTSuperclass()
  1063. {
  1064. LOG((MSP_TRACE, "CPTSuperclass::CPTSuperclass - enter"));
  1065. m_bstrName = NULL;
  1066. m_clsidSuperclass = CLSID_NULL;
  1067. LOG((MSP_TRACE, "CPTSuperclass::CPTSuperclass - exit"));
  1068. }
  1069. CPTSuperclass::~CPTSuperclass()
  1070. {
  1071. LOG((MSP_TRACE, "CPTSuperclass::~CPTSuperclass - enter"));
  1072. if(m_bstrName)
  1073. SysFreeString( m_bstrName );
  1074. LOG((MSP_TRACE, "CPTSuperclass::~CPTSuperclass - exit"));
  1075. }
  1076. // CPTSuperclass methods
  1077. HRESULT CPTSuperclass::Add()
  1078. {
  1079. LOG((MSP_TRACE, "CPTSuperclass::Add - enter"));
  1080. //
  1081. // Get the superclass CLSID as string
  1082. //
  1083. LPOLESTR lpszSuperclassCLSID = NULL;
  1084. HRESULT hr = E_FAIL;
  1085. hr = StringFromCLSID( m_clsidSuperclass, &lpszSuperclassCLSID);
  1086. if( FAILED(hr) )
  1087. {
  1088. LOG((MSP_ERROR, "CPTSuperclass::Add exit -"
  1089. "StringFromCLSID failed, returns E_OUTOFMEMORY"));
  1090. return E_OUTOFMEMORY;
  1091. }
  1092. //
  1093. // Create key path for superclass
  1094. //
  1095. WCHAR szKey[PTKEY_MAXSIZE];
  1096. wsprintf( szKey, TEXT("%s\\%s"), PTKEY_TERMINALS, lpszSuperclassCLSID);
  1097. // Clean-up
  1098. CoTaskMemFree( lpszSuperclassCLSID );
  1099. //
  1100. // Open the registry key
  1101. //
  1102. HKEY hKey = NULL;
  1103. long lResult;
  1104. lResult = RegCreateKeyEx(
  1105. HKEY_LOCAL_MACHINE,
  1106. szKey,
  1107. 0,
  1108. NULL,
  1109. REG_OPTION_NON_VOLATILE,
  1110. KEY_ALL_ACCESS,
  1111. NULL,
  1112. &hKey,
  1113. NULL);
  1114. //
  1115. // Validates the registry operation
  1116. //
  1117. if( ERROR_SUCCESS != lResult )
  1118. {
  1119. LOG((MSP_ERROR, "CPTSuperclass::Add exit -"
  1120. "RegCreateKeyEx failed, returns E_UNEXPECTED"));
  1121. return E_UNEXPECTED;
  1122. }
  1123. //
  1124. // Edit the name of the terminal class
  1125. //
  1126. if( !IsBadStringPtr(m_bstrName, (UINT)-1) )
  1127. {
  1128. lResult = RegSetValueEx(
  1129. hKey,
  1130. PTKEY_NAME,
  1131. 0,
  1132. REG_SZ,
  1133. (BYTE *)m_bstrName,
  1134. (SysStringLen( m_bstrName) + 1) * sizeof(WCHAR)
  1135. );
  1136. }
  1137. //
  1138. // Clean-up hKey
  1139. //
  1140. RegFlushKey( hKey );
  1141. RegCloseKey( hKey );
  1142. LOG((MSP_TRACE, "CPTSuperclass::Add - exit"));
  1143. return S_OK;
  1144. }
  1145. HRESULT CPTSuperclass::Delete()
  1146. {
  1147. LOG((MSP_TRACE, "CPTSuperclass::Delete - enter"));
  1148. //
  1149. // Get the superclass CLSID as string
  1150. //
  1151. LPOLESTR lpszSuperclassCLSID = NULL;
  1152. HRESULT hr = E_FAIL;
  1153. hr = StringFromCLSID( m_clsidSuperclass, &lpszSuperclassCLSID);
  1154. if( FAILED(hr) )
  1155. {
  1156. LOG((MSP_ERROR, "CPTSuperclass::Delete exit -"
  1157. "StringFromCLSID failed, returns E_OUTOFMEMORY"));
  1158. return E_OUTOFMEMORY;
  1159. }
  1160. //
  1161. // Create key path for superclass
  1162. //
  1163. WCHAR szKey[PTKEY_MAXSIZE];
  1164. wsprintf( szKey, TEXT("%s\\%s"), PTKEY_TERMINALS, lpszSuperclassCLSID);
  1165. // Clean-up
  1166. CoTaskMemFree( lpszSuperclassCLSID );
  1167. //
  1168. // Remove key
  1169. //
  1170. hr = CPTUtil::RecursiveDeleteKey(
  1171. HKEY_LOCAL_MACHINE,
  1172. szKey
  1173. );
  1174. //
  1175. // Return value
  1176. //
  1177. LOG((MSP_TRACE, "CPTSuperclass::Delete - exit (0x%08x)", hr));
  1178. return hr;
  1179. }
  1180. HRESULT CPTSuperclass::Get()
  1181. {
  1182. LOG((MSP_TRACE, "CPTSuperclass::Get - enter"));
  1183. //
  1184. // Get the superclass CLSID as string
  1185. //
  1186. LPOLESTR lpszSuperclassCLSID = NULL;
  1187. HRESULT hr = E_FAIL;
  1188. hr = StringFromCLSID( m_clsidSuperclass, &lpszSuperclassCLSID);
  1189. if( FAILED(hr) )
  1190. {
  1191. LOG((MSP_ERROR, "CPTSuperclass::Get exit -"
  1192. "StringFromCLSID failed, returns E_OUTOFMEMORY"));
  1193. return E_OUTOFMEMORY;
  1194. }
  1195. //
  1196. // Create key path for superclass
  1197. //
  1198. WCHAR szKey[PTKEY_MAXSIZE];
  1199. wsprintf( szKey, TEXT("%s\\%s"), PTKEY_TERMINALS, lpszSuperclassCLSID);
  1200. // Clean-up
  1201. CoTaskMemFree( lpszSuperclassCLSID );
  1202. //
  1203. // Reset members
  1204. //
  1205. if(m_bstrName)
  1206. {
  1207. SysFreeString( m_bstrName );
  1208. m_bstrName = NULL;
  1209. }
  1210. //
  1211. // Open terminal key
  1212. //
  1213. HKEY hKey = NULL;
  1214. LONG lResult;
  1215. lResult = RegOpenKeyEx(
  1216. HKEY_LOCAL_MACHINE,
  1217. szKey,
  1218. 0,
  1219. KEY_QUERY_VALUE,
  1220. &hKey);
  1221. //
  1222. // Validates registry operation
  1223. //
  1224. if( ERROR_SUCCESS != lResult )
  1225. {
  1226. LOG((MSP_ERROR, "CPTSuperclass::Get exit -"
  1227. "RegOpenKeyEx failed, returns E_UNEXPECTED"));
  1228. return E_UNEXPECTED;
  1229. }
  1230. //
  1231. // Query for name
  1232. //
  1233. TCHAR szBuffer[PTKEY_MAXSIZE];
  1234. DWORD dwSize = PTKEY_MAXSIZE * sizeof( TCHAR );
  1235. DWORD dwType = REG_SZ;
  1236. lResult = RegQueryValueEx(
  1237. hKey,
  1238. PTKEY_NAME,
  1239. 0,
  1240. &dwType,
  1241. (LPBYTE)szBuffer,
  1242. &dwSize);
  1243. if( ERROR_SUCCESS == lResult )
  1244. {
  1245. m_bstrName = SysAllocString( szBuffer );
  1246. }
  1247. else
  1248. {
  1249. m_bstrName = SysAllocString(_T(""));
  1250. }
  1251. //
  1252. // Clean-up hKey
  1253. //
  1254. RegCloseKey( hKey );
  1255. LOG((MSP_TRACE, "CPTSuperclass::Get - exit"));
  1256. return S_OK;
  1257. }
  1258. HRESULT CPTSuperclass::ListTerminalClasses(
  1259. IN DWORD dwMediaTypes,
  1260. OUT CLSID** ppTerminals,
  1261. OUT DWORD* pdwCount
  1262. )
  1263. {
  1264. LOG((MSP_TRACE, "CPTSuperclass::ListTerminalSuperclasses - enter"));
  1265. //
  1266. // Validates argument
  1267. //
  1268. if( TM_IsBadWritePtr( ppTerminals, sizeof(CLSID*)) )
  1269. {
  1270. LOG((MSP_ERROR, "CPTSuperclass::ListTerminalSuperclasses exit -"
  1271. "pTerminals invalid, returns E_INVALIDARG"));
  1272. return E_INVALIDARG;
  1273. }
  1274. //
  1275. // Reset the output arguments
  1276. //
  1277. *ppTerminals = NULL;
  1278. *pdwCount = 0;
  1279. //
  1280. // Get the superclass CLSID as string
  1281. //
  1282. LPOLESTR lpszSuperclassCLSID = NULL;
  1283. HRESULT hr = E_FAIL;
  1284. hr = StringFromCLSID( m_clsidSuperclass, &lpszSuperclassCLSID);
  1285. if( FAILED(hr) )
  1286. {
  1287. LOG((MSP_ERROR, "CPTSuperclass::Get exit -"
  1288. "StringFromCLSID failed, returns E_OUTOFMEMORY"));
  1289. return E_OUTOFMEMORY;
  1290. }
  1291. //
  1292. // Create key path for superclass
  1293. //
  1294. WCHAR szKey[PTKEY_MAXSIZE];
  1295. wsprintf( szKey, TEXT("%s\\%s"), PTKEY_TERMINALS, lpszSuperclassCLSID);
  1296. // Clean-up
  1297. CoTaskMemFree( lpszSuperclassCLSID );
  1298. //
  1299. // Open the terminal class key
  1300. //
  1301. HKEY hKey;
  1302. LONG lResult = RegOpenKeyEx(
  1303. HKEY_LOCAL_MACHINE,
  1304. szKey,
  1305. 0,
  1306. KEY_READ,
  1307. &hKey);
  1308. //
  1309. // Validates registry operation
  1310. //
  1311. if( ERROR_SUCCESS != lResult )
  1312. {
  1313. LOG((MSP_ERROR, "CPTSuperclass::ListTerminalSuperclasses exit - "
  1314. "RegOpenKeyEx failed, returns E_INVALIDARG"));
  1315. return E_INVALIDARG;
  1316. }
  1317. DWORD dwArraySize = 8;
  1318. CLSID* pTerminals = new CLSID[dwArraySize];
  1319. if( pTerminals == NULL )
  1320. {
  1321. // Clean-up hKey
  1322. RegCloseKey( hKey );
  1323. LOG((MSP_ERROR, "CPTSuperclass::ListTerminalSuperclasses exit - "
  1324. "new operator failed, returns E_OUTOFMEMORY"));
  1325. return E_OUTOFMEMORY;
  1326. }
  1327. //
  1328. // Enumerate the descendents
  1329. //
  1330. FILETIME time;
  1331. TCHAR szBuffer[PTKEY_MAXSIZE]; // Buffer
  1332. DWORD dwSize = PTKEY_MAXSIZE; // Buffer size
  1333. DWORD dwIndex = 0; // Index into array
  1334. DWORD dwChildIndex = 0; // Child index into registry
  1335. while( RegEnumKeyEx(
  1336. hKey,
  1337. dwChildIndex,
  1338. szBuffer,
  1339. &dwSize,
  1340. NULL,
  1341. NULL,
  1342. NULL,
  1343. &time) == ERROR_SUCCESS)
  1344. {
  1345. //
  1346. // Prepare for the nex child
  1347. //
  1348. dwChildIndex++;
  1349. dwSize = PTKEY_MAXSIZE;
  1350. //
  1351. // I have to qury MediaType value for this entry
  1352. //
  1353. CPTTerminal Terminal;
  1354. HRESULT hr = CLSIDFromString( szBuffer, &Terminal.m_clsidTerminalClass);
  1355. if( FAILED(hr) )
  1356. {
  1357. hr = S_OK;
  1358. continue;
  1359. }
  1360. if( dwMediaTypes )
  1361. {
  1362. HRESULT hr = E_FAIL;
  1363. hr = Terminal.Get( m_clsidSuperclass );
  1364. if( FAILED(hr) )
  1365. {
  1366. hr = S_OK;
  1367. continue;
  1368. }
  1369. if( !(Terminal.m_dwMediaTypes & dwMediaTypes) )
  1370. {
  1371. continue;
  1372. }
  1373. }
  1374. //
  1375. // Increase the array room if it's necessary
  1376. //
  1377. if( dwArraySize <= dwIndex)
  1378. {
  1379. // Old buffer
  1380. CLSID* pOldTerminals = pTerminals;
  1381. // New buffer
  1382. dwArraySize *= 2;
  1383. pTerminals = new CLSID[dwArraySize];
  1384. if( pTerminals == NULL )
  1385. {
  1386. delete[] pOldTerminals;
  1387. LOG((MSP_ERROR, "CPTSuperclass::ListTerminalSuperclasses exit - "
  1388. "new operator failed, returns E_OUTOFMEMORY"));
  1389. return E_OUTOFMEMORY;
  1390. }
  1391. // Copies the old buffer into the new one
  1392. memcpy( pTerminals, pOldTerminals, sizeof(CLSID)*dwArraySize/2);
  1393. // Delete the old buffer
  1394. delete[] pOldTerminals;
  1395. }
  1396. //
  1397. // Add the terminal class
  1398. //
  1399. pTerminals[dwIndex] = Terminal.m_clsidTerminalClass;
  1400. dwIndex++;
  1401. }
  1402. //
  1403. // Clean-up hKey
  1404. //
  1405. RegCloseKey( hKey );
  1406. //
  1407. // Return values
  1408. //
  1409. if( SUCCEEDED(hr) )
  1410. {
  1411. *ppTerminals = pTerminals;
  1412. *pdwCount = dwIndex;
  1413. }
  1414. LOG((MSP_TRACE, "CPTSuperclass::ListTerminalSuperclasses - exit Len=%ld, 0x%08x", dwIndex, hr));
  1415. return hr;
  1416. }
  1417. // eof