WindowsXP-SP1/termsrv/regapi/query.c

1388 lines
40 KiB
C

/*************************************************************************
*
* query.c
*
* Query Register APIs
*
* Copyright (c) 1998 Microsoft Corporation
*
*
*************************************************************************/
/*
* Includes
*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <ntddkbd.h>
#include <ntddmou.h>
#include <winstaw.h>
#include <regapi.h>
/*
* Procedures defined
*/
VOID QueryWinStaCreate( HKEY, PWINSTATIONCREATE );
VOID QueryUserConfig( HKEY, PUSERCONFIG );
VOID QueryConfig( HKEY, PWINSTATIONCONFIG );
VOID QueryNetwork( HKEY, PNETWORKCONFIG );
VOID QueryNasi( HKEY, PNASICONFIG );
VOID QueryAsync( HKEY, PASYNCCONFIG );
VOID QueryOemTd( HKEY, POEMTDCONFIG );
VOID QueryFlow( HKEY, PFLOWCONTROLCONFIG );
VOID QueryConnect( HKEY, PCONNECTCONFIG );
VOID QueryCd( HKEY, PCDCONFIG );
VOID QueryWd( HKEY, PWDCONFIG );
VOID QueryPdConfig( HKEY, PPDCONFIG, PULONG );
VOID QueryPdConfig2( HKEY, PPDCONFIG2, ULONG );
VOID QueryPdConfig3( HKEY, PPDCONFIG3, ULONG );
VOID QueryPdParams( HKEY, SDCLASS, PPDPARAMS );
BOOLEAN WINAPI RegBuildNumberQuery( PULONG );
BOOLEAN RegQueryOEMId( PBYTE, ULONG );
BOOLEAN WINAPI RegGetCitrixVersion(WCHAR *, PULONG);
BOOLEAN IsWallPaperDisabled( HKEY );
/*
* procedures used
*/
DWORD GetNumValue( HKEY, LPWSTR, DWORD );
DWORD GetNumValueEx( HKEY, LPWSTR, DWORD, DWORD );
LONG GetStringValue( HKEY, LPWSTR, LPWSTR, LPWSTR, DWORD );
LONG GetStringValueEx( HKEY, LPWSTR, DWORD, LPWSTR, LPWSTR, DWORD );
VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
/*******************************************************************************
*
* QueryWinStaCreate
*
* query WINSTATIONCREATE structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pCreate (output)
* address to return WINSTATIONCREATE structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryWinStaCreate( HKEY Handle,
PWINSTATIONCREATE pCreate )
{
pCreate->fEnableWinStation = (BOOLEAN) GetNumValue( Handle,
WIN_ENABLEWINSTATION,
TRUE );
pCreate->MaxInstanceCount = GetNumValue( Handle,
WIN_MAXINSTANCECOUNT,
1 );
}
/*******************************************************************************
*
* QueryUserConfig
*
* query USERCONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pUser (input)
* pointer to USERCONFIG structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryUserConfig( HKEY Handle,
PUSERCONFIG pUser )
{
UCHAR seed;
UNICODE_STRING UnicodePassword;
WCHAR encPassword[ PASSWORD_LENGTH + 2 ];
pUser->fInheritAutoLogon =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITAUTOLOGON, TRUE );
pUser->fInheritResetBroken =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITRESETBROKEN, TRUE );
pUser->fInheritReconnectSame =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITRECONNECTSAME, TRUE );
pUser->fInheritInitialProgram =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITINITIALPROGRAM, TRUE );
pUser->fInheritCallback =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITCALLBACK, FALSE );
pUser->fInheritCallbackNumber =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITCALLBACKNUMBER, TRUE );
pUser->fInheritShadow =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITSHADOW, TRUE );
pUser->fInheritMaxSessionTime =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITMAXSESSIONTIME, TRUE );
pUser->fInheritMaxDisconnectionTime =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITMAXDISCONNECTIONTIME, TRUE );
pUser->fInheritMaxIdleTime =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITMAXIDLETIME, TRUE );
pUser->fInheritAutoClient =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITAUTOCLIENT, TRUE );
pUser->fInheritSecurity =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITSECURITY, FALSE );
//NA 2/23/01
pUser->fInheritColorDepth =
(BOOLEAN) GetNumValue( Handle, WIN_INHERITCOLORDEPTH, TRUE );
pUser->fPromptForPassword =
(BOOLEAN) GetNumValue( Handle, WIN_PROMPTFORPASSWORD, FALSE );
pUser->fResetBroken =
(BOOLEAN) GetNumValue( Handle, WIN_RESETBROKEN, FALSE );
pUser->fReconnectSame =
(BOOLEAN) GetNumValue( Handle, WIN_RECONNECTSAME, FALSE );
pUser->fLogonDisabled =
(BOOLEAN) GetNumValue( Handle, WIN_LOGONDISABLED, FALSE );
pUser->fAutoClientDrives =
(BOOLEAN) GetNumValue( Handle, WIN_AUTOCLIENTDRIVES, TRUE );
pUser->fAutoClientLpts =
(BOOLEAN) GetNumValue( Handle, WIN_AUTOCLIENTLPTS, TRUE );
pUser->fForceClientLptDef =
(BOOLEAN) GetNumValue( Handle, WIN_FORCECLIENTLPTDEF, TRUE );
pUser->fDisableEncryption =
(BOOLEAN) GetNumValue( Handle, WIN_DISABLEENCRYPTION, TRUE );
pUser->fHomeDirectoryMapRoot =
(BOOLEAN) GetNumValue( Handle, WIN_HOMEDIRECTORYMAPROOT, FALSE );
pUser->fUseDefaultGina =
(BOOLEAN) GetNumValue( Handle, WIN_USEDEFAULTGINA, FALSE );
pUser->fDisableCpm =
(BOOLEAN) GetNumValue( Handle, WIN_DISABLECPM, FALSE );
pUser->fDisableCdm =
(BOOLEAN) GetNumValue( Handle, WIN_DISABLECDM, FALSE );
pUser->fDisableCcm =
(BOOLEAN) GetNumValue( Handle, WIN_DISABLECCM, FALSE );
pUser->fDisableLPT =
(BOOLEAN) GetNumValue( Handle, WIN_DISABLELPT, FALSE );
pUser->fDisableClip =
(BOOLEAN) GetNumValue( Handle, WIN_DISABLECLIP, FALSE );
pUser->fDisableExe =
(BOOLEAN) GetNumValue( Handle, WIN_DISABLEEXE, FALSE );
pUser->fDisableCam =
(BOOLEAN) GetNumValue( Handle, WIN_DISABLECAM, FALSE );
GetStringValue( Handle, WIN_USERNAME, NULL, pUser->UserName,
USERNAME_LENGTH + 1 );
GetStringValue( Handle, WIN_DOMAIN, NULL, pUser->Domain,
DOMAIN_LENGTH + 1 );
// pull encrypted password out of registry
GetStringValue( Handle, WIN_PASSWORD, NULL, encPassword,
PASSWORD_LENGTH + 2 );
// check for password if there is one then decrypt it
if ( wcslen( encPassword ) ) {
// generate unicode string
RtlInitUnicodeString( &UnicodePassword, &encPassword[1] );
// decrypt password in place
seed = (UCHAR) encPassword[0];
RtlRunDecodeUnicodeString( seed, &UnicodePassword );
// pull clear text password
RtlMoveMemory( pUser->Password, &encPassword[1], sizeof(pUser->Password) );
}
else {
// set to null
pUser->Password[0] = (WCHAR) NULL;
}
GetStringValue( Handle, WIN_WORKDIRECTORY, NULL, pUser->WorkDirectory,
DIRECTORY_LENGTH + 1 );
GetStringValue( Handle, WIN_INITIALPROGRAM, NULL, pUser->InitialProgram,
INITIALPROGRAM_LENGTH + 1 );
GetStringValue( Handle, WIN_CALLBACKNUMBER, NULL, pUser->CallbackNumber,
CALLBACK_LENGTH + 1 );
pUser->Callback = GetNumValue( Handle, WIN_CALLBACK, Callback_Disable );
pUser->Shadow = GetNumValue( Handle, WIN_SHADOW, Shadow_EnableInputNotify );
pUser->MaxConnectionTime = GetNumValue( Handle, WIN_MAXCONNECTIONTIME, 0 );
pUser->MaxDisconnectionTime = GetNumValue( Handle,
WIN_MAXDISCONNECTIONTIME, 0 );
pUser->MaxIdleTime = GetNumValue( Handle, WIN_MAXIDLETIME, 0 );
pUser->KeyboardLayout = GetNumValue( Handle, WIN_KEYBOARDLAYOUT, 0 );
pUser->MinEncryptionLevel = (BYTE) GetNumValue( Handle, WIN_MINENCRYPTIONLEVEL, 1 );
pUser->fWallPaperDisabled = (BOOLEAN) IsWallPaperDisabled( Handle );
GetStringValue( Handle, WIN_NWLOGONSERVER, NULL, pUser->NWLogonServer,
NASIFILESERVER_LENGTH + 1 );
GetStringValue( Handle, WIN_WFPROFILEPATH, NULL, pUser->WFProfilePath,
DIRECTORY_LENGTH + 1 );
GetStringValue( Handle, WIN_WFHOMEDIR, NULL, pUser->WFHomeDir,
DIRECTORY_LENGTH + 1 );
GetStringValue( Handle, WIN_WFHOMEDIRDRIVE, NULL, pUser->WFHomeDirDrive,
4 );
pUser->ColorDepth = GetNumValue( Handle, POLICY_TS_COLOR_DEPTH, TS_8BPP_SUPPORT );
}
/*******************************************************************************
*
* QueryConfig
*
* query WINSTATIONCONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pConfig (output)
* address to return WINSTATIONCONFIG structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryConfig( HKEY Handle,
PWINSTATIONCONFIG pConfig )
{
GetStringValue( Handle, WIN_COMMENT, NULL, pConfig->Comment,
WINSTATIONCOMMENT_LENGTH + 1 );
QueryUserConfig( Handle, &pConfig->User );
(void) RegQueryOEMId( pConfig->OEMId, sizeof(pConfig->OEMId) );
}
/*******************************************************************************
*
* QueryNetwork
*
* Query NETWORKCONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pNetwork (output)
* address to return NETWORKCONFIG structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryNetwork( HKEY Handle,
PNETWORKCONFIG pNetwork )
{
pNetwork->LanAdapter = GetNumValue( Handle, WIN_LANADAPTER, 0 );
}
/*******************************************************************************
*
* QueryNasi
*
* Query NASICONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pNasi (output)
* address to return NASICONFIG structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryNasi( HKEY Handle,
PNASICONFIG pNasi )
{
UCHAR seed;
UNICODE_STRING UnicodePassword;
WCHAR encPassword[ NASIPASSWORD_LENGTH + 2 ];
// pull encrypted password out of registry
GetStringValue( Handle, WIN_NASIPASSWORD, NULL, encPassword,
NASIPASSWORD_LENGTH + 1 );
// check for password if there is one then decrypt it
if ( wcslen( encPassword ) ) {
// generate unicode string
RtlInitUnicodeString( &UnicodePassword, &encPassword[1] );
// decrypt password in place
seed = (UCHAR) encPassword[0];
RtlRunDecodeUnicodeString( seed, &UnicodePassword );
// pull clear text password
RtlMoveMemory( pNasi->PassWord, &encPassword[1], sizeof(pNasi->PassWord) );
}
else {
// set to null
pNasi->PassWord[0] = (WCHAR) NULL;
}
GetStringValue( Handle, WIN_NASISPECIFICNAME, NULL, pNasi->SpecificName,
NASISPECIFICNAME_LENGTH + 1 );
GetStringValue( Handle, WIN_NASIUSERNAME, NULL, pNasi->UserName,
NASIUSERNAME_LENGTH + 1 );
GetStringValue( Handle, WIN_NASISESSIONNAME, NULL, pNasi->SessionName,
NASISESSIONNAME_LENGTH + 1 );
GetStringValue( Handle, WIN_NASIFILESERVER, NULL, pNasi->FileServer,
NASIFILESERVER_LENGTH + 1 );
pNasi->GlobalSession = (BOOLEAN)GetNumValue( Handle, WIN_NASIGLOBALSESSION, 0 );
}
/*******************************************************************************
*
* QueryAsync
*
* query ASYNCCONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pAsync (output)
* address to return ASYNCCONFIG structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryAsync( HKEY Handle,
PASYNCCONFIG pAsync )
{
GetStringValue( Handle, WIN_DEVICENAME, NULL, pAsync->DeviceName,
DEVICENAME_LENGTH + 1 );
GetStringValue( Handle, WIN_MODEMNAME, NULL, pAsync->ModemName,
MODEMNAME_LENGTH + 1 );
pAsync->BaudRate = GetNumValue( Handle, WIN_BAUDRATE, 9600 );
pAsync->Parity = GetNumValue( Handle, WIN_PARITY, NOPARITY );
pAsync->StopBits = GetNumValue( Handle, WIN_STOPBITS, ONESTOPBIT );
pAsync->ByteSize = GetNumValue( Handle, WIN_BYTESIZE, 8 );
pAsync->fEnableDsrSensitivity = (BOOLEAN) GetNumValue( Handle,
WIN_ENABLEDSRSENSITIVITY,
FALSE );
pAsync->fConnectionDriver = (BOOLEAN) GetNumValue( Handle,
WIN_CONNECTIONDRIVER,
FALSE );
QueryFlow( Handle, &pAsync->FlowControl );
QueryConnect( Handle, &pAsync->Connect );
}
/*******************************************************************************
*
* QueryOemTd
*
* Query OEMTDCONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pOemTd (output)
* address to return OEMTDCONFIG structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryOemTd( HKEY Handle,
POEMTDCONFIG pOemTd )
{
pOemTd->Adapter = GetNumValue( Handle, WIN_OEMTDADAPTER, 0 );
GetStringValue( Handle, WIN_OEMTDDEVICENAME, NULL, pOemTd->DeviceName,
DEVICENAME_LENGTH + 1 );
pOemTd->Flags = GetNumValue( Handle, WIN_OEMTDFLAGS, 0 );
}
/*******************************************************************************
*
* QueryFlow
*
* query FLOWCONTROLCONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pFlow (output)
* address to return FLOWCONTROLCONFIG structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryFlow( HKEY Handle,
PFLOWCONTROLCONFIG pFlow )
{
pFlow->fEnableSoftwareRx = (BOOLEAN) GetNumValue( Handle,
WIN_FLOWSOFTWARERX,
FALSE );
pFlow->fEnableSoftwareTx = (BOOLEAN) GetNumValue( Handle,
WIN_FLOWSOFTWARETX,
TRUE );
pFlow->fEnableDTR = (BOOLEAN) GetNumValue( Handle, WIN_ENABLEDTR, TRUE );
pFlow->fEnableRTS = (BOOLEAN) GetNumValue( Handle, WIN_ENABLERTS, TRUE );
pFlow->XonChar = (UCHAR) GetNumValue( Handle, WIN_XONCHAR, 0 );
pFlow->XoffChar = (UCHAR) GetNumValue( Handle, WIN_XOFFCHAR, 0 );
pFlow->Type = GetNumValue( Handle, WIN_FLOWTYPE, FlowControl_Hardware );
pFlow->HardwareReceive = GetNumValue( Handle, WIN_FLOWHARDWARERX,
ReceiveFlowControl_RTS );
pFlow->HardwareTransmit = GetNumValue( Handle, WIN_FLOWHARDWARETX,
TransmitFlowControl_CTS );
}
/*******************************************************************************
*
* QueryConnect
*
* query CONNECTCONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pConnect (output)
* address to return CONNECTCONFIG structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryConnect( HKEY Handle,
PCONNECTCONFIG pConnect )
{
pConnect->Type = GetNumValue( Handle, WIN_CONNECTTYPE, Connect_DSR );
pConnect->fEnableBreakDisconnect = (BOOLEAN) GetNumValue( Handle,
WIN_ENABLEBREAKDISCONNECT,
FALSE );
}
/*******************************************************************************
*
* QueryCd
*
* query CDCONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pCdConfig (output)
* address to return CDCONFIG structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryCd( HKEY Handle,
PCDCONFIG pCdConfig )
{
pCdConfig->CdClass = GetNumValue( Handle, WIN_CDCLASS, CdNone );
GetStringValue( Handle, WIN_CDNAME, NULL, pCdConfig->CdName,
CDNAME_LENGTH + 1 );
GetStringValue( Handle, WIN_CDDLL, L"", pCdConfig->CdDLL,
DLLNAME_LENGTH + 1 );
pCdConfig->CdFlag = GetNumValue( Handle, WIN_CDFLAG, 0 );
}
/*******************************************************************************
*
* QueryWd
*
* query WDCONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pWd (output)
* address to return WDCONFIG structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryWd( HKEY Handle,
PWDCONFIG pWd )
{
GetStringValue( Handle, WIN_WDNAME, NULL, pWd->WdName, WDNAME_LENGTH + 1 );
GetStringValue( Handle, WIN_WDDLL, L"", pWd->WdDLL, DLLNAME_LENGTH + 1 );
GetStringValue( Handle, WIN_WSXDLL, NULL, pWd->WsxDLL, DLLNAME_LENGTH + 1 );
pWd->WdFlag = GetNumValue( Handle, WIN_WDFLAG, 0 );
pWd->WdInputBufferLength = GetNumValue( Handle, WIN_INPUTBUFFERLENGTH, 2048 );
GetStringValue( Handle, WIN_CFGDLL, NULL, pWd->CfgDLL, DLLNAME_LENGTH + 1 );
GetStringValue( Handle, WIN_WDPREFIX, NULL, pWd->WdPrefix, WDPREFIX_LENGTH + 1 );
}
/*******************************************************************************
*
* QueryPdConfig
*
* query PDCONFIG structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pConfig (output)
* address to return array of PDCONFIG structures
* pCount (input/output)
* pointer to number of PDCONFIG array elements
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryPdConfig( HKEY Handle,
PPDCONFIG pConfig,
PULONG pCount )
{
ULONG i;
for ( i=0; i < *pCount; i++ ) {
QueryPdConfig2( Handle, &pConfig[i].Create, i );
QueryPdParams( Handle,
pConfig[i].Create.SdClass,
&pConfig[i].Params );
}
*pCount = MAX_PDCONFIG;
}
/*******************************************************************************
*
* QueryPdConfig2
*
* query PDCONFIG2 structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pPd2 (output)
* address to return PDCONFIG2 structure
* Index (input)
* Index (array index)
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryPdConfig2( HKEY Handle,
PPDCONFIG2 pPd2,
ULONG Index )
{
GetStringValueEx( Handle, WIN_PDNAME, Index,
NULL, pPd2->PdName, PDNAME_LENGTH + 1 );
pPd2->SdClass = GetNumValueEx( Handle, WIN_PDCLASS, Index, Index==0 ? SdAsync : SdNone );
GetStringValueEx( Handle, WIN_PDDLL, Index,
NULL, pPd2->PdDLL, DLLNAME_LENGTH + 1 );
pPd2->PdFlag = GetNumValueEx( Handle, WIN_PDFLAG, Index, 0 );
/*
* The following data is the same for all pds
*/
pPd2->OutBufLength = GetNumValue( Handle, WIN_OUTBUFLENGTH, 530 );
pPd2->OutBufCount = GetNumValue( Handle, WIN_OUTBUFCOUNT, 10 );
pPd2->OutBufDelay = GetNumValue( Handle, WIN_OUTBUFDELAY, 100 );
pPd2->InteractiveDelay = GetNumValue( Handle, WIN_INTERACTIVEDELAY, 10 );
pPd2->KeepAliveTimeout = GetNumValue( Handle, WIN_KEEPALIVETIMEOUT, 0 );
pPd2->PortNumber = GetNumValue( Handle, WIN_PORTNUMBER, 0 );
}
/*******************************************************************************
*
* QueryPdConfig3
*
* query PDCONFIG3 structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* pPd (output)
* address to return PDCONFIG3 structure
* Index (input)
* Index (array index)
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryPdConfig3( HKEY Handle,
PPDCONFIG3 pPd3,
ULONG Index )
{
int i;
ULONG Length;
LPWSTR tmp;
WCHAR PdName[ MAX_PDCONFIG * ( PDNAME_LENGTH + 1 ) + 1 ];
ULONG ValueType;
QueryPdConfig2( Handle, &pPd3->Data, Index );
GetStringValue( Handle, WIN_SERVICENAME, NULL,
pPd3->ServiceName,
PDNAME_LENGTH + 1 );
GetStringValue( Handle, WIN_CONFIGDLL, NULL,
pPd3->ConfigDLL,
DLLNAME_LENGTH + 1 );
Length = sizeof(PdName);
pPd3->RequiredPdCount = 0;
if ( RegQueryValueEx( Handle, WIN_REQUIREDPDS, NULL, &ValueType,
(LPBYTE)PdName, &Length ) == ERROR_SUCCESS ) {
tmp = PdName;
i = 0;
while ( *tmp != UNICODE_NULL ) {
pPd3->RequiredPdCount++;
wcscpy( pPd3->RequiredPds[i], tmp );
i++;
tmp += wcslen(tmp) + 1;
}
}
}
/*******************************************************************************
*
* QueryPdParams
*
* query PDPARAMS structure
*
* ENTRY:
*
* Handle (input)
* registry handle
* SdClass (input)
* type of PD
* pParams (output)
* address to return PDPARAMS structure
*
* EXIT:
* nothing
*
******************************************************************************/
VOID
QueryPdParams( HKEY Handle,
SDCLASS SdClass,
PPDPARAMS pParams )
{
pParams->SdClass = SdClass;
switch ( SdClass ) {
case SdNetwork :
QueryNetwork( Handle, &pParams->Network );
break;
case SdNasi :
QueryNasi( Handle, &pParams->Nasi );
break;
case SdAsync :
QueryAsync( Handle, &pParams->Async );
break;
case SdOemTransport :
QueryOemTd( Handle, &pParams->OemTd );
break;
}
}
#define CONTROL_PANEL L"Control Panel"
#define DESKTOP L"Desktop"
#define WALLPAPER L"Wallpaper"
#define NONE L"(None)"
/*******************************************************************************
*
* IsWallPaperDisabled
*
* Is the wall paper disabled?
*
* ENTRY:
* Handle (input)
* registry handle
* EXIT:
* TRUE or FALSE (returns FALSE as default)
*
******************************************************************************/
BOOLEAN IsWallPaperDisabled( HKEY Handle )
{
HKEY Handle1;
WCHAR KeyString[256];
wcscpy( KeyString, WIN_USEROVERRIDE );
wcscat( KeyString, L"\\" );
wcscat( KeyString, CONTROL_PANEL );
wcscat( KeyString, L"\\" );
wcscat( KeyString, DESKTOP );
if ( RegOpenKeyEx( Handle, KeyString, 0, KEY_READ,
&Handle1 ) != ERROR_SUCCESS )
return FALSE;
GetStringValue( Handle1, WALLPAPER, NULL, KeyString, 256 );
RegCloseKey( Handle1 );
if( KeyString[0] == 0 || ( _wcsicmp( NONE, KeyString ) == 0 ) )
{
return TRUE;
}
return FALSE;
}
/*****************************************************************************
*
* RegBuildNumberQuery
*
* Query the current build number from the registry.
*
* HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\Current Version\
* CurrentBuildNumber:REG_SZ:129
*
* ENTRY:
* Param1 (input/output)
* Comments
*
* EXIT:
* STATUS_SUCCESS - no error
*
****************************************************************************/
BOOLEAN WINAPI
RegBuildNumberQuery(
PULONG pBuildNum
)
{
ULONG Result, Value;
HKEY hKey;
WCHAR Buf[256];
Result = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
BUILD_NUMBER_KEY,
0, // Reserved
KEY_READ,
&hKey
);
if( Result != ERROR_SUCCESS ) {
#if DBG
DbgPrint("RegBuildNumberQuery: Failed to open key %ws\n",BUILD_NUMBER_KEY);
#endif
return( FALSE );
}
Result = GetStringValue(
hKey,
BUILD_NUMBER_VALUE,
L"0",
Buf,
sizeof(Buf)
);
if( Result != ERROR_SUCCESS ) {
#if DBG
DbgPrint("RegBuildNumberQuery: Failed to query value %ws\n",BUILD_NUMBER_VALUE);
#endif
RegCloseKey( hKey );
return( FALSE );
}
RegCloseKey( hKey );
//
// Now must convert it into a number
//
Value = 0;
swscanf( Buf, L"%d", &Value );
*pBuildNum = Value;
return( TRUE );
}
/*******************************************************************************
*
* RegQueryOEMId
*
* query oem id
*
* ENTRY:
*
* pOEMId (output)
* pointer to buffer to return oem id
* Length (input)
* length of buffer
*
* EXIT:
*
* TRUE -- The operation succeeded.
*
* FALSE -- The operation failed. Extended error status is available
* using GetLastError.
*
******************************************************************************/
BOOLEAN
RegQueryOEMId( PBYTE pOEMId, ULONG Length )
{
HKEY Handle2;
WCHAR OEMIdW[10];
/*
* Open registry (LOCAL_MACHINE\....\Terminal Server)
*/
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
KEY_READ, &Handle2 ) == ERROR_SUCCESS ) {
GetStringValue( Handle2, REG_CITRIX_OEMID, NULL, OEMIdW, 10 );
UnicodeToAnsi( pOEMId, Length, OEMIdW );
pOEMId[3] = '\0';
RegCloseKey( Handle2 );
}
return( TRUE );
}
/*******************************************************************************
*
* RegGetTServerVersion (UNICODE)
*
* Get the Terminal Server version number from the specified server.
*
* This version number is changed by Microsoft, and not OEM's.
*
* ENTRY:
* pServerName (input)
* Points to string of server to check.
*
* EXIT:
* TRUE if Hydra Terminal Server; FALSE otherwise
*
******************************************************************************/
BOOLEAN WINAPI
RegGetTServerVersion(
WCHAR * pServerName,
PULONG pVersionNumber
)
{
LONG Error;
HKEY ServerHandle, UserHandle;
ULONG Value;
/*
* Connect to registry of specified server.
*/
if ( (Error = RegConnectRegistry( pServerName,
HKEY_LOCAL_MACHINE,
&ServerHandle )) != ERROR_SUCCESS )
return( FALSE );
/*
* Open the Terminal Server key and get the Version value.
*/
if ( (Error = RegOpenKeyEx( ServerHandle, REG_CONTROL_TSERVER, 0,
KEY_READ, &UserHandle )) != ERROR_SUCCESS ) {
RegCloseKey( ServerHandle );
return( FALSE );
}
Value = GetNumValue(
UserHandle,
REG_CITRIX_VERSION,
0 );
/*
* Close registry handles.
*/
RegCloseKey( UserHandle );
RegCloseKey( ServerHandle );
*pVersionNumber = Value;
return( TRUE );
}
/*******************************************************************************
*
* RegQueryUtilityCommandList (UNICODE)
*
* Allocate and build an array of PROGRAMCALL structures for the specified
* MultiUser utility.
*
* ENTRY:
* pUtilityKey (input)
* Points to string containing the utility's command registry key.
* ppProgramCall (output)
* Points to a PPROGRAMCALL variable that will be set to the API-allocated
* array of PROGRAMCALL structures, containing n elements, where n =
* number of commands supported by the utility (as specified in the
* registry). The pFirst item of array element 0 will point to the
* first command (sorted alphabetically by command name). The pNext items
* are then used to walk the list, till pNext is NULL.
*
* EXIT:
* ERROR_SUCCESS if all goes well;
* An error code is returned if failure.
*
* If success, the caller must call RegFreeUtilityCommandList with the
* ppProgramCall variable to free the PROGRAMCALL structure array when
* finished using the array.
*
* The format of the REG_MULTI_SZ command item in the registry is as follows:
*
* string 1: "0" or "1" (required)
*
* 0 specifies that the command is a normal command which will
* be presented as an option by the utility USAGE help. 1
* indicates a command alias (hidden option), which won't
* appear in USAGE help.
*
* string 2: "number" (required)
*
* Specifies the minimum number of characters that must be
* typed for the command to be recognized (base 10).
*
* string 3: "command" (required)
*
* This is the actual command that will be recognized and
* displayed in the USAGE help (if not an aliased command).
*
* string 4: "program" (required)
*
* The file name of the program that will be executed. This
* should be a standard name.extension filename, and can
* include a full path, although this is not necessary since
* the utilities will normally reside in the standard SYSTEM32
* directory, which is a part of the standard PATH.
*
* string 5: "extra args" (optional)
*
* If specified, this string will be passed along to the
* utilsub.lib ExecProgram API to specify additional
* hard-coded arguments that will be used, in addition to any
* other arguments that were specified by the user on the
* command line.
*
* Note: If the command item is not a REG_MULTI_SZ value, or the command item
* is a REG_MULTI_SZ item but there is an error in its format, that
* command will be omitted from the command list. The return value
* from this function will still be ERROR_SUCCESS, but the command in
* error will be ignored by the utilities.
*
******************************************************************************/
LONG WINAPI
RegQueryUtilityCommandList(
LPWSTR pUtilityKey,
PPROGRAMCALL * ppProgramCall
)
{
HKEY Handle = NULL;
LONG status = ERROR_SUCCESS;
DWORD iValue, cValues, ccValueName, cbValueData,
ccTmpValueName, cbTmpValueData, dwType;
LPWSTR pValueName = NULL, pValueData = NULL, pString;
PPROGRAMCALL pProg = NULL, pProgNext, pProgPrev;
ULONG ulCommandLen;
PWCHAR pEndptr;
int iCompare;
*ppProgramCall = NULL;
/*
* Open specified utility key and determine number of values and maximum
* value name and data length.
*/
if ( status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
pUtilityKey,
0,
KEY_READ,
&Handle ) != ERROR_SUCCESS ) {
#if DBG
DbgPrint("RegQueryUtilityCommandList: Can't open command list utility key %ws; error = %d\n", pUtilityKey, status);
#endif
goto error;
}
if ( status = RegQueryInfoKey( Handle,
NULL, // lpClass
NULL, // lpcbClass
NULL, // lpReserved
NULL, // lpcSubKeys
NULL, // lpcbMaxSubKeyLen
NULL, // lpcbMaxClassLen
&cValues, // lpcValues
&ccValueName, // lpcbMaxValueNameLen
&cbValueData, // lpcbMaxValueLen
NULL, // lpcbSecurityDescriptor
NULL // lpftLastWriteTime
) != ERROR_SUCCESS ) {
#if DBG
DbgPrint("RegQueryUtilityCommandList: Can't query info for utility %ws; error = %d\n", pUtilityKey, status);
#endif
goto error;
}
/*
* Allocate space for #values + 1 PROGRAMCALL elements and value name and
* data buffers.
*/
if ( ((*ppProgramCall = (PPROGRAMCALL)LocalAlloc( LPTR, (sizeof(PROGRAMCALL) * (cValues+1)) )) == NULL) ||
((pValueName = (LPWSTR)LocalAlloc( LPTR, (int)(++ccValueName * sizeof(WCHAR)) )) == NULL) ||
((pValueData = (LPWSTR)LocalAlloc( LPTR, (int)cbValueData )) == NULL) ) {
status = GetLastError();
#if DBG
DbgPrint("RegQueryUtilityCommandList: Can't allocate memory buffer(s) for utility %ws; error = %d\n", pUtilityKey, status);
#endif
goto error;
}
/*
* Enumerate and parse each value into the PROGRAMCALL components.
*/
for ( iValue = 0, pProg = *ppProgramCall;
iValue < cValues;
iValue++, pProg++ ) {
ccTmpValueName = ccValueName;
cbTmpValueData = cbValueData;
if ( (status = RegEnumValue( Handle,
iValue,
pValueName,
&ccTmpValueName,
NULL,
&dwType,
(LPBYTE)pValueData,
&cbTmpValueData )) != ERROR_SUCCESS ) {
#if DBG
DbgPrint("RegQueryUtilityCommandList: Can't enumerate command (index = %d) for utility %ws; error = %d\n", iValue, pUtilityKey, status);
#endif
goto error;
}
/*
* If the data is not REG_MULTI_SZ, ignore it.
*/
if ( dwType != REG_MULTI_SZ )
goto CommandInError;
/*
* Allocate data storage for this command, then parse and assign
* to the PROGRAMCALL structure items.
*/
if ( (pProg->pRegistryMultiString = LocalAlloc(LPTR, cbTmpValueData)) == NULL ) {
status = GetLastError();
#if DBG
DbgPrint("RegQueryUtilityCommandList: Can't allocate memory buffer for utility %ws; error = %d\n", pUtilityKey, status);
#endif
goto error;
}
memcpy(pProg->pRegistryMultiString, pValueData, cbTmpValueData);
pString = pProg->pRegistryMultiString;
/*
* Parse alias flag.
*/
if ( !wcscmp(pString, L"1") )
pProg->fAlias = TRUE;
else if ( !wcscmp(pString, L"0") )
pProg->fAlias = FALSE;
else
goto CommandInError;
pString += (wcslen(pString) + 1);
/*
* Parse command length.
*/
if ( *pString == L'\0' )
goto CommandInError;
ulCommandLen = wcstoul(pString, &pEndptr, 10);
if ( *pEndptr != L'\0' )
goto CommandInError;
pProg->CommandLen = (USHORT)ulCommandLen;
pString += (wcslen(pString) + 1);
/*
* Parse command string.
*/
if ( *pString == L'\0' )
goto CommandInError;
pProg->Command = pString;
pString += (wcslen(pString) + 1);
/*
* Parse program string.
*/
if ( *pString == L'\0' )
goto CommandInError;
pProg->Program = pString;
pString += (wcslen(pString) + 1);
/*
* Parse (optional) Args string.
*/
if ( *pString != L'\0' )
pProg->Args = pString;
/*
* Walk the command list to link this item in it's proper
* sorted place.
*/
if ( pProg == *ppProgramCall ) {
pProg->pFirst = pProg; // first item in the list
} else for ( pProgPrev = pProgNext = (*ppProgramCall)->pFirst; ; ) {
if ( (iCompare = _wcsicmp(pProg->Command, pProgNext->Command)) < 0 ) {
pProg->pNext = pProgNext; // point to next
if ( pProgNext == (*ppProgramCall)->pFirst )
(*ppProgramCall)->pFirst = pProg; // first item
else
pProgPrev->pNext = pProg; // link after previous
break;
} else if ( iCompare == 0 ) {
goto CommandInError; // duplicate command - ignore
}
if ( pProgNext->pNext == NULL ) {
pProgNext->pNext = pProg; // link at end of list
break;
} else {
pProgPrev = pProgNext;
pProgNext = pProgNext->pNext;
}
}
continue;
CommandInError:
/*
* The command format is in error - ignore it.
*/
if ( pProg->pRegistryMultiString )
LocalFree(pProg->pRegistryMultiString);
memset(pProg, 0, sizeof(PROGRAMCALL));
pProg--;
}
error:
if ( Handle != NULL )
RegCloseKey(Handle);
if ( pValueName )
LocalFree(pValueName);
if ( pValueData )
LocalFree(pValueData);
if ( status != ERROR_SUCCESS ) {
if ( *ppProgramCall ) {
RegFreeUtilityCommandList(*ppProgramCall);
*ppProgramCall = NULL;
}
}
return( status );
}
/*******************************************************************************
*
* RegFreeUtilityCommandList (UNICODE)
*
* Free the specified array of PROGRAMCALL structures.
*
* ENTRY:
* pProgramCall (input)
* Points PROGRAMCALL array to free.
*
* EXIT:
* ERROR_SUCCESS if all goes well; error code if failure
*
******************************************************************************/
LONG WINAPI
RegFreeUtilityCommandList(
PPROGRAMCALL pProgramCall
)
{
PPROGRAMCALL pProg;
LONG status = ERROR_SUCCESS;
if ( pProgramCall ) {
for ( pProg = pProgramCall->pFirst; pProg != NULL; pProg = pProg->pNext ) {
if ( LocalFree( pProg->pRegistryMultiString ) != NULL ) {
status = GetLastError();
#if DBG
DbgPrint("RegFreeUtilityCommandList: Failed to free command list element for %ws; error = %d\n", pProg->Program, status);
#endif
}
}
if ( LocalFree( pProgramCall ) != NULL ) {
status = GetLastError();
#if DBG
DbgPrint("RegFreeUtilityCommandList: Failed to free command list array; error = %d\n", status);
#endif
}
}
return( status );
}