Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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