windows-nt/Source/XPSP1/NT/termsrv/regapi/regcd.c
2020-09-26 16:20:57 +08:00

676 lines
19 KiB
C

/*************************************************************************
*
* regcd.c
*
* Register APIs for CDs (connection drivers)
*
* Copyright (c) 1998 Microsoft Corporation
*
*
*************************************************************************/
/*
* Includes
*/
#include <windows.h>
/* Added By SalimC */
#include <ksguid.h>
/**/
#include <ntddkbd.h>
#include <ntddmou.h>
#include <winstaw.h>
#include <regapi.h>
/*
* External Procedures defined here
*/
LONG WINAPI RegCdEnumerateA( HANDLE, PWDNAMEA, PULONG, PULONG, PCDNAMEA, PULONG );
LONG WINAPI RegCdEnumerateW( HANDLE, PWDNAMEW, PULONG, PULONG, PCDNAMEW, PULONG );
LONG WINAPI RegCdCreateA( HANDLE, PWDNAMEA, PCDNAMEA, BOOLEAN, PCDCONFIGA, ULONG );
LONG WINAPI RegCdCreateW( HANDLE, PWDNAMEW, PCDNAMEW, BOOLEAN, PCDCONFIGW, ULONG );
LONG WINAPI RegCdQueryA( HANDLE, PWDNAMEA, PCDNAMEA, PCDCONFIGA, ULONG, PULONG );
LONG WINAPI RegCdQueryW( HANDLE, PWDNAMEW, PCDNAMEW, PCDCONFIGW, ULONG, PULONG );
LONG WINAPI RegCdDeleteA( HANDLE, PWDNAMEA, PCDNAMEA );
LONG WINAPI RegCdDeleteW( HANDLE, PWDNAMEW, PCDNAMEW );
/*
* other internal Procedures used (not defined here)
*/
VOID CreateCd( HKEY, PCDCONFIG );
VOID QueryCd( HKEY, PCDCONFIG );
VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
VOID CdConfigU2A( PCDCONFIGA, PCDCONFIGW );
VOID CdConfigA2U( PCDCONFIGW, PCDCONFIGA );
/*******************************************************************************
*
* RegCdEnumerateA (ANSI stub)
*
* Returns a list of configured connection drivers in the registry.
*
* ENTRY:
*
* see RegCdEnumerateW
*
* EXIT:
*
* see RegCdEnumerateW, plus
*
* ERROR_NOT_ENOUGH_MEMORY - the LocalAlloc failed
*
******************************************************************************/
LONG WINAPI
RegCdEnumerateA( HANDLE hServer,
PWDNAMEA pWdName,
PULONG pIndex,
PULONG pEntries,
PCDNAMEA pCdName,
PULONG pByteCount )
{
PCDNAMEW pBuffer = NULL, pCdNameW;
WDNAMEW WdNameW;
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 ( pCdName && ByteCountW ) {
if ( !(pBuffer = LocalAlloc(0, ByteCountW)) )
return ( ERROR_NOT_ENOUGH_MEMORY );
}
/*
* Convert ANSI WdName to UNICODE.
*/
AnsiToUnicode( WdNameW, sizeof(WDNAMEW), pWdName );
/*
* Enumerate connection drivers
*/
pCdNameW = pBuffer;
Status = RegCdEnumerateW( hServer,
WdNameW,
pIndex,
pEntries,
pCdNameW,
&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))
&& pCdNameW && pCdName ) {
for ( Count = *pEntries; Count; Count-- ) {
UnicodeToAnsi( pCdName, sizeof(CDNAMEA), pCdNameW );
(char*)pCdName += sizeof(CDNAMEA);
(char*)pCdNameW += sizeof(CDNAMEW);
}
}
/*
* If we defined a buffer, free it now, then return the status
* of the Reg...EnumerateW function call.
*/
if ( pBuffer )
LocalFree(pBuffer);
return ( Status );
}
/*******************************************************************************
*
* RegCdEnumerateW (UNICODE)
*
* Returns a list of configured connection drivers in the registry.
*
* ENTRY:
*
* hServer (input)
* Handle to WinFrame Server
* pWdName (input)
* Points to the wdname to enumerate Cds for
* pIndex (input/output)
* Specifies the subkey index for the \Citrix\Wds\<wdname>\Cds 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.
* pCdName (input)
* Points to the buffer to receive the enumeration results, which are
* returned as an array of CDNAMEW 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
* pCdName 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 pCdName.
*
* EXIT:
*
* "No Error" codes:
* ERROR_SUCCESS - The enumeration completed as requested and there
* are more CDS subkeys (CDNAMEs) to be
* read.
* ERROR_NO_MORE_ITEMS - The enumeration completed as requested and there
* are no more CDS subkeys (CDNAMEs) to
* be read.
*
* "Error" codes:
* ERROR_OUTOFMEMORY - The pCdName buffer is too small for even one
* entry.
* ERROR_CANTOPEN - The Citrix\Cds key can't be opened.
*
******************************************************************************/
LONG WINAPI
RegCdEnumerateW( HANDLE hServer,
PWDNAMEW pWdName,
PULONG pIndex,
PULONG pEntries,
PCDNAMEW pCdName,
PULONG pByteCount )
{
LONG Status;
HKEY Handle;
ULONG Count;
ULONG i;
WCHAR KeyString[256];
/*
* Get the number of names to return
*/
Count = pCdName ?
min( *pByteCount / sizeof(CDNAME), *pEntries ) :
(ULONG) -1;
*pEntries = *pByteCount = 0;
/*
* Make sure buffer is big enough for at least one name
*/
if ( Count == 0 ) {
*pByteCount = sizeof(CDNAME);
return( ERROR_OUTOFMEMORY );
}
/*
* Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\Cds)
*/
wcscpy( KeyString, WD_REG_NAME );
wcscat( KeyString, L"\\" );
wcscat( KeyString, pWdName );
wcscat( KeyString, CD_REG_NAME );
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, KeyString, 0,
KEY_ENUMERATE_SUB_KEYS, &Handle ) != ERROR_SUCCESS ) {
return( ERROR_CANTOPEN );
}
/*
* Get list of connection drivers
*/
for ( i = 0; i < Count; i++ ) {
CDNAME CdName;
if ( (Status = RegEnumKey(Handle, *pIndex, CdName,
sizeof(CDNAME)/sizeof(TCHAR) )) != ERROR_SUCCESS )
break;
/*
* If caller supplied a buffer, then copy the CdName
* and increment the pointer and byte count. Always increment the
* entry count and index for the next iteration.
*/
if ( pCdName ) {
wcscpy( pCdName, CdName );
(char*)pCdName += sizeof(CDNAME);
*pByteCount += sizeof(CDNAME);
}
(*pEntries)++;
(*pIndex)++;
}
/*
* Close registry
*/
RegCloseKey( Handle );
return( Status );
}
/*******************************************************************************
*
* RegCdCreateA (ANSI stub)
*
* Creates a new Cd in the registry or updates an existing entry.
* (See RegCdCreateW)
*
* ENTRY:
* see RegCdCreateW
* EXIT:
* see RegCdCreateW
*
******************************************************************************/
LONG WINAPI
RegCdCreateA( HANDLE hServer,
PWDNAMEA pWdName,
PCDNAMEA pCdName,
BOOLEAN bCreate,
PCDCONFIGA pCdConfig,
ULONG CdConfigLength )
{
WDNAMEW WdNameW;
CDNAMEW CdNameW;
CDCONFIGW CdConfigW;
/*
* Validate target buffer size.
*/
if ( CdConfigLength < sizeof(CDCONFIGA) )
return( ERROR_INSUFFICIENT_BUFFER );
/*
* Convert ANSI WdName and CdName to UNICODE.
*/
AnsiToUnicode( WdNameW, sizeof(WDNAMEW), pWdName );
AnsiToUnicode( CdNameW, sizeof(CDNAMEW), pCdName );
/*
* Copy CDCONFIGA elements to CDCONFIGW elements.
*/
CdConfigA2U( &CdConfigW, pCdConfig );
/*
* Call RegCdCreateW & return it's status.
*/
return ( RegCdCreateW( hServer,
WdNameW,
CdNameW,
bCreate,
&CdConfigW,
sizeof(CdConfigW)) );
}
/*******************************************************************************
*
* RegCdCreateW (UNICODE)
*
* Creates a new Cd in the registry or updates an existing entry. The
* state of the bCreate flag determines whether this function will expect
* to create a new Cd 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 Cd for
* pCdName (input)
* Name of a new or exisiting connection driver in the registry.
* bCreate (input)
* TRUE if this is a creation of a new Cd
* FALSE if this is an update to an existing Cd
* pCdConfig (input)
* Pointer to a CDCONFIGW structure containing configuration
* information for the specified connection driver name.
* CdConfigLength (input)
* Specifies the length in bytes of the pCdConfig buffer.
* EXIT:
* ERROR_SUCCESS - no error
*
* ERROR_INSUFFICIENT_BUFFER - pCdConfig buffer too small
* ERROR_FILE_NOT_FOUND - can't open ...\Citrix\Wds\<wdname>\Cds key
* ERROR_CANNOT_MAKE - can't create Cd key (registry problem)
* ERROR_ALREADY_EXISTS - create; but Cd key already present
* ERROR_CANTOPEN - update; but Cd key could not be opened
*
******************************************************************************/
LONG WINAPI
RegCdCreateW( HANDLE hServer,
PWDNAMEW pWdName,
PCDNAMEW pCdName,
BOOLEAN bCreate,
PCDCONFIGW pCdConfig,
ULONG CdConfigLength )
{
HKEY Handle;
HKEY Handle1;
DWORD Disp;
WCHAR KeyString[256];
/*
* Validate length of buffer
*/
if ( CdConfigLength < sizeof(CDCONFIG) )
return( ERROR_INSUFFICIENT_BUFFER );
/*
* Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\Cds)
*/
wcscpy( KeyString, WD_REG_NAME );
wcscat( KeyString, L"\\" );
wcscat( KeyString, pWdName );
wcscat( KeyString, CD_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
* Cd name.
*/
if ( RegCreateKeyEx( Handle1, pCdName, 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
* Cd name.
*/
if ( RegOpenKeyEx( Handle1, pCdName, 0, KEY_ALL_ACCESS,
&Handle ) != ERROR_SUCCESS ) {
RegCloseKey( Handle1 );
return( ERROR_CANTOPEN );
}
}
RegCloseKey( Handle1 );
/*
* Save CDCONFIG Structure
*/
CreateCd( Handle, pCdConfig );
/*
* Close registry handle
*/
RegCloseKey( Handle );
return( ERROR_SUCCESS );
}
/*******************************************************************************
*
* RegCdQueryA (ANSI stub)
*
* Query configuration information of a connection driver in the registry.
*
* ENTRY:
* see RegCdQueryW
* EXIT:
* see RegCdQueryW
*
******************************************************************************/
LONG WINAPI
RegCdQueryA( HANDLE hServer,
PWDNAMEA pWdName,
PCDNAMEA pCdName,
PCDCONFIGA pCdConfig,
ULONG CdConfigLength,
PULONG pReturnLength )
{
WDNAMEW WdNameW;
CDNAMEW CdNameW;
CDCONFIGW CdConfigW;
LONG Status;
ULONG ReturnLengthW;
/*
* Validate length and zero-initialize the destination
* PDCONFIG3A structure.
*/
if ( CdConfigLength < sizeof(CDCONFIGA) )
return( ERROR_INSUFFICIENT_BUFFER );
memset(pCdConfig, 0, CdConfigLength);
/*
* Convert ANSI WdName and CdName to UNICODE.
*/
AnsiToUnicode(WdNameW, sizeof(WDNAMEW), pWdName);
AnsiToUnicode(CdNameW, sizeof(CDNAMEW), pCdName);
/*
* Query Cd.
*/
if ( (Status = RegCdQueryW( hServer,
WdNameW,
CdNameW,
&CdConfigW,
sizeof(CDCONFIGW),
&ReturnLengthW)) != ERROR_SUCCESS )
return ( Status );
/*
* Copy CDCONFIGW elements to CDCONFIGA elements.
*/
CdConfigU2A( pCdConfig, &CdConfigW );
*pReturnLength = sizeof(CDCONFIGA);
return( ERROR_SUCCESS );
}
/*******************************************************************************
*
* RegCdQueryW (UNICODE)
*
* Query configuration information of a connection driver in the registry.
*
* ENTRY:
* hServer (input)
* Handle to WinFrame Server
* pWdName (input)
* Points to the wdname to query Cd for
* pCdName (input)
* Name of an exisiting connection driver in the registry.
* pCdConfig (input)
* Pointer to a CDCONFIGW structure that will receive
* information about the specified connection driver name.
* CdConfigLength (input)
* Specifies the length in bytes of the pCdConfig buffer.
* pReturnLength (output)
* Receives the number of bytes placed in the pCdConfig buffer.
* EXIT:
* ERROR_SUCCESS - no error
*
******************************************************************************/
LONG WINAPI
RegCdQueryW( HANDLE hServer,
PWDNAMEW pWdName,
PCDNAMEW pCdName,
PCDCONFIGW pCdConfig,
ULONG CdConfigLength,
PULONG pReturnLength )
{
HKEY Handle;
HKEY Handle1;
WCHAR KeyString[256];
/*
* Validate length and zero-initialize the destination
* PDCONFIG3A structure.
*/
if ( CdConfigLength < sizeof(CDCONFIG) )
return( ERROR_INSUFFICIENT_BUFFER );
memset(pCdConfig, 0, CdConfigLength);
/*
* Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\Cds)
*/
wcscpy( KeyString, WD_REG_NAME );
wcscat( KeyString, L"\\" );
wcscat( KeyString, pWdName );
wcscat( KeyString, CD_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 Cd
*/
if ( RegOpenKeyEx( Handle1, pCdName, 0,
KEY_READ, &Handle ) != ERROR_SUCCESS ) {
RegCloseKey( Handle1 );
return( ERROR_FILE_NOT_FOUND );
}
RegCloseKey( Handle1 );
/*
* Query CDCONFIG Structure
*/
QueryCd( Handle, pCdConfig );
/*
* Close registry
*/
RegCloseKey( Handle );
*pReturnLength = sizeof(CDCONFIG);
return( ERROR_SUCCESS );
}
/*******************************************************************************
*
* RegCdDeleteA (ANSI stub)
*
* Deletes a connection driver from the registry.
*
* ENTRY:
*
* see RegCdDeleteW
*
* EXIT:
*
* see RegCdDeleteW
*
******************************************************************************/
LONG WINAPI
RegCdDeleteA( HANDLE hServer,
PWDNAMEA pWdName,
PCDNAMEA pCdName )
{
WDNAMEW WdNameW;
CDNAMEW CdNameW;
AnsiToUnicode( WdNameW, sizeof(WdNameW), pWdName);
AnsiToUnicode( CdNameW, sizeof(CdNameW), pCdName);
return ( RegCdDeleteW ( hServer, WdNameW, CdNameW ) );
}
/*******************************************************************************
*
* RegCdDeleteW (UNICODE)
*
* Deletes a connection driver from the registry.
*
* ENTRY:
* hServer (input)
* Handle to WinFrame Server
* pWdName (input)
* Points to the wdname to delete Cd from
* pCdName (input)
* Name of a connection driver to delete from the registry.
*
* EXIT:
* ERROR_SUCCESS - no error
*
******************************************************************************/
LONG WINAPI
RegCdDeleteW( HANDLE hServer,
PWDNAMEW pWdName,
PCDNAMEW pCdName )
{
LONG Status;
HKEY Handle;
HKEY Handle1;
WCHAR KeyString[256];
/*
* Open registry (LOCAL_MACHINE\....\Citrix\Wds\<wdname>\Cds)
*/
wcscpy( KeyString, WD_REG_NAME );
wcscat( KeyString, L"\\" );
wcscat( KeyString, pWdName );
wcscat( KeyString, CD_REG_NAME );
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, CD_REG_NAME, 0,
KEY_READ, &Handle ) != ERROR_SUCCESS ) {
return( ERROR_FILE_NOT_FOUND );
}
/*
* Now try to open the specified Cd
*/
if ( RegOpenKeyEx( Handle, pCdName, 0,
KEY_READ, &Handle1 ) != ERROR_SUCCESS ) {
RegCloseKey( Handle );
return( ERROR_FILE_NOT_FOUND );
}
/*
* Close the Cd key handle, delete the Cd,
* and close the parent handle
*/
RegCloseKey( Handle1 );
Status = RegDeleteKey( Handle, pCdName );
RegCloseKey( Handle );
return( Status );
}