summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/server/queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/server/queue.c')
-rw-r--r--private/nw/svcdlls/nwwks/server/queue.c1928
1 files changed, 1928 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/server/queue.c b/private/nw/svcdlls/nwwks/server/queue.c
new file mode 100644
index 000000000..2dfae997b
--- /dev/null
+++ b/private/nw/svcdlls/nwwks/server/queue.c
@@ -0,0 +1,1928 @@
+/*++
+
+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;
+ // Default Print Control Flags: Suppress form
+ // feed, banner on, notify on
+DWORD NwGatewayPrintOption = NW_GATEWAY_PRINT_OPTION_DEFAULT;
+ // Gateway default print control flags:
+ // Suppress form feed, banner on, notify off
+
+
+
+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 fGateway,
+ 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
+ fGateway - TRUE if gateway printing, FALSE otherwise
+ 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 : "";
+
+ 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
+ NwPrintOption, // 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
+
+ RtlFreeOemString( &OemDocumentName );
+ RtlFreeOemString( &OemUserName );
+ 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;
+ WORD pwJobList[250];
+ WORD i;
+
+#if DBG
+ IF_DEBUG(QUEUE)
+ {
+ KdPrint(("NWWORKSTATION: NwRemoveAllJobsFromQueue QueueId %08lx\n",
+ QueueId ));
+ }
+#endif
+
+ 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;
+ DWORD TargetServerId;
+ JOBTIME TargetExecutionTime;
+ WORD JobType;
+ BYTE JobControlFlags;
+ BYTE TextJobDescription[50];
+ BYTE ClientRecordArea[152];
+
+ UNICODE_STRING UDocumentName;
+ OEM_STRING OemDocumentName;
+ UNICODE_STRING UUserName;
+ OEM_STRING OemUserName;
+ LPSTR pszDocument, pszUser;
+
+#if DBG
+ IF_DEBUG(QUEUE) {
+ KdPrint(("NWWORKSTATION: NwChangeQueueJobEntry QueueId %08lx JobId %d dwCommand %d\n", QueueId, JobId, dwCommand ));
+ }
+#endif
+
+ if ( pNwJobInfo )
+ {
+ if ( pNwJobInfo->pUserName )
+ {
+ RtlInitUnicodeString( &UUserName, pNwJobInfo->pUserName);
+ ntstatus = RtlUnicodeStringToOemString( &OemUserName,
+ &UUserName,
+ TRUE );
+ }
+
+ if ( NT_SUCCESS(ntstatus) && pNwJobInfo->pDocument )
+ {
+ RtlInitUnicodeString( &UDocumentName, pNwJobInfo->pDocument);
+ ntstatus = RtlUnicodeStringToOemString( &OemDocumentName,
+ &UDocumentName,
+ TRUE );
+ }
+
+ 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 ( pNwJobInfo )
+ {
+ if ( pNwJobInfo->pDocument )
+ RtlFreeOemString( &OemDocumentName );
+
+ if ( pNwJobInfo->pUserName )
+ RtlFreeOemString( &OemUserName );
+ }
+ }
+
+ 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;
+ WORD pwJobList[250];
+
+ DWORD EntrySize = 0;
+ LPBYTE FixedPortion = Buffer;
+ LPWSTR EndOfVariableData = ( LPWSTR ) ((DWORD) 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;
+
+ 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 ( ((DWORD) *FixedPortion + *EntrySize ) > (DWORD) *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.
+ //
+ (DWORD) (*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.
+ //
+ (DWORD) (*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
+
+ BUGBUG: Current implementation does not return an error condition in any case
+
+--*/
+
+{
+ 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