4.1 Adding a Printer to a Server

To add a printer ("HP LaserJet 4") to a print server ("CORPSERV"), a client ("TESTCLT") performs the following steps:

  1. Enumerate existing printer drivers using RpcEnumPrinterDrivers.

    • The client obtains the server platform by calling RpcGetPrinterData on a server object with the "Architecture" key value.

    • The client calls RpcEnumPrinterDrivers, specifying the environment parameter to match the server platform.

       RpcEnumPrinterDrivers( L"\\\\CORPSERV"., L"Windows NT x86", 1, NULL, 0, &countBytesNeeded, &driversFound )
    • The server returns ERROR_INSUFFICIENT_BUFFER and sets countBytesNeeded large enough to store _DRIVER_INFO_1 structures for all drivers matching the specified environment "Windows NT x86".

    • The client allocates memory, setting the size of driverInfo1[] to countBytesNeeded, and calls RpcEnumPrinterDrivers again.

       RpcEnumPrinterDrivers ( L"\\\\CORPSERV", L"Windows NT x86", 1, driverInfo1, countBytesNeeded, &countBytesNeeded, &driversFound )
    • The server writes a _DRIVER_INFO_1 structure for each driver matching the specified environment ("Windows NT x86") to the output buffer, writes the number of _DRIVER_INFO_1 structures to driversFound, and returns 0 (success).

    Note: If the number of drivers on the server has increased between the first and second call to RpcEnumPrinterDrivers, the server returns ERROR_INSUFFICIENT_BUFFER from the second call as well. In that case, the server updates countBytesNeeded and the client allocates more memory and calls RpcEnumPrinterDrivers again.

  2. Select an existing printer driver or add a new printer driver using RpcAddPrinterDriver.

    • Assume the server returned a driver named "HP LaserJet 4".

    • The client calls RpcEnumPorts to enumerate the available ports. This process is analogous to the previous step, which enumerated printer drivers using RpcEnumPrinterDrivers.

    • The client displays a dialog box so the end user can pick the driver, enter a desired port, and optionally enter a share name for the new printer.

    • If the driver does not already exist, or the client requests to update the driver, use RpcAddPrinterDriver to add the driver to the print server, as shown in 4.2.

  3. Populate a PRINTER_INFO_2 structure with information about the new printer and call RpcAddPrinter.

    • The client allocates and zero-initializes a PRINTER_INFO_2 structure.

    • The client sets the following members of the structure:

       pPrinterName = L"HP LaserJet 4"  /* Typically set to the driver name */
       pShareName = L"My Printer"       /* Any name the user selects */
       pPortName = L""      /* A port that exists on the server */
       pDriverName = L"HP LaserJet 4"   /* Driver selected in previous step */

    For pPortName, the client might have previously enumerated the server's ports using RpcEnumPorts or the user might know a valid port name.

    The client initializes all other members of the structure to zero or NULL, as appropriate. Or, the client specifies higher DRIVER_INFO levels in the call to RpcEnumPrinterDrivers to obtain more details to initialize these structure members. Or, the client prompts the user to specify values such as priorities or times at which the printer is available and initializes these members with the values specified by the user.

    • The client allocates a PRINTER_CONTAINER (section structure and initializes it to contain the prepared PRINTER_INFO_2.

    • The client allocates a DEVMODE_CONTAINER devmodeContainer structure, and optionally initializes it with a DEVMODE structure.

    • The client allocates a SECURITY_CONTAINER securityContainer structure, and optionally initializes it with a SECURITY_DESCRIPTOR.

    • The client calls RpcAddPrinter to add the printer.

       RpcAddPrinter( L"\\\\CORPSERV", &printerContainer, &devmodeContainer, &securityContainer, &hPrinter )
    • The server creates the print queue, writes the handle to hPrinter, and returns 0 (success).

  4. Close the returned PRINTER_HANDLE using RpcClosePrinter.

    • When the client is done using the print queue, the client closes it.

       RpcClosePrinter( &hPrinter )
    • The server frees the memory associated with the print queue handle, sets hPrinter to NULL, and returns 0 (success).

Adding a printer to a server

Figure 5: Adding a printer to a server