841 lines
23 KiB
C
841 lines
23 KiB
C
|
|
/*************************************************************************
|
|
*
|
|
* regpd.c
|
|
*
|
|
* Register APIs for Tds and Pds (transport and protocol drivers)
|
|
*
|
|
* Copyright (c) 1998 Microsoft Corporation
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
|
|
/*
|
|
* Includes
|
|
*/
|
|
#include <windows.h>
|
|
|
|
#include <ksguid.h>
|
|
#include <ntddkbd.h>
|
|
#include <ntddmou.h>
|
|
#include <winstaw.h>
|
|
#include <regapi.h>
|
|
|
|
|
|
/*
|
|
* External Procedures defined here
|
|
*/
|
|
|
|
|
|
HANDLE WINAPI RegOpenServerW ( LPWSTR pServerName );
|
|
HANDLE WINAPI RegOpenServerA ( LPSTR pServerName );
|
|
LONG WINAPI RegCloseServer ( HANDLE hServer );
|
|
LONG WINAPI RegPdEnumerateW( HANDLE, PWDNAMEW, BOOLEAN, PULONG, PULONG, PPDNAMEW, PULONG );
|
|
LONG WINAPI RegPdEnumerateA( HANDLE, PWDNAMEA, BOOLEAN, PULONG, PULONG, PPDNAMEA, PULONG );
|
|
LONG WINAPI RegPdCreateW( HANDLE, PWDNAMEW, BOOLEAN, PPDNAMEW, BOOLEAN, PPDCONFIG3W, ULONG );
|
|
LONG WINAPI RegPdCreateA( HANDLE, PWDNAMEA, BOOLEAN, PPDNAMEA, BOOLEAN, PPDCONFIG3A, ULONG );
|
|
LONG WINAPI RegPdQueryW( HANDLE, PWDNAMEW, BOOLEAN, PPDNAMEW, PPDCONFIG3W, ULONG, PULONG );
|
|
LONG WINAPI RegPdQueryA( HANDLE, PWDNAMEA, BOOLEAN, PPDNAMEA, PPDCONFIG3A, ULONG, PULONG );
|
|
LONG WINAPI RegPdDeleteW( HANDLE, PWDNAMEW, BOOLEAN, PPDNAMEW );
|
|
LONG WINAPI RegPdDeleteA( HANDLE, PWDNAMEA, BOOLEAN, PPDNAMEA );
|
|
|
|
/*
|
|
* other internal Procedures used (not defined here)
|
|
*/
|
|
VOID CreatePdConfig3( HKEY, PPDCONFIG3, ULONG );
|
|
VOID QueryPdConfig3( HKEY, PPDCONFIG3, ULONG );
|
|
VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
|
|
VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
|
|
VOID PdConfigU2A( PPDCONFIGA, PPDCONFIGW );
|
|
VOID PdConfigA2U( PPDCONFIGW, PPDCONFIGA );
|
|
VOID PdConfig3U2A( PPDCONFIG3A, PPDCONFIG3W );
|
|
VOID PdConfig3A2U( PPDCONFIG3W, PPDCONFIG3A );
|
|
VOID PdParamsU2A( PPDPARAMSA, PPDPARAMSW );
|
|
VOID PdParamsA2U( PPDPARAMSW, PPDPARAMSA );
|
|
VOID AsyncConfigU2A ( PASYNCCONFIGA, PASYNCCONFIGW );
|
|
VOID AsyncConfigA2U ( PASYNCCONFIGW, PASYNCCONFIGA );
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* RegOpenServerA
|
|
*
|
|
*
|
|
* ENTRY:
|
|
* Machine (input)
|
|
* Name of WinFrame computer to connect to
|
|
*
|
|
* EXIT:
|
|
* handle to a server's Registry (or NULL on error)
|
|
*
|
|
****************************************************************************/
|
|
|
|
HANDLE WINAPI
|
|
RegOpenServerA(
|
|
LPSTR pServerName
|
|
)
|
|
{
|
|
HKEY hServer;
|
|
ULONG NameLength;
|
|
PWCHAR pServerNameW = NULL;
|
|
|
|
if( pServerName == NULL ) {
|
|
return( (HANDLE)HKEY_LOCAL_MACHINE );
|
|
}
|
|
|
|
NameLength = strlen( pServerName ) + 1;
|
|
|
|
pServerNameW = LocalAlloc( 0, NameLength * sizeof(WCHAR) );
|
|
if( pServerNameW == NULL ) {
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return( NULL );
|
|
}
|
|
|
|
AnsiToUnicode( pServerNameW, NameLength*sizeof(WCHAR), pServerName );
|
|
|
|
hServer = RegOpenServerW( pServerNameW );
|
|
|
|
LocalFree( pServerNameW );
|
|
|
|
return( (HANDLE) hServer );
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* RegOpenServerW
|
|
*
|
|
* NULL for machine name means local system.
|
|
*
|
|
* ENTRY:
|
|
* Machine (input)
|
|
* Name of WinFrame computer to connect to
|
|
*
|
|
* EXIT:
|
|
* handle to server's Registry (or NULL on error)
|
|
*
|
|
****************************************************************************/
|
|
|
|
HANDLE WINAPI
|
|
RegOpenServerW( LPWSTR pServerName ){
|
|
|
|
HKEY hKey;
|
|
|
|
if( pServerName == NULL )
|
|
return( HKEY_LOCAL_MACHINE );
|
|
|
|
else {
|
|
if( RegConnectRegistry( pServerName, HKEY_LOCAL_MACHINE, &hKey ) != ERROR_SUCCESS ){
|
|
return( NULL );
|
|
}
|
|
}
|
|
|
|
return( hKey );
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* RegCloseServer
|
|
*
|
|
* Close a connection to a Server Registry.
|
|
*
|
|
* ENTRY:
|
|
* hServer (input)
|
|
* Handle to close
|
|
*
|
|
* EXIT:
|
|
* ERROR_SUCCESS - no error
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG WINAPI
|
|
RegCloseServer( HANDLE hServer )
|
|
{
|
|
return( RegCloseKey( (HKEY)hServer ) );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegPdEnumerateA (ANSI stub)
|
|
*
|
|
* Returns a list of configured Pds in the registry.
|
|
*
|
|
* ENTRY:
|
|
*
|
|
* see RegPdEnumerateW
|
|
*
|
|
* EXIT:
|
|
*
|
|
* see RegPdEnumerateW, plus
|
|
*
|
|
* ERROR_NOT_ENOUGH_MEMORY - the LocalAlloc failed
|
|
*
|
|
******************************************************************************/
|
|
|
|
LONG WINAPI
|
|
RegPdEnumerateA( HANDLE hServer,
|
|
PWDNAMEA pWdName,
|
|
BOOLEAN bTd,
|
|
PULONG pIndex,
|
|
PULONG pEntries,
|
|
PPDNAMEA pPdName,
|
|
PULONG pByteCount )
|
|
{
|
|
WDNAMEW WdNameW;
|
|
PPDNAMEW pBuffer = NULL, pPdNameW;
|
|
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 ( pPdName && ByteCountW ) {
|
|
|
|
if ( !(pBuffer = LocalAlloc(0, ByteCountW)) )
|
|
return ( ERROR_NOT_ENOUGH_MEMORY );
|
|
}
|
|
|
|
/*
|
|
* Convert ANSI WdName to UNICODE.
|
|
*/
|
|
AnsiToUnicode( WdNameW, sizeof(WDNAMEW), pWdName );
|
|
|
|
/*
|
|
* Enumerate Pds
|
|
*/
|
|
pPdNameW = pBuffer;
|
|
Status = RegPdEnumerateW( hServer,
|
|
WdNameW,
|
|
bTd,
|
|
pIndex,
|
|
pEntries,
|
|
pPdNameW,
|
|
&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))
|
|
&& pPdNameW && pPdName ) {
|
|
|
|
for ( Count = *pEntries; Count; Count-- ) {
|
|
UnicodeToAnsi( pPdName, sizeof(PDNAMEA), pPdNameW );
|
|
(char*)pPdName += sizeof(PDNAMEA);
|
|
(char*)pPdNameW += sizeof(PDNAMEW);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If we defined a buffer, free it now, then return the status
|
|
* of the Reg...EnumerateW function call.
|
|
*/
|
|
if ( pBuffer )
|
|
LocalFree(pBuffer);
|
|
|
|
return ( Status );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegPdEnumerateW (UNICODE)
|
|
*
|
|
* Returns a list of configured Pds in the registry.
|
|
*
|
|
* ENTRY:
|
|
*
|
|
* hServer (input)
|
|
* Handle to WinFrame Server
|
|
* pWdName (input)
|
|
* Points to the wdname to enumerate pds for
|
|
* bTd (input)
|
|
* TRUE to enumerate Transport Drivers (Tds),
|
|
* FALSE to enumerate Protocol Drivers (Pds)
|
|
* pIndex (input/output)
|
|
* Specifies the subkey index for the \Citrix\Wds\<wdname>\<Pd or Td>
|
|
* 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.
|
|
* pPdName (input)
|
|
* Points to the buffer to receive the enumeration results, which are
|
|
* returned as an array of PDNAME 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
|
|
* pPdName 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 pPdName.
|
|
*
|
|
* EXIT:
|
|
*
|
|
* "No Error" codes:
|
|
* ERROR_SUCCESS - The enumeration completed as requested and there
|
|
* are more Pds subkeys (PDNAMEs) to be read.
|
|
* ERROR_NO_MORE_ITEMS - The enumeration completed as requested and there
|
|
* are no more Pds subkeys (PDNAMEs) to be read.
|
|
*
|
|
* "Error" codes:
|
|
* ERROR_OUTOFMEMORY - The pPdName buffer is too small for even one entry.
|
|
* ERROR_CANTOPEN - The \Citrix\Wds\<wdname>\<Pd or Td> key can't be opened.
|
|
*
|
|
******************************************************************************/
|
|
|
|
LONG WINAPI
|
|
RegPdEnumerateW( HANDLE hServer,
|
|
PWDNAMEW pWdName,
|
|
BOOLEAN bTd,
|
|
PULONG pIndex,
|
|
PULONG pEntries,
|
|
PPDNAMEW pPdName,
|
|
PULONG pByteCount )
|
|
{
|
|
LONG Status;
|
|
HKEY Handle;
|
|
ULONG Count;
|
|
ULONG i;
|
|
HKEY hkey_local_machine;
|
|
WCHAR KeyString[256];
|
|
|
|
if( hServer == NULL )
|
|
hkey_local_machine = HKEY_LOCAL_MACHINE;
|
|
else
|
|
hkey_local_machine = hServer;
|
|
|
|
|
|
|
|
/*
|
|
* Get the number of names to return
|
|
*/
|
|
Count = pPdName ?
|
|
min( *pByteCount / sizeof(PDNAME), *pEntries ) :
|
|
(ULONG) -1;
|
|
*pEntries = *pByteCount = 0;
|
|
|
|
/*
|
|
* Make sure buffer is big enough for at least one name
|
|
*/
|
|
if ( Count == 0 ) {
|
|
*pByteCount = sizeof(PDNAME);
|
|
return( ERROR_OUTOFMEMORY );
|
|
}
|
|
|
|
/*
|
|
* Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\<Pd or Td>)
|
|
*/
|
|
wcscpy( KeyString, WD_REG_NAME );
|
|
wcscat( KeyString, L"\\" );
|
|
wcscat( KeyString, pWdName );
|
|
wcscat( KeyString, bTd ? TD_REG_NAME : PD_REG_NAME );
|
|
if ( RegOpenKeyEx( hkey_local_machine, KeyString, 0,
|
|
KEY_ENUMERATE_SUB_KEYS, &Handle ) != ERROR_SUCCESS ) {
|
|
return( ERROR_CANTOPEN );
|
|
}
|
|
|
|
/*
|
|
* Get list of Tds or Pds
|
|
*/
|
|
for ( i = 0; i < Count; i++ ) {
|
|
PDNAME PdName;
|
|
|
|
if ( (Status = RegEnumKey(Handle, *pIndex, PdName,
|
|
sizeof(PDNAME)/sizeof(TCHAR) )) != ERROR_SUCCESS )
|
|
break;
|
|
|
|
/*
|
|
* If caller supplied a buffer, then copy the PdName
|
|
* and increment the pointer and byte count. Always increment the
|
|
* entry count and index for the next iteration.
|
|
*/
|
|
if ( pPdName ) {
|
|
wcscpy( pPdName, PdName );
|
|
(char*)pPdName += sizeof(PDNAME);
|
|
*pByteCount += sizeof(PDNAME);
|
|
}
|
|
(*pEntries)++;
|
|
(*pIndex)++;
|
|
}
|
|
|
|
/*
|
|
* Close registry
|
|
*/
|
|
RegCloseKey( Handle );
|
|
return( Status );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegPdCreateA (ANSI stub)
|
|
*
|
|
* Creates a new Pd in the registry or updates an existing entry.
|
|
* (See RegPdCreateW)
|
|
*
|
|
* ENTRY:
|
|
*
|
|
* see RegPdCreateW
|
|
*
|
|
* EXIT:
|
|
*
|
|
* see RegPdCreateW
|
|
*
|
|
******************************************************************************/
|
|
|
|
LONG WINAPI
|
|
RegPdCreateA( HANDLE hServer,
|
|
PWDNAMEA pWdName,
|
|
BOOLEAN bTd,
|
|
PPDNAMEA pPdName,
|
|
BOOLEAN bCreate,
|
|
PPDCONFIG3A pPdConfig,
|
|
ULONG PdConfigLength )
|
|
{
|
|
PDNAMEW PdNameW;
|
|
WDNAMEW WdNameW;
|
|
PDCONFIG3W PdConfig3W;
|
|
|
|
/*
|
|
* Validate target buffer size.
|
|
*/
|
|
if ( PdConfigLength < sizeof(PDCONFIG3A) )
|
|
return( ERROR_INSUFFICIENT_BUFFER );
|
|
|
|
/*
|
|
* Convert ANSI WdName and PdName to UNICODE.
|
|
*/
|
|
AnsiToUnicode( WdNameW, sizeof(WDNAMEW), pWdName );
|
|
AnsiToUnicode( PdNameW, sizeof(PDNAMEW), pPdName );
|
|
|
|
/*
|
|
* Copy PDCONFIG3A elements to PDCONFIG3W elements.
|
|
*/
|
|
PdConfig3A2U( &PdConfig3W, pPdConfig );
|
|
|
|
/*
|
|
* Call RegPdCreateW & return it's status.
|
|
*/
|
|
return ( RegPdCreateW( hServer,
|
|
WdNameW,
|
|
bTd,
|
|
PdNameW,
|
|
bCreate,
|
|
&PdConfig3W,
|
|
sizeof(PdConfig3W)) );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegPdCreateW (UNICODE)
|
|
*
|
|
* Creates a new Pd in the registry or updates an existing entry. The
|
|
* state of the bCreate flag determines whether this function will expect
|
|
* to create a new Pd entry (bCreate == TRUE) or expects to update an
|
|
* existing entry (bCreate == FALSE).
|
|
*
|
|
* ENTRY:
|
|
* hServer (input)
|
|
* Handle to WinFrame Server
|
|
* pWdName (input)
|
|
* Points to the wdname to create pd for
|
|
* bTd (input)
|
|
* TRUE to create a Transport Driver (Td),
|
|
* FALSE to create a Protocol Driver (Pd)
|
|
* pPdName (input)
|
|
* Name of a new or exisiting Pd in the registry.
|
|
* bCreate (input)
|
|
* TRUE if this is a creation of a new Pd
|
|
* FALSE if this is an update to an existing Pd
|
|
* pPdConfig (input)
|
|
* Pointer to a PDCONFIG3 structure containing configuration
|
|
* information for the specified Pd name.
|
|
* PdConfigLength (input)
|
|
* Specifies the length in bytes of the pPdConfig buffer.
|
|
*
|
|
* EXIT:
|
|
* ERROR_SUCCESS - no error
|
|
*
|
|
* ERROR_INSUFFICIENT_BUFFER - pPdConfig buffer too small
|
|
* ERROR_FILE_NOT_FOUND - can't open ...\Citrix\Wds\<wdname>\<Pd or Td> key
|
|
* ERROR_CANNOT_MAKE - can't create Pd key (registry problem)
|
|
* ERROR_ALREADY_EXISTS - create; but Pd key was already present
|
|
* ERROR_CANTOPEN - update; but Pd key could not be opened
|
|
*
|
|
******************************************************************************/
|
|
|
|
LONG WINAPI
|
|
RegPdCreateW( HANDLE hServer,
|
|
PWDNAMEW pWdName,
|
|
BOOLEAN bTd,
|
|
PPDNAMEW pPdName,
|
|
BOOLEAN bCreate,
|
|
PPDCONFIG3W pPdConfig,
|
|
ULONG PdConfigLength )
|
|
{
|
|
HKEY Handle;
|
|
HKEY Handle1;
|
|
DWORD Disp;
|
|
HKEY hkey_local_machine;
|
|
WCHAR KeyString[256];
|
|
|
|
if( hServer == NULL )
|
|
hkey_local_machine = HKEY_LOCAL_MACHINE;
|
|
else
|
|
hkey_local_machine = hServer;
|
|
|
|
|
|
/*
|
|
* Validate length of buffer
|
|
*/
|
|
if ( PdConfigLength < sizeof(PDCONFIG3) )
|
|
return( ERROR_INSUFFICIENT_BUFFER );
|
|
|
|
/*
|
|
* Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\<Pd or Td>)
|
|
*/
|
|
wcscpy( KeyString, WD_REG_NAME );
|
|
wcscat( KeyString, L"\\" );
|
|
wcscat( KeyString, pWdName );
|
|
wcscat( KeyString, bTd ? TD_REG_NAME : PD_REG_NAME );
|
|
if ( RegOpenKeyEx( hkey_local_machine, KeyString, 0,
|
|
KEY_ALL_ACCESS, &Handle1 ) != ERROR_SUCCESS ) {
|
|
return( ERROR_FILE_NOT_FOUND );
|
|
}
|
|
|
|
if ( bCreate ) {
|
|
|
|
/*
|
|
* Create requested: create a registry key for the specified
|
|
* Pd name.
|
|
*/
|
|
if ( RegCreateKeyEx( Handle1, pPdName, 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
|
|
* Pd name.
|
|
*/
|
|
if ( RegOpenKeyEx( Handle1, pPdName, 0, KEY_ALL_ACCESS,
|
|
&Handle ) != ERROR_SUCCESS ) {
|
|
RegCloseKey( Handle1 );
|
|
return( ERROR_CANTOPEN );
|
|
}
|
|
}
|
|
|
|
RegCloseKey( Handle1 );
|
|
|
|
/*
|
|
* Save Pd information
|
|
*/
|
|
CreatePdConfig3( Handle, pPdConfig, 0 );
|
|
|
|
/*
|
|
* Close registry handle
|
|
*/
|
|
RegCloseKey( Handle );
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegPdQueryA (ANSI stub)
|
|
*
|
|
* Query configuration information of a Pd in the registry.
|
|
*
|
|
* ENTRY:
|
|
*
|
|
* see RegPdQueryW
|
|
*
|
|
* EXIT:
|
|
*
|
|
* see RegPdQueryW
|
|
*
|
|
******************************************************************************/
|
|
|
|
LONG WINAPI
|
|
RegPdQueryA( HANDLE hServer,
|
|
PWDNAMEA pWdName,
|
|
BOOLEAN bTd,
|
|
PPDNAMEA pPdName,
|
|
PPDCONFIG3A pPdConfig,
|
|
ULONG PdConfigLength,
|
|
PULONG pReturnLength )
|
|
{
|
|
PDNAMEW PdNameW;
|
|
WDNAMEW WdNameW;
|
|
PDCONFIG3W PdConfig3W;
|
|
LONG Status;
|
|
ULONG ReturnLengthW;
|
|
|
|
/*
|
|
* Validate length and zero-initialize the destination
|
|
* PDCONFIG3A structure.
|
|
*/
|
|
if ( PdConfigLength < sizeof(PDCONFIG3A) )
|
|
return( ERROR_INSUFFICIENT_BUFFER );
|
|
memset(pPdConfig, 0, PdConfigLength);
|
|
|
|
/*
|
|
* Convert ANSI WdName and PdName to UNICODE.
|
|
*/
|
|
AnsiToUnicode(WdNameW, sizeof(WDNAMEW), pWdName);
|
|
AnsiToUnicode(PdNameW, sizeof(PDNAMEW), pPdName);
|
|
|
|
/*
|
|
* Query Pd.
|
|
*/
|
|
if ( (Status = RegPdQueryW( hServer,
|
|
WdNameW,
|
|
bTd,
|
|
PdNameW,
|
|
&PdConfig3W,
|
|
sizeof(PDCONFIG3W),
|
|
&ReturnLengthW)) != ERROR_SUCCESS )
|
|
return ( Status );
|
|
|
|
/*
|
|
* Copy PDCONFIG3W elements to PDCONFIG3A elements.
|
|
*/
|
|
PdConfig3U2A( pPdConfig, &PdConfig3W );
|
|
|
|
*pReturnLength = sizeof(PDCONFIG3A);
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegPdQueryW (UNICODE)
|
|
*
|
|
* Query configuration information of a Pd in the registry.
|
|
*
|
|
* ENTRY:
|
|
* hServer (input)
|
|
* Handle to WinFrame Server
|
|
* pWdName (input)
|
|
* Points to the wdname to query pd for
|
|
* bTd (input)
|
|
* TRUE to query a Transport Driver (Td),
|
|
* FALSE to query a Protocol Driver (Pd)
|
|
* pPdName (input)
|
|
* Name of an exisiting Pd in the registry.
|
|
* pPdConfig (input)
|
|
* Pointer to a PDCONFIG3 structure that will receive
|
|
* information about the specified Pd name.
|
|
* PdConfigLength (input)
|
|
* Specifies the length in bytes of the pPdConfig buffer.
|
|
* pReturnLength (output)
|
|
* Receives the number of bytes placed in the pPdConfig buffer.
|
|
*
|
|
* EXIT:
|
|
* ERROR_SUCCESS - no error
|
|
*
|
|
******************************************************************************/
|
|
|
|
LONG WINAPI
|
|
RegPdQueryW( HANDLE hServer,
|
|
PWDNAMEW pWdName,
|
|
BOOLEAN bTd,
|
|
PPDNAMEW pPdName,
|
|
PPDCONFIG3W pPdConfig,
|
|
ULONG PdConfigLength,
|
|
PULONG pReturnLength )
|
|
{
|
|
HKEY Handle;
|
|
HKEY Handle1;
|
|
HKEY hkey_local_machine;
|
|
WCHAR KeyString[256];
|
|
|
|
if( hServer == NULL )
|
|
hkey_local_machine = HKEY_LOCAL_MACHINE;
|
|
else
|
|
hkey_local_machine = hServer;
|
|
|
|
|
|
/*
|
|
* Validate length and zero-initialize the destination
|
|
* PDCONFIG3A structure.
|
|
*/
|
|
if ( PdConfigLength < sizeof(PDCONFIG3) )
|
|
return( ERROR_INSUFFICIENT_BUFFER );
|
|
memset(pPdConfig, 0, PdConfigLength);
|
|
|
|
/*
|
|
* Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\<Pd or Td>)
|
|
*/
|
|
wcscpy( KeyString, WD_REG_NAME );
|
|
wcscat( KeyString, L"\\" );
|
|
wcscat( KeyString, pWdName );
|
|
wcscat( KeyString, bTd ? TD_REG_NAME : PD_REG_NAME );
|
|
if ( RegOpenKeyEx( hkey_local_machine, KeyString, 0,
|
|
KEY_READ, &Handle1 ) != ERROR_SUCCESS ) {
|
|
return( ERROR_FILE_NOT_FOUND );
|
|
}
|
|
|
|
/*
|
|
* Now try to open the specified Pd
|
|
*/
|
|
if ( RegOpenKeyEx( Handle1, pPdName, 0,
|
|
KEY_READ, &Handle ) != ERROR_SUCCESS ) {
|
|
RegCloseKey( Handle1 );
|
|
return( ERROR_FILE_NOT_FOUND );
|
|
}
|
|
RegCloseKey( Handle1 );
|
|
|
|
/*
|
|
* Query PDCONFIG3 Structure
|
|
*/
|
|
QueryPdConfig3( Handle, pPdConfig, 0 );
|
|
|
|
/*
|
|
* Close registry
|
|
*/
|
|
RegCloseKey( Handle );
|
|
|
|
*pReturnLength = sizeof(PDCONFIG3);
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegPdDeleteA (ANSI stub)
|
|
*
|
|
* Deletes a Pd from the registry.
|
|
*
|
|
* ENTRY:
|
|
*
|
|
* see RegPdDeleteW
|
|
*
|
|
* EXIT:
|
|
*
|
|
* see RegPdDeleteW
|
|
*
|
|
******************************************************************************/
|
|
|
|
LONG WINAPI
|
|
RegPdDeleteA( HANDLE hServer,
|
|
PWDNAMEA pWdName,
|
|
BOOLEAN bTd,
|
|
PPDNAMEA pPdName )
|
|
{
|
|
WDNAMEW WdNameW;
|
|
PDNAMEW PdNameW;
|
|
|
|
AnsiToUnicode( WdNameW, sizeof(WdNameW), pWdName );
|
|
AnsiToUnicode( PdNameW, sizeof(PdNameW), pPdName );
|
|
|
|
return ( RegPdDeleteW ( hServer, WdNameW, bTd, PdNameW ) );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegPdDeleteW (UNICODE)
|
|
*
|
|
* Deletes a Pd from the registry.
|
|
*
|
|
* ENTRY:
|
|
* hServer (input)
|
|
* Handle to WinFrame Server
|
|
* pWdName (input)
|
|
* Points to the wdname to delete pd from
|
|
* bTd (input)
|
|
* TRUE to delete a Transport Driver (Td),
|
|
* FALSE to delete a Protocol Driver (Pd)
|
|
* pPdName (input)
|
|
* Name of a Pd to delete from the registry.
|
|
*
|
|
* EXIT:
|
|
* ERROR_SUCCESS - no error
|
|
*
|
|
******************************************************************************/
|
|
|
|
LONG WINAPI
|
|
RegPdDeleteW( HANDLE hServer,
|
|
PWDNAMEW pWdName,
|
|
BOOLEAN bTd,
|
|
PPDNAMEW pPdName )
|
|
{
|
|
LONG Status;
|
|
HKEY Handle;
|
|
HKEY Handle1;
|
|
HKEY hkey_local_machine;
|
|
WCHAR KeyString[256];
|
|
|
|
if( hServer == NULL )
|
|
hkey_local_machine = HKEY_LOCAL_MACHINE;
|
|
else
|
|
hkey_local_machine = hServer;
|
|
|
|
/*
|
|
* Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\<Pd or Td>)
|
|
*/
|
|
wcscpy( KeyString, WD_REG_NAME );
|
|
wcscat( KeyString, L"\\" );
|
|
wcscat( KeyString, pWdName );
|
|
wcscat( KeyString, bTd ? TD_REG_NAME : PD_REG_NAME );
|
|
if ( RegOpenKeyEx( hkey_local_machine, KeyString, 0,
|
|
KEY_READ, &Handle ) != ERROR_SUCCESS ) {
|
|
return( ERROR_FILE_NOT_FOUND );
|
|
}
|
|
|
|
/*
|
|
* Now try to open the specified Pd
|
|
*/
|
|
if ( RegOpenKeyEx( Handle, pPdName, 0,
|
|
KEY_READ, &Handle1 ) != ERROR_SUCCESS ) {
|
|
RegCloseKey( Handle );
|
|
return( ERROR_FILE_NOT_FOUND );
|
|
}
|
|
|
|
/*
|
|
* Close the Pd key handle, delete the Pd,
|
|
* and close the parent handle.
|
|
*/
|
|
RegCloseKey( Handle1 );
|
|
Status = RegDeleteKey( Handle, pPdName );
|
|
RegCloseKey( Handle );
|
|
|
|
return( Status );
|
|
}
|
|
|