/*++ Copyright (c) 1991 Microsoft Corporation Module Name: ApiGroup.c Abstract: This module contains individual API handlers for the NetGroup APIs. SUPPORTED : NetGroupAdd, NetGroupAddUser, NetGroupDel, NetGroupDelUser, NetGroupEnum, NetGroupGetInfo, NetGroupGetUsers, NetGroupSetInfo, NetGroupSetUsers. Author: Shanku Niyogi (w-shanku) 13-Mar-1991 Revision History: --*/ // // Group APIs are UNICODE only. // #ifndef UNICODE #define UNICODE #endif #include "xactsrvp.h" // // Declaration of descriptor strings. // STATIC const LPDESC Desc16_group_info_0 = REM16_group_info_0; STATIC const LPDESC Desc32_group_info_0 = REM32_group_info_0; STATIC const LPDESC Desc16_group_info_1 = REM16_group_info_1; STATIC const LPDESC Desc32_group_info_1 = REM32_group_info_1; STATIC const LPDESC Desc16_group_info_1_setinfo = REM16_group_info_1_setinfo; STATIC const LPDESC Desc32_group_info_1_setinfo = REM32_group_info_1_setinfo; STATIC const LPDESC Desc16_group_users_info_0 = REM16_group_users_info_0; STATIC const LPDESC Desc32_group_users_info_0 = REM32_group_users_info_0; STATIC const LPDESC Desc16_group_users_info_0_set = REM16_group_users_info_0_set; STATIC const LPDESC Desc32_group_users_info_0_set = REM32_group_users_info_0_set; NTSTATUS XsNetGroupAdd ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetGroupAdd. 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_GROUP_ADD parameters = Parameters; LPVOID buffer = NULL; // Native parameters LPBYTE stringLocation = NULL; // Conversion variables DWORD bytesRequired = 0; DWORD bufferSize; LPDESC nativeStructureDesc; API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings IF_DEBUG(GROUP) { NetpKdPrint(( "XsNetGroupAdd: header at %lx, params at %lx, " "level %ld\n", Header, parameters, SmbGetUshort( ¶meters->Level ) )); } try { // // Use the requested level to determine the format of the destination // 32-bit structure. // switch ( SmbGetUshort( ¶meters->Level ) ) { case 0: StructureDesc = Desc16_group_info_0; nativeStructureDesc = Desc32_group_info_0; break; case 1: StructureDesc = Desc16_group_info_1; nativeStructureDesc = Desc32_group_info_1; break; default: Header->Status = ERROR_INVALID_LEVEL; goto cleanup; } // // Figure out if there is enough room in the buffer for all the // data required. If not, return NERR_BufTooSmall. // if ( !XsCheckBufferSize( SmbGetUshort( ¶meters->BufLen ), StructureDesc, FALSE // not in native format )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupAdd: Buffer too small.\n" )); } Header->Status = NERR_BufTooSmall; goto cleanup; } // // Find out how big a buffer we need to allocate to hold the native // 32-bit version of the input data structure. // 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(( "XsNetGroupAdd: failed to create buffer" )); } Header->Status = NERR_NoRoom; goto cleanup; } IF_DEBUG(GROUP) { NetpKdPrint(( "XsNetGroupAdd: buffer of %ld bytes at %lx\n", bufferSize, buffer )); } // // Convert the buffer from 16-bit to 32-bit. // 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(( "XsNetGroupAdd: RapConvertSingleEntry failed: " "%X\n", status )); } Header->Status = NERR_InternalError; goto cleanup; } // // Make the local call. // status = NetGroupAdd( NULL, (DWORD)SmbGetUshort( ¶meters->Level ), buffer, NULL ); if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupAdd: NetGroupAdd failed: %X\n", status )); } Header->Status = (WORD)status; goto cleanup; } // // There is no real return information for this API. // cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); } NetpMemoryFree( buffer ); return STATUS_SUCCESS; } // XsNetGroupAdd NTSTATUS XsNetGroupAddUser ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetGroupAddUser. 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_GROUP_ADD_USER parameters = Parameters; LPTSTR nativeGroupName = NULL; // Native parameters LPTSTR nativeUserName = NULL; API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings try { // // Translate parameters, check for errors. // XsConvertTextParameter( nativeGroupName, (LPSTR)XsSmbGetPointer( ¶meters->GroupName ) ); XsConvertTextParameter( nativeUserName, (LPSTR)XsSmbGetPointer( ¶meters->UserName ) ); // // Make the local call. // status = NetGroupAddUser( NULL, nativeGroupName, nativeUserName ); if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupAddUser: NetGroupAddUser failed: %X\n", status )); } } cleanup: ; } except ( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); } NetpMemoryFree( nativeGroupName ); NetpMemoryFree( nativeUserName ); // // Nothing to return. // Header->Status = (WORD)status; return STATUS_SUCCESS; } // XsNetGroupAddUser NTSTATUS XsNetGroupDel ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetGroupDel. 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_GROUP_DEL parameters = Parameters; LPTSTR nativeGroupName = NULL; // Native parameters API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings IF_DEBUG(GROUP) { NetpKdPrint(( "XsNetGroupDel: header at %lx, params at %lx, name %s\n", Header, parameters, SmbGetUlong( ¶meters->GroupName ))); } try { // // Translate parameters, check for errors. // XsConvertTextParameter( nativeGroupName, (LPSTR)XsSmbGetPointer( ¶meters->GroupName ) ); // // Make the local call. // status = NetGroupDel( NULL, nativeGroupName ); if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupDel: NetGroupDel failed: %X\n", status )); } } cleanup: ; } except ( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); } NetpMemoryFree( nativeGroupName ); // // Nothing to return. // Header->Status = (WORD)status; return STATUS_SUCCESS; } // XsNetGroupDel NTSTATUS XsNetGroupDelUser ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetGroupDelUser. 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_GROUP_DEL_USER parameters = Parameters; LPTSTR nativeGroupName = NULL; // Native parameters LPTSTR nativeUserName = NULL; API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings try { // // Translate parameters, check for errors. // XsConvertTextParameter( nativeGroupName, (LPSTR)XsSmbGetPointer( ¶meters->GroupName ) ); XsConvertTextParameter( nativeUserName, (LPSTR)XsSmbGetPointer( ¶meters->UserName ) ); // // Make the local call. // status = NetGroupDelUser( NULL, nativeGroupName, nativeUserName ); if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupDelUser: NetGroupDelUser failed: %X\n", status )); } } cleanup: ; } except ( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); } NetpMemoryFree( nativeGroupName ); NetpMemoryFree( nativeUserName ); // // Nothing to return. // Header->Status = (WORD)status; return STATUS_SUCCESS; } // XsNetGroupDelUser NTSTATUS XsNetGroupEnum ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetGroupEnum. 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_GROUP_ENUM parameters = Parameters; LPVOID outBuffer= NULL; // Native parameters DWORD entriesRead; DWORD totalEntries; DWORD entriesFilled = 0; // Conversion variables DWORD bytesRequired = 0; LPDESC nativeStructureDesc; API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings IF_DEBUG(GROUP) { NetpKdPrint(( "XsNetGroupEnum: header at %lx, params at %lx, " "level %ld, buf size %ld\n", Header, parameters, SmbGetUshort( ¶meters->Level ), SmbGetUshort( ¶meters->BufLen ))); } try { // // Check for errors. // if ( XsWordParamOutOfRange( parameters->Level, 0, 1 )) { Header->Status = ERROR_INVALID_LEVEL; goto cleanup; } // // Make the local call. // status = NetGroupEnum( NULL, (DWORD)SmbGetUshort( ¶meters->Level ), (LPBYTE *)&outBuffer, XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )), &entriesRead, &totalEntries, NULL ); if ( !XsApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetGroupEnum: NetGroupEnum failed: %X\n", status )); } Header->Status = (WORD)status; goto cleanup; } IF_DEBUG(GROUP) { NetpKdPrint(( "XsNetGroupEnum: received %ld entries at %lx\n", entriesRead, outBuffer )); } // // Use the requested level to determine the format of the // data structure. // switch ( SmbGetUshort( ¶meters->Level ) ) { case 0: nativeStructureDesc = Desc32_group_info_0; StructureDesc = Desc16_group_info_0; break; case 1: nativeStructureDesc = Desc32_group_info_1; StructureDesc = Desc16_group_info_1; break; } // // Do the actual conversion from the 32-bit structures to 16-bit // structures. // XsFillEnumBuffer( outBuffer, entriesRead, nativeStructureDesc, (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), StructureDesc, NULL, // verify function &bytesRequired, &entriesFilled, NULL ); IF_DEBUG(GROUP) { 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 )); } // // If all the entries could not be filled, return ERROR_MORE_DATA, // and return the buffer as is. Otherwise, the data needs to be // packed so that we don't send too much useless data. // if ( entriesFilled < totalEntries ) { Header->Status = ERROR_MORE_DATA; } else { Header->Converter = XsPackReturnData( (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), StructureDesc, entriesFilled ); } // // 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() ); } NetApiBufferFree( outBuffer ); // // Determine return buffer size. // XsSetDataCount( ¶meters->BufLen, StructureDesc, Header->Converter, entriesFilled, Header->Status ); return STATUS_SUCCESS; } // XsNetGroupEnum NTSTATUS XsNetGroupGetInfo ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetGroupGetInfo. 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_GROUP_GET_INFO parameters = Parameters; LPTSTR nativeGroupName = NULL; // Native parameters LPVOID outBuffer = NULL; LPBYTE stringLocation = NULL; // Conversion variables DWORD bytesRequired = 0; LPDESC nativeStructureDesc; API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings IF_DEBUG(GROUP) { NetpKdPrint(( "XsNetGroupGetInfo: header at %lx, " "params at %lx, level %ld\n", Header, parameters, SmbGetUshort( ¶meters->Level ) )); } try { // // Translate parameters, check for errors. // if ( XsWordParamOutOfRange( parameters->Level, 0, 1 )) { Header->Status = ERROR_INVALID_LEVEL; goto cleanup; } XsConvertTextParameter( nativeGroupName, (LPSTR)XsSmbGetPointer( ¶meters->GroupName ) ); // // Make the local call. // status = NetGroupGetInfo( NULL, nativeGroupName, (DWORD)SmbGetUshort( ¶meters->Level ), (LPBYTE *)&outBuffer ); if ( !XsApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetGroupGetInfo: NetGroupGetInfo 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 0: nativeStructureDesc = Desc32_group_info_0; StructureDesc = Desc16_group_info_0; break; case 1: nativeStructureDesc = Desc32_group_info_1; StructureDesc = Desc16_group_info_1; 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(( "XsNetGroupGetInfo: RapConvertSingleEntry failed: " "%X\n", status )); } Header->Status = NERR_InternalError; goto cleanup; } IF_DEBUG(GROUP) { 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(( "XsNetGroupGetInfo: Buffer too small %ld s.b. %ld.\n", SmbGetUshort( ¶meters->BufLen ), RapStructureSize( StructureDesc, Response, FALSE ) )); } Header->Status = NERR_BufTooSmall; } else if ( bytesRequired > (DWORD)SmbGetUshort( ¶meters-> BufLen )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "NetGroupGetInfo: 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 ); NetpMemoryFree( nativeGroupName ); // // Determine return buffer size. // XsSetDataCount( ¶meters->BufLen, StructureDesc, Header->Converter, 1, Header->Status ); return STATUS_SUCCESS; } // XsNetGroupGetInfo NTSTATUS XsNetGroupGetUsers ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetGroupGetUsers. 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_GROUP_GET_USERS parameters = Parameters; LPTSTR nativeGroupName = NULL; // Native parameters LPVOID outBuffer= NULL; DWORD entriesRead; DWORD totalEntries; DWORD entriesFilled = 0; // Conversion variables DWORD bytesRequired = 0; API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings IF_DEBUG(GROUP) { NetpKdPrint(( "XsNetGroupGetUsers: 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 ( SmbGetUshort( ¶meters->Level ) != 0 ) { Header->Status = ERROR_INVALID_LEVEL; goto cleanup; } XsConvertTextParameter( nativeGroupName, (LPSTR)XsSmbGetPointer( ¶meters->GroupName ) ); // // Make the local call. // status = NetGroupGetUsers( NULL, nativeGroupName, (DWORD)SmbGetUshort( ¶meters->Level ), (LPBYTE *)&outBuffer, XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )), &entriesRead, &totalEntries, NULL ); if ( !XsApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetGroupGetUsers: NetGroupGetUsers failed: %X\n", status )); } Header->Status = (WORD)status; goto cleanup; } IF_DEBUG(GROUP) { NetpKdPrint(( "XsNetGroupGetUsers: received %ld entries at %lx\n", entriesRead, outBuffer )); } // // Do the conversion from 32- to 16-bit data. // XsFillEnumBuffer( outBuffer, entriesRead, Desc32_group_users_info_0, (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), Desc16_group_users_info_0, NULL, // verify function &bytesRequired, &entriesFilled, NULL ); IF_DEBUG(GROUP) { 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 )); } // // If there is no room for one fixed structure, return NERR_BufTooSmall. // If all the entries could not be filled, return ERROR_MORE_DATA, // and return the buffer as is. GROUP_USERS_INFO_0 structures don't // need to be packed, because they have no variable data. // if ( !XsCheckBufferSize( SmbGetUshort( ¶meters->BufLen ), Desc16_group_users_info_0, FALSE // not in native format )) { Header->Status = NERR_BufTooSmall; } else if ( entriesFilled < totalEntries ) { Header->Status = ERROR_MORE_DATA; } // // 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() ); } NetApiBufferFree( outBuffer ); NetpMemoryFree( nativeGroupName ); // // Determine return buffer size. // XsSetDataCount( ¶meters->BufLen, Desc16_group_users_info_0, Header->Converter, entriesFilled, Header->Status ); return STATUS_SUCCESS; } // XsNetGroupGetUsers NTSTATUS XsNetGroupSetInfo ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetGroupSetInfo. 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_GROUP_SET_INFO parameters = Parameters; LPTSTR nativeGroupName = NULL; // Native parameters LPVOID buffer = NULL; WORD fieldIndex; // Conversion variables API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings try { // // Translate parameters, check for errors. // if ( SmbGetUshort( ¶meters->Level ) != 1 ) { Header->Status = ERROR_INVALID_LEVEL; goto cleanup; } XsConvertTextParameter( nativeGroupName, (LPSTR)XsSmbGetPointer( ¶meters->GroupName ) ); // // Translate parmnum to a field number. // fieldIndex = SmbGetUshort( ¶meters->ParmNum ); fieldIndex = ( fieldIndex == PARMNUM_ALL ) ? PARMNUM_ALL : fieldIndex + 1; status = XsConvertSetInfoBuffer( (LPBYTE)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), fieldIndex, TRUE, TRUE, Desc16_group_info_1, Desc32_group_info_1, Desc16_group_info_1_setinfo, Desc32_group_info_1_setinfo, (LPBYTE *)&buffer, NULL ); if ( status != NERR_Success ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupSetInfo: Problem with conversion: %X\n", status )); } Header->Status = (WORD)status; goto cleanup; } // // Do the actual local call. // status = NetGroupSetInfo( NULL, nativeGroupName, XsLevelFromParmNum( SmbGetUshort( ¶meters->Level ), SmbGetUshort( ¶meters->ParmNum )), buffer, NULL ); if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupSetInfo: NetGroupSetInfo 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. // NetpMemoryFree( buffer ); NetpMemoryFree( nativeGroupName ); return STATUS_SUCCESS; } // XsNetGroupSetInfo NTSTATUS XsNetGroupSetUsers ( API_HANDLER_PARAMETERS ) /*++ Routine Description: This routine handles a call to NetGroupSetUsers. 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_GROUP_SET_USERS parameters = Parameters; LPTSTR nativeGroupName = NULL; // Native parameters LPBYTE actualBuffer = NULL; DWORD userCount; LPBYTE stringLocation = NULL; // Conversion variables LPVOID buffer = NULL; DWORD bytesRequired = 0; LPDESC longDescriptor = NULL; LPDESC longNativeDescriptor = NULL; DWORD bufferSize; DWORD i; API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings IF_DEBUG(GROUP) { NetpKdPrint(( "XsNetGroupSetUsers: header at %lx, params at %lx," "level %ld\n", Header, parameters, SmbGetUshort( ¶meters->Level ) )); } try { // // Translate parameters, check for errors. // if ( SmbGetUshort( ¶meters->Level ) != 0 ) { Header->Status = ERROR_INVALID_LEVEL; goto cleanup; } StructureDesc = Desc16_group_users_info_0_set; AuxStructureDesc = Desc16_group_users_info_0; XsConvertTextParameter( nativeGroupName, (LPSTR)XsSmbGetPointer( ¶meters->GroupName ) ); // // Use the count of group_users_info_0 structures to form a long // descriptor string which can be used to do all the conversion // in one pass. // userCount = (DWORD)SmbGetUshort( ¶meters->Entries ); longDescriptor = NetpMemoryAllocate( strlen( StructureDesc ) + strlen( AuxStructureDesc ) * userCount + 1 ); longNativeDescriptor = NetpMemoryAllocate( strlen( Desc32_group_users_info_0_set ) + strlen( Desc32_group_users_info_0 ) * userCount + 1 ); if (( longDescriptor == NULL ) || ( longNativeDescriptor == NULL )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupSetUsers: failed to allocate memory" )); } Header->Status = NERR_NoRoom; goto cleanup; } strcpy( longDescriptor, StructureDesc ); strcpy( longNativeDescriptor, Desc32_group_users_info_0_set ); for ( i = 0; i < userCount; i++ ) { strcat( longDescriptor, AuxStructureDesc ); strcat( longNativeDescriptor, Desc32_group_users_info_0 ); } // // Figure out if there is enough room in the buffer for all this // data. If not, return NERR_BufTooSmall. // if ( !XsCheckBufferSize( SmbGetUshort( ¶meters->BufLen ), longDescriptor, FALSE // not in native format )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupSetUsers: Buffer too small.\n" )); } Header->Status = NERR_BufTooSmall; goto cleanup; } // // Find out how big a buffer we need to allocate to hold the native // 32-bit version of the input data structure. // bufferSize = XsBytesForConvertedStructure( (LPBYTE)XsSmbGetPointer( ¶meters->Buffer ), longDescriptor, longNativeDescriptor, RapToNative, TRUE ); // // Allocate enough memory to hold the converted native buffer. // buffer = NetpMemoryAllocate( bufferSize ); if ( buffer == NULL ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupSetUsers: failed to create buffer" )); } Header->Status = NERR_NoRoom; goto cleanup; } IF_DEBUG(GROUP) { NetpKdPrint(( "XsNetGroupSetUsers: buffer of %ld bytes at %lx\n", bufferSize, buffer )); } // // Convert the buffer from 16-bit to 32-bit. // stringLocation = (LPBYTE)buffer + bufferSize; bytesRequired = 0; status = RapConvertSingleEntry( (LPBYTE)XsSmbGetPointer( ¶meters->Buffer ), longDescriptor, TRUE, buffer, buffer, longNativeDescriptor, FALSE, &stringLocation, &bytesRequired, Response, RapToNative ); if ( status != NERR_Success ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupSetUsers: RapConvertSingleEntry failed: " "%X\n", status )); } Header->Status = NERR_InternalError; goto cleanup; } // // Check if we got all the entries. If not, we'll quit. // if ( RapAuxDataCount( buffer, Desc32_group_users_info_0_set, Both, TRUE ) != userCount ) { Header->Status = NERR_BufTooSmall; goto cleanup; } // // If there are no entries, there's no data. Otherwise, the data comes // after an initial header structure. // if ( userCount > 0 ) { actualBuffer = (LPBYTE)buffer + RapStructureSize( Desc32_group_users_info_0_set, Both, TRUE ); } else { actualBuffer = NULL; } // // Make the local call. // status = NetGroupSetUsers( NULL, nativeGroupName, (DWORD)SmbGetUshort( ¶meters->Level ), actualBuffer, userCount ); if ( !XsApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetGroupSetUsers: NetGroupSetUsers failed: %X\n", status )); } Header->Status = (WORD)status; goto cleanup; } // // There is no real return information for this API. // cleanup: ; } except ( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); } NetpMemoryFree( nativeGroupName ); NetpMemoryFree( buffer ); NetpMemoryFree( longDescriptor ); NetpMemoryFree( longNativeDescriptor ); return STATUS_SUCCESS; } // XsNetGroupSetUsers