619 lines
15 KiB
C
619 lines
15 KiB
C
|
/*++
|
|||
|
|
|||
|
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
|