|
|
/*++
Copyright (c) 1991-1992 Microsoft Corporation
Module Name:
ApiPrint.c
Abstract:
This module contains individual API handlers for the DosPrint APIs.
SUPPORTED : DosPrintDestAdd, DosPrintDestControl, DosPrintDestDel, DosPrintDestEnum, DosPrintDestGetInfo, DosPrintDestSetInfo, DosPrintJobContinue, DosPrintJobDel, DosPrintJobEnum, DosPrintJobGetId, DosPrintJobGetInfo, DosPrintJobPause, DosPrintJobSetInfo, DosPrintQAdd, DosPrintQContinue, DosPrintQDel, DosPrintQEnum, DosPrintQGetInfo, DosPrintQPause, DosPrintQPurge, DosPrintQSetInfo.
Author:
Shanku Niyogi (w-shanku) 04-Apr-1991
Revision History:
18-Jun-1992 JohnRo RAID 10324: net print vs. UNICODE. Use FORMAT_ equates. 01-Oct-1992 JohnRo RAID 3556: DosPrintQGetInfo(from downlevel) level 3, rc=124. (4&5 too.)
--*/
#include "XactSrvP.h"
#include <dosprint.h>
//
// Declaration of descriptor strings.
//
STATIC const LPDESC Desc16_print_dest_0 = REM16_print_dest_0; STATIC const LPDESC Desc32_print_dest_0 = REM32_print_dest_0; STATIC const LPDESC Desc16_print_dest_1 = REM16_print_dest_1; STATIC const LPDESC Desc32_print_dest_1 = REM32_print_dest_1; STATIC const LPDESC Desc16_print_dest_2 = REM16_print_dest_2; STATIC const LPDESC Desc32_print_dest_2 = REM32_print_dest_2; STATIC const LPDESC Desc16_print_dest_3 = REM16_print_dest_3; STATIC const LPDESC Desc32_print_dest_3 = REM32_print_dest_3; STATIC const LPDESC Desc16_print_dest_3_setinfo = REM16_print_dest_3_setinfo; STATIC const LPDESC Desc32_print_dest_3_setinfo = REM32_print_dest_3_setinfo; STATIC const LPDESC Desc16_print_job_0 = REM16_print_job_0; STATIC const LPDESC Desc32_print_job_0 = REM32_print_job_0; STATIC const LPDESC Desc16_print_job_1 = REM16_print_job_1; STATIC const LPDESC Desc32_print_job_1 = REM32_print_job_1; STATIC const LPDESC Desc16_print_job_1_setinfo = REM16_print_job_1_setinfo; STATIC const LPDESC Desc32_print_job_1_setinfo = REM32_print_job_1_setinfo; STATIC const LPDESC Desc16_print_job_2 = REM16_print_job_2; STATIC const LPDESC Desc32_print_job_2 = REM32_print_job_2; STATIC const LPDESC Desc16_print_job_3 = REM16_print_job_3; STATIC const LPDESC Desc32_print_job_3 = REM32_print_job_3; STATIC const LPDESC Desc16_print_job_3_setinfo = REM16_print_job_3_setinfo; STATIC const LPDESC Desc32_print_job_3_setinfo = REM32_print_job_3_setinfo; STATIC const LPDESC Desc16_printQ_0 = REM16_printQ_0; STATIC const LPDESC Desc32_printQ_0 = REM32_printQ_0; STATIC const LPDESC Desc16_printQ_1 = REM16_printQ_1; STATIC const LPDESC Desc32_printQ_1 = REM32_printQ_1; STATIC const LPDESC Desc16_printQ_1_setinfo = REM16_printQ_1_setinfo; STATIC const LPDESC Desc32_printQ_1_setinfo = REM32_printQ_1_setinfo; STATIC const LPDESC Desc16_printQ_2 = REM16_printQ_2; STATIC const LPDESC Desc32_printQ_2 = REM32_printQ_2; STATIC const LPDESC Desc16_printQ_3 = REM16_printQ_3; STATIC const LPDESC Desc32_printQ_3 = REM32_printQ_3; STATIC const LPDESC Desc16_printQ_3_setinfo = REM16_printQ_3_setinfo; STATIC const LPDESC Desc32_printQ_3_setinfo = REM32_printQ_3_setinfo; STATIC const LPDESC Desc16_printQ_4 = REM16_printQ_4; STATIC const LPDESC Desc32_printQ_4 = REM32_printQ_4; STATIC const LPDESC Desc16_printQ_5 = REM16_printQ_5; STATIC const LPDESC Desc32_printQ_5 = REM32_printQ_5; STATIC const LPDESC Desc16_printQ_52 = REM16_printQ_52; STATIC const LPDESC Desc32_printQ_52 = REM32_printQ_52;
//
// DosPrint calls behave differently from Net api calls. On Net api calls,
// the called routine supplies the buffer to us. DosPrint apis need a
// supplied buffer and thus can return NERR_BufferTooSmall which means
// it's an error but return the bytes needed if it's a XXGetInfo call.
//
#define XsPrintApiSuccess( Status ) \
(( (Status) == NERR_Success ) || ( (Status) == ERROR_MORE_DATA ))
//
// Now that servers can have multiple names (See SrvNetTransportAdd, and clusters),
// it is necessary to transmit the server name part of a queue name to the spooler.
// The following three macros aid in the translation.
//
#define PREPARE_CONVERT_QUEUE_NAME() \
WCHAR queueNameBuf[ MAX_PATH ]; \ CHAR localComputerName[ NETBIOS_NAME_LEN ]; \ DWORD localComputerNameLen = sizeof( localComputerName ); \ PUCHAR p = &Header->ServerName[ NETBIOS_NAME_LEN-2 ]; \ for( ; p > Header->ServerName && *p == ' '; p-- ); \ p++; \ GetComputerNameA( localComputerName, &localComputerNameLen );
#define CONVERT_QUEUE_NAME( queue ) \
if( queue && ((DWORD)(p-Header->ServerName) != localComputerNameLen || \ memcmp( localComputerName, Header->ServerName, localComputerNameLen )) &&\ mbstowcs( NULL, Header->ServerName, (size_t)(p-Header->ServerName )) <= \ sizeof( queueNameBuf ) - wcslen(queue)*sizeof(WCHAR) - 4*sizeof(WCHAR)){\ \ RtlZeroMemory( queueNameBuf, sizeof( queueNameBuf ) ); \ queueNameBuf[0] = queueNameBuf[1] = L'\\'; \ mbstowcs( queueNameBuf+2, Header->ServerName, \ (size_t)(p-Header->ServerName) ); \ wcscat( queueNameBuf, L"\\" ); \ wcscat( queueNameBuf, queue ); \ NetApiBufferFree( queue ); \ queue = queueNameBuf; \ }
#define FREE_QUEUE_NAME( queue ) if( queue != queueNameBuf ) NetApiBufferFree( queue )
#define GET_LOCAL_SERVER_NAME() \
WCHAR LocalServerName[ MAX_PATH ]; \ PUCHAR p = &Header->ServerName[ NETBIOS_NAME_LEN-2 ]; \ for( ; p > Header->ServerName && *p == ' '; p-- ); \ p++; \ LocalServerName[0] = LocalServerName[1] = L'\\'; \ mbstowcs( LocalServerName+2, Header->ServerName, \ (size_t)(p-Header->ServerName) ); \ LocalServerName[2+p-Header->ServerName] = L'\0';
NTSTATUS XsNetPrintDestAdd ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintDestAdd.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_DEST_ADD parameters = Parameters; LPVOID buffer = NULL; // Native parameters
LPBYTE stringLocation = NULL; // Conversion variables
DWORD bytesRequired = 0; DWORD bufferSize;
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintDestAdd: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "level " FORMAT_DWORD "\n", Header, parameters, SmbGetUshort( ¶meters->Level ) )); }
try { //
// Check for errors.
//
if ( SmbGetUshort( ¶meters->Level ) != 3 ) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
StructureDesc = Desc16_print_dest_3;
//
// 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(( "XsNetPrintDestAdd: 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, Desc32_print_dest_3, RapToNative, TRUE );
//
// Allocate enough memory to hold the converted native buffer.
//
buffer = NetpMemoryAllocate( bufferSize );
if ( buffer == NULL ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintDestAdd: failed to create buffer" )); } Header->Status = NERR_NoRoom; goto cleanup;
}
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintDestAdd: buffer of " FORMAT_DWORD " bytes at " FORMAT_LPVOID "\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, Desc32_print_dest_3, FALSE, &stringLocation, &bytesRequired, Response, RapToNative );
if ( status != NERR_Success ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintDestAdd: RapConvertSingleEntry failed: " FORMAT_API_STATUS "\n", status )); }
Header->Status = NERR_InternalError; goto cleanup; }
//
// Make the local call.
//
status = DosPrintDestAdd( NULL, SmbGetUshort( ¶meters->Level ), buffer, (WORD)bufferSize );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintDestAdd: DosPrintDestAdd failed: " FORMAT_API_STATUS "\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;
} // XsNetPrintDestAdd
NTSTATUS XsNetPrintDestControl ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintDestControl.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_DEST_CONTROL parameters = Parameters; LPTSTR nativeDestName = NULL; // Native parameters
PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintDestControl: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "name " FORMAT_LPSTR "\n", Header, parameters, SmbGetUlong( ¶meters->DestName ))); }
try { //
// Translate parameters, check for errors.
//
XsConvertTextParameter( nativeDestName, (LPSTR)XsSmbGetPointer( ¶meters->DestName ) );
CONVERT_QUEUE_NAME( nativeDestName );
//
// Make the local call.
//
status = DosPrintDestControl( NULL, nativeDestName, SmbGetUshort( ¶meters->Control ) );
cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintDestControl: DosPrintDestControl failed: " FORMAT_API_STATUS "\n", status )); } }
//
// Nothing to return.
//
Header->Status = (WORD)status;
FREE_QUEUE_NAME( nativeDestName );
return STATUS_SUCCESS;
} // XsNetPrintDestControl
NTSTATUS XsNetPrintDestDel ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintDestDel.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_DEST_DEL parameters = Parameters; LPTSTR nativePrinterName = NULL; // Native parameters
PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintDestDel: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "name " FORMAT_LPSTR "\n", Header, parameters, SmbGetUlong( ¶meters->PrinterName ))); }
try { //
// Translate parameters, check for errors.
//
XsConvertTextParameter( nativePrinterName, (LPSTR)XsSmbGetPointer( ¶meters->PrinterName ) );
CONVERT_QUEUE_NAME( nativePrinterName );
//
// Make the local call.
//
status = DosPrintDestDel( NULL, nativePrinterName ); cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintDestDel: DosPrintDestDel failed: " FORMAT_API_STATUS "\n", status )); } }
//
// Nothing to return.
//
Header->Status = (WORD)status;
FREE_QUEUE_NAME( nativePrinterName ); return STATUS_SUCCESS;
} // XsNetPrintDestDel
NTSTATUS XsNetPrintDestEnum ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintDestEnum.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_DEST_ENUM parameters = Parameters; LPVOID outBuffer= NULL; // Native parameters
DWORD outBufferSize; DWORD entriesRead = 0; DWORD totalEntries = 0;
DWORD entriesFilled = 0; // Conversion variables
DWORD bytesRequired = 0; LPDESC nativeStructureDesc;
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintDestEnum: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "level " FORMAT_DWORD ", buf size " FORMAT_DWORD "\n", Header, parameters, SmbGetUshort( ¶meters->Level ), SmbGetUshort( ¶meters->BufLen ))); }
try { //
// Check for errors.
//
if ( XsWordParamOutOfRange( parameters->Level, 0, 3 )) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
//
// !!! Print API mapping layer presently requires a preallocated buffer.
//
outBufferSize = XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )); if ( NetapipBufferAllocate( outBufferSize, &outBuffer ) != NERR_Success || outBuffer == NULL ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintDestEnum: cannot allocate memory\n" )); } Header->Status = NERR_NoRoom; goto cleanup; }
//
// Make the local call.
//
status = DosPrintDestEnum( NULL, SmbGetUshort( ¶meters->Level ), (LPBYTE)outBuffer, (WORD)outBufferSize, (LPWORD)&entriesRead, (LPWORD)&totalEntries );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetPrintDestEnum: DosPrintDestEnum failed: " FORMAT_API_STATUS "\n", status )); } Header->Status = (WORD)status; goto cleanup; }
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintDestEnum: received " FORMAT_DWORD " entries at " FORMAT_LPVOID "\n", entriesRead, outBuffer )); }
//
// Use the requested level to determine the format of the
// data structure.
//
switch ( SmbGetUshort( ¶meters->Level ) ) {
case 0:
nativeStructureDesc = Desc32_print_dest_0; StructureDesc = Desc16_print_dest_0; break;
case 1:
nativeStructureDesc = Desc32_print_dest_1; StructureDesc = Desc16_print_dest_1; break;
case 2:
nativeStructureDesc = Desc32_print_dest_2; StructureDesc = Desc16_print_dest_2; break;
case 3:
nativeStructureDesc = Desc32_print_dest_3; StructureDesc = Desc16_print_dest_3; 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(PRINT) { NetpKdPrint(( "32-bit data at " FORMAT_LPVOID ", 16-bit data at " FORMAT_LPVOID ", " FORMAT_DWORD " BR," " Entries " FORMAT_DWORD " of " FORMAT_DWORD "\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->Returned, (WORD)entriesFilled ); SmbPutUshort( ¶meters->Total, (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;
} // XsNetPrintDestEnum
NTSTATUS XsNetPrintDestGetInfo ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintDestGetInfo.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_DEST_GET_INFO parameters = Parameters; LPTSTR nativeName = NULL; // Native parameters
LPVOID outBuffer = NULL; DWORD outBufferSize; WORD bytesNeeded = 0;
LPBYTE stringLocation = NULL; // Conversion variables
DWORD bytesRequired = 0; LPDESC nativeStructureDesc; PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintDestGetInfo: header at " FORMAT_LPVOID ", " "params at " FORMAT_LPVOID ", level " FORMAT_DWORD "\n", Header, parameters, SmbGetUshort( ¶meters->Level ) )); }
try { //
// Translate parameters, check for errors.
//
if ( XsWordParamOutOfRange( parameters->Level, 0, 3 )) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
XsConvertTextParameter( nativeName, (LPSTR)XsSmbGetPointer( ¶meters->Name ) );
CONVERT_QUEUE_NAME( nativeName );
//
// !!! Print API mapping layer presently requires a preallocated buffer.
//
outBufferSize = XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )); if ( NetapipBufferAllocate( outBufferSize, &outBuffer ) != NERR_Success || outBuffer == NULL ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintDestGetInfo: cannot allocate memory\n" )); } Header->Status = NERR_NoRoom; goto cleanup; }
//
// Make the local call.
//
status = DosPrintDestGetInfo( NULL, nativeName, SmbGetUshort( ¶meters->Level ), (LPBYTE)outBuffer, (WORD)outBufferSize, &bytesNeeded );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetPrintDestGetInfo: DosPrintDestGetInfo failed: " FORMAT_API_STATUS "\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_print_dest_0; StructureDesc = Desc16_print_dest_0; break;
case 1:
nativeStructureDesc = Desc32_print_dest_1; StructureDesc = Desc16_print_dest_1; break;
case 2:
nativeStructureDesc = Desc32_print_dest_2; StructureDesc = Desc16_print_dest_2; break;
case 3:
nativeStructureDesc = Desc32_print_dest_3; StructureDesc = Desc16_print_dest_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(( "XsDosPrintDestGetInfo: RapConvertSingleEntry failed: " FORMAT_API_STATUS "\n", status )); }
Header->Status = NERR_InternalError; goto cleanup; }
IF_DEBUG(PRINT) { NetpKdPrint(( "32-bit data at " FORMAT_LPVOID ", 16-bit data at " FORMAT_LPVOID ", " FORMAT_DWORD " 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(( "XsNetPrintDestGetInfo: Buffer too small.\n" )); } Header->Status = NERR_BufTooSmall;
} else if ( bytesRequired > (DWORD)SmbGetUshort( ¶meters-> BufLen )) {
IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintDestGetInfo: 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 ); }
bytesNeeded = (WORD)bytesRequired;
cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
//
// Set up the response parameters.
//
SmbPutUshort( ¶meters->Needed, bytesNeeded );
NetApiBufferFree( outBuffer ); FREE_QUEUE_NAME( nativeName );
//
// Determine return buffer size.
//
XsSetDataCount( ¶meters->BufLen, StructureDesc, Header->Converter, 1, Header->Status );
return STATUS_SUCCESS;
} // XsNetPrintDestGetInfo
NTSTATUS XsNetPrintDestSetInfo ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintDestSetInfo.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_DEST_SET_INFO parameters = Parameters; LPTSTR nativeName = NULL; // Native parameters
LPVOID buffer = NULL; DWORD bytesRequired; PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
try { //
// Translate parameters, check for errors.
//
if ( SmbGetUshort( ¶meters->Level ) != 3 ) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
StructureDesc = Desc16_print_dest_3;
XsConvertTextParameter( nativeName, (LPSTR)XsSmbGetPointer( ¶meters->Name ) );
status = XsConvertSetInfoBuffer( (LPBYTE)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), SmbGetUshort( ¶meters->ParmNum ), FALSE, TRUE, StructureDesc, Desc32_print_dest_3, Desc16_print_dest_3_setinfo, Desc32_print_dest_3_setinfo, (LPBYTE *)&buffer, &bytesRequired );
if ( status != NERR_Success ) {
IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintDestSetInfo: Problem with conversion: " FORMAT_API_STATUS "\n", status )); } Header->Status = (WORD)status; goto cleanup;
}
CONVERT_QUEUE_NAME( nativeName );
//
// Do the actual local call.
//
status = DosPrintDestSetInfo( NULL, nativeName, SmbGetUshort( ¶meters->Level ), (LPBYTE)buffer, (WORD)bytesRequired, SmbGetUshort( ¶meters->ParmNum ) );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintDestSetInfo: DosPrintDestSetInfo failed: " FORMAT_API_STATUS "\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 ); FREE_QUEUE_NAME( nativeName );
return STATUS_SUCCESS;
} // XsNetPrintDestSetInfo
NTSTATUS XsNetPrintJobContinue ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintJobContinue.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_JOB_CONTINUE parameters = Parameters;
GET_LOCAL_SERVER_NAME(); API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintJobContinue: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "job " FORMAT_WORD_ONLY "\n", Header, parameters, SmbGetUshort( ¶meters->JobId ))); }
try { //
// Make the local call.
//
status = DosPrintJobContinue( LocalServerName, FALSE, SmbGetUshort( ¶meters->JobId ) );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintJobContinue: DosPrintJobContinue failed: " FORMAT_API_STATUS "\n", status )); } } } except( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
//
// Nothing to return.
//
Header->Status = (WORD)status;
return STATUS_SUCCESS;
} // XsNetPrintJobContinue
NTSTATUS XsNetPrintJobDel ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintJobDel.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_JOB_DEL parameters = Parameters;
GET_LOCAL_SERVER_NAME(); API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintJobDel: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "job " FORMAT_WORD_ONLY "\n", Header, parameters, SmbGetUshort( ¶meters->JobId ))); }
try { //
// Make the local call.
//
status = DosPrintJobDel( LocalServerName, FALSE, SmbGetUshort( ¶meters->JobId ) );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintJobDel: DosPrintJobDel failed: " FORMAT_API_STATUS "\n", status )); } } } except( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
//
// Nothing to return.
//
Header->Status = (WORD)status;
return STATUS_SUCCESS;
} // XsNetPrintJobDel
NTSTATUS XsNetPrintJobEnum ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintJobEnum.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_JOB_ENUM parameters = Parameters; LPTSTR nativeQueueName = NULL; // Native parameters
LPVOID outBuffer= NULL; DWORD outBufferSize; DWORD entriesRead = 0; DWORD totalEntries = 0;
DWORD entriesFilled = 0; // Conversion variables
DWORD bytesRequired = 0; LPDESC nativeStructureDesc; WORD bufferLength; PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintJobEnum: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "level " FORMAT_DWORD ", buf size " FORMAT_DWORD "\n", Header, parameters, SmbGetUshort( ¶meters->Level ), SmbGetUshort( ¶meters->BufLen ))); }
try { //
// Translate parameters, check for errors.
//
if ( XsWordParamOutOfRange( parameters->Level, 0, 2 )) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
XsConvertTextParameter( nativeQueueName, (LPSTR)XsSmbGetPointer( ¶meters->QueueName ) );
bufferLength = SmbGetUshort( ¶meters->BufLen );
CONVERT_QUEUE_NAME( nativeQueueName );
//
// !!! Print API mapping layer presently requires a preallocated buffer.
//
outBufferSize = XsNativeBufferSize( bufferLength ); if ( NetapipBufferAllocate( outBufferSize, &outBuffer ) != NERR_Success || outBuffer == NULL ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintJobEnum: cannot allocate memory\n" )); } Header->Status = NERR_NoRoom; goto cleanup; }
//
// Make the local call.
//
status = DosPrintJobEnum( NULL, nativeQueueName, SmbGetUshort( ¶meters->Level ), (LPBYTE)outBuffer, (WORD)outBufferSize, (LPWORD)&entriesRead, (LPWORD)&totalEntries );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetPrintJobEnum: DosPrintJobEnum failed: " FORMAT_API_STATUS "\n", status )); } Header->Status = (WORD)status; goto cleanup; }
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintJobEnum: received " FORMAT_DWORD " entries at " FORMAT_LPVOID "\n", entriesRead, outBuffer )); }
//
// Use the requested level to determine the format of the
// data structure.
//
switch ( SmbGetUshort( ¶meters->Level ) ) {
case 0:
nativeStructureDesc = Desc32_print_job_0; StructureDesc = Desc16_print_job_0; break;
case 1:
nativeStructureDesc = Desc32_print_job_1; StructureDesc = Desc16_print_job_1; break;
case 2:
nativeStructureDesc = Desc32_print_job_2; StructureDesc = Desc16_print_job_2; 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 ), (DWORD)bufferLength, StructureDesc, NULL, // verify function
&bytesRequired, &entriesFilled, NULL );
IF_DEBUG(PRINT) { NetpKdPrint(( "32-bit data at " FORMAT_LPVOID ", 16-bit data at " FORMAT_LPVOID ", " FORMAT_DWORD " BR," " Entries " FORMAT_DWORD " of " FORMAT_DWORD "\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) || (bytesRequired > bufferLength) ) {
Header->Status = ERROR_MORE_DATA;
} else {
Header->Converter = XsPackReturnData( (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), bufferLength, StructureDesc, entriesFilled );
}
//
// Set up the response parameters.
//
SmbPutUshort( ¶meters->Returned, (WORD)entriesFilled ); SmbPutUshort( ¶meters->Total, (WORD)totalEntries );
cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
NetApiBufferFree( outBuffer ); FREE_QUEUE_NAME( nativeQueueName );
//
// Determine return buffer size.
//
XsSetDataCount( ¶meters->BufLen, StructureDesc, Header->Converter, entriesFilled, Header->Status );
return STATUS_SUCCESS;
} // XsNetPrintJobEnum
NTSTATUS XsNetPrintJobGetInfo ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintJobGetInfo.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_JOB_GET_INFO parameters = Parameters; LPVOID outBuffer = NULL; // Native parameters
DWORD outBufferSize; WORD bytesNeeded = 0;
LPBYTE stringLocation = NULL; // Conversion variables
DWORD bytesRequired = 0; LPDESC nativeStructureDesc;
GET_LOCAL_SERVER_NAME(); API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintJobGetInfo: header at " FORMAT_LPVOID ", " "params at " FORMAT_LPVOID ", level " FORMAT_DWORD "\n", Header, parameters, SmbGetUshort( ¶meters->Level ) )); }
try { //
// Check for errors.
//
if ( XsWordParamOutOfRange( parameters->Level, 0, 3 )) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
//
// !!! Print API mapping layer presently requires a preallocated buffer.
//
outBufferSize = XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )); if ( NetapipBufferAllocate( outBufferSize, &outBuffer ) != NERR_Success || outBuffer == NULL ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintJobGetInfo: cannot allocate memory\n" )); } Header->Status = NERR_NoRoom; goto cleanup; }
//
// Make the local call.
//
status = DosPrintJobGetInfo( LocalServerName, FALSE, SmbGetUshort( ¶meters->JobId ), SmbGetUshort( ¶meters->Level ), (LPBYTE)outBuffer, (WORD)outBufferSize, &bytesNeeded );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetPrintJobGetInfo: DosPrintJobGetInfo failed: " FORMAT_API_STATUS "\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_print_job_0; StructureDesc = Desc16_print_job_0; break;
case 1:
nativeStructureDesc = Desc32_print_job_1; StructureDesc = Desc16_print_job_1; break;
case 2:
nativeStructureDesc = Desc32_print_job_2; StructureDesc = Desc16_print_job_2; break;
case 3:
nativeStructureDesc = Desc32_print_job_3; StructureDesc = Desc16_print_job_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(( "XsDosPrintJobGetInfo: RapConvertSingleEntry failed: " FORMAT_API_STATUS "\n", status )); }
Header->Status = NERR_InternalError; goto cleanup; }
IF_DEBUG(PRINT) { NetpKdPrint(( "32-bit data at " FORMAT_LPVOID ", 16-bit data at " FORMAT_LPVOID ", " FORMAT_DWORD " 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(( "XsNetPrintJobGetInfo: Buffer too small.\n" )); }
Header->Status = NERR_BufTooSmall;
} else if ( bytesRequired > (DWORD)SmbGetUshort( ¶meters-> BufLen )) {
IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintJobGetInfo: 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 ); }
bytesNeeded = (WORD)bytesRequired;
cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
//
// Set up the response parameters.
//
SmbPutUshort( ¶meters->Needed, bytesNeeded );
NetApiBufferFree( outBuffer );
//
// Determine return buffer size.
//
XsSetDataCount( ¶meters->BufLen, StructureDesc, Header->Converter, 1, Header->Status );
return STATUS_SUCCESS;
} // XsNetPrintJobGetInfo
NTSTATUS XsNetPrintJobPause ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintJobPause.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_JOB_PAUSE parameters = Parameters;
GET_LOCAL_SERVER_NAME(); API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintJobPause: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "job " FORMAT_WORD_ONLY "\n", Header, parameters, SmbGetUshort( ¶meters->JobId ))); }
try { //
// Make the local call.
//
status = DosPrintJobPause( LocalServerName, FALSE, SmbGetUshort( ¶meters->JobId ) ); } except( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintJobPause: DosPrintJobPause failed: " FORMAT_API_STATUS "\n", status )); } }
//
// Nothing to return.
//
Header->Status = (WORD)status;
return STATUS_SUCCESS;
} // XsNetPrintJobPause
NTSTATUS XsNetPrintJobSetInfo ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintJobSetInfo.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_JOB_SET_INFO parameters = Parameters; LPVOID buffer = NULL; // Native parameters
DWORD bytesRequired; WORD level;
DWORD fieldIndex; LPDESC setInfoDesc; // Conversion variables
LPDESC nativeSetInfoDesc; LPDESC nativeStructureDesc;
GET_LOCAL_SERVER_NAME(); API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
try { //
// Check for errors.
//
level = SmbGetUshort( ¶meters->Level );
if ( level != 1 && level != 3 ) { Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
//
// Determine descriptor strings based on level. Also translate the
// parmnum value to a field index.
// !!! - Right now, we don't check for parameters settable in downlevel
// that are meaningless in the NT mapping layer. Fix this,
// if necessary, in the descriptor string file (with
// REM_IGNORE fields).
//
fieldIndex = (DWORD)SmbGetUshort( ¶meters->ParmNum );
switch ( level ) {
case 1:
StructureDesc = Desc16_print_job_1; nativeStructureDesc = Desc32_print_job_1; setInfoDesc = Desc16_print_job_1_setinfo; nativeSetInfoDesc = Desc32_print_job_1_setinfo; if ( fieldIndex > 2 ) { // Account for pad field
fieldIndex++; }
break;
case 3:
StructureDesc = Desc16_print_job_3; nativeStructureDesc = Desc32_print_job_3; setInfoDesc = Desc16_print_job_3_setinfo; nativeSetInfoDesc = Desc32_print_job_3_setinfo; if ( fieldIndex != PARMNUM_ALL && fieldIndex < 15 ) { switch ( fieldIndex ) { case PRJ_NOTIFYNAME_PARMNUM: case PRJ_DATATYPE_PARMNUM: case PRJ_PARMS_PARMNUM: fieldIndex += 7; break; case PRJ_POSITION_PARMNUM: fieldIndex = 4; break; case PRJ_COMMENT_PARMNUM: case PRJ_DOCUMENT_PARMNUM: fieldIndex -= 3; break; case PRJ_PRIORITY_PARMNUM: fieldIndex = 2; break; default: fieldIndex = 0xFFFFFFFF; // Some invalid field
} }
break;
}
status = XsConvertSetInfoBuffer( (LPBYTE)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), (WORD)fieldIndex, FALSE, TRUE, StructureDesc, nativeStructureDesc, setInfoDesc, nativeSetInfoDesc, (LPBYTE *)&buffer, &bytesRequired );
if ( status != NERR_Success ) {
IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintJobSetInfo: Problem with conversion: " FORMAT_API_STATUS "\n", status )); } Header->Status = (WORD)status; goto cleanup;
}
//
// Do the actual local call.
//
status = DosPrintJobSetInfo( LocalServerName, FALSE, SmbGetUshort( ¶meters->JobId ), level, (LPBYTE)buffer, (WORD)bytesRequired, SmbGetUshort( ¶meters->ParmNum ) );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintJobSetInfo: DosPrintJobSetInfo failed: " FORMAT_API_STATUS "\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 );
return STATUS_SUCCESS;
} // XsNetPrintJobSetInfo
NTSTATUS XsNetPrintQAdd ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintQAdd.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_Q_ADD parameters = Parameters; LPVOID buffer = NULL; // Native parameters
LPBYTE stringLocation = NULL; // Conversion variables
DWORD bytesRequired = 0; LPTSTR nativeStructureDesc; DWORD bufferSize;
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintQAdd: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "level " FORMAT_DWORD "\n", Header, parameters, SmbGetUshort( ¶meters->Level ) )); }
try {
//
// Determine native structure descriptor based on level.
//
switch ( SmbGetUshort( ¶meters->Level )) {
case 1: StructureDesc = Desc16_printQ_1; nativeStructureDesc = (LPTSTR)Desc32_printQ_1; break;
case 3: StructureDesc = Desc16_printQ_3; nativeStructureDesc = (LPTSTR)Desc32_printQ_3; 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(( "XsNetPrintQAdd: 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, (LPDESC)nativeStructureDesc, RapToNative, TRUE );
//
// Allocate enough memory to hold the converted native buffer.
//
buffer = NetpMemoryAllocate( bufferSize );
if ( buffer == NULL ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQAdd: failed to create buffer" )); } Header->Status = NERR_NoRoom; goto cleanup;
}
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintQAdd: buffer of " FORMAT_DWORD " bytes at " FORMAT_LPVOID "\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, (LPDESC)nativeStructureDesc, FALSE, &stringLocation, &bytesRequired, Response, RapToNative );
if ( status != NERR_Success ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQAdd: RapConvertSingleEntry failed: " FORMAT_API_STATUS "\n", status )); }
Header->Status = NERR_InternalError; goto cleanup; }
//
// Make the local call.
//
status = DosPrintQAdd( NULL, SmbGetUshort( ¶meters->Level ), buffer, (WORD)bufferSize );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQAdd: DosPrintQAdd failed: " FORMAT_API_STATUS "\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;
} // XsNetPrintQAdd
NTSTATUS XsNetPrintQContinue ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintQContinue.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_Q_CONTINUE parameters = Parameters; LPTSTR nativeQueueName = NULL; // Native parameters
PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintQContinue: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "name " FORMAT_LPSTR "\n", Header, parameters, SmbGetUlong( ¶meters->QueueName ))); }
try { //
// Translate parameters, check for errors.
//
XsConvertTextParameter( nativeQueueName, (LPSTR)XsSmbGetPointer( ¶meters->QueueName ) );
CONVERT_QUEUE_NAME( nativeQueueName );
//
// Make the local call.
//
status = DosPrintQContinue( NULL, nativeQueueName ); cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQContinue: DosPrintQContinue failed: " FORMAT_API_STATUS "\n", status )); } }
//
// Nothing to return.
//
Header->Status = (WORD)status;
FREE_QUEUE_NAME( nativeQueueName ); return STATUS_SUCCESS;
} // XsNetPrintQContinue
NTSTATUS XsNetPrintQDel ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintQDel.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_Q_DEL parameters = Parameters; LPTSTR nativeQueueName = NULL; // Native parameters
PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintQDel: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", name " FORMAT_LPSTR "\n", Header, parameters, SmbGetUlong( ¶meters->QueueName ))); }
try { //
// Translate parameters, check for errors.
//
XsConvertTextParameter( nativeQueueName, (LPSTR)XsSmbGetPointer( ¶meters->QueueName ) );
CONVERT_QUEUE_NAME( nativeQueueName );
//
// Make the local call.
//
status = DosPrintQDel( NULL, nativeQueueName );
cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQDel: DosPrintQDel failed: " FORMAT_API_STATUS "\n", status )); } }
//
// Nothing to return.
//
Header->Status = (WORD)status;
FREE_QUEUE_NAME( nativeQueueName ); return STATUS_SUCCESS;
} // XsNetPrintQDel
NTSTATUS XsNetPrintQEnum ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintQEnum.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_Q_ENUM parameters = Parameters; LPVOID outBuffer= NULL; // Native parameters
DWORD outBufferSize; DWORD entriesRead = 0; DWORD totalEntries = 0; WORD bufferLength;
DWORD entriesFilled = 0; // Conversion variables
DWORD bytesRequired = 0; LPDESC nativeStructureDesc; LPDESC nativeAuxStructureDesc;
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintQEnum: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "level " FORMAT_DWORD ", buf size " FORMAT_DWORD "\n", Header, parameters, SmbGetUshort( ¶meters->Level ), SmbGetUshort( ¶meters->BufLen ))); }
try { //
// Check for errors.
//
if ( XsWordParamOutOfRange( parameters->Level, 0, 5 )) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
//
// !!! Print API mapping layer presently requires a preallocated buffer.
//
bufferLength = SmbGetUshort( ¶meters->BufLen ); outBufferSize = XsNativeBufferSize( bufferLength ); if ( NetapipBufferAllocate( outBufferSize, &outBuffer ) != NERR_Success || outBuffer == NULL ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQEnum: cannot allocate memory\n" )); } Header->Status = NERR_NoRoom; goto cleanup; }
//
// Make the local call.
//
status = DosPrintQEnum( NULL, SmbGetUshort( ¶meters->Level ), (LPBYTE)outBuffer, (WORD)outBufferSize, (LPWORD)&entriesRead, (LPWORD)&totalEntries );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetPrintQEnum: DosPrintQEnum failed: " FORMAT_API_STATUS "\n", status )); } Header->Status = (WORD)status; goto cleanup; }
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintQEnum: received " FORMAT_DWORD " entries at " FORMAT_LPVOID "\n", entriesRead, outBuffer )); }
//
// Use the requested level to determine the format of the
// data structure.
//
nativeAuxStructureDesc = NULL; AuxStructureDesc = NULL;
switch ( SmbGetUshort( ¶meters->Level ) ) {
case 0:
nativeStructureDesc = Desc32_printQ_0; StructureDesc = Desc16_printQ_0; break;
case 1:
nativeStructureDesc = Desc32_printQ_1; StructureDesc = Desc16_printQ_1; break;
case 2:
nativeStructureDesc = Desc32_printQ_2; nativeAuxStructureDesc = Desc32_print_job_1; StructureDesc = Desc16_printQ_2; AuxStructureDesc = Desc16_print_job_1; break;
case 3:
nativeStructureDesc = Desc32_printQ_3; StructureDesc = Desc16_printQ_3; break;
case 4:
nativeStructureDesc = Desc32_printQ_4; nativeAuxStructureDesc = Desc32_print_job_2; StructureDesc = Desc16_printQ_4; AuxStructureDesc = Desc16_print_job_2; break;
case 5:
nativeStructureDesc = Desc32_printQ_5; StructureDesc = Desc16_printQ_5; break; }
//
// Do the actual conversion from the 32-bit structures to 16-bit
// structures. Levels 2 and 4 have auxiliary data, other levels call
// with NULL auxiliary descriptors, so that the normal XsFillEnumBuffer
// is called.
//
XsFillAuxEnumBuffer( outBuffer, entriesRead, nativeStructureDesc, nativeAuxStructureDesc, (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), (DWORD)bufferLength, StructureDesc, AuxStructureDesc, NULL, // verify function
&bytesRequired, &entriesFilled, NULL );
IF_DEBUG(PRINT) { NetpKdPrint(( "32-bit data at " FORMAT_LPVOID ", 16-bit data at " FORMAT_LPVOID ", " FORMAT_DWORD " BR," " Entries " FORMAT_DWORD " of " FORMAT_DWORD "\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. We won't
// try to pack the ones with the auxiliary structures.
//
if ( (entriesFilled < totalEntries) || (bytesRequired > bufferLength) ) {
Header->Status = ERROR_MORE_DATA;
} else {
switch ( SmbGetUshort( ¶meters->Level )) {
case 2: case 4:
break;
default:
Header->Converter = XsPackReturnData( (LPVOID)XsSmbGetPointer( ¶meters->Buffer ), bufferLength, StructureDesc, entriesFilled ); } }
//
// Set up the response parameters.
//
SmbPutUshort( ¶meters->Returned, (WORD)entriesFilled ); SmbPutUshort( ¶meters->Total, (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;
} // XsNetPrintQEnum
NTSTATUS XsNetPrintQGetInfo ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintQGetInfo.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_Q_GET_INFO parameters = Parameters; LPTSTR nativeQueueName = NULL; // Native parameters
LPVOID outBuffer = NULL; DWORD outBufferSize; WORD bytesNeeded = 0;
LPBYTE stringLocation = NULL; // Conversion variables
DWORD bytesRequired = 0; LPDESC nativeStructureDesc = NULL; LPDESC nativeAuxStructureDesc = NULL; LPDESC longDescriptor = NULL; LPDESC longNativeDescriptor = NULL; DWORD auxDataCount; DWORD i; PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintQGetInfo: header at " FORMAT_LPVOID ", " "params at " FORMAT_LPVOID ", level " FORMAT_DWORD "\n", Header, parameters, SmbGetUshort( ¶meters->Level ) )); }
try { //
// Translate parameters, check for errors.
//
//
// Level 52 supported for Win95 clients
//
if ( XsWordParamOutOfRange( parameters->Level, 0, 5 ) && (DWORD) SmbGetUshort(¶meters->Level) != 52 ) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
XsConvertTextParameter( nativeQueueName, (LPSTR)XsSmbGetPointer( ¶meters->QueueName ) );
CONVERT_QUEUE_NAME( nativeQueueName );
//
// !!! Print API mapping layer presently requires a preallocated buffer.
//
outBufferSize = XsNativeBufferSize( SmbGetUshort( ¶meters->BufLen )); if ( NetapipBufferAllocate( outBufferSize, &outBuffer ) != NERR_Success || outBuffer == NULL ) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQGetInfo: cannot allocate memory\n" )); } Header->Status = NERR_NoRoom; goto cleanup; }
//
// Make the local call.
//
status = DosPrintQGetInfo( NULL, nativeQueueName, SmbGetUshort( ¶meters->Level ), (LPBYTE)outBuffer, SmbGetUshort( ¶meters->BufLen ), &bytesNeeded );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(API_ERRORS) { NetpKdPrint(( "XsNetPrintQGetInfo: DosPrintQGetInfo failed: " FORMAT_API_STATUS "\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_printQ_0; StructureDesc = Desc16_printQ_0; break;
case 1:
nativeStructureDesc = Desc32_printQ_1; StructureDesc = Desc16_printQ_1; break;
case 2:
nativeStructureDesc = Desc32_printQ_2; nativeAuxStructureDesc = Desc32_print_job_1; StructureDesc = Desc16_printQ_2; AuxStructureDesc = Desc16_print_job_1; break;
case 3:
nativeStructureDesc = Desc32_printQ_3; StructureDesc = Desc16_printQ_3; break;
case 4:
nativeStructureDesc = Desc32_printQ_4; nativeAuxStructureDesc = Desc32_print_job_2; StructureDesc = Desc16_printQ_4; AuxStructureDesc = Desc16_print_job_2; break;
case 5:
nativeStructureDesc = Desc32_printQ_5; StructureDesc = Desc16_printQ_5; break;
case 52:
nativeStructureDesc = Desc32_printQ_52; StructureDesc = Desc16_printQ_52; break;
}
//
// Common code between cases 2 and 4 - form long descriptors.
//
switch ( SmbGetUshort( ¶meters->Level )) {
case 2: case 4:
//
// Find the auxiliary data count.
//
auxDataCount = RapAuxDataCount( (LPBYTE)outBuffer, nativeStructureDesc, Response, TRUE // native format
);
longDescriptor = NetpMemoryAllocate( strlen( StructureDesc ) + strlen( AuxStructureDesc ) * auxDataCount + 1 ); longNativeDescriptor = NetpMemoryAllocate( strlen( nativeStructureDesc ) + strlen( nativeAuxStructureDesc ) * auxDataCount + 1 );
if (( longDescriptor == NULL ) || ( longNativeDescriptor == NULL )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQGetInfo: failed to allocate memory" )); } Header->Status = (WORD)NERR_NoRoom; goto cleanup; }
strcpy( longDescriptor, StructureDesc ); strcpy( longNativeDescriptor, nativeStructureDesc ); for ( i = 0; i < auxDataCount; i++ ) { strcat( longDescriptor, AuxStructureDesc ); strcat( longNativeDescriptor, nativeAuxStructureDesc ); }
StructureDesc = longDescriptor; nativeStructureDesc = longNativeDescriptor;
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(( "XsDosPrintQGetInfo: RapConvertSingleEntry failed: " FORMAT_API_STATUS "\n", status )); }
Header->Status = NERR_InternalError; goto cleanup; }
//
// 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(( "XsNetPrintQGetInfo: Buffer too small.\n" )); } Header->Status = NERR_BufTooSmall;
} else if ( bytesRequired > (DWORD)SmbGetUshort( ¶meters-> BufLen )) {
IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQGetInfo: 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 ); }
bytesNeeded = (WORD)bytesRequired;
cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
//
// Set up the response parameters.
//
SmbPutUshort( ¶meters->Needed, bytesNeeded );
//
// Determine return buffer size.
//
XsSetDataCount( ¶meters->BufLen, StructureDesc, // desc (may be one we created on heap)
Header->Converter, 1, Header->Status );
(VOID) NetApiBufferFree( outBuffer ); FREE_QUEUE_NAME( nativeQueueName ); NetpMemoryFree( longDescriptor ); NetpMemoryFree( longNativeDescriptor );
return STATUS_SUCCESS;
} // XsNetPrintQGetInfo
NTSTATUS XsNetPrintQPause ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintQPause.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_Q_PAUSE parameters = Parameters; LPTSTR nativeQueueName = NULL; // Native parameters
PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintQPause: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "name " FORMAT_LPSTR "\n", Header, parameters, SmbGetUlong( ¶meters->QueueName ))); }
try { //
// Translate parameters, check for errors.
//
XsConvertTextParameter( nativeQueueName, (LPSTR)XsSmbGetPointer( ¶meters->QueueName ) );
CONVERT_QUEUE_NAME( nativeQueueName );
//
// Make the local call.
//
status = DosPrintQPause( NULL, nativeQueueName );
cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQPause: DosPrintQPause failed: " FORMAT_API_STATUS "\n", status )); } }
//
// Nothing to return.
//
Header->Status = (WORD)status;
FREE_QUEUE_NAME( nativeQueueName ); return STATUS_SUCCESS;
} // XsNetPrintQPause
NTSTATUS XsNetPrintQPurge ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to DosPrintQPurge.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_Q_PURGE parameters = Parameters; LPTSTR nativeQueueName = NULL; // Native parameters
PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
IF_DEBUG(PRINT) { NetpKdPrint(( "XsNetPrintQPurge: header at " FORMAT_LPVOID ", params at " FORMAT_LPVOID ", " "name " FORMAT_LPSTR "\n", Header, parameters, SmbGetUlong( ¶meters->QueueName ))); }
try { //
// Translate parameters, check for errors.
//
XsConvertTextParameter( nativeQueueName, (LPSTR)XsSmbGetPointer( ¶meters->QueueName ) );
CONVERT_QUEUE_NAME( nativeQueueName );
//
// Make the local call.
//
status = DosPrintQPurge( NULL, nativeQueueName );
cleanup: ; } except( EXCEPTION_EXECUTE_HANDLER ) { status = (WORD)RtlNtStatusToDosError( GetExceptionCode() ); }
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQPurge: DosPrintQPurge failed: " FORMAT_API_STATUS "\n", status )); } }
//
// Nothing to return.
//
Header->Status = (WORD)status;
FREE_QUEUE_NAME( nativeQueueName ); return STATUS_SUCCESS;
} // XsNetPrintQPurge
NTSTATUS XsNetPrintQSetInfo ( API_HANDLER_PARAMETERS )
/*++
Routine Description:
This routine handles a call to NetPrintQSetInfo.
Arguments:
API_HANDLER_PARAMETERS - information about the API call. See XsTypes.h for details.
Return Value:
NTSTATUS - STATUS_SUCCESS or reason for failure.
--*/
{ SPLERR status;
PXS_DOS_PRINT_Q_SET_INFO parameters = Parameters; LPTSTR nativeQueueName = NULL; // Native parameters
LPVOID buffer = NULL; DWORD bytesRequired;
DWORD fieldIndex; LPDESC setInfoDesc; // Conversion variables
LPDESC nativeSetInfoDesc; LPDESC nativeStructureDesc; PREPARE_CONVERT_QUEUE_NAME();
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
try { //
// Translate parameters, check for errors.
//
if ( SmbGetUshort( ¶meters->Level ) != 1 && SmbGetUshort( ¶meters->Level ) != 3 ) {
Header->Status = ERROR_INVALID_LEVEL; goto cleanup; }
XsConvertTextParameter( nativeQueueName, (LPSTR)XsSmbGetPointer( ¶meters->QueueName ) );
CONVERT_QUEUE_NAME( nativeQueueName );
//
// Determine descriptor strings based on level. Also translate the
// parmnum value to a field index.
// !!! - Right now, we don't check for parameters settable in downlevel
// that are meaningless in the NT mapping layer.
//
fieldIndex = (DWORD)SmbGetUshort( ¶meters->ParmNum );
switch ( SmbGetUshort( ¶meters->Level )) {
case 1:
StructureDesc = Desc16_printQ_1; nativeStructureDesc = Desc32_printQ_1; setInfoDesc = Desc16_printQ_1_setinfo; nativeSetInfoDesc = Desc32_printQ_1_setinfo;
if ( fieldIndex > 1 ) { // Account for pad field
fieldIndex++; }
break;
case 3:
StructureDesc = Desc16_printQ_3; nativeStructureDesc = Desc32_printQ_3; setInfoDesc = Desc16_printQ_3_setinfo; nativeSetInfoDesc = Desc32_printQ_3_setinfo; if ( fieldIndex == PRQ_DESTINATIONS_PARMNUM ) { fieldIndex = (DWORD)-1; // No corresponding field
} else if ( fieldIndex == PRQ_SEPARATOR_PARMNUM || fieldIndex == PRQ_PROCESSOR_PARMNUM ) { fieldIndex++; } break;
}
status = XsConvertSetInfoBuffer( (LPBYTE)XsSmbGetPointer( ¶meters->Buffer ), SmbGetUshort( ¶meters->BufLen ), (WORD)fieldIndex, FALSE, TRUE, StructureDesc, nativeStructureDesc, setInfoDesc, nativeSetInfoDesc, (LPBYTE *)&buffer, &bytesRequired );
if ( status != NERR_Success ) {
IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQSetInfo: Problem with conversion: " FORMAT_API_STATUS "\n", status )); } Header->Status = (WORD)status; goto cleanup;
}
//
// Do the actual local call.
//
status = DosPrintQSetInfo( NULL, nativeQueueName, SmbGetUshort( ¶meters->Level ), (LPBYTE)buffer, (WORD)bytesRequired, SmbGetUshort( ¶meters->ParmNum ) );
if ( !XsPrintApiSuccess( status )) { IF_DEBUG(ERRORS) { NetpKdPrint(( "XsNetPrintQSetInfo: DosPrintQSetInfo failed: " FORMAT_API_STATUS "\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 ); FREE_QUEUE_NAME( nativeQueueName );
return STATUS_SUCCESS;
} // XsNetPrintQSetInfo
|