Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
7.1 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. clusupg.cxx
  6. Purpose:
  7. Upgrade printer drivers for clusters spoolers
  8. Author:
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. /*++
  14. Routine Name:
  15. PSetupUpgradeClusterDriversW
  16. Routine Description:
  17. Upgrade function. Called by a cluster spooler to upgrade its drivers.
  18. This function is called the first time when the cluster spooler fails
  19. over to a node that was upgraded. This function is called via rundll32.
  20. Arguments:
  21. hwnd - Window handle of stub window.
  22. hInstance, - Rundll instance handle.
  23. pszCmdLine - Pointer to command line.
  24. nCmdShow - Show command value always TRUE.
  25. Return Value:
  26. Returns the last error code. This can be read by the spooler by getting the return code from the process.
  27. --*/
  28. DWORD
  29. PSetupUpgradeClusterDriversW(
  30. IN HWND hWnd,
  31. IN HINSTANCE hInstance,
  32. IN LPCTSTR pszCmdLine,
  33. IN UINT nCmdShow
  34. )
  35. {
  36. LPBYTE pDriverEnum = NULL;
  37. DWORD cbNeeded;
  38. DWORD cStrucs;
  39. DWORD dwError = ERROR_INVALID_PARAMETER;
  40. LPTSTR pszServer = const_cast<LPTSTR>(pszCmdLine);
  41. if (pszServer)
  42. {
  43. //
  44. // Enumerate all the drivers on the server
  45. //
  46. dwError = EnumPrinterDrivers(pszServer,
  47. _T("all"),
  48. 6,
  49. NULL,
  50. 0,
  51. &cbNeeded,
  52. &cStrucs) ? ERROR_SUCCESS : GetLastError();
  53. if (dwError == ERROR_INSUFFICIENT_BUFFER)
  54. {
  55. if (pDriverEnum = static_cast<LPBYTE>(LocalAllocMem(cbNeeded)))
  56. {
  57. if (EnumPrinterDrivers(pszServer,
  58. _T("all"),
  59. 6,
  60. pDriverEnum,
  61. cbNeeded,
  62. &cbNeeded,
  63. &cStrucs))
  64. {
  65. dwError = ERROR_SUCCESS;
  66. }
  67. else
  68. {
  69. LocalFreeMem(pDriverEnum);
  70. pDriverEnum = NULL;
  71. dwError = GetLastError();
  72. }
  73. }
  74. else
  75. {
  76. dwError = GetLastError();
  77. }
  78. }
  79. if (dwError==ERROR_SUCCESS && cStrucs)
  80. {
  81. DRIVER_INFO_6 *pDrv = NULL;
  82. UINT uIndex = 0;
  83. HINSTANCE hLibrary = NULL;
  84. typedef (* PFNENTRY)(HWND, HINSTANCE, LPCTSTR, UINT);
  85. PFNENTRY pfnEntry;
  86. //
  87. // Load printui and get the entry point
  88. //
  89. if ((hLibrary = LoadLibraryUsingFullPath(_T("printui.dll"))) &&
  90. (pfnEntry = (PFNENTRY)GetProcAddress(hLibrary, "PrintUIEntryW"))
  91. )
  92. {
  93. //
  94. // Loop through drivers and try to upgrade them using the cab
  95. //
  96. for (uIndex = 0, pDrv=reinterpret_cast<LPDRIVER_INFO_6>(pDriverEnum);
  97. dwError == ERROR_SUCCESS && uIndex < cStrucs;
  98. uIndex++, pDrv++
  99. )
  100. {
  101. TString strCommand;
  102. DWORD cbNeeded = 0;
  103. LPCTSTR pszFormat = _T("/q /Gw /ia /K /c \"%ws\" /m \"%ws\" /h \"%ws\" /v %u");
  104. //
  105. // Format the string that will be used as aparameter for printui
  106. //
  107. if (strCommand.bFormat(pszFormat, pszServer, pDrv->pName, pDrv->pEnvironment, pDrv->cVersion))
  108. {
  109. //
  110. // This will try to upgrade the driver/ We don't care about the error. Even if a driver
  111. // couldn't be upgraded, we still want to loop and try to upgrade the other drivers
  112. //
  113. dwError = (pfnEntry)(hWnd, hInstance, strCommand, 0);
  114. DBGMSG(DBG_WARN, ("Command %ws dwError from printui %u\n", (LPCTSTR)strCommand, dwError));
  115. //
  116. // The case statements reperesent errors where we cannot continue executing the
  117. // printer driver update. This is when the spooler dies or the cluster group
  118. // becomes active on a different node
  119. //
  120. switch (dwError)
  121. {
  122. case RPC_S_SERVER_UNAVAILABLE:
  123. //
  124. // We can get access deined when the cluster group moves to a different node.
  125. // Since this process executes in the local system acocunt, this account doesn't
  126. // have permissins to install printer drivers on a remote machine
  127. //
  128. case ERROR_ACCESS_DENIED:
  129. //
  130. // The spooler returns this error when it cannot create temporary directories
  131. // for driver upgrade
  132. //
  133. case ERROR_NO_SYSTEM_RESOURCES:
  134. //
  135. // printui returns this error when it cannot do OpenPrinter(\\server name).
  136. // This means the cluster group is off line (inaccessible)
  137. //
  138. case ERROR_INVALID_PRINTER_NAME:
  139. //
  140. // We will exit the loop since dwError is not error success
  141. //
  142. break;
  143. default:
  144. //
  145. // We continue looping
  146. //
  147. dwError = ERROR_SUCCESS;
  148. }
  149. }
  150. }
  151. }
  152. else
  153. {
  154. dwError = GetLastError();
  155. }
  156. if (hLibrary)
  157. {
  158. FreeLibrary(hLibrary);
  159. }
  160. }
  161. LocalFreeMem(pDriverEnum);
  162. }
  163. DBGMSG(DBG_WARN, ("PSetupClusterDrivers Error %u \n", dwError));
  164. //
  165. // If an error occurs we call ExitProcess. Then the spooler picks up the
  166. // error code using GetExitCodeProcess. If no error occurs, then we
  167. // terminate normally
  168. //
  169. if (dwError != ERROR_SUCCESS)
  170. {
  171. ExitProcess(dwError);
  172. }
  173. return dwError;
  174. }