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.

840 lines
23 KiB

  1. /*************************************************************************
  2. *
  3. * regpd.c
  4. *
  5. * Register APIs for Tds and Pds (transport and protocol drivers)
  6. *
  7. * Copyright (c) 1998 Microsoft Corporation
  8. *
  9. *
  10. *************************************************************************/
  11. /*
  12. * Includes
  13. */
  14. #include <windows.h>
  15. #include <ksguid.h>
  16. #include <ntddkbd.h>
  17. #include <ntddmou.h>
  18. #include <winstaw.h>
  19. #include <regapi.h>
  20. /*
  21. * External Procedures defined here
  22. */
  23. HANDLE WINAPI RegOpenServerW ( LPWSTR pServerName );
  24. HANDLE WINAPI RegOpenServerA ( LPSTR pServerName );
  25. LONG WINAPI RegCloseServer ( HANDLE hServer );
  26. LONG WINAPI RegPdEnumerateW( HANDLE, PWDNAMEW, BOOLEAN, PULONG, PULONG, PPDNAMEW, PULONG );
  27. LONG WINAPI RegPdEnumerateA( HANDLE, PWDNAMEA, BOOLEAN, PULONG, PULONG, PPDNAMEA, PULONG );
  28. LONG WINAPI RegPdCreateW( HANDLE, PWDNAMEW, BOOLEAN, PPDNAMEW, BOOLEAN, PPDCONFIG3W, ULONG );
  29. LONG WINAPI RegPdCreateA( HANDLE, PWDNAMEA, BOOLEAN, PPDNAMEA, BOOLEAN, PPDCONFIG3A, ULONG );
  30. LONG WINAPI RegPdQueryW( HANDLE, PWDNAMEW, BOOLEAN, PPDNAMEW, PPDCONFIG3W, ULONG, PULONG );
  31. LONG WINAPI RegPdQueryA( HANDLE, PWDNAMEA, BOOLEAN, PPDNAMEA, PPDCONFIG3A, ULONG, PULONG );
  32. LONG WINAPI RegPdDeleteW( HANDLE, PWDNAMEW, BOOLEAN, PPDNAMEW );
  33. LONG WINAPI RegPdDeleteA( HANDLE, PWDNAMEA, BOOLEAN, PPDNAMEA );
  34. /*
  35. * other internal Procedures used (not defined here)
  36. */
  37. VOID CreatePdConfig3( HKEY, PPDCONFIG3, ULONG );
  38. VOID QueryPdConfig3( HKEY, PPDCONFIG3, ULONG );
  39. VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
  40. VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
  41. VOID PdConfigU2A( PPDCONFIGA, PPDCONFIGW );
  42. VOID PdConfigA2U( PPDCONFIGW, PPDCONFIGA );
  43. VOID PdConfig3U2A( PPDCONFIG3A, PPDCONFIG3W );
  44. VOID PdConfig3A2U( PPDCONFIG3W, PPDCONFIG3A );
  45. VOID PdParamsU2A( PPDPARAMSA, PPDPARAMSW );
  46. VOID PdParamsA2U( PPDPARAMSW, PPDPARAMSA );
  47. VOID AsyncConfigU2A ( PASYNCCONFIGA, PASYNCCONFIGW );
  48. VOID AsyncConfigA2U ( PASYNCCONFIGW, PASYNCCONFIGA );
  49. /*****************************************************************************
  50. *
  51. * RegOpenServerA
  52. *
  53. *
  54. * ENTRY:
  55. * Machine (input)
  56. * Name of WinFrame computer to connect to
  57. *
  58. * EXIT:
  59. * handle to a server's Registry (or NULL on error)
  60. *
  61. ****************************************************************************/
  62. HANDLE WINAPI
  63. RegOpenServerA(
  64. LPSTR pServerName
  65. )
  66. {
  67. HKEY hServer;
  68. ULONG NameLength;
  69. PWCHAR pServerNameW = NULL;
  70. if( pServerName == NULL ) {
  71. return( (HANDLE)HKEY_LOCAL_MACHINE );
  72. }
  73. NameLength = strlen( pServerName ) + 1;
  74. pServerNameW = LocalAlloc( 0, NameLength * sizeof(WCHAR) );
  75. if( pServerNameW == NULL ) {
  76. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  77. return( NULL );
  78. }
  79. AnsiToUnicode( pServerNameW, NameLength*sizeof(WCHAR), pServerName );
  80. hServer = RegOpenServerW( pServerNameW );
  81. LocalFree( pServerNameW );
  82. return( (HANDLE) hServer );
  83. }
  84. /*****************************************************************************
  85. *
  86. * RegOpenServerW
  87. *
  88. * NULL for machine name means local system.
  89. *
  90. * ENTRY:
  91. * Machine (input)
  92. * Name of WinFrame computer to connect to
  93. *
  94. * EXIT:
  95. * handle to server's Registry (or NULL on error)
  96. *
  97. ****************************************************************************/
  98. HANDLE WINAPI
  99. RegOpenServerW( LPWSTR pServerName ){
  100. HKEY hKey;
  101. if( pServerName == NULL )
  102. return( HKEY_LOCAL_MACHINE );
  103. else {
  104. if( RegConnectRegistry( pServerName, HKEY_LOCAL_MACHINE, &hKey ) != ERROR_SUCCESS ){
  105. return( NULL );
  106. }
  107. }
  108. return( hKey );
  109. }
  110. /*****************************************************************************
  111. *
  112. * RegCloseServer
  113. *
  114. * Close a connection to a Server Registry.
  115. *
  116. * ENTRY:
  117. * hServer (input)
  118. * Handle to close
  119. *
  120. * EXIT:
  121. * ERROR_SUCCESS - no error
  122. *
  123. ****************************************************************************/
  124. LONG WINAPI
  125. RegCloseServer( HANDLE hServer )
  126. {
  127. return( RegCloseKey( (HKEY)hServer ) );
  128. }
  129. /*******************************************************************************
  130. *
  131. * RegPdEnumerateA (ANSI stub)
  132. *
  133. * Returns a list of configured Pds in the registry.
  134. *
  135. * ENTRY:
  136. *
  137. * see RegPdEnumerateW
  138. *
  139. * EXIT:
  140. *
  141. * see RegPdEnumerateW, plus
  142. *
  143. * ERROR_NOT_ENOUGH_MEMORY - the LocalAlloc failed
  144. *
  145. ******************************************************************************/
  146. LONG WINAPI
  147. RegPdEnumerateA( HANDLE hServer,
  148. PWDNAMEA pWdName,
  149. BOOLEAN bTd,
  150. PULONG pIndex,
  151. PULONG pEntries,
  152. PPDNAMEA pPdName,
  153. PULONG pByteCount )
  154. {
  155. WDNAMEW WdNameW;
  156. PPDNAMEW pBuffer = NULL, pPdNameW;
  157. LONG Status;
  158. ULONG Count, ByteCountW = (*pByteCount << 1);
  159. /*
  160. * If the caller supplied a buffer and the length is not 0,
  161. * allocate a corresponding (*2) buffer for UNICODE strings.
  162. */
  163. if ( pPdName && ByteCountW ) {
  164. if ( !(pBuffer = LocalAlloc(0, ByteCountW)) )
  165. return ( ERROR_NOT_ENOUGH_MEMORY );
  166. }
  167. /*
  168. * Convert ANSI WdName to UNICODE.
  169. */
  170. AnsiToUnicode( WdNameW, sizeof(WDNAMEW), pWdName );
  171. /*
  172. * Enumerate Pds
  173. */
  174. pPdNameW = pBuffer;
  175. Status = RegPdEnumerateW( hServer,
  176. WdNameW,
  177. bTd,
  178. pIndex,
  179. pEntries,
  180. pPdNameW,
  181. &ByteCountW );
  182. /*
  183. * Always /2 the resultant ByteCount (whether sucessful or not).
  184. */
  185. *pByteCount = (ByteCountW >> 1);
  186. /*
  187. * If the function completed sucessfully and caller
  188. * (and stub) defined a buffer to copy into, perform conversion
  189. * from UNICODE to ANSI. Note: sucessful return may have copied
  190. * 0 items from registry (end of enumeration), denoted by *pEntries
  191. * == 0.
  192. */
  193. if ( ((Status == ERROR_SUCCESS) || (Status == ERROR_NO_MORE_ITEMS))
  194. && pPdNameW && pPdName ) {
  195. for ( Count = *pEntries; Count; Count-- ) {
  196. UnicodeToAnsi( pPdName, sizeof(PDNAMEA), pPdNameW );
  197. (char*)pPdName += sizeof(PDNAMEA);
  198. (char*)pPdNameW += sizeof(PDNAMEW);
  199. }
  200. }
  201. /*
  202. * If we defined a buffer, free it now, then return the status
  203. * of the Reg...EnumerateW function call.
  204. */
  205. if ( pBuffer )
  206. LocalFree(pBuffer);
  207. return ( Status );
  208. }
  209. /*******************************************************************************
  210. *
  211. * RegPdEnumerateW (UNICODE)
  212. *
  213. * Returns a list of configured Pds in the registry.
  214. *
  215. * ENTRY:
  216. *
  217. * hServer (input)
  218. * Handle to WinFrame Server
  219. * pWdName (input)
  220. * Points to the wdname to enumerate pds for
  221. * bTd (input)
  222. * TRUE to enumerate Transport Drivers (Tds),
  223. * FALSE to enumerate Protocol Drivers (Pds)
  224. * pIndex (input/output)
  225. * Specifies the subkey index for the \Citrix\Wds\<wdname>\<Pd or Td>
  226. * subkeys in the registry. Should be set to 0 for the initial call,
  227. * and supplied again (as modified by this function) for multi-call
  228. * enumeration.
  229. * pEntries (input/output)
  230. * Points to a variable specifying the number of entries requested.
  231. * If the number requested is 0xFFFFFFFF, the function returns as
  232. * many entries as possible. When the function finishes successfully,
  233. * the variable pointed to by the pEntries parameter contains the
  234. * number of entries actually read.
  235. * pPdName (input)
  236. * Points to the buffer to receive the enumeration results, which are
  237. * returned as an array of PDNAME structures. If this parameter is
  238. * NULL, then no data will be copied, but just an enumeration count will
  239. * be made.
  240. * pByteCount (input/output)
  241. * Points to a variable that specifies the size, in bytes, of the
  242. * pPdName parameter. If the buffer is too small to receive even
  243. * one entry, the function returns an error code (ERROR_OUTOFMEMORY)
  244. * and this variable receives the required size of the buffer for a
  245. * single subkey. When the function finishes sucessfully, the variable
  246. * pointed to by the pByteCount parameter contains the number of bytes
  247. * actually stored in pPdName.
  248. *
  249. * EXIT:
  250. *
  251. * "No Error" codes:
  252. * ERROR_SUCCESS - The enumeration completed as requested and there
  253. * are more Pds subkeys (PDNAMEs) to be read.
  254. * ERROR_NO_MORE_ITEMS - The enumeration completed as requested and there
  255. * are no more Pds subkeys (PDNAMEs) to be read.
  256. *
  257. * "Error" codes:
  258. * ERROR_OUTOFMEMORY - The pPdName buffer is too small for even one entry.
  259. * ERROR_CANTOPEN - The \Citrix\Wds\<wdname>\<Pd or Td> key can't be opened.
  260. *
  261. ******************************************************************************/
  262. LONG WINAPI
  263. RegPdEnumerateW( HANDLE hServer,
  264. PWDNAMEW pWdName,
  265. BOOLEAN bTd,
  266. PULONG pIndex,
  267. PULONG pEntries,
  268. PPDNAMEW pPdName,
  269. PULONG pByteCount )
  270. {
  271. LONG Status;
  272. HKEY Handle;
  273. ULONG Count;
  274. ULONG i;
  275. HKEY hkey_local_machine;
  276. WCHAR KeyString[256];
  277. if( hServer == NULL )
  278. hkey_local_machine = HKEY_LOCAL_MACHINE;
  279. else
  280. hkey_local_machine = hServer;
  281. /*
  282. * Get the number of names to return
  283. */
  284. Count = pPdName ?
  285. min( *pByteCount / sizeof(PDNAME), *pEntries ) :
  286. (ULONG) -1;
  287. *pEntries = *pByteCount = 0;
  288. /*
  289. * Make sure buffer is big enough for at least one name
  290. */
  291. if ( Count == 0 ) {
  292. *pByteCount = sizeof(PDNAME);
  293. return( ERROR_OUTOFMEMORY );
  294. }
  295. /*
  296. * Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\<Pd or Td>)
  297. */
  298. wcscpy( KeyString, WD_REG_NAME );
  299. wcscat( KeyString, L"\\" );
  300. wcscat( KeyString, pWdName );
  301. wcscat( KeyString, bTd ? TD_REG_NAME : PD_REG_NAME );
  302. if ( RegOpenKeyEx( hkey_local_machine, KeyString, 0,
  303. KEY_ENUMERATE_SUB_KEYS, &Handle ) != ERROR_SUCCESS ) {
  304. return( ERROR_CANTOPEN );
  305. }
  306. /*
  307. * Get list of Tds or Pds
  308. */
  309. for ( i = 0; i < Count; i++ ) {
  310. PDNAME PdName;
  311. if ( (Status = RegEnumKey(Handle, *pIndex, PdName,
  312. sizeof(PDNAME)/sizeof(TCHAR) )) != ERROR_SUCCESS )
  313. break;
  314. /*
  315. * If caller supplied a buffer, then copy the PdName
  316. * and increment the pointer and byte count. Always increment the
  317. * entry count and index for the next iteration.
  318. */
  319. if ( pPdName ) {
  320. wcscpy( pPdName, PdName );
  321. (char*)pPdName += sizeof(PDNAME);
  322. *pByteCount += sizeof(PDNAME);
  323. }
  324. (*pEntries)++;
  325. (*pIndex)++;
  326. }
  327. /*
  328. * Close registry
  329. */
  330. RegCloseKey( Handle );
  331. return( Status );
  332. }
  333. /*******************************************************************************
  334. *
  335. * RegPdCreateA (ANSI stub)
  336. *
  337. * Creates a new Pd in the registry or updates an existing entry.
  338. * (See RegPdCreateW)
  339. *
  340. * ENTRY:
  341. *
  342. * see RegPdCreateW
  343. *
  344. * EXIT:
  345. *
  346. * see RegPdCreateW
  347. *
  348. ******************************************************************************/
  349. LONG WINAPI
  350. RegPdCreateA( HANDLE hServer,
  351. PWDNAMEA pWdName,
  352. BOOLEAN bTd,
  353. PPDNAMEA pPdName,
  354. BOOLEAN bCreate,
  355. PPDCONFIG3A pPdConfig,
  356. ULONG PdConfigLength )
  357. {
  358. PDNAMEW PdNameW;
  359. WDNAMEW WdNameW;
  360. PDCONFIG3W PdConfig3W;
  361. /*
  362. * Validate target buffer size.
  363. */
  364. if ( PdConfigLength < sizeof(PDCONFIG3A) )
  365. return( ERROR_INSUFFICIENT_BUFFER );
  366. /*
  367. * Convert ANSI WdName and PdName to UNICODE.
  368. */
  369. AnsiToUnicode( WdNameW, sizeof(WDNAMEW), pWdName );
  370. AnsiToUnicode( PdNameW, sizeof(PDNAMEW), pPdName );
  371. /*
  372. * Copy PDCONFIG3A elements to PDCONFIG3W elements.
  373. */
  374. PdConfig3A2U( &PdConfig3W, pPdConfig );
  375. /*
  376. * Call RegPdCreateW & return it's status.
  377. */
  378. return ( RegPdCreateW( hServer,
  379. WdNameW,
  380. bTd,
  381. PdNameW,
  382. bCreate,
  383. &PdConfig3W,
  384. sizeof(PdConfig3W)) );
  385. }
  386. /*******************************************************************************
  387. *
  388. * RegPdCreateW (UNICODE)
  389. *
  390. * Creates a new Pd in the registry or updates an existing entry. The
  391. * state of the bCreate flag determines whether this function will expect
  392. * to create a new Pd entry (bCreate == TRUE) or expects to update an
  393. * existing entry (bCreate == FALSE).
  394. *
  395. * ENTRY:
  396. * hServer (input)
  397. * Handle to WinFrame Server
  398. * pWdName (input)
  399. * Points to the wdname to create pd for
  400. * bTd (input)
  401. * TRUE to create a Transport Driver (Td),
  402. * FALSE to create a Protocol Driver (Pd)
  403. * pPdName (input)
  404. * Name of a new or exisiting Pd in the registry.
  405. * bCreate (input)
  406. * TRUE if this is a creation of a new Pd
  407. * FALSE if this is an update to an existing Pd
  408. * pPdConfig (input)
  409. * Pointer to a PDCONFIG3 structure containing configuration
  410. * information for the specified Pd name.
  411. * PdConfigLength (input)
  412. * Specifies the length in bytes of the pPdConfig buffer.
  413. *
  414. * EXIT:
  415. * ERROR_SUCCESS - no error
  416. *
  417. * ERROR_INSUFFICIENT_BUFFER - pPdConfig buffer too small
  418. * ERROR_FILE_NOT_FOUND - can't open ...\Citrix\Wds\<wdname>\<Pd or Td> key
  419. * ERROR_CANNOT_MAKE - can't create Pd key (registry problem)
  420. * ERROR_ALREADY_EXISTS - create; but Pd key was already present
  421. * ERROR_CANTOPEN - update; but Pd key could not be opened
  422. *
  423. ******************************************************************************/
  424. LONG WINAPI
  425. RegPdCreateW( HANDLE hServer,
  426. PWDNAMEW pWdName,
  427. BOOLEAN bTd,
  428. PPDNAMEW pPdName,
  429. BOOLEAN bCreate,
  430. PPDCONFIG3W pPdConfig,
  431. ULONG PdConfigLength )
  432. {
  433. HKEY Handle;
  434. HKEY Handle1;
  435. DWORD Disp;
  436. HKEY hkey_local_machine;
  437. WCHAR KeyString[256];
  438. if( hServer == NULL )
  439. hkey_local_machine = HKEY_LOCAL_MACHINE;
  440. else
  441. hkey_local_machine = hServer;
  442. /*
  443. * Validate length of buffer
  444. */
  445. if ( PdConfigLength < sizeof(PDCONFIG3) )
  446. return( ERROR_INSUFFICIENT_BUFFER );
  447. /*
  448. * Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\<Pd or Td>)
  449. */
  450. wcscpy( KeyString, WD_REG_NAME );
  451. wcscat( KeyString, L"\\" );
  452. wcscat( KeyString, pWdName );
  453. wcscat( KeyString, bTd ? TD_REG_NAME : PD_REG_NAME );
  454. if ( RegOpenKeyEx( hkey_local_machine, KeyString, 0,
  455. KEY_ALL_ACCESS, &Handle1 ) != ERROR_SUCCESS ) {
  456. return( ERROR_FILE_NOT_FOUND );
  457. }
  458. if ( bCreate ) {
  459. /*
  460. * Create requested: create a registry key for the specified
  461. * Pd name.
  462. */
  463. if ( RegCreateKeyEx( Handle1, pPdName, 0, NULL,
  464. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  465. NULL, &Handle, &Disp ) != ERROR_SUCCESS ) {
  466. RegCloseKey( Handle1 );
  467. return( ERROR_CANNOT_MAKE );
  468. }
  469. /*
  470. * If an existing key was returned instead of a new one being
  471. * created, return error (don't update).
  472. */
  473. if ( Disp != REG_CREATED_NEW_KEY ) {
  474. RegCloseKey( Handle1 );
  475. RegCloseKey( Handle );
  476. return( ERROR_ALREADY_EXISTS );
  477. }
  478. } else {
  479. /*
  480. * Update requested: open the registry key for the specified
  481. * Pd name.
  482. */
  483. if ( RegOpenKeyEx( Handle1, pPdName, 0, KEY_ALL_ACCESS,
  484. &Handle ) != ERROR_SUCCESS ) {
  485. RegCloseKey( Handle1 );
  486. return( ERROR_CANTOPEN );
  487. }
  488. }
  489. RegCloseKey( Handle1 );
  490. /*
  491. * Save Pd information
  492. */
  493. CreatePdConfig3( Handle, pPdConfig, 0 );
  494. /*
  495. * Close registry handle
  496. */
  497. RegCloseKey( Handle );
  498. return( ERROR_SUCCESS );
  499. }
  500. /*******************************************************************************
  501. *
  502. * RegPdQueryA (ANSI stub)
  503. *
  504. * Query configuration information of a Pd in the registry.
  505. *
  506. * ENTRY:
  507. *
  508. * see RegPdQueryW
  509. *
  510. * EXIT:
  511. *
  512. * see RegPdQueryW
  513. *
  514. ******************************************************************************/
  515. LONG WINAPI
  516. RegPdQueryA( HANDLE hServer,
  517. PWDNAMEA pWdName,
  518. BOOLEAN bTd,
  519. PPDNAMEA pPdName,
  520. PPDCONFIG3A pPdConfig,
  521. ULONG PdConfigLength,
  522. PULONG pReturnLength )
  523. {
  524. PDNAMEW PdNameW;
  525. WDNAMEW WdNameW;
  526. PDCONFIG3W PdConfig3W;
  527. LONG Status;
  528. ULONG ReturnLengthW;
  529. /*
  530. * Validate length and zero-initialize the destination
  531. * PDCONFIG3A structure.
  532. */
  533. if ( PdConfigLength < sizeof(PDCONFIG3A) )
  534. return( ERROR_INSUFFICIENT_BUFFER );
  535. memset(pPdConfig, 0, PdConfigLength);
  536. /*
  537. * Convert ANSI WdName and PdName to UNICODE.
  538. */
  539. AnsiToUnicode(WdNameW, sizeof(WDNAMEW), pWdName);
  540. AnsiToUnicode(PdNameW, sizeof(PDNAMEW), pPdName);
  541. /*
  542. * Query Pd.
  543. */
  544. if ( (Status = RegPdQueryW( hServer,
  545. WdNameW,
  546. bTd,
  547. PdNameW,
  548. &PdConfig3W,
  549. sizeof(PDCONFIG3W),
  550. &ReturnLengthW)) != ERROR_SUCCESS )
  551. return ( Status );
  552. /*
  553. * Copy PDCONFIG3W elements to PDCONFIG3A elements.
  554. */
  555. PdConfig3U2A( pPdConfig, &PdConfig3W );
  556. *pReturnLength = sizeof(PDCONFIG3A);
  557. return( ERROR_SUCCESS );
  558. }
  559. /*******************************************************************************
  560. *
  561. * RegPdQueryW (UNICODE)
  562. *
  563. * Query configuration information of a Pd in the registry.
  564. *
  565. * ENTRY:
  566. * hServer (input)
  567. * Handle to WinFrame Server
  568. * pWdName (input)
  569. * Points to the wdname to query pd for
  570. * bTd (input)
  571. * TRUE to query a Transport Driver (Td),
  572. * FALSE to query a Protocol Driver (Pd)
  573. * pPdName (input)
  574. * Name of an exisiting Pd in the registry.
  575. * pPdConfig (input)
  576. * Pointer to a PDCONFIG3 structure that will receive
  577. * information about the specified Pd name.
  578. * PdConfigLength (input)
  579. * Specifies the length in bytes of the pPdConfig buffer.
  580. * pReturnLength (output)
  581. * Receives the number of bytes placed in the pPdConfig buffer.
  582. *
  583. * EXIT:
  584. * ERROR_SUCCESS - no error
  585. *
  586. ******************************************************************************/
  587. LONG WINAPI
  588. RegPdQueryW( HANDLE hServer,
  589. PWDNAMEW pWdName,
  590. BOOLEAN bTd,
  591. PPDNAMEW pPdName,
  592. PPDCONFIG3W pPdConfig,
  593. ULONG PdConfigLength,
  594. PULONG pReturnLength )
  595. {
  596. HKEY Handle;
  597. HKEY Handle1;
  598. HKEY hkey_local_machine;
  599. WCHAR KeyString[256];
  600. if( hServer == NULL )
  601. hkey_local_machine = HKEY_LOCAL_MACHINE;
  602. else
  603. hkey_local_machine = hServer;
  604. /*
  605. * Validate length and zero-initialize the destination
  606. * PDCONFIG3A structure.
  607. */
  608. if ( PdConfigLength < sizeof(PDCONFIG3) )
  609. return( ERROR_INSUFFICIENT_BUFFER );
  610. memset(pPdConfig, 0, PdConfigLength);
  611. /*
  612. * Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\<Pd or Td>)
  613. */
  614. wcscpy( KeyString, WD_REG_NAME );
  615. wcscat( KeyString, L"\\" );
  616. wcscat( KeyString, pWdName );
  617. wcscat( KeyString, bTd ? TD_REG_NAME : PD_REG_NAME );
  618. if ( RegOpenKeyEx( hkey_local_machine, KeyString, 0,
  619. KEY_READ, &Handle1 ) != ERROR_SUCCESS ) {
  620. return( ERROR_FILE_NOT_FOUND );
  621. }
  622. /*
  623. * Now try to open the specified Pd
  624. */
  625. if ( RegOpenKeyEx( Handle1, pPdName, 0,
  626. KEY_READ, &Handle ) != ERROR_SUCCESS ) {
  627. RegCloseKey( Handle1 );
  628. return( ERROR_FILE_NOT_FOUND );
  629. }
  630. RegCloseKey( Handle1 );
  631. /*
  632. * Query PDCONFIG3 Structure
  633. */
  634. QueryPdConfig3( Handle, pPdConfig, 0 );
  635. /*
  636. * Close registry
  637. */
  638. RegCloseKey( Handle );
  639. *pReturnLength = sizeof(PDCONFIG3);
  640. return( ERROR_SUCCESS );
  641. }
  642. /*******************************************************************************
  643. *
  644. * RegPdDeleteA (ANSI stub)
  645. *
  646. * Deletes a Pd from the registry.
  647. *
  648. * ENTRY:
  649. *
  650. * see RegPdDeleteW
  651. *
  652. * EXIT:
  653. *
  654. * see RegPdDeleteW
  655. *
  656. ******************************************************************************/
  657. LONG WINAPI
  658. RegPdDeleteA( HANDLE hServer,
  659. PWDNAMEA pWdName,
  660. BOOLEAN bTd,
  661. PPDNAMEA pPdName )
  662. {
  663. WDNAMEW WdNameW;
  664. PDNAMEW PdNameW;
  665. AnsiToUnicode( WdNameW, sizeof(WdNameW), pWdName );
  666. AnsiToUnicode( PdNameW, sizeof(PdNameW), pPdName );
  667. return ( RegPdDeleteW ( hServer, WdNameW, bTd, PdNameW ) );
  668. }
  669. /*******************************************************************************
  670. *
  671. * RegPdDeleteW (UNICODE)
  672. *
  673. * Deletes a Pd from the registry.
  674. *
  675. * ENTRY:
  676. * hServer (input)
  677. * Handle to WinFrame Server
  678. * pWdName (input)
  679. * Points to the wdname to delete pd from
  680. * bTd (input)
  681. * TRUE to delete a Transport Driver (Td),
  682. * FALSE to delete a Protocol Driver (Pd)
  683. * pPdName (input)
  684. * Name of a Pd to delete from the registry.
  685. *
  686. * EXIT:
  687. * ERROR_SUCCESS - no error
  688. *
  689. ******************************************************************************/
  690. LONG WINAPI
  691. RegPdDeleteW( HANDLE hServer,
  692. PWDNAMEW pWdName,
  693. BOOLEAN bTd,
  694. PPDNAMEW pPdName )
  695. {
  696. LONG Status;
  697. HKEY Handle;
  698. HKEY Handle1;
  699. HKEY hkey_local_machine;
  700. WCHAR KeyString[256];
  701. if( hServer == NULL )
  702. hkey_local_machine = HKEY_LOCAL_MACHINE;
  703. else
  704. hkey_local_machine = hServer;
  705. /*
  706. * Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\<Pd or Td>)
  707. */
  708. wcscpy( KeyString, WD_REG_NAME );
  709. wcscat( KeyString, L"\\" );
  710. wcscat( KeyString, pWdName );
  711. wcscat( KeyString, bTd ? TD_REG_NAME : PD_REG_NAME );
  712. if ( RegOpenKeyEx( hkey_local_machine, KeyString, 0,
  713. KEY_READ, &Handle ) != ERROR_SUCCESS ) {
  714. return( ERROR_FILE_NOT_FOUND );
  715. }
  716. /*
  717. * Now try to open the specified Pd
  718. */
  719. if ( RegOpenKeyEx( Handle, pPdName, 0,
  720. KEY_READ, &Handle1 ) != ERROR_SUCCESS ) {
  721. RegCloseKey( Handle );
  722. return( ERROR_FILE_NOT_FOUND );
  723. }
  724. /*
  725. * Close the Pd key handle, delete the Pd,
  726. * and close the parent handle.
  727. */
  728. RegCloseKey( Handle1 );
  729. Status = RegDeleteKey( Handle, pPdName );
  730. RegCloseKey( Handle );
  731. return( Status );
  732. }