Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 1 | /* |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2 | * WINSPOOL functions |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 3 | * |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 4 | * Copyright 1996 John Harvey |
| 5 | * Copyright 1998 Andreas Mohr |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 6 | * Copyright 1999 Klaas van Gend |
| 7 | * Copyright 1999, 2000 Huw D M Davies |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 8 | * Copyright 2001 Marcus Meissner |
Detlef Riekenberg | ae91e97 | 2008-02-26 23:09:55 +0100 | [diff] [blame] | 9 | * Copyright 2005-2008 Detlef Riekenberg |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 10 | * |
| 11 | * This library is free software; you can redistribute it and/or |
| 12 | * modify it under the terms of the GNU Lesser General Public |
| 13 | * License as published by the Free Software Foundation; either |
| 14 | * version 2.1 of the License, or (at your option) any later version. |
| 15 | * |
| 16 | * This library is distributed in the hope that it will be useful, |
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 19 | * Lesser General Public License for more details. |
| 20 | * |
| 21 | * You should have received a copy of the GNU Lesser General Public |
| 22 | * License along with this library; if not, write to the Free Software |
Jonathan Ernst | 360a3f9 | 2006-05-18 14:49:52 +0200 | [diff] [blame] | 23 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 24 | */ |
| 25 | |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 26 | #include "config.h" |
Marcus Meissner | f061f76 | 2002-11-12 02:22:24 +0000 | [diff] [blame] | 27 | #include "wine/port.h" |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 28 | |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 29 | #include <stdarg.h> |
Alexandre Julliard | 49556bc | 2000-11-29 18:38:24 +0000 | [diff] [blame] | 30 | #include <stdio.h> |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 31 | #include <stdlib.h> |
| 32 | #include <string.h> |
| 33 | #include <ctype.h> |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 34 | #include <stddef.h> |
Francois Gouget | d867a77 | 2005-07-22 09:04:08 +0000 | [diff] [blame] | 35 | #ifdef HAVE_UNISTD_H |
| 36 | # include <unistd.h> |
| 37 | #endif |
Huw Davies | 0a4681f | 2005-07-20 17:48:53 +0000 | [diff] [blame] | 38 | #include <signal.h> |
Marcus Meissner | f061f76 | 2002-11-12 02:22:24 +0000 | [diff] [blame] | 39 | #ifdef HAVE_CUPS_CUPS_H |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 40 | # include <cups/cups.h> |
| 41 | #endif |
Dimitrie O. Paun | 297f3d8 | 2003-01-07 20:36:20 +0000 | [diff] [blame] | 42 | |
| 43 | #define NONAMELESSUNION |
| 44 | #define NONAMELESSSTRUCT |
| 45 | #include "wine/library.h" |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 46 | #include "windef.h" |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 47 | #include "winbase.h" |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 48 | #include "winuser.h" |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 49 | #include "winerror.h" |
| 50 | #include "winreg.h" |
Francois Gouget | 3efacb0 | 2003-01-07 23:09:22 +0000 | [diff] [blame] | 51 | #include "wingdi.h" |
| 52 | #include "winspool.h" |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 53 | #include "winternl.h" |
Alexandre Julliard | 83f52d1 | 2000-09-26 22:20:14 +0000 | [diff] [blame] | 54 | #include "wine/windef16.h" |
Alexandre Julliard | c7e7df8 | 2000-08-14 14:41:19 +0000 | [diff] [blame] | 55 | #include "wine/unicode.h" |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 56 | #include "wine/debug.h" |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 57 | #include "wine/list.h" |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 58 | #include "winnls.h" |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 59 | |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 60 | #include "ddk/winsplp.h" |
Huw Davies | e502d4d | 2005-07-12 17:01:44 +0000 | [diff] [blame] | 61 | #include "wspool.h" |
| 62 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 63 | WINE_DEFAULT_DEBUG_CHANNEL(winspool); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 64 | |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 65 | /* ############################### */ |
| 66 | |
| 67 | static CRITICAL_SECTION monitor_handles_cs; |
| 68 | static CRITICAL_SECTION_DEBUG monitor_handles_cs_debug = |
| 69 | { |
| 70 | 0, 0, &monitor_handles_cs, |
| 71 | { &monitor_handles_cs_debug.ProcessLocksList, &monitor_handles_cs_debug.ProcessLocksList }, |
| 72 | 0, 0, { (DWORD_PTR)(__FILE__ ": monitor_handles_cs") } |
| 73 | }; |
| 74 | static CRITICAL_SECTION monitor_handles_cs = { &monitor_handles_cs_debug, -1, 0, 0, 0, 0 }; |
| 75 | |
| 76 | |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 77 | static CRITICAL_SECTION printer_handles_cs; |
| 78 | static CRITICAL_SECTION_DEBUG printer_handles_cs_debug = |
| 79 | { |
| 80 | 0, 0, &printer_handles_cs, |
| 81 | { &printer_handles_cs_debug.ProcessLocksList, &printer_handles_cs_debug.ProcessLocksList }, |
Alexandre Julliard | 20a1a20 | 2005-09-09 10:19:44 +0000 | [diff] [blame] | 82 | 0, 0, { (DWORD_PTR)(__FILE__ ": printer_handles_cs") } |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 83 | }; |
| 84 | static CRITICAL_SECTION printer_handles_cs = { &printer_handles_cs_debug, -1, 0, 0, 0, 0 }; |
| 85 | |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 86 | /* ############################### */ |
| 87 | |
| 88 | typedef struct { |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 89 | struct list entry; |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 90 | LPWSTR name; |
| 91 | LPWSTR dllname; |
| 92 | PMONITORUI monitorUI; |
| 93 | LPMONITOR monitor; |
| 94 | HMODULE hdll; |
| 95 | DWORD refcount; |
| 96 | DWORD dwMonitorSize; |
| 97 | } monitor_t; |
| 98 | |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 99 | typedef struct { |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 100 | DWORD job_id; |
| 101 | HANDLE hf; |
| 102 | } started_doc_t; |
| 103 | |
| 104 | typedef struct { |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 105 | struct list jobs; |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 106 | LONG ref; |
Robert Lunnon | c22716f | 2005-10-24 15:03:02 +0000 | [diff] [blame] | 107 | } jobqueue_t; |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 108 | |
| 109 | typedef struct { |
| 110 | LPWSTR name; |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 111 | LPWSTR printername; |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 112 | monitor_t *pm; |
Detlef Riekenberg | 72b126b | 2007-01-05 01:09:46 +0100 | [diff] [blame] | 113 | HANDLE hXcv; |
Robert Lunnon | c22716f | 2005-10-24 15:03:02 +0000 | [diff] [blame] | 114 | jobqueue_t *queue; |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 115 | started_doc_t *doc; |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 116 | } opened_printer_t; |
| 117 | |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 118 | typedef struct { |
| 119 | struct list entry; |
| 120 | DWORD job_id; |
| 121 | WCHAR *filename; |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 122 | WCHAR *document_title; |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 123 | } job_t; |
| 124 | |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 125 | |
| 126 | typedef struct { |
| 127 | LPCWSTR envname; |
| 128 | LPCWSTR subdir; |
Detlef Riekenberg | 6c233ef | 2006-05-11 23:59:17 +0200 | [diff] [blame] | 129 | DWORD driverversion; |
| 130 | LPCWSTR versionregpath; |
| 131 | LPCWSTR versionsubdir; |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 132 | } printenv_t; |
| 133 | |
| 134 | /* ############################### */ |
| 135 | |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 136 | static struct list monitor_handles = LIST_INIT( monitor_handles ); |
Detlef Riekenberg | a7481a9 | 2006-11-28 20:04:08 +0100 | [diff] [blame] | 137 | static monitor_t * pm_localport; |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 138 | |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 139 | static opened_printer_t **printer_handles; |
Detlef Riekenberg | d244a55 | 2007-11-04 17:57:54 +0100 | [diff] [blame] | 140 | static UINT nb_printer_handles; |
Kevin Koltzau | 7d8e377 | 2005-09-29 13:34:34 +0000 | [diff] [blame] | 141 | static LONG next_job_id = 1; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 142 | |
Patrik Stridvall | 57e5784 | 2002-02-02 18:42:11 +0000 | [diff] [blame] | 143 | static DWORD (WINAPI *GDI_CallDeviceCapabilities16)( LPCSTR lpszDevice, LPCSTR lpszPort, |
Alexandre Julliard | 49556bc | 2000-11-29 18:38:24 +0000 | [diff] [blame] | 144 | WORD fwCapability, LPSTR lpszOutput, |
| 145 | LPDEVMODEA lpdm ); |
Patrik Stridvall | 57e5784 | 2002-02-02 18:42:11 +0000 | [diff] [blame] | 146 | static INT (WINAPI *GDI_CallExtDeviceMode16)( HWND hwnd, LPDEVMODEA lpdmOutput, |
Alexandre Julliard | 49556bc | 2000-11-29 18:38:24 +0000 | [diff] [blame] | 147 | LPSTR lpszDevice, LPSTR lpszPort, |
| 148 | LPDEVMODEA lpdmInput, LPSTR lpszProfile, |
| 149 | DWORD fwMode ); |
| 150 | |
Dimitrie O. Paun | d4193bb | 2005-03-29 13:10:35 +0000 | [diff] [blame] | 151 | static const WCHAR DriversW[] = { 'S','y','s','t','e','m','\\', |
| 152 | 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', |
| 153 | 'c','o','n','t','r','o','l','\\', |
| 154 | 'P','r','i','n','t','\\', |
| 155 | 'E','n','v','i','r','o','n','m','e','n','t','s','\\', |
Detlef Riekenberg | 6c233ef | 2006-05-11 23:59:17 +0200 | [diff] [blame] | 156 | '%','s','\\','D','r','i','v','e','r','s','%','s',0 }; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 157 | |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 158 | static const WCHAR MonitorsW[] = { 'S','y','s','t','e','m','\\', |
| 159 | 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', |
| 160 | 'C','o','n','t','r','o','l','\\', |
| 161 | 'P','r','i','n','t','\\', |
Detlef Riekenberg | 1e2b9b7 | 2006-09-18 07:57:41 +0200 | [diff] [blame] | 162 | 'M','o','n','i','t','o','r','s','\\',0}; |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 163 | |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 164 | static const WCHAR PrintersW[] = {'S','y','s','t','e','m','\\', |
| 165 | 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', |
| 166 | 'C','o','n','t','r','o','l','\\', |
| 167 | 'P','r','i','n','t','\\', |
| 168 | 'P','r','i','n','t','e','r','s',0}; |
| 169 | |
Dmitry Timoshkov | 1804900 | 2006-11-29 18:04:13 +0800 | [diff] [blame] | 170 | static const WCHAR LocalPortW[] = {'L','o','c','a','l',' ','P','o','r','t',0}; |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 171 | |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 172 | static const WCHAR user_default_reg_key[] = { 'S','o','f','t','w','a','r','e','\\', |
| 173 | 'M','i','c','r','o','s','o','f','t','\\', |
| 174 | 'W','i','n','d','o','w','s',' ','N','T','\\', |
| 175 | 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', |
| 176 | 'W','i','n','d','o','w','s',0}; |
| 177 | |
| 178 | static const WCHAR user_printers_reg_key[] = { 'S','o','f','t','w','a','r','e','\\', |
| 179 | 'M','i','c','r','o','s','o','f','t','\\', |
| 180 | 'W','i','n','d','o','w','s',' ','N','T','\\', |
| 181 | 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', |
| 182 | 'D','e','v','i','c','e','s',0}; |
| 183 | |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 184 | static const WCHAR WinNT_CV_PortsW[] = {'S','o','f','t','w','a','r','e','\\', |
| 185 | 'M','i','c','r','o','s','o','f','t','\\', |
| 186 | 'W','i','n','d','o','w','s',' ','N','T','\\', |
| 187 | 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', |
| 188 | 'P','o','r','t','s',0}; |
| 189 | |
Detlef Riekenberg | 473717f | 2008-05-06 20:26:05 +0200 | [diff] [blame] | 190 | static const WCHAR WinNT_CV_PrinterPortsW[] = { 'S','o','f','t','w','a','r','e','\\', |
| 191 | 'M','i','c','r','o','s','o','f','t','\\', |
| 192 | 'W','i','n','d','o','w','s',' ','N','T','\\', |
| 193 | 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', |
| 194 | 'P','r','i','n','t','e','r','P','o','r','t','s',0}; |
| 195 | |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 196 | static const WCHAR DefaultEnvironmentW[] = {'W','i','n','e',0}; |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 197 | static const WCHAR envname_win40W[] = {'W','i','n','d','o','w','s',' ','4','.','0',0}; |
| 198 | static const WCHAR envname_x86W[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0}; |
| 199 | static const WCHAR subdir_win40W[] = {'w','i','n','4','0',0}; |
| 200 | static const WCHAR subdir_x86W[] = {'w','3','2','x','8','6',0}; |
Detlef Riekenberg | 36a6515 | 2007-07-26 22:54:14 +0200 | [diff] [blame] | 201 | static const WCHAR Version0_RegPathW[] = {'\\','V','e','r','s','i','o','n','-','0',0}; |
| 202 | static const WCHAR Version0_SubdirW[] = {'\\','0',0}; |
Detlef Riekenberg | 6c233ef | 2006-05-11 23:59:17 +0200 | [diff] [blame] | 203 | static const WCHAR Version3_RegPathW[] = {'\\','V','e','r','s','i','o','n','-','3',0}; |
| 204 | static const WCHAR Version3_SubdirW[] = {'\\','3',0}; |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 205 | |
| 206 | static const WCHAR spooldriversW[] = {'\\','s','p','o','o','l','\\','d','r','i','v','e','r','s','\\',0}; |
Detlef Riekenberg | f0a62dd | 2006-05-28 21:56:52 +0200 | [diff] [blame] | 207 | static const WCHAR spoolprtprocsW[] = {'\\','s','p','o','o','l','\\','p','r','t','p','r','o','c','s','\\',0}; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 208 | |
Detlef Riekenberg | 4b53154 | 2007-07-26 23:05:27 +0200 | [diff] [blame] | 209 | static const WCHAR backslashW[] = {'\\',0}; |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 210 | static const WCHAR Configuration_FileW[] = {'C','o','n','f','i','g','u','r','a','t', |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 211 | 'i','o','n',' ','F','i','l','e',0}; |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 212 | static const WCHAR DatatypeW[] = {'D','a','t','a','t','y','p','e',0}; |
| 213 | static const WCHAR Data_FileW[] = {'D','a','t','a',' ','F','i','l','e',0}; |
Detlef Riekenberg | 510c4dc | 2007-07-26 23:37:22 +0200 | [diff] [blame] | 214 | static const WCHAR Default_DevModeW[] = {'D','e','f','a','u','l','t',' ','D','e','v','M','o','d','e',0}; |
| 215 | static const WCHAR Dependent_FilesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0}; |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 216 | static const WCHAR DescriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0}; |
| 217 | static const WCHAR DriverW[] = {'D','r','i','v','e','r',0}; |
Detlef Riekenberg | 510c4dc | 2007-07-26 23:37:22 +0200 | [diff] [blame] | 218 | static const WCHAR HardwareIDW[] = {'H','a','r','d','w','a','r','e','I','D',0}; |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 219 | static const WCHAR Help_FileW[] = {'H','e','l','p',' ','F','i','l','e',0}; |
| 220 | static const WCHAR LocationW[] = {'L','o','c','a','t','i','o','n',0}; |
Detlef Riekenberg | 510c4dc | 2007-07-26 23:37:22 +0200 | [diff] [blame] | 221 | static const WCHAR ManufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 222 | static const WCHAR MonitorW[] = {'M','o','n','i','t','o','r',0}; |
Detlef Riekenberg | e576b09 | 2007-01-11 13:10:37 +0100 | [diff] [blame] | 223 | static const WCHAR MonitorUIW[] = {'M','o','n','i','t','o','r','U','I',0}; |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 224 | static const WCHAR NameW[] = {'N','a','m','e',0}; |
Detlef Riekenberg | ae91e97 | 2008-02-26 23:09:55 +0100 | [diff] [blame] | 225 | static const WCHAR ObjectGUIDW[] = {'O','b','j','e','c','t','G','U','I','D',0}; |
Detlef Riekenberg | 510c4dc | 2007-07-26 23:37:22 +0200 | [diff] [blame] | 226 | static const WCHAR OEM_UrlW[] = {'O','E','M',' ','U','r','l',0}; |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 227 | static const WCHAR ParametersW[] = {'P','a','r','a','m','e','t','e','r','s',0}; |
| 228 | static const WCHAR PortW[] = {'P','o','r','t',0}; |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 229 | static const WCHAR bs_Ports_bsW[] = {'\\','P','o','r','t','s','\\',0}; |
Detlef Riekenberg | 510c4dc | 2007-07-26 23:37:22 +0200 | [diff] [blame] | 230 | static const WCHAR Previous_NamesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0}; |
| 231 | static const WCHAR Print_ProcessorW[] = {'P','r','i','n','t',' ','P','r','o','c','e','s','s','o','r',0}; |
| 232 | static const WCHAR Printer_DriverW[] = {'P','r','i','n','t','e','r',' ','D','r','i','v','e','r',0}; |
| 233 | static const WCHAR PrinterDriverDataW[] = {'P','r','i','n','t','e','r','D','r','i','v','e','r','D','a','t','a',0}; |
Detlef Riekenberg | 473717f | 2008-05-06 20:26:05 +0200 | [diff] [blame] | 234 | static const WCHAR PrinterPortsW[] = {'P','r','i','n','t','e','r','P','o','r','t','s',0}; |
Detlef Riekenberg | 510c4dc | 2007-07-26 23:37:22 +0200 | [diff] [blame] | 235 | static const WCHAR ProviderW[] = {'P','r','o','v','i','d','e','r',0}; |
| 236 | static const WCHAR Separator_FileW[] = {'S','e','p','a','r','a','t','o','r',' ','F','i','l','e',0}; |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 237 | static const WCHAR Share_NameW[] = {'S','h','a','r','e',' ','N','a','m','e',0}; |
Detlef Riekenberg | 29444b4 | 2007-08-15 23:30:59 +0200 | [diff] [blame] | 238 | static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0}; |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 239 | static const WCHAR WinPrintW[] = {'W','i','n','P','r','i','n','t',0}; |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 240 | static const WCHAR deviceW[] = {'d','e','v','i','c','e',0}; |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 241 | static const WCHAR devicesW[] = {'d','e','v','i','c','e','s',0}; |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 242 | static const WCHAR windowsW[] = {'w','i','n','d','o','w','s',0}; |
| 243 | static const WCHAR emptyStringW[] = {0}; |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 244 | static const WCHAR XcvMonitorW[] = {',','X','c','v','M','o','n','i','t','o','r',' ',0}; |
| 245 | static const WCHAR XcvPortW[] = {',','X','c','v','P','o','r','t',' ',0}; |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 246 | |
| 247 | static const WCHAR May_Delete_Value[] = {'W','i','n','e','M','a','y','D','e','l','e','t','e','M','e',0}; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 248 | |
Huw Davies | c108d80 | 2005-07-10 17:39:01 +0000 | [diff] [blame] | 249 | static const WCHAR CUPS_Port[] = {'C','U','P','S',':',0}; |
| 250 | static const WCHAR FILE_Port[] = {'F','I','L','E',':',0}; |
| 251 | static const WCHAR LPR_Port[] = {'L','P','R',':',0}; |
| 252 | |
Huw Davies | 183fcb5 | 2005-07-15 09:55:23 +0000 | [diff] [blame] | 253 | static const WCHAR default_doc_title[] = {'L','o','c','a','l',' ','D','o','w','n','l','e','v','e','l',' ', |
| 254 | 'D','o','c','u','m','e','n','t',0}; |
| 255 | |
Detlef Riekenberg | a2daf75 | 2007-07-26 23:14:55 +0200 | [diff] [blame] | 256 | static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_2W), |
| 257 | sizeof(DRIVER_INFO_3W), sizeof(DRIVER_INFO_4W), |
| 258 | sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W), |
| 259 | 0, sizeof(DRIVER_INFO_8W)}; |
Francois Gouget | 0c31ca3 | 2007-01-17 17:18:54 +0100 | [diff] [blame] | 260 | |
Detlef Riekenberg | 9e35ee8 | 2008-03-22 19:28:50 +0100 | [diff] [blame] | 261 | |
| 262 | static const DWORD pi_sizeof[] = {0, sizeof(PRINTER_INFO_1W), sizeof(PRINTER_INFO_2W), |
| 263 | sizeof(PRINTER_INFO_3), sizeof(PRINTER_INFO_4W), |
| 264 | sizeof(PRINTER_INFO_5W), sizeof(PRINTER_INFO_6), |
| 265 | sizeof(PRINTER_INFO_7W), sizeof(PRINTER_INFO_8W), |
| 266 | sizeof(PRINTER_INFO_9W)}; |
| 267 | |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 268 | /****************************************************************** |
| 269 | * validate the user-supplied printing-environment [internal] |
| 270 | * |
| 271 | * PARAMS |
| 272 | * env [I] PTR to Environment-String or NULL |
| 273 | * |
| 274 | * RETURNS |
| 275 | * Failure: NULL |
| 276 | * Success: PTR to printenv_t |
| 277 | * |
| 278 | * NOTES |
Detlef Riekenberg | 366f452 | 2006-02-01 12:32:10 +0100 | [diff] [blame] | 279 | * An empty string is handled the same way as NULL. |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 280 | * SetLastEror(ERROR_INVALID_ENVIRONMENT) is called on Failure |
| 281 | * |
| 282 | */ |
| 283 | |
| 284 | static const printenv_t * validate_envW(LPCWSTR env) |
| 285 | { |
Detlef Riekenberg | 6c233ef | 2006-05-11 23:59:17 +0200 | [diff] [blame] | 286 | static const printenv_t env_x86 = {envname_x86W, subdir_x86W, |
| 287 | 3, Version3_RegPathW, Version3_SubdirW}; |
| 288 | static const printenv_t env_win40 = {envname_win40W, subdir_win40W, |
Detlef Riekenberg | 36a6515 | 2007-07-26 22:54:14 +0200 | [diff] [blame] | 289 | 0, Version0_RegPathW, Version0_SubdirW}; |
| 290 | |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 291 | static const printenv_t * const all_printenv[]={&env_x86, &env_win40}; |
| 292 | |
| 293 | const printenv_t *result = NULL; |
| 294 | unsigned int i; |
| 295 | |
| 296 | TRACE("testing %s\n", debugstr_w(env)); |
Detlef Riekenberg | 366f452 | 2006-02-01 12:32:10 +0100 | [diff] [blame] | 297 | if (env && env[0]) |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 298 | { |
| 299 | for (i = 0; i < sizeof(all_printenv)/sizeof(all_printenv[0]); i++) |
| 300 | { |
| 301 | if (lstrcmpiW(env, all_printenv[i]->envname) == 0) |
| 302 | { |
| 303 | result = all_printenv[i]; |
| 304 | break; |
| 305 | } |
| 306 | } |
| 307 | |
| 308 | if (result == NULL) { |
| 309 | FIXME("unsupported Environment: %s\n", debugstr_w(env)); |
| 310 | SetLastError(ERROR_INVALID_ENVIRONMENT); |
| 311 | } |
| 312 | /* on win9x, only "Windows 4.0" is allowed, but we ignore this */ |
| 313 | } |
| 314 | else |
| 315 | { |
| 316 | result = (GetVersion() & 0x80000000) ? &env_win40 : &env_x86; |
| 317 | } |
| 318 | TRACE("using %p: %s\n", result, debugstr_w(result ? result->envname : NULL)); |
| 319 | |
| 320 | return result; |
| 321 | } |
| 322 | |
| 323 | |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 324 | /* RtlCreateUnicodeStringFromAsciiz will return an empty string in the buffer |
| 325 | if passed a NULL string. This returns NULLs to the result. |
| 326 | */ |
| 327 | static inline PWSTR asciitounicode( UNICODE_STRING * usBufferPtr, LPCSTR src ) |
| 328 | { |
| 329 | if ( (src) ) |
| 330 | { |
| 331 | RtlCreateUnicodeStringFromAsciiz(usBufferPtr, src); |
| 332 | return usBufferPtr->Buffer; |
| 333 | } |
| 334 | usBufferPtr->Buffer = NULL; /* so that RtlFreeUnicodeString won't barf */ |
| 335 | return NULL; |
| 336 | } |
| 337 | |
Huw Davies | 183fcb5 | 2005-07-15 09:55:23 +0000 | [diff] [blame] | 338 | static LPWSTR strdupW(LPCWSTR p) |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 339 | { |
| 340 | LPWSTR ret; |
| 341 | DWORD len; |
| 342 | |
| 343 | if(!p) return NULL; |
| 344 | len = (strlenW(p) + 1) * sizeof(WCHAR); |
| 345 | ret = HeapAlloc(GetProcessHeap(), 0, len); |
| 346 | memcpy(ret, p, len); |
| 347 | return ret; |
| 348 | } |
| 349 | |
Alexandre Julliard | 2731998 | 2006-11-17 15:29:40 +0100 | [diff] [blame] | 350 | static LPSTR strdupWtoA( LPCWSTR str ) |
| 351 | { |
| 352 | LPSTR ret; |
| 353 | INT len; |
| 354 | |
| 355 | if (!str) return NULL; |
| 356 | len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL ); |
| 357 | ret = HeapAlloc( GetProcessHeap(), 0, len ); |
| 358 | if(ret) WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); |
| 359 | return ret; |
| 360 | } |
| 361 | |
Detlef Riekenberg | 29444b4 | 2007-08-15 23:30:59 +0200 | [diff] [blame] | 362 | /****************************************************************** |
Detlef Riekenberg | 29444b4 | 2007-08-15 23:30:59 +0200 | [diff] [blame] | 363 | * Return the number of bytes for an multi_sz string. |
| 364 | * The result includes all \0s |
| 365 | * (specifically the extra \0, that is needed as multi_sz terminator). |
| 366 | */ |
Detlef Riekenberg | 6ec7c2d | 2008-02-08 00:41:24 +0100 | [diff] [blame] | 367 | #if 0 |
Detlef Riekenberg | 29444b4 | 2007-08-15 23:30:59 +0200 | [diff] [blame] | 368 | static int multi_sz_lenW(const WCHAR *str) |
| 369 | { |
| 370 | const WCHAR *ptr = str; |
| 371 | if(!str) return 0; |
| 372 | do |
| 373 | { |
| 374 | ptr += lstrlenW(ptr) + 1; |
| 375 | } while(*ptr); |
| 376 | |
| 377 | return (ptr - str + 1) * sizeof(WCHAR); |
| 378 | } |
Detlef Riekenberg | 6ec7c2d | 2008-02-08 00:41:24 +0100 | [diff] [blame] | 379 | #endif |
Detlef Riekenberg | 29444b4 | 2007-08-15 23:30:59 +0200 | [diff] [blame] | 380 | /* ################################ */ |
| 381 | |
Huw Davies | 1ad05ac | 2006-11-07 17:16:29 +0000 | [diff] [blame] | 382 | static int multi_sz_lenA(const char *str) |
| 383 | { |
| 384 | const char *ptr = str; |
| 385 | if(!str) return 0; |
| 386 | do |
| 387 | { |
| 388 | ptr += lstrlenA(ptr) + 1; |
| 389 | } while(*ptr); |
| 390 | |
| 391 | return ptr - str + 1; |
| 392 | } |
| 393 | |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 394 | static void |
Vitaly Lipatov | c9d78fc | 2007-02-18 13:51:09 +0300 | [diff] [blame] | 395 | WINSPOOL_SetDefaultPrinter(const char *devname, const char *name, BOOL force) { |
Marcus Meissner | 6d3e81b | 2001-05-18 20:57:36 +0000 | [diff] [blame] | 396 | char qbuf[200]; |
| 397 | |
| 398 | /* If forcing, or no profile string entry for device yet, set the entry |
| 399 | * |
| 400 | * The always change entry if not WINEPS yet is discussable. |
| 401 | */ |
| 402 | if (force || |
| 403 | !GetProfileStringA("windows","device","*",qbuf,sizeof(qbuf)) || |
| 404 | !strcmp(qbuf,"*") || |
Alexandre Julliard | b3e9c44 | 2005-05-06 20:04:27 +0000 | [diff] [blame] | 405 | !strstr(qbuf,"WINEPS.DRV") |
Marcus Meissner | 6d3e81b | 2001-05-18 20:57:36 +0000 | [diff] [blame] | 406 | ) { |
Alexandre Julliard | b3e9c44 | 2005-05-06 20:04:27 +0000 | [diff] [blame] | 407 | char *buf = HeapAlloc(GetProcessHeap(),0,strlen(name)+strlen(devname)+strlen(",WINEPS.DRV,LPR:")+1); |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 408 | HKEY hkey; |
Marcus Meissner | 6d3e81b | 2001-05-18 20:57:36 +0000 | [diff] [blame] | 409 | |
Alexandre Julliard | b3e9c44 | 2005-05-06 20:04:27 +0000 | [diff] [blame] | 410 | sprintf(buf,"%s,WINEPS.DRV,LPR:%s",devname,name); |
Marcus Meissner | 6d3e81b | 2001-05-18 20:57:36 +0000 | [diff] [blame] | 411 | WriteProfileStringA("windows","device",buf); |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 412 | if(RegCreateKeyW(HKEY_CURRENT_USER, user_default_reg_key, &hkey) == ERROR_SUCCESS) { |
Mike McCormack | bc4a576 | 2005-08-03 11:03:44 +0000 | [diff] [blame] | 413 | RegSetValueExA(hkey, "Device", 0, REG_SZ, (LPBYTE)buf, strlen(buf) + 1); |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 414 | RegCloseKey(hkey); |
| 415 | } |
Marcus Meissner | 6d3e81b | 2001-05-18 20:57:36 +0000 | [diff] [blame] | 416 | HeapFree(GetProcessHeap(),0,buf); |
| 417 | } |
| 418 | } |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 419 | |
Vitaly Lipatov | c9d78fc | 2007-02-18 13:51:09 +0300 | [diff] [blame] | 420 | static BOOL add_printer_driver(const char *name) |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 421 | { |
| 422 | DRIVER_INFO_3A di3a; |
| 423 | |
Detlef Riekenberg | 8506125 | 2007-08-22 20:24:35 +0200 | [diff] [blame] | 424 | static char driver_9x[] = "wineps16.drv", |
| 425 | driver_nt[] = "wineps.drv", |
| 426 | env_9x[] = "Windows 4.0", |
| 427 | env_nt[] = "Windows NT x86", |
| 428 | data_file[] = "generic.ppd", |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 429 | default_data_type[] = "RAW"; |
| 430 | |
Detlef Riekenberg | 8506125 | 2007-08-22 20:24:35 +0200 | [diff] [blame] | 431 | ZeroMemory(&di3a, sizeof(DRIVER_INFO_3A)); |
| 432 | di3a.cVersion = 3; |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 433 | di3a.pName = (char *)name; |
Detlef Riekenberg | 8506125 | 2007-08-22 20:24:35 +0200 | [diff] [blame] | 434 | di3a.pEnvironment = env_nt; |
| 435 | di3a.pDriverPath = driver_nt; |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 436 | di3a.pDataFile = data_file; |
Detlef Riekenberg | 8506125 | 2007-08-22 20:24:35 +0200 | [diff] [blame] | 437 | di3a.pConfigFile = driver_nt; |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 438 | di3a.pDefaultDataType = default_data_type; |
| 439 | |
Detlef Riekenberg | d6d0239 | 2007-11-05 22:48:07 +0100 | [diff] [blame] | 440 | if (AddPrinterDriverA(NULL, 3, (LPBYTE)&di3a) || |
| 441 | (GetLastError() == ERROR_PRINTER_DRIVER_ALREADY_INSTALLED )) |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 442 | { |
Detlef Riekenberg | 8506125 | 2007-08-22 20:24:35 +0200 | [diff] [blame] | 443 | di3a.cVersion = 0; |
| 444 | di3a.pEnvironment = env_9x; |
| 445 | di3a.pDriverPath = driver_9x; |
| 446 | di3a.pConfigFile = driver_9x; |
Detlef Riekenberg | d6d0239 | 2007-11-05 22:48:07 +0100 | [diff] [blame] | 447 | if (AddPrinterDriverA(NULL, 3, (LPBYTE)&di3a) || |
| 448 | (GetLastError() == ERROR_PRINTER_DRIVER_ALREADY_INSTALLED )) |
Detlef Riekenberg | 8506125 | 2007-08-22 20:24:35 +0200 | [diff] [blame] | 449 | { |
| 450 | return TRUE; |
| 451 | } |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 452 | } |
Detlef Riekenberg | d6d0239 | 2007-11-05 22:48:07 +0100 | [diff] [blame] | 453 | ERR("Failed adding driver %s (%s): %u\n", debugstr_a(di3a.pDriverPath), |
| 454 | debugstr_a(di3a.pEnvironment), GetLastError()); |
Detlef Riekenberg | 8506125 | 2007-08-22 20:24:35 +0200 | [diff] [blame] | 455 | return FALSE; |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 456 | } |
| 457 | |
Alexandre Julliard | 702d355 | 2007-07-02 17:30:44 +0200 | [diff] [blame] | 458 | #ifdef SONAME_LIBCUPS |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 459 | static typeof(cupsGetDests) *pcupsGetDests; |
| 460 | static typeof(cupsGetPPD) *pcupsGetPPD; |
| 461 | static typeof(cupsPrintFile) *pcupsPrintFile; |
| 462 | static void *cupshandle; |
| 463 | |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 464 | static BOOL CUPS_LoadPrinters(void) |
| 465 | { |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 466 | int i, nrofdests; |
Pedro Araujo Chaves Jr | ffbd30d | 2007-07-04 20:22:15 -0300 | [diff] [blame] | 467 | BOOL hadprinter = FALSE, haddefault = FALSE; |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 468 | cups_dest_t *dests; |
| 469 | PRINTER_INFO_2A pinfo2a; |
Duane Clark | 45abf7c | 2003-02-12 21:27:27 +0000 | [diff] [blame] | 470 | char *port,*devline; |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 471 | HKEY hkeyPrinter, hkeyPrinters, hkey; |
Detlef Riekenberg | f976fc8 | 2007-07-30 19:41:03 +0200 | [diff] [blame] | 472 | char loaderror[256]; |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 473 | |
Detlef Riekenberg | f976fc8 | 2007-07-30 19:41:03 +0200 | [diff] [blame] | 474 | cupshandle = wine_dlopen(SONAME_LIBCUPS, RTLD_NOW, loaderror, sizeof(loaderror)); |
| 475 | if (!cupshandle) { |
| 476 | TRACE("%s\n", loaderror); |
| 477 | return FALSE; |
| 478 | } |
| 479 | TRACE("%p: %s loaded\n", cupshandle, SONAME_LIBCUPS); |
Marcus Meissner | f061f76 | 2002-11-12 02:22:24 +0000 | [diff] [blame] | 480 | |
| 481 | #define DYNCUPS(x) \ |
| 482 | p##x = wine_dlsym(cupshandle, #x, NULL,0); \ |
| 483 | if (!p##x) return FALSE; |
| 484 | |
Marcus Meissner | f061f76 | 2002-11-12 02:22:24 +0000 | [diff] [blame] | 485 | DYNCUPS(cupsGetPPD); |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 486 | DYNCUPS(cupsGetDests); |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 487 | DYNCUPS(cupsPrintFile); |
Marcus Meissner | f061f76 | 2002-11-12 02:22:24 +0000 | [diff] [blame] | 488 | #undef DYNCUPS |
| 489 | |
Detlef Riekenberg | 358ce06 | 2006-05-21 14:35:29 +0200 | [diff] [blame] | 490 | if(RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) != |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 491 | ERROR_SUCCESS) { |
| 492 | ERR("Can't create Printers key\n"); |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 493 | return FALSE; |
| 494 | } |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 495 | |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 496 | nrofdests = pcupsGetDests(&dests); |
| 497 | TRACE("Found %d CUPS %s:\n", nrofdests, (nrofdests == 1) ? "printer" : "printers"); |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 498 | for (i=0;i<nrofdests;i++) { |
Detlef Riekenberg | 473717f | 2008-05-06 20:26:05 +0200 | [diff] [blame] | 499 | /* FIXME: replace "LPR:" with "CUPS:". Fix printing output first */ |
| 500 | port = HeapAlloc(GetProcessHeap(), 0, strlen("LPR:") + strlen(dests[i].name)+1); |
| 501 | sprintf(port,"LPR:%s", dests[i].name); |
| 502 | /* FIXME: remove extension. Fix gdi32/drivers and comdlg32/printdlg first */ |
| 503 | devline = HeapAlloc(GetProcessHeap(), 0, sizeof("WINEPS.DRV,,15,45") + strlen(port)); |
| 504 | sprintf(devline, "WINEPS.DRV,%s", port); |
| 505 | WriteProfileStringA("devices", dests[i].name, devline); |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 506 | if(RegCreateKeyW(HKEY_CURRENT_USER, user_printers_reg_key, &hkey) == ERROR_SUCCESS) { |
Mike McCormack | bc4a576 | 2005-08-03 11:03:44 +0000 | [diff] [blame] | 507 | RegSetValueExA(hkey, dests[i].name, 0, REG_SZ, (LPBYTE)devline, strlen(devline) + 1); |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 508 | RegCloseKey(hkey); |
| 509 | } |
Detlef Riekenberg | 473717f | 2008-05-06 20:26:05 +0200 | [diff] [blame] | 510 | |
| 511 | lstrcatA(devline, ",15,45"); |
| 512 | WriteProfileStringA("PrinterPorts", dests[i].name, devline); |
| 513 | if(RegCreateKeyW(HKEY_CURRENT_USER, WinNT_CV_PrinterPortsW, &hkey) == ERROR_SUCCESS) { |
| 514 | RegSetValueExA(hkey, dests[i].name, 0, REG_SZ, (LPBYTE)devline, strlen(devline) + 1); |
| 515 | RegCloseKey(hkey); |
| 516 | } |
| 517 | |
| 518 | HeapFree(GetProcessHeap(), 0, devline); |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 519 | |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 520 | TRACE("Printer %d: %s\n", i, dests[i].name); |
| 521 | if(RegOpenKeyA(hkeyPrinters, dests[i].name, &hkeyPrinter) == ERROR_SUCCESS) { |
| 522 | /* Printer already in registry, delete the tag added in WINSPOOL_LoadSystemPrinters |
| 523 | and continue */ |
| 524 | TRACE("Printer already exists\n"); |
| 525 | RegDeleteValueW(hkeyPrinter, May_Delete_Value); |
| 526 | RegCloseKey(hkeyPrinter); |
| 527 | } else { |
Andrew Talbot | 02c04ea | 2006-08-19 14:22:39 +0100 | [diff] [blame] | 528 | static CHAR data_type[] = "RAW", |
| 529 | print_proc[] = "WinPrint", |
Andrew Talbot | 02c04ea | 2006-08-19 14:22:39 +0100 | [diff] [blame] | 530 | comment[] = "WINEPS Printer using CUPS", |
| 531 | location[] = "<physical location of printer>", |
| 532 | params[] = "<parameters?>", |
| 533 | share_name[] = "<share name?>", |
| 534 | sep_file[] = "<sep file?>"; |
| 535 | |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 536 | add_printer_driver(dests[i].name); |
| 537 | |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 538 | memset(&pinfo2a,0,sizeof(pinfo2a)); |
Andrew Talbot | 02c04ea | 2006-08-19 14:22:39 +0100 | [diff] [blame] | 539 | pinfo2a.pPrinterName = dests[i].name; |
| 540 | pinfo2a.pDatatype = data_type; |
| 541 | pinfo2a.pPrintProcessor = print_proc; |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 542 | pinfo2a.pDriverName = dests[i].name; |
Andrew Talbot | 02c04ea | 2006-08-19 14:22:39 +0100 | [diff] [blame] | 543 | pinfo2a.pComment = comment; |
| 544 | pinfo2a.pLocation = location; |
| 545 | pinfo2a.pPortName = port; |
| 546 | pinfo2a.pParameters = params; |
| 547 | pinfo2a.pShareName = share_name; |
| 548 | pinfo2a.pSepFile = sep_file; |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 549 | |
| 550 | if (!AddPrinterA(NULL,2,(LPBYTE)&pinfo2a)) { |
| 551 | if (GetLastError() != ERROR_PRINTER_ALREADY_EXISTS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 552 | ERR("printer '%s' not added by AddPrinterA (error %d)\n",dests[i].name,GetLastError()); |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 553 | } |
| 554 | } |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 555 | HeapFree(GetProcessHeap(),0,port); |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 556 | |
| 557 | hadprinter = TRUE; |
Pedro Araujo Chaves Jr | ffbd30d | 2007-07-04 20:22:15 -0300 | [diff] [blame] | 558 | if (dests[i].is_default) { |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 559 | WINSPOOL_SetDefaultPrinter(dests[i].name, dests[i].name, TRUE); |
Pedro Araujo Chaves Jr | ffbd30d | 2007-07-04 20:22:15 -0300 | [diff] [blame] | 560 | haddefault = TRUE; |
| 561 | } |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 562 | } |
Pedro Araujo Chaves Jr | ffbd30d | 2007-07-04 20:22:15 -0300 | [diff] [blame] | 563 | if (hadprinter & !haddefault) |
| 564 | WINSPOOL_SetDefaultPrinter(dests[0].name, dests[0].name, TRUE); |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 565 | RegCloseKey(hkeyPrinters); |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 566 | return hadprinter; |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 567 | } |
| 568 | #endif |
| 569 | |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 570 | static BOOL |
Andrew Talbot | 02c04ea | 2006-08-19 14:22:39 +0100 | [diff] [blame] | 571 | PRINTCAP_ParseEntry(const char *pent, BOOL isfirst) { |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 572 | PRINTER_INFO_2A pinfo2a; |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 573 | char *e,*s,*name,*prettyname,*devname; |
| 574 | BOOL ret = FALSE, set_default = FALSE; |
Lionel Debroux | 87b33cc | 2007-12-14 14:56:57 +0100 | [diff] [blame] | 575 | char *port = NULL, *devline,*env_default; |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 576 | HKEY hkeyPrinter, hkeyPrinters, hkey; |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 577 | |
Bill Medland | dff78ed | 2002-05-17 00:10:15 +0000 | [diff] [blame] | 578 | while (isspace(*pent)) pent++; |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 579 | s = strchr(pent,':'); |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 580 | if(s) *s='\0'; |
| 581 | name = HeapAlloc(GetProcessHeap(), 0, strlen(pent) + 1); |
| 582 | strcpy(name,pent); |
| 583 | if(s) { |
| 584 | *s=':'; |
| 585 | pent = s; |
| 586 | } else |
| 587 | pent = ""; |
| 588 | |
| 589 | TRACE("name=%s entry=%s\n",name, pent); |
| 590 | |
| 591 | if(ispunct(*name)) { /* a tc entry, not a real printer */ |
| 592 | TRACE("skipping tc entry\n"); |
| 593 | goto end; |
| 594 | } |
| 595 | |
| 596 | if(strstr(pent,":server")) { /* server only version so skip */ |
| 597 | TRACE("skipping server entry\n"); |
| 598 | goto end; |
| 599 | } |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 600 | |
| 601 | /* Determine whether this is a postscript printer. */ |
| 602 | |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 603 | ret = TRUE; |
| 604 | env_default = getenv("PRINTER"); |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 605 | prettyname = name; |
| 606 | /* Get longest name, usually the one at the right for later display. */ |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 607 | while((s=strchr(prettyname,'|'))) { |
| 608 | *s = '\0'; |
| 609 | e = s; |
| 610 | while(isspace(*--e)) *e = '\0'; |
| 611 | TRACE("\t%s\n", debugstr_a(prettyname)); |
| 612 | if(env_default && !strcasecmp(prettyname, env_default)) set_default = TRUE; |
| 613 | for(prettyname = s+1; isspace(*prettyname); prettyname++) |
| 614 | ; |
| 615 | } |
| 616 | e = prettyname + strlen(prettyname); |
| 617 | while(isspace(*--e)) *e = '\0'; |
| 618 | TRACE("\t%s\n", debugstr_a(prettyname)); |
| 619 | if(env_default && !strcasecmp(prettyname, env_default)) set_default = TRUE; |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 620 | |
| 621 | /* prettyname must fit into the dmDeviceName member of DEVMODE struct, |
| 622 | * if it is too long, we use it as comment below. */ |
| 623 | devname = prettyname; |
| 624 | if (strlen(devname)>=CCHDEVICENAME-1) |
| 625 | devname = name; |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 626 | if (strlen(devname)>=CCHDEVICENAME-1) { |
| 627 | ret = FALSE; |
| 628 | goto end; |
| 629 | } |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 630 | |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 631 | port = HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(name)+1); |
| 632 | sprintf(port,"LPR:%s",name); |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 633 | |
Detlef Riekenberg | 473717f | 2008-05-06 20:26:05 +0200 | [diff] [blame] | 634 | /* FIXME: remove extension. Fix gdi32/drivers and comdlg32/printdlg first */ |
| 635 | devline = HeapAlloc(GetProcessHeap(), 0, sizeof("WINEPS.DRV,,15,45") + strlen(port)); |
| 636 | sprintf(devline, "WINEPS.DRV,%s", port); |
| 637 | WriteProfileStringA("devices", devname, devline); |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 638 | if(RegCreateKeyW(HKEY_CURRENT_USER, user_printers_reg_key, &hkey) == ERROR_SUCCESS) { |
Mike McCormack | bc4a576 | 2005-08-03 11:03:44 +0000 | [diff] [blame] | 639 | RegSetValueExA(hkey, devname, 0, REG_SZ, (LPBYTE)devline, strlen(devline) + 1); |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 640 | RegCloseKey(hkey); |
| 641 | } |
Detlef Riekenberg | 473717f | 2008-05-06 20:26:05 +0200 | [diff] [blame] | 642 | |
| 643 | lstrcatA(devline, ",15,45"); |
| 644 | WriteProfileStringA("PrinterPorts", devname, devline); |
| 645 | if(RegCreateKeyW(HKEY_CURRENT_USER, WinNT_CV_PrinterPortsW, &hkey) == ERROR_SUCCESS) { |
| 646 | RegSetValueExA(hkey, devname, 0, REG_SZ, (LPBYTE)devline, strlen(devline) + 1); |
| 647 | RegCloseKey(hkey); |
| 648 | } |
| 649 | |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 650 | HeapFree(GetProcessHeap(),0,devline); |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 651 | |
Detlef Riekenberg | 358ce06 | 2006-05-21 14:35:29 +0200 | [diff] [blame] | 652 | if(RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) != |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 653 | ERROR_SUCCESS) { |
| 654 | ERR("Can't create Printers key\n"); |
| 655 | ret = FALSE; |
| 656 | goto end; |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 657 | } |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 658 | if(RegOpenKeyA(hkeyPrinters, devname, &hkeyPrinter) == ERROR_SUCCESS) { |
| 659 | /* Printer already in registry, delete the tag added in WINSPOOL_LoadSystemPrinters |
| 660 | and continue */ |
| 661 | TRACE("Printer already exists\n"); |
| 662 | RegDeleteValueW(hkeyPrinter, May_Delete_Value); |
| 663 | RegCloseKey(hkeyPrinter); |
| 664 | } else { |
Andrew Talbot | 02c04ea | 2006-08-19 14:22:39 +0100 | [diff] [blame] | 665 | static CHAR data_type[] = "RAW", |
| 666 | print_proc[] = "WinPrint", |
Andrew Talbot | 02c04ea | 2006-08-19 14:22:39 +0100 | [diff] [blame] | 667 | comment[] = "WINEPS Printer using LPR", |
| 668 | params[] = "<parameters?>", |
| 669 | share_name[] = "<share name?>", |
| 670 | sep_file[] = "<sep file?>"; |
| 671 | |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 672 | add_printer_driver(devname); |
| 673 | |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 674 | memset(&pinfo2a,0,sizeof(pinfo2a)); |
Andrew Talbot | 02c04ea | 2006-08-19 14:22:39 +0100 | [diff] [blame] | 675 | pinfo2a.pPrinterName = devname; |
| 676 | pinfo2a.pDatatype = data_type; |
| 677 | pinfo2a.pPrintProcessor = print_proc; |
Huw Davies | d510bdc | 2006-11-07 17:19:06 +0000 | [diff] [blame] | 678 | pinfo2a.pDriverName = devname; |
Andrew Talbot | 02c04ea | 2006-08-19 14:22:39 +0100 | [diff] [blame] | 679 | pinfo2a.pComment = comment; |
| 680 | pinfo2a.pLocation = prettyname; |
| 681 | pinfo2a.pPortName = port; |
| 682 | pinfo2a.pParameters = params; |
| 683 | pinfo2a.pShareName = share_name; |
| 684 | pinfo2a.pSepFile = sep_file; |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 685 | |
| 686 | if (!AddPrinterA(NULL,2,(LPBYTE)&pinfo2a)) { |
| 687 | if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 688 | ERR("%s not added by AddPrinterA (%d)\n",name,GetLastError()); |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 689 | } |
| 690 | } |
| 691 | RegCloseKey(hkeyPrinters); |
| 692 | |
| 693 | if (isfirst || set_default) |
| 694 | WINSPOOL_SetDefaultPrinter(devname,name,TRUE); |
| 695 | |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 696 | end: |
Lionel Debroux | 87b33cc | 2007-12-14 14:56:57 +0100 | [diff] [blame] | 697 | HeapFree(GetProcessHeap(), 0, port); |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 698 | HeapFree(GetProcessHeap(), 0, name); |
| 699 | return ret; |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 700 | } |
| 701 | |
| 702 | static BOOL |
| 703 | PRINTCAP_LoadPrinters(void) { |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 704 | BOOL hadprinter = FALSE; |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 705 | char buf[200]; |
| 706 | FILE *f; |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 707 | char *pent = NULL; |
| 708 | BOOL had_bash = FALSE; |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 709 | |
| 710 | f = fopen("/etc/printcap","r"); |
| 711 | if (!f) |
| 712 | return FALSE; |
| 713 | |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 714 | while(fgets(buf,sizeof(buf),f)) { |
| 715 | char *start, *end; |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 716 | |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 717 | end=strchr(buf,'\n'); |
| 718 | if (end) *end='\0'; |
| 719 | |
| 720 | start = buf; |
| 721 | while(isspace(*start)) start++; |
| 722 | if(*start == '#' || *start == '\0') |
| 723 | continue; |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 724 | |
Huw Davies | e459f7a | 2003-11-11 00:42:35 +0000 | [diff] [blame] | 725 | if(pent && !had_bash && *start != ':' && *start != '|') { /* start of new entry, parse the previous one */ |
| 726 | hadprinter |= PRINTCAP_ParseEntry(pent,!hadprinter); |
| 727 | HeapFree(GetProcessHeap(),0,pent); |
| 728 | pent = NULL; |
| 729 | } |
| 730 | |
| 731 | if (end && *--end == '\\') { |
| 732 | *end = '\0'; |
| 733 | had_bash = TRUE; |
| 734 | } else |
| 735 | had_bash = FALSE; |
| 736 | |
| 737 | if (pent) { |
| 738 | pent=HeapReAlloc(GetProcessHeap(),0,pent,strlen(pent)+strlen(start)+1); |
| 739 | strcat(pent,start); |
| 740 | } else { |
| 741 | pent=HeapAlloc(GetProcessHeap(),0,strlen(start)+1); |
| 742 | strcpy(pent,start); |
| 743 | } |
| 744 | |
| 745 | } |
| 746 | if(pent) { |
| 747 | hadprinter |= PRINTCAP_ParseEntry(pent,!hadprinter); |
| 748 | HeapFree(GetProcessHeap(),0,pent); |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 749 | } |
| 750 | fclose(f); |
| 751 | return hadprinter; |
| 752 | } |
| 753 | |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 754 | static inline DWORD set_reg_szW(HKEY hkey, const WCHAR *keyname, const WCHAR *value) |
Gerard Patel | 14c9429 | 2001-10-28 21:16:38 +0000 | [diff] [blame] | 755 | { |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 756 | if (value) |
Eric Pouech | 0a25896 | 2004-11-30 21:38:57 +0000 | [diff] [blame] | 757 | return RegSetValueExW(hkey, keyname, 0, REG_SZ, (const BYTE*)value, |
Huw Davies | 1ad05ac | 2006-11-07 17:16:29 +0000 | [diff] [blame] | 758 | (lstrlenW(value) + 1) * sizeof(WCHAR)); |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 759 | else |
| 760 | return ERROR_FILE_NOT_FOUND; |
Gerard Patel | 14c9429 | 2001-10-28 21:16:38 +0000 | [diff] [blame] | 761 | } |
| 762 | |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 763 | /***************************************************************************** |
Francois Gouget | 0c31ca3 | 2007-01-17 17:18:54 +0100 | [diff] [blame] | 764 | * enumerate the local monitors (INTERNAL) |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 765 | * |
| 766 | * returns the needed size (in bytes) for pMonitors |
| 767 | * and *lpreturned is set to number of entries returned in pMonitors |
| 768 | * |
| 769 | */ |
| 770 | static DWORD get_local_monitors(DWORD level, LPBYTE pMonitors, DWORD cbBuf, LPDWORD lpreturned) |
| 771 | { |
| 772 | HKEY hroot = NULL; |
| 773 | HKEY hentry = NULL; |
| 774 | LPWSTR ptr; |
| 775 | LPMONITOR_INFO_2W mi; |
| 776 | WCHAR buffer[MAX_PATH]; |
| 777 | WCHAR dllname[MAX_PATH]; |
| 778 | DWORD dllsize; |
| 779 | DWORD len; |
| 780 | DWORD index = 0; |
| 781 | DWORD needed = 0; |
| 782 | DWORD numentries; |
| 783 | DWORD entrysize; |
| 784 | |
| 785 | entrysize = (level == 1) ? sizeof(MONITOR_INFO_1W) : sizeof(MONITOR_INFO_2W); |
| 786 | |
| 787 | numentries = *lpreturned; /* this is 0, when we scan the registry */ |
| 788 | len = entrysize * numentries; |
| 789 | ptr = (LPWSTR) &pMonitors[len]; |
| 790 | |
| 791 | numentries = 0; |
Rob Shearman | 35be5e1 | 2008-02-21 16:44:48 +0000 | [diff] [blame] | 792 | len = sizeof(buffer)/sizeof(buffer[0]); |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 793 | buffer[0] = '\0'; |
| 794 | |
| 795 | /* Windows creates the "Monitors"-Key on reboot / start "spooler" */ |
| 796 | if (RegCreateKeyW(HKEY_LOCAL_MACHINE, MonitorsW, &hroot) == ERROR_SUCCESS) { |
| 797 | /* Scan all Monitor-Registry-Keys */ |
| 798 | while (RegEnumKeyExW(hroot, index, buffer, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 799 | TRACE("Monitor_%d: %s\n", numentries, debugstr_w(buffer)); |
Rob Shearman | ee8dd6a | 2008-02-21 16:44:42 +0000 | [diff] [blame] | 800 | dllsize = sizeof(dllname); |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 801 | dllname[0] = '\0'; |
| 802 | |
| 803 | /* The Monitor must have a Driver-DLL */ |
| 804 | if (RegOpenKeyExW(hroot, buffer, 0, KEY_READ, &hentry) == ERROR_SUCCESS) { |
| 805 | if (RegQueryValueExW(hentry, DriverW, NULL, NULL, (LPBYTE) dllname, &dllsize) == ERROR_SUCCESS) { |
| 806 | /* We found a valid DLL for this Monitor. */ |
| 807 | TRACE("using Driver: %s\n", debugstr_w(dllname)); |
| 808 | } |
| 809 | RegCloseKey(hentry); |
| 810 | } |
| 811 | |
| 812 | /* Windows returns only Port-Monitors here, but to simplify our code, |
| 813 | we do no filtering for Language-Monitors */ |
| 814 | if (dllname[0]) { |
| 815 | numentries++; |
| 816 | needed += entrysize; |
| 817 | needed += (len+1) * sizeof(WCHAR); /* len is lstrlenW(monitorname) */ |
| 818 | if (level > 1) { |
| 819 | /* we install and return only monitors for "Windows NT x86" */ |
| 820 | needed += (lstrlenW(envname_x86W) +1) * sizeof(WCHAR); |
| 821 | needed += dllsize; |
| 822 | } |
| 823 | |
| 824 | /* required size is calculated. Now fill the user-buffer */ |
| 825 | if (pMonitors && (cbBuf >= needed)){ |
| 826 | mi = (LPMONITOR_INFO_2W) pMonitors; |
| 827 | pMonitors += entrysize; |
| 828 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 829 | TRACE("%p: writing MONITOR_INFO_%dW #%d\n", mi, level, numentries); |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 830 | mi->pName = ptr; |
| 831 | lstrcpyW(ptr, buffer); /* Name of the Monitor */ |
| 832 | ptr += (len+1); /* len is lstrlenW(monitorname) */ |
| 833 | if (level > 1) { |
| 834 | mi->pEnvironment = ptr; |
| 835 | lstrcpyW(ptr, envname_x86W); /* fixed to "Windows NT x86" */ |
| 836 | ptr += (lstrlenW(envname_x86W)+1); |
| 837 | |
| 838 | mi->pDLLName = ptr; |
| 839 | lstrcpyW(ptr, dllname); /* Name of the Driver-DLL */ |
| 840 | ptr += (dllsize / sizeof(WCHAR)); |
| 841 | } |
| 842 | } |
| 843 | } |
| 844 | index++; |
Rob Shearman | 18d8919 | 2008-02-25 09:01:29 +0000 | [diff] [blame] | 845 | len = sizeof(buffer)/sizeof(buffer[0]); |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 846 | buffer[0] = '\0'; |
| 847 | } |
| 848 | RegCloseKey(hroot); |
| 849 | } |
| 850 | *lpreturned = numentries; |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 851 | TRACE("need %d byte for %d entries\n", needed, numentries); |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 852 | return needed; |
| 853 | } |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 854 | |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 855 | /****************************************************************** |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 856 | * monitor_unload [internal] |
| 857 | * |
| 858 | * release a printmonitor and unload it from memory, when needed |
| 859 | * |
| 860 | */ |
| 861 | static void monitor_unload(monitor_t * pm) |
| 862 | { |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 863 | if (pm == NULL) return; |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 864 | TRACE("%p (refcount: %d) %s\n", pm, pm->refcount, debugstr_w(pm->name)); |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 865 | |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 866 | EnterCriticalSection(&monitor_handles_cs); |
| 867 | |
| 868 | if (pm->refcount) pm->refcount--; |
| 869 | |
| 870 | if (pm->refcount == 0) { |
| 871 | list_remove(&pm->entry); |
| 872 | FreeLibrary(pm->hdll); |
| 873 | HeapFree(GetProcessHeap(), 0, pm->name); |
| 874 | HeapFree(GetProcessHeap(), 0, pm->dllname); |
| 875 | HeapFree(GetProcessHeap(), 0, pm); |
| 876 | } |
| 877 | LeaveCriticalSection(&monitor_handles_cs); |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 878 | } |
| 879 | |
| 880 | /****************************************************************** |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 881 | * monitor_unloadall [internal] |
| 882 | * |
| 883 | * release all printmonitors and unload them from memory, when needed |
| 884 | */ |
| 885 | |
| 886 | static void monitor_unloadall(void) |
| 887 | { |
| 888 | monitor_t * pm; |
| 889 | monitor_t * next; |
| 890 | |
| 891 | EnterCriticalSection(&monitor_handles_cs); |
| 892 | /* iterate through the list, with safety against removal */ |
| 893 | LIST_FOR_EACH_ENTRY_SAFE(pm, next, &monitor_handles, monitor_t, entry) |
| 894 | { |
| 895 | monitor_unload(pm); |
| 896 | } |
| 897 | LeaveCriticalSection(&monitor_handles_cs); |
| 898 | } |
| 899 | |
| 900 | /****************************************************************** |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 901 | * monitor_load [internal] |
| 902 | * |
| 903 | * load a printmonitor, get the dllname from the registry, when needed |
| 904 | * initialize the monitor and dump found function-pointers |
| 905 | * |
| 906 | * On failure, SetLastError() is called and NULL is returned |
| 907 | */ |
| 908 | |
Dmitry Timoshkov | 1804900 | 2006-11-29 18:04:13 +0800 | [diff] [blame] | 909 | static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname) |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 910 | { |
| 911 | LPMONITOR2 (WINAPI *pInitializePrintMonitor2) (PMONITORINIT, LPHANDLE); |
| 912 | PMONITORUI (WINAPI *pInitializePrintMonitorUI)(VOID); |
| 913 | LPMONITOREX (WINAPI *pInitializePrintMonitor) (LPWSTR); |
| 914 | DWORD (WINAPI *pInitializeMonitorEx)(LPWSTR, LPMONITOR); |
| 915 | DWORD (WINAPI *pInitializeMonitor) (LPWSTR); |
| 916 | |
| 917 | monitor_t * pm = NULL; |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 918 | monitor_t * cursor; |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 919 | LPWSTR regroot = NULL; |
| 920 | LPWSTR driver = dllname; |
| 921 | |
| 922 | TRACE("(%s, %s)\n", debugstr_w(name), debugstr_w(dllname)); |
| 923 | /* Is the Monitor already loaded? */ |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 924 | EnterCriticalSection(&monitor_handles_cs); |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 925 | |
Detlef Riekenberg | 9bdd900 | 2007-01-11 13:05:16 +0100 | [diff] [blame] | 926 | if (name) { |
| 927 | LIST_FOR_EACH_ENTRY(cursor, &monitor_handles, monitor_t, entry) |
| 928 | { |
| 929 | if (cursor->name && (lstrcmpW(name, cursor->name) == 0)) { |
| 930 | pm = cursor; |
| 931 | break; |
| 932 | } |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 933 | } |
| 934 | } |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 935 | |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 936 | if (pm == NULL) { |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 937 | pm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(monitor_t)); |
| 938 | if (pm == NULL) goto cleanup; |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 939 | list_add_tail(&monitor_handles, &pm->entry); |
| 940 | } |
| 941 | pm->refcount++; |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 942 | |
| 943 | if (pm->name == NULL) { |
| 944 | /* Load the monitor */ |
| 945 | LPMONITOREX pmonitorEx; |
| 946 | DWORD len; |
| 947 | |
Detlef Riekenberg | 9bdd900 | 2007-01-11 13:05:16 +0100 | [diff] [blame] | 948 | if (name) { |
| 949 | len = lstrlenW(MonitorsW) + lstrlenW(name) + 2; |
| 950 | regroot = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 951 | } |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 952 | |
| 953 | if (regroot) { |
| 954 | lstrcpyW(regroot, MonitorsW); |
| 955 | lstrcatW(regroot, name); |
| 956 | /* Get the Driver from the Registry */ |
Detlef Riekenberg | 0bd336a | 2006-11-04 00:26:20 +0100 | [diff] [blame] | 957 | if (driver == NULL) { |
| 958 | HKEY hroot; |
| 959 | DWORD namesize; |
| 960 | if (RegOpenKeyW(HKEY_LOCAL_MACHINE, regroot, &hroot) == ERROR_SUCCESS) { |
| 961 | if (RegQueryValueExW(hroot, DriverW, NULL, NULL, NULL, |
| 962 | &namesize) == ERROR_SUCCESS) { |
| 963 | driver = HeapAlloc(GetProcessHeap(), 0, namesize); |
| 964 | RegQueryValueExW(hroot, DriverW, NULL, NULL, (LPBYTE) driver, &namesize) ; |
| 965 | } |
| 966 | RegCloseKey(hroot); |
| 967 | } |
| 968 | } |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 969 | } |
| 970 | |
| 971 | pm->name = strdupW(name); |
| 972 | pm->dllname = strdupW(driver); |
| 973 | |
Detlef Riekenberg | 9bdd900 | 2007-01-11 13:05:16 +0100 | [diff] [blame] | 974 | if ((name && (!regroot || !pm->name)) || !pm->dllname) { |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 975 | monitor_unload(pm); |
| 976 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); |
| 977 | pm = NULL; |
| 978 | goto cleanup; |
| 979 | } |
| 980 | |
| 981 | pm->hdll = LoadLibraryW(driver); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 982 | TRACE("%p: LoadLibrary(%s) => %d\n", pm->hdll, debugstr_w(driver), GetLastError()); |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 983 | |
| 984 | if (pm->hdll == NULL) { |
| 985 | monitor_unload(pm); |
| 986 | SetLastError(ERROR_MOD_NOT_FOUND); |
| 987 | pm = NULL; |
| 988 | goto cleanup; |
| 989 | } |
| 990 | |
| 991 | pInitializePrintMonitor2 = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitor2"); |
| 992 | pInitializePrintMonitorUI = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitorUI"); |
| 993 | pInitializePrintMonitor = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitor"); |
| 994 | pInitializeMonitorEx = (void *)GetProcAddress(pm->hdll, "InitializeMonitorEx"); |
| 995 | pInitializeMonitor = (void *)GetProcAddress(pm->hdll, "InitializeMonitor"); |
| 996 | |
| 997 | |
| 998 | TRACE("%p: %s,pInitializePrintMonitor2\n", pInitializePrintMonitor2, debugstr_w(driver)); |
| 999 | TRACE("%p: %s,pInitializePrintMonitorUI\n", pInitializePrintMonitorUI, debugstr_w(driver)); |
| 1000 | TRACE("%p: %s,pInitializePrintMonitor\n", pInitializePrintMonitor, debugstr_w(driver)); |
| 1001 | TRACE("%p: %s,pInitializeMonitorEx\n", pInitializeMonitorEx, debugstr_w(driver)); |
| 1002 | TRACE("%p: %s,pInitializeMonitor\n", pInitializeMonitor, debugstr_w(driver)); |
| 1003 | |
| 1004 | if (pInitializePrintMonitorUI != NULL) { |
| 1005 | pm->monitorUI = pInitializePrintMonitorUI(); |
| 1006 | TRACE("%p: MONITORUI from %s,InitializePrintMonitorUI()\n", pm->monitorUI, debugstr_w(driver)); |
| 1007 | if (pm->monitorUI) { |
Alexandre Julliard | b0ea577 | 2006-10-20 12:16:45 +0200 | [diff] [blame] | 1008 | TRACE( "0x%08x: dwMonitorSize (%d)\n", |
| 1009 | pm->monitorUI->dwMonitorUISize, pm->monitorUI->dwMonitorUISize ); |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 1010 | |
| 1011 | } |
| 1012 | } |
| 1013 | |
Detlef Riekenberg | 9bdd900 | 2007-01-11 13:05:16 +0100 | [diff] [blame] | 1014 | if (pInitializePrintMonitor && regroot) { |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 1015 | pmonitorEx = pInitializePrintMonitor(regroot); |
Detlef Riekenberg | 9bdd900 | 2007-01-11 13:05:16 +0100 | [diff] [blame] | 1016 | TRACE( "%p: LPMONITOREX from %s,InitializePrintMonitor(%s)\n", |
| 1017 | pmonitorEx, debugstr_w(driver), debugstr_w(regroot)); |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 1018 | |
| 1019 | if (pmonitorEx) { |
| 1020 | pm->dwMonitorSize = pmonitorEx->dwMonitorSize; |
| 1021 | pm->monitor = &(pmonitorEx->Monitor); |
| 1022 | } |
| 1023 | } |
| 1024 | |
| 1025 | if (pm->monitor) { |
Alexandre Julliard | b0ea577 | 2006-10-20 12:16:45 +0200 | [diff] [blame] | 1026 | TRACE( "0x%08x: dwMonitorSize (%d)\n", pm->dwMonitorSize, pm->dwMonitorSize ); |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 1027 | |
| 1028 | } |
| 1029 | |
Detlef Riekenberg | 9bdd900 | 2007-01-11 13:05:16 +0100 | [diff] [blame] | 1030 | if (!pm->monitor && regroot) { |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 1031 | if (pInitializePrintMonitor2 != NULL) { |
| 1032 | FIXME("%s,InitializePrintMonitor2 not implemented\n", debugstr_w(driver)); |
| 1033 | } |
| 1034 | if (pInitializeMonitorEx != NULL) { |
| 1035 | FIXME("%s,InitializeMonitorEx not implemented\n", debugstr_w(driver)); |
| 1036 | } |
| 1037 | if (pInitializeMonitor != NULL) { |
| 1038 | FIXME("%s,InitializeMonitor not implemented\n", debugstr_w(driver)); |
| 1039 | } |
| 1040 | } |
| 1041 | if (!pm->monitor && !pm->monitorUI) { |
| 1042 | monitor_unload(pm); |
| 1043 | SetLastError(ERROR_PROC_NOT_FOUND); |
| 1044 | pm = NULL; |
| 1045 | } |
| 1046 | } |
| 1047 | cleanup: |
Detlef Riekenberg | a7481a9 | 2006-11-28 20:04:08 +0100 | [diff] [blame] | 1048 | if ((pm_localport == NULL) && (pm != NULL) && (lstrcmpW(pm->name, LocalPortW) == 0)) { |
| 1049 | pm->refcount++; |
| 1050 | pm_localport = pm; |
| 1051 | } |
Detlef Riekenberg | ec1c7cc | 2006-09-02 22:55:25 +0200 | [diff] [blame] | 1052 | LeaveCriticalSection(&monitor_handles_cs); |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 1053 | if (driver != dllname) HeapFree(GetProcessHeap(), 0, driver); |
| 1054 | HeapFree(GetProcessHeap(), 0, regroot); |
| 1055 | TRACE("=> %p\n", pm); |
| 1056 | return pm; |
| 1057 | } |
| 1058 | |
| 1059 | /****************************************************************** |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 1060 | * monitor_loadall [internal] |
| 1061 | * |
| 1062 | * Load all registered monitors |
| 1063 | * |
| 1064 | */ |
| 1065 | static DWORD monitor_loadall(void) |
| 1066 | { |
| 1067 | monitor_t * pm; |
| 1068 | DWORD registered = 0; |
| 1069 | DWORD loaded = 0; |
| 1070 | HKEY hmonitors; |
| 1071 | WCHAR buffer[MAX_PATH]; |
| 1072 | DWORD id = 0; |
| 1073 | |
| 1074 | if (RegOpenKeyW(HKEY_LOCAL_MACHINE, MonitorsW, &hmonitors) == ERROR_SUCCESS) { |
| 1075 | RegQueryInfoKeyW(hmonitors, NULL, NULL, NULL, ®istered, NULL, NULL, |
| 1076 | NULL, NULL, NULL, NULL, NULL); |
| 1077 | |
| 1078 | TRACE("%d monitors registered\n", registered); |
| 1079 | |
| 1080 | EnterCriticalSection(&monitor_handles_cs); |
| 1081 | while (id < registered) { |
| 1082 | buffer[0] = '\0'; |
| 1083 | RegEnumKeyW(hmonitors, id, buffer, MAX_PATH); |
| 1084 | pm = monitor_load(buffer, NULL); |
| 1085 | if (pm) loaded++; |
| 1086 | id++; |
| 1087 | } |
| 1088 | LeaveCriticalSection(&monitor_handles_cs); |
| 1089 | RegCloseKey(hmonitors); |
| 1090 | } |
| 1091 | TRACE("%d monitors loaded\n", loaded); |
| 1092 | return loaded; |
| 1093 | } |
| 1094 | |
| 1095 | /****************************************************************** |
Detlef Riekenberg | e576b09 | 2007-01-11 13:10:37 +0100 | [diff] [blame] | 1096 | * monitor_loadui [internal] |
| 1097 | * |
| 1098 | * load the userinterface-dll for a given portmonitor |
| 1099 | * |
| 1100 | * On failure, NULL is returned |
| 1101 | */ |
| 1102 | |
| 1103 | static monitor_t * monitor_loadui(monitor_t * pm) |
| 1104 | { |
| 1105 | monitor_t * pui = NULL; |
| 1106 | LPWSTR buffer[MAX_PATH]; |
| 1107 | HANDLE hXcv; |
| 1108 | DWORD len; |
| 1109 | DWORD res; |
| 1110 | |
| 1111 | if (pm == NULL) return NULL; |
| 1112 | TRACE("(%p) => dllname: %s\n", pm, debugstr_w(pm->dllname)); |
| 1113 | |
| 1114 | /* Try the Portmonitor first; works for many monitors */ |
| 1115 | if (pm->monitorUI) { |
| 1116 | EnterCriticalSection(&monitor_handles_cs); |
| 1117 | pm->refcount++; |
| 1118 | LeaveCriticalSection(&monitor_handles_cs); |
| 1119 | return pm; |
| 1120 | } |
| 1121 | |
| 1122 | /* query the userinterface-dllname from the Portmonitor */ |
| 1123 | if ((pm->monitor) && (pm->monitor->pfnXcvDataPort)) { |
| 1124 | /* building (",XcvMonitor %s",pm->name) not needed yet */ |
| 1125 | res = pm->monitor->pfnXcvOpenPort(emptyStringW, SERVER_ACCESS_ADMINISTER, &hXcv); |
| 1126 | TRACE("got %u with %p\n", res, hXcv); |
| 1127 | if (res) { |
| 1128 | res = pm->monitor->pfnXcvDataPort(hXcv, MonitorUIW, NULL, 0, (BYTE *) buffer, sizeof(buffer), &len); |
| 1129 | TRACE("got %u with %s\n", res, debugstr_w((LPWSTR) buffer)); |
| 1130 | if (res == ERROR_SUCCESS) pui = monitor_load(NULL, (LPWSTR) buffer); |
| 1131 | pm->monitor->pfnXcvClosePort(hXcv); |
| 1132 | } |
| 1133 | } |
| 1134 | return pui; |
| 1135 | } |
| 1136 | |
| 1137 | |
| 1138 | /****************************************************************** |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 1139 | * monitor_load_by_port [internal] |
| 1140 | * |
| 1141 | * load a printmonitor for a given port |
| 1142 | * |
| 1143 | * On failure, NULL is returned |
| 1144 | */ |
| 1145 | |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 1146 | static monitor_t * monitor_load_by_port(LPCWSTR portname) |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 1147 | { |
| 1148 | HKEY hroot; |
| 1149 | HKEY hport; |
| 1150 | LPWSTR buffer; |
| 1151 | monitor_t * pm = NULL; |
| 1152 | DWORD registered = 0; |
| 1153 | DWORD id = 0; |
| 1154 | DWORD len; |
| 1155 | |
| 1156 | TRACE("(%s)\n", debugstr_w(portname)); |
| 1157 | |
| 1158 | /* Try the Local Monitor first */ |
| 1159 | if (RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot) == ERROR_SUCCESS) { |
| 1160 | if (RegQueryValueExW(hroot, portname, NULL, NULL, NULL, &len) == ERROR_SUCCESS) { |
| 1161 | /* found the portname */ |
| 1162 | RegCloseKey(hroot); |
| 1163 | return monitor_load(LocalPortW, NULL); |
| 1164 | } |
| 1165 | RegCloseKey(hroot); |
| 1166 | } |
| 1167 | |
| 1168 | len = MAX_PATH + lstrlenW(bs_Ports_bsW) + lstrlenW(portname) + 1; |
| 1169 | buffer = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 1170 | if (buffer == NULL) return NULL; |
| 1171 | |
| 1172 | if (RegOpenKeyW(HKEY_LOCAL_MACHINE, MonitorsW, &hroot) == ERROR_SUCCESS) { |
| 1173 | EnterCriticalSection(&monitor_handles_cs); |
| 1174 | RegQueryInfoKeyW(hroot, NULL, NULL, NULL, ®istered, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
| 1175 | |
| 1176 | while ((pm == NULL) && (id < registered)) { |
| 1177 | buffer[0] = '\0'; |
| 1178 | RegEnumKeyW(hroot, id, buffer, MAX_PATH); |
| 1179 | TRACE("testing %s\n", debugstr_w(buffer)); |
| 1180 | len = lstrlenW(buffer); |
| 1181 | lstrcatW(buffer, bs_Ports_bsW); |
| 1182 | lstrcatW(buffer, portname); |
| 1183 | if (RegOpenKeyW(hroot, buffer, &hport) == ERROR_SUCCESS) { |
| 1184 | RegCloseKey(hport); |
| 1185 | buffer[len] = '\0'; /* use only the Monitor-Name */ |
| 1186 | pm = monitor_load(buffer, NULL); |
| 1187 | } |
| 1188 | id++; |
| 1189 | } |
| 1190 | LeaveCriticalSection(&monitor_handles_cs); |
| 1191 | RegCloseKey(hroot); |
| 1192 | } |
| 1193 | HeapFree(GetProcessHeap(), 0, buffer); |
| 1194 | return pm; |
| 1195 | } |
| 1196 | |
| 1197 | /****************************************************************** |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 1198 | * enumerate the local Ports from all loaded monitors (internal) |
| 1199 | * |
| 1200 | * returns the needed size (in bytes) for pPorts |
| 1201 | * and *lpreturned is set to number of entries returned in pPorts |
| 1202 | * |
| 1203 | */ |
| 1204 | static DWORD get_ports_from_all_monitors(DWORD level, LPBYTE pPorts, DWORD cbBuf, LPDWORD lpreturned) |
| 1205 | { |
| 1206 | monitor_t * pm; |
| 1207 | LPWSTR ptr; |
| 1208 | LPPORT_INFO_2W cache; |
| 1209 | LPPORT_INFO_2W out; |
Detlef Riekenberg | 4cd9d53 | 2007-03-29 17:38:16 +0200 | [diff] [blame] | 1210 | LPBYTE pi_buffer = NULL; |
| 1211 | DWORD pi_allocated = 0; |
| 1212 | DWORD pi_needed; |
| 1213 | DWORD pi_index; |
| 1214 | DWORD pi_returned; |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 1215 | DWORD res; |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 1216 | DWORD outindex = 0; |
Detlef Riekenberg | 4cd9d53 | 2007-03-29 17:38:16 +0200 | [diff] [blame] | 1217 | DWORD needed; |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 1218 | DWORD numentries; |
| 1219 | DWORD entrysize; |
| 1220 | |
| 1221 | |
| 1222 | TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned); |
| 1223 | entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W); |
| 1224 | |
| 1225 | numentries = *lpreturned; /* this is 0, when we scan the registry */ |
| 1226 | needed = entrysize * numentries; |
| 1227 | ptr = (LPWSTR) &pPorts[needed]; |
| 1228 | |
| 1229 | numentries = 0; |
| 1230 | needed = 0; |
| 1231 | |
| 1232 | LIST_FOR_EACH_ENTRY(pm, &monitor_handles, monitor_t, entry) |
| 1233 | { |
| 1234 | if ((pm->monitor) && (pm->monitor->pfnEnumPorts)) { |
Detlef Riekenberg | 4cd9d53 | 2007-03-29 17:38:16 +0200 | [diff] [blame] | 1235 | pi_needed = 0; |
| 1236 | pi_returned = 0; |
| 1237 | res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); |
| 1238 | if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { |
| 1239 | /* Do not use HeapReAlloc (we do not need the old data in the buffer) */ |
| 1240 | HeapFree(GetProcessHeap(), 0, pi_buffer); |
| 1241 | pi_buffer = HeapAlloc(GetProcessHeap(), 0, pi_needed); |
| 1242 | pi_allocated = (pi_buffer) ? pi_needed : 0; |
| 1243 | res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 1244 | } |
Detlef Riekenberg | 4cd9d53 | 2007-03-29 17:38:16 +0200 | [diff] [blame] | 1245 | TRACE( "(%s) got %d with %d (need %d byte for %d entries)\n", |
| 1246 | debugstr_w(pm->name), res, GetLastError(), pi_needed, pi_returned); |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 1247 | |
Detlef Riekenberg | 4cd9d53 | 2007-03-29 17:38:16 +0200 | [diff] [blame] | 1248 | numentries += pi_returned; |
| 1249 | needed += pi_needed; |
| 1250 | |
| 1251 | /* fill the output-buffer (pPorts), if we have one */ |
| 1252 | if (pPorts && (cbBuf >= needed ) && pi_buffer) { |
| 1253 | pi_index = 0; |
| 1254 | while (pi_returned > pi_index) { |
| 1255 | cache = (LPPORT_INFO_2W) &pi_buffer[pi_index * entrysize]; |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 1256 | out = (LPPORT_INFO_2W) &pPorts[outindex * entrysize]; |
| 1257 | out->pPortName = ptr; |
| 1258 | lstrcpyW(ptr, cache->pPortName); |
| 1259 | ptr += (lstrlenW(ptr)+1); |
| 1260 | if (level > 1) { |
| 1261 | out->pMonitorName = ptr; |
| 1262 | lstrcpyW(ptr, cache->pMonitorName); |
| 1263 | ptr += (lstrlenW(ptr)+1); |
| 1264 | |
| 1265 | out->pDescription = ptr; |
| 1266 | lstrcpyW(ptr, cache->pDescription); |
| 1267 | ptr += (lstrlenW(ptr)+1); |
| 1268 | out->fPortType = cache->fPortType; |
| 1269 | out->Reserved = cache->Reserved; |
| 1270 | } |
Detlef Riekenberg | 4cd9d53 | 2007-03-29 17:38:16 +0200 | [diff] [blame] | 1271 | pi_index++; |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 1272 | outindex++; |
| 1273 | } |
| 1274 | } |
| 1275 | } |
| 1276 | } |
Detlef Riekenberg | 4cd9d53 | 2007-03-29 17:38:16 +0200 | [diff] [blame] | 1277 | /* the temporary portinfo-buffer is no longer needed */ |
| 1278 | HeapFree(GetProcessHeap(), 0, pi_buffer); |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 1279 | |
| 1280 | *lpreturned = numentries; |
| 1281 | TRACE("need %d byte for %d entries\n", needed, numentries); |
| 1282 | return needed; |
| 1283 | } |
| 1284 | |
| 1285 | /****************************************************************** |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 1286 | * get_servername_from_name (internal) |
| 1287 | * |
| 1288 | * for an external server, a copy of the serverpart from the full name is returned |
| 1289 | * |
| 1290 | */ |
| 1291 | static LPWSTR get_servername_from_name(LPCWSTR name) |
| 1292 | { |
| 1293 | LPWSTR server; |
| 1294 | LPWSTR ptr; |
| 1295 | WCHAR buffer[MAX_PATH]; |
| 1296 | DWORD len; |
| 1297 | |
| 1298 | if (name == NULL) return NULL; |
| 1299 | if ((name[0] != '\\') || (name[1] != '\\')) return NULL; |
| 1300 | |
| 1301 | server = strdupW(&name[2]); /* skip over both backslash */ |
| 1302 | if (server == NULL) return NULL; |
| 1303 | |
| 1304 | /* strip '\' and the printername */ |
| 1305 | ptr = strchrW(server, '\\'); |
| 1306 | if (ptr) ptr[0] = '\0'; |
| 1307 | |
| 1308 | TRACE("found %s\n", debugstr_w(server)); |
| 1309 | |
| 1310 | len = sizeof(buffer)/sizeof(buffer[0]); |
| 1311 | if (GetComputerNameW(buffer, &len)) { |
| 1312 | if (lstrcmpW(buffer, server) == 0) { |
| 1313 | /* The requested Servername is our computername */ |
| 1314 | HeapFree(GetProcessHeap(), 0, server); |
| 1315 | return NULL; |
| 1316 | } |
| 1317 | } |
| 1318 | return server; |
| 1319 | } |
| 1320 | |
| 1321 | /****************************************************************** |
| 1322 | * get_basename_from_name (internal) |
| 1323 | * |
| 1324 | * skip over the serverpart from the full name |
| 1325 | * |
| 1326 | */ |
| 1327 | static LPCWSTR get_basename_from_name(LPCWSTR name) |
| 1328 | { |
| 1329 | if (name == NULL) return NULL; |
| 1330 | if ((name[0] == '\\') && (name[1] == '\\')) { |
| 1331 | /* skip over the servername and search for the following '\' */ |
| 1332 | name = strchrW(&name[2], '\\'); |
| 1333 | if ((name) && (name[1])) { |
Francois Gouget | b0bde6b | 2007-01-18 11:35:50 +0100 | [diff] [blame] | 1334 | /* found a separator ('\') followed by a name: |
| 1335 | skip over the separator and return the rest */ |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 1336 | name++; |
| 1337 | } |
| 1338 | else |
| 1339 | { |
| 1340 | /* no basename present (we found only a servername) */ |
| 1341 | return NULL; |
| 1342 | } |
| 1343 | } |
| 1344 | return name; |
| 1345 | } |
| 1346 | |
| 1347 | /****************************************************************** |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1348 | * get_opened_printer_entry |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 1349 | * Get the first place empty in the opened printer table |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 1350 | * |
| 1351 | * ToDo: |
| 1352 | * - pDefault is ignored |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 1353 | */ |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 1354 | static HANDLE get_opened_printer_entry(LPCWSTR name, LPPRINTER_DEFAULTSW pDefault) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 1355 | { |
Kevin Koltzau | 7d8e377 | 2005-09-29 13:34:34 +0000 | [diff] [blame] | 1356 | UINT_PTR handle = nb_printer_handles, i; |
Robert Lunnon | c22716f | 2005-10-24 15:03:02 +0000 | [diff] [blame] | 1357 | jobqueue_t *queue = NULL; |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 1358 | opened_printer_t *printer = NULL; |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 1359 | LPWSTR servername; |
| 1360 | LPCWSTR printername; |
| 1361 | HKEY hkeyPrinters; |
| 1362 | HKEY hkeyPrinter; |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 1363 | DWORD len; |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 1364 | |
| 1365 | servername = get_servername_from_name(name); |
| 1366 | if (servername) { |
| 1367 | FIXME("server %s not supported\n", debugstr_w(servername)); |
| 1368 | HeapFree(GetProcessHeap(), 0, servername); |
| 1369 | SetLastError(ERROR_INVALID_PRINTER_NAME); |
| 1370 | return NULL; |
| 1371 | } |
| 1372 | |
| 1373 | printername = get_basename_from_name(name); |
| 1374 | if (name != printername) TRACE("converted %s to %s\n", debugstr_w(name), debugstr_w(printername)); |
| 1375 | |
| 1376 | /* an empty printername is invalid */ |
| 1377 | if (printername && (!printername[0])) { |
| 1378 | SetLastError(ERROR_INVALID_PARAMETER); |
| 1379 | return NULL; |
| 1380 | } |
Thuy Nguyen | 6374cd2 | 1999-08-15 16:34:22 +0000 | [diff] [blame] | 1381 | |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1382 | EnterCriticalSection(&printer_handles_cs); |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 1383 | |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 1384 | for (i = 0; i < nb_printer_handles; i++) |
| 1385 | { |
| 1386 | if (!printer_handles[i]) |
| 1387 | { |
| 1388 | if(handle == nb_printer_handles) |
| 1389 | handle = i; |
| 1390 | } |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 1391 | else |
| 1392 | { |
| 1393 | if(!queue && (name) && !lstrcmpW(name, printer_handles[i]->name)) |
| 1394 | queue = printer_handles[i]->queue; |
| 1395 | } |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 1396 | } |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1397 | |
| 1398 | if (handle >= nb_printer_handles) |
Thuy Nguyen | 6374cd2 | 1999-08-15 16:34:22 +0000 | [diff] [blame] | 1399 | { |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1400 | opened_printer_t **new_array; |
| 1401 | if (printer_handles) |
| 1402 | new_array = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, printer_handles, |
| 1403 | (nb_printer_handles + 16) * sizeof(*new_array) ); |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 1404 | else |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1405 | new_array = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, |
| 1406 | (nb_printer_handles + 16) * sizeof(*new_array) ); |
Oleg Prokhorov | cf8b84c | 2003-10-15 21:01:05 +0000 | [diff] [blame] | 1407 | |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1408 | if (!new_array) |
| 1409 | { |
| 1410 | handle = 0; |
| 1411 | goto end; |
| 1412 | } |
| 1413 | printer_handles = new_array; |
| 1414 | nb_printer_handles += 16; |
Thuy Nguyen | 6374cd2 | 1999-08-15 16:34:22 +0000 | [diff] [blame] | 1415 | } |
| 1416 | |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 1417 | if (!(printer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*printer)))) |
Thuy Nguyen | 6374cd2 | 1999-08-15 16:34:22 +0000 | [diff] [blame] | 1418 | { |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1419 | handle = 0; |
| 1420 | goto end; |
Thuy Nguyen | 6374cd2 | 1999-08-15 16:34:22 +0000 | [diff] [blame] | 1421 | } |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1422 | |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 1423 | |
| 1424 | /* clone the base name. This is NULL for the printserver */ |
| 1425 | printer->printername = strdupW(printername); |
| 1426 | |
| 1427 | /* clone the full name */ |
| 1428 | printer->name = strdupW(name); |
| 1429 | if (name && (!printer->name)) { |
| 1430 | handle = 0; |
| 1431 | goto end; |
| 1432 | } |
| 1433 | |
| 1434 | if (printername) { |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 1435 | len = sizeof(XcvMonitorW)/sizeof(WCHAR) - 1; |
| 1436 | if (strncmpW(printername, XcvMonitorW, len) == 0) { |
| 1437 | /* OpenPrinter(",XcvMonitor " detected */ |
| 1438 | TRACE(",XcvMonitor: %s\n", debugstr_w(&printername[len])); |
| 1439 | printer->pm = monitor_load(&printername[len], NULL); |
| 1440 | if (printer->pm == NULL) { |
Detlef Riekenberg | fc78034 | 2007-04-30 10:37:58 +0200 | [diff] [blame] | 1441 | SetLastError(ERROR_UNKNOWN_PORT); |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 1442 | handle = 0; |
| 1443 | goto end; |
| 1444 | } |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 1445 | } |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 1446 | else |
| 1447 | { |
| 1448 | len = sizeof(XcvPortW)/sizeof(WCHAR) - 1; |
| 1449 | if (strncmpW( printername, XcvPortW, len) == 0) { |
| 1450 | /* OpenPrinter(",XcvPort " detected */ |
| 1451 | TRACE(",XcvPort: %s\n", debugstr_w(&printername[len])); |
| 1452 | printer->pm = monitor_load_by_port(&printername[len]); |
| 1453 | if (printer->pm == NULL) { |
Detlef Riekenberg | fc78034 | 2007-04-30 10:37:58 +0200 | [diff] [blame] | 1454 | SetLastError(ERROR_UNKNOWN_PORT); |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 1455 | handle = 0; |
| 1456 | goto end; |
| 1457 | } |
| 1458 | } |
| 1459 | } |
| 1460 | |
| 1461 | if (printer->pm) { |
Detlef Riekenberg | 72b126b | 2007-01-05 01:09:46 +0100 | [diff] [blame] | 1462 | if ((printer->pm->monitor) && (printer->pm->monitor->pfnXcvOpenPort)) { |
Detlef Riekenberg | 6b7c482 | 2007-04-30 10:41:02 +0200 | [diff] [blame] | 1463 | printer->pm->monitor->pfnXcvOpenPort(&printername[len], |
| 1464 | pDefault ? pDefault->DesiredAccess : 0, |
| 1465 | &printer->hXcv); |
Detlef Riekenberg | 72b126b | 2007-01-05 01:09:46 +0100 | [diff] [blame] | 1466 | } |
| 1467 | if (printer->hXcv == NULL) { |
| 1468 | SetLastError(ERROR_INVALID_PARAMETER); |
| 1469 | handle = 0; |
| 1470 | goto end; |
| 1471 | } |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 1472 | } |
| 1473 | else |
| 1474 | { |
| 1475 | /* Does the Printer exist? */ |
| 1476 | if (RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) != ERROR_SUCCESS) { |
| 1477 | ERR("Can't create Printers key\n"); |
| 1478 | handle = 0; |
| 1479 | goto end; |
| 1480 | } |
| 1481 | if (RegOpenKeyW(hkeyPrinters, printername, &hkeyPrinter) != ERROR_SUCCESS) { |
Francois Gouget | 42c4114 | 2007-01-18 11:37:51 +0100 | [diff] [blame] | 1482 | WARN("Printer not found in Registry: %s\n", debugstr_w(printername)); |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 1483 | RegCloseKey(hkeyPrinters); |
| 1484 | SetLastError(ERROR_INVALID_PRINTER_NAME); |
| 1485 | handle = 0; |
| 1486 | goto end; |
| 1487 | } |
| 1488 | RegCloseKey(hkeyPrinter); |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 1489 | RegCloseKey(hkeyPrinters); |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 1490 | } |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 1491 | } |
| 1492 | else |
| 1493 | { |
| 1494 | TRACE("using the local printserver\n"); |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 1495 | } |
| 1496 | |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 1497 | if(queue) |
| 1498 | printer->queue = queue; |
| 1499 | else |
| 1500 | { |
| 1501 | printer->queue = HeapAlloc(GetProcessHeap(), 0, sizeof(*queue)); |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 1502 | if (!printer->queue) { |
| 1503 | handle = 0; |
| 1504 | goto end; |
| 1505 | } |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 1506 | list_init(&printer->queue->jobs); |
| 1507 | printer->queue->ref = 0; |
| 1508 | } |
| 1509 | InterlockedIncrement(&printer->queue->ref); |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1510 | |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 1511 | printer_handles[handle] = printer; |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1512 | handle++; |
| 1513 | end: |
| 1514 | LeaveCriticalSection(&printer_handles_cs); |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 1515 | if (!handle && printer) { |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 1516 | /* Something failed: Free all resources */ |
Detlef Riekenberg | 72b126b | 2007-01-05 01:09:46 +0100 | [diff] [blame] | 1517 | if (printer->hXcv) printer->pm->monitor->pfnXcvClosePort(printer->hXcv); |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 1518 | monitor_unload(printer->pm); |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 1519 | HeapFree(GetProcessHeap(), 0, printer->printername); |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 1520 | HeapFree(GetProcessHeap(), 0, printer->name); |
| 1521 | if (!queue) HeapFree(GetProcessHeap(), 0, printer->queue); |
| 1522 | HeapFree(GetProcessHeap(), 0, printer); |
| 1523 | } |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1524 | |
| 1525 | return (HANDLE)handle; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 1526 | } |
| 1527 | |
| 1528 | /****************************************************************** |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1529 | * get_opened_printer |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 1530 | * Get the pointer to the opened printer referred by the handle |
| 1531 | */ |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1532 | static opened_printer_t *get_opened_printer(HANDLE hprn) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 1533 | { |
Kevin Koltzau | 7d8e377 | 2005-09-29 13:34:34 +0000 | [diff] [blame] | 1534 | UINT_PTR idx = (UINT_PTR)hprn; |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1535 | opened_printer_t *ret = NULL; |
| 1536 | |
| 1537 | EnterCriticalSection(&printer_handles_cs); |
| 1538 | |
Detlef Riekenberg | d244a55 | 2007-11-04 17:57:54 +0100 | [diff] [blame] | 1539 | if ((idx > 0) && (idx <= nb_printer_handles)) { |
| 1540 | ret = printer_handles[idx - 1]; |
| 1541 | } |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1542 | LeaveCriticalSection(&printer_handles_cs); |
| 1543 | return ret; |
| 1544 | } |
| 1545 | |
| 1546 | /****************************************************************** |
| 1547 | * get_opened_printer_name |
| 1548 | * Get the pointer to the opened printer name referred by the handle |
| 1549 | */ |
| 1550 | static LPCWSTR get_opened_printer_name(HANDLE hprn) |
| 1551 | { |
| 1552 | opened_printer_t *printer = get_opened_printer(hprn); |
| 1553 | if(!printer) return NULL; |
| 1554 | return printer->name; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 1555 | } |
| 1556 | |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 1557 | /****************************************************************** |
| 1558 | * WINSPOOL_GetOpenedPrinterRegKey |
| 1559 | * |
| 1560 | */ |
| 1561 | static DWORD WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter, HKEY *phkey) |
| 1562 | { |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1563 | LPCWSTR name = get_opened_printer_name(hPrinter); |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 1564 | DWORD ret; |
| 1565 | HKEY hkeyPrinters; |
| 1566 | |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 1567 | if(!name) return ERROR_INVALID_HANDLE; |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 1568 | |
Detlef Riekenberg | 358ce06 | 2006-05-21 14:35:29 +0200 | [diff] [blame] | 1569 | if((ret = RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters)) != |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 1570 | ERROR_SUCCESS) |
| 1571 | return ret; |
| 1572 | |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 1573 | if(RegOpenKeyW(hkeyPrinters, name, phkey) != ERROR_SUCCESS) |
| 1574 | { |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 1575 | ERR("Can't find opened printer %s in registry\n", |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 1576 | debugstr_w(name)); |
| 1577 | RegCloseKey(hkeyPrinters); |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 1578 | return ERROR_INVALID_PRINTER_NAME; /* ? */ |
| 1579 | } |
| 1580 | RegCloseKey(hkeyPrinters); |
| 1581 | return ERROR_SUCCESS; |
| 1582 | } |
| 1583 | |
Francois Gouget | 0c31ca3 | 2007-01-17 17:18:54 +0100 | [diff] [blame] | 1584 | void WINSPOOL_LoadSystemPrinters(void) |
| 1585 | { |
| 1586 | HKEY hkey, hkeyPrinters; |
| 1587 | HANDLE hprn; |
| 1588 | DWORD needed, num, i; |
| 1589 | WCHAR PrinterName[256]; |
| 1590 | BOOL done = FALSE; |
| 1591 | |
| 1592 | /* This ensures that all printer entries have a valid Name value. If causes |
| 1593 | problems later if they don't. If one is found to be missed we create one |
| 1594 | and set it equal to the name of the key */ |
| 1595 | if(RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) == ERROR_SUCCESS) { |
| 1596 | if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &num, NULL, NULL, |
| 1597 | NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { |
| 1598 | for(i = 0; i < num; i++) { |
Vitaly Lipatov | 914e78a | 2007-12-01 19:43:37 +0300 | [diff] [blame] | 1599 | if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)/sizeof(PrinterName[0])) == ERROR_SUCCESS) { |
Francois Gouget | 0c31ca3 | 2007-01-17 17:18:54 +0100 | [diff] [blame] | 1600 | if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkey) == ERROR_SUCCESS) { |
| 1601 | if(RegQueryValueExW(hkey, NameW, 0, 0, 0, &needed) == ERROR_FILE_NOT_FOUND) { |
| 1602 | set_reg_szW(hkey, NameW, PrinterName); |
| 1603 | } |
| 1604 | RegCloseKey(hkey); |
| 1605 | } |
| 1606 | } |
| 1607 | } |
| 1608 | } |
| 1609 | RegCloseKey(hkeyPrinters); |
| 1610 | } |
| 1611 | |
| 1612 | /* We want to avoid calling AddPrinter on printers as much as |
| 1613 | possible, because on cups printers this will (eventually) lead |
| 1614 | to a call to cupsGetPPD which takes forever, even with non-cups |
| 1615 | printers AddPrinter takes a while. So we'll tag all printers that |
| 1616 | were automatically added last time around, if they still exist |
| 1617 | we'll leave them be otherwise we'll delete them. */ |
| 1618 | EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 5, NULL, 0, &needed, &num); |
| 1619 | if(needed) { |
| 1620 | PRINTER_INFO_5A* pi = HeapAlloc(GetProcessHeap(), 0, needed); |
| 1621 | if(EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 5, (LPBYTE)pi, needed, &needed, &num)) { |
| 1622 | for(i = 0; i < num; i++) { |
| 1623 | if(pi[i].pPortName == NULL || !strncmp(pi[i].pPortName,"CUPS:", 5) || !strncmp(pi[i].pPortName, "LPR:", 4)) { |
| 1624 | if(OpenPrinterA(pi[i].pPrinterName, &hprn, NULL)) { |
| 1625 | if(WINSPOOL_GetOpenedPrinterRegKey(hprn, &hkey) == ERROR_SUCCESS) { |
| 1626 | DWORD dw = 1; |
| 1627 | RegSetValueExW(hkey, May_Delete_Value, 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)); |
| 1628 | RegCloseKey(hkey); |
| 1629 | } |
| 1630 | ClosePrinter(hprn); |
| 1631 | } |
| 1632 | } |
| 1633 | } |
| 1634 | } |
| 1635 | HeapFree(GetProcessHeap(), 0, pi); |
| 1636 | } |
| 1637 | |
| 1638 | |
Alexandre Julliard | 702d355 | 2007-07-02 17:30:44 +0200 | [diff] [blame] | 1639 | #ifdef SONAME_LIBCUPS |
Francois Gouget | 0c31ca3 | 2007-01-17 17:18:54 +0100 | [diff] [blame] | 1640 | done = CUPS_LoadPrinters(); |
| 1641 | #endif |
| 1642 | |
Huw Davies | 37b671c | 2007-01-30 21:27:11 +0000 | [diff] [blame] | 1643 | if(!done) /* If we have any CUPS based printers, skip looking for printcap printers */ |
| 1644 | PRINTCAP_LoadPrinters(); |
Francois Gouget | 0c31ca3 | 2007-01-17 17:18:54 +0100 | [diff] [blame] | 1645 | |
Francois Gouget | b2bc712 | 2007-09-27 18:57:51 +0200 | [diff] [blame] | 1646 | /* Now enumerate the list again and delete any printers that are still tagged */ |
Francois Gouget | 0c31ca3 | 2007-01-17 17:18:54 +0100 | [diff] [blame] | 1647 | EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 5, NULL, 0, &needed, &num); |
| 1648 | if(needed) { |
| 1649 | PRINTER_INFO_5A* pi = HeapAlloc(GetProcessHeap(), 0, needed); |
| 1650 | if(EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 5, (LPBYTE)pi, needed, &needed, &num)) { |
| 1651 | for(i = 0; i < num; i++) { |
| 1652 | if(pi[i].pPortName == NULL || !strncmp(pi[i].pPortName,"CUPS:", 5) || !strncmp(pi[i].pPortName, "LPR:", 4)) { |
| 1653 | if(OpenPrinterA(pi[i].pPrinterName, &hprn, NULL)) { |
| 1654 | BOOL delete_driver = FALSE; |
| 1655 | if(WINSPOOL_GetOpenedPrinterRegKey(hprn, &hkey) == ERROR_SUCCESS) { |
| 1656 | DWORD dw, type, size = sizeof(dw); |
| 1657 | if(RegQueryValueExW(hkey, May_Delete_Value, NULL, &type, (LPBYTE)&dw, &size) == ERROR_SUCCESS) { |
| 1658 | TRACE("Deleting old printer %s\n", pi[i].pPrinterName); |
| 1659 | DeletePrinter(hprn); |
| 1660 | delete_driver = TRUE; |
| 1661 | } |
| 1662 | RegCloseKey(hkey); |
| 1663 | } |
| 1664 | ClosePrinter(hprn); |
| 1665 | if(delete_driver) |
| 1666 | DeletePrinterDriverExA(NULL, NULL, pi[i].pPrinterName, 0, 0); |
| 1667 | } |
| 1668 | } |
| 1669 | } |
| 1670 | } |
| 1671 | HeapFree(GetProcessHeap(), 0, pi); |
| 1672 | } |
| 1673 | |
| 1674 | return; |
| 1675 | |
| 1676 | } |
| 1677 | |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 1678 | /****************************************************************** |
| 1679 | * get_job |
| 1680 | * |
| 1681 | * Get the pointer to the specified job. |
| 1682 | * Should hold the printer_handles_cs before calling. |
| 1683 | */ |
| 1684 | static job_t *get_job(HANDLE hprn, DWORD JobId) |
| 1685 | { |
| 1686 | opened_printer_t *printer = get_opened_printer(hprn); |
| 1687 | job_t *job; |
| 1688 | |
| 1689 | if(!printer) return NULL; |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 1690 | LIST_FOR_EACH_ENTRY(job, &printer->queue->jobs, job_t, entry) |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 1691 | { |
| 1692 | if(job->job_id == JobId) |
| 1693 | return job; |
| 1694 | } |
| 1695 | return NULL; |
| 1696 | } |
| 1697 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1698 | /*********************************************************** |
| 1699 | * DEVMODEcpyAtoW |
| 1700 | */ |
| 1701 | static LPDEVMODEW DEVMODEcpyAtoW(DEVMODEW *dmW, const DEVMODEA *dmA) |
| 1702 | { |
| 1703 | BOOL Formname; |
Eric Pouech | 0a25896 | 2004-11-30 21:38:57 +0000 | [diff] [blame] | 1704 | ptrdiff_t off_formname = (const char *)dmA->dmFormName - (const char *)dmA; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1705 | DWORD size; |
| 1706 | |
| 1707 | Formname = (dmA->dmSize > off_formname); |
| 1708 | size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0); |
Mike McCormack | 516a577 | 2005-08-19 10:04:03 +0000 | [diff] [blame] | 1709 | MultiByteToWideChar(CP_ACP, 0, (LPCSTR)dmA->dmDeviceName, -1, |
| 1710 | dmW->dmDeviceName, CCHDEVICENAME); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1711 | if(!Formname) { |
| 1712 | memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion, |
| 1713 | dmA->dmSize - CCHDEVICENAME); |
| 1714 | } else { |
| 1715 | memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion, |
| 1716 | off_formname - CCHDEVICENAME); |
Mike McCormack | 516a577 | 2005-08-19 10:04:03 +0000 | [diff] [blame] | 1717 | MultiByteToWideChar(CP_ACP, 0, (LPCSTR)dmA->dmFormName, -1, |
| 1718 | dmW->dmFormName, CCHFORMNAME); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1719 | memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA->dmSize - |
| 1720 | (off_formname + CCHFORMNAME)); |
| 1721 | } |
| 1722 | dmW->dmSize = size; |
Eric Pouech | 0a25896 | 2004-11-30 21:38:57 +0000 | [diff] [blame] | 1723 | memcpy((char *)dmW + dmW->dmSize, (const char *)dmA + dmA->dmSize, |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1724 | dmA->dmDriverExtra); |
| 1725 | return dmW; |
| 1726 | } |
| 1727 | |
| 1728 | /*********************************************************** |
Detlef Riekenberg | 741fa21 | 2008-03-09 00:38:49 +0100 | [diff] [blame] | 1729 | * DEVMODEdupWtoA |
| 1730 | * Creates an ansi copy of supplied devmode |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1731 | */ |
Detlef Riekenberg | 741fa21 | 2008-03-09 00:38:49 +0100 | [diff] [blame] | 1732 | static LPDEVMODEA DEVMODEdupWtoA(const DEVMODEW *dmW) |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1733 | { |
| 1734 | LPDEVMODEA dmA; |
| 1735 | DWORD size; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1736 | |
Detlef Riekenberg | 741fa21 | 2008-03-09 00:38:49 +0100 | [diff] [blame] | 1737 | if (!dmW) return NULL; |
| 1738 | size = dmW->dmSize - CCHDEVICENAME - |
| 1739 | ((dmW->dmSize > FIELD_OFFSET(DEVMODEW, dmFormName)) ? CCHFORMNAME : 0); |
| 1740 | |
| 1741 | dmA = HeapAlloc(GetProcessHeap(), 0, size + dmW->dmDriverExtra); |
| 1742 | if (!dmA) return NULL; |
| 1743 | |
Mike McCormack | 516a577 | 2005-08-19 10:04:03 +0000 | [diff] [blame] | 1744 | WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, |
| 1745 | (LPSTR)dmA->dmDeviceName, CCHDEVICENAME, NULL, NULL); |
Detlef Riekenberg | 741fa21 | 2008-03-09 00:38:49 +0100 | [diff] [blame] | 1746 | |
| 1747 | if (FIELD_OFFSET(DEVMODEW, dmFormName) >= dmW->dmSize) { |
| 1748 | memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion, |
| 1749 | dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmSpecVersion)); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1750 | } |
Detlef Riekenberg | 741fa21 | 2008-03-09 00:38:49 +0100 | [diff] [blame] | 1751 | else |
| 1752 | { |
| 1753 | memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion, |
| 1754 | FIELD_OFFSET(DEVMODEW, dmFormName) - FIELD_OFFSET(DEVMODEW, dmSpecVersion)); |
| 1755 | WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, |
| 1756 | (LPSTR)dmA->dmFormName, CCHFORMNAME, NULL, NULL); |
| 1757 | |
| 1758 | memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels)); |
| 1759 | } |
| 1760 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1761 | dmA->dmSize = size; |
Detlef Riekenberg | 741fa21 | 2008-03-09 00:38:49 +0100 | [diff] [blame] | 1762 | memcpy((char *)dmA + dmA->dmSize, (const char *)dmW + dmW->dmSize, dmW->dmDriverExtra); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1763 | return dmA; |
| 1764 | } |
| 1765 | |
Detlef Riekenberg | 9e35ee8 | 2008-03-22 19:28:50 +0100 | [diff] [blame] | 1766 | /****************************************************************** |
| 1767 | * convert_printerinfo_W_to_A [internal] |
| 1768 | * |
| 1769 | */ |
| 1770 | static void convert_printerinfo_W_to_A(LPBYTE out, LPBYTE pPrintersW, |
| 1771 | DWORD level, DWORD outlen, DWORD numentries) |
| 1772 | { |
| 1773 | DWORD id = 0; |
| 1774 | LPSTR ptr; |
| 1775 | INT len; |
| 1776 | |
| 1777 | TRACE("(%p, %p, %d, %u, %u)\n", out, pPrintersW, level, outlen, numentries); |
| 1778 | |
| 1779 | len = pi_sizeof[level] * numentries; |
| 1780 | ptr = (LPSTR) out + len; |
| 1781 | outlen -= len; |
| 1782 | |
| 1783 | /* copy the numbers of all PRINTER_INFO_* first */ |
| 1784 | memcpy(out, pPrintersW, len); |
| 1785 | |
| 1786 | while (id < numentries) { |
| 1787 | switch (level) { |
| 1788 | case 1: |
| 1789 | { |
| 1790 | PRINTER_INFO_1W * piW = (PRINTER_INFO_1W *) pPrintersW; |
| 1791 | PRINTER_INFO_1A * piA = (PRINTER_INFO_1A *) out; |
| 1792 | |
| 1793 | TRACE("(%u) #%u: %s\n", level, id, debugstr_w(piW->pName)); |
| 1794 | if (piW->pDescription) { |
| 1795 | piA->pDescription = ptr; |
| 1796 | len = WideCharToMultiByte(CP_ACP, 0, piW->pDescription, -1, |
| 1797 | ptr, outlen, NULL, NULL); |
| 1798 | ptr += len; |
| 1799 | outlen -= len; |
| 1800 | } |
| 1801 | if (piW->pName) { |
| 1802 | piA->pName = ptr; |
| 1803 | len = WideCharToMultiByte(CP_ACP, 0, piW->pName, -1, |
| 1804 | ptr, outlen, NULL, NULL); |
| 1805 | ptr += len; |
| 1806 | outlen -= len; |
| 1807 | } |
| 1808 | if (piW->pComment) { |
| 1809 | piA->pComment = ptr; |
| 1810 | len = WideCharToMultiByte(CP_ACP, 0, piW->pComment, -1, |
| 1811 | ptr, outlen, NULL, NULL); |
| 1812 | ptr += len; |
| 1813 | outlen -= len; |
| 1814 | } |
| 1815 | break; |
| 1816 | } |
| 1817 | |
| 1818 | case 2: |
| 1819 | { |
| 1820 | PRINTER_INFO_2W * piW = (PRINTER_INFO_2W *) pPrintersW; |
| 1821 | PRINTER_INFO_2A * piA = (PRINTER_INFO_2A *) out; |
| 1822 | LPDEVMODEA dmA; |
| 1823 | |
| 1824 | TRACE("(%u) #%u: %s\n", level, id, debugstr_w(piW->pPrinterName)); |
| 1825 | if (piW->pServerName) { |
| 1826 | piA->pServerName = ptr; |
| 1827 | len = WideCharToMultiByte(CP_ACP, 0, piW->pServerName, -1, |
| 1828 | ptr, outlen, NULL, NULL); |
| 1829 | ptr += len; |
| 1830 | outlen -= len; |
| 1831 | } |
| 1832 | if (piW->pPrinterName) { |
| 1833 | piA->pPrinterName = ptr; |
| 1834 | len = WideCharToMultiByte(CP_ACP, 0, piW->pPrinterName, -1, |
| 1835 | ptr, outlen, NULL, NULL); |
| 1836 | ptr += len; |
| 1837 | outlen -= len; |
| 1838 | } |
| 1839 | if (piW->pShareName) { |
| 1840 | piA->pShareName = ptr; |
| 1841 | len = WideCharToMultiByte(CP_ACP, 0, piW->pShareName, -1, |
| 1842 | ptr, outlen, NULL, NULL); |
| 1843 | ptr += len; |
| 1844 | outlen -= len; |
| 1845 | } |
| 1846 | if (piW->pPortName) { |
| 1847 | piA->pPortName = ptr; |
| 1848 | len = WideCharToMultiByte(CP_ACP, 0, piW->pPortName, -1, |
| 1849 | ptr, outlen, NULL, NULL); |
| 1850 | ptr += len; |
| 1851 | outlen -= len; |
| 1852 | } |
| 1853 | if (piW->pDriverName) { |
| 1854 | piA->pDriverName = ptr; |
| 1855 | len = WideCharToMultiByte(CP_ACP, 0, piW->pDriverName, -1, |
| 1856 | ptr, outlen, NULL, NULL); |
| 1857 | ptr += len; |
| 1858 | outlen -= len; |
| 1859 | } |
| 1860 | if (piW->pComment) { |
| 1861 | piA->pComment = ptr; |
| 1862 | len = WideCharToMultiByte(CP_ACP, 0, piW->pComment, -1, |
| 1863 | ptr, outlen, NULL, NULL); |
| 1864 | ptr += len; |
| 1865 | outlen -= len; |
| 1866 | } |
| 1867 | if (piW->pLocation) { |
| 1868 | piA->pLocation = ptr; |
| 1869 | len = WideCharToMultiByte(CP_ACP, 0, piW->pLocation, -1, |
| 1870 | ptr, outlen, NULL, NULL); |
| 1871 | ptr += len; |
| 1872 | outlen -= len; |
| 1873 | } |
| 1874 | |
| 1875 | dmA = DEVMODEdupWtoA(piW->pDevMode); |
| 1876 | if (dmA) { |
| 1877 | /* align DEVMODEA to a DWORD boundary */ |
| 1878 | len = (4 - ( (DWORD_PTR) ptr & 3)) & 3; |
| 1879 | ptr += len; |
| 1880 | outlen -= len; |
| 1881 | |
| 1882 | piA->pDevMode = (LPDEVMODEA) ptr; |
| 1883 | len = dmA->dmSize + dmA->dmDriverExtra; |
| 1884 | memcpy(ptr, dmA, len); |
| 1885 | HeapFree(GetProcessHeap(), 0, dmA); |
| 1886 | |
| 1887 | ptr += len; |
| 1888 | outlen -= len; |
| 1889 | } |
| 1890 | |
| 1891 | if (piW->pSepFile) { |
| 1892 | piA->pSepFile = ptr; |
| 1893 | len = WideCharToMultiByte(CP_ACP, 0, piW->pSepFile, -1, |
| 1894 | ptr, outlen, NULL, NULL); |
| 1895 | ptr += len; |
| 1896 | outlen -= len; |
| 1897 | } |
| 1898 | if (piW->pPrintProcessor) { |
| 1899 | piA->pPrintProcessor = ptr; |
| 1900 | len = WideCharToMultiByte(CP_ACP, 0, piW->pPrintProcessor, -1, |
| 1901 | ptr, outlen, NULL, NULL); |
| 1902 | ptr += len; |
| 1903 | outlen -= len; |
| 1904 | } |
| 1905 | if (piW->pDatatype) { |
| 1906 | piA->pDatatype = ptr; |
| 1907 | len = WideCharToMultiByte(CP_ACP, 0, piW->pDatatype, -1, |
| 1908 | ptr, outlen, NULL, NULL); |
| 1909 | ptr += len; |
| 1910 | outlen -= len; |
| 1911 | } |
| 1912 | if (piW->pParameters) { |
| 1913 | piA->pParameters = ptr; |
| 1914 | len = WideCharToMultiByte(CP_ACP, 0, piW->pParameters, -1, |
| 1915 | ptr, outlen, NULL, NULL); |
| 1916 | ptr += len; |
| 1917 | outlen -= len; |
| 1918 | } |
| 1919 | if (piW->pSecurityDescriptor) { |
| 1920 | piA->pSecurityDescriptor = NULL; |
| 1921 | FIXME("pSecurityDescriptor ignored: %s\n", debugstr_w(piW->pPrinterName)); |
| 1922 | } |
| 1923 | break; |
| 1924 | } |
| 1925 | |
| 1926 | case 4: |
| 1927 | { |
| 1928 | PRINTER_INFO_4W * piW = (PRINTER_INFO_4W *) pPrintersW; |
| 1929 | PRINTER_INFO_4A * piA = (PRINTER_INFO_4A *) out; |
| 1930 | |
| 1931 | TRACE("(%u) #%u: %s\n", level, id, debugstr_w(piW->pPrinterName)); |
| 1932 | |
| 1933 | if (piW->pPrinterName) { |
| 1934 | piA->pPrinterName = ptr; |
| 1935 | len = WideCharToMultiByte(CP_ACP, 0, piW->pPrinterName, -1, |
| 1936 | ptr, outlen, NULL, NULL); |
| 1937 | ptr += len; |
| 1938 | outlen -= len; |
| 1939 | } |
| 1940 | if (piW->pServerName) { |
| 1941 | piA->pServerName = ptr; |
| 1942 | len = WideCharToMultiByte(CP_ACP, 0, piW->pServerName, -1, |
| 1943 | ptr, outlen, NULL, NULL); |
| 1944 | ptr += len; |
| 1945 | outlen -= len; |
| 1946 | } |
| 1947 | break; |
| 1948 | } |
| 1949 | |
| 1950 | case 5: |
| 1951 | { |
| 1952 | PRINTER_INFO_5W * piW = (PRINTER_INFO_5W *) pPrintersW; |
| 1953 | PRINTER_INFO_5A * piA = (PRINTER_INFO_5A *) out; |
| 1954 | |
| 1955 | TRACE("(%u) #%u: %s\n", level, id, debugstr_w(piW->pPrinterName)); |
| 1956 | |
| 1957 | if (piW->pPrinterName) { |
| 1958 | piA->pPrinterName = ptr; |
| 1959 | len = WideCharToMultiByte(CP_ACP, 0, piW->pPrinterName, -1, |
| 1960 | ptr, outlen, NULL, NULL); |
| 1961 | ptr += len; |
| 1962 | outlen -= len; |
| 1963 | } |
| 1964 | if (piW->pPortName) { |
| 1965 | piA->pPortName = ptr; |
| 1966 | len = WideCharToMultiByte(CP_ACP, 0, piW->pPortName, -1, |
| 1967 | ptr, outlen, NULL, NULL); |
| 1968 | ptr += len; |
| 1969 | outlen -= len; |
| 1970 | } |
| 1971 | break; |
| 1972 | } |
| 1973 | |
| 1974 | default: |
| 1975 | FIXME("for level %u\n", level); |
| 1976 | } |
| 1977 | pPrintersW += pi_sizeof[level]; |
| 1978 | out += pi_sizeof[level]; |
| 1979 | id++; |
| 1980 | } |
| 1981 | } |
| 1982 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1983 | /*********************************************************** |
| 1984 | * PRINTER_INFO_2AtoW |
| 1985 | * Creates a unicode copy of PRINTER_INFO_2A on heap |
| 1986 | */ |
| 1987 | static LPPRINTER_INFO_2W PRINTER_INFO_2AtoW(HANDLE heap, LPPRINTER_INFO_2A piA) |
| 1988 | { |
| 1989 | LPPRINTER_INFO_2W piW; |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 1990 | UNICODE_STRING usBuffer; |
| 1991 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 1992 | if(!piA) return NULL; |
| 1993 | piW = HeapAlloc(heap, 0, sizeof(*piW)); |
| 1994 | memcpy(piW, piA, sizeof(*piW)); /* copy everything first */ |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 1995 | |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 1996 | piW->pServerName = asciitounicode(&usBuffer,piA->pServerName); |
| 1997 | piW->pPrinterName = asciitounicode(&usBuffer,piA->pPrinterName); |
| 1998 | piW->pShareName = asciitounicode(&usBuffer,piA->pShareName); |
| 1999 | piW->pPortName = asciitounicode(&usBuffer,piA->pPortName); |
| 2000 | piW->pDriverName = asciitounicode(&usBuffer,piA->pDriverName); |
| 2001 | piW->pComment = asciitounicode(&usBuffer,piA->pComment); |
| 2002 | piW->pLocation = asciitounicode(&usBuffer,piA->pLocation); |
Alexandre Julliard | c2320db | 2003-08-12 23:46:34 +0000 | [diff] [blame] | 2003 | piW->pDevMode = piA->pDevMode ? GdiConvertToDevmodeW(piA->pDevMode) : NULL; |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 2004 | piW->pSepFile = asciitounicode(&usBuffer,piA->pSepFile); |
| 2005 | piW->pPrintProcessor = asciitounicode(&usBuffer,piA->pPrintProcessor); |
| 2006 | piW->pDatatype = asciitounicode(&usBuffer,piA->pDatatype); |
| 2007 | piW->pParameters = asciitounicode(&usBuffer,piA->pParameters); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2008 | return piW; |
| 2009 | } |
| 2010 | |
| 2011 | /*********************************************************** |
| 2012 | * FREE_PRINTER_INFO_2W |
| 2013 | * Free PRINTER_INFO_2W and all strings |
| 2014 | */ |
| 2015 | static void FREE_PRINTER_INFO_2W(HANDLE heap, LPPRINTER_INFO_2W piW) |
| 2016 | { |
| 2017 | if(!piW) return; |
| 2018 | |
| 2019 | HeapFree(heap,0,piW->pServerName); |
| 2020 | HeapFree(heap,0,piW->pPrinterName); |
| 2021 | HeapFree(heap,0,piW->pShareName); |
| 2022 | HeapFree(heap,0,piW->pPortName); |
| 2023 | HeapFree(heap,0,piW->pDriverName); |
| 2024 | HeapFree(heap,0,piW->pComment); |
| 2025 | HeapFree(heap,0,piW->pLocation); |
| 2026 | HeapFree(heap,0,piW->pDevMode); |
| 2027 | HeapFree(heap,0,piW->pSepFile); |
| 2028 | HeapFree(heap,0,piW->pPrintProcessor); |
| 2029 | HeapFree(heap,0,piW->pDatatype); |
| 2030 | HeapFree(heap,0,piW->pParameters); |
| 2031 | HeapFree(heap,0,piW); |
| 2032 | return; |
| 2033 | } |
| 2034 | |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2035 | /****************************************************************** |
Patrik Stridvall | 01d5e5b | 2001-07-02 19:59:40 +0000 | [diff] [blame] | 2036 | * DeviceCapabilities [WINSPOOL.@] |
| 2037 | * DeviceCapabilitiesA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2038 | * |
| 2039 | */ |
Andreas Mohr | 2caee71 | 2000-07-16 15:44:22 +0000 | [diff] [blame] | 2040 | INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD cap, |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2041 | LPSTR pOutput, LPDEVMODEA lpdm) |
| 2042 | { |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 2043 | INT ret; |
Alexandre Julliard | 49556bc | 2000-11-29 18:38:24 +0000 | [diff] [blame] | 2044 | |
| 2045 | if (!GDI_CallDeviceCapabilities16) |
| 2046 | { |
| 2047 | GDI_CallDeviceCapabilities16 = (void*)GetProcAddress( GetModuleHandleA("gdi32"), |
| 2048 | (LPCSTR)104 ); |
| 2049 | if (!GDI_CallDeviceCapabilities16) return -1; |
| 2050 | } |
Andreas Mohr | 2caee71 | 2000-07-16 15:44:22 +0000 | [diff] [blame] | 2051 | ret = GDI_CallDeviceCapabilities16(pDevice, pPort, cap, pOutput, lpdm); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2052 | |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 2053 | /* If DC_PAPERSIZE map POINT16s to POINTs */ |
| 2054 | if(ret != -1 && cap == DC_PAPERSIZE && pOutput) { |
| 2055 | POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) ); |
Alexandre Julliard | f6168db | 2000-12-13 20:03:53 +0000 | [diff] [blame] | 2056 | POINT *pt = (POINT *)pOutput; |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 2057 | INT i; |
| 2058 | memcpy(tmp, pOutput, ret * sizeof(POINT16)); |
Alexandre Julliard | f6168db | 2000-12-13 20:03:53 +0000 | [diff] [blame] | 2059 | for(i = 0; i < ret; i++, pt++) |
| 2060 | { |
| 2061 | pt->x = tmp[i].x; |
| 2062 | pt->y = tmp[i].y; |
| 2063 | } |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 2064 | HeapFree( GetProcessHeap(), 0, tmp ); |
| 2065 | } |
| 2066 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2067 | } |
| 2068 | |
| 2069 | |
| 2070 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2071 | * DeviceCapabilitiesW [WINSPOOL.@] |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2072 | * |
| 2073 | * Call DeviceCapabilitiesA since we later call 16bit stuff anyway |
| 2074 | * |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2075 | */ |
| 2076 | INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, |
| 2077 | WORD fwCapability, LPWSTR pOutput, |
| 2078 | const DEVMODEW *pDevMode) |
| 2079 | { |
Detlef Riekenberg | 741fa21 | 2008-03-09 00:38:49 +0100 | [diff] [blame] | 2080 | LPDEVMODEA dmA = DEVMODEdupWtoA(pDevMode); |
Alexandre Julliard | 2731998 | 2006-11-17 15:29:40 +0100 | [diff] [blame] | 2081 | LPSTR pDeviceA = strdupWtoA(pDevice); |
| 2082 | LPSTR pPortA = strdupWtoA(pPort); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2083 | INT ret; |
| 2084 | |
| 2085 | if(pOutput && (fwCapability == DC_BINNAMES || |
| 2086 | fwCapability == DC_FILEDEPENDENCIES || |
| 2087 | fwCapability == DC_PAPERNAMES)) { |
| 2088 | /* These need A -> W translation */ |
| 2089 | INT size = 0, i; |
| 2090 | LPSTR pOutputA; |
| 2091 | ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, NULL, |
| 2092 | dmA); |
| 2093 | if(ret == -1) |
| 2094 | return ret; |
| 2095 | switch(fwCapability) { |
| 2096 | case DC_BINNAMES: |
| 2097 | size = 24; |
| 2098 | break; |
| 2099 | case DC_PAPERNAMES: |
| 2100 | case DC_FILEDEPENDENCIES: |
| 2101 | size = 64; |
| 2102 | break; |
| 2103 | } |
| 2104 | pOutputA = HeapAlloc(GetProcessHeap(), 0, size * ret); |
| 2105 | ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, pOutputA, |
| 2106 | dmA); |
| 2107 | for(i = 0; i < ret; i++) |
| 2108 | MultiByteToWideChar(CP_ACP, 0, pOutputA + (i * size), -1, |
| 2109 | pOutput + (i * size), size); |
| 2110 | HeapFree(GetProcessHeap(), 0, pOutputA); |
| 2111 | } else { |
| 2112 | ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, |
| 2113 | (LPSTR)pOutput, dmA); |
| 2114 | } |
| 2115 | HeapFree(GetProcessHeap(),0,pPortA); |
| 2116 | HeapFree(GetProcessHeap(),0,pDeviceA); |
| 2117 | HeapFree(GetProcessHeap(),0,dmA); |
| 2118 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2119 | } |
| 2120 | |
| 2121 | /****************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2122 | * DocumentPropertiesA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2123 | * |
Dmitry Timoshkov | 3a910c7 | 2003-08-12 20:42:18 +0000 | [diff] [blame] | 2124 | * FIXME: implement DocumentPropertiesA via DocumentPropertiesW, not vice versa |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2125 | */ |
| 2126 | LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter, |
| 2127 | LPSTR pDeviceName, LPDEVMODEA pDevModeOutput, |
| 2128 | LPDEVMODEA pDevModeInput,DWORD fMode ) |
| 2129 | { |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2130 | LPSTR lpName = pDeviceName; |
Andrew Talbot | 8c56ffd | 2006-08-16 21:00:14 +0100 | [diff] [blame] | 2131 | static CHAR port[] = "LPT1:"; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2132 | LONG ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2133 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2134 | TRACE("(%p,%p,%s,%p,%p,%d)\n", |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2135 | hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode |
| 2136 | ); |
| 2137 | |
| 2138 | if(!pDeviceName) { |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 2139 | LPCWSTR lpNameW = get_opened_printer_name(hPrinter); |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 2140 | if(!lpNameW) { |
| 2141 | ERR("no name from hPrinter?\n"); |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 2142 | SetLastError(ERROR_INVALID_HANDLE); |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 2143 | return -1; |
| 2144 | } |
Alexandre Julliard | 2731998 | 2006-11-17 15:29:40 +0100 | [diff] [blame] | 2145 | lpName = strdupWtoA(lpNameW); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2146 | } |
| 2147 | |
Alexandre Julliard | 49556bc | 2000-11-29 18:38:24 +0000 | [diff] [blame] | 2148 | if (!GDI_CallExtDeviceMode16) |
| 2149 | { |
| 2150 | GDI_CallExtDeviceMode16 = (void*)GetProcAddress( GetModuleHandleA("gdi32"), |
| 2151 | (LPCSTR)102 ); |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 2152 | if (!GDI_CallExtDeviceMode16) { |
| 2153 | ERR("No CallExtDeviceMode16?\n"); |
| 2154 | return -1; |
| 2155 | } |
Alexandre Julliard | 49556bc | 2000-11-29 18:38:24 +0000 | [diff] [blame] | 2156 | } |
Andrew Talbot | 8c56ffd | 2006-08-16 21:00:14 +0100 | [diff] [blame] | 2157 | ret = GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, port, |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2158 | pDevModeInput, NULL, fMode); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2159 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2160 | if(!pDeviceName) |
| 2161 | HeapFree(GetProcessHeap(),0,lpName); |
| 2162 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2163 | } |
| 2164 | |
| 2165 | |
| 2166 | /***************************************************************************** |
Patrik Stridvall | 8b216b3 | 2001-06-19 18:20:47 +0000 | [diff] [blame] | 2167 | * DocumentPropertiesW (WINSPOOL.@) |
Dmitry Timoshkov | 3a910c7 | 2003-08-12 20:42:18 +0000 | [diff] [blame] | 2168 | * |
| 2169 | * FIXME: implement DocumentPropertiesA via DocumentPropertiesW, not vice versa |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2170 | */ |
| 2171 | LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2172 | LPWSTR pDeviceName, |
| 2173 | LPDEVMODEW pDevModeOutput, |
| 2174 | LPDEVMODEW pDevModeInput, DWORD fMode) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2175 | { |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2176 | |
Alexandre Julliard | 2731998 | 2006-11-17 15:29:40 +0100 | [diff] [blame] | 2177 | LPSTR pDeviceNameA = strdupWtoA(pDeviceName); |
Detlef Riekenberg | 741fa21 | 2008-03-09 00:38:49 +0100 | [diff] [blame] | 2178 | LPDEVMODEA pDevModeInputA = DEVMODEdupWtoA(pDevModeInput); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2179 | LPDEVMODEA pDevModeOutputA = NULL; |
| 2180 | LONG ret; |
| 2181 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2182 | TRACE("(%p,%p,%s,%p,%p,%d)\n", |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2183 | hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput, |
| 2184 | fMode); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2185 | if(pDevModeOutput) { |
| 2186 | ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, NULL, NULL, 0); |
| 2187 | if(ret < 0) return ret; |
| 2188 | pDevModeOutputA = HeapAlloc(GetProcessHeap(), 0, ret); |
| 2189 | } |
| 2190 | ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, pDevModeOutputA, |
| 2191 | pDevModeInputA, fMode); |
| 2192 | if(pDevModeOutput) { |
| 2193 | DEVMODEcpyAtoW(pDevModeOutput, pDevModeOutputA); |
| 2194 | HeapFree(GetProcessHeap(),0,pDevModeOutputA); |
| 2195 | } |
| 2196 | if(fMode == 0 && ret > 0) |
| 2197 | ret += (CCHDEVICENAME + CCHFORMNAME); |
| 2198 | HeapFree(GetProcessHeap(),0,pDevModeInputA); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 2199 | HeapFree(GetProcessHeap(),0,pDeviceNameA); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2200 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2201 | } |
| 2202 | |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2203 | /****************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2204 | * OpenPrinterA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2205 | * |
Detlef Riekenberg | dd6aa8c | 2005-12-12 12:10:13 +0100 | [diff] [blame] | 2206 | * See OpenPrinterW. |
| 2207 | * |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2208 | */ |
| 2209 | BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter, |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2210 | LPPRINTER_DEFAULTSA pDefault) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2211 | { |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 2212 | UNICODE_STRING lpPrinterNameW; |
| 2213 | UNICODE_STRING usBuffer; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2214 | PRINTER_DEFAULTSW DefaultW, *pDefaultW = NULL; |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 2215 | PWSTR pwstrPrinterNameW; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2216 | BOOL ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2217 | |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 2218 | pwstrPrinterNameW = asciitounicode(&lpPrinterNameW,lpPrinterName); |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 2219 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2220 | if(pDefault) { |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 2221 | DefaultW.pDatatype = asciitounicode(&usBuffer,pDefault->pDatatype); |
Alexandre Julliard | c2320db | 2003-08-12 23:46:34 +0000 | [diff] [blame] | 2222 | DefaultW.pDevMode = pDefault->pDevMode ? GdiConvertToDevmodeW(pDefault->pDevMode) : NULL; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2223 | DefaultW.DesiredAccess = pDefault->DesiredAccess; |
| 2224 | pDefaultW = &DefaultW; |
| 2225 | } |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 2226 | ret = OpenPrinterW(pwstrPrinterNameW, phPrinter, pDefaultW); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2227 | if(pDefault) { |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 2228 | RtlFreeUnicodeString(&usBuffer); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2229 | HeapFree(GetProcessHeap(), 0, DefaultW.pDevMode); |
| 2230 | } |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 2231 | RtlFreeUnicodeString(&lpPrinterNameW); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2232 | return ret; |
| 2233 | } |
| 2234 | |
| 2235 | /****************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2236 | * OpenPrinterW [WINSPOOL.@] |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2237 | * |
Detlef Riekenberg | dd6aa8c | 2005-12-12 12:10:13 +0100 | [diff] [blame] | 2238 | * Open a Printer / Printserver or a Printer-Object |
| 2239 | * |
| 2240 | * PARAMS |
| 2241 | * lpPrinterName [I] Name of Printserver, Printer, or Printer-Object |
| 2242 | * phPrinter [O] The resulting Handle is stored here |
| 2243 | * pDefault [I] PTR to Default Printer Settings or NULL |
| 2244 | * |
| 2245 | * RETURNS |
| 2246 | * Success: TRUE |
| 2247 | * Failure: FALSE |
| 2248 | * |
| 2249 | * NOTES |
| 2250 | * lpPrinterName is one of: |
| 2251 | *| Printserver (NT only): "Servername" or NULL for the local Printserver |
| 2252 | *| Printer: "PrinterName" |
| 2253 | *| Printer-Object: "PrinterName,Job xxx" |
| 2254 | *| XcvMonitor: "Servername,XcvMonitor MonitorName" |
| 2255 | *| XcvPort: "Servername,XcvPort PortName" |
| 2256 | * |
| 2257 | * BUGS |
Detlef Riekenberg | dd6aa8c | 2005-12-12 12:10:13 +0100 | [diff] [blame] | 2258 | *| Printer-Object not supported |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 2259 | *| pDefaults is ignored |
Detlef Riekenberg | dd6aa8c | 2005-12-12 12:10:13 +0100 | [diff] [blame] | 2260 | * |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2261 | */ |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 2262 | BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter, LPPRINTER_DEFAULTSW pDefault) |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2263 | { |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2264 | |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 2265 | TRACE("(%s, %p, %p)\n", debugstr_w(lpPrinterName), phPrinter, pDefault); |
| 2266 | if (pDefault) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2267 | FIXME("PRINTER_DEFAULTS ignored => %s,%p,0x%08x\n", |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 2268 | debugstr_w(pDefault->pDatatype), pDefault->pDevMode, pDefault->DesiredAccess); |
Ulrich Czekalla | 6a80c8a | 2000-02-25 21:38:17 +0000 | [diff] [blame] | 2269 | } |
| 2270 | |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 2271 | if(!phPrinter) { |
| 2272 | /* NT: FALSE with ERROR_INVALID_PARAMETER, 9x: TRUE */ |
| 2273 | SetLastError(ERROR_INVALID_PARAMETER); |
| 2274 | return FALSE; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2275 | } |
| 2276 | |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 2277 | /* Get the unique handle of the printer or Printserver */ |
| 2278 | *phPrinter = get_opened_printer_entry(lpPrinterName, pDefault); |
Francois Gouget | 42c4114 | 2007-01-18 11:37:51 +0100 | [diff] [blame] | 2279 | TRACE("returning %d with %u and %p\n", *phPrinter != NULL, GetLastError(), *phPrinter); |
Detlef Riekenberg | 351106f | 2006-05-12 16:14:59 +0200 | [diff] [blame] | 2280 | return (*phPrinter != 0); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2281 | } |
| 2282 | |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2283 | /****************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2284 | * AddMonitorA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2285 | * |
Detlef Riekenberg | a521947 | 2005-12-06 11:33:52 +0100 | [diff] [blame] | 2286 | * See AddMonitorW. |
| 2287 | * |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2288 | */ |
Huw D M Davies | 685fa2d | 1999-09-04 14:30:33 +0000 | [diff] [blame] | 2289 | BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2290 | { |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2291 | LPWSTR nameW = NULL; |
| 2292 | INT len; |
| 2293 | BOOL res; |
| 2294 | LPMONITOR_INFO_2A mi2a; |
| 2295 | MONITOR_INFO_2W mi2w; |
| 2296 | |
| 2297 | mi2a = (LPMONITOR_INFO_2A) pMonitors; |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2298 | TRACE("(%s, %d, %p) : %s %s %s\n", debugstr_a(pName), Level, pMonitors, |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2299 | mi2a ? debugstr_a(mi2a->pName) : NULL, |
| 2300 | mi2a ? debugstr_a(mi2a->pEnvironment) : NULL, |
| 2301 | mi2a ? debugstr_a(mi2a->pDLLName) : NULL); |
| 2302 | |
| 2303 | if (Level != 2) { |
| 2304 | SetLastError(ERROR_INVALID_LEVEL); |
| 2305 | return FALSE; |
| 2306 | } |
| 2307 | |
| 2308 | /* XP: unchanged, win9x: ERROR_INVALID_ENVIRONMENT */ |
| 2309 | if (mi2a == NULL) { |
| 2310 | return FALSE; |
| 2311 | } |
| 2312 | |
| 2313 | if (pName) { |
| 2314 | len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); |
| 2315 | nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2316 | MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); |
| 2317 | } |
| 2318 | |
| 2319 | memset(&mi2w, 0, sizeof(MONITOR_INFO_2W)); |
| 2320 | if (mi2a->pName) { |
| 2321 | len = MultiByteToWideChar(CP_ACP, 0, mi2a->pName, -1, NULL, 0); |
| 2322 | mi2w.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2323 | MultiByteToWideChar(CP_ACP, 0, mi2a->pName, -1, mi2w.pName, len); |
| 2324 | } |
| 2325 | if (mi2a->pEnvironment) { |
| 2326 | len = MultiByteToWideChar(CP_ACP, 0, mi2a->pEnvironment, -1, NULL, 0); |
| 2327 | mi2w.pEnvironment = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2328 | MultiByteToWideChar(CP_ACP, 0, mi2a->pEnvironment, -1, mi2w.pEnvironment, len); |
| 2329 | } |
| 2330 | if (mi2a->pDLLName) { |
| 2331 | len = MultiByteToWideChar(CP_ACP, 0, mi2a->pDLLName, -1, NULL, 0); |
| 2332 | mi2w.pDLLName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2333 | MultiByteToWideChar(CP_ACP, 0, mi2a->pDLLName, -1, mi2w.pDLLName, len); |
| 2334 | } |
| 2335 | |
| 2336 | res = AddMonitorW(nameW, Level, (LPBYTE) &mi2w); |
| 2337 | |
| 2338 | HeapFree(GetProcessHeap(), 0, mi2w.pName); |
| 2339 | HeapFree(GetProcessHeap(), 0, mi2w.pEnvironment); |
| 2340 | HeapFree(GetProcessHeap(), 0, mi2w.pDLLName); |
| 2341 | |
| 2342 | HeapFree(GetProcessHeap(), 0, nameW); |
| 2343 | return (res); |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2344 | } |
| 2345 | |
| 2346 | /****************************************************************************** |
| 2347 | * AddMonitorW [WINSPOOL.@] |
Detlef Riekenberg | a521947 | 2005-12-06 11:33:52 +0100 | [diff] [blame] | 2348 | * |
| 2349 | * Install a Printmonitor |
| 2350 | * |
| 2351 | * PARAMS |
| 2352 | * pName [I] Servername or NULL (local Computer) |
| 2353 | * Level [I] Structure-Level (Must be 2) |
| 2354 | * pMonitors [I] PTR to MONITOR_INFO_2 |
| 2355 | * |
| 2356 | * RETURNS |
| 2357 | * Success: TRUE |
| 2358 | * Failure: FALSE |
| 2359 | * |
| 2360 | * NOTES |
| 2361 | * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32") |
| 2362 | * |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2363 | */ |
| 2364 | BOOL WINAPI AddMonitorW(LPWSTR pName, DWORD Level, LPBYTE pMonitors) |
| 2365 | { |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 2366 | monitor_t * pm = NULL; |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2367 | LPMONITOR_INFO_2W mi2w; |
| 2368 | HKEY hroot = NULL; |
| 2369 | HKEY hentry = NULL; |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2370 | DWORD disposition; |
| 2371 | BOOL res = FALSE; |
| 2372 | |
| 2373 | mi2w = (LPMONITOR_INFO_2W) pMonitors; |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2374 | TRACE("(%s, %d, %p) : %s %s %s\n", debugstr_w(pName), Level, pMonitors, |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2375 | mi2w ? debugstr_w(mi2w->pName) : NULL, |
| 2376 | mi2w ? debugstr_w(mi2w->pEnvironment) : NULL, |
| 2377 | mi2w ? debugstr_w(mi2w->pDLLName) : NULL); |
| 2378 | |
| 2379 | if (Level != 2) { |
| 2380 | SetLastError(ERROR_INVALID_LEVEL); |
| 2381 | return FALSE; |
| 2382 | } |
| 2383 | |
| 2384 | /* XP: unchanged, win9x: ERROR_INVALID_ENVIRONMENT */ |
| 2385 | if (mi2w == NULL) { |
| 2386 | return FALSE; |
| 2387 | } |
| 2388 | |
| 2389 | if (pName && (pName[0])) { |
| 2390 | FIXME("for server %s not implemented\n", debugstr_w(pName)); |
| 2391 | SetLastError(ERROR_ACCESS_DENIED); |
| 2392 | return FALSE; |
| 2393 | } |
| 2394 | |
| 2395 | |
| 2396 | if (!mi2w->pName || (! mi2w->pName[0])) { |
Francois Gouget | f7c24f3 | 2006-05-12 00:32:31 +0200 | [diff] [blame] | 2397 | WARN("pName not valid : %s\n", debugstr_w(mi2w->pName)); |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2398 | SetLastError(ERROR_INVALID_PARAMETER); |
| 2399 | return FALSE; |
| 2400 | } |
| 2401 | if (!mi2w->pEnvironment || lstrcmpW(mi2w->pEnvironment, envname_x86W)) { |
| 2402 | WARN("Environment %s requested (we support only %s)\n", |
| 2403 | debugstr_w(mi2w->pEnvironment), debugstr_w(envname_x86W)); |
| 2404 | SetLastError(ERROR_INVALID_ENVIRONMENT); |
| 2405 | return FALSE; |
| 2406 | } |
| 2407 | |
| 2408 | if (!mi2w->pDLLName || (! mi2w->pDLLName[0])) { |
Francois Gouget | f7c24f3 | 2006-05-12 00:32:31 +0200 | [diff] [blame] | 2409 | WARN("pDLLName not valid : %s\n", debugstr_w(mi2w->pDLLName)); |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2410 | SetLastError(ERROR_INVALID_PARAMETER); |
| 2411 | return FALSE; |
| 2412 | } |
| 2413 | |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 2414 | /* Load and initialize the monitor. SetLastError() is called on failure */ |
| 2415 | if ((pm = monitor_load(mi2w->pName, mi2w->pDLLName)) == NULL) { |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2416 | return FALSE; |
| 2417 | } |
Detlef Riekenberg | 1e17738 | 2006-09-02 22:50:32 +0200 | [diff] [blame] | 2418 | monitor_unload(pm); |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2419 | |
| 2420 | if(RegCreateKeyW(HKEY_LOCAL_MACHINE, MonitorsW, &hroot) != ERROR_SUCCESS) { |
| 2421 | ERR("unable to create key %s\n", debugstr_w(MonitorsW)); |
| 2422 | return FALSE; |
| 2423 | } |
| 2424 | |
Detlef Riekenberg | 698a8a0 | 2006-06-16 10:01:31 +0200 | [diff] [blame] | 2425 | if(RegCreateKeyExW( hroot, mi2w->pName, 0, NULL, REG_OPTION_NON_VOLATILE, |
| 2426 | KEY_WRITE | KEY_QUERY_VALUE, NULL, &hentry, |
| 2427 | &disposition) == ERROR_SUCCESS) { |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2428 | |
Detlef Riekenberg | 698a8a0 | 2006-06-16 10:01:31 +0200 | [diff] [blame] | 2429 | /* Some installers set options for the port before calling AddMonitor. |
| 2430 | We query the "Driver" entry to verify that the monitor is installed, |
| 2431 | before we return an error. |
| 2432 | When a user installs two print monitors at the same time with the |
| 2433 | same name but with a different driver DLL and a task switch comes |
| 2434 | between RegQueryValueExW and RegSetValueExW, a race condition |
| 2435 | is possible but silently ignored. */ |
| 2436 | |
| 2437 | DWORD namesize = 0; |
| 2438 | |
| 2439 | if ((disposition == REG_OPENED_EXISTING_KEY) && |
| 2440 | (RegQueryValueExW(hentry, DriverW, NULL, NULL, NULL, |
| 2441 | &namesize) == ERROR_SUCCESS)) { |
Detlef Riekenberg | ed1161f | 2006-04-11 20:42:18 +0200 | [diff] [blame] | 2442 | TRACE("monitor %s already exists\n", debugstr_w(mi2w->pName)); |
| 2443 | /* NT: ERROR_PRINT_MONITOR_ALREADY_INSTALLED (3006) |
| 2444 | 9x: ERROR_ALREADY_EXISTS (183) */ |
| 2445 | SetLastError(ERROR_PRINT_MONITOR_ALREADY_INSTALLED); |
| 2446 | } |
| 2447 | else |
| 2448 | { |
| 2449 | INT len; |
| 2450 | len = (lstrlenW(mi2w->pDLLName) +1) * sizeof(WCHAR); |
| 2451 | res = (RegSetValueExW(hentry, DriverW, 0, |
| 2452 | REG_SZ, (LPBYTE) mi2w->pDLLName, len) == ERROR_SUCCESS); |
| 2453 | } |
| 2454 | RegCloseKey(hentry); |
| 2455 | } |
| 2456 | |
| 2457 | RegCloseKey(hroot); |
| 2458 | return (res); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2459 | } |
| 2460 | |
| 2461 | /****************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2462 | * DeletePrinterDriverA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2463 | * |
| 2464 | */ |
Huw Davies | d4fb1c3 | 2006-11-07 11:57:39 +0000 | [diff] [blame] | 2465 | BOOL WINAPI DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2466 | { |
Huw Davies | d4fb1c3 | 2006-11-07 11:57:39 +0000 | [diff] [blame] | 2467 | return DeletePrinterDriverExA(pName, pEnvironment, pDriverName, 0, 0); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2468 | } |
| 2469 | |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2470 | /****************************************************************** |
| 2471 | * DeletePrinterDriverW [WINSPOOL.@] |
| 2472 | * |
| 2473 | */ |
Huw Davies | d4fb1c3 | 2006-11-07 11:57:39 +0000 | [diff] [blame] | 2474 | BOOL WINAPI DeletePrinterDriverW (LPWSTR pName, LPWSTR pEnvironment, LPWSTR pDriverName) |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2475 | { |
Huw Davies | d4fb1c3 | 2006-11-07 11:57:39 +0000 | [diff] [blame] | 2476 | return DeletePrinterDriverExW(pName, pEnvironment, pDriverName, 0, 0); |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2477 | } |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2478 | |
| 2479 | /****************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2480 | * DeleteMonitorA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2481 | * |
Detlef Riekenberg | a521947 | 2005-12-06 11:33:52 +0100 | [diff] [blame] | 2482 | * See DeleteMonitorW. |
| 2483 | * |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2484 | */ |
Detlef Riekenberg | 3b38308 | 2006-04-16 02:56:27 +0200 | [diff] [blame] | 2485 | BOOL WINAPI DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2486 | { |
Detlef Riekenberg | 3b38308 | 2006-04-16 02:56:27 +0200 | [diff] [blame] | 2487 | LPWSTR nameW = NULL; |
| 2488 | LPWSTR EnvironmentW = NULL; |
| 2489 | LPWSTR MonitorNameW = NULL; |
| 2490 | BOOL res; |
| 2491 | INT len; |
| 2492 | |
| 2493 | if (pName) { |
| 2494 | len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); |
| 2495 | nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2496 | MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); |
| 2497 | } |
| 2498 | |
| 2499 | if (pEnvironment) { |
| 2500 | len = MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, NULL, 0); |
| 2501 | EnvironmentW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2502 | MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, EnvironmentW, len); |
| 2503 | } |
| 2504 | if (pMonitorName) { |
| 2505 | len = MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, NULL, 0); |
| 2506 | MonitorNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2507 | MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, MonitorNameW, len); |
| 2508 | } |
| 2509 | |
| 2510 | res = DeleteMonitorW(nameW, EnvironmentW, MonitorNameW); |
| 2511 | |
| 2512 | HeapFree(GetProcessHeap(), 0, MonitorNameW); |
| 2513 | HeapFree(GetProcessHeap(), 0, EnvironmentW); |
| 2514 | HeapFree(GetProcessHeap(), 0, nameW); |
| 2515 | return (res); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2516 | } |
| 2517 | |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2518 | /****************************************************************** |
| 2519 | * DeleteMonitorW [WINSPOOL.@] |
| 2520 | * |
Detlef Riekenberg | a521947 | 2005-12-06 11:33:52 +0100 | [diff] [blame] | 2521 | * Delete a specific Printmonitor from a Printing-Environment |
| 2522 | * |
| 2523 | * PARAMS |
| 2524 | * pName [I] Servername or NULL (local Computer) |
| 2525 | * pEnvironment [I] Printing-Environment of the Monitor or NULL (Default) |
| 2526 | * pMonitorName [I] Name of the Monitor, that should be deleted |
| 2527 | * |
| 2528 | * RETURNS |
| 2529 | * Success: TRUE |
| 2530 | * Failure: FALSE |
| 2531 | * |
Detlef Riekenberg | 3b38308 | 2006-04-16 02:56:27 +0200 | [diff] [blame] | 2532 | * NOTES |
| 2533 | * pEnvironment is ignored in Windows for the local Computer. |
Detlef Riekenberg | a521947 | 2005-12-06 11:33:52 +0100 | [diff] [blame] | 2534 | * |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2535 | */ |
Detlef Riekenberg | 3b38308 | 2006-04-16 02:56:27 +0200 | [diff] [blame] | 2536 | |
| 2537 | BOOL WINAPI DeleteMonitorW (LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName) |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2538 | { |
Detlef Riekenberg | 3b38308 | 2006-04-16 02:56:27 +0200 | [diff] [blame] | 2539 | HKEY hroot = NULL; |
| 2540 | |
| 2541 | TRACE("(%s, %s, %s)\n",debugstr_w(pName),debugstr_w(pEnvironment), |
| 2542 | debugstr_w(pMonitorName)); |
| 2543 | |
| 2544 | if (pName && (pName[0])) { |
| 2545 | FIXME("for server %s not implemented\n", debugstr_w(pName)); |
| 2546 | SetLastError(ERROR_ACCESS_DENIED); |
| 2547 | return FALSE; |
| 2548 | } |
| 2549 | |
| 2550 | /* pEnvironment is ignored in Windows for the local Computer */ |
| 2551 | |
| 2552 | if (!pMonitorName || !pMonitorName[0]) { |
| 2553 | WARN("pMonitorName %s is invalid\n", debugstr_w(pMonitorName)); |
| 2554 | SetLastError(ERROR_INVALID_PARAMETER); |
| 2555 | return FALSE; |
| 2556 | } |
| 2557 | |
| 2558 | if(RegCreateKeyW(HKEY_LOCAL_MACHINE, MonitorsW, &hroot) != ERROR_SUCCESS) { |
| 2559 | ERR("unable to create key %s\n", debugstr_w(MonitorsW)); |
| 2560 | return FALSE; |
| 2561 | } |
| 2562 | |
Stefan Leichter | 06b64a1 | 2007-06-05 18:47:17 +0200 | [diff] [blame] | 2563 | if(RegDeleteTreeW(hroot, pMonitorName) == ERROR_SUCCESS) { |
Detlef Riekenberg | 3b38308 | 2006-04-16 02:56:27 +0200 | [diff] [blame] | 2564 | TRACE("monitor %s deleted\n", debugstr_w(pMonitorName)); |
| 2565 | RegCloseKey(hroot); |
| 2566 | return TRUE; |
| 2567 | } |
| 2568 | |
Francois Gouget | b0bde6b | 2007-01-18 11:35:50 +0100 | [diff] [blame] | 2569 | WARN("monitor %s does not exist\n", debugstr_w(pMonitorName)); |
Detlef Riekenberg | 3b38308 | 2006-04-16 02:56:27 +0200 | [diff] [blame] | 2570 | RegCloseKey(hroot); |
| 2571 | |
| 2572 | /* NT: ERROR_UNKNOWN_PRINT_MONITOR (3000), 9x: ERROR_INVALID_PARAMETER (87) */ |
| 2573 | SetLastError(ERROR_UNKNOWN_PRINT_MONITOR); |
| 2574 | return (FALSE); |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2575 | } |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2576 | |
| 2577 | /****************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2578 | * DeletePortA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2579 | * |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 2580 | * See DeletePortW. |
| 2581 | * |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2582 | */ |
Detlef Riekenberg | bcfa90e | 2006-11-28 00:47:08 +0100 | [diff] [blame] | 2583 | BOOL WINAPI DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2584 | { |
Detlef Riekenberg | bcfa90e | 2006-11-28 00:47:08 +0100 | [diff] [blame] | 2585 | LPWSTR nameW = NULL; |
| 2586 | LPWSTR portW = NULL; |
| 2587 | INT len; |
| 2588 | DWORD res; |
| 2589 | |
| 2590 | TRACE("(%s, %p, %s)\n", debugstr_a(pName), hWnd, debugstr_a(pPortName)); |
| 2591 | |
| 2592 | /* convert servername to unicode */ |
| 2593 | if (pName) { |
| 2594 | len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); |
| 2595 | nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2596 | MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); |
| 2597 | } |
| 2598 | |
| 2599 | /* convert portname to unicode */ |
| 2600 | if (pPortName) { |
| 2601 | len = MultiByteToWideChar(CP_ACP, 0, pPortName, -1, NULL, 0); |
| 2602 | portW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2603 | MultiByteToWideChar(CP_ACP, 0, pPortName, -1, portW, len); |
| 2604 | } |
| 2605 | |
| 2606 | res = DeletePortW(nameW, hWnd, portW); |
| 2607 | HeapFree(GetProcessHeap(), 0, nameW); |
| 2608 | HeapFree(GetProcessHeap(), 0, portW); |
| 2609 | return res; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2610 | } |
| 2611 | |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2612 | /****************************************************************** |
| 2613 | * DeletePortW [WINSPOOL.@] |
| 2614 | * |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 2615 | * Delete a specific Port |
| 2616 | * |
| 2617 | * PARAMS |
| 2618 | * pName [I] Servername or NULL (local Computer) |
| 2619 | * hWnd [I] Handle to parent Window for the Dialog-Box |
| 2620 | * pPortName [I] Name of the Port, that should be deleted |
| 2621 | * |
| 2622 | * RETURNS |
| 2623 | * Success: TRUE |
| 2624 | * Failure: FALSE |
| 2625 | * |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2626 | */ |
Detlef Riekenberg | c587d1a | 2006-11-28 00:46:28 +0100 | [diff] [blame] | 2627 | BOOL WINAPI DeletePortW (LPWSTR pName, HWND hWnd, LPWSTR pPortName) |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2628 | { |
Detlef Riekenberg | c587d1a | 2006-11-28 00:46:28 +0100 | [diff] [blame] | 2629 | monitor_t * pm; |
Detlef Riekenberg | 917b0ee | 2007-01-15 05:37:20 +0100 | [diff] [blame] | 2630 | monitor_t * pui; |
| 2631 | DWORD res; |
Detlef Riekenberg | c587d1a | 2006-11-28 00:46:28 +0100 | [diff] [blame] | 2632 | |
| 2633 | TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName)); |
| 2634 | |
| 2635 | if (pName && pName[0]) { |
| 2636 | SetLastError(ERROR_INVALID_PARAMETER); |
| 2637 | return FALSE; |
| 2638 | } |
| 2639 | |
| 2640 | if (!pPortName) { |
| 2641 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 2642 | return FALSE; |
| 2643 | } |
| 2644 | |
| 2645 | /* an empty Portname is Invalid */ |
Detlef Riekenberg | 917b0ee | 2007-01-15 05:37:20 +0100 | [diff] [blame] | 2646 | if (!pPortName[0]) { |
| 2647 | SetLastError(ERROR_NOT_SUPPORTED); |
| 2648 | return FALSE; |
| 2649 | } |
Detlef Riekenberg | c587d1a | 2006-11-28 00:46:28 +0100 | [diff] [blame] | 2650 | |
| 2651 | pm = monitor_load_by_port(pPortName); |
Detlef Riekenberg | 917b0ee | 2007-01-15 05:37:20 +0100 | [diff] [blame] | 2652 | if (pm && pm->monitor && pm->monitor->pfnDeletePort) { |
| 2653 | TRACE("Using %s for %s (%p: %s)\n", debugstr_w(pm->name), debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); |
| 2654 | res = pm->monitor->pfnDeletePort(pName, hWnd, pPortName); |
| 2655 | TRACE("got %d with %u\n", res, GetLastError()); |
Detlef Riekenberg | c587d1a | 2006-11-28 00:46:28 +0100 | [diff] [blame] | 2656 | } |
Detlef Riekenberg | 917b0ee | 2007-01-15 05:37:20 +0100 | [diff] [blame] | 2657 | else |
| 2658 | { |
| 2659 | pui = monitor_loadui(pm); |
| 2660 | if (pui && pui->monitorUI && pui->monitorUI->pfnDeletePortUI) { |
| 2661 | TRACE("use %s for %s (%p: %s)\n", debugstr_w(pui->name), debugstr_w(pPortName), pui, debugstr_w(pui->dllname)); |
| 2662 | res = pui->monitorUI->pfnDeletePortUI(pName, hWnd, pPortName); |
| 2663 | TRACE("got %d with %u\n", res, GetLastError()); |
| 2664 | } |
| 2665 | else |
| 2666 | { |
| 2667 | FIXME("not implemented for %s (%p: %s => %p: %s)\n", debugstr_w(pPortName), |
| 2668 | pm, pm ? debugstr_w(pm->dllname) : NULL, pui, pui ? debugstr_w(pui->dllname) : NULL); |
| 2669 | |
| 2670 | /* XP: ERROR_NOT_SUPPORTED, NT351,9x: ERROR_INVALID_PARAMETER */ |
| 2671 | SetLastError(ERROR_NOT_SUPPORTED); |
| 2672 | res = FALSE; |
| 2673 | } |
| 2674 | monitor_unload(pui); |
| 2675 | } |
Detlef Riekenberg | c587d1a | 2006-11-28 00:46:28 +0100 | [diff] [blame] | 2676 | monitor_unload(pm); |
| 2677 | |
Detlef Riekenberg | 917b0ee | 2007-01-15 05:37:20 +0100 | [diff] [blame] | 2678 | TRACE("returning %d with %u\n", res, GetLastError()); |
| 2679 | return res; |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2680 | } |
| 2681 | |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2682 | /****************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2683 | * SetPrinterW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2684 | */ |
Detlef Riekenberg | b7a62e5 | 2006-05-12 14:53:17 +0200 | [diff] [blame] | 2685 | BOOL WINAPI SetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD Command) |
| 2686 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2687 | FIXME("(%p, %d, %p, %d): stub\n", hPrinter, Level, pPrinter, Command); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 2688 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| 2689 | return FALSE; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2690 | } |
| 2691 | |
| 2692 | /****************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2693 | * WritePrinter [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2694 | */ |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 2695 | BOOL WINAPI WritePrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, LPDWORD pcWritten) |
| 2696 | { |
| 2697 | opened_printer_t *printer; |
| 2698 | BOOL ret = FALSE; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2699 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2700 | TRACE("(%p, %p, %d, %p)\n", hPrinter, pBuf, cbBuf, pcWritten); |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 2701 | |
| 2702 | EnterCriticalSection(&printer_handles_cs); |
| 2703 | printer = get_opened_printer(hPrinter); |
| 2704 | if(!printer) |
| 2705 | { |
| 2706 | SetLastError(ERROR_INVALID_HANDLE); |
| 2707 | goto end; |
| 2708 | } |
| 2709 | |
| 2710 | if(!printer->doc) |
| 2711 | { |
| 2712 | SetLastError(ERROR_SPL_NO_STARTDOC); |
| 2713 | goto end; |
| 2714 | } |
| 2715 | |
| 2716 | ret = WriteFile(printer->doc->hf, pBuf, cbBuf, pcWritten, NULL); |
| 2717 | end: |
| 2718 | LeaveCriticalSection(&printer_handles_cs); |
| 2719 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2720 | } |
| 2721 | |
| 2722 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2723 | * AddFormA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2724 | */ |
| 2725 | BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm) |
| 2726 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2727 | FIXME("(%p,%d,%p): stub\n", hPrinter, Level, pForm); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2728 | return 1; |
| 2729 | } |
| 2730 | |
| 2731 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2732 | * AddFormW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2733 | */ |
| 2734 | BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm) |
| 2735 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2736 | FIXME("(%p,%d,%p): stub\n", hPrinter, Level, pForm); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2737 | return 1; |
| 2738 | } |
| 2739 | |
| 2740 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2741 | * AddJobA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2742 | */ |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 2743 | BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeeded) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2744 | { |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 2745 | BOOL ret; |
| 2746 | BYTE buf[MAX_PATH * sizeof(WCHAR) + sizeof(ADDJOB_INFO_1W)]; |
| 2747 | DWORD needed; |
| 2748 | |
| 2749 | if(Level != 1) { |
| 2750 | SetLastError(ERROR_INVALID_LEVEL); |
| 2751 | return FALSE; |
| 2752 | } |
| 2753 | |
| 2754 | ret = AddJobW(hPrinter, Level, buf, sizeof(buf), &needed); |
| 2755 | |
| 2756 | if(ret) { |
| 2757 | ADDJOB_INFO_1W *addjobW = (ADDJOB_INFO_1W*)buf; |
| 2758 | DWORD len = WideCharToMultiByte(CP_ACP, 0, addjobW->Path, -1, NULL, 0, NULL, NULL); |
| 2759 | *pcbNeeded = len + sizeof(ADDJOB_INFO_1A); |
| 2760 | if(*pcbNeeded > cbBuf) { |
| 2761 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 2762 | ret = FALSE; |
| 2763 | } else { |
| 2764 | ADDJOB_INFO_1A *addjobA = (ADDJOB_INFO_1A*)pData; |
| 2765 | addjobA->JobId = addjobW->JobId; |
| 2766 | addjobA->Path = (char *)(addjobA + 1); |
| 2767 | WideCharToMultiByte(CP_ACP, 0, addjobW->Path, -1, addjobA->Path, len, NULL, NULL); |
| 2768 | } |
| 2769 | } |
| 2770 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2771 | } |
| 2772 | |
| 2773 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 2774 | * AddJobW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2775 | */ |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 2776 | BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeeded) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2777 | { |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 2778 | opened_printer_t *printer; |
| 2779 | job_t *job; |
| 2780 | BOOL ret = FALSE; |
| 2781 | static const WCHAR spool_path[] = {'s','p','o','o','l','\\','P','R','I','N','T','E','R','S','\\',0}; |
| 2782 | static const WCHAR fmtW[] = {'%','s','%','0','5','d','.','S','P','L',0}; |
| 2783 | WCHAR path[MAX_PATH], filename[MAX_PATH]; |
| 2784 | DWORD len; |
| 2785 | ADDJOB_INFO_1W *addjob; |
| 2786 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2787 | TRACE("(%p,%d,%p,%d,%p)\n", hPrinter, Level, pData, cbBuf, pcbNeeded); |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 2788 | |
| 2789 | EnterCriticalSection(&printer_handles_cs); |
| 2790 | |
| 2791 | printer = get_opened_printer(hPrinter); |
| 2792 | |
| 2793 | if(!printer) { |
| 2794 | SetLastError(ERROR_INVALID_HANDLE); |
| 2795 | goto end; |
| 2796 | } |
| 2797 | |
| 2798 | if(Level != 1) { |
| 2799 | SetLastError(ERROR_INVALID_LEVEL); |
| 2800 | goto end; |
| 2801 | } |
| 2802 | |
| 2803 | job = HeapAlloc(GetProcessHeap(), 0, sizeof(*job)); |
| 2804 | if(!job) |
| 2805 | goto end; |
| 2806 | |
| 2807 | job->job_id = InterlockedIncrement(&next_job_id); |
| 2808 | |
| 2809 | len = GetSystemDirectoryW(path, sizeof(path) / sizeof(WCHAR)); |
| 2810 | if(path[len - 1] != '\\') |
| 2811 | path[len++] = '\\'; |
| 2812 | memcpy(path + len, spool_path, sizeof(spool_path)); |
| 2813 | sprintfW(filename, fmtW, path, job->job_id); |
| 2814 | |
| 2815 | len = strlenW(filename); |
| 2816 | job->filename = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); |
| 2817 | memcpy(job->filename, filename, (len + 1) * sizeof(WCHAR)); |
Huw Davies | 183fcb5 | 2005-07-15 09:55:23 +0000 | [diff] [blame] | 2818 | job->document_title = strdupW(default_doc_title); |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 2819 | list_add_tail(&printer->queue->jobs, &job->entry); |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 2820 | |
| 2821 | *pcbNeeded = (len + 1) * sizeof(WCHAR) + sizeof(*addjob); |
| 2822 | if(*pcbNeeded <= cbBuf) { |
| 2823 | addjob = (ADDJOB_INFO_1W*)pData; |
| 2824 | addjob->JobId = job->job_id; |
| 2825 | addjob->Path = (WCHAR *)(addjob + 1); |
| 2826 | memcpy(addjob->Path, filename, (len + 1) * sizeof(WCHAR)); |
| 2827 | ret = TRUE; |
| 2828 | } else |
| 2829 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 2830 | |
| 2831 | end: |
| 2832 | LeaveCriticalSection(&printer_handles_cs); |
| 2833 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 2834 | } |
| 2835 | |
| 2836 | /***************************************************************************** |
Uwe Bonnes | 1d60387 | 2003-04-27 20:35:08 +0000 | [diff] [blame] | 2837 | * GetPrintProcessorDirectoryA [WINSPOOL.@] |
Detlef Riekenberg | aff1b33 | 2006-05-27 00:30:58 +0200 | [diff] [blame] | 2838 | * |
| 2839 | * Return the PATH for the Print-Processors |
| 2840 | * |
| 2841 | * See GetPrintProcessorDirectoryW. |
| 2842 | * |
Detlef Riekenberg | aff1b33 | 2006-05-27 00:30:58 +0200 | [diff] [blame] | 2843 | * |
Uwe Bonnes | 1d60387 | 2003-04-27 20:35:08 +0000 | [diff] [blame] | 2844 | */ |
Alexandre Julliard | 402b79a | 2003-11-27 00:59:36 +0000 | [diff] [blame] | 2845 | BOOL WINAPI GetPrintProcessorDirectoryA(LPSTR server, LPSTR env, |
Uwe Bonnes | 1d60387 | 2003-04-27 20:35:08 +0000 | [diff] [blame] | 2846 | DWORD level, LPBYTE Info, |
Detlef Riekenberg | 94543cb | 2006-06-09 13:06:41 +0200 | [diff] [blame] | 2847 | DWORD cbBuf, LPDWORD pcbNeeded) |
Uwe Bonnes | 1d60387 | 2003-04-27 20:35:08 +0000 | [diff] [blame] | 2848 | { |
Detlef Riekenberg | 94543cb | 2006-06-09 13:06:41 +0200 | [diff] [blame] | 2849 | LPWSTR serverW = NULL; |
| 2850 | LPWSTR envW = NULL; |
| 2851 | BOOL ret; |
| 2852 | INT len; |
| 2853 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2854 | TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_a(server), |
Detlef Riekenberg | 94543cb | 2006-06-09 13:06:41 +0200 | [diff] [blame] | 2855 | debugstr_a(env), level, Info, cbBuf, pcbNeeded); |
| 2856 | |
| 2857 | |
| 2858 | if (server) { |
| 2859 | len = MultiByteToWideChar(CP_ACP, 0, server, -1, NULL, 0); |
| 2860 | serverW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2861 | MultiByteToWideChar(CP_ACP, 0, server, -1, serverW, len); |
| 2862 | } |
| 2863 | |
| 2864 | if (env) { |
| 2865 | len = MultiByteToWideChar(CP_ACP, 0, env, -1, NULL, 0); |
| 2866 | envW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 2867 | MultiByteToWideChar(CP_ACP, 0, env, -1, envW, len); |
| 2868 | } |
| 2869 | |
| 2870 | /* NT requires the buffersize from GetPrintProcessorDirectoryW also |
| 2871 | for GetPrintProcessorDirectoryA and WC2MB is done in-place. |
| 2872 | */ |
| 2873 | ret = GetPrintProcessorDirectoryW(serverW, envW, level, Info, |
| 2874 | cbBuf, pcbNeeded); |
| 2875 | |
| 2876 | if (ret) ret = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)Info, -1, (LPSTR)Info, |
| 2877 | cbBuf, NULL, NULL) > 0; |
| 2878 | |
| 2879 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2880 | TRACE(" required: 0x%x/%d\n", pcbNeeded ? *pcbNeeded : 0, pcbNeeded ? *pcbNeeded : 0); |
Detlef Riekenberg | 94543cb | 2006-06-09 13:06:41 +0200 | [diff] [blame] | 2881 | HeapFree(GetProcessHeap(), 0, envW); |
| 2882 | HeapFree(GetProcessHeap(), 0, serverW); |
| 2883 | return ret; |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2884 | } |
| 2885 | |
| 2886 | /***************************************************************************** |
| 2887 | * GetPrintProcessorDirectoryW [WINSPOOL.@] |
Detlef Riekenberg | aff1b33 | 2006-05-27 00:30:58 +0200 | [diff] [blame] | 2888 | * |
| 2889 | * Return the PATH for the Print-Processors |
| 2890 | * |
| 2891 | * PARAMS |
| 2892 | * server [I] Servername (NT only) or NULL (local Computer) |
| 2893 | * env [I] Printing-Environment (see below) or NULL (Default) |
| 2894 | * level [I] Structure-Level (must be 1) |
| 2895 | * Info [O] PTR to Buffer that receives the Result |
| 2896 | * cbBuf [I] Size of Buffer at "Info" |
Detlef Riekenberg | f0a62dd | 2006-05-28 21:56:52 +0200 | [diff] [blame] | 2897 | * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / |
Detlef Riekenberg | aff1b33 | 2006-05-27 00:30:58 +0200 | [diff] [blame] | 2898 | * required for the Buffer at "Info" |
| 2899 | * |
| 2900 | * RETURNS |
Detlef Riekenberg | f0a62dd | 2006-05-28 21:56:52 +0200 | [diff] [blame] | 2901 | * Success: TRUE and in pcbNeeded the Bytes used in Info |
| 2902 | * Failure: FALSE and in pcbNeeded the Bytes required for Info, |
Detlef Riekenberg | aff1b33 | 2006-05-27 00:30:58 +0200 | [diff] [blame] | 2903 | * if cbBuf is too small |
| 2904 | * |
Detlef Riekenberg | f0a62dd | 2006-05-28 21:56:52 +0200 | [diff] [blame] | 2905 | * Native Values returned in Info on Success: |
Detlef Riekenberg | aff1b33 | 2006-05-27 00:30:58 +0200 | [diff] [blame] | 2906 | *| NT(Windows NT x86): "%winsysdir%\\spool\\PRTPROCS\\w32x86" |
| 2907 | *| NT(Windows 4.0): "%winsysdir%\\spool\\PRTPROCS\\win40" |
| 2908 | *| win9x(Windows 4.0): "%winsysdir%" |
| 2909 | * |
| 2910 | * "%winsysdir%" is the Value from GetSystemDirectoryW() |
| 2911 | * |
| 2912 | * BUGS |
Detlef Riekenberg | f0a62dd | 2006-05-28 21:56:52 +0200 | [diff] [blame] | 2913 | * Only NULL or "" is supported for server |
Detlef Riekenberg | aff1b33 | 2006-05-27 00:30:58 +0200 | [diff] [blame] | 2914 | * |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2915 | */ |
| 2916 | BOOL WINAPI GetPrintProcessorDirectoryW(LPWSTR server, LPWSTR env, |
| 2917 | DWORD level, LPBYTE Info, |
Detlef Riekenberg | f0a62dd | 2006-05-28 21:56:52 +0200 | [diff] [blame] | 2918 | DWORD cbBuf, LPDWORD pcbNeeded) |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 2919 | { |
Detlef Riekenberg | f0a62dd | 2006-05-28 21:56:52 +0200 | [diff] [blame] | 2920 | DWORD needed; |
| 2921 | const printenv_t * env_t; |
| 2922 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2923 | TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(server), |
Detlef Riekenberg | f0a62dd | 2006-05-28 21:56:52 +0200 | [diff] [blame] | 2924 | debugstr_w(env), level, Info, cbBuf, pcbNeeded); |
| 2925 | |
| 2926 | if(server != NULL && server[0]) { |
| 2927 | FIXME("server not supported: %s\n", debugstr_w(server)); |
| 2928 | SetLastError(ERROR_INVALID_PARAMETER); |
| 2929 | return FALSE; |
| 2930 | } |
| 2931 | |
| 2932 | env_t = validate_envW(env); |
| 2933 | if(!env_t) return FALSE; /* environment invalid or unsupported */ |
| 2934 | |
| 2935 | if(level != 1) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2936 | WARN("(Level: %d) is ignored in win9x\n", level); |
Detlef Riekenberg | f0a62dd | 2006-05-28 21:56:52 +0200 | [diff] [blame] | 2937 | SetLastError(ERROR_INVALID_LEVEL); |
| 2938 | return FALSE; |
| 2939 | } |
| 2940 | |
| 2941 | /* GetSystemDirectoryW returns number of WCHAR including the '\0' */ |
| 2942 | needed = GetSystemDirectoryW(NULL, 0); |
| 2943 | /* add the Size for the Subdirectories */ |
| 2944 | needed += lstrlenW(spoolprtprocsW); |
| 2945 | needed += lstrlenW(env_t->subdir); |
| 2946 | needed *= sizeof(WCHAR); /* return-value is size in Bytes */ |
| 2947 | |
| 2948 | if(pcbNeeded) *pcbNeeded = needed; |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 2949 | TRACE ("required: 0x%x/%d\n", needed, needed); |
Detlef Riekenberg | f0a62dd | 2006-05-28 21:56:52 +0200 | [diff] [blame] | 2950 | if (needed > cbBuf) { |
| 2951 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 2952 | return FALSE; |
| 2953 | } |
| 2954 | if(pcbNeeded == NULL) { |
| 2955 | /* NT: RPC_X_NULL_REF_POINTER, 9x: ignored */ |
| 2956 | WARN("(pcbNeeded == NULL) is ignored in win9x\n"); |
| 2957 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 2958 | return FALSE; |
| 2959 | } |
| 2960 | if(Info == NULL) { |
| 2961 | /* NT: RPC_X_NULL_REF_POINTER, 9x: ERROR_INVALID_PARAMETER */ |
| 2962 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 2963 | return FALSE; |
| 2964 | } |
| 2965 | |
| 2966 | GetSystemDirectoryW((LPWSTR) Info, cbBuf/sizeof(WCHAR)); |
| 2967 | /* add the Subdirectories */ |
| 2968 | lstrcatW((LPWSTR) Info, spoolprtprocsW); |
| 2969 | lstrcatW((LPWSTR) Info, env_t->subdir); |
| 2970 | TRACE(" => %s\n", debugstr_w((LPWSTR) Info)); |
| 2971 | return TRUE; |
Uwe Bonnes | 1d60387 | 2003-04-27 20:35:08 +0000 | [diff] [blame] | 2972 | } |
| 2973 | |
| 2974 | /***************************************************************************** |
Stefan Leichter | ca1661c | 2000-11-06 05:26:00 +0000 | [diff] [blame] | 2975 | * WINSPOOL_OpenDriverReg [internal] |
| 2976 | * |
| 2977 | * opens the registry for the printer drivers depending on the given input |
| 2978 | * variable pEnvironment |
| 2979 | * |
| 2980 | * RETURNS: |
| 2981 | * the opened hkey on success |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 2982 | * NULL on error |
Stefan Leichter | ca1661c | 2000-11-06 05:26:00 +0000 | [diff] [blame] | 2983 | */ |
Vitaly Lipatov | c9d78fc | 2007-02-18 13:51:09 +0300 | [diff] [blame] | 2984 | static HKEY WINSPOOL_OpenDriverReg( LPCVOID pEnvironment, BOOL unicode) |
Dimitrie O. Paun | d4193bb | 2005-03-29 13:10:35 +0000 | [diff] [blame] | 2985 | { |
Detlef Riekenberg | 6c233ef | 2006-05-11 23:59:17 +0200 | [diff] [blame] | 2986 | HKEY retval = NULL; |
| 2987 | LPWSTR buffer; |
| 2988 | const printenv_t * env; |
Stefan Leichter | ca1661c | 2000-11-06 05:26:00 +0000 | [diff] [blame] | 2989 | |
Detlef Riekenberg | 6c233ef | 2006-05-11 23:59:17 +0200 | [diff] [blame] | 2990 | TRACE("(%s, %d)\n", |
| 2991 | (unicode) ? debugstr_w(pEnvironment) : debugstr_a(pEnvironment), unicode); |
Stefan Leichter | ca1661c | 2000-11-06 05:26:00 +0000 | [diff] [blame] | 2992 | |
Detlef Riekenberg | 6c233ef | 2006-05-11 23:59:17 +0200 | [diff] [blame] | 2993 | if (!pEnvironment || unicode) { |
| 2994 | /* pEnvironment was NULL or an Unicode-String: use it direct */ |
| 2995 | env = validate_envW(pEnvironment); |
Stefan Leichter | ca1661c | 2000-11-06 05:26:00 +0000 | [diff] [blame] | 2996 | } |
Detlef Riekenberg | 6c233ef | 2006-05-11 23:59:17 +0200 | [diff] [blame] | 2997 | else |
| 2998 | { |
| 2999 | /* pEnvironment was an ANSI-String: convert to unicode first */ |
| 3000 | LPWSTR buffer; |
| 3001 | INT len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pEnvironment, -1, NULL, 0); |
| 3002 | buffer = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 3003 | if (buffer) MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pEnvironment, -1, buffer, len); |
| 3004 | env = validate_envW(buffer); |
| 3005 | HeapFree(GetProcessHeap(), 0, buffer); |
| 3006 | } |
| 3007 | if (!env) return NULL; |
Stefan Leichter | ca1661c | 2000-11-06 05:26:00 +0000 | [diff] [blame] | 3008 | |
Detlef Riekenberg | 6c233ef | 2006-05-11 23:59:17 +0200 | [diff] [blame] | 3009 | buffer = HeapAlloc( GetProcessHeap(), 0, |
| 3010 | (strlenW(DriversW) + strlenW(env->envname) + |
| 3011 | strlenW(env->versionregpath) + 1) * sizeof(WCHAR)); |
| 3012 | if(buffer) { |
| 3013 | wsprintfW(buffer, DriversW, env->envname, env->versionregpath); |
| 3014 | RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval); |
| 3015 | HeapFree(GetProcessHeap(), 0, buffer); |
| 3016 | } |
Stefan Leichter | ca1661c | 2000-11-06 05:26:00 +0000 | [diff] [blame] | 3017 | return retval; |
| 3018 | } |
| 3019 | |
| 3020 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3021 | * AddPrinterW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3022 | */ |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3023 | HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3024 | { |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3025 | PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter; |
| 3026 | LPDEVMODEA dmA; |
| 3027 | LPDEVMODEW dmW; |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3028 | HANDLE retval; |
| 3029 | HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3030 | LONG size; |
Andrew Talbot | 54d578b | 2007-02-27 23:06:30 +0000 | [diff] [blame] | 3031 | static const WCHAR attributesW[] = {'A','t','t','r','i','b','u','t','e','s',0}, |
| 3032 | default_devmodeW[] = {'D','e','f','a','u','l','t',' ','D','e','v','M','o','d','e',0}, |
| 3033 | priorityW[] = {'P','r','i','o','r','i','t','y',0}, |
| 3034 | start_timeW[] = {'S','t','a','r','t','T','i','m','e',0}, |
| 3035 | statusW[] = {'S','t','a','t','u','s',0}, |
| 3036 | until_timeW[] = {'U','n','t','i','l','T','i','m','e',0}; |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3037 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3038 | TRACE("(%s,%d,%p)\n", debugstr_w(pName), Level, pPrinter); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 3039 | |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3040 | if(pName != NULL) { |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 3041 | ERR("pName = %s - unsupported\n", debugstr_w(pName)); |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3042 | SetLastError(ERROR_INVALID_PARAMETER); |
| 3043 | return 0; |
| 3044 | } |
| 3045 | if(Level != 2) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3046 | ERR("Level = %d, unsupported!\n", Level); |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3047 | SetLastError(ERROR_INVALID_LEVEL); |
| 3048 | return 0; |
| 3049 | } |
| 3050 | if(!pPrinter) { |
| 3051 | SetLastError(ERROR_INVALID_PARAMETER); |
| 3052 | return 0; |
| 3053 | } |
Detlef Riekenberg | 358ce06 | 2006-05-21 14:35:29 +0200 | [diff] [blame] | 3054 | if(RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) != |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3055 | ERROR_SUCCESS) { |
| 3056 | ERR("Can't create Printers key\n"); |
| 3057 | return 0; |
| 3058 | } |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 3059 | if(!RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter)) { |
Andrew Talbot | 54d578b | 2007-02-27 23:06:30 +0000 | [diff] [blame] | 3060 | if (!RegQueryValueW(hkeyPrinter, attributesW, NULL, NULL)) { |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 3061 | SetLastError(ERROR_PRINTER_ALREADY_EXISTS); |
| 3062 | RegCloseKey(hkeyPrinter); |
| 3063 | RegCloseKey(hkeyPrinters); |
| 3064 | return 0; |
| 3065 | } |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3066 | RegCloseKey(hkeyPrinter); |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3067 | } |
Stefan Leichter | ca1661c | 2000-11-06 05:26:00 +0000 | [diff] [blame] | 3068 | hkeyDrivers = WINSPOOL_OpenDriverReg( NULL, TRUE); |
| 3069 | if(!hkeyDrivers) { |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3070 | ERR("Can't create Drivers key\n"); |
| 3071 | RegCloseKey(hkeyPrinters); |
| 3072 | return 0; |
| 3073 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 3074 | if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) != |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3075 | ERROR_SUCCESS) { |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3076 | WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName)); |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3077 | RegCloseKey(hkeyPrinters); |
| 3078 | RegCloseKey(hkeyDrivers); |
| 3079 | SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); |
| 3080 | return 0; |
| 3081 | } |
| 3082 | RegCloseKey(hkeyDriver); |
| 3083 | RegCloseKey(hkeyDrivers); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3084 | |
| 3085 | if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) { /* FIXME */ |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 3086 | FIXME("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor)); |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3087 | SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR); |
| 3088 | RegCloseKey(hkeyPrinters); |
| 3089 | return 0; |
| 3090 | } |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3091 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3092 | if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) != |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3093 | ERROR_SUCCESS) { |
Marcus Meissner | ab8b7db | 2001-04-27 18:02:46 +0000 | [diff] [blame] | 3094 | FIXME("Can't create printer %s\n", debugstr_w(pi->pPrinterName)); |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3095 | SetLastError(ERROR_INVALID_PRINTER_NAME); |
| 3096 | RegCloseKey(hkeyPrinters); |
| 3097 | return 0; |
| 3098 | } |
Andrew Talbot | 54d578b | 2007-02-27 23:06:30 +0000 | [diff] [blame] | 3099 | RegSetValueExW(hkeyPrinter, attributesW, 0, REG_DWORD, |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3100 | (LPBYTE)&pi->Attributes, sizeof(DWORD)); |
Gerard Patel | 14c9429 | 2001-10-28 21:16:38 +0000 | [diff] [blame] | 3101 | set_reg_szW(hkeyPrinter, DatatypeW, pi->pDatatype); |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 3102 | |
| 3103 | /* See if we can load the driver. We may need the devmode structure anyway |
| 3104 | * |
| 3105 | * FIXME: |
| 3106 | * Note that DocumentPropertiesW will briefly try to open the printer we |
| 3107 | * just create to find a DEVMODEA struct (it will use the WINEPS default |
| 3108 | * one in case it is not there, so we are ok). |
| 3109 | */ |
Alexandre Julliard | 613ead7 | 2002-10-04 00:27:10 +0000 | [diff] [blame] | 3110 | size = DocumentPropertiesW(0, 0, pi->pPrinterName, NULL, NULL, 0); |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 3111 | |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 3112 | if(size < 0) { |
Francois Gouget | 42c4114 | 2007-01-18 11:37:51 +0100 | [diff] [blame] | 3113 | FIXME("DocumentPropertiesW on printer %s fails\n", debugstr_w(pi->pPrinterName)); |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 3114 | size = sizeof(DEVMODEW); |
| 3115 | } |
| 3116 | if(pi->pDevMode) |
| 3117 | dmW = pi->pDevMode; |
Michael Stefaniuc | 5f62da1 | 2007-04-25 00:57:55 +0200 | [diff] [blame] | 3118 | else |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 3119 | { |
Michael Stefaniuc | 5f62da1 | 2007-04-25 00:57:55 +0200 | [diff] [blame] | 3120 | dmW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); |
Huw Davies | 7afe18e | 2006-06-15 11:36:00 +0100 | [diff] [blame] | 3121 | dmW->dmSize = size; |
| 3122 | if (0>DocumentPropertiesW(0,0,pi->pPrinterName,dmW,NULL,DM_OUT_BUFFER)) |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 3123 | { |
Francois Gouget | 42c4114 | 2007-01-18 11:37:51 +0100 | [diff] [blame] | 3124 | WARN("DocumentPropertiesW on printer %s failed!\n", debugstr_w(pi->pPrinterName)); |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 3125 | HeapFree(GetProcessHeap(),0,dmW); |
| 3126 | dmW=NULL; |
Huw Davies | 7afe18e | 2006-06-15 11:36:00 +0100 | [diff] [blame] | 3127 | } |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 3128 | else |
| 3129 | { |
Huw Davies | 7afe18e | 2006-06-15 11:36:00 +0100 | [diff] [blame] | 3130 | /* set devmode to printer name */ |
| 3131 | lstrcpynW(dmW->dmDeviceName, pi->pPrinterName, CCHDEVICENAME); |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 3132 | } |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 3133 | } |
| 3134 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3135 | /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does |
| 3136 | and we support these drivers. NT writes DEVMODEW so somehow |
| 3137 | we'll need to distinguish between these when we support NT |
| 3138 | drivers */ |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 3139 | if (dmW) |
| 3140 | { |
Detlef Riekenberg | 741fa21 | 2008-03-09 00:38:49 +0100 | [diff] [blame] | 3141 | dmA = DEVMODEdupWtoA(dmW); |
Andrew Talbot | 54d578b | 2007-02-27 23:06:30 +0000 | [diff] [blame] | 3142 | RegSetValueExW(hkeyPrinter, default_devmodeW, 0, REG_BINARY, |
Huw Davies | 6694ce9 | 2003-06-23 19:52:55 +0000 | [diff] [blame] | 3143 | (LPBYTE)dmA, dmA->dmSize + dmA->dmDriverExtra); |
| 3144 | HeapFree(GetProcessHeap(), 0, dmA); |
| 3145 | if(!pi->pDevMode) |
| 3146 | HeapFree(GetProcessHeap(), 0, dmW); |
| 3147 | } |
Gerard Patel | 14c9429 | 2001-10-28 21:16:38 +0000 | [diff] [blame] | 3148 | set_reg_szW(hkeyPrinter, DescriptionW, pi->pComment); |
| 3149 | set_reg_szW(hkeyPrinter, LocationW, pi->pLocation); |
| 3150 | set_reg_szW(hkeyPrinter, NameW, pi->pPrinterName); |
| 3151 | set_reg_szW(hkeyPrinter, ParametersW, pi->pParameters); |
| 3152 | |
| 3153 | set_reg_szW(hkeyPrinter, PortW, pi->pPortName); |
| 3154 | set_reg_szW(hkeyPrinter, Print_ProcessorW, pi->pPrintProcessor); |
| 3155 | set_reg_szW(hkeyPrinter, Printer_DriverW, pi->pDriverName); |
Andrew Talbot | 54d578b | 2007-02-27 23:06:30 +0000 | [diff] [blame] | 3156 | RegSetValueExW(hkeyPrinter, priorityW, 0, REG_DWORD, |
| 3157 | (LPBYTE)&pi->Priority, sizeof(DWORD)); |
Gerard Patel | 14c9429 | 2001-10-28 21:16:38 +0000 | [diff] [blame] | 3158 | set_reg_szW(hkeyPrinter, Separator_FileW, pi->pSepFile); |
| 3159 | set_reg_szW(hkeyPrinter, Share_NameW, pi->pShareName); |
Andrew Talbot | 54d578b | 2007-02-27 23:06:30 +0000 | [diff] [blame] | 3160 | RegSetValueExW(hkeyPrinter, start_timeW, 0, REG_DWORD, |
| 3161 | (LPBYTE)&pi->StartTime, sizeof(DWORD)); |
| 3162 | RegSetValueExW(hkeyPrinter, statusW, 0, REG_DWORD, |
| 3163 | (LPBYTE)&pi->Status, sizeof(DWORD)); |
| 3164 | RegSetValueExW(hkeyPrinter, until_timeW, 0, REG_DWORD, |
| 3165 | (LPBYTE)&pi->UntilTime, sizeof(DWORD)); |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3166 | |
| 3167 | RegCloseKey(hkeyPrinter); |
| 3168 | RegCloseKey(hkeyPrinters); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3169 | if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) { |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 3170 | ERR("OpenPrinter failing\n"); |
| 3171 | return 0; |
| 3172 | } |
| 3173 | return retval; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3174 | } |
| 3175 | |
| 3176 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3177 | * AddPrinterA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3178 | */ |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3179 | HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3180 | { |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 3181 | UNICODE_STRING pNameW; |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 3182 | PWSTR pwstrNameW; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3183 | PRINTER_INFO_2W *piW; |
| 3184 | PRINTER_INFO_2A *piA = (PRINTER_INFO_2A*)pPrinter; |
| 3185 | HANDLE ret; |
| 3186 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3187 | TRACE("(%s,%d,%p): stub\n", debugstr_a(pName), Level, pPrinter); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3188 | if(Level != 2) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3189 | ERR("Level = %d, unsupported!\n", Level); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3190 | SetLastError(ERROR_INVALID_LEVEL); |
| 3191 | return 0; |
| 3192 | } |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 3193 | pwstrNameW = asciitounicode(&pNameW,pName); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3194 | piW = PRINTER_INFO_2AtoW(GetProcessHeap(), piA); |
| 3195 | |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 3196 | ret = AddPrinterW(pwstrNameW, Level, (LPBYTE)piW); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3197 | |
| 3198 | FREE_PRINTER_INFO_2W(GetProcessHeap(), piW); |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 3199 | RtlFreeUnicodeString(&pNameW); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3200 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3201 | } |
| 3202 | |
| 3203 | |
| 3204 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3205 | * ClosePrinter [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3206 | */ |
| 3207 | BOOL WINAPI ClosePrinter(HANDLE hPrinter) |
| 3208 | { |
Kevin Koltzau | 7d8e377 | 2005-09-29 13:34:34 +0000 | [diff] [blame] | 3209 | UINT_PTR i = (UINT_PTR)hPrinter; |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 3210 | opened_printer_t *printer = NULL; |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 3211 | BOOL ret = FALSE; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3212 | |
Detlef Riekenberg | 619621d | 2007-01-15 05:38:22 +0100 | [diff] [blame] | 3213 | TRACE("(%p)\n", hPrinter); |
Thuy Nguyen | 6374cd2 | 1999-08-15 16:34:22 +0000 | [diff] [blame] | 3214 | |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 3215 | EnterCriticalSection(&printer_handles_cs); |
| 3216 | |
| 3217 | if ((i > 0) && (i <= nb_printer_handles)) |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 3218 | printer = printer_handles[i - 1]; |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 3219 | |
Detlef Riekenberg | 619621d | 2007-01-15 05:38:22 +0100 | [diff] [blame] | 3220 | |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 3221 | if(printer) |
| 3222 | { |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 3223 | struct list *cursor, *cursor2; |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 3224 | |
Detlef Riekenberg | 619621d | 2007-01-15 05:38:22 +0100 | [diff] [blame] | 3225 | TRACE("%p: %s (hXcv: %p) for %s (doc: %p)\n", printer->pm, |
| 3226 | debugstr_w(printer->pm ? printer->pm->dllname : NULL), |
| 3227 | printer->hXcv, debugstr_w(printer->name), printer->doc ); |
| 3228 | |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 3229 | if(printer->doc) |
| 3230 | EndDocPrinter(hPrinter); |
| 3231 | |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 3232 | if(InterlockedDecrement(&printer->queue->ref) == 0) |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 3233 | { |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 3234 | LIST_FOR_EACH_SAFE(cursor, cursor2, &printer->queue->jobs) |
| 3235 | { |
| 3236 | job_t *job = LIST_ENTRY(cursor, job_t, entry); |
| 3237 | ScheduleJob(hPrinter, job->job_id); |
| 3238 | } |
| 3239 | HeapFree(GetProcessHeap(), 0, printer->queue); |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 3240 | } |
Detlef Riekenberg | 72b126b | 2007-01-05 01:09:46 +0100 | [diff] [blame] | 3241 | if (printer->hXcv) printer->pm->monitor->pfnXcvClosePort(printer->hXcv); |
Detlef Riekenberg | f85b02b | 2007-01-05 01:09:13 +0100 | [diff] [blame] | 3242 | monitor_unload(printer->pm); |
Detlef Riekenberg | 58d1e2f | 2007-01-05 01:09:02 +0100 | [diff] [blame] | 3243 | HeapFree(GetProcessHeap(), 0, printer->printername); |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 3244 | HeapFree(GetProcessHeap(), 0, printer->name); |
| 3245 | HeapFree(GetProcessHeap(), 0, printer); |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 3246 | printer_handles[i - 1] = NULL; |
| 3247 | ret = TRUE; |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 3248 | } |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 3249 | LeaveCriticalSection(&printer_handles_cs); |
| 3250 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3251 | } |
| 3252 | |
| 3253 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3254 | * DeleteFormA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3255 | */ |
| 3256 | BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName) |
| 3257 | { |
Michael Stefaniuc | ea335dd | 2002-10-22 00:47:33 +0000 | [diff] [blame] | 3258 | FIXME("(%p,%s): stub\n", hPrinter, pFormName); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3259 | return 1; |
| 3260 | } |
| 3261 | |
| 3262 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3263 | * DeleteFormW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3264 | */ |
| 3265 | BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName) |
| 3266 | { |
Michael Stefaniuc | ea335dd | 2002-10-22 00:47:33 +0000 | [diff] [blame] | 3267 | FIXME("(%p,%s): stub\n", hPrinter, debugstr_w(pFormName)); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3268 | return 1; |
| 3269 | } |
| 3270 | |
| 3271 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3272 | * DeletePrinter [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3273 | */ |
| 3274 | BOOL WINAPI DeletePrinter(HANDLE hPrinter) |
| 3275 | { |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 3276 | LPCWSTR lpNameW = get_opened_printer_name(hPrinter); |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 3277 | HKEY hkeyPrinters, hkey; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3278 | |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 3279 | if(!lpNameW) { |
| 3280 | SetLastError(ERROR_INVALID_HANDLE); |
| 3281 | return FALSE; |
| 3282 | } |
Detlef Riekenberg | 358ce06 | 2006-05-21 14:35:29 +0200 | [diff] [blame] | 3283 | if(RegOpenKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) == ERROR_SUCCESS) { |
Stefan Leichter | 06b64a1 | 2007-06-05 18:47:17 +0200 | [diff] [blame] | 3284 | RegDeleteTreeW(hkeyPrinters, lpNameW); |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 3285 | RegCloseKey(hkeyPrinters); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3286 | } |
Huw Davies | 4b0fc2e | 2003-11-05 00:36:47 +0000 | [diff] [blame] | 3287 | WriteProfileStringW(devicesW, lpNameW, NULL); |
Detlef Riekenberg | 473717f | 2008-05-06 20:26:05 +0200 | [diff] [blame] | 3288 | WriteProfileStringW(PrinterPortsW, lpNameW, NULL); |
| 3289 | |
Huw Davies | 3d0b22b | 2005-03-31 10:06:46 +0000 | [diff] [blame] | 3290 | if(RegCreateKeyW(HKEY_CURRENT_USER, user_printers_reg_key, &hkey) == ERROR_SUCCESS) { |
| 3291 | RegDeleteValueW(hkey, lpNameW); |
| 3292 | RegCloseKey(hkey); |
| 3293 | } |
Detlef Riekenberg | 473717f | 2008-05-06 20:26:05 +0200 | [diff] [blame] | 3294 | |
| 3295 | if(RegCreateKeyW(HKEY_CURRENT_USER, WinNT_CV_PrinterPortsW, &hkey) == ERROR_SUCCESS) { |
| 3296 | RegDeleteValueW(hkey, lpNameW); |
| 3297 | RegCloseKey(hkey); |
| 3298 | } |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3299 | return TRUE; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3300 | } |
| 3301 | |
| 3302 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3303 | * SetPrinterA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3304 | */ |
| 3305 | BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, |
| 3306 | DWORD Command) |
| 3307 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3308 | FIXME("(%p,%d,%p,%d): stub\n",hPrinter,Level,pPrinter,Command); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3309 | return FALSE; |
| 3310 | } |
| 3311 | |
| 3312 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3313 | * SetJobA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3314 | */ |
| 3315 | BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 3316 | LPBYTE pJob, DWORD Command) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3317 | { |
Huw Davies | f675a78 | 2005-07-12 19:19:09 +0000 | [diff] [blame] | 3318 | BOOL ret; |
| 3319 | LPBYTE JobW; |
| 3320 | UNICODE_STRING usBuffer; |
| 3321 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3322 | TRACE("(%p, %d, %d, %p, %d)\n",hPrinter, JobId, Level, pJob, Command); |
Huw Davies | f675a78 | 2005-07-12 19:19:09 +0000 | [diff] [blame] | 3323 | |
| 3324 | /* JobId, pPrinterName, pMachineName, pDriverName, Size, Submitted, Time and TotalPages |
| 3325 | are all ignored by SetJob, so we don't bother copying them */ |
| 3326 | switch(Level) |
| 3327 | { |
| 3328 | case 0: |
| 3329 | JobW = NULL; |
| 3330 | break; |
| 3331 | case 1: |
| 3332 | { |
| 3333 | JOB_INFO_1W *info1W = HeapAlloc(GetProcessHeap(), 0, sizeof(*info1W)); |
| 3334 | JOB_INFO_1A *info1A = (JOB_INFO_1A*)pJob; |
| 3335 | |
| 3336 | JobW = (LPBYTE)info1W; |
| 3337 | info1W->pUserName = asciitounicode(&usBuffer, info1A->pUserName); |
| 3338 | info1W->pDocument = asciitounicode(&usBuffer, info1A->pDocument); |
| 3339 | info1W->pDatatype = asciitounicode(&usBuffer, info1A->pDatatype); |
| 3340 | info1W->pStatus = asciitounicode(&usBuffer, info1A->pStatus); |
| 3341 | info1W->Status = info1A->Status; |
| 3342 | info1W->Priority = info1A->Priority; |
| 3343 | info1W->Position = info1A->Position; |
| 3344 | info1W->PagesPrinted = info1A->PagesPrinted; |
| 3345 | break; |
| 3346 | } |
| 3347 | case 2: |
| 3348 | { |
| 3349 | JOB_INFO_2W *info2W = HeapAlloc(GetProcessHeap(), 0, sizeof(*info2W)); |
| 3350 | JOB_INFO_2A *info2A = (JOB_INFO_2A*)pJob; |
| 3351 | |
| 3352 | JobW = (LPBYTE)info2W; |
| 3353 | info2W->pUserName = asciitounicode(&usBuffer, info2A->pUserName); |
| 3354 | info2W->pDocument = asciitounicode(&usBuffer, info2A->pDocument); |
| 3355 | info2W->pNotifyName = asciitounicode(&usBuffer, info2A->pNotifyName); |
| 3356 | info2W->pDatatype = asciitounicode(&usBuffer, info2A->pDatatype); |
| 3357 | info2W->pPrintProcessor = asciitounicode(&usBuffer, info2A->pPrintProcessor); |
| 3358 | info2W->pParameters = asciitounicode(&usBuffer, info2A->pParameters); |
| 3359 | info2W->pDevMode = info2A->pDevMode ? GdiConvertToDevmodeW(info2A->pDevMode) : NULL; |
| 3360 | info2W->pStatus = asciitounicode(&usBuffer, info2A->pStatus); |
| 3361 | info2W->pSecurityDescriptor = info2A->pSecurityDescriptor; |
| 3362 | info2W->Status = info2A->Status; |
| 3363 | info2W->Priority = info2A->Priority; |
| 3364 | info2W->Position = info2A->Position; |
| 3365 | info2W->StartTime = info2A->StartTime; |
| 3366 | info2W->UntilTime = info2A->UntilTime; |
| 3367 | info2W->PagesPrinted = info2A->PagesPrinted; |
| 3368 | break; |
| 3369 | } |
| 3370 | case 3: |
| 3371 | JobW = HeapAlloc(GetProcessHeap(), 0, sizeof(JOB_INFO_3)); |
| 3372 | memcpy(JobW, pJob, sizeof(JOB_INFO_3)); |
| 3373 | break; |
| 3374 | default: |
| 3375 | SetLastError(ERROR_INVALID_LEVEL); |
| 3376 | return FALSE; |
| 3377 | } |
| 3378 | |
| 3379 | ret = SetJobW(hPrinter, JobId, Level, JobW, Command); |
| 3380 | |
| 3381 | switch(Level) |
| 3382 | { |
| 3383 | case 1: |
| 3384 | { |
| 3385 | JOB_INFO_1W *info1W = (JOB_INFO_1W*)JobW; |
| 3386 | HeapFree(GetProcessHeap(), 0, info1W->pUserName); |
| 3387 | HeapFree(GetProcessHeap(), 0, info1W->pDocument); |
| 3388 | HeapFree(GetProcessHeap(), 0, info1W->pDatatype); |
| 3389 | HeapFree(GetProcessHeap(), 0, info1W->pStatus); |
| 3390 | break; |
| 3391 | } |
| 3392 | case 2: |
| 3393 | { |
| 3394 | JOB_INFO_2W *info2W = (JOB_INFO_2W*)JobW; |
| 3395 | HeapFree(GetProcessHeap(), 0, info2W->pUserName); |
| 3396 | HeapFree(GetProcessHeap(), 0, info2W->pDocument); |
| 3397 | HeapFree(GetProcessHeap(), 0, info2W->pNotifyName); |
| 3398 | HeapFree(GetProcessHeap(), 0, info2W->pDatatype); |
| 3399 | HeapFree(GetProcessHeap(), 0, info2W->pPrintProcessor); |
| 3400 | HeapFree(GetProcessHeap(), 0, info2W->pParameters); |
| 3401 | HeapFree(GetProcessHeap(), 0, info2W->pDevMode); |
| 3402 | HeapFree(GetProcessHeap(), 0, info2W->pStatus); |
| 3403 | break; |
| 3404 | } |
| 3405 | } |
| 3406 | HeapFree(GetProcessHeap(), 0, JobW); |
| 3407 | |
| 3408 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3409 | } |
| 3410 | |
| 3411 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3412 | * SetJobW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3413 | */ |
| 3414 | BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 3415 | LPBYTE pJob, DWORD Command) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3416 | { |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 3417 | BOOL ret = FALSE; |
| 3418 | job_t *job; |
| 3419 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3420 | TRACE("(%p, %d, %d, %p, %d)\n", hPrinter, JobId, Level, pJob, Command); |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 3421 | FIXME("Ignoring everything other than document title\n"); |
| 3422 | |
| 3423 | EnterCriticalSection(&printer_handles_cs); |
| 3424 | job = get_job(hPrinter, JobId); |
| 3425 | if(!job) |
| 3426 | goto end; |
| 3427 | |
| 3428 | switch(Level) |
| 3429 | { |
| 3430 | case 0: |
| 3431 | break; |
| 3432 | case 1: |
| 3433 | { |
| 3434 | JOB_INFO_1W *info1 = (JOB_INFO_1W*)pJob; |
| 3435 | HeapFree(GetProcessHeap(), 0, job->document_title); |
| 3436 | job->document_title = strdupW(info1->pDocument); |
| 3437 | break; |
| 3438 | } |
| 3439 | case 2: |
| 3440 | { |
| 3441 | JOB_INFO_2W *info2 = (JOB_INFO_2W*)pJob; |
| 3442 | HeapFree(GetProcessHeap(), 0, job->document_title); |
| 3443 | job->document_title = strdupW(info2->pDocument); |
| 3444 | break; |
| 3445 | } |
| 3446 | case 3: |
| 3447 | break; |
| 3448 | default: |
| 3449 | SetLastError(ERROR_INVALID_LEVEL); |
| 3450 | goto end; |
| 3451 | } |
| 3452 | ret = TRUE; |
| 3453 | end: |
| 3454 | LeaveCriticalSection(&printer_handles_cs); |
| 3455 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3456 | } |
| 3457 | |
| 3458 | /***************************************************************************** |
Dimitrie O. Paun | 6d267e9 | 2002-12-17 21:00:38 +0000 | [diff] [blame] | 3459 | * EndDocPrinter [WINSPOOL.@] |
| 3460 | */ |
| 3461 | BOOL WINAPI EndDocPrinter(HANDLE hPrinter) |
| 3462 | { |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 3463 | opened_printer_t *printer; |
| 3464 | BOOL ret = FALSE; |
| 3465 | TRACE("(%p)\n", hPrinter); |
| 3466 | |
| 3467 | EnterCriticalSection(&printer_handles_cs); |
| 3468 | |
| 3469 | printer = get_opened_printer(hPrinter); |
| 3470 | if(!printer) |
| 3471 | { |
| 3472 | SetLastError(ERROR_INVALID_HANDLE); |
| 3473 | goto end; |
| 3474 | } |
| 3475 | |
| 3476 | if(!printer->doc) |
| 3477 | { |
| 3478 | SetLastError(ERROR_SPL_NO_STARTDOC); |
| 3479 | goto end; |
| 3480 | } |
| 3481 | |
| 3482 | CloseHandle(printer->doc->hf); |
| 3483 | ScheduleJob(hPrinter, printer->doc->job_id); |
| 3484 | HeapFree(GetProcessHeap(), 0, printer->doc); |
| 3485 | printer->doc = NULL; |
| 3486 | ret = TRUE; |
| 3487 | end: |
| 3488 | LeaveCriticalSection(&printer_handles_cs); |
| 3489 | return ret; |
Dimitrie O. Paun | 6d267e9 | 2002-12-17 21:00:38 +0000 | [diff] [blame] | 3490 | } |
| 3491 | |
| 3492 | /***************************************************************************** |
| 3493 | * EndPagePrinter [WINSPOOL.@] |
| 3494 | */ |
| 3495 | BOOL WINAPI EndPagePrinter(HANDLE hPrinter) |
| 3496 | { |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 3497 | FIXME("(%p): stub\n", hPrinter); |
| 3498 | return TRUE; |
Dimitrie O. Paun | 6d267e9 | 2002-12-17 21:00:38 +0000 | [diff] [blame] | 3499 | } |
| 3500 | |
| 3501 | /***************************************************************************** |
| 3502 | * StartDocPrinterA [WINSPOOL.@] |
| 3503 | */ |
| 3504 | DWORD WINAPI StartDocPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo) |
| 3505 | { |
Huw Davies | d830266 | 2005-06-30 18:10:59 +0000 | [diff] [blame] | 3506 | UNICODE_STRING usBuffer; |
| 3507 | DOC_INFO_2W doc2W; |
| 3508 | DOC_INFO_2A *doc2 = (DOC_INFO_2A*)pDocInfo; |
| 3509 | DWORD ret; |
| 3510 | |
| 3511 | /* DOC_INFO_1, 2 and 3 all have the strings in the same place with either two (DOC_INFO_2) |
| 3512 | or one (DOC_INFO_3) extra DWORDs */ |
| 3513 | |
| 3514 | switch(Level) { |
| 3515 | case 2: |
| 3516 | doc2W.JobId = doc2->JobId; |
| 3517 | /* fall through */ |
| 3518 | case 3: |
| 3519 | doc2W.dwMode = doc2->dwMode; |
| 3520 | /* fall through */ |
| 3521 | case 1: |
| 3522 | doc2W.pDocName = asciitounicode(&usBuffer, doc2->pDocName); |
| 3523 | doc2W.pOutputFile = asciitounicode(&usBuffer, doc2->pOutputFile); |
| 3524 | doc2W.pDatatype = asciitounicode(&usBuffer, doc2->pDatatype); |
| 3525 | break; |
| 3526 | |
| 3527 | default: |
| 3528 | SetLastError(ERROR_INVALID_LEVEL); |
| 3529 | return FALSE; |
| 3530 | } |
| 3531 | |
| 3532 | ret = StartDocPrinterW(hPrinter, Level, (LPBYTE)&doc2W); |
| 3533 | |
| 3534 | HeapFree(GetProcessHeap(), 0, doc2W.pDatatype); |
| 3535 | HeapFree(GetProcessHeap(), 0, doc2W.pOutputFile); |
| 3536 | HeapFree(GetProcessHeap(), 0, doc2W.pDocName); |
| 3537 | |
| 3538 | return ret; |
Dimitrie O. Paun | 6d267e9 | 2002-12-17 21:00:38 +0000 | [diff] [blame] | 3539 | } |
| 3540 | |
| 3541 | /***************************************************************************** |
| 3542 | * StartDocPrinterW [WINSPOOL.@] |
| 3543 | */ |
| 3544 | DWORD WINAPI StartDocPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo) |
| 3545 | { |
Huw Davies | d830266 | 2005-06-30 18:10:59 +0000 | [diff] [blame] | 3546 | DOC_INFO_2W *doc = (DOC_INFO_2W *)pDocInfo; |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 3547 | opened_printer_t *printer; |
| 3548 | BYTE addjob_buf[MAX_PATH * sizeof(WCHAR) + sizeof(ADDJOB_INFO_1W)]; |
| 3549 | ADDJOB_INFO_1W *addjob = (ADDJOB_INFO_1W*) addjob_buf; |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 3550 | JOB_INFO_1W job_info; |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 3551 | DWORD needed, ret = 0; |
| 3552 | HANDLE hf; |
| 3553 | WCHAR *filename; |
Huw Davies | d830266 | 2005-06-30 18:10:59 +0000 | [diff] [blame] | 3554 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3555 | TRACE("(hPrinter = %p, Level = %d, pDocInfo = %p {pDocName = %s, pOutputFile = %s, pDatatype = %s}):\n", |
Huw Davies | d830266 | 2005-06-30 18:10:59 +0000 | [diff] [blame] | 3556 | hPrinter, Level, doc, debugstr_w(doc->pDocName), debugstr_w(doc->pOutputFile), |
| 3557 | debugstr_w(doc->pDatatype)); |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 3558 | |
| 3559 | if(Level < 1 || Level > 3) |
| 3560 | { |
| 3561 | SetLastError(ERROR_INVALID_LEVEL); |
| 3562 | return 0; |
| 3563 | } |
| 3564 | |
| 3565 | EnterCriticalSection(&printer_handles_cs); |
| 3566 | printer = get_opened_printer(hPrinter); |
| 3567 | if(!printer) |
| 3568 | { |
| 3569 | SetLastError(ERROR_INVALID_HANDLE); |
| 3570 | goto end; |
| 3571 | } |
| 3572 | |
| 3573 | if(printer->doc) |
| 3574 | { |
| 3575 | SetLastError(ERROR_INVALID_PRINTER_STATE); |
| 3576 | goto end; |
| 3577 | } |
| 3578 | |
| 3579 | /* Even if we're printing to a file we still add a print job, we'll |
| 3580 | just ignore the spool file name */ |
| 3581 | |
| 3582 | if(!AddJobW(hPrinter, 1, addjob_buf, sizeof(addjob_buf), &needed)) |
| 3583 | { |
Francois Gouget | 42c4114 | 2007-01-18 11:37:51 +0100 | [diff] [blame] | 3584 | ERR("AddJob failed gle %u\n", GetLastError()); |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 3585 | goto end; |
| 3586 | } |
| 3587 | |
| 3588 | if(doc->pOutputFile) |
| 3589 | filename = doc->pOutputFile; |
| 3590 | else |
| 3591 | filename = addjob->Path; |
| 3592 | |
| 3593 | hf = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
| 3594 | if(hf == INVALID_HANDLE_VALUE) |
| 3595 | goto end; |
| 3596 | |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 3597 | memset(&job_info, 0, sizeof(job_info)); |
| 3598 | job_info.pDocument = doc->pDocName; |
| 3599 | SetJobW(hPrinter, addjob->JobId, 1, (LPBYTE)&job_info, 0); |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 3600 | |
| 3601 | printer->doc = HeapAlloc(GetProcessHeap(), 0, sizeof(*printer->doc)); |
| 3602 | printer->doc->hf = hf; |
| 3603 | ret = printer->doc->job_id = addjob->JobId; |
| 3604 | end: |
| 3605 | LeaveCriticalSection(&printer_handles_cs); |
| 3606 | |
| 3607 | return ret; |
Dimitrie O. Paun | 6d267e9 | 2002-12-17 21:00:38 +0000 | [diff] [blame] | 3608 | } |
| 3609 | |
| 3610 | /***************************************************************************** |
| 3611 | * StartPagePrinter [WINSPOOL.@] |
| 3612 | */ |
| 3613 | BOOL WINAPI StartPagePrinter(HANDLE hPrinter) |
| 3614 | { |
Huw Davies | 6fd3c47 | 2005-07-08 14:19:18 +0000 | [diff] [blame] | 3615 | FIXME("(%p): stub\n", hPrinter); |
| 3616 | return TRUE; |
Dimitrie O. Paun | 6d267e9 | 2002-12-17 21:00:38 +0000 | [diff] [blame] | 3617 | } |
| 3618 | |
| 3619 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3620 | * GetFormA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3621 | */ |
| 3622 | BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level, |
| 3623 | LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded) |
| 3624 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3625 | FIXME("(%p,%s,%d,%p,%d,%p): stub\n",hPrinter,pFormName, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 3626 | Level,pForm,cbBuf,pcbNeeded); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3627 | return FALSE; |
| 3628 | } |
| 3629 | |
| 3630 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3631 | * GetFormW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3632 | */ |
| 3633 | BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level, |
| 3634 | LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded) |
| 3635 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3636 | FIXME("(%p,%s,%d,%p,%d,%p): stub\n",hPrinter, |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3637 | debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded); |
| 3638 | return FALSE; |
| 3639 | } |
| 3640 | |
| 3641 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3642 | * SetFormA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3643 | */ |
| 3644 | BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level, |
| 3645 | LPBYTE pForm) |
| 3646 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3647 | FIXME("(%p,%s,%d,%p): stub\n",hPrinter,pFormName,Level,pForm); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3648 | return FALSE; |
| 3649 | } |
| 3650 | |
| 3651 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3652 | * SetFormW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3653 | */ |
| 3654 | BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level, |
| 3655 | LPBYTE pForm) |
| 3656 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3657 | FIXME("(%p,%p,%d,%p): stub\n",hPrinter,pFormName,Level,pForm); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3658 | return FALSE; |
| 3659 | } |
| 3660 | |
| 3661 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3662 | * ReadPrinter [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3663 | */ |
| 3664 | BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, |
| 3665 | LPDWORD pNoBytesRead) |
| 3666 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3667 | FIXME("(%p,%p,%d,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3668 | return FALSE; |
| 3669 | } |
| 3670 | |
| 3671 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3672 | * ResetPrinterA [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3673 | */ |
| 3674 | BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault) |
| 3675 | { |
Michael Stefaniuc | ea335dd | 2002-10-22 00:47:33 +0000 | [diff] [blame] | 3676 | FIXME("(%p, %p): stub\n", hPrinter, pDefault); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3677 | return FALSE; |
| 3678 | } |
| 3679 | |
| 3680 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 3681 | * ResetPrinterW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3682 | */ |
| 3683 | BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault) |
| 3684 | { |
Michael Stefaniuc | ea335dd | 2002-10-22 00:47:33 +0000 | [diff] [blame] | 3685 | FIXME("(%p, %p): stub\n", hPrinter, pDefault); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 3686 | return FALSE; |
| 3687 | } |
| 3688 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3689 | /***************************************************************************** |
| 3690 | * WINSPOOL_GetDWORDFromReg |
| 3691 | * |
| 3692 | * Return DWORD associated with ValueName from hkey. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 3693 | */ |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3694 | static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName) |
| 3695 | { |
| 3696 | DWORD sz = sizeof(DWORD), type, value = 0; |
| 3697 | LONG ret; |
| 3698 | |
| 3699 | ret = RegQueryValueExA(hkey, ValueName, 0, &type, (LPBYTE)&value, &sz); |
| 3700 | |
| 3701 | if(ret != ERROR_SUCCESS) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3702 | WARN("Got ret = %d on name %s\n", ret, ValueName); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3703 | return 0; |
| 3704 | } |
| 3705 | if(type != REG_DWORD) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3706 | ERR("Got type %d\n", type); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3707 | return 0; |
| 3708 | } |
| 3709 | return value; |
| 3710 | } |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 3711 | |
Detlef Riekenberg | 4b53154 | 2007-07-26 23:05:27 +0200 | [diff] [blame] | 3712 | |
| 3713 | /***************************************************************************** |
| 3714 | * get_filename_from_reg [internal] |
| 3715 | * |
| 3716 | * Get ValueName from hkey storing result in out |
| 3717 | * when the Value in the registry has only a filename, use driverdir as prefix |
| 3718 | * outlen is space left in out |
| 3719 | * String is stored either as unicode or ascii |
| 3720 | * |
| 3721 | */ |
| 3722 | |
| 3723 | static BOOL get_filename_from_reg(HKEY hkey, LPCWSTR driverdir, DWORD dirlen, LPCWSTR ValueName, |
| 3724 | LPBYTE out, DWORD outlen, LPDWORD needed, BOOL unicode) |
| 3725 | { |
| 3726 | WCHAR filename[MAX_PATH]; |
| 3727 | DWORD size; |
| 3728 | DWORD type; |
| 3729 | LONG ret; |
| 3730 | LPWSTR buffer = filename; |
| 3731 | LPWSTR ptr; |
| 3732 | |
| 3733 | *needed = 0; |
| 3734 | size = sizeof(filename); |
| 3735 | buffer[0] = '\0'; |
| 3736 | ret = RegQueryValueExW(hkey, ValueName, NULL, &type, (LPBYTE) buffer, &size); |
| 3737 | if (ret == ERROR_MORE_DATA) { |
| 3738 | TRACE("need dynamic buffer: %u\n", size); |
| 3739 | buffer = HeapAlloc(GetProcessHeap(), 0, size); |
| 3740 | if (!buffer) { |
| 3741 | /* No Memory is bad */ |
| 3742 | return FALSE; |
| 3743 | } |
| 3744 | buffer[0] = '\0'; |
| 3745 | ret = RegQueryValueExW(hkey, ValueName, NULL, &type, (LPBYTE) buffer, &size); |
| 3746 | } |
| 3747 | |
| 3748 | if ((ret != ERROR_SUCCESS) || (!buffer[0])) { |
| 3749 | if (buffer != filename) HeapFree(GetProcessHeap(), 0, buffer); |
| 3750 | return FALSE; |
| 3751 | } |
| 3752 | |
| 3753 | ptr = buffer; |
| 3754 | while (ptr) { |
| 3755 | /* do we have a full path ? */ |
| 3756 | ret = (((buffer[0] == '\\') && (buffer[1] == '\\')) || |
| 3757 | (buffer[0] && (buffer[1] == ':') && (buffer[2] == '\\')) ); |
| 3758 | |
| 3759 | if (!ret) { |
| 3760 | /* we must build the full Path */ |
| 3761 | *needed += dirlen; |
| 3762 | if ((out) && (outlen > dirlen)) { |
| 3763 | if (unicode) { |
| 3764 | lstrcpyW((LPWSTR)out, driverdir); |
| 3765 | } |
| 3766 | else |
| 3767 | { |
| 3768 | WideCharToMultiByte(CP_ACP, 0, driverdir, -1, (LPSTR)out, outlen, NULL, NULL); |
| 3769 | } |
| 3770 | out += dirlen; |
| 3771 | outlen -= dirlen; |
| 3772 | } |
| 3773 | else |
| 3774 | out = NULL; |
| 3775 | } |
| 3776 | |
| 3777 | /* write the filename */ |
| 3778 | if (unicode) { |
| 3779 | size = (lstrlenW(ptr) + 1) * sizeof(WCHAR); |
| 3780 | if ((out) && (outlen >= size)) { |
| 3781 | lstrcpyW((LPWSTR)out, ptr); |
| 3782 | out += size; |
| 3783 | outlen -= size; |
| 3784 | } |
| 3785 | else |
| 3786 | out = NULL; |
| 3787 | } |
| 3788 | else |
| 3789 | { |
| 3790 | size = WideCharToMultiByte(CP_ACP, 0, ptr, -1, NULL, 0, NULL, NULL); |
| 3791 | if ((out) && (outlen >= size)) { |
| 3792 | WideCharToMultiByte(CP_ACP, 0, ptr, -1, (LPSTR)out, outlen, NULL, NULL); |
| 3793 | out += size; |
| 3794 | outlen -= size; |
| 3795 | } |
| 3796 | else |
| 3797 | out = NULL; |
| 3798 | } |
| 3799 | *needed += size; |
| 3800 | ptr += lstrlenW(ptr)+1; |
| 3801 | if ((type != REG_MULTI_SZ) || (!ptr[0])) ptr = NULL; |
| 3802 | } |
| 3803 | |
| 3804 | if (buffer != filename) HeapFree(GetProcessHeap(), 0, buffer); |
| 3805 | |
| 3806 | /* write the multisz-termination */ |
| 3807 | if (type == REG_MULTI_SZ) { |
| 3808 | size = (unicode) ? sizeof(WCHAR) : 1; |
| 3809 | |
| 3810 | *needed += size; |
| 3811 | if (out && (outlen >= size)) { |
| 3812 | memset (out, 0, size); |
| 3813 | } |
| 3814 | } |
| 3815 | return TRUE; |
| 3816 | } |
| 3817 | |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 3818 | /***************************************************************************** |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3819 | * WINSPOOL_GetStringFromReg |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 3820 | * |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3821 | * Get ValueName from hkey storing result in ptr. buflen is space left in ptr |
| 3822 | * String is stored either as unicode or ascii. |
| 3823 | * Bit of a hack here to get the ValueName if we want ascii. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 3824 | */ |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3825 | static BOOL WINSPOOL_GetStringFromReg(HKEY hkey, LPCWSTR ValueName, LPBYTE ptr, |
| 3826 | DWORD buflen, DWORD *needed, |
| 3827 | BOOL unicode) |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 3828 | { |
| 3829 | DWORD sz = buflen, type; |
| 3830 | LONG ret; |
| 3831 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3832 | if(unicode) |
| 3833 | ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz); |
| 3834 | else { |
Alexandre Julliard | 2731998 | 2006-11-17 15:29:40 +0100 | [diff] [blame] | 3835 | LPSTR ValueNameA = strdupWtoA(ValueName); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3836 | ret = RegQueryValueExA(hkey, ValueNameA, 0, &type, ptr, &sz); |
| 3837 | HeapFree(GetProcessHeap(),0,ValueNameA); |
| 3838 | } |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 3839 | if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3840 | WARN("Got ret = %d\n", ret); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3841 | *needed = 0; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 3842 | return FALSE; |
| 3843 | } |
Dmitry Timoshkov | b13c498 | 2006-04-14 22:34:57 +0900 | [diff] [blame] | 3844 | /* add space for terminating '\0' */ |
| 3845 | sz += unicode ? sizeof(WCHAR) : 1; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 3846 | *needed = sz; |
Dmitry Timoshkov | b13c498 | 2006-04-14 22:34:57 +0900 | [diff] [blame] | 3847 | |
| 3848 | if (ptr) |
| 3849 | TRACE("%s: %s\n", debugstr_w(ValueName), unicode ? debugstr_w((LPCWSTR)ptr) : debugstr_a((LPCSTR)ptr)); |
| 3850 | |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 3851 | return TRUE; |
| 3852 | } |
| 3853 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3854 | /***************************************************************************** |
Hidenori Takeshima | b544637 | 2001-09-07 18:35:58 +0000 | [diff] [blame] | 3855 | * WINSPOOL_GetDefaultDevMode |
| 3856 | * |
| 3857 | * Get a default DevMode values for wineps. |
| 3858 | * FIXME - use ppd. |
| 3859 | */ |
| 3860 | |
| 3861 | static void WINSPOOL_GetDefaultDevMode( |
| 3862 | LPBYTE ptr, |
| 3863 | DWORD buflen, DWORD *needed, |
| 3864 | BOOL unicode) |
| 3865 | { |
| 3866 | DEVMODEA dm; |
Mike McCormack | 516a577 | 2005-08-19 10:04:03 +0000 | [diff] [blame] | 3867 | static const char szwps[] = "wineps.drv"; |
Hidenori Takeshima | b544637 | 2001-09-07 18:35:58 +0000 | [diff] [blame] | 3868 | |
| 3869 | /* fill default DEVMODE - should be read from ppd... */ |
| 3870 | ZeroMemory( &dm, sizeof(dm) ); |
Mike McCormack | 516a577 | 2005-08-19 10:04:03 +0000 | [diff] [blame] | 3871 | memcpy(dm.dmDeviceName,szwps,sizeof szwps); |
Hidenori Takeshima | b544637 | 2001-09-07 18:35:58 +0000 | [diff] [blame] | 3872 | dm.dmSpecVersion = DM_SPECVERSION; |
| 3873 | dm.dmDriverVersion = 1; |
| 3874 | dm.dmSize = sizeof(DEVMODEA); |
| 3875 | dm.dmDriverExtra = 0; |
| 3876 | dm.dmFields = |
| 3877 | DM_ORIENTATION | DM_PAPERSIZE | |
| 3878 | DM_PAPERLENGTH | DM_PAPERWIDTH | |
| 3879 | DM_SCALE | |
| 3880 | DM_COPIES | |
| 3881 | DM_DEFAULTSOURCE | DM_PRINTQUALITY | |
| 3882 | DM_YRESOLUTION | DM_TTOPTION; |
| 3883 | |
| 3884 | dm.u1.s1.dmOrientation = DMORIENT_PORTRAIT; |
| 3885 | dm.u1.s1.dmPaperSize = DMPAPER_A4; |
| 3886 | dm.u1.s1.dmPaperLength = 2970; |
| 3887 | dm.u1.s1.dmPaperWidth = 2100; |
| 3888 | |
Dmitry Timoshkov | d43fdc5 | 2007-11-01 14:22:11 +0800 | [diff] [blame] | 3889 | dm.u1.s1.dmScale = 100; |
| 3890 | dm.u1.s1.dmCopies = 1; |
| 3891 | dm.u1.s1.dmDefaultSource = DMBIN_AUTO; |
| 3892 | dm.u1.s1.dmPrintQuality = DMRES_MEDIUM; |
Hidenori Takeshima | b544637 | 2001-09-07 18:35:58 +0000 | [diff] [blame] | 3893 | /* dm.dmColor */ |
| 3894 | /* dm.dmDuplex */ |
| 3895 | dm.dmYResolution = 300; /* 300dpi */ |
| 3896 | dm.dmTTOption = DMTT_BITMAP; |
| 3897 | /* dm.dmCollate */ |
| 3898 | /* dm.dmFormName */ |
| 3899 | /* dm.dmLogPixels */ |
| 3900 | /* dm.dmBitsPerPel */ |
| 3901 | /* dm.dmPelsWidth */ |
| 3902 | /* dm.dmPelsHeight */ |
Dmitry Timoshkov | d43fdc5 | 2007-11-01 14:22:11 +0800 | [diff] [blame] | 3903 | /* dm.u2.dmDisplayFlags */ |
Hidenori Takeshima | b544637 | 2001-09-07 18:35:58 +0000 | [diff] [blame] | 3904 | /* dm.dmDisplayFrequency */ |
| 3905 | /* dm.dmICMMethod */ |
| 3906 | /* dm.dmICMIntent */ |
| 3907 | /* dm.dmMediaType */ |
| 3908 | /* dm.dmDitherType */ |
| 3909 | /* dm.dmReserved1 */ |
| 3910 | /* dm.dmReserved2 */ |
| 3911 | /* dm.dmPanningWidth */ |
| 3912 | /* dm.dmPanningHeight */ |
| 3913 | |
| 3914 | if(unicode) { |
| 3915 | if(buflen >= sizeof(DEVMODEW)) { |
Dmitry Timoshkov | 3a910c7 | 2003-08-12 20:42:18 +0000 | [diff] [blame] | 3916 | DEVMODEW *pdmW = GdiConvertToDevmodeW(&dm); |
Hidenori Takeshima | b544637 | 2001-09-07 18:35:58 +0000 | [diff] [blame] | 3917 | memcpy(ptr, pdmW, sizeof(DEVMODEW)); |
| 3918 | HeapFree(GetProcessHeap(),0,pdmW); |
| 3919 | } |
| 3920 | *needed = sizeof(DEVMODEW); |
| 3921 | } |
| 3922 | else |
| 3923 | { |
| 3924 | if(buflen >= sizeof(DEVMODEA)) { |
| 3925 | memcpy(ptr, &dm, sizeof(DEVMODEA)); |
| 3926 | } |
| 3927 | *needed = sizeof(DEVMODEA); |
| 3928 | } |
| 3929 | } |
| 3930 | |
| 3931 | /***************************************************************************** |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3932 | * WINSPOOL_GetDevModeFromReg |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 3933 | * |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3934 | * Get ValueName from hkey storing result in ptr. buflen is space left in ptr |
| 3935 | * DevMode is stored either as unicode or ascii. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 3936 | */ |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3937 | static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName, |
| 3938 | LPBYTE ptr, |
| 3939 | DWORD buflen, DWORD *needed, |
| 3940 | BOOL unicode) |
| 3941 | { |
| 3942 | DWORD sz = buflen, type; |
| 3943 | LONG ret; |
| 3944 | |
Hidenori Takeshima | b544637 | 2001-09-07 18:35:58 +0000 | [diff] [blame] | 3945 | if (ptr && buflen>=sizeof(DEVMODEA)) memset(ptr, 0, sizeof(DEVMODEA)); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3946 | ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz); |
Gerard Patel | aaaee1b | 2000-08-16 12:43:00 +0000 | [diff] [blame] | 3947 | if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0; |
| 3948 | if (sz < sizeof(DEVMODEA)) |
| 3949 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 3950 | TRACE("corrupted registry for %s ( size %d)\n",debugstr_w(ValueName),sz); |
Marcus Meissner | 0c63012 | 2001-05-09 17:10:41 +0000 | [diff] [blame] | 3951 | return FALSE; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3952 | } |
Gerard Patel | aaaee1b | 2000-08-16 12:43:00 +0000 | [diff] [blame] | 3953 | /* ensures that dmSize is not erratically bogus if registry is invalid */ |
| 3954 | if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA)) |
| 3955 | ((DEVMODEA*)ptr)->dmSize = sizeof(DEVMODEA); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3956 | if(unicode) { |
| 3957 | sz += (CCHDEVICENAME + CCHFORMNAME); |
| 3958 | if(buflen >= sz) { |
Dmitry Timoshkov | 3a910c7 | 2003-08-12 20:42:18 +0000 | [diff] [blame] | 3959 | DEVMODEW *dmW = GdiConvertToDevmodeW((DEVMODEA*)ptr); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 3960 | memcpy(ptr, dmW, sz); |
| 3961 | HeapFree(GetProcessHeap(),0,dmW); |
| 3962 | } |
| 3963 | } |
| 3964 | *needed = sz; |
| 3965 | return TRUE; |
| 3966 | } |
| 3967 | |
| 3968 | /********************************************************************* |
Huw Davies | 09a2c89 | 2007-04-12 14:08:22 +0100 | [diff] [blame] | 3969 | * WINSPOOL_GetPrinter_1 |
| 3970 | * |
| 3971 | * Fills out a PRINTER_INFO_1A|W struct storing the strings in buf. |
| 3972 | * The strings are either stored as unicode or ascii. |
| 3973 | */ |
| 3974 | static BOOL WINSPOOL_GetPrinter_1(HKEY hkeyPrinter, PRINTER_INFO_1W *pi1, |
| 3975 | LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded, |
| 3976 | BOOL unicode) |
| 3977 | { |
| 3978 | DWORD size, left = cbBuf; |
| 3979 | BOOL space = (cbBuf > 0); |
| 3980 | LPBYTE ptr = buf; |
| 3981 | |
| 3982 | *pcbNeeded = 0; |
| 3983 | |
| 3984 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size, |
| 3985 | unicode)) { |
| 3986 | if(space && size <= left) { |
| 3987 | pi1->pName = (LPWSTR)ptr; |
| 3988 | ptr += size; |
| 3989 | left -= size; |
| 3990 | } else |
| 3991 | space = FALSE; |
| 3992 | *pcbNeeded += size; |
| 3993 | } |
| 3994 | |
| 3995 | /* FIXME: pDescription should be something like "Name,Driver_Name,". */ |
| 3996 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size, |
| 3997 | unicode)) { |
| 3998 | if(space && size <= left) { |
| 3999 | pi1->pDescription = (LPWSTR)ptr; |
| 4000 | ptr += size; |
| 4001 | left -= size; |
| 4002 | } else |
| 4003 | space = FALSE; |
| 4004 | *pcbNeeded += size; |
| 4005 | } |
| 4006 | |
| 4007 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size, |
| 4008 | unicode)) { |
| 4009 | if(space && size <= left) { |
| 4010 | pi1->pComment = (LPWSTR)ptr; |
| 4011 | ptr += size; |
| 4012 | left -= size; |
| 4013 | } else |
| 4014 | space = FALSE; |
| 4015 | *pcbNeeded += size; |
| 4016 | } |
| 4017 | |
| 4018 | if(pi1) pi1->Flags = PRINTER_ENUM_ICON8; /* We're a printer */ |
| 4019 | |
| 4020 | if(!space && pi1) /* zero out pi1 if we can't completely fill buf */ |
| 4021 | memset(pi1, 0, sizeof(*pi1)); |
| 4022 | |
| 4023 | return space; |
| 4024 | } |
| 4025 | /********************************************************************* |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4026 | * WINSPOOL_GetPrinter_2 |
| 4027 | * |
| 4028 | * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf. |
| 4029 | * The strings are either stored as unicode or ascii. |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4030 | */ |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4031 | static BOOL WINSPOOL_GetPrinter_2(HKEY hkeyPrinter, PRINTER_INFO_2W *pi2, |
| 4032 | LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded, |
| 4033 | BOOL unicode) |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4034 | { |
| 4035 | DWORD size, left = cbBuf; |
| 4036 | BOOL space = (cbBuf > 0); |
| 4037 | LPBYTE ptr = buf; |
| 4038 | |
| 4039 | *pcbNeeded = 0; |
| 4040 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4041 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size, |
| 4042 | unicode)) { |
| 4043 | if(space && size <= left) { |
| 4044 | pi2->pPrinterName = (LPWSTR)ptr; |
| 4045 | ptr += size; |
| 4046 | left -= size; |
| 4047 | } else |
| 4048 | space = FALSE; |
| 4049 | *pcbNeeded += size; |
| 4050 | } |
| 4051 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, Share_NameW, ptr, left, &size, |
| 4052 | unicode)) { |
| 4053 | if(space && size <= left) { |
| 4054 | pi2->pShareName = (LPWSTR)ptr; |
| 4055 | ptr += size; |
| 4056 | left -= size; |
| 4057 | } else |
| 4058 | space = FALSE; |
| 4059 | *pcbNeeded += size; |
| 4060 | } |
| 4061 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size, |
| 4062 | unicode)) { |
| 4063 | if(space && size <= left) { |
| 4064 | pi2->pPortName = (LPWSTR)ptr; |
| 4065 | ptr += size; |
| 4066 | left -= size; |
| 4067 | } else |
| 4068 | space = FALSE; |
| 4069 | *pcbNeeded += size; |
| 4070 | } |
| 4071 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, Printer_DriverW, ptr, left, |
| 4072 | &size, unicode)) { |
| 4073 | if(space && size <= left) { |
| 4074 | pi2->pDriverName = (LPWSTR)ptr; |
| 4075 | ptr += size; |
| 4076 | left -= size; |
| 4077 | } else |
| 4078 | space = FALSE; |
| 4079 | *pcbNeeded += size; |
| 4080 | } |
| 4081 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size, |
| 4082 | unicode)) { |
| 4083 | if(space && size <= left) { |
| 4084 | pi2->pComment = (LPWSTR)ptr; |
| 4085 | ptr += size; |
| 4086 | left -= size; |
| 4087 | } else |
| 4088 | space = FALSE; |
| 4089 | *pcbNeeded += size; |
| 4090 | } |
| 4091 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, LocationW, ptr, left, &size, |
| 4092 | unicode)) { |
| 4093 | if(space && size <= left) { |
| 4094 | pi2->pLocation = (LPWSTR)ptr; |
| 4095 | ptr += size; |
| 4096 | left -= size; |
| 4097 | } else |
| 4098 | space = FALSE; |
| 4099 | *pcbNeeded += size; |
| 4100 | } |
| 4101 | if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, ptr, left, |
| 4102 | &size, unicode)) { |
| 4103 | if(space && size <= left) { |
| 4104 | pi2->pDevMode = (LPDEVMODEW)ptr; |
| 4105 | ptr += size; |
| 4106 | left -= size; |
| 4107 | } else |
| 4108 | space = FALSE; |
| 4109 | *pcbNeeded += size; |
| 4110 | } |
Hidenori Takeshima | b544637 | 2001-09-07 18:35:58 +0000 | [diff] [blame] | 4111 | else |
| 4112 | { |
Hidenori Takeshima | b544637 | 2001-09-07 18:35:58 +0000 | [diff] [blame] | 4113 | WINSPOOL_GetDefaultDevMode(ptr, left, &size, unicode); |
| 4114 | if(space && size <= left) { |
| 4115 | pi2->pDevMode = (LPDEVMODEW)ptr; |
| 4116 | ptr += size; |
| 4117 | left -= size; |
| 4118 | } else |
| 4119 | space = FALSE; |
| 4120 | *pcbNeeded += size; |
| 4121 | } |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4122 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, Separator_FileW, ptr, left, |
| 4123 | &size, unicode)) { |
| 4124 | if(space && size <= left) { |
| 4125 | pi2->pSepFile = (LPWSTR)ptr; |
| 4126 | ptr += size; |
| 4127 | left -= size; |
| 4128 | } else |
| 4129 | space = FALSE; |
| 4130 | *pcbNeeded += size; |
| 4131 | } |
| 4132 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, Print_ProcessorW, ptr, left, |
| 4133 | &size, unicode)) { |
| 4134 | if(space && size <= left) { |
| 4135 | pi2->pPrintProcessor = (LPWSTR)ptr; |
| 4136 | ptr += size; |
| 4137 | left -= size; |
| 4138 | } else |
| 4139 | space = FALSE; |
| 4140 | *pcbNeeded += size; |
| 4141 | } |
| 4142 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, DatatypeW, ptr, left, |
| 4143 | &size, unicode)) { |
| 4144 | if(space && size <= left) { |
| 4145 | pi2->pDatatype = (LPWSTR)ptr; |
| 4146 | ptr += size; |
| 4147 | left -= size; |
| 4148 | } else |
| 4149 | space = FALSE; |
| 4150 | *pcbNeeded += size; |
| 4151 | } |
| 4152 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, ParametersW, ptr, left, |
| 4153 | &size, unicode)) { |
| 4154 | if(space && size <= left) { |
| 4155 | pi2->pParameters = (LPWSTR)ptr; |
| 4156 | ptr += size; |
| 4157 | left -= size; |
| 4158 | } else |
| 4159 | space = FALSE; |
| 4160 | *pcbNeeded += size; |
| 4161 | } |
| 4162 | if(pi2) { |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4163 | pi2->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes"); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4164 | pi2->Priority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Priority"); |
| 4165 | pi2->DefaultPriority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, |
| 4166 | "Default Priority"); |
| 4167 | pi2->StartTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "StartTime"); |
| 4168 | pi2->UntilTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "UntilTime"); |
| 4169 | } |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4170 | |
| 4171 | if(!space && pi2) /* zero out pi2 if we can't completely fill buf */ |
| 4172 | memset(pi2, 0, sizeof(*pi2)); |
| 4173 | |
| 4174 | return space; |
| 4175 | } |
| 4176 | |
| 4177 | /********************************************************************* |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4178 | * WINSPOOL_GetPrinter_4 |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4179 | * |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4180 | * Fills out a PRINTER_INFO_4 struct storing the strings in buf. |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4181 | */ |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4182 | static BOOL WINSPOOL_GetPrinter_4(HKEY hkeyPrinter, PRINTER_INFO_4W *pi4, |
| 4183 | LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded, |
| 4184 | BOOL unicode) |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4185 | { |
| 4186 | DWORD size, left = cbBuf; |
| 4187 | BOOL space = (cbBuf > 0); |
| 4188 | LPBYTE ptr = buf; |
| 4189 | |
| 4190 | *pcbNeeded = 0; |
| 4191 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4192 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size, |
| 4193 | unicode)) { |
| 4194 | if(space && size <= left) { |
| 4195 | pi4->pPrinterName = (LPWSTR)ptr; |
| 4196 | ptr += size; |
| 4197 | left -= size; |
| 4198 | } else |
| 4199 | space = FALSE; |
| 4200 | *pcbNeeded += size; |
| 4201 | } |
| 4202 | if(pi4) { |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4203 | pi4->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes"); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4204 | } |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4205 | |
| 4206 | if(!space && pi4) /* zero out pi4 if we can't completely fill buf */ |
| 4207 | memset(pi4, 0, sizeof(*pi4)); |
| 4208 | |
| 4209 | return space; |
| 4210 | } |
| 4211 | |
| 4212 | /********************************************************************* |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4213 | * WINSPOOL_GetPrinter_5 |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4214 | * |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4215 | * Fills out a PRINTER_INFO_5 struct storing the strings in buf. |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4216 | */ |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4217 | static BOOL WINSPOOL_GetPrinter_5(HKEY hkeyPrinter, PRINTER_INFO_5W *pi5, |
| 4218 | LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded, |
| 4219 | BOOL unicode) |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4220 | { |
| 4221 | DWORD size, left = cbBuf; |
| 4222 | BOOL space = (cbBuf > 0); |
| 4223 | LPBYTE ptr = buf; |
| 4224 | |
| 4225 | *pcbNeeded = 0; |
| 4226 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4227 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size, |
| 4228 | unicode)) { |
| 4229 | if(space && size <= left) { |
| 4230 | pi5->pPrinterName = (LPWSTR)ptr; |
| 4231 | ptr += size; |
| 4232 | left -= size; |
| 4233 | } else |
| 4234 | space = FALSE; |
| 4235 | *pcbNeeded += size; |
| 4236 | } |
| 4237 | if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size, |
| 4238 | unicode)) { |
| 4239 | if(space && size <= left) { |
| 4240 | pi5->pPortName = (LPWSTR)ptr; |
| 4241 | ptr += size; |
| 4242 | left -= size; |
| 4243 | } else |
| 4244 | space = FALSE; |
| 4245 | *pcbNeeded += size; |
| 4246 | } |
| 4247 | if(pi5) { |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4248 | pi5->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes"); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4249 | pi5->DeviceNotSelectedTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4250 | "dnsTimeout"); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4251 | pi5->TransmissionRetryTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4252 | "txTimeout"); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4253 | } |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4254 | |
| 4255 | if(!space && pi5) /* zero out pi5 if we can't completely fill buf */ |
| 4256 | memset(pi5, 0, sizeof(*pi5)); |
| 4257 | |
| 4258 | return space; |
| 4259 | } |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4260 | |
Detlef Riekenberg | ae91e97 | 2008-02-26 23:09:55 +0100 | [diff] [blame] | 4261 | /********************************************************************* |
| 4262 | * WINSPOOL_GetPrinter_7 |
| 4263 | * |
| 4264 | * Fills out a PRINTER_INFO_7 struct storing the strings in buf. |
| 4265 | */ |
| 4266 | static BOOL WINSPOOL_GetPrinter_7(HKEY hkeyPrinter, PRINTER_INFO_7W *pi7, LPBYTE buf, |
| 4267 | DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode) |
| 4268 | { |
| 4269 | DWORD size, left = cbBuf; |
| 4270 | BOOL space = (cbBuf > 0); |
| 4271 | LPBYTE ptr = buf; |
| 4272 | |
| 4273 | *pcbNeeded = 0; |
| 4274 | |
| 4275 | if (WINSPOOL_GetStringFromReg(hkeyPrinter, ObjectGUIDW, ptr, left, &size, unicode)) |
| 4276 | { |
| 4277 | if (space && size <= left) { |
| 4278 | pi7->pszObjectGUID = (LPWSTR)ptr; |
| 4279 | ptr += size; |
| 4280 | left -= size; |
| 4281 | } else |
| 4282 | space = FALSE; |
| 4283 | *pcbNeeded += size; |
| 4284 | } |
| 4285 | if (pi7) { |
| 4286 | /* We do not have a Directory Service */ |
| 4287 | pi7->dwAction = DSPRINT_UNPUBLISH; |
| 4288 | } |
| 4289 | |
| 4290 | if (!space && pi7) /* zero out pi7 if we can't completely fill buf */ |
| 4291 | memset(pi7, 0, sizeof(*pi7)); |
| 4292 | |
| 4293 | return space; |
| 4294 | } |
| 4295 | |
Detlef Riekenberg | 81dadcb | 2008-02-28 21:46:17 +0100 | [diff] [blame] | 4296 | /********************************************************************* |
| 4297 | * WINSPOOL_GetPrinter_9 |
| 4298 | * |
| 4299 | * Fills out a PRINTER_INFO_9A|W struct storing the strings in buf. |
| 4300 | * The strings are either stored as unicode or ascii. |
| 4301 | */ |
| 4302 | static BOOL WINSPOOL_GetPrinter_9(HKEY hkeyPrinter, PRINTER_INFO_9W *pi9, LPBYTE buf, |
| 4303 | DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode) |
| 4304 | { |
| 4305 | DWORD size; |
| 4306 | BOOL space = (cbBuf > 0); |
| 4307 | |
| 4308 | *pcbNeeded = 0; |
| 4309 | |
| 4310 | if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, buf, cbBuf, &size, unicode)) { |
| 4311 | if(space && size <= cbBuf) { |
| 4312 | pi9->pDevMode = (LPDEVMODEW)buf; |
| 4313 | } else |
| 4314 | space = FALSE; |
| 4315 | *pcbNeeded += size; |
| 4316 | } |
| 4317 | else |
| 4318 | { |
| 4319 | WINSPOOL_GetDefaultDevMode(buf, cbBuf, &size, unicode); |
| 4320 | if(space && size <= cbBuf) { |
| 4321 | pi9->pDevMode = (LPDEVMODEW)buf; |
| 4322 | } else |
| 4323 | space = FALSE; |
| 4324 | *pcbNeeded += size; |
| 4325 | } |
| 4326 | |
| 4327 | if(!space && pi9) /* zero out pi9 if we can't completely fill buf */ |
| 4328 | memset(pi9, 0, sizeof(*pi9)); |
| 4329 | |
| 4330 | return space; |
| 4331 | } |
| 4332 | |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 4333 | /***************************************************************************** |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4334 | * WINSPOOL_GetPrinter |
| 4335 | * |
| 4336 | * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being |
| 4337 | * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is |
| 4338 | * just a collection of pointers to strings. |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 4339 | */ |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4340 | static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, |
| 4341 | DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 4342 | { |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 4343 | LPCWSTR name; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4344 | DWORD size, needed = 0; |
| 4345 | LPBYTE ptr = NULL; |
| 4346 | HKEY hkeyPrinter, hkeyPrinters; |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4347 | BOOL ret; |
| 4348 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 4349 | TRACE("(%p,%d,%p,%d,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 4350 | |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 4351 | if (!(name = get_opened_printer_name(hPrinter))) { |
| 4352 | SetLastError(ERROR_INVALID_HANDLE); |
| 4353 | return FALSE; |
| 4354 | } |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 4355 | |
Detlef Riekenberg | 358ce06 | 2006-05-21 14:35:29 +0200 | [diff] [blame] | 4356 | if(RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) != |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4357 | ERROR_SUCCESS) { |
| 4358 | ERR("Can't create Printers key\n"); |
| 4359 | return FALSE; |
| 4360 | } |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 4361 | if(RegOpenKeyW(hkeyPrinters, name, &hkeyPrinter) != ERROR_SUCCESS) |
| 4362 | { |
| 4363 | ERR("Can't find opened printer %s in registry\n", debugstr_w(name)); |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4364 | RegCloseKey(hkeyPrinters); |
| 4365 | SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */ |
| 4366 | return FALSE; |
| 4367 | } |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 4368 | |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4369 | switch(Level) { |
| 4370 | case 2: |
| 4371 | { |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4372 | PRINTER_INFO_2W *pi2 = (PRINTER_INFO_2W *)pPrinter; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4373 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4374 | size = sizeof(PRINTER_INFO_2W); |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4375 | if(size <= cbBuf) { |
| 4376 | ptr = pPrinter + size; |
| 4377 | cbBuf -= size; |
| 4378 | memset(pPrinter, 0, size); |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4379 | } else { |
| 4380 | pi2 = NULL; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4381 | cbBuf = 0; |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4382 | } |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4383 | ret = WINSPOOL_GetPrinter_2(hkeyPrinter, pi2, ptr, cbBuf, &needed, |
| 4384 | unicode); |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4385 | needed += size; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4386 | break; |
| 4387 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4388 | |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4389 | case 4: |
| 4390 | { |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4391 | PRINTER_INFO_4W *pi4 = (PRINTER_INFO_4W *)pPrinter; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4392 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4393 | size = sizeof(PRINTER_INFO_4W); |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4394 | if(size <= cbBuf) { |
| 4395 | ptr = pPrinter + size; |
| 4396 | cbBuf -= size; |
| 4397 | memset(pPrinter, 0, size); |
| 4398 | } else { |
| 4399 | pi4 = NULL; |
| 4400 | cbBuf = 0; |
| 4401 | } |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4402 | ret = WINSPOOL_GetPrinter_4(hkeyPrinter, pi4, ptr, cbBuf, &needed, |
| 4403 | unicode); |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4404 | needed += size; |
| 4405 | break; |
| 4406 | } |
| 4407 | |
| 4408 | |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4409 | case 5: |
| 4410 | { |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4411 | PRINTER_INFO_5W *pi5 = (PRINTER_INFO_5W *)pPrinter; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4412 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4413 | size = sizeof(PRINTER_INFO_5W); |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4414 | if(size <= cbBuf) { |
| 4415 | ptr = pPrinter + size; |
| 4416 | cbBuf -= size; |
| 4417 | memset(pPrinter, 0, size); |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4418 | } else { |
| 4419 | pi5 = NULL; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4420 | cbBuf = 0; |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4421 | } |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4422 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4423 | ret = WINSPOOL_GetPrinter_5(hkeyPrinter, pi5, ptr, cbBuf, &needed, |
| 4424 | unicode); |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4425 | needed += size; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4426 | break; |
| 4427 | } |
| 4428 | |
Detlef Riekenberg | ae91e97 | 2008-02-26 23:09:55 +0100 | [diff] [blame] | 4429 | |
| 4430 | case 6: |
| 4431 | { |
| 4432 | PRINTER_INFO_6 *pi6 = (PRINTER_INFO_6 *) pPrinter; |
| 4433 | |
| 4434 | size = sizeof(PRINTER_INFO_6); |
| 4435 | if (size <= cbBuf) { |
| 4436 | /* FIXME: We do not update the status yet */ |
| 4437 | pi6->dwStatus = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Status"); |
| 4438 | ret = TRUE; |
| 4439 | } else { |
| 4440 | ret = FALSE; |
| 4441 | } |
| 4442 | |
| 4443 | needed += size; |
| 4444 | break; |
| 4445 | } |
| 4446 | |
| 4447 | case 7: |
| 4448 | { |
| 4449 | PRINTER_INFO_7W *pi7 = (PRINTER_INFO_7W *) pPrinter; |
| 4450 | |
| 4451 | size = sizeof(PRINTER_INFO_7W); |
| 4452 | if (size <= cbBuf) { |
| 4453 | ptr = pPrinter + size; |
| 4454 | cbBuf -= size; |
| 4455 | memset(pPrinter, 0, size); |
| 4456 | } else { |
| 4457 | pi7 = NULL; |
| 4458 | cbBuf = 0; |
| 4459 | } |
| 4460 | |
| 4461 | ret = WINSPOOL_GetPrinter_7(hkeyPrinter, pi7, ptr, cbBuf, &needed, unicode); |
| 4462 | needed += size; |
| 4463 | break; |
| 4464 | } |
| 4465 | |
| 4466 | |
Detlef Riekenberg | 81dadcb | 2008-02-28 21:46:17 +0100 | [diff] [blame] | 4467 | case 9: |
| 4468 | { |
| 4469 | PRINTER_INFO_9W *pi9 = (PRINTER_INFO_9W *)pPrinter; |
| 4470 | |
| 4471 | size = sizeof(PRINTER_INFO_9W); |
| 4472 | if(size <= cbBuf) { |
| 4473 | ptr = pPrinter + size; |
| 4474 | cbBuf -= size; |
| 4475 | memset(pPrinter, 0, size); |
| 4476 | } else { |
| 4477 | pi9 = NULL; |
| 4478 | cbBuf = 0; |
| 4479 | } |
| 4480 | |
| 4481 | ret = WINSPOOL_GetPrinter_9(hkeyPrinter, pi9, ptr, cbBuf, &needed, unicode); |
| 4482 | needed += size; |
| 4483 | break; |
| 4484 | } |
| 4485 | |
| 4486 | |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4487 | default: |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 4488 | FIXME("Unimplemented level %d\n", Level); |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4489 | SetLastError(ERROR_INVALID_LEVEL); |
| 4490 | RegCloseKey(hkeyPrinters); |
| 4491 | RegCloseKey(hkeyPrinter); |
| 4492 | return FALSE; |
| 4493 | } |
| 4494 | |
| 4495 | RegCloseKey(hkeyPrinter); |
| 4496 | RegCloseKey(hkeyPrinters); |
| 4497 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 4498 | TRACE("returning %d needed = %d\n", ret, needed); |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 4499 | if(pcbNeeded) *pcbNeeded = needed; |
Huw D M Davies | c7665eb | 1999-09-10 14:37:29 +0000 | [diff] [blame] | 4500 | if(!ret) |
| 4501 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 4502 | return ret; |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 4503 | } |
| 4504 | |
| 4505 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 4506 | * GetPrinterW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 4507 | */ |
| 4508 | BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4509 | DWORD cbBuf, LPDWORD pcbNeeded) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 4510 | { |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4511 | return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded, |
| 4512 | TRUE); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 4513 | } |
| 4514 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4515 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 4516 | * GetPrinterA [WINSPOOL.@] |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4517 | */ |
| 4518 | BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, |
| 4519 | DWORD cbBuf, LPDWORD pcbNeeded) |
| 4520 | { |
| 4521 | return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded, |
| 4522 | FALSE); |
| 4523 | } |
| 4524 | |
| 4525 | /***************************************************************************** |
| 4526 | * WINSPOOL_EnumPrinters |
| 4527 | * |
| 4528 | * Implementation of EnumPrintersA|W |
| 4529 | */ |
| 4530 | static BOOL WINSPOOL_EnumPrinters(DWORD dwType, LPWSTR lpszName, |
| 4531 | DWORD dwLevel, LPBYTE lpbPrinters, |
| 4532 | DWORD cbBuf, LPDWORD lpdwNeeded, |
| 4533 | LPDWORD lpdwReturned, BOOL unicode) |
| 4534 | |
| 4535 | { |
| 4536 | HKEY hkeyPrinters, hkeyPrinter; |
| 4537 | WCHAR PrinterName[255]; |
| 4538 | DWORD needed = 0, number = 0; |
| 4539 | DWORD used, i, left; |
| 4540 | PBYTE pi, buf; |
| 4541 | |
| 4542 | if(lpbPrinters) |
| 4543 | memset(lpbPrinters, 0, cbBuf); |
| 4544 | if(lpdwReturned) |
| 4545 | *lpdwReturned = 0; |
Huw D M Davies | 87f98a5 | 2001-01-09 20:52:17 +0000 | [diff] [blame] | 4546 | if(lpdwNeeded) |
| 4547 | *lpdwNeeded = 0; |
| 4548 | |
| 4549 | /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */ |
| 4550 | if(dwType == PRINTER_ENUM_DEFAULT) |
| 4551 | return TRUE; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4552 | |
Marcus Meissner | 75e4e94 | 2002-09-09 19:19:18 +0000 | [diff] [blame] | 4553 | if (dwType & PRINTER_ENUM_CONNECTIONS) { |
Detlef Riekenberg | bc85a34 | 2007-01-21 20:49:34 +0100 | [diff] [blame] | 4554 | TRACE("ignoring PRINTER_ENUM_CONNECTIONS\n"); |
| 4555 | dwType &= ~PRINTER_ENUM_CONNECTIONS; /* we don't handle that */ |
| 4556 | if (!dwType) { |
| 4557 | FIXME("We don't handle PRINTER_ENUM_CONNECTIONS\n"); |
| 4558 | *lpdwNeeded = 0; |
| 4559 | *lpdwReturned = 0; |
| 4560 | return TRUE; |
| 4561 | } |
| 4562 | |
Marcus Meissner | 75e4e94 | 2002-09-09 19:19:18 +0000 | [diff] [blame] | 4563 | } |
| 4564 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4565 | if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 4566 | FIXME("dwType = %08x\n", dwType); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4567 | SetLastError(ERROR_INVALID_FLAGS); |
| 4568 | return FALSE; |
| 4569 | } |
| 4570 | |
Detlef Riekenberg | 358ce06 | 2006-05-21 14:35:29 +0200 | [diff] [blame] | 4571 | if(RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) != |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4572 | ERROR_SUCCESS) { |
| 4573 | ERR("Can't create Printers key\n"); |
| 4574 | return FALSE; |
| 4575 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4576 | |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4577 | if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL, |
| 4578 | NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { |
| 4579 | RegCloseKey(hkeyPrinters); |
| 4580 | ERR("Can't query Printers key\n"); |
| 4581 | return FALSE; |
| 4582 | } |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 4583 | TRACE("Found %d printers\n", number); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4584 | |
| 4585 | switch(dwLevel) { |
| 4586 | case 1: |
Huw Davies | 09a2c89 | 2007-04-12 14:08:22 +0100 | [diff] [blame] | 4587 | used = number * sizeof(PRINTER_INFO_1W); |
| 4588 | break; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4589 | case 2: |
| 4590 | used = number * sizeof(PRINTER_INFO_2W); |
| 4591 | break; |
| 4592 | case 4: |
| 4593 | used = number * sizeof(PRINTER_INFO_4W); |
| 4594 | break; |
| 4595 | case 5: |
| 4596 | used = number * sizeof(PRINTER_INFO_5W); |
| 4597 | break; |
| 4598 | |
| 4599 | default: |
| 4600 | SetLastError(ERROR_INVALID_LEVEL); |
| 4601 | RegCloseKey(hkeyPrinters); |
| 4602 | return FALSE; |
| 4603 | } |
| 4604 | pi = (used <= cbBuf) ? lpbPrinters : NULL; |
| 4605 | |
| 4606 | for(i = 0; i < number; i++) { |
Vitaly Lipatov | 914e78a | 2007-12-01 19:43:37 +0300 | [diff] [blame] | 4607 | if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)/sizeof(PrinterName[0])) != |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4608 | ERROR_SUCCESS) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 4609 | ERR("Can't enum key number %d\n", i); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4610 | RegCloseKey(hkeyPrinters); |
| 4611 | return FALSE; |
| 4612 | } |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 4613 | TRACE("Printer %d is %s\n", i, debugstr_w(PrinterName)); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4614 | if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkeyPrinter) != |
| 4615 | ERROR_SUCCESS) { |
| 4616 | ERR("Can't open key %s\n", debugstr_w(PrinterName)); |
| 4617 | RegCloseKey(hkeyPrinters); |
| 4618 | return FALSE; |
| 4619 | } |
| 4620 | |
| 4621 | if(cbBuf > used) { |
| 4622 | buf = lpbPrinters + used; |
| 4623 | left = cbBuf - used; |
| 4624 | } else { |
| 4625 | buf = NULL; |
| 4626 | left = 0; |
| 4627 | } |
| 4628 | |
| 4629 | switch(dwLevel) { |
Huw Davies | 09a2c89 | 2007-04-12 14:08:22 +0100 | [diff] [blame] | 4630 | case 1: |
| 4631 | WINSPOOL_GetPrinter_1(hkeyPrinter, (PRINTER_INFO_1W *)pi, buf, |
| 4632 | left, &needed, unicode); |
| 4633 | used += needed; |
| 4634 | if(pi) pi += sizeof(PRINTER_INFO_1W); |
| 4635 | break; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4636 | case 2: |
| 4637 | WINSPOOL_GetPrinter_2(hkeyPrinter, (PRINTER_INFO_2W *)pi, buf, |
| 4638 | left, &needed, unicode); |
| 4639 | used += needed; |
| 4640 | if(pi) pi += sizeof(PRINTER_INFO_2W); |
| 4641 | break; |
| 4642 | case 4: |
| 4643 | WINSPOOL_GetPrinter_4(hkeyPrinter, (PRINTER_INFO_4W *)pi, buf, |
| 4644 | left, &needed, unicode); |
| 4645 | used += needed; |
| 4646 | if(pi) pi += sizeof(PRINTER_INFO_4W); |
| 4647 | break; |
| 4648 | case 5: |
| 4649 | WINSPOOL_GetPrinter_5(hkeyPrinter, (PRINTER_INFO_5W *)pi, buf, |
| 4650 | left, &needed, unicode); |
| 4651 | used += needed; |
| 4652 | if(pi) pi += sizeof(PRINTER_INFO_5W); |
| 4653 | break; |
| 4654 | default: |
| 4655 | ERR("Shouldn't be here!\n"); |
| 4656 | RegCloseKey(hkeyPrinter); |
| 4657 | RegCloseKey(hkeyPrinters); |
| 4658 | return FALSE; |
| 4659 | } |
| 4660 | RegCloseKey(hkeyPrinter); |
| 4661 | } |
| 4662 | RegCloseKey(hkeyPrinters); |
| 4663 | |
| 4664 | if(lpdwNeeded) |
| 4665 | *lpdwNeeded = used; |
| 4666 | |
| 4667 | if(used > cbBuf) { |
| 4668 | if(lpbPrinters) |
| 4669 | memset(lpbPrinters, 0, cbBuf); |
| 4670 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 4671 | return FALSE; |
| 4672 | } |
| 4673 | if(lpdwReturned) |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4674 | *lpdwReturned = number; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4675 | SetLastError(ERROR_SUCCESS); |
| 4676 | return TRUE; |
| 4677 | } |
| 4678 | |
| 4679 | |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4680 | /****************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 4681 | * EnumPrintersW [WINSPOOL.@] |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4682 | * |
| 4683 | * Enumerates the available printers, print servers and print |
| 4684 | * providers, depending on the specified flags, name and level. |
| 4685 | * |
| 4686 | * RETURNS: |
| 4687 | * |
| 4688 | * If level is set to 1: |
Huw Davies | 09a2c89 | 2007-04-12 14:08:22 +0100 | [diff] [blame] | 4689 | * Returns an array of PRINTER_INFO_1 data structures in the |
| 4690 | * lpbPrinters buffer. |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4691 | * |
| 4692 | * If level is set to 2: |
| 4693 | * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4694 | * Returns an array of PRINTER_INFO_2 data structures in the |
| 4695 | * lpbPrinters buffer. Note that according to MSDN also an |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4696 | * OpenPrinter should be performed on every remote printer. |
| 4697 | * |
| 4698 | * If level is set to 4 (officially WinNT only): |
| 4699 | * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL. |
| 4700 | * Fast: Only the registry is queried to retrieve printer names, |
| 4701 | * no connection to the driver is made. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4702 | * Returns an array of PRINTER_INFO_4 data structures in the |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4703 | * lpbPrinters buffer. |
| 4704 | * |
| 4705 | * If level is set to 5 (officially WinNT4/Win9x only): |
| 4706 | * Fast: Only the registry is queried to retrieve printer names, |
| 4707 | * no connection to the driver is made. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4708 | * Returns an array of PRINTER_INFO_5 data structures in the |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4709 | * lpbPrinters buffer. |
| 4710 | * |
| 4711 | * If level set to 3 or 6+: |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 4712 | * returns zero (failure!) |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4713 | * |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 4714 | * Returns nonzero (TRUE) on success, or zero on failure, use GetLastError |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4715 | * for information. |
| 4716 | * |
| 4717 | * BUGS: |
| 4718 | * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented. |
| 4719 | * - Only levels 2, 4 and 5 are implemented at the moment. |
| 4720 | * - 16-bit printer drivers are not enumerated. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 4721 | * - Returned amount of bytes used/needed does not match the real Windoze |
| 4722 | * implementation (as in this implementation, all strings are part |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4723 | * of the buffer, whereas Win32 keeps them somewhere else) |
| 4724 | * - At level 2, EnumPrinters should also call OpenPrinter for remote printers. |
| 4725 | * |
| 4726 | * NOTE: |
| 4727 | * - In a regular Wine installation, no registry settings for printers |
| 4728 | * exist, which makes this function return an empty list. |
| 4729 | */ |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4730 | BOOL WINAPI EnumPrintersW( |
Patrik Stridvall | 2b3aa61 | 2000-12-01 23:58:28 +0000 | [diff] [blame] | 4731 | DWORD dwType, /* [in] Types of print objects to enumerate */ |
| 4732 | LPWSTR lpszName, /* [in] name of objects to enumerate */ |
| 4733 | DWORD dwLevel, /* [in] type of printer info structure */ |
| 4734 | LPBYTE lpbPrinters, /* [out] buffer which receives info */ |
| 4735 | DWORD cbBuf, /* [in] max size of buffer in bytes */ |
| 4736 | LPDWORD lpdwNeeded, /* [out] pointer to var: # bytes used/needed */ |
| 4737 | LPDWORD lpdwReturned /* [out] number of entries returned */ |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4738 | ) |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4739 | { |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4740 | return WINSPOOL_EnumPrinters(dwType, lpszName, dwLevel, lpbPrinters, cbBuf, |
| 4741 | lpdwNeeded, lpdwReturned, TRUE); |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4742 | } |
| 4743 | |
| 4744 | /****************************************************************** |
Detlef Riekenberg | 9e35ee8 | 2008-03-22 19:28:50 +0100 | [diff] [blame] | 4745 | * EnumPrintersA [WINSPOOL.@] |
| 4746 | * |
| 4747 | * See EnumPrintersW |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4748 | * |
| 4749 | */ |
Detlef Riekenberg | 9e35ee8 | 2008-03-22 19:28:50 +0100 | [diff] [blame] | 4750 | BOOL WINAPI EnumPrintersA(DWORD flags, LPSTR pName, DWORD level, LPBYTE pPrinters, |
| 4751 | DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4752 | { |
Detlef Riekenberg | 9e35ee8 | 2008-03-22 19:28:50 +0100 | [diff] [blame] | 4753 | BOOL ret; |
| 4754 | UNICODE_STRING pNameU; |
| 4755 | LPWSTR pNameW; |
| 4756 | LPBYTE pPrintersW; |
Huw Davies | 9108eed | 2006-12-04 14:32:36 +0000 | [diff] [blame] | 4757 | |
Detlef Riekenberg | 9e35ee8 | 2008-03-22 19:28:50 +0100 | [diff] [blame] | 4758 | TRACE("(0x%x, %s, %u, %p, %d, %p, %p)\n", flags, debugstr_a(pName), level, |
| 4759 | pPrinters, cbBuf, pcbNeeded, pcReturned); |
| 4760 | |
| 4761 | pNameW = asciitounicode(&pNameU, pName); |
| 4762 | |
| 4763 | /* Request a buffer with a size, that is big enough for EnumPrintersW. |
| 4764 | MS Office need this */ |
| 4765 | pPrintersW = (pPrinters && cbBuf) ? HeapAlloc(GetProcessHeap(), 0, cbBuf) : NULL; |
| 4766 | |
| 4767 | ret = EnumPrintersW(flags, pNameW, level, pPrintersW, cbBuf, pcbNeeded, pcReturned); |
| 4768 | |
| 4769 | RtlFreeUnicodeString(&pNameU); |
| 4770 | if (ret) { |
| 4771 | convert_printerinfo_W_to_A(pPrinters, pPrintersW, level, *pcbNeeded, *pcReturned); |
| 4772 | } |
| 4773 | HeapFree(GetProcessHeap(), 0, pPrintersW); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 4774 | return ret; |
Huw D M Davies | cb6aa38 | 1999-10-31 17:34:31 +0000 | [diff] [blame] | 4775 | } |
| 4776 | |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4777 | /***************************************************************************** |
| 4778 | * WINSPOOL_GetDriverInfoFromReg [internal] |
| 4779 | * |
| 4780 | * Enters the information from the registry into the DRIVER_INFO struct |
| 4781 | * |
| 4782 | * RETURNS |
| 4783 | * zero if the printer driver does not exist in the registry |
| 4784 | * (only if Level > 1) otherwise nonzero |
| 4785 | */ |
| 4786 | static BOOL WINSPOOL_GetDriverInfoFromReg( |
| 4787 | HKEY hkeyDrivers, |
| 4788 | LPWSTR DriverName, |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4789 | const printenv_t * env, |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4790 | DWORD Level, |
| 4791 | LPBYTE ptr, /* DRIVER_INFO */ |
| 4792 | LPBYTE pDriverStrings, /* strings buffer */ |
| 4793 | DWORD cbBuf, /* size of string buffer */ |
| 4794 | LPDWORD pcbNeeded, /* space needed for str. */ |
| 4795 | BOOL unicode) /* type of strings */ |
Dmitry Timoshkov | b13c498 | 2006-04-14 22:34:57 +0900 | [diff] [blame] | 4796 | { |
| 4797 | DWORD size, tmp; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4798 | HKEY hkeyDriver; |
Detlef Riekenberg | 4b53154 | 2007-07-26 23:05:27 +0200 | [diff] [blame] | 4799 | WCHAR driverdir[MAX_PATH]; |
| 4800 | DWORD dirlen; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4801 | LPBYTE strPtr = pDriverStrings; |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4802 | LPDRIVER_INFO_8W di = (LPDRIVER_INFO_8W) ptr; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4803 | |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4804 | TRACE("(%p, %s, %p, %d, %p, %p, %d, %d)\n", hkeyDrivers, |
| 4805 | debugstr_w(DriverName), env, |
| 4806 | Level, di, pDriverStrings, cbBuf, unicode); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4807 | |
Detlef Riekenberg | a2daf75 | 2007-07-26 23:14:55 +0200 | [diff] [blame] | 4808 | if (di) ZeroMemory(di, di_sizeof[Level]); |
| 4809 | |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4810 | if (unicode) { |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4811 | *pcbNeeded = (lstrlenW(DriverName) + 1) * sizeof(WCHAR); |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4812 | if (*pcbNeeded <= cbBuf) |
| 4813 | strcpyW((LPWSTR)strPtr, DriverName); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4814 | } |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4815 | else |
| 4816 | { |
| 4817 | *pcbNeeded = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0, NULL, NULL); |
| 4818 | if (*pcbNeeded <= cbBuf) |
| 4819 | WideCharToMultiByte(CP_ACP, 0, DriverName, -1, (LPSTR)strPtr, *pcbNeeded, NULL, NULL); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4820 | } |
| 4821 | |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4822 | /* pName for level 1 has a different offset! */ |
| 4823 | if (Level == 1) { |
| 4824 | if (di) ((LPDRIVER_INFO_1W) di)->pName = (LPWSTR) strPtr; |
| 4825 | return TRUE; |
| 4826 | } |
| 4827 | |
| 4828 | /* .cVersion and .pName for level > 1 */ |
| 4829 | if (di) { |
| 4830 | di->cVersion = env->driverversion; |
| 4831 | di->pName = (LPWSTR) strPtr; |
| 4832 | strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL; |
| 4833 | } |
| 4834 | |
Detlef Riekenberg | 4b53154 | 2007-07-26 23:05:27 +0200 | [diff] [blame] | 4835 | /* Reserve Space for the largest subdir and a Backslash*/ |
| 4836 | size = sizeof(driverdir) - sizeof(Version3_SubdirW) - sizeof(WCHAR); |
| 4837 | if (!GetPrinterDriverDirectoryW(NULL, (LPWSTR) env->envname, 1, (LPBYTE) driverdir, size, &size)) { |
| 4838 | /* Should never Fail */ |
| 4839 | return FALSE; |
| 4840 | } |
| 4841 | lstrcatW(driverdir, env->versionsubdir); |
| 4842 | lstrcatW(driverdir, backslashW); |
| 4843 | |
| 4844 | /* dirlen must not include the terminating zero */ |
| 4845 | dirlen = (unicode) ? lstrlenW(driverdir) * sizeof(WCHAR) : |
| 4846 | WideCharToMultiByte(CP_ACP, 0, driverdir, -1, NULL, 0, NULL, NULL) -1; |
| 4847 | |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4848 | if (!DriverName[0] || RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver) != ERROR_SUCCESS) { |
Francois Gouget | 42c4114 | 2007-01-18 11:37:51 +0100 | [diff] [blame] | 4849 | ERR("Can't find driver %s in registry\n", debugstr_w(DriverName)); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4850 | SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */ |
| 4851 | return FALSE; |
| 4852 | } |
| 4853 | |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4854 | /* pEnvironment */ |
| 4855 | if (unicode) |
| 4856 | size = (lstrlenW(env->envname) + 1) * sizeof(WCHAR); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4857 | else |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4858 | size = WideCharToMultiByte(CP_ACP, 0, env->envname, -1, NULL, 0, NULL, NULL); |
| 4859 | |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4860 | *pcbNeeded += size; |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4861 | if (*pcbNeeded <= cbBuf) { |
| 4862 | if (unicode) { |
| 4863 | lstrcpyW((LPWSTR)strPtr, env->envname); |
| 4864 | } |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4865 | else |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 4866 | { |
| 4867 | WideCharToMultiByte(CP_ACP, 0, env->envname, -1, (LPSTR)strPtr, size, NULL, NULL); |
| 4868 | } |
| 4869 | if (di) di->pEnvironment = (LPWSTR)strPtr; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4870 | strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL; |
| 4871 | } |
| 4872 | |
Detlef Riekenberg | 4b53154 | 2007-07-26 23:05:27 +0200 | [diff] [blame] | 4873 | /* .pDriverPath is the Graphics rendering engine. |
| 4874 | The full Path is required to avoid a crash in some apps */ |
| 4875 | if (get_filename_from_reg(hkeyDriver, driverdir, dirlen, DriverW, strPtr, 0, &size, unicode)) { |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4876 | *pcbNeeded += size; |
Detlef Riekenberg | 4b53154 | 2007-07-26 23:05:27 +0200 | [diff] [blame] | 4877 | if (*pcbNeeded <= cbBuf) |
| 4878 | get_filename_from_reg(hkeyDriver, driverdir, dirlen, DriverW, strPtr, size, &tmp, unicode); |
| 4879 | |
| 4880 | if (di) di->pDriverPath = (LPWSTR)strPtr; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4881 | strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL; |
| 4882 | } |
| 4883 | |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4884 | /* .pDataFile: For postscript-drivers, this is the ppd-file */ |
| 4885 | if (get_filename_from_reg(hkeyDriver, driverdir, dirlen, Data_FileW, strPtr, 0, &size, unicode)) { |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4886 | *pcbNeeded += size; |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4887 | if (*pcbNeeded <= cbBuf) |
| 4888 | get_filename_from_reg(hkeyDriver, driverdir, dirlen, Data_FileW, strPtr, size, &size, unicode); |
| 4889 | |
| 4890 | if (di) di->pDataFile = (LPWSTR)strPtr; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4891 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 4892 | } |
| 4893 | |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4894 | /* .pConfigFile is the Driver user Interface */ |
| 4895 | if (get_filename_from_reg(hkeyDriver, driverdir, dirlen, Configuration_FileW, strPtr, 0, &size, unicode)) { |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4896 | *pcbNeeded += size; |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4897 | if (*pcbNeeded <= cbBuf) |
| 4898 | get_filename_from_reg(hkeyDriver, driverdir, dirlen, Configuration_FileW, strPtr, size, &size, unicode); |
| 4899 | |
| 4900 | if (di) di->pConfigFile = (LPWSTR)strPtr; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4901 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 4902 | } |
| 4903 | |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4904 | if (Level == 2 ) { |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4905 | RegCloseKey(hkeyDriver); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 4906 | TRACE("buffer space %d required %d\n", cbBuf, *pcbNeeded); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4907 | return TRUE; |
| 4908 | } |
| 4909 | |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4910 | if (Level == 5 ) { |
| 4911 | RegCloseKey(hkeyDriver); |
| 4912 | FIXME("level 5: incomplete\n"); |
| 4913 | return TRUE; |
| 4914 | } |
| 4915 | |
| 4916 | /* .pHelpFile */ |
| 4917 | if (get_filename_from_reg(hkeyDriver, driverdir, dirlen, Help_FileW, strPtr, 0, &size, unicode)) { |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4918 | *pcbNeeded += size; |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4919 | if (*pcbNeeded <= cbBuf) |
| 4920 | get_filename_from_reg(hkeyDriver, driverdir, dirlen, Help_FileW, strPtr, size, &size, unicode); |
| 4921 | |
| 4922 | if (di) di->pHelpFile = (LPWSTR)strPtr; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4923 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 4924 | } |
| 4925 | |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4926 | /* .pDependentFiles */ |
| 4927 | if (get_filename_from_reg(hkeyDriver, driverdir, dirlen, Dependent_FilesW, strPtr, 0, &size, unicode)) { |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4928 | *pcbNeeded += size; |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4929 | if (*pcbNeeded <= cbBuf) |
| 4930 | get_filename_from_reg(hkeyDriver, driverdir, dirlen, Dependent_FilesW, strPtr, size, &size, unicode); |
| 4931 | |
| 4932 | if (di) di->pDependentFiles = (LPWSTR)strPtr; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4933 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 4934 | } |
Detlef Riekenberg | 449fa0d | 2007-08-24 20:05:57 +0200 | [diff] [blame] | 4935 | else if (GetVersion() & 0x80000000) { |
Francois Gouget | b2bc712 | 2007-09-27 18:57:51 +0200 | [diff] [blame] | 4936 | /* PowerPoint XP expects that pDependentFiles is always valid on win9x */ |
Detlef Riekenberg | 449fa0d | 2007-08-24 20:05:57 +0200 | [diff] [blame] | 4937 | size = 2 * ((unicode) ? sizeof(WCHAR) : 1); |
| 4938 | *pcbNeeded += size; |
| 4939 | if ((*pcbNeeded <= cbBuf) && strPtr) ZeroMemory(strPtr, size); |
| 4940 | |
| 4941 | if (di) di->pDependentFiles = (LPWSTR)strPtr; |
| 4942 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 4943 | } |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4944 | |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4945 | /* .pMonitorName is the optional Language Monitor */ |
| 4946 | if (WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size, unicode)) { |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4947 | *pcbNeeded += size; |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4948 | if (*pcbNeeded <= cbBuf) |
| 4949 | WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, size, &size, unicode); |
| 4950 | |
| 4951 | if (di) di->pMonitorName = (LPWSTR)strPtr; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4952 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 4953 | } |
| 4954 | |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4955 | /* .pDefaultDataType */ |
| 4956 | if (WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size, unicode)) { |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4957 | *pcbNeeded += size; |
| 4958 | if(*pcbNeeded <= cbBuf) |
Detlef Riekenberg | 7a2c4fb | 2007-07-26 23:24:31 +0200 | [diff] [blame] | 4959 | WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, size, &size, unicode); |
| 4960 | |
| 4961 | if (di) di->pDefaultDataType = (LPWSTR)strPtr; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 4962 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 4963 | } |
| 4964 | |
Detlef Riekenberg | 510c4dc | 2007-07-26 23:37:22 +0200 | [diff] [blame] | 4965 | if (Level == 3 ) { |
| 4966 | RegCloseKey(hkeyDriver); |
| 4967 | TRACE("buffer space %d required %d\n", cbBuf, *pcbNeeded); |
| 4968 | return TRUE; |
| 4969 | } |
| 4970 | |
| 4971 | /* .pszzPreviousNames */ |
| 4972 | if (WINSPOOL_GetStringFromReg(hkeyDriver, Previous_NamesW, strPtr, 0, &size, unicode)) { |
| 4973 | *pcbNeeded += size; |
| 4974 | if(*pcbNeeded <= cbBuf) |
| 4975 | WINSPOOL_GetStringFromReg(hkeyDriver, Previous_NamesW, strPtr, size, &size, unicode); |
| 4976 | |
| 4977 | if (di) di->pszzPreviousNames = (LPWSTR)strPtr; |
| 4978 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 4979 | } |
| 4980 | |
| 4981 | if (Level == 4 ) { |
| 4982 | RegCloseKey(hkeyDriver); |
| 4983 | TRACE("buffer space %d required %d\n", cbBuf, *pcbNeeded); |
| 4984 | return TRUE; |
| 4985 | } |
| 4986 | |
| 4987 | /* support is missing, but not important enough for a FIXME */ |
| 4988 | TRACE("%s: DriverDate + DriverVersion not supported\n", debugstr_w(DriverName)); |
| 4989 | |
| 4990 | /* .pszMfgName */ |
| 4991 | if (WINSPOOL_GetStringFromReg(hkeyDriver, ManufacturerW, strPtr, 0, &size, unicode)) { |
| 4992 | *pcbNeeded += size; |
| 4993 | if(*pcbNeeded <= cbBuf) |
| 4994 | WINSPOOL_GetStringFromReg(hkeyDriver, ManufacturerW, strPtr, size, &size, unicode); |
| 4995 | |
| 4996 | if (di) di->pszMfgName = (LPWSTR)strPtr; |
| 4997 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 4998 | } |
| 4999 | |
| 5000 | /* .pszOEMUrl */ |
| 5001 | if (WINSPOOL_GetStringFromReg(hkeyDriver, OEM_UrlW, strPtr, 0, &size, unicode)) { |
| 5002 | *pcbNeeded += size; |
| 5003 | if(*pcbNeeded <= cbBuf) |
| 5004 | WINSPOOL_GetStringFromReg(hkeyDriver, OEM_UrlW, strPtr, size, &size, unicode); |
| 5005 | |
| 5006 | if (di) di->pszOEMUrl = (LPWSTR)strPtr; |
| 5007 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 5008 | } |
| 5009 | |
| 5010 | /* .pszHardwareID */ |
| 5011 | if (WINSPOOL_GetStringFromReg(hkeyDriver, HardwareIDW, strPtr, 0, &size, unicode)) { |
| 5012 | *pcbNeeded += size; |
| 5013 | if(*pcbNeeded <= cbBuf) |
| 5014 | WINSPOOL_GetStringFromReg(hkeyDriver, HardwareIDW, strPtr, size, &size, unicode); |
| 5015 | |
| 5016 | if (di) di->pszHardwareID = (LPWSTR)strPtr; |
| 5017 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 5018 | } |
| 5019 | |
| 5020 | /* .pszProvider */ |
| 5021 | if (WINSPOOL_GetStringFromReg(hkeyDriver, ProviderW, strPtr, 0, &size, unicode)) { |
| 5022 | *pcbNeeded += size; |
| 5023 | if(*pcbNeeded <= cbBuf) |
| 5024 | WINSPOOL_GetStringFromReg(hkeyDriver, ProviderW, strPtr, size, &size, unicode); |
| 5025 | |
| 5026 | if (di) di->pszProvider = (LPWSTR)strPtr; |
| 5027 | strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL; |
| 5028 | } |
| 5029 | |
| 5030 | if (Level == 6 ) { |
| 5031 | RegCloseKey(hkeyDriver); |
| 5032 | return TRUE; |
| 5033 | } |
| 5034 | |
| 5035 | /* support is missing, but not important enough for a FIXME */ |
| 5036 | TRACE("level 8: incomplete\n"); |
| 5037 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5038 | TRACE("buffer space %d required %d\n", cbBuf, *pcbNeeded); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5039 | RegCloseKey(hkeyDriver); |
| 5040 | return TRUE; |
| 5041 | } |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5042 | |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5043 | /***************************************************************************** |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 5044 | * WINSPOOL_GetPrinterDriver |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5045 | */ |
Vitaly Lipatov | c9d78fc | 2007-02-18 13:51:09 +0300 | [diff] [blame] | 5046 | static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPCWSTR pEnvironment, |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 5047 | DWORD Level, LPBYTE pDriverInfo, |
| 5048 | DWORD cbBuf, LPDWORD pcbNeeded, |
| 5049 | BOOL unicode) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5050 | { |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 5051 | LPCWSTR name; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 5052 | WCHAR DriverName[100]; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5053 | DWORD ret, type, size, needed = 0; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5054 | LPBYTE ptr = NULL; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5055 | HKEY hkeyPrinter, hkeyPrinters, hkeyDrivers; |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 5056 | const printenv_t * env; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 5057 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5058 | TRACE("(%p,%s,%d,%p,%d,%p)\n",hPrinter,debugstr_w(pEnvironment), |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 5059 | Level,pDriverInfo,cbBuf, pcbNeeded); |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5060 | |
Ulrich Czekalla | 6a80c8a | 2000-02-25 21:38:17 +0000 | [diff] [blame] | 5061 | |
Huw Davies | df9c434 | 2005-07-05 11:00:09 +0000 | [diff] [blame] | 5062 | if (!(name = get_opened_printer_name(hPrinter))) { |
| 5063 | SetLastError(ERROR_INVALID_HANDLE); |
| 5064 | return FALSE; |
| 5065 | } |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 5066 | |
Detlef Riekenberg | a2daf75 | 2007-07-26 23:14:55 +0200 | [diff] [blame] | 5067 | if (Level < 1 || Level == 7 || Level > 8) { |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5068 | SetLastError(ERROR_INVALID_LEVEL); |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 5069 | return FALSE; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5070 | } |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 5071 | |
| 5072 | env = validate_envW(pEnvironment); |
| 5073 | if (!env) return FALSE; /* SetLastError() is in validate_envW */ |
| 5074 | |
Detlef Riekenberg | 358ce06 | 2006-05-21 14:35:29 +0200 | [diff] [blame] | 5075 | if(RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) != |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5076 | ERROR_SUCCESS) { |
| 5077 | ERR("Can't create Printers key\n"); |
| 5078 | return FALSE; |
| 5079 | } |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 5080 | if(RegOpenKeyW(hkeyPrinters, name, &hkeyPrinter) |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5081 | != ERROR_SUCCESS) { |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 5082 | ERR("Can't find opened printer %s in registry\n", debugstr_w(name)); |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5083 | RegCloseKey(hkeyPrinters); |
| 5084 | SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */ |
| 5085 | return FALSE; |
| 5086 | } |
| 5087 | size = sizeof(DriverName); |
Gerard Patel | 14c9429 | 2001-10-28 21:16:38 +0000 | [diff] [blame] | 5088 | DriverName[0] = 0; |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 5089 | ret = RegQueryValueExW(hkeyPrinter, Printer_DriverW, 0, &type, |
| 5090 | (LPBYTE)DriverName, &size); |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5091 | RegCloseKey(hkeyPrinter); |
| 5092 | RegCloseKey(hkeyPrinters); |
| 5093 | if(ret != ERROR_SUCCESS) { |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 5094 | ERR("Can't get DriverName for printer %s\n", debugstr_w(name)); |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5095 | return FALSE; |
| 5096 | } |
Stefan Leichter | ca1661c | 2000-11-06 05:26:00 +0000 | [diff] [blame] | 5097 | |
| 5098 | hkeyDrivers = WINSPOOL_OpenDriverReg( pEnvironment, TRUE); |
| 5099 | if(!hkeyDrivers) { |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5100 | ERR("Can't create Drivers key\n"); |
| 5101 | return FALSE; |
| 5102 | } |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5103 | |
Detlef Riekenberg | a2daf75 | 2007-07-26 23:14:55 +0200 | [diff] [blame] | 5104 | size = di_sizeof[Level]; |
| 5105 | if ((size <= cbBuf) && pDriverInfo) |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5106 | ptr = pDriverInfo + size; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5107 | |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5108 | if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverName, |
Detlef Riekenberg | a2daf75 | 2007-07-26 23:14:55 +0200 | [diff] [blame] | 5109 | env, Level, pDriverInfo, ptr, |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5110 | (cbBuf < size) ? 0 : cbBuf - size, |
| 5111 | &needed, unicode)) { |
| 5112 | RegCloseKey(hkeyDrivers); |
| 5113 | return FALSE; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5114 | } |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5115 | |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5116 | RegCloseKey(hkeyDrivers); |
| 5117 | |
Stefan Leichter | a2053ab | 2000-11-12 03:39:53 +0000 | [diff] [blame] | 5118 | if(pcbNeeded) *pcbNeeded = size + needed; |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5119 | TRACE("buffer space %d required %d\n", cbBuf, size + needed); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5120 | if(cbBuf >= needed) return TRUE; |
Huw D M Davies | 450270b | 1999-07-10 11:58:50 +0000 | [diff] [blame] | 5121 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5122 | return FALSE; |
| 5123 | } |
| 5124 | |
| 5125 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 5126 | * GetPrinterDriverA [WINSPOOL.@] |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 5127 | */ |
| 5128 | BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, |
| 5129 | DWORD Level, LPBYTE pDriverInfo, |
| 5130 | DWORD cbBuf, LPDWORD pcbNeeded) |
| 5131 | { |
| 5132 | BOOL ret; |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 5133 | UNICODE_STRING pEnvW; |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 5134 | PWSTR pwstrEnvW; |
| 5135 | |
| 5136 | pwstrEnvW = asciitounicode(&pEnvW, pEnvironment); |
| 5137 | ret = WINSPOOL_GetPrinterDriver(hPrinter, pwstrEnvW, Level, pDriverInfo, |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 5138 | cbBuf, pcbNeeded, FALSE); |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 5139 | RtlFreeUnicodeString(&pEnvW); |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 5140 | return ret; |
| 5141 | } |
| 5142 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 5143 | * GetPrinterDriverW [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5144 | */ |
| 5145 | BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 5146 | DWORD Level, LPBYTE pDriverInfo, |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5147 | DWORD cbBuf, LPDWORD pcbNeeded) |
| 5148 | { |
Huw D M Davies | 7aaabc3 | 2000-05-25 23:02:46 +0000 | [diff] [blame] | 5149 | return WINSPOOL_GetPrinterDriver(hPrinter, pEnvironment, Level, |
| 5150 | pDriverInfo, cbBuf, pcbNeeded, TRUE); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5151 | } |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5152 | |
| 5153 | /***************************************************************************** |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5154 | * GetPrinterDriverDirectoryW [WINSPOOL.@] |
Detlef Riekenberg | f152244 | 2005-11-28 17:29:38 +0100 | [diff] [blame] | 5155 | * |
| 5156 | * Return the PATH for the Printer-Drivers (UNICODE) |
| 5157 | * |
| 5158 | * PARAMS |
| 5159 | * pName [I] Servername (NT only) or NULL (local Computer) |
| 5160 | * pEnvironment [I] Printing-Environment (see below) or NULL (Default) |
| 5161 | * Level [I] Structure-Level (must be 1) |
| 5162 | * pDriverDirectory [O] PTR to Buffer that receives the Result |
| 5163 | * cbBuf [I] Size of Buffer at pDriverDirectory |
| 5164 | * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / |
| 5165 | * required for pDriverDirectory |
| 5166 | * |
| 5167 | * RETURNS |
| 5168 | * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory |
| 5169 | * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory, |
Francois Gouget | 5127dc9 | 2005-12-02 16:15:09 +0100 | [diff] [blame] | 5170 | * if cbBuf is too small |
Detlef Riekenberg | f152244 | 2005-11-28 17:29:38 +0100 | [diff] [blame] | 5171 | * |
| 5172 | * Native Values returned in pDriverDirectory on Success: |
| 5173 | *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86" |
| 5174 | *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40" |
| 5175 | *| win9x(Windows 4.0): "%winsysdir%" |
| 5176 | * |
| 5177 | * "%winsysdir%" is the Value from GetSystemDirectoryW() |
| 5178 | * |
| 5179 | * FIXME |
Detlef Riekenberg | 366f452 | 2006-02-01 12:32:10 +0100 | [diff] [blame] | 5180 | *- Only NULL or "" is supported for pName |
Detlef Riekenberg | f152244 | 2005-11-28 17:29:38 +0100 | [diff] [blame] | 5181 | * |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5182 | */ |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5183 | BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment, |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5184 | DWORD Level, LPBYTE pDriverDirectory, |
| 5185 | DWORD cbBuf, LPDWORD pcbNeeded) |
| 5186 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5187 | TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName), |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5188 | debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 5189 | |
Detlef Riekenberg | 36130b4 | 2008-02-04 09:51:38 +0100 | [diff] [blame] | 5190 | if ((backend == NULL) && !load_backend()) return FALSE; |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 5191 | |
Detlef Riekenberg | 36130b4 | 2008-02-04 09:51:38 +0100 | [diff] [blame] | 5192 | if (Level != 1) { |
| 5193 | /* (Level != 1) is ignored in win9x */ |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 5194 | SetLastError(ERROR_INVALID_LEVEL); |
| 5195 | return FALSE; |
| 5196 | } |
Detlef Riekenberg | 36130b4 | 2008-02-04 09:51:38 +0100 | [diff] [blame] | 5197 | if (pcbNeeded == NULL) { |
| 5198 | /* (pcbNeeded == NULL) is ignored in win9x */ |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 5199 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 5200 | return FALSE; |
| 5201 | } |
Detlef Riekenberg | 36130b4 | 2008-02-04 09:51:38 +0100 | [diff] [blame] | 5202 | |
| 5203 | return backend->fpGetPrinterDriverDirectory(pName, pEnvironment, Level, |
| 5204 | pDriverDirectory, cbBuf, pcbNeeded); |
| 5205 | |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5206 | } |
| 5207 | |
| 5208 | |
| 5209 | /***************************************************************************** |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5210 | * GetPrinterDriverDirectoryA [WINSPOOL.@] |
Detlef Riekenberg | f152244 | 2005-11-28 17:29:38 +0100 | [diff] [blame] | 5211 | * |
| 5212 | * Return the PATH for the Printer-Drivers (ANSI) |
| 5213 | * |
| 5214 | * See GetPrinterDriverDirectoryW. |
| 5215 | * |
| 5216 | * NOTES |
| 5217 | * On NT, pDriverDirectory need the same Size as the Unicode-Version |
| 5218 | * |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5219 | */ |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5220 | BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment, |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5221 | DWORD Level, LPBYTE pDriverDirectory, |
| 5222 | DWORD cbBuf, LPDWORD pcbNeeded) |
| 5223 | { |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5224 | UNICODE_STRING nameW, environmentW; |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5225 | BOOL ret; |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5226 | DWORD pcbNeededW; |
| 5227 | INT len = cbBuf * sizeof(WCHAR)/sizeof(CHAR); |
| 5228 | WCHAR *driverDirectoryW = NULL; |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5229 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5230 | TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_a(pName), |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 5231 | debugstr_a(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded); |
| 5232 | |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5233 | if (len) driverDirectoryW = HeapAlloc( GetProcessHeap(), 0, len ); |
| 5234 | |
| 5235 | if(pName) RtlCreateUnicodeStringFromAsciiz(&nameW, pName); |
| 5236 | else nameW.Buffer = NULL; |
| 5237 | if(pEnvironment) RtlCreateUnicodeStringFromAsciiz(&environmentW, pEnvironment); |
| 5238 | else environmentW.Buffer = NULL; |
| 5239 | |
| 5240 | ret = GetPrinterDriverDirectoryW( nameW.Buffer, environmentW.Buffer, Level, |
| 5241 | (LPBYTE)driverDirectoryW, len, &pcbNeededW ); |
| 5242 | if (ret) { |
Stefan Leichter | 8780853 | 2003-01-15 00:51:16 +0000 | [diff] [blame] | 5243 | DWORD needed; |
Detlef Riekenberg | 23ead2b | 2006-01-18 12:26:32 +0100 | [diff] [blame] | 5244 | needed = WideCharToMultiByte( CP_ACP, 0, driverDirectoryW, -1, |
Mike McCormack | 516a577 | 2005-08-19 10:04:03 +0000 | [diff] [blame] | 5245 | (LPSTR)pDriverDirectory, cbBuf, NULL, NULL); |
Stefan Leichter | 7a78ca0 | 2003-01-08 19:52:25 +0000 | [diff] [blame] | 5246 | if(pcbNeeded) |
Stefan Leichter | 8780853 | 2003-01-15 00:51:16 +0000 | [diff] [blame] | 5247 | *pcbNeeded = needed; |
| 5248 | ret = (needed <= cbBuf) ? TRUE : FALSE; |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5249 | } else |
Stefan Leichter | 7a78ca0 | 2003-01-08 19:52:25 +0000 | [diff] [blame] | 5250 | if(pcbNeeded) *pcbNeeded = pcbNeededW * sizeof(CHAR)/sizeof(WCHAR); |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5251 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5252 | TRACE("required: 0x%x/%d\n", pcbNeeded ? *pcbNeeded : 0, pcbNeeded ? *pcbNeeded : 0); |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5253 | |
Michael Stefaniuc | 5ad7d85 | 2004-12-23 17:06:43 +0000 | [diff] [blame] | 5254 | HeapFree( GetProcessHeap(), 0, driverDirectoryW ); |
Stefan Leichter | facaee4 | 2003-01-03 03:04:46 +0000 | [diff] [blame] | 5255 | RtlFreeUnicodeString(&environmentW); |
| 5256 | RtlFreeUnicodeString(&nameW); |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5257 | |
| 5258 | return ret; |
| 5259 | } |
| 5260 | |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5261 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 5262 | * AddPrinterDriverA [WINSPOOL.@] |
Detlef Riekenberg | b068ce5 | 2007-08-24 00:02:11 +0200 | [diff] [blame] | 5263 | * |
| 5264 | * See AddPrinterDriverW. |
| 5265 | * |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5266 | */ |
Huw D M Davies | ee2d9d5 | 1999-05-22 18:53:56 +0000 | [diff] [blame] | 5267 | BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5268 | { |
Detlef Riekenberg | b068ce5 | 2007-08-24 00:02:11 +0200 | [diff] [blame] | 5269 | TRACE("(%s, %d, %p)\n", debugstr_a(pName), level, pDriverInfo); |
| 5270 | return AddPrinterDriverExA(pName, level, pDriverInfo, APD_COPY_NEW_FILES); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5271 | } |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 5272 | |
Detlef Riekenberg | b068ce5 | 2007-08-24 00:02:11 +0200 | [diff] [blame] | 5273 | /****************************************************************************** |
| 5274 | * AddPrinterDriverW (WINSPOOL.@) |
| 5275 | * |
| 5276 | * Install a Printer Driver |
| 5277 | * |
| 5278 | * PARAMS |
| 5279 | * pName [I] Servername or NULL (local Computer) |
| 5280 | * level [I] Level for the supplied DRIVER_INFO_*W struct |
| 5281 | * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter |
| 5282 | * |
| 5283 | * RESULTS |
| 5284 | * Success: TRUE |
| 5285 | * Failure: FALSE |
| 5286 | * |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5287 | */ |
Detlef Riekenberg | b068ce5 | 2007-08-24 00:02:11 +0200 | [diff] [blame] | 5288 | BOOL WINAPI AddPrinterDriverW(LPWSTR pName, DWORD level, LPBYTE pDriverInfo) |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5289 | { |
Detlef Riekenberg | b068ce5 | 2007-08-24 00:02:11 +0200 | [diff] [blame] | 5290 | TRACE("(%s, %d, %p)\n", debugstr_w(pName), level, pDriverInfo); |
| 5291 | return AddPrinterDriverExW(pName, level, pDriverInfo, APD_COPY_NEW_FILES); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5292 | } |
| 5293 | |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 5294 | /***************************************************************************** |
| 5295 | * AddPrintProcessorA [WINSPOOL.@] |
| 5296 | */ |
| 5297 | BOOL WINAPI AddPrintProcessorA(LPSTR pName, LPSTR pEnvironment, LPSTR pPathName, |
| 5298 | LPSTR pPrintProcessorName) |
| 5299 | { |
| 5300 | FIXME("(%s,%s,%s,%s): stub\n", debugstr_a(pName), debugstr_a(pEnvironment), |
| 5301 | debugstr_a(pPathName), debugstr_a(pPrintProcessorName)); |
| 5302 | return FALSE; |
| 5303 | } |
| 5304 | |
| 5305 | /***************************************************************************** |
| 5306 | * AddPrintProcessorW [WINSPOOL.@] |
| 5307 | */ |
| 5308 | BOOL WINAPI AddPrintProcessorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pPathName, |
| 5309 | LPWSTR pPrintProcessorName) |
| 5310 | { |
| 5311 | FIXME("(%s,%s,%s,%s): stub\n", debugstr_w(pName), debugstr_w(pEnvironment), |
| 5312 | debugstr_w(pPathName), debugstr_w(pPrintProcessorName)); |
| 5313 | return FALSE; |
| 5314 | } |
| 5315 | |
| 5316 | /***************************************************************************** |
| 5317 | * AddPrintProvidorA [WINSPOOL.@] |
| 5318 | */ |
| 5319 | BOOL WINAPI AddPrintProvidorA(LPSTR pName, DWORD Level, LPBYTE pProviderInfo) |
| 5320 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5321 | FIXME("(%s,0x%08x,%p): stub\n", debugstr_a(pName), Level, pProviderInfo); |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 5322 | return FALSE; |
| 5323 | } |
| 5324 | |
| 5325 | /***************************************************************************** |
| 5326 | * AddPrintProvidorW [WINSPOOL.@] |
| 5327 | */ |
| 5328 | BOOL WINAPI AddPrintProvidorW(LPWSTR pName, DWORD Level, LPBYTE pProviderInfo) |
| 5329 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5330 | FIXME("(%s,0x%08x,%p): stub\n", debugstr_w(pName), Level, pProviderInfo); |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 5331 | return FALSE; |
| 5332 | } |
| 5333 | |
| 5334 | /***************************************************************************** |
| 5335 | * AdvancedDocumentPropertiesA [WINSPOOL.@] |
| 5336 | */ |
| 5337 | LONG WINAPI AdvancedDocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, |
| 5338 | PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput) |
| 5339 | { |
| 5340 | FIXME("(%p,%p,%s,%p,%p): stub\n", hWnd, hPrinter, debugstr_a(pDeviceName), |
| 5341 | pDevModeOutput, pDevModeInput); |
| 5342 | return 0; |
| 5343 | } |
| 5344 | |
| 5345 | /***************************************************************************** |
| 5346 | * AdvancedDocumentPropertiesW [WINSPOOL.@] |
| 5347 | */ |
| 5348 | LONG WINAPI AdvancedDocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, |
| 5349 | PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput) |
| 5350 | { |
| 5351 | FIXME("(%p,%p,%s,%p,%p): stub\n", hWnd, hPrinter, debugstr_w(pDeviceName), |
| 5352 | pDevModeOutput, pDevModeInput); |
| 5353 | return 0; |
| 5354 | } |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5355 | |
| 5356 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 5357 | * PrinterProperties [WINSPOOL.@] |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5358 | * |
| 5359 | * Displays a dialog to set the properties of the printer. |
| 5360 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 5361 | * RETURNS |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 5362 | * nonzero on success or zero on failure |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5363 | * |
| 5364 | * BUGS |
| 5365 | * implemented as stub only |
| 5366 | */ |
Patrik Stridvall | 2b3aa61 | 2000-12-01 23:58:28 +0000 | [diff] [blame] | 5367 | BOOL WINAPI PrinterProperties(HWND hWnd, /* [in] handle to parent window */ |
| 5368 | HANDLE hPrinter /* [in] handle to printer object */ |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5369 | ){ |
Michael Stefaniuc | ea335dd | 2002-10-22 00:47:33 +0000 | [diff] [blame] | 5370 | FIXME("(%p,%p): stub\n", hWnd, hPrinter); |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5371 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| 5372 | return FALSE; |
| 5373 | } |
| 5374 | |
Huw D M Davies | bb14056 | 1999-07-23 19:23:49 +0000 | [diff] [blame] | 5375 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 5376 | * EnumJobsA [WINSPOOL.@] |
Huw D M Davies | bb14056 | 1999-07-23 19:23:49 +0000 | [diff] [blame] | 5377 | * |
| 5378 | */ |
| 5379 | BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, |
| 5380 | DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded, |
| 5381 | LPDWORD pcReturned) |
| 5382 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5383 | FIXME("(%p,first=%d,no=%d,level=%d,job=%p,cb=%d,%p,%p), stub!\n", |
Marcus Meissner | f061f76 | 2002-11-12 02:22:24 +0000 | [diff] [blame] | 5384 | hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned |
| 5385 | ); |
Huw D M Davies | bb14056 | 1999-07-23 19:23:49 +0000 | [diff] [blame] | 5386 | if(pcbNeeded) *pcbNeeded = 0; |
| 5387 | if(pcReturned) *pcReturned = 0; |
Marcus Meissner | f061f76 | 2002-11-12 02:22:24 +0000 | [diff] [blame] | 5388 | return FALSE; |
Huw D M Davies | bb14056 | 1999-07-23 19:23:49 +0000 | [diff] [blame] | 5389 | } |
Huw D M Davies | e39b676 | 1999-05-17 16:20:51 +0000 | [diff] [blame] | 5390 | |
Huw D M Davies | bb14056 | 1999-07-23 19:23:49 +0000 | [diff] [blame] | 5391 | |
| 5392 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 5393 | * EnumJobsW [WINSPOOL.@] |
Huw D M Davies | bb14056 | 1999-07-23 19:23:49 +0000 | [diff] [blame] | 5394 | * |
| 5395 | */ |
| 5396 | BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, |
| 5397 | DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded, |
| 5398 | LPDWORD pcReturned) |
| 5399 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5400 | FIXME("(%p,first=%d,no=%d,level=%d,job=%p,cb=%d,%p,%p), stub!\n", |
Marcus Meissner | f061f76 | 2002-11-12 02:22:24 +0000 | [diff] [blame] | 5401 | hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned |
| 5402 | ); |
Huw D M Davies | bb14056 | 1999-07-23 19:23:49 +0000 | [diff] [blame] | 5403 | if(pcbNeeded) *pcbNeeded = 0; |
| 5404 | if(pcReturned) *pcReturned = 0; |
Marcus Meissner | f061f76 | 2002-11-12 02:22:24 +0000 | [diff] [blame] | 5405 | return FALSE; |
Huw D M Davies | bb14056 | 1999-07-23 19:23:49 +0000 | [diff] [blame] | 5406 | } |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5407 | |
| 5408 | /***************************************************************************** |
| 5409 | * WINSPOOL_EnumPrinterDrivers [internal] |
| 5410 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 5411 | * Delivers information about all printer drivers installed on the |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5412 | * localhost or a given server |
| 5413 | * |
| 5414 | * RETURNS |
Alexandre Julliard | e1635e9 | 2001-02-28 05:26:08 +0000 | [diff] [blame] | 5415 | * nonzero on success or zero on failure. If the buffer for the returned |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5416 | * information is too small the function will return an error |
| 5417 | * |
| 5418 | * BUGS |
| 5419 | * - only implemented for localhost, foreign hosts will return an error |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5420 | */ |
Vitaly Lipatov | c9d78fc | 2007-02-18 13:51:09 +0300 | [diff] [blame] | 5421 | static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPCWSTR pEnvironment, |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5422 | DWORD Level, LPBYTE pDriverInfo, |
| 5423 | DWORD cbBuf, LPDWORD pcbNeeded, |
| 5424 | LPDWORD pcReturned, BOOL unicode) |
| 5425 | |
| 5426 | { HKEY hkeyDrivers; |
| 5427 | DWORD i, needed, number = 0, size = 0; |
| 5428 | WCHAR DriverNameW[255]; |
| 5429 | PBYTE ptr; |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 5430 | const printenv_t * env; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5431 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5432 | TRACE("%s,%s,%d,%p,%d,%d\n", |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5433 | debugstr_w(pName), debugstr_w(pEnvironment), |
| 5434 | Level, pDriverInfo, cbBuf, unicode); |
| 5435 | |
| 5436 | /* check for local drivers */ |
Detlef Riekenberg | 5de733e | 2006-05-20 18:39:20 +0200 | [diff] [blame] | 5437 | if((pName) && (pName[0])) { |
| 5438 | FIXME("remote drivers (%s) not supported!\n", debugstr_w(pName)); |
| 5439 | SetLastError(ERROR_ACCESS_DENIED); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5440 | return FALSE; |
| 5441 | } |
| 5442 | |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 5443 | env = validate_envW(pEnvironment); |
| 5444 | if (!env) return FALSE; /* SetLastError() is in validate_envW */ |
| 5445 | |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5446 | /* check input parameter */ |
Detlef Riekenberg | a2daf75 | 2007-07-26 23:14:55 +0200 | [diff] [blame] | 5447 | if ((Level < 1) || (Level == 7) || (Level > 8)) { |
Mike McCormack | 1a10b1c | 2004-11-24 18:11:28 +0000 | [diff] [blame] | 5448 | SetLastError(ERROR_INVALID_LEVEL); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5449 | return FALSE; |
| 5450 | } |
| 5451 | |
Detlef Riekenberg | 5c04d1f | 2007-08-10 10:47:36 +0200 | [diff] [blame] | 5452 | if ((pcbNeeded == NULL) || (pcReturned == NULL)) { |
| 5453 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 5454 | return FALSE; |
| 5455 | } |
| 5456 | |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5457 | /* initialize return values */ |
| 5458 | if(pDriverInfo) |
| 5459 | memset( pDriverInfo, 0, cbBuf); |
| 5460 | *pcbNeeded = 0; |
| 5461 | *pcReturned = 0; |
| 5462 | |
Stefan Leichter | ca1661c | 2000-11-06 05:26:00 +0000 | [diff] [blame] | 5463 | hkeyDrivers = WINSPOOL_OpenDriverReg(pEnvironment, TRUE); |
| 5464 | if(!hkeyDrivers) { |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5465 | ERR("Can't open Drivers key\n"); |
| 5466 | return FALSE; |
| 5467 | } |
| 5468 | |
| 5469 | if(RegQueryInfoKeyA(hkeyDrivers, NULL, NULL, NULL, &number, NULL, NULL, |
| 5470 | NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { |
| 5471 | RegCloseKey(hkeyDrivers); |
| 5472 | ERR("Can't query Drivers key\n"); |
| 5473 | return FALSE; |
| 5474 | } |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5475 | TRACE("Found %d Drivers\n", number); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5476 | |
| 5477 | /* get size of single struct |
| 5478 | * unicode and ascii structure have the same size |
| 5479 | */ |
Detlef Riekenberg | a2daf75 | 2007-07-26 23:14:55 +0200 | [diff] [blame] | 5480 | size = di_sizeof[Level]; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5481 | |
| 5482 | /* calculate required buffer size */ |
| 5483 | *pcbNeeded = size * number; |
| 5484 | |
| 5485 | for( i = 0, ptr = (pDriverInfo && (cbBuf >= size)) ? pDriverInfo : NULL ; |
| 5486 | i < number; |
| 5487 | i++, ptr = (ptr && (cbBuf >= size * i)) ? ptr + size : NULL) { |
Vitaly Lipatov | 914e78a | 2007-12-01 19:43:37 +0300 | [diff] [blame] | 5488 | if(RegEnumKeyW(hkeyDrivers, i, DriverNameW, sizeof(DriverNameW)/sizeof(DriverNameW[0])) |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5489 | != ERROR_SUCCESS) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5490 | ERR("Can't enum key number %d\n", i); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5491 | RegCloseKey(hkeyDrivers); |
| 5492 | return FALSE; |
| 5493 | } |
| 5494 | if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverNameW, |
Detlef Riekenberg | 92f843d | 2007-07-22 17:21:25 +0200 | [diff] [blame] | 5495 | env, Level, ptr, |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5496 | (cbBuf < *pcbNeeded) ? NULL : pDriverInfo + *pcbNeeded, |
| 5497 | (cbBuf < *pcbNeeded) ? 0 : cbBuf - *pcbNeeded, |
| 5498 | &needed, unicode)) { |
| 5499 | RegCloseKey(hkeyDrivers); |
| 5500 | return FALSE; |
| 5501 | } |
| 5502 | (*pcbNeeded) += needed; |
| 5503 | } |
| 5504 | |
| 5505 | RegCloseKey(hkeyDrivers); |
| 5506 | |
| 5507 | if(cbBuf < *pcbNeeded){ |
| 5508 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 5509 | return FALSE; |
| 5510 | } |
| 5511 | |
Detlef Riekenberg | 7bb00b1 | 2005-09-13 10:32:33 +0000 | [diff] [blame] | 5512 | *pcReturned = number; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5513 | return TRUE; |
| 5514 | } |
| 5515 | |
| 5516 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 5517 | * EnumPrinterDriversW [WINSPOOL.@] |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5518 | * |
| 5519 | * see function EnumPrinterDrivers for RETURNS, BUGS |
| 5520 | */ |
| 5521 | BOOL WINAPI EnumPrinterDriversW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, |
| 5522 | LPBYTE pDriverInfo, DWORD cbBuf, |
| 5523 | LPDWORD pcbNeeded, LPDWORD pcReturned) |
| 5524 | { |
| 5525 | return WINSPOOL_EnumPrinterDrivers(pName, pEnvironment, Level, pDriverInfo, |
| 5526 | cbBuf, pcbNeeded, pcReturned, TRUE); |
| 5527 | } |
| 5528 | |
| 5529 | /***************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 5530 | * EnumPrinterDriversA [WINSPOOL.@] |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5531 | * |
| 5532 | * see function EnumPrinterDrivers for RETURNS, BUGS |
| 5533 | */ |
| 5534 | BOOL WINAPI EnumPrinterDriversA(LPSTR pName, LPSTR pEnvironment, DWORD Level, |
| 5535 | LPBYTE pDriverInfo, DWORD cbBuf, |
| 5536 | LPDWORD pcbNeeded, LPDWORD pcReturned) |
| 5537 | { BOOL ret; |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 5538 | UNICODE_STRING pNameW, pEnvironmentW; |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 5539 | PWSTR pwstrNameW, pwstrEnvironmentW; |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5540 | |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 5541 | pwstrNameW = asciitounicode(&pNameW, pName); |
| 5542 | pwstrEnvironmentW = asciitounicode(&pEnvironmentW, pEnvironment); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5543 | |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 5544 | ret = WINSPOOL_EnumPrinterDrivers(pwstrNameW, pwstrEnvironmentW, |
Matthew Davison | 60009b9 | 2003-01-23 23:07:38 +0000 | [diff] [blame] | 5545 | Level, pDriverInfo, cbBuf, pcbNeeded, |
| 5546 | pcReturned, FALSE); |
Duane Clark | 0987ae0 | 2003-02-12 01:19:25 +0000 | [diff] [blame] | 5547 | RtlFreeUnicodeString(&pNameW); |
| 5548 | RtlFreeUnicodeString(&pEnvironmentW); |
Stefan Leichter | 5cfe177 | 2000-09-29 21:05:11 +0000 | [diff] [blame] | 5549 | |
| 5550 | return ret; |
| 5551 | } |
Alexandre Julliard | 89b18a7 | 2000-11-28 22:33:46 +0000 | [diff] [blame] | 5552 | |
Alexandre Julliard | 89b18a7 | 2000-11-28 22:33:46 +0000 | [diff] [blame] | 5553 | /****************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 5554 | * EnumPortsA (WINSPOOL.@) |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 5555 | * |
| 5556 | * See EnumPortsW. |
| 5557 | * |
Alexandre Julliard | 89b18a7 | 2000-11-28 22:33:46 +0000 | [diff] [blame] | 5558 | */ |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5559 | BOOL WINAPI EnumPortsA( LPSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf, |
| 5560 | LPDWORD pcbNeeded, LPDWORD pcReturned) |
Alexandre Julliard | 89b18a7 | 2000-11-28 22:33:46 +0000 | [diff] [blame] | 5561 | { |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5562 | BOOL res; |
| 5563 | LPBYTE bufferW = NULL; |
| 5564 | LPWSTR nameW = NULL; |
| 5565 | DWORD needed = 0; |
| 5566 | DWORD numentries = 0; |
| 5567 | INT len; |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5568 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5569 | TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_a(pName), Level, pPorts, |
| 5570 | cbBuf, pcbNeeded, pcReturned); |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5571 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5572 | /* convert servername to unicode */ |
| 5573 | if (pName) { |
| 5574 | len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); |
| 5575 | nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 5576 | MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5577 | } |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5578 | /* alloc (userbuffersize*sizeof(WCHAR) and try to enum the Ports */ |
| 5579 | needed = cbBuf * sizeof(WCHAR); |
| 5580 | if (needed) bufferW = HeapAlloc(GetProcessHeap(), 0, needed); |
| 5581 | res = EnumPortsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned); |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5582 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5583 | if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { |
| 5584 | if (pcbNeeded) needed = *pcbNeeded; |
| 5585 | /* HeapReAlloc return NULL, when bufferW was NULL */ |
| 5586 | bufferW = (bufferW) ? HeapReAlloc(GetProcessHeap(), 0, bufferW, needed) : |
| 5587 | HeapAlloc(GetProcessHeap(), 0, needed); |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5588 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5589 | /* Try again with the large Buffer */ |
| 5590 | res = EnumPortsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned); |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5591 | } |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5592 | needed = pcbNeeded ? *pcbNeeded : 0; |
| 5593 | numentries = pcReturned ? *pcReturned : 0; |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5594 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5595 | /* |
| 5596 | W2k require the buffersize from EnumPortsW also for EnumPortsA. |
| 5597 | We use the smaller Ansi-Size to avoid conflicts with fixed Buffers of old Apps. |
| 5598 | */ |
| 5599 | if (res) { |
Francois Gouget | b0bde6b | 2007-01-18 11:35:50 +0100 | [diff] [blame] | 5600 | /* EnumPortsW collected all Data. Parse them to calculate ANSI-Size */ |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5601 | DWORD entrysize = 0; |
| 5602 | DWORD index; |
| 5603 | LPSTR ptr; |
| 5604 | LPPORT_INFO_2W pi2w; |
| 5605 | LPPORT_INFO_2A pi2a; |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5606 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5607 | needed = 0; |
| 5608 | entrysize = (Level == 1) ? sizeof(PORT_INFO_1A) : sizeof(PORT_INFO_2A); |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5609 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5610 | /* First pass: calculate the size for all Entries */ |
| 5611 | pi2w = (LPPORT_INFO_2W) bufferW; |
| 5612 | pi2a = (LPPORT_INFO_2A) pPorts; |
| 5613 | index = 0; |
| 5614 | while (index < numentries) { |
| 5615 | index++; |
| 5616 | needed += entrysize; /* PORT_INFO_?A */ |
| 5617 | TRACE("%p: parsing #%d (%s)\n", pi2w, index, debugstr_w(pi2w->pPortName)); |
Mike McCormack | d71bc33 | 2004-10-18 19:38:57 +0000 | [diff] [blame] | 5618 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5619 | needed += WideCharToMultiByte(CP_ACP, 0, pi2w->pPortName, -1, |
| 5620 | NULL, 0, NULL, NULL); |
| 5621 | if (Level > 1) { |
| 5622 | needed += WideCharToMultiByte(CP_ACP, 0, pi2w->pMonitorName, -1, |
| 5623 | NULL, 0, NULL, NULL); |
| 5624 | needed += WideCharToMultiByte(CP_ACP, 0, pi2w->pDescription, -1, |
| 5625 | NULL, 0, NULL, NULL); |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5626 | } |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5627 | /* use LPBYTE with entrysize to avoid double code (PORT_INFO_1 + PORT_INFO_2) */ |
| 5628 | pi2w = (LPPORT_INFO_2W) (((LPBYTE)pi2w) + entrysize); |
| 5629 | pi2a = (LPPORT_INFO_2A) (((LPBYTE)pi2a) + entrysize); |
Mike McCormack | d71bc33 | 2004-10-18 19:38:57 +0000 | [diff] [blame] | 5630 | } |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5631 | |
| 5632 | /* check for errors and quit on failure */ |
| 5633 | if (cbBuf < needed) { |
| 5634 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 5635 | res = FALSE; |
| 5636 | goto cleanup; |
| 5637 | } |
| 5638 | len = entrysize * numentries; /* room for all PORT_INFO_?A */ |
| 5639 | ptr = (LPSTR) &pPorts[len]; /* room for strings */ |
| 5640 | cbBuf -= len ; /* free Bytes in the user-Buffer */ |
| 5641 | pi2w = (LPPORT_INFO_2W) bufferW; |
| 5642 | pi2a = (LPPORT_INFO_2A) pPorts; |
| 5643 | index = 0; |
| 5644 | /* Second Pass: Fill the User Buffer (if we have one) */ |
| 5645 | while ((index < numentries) && pPorts) { |
| 5646 | index++; |
| 5647 | TRACE("%p: writing PORT_INFO_%dA #%d\n", pi2a, Level, index); |
| 5648 | pi2a->pPortName = ptr; |
| 5649 | len = WideCharToMultiByte(CP_ACP, 0, pi2w->pPortName, -1, |
| 5650 | ptr, cbBuf , NULL, NULL); |
| 5651 | ptr += len; |
| 5652 | cbBuf -= len; |
| 5653 | if (Level > 1) { |
| 5654 | pi2a->pMonitorName = ptr; |
| 5655 | len = WideCharToMultiByte(CP_ACP, 0, pi2w->pMonitorName, -1, |
| 5656 | ptr, cbBuf, NULL, NULL); |
| 5657 | ptr += len; |
| 5658 | cbBuf -= len; |
| 5659 | |
| 5660 | pi2a->pDescription = ptr; |
| 5661 | len = WideCharToMultiByte(CP_ACP, 0, pi2w->pDescription, -1, |
| 5662 | ptr, cbBuf, NULL, NULL); |
| 5663 | ptr += len; |
| 5664 | cbBuf -= len; |
| 5665 | |
| 5666 | pi2a->fPortType = pi2w->fPortType; |
| 5667 | pi2a->Reserved = 0; /* documented: "must be zero" */ |
| 5668 | |
| 5669 | } |
| 5670 | /* use LPBYTE with entrysize to avoid double code (PORT_INFO_1 + PORT_INFO_2) */ |
| 5671 | pi2w = (LPPORT_INFO_2W) (((LPBYTE)pi2w) + entrysize); |
| 5672 | pi2a = (LPPORT_INFO_2A) (((LPBYTE)pi2a) + entrysize); |
| 5673 | } |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5674 | } |
| 5675 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5676 | cleanup: |
| 5677 | if (pcbNeeded) *pcbNeeded = needed; |
| 5678 | if (pcReturned) *pcReturned = (res) ? numentries : 0; |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5679 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5680 | HeapFree(GetProcessHeap(), 0, nameW); |
| 5681 | HeapFree(GetProcessHeap(), 0, bufferW); |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5682 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5683 | TRACE("returning %d with %d (%d byte for %d of %d entries)\n", |
| 5684 | (res), GetLastError(), needed, (res)? numentries : 0, numentries); |
Huw Davies | 686a9f9 | 2003-05-19 23:19:21 +0000 | [diff] [blame] | 5685 | |
Detlef Riekenberg | ecce2d8 | 2006-11-04 00:27:31 +0100 | [diff] [blame] | 5686 | return (res); |
| 5687 | |
Alexandre Julliard | 89b18a7 | 2000-11-28 22:33:46 +0000 | [diff] [blame] | 5688 | } |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5689 | |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 5690 | /****************************************************************************** |
| 5691 | * EnumPortsW (WINSPOOL.@) |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 5692 | * |
| 5693 | * Enumerate available Ports |
| 5694 | * |
| 5695 | * PARAMS |
| 5696 | * name [I] Servername or NULL (local Computer) |
| 5697 | * level [I] Structure-Level (1 or 2) |
| 5698 | * buffer [O] PTR to Buffer that receives the Result |
| 5699 | * bufsize [I] Size of Buffer at buffer |
| 5700 | * bufneeded [O] PTR to DWORD that receives the size in Bytes used / required for buffer |
| 5701 | * bufreturned [O] PTR to DWORD that receives the number of Ports in buffer |
| 5702 | * |
| 5703 | * RETURNS |
| 5704 | * Success: TRUE |
| 5705 | * Failure: FALSE and in bufneeded the Bytes required for buffer, if bufsize is too small |
| 5706 | * |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 5707 | */ |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 5708 | |
| 5709 | BOOL WINAPI EnumPortsW(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 5710 | { |
Detlef Riekenberg | 412acde | 2006-11-04 00:27:16 +0100 | [diff] [blame] | 5711 | DWORD needed = 0; |
| 5712 | DWORD numentries = 0; |
| 5713 | BOOL res = FALSE; |
| 5714 | |
| 5715 | TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pPorts, |
| 5716 | cbBuf, pcbNeeded, pcReturned); |
| 5717 | |
| 5718 | if (pName && (pName[0])) { |
| 5719 | FIXME("not implemented for Server %s\n", debugstr_w(pName)); |
| 5720 | SetLastError(ERROR_ACCESS_DENIED); |
| 5721 | goto emP_cleanup; |
| 5722 | } |
| 5723 | |
| 5724 | /* Level is not checked in win9x */ |
| 5725 | if (!Level || (Level > 2)) { |
| 5726 | WARN("level (%d) is ignored in win9x\n", Level); |
| 5727 | SetLastError(ERROR_INVALID_LEVEL); |
| 5728 | goto emP_cleanup; |
| 5729 | } |
| 5730 | if (!pcbNeeded) { |
| 5731 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 5732 | goto emP_cleanup; |
| 5733 | } |
| 5734 | |
| 5735 | EnterCriticalSection(&monitor_handles_cs); |
| 5736 | monitor_loadall(); |
| 5737 | |
| 5738 | /* Scan all local Ports */ |
| 5739 | numentries = 0; |
| 5740 | needed = get_ports_from_all_monitors(Level, NULL, 0, &numentries); |
| 5741 | |
| 5742 | /* we calculated the needed buffersize. now do the error-checks */ |
| 5743 | if (cbBuf < needed) { |
| 5744 | monitor_unloadall(); |
| 5745 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 5746 | goto emP_cleanup_cs; |
| 5747 | } |
| 5748 | else if (!pPorts || !pcReturned) { |
| 5749 | monitor_unloadall(); |
| 5750 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 5751 | goto emP_cleanup_cs; |
| 5752 | } |
| 5753 | |
| 5754 | /* Fill the Buffer */ |
| 5755 | needed = get_ports_from_all_monitors(Level, pPorts, cbBuf, &numentries); |
| 5756 | res = TRUE; |
| 5757 | monitor_unloadall(); |
| 5758 | |
| 5759 | emP_cleanup_cs: |
| 5760 | LeaveCriticalSection(&monitor_handles_cs); |
| 5761 | |
| 5762 | emP_cleanup: |
| 5763 | if (pcbNeeded) *pcbNeeded = needed; |
| 5764 | if (pcReturned) *pcReturned = (res) ? numentries : 0; |
| 5765 | |
| 5766 | TRACE("returning %d with %d (%d byte for %d of %d entries)\n", |
| 5767 | (res), GetLastError(), needed, (res)? numentries : 0, numentries); |
| 5768 | |
| 5769 | return (res); |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 5770 | } |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 5771 | |
| 5772 | /****************************************************************************** |
| 5773 | * GetDefaultPrinterW (WINSPOOL.@) |
| 5774 | * |
| 5775 | * FIXME |
| 5776 | * This function must read the value from data 'device' of key |
| 5777 | * HCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows |
| 5778 | */ |
| 5779 | BOOL WINAPI GetDefaultPrinterW(LPWSTR name, LPDWORD namesize) |
| 5780 | { |
| 5781 | BOOL retval = TRUE; |
| 5782 | DWORD insize, len; |
| 5783 | WCHAR *buffer, *ptr; |
| 5784 | |
| 5785 | if (!namesize) |
| 5786 | { |
| 5787 | SetLastError(ERROR_INVALID_PARAMETER); |
| 5788 | return FALSE; |
| 5789 | } |
| 5790 | |
| 5791 | /* make the buffer big enough for the stuff from the profile/registry, |
| 5792 | * the content must fit into the local buffer to compute the correct |
Francois Gouget | f5c9da6 | 2005-05-06 15:44:31 +0000 | [diff] [blame] | 5793 | * size even if the extern buffer is too small or not given. |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 5794 | * (20 for ,driver,port) */ |
| 5795 | insize = *namesize; |
| 5796 | len = max(100, (insize + 20)); |
| 5797 | buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 5798 | |
| 5799 | if (!GetProfileStringW(windowsW, deviceW, emptyStringW, buffer, len)) |
| 5800 | { |
| 5801 | SetLastError (ERROR_FILE_NOT_FOUND); |
| 5802 | retval = FALSE; |
| 5803 | goto end; |
| 5804 | } |
| 5805 | TRACE("%s\n", debugstr_w(buffer)); |
| 5806 | |
| 5807 | if ((ptr = strchrW(buffer, ',')) == NULL) |
| 5808 | { |
| 5809 | SetLastError(ERROR_INVALID_NAME); |
| 5810 | retval = FALSE; |
| 5811 | goto end; |
| 5812 | } |
| 5813 | |
| 5814 | *ptr = 0; |
| 5815 | *namesize = strlenW(buffer) + 1; |
| 5816 | if(!name || (*namesize > insize)) |
| 5817 | { |
| 5818 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 5819 | retval = FALSE; |
| 5820 | goto end; |
| 5821 | } |
| 5822 | strcpyW(name, buffer); |
| 5823 | |
| 5824 | end: |
Michael Stefaniuc | 5ad7d85 | 2004-12-23 17:06:43 +0000 | [diff] [blame] | 5825 | HeapFree( GetProcessHeap(), 0, buffer); |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 5826 | return retval; |
| 5827 | } |
| 5828 | |
| 5829 | |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5830 | /****************************************************************************** |
Mark G. Adams | a0324f7 | 2002-01-22 00:49:24 +0000 | [diff] [blame] | 5831 | * GetDefaultPrinterA (WINSPOOL.@) |
Mark G. Adams | a0324f7 | 2002-01-22 00:49:24 +0000 | [diff] [blame] | 5832 | */ |
| 5833 | BOOL WINAPI GetDefaultPrinterA(LPSTR name, LPDWORD namesize) |
| 5834 | { |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 5835 | BOOL retval = TRUE; |
| 5836 | DWORD insize = 0; |
| 5837 | WCHAR *bufferW = NULL; |
Mark G. Adams | a0324f7 | 2002-01-22 00:49:24 +0000 | [diff] [blame] | 5838 | |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 5839 | if (!namesize) |
| 5840 | { |
| 5841 | SetLastError(ERROR_INVALID_PARAMETER); |
| 5842 | return FALSE; |
| 5843 | } |
Mark G. Adams | a0324f7 | 2002-01-22 00:49:24 +0000 | [diff] [blame] | 5844 | |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 5845 | if(name && *namesize) { |
| 5846 | insize = *namesize; |
| 5847 | bufferW = HeapAlloc( GetProcessHeap(), 0, insize * sizeof(WCHAR)); |
| 5848 | } |
Mark G. Adams | a0324f7 | 2002-01-22 00:49:24 +0000 | [diff] [blame] | 5849 | |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 5850 | if(!GetDefaultPrinterW( bufferW, namesize)) { |
| 5851 | retval = FALSE; |
| 5852 | goto end; |
| 5853 | } |
Mark G. Adams | a0324f7 | 2002-01-22 00:49:24 +0000 | [diff] [blame] | 5854 | |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 5855 | *namesize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, name, insize, |
| 5856 | NULL, NULL); |
| 5857 | if (!*namesize) |
| 5858 | { |
| 5859 | *namesize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL); |
| 5860 | retval = FALSE; |
| 5861 | } |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5862 | TRACE("0x%08x/0x%08x:%s\n", *namesize, insize, debugstr_w(bufferW)); |
Mark G. Adams | a0324f7 | 2002-01-22 00:49:24 +0000 | [diff] [blame] | 5863 | |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 5864 | end: |
Michael Stefaniuc | 5ad7d85 | 2004-12-23 17:06:43 +0000 | [diff] [blame] | 5865 | HeapFree( GetProcessHeap(), 0, bufferW); |
Stefan Leichter | 03210d4 | 2004-03-07 03:46:54 +0000 | [diff] [blame] | 5866 | return retval; |
Mark G. Adams | a0324f7 | 2002-01-22 00:49:24 +0000 | [diff] [blame] | 5867 | } |
| 5868 | |
| 5869 | |
| 5870 | /****************************************************************************** |
Detlef Riekenberg | e267ccf | 2006-02-20 11:51:04 +0100 | [diff] [blame] | 5871 | * SetDefaultPrinterW (WINSPOOL.204) |
| 5872 | * |
| 5873 | * Set the Name of the Default Printer |
| 5874 | * |
| 5875 | * PARAMS |
| 5876 | * pszPrinter [I] Name of the Printer or NULL |
| 5877 | * |
| 5878 | * RETURNS |
| 5879 | * Success: True |
| 5880 | * Failure: FALSE |
| 5881 | * |
| 5882 | * NOTES |
| 5883 | * When the Parameter is NULL or points to an Empty String and |
| 5884 | * a Default Printer was already present, then this Function changes nothing. |
| 5885 | * Without a Default Printer and NULL (or an Empty String) as Parameter, |
| 5886 | * the First enumerated local Printer is used. |
| 5887 | * |
| 5888 | */ |
| 5889 | BOOL WINAPI SetDefaultPrinterW(LPCWSTR pszPrinter) |
| 5890 | { |
| 5891 | |
| 5892 | TRACE("(%s)\n", debugstr_w(pszPrinter)); |
| 5893 | |
| 5894 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| 5895 | return FALSE; |
| 5896 | } |
| 5897 | |
| 5898 | /****************************************************************************** |
| 5899 | * SetDefaultPrinterA (WINSPOOL.202) |
| 5900 | * |
| 5901 | * See SetDefaultPrinterW. |
| 5902 | * |
| 5903 | */ |
| 5904 | BOOL WINAPI SetDefaultPrinterA(LPCSTR pszPrinter) |
| 5905 | { |
| 5906 | |
| 5907 | TRACE("(%s)\n", debugstr_a(pszPrinter)); |
| 5908 | |
| 5909 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| 5910 | return FALSE; |
| 5911 | } |
| 5912 | |
| 5913 | |
| 5914 | /****************************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 5915 | * SetPrinterDataExA (WINSPOOL.@) |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5916 | */ |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 5917 | DWORD WINAPI SetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, |
| 5918 | LPCSTR pValueName, DWORD Type, |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5919 | LPBYTE pData, DWORD cbData) |
| 5920 | { |
| 5921 | HKEY hkeyPrinter, hkeySubkey; |
| 5922 | DWORD ret; |
| 5923 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5924 | TRACE("(%p, %s, %s %08x, %p, %08x)\n", hPrinter, debugstr_a(pKeyName), |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5925 | debugstr_a(pValueName), Type, pData, cbData); |
| 5926 | |
| 5927 | if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter)) |
| 5928 | != ERROR_SUCCESS) |
| 5929 | return ret; |
| 5930 | |
| 5931 | if((ret = RegCreateKeyA(hkeyPrinter, pKeyName, &hkeySubkey)) |
| 5932 | != ERROR_SUCCESS) { |
| 5933 | ERR("Can't create subkey %s\n", debugstr_a(pKeyName)); |
| 5934 | RegCloseKey(hkeyPrinter); |
| 5935 | return ret; |
| 5936 | } |
| 5937 | ret = RegSetValueExA(hkeySubkey, pValueName, 0, Type, pData, cbData); |
| 5938 | RegCloseKey(hkeySubkey); |
| 5939 | RegCloseKey(hkeyPrinter); |
| 5940 | return ret; |
| 5941 | } |
| 5942 | |
| 5943 | /****************************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 5944 | * SetPrinterDataExW (WINSPOOL.@) |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5945 | */ |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 5946 | DWORD WINAPI SetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, |
| 5947 | LPCWSTR pValueName, DWORD Type, |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5948 | LPBYTE pData, DWORD cbData) |
| 5949 | { |
| 5950 | HKEY hkeyPrinter, hkeySubkey; |
| 5951 | DWORD ret; |
| 5952 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 5953 | TRACE("(%p, %s, %s %08x, %p, %08x)\n", hPrinter, debugstr_w(pKeyName), |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5954 | debugstr_w(pValueName), Type, pData, cbData); |
| 5955 | |
| 5956 | if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter)) |
| 5957 | != ERROR_SUCCESS) |
| 5958 | return ret; |
| 5959 | |
| 5960 | if((ret = RegCreateKeyW(hkeyPrinter, pKeyName, &hkeySubkey)) |
| 5961 | != ERROR_SUCCESS) { |
| 5962 | ERR("Can't create subkey %s\n", debugstr_w(pKeyName)); |
| 5963 | RegCloseKey(hkeyPrinter); |
| 5964 | return ret; |
| 5965 | } |
| 5966 | ret = RegSetValueExW(hkeySubkey, pValueName, 0, Type, pData, cbData); |
| 5967 | RegCloseKey(hkeySubkey); |
| 5968 | RegCloseKey(hkeyPrinter); |
| 5969 | return ret; |
| 5970 | } |
| 5971 | |
| 5972 | /****************************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 5973 | * SetPrinterDataA (WINSPOOL.@) |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5974 | */ |
| 5975 | DWORD WINAPI SetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, DWORD Type, |
| 5976 | LPBYTE pData, DWORD cbData) |
| 5977 | { |
| 5978 | return SetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, Type, |
| 5979 | pData, cbData); |
| 5980 | } |
| 5981 | |
| 5982 | /****************************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 5983 | * SetPrinterDataW (WINSPOOL.@) |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5984 | */ |
| 5985 | DWORD WINAPI SetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, DWORD Type, |
| 5986 | LPBYTE pData, DWORD cbData) |
| 5987 | { |
| 5988 | return SetPrinterDataExW(hPrinter, PrinterDriverDataW, pValueName, Type, |
| 5989 | pData, cbData); |
| 5990 | } |
| 5991 | |
| 5992 | /****************************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 5993 | * GetPrinterDataExA (WINSPOOL.@) |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5994 | */ |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 5995 | DWORD WINAPI GetPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, |
| 5996 | LPCSTR pValueName, LPDWORD pType, |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 5997 | LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) |
| 5998 | { |
| 5999 | HKEY hkeyPrinter, hkeySubkey; |
| 6000 | DWORD ret; |
| 6001 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6002 | TRACE("(%p, %s, %s %p, %p, %08x, %p)\n", hPrinter, |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 6003 | debugstr_a(pKeyName), debugstr_a(pValueName), pType, pData, nSize, |
| 6004 | pcbNeeded); |
| 6005 | |
| 6006 | if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter)) |
| 6007 | != ERROR_SUCCESS) |
| 6008 | return ret; |
| 6009 | |
| 6010 | if((ret = RegOpenKeyA(hkeyPrinter, pKeyName, &hkeySubkey)) |
| 6011 | != ERROR_SUCCESS) { |
| 6012 | WARN("Can't open subkey %s\n", debugstr_a(pKeyName)); |
| 6013 | RegCloseKey(hkeyPrinter); |
| 6014 | return ret; |
| 6015 | } |
| 6016 | *pcbNeeded = nSize; |
| 6017 | ret = RegQueryValueExA(hkeySubkey, pValueName, 0, pType, pData, pcbNeeded); |
| 6018 | RegCloseKey(hkeySubkey); |
| 6019 | RegCloseKey(hkeyPrinter); |
| 6020 | return ret; |
| 6021 | } |
| 6022 | |
| 6023 | /****************************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 6024 | * GetPrinterDataExW (WINSPOOL.@) |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 6025 | */ |
Alexandre Julliard | 4d626b0 | 2003-11-11 20:38:51 +0000 | [diff] [blame] | 6026 | DWORD WINAPI GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, |
| 6027 | LPCWSTR pValueName, LPDWORD pType, |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 6028 | LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) |
| 6029 | { |
| 6030 | HKEY hkeyPrinter, hkeySubkey; |
| 6031 | DWORD ret; |
| 6032 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6033 | TRACE("(%p, %s, %s %p, %p, %08x, %p)\n", hPrinter, |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 6034 | debugstr_w(pKeyName), debugstr_w(pValueName), pType, pData, nSize, |
| 6035 | pcbNeeded); |
| 6036 | |
| 6037 | if((ret = WINSPOOL_GetOpenedPrinterRegKey(hPrinter, &hkeyPrinter)) |
| 6038 | != ERROR_SUCCESS) |
| 6039 | return ret; |
| 6040 | |
| 6041 | if((ret = RegOpenKeyW(hkeyPrinter, pKeyName, &hkeySubkey)) |
| 6042 | != ERROR_SUCCESS) { |
| 6043 | WARN("Can't open subkey %s\n", debugstr_w(pKeyName)); |
| 6044 | RegCloseKey(hkeyPrinter); |
| 6045 | return ret; |
| 6046 | } |
| 6047 | *pcbNeeded = nSize; |
| 6048 | ret = RegQueryValueExW(hkeySubkey, pValueName, 0, pType, pData, pcbNeeded); |
| 6049 | RegCloseKey(hkeySubkey); |
| 6050 | RegCloseKey(hkeyPrinter); |
| 6051 | return ret; |
| 6052 | } |
| 6053 | |
| 6054 | /****************************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 6055 | * GetPrinterDataA (WINSPOOL.@) |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 6056 | */ |
| 6057 | DWORD WINAPI GetPrinterDataA(HANDLE hPrinter, LPSTR pValueName, LPDWORD pType, |
| 6058 | LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) |
| 6059 | { |
| 6060 | return GetPrinterDataExA(hPrinter, "PrinterDriverData", pValueName, pType, |
| 6061 | pData, nSize, pcbNeeded); |
| 6062 | } |
| 6063 | |
| 6064 | /****************************************************************************** |
Patrik Stridvall | 3ca9823 | 2001-06-20 23:03:14 +0000 | [diff] [blame] | 6065 | * GetPrinterDataW (WINSPOOL.@) |
Huw D M Davies | d2b850e | 2001-02-12 01:26:47 +0000 | [diff] [blame] | 6066 | */ |
| 6067 | DWORD WINAPI GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, |
| 6068 | LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded) |
| 6069 | { |
| 6070 | return GetPrinterDataExW(hPrinter, PrinterDriverDataW, pValueName, pType, |
| 6071 | pData, nSize, pcbNeeded); |
| 6072 | } |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6073 | |
| 6074 | /******************************************************************************* |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 6075 | * EnumPrinterDataExW [WINSPOOL.@] |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6076 | */ |
| 6077 | DWORD WINAPI EnumPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, |
| 6078 | LPBYTE pEnumValues, DWORD cbEnumValues, |
| 6079 | LPDWORD pcbEnumValues, LPDWORD pnEnumValues) |
| 6080 | { |
| 6081 | HKEY hkPrinter, hkSubKey; |
| 6082 | DWORD r, ret, dwIndex, cValues, cbMaxValueNameLen, |
| 6083 | cbValueNameLen, cbMaxValueLen, cbValueLen, |
| 6084 | cbBufSize, dwType; |
| 6085 | LPWSTR lpValueName; |
| 6086 | HANDLE hHeap; |
| 6087 | PBYTE lpValue; |
| 6088 | PPRINTER_ENUM_VALUESW ppev; |
| 6089 | |
Michael Stefaniuc | ea335dd | 2002-10-22 00:47:33 +0000 | [diff] [blame] | 6090 | TRACE ("%p %s\n", hPrinter, debugstr_w (pKeyName)); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6091 | |
| 6092 | if (pKeyName == NULL || *pKeyName == 0) |
| 6093 | return ERROR_INVALID_PARAMETER; |
| 6094 | |
| 6095 | ret = WINSPOOL_GetOpenedPrinterRegKey (hPrinter, &hkPrinter); |
| 6096 | if (ret != ERROR_SUCCESS) |
| 6097 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6098 | TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%p) returned %i\n", |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6099 | hPrinter, ret); |
| 6100 | return ret; |
| 6101 | } |
| 6102 | |
| 6103 | ret = RegOpenKeyExW (hkPrinter, pKeyName, 0, KEY_READ, &hkSubKey); |
| 6104 | if (ret != ERROR_SUCCESS) |
| 6105 | { |
| 6106 | r = RegCloseKey (hkPrinter); |
| 6107 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6108 | WARN ("RegCloseKey returned %i\n", r); |
| 6109 | TRACE ("RegOpenKeyExW (%p, %s) returned %i\n", hPrinter, |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6110 | debugstr_w (pKeyName), ret); |
| 6111 | return ret; |
| 6112 | } |
| 6113 | |
| 6114 | ret = RegCloseKey (hkPrinter); |
| 6115 | if (ret != ERROR_SUCCESS) |
| 6116 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6117 | ERR ("RegCloseKey returned %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6118 | r = RegCloseKey (hkSubKey); |
| 6119 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6120 | WARN ("RegCloseKey returned %i\n", r); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6121 | return ret; |
| 6122 | } |
| 6123 | |
| 6124 | ret = RegQueryInfoKeyW (hkSubKey, NULL, NULL, NULL, NULL, NULL, NULL, |
| 6125 | &cValues, &cbMaxValueNameLen, &cbMaxValueLen, NULL, NULL); |
| 6126 | if (ret != ERROR_SUCCESS) |
| 6127 | { |
| 6128 | r = RegCloseKey (hkSubKey); |
| 6129 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6130 | WARN ("RegCloseKey returned %i\n", r); |
| 6131 | TRACE ("RegQueryInfoKeyW (%p) returned %i\n", hkSubKey, ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6132 | return ret; |
| 6133 | } |
| 6134 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6135 | TRACE ("RegQueryInfoKeyW returned cValues = %i, cbMaxValueNameLen = %i, " |
| 6136 | "cbMaxValueLen = %i\n", cValues, cbMaxValueNameLen, cbMaxValueLen); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6137 | |
| 6138 | if (cValues == 0) /* empty key */ |
| 6139 | { |
| 6140 | r = RegCloseKey (hkSubKey); |
| 6141 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6142 | WARN ("RegCloseKey returned %i\n", r); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6143 | *pcbEnumValues = *pnEnumValues = 0; |
| 6144 | return ERROR_SUCCESS; |
| 6145 | } |
| 6146 | |
| 6147 | ++cbMaxValueNameLen; /* allow for trailing '\0' */ |
| 6148 | |
| 6149 | hHeap = GetProcessHeap (); |
Francois Gouget | 9b0b1e0 | 2003-01-14 23:43:41 +0000 | [diff] [blame] | 6150 | if (hHeap == NULL) |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6151 | { |
| 6152 | ERR ("GetProcessHeap failed\n"); |
| 6153 | r = RegCloseKey (hkSubKey); |
| 6154 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6155 | WARN ("RegCloseKey returned %i\n", r); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6156 | return ERROR_OUTOFMEMORY; |
| 6157 | } |
| 6158 | |
| 6159 | lpValueName = HeapAlloc (hHeap, 0, cbMaxValueNameLen * sizeof (WCHAR)); |
| 6160 | if (lpValueName == NULL) |
| 6161 | { |
Alexandre Julliard | b0ea577 | 2006-10-20 12:16:45 +0200 | [diff] [blame] | 6162 | ERR ("Failed to allocate %i WCHARs from process heap\n", cbMaxValueNameLen); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6163 | r = RegCloseKey (hkSubKey); |
| 6164 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6165 | WARN ("RegCloseKey returned %i\n", r); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6166 | return ERROR_OUTOFMEMORY; |
| 6167 | } |
| 6168 | |
| 6169 | lpValue = HeapAlloc (hHeap, 0, cbMaxValueLen); |
| 6170 | if (lpValue == NULL) |
| 6171 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6172 | ERR ("Failed to allocate %i bytes from process heap\n", cbMaxValueLen); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6173 | if (HeapFree (hHeap, 0, lpValueName) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6174 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6175 | r = RegCloseKey (hkSubKey); |
| 6176 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6177 | WARN ("RegCloseKey returned %i\n", r); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6178 | return ERROR_OUTOFMEMORY; |
| 6179 | } |
| 6180 | |
| 6181 | TRACE ("pass 1: calculating buffer required for all names and values\n"); |
| 6182 | |
| 6183 | cbBufSize = cValues * sizeof (PRINTER_ENUM_VALUESW); |
| 6184 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6185 | TRACE ("%i bytes required for %i headers\n", cbBufSize, cValues); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6186 | |
| 6187 | for (dwIndex = 0; dwIndex < cValues; ++dwIndex) |
| 6188 | { |
| 6189 | cbValueNameLen = cbMaxValueNameLen; cbValueLen = cbMaxValueLen; |
| 6190 | ret = RegEnumValueW (hkSubKey, dwIndex, lpValueName, &cbValueNameLen, |
| 6191 | NULL, NULL, lpValue, &cbValueLen); |
| 6192 | if (ret != ERROR_SUCCESS) |
| 6193 | { |
| 6194 | if (HeapFree (hHeap, 0, lpValue) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6195 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6196 | if (HeapFree (hHeap, 0, lpValueName) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6197 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6198 | r = RegCloseKey (hkSubKey); |
| 6199 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6200 | WARN ("RegCloseKey returned %i\n", r); |
| 6201 | TRACE ("RegEnumValueW (%i) returned %i\n", dwIndex, ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6202 | return ret; |
| 6203 | } |
| 6204 | |
Alexandre Julliard | b0ea577 | 2006-10-20 12:16:45 +0200 | [diff] [blame] | 6205 | TRACE ("%s [%i]: name needs %i WCHARs, data needs %i bytes\n", |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6206 | debugstr_w (lpValueName), dwIndex, |
Alexandre Julliard | b0ea577 | 2006-10-20 12:16:45 +0200 | [diff] [blame] | 6207 | cbValueNameLen + 1, cbValueLen); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6208 | |
| 6209 | cbBufSize += (cbValueNameLen + 1) * sizeof (WCHAR); |
| 6210 | cbBufSize += cbValueLen; |
| 6211 | } |
| 6212 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6213 | TRACE ("%i bytes required for all %i values\n", cbBufSize, cValues); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6214 | |
| 6215 | *pcbEnumValues = cbBufSize; |
| 6216 | *pnEnumValues = cValues; |
| 6217 | |
| 6218 | if (cbEnumValues < cbBufSize) /* buffer too small */ |
| 6219 | { |
| 6220 | if (HeapFree (hHeap, 0, lpValue) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6221 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6222 | if (HeapFree (hHeap, 0, lpValueName) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6223 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6224 | r = RegCloseKey (hkSubKey); |
| 6225 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6226 | WARN ("RegCloseKey returned %i\n", r); |
| 6227 | TRACE ("%i byte buffer is not large enough\n", cbEnumValues); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6228 | return ERROR_MORE_DATA; |
| 6229 | } |
| 6230 | |
| 6231 | TRACE ("pass 2: copying all names and values to buffer\n"); |
| 6232 | |
| 6233 | ppev = (PPRINTER_ENUM_VALUESW) pEnumValues; /* array of structs */ |
| 6234 | pEnumValues += cValues * sizeof (PRINTER_ENUM_VALUESW); |
| 6235 | |
| 6236 | for (dwIndex = 0; dwIndex < cValues; ++dwIndex) |
| 6237 | { |
| 6238 | cbValueNameLen = cbMaxValueNameLen; cbValueLen = cbMaxValueLen; |
| 6239 | ret = RegEnumValueW (hkSubKey, dwIndex, lpValueName, &cbValueNameLen, |
| 6240 | NULL, &dwType, lpValue, &cbValueLen); |
| 6241 | if (ret != ERROR_SUCCESS) |
| 6242 | { |
| 6243 | if (HeapFree (hHeap, 0, lpValue) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6244 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6245 | if (HeapFree (hHeap, 0, lpValueName) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6246 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6247 | r = RegCloseKey (hkSubKey); |
| 6248 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6249 | WARN ("RegCloseKey returned %i\n", r); |
| 6250 | TRACE ("RegEnumValueW (%i) returned %i\n", dwIndex, ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6251 | return ret; |
| 6252 | } |
| 6253 | |
| 6254 | cbValueNameLen = (cbValueNameLen + 1) * sizeof (WCHAR); |
| 6255 | memcpy (pEnumValues, lpValueName, cbValueNameLen); |
| 6256 | ppev[dwIndex].pValueName = (LPWSTR) pEnumValues; |
| 6257 | pEnumValues += cbValueNameLen; |
| 6258 | |
| 6259 | /* return # of *bytes* (including trailing \0), not # of chars */ |
| 6260 | ppev[dwIndex].cbValueName = cbValueNameLen; |
| 6261 | |
| 6262 | ppev[dwIndex].dwType = dwType; |
| 6263 | |
| 6264 | memcpy (pEnumValues, lpValue, cbValueLen); |
| 6265 | ppev[dwIndex].pData = pEnumValues; |
| 6266 | pEnumValues += cbValueLen; |
| 6267 | |
| 6268 | ppev[dwIndex].cbData = cbValueLen; |
| 6269 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6270 | TRACE ("%s [%i]: copied name (%i bytes) and data (%i bytes)\n", |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6271 | debugstr_w (lpValueName), dwIndex, cbValueNameLen, cbValueLen); |
| 6272 | } |
| 6273 | |
| 6274 | if (HeapFree (hHeap, 0, lpValue) == 0) |
| 6275 | { |
| 6276 | ret = GetLastError (); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6277 | ERR ("HeapFree failed with code %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6278 | if (HeapFree (hHeap, 0, lpValueName) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6279 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6280 | r = RegCloseKey (hkSubKey); |
| 6281 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6282 | WARN ("RegCloseKey returned %i\n", r); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6283 | return ret; |
| 6284 | } |
| 6285 | |
| 6286 | if (HeapFree (hHeap, 0, lpValueName) == 0) |
| 6287 | { |
| 6288 | ret = GetLastError (); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6289 | ERR ("HeapFree failed with code %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6290 | r = RegCloseKey (hkSubKey); |
| 6291 | if (r != ERROR_SUCCESS) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6292 | WARN ("RegCloseKey returned %i\n", r); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6293 | return ret; |
| 6294 | } |
| 6295 | |
| 6296 | ret = RegCloseKey (hkSubKey); |
| 6297 | if (ret != ERROR_SUCCESS) |
| 6298 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6299 | ERR ("RegCloseKey returned %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6300 | return ret; |
| 6301 | } |
| 6302 | |
| 6303 | return ERROR_SUCCESS; |
| 6304 | } |
| 6305 | |
| 6306 | /******************************************************************************* |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 6307 | * EnumPrinterDataExA [WINSPOOL.@] |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6308 | * |
| 6309 | * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and |
| 6310 | * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is |
| 6311 | * what Windows 2000 SP1 does. |
| 6312 | * |
| 6313 | */ |
| 6314 | DWORD WINAPI EnumPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, |
| 6315 | LPBYTE pEnumValues, DWORD cbEnumValues, |
| 6316 | LPDWORD pcbEnumValues, LPDWORD pnEnumValues) |
| 6317 | { |
| 6318 | INT len; |
| 6319 | LPWSTR pKeyNameW; |
| 6320 | DWORD ret, dwIndex, dwBufSize; |
| 6321 | HANDLE hHeap; |
| 6322 | LPSTR pBuffer; |
| 6323 | |
Michael Stefaniuc | ea335dd | 2002-10-22 00:47:33 +0000 | [diff] [blame] | 6324 | TRACE ("%p %s\n", hPrinter, pKeyName); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6325 | |
| 6326 | if (pKeyName == NULL || *pKeyName == 0) |
| 6327 | return ERROR_INVALID_PARAMETER; |
| 6328 | |
| 6329 | len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0); |
| 6330 | if (len == 0) |
| 6331 | { |
| 6332 | ret = GetLastError (); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6333 | ERR ("MultiByteToWideChar failed with code %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6334 | return ret; |
| 6335 | } |
| 6336 | |
| 6337 | hHeap = GetProcessHeap (); |
Francois Gouget | 9b0b1e0 | 2003-01-14 23:43:41 +0000 | [diff] [blame] | 6338 | if (hHeap == NULL) |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6339 | { |
| 6340 | ERR ("GetProcessHeap failed\n"); |
| 6341 | return ERROR_OUTOFMEMORY; |
| 6342 | } |
| 6343 | |
| 6344 | pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR)); |
| 6345 | if (pKeyNameW == NULL) |
| 6346 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6347 | ERR ("Failed to allocate %i bytes from process heap\n", |
Alexandre Julliard | b0ea577 | 2006-10-20 12:16:45 +0200 | [diff] [blame] | 6348 | (LONG)(len * sizeof (WCHAR))); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6349 | return ERROR_OUTOFMEMORY; |
| 6350 | } |
| 6351 | |
| 6352 | if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0) |
| 6353 | { |
| 6354 | ret = GetLastError (); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6355 | ERR ("MultiByteToWideChar failed with code %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6356 | if (HeapFree (hHeap, 0, pKeyNameW) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6357 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6358 | return ret; |
| 6359 | } |
| 6360 | |
| 6361 | ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues, |
| 6362 | pcbEnumValues, pnEnumValues); |
| 6363 | if (ret != ERROR_SUCCESS) |
| 6364 | { |
| 6365 | if (HeapFree (hHeap, 0, pKeyNameW) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6366 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
| 6367 | TRACE ("EnumPrinterDataExW returned %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6368 | return ret; |
| 6369 | } |
| 6370 | |
| 6371 | if (HeapFree (hHeap, 0, pKeyNameW) == 0) |
| 6372 | { |
| 6373 | ret = GetLastError (); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6374 | ERR ("HeapFree failed with code %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6375 | return ret; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 6376 | } |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6377 | |
| 6378 | if (*pnEnumValues == 0) /* empty key */ |
| 6379 | return ERROR_SUCCESS; |
| 6380 | |
| 6381 | dwBufSize = 0; |
| 6382 | for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex) |
| 6383 | { |
| 6384 | PPRINTER_ENUM_VALUESW ppev = |
| 6385 | &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex]; |
| 6386 | |
| 6387 | if (dwBufSize < ppev->cbValueName) |
| 6388 | dwBufSize = ppev->cbValueName; |
| 6389 | |
| 6390 | if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ || |
| 6391 | ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ)) |
| 6392 | dwBufSize = ppev->cbData; |
| 6393 | } |
| 6394 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6395 | TRACE ("Largest Unicode name or value is %i bytes\n", dwBufSize); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6396 | |
| 6397 | pBuffer = HeapAlloc (hHeap, 0, dwBufSize); |
| 6398 | if (pBuffer == NULL) |
| 6399 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6400 | ERR ("Failed to allocate %i bytes from process heap\n", dwBufSize); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6401 | return ERROR_OUTOFMEMORY; |
| 6402 | } |
| 6403 | |
| 6404 | for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex) |
| 6405 | { |
| 6406 | PPRINTER_ENUM_VALUESW ppev = |
| 6407 | &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex]; |
| 6408 | |
| 6409 | len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName, |
| 6410 | ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL, |
| 6411 | NULL); |
| 6412 | if (len == 0) |
| 6413 | { |
| 6414 | ret = GetLastError (); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6415 | ERR ("WideCharToMultiByte failed with code %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6416 | if (HeapFree (hHeap, 0, pBuffer) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6417 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6418 | return ret; |
| 6419 | } |
| 6420 | |
| 6421 | memcpy (ppev->pValueName, pBuffer, len); |
| 6422 | |
| 6423 | TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer); |
| 6424 | |
| 6425 | if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ && |
| 6426 | ppev->dwType != REG_MULTI_SZ) |
| 6427 | continue; |
| 6428 | |
| 6429 | len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData, |
| 6430 | ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL); |
| 6431 | if (len == 0) |
| 6432 | { |
| 6433 | ret = GetLastError (); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6434 | ERR ("WideCharToMultiByte failed with code %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6435 | if (HeapFree (hHeap, 0, pBuffer) == 0) |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6436 | WARN ("HeapFree failed with code %i\n", GetLastError ()); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6437 | return ret; |
| 6438 | } |
| 6439 | |
| 6440 | memcpy (ppev->pData, pBuffer, len); |
| 6441 | |
| 6442 | TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer); |
| 6443 | TRACE (" (only first string of REG_MULTI_SZ printed)\n"); |
| 6444 | } |
| 6445 | |
| 6446 | if (HeapFree (hHeap, 0, pBuffer) == 0) |
| 6447 | { |
| 6448 | ret = GetLastError (); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 6449 | ERR ("HeapFree failed with code %i\n", ret); |
Ian Pilcher | ccfe6e9 | 2001-02-21 04:00:40 +0000 | [diff] [blame] | 6450 | return ret; |
| 6451 | } |
| 6452 | |
| 6453 | return ERROR_SUCCESS; |
| 6454 | } |
Aric Stewart | 6d5cd45 | 2003-05-13 22:25:12 +0000 | [diff] [blame] | 6455 | |
| 6456 | /****************************************************************************** |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 6457 | * AbortPrinter (WINSPOOL.@) |
| 6458 | */ |
| 6459 | BOOL WINAPI AbortPrinter( HANDLE hPrinter ) |
| 6460 | { |
| 6461 | FIXME("(%p), stub!\n", hPrinter); |
| 6462 | return TRUE; |
| 6463 | } |
| 6464 | |
| 6465 | /****************************************************************************** |
Aric Stewart | 6d5cd45 | 2003-05-13 22:25:12 +0000 | [diff] [blame] | 6466 | * AddPortA (WINSPOOL.@) |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 6467 | * |
| 6468 | * See AddPortW. |
| 6469 | * |
Aric Stewart | 6d5cd45 | 2003-05-13 22:25:12 +0000 | [diff] [blame] | 6470 | */ |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 6471 | BOOL WINAPI AddPortA(LPSTR pName, HWND hWnd, LPSTR pMonitorName) |
Aric Stewart | 6d5cd45 | 2003-05-13 22:25:12 +0000 | [diff] [blame] | 6472 | { |
Detlef Riekenberg | 1f3c289 | 2006-11-28 00:49:54 +0100 | [diff] [blame] | 6473 | LPWSTR nameW = NULL; |
| 6474 | LPWSTR monitorW = NULL; |
| 6475 | DWORD len; |
| 6476 | BOOL res; |
| 6477 | |
| 6478 | TRACE("(%s, %p, %s)\n",debugstr_a(pName), hWnd, debugstr_a(pMonitorName)); |
| 6479 | |
| 6480 | if (pName) { |
| 6481 | len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); |
| 6482 | nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6483 | MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); |
| 6484 | } |
| 6485 | |
| 6486 | if (pMonitorName) { |
| 6487 | len = MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, NULL, 0); |
| 6488 | monitorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6489 | MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, monitorW, len); |
| 6490 | } |
| 6491 | res = AddPortW(nameW, hWnd, monitorW); |
| 6492 | HeapFree(GetProcessHeap(), 0, nameW); |
| 6493 | HeapFree(GetProcessHeap(), 0, monitorW); |
| 6494 | return res; |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 6495 | } |
| 6496 | |
| 6497 | /****************************************************************************** |
| 6498 | * AddPortW (WINSPOOL.@) |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 6499 | * |
| 6500 | * Add a Port for a specific Monitor |
| 6501 | * |
| 6502 | * PARAMS |
| 6503 | * pName [I] Servername or NULL (local Computer) |
| 6504 | * hWnd [I] Handle to parent Window for the Dialog-Box |
| 6505 | * pMonitorName [I] Name of the Monitor that manage the Port |
| 6506 | * |
| 6507 | * RETURNS |
| 6508 | * Success: TRUE |
| 6509 | * Failure: FALSE |
| 6510 | * |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 6511 | */ |
| 6512 | BOOL WINAPI AddPortW(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName) |
| 6513 | { |
Detlef Riekenberg | 03daa60 | 2006-11-28 00:49:06 +0100 | [diff] [blame] | 6514 | monitor_t * pm; |
Detlef Riekenberg | 5012fa0 | 2007-01-15 05:37:24 +0100 | [diff] [blame] | 6515 | monitor_t * pui; |
| 6516 | DWORD res; |
Detlef Riekenberg | 03daa60 | 2006-11-28 00:49:06 +0100 | [diff] [blame] | 6517 | |
| 6518 | TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pMonitorName)); |
| 6519 | |
| 6520 | if (pName && pName[0]) { |
| 6521 | SetLastError(ERROR_INVALID_PARAMETER); |
| 6522 | return FALSE; |
| 6523 | } |
| 6524 | |
| 6525 | if (!pMonitorName) { |
| 6526 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 6527 | return FALSE; |
| 6528 | } |
| 6529 | |
| 6530 | /* an empty Monitorname is Invalid */ |
Detlef Riekenberg | 5012fa0 | 2007-01-15 05:37:24 +0100 | [diff] [blame] | 6531 | if (!pMonitorName[0]) { |
| 6532 | SetLastError(ERROR_NOT_SUPPORTED); |
| 6533 | return FALSE; |
| 6534 | } |
Detlef Riekenberg | 03daa60 | 2006-11-28 00:49:06 +0100 | [diff] [blame] | 6535 | |
| 6536 | pm = monitor_load(pMonitorName, NULL); |
Detlef Riekenberg | 5012fa0 | 2007-01-15 05:37:24 +0100 | [diff] [blame] | 6537 | if (pm && pm->monitor && pm->monitor->pfnAddPort) { |
| 6538 | res = pm->monitor->pfnAddPort(pName, hWnd, pMonitorName); |
| 6539 | TRACE("got %d with %u\n", res, GetLastError()); |
| 6540 | res = TRUE; |
Detlef Riekenberg | 03daa60 | 2006-11-28 00:49:06 +0100 | [diff] [blame] | 6541 | } |
Detlef Riekenberg | 5012fa0 | 2007-01-15 05:37:24 +0100 | [diff] [blame] | 6542 | else |
| 6543 | { |
| 6544 | pui = monitor_loadui(pm); |
| 6545 | if (pui && pui->monitorUI && pui->monitorUI->pfnAddPortUI) { |
| 6546 | TRACE("use %p: %s\n", pui, debugstr_w(pui->dllname)); |
| 6547 | res = pui->monitorUI->pfnAddPortUI(pName, hWnd, pMonitorName, NULL); |
| 6548 | TRACE("got %d with %u\n", res, GetLastError()); |
| 6549 | res = TRUE; |
| 6550 | } |
| 6551 | else |
| 6552 | { |
| 6553 | FIXME("not implemented for %s (%p: %s => %p: %s)\n", debugstr_w(pMonitorName), |
| 6554 | pm, pm ? debugstr_w(pm->dllname) : NULL, pui, pui ? debugstr_w(pui->dllname) : NULL); |
Detlef Riekenberg | 03daa60 | 2006-11-28 00:49:06 +0100 | [diff] [blame] | 6555 | |
Detlef Riekenberg | 5012fa0 | 2007-01-15 05:37:24 +0100 | [diff] [blame] | 6556 | /* XP: ERROR_NOT_SUPPORTED, NT351,9x: ERROR_INVALID_PARAMETER */ |
| 6557 | SetLastError(ERROR_NOT_SUPPORTED); |
| 6558 | res = FALSE; |
| 6559 | } |
| 6560 | monitor_unload(pui); |
| 6561 | } |
Detlef Riekenberg | 5012fa0 | 2007-01-15 05:37:24 +0100 | [diff] [blame] | 6562 | monitor_unload(pm); |
| 6563 | TRACE("returning %d with %u\n", res, GetLastError()); |
| 6564 | return res; |
Aric Stewart | 6d5cd45 | 2003-05-13 22:25:12 +0000 | [diff] [blame] | 6565 | } |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 6566 | |
| 6567 | /****************************************************************************** |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 6568 | * AddPortExA (WINSPOOL.@) |
| 6569 | * |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 6570 | * See AddPortExW. |
| 6571 | * |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 6572 | */ |
Detlef Riekenberg | 0c71799 | 2007-06-04 00:23:55 +0200 | [diff] [blame] | 6573 | BOOL WINAPI AddPortExA(LPSTR pName, DWORD level, LPBYTE pBuffer, LPSTR pMonitorName) |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 6574 | { |
Detlef Riekenberg | 0c71799 | 2007-06-04 00:23:55 +0200 | [diff] [blame] | 6575 | PORT_INFO_2W pi2W; |
| 6576 | PORT_INFO_2A * pi2A; |
| 6577 | LPWSTR nameW = NULL; |
| 6578 | LPWSTR monitorW = NULL; |
| 6579 | DWORD len; |
| 6580 | BOOL res; |
| 6581 | |
| 6582 | pi2A = (PORT_INFO_2A *) pBuffer; |
| 6583 | |
| 6584 | TRACE("(%s, %d, %p, %s): %s\n", debugstr_a(pName), level, pBuffer, |
| 6585 | debugstr_a(pMonitorName), debugstr_a(pi2A ? pi2A->pPortName : NULL)); |
| 6586 | |
| 6587 | if ((level < 1) || (level > 2)) { |
| 6588 | SetLastError(ERROR_INVALID_LEVEL); |
| 6589 | return FALSE; |
| 6590 | } |
| 6591 | |
| 6592 | if (!pi2A) { |
| 6593 | SetLastError(ERROR_INVALID_PARAMETER); |
| 6594 | return FALSE; |
| 6595 | } |
| 6596 | |
| 6597 | if (pName) { |
| 6598 | len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); |
| 6599 | nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6600 | MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); |
| 6601 | } |
| 6602 | |
| 6603 | if (pMonitorName) { |
| 6604 | len = MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, NULL, 0); |
| 6605 | monitorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6606 | MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, monitorW, len); |
| 6607 | } |
| 6608 | |
| 6609 | ZeroMemory(&pi2W, sizeof(PORT_INFO_2W)); |
| 6610 | |
| 6611 | if (pi2A->pPortName) { |
| 6612 | len = MultiByteToWideChar(CP_ACP, 0, pi2A->pPortName, -1, NULL, 0); |
| 6613 | pi2W.pPortName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6614 | MultiByteToWideChar(CP_ACP, 0, pi2A->pPortName, -1, pi2W.pPortName, len); |
| 6615 | } |
| 6616 | |
| 6617 | if (level > 1) { |
| 6618 | if (pi2A->pMonitorName) { |
| 6619 | len = MultiByteToWideChar(CP_ACP, 0, pi2A->pMonitorName, -1, NULL, 0); |
| 6620 | pi2W.pMonitorName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6621 | MultiByteToWideChar(CP_ACP, 0, pi2A->pMonitorName, -1, pi2W.pMonitorName, len); |
| 6622 | } |
| 6623 | |
| 6624 | if (pi2A->pDescription) { |
| 6625 | len = MultiByteToWideChar(CP_ACP, 0, pi2A->pDescription, -1, NULL, 0); |
| 6626 | pi2W.pDescription = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6627 | MultiByteToWideChar(CP_ACP, 0, pi2A->pDescription, -1, pi2W.pDescription, len); |
| 6628 | } |
| 6629 | pi2W.fPortType = pi2A->fPortType; |
| 6630 | pi2W.Reserved = pi2A->Reserved; |
| 6631 | } |
| 6632 | |
| 6633 | res = AddPortExW(nameW, level, (LPBYTE) &pi2W, monitorW); |
| 6634 | |
| 6635 | HeapFree(GetProcessHeap(), 0, nameW); |
| 6636 | HeapFree(GetProcessHeap(), 0, monitorW); |
| 6637 | HeapFree(GetProcessHeap(), 0, pi2W.pPortName); |
| 6638 | HeapFree(GetProcessHeap(), 0, pi2W.pMonitorName); |
| 6639 | HeapFree(GetProcessHeap(), 0, pi2W.pDescription); |
| 6640 | return res; |
| 6641 | |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 6642 | } |
| 6643 | |
| 6644 | /****************************************************************************** |
| 6645 | * AddPortExW (WINSPOOL.@) |
| 6646 | * |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 6647 | * Add a Port for a specific Monitor, without presenting a user interface |
| 6648 | * |
| 6649 | * PARAMS |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 6650 | * pName [I] Servername or NULL (local Computer) |
Detlef Riekenberg | 0c71799 | 2007-06-04 00:23:55 +0200 | [diff] [blame] | 6651 | * level [I] Structure-Level (1 or 2) for pBuffer |
| 6652 | * pBuffer [I] PTR to: PORT_INFO_1 or PORT_INFO_2 |
| 6653 | * pMonitorName [I] Name of the Monitor that manage the Port |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 6654 | * |
| 6655 | * RETURNS |
| 6656 | * Success: TRUE |
| 6657 | * Failure: FALSE |
| 6658 | * |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 6659 | */ |
Detlef Riekenberg | 0c71799 | 2007-06-04 00:23:55 +0200 | [diff] [blame] | 6660 | BOOL WINAPI AddPortExW(LPWSTR pName, DWORD level, LPBYTE pBuffer, LPWSTR pMonitorName) |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 6661 | { |
Detlef Riekenberg | 0c71799 | 2007-06-04 00:23:55 +0200 | [diff] [blame] | 6662 | PORT_INFO_2W * pi2; |
| 6663 | monitor_t * pm; |
| 6664 | DWORD res = FALSE; |
| 6665 | |
| 6666 | pi2 = (PORT_INFO_2W *) pBuffer; |
| 6667 | |
| 6668 | TRACE("(%s, %d, %p, %s): %s %s %s\n", debugstr_w(pName), level, pBuffer, |
| 6669 | debugstr_w(pMonitorName), debugstr_w(pi2 ? pi2->pPortName : NULL), |
| 6670 | debugstr_w(((level > 1) && pi2) ? pi2->pMonitorName : NULL), |
| 6671 | debugstr_w(((level > 1) && pi2) ? pi2->pDescription : NULL)); |
| 6672 | |
| 6673 | |
| 6674 | if ((level < 1) || (level > 2)) { |
| 6675 | SetLastError(ERROR_INVALID_LEVEL); |
| 6676 | return FALSE; |
| 6677 | } |
| 6678 | |
Detlef Riekenberg | 4307f64 | 2007-06-18 00:58:49 +0200 | [diff] [blame] | 6679 | if ((!pi2) || (!pMonitorName) || (!pMonitorName[0])) { |
Detlef Riekenberg | 0c71799 | 2007-06-04 00:23:55 +0200 | [diff] [blame] | 6680 | SetLastError(ERROR_INVALID_PARAMETER); |
| 6681 | return FALSE; |
| 6682 | } |
| 6683 | |
Detlef Riekenberg | 0c71799 | 2007-06-04 00:23:55 +0200 | [diff] [blame] | 6684 | /* load the Monitor */ |
| 6685 | pm = monitor_load(pMonitorName, NULL); |
Detlef Riekenberg | 4307f64 | 2007-06-18 00:58:49 +0200 | [diff] [blame] | 6686 | if (!pm) { |
| 6687 | SetLastError(ERROR_INVALID_PARAMETER); |
| 6688 | return FALSE; |
| 6689 | } |
Detlef Riekenberg | 0c71799 | 2007-06-04 00:23:55 +0200 | [diff] [blame] | 6690 | |
| 6691 | if (pm->monitor && pm->monitor->pfnAddPortEx) { |
| 6692 | res = pm->monitor->pfnAddPortEx(pName, level, pBuffer, pMonitorName); |
| 6693 | TRACE("got %u with %u\n", res, GetLastError()); |
| 6694 | } |
Detlef Riekenberg | 4307f64 | 2007-06-18 00:58:49 +0200 | [diff] [blame] | 6695 | else |
| 6696 | { |
| 6697 | FIXME("not implemented for %s (%p)\n", debugstr_w(pMonitorName), pm->monitor); |
| 6698 | } |
Detlef Riekenberg | 0c71799 | 2007-06-04 00:23:55 +0200 | [diff] [blame] | 6699 | monitor_unload(pm); |
| 6700 | return res; |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 6701 | } |
| 6702 | |
| 6703 | /****************************************************************************** |
| 6704 | * AddPrinterConnectionA (WINSPOOL.@) |
| 6705 | */ |
| 6706 | BOOL WINAPI AddPrinterConnectionA( LPSTR pName ) |
| 6707 | { |
| 6708 | FIXME("%s\n", debugstr_a(pName)); |
| 6709 | return FALSE; |
| 6710 | } |
| 6711 | |
| 6712 | /****************************************************************************** |
| 6713 | * AddPrinterConnectionW (WINSPOOL.@) |
| 6714 | */ |
| 6715 | BOOL WINAPI AddPrinterConnectionW( LPWSTR pName ) |
| 6716 | { |
| 6717 | FIXME("%s\n", debugstr_w(pName)); |
| 6718 | return FALSE; |
| 6719 | } |
| 6720 | |
| 6721 | /****************************************************************************** |
Detlef Riekenberg | 29444b4 | 2007-08-15 23:30:59 +0200 | [diff] [blame] | 6722 | * AddPrinterDriverExW (WINSPOOL.@) |
| 6723 | * |
| 6724 | * Install a Printer Driver with the Option to upgrade / downgrade the Files |
| 6725 | * |
| 6726 | * PARAMS |
| 6727 | * pName [I] Servername or NULL (local Computer) |
| 6728 | * level [I] Level for the supplied DRIVER_INFO_*W struct |
| 6729 | * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter |
| 6730 | * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files |
| 6731 | * |
| 6732 | * RESULTS |
| 6733 | * Success: TRUE |
| 6734 | * Failure: FALSE |
| 6735 | * |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 6736 | */ |
Detlef Riekenberg | 29444b4 | 2007-08-15 23:30:59 +0200 | [diff] [blame] | 6737 | BOOL WINAPI AddPrinterDriverExW( LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags) |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 6738 | { |
Detlef Riekenberg | 29444b4 | 2007-08-15 23:30:59 +0200 | [diff] [blame] | 6739 | TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags); |
| 6740 | |
Detlef Riekenberg | 6ec7c2d | 2008-02-08 00:41:24 +0100 | [diff] [blame] | 6741 | if ((backend == NULL) && !load_backend()) return FALSE; |
| 6742 | |
Detlef Riekenberg | 29444b4 | 2007-08-15 23:30:59 +0200 | [diff] [blame] | 6743 | if (level < 2 || level == 5 || level == 7 || level > 8) { |
| 6744 | SetLastError(ERROR_INVALID_LEVEL); |
| 6745 | return FALSE; |
| 6746 | } |
| 6747 | |
| 6748 | if (!pDriverInfo) { |
| 6749 | SetLastError(ERROR_INVALID_PARAMETER); |
| 6750 | return FALSE; |
| 6751 | } |
| 6752 | |
Detlef Riekenberg | 6ec7c2d | 2008-02-08 00:41:24 +0100 | [diff] [blame] | 6753 | return backend->fpAddPrinterDriverEx(pName, level, pDriverInfo, dwFileCopyFlags); |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 6754 | } |
| 6755 | |
| 6756 | /****************************************************************************** |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6757 | * AddPrinterDriverExA (WINSPOOL.@) |
| 6758 | * |
| 6759 | * See AddPrinterDriverExW. |
| 6760 | * |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 6761 | */ |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6762 | BOOL WINAPI AddPrinterDriverExA(LPSTR pName, DWORD Level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags) |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 6763 | { |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6764 | DRIVER_INFO_8A *diA; |
| 6765 | DRIVER_INFO_8W diW; |
| 6766 | LPWSTR nameW = NULL; |
| 6767 | DWORD lenA; |
| 6768 | DWORD len; |
| 6769 | DWORD res = FALSE; |
| 6770 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6771 | TRACE("(%s, %d, %p, 0x%x)\n", debugstr_a(pName), Level, pDriverInfo, dwFileCopyFlags); |
| 6772 | |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6773 | diA = (DRIVER_INFO_8A *) pDriverInfo; |
| 6774 | ZeroMemory(&diW, sizeof(diW)); |
| 6775 | |
| 6776 | if (Level < 2 || Level == 5 || Level == 7 || Level > 8) { |
| 6777 | SetLastError(ERROR_INVALID_LEVEL); |
| 6778 | return FALSE; |
| 6779 | } |
| 6780 | |
| 6781 | if (diA == NULL) { |
| 6782 | SetLastError(ERROR_INVALID_PARAMETER); |
| 6783 | return FALSE; |
| 6784 | } |
| 6785 | |
| 6786 | /* convert servername to unicode */ |
| 6787 | if (pName) { |
| 6788 | len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); |
| 6789 | nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6790 | MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); |
| 6791 | } |
| 6792 | |
| 6793 | /* common fields */ |
| 6794 | diW.cVersion = diA->cVersion; |
| 6795 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6796 | if (diA->pName) { |
| 6797 | len = MultiByteToWideChar(CP_ACP, 0, diA->pName, -1, NULL, 0); |
| 6798 | diW.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6799 | MultiByteToWideChar(CP_ACP, 0, diA->pName, -1, diW.pName, len); |
| 6800 | } |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6801 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6802 | if (diA->pEnvironment) { |
| 6803 | len = MultiByteToWideChar(CP_ACP, 0, diA->pEnvironment, -1, NULL, 0); |
| 6804 | diW.pEnvironment = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6805 | MultiByteToWideChar(CP_ACP, 0, diA->pEnvironment, -1, diW.pEnvironment, len); |
| 6806 | } |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6807 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6808 | if (diA->pDriverPath) { |
| 6809 | len = MultiByteToWideChar(CP_ACP, 0, diA->pDriverPath, -1, NULL, 0); |
| 6810 | diW.pDriverPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6811 | MultiByteToWideChar(CP_ACP, 0, diA->pDriverPath, -1, diW.pDriverPath, len); |
| 6812 | } |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6813 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6814 | if (diA->pDataFile) { |
| 6815 | len = MultiByteToWideChar(CP_ACP, 0, diA->pDataFile, -1, NULL, 0); |
| 6816 | diW.pDataFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6817 | MultiByteToWideChar(CP_ACP, 0, diA->pDataFile, -1, diW.pDataFile, len); |
| 6818 | } |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6819 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6820 | if (diA->pConfigFile) { |
| 6821 | len = MultiByteToWideChar(CP_ACP, 0, diA->pConfigFile, -1, NULL, 0); |
| 6822 | diW.pConfigFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6823 | MultiByteToWideChar(CP_ACP, 0, diA->pConfigFile, -1, diW.pConfigFile, len); |
| 6824 | } |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6825 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6826 | if ((Level > 2) && diA->pDependentFiles) { |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6827 | lenA = multi_sz_lenA(diA->pDependentFiles); |
| 6828 | len = MultiByteToWideChar(CP_ACP, 0, diA->pDependentFiles, lenA, NULL, 0); |
| 6829 | diW.pDependentFiles = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6830 | MultiByteToWideChar(CP_ACP, 0, diA->pDependentFiles, lenA, diW.pDependentFiles, len); |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6831 | } |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6832 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6833 | if ((Level > 2) && diA->pMonitorName) { |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6834 | len = MultiByteToWideChar(CP_ACP, 0, diA->pMonitorName, -1, NULL, 0); |
| 6835 | diW.pMonitorName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6836 | MultiByteToWideChar(CP_ACP, 0, diA->pMonitorName, -1, diW.pMonitorName, len); |
| 6837 | } |
| 6838 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6839 | if ((Level > 3) && diA->pDefaultDataType) { |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6840 | len = MultiByteToWideChar(CP_ACP, 0, diA->pDefaultDataType, -1, NULL, 0); |
| 6841 | diW.pDefaultDataType = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6842 | MultiByteToWideChar(CP_ACP, 0, diA->pDefaultDataType, -1, diW.pDefaultDataType, len); |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6843 | } |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6844 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6845 | if ((Level > 3) && diA->pszzPreviousNames) { |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6846 | lenA = multi_sz_lenA(diA->pszzPreviousNames); |
| 6847 | len = MultiByteToWideChar(CP_ACP, 0, diA->pszzPreviousNames, lenA, NULL, 0); |
| 6848 | diW.pszzPreviousNames = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6849 | MultiByteToWideChar(CP_ACP, 0, diA->pszzPreviousNames, lenA, diW.pszzPreviousNames, len); |
| 6850 | } |
| 6851 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6852 | if ((Level > 5) && diA->pszMfgName) { |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6853 | len = MultiByteToWideChar(CP_ACP, 0, diA->pszMfgName, -1, NULL, 0); |
| 6854 | diW.pszMfgName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6855 | MultiByteToWideChar(CP_ACP, 0, diA->pszMfgName, -1, diW.pszMfgName, len); |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6856 | } |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6857 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6858 | if ((Level > 5) && diA->pszOEMUrl) { |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6859 | len = MultiByteToWideChar(CP_ACP, 0, diA->pszOEMUrl, -1, NULL, 0); |
| 6860 | diW.pszOEMUrl = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6861 | MultiByteToWideChar(CP_ACP, 0, diA->pszOEMUrl, -1, diW.pszOEMUrl, len); |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6862 | } |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6863 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6864 | if ((Level > 5) && diA->pszHardwareID) { |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6865 | len = MultiByteToWideChar(CP_ACP, 0, diA->pszHardwareID, -1, NULL, 0); |
| 6866 | diW.pszHardwareID = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6867 | MultiByteToWideChar(CP_ACP, 0, diA->pszHardwareID, -1, diW.pszHardwareID, len); |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6868 | } |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6869 | |
Detlef Riekenberg | 9be4cc3 | 2007-08-22 23:41:44 +0200 | [diff] [blame] | 6870 | if ((Level > 5) && diA->pszProvider) { |
Detlef Riekenberg | 4ff59a8 | 2007-08-16 05:18:08 +0200 | [diff] [blame] | 6871 | len = MultiByteToWideChar(CP_ACP, 0, diA->pszProvider, -1, NULL, 0); |
| 6872 | diW.pszProvider = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6873 | MultiByteToWideChar(CP_ACP, 0, diA->pszProvider, -1, diW.pszProvider, len); |
| 6874 | } |
| 6875 | |
| 6876 | if (Level > 7) { |
| 6877 | FIXME("level %u is incomplete\n", Level); |
| 6878 | } |
| 6879 | |
| 6880 | res = AddPrinterDriverExW(nameW, Level, (LPBYTE) &diW, dwFileCopyFlags); |
| 6881 | TRACE("got %u with %u\n", res, GetLastError()); |
| 6882 | HeapFree(GetProcessHeap(), 0, nameW); |
| 6883 | HeapFree(GetProcessHeap(), 0, diW.pName); |
| 6884 | HeapFree(GetProcessHeap(), 0, diW.pEnvironment); |
| 6885 | HeapFree(GetProcessHeap(), 0, diW.pDriverPath); |
| 6886 | HeapFree(GetProcessHeap(), 0, diW.pDataFile); |
| 6887 | HeapFree(GetProcessHeap(), 0, diW.pConfigFile); |
| 6888 | HeapFree(GetProcessHeap(), 0, diW.pDependentFiles); |
| 6889 | HeapFree(GetProcessHeap(), 0, diW.pMonitorName); |
| 6890 | HeapFree(GetProcessHeap(), 0, diW.pDefaultDataType); |
| 6891 | HeapFree(GetProcessHeap(), 0, diW.pszzPreviousNames); |
| 6892 | HeapFree(GetProcessHeap(), 0, diW.pszMfgName); |
| 6893 | HeapFree(GetProcessHeap(), 0, diW.pszOEMUrl); |
| 6894 | HeapFree(GetProcessHeap(), 0, diW.pszHardwareID); |
| 6895 | HeapFree(GetProcessHeap(), 0, diW.pszProvider); |
| 6896 | |
| 6897 | TRACE("=> %u with %u\n", res, GetLastError()); |
| 6898 | return res; |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 6899 | } |
| 6900 | |
| 6901 | /****************************************************************************** |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 6902 | * ConfigurePortA (WINSPOOL.@) |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 6903 | * |
| 6904 | * See ConfigurePortW. |
| 6905 | * |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 6906 | */ |
| 6907 | BOOL WINAPI ConfigurePortA(LPSTR pName, HWND hWnd, LPSTR pPortName) |
| 6908 | { |
Detlef Riekenberg | 6d88e43 | 2006-11-09 00:04:11 +0100 | [diff] [blame] | 6909 | LPWSTR nameW = NULL; |
| 6910 | LPWSTR portW = NULL; |
| 6911 | INT len; |
| 6912 | DWORD res; |
| 6913 | |
| 6914 | TRACE("(%s, %p, %s)\n", debugstr_a(pName), hWnd, debugstr_a(pPortName)); |
| 6915 | |
| 6916 | /* convert servername to unicode */ |
| 6917 | if (pName) { |
| 6918 | len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); |
| 6919 | nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6920 | MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); |
| 6921 | } |
| 6922 | |
| 6923 | /* convert portname to unicode */ |
| 6924 | if (pPortName) { |
| 6925 | len = MultiByteToWideChar(CP_ACP, 0, pPortName, -1, NULL, 0); |
| 6926 | portW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 6927 | MultiByteToWideChar(CP_ACP, 0, pPortName, -1, portW, len); |
| 6928 | } |
| 6929 | |
| 6930 | res = ConfigurePortW(nameW, hWnd, portW); |
| 6931 | HeapFree(GetProcessHeap(), 0, nameW); |
| 6932 | HeapFree(GetProcessHeap(), 0, portW); |
| 6933 | return res; |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 6934 | } |
| 6935 | |
| 6936 | /****************************************************************************** |
| 6937 | * ConfigurePortW (WINSPOOL.@) |
Detlef Riekenberg | 1395d14 | 2005-12-06 10:57:01 +0100 | [diff] [blame] | 6938 | * |
| 6939 | * Display the Configuration-Dialog for a specific Port |
| 6940 | * |
| 6941 | * PARAMS |
| 6942 | * pName [I] Servername or NULL (local Computer) |
| 6943 | * hWnd [I] Handle to parent Window for the Dialog-Box |
| 6944 | * pPortName [I] Name of the Port, that should be configured |
| 6945 | * |
| 6946 | * RETURNS |
| 6947 | * Success: TRUE |
| 6948 | * Failure: FALSE |
| 6949 | * |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 6950 | */ |
| 6951 | BOOL WINAPI ConfigurePortW(LPWSTR pName, HWND hWnd, LPWSTR pPortName) |
| 6952 | { |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 6953 | monitor_t * pm; |
Detlef Riekenberg | e576b09 | 2007-01-11 13:10:37 +0100 | [diff] [blame] | 6954 | monitor_t * pui; |
| 6955 | DWORD res; |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 6956 | |
| 6957 | TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName)); |
| 6958 | |
| 6959 | if (pName && pName[0]) { |
| 6960 | SetLastError(ERROR_INVALID_PARAMETER); |
| 6961 | return FALSE; |
| 6962 | } |
| 6963 | |
| 6964 | if (!pPortName) { |
| 6965 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 6966 | return FALSE; |
| 6967 | } |
| 6968 | |
| 6969 | /* an empty Portname is Invalid, but can popup a Dialog */ |
Detlef Riekenberg | e576b09 | 2007-01-11 13:10:37 +0100 | [diff] [blame] | 6970 | if (!pPortName[0]) { |
| 6971 | SetLastError(ERROR_NOT_SUPPORTED); |
| 6972 | return FALSE; |
| 6973 | } |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 6974 | |
| 6975 | pm = monitor_load_by_port(pPortName); |
Detlef Riekenberg | e576b09 | 2007-01-11 13:10:37 +0100 | [diff] [blame] | 6976 | if (pm && pm->monitor && pm->monitor->pfnConfigurePort) { |
| 6977 | TRACE("Using %s for %s (%p: %s)\n", debugstr_w(pm->name), debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); |
| 6978 | res = pm->monitor->pfnConfigurePort(pName, hWnd, pPortName); |
| 6979 | TRACE("got %d with %u\n", res, GetLastError()); |
| 6980 | } |
| 6981 | else |
| 6982 | { |
| 6983 | pui = monitor_loadui(pm); |
| 6984 | if (pui && pui->monitorUI && pui->monitorUI->pfnConfigurePortUI) { |
| 6985 | TRACE("Use %s for %s (%p: %s)\n", debugstr_w(pui->name), debugstr_w(pPortName), pui, debugstr_w(pui->dllname)); |
| 6986 | res = pui->monitorUI->pfnConfigurePortUI(pName, hWnd, pPortName); |
| 6987 | TRACE("got %d with %u\n", res, GetLastError()); |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 6988 | } |
| 6989 | else |
| 6990 | { |
Detlef Riekenberg | e576b09 | 2007-01-11 13:10:37 +0100 | [diff] [blame] | 6991 | FIXME("not implemented for %s (%p: %s => %p: %s)\n", debugstr_w(pPortName), |
| 6992 | pm, pm ? debugstr_w(pm->dllname) : NULL, pui, pui ? debugstr_w(pui->dllname) : NULL); |
| 6993 | |
| 6994 | /* XP: ERROR_NOT_SUPPORTED, NT351,9x: ERROR_INVALID_PARAMETER */ |
| 6995 | SetLastError(ERROR_NOT_SUPPORTED); |
| 6996 | res = FALSE; |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 6997 | } |
Detlef Riekenberg | e576b09 | 2007-01-11 13:10:37 +0100 | [diff] [blame] | 6998 | monitor_unload(pui); |
Detlef Riekenberg | a44e0ac | 2006-11-09 00:04:08 +0100 | [diff] [blame] | 6999 | } |
| 7000 | monitor_unload(pm); |
| 7001 | |
Detlef Riekenberg | e576b09 | 2007-01-11 13:10:37 +0100 | [diff] [blame] | 7002 | TRACE("returning %d with %u\n", res, GetLastError()); |
| 7003 | return res; |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7004 | } |
| 7005 | |
| 7006 | /****************************************************************************** |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7007 | * ConnectToPrinterDlg (WINSPOOL.@) |
| 7008 | */ |
| 7009 | HANDLE WINAPI ConnectToPrinterDlg( HWND hWnd, DWORD Flags ) |
| 7010 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7011 | FIXME("%p %x\n", hWnd, Flags); |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7012 | return NULL; |
| 7013 | } |
| 7014 | |
| 7015 | /****************************************************************************** |
| 7016 | * DeletePrinterConnectionA (WINSPOOL.@) |
| 7017 | */ |
| 7018 | BOOL WINAPI DeletePrinterConnectionA( LPSTR pName ) |
| 7019 | { |
| 7020 | FIXME("%s\n", debugstr_a(pName)); |
| 7021 | return TRUE; |
| 7022 | } |
| 7023 | |
| 7024 | /****************************************************************************** |
| 7025 | * DeletePrinterConnectionW (WINSPOOL.@) |
| 7026 | */ |
| 7027 | BOOL WINAPI DeletePrinterConnectionW( LPWSTR pName ) |
| 7028 | { |
| 7029 | FIXME("%s\n", debugstr_w(pName)); |
| 7030 | return TRUE; |
| 7031 | } |
| 7032 | |
| 7033 | /****************************************************************************** |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 7034 | * DeletePrinterDriverExW (WINSPOOL.@) |
| 7035 | */ |
| 7036 | BOOL WINAPI DeletePrinterDriverExW( LPWSTR pName, LPWSTR pEnvironment, |
| 7037 | LPWSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag) |
| 7038 | { |
Huw Davies | 388fd47 | 2006-11-07 12:27:09 +0000 | [diff] [blame] | 7039 | HKEY hkey_drivers; |
| 7040 | BOOL ret = FALSE; |
| 7041 | |
| 7042 | TRACE("%s %s %s %x %x\n", debugstr_w(pName), debugstr_w(pEnvironment), |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 7043 | debugstr_w(pDriverName), dwDeleteFlag, dwVersionFlag); |
Huw Davies | 388fd47 | 2006-11-07 12:27:09 +0000 | [diff] [blame] | 7044 | |
| 7045 | if(pName && pName[0]) |
| 7046 | { |
| 7047 | FIXME("pName = %s - unsupported\n", debugstr_w(pName)); |
| 7048 | SetLastError(ERROR_INVALID_PARAMETER); |
| 7049 | return FALSE; |
| 7050 | } |
| 7051 | |
| 7052 | if(dwDeleteFlag) |
| 7053 | { |
| 7054 | FIXME("dwDeleteFlag = %x - unsupported\n", dwDeleteFlag); |
| 7055 | SetLastError(ERROR_INVALID_PARAMETER); |
| 7056 | return FALSE; |
| 7057 | } |
| 7058 | |
| 7059 | hkey_drivers = WINSPOOL_OpenDriverReg(pEnvironment, TRUE); |
| 7060 | |
| 7061 | if(!hkey_drivers) |
| 7062 | { |
| 7063 | ERR("Can't open drivers key\n"); |
| 7064 | return FALSE; |
| 7065 | } |
| 7066 | |
Stefan Leichter | 06b64a1 | 2007-06-05 18:47:17 +0200 | [diff] [blame] | 7067 | if(RegDeleteTreeW(hkey_drivers, pDriverName) == ERROR_SUCCESS) |
Huw Davies | 388fd47 | 2006-11-07 12:27:09 +0000 | [diff] [blame] | 7068 | ret = TRUE; |
| 7069 | |
| 7070 | RegCloseKey(hkey_drivers); |
| 7071 | |
| 7072 | return ret; |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 7073 | } |
| 7074 | |
| 7075 | /****************************************************************************** |
| 7076 | * DeletePrinterDriverExA (WINSPOOL.@) |
| 7077 | */ |
| 7078 | BOOL WINAPI DeletePrinterDriverExA( LPSTR pName, LPSTR pEnvironment, |
| 7079 | LPSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag) |
| 7080 | { |
Huw Davies | 7ce85a8 | 2006-11-07 12:06:04 +0000 | [diff] [blame] | 7081 | UNICODE_STRING NameW, EnvW, DriverW; |
| 7082 | BOOL ret; |
| 7083 | |
| 7084 | asciitounicode(&NameW, pName); |
| 7085 | asciitounicode(&EnvW, pEnvironment); |
| 7086 | asciitounicode(&DriverW, pDriverName); |
| 7087 | |
| 7088 | ret = DeletePrinterDriverExW(NameW.Buffer, EnvW.Buffer, DriverW.Buffer, dwDeleteFlag, dwVersionFlag); |
| 7089 | |
| 7090 | RtlFreeUnicodeString(&DriverW); |
| 7091 | RtlFreeUnicodeString(&EnvW); |
| 7092 | RtlFreeUnicodeString(&NameW); |
| 7093 | |
| 7094 | return ret; |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 7095 | } |
| 7096 | |
| 7097 | /****************************************************************************** |
| 7098 | * DeletePrinterDataExW (WINSPOOL.@) |
| 7099 | */ |
| 7100 | DWORD WINAPI DeletePrinterDataExW( HANDLE hPrinter, LPCWSTR pKeyName, |
| 7101 | LPCWSTR pValueName) |
| 7102 | { |
| 7103 | FIXME("%p %s %s\n", hPrinter, |
| 7104 | debugstr_w(pKeyName), debugstr_w(pValueName)); |
| 7105 | return ERROR_INVALID_PARAMETER; |
| 7106 | } |
| 7107 | |
| 7108 | /****************************************************************************** |
| 7109 | * DeletePrinterDataExA (WINSPOOL.@) |
| 7110 | */ |
| 7111 | DWORD WINAPI DeletePrinterDataExA( HANDLE hPrinter, LPCSTR pKeyName, |
| 7112 | LPCSTR pValueName) |
| 7113 | { |
| 7114 | FIXME("%p %s %s\n", hPrinter, |
| 7115 | debugstr_a(pKeyName), debugstr_a(pValueName)); |
| 7116 | return ERROR_INVALID_PARAMETER; |
| 7117 | } |
| 7118 | |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7119 | /****************************************************************************** |
| 7120 | * DeletePrintProcessorA (WINSPOOL.@) |
| 7121 | */ |
| 7122 | BOOL WINAPI DeletePrintProcessorA(LPSTR pName, LPSTR pEnvironment, LPSTR pPrintProcessorName) |
| 7123 | { |
| 7124 | FIXME("%s %s %s\n", debugstr_a(pName), debugstr_a(pEnvironment), |
| 7125 | debugstr_a(pPrintProcessorName)); |
| 7126 | return TRUE; |
| 7127 | } |
| 7128 | |
| 7129 | /****************************************************************************** |
| 7130 | * DeletePrintProcessorW (WINSPOOL.@) |
| 7131 | */ |
| 7132 | BOOL WINAPI DeletePrintProcessorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pPrintProcessorName) |
| 7133 | { |
| 7134 | FIXME("%s %s %s\n", debugstr_w(pName), debugstr_w(pEnvironment), |
| 7135 | debugstr_w(pPrintProcessorName)); |
| 7136 | return TRUE; |
| 7137 | } |
| 7138 | |
| 7139 | /****************************************************************************** |
| 7140 | * DeletePrintProvidorA (WINSPOOL.@) |
| 7141 | */ |
| 7142 | BOOL WINAPI DeletePrintProvidorA(LPSTR pName, LPSTR pEnvironment, LPSTR pPrintProviderName) |
| 7143 | { |
| 7144 | FIXME("%s %s %s\n", debugstr_a(pName), debugstr_a(pEnvironment), |
| 7145 | debugstr_a(pPrintProviderName)); |
| 7146 | return TRUE; |
| 7147 | } |
| 7148 | |
| 7149 | /****************************************************************************** |
| 7150 | * DeletePrintProvidorW (WINSPOOL.@) |
| 7151 | */ |
| 7152 | BOOL WINAPI DeletePrintProvidorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pPrintProviderName) |
| 7153 | { |
| 7154 | FIXME("%s %s %s\n", debugstr_w(pName), debugstr_w(pEnvironment), |
| 7155 | debugstr_w(pPrintProviderName)); |
| 7156 | return TRUE; |
| 7157 | } |
| 7158 | |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7159 | /****************************************************************************** |
| 7160 | * EnumFormsA (WINSPOOL.@) |
| 7161 | */ |
| 7162 | BOOL WINAPI EnumFormsA( HANDLE hPrinter, DWORD Level, LPBYTE pForm, |
| 7163 | DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) |
| 7164 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7165 | FIXME("%p %x %p %x %p %p\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned); |
Detlef Riekenberg | 89ed2d9 | 2006-06-16 09:54:55 +0200 | [diff] [blame] | 7166 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7167 | return FALSE; |
| 7168 | } |
| 7169 | |
| 7170 | /****************************************************************************** |
| 7171 | * EnumFormsW (WINSPOOL.@) |
| 7172 | */ |
| 7173 | BOOL WINAPI EnumFormsW( HANDLE hPrinter, DWORD Level, LPBYTE pForm, |
| 7174 | DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned ) |
| 7175 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7176 | FIXME("%p %x %p %x %p %p\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned); |
Detlef Riekenberg | 89ed2d9 | 2006-06-16 09:54:55 +0200 | [diff] [blame] | 7177 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7178 | return FALSE; |
| 7179 | } |
| 7180 | |
Steven Edwards | 86b3056 | 2004-03-17 01:42:46 +0000 | [diff] [blame] | 7181 | /***************************************************************************** |
| 7182 | * EnumMonitorsA [WINSPOOL.@] |
| 7183 | * |
Detlef Riekenberg | a521947 | 2005-12-06 11:33:52 +0100 | [diff] [blame] | 7184 | * See EnumMonitorsW. |
| 7185 | * |
Steven Edwards | 86b3056 | 2004-03-17 01:42:46 +0000 | [diff] [blame] | 7186 | */ |
| 7187 | BOOL WINAPI EnumMonitorsA(LPSTR pName, DWORD Level, LPBYTE pMonitors, |
| 7188 | DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) |
| 7189 | { |
Detlef Riekenberg | 603f13e | 2006-03-31 14:32:02 +0200 | [diff] [blame] | 7190 | BOOL res; |
| 7191 | LPBYTE bufferW = NULL; |
| 7192 | LPWSTR nameW = NULL; |
| 7193 | DWORD needed = 0; |
| 7194 | DWORD numentries = 0; |
| 7195 | INT len; |
| 7196 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7197 | TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_a(pName), Level, pMonitors, |
Steven Edwards | 86b3056 | 2004-03-17 01:42:46 +0000 | [diff] [blame] | 7198 | cbBuf, pcbNeeded, pcReturned); |
Detlef Riekenberg | 603f13e | 2006-03-31 14:32:02 +0200 | [diff] [blame] | 7199 | |
| 7200 | /* convert servername to unicode */ |
| 7201 | if (pName) { |
| 7202 | len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); |
| 7203 | nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 7204 | MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); |
| 7205 | } |
| 7206 | /* alloc (userbuffersize*sizeof(WCHAR) and try to enum the monitors */ |
| 7207 | needed = cbBuf * sizeof(WCHAR); |
| 7208 | if (needed) bufferW = HeapAlloc(GetProcessHeap(), 0, needed); |
| 7209 | res = EnumMonitorsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned); |
| 7210 | |
| 7211 | if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { |
| 7212 | if (pcbNeeded) needed = *pcbNeeded; |
| 7213 | /* HeapReAlloc return NULL, when bufferW was NULL */ |
| 7214 | bufferW = (bufferW) ? HeapReAlloc(GetProcessHeap(), 0, bufferW, needed) : |
| 7215 | HeapAlloc(GetProcessHeap(), 0, needed); |
| 7216 | |
| 7217 | /* Try again with the large Buffer */ |
| 7218 | res = EnumMonitorsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned); |
| 7219 | } |
| 7220 | numentries = pcReturned ? *pcReturned : 0; |
| 7221 | needed = 0; |
| 7222 | /* |
| 7223 | W2k require the buffersize from EnumMonitorsW also for EnumMonitorsA. |
| 7224 | We use the smaller Ansi-Size to avoid conflicts with fixed Buffers of old Apps. |
| 7225 | */ |
| 7226 | if (res) { |
Francois Gouget | b0bde6b | 2007-01-18 11:35:50 +0100 | [diff] [blame] | 7227 | /* EnumMonitorsW collected all Data. Parse them to calculate ANSI-Size */ |
Detlef Riekenberg | 603f13e | 2006-03-31 14:32:02 +0200 | [diff] [blame] | 7228 | DWORD entrysize = 0; |
| 7229 | DWORD index; |
| 7230 | LPSTR ptr; |
| 7231 | LPMONITOR_INFO_2W mi2w; |
| 7232 | LPMONITOR_INFO_2A mi2a; |
| 7233 | |
| 7234 | /* MONITOR_INFO_*W and MONITOR_INFO_*A have the same size */ |
| 7235 | entrysize = (Level == 1) ? sizeof(MONITOR_INFO_1A) : sizeof(MONITOR_INFO_2A); |
| 7236 | |
| 7237 | /* First pass: calculate the size for all Entries */ |
| 7238 | mi2w = (LPMONITOR_INFO_2W) bufferW; |
| 7239 | mi2a = (LPMONITOR_INFO_2A) pMonitors; |
| 7240 | index = 0; |
| 7241 | while (index < numentries) { |
| 7242 | index++; |
| 7243 | needed += entrysize; /* MONITOR_INFO_?A */ |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7244 | TRACE("%p: parsing #%d (%s)\n", mi2w, index, debugstr_w(mi2w->pName)); |
Detlef Riekenberg | 603f13e | 2006-03-31 14:32:02 +0200 | [diff] [blame] | 7245 | |
| 7246 | needed += WideCharToMultiByte(CP_ACP, 0, mi2w->pName, -1, |
| 7247 | NULL, 0, NULL, NULL); |
| 7248 | if (Level > 1) { |
| 7249 | needed += WideCharToMultiByte(CP_ACP, 0, mi2w->pEnvironment, -1, |
| 7250 | NULL, 0, NULL, NULL); |
| 7251 | needed += WideCharToMultiByte(CP_ACP, 0, mi2w->pDLLName, -1, |
| 7252 | NULL, 0, NULL, NULL); |
| 7253 | } |
| 7254 | /* use LPBYTE with entrysize to avoid double code (MONITOR_INFO_1 + MONITOR_INFO_2) */ |
| 7255 | mi2w = (LPMONITOR_INFO_2W) (((LPBYTE)mi2w) + entrysize); |
| 7256 | mi2a = (LPMONITOR_INFO_2A) (((LPBYTE)mi2a) + entrysize); |
| 7257 | } |
| 7258 | |
| 7259 | /* check for errors and quit on failure */ |
| 7260 | if (cbBuf < needed) { |
| 7261 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 7262 | res = FALSE; |
| 7263 | goto emA_cleanup; |
| 7264 | } |
| 7265 | len = entrysize * numentries; /* room for all MONITOR_INFO_?A */ |
| 7266 | ptr = (LPSTR) &pMonitors[len]; /* room for strings */ |
| 7267 | cbBuf -= len ; /* free Bytes in the user-Buffer */ |
| 7268 | mi2w = (LPMONITOR_INFO_2W) bufferW; |
| 7269 | mi2a = (LPMONITOR_INFO_2A) pMonitors; |
| 7270 | index = 0; |
| 7271 | /* Second Pass: Fill the User Buffer (if we have one) */ |
| 7272 | while ((index < numentries) && pMonitors) { |
| 7273 | index++; |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7274 | TRACE("%p: writing MONITOR_INFO_%dA #%d\n", mi2a, Level, index); |
Detlef Riekenberg | 603f13e | 2006-03-31 14:32:02 +0200 | [diff] [blame] | 7275 | mi2a->pName = ptr; |
| 7276 | len = WideCharToMultiByte(CP_ACP, 0, mi2w->pName, -1, |
| 7277 | ptr, cbBuf , NULL, NULL); |
| 7278 | ptr += len; |
| 7279 | cbBuf -= len; |
| 7280 | if (Level > 1) { |
| 7281 | mi2a->pEnvironment = ptr; |
| 7282 | len = WideCharToMultiByte(CP_ACP, 0, mi2w->pEnvironment, -1, |
| 7283 | ptr, cbBuf, NULL, NULL); |
| 7284 | ptr += len; |
| 7285 | cbBuf -= len; |
| 7286 | |
| 7287 | mi2a->pDLLName = ptr; |
| 7288 | len = WideCharToMultiByte(CP_ACP, 0, mi2w->pDLLName, -1, |
| 7289 | ptr, cbBuf, NULL, NULL); |
| 7290 | ptr += len; |
| 7291 | cbBuf -= len; |
| 7292 | } |
| 7293 | /* use LPBYTE with entrysize to avoid double code (MONITOR_INFO_1 + MONITOR_INFO_2) */ |
| 7294 | mi2w = (LPMONITOR_INFO_2W) (((LPBYTE)mi2w) + entrysize); |
| 7295 | mi2a = (LPMONITOR_INFO_2A) (((LPBYTE)mi2a) + entrysize); |
| 7296 | } |
| 7297 | } |
| 7298 | emA_cleanup: |
| 7299 | if (pcbNeeded) *pcbNeeded = needed; |
| 7300 | if (pcReturned) *pcReturned = (res) ? numentries : 0; |
| 7301 | |
| 7302 | HeapFree(GetProcessHeap(), 0, nameW); |
| 7303 | HeapFree(GetProcessHeap(), 0, bufferW); |
| 7304 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7305 | TRACE("returning %d with %d (%d byte for %d entries)\n", |
Detlef Riekenberg | 603f13e | 2006-03-31 14:32:02 +0200 | [diff] [blame] | 7306 | (res), GetLastError(), needed, numentries); |
| 7307 | |
| 7308 | return (res); |
| 7309 | |
Steven Edwards | 86b3056 | 2004-03-17 01:42:46 +0000 | [diff] [blame] | 7310 | } |
| 7311 | |
| 7312 | /***************************************************************************** |
| 7313 | * EnumMonitorsW [WINSPOOL.@] |
| 7314 | * |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 7315 | * Enumerate available Port-Monitors |
Detlef Riekenberg | a521947 | 2005-12-06 11:33:52 +0100 | [diff] [blame] | 7316 | * |
| 7317 | * PARAMS |
| 7318 | * pName [I] Servername or NULL (local Computer) |
| 7319 | * Level [I] Structure-Level (1:Win9x+NT or 2:NT only) |
| 7320 | * pMonitors [O] PTR to Buffer that receives the Result |
| 7321 | * cbBuf [I] Size of Buffer at pMonitors |
| 7322 | * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pMonitors |
| 7323 | * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors |
| 7324 | * |
| 7325 | * RETURNS |
| 7326 | * Success: TRUE |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 7327 | * Failure: FALSE and in pcbNeeded the Bytes required for buffer, if cbBuf is too small |
Detlef Riekenberg | a521947 | 2005-12-06 11:33:52 +0100 | [diff] [blame] | 7328 | * |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 7329 | * NOTES |
| 7330 | * Windows reads the Registry once and cache the Results. |
| 7331 | * |
| 7332 | *| Language-Monitors are also installed in the same Registry-Location but |
| 7333 | *| they are filtered in Windows (not returned by EnumMonitors). |
| 7334 | *| We do no filtering to simplify our Code. |
Detlef Riekenberg | a521947 | 2005-12-06 11:33:52 +0100 | [diff] [blame] | 7335 | * |
Steven Edwards | 86b3056 | 2004-03-17 01:42:46 +0000 | [diff] [blame] | 7336 | */ |
| 7337 | BOOL WINAPI EnumMonitorsW(LPWSTR pName, DWORD Level, LPBYTE pMonitors, |
| 7338 | DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) |
| 7339 | { |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 7340 | DWORD needed = 0; |
| 7341 | DWORD numentries = 0; |
Detlef Riekenberg | 50b32da | 2006-04-08 19:17:06 +0200 | [diff] [blame] | 7342 | BOOL res = FALSE; |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 7343 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7344 | TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors, |
Steven Edwards | 86b3056 | 2004-03-17 01:42:46 +0000 | [diff] [blame] | 7345 | cbBuf, pcbNeeded, pcReturned); |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 7346 | |
| 7347 | if (pName && (lstrlenW(pName))) { |
| 7348 | FIXME("for Server %s not implemented\n", debugstr_w(pName)); |
| 7349 | SetLastError(ERROR_ACCESS_DENIED); |
| 7350 | goto emW_cleanup; |
| 7351 | } |
| 7352 | |
| 7353 | /* Level is not checked in win9x */ |
| 7354 | if (!Level || (Level > 2)) { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7355 | WARN("level (%d) is ignored in win9x\n", Level); |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 7356 | SetLastError(ERROR_INVALID_LEVEL); |
| 7357 | goto emW_cleanup; |
| 7358 | } |
| 7359 | if (!pcbNeeded) { |
| 7360 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 7361 | goto emW_cleanup; |
| 7362 | } |
| 7363 | |
| 7364 | /* Scan all Monitor-Keys */ |
| 7365 | numentries = 0; |
| 7366 | needed = get_local_monitors(Level, NULL, 0, &numentries); |
| 7367 | |
| 7368 | /* we calculated the needed buffersize. now do the error-checks */ |
| 7369 | if (cbBuf < needed) { |
| 7370 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| 7371 | goto emW_cleanup; |
| 7372 | } |
| 7373 | else if (!pMonitors || !pcReturned) { |
| 7374 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 7375 | goto emW_cleanup; |
| 7376 | } |
| 7377 | |
| 7378 | /* fill the Buffer with the Monitor-Keys */ |
| 7379 | needed = get_local_monitors(Level, pMonitors, cbBuf, &numentries); |
| 7380 | res = TRUE; |
| 7381 | |
| 7382 | emW_cleanup: |
| 7383 | if (pcbNeeded) *pcbNeeded = needed; |
| 7384 | if (pcReturned) *pcReturned = numentries; |
| 7385 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7386 | TRACE("returning %d with %d (%d byte for %d entries)\n", |
Detlef Riekenberg | 4b00805 | 2006-03-31 14:30:10 +0200 | [diff] [blame] | 7387 | res, GetLastError(), needed, numentries); |
| 7388 | |
| 7389 | return (res); |
Steven Edwards | 86b3056 | 2004-03-17 01:42:46 +0000 | [diff] [blame] | 7390 | } |
| 7391 | |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 7392 | /****************************************************************************** |
Detlef Riekenberg | 94a8784 | 2008-03-07 23:49:57 +0100 | [diff] [blame] | 7393 | * SpoolerInit (WINSPOOL.@) |
| 7394 | * |
| 7395 | * Initialize the Spooler |
| 7396 | * |
| 7397 | * RETURNS |
| 7398 | * Success: TRUE |
| 7399 | * Failure: FALSE |
| 7400 | * |
| 7401 | * NOTES |
| 7402 | * The function fails on windows, when the spooler service is not running |
| 7403 | * |
| 7404 | */ |
| 7405 | BOOL WINAPI SpoolerInit(void) |
| 7406 | { |
| 7407 | |
| 7408 | if ((backend == NULL) && !load_backend()) return FALSE; |
| 7409 | return TRUE; |
| 7410 | } |
| 7411 | |
| 7412 | /****************************************************************************** |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 7413 | * XcvDataW (WINSPOOL.@) |
| 7414 | * |
Detlef Riekenberg | e82d228 | 2007-01-05 01:11:21 +0100 | [diff] [blame] | 7415 | * Execute commands in the Printmonitor DLL |
| 7416 | * |
| 7417 | * PARAMS |
| 7418 | * hXcv [i] Handle from OpenPrinter (with XcvMonitor or XcvPort) |
| 7419 | * pszDataName [i] Name of the command to execute |
| 7420 | * pInputData [i] Buffer for extra Input Data (needed only for some commands) |
| 7421 | * cbInputData [i] Size in Bytes of Buffer at pInputData |
| 7422 | * pOutputData [o] Buffer to receive additional Data (needed only for some commands) |
| 7423 | * cbOutputData [i] Size in Bytes of Buffer at pOutputData |
| 7424 | * pcbOutputNeeded [o] PTR to receive the minimal Size in Bytes of the Buffer at pOutputData |
| 7425 | * pdwStatus [o] PTR to receive the win32 error code from the Printmonitor DLL |
| 7426 | * |
| 7427 | * RETURNS |
| 7428 | * Success: TRUE |
| 7429 | * Failure: FALSE |
| 7430 | * |
| 7431 | * NOTES |
| 7432 | * Returning "TRUE" does mean, that the Printmonitor DLL was called successful. |
| 7433 | * The execution of the command can still fail (check pdwStatus for ERROR_SUCCESS). |
| 7434 | * |
| 7435 | * Minimal List of commands, that a Printmonitor DLL should support: |
| 7436 | * |
| 7437 | *| "MonitorUI" : Return the Name of the Userinterface-DLL as WSTR in pOutputData |
| 7438 | *| "AddPort" : Add a Port |
| 7439 | *| "DeletePort": Delete a Port |
| 7440 | * |
| 7441 | * Many Printmonitors support additional commands. Examples for localspl.dll: |
| 7442 | * "GetDefaultCommConfig", "SetDefaultCommConfig", |
| 7443 | * "GetTransmissionRetryTimeout", "ConfigureLPTPortCommandOK" |
| 7444 | * |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 7445 | */ |
| 7446 | BOOL WINAPI XcvDataW( HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData, |
| 7447 | DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, |
| 7448 | PDWORD pcbOutputNeeded, PDWORD pdwStatus) |
| 7449 | { |
Detlef Riekenberg | e82d228 | 2007-01-05 01:11:21 +0100 | [diff] [blame] | 7450 | opened_printer_t *printer; |
| 7451 | |
| 7452 | TRACE("(%p, %s, %p, %d, %p, %d, %p, %p)\n", hXcv, debugstr_w(pszDataName), |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 7453 | pInputData, cbInputData, pOutputData, |
| 7454 | cbOutputData, pcbOutputNeeded, pdwStatus); |
Detlef Riekenberg | e82d228 | 2007-01-05 01:11:21 +0100 | [diff] [blame] | 7455 | |
| 7456 | printer = get_opened_printer(hXcv); |
| 7457 | if (!printer || (!printer->hXcv)) { |
| 7458 | SetLastError(ERROR_INVALID_HANDLE); |
| 7459 | return FALSE; |
| 7460 | } |
| 7461 | |
Detlef Riekenberg | b86a764 | 2007-01-15 05:38:28 +0100 | [diff] [blame] | 7462 | if (!pcbOutputNeeded) { |
| 7463 | SetLastError(ERROR_INVALID_PARAMETER); |
| 7464 | return FALSE; |
| 7465 | } |
| 7466 | |
| 7467 | if (!pszDataName || !pdwStatus || (!pOutputData && (cbOutputData > 0))) { |
| 7468 | SetLastError(RPC_X_NULL_REF_POINTER); |
| 7469 | return FALSE; |
| 7470 | } |
| 7471 | |
| 7472 | *pcbOutputNeeded = 0; |
| 7473 | |
Detlef Riekenberg | e82d228 | 2007-01-05 01:11:21 +0100 | [diff] [blame] | 7474 | *pdwStatus = printer->pm->monitor->pfnXcvDataPort(printer->hXcv, pszDataName, |
| 7475 | pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded); |
| 7476 | |
| 7477 | return TRUE; |
Mike McCormack | 0f669e4 | 2003-08-12 18:54:26 +0000 | [diff] [blame] | 7478 | } |
Ulrich Czekalla | 601d466 | 2004-10-29 21:27:38 +0000 | [diff] [blame] | 7479 | |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7480 | /***************************************************************************** |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7481 | * EnumPrinterDataA [WINSPOOL.@] |
| 7482 | * |
| 7483 | */ |
| 7484 | DWORD WINAPI EnumPrinterDataA( HANDLE hPrinter, DWORD dwIndex, LPSTR pValueName, |
| 7485 | DWORD cbValueName, LPDWORD pcbValueName, LPDWORD pType, LPBYTE pData, |
| 7486 | DWORD cbData, LPDWORD pcbData ) |
| 7487 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7488 | FIXME("%p %x %p %x %p %p %p %x %p\n", hPrinter, dwIndex, pValueName, |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7489 | cbValueName, pcbValueName, pType, pData, cbData, pcbData); |
| 7490 | return ERROR_NO_MORE_ITEMS; |
| 7491 | } |
| 7492 | |
| 7493 | /***************************************************************************** |
| 7494 | * EnumPrinterDataW [WINSPOOL.@] |
| 7495 | * |
| 7496 | */ |
| 7497 | DWORD WINAPI EnumPrinterDataW( HANDLE hPrinter, DWORD dwIndex, LPWSTR pValueName, |
| 7498 | DWORD cbValueName, LPDWORD pcbValueName, LPDWORD pType, LPBYTE pData, |
| 7499 | DWORD cbData, LPDWORD pcbData ) |
| 7500 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7501 | FIXME("%p %x %p %x %p %p %p %x %p\n", hPrinter, dwIndex, pValueName, |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7502 | cbValueName, pcbValueName, pType, pData, cbData, pcbData); |
| 7503 | return ERROR_NO_MORE_ITEMS; |
| 7504 | } |
| 7505 | |
| 7506 | /***************************************************************************** |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7507 | * EnumPrintProcessorDatatypesA [WINSPOOL.@] |
| 7508 | * |
| 7509 | */ |
| 7510 | BOOL WINAPI EnumPrintProcessorDatatypesA(LPSTR pName, LPSTR pPrintProcessorName, |
| 7511 | DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, |
| 7512 | LPDWORD pcbNeeded, LPDWORD pcReturned) |
| 7513 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7514 | FIXME("Stub: %s %s %d %p %d %p %p\n", debugstr_a(pName), |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7515 | debugstr_a(pPrintProcessorName), Level, pDatatypes, cbBuf, |
| 7516 | pcbNeeded, pcReturned); |
| 7517 | return FALSE; |
| 7518 | } |
| 7519 | |
| 7520 | /***************************************************************************** |
| 7521 | * EnumPrintProcessorDatatypesW [WINSPOOL.@] |
| 7522 | * |
| 7523 | */ |
| 7524 | BOOL WINAPI EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, |
| 7525 | DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, |
| 7526 | LPDWORD pcbNeeded, LPDWORD pcReturned) |
| 7527 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7528 | FIXME("Stub: %s %s %d %p %d %p %p\n", debugstr_w(pName), |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7529 | debugstr_w(pPrintProcessorName), Level, pDatatypes, cbBuf, |
| 7530 | pcbNeeded, pcReturned); |
| 7531 | return FALSE; |
| 7532 | } |
Ulrich Czekalla | 601d466 | 2004-10-29 21:27:38 +0000 | [diff] [blame] | 7533 | |
| 7534 | /***************************************************************************** |
| 7535 | * EnumPrintProcessorsA [WINSPOOL.@] |
| 7536 | * |
| 7537 | */ |
| 7538 | BOOL WINAPI EnumPrintProcessorsA(LPSTR pName, LPSTR pEnvironment, DWORD Level, |
| 7539 | LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcbReturned) |
| 7540 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7541 | FIXME("Stub: %s %s %d %p %d %p %p\n", pName, pEnvironment, Level, |
Ulrich Czekalla | 601d466 | 2004-10-29 21:27:38 +0000 | [diff] [blame] | 7542 | pPrintProcessorInfo, cbBuf, pcbNeeded, pcbReturned); |
| 7543 | return FALSE; |
| 7544 | } |
| 7545 | |
| 7546 | /***************************************************************************** |
| 7547 | * EnumPrintProcessorsW [WINSPOOL.@] |
| 7548 | * |
| 7549 | */ |
| 7550 | BOOL WINAPI EnumPrintProcessorsW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, |
| 7551 | LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcbReturned) |
| 7552 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7553 | FIXME("Stub: %s %s %d %p %d %p %p\n", debugstr_w(pName), |
Ulrich Czekalla | 601d466 | 2004-10-29 21:27:38 +0000 | [diff] [blame] | 7554 | debugstr_w(pEnvironment), Level, pPrintProcessorInfo, |
| 7555 | cbBuf, pcbNeeded, pcbReturned); |
| 7556 | return FALSE; |
| 7557 | } |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7558 | |
| 7559 | /***************************************************************************** |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7560 | * ExtDeviceMode [WINSPOOL.@] |
| 7561 | * |
| 7562 | */ |
| 7563 | LONG WINAPI ExtDeviceMode( HWND hWnd, HANDLE hInst, LPDEVMODEA pDevModeOutput, |
| 7564 | LPSTR pDeviceName, LPSTR pPort, LPDEVMODEA pDevModeInput, LPSTR pProfile, |
| 7565 | DWORD fMode) |
| 7566 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7567 | FIXME("Stub: %p %p %p %s %s %p %s %x\n", hWnd, hInst, pDevModeOutput, |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7568 | debugstr_a(pDeviceName), debugstr_a(pPort), pDevModeInput, |
| 7569 | debugstr_a(pProfile), fMode); |
| 7570 | return -1; |
| 7571 | } |
| 7572 | |
| 7573 | /***************************************************************************** |
| 7574 | * FindClosePrinterChangeNotification [WINSPOOL.@] |
| 7575 | * |
| 7576 | */ |
| 7577 | BOOL WINAPI FindClosePrinterChangeNotification( HANDLE hChange ) |
| 7578 | { |
| 7579 | FIXME("Stub: %p\n", hChange); |
| 7580 | return TRUE; |
| 7581 | } |
| 7582 | |
| 7583 | /***************************************************************************** |
| 7584 | * FindFirstPrinterChangeNotification [WINSPOOL.@] |
| 7585 | * |
| 7586 | */ |
| 7587 | HANDLE WINAPI FindFirstPrinterChangeNotification( HANDLE hPrinter, |
| 7588 | DWORD fdwFlags, DWORD fdwOptions, LPVOID pPrinterNotifyOptions ) |
| 7589 | { |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7590 | FIXME("Stub: %p %x %x %p\n", |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7591 | hPrinter, fdwFlags, fdwOptions, pPrinterNotifyOptions); |
| 7592 | return INVALID_HANDLE_VALUE; |
| 7593 | } |
| 7594 | |
| 7595 | /***************************************************************************** |
| 7596 | * FindNextPrinterChangeNotification [WINSPOOL.@] |
| 7597 | * |
| 7598 | */ |
| 7599 | BOOL WINAPI FindNextPrinterChangeNotification( HANDLE hChange, PDWORD pdwChange, |
| 7600 | LPVOID pPrinterNotifyOptions, LPVOID *ppPrinterNotifyInfo ) |
| 7601 | { |
| 7602 | FIXME("Stub: %p %p %p %p\n", |
| 7603 | hChange, pdwChange, pPrinterNotifyOptions, ppPrinterNotifyInfo); |
| 7604 | return FALSE; |
| 7605 | } |
| 7606 | |
| 7607 | /***************************************************************************** |
| 7608 | * FreePrinterNotifyInfo [WINSPOOL.@] |
| 7609 | * |
| 7610 | */ |
| 7611 | BOOL WINAPI FreePrinterNotifyInfo( PPRINTER_NOTIFY_INFO pPrinterNotifyInfo ) |
| 7612 | { |
| 7613 | FIXME("Stub: %p\n", pPrinterNotifyInfo); |
| 7614 | return TRUE; |
| 7615 | } |
| 7616 | |
| 7617 | /***************************************************************************** |
Huw Davies | 03f36e6 | 2005-07-18 13:13:31 +0000 | [diff] [blame] | 7618 | * string_to_buf |
| 7619 | * |
| 7620 | * Copies a unicode string into a buffer. The buffer will either contain unicode or |
| 7621 | * ansi depending on the unicode parameter. |
| 7622 | */ |
| 7623 | static BOOL string_to_buf(LPCWSTR str, LPBYTE ptr, DWORD cb, DWORD *size, BOOL unicode) |
| 7624 | { |
| 7625 | if(!str) |
| 7626 | { |
| 7627 | *size = 0; |
| 7628 | return TRUE; |
| 7629 | } |
| 7630 | |
| 7631 | if(unicode) |
| 7632 | { |
| 7633 | *size = (strlenW(str) + 1) * sizeof(WCHAR); |
| 7634 | if(*size <= cb) |
| 7635 | { |
| 7636 | memcpy(ptr, str, *size); |
| 7637 | return TRUE; |
| 7638 | } |
| 7639 | return FALSE; |
| 7640 | } |
| 7641 | else |
| 7642 | { |
| 7643 | *size = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL); |
| 7644 | if(*size <= cb) |
| 7645 | { |
Mike McCormack | 516a577 | 2005-08-19 10:04:03 +0000 | [diff] [blame] | 7646 | WideCharToMultiByte(CP_ACP, 0, str, -1, (LPSTR)ptr, *size, NULL, NULL); |
Huw Davies | 03f36e6 | 2005-07-18 13:13:31 +0000 | [diff] [blame] | 7647 | return TRUE; |
| 7648 | } |
| 7649 | return FALSE; |
| 7650 | } |
| 7651 | } |
| 7652 | |
| 7653 | /***************************************************************************** |
| 7654 | * get_job_info_1 |
| 7655 | */ |
| 7656 | static BOOL get_job_info_1(job_t *job, JOB_INFO_1W *ji1, LPBYTE buf, DWORD cbBuf, |
| 7657 | LPDWORD pcbNeeded, BOOL unicode) |
| 7658 | { |
| 7659 | DWORD size, left = cbBuf; |
| 7660 | BOOL space = (cbBuf > 0); |
| 7661 | LPBYTE ptr = buf; |
| 7662 | |
| 7663 | *pcbNeeded = 0; |
| 7664 | |
| 7665 | if(space) |
| 7666 | { |
| 7667 | ji1->JobId = job->job_id; |
| 7668 | } |
| 7669 | |
| 7670 | string_to_buf(job->document_title, ptr, left, &size, unicode); |
| 7671 | if(space && size <= left) |
| 7672 | { |
| 7673 | ji1->pDocument = (LPWSTR)ptr; |
| 7674 | ptr += size; |
| 7675 | left -= size; |
| 7676 | } |
| 7677 | else |
| 7678 | space = FALSE; |
| 7679 | *pcbNeeded += size; |
| 7680 | |
| 7681 | return space; |
| 7682 | } |
| 7683 | |
| 7684 | /***************************************************************************** |
| 7685 | * get_job_info_2 |
| 7686 | */ |
| 7687 | static BOOL get_job_info_2(job_t *job, JOB_INFO_2W *ji2, LPBYTE buf, DWORD cbBuf, |
| 7688 | LPDWORD pcbNeeded, BOOL unicode) |
| 7689 | { |
| 7690 | DWORD size, left = cbBuf; |
| 7691 | BOOL space = (cbBuf > 0); |
| 7692 | LPBYTE ptr = buf; |
| 7693 | |
| 7694 | *pcbNeeded = 0; |
| 7695 | |
| 7696 | if(space) |
| 7697 | { |
| 7698 | ji2->JobId = job->job_id; |
| 7699 | } |
| 7700 | |
| 7701 | string_to_buf(job->document_title, ptr, left, &size, unicode); |
| 7702 | if(space && size <= left) |
| 7703 | { |
| 7704 | ji2->pDocument = (LPWSTR)ptr; |
| 7705 | ptr += size; |
| 7706 | left -= size; |
| 7707 | } |
| 7708 | else |
| 7709 | space = FALSE; |
| 7710 | *pcbNeeded += size; |
| 7711 | |
| 7712 | return space; |
| 7713 | } |
| 7714 | |
| 7715 | /***************************************************************************** |
| 7716 | * get_job_info |
| 7717 | */ |
| 7718 | static BOOL get_job_info(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, |
| 7719 | DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode) |
| 7720 | { |
| 7721 | BOOL ret = FALSE; |
| 7722 | DWORD needed = 0, size; |
| 7723 | job_t *job; |
| 7724 | LPBYTE ptr = pJob; |
| 7725 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 7726 | TRACE("%p %d %d %p %d %p\n", hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded); |
Huw Davies | 03f36e6 | 2005-07-18 13:13:31 +0000 | [diff] [blame] | 7727 | |
| 7728 | EnterCriticalSection(&printer_handles_cs); |
| 7729 | job = get_job(hPrinter, JobId); |
| 7730 | if(!job) |
| 7731 | goto end; |
| 7732 | |
| 7733 | switch(Level) |
| 7734 | { |
| 7735 | case 1: |
| 7736 | size = sizeof(JOB_INFO_1W); |
| 7737 | if(cbBuf >= size) |
| 7738 | { |
| 7739 | cbBuf -= size; |
| 7740 | ptr += size; |
| 7741 | memset(pJob, 0, size); |
| 7742 | } |
| 7743 | else |
| 7744 | cbBuf = 0; |
| 7745 | ret = get_job_info_1(job, (JOB_INFO_1W *)pJob, ptr, cbBuf, &needed, unicode); |
| 7746 | needed += size; |
| 7747 | break; |
| 7748 | |
| 7749 | case 2: |
| 7750 | size = sizeof(JOB_INFO_2W); |
| 7751 | if(cbBuf >= size) |
| 7752 | { |
| 7753 | cbBuf -= size; |
| 7754 | ptr += size; |
| 7755 | memset(pJob, 0, size); |
| 7756 | } |
| 7757 | else |
| 7758 | cbBuf = 0; |
| 7759 | ret = get_job_info_2(job, (JOB_INFO_2W *)pJob, ptr, cbBuf, &needed, unicode); |
| 7760 | needed += size; |
| 7761 | break; |
| 7762 | |
| 7763 | case 3: |
| 7764 | size = sizeof(JOB_INFO_3); |
| 7765 | if(cbBuf >= size) |
| 7766 | { |
| 7767 | cbBuf -= size; |
| 7768 | memset(pJob, 0, size); |
| 7769 | ret = TRUE; |
| 7770 | } |
| 7771 | else |
| 7772 | cbBuf = 0; |
| 7773 | needed = size; |
| 7774 | break; |
| 7775 | |
| 7776 | default: |
| 7777 | SetLastError(ERROR_INVALID_LEVEL); |
| 7778 | goto end; |
| 7779 | } |
| 7780 | if(pcbNeeded) |
| 7781 | *pcbNeeded = needed; |
| 7782 | end: |
| 7783 | LeaveCriticalSection(&printer_handles_cs); |
| 7784 | return ret; |
| 7785 | } |
| 7786 | |
| 7787 | /***************************************************************************** |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7788 | * GetJobA [WINSPOOL.@] |
| 7789 | * |
| 7790 | */ |
| 7791 | BOOL WINAPI GetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, |
Huw Davies | 03f36e6 | 2005-07-18 13:13:31 +0000 | [diff] [blame] | 7792 | DWORD cbBuf, LPDWORD pcbNeeded) |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7793 | { |
Huw Davies | 03f36e6 | 2005-07-18 13:13:31 +0000 | [diff] [blame] | 7794 | return get_job_info(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded, FALSE); |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7795 | } |
| 7796 | |
| 7797 | /***************************************************************************** |
| 7798 | * GetJobW [WINSPOOL.@] |
| 7799 | * |
| 7800 | */ |
| 7801 | BOOL WINAPI GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, |
Huw Davies | 03f36e6 | 2005-07-18 13:13:31 +0000 | [diff] [blame] | 7802 | DWORD cbBuf, LPDWORD pcbNeeded) |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7803 | { |
Huw Davies | 03f36e6 | 2005-07-18 13:13:31 +0000 | [diff] [blame] | 7804 | return get_job_info(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded, TRUE); |
Hans Leidekker | 8facd46 | 2005-01-03 20:24:39 +0000 | [diff] [blame] | 7805 | } |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 7806 | |
| 7807 | /***************************************************************************** |
Huw Davies | c108d80 | 2005-07-10 17:39:01 +0000 | [diff] [blame] | 7808 | * schedule_lpr |
| 7809 | */ |
| 7810 | static BOOL schedule_lpr(LPCWSTR printer_name, LPCWSTR filename) |
| 7811 | { |
| 7812 | char *unixname, *queue, *cmd; |
| 7813 | char fmt[] = "lpr -P%s %s"; |
| 7814 | DWORD len; |
| 7815 | |
| 7816 | if(!(unixname = wine_get_unix_file_name(filename))) |
| 7817 | return FALSE; |
| 7818 | |
| 7819 | len = WideCharToMultiByte(CP_ACP, 0, printer_name, -1, NULL, 0, NULL, NULL); |
| 7820 | queue = HeapAlloc(GetProcessHeap(), 0, len); |
| 7821 | WideCharToMultiByte(CP_ACP, 0, printer_name, -1, queue, len, NULL, NULL); |
| 7822 | |
| 7823 | cmd = HeapAlloc(GetProcessHeap(), 0, strlen(unixname) + len + sizeof(fmt) - 5); |
| 7824 | sprintf(cmd, fmt, queue, unixname); |
| 7825 | |
| 7826 | TRACE("printing with: %s\n", cmd); |
| 7827 | system(cmd); |
| 7828 | |
| 7829 | HeapFree(GetProcessHeap(), 0, cmd); |
| 7830 | HeapFree(GetProcessHeap(), 0, queue); |
| 7831 | HeapFree(GetProcessHeap(), 0, unixname); |
| 7832 | return TRUE; |
| 7833 | } |
| 7834 | |
| 7835 | /***************************************************************************** |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 7836 | * schedule_cups |
| 7837 | */ |
Huw Davies | 183fcb5 | 2005-07-15 09:55:23 +0000 | [diff] [blame] | 7838 | static BOOL schedule_cups(LPCWSTR printer_name, LPCWSTR filename, LPCWSTR document_title) |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 7839 | { |
Alexandre Julliard | 702d355 | 2007-07-02 17:30:44 +0200 | [diff] [blame] | 7840 | #ifdef SONAME_LIBCUPS |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 7841 | if(pcupsPrintFile) |
| 7842 | { |
Huw Davies | 183fcb5 | 2005-07-15 09:55:23 +0000 | [diff] [blame] | 7843 | char *unixname, *queue, *doc_titleA; |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 7844 | DWORD len; |
| 7845 | BOOL ret; |
| 7846 | |
| 7847 | if(!(unixname = wine_get_unix_file_name(filename))) |
| 7848 | return FALSE; |
| 7849 | |
| 7850 | len = WideCharToMultiByte(CP_ACP, 0, printer_name, -1, NULL, 0, NULL, NULL); |
| 7851 | queue = HeapAlloc(GetProcessHeap(), 0, len); |
| 7852 | WideCharToMultiByte(CP_ACP, 0, printer_name, -1, queue, len, NULL, NULL); |
| 7853 | |
Huw Davies | 183fcb5 | 2005-07-15 09:55:23 +0000 | [diff] [blame] | 7854 | len = WideCharToMultiByte(CP_ACP, 0, document_title, -1, NULL, 0, NULL, NULL); |
| 7855 | doc_titleA = HeapAlloc(GetProcessHeap(), 0, len); |
| 7856 | WideCharToMultiByte(CP_ACP, 0, document_title, -1, doc_titleA, len, NULL, NULL); |
| 7857 | |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 7858 | TRACE("printing via cups\n"); |
Huw Davies | 183fcb5 | 2005-07-15 09:55:23 +0000 | [diff] [blame] | 7859 | ret = pcupsPrintFile(queue, unixname, doc_titleA, 0, NULL); |
| 7860 | HeapFree(GetProcessHeap(), 0, doc_titleA); |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 7861 | HeapFree(GetProcessHeap(), 0, queue); |
| 7862 | HeapFree(GetProcessHeap(), 0, unixname); |
| 7863 | return ret; |
| 7864 | } |
| 7865 | else |
| 7866 | #endif |
| 7867 | { |
| 7868 | return schedule_lpr(printer_name, filename); |
| 7869 | } |
| 7870 | } |
| 7871 | |
Huw Davies | e502d4d | 2005-07-12 17:01:44 +0000 | [diff] [blame] | 7872 | INT_PTR CALLBACK file_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) |
| 7873 | { |
| 7874 | LPWSTR filename; |
| 7875 | |
| 7876 | switch(msg) |
| 7877 | { |
| 7878 | case WM_INITDIALOG: |
| 7879 | SetWindowLongPtrW(hwnd, DWLP_USER, lparam); |
| 7880 | return TRUE; |
| 7881 | |
| 7882 | case WM_COMMAND: |
| 7883 | if(HIWORD(wparam) == BN_CLICKED) |
| 7884 | { |
| 7885 | if(LOWORD(wparam) == IDOK) |
| 7886 | { |
| 7887 | HANDLE hf; |
Huw Davies | 3b77de9 | 2005-07-22 18:28:12 +0000 | [diff] [blame] | 7888 | DWORD len = SendDlgItemMessageW(hwnd, EDITBOX, WM_GETTEXTLENGTH, 0, 0); |
Huw Davies | e502d4d | 2005-07-12 17:01:44 +0000 | [diff] [blame] | 7889 | LPWSTR *output; |
| 7890 | |
| 7891 | filename = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); |
| 7892 | GetDlgItemTextW(hwnd, EDITBOX, filename, len + 1); |
Huw Davies | 3b77de9 | 2005-07-22 18:28:12 +0000 | [diff] [blame] | 7893 | |
Huw Davies | e502d4d | 2005-07-12 17:01:44 +0000 | [diff] [blame] | 7894 | if(GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES) |
| 7895 | { |
| 7896 | WCHAR caption[200], message[200]; |
| 7897 | int mb_ret; |
| 7898 | |
| 7899 | LoadStringW(WINSPOOL_hInstance, IDS_CAPTION, caption, sizeof(caption) / sizeof(WCHAR)); |
| 7900 | LoadStringW(WINSPOOL_hInstance, IDS_FILE_EXISTS, message, sizeof(message) / sizeof(WCHAR)); |
| 7901 | mb_ret = MessageBoxW(hwnd, message, caption, MB_OKCANCEL | MB_ICONEXCLAMATION); |
| 7902 | if(mb_ret == IDCANCEL) |
| 7903 | { |
| 7904 | HeapFree(GetProcessHeap(), 0, filename); |
| 7905 | return TRUE; |
| 7906 | } |
| 7907 | } |
| 7908 | hf = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
| 7909 | if(hf == INVALID_HANDLE_VALUE) |
| 7910 | { |
| 7911 | WCHAR caption[200], message[200]; |
| 7912 | |
| 7913 | LoadStringW(WINSPOOL_hInstance, IDS_CAPTION, caption, sizeof(caption) / sizeof(WCHAR)); |
| 7914 | LoadStringW(WINSPOOL_hInstance, IDS_CANNOT_OPEN, message, sizeof(message) / sizeof(WCHAR)); |
| 7915 | MessageBoxW(hwnd, message, caption, MB_OK | MB_ICONEXCLAMATION); |
| 7916 | HeapFree(GetProcessHeap(), 0, filename); |
| 7917 | return TRUE; |
| 7918 | } |
| 7919 | CloseHandle(hf); |
| 7920 | DeleteFileW(filename); |
| 7921 | output = (LPWSTR *)GetWindowLongPtrW(hwnd, DWLP_USER); |
| 7922 | *output = filename; |
| 7923 | EndDialog(hwnd, IDOK); |
| 7924 | return TRUE; |
| 7925 | } |
| 7926 | if(LOWORD(wparam) == IDCANCEL) |
| 7927 | { |
| 7928 | EndDialog(hwnd, IDCANCEL); |
| 7929 | return TRUE; |
| 7930 | } |
| 7931 | } |
| 7932 | return FALSE; |
| 7933 | } |
| 7934 | return FALSE; |
| 7935 | } |
| 7936 | |
| 7937 | /***************************************************************************** |
Huw Davies | 3b77de9 | 2005-07-22 18:28:12 +0000 | [diff] [blame] | 7938 | * get_filename |
| 7939 | */ |
| 7940 | static BOOL get_filename(LPWSTR *filename) |
| 7941 | { |
| 7942 | return DialogBoxParamW(WINSPOOL_hInstance, MAKEINTRESOURCEW(FILENAME_DIALOG), GetForegroundWindow(), |
| 7943 | file_dlg_proc, (LPARAM)filename) == IDOK; |
| 7944 | } |
| 7945 | |
| 7946 | /***************************************************************************** |
Huw Davies | e502d4d | 2005-07-12 17:01:44 +0000 | [diff] [blame] | 7947 | * schedule_file |
| 7948 | */ |
| 7949 | static BOOL schedule_file(LPCWSTR filename) |
| 7950 | { |
| 7951 | LPWSTR output = NULL; |
| 7952 | |
Huw Davies | 3b77de9 | 2005-07-22 18:28:12 +0000 | [diff] [blame] | 7953 | if(get_filename(&output)) |
Huw Davies | e502d4d | 2005-07-12 17:01:44 +0000 | [diff] [blame] | 7954 | { |
| 7955 | TRACE("copy to %s\n", debugstr_w(output)); |
| 7956 | CopyFileW(filename, output, FALSE); |
| 7957 | HeapFree(GetProcessHeap(), 0, output); |
| 7958 | return TRUE; |
| 7959 | } |
| 7960 | return FALSE; |
| 7961 | } |
Huw Davies | 0a4681f | 2005-07-20 17:48:53 +0000 | [diff] [blame] | 7962 | |
| 7963 | /***************************************************************************** |
| 7964 | * schedule_pipe |
| 7965 | */ |
| 7966 | static BOOL schedule_pipe(LPCWSTR cmd, LPCWSTR filename) |
| 7967 | { |
| 7968 | #ifdef HAVE_FORK |
| 7969 | char *unixname, *cmdA; |
| 7970 | DWORD len; |
| 7971 | int fds[2] = {-1, -1}, file_fd = -1, no_read; |
| 7972 | BOOL ret = FALSE; |
| 7973 | char buf[1024]; |
| 7974 | |
| 7975 | if(!(unixname = wine_get_unix_file_name(filename))) |
| 7976 | return FALSE; |
| 7977 | |
| 7978 | len = WideCharToMultiByte(CP_ACP, 0, cmd, -1, NULL, 0, NULL, NULL); |
| 7979 | cmdA = HeapAlloc(GetProcessHeap(), 0, len); |
| 7980 | WideCharToMultiByte(CP_ACP, 0, cmd, -1, cmdA, len, NULL, NULL); |
| 7981 | |
| 7982 | TRACE("printing with: %s\n", cmdA); |
| 7983 | |
| 7984 | if((file_fd = open(unixname, O_RDONLY)) == -1) |
| 7985 | goto end; |
| 7986 | |
| 7987 | if (pipe(fds)) |
| 7988 | { |
| 7989 | ERR("pipe() failed!\n"); |
| 7990 | goto end; |
| 7991 | } |
| 7992 | |
| 7993 | if (fork() == 0) |
| 7994 | { |
| 7995 | close(0); |
| 7996 | dup2(fds[0], 0); |
| 7997 | close(fds[1]); |
| 7998 | |
| 7999 | /* reset signals that we previously set to SIG_IGN */ |
| 8000 | signal(SIGPIPE, SIG_DFL); |
| 8001 | signal(SIGCHLD, SIG_DFL); |
| 8002 | |
Ken Thomases | 1f42096 | 2007-02-28 14:04:54 -0600 | [diff] [blame] | 8003 | execl("/bin/sh", "/bin/sh", "-c", cmdA, (char*)0); |
| 8004 | _exit(1); |
Huw Davies | 0a4681f | 2005-07-20 17:48:53 +0000 | [diff] [blame] | 8005 | } |
| 8006 | |
Detlef Riekenberg | 50b32da | 2006-04-08 19:17:06 +0200 | [diff] [blame] | 8007 | while((no_read = read(file_fd, buf, sizeof(buf))) > 0) |
Huw Davies | 0a4681f | 2005-07-20 17:48:53 +0000 | [diff] [blame] | 8008 | write(fds[1], buf, no_read); |
| 8009 | |
| 8010 | ret = TRUE; |
| 8011 | |
| 8012 | end: |
| 8013 | if(file_fd != -1) close(file_fd); |
| 8014 | if(fds[0] != -1) close(fds[0]); |
| 8015 | if(fds[1] != -1) close(fds[1]); |
| 8016 | |
| 8017 | HeapFree(GetProcessHeap(), 0, cmdA); |
| 8018 | HeapFree(GetProcessHeap(), 0, unixname); |
| 8019 | return ret; |
| 8020 | #else |
| 8021 | return FALSE; |
| 8022 | #endif |
| 8023 | } |
| 8024 | |
| 8025 | /***************************************************************************** |
| 8026 | * schedule_unixfile |
| 8027 | */ |
| 8028 | static BOOL schedule_unixfile(LPCWSTR output, LPCWSTR filename) |
| 8029 | { |
| 8030 | int in_fd, out_fd, no_read; |
| 8031 | char buf[1024]; |
| 8032 | BOOL ret = FALSE; |
| 8033 | char *unixname, *outputA; |
| 8034 | DWORD len; |
| 8035 | |
| 8036 | if(!(unixname = wine_get_unix_file_name(filename))) |
| 8037 | return FALSE; |
| 8038 | |
| 8039 | len = WideCharToMultiByte(CP_ACP, 0, output, -1, NULL, 0, NULL, NULL); |
| 8040 | outputA = HeapAlloc(GetProcessHeap(), 0, len); |
| 8041 | WideCharToMultiByte(CP_ACP, 0, output, -1, outputA, len, NULL, NULL); |
| 8042 | |
| 8043 | out_fd = open(outputA, O_CREAT | O_TRUNC | O_WRONLY, 0666); |
| 8044 | in_fd = open(unixname, O_RDONLY); |
| 8045 | if(out_fd == -1 || in_fd == -1) |
| 8046 | goto end; |
| 8047 | |
Detlef Riekenberg | 50b32da | 2006-04-08 19:17:06 +0200 | [diff] [blame] | 8048 | while((no_read = read(in_fd, buf, sizeof(buf))) > 0) |
Huw Davies | 0a4681f | 2005-07-20 17:48:53 +0000 | [diff] [blame] | 8049 | write(out_fd, buf, no_read); |
| 8050 | |
| 8051 | ret = TRUE; |
| 8052 | end: |
| 8053 | if(in_fd != -1) close(in_fd); |
| 8054 | if(out_fd != -1) close(out_fd); |
| 8055 | HeapFree(GetProcessHeap(), 0, outputA); |
| 8056 | HeapFree(GetProcessHeap(), 0, unixname); |
| 8057 | return ret; |
| 8058 | } |
| 8059 | |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 8060 | /***************************************************************************** |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 8061 | * ScheduleJob [WINSPOOL.@] |
| 8062 | * |
| 8063 | */ |
| 8064 | BOOL WINAPI ScheduleJob( HANDLE hPrinter, DWORD dwJobID ) |
| 8065 | { |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 8066 | opened_printer_t *printer; |
| 8067 | BOOL ret = FALSE; |
| 8068 | struct list *cursor, *cursor2; |
| 8069 | |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 8070 | TRACE("(%p, %x)\n", hPrinter, dwJobID); |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 8071 | EnterCriticalSection(&printer_handles_cs); |
| 8072 | printer = get_opened_printer(hPrinter); |
| 8073 | if(!printer) |
| 8074 | goto end; |
| 8075 | |
Huw Davies | 48a52d0 | 2005-07-19 19:12:13 +0000 | [diff] [blame] | 8076 | LIST_FOR_EACH_SAFE(cursor, cursor2, &printer->queue->jobs) |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 8077 | { |
| 8078 | job_t *job = LIST_ENTRY(cursor, job_t, entry); |
| 8079 | HANDLE hf; |
| 8080 | |
| 8081 | if(job->job_id != dwJobID) continue; |
| 8082 | |
| 8083 | hf = CreateFileW(job->filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); |
| 8084 | if(hf != INVALID_HANDLE_VALUE) |
| 8085 | { |
Huw Davies | c108d80 | 2005-07-10 17:39:01 +0000 | [diff] [blame] | 8086 | PRINTER_INFO_5W *pi5; |
| 8087 | DWORD needed; |
Huw Davies | 0a4681f | 2005-07-20 17:48:53 +0000 | [diff] [blame] | 8088 | HKEY hkey; |
| 8089 | WCHAR output[1024]; |
| 8090 | static const WCHAR spooler_key[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\', |
| 8091 | 'P','r','i','n','t','i','n','g','\\','S','p','o','o','l','e','r',0}; |
Huw Davies | c108d80 | 2005-07-10 17:39:01 +0000 | [diff] [blame] | 8092 | |
| 8093 | GetPrinterW(hPrinter, 5, NULL, 0, &needed); |
| 8094 | pi5 = HeapAlloc(GetProcessHeap(), 0, needed); |
| 8095 | GetPrinterW(hPrinter, 5, (LPBYTE)pi5, needed, &needed); |
Hans Leidekker | 61faa6b | 2006-10-13 11:51:23 +0200 | [diff] [blame] | 8096 | TRACE("need to schedule job %d filename %s to port %s\n", job->job_id, debugstr_w(job->filename), |
Huw Davies | c108d80 | 2005-07-10 17:39:01 +0000 | [diff] [blame] | 8097 | debugstr_w(pi5->pPortName)); |
| 8098 | |
Huw Davies | 0a4681f | 2005-07-20 17:48:53 +0000 | [diff] [blame] | 8099 | output[0] = 0; |
| 8100 | |
| 8101 | /* @@ Wine registry key: HKCU\Software\Wine\Printing\Spooler */ |
| 8102 | if(RegOpenKeyW(HKEY_CURRENT_USER, spooler_key, &hkey) == ERROR_SUCCESS) |
| 8103 | { |
| 8104 | DWORD type, count = sizeof(output); |
| 8105 | RegQueryValueExW(hkey, pi5->pPortName, NULL, &type, (LPBYTE)output, &count); |
| 8106 | RegCloseKey(hkey); |
| 8107 | } |
| 8108 | if(output[0] == '|') |
| 8109 | { |
| 8110 | schedule_pipe(output + 1, job->filename); |
| 8111 | } |
| 8112 | else if(output[0]) |
| 8113 | { |
| 8114 | schedule_unixfile(output, job->filename); |
| 8115 | } |
| 8116 | else if(!strncmpW(pi5->pPortName, LPR_Port, strlenW(LPR_Port))) |
Huw Davies | c108d80 | 2005-07-10 17:39:01 +0000 | [diff] [blame] | 8117 | { |
| 8118 | schedule_lpr(pi5->pPortName + strlenW(LPR_Port), job->filename); |
| 8119 | } |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 8120 | else if(!strncmpW(pi5->pPortName, CUPS_Port, strlenW(CUPS_Port))) |
| 8121 | { |
Huw Davies | 183fcb5 | 2005-07-15 09:55:23 +0000 | [diff] [blame] | 8122 | schedule_cups(pi5->pPortName + strlenW(CUPS_Port), job->filename, job->document_title); |
Huw Davies | 18116de | 2005-07-11 13:21:48 +0000 | [diff] [blame] | 8123 | } |
Huw Davies | e502d4d | 2005-07-12 17:01:44 +0000 | [diff] [blame] | 8124 | else if(!strncmpW(pi5->pPortName, FILE_Port, strlenW(FILE_Port))) |
| 8125 | { |
| 8126 | schedule_file(job->filename); |
| 8127 | } |
Huw Davies | c108d80 | 2005-07-10 17:39:01 +0000 | [diff] [blame] | 8128 | else |
| 8129 | { |
| 8130 | FIXME("can't schedule to port %s\n", debugstr_w(pi5->pPortName)); |
| 8131 | } |
Huw Davies | c108d80 | 2005-07-10 17:39:01 +0000 | [diff] [blame] | 8132 | HeapFree(GetProcessHeap(), 0, pi5); |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 8133 | CloseHandle(hf); |
| 8134 | DeleteFileW(job->filename); |
| 8135 | } |
| 8136 | list_remove(cursor); |
Huw Davies | 1ed9bac | 2005-07-13 14:14:37 +0000 | [diff] [blame] | 8137 | HeapFree(GetProcessHeap(), 0, job->document_title); |
Huw Davies | 344090f | 2005-07-06 15:44:15 +0000 | [diff] [blame] | 8138 | HeapFree(GetProcessHeap(), 0, job->filename); |
| 8139 | HeapFree(GetProcessHeap(), 0, job); |
| 8140 | ret = TRUE; |
| 8141 | break; |
| 8142 | } |
| 8143 | end: |
| 8144 | LeaveCriticalSection(&printer_handles_cs); |
| 8145 | return ret; |
Hans Leidekker | 1e33aca | 2005-02-21 18:33:55 +0000 | [diff] [blame] | 8146 | } |
Huw Davies | 3b77de9 | 2005-07-22 18:28:12 +0000 | [diff] [blame] | 8147 | |
| 8148 | /***************************************************************************** |
| 8149 | * StartDocDlgA [WINSPOOL.@] |
| 8150 | */ |
Hans Leidekker | ab85b65 | 2006-10-06 14:25:54 +0200 | [diff] [blame] | 8151 | LPSTR WINAPI StartDocDlgA( HANDLE hPrinter, DOCINFOA *doc ) |
Huw Davies | 3b77de9 | 2005-07-22 18:28:12 +0000 | [diff] [blame] | 8152 | { |
| 8153 | UNICODE_STRING usBuffer; |
| 8154 | DOCINFOW docW; |
| 8155 | LPWSTR retW; |
Hans Leidekker | ab85b65 | 2006-10-06 14:25:54 +0200 | [diff] [blame] | 8156 | LPWSTR docnameW = NULL, outputW = NULL, datatypeW = NULL; |
Huw Davies | 3b77de9 | 2005-07-22 18:28:12 +0000 | [diff] [blame] | 8157 | LPSTR ret = NULL; |
| 8158 | |
| 8159 | docW.cbSize = sizeof(docW); |
Hans Leidekker | ab85b65 | 2006-10-06 14:25:54 +0200 | [diff] [blame] | 8160 | if (doc->lpszDocName) |
| 8161 | { |
| 8162 | docnameW = asciitounicode(&usBuffer, doc->lpszDocName); |
| 8163 | if (!(docW.lpszDocName = docnameW)) return NULL; |
| 8164 | } |
| 8165 | if (doc->lpszOutput) |
| 8166 | { |
| 8167 | outputW = asciitounicode(&usBuffer, doc->lpszOutput); |
| 8168 | if (!(docW.lpszOutput = outputW)) return NULL; |
| 8169 | } |
| 8170 | if (doc->lpszDatatype) |
| 8171 | { |
| 8172 | datatypeW = asciitounicode(&usBuffer, doc->lpszDatatype); |
| 8173 | if (!(docW.lpszDatatype = datatypeW)) return NULL; |
| 8174 | } |
Huw Davies | 3b77de9 | 2005-07-22 18:28:12 +0000 | [diff] [blame] | 8175 | docW.fwType = doc->fwType; |
| 8176 | |
| 8177 | retW = StartDocDlgW(hPrinter, &docW); |
| 8178 | |
| 8179 | if(retW) |
| 8180 | { |
| 8181 | DWORD len = WideCharToMultiByte(CP_ACP, 0, retW, -1, NULL, 0, NULL, NULL); |
| 8182 | ret = HeapAlloc(GetProcessHeap(), 0, len); |
| 8183 | WideCharToMultiByte(CP_ACP, 0, retW, -1, ret, len, NULL, NULL); |
| 8184 | HeapFree(GetProcessHeap(), 0, retW); |
| 8185 | } |
| 8186 | |
Hans Leidekker | ab85b65 | 2006-10-06 14:25:54 +0200 | [diff] [blame] | 8187 | HeapFree(GetProcessHeap(), 0, datatypeW); |
| 8188 | HeapFree(GetProcessHeap(), 0, outputW); |
| 8189 | HeapFree(GetProcessHeap(), 0, docnameW); |
Huw Davies | 3b77de9 | 2005-07-22 18:28:12 +0000 | [diff] [blame] | 8190 | |
| 8191 | return ret; |
| 8192 | } |
| 8193 | |
| 8194 | /***************************************************************************** |
| 8195 | * StartDocDlgW [WINSPOOL.@] |
| 8196 | * |
| 8197 | * Undocumented: Apparently used by gdi32:StartDocW() to popup the file dialog |
| 8198 | * when lpszOutput is "FILE:" or if lpszOutput is NULL and the default printer |
| 8199 | * port is "FILE:". Also returns the full path if passed a relative path. |
| 8200 | * |
| 8201 | * The caller should free the returned string from the process heap. |
| 8202 | */ |
| 8203 | LPWSTR WINAPI StartDocDlgW( HANDLE hPrinter, DOCINFOW *doc ) |
| 8204 | { |
| 8205 | LPWSTR ret = NULL; |
| 8206 | DWORD len, attr; |
| 8207 | |
| 8208 | if(doc->lpszOutput == NULL) /* Check whether default port is FILE: */ |
| 8209 | { |
| 8210 | PRINTER_INFO_5W *pi5; |
| 8211 | GetPrinterW(hPrinter, 5, NULL, 0, &len); |
| 8212 | if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) |
| 8213 | return NULL; |
| 8214 | pi5 = HeapAlloc(GetProcessHeap(), 0, len); |
| 8215 | GetPrinterW(hPrinter, 5, (LPBYTE)pi5, len, &len); |
| 8216 | if(!pi5->pPortName || strcmpW(pi5->pPortName, FILE_Port)) |
| 8217 | { |
| 8218 | HeapFree(GetProcessHeap(), 0, pi5); |
| 8219 | return NULL; |
| 8220 | } |
| 8221 | HeapFree(GetProcessHeap(), 0, pi5); |
| 8222 | } |
| 8223 | |
| 8224 | if(doc->lpszOutput == NULL || !strcmpW(doc->lpszOutput, FILE_Port)) |
| 8225 | { |
| 8226 | LPWSTR name; |
James Hawkins | 6840693 | 2007-01-11 03:19:58 -0600 | [diff] [blame] | 8227 | |
| 8228 | if (get_filename(&name)) |
Huw Davies | 3b77de9 | 2005-07-22 18:28:12 +0000 | [diff] [blame] | 8229 | { |
| 8230 | if(!(len = GetFullPathNameW(name, 0, NULL, NULL))) |
| 8231 | { |
| 8232 | HeapFree(GetProcessHeap(), 0, name); |
| 8233 | return NULL; |
| 8234 | } |
| 8235 | ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 8236 | GetFullPathNameW(name, len, ret, NULL); |
| 8237 | HeapFree(GetProcessHeap(), 0, name); |
| 8238 | } |
| 8239 | return ret; |
| 8240 | } |
| 8241 | |
| 8242 | if(!(len = GetFullPathNameW(doc->lpszOutput, 0, NULL, NULL))) |
| 8243 | return NULL; |
| 8244 | |
| 8245 | ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); |
| 8246 | GetFullPathNameW(doc->lpszOutput, len, ret, NULL); |
| 8247 | |
| 8248 | attr = GetFileAttributesW(ret); |
| 8249 | if(attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY)) |
| 8250 | { |
| 8251 | HeapFree(GetProcessHeap(), 0, ret); |
| 8252 | ret = NULL; |
| 8253 | } |
| 8254 | return ret; |
| 8255 | } |