diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/net/svcdlls/rpl/server/config.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/net/svcdlls/rpl/server/config.c')
-rw-r--r-- | private/net/svcdlls/rpl/server/config.c | 711 |
1 files changed, 711 insertions, 0 deletions
diff --git a/private/net/svcdlls/rpl/server/config.c b/private/net/svcdlls/rpl/server/config.c new file mode 100644 index 000000000..698cb962e --- /dev/null +++ b/private/net/svcdlls/rpl/server/config.c @@ -0,0 +1,711 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + config.c + +Abstract: + + This module contains RPL config apis: ConfigEnum. + +Author: + + Vladimir Z. Vulovic (vladimv) 05 - November - 1993 + +Revision History: + + 05-Nov-1993 vladimv + Created + +--*/ + +#include "local.h" +#include "rpldb.h" +#include "db.h" +#include "dblib.h" +#include "boot.h" +#include "profile.h" +#define RPLCONFIG_ALLOCATE +#include "config.h" +#undef RPLCONFIG_ALLOCATE +#include "setup.h" // IsConfigEnabled() + + + +DWORD ConfigSetInfo( + IN PRPL_SESSION pSession, + IN DWORD Level, + IN LPVOID Buffer, + OUT LPDWORD pErrorParameter + ) +{ + LPRPL_CONFIG_INFO_2 Info = Buffer; + switch( Level) { + case 2: + if ( Info->FitPersonal != NULL) { + *pErrorParameter = CONFIG_FitPersonal; + CallM( JetSetColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ CONFIG_FitPersonal].ColumnId, + Info->FitPersonal, + ( wcslen( Info->FitPersonal) + 1) * sizeof(WCHAR), + 0, NULL)); + } + if ( Info->FitShared != NULL) { + *pErrorParameter = CONFIG_FitShared; + CallM( JetSetColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ CONFIG_FitShared].ColumnId, + Info->FitShared, + ( wcslen( Info->FitShared) + 1) * sizeof(WCHAR), + 0, NULL)); + } + if ( Info->DirName4 != NULL) { + *pErrorParameter = CONFIG_DirName4; + CallM( JetSetColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ CONFIG_DirName4].ColumnId, + Info->DirName4, + ( wcslen( Info->DirName4) + 1) * sizeof(WCHAR), + 0, NULL)); + } + if ( Info->DirName3 != NULL) { + *pErrorParameter = CONFIG_DirName3; + CallM( JetSetColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ CONFIG_DirName3].ColumnId, + Info->DirName3, + ( wcslen( Info->DirName3) + 1) * sizeof(WCHAR), + 0, NULL)); + } + if ( Info->DirName2 != NULL) { + *pErrorParameter = CONFIG_DirName2; + CallM( JetSetColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ CONFIG_DirName2].ColumnId, + Info->DirName2, + ( wcslen( Info->DirName2) + 1) * sizeof(WCHAR), + 0, NULL)); + } + if ( Info->DirName != NULL) { + *pErrorParameter = CONFIG_DirName; + CallM( JetSetColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ CONFIG_DirName].ColumnId, + Info->DirName, + ( wcslen( Info->DirName) + 1) * sizeof(WCHAR), + 0, NULL)); + } + if ( Info->BootName != NULL) { + *pErrorParameter = CONFIG_BootName; + CallM( JetSetColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ CONFIG_BootName].ColumnId, + Info->BootName, + ( wcslen( Info->BootName) + 1) * sizeof(WCHAR), + 0, NULL)); + } + NOTHING; // fall through + case 1: + if ( Info->Flags != 0) { + *pErrorParameter = CONFIG_Flags; + CallM( JetSetColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ CONFIG_Flags].ColumnId, + &Info->Flags, sizeof( Info->Flags), 0, NULL)); + } + NOTHING; // fall through + case 0: + if ( Info->ConfigComment != NULL) { + *pErrorParameter = CONFIG_ConfigComment; + CallM( JetSetColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ CONFIG_ConfigComment].ColumnId, + Info->ConfigComment, + ( wcslen( Info->ConfigComment) + 1) * sizeof(WCHAR), + 0, NULL)); + } + if ( Info->ConfigName != NULL) { + *pErrorParameter = CONFIG_ConfigName; + CallM( JetSetColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ CONFIG_ConfigName].ColumnId, + Info->ConfigName, + ( wcslen( Info->ConfigName) + 1) * sizeof(WCHAR), + 0, NULL)); + } + break; + } + return( NO_ERROR); +} + + +DWORD ConfigGetField( + IN PRPL_SESSION pSession, + IN DWORD FieldIndex, + OUT LPVOID * pData, + IN OUT LPINT pSpaceLeft + ) +{ + BYTE LocalBuffer[ 300]; + PBYTE Buffer; + DWORD DataSize; + DWORD BufferSize; + JET_ERR JetError; + + switch( FieldIndex) { + case CONFIG_Flags: + Buffer = (PBYTE)pData; + BufferSize = sizeof( DWORD); + break; + default: + Buffer = LocalBuffer; + BufferSize = sizeof( LocalBuffer); + break; + } + JetError = JetRetrieveColumn( pSession->SesId, pSession->ConfigTableId, + ConfigTable[ FieldIndex].ColumnId, Buffer, + BufferSize, &DataSize, 0, NULL); + if ( JetError < 0) { + RplDump( ++RG_Assert, ("JetError=%d", JetError)); + return( NERR_RplConfigInfoCorrupted); + } + if ( Buffer != LocalBuffer) { + if ( BufferSize == DataSize) { + return( NO_ERROR); + } else { + RplDump( ++RG_Assert, ("Bad DataSize=0x%x", DataSize)); + return( NERR_RplConfigInfoCorrupted); + } + } + // + // We have done with fixed data. From here on we deal with unicode + // strings only. + // + if ( DataSize > sizeof( LocalBuffer)) { + RplDump( ++RG_Assert, ( "Too big DataSize=0x%x", DataSize)); + return( NERR_RplConfigInfoCorrupted); + } + if ( DataSize == 0) { + if ( JetError != JET_wrnColumnNull) { + RplDump( ++RG_Assert, ( "JetError=%d", JetError)); + return( NERR_RplConfigInfoCorrupted); + } else { + *pData = NULL; // so RPC rpcrt4!_tree_size_ndr() does not bomb here + return( NO_ERROR); + } + } + if ( DataSize & 1 != 0 || wcslen((PWCHAR)LocalBuffer) + 1 != DataSize/2) { + RplDump( ++RG_Assert, ("LocalBuffer=0x%x, DataSize=0x%x", LocalBuffer, DataSize)); + return( NERR_RplConfigInfoCorrupted); + } + *pData = MIDL_user_allocate( DataSize); + if ( *pData == NULL) { + RplDump( ++RG_Assert, ( "Error=%d", GetLastError())); + RPL_RETURN( ERROR_NOT_ENOUGH_MEMORY); + } + memcpy( *pData, LocalBuffer, DataSize); + *pSpaceLeft -= DataSize; // BUGBUG might become negative? + return( NO_ERROR); +} + + +DWORD ConfigGetInfo( + IN PRPL_SESSION pSession, + IN LPWSTR ConfigName, + IN DWORD Level, + OUT LPVOID Buffer, + IN OUT LPINT pSpaceLeft + ) +{ + DWORD Error; + LPRPL_CONFIG_INFO_2 Info = Buffer; + + switch( Level) { + case 2: + Error = ConfigGetField( pSession, CONFIG_FitPersonal, &Info->FitPersonal, pSpaceLeft); + if ( Error != NO_ERROR) { + return( Error); + } + Error = ConfigGetField( pSession, CONFIG_FitShared, &Info->FitShared, pSpaceLeft); + if ( Error != NO_ERROR) { + return( Error); + } + Error = ConfigGetField( pSession, CONFIG_DirName4, &Info->DirName4, pSpaceLeft); + if ( Error != NO_ERROR) { + return( Error); + } + Error = ConfigGetField( pSession, CONFIG_DirName3, &Info->DirName3, pSpaceLeft); + if ( Error != NO_ERROR) { + return( Error); + } + Error = ConfigGetField( pSession, CONFIG_DirName2, &Info->DirName2, pSpaceLeft); + if ( Error != NO_ERROR) { + return( Error); + } + Error = ConfigGetField( pSession, CONFIG_DirName, &Info->DirName, pSpaceLeft); + if ( Error != NO_ERROR) { + return( Error); + } + Error = ConfigGetField( pSession, CONFIG_BootName, &Info->BootName, pSpaceLeft); + if ( Error != NO_ERROR) { + return( Error); + } + NOTHING; // fall through + case 1: + Error = ConfigGetField( pSession, CONFIG_Flags, (LPVOID *)&Info->Flags, pSpaceLeft); + if ( Error != NO_ERROR) { + return( Error); + } + case 0: + Error = ConfigGetField( pSession, CONFIG_ConfigComment, &Info->ConfigComment, pSpaceLeft); + if ( Error != NO_ERROR) { + return( Error); + } + if ( ConfigName == NULL) { + Error = ConfigGetField( pSession, CONFIG_ConfigName, &Info->ConfigName, pSpaceLeft); + if ( Error != NO_ERROR) { + return( Error); + } + } else { + DWORD DataSize = (wcslen( ConfigName) + 1) * sizeof(WCHAR); + Info->ConfigName = MIDL_user_allocate( DataSize); + if ( Info->ConfigName == NULL) { + return( ERROR_NOT_ENOUGH_MEMORY); + } + RplDump( RG_DebugLevel & RPL_DEBUG_CONFIG, ( "ConfigName=0x%x", Info->ConfigName)); + memcpy( Info->ConfigName, ConfigName, DataSize); + *pSpaceLeft -= DataSize; + } + break; + default: + return( ERROR_INVALID_LEVEL); + break; + } + return( NO_ERROR); +} + + + +VOID ConfigGetInfoCleanup( + IN DWORD Level, + IN OUT LPVOID Buffer + ) +{ + LPRPL_CONFIG_INFO_2 Info = Buffer; + + switch( Level) { + case 2: + if ( Info->FitPersonal != NULL) { + MIDL_user_free( Info->FitPersonal); + } + if ( Info->FitShared != NULL) { + MIDL_user_free( Info->FitShared); + } + if ( Info->DirName4 != NULL) { + MIDL_user_free( Info->DirName4); + } + if ( Info->DirName3 != NULL) { + MIDL_user_free( Info->DirName3); + } + if ( Info->DirName2 != NULL) { + MIDL_user_free( Info->DirName2); + } + if ( Info->DirName != NULL) { + MIDL_user_free( Info->DirName); + } + if ( Info->BootName != NULL) { + MIDL_user_free( Info->BootName); + } + NOTHING; // fall through + case 1: + NOTHING; // fall through + case 0: + if ( Info->ConfigComment != NULL) { + MIDL_user_free( Info->ConfigComment); + } + if ( Info->ConfigName != NULL) { + MIDL_user_free( Info->ConfigName); + } + break; + } +} + + +NET_API_STATUS NET_API_FUNCTION +NetrRplConfigAdd( + IN RPL_HANDLE ServerHandle, + IN DWORD Level, + OUT LPRPL_CONFIG_INFO_STRUCT ConfigInfoStruct, + OUT LPDWORD pErrorParameter OPTIONAL + ) +{ + LPRPL_CONFIG_INFO_2 Info; + LPVOID Buffer; + DWORD Error; + DWORD ErrorParameter; + PRPL_SESSION pSession = &RG_ApiSession; + + ErrorParameter = INVALID_ERROR_PARAMETER; + Buffer = Info = ConfigInfoStruct->ConfigInfo2; + + switch( Level) { + case 2: + if ( !ValidName( Info->FitPersonal, RPL_MAX_STRING_LENGTH, TRUE)) { + ErrorParameter = CONFIG_FitPersonal; + break; + } + if ( !ValidName( Info->FitShared, RPL_MAX_STRING_LENGTH, TRUE)) { + ErrorParameter = CONFIG_FitShared; + break; + } + if ( !ValidName( Info->DirName4, RPL_MAX_STRING_LENGTH, FALSE)) { + ErrorParameter = CONFIG_DirName4; + break; + } + if ( !ValidName( Info->DirName3, RPL_MAX_STRING_LENGTH, FALSE)) { + ErrorParameter = CONFIG_DirName3; + break; + } + if ( !ValidName( Info->DirName2, RPL_MAX_STRING_LENGTH, TRUE)) { + ErrorParameter = CONFIG_DirName2; + break; + } + if ( !ValidName( Info->DirName, RPL_MAX_STRING_LENGTH, TRUE)) { + ErrorParameter = CONFIG_DirName; + break; + } + if ( !ValidName( Info->BootName, RPL_MAX_BOOT_NAME_LENGTH, TRUE)) { + ErrorParameter = CONFIG_BootName; + break; + } + _wcsupr( Info->BootName); + if ( Info->Flags & ~CONFIG_FLAGS_MASK_ENABLED) { + ErrorParameter = CONFIG_Flags; + break; + } + switch ( Info->Flags) { + case 0: + Info->Flags = RplConfigEnabled( Info->DirName2) == TRUE ? + CONFIG_FLAGS_ENABLED_TRUE : CONFIG_FLAGS_ENABLED_FALSE; + break; + case CONFIG_FLAGS_ENABLED_TRUE: + case CONFIG_FLAGS_ENABLED_FALSE: + break; + default: + ErrorParameter = CONFIG_Flags; + break; + } + if ( RPL_STRING_TOO_LONG( Info->ConfigComment)) { + ErrorParameter = CONFIG_ConfigComment; + break; + } + if ( !ValidName( Info->ConfigName, RPL_MAX_CONFIG_NAME_LENGTH, TRUE)) { + ErrorParameter = CONFIG_ConfigName; + break; + } + _wcsupr( Info->ConfigName); + break; + default: + return( ERROR_INVALID_LEVEL); + break; + } + + if ( ErrorParameter != INVALID_ERROR_PARAMETER) { + if ( ARGUMENT_PRESENT( pErrorParameter)) { + *pErrorParameter = ErrorParameter; + } + return( ERROR_INVALID_PARAMETER); + } + + EnterCriticalSection( &RG_ProtectDatabase); + Call( JetBeginTransaction( pSession->SesId)); + + // + // Verify that ConfigName is available in the database. + // + if ( RplFind( pSession, CONFIG_TABLE_TAG, Info->ConfigName)) { + Error = NERR_RplConfigNameUnavailable; + goto cleanup; + } + + CallJ( JetPrepareUpdate( pSession->SesId, pSession->ConfigTableId, JET_prepInsert)); + + Error = ConfigSetInfo( pSession, Level, Buffer, &ErrorParameter); + if ( Error == ERROR_SUCCESS) { + ErrorParameter = 0; + CallJ( JetUpdate( pSession->SesId, pSession->ConfigTableId, NULL, 0, NULL)); + } + +cleanup: + if ( Error == NO_ERROR) { + Call( JetCommitTransaction( pSession->SesId, JET_bitCommitFlush)); + } else { + Call( JetRollback( pSession->SesId, JET_bitRollbackAll)); + } + LeaveCriticalSection( &RG_ProtectDatabase); + + if ( Error != ERROR_SUCCESS) { + if ( ARGUMENT_PRESENT( pErrorParameter)) { + *pErrorParameter = ErrorParameter; + } + } + return( Error); +} + + +NET_API_STATUS NET_API_FUNCTION +NetrRplConfigDel( + IN RPL_HANDLE ServerHandle, + IN LPWSTR ConfigName + ) +/*++ +--*/ +{ + DWORD Error; + PRPL_SESSION pSession = &RG_ApiSession; + + _wcsupr( ConfigName); + + EnterCriticalSection( &RG_ProtectDatabase); + Call( JetBeginTransaction( pSession->SesId)); + + if ( RplFindByField( pSession, PROFILE_TABLE_TAG, + PROFILE_INDEX_ConfigNameProfileName, ConfigName)) { + // + // We found a PROFILE record which uses this CONFIG. + // + Error = NERR_RplConfigNotEmpty; + goto cleanup; + } + if ( !RplFind( pSession, CONFIG_TABLE_TAG, ConfigName)) { + Error = NERR_RplConfigNotFound; + goto cleanup; + } + CallJ( JetDelete( pSession->SesId, pSession->ConfigTableId)); + Error = NO_ERROR; + +cleanup: + if ( Error == NO_ERROR) { + Call( JetCommitTransaction( pSession->SesId, JET_bitCommitFlush)); + } else { + Call( JetRollback( pSession->SesId, JET_bitRollbackAll)); + } + LeaveCriticalSection( &RG_ProtectDatabase); + return( Error); +} + + +NET_API_STATUS NET_API_FUNCTION +NetrRplConfigEnum( + IN RPL_RPC_HANDLE ServerHandle, + IN PWCHAR AdapterName, + IN OUT LPRPL_CONFIG_ENUM ConfigEnum, + IN DWORD PrefMaxLength, + OUT LPDWORD TotalEntries, + IN OUT LPDWORD pResumeHandle OPTIONAL + ) +/*++ + +Routine Description: + + If AdapterName is null, enumerate all configurations. + If AdapterName is not null, enumerate all configurations that can support + this adapter id. + +Arguments: + + pServerHandle - ptr to RPL_HANDLE + + InfoStruct - Pointer to a structure that contains the information that + RPC needs about the returned data. This structure contains the + following information: + Level - The desired information level - indicates how to + interpret the structure of the returned buffer. + EntriesRead - Indicates how many elements are returned in the + array of structures that are returned. + BufferPointer - Location for the pointer to the array of + structures that are being returned. + + PrefMaxLen - Indicates a maximum size limit that the caller will allow + for (the return buffer. + + TotalEntries - Pointer to a value that upon return indicates the total + number of entries in the "active" database. + + pResumeHandle - Inidcates where to restart the enumeration. This is an + optional parameter and can be NULL. + +Return Value: + NO_ERROR if success. + +--*/ +{ + LPBYTE Buffer; + DWORD TypicalSize; + DWORD CoreSize; + DWORD Error; + INT SpaceLeft; + DWORD ArrayLength; + DWORD EntriesRead; + BOOL InfoError; + BOOL TableEnd; + RPL_FILTER Filter; + PRPL_FILTER pFilter; + PRPL_SESSION pSession = &RG_ApiSession; + + switch( ConfigEnum->Level) { + case 2: + TypicalSize = CoreSize = sizeof( RPL_CONFIG_INFO_2); + TypicalSize += 20 * sizeof( WCHAR); // typical size of FitPersonal + TypicalSize += 20 * sizeof( WCHAR); // typical size of FitShared + TypicalSize += 12 * sizeof( WCHAR); // typical size of DirName4 + TypicalSize += 12 * sizeof( WCHAR); // typical size of DirName3 + TypicalSize += 12 * sizeof( WCHAR); // typical size of DirName2 + TypicalSize += 12 * sizeof( WCHAR); // typical size of DirName + TypicalSize += 8 * sizeof( WCHAR); // typical size of BootName + NOTHING; // fall through + case 1: + if ( ConfigEnum->Level == 1) { + TypicalSize = CoreSize = sizeof( RPL_CONFIG_INFO_1); + } + NOTHING; // fall through + case 0: + if ( ConfigEnum->Level == 0) { + TypicalSize = CoreSize = sizeof( RPL_CONFIG_INFO_0); + } + TypicalSize += 20 * sizeof( WCHAR); // typical size of ConfigComment + TypicalSize += 8 * sizeof( WCHAR); // typical size of ConfigName + break; + default: + return( ERROR_INVALID_LEVEL); + break; + } + + if ( AdapterName != NULL) { + pFilter = &Filter; + if ( !ValidHexName( AdapterName, RPL_ADAPTER_NAME_LENGTH, TRUE)) { + return( ERROR_INVALID_PARAMETER); + } + pFilter->VendorId = AdapterNameToVendorId( AdapterName); + pFilter->FindFirst = TRUE; + } else { + pFilter = NULL; + } + + if ( PrefMaxLength == -1) { + // + // If the caller has not specified a size, calculate a size + // that will hold the entire enumeration. + // + SpaceLeft = DEFAULT_BUFFER_SIZE; + } else { + SpaceLeft = PrefMaxLength; + } + + // + // Buffer space is shared by the array and by strings pointed at + // by the elements in this array. We need to decide up front how much + // space is allocated for array and how much for the strings. + // + ArrayLength = SpaceLeft / TypicalSize; + if ( ArrayLength == 0) { + ArrayLength = 1; // try to return at least one element + } + + // + // Note that MIDL_user_allocate() returns memory which is NOT initialized + // to zero. Since we do NOT use allocate all nodes, this means that all + // fields, especially pointers, in array elements must be properly set. + // + Buffer = MIDL_user_allocate( ArrayLength * CoreSize); + if ( Buffer == NULL) { + return( ERROR_NOT_ENOUGH_MEMORY); + } + RplDump( RG_DebugLevel & RPL_DEBUG_CONFIG, ( + "ConfigEnum: Buffer=0x%x, ArrayLength=0x%x", Buffer, ArrayLength)); + ConfigEnum->ConfigInfo.Level0->Buffer = (LPRPL_CONFIG_INFO_0)Buffer; + + EntriesRead = 0; + InfoError = FALSE; + Error = NO_ERROR; + + EnterCriticalSection( &RG_ProtectDatabase); + Call( JetBeginTransaction( pSession->SesId)); + + if ( !RplFilterFirst( pSession, CONFIG_TABLE_TAG, pFilter, pResumeHandle, &TableEnd)) { + Error = NERR_RplCannotEnum; + goto cleanup; + } + if ( TableEnd == TRUE) { + goto cleanup; + } + for ( ; ; ) { + memset( Buffer, 0, CoreSize); // for cleanup to work properly + Error = ConfigGetInfo( pSession, NULL, ConfigEnum->Level, Buffer, &SpaceLeft); + if ( Error != NO_ERROR) { + InfoError = TRUE; // clean things up without holding crit sec + break; + } + EntriesRead++; + Buffer += CoreSize; + SpaceLeft -= CoreSize; + if ( !RplFilterNext( pSession, pSession->ConfigTableId, pFilter, &TableEnd)) { + Error = NERR_RplCannotEnum; + goto cleanup; + } + if ( TableEnd == TRUE) { + goto cleanup; + } + if ( SpaceLeft <= 0) { + Error = ERROR_MORE_DATA; + break; + } + if ( EntriesRead >= ArrayLength) { + // + // We have space available but allocated array is not big enough. + // This should NOT happen often as our intent (see above) is to + // overestimate array length. When it happens we can still try + // to reallocate array to a larger size here. This is not done + // for now (too cumbersome) & we just stop the enumeration. + // + Error = ERROR_MORE_DATA; + break; + } + } +cleanup: + Call( JetCommitTransaction( pSession->SesId, 0)); + LeaveCriticalSection( &RG_ProtectDatabase); + if ( InfoError == TRUE) { + ConfigGetInfoCleanup( ConfigEnum->Level, Buffer); + } + if ( Error == NO_ERROR) { + *TotalEntries = EntriesRead; + } else if ( Error == ERROR_MORE_DATA) { + *TotalEntries = EntriesRead * 2; // we cheat here + } else { + // + // Cleanup in case of "bad" errors. + // + while ( EntriesRead > 0) { + EntriesRead--; + Buffer -= CoreSize; + ConfigGetInfoCleanup( ConfigEnum->Level, Buffer); + } + MIDL_user_free( Buffer); + } + + RplDump( RG_DebugLevel & RPL_DEBUG_CONFIG, ("ConfigEnum: EntriesRead = 0x%x", EntriesRead)); + + ConfigEnum->ConfigInfo.Level0->EntriesRead = EntriesRead; + if ( EntriesRead == 0) { + ConfigEnum->ConfigInfo.Level0->Buffer = NULL; + } + + if ( ARGUMENT_PRESENT( pResumeHandle)) { + if ( Error == ERROR_MORE_DATA && EntriesRead > 0) { + EnterCriticalSection( &RG_ProtectDatabase); + Call( JetBeginTransaction( pSession->SesId)); + RplFilterSave( pSession, (DWORD)ServerHandle, pFilter, + ((LPRPL_CONFIG_INFO_0)(Buffer-CoreSize))->ConfigName, + pResumeHandle); + Call( JetCommitTransaction( pSession->SesId, JET_bitCommitFlush)); + LeaveCriticalSection( &RG_ProtectDatabase); + } else { + *pResumeHandle = 0; // resume from beginning + } + } + return( Error); +} |