xref: /reactos/win32ss/printing/base/spoolss/main.c (revision 144e984b)
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, ULONG * ptr2)
257 {
258     FIXME("(%p, %p) stub\n", ptr1, ptr2);
259 
260     *ptr1 = NULL;
261     *ptr2 = 0;
262     return FALSE;
263 }
264 
265