/*++ Copyright (c) 1992-1993 Microsoft Corporation Module Name: ImpEnum.c Abstract: This file contains NetrReplImportDirEnum. Author: John Rogers (JohnRo) 14-Jan-1992 Environment: Runs under Windows NT. Requires ANSI C extensions: slash-slash comments, long external names. Revision History: 14-Jan-1992 JohnRo Created. 20-Jan-1992 JohnRo Netr prototypes are now generated by MIDL and put in repl.h. 20-Jan-1992 JohnRo Changed prototype to match MIDL requirements. 27-Jan-1992 JohnRo Changed to use LPTSTR etc. Changed interface of ImportDirBuildApiRecord to work w/o service. 23-Mar-1992 JohnRo Fixed enum when service is running. 27-Mar-1992 JohnRo More debug output. 17-Nov-1992 JohnRo RAID 1537: repl APIs in wrong role kill service. 10-Mar-1993 JohnRo Fixed various lock/unlock mistakes. PC-LINT 5.0 noticed that EntriesRead may not be set. Use NetpKdPrint() where possible. --*/ // These must be included first: #include // IN, VOID, LPTSTR, etc. #include // NET_API_STATUS, PARM equates, etc. #include // Needed by . #include // ReplIsIntegrityValid(), etc. #include // Needed by . // These can be in any order: #include // RC globals, etc. #include // ImportDirBuildApiRecord(). #include // NetApiBufferAllocate(). #include // NetpAssert(), NetpKdPrint(), etc. #include // NetpPointerPlusSomeBytes(). #include // ACQUIRE_LOCK_SHARED(), RELEASE_LOCK(). #include // My prototype (in MIDL-generated .h file). #include // ReplConfigLock, ReplConfigRole. #include // Netp{various}StructureInfo(). #include // ERROR_ equates, NO_ERROR. NET_API_STATUS NetrReplImportDirEnum ( IN LPTSTR UncServerName OPTIONAL, // IN DWORD Level, IN OUT LPIMPORT_ENUM_STRUCT EnumContainer, // OUT LPIMPORT_CONTAINER BufPtr, // RPC container (union) IN DWORD PrefMaxSize, // OUT LPDWORD EntriesRead, OUT LPDWORD TotalEntries, IN OUT LPDWORD ResumeHandle OPTIONAL ) /*++ Routine Description: Same as NetReplImportDirEnum. Arguments: Same as NetReplImportDirEnum. Return Value: Same as NetReplImportDirEnum. --*/ { LPVOID ApiArray = NULL; LPVOID ApiEntry; NET_API_STATUS ApiStatus; LPCLIENT_LIST_REC ClientRecord; DWORD EntryCount = 0; DWORD FixedSize; DWORD Level; BOOL LockedClientList = FALSE; BOOL LockedConfigData = FALSE; DWORD OutputSize; LPVOID StringLocation; UNREFERENCED_PARAMETER(PrefMaxSize); UNREFERENCED_PARAMETER(UncServerName); #define SET_ENTRIES_READ( value ) \ { \ /* Pretend level 0, to make life easy. */ \ EnumContainer->ImportInfo.Level0->EntriesRead = (value); \ } #define SET_BUFFER_POINTER( value ) \ { \ /* Pretend level 0, to make life easy. */ \ EnumContainer->ImportInfo.Level0->Buffer = (value); \ } // // Check for caller errors. // NetpAssert( EnumContainer != NULL ); NetpAssert( EnumContainer->ImportInfo.Level0 != NULL ); Level = EnumContainer->Level; SET_BUFFER_POINTER( NULL ); // Don't confuse caller about possible alloc. if (TotalEntries == NULL) { return (ERROR_INVALID_PARAMETER); } // Test for memory faults before we lock anything. SET_ENTRIES_READ( 0 ); * TotalEntries = 0; // This version only supports 1 call to enumerate, so resume handle // should never be set to nonzero. But let's check, so caller finds out // they have a buggy program. if (ResumeHandle != NULL) { if (*ResumeHandle != 0) { return (ERROR_INVALID_PARAMETER); } } // // Check role and handle call if import half of service is not running. // ACQUIRE_LOCK_SHARED( ReplConfigLock ); LockedConfigData = TRUE; if ( !ReplRoleIncludesImport( ReplConfigRole ) ) { ApiStatus = ImportDirEnumApiRecords( UncServerName, Level, (LPBYTE *) (LPVOID) &ApiArray, PrefMaxSize, & EntryCount, TotalEntries ); goto Cleanup; } // // Import side of service is running... // Compute size of output area (and check caller's Level too). // ApiStatus = NetpReplImportDirStructureInfo ( Level, PARMNUM_ALL, TRUE, // want native sizes NULL, // don't need DataDesc16 NULL, // don't need DataDesc32 NULL, // don't need DataDescSmb & OutputSize, // need max size of structure & FixedSize, NULL); // don't need StringSize if (ApiStatus != NO_ERROR) { goto Cleanup; // don't forget to unlock... } // // Get read-only lock on client list. // ACQUIRE_LOCK_SHARED( RCGlobalClientListLock ); LockedClientList = TRUE; // // Find out how many entries there are. // EntryCount = RCGlobalClientListCount; IF_DEBUG( IMPAPI ) { NetpKdPrint(( "NetrReplImportDirEnum: there are " FORMAT_DWORD " client records.\n", EntryCount )); } if (EntryCount > 0) { // // Allocate the output area. // ApiStatus = NetApiBufferAllocate( OutputSize * EntryCount, (LPVOID *) & ApiArray); if (ApiStatus != NO_ERROR) { // ApiStatus is already set to return error to caller. // Don't forget to release lock... } else { NetpAssert( ApiArray != NULL ); // // Loop for each entry in client list. // ApiEntry = ApiArray; ClientRecord = RCGlobalClientListHeader; StringLocation = NetpPointerPlusSomeBytes( ApiArray, OutputSize * EntryCount ); while (ClientRecord != NULL) { // // Build an array entry for this client record. // ApiStatus = ImportDirBuildApiRecord ( Level, ClientRecord->dir_name, ClientRecord->state, ClientRecord->master, ClientRecord->timestamp, // Last update, secs since '70. ClientRecord->lockcount, ClientRecord->time_of_first_lock, // Seconds since 1970. ApiEntry, (LPBYTE *) (LPVOID) & StringLocation); IF_DEBUG( IMPAPI ) { NetpKdPrint(( "NetrReplImportDirEnum: build status is " FORMAT_API_STATUS ".\n", ApiStatus )); } NetpAssert( ApiStatus == NO_ERROR ); // We checked all parms. ClientRecord = ClientRecord->next_p; ApiEntry = NetpPointerPlusSomeBytes( ApiEntry, FixedSize ); } } // Don't forget to release lock... } else { // No entries... ApiArray = NULL; ApiStatus = NO_ERROR; // Don't forget to release lock... } // // Release lock and tell caller how everything went. // Cleanup: if (LockedClientList) { RELEASE_LOCK( RCGlobalClientListLock ); } if (LockedConfigData) { RELEASE_LOCK( ReplConfigLock ); } SET_BUFFER_POINTER( (LPVOID) ApiArray ); SET_ENTRIES_READ( EntryCount ); * TotalEntries = EntryCount; if (ApiStatus==NO_ERROR) { IF_DEBUG( IMPAPI ) { NetpKdPrint(( "NetrReplImportDirEnum: at end, ApiArray at " FORMAT_LPVOID " and EntryCount=" FORMAT_DWORD ".\n", (LPVOID) ApiArray, EntryCount )); } if (ApiArray != NULL) { NetpAssert( EntryCount > 0 ); IF_DEBUG( IMPAPI ) { NetpDbgDisplayReplImportDirArray( Level, ApiArray, EntryCount ); } } else { NetpAssert( EntryCount == 0 ); } } return (ApiStatus); }