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