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.

629 lines
18 KiB

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