/*++ Copyright (c) 1991 Microsoft Corporation Module Name: ApiFile.c Abstract: This module contains individual API handlers for the NetFile APIs. SUPPORTED - NetFileClose2, NetFileEnum2, NetFileGetInfo2. Author: Shanku Niyogi (w-shanku) 20-Feb-1991 Revision History: --*/ #include "XactSrvP.h" // // Declaration of descriptor strings. // STATIC const LPDESC Desc16_file_info_2 = REM16_file_info_2; STATIC const LPDESC Desc32_file_info_2 = REM32_file_info_2; STATIC const LPDESC Desc16_file_info_3 = REM16_file_info_3; STATIC const LPDESC Desc32_file_info_3 = REM32_file_info_3; NTSTATUS XsNetFileClose2 ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetFileClose. Arguments: API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details. Return Value: NTSTATUS - STATUS_SUCCESS or reason for failure. --*/ { NET_API_STATUS status; PXS_NET_FILE_CLOSE_2 parameters = Parameters; API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings try { // // Make the local call. // status = NetFileClose( NULL, SmbGetUlong( ¶meters->FileId ) ); } except( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); } if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetFileClose2: NetFileClose failed: %X\n", status )); } } // // No return data. // Header->Status = (WORD)status; return STATUS_SUCCESS; } // XsNetFileClose2 NTSTATUS XsNetFileEnum2 ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetFileEnum. Arguments: API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details. Return Value: NTSTATUS - STATUS_SUCCESS or reason for failure. --*/ { NET_API_STATUS status; PXS_NET_FILE_ENUM_2 parameters = Parameters; LPTSTR nativeBasePath = NULL; // Native parameters LPTSTR nativeUserName = NULL; LPVOID outBuffer = NULL; DWORD entriesRead; DWORD totalEntries; DWORD_PTR resumeKey = 0; DWORD entriesFilled = 0; // Conversion variables DWORD totalEntriesRead = 0; DWORD bytesRequired = 0; DWORD nativeBufferSize; LPDESC nativeStructureDesc; LPBYTE bufferBegin; DWORD bufferSize; API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings IF_DEBUG(FILE) { NetpKdPrint(( "XsNetFileEnum2: header at %lx, params at %lx, " "level %ld, buf size %ld\n", Header, parameters, SmbGetUshort( ¶meters->Level ), SmbGetUshort( ¶meters->BufLen ))); } try { // // Translate parameters, check for errors. // XsConvertTextParameter( nativeBasePath, (LPSTR)XsSmbGetPointer( ¶meters->BasePath ) ); XsConvertTextParameter( nativeUserName, (LPSTR)XsSmbGetPointer( ¶meters->UserName ) ); // // Copy input resume handle to output resume handle, and get a copy of it. // if ( SmbGetUlong( ¶meters->ResumeKeyIn ) == 0 ) { Header->Status = ERROR_INVALID_PARAMETER; goto cleanup; } RtlCopyMemory( parameters->ResumeKeyOut, (LPBYTE)XsSmbGetPointer( ¶meters->ResumeKeyIn ), 8 ); resumeKey = (DWORD)SmbGetUlong( ¶meters->ResumeKeyOut[2] ); IF_DEBUG(FILE) { NetpKdPrint(( "XsNetFileEnum2: resume key is %ld\n", resumeKey )); } // // Use the level to determine the descriptor string. // switch ( SmbGetUshort( ¶meters->Level ) ) { case 2: StructureDesc = Desc16_file_info_2; nativeStructureDesc = Desc32_file_info_2; break; case 3: StructureDesc = Desc16_file_info_3; nativeStructureDesc = Desc32_file_info_3; break; default: // // Unsupported levels, abort before any work. // Header->Status = ERROR_INVALID_LEVEL; goto cleanup; } // // NetFileEnum2 is a resumable API, so we cannot get more information // from the native call than we can send back. The most efficient way // to do this is in a loop...we use the 16-bit buffer size to determine // a safe native buffer size, make the call, fill the entries, then // take the amount of space remaining and determine a safe size again, // and so on, until NetFileEnum returns either no entries or all entries // read. // // // Initialize important variables for loop. // bufferBegin = (LPBYTE)XsSmbGetPointer( ¶meters->Buffer ); bufferSize = (DWORD)SmbGetUshort( ¶meters->BufLen ); totalEntriesRead = 0; for ( ; ; ) { // // Compute a safe size for the native buffer. // switch ( SmbGetUshort( ¶meters->Level ) ) { case 2: nativeBufferSize = bufferSize; break; case 3: nativeBufferSize = bufferSize; break; } // // Make the local call. // status = NetFileEnum( NULL, nativeBasePath, nativeUserName, (DWORD)SmbGetUshort( ¶meters->Level ), (LPBYTE *)&outBuffer, nativeBufferSize, &entriesRead, &totalEntries, &resumeKey ); if ( !XsApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetFileEnum2: NetFileEnum failed: %X\n", status )); } Header->Status = (WORD)status; goto cleanup; } IF_DEBUG(FILE) { NetpKdPrint(( "XsNetFileEnum2: received %ld entries at %lx\n", entriesRead, outBuffer )); NetpKdPrint(( "XsNetFileEnum2: resume key is now %Id\n", resumeKey )); } // // Was NetFileEnum able to read at least one complete entry? // if ( entriesRead == 0 ) { break; } // // Do the actual conversion from the 32-bit structures to 16-bit // structures. // XsFillEnumBuffer( outBuffer, entriesRead, nativeStructureDesc, bufferBegin, (LPBYTE)XsSmbGetPointer( ¶meters->Buffer ), bufferSize, StructureDesc, NULL, // verify function &bytesRequired, &entriesFilled, NULL ); IF_DEBUG(FILE) { NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR," " Entries %ld of %ld\n", outBuffer, SmbGetUlong( ¶meters->Buffer ), bytesRequired, entriesFilled, totalEntries )); } // // Very key assertion! // NetpAssert( entriesRead == entriesFilled ); // // Update count of entries read. // totalEntriesRead += entriesRead; // // Are there any more entries to read? // if ( entriesRead == totalEntries ) { break; } // // Calculate new buffer beginning and size. // bufferBegin += entriesRead * RapStructureSize( StructureDesc, Response, FALSE ); bufferSize -= bytesRequired; // // Free last native buffer. // NetApiBufferFree( outBuffer ); outBuffer = NULL; } // // Upon exit from the loop, totalEntriesRead has the number of entries // read, entriesRead has the number read in the last call, totalEntries // has the number remaining plus entriesRead. Formulate return codes, // etc. from these values. // if ( totalEntries > entriesRead ) { Header->Status = ERROR_MORE_DATA; } else { Header->Converter = XsPackReturnData( (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), StructureDesc, totalEntriesRead ); } IF_DEBUG(FILE) { NetpKdPrint(( "XsNetFileEnum2: resume key is now %ld\n", resumeKey )); } // // Set up the response parameters. // SmbPutUshort( ¶meters->EntriesRead, (WORD)totalEntriesRead ); SmbPutUshort( ¶meters->EntriesRemaining, (WORD)( totalEntries - entriesRead )); // // Over the wire, resumeKey is a true 32-bit index, so this cast works. // SmbPutUlong( (LPDWORD)¶meters->ResumeKeyOut[2], (DWORD)resumeKey ); cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); } NetApiBufferFree( outBuffer ); NetpMemoryFree( nativeBasePath ); NetpMemoryFree( nativeUserName ); // // Determine return buffer size. // XsSetDataCount( ¶meters->BufLen, StructureDesc, Header->Converter, totalEntriesRead, Header->Status ); return STATUS_SUCCESS; } // XsNetFileEnum2 NTSTATUS XsNetFileGetInfo2 ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetFileGetInfo2. Arguments: API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details. Return Value: NTSTATUS - STATUS_SUCCESS or reason for failure. --*/ { NET_API_STATUS status; PXS_NET_FILE_GET_INFO_2 parameters = Parameters; LPVOID outBuffer = NULL; // Native parameters LPBYTE stringLocation = NULL; // Conversion variables DWORD bytesRequired = 0; LPDESC nativeStructureDesc; API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings IF_DEBUG(FILE) { NetpKdPrint(( "XsNetFileGetInfo2: header at %lx, " "params at %lx, level %ld\n", Header, parameters, SmbGetUshort( ¶meters->Level ) )); } try { // // Check errors. // if ( XsWordParamOutOfRange( parameters->Level, 2, 3 )) { Header->Status = ERROR_INVALID_LEVEL; goto cleanup; } // // Make the local call. // status = NetFileGetInfo( NULL, SmbGetUlong( ¶meters->FileId ), (DWORD)SmbGetUshort( ¶meters->Level ), (LPBYTE *)&outBuffer ); if ( !XsApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetFileGetInfo2: NetFileGetInfo failed: " "%X\n", status )); } Header->Status = (WORD)status; goto cleanup; } // // Use the requested level to determine the format of the // data structure. // switch ( SmbGetUshort( ¶meters->Level ) ) { case 2: StructureDesc = Desc16_file_info_2; nativeStructureDesc = Desc32_file_info_2; break; case 3: StructureDesc = Desc16_file_info_3; nativeStructureDesc = Desc32_file_info_3; break; } // // Convert the structure returned by the 32-bit call to a 16-bit // structure. The last possible location for variable data is // calculated from buffer location and length. // stringLocation = (LPBYTE)( XsSmbGetPointer( ¶meters->Buffer ) + SmbGetUshort( ¶meters->BufLen ) ); status = RapConvertSingleEntry( outBuffer, nativeStructureDesc, FALSE, (LPBYTE)XsSmbGetPointer( ¶meters->Buffer ), (LPBYTE)XsSmbGetPointer( ¶meters->Buffer ), StructureDesc, TRUE, &stringLocation, &bytesRequired, Response, NativeToRap ); if ( status != NERR_Success ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsFileGetInfo2: RapConvertSingleEntry failed: " "%X\n", status )); } Header->Status = NERR_InternalError; goto cleanup; } IF_DEBUG(FILE) { NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n", outBuffer, SmbGetUlong( ¶meters->Buffer ), bytesRequired )); } // // Determine return code based on the size of the buffer. // if ( !XsCheckBufferSize( SmbGetUshort( ¶meters->BufLen ), StructureDesc, FALSE // not in native format )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetFileGetInfo2: Buffer too small.\n" )); } Header->Status = NERR_BufTooSmall; } else { if ( bytesRequired > (DWORD)SmbGetUshort( ¶meters-> BufLen )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "NetFileGetInfo2: More data available.\n" )); } Header->Status = ERROR_MORE_DATA; } else { // // Pack the response data. // Header->Converter = XsPackReturnData( (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), StructureDesc, 1 ); } } // // Set up the response parameters. // SmbPutUshort( ¶meters->TotalAvail, (WORD)bytesRequired ); cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); } NetApiBufferFree( outBuffer ); // // Determine return buffer size. // XsSetDataCount( ¶meters->BufLen, StructureDesc, Header->Converter, 1, Header->Status ); return STATUS_SUCCESS; } // XsNetFileGetInfo2