WaitForPrnPipeWithPriority

 

#include “BLICECTR.H”

 

BOOL PASCAL WaitForPrnPipeWithPriority(LPWSTR pszPipeName, HWND hMsgWnd, DWORD dwMessageNum, int nPri);

 

Description

Starts the Pipe Message Capture thread with desired thread priority. The thread receives messages from the Printer Driver through a named pipe, translates them to regular Window messages and sends them to the Window specified by hMsgWnd. This way the application can easily handle the pipe messages sent by the Printer Driver without directly dealing with the named pipe.

 

The WaitForPrnPipe function is non-blocking, it returns immediately after the Message Capture thread is created. To stop the Message Capture thread, the application should call EndWaitPrnPipe. The priority of the Message Capture thread can NOT be set using the deprecated SetListeningPriority function.

 

Parameters

LPWSTR pszPipeName               - pointer to a NULL terminated UNICODE string that contains the pipe name, including the \\.\pipe\ prefix. To see how to construct the pipe name, refer to the Code Example section below.
HWND hMsgWnd                           - A Window handle. The BLICECTR.DLL will send window messages to this window. The message loop of the specified window should accept and handle the type of window messages that are specified in dwMessageNum.
DWORD dwMessageNum            - Message number. The message number of the window message to send, if a pipe message arrives. Can be any unused number above WM_USER, e.g: WM_USER + 1000.

int nPri - sets  the  priority of the thread which waits for pipe messages. Valid values are the following:

 

THREAD_PRIORITY_LOWEST
THREAD_PRIORITY_BELOW_NORMAL
THREAD_PRIORITY_NORMAL
THREAD_PRIORITY_HIGHEST
THREAD_PRIORITY_ABOVE_NORMAL
THREAD_PRIORITY_ERROR_RETURN
THREAD_PRIORITY_TIME_CRITICAL
THREAD_PRIORITY_IDLE

 

Return value

TRUE if the message capture thread was started successfully, FALSE otherwise.

 

Programming Notes

The window that receives the messages must be created in the same process where the WaitForPrnPipeWithPriority function is called.

 

Code Example

 

C++ Example

 

GetSessionID(lpDevMode, &dwSessionID);

swprintf(szPipeName, L"\\\\.\\pipe\\%s%d", GetInterfaceName(lpDevMode),dwSessionID);

WaitForPrnPipeWithPriority(szPipeName, hWnd, WM_USER + 1000, THREAD_PRIORITY_TIME_CRITICAL);

 

C# example

 

        //Black Ice Message Capture functions from blicectr.dll

        //Messages reserved for use by the system.

        public const int WM_USER = 0x0400;

 

        //Base priority of 15 for NORMAL_PRIORITY_CLASS processes.

        public const int THREAD_PRIORITY_TIME_CRITICAL = 15;

 

        [DllImport("blicectr.dll", EntryPoint = "WaitForPrnPipeWithPriority", CharSet = CharSet.Unicode)]

        private static extern int WaitForPrnPipeWithPriority(string pszPipeName, IntPtr hMsgWnd, int dwMessageNum, int nPri);

 

        [DllImport("blicectr.dll", EntryPoint = "EndWaitPrnPipe", CharSet = CharSet.Unicode)]

        private static extern int EndWaitPrnPipe(string pszPipeName);

 

        //Locks a global memory object and returns a pointer to the first byte of the object's memory block.

        [DllImport("kernel32.dll")]

        static extern IntPtr GlobalLock(IntPtr hMem);

 

        //Decrements the lock count associated with a memory object that was allocated with GMEM_MOVEABLE. This function has no effect on memory objects allocated with GMEM_FIXED.

        [DllImport("kernel32.dll")]

        [return: MarshalAs(UnmanagedType.Bool)]

        static extern bool GlobalUnlock(IntPtr hMem);

 

        //Frees the specified global memory object and invalidates its handle.

        [DllImport("kernel32.dll")]

        static extern IntPtr GlobalFree(IntPtr hMem);

 

        //Retrieves the current size of the specified global memory object, in bytes.

        [DllImport("kernel32.dll")]

        static extern UIntPtr GlobalSize(IntPtr hMem);

 

        //Printer Driver Messaging Interface structure for Printer Drivers 14.97 and earlier

        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]

        struct TSPrnMessageV1

        {

            public uint dwMessage;

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 260)]

            public string szDocName;

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 260)]

            public string szFileName;

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 260)]

            public string szPrinterName;

            public int nPageNumber;

            [MarshalAsAttribute(UnmanagedType.Bool)]

            public bool fAppendPage;

            [MarshalAsAttribute(UnmanagedType.Bool)]

            public bool fPortrait;

            public uint dwOCRDataType;

        };

 

        //Printer Driver Messaging Interface structure for Printer Drivers version 14.98 and newer

        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]

        struct TSPrnMessage

        {

            public TSPrnMessage(TSPrnMessageV1 v1)

            {

                dwMessage = v1.dwMessage;

                szDocName = v1.szDocName;

                szFileName = v1.szFileName;

                szPrinterName = v1.szPrinterName;

                nPageNumber = v1.nPageNumber;

                fAppendPage = v1.fAppendPage;

                fPortrait = v1.fPortrait;

                dwJobID = 0;

 

                if (dwMessage == BLACKICE_MESSAGE_STARTDOC || dwMessage == BLACKICE_MESSAGE_ENDDOC)

                {

                    szOutputFileName = "";

                    szGroupFileName = v1.szFileName;

                }

                else if (dwMessage == BLACKICE_MESSAGE_STARTPAGE || dwMessage == BLACKICE_MESSAGE_ENDPAGE)

                {

                    szOutputFileName = v1.szFileName;

                    szGroupFileName = "";

                }

                else

                {

                    szOutputFileName = "";

                    szGroupFileName = "";

                }

 

                dwOCRDataType = v1.dwOCRDataType;

            }

 

            public uint dwMessage;

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 260)]

            public string szDocName;

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 260)]

            public string szFileName;

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 260)]

           public string szPrinterName;

            public int nPageNumber;

            [MarshalAsAttribute(UnmanagedType.Bool)]

            public bool fAppendPage;

            [MarshalAsAttribute(UnmanagedType.Bool)]

            public bool fPortrait;

            public uint dwJobID;

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 260)]

            public string szOutputFileName;

            [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 260)]

            public string szGroupFileName;

 

            public uint dwOCRDataType;

        };

 

        // Printer Message identifiers

        public const int BLACKICE_MESSAGE_STARTDOC = 0x00000001;

        public const int BLACKICE_MESSAGE_STARTPAGE = 0x00000002;

        public const int BLACKICE_MESSAGE_ENDPAGE = 0x00000003;

        public const int BLACKICE_MESSAGE_ENDDOC = 0x00000004;

        public const int BLACKICE_MESSAGE_ABORT = 0x00000005;

        public const int BLACKICE_MESSAGE_ERROR = 0x00000006;

 

        public const int BLACKICE_MESSAGE_DEVMODE = 0x00000007;

        public const int BLACKICE_MESSAGE_MEMIMAGE = 0x00000008;

 

        public const int BLACKICE_MESSAGE_OCR = 0x00000009;

        public const int BLACKICE_MESSAGE_TEXT = 0x0000000A;

 

        public const int BI_OCR_MEM_FORMAT_TEXT = 0x00000001;

        public const int BI_OCR_MEM_FORMAT_HOCR_HEADER = 0x00000002;

        public const int BI_OCR_MEM_FORMAT_HOCR_PAGE = 0x00000003;

        public const int BI_OCR_MEM_FORMAT_HOCR_FOOTER = 0x00000004;

 

BiHelper class with GetPrinterSessionID and GetPrinterInterfaceName functions for WaitForPrnPipeWithPriority function

 

                using System.Runtime.InteropServices;

       class BiHelper

       {

              //Black Ice Devmode functions from BlackIceDEVMODE.dll

              [DllImport("BlackIceDEVMODE.dll", EntryPoint = "LoadBlackIceDEVMODE", CharSet = CharSet.Unicode)]

              private static extern IntPtr LoadBlackIceDEVMODE(string szPrinter);

 

              [DllImport("BlackIceDEVMODE.dll", EntryPoint = "ReleaseBlackIceDEVMODE", CharSet = CharSet.Unicode)]

              private static extern bool ReleaseBlackIceDEVMODE(IntPtr lDevmode);

 

              [DllImport("BlackIceDEVMODE.dll", EntryPoint = "GetSessionID", CharSet = CharSet.Unicode)]

              private static extern int GetSessionID(IntPtr lDevmode, ref int iSessionID);

 

              [DllImport("BlackIceDEVMODE.dll", EntryPoint = "GetInterfaceName", CharSet = CharSet.Unicode)]

              private static extern IntPtr GetInterfaceName(IntPtr lDevmode);

 

              //Get session ID from Printer name

              public int GetPrinterSessionID(string szPrinterName)

              {

                     int iRet = 0;

 

                     // Load the devmode

                     IntPtr lDevmode = LoadBlackIceDEVMODE(szPrinterName);

 

                     if ((Int32)lDevmode > 0)

                     {

                           // Get interface ID of the printer driver

                           GetSessionID(lDevmode, ref iRet);

                           // Release the DEVMODE

                           ReleaseBlackIceDEVMODE(lDevmode);

                     }

 

                     // Return printer Session ID

                     return iRet;

              }

 

              //Get interface name from Printer name

              public string GetPrinterInterfaceName(string szPrinterName)

              {

                     string sInterfaceName = string.Empty;

 

                     // Load the devmode

                     IntPtr lDevmode = LoadBlackIceDEVMODE(szPrinterName);

 

                     if ((Int32)lDevmode > 0)

                     {

                           // Get interface ID of the printer driver

                           IntPtr ipInterfaceName = GetInterfaceName(lDevmode);

                           sInterfaceName = Marshal.PtrToStringUni(ipInterfaceName);

 

                           // Release the DEVMODE

                           ReleaseBlackIceDEVMODE(lDevmode);

                     }

 

                     // Return printer Interface Name

                     return sInterfaceName;

              }

       }

 

Once imported, one can use the WaitForPrnPipeWithPriority function in the C# code as in the following example

 

                //Printer driver name

       string sPrinterName = "Printer Name";

 

       //Create an object of type BiHelper

         BiHelper helper = new BiHelper();

 

         //Interface name of Printer driver

         string sInterfaceName = helper.GetPrinterInterfaceName(sPrinterName);

 

         //Session ID of Printer driver

         int iSessionID = helper.GetPrinterSessionID(sPrinterName);

 

         //Pipe name

         szPipeName = @"\\.\pipe\" + sInterfaceName + iSessionID.ToString();

 

         //Start listening for messages. The pipe messages will be forwarded to the WndProc function as WM_USER + 1000 messages

         WaitForPrnPipeWithPriority(szPipeName, this.Handle, WM_USER + 1000, THREAD_PRIORITY_TIME_CRITICAL);

 

                    //WndProc method to handle operating system messages

                        protected override void WndProc(ref Message message)

        {

            if (message.Msg == WM_USER + 1000) // WM_USER + 1000 is the same value that is passed to the WaitForPrnPipeWithPriority function

            {

                //Read the Printer Driver Messaging Interface structure from the WParam parameter

                IntPtr pParams = GlobalLock(message.WParam);

                TSPrnMessage sParams;

 

                // The larger message capture structure is available since Printer Driver Version 14.98.

                // For compatibility with older drivers, check the size of the structure to see if we recieved the

                // new structure or the old one.

                bool bNewDriver = ((int)GlobalSize(message.WParam) >= Marshal.SizeOf(typeof(TSPrnMessage)));

 

                if (bNewDriver)

                {

                    // Driver Version is 14.98 or newer, use the new structure

                    sParams = (TSPrnMessage)Marshal.PtrToStructure(pParams, typeof(TSPrnMessage));

                }

                else

                {

                    // Driver Version is 14.97 or earlier, copy what we can from the old structure

                    TSPrnMessageV1 sParamsV1;

                    sParamsV1 = (TSPrnMessageV1)Marshal.PtrToStructure(pParams, typeof(TSPrnMessageV1));

                    sParams = new TSPrnMessage(sParamsV1);

                }

 

                switch (sParams.dwMessage)

                {

                    case BLACKICE_MESSAGE_STARTDOC:

                        DisplayAndLog("Start Doc");

                        DisplayAndLog("    Printer Name: " + sParams.szPrinterName);

                        DisplayAndLog("    Document Name: " + sParams.szDocName);

                        DisplayAndLog("    Group File Name: " + sParams.szGroupFileName);

                        if (bNewDriver)

                        {

                            DisplayAndLog("    Job ID: " + sParams.dwJobID);

                        }

                        break;

 

                    case BLACKICE_MESSAGE_STARTPAGE:

                        DisplayAndLog("Start Page");

                        DisplayAndLog("    Printer Name: " + sParams.szPrinterName);

                        DisplayAndLog("    Document Name: " + sParams.szDocName);

                        DisplayAndLog("    Page Number: " + sParams.nPageNumber.ToString());

                        if (bNewDriver)

                        {

                            DisplayAndLog("    Job ID: " + sParams.dwJobID);

                            DisplayAndLog("    Output File Name: " + sParams.szOutputFileName);

                            DisplayAndLog("    Group File Name: " + sParams.szGroupFileName);

                        }

                        else

                        {

                            DisplayAndLog("    Output File Name: " + sParams.szFileName);

                        }

                        break;

 

                    case BLACKICE_MESSAGE_ENDDOC:

                        DisplayAndLog("End Doc");

                        DisplayAndLog("    Printer Name: " + sParams.szPrinterName);

                        DisplayAndLog("    Document Name: " + sParams.szDocName);

                        if (bNewDriver)

                        {

                            DisplayAndLog("    Job ID: " + sParams.dwJobID);

                            DisplayAndLog("    Output File Name: " + sParams.szOutputFileName);

                            DisplayAndLog("    Group File Name: " + sParams.szGroupFileName);

                        }

                        else

                        {

                            DisplayAndLog("    Group File Name: " + sParams.szFileName);

                        }

                        break;

 

                    case BLACKICE_MESSAGE_ENDPAGE:

                        DisplayAndLog("End Page");

                        DisplayAndLog("    Printer Name: " + sParams.szPrinterName);

                        DisplayAndLog("    Document Name: " + sParams.szDocName);

                        DisplayAndLog("    Page Number: " + sParams.nPageNumber.ToString());

                        if (bNewDriver)

                        {

                            DisplayAndLog("    Job ID: " + sParams.dwJobID);

                            DisplayAndLog("    Output File Name: " + sParams.szOutputFileName);

                            DisplayAndLog("    Group File Name: " + sParams.szGroupFileName);

                        }

                        else

                        {

                            DisplayAndLog("    Output File Name: " + sParams.szFileName);

                        }

                        break;

 

                    case BLACKICE_MESSAGE_ABORT:

                        DisplayAndLog("Abort:  Print job has been aborted");

                        if (bNewDriver)

                        {

                            DisplayAndLog("    Printer Name: " + sParams.szPrinterName);

                            DisplayAndLog("    Document Name: " + sParams.szDocName);

                            DisplayAndLog("    Job ID: " + sParams.dwJobID);

                        }

                        break;

 

                    case BLACKICE_MESSAGE_DEVMODE:

                        DisplayAndLog("ChangeDevmode");

                        if (bNewDriver)

                        {

                            DisplayAndLog("    Printer Name: " + sParams.szPrinterName);

                            DisplayAndLog("    Document Name: " + sParams.szDocName);

                            DisplayAndLog("    Job ID: " + sParams.dwJobID);

                        }

 

 

                        // ChangeDevmode message received, read the DEVMODE structure from the LParam parameter and configure it

                        IntPtr ipDevmode = message.LParam;

                        if ((int)ipDevmode > 0)

                        {

                            // modify the BlackIceDEVMODE structure as needed

                            // do not modify the standard DEVMDOE structure, (pDevMode->DM)

                            // only modify the extended part of the BlackIceDEVMODE structure.

                            // DO NOT MAKE TIME CONSUMING OPEARTIONS HERE

                            // The printer drive will wait a maximum of 2 seconds for an updated

                            // BlackIceDEVMODE structure.

                        }

                        break;

 

                    case BLACKICE_MESSAGE_ERROR:

                        DisplayAndLog("Error message was received.");

                        DisplayAndLog("    Error Code: " + message.LParam.ToString());

                        break;

 

                    case BLACKICE_MESSAGE_MEMIMAGE:

                        ipDevmode = message.LParam;

                       if ((int)ipDevmode > 0 && (int)pParams > 0)

                        {

                            //Printer driver name

                            string sPrinterName = CurrentPrinter.Text;

 

                            //Create an object of type BiHelper

                            BiHelper helper = new BiHelper();

 

                            //File extension of Printer driver

                            string sFileExt = helper.GetFileExtension(sPrinterName);

 

                            string saveFileName = string.Empty;

                            saveFileName = GetCustomTempFile("BLI", sFileExt);

 

                            //Get pointer to the image data

                            IntPtr pImage = GlobalLock(message.LParam);

                           //Get the size of the image data

                            int dwSize = (int)GlobalSize(message.LParam);

                            //Copy the image data from the unmanaged memory to a byte array

                            byte[] buffer = new byte[dwSize];

                            Marshal.Copy(pImage, buffer, 0, dwSize);

 

                            //Write image data to a file

                            File.WriteAllBytes(saveFileName, buffer);

 

                            if (bNewDriver)

                            {

                                DisplayAndLog("MemoryImageEx message was received.");

                                DisplayAndLog("    Printer Name: " + sParams.szPrinterName);

                                DisplayAndLog("    Document Name: " + sParams.szDocName);

                                DisplayAndLog("    Job ID: " + sParams.dwJobID);

                                DisplayAndLog("    The file has been saved to: " + saveFileName);

 

                            }

                            else

                            {

                                DisplayAndLog("Print to Memory message received and the file has been saved to: " + saveFileName);

                            }

                            //Free unmanaged memory

                            GlobalUnlock(message.LParam);

                            GlobalFree(message.LParam);

                        }

                       

                        break;

 

                    case BLACKICE_MESSAGE_OCR:

                        ipDevmode = message.LParam;

                        if (ipDevmode.ToInt32() > 0)

                        {

                            if (bNewDriver)

                            {

                                //Printer driver name

                                string sPrinterName = CurrentPrinter.Text;

 

                                //Get pointer to the OCR data

                                IntPtr pOCR = GlobalLock(message.LParam);

 

                                string OCRData = Marshal.PtrToStringUni(pOCR);

                                DisplayAndLog("OCR message was received.");

                                DisplayAndLog("    Printer Name: " + sParams.szPrinterName);

                                DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString());

                                DisplayAndLog("    Document Name: " + sParams.szDocName);

 

                                switch (sParams.dwOCRDataType)

                                {

                                    case BI_OCR_MEM_FORMAT_TEXT:

                                        try

                                        {

                                            DisplayAndLog("    The OCR Data Type is TEXT (1))");

                                            DisplayAndLog("    The OCR Data is: " + OCRData);

 

                                            string saveFileName = string.Empty;

                                            saveFileName = GetCustomTempFile("BLI", "txt");

 

                                            //Write OCR data to a file

                                            File.WriteAllText(saveFileName, OCRData);

                                        }

                                        catch (Exception Ex)

                                        {

                                            DisplayAndLog("    " + Ex.ToString());

                                        }

 

                                        break;

 

                                    case BI_OCR_MEM_FORMAT_HOCR_HEADER:

                                        try

                                        {

                                            DisplayAndLog("    The OCR Data Type is hOCR header (2)");

                                            DisplayAndLog("    The OCR Data is: " + OCRData);

                                            sHOCRFileName = GetCustomTempFile("BLI", "html");

 

                                            //Write OCR header to a file

                                            File.WriteAllText(sHOCRFileName, OCRData);

                                            DisplayAndLog("    The file has been saved to: " + sHOCRFileName);

                                       }

                                        catch (Exception Ex)

                                        {

                                            DisplayAndLog("    " + Ex.ToString());

                                        }

 

                                        break;

 

                                    case BI_OCR_MEM_FORMAT_HOCR_PAGE:

                                        try

                                        {

                                            DisplayAndLog("    The OCR Data Type is hOCR data (3)");

                                            DisplayAndLog("    The OCR Data is: " + OCRData);

 

                                            //Append OCR data to a file

                                            File.AppendAllText(sHOCRFileName, OCRData);

                                            DisplayAndLog("    The file has been saved to: " + sHOCRFileName);

                                        }

                                        catch (Exception Ex)

                                        {

                                            DisplayAndLog("    " + Ex.ToString());

                                        }

 

                                        break;

 

                                    case BI_OCR_MEM_FORMAT_HOCR_FOOTER:

                                        try

                                        {

                                            DisplayAndLog("    The OCR Data Type is hOCR footer (4)");

                                            DisplayAndLog("    The OCR Data is: " + OCRData);

 

                                            //Append OCR footer to a file

                                            File.AppendAllText(sHOCRFileName, OCRData);

                                            DisplayAndLog("    The file has been saved to: " + sHOCRFileName);

                                        }

                                        catch (Exception Ex)

                                        {

                                            DisplayAndLog("    " + Ex.ToString());

                                        }

 

                                        break;

                                }

                            }

                        }

 

                        break;

       case BLACKICE_MESSAGE_TEXT:

              ipDevmode = message.LParam;

              if (ipDevmode.ToInt32() > 0)

              {

                     if (bNewDriver)

                     {

                           //Get pointer to the TEXT data

                           IntPtr pTEXT = GlobalLock(message.LParam);

 

                           string TEXTData = Marshal.PtrToStringUni(pTEXT);

                           DisplayAndLog("TEXT message was received.");

                           DisplayAndLog("    Printer Name: " + sParams.szPrinterName);

                           DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString());

                           DisplayAndLog("    Document Name: " + sParams.szDocName);

                           DisplayAndLog("    Page Number: " + sParams.nPageNumber.ToString());

 

                           try

                           {

                                  //DisplayAndLog("    The TEXT Data is: " + TEXTData);

 

                                  string saveFileName = string.Empty;

                                  saveFileName = GetCustomTempFile("BLI", "txt");

 

                                 //Write OCR data to a file

                                  File.WriteAllText(saveFileName, TEXTData);

                                  DisplayAndLog("    The file has been saved to: " + saveFileName);

                           }

                           catch (Exception Ex)

                           {

                                  DisplayAndLog("    " + Ex.ToString());

                           }

                     }

              }

              break;

 

                }

 

                GlobalUnlock(message.WParam);

                GlobalFree(message.WParam);

            }

 

            base.WndProc(ref message);

        }

 

VB.NET example

Please see following example for IMPORTING the blicectr.dll functions in VB.NET code:

        'Black Ice Message Capture functions from blicectr.dll

        'Messages reserved for use by the system.

        Public Const WM_USER As Integer = &H400

 

        'Base priority of 15 for NORMAL_PRIORITY_CLASS processes.

        Public Const THREAD_PRIORITY_TIME_CRITICAL As Integer = 15

 

        Private Declare Unicode Function WaitForPrnPipeWithPriority Lib "blicectr.dll" (pszPipeName As String, hMsgWnd As IntPtr, dwMessageNum As Integer, nPri As Integer) As Integer

 

        Private Declare Unicode Function EndWaitPrnPipe Lib "blicectr.dll" (pszPipeName As String) As Integer

 

        'Locks a global memory object and returns a pointer to the first byte of the object's memory block.

        Private Declare Unicode Function GlobalLock Lib "kernel32.dll" (hMem As IntPtr) As IntPtr

 

        'Decrements the lock count associated with a memory object that was allocated with GMEM_MOVEABLE. This function has no effect on memory objects allocated with GMEM_FIXED.

        Private Declare Unicode Function GlobalUnlock Lib "kernel32.dll" (hMem As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean

 

        'Frees the specified global memory object and invalidates its handle.

        Private Declare Unicode Function GlobalFree Lib "kernel32.dll" (hMem As IntPtr) As IntPtr

 

        'Retrieves the current size of the specified global memory object, in bytes.

        Private Declare Unicode Function GlobalSize Lib "kernel32.dll" (hMem As IntPtr) As IntPtr

 

        'Printer Driver Messaging Interface structure for Printer Drivers version 14.98 and newer

        <StructLayoutAttribute(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _

        Structure TSPrnMessageV1

            Public dwMessage As UInteger

            <MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst:=260)> _

            Public szDocName As String

            <MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst:=260)> _

            Public szFileName As String

            <MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst:=260)> _

            Public szPrinterName As String

            Public nPageNumber As Integer

            <MarshalAsAttribute(UnmanagedType.Bool)> _

            Public fAppendPage As Boolean

            <MarshalAsAttribute(UnmanagedType.Bool)> _

            Public fPortrait As Boolean

        End Structure

 

        'Printer Driver Messaging Interface structure for Printer Drivers version 14.98 and newer

        <StructLayoutAttribute(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _

        Structure TSPrnMessage

            Public Sub New(v1 As TSPrnMessageV1)

                dwMessage = v1.dwMessage

                szDocName = v1.szDocName

                szFileName = v1.szFileName

                szPrinterName = v1.szPrinterName

                nPageNumber = v1.nPageNumber

                fAppendPage = v1.fAppendPage

                fPortrait = v1.fPortrait

                dwJobID = 0

 

                If dwMessage = BLACKICE_MESSAGE_STARTDOC OrElse dwMessage = BLACKICE_MESSAGE_ENDDOC Then

                    szOutputFileName = ""

                    szGroupFileName = v1.szFileName

                ElseIf dwMessage = BLACKICE_MESSAGE_STARTPAGE OrElse dwMessage = BLACKICE_MESSAGE_ENDPAGE Then

                    szOutputFileName = v1.szFileName

                    szGroupFileName = ""

                Else

                    szOutputFileName = ""

                    szGroupFileName = ""

                End If

 

                dwOCRDataType = 0

 

            End Sub

 

            Public dwMessage As UInteger

            <MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst:=260)> _

            Public szDocName As String

            <MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst:=260)> _

            Public szFileName As String

            <MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst:=260)> _

            Public szPrinterName As String

            Public nPageNumber As Integer

            <MarshalAsAttribute(UnmanagedType.Bool)> _

            Public fAppendPage As Boolean

            <MarshalAsAttribute(UnmanagedType.Bool)> _

            Public fPortrait As Boolean

            Public dwJobID As UInteger

            <MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst:=260)> _

            Public szOutputFileName As String

            <MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst:=260)> _

            Public szGroupFileName As String

            Public dwOCRDataType As UInteger

        End Structure

 

        'Printer Message identifiers

        Public Const BLACKICE_MESSAGE_STARTDOC As Integer = &H1

        Public Const BLACKICE_MESSAGE_STARTPAGE As Integer = &H2

        Public Const BLACKICE_MESSAGE_ENDPAGE As Integer = &H3

        Public Const BLACKICE_MESSAGE_ENDDOC As Integer = &H4

        Public Const BLACKICE_MESSAGE_ABORT As Integer = &H5

        Public Const BLACKICE_MESSAGE_ERROR As Integer = &H6

 

        Public Const BLACKICE_MESSAGE_DEVMODE As Integer = &H7

        Public Const BLACKICE_MESSAGE_MEMIMAGE As Integer = &H8

 

        Public Const BLACKICE_MESSAGE_OCR As Integer = &H9

        Public Const BLACKICE_MESSAGE_TEXT As Integer = &HA

 

        Public Const BI_OCR_MEM_FORMAT_TEXT As Integer = &H1

        Public Const BI_OCR_MEM_FORMAT_HOCR_HEADER As Integer = &H2

        Public Const BI_OCR_MEM_FORMAT_HOCR_PAGE As Integer = &H3

        Public Const BI_OCR_MEM_FORMAT_HOCR_FOOTER As Integer = &H4

 

BiHelper class with GetPrinterSessionID and GetPrinterInterfaceName functions for WaitForPrnPipeWithPriority function

 

Imports System.Runtime.InteropServices

 

Public Class BiHelper

 

    'Black Ice Devmode functions from BlackIceDEVMODE.dll

    Private Declare Unicode Function LoadBlackIceDEVMODE Lib "BlackIceDEVMODE.dll" (ByVal sPrinter As String) As IntPtr

 

    Private Declare Unicode Function ReleaseBlackIceDEVMODE Lib "BlackIceDEVMODE.dll" (ByVal lDevmode As IntPtr) As Boolean

 

    Private Declare Unicode Function GetSessionID Lib "BlackIceDEVMODE.dll" (lDevmode As IntPtr, ByRef iSessionID As Integer) As Integer

 

    Private Declare Unicode Function GetInterfaceName Lib "BlackIceDEVMODE.dll" (lDevmode As IntPtr) As IntPtr

 

    'Get session ID from Printer name

    Public Function GetPrinterSessionID(szPrinterName As String) As Integer

        Dim iRet As Integer = 0

 

        ' Load the devmode

        Dim lDevmode As IntPtr = LoadBlackIceDEVMODE(szPrinterName)

 

        If lDevmode.ToInt32() > 0 Then

            ' Get interface ID of the printer driver

            GetSessionID(lDevmode, iRet)

            ' Release the DEVMODE

            ReleaseBlackIceDEVMODE(lDevmode)

        End If

        Return iRet

    End Function

 

    'Get interface name from Printer name

    Public Function GetPrinterInterfaceName(szPrinterName As String) As String

        Dim sInterfaceName As String = String.Empty

 

        ' Load the devmode

        Dim lDevmode As IntPtr = LoadBlackIceDEVMODE(szPrinterName)

 

        If lDevmode.ToInt32() > 0 Then

            ' Get interface ID of the printer driver

            Dim ipInterfaceName As IntPtr = GetInterfaceName(lDevmode)

            sInterfaceName = Marshal.PtrToStringUni(ipInterfaceName)

 

            ' Release the DEVMODE

            ReleaseBlackIceDEVMODE(lDevmode)

        End If

        ' Return printer interface name

        Return sInterfaceName

    End Function

End Class

 

Once imported, one can use the WaitForPrnPipeWithPriority function in the VB.NET code as in the following example

 

       'Printer driver name

       Dim sPrinterName As String = "Printer Name"

 

       'Create an object of type BiHelper

       Dim helper As New BiHelper()

 

       'Interface name of Printer driver

       Dim sInterfaceName As String = helper.GetPrinterInterfaceName(sPrinterName)

 

       'Session ID of Printer driver

       Dim iSessionID As Integer = helper.GetPrinterSessionID(sPrinterName)

 

       'Pipe name

       szPipeName = (Convert.ToString("\\.\pipe\") & sInterfaceName) + iSessionID.ToString()

 

       'Start listening for messages. The pipe messages will be forwarded to the WndProc function as WM_USER + 1000 messages

       WaitForPrnPipeWithPriority(szPipeName, Me.Handle, WM_USER + 1000, THREAD_PRIORITY_TIME_CRITICAL)

 

                Protected Overrides Sub WndProc(ByRef message As Message)

            If message.Msg = WM_USER + 1000 Then

                ' WM_USER + 1000 is the same value that is passed to the WaitForPrnPipeWithPriority function

                'Read the Printer Driver Messaging Interface structure from the WParam parameter

                Dim pParams As IntPtr = GlobalLock(message.WParam)

                Dim sParams As TSPrnMessage = DirectCast(Marshal.PtrToStructure(pParams, GetType(TSPrnMessage)), TSPrnMessage)

 

                ' The larger message capture structure is available since Printer Driver Version 14.98.

                ' For compatibility with older drivers, check the size of the structure to see if we recieved the

                ' new structure or the old one.

                Dim bNewDriver As Boolean = (CInt(GlobalSize(message.WParam)) >= Marshal.SizeOf(GetType(TSPrnMessage)))

 

                If bNewDriver Then

                    ' Driver Version is 14.98 or newer, use the new structure

                    sParams = DirectCast(Marshal.PtrToStructure(pParams, GetType(TSPrnMessage)), TSPrnMessage)

                Else

                    ' Driver Version is 14.97 or earlier, copy what we can from the old structure

                    Dim sParamsV1 As TSPrnMessageV1

                    sParamsV1 = DirectCast(Marshal.PtrToStructure(pParams, GetType(TSPrnMessageV1)), TSPrnMessageV1)

                    sParams = New TSPrnMessage(sParamsV1)

                End If

 

                Select Case sParams.dwMessage

                    Case BLACKICE_MESSAGE_STARTDOC

                        DisplayAndLog("Start Doc")

                        DisplayAndLog("    Printer Name: " + sParams.szPrinterName)

                        DisplayAndLog("    Document Name: " + sParams.szDocName)

                        DisplayAndLog("    Group File Name: " + sParams.szGroupFileName)

                        If (bNewDriver) Then

                            DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString())

                        End If

                        Exit Select

 

                    Case BLACKICE_MESSAGE_STARTPAGE

                        DisplayAndLog("Start Page")

                        DisplayAndLog("    Printer Name: " + sParams.szPrinterName)

                        DisplayAndLog("    Document Name: " + sParams.szDocName)

                        DisplayAndLog("    Page Number: " + sParams.nPageNumber.ToString())

                        If (bNewDriver) Then

                            DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString())

                            DisplayAndLog("    Output File Name: " + sParams.szOutputFileName)

                            DisplayAndLog("    Group File Name: " + sParams.szGroupFileName)

                        Else

                            DisplayAndLog("    Output File Name: " + sParams.szFileName)

                        End If

                        Exit Select

 

                    Case BLACKICE_MESSAGE_ENDDOC

                        DisplayAndLog("End Doc")

                        DisplayAndLog("    Printer Name: " + sParams.szPrinterName)

                        DisplayAndLog("    Document Name: " + sParams.szDocName)

                        If (bNewDriver) Then

                            DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString())

                            DisplayAndLog("    Output File Name: " + sParams.szOutputFileName)

                            DisplayAndLog("    Group File Name: " + sParams.szGroupFileName)

                        Else

                            DisplayAndLog("    Group File Name: " + sParams.szFileName)

                        End If

                        Exit Select

 

                    Case BLACKICE_MESSAGE_ENDPAGE

                        DisplayAndLog("End Page")

                        DisplayAndLog("    Printer Name: " + sParams.szPrinterName)

                        DisplayAndLog("    Document Name: " + sParams.szDocName)

                        DisplayAndLog("    Page Number: " + sParams.nPageNumber.ToString())

                        If (bNewDriver) Then

                            DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString())

                            DisplayAndLog("    Output File Name: " + sParams.szOutputFileName)

                            DisplayAndLog("    Group File Name: " + sParams.szGroupFileName)

                        Else

                            DisplayAndLog("    Output File Name: " + sParams.szFileName)

                        End If

                        Exit Select

 

                    Case BLACKICE_MESSAGE_ABORT

                        DisplayAndLog("Abort:  Print job has been aborted")

                        If (bNewDriver) Then

                            DisplayAndLog("    Printer Name: " + sParams.szPrinterName)

                            DisplayAndLog("    Document Name: " + sParams.szDocName)

                            DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString())

                        End If

                        Exit Select

 

                    Case BLACKICE_MESSAGE_DEVMODE

                        DisplayAndLog("ChangeDevmode")

                        If (bNewDriver) Then

                            DisplayAndLog("    Printer Name: " + sParams.szPrinterName)

                            DisplayAndLog("    Document Name: " + sParams.szDocName)

                            DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString())

                        End If

 

                        ' ChangeDevmode message received, read the DEVMODE structure from the LParam parameter and configure it

                        Dim ipDevmode As IntPtr = message.LParam

                        If ipDevmode.ToInt32() > 0 Then

                            ' modify the BlackIceDEVMODE structure as needed

                            ' do not modify the standard DEVMDOE structure, (pDevMode->DM)

                            ' only modify the extended part of the BlackIceDEVMODE structure.

                            ' DO NOT MAKE TIME CONSUMING OPEARTIONS HERE

                            ' The printer drive will wait a maximum of 2 seconds for an updated

                            ' BlackIceDEVMODE structure.

                        End If

                        Exit Select

 

                    Case BLACKICE_MESSAGE_MEMIMAGE

                        ipDevmode = message.LParam

                        If ipDevmode.ToInt32() > 0 Then

                            'Printer driver name

                            Dim sPrinterName As String = CurrentPrinter.Text

                            'Create an object of type BiHelper

                            Dim helper As New BiHelper()

 

                            'File extension of Printer driver

                            Dim sFileExt As String = helper.GetFileExtension_(sPrinterName)

 

                            Dim saveFileName As String = String.Empty

                            saveFileName = GetCustomTempFile("BLI", sFileExt)

 

                            'Get pointer to the image data

                            Dim pImage As IntPtr = GlobalLock(message.LParam)

                            'Get the size of the image data

                            Dim dwSize As Integer = CInt(GlobalSize(message.LParam))

                            'Copy the image data from the unmanaged memory to a byte array

                            Dim buffer As Byte() = New Byte(dwSize - 1) {}

                            Marshal.Copy(pImage, buffer, 0, dwSize)

 

                            'Write image data to a file

                            File.WriteAllBytes(saveFileName, buffer)

                            If (bNewDriver) Then

                                DisplayAndLog("MemoryImageEx message was received.")

                                DisplayAndLog("    Printer Name: " + sParams.szPrinterName)

                                DisplayAndLog("    Document Name: " + sParams.szDocName)

                                DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString())

                                DisplayAndLog("    The file has been saved to: " + saveFileName)

                            Else

                                DisplayAndLog("Print to Memory message received and the file has been saved to: " + saveFileName)

                            End If

 

                            'Free unmanaged memory

                            GlobalUnlock(message.LParam)

                            GlobalFree(message.LParam)

 

                        End If

                            Exit Select

 

                    Case BLACKICE_MESSAGE_ERROR

                            DisplayAndLog("Error message was received.")

                            DisplayAndLog("    Error Code: " + message.LParam.ToString())

                        Exit Select

 

                    Case BLACKICE_MESSAGE_OCR

                        ipDevmode = message.LParam

                        If ipDevmode.ToInt32() > 0 Then

                            If (bNewDriver) Then

                                'Printer driver name

                                Dim sPrinterName As String = CurrentPrinter.Text

 

                                'Get pointer to the OCR data

                                Dim pOCR As IntPtr = GlobalLock(message.LParam)

 

                                Dim OCRData As String = Marshal.PtrToStringUni(pOCR)

                                DisplayAndLog("OCR message was received.")

                                DisplayAndLog("    Printer Name: " + sParams.szPrinterName)

                                DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString())

                                DisplayAndLog("    Document Name: " + sParams.szDocName)

 

                                Select Case sParams.dwOCRDataType

                                    Case BI_OCR_MEM_FORMAT_TEXT

                                        Try

                                            DisplayAndLog("    The OCR Data Type is TEXT (1))")

                                            DisplayAndLog("    The OCR Data is: " + OCRData)

 

                                            Dim saveFileName As String = String.Empty

                                            saveFileName = GetCustomTempFile("BLI", "txt")

 

                                            'Write OCR data to a file

                                            File.WriteAllText(saveFileName, OCRData)

                                        Catch Ex As Exception

                                            DisplayAndLog("    " + Ex.ToString())

                                        End Try

 

                                    Case BI_OCR_MEM_FORMAT_HOCR_HEADER

                                        Try

                                            DisplayAndLog("    The OCR Data Type is hOCR header (2)")

                                            DisplayAndLog("    The OCR Data is: " + OCRData)

                                            sHOCRFileName = GetCustomTempFile("BLI", "html")

 

                                            'Write OCR header to a file

                                            File.WriteAllText(sHOCRFileName, OCRData)

                                            DisplayAndLog("    The file has been saved to: " & sHOCRFileName)

                                        Catch Ex As Exception

                                            DisplayAndLog("    " + Ex.ToString())

                                        End Try

 

                                    Case BI_OCR_MEM_FORMAT_HOCR_PAGE

                                        Try

                                            DisplayAndLog("    The OCR Data Type is hOCR data (3)")

                                            DisplayAndLog("    The OCR Data is: " + OCRData)

 

                                            'Append OCR data to a file

                                            File.AppendAllText(sHOCRFileName, OCRData)

                                            DisplayAndLog("    The file has been saved to: " & sHOCRFileName)

                                        Catch Ex As Exception

                                            DisplayAndLog("    " + Ex.ToString())

                                        End Try

 

                                    Case BI_OCR_MEM_FORMAT_HOCR_FOOTER

                                        Try

                                            DisplayAndLog("    The OCR Data Type is hOCR footer (4)")

                                            DisplayAndLog("    The OCR Data is: " + OCRData)

 

                                            'Append OCR footer to a file

                                            File.AppendAllText(sHOCRFileName, OCRData)

                                            DisplayAndLog("    The file has been saved to: " & sHOCRFileName)

                                        Catch Ex As Exception

                                            DisplayAndLog("    " + Ex.ToString())

                                        End Try

 

                                End Select

                            End If

 

                            'Free unmanaged memory

                            GlobalUnlock(message.LParam)

                            GlobalFree(message.LParam)

 

                        End If

                        Exit Select

                End Select

 

       CaseBLACKICE_MESSAGE_TEXT

              ipDevmode = message.LParam

              If ipDevmode.ToInt32() > 0 Then

                     If (bNewDriver) Then

 

                           'Get pointer to the TEXT data

                           Dim pTEXT As IntPtr = GlobalLock(message.LParam)

 

                           Dim TEXTData As String = Marshal.PtrToStringUni(pTEXT)

                           DisplayAndLog("TEXT message was received.")

                           DisplayAndLog("    Printer Name: " + sParams.szPrinterName)

                           DisplayAndLog("    Job ID: " + sParams.dwJobID.ToString())

                           DisplayAndLog("    Document Name: " + sParams.szDocName)

                           DisplayAndLog("    Page Number: " + sParams.nPageNumber.ToString())

                           Try

 

                                  'DisplayAndLog("    The TEXT Data is: " + TEXTData);

 

                                  Dim saveFileName As String = String.Empty

                                  saveFileName = GetCustomTempFile("BLI", "txt")

 

                                  'Write TEXT data to a file

                                  File.WriteAllText(saveFileName, TEXTData)

                                  DisplayAndLog("    The file has been saved to: " + saveFileName)

 

                           Catch Ex As Exception

                                  DisplayAndLog("    " + Ex.ToString())

                           End Try

                     End If

 

                     'Free unmanaged memory

                     GlobalUnlock(message.LParam)

                     GlobalFree(message.LParam)

                     Exit Select

              End If

       End Select

 

                GlobalUnlock(message.WParam)

                GlobalFree(message.WParam)

            End If

 

            MyBase.WndProc(message)

        End Sub