You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
740 lines
23 KiB
740 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 1991-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
PrtQ.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the print queue APIs to remote machines using
|
|
the Remote Admin Protocol. In addition to the usual downlevel usage, this
|
|
protocol is also used for the NT-to-NT print APIs.
|
|
|
|
Author:
|
|
|
|
John Rogers (JohnRo) 16-May-1991
|
|
|
|
Environment:
|
|
|
|
Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
|
|
Requires ANSI C extensions: slash-slash comments, long external names.
|
|
|
|
Notes:
|
|
|
|
All of the RxPrint APIs are wide-character APIs, regardless of
|
|
whether or not UNICODE is defined. This allows the net/dosprint/dosprint.c
|
|
code to use the winspool APIs (which are currently ANSI APIs, despite their
|
|
prototypes using LPTSTR in some places).
|
|
|
|
Revision History:
|
|
|
|
16-May-1991 JohnRo
|
|
Initial version.
|
|
17-Jun-1991 JohnRo
|
|
Added RxPrintQ{Continue,Pause,Purge}. Added module header.
|
|
15-Jul-1991 JohnRo
|
|
Added RxPrintQ{Add,Del,Enum,SetInfo}.
|
|
16-Jul-1991 JohnRo
|
|
Estimate bytes needed for print APIs.
|
|
17-Jul-1991 JohnRo
|
|
Extracted RxpDebug.h from Rxp.h.
|
|
21-Nov-1991 JohnRo
|
|
Removed NT dependencies to reduce recompiles.
|
|
07-Jun-1992 JohnRo
|
|
RAID 10324: net print vs. UNICODE.
|
|
RAID 7243: Avoid 64KB requests (Winball servers only HAVE 64KB!)
|
|
Use PREFIX_ equates.
|
|
11-May-1993 JohnRo
|
|
RAID 9942: workaround Windows For Workgroups (WFW) bug in DosPrintQEnum,
|
|
when level=0 and multiple queues exist.
|
|
18-May-1993 JohnRo
|
|
RAID 10222: DosPrintQGetInfoW underestimates number of bytes needed.
|
|
|
|
--*/
|
|
|
|
|
|
#ifndef UNICODE
|
|
#error "RxPrint APIs assume RxRemoteApi uses wide characters."
|
|
#endif
|
|
|
|
|
|
// These must be included first:
|
|
|
|
#include <windows.h> // IN, LPWSTR, etc.
|
|
#include <lmcons.h> // NET_API_STATUS, etc.
|
|
|
|
// These may be included in any order:
|
|
|
|
#include <apinums.h> // API_ equates.
|
|
#include <lmerr.h> // NERR_ and ERROR_ equates.
|
|
#include <names.h> // NetpIsUncComputerNameValid(), etc.
|
|
#include <netdebug.h> // NetpAssert().
|
|
#include <netlib.h> // NetpSetOptionalArg().
|
|
#include <prefix.h> // PREFIX_ equates.
|
|
#include <remdef.h> // REM16_, REM32_, REMSmb_, field index equates.
|
|
#include <rx.h> // RxRemoteApi().
|
|
#include <rxp.h> // RxpEstimatedBytesNeeded(). MAX_TRANSACT_ equates.
|
|
#include <rxpdebug.h> // IF_DEBUG().
|
|
#include <rxprint.h> // My prototypes, some PRQ_ equates.
|
|
#include <strucinf.h> // NetpPrintQStructureInfo().
|
|
|
|
|
|
DBGSTATIC NET_API_STATUS
|
|
RxpGetPrintQInfoDescs(
|
|
IN DWORD InfoLevel,
|
|
IN BOOL AddOrSet,
|
|
OUT LPDESC * DataDesc16 OPTIONAL,
|
|
OUT LPDESC * DataDesc32 OPTIONAL,
|
|
OUT LPDESC * DataDescSmb OPTIONAL,
|
|
OUT LPDESC * AuxDesc16 OPTIONAL,
|
|
OUT LPDESC * AuxDesc32 OPTIONAL,
|
|
OUT LPDESC * AuxDescSmb OPTIONAL
|
|
)
|
|
{
|
|
switch (InfoLevel) {
|
|
case 0 :
|
|
if (AddOrSet) {
|
|
return (ERROR_INVALID_LEVEL);
|
|
}
|
|
NetpSetOptionalArg(AuxDesc16, NULL);
|
|
NetpSetOptionalArg(AuxDesc32, NULL);
|
|
NetpSetOptionalArg(AuxDescSmb, NULL);
|
|
NetpSetOptionalArg(DataDesc16, REM16_printQ_0);
|
|
NetpSetOptionalArg(DataDesc32, REM32_printQ_0);
|
|
NetpSetOptionalArg(DataDescSmb, REMSmb_printQ_0);
|
|
return (NERR_Success);
|
|
|
|
case 1 :
|
|
NetpSetOptionalArg(AuxDesc16, NULL);
|
|
NetpSetOptionalArg(AuxDesc32, NULL);
|
|
NetpSetOptionalArg(AuxDescSmb, NULL);
|
|
NetpSetOptionalArg(DataDesc16, REM16_printQ_1);
|
|
NetpSetOptionalArg(DataDesc32, REM32_printQ_1);
|
|
NetpSetOptionalArg(DataDescSmb, REMSmb_printQ_1);
|
|
return (NERR_Success);
|
|
|
|
case 2 :
|
|
if (AddOrSet) {
|
|
return (ERROR_INVALID_LEVEL);
|
|
}
|
|
NetpSetOptionalArg(AuxDesc16, REM16_print_job_1);
|
|
NetpSetOptionalArg(AuxDesc32, REM32_print_job_1);
|
|
NetpSetOptionalArg(AuxDescSmb, REMSmb_print_job_1);
|
|
NetpSetOptionalArg(DataDesc16, REM16_printQ_2);
|
|
NetpSetOptionalArg(DataDesc32, REM32_printQ_2);
|
|
NetpSetOptionalArg(DataDescSmb, REMSmb_printQ_2);
|
|
return (NERR_Success);
|
|
|
|
case 3 :
|
|
NetpSetOptionalArg(AuxDesc16, NULL);
|
|
NetpSetOptionalArg(AuxDesc32, NULL);
|
|
NetpSetOptionalArg(AuxDescSmb, NULL);
|
|
NetpSetOptionalArg(DataDesc16, REM16_printQ_3);
|
|
NetpSetOptionalArg(DataDesc32, REM32_printQ_3);
|
|
NetpSetOptionalArg(DataDescSmb, REMSmb_printQ_3);
|
|
return (NERR_Success);
|
|
|
|
case 4 :
|
|
if (AddOrSet) {
|
|
return (ERROR_INVALID_LEVEL);
|
|
}
|
|
NetpSetOptionalArg(AuxDesc16, REM16_print_job_2);
|
|
NetpSetOptionalArg(AuxDesc32, REM32_print_job_2);
|
|
NetpSetOptionalArg(AuxDescSmb, REMSmb_print_job_2);
|
|
NetpSetOptionalArg(DataDesc16, REM16_printQ_4);
|
|
NetpSetOptionalArg(DataDesc32, REM32_printQ_4);
|
|
NetpSetOptionalArg(DataDescSmb, REMSmb_printQ_4);
|
|
return (NERR_Success);
|
|
|
|
case 5 :
|
|
if (AddOrSet) {
|
|
return (ERROR_INVALID_LEVEL);
|
|
}
|
|
NetpSetOptionalArg(AuxDesc16, NULL);
|
|
NetpSetOptionalArg(AuxDesc32, NULL);
|
|
NetpSetOptionalArg(AuxDescSmb, NULL);
|
|
NetpSetOptionalArg(DataDesc16, REM16_printQ_5);
|
|
NetpSetOptionalArg(DataDesc32, REM32_printQ_5);
|
|
NetpSetOptionalArg(DataDescSmb, REMSmb_printQ_5);
|
|
return (NERR_Success);
|
|
|
|
default :
|
|
return (ERROR_INVALID_LEVEL);
|
|
}
|
|
/* NOTREACHED */
|
|
} // RxpGetPrintQInfoDescs
|
|
|
|
|
|
SPLERR SPLENTRY
|
|
RxPrintQAdd(
|
|
IN LPWSTR UncServerName,
|
|
IN DWORD Level,
|
|
IN LPBYTE Buffer,
|
|
IN DWORD BufferSize
|
|
)
|
|
{
|
|
LPDESC AuxDesc16, AuxDesc32, AuxDescSmb;
|
|
LPDESC DataDesc16, DataDesc32, DataDescSmb;
|
|
NET_API_STATUS Status;
|
|
|
|
Status = RxpGetPrintQInfoDescs(
|
|
Level,
|
|
TRUE, // this is an add or set API.
|
|
& DataDesc16,
|
|
& DataDesc32,
|
|
& DataDescSmb,
|
|
& AuxDesc16,
|
|
& AuxDesc32,
|
|
& AuxDescSmb);
|
|
if (Status != NERR_Success) {
|
|
return (Status);
|
|
}
|
|
return (RxRemoteApi(
|
|
API_WPrintQAdd, // API number
|
|
(LPTSTR) UncServerName,
|
|
REMSmb_DosPrintQAdd_P, // parm desc
|
|
DataDesc16,
|
|
DataDesc32,
|
|
DataDescSmb,
|
|
AuxDesc16,
|
|
AuxDesc32,
|
|
AuxDescSmb,
|
|
FALSE, // not a null session API
|
|
// rest of API's arguments, in 32-bit LM2.x format:
|
|
Level,
|
|
Buffer,
|
|
BufferSize));
|
|
|
|
} // RxPrintQAdd
|
|
|
|
|
|
SPLERR SPLENTRY
|
|
RxPrintQContinue(
|
|
IN LPWSTR UncServerName,
|
|
IN LPWSTR QueueName
|
|
)
|
|
{
|
|
return (RxRemoteApi(
|
|
API_WPrintQContinue, // API number
|
|
(LPTSTR) UncServerName,
|
|
REMSmb_DosPrintQContinue_P, // parm desc
|
|
NULL, // no data desc 16
|
|
NULL, // no data desc 32
|
|
NULL, // no data desc SMB
|
|
NULL, // no aux desc 16
|
|
NULL, // no aux desc 32
|
|
NULL, // no aux desc SMB
|
|
FALSE, // not a null session API
|
|
// rest of API's arguments, in 32-bit LM2.x format:
|
|
QueueName));
|
|
|
|
} // RxPrintQContinue
|
|
|
|
|
|
SPLERR SPLENTRY
|
|
RxPrintQDel(
|
|
IN LPWSTR UncServerName,
|
|
IN LPWSTR QueueName
|
|
)
|
|
{
|
|
return (RxRemoteApi(
|
|
API_WPrintQDel, // API number
|
|
(LPTSTR) UncServerName,
|
|
REMSmb_DosPrintQDel_P, // parm desc
|
|
NULL, // no data desc 16
|
|
NULL, // no data desc 32
|
|
NULL, // no data desc SMB
|
|
NULL, // no aux desc 16
|
|
NULL, // no aux desc 32
|
|
NULL, // no aux desc SMB
|
|
FALSE, // not a null session API
|
|
// rest of API's arguments, in 32-bit LM2.x format:
|
|
QueueName));
|
|
|
|
} // RxPrintQDel
|
|
|
|
|
|
SPLERR SPLENTRY
|
|
RxPrintQEnum(
|
|
IN LPWSTR UncServerName,
|
|
IN DWORD Level,
|
|
OUT LPBYTE Buffer,
|
|
IN DWORD BufferSize,
|
|
OUT LPDWORD EntriesRead,
|
|
OUT LPDWORD EntriesAvail
|
|
)
|
|
{
|
|
DWORD ActualEntries = 0;
|
|
LPDESC AuxDesc16, AuxDesc32, AuxDescSmb;
|
|
LPDESC DataDesc16, DataDesc32, DataDescSmb;
|
|
DWORD SafeEntries;
|
|
LPVOID SafeLevelBuffer = NULL;
|
|
NET_API_STATUS Status;
|
|
|
|
Status = RxpGetPrintQInfoDescs(
|
|
Level,
|
|
FALSE, // this is not an add or set API.
|
|
& DataDesc16,
|
|
& DataDesc32,
|
|
& DataDescSmb,
|
|
& AuxDesc16,
|
|
& AuxDesc32,
|
|
& AuxDescSmb);
|
|
if (Status != NERR_Success) {
|
|
return (Status);
|
|
}
|
|
|
|
//
|
|
// Assume normal call, on assumption that we won't run into WFW 3.1
|
|
//
|
|
|
|
Status = RxRemoteApi(
|
|
API_WPrintQEnum, // API number
|
|
(LPTSTR) UncServerName,
|
|
REMSmb_DosPrintQEnum_P, // parm desc
|
|
DataDesc16,
|
|
DataDesc32,
|
|
DataDescSmb,
|
|
AuxDesc16,
|
|
AuxDesc32,
|
|
AuxDescSmb,
|
|
0, // flags: not a null session API
|
|
// rest of API's arguments, in 32-bit LM2.x format:
|
|
Level,
|
|
Buffer,
|
|
BufferSize,
|
|
&ActualEntries,
|
|
EntriesAvail);
|
|
|
|
//
|
|
// Check for a nasty WFW 3.1 bug: for level 0, with multiple queues,
|
|
// one or more queue names are garbage. (I've seen garbage "zzzzWWzzl"
|
|
// come back, in particular.) If we might have gotten this,
|
|
// then retry with a safe info level. Since level 0 is just short queue
|
|
// names, and level 1 is a superset of that, we can make one from the other.
|
|
//
|
|
|
|
if ( (!RxpFatalErrorCode(Status))
|
|
&& (Level == 0)
|
|
&& (ActualEntries > 1 ) ) {
|
|
|
|
LPCTSTR OutEntry = (LPVOID) Buffer;
|
|
DWORD SafeAvail;
|
|
PPRQINFO SafeEntry;
|
|
const DWORD SafeLevel = 1;
|
|
DWORD SafeLevelEntrySize;
|
|
DWORD SafeLevelBufferSize;
|
|
|
|
RetryTheApi:
|
|
|
|
//
|
|
// Avoid pointer faults below if caller's buffer isn't large enough.
|
|
//
|
|
|
|
if ( (ActualEntries * (LM20_QNLEN+1) * sizeof(TCHAR)) > BufferSize ) {
|
|
Status = NERR_BufTooSmall;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Compute area needed for safe array, and allocate it.
|
|
//
|
|
|
|
(VOID) NetpPrintQStructureInfo(
|
|
SafeLevel,
|
|
PARMNUM_ALL,
|
|
TRUE, // Yes, we need native size
|
|
FALSE, // not add or setinfo API
|
|
sizeof(TCHAR), // size of chars wanted
|
|
NULL, // don't need DataDesc16 OPTIONAL,
|
|
NULL, // don't need DataDesc32 OPTIONAL,
|
|
NULL, // don't need DataDescSmb OPTIONAL,
|
|
NULL, // don't need AuxDesc16 OPTIONAL,
|
|
NULL, // don't need AuxDesc32 OPTIONAL,
|
|
NULL, // don't need AuxDescSmb OPTIONAL,
|
|
&SafeLevelEntrySize, // need max size
|
|
NULL, // don't need size of fixed part
|
|
NULL ); // don't need size of string area
|
|
NetpAssert( SafeLevelEntrySize > 0 );
|
|
SafeLevelBufferSize = ActualEntries * SafeLevelEntrySize;
|
|
NetpAssert( SafeLevelBufferSize > 0 );
|
|
|
|
SafeLevelBuffer = NetpMemoryAllocate( SafeLevelBufferSize );
|
|
if (SafeLevelBuffer == NULL) {
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Do recursive call, to get queues at safe info level.
|
|
//
|
|
|
|
Status = RxPrintQEnum(
|
|
UncServerName,
|
|
SafeLevel, // level we want
|
|
SafeLevelBuffer, // buffer to fill in
|
|
SafeLevelBufferSize,
|
|
&SafeEntries,
|
|
&SafeAvail );
|
|
|
|
if ( Status == ERROR_MORE_DATA) {
|
|
|
|
if (SafeLevelBuffer != NULL) {
|
|
NetpMemoryFree( SafeLevelBuffer );
|
|
}
|
|
SafeLevelBuffer = NULL;
|
|
|
|
if (SafeAvail > ActualEntries) {
|
|
// Retry if queue was added.
|
|
ActualEntries = SafeAvail;
|
|
goto RetryTheApi;
|
|
} else {
|
|
// Not enough information to know what to do differently.
|
|
NetpKdPrint(( PREFIX_NETAPI
|
|
"RxPrintQEnum: WFW workaround failed, error more data "
|
|
"but should have been enough!\n" ));
|
|
Status = NERR_InternalError;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if ( RxpFatalErrorCode( Status ) ) {
|
|
NetpKdPrint(( PREFIX_NETAPI
|
|
"RxPrintQEnum: WFW workaround failed, API status="
|
|
FORMAT_API_STATUS ".\n", Status ));
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (SafeEntries==0) {
|
|
// Deleted them all of a sudden? OK, I guess.
|
|
ActualEntries = 0;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Convert safe info level to desired info level.
|
|
//
|
|
|
|
ActualEntries = 0;
|
|
SafeEntry = (LPVOID) SafeLevelBuffer;
|
|
do {
|
|
|
|
LPCTSTR SafeQueueName;
|
|
SafeQueueName = SafeEntry->szName;
|
|
NetpAssert( SafeQueueName != NULL );
|
|
if ( (*SafeQueueName) == TCHAR_EOS) {
|
|
NetpKdPrint(( PREFIX_NETAPI
|
|
"RxPrintQEnum: WFW workaround failed, got empty "
|
|
"queue name anyway.\n" ));
|
|
Status = NERR_InternalError;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ( STRLEN( SafeQueueName ) < LM20_QNLEN ) {
|
|
|
|
if (NetpIsPrintQueueNameValid( SafeQueueName ) ) {
|
|
// Hey, it's short and valid. Copy it over.
|
|
|
|
(VOID) STRCPY(
|
|
(LPTSTR) OutEntry, // dest
|
|
(LPTSTR) SafeQueueName ); // src
|
|
|
|
OutEntry += (LM20_QNLEN+1);
|
|
++ActualEntries;
|
|
} else {
|
|
NetpKdPrint(( PREFIX_NETAPI
|
|
"RxPrintQEnum: WFW workaround failed, got bad "
|
|
"queue name anyway.\n" ));
|
|
Status = NERR_InternalError;
|
|
goto Cleanup;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
--SafeEntries;
|
|
++SafeEntry;
|
|
|
|
} while (SafeEntries > 0);
|
|
|
|
}
|
|
|
|
Cleanup:
|
|
NetpSetOptionalArg( EntriesRead, ActualEntries );
|
|
if (SafeLevelBuffer != NULL) {
|
|
NetpMemoryFree( SafeLevelBuffer );
|
|
}
|
|
return (Status);
|
|
|
|
} // RxPrintQEnum
|
|
|
|
|
|
SPLERR SPLENTRY
|
|
RxPrintQGetInfo(
|
|
IN LPWSTR UncServerName,
|
|
IN LPWSTR QueueName,
|
|
IN DWORD Level,
|
|
OUT LPBYTE Buffer,
|
|
IN DWORD BufferSize,
|
|
OUT LPDWORD BytesNeeded // estimated (probably too large).
|
|
)
|
|
{
|
|
LPDESC AuxDesc16, AuxDesc32, AuxDescSmb;
|
|
LPDESC DataDesc16, DataDesc32, DataDescSmb;
|
|
DWORD BytesNeeded16;
|
|
DWORD EdittedBufferSize;
|
|
NET_API_STATUS Status;
|
|
|
|
NetpAssert(UncServerName != NULL);
|
|
NetpAssert(*UncServerName != '\0');
|
|
|
|
Status = RxpGetPrintQInfoDescs(
|
|
Level,
|
|
FALSE, // not an add or set API.
|
|
& DataDesc16,
|
|
& DataDesc32,
|
|
& DataDescSmb,
|
|
& AuxDesc16,
|
|
& AuxDesc32,
|
|
& AuxDescSmb);
|
|
if (Status != NERR_Success) {
|
|
return (Status);
|
|
}
|
|
NetpAssert( DataDesc16 != NULL );
|
|
NetpAssert( DataDesc32 != NULL );
|
|
NetpAssert( DataDescSmb != NULL );
|
|
|
|
if (BufferSize <= MAX_TRANSACT_RET_DATA_SIZE) {
|
|
EdittedBufferSize = BufferSize;
|
|
} else {
|
|
EdittedBufferSize = MAX_TRANSACT_RET_DATA_SIZE;
|
|
}
|
|
|
|
Status = RxRemoteApi(
|
|
API_WPrintQGetInfo,
|
|
(LPTSTR) UncServerName,
|
|
REMSmb_DosPrintQGetInfo_P,
|
|
DataDesc16,
|
|
DataDesc32,
|
|
DataDescSmb,
|
|
AuxDesc16,
|
|
AuxDesc32,
|
|
AuxDescSmb,
|
|
FALSE, // not a null session API.
|
|
// rest of API's arguments in LM 2.x format:
|
|
QueueName,
|
|
Level,
|
|
Buffer,
|
|
EdittedBufferSize,
|
|
& BytesNeeded16); // downlevel buffer size needed.
|
|
|
|
// If ERROR_MORE_DATA, convert BytesNeeded to native num.
|
|
if ( (Status == ERROR_MORE_DATA) || (Status == NERR_BufTooSmall) ) {
|
|
*BytesNeeded = RxpEstimateBytesNeeded(BytesNeeded16);
|
|
} else {
|
|
*BytesNeeded = BufferSize;
|
|
}
|
|
|
|
IF_DEBUG(PRTQ) {
|
|
NetpKdPrint(( PREFIX_NETAPI "RxPrintQGetInfo: returned, status is "
|
|
FORMAT_API_STATUS "\n", Status));
|
|
}
|
|
|
|
// Return results of RxRemoteApi call.
|
|
return (Status);
|
|
|
|
} // RxPrintQGetInfo
|
|
|
|
SPLERR SPLENTRY
|
|
RxPrintQPause(
|
|
IN LPWSTR UncServerName,
|
|
IN LPWSTR QueueName
|
|
)
|
|
{
|
|
return (RxRemoteApi(
|
|
API_WPrintQPause, // API number
|
|
(LPTSTR) UncServerName,
|
|
REMSmb_DosPrintQPause_P, // parm desc
|
|
NULL, // no data desc 16
|
|
NULL, // no data desc 32
|
|
NULL, // no data desc SMB
|
|
NULL, // no aux desc 16
|
|
NULL, // no aux desc 32
|
|
NULL, // no aux desc SMB
|
|
FALSE, // not a null session API
|
|
// rest of API's arguments, in 32-bit LM2.x format:
|
|
QueueName));
|
|
|
|
} // RxPrintQPause
|
|
|
|
SPLERR SPLENTRY
|
|
RxPrintQPurge(
|
|
IN LPWSTR UncServerName,
|
|
IN LPWSTR QueueName
|
|
)
|
|
{
|
|
return (RxRemoteApi(
|
|
API_WPrintQPurge, // API number
|
|
(LPTSTR) UncServerName,
|
|
REMSmb_DosPrintQPurge_P, // parm desc
|
|
NULL, // no data desc 16
|
|
NULL, // no data desc 32
|
|
NULL, // no data desc SMB
|
|
NULL, // no aux desc 16
|
|
NULL, // no aux desc 32
|
|
NULL, // no aux desc SMB
|
|
FALSE, // not a null session API
|
|
// rest of API's arguments, in 32-bit LM2.x format:
|
|
QueueName));
|
|
|
|
} // RxPrintQPurge
|
|
|
|
|
|
SPLERR SPLENTRY
|
|
RxPrintQSetInfo(
|
|
IN LPWSTR UncServerName,
|
|
IN LPWSTR QueueName,
|
|
IN DWORD Level,
|
|
IN LPBYTE Buffer,
|
|
IN DWORD BufferSize,
|
|
IN DWORD ParmNum
|
|
)
|
|
{
|
|
LPDESC AuxDesc16, AuxDesc32, AuxDescSmb;
|
|
LPDESC DataDesc16, DataDesc32, DataDescSmb;
|
|
NET_API_STATUS Status;
|
|
|
|
NetpAssert(UncServerName != NULL);
|
|
NetpAssert(*UncServerName != '\0');
|
|
|
|
Status = RxpGetPrintQInfoDescs(
|
|
Level,
|
|
TRUE, // This is a setinfo API.
|
|
& DataDesc16,
|
|
& DataDesc32,
|
|
& DataDescSmb,
|
|
& AuxDesc16,
|
|
& AuxDesc32,
|
|
& AuxDescSmb);
|
|
if (Status != NERR_Success) {
|
|
return (Status);
|
|
}
|
|
|
|
if (ParmNum == PARMNUM_ALL) {
|
|
Status = RxRemoteApi(
|
|
API_WPrintQSetInfo, // API number
|
|
(LPTSTR) UncServerName,
|
|
REMSmb_DosPrintQSetInfo_P, // parm desc
|
|
DataDesc16,
|
|
DataDesc32,
|
|
DataDescSmb,
|
|
AuxDesc16,
|
|
AuxDesc32,
|
|
AuxDescSmb,
|
|
FALSE, // not a null session API
|
|
// rest of API's arguments, in 32-bit LM 2.x format:
|
|
QueueName,
|
|
Level,
|
|
Buffer,
|
|
BufferSize,
|
|
ParmNum);
|
|
} else {
|
|
DWORD FieldIndex;
|
|
|
|
// Compute field index from parmnum and level.
|
|
NetpAssert( (Level==1) || (Level==3) ); // Already verified.
|
|
switch (ParmNum) {
|
|
case PRQ_PRIORITY_PARMNUM :
|
|
if (Level==1) {
|
|
FieldIndex = PRQ_PRIORITY_LVL1_FIELDINDEX;
|
|
} else {
|
|
FieldIndex = PRQ_PRIORITY_LVL3_FIELDINDEX;
|
|
}
|
|
break;
|
|
case PRQ_STARTTIME_PARMNUM :
|
|
if (Level==1) {
|
|
FieldIndex = PRQ_STARTTIME_LVL1_FIELDINDEX;
|
|
} else {
|
|
FieldIndex = PRQ_STARTTIME_LVL3_FIELDINDEX;
|
|
}
|
|
break;
|
|
case PRQ_UNTILTIME_PARMNUM :
|
|
if (Level==1) {
|
|
FieldIndex = PRQ_UNTILTIME_LVL1_FIELDINDEX;
|
|
} else {
|
|
FieldIndex = PRQ_UNTILTIME_LVL3_FIELDINDEX;
|
|
}
|
|
break;
|
|
case PRQ_SEPARATOR_PARMNUM :
|
|
if (Level==1) {
|
|
FieldIndex = PRQ_SEPARATOR_LVL1_FIELDINDEX;
|
|
} else {
|
|
FieldIndex = PRQ_SEPARATOR_LVL3_FIELDINDEX;
|
|
}
|
|
break;
|
|
case PRQ_PROCESSOR_PARMNUM :
|
|
if (Level==1) {
|
|
FieldIndex = PRQ_PROCESSOR_LVL1_FIELDINDEX;
|
|
} else {
|
|
FieldIndex = PRQ_PROCESSOR_LVL3_FIELDINDEX;
|
|
}
|
|
break;
|
|
case PRQ_DESTINATIONS_PARMNUM :
|
|
if (Level==1) {
|
|
FieldIndex = PRQ_DESTINATIONS_LVL1_FIELDINDEX;
|
|
} else {
|
|
return (ERROR_INVALID_LEVEL);
|
|
}
|
|
break;
|
|
case PRQ_PARMS_PARMNUM :
|
|
if (Level==1) {
|
|
FieldIndex = PRQ_PARMS_LVL1_FIELDINDEX;
|
|
} else {
|
|
FieldIndex = PRQ_PARMS_LVL3_FIELDINDEX;
|
|
}
|
|
break;
|
|
case PRQ_COMMENT_PARMNUM :
|
|
if (Level==1) {
|
|
FieldIndex = PRQ_COMMENT_LVL1_FIELDINDEX;
|
|
} else {
|
|
FieldIndex = PRQ_COMMENT_LVL3_FIELDINDEX;
|
|
}
|
|
break;
|
|
case PRQ_PRINTERS_PARMNUM :
|
|
if (Level==1) {
|
|
return (ERROR_INVALID_LEVEL);
|
|
} else {
|
|
FieldIndex = PRQ_PRINTERS_LVL3_FIELDINDEX;
|
|
}
|
|
break;
|
|
case PRQ_DRIVERDATA_PARMNUM :
|
|
// Can't set driver data from NT
|
|
/* FALLTHROUGH */
|
|
|
|
default :
|
|
IF_DEBUG(PRTQ) {
|
|
NetpKdPrint(( PREFIX_NETAPI
|
|
"RxPrintQSetInfo: invalid (bad parmnum).\n" ));
|
|
}
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
Status = RxpSetField (
|
|
API_WPrintQSetInfo, // API number
|
|
UncServerName,
|
|
"z", // object's desc
|
|
QueueName, // object to set
|
|
REMSmb_DosPrintQSetInfo_P, // parm desc
|
|
DataDesc16,
|
|
DataDesc32,
|
|
DataDescSmb,
|
|
(LPVOID) Buffer, // native info buffer
|
|
ParmNum, // parm num to send
|
|
FieldIndex, // field index
|
|
Level);
|
|
}
|
|
|
|
return (Status);
|
|
|
|
} // RxPrintQSetInfo
|