Leaked source code of windows server 2003
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.

417 lines
11 KiB

  1. /*++
  2. Copyright (c) 1996 - 1998 Microsoft Corporation
  3. Module Name:
  4. config.c
  5. Abstract:
  6. Routines to do multiple hardware profile support for printing
  7. Author:
  8. Muhunthan Sivapragasam (MuhuntS) 07-Nov-96 (Rewrite from Win95)
  9. Revision History:
  10. --*/
  11. #include <precomp.h>
  12. #include "config.h"
  13. #include "clusspl.h"
  14. #include <devguid.h>
  15. #define CM_REGSITRY_CONFIG 0x00000200
  16. WCHAR cszPnPKey[] = L"PnPData";
  17. WCHAR cszPrinter[] = L"Printer";
  18. WCHAR cszPrinterOnLine[] = L"PrinterOnLine";
  19. WCHAR cszDeviceInstanceId[] = L"DeviceInstanceId";
  20. WCHAR cszRegistryConfig[] = L"System\\CurrentControlSet\\Hardware Profiles\\";
  21. BOOL
  22. LoadSetupApiDll(
  23. PSETUPAPI_INFO pSetupInfo
  24. )
  25. {
  26. UINT uOldErrMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  27. pSetupInfo->hSetupApi = LoadLibrary(L"setupapi");
  28. SetErrorMode(uOldErrMode);
  29. if ( !pSetupInfo->hSetupApi )
  30. return FALSE;
  31. (FARPROC) pSetupInfo->pfnDestroyDeviceInfoList
  32. = GetProcAddress(pSetupInfo->hSetupApi,
  33. "SetupDiDestroyDeviceInfoList");
  34. (FARPROC) pSetupInfo->pfnGetClassDevs
  35. = GetProcAddress(pSetupInfo->hSetupApi,
  36. "SetupDiGetClassDevsA");
  37. (FARPROC) pSetupInfo->pfnRemoveDevice
  38. = GetProcAddress(pSetupInfo->hSetupApi,
  39. "SetupDiRemoveDevice");
  40. (FARPROC) pSetupInfo->pfnOpenDeviceInfo
  41. = GetProcAddress(pSetupInfo->hSetupApi,
  42. "SetupDiOpenDeviceInfoW");
  43. if ( !pSetupInfo->pfnDestroyDeviceInfoList ||
  44. !pSetupInfo->pfnGetClassDevs ||
  45. !pSetupInfo->pfnRemoveDevice ||
  46. !pSetupInfo->pfnOpenDeviceInfo ) {
  47. FreeLibrary(pSetupInfo->hSetupApi);
  48. pSetupInfo->hSetupApi = NULL;
  49. return FALSE;
  50. }
  51. return TRUE;
  52. }
  53. BOOL
  54. DeletePrinterDevNode(
  55. LPWSTR pszDeviceInstanceId
  56. )
  57. {
  58. BOOL bRet = FALSE;
  59. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  60. SP_DEVINFO_DATA DevData;
  61. SETUPAPI_INFO SetupInfo;
  62. HANDLE UserToken;
  63. if ( !LoadSetupApiDll(&SetupInfo) )
  64. return FALSE;
  65. UserToken = RevertToPrinterSelf();
  66. hDevInfo = SetupInfo.pfnGetClassDevs((LPGUID)&GUID_DEVCLASS_PRINTER,
  67. NULL,
  68. INVALID_HANDLE_VALUE,
  69. 0);
  70. if ( hDevInfo == INVALID_HANDLE_VALUE )
  71. goto Cleanup;
  72. DevData.cbSize = sizeof(DevData);
  73. if ( SetupInfo.pfnOpenDeviceInfo(hDevInfo,
  74. pszDeviceInstanceId,
  75. INVALID_HANDLE_VALUE,
  76. 0,
  77. &DevData) ) {
  78. bRet = SetupInfo.pfnRemoveDevice(hDevInfo, &DevData);
  79. }
  80. Cleanup:
  81. if ( hDevInfo != INVALID_HANDLE_VALUE )
  82. SetupInfo.pfnDestroyDeviceInfoList(hDevInfo);
  83. if (!ImpersonatePrinterClient(UserToken))
  84. {
  85. DBGMSG(DBG_ERROR, ("DeletePrinterDevNode: ImpersonatePrinterClient Failed. Error %d\n", GetLastError()));
  86. }
  87. FreeLibrary(SetupInfo.hSetupApi);
  88. return bRet;
  89. }
  90. LPWSTR
  91. GetPrinterDeviceInstanceId(
  92. PINIPRINTER pIniPrinter
  93. )
  94. {
  95. WCHAR buf[MAX_PATH];
  96. DWORD dwType, cbNeeded, dwReturn;
  97. HKEY hKey = NULL;
  98. LPWSTR pszDeviceInstanceId = NULL;
  99. SplInSem();
  100. cbNeeded = sizeof(buf);
  101. if ( ERROR_SUCCESS == OpenPrinterKey(pIniPrinter,
  102. KEY_READ,
  103. &hKey,
  104. cszPnPKey,
  105. TRUE) &&
  106. ERROR_SUCCESS == SplRegQueryValue(hKey,
  107. cszDeviceInstanceId,
  108. &dwType,
  109. (LPBYTE)buf,
  110. &cbNeeded,
  111. pIniPrinter->pIniSpooler) &&
  112. dwType == REG_SZ ) {
  113. pszDeviceInstanceId = AllocSplStr(buf);
  114. }
  115. if ( hKey )
  116. SplRegCloseKey(hKey, pIniPrinter->pIniSpooler);
  117. return pszDeviceInstanceId;
  118. }
  119. BOOL
  120. DeleteIniPrinterDevNode(
  121. PINIPRINTER pIniPrinter
  122. )
  123. {
  124. BOOL bRet = FALSE;
  125. LPWSTR pszStr = GetPrinterDeviceInstanceId(pIniPrinter);
  126. if ( pszStr ) {
  127. bRet = DeletePrinterDevNode(pszStr);
  128. FreeSplStr(pszStr);
  129. }
  130. return bRet;
  131. }
  132. VOID
  133. SplConfigChange(
  134. )
  135. {
  136. PINIPRINTER pIniPrinter = NULL;
  137. BOOL bCheckScheduler = FALSE;
  138. HKEY hConfig = NULL;
  139. HKEY hKey;
  140. DWORD dwOnline, dwType, cbNeeded;
  141. EnterSplSem();
  142. //
  143. // If we have no printers which are offline then we would not have
  144. // created the key at all
  145. //
  146. if ( RegCreateKeyEx(HKEY_CURRENT_CONFIG,
  147. ipszRegistryPrinters,
  148. 0,
  149. NULL,
  150. 0,
  151. KEY_READ,
  152. NULL,
  153. &hConfig,
  154. NULL) )
  155. goto Cleanup;
  156. for ( pIniPrinter = pLocalIniSpooler->pIniPrinter ;
  157. pIniPrinter ;
  158. pIniPrinter = pIniPrinter->pNext ) {
  159. //
  160. // Don't consider printers that have invalid ports, these must always
  161. // stay offline until this is resolved. If the user explicitely turns
  162. // the port online, that is up to them.
  163. //
  164. UINT i = 0;
  165. //
  166. // If pIniPrinter->ppIniPorts is NULL, cPorts would be zero.
  167. //
  168. for(i = 0; i < pIniPrinter->cPorts; i++) {
  169. if (pIniPrinter->ppIniPorts[i]->Status & PP_PLACEHOLDER) {
  170. break;
  171. }
  172. }
  173. //
  174. // If we reached the end of the list, none of the ports were
  175. // placeholders. If we didn't go onto the next one.
  176. //
  177. if (i < pIniPrinter->cPorts) {
  178. continue;
  179. }
  180. if ( RegOpenKeyEx(hConfig,
  181. pIniPrinter->pName,
  182. 0,
  183. KEY_READ,
  184. &hKey) )
  185. continue; // to next printer
  186. cbNeeded = sizeof(dwOnline);
  187. if ( ERROR_SUCCESS == SplRegQueryValue(hKey,
  188. cszPrinterOnLine,
  189. &dwType,
  190. (LPBYTE)&dwOnline,
  191. &cbNeeded,
  192. NULL) ) {
  193. if ( dwOnline ) {
  194. //
  195. // If any printers which are offline in current config
  196. // become online in the new config then we need to trigger
  197. // the scheduler
  198. //
  199. if ( pIniPrinter->Attributes & PRINTER_ATTRIBUTE_WORK_OFFLINE ) {
  200. pIniPrinter->Attributes &= ~PRINTER_ATTRIBUTE_WORK_OFFLINE;
  201. bCheckScheduler = TRUE;
  202. }
  203. } else {
  204. pIniPrinter->Attributes |= PRINTER_ATTRIBUTE_WORK_OFFLINE;
  205. }
  206. }
  207. RegCloseKey(hKey);
  208. }
  209. if ( bCheckScheduler )
  210. CHECK_SCHEDULER();
  211. Cleanup:
  212. LeaveSplSem();
  213. if ( hConfig )
  214. RegCloseKey(hConfig);
  215. }
  216. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  217. DeletePrinterInAllConfigs
  218. Routine Description:
  219. Deletes a pIniPrinter from all the hardware profiles.
  220. Arguments:
  221. pIniPrinter - Printer to delete.
  222. Return Value:
  223. BOOL, TRUE = success, FALSE = FAILUER
  224. Last Error:
  225. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  226. BOOL
  227. DeletePrinterInAllConfigs(
  228. PINIPRINTER pIniPrinter
  229. )
  230. {
  231. HKEY hConfig;
  232. WCHAR szSubKey[2 * MAX_PATH];
  233. DWORD Config;
  234. DWORD Size;
  235. DWORD Status;
  236. SplInSem();
  237. Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  238. cszRegistryConfig,
  239. 0,
  240. KEY_READ | KEY_WRITE | DELETE,
  241. &hConfig);
  242. if (Status != ERROR_SUCCESS)
  243. {
  244. DBGMSG(DBG_WARN, ("DeletePrinterInAllConfigs: RegOpenKey failed %d\n", Status));
  245. }
  246. else
  247. {
  248. DWORD RegPrintersLen = wcslen(ipszRegistryPrinters);
  249. for (Config = 0;
  250. Size = (DWORD)(COUNTOF(szSubKey) - ( RegPrintersLen + wcslen(pIniPrinter->pName) +2)) ,
  251. (Status = RegEnumKeyEx(hConfig,
  252. Config,
  253. szSubKey,
  254. &Size,
  255. NULL,
  256. NULL,
  257. NULL,
  258. NULL)) == ERROR_SUCCESS;
  259. ++Config)
  260. {
  261. StrNCatBuff(szSubKey, COUNTOF(szSubKey), L"\\", ipszRegistryPrinters, L"\\", pIniPrinter->pName, NULL);
  262. Status = RegDeleteKey(hConfig, szSubKey);
  263. if (Status != ERROR_SUCCESS &&
  264. Status != ERROR_FILE_NOT_FOUND)
  265. {
  266. DBGMSG( DBG_WARN, ("DeletePrinterInAllConfigs: RegDeleteKey failed %d\n", Status));
  267. }
  268. }
  269. if (Status != ERROR_NO_MORE_ITEMS)
  270. {
  271. DBGMSG(DBG_WARN, ("DeletePrinterInAllConfigs: RegEnumKey failed %d\n", Status));
  272. }
  273. RegCloseKey(hConfig);
  274. }
  275. return TRUE;
  276. }
  277. BOOL
  278. WritePrinterOnlineStatusInCurrentConfig(
  279. PINIPRINTER pIniPrinter
  280. )
  281. {
  282. HKEY hKey = NULL;
  283. DWORD dwOnline, dwReturn;
  284. WCHAR szKey[2 * MAX_PATH];
  285. HANDLE hToken;
  286. SplInSem();
  287. hToken = RevertToPrinterSelf();
  288. StrNCatBuff(szKey, COUNTOF(szKey), ipszRegistryPrinters, L"\\", pIniPrinter->pName, NULL);
  289. dwOnline = (pIniPrinter->Attributes & PRINTER_ATTRIBUTE_WORK_OFFLINE)
  290. ? 0 : 1;
  291. dwReturn = RegCreateKeyEx(HKEY_CURRENT_CONFIG,
  292. szKey,
  293. 0,
  294. NULL,
  295. 0,
  296. KEY_WRITE,
  297. NULL,
  298. &hKey,
  299. NULL);
  300. if ( dwReturn == ERROR_SUCCESS )
  301. dwReturn = RegSetValueEx(hKey,
  302. cszPrinterOnLine,
  303. 0,
  304. REG_DWORD,
  305. (LPBYTE)&dwOnline,
  306. sizeof(DWORD));
  307. if ( hKey )
  308. RegCloseKey(hKey);
  309. ImpersonatePrinterClient(hToken);
  310. return dwReturn == ERROR_SUCCESS;
  311. }