views:

627

answers:

1

We have a virtual printer (provided by a 3rd party) that is getting assigned to an invalid local printer port. The printer is always local (we aren't dealing with a remote print server or anything like that). I'd like to create a new local port (specific for our application), then configure the printer to be assigned to that port instead of the random (and often incorrect) port that the print driver installer chooses.

I believe that I need to use the XcvData and/or XcvDataPort functions to do this, but I'm at a bit of a loss as to how.

Does anyone have any examples or pointers on how to proceed?

I'd imagine that I need to do the following:

  1. Check to ensure the port name doesn't already exist (I can probably use EnumPorts for this, but I'm not sure that's the best approach given that I have to also create ports)
  2. Create the port name if it does exist
  3. Change the printer configuration to use the new port

and for uninstall:

  1. Remove the port
+1  A: 

Wow, looks like that one stumped everyone... After much digging, here's how to do it:

DWORD CreatePort(LPWSTR portName)
{
      HANDLE hPrinter;
      PRINTER_DEFAULTS PrinterDefaults;
      memset(&PrinterDefaults, 0, sizeof(PrinterDefaults));

      PrinterDefaults.pDatatype = NULL;
      PrinterDefaults.pDevMode = NULL;
      PrinterDefaults.DesiredAccess = SERVER_ACCESS_ADMINISTER;

      DWORD needed;
      DWORD rslt;


      if (!OpenPrinter(",XcvMonitor Local Port", &hPrinter, &PrinterDefaults))
       return -1;

      DWORD xcvresult= 0;
      if (!XcvData(hPrinter, L"AddPort", (BYTE *)portName, (lstrlenW(portName) + 1)*2, NULL, 0, &needed, &xcvresult))
            rslt= GetLastError();

      if (!ClosePrinter(hPrinter))
       rslt= GetLastError();

      return rslt;
}

Setting the port on a given printer is relatively straight forward - OpenPrinter(), GetPrinter() with PRINTER_INFO_2, SetPrinter(), ClosePrinter()

Cheerio.

Kevin Day