|
|
/*************************************************************************
* * regwin.c * * Register APIs for window stations * * Copyright (c) 1998 Microsoft Corporation * * *************************************************************************/
/*
* Includes */ #include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <ntddkbd.h>
#include <ntddmou.h>
#include <winstaw.h>
#include <regapi.h>
//
extern HKEY g_hTSPolicyKey;//handle to TS_POLICY_SUB_TREE key
extern HKEY g_hTSControlKey;//handle to REG_CONTROL_TSERVER key
/*
* External Procedures defined here */ LONG WINAPI RegWinStationAccessCheck( HANDLE, REGSAM ); LONG WINAPI RegWinStationEnumerateW( HANDLE, PULONG, PULONG, PWINSTATIONNAMEW, PULONG ); LONG WINAPI RegWinStationEnumerateA( HANDLE, PULONG, PULONG, PWINSTATIONNAMEA, PULONG ); LONG WINAPI RegWinStationCreateW( HANDLE, PWINSTATIONNAMEW, BOOLEAN, PWINSTATIONCONFIG2W, ULONG ); LONG WINAPI RegWinStationCreateA( HANDLE, PWINSTATIONNAMEA, BOOLEAN, PWINSTATIONCONFIG2A, ULONG ); LONG WINAPI RegWinStationQueryW( HANDLE, PWINSTATIONNAMEW, PWINSTATIONCONFIG2W, ULONG, PULONG ); LONG WINAPI RegWinStationQueryA( HANDLE, PWINSTATIONNAMEA, PWINSTATIONCONFIG2A, ULONG, PULONG ); LONG WINAPI RegWinStationDeleteW( HANDLE, PWINSTATIONNAMEW ); LONG WINAPI RegWinStationDeleteA( HANDLE, PWINSTATIONNAMEA ); LONG WINAPI RegWinStationSetSecurityW( HANDLE, PWINSTATIONNAMEW, PSECURITY_DESCRIPTOR, ULONG ); LONG WINAPI RegWinStationSetSecurityA( HANDLE, PWINSTATIONNAMEA, PSECURITY_DESCRIPTOR, ULONG ); LONG WINAPI RegWinStationQuerySecurityW( HANDLE, PWINSTATIONNAMEW, PSECURITY_DESCRIPTOR, ULONG, PULONG ); LONG WINAPI RegWinStationQuerySecurityA( HANDLE, PWINSTATIONNAMEA, PSECURITY_DESCRIPTOR, ULONG, PULONG ); LONG WINAPI RegWinStationQueryDefaultSecurity( HANDLE, PSECURITY_DESCRIPTOR, ULONG, PULONG );
LONG WINAPI RegWinStationSetNumValueW( HANDLE, PWINSTATIONNAMEW, LPWSTR, ULONG ); LONG WINAPI RegWinStationQueryNumValueW( HANDLE, PWINSTATIONNAMEW, LPWSTR, PULONG );
LONG WINAPI RegConsoleShadowQueryA( HANDLE hServer, PWINSTATIONNAMEA pWinStationName, PWDPREFIXA pWdPrefixName, PWINSTATIONCONFIG2A pWinStationConfig, ULONG WinStationConfigLength, PULONG pReturnLength );
LONG WINAPI RegConsoleShadowQueryW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName, PWDPREFIXW pWdPrefixName, PWINSTATIONCONFIG2W pWinStationConfig, ULONG WinStationConfigLength, PULONG pReturnLength );
/*
* Private Procedures defined here */ LONG _RegOpenWinStation( PWINSTATIONNAMEW, REGSAM, HKEY * ); LONG _RegGetWinStationSecurity( HKEY, LPWSTR, PSECURITY_DESCRIPTOR, ULONG, PULONG );
/*
* other internal Procedures used (not defined here) */ VOID CreateWinStaCreate( HKEY, PWINSTATIONCREATE ); VOID CreateConfig( HKEY, PWINSTATIONCONFIG ); VOID CreateWd( HKEY, PWDCONFIG ); VOID CreateCd( HKEY, PCDCONFIG ); VOID CreatePdConfig( BOOLEAN, HKEY, PPDCONFIG, ULONG ); VOID QueryWinStaCreate( HKEY, PWINSTATIONCREATE ); VOID QueryConfig( HKEY, PWINSTATIONCONFIG ); VOID QueryWd( HKEY, PWDCONFIG ); VOID QueryCd( HKEY, PCDCONFIG ); VOID QueryPdConfig( HKEY, PPDCONFIG, PULONG ); VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * ); VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * ); VOID PdConfigU2A( PPDCONFIGA, PPDCONFIGW ); VOID PdConfigA2U( PPDCONFIGW, PPDCONFIGA ); VOID WdConfigU2A( PWDCONFIGA, PWDCONFIGW ); VOID WdConfigA2U( PWDCONFIGW, PWDCONFIGA ); VOID CdConfigU2A( PCDCONFIGA, PCDCONFIGW ); VOID CdConfigA2U( PCDCONFIGW, PCDCONFIGA ); VOID WinStationCreateU2A( PWINSTATIONCREATEA, PWINSTATIONCREATEW ); VOID WinStationCreateA2U( PWINSTATIONCREATEW, PWINSTATIONCREATEA ); VOID WinStationConfigU2A( PWINSTATIONCONFIGA, PWINSTATIONCONFIGW ); VOID WinStationConfigA2U( PWINSTATIONCONFIGW, PWINSTATIONCONFIGA ); VOID SetWallPaperDisabled( HKEY, BOOLEAN );
/****************************************************************************
* * DllEntryPoint * * Function is called when the DLL is loaded and unloaded. * * ENTRY: * hinstDLL (input) * Handle of DLL module * * fdwReason (input) * Why function was called * * lpvReserved (input) * Reserved; must be NULL * * EXIT: * TRUE - Success * FALSE - Error occurred * ****************************************************************************/
BOOL WINAPI DllEntryPoint( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) { switch ( fdwReason ) { case DLL_PROCESS_ATTACH: break;
case DLL_PROCESS_DETACH: if( g_hTSPolicyKey ) { RegCloseKey(g_hTSPolicyKey); }
if( g_hTSControlKey ) { RegCloseKey(g_hTSControlKey); } break;
default: break; }
return( TRUE ); }
/*******************************************************************************
* * RegWinStationAccessCheck (ANSI or UNICODE) * * Determines if the current user has the requested access to the * WinStation registry. * * ENTRY: * hServer (input) * Handle to WinFrame Server * samDesired (input) * Specifies the security access mask to be used in determining access * to the WinStation registry. * * EXIT: * ERROR_SUCCESS if the user has the requested access * other error value (most likely ERROR_ACCESS_DENIED) if the user does * not have the requested access. * ******************************************************************************/
LONG WINAPI RegWinStationAccessCheck( HANDLE hServer, REGSAM samDesired ) { LONG Status; HKEY Handle;
/*
* Attempt to open the registry (LOCAL_MACHINE\....\Citrix\Pd) * at the requested access level. */ if ( (Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0, samDesired, &Handle )) == ERROR_SUCCESS ) RegCloseKey( Handle );
return( Status ); }
/*******************************************************************************
* * RegWinStationEnumerateA (ANSI stub) * * Returns a list of configured WinStations in the registry. * * ENTRY: * see RegWinStationEnumerateW * * EXIT: * see RegWinStationEnumerateW, plus * * ERROR_NOT_ENOUGH_MEMORY - the LocalAlloc failed * ******************************************************************************/
LONG WINAPI RegWinStationEnumerateA( HANDLE hServer, PULONG pIndex, PULONG pEntries, PWINSTATIONNAMEA pWinStationName, PULONG pByteCount ) { PWINSTATIONNAMEW pBuffer = NULL, pWinStationNameW; LONG Status; ULONG Count, ByteCountW = (*pByteCount << 1);
/*
* If the caller supplied a buffer and the length is not 0, * allocate a corresponding (*2) buffer for UNICODE strings. */ if ( pWinStationName && ByteCountW ) { if ( !(pBuffer = LocalAlloc(0, ByteCountW)) ) return ( ERROR_NOT_ENOUGH_MEMORY ); }
/*
* Enumerate WinStations */ pWinStationNameW = pBuffer; Status = RegWinStationEnumerateW( hServer, pIndex, pEntries, pWinStationNameW, &ByteCountW );
/*
* Always /2 the resultant ByteCount (whether sucessful or not). */ *pByteCount = (ByteCountW >> 1);
/*
* If the function completed sucessfully and caller * (and stub) defined a buffer to copy into, perform conversion * from UNICODE to ANSI. Note: sucessful return may have copied * 0 items from registry (end of enumeration), denoted by *pEntries * == 0. */ if ( ((Status == ERROR_SUCCESS) || (Status == ERROR_NO_MORE_ITEMS)) && pWinStationNameW && pWinStationName ) {
for ( Count = *pEntries; Count; Count-- ) { UnicodeToAnsi( pWinStationName, sizeof(WINSTATIONNAMEA), pWinStationNameW ); (char*)pWinStationName += sizeof(WINSTATIONNAMEA); (char*)pWinStationNameW += sizeof(WINSTATIONNAMEW); } }
/*
* If we defined a buffer, free it now, then return the status * of the Reg...EnumerateW function call. */ if ( pBuffer ) LocalFree(pBuffer);
return ( Status ); }
/*******************************************************************************
* * RegWinStationEnumerateW (UNICODE) * * Returns a list of configured window stations in the registry. * * ENTRY: * hServer (input) * Handle to WinFrame Server * pIndex (input/output) * Specifies the subkey index for the \Citrix\WinStations subkeys in the * registry. Should be set to 0 for the initial call, and supplied * again (as modified by this function) for multi-call enumeration. * pEntries (input/output) * Points to a variable specifying the number of entries requested. * If the number requested is 0xFFFFFFFF, the function returns as * many entries as possible. When the function finishes successfully, * the variable pointed to by the pEntries parameter contains the * number of entries actually read. * pWinStationName (input) * Points to the buffer to receive the enumeration results, which are * returned as an array of WINSTATIONNAME structures. If this parameter * is NULL, then no data will be copied, but just an enumeration count * will be made. * pByteCount (input/output) * Points to a variable that specifies the size, in bytes, of the * pWinStationName parameter. If the buffer is too small to receive even * one entry, the function returns an error code (ERROR_OUTOFMEMORY) * and this variable receives the required size of the buffer for a * single subkey. When the function finishes sucessfully, the variable * pointed to by the pByteCount parameter contains the number of bytes * actually stored in pWinStationName. * * EXIT: * * "No Error" codes: * ERROR_SUCCESS - The enumeration completed as requested and there * are more WinStations subkeys (WINSTATIONNAMEs) to * be read. * ERROR_NO_MORE_ITEMS - The enumeration completed as requested and there * are no more WinStations subkeys (WINSTATIONNAMEs) * to be read. * * "Error" codes: * ERROR_OUTOFMEMORY - The pWinStationName buffer is too small for even * one entry. * ERROR_CANTOPEN - The Citrix\WinStations key can't be opened. * ******************************************************************************/
LONG WINAPI RegWinStationEnumerateW( HANDLE hServer, PULONG pIndex, PULONG pEntries, PWINSTATIONNAMEW pWinStationName, PULONG pByteCount ) { LONG Status; HKEY Handle; ULONG Count; ULONG i;
/*
* Get the number of names to return */ Count = pWinStationName ? min( *pByteCount / sizeof(WINSTATIONNAME), *pEntries ) : (ULONG) -1; *pEntries = *pByteCount = 0;
/*
* Make sure buffer is big enough for at least one name */ if ( Count == 0 ) { *pByteCount = sizeof(WINSTATIONNAME); return( ERROR_OUTOFMEMORY ); }
/*
* Open registry (LOCAL_MACHINE\....\Citrix\WinStations) */ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0, KEY_ENUMERATE_SUB_KEYS, &Handle ) != ERROR_SUCCESS ) { goto DefaultConsole; }
/*
* Get list of window stations */ for ( i = 0; i < Count; i++ ) { WINSTATIONNAME WinStationName;
if ( (Status = RegEnumKey(Handle, *pIndex, WinStationName, sizeof(WINSTATIONNAME)/sizeof(TCHAR) )) != ERROR_SUCCESS ) break;
/*
* If caller supplied a buffer, then copy the WinStationName * and increment the pointer and byte count. Always increment the * entry count and index for the next iteration. */ if ( pWinStationName ) { wcscpy( pWinStationName, WinStationName ); (char*)pWinStationName += sizeof(WINSTATIONNAME); *pByteCount += sizeof(WINSTATIONNAME); } (*pEntries)++; (*pIndex)++; }
/*
* Close registry */ RegCloseKey( Handle );
if ( Status == ERROR_NO_MORE_ITEMS ) { if ( (*pEntries == 0) && (*pIndex == 0) ) goto DefaultConsole; } return( Status );
/*
* We come here when there are no WinStations defined. * We return a default "Console" name (if pWinStationName isn't NULL). */ DefaultConsole: if ( pWinStationName ) wcscpy( pWinStationName, L"Console" ); *pEntries = 1; *pByteCount = sizeof(WINSTATIONNAME); return( ERROR_NO_MORE_ITEMS ); }
/*******************************************************************************
* * RegWinStationCreateA (ANSI stub) * * Creates a new WinStaton in the registry or updates an existing entry. * (See RegWinStationCreateW) * * ENTRY: * see RegWinStationCreateW * * EXIT: * see RegWinStationCreateW * ******************************************************************************/
LONG WINAPI RegWinStationCreateA( HANDLE hServer, PWINSTATIONNAMEA pWinStationName, BOOLEAN bCreate, PWINSTATIONCONFIG2A pWinStationConfig, ULONG WinStationConfigLength ) { WINSTATIONNAMEW WinStationNameW; WINSTATIONCONFIG2W WinStationConfig2W; int i;
/*
* Validate target buffer size. */ if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2A) ) return( ERROR_INSUFFICIENT_BUFFER );
/*
* Convert ANSI WinStationName to UNICODE. */ AnsiToUnicode( WinStationNameW, sizeof(WINSTATIONNAMEW), pWinStationName );
/*
* Copy WINSTATIONCONFIG2A elements to WINSTATIONCONFIG2W elements. */ WinStationCreateA2U( &(WinStationConfig2W.Create), &(pWinStationConfig->Create) ); for ( i=0; i<MAX_PDCONFIG; i++ ) { PdConfigA2U( &(WinStationConfig2W.Pd[i]), &(pWinStationConfig->Pd[i]) ); } WdConfigA2U( &(WinStationConfig2W.Wd), &(pWinStationConfig->Wd) ); CdConfigA2U( &(WinStationConfig2W.Cd), &(pWinStationConfig->Cd) ); WinStationConfigA2U( &(WinStationConfig2W.Config), &(pWinStationConfig->Config) );
/*
* Call RegWinStationCreateW & return it's status. */ return ( RegWinStationCreateW( hServer, WinStationNameW, bCreate, &WinStationConfig2W, sizeof(WinStationConfig2W)) ); }
/*******************************************************************************
* * RegWinStationCreateW (UNICODE) * * Creates a new WinStaton in the registry or updates an existing entry. * The state of the bCreate flag determines whether this function will * expect to create a new WinStation entry (bCreate == TRUE) or expects to * update an existing entry (bCreate == FALSE). * * ENTRY: * hServer (input) * Handle to WinFrame Server * pWinStationName (input) * Name of a new or exisiting window station in the registry. * bCreate (input) * TRUE if this is a creation of a new WinStation * FALSE if this is an update to an existing WinStation * pWinStationConfig (input) * Pointer to a WINSTATIONCONFIG2 structure containing configuration * information for the specified window station name. * WinStationConfigLength (input) * Specifies the length in bytes of the pWinStationConfig buffer. * * EXIT: * ERROR_SUCCESS - no error * * ERROR_INSUFFICIENT_BUFFER - pWinStationConfig buffer too small * ERROR_FILE_NOT_FOUND - can't open ...\Citrix\WinStations key * ERROR_CANNOT_MAKE - can't create WinStation key (registry problem) * ERROR_ALREADY_EXISTS - create; but WinStation key already present * ERROR_CANTOPEN - update; but WinStation key could not be opened * ******************************************************************************/
LONG WINAPI RegWinStationCreateW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName, BOOLEAN bCreate, PWINSTATIONCONFIG2W pWinStationConfig, ULONG WinStationConfigLength ) { HKEY Handle; HKEY Handle1; DWORD Disp;
/*
* Validate length of buffer */ if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2) ) return( ERROR_INSUFFICIENT_BUFFER );
/*
* Open registry (LOCAL_MACHINE\....\Citrix\WinStations). * If it doesn't exist, we attemp to create it. */ if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0, KEY_ALL_ACCESS, &Handle1 ) != ERROR_SUCCESS && RegCreateKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &Handle1, &Disp ) != ERROR_SUCCESS ) { return( ERROR_FILE_NOT_FOUND ); }
if ( bCreate ) {
/*
* Create requested: create a registry key for the specified * WinStation name. */ if ( RegCreateKeyEx( Handle1, pWinStationName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &Handle, &Disp ) != ERROR_SUCCESS ) { RegCloseKey( Handle1 ); return( ERROR_CANNOT_MAKE ); }
/*
* If an existing key was returned instead of a new one being * created, return error (don't update). */ if ( Disp != REG_CREATED_NEW_KEY ) { RegCloseKey( Handle1 ); RegCloseKey( Handle ); return( ERROR_ALREADY_EXISTS ); }
} else {
/*
* Update requested: open the registry key for the specified * WinStation name. */ if ( RegOpenKeyEx( Handle1, pWinStationName, 0, KEY_ALL_ACCESS, &Handle ) != ERROR_SUCCESS ) { RegCloseKey( Handle1 ); return( ERROR_CANTOPEN ); } }
RegCloseKey( Handle1 );
/*
* Save WINSTATIONCONFIG2 Structure */ CreateWinStaCreate( Handle, &pWinStationConfig->Create ); CreatePdConfig( bCreate, Handle, pWinStationConfig->Pd, MAX_PDCONFIG ); CreateWd( Handle, &pWinStationConfig->Wd ); CreateCd( Handle, &pWinStationConfig->Cd ); CreateConfig( Handle, &pWinStationConfig->Config );
/*
* Close registry handle */ RegCloseKey( Handle );
return( ERROR_SUCCESS ); }
/*******************************************************************************
* * RegWinStationQueryA (ANSI stub) * * Query configuration information of a window station in the registry. * * ENTRY: * see RegWinStationQueryW * * EXIT: * see RegWinStationQueryW * ******************************************************************************/
LONG WINAPI RegWinStationQueryA( HANDLE hServer, PWINSTATIONNAMEA pWinStationName, PWINSTATIONCONFIG2A pWinStationConfig, ULONG WinStationConfigLength, PULONG pReturnLength ) { WINSTATIONNAMEW WinStationNameW; WINSTATIONCONFIG2W WinStationConfig2W; LONG Status; ULONG ReturnLengthW; int i;
/*
* Validate length and zero-initialize the destination * WINSTATIONCONFIG2A structure. */ if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2A) ) return( ERROR_INSUFFICIENT_BUFFER ); memset(pWinStationConfig, 0, WinStationConfigLength);
/*
* Convert ANSI WinStationName to UNICODE. */ AnsiToUnicode( WinStationNameW, sizeof(WINSTATIONNAMEW), pWinStationName );
/*
* Query WinStation. */ if ( (Status = RegWinStationQueryW( hServer, WinStationNameW, &WinStationConfig2W, sizeof(WINSTATIONCONFIG2W), &ReturnLengthW)) != ERROR_SUCCESS ) return ( Status );
/*
* Copy WINSTATIONCONFIG2W elements to WINSTATIONCONFIG2A elements. */ WinStationCreateU2A( &(pWinStationConfig->Create), &(WinStationConfig2W.Create) ); for ( i=0; i<MAX_PDCONFIG; i++ ) { PdConfigU2A( &(pWinStationConfig->Pd[i]), &(WinStationConfig2W.Pd[i]) ); } WdConfigU2A( &(pWinStationConfig->Wd), &(WinStationConfig2W.Wd) ); CdConfigU2A( &(pWinStationConfig->Cd), &(WinStationConfig2W.Cd) ); WinStationConfigU2A( &(pWinStationConfig->Config), &(WinStationConfig2W.Config) );
*pReturnLength = sizeof(WINSTATIONCONFIG2A);
return( ERROR_SUCCESS ); }
/*******************************************************************************
* * * * RegWinStationQueryEx (UNICODE) * * USE THIS CALL if you are in TermSrv.DLL, since it will update the global policy object * * Same as RegWinStationQueryW with the excpetion that a pointer to a global policy object is passed in. * * Query configuration information of a window station in the registry. * * ENTRY: * hServer (input) * Handle to WinFrame Server * pMachinePolicy (input) * pointer to a gloabl machine policy struct * pWinStationName (input) * Name of an exisiting window station in the registry. * pWinStationConfig (input) * Pointer to a WINSTATIONCONFIG2 structure that will receive * information about the specified window station name. * WinStationConfigLength (input) * Specifies the length in bytes of the pWinStationConfig buffer. * pReturnLength (output) * Receives the number of bytes placed in the pWinStationConfig buffer. * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG WINAPI RegWinStationQueryEx( HANDLE hServer, PPOLICY_TS_MACHINE pMachinePolicy, PWINSTATIONNAMEW pWinStationName, PWINSTATIONCONFIG2W pWinStationConfig, ULONG WinStationConfigLength, PULONG pReturnLength, BOOLEAN bPerformMerger) { LONG Status; HKEY Handle; ULONG Count;
/*
* Validate length and zero-initialize the destination * WINSTATIONCONFIG2W buffer. */ if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2) ) return( ERROR_INSUFFICIENT_BUFFER ); memset(pWinStationConfig, 0, WinStationConfigLength);
/*
* Open registry */ Status = _RegOpenWinStation( pWinStationName, KEY_READ, &Handle ); if ( Status ) Handle = 0;
/*
* Query WINSTATIONCONFIG2 Structure */ QueryWinStaCreate( Handle, &pWinStationConfig->Create ); Count = MAX_PDCONFIG; QueryPdConfig( Handle, pWinStationConfig->Pd, &Count ); QueryWd( Handle, &pWinStationConfig->Wd ); QueryCd( Handle, &pWinStationConfig->Cd );
// This will populate the winstation's userconfig data with machine's version of that data.
QueryConfig( Handle, &pWinStationConfig->Config );
// Since we want to co-exist with the legacy path thru TSCC, we continue to call QueryConfig()
// as we have done above, however, we follow up with a call that get's data from the group policy
// tree, and then overrides the existing data (aquired above) by the specific data from group policy.
RegGetMachinePolicy( pMachinePolicy );
if (bPerformMerger) RegMergeMachinePolicy( pMachinePolicy, &pWinStationConfig->Config.User , &pWinStationConfig->Create );
/*
* Close registry */ if ( Status == ERROR_SUCCESS ) RegCloseKey( Handle );
*pReturnLength = sizeof(WINSTATIONCONFIG2);
return( ERROR_SUCCESS ); }
/*******************************************************************************
* * RegWinStationQueryW (UNICODE) * * Query configuration information of a window station in the registry. * * ENTRY: * hServer (input) * Handle to WinFrame Server * pWinStationName (input) * Name of an exisiting window station in the registry. * pWinStationConfig (input) * Pointer to a WINSTATIONCONFIG2 structure that will receive * information about the specified window station name. * WinStationConfigLength (input) * Specifies the length in bytes of the pWinStationConfig buffer. * pReturnLength (output) * Receives the number of bytes placed in the pWinStationConfig buffer. * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG WINAPI RegWinStationQueryW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName, PWINSTATIONCONFIG2W pWinStationConfig, ULONG WinStationConfigLength, PULONG pReturnLength ) { LONG Status; HKEY Handle; ULONG Count; POLICY_TS_MACHINE MachinePolicy;
/*
* Validate length and zero-initialize the destination * WINSTATIONCONFIG2W buffer. */ if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2) ) return( ERROR_INSUFFICIENT_BUFFER ); memset(pWinStationConfig, 0, WinStationConfigLength);
/*
* Open registry */ Status = _RegOpenWinStation( pWinStationName, KEY_READ, &Handle ); if ( Status ) Handle = 0;
/*
* Query WINSTATIONCONFIG2 Structure */ QueryWinStaCreate( Handle, &pWinStationConfig->Create ); Count = MAX_PDCONFIG; QueryPdConfig( Handle, pWinStationConfig->Pd, &Count ); QueryWd( Handle, &pWinStationConfig->Wd ); QueryCd( Handle, &pWinStationConfig->Cd );
// This will populate the winstation's userconfig data with machine's version of that data.
QueryConfig( Handle, &pWinStationConfig->Config );
// Since we want to co-exist with the legacy path thru TSCC, we continue to call QueryConfig()
// as we have done above, however, we follow up with a call that get's data from the group policy
// tree, and then overrides the existing data (aquired above) by the specific data from group policy.
RegGetMachinePolicy( & MachinePolicy ); RegMergeMachinePolicy( & MachinePolicy, &pWinStationConfig->Config.User , &pWinStationConfig->Create );
/*
* Close registry */ if ( Status == ERROR_SUCCESS ) RegCloseKey( Handle );
*pReturnLength = sizeof(WINSTATIONCONFIG2);
return( ERROR_SUCCESS ); }
/*******************************************************************************
* * RegConsoleShadowQueryA (ANSI stub) * * Query configuration information for the console shadow in the registry. * * ENTRY: * see RegConsoleShadowQueryW * * EXIT: * see RegConsoleShadowQueryW * ******************************************************************************/
LONG WINAPI RegConsoleShadowQueryA( HANDLE hServer, PWINSTATIONNAMEA pWinStationName, PWDPREFIXA pWdPrefixName, PWINSTATIONCONFIG2A pWinStationConfig, ULONG WinStationConfigLength, PULONG pReturnLength ) { WINSTATIONNAMEW WinStationNameW; WDPREFIXW WdPrefixNameW; WINSTATIONCONFIG2W WinStationConfig2W; LONG Status; ULONG ReturnLengthW; int i;
/*
* Validate length and zero-initialize the destination * WINSTATIONCONFIG2A structure. */ if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2A) ) return( ERROR_INSUFFICIENT_BUFFER );
/*
* Convert ANSI WinStationName and prefix name to UNICODE. */ AnsiToUnicode( WinStationNameW, sizeof(WINSTATIONNAMEW), pWinStationName ); AnsiToUnicode( WdPrefixNameW, sizeof(WDPREFIXW), pWdPrefixName );
/*
* Query WinStation. */ if ( (Status = RegConsoleShadowQueryW( hServer, WinStationNameW, WdPrefixNameW, &WinStationConfig2W, sizeof(WINSTATIONCONFIG2W), &ReturnLengthW)) != ERROR_SUCCESS ) return ( Status );
/*
* Copy WINSTATIONCONFIG2W elements to WINSTATIONCONFIG2A elements. */ for ( i=0; i<MAX_PDCONFIG; i++ ) { PdConfigU2A( &(pWinStationConfig->Pd[i]), &(WinStationConfig2W.Pd[i]) ); } WdConfigU2A( &(pWinStationConfig->Wd), &(WinStationConfig2W.Wd) ); CdConfigU2A( &(pWinStationConfig->Cd), &(WinStationConfig2W.Cd) );
*pReturnLength = sizeof(WINSTATIONCONFIG2A);
return( ERROR_SUCCESS ); }
/*******************************************************************************
* * RegConsoleShadowQueryW (UNICODE) * * Query configuration information for the console shadow in the registry. * * ENTRY: * hServer (input) * Handle to WinFrame Server * pWinStationName (input) * Name of an exisiting window station in the registry. * pWdPrefixName (input) * Name of the Wd prefix used to point to the sub-winstation key. * pWinStationConfig (input) * Pointer to a WINSTATIONCONFIG2 structure that will receive * information about the specified window station name. * WinStationConfigLength (input) * Specifies the length in bytes of the pWinStationConfig buffer. * pReturnLength (output) * Receives the number of bytes placed in the pWinStationConfig buffer. * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG WINAPI RegConsoleShadowQueryW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName, PWDPREFIXW pWdPrefixName, PWINSTATIONCONFIG2W pWinStationConfig, ULONG WinStationConfigLength, PULONG pReturnLength ) { LONG Status; LONG lLength; HKEY Handle; ULONG Count; WCHAR szRegName[ WINSTATIONNAME_LENGTH + WDPREFIX_LENGTH + 2 ]; /*
* Validate length and zero-initialize the destination * WINSTATIONCONFIG2W buffer. */ if ( WinStationConfigLength < sizeof(WINSTATIONCONFIG2) ) return( ERROR_INSUFFICIENT_BUFFER );
/*
* Open registry */ wcsncpy( szRegName, pWinStationName, sizeof(szRegName)/sizeof(WCHAR) - 1 ); szRegName[sizeof(szRegName)/sizeof(WCHAR) - 1] = 0; // terminate the string even if pWinStationName is longer than the buffer
lLength = wcslen( szRegName );
if ( sizeof(szRegName)/sizeof(WCHAR) > ( lLength + 1 + wcslen( pWdPrefixName ) ) ) {
wcsncat( szRegName, L"\\", sizeof(szRegName)/sizeof(WCHAR) - lLength - 1 ); wcsncat( szRegName, pWdPrefixName, sizeof(szRegName)/sizeof(WCHAR) - lLength - 2 );
} else { return ERROR_INVALID_PARAMETER; }
Status = _RegOpenWinStation( szRegName, KEY_READ, &Handle );
if ( Status ) Handle = 0;
/*
* Query WINSTATIONCONFIG2 Structure */ Count = MAX_PDCONFIG; QueryPdConfig( Handle, pWinStationConfig->Pd, &Count ); QueryWd( Handle, &pWinStationConfig->Wd ); QueryCd( Handle, &pWinStationConfig->Cd );
/*
* Close registry */ if ( Status == ERROR_SUCCESS ) RegCloseKey( Handle );
*pReturnLength = sizeof(WINSTATIONCONFIG2);
return( ERROR_SUCCESS ); }
/*******************************************************************************
* * RegWinStationDeleteA (ANSI stub) * * Deletes a window station from the registry. * * ENTRY: * see RegWinStationDeleteW * * EXIT: * see RegWinStationDeleteW * ******************************************************************************/
LONG WINAPI RegWinStationDeleteA( HANDLE hServer, PWINSTATIONNAMEA pWinStationName ) { WINSTATIONNAMEW WinStationNameW;
AnsiToUnicode( WinStationNameW, sizeof(WinStationNameW), pWinStationName );
return ( RegWinStationDeleteW ( hServer, WinStationNameW ) ); }
/*******************************************************************************
* * RegWinStationDeleteW (UNICODE) * * Deletes a window station from the registry. * * ENTRY: * hServer (input) * Handle to WinFrame Server * pWinStationName (input) * Name of a window station to delete from the registry. * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG WINAPI RegWinStationDeleteW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName ) { LONG Status; HKEY Handle1, Handle2;
/*
* Open registry (LOCAL_MACHINE\....\Citrix\WinStations). */ if ( (Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0, KEY_ALL_ACCESS, &Handle1 ) != ERROR_SUCCESS) ) { return( Status ); }
/*
* Open the registry key for the specified WinStation name. */ if ( (Status = RegOpenKeyEx( Handle1, pWinStationName, 0, KEY_ALL_ACCESS, &Handle2 ) != ERROR_SUCCESS) ) { RegCloseKey( Handle1 ); return( Status ); } SetWallPaperDisabled( Handle2, FALSE );
/*
* Close the WinStation key handle just opened (so we can delete key), * delete the key, and close the Citrix registry handle. */ RegCloseKey( Handle2 ); Status = RegDeleteKey( Handle1, pWinStationName ); RegCloseKey( Handle1 );
return( Status ); }
/*******************************************************************************
* * RegWinStationSetSecurityA (ANSI stub) * * Sets security info for the specified WinStation. * * ENTRY: * see RegWinStationSetSecurityW * * EXIT: * see RegWinStationSetSecurityW * ******************************************************************************/
LONG WINAPI RegWinStationSetSecurityA( HANDLE hServer, PWINSTATIONNAMEA pWinStationName, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Length ) { WINSTATIONNAMEW WinStationNameW;
AnsiToUnicode( WinStationNameW, sizeof(WinStationNameW), pWinStationName );
return ( RegWinStationSetSecurityW( hServer, WinStationNameW, SecurityDescriptor, Length ) ); }
/*******************************************************************************
* * RegWinStationSetSecurityW (UNICODE) * * Sets security info for the specified WinStation. * * ENTRY: * hServer (input) * Handle to WinFrame Server * pWinStationName (input) * Name of a window station to set security for. * pSecurityDescriptor (input) * Pointer to Security Descriptor to save * Length (input) * Length of SecurityDescriptor above * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG WINAPI RegWinStationSetSecurityW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Length ) { HKEY Handle; ULONG SrLength; PSECURITY_DESCRIPTOR SrSecurityDescriptor; LONG Error; NTSTATUS Status;
/*
* Open registry */ if ( Error = _RegOpenWinStation( pWinStationName, KEY_ALL_ACCESS, &Handle ) ) return( Error );
/*
* Determine buffer length needed to convert SD to self-relative format. */ SrLength = 0; Status = RtlMakeSelfRelativeSD( SecurityDescriptor, NULL, &SrLength ); if ( Status != STATUS_BUFFER_TOO_SMALL ) { RegCloseKey( Handle ); return( RtlNtStatusToDosError( Status ) ); }
/*
* Allocate buffer for self-relative SD. */ SrSecurityDescriptor = LocalAlloc( 0, SrLength ); if ( SrSecurityDescriptor == NULL ) { RegCloseKey( Handle ); return( ERROR_NOT_ENOUGH_MEMORY ); }
/*
* Now convert SD to self-relative format. */ Status = RtlMakeSelfRelativeSD( SecurityDescriptor, SrSecurityDescriptor, &SrLength ); if ( !NT_SUCCESS( Status ) ) { LocalFree( SrSecurityDescriptor ); RegCloseKey( Handle ); return( RtlNtStatusToDosError( Status ) ); }
/*
* Save the security data */ Error = RegSetValueEx( Handle, L"Security", 0, REG_BINARY, (BYTE *)SrSecurityDescriptor, SrLength );
/*
* Free memory used for Self-relative Security Descriptor */ LocalFree( SrSecurityDescriptor );
/*
* Close registry */ RegCloseKey( Handle );
return( Error ); }
/*******************************************************************************
* * RegWinStationQuerySecurityA (ANSI stub) * * Query security info for the specified WinStation. * * ENTRY: * see RegWinStationQuerySecurityW * * EXIT: * see RegWinStationQuerySecurityW * ******************************************************************************/
LONG WINAPI RegWinStationQuerySecurityA( HANDLE hServer, PWINSTATIONNAMEA pWinStationName, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Length, PULONG ReturnLength ) { WINSTATIONNAMEW WinStationNameW;
AnsiToUnicode( WinStationNameW, sizeof(WinStationNameW), pWinStationName );
return ( RegWinStationQuerySecurityW( hServer, WinStationNameW, SecurityDescriptor, Length, ReturnLength ) ); }
/*******************************************************************************
* * RegWinStationQuerySecurityW (UNICODE) * * Query security info for the specified WinStation. * * ENTRY: * hServer (input) * Handle to WinFrame Server * pWinStationName (input) * Name of a window station to query security for. * pSecurityDescriptor (output) * Pointer to location to return SecurityDescriptor. * Length (input) * Length of SecurityDescriptor buffer. * ReturnLength (output) * Pointer to location to return length of SecurityDescriptor returned. * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG WINAPI RegWinStationQuerySecurityW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Length, PULONG ReturnLength ) { HKEY Handle; LONG Error;
/*
* Open registry */ if ( Error = _RegOpenWinStation( pWinStationName, KEY_READ, &Handle ) ) return( Error );
/*
* Call RegGetWinStationSecurity() to do all the work */ Error = _RegGetWinStationSecurity( Handle, L"Security", SecurityDescriptor, Length, ReturnLength );
RegCloseKey( Handle ); return( Error ); }
/*******************************************************************************
* * RegWinStationQueryDefaultSecurity * * Query default WinStation security. * * ENTRY: * hServer (input) * Handle to WinFrame Server * pSecurityDescriptor (output) * Pointer to location to return SecurityDescriptor. * Length (input) * Length of SecurityDescriptor buffer. * ReturnLength (output) * Pointer to location to return length of SecurityDescriptor returned. * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG WINAPI RegWinStationQueryDefaultSecurity( HANDLE hServer, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Length, PULONG ReturnLength ) { HKEY Handle; LONG Error;
/*
* Open registry */ if ( Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0, KEY_READ, &Handle ) ) return( Error );
/*
* Call RegGetWinStationSecurity() to do all the work */ Error = _RegGetWinStationSecurity( Handle, L"DefaultSecurity", SecurityDescriptor, Length, ReturnLength );
RegCloseKey( Handle ); return( Error ); }
/*******************************************************************************
* * RegWinStationSetNumValueW (UNICODE) * * Set numeric value in WinStation registry configuration * * ENTRY: * hServer (input) * Handle to WinFrame Server * pWinStationName (input) * Name of a window station to modify from the registry. * pValueName (input) * name of registry value to set * ValueData (input) * data (DWORD) for registry value to set * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG WINAPI RegWinStationSetNumValueW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName, LPWSTR pValueName, ULONG ValueData ) { HKEY Handle; LONG Error;
/*
* Open registry */ if ( Error = _RegOpenWinStation( pWinStationName, KEY_ALL_ACCESS, &Handle ) ) return( Error );
/*
* Set the numeric value */ Error = RegSetValueEx( Handle, pValueName, 0, REG_DWORD, (BYTE *)&ValueData, sizeof(DWORD) );
/*
* Close registry */ RegCloseKey( Handle );
return( Error ); }
/*******************************************************************************
* * RegWinStationQueryNumValueW (UNICODE) * * Query numeric value from WinStation registry configuration * * ENTRY: * hServer (input) * Handle to WinFrame Server * pWinStationName (input) * Name of a window station to modify from the registry. * pValueName (input) * name of registry value to set * pValueData (output) * address to return data (DWORD) value from registry * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG WINAPI RegWinStationQueryNumValueW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName, LPWSTR pValueName, PULONG pValueData ) { DWORD ValueSize = sizeof(DWORD); DWORD ValueType; HKEY Handle; LONG Error;
/*
* Open registry */ if ( Error = _RegOpenWinStation( pWinStationName, KEY_READ, &Handle ) ) return( Error );
/*
* Query the numeric value */ Error = RegQueryValueEx( Handle, pValueName, NULL, &ValueType, (LPBYTE) pValueData, &ValueSize );
/*
* Close registry */ RegCloseKey( Handle );
return( Error ); }
/*******************************************************************************
* * RegWinStationQueryValueW (UNICODE) * * Query value from WinStation registry configuration * * ENTRY: * hServer (input) * Handle to WinFrame Server * pWinStationName (input) * Name of a window station to modify from the registry. * pValueName (input) * name of registry value to set * pValueData (output) * address to return data (DWORD) value from registry * ValueSize (input) * size of value buffer * pValueSize (input) * actual value size * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG WINAPI RegWinStationQueryValueW( HANDLE hServer, PWINSTATIONNAMEW pWinStationName, LPWSTR pValueName, PVOID pValueData, ULONG ValueSize, PULONG pValueSize ) { DWORD ValueType; HKEY Handle; LONG Error;
*pValueSize = ValueSize;
/*
* Open registry */ if ( Error = _RegOpenWinStation( pWinStationName, KEY_READ, &Handle ) ) return( Error );
/*
* Query the numeric value */ Error = RegQueryValueEx( Handle, pValueName, NULL, &ValueType, (LPBYTE) pValueData, pValueSize );
/*
* Close registry */ RegCloseKey( Handle );
return( Error ); }
/*******************************************************************************
* * -- private routine -- * * _RegOpenWinStation * * open registry of specified winstation * * NOTE: handle must be closed with "RegCloseKey" * * ENTRY: * hServer (input) * Handle to WinFrame Server * pWinStationName (input) * Name of a window station to modify from the registry. * samDesired (input) * REGSAM access level for registry open. * pHandle (output) * address to return handle * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG _RegOpenWinStation( PWINSTATIONNAMEW pWinStationName, REGSAM samDesired, HKEY * pHandle )
{ HKEY Handle1; LONG Error;
/*
* Open registry (LOCAL_MACHINE\....\Citrix\WinStations). */ if ( (Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0, samDesired, &Handle1 ) != ERROR_SUCCESS) ) { return( Error ); }
/*
* Open the registry key for the specified WinStation name. */ Error = RegOpenKeyEx( Handle1, pWinStationName, 0, samDesired, pHandle);
RegCloseKey( Handle1 );
return( Error ); }
/*******************************************************************************
* * -- private routine -- * * _RegGetWinStationSecurity * * Query the security descriptor from the specified registry key. * * ENTRY: * Handle (input) * Open registry key handle. * ValueName (input) * Name of security value. * pSecurityDescriptor (output) * Pointer to location to return SecurityDescriptor. * Length (input) * Length of SecurityDescriptor buffer. * ReturnLength (output) * Pointer to location to return length of SecurityDescriptor returned. * * EXIT: * ERROR_SUCCESS - no error * otherwise: the error code * ******************************************************************************/
LONG _RegGetWinStationSecurity( HKEY Handle, LPWSTR ValueName, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Length, PULONG ReturnLength ) { DWORD ValueType; DWORD SrLength; ULONG SdSize, DaclSize, SaclSize, OwnerSize, GroupSize; PSECURITY_DESCRIPTOR SrSecurityDescriptor; PACL pDacl, pSacl; PSID pOwner, pGroup; LONG Error; NTSTATUS Status;
/*
* Query the length of the Security value */ SrLength = 0; if ( Error = RegQueryValueEx( Handle, ValueName, NULL, &ValueType, NULL, &SrLength ) ) { return( Error ); }
/*
* Return error if not correct data type */ if ( ValueType != REG_BINARY ) { return( ERROR_FILE_NOT_FOUND ); }
/*
* Allocate a buffer to read the Security info and read it */ SrSecurityDescriptor = LocalAlloc( 0, SrLength ); if ( SrSecurityDescriptor == NULL ) { return( ERROR_NOT_ENOUGH_MEMORY ); } if ( Error = RegQueryValueEx( Handle, ValueName, NULL, &ValueType, SrSecurityDescriptor, &SrLength ) ) { LocalFree( SrSecurityDescriptor ); return( Error ); }
/*
* Determine amount of space required to convert SD from * self-relative format to absolute format. */ SdSize = DaclSize = SaclSize = OwnerSize = GroupSize = 0; Status = RtlSelfRelativeToAbsoluteSD( SrSecurityDescriptor, NULL, &SdSize, NULL, &DaclSize, NULL, &SaclSize, NULL, &OwnerSize, NULL, &GroupSize ); if ( Status != STATUS_BUFFER_TOO_SMALL ) { LocalFree( SrSecurityDescriptor ); return( RtlNtStatusToDosError( Status ) ); } *ReturnLength = SdSize + DaclSize + SaclSize + OwnerSize + GroupSize;
/*
* If required size is greater than callers buffer size, then return */ if ( *ReturnLength > Length ) { LocalFree( SrSecurityDescriptor ); return( ERROR_INSUFFICIENT_BUFFER ); }
pDacl = (PACL)((PCHAR)SecurityDescriptor + SdSize); pSacl = (PACL)((PCHAR)pDacl + DaclSize); pOwner = (PSID)((PCHAR)pSacl + SaclSize); pGroup = (PSID)((PCHAR)pOwner + OwnerSize);
/*
* Now convert self-relative SD to absolute format. */ Status = RtlSelfRelativeToAbsoluteSD( SrSecurityDescriptor, SecurityDescriptor, &SdSize, pDacl, &DaclSize, pSacl, &SaclSize, pOwner, &OwnerSize, pGroup, &GroupSize ); if ( !NT_SUCCESS( Status ) ) Error = RtlNtStatusToDosError( Status );
/*
* Free memory used for Self-relative Security Descriptor */ LocalFree( SrSecurityDescriptor );
return( Error ); }
|