/*++ Copyright (c) 1991-1993 Microsoft Corporation Module Name: ConfEnum.c Abstract: This module contains helper routines to _read fields out of the NT configuration files. This is for temporary use until the Configuration Registry is available. Author: John Rogers (JohnRo) 27-Nov-1991 Revision History: 27-Nov-1991 JohnRo Prepare for revised config handlers. (Actually swiped the NtRtl version of this code from RitaW.) 12-Mar-1992 JohnRo Added support for using the real Win32 registry. Added support for FAKE_PER_PROCESS_RW_CONFIG handling. 01-Apr-1992 JohnRo Use NetApiBufferAllocate() instead of private version. 06-May-1992 JohnRo REG_SZ now implies a UNICODE string, so we can't use REG_USZ anymore. 13-Jun-1992 JohnRo Title index parm is defunct (now lpReserved). Use PREFIX_ equates. 13-Apr-1993 JohnRo RAID 5483: server manager: wrong path given in repl dialog. Made changes suggested by PC-LINT 5.0 --*/ // These must be included first: #include // NT definitions #include // NT Rtl structures #include // NT Rtl structures #include // Needed by and #include // LAN Manager common definitions #include // (Needed by config.h) // These may be included in any order: #include // My prototype, LPNET_CONFIG_HANDLE, etc. #include // NET_CONFIG_HANDLE. #include // IF_DEBUG() #include // NetApiBufferAllocate(), NetApiBufferFree(). #include // LAN Manager network error definitions #include // PREFIX_ equates. NET_API_STATUS NetpEnumConfigSectionValues( IN LPNET_CONFIG_HANDLE ConfigHandle, OUT LPTSTR * KeywordBuffer, // Must be freed by NetApiBufferFree(). OUT LPTSTR * ValueBuffer, // Must be freed by NetApiBufferFree(). IN BOOL FirstTime ) /*++ Routine Description: This function gets the keyword value string from the configuration file. Arguments: ConfigHandle - Supplies a handle from NetpOpenConfigData for the appropriate section of the config data. KeywordBuffer - Returns the string of the keyword value which is copied into this buffer. This string will be allocated by this routine and must be freed by NetApiBufferFree(). ValueBuffer - Returns the string of the keyword value which is copied into this buffer. This string will be allocated by this routine and must be freed by NetApiBufferFree(). FirstTime - TRUE if caller wants to start at first keyword for this section. FALSE if caller wants to continue a previous enum on this handle. Return Value: NET_API_STATUS - NERR_Success or reason for failure. (NERR_CfgParamNotFound if no other values exist for this section.) --*/ { NET_CONFIG_HANDLE * lpnetHandle = ConfigHandle; // conv from opaque type NET_API_STATUS ApiStatus; NetpAssert( KeywordBuffer != NULL ); NetpAssert( ValueBuffer != NULL ); NetpAssert( (FirstTime==TRUE) || (FirstTime==FALSE) ); // // Assume error until proven otherwise. // *KeywordBuffer = NULL; *ValueBuffer = NULL; { DWORD dwType; LONG Error; DWORD MaxKeywordSize, MaxValueSize; DWORD NumberOfKeywords; LPTSTR ValueT; // // Find number of keys in this section. // ApiStatus = NetpNumberOfConfigKeywords ( lpnetHandle, & NumberOfKeywords ); NetpAssert( ApiStatus == NO_ERROR ); if (NumberOfKeywords == 0) { return (NERR_CfgParamNotFound); } // // Set our index to something reasonable. Note that some other // process might have deleted a keyword since we last did an enum, // so don't worry if the index gets larger than the number of keys. // if (FirstTime) { lpnetHandle->LastEnumIndex = 0; } else { DWORD MaxKeyIndex = NumberOfKeywords - 1; // Indices start at 0. if (MaxKeyIndex < (lpnetHandle->LastEnumIndex)) { // Bug or someone deleted. No way to tell, so assume latter. return (NERR_CfgParamNotFound); } else if (MaxKeyIndex == (lpnetHandle->LastEnumIndex)) { // This is how we normally exit at end of list. return (NERR_CfgParamNotFound); } else { // Normal bump to next entry. ++(lpnetHandle->LastEnumIndex); } } // // Compute sizes and allocate (maximum) buffers. // ApiStatus = NetpGetConfigMaxSizes ( lpnetHandle, & MaxKeywordSize, & MaxValueSize ); NetpAssert( ApiStatus == NO_ERROR ); NetpAssert( MaxKeywordSize > 0 ); NetpAssert( MaxValueSize > 0 ); ApiStatus = NetApiBufferAllocate( MaxValueSize, (LPVOID *) & ValueT); if (ApiStatus != NO_ERROR) { return (ApiStatus); } NetpAssert( ValueT != NULL); ApiStatus = NetApiBufferAllocate( MaxKeywordSize, (LPVOID *) KeywordBuffer); if (ApiStatus != NO_ERROR) { (void) NetApiBufferFree( ValueT ); return (ApiStatus); } NetpAssert( (*KeywordBuffer) != NULL); // // Get the keyword name and the value. // (Win32 reg APIs convert from TCHARs to UNICODE for us.) // IF_DEBUG(CONFIG) { NetpKdPrint(( PREFIX_NETLIB "NetpEnumConfigSectionValues: getting entry " FORMAT_DWORD "...\n", lpnetHandle->LastEnumIndex )); } Error = RegEnumValue ( lpnetHandle->WinRegKey, // handle to key (section) lpnetHandle->LastEnumIndex, // index of value name * KeywordBuffer, // value name (keyword) & MaxKeywordSize, // value name len (updated) NULL, // reserved & dwType, (LPVOID) ValueT, // TCHAR value & MaxValueSize ); // value size (updated) IF_DEBUG(CONFIG) { NetpKdPrint(( PREFIX_NETLIB "NetpEnumConfigSectionValues: RegEnumValue() ret " FORMAT_LONG ".\n", Error )); } if ( Error != ERROR_SUCCESS ) { NetpAssert( Error == ERROR_SUCCESS ); NetApiBufferFree( ValueT ); return (Error); } if (dwType == REG_SZ) { *ValueBuffer = ValueT; ApiStatus = NO_ERROR; } else if (dwType == REG_EXPAND_SZ) { LPTSTR UnexpandedString = ValueT; LPTSTR ExpandedString = NULL; // Expand string, using remote environment if necessary. ApiStatus = NetpExpandConfigString( lpnetHandle->UncServerName, // server name (or null char) UnexpandedString, &ExpandedString ); // expanded: alloc and set ptr if (ApiStatus != NO_ERROR) { NetpKdPrint(( PREFIX_NETLIB "NetpEnumConfigSectionValues: NetpExpandConfigString " " returned API status " FORMAT_API_STATUS ".\n", ApiStatus )); ExpandedString = NULL; } (VOID) NetApiBufferFree( UnexpandedString ); *ValueBuffer = ExpandedString; } else { // Unexpected data type. NetpAssert( dwType == REG_SZ ); *ValueBuffer = NULL; (VOID) NetApiBufferFree( ValueT ); ApiStatus = ERROR_INVALID_DATA; } } return (ApiStatus); }