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.

675 lines
19 KiB

  1. /*************************************************************************
  2. *
  3. * regcd.c
  4. *
  5. * Register APIs for CDs (connection drivers)
  6. *
  7. * Copyright (c) 1998 Microsoft Corporation
  8. *
  9. *
  10. *************************************************************************/
  11. /*
  12. * Includes
  13. */
  14. #include <windows.h>
  15. /* Added By SalimC */
  16. #include <ksguid.h>
  17. /**/
  18. #include <ntddkbd.h>
  19. #include <ntddmou.h>
  20. #include <winstaw.h>
  21. #include <regapi.h>
  22. /*
  23. * External Procedures defined here
  24. */
  25. LONG WINAPI RegCdEnumerateA( HANDLE, PWDNAMEA, PULONG, PULONG, PCDNAMEA, PULONG );
  26. LONG WINAPI RegCdEnumerateW( HANDLE, PWDNAMEW, PULONG, PULONG, PCDNAMEW, PULONG );
  27. LONG WINAPI RegCdCreateA( HANDLE, PWDNAMEA, PCDNAMEA, BOOLEAN, PCDCONFIGA, ULONG );
  28. LONG WINAPI RegCdCreateW( HANDLE, PWDNAMEW, PCDNAMEW, BOOLEAN, PCDCONFIGW, ULONG );
  29. LONG WINAPI RegCdQueryA( HANDLE, PWDNAMEA, PCDNAMEA, PCDCONFIGA, ULONG, PULONG );
  30. LONG WINAPI RegCdQueryW( HANDLE, PWDNAMEW, PCDNAMEW, PCDCONFIGW, ULONG, PULONG );
  31. LONG WINAPI RegCdDeleteA( HANDLE, PWDNAMEA, PCDNAMEA );
  32. LONG WINAPI RegCdDeleteW( HANDLE, PWDNAMEW, PCDNAMEW );
  33. /*
  34. * other internal Procedures used (not defined here)
  35. */
  36. VOID CreateCd( HKEY, PCDCONFIG );
  37. VOID QueryCd( HKEY, PCDCONFIG );
  38. VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
  39. VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
  40. VOID CdConfigU2A( PCDCONFIGA, PCDCONFIGW );
  41. VOID CdConfigA2U( PCDCONFIGW, PCDCONFIGA );
  42. /*******************************************************************************
  43. *
  44. * RegCdEnumerateA (ANSI stub)
  45. *
  46. * Returns a list of configured connection drivers in the registry.
  47. *
  48. * ENTRY:
  49. *
  50. * see RegCdEnumerateW
  51. *
  52. * EXIT:
  53. *
  54. * see RegCdEnumerateW, plus
  55. *
  56. * ERROR_NOT_ENOUGH_MEMORY - the LocalAlloc failed
  57. *
  58. ******************************************************************************/
  59. LONG WINAPI
  60. RegCdEnumerateA( HANDLE hServer,
  61. PWDNAMEA pWdName,
  62. PULONG pIndex,
  63. PULONG pEntries,
  64. PCDNAMEA pCdName,
  65. PULONG pByteCount )
  66. {
  67. PCDNAMEW pBuffer = NULL, pCdNameW;
  68. WDNAMEW WdNameW;
  69. LONG Status;
  70. ULONG Count, ByteCountW = (*pByteCount << 1);
  71. /*
  72. * If the caller supplied a buffer and the length is not 0,
  73. * allocate a corresponding (*2) buffer for UNICODE strings.
  74. */
  75. if ( pCdName && ByteCountW ) {
  76. if ( !(pBuffer = LocalAlloc(0, ByteCountW)) )
  77. return ( ERROR_NOT_ENOUGH_MEMORY );
  78. }
  79. /*
  80. * Convert ANSI WdName to UNICODE.
  81. */
  82. AnsiToUnicode( WdNameW, sizeof(WDNAMEW), pWdName );
  83. /*
  84. * Enumerate connection drivers
  85. */
  86. pCdNameW = pBuffer;
  87. Status = RegCdEnumerateW( hServer,
  88. WdNameW,
  89. pIndex,
  90. pEntries,
  91. pCdNameW,
  92. &ByteCountW );
  93. /*
  94. * Always /2 the resultant ByteCount (whether sucessful or not).
  95. */
  96. *pByteCount = (ByteCountW >> 1);
  97. /*
  98. * If the function completed sucessfully and caller
  99. * (and stub) defined a buffer to copy into, perform conversion
  100. * from UNICODE to ANSI. Note: sucessful return may have copied
  101. * 0 items from registry (end of enumeration), denoted by *pEntries
  102. * == 0.
  103. */
  104. if ( ((Status == ERROR_SUCCESS) || (Status == ERROR_NO_MORE_ITEMS))
  105. && pCdNameW && pCdName ) {
  106. for ( Count = *pEntries; Count; Count-- ) {
  107. UnicodeToAnsi( pCdName, sizeof(CDNAMEA), pCdNameW );
  108. (char*)pCdName += sizeof(CDNAMEA);
  109. (char*)pCdNameW += sizeof(CDNAMEW);
  110. }
  111. }
  112. /*
  113. * If we defined a buffer, free it now, then return the status
  114. * of the Reg...EnumerateW function call.
  115. */
  116. if ( pBuffer )
  117. LocalFree(pBuffer);
  118. return ( Status );
  119. }
  120. /*******************************************************************************
  121. *
  122. * RegCdEnumerateW (UNICODE)
  123. *
  124. * Returns a list of configured connection drivers in the registry.
  125. *
  126. * ENTRY:
  127. *
  128. * hServer (input)
  129. * Handle to WinFrame Server
  130. * pWdName (input)
  131. * Points to the wdname to enumerate Cds for
  132. * pIndex (input/output)
  133. * Specifies the subkey index for the \Citrix\Wds\<wdname>\Cds subkeys
  134. * in the registry. Should be set to 0 for the initial call, and
  135. * supplied again (as modified by this function) for multi-call
  136. * enumeration.
  137. * pEntries (input/output)
  138. * Points to a variable specifying the number of entries requested.
  139. * If the number requested is 0xFFFFFFFF, the function returns as
  140. * many entries as possible. When the function finishes successfully,
  141. * the variable pointed to by the pEntries parameter contains the
  142. * number of entries actually read.
  143. * pCdName (input)
  144. * Points to the buffer to receive the enumeration results, which are
  145. * returned as an array of CDNAMEW structures. If this parameter is
  146. * NULL, then no data will be copied, but just an enumeration count will
  147. * be made.
  148. * pByteCount (input/output)
  149. * Points to a variable that specifies the size, in bytes, of the
  150. * pCdName parameter. If the buffer is too small to receive even
  151. * one entry, the function returns an error code (ERROR_OUTOFMEMORY)
  152. * and this variable receives the required size of the buffer for a
  153. * single subkey. When the function finishes sucessfully, the variable
  154. * pointed to by the pByteCount parameter contains the number of bytes
  155. * actually stored in pCdName.
  156. *
  157. * EXIT:
  158. *
  159. * "No Error" codes:
  160. * ERROR_SUCCESS - The enumeration completed as requested and there
  161. * are more CDS subkeys (CDNAMEs) to be
  162. * read.
  163. * ERROR_NO_MORE_ITEMS - The enumeration completed as requested and there
  164. * are no more CDS subkeys (CDNAMEs) to
  165. * be read.
  166. *
  167. * "Error" codes:
  168. * ERROR_OUTOFMEMORY - The pCdName buffer is too small for even one
  169. * entry.
  170. * ERROR_CANTOPEN - The Citrix\Cds key can't be opened.
  171. *
  172. ******************************************************************************/
  173. LONG WINAPI
  174. RegCdEnumerateW( HANDLE hServer,
  175. PWDNAMEW pWdName,
  176. PULONG pIndex,
  177. PULONG pEntries,
  178. PCDNAMEW pCdName,
  179. PULONG pByteCount )
  180. {
  181. LONG Status;
  182. HKEY Handle;
  183. ULONG Count;
  184. ULONG i;
  185. WCHAR KeyString[256];
  186. /*
  187. * Get the number of names to return
  188. */
  189. Count = pCdName ?
  190. min( *pByteCount / sizeof(CDNAME), *pEntries ) :
  191. (ULONG) -1;
  192. *pEntries = *pByteCount = 0;
  193. /*
  194. * Make sure buffer is big enough for at least one name
  195. */
  196. if ( Count == 0 ) {
  197. *pByteCount = sizeof(CDNAME);
  198. return( ERROR_OUTOFMEMORY );
  199. }
  200. /*
  201. * Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\Cds)
  202. */
  203. wcscpy( KeyString, WD_REG_NAME );
  204. wcscat( KeyString, L"\\" );
  205. wcscat( KeyString, pWdName );
  206. wcscat( KeyString, CD_REG_NAME );
  207. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, KeyString, 0,
  208. KEY_ENUMERATE_SUB_KEYS, &Handle ) != ERROR_SUCCESS ) {
  209. return( ERROR_CANTOPEN );
  210. }
  211. /*
  212. * Get list of connection drivers
  213. */
  214. for ( i = 0; i < Count; i++ ) {
  215. CDNAME CdName;
  216. if ( (Status = RegEnumKey(Handle, *pIndex, CdName,
  217. sizeof(CDNAME)/sizeof(TCHAR) )) != ERROR_SUCCESS )
  218. break;
  219. /*
  220. * If caller supplied a buffer, then copy the CdName
  221. * and increment the pointer and byte count. Always increment the
  222. * entry count and index for the next iteration.
  223. */
  224. if ( pCdName ) {
  225. wcscpy( pCdName, CdName );
  226. (char*)pCdName += sizeof(CDNAME);
  227. *pByteCount += sizeof(CDNAME);
  228. }
  229. (*pEntries)++;
  230. (*pIndex)++;
  231. }
  232. /*
  233. * Close registry
  234. */
  235. RegCloseKey( Handle );
  236. return( Status );
  237. }
  238. /*******************************************************************************
  239. *
  240. * RegCdCreateA (ANSI stub)
  241. *
  242. * Creates a new Cd in the registry or updates an existing entry.
  243. * (See RegCdCreateW)
  244. *
  245. * ENTRY:
  246. * see RegCdCreateW
  247. * EXIT:
  248. * see RegCdCreateW
  249. *
  250. ******************************************************************************/
  251. LONG WINAPI
  252. RegCdCreateA( HANDLE hServer,
  253. PWDNAMEA pWdName,
  254. PCDNAMEA pCdName,
  255. BOOLEAN bCreate,
  256. PCDCONFIGA pCdConfig,
  257. ULONG CdConfigLength )
  258. {
  259. WDNAMEW WdNameW;
  260. CDNAMEW CdNameW;
  261. CDCONFIGW CdConfigW;
  262. /*
  263. * Validate target buffer size.
  264. */
  265. if ( CdConfigLength < sizeof(CDCONFIGA) )
  266. return( ERROR_INSUFFICIENT_BUFFER );
  267. /*
  268. * Convert ANSI WdName and CdName to UNICODE.
  269. */
  270. AnsiToUnicode( WdNameW, sizeof(WDNAMEW), pWdName );
  271. AnsiToUnicode( CdNameW, sizeof(CDNAMEW), pCdName );
  272. /*
  273. * Copy CDCONFIGA elements to CDCONFIGW elements.
  274. */
  275. CdConfigA2U( &CdConfigW, pCdConfig );
  276. /*
  277. * Call RegCdCreateW & return it's status.
  278. */
  279. return ( RegCdCreateW( hServer,
  280. WdNameW,
  281. CdNameW,
  282. bCreate,
  283. &CdConfigW,
  284. sizeof(CdConfigW)) );
  285. }
  286. /*******************************************************************************
  287. *
  288. * RegCdCreateW (UNICODE)
  289. *
  290. * Creates a new Cd in the registry or updates an existing entry. The
  291. * state of the bCreate flag determines whether this function will expect
  292. * to create a new Cd entry (bCreate == TRUE) or expects to update an
  293. * existing entry (bCreate == FALSE).
  294. *
  295. * ENTRY:
  296. * hServer (input)
  297. * Handle to WinFrame Server
  298. * pWdName (input)
  299. * Points to the wdname to create Cd for
  300. * pCdName (input)
  301. * Name of a new or exisiting connection driver in the registry.
  302. * bCreate (input)
  303. * TRUE if this is a creation of a new Cd
  304. * FALSE if this is an update to an existing Cd
  305. * pCdConfig (input)
  306. * Pointer to a CDCONFIGW structure containing configuration
  307. * information for the specified connection driver name.
  308. * CdConfigLength (input)
  309. * Specifies the length in bytes of the pCdConfig buffer.
  310. * EXIT:
  311. * ERROR_SUCCESS - no error
  312. *
  313. * ERROR_INSUFFICIENT_BUFFER - pCdConfig buffer too small
  314. * ERROR_FILE_NOT_FOUND - can't open ...\Citrix\Wds\<wdname>\Cds key
  315. * ERROR_CANNOT_MAKE - can't create Cd key (registry problem)
  316. * ERROR_ALREADY_EXISTS - create; but Cd key already present
  317. * ERROR_CANTOPEN - update; but Cd key could not be opened
  318. *
  319. ******************************************************************************/
  320. LONG WINAPI
  321. RegCdCreateW( HANDLE hServer,
  322. PWDNAMEW pWdName,
  323. PCDNAMEW pCdName,
  324. BOOLEAN bCreate,
  325. PCDCONFIGW pCdConfig,
  326. ULONG CdConfigLength )
  327. {
  328. HKEY Handle;
  329. HKEY Handle1;
  330. DWORD Disp;
  331. WCHAR KeyString[256];
  332. /*
  333. * Validate length of buffer
  334. */
  335. if ( CdConfigLength < sizeof(CDCONFIG) )
  336. return( ERROR_INSUFFICIENT_BUFFER );
  337. /*
  338. * Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\Cds)
  339. */
  340. wcscpy( KeyString, WD_REG_NAME );
  341. wcscat( KeyString, L"\\" );
  342. wcscat( KeyString, pWdName );
  343. wcscat( KeyString, CD_REG_NAME );
  344. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, KeyString, 0,
  345. KEY_ALL_ACCESS, &Handle1 ) != ERROR_SUCCESS ) {
  346. return( ERROR_FILE_NOT_FOUND );
  347. }
  348. if ( bCreate ) {
  349. /*
  350. * Create requested: create a registry key for the specified
  351. * Cd name.
  352. */
  353. if ( RegCreateKeyEx( Handle1, pCdName, 0, NULL,
  354. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  355. NULL, &Handle, &Disp ) != ERROR_SUCCESS ) {
  356. RegCloseKey( Handle1 );
  357. return( ERROR_CANNOT_MAKE );
  358. }
  359. /*
  360. * If an existing key was returned instead of a new one being
  361. * created, return error (don't update).
  362. */
  363. if ( Disp != REG_CREATED_NEW_KEY ) {
  364. RegCloseKey( Handle1 );
  365. RegCloseKey( Handle );
  366. return( ERROR_ALREADY_EXISTS );
  367. }
  368. } else {
  369. /*
  370. * Update requested: open the registry key for the specified
  371. * Cd name.
  372. */
  373. if ( RegOpenKeyEx( Handle1, pCdName, 0, KEY_ALL_ACCESS,
  374. &Handle ) != ERROR_SUCCESS ) {
  375. RegCloseKey( Handle1 );
  376. return( ERROR_CANTOPEN );
  377. }
  378. }
  379. RegCloseKey( Handle1 );
  380. /*
  381. * Save CDCONFIG Structure
  382. */
  383. CreateCd( Handle, pCdConfig );
  384. /*
  385. * Close registry handle
  386. */
  387. RegCloseKey( Handle );
  388. return( ERROR_SUCCESS );
  389. }
  390. /*******************************************************************************
  391. *
  392. * RegCdQueryA (ANSI stub)
  393. *
  394. * Query configuration information of a connection driver in the registry.
  395. *
  396. * ENTRY:
  397. * see RegCdQueryW
  398. * EXIT:
  399. * see RegCdQueryW
  400. *
  401. ******************************************************************************/
  402. LONG WINAPI
  403. RegCdQueryA( HANDLE hServer,
  404. PWDNAMEA pWdName,
  405. PCDNAMEA pCdName,
  406. PCDCONFIGA pCdConfig,
  407. ULONG CdConfigLength,
  408. PULONG pReturnLength )
  409. {
  410. WDNAMEW WdNameW;
  411. CDNAMEW CdNameW;
  412. CDCONFIGW CdConfigW;
  413. LONG Status;
  414. ULONG ReturnLengthW;
  415. /*
  416. * Validate length and zero-initialize the destination
  417. * PDCONFIG3A structure.
  418. */
  419. if ( CdConfigLength < sizeof(CDCONFIGA) )
  420. return( ERROR_INSUFFICIENT_BUFFER );
  421. memset(pCdConfig, 0, CdConfigLength);
  422. /*
  423. * Convert ANSI WdName and CdName to UNICODE.
  424. */
  425. AnsiToUnicode(WdNameW, sizeof(WDNAMEW), pWdName);
  426. AnsiToUnicode(CdNameW, sizeof(CDNAMEW), pCdName);
  427. /*
  428. * Query Cd.
  429. */
  430. if ( (Status = RegCdQueryW( hServer,
  431. WdNameW,
  432. CdNameW,
  433. &CdConfigW,
  434. sizeof(CDCONFIGW),
  435. &ReturnLengthW)) != ERROR_SUCCESS )
  436. return ( Status );
  437. /*
  438. * Copy CDCONFIGW elements to CDCONFIGA elements.
  439. */
  440. CdConfigU2A( pCdConfig, &CdConfigW );
  441. *pReturnLength = sizeof(CDCONFIGA);
  442. return( ERROR_SUCCESS );
  443. }
  444. /*******************************************************************************
  445. *
  446. * RegCdQueryW (UNICODE)
  447. *
  448. * Query configuration information of a connection driver in the registry.
  449. *
  450. * ENTRY:
  451. * hServer (input)
  452. * Handle to WinFrame Server
  453. * pWdName (input)
  454. * Points to the wdname to query Cd for
  455. * pCdName (input)
  456. * Name of an exisiting connection driver in the registry.
  457. * pCdConfig (input)
  458. * Pointer to a CDCONFIGW structure that will receive
  459. * information about the specified connection driver name.
  460. * CdConfigLength (input)
  461. * Specifies the length in bytes of the pCdConfig buffer.
  462. * pReturnLength (output)
  463. * Receives the number of bytes placed in the pCdConfig buffer.
  464. * EXIT:
  465. * ERROR_SUCCESS - no error
  466. *
  467. ******************************************************************************/
  468. LONG WINAPI
  469. RegCdQueryW( HANDLE hServer,
  470. PWDNAMEW pWdName,
  471. PCDNAMEW pCdName,
  472. PCDCONFIGW pCdConfig,
  473. ULONG CdConfigLength,
  474. PULONG pReturnLength )
  475. {
  476. HKEY Handle;
  477. HKEY Handle1;
  478. WCHAR KeyString[256];
  479. /*
  480. * Validate length and zero-initialize the destination
  481. * PDCONFIG3A structure.
  482. */
  483. if ( CdConfigLength < sizeof(CDCONFIG) )
  484. return( ERROR_INSUFFICIENT_BUFFER );
  485. memset(pCdConfig, 0, CdConfigLength);
  486. /*
  487. * Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\Cds)
  488. */
  489. wcscpy( KeyString, WD_REG_NAME );
  490. wcscat( KeyString, L"\\" );
  491. wcscat( KeyString, pWdName );
  492. wcscat( KeyString, CD_REG_NAME );
  493. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, KeyString, 0,
  494. KEY_READ, &Handle1 ) != ERROR_SUCCESS ) {
  495. return( ERROR_FILE_NOT_FOUND );
  496. }
  497. /*
  498. * Now try to open the specified Cd
  499. */
  500. if ( RegOpenKeyEx( Handle1, pCdName, 0,
  501. KEY_READ, &Handle ) != ERROR_SUCCESS ) {
  502. RegCloseKey( Handle1 );
  503. return( ERROR_FILE_NOT_FOUND );
  504. }
  505. RegCloseKey( Handle1 );
  506. /*
  507. * Query CDCONFIG Structure
  508. */
  509. QueryCd( Handle, pCdConfig );
  510. /*
  511. * Close registry
  512. */
  513. RegCloseKey( Handle );
  514. *pReturnLength = sizeof(CDCONFIG);
  515. return( ERROR_SUCCESS );
  516. }
  517. /*******************************************************************************
  518. *
  519. * RegCdDeleteA (ANSI stub)
  520. *
  521. * Deletes a connection driver from the registry.
  522. *
  523. * ENTRY:
  524. *
  525. * see RegCdDeleteW
  526. *
  527. * EXIT:
  528. *
  529. * see RegCdDeleteW
  530. *
  531. ******************************************************************************/
  532. LONG WINAPI
  533. RegCdDeleteA( HANDLE hServer,
  534. PWDNAMEA pWdName,
  535. PCDNAMEA pCdName )
  536. {
  537. WDNAMEW WdNameW;
  538. CDNAMEW CdNameW;
  539. AnsiToUnicode( WdNameW, sizeof(WdNameW), pWdName);
  540. AnsiToUnicode( CdNameW, sizeof(CdNameW), pCdName);
  541. return ( RegCdDeleteW ( hServer, WdNameW, CdNameW ) );
  542. }
  543. /*******************************************************************************
  544. *
  545. * RegCdDeleteW (UNICODE)
  546. *
  547. * Deletes a connection driver from the registry.
  548. *
  549. * ENTRY:
  550. * hServer (input)
  551. * Handle to WinFrame Server
  552. * pWdName (input)
  553. * Points to the wdname to delete Cd from
  554. * pCdName (input)
  555. * Name of a connection driver to delete from the registry.
  556. *
  557. * EXIT:
  558. * ERROR_SUCCESS - no error
  559. *
  560. ******************************************************************************/
  561. LONG WINAPI
  562. RegCdDeleteW( HANDLE hServer,
  563. PWDNAMEW pWdName,
  564. PCDNAMEW pCdName )
  565. {
  566. LONG Status;
  567. HKEY Handle;
  568. HKEY Handle1;
  569. WCHAR KeyString[256];
  570. /*
  571. * Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\Cds)
  572. */
  573. wcscpy( KeyString, WD_REG_NAME );
  574. wcscat( KeyString, L"\\" );
  575. wcscat( KeyString, pWdName );
  576. wcscat( KeyString, CD_REG_NAME );
  577. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, CD_REG_NAME, 0,
  578. KEY_READ, &Handle ) != ERROR_SUCCESS ) {
  579. return( ERROR_FILE_NOT_FOUND );
  580. }
  581. /*
  582. * Now try to open the specified Cd
  583. */
  584. if ( RegOpenKeyEx( Handle, pCdName, 0,
  585. KEY_READ, &Handle1 ) != ERROR_SUCCESS ) {
  586. RegCloseKey( Handle );
  587. return( ERROR_FILE_NOT_FOUND );
  588. }
  589. /*
  590. * Close the Cd key handle, delete the Cd,
  591. * and close the parent handle
  592. */
  593. RegCloseKey( Handle1 );
  594. Status = RegDeleteKey( Handle, pCdName );
  595. RegCloseKey( Handle );
  596. return( Status );
  597. }