1 /* 2 * PROJECT: ReactOS Spooler Router 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Main functions 5 * COPYRIGHT: Copyright 2015 Colin Finck (colin@reactos.org) 6 */ 7 8 #include "precomp.h" 9 10 // Global Variables 11 HANDLE hProcessHeap; 12 LIST_ENTRY PrintProviderList; 13 14 15 static DWORD 16 _AddPrintProviderToList(PCWSTR pwszFileName) 17 { 18 DWORD dwErrorCode; 19 HINSTANCE hinstPrintProvider; 20 PInitializePrintProvidor pfnInitializePrintProvidor; 21 PSPOOLSS_PRINT_PROVIDER pPrintProvider = NULL; 22 23 // Try to load it. 24 hinstPrintProvider = LoadLibraryW(pwszFileName); 25 if (!hinstPrintProvider) 26 { 27 dwErrorCode = GetLastError(); 28 ERR("LoadLibraryW failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode); 29 goto Cleanup; 30 } 31 32 // Get the initialization routine. 33 pfnInitializePrintProvidor = (PInitializePrintProvidor)GetProcAddress(hinstPrintProvider, "InitializePrintProvidor"); 34 if (!pfnInitializePrintProvidor) 35 { 36 dwErrorCode = GetLastError(); 37 ERR("GetProcAddress failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode); 38 goto Cleanup; 39 } 40 41 // Create a new SPOOLSS_PRINT_PROVIDER structure for it. 42 pPrintProvider = DllAllocSplMem(sizeof(SPOOLSS_PRINT_PROVIDER)); 43 if (!pPrintProvider) 44 { 45 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; 46 ERR("DllAllocSplMem failed!\n"); 47 goto Cleanup; 48 } 49 50 // Call the Print Provider initialization function. 51 if (!pfnInitializePrintProvidor(&pPrintProvider->PrintProvider, sizeof(PRINTPROVIDOR), NULL)) 52 { 53 dwErrorCode = GetLastError(); 54 ERR("InitializePrintProvidor failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode); 55 goto Cleanup; 56 } 57 58 // Add this Print Provider to the list. 59 InsertTailList(&PrintProviderList, &pPrintProvider->Entry); 60 61 // Don't let the cleanup routine free this. 62 pPrintProvider = NULL; 63 dwErrorCode = ERROR_SUCCESS; 64 65 Cleanup: 66 if (pPrintProvider) 67 DllFreeSplMem(pPrintProvider); 68 69 return dwErrorCode; 70 } 71 72 static BOOL 73 _InitializePrintProviderList(VOID) 74 { 75 DWORD cbFileName; 76 DWORD cchMaxSubKey; 77 DWORD cchPrintProviderName; 78 DWORD dwErrorCode; 79 DWORD dwSubKeys; 80 DWORD i; 81 HKEY hKey = NULL; 82 HKEY hSubKey = NULL; 83 PWSTR pwszPrintProviderName = NULL; 84 WCHAR wszFileName[MAX_PATH]; 85 86 // Initialize an empty list for our Print Providers. 87 InitializeListHead(&PrintProviderList); 88 89 // First add the Local Spooler. 90 // This one must exist and must be the first one in the list. 91 dwErrorCode = _AddPrintProviderToList(L"localspl"); 92 if (dwErrorCode != ERROR_SUCCESS) 93 { 94 ERR("The Local Spooler could not be loaded!\n"); 95 goto Cleanup; 96 } 97 98 // Now add additional Print Providers from the registry. 99 // First of all, open the key containing print providers. 100 dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Providers", 0, KEY_READ, &hKey); 101 if (dwErrorCode != ERROR_SUCCESS) 102 { 103 ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); 104 goto Cleanup; 105 } 106 107 // Get the number of Print Providers and maximum sub key length. 108 dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL); 109 if (dwErrorCode != ERROR_SUCCESS) 110 { 111 ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); 112 goto Cleanup; 113 } 114 115 // Allocate a temporary buffer for the Print Provider names. 116 pwszPrintProviderName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR)); 117 if (!pwszPrintProviderName) 118 { 119 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; 120 ERR("DllAllocSplMem failed!\n"); 121 goto Cleanup; 122 } 123 124 // Loop through all available Print Providers. 125 for (i = 0; i < dwSubKeys; i++) 126 { 127 // Cleanup tasks from the previous run 128 if (hSubKey) 129 { 130 RegCloseKey(hSubKey); 131 hSubKey = NULL; 132 } 133 134 // Get the name of this Print Provider. 135 cchPrintProviderName = cchMaxSubKey + 1; 136 dwErrorCode = (DWORD)RegEnumKeyExW(hKey, i, pwszPrintProviderName, &cchPrintProviderName, NULL, NULL, NULL, NULL); 137 if (dwErrorCode != ERROR_SUCCESS) 138 { 139 ERR("RegEnumKeyExW failed for iteration %lu with status %lu!\n", i, dwErrorCode); 140 continue; 141 } 142 143 // Open this Print Provider's registry key. 144 dwErrorCode = (DWORD)RegOpenKeyExW(hKey, pwszPrintProviderName, 0, KEY_READ, &hSubKey); 145 if (dwErrorCode != ERROR_SUCCESS) 146 { 147 ERR("RegOpenKeyExW failed for Print Provider \"%S\" with status %lu!\n", pwszPrintProviderName, dwErrorCode); 148 continue; 149 } 150 151 // Get the file name of the Print Provider. 152 cbFileName = MAX_PATH * sizeof(WCHAR); 153 dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Driver", NULL, NULL, (PBYTE)wszFileName, &cbFileName); 154 if (dwErrorCode != ERROR_SUCCESS) 155 { 156 ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode); 157 continue; 158 } 159 160 // Load and add it to the list. 161 dwErrorCode = _AddPrintProviderToList(wszFileName); 162 if (dwErrorCode != ERROR_SUCCESS) 163 continue; 164 } 165 166 dwErrorCode = ERROR_SUCCESS; 167 168 Cleanup: 169 // Inside the loop 170 if (hSubKey) 171 RegCloseKey(hSubKey); 172 173 // Outside the loop 174 if (pwszPrintProviderName) 175 DllFreeSplMem(pwszPrintProviderName); 176 177 if (hKey) 178 RegCloseKey(hKey); 179 180 SetLastError(dwErrorCode); 181 return (dwErrorCode == ERROR_SUCCESS); 182 } 183 184 BOOL WINAPI 185 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 186 { 187 switch (fdwReason) 188 { 189 case DLL_PROCESS_ATTACH: 190 DisableThreadLibraryCalls(hinstDLL); 191 hProcessHeap = GetProcessHeap(); 192 break; 193 } 194 195 return TRUE; 196 } 197 198 BOOL WINAPI 199 InitializeRouter(HANDLE SpoolerStatusHandle) 200 { 201 return _InitializePrintProviderList(); 202 } 203 204 BOOL WINAPI 205 SplInitializeWinSpoolDrv(PVOID* pTable) 206 { 207 HINSTANCE hWinspool; 208 int i; 209 210 hWinspool = LoadLibraryW(L"winspool.drv"); 211 if (!hWinspool) 212 { 213 ERR("Could not load winspool.drv, last error is %lu!\n", GetLastError()); 214 return FALSE; 215 } 216 217 // Get the function pointers which are meant to be returned by this function. 218 pTable[0] = GetProcAddress(hWinspool, "OpenPrinterW"); 219 pTable[1] = GetProcAddress(hWinspool, "ClosePrinter"); 220 pTable[2] = GetProcAddress(hWinspool, "SpoolerDevQueryPrintW"); 221 pTable[3] = GetProcAddress(hWinspool, "SpoolerPrinterEvent"); 222 pTable[4] = GetProcAddress(hWinspool, "DocumentPropertiesW"); 223 pTable[5] = GetProcAddress(hWinspool, (LPSTR)212); 224 pTable[6] = GetProcAddress(hWinspool, (LPSTR)213); 225 pTable[7] = GetProcAddress(hWinspool, (LPSTR)214); 226 pTable[8] = GetProcAddress(hWinspool, (LPSTR)215); 227 228 // Verify that all calls succeeded. 229 for (i = 0; i < 9; i++) 230 { 231 if (!pTable[i]) 232 { 233 FreeLibrary(hWinspool); 234 return FALSE; 235 } 236 } 237 238 return TRUE; 239 } 240 241 BOOL WINAPI 242 SplIsUpgrade(VOID) 243 { 244 return FALSE; 245 } 246 247 BOOL WINAPI 248 SpoolerInit(VOID) 249 { 250 // Nothing to do here yet 251 SetLastError(ERROR_SUCCESS); 252 return TRUE; 253 } 254 255 BOOL WINAPI 256 BuildOtherNamesFromMachineName(LPVOID * ptr1, LPVOID * ptr2) 257 { 258 FIXME("(%p, %p) stub\n", ptr1, ptr2); 259 260 *ptr1 = NULL; 261 *ptr2 = NULL; 262 return FALSE; 263 } 264 265