Install Port Monitor using Win32

Install Port Monitor and Create New Port Programmatically

I have worked on the windows printer driver, where I have to install the port monitor silently without user interaction. It is a user-mode DLL which responsible for providing a communications path between the user-mode print spooler and the kernel-mode port drivers that access I/O port hardware.

You can also check the below article,

It uses the CreateFile, WriteFile, ReadFile, and DeviceIOControl functions, described in the Microsoft Windows SDK documentation, to communicate with kernel-mode port drivers also responsible for management and configuration of a server’s printer ports.

Note: All the thing tested on the windows 10X64 machine (64 bits).

 

Here, I am assuming you are familiar with windows internals and API. If you are not familiar with windows internal and API, see this popular course: Windows Internals

 

You can install the port monitor to follow the below steps

 

Open the Administrative Tools.

 

port monitor

 

Open Print Management in admenestrative mode.

 

Add port monitor





Select the Printers folder and click on any printer.

 

install print monitor

 

Now click the Ports tab and then click Add Port button.

 

On the Printer Ports dialog, click the New Port Type button.

 

New port type

Enter the path to the INF file (port monitor) in the text input box, and then click OK.

install print monitor inf

 

Note: Port Monitor DLL (package) should be present in system32 before running the below code.

After following the above steps you able to install your DLL. Here the task is not completed yet after installing the print monitor I need to create the port. I can also create the port manually, but here I want to create a custom application which installs the monitor silently and create the port. See the below example code it worked for me.



#include "stdafx.h"
#include <windows.h>

//Function to add port
int AddLocalPort()

{

    PRINTER_DEFAULTS PrinterDefaults;

    WCHAR PortName[100] = { 0 };

    HANDLE  hPrinter;

    LPTSTR pszBuf = NULL;

    DWORD dwNeeded;

    DWORD dwStatus;



    PrinterDefaults.pDatatype = NULL;

    PrinterDefaults.pDevMode = NULL;

    PrinterDefaults.DesiredAccess = SERVER_ACCESS_ADMINISTER;



    //OpenPrinter function retrieves a handle to the specified printer or print server

    if (!OpenPrinter(L",XcvMonitor Aticleworld Port Monitor", &hPrinter, &PrinterDefaults))

    {

        printf("OpenPrinter failed - %d\n", GetLastError());

        return -1;

    }


    //You can take name as per your requirement

    //Here I am taking com6 as port name

    lstrcpyW(PortName, L"COM6");



    //The print spooler's XcvData function is the means by which a port monitor UI DLL communicates with its associated port monitor server DLL

    if (!XcvData(hPrinter, L"AddPort", (BYTE *)PortName, (lstrlenW(PortName) + 1) * 2, NULL, 0, &dwNeeded, &dwStatus))

    {

        printf("XcvData failed - %d\n", GetLastError());

        return -1;

    }

    if (dwStatus != 0)

    {

        printf("XcvData - Returned %lu\n", dwStatus);

        return -1;

    }
    //close printer
    if (!ClosePrinter(hPrinter))

    {

        printf("ClosePrinter failed - %lu\n", GetLastError());

        return -1;

    }



    return 0;
}





int main()

{

    //MONITOR_INFO_2 structure identifies a monitor

    MONITOR_INFO_2 AddComport;

    BOOL ret;

    //Name of the port monitor dll (driver)

    AddComport.pDLLName = L"monitor.dll";

    AddComport.pEnvironment = NULL;

    AddComport.pName = L"Aticleworld Port Monitor";


    //AddMonitor function installs a local port monitor and links the configuration, data, and monitor files.

    ret = AddMonitor(NULL, 2, (LPBYTE)&AddComport);

    if (ret == 0)

    {

        printf("Failed to Add Print Monitor\n");

        return -1;

    }

    Sleep(10);

    system("net stop spooler");

    Sleep(10);

    system("net start spooler");



    //Call function to add port to the port monitor

    ret = AddLocalPort();

    if (ret == 0)

    {

        printf("Failed to Add port\n");

        return -1;

    }

    Sleep(10);

    //Stop Spooler
    system("net stop spooler");

    Sleep(10);
    //Start Spooler
    system("net start spooler");


    return 0;
}

 

 

After running the above code you will find that the Aticleworld installed and it will show in port type.

showing available port types

 

Reference: https://docs.microsoft.com/en-us/windows-hardware/drivers/print/