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.

1680 lines
51 KiB

  1. /*************************************************************************
  2. *
  3. * regwin.c
  4. *
  5. * Register APIs for window stations
  6. *
  7. * Copyright (c) 1998 Microsoft Corporation
  8. *
  9. *
  10. *************************************************************************/
  11. /*
  12. * Includes
  13. */
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <windows.h>
  18. #include <ntddkbd.h>
  19. #include <ntddmou.h>
  20. #include <winstaw.h>
  21. #include <regapi.h>
  22. //
  23. extern HKEY g_hTSPolicyKey;//handle to TS_POLICY_SUB_TREE key
  24. extern HKEY g_hTSControlKey;//handle to REG_CONTROL_TSERVER key
  25. /*
  26. * External Procedures defined here
  27. */
  28. LONG WINAPI RegWinStationAccessCheck( HANDLE, REGSAM );
  29. LONG WINAPI RegWinStationEnumerateW( HANDLE, PULONG, PULONG, PWINSTATIONNAMEW, PULONG );
  30. LONG WINAPI RegWinStationEnumerateA( HANDLE, PULONG, PULONG, PWINSTATIONNAMEA, PULONG );
  31. LONG WINAPI RegWinStationCreateW( HANDLE, PWINSTATIONNAMEW, BOOLEAN,
  32. PWINSTATIONCONFIG2W, ULONG );
  33. LONG WINAPI RegWinStationCreateA( HANDLE, PWINSTATIONNAMEA, BOOLEAN,
  34. PWINSTATIONCONFIG2A, ULONG );
  35. LONG WINAPI RegWinStationQueryW( HANDLE, PWINSTATIONNAMEW, PWINSTATIONCONFIG2W,
  36. ULONG, PULONG );
  37. LONG WINAPI RegWinStationQueryA( HANDLE, PWINSTATIONNAMEA, PWINSTATIONCONFIG2A,
  38. ULONG, PULONG );
  39. LONG WINAPI RegWinStationDeleteW( HANDLE, PWINSTATIONNAMEW );
  40. LONG WINAPI RegWinStationDeleteA( HANDLE, PWINSTATIONNAMEA );
  41. LONG WINAPI RegWinStationSetSecurityW( HANDLE, PWINSTATIONNAMEW, PSECURITY_DESCRIPTOR,
  42. ULONG );
  43. LONG WINAPI RegWinStationSetSecurityA( HANDLE, PWINSTATIONNAMEA, PSECURITY_DESCRIPTOR,
  44. ULONG );
  45. LONG WINAPI RegWinStationQuerySecurityW( HANDLE, PWINSTATIONNAMEW, PSECURITY_DESCRIPTOR,
  46. ULONG, PULONG );
  47. LONG WINAPI RegWinStationQuerySecurityA( HANDLE, PWINSTATIONNAMEA, PSECURITY_DESCRIPTOR,
  48. ULONG, PULONG );
  49. LONG WINAPI RegWinStationQueryDefaultSecurity( HANDLE, PSECURITY_DESCRIPTOR,
  50. ULONG, PULONG );
  51. LONG WINAPI RegWinStationSetNumValueW( HANDLE, PWINSTATIONNAMEW, LPWSTR, ULONG );
  52. LONG WINAPI RegWinStationQueryNumValueW( HANDLE, PWINSTATIONNAMEW, LPWSTR, PULONG );
  53. LONG WINAPI
  54. RegConsoleShadowQueryA( HANDLE hServer,
  55. PWINSTATIONNAMEA pWinStationName,
  56. PWDPREFIXA pWdPrefixName,
  57. PWINSTATIONCONFIG2A pWinStationConfig,
  58. ULONG WinStationConfigLength,
  59. PULONG pReturnLength );
  60. LONG WINAPI
  61. RegConsoleShadowQueryW( HANDLE hServer,
  62. PWINSTATIONNAMEW pWinStationName,
  63. PWDPREFIXW pWdPrefixName,
  64. PWINSTATIONCONFIG2W pWinStationConfig,
  65. ULONG WinStationConfigLength,
  66. PULONG pReturnLength );
  67. /*
  68. * Private Procedures defined here
  69. */
  70. LONG _RegOpenWinStation( PWINSTATIONNAMEW, REGSAM, HKEY * );
  71. LONG _RegGetWinStationSecurity( HKEY, LPWSTR, PSECURITY_DESCRIPTOR, ULONG, PULONG );
  72. /*
  73. * other internal Procedures used (not defined here)
  74. */
  75. VOID CreateWinStaCreate( HKEY, PWINSTATIONCREATE );
  76. VOID CreateConfig( HKEY, PWINSTATIONCONFIG );
  77. VOID CreateWd( HKEY, PWDCONFIG );
  78. VOID CreateCd( HKEY, PCDCONFIG );
  79. VOID CreatePdConfig( BOOLEAN, HKEY, PPDCONFIG, ULONG );
  80. VOID QueryWinStaCreate( HKEY, PWINSTATIONCREATE );
  81. VOID QueryConfig( HKEY, PWINSTATIONCONFIG );
  82. VOID QueryWd( HKEY, PWDCONFIG );
  83. VOID QueryCd( HKEY, PCDCONFIG );
  84. VOID QueryPdConfig( HKEY, PPDCONFIG, PULONG );
  85. VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
  86. VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
  87. VOID PdConfigU2A( PPDCONFIGA, PPDCONFIGW );
  88. VOID PdConfigA2U( PPDCONFIGW, PPDCONFIGA );
  89. VOID WdConfigU2A( PWDCONFIGA, PWDCONFIGW );
  90. VOID WdConfigA2U( PWDCONFIGW, PWDCONFIGA );
  91. VOID CdConfigU2A( PCDCONFIGA, PCDCONFIGW );
  92. VOID CdConfigA2U( PCDCONFIGW, PCDCONFIGA );
  93. VOID WinStationCreateU2A( PWINSTATIONCREATEA, PWINSTATIONCREATEW );
  94. VOID WinStationCreateA2U( PWINSTATIONCREATEW, PWINSTATIONCREATEA );
  95. VOID WinStationConfigU2A( PWINSTATIONCONFIGA, PWINSTATIONCONFIGW );
  96. VOID WinStationConfigA2U( PWINSTATIONCONFIGW, PWINSTATIONCONFIGA );
  97. VOID SetWallPaperDisabled( HKEY, BOOLEAN );
  98. /****************************************************************************
  99. *
  100. * DllEntryPoint
  101. *
  102. * Function is called when the DLL is loaded and unloaded.
  103. *
  104. * ENTRY:
  105. * hinstDLL (input)
  106. * Handle of DLL module
  107. *
  108. * fdwReason (input)
  109. * Why function was called
  110. *
  111. * lpvReserved (input)
  112. * Reserved; must be NULL
  113. *
  114. * EXIT:
  115. * TRUE - Success
  116. * FALSE - Error occurred
  117. *
  118. ****************************************************************************/
  119. BOOL WINAPI
  120. DllEntryPoint( HINSTANCE hinstDLL,
  121. DWORD fdwReason,
  122. LPVOID lpvReserved )
  123. {
  124. switch ( fdwReason ) {
  125. case DLL_PROCESS_ATTACH:
  126. break;
  127. case DLL_PROCESS_DETACH:
  128. if( g_hTSPolicyKey )
  129. {
  130. RegCloseKey(g_hTSPolicyKey);
  131. }
  132. if( g_hTSControlKey )
  133. {
  134. RegCloseKey(g_hTSControlKey);
  135. }
  136. break;
  137. default:
  138. break;
  139. }
  140. return( TRUE );
  141. }
  142. /*******************************************************************************
  143. *
  144. * RegWinStationAccessCheck (ANSI or UNICODE)
  145. *
  146. * Determines if the current user has the requested access to the
  147. * WinStation registry.
  148. *
  149. * ENTRY:
  150. * hServer (input)
  151. * Handle to WinFrame Server
  152. * samDesired (input)
  153. * Specifies the security access mask to be used in determining access
  154. * to the WinStation registry.
  155. *
  156. * EXIT:
  157. * ERROR_SUCCESS if the user has the requested access
  158. * other error value (most likely ERROR_ACCESS_DENIED) if the user does
  159. * not have the requested access.
  160. *
  161. ******************************************************************************/
  162. LONG WINAPI
  163. RegWinStationAccessCheck( HANDLE hServer, REGSAM samDesired )
  164. {
  165. LONG Status;
  166. HKEY Handle;
  167. /*
  168. * Attempt to open the registry (LOCAL_MACHINE\....\Citrix\Pd)
  169. * at the requested access level.
  170. */
  171. if ( (Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,
  172. samDesired, &Handle )) == ERROR_SUCCESS )
  173. RegCloseKey( Handle );
  174. return( Status );
  175. }
  176. /*******************************************************************************
  177. *
  178. * RegWinStationEnumerateA (ANSI stub)
  179. *
  180. * Returns a list of configured WinStations in the registry.
  181. *
  182. * ENTRY:
  183. * see RegWinStationEnumerateW
  184. *
  185. * EXIT:
  186. * see RegWinStationEnumerateW, plus
  187. *
  188. * ERROR_NOT_ENOUGH_MEMORY - the LocalAlloc failed
  189. *
  190. ******************************************************************************/
  191. LONG WINAPI
  192. RegWinStationEnumerateA( HANDLE hServer,
  193. PULONG pIndex,
  194. PULONG pEntries,
  195. PWINSTATIONNAMEA pWinStationName,
  196. PULONG pByteCount )
  197. {
  198. PWINSTATIONNAMEW pBuffer = NULL, pWinStationNameW;
  199. LONG Status;
  200. ULONG Count, ByteCountW = (*pByteCount << 1);
  201. /*
  202. * If the caller supplied a buffer and the length is not 0,
  203. * allocate a corresponding (*2) buffer for UNICODE strings.
  204. */
  205. if ( pWinStationName && ByteCountW )
  206. {
  207. if ( !(pBuffer = LocalAlloc(0, ByteCountW)) )
  208. return ( ERROR_NOT_ENOUGH_MEMORY );
  209. }
  210. /*
  211. * Enumerate WinStations
  212. */
  213. pWinStationNameW = pBuffer;
  214. Status = RegWinStationEnumerateW( hServer, pIndex, pEntries, pWinStationNameW,
  215. &ByteCountW );
  216. /*
  217. * Always /2 the resultant ByteCount (whether sucessful or not).
  218. */
  219. *pByteCount = (ByteCountW >> 1);
  220. /*
  221. * If the function completed sucessfully and caller
  222. * (and stub) defined a buffer to copy into, perform conversion
  223. * from UNICODE to ANSI. Note: sucessful return may have copied
  224. * 0 items from registry (end of enumeration), denoted by *pEntries
  225. * == 0.
  226. */
  227. if ( ((Status == ERROR_SUCCESS) || (Status == ERROR_NO_MORE_ITEMS))
  228. && pWinStationNameW && pWinStationName ) {
  229. for ( Count = *pEntries; Count; Count-- ) {
  230. UnicodeToAnsi( pWinStationName, sizeof(WINSTATIONNAMEA),
  231. pWinStationNameW );
  232. (char*)pWinStationName += sizeof(WINSTATIONNAMEA);
  233. (char*)pWinStationNameW += sizeof(WINSTATIONNAMEW);
  234. }
  235. }
  236. /*
  237. * If we defined a buffer, free it now, then return the status
  238. * of the Reg...EnumerateW function call.
  239. */
  240. if ( pBuffer )
  241. LocalFree(pBuffer);
  242. return ( Status );
  243. }
  244. /*******************************************************************************
  245. *
  246. * RegWinStationEnumerateW (UNICODE)
  247. *
  248. * Returns a list of configured window stations in the registry.
  249. *
  250. * ENTRY:
  251. * hServer (input)
  252. * Handle to WinFrame Server
  253. * pIndex (input/output)
  254. * Specifies the subkey index for the \Citrix\WinStations subkeys in the
  255. * registry. Should be set to 0 for the initial call, and supplied
  256. * again (as modified by this function) for multi-call enumeration.
  257. * pEntries (input/output)
  258. * Points to a variable specifying the number of entries requested.
  259. * If the number requested is 0xFFFFFFFF, the function returns as
  260. * many entries as possible. When the function finishes successfully,
  261. * the variable pointed to by the pEntries parameter contains the
  262. * number of entries actually read.
  263. * pWinStationName (input)
  264. * Points to the buffer to receive the enumeration results, which are
  265. * returned as an array of WINSTATIONNAME structures. If this parameter
  266. * is NULL, then no data will be copied, but just an enumeration count
  267. * will be made.
  268. * pByteCount (input/output)
  269. * Points to a variable that specifies the size, in bytes, of the
  270. * pWinStationName parameter. If the buffer is too small to receive even
  271. * one entry, the function returns an error code (ERROR_OUTOFMEMORY)
  272. * and this variable receives the required size of the buffer for a
  273. * single subkey. When the function finishes sucessfully, the variable
  274. * pointed to by the pByteCount parameter contains the number of bytes
  275. * actually stored in pWinStationName.
  276. *
  277. * EXIT:
  278. *
  279. * "No Error" codes:
  280. * ERROR_SUCCESS - The enumeration completed as requested and there
  281. * are more WinStations subkeys (WINSTATIONNAMEs) to
  282. * be read.
  283. * ERROR_NO_MORE_ITEMS - The enumeration completed as requested and there
  284. * are no more WinStations subkeys (WINSTATIONNAMEs)
  285. * to be read.
  286. *
  287. * "Error" codes:
  288. * ERROR_OUTOFMEMORY - The pWinStationName buffer is too small for even
  289. * one entry.
  290. * ERROR_CANTOPEN - The Citrix\WinStations key can't be opened.
  291. *
  292. ******************************************************************************/
  293. LONG WINAPI
  294. RegWinStationEnumerateW( HANDLE hServer,
  295. PULONG pIndex,
  296. PULONG pEntries,
  297. PWINSTATIONNAMEW pWinStationName,
  298. PULONG pByteCount )
  299. {
  300. LONG Status;
  301. HKEY Handle;
  302. ULONG Count;
  303. ULONG i;
  304. /*
  305. * Get the number of names to return
  306. */
  307. Count = pWinStationName ?
  308. min( *pByteCount / sizeof(WINSTATIONNAME), *pEntries ) :
  309. (ULONG) -1;
  310. *pEntries = *pByteCount = 0;
  311. /*
  312. * Make sure buffer is big enough for at least one name
  313. */
  314. if ( Count == 0 ) {
  315. *pByteCount = sizeof(WINSTATIONNAME);
  316. return( ERROR_OUTOFMEMORY );
  317. }
  318. /*
  319. * Open registry (LOCAL_MACHINE\....\Citrix\WinStations)
  320. */
  321. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,
  322. KEY_ENUMERATE_SUB_KEYS, &Handle ) != ERROR_SUCCESS ) {
  323. goto DefaultConsole;
  324. }
  325. /*
  326. * Get list of window stations
  327. */
  328. for ( i = 0; i < Count; i++ ) {
  329. WINSTATIONNAME WinStationName;
  330. if ( (Status = RegEnumKey(Handle, *pIndex, WinStationName,
  331. sizeof(WINSTATIONNAME)/sizeof(TCHAR) )) != ERROR_SUCCESS )
  332. break;
  333. /*
  334. * If caller supplied a buffer, then copy the WinStationName
  335. * and increment the pointer and byte count. Always increment the
  336. * entry count and index for the next iteration.
  337. */
  338. if ( pWinStationName ) {
  339. wcscpy( pWinStationName, WinStationName );
  340. (char*)pWinStationName += sizeof(WINSTATIONNAME);
  341. *pByteCount += sizeof(WINSTATIONNAME);
  342. }
  343. (*pEntries)++;
  344. (*pIndex)++;
  345. }
  346. /*
  347. * Close registry
  348. */
  349. RegCloseKey( Handle );
  350. if ( Status == ERROR_NO_MORE_ITEMS ) {
  351. if ( (*pEntries == 0) && (*pIndex == 0) )
  352. goto DefaultConsole;
  353. }
  354. return( Status );
  355. /*
  356. * We come here when there are no WinStations defined.
  357. * We return a default "Console" name (if pWinStationName isn't NULL).
  358. */
  359. DefaultConsole:
  360. if ( pWinStationName )
  361. wcscpy( pWinStationName, L"Console" );
  362. *pEntries = 1;
  363. *pByteCount = sizeof(WINSTATIONNAME);
  364. return( ERROR_NO_MORE_ITEMS );
  365. }
  366. /*******************************************************************************
  367. *
  368. * RegWinStationCreateA (ANSI stub)
  369. *
  370. * Creates a new WinStaton in the registry or updates an existing entry.
  371. * (See RegWinStationCreateW)
  372. *
  373. * ENTRY:
  374. * see RegWinStationCreateW
  375. *
  376. * EXIT:
  377. * see RegWinStationCreateW
  378. *
  379. ******************************************************************************/
  380. LONG WINAPI
  381. RegWinStationCreateA( HANDLE hServer,
  382. PWINSTATIONNAMEA pWinStationName,
  383. BOOLEAN bCreate,
  384. PWINSTATIONCONFIG2A pWinStationConfig,
  385. ULONG WinStationConfigLength )
  386. {
  387. WINSTATIONNAMEW WinStationNameW;
  388. WINSTATIONCONFIG2W WinStationConfig2W;
  389. int i;
  390. /*
  391. * Validate target buffer size.
  392. */
  393. if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2A) )
  394. return( ERROR_INSUFFICIENT_BUFFER );
  395. /*
  396. * Convert ANSI WinStationName to UNICODE.
  397. */
  398. AnsiToUnicode( WinStationNameW, sizeof(WINSTATIONNAMEW), pWinStationName );
  399. /*
  400. * Copy WINSTATIONCONFIG2A elements to WINSTATIONCONFIG2W elements.
  401. */
  402. WinStationCreateA2U( &(WinStationConfig2W.Create),
  403. &(pWinStationConfig->Create) );
  404. for ( i=0; i<MAX_PDCONFIG; i++ ) {
  405. PdConfigA2U( &(WinStationConfig2W.Pd[i]),
  406. &(pWinStationConfig->Pd[i]) );
  407. }
  408. WdConfigA2U( &(WinStationConfig2W.Wd),
  409. &(pWinStationConfig->Wd) );
  410. CdConfigA2U( &(WinStationConfig2W.Cd),
  411. &(pWinStationConfig->Cd) );
  412. WinStationConfigA2U( &(WinStationConfig2W.Config),
  413. &(pWinStationConfig->Config) );
  414. /*
  415. * Call RegWinStationCreateW & return it's status.
  416. */
  417. return ( RegWinStationCreateW( hServer, WinStationNameW, bCreate,
  418. &WinStationConfig2W,
  419. sizeof(WinStationConfig2W)) );
  420. }
  421. /*******************************************************************************
  422. *
  423. * RegWinStationCreateW (UNICODE)
  424. *
  425. * Creates a new WinStaton in the registry or updates an existing entry.
  426. * The state of the bCreate flag determines whether this function will
  427. * expect to create a new WinStation entry (bCreate == TRUE) or expects to
  428. * update an existing entry (bCreate == FALSE).
  429. *
  430. * ENTRY:
  431. * hServer (input)
  432. * Handle to WinFrame Server
  433. * pWinStationName (input)
  434. * Name of a new or exisiting window station in the registry.
  435. * bCreate (input)
  436. * TRUE if this is a creation of a new WinStation
  437. * FALSE if this is an update to an existing WinStation
  438. * pWinStationConfig (input)
  439. * Pointer to a WINSTATIONCONFIG2 structure containing configuration
  440. * information for the specified window station name.
  441. * WinStationConfigLength (input)
  442. * Specifies the length in bytes of the pWinStationConfig buffer.
  443. *
  444. * EXIT:
  445. * ERROR_SUCCESS - no error
  446. *
  447. * ERROR_INSUFFICIENT_BUFFER - pWinStationConfig buffer too small
  448. * ERROR_FILE_NOT_FOUND - can't open ...\Citrix\WinStations key
  449. * ERROR_CANNOT_MAKE - can't create WinStation key (registry problem)
  450. * ERROR_ALREADY_EXISTS - create; but WinStation key already present
  451. * ERROR_CANTOPEN - update; but WinStation key could not be opened
  452. *
  453. ******************************************************************************/
  454. LONG WINAPI
  455. RegWinStationCreateW( HANDLE hServer,
  456. PWINSTATIONNAMEW pWinStationName,
  457. BOOLEAN bCreate,
  458. PWINSTATIONCONFIG2W pWinStationConfig,
  459. ULONG WinStationConfigLength )
  460. {
  461. HKEY Handle;
  462. HKEY Handle1;
  463. DWORD Disp;
  464. /*
  465. * Validate length of buffer
  466. */
  467. if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2) )
  468. return( ERROR_INSUFFICIENT_BUFFER );
  469. /*
  470. * Open registry (LOCAL_MACHINE\....\Citrix\WinStations).
  471. * If it doesn't exist, we attemp to create it.
  472. */
  473. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,
  474. KEY_ALL_ACCESS, &Handle1 ) != ERROR_SUCCESS &&
  475. RegCreateKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0, NULL,
  476. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  477. &Handle1, &Disp ) != ERROR_SUCCESS ) {
  478. return( ERROR_FILE_NOT_FOUND );
  479. }
  480. if ( bCreate ) {
  481. /*
  482. * Create requested: create a registry key for the specified
  483. * WinStation name.
  484. */
  485. if ( RegCreateKeyEx( Handle1, pWinStationName, 0, NULL,
  486. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  487. NULL, &Handle, &Disp ) != ERROR_SUCCESS ) {
  488. RegCloseKey( Handle1 );
  489. return( ERROR_CANNOT_MAKE );
  490. }
  491. /*
  492. * If an existing key was returned instead of a new one being
  493. * created, return error (don't update).
  494. */
  495. if ( Disp != REG_CREATED_NEW_KEY ) {
  496. RegCloseKey( Handle1 );
  497. RegCloseKey( Handle );
  498. return( ERROR_ALREADY_EXISTS );
  499. }
  500. } else {
  501. /*
  502. * Update requested: open the registry key for the specified
  503. * WinStation name.
  504. */
  505. if ( RegOpenKeyEx( Handle1, pWinStationName, 0, KEY_ALL_ACCESS,
  506. &Handle ) != ERROR_SUCCESS ) {
  507. RegCloseKey( Handle1 );
  508. return( ERROR_CANTOPEN );
  509. }
  510. }
  511. RegCloseKey( Handle1 );
  512. /*
  513. * Save WINSTATIONCONFIG2 Structure
  514. */
  515. CreateWinStaCreate( Handle, &pWinStationConfig->Create );
  516. CreatePdConfig( bCreate, Handle, pWinStationConfig->Pd, MAX_PDCONFIG );
  517. CreateWd( Handle, &pWinStationConfig->Wd );
  518. CreateCd( Handle, &pWinStationConfig->Cd );
  519. CreateConfig( Handle, &pWinStationConfig->Config );
  520. /*
  521. * Close registry handle
  522. */
  523. RegCloseKey( Handle );
  524. return( ERROR_SUCCESS );
  525. }
  526. /*******************************************************************************
  527. *
  528. * RegWinStationQueryA (ANSI stub)
  529. *
  530. * Query configuration information of a window station in the registry.
  531. *
  532. * ENTRY:
  533. * see RegWinStationQueryW
  534. *
  535. * EXIT:
  536. * see RegWinStationQueryW
  537. *
  538. ******************************************************************************/
  539. LONG WINAPI
  540. RegWinStationQueryA( HANDLE hServer,
  541. PWINSTATIONNAMEA pWinStationName,
  542. PWINSTATIONCONFIG2A pWinStationConfig,
  543. ULONG WinStationConfigLength,
  544. PULONG pReturnLength )
  545. {
  546. WINSTATIONNAMEW WinStationNameW;
  547. WINSTATIONCONFIG2W WinStationConfig2W;
  548. LONG Status;
  549. ULONG ReturnLengthW;
  550. int i;
  551. /*
  552. * Validate length and zero-initialize the destination
  553. * WINSTATIONCONFIG2A structure.
  554. */
  555. if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2A) )
  556. return( ERROR_INSUFFICIENT_BUFFER );
  557. memset(pWinStationConfig, 0, WinStationConfigLength);
  558. /*
  559. * Convert ANSI WinStationName to UNICODE.
  560. */
  561. AnsiToUnicode( WinStationNameW, sizeof(WINSTATIONNAMEW), pWinStationName );
  562. /*
  563. * Query WinStation.
  564. */
  565. if ( (Status = RegWinStationQueryW( hServer,
  566. WinStationNameW,
  567. &WinStationConfig2W,
  568. sizeof(WINSTATIONCONFIG2W),
  569. &ReturnLengthW)) != ERROR_SUCCESS )
  570. return ( Status );
  571. /*
  572. * Copy WINSTATIONCONFIG2W elements to WINSTATIONCONFIG2A elements.
  573. */
  574. WinStationCreateU2A( &(pWinStationConfig->Create),
  575. &(WinStationConfig2W.Create) );
  576. for ( i=0; i<MAX_PDCONFIG; i++ ) {
  577. PdConfigU2A( &(pWinStationConfig->Pd[i]),
  578. &(WinStationConfig2W.Pd[i]) );
  579. }
  580. WdConfigU2A( &(pWinStationConfig->Wd),
  581. &(WinStationConfig2W.Wd) );
  582. CdConfigU2A( &(pWinStationConfig->Cd),
  583. &(WinStationConfig2W.Cd) );
  584. WinStationConfigU2A( &(pWinStationConfig->Config),
  585. &(WinStationConfig2W.Config) );
  586. *pReturnLength = sizeof(WINSTATIONCONFIG2A);
  587. return( ERROR_SUCCESS );
  588. }
  589. /*******************************************************************************
  590. *
  591. *
  592. *
  593. * RegWinStationQueryEx (UNICODE)
  594. *
  595. * USE THIS CALL if you are in TermSrv.DLL, since it will update the global policy object
  596. *
  597. * Same as RegWinStationQueryW with the excpetion that a pointer to a global policy object is passed in.
  598. *
  599. * Query configuration information of a window station in the registry.
  600. *
  601. * ENTRY:
  602. * hServer (input)
  603. * Handle to WinFrame Server
  604. * pMachinePolicy (input)
  605. * pointer to a gloabl machine policy struct
  606. * pWinStationName (input)
  607. * Name of an exisiting window station in the registry.
  608. * pWinStationConfig (input)
  609. * Pointer to a WINSTATIONCONFIG2 structure that will receive
  610. * information about the specified window station name.
  611. * WinStationConfigLength (input)
  612. * Specifies the length in bytes of the pWinStationConfig buffer.
  613. * pReturnLength (output)
  614. * Receives the number of bytes placed in the pWinStationConfig buffer.
  615. *
  616. * EXIT:
  617. * ERROR_SUCCESS - no error
  618. * otherwise: the error code
  619. *
  620. ******************************************************************************/
  621. LONG WINAPI
  622. RegWinStationQueryEx( HANDLE hServer,
  623. PPOLICY_TS_MACHINE pMachinePolicy,
  624. PWINSTATIONNAMEW pWinStationName,
  625. PWINSTATIONCONFIG2W pWinStationConfig,
  626. ULONG WinStationConfigLength,
  627. PULONG pReturnLength,
  628. BOOLEAN bPerformMerger)
  629. {
  630. LONG Status;
  631. HKEY Handle;
  632. ULONG Count;
  633. /*
  634. * Validate length and zero-initialize the destination
  635. * WINSTATIONCONFIG2W buffer.
  636. */
  637. if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2) )
  638. return( ERROR_INSUFFICIENT_BUFFER );
  639. memset(pWinStationConfig, 0, WinStationConfigLength);
  640. /*
  641. * Open registry
  642. */
  643. Status = _RegOpenWinStation( pWinStationName, KEY_READ, &Handle );
  644. if ( Status )
  645. Handle = 0;
  646. /*
  647. * Query WINSTATIONCONFIG2 Structure
  648. */
  649. QueryWinStaCreate( Handle, &pWinStationConfig->Create );
  650. Count = MAX_PDCONFIG;
  651. QueryPdConfig( Handle, pWinStationConfig->Pd, &Count );
  652. QueryWd( Handle, &pWinStationConfig->Wd );
  653. QueryCd( Handle, &pWinStationConfig->Cd );
  654. // This will populate the winstation's userconfig data with machine's version of that data.
  655. QueryConfig( Handle, &pWinStationConfig->Config );
  656. // Since we want to co-exist with the legacy path thru TSCC, we continue to call QueryConfig()
  657. // as we have done above, however, we follow up with a call that get's data from the group policy
  658. // tree, and then overrides the existing data (aquired above) by the specific data from group policy.
  659. RegGetMachinePolicy( pMachinePolicy );
  660. if (bPerformMerger)
  661. RegMergeMachinePolicy( pMachinePolicy, &pWinStationConfig->Config.User , &pWinStationConfig->Create );
  662. /*
  663. * Close registry
  664. */
  665. if ( Status == ERROR_SUCCESS )
  666. RegCloseKey( Handle );
  667. *pReturnLength = sizeof(WINSTATIONCONFIG2);
  668. return( ERROR_SUCCESS );
  669. }
  670. /*******************************************************************************
  671. *
  672. * RegWinStationQueryW (UNICODE)
  673. *
  674. * Query configuration information of a window station in the registry.
  675. *
  676. * ENTRY:
  677. * hServer (input)
  678. * Handle to WinFrame Server
  679. * pWinStationName (input)
  680. * Name of an exisiting window station in the registry.
  681. * pWinStationConfig (input)
  682. * Pointer to a WINSTATIONCONFIG2 structure that will receive
  683. * information about the specified window station name.
  684. * WinStationConfigLength (input)
  685. * Specifies the length in bytes of the pWinStationConfig buffer.
  686. * pReturnLength (output)
  687. * Receives the number of bytes placed in the pWinStationConfig buffer.
  688. *
  689. * EXIT:
  690. * ERROR_SUCCESS - no error
  691. * otherwise: the error code
  692. *
  693. ******************************************************************************/
  694. LONG WINAPI
  695. RegWinStationQueryW( HANDLE hServer,
  696. PWINSTATIONNAMEW pWinStationName,
  697. PWINSTATIONCONFIG2W pWinStationConfig,
  698. ULONG WinStationConfigLength,
  699. PULONG pReturnLength )
  700. {
  701. LONG Status;
  702. HKEY Handle;
  703. ULONG Count;
  704. POLICY_TS_MACHINE MachinePolicy;
  705. /*
  706. * Validate length and zero-initialize the destination
  707. * WINSTATIONCONFIG2W buffer.
  708. */
  709. if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2) )
  710. return( ERROR_INSUFFICIENT_BUFFER );
  711. memset(pWinStationConfig, 0, WinStationConfigLength);
  712. /*
  713. * Open registry
  714. */
  715. Status = _RegOpenWinStation( pWinStationName, KEY_READ, &Handle );
  716. if ( Status )
  717. Handle = 0;
  718. /*
  719. * Query WINSTATIONCONFIG2 Structure
  720. */
  721. QueryWinStaCreate( Handle, &pWinStationConfig->Create );
  722. Count = MAX_PDCONFIG;
  723. QueryPdConfig( Handle, pWinStationConfig->Pd, &Count );
  724. QueryWd( Handle, &pWinStationConfig->Wd );
  725. QueryCd( Handle, &pWinStationConfig->Cd );
  726. // This will populate the winstation's userconfig data with machine's version of that data.
  727. QueryConfig( Handle, &pWinStationConfig->Config );
  728. // Since we want to co-exist with the legacy path thru TSCC, we continue to call QueryConfig()
  729. // as we have done above, however, we follow up with a call that get's data from the group policy
  730. // tree, and then overrides the existing data (aquired above) by the specific data from group policy.
  731. RegGetMachinePolicy( & MachinePolicy );
  732. RegMergeMachinePolicy( & MachinePolicy, &pWinStationConfig->Config.User , &pWinStationConfig->Create );
  733. /*
  734. * Close registry
  735. */
  736. if ( Status == ERROR_SUCCESS )
  737. RegCloseKey( Handle );
  738. *pReturnLength = sizeof(WINSTATIONCONFIG2);
  739. return( ERROR_SUCCESS );
  740. }
  741. /*******************************************************************************
  742. *
  743. * RegConsoleShadowQueryA (ANSI stub)
  744. *
  745. * Query configuration information for the console shadow in the registry.
  746. *
  747. * ENTRY:
  748. * see RegConsoleShadowQueryW
  749. *
  750. * EXIT:
  751. * see RegConsoleShadowQueryW
  752. *
  753. ******************************************************************************/
  754. LONG WINAPI
  755. RegConsoleShadowQueryA( HANDLE hServer,
  756. PWINSTATIONNAMEA pWinStationName,
  757. PWDPREFIXA pWdPrefixName,
  758. PWINSTATIONCONFIG2A pWinStationConfig,
  759. ULONG WinStationConfigLength,
  760. PULONG pReturnLength )
  761. {
  762. WINSTATIONNAMEW WinStationNameW;
  763. WDPREFIXW WdPrefixNameW;
  764. WINSTATIONCONFIG2W WinStationConfig2W;
  765. LONG Status;
  766. ULONG ReturnLengthW;
  767. int i;
  768. /*
  769. * Validate length and zero-initialize the destination
  770. * WINSTATIONCONFIG2A structure.
  771. */
  772. if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2A) )
  773. return( ERROR_INSUFFICIENT_BUFFER );
  774. /*
  775. * Convert ANSI WinStationName and prefix name to UNICODE.
  776. */
  777. AnsiToUnicode( WinStationNameW, sizeof(WINSTATIONNAMEW), pWinStationName );
  778. AnsiToUnicode( WdPrefixNameW, sizeof(WDPREFIXW), pWdPrefixName );
  779. /*
  780. * Query WinStation.
  781. */
  782. if ( (Status = RegConsoleShadowQueryW( hServer,
  783. WinStationNameW,
  784. WdPrefixNameW,
  785. &WinStationConfig2W,
  786. sizeof(WINSTATIONCONFIG2W),
  787. &ReturnLengthW)) != ERROR_SUCCESS )
  788. return ( Status );
  789. /*
  790. * Copy WINSTATIONCONFIG2W elements to WINSTATIONCONFIG2A elements.
  791. */
  792. for ( i=0; i<MAX_PDCONFIG; i++ ) {
  793. PdConfigU2A( &(pWinStationConfig->Pd[i]),
  794. &(WinStationConfig2W.Pd[i]) );
  795. }
  796. WdConfigU2A( &(pWinStationConfig->Wd),
  797. &(WinStationConfig2W.Wd) );
  798. CdConfigU2A( &(pWinStationConfig->Cd),
  799. &(WinStationConfig2W.Cd) );
  800. *pReturnLength = sizeof(WINSTATIONCONFIG2A);
  801. return( ERROR_SUCCESS );
  802. }
  803. /*******************************************************************************
  804. *
  805. * RegConsoleShadowQueryW (UNICODE)
  806. *
  807. * Query configuration information for the console shadow in the registry.
  808. *
  809. * ENTRY:
  810. * hServer (input)
  811. * Handle to WinFrame Server
  812. * pWinStationName (input)
  813. * Name of an exisiting window station in the registry.
  814. * pWdPrefixName (input)
  815. * Name of the Wd prefix used to point to the sub-winstation key.
  816. * pWinStationConfig (input)
  817. * Pointer to a WINSTATIONCONFIG2 structure that will receive
  818. * information about the specified window station name.
  819. * WinStationConfigLength (input)
  820. * Specifies the length in bytes of the pWinStationConfig buffer.
  821. * pReturnLength (output)
  822. * Receives the number of bytes placed in the pWinStationConfig buffer.
  823. *
  824. * EXIT:
  825. * ERROR_SUCCESS - no error
  826. * otherwise: the error code
  827. *
  828. ******************************************************************************/
  829. LONG WINAPI
  830. RegConsoleShadowQueryW( HANDLE hServer,
  831. PWINSTATIONNAMEW pWinStationName,
  832. PWDPREFIXW pWdPrefixName,
  833. PWINSTATIONCONFIG2W pWinStationConfig,
  834. ULONG WinStationConfigLength,
  835. PULONG pReturnLength )
  836. {
  837. LONG Status;
  838. LONG lLength;
  839. HKEY Handle;
  840. ULONG Count;
  841. WCHAR szRegName[ WINSTATIONNAME_LENGTH + WDPREFIX_LENGTH + 2 ];
  842. /*
  843. * Validate length and zero-initialize the destination
  844. * WINSTATIONCONFIG2W buffer.
  845. */
  846. if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2) )
  847. return( ERROR_INSUFFICIENT_BUFFER );
  848. /*
  849. * Open registry
  850. */
  851. wcsncpy( szRegName, pWinStationName, sizeof(szRegName)/sizeof(WCHAR) - 1 );
  852. szRegName[sizeof(szRegName)/sizeof(WCHAR) - 1] = 0; // terminate the string even if pWinStationName is longer than the buffer
  853. lLength = wcslen( szRegName );
  854. if ( sizeof(szRegName)/sizeof(WCHAR) > ( lLength + 1 + wcslen( pWdPrefixName ) ) ) {
  855. wcsncat( szRegName, L"\\", sizeof(szRegName)/sizeof(WCHAR) - lLength - 1 );
  856. wcsncat( szRegName, pWdPrefixName, sizeof(szRegName)/sizeof(WCHAR) - lLength - 2 );
  857. } else {
  858. return ERROR_INVALID_PARAMETER;
  859. }
  860. Status = _RegOpenWinStation( szRegName, KEY_READ, &Handle );
  861. if ( Status )
  862. Handle = 0;
  863. /*
  864. * Query WINSTATIONCONFIG2 Structure
  865. */
  866. Count = MAX_PDCONFIG;
  867. QueryPdConfig( Handle, pWinStationConfig->Pd, &Count );
  868. QueryWd( Handle, &pWinStationConfig->Wd );
  869. QueryCd( Handle, &pWinStationConfig->Cd );
  870. /*
  871. * Close registry
  872. */
  873. if ( Status == ERROR_SUCCESS )
  874. RegCloseKey( Handle );
  875. *pReturnLength = sizeof(WINSTATIONCONFIG2);
  876. return( ERROR_SUCCESS );
  877. }
  878. /*******************************************************************************
  879. *
  880. * RegWinStationDeleteA (ANSI stub)
  881. *
  882. * Deletes a window station from the registry.
  883. *
  884. * ENTRY:
  885. * see RegWinStationDeleteW
  886. *
  887. * EXIT:
  888. * see RegWinStationDeleteW
  889. *
  890. ******************************************************************************/
  891. LONG WINAPI
  892. RegWinStationDeleteA( HANDLE hServer, PWINSTATIONNAMEA pWinStationName )
  893. {
  894. WINSTATIONNAMEW WinStationNameW;
  895. AnsiToUnicode( WinStationNameW, sizeof(WinStationNameW), pWinStationName );
  896. return ( RegWinStationDeleteW ( hServer, WinStationNameW ) );
  897. }
  898. /*******************************************************************************
  899. *
  900. * RegWinStationDeleteW (UNICODE)
  901. *
  902. * Deletes a window station from the registry.
  903. *
  904. * ENTRY:
  905. * hServer (input)
  906. * Handle to WinFrame Server
  907. * pWinStationName (input)
  908. * Name of a window station to delete from the registry.
  909. *
  910. * EXIT:
  911. * ERROR_SUCCESS - no error
  912. * otherwise: the error code
  913. *
  914. ******************************************************************************/
  915. LONG WINAPI
  916. RegWinStationDeleteW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName )
  917. {
  918. LONG Status;
  919. HKEY Handle1, Handle2;
  920. /*
  921. * Open registry (LOCAL_MACHINE\....\Citrix\WinStations).
  922. */
  923. if ( (Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  924. WINSTATION_REG_NAME, 0,
  925. KEY_ALL_ACCESS, &Handle1 )
  926. != ERROR_SUCCESS) ) {
  927. return( Status );
  928. }
  929. /*
  930. * Open the registry key for the specified WinStation name.
  931. */
  932. if ( (Status = RegOpenKeyEx( Handle1, pWinStationName, 0,
  933. KEY_ALL_ACCESS, &Handle2 )
  934. != ERROR_SUCCESS) ) {
  935. RegCloseKey( Handle1 );
  936. return( Status );
  937. }
  938. SetWallPaperDisabled( Handle2, FALSE );
  939. /*
  940. * Close the WinStation key handle just opened (so we can delete key),
  941. * delete the key, and close the Citrix registry handle.
  942. */
  943. RegCloseKey( Handle2 );
  944. Status = RegDeleteKey( Handle1, pWinStationName );
  945. RegCloseKey( Handle1 );
  946. return( Status );
  947. }
  948. /*******************************************************************************
  949. *
  950. * RegWinStationSetSecurityA (ANSI stub)
  951. *
  952. * Sets security info for the specified WinStation.
  953. *
  954. * ENTRY:
  955. * see RegWinStationSetSecurityW
  956. *
  957. * EXIT:
  958. * see RegWinStationSetSecurityW
  959. *
  960. ******************************************************************************/
  961. LONG WINAPI
  962. RegWinStationSetSecurityA( HANDLE hServer,
  963. PWINSTATIONNAMEA pWinStationName,
  964. PSECURITY_DESCRIPTOR SecurityDescriptor,
  965. ULONG Length )
  966. {
  967. WINSTATIONNAMEW WinStationNameW;
  968. AnsiToUnicode( WinStationNameW, sizeof(WinStationNameW), pWinStationName );
  969. return ( RegWinStationSetSecurityW( hServer, WinStationNameW,
  970. SecurityDescriptor,
  971. Length ) );
  972. }
  973. /*******************************************************************************
  974. *
  975. * RegWinStationSetSecurityW (UNICODE)
  976. *
  977. * Sets security info for the specified WinStation.
  978. *
  979. * ENTRY:
  980. * hServer (input)
  981. * Handle to WinFrame Server
  982. * pWinStationName (input)
  983. * Name of a window station to set security for.
  984. * pSecurityDescriptor (input)
  985. * Pointer to Security Descriptor to save
  986. * Length (input)
  987. * Length of SecurityDescriptor above
  988. *
  989. * EXIT:
  990. * ERROR_SUCCESS - no error
  991. * otherwise: the error code
  992. *
  993. ******************************************************************************/
  994. LONG WINAPI
  995. RegWinStationSetSecurityW( HANDLE hServer,
  996. PWINSTATIONNAMEW pWinStationName,
  997. PSECURITY_DESCRIPTOR SecurityDescriptor,
  998. ULONG Length )
  999. {
  1000. HKEY Handle;
  1001. ULONG SrLength;
  1002. PSECURITY_DESCRIPTOR SrSecurityDescriptor;
  1003. LONG Error;
  1004. NTSTATUS Status;
  1005. /*
  1006. * Open registry
  1007. */
  1008. if ( Error = _RegOpenWinStation( pWinStationName, KEY_ALL_ACCESS, &Handle ) )
  1009. return( Error );
  1010. /*
  1011. * Determine buffer length needed to convert SD to self-relative format.
  1012. */
  1013. SrLength = 0;
  1014. Status = RtlMakeSelfRelativeSD( SecurityDescriptor, NULL, &SrLength );
  1015. if ( Status != STATUS_BUFFER_TOO_SMALL ) {
  1016. RegCloseKey( Handle );
  1017. return( RtlNtStatusToDosError( Status ) );
  1018. }
  1019. /*
  1020. * Allocate buffer for self-relative SD.
  1021. */
  1022. SrSecurityDescriptor = LocalAlloc( 0, SrLength );
  1023. if ( SrSecurityDescriptor == NULL ) {
  1024. RegCloseKey( Handle );
  1025. return( ERROR_NOT_ENOUGH_MEMORY );
  1026. }
  1027. /*
  1028. * Now convert SD to self-relative format.
  1029. */
  1030. Status = RtlMakeSelfRelativeSD( SecurityDescriptor,
  1031. SrSecurityDescriptor, &SrLength );
  1032. if ( !NT_SUCCESS( Status ) ) {
  1033. LocalFree( SrSecurityDescriptor );
  1034. RegCloseKey( Handle );
  1035. return( RtlNtStatusToDosError( Status ) );
  1036. }
  1037. /*
  1038. * Save the security data
  1039. */
  1040. Error = RegSetValueEx( Handle, L"Security", 0, REG_BINARY,
  1041. (BYTE *)SrSecurityDescriptor, SrLength );
  1042. /*
  1043. * Free memory used for Self-relative Security Descriptor
  1044. */
  1045. LocalFree( SrSecurityDescriptor );
  1046. /*
  1047. * Close registry
  1048. */
  1049. RegCloseKey( Handle );
  1050. return( Error );
  1051. }
  1052. /*******************************************************************************
  1053. *
  1054. * RegWinStationQuerySecurityA (ANSI stub)
  1055. *
  1056. * Query security info for the specified WinStation.
  1057. *
  1058. * ENTRY:
  1059. * see RegWinStationQuerySecurityW
  1060. *
  1061. * EXIT:
  1062. * see RegWinStationQuerySecurityW
  1063. *
  1064. ******************************************************************************/
  1065. LONG WINAPI
  1066. RegWinStationQuerySecurityA( HANDLE hServer,
  1067. PWINSTATIONNAMEA pWinStationName,
  1068. PSECURITY_DESCRIPTOR SecurityDescriptor,
  1069. ULONG Length,
  1070. PULONG ReturnLength )
  1071. {
  1072. WINSTATIONNAMEW WinStationNameW;
  1073. AnsiToUnicode( WinStationNameW, sizeof(WinStationNameW), pWinStationName );
  1074. return ( RegWinStationQuerySecurityW( hServer, WinStationNameW,
  1075. SecurityDescriptor,
  1076. Length,
  1077. ReturnLength ) );
  1078. }
  1079. /*******************************************************************************
  1080. *
  1081. * RegWinStationQuerySecurityW (UNICODE)
  1082. *
  1083. * Query security info for the specified WinStation.
  1084. *
  1085. * ENTRY:
  1086. * hServer (input)
  1087. * Handle to WinFrame Server
  1088. * pWinStationName (input)
  1089. * Name of a window station to query security for.
  1090. * pSecurityDescriptor (output)
  1091. * Pointer to location to return SecurityDescriptor.
  1092. * Length (input)
  1093. * Length of SecurityDescriptor buffer.
  1094. * ReturnLength (output)
  1095. * Pointer to location to return length of SecurityDescriptor returned.
  1096. *
  1097. * EXIT:
  1098. * ERROR_SUCCESS - no error
  1099. * otherwise: the error code
  1100. *
  1101. ******************************************************************************/
  1102. LONG WINAPI
  1103. RegWinStationQuerySecurityW( HANDLE hServer,
  1104. PWINSTATIONNAMEW pWinStationName,
  1105. PSECURITY_DESCRIPTOR SecurityDescriptor,
  1106. ULONG Length,
  1107. PULONG ReturnLength )
  1108. {
  1109. HKEY Handle;
  1110. LONG Error;
  1111. /*
  1112. * Open registry
  1113. */
  1114. if ( Error = _RegOpenWinStation( pWinStationName, KEY_READ, &Handle ) )
  1115. return( Error );
  1116. /*
  1117. * Call RegGetWinStationSecurity() to do all the work
  1118. */
  1119. Error = _RegGetWinStationSecurity( Handle, L"Security",
  1120. SecurityDescriptor, Length, ReturnLength );
  1121. RegCloseKey( Handle );
  1122. return( Error );
  1123. }
  1124. /*******************************************************************************
  1125. *
  1126. * RegWinStationQueryDefaultSecurity
  1127. *
  1128. * Query default WinStation security.
  1129. *
  1130. * ENTRY:
  1131. * hServer (input)
  1132. * Handle to WinFrame Server
  1133. * pSecurityDescriptor (output)
  1134. * Pointer to location to return SecurityDescriptor.
  1135. * Length (input)
  1136. * Length of SecurityDescriptor buffer.
  1137. * ReturnLength (output)
  1138. * Pointer to location to return length of SecurityDescriptor returned.
  1139. *
  1140. * EXIT:
  1141. * ERROR_SUCCESS - no error
  1142. * otherwise: the error code
  1143. *
  1144. ******************************************************************************/
  1145. LONG WINAPI
  1146. RegWinStationQueryDefaultSecurity( HANDLE hServer,
  1147. PSECURITY_DESCRIPTOR SecurityDescriptor,
  1148. ULONG Length,
  1149. PULONG ReturnLength )
  1150. {
  1151. HKEY Handle;
  1152. LONG Error;
  1153. /*
  1154. * Open registry
  1155. */
  1156. if ( Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,
  1157. KEY_READ, &Handle ) )
  1158. return( Error );
  1159. /*
  1160. * Call RegGetWinStationSecurity() to do all the work
  1161. */
  1162. Error = _RegGetWinStationSecurity( Handle, L"DefaultSecurity",
  1163. SecurityDescriptor, Length, ReturnLength );
  1164. RegCloseKey( Handle );
  1165. return( Error );
  1166. }
  1167. /*******************************************************************************
  1168. *
  1169. * RegWinStationSetNumValueW (UNICODE)
  1170. *
  1171. * Set numeric value in WinStation registry configuration
  1172. *
  1173. * ENTRY:
  1174. * hServer (input)
  1175. * Handle to WinFrame Server
  1176. * pWinStationName (input)
  1177. * Name of a window station to modify from the registry.
  1178. * pValueName (input)
  1179. * name of registry value to set
  1180. * ValueData (input)
  1181. * data (DWORD) for registry value to set
  1182. *
  1183. * EXIT:
  1184. * ERROR_SUCCESS - no error
  1185. * otherwise: the error code
  1186. *
  1187. ******************************************************************************/
  1188. LONG WINAPI
  1189. RegWinStationSetNumValueW( HANDLE hServer,
  1190. PWINSTATIONNAMEW pWinStationName,
  1191. LPWSTR pValueName,
  1192. ULONG ValueData )
  1193. {
  1194. HKEY Handle;
  1195. LONG Error;
  1196. /*
  1197. * Open registry
  1198. */
  1199. if ( Error = _RegOpenWinStation( pWinStationName, KEY_ALL_ACCESS, &Handle ) )
  1200. return( Error );
  1201. /*
  1202. * Set the numeric value
  1203. */
  1204. Error = RegSetValueEx( Handle, pValueName, 0, REG_DWORD,
  1205. (BYTE *)&ValueData, sizeof(DWORD) );
  1206. /*
  1207. * Close registry
  1208. */
  1209. RegCloseKey( Handle );
  1210. return( Error );
  1211. }
  1212. /*******************************************************************************
  1213. *
  1214. * RegWinStationQueryNumValueW (UNICODE)
  1215. *
  1216. * Query numeric value from WinStation registry configuration
  1217. *
  1218. * ENTRY:
  1219. * hServer (input)
  1220. * Handle to WinFrame Server
  1221. * pWinStationName (input)
  1222. * Name of a window station to modify from the registry.
  1223. * pValueName (input)
  1224. * name of registry value to set
  1225. * pValueData (output)
  1226. * address to return data (DWORD) value from registry
  1227. *
  1228. * EXIT:
  1229. * ERROR_SUCCESS - no error
  1230. * otherwise: the error code
  1231. *
  1232. ******************************************************************************/
  1233. LONG WINAPI
  1234. RegWinStationQueryNumValueW( HANDLE hServer,
  1235. PWINSTATIONNAMEW pWinStationName,
  1236. LPWSTR pValueName,
  1237. PULONG pValueData )
  1238. {
  1239. DWORD ValueSize = sizeof(DWORD);
  1240. DWORD ValueType;
  1241. HKEY Handle;
  1242. LONG Error;
  1243. /*
  1244. * Open registry
  1245. */
  1246. if ( Error = _RegOpenWinStation( pWinStationName, KEY_READ, &Handle ) )
  1247. return( Error );
  1248. /*
  1249. * Query the numeric value
  1250. */
  1251. Error = RegQueryValueEx( Handle, pValueName, NULL, &ValueType,
  1252. (LPBYTE) pValueData, &ValueSize );
  1253. /*
  1254. * Close registry
  1255. */
  1256. RegCloseKey( Handle );
  1257. return( Error );
  1258. }
  1259. /*******************************************************************************
  1260. *
  1261. * RegWinStationQueryValueW (UNICODE)
  1262. *
  1263. * Query value from WinStation registry configuration
  1264. *
  1265. * ENTRY:
  1266. * hServer (input)
  1267. * Handle to WinFrame Server
  1268. * pWinStationName (input)
  1269. * Name of a window station to modify from the registry.
  1270. * pValueName (input)
  1271. * name of registry value to set
  1272. * pValueData (output)
  1273. * address to return data (DWORD) value from registry
  1274. * ValueSize (input)
  1275. * size of value buffer
  1276. * pValueSize (input)
  1277. * actual value size
  1278. *
  1279. * EXIT:
  1280. * ERROR_SUCCESS - no error
  1281. * otherwise: the error code
  1282. *
  1283. ******************************************************************************/
  1284. LONG WINAPI
  1285. RegWinStationQueryValueW( HANDLE hServer,
  1286. PWINSTATIONNAMEW pWinStationName,
  1287. LPWSTR pValueName,
  1288. PVOID pValueData,
  1289. ULONG ValueSize,
  1290. PULONG pValueSize )
  1291. {
  1292. DWORD ValueType;
  1293. HKEY Handle;
  1294. LONG Error;
  1295. *pValueSize = ValueSize;
  1296. /*
  1297. * Open registry
  1298. */
  1299. if ( Error = _RegOpenWinStation( pWinStationName, KEY_READ, &Handle ) )
  1300. return( Error );
  1301. /*
  1302. * Query the numeric value
  1303. */
  1304. Error = RegQueryValueEx( Handle, pValueName, NULL, &ValueType,
  1305. (LPBYTE) pValueData, pValueSize );
  1306. /*
  1307. * Close registry
  1308. */
  1309. RegCloseKey( Handle );
  1310. return( Error );
  1311. }
  1312. /*******************************************************************************
  1313. *
  1314. * -- private routine --
  1315. *
  1316. * _RegOpenWinStation
  1317. *
  1318. * open registry of specified winstation
  1319. *
  1320. * NOTE: handle must be closed with "RegCloseKey"
  1321. *
  1322. * ENTRY:
  1323. * hServer (input)
  1324. * Handle to WinFrame Server
  1325. * pWinStationName (input)
  1326. * Name of a window station to modify from the registry.
  1327. * samDesired (input)
  1328. * REGSAM access level for registry open.
  1329. * pHandle (output)
  1330. * address to return handle
  1331. *
  1332. * EXIT:
  1333. * ERROR_SUCCESS - no error
  1334. * otherwise: the error code
  1335. *
  1336. ******************************************************************************/
  1337. LONG
  1338. _RegOpenWinStation( PWINSTATIONNAMEW pWinStationName,
  1339. REGSAM samDesired,
  1340. HKEY * pHandle )
  1341. {
  1342. HKEY Handle1;
  1343. LONG Error;
  1344. /*
  1345. * Open registry (LOCAL_MACHINE\....\Citrix\WinStations).
  1346. */
  1347. if ( (Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,
  1348. samDesired, &Handle1 ) != ERROR_SUCCESS) ) {
  1349. return( Error );
  1350. }
  1351. /*
  1352. * Open the registry key for the specified WinStation name.
  1353. */
  1354. Error = RegOpenKeyEx( Handle1, pWinStationName, 0, samDesired, pHandle);
  1355. RegCloseKey( Handle1 );
  1356. return( Error );
  1357. }
  1358. /*******************************************************************************
  1359. *
  1360. * -- private routine --
  1361. *
  1362. * _RegGetWinStationSecurity
  1363. *
  1364. * Query the security descriptor from the specified registry key.
  1365. *
  1366. * ENTRY:
  1367. * Handle (input)
  1368. * Open registry key handle.
  1369. * ValueName (input)
  1370. * Name of security value.
  1371. * pSecurityDescriptor (output)
  1372. * Pointer to location to return SecurityDescriptor.
  1373. * Length (input)
  1374. * Length of SecurityDescriptor buffer.
  1375. * ReturnLength (output)
  1376. * Pointer to location to return length of SecurityDescriptor returned.
  1377. *
  1378. * EXIT:
  1379. * ERROR_SUCCESS - no error
  1380. * otherwise: the error code
  1381. *
  1382. ******************************************************************************/
  1383. LONG
  1384. _RegGetWinStationSecurity( HKEY Handle,
  1385. LPWSTR ValueName,
  1386. PSECURITY_DESCRIPTOR SecurityDescriptor,
  1387. ULONG Length,
  1388. PULONG ReturnLength )
  1389. {
  1390. DWORD ValueType;
  1391. DWORD SrLength;
  1392. ULONG SdSize, DaclSize, SaclSize, OwnerSize, GroupSize;
  1393. PSECURITY_DESCRIPTOR SrSecurityDescriptor;
  1394. PACL pDacl, pSacl;
  1395. PSID pOwner, pGroup;
  1396. LONG Error;
  1397. NTSTATUS Status;
  1398. /*
  1399. * Query the length of the Security value
  1400. */
  1401. SrLength = 0;
  1402. if ( Error = RegQueryValueEx( Handle, ValueName, NULL, &ValueType,
  1403. NULL, &SrLength ) ) {
  1404. return( Error );
  1405. }
  1406. /*
  1407. * Return error if not correct data type
  1408. */
  1409. if ( ValueType != REG_BINARY ) {
  1410. return( ERROR_FILE_NOT_FOUND );
  1411. }
  1412. /*
  1413. * Allocate a buffer to read the Security info and read it
  1414. */
  1415. SrSecurityDescriptor = LocalAlloc( 0, SrLength );
  1416. if ( SrSecurityDescriptor == NULL ) {
  1417. return( ERROR_NOT_ENOUGH_MEMORY );
  1418. }
  1419. if ( Error = RegQueryValueEx( Handle, ValueName, NULL, &ValueType,
  1420. SrSecurityDescriptor, &SrLength ) ) {
  1421. LocalFree( SrSecurityDescriptor );
  1422. return( Error );
  1423. }
  1424. /*
  1425. * Determine amount of space required to convert SD from
  1426. * self-relative format to absolute format.
  1427. */
  1428. SdSize = DaclSize = SaclSize = OwnerSize = GroupSize = 0;
  1429. Status = RtlSelfRelativeToAbsoluteSD( SrSecurityDescriptor,
  1430. NULL, &SdSize,
  1431. NULL, &DaclSize,
  1432. NULL, &SaclSize,
  1433. NULL, &OwnerSize,
  1434. NULL, &GroupSize );
  1435. if ( Status != STATUS_BUFFER_TOO_SMALL ) {
  1436. LocalFree( SrSecurityDescriptor );
  1437. return( RtlNtStatusToDosError( Status ) );
  1438. }
  1439. *ReturnLength = SdSize + DaclSize + SaclSize + OwnerSize + GroupSize;
  1440. /*
  1441. * If required size is greater than callers buffer size, then return
  1442. */
  1443. if ( *ReturnLength > Length ) {
  1444. LocalFree( SrSecurityDescriptor );
  1445. return( ERROR_INSUFFICIENT_BUFFER );
  1446. }
  1447. pDacl = (PACL)((PCHAR)SecurityDescriptor + SdSize);
  1448. pSacl = (PACL)((PCHAR)pDacl + DaclSize);
  1449. pOwner = (PSID)((PCHAR)pSacl + SaclSize);
  1450. pGroup = (PSID)((PCHAR)pOwner + OwnerSize);
  1451. /*
  1452. * Now convert self-relative SD to absolute format.
  1453. */
  1454. Status = RtlSelfRelativeToAbsoluteSD( SrSecurityDescriptor,
  1455. SecurityDescriptor, &SdSize,
  1456. pDacl, &DaclSize,
  1457. pSacl, &SaclSize,
  1458. pOwner, &OwnerSize,
  1459. pGroup, &GroupSize );
  1460. if ( !NT_SUCCESS( Status ) )
  1461. Error = RtlNtStatusToDosError( Status );
  1462. /*
  1463. * Free memory used for Self-relative Security Descriptor
  1464. */
  1465. LocalFree( SrSecurityDescriptor );
  1466. return( Error );
  1467. }