HOWTO: How to Connect Local Printers to Network Print Shares

This article was previously published under Q152551
This article has been archived. It is offered "as is" and will no longer be updated.
Prior to Windows 95 and Windows NT, network print shares were used inWindows by connecting MS-DOS devices to network resources. Often, this wasaccomplished by the WNetAddConnection function that was implemented by theunderlying network software. This architecture limited the number ofconnections to the number of MS-DOS devices that could be redirected.Further, it suffered from an inherent inflexibility of print job andprinter management.

The current Win32 Application Programming Interface (API) defines a collection of functions known as the Print Spooler API. The Print Spooler API manipulates the Spooler, a component of the operating system that is always running, and manages printers and print jobs both local and remote. The Spooler and its printers are no longer tied to MS-DOS devices for access to network print shares. Any printer in Windows can now be connected (redirected) directly to network print shares by their UNC names.
Configuring a printer to be redirected to a network print share is a three-step process: The application first obtains a current PRINTER_INFO_2structure via the GetPrinter function; the new configuration is thendefined by altering the members of the PRINTER_INFO_2 structure; once modified, the structure is passed to the SetPrinter function that resets the configuration.

To configure a printer to print to a network print share, set the pPortName member of the PRINTER_INFO_2 structure to point to a valid port name string. Windows NT requires the name of the port to be in the list of ports that are returned from the EnumPorts function. On Windows 95, this string may contain the UNC path to a remote network print share or can be from this list of installed ports. Additional ports are defined by calling the AddPort function and specifying the appropriate Port Monitor.

When AddPort is used to set up a new port, a dialog box provided by the Port Monitor appears. There is no way to prevent this dialog box from beingdisplayed. The Port Monitor uses this dialog box to configure the new port with information specific to that type of port.

Although Windows NT supports the redirection of local printers to networkprint shares, the recommended method for printing to a network print shareon Windows NT is a Printer Connection. A Printer Connection is a directrepresentation of the network printer resource on the local workstation.Printing to a Connection involves Remote Procedure Calls (RPC) that offermany advantages, such as spooling on the Server and Server-supplied printerdrivers. However, Printer Connections currently work only when the clientand server are both Windows NT or if the network specifically supports it.

Microsoft recommends that applications running on Windows NT attempt tocall AddPrinterConnection to define Network Printers to which applicationswould print. If AddPrinterConnection fails, applications should thenattempt to use a local printer redirected to the network print share asthis article describes. Use and diagnosis of AddPrinterConnection failuresis beyond the scope of this article.

For more information on the use of AddPrinterConnection and how to installlocal printers, please see the following article in the Microsoft KnowledgeBase:
147202How to Add a Network Printer Connection
Use the following steps to configure a printer with the Print Spoolerfunctions:
  1. Use OpenPrinter to obtain a handle to a printer object whose configuration can be modified by the SetPrinter function. For SetPrinter to succeed, the calling process must have administrative privileges and the printer must be opened with PRINTER_ALL_ACCESS.
  2. Call GetPrinter once to determine the size of a PRINTER_INFO_2 structure for the current configuration by passing zero for the size of the buffer in the cbBuffer parameter, two in the Level parameter, NULL for pPrinter parameter, the handle to the opened printer in the hPrinter parameter and the address of a DWORD in the pcbNeeded parameter. GetPrinter fails and GetLastError returns ERROR_INSUFFICIENT_BUFFER. This is an indication of success, because GetPrinter was asked to return the required buffer size by forcing a failure with too small a buffer. Under these conditions, GetPrinter returns the required buffer size in the pcbNeeded parameter. If GetLastError returns anything other than this return value, it is an indication of an actual error.
  3. Allocate a buffer of size pcbNeeded and call GetPrinter to retrieve the PRINTER_INFO_2 structure for the current configuration. For this second call, the address of the allocated buffer is passed in the pPrinterparameter and the size of this buffer is passed in the cbBuffer parameter.
  4. Update the members of the PRINTER_INFO_2 structure to change the printer's configuration. Generally, the pSecurityDescriptor member of the structure should be set to NULL to avoid changing the security information for the printer. String pointers such as pPortName should simply be assigned the address of the string containing the new value. SetPrinter copies the data from this structure and any strings pointed to by members of this structure.
  5. Finally, call SetPrinter, passing the handle to the open printer, two for the dwLevel parameter, the address of the buffer containing the modified PRINTER_INFO_2 structure, and zero in the dwCommand parameter. If SetPrinter succeeds, the contents of the PRINTER_INFO_2 structure will have been used to reconfigure the printer. If SetPrinter fails, call GetLastError to determine the cause. A typical reason for the failure of a SetPrinter call is insufficient privileges for the user to change some part of the printer's configuration.

Sample Code

The following code sample demonstrates the calls to GetPrinter andSetPrinter:
   BOOL ConnectToRemotePrinter(char *pszRemotePath, HANDLE hPrinter)   {   PRINTER_INFO_2  *ppi = NULL;   DWORD           dwNeeded, dwReturned;   if (!pszRemotePath && lstrlen(pszRemotePath) == 0)      goto Fail;   /*    * Manage Printer's port connections    */    /* Get the size required for the buffer */    SetLastError(0);   if (!GetPrinter(hPrinter, 2, NULL, 0, &dwNeeded))   {   if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)           goto Fail;   }   ppi = (PRINTER_INFO_2 *)malloc(dwNeeded);   if (!ppi)      goto Fail;   /* Get a copy of the printer's configuration */    if (!GetPrinter(hPrinter, 2, (LPBYTE)ppi, dwNeeded, &dwReturned))      goto Fail;   /* change the connection */    ppi->pPortName = pszRemotePath;   /* don't set the security information */    ppi->pSecurityDescriptor = NULL;   /* Make it so */    if (!SetPrinter(hPrinter, 2, (LPBYTE)ppi, 0))      goto Fail;   /* cleanup */    free(ppi);   return TRUE;   Fail:    if (ppi)       free(ppi);    return FALSE;   } /* end of function ConnectToRemotePrinter */ 				
3.51 4.00 redirection remote print resource WNetCancelConnection WNetAddConnection

Article ID: 152551 - Last Review: 12/04/2015 14:55:28 - Revision: 2.2

Microsoft Win32 Application Programming Interface

  • kbnosurvey kbarchive kbhowto KB152551