Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / win32ss / printing / base / spoolss / main.c
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()
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 if (!pTable[i])
231 return FALSE;
232
233 return TRUE;
234 }
235
236 BOOL WINAPI
237 SplIsUpgrade()
238 {
239 return FALSE;
240 }
241
242 BOOL WINAPI
243 SpoolerInit()
244 {
245 // Nothing to do here yet
246 SetLastError(ERROR_SUCCESS);
247 return TRUE;
248 }
249
250 BOOL WINAPI
251 BuildOtherNamesFromMachineName(LPVOID * ptr1, LPVOID * ptr2)
252 {
253 FIXME("(%p, %p) stub\n", ptr1, ptr2);
254
255 *ptr1 = NULL;
256 *ptr2 = NULL;
257 return FALSE;
258 }
259