/*++ 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 // 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