mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
687 lines
20 KiB
687 lines
20 KiB
/*++
|
|
|
|
Copyright (c) 1991-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ConfOpen.c
|
|
|
|
Abstract:
|
|
|
|
This module contains:
|
|
|
|
NetpOpenConfigData
|
|
NetpOpenConfigDataEx
|
|
|
|
Author:
|
|
|
|
John Rogers (JohnRo) 02-Dec-1991
|
|
|
|
Environment:
|
|
|
|
Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
|
|
Requires ANSI C extensions: slash-slash comments, long external names.
|
|
|
|
Revision History:
|
|
|
|
02-Dec-1991 JohnRo
|
|
Created this routine, to prepare for revised config handlers.
|
|
(Actually, I swiped some of this code from RitaW.)
|
|
06-Jan-1992 JohnRo
|
|
Added support for FAKE_PER_PROCESS_RW_CONFIG handling.
|
|
09-Jan-1992 JohnRo
|
|
Try workaround for lib/linker problem with NetpIsRemote().
|
|
22-Mar-1992 JohnRo
|
|
Added support for using the real Win32 registry.
|
|
Added debug code to print the fake array.
|
|
Fixed a UNICODE bug which PC-LINT caught.
|
|
Fixed double _close of RTL config file.
|
|
Fixed memory _access error in setting fake end of array.
|
|
Use DBGSTATIC where applicable.
|
|
05-May-1992 JohnRo
|
|
Reflect movement of keys to under System\CurrentControlSet\Services.
|
|
08-May-1992 JohnRo
|
|
Use <prefix.h> equates.
|
|
21-May-1992 JohnRo
|
|
RAID 9826: Match revised winreg error codes.
|
|
08-Jul-1992 JohnRo
|
|
RAID 10503: srv mgr: repl dialog doesn't come up.
|
|
Added more debug output to track down bad error code during logoff.
|
|
23-Jul-1992 JohnRo
|
|
RAID 2274: repl svc should impersonate caller.
|
|
22-Sep-1992 JohnRo
|
|
Avoid GP fault printing first part of winreg handle.
|
|
28-Oct-1992 JohnRo
|
|
RAID 10136: NetConfig APIs don't work to remote NT server.
|
|
12-Apr-1993 JohnRo
|
|
RAID 5483: server manager: wrong path given in repl dialog.
|
|
|
|
--*/
|
|
|
|
|
|
// These must be included first:
|
|
|
|
#include <nt.h> // NT definitions
|
|
#include <ntrtl.h> // NT Rtl structures
|
|
#include <nturtl.h> // NT config Rtl routines
|
|
|
|
#include <windows.h> // Needed by <configp.h> and <winreg.h>
|
|
#include <lmcons.h> // LAN Manager common definitions
|
|
#include <netdebug.h> // (Needed by config.h)
|
|
|
|
// These may be included in any order:
|
|
|
|
#include <config.h> // My prototype, LPNET_CONFIG_HANDLE.
|
|
#include <configp.h> // NET_CONFIG_HANDLE, etc.
|
|
#include <debuglib.h> // IF_DEBUG().
|
|
#include <icanon.h> // NetpIsRemote(), etc.
|
|
#include <lmerr.h> // LAN Manager network error definitions
|
|
#include <netlib.h> // NetpMemoryAllocate(), etc.
|
|
#include <netlibnt.h> // NetpNtStatusToApiStatus
|
|
#include <prefix.h> // PREFIX_ equates.
|
|
#include <tstring.h> // NetpAlloc{type}From{type}, STRICMP(), etc.
|
|
|
|
|
|
#define DEFAULT_AREA TEXT("Parameters")
|
|
|
|
#define DEFAULT_ROOT_KEY HKEY_LOCAL_MACHINE
|
|
|
|
|
|
#if defined(USE_WIN32_CONFIG)
|
|
#elif defined(FAKE_PER_PROCESS_RW_CONFIG)
|
|
|
|
DBGSTATIC NET_API_STATUS
|
|
NetpCopyNtKeywordsToFakeRWSection(
|
|
IN OUT LPFAKE_RW_CONFIG_SECTION ThisSection,
|
|
IN PCONFIG_SECTION ConfigSection,
|
|
OUT LPTSTR_ARRAY * KeyValueArrayPtr // will be alloc'ed and ptr set
|
|
);
|
|
|
|
#endif // def FAKE_PER_PROCESS_RW_CONFIG
|
|
|
|
|
|
DBGSTATIC NET_API_STATUS
|
|
NetpSetupConfigSection (
|
|
IN NET_CONFIG_HANDLE * ConfigHandle,
|
|
IN LPTSTR SectionName
|
|
);
|
|
|
|
|
|
|
|
NET_API_STATUS
|
|
NetpOpenConfigData(
|
|
OUT LPNET_CONFIG_HANDLE *ConfigHandle,
|
|
IN LPTSTR UncServerName OPTIONAL,
|
|
IN LPTSTR SectionName,
|
|
IN BOOL ReadOnly
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function opens the system configuration file.
|
|
|
|
Arguments:
|
|
|
|
ConfigHandle - Points to a pointer which will be set to point to a
|
|
net config handle for this section name. ConfigHandle will be set to
|
|
NULL if any error occurs.
|
|
|
|
SectionName - Points to the new (NT) section name to be opened.
|
|
|
|
ReadOnly - Indicates whether all access through this net config handle is
|
|
to be read only.
|
|
|
|
Return Value:
|
|
|
|
NET_API_STATUS - NO_ERROR or reason for failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
return ( NetpOpenConfigDataEx(
|
|
ConfigHandle,
|
|
UncServerName,
|
|
SectionName, // Must be a SECT_NT_ name.
|
|
DEFAULT_AREA,
|
|
ReadOnly) );
|
|
|
|
} // NetpOpenConfigData
|
|
|
|
|
|
// NetpOpenConfigDataEx opens any area of a given service.
|
|
NET_API_STATUS
|
|
NetpOpenConfigDataEx(
|
|
OUT LPNET_CONFIG_HANDLE *ConfigHandle,
|
|
IN LPTSTR UncServerName OPTIONAL,
|
|
IN LPTSTR SectionName, // Must be a SECT_NT_ name.
|
|
IN LPTSTR AreaUnderSection OPTIONAL,
|
|
IN BOOL ReadOnly
|
|
)
|
|
{
|
|
|
|
NET_API_STATUS ApiStatus;
|
|
DWORD LocalOrRemote; // Will be set to ISLOCAL or ISREMOTE.
|
|
NET_CONFIG_HANDLE * MyHandle = NULL;
|
|
#if defined(USE_WIN32_CONFIG)
|
|
LONG Error;
|
|
HKEY RootKey = DEFAULT_ROOT_KEY;
|
|
#endif
|
|
|
|
NetpAssert( ConfigHandle != NULL );
|
|
*ConfigHandle = NULL; // Assume error until proven innocent.
|
|
|
|
if ( (SectionName == NULL) || (*SectionName == TCHAR_EOS) ) {
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
NetpAssert( (ReadOnly==TRUE) || (ReadOnly==FALSE) );
|
|
|
|
if ( (UncServerName != NULL ) && ((*UncServerName) != TCHAR_EOS) ) {
|
|
|
|
if( STRLEN(UncServerName) > MAX_PATH ) {
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
#if defined(USE_WIN32_CONFIG)
|
|
|
|
//
|
|
// Name was given. Canonicalize it and check if it's remote.
|
|
//
|
|
ApiStatus = NetpIsRemote(
|
|
UncServerName, // input: uncanon name
|
|
& LocalOrRemote, // output: local or remote flag
|
|
NULL, // dont need output (canon name)
|
|
0); // flags: normal
|
|
IF_DEBUG(CONFIG) {
|
|
NetpKdPrint(( PREFIX_NETLIB "NetpOpenConfigDataEx: canon status is "
|
|
FORMAT_API_STATUS ", Lcl/rmt=" FORMAT_HEX_DWORD ".\n",
|
|
ApiStatus, LocalOrRemote));
|
|
}
|
|
if (ApiStatus != NO_ERROR) {
|
|
return (ApiStatus);
|
|
}
|
|
|
|
if (LocalOrRemote == ISREMOTE) {
|
|
|
|
//
|
|
// Explicit remote name given.
|
|
//
|
|
|
|
Error = RegConnectRegistry(
|
|
UncServerName,
|
|
DEFAULT_ROOT_KEY,
|
|
& RootKey ); // result key
|
|
|
|
if (Error != ERROR_SUCCESS) {
|
|
NetpKdPrint(( PREFIX_NETLIB
|
|
"NetpOpenConfigDataEx: RegConnectRegistry(machine '"
|
|
FORMAT_LPTSTR "') ret error " FORMAT_LONG ".\n",
|
|
UncServerName, Error ));
|
|
return ((NET_API_STATUS) Error);
|
|
}
|
|
NetpAssert( RootKey != DEFAULT_ROOT_KEY );
|
|
|
|
}
|
|
#else
|
|
return (ERROR_NOT_SUPPORTED);
|
|
#endif
|
|
} else {
|
|
|
|
LocalOrRemote = ISLOCAL;
|
|
|
|
}
|
|
|
|
MyHandle = NetpMemoryAllocate( sizeof(NET_CONFIG_HANDLE) );
|
|
if (MyHandle == NULL) {
|
|
|
|
#if defined(USE_WIN32_CONFIG)
|
|
if (RootKey != DEFAULT_ROOT_KEY) {
|
|
(VOID) RegCloseKey( RootKey );
|
|
}
|
|
#endif
|
|
|
|
return (ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
#if defined(USE_WIN32_CONFIG)
|
|
{
|
|
LPTSTR AreaToUse = DEFAULT_AREA;
|
|
DWORD DesiredAccess;
|
|
DWORD SubKeySize;
|
|
LPTSTR SubKeyString;
|
|
HKEY SectionKey;
|
|
|
|
#define LM_SUBKEY_UNDER_LOCAL_MACHINE \
|
|
TEXT("System\\CurrentControlSet\\Services\\")
|
|
|
|
if (AreaUnderSection != NULL) {
|
|
if ((*AreaUnderSection) != TCHAR_EOS) {
|
|
AreaToUse = AreaUnderSection;
|
|
}
|
|
}
|
|
|
|
SubKeySize = ( STRLEN(LM_SUBKEY_UNDER_LOCAL_MACHINE)
|
|
+ STRLEN(SectionName)
|
|
+ 1 // backslash
|
|
+ STRLEN(AreaToUse)
|
|
+ 1 ) // trailing null
|
|
* sizeof(TCHAR);
|
|
SubKeyString = NetpMemoryAllocate( SubKeySize );
|
|
if (SubKeyString == NULL) {
|
|
return (ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
(void) STRCPY( SubKeyString, LM_SUBKEY_UNDER_LOCAL_MACHINE );
|
|
(void) STRCAT( SubKeyString, SectionName );
|
|
(void) STRCAT( SubKeyString, TEXT("\\") );
|
|
(void) STRCAT( SubKeyString, AreaToUse );
|
|
|
|
if ( ReadOnly ) {
|
|
DesiredAccess = KEY_READ;
|
|
} else {
|
|
DesiredAccess = KEY_READ | KEY_WRITE;
|
|
// DesiredAccess = KEY_ALL_ACCESS; // Everything but SYNCHRONIZE.
|
|
}
|
|
|
|
Error = RegOpenKeyEx (
|
|
RootKey,
|
|
SubKeyString,
|
|
REG_OPTION_NON_VOLATILE,
|
|
DesiredAccess,
|
|
& SectionKey );
|
|
IF_DEBUG(CONFIG) {
|
|
NetpKdPrint(( PREFIX_NETLIB
|
|
"NetpOpenConfigDataEx: RegOpenKeyEx(subkey '"
|
|
FORMAT_LPTSTR "') ret " FORMAT_LONG ", win reg handle at "
|
|
FORMAT_LPVOID " is " FORMAT_HEX_DWORD ".\n",
|
|
SubKeyString, Error, (LPVOID) &(MyHandle->WinRegKey),
|
|
(DWORD) SectionKey ));
|
|
}
|
|
if (Error == ERROR_FILE_NOT_FOUND) {
|
|
ApiStatus = NERR_CfgCompNotFound;
|
|
// Code below will free MyHandle, etc., based on ApiStatus.
|
|
} else if (Error != ERROR_SUCCESS) {
|
|
ApiStatus = (NET_API_STATUS) Error;
|
|
// Code below will free MyHandle, etc., based on ApiStatus.
|
|
} else {
|
|
ApiStatus = NO_ERROR;
|
|
}
|
|
|
|
NetpMemoryFree( SubKeyString );
|
|
|
|
if (RootKey != DEFAULT_ROOT_KEY) {
|
|
(VOID) RegCloseKey( RootKey );
|
|
}
|
|
|
|
MyHandle->WinRegKey = SectionKey;
|
|
|
|
#if 0
|
|
IF_DEBUG(CONFIG) {
|
|
if (SectionKey != NULL) {
|
|
NetpKdPrint(( PREFIX_NETLIB
|
|
"NetpOpenConfigDataEx: First part of winreg handle is "
|
|
FORMAT_HEX_DWORD ".\n", * (LPDWORD) (SectionKey) ));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
#elif defined(FAKE_PER_PROCESS_RW_CONFIG)
|
|
|
|
UNREFERENCED_PARAMETER( ReadOnly );
|
|
|
|
ApiStatus = NetpSetupConfigSection (
|
|
MyHandle,
|
|
SectionName
|
|
);
|
|
|
|
#else // NT RTL read-only temporary stuff
|
|
|
|
UNREFERENCED_PARAMETER( ReadOnly );
|
|
|
|
ApiStatus = NetpSetupConfigSection (
|
|
MyHandle,
|
|
SectionName
|
|
);
|
|
|
|
#endif // NT RTL read-only temporary stuff
|
|
|
|
if (ApiStatus != NO_ERROR) {
|
|
NetpMemoryFree( MyHandle );
|
|
MyHandle = NULL;
|
|
}
|
|
|
|
if (MyHandle != NULL) {
|
|
if (LocalOrRemote == ISREMOTE) {
|
|
|
|
(VOID) STRCPY(
|
|
MyHandle->UncServerName, // dest
|
|
UncServerName ); // src
|
|
|
|
} else {
|
|
|
|
MyHandle->UncServerName[0] = TCHAR_EOS;
|
|
}
|
|
}
|
|
|
|
*ConfigHandle = MyHandle; // Points to private handle, or is NULL on err.
|
|
return (ApiStatus);
|
|
|
|
} // NetpOpenConfigDataEx
|
|
|
|
|
|
|
|
#ifndef USE_WIN32_CONFIG
|
|
|
|
DBGSTATIC NET_API_STATUS
|
|
NetpSetupConfigSection (
|
|
IN NET_CONFIG_HANDLE * MyHandle,
|
|
IN LPTSTR lptstrSectionName
|
|
)
|
|
{
|
|
NET_API_STATUS ApiStatus;
|
|
NTSTATUS NtStatus;
|
|
|
|
#if defined(FAKE_PER_PROCESS_RW_CONFIG)
|
|
|
|
PCONFIG_FILE TheRtlConfigFileHandle;
|
|
PCONFIG_SECTION TheRtlConfigSectionHandle;
|
|
|
|
#else // NT RTL read-only temporary stuff
|
|
|
|
#define TheRtlConfigFileHandle MyHandle->ConfigFile
|
|
#define TheRtlConfigSectionHandle MyHandle->ConfigSection
|
|
|
|
#endif // NT RTL read-only temporary stuff
|
|
|
|
|
|
NetpAssert( MyHandle != NULL );
|
|
|
|
NtStatus = RtlOpenConfigFile(
|
|
NULL, // No config file path.
|
|
& TheRtlConfigFileHandle );
|
|
|
|
if (! NT_SUCCESS( NtStatus ) ) {
|
|
NetpKdPrint(( PREFIX_NETLIB
|
|
"NetpSetupConfigSection: RtlOpenConfigFile failed "
|
|
FORMAT_NTSTATUS "\n", NtStatus));
|
|
return (NetpNtStatusToApiStatus( NtStatus ));
|
|
}
|
|
NetpAssert( TheRtlConfigFileHandle != NULL );
|
|
|
|
|
|
|
|
//
|
|
// Have NT RTL look for section name.
|
|
//
|
|
{
|
|
LPSTR lpstrSectionName;
|
|
STRING stringSectionName;
|
|
|
|
lpstrSectionName = NetpAllocStrFromTStr( lptstrSectionName );
|
|
if (lpstrSectionName == NULL) {
|
|
RtlCloseConfigFile( TheRtlConfigFileHandle );
|
|
return (ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
RtlInitString( &stringSectionName, lpstrSectionName );
|
|
|
|
TheRtlConfigSectionHandle = RtlLocateSectionConfigFile(
|
|
TheRtlConfigFileHandle,
|
|
&stringSectionName);
|
|
NetpMemoryFree( lpstrSectionName );
|
|
}
|
|
|
|
if (TheRtlConfigSectionHandle == NULL) {
|
|
|
|
NetpKdPrint(( PREFIX_NETLIB
|
|
"NetpSetupConfigSection: RtlLocateSectionConfigFile ["
|
|
FORMAT_LPTSTR "] failed\n", lptstrSectionName ));
|
|
|
|
RtlCloseConfigFile( TheRtlConfigFileHandle );
|
|
return (NERR_CfgCompNotFound);
|
|
}
|
|
ApiStatus = NO_ERROR;
|
|
|
|
#ifdef FAKE_PER_PROCESS_RW_CONFIG
|
|
NetpAssert( NetpFakePerProcessRWConfigLock != NULL );
|
|
|
|
ACQUIRE_LOCK( NetpFakePerProcessRWConfigLock ); // Wait for excl access.
|
|
|
|
//
|
|
// Search for match on this section name in our fake array.
|
|
//
|
|
{
|
|
LPTSTR_ARRAY KeyValueArray;
|
|
LPFAKE_RW_CONFIG_SECTION ThisSection;
|
|
|
|
|
|
ThisSection = NetpFindFakeConfigSection ( // Find section, or NULL.
|
|
lptstrSectionName);
|
|
|
|
if (ThisSection == NULL) {
|
|
|
|
//
|
|
// No match on section name, must create new one.
|
|
// This involves reallocating a global array
|
|
// (NetpFakePerProcessRWConfigData). Of course, other parts of
|
|
// this process may fail, so we have to be prepared to put the
|
|
// global array back the way it was.
|
|
//
|
|
|
|
LPFAKE_RW_CONFIG_SECTION NewGlobalAddr;
|
|
DWORD OldSectionCount = NetpFakeRWSectionCount;
|
|
DWORD NewSectionCount = OldSectionCount+1;
|
|
NetpAssert(NewSectionCount >= 1);
|
|
|
|
KeyValueArray = NULL;
|
|
NewGlobalAddr = NetpMemoryReallocate(
|
|
NetpFakePerProcessRWConfigData, // old global array
|
|
NewSectionCount * sizeof( FAKE_RW_CONFIG_SECTION ) );
|
|
|
|
if (NewGlobalAddr == NULL) { // realloc failed
|
|
|
|
ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|
// Don't forget to release lock...
|
|
|
|
} else { // realloc succeeded
|
|
|
|
LPTSTR SectionNameCopy;
|
|
|
|
NetpFakePerProcessRWConfigData = NewGlobalAddr;
|
|
|
|
ThisSection = & NewGlobalAddr[NewSectionCount-1];
|
|
SectionNameCopy = NetpAllocTStrFromTStr( lptstrSectionName );
|
|
if (SectionNameCopy == NULL) {
|
|
ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
// Put size of array back to what it was.
|
|
NetpFakePerProcessRWConfigData = NetpMemoryReallocate(
|
|
NewGlobalAddr,
|
|
OldSectionCount * sizeof( FAKE_RW_CONFIG_SECTION ) );
|
|
KeyValueArray = NULL;
|
|
// Don't forget to release lock...
|
|
} else {
|
|
NetpFakePerProcessRWConfigData->SectionName
|
|
= SectionNameCopy;
|
|
|
|
// Copy stuff from RTL tables part here.
|
|
ApiStatus = NetpCopyNtKeywordsToFakeRWSection(
|
|
ThisSection, // fake section struct
|
|
TheRtlConfigSectionHandle, // NT RTL section handle
|
|
& KeyValueArray); // alloc'ed and ptr set.
|
|
|
|
if (ApiStatus == NO_ERROR) {
|
|
MyHandle->FakeRWDataForThisSection = ThisSection;
|
|
NetpFakeRWSectionCount = NewSectionCount;
|
|
IF_DEBUG(CONFIG) {
|
|
NetpKdPrint((PREFIX_NETLIB
|
|
"NetpSetupConfigSection: "
|
|
"built fake section:\n"));
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
} else { // found match on section
|
|
IF_DEBUG(CONFIG) {
|
|
NetpKdPrint(( PREFIX_NETLIB
|
|
"NetpSetupConfigSection: found fake section:\n" ));
|
|
}
|
|
KeyValueArray = ThisSection->KeyValueArrayPtr;
|
|
}
|
|
|
|
NetpAssert( KeyValueArray != NULL );
|
|
|
|
MyHandle->FakeRWDataForThisSection = ThisSection;
|
|
MyHandle->NextFakeEnumEntry = KeyValueArray;
|
|
|
|
IF_DEBUG(CONFIG) {
|
|
NetpKdPrint(( PREFIX_NETLIB
|
|
"NetpSetupConfigSection: returning status "
|
|
FORMAT_API_STATUS ".\n", ApiStatus ));
|
|
NetpDbgDisplayConfigSection( MyHandle );
|
|
}
|
|
|
|
}
|
|
|
|
RELEASE_LOCK( NetpFakePerProcessRWConfigLock );
|
|
|
|
RtlCloseConfigFile( TheRtlConfigFileHandle );
|
|
|
|
#endif // FAKE_PER_PROCESS_RW_CONFIG
|
|
|
|
return (ApiStatus);
|
|
|
|
} // NetpSetupConfigSection
|
|
|
|
|
|
#if defined(FAKE_PER_PROCESS_RW_CONFIG)
|
|
|
|
DBGSTATIC NET_API_STATUS
|
|
NetpCopyNtKeywordsToFakeRWSection(
|
|
IN OUT LPFAKE_RW_CONFIG_SECTION ThisSection,
|
|
IN PCONFIG_SECTION ConfigSection,
|
|
OUT LPTSTR_ARRAY * KeyValueArrayPtr
|
|
)
|
|
{
|
|
DWORD ArraySizeSoFar = 0;
|
|
BOOLEAN FirstTime = TRUE;
|
|
LPTSTR_ARRAY KeyValueArray = NULL; // Will be realloc'ed as we go.
|
|
DWORD KeywordLength; // Chars in keyword (incl null char).
|
|
LPTSTR lptstrKeyword;
|
|
PCONFIG_KEYWORD lprtlKeyword;
|
|
LPTSTR lptstrValue;
|
|
LPTSTR_ARRAY NewArray;
|
|
DWORD OldArraySize;
|
|
|
|
//
|
|
// Loop for each keyword that is in NT RTL .cfg file.
|
|
//
|
|
|
|
while (TRUE) {
|
|
|
|
//
|
|
// Tell caller about array we've got (if any).
|
|
//
|
|
* KeyValueArrayPtr = KeyValueArray;
|
|
|
|
//
|
|
// Ask NT RTL to find first/next keyword in this section.
|
|
//
|
|
|
|
lprtlKeyword = RtlEnumerateKeywordConfigFile(
|
|
ConfigSection,
|
|
FirstTime);
|
|
if (lprtlKeyword == NULL) {
|
|
break; // done
|
|
}
|
|
|
|
//
|
|
// Since we'll want to put next keyword at end of current array
|
|
// (if any), remember that size before we muck with anything.
|
|
//
|
|
OldArraySize = ArraySizeSoFar;
|
|
|
|
//
|
|
// Expand KeyValueArray to allow for this keyword and its value.
|
|
// Don't forget that we'll need trailing nulls for each of these.
|
|
//
|
|
KeywordLength = lprtlKeyword->Keyword.Length + 1;
|
|
NetpAssert( KeywordLength > 1 );
|
|
ArraySizeSoFar += ( KeywordLength
|
|
+ lprtlKeyword->Value.Length + 1 ) * sizeof(TCHAR);
|
|
NewArray = NetpMemoryReallocate(
|
|
KeyValueArray,
|
|
ArraySizeSoFar);
|
|
|
|
if (NewArray == NULL) {
|
|
NetpMemoryFree( KeyValueArray );
|
|
* KeyValueArrayPtr = NULL;;
|
|
return (ERROR_NOT_ENOUGH_MEMORY);
|
|
} else {
|
|
KeyValueArray = NewArray;
|
|
}
|
|
|
|
lptstrKeyword = (LPTSTR) NetpPointerPlusSomeBytes(
|
|
KeyValueArray,
|
|
OldArraySize);
|
|
NetpAssert( lptstrKeyword != NULL );
|
|
|
|
|
|
//
|
|
// Copy keyword.
|
|
//
|
|
|
|
NetpCopyStringToTStr (
|
|
lptstrKeyword, // dest
|
|
& lprtlKeyword->Keyword); // src
|
|
|
|
//
|
|
// Copy value for this keyword.
|
|
//
|
|
|
|
lptstrValue = lptstrKeyword + KeywordLength;
|
|
NetpAssert( lptstrValue != NULL );
|
|
NetpCopyStringToTStr (
|
|
lptstrValue, // dest
|
|
& lprtlKeyword->Value); // src
|
|
|
|
FirstTime = FALSE;
|
|
}
|
|
|
|
//
|
|
// Expand array to make room for end of array marker.
|
|
// Note that the array might not exist yet, which is OK.
|
|
//
|
|
ArraySizeSoFar += sizeof(TCHAR);
|
|
NewArray = NetpMemoryReallocate(
|
|
KeyValueArray, // May be NULL if zero entries.
|
|
ArraySizeSoFar );
|
|
if (NewArray == NULL) { // Only NULL if unable to allocate.
|
|
NetpMemoryFree( KeyValueArray );
|
|
* KeyValueArrayPtr = NULL;;
|
|
return (ERROR_NOT_ENOUGH_MEMORY);
|
|
} else {
|
|
KeyValueArray = NewArray;
|
|
}
|
|
|
|
//
|
|
// Mark end of array.
|
|
//
|
|
KeyValueArray[ArraySizeSoFar / sizeof(TCHAR)] = TCHAR_EOS;
|
|
|
|
NetpAssert( NetpIsValidFakeConfigArray( KeyValueArray ) );
|
|
|
|
ThisSection->KeyValueArrayPtr = KeyValueArray;
|
|
|
|
* KeyValueArrayPtr = KeyValueArray;
|
|
|
|
return (NO_ERROR);
|
|
|
|
} // NetpCopyNtKeywordsToFakeRWSection
|
|
|
|
#endif // def FAKE_PER_PROCESS_RW_CONFIG
|
|
|
|
#endif // ndef USE_WIN32_CONFIG
|