spoolss: Add missing LeaveCriticalSection on error path (Smatch).
[wine/multimedia.git] / dlls / spoolss / router.c
blob0cd24a7d94f849df8a8080d75f31f6d909e56350
1 /*
2 * Routing for Spooler-Service helper DLL
4 * Copyright 2006-2009 Detlef Riekenberg
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "winreg.h"
28 #include "wingdi.h"
29 #include "winspool.h"
30 #include "ddk/winsplp.h"
31 #include "spoolss.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
37 /* ################################ */
39 #define MAX_BACKEND 3
41 typedef struct {
42 /* PRINTPROVIDOR functions */
43 DWORD (WINAPI *fpOpenPrinter)(LPWSTR, HANDLE *, LPPRINTER_DEFAULTSW);
44 DWORD (WINAPI *fpSetJob)(HANDLE, DWORD, DWORD, LPBYTE, DWORD);
45 DWORD (WINAPI *fpGetJob)(HANDLE, DWORD, DWORD, LPBYTE, DWORD, LPDWORD);
46 DWORD (WINAPI *fpEnumJobs)(HANDLE, DWORD, DWORD, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
47 HANDLE (WINAPI *fpAddPrinter)(LPWSTR, DWORD, LPBYTE);
48 DWORD (WINAPI *fpDeletePrinter)(HANDLE);
49 DWORD (WINAPI *fpSetPrinter)(HANDLE, DWORD, LPBYTE, DWORD);
50 DWORD (WINAPI *fpGetPrinter)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
51 DWORD (WINAPI *fpEnumPrinters)(DWORD, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
52 DWORD (WINAPI *fpAddPrinterDriver)(LPWSTR, DWORD, LPBYTE);
53 DWORD (WINAPI *fpEnumPrinterDrivers)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
54 DWORD (WINAPI *fpGetPrinterDriver)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
55 DWORD (WINAPI *fpGetPrinterDriverDirectory)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
56 DWORD (WINAPI *fpDeletePrinterDriver)(LPWSTR, LPWSTR, LPWSTR);
57 DWORD (WINAPI *fpAddPrintProcessor)(LPWSTR, LPWSTR, LPWSTR, LPWSTR);
58 DWORD (WINAPI *fpEnumPrintProcessors)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
59 DWORD (WINAPI *fpGetPrintProcessorDirectory)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
60 DWORD (WINAPI *fpDeletePrintProcessor)(LPWSTR, LPWSTR, LPWSTR);
61 DWORD (WINAPI *fpEnumPrintProcessorDatatypes)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
62 DWORD (WINAPI *fpStartDocPrinter)(HANDLE, DWORD, LPBYTE);
63 DWORD (WINAPI *fpStartPagePrinter)(HANDLE);
64 DWORD (WINAPI *fpWritePrinter)(HANDLE, LPVOID, DWORD, LPDWORD);
65 DWORD (WINAPI *fpEndPagePrinter)(HANDLE);
66 DWORD (WINAPI *fpAbortPrinter)(HANDLE);
67 DWORD (WINAPI *fpReadPrinter)(HANDLE, LPVOID, DWORD, LPDWORD);
68 DWORD (WINAPI *fpEndDocPrinter)(HANDLE);
69 DWORD (WINAPI *fpAddJob)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
70 DWORD (WINAPI *fpScheduleJob)(HANDLE, DWORD);
71 DWORD (WINAPI *fpGetPrinterData)(HANDLE, LPWSTR, LPDWORD, LPBYTE, DWORD, LPDWORD);
72 DWORD (WINAPI *fpSetPrinterData)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD);
73 DWORD (WINAPI *fpWaitForPrinterChange)(HANDLE, DWORD);
74 DWORD (WINAPI *fpClosePrinter)(HANDLE);
75 DWORD (WINAPI *fpAddForm)(HANDLE, DWORD, LPBYTE);
76 DWORD (WINAPI *fpDeleteForm)(HANDLE, LPWSTR);
77 DWORD (WINAPI *fpGetForm)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
78 DWORD (WINAPI *fpSetForm)(HANDLE, LPWSTR, DWORD, LPBYTE);
79 DWORD (WINAPI *fpEnumForms)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
80 DWORD (WINAPI *fpEnumMonitors)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
81 DWORD (WINAPI *fpEnumPorts)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
82 DWORD (WINAPI *fpAddPort)(LPWSTR, HWND, LPWSTR);
83 DWORD (WINAPI *fpConfigurePort)(LPWSTR, HWND, LPWSTR);
84 DWORD (WINAPI *fpDeletePort)(LPWSTR, HWND, LPWSTR);
85 HANDLE (WINAPI *fpCreatePrinterIC)(HANDLE, LPDEVMODEW);
86 DWORD (WINAPI *fpPlayGdiScriptOnPrinterIC)(HANDLE, LPBYTE, DWORD, LPBYTE, DWORD, DWORD);
87 DWORD (WINAPI *fpDeletePrinterIC)(HANDLE);
88 DWORD (WINAPI *fpAddPrinterConnection)(LPWSTR);
89 DWORD (WINAPI *fpDeletePrinterConnection)(LPWSTR);
90 DWORD (WINAPI *fpPrinterMessageBox)(HANDLE, DWORD, HWND, LPWSTR, LPWSTR, DWORD);
91 DWORD (WINAPI *fpAddMonitor)(LPWSTR, DWORD, LPBYTE);
92 DWORD (WINAPI *fpDeleteMonitor)(LPWSTR, LPWSTR, LPWSTR);
93 DWORD (WINAPI *fpResetPrinter)(HANDLE, LPPRINTER_DEFAULTSW);
94 DWORD (WINAPI *fpGetPrinterDriverEx)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, DWORD, DWORD, PDWORD, PDWORD);
95 HANDLE (WINAPI *fpFindFirstPrinterChangeNotification)(HANDLE, DWORD, DWORD, LPVOID);
96 DWORD (WINAPI *fpFindClosePrinterChangeNotification)(HANDLE);
97 DWORD (WINAPI *fpAddPortEx)(HANDLE, LPWSTR, DWORD, LPBYTE, LPWSTR);
98 DWORD (WINAPI *fpShutDown)(LPVOID);
99 DWORD (WINAPI *fpRefreshPrinterChangeNotification)(HANDLE, DWORD, PVOID, PVOID);
100 DWORD (WINAPI *fpOpenPrinterEx)(LPWSTR, LPHANDLE, LPPRINTER_DEFAULTSW, LPBYTE, DWORD);
101 HANDLE (WINAPI *fpAddPrinterEx)(LPWSTR, DWORD, LPBYTE, LPBYTE, DWORD);
102 DWORD (WINAPI *fpSetPort)(LPWSTR, LPWSTR, DWORD, LPBYTE);
103 DWORD (WINAPI *fpEnumPrinterData)(HANDLE, DWORD, LPWSTR, DWORD, LPDWORD, LPDWORD, LPBYTE, DWORD, LPDWORD);
104 DWORD (WINAPI *fpDeletePrinterData)(HANDLE, LPWSTR);
105 DWORD (WINAPI *fpClusterSplOpen)(LPCWSTR, LPCWSTR, PHANDLE, LPCWSTR, LPCWSTR);
106 DWORD (WINAPI *fpClusterSplClose)(HANDLE);
107 DWORD (WINAPI *fpClusterSplIsAlive)(HANDLE);
108 DWORD (WINAPI *fpSetPrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR, DWORD, LPBYTE, DWORD);
109 DWORD (WINAPI *fpGetPrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR, LPDWORD, LPBYTE, DWORD, LPDWORD);
110 DWORD (WINAPI *fpEnumPrinterDataEx)(HANDLE, LPCWSTR, LPBYTE, DWORD, LPDWORD, LPDWORD);
111 DWORD (WINAPI *fpEnumPrinterKey)(HANDLE, LPCWSTR, LPWSTR, DWORD, LPDWORD);
112 DWORD (WINAPI *fpDeletePrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR);
113 DWORD (WINAPI *fpDeletePrinterKey)(HANDLE hPrinter, LPCWSTR pKeyName);
114 DWORD (WINAPI *fpSeekPrinter)(HANDLE, LARGE_INTEGER, PLARGE_INTEGER, DWORD, BOOL);
115 DWORD (WINAPI *fpDeletePrinterDriverEx)(LPWSTR, LPWSTR, LPWSTR, DWORD, DWORD);
116 DWORD (WINAPI *fpAddPerMachineConnection)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
117 DWORD (WINAPI *fpDeletePerMachineConnection)(LPCWSTR, LPCWSTR);
118 DWORD (WINAPI *fpEnumPerMachineConnections)(LPCWSTR, LPBYTE, DWORD, LPDWORD, LPDWORD);
119 DWORD (WINAPI *fpXcvData)(HANDLE, LPCWSTR, PBYTE, DWORD, PBYTE, DWORD, PDWORD, PDWORD);
120 DWORD (WINAPI *fpAddPrinterDriverEx)(LPWSTR, DWORD, LPBYTE, DWORD);
121 DWORD (WINAPI *fpSplReadPrinter)(HANDLE, LPBYTE *, DWORD);
122 DWORD (WINAPI *fpDriverUnloadComplete)(LPWSTR);
123 DWORD (WINAPI *fpGetSpoolFileInfo)(HANDLE, LPWSTR *, LPHANDLE, HANDLE, HANDLE);
124 DWORD (WINAPI *fpCommitSpoolData)(HANDLE, DWORD);
125 DWORD (WINAPI *fpCloseSpoolFileHandle)(HANDLE);
126 DWORD (WINAPI *fpFlushPrinter)(HANDLE, LPBYTE, DWORD, LPDWORD, DWORD);
127 DWORD (WINAPI *fpSendRecvBidiData)(HANDLE, LPCWSTR, LPBIDI_REQUEST_CONTAINER, LPBIDI_RESPONSE_CONTAINER *);
128 DWORD (WINAPI *fpAddDriverCatalog)(HANDLE, DWORD, VOID *, DWORD);
129 /* Private Data */
130 HMODULE dll;
131 LPWSTR dllname;
132 LPWSTR name;
133 LPWSTR regroot;
134 DWORD index;
135 } backend_t;
137 /* ################################ */
139 static backend_t *backend[MAX_BACKEND];
140 static DWORD used_backends = 0;
142 static CRITICAL_SECTION backend_cs;
143 static CRITICAL_SECTION_DEBUG backend_cs_debug =
145 0, 0, &backend_cs,
146 { &backend_cs_debug.ProcessLocksList, &backend_cs_debug.ProcessLocksList },
147 0, 0, { (DWORD_PTR)(__FILE__ ": backend_cs") }
149 static CRITICAL_SECTION backend_cs = { &backend_cs_debug, -1, 0, 0, 0, 0 };
151 /* ################################ */
153 static WCHAR localsplW[] = {'l','o','c','a','l','s','p','l','.','d','l','l',0};
155 /******************************************************************
156 * strdupW [internal]
158 * create a copy of a unicode-string
162 static LPWSTR strdupW(LPCWSTR p)
164 LPWSTR ret;
165 DWORD len;
167 if(!p) return NULL;
168 len = (lstrlenW(p) + 1) * sizeof(WCHAR);
169 ret = heap_alloc(len);
170 memcpy(ret, p, len);
171 return ret;
174 /******************************************************************
175 * backend_unload_all [internal]
177 * unload all backends
179 void backend_unload_all(void)
181 EnterCriticalSection(&backend_cs);
182 while (used_backends > 0) {
183 used_backends--;
184 FreeLibrary(backend[used_backends]->dll);
185 heap_free(backend[used_backends]->dllname);
186 heap_free(backend[used_backends]->name);
187 heap_free(backend[used_backends]->regroot);
188 heap_free(backend[used_backends]);
189 backend[used_backends] = NULL;
191 LeaveCriticalSection(&backend_cs);
194 /******************************************************************************
195 * backend_load [internal]
197 * load and init a backend
199 * PARAMS
200 * name [I] Printprovider to use for the backend. NULL for the local print provider
202 * RETURNS
203 * Success: PTR to the backend
204 * Failure: NULL
207 static backend_t * backend_load(LPWSTR dllname, LPWSTR name, LPWSTR regroot)
210 BOOL (WINAPI *pInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR);
211 DWORD id;
212 DWORD res;
214 EnterCriticalSection(&backend_cs);
215 id = used_backends;
217 backend[id] = heap_alloc_zero(sizeof(backend_t));
218 if (!backend[id]) {
219 LeaveCriticalSection(&backend_cs);
220 return NULL;
223 backend[id]->dllname = strdupW(dllname);
224 backend[id]->name = strdupW(name);
225 backend[id]->regroot = strdupW(regroot);
227 backend[id]->dll = LoadLibraryW(dllname);
228 if (backend[id]->dll) {
229 pInitializePrintProvidor = (void *) GetProcAddress(backend[id]->dll, "InitializePrintProvidor");
230 if (pInitializePrintProvidor) {
232 /* native localspl does not clear unused entries */
233 res = pInitializePrintProvidor((PRINTPROVIDOR *) backend[id], sizeof(PRINTPROVIDOR), regroot);
234 if (res) {
235 used_backends++;
236 backend[id]->index = used_backends;
237 LeaveCriticalSection(&backend_cs);
238 TRACE("--> backend #%d: %p (%s)\n", id, backend[id], debugstr_w(dllname));
239 return backend[id];
242 FreeLibrary(backend[id]->dll);
244 heap_free(backend[id]->dllname);
245 heap_free(backend[id]->name);
246 heap_free(backend[id]->regroot);
247 heap_free(backend[id]);
248 backend[id] = NULL;
249 LeaveCriticalSection(&backend_cs);
250 WARN("failed to init %s: %u\n", debugstr_w(dllname), GetLastError());
251 return NULL;
254 /******************************************************************************
255 * backend_load_all [internal]
257 * load and init all backends
259 * RETURNS
260 * Success: TRUE
261 * Failure: FALSE
264 BOOL backend_load_all(void)
266 backend_t * pb;
268 pb = backend_load(localsplW, NULL, NULL);
270 /* ToDo: parse the registry and load all other backends */
272 return (pb != NULL);