|
|
/*++
Copyright (c) 2000 Microsoft Corporation All rights reserved.
Module Name: clusupg.cxx
Purpose: Upgrade printer drivers for clusters spoolers
Author:
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
/*++
Routine Name:
PSetupUpgradeClusterDriversW
Routine Description:
Upgrade function. Called by a cluster spooler to upgrade its drivers. This function is called the first time when the cluster spooler fails over to a node that was upgraded. SplCreatespooler spins a thread executing SplCreateSpoolerWorkerThread. So SplCreateSpoolerWorkerThread runs in the context of the spooler process, which is local system. This function then creates a rundll32 process (with CreateProcess) that invokes PSetupUpgradeClusterDrivers and thus runs in local system context. PSetupUpgradeClusterDrivers enumerates all the printer drivers, loads printui.dll and calls the function PrintUIEntryW in printui.dll.
Arguments:
hwnd - Window handle of stub window. hInstance, - Rundll instance handle. pszCmdLine - Pointer to command line. nCmdShow - Show command value always TRUE.
Return Value:
Returns the last error code. This can be read by the spooler by getting the return code from the process.
--*/ DWORD PSetupUpgradeClusterDriversW( IN HWND hWnd, IN HINSTANCE hInstance, IN LPCTSTR pszCmdLine, IN UINT nCmdShow ) { LPBYTE pDriverEnum = NULL; DWORD cbNeeded; DWORD cStrucs; DWORD dwError = ERROR_INVALID_PARAMETER; LPTSTR pszServer = const_cast<LPTSTR>(pszCmdLine); if (pszServer) { //
// Enumerate all the drivers on the server
//
dwError = EnumPrinterDrivers(pszServer, _T("all"), 6, NULL, 0, &cbNeeded, &cStrucs) ? ERROR_SUCCESS : GetLastError(); if (dwError == ERROR_INSUFFICIENT_BUFFER) { if (pDriverEnum = static_cast<LPBYTE>(LocalAllocMem(cbNeeded))) { if (EnumPrinterDrivers(pszServer, _T("all"), 6, pDriverEnum, cbNeeded, &cbNeeded, &cStrucs)) { dwError = ERROR_SUCCESS; } else { LocalFreeMem(pDriverEnum);
pDriverEnum = NULL; dwError = GetLastError(); } } else { dwError = GetLastError(); } }
if (dwError==ERROR_SUCCESS && cStrucs) { DRIVER_INFO_6 *pDrv = NULL; UINT uIndex = 0; HINSTANCE hLibrary = NULL; typedef (* PFNENTRY)(HWND, HINSTANCE, LPCTSTR, UINT); PFNENTRY pfnEntry;
//
// Load printui and get the entry point
//
if ((hLibrary = LoadLibraryUsingFullPath(_T("printui.dll"))) && (pfnEntry = (PFNENTRY)GetProcAddress(hLibrary, "PrintUIEntryW")) ) { //
// Loop through drivers and try to upgrade them using the cab
//
for (uIndex = 0, pDrv=reinterpret_cast<LPDRIVER_INFO_6>(pDriverEnum); dwError == ERROR_SUCCESS && uIndex < cStrucs; uIndex++, pDrv++ ) { TString strCommand; DWORD cbNeeded = 0; LPCTSTR pszFormat = _T("/q /Gw /ia /K /c \"%ws\" /m \"%ws\" /h \"%ws\" /v %u"); //
// Format the string that will be used as aparameter for printui
//
if (strCommand.bFormat(pszFormat, pszServer, pDrv->pName, pDrv->pEnvironment, pDrv->cVersion)) { //
// The printer we install will never have a print processor associated
// with it.
// The call into printui goes thrgouh the following path:
// PSetupUpgradeClusterDriversW -> PrintUIEntryW -> bDoCommand ->
// bExecuteCommand( XX, kInstallDriverWithInf, XX ) -> bDoInfPrinterInstall ->
// PnPInterface(kInfInstall, XX) -> bInfInstall
//
//
// This will try to upgrade the driver/ We don't care about the error. Even if a driver
// couldn't be upgraded, we still want to loop and try to upgrade the other drivers
//
dwError = (pfnEntry)(hWnd, hInstance, strCommand, 0); DBGMSG(DBG_WARN, ("Command %ws dwError from printui %u\n", (LPCTSTR)strCommand, dwError)); //
// The case statements reperesent errors where we cannot continue executing the
// printer driver update. This is when the spooler dies or the cluster group
// becomes active on a different node
//
switch (dwError) { case RPC_S_SERVER_UNAVAILABLE: //
// We can get access deined when the cluster group moves to a different node.
// Since this process executes in the local system acocunt, this account doesn't
// have permissins to install printer drivers on a remote machine
//
case ERROR_ACCESS_DENIED: //
// The spooler returns this error when it cannot create temporary directories
// for driver upgrade
//
case ERROR_NO_SYSTEM_RESOURCES:
//
// printui returns this error when it cannot do OpenPrinter(\\server name).
// This means the cluster group is off line (inaccessible)
//
case ERROR_INVALID_PRINTER_NAME: //
// We will exit the loop since dwError is not error success
//
break;
default:
//
// We continue looping
//
dwError = ERROR_SUCCESS; } } } } else { dwError = GetLastError(); }
if (hLibrary) { FreeLibrary(hLibrary); } }
LocalFreeMem(pDriverEnum); pDriverEnum = NULL; } DBGMSG(DBG_WARN, ("PSetupClusterDrivers Error %u \n", dwError));
//
// If an error occurs we call ExitProcess. Then the spooler picks up the
// error code using GetExitCodeProcess. If no error occurs, then we
// terminate normally
//
if (dwError != ERROR_SUCCESS) { ExitProcess(dwError); }
return dwError; }
|