55b5c23d249f549a85db5ca23133dfd229676732
[reactos.git] / reactos / dll / win32 / winspool / info.c
1 /*
2 * WINSPOOL functions
3 *
4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
7 * Copyright 1999, 2000 Huw D M Davies
8 * Copyright 2001 Marcus Meissner
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "precomp.h"
26
27 #include <winreg.h>
28 #include <winnls.h>
29 #include <shlwapi.h>
30
31 #include <wine/debug.h>
32
33 WINE_DEFAULT_DEBUG_CHANNEL(winspool);
34
35 /******************************************************************************
36 * GetDefaultPrinterA (WINSPOOL.@)
37 */
38 BOOL WINAPI GetDefaultPrinterA(LPSTR name, LPDWORD namesize)
39 {
40 char *ptr;
41
42 if (*namesize < 1)
43 {
44 SetLastError (ERROR_INSUFFICIENT_BUFFER);
45 return FALSE;
46 }
47
48 if (!GetProfileStringA ("windows", "device", "", name, *namesize))
49 {
50 SetLastError (ERROR_FILE_NOT_FOUND);
51 return FALSE;
52 }
53
54 if ((ptr = strchr (name, ',')) == NULL)
55 {
56 SetLastError (ERROR_FILE_NOT_FOUND);
57 return FALSE;
58 }
59
60 *ptr = '\0';
61 *namesize = strlen (name) + 1;
62 return TRUE;
63 }
64
65
66 /******************************************************************************
67 * GetDefaultPrinterW (WINSPOOL.@)
68 */
69 BOOL WINAPI GetDefaultPrinterW(LPWSTR name, LPDWORD namesize)
70 {
71 char *buf;
72 BOOL ret;
73
74 if (*namesize < 1)
75 {
76 SetLastError (ERROR_INSUFFICIENT_BUFFER);
77 return FALSE;
78 }
79
80 buf = HeapAlloc (GetProcessHeap (), 0, *namesize);
81 ret = GetDefaultPrinterA (buf, namesize);
82 if (ret)
83 {
84 DWORD len = MultiByteToWideChar (CP_ACP, 0, buf, -1, name, *namesize);
85 if (!len)
86 {
87 SetLastError (ERROR_INSUFFICIENT_BUFFER);
88 ret = FALSE;
89 }
90 else *namesize = len;
91 }
92
93 HeapFree (GetProcessHeap (), 0, buf);
94 return ret;
95 }
96
97 /******************************************************************************
98 * AddPrintProvidorA (WINSPOOL.@)
99 */
100 BOOL
101 WINAPI
102 AddPrintProvidorA(LPSTR Name, DWORD Level, PBYTE Buffer)
103 {
104 if (Name || Level > 2 || Buffer == NULL)
105 {
106 SetLastError(ERROR_INVALID_PARAMETER);
107 return FALSE;
108 }
109
110 if (Level == 1)
111 {
112 BOOL bRet;
113 PROVIDOR_INFO_1W Provider;
114 PROVIDOR_INFO_1A *Prov = (PROVIDOR_INFO_1A*)Buffer;
115
116 if (Prov->pName == NULL || Prov->pDLLName == NULL || Prov->pEnvironment == NULL)
117 {
118 return FALSE;
119 }
120
121 Provider.pDLLName = HeapAlloc(GetProcessHeap(), 0, (strlen(Prov->pDLLName)+1) * sizeof(WCHAR));
122 if (Provider.pDLLName)
123 {
124 MultiByteToWideChar(CP_ACP, 0, Prov->pDLLName, -1, Provider.pDLLName, strlen(Prov->pDLLName)+1);
125 Provider.pDLLName[strlen(Prov->pDLLName)] = L'\0';
126 }
127
128 Provider.pEnvironment = HeapAlloc(GetProcessHeap(), 0, (strlen(Prov->pEnvironment)+1) * sizeof(WCHAR));
129 if (Provider.pEnvironment)
130 {
131 MultiByteToWideChar(CP_ACP, 0, Prov->pEnvironment, -1, Provider.pEnvironment, strlen(Prov->pEnvironment)+1);
132 Provider.pEnvironment[strlen(Prov->pEnvironment)] = L'\0';
133 }
134
135 Provider.pName = HeapAlloc(GetProcessHeap(), 0, (strlen(Prov->pName)+1) * sizeof(WCHAR));
136 if (Provider.pName)
137 {
138 MultiByteToWideChar(CP_ACP, 0, Prov->pName, -1, Provider.pName, strlen(Prov->pName)+1);
139 Provider.pName[strlen(Prov->pName)] = L'\0';
140 }
141
142 bRet = AddPrintProvidorW(NULL, Level, (LPBYTE)&Provider);
143
144 if (Provider.pDLLName)
145 HeapFree(GetProcessHeap(), 0, Provider.pDLLName);
146
147 if (Provider.pEnvironment)
148 HeapFree(GetProcessHeap(), 0, Provider.pEnvironment);
149
150 if (Provider.pName)
151 HeapFree(GetProcessHeap(), 0, Provider.pName);
152
153 return bRet;
154 }
155 else
156 {
157 PROVIDOR_INFO_2W Provider;
158 PROVIDOR_INFO_2A *Prov = (PROVIDOR_INFO_2A*)Buffer;
159
160 Provider.pOrder = HeapAlloc(GetProcessHeap(), 0, (strlen(Prov->pOrder)+1) * sizeof(WCHAR));
161 if (Provider.pOrder)
162 {
163 BOOL bRet;
164 MultiByteToWideChar(CP_ACP, 0, Prov->pOrder, -1, Provider.pOrder, strlen(Prov->pOrder)+1);
165 Provider.pOrder[strlen(Prov->pOrder)] = L'\0';
166
167 bRet = AddPrintProvidorW(NULL, Level, (LPBYTE)&Provider);
168 HeapFree(GetProcessHeap(), 0, Provider.pOrder);
169 return bRet;
170 }
171 }
172
173 return FALSE;
174 }
175
176
177 /******************************************************************************
178 * AddPrintProvidorW (WINSPOOL.@)
179 */
180 BOOL
181 WINAPI
182 AddPrintProvidorW(LPWSTR Name, DWORD Level, PBYTE Buffer)
183 {
184 HKEY hKey;
185 LPWSTR pOrder;
186 DWORD dwSize, dwType;
187 BOOL bRet = FALSE;
188
189 if (Name || Level > 2 || Buffer == NULL)
190 {
191 SetLastError(ERROR_INVALID_PARAMETER);
192 return FALSE;
193 }
194
195
196 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Providers", 0, KEY_READ | KEY_WRITE, &hKey) != ERROR_SUCCESS)
197 {
198 return FALSE;
199 }
200
201 if (RegQueryValueExW(hKey, L"Order", NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS || dwType != REG_MULTI_SZ)
202 {
203 RegCloseKey(hKey);
204 return FALSE;
205 }
206
207 pOrder = HeapAlloc(GetProcessHeap(), 0, dwSize);
208 if (!pOrder)
209 {
210 RegCloseKey(hKey);
211 return FALSE;
212 }
213
214 if (RegQueryValueExW(hKey, L"Order", NULL, &dwType, (LPBYTE)pOrder, &dwSize) != ERROR_SUCCESS || dwType != REG_MULTI_SZ)
215 {
216 RegCloseKey(hKey);
217 return FALSE;
218 }
219
220 if (Level == 1)
221 {
222 LPWSTR pBuffer;
223 BOOL bFound = FALSE;
224 PROVIDOR_INFO_1W * Prov = (PROVIDOR_INFO_1W*)Buffer;
225
226 if (Prov->pName == NULL || Prov->pDLLName == NULL || Prov->pEnvironment == NULL)
227 {
228 SetLastError(ERROR_INVALID_PARAMETER);
229 RegCloseKey(hKey);
230 return FALSE;
231 }
232
233 pBuffer = pOrder;
234
235 while(pBuffer[0])
236 {
237 if (!wcsicmp(pBuffer, Prov->pName))
238 {
239 bFound = TRUE;
240 break;
241 }
242 pBuffer += wcslen(pBuffer) + 1;
243 }
244
245 if (!bFound)
246 {
247 HKEY hSubKey;
248 DWORD dwFullSize = dwSize + (wcslen(Prov->pName)+1) * sizeof(WCHAR);
249
250 if (RegCreateKeyExW(hKey, Prov->pName, 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
251 {
252 RegSetValueExW(hSubKey, L"Name", 0, REG_SZ, (LPBYTE)Prov->pDLLName, (wcslen(Prov->pDLLName)+1) * sizeof(WCHAR));
253 RegCloseKey(hSubKey);
254 }
255
256 pBuffer = HeapAlloc(GetProcessHeap(), 0, dwFullSize);
257 if (pBuffer)
258 {
259 CopyMemory(pBuffer, pOrder, dwSize);
260 wcscpy(&pBuffer[(dwSize/sizeof(WCHAR))-1], Prov->pName);
261 pBuffer[(dwSize/sizeof(WCHAR)) + wcslen(Prov->pName)] = L'\0';
262 RegSetValueExW(hKey, L"Order", 0, REG_MULTI_SZ, (LPBYTE)pBuffer, dwFullSize);
263 HeapFree(GetProcessHeap(), 0, pBuffer);
264 }
265 bRet = TRUE;
266 }
267
268 }
269
270 RegCloseKey(hKey);
271 HeapFree(GetProcessHeap(), 0, pOrder);
272
273 return bRet;
274 }
275
276 /******************************************************************************
277 * DeletePrintProvidorA (WINSPOOL.@)
278 */
279 BOOL
280 WINAPI
281 DeletePrintProvidorA(LPSTR Name, LPSTR Environment, LPSTR PrintProvidor)
282 {
283 BOOL bRet;
284 LPWSTR Env, Prov;
285
286 if (Name || !Environment || !PrintProvidor)
287 {
288 SetLastError(ERROR_INVALID_PARAMETER);
289 return FALSE;
290 }
291
292 Env = HeapAlloc(GetProcessHeap(), 0, (strlen(Environment)+1) * sizeof(WCHAR));
293 if (!Env)
294 {
295 return FALSE;
296 }
297
298 MultiByteToWideChar(CP_ACP, 0, Environment, -1, Env, strlen(Environment)+1);
299 Env[strlen(Environment)] = L'\0';
300
301 Prov = HeapAlloc(GetProcessHeap(), 0, (strlen(PrintProvidor)+1) * sizeof(WCHAR));
302 if (!Prov)
303 {
304 HeapFree(GetProcessHeap(), 0, Env);
305 return FALSE;
306 }
307
308 MultiByteToWideChar(CP_ACP, 0, PrintProvidor, -1, Prov, strlen(PrintProvidor)+1);
309 Prov[strlen(PrintProvidor)] = L'\0';
310
311 bRet = DeletePrintProvidorW(NULL, Env, Prov);
312 HeapFree(GetProcessHeap(), 0, Env);
313 HeapFree(GetProcessHeap(), 0, Prov);
314
315 return bRet;
316 }
317
318 /*
319 * @unimplemented
320 */
321 BOOL
322 WINAPI
323 DeletePrintProvidorW(LPWSTR Name, LPWSTR Environment, LPWSTR PrintProvidor)
324 {
325 HKEY hKey;
326 BOOL bFound;
327 DWORD dwType, dwSize, dwOffset, dwLength;
328 LPWSTR pOrder, pBuffer, pNew;
329
330 if (Name || !Environment || !PrintProvidor)
331 {
332 SetLastError(ERROR_INVALID_PARAMETER);
333 return FALSE;
334 }
335
336 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Providers", 0, KEY_READ | KEY_WRITE, &hKey) != ERROR_SUCCESS)
337 {
338 return FALSE;
339 }
340
341 if (RegQueryValueExW(hKey, L"Order", NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS || dwType != REG_MULTI_SZ)
342 {
343 RegCloseKey(hKey);
344 return FALSE;
345 }
346
347 pOrder = HeapAlloc(GetProcessHeap(), 0, dwSize);
348 if (!pOrder)
349 {
350 RegCloseKey(hKey);
351 return FALSE;
352 }
353
354 if (RegQueryValueExW(hKey, L"Order", NULL, &dwType, (LPBYTE)pOrder, &dwSize) != ERROR_SUCCESS || dwType != REG_MULTI_SZ)
355 {
356 RegCloseKey(hKey);
357 return FALSE;
358 }
359
360
361 pBuffer = pOrder;
362 bFound = FALSE;
363 while(pBuffer[0])
364 {
365 if (!wcsicmp(pBuffer, PrintProvidor))
366 {
367 bFound = TRUE;
368 break;
369 }
370 pBuffer += wcslen(pBuffer) + 1;
371 }
372
373 if (!bFound)
374 {
375 RegCloseKey(hKey);
376 HeapFree(GetProcessHeap(), 0, pOrder);
377 return FALSE;
378 }
379
380 pNew = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
381 if (!pNew)
382 {
383 RegCloseKey(hKey);
384 HeapFree(GetProcessHeap(), 0, pOrder);
385 return FALSE;
386 }
387
388 dwOffset = pBuffer - pOrder;
389 dwLength = (dwSize / sizeof(WCHAR)) - (dwOffset + wcslen(pBuffer) + 1);
390 CopyMemory(pNew, pOrder, dwOffset * sizeof(WCHAR));
391 CopyMemory(&pNew[dwOffset], pBuffer + wcslen(pBuffer) + 1, dwLength);
392
393 RegSetValueExW(hKey, L"Order", 0, REG_MULTI_SZ, (LPBYTE)pNew, (dwOffset + dwLength) * sizeof(WCHAR));
394 RegDeleteKey(hKey, PrintProvidor);
395
396 HeapFree(GetProcessHeap(), 0, pOrder);
397 HeapFree(GetProcessHeap(), 0, pNew);
398 RegCloseKey(hKey);
399
400 return TRUE;
401 }
402
403 /*
404 * @unimplemented
405 */
406 BOOL
407 WINAPI
408 AddMonitorA(LPSTR Name, DWORD Level, PBYTE Monitors)
409 {
410 LPWSTR szName = NULL;
411 MONITOR_INFO_2W Monitor;
412 MONITOR_INFO_2A *pMonitor;
413 BOOL bRet = FALSE;
414
415 if (Level != 2 || !Monitors)
416 {
417 SetLastError(ERROR_INVALID_PARAMETER);
418 return FALSE;
419 }
420
421 pMonitor = (MONITOR_INFO_2A*)Monitors;
422 if (pMonitor->pDLLName == NULL || pMonitor->pName == NULL)
423 {
424 SetLastError(ERROR_INVALID_PARAMETER);
425 return FALSE;
426 }
427
428 ZeroMemory(&Monitor, sizeof(Monitor));
429
430 if (Name)
431 {
432 szName = HeapAlloc(GetProcessHeap(), 0, (strlen(Name) + 1) * sizeof(WCHAR));
433 if (!szName)
434 {
435 return FALSE;
436 }
437 MultiByteToWideChar(CP_ACP, 0, Name, -1, szName, strlen(Name)+1);
438 szName[strlen(Name)] = L'\0';
439 }
440
441 Monitor.pDLLName = HeapAlloc(GetProcessHeap(), 0, (strlen(pMonitor->pDLLName)+1) * sizeof(WCHAR));
442 if (!Monitor.pDLLName)
443 {
444 goto cleanup;
445 }
446 MultiByteToWideChar(CP_ACP, 0, pMonitor->pDLLName, -1, Monitor.pDLLName, strlen(pMonitor->pDLLName)+1);
447 pMonitor->pDLLName[strlen(pMonitor->pDLLName)] = L'\0';
448
449 Monitor.pName = HeapAlloc(GetProcessHeap(), 0, (strlen(pMonitor->pName)+1) * sizeof(WCHAR));
450 if (!Monitor.pName)
451 {
452 goto cleanup;
453 }
454 MultiByteToWideChar(CP_ACP, 0, pMonitor->pName, -1, Monitor.pName, strlen(pMonitor->pName)+1);
455 pMonitor->pName[strlen(pMonitor->pName)] = L'\0';
456
457
458 if (pMonitor->pEnvironment)
459 {
460 Monitor.pEnvironment = HeapAlloc(GetProcessHeap(), 0, (strlen(pMonitor->pEnvironment)+1) * sizeof(WCHAR));
461 if (!Monitor.pEnvironment)
462 {
463 goto cleanup;
464 }
465 MultiByteToWideChar(CP_ACP, 0, pMonitor->pEnvironment, -1, Monitor.pEnvironment, strlen(pMonitor->pEnvironment)+1);
466 pMonitor->pEnvironment[strlen(pMonitor->pEnvironment)] = L'\0';
467 }
468
469 bRet = AddMonitorW(szName, Level, (LPBYTE)&Monitor);
470
471 cleanup:
472
473 if (szName)
474 HeapFree(GetProcessHeap(), 0, szName);
475
476 if (Monitor.pDLLName)
477 HeapFree(GetProcessHeap(), 0, Monitor.pDLLName);
478
479 if (Monitor.pEnvironment)
480 HeapFree(GetProcessHeap(), 0, Monitor.pEnvironment);
481
482 if (Monitor.pName)
483 HeapFree(GetProcessHeap(), 0, Monitor.pName);
484
485 return bRet;
486 }
487
488
489 /*
490 * @unimplemented
491 */
492 BOOL
493 WINAPI
494 AddMonitorW(LPWSTR Name, DWORD Level, PBYTE Monitors)
495 {
496 WCHAR szPath[MAX_PATH];
497 HMODULE hLibrary = NULL;
498 FARPROC InitProc;
499 HKEY hKey, hSubKey;
500 MONITOR_INFO_2W * pMonitor;
501
502
503 if (Level != 2 || !Monitors)
504 {
505 SetLastError(ERROR_INVALID_PARAMETER);
506 return FALSE;
507 }
508
509 pMonitor = (MONITOR_INFO_2W*)Monitors;
510
511 if (pMonitor->pDLLName == NULL || pMonitor->pName == NULL)
512 {
513 SetLastError(ERROR_INVALID_PARAMETER);
514 return FALSE;
515 }
516
517 if (wcschr(pMonitor->pDLLName, L'\\'))
518 {
519 hLibrary = LoadLibraryExW(pMonitor->pDLLName, NULL, 0);
520 }
521 else if (GetSystemDirectoryW(szPath, MAX_PATH) && PathAddBackslashW(szPath))
522 {
523 wcscat(szPath, pMonitor->pDLLName);
524 hLibrary = LoadLibraryExW(szPath, NULL, 0);
525 }
526
527 if (!hLibrary)
528 {
529 return FALSE;
530 }
531
532 InitProc = GetProcAddress(hLibrary, "InitializePrintMonitor");
533 if (!InitProc)
534 {
535 InitProc = GetProcAddress(hLibrary, "InitializePrintMonitor2");
536 if (!InitProc)
537 {
538 FreeLibrary(hLibrary);
539 SetLastError(ERROR_PROC_NOT_FOUND);
540 return FALSE;
541 }
542 }
543
544 // FIXME
545 // Initialize monitor
546 FreeLibrary(hLibrary);
547
548 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors", 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
549 {
550 if (RegCreateKeyExW(hKey, pMonitor->pName, 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
551 {
552 RegSetValueExW(hSubKey, L"Driver", 0, REG_SZ, (LPBYTE)pMonitor->pDLLName, (wcslen(pMonitor->pDLLName)+1)*sizeof(WCHAR));
553 RegCloseKey(hSubKey);
554 }
555 RegCloseKey(hKey);
556 }
557 return TRUE;
558 }
559