1423 lines
40 KiB
C
1423 lines
40 KiB
C
/*++
|
||
|
||
Copyright (c) 1991-1992 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ApiSrv.c
|
||
|
||
Abstract:
|
||
|
||
This module contains individual API handlers for the NetServer APIs.
|
||
|
||
SUPPORTED : NetServerDiskEnum, NetServerEnum2, NetServerGetInfo,
|
||
NetServerSetInfo.
|
||
|
||
SEE ALSO : NetServerAuthenticate, NetServerPasswordSet,
|
||
NetServerReqChallenge - in ApiLogon.c.
|
||
|
||
Author:
|
||
|
||
Shanku Niyogi (w-shanku) 25-Feb-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "XactSrvP.h"
|
||
#include <lmbrowsr.h> // Definition of I_BrowserServerEnum
|
||
|
||
|
||
//
|
||
// Declaration of descriptor strings.
|
||
//
|
||
|
||
STATIC const LPDESC Desc16_server_info_0 = REM16_server_info_0;
|
||
STATIC const LPDESC Desc32_server_info_0 = REM32_server_info_0;
|
||
STATIC const LPDESC Desc16_server_info_1 = REM16_server_info_1;
|
||
STATIC const LPDESC Desc32_server_info_1 = REM32_server_info_1;
|
||
STATIC const LPDESC Desc16_server_info_2 = REM16_server_info_2;
|
||
STATIC const LPDESC Desc32_server_info_2 = REM32_server_info_2;
|
||
STATIC const LPDESC Desc16_server_info_3 = REM16_server_info_3;
|
||
STATIC const LPDESC Desc32_server_info_3 = REM32_server_info_3;
|
||
|
||
|
||
NTSTATUS
|
||
XsNetServerDiskEnum (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetServerDiskEnum.
|
||
|
||
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_SERVER_DISK_ENUM parameters = Parameters;
|
||
LPBYTE outBuffer = NULL; // Native parameters
|
||
DWORD entriesRead;
|
||
DWORD totalEntries = 0;
|
||
DWORD entriesFilled = 0; // Conversion variables
|
||
DWORD bufferLength;
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
try {
|
||
//
|
||
// Check for errors.
|
||
//
|
||
|
||
if ( SmbGetUshort( ¶meters->Level ) != 0 ) {
|
||
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
|
||
}
|
||
|
||
//
|
||
// Make the local call.
|
||
//
|
||
|
||
bufferLength = (DWORD)SmbGetUshort( ¶meters->BufLen );
|
||
|
||
status = NetServerDiskEnum(
|
||
NULL,
|
||
(DWORD)SmbGetUshort( ¶meters->Level ),
|
||
(LPBYTE *)&outBuffer,
|
||
XsNativeBufferSize( bufferLength ),
|
||
&entriesRead,
|
||
&totalEntries,
|
||
NULL
|
||
);
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetServer: NetServerDiskEnum failed: "
|
||
"%X\n", status ));
|
||
}
|
||
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Calculate how many entries will fit in 16-bit buffer;
|
||
//
|
||
|
||
if ( bufferLength > 0 ) {
|
||
DWORD elementSize;
|
||
|
||
elementSize = RapStructureSize( StructureDesc, Response, FALSE );
|
||
|
||
if (elementSize != 0) {
|
||
entriesFilled = ( bufferLength - 1 ) / elementSize;
|
||
}
|
||
}
|
||
|
||
if ( entriesFilled < entriesRead ) {
|
||
|
||
status = ERROR_MORE_DATA;
|
||
} else {
|
||
|
||
entriesFilled = entriesRead;
|
||
status = NERR_Success;
|
||
}
|
||
|
||
//
|
||
// Copy native buffer to 16-bit buffer, converting Unicode to Ansi
|
||
// if necessary.
|
||
//
|
||
|
||
if ( bufferLength > 0 ) {
|
||
|
||
DWORD i;
|
||
LPTSTR entryIn = (LPTSTR)outBuffer;
|
||
LPSTR entryOut = (LPSTR)XsSmbGetPointer( ¶meters->Buffer );
|
||
|
||
for ( i = 0; i < entriesFilled; i++ ) {
|
||
|
||
NetpCopyWStrToStrDBCS( entryOut, entryIn );
|
||
entryOut += ( strlen( entryOut ) + 1 );
|
||
entryIn += ( STRLEN( entryIn ) + 1 );
|
||
|
||
}
|
||
strcpy( entryOut, "" );
|
||
}
|
||
|
||
Header->Status = (WORD)status;
|
||
|
||
cleanup:
|
||
;
|
||
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
//
|
||
// Put return data into fields.
|
||
//
|
||
|
||
SmbPutUshort( ¶meters->EntriesRead, (WORD)entriesFilled );
|
||
SmbPutUshort( ¶meters->TotalAvail, (WORD)totalEntries );
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetServerDiskEnum
|
||
|
||
|
||
NTSTATUS
|
||
XsNetServerEnum2 (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetServerEnum.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Transport - The name of the transport provided to the API.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
NET_API_STATUS status = NERR_Success;
|
||
|
||
PXS_NET_SERVER_ENUM_2 parameters = Parameters;
|
||
LPTSTR nativeDomain = NULL; // Native parameters
|
||
LPVOID outBuffer= NULL;
|
||
DWORD entriesRead;
|
||
DWORD totalEntries;
|
||
LPTSTR clientTransportName = NULL;
|
||
LPTSTR clientName = NULL;
|
||
|
||
DWORD entriesFilled = 0; // Conversion variables
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
IF_DEBUG(SERVER) {
|
||
NetpKdPrint(( "XsNetServerEnum2: 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.
|
||
//
|
||
|
||
if ( XsWordParamOutOfRange( parameters->Level, 0, 1 )) {
|
||
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
}
|
||
|
||
XsConvertTextParameter(
|
||
nativeDomain,
|
||
(LPSTR)XsSmbGetPointer( ¶meters->Domain )
|
||
);
|
||
|
||
clientTransportName = Header->ClientTransportName;
|
||
|
||
clientName = Header->ClientMachineName;
|
||
|
||
//
|
||
// Get the actual server information from the local 32-bit call. The
|
||
// native level is 100 or 101.
|
||
//
|
||
|
||
if (clientTransportName == NULL) {
|
||
status = NetServerEnum(
|
||
NULL,
|
||
100 + (DWORD)SmbGetUshort( ¶meters->Level ),
|
||
(LPBYTE *)&outBuffer,
|
||
XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )),
|
||
&entriesRead,
|
||
&totalEntries,
|
||
SmbGetUlong( ¶meters->ServerType ),
|
||
nativeDomain,
|
||
NULL
|
||
);
|
||
|
||
if ( !XsApiSuccess( status ) ) {
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsNetServerEnum2: NetServerEnum failed: %X\n",
|
||
status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
Header->Status = XsConvertServerEnumBuffer(
|
||
outBuffer,
|
||
entriesRead,
|
||
&totalEntries,
|
||
SmbGetUshort( ¶meters->Level ),
|
||
(LPVOID)XsSmbGetPointer( ¶meters->Buffer ),
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
&entriesFilled,
|
||
&Header->Converter);
|
||
|
||
} else {
|
||
|
||
Header->Status = I_BrowserServerEnumForXactsrv(
|
||
clientTransportName,
|
||
clientName,
|
||
|
||
100 + SmbGetUshort( ¶meters->Level ),
|
||
SmbGetUshort( ¶meters->Level ),
|
||
|
||
(PVOID)XsSmbGetPointer( ¶meters->Buffer ),
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen ) ),
|
||
|
||
&entriesFilled,
|
||
&totalEntries,
|
||
|
||
SmbGetUlong( ¶meters->ServerType ),
|
||
nativeDomain,
|
||
NULL,
|
||
|
||
&Header->Converter
|
||
|
||
);
|
||
|
||
|
||
if (!XsApiSuccess( Header->Status )) {
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsNetServerEnum2: I_BrowserServerEnum failed: %d\n", Header->Status));
|
||
}
|
||
goto cleanup;
|
||
}
|
||
}
|
||
|
||
if ( entriesFilled == 0 ) {
|
||
SmbPutUshort( ¶meters->BufLen, 0 );
|
||
}
|
||
|
||
//
|
||
// Set up the response parameters.
|
||
//
|
||
|
||
SmbPutUshort( ¶meters->EntriesRead, (WORD)entriesFilled );
|
||
SmbPutUshort( ¶meters->TotalAvail, (WORD)totalEntries );
|
||
|
||
cleanup:
|
||
;
|
||
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
if ( outBuffer != NULL ) {
|
||
NetApiBufferFree( outBuffer );
|
||
}
|
||
NetpMemoryFree( nativeDomain );
|
||
|
||
//
|
||
// Determine return buffer size.
|
||
//
|
||
|
||
XsSetDataCount(
|
||
¶meters->BufLen,
|
||
SmbGetUshort( ¶meters->Level ) == 0 ?
|
||
Desc16_server_info_0 :
|
||
Desc16_server_info_1,
|
||
Header->Converter,
|
||
entriesFilled,
|
||
Header->Status
|
||
);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetServerEnum2
|
||
|
||
|
||
NTSTATUS
|
||
XsNetServerEnum3 (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetServerEnum.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Transport - The name of the transport provided to the API.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
NET_API_STATUS status = NERR_Success;
|
||
|
||
PXS_NET_SERVER_ENUM_3 parameters = Parameters;
|
||
LPTSTR nativeDomain = NULL; // Native parameters
|
||
LPTSTR nativeFirstNameToReturn = NULL; // Native parameters
|
||
LPVOID outBuffer= NULL;
|
||
DWORD entriesRead;
|
||
DWORD totalEntries;
|
||
LPTSTR clientTransportName = NULL;
|
||
LPTSTR clientName = NULL;
|
||
|
||
DWORD entriesFilled = 0; // Conversion variables
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
IF_DEBUG(SERVER) {
|
||
NetpKdPrint(( "XsNetServerEnum3: 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.
|
||
//
|
||
|
||
if ( XsWordParamOutOfRange( parameters->Level, 0, 1 )) {
|
||
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
}
|
||
|
||
XsConvertTextParameter(
|
||
nativeDomain,
|
||
(LPSTR)XsSmbGetPointer( ¶meters->Domain )
|
||
);
|
||
|
||
XsConvertTextParameter(
|
||
nativeFirstNameToReturn,
|
||
(LPSTR)XsSmbGetPointer( ¶meters->FirstNameToReturn )
|
||
);
|
||
|
||
clientTransportName = Header->ClientTransportName;
|
||
|
||
clientName = Header->ClientMachineName;
|
||
|
||
//
|
||
// Get the actual server information from the local 32-bit call. The
|
||
// native level is 100 or 101.
|
||
//
|
||
|
||
if (clientTransportName == NULL) {
|
||
status = NetServerEnumEx(
|
||
NULL,
|
||
100 + (DWORD)SmbGetUshort( ¶meters->Level ),
|
||
(LPBYTE *)&outBuffer,
|
||
XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )),
|
||
&entriesRead,
|
||
&totalEntries,
|
||
SmbGetUlong( ¶meters->ServerType ),
|
||
nativeDomain,
|
||
nativeFirstNameToReturn
|
||
);
|
||
|
||
if ( !XsApiSuccess( status ) ) {
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsNetServerEnum3: NetServerEnum failed: %X\n",
|
||
status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
Header->Status = XsConvertServerEnumBuffer(
|
||
outBuffer,
|
||
entriesRead,
|
||
&totalEntries,
|
||
SmbGetUshort( ¶meters->Level ),
|
||
(LPVOID)XsSmbGetPointer( ¶meters->Buffer ),
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
&entriesFilled,
|
||
&Header->Converter);
|
||
|
||
} else {
|
||
|
||
Header->Status = I_BrowserServerEnumForXactsrv(
|
||
clientTransportName,
|
||
clientName,
|
||
|
||
100 + SmbGetUshort( ¶meters->Level ),
|
||
SmbGetUshort( ¶meters->Level ),
|
||
|
||
(PVOID)XsSmbGetPointer( ¶meters->Buffer ),
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen ) ),
|
||
|
||
&entriesFilled,
|
||
&totalEntries,
|
||
|
||
SmbGetUlong( ¶meters->ServerType ),
|
||
nativeDomain,
|
||
nativeFirstNameToReturn,
|
||
|
||
&Header->Converter
|
||
|
||
);
|
||
|
||
|
||
if (!XsApiSuccess( Header->Status )) {
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsNetServerEnum3: I_BrowserServerEnum failed: %d\n", Header->Status));
|
||
}
|
||
goto cleanup;
|
||
}
|
||
}
|
||
|
||
if ( entriesFilled == 0 ) {
|
||
SmbPutUshort( ¶meters->BufLen, 0 );
|
||
}
|
||
|
||
//
|
||
// Set up the response parameters.
|
||
//
|
||
|
||
SmbPutUshort( ¶meters->EntriesRead, (WORD)entriesFilled );
|
||
SmbPutUshort( ¶meters->TotalAvail, (WORD)totalEntries );
|
||
|
||
cleanup:
|
||
;
|
||
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
if ( outBuffer != NULL ) {
|
||
NetApiBufferFree( outBuffer );
|
||
}
|
||
NetpMemoryFree( nativeDomain );
|
||
NetpMemoryFree( nativeFirstNameToReturn );
|
||
|
||
//
|
||
// Determine return buffer size.
|
||
//
|
||
|
||
XsSetDataCount(
|
||
¶meters->BufLen,
|
||
SmbGetUshort( ¶meters->Level ) == 0 ?
|
||
Desc16_server_info_0 :
|
||
Desc16_server_info_1,
|
||
Header->Converter,
|
||
entriesFilled,
|
||
Header->Status
|
||
);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetServerEnum3
|
||
|
||
|
||
USHORT
|
||
XsConvertServerEnumBuffer(
|
||
IN LPVOID ServerEnumBuffer,
|
||
IN DWORD EntriesRead,
|
||
IN OUT PDWORD TotalEntries,
|
||
IN USHORT Level,
|
||
IN LPBYTE ClientBuffer,
|
||
IN USHORT BufferLength,
|
||
OUT PDWORD EntriesFilled,
|
||
OUT PUSHORT Converter
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine converts an NT server info array into a down level RAP
|
||
server info buffer.
|
||
|
||
Arguments:
|
||
|
||
IN LPVOID ServerEnumBuffer - Buffer with NT server info.
|
||
IN DWORD EntriesRead - Number of entries in buffer.
|
||
IN OUT PDWORD TotalEntries - Total Number of entries.
|
||
IN USHORT Level - Downlevel information Level (0 or 1).
|
||
IN LPBYTE ClientBuffer - Pointer to 16 bit client side buffer.
|
||
IN USHORT BufferLength - Size of client buffer.
|
||
OUT PDWORD EntriesFilled - Number of entries converted into client buffer.
|
||
OUT PUSHORT Converter - Converter used by client side to convert back.
|
||
|
||
Return Value:
|
||
|
||
USHORT - NERR_Success or reason for failure (16 bit DOS error).
|
||
|
||
--*/
|
||
|
||
{
|
||
USHORT status = NERR_Success;
|
||
DWORD invalidEntries;
|
||
LPDESC nativeStructureDesc;
|
||
DWORD bytesRequired = 0;
|
||
PCHAR StructureDesc;
|
||
|
||
IF_DEBUG(SERVER) {
|
||
NetpKdPrint(( "XsConvertServerEnumBuffer: received %ld entries at %lx\n",
|
||
EntriesRead, ServerEnumBuffer ));
|
||
}
|
||
|
||
//
|
||
// Use the requested level to determine the format of the
|
||
// data structure.
|
||
//
|
||
|
||
switch ( Level ) {
|
||
|
||
case 0:
|
||
|
||
StructureDesc = Desc16_server_info_0;
|
||
nativeStructureDesc = Desc32_server_info_0;
|
||
break;
|
||
|
||
case 1:
|
||
|
||
StructureDesc = Desc16_server_info_1;
|
||
nativeStructureDesc = Desc32_server_info_1;
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Do the actual conversion from the 32-bit structures to 16-bit
|
||
// structures.
|
||
//
|
||
|
||
XsFillEnumBuffer(
|
||
ServerEnumBuffer,
|
||
EntriesRead,
|
||
nativeStructureDesc,
|
||
ClientBuffer,
|
||
ClientBuffer,
|
||
BufferLength,
|
||
StructureDesc,
|
||
NULL, // verify function
|
||
&bytesRequired,
|
||
EntriesFilled,
|
||
&invalidEntries
|
||
);
|
||
|
||
IF_DEBUG(SERVER) {
|
||
NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR,"
|
||
" Entries %ld of %ld\n",
|
||
ServerEnumBuffer, ClientBuffer ,
|
||
bytesRequired, *EntriesFilled, *TotalEntries ));
|
||
}
|
||
|
||
//
|
||
// If there are any invalid entries, subtract this from the
|
||
// number of total entries to avoid the case where the client
|
||
// keeps bugging us for more data.
|
||
//
|
||
|
||
if ( invalidEntries > 0) {
|
||
(*TotalEntries) -= invalidEntries;
|
||
#if DBG
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsNetServerEnum: %d invalid entries removed."
|
||
" Total entries now %d, entries filled %d.\n",
|
||
invalidEntries, *TotalEntries, *EntriesFilled ));
|
||
}
|
||
#endif
|
||
}
|
||
|
||
//
|
||
// If all the entries could not be filled, return ERROR_MORE_DATA,
|
||
// The data needs to be packed so that we don't send too much
|
||
// useless data.
|
||
//
|
||
|
||
if ( (*EntriesFilled < *TotalEntries) ||
|
||
(bytesRequired > BufferLength) ) {
|
||
|
||
status = ERROR_MORE_DATA;
|
||
}
|
||
|
||
*Converter = XsPackReturnData(
|
||
ClientBuffer,
|
||
BufferLength,
|
||
StructureDesc,
|
||
*EntriesFilled
|
||
);
|
||
|
||
|
||
return status;
|
||
} // XsConvertServerEnumBuffer
|
||
|
||
|
||
|
||
NTSTATUS
|
||
XsNetServerGetInfo (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetServerGetInfo. Since NT only provides
|
||
levels 100-102, this routine manually fills in default values for other
|
||
fields. Because of this, the handling in this procedure is different
|
||
from other Xs...GetInfo handlers.
|
||
|
||
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_SERVER_GET_INFO parameters = Parameters;
|
||
DWORD localLevel; // Native parameters
|
||
PSERVER_INFO_102 nativeStruct = NULL;
|
||
PSERVER_INFO_502 secondaryNativeStruct = NULL;
|
||
|
||
LPBYTE stringLocation = NULL; // Conversion variables
|
||
DWORD bytesRequired = 0;
|
||
DWORD sizeOfFixedStructure;
|
||
LPDESC nativeStructureDesc;
|
||
PSERVER_16_INFO_3 returnStruct;
|
||
BOOLEAN bufferTooSmall = FALSE;
|
||
LPWSTR ServerName = NULL;
|
||
UCHAR serverNameBuf[ 2 + NETBIOS_NAME_LEN + 1 ];
|
||
PUCHAR p;
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
IF_DEBUG(SERVER) {
|
||
NetpKdPrint(( "XsNetServerGetInfo: header at %lx, "
|
||
"params at %lx, level %ld\n",
|
||
Header, parameters, SmbGetUshort( ¶meters->Level ) ));
|
||
}
|
||
|
||
try {
|
||
//
|
||
// Check for errors.
|
||
//
|
||
|
||
if ( XsWordParamOutOfRange( parameters->Level, 0, 3 ) ) {
|
||
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Use the 16-bit level number to determine the NT level number and the
|
||
// native descriptor string.
|
||
//
|
||
|
||
switch ( SmbGetUshort( ¶meters->Level ) ) {
|
||
|
||
case 0:
|
||
|
||
nativeStructureDesc = Desc32_server_info_0;
|
||
StructureDesc = Desc16_server_info_0;
|
||
localLevel = 100;
|
||
break;
|
||
|
||
case 1:
|
||
|
||
nativeStructureDesc = Desc32_server_info_1;
|
||
StructureDesc = Desc16_server_info_1;
|
||
localLevel = 101;
|
||
break;
|
||
|
||
case 2:
|
||
|
||
nativeStructureDesc = Desc32_server_info_2;
|
||
StructureDesc = Desc16_server_info_2;
|
||
localLevel = 102;
|
||
break;
|
||
|
||
case 3:
|
||
|
||
nativeStructureDesc = Desc32_server_info_3;
|
||
StructureDesc = Desc16_server_info_3;
|
||
localLevel = 102;
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// If the buffer is not big enough, we have to continue doing the
|
||
// Rap Conversion so that we can return the right buffer size to
|
||
// the caller.
|
||
//
|
||
|
||
sizeOfFixedStructure = RapStructureSize( StructureDesc,
|
||
Response,
|
||
FALSE );
|
||
|
||
if ( SmbGetUshort( ¶meters->BufLen ) < sizeOfFixedStructure ) {
|
||
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetServerGetInfo: Buffer too small.\n" ));
|
||
}
|
||
|
||
bufferTooSmall = TRUE;
|
||
}
|
||
|
||
serverNameBuf[0] = serverNameBuf[1] = '\\';
|
||
memcpy( &serverNameBuf[2], Header->ServerName, NETBIOS_NAME_LEN );
|
||
for( p = &serverNameBuf[ NETBIOS_NAME_LEN + 1 ]; p > serverNameBuf && *p == ' '; p-- )
|
||
;
|
||
*(p+1) = '\0';
|
||
|
||
ServerName = XsDupStrToWStr( serverNameBuf );
|
||
|
||
if( ServerName == NULL ) {
|
||
Header->Status = NERR_NoRoom;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Do the actual local call.
|
||
//
|
||
status = NetServerGetInfo(
|
||
ServerName,
|
||
localLevel,
|
||
(LPBYTE *)&nativeStruct
|
||
);
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsNetServerGetInfo: NetServerGetInfo failed: "
|
||
"%X\n", status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
|
||
}
|
||
|
||
//
|
||
// For levels 2 and 3 (native level 102), additional data is
|
||
// required from native level 502. Do this call.
|
||
//
|
||
|
||
if ( localLevel == 102 ) {
|
||
|
||
status = NetServerGetInfo(
|
||
ServerName,
|
||
502,
|
||
(LPBYTE *)&secondaryNativeStruct
|
||
);
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsNetServerGetInfo: NetServerGetInfo failed: "
|
||
"%X\n", status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
|
||
}
|
||
}
|
||
|
||
//
|
||
// Convert the structure returned by the 32-bit call to a 16-bit
|
||
// structure. For levels 0 and 1, there is no additional work
|
||
// involved after this step, so ConvertSingleEntry can store the
|
||
// variable data in the structure. This is indicated by passing
|
||
// the end of the entire buffer in stringLocation. For levels 2 and 3,
|
||
// the manual filling scheme requires that variable data not be entered
|
||
// at this stage, so stringLocation is set to the end of the fixed
|
||
// structure.
|
||
//
|
||
|
||
stringLocation = (LPBYTE)XsSmbGetPointer( ¶meters->Buffer );
|
||
|
||
if ( !bufferTooSmall ) {
|
||
stringLocation += ( localLevel == 102 ) ?
|
||
sizeOfFixedStructure:
|
||
SmbGetUshort( ¶meters->BufLen );
|
||
}
|
||
|
||
status = RapConvertSingleEntry(
|
||
(LPBYTE)nativeStruct,
|
||
nativeStructureDesc,
|
||
FALSE,
|
||
(LPBYTE)XsSmbGetPointer( ¶meters->Buffer ),
|
||
(LPBYTE)XsSmbGetPointer( ¶meters->Buffer ),
|
||
StructureDesc,
|
||
TRUE,
|
||
&stringLocation,
|
||
&bytesRequired,
|
||
Response,
|
||
NativeToRap
|
||
);
|
||
|
||
if ( status != NERR_Success ) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetServerGetInfo: RapConvertSingleEntry failed: "
|
||
"%X\n", status ));
|
||
}
|
||
|
||
Header->Status = NERR_InternalError;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// For levels 2 and 3, the number of bytes required is, in fact, more than
|
||
// that returned by ConvertSingleEntry. We also need space for the
|
||
// string defaults.
|
||
//
|
||
|
||
if ( localLevel == 102 ) {
|
||
|
||
//
|
||
// The number we get from rap includes some string lengths.
|
||
// We only need the fixed length since we are manually adding
|
||
// those ourselves.
|
||
//
|
||
|
||
bytesRequired = sizeOfFixedStructure;
|
||
}
|
||
|
||
switch ( SmbGetUshort( ¶meters->Level ) ) {
|
||
|
||
case 3:
|
||
|
||
bytesRequired += NetpUnicodeToDBCSLen( DEF16_sv_autopath ) + 1;
|
||
|
||
case 2:
|
||
|
||
bytesRequired += ( NetpUnicodeToDBCSLen( DEF16_sv_alerts )
|
||
+ NetpUnicodeToDBCSLen( DEF16_sv_srvheuristics )
|
||
+ NetpUnicodeToDBCSLen( nativeStruct->sv102_comment )
|
||
+ NetpUnicodeToDBCSLen( nativeStruct->sv102_userpath )
|
||
+ 4 );
|
||
}
|
||
|
||
//
|
||
// We don't have room even for the fixed data, abort.
|
||
//
|
||
|
||
if ( bufferTooSmall ) {
|
||
|
||
Header->Status = NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// For levels 2 and 3, fill in the default values in the fixed structure
|
||
// manually.
|
||
//
|
||
|
||
returnStruct = (PSERVER_16_INFO_3)XsSmbGetPointer( ¶meters->Buffer );
|
||
|
||
switch ( SmbGetUshort( ¶meters->Level ) ) {
|
||
|
||
case 3:
|
||
|
||
SmbPutUlong( &returnStruct->sv3_auditedevents, DEF16_sv_auditedevents );
|
||
SmbPutUshort( &returnStruct->sv3_autoprofile, DEF16_sv_autoprofile );
|
||
|
||
case 2:
|
||
|
||
SmbPutUlong( &returnStruct->sv3_ulist_mtime, DEF16_sv_ulist_mtime );
|
||
SmbPutUlong( &returnStruct->sv3_alist_mtime, DEF16_sv_alist_mtime );
|
||
SmbPutUlong( &returnStruct->sv3_glist_mtime, DEF16_sv_glist_mtime );
|
||
SmbPutUshort( &returnStruct->sv3_security, DEF16_sv_security );
|
||
SmbPutUshort( &returnStruct->sv3_auditing, DEF16_sv_auditing );
|
||
SmbPutUshort( &returnStruct->sv3_numadmin, (USHORT)DEF16_sv_numadmin );
|
||
SmbPutUshort( &returnStruct->sv3_lanmask, DEF16_sv_lanmask );
|
||
NetpCopyTStrToStr( returnStruct->sv3_guestacct, DEF16_sv_guestacct );
|
||
SmbPutUshort( &returnStruct->sv3_chdevs, DEF16_sv_chdevs );
|
||
SmbPutUshort( &returnStruct->sv3_chdevq, DEF16_sv_chdevq );
|
||
SmbPutUshort( &returnStruct->sv3_chdevjobs, DEF16_sv_chdevjobs );
|
||
SmbPutUshort( &returnStruct->sv3_connections, DEF16_sv_connections );
|
||
SmbPutUshort( &returnStruct->sv3_shares, DEF16_sv_shares );
|
||
SmbPutUshort( &returnStruct->sv3_openfiles, DEF16_sv_openfiles );
|
||
SmbPutUshort( &returnStruct->sv3_sessopens,
|
||
(WORD)secondaryNativeStruct->sv502_sessopens );
|
||
SmbPutUshort( &returnStruct->sv3_sessvcs,
|
||
(WORD)secondaryNativeStruct->sv502_sessvcs );
|
||
SmbPutUshort( &returnStruct->sv3_sessreqs, DEF16_sv_sessreqs );
|
||
SmbPutUshort( &returnStruct->sv3_opensearch,
|
||
(WORD)secondaryNativeStruct->sv502_opensearch );
|
||
SmbPutUshort( &returnStruct->sv3_activelocks, DEF16_sv_activelocks );
|
||
SmbPutUshort( &returnStruct->sv3_numreqbuf, DEF16_sv_numreqbuf );
|
||
SmbPutUshort( &returnStruct->sv3_sizreqbuf,
|
||
(WORD)secondaryNativeStruct->sv502_sizreqbuf );
|
||
SmbPutUshort( &returnStruct->sv3_numbigbuf, DEF16_sv_numbigbuf );
|
||
SmbPutUshort( &returnStruct->sv3_numfiletasks, DEF16_sv_numfiletasks );
|
||
SmbPutUshort( &returnStruct->sv3_alertsched, DEF16_sv_alertsched );
|
||
SmbPutUshort( &returnStruct->sv3_erroralert, DEF16_sv_erroralert );
|
||
SmbPutUshort( &returnStruct->sv3_logonalert, DEF16_sv_logonalert );
|
||
SmbPutUshort( &returnStruct->sv3_accessalert, DEF16_sv_accessalert );
|
||
SmbPutUshort( &returnStruct->sv3_diskalert, DEF16_sv_diskalert );
|
||
SmbPutUshort( &returnStruct->sv3_netioalert, DEF16_sv_netioalert );
|
||
SmbPutUshort( &returnStruct->sv3_maxauditsz, DEF16_sv_maxauditsz );
|
||
}
|
||
|
||
//
|
||
// Now check if there is room for the variable data. If there isn't,
|
||
// set return status and quit. This is done here to prevent code
|
||
// below from overwriting the buffer.
|
||
//
|
||
|
||
if ( bytesRequired > (DWORD)SmbGetUshort( ¶meters-> BufLen )) {
|
||
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "NetServerGetInfo: More data available.\n" ));
|
||
}
|
||
Header->Status = ERROR_MORE_DATA;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// For levels 2 and 3, fill in the variable data manually. The variable
|
||
// data is filled in immediately following the fixed structures. For
|
||
// other levels, pack the response data as normal.
|
||
|
||
stringLocation = (LPBYTE)( XsSmbGetPointer( ¶meters->Buffer )
|
||
+ sizeOfFixedStructure );
|
||
|
||
switch ( SmbGetUshort( ¶meters->Level )) {
|
||
|
||
case 3:
|
||
|
||
XsAddVarString(
|
||
stringLocation,
|
||
DEF16_sv_autopath,
|
||
&returnStruct->sv3_autopath,
|
||
returnStruct
|
||
);
|
||
|
||
case 2:
|
||
|
||
XsAddVarString(
|
||
stringLocation,
|
||
DEF16_sv_srvheuristics,
|
||
&returnStruct->sv3_srvheuristics,
|
||
returnStruct
|
||
);
|
||
|
||
XsAddVarString(
|
||
stringLocation,
|
||
nativeStruct->sv102_userpath,
|
||
&returnStruct->sv3_userpath,
|
||
returnStruct
|
||
);
|
||
|
||
XsAddVarString(
|
||
stringLocation,
|
||
DEF16_sv_alerts,
|
||
&returnStruct->sv3_alerts,
|
||
returnStruct
|
||
);
|
||
|
||
XsAddVarString(
|
||
stringLocation,
|
||
nativeStruct->sv102_comment,
|
||
&returnStruct->sv3_comment,
|
||
returnStruct
|
||
);
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
//
|
||
// Pack the response data.
|
||
//
|
||
|
||
Header->Converter = XsPackReturnData(
|
||
(LPVOID)XsSmbGetPointer( ¶meters->Buffer ),
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
StructureDesc,
|
||
1
|
||
);
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
cleanup:
|
||
;
|
||
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
if( ServerName != NULL ) {
|
||
NetpMemoryFree( ServerName );
|
||
}
|
||
|
||
//
|
||
// Set up the response parameters.
|
||
//
|
||
|
||
SmbPutUshort( ¶meters->TotalAvail, (WORD)bytesRequired );
|
||
|
||
NetApiBufferFree( nativeStruct );
|
||
NetApiBufferFree( secondaryNativeStruct );
|
||
|
||
//
|
||
// Determine return buffer size.
|
||
//
|
||
|
||
XsSetDataCount(
|
||
¶meters->BufLen,
|
||
StructureDesc,
|
||
Header->Converter,
|
||
1,
|
||
Header->Status
|
||
);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetServerGetInfo
|
||
|
||
|
||
NTSTATUS
|
||
XsNetServerSetInfo (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetServerSetInfo.
|
||
|
||
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_SERVER_SET_INFO parameters = Parameters;
|
||
LPVOID buffer = NULL; // Native parameters
|
||
|
||
LPBYTE stringLocation = NULL; // Conversion variables
|
||
DWORD bytesRequired = 0;
|
||
LPDESC nativeStructureDesc;
|
||
DWORD data;
|
||
DWORD bufferSize;
|
||
DWORD level;
|
||
LPTSTR comment = NULL;
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
try {
|
||
//
|
||
// Check for errors.
|
||
//
|
||
|
||
if ( XsWordParamOutOfRange( parameters->Level, 1, 3 )) {
|
||
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Processing of this API depends on the value of the ParmNum
|
||
// parameter.
|
||
//
|
||
|
||
switch ( SmbGetUshort( ¶meters->ParmNum )) {
|
||
|
||
case PARMNUM_ALL:
|
||
|
||
//
|
||
// PARMNUM_ALL.
|
||
//
|
||
// The structure descriptor given is OK; determine native descriptor
|
||
// (and expected minimum buffer length) from level. The buffer then
|
||
// needs to be converted into a native 32-bit buffer.
|
||
//
|
||
|
||
switch( SmbGetUshort( ¶meters->Level )) {
|
||
|
||
case 1:
|
||
|
||
StructureDesc = Desc16_server_info_1;
|
||
nativeStructureDesc = Desc32_server_info_1;
|
||
break;
|
||
|
||
case 2:
|
||
|
||
StructureDesc = Desc16_server_info_2;
|
||
nativeStructureDesc = Desc32_server_info_2;
|
||
break;
|
||
|
||
case 3:
|
||
|
||
StructureDesc = Desc16_server_info_3;
|
||
nativeStructureDesc = Desc32_server_info_3;
|
||
break;
|
||
|
||
}
|
||
|
||
if ( !XsCheckBufferSize(
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
StructureDesc,
|
||
FALSE // native format
|
||
)) {
|
||
|
||
Header->Status = NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Find out how big a 32-bit data buffer we need.
|
||
//
|
||
|
||
bufferSize = XsBytesForConvertedStructure(
|
||
(LPBYTE)XsSmbGetPointer( ¶meters->Buffer ),
|
||
StructureDesc,
|
||
nativeStructureDesc,
|
||
RapToNative,
|
||
TRUE
|
||
);
|
||
|
||
//
|
||
// Allocate enough memory to hold the converted native buffer.
|
||
//
|
||
|
||
buffer = NetpMemoryAllocate( bufferSize );
|
||
|
||
if ( buffer == NULL ) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetServerSetInfo: failed to create buffer" ));
|
||
}
|
||
Header->Status = NERR_NoRoom;
|
||
goto cleanup;
|
||
|
||
}
|
||
|
||
IF_DEBUG(SERVER) {
|
||
NetpKdPrint(( "XsNetServerSetInfo: buffer of %ld bytes at %lx\n",
|
||
bufferSize, buffer ));
|
||
}
|
||
|
||
//
|
||
// Convert 16-bit data into 32-bit data and store it in the native
|
||
// buffer.
|
||
//
|
||
|
||
stringLocation = (LPBYTE)buffer + bufferSize;
|
||
bytesRequired = 0;
|
||
|
||
status = RapConvertSingleEntry(
|
||
(LPBYTE)XsSmbGetPointer( ¶meters->Buffer ),
|
||
StructureDesc,
|
||
TRUE,
|
||
buffer,
|
||
buffer,
|
||
nativeStructureDesc,
|
||
FALSE,
|
||
&stringLocation,
|
||
&bytesRequired,
|
||
Response,
|
||
RapToNative
|
||
);
|
||
|
||
if ( status != NERR_Success ) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetServerSetInfo: RapConvertSingleEntry "
|
||
"failed: %X\n", status ));
|
||
}
|
||
|
||
Header->Status = NERR_InternalError;
|
||
goto cleanup;
|
||
}
|
||
|
||
break;
|
||
|
||
case SV_COMMENT_PARMNUM:
|
||
|
||
//
|
||
// SV_COMMENT_PARMNUM.
|
||
//
|
||
// The structure descriptor given is meaningless. The data is actually
|
||
// a null terminated string, and can be passed to the native routine
|
||
// immediately. Being a string, it must be at least one character long.
|
||
//
|
||
|
||
if ( !XsCheckBufferSize(
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
"B",
|
||
FALSE // not in native format
|
||
)) {
|
||
|
||
Header->Status= NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
|
||
XsConvertUnicodeTextParameter(
|
||
comment,
|
||
(LPSTR)XsSmbGetPointer( ¶meters->Buffer )
|
||
);
|
||
|
||
if ( comment == NULL ) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetServerSetInfo: failed to create buffer" ));
|
||
}
|
||
Header->Status = NERR_NoRoom;
|
||
goto cleanup;
|
||
}
|
||
|
||
buffer = &comment;
|
||
|
||
break;
|
||
|
||
case SV_ALERTS_PARMNUM:
|
||
case SV_ALERTSCHED_PARMNUM:
|
||
case SV_ERRORALERT_PARMNUM:
|
||
case SV_LOGONALERT_PARMNUM:
|
||
|
||
goto cleanup;
|
||
|
||
case SV_ACCESSALERT_PARMNUM:
|
||
case SV_DISKALERT_PARMNUM:
|
||
case SV_NETIOALERT_PARMNUM:
|
||
case SV_MAXAUDITSZ_PARMNUM:
|
||
|
||
//
|
||
// SV_ALERTS_PARMNUM, SV_ALERTSCHED_PARMNUM, SV_ERRORALERT_PARMNUM,
|
||
// SV_LOGONALERT_PARMNUM, SV_ACCESSALERT_PARMNUM, SV_DISKALERT_PARMNUM,
|
||
// SV_NETIOALERT_PARMNUM, or SV_MAXAUDITSZ_PARMNUM.
|
||
//
|
||
// These parameters are not supported in NT, so just return an OK.
|
||
//
|
||
|
||
goto cleanup;
|
||
|
||
case SV_DISC_PARMNUM:
|
||
case SV_HIDDEN_PARMNUM:
|
||
case SV_ANNOUNCE_PARMNUM:
|
||
case SV_ANNDELTA_PARMNUM:
|
||
|
||
//
|
||
// SV_DISC_PARMNUM, SV_HIDDEN_PARMNUM, SV_ANNOUNCE_PARMNUM, or
|
||
// SV_ANNDELTA_PARMNUM.
|
||
//
|
||
// The structure descriptor given is meaningless; the data is a word
|
||
// to be converted into a 32-bit DWORD. The length of data must be 2.
|
||
//
|
||
|
||
if ( !XsCheckBufferSize(
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
"W",
|
||
FALSE // not in native format
|
||
)) {
|
||
|
||
Header->Status= NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
|
||
data = (DWORD)SmbGetUshort(
|
||
(LPWORD)XsSmbGetPointer( ¶meters->Buffer )
|
||
);
|
||
buffer = &data;
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
Header->Status = ERROR_INVALID_PARAMETER;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Do the actual local call.
|
||
//
|
||
|
||
level = SmbGetUshort( ¶meters->ParmNum );
|
||
if ( level != 0 ) {
|
||
level = level + PARMNUM_BASE_INFOLEVEL;
|
||
} else {
|
||
level = 100 + SmbGetUshort( ¶meters->Level );
|
||
if ( level == 103 ) {
|
||
level = 102;
|
||
}
|
||
}
|
||
|
||
status = NetServerSetInfo(
|
||
NULL,
|
||
level,
|
||
buffer,
|
||
NULL
|
||
);
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetServerSetInfo: NetServerSetInfo failed: %X\n",
|
||
status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// No return information for this API.
|
||
//
|
||
|
||
cleanup:
|
||
;
|
||
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
//
|
||
// If there is a native 32-bit buffer, free it.
|
||
//
|
||
|
||
if ( SmbGetUshort( ¶meters->ParmNum ) == PARMNUM_ALL ) {
|
||
NetpMemoryFree( buffer );
|
||
} else if ( SmbGetUshort( ¶meters->ParmNum ) == SV_COMMENT_PARMNUM ) {
|
||
NetpMemoryFree( comment );
|
||
}
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetServerSetInfo
|
||
|
||
|