Leaked source code of windows server 2003
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

  1. /*++
  2. Copyright (c) 1991-1993 Microsoft Corporation
  3. Module Name:
  4. queue.c
  5. Abstract:
  6. This module contains the support routines for the queue APIs that call
  7. into the NetWare redirector
  8. Author:
  9. Yi-Hsin Sung (yihsins) 24-Apr-1993
  10. Revision History:
  11. --*/
  12. #include <nw.h>
  13. #include <nwxchg.h>
  14. #include <nwapi.h>
  15. #include <nwreg.h>
  16. #include <queue.h>
  17. #include <splutil.h>
  18. //-------------------------------------------------------------------//
  19. // //
  20. // Local Function Prototypes //
  21. // //
  22. //-------------------------------------------------------------------//
  23. DWORD
  24. NwWriteJobInfoEntry(
  25. IN OUT LPBYTE *FixedPortion,
  26. IN OUT LPWSTR *EndOfVariableData,
  27. IN DWORD Level,
  28. IN WORD JobId,
  29. IN LPWSTR PrinterName,
  30. IN LPWSTR JobDescription,
  31. IN LPWSTR UserName,
  32. IN BYTE JobControlFlags,
  33. IN BYTE JobPosition,
  34. IN LPBYTE JobEntryTime,
  35. IN JOBTIME TargetExecutionTime,
  36. IN DWORD FileSize
  37. );
  38. DWORD
  39. ConvertToSystemTime(
  40. IN JOBTIME JobTime,
  41. OUT LPSYSTEMTIME pSystemTime
  42. );
  43. //-------------------------------------------------------------------//
  44. // //
  45. // Global variables //
  46. // //
  47. //-------------------------------------------------------------------//
  48. #define NW_RDR_SERVER_PREFIX L"\\Device\\Nwrdr\\"
  49. #define QF_USER_HOLD 0x40
  50. #define QF_OPERATOR_HOLD 0x80
  51. //
  52. // Stores the current user's print control options
  53. //
  54. //DWORD NwPrintOption = NW_PRINT_OPTION_DEFAULT; - Commented out for multi-user code merge. We don't use global flag anymore
  55. // The print option is passed from the client for each user
  56. // Default Print Control Flags: Suppress form
  57. // feed, banner on, notify on
  58. DWORD
  59. NwAttachToNetwareServer(
  60. IN LPWSTR ServerName,
  61. OUT LPHANDLE phandleServer
  62. )
  63. /*++
  64. Routine Description:
  65. This routine opens a handle to the given server.
  66. Arguments:
  67. ServerName - The server name to attach to.
  68. phandleServer - Receives an opened handle to the preferred or
  69. nearest server.
  70. Return Value:
  71. NO_ERROR or reason for failure.
  72. --*/
  73. {
  74. NTSTATUS ntstatus;
  75. IO_STATUS_BLOCK IoStatusBlock;
  76. OBJECT_ATTRIBUTES ObjectAttributes;
  77. LPWSTR FullName;
  78. UNICODE_STRING UServerName;
  79. FullName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT,
  80. (UINT) ( wcslen( NW_RDR_SERVER_PREFIX) +
  81. wcslen( ServerName ) - 1) *
  82. sizeof(WCHAR)
  83. );
  84. if ( FullName == NULL ) {
  85. return ERROR_NOT_ENOUGH_MEMORY;
  86. }
  87. wcscpy( FullName, NW_RDR_SERVER_PREFIX );
  88. wcscat( FullName, ServerName + 2 ); // Skip past the prefix "\\"
  89. RtlInitUnicodeString( &UServerName, FullName );
  90. InitializeObjectAttributes(
  91. &ObjectAttributes,
  92. &UServerName,
  93. OBJ_CASE_INSENSITIVE,
  94. NULL,
  95. NULL
  96. );
  97. //
  98. // Open a handle to the preferred server.
  99. //
  100. ntstatus = NtOpenFile(
  101. phandleServer,
  102. SYNCHRONIZE | GENERIC_WRITE,
  103. &ObjectAttributes,
  104. &IoStatusBlock,
  105. FILE_SHARE_VALID_FLAGS,
  106. FILE_SYNCHRONOUS_IO_NONALERT
  107. );
  108. if ( NT_SUCCESS(ntstatus)) {
  109. ntstatus = IoStatusBlock.Status;
  110. }
  111. if (! NT_SUCCESS(ntstatus)) {
  112. *phandleServer = NULL;
  113. }
  114. LocalFree( FullName );
  115. return RtlNtStatusToDosError(ntstatus);
  116. }
  117. DWORD
  118. NwGetNextQueueEntry(
  119. IN HANDLE PreferredServer,
  120. IN OUT LPDWORD LastObjectId,
  121. OUT LPSTR QueueName
  122. )
  123. /*++
  124. Routine Description:
  125. This function uses an opened handle to the preferred server to
  126. scan it bindery for all print queue objects.
  127. Arguments:
  128. PreferredServer - Supplies the handle to the preferred server on
  129. which to scan the bindery.
  130. LastObjectId - On input, supplies the object ID to the last print
  131. queue object returned, which is the resume handle to get the
  132. next print queue object. On output, receives the object ID
  133. of the print queue object returned.
  134. QueueName - Receives the name of the returned print queue object.
  135. Return Value:
  136. NO_ERROR - Successfully gotten a print name.
  137. WN_NO_MORE_ENTRIES - No other print queue object past the one
  138. specified by LastObjectId.
  139. --*/
  140. {
  141. NTSTATUS ntstatus;
  142. WORD ObjectType;
  143. #if DBG
  144. IF_DEBUG(ENUM) {
  145. KdPrint(("NWWORKSTATION: NwGetNextQueueEntry LastObjectId %lu\n",
  146. *LastObjectId));
  147. }
  148. #endif
  149. ntstatus = NwlibMakeNcp(
  150. PreferredServer,
  151. FSCTL_NWR_NCP_E3H, // Bindery function
  152. 58, // Max request packet size
  153. 59, // Max response packet size
  154. "bdwp|dwc", // Format string
  155. 0x37, // Scan bindery object
  156. *LastObjectId, // Previous ID
  157. 0x3, // Print Queue object
  158. "*", // Wildcard to match all
  159. LastObjectId, // Current ID
  160. &ObjectType, // Ignore
  161. QueueName // Currently returned print queue
  162. );
  163. //
  164. // Unmap Japanese special chars
  165. //
  166. UnmapSpecialJapaneseChars(QueueName,(WORD)lstrlenA(QueueName));
  167. #if DBG
  168. if ( NT_SUCCESS(ntstatus)) {
  169. IF_DEBUG(ENUM) {
  170. KdPrint(("NWWORKSTATION: NwGetNextQueueEntry NewObjectId %08lx, QueueName %s\n", *LastObjectId, QueueName));
  171. }
  172. }
  173. #endif
  174. return NwMapBinderyCompletionCode(ntstatus);
  175. }
  176. DWORD
  177. NwGetQueueId(
  178. IN HANDLE handleServer,
  179. IN LPWSTR QueueName,
  180. OUT LPDWORD QueueId
  181. )
  182. /*++
  183. Routine Description:
  184. This function opens a handle to the server and scan its bindery
  185. for the given queue object id.
  186. Arguments:
  187. handleServer - Supplies the handle of the server on which to
  188. scan the bindery.
  189. QueueName - Supplies the name of the print queue.
  190. QueueId - On output, supplies the object ID of the given queue.
  191. Return Value:
  192. NO_ERROR - Successfully gotten a file server name.
  193. --*/
  194. {
  195. NTSTATUS ntstatus;
  196. UNICODE_STRING UQueueName;
  197. OEM_STRING OemQueueName;
  198. #if DBG
  199. IF_DEBUG(QUEUE) {
  200. KdPrint(("NWWORKSTATION: NwGetQueueId %ws\n",
  201. QueueName ));
  202. }
  203. #endif
  204. RtlInitUnicodeString( &UQueueName, QueueName);
  205. ntstatus = RtlUnicodeStringToOemString( &OemQueueName, &UQueueName, TRUE);
  206. //
  207. // Map Japanese special characters
  208. //
  209. MapSpecialJapaneseChars(OemQueueName.Buffer,OemQueueName.Length);
  210. if ( NT_SUCCESS(ntstatus))
  211. {
  212. ntstatus = NwlibMakeNcp(
  213. handleServer,
  214. FSCTL_NWR_NCP_E3H, // Bindery function
  215. 58, // Max request packet size
  216. 59, // Max response packet size
  217. "bdwp|d", // Format string
  218. 0x37, // Scan bindery object
  219. 0xFFFFFFFF, // Previous ID
  220. 0x3, // Print Queue object
  221. OemQueueName.Buffer, // Queue Name
  222. QueueId // Queue ID
  223. );
  224. }
  225. #if DBG
  226. if ( NT_SUCCESS(ntstatus)) {
  227. IF_DEBUG(QUEUE) {
  228. KdPrint(("NWWORKSTATION: NwGetQueueId QueueId %08lx\n",
  229. *QueueId ));
  230. }
  231. }
  232. #endif
  233. RtlFreeOemString( &OemQueueName );
  234. return NwMapBinderyCompletionCode(ntstatus);
  235. }
  236. DWORD
  237. NwCreateQueueJobAndFile(
  238. IN HANDLE handleServer,
  239. IN DWORD QueueId,
  240. IN LPWSTR DocumentName,
  241. IN LPWSTR UserName,
  242. IN DWORD PrintOption, //Multi-user change
  243. IN LPWSTR QueueName,
  244. OUT LPWORD JobId
  245. )
  246. /*++
  247. Routine Description:
  248. This function uses an opened handle to a server to
  249. enter a new job into the queue with the given QueueId.
  250. Arguments:
  251. handleServer - Supplies the handle to the server on
  252. which add the job.
  253. QueueId - Supplies the id of the queue in which to add the job.
  254. DocumentName - Supplies the name of the document to be printed
  255. UserName - Supplies the banner name to be printed
  256. QueueName - Supplies the header name to be printed
  257. JobId - Receives the job id of the newly added job.
  258. Return Value:
  259. NO_ERROR - Successfully added the job to the queue.
  260. --*/
  261. {
  262. NTSTATUS ntstatus = STATUS_SUCCESS;
  263. UNICODE_STRING UDocumentName;
  264. OEM_STRING OemDocumentName;
  265. UNICODE_STRING UUserName;
  266. OEM_STRING OemUserName;
  267. UNICODE_STRING UQueueName;
  268. OEM_STRING OemQueueName;
  269. #if DBG
  270. IF_DEBUG(QUEUE) {
  271. KdPrint(("NWWORKSTATION: NwCreateQueueJobAndFile QueueId %08lx\n",
  272. QueueId ));
  273. }
  274. #endif
  275. if ( UserName )
  276. {
  277. RtlInitUnicodeString( &UUserName, UserName);
  278. ntstatus = RtlUnicodeStringToOemString( &OemUserName,
  279. &UUserName,
  280. TRUE );
  281. }
  282. if ( NT_SUCCESS(ntstatus) && DocumentName )
  283. {
  284. RtlInitUnicodeString( &UDocumentName, DocumentName);
  285. ntstatus = RtlUnicodeStringToOemString( &OemDocumentName,
  286. &UDocumentName,
  287. TRUE );
  288. }
  289. if ( NT_SUCCESS(ntstatus) && QueueName )
  290. {
  291. RtlInitUnicodeString( &UQueueName, QueueName);
  292. ntstatus = RtlUnicodeStringToOemString( &OemQueueName,
  293. &UQueueName,
  294. TRUE );
  295. }
  296. if ( NT_SUCCESS( ntstatus)) {
  297. LPSTR pszDocument, pszUser, pszQueue;
  298. pszDocument = DocumentName? OemDocumentName.Buffer : "";
  299. pszUser = UserName? OemUserName.Buffer : "";
  300. pszQueue = QueueName? OemQueueName.Buffer : "";
  301. //Multi-user uses passed print flag
  302. //
  303. ntstatus = NwlibMakeNcp(
  304. handleServer,
  305. FSCTL_NWR_NCP_E3H, // Bindery function
  306. 263, // Max request packet size
  307. 56, // Max response packet size
  308. "bd_ddw_b_Cbbwwww_C-C-_|_w", // Format string
  309. 0x68, // Create Queue Job and File object
  310. QueueId, // Queue ID
  311. 6, // Skip bytes
  312. 0xffffffff, // Target Server ID number
  313. 0xffffffff, 0xffff, // Target Execution time
  314. 11, // Skip bytes
  315. 0x00, // Job Control Flags
  316. 26, // Skip bytes
  317. pszDocument, // TextJobDescription
  318. 50, // Skip bytes
  319. 0, // Version number (clientarea)
  320. 8, // Tab Size
  321. 1, // Number of copies
  322. PrintOption, // Print Control Flags
  323. 0x3C, // Maximum lines
  324. 0x84, // Maximum characters
  325. 22, // Skip bytes
  326. pszUser, // Banner Name
  327. 12, // Max Length of pszUser
  328. pszQueue, // Header Name
  329. 12, // Max Length of pszQueue
  330. 14 + 80, // Skip remainder of client area
  331. 22, // Skip bytes
  332. JobId // Job ID
  333. );
  334. }
  335. #if DBG
  336. if ( NT_SUCCESS( ntstatus)) {
  337. IF_DEBUG(QUEUE) {
  338. KdPrint(("NWWORKSTATION: NwCreateQueueJobAndFile JobId %d\n",
  339. *JobId ));
  340. }
  341. }
  342. #endif
  343. if ( DocumentName )
  344. RtlFreeOemString( &OemDocumentName );
  345. if ( UserName )
  346. RtlFreeOemString( &OemUserName );
  347. if ( QueueName )
  348. RtlFreeOemString( &OemQueueName );
  349. return NwMapStatus(ntstatus);
  350. }
  351. DWORD
  352. NwCloseFileAndStartQueueJob(
  353. IN HANDLE handleServer,
  354. IN DWORD QueueId,
  355. IN WORD JobId
  356. )
  357. /*++
  358. Routine Description:
  359. This function uses an opened handle to a server to
  360. close a job file and mark the job file ready for service.
  361. Arguments:
  362. handleServer - Supplies the handle to the server on
  363. which add the job.
  364. QueueId - Supplies the id of the queue in which to add the job.
  365. JobId - Supplies the job id.
  366. Return Value:
  367. NO_ERROR - Successfully added the job to the queue.
  368. --*/
  369. {
  370. NTSTATUS ntstatus;
  371. #if DBG
  372. IF_DEBUG(QUEUE) {
  373. KdPrint(("NWWORKSTATION: NwCloseFileAndStartQueueJob QueueId %08lx JobId %d\n", QueueId, JobId ));
  374. }
  375. #endif
  376. // Two versions of CloseFileAndStartQueueJobNCP
  377. ntstatus = NwlibMakeNcp(
  378. handleServer,
  379. FSCTL_NWR_NCP_E3H, // Bindery function
  380. 9, // Max request packet size
  381. 2, // Max response packet size
  382. "bdw|", // Format string
  383. 0x69, // Close File And Start Queue Job
  384. QueueId, // Queue ID
  385. JobId ); // Job ID
  386. return NwMapStatus(ntstatus);
  387. }
  388. DWORD
  389. NwRemoveJobFromQueue(
  390. IN HANDLE handleServer,
  391. IN DWORD QueueId,
  392. IN WORD JobId
  393. )
  394. /*++
  395. Routine Description:
  396. This function removes a job from a queue and closes the associate file.
  397. Arguments:
  398. handleServer - Supplies the handle to the server on
  399. which to remove the job.
  400. QueueId - Supplies the id of the queue in which to remove the job.
  401. JobId - Supplies the job id to be removed.
  402. Return Value:
  403. NO_ERROR - Successfully removed the job from the queue.
  404. --*/
  405. {
  406. NTSTATUS ntstatus;
  407. #if DBG
  408. IF_DEBUG(QUEUE) {
  409. KdPrint(("NWWORKSTATION: NwRemoveJobFromQueue QueueId %08lx JobId %d\n",
  410. QueueId, JobId ));
  411. }
  412. #endif
  413. ntstatus = NwlibMakeNcp(
  414. handleServer,
  415. FSCTL_NWR_NCP_E3H, // Bindery function
  416. 9, // Max request packet size
  417. 2, // Max response packet size
  418. "bdw|", // Format string
  419. 0x6A, // Remove Job From Queue
  420. QueueId, // Queue ID
  421. JobId ); // Job ID
  422. return NwMapStatus(ntstatus);
  423. }
  424. DWORD
  425. NwRemoveAllJobsFromQueue(
  426. IN HANDLE handleServer,
  427. IN DWORD QueueId
  428. )
  429. /*++
  430. Routine Description:
  431. This function removes all jobs from a queue.
  432. Arguments:
  433. handleServer - Supplies the handle to the server on
  434. which to remove all jobs.
  435. QueueId - Supplies the id of the queue in which to remove all jobs.
  436. Return Value:
  437. NO_ERROR - Successfully removed all jobs from the queue.
  438. --*/
  439. {
  440. DWORD err;
  441. WORD JobCount = 0;
  442. WORD pwJobList[250];
  443. WORD i;
  444. #if DBG
  445. IF_DEBUG(QUEUE)
  446. {
  447. KdPrint(("NWWORKSTATION: NwRemoveAllJobsFromQueue QueueId %08lx\n",
  448. QueueId ));
  449. }
  450. #endif
  451. pwJobList[0] = 0;
  452. err = NwGetQueueJobList( handleServer,
  453. QueueId,
  454. &JobCount,
  455. pwJobList );
  456. for ( i = 0; !err && i < JobCount; i++ )
  457. {
  458. err = NwRemoveJobFromQueue( handleServer,
  459. QueueId,
  460. pwJobList[i] );
  461. }
  462. return err;
  463. }
  464. DWORD
  465. NwReadQueueCurrentStatus(
  466. IN HANDLE handleServer,
  467. IN DWORD QueueId,
  468. OUT LPBYTE QueueStatus,
  469. OUT LPBYTE NumberOfJobs
  470. )
  471. /*++
  472. Routine Description:
  473. This function uses an opened handle to a server to
  474. query the status of the queue with the given QueueId.
  475. Arguments:
  476. handleServer - Supplies the handle to the server on
  477. which add the job.
  478. QueueId - Supplies the id of the queue
  479. QueueStatus - Receives the status of the queue
  480. NumberOfJobs - Receives the number of jobs in the queue.
  481. Return Value:
  482. NO_ERROR - Successfully retrieved the status of the queue.
  483. --*/
  484. {
  485. NTSTATUS ntstatus;
  486. #if DBG
  487. IF_DEBUG(QUEUE) {
  488. KdPrint(("NWWORKSTATION: NwReadQueueCurrentStatus QueueId %08lx\n",
  489. QueueId ));
  490. }
  491. #endif
  492. ntstatus = NwlibMakeNcp(
  493. handleServer,
  494. FSCTL_NWR_NCP_E3H, // Bindery function
  495. 7, // Max request packet size
  496. 135, // Max response packet size
  497. "bd|==bb", // Format string
  498. 0x66, // ReadQueueCurrentStatus
  499. QueueId, // Queue ID
  500. QueueStatus, // Queue status
  501. NumberOfJobs // Number of jobs in the queue
  502. );
  503. #if DBG
  504. if ( NT_SUCCESS( ntstatus)) {
  505. IF_DEBUG(QUEUE) {
  506. KdPrint(("NWWORKSTATION: NwReadQueueCurrentStatus QueueStatus %d Number of Jobs %d\n", *QueueStatus, *NumberOfJobs ));
  507. }
  508. }
  509. #endif
  510. return NwMapStatus(ntstatus);
  511. }
  512. DWORD
  513. NwSetQueueCurrentStatus(
  514. IN HANDLE handleServer,
  515. IN DWORD QueueId,
  516. IN BYTE QueueStatus
  517. )
  518. /*++
  519. Routine Description:
  520. This function uses an opened handle to a server to
  521. set the status (pause/ready...) of the queue with the given QueueId.
  522. Arguments:
  523. handleServer - Supplies the handle to the server on
  524. which add the job.
  525. QueueId - Supplies the id of the queue
  526. QueueStatus - Supplies the status of the queue
  527. Return Value:
  528. NO_ERROR - Successfully set the status of the queue.
  529. --*/
  530. {
  531. NTSTATUS ntstatus;
  532. #if DBG
  533. IF_DEBUG(QUEUE) {
  534. KdPrint(("NWWORKSTATION: NwSetQueueCurrentStatus QueueId %08lx\n",
  535. QueueId ));
  536. }
  537. #endif
  538. ntstatus = NwlibMakeNcp(
  539. handleServer,
  540. FSCTL_NWR_NCP_E3H, // Bindery function
  541. 8, // Max request packet size
  542. 2, // Max response packet size
  543. "bdb|", // Format string
  544. 0x67, // ReadQueueCurrentStatus
  545. QueueId, // Queue ID
  546. QueueStatus // Queue status
  547. );
  548. return NwMapStatus(ntstatus);
  549. }
  550. DWORD
  551. NwGetQueueJobList(
  552. IN HANDLE handleServer,
  553. IN DWORD QueueId,
  554. OUT LPWORD NumberOfJobs,
  555. OUT LPWORD JobIdList
  556. )
  557. /*++
  558. Routine Description:
  559. This function uses an opened handle to a server to
  560. get the job list of the queue with the given QueueId.
  561. Arguments:
  562. handleServer - Supplies the handle to the server on
  563. which add the job.
  564. QueueId - Supplies the id of the queue
  565. NumberOfJobs - Receives the number of jobs in the queue.
  566. JobIdList - Receives the array of job ids in the queue
  567. Return Value:
  568. NO_ERROR - Successfully added the job to the queue.
  569. --*/
  570. {
  571. NTSTATUS ntstatus;
  572. #if DBG
  573. WORD i;
  574. IF_DEBUG(QUEUE) {
  575. KdPrint(("NWWORKSTATION: NwGetQueueJobList QueueId %08lx\n",
  576. QueueId ));
  577. }
  578. #endif
  579. ntstatus = NwlibMakeNcp(
  580. handleServer,
  581. FSCTL_NWR_NCP_E3H, // Bindery function
  582. 7, // Max request packet size
  583. 506, // Max response packet size
  584. "bd|W", // Format string
  585. 0x6B, // Get Queue Job List
  586. QueueId, // Queue ID
  587. NumberOfJobs, // Number of jobs in the queue
  588. JobIdList // Array of job ids
  589. );
  590. #if DBG
  591. if ( NT_SUCCESS(ntstatus)) {
  592. IF_DEBUG(QUEUE) {
  593. KdPrint(("NWWORKSTATION: NwGetQueueJobList Number of Jobs %d\nJob List = ", *NumberOfJobs ));
  594. for ( i = 0; i < *NumberOfJobs; i++ )
  595. KdPrint(("%d ", JobIdList[i] ));
  596. KdPrint(("\n"));
  597. }
  598. }
  599. #endif
  600. return NwMapStatus(ntstatus);
  601. }
  602. DWORD
  603. NwReadQueueJobEntry(
  604. IN HANDLE handleServer,
  605. IN DWORD QueueId,
  606. IN WORD JobId,
  607. OUT JOBTIME TargetExecutionTime,
  608. OUT JOBTIME JobEntryTime,
  609. OUT LPBYTE JobPosition,
  610. OUT LPBYTE JobControlFlags,
  611. OUT LPSTR TextJobDescription,
  612. OUT LPSTR UserName
  613. )
  614. /*++
  615. Routine Description:
  616. This function uses an opened handle to a server to
  617. get the information about the job with the given JobId
  618. in the given QueueId.
  619. Arguments:
  620. handleServer - Supplies the handle to the server on
  621. which add the job.
  622. QueueId - Supplies the id of the queue
  623. JobId - Supplies the job we are interested in
  624. TargetExecutionTime -
  625. JobEntryTime -
  626. JobPosition -
  627. JobControlsFlags -
  628. TextJobDescription -
  629. Return Value:
  630. NO_ERROR - Successfully added the job to the queue.
  631. --*/
  632. {
  633. NTSTATUS ntstatus;
  634. #if DBG
  635. IF_DEBUG(QUEUE) {
  636. KdPrint(("NWWORKSTATION: NwReadQueueJobEntry QueueId %08lx JobId %d\n",
  637. QueueId, JobId ));
  638. }
  639. #endif
  640. ntstatus = NwlibMakeNcp(
  641. handleServer,
  642. FSCTL_NWR_NCP_E3H, // Bindery function
  643. 9, // Max request packet size
  644. 258, // Max response packet size
  645. "bdw|_rr==bb_C_c", // Format string
  646. 0x6C, // Read Queue Job Entry
  647. QueueId, // Queue ID
  648. JobId, // Job ID
  649. 10, // Skip bytes
  650. TargetExecutionTime, // Array storing execution time
  651. 6, // Size of TargetExecutionTime
  652. JobEntryTime, // Array storing job entry time
  653. 6, // Size of JobEntryTime
  654. JobPosition, // Job Position
  655. JobControlFlags, // Job Control Flag
  656. 26, // Skip bytes
  657. TextJobDescription, // Array storing the description
  658. 50, // Maximum size in the above array
  659. 32, // Skip bytes
  660. UserName // Banner Name
  661. );
  662. #if DBG
  663. if ( NT_SUCCESS( ntstatus)) {
  664. IF_DEBUG(QUEUE) {
  665. KdPrint(("NWWORKSTATION: NwReadQueueJobEntry JobPosition %d Status %d Description %s\n", *JobPosition, *JobControlFlags, TextJobDescription ));
  666. }
  667. }
  668. #endif
  669. return NwMapStatus(ntstatus);
  670. }
  671. DWORD
  672. NwGetQueueJobsFileSize(
  673. IN HANDLE handleServer,
  674. IN DWORD QueueId,
  675. IN WORD JobId,
  676. OUT LPDWORD FileSize
  677. )
  678. /*++
  679. Routine Description:
  680. This function uses an opened handle to a server to
  681. get the file size of the given job.
  682. Arguments:
  683. handleServer - Supplies the handle to the server on
  684. which add the job.
  685. QueueId - Supplies the id of the queue
  686. JobId - Identifying the job we are interested in
  687. FileSize - Receives the file size of the given job
  688. Return Value:
  689. NO_ERROR - Successfully retrieved the file size.
  690. --*/
  691. {
  692. NTSTATUS ntstatus;
  693. #if DBG
  694. IF_DEBUG(QUEUE) {
  695. KdPrint(("NWWORKSTATION: NwGetQueueJobsFileSize QueueId %08lx JobId %d\n", QueueId, JobId ));
  696. }
  697. #endif
  698. ntstatus = NwlibMakeNcp(
  699. handleServer,
  700. FSCTL_NWR_NCP_E3H, // Bindery function
  701. 9, // Max request packet size
  702. 12, // Max response packet size
  703. "bdw|===d", // Format string
  704. 0x78, // Get Queue Job's File Size
  705. QueueId, // Queue ID
  706. JobId, // Job ID
  707. FileSize // File Size
  708. );
  709. #if DBG
  710. if ( NT_SUCCESS( ntstatus)) {
  711. IF_DEBUG(QUEUE) {
  712. KdPrint(("NWWORKSTATION: NwGetQueueJobsFileSize File Size %d\n",
  713. *FileSize ));
  714. }
  715. }
  716. #endif
  717. return NwMapStatus(ntstatus);
  718. }
  719. DWORD
  720. NwChangeQueueJobPosition(
  721. IN HANDLE handleServer,
  722. IN DWORD QueueId,
  723. IN WORD JobId,
  724. IN BYTE NewPosition
  725. )
  726. /*++
  727. Routine Description:
  728. This function uses an opened handle to a server to
  729. get the change a job's position in a queue.
  730. Arguments:
  731. handleServer - Supplies the handle to the server on
  732. which add the job.
  733. QueueId - Supplies the id of the queue
  734. JobId - Identifying the job we are interested in
  735. NewPosition - Supplies the new position of the job
  736. Return Value:
  737. NO_ERROR - Successfully retrieved the file size.
  738. --*/
  739. {
  740. NTSTATUS ntstatus;
  741. #if DBG
  742. IF_DEBUG(QUEUE) {
  743. KdPrint(("NWWORKSTATION: NwChangeQueueJobPosition QueueId %08lx JobId %d NewPosition %d\n", QueueId, JobId, NewPosition ));
  744. }
  745. #endif
  746. ntstatus = NwlibMakeNcp(
  747. handleServer,
  748. FSCTL_NWR_NCP_E3H, // Bindery function
  749. 10, // Max request packet size
  750. 2, // Max response packet size
  751. "bdwb|", // Format string
  752. 0x6E, // Change Queue Job Position
  753. QueueId, // Queue ID
  754. JobId, // Job ID
  755. NewPosition // New position of the job
  756. );
  757. return NwMapStatus(ntstatus);
  758. }
  759. DWORD
  760. NwChangeQueueJobEntry(
  761. IN HANDLE handleServer,
  762. IN DWORD QueueId,
  763. IN WORD JobId,
  764. IN DWORD dwCommand,
  765. IN PNW_JOB_INFO pNwJobInfo
  766. )
  767. /*++
  768. Routine Description:
  769. This function uses an opened handle to a server to
  770. get the change a job's position in a queue.
  771. Arguments:
  772. handleServer - Supplies the handle to the server on
  773. which add the job.
  774. QueueId - Supplies the id of the queue
  775. JobId - Identifying the job we are interested in
  776. JobControlFlags - Supplies the new job control flags
  777. pNwJobInfo -
  778. Return Value:
  779. NO_ERROR - Successfully retrieved the file size.
  780. --*/
  781. {
  782. NTSTATUS ntstatus = STATUS_SUCCESS;
  783. DWORD TargetServerId;
  784. JOBTIME TargetExecutionTime;
  785. WORD JobType;
  786. BYTE JobControlFlags;
  787. BYTE TextJobDescription[50];
  788. BYTE ClientRecordArea[152];
  789. UNICODE_STRING UDocumentName;
  790. UNICODE_STRING UUserName;
  791. OEM_STRING OemDocumentName, *pOemDocumentName = NULL;
  792. OEM_STRING OemUserName, *pOemUserName = NULL;
  793. LPSTR pszDocument, pszUser;
  794. #if DBG
  795. IF_DEBUG(QUEUE) {
  796. KdPrint(("NWWORKSTATION: NwChangeQueueJobEntry QueueId %08lx JobId %d dwCommand %d\n", QueueId, JobId, dwCommand ));
  797. }
  798. #endif
  799. TextJobDescription[0] = 0;
  800. if ( pNwJobInfo )
  801. {
  802. if ( pNwJobInfo->pUserName )
  803. {
  804. RtlInitUnicodeString( &UUserName, pNwJobInfo->pUserName);
  805. ntstatus = RtlUnicodeStringToOemString( &OemUserName,
  806. &UUserName,
  807. TRUE );
  808. if ( NT_SUCCESS(ntstatus) )
  809. pOemUserName = &OemUserName ; // record to free later
  810. }
  811. if ( NT_SUCCESS(ntstatus) && pNwJobInfo->pDocument )
  812. {
  813. RtlInitUnicodeString( &UDocumentName, pNwJobInfo->pDocument);
  814. ntstatus = RtlUnicodeStringToOemString( &OemDocumentName,
  815. &UDocumentName,
  816. TRUE );
  817. if ( NT_SUCCESS(ntstatus) )
  818. pOemDocumentName = &OemDocumentName ; // record to free later
  819. }
  820. if ( NT_SUCCESS( ntstatus))
  821. {
  822. pszDocument = pNwJobInfo->pDocument? OemDocumentName.Buffer : "";
  823. pszUser = pNwJobInfo->pUserName? OemUserName.Buffer: "";
  824. }
  825. }
  826. if ( NT_SUCCESS( ntstatus))
  827. {
  828. ntstatus = NwlibMakeNcp(
  829. handleServer,
  830. FSCTL_NWR_NCP_E3H, // Bindery function
  831. 9, // Max request packet size
  832. 258, // Max response packet size
  833. "bdw|_dr_w-b_rr", // Format string
  834. 0x6C, // Read Queue Job Entry
  835. QueueId, // Queue ID
  836. JobId, // Job ID
  837. 6, // Skip bytes
  838. &TargetServerId, // Target Server ID Number
  839. TargetExecutionTime, // Target Execution Time
  840. 6, // sizeof TargetExecutionTime
  841. 8, // Skip bytes
  842. &JobType, // Job Type
  843. &JobControlFlags, // Job Control flags
  844. 26, // Skip bytes
  845. TextJobDescription, // TextJobDescription
  846. 50, // sizeof TextJobDescription
  847. ClientRecordArea, // Client record area
  848. 152 // sizeof ClientRecordArea
  849. );
  850. }
  851. if ( NT_SUCCESS( ntstatus))
  852. {
  853. switch ( dwCommand )
  854. {
  855. case JOB_CONTROL_PAUSE:
  856. JobControlFlags |= QF_USER_HOLD;
  857. break;
  858. case JOB_CONTROL_RESUME:
  859. JobControlFlags &= ~( QF_USER_HOLD | QF_OPERATOR_HOLD );
  860. break;
  861. default:
  862. break;
  863. }
  864. ntstatus = NwlibMakeNcp(
  865. handleServer,
  866. FSCTL_NWR_NCP_E3H, // Bindery function
  867. 263, // Max request packet size
  868. 2, // Max response packet size
  869. "bd_dr_ww-b_CrCr|", // Format string
  870. 0x6D, // Change Queue Job Entry
  871. QueueId, // Queue ID
  872. 6, // Skip bytes
  873. TargetServerId, // Target Server ID Number
  874. TargetExecutionTime, // Target Execution Time
  875. 6, // sizeof TargetExecutionTime
  876. 6, // Skip bytes
  877. JobId, // Job ID
  878. JobType, // Job Type
  879. JobControlFlags, // Job Control Flags
  880. 26, // Skip bytes
  881. pNwJobInfo? pszDocument
  882. : TextJobDescription, // Description
  883. 50, // Skip bytes of Description
  884. ClientRecordArea, // Client Record Area
  885. 32, // First 32 bytes of the above
  886. pNwJobInfo? pszUser
  887. : (LPSTR) &ClientRecordArea[32], // Banner Name
  888. 13, // sizeof BannerName
  889. &ClientRecordArea[45], // Rest of the Client Area
  890. 107 // sizeof the above
  891. );
  892. }
  893. if ( pOemDocumentName )
  894. RtlFreeOemString( pOemDocumentName );
  895. if ( pOemUserName )
  896. RtlFreeOemString( pOemUserName );
  897. return NwMapStatus(ntstatus);
  898. }
  899. DWORD
  900. NwGetQueueJobs(
  901. IN HANDLE handleServer,
  902. IN DWORD QueueId,
  903. IN LPWSTR PrinterName,
  904. IN DWORD FirstJobRequested,
  905. IN DWORD EntriesRequested,
  906. IN DWORD Level,
  907. OUT LPBYTE Buffer,
  908. IN DWORD cbBuf,
  909. OUT LPDWORD BytesNeeded,
  910. OUT LPDWORD Entries
  911. )
  912. /*++
  913. Routine Description:
  914. Arguments:
  915. handleServer - Supplies the handle to the server on
  916. which add the job.
  917. QueueId - Supplies the id of the queue
  918. Return Value:
  919. --*/
  920. {
  921. DWORD err = NO_ERROR;
  922. DWORD i;
  923. WORD JobCount = 0;
  924. WORD pwJobList[250];
  925. DWORD EntrySize = 0;
  926. LPBYTE FixedPortion = Buffer;
  927. LPWSTR EndOfVariableData = ( LPWSTR ) ( Buffer + cbBuf );
  928. #if DBG
  929. IF_DEBUG(QUEUE)
  930. KdPrint(("NWWORKSTATION: NwGetQueueJobs QueueId %08lx\n", QueueId));
  931. #endif
  932. *BytesNeeded = 0;
  933. *Entries = 0;
  934. err = NwGetQueueJobList( handleServer,
  935. QueueId,
  936. &JobCount,
  937. pwJobList );
  938. if ( err )
  939. {
  940. KdPrint(("NWWORKSTATION: NwGetQueueJobList Error %d\n", err ));
  941. return err;
  942. }
  943. for ( i = 0; (i < EntriesRequested) && ( i+FirstJobRequested+1 <= JobCount);
  944. i++ )
  945. {
  946. err = NwGetQueueJobInfo( handleServer,
  947. QueueId,
  948. pwJobList[i+FirstJobRequested],
  949. PrinterName,
  950. Level,
  951. &FixedPortion,
  952. &EndOfVariableData,
  953. &EntrySize );
  954. if ( err != NO_ERROR && err != ERROR_INSUFFICIENT_BUFFER )
  955. break;
  956. *BytesNeeded += EntrySize;
  957. }
  958. if ( err == ERROR_INSUFFICIENT_BUFFER )
  959. {
  960. *Entries = 0;
  961. }
  962. else if ( err == NO_ERROR )
  963. {
  964. *Entries = i;
  965. }
  966. return err;
  967. }
  968. DWORD
  969. NwGetQueueJobInfo(
  970. IN HANDLE handleServer,
  971. IN DWORD QueueId,
  972. IN WORD JobId,
  973. IN LPWSTR PrinterName,
  974. IN DWORD Level,
  975. IN OUT LPBYTE *FixedPortion,
  976. IN OUT LPWSTR *EndOfVariableData,
  977. OUT LPDWORD EntrySize
  978. )
  979. /*++
  980. Routine Description:
  981. Arguments:
  982. handleServer - Supplies the handle to the server on
  983. which add the job.
  984. QueueId - Supplies the id of the queue
  985. Return Value:
  986. --*/
  987. {
  988. DWORD err;
  989. LPWSTR UTextJobDescription = NULL;
  990. LPWSTR UUserName = NULL;
  991. JOBTIME TargetExecutionTime;
  992. JOBTIME JobEntryTime;
  993. BYTE JobPosition;
  994. BYTE JobControlFlags;
  995. CHAR UserName[14];
  996. CHAR TextJobDescription[50];
  997. DWORD FileSize = 0;
  998. TextJobDescription[0] = 0;
  999. err = NwReadQueueJobEntry( handleServer,
  1000. QueueId,
  1001. JobId,
  1002. TargetExecutionTime,
  1003. JobEntryTime,
  1004. &JobPosition,
  1005. &JobControlFlags,
  1006. TextJobDescription,
  1007. UserName );
  1008. if ( err )
  1009. {
  1010. KdPrint(("NWWORKSTATION: NwReadQueueJobEntry JobId %d Error %d\n",
  1011. JobId, err ));
  1012. return err;
  1013. }
  1014. if (!NwConvertToUnicode( &UTextJobDescription, TextJobDescription ))
  1015. {
  1016. err = ERROR_NOT_ENOUGH_MEMORY ;
  1017. goto ErrorExit ;
  1018. }
  1019. if (!NwConvertToUnicode( &UUserName, UserName ))
  1020. {
  1021. err = ERROR_NOT_ENOUGH_MEMORY ;
  1022. goto ErrorExit ;
  1023. }
  1024. *EntrySize = ( Level == 1? sizeof( JOB_INFO_1W ) : sizeof( JOB_INFO_2W ))
  1025. + ( wcslen( UTextJobDescription ) + wcslen( UUserName) +
  1026. wcslen( PrinterName ) + 3 ) * sizeof( WCHAR );
  1027. //
  1028. // See if the buffer is large enough to fit the entry
  1029. //
  1030. if ( (LPWSTR)( *FixedPortion + *EntrySize ) > *EndOfVariableData )
  1031. {
  1032. err = ERROR_INSUFFICIENT_BUFFER;
  1033. goto ErrorExit ;
  1034. }
  1035. if ( Level == 2 )
  1036. {
  1037. err = NwGetQueueJobsFileSize( handleServer,
  1038. QueueId,
  1039. JobId,
  1040. &FileSize );
  1041. if ( err )
  1042. {
  1043. KdPrint(("NWWORKSTATION: NwGetQueueJobsFileSize JobId %d Error %d\n", JobId, err ));
  1044. goto ErrorExit ;
  1045. }
  1046. }
  1047. err = NwWriteJobInfoEntry( FixedPortion,
  1048. EndOfVariableData,
  1049. Level,
  1050. JobId,
  1051. PrinterName,
  1052. UTextJobDescription,
  1053. UUserName,
  1054. JobControlFlags,
  1055. JobPosition,
  1056. JobEntryTime,
  1057. TargetExecutionTime,
  1058. FileSize );
  1059. ErrorExit:
  1060. if (UTextJobDescription)
  1061. (void) LocalFree((HLOCAL) UTextJobDescription) ;
  1062. if (UUserName)
  1063. (void) LocalFree((HLOCAL) UUserName) ;
  1064. return err;
  1065. }
  1066. DWORD
  1067. NwWriteJobInfoEntry(
  1068. IN OUT LPBYTE *FixedPortion,
  1069. IN OUT LPWSTR *EndOfVariableData,
  1070. IN DWORD Level,
  1071. IN WORD JobId,
  1072. IN LPWSTR PrinterName,
  1073. IN LPWSTR JobDescription,
  1074. IN LPWSTR UserName,
  1075. IN BYTE JobControlFlags,
  1076. IN BYTE JobPosition,
  1077. IN JOBTIME JobEntryTime,
  1078. IN JOBTIME TargetExecutionTime,
  1079. IN DWORD FileSize
  1080. )
  1081. /*++
  1082. Routine Description:
  1083. This function packages a JOB_INFO_1 or JOB_INFO_2 entry into the
  1084. user output buffer.
  1085. Arguments:
  1086. FixedPortion - Supplies a pointer to the output buffer where the next
  1087. entry of the fixed portion of the use information will be written.
  1088. This pointer is updated to point to the next fixed portion entry
  1089. after a PRINT_INFO_1 entry is written.
  1090. EndOfVariableData - Supplies a pointer just off the last available byte
  1091. in the output buffer. This is because the variable portion of the
  1092. user information is written into the output buffer starting from
  1093. the end.
  1094. This pointer is updated after any variable length information is
  1095. written to the output buffer.
  1096. Return Value:
  1097. NO_ERROR - Successfully wrote entry into user buffer.
  1098. ERROR_INSUFFICIENT_BUFFER - Buffer was too small to fit entry.
  1099. --*/
  1100. {
  1101. DWORD err = NO_ERROR;
  1102. BOOL FitInBuffer = TRUE;
  1103. DWORD JobStatus = 0;
  1104. JOB_INFO_1W *pJobInfo1 = (JOB_INFO_1W *) *FixedPortion;
  1105. JOB_INFO_2W *pJobInfo2 = (JOB_INFO_2W *) *FixedPortion;
  1106. if ( ( JobControlFlags & QF_USER_HOLD )
  1107. || ( JobControlFlags & QF_OPERATOR_HOLD )
  1108. )
  1109. {
  1110. JobStatus = JOB_STATUS_PAUSED;
  1111. }
  1112. //
  1113. // See if buffer is large enough to fit the entry.
  1114. //
  1115. if ( Level == 1 )
  1116. {
  1117. pJobInfo1->JobId = JobId;
  1118. pJobInfo1->Position = JobPosition;
  1119. pJobInfo1->Status = JobStatus;
  1120. if ( err = ConvertToSystemTime( JobEntryTime, &pJobInfo1->Submitted ))
  1121. return err;
  1122. pJobInfo1->pMachineName = NULL;
  1123. pJobInfo1->pDatatype = NULL;
  1124. pJobInfo1->pStatus = NULL;
  1125. pJobInfo1->Priority = 0;
  1126. pJobInfo1->TotalPages = 0;
  1127. pJobInfo1->PagesPrinted = 0;
  1128. //
  1129. // Update fixed entry pointer to next entry.
  1130. //
  1131. (*FixedPortion) += sizeof(JOB_INFO_1W);
  1132. //
  1133. // PrinterName
  1134. //
  1135. FitInBuffer = NwlibCopyStringToBuffer(
  1136. PrinterName,
  1137. wcslen(PrinterName),
  1138. (LPCWSTR) *FixedPortion,
  1139. EndOfVariableData,
  1140. &pJobInfo1->pPrinterName
  1141. );
  1142. ASSERT(FitInBuffer);
  1143. //
  1144. // UserName
  1145. //
  1146. FitInBuffer = NwlibCopyStringToBuffer(
  1147. UserName,
  1148. wcslen(UserName),
  1149. (LPCWSTR) *FixedPortion,
  1150. EndOfVariableData,
  1151. &pJobInfo1->pUserName
  1152. );
  1153. ASSERT(FitInBuffer);
  1154. //
  1155. // Description
  1156. //
  1157. FitInBuffer = NwlibCopyStringToBuffer(
  1158. JobDescription,
  1159. wcslen(JobDescription),
  1160. (LPCWSTR) *FixedPortion,
  1161. EndOfVariableData,
  1162. &pJobInfo1->pDocument
  1163. );
  1164. ASSERT(FitInBuffer);
  1165. }
  1166. else // Level == 2
  1167. {
  1168. pJobInfo2->JobId = JobId;
  1169. pJobInfo2->Position = JobPosition;
  1170. pJobInfo2->Status = JobStatus;
  1171. if ( err = ConvertToSystemTime( JobEntryTime, &pJobInfo2->Submitted ))
  1172. return err;
  1173. pJobInfo2->StartTime = 0;
  1174. pJobInfo2->Size = FileSize;
  1175. pJobInfo2->pMachineName = NULL;
  1176. pJobInfo2->pNotifyName = NULL;
  1177. pJobInfo2->pDatatype = NULL;
  1178. pJobInfo2->pPrintProcessor = NULL;
  1179. pJobInfo2->pParameters = NULL;
  1180. pJobInfo2->pDriverName = NULL;
  1181. pJobInfo2->pDevMode = NULL;
  1182. pJobInfo2->pStatus = NULL;
  1183. pJobInfo2->pSecurityDescriptor = NULL;
  1184. pJobInfo2->Priority = 0;
  1185. pJobInfo2->TotalPages = 0;
  1186. pJobInfo2->UntilTime = 0;
  1187. pJobInfo2->Time = 0;
  1188. pJobInfo2->PagesPrinted = 0;
  1189. //
  1190. // Update fixed entry pointer to next entry.
  1191. //
  1192. (*FixedPortion) += sizeof(JOB_INFO_2W);
  1193. //
  1194. // PrinterName
  1195. //
  1196. FitInBuffer = NwlibCopyStringToBuffer(
  1197. PrinterName,
  1198. wcslen(PrinterName),
  1199. (LPCWSTR) *FixedPortion,
  1200. EndOfVariableData,
  1201. &pJobInfo2->pPrinterName
  1202. );
  1203. ASSERT(FitInBuffer);
  1204. //
  1205. // UserName
  1206. //
  1207. FitInBuffer = NwlibCopyStringToBuffer(
  1208. UserName,
  1209. wcslen(UserName),
  1210. (LPCWSTR) *FixedPortion,
  1211. EndOfVariableData,
  1212. &pJobInfo2->pUserName
  1213. );
  1214. ASSERT(FitInBuffer);
  1215. //
  1216. // Description
  1217. //
  1218. FitInBuffer = NwlibCopyStringToBuffer(
  1219. JobDescription,
  1220. wcslen(JobDescription),
  1221. (LPCWSTR) *FixedPortion,
  1222. EndOfVariableData,
  1223. &pJobInfo2->pDocument
  1224. );
  1225. ASSERT(FitInBuffer);
  1226. }
  1227. if (!FitInBuffer)
  1228. return ERROR_INSUFFICIENT_BUFFER;
  1229. return NO_ERROR;
  1230. }
  1231. DWORD
  1232. ConvertToSystemTime(
  1233. IN JOBTIME JobTime,
  1234. OUT LPSYSTEMTIME pSystemTime
  1235. )
  1236. /*++
  1237. Routine Description:
  1238. Arguments:
  1239. JobTime -
  1240. pSystemTime -
  1241. Return Value:
  1242. --*/
  1243. {
  1244. FILETIME fileTimeLocal, fileTimeUTC;
  1245. pSystemTime->wYear = JobTime[0] + 1900;
  1246. pSystemTime->wMonth = JobTime[1];
  1247. pSystemTime->wDay = JobTime[2];
  1248. pSystemTime->wDayOfWeek = 0;
  1249. pSystemTime->wHour = JobTime[3];
  1250. pSystemTime->wMinute = JobTime[4];
  1251. pSystemTime->wSecond = JobTime[5];
  1252. pSystemTime->wMilliseconds = 0;
  1253. if ( ( !SystemTimeToFileTime( pSystemTime, &fileTimeLocal ) )
  1254. || ( !LocalFileTimeToFileTime( &fileTimeLocal, &fileTimeUTC ) )
  1255. || ( !FileTimeToSystemTime( &fileTimeUTC, pSystemTime ) )
  1256. )
  1257. {
  1258. KdPrint(("NWWORKSTATION: Time Conversion Error = %d\n",GetLastError()));
  1259. return GetLastError();
  1260. }
  1261. return NO_ERROR;
  1262. }
  1263. #ifndef NOT_USED
  1264. DWORD
  1265. NwCreateQueue ( IN HANDLE hServer,
  1266. IN LPWSTR pszQueue,
  1267. OUT LPDWORD pQueueId
  1268. )
  1269. /*+++
  1270. Routine Description:
  1271. Uses the handle opened to a server to create a queue on the server.
  1272. Return the Queue Id if successful.
  1273. Arguments:
  1274. hServer : Handle to the file Server
  1275. pszQueue : Name of the queue that you are creating on the server
  1276. pQueueId : Address of QueueId
  1277. Return Value:
  1278. An error condition as it arises.
  1279. NO_ERROR: Successful in adding printer name
  1280. ERROR : otherwise
  1281. --*/
  1282. {
  1283. NTSTATUS ntstatus;
  1284. WORD ObjectType;
  1285. UNICODE_STRING UQueueName;
  1286. OEM_STRING OemQueueName;
  1287. *pQueueId = 0;
  1288. #if DBG
  1289. IF_DEBUG(PRINT) {
  1290. KdPrint(("NWWORKSTATION: NwCreateQueue : %ws\n",
  1291. pszQueue));
  1292. }
  1293. #endif
  1294. RtlInitUnicodeString( &UQueueName, pszQueue);
  1295. ntstatus = RtlUnicodeStringToOemString( &OemQueueName, &UQueueName, TRUE);
  1296. if ( NT_SUCCESS(ntstatus))
  1297. {
  1298. ntstatus = NwlibMakeNcp(
  1299. hServer,
  1300. FSCTL_NWR_NCP_E3H,
  1301. 174,
  1302. 6,
  1303. "bwpbp|d",
  1304. 0x64, //Create Queue
  1305. 0x0003, // Queue Type = Print Queue
  1306. OemQueueName.Buffer, //Queue Name
  1307. 0x00, // Directory Handle
  1308. "SYS:SYSTEM", //queue created in SYS:SYSTEM directory
  1309. pQueueId
  1310. );
  1311. }
  1312. else
  1313. {
  1314. goto Exit;
  1315. }
  1316. if ( NT_SUCCESS(ntstatus)) {
  1317. #if DBG
  1318. IF_DEBUG(ENUM) {
  1319. KdPrint(("NWWORKSTATION: NwCreateQueue successful\n" ));
  1320. }
  1321. #endif
  1322. }
  1323. else
  1324. goto FreeExit;
  1325. // Change Property Security on Q_OPERATORS
  1326. ntstatus = NwlibMakeNcp (
  1327. hServer,
  1328. FSCTL_NWR_NCP_E3H,
  1329. 70,
  1330. 2,
  1331. "bwpbp|",
  1332. 0x3B,
  1333. 0x0003,
  1334. OemQueueName.Buffer,
  1335. 0x1, //New Property security
  1336. "Q_OPERATORS"
  1337. );
  1338. if ( NT_SUCCESS(ntstatus)) {
  1339. #if DBG
  1340. IF_DEBUG(PRINT) {
  1341. KdPrint(("NWWORKSTATION: Change Property Security successful\n" ));
  1342. }
  1343. #endif
  1344. }
  1345. else
  1346. //unable to add new property security, so destroy queue and go to end
  1347. {
  1348. (void) NwDestroyQueue( hServer,
  1349. *pQueueId );
  1350. goto FreeExit;
  1351. }
  1352. // Add Bindery Object of Type Queue to Set
  1353. ntstatus = NwlibMakeNcp (
  1354. hServer,
  1355. FSCTL_NWR_NCP_E3H, // Bindery function
  1356. 122,
  1357. 2,
  1358. "bwppwp|",
  1359. 0x41,
  1360. 0x0003,
  1361. OemQueueName.Buffer,
  1362. "Q_OPERATORS",
  1363. 0x0001,
  1364. "SUPERVISOR"
  1365. );
  1366. if ( NT_SUCCESS(ntstatus)) {
  1367. #if DBG
  1368. IF_DEBUG(PRINT) {
  1369. KdPrint(("NWWORKSTATION: Add Bindery Object:Q_OPERATORS\n" ));
  1370. }
  1371. #endif
  1372. }
  1373. else
  1374. {
  1375. (void)NwDestroyQueue(hServer,*pQueueId);
  1376. goto FreeExit;
  1377. }
  1378. // Add Bindery Object to Set of Q_USERS
  1379. ntstatus = NwlibMakeNcp (
  1380. hServer,
  1381. FSCTL_NWR_NCP_E3H, // Bindery function
  1382. 122,
  1383. 2,
  1384. "bwppwp|",
  1385. 0x41,
  1386. 0x0003,
  1387. OemQueueName.Buffer,
  1388. "Q_USERS",
  1389. 0x0002,
  1390. "EVERYONE"
  1391. );
  1392. // bunch of parameters to Add Bindery Object to Set Q_USERS
  1393. if ( NT_SUCCESS(ntstatus)) {
  1394. #if DBG
  1395. IF_DEBUG(PRINT) {
  1396. KdPrint(("NWWORKSTATION: AddBinderyObjecttoSet Q_USERS\n" ));
  1397. }
  1398. #endif
  1399. }
  1400. FreeExit: RtlFreeOemString( &OemQueueName);
  1401. Exit:
  1402. return NwMapBinderyCompletionCode(ntstatus);
  1403. }
  1404. DWORD
  1405. NwAssocPServers ( IN HANDLE hServer,
  1406. IN LPWSTR pszQueue,
  1407. IN LPWSTR pszPServer
  1408. )
  1409. /*+++
  1410. Routine Description:
  1411. Associates a list of Q Servers with a queue id. This list is supplied
  1412. to this routine as pszPServer with entries separated by semicolons
  1413. Arguments:
  1414. hServer : Handle to the file Server
  1415. pszQueue : Name of the queue to which to associate the Q servers
  1416. pszPServer : List of Q Servers.
  1417. Return Value:
  1418. An error condition as it arises.
  1419. 0x0 is returned if there is no error
  1420. --*/
  1421. {
  1422. LPWSTR pszPServerlist = NULL;
  1423. LPWSTR pszNextPServer = NULL;
  1424. DWORD err = 0x00000000 ;
  1425. NTSTATUS ntstatus ;
  1426. UNICODE_STRING UQueueName, UNextPServer;
  1427. OEM_STRING OemQueueName,OemNextPServer;
  1428. if (pszPServer == NULL)
  1429. return NO_ERROR;
  1430. if((pszPServerlist = AllocNwSplStr(pszPServer)) == NULL)
  1431. {
  1432. err = ERROR_NOT_ENOUGH_MEMORY;
  1433. return err;
  1434. }
  1435. RtlInitUnicodeString( &UQueueName, pszQueue);
  1436. ntstatus = RtlUnicodeStringToOemString( &OemQueueName, &UQueueName, TRUE);
  1437. if (! NT_SUCCESS(ntstatus))
  1438. {
  1439. goto Exit;
  1440. }
  1441. while( (pszNextPServer = GetNextElement(&pszPServerlist, L';')) != NULL )
  1442. {
  1443. RtlInitUnicodeString( &UNextPServer, pszNextPServer);
  1444. ntstatus = RtlUnicodeStringToOemString( &OemNextPServer, &UNextPServer, TRUE);
  1445. if ( !NT_SUCCESS(ntstatus))
  1446. {
  1447. RtlFreeOemString(&OemNextPServer);
  1448. goto Exit;
  1449. }
  1450. //NwlibMakeNcp should associate a print server with a printer
  1451. // Add Bindery Object to Set
  1452. ntstatus = NwlibMakeNcp (
  1453. hServer,
  1454. FSCTL_NWR_NCP_E3H, // Bindery function
  1455. 122,
  1456. 2,
  1457. "bwppwp|",
  1458. 0x41,
  1459. 0x0003,
  1460. OemQueueName.Buffer,
  1461. "Q_SERVERS",
  1462. 0x0007, // Object of type Print Server
  1463. OemNextPServer.Buffer
  1464. );
  1465. RtlFreeOemString(&OemNextPServer);
  1466. if (!( NT_SUCCESS(ntstatus)))
  1467. {
  1468. RtlFreeOemString(&OemNextPServer);
  1469. goto Exit;
  1470. }
  1471. }
  1472. RtlFreeOemString(&OemQueueName);
  1473. Exit:
  1474. return NwMapBinderyCompletionCode(ntstatus);
  1475. }
  1476. DWORD
  1477. NwDestroyQueue (HANDLE hServer,
  1478. DWORD dwQueueId)
  1479. /*+++
  1480. Routine Description:
  1481. Makes the Ncp call to destroy the queue given by dwQueueId
  1482. Arguments:
  1483. dwQueueId : Id of the queue you are creating.
  1484. Return Value:
  1485. An error condition as it arises.
  1486. 0x0 is returned if there is no error
  1487. ---*/
  1488. {
  1489. NTSTATUS ntstatus;
  1490. ntstatus = NwlibMakeNcp(
  1491. hServer,
  1492. FSCTL_NWR_NCP_E3H,
  1493. 7,
  1494. 2,
  1495. "bd|",
  1496. 0x65,
  1497. dwQueueId
  1498. );
  1499. #if DBG
  1500. if ( NT_SUCCESS(ntstatus)) {
  1501. IF_DEBUG(PRINT) {
  1502. KdPrint(("NWWORKSTATION: Queue successfully destroyed\n"));
  1503. }
  1504. }
  1505. #endif
  1506. return NwMapBinderyCompletionCode(ntstatus);
  1507. }
  1508. #endif // #ifndef NOT_USED