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.
1934 lines
54 KiB
1934 lines
54 KiB
/*++
|
|
|
|
Copyright (c) 1991-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
queue.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the support routines for the queue APIs that call
|
|
into the NetWare redirector
|
|
|
|
Author:
|
|
|
|
Yi-Hsin Sung (yihsins) 24-Apr-1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <nw.h>
|
|
#include <nwxchg.h>
|
|
#include <nwapi.h>
|
|
#include <nwreg.h>
|
|
#include <queue.h>
|
|
#include <splutil.h>
|
|
//-------------------------------------------------------------------//
|
|
// //
|
|
// Local Function Prototypes //
|
|
// //
|
|
//-------------------------------------------------------------------//
|
|
|
|
DWORD
|
|
NwWriteJobInfoEntry(
|
|
IN OUT LPBYTE *FixedPortion,
|
|
IN OUT LPWSTR *EndOfVariableData,
|
|
IN DWORD Level,
|
|
IN WORD JobId,
|
|
IN LPWSTR PrinterName,
|
|
IN LPWSTR JobDescription,
|
|
IN LPWSTR UserName,
|
|
IN BYTE JobControlFlags,
|
|
IN BYTE JobPosition,
|
|
IN LPBYTE JobEntryTime,
|
|
IN JOBTIME TargetExecutionTime,
|
|
IN DWORD FileSize
|
|
);
|
|
|
|
DWORD
|
|
ConvertToSystemTime(
|
|
IN JOBTIME JobTime,
|
|
OUT LPSYSTEMTIME pSystemTime
|
|
);
|
|
|
|
//-------------------------------------------------------------------//
|
|
// //
|
|
// Global variables //
|
|
// //
|
|
//-------------------------------------------------------------------//
|
|
|
|
#define NW_RDR_SERVER_PREFIX L"\\Device\\Nwrdr\\"
|
|
|
|
#define QF_USER_HOLD 0x40
|
|
#define QF_OPERATOR_HOLD 0x80
|
|
|
|
//
|
|
// Stores the current user's print control options
|
|
//
|
|
//DWORD NwPrintOption = NW_PRINT_OPTION_DEFAULT; - Commented out for multi-user code merge. We don't use global flag anymore
|
|
// The print option is passed from the client for each user
|
|
// Default Print Control Flags: Suppress form
|
|
// feed, banner on, notify on
|
|
|
|
|
|
|
|
DWORD
|
|
NwAttachToNetwareServer(
|
|
IN LPWSTR ServerName,
|
|
OUT LPHANDLE phandleServer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine opens a handle to the given server.
|
|
|
|
Arguments:
|
|
|
|
ServerName - The server name to attach to.
|
|
phandleServer - Receives an opened handle to the preferred or
|
|
nearest server.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR or reason for failure.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
LPWSTR FullName;
|
|
UNICODE_STRING UServerName;
|
|
|
|
FullName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT,
|
|
(UINT) ( wcslen( NW_RDR_SERVER_PREFIX) +
|
|
wcslen( ServerName ) - 1) *
|
|
sizeof(WCHAR)
|
|
);
|
|
|
|
if ( FullName == NULL ) {
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
wcscpy( FullName, NW_RDR_SERVER_PREFIX );
|
|
wcscat( FullName, ServerName + 2 ); // Skip past the prefix "\\"
|
|
|
|
RtlInitUnicodeString( &UServerName, FullName );
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&UServerName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Open a handle to the preferred server.
|
|
//
|
|
ntstatus = NtOpenFile(
|
|
phandleServer,
|
|
SYNCHRONIZE | GENERIC_WRITE,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
FILE_SHARE_VALID_FLAGS,
|
|
FILE_SYNCHRONOUS_IO_NONALERT
|
|
);
|
|
|
|
if ( NT_SUCCESS(ntstatus)) {
|
|
ntstatus = IoStatusBlock.Status;
|
|
}
|
|
|
|
if (! NT_SUCCESS(ntstatus)) {
|
|
*phandleServer = NULL;
|
|
}
|
|
|
|
LocalFree( FullName );
|
|
return RtlNtStatusToDosError(ntstatus);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwGetNextQueueEntry(
|
|
IN HANDLE PreferredServer,
|
|
IN OUT LPDWORD LastObjectId,
|
|
OUT LPSTR QueueName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function uses an opened handle to the preferred server to
|
|
scan it bindery for all print queue objects.
|
|
|
|
Arguments:
|
|
|
|
PreferredServer - Supplies the handle to the preferred server on
|
|
which to scan the bindery.
|
|
|
|
LastObjectId - On input, supplies the object ID to the last print
|
|
queue object returned, which is the resume handle to get the
|
|
next print queue object. On output, receives the object ID
|
|
of the print queue object returned.
|
|
|
|
QueueName - Receives the name of the returned print queue object.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully gotten a print name.
|
|
|
|
WN_NO_MORE_ENTRIES - No other print queue object past the one
|
|
specified by LastObjectId.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
WORD ObjectType;
|
|
|
|
#if DBG
|
|
IF_DEBUG(ENUM) {
|
|
KdPrint(("NWWORKSTATION: NwGetNextQueueEntry LastObjectId %lu\n",
|
|
*LastObjectId));
|
|
}
|
|
#endif
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
PreferredServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
58, // Max request packet size
|
|
59, // Max response packet size
|
|
"bdwp|dwc", // Format string
|
|
0x37, // Scan bindery object
|
|
*LastObjectId, // Previous ID
|
|
0x3, // Print Queue object
|
|
"*", // Wildcard to match all
|
|
LastObjectId, // Current ID
|
|
&ObjectType, // Ignore
|
|
QueueName // Currently returned print queue
|
|
);
|
|
|
|
//
|
|
// Unmap Japanese special chars
|
|
//
|
|
UnmapSpecialJapaneseChars(QueueName,(WORD)lstrlenA(QueueName));
|
|
|
|
#if DBG
|
|
if ( NT_SUCCESS(ntstatus)) {
|
|
IF_DEBUG(ENUM) {
|
|
KdPrint(("NWWORKSTATION: NwGetNextQueueEntry NewObjectId %08lx, QueueName %s\n", *LastObjectId, QueueName));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return NwMapBinderyCompletionCode(ntstatus);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwGetQueueId(
|
|
IN HANDLE handleServer,
|
|
IN LPWSTR QueueName,
|
|
OUT LPDWORD QueueId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function opens a handle to the server and scan its bindery
|
|
for the given queue object id.
|
|
|
|
Arguments:
|
|
handleServer - Supplies the handle of the server on which to
|
|
scan the bindery.
|
|
|
|
QueueName - Supplies the name of the print queue.
|
|
|
|
QueueId - On output, supplies the object ID of the given queue.
|
|
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully gotten a file server name.
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS ntstatus;
|
|
|
|
UNICODE_STRING UQueueName;
|
|
OEM_STRING OemQueueName;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwGetQueueId %ws\n",
|
|
QueueName ));
|
|
}
|
|
#endif
|
|
|
|
RtlInitUnicodeString( &UQueueName, QueueName);
|
|
ntstatus = RtlUnicodeStringToOemString( &OemQueueName, &UQueueName, TRUE);
|
|
|
|
//
|
|
// Map Japanese special characters
|
|
//
|
|
MapSpecialJapaneseChars(OemQueueName.Buffer,OemQueueName.Length);
|
|
|
|
if ( NT_SUCCESS(ntstatus))
|
|
{
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
58, // Max request packet size
|
|
59, // Max response packet size
|
|
"bdwp|d", // Format string
|
|
0x37, // Scan bindery object
|
|
0xFFFFFFFF, // Previous ID
|
|
0x3, // Print Queue object
|
|
OemQueueName.Buffer, // Queue Name
|
|
QueueId // Queue ID
|
|
);
|
|
}
|
|
|
|
#if DBG
|
|
if ( NT_SUCCESS(ntstatus)) {
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwGetQueueId QueueId %08lx\n",
|
|
*QueueId ));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
RtlFreeOemString( &OemQueueName );
|
|
return NwMapBinderyCompletionCode(ntstatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwCreateQueueJobAndFile(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
IN LPWSTR DocumentName,
|
|
IN LPWSTR UserName,
|
|
IN DWORD PrintOption, //Multi-user change
|
|
IN LPWSTR QueueName,
|
|
OUT LPWORD JobId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function uses an opened handle to a server to
|
|
enter a new job into the queue with the given QueueId.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
|
|
QueueId - Supplies the id of the queue in which to add the job.
|
|
DocumentName - Supplies the name of the document to be printed
|
|
UserName - Supplies the banner name to be printed
|
|
QueueName - Supplies the header name to be printed
|
|
JobId - Receives the job id of the newly added job.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully added the job to the queue.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
|
|
UNICODE_STRING UDocumentName;
|
|
OEM_STRING OemDocumentName;
|
|
UNICODE_STRING UUserName;
|
|
OEM_STRING OemUserName;
|
|
UNICODE_STRING UQueueName;
|
|
OEM_STRING OemQueueName;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwCreateQueueJobAndFile QueueId %08lx\n",
|
|
QueueId ));
|
|
}
|
|
#endif
|
|
|
|
if ( UserName )
|
|
{
|
|
RtlInitUnicodeString( &UUserName, UserName);
|
|
ntstatus = RtlUnicodeStringToOemString( &OemUserName,
|
|
&UUserName,
|
|
TRUE );
|
|
}
|
|
|
|
if ( NT_SUCCESS(ntstatus) && DocumentName )
|
|
{
|
|
RtlInitUnicodeString( &UDocumentName, DocumentName);
|
|
ntstatus = RtlUnicodeStringToOemString( &OemDocumentName,
|
|
&UDocumentName,
|
|
TRUE );
|
|
}
|
|
|
|
if ( NT_SUCCESS(ntstatus) && QueueName )
|
|
{
|
|
RtlInitUnicodeString( &UQueueName, QueueName);
|
|
ntstatus = RtlUnicodeStringToOemString( &OemQueueName,
|
|
&UQueueName,
|
|
TRUE );
|
|
}
|
|
|
|
if ( NT_SUCCESS( ntstatus)) {
|
|
|
|
LPSTR pszDocument, pszUser, pszQueue;
|
|
|
|
pszDocument = DocumentName? OemDocumentName.Buffer : "";
|
|
pszUser = UserName? OemUserName.Buffer : "";
|
|
pszQueue = QueueName? OemQueueName.Buffer : "";
|
|
|
|
//Multi-user uses passed print flag
|
|
//
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
263, // Max request packet size
|
|
56, // Max response packet size
|
|
"bd_ddw_b_Cbbwwww_C-C-_|_w", // Format string
|
|
0x68, // Create Queue Job and File object
|
|
QueueId, // Queue ID
|
|
6, // Skip bytes
|
|
0xffffffff, // Target Server ID number
|
|
0xffffffff, 0xffff, // Target Execution time
|
|
11, // Skip bytes
|
|
0x00, // Job Control Flags
|
|
26, // Skip bytes
|
|
pszDocument, // TextJobDescription
|
|
50, // Skip bytes
|
|
0, // Version number (clientarea)
|
|
8, // Tab Size
|
|
1, // Number of copies
|
|
PrintOption, // Print Control Flags
|
|
0x3C, // Maximum lines
|
|
0x84, // Maximum characters
|
|
22, // Skip bytes
|
|
pszUser, // Banner Name
|
|
12, // Max Length of pszUser
|
|
pszQueue, // Header Name
|
|
12, // Max Length of pszQueue
|
|
14 + 80, // Skip remainder of client area
|
|
22, // Skip bytes
|
|
JobId // Job ID
|
|
);
|
|
|
|
|
|
}
|
|
|
|
#if DBG
|
|
if ( NT_SUCCESS( ntstatus)) {
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwCreateQueueJobAndFile JobId %d\n",
|
|
*JobId ));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if ( DocumentName )
|
|
RtlFreeOemString( &OemDocumentName );
|
|
if ( UserName )
|
|
RtlFreeOemString( &OemUserName );
|
|
if ( QueueName )
|
|
RtlFreeOemString( &OemQueueName );
|
|
return NwMapStatus(ntstatus);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwCloseFileAndStartQueueJob(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
IN WORD JobId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function uses an opened handle to a server to
|
|
close a job file and mark the job file ready for service.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
|
|
QueueId - Supplies the id of the queue in which to add the job.
|
|
JobId - Supplies the job id.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully added the job to the queue.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwCloseFileAndStartQueueJob QueueId %08lx JobId %d\n", QueueId, JobId ));
|
|
}
|
|
#endif
|
|
|
|
// Two versions of CloseFileAndStartQueueJobNCP
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
9, // Max request packet size
|
|
2, // Max response packet size
|
|
"bdw|", // Format string
|
|
0x69, // Close File And Start Queue Job
|
|
QueueId, // Queue ID
|
|
JobId ); // Job ID
|
|
|
|
return NwMapStatus(ntstatus);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwRemoveJobFromQueue(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
IN WORD JobId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a job from a queue and closes the associate file.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which to remove the job.
|
|
|
|
QueueId - Supplies the id of the queue in which to remove the job.
|
|
JobId - Supplies the job id to be removed.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully removed the job from the queue.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwRemoveJobFromQueue QueueId %08lx JobId %d\n",
|
|
QueueId, JobId ));
|
|
}
|
|
#endif
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
9, // Max request packet size
|
|
2, // Max response packet size
|
|
"bdw|", // Format string
|
|
0x6A, // Remove Job From Queue
|
|
QueueId, // Queue ID
|
|
JobId ); // Job ID
|
|
|
|
return NwMapStatus(ntstatus);
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwRemoveAllJobsFromQueue(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes all jobs from a queue.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which to remove all jobs.
|
|
|
|
QueueId - Supplies the id of the queue in which to remove all jobs.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully removed all jobs from the queue.
|
|
|
|
--*/
|
|
{
|
|
DWORD err;
|
|
WORD JobCount = 0;
|
|
WORD pwJobList[250];
|
|
WORD i;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE)
|
|
{
|
|
KdPrint(("NWWORKSTATION: NwRemoveAllJobsFromQueue QueueId %08lx\n",
|
|
QueueId ));
|
|
}
|
|
#endif
|
|
|
|
pwJobList[0] = 0;
|
|
err = NwGetQueueJobList( handleServer,
|
|
QueueId,
|
|
&JobCount,
|
|
pwJobList );
|
|
|
|
for ( i = 0; !err && i < JobCount; i++ )
|
|
{
|
|
err = NwRemoveJobFromQueue( handleServer,
|
|
QueueId,
|
|
pwJobList[i] );
|
|
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwReadQueueCurrentStatus(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
OUT LPBYTE QueueStatus,
|
|
OUT LPBYTE NumberOfJobs
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function uses an opened handle to a server to
|
|
query the status of the queue with the given QueueId.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
QueueId - Supplies the id of the queue
|
|
QueueStatus - Receives the status of the queue
|
|
NumberOfJobs - Receives the number of jobs in the queue.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully retrieved the status of the queue.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwReadQueueCurrentStatus QueueId %08lx\n",
|
|
QueueId ));
|
|
}
|
|
#endif
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
7, // Max request packet size
|
|
135, // Max response packet size
|
|
"bd|==bb", // Format string
|
|
0x66, // ReadQueueCurrentStatus
|
|
QueueId, // Queue ID
|
|
QueueStatus, // Queue status
|
|
NumberOfJobs // Number of jobs in the queue
|
|
);
|
|
|
|
#if DBG
|
|
if ( NT_SUCCESS( ntstatus)) {
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwReadQueueCurrentStatus QueueStatus %d Number of Jobs %d\n", *QueueStatus, *NumberOfJobs ));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return NwMapStatus(ntstatus);
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwSetQueueCurrentStatus(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
IN BYTE QueueStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function uses an opened handle to a server to
|
|
set the status (pause/ready...) of the queue with the given QueueId.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
QueueId - Supplies the id of the queue
|
|
QueueStatus - Supplies the status of the queue
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully set the status of the queue.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwSetQueueCurrentStatus QueueId %08lx\n",
|
|
QueueId ));
|
|
}
|
|
#endif
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
8, // Max request packet size
|
|
2, // Max response packet size
|
|
"bdb|", // Format string
|
|
0x67, // ReadQueueCurrentStatus
|
|
QueueId, // Queue ID
|
|
QueueStatus // Queue status
|
|
);
|
|
|
|
return NwMapStatus(ntstatus);
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwGetQueueJobList(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
OUT LPWORD NumberOfJobs,
|
|
OUT LPWORD JobIdList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function uses an opened handle to a server to
|
|
get the job list of the queue with the given QueueId.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
QueueId - Supplies the id of the queue
|
|
NumberOfJobs - Receives the number of jobs in the queue.
|
|
JobIdList - Receives the array of job ids in the queue
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully added the job to the queue.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
#if DBG
|
|
WORD i;
|
|
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwGetQueueJobList QueueId %08lx\n",
|
|
QueueId ));
|
|
}
|
|
#endif
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
7, // Max request packet size
|
|
506, // Max response packet size
|
|
"bd|W", // Format string
|
|
0x6B, // Get Queue Job List
|
|
QueueId, // Queue ID
|
|
NumberOfJobs, // Number of jobs in the queue
|
|
JobIdList // Array of job ids
|
|
);
|
|
|
|
#if DBG
|
|
if ( NT_SUCCESS(ntstatus)) {
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwGetQueueJobList Number of Jobs %d\nJob List = ", *NumberOfJobs ));
|
|
for ( i = 0; i < *NumberOfJobs; i++ )
|
|
KdPrint(("%d ", JobIdList[i] ));
|
|
KdPrint(("\n"));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return NwMapStatus(ntstatus);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwReadQueueJobEntry(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
IN WORD JobId,
|
|
OUT JOBTIME TargetExecutionTime,
|
|
OUT JOBTIME JobEntryTime,
|
|
OUT LPBYTE JobPosition,
|
|
OUT LPBYTE JobControlFlags,
|
|
OUT LPSTR TextJobDescription,
|
|
OUT LPSTR UserName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function uses an opened handle to a server to
|
|
get the information about the job with the given JobId
|
|
in the given QueueId.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
QueueId - Supplies the id of the queue
|
|
JobId - Supplies the job we are interested in
|
|
|
|
TargetExecutionTime -
|
|
JobEntryTime -
|
|
JobPosition -
|
|
JobControlsFlags -
|
|
TextJobDescription -
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully added the job to the queue.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwReadQueueJobEntry QueueId %08lx JobId %d\n",
|
|
QueueId, JobId ));
|
|
}
|
|
#endif
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
9, // Max request packet size
|
|
258, // Max response packet size
|
|
"bdw|_rr==bb_C_c", // Format string
|
|
0x6C, // Read Queue Job Entry
|
|
QueueId, // Queue ID
|
|
JobId, // Job ID
|
|
10, // Skip bytes
|
|
TargetExecutionTime, // Array storing execution time
|
|
6, // Size of TargetExecutionTime
|
|
JobEntryTime, // Array storing job entry time
|
|
6, // Size of JobEntryTime
|
|
JobPosition, // Job Position
|
|
JobControlFlags, // Job Control Flag
|
|
26, // Skip bytes
|
|
TextJobDescription, // Array storing the description
|
|
50, // Maximum size in the above array
|
|
32, // Skip bytes
|
|
UserName // Banner Name
|
|
);
|
|
|
|
#if DBG
|
|
if ( NT_SUCCESS( ntstatus)) {
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwReadQueueJobEntry JobPosition %d Status %d Description %s\n", *JobPosition, *JobControlFlags, TextJobDescription ));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return NwMapStatus(ntstatus);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwGetQueueJobsFileSize(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
IN WORD JobId,
|
|
OUT LPDWORD FileSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function uses an opened handle to a server to
|
|
get the file size of the given job.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
QueueId - Supplies the id of the queue
|
|
JobId - Identifying the job we are interested in
|
|
FileSize - Receives the file size of the given job
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully retrieved the file size.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwGetQueueJobsFileSize QueueId %08lx JobId %d\n", QueueId, JobId ));
|
|
}
|
|
#endif
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
9, // Max request packet size
|
|
12, // Max response packet size
|
|
"bdw|===d", // Format string
|
|
0x78, // Get Queue Job's File Size
|
|
QueueId, // Queue ID
|
|
JobId, // Job ID
|
|
FileSize // File Size
|
|
);
|
|
|
|
#if DBG
|
|
if ( NT_SUCCESS( ntstatus)) {
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwGetQueueJobsFileSize File Size %d\n",
|
|
*FileSize ));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return NwMapStatus(ntstatus);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwChangeQueueJobPosition(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
IN WORD JobId,
|
|
IN BYTE NewPosition
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function uses an opened handle to a server to
|
|
get the change a job's position in a queue.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
QueueId - Supplies the id of the queue
|
|
JobId - Identifying the job we are interested in
|
|
NewPosition - Supplies the new position of the job
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully retrieved the file size.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwChangeQueueJobPosition QueueId %08lx JobId %d NewPosition %d\n", QueueId, JobId, NewPosition ));
|
|
}
|
|
#endif
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
10, // Max request packet size
|
|
2, // Max response packet size
|
|
"bdwb|", // Format string
|
|
0x6E, // Change Queue Job Position
|
|
QueueId, // Queue ID
|
|
JobId, // Job ID
|
|
NewPosition // New position of the job
|
|
);
|
|
|
|
return NwMapStatus(ntstatus);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwChangeQueueJobEntry(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
IN WORD JobId,
|
|
IN DWORD dwCommand,
|
|
IN PNW_JOB_INFO pNwJobInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function uses an opened handle to a server to
|
|
get the change a job's position in a queue.
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
QueueId - Supplies the id of the queue
|
|
JobId - Identifying the job we are interested in
|
|
JobControlFlags - Supplies the new job control flags
|
|
pNwJobInfo -
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully retrieved the file size.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD TargetServerId;
|
|
JOBTIME TargetExecutionTime;
|
|
WORD JobType;
|
|
BYTE JobControlFlags;
|
|
BYTE TextJobDescription[50];
|
|
BYTE ClientRecordArea[152];
|
|
|
|
UNICODE_STRING UDocumentName;
|
|
UNICODE_STRING UUserName;
|
|
OEM_STRING OemDocumentName, *pOemDocumentName = NULL;
|
|
OEM_STRING OemUserName, *pOemUserName = NULL;
|
|
LPSTR pszDocument, pszUser;
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE) {
|
|
KdPrint(("NWWORKSTATION: NwChangeQueueJobEntry QueueId %08lx JobId %d dwCommand %d\n", QueueId, JobId, dwCommand ));
|
|
}
|
|
#endif
|
|
|
|
TextJobDescription[0] = 0;
|
|
if ( pNwJobInfo )
|
|
{
|
|
if ( pNwJobInfo->pUserName )
|
|
{
|
|
RtlInitUnicodeString( &UUserName, pNwJobInfo->pUserName);
|
|
ntstatus = RtlUnicodeStringToOemString( &OemUserName,
|
|
&UUserName,
|
|
TRUE );
|
|
if ( NT_SUCCESS(ntstatus) )
|
|
pOemUserName = &OemUserName ; // record to free later
|
|
}
|
|
|
|
if ( NT_SUCCESS(ntstatus) && pNwJobInfo->pDocument )
|
|
{
|
|
RtlInitUnicodeString( &UDocumentName, pNwJobInfo->pDocument);
|
|
ntstatus = RtlUnicodeStringToOemString( &OemDocumentName,
|
|
&UDocumentName,
|
|
TRUE );
|
|
if ( NT_SUCCESS(ntstatus) )
|
|
pOemDocumentName = &OemDocumentName ; // record to free later
|
|
}
|
|
|
|
if ( NT_SUCCESS( ntstatus))
|
|
{
|
|
pszDocument = pNwJobInfo->pDocument? OemDocumentName.Buffer : "";
|
|
pszUser = pNwJobInfo->pUserName? OemUserName.Buffer: "";
|
|
}
|
|
}
|
|
|
|
if ( NT_SUCCESS( ntstatus))
|
|
{
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
9, // Max request packet size
|
|
258, // Max response packet size
|
|
"bdw|_dr_w-b_rr", // Format string
|
|
0x6C, // Read Queue Job Entry
|
|
QueueId, // Queue ID
|
|
JobId, // Job ID
|
|
6, // Skip bytes
|
|
&TargetServerId, // Target Server ID Number
|
|
TargetExecutionTime, // Target Execution Time
|
|
6, // sizeof TargetExecutionTime
|
|
8, // Skip bytes
|
|
&JobType, // Job Type
|
|
&JobControlFlags, // Job Control flags
|
|
26, // Skip bytes
|
|
TextJobDescription, // TextJobDescription
|
|
50, // sizeof TextJobDescription
|
|
ClientRecordArea, // Client record area
|
|
152 // sizeof ClientRecordArea
|
|
);
|
|
}
|
|
|
|
if ( NT_SUCCESS( ntstatus))
|
|
{
|
|
switch ( dwCommand )
|
|
{
|
|
case JOB_CONTROL_PAUSE:
|
|
JobControlFlags |= QF_USER_HOLD;
|
|
break;
|
|
|
|
case JOB_CONTROL_RESUME:
|
|
JobControlFlags &= ~( QF_USER_HOLD | QF_OPERATOR_HOLD );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
handleServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
263, // Max request packet size
|
|
2, // Max response packet size
|
|
"bd_dr_ww-b_CrCr|", // Format string
|
|
0x6D, // Change Queue Job Entry
|
|
QueueId, // Queue ID
|
|
6, // Skip bytes
|
|
TargetServerId, // Target Server ID Number
|
|
TargetExecutionTime, // Target Execution Time
|
|
6, // sizeof TargetExecutionTime
|
|
6, // Skip bytes
|
|
JobId, // Job ID
|
|
JobType, // Job Type
|
|
JobControlFlags, // Job Control Flags
|
|
26, // Skip bytes
|
|
pNwJobInfo? pszDocument
|
|
: TextJobDescription, // Description
|
|
50, // Skip bytes of Description
|
|
ClientRecordArea, // Client Record Area
|
|
32, // First 32 bytes of the above
|
|
pNwJobInfo? pszUser
|
|
: (LPSTR) &ClientRecordArea[32], // Banner Name
|
|
13, // sizeof BannerName
|
|
&ClientRecordArea[45], // Rest of the Client Area
|
|
107 // sizeof the above
|
|
);
|
|
}
|
|
|
|
if ( pOemDocumentName )
|
|
RtlFreeOemString( pOemDocumentName );
|
|
|
|
if ( pOemUserName )
|
|
RtlFreeOemString( pOemUserName );
|
|
|
|
return NwMapStatus(ntstatus);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwGetQueueJobs(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
IN LPWSTR PrinterName,
|
|
IN DWORD FirstJobRequested,
|
|
IN DWORD EntriesRequested,
|
|
IN DWORD Level,
|
|
OUT LPBYTE Buffer,
|
|
IN DWORD cbBuf,
|
|
OUT LPDWORD BytesNeeded,
|
|
OUT LPDWORD Entries
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
QueueId - Supplies the id of the queue
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD err = NO_ERROR;
|
|
|
|
DWORD i;
|
|
WORD JobCount = 0;
|
|
WORD pwJobList[250];
|
|
|
|
DWORD EntrySize = 0;
|
|
LPBYTE FixedPortion = Buffer;
|
|
LPWSTR EndOfVariableData = ( LPWSTR ) ( Buffer + cbBuf );
|
|
|
|
#if DBG
|
|
IF_DEBUG(QUEUE)
|
|
KdPrint(("NWWORKSTATION: NwGetQueueJobs QueueId %08lx\n", QueueId));
|
|
#endif
|
|
|
|
*BytesNeeded = 0;
|
|
*Entries = 0;
|
|
|
|
err = NwGetQueueJobList( handleServer,
|
|
QueueId,
|
|
&JobCount,
|
|
pwJobList );
|
|
|
|
|
|
if ( err )
|
|
{
|
|
KdPrint(("NWWORKSTATION: NwGetQueueJobList Error %d\n", err ));
|
|
return err;
|
|
}
|
|
|
|
for ( i = 0; (i < EntriesRequested) && ( i+FirstJobRequested+1 <= JobCount);
|
|
i++ )
|
|
{
|
|
err = NwGetQueueJobInfo( handleServer,
|
|
QueueId,
|
|
pwJobList[i+FirstJobRequested],
|
|
PrinterName,
|
|
Level,
|
|
&FixedPortion,
|
|
&EndOfVariableData,
|
|
&EntrySize );
|
|
|
|
if ( err != NO_ERROR && err != ERROR_INSUFFICIENT_BUFFER )
|
|
break;
|
|
|
|
*BytesNeeded += EntrySize;
|
|
}
|
|
|
|
|
|
if ( err == ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
*Entries = 0;
|
|
}
|
|
else if ( err == NO_ERROR )
|
|
{
|
|
*Entries = i;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwGetQueueJobInfo(
|
|
IN HANDLE handleServer,
|
|
IN DWORD QueueId,
|
|
IN WORD JobId,
|
|
IN LPWSTR PrinterName,
|
|
IN DWORD Level,
|
|
IN OUT LPBYTE *FixedPortion,
|
|
IN OUT LPWSTR *EndOfVariableData,
|
|
OUT LPDWORD EntrySize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
handleServer - Supplies the handle to the server on
|
|
which add the job.
|
|
QueueId - Supplies the id of the queue
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD err;
|
|
LPWSTR UTextJobDescription = NULL;
|
|
LPWSTR UUserName = NULL;
|
|
|
|
JOBTIME TargetExecutionTime;
|
|
JOBTIME JobEntryTime;
|
|
BYTE JobPosition;
|
|
BYTE JobControlFlags;
|
|
CHAR UserName[14];
|
|
CHAR TextJobDescription[50];
|
|
DWORD FileSize = 0;
|
|
|
|
TextJobDescription[0] = 0;
|
|
|
|
err = NwReadQueueJobEntry( handleServer,
|
|
QueueId,
|
|
JobId,
|
|
TargetExecutionTime,
|
|
JobEntryTime,
|
|
&JobPosition,
|
|
&JobControlFlags,
|
|
TextJobDescription,
|
|
UserName );
|
|
|
|
if ( err )
|
|
{
|
|
KdPrint(("NWWORKSTATION: NwReadQueueJobEntry JobId %d Error %d\n",
|
|
JobId, err ));
|
|
return err;
|
|
}
|
|
|
|
if (!NwConvertToUnicode( &UTextJobDescription, TextJobDescription ))
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
if (!NwConvertToUnicode( &UUserName, UserName ))
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY ;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
*EntrySize = ( Level == 1? sizeof( JOB_INFO_1W ) : sizeof( JOB_INFO_2W ))
|
|
+ ( wcslen( UTextJobDescription ) + wcslen( UUserName) +
|
|
wcslen( PrinterName ) + 3 ) * sizeof( WCHAR );
|
|
//
|
|
// See if the buffer is large enough to fit the entry
|
|
//
|
|
if ( (LPWSTR)( *FixedPortion + *EntrySize ) > *EndOfVariableData )
|
|
{
|
|
err = ERROR_INSUFFICIENT_BUFFER;
|
|
goto ErrorExit ;
|
|
}
|
|
|
|
if ( Level == 2 )
|
|
{
|
|
err = NwGetQueueJobsFileSize( handleServer,
|
|
QueueId,
|
|
JobId,
|
|
&FileSize );
|
|
|
|
if ( err )
|
|
{
|
|
KdPrint(("NWWORKSTATION: NwGetQueueJobsFileSize JobId %d Error %d\n", JobId, err ));
|
|
goto ErrorExit ;
|
|
}
|
|
}
|
|
|
|
err = NwWriteJobInfoEntry( FixedPortion,
|
|
EndOfVariableData,
|
|
Level,
|
|
JobId,
|
|
PrinterName,
|
|
UTextJobDescription,
|
|
UUserName,
|
|
JobControlFlags,
|
|
JobPosition,
|
|
JobEntryTime,
|
|
TargetExecutionTime,
|
|
FileSize );
|
|
|
|
ErrorExit:
|
|
|
|
if (UTextJobDescription)
|
|
(void) LocalFree((HLOCAL) UTextJobDescription) ;
|
|
if (UUserName)
|
|
(void) LocalFree((HLOCAL) UUserName) ;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
NwWriteJobInfoEntry(
|
|
IN OUT LPBYTE *FixedPortion,
|
|
IN OUT LPWSTR *EndOfVariableData,
|
|
IN DWORD Level,
|
|
IN WORD JobId,
|
|
IN LPWSTR PrinterName,
|
|
IN LPWSTR JobDescription,
|
|
IN LPWSTR UserName,
|
|
IN BYTE JobControlFlags,
|
|
IN BYTE JobPosition,
|
|
IN JOBTIME JobEntryTime,
|
|
IN JOBTIME TargetExecutionTime,
|
|
IN DWORD FileSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function packages a JOB_INFO_1 or JOB_INFO_2 entry into the
|
|
user output buffer.
|
|
|
|
Arguments:
|
|
|
|
FixedPortion - Supplies a pointer to the output buffer where the next
|
|
entry of the fixed portion of the use information will be written.
|
|
This pointer is updated to point to the next fixed portion entry
|
|
after a PRINT_INFO_1 entry is written.
|
|
|
|
EndOfVariableData - Supplies a pointer just off the last available byte
|
|
in the output buffer. This is because the variable portion of the
|
|
user information is written into the output buffer starting from
|
|
the end.
|
|
|
|
This pointer is updated after any variable length information is
|
|
written to the output buffer.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - Successfully wrote entry into user buffer.
|
|
|
|
ERROR_INSUFFICIENT_BUFFER - Buffer was too small to fit entry.
|
|
|
|
--*/
|
|
{
|
|
DWORD err = NO_ERROR;
|
|
BOOL FitInBuffer = TRUE;
|
|
DWORD JobStatus = 0;
|
|
|
|
JOB_INFO_1W *pJobInfo1 = (JOB_INFO_1W *) *FixedPortion;
|
|
JOB_INFO_2W *pJobInfo2 = (JOB_INFO_2W *) *FixedPortion;
|
|
|
|
|
|
if ( ( JobControlFlags & QF_USER_HOLD )
|
|
|| ( JobControlFlags & QF_OPERATOR_HOLD )
|
|
)
|
|
{
|
|
JobStatus = JOB_STATUS_PAUSED;
|
|
}
|
|
|
|
//
|
|
// See if buffer is large enough to fit the entry.
|
|
//
|
|
|
|
if ( Level == 1 )
|
|
{
|
|
pJobInfo1->JobId = JobId;
|
|
pJobInfo1->Position = JobPosition;
|
|
pJobInfo1->Status = JobStatus;
|
|
if ( err = ConvertToSystemTime( JobEntryTime, &pJobInfo1->Submitted ))
|
|
return err;
|
|
|
|
pJobInfo1->pMachineName = NULL;
|
|
pJobInfo1->pDatatype = NULL;
|
|
pJobInfo1->pStatus = NULL;
|
|
pJobInfo1->Priority = 0;
|
|
pJobInfo1->TotalPages = 0;
|
|
pJobInfo1->PagesPrinted = 0;
|
|
|
|
//
|
|
// Update fixed entry pointer to next entry.
|
|
//
|
|
(*FixedPortion) += sizeof(JOB_INFO_1W);
|
|
|
|
//
|
|
// PrinterName
|
|
//
|
|
FitInBuffer = NwlibCopyStringToBuffer(
|
|
PrinterName,
|
|
wcslen(PrinterName),
|
|
(LPCWSTR) *FixedPortion,
|
|
EndOfVariableData,
|
|
&pJobInfo1->pPrinterName
|
|
);
|
|
|
|
ASSERT(FitInBuffer);
|
|
|
|
//
|
|
// UserName
|
|
//
|
|
FitInBuffer = NwlibCopyStringToBuffer(
|
|
UserName,
|
|
wcslen(UserName),
|
|
(LPCWSTR) *FixedPortion,
|
|
EndOfVariableData,
|
|
&pJobInfo1->pUserName
|
|
);
|
|
|
|
ASSERT(FitInBuffer);
|
|
|
|
//
|
|
// Description
|
|
//
|
|
FitInBuffer = NwlibCopyStringToBuffer(
|
|
JobDescription,
|
|
wcslen(JobDescription),
|
|
(LPCWSTR) *FixedPortion,
|
|
EndOfVariableData,
|
|
&pJobInfo1->pDocument
|
|
);
|
|
|
|
ASSERT(FitInBuffer);
|
|
}
|
|
else // Level == 2
|
|
{
|
|
pJobInfo2->JobId = JobId;
|
|
pJobInfo2->Position = JobPosition;
|
|
pJobInfo2->Status = JobStatus;
|
|
if ( err = ConvertToSystemTime( JobEntryTime, &pJobInfo2->Submitted ))
|
|
return err;
|
|
|
|
pJobInfo2->StartTime = 0;
|
|
pJobInfo2->Size = FileSize;
|
|
|
|
pJobInfo2->pMachineName = NULL;
|
|
pJobInfo2->pNotifyName = NULL;
|
|
pJobInfo2->pDatatype = NULL;
|
|
pJobInfo2->pPrintProcessor = NULL;
|
|
pJobInfo2->pParameters = NULL;
|
|
pJobInfo2->pDriverName = NULL;
|
|
pJobInfo2->pDevMode = NULL;
|
|
pJobInfo2->pStatus = NULL;
|
|
pJobInfo2->pSecurityDescriptor = NULL;
|
|
pJobInfo2->Priority = 0;
|
|
pJobInfo2->TotalPages = 0;
|
|
pJobInfo2->UntilTime = 0;
|
|
pJobInfo2->Time = 0;
|
|
pJobInfo2->PagesPrinted = 0;
|
|
|
|
//
|
|
// Update fixed entry pointer to next entry.
|
|
//
|
|
(*FixedPortion) += sizeof(JOB_INFO_2W);
|
|
|
|
//
|
|
// PrinterName
|
|
//
|
|
FitInBuffer = NwlibCopyStringToBuffer(
|
|
PrinterName,
|
|
wcslen(PrinterName),
|
|
(LPCWSTR) *FixedPortion,
|
|
EndOfVariableData,
|
|
&pJobInfo2->pPrinterName
|
|
);
|
|
|
|
ASSERT(FitInBuffer);
|
|
|
|
//
|
|
// UserName
|
|
//
|
|
FitInBuffer = NwlibCopyStringToBuffer(
|
|
UserName,
|
|
wcslen(UserName),
|
|
(LPCWSTR) *FixedPortion,
|
|
EndOfVariableData,
|
|
&pJobInfo2->pUserName
|
|
);
|
|
|
|
ASSERT(FitInBuffer);
|
|
|
|
//
|
|
// Description
|
|
//
|
|
FitInBuffer = NwlibCopyStringToBuffer(
|
|
JobDescription,
|
|
wcslen(JobDescription),
|
|
(LPCWSTR) *FixedPortion,
|
|
EndOfVariableData,
|
|
&pJobInfo2->pDocument
|
|
);
|
|
|
|
ASSERT(FitInBuffer);
|
|
}
|
|
|
|
if (!FitInBuffer)
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
ConvertToSystemTime(
|
|
IN JOBTIME JobTime,
|
|
OUT LPSYSTEMTIME pSystemTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
JobTime -
|
|
pSystemTime -
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
FILETIME fileTimeLocal, fileTimeUTC;
|
|
|
|
pSystemTime->wYear = JobTime[0] + 1900;
|
|
pSystemTime->wMonth = JobTime[1];
|
|
pSystemTime->wDay = JobTime[2];
|
|
pSystemTime->wDayOfWeek = 0;
|
|
pSystemTime->wHour = JobTime[3];
|
|
pSystemTime->wMinute = JobTime[4];
|
|
pSystemTime->wSecond = JobTime[5];
|
|
pSystemTime->wMilliseconds = 0;
|
|
|
|
if ( ( !SystemTimeToFileTime( pSystemTime, &fileTimeLocal ) )
|
|
|| ( !LocalFileTimeToFileTime( &fileTimeLocal, &fileTimeUTC ) )
|
|
|| ( !FileTimeToSystemTime( &fileTimeUTC, pSystemTime ) )
|
|
)
|
|
{
|
|
KdPrint(("NWWORKSTATION: Time Conversion Error = %d\n",GetLastError()));
|
|
return GetLastError();
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
#ifndef NOT_USED
|
|
|
|
DWORD
|
|
|
|
NwCreateQueue ( IN HANDLE hServer,
|
|
IN LPWSTR pszQueue,
|
|
OUT LPDWORD pQueueId
|
|
)
|
|
|
|
/*+++
|
|
Routine Description:
|
|
|
|
Uses the handle opened to a server to create a queue on the server.
|
|
Return the Queue Id if successful.
|
|
|
|
Arguments:
|
|
|
|
hServer : Handle to the file Server
|
|
pszQueue : Name of the queue that you are creating on the server
|
|
pQueueId : Address of QueueId
|
|
|
|
|
|
Return Value:
|
|
|
|
An error condition as it arises.
|
|
NO_ERROR: Successful in adding printer name
|
|
ERROR : otherwise
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS ntstatus;
|
|
WORD ObjectType;
|
|
UNICODE_STRING UQueueName;
|
|
OEM_STRING OemQueueName;
|
|
|
|
*pQueueId = 0;
|
|
#if DBG
|
|
IF_DEBUG(PRINT) {
|
|
KdPrint(("NWWORKSTATION: NwCreateQueue : %ws\n",
|
|
pszQueue));
|
|
}
|
|
#endif
|
|
|
|
RtlInitUnicodeString( &UQueueName, pszQueue);
|
|
ntstatus = RtlUnicodeStringToOemString( &OemQueueName, &UQueueName, TRUE);
|
|
|
|
if ( NT_SUCCESS(ntstatus))
|
|
{
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
hServer,
|
|
FSCTL_NWR_NCP_E3H,
|
|
174,
|
|
6,
|
|
"bwpbp|d",
|
|
0x64, //Create Queue
|
|
0x0003, // Queue Type = Print Queue
|
|
OemQueueName.Buffer, //Queue Name
|
|
0x00, // Directory Handle
|
|
"SYS:SYSTEM", //queue created in SYS:SYSTEM directory
|
|
pQueueId
|
|
);
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if ( NT_SUCCESS(ntstatus)) {
|
|
#if DBG
|
|
IF_DEBUG(ENUM) {
|
|
KdPrint(("NWWORKSTATION: NwCreateQueue successful\n" ));
|
|
}
|
|
#endif
|
|
|
|
}
|
|
else
|
|
goto FreeExit;
|
|
|
|
// Change Property Security on Q_OPERATORS
|
|
|
|
ntstatus = NwlibMakeNcp (
|
|
hServer,
|
|
FSCTL_NWR_NCP_E3H,
|
|
70,
|
|
2,
|
|
"bwpbp|",
|
|
0x3B,
|
|
0x0003,
|
|
OemQueueName.Buffer,
|
|
0x1, //New Property security
|
|
"Q_OPERATORS"
|
|
);
|
|
|
|
|
|
|
|
if ( NT_SUCCESS(ntstatus)) {
|
|
#if DBG
|
|
IF_DEBUG(PRINT) {
|
|
KdPrint(("NWWORKSTATION: Change Property Security successful\n" ));
|
|
}
|
|
#endif
|
|
|
|
}
|
|
else
|
|
//unable to add new property security, so destroy queue and go to end
|
|
{
|
|
(void) NwDestroyQueue( hServer,
|
|
*pQueueId );
|
|
|
|
goto FreeExit;
|
|
}
|
|
|
|
|
|
// Add Bindery Object of Type Queue to Set
|
|
|
|
ntstatus = NwlibMakeNcp (
|
|
hServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
122,
|
|
2,
|
|
"bwppwp|",
|
|
0x41,
|
|
0x0003,
|
|
OemQueueName.Buffer,
|
|
"Q_OPERATORS",
|
|
0x0001,
|
|
"SUPERVISOR"
|
|
);
|
|
|
|
|
|
|
|
if ( NT_SUCCESS(ntstatus)) {
|
|
|
|
#if DBG
|
|
IF_DEBUG(PRINT) {
|
|
KdPrint(("NWWORKSTATION: Add Bindery Object:Q_OPERATORS\n" ));
|
|
}
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
(void)NwDestroyQueue(hServer,*pQueueId);
|
|
goto FreeExit;
|
|
|
|
}
|
|
// Add Bindery Object to Set of Q_USERS
|
|
|
|
ntstatus = NwlibMakeNcp (
|
|
hServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
122,
|
|
2,
|
|
"bwppwp|",
|
|
0x41,
|
|
0x0003,
|
|
OemQueueName.Buffer,
|
|
"Q_USERS",
|
|
0x0002,
|
|
"EVERYONE"
|
|
);
|
|
|
|
// bunch of parameters to Add Bindery Object to Set Q_USERS
|
|
|
|
|
|
if ( NT_SUCCESS(ntstatus)) {
|
|
#if DBG
|
|
IF_DEBUG(PRINT) {
|
|
KdPrint(("NWWORKSTATION: AddBinderyObjecttoSet Q_USERS\n" ));
|
|
}
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
FreeExit: RtlFreeOemString( &OemQueueName);
|
|
Exit:
|
|
return NwMapBinderyCompletionCode(ntstatus);
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwAssocPServers ( IN HANDLE hServer,
|
|
IN LPWSTR pszQueue,
|
|
IN LPWSTR pszPServer
|
|
)
|
|
|
|
/*+++
|
|
Routine Description:
|
|
|
|
Associates a list of Q Servers with a queue id. This list is supplied
|
|
to this routine as pszPServer with entries separated by semicolons
|
|
|
|
Arguments:
|
|
|
|
hServer : Handle to the file Server
|
|
pszQueue : Name of the queue to which to associate the Q servers
|
|
pszPServer : List of Q Servers.
|
|
|
|
|
|
Return Value:
|
|
|
|
An error condition as it arises.
|
|
0x0 is returned if there is no error
|
|
|
|
--*/
|
|
|
|
{
|
|
LPWSTR pszPServerlist = NULL;
|
|
LPWSTR pszNextPServer = NULL;
|
|
DWORD err = 0x00000000 ;
|
|
NTSTATUS ntstatus ;
|
|
UNICODE_STRING UQueueName, UNextPServer;
|
|
OEM_STRING OemQueueName,OemNextPServer;
|
|
|
|
|
|
if (pszPServer == NULL)
|
|
return NO_ERROR;
|
|
|
|
if((pszPServerlist = AllocNwSplStr(pszPServer)) == NULL)
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY;
|
|
return err;
|
|
}
|
|
|
|
RtlInitUnicodeString( &UQueueName, pszQueue);
|
|
ntstatus = RtlUnicodeStringToOemString( &OemQueueName, &UQueueName, TRUE);
|
|
|
|
if (! NT_SUCCESS(ntstatus))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
while( (pszNextPServer = GetNextElement(&pszPServerlist, L';')) != NULL )
|
|
{
|
|
RtlInitUnicodeString( &UNextPServer, pszNextPServer);
|
|
ntstatus = RtlUnicodeStringToOemString( &OemNextPServer, &UNextPServer, TRUE);
|
|
|
|
|
|
if ( !NT_SUCCESS(ntstatus))
|
|
{
|
|
RtlFreeOemString(&OemNextPServer);
|
|
goto Exit;
|
|
}
|
|
//NwlibMakeNcp should associate a print server with a printer
|
|
|
|
// Add Bindery Object to Set
|
|
|
|
ntstatus = NwlibMakeNcp (
|
|
hServer,
|
|
FSCTL_NWR_NCP_E3H, // Bindery function
|
|
122,
|
|
2,
|
|
"bwppwp|",
|
|
0x41,
|
|
0x0003,
|
|
OemQueueName.Buffer,
|
|
"Q_SERVERS",
|
|
0x0007, // Object of type Print Server
|
|
OemNextPServer.Buffer
|
|
);
|
|
|
|
RtlFreeOemString(&OemNextPServer);
|
|
if (!( NT_SUCCESS(ntstatus)))
|
|
{
|
|
RtlFreeOemString(&OemNextPServer);
|
|
goto Exit;
|
|
|
|
}
|
|
}
|
|
RtlFreeOemString(&OemQueueName);
|
|
|
|
Exit:
|
|
|
|
return NwMapBinderyCompletionCode(ntstatus);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwDestroyQueue (HANDLE hServer,
|
|
DWORD dwQueueId)
|
|
|
|
/*+++
|
|
Routine Description:
|
|
|
|
Makes the Ncp call to destroy the queue given by dwQueueId
|
|
|
|
|
|
Arguments:
|
|
|
|
dwQueueId : Id of the queue you are creating.
|
|
|
|
Return Value:
|
|
|
|
An error condition as it arises.
|
|
0x0 is returned if there is no error
|
|
|
|
---*/
|
|
|
|
{
|
|
|
|
NTSTATUS ntstatus;
|
|
|
|
ntstatus = NwlibMakeNcp(
|
|
hServer,
|
|
FSCTL_NWR_NCP_E3H,
|
|
7,
|
|
2,
|
|
"bd|",
|
|
0x65,
|
|
dwQueueId
|
|
);
|
|
|
|
#if DBG
|
|
if ( NT_SUCCESS(ntstatus)) {
|
|
IF_DEBUG(PRINT) {
|
|
KdPrint(("NWWORKSTATION: Queue successfully destroyed\n"));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return NwMapBinderyCompletionCode(ntstatus);
|
|
|
|
}
|
|
|
|
#endif // #ifndef NOT_USED
|