/************************************************************************* * * regcd.c * * Register APIs for CDs (connection drivers) * * Copyright (c) 1998 Microsoft Corporation * * *************************************************************************/ /* * Includes */ #include /* Added By SalimC */ #include /**/ #include #include #include #include /* * 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\\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\\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\\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\\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\\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\\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 ); }