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