public void PauseNewJobsProc(List<string> printersToPause) { if (printersToPause == null || printersToPause.Count == 0) { return; } // fetch the printer handles using (var printerHandlesDisposer = InteropHelpers.HandleArrayDisposer.NewReturningBool(Natives.Winspool.ClosePrinter)) { foreach (var printerName in printersToPause) { IntPtr printerHandle; if (!Natives.Winspool.OpenPrinter(printerName, out printerHandle, IntPtr.Zero) || printerHandle == Natives.Constants.INVALID_HANDLE_VALUE) { throw new InteropHelpers.FatalNativeCodeException("failed to open printer " + printerName, "OpenPrinter2"); } printerHandlesDisposer.Handles.Add(printerHandle); } // prepare notification options using (var fieldsArrayBytes = new InteropHelpers.HGlobalBytes(1 * sizeof(ushort))) using (var notifyOptionsTypeSerializer = new InteropHelpers.StructSerializer<Natives.Structures.PRINTER_NOTIFY_OPTIONS_TYPE>()) using (var notifyOptionsSerializer = new InteropHelpers.StructSerializer<Natives.Structures.PRINTER_NOTIFY_OPTIONS>()) { Marshal.WriteInt16(fieldsArrayBytes.Pointer, (short)Natives.Constants.PRINTER_NOTIFY_FIELD_STATUS); var notifyOptionsType = new Natives.Structures.PRINTER_NOTIFY_OPTIONS_TYPE { Type = Natives.Constants.JOB_NOTIFY_TYPE, Reserved0 = 0, Reserved1 = 0, Reserved2 = 0, Count = 1, Fields = fieldsArrayBytes.Pointer }; notifyOptionsTypeSerializer.TheStruct = notifyOptionsType; notifyOptionsTypeSerializer.Serialize(); var notifyOptions = new Natives.Structures.PRINTER_NOTIFY_OPTIONS { Version = 2, Flags = 0, Count = 1, Types = notifyOptionsTypeSerializer.StructPointer }; notifyOptionsSerializer.TheStruct = notifyOptions; notifyOptionsSerializer.Serialize(); // fetch the notifications using (var notificationDisposer = InteropHelpers.HandleArrayDisposer.NewReturningBool(Natives.Winspool.FindClosePrinterChangeNotification)) { foreach (var printerHandle in printerHandlesDisposer.Handles) { IntPtr notif = Natives.Winspool.FindFirstPrinterChangeNotification(printerHandle, Natives.Constants.PRINTER_CHANGE_ADD_JOB, 0, notifyOptionsSerializer.StructPointer); if (notif == Natives.Constants.INVALID_HANDLE_VALUE) { throw new InteropHelpers.FatalNativeCodeException("failed to subscribe to notifications for a printer", "FindFirstPrinterChangeNotification"); } notificationDisposer.Handles.Add(notif); } // prepare the array for waiting IntPtr[] waitHandles = new IntPtr[notificationDisposer.Handles.Count + 1]; waitHandles[0] = StopSemaphore; notificationDisposer.Handles.CopyTo(waitHandles, 1); // and we wait and we wonder for (;;) { uint waitResult = Natives.Kernel32.WaitForMultipleObjects((uint)waitHandles.Length, waitHandles, false, Natives.Constants.INFINITE); if (waitResult >= waitHandles.Length) { throw new InteropHelpers.FatalNativeCodeException("waiting for printers failed", "WaitForMultipleObjects"); } else if (waitResult == 0) { // stopping semaphore triggered break; } IntPtr triggeredNotif = waitHandles[waitResult]; uint whatChanged; IntPtr notifyInfoPointer; if (!Natives.Winspool.FindNextPrinterChangeNotification(triggeredNotif, out whatChanged, notifyOptionsSerializer.StructPointer, out notifyInfoPointer)) { throw new InteropHelpers.NativeCodeException("fetching change notification failed", "FindNextPrinterChangeNotification"); } using (var notifyInfoDisposer = InteropHelpers.HandleArrayDisposer.NewReturningBool(Natives.Winspool.FreePrinterNotifyInfo)) using (var notifyInfoSerializer = new InteropHelpers.StructSerializer<Natives.Structures.PRINTER_NOTIFY_INFO>()) { var notifyInfo = SpecialStructures.PrinterNotifyInfo.Deserialize(notifyInfoPointer); if (notifyInfo.DataList.Count == 0) { throw new InteropHelpers.NativeCodeException("add-job notification with no data?!", "FindNextPrinterChangeNotification"); } if (notifyInfo.DataList[0].Type != Natives.Constants.JOB_NOTIFY_TYPE) { throw new InteropHelpers.NativeCodeException("add-job notification with no job-related data?!", "FindNextPrinterChangeNotification"); } // pause it // (need to subtract 1 because 0 is the stopping semaphore) if (!Natives.Winspool.SetJob(printerHandlesDisposer.Handles[(int)waitResult - 1], notifyInfo.DataList[0].ID, 0, IntPtr.Zero, Natives.Constants.JOB_CONTROL_PAUSE)) { throw new InteropHelpers.NativeCodeException("pausing job failed", "SetJob"); } } } } } } }
public void PauseNewJobsProc(List <string> printersToPause) { if (printersToPause == null || printersToPause.Count == 0) { return; } // fetch the printer handles using (var printerHandlesDisposer = InteropHelpers.HandleArrayDisposer.NewReturningBool(Natives.Winspool.ClosePrinter)) { foreach (var printerName in printersToPause) { IntPtr printerHandle; if (!Natives.Winspool.OpenPrinter(printerName, out printerHandle, IntPtr.Zero) || printerHandle == Natives.Constants.INVALID_HANDLE_VALUE) { throw new InteropHelpers.FatalNativeCodeException("failed to open printer " + printerName, "OpenPrinter2"); } printerHandlesDisposer.Handles.Add(printerHandle); } // prepare notification options using (var fieldsArrayBytes = new InteropHelpers.HGlobalBytes(1 * sizeof(ushort))) using (var notifyOptionsTypeSerializer = new InteropHelpers.StructSerializer <Natives.Structures.PRINTER_NOTIFY_OPTIONS_TYPE>()) using (var notifyOptionsSerializer = new InteropHelpers.StructSerializer <Natives.Structures.PRINTER_NOTIFY_OPTIONS>()) { Marshal.WriteInt16(fieldsArrayBytes.Pointer, (short)Natives.Constants.PRINTER_NOTIFY_FIELD_STATUS); var notifyOptionsType = new Natives.Structures.PRINTER_NOTIFY_OPTIONS_TYPE { Type = Natives.Constants.JOB_NOTIFY_TYPE, Reserved0 = 0, Reserved1 = 0, Reserved2 = 0, Count = 1, Fields = fieldsArrayBytes.Pointer }; notifyOptionsTypeSerializer.TheStruct = notifyOptionsType; notifyOptionsTypeSerializer.Serialize(); var notifyOptions = new Natives.Structures.PRINTER_NOTIFY_OPTIONS { Version = 2, Flags = 0, Count = 1, Types = notifyOptionsTypeSerializer.StructPointer }; notifyOptionsSerializer.TheStruct = notifyOptions; notifyOptionsSerializer.Serialize(); // fetch the notifications using (var notificationDisposer = InteropHelpers.HandleArrayDisposer.NewReturningBool(Natives.Winspool.FindClosePrinterChangeNotification)) { foreach (var printerHandle in printerHandlesDisposer.Handles) { IntPtr notif = Natives.Winspool.FindFirstPrinterChangeNotification(printerHandle, Natives.Constants.PRINTER_CHANGE_ADD_JOB, 0, notifyOptionsSerializer.StructPointer); if (notif == Natives.Constants.INVALID_HANDLE_VALUE) { throw new InteropHelpers.FatalNativeCodeException("failed to subscribe to notifications for a printer", "FindFirstPrinterChangeNotification"); } notificationDisposer.Handles.Add(notif); } // prepare the array for waiting IntPtr[] waitHandles = new IntPtr[notificationDisposer.Handles.Count + 1]; waitHandles[0] = StopSemaphore; notificationDisposer.Handles.CopyTo(waitHandles, 1); // and we wait and we wonder for (;;) { uint waitResult = Natives.Kernel32.WaitForMultipleObjects((uint)waitHandles.Length, waitHandles, false, Natives.Constants.INFINITE); if (waitResult >= waitHandles.Length) { throw new InteropHelpers.FatalNativeCodeException("waiting for printers failed", "WaitForMultipleObjects"); } else if (waitResult == 0) { // stopping semaphore triggered break; } IntPtr triggeredNotif = waitHandles[waitResult]; uint whatChanged; IntPtr notifyInfoPointer; if (!Natives.Winspool.FindNextPrinterChangeNotification(triggeredNotif, out whatChanged, notifyOptionsSerializer.StructPointer, out notifyInfoPointer)) { throw new InteropHelpers.NativeCodeException("fetching change notification failed", "FindNextPrinterChangeNotification"); } using (var notifyInfoDisposer = InteropHelpers.HandleArrayDisposer.NewReturningBool(Natives.Winspool.FreePrinterNotifyInfo)) using (var notifyInfoSerializer = new InteropHelpers.StructSerializer <Natives.Structures.PRINTER_NOTIFY_INFO>()) { var notifyInfo = SpecialStructures.PrinterNotifyInfo.Deserialize(notifyInfoPointer); if (notifyInfo.DataList.Count == 0) { throw new InteropHelpers.NativeCodeException("add-job notification with no data?!", "FindNextPrinterChangeNotification"); } if (notifyInfo.DataList[0].Type != Natives.Constants.JOB_NOTIFY_TYPE) { throw new InteropHelpers.NativeCodeException("add-job notification with no job-related data?!", "FindNextPrinterChangeNotification"); } // pause it // (need to subtract 1 because 0 is the stopping semaphore) if (!Natives.Winspool.SetJob(printerHandlesDisposer.Handles[(int)waitResult - 1], notifyInfo.DataList[0].ID, 0, IntPtr.Zero, Natives.Constants.JOB_CONTROL_PAUSE)) { throw new InteropHelpers.NativeCodeException("pausing job failed", "SetJob"); } } } } } } }