Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenprovider.c
Go to the documentation of this file.
00001 /* 00002 * Implementation of the Local Printprovider 00003 * 00004 * Copyright 2006-2009 Detlef Riekenberg 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <stdarg.h> 00022 00023 #define COBJMACROS 00024 #define NONAMELESSUNION 00025 00026 #include "windef.h" 00027 #include "winbase.h" 00028 #include "wingdi.h" 00029 #include "winreg.h" 00030 #include "winspool.h" 00031 #include "winuser.h" 00032 #include "ddk/winddiui.h" 00033 #include "ddk/winsplp.h" 00034 00035 #include "wine/list.h" 00036 #include "wine/debug.h" 00037 #include "wine/unicode.h" 00038 #include "localspl_private.h" 00039 00040 WINE_DEFAULT_DEBUG_CHANNEL(localspl); 00041 00042 /* ############################### */ 00043 00044 static CRITICAL_SECTION monitor_handles_cs; 00045 static CRITICAL_SECTION_DEBUG monitor_handles_cs_debug = 00046 { 00047 0, 0, &monitor_handles_cs, 00048 { &monitor_handles_cs_debug.ProcessLocksList, &monitor_handles_cs_debug.ProcessLocksList }, 00049 0, 0, { (DWORD_PTR)(__FILE__ ": monitor_handles_cs") } 00050 }; 00051 static CRITICAL_SECTION monitor_handles_cs = { &monitor_handles_cs_debug, -1, 0, 0, 0, 0 }; 00052 00053 /* ############################### */ 00054 00055 typedef struct { 00056 WCHAR src[MAX_PATH+MAX_PATH]; 00057 WCHAR dst[MAX_PATH+MAX_PATH]; 00058 DWORD srclen; 00059 DWORD dstlen; 00060 DWORD copyflags; 00061 BOOL lazy; 00062 } apd_data_t; 00063 00064 typedef struct { 00065 struct list entry; 00066 LPWSTR name; 00067 LPWSTR dllname; 00068 PMONITORUI monitorUI; 00069 LPMONITOR monitor; 00070 HMODULE hdll; 00071 DWORD refcount; 00072 DWORD dwMonitorSize; 00073 } monitor_t; 00074 00075 typedef struct { 00076 LPCWSTR envname; 00077 LPCWSTR subdir; 00078 DWORD driverversion; 00079 LPCWSTR versionregpath; 00080 LPCWSTR versionsubdir; 00081 } printenv_t; 00082 00083 typedef struct { 00084 LPWSTR name; 00085 LPWSTR printername; 00086 monitor_t * pm; 00087 HANDLE hXcv; 00088 } printer_t; 00089 00090 /* ############################### */ 00091 00092 static struct list monitor_handles = LIST_INIT( monitor_handles ); 00093 static monitor_t * pm_localport; 00094 00095 static const PRINTPROVIDOR * pprovider = NULL; 00096 00097 static const WCHAR backslashW[] = {'\\',0}; 00098 static const WCHAR bs_ports_bsW[] = {'\\','P','o','r','t','s','\\',0}; 00099 static const WCHAR configuration_fileW[] = {'C','o','n','f','i','g','u','r','a','t','i','o','n',' ','F','i','l','e',0}; 00100 static const WCHAR datatypeW[] = {'D','a','t','a','t','y','p','e',0}; 00101 static const WCHAR data_fileW[] = {'D','a','t','a',' ','F','i','l','e',0}; 00102 static const WCHAR default_devmodeW[] = {'D','e','f','a','u','l','t',' ','D','e','v','M','o','d','e',0}; 00103 static const WCHAR dependent_filesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0}; 00104 static const WCHAR descriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0}; 00105 static const WCHAR driverW[] = {'D','r','i','v','e','r',0}; 00106 static const WCHAR emptyW[] = {0}; 00107 static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\', 00108 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 00109 'c','o','n','t','r','o','l','\\', 00110 'P','r','i','n','t','\\', 00111 'E','n','v','i','r','o','n','m','e','n','t','s','\\', 00112 '%','s','\\','D','r','i','v','e','r','s','%','s',0 }; 00113 static const WCHAR fmt_printprocessorsW[] = { 'S','y','s','t','e','m','\\', 00114 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 00115 'C','o','n','t','r','o','l','\\', 00116 'P','r','i','n','t','\\', 00117 'E','n','v','i','r','o','n','m','e','n','t','s','\\','%','s','\\', 00118 'P','r','i','n','t',' ','P','r','o','c','e','s','s','o','r','s',0 }; 00119 static const WCHAR hardwareidW[] = {'H','a','r','d','w','a','r','e','I','D',0}; 00120 static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0}; 00121 static const WCHAR ia64_envnameW[] = {'W','i','n','d','o','w','s',' ','I','A','6','4',0}; 00122 static const WCHAR ia64_subdirW[] = {'i','a','6','4',0}; 00123 static const WCHAR localportW[] = {'L','o','c','a','l',' ','P','o','r','t',0}; 00124 static const WCHAR locationW[] = {'L','o','c','a','t','i','o','n',0}; 00125 static const WCHAR manufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; 00126 static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0}; 00127 static const WCHAR monitorsW[] = {'S','y','s','t','e','m','\\', 00128 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 00129 'C','o','n','t','r','o','l','\\', 00130 'P','r','i','n','t','\\', 00131 'M','o','n','i','t','o','r','s','\\',0}; 00132 static const WCHAR monitorUIW[] = {'M','o','n','i','t','o','r','U','I',0}; 00133 static const WCHAR nameW[] = {'N','a','m','e',0}; 00134 static const WCHAR oem_urlW[] = {'O','E','M',' ','U','r','l',0}; 00135 static const WCHAR parametersW[] = {'P','a','r','a','m','e','t','e','r','s',0}; 00136 static const WCHAR portW[] = {'P','o','r','t',0}; 00137 static const WCHAR previous_namesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0}; 00138 static const WCHAR printersW[] = {'S','y','s','t','e','m','\\', 00139 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 00140 'C','o','n','t','r','o','l','\\', 00141 'P','r','i','n','t','\\', 00142 'P','r','i','n','t','e','r','s',0}; 00143 static const WCHAR spooldriversW[] = {'\\','s','p','o','o','l','\\','d','r','i','v','e','r','s','\\',0}; 00144 static const WCHAR spoolprtprocsW[] = {'\\','s','p','o','o','l','\\','p','r','t','p','r','o','c','s','\\',0}; 00145 static const WCHAR version0_regpathW[] = {'\\','V','e','r','s','i','o','n','-','0',0}; 00146 static const WCHAR version0_subdirW[] = {'\\','0',0}; 00147 static const WCHAR version3_regpathW[] = {'\\','V','e','r','s','i','o','n','-','3',0}; 00148 static const WCHAR version3_subdirW[] = {'\\','3',0}; 00149 static const WCHAR versionW[] = {'V','e','r','s','i','o','n',0}; 00150 static const WCHAR win40_envnameW[] = {'W','i','n','d','o','w','s',' ','4','.','0',0}; 00151 static const WCHAR win40_subdirW[] = {'w','i','n','4','0',0}; 00152 static const WCHAR winnt_cv_portsW[] = {'S','o','f','t','w','a','r','e','\\', 00153 'M','i','c','r','o','s','o','f','t','\\', 00154 'W','i','n','d','o','w','s',' ','N','T','\\', 00155 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 00156 'P','o','r','t','s',0}; 00157 static const WCHAR winprintW[] = {'w','i','n','p','r','i','n','t',0}; 00158 static const WCHAR x64_envnameW[] = {'W','i','n','d','o','w','s',' ','x','6','4',0}; 00159 static const WCHAR x64_subdirW[] = {'x','6','4',0}; 00160 static const WCHAR x86_envnameW[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0}; 00161 static const WCHAR x86_subdirW[] = {'w','3','2','x','8','6',0}; 00162 static const WCHAR XcvMonitorW[] = {',','X','c','v','M','o','n','i','t','o','r',' ',0}; 00163 static const WCHAR XcvPortW[] = {',','X','c','v','P','o','r','t',' ',0}; 00164 00165 00166 static const printenv_t env_ia64 = {ia64_envnameW, ia64_subdirW, 3, 00167 version3_regpathW, version3_subdirW}; 00168 00169 static const printenv_t env_x86 = {x86_envnameW, x86_subdirW, 3, 00170 version3_regpathW, version3_subdirW}; 00171 00172 static const printenv_t env_x64 = {x64_envnameW, x64_subdirW, 3, 00173 version3_regpathW, version3_subdirW}; 00174 00175 static const printenv_t env_win40 = {win40_envnameW, win40_subdirW, 0, 00176 version0_regpathW, version0_subdirW}; 00177 00178 static const printenv_t * const all_printenv[] = {&env_x86, &env_x64, &env_ia64, &env_win40}; 00179 00180 00181 static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_2W), 00182 sizeof(DRIVER_INFO_3W), sizeof(DRIVER_INFO_4W), 00183 sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W), 00184 0, sizeof(DRIVER_INFO_8W)}; 00185 00186 00187 /****************************************************************** 00188 * strdupW [internal] 00189 * 00190 * create a copy of a unicode-string 00191 * 00192 */ 00193 static LPWSTR strdupW(LPCWSTR p) 00194 { 00195 LPWSTR ret; 00196 DWORD len; 00197 00198 if(!p) return NULL; 00199 len = (lstrlenW(p) + 1) * sizeof(WCHAR); 00200 ret = heap_alloc(len); 00201 if (ret) memcpy(ret, p, len); 00202 return ret; 00203 } 00204 00205 /****************************************************************** 00206 * apd_copyfile [internal] 00207 * 00208 * Copy a file from the driverdirectory to the versioned directory 00209 * 00210 * RETURNS 00211 * Success: TRUE 00212 * Failure: FALSE 00213 * 00214 */ 00215 static BOOL apd_copyfile(LPWSTR filename, apd_data_t *apd) 00216 { 00217 LPWSTR ptr; 00218 LPWSTR srcname; 00219 DWORD res; 00220 00221 apd->src[apd->srclen] = '\0'; 00222 apd->dst[apd->dstlen] = '\0'; 00223 00224 if (!filename || !filename[0]) { 00225 /* nothing to copy */ 00226 return TRUE; 00227 } 00228 00229 ptr = strrchrW(filename, '\\'); 00230 if (ptr) { 00231 ptr++; 00232 } 00233 else 00234 { 00235 ptr = filename; 00236 } 00237 00238 if (apd->copyflags & APD_COPY_FROM_DIRECTORY) { 00239 /* we have an absolute Path */ 00240 srcname = filename; 00241 } 00242 else 00243 { 00244 srcname = apd->src; 00245 lstrcatW(srcname, ptr); 00246 } 00247 lstrcatW(apd->dst, ptr); 00248 00249 TRACE("%s => %s\n", debugstr_w(filename), debugstr_w(apd->dst)); 00250 00251 /* FIXME: handle APD_COPY_NEW_FILES */ 00252 res = CopyFileW(srcname, apd->dst, FALSE); 00253 TRACE("got %u with %u\n", res, GetLastError()); 00254 00255 return (apd->lazy) ? TRUE : res; 00256 } 00257 00258 /****************************************************************** 00259 * copy_servername_from_name (internal) 00260 * 00261 * for an external server, the serverpart from the name is copied. 00262 * 00263 * RETURNS 00264 * the length (in WCHAR) of the serverpart (0 for the local computer) 00265 * (-length), when the name is to long 00266 * 00267 */ 00268 static LONG copy_servername_from_name(LPCWSTR name, LPWSTR target) 00269 { 00270 LPCWSTR server; 00271 LPWSTR ptr; 00272 WCHAR buffer[MAX_COMPUTERNAME_LENGTH +1]; 00273 DWORD len; 00274 DWORD serverlen; 00275 00276 if (target) *target = '\0'; 00277 00278 if (name == NULL) return 0; 00279 if ((name[0] != '\\') || (name[1] != '\\')) return 0; 00280 00281 server = &name[2]; 00282 /* skip over both backslash, find separator '\' */ 00283 ptr = strchrW(server, '\\'); 00284 serverlen = (ptr) ? ptr - server : lstrlenW(server); 00285 00286 /* servername is empty */ 00287 if (serverlen == 0) return 0; 00288 00289 TRACE("found %s\n", debugstr_wn(server, serverlen)); 00290 00291 if (serverlen > MAX_COMPUTERNAME_LENGTH) return -serverlen; 00292 00293 if (target) { 00294 memcpy(target, server, serverlen * sizeof(WCHAR)); 00295 target[serverlen] = '\0'; 00296 } 00297 00298 len = sizeof(buffer) / sizeof(buffer[0]); 00299 if (GetComputerNameW(buffer, &len)) { 00300 if ((serverlen == len) && (strncmpiW(server, buffer, len) == 0)) { 00301 /* The requested Servername is our computername */ 00302 return 0; 00303 } 00304 } 00305 return serverlen; 00306 } 00307 00308 /****************************************************************** 00309 * get_basename_from_name (internal) 00310 * 00311 * skip over the serverpart from the full name 00312 * 00313 */ 00314 static LPCWSTR get_basename_from_name(LPCWSTR name) 00315 { 00316 if (name == NULL) return NULL; 00317 if ((name[0] == '\\') && (name[1] == '\\')) { 00318 /* skip over the servername and search for the following '\' */ 00319 name = strchrW(&name[2], '\\'); 00320 if ((name) && (name[1])) { 00321 /* found a separator ('\') followed by a name: 00322 skip over the separator and return the rest */ 00323 name++; 00324 } 00325 else 00326 { 00327 /* no basename present (we found only a servername) */ 00328 return NULL; 00329 } 00330 } 00331 return name; 00332 } 00333 00334 /****************************************************************** 00335 * monitor_unload [internal] 00336 * 00337 * release a printmonitor and unload it from memory, when needed 00338 * 00339 */ 00340 static void monitor_unload(monitor_t * pm) 00341 { 00342 if (pm == NULL) return; 00343 TRACE("%p (refcount: %d) %s\n", pm, pm->refcount, debugstr_w(pm->name)); 00344 00345 EnterCriticalSection(&monitor_handles_cs); 00346 00347 if (pm->refcount) pm->refcount--; 00348 00349 if (pm->refcount == 0) { 00350 list_remove(&pm->entry); 00351 FreeLibrary(pm->hdll); 00352 heap_free(pm->name); 00353 heap_free(pm->dllname); 00354 heap_free(pm); 00355 } 00356 LeaveCriticalSection(&monitor_handles_cs); 00357 } 00358 00359 /****************************************************************** 00360 * monitor_unloadall [internal] 00361 * 00362 * release all registered printmonitors and unload them from memory, when needed 00363 * 00364 */ 00365 00366 static void monitor_unloadall(void) 00367 { 00368 monitor_t * pm; 00369 monitor_t * next; 00370 00371 EnterCriticalSection(&monitor_handles_cs); 00372 /* iterate through the list, with safety against removal */ 00373 LIST_FOR_EACH_ENTRY_SAFE(pm, next, &monitor_handles, monitor_t, entry) 00374 { 00375 /* skip monitorui dlls */ 00376 if (pm->monitor) monitor_unload(pm); 00377 } 00378 LeaveCriticalSection(&monitor_handles_cs); 00379 } 00380 00381 /****************************************************************** 00382 * monitor_load [internal] 00383 * 00384 * load a printmonitor, get the dllname from the registry, when needed 00385 * initialize the monitor and dump found function-pointers 00386 * 00387 * On failure, SetLastError() is called and NULL is returned 00388 */ 00389 00390 static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname) 00391 { 00392 LPMONITOR2 (WINAPI *pInitializePrintMonitor2) (PMONITORINIT, LPHANDLE); 00393 PMONITORUI (WINAPI *pInitializePrintMonitorUI)(VOID); 00394 LPMONITOREX (WINAPI *pInitializePrintMonitor) (LPWSTR); 00395 DWORD (WINAPI *pInitializeMonitorEx)(LPWSTR, LPMONITOR); 00396 DWORD (WINAPI *pInitializeMonitor) (LPWSTR); 00397 00398 monitor_t * pm = NULL; 00399 monitor_t * cursor; 00400 LPWSTR regroot = NULL; 00401 LPWSTR driver = dllname; 00402 00403 TRACE("(%s, %s)\n", debugstr_w(name), debugstr_w(dllname)); 00404 /* Is the Monitor already loaded? */ 00405 EnterCriticalSection(&monitor_handles_cs); 00406 00407 if (name) { 00408 LIST_FOR_EACH_ENTRY(cursor, &monitor_handles, monitor_t, entry) 00409 { 00410 if (cursor->name && (lstrcmpW(name, cursor->name) == 0)) { 00411 pm = cursor; 00412 break; 00413 } 00414 } 00415 } 00416 00417 if (pm == NULL) { 00418 pm = heap_alloc_zero(sizeof(monitor_t)); 00419 if (pm == NULL) goto cleanup; 00420 list_add_tail(&monitor_handles, &pm->entry); 00421 } 00422 pm->refcount++; 00423 00424 if (pm->name == NULL) { 00425 /* Load the monitor */ 00426 LPMONITOREX pmonitorEx; 00427 DWORD len; 00428 00429 if (name) { 00430 len = lstrlenW(monitorsW) + lstrlenW(name) + 2; 00431 regroot = heap_alloc(len * sizeof(WCHAR)); 00432 } 00433 00434 if (regroot) { 00435 lstrcpyW(regroot, monitorsW); 00436 lstrcatW(regroot, name); 00437 /* Get the Driver from the Registry */ 00438 if (driver == NULL) { 00439 HKEY hroot; 00440 DWORD namesize; 00441 if (RegOpenKeyW(HKEY_LOCAL_MACHINE, regroot, &hroot) == ERROR_SUCCESS) { 00442 if (RegQueryValueExW(hroot, driverW, NULL, NULL, NULL, 00443 &namesize) == ERROR_SUCCESS) { 00444 driver = heap_alloc(namesize); 00445 RegQueryValueExW(hroot, driverW, NULL, NULL, (LPBYTE) driver, &namesize) ; 00446 } 00447 RegCloseKey(hroot); 00448 } 00449 } 00450 } 00451 00452 pm->name = strdupW(name); 00453 pm->dllname = strdupW(driver); 00454 00455 if ((name && (!regroot || !pm->name)) || !pm->dllname) { 00456 monitor_unload(pm); 00457 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00458 pm = NULL; 00459 goto cleanup; 00460 } 00461 00462 pm->hdll = LoadLibraryW(driver); 00463 TRACE("%p: LoadLibrary(%s) => %d\n", pm->hdll, debugstr_w(driver), GetLastError()); 00464 00465 if (pm->hdll == NULL) { 00466 monitor_unload(pm); 00467 SetLastError(ERROR_MOD_NOT_FOUND); 00468 pm = NULL; 00469 goto cleanup; 00470 } 00471 00472 pInitializePrintMonitor2 = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitor2"); 00473 pInitializePrintMonitorUI = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitorUI"); 00474 pInitializePrintMonitor = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitor"); 00475 pInitializeMonitorEx = (void *)GetProcAddress(pm->hdll, "InitializeMonitorEx"); 00476 pInitializeMonitor = (void *)GetProcAddress(pm->hdll, "InitializeMonitor"); 00477 00478 00479 TRACE("%p: %s,pInitializePrintMonitor2\n", pInitializePrintMonitor2, debugstr_w(driver)); 00480 TRACE("%p: %s,pInitializePrintMonitorUI\n", pInitializePrintMonitorUI, debugstr_w(driver)); 00481 TRACE("%p: %s,pInitializePrintMonitor\n", pInitializePrintMonitor, debugstr_w(driver)); 00482 TRACE("%p: %s,pInitializeMonitorEx\n", pInitializeMonitorEx, debugstr_w(driver)); 00483 TRACE("%p: %s,pInitializeMonitor\n", pInitializeMonitor, debugstr_w(driver)); 00484 00485 if (pInitializePrintMonitorUI != NULL) { 00486 pm->monitorUI = pInitializePrintMonitorUI(); 00487 TRACE("%p: MONITORUI from %s,InitializePrintMonitorUI()\n", pm->monitorUI, debugstr_w(driver)); 00488 if (pm->monitorUI) { 00489 TRACE("0x%08x: dwMonitorSize (%d)\n", 00490 pm->monitorUI->dwMonitorUISize, pm->monitorUI->dwMonitorUISize); 00491 00492 } 00493 } 00494 00495 if (pInitializePrintMonitor && regroot) { 00496 pmonitorEx = pInitializePrintMonitor(regroot); 00497 TRACE("%p: LPMONITOREX from %s,InitializePrintMonitor(%s)\n", 00498 pmonitorEx, debugstr_w(driver), debugstr_w(regroot)); 00499 00500 if (pmonitorEx) { 00501 pm->dwMonitorSize = pmonitorEx->dwMonitorSize; 00502 pm->monitor = &(pmonitorEx->Monitor); 00503 } 00504 } 00505 00506 if (pm->monitor) { 00507 TRACE("0x%08x: dwMonitorSize (%d)\n", pm->dwMonitorSize, pm->dwMonitorSize); 00508 00509 } 00510 00511 if (!pm->monitor && regroot) { 00512 if (pInitializePrintMonitor2 != NULL) { 00513 FIXME("%s,InitializePrintMonitor2 not implemented\n", debugstr_w(driver)); 00514 } 00515 if (pInitializeMonitorEx != NULL) { 00516 FIXME("%s,InitializeMonitorEx not implemented\n", debugstr_w(driver)); 00517 } 00518 if (pInitializeMonitor != NULL) { 00519 FIXME("%s,InitializeMonitor not implemented\n", debugstr_w(driver)); 00520 } 00521 } 00522 if (!pm->monitor && !pm->monitorUI) { 00523 monitor_unload(pm); 00524 SetLastError(ERROR_PROC_NOT_FOUND); 00525 pm = NULL; 00526 } 00527 } 00528 cleanup: 00529 if ((pm_localport == NULL) && (pm != NULL) && (lstrcmpW(pm->name, localportW) == 0)) { 00530 pm->refcount++; 00531 pm_localport = pm; 00532 } 00533 LeaveCriticalSection(&monitor_handles_cs); 00534 if (driver != dllname) heap_free(driver); 00535 heap_free(regroot); 00536 TRACE("=> %p\n", pm); 00537 return pm; 00538 } 00539 00540 /****************************************************************** 00541 * monitor_loadall [internal] 00542 * 00543 * Load all registered monitors 00544 * 00545 */ 00546 static DWORD monitor_loadall(void) 00547 { 00548 monitor_t * pm; 00549 DWORD registered = 0; 00550 DWORD loaded = 0; 00551 HKEY hmonitors; 00552 WCHAR buffer[MAX_PATH]; 00553 DWORD id = 0; 00554 00555 if (RegOpenKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hmonitors) == ERROR_SUCCESS) { 00556 RegQueryInfoKeyW(hmonitors, NULL, NULL, NULL, ®istered, NULL, NULL, 00557 NULL, NULL, NULL, NULL, NULL); 00558 00559 TRACE("%d monitors registered\n", registered); 00560 00561 while (id < registered) { 00562 buffer[0] = '\0'; 00563 RegEnumKeyW(hmonitors, id, buffer, MAX_PATH); 00564 pm = monitor_load(buffer, NULL); 00565 if (pm) loaded++; 00566 id++; 00567 } 00568 RegCloseKey(hmonitors); 00569 } 00570 TRACE("%d monitors loaded\n", loaded); 00571 return loaded; 00572 } 00573 00574 /****************************************************************** 00575 * monitor_loadui [internal] 00576 * 00577 * load the userinterface-dll for a given portmonitor 00578 * 00579 * On failure, NULL is returned 00580 */ 00581 static monitor_t * monitor_loadui(monitor_t * pm) 00582 { 00583 monitor_t * pui = NULL; 00584 WCHAR buffer[MAX_PATH]; 00585 HANDLE hXcv; 00586 DWORD len; 00587 DWORD res; 00588 00589 if (pm == NULL) return NULL; 00590 TRACE("(%p) => dllname: %s\n", pm, debugstr_w(pm->dllname)); 00591 00592 /* Try the Portmonitor first; works for many monitors */ 00593 if (pm->monitorUI) { 00594 EnterCriticalSection(&monitor_handles_cs); 00595 pm->refcount++; 00596 LeaveCriticalSection(&monitor_handles_cs); 00597 return pm; 00598 } 00599 00600 /* query the userinterface-dllname from the Portmonitor */ 00601 if ((pm->monitor) && (pm->monitor->pfnXcvDataPort)) { 00602 /* building (",XcvMonitor %s",pm->name) not needed yet */ 00603 res = pm->monitor->pfnXcvOpenPort(emptyW, SERVER_ACCESS_ADMINISTER, &hXcv); 00604 TRACE("got %u with %p\n", res, hXcv); 00605 if (res) { 00606 res = pm->monitor->pfnXcvDataPort(hXcv, monitorUIW, NULL, 0, (BYTE *) buffer, sizeof(buffer), &len); 00607 TRACE("got %u with %s\n", res, debugstr_w(buffer)); 00608 if (res == ERROR_SUCCESS) pui = monitor_load(NULL, buffer); 00609 pm->monitor->pfnXcvClosePort(hXcv); 00610 } 00611 } 00612 return pui; 00613 } 00614 00615 /****************************************************************** 00616 * monitor_load_by_port [internal] 00617 * 00618 * load a printmonitor for a given port 00619 * 00620 * On failure, NULL is returned 00621 */ 00622 00623 static monitor_t * monitor_load_by_port(LPCWSTR portname) 00624 { 00625 HKEY hroot; 00626 HKEY hport; 00627 LPWSTR buffer; 00628 monitor_t * pm = NULL; 00629 DWORD registered = 0; 00630 DWORD id = 0; 00631 DWORD len; 00632 00633 TRACE("(%s)\n", debugstr_w(portname)); 00634 00635 /* Try the Local Monitor first */ 00636 if (RegOpenKeyW(HKEY_LOCAL_MACHINE, winnt_cv_portsW, &hroot) == ERROR_SUCCESS) { 00637 if (RegQueryValueExW(hroot, portname, NULL, NULL, NULL, &len) == ERROR_SUCCESS) { 00638 /* found the portname */ 00639 RegCloseKey(hroot); 00640 return monitor_load(localportW, NULL); 00641 } 00642 RegCloseKey(hroot); 00643 } 00644 00645 len = MAX_PATH + lstrlenW(bs_ports_bsW) + lstrlenW(portname) + 1; 00646 buffer = heap_alloc(len * sizeof(WCHAR)); 00647 if (buffer == NULL) return NULL; 00648 00649 if (RegOpenKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) == ERROR_SUCCESS) { 00650 EnterCriticalSection(&monitor_handles_cs); 00651 RegQueryInfoKeyW(hroot, NULL, NULL, NULL, ®istered, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 00652 00653 while ((pm == NULL) && (id < registered)) { 00654 buffer[0] = '\0'; 00655 RegEnumKeyW(hroot, id, buffer, MAX_PATH); 00656 TRACE("testing %s\n", debugstr_w(buffer)); 00657 len = lstrlenW(buffer); 00658 lstrcatW(buffer, bs_ports_bsW); 00659 lstrcatW(buffer, portname); 00660 if (RegOpenKeyW(hroot, buffer, &hport) == ERROR_SUCCESS) { 00661 RegCloseKey(hport); 00662 buffer[len] = '\0'; /* use only the Monitor-Name */ 00663 pm = monitor_load(buffer, NULL); 00664 } 00665 id++; 00666 } 00667 LeaveCriticalSection(&monitor_handles_cs); 00668 RegCloseKey(hroot); 00669 } 00670 heap_free(buffer); 00671 return pm; 00672 } 00673 00674 /****************************************************************** 00675 * Return the number of bytes for an multi_sz string. 00676 * The result includes all \0s 00677 * (specifically the extra \0, that is needed as multi_sz terminator). 00678 */ 00679 static int multi_sz_lenW(const WCHAR *str) 00680 { 00681 const WCHAR *ptr = str; 00682 if (!str) return 0; 00683 do 00684 { 00685 ptr += lstrlenW(ptr) + 1; 00686 } while (*ptr); 00687 00688 return (ptr - str + 1) * sizeof(WCHAR); 00689 } 00690 00691 /****************************************************************** 00692 * validate_envW [internal] 00693 * 00694 * validate the user-supplied printing-environment 00695 * 00696 * PARAMS 00697 * env [I] PTR to Environment-String or NULL 00698 * 00699 * RETURNS 00700 * Success: PTR to printenv_t 00701 * Failure: NULL and ERROR_INVALID_ENVIRONMENT 00702 * 00703 * NOTES 00704 * An empty string is handled the same way as NULL. 00705 * 00706 */ 00707 00708 static const printenv_t * validate_envW(LPCWSTR env) 00709 { 00710 const printenv_t *result = NULL; 00711 unsigned int i; 00712 00713 TRACE("(%s)\n", debugstr_w(env)); 00714 if (env && env[0]) 00715 { 00716 for (i = 0; i < sizeof(all_printenv)/sizeof(all_printenv[0]); i++) 00717 { 00718 if (lstrcmpiW(env, all_printenv[i]->envname) == 0) 00719 { 00720 result = all_printenv[i]; 00721 break; 00722 } 00723 } 00724 if (result == NULL) { 00725 FIXME("unsupported Environment: %s\n", debugstr_w(env)); 00726 SetLastError(ERROR_INVALID_ENVIRONMENT); 00727 } 00728 /* on win9x, only "Windows 4.0" is allowed, but we ignore this */ 00729 } 00730 else 00731 { 00732 result = (GetVersion() & 0x80000000) ? &env_win40 : &env_x86; 00733 } 00734 00735 TRACE("=> using %p: %s\n", result, debugstr_w(result ? result->envname : NULL)); 00736 return result; 00737 } 00738 00739 /***************************************************************************** 00740 * enumerate the local monitors (INTERNAL) 00741 * 00742 * returns the needed size (in bytes) for pMonitors 00743 * and *lpreturned is set to number of entries returned in pMonitors 00744 * 00745 * Language-Monitors are also installed in the same Registry-Location but 00746 * they are filtered in Windows (not returned by EnumMonitors). 00747 * We do no filtering to simplify our Code. 00748 * 00749 */ 00750 static DWORD get_local_monitors(DWORD level, LPBYTE pMonitors, DWORD cbBuf, LPDWORD lpreturned) 00751 { 00752 HKEY hroot = NULL; 00753 HKEY hentry = NULL; 00754 LPWSTR ptr; 00755 LPMONITOR_INFO_2W mi; 00756 WCHAR buffer[MAX_PATH]; 00757 WCHAR dllname[MAX_PATH]; 00758 DWORD dllsize; 00759 DWORD len; 00760 DWORD index = 0; 00761 DWORD needed = 0; 00762 DWORD numentries; 00763 DWORD entrysize; 00764 00765 entrysize = (level == 1) ? sizeof(MONITOR_INFO_1W) : sizeof(MONITOR_INFO_2W); 00766 00767 numentries = *lpreturned; /* this is 0, when we scan the registry */ 00768 len = entrysize * numentries; 00769 ptr = (LPWSTR) &pMonitors[len]; 00770 00771 numentries = 0; 00772 len = sizeof(buffer)/sizeof(buffer[0]); 00773 buffer[0] = '\0'; 00774 00775 /* Windows creates the "Monitors"-Key on reboot / start "spooler" */ 00776 if (RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) == ERROR_SUCCESS) { 00777 /* Scan all Monitor-Registry-Keys */ 00778 while (RegEnumKeyExW(hroot, index, buffer, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { 00779 TRACE("Monitor_%d: %s\n", numentries, debugstr_w(buffer)); 00780 dllsize = sizeof(dllname); 00781 dllname[0] = '\0'; 00782 00783 /* The Monitor must have a Driver-DLL */ 00784 if (RegOpenKeyExW(hroot, buffer, 0, KEY_READ, &hentry) == ERROR_SUCCESS) { 00785 if (RegQueryValueExW(hentry, driverW, NULL, NULL, (LPBYTE) dllname, &dllsize) == ERROR_SUCCESS) { 00786 /* We found a valid DLL for this Monitor. */ 00787 TRACE("using Driver: %s\n", debugstr_w(dllname)); 00788 } 00789 RegCloseKey(hentry); 00790 } 00791 00792 /* Windows returns only Port-Monitors here, but to simplify our code, 00793 we do no filtering for Language-Monitors */ 00794 if (dllname[0]) { 00795 numentries++; 00796 needed += entrysize; 00797 needed += (len+1) * sizeof(WCHAR); /* len is lstrlenW(monitorname) */ 00798 if (level > 1) { 00799 /* we install and return only monitors for "Windows NT x86" */ 00800 needed += (lstrlenW(x86_envnameW) +1) * sizeof(WCHAR); 00801 needed += dllsize; 00802 } 00803 00804 /* required size is calculated. Now fill the user-buffer */ 00805 if (pMonitors && (cbBuf >= needed)){ 00806 mi = (LPMONITOR_INFO_2W) pMonitors; 00807 pMonitors += entrysize; 00808 00809 TRACE("%p: writing MONITOR_INFO_%dW #%d\n", mi, level, numentries); 00810 mi->pName = ptr; 00811 lstrcpyW(ptr, buffer); /* Name of the Monitor */ 00812 ptr += (len+1); /* len is lstrlenW(monitorname) */ 00813 if (level > 1) { 00814 mi->pEnvironment = ptr; 00815 lstrcpyW(ptr, x86_envnameW); /* fixed to "Windows NT x86" */ 00816 ptr += (lstrlenW(x86_envnameW)+1); 00817 00818 mi->pDLLName = ptr; 00819 lstrcpyW(ptr, dllname); /* Name of the Driver-DLL */ 00820 ptr += (dllsize / sizeof(WCHAR)); 00821 } 00822 } 00823 } 00824 index++; 00825 len = sizeof(buffer)/sizeof(buffer[0]); 00826 buffer[0] = '\0'; 00827 } 00828 RegCloseKey(hroot); 00829 } 00830 *lpreturned = numentries; 00831 TRACE("need %d byte for %d entries\n", needed, numentries); 00832 return needed; 00833 } 00834 00835 /***************************************************************************** 00836 * enumerate the local print processors (INTERNAL) 00837 * 00838 * returns the needed size (in bytes) for pPPInfo 00839 * and *lpreturned is set to number of entries returned in pPPInfo 00840 * 00841 */ 00842 static DWORD get_local_printprocessors(LPWSTR regpathW, LPBYTE pPPInfo, DWORD cbBuf, LPDWORD lpreturned) 00843 { 00844 HKEY hroot = NULL; 00845 HKEY hentry = NULL; 00846 LPWSTR ptr; 00847 PPRINTPROCESSOR_INFO_1W ppi; 00848 WCHAR buffer[MAX_PATH]; 00849 WCHAR dllname[MAX_PATH]; 00850 DWORD dllsize; 00851 DWORD len; 00852 DWORD index = 0; 00853 DWORD needed = 0; 00854 DWORD numentries; 00855 00856 numentries = *lpreturned; /* this is 0, when we scan the registry */ 00857 len = numentries * sizeof(PRINTPROCESSOR_INFO_1W); 00858 ptr = (LPWSTR) &pPPInfo[len]; 00859 00860 numentries = 0; 00861 len = sizeof(buffer)/sizeof(buffer[0]); 00862 buffer[0] = '\0'; 00863 00864 if (RegCreateKeyW(HKEY_LOCAL_MACHINE, regpathW, &hroot) == ERROR_SUCCESS) { 00865 /* add "winprint" first */ 00866 numentries++; 00867 needed = sizeof(PRINTPROCESSOR_INFO_1W) + sizeof(winprintW); 00868 if (pPPInfo && (cbBuf >= needed)){ 00869 ppi = (PPRINTPROCESSOR_INFO_1W) pPPInfo; 00870 pPPInfo += sizeof(PRINTPROCESSOR_INFO_1W); 00871 00872 TRACE("%p: writing PRINTPROCESSOR_INFO_1W #%d\n", ppi, numentries); 00873 ppi->pName = ptr; 00874 lstrcpyW(ptr, winprintW); /* Name of the Print Processor */ 00875 ptr += sizeof(winprintW) / sizeof(WCHAR); 00876 } 00877 00878 /* Scan all Printprocessor Keys */ 00879 while ((RegEnumKeyExW(hroot, index, buffer, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) && 00880 (lstrcmpiW(buffer, winprintW) != 0)) { 00881 TRACE("PrintProcessor_%d: %s\n", numentries, debugstr_w(buffer)); 00882 dllsize = sizeof(dllname); 00883 dllname[0] = '\0'; 00884 00885 /* The Print Processor must have a Driver-DLL */ 00886 if (RegOpenKeyExW(hroot, buffer, 0, KEY_READ, &hentry) == ERROR_SUCCESS) { 00887 if (RegQueryValueExW(hentry, driverW, NULL, NULL, (LPBYTE) dllname, &dllsize) == ERROR_SUCCESS) { 00888 /* We found a valid DLL for this Print Processor */ 00889 TRACE("using Driver: %s\n", debugstr_w(dllname)); 00890 } 00891 RegCloseKey(hentry); 00892 } 00893 00894 if (dllname[0]) { 00895 numentries++; 00896 needed += sizeof(PRINTPROCESSOR_INFO_1W); 00897 needed += (len+1) * sizeof(WCHAR); /* len is lstrlenW(printprocessor name) */ 00898 00899 /* required size is calculated. Now fill the user-buffer */ 00900 if (pPPInfo && (cbBuf >= needed)){ 00901 ppi = (PPRINTPROCESSOR_INFO_1W) pPPInfo; 00902 pPPInfo += sizeof(PRINTPROCESSOR_INFO_1W); 00903 00904 TRACE("%p: writing PRINTPROCESSOR_INFO_1W #%d\n", ppi, numentries); 00905 ppi->pName = ptr; 00906 lstrcpyW(ptr, buffer); /* Name of the Print Processor */ 00907 ptr += (len+1); /* len is lstrlenW(printprosessor name) */ 00908 } 00909 } 00910 index++; 00911 len = sizeof(buffer)/sizeof(buffer[0]); 00912 buffer[0] = '\0'; 00913 } 00914 RegCloseKey(hroot); 00915 } 00916 *lpreturned = numentries; 00917 TRACE("need %d byte for %d entries\n", needed, numentries); 00918 return needed; 00919 } 00920 00921 /****************************************************************** 00922 * enumerate the local Ports from all loaded monitors (internal) 00923 * 00924 * returns the needed size (in bytes) for pPorts 00925 * and *lpreturned is set to number of entries returned in pPorts 00926 * 00927 */ 00928 static DWORD get_ports_from_all_monitors(DWORD level, LPBYTE pPorts, DWORD cbBuf, LPDWORD lpreturned) 00929 { 00930 monitor_t * pm; 00931 LPWSTR ptr; 00932 LPPORT_INFO_2W cache; 00933 LPPORT_INFO_2W out; 00934 LPBYTE pi_buffer = NULL; 00935 DWORD pi_allocated = 0; 00936 DWORD pi_needed; 00937 DWORD pi_index; 00938 DWORD pi_returned; 00939 DWORD res; 00940 DWORD outindex = 0; 00941 DWORD needed; 00942 DWORD numentries; 00943 DWORD entrysize; 00944 00945 00946 TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned); 00947 entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W); 00948 00949 numentries = *lpreturned; /* this is 0, when we scan the registry */ 00950 needed = entrysize * numentries; 00951 ptr = (LPWSTR) &pPorts[needed]; 00952 00953 numentries = 0; 00954 needed = 0; 00955 00956 LIST_FOR_EACH_ENTRY(pm, &monitor_handles, monitor_t, entry) 00957 { 00958 if ((pm->monitor) && (pm->monitor->pfnEnumPorts)) { 00959 pi_needed = 0; 00960 pi_returned = 0; 00961 res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); 00962 if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { 00963 /* Do not use heap_realloc (we do not need the old data in the buffer) */ 00964 heap_free(pi_buffer); 00965 pi_buffer = heap_alloc(pi_needed); 00966 pi_allocated = (pi_buffer) ? pi_needed : 0; 00967 res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); 00968 } 00969 TRACE("(%s) got %d with %d (need %d byte for %d entries)\n", 00970 debugstr_w(pm->name), res, GetLastError(), pi_needed, pi_returned); 00971 00972 numentries += pi_returned; 00973 needed += pi_needed; 00974 00975 /* fill the output-buffer (pPorts), if we have one */ 00976 if (pPorts && (cbBuf >= needed ) && pi_buffer) { 00977 pi_index = 0; 00978 while (pi_returned > pi_index) { 00979 cache = (LPPORT_INFO_2W) &pi_buffer[pi_index * entrysize]; 00980 out = (LPPORT_INFO_2W) &pPorts[outindex * entrysize]; 00981 out->pPortName = ptr; 00982 lstrcpyW(ptr, cache->pPortName); 00983 ptr += (lstrlenW(ptr)+1); 00984 if (level > 1) { 00985 out->pMonitorName = ptr; 00986 lstrcpyW(ptr, cache->pMonitorName); 00987 ptr += (lstrlenW(ptr)+1); 00988 00989 out->pDescription = ptr; 00990 lstrcpyW(ptr, cache->pDescription); 00991 ptr += (lstrlenW(ptr)+1); 00992 out->fPortType = cache->fPortType; 00993 out->Reserved = cache->Reserved; 00994 } 00995 pi_index++; 00996 outindex++; 00997 } 00998 } 00999 } 01000 } 01001 /* the temporary portinfo-buffer is no longer needed */ 01002 heap_free(pi_buffer); 01003 01004 *lpreturned = numentries; 01005 TRACE("need %d byte for %d entries\n", needed, numentries); 01006 return needed; 01007 } 01008 01009 01010 /***************************************************************************** 01011 * open_driver_reg [internal] 01012 * 01013 * opens the registry for the printer drivers depending on the given input 01014 * variable pEnvironment 01015 * 01016 * RETURNS: 01017 * Success: the opened hkey 01018 * Failure: NULL 01019 */ 01020 static HKEY open_driver_reg(LPCWSTR pEnvironment) 01021 { 01022 HKEY retval = NULL; 01023 LPWSTR buffer; 01024 const printenv_t * env; 01025 01026 TRACE("(%s)\n", debugstr_w(pEnvironment)); 01027 01028 env = validate_envW(pEnvironment); 01029 if (!env) return NULL; 01030 01031 buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(fmt_driversW) + 01032 (lstrlenW(env->envname) + lstrlenW(env->versionregpath)) * sizeof(WCHAR)); 01033 01034 if (buffer) { 01035 wsprintfW(buffer, fmt_driversW, env->envname, env->versionregpath); 01036 RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval); 01037 HeapFree(GetProcessHeap(), 0, buffer); 01038 } 01039 return retval; 01040 } 01041 01042 /***************************************************************************** 01043 * fpGetPrinterDriverDirectory [exported through PRINTPROVIDOR] 01044 * 01045 * Return the PATH for the Printer-Drivers 01046 * 01047 * PARAMS 01048 * pName [I] Servername (NT only) or NULL (local Computer) 01049 * pEnvironment [I] Printing-Environment (see below) or NULL (Default) 01050 * Level [I] Structure-Level (must be 1) 01051 * pDriverDirectory [O] PTR to Buffer that receives the Result 01052 * cbBuf [I] Size of Buffer at pDriverDirectory 01053 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / 01054 * required for pDriverDirectory 01055 * 01056 * RETURNS 01057 * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory 01058 * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory, 01059 * if cbBuf is too small 01060 * 01061 * Native Values returned in pDriverDirectory on Success: 01062 *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86" 01063 *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40" 01064 *| win9x(Windows 4.0): "%winsysdir%" 01065 * 01066 * "%winsysdir%" is the Value from GetSystemDirectoryW() 01067 * 01068 */ 01069 static BOOL WINAPI fpGetPrinterDriverDirectory(LPWSTR pName, LPWSTR pEnvironment, 01070 DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded) 01071 { 01072 DWORD needed; 01073 const printenv_t * env; 01074 01075 TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName), 01076 debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded); 01077 01078 if (pName != NULL && pName[0]) { 01079 FIXME("server %s not supported\n", debugstr_w(pName)); 01080 SetLastError(ERROR_INVALID_PARAMETER); 01081 return FALSE; 01082 } 01083 01084 env = validate_envW(pEnvironment); 01085 if (!env) return FALSE; /* pEnvironment invalid or unsupported */ 01086 01087 01088 /* GetSystemDirectoryW returns number of WCHAR including the '\0' */ 01089 needed = GetSystemDirectoryW(NULL, 0); 01090 /* add the Size for the Subdirectories */ 01091 needed += lstrlenW(spooldriversW); 01092 needed += lstrlenW(env->subdir); 01093 needed *= sizeof(WCHAR); /* return-value is size in Bytes */ 01094 01095 *pcbNeeded = needed; 01096 01097 if (needed > cbBuf) { 01098 SetLastError(ERROR_INSUFFICIENT_BUFFER); 01099 return FALSE; 01100 } 01101 01102 if (pDriverDirectory == NULL) { 01103 /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */ 01104 SetLastError(ERROR_INVALID_USER_BUFFER); 01105 return FALSE; 01106 } 01107 01108 GetSystemDirectoryW((LPWSTR) pDriverDirectory, cbBuf/sizeof(WCHAR)); 01109 /* add the Subdirectories */ 01110 lstrcatW((LPWSTR) pDriverDirectory, spooldriversW); 01111 lstrcatW((LPWSTR) pDriverDirectory, env->subdir); 01112 01113 TRACE("=> %s\n", debugstr_w((LPWSTR) pDriverDirectory)); 01114 return TRUE; 01115 } 01116 01117 /****************************************************************** 01118 * driver_load [internal] 01119 * 01120 * load a driver user interface dll 01121 * 01122 * On failure, NULL is returned 01123 * 01124 */ 01125 01126 static HMODULE driver_load(const printenv_t * env, LPWSTR dllname) 01127 { 01128 WCHAR fullname[MAX_PATH]; 01129 HMODULE hui; 01130 DWORD len; 01131 01132 TRACE("(%p, %s)\n", env, debugstr_w(dllname)); 01133 01134 /* build the driverdir */ 01135 len = sizeof(fullname) - 01136 (lstrlenW(env->versionsubdir) + 1 + lstrlenW(dllname) + 1) * sizeof(WCHAR); 01137 01138 if (!fpGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, 01139 (LPBYTE) fullname, len, &len)) { 01140 /* Should never Fail */ 01141 SetLastError(ERROR_BUFFER_OVERFLOW); 01142 return NULL; 01143 } 01144 01145 lstrcatW(fullname, env->versionsubdir); 01146 lstrcatW(fullname, backslashW); 01147 lstrcatW(fullname, dllname); 01148 01149 hui = LoadLibraryW(fullname); 01150 TRACE("%p: LoadLibrary(%s) %d\n", hui, debugstr_w(fullname), GetLastError()); 01151 01152 return hui; 01153 } 01154 01155 /****************************************************************** 01156 * printer_free 01157 * free the data pointer of an opened printer 01158 */ 01159 static VOID printer_free(printer_t * printer) 01160 { 01161 if (printer->hXcv) 01162 printer->pm->monitor->pfnXcvClosePort(printer->hXcv); 01163 01164 monitor_unload(printer->pm); 01165 01166 heap_free(printer->printername); 01167 heap_free(printer->name); 01168 heap_free(printer); 01169 } 01170 01171 /****************************************************************** 01172 * printer_alloc_handle 01173 * alloc a printer handle and remember the data pointer in the printer handle table 01174 * 01175 */ 01176 static HANDLE printer_alloc_handle(LPCWSTR name, LPPRINTER_DEFAULTSW pDefault) 01177 { 01178 WCHAR servername[MAX_COMPUTERNAME_LENGTH + 1]; 01179 printer_t *printer = NULL; 01180 LPCWSTR printername; 01181 HKEY hkeyPrinters; 01182 HKEY hkeyPrinter; 01183 DWORD len; 01184 01185 if (copy_servername_from_name(name, servername)) { 01186 FIXME("server %s not supported\n", debugstr_w(servername)); 01187 SetLastError(ERROR_INVALID_PRINTER_NAME); 01188 return NULL; 01189 } 01190 01191 printername = get_basename_from_name(name); 01192 if (name != printername) TRACE("converted %s to %s\n", debugstr_w(name), debugstr_w(printername)); 01193 01194 /* an empty printername is invalid */ 01195 if (printername && (!printername[0])) { 01196 SetLastError(ERROR_INVALID_PARAMETER); 01197 return NULL; 01198 } 01199 01200 printer = heap_alloc_zero(sizeof(printer_t)); 01201 if (!printer) goto end; 01202 01203 /* clone the base name. This is NULL for the printserver */ 01204 printer->printername = strdupW(printername); 01205 01206 /* clone the full name */ 01207 printer->name = strdupW(name); 01208 if (name && (!printer->name)) { 01209 printer_free(printer); 01210 printer = NULL; 01211 } 01212 if (printername) { 01213 len = sizeof(XcvMonitorW)/sizeof(WCHAR) - 1; 01214 if (strncmpW(printername, XcvMonitorW, len) == 0) { 01215 /* OpenPrinter(",XcvMonitor ", ...) detected */ 01216 TRACE(",XcvMonitor: %s\n", debugstr_w(&printername[len])); 01217 printer->pm = monitor_load(&printername[len], NULL); 01218 if (printer->pm == NULL) { 01219 printer_free(printer); 01220 SetLastError(ERROR_UNKNOWN_PORT); 01221 printer = NULL; 01222 goto end; 01223 } 01224 } 01225 else 01226 { 01227 len = sizeof(XcvPortW)/sizeof(WCHAR) - 1; 01228 if (strncmpW( printername, XcvPortW, len) == 0) { 01229 /* OpenPrinter(",XcvPort ", ...) detected */ 01230 TRACE(",XcvPort: %s\n", debugstr_w(&printername[len])); 01231 printer->pm = monitor_load_by_port(&printername[len]); 01232 if (printer->pm == NULL) { 01233 printer_free(printer); 01234 SetLastError(ERROR_UNKNOWN_PORT); 01235 printer = NULL; 01236 goto end; 01237 } 01238 } 01239 } 01240 01241 if (printer->pm) { 01242 if ((printer->pm->monitor) && (printer->pm->monitor->pfnXcvOpenPort)) { 01243 printer->pm->monitor->pfnXcvOpenPort(&printername[len], 01244 pDefault ? pDefault->DesiredAccess : 0, 01245 &printer->hXcv); 01246 } 01247 if (printer->hXcv == NULL) { 01248 printer_free(printer); 01249 SetLastError(ERROR_INVALID_PARAMETER); 01250 printer = NULL; 01251 goto end; 01252 } 01253 } 01254 else 01255 { 01256 /* Does the Printer exist? */ 01257 if (RegCreateKeyW(HKEY_LOCAL_MACHINE, printersW, &hkeyPrinters) != ERROR_SUCCESS) { 01258 ERR("Can't create Printers key\n"); 01259 printer_free(printer); 01260 SetLastError(ERROR_INVALID_PRINTER_NAME); 01261 printer = NULL; 01262 goto end; 01263 } 01264 if (RegOpenKeyW(hkeyPrinters, printername, &hkeyPrinter) != ERROR_SUCCESS) { 01265 WARN("Printer not found in Registry: %s\n", debugstr_w(printername)); 01266 RegCloseKey(hkeyPrinters); 01267 printer_free(printer); 01268 SetLastError(ERROR_INVALID_PRINTER_NAME); 01269 printer = NULL; 01270 goto end; 01271 } 01272 RegCloseKey(hkeyPrinter); 01273 RegCloseKey(hkeyPrinters); 01274 } 01275 } 01276 else 01277 { 01278 TRACE("using the local printserver\n"); 01279 } 01280 01281 end: 01282 01283 TRACE("==> %p\n", printer); 01284 return (HANDLE)printer; 01285 } 01286 01287 01288 /****************************************************************************** 01289 * myAddPrinterDriverEx [internal] 01290 * 01291 * Install a Printer Driver with the Option to upgrade / downgrade the Files 01292 * and a special mode with lazy error checking. 01293 * 01294 */ 01295 static BOOL myAddPrinterDriverEx(DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags, BOOL lazy) 01296 { 01297 const printenv_t *env; 01298 apd_data_t apd; 01299 DRIVER_INFO_8W di; 01300 BOOL (WINAPI *pDrvDriverEvent)(DWORD, DWORD, LPBYTE, LPARAM); 01301 HMODULE hui; 01302 LPWSTR ptr; 01303 HKEY hroot; 01304 HKEY hdrv; 01305 DWORD disposition; 01306 DWORD len; 01307 LONG lres; 01308 BOOL res; 01309 01310 /* we need to set all entries in the Registry, independent from the Level of 01311 DRIVER_INFO, that the caller supplied */ 01312 01313 ZeroMemory(&di, sizeof(di)); 01314 if (pDriverInfo && (level < (sizeof(di_sizeof) / sizeof(di_sizeof[0])))) { 01315 memcpy(&di, pDriverInfo, di_sizeof[level]); 01316 } 01317 01318 /* dump the most used infos */ 01319 TRACE("%p: .cVersion : 0x%x/%d\n", pDriverInfo, di.cVersion, di.cVersion); 01320 TRACE("%p: .pName : %s\n", di.pName, debugstr_w(di.pName)); 01321 TRACE("%p: .pEnvironment: %s\n", di.pEnvironment, debugstr_w(di.pEnvironment)); 01322 TRACE("%p: .pDriverPath : %s\n", di.pDriverPath, debugstr_w(di.pDriverPath)); 01323 TRACE("%p: .pDataFile : %s\n", di.pDataFile, debugstr_w(di.pDataFile)); 01324 TRACE("%p: .pConfigFile : %s\n", di.pConfigFile, debugstr_w(di.pConfigFile)); 01325 TRACE("%p: .pHelpFile : %s\n", di.pHelpFile, debugstr_w(di.pHelpFile)); 01326 /* dump only the first of the additional Files */ 01327 TRACE("%p: .pDependentFiles: %s\n", di.pDependentFiles, debugstr_w(di.pDependentFiles)); 01328 01329 01330 /* check environment */ 01331 env = validate_envW(di.pEnvironment); 01332 if (env == NULL) return FALSE; /* ERROR_INVALID_ENVIRONMENT */ 01333 01334 /* fill the copy-data / get the driverdir */ 01335 len = sizeof(apd.src) - sizeof(version3_subdirW) - sizeof(WCHAR); 01336 if (!fpGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, 01337 (LPBYTE) apd.src, len, &len)) { 01338 /* Should never Fail */ 01339 return FALSE; 01340 } 01341 memcpy(apd.dst, apd.src, len); 01342 lstrcatW(apd.src, backslashW); 01343 apd.srclen = lstrlenW(apd.src); 01344 lstrcatW(apd.dst, env->versionsubdir); 01345 lstrcatW(apd.dst, backslashW); 01346 apd.dstlen = lstrlenW(apd.dst); 01347 apd.copyflags = dwFileCopyFlags; 01348 apd.lazy = lazy; 01349 CreateDirectoryW(apd.src, NULL); 01350 CreateDirectoryW(apd.dst, NULL); 01351 01352 hroot = open_driver_reg(env->envname); 01353 if (!hroot) { 01354 ERR("Can't create Drivers key\n"); 01355 return FALSE; 01356 } 01357 01358 /* Fill the Registry for the Driver */ 01359 if ((lres = RegCreateKeyExW(hroot, di.pName, 0, NULL, REG_OPTION_NON_VOLATILE, 01360 KEY_WRITE | KEY_QUERY_VALUE, NULL, 01361 &hdrv, &disposition)) != ERROR_SUCCESS) { 01362 01363 ERR("can't create driver %s: %u\n", debugstr_w(di.pName), lres); 01364 RegCloseKey(hroot); 01365 SetLastError(lres); 01366 return FALSE; 01367 } 01368 RegCloseKey(hroot); 01369 01370 if (disposition == REG_OPENED_EXISTING_KEY) { 01371 TRACE("driver %s already installed\n", debugstr_w(di.pName)); 01372 RegCloseKey(hdrv); 01373 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED); 01374 return FALSE; 01375 } 01376 01377 /* Verified with the Adobe PS Driver, that w2k does not use di.Version */ 01378 RegSetValueExW(hdrv, versionW, 0, REG_DWORD, (const BYTE*) &env->driverversion, 01379 sizeof(DWORD)); 01380 01381 RegSetValueExW(hdrv, driverW, 0, REG_SZ, (LPBYTE) di.pDriverPath, 01382 (lstrlenW(di.pDriverPath)+1)* sizeof(WCHAR)); 01383 apd_copyfile(di.pDriverPath, &apd); 01384 01385 RegSetValueExW(hdrv, data_fileW, 0, REG_SZ, (LPBYTE) di.pDataFile, 01386 (lstrlenW(di.pDataFile)+1)* sizeof(WCHAR)); 01387 apd_copyfile(di.pDataFile, &apd); 01388 01389 RegSetValueExW(hdrv, configuration_fileW, 0, REG_SZ, (LPBYTE) di.pConfigFile, 01390 (lstrlenW(di.pConfigFile)+1)* sizeof(WCHAR)); 01391 apd_copyfile(di.pConfigFile, &apd); 01392 01393 /* settings for level 3 */ 01394 if (di.pHelpFile) 01395 RegSetValueExW(hdrv, help_fileW, 0, REG_SZ, (LPBYTE) di.pHelpFile, 01396 (lstrlenW(di.pHelpFile)+1)* sizeof(WCHAR)); 01397 else 01398 RegSetValueExW(hdrv, help_fileW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW)); 01399 apd_copyfile(di.pHelpFile, &apd); 01400 01401 01402 ptr = di.pDependentFiles; 01403 if (ptr) 01404 RegSetValueExW(hdrv, dependent_filesW, 0, REG_MULTI_SZ, (LPBYTE) di.pDependentFiles, 01405 multi_sz_lenW(di.pDependentFiles)); 01406 else 01407 RegSetValueExW(hdrv, dependent_filesW, 0, REG_MULTI_SZ, (const BYTE*)emptyW, sizeof(emptyW)); 01408 while ((ptr != NULL) && (ptr[0])) { 01409 if (apd_copyfile(ptr, &apd)) { 01410 ptr += lstrlenW(ptr) + 1; 01411 } 01412 else 01413 { 01414 WARN("Failed to copy %s\n", debugstr_w(ptr)); 01415 ptr = NULL; 01416 } 01417 } 01418 /* The language-Monitor was already copied by the caller to "%SystemRoot%\system32" */ 01419 if (di.pMonitorName) 01420 RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (LPBYTE) di.pMonitorName, 01421 (lstrlenW(di.pMonitorName)+1)* sizeof(WCHAR)); 01422 else 01423 RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW)); 01424 01425 if (di.pDefaultDataType) 01426 RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (LPBYTE) di.pDefaultDataType, 01427 (lstrlenW(di.pDefaultDataType)+1)* sizeof(WCHAR)); 01428 else 01429 RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW)); 01430 01431 /* settings for level 4 */ 01432 if (di.pszzPreviousNames) 01433 RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (LPBYTE) di.pszzPreviousNames, 01434 multi_sz_lenW(di.pszzPreviousNames)); 01435 else 01436 RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (const BYTE*)emptyW, sizeof(emptyW)); 01437 01438 if (level > 5) TRACE("level %u for Driver %s is incomplete\n", level, debugstr_w(di.pName)); 01439 01440 RegCloseKey(hdrv); 01441 hui = driver_load(env, di.pConfigFile); 01442 pDrvDriverEvent = (void *)GetProcAddress(hui, "DrvDriverEvent"); 01443 if (hui && pDrvDriverEvent) { 01444 01445 /* Support for DrvDriverEvent is optional */ 01446 TRACE("DRIVER_EVENT_INITIALIZE for %s (%s)\n", debugstr_w(di.pName), debugstr_w(di.pConfigFile)); 01447 /* MSDN: level for DRIVER_INFO is 1 to 3 */ 01448 res = pDrvDriverEvent(DRIVER_EVENT_INITIALIZE, 3, (LPBYTE) &di, 0); 01449 TRACE("got %d from DRIVER_EVENT_INITIALIZE\n", res); 01450 } 01451 FreeLibrary(hui); 01452 01453 TRACE("=> TRUE with %u\n", GetLastError()); 01454 return TRUE; 01455 01456 } 01457 01458 /****************************************************************************** 01459 * fpAddMonitor [exported through PRINTPROVIDOR] 01460 * 01461 * Install a Printmonitor 01462 * 01463 * PARAMS 01464 * pName [I] Servername or NULL (local Computer) 01465 * Level [I] Structure-Level (Must be 2) 01466 * pMonitors [I] PTR to MONITOR_INFO_2 01467 * 01468 * RETURNS 01469 * Success: TRUE 01470 * Failure: FALSE 01471 * 01472 * NOTES 01473 * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32") 01474 * 01475 */ 01476 static BOOL WINAPI fpAddMonitor(LPWSTR pName, DWORD Level, LPBYTE pMonitors) 01477 { 01478 monitor_t * pm = NULL; 01479 LPMONITOR_INFO_2W mi2w; 01480 HKEY hroot = NULL; 01481 HKEY hentry = NULL; 01482 DWORD disposition; 01483 BOOL res = FALSE; 01484 01485 mi2w = (LPMONITOR_INFO_2W) pMonitors; 01486 TRACE("(%s, %d, %p): %s %s %s\n", debugstr_w(pName), Level, pMonitors, 01487 debugstr_w(mi2w ? mi2w->pName : NULL), 01488 debugstr_w(mi2w ? mi2w->pEnvironment : NULL), 01489 debugstr_w(mi2w ? mi2w->pDLLName : NULL)); 01490 01491 if (copy_servername_from_name(pName, NULL)) { 01492 FIXME("server %s not supported\n", debugstr_w(pName)); 01493 SetLastError(ERROR_ACCESS_DENIED); 01494 return FALSE; 01495 } 01496 01497 if (!mi2w->pName || (! mi2w->pName[0])) { 01498 WARN("pName not valid : %s\n", debugstr_w(mi2w->pName)); 01499 SetLastError(ERROR_INVALID_PARAMETER); 01500 return FALSE; 01501 } 01502 if (!mi2w->pEnvironment || lstrcmpW(mi2w->pEnvironment, x86_envnameW)) { 01503 WARN("Environment %s requested (we support only %s)\n", 01504 debugstr_w(mi2w->pEnvironment), debugstr_w(x86_envnameW)); 01505 SetLastError(ERROR_INVALID_ENVIRONMENT); 01506 return FALSE; 01507 } 01508 01509 if (!mi2w->pDLLName || (! mi2w->pDLLName[0])) { 01510 WARN("pDLLName not valid : %s\n", debugstr_w(mi2w->pDLLName)); 01511 SetLastError(ERROR_INVALID_PARAMETER); 01512 return FALSE; 01513 } 01514 01515 /* Load and initialize the monitor. SetLastError() is called on failure */ 01516 if ((pm = monitor_load(mi2w->pName, mi2w->pDLLName)) == NULL) { 01517 return FALSE; 01518 } 01519 monitor_unload(pm); 01520 01521 if (RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) != ERROR_SUCCESS) { 01522 ERR("unable to create key %s\n", debugstr_w(monitorsW)); 01523 return FALSE; 01524 } 01525 01526 if (RegCreateKeyExW(hroot, mi2w->pName, 0, NULL, REG_OPTION_NON_VOLATILE, 01527 KEY_WRITE | KEY_QUERY_VALUE, NULL, &hentry, 01528 &disposition) == ERROR_SUCCESS) { 01529 01530 /* Some installers set options for the port before calling AddMonitor. 01531 We query the "Driver" entry to verify that the monitor is installed, 01532 before we return an error. 01533 When a user installs two print monitors at the same time with the 01534 same name, a race condition is possible but silently ignored. */ 01535 01536 DWORD namesize = 0; 01537 01538 if ((disposition == REG_OPENED_EXISTING_KEY) && 01539 (RegQueryValueExW(hentry, driverW, NULL, NULL, NULL, 01540 &namesize) == ERROR_SUCCESS)) { 01541 TRACE("monitor %s already exists\n", debugstr_w(mi2w->pName)); 01542 /* 9x use ERROR_ALREADY_EXISTS */ 01543 SetLastError(ERROR_PRINT_MONITOR_ALREADY_INSTALLED); 01544 } 01545 else 01546 { 01547 INT len; 01548 len = (lstrlenW(mi2w->pDLLName) +1) * sizeof(WCHAR); 01549 res = (RegSetValueExW(hentry, driverW, 0, REG_SZ, 01550 (LPBYTE) mi2w->pDLLName, len) == ERROR_SUCCESS); 01551 } 01552 RegCloseKey(hentry); 01553 } 01554 01555 RegCloseKey(hroot); 01556 return (res); 01557 } 01558 01559 /****************************************************************************** 01560 * fpAddPort [exported through PRINTPROVIDOR] 01561 * 01562 * Add a Port for a specific Monitor 01563 * 01564 * PARAMS 01565 * pName [I] Servername or NULL (local Computer) 01566 * hWnd [I] Handle to parent Window for the Dialog-Box 01567 * pMonitorName [I] Name of the Monitor that manage the Port 01568 * 01569 * RETURNS 01570 * Success: TRUE 01571 * Failure: FALSE 01572 * 01573 */ 01574 static BOOL WINAPI fpAddPort(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName) 01575 { 01576 monitor_t * pm; 01577 monitor_t * pui; 01578 LONG lres; 01579 DWORD res; 01580 01581 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pMonitorName)); 01582 01583 lres = copy_servername_from_name(pName, NULL); 01584 if (lres) { 01585 FIXME("server %s not supported\n", debugstr_w(pName)); 01586 SetLastError(ERROR_INVALID_PARAMETER); 01587 return FALSE; 01588 } 01589 01590 /* an empty Monitorname is Invalid */ 01591 if (!pMonitorName[0]) { 01592 SetLastError(ERROR_NOT_SUPPORTED); 01593 return FALSE; 01594 } 01595 01596 pm = monitor_load(pMonitorName, NULL); 01597 if (pm && pm->monitor && pm->monitor->pfnAddPort) { 01598 res = pm->monitor->pfnAddPort(pName, hWnd, pMonitorName); 01599 TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname)); 01600 } 01601 else 01602 { 01603 pui = monitor_loadui(pm); 01604 if (pui && pui->monitorUI && pui->monitorUI->pfnAddPortUI) { 01605 res = pui->monitorUI->pfnAddPortUI(pName, hWnd, pMonitorName, NULL); 01606 TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pui->dllname)); 01607 } 01608 else 01609 { 01610 FIXME("not implemented for %s (monitor %p: %s / monitorui %p: %s)\n", 01611 debugstr_w(pMonitorName), pm, debugstr_w(pm ? pm->dllname : NULL), 01612 pui, debugstr_w(pui ? pui->dllname : NULL)); 01613 01614 SetLastError(ERROR_NOT_SUPPORTED); 01615 res = FALSE; 01616 } 01617 monitor_unload(pui); 01618 } 01619 monitor_unload(pm); 01620 01621 TRACE("returning %d with %u\n", res, GetLastError()); 01622 return res; 01623 } 01624 01625 /****************************************************************************** 01626 * fpAddPortEx [exported through PRINTPROVIDOR] 01627 * 01628 * Add a Port for a specific Monitor, without presenting a user interface 01629 * 01630 * PARAMS 01631 * pName [I] Servername or NULL (local Computer) 01632 * level [I] Structure-Level (1 or 2) for pBuffer 01633 * pBuffer [I] PTR to: PORT_INFO_1 or PORT_INFO_2 01634 * pMonitorName [I] Name of the Monitor that manage the Port 01635 * 01636 * RETURNS 01637 * Success: TRUE 01638 * Failure: FALSE 01639 * 01640 */ 01641 static BOOL WINAPI fpAddPortEx(LPWSTR pName, DWORD level, LPBYTE pBuffer, LPWSTR pMonitorName) 01642 { 01643 PORT_INFO_2W * pi2; 01644 monitor_t * pm; 01645 DWORD lres; 01646 DWORD res; 01647 01648 pi2 = (PORT_INFO_2W *) pBuffer; 01649 01650 TRACE("(%s, %d, %p, %s): %s %s %s\n", debugstr_w(pName), level, pBuffer, 01651 debugstr_w(pMonitorName), debugstr_w(pi2 ? pi2->pPortName : NULL), 01652 debugstr_w(((level > 1) && pi2) ? pi2->pMonitorName : NULL), 01653 debugstr_w(((level > 1) && pi2) ? pi2->pDescription : NULL)); 01654 01655 lres = copy_servername_from_name(pName, NULL); 01656 if (lres) { 01657 FIXME("server %s not supported\n", debugstr_w(pName)); 01658 SetLastError(ERROR_INVALID_PARAMETER); 01659 return FALSE; 01660 } 01661 01662 if ((level < 1) || (level > 2)) { 01663 SetLastError(ERROR_INVALID_LEVEL); 01664 return FALSE; 01665 } 01666 01667 if ((!pi2) || (!pMonitorName) || (!pMonitorName[0])) { 01668 SetLastError(ERROR_INVALID_PARAMETER); 01669 return FALSE; 01670 } 01671 01672 /* load the Monitor */ 01673 pm = monitor_load(pMonitorName, NULL); 01674 if (pm && pm->monitor && pm->monitor->pfnAddPortEx) { 01675 res = pm->monitor->pfnAddPortEx(pName, level, pBuffer, pMonitorName); 01676 TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname)); 01677 } 01678 else 01679 { 01680 FIXME("not implemented for %s (monitor %p: %s)\n", 01681 debugstr_w(pMonitorName), pm, pm ? debugstr_w(pm->dllname) : NULL); 01682 SetLastError(ERROR_INVALID_PARAMETER); 01683 res = FALSE; 01684 } 01685 monitor_unload(pm); 01686 return res; 01687 } 01688 01689 /****************************************************************************** 01690 * fpAddPrinterDriverEx [exported through PRINTPROVIDOR] 01691 * 01692 * Install a Printer Driver with the Option to upgrade / downgrade the Files 01693 * 01694 * PARAMS 01695 * pName [I] Servername or NULL (local Computer) 01696 * level [I] Level for the supplied DRIVER_INFO_*W struct 01697 * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter 01698 * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files 01699 * 01700 * RESULTS 01701 * Success: TRUE 01702 * Failure: FALSE 01703 * 01704 */ 01705 static BOOL WINAPI fpAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags) 01706 { 01707 LONG lres; 01708 01709 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags); 01710 lres = copy_servername_from_name(pName, NULL); 01711 if (lres) { 01712 FIXME("server %s not supported\n", debugstr_w(pName)); 01713 SetLastError(ERROR_ACCESS_DENIED); 01714 return FALSE; 01715 } 01716 01717 if ((dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY) != APD_COPY_ALL_FILES) { 01718 TRACE("Flags 0x%x ignored (using APD_COPY_ALL_FILES)\n", dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY); 01719 } 01720 01721 return myAddPrinterDriverEx(level, pDriverInfo, dwFileCopyFlags, TRUE); 01722 } 01723 01724 /****************************************************************************** 01725 * fpClosePrinter [exported through PRINTPROVIDOR] 01726 * 01727 * Close a printer handle and free associated resources 01728 * 01729 * PARAMS 01730 * hPrinter [I] Printerhandle to close 01731 * 01732 * RESULTS 01733 * Success: TRUE 01734 * Failure: FALSE 01735 * 01736 */ 01737 static BOOL WINAPI fpClosePrinter(HANDLE hPrinter) 01738 { 01739 printer_t *printer = (printer_t *) hPrinter; 01740 01741 TRACE("(%p)\n", hPrinter); 01742 01743 if (printer) { 01744 printer_free(printer); 01745 return TRUE; 01746 } 01747 return FALSE; 01748 } 01749 01750 /****************************************************************************** 01751 * fpConfigurePort [exported through PRINTPROVIDOR] 01752 * 01753 * Display the Configuration-Dialog for a specific Port 01754 * 01755 * PARAMS 01756 * pName [I] Servername or NULL (local Computer) 01757 * hWnd [I] Handle to parent Window for the Dialog-Box 01758 * pPortName [I] Name of the Port, that should be configured 01759 * 01760 * RETURNS 01761 * Success: TRUE 01762 * Failure: FALSE 01763 * 01764 */ 01765 static BOOL WINAPI fpConfigurePort(LPWSTR pName, HWND hWnd, LPWSTR pPortName) 01766 { 01767 monitor_t * pm; 01768 monitor_t * pui; 01769 LONG lres; 01770 DWORD res; 01771 01772 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName)); 01773 01774 lres = copy_servername_from_name(pName, NULL); 01775 if (lres) { 01776 FIXME("server %s not supported\n", debugstr_w(pName)); 01777 SetLastError(ERROR_INVALID_NAME); 01778 return FALSE; 01779 } 01780 01781 /* an empty Portname is Invalid, but can popup a Dialog */ 01782 if (!pPortName[0]) { 01783 SetLastError(ERROR_NOT_SUPPORTED); 01784 return FALSE; 01785 } 01786 01787 pm = monitor_load_by_port(pPortName); 01788 if (pm && pm->monitor && pm->monitor->pfnConfigurePort) { 01789 TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name), 01790 debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); 01791 res = pm->monitor->pfnConfigurePort(pName, hWnd, pPortName); 01792 TRACE("got %d with %u\n", res, GetLastError()); 01793 } 01794 else 01795 { 01796 pui = monitor_loadui(pm); 01797 if (pui && pui->monitorUI && pui->monitorUI->pfnConfigurePortUI) { 01798 TRACE("use %s for %s (monitorui %p: %s)\n", debugstr_w(pui->name), 01799 debugstr_w(pPortName), pui, debugstr_w(pui->dllname)); 01800 res = pui->monitorUI->pfnConfigurePortUI(pName, hWnd, pPortName); 01801 TRACE("got %d with %u\n", res, GetLastError()); 01802 } 01803 else 01804 { 01805 FIXME("not implemented for %s (monitor %p: %s / monitorui %p: %s)\n", 01806 debugstr_w(pPortName), pm, debugstr_w(pm ? pm->dllname : NULL), 01807 pui, debugstr_w(pui ? pui->dllname : NULL)); 01808 01809 SetLastError(ERROR_NOT_SUPPORTED); 01810 res = FALSE; 01811 } 01812 monitor_unload(pui); 01813 } 01814 monitor_unload(pm); 01815 01816 TRACE("returning %d with %u\n", res, GetLastError()); 01817 return res; 01818 } 01819 01820 /****************************************************************** 01821 * fpDeleteMonitor [exported through PRINTPROVIDOR] 01822 * 01823 * Delete a specific Printmonitor from a Printing-Environment 01824 * 01825 * PARAMS 01826 * pName [I] Servername or NULL (local Computer) 01827 * pEnvironment [I] Printing-Environment of the Monitor or NULL (Default) 01828 * pMonitorName [I] Name of the Monitor, that should be deleted 01829 * 01830 * RETURNS 01831 * Success: TRUE 01832 * Failure: FALSE 01833 * 01834 * NOTES 01835 * pEnvironment is ignored in Windows for the local Computer. 01836 * 01837 */ 01838 01839 static BOOL WINAPI fpDeleteMonitor(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName) 01840 { 01841 HKEY hroot = NULL; 01842 LONG lres; 01843 01844 TRACE("(%s, %s, %s)\n",debugstr_w(pName),debugstr_w(pEnvironment), 01845 debugstr_w(pMonitorName)); 01846 01847 lres = copy_servername_from_name(pName, NULL); 01848 if (lres) { 01849 FIXME("server %s not supported\n", debugstr_w(pName)); 01850 SetLastError(ERROR_INVALID_NAME); 01851 return FALSE; 01852 } 01853 01854 /* pEnvironment is ignored in Windows for the local Computer */ 01855 if (!pMonitorName || !pMonitorName[0]) { 01856 TRACE("pMonitorName %s is invalid\n", debugstr_w(pMonitorName)); 01857 SetLastError(ERROR_INVALID_PARAMETER); 01858 return FALSE; 01859 } 01860 01861 if(RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) != ERROR_SUCCESS) { 01862 ERR("unable to create key %s\n", debugstr_w(monitorsW)); 01863 return FALSE; 01864 } 01865 01866 if(RegDeleteTreeW(hroot, pMonitorName) == ERROR_SUCCESS) { 01867 TRACE("%s deleted\n", debugstr_w(pMonitorName)); 01868 RegCloseKey(hroot); 01869 return TRUE; 01870 } 01871 01872 TRACE("%s does not exist\n", debugstr_w(pMonitorName)); 01873 RegCloseKey(hroot); 01874 01875 /* NT: ERROR_UNKNOWN_PRINT_MONITOR (3000), 9x: ERROR_INVALID_PARAMETER (87) */ 01876 SetLastError(ERROR_UNKNOWN_PRINT_MONITOR); 01877 return FALSE; 01878 } 01879 01880 /***************************************************************************** 01881 * fpDeletePort [exported through PRINTPROVIDOR] 01882 * 01883 * Delete a specific Port 01884 * 01885 * PARAMS 01886 * pName [I] Servername or NULL (local Computer) 01887 * hWnd [I] Handle to parent Window for the Dialog-Box 01888 * pPortName [I] Name of the Port, that should be deleted 01889 * 01890 * RETURNS 01891 * Success: TRUE 01892 * Failure: FALSE 01893 * 01894 */ 01895 static BOOL WINAPI fpDeletePort(LPWSTR pName, HWND hWnd, LPWSTR pPortName) 01896 { 01897 monitor_t * pm; 01898 monitor_t * pui; 01899 LONG lres; 01900 DWORD res; 01901 01902 TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName)); 01903 01904 lres = copy_servername_from_name(pName, NULL); 01905 if (lres) { 01906 FIXME("server %s not supported\n", debugstr_w(pName)); 01907 SetLastError(ERROR_INVALID_NAME); 01908 return FALSE; 01909 } 01910 01911 /* an empty Portname is Invalid */ 01912 if (!pPortName[0]) { 01913 SetLastError(ERROR_NOT_SUPPORTED); 01914 return FALSE; 01915 } 01916 01917 pm = monitor_load_by_port(pPortName); 01918 if (pm && pm->monitor && pm->monitor->pfnDeletePort) { 01919 TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name), 01920 debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); 01921 res = pm->monitor->pfnDeletePort(pName, hWnd, pPortName); 01922 TRACE("got %d with %u\n", res, GetLastError()); 01923 } 01924 else 01925 { 01926 pui = monitor_loadui(pm); 01927 if (pui && pui->monitorUI && pui->monitorUI->pfnDeletePortUI) { 01928 TRACE("use %s for %s (monitorui %p: %s)\n", debugstr_w(pui->name), 01929 debugstr_w(pPortName), pui, debugstr_w(pui->dllname)); 01930 res = pui->monitorUI->pfnDeletePortUI(pName, hWnd, pPortName); 01931 TRACE("got %d with %u\n", res, GetLastError()); 01932 } 01933 else 01934 { 01935 FIXME("not implemented for %s (monitor %p: %s / monitorui %p: %s)\n", 01936 debugstr_w(pPortName), pm, debugstr_w(pm ? pm->dllname : NULL), 01937 pui, debugstr_w(pui ? pui->dllname : NULL)); 01938 01939 SetLastError(ERROR_NOT_SUPPORTED); 01940 res = FALSE; 01941 } 01942 monitor_unload(pui); 01943 } 01944 monitor_unload(pm); 01945 01946 TRACE("returning %d with %u\n", res, GetLastError()); 01947 return res; 01948 } 01949 01950 /***************************************************************************** 01951 * fpEnumMonitors [exported through PRINTPROVIDOR] 01952 * 01953 * Enumerate available Port-Monitors 01954 * 01955 * PARAMS 01956 * pName [I] Servername or NULL (local Computer) 01957 * Level [I] Structure-Level (1:Win9x+NT or 2:NT only) 01958 * pMonitors [O] PTR to Buffer that receives the Result 01959 * cbBuf [I] Size of Buffer at pMonitors 01960 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pMonitors 01961 * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors 01962 * 01963 * RETURNS 01964 * Success: TRUE 01965 * Failure: FALSE and in pcbNeeded the Bytes required for pMonitors, if cbBuf is too small 01966 * 01967 * NOTES 01968 * Windows reads the Registry once and cache the Results. 01969 * 01970 */ 01971 static BOOL WINAPI fpEnumMonitors(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf, 01972 LPDWORD pcbNeeded, LPDWORD pcReturned) 01973 { 01974 DWORD numentries = 0; 01975 DWORD needed = 0; 01976 LONG lres; 01977 BOOL res = FALSE; 01978 01979 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors, 01980 cbBuf, pcbNeeded, pcReturned); 01981 01982 lres = copy_servername_from_name(pName, NULL); 01983 if (lres) { 01984 FIXME("server %s not supported\n", debugstr_w(pName)); 01985 SetLastError(ERROR_INVALID_NAME); 01986 goto em_cleanup; 01987 } 01988 01989 if (!Level || (Level > 2)) { 01990 WARN("level (%d) is ignored in win9x\n", Level); 01991 SetLastError(ERROR_INVALID_LEVEL); 01992 return FALSE; 01993 } 01994 01995 /* Scan all Monitor-Keys */ 01996 numentries = 0; 01997 needed = get_local_monitors(Level, NULL, 0, &numentries); 01998 01999 /* we calculated the needed buffersize. now do more error-checks */ 02000 if (cbBuf < needed) { 02001 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02002 goto em_cleanup; 02003 } 02004 02005 /* fill the Buffer with the Monitor-Keys */ 02006 needed = get_local_monitors(Level, pMonitors, cbBuf, &numentries); 02007 res = TRUE; 02008 02009 em_cleanup: 02010 if (pcbNeeded) *pcbNeeded = needed; 02011 if (pcReturned) *pcReturned = numentries; 02012 02013 TRACE("returning %d with %d (%d byte for %d entries)\n", 02014 res, GetLastError(), needed, numentries); 02015 02016 return (res); 02017 } 02018 02019 /****************************************************************************** 02020 * fpEnumPorts [exported through PRINTPROVIDOR] 02021 * 02022 * Enumerate available Ports 02023 * 02024 * PARAMS 02025 * pName [I] Servername or NULL (local Computer) 02026 * Level [I] Structure-Level (1 or 2) 02027 * pPorts [O] PTR to Buffer that receives the Result 02028 * cbBuf [I] Size of Buffer at pPorts 02029 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts 02030 * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts 02031 * 02032 * RETURNS 02033 * Success: TRUE 02034 * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small 02035 * 02036 */ 02037 static BOOL WINAPI fpEnumPorts(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf, 02038 LPDWORD pcbNeeded, LPDWORD pcReturned) 02039 { 02040 DWORD needed = 0; 02041 DWORD numentries = 0; 02042 LONG lres; 02043 BOOL res = FALSE; 02044 02045 TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pPorts, 02046 cbBuf, pcbNeeded, pcReturned); 02047 02048 lres = copy_servername_from_name(pName, NULL); 02049 if (lres) { 02050 FIXME("server %s not supported\n", debugstr_w(pName)); 02051 SetLastError(ERROR_INVALID_NAME); 02052 goto emP_cleanup; 02053 } 02054 02055 if (!Level || (Level > 2)) { 02056 SetLastError(ERROR_INVALID_LEVEL); 02057 goto emP_cleanup; 02058 } 02059 02060 if (!pcbNeeded || (!pPorts && (cbBuf > 0))) { 02061 SetLastError(RPC_X_NULL_REF_POINTER); 02062 goto emP_cleanup; 02063 } 02064 02065 EnterCriticalSection(&monitor_handles_cs); 02066 monitor_loadall(); 02067 02068 /* Scan all local Ports */ 02069 numentries = 0; 02070 needed = get_ports_from_all_monitors(Level, NULL, 0, &numentries); 02071 02072 /* we calculated the needed buffersize. now do the error-checks */ 02073 if (cbBuf < needed) { 02074 monitor_unloadall(); 02075 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02076 goto emP_cleanup_cs; 02077 } 02078 else if (!pPorts || !pcReturned) { 02079 monitor_unloadall(); 02080 SetLastError(RPC_X_NULL_REF_POINTER); 02081 goto emP_cleanup_cs; 02082 } 02083 02084 /* Fill the Buffer */ 02085 needed = get_ports_from_all_monitors(Level, pPorts, cbBuf, &numentries); 02086 res = TRUE; 02087 monitor_unloadall(); 02088 02089 emP_cleanup_cs: 02090 LeaveCriticalSection(&monitor_handles_cs); 02091 02092 emP_cleanup: 02093 if (pcbNeeded) *pcbNeeded = needed; 02094 if (pcReturned) *pcReturned = (res) ? numentries : 0; 02095 02096 TRACE("returning %d with %d (%d byte for %d of %d entries)\n", 02097 (res), GetLastError(), needed, (res) ? numentries : 0, numentries); 02098 02099 return (res); 02100 } 02101 02102 /***************************************************************************** 02103 * fpEnumPrintProcessors [exported through PRINTPROVIDOR] 02104 * 02105 * Enumerate available Print Processors 02106 * 02107 * PARAMS 02108 * pName [I] Servername or NULL (local Computer) 02109 * pEnvironment [I] Printing-Environment or NULL (Default) 02110 * Level [I] Structure-Level (Only 1 is allowed) 02111 * pPPInfo [O] PTR to Buffer that receives the Result 02112 * cbBuf [I] Size of Buffer at pMonitors 02113 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPPInfo 02114 * pcReturned [O] PTR to DWORD that receives the number of Print Processors in pPPInfo 02115 * 02116 * RETURNS 02117 * Success: TRUE 02118 * Failure: FALSE and in pcbNeeded the Bytes required for pPPInfo, if cbBuf is too small 02119 * 02120 */ 02121 static BOOL WINAPI fpEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, 02122 LPBYTE pPPInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) 02123 { 02124 const printenv_t * env; 02125 LPWSTR regpathW = NULL; 02126 DWORD numentries = 0; 02127 DWORD needed = 0; 02128 LONG lres; 02129 BOOL res = FALSE; 02130 02131 TRACE("(%s, %s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), debugstr_w(pEnvironment), 02132 Level, pPPInfo, cbBuf, pcbNeeded, pcReturned); 02133 02134 lres = copy_servername_from_name(pName, NULL); 02135 if (lres) { 02136 FIXME("server %s not supported\n", debugstr_w(pName)); 02137 SetLastError(ERROR_INVALID_NAME); 02138 goto epp_cleanup; 02139 } 02140 02141 if (Level != 1) { 02142 SetLastError(ERROR_INVALID_LEVEL); 02143 goto epp_cleanup; 02144 } 02145 02146 env = validate_envW(pEnvironment); 02147 if (!env) 02148 goto epp_cleanup; /* ERROR_INVALID_ENVIRONMENT */ 02149 02150 regpathW = heap_alloc(sizeof(fmt_printprocessorsW) + 02151 (lstrlenW(env->envname) * sizeof(WCHAR))); 02152 02153 if (!regpathW) 02154 goto epp_cleanup; 02155 02156 wsprintfW(regpathW, fmt_printprocessorsW, env->envname); 02157 02158 /* Scan all Printprocessor-Keys */ 02159 numentries = 0; 02160 needed = get_local_printprocessors(regpathW, NULL, 0, &numentries); 02161 02162 /* we calculated the needed buffersize. now do more error-checks */ 02163 if (cbBuf < needed) { 02164 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02165 goto epp_cleanup; 02166 } 02167 02168 /* fill the Buffer with the Printprocessor Infos */ 02169 needed = get_local_printprocessors(regpathW, pPPInfo, cbBuf, &numentries); 02170 res = TRUE; 02171 02172 epp_cleanup: 02173 heap_free(regpathW); 02174 if (pcbNeeded) *pcbNeeded = needed; 02175 if (pcReturned) *pcReturned = numentries; 02176 02177 TRACE("returning %d with %d (%d byte for %d entries)\n", 02178 res, GetLastError(), needed, numentries); 02179 02180 return (res); 02181 } 02182 02183 /****************************************************************************** 02184 * fpGetPrintProcessorDirectory [exported through PRINTPROVIDOR] 02185 * 02186 * Return the PATH for the Print-Processors 02187 * 02188 * PARAMS 02189 * pName [I] Servername or NULL (this computer) 02190 * pEnvironment [I] Printing-Environment or NULL (Default) 02191 * level [I] Structure-Level (must be 1) 02192 * pPPInfo [O] PTR to Buffer that receives the Result 02193 * cbBuf [I] Size of Buffer at pPPInfo 02194 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPPInfo 02195 * 02196 * RETURNS 02197 * Success: TRUE 02198 * Failure: FALSE and in pcbNeeded the Bytes required for pPPInfo, if cbBuf is too small 02199 * 02200 * Native Values returned in pPPInfo on Success for this computer: 02201 *| NT(Windows x64): "%winsysdir%\\spool\\PRTPROCS\\x64" 02202 *| NT(Windows NT x86): "%winsysdir%\\spool\\PRTPROCS\\w32x86" 02203 *| NT(Windows 4.0): "%winsysdir%\\spool\\PRTPROCS\\win40" 02204 * 02205 * "%winsysdir%" is the Value from GetSystemDirectoryW() 02206 * 02207 */ 02208 static BOOL WINAPI fpGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD level, 02209 LPBYTE pPPInfo, DWORD cbBuf, LPDWORD pcbNeeded) 02210 { 02211 const printenv_t * env; 02212 DWORD needed; 02213 LONG lres; 02214 02215 TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName), debugstr_w(pEnvironment), 02216 level, pPPInfo, cbBuf, pcbNeeded); 02217 02218 *pcbNeeded = 0; 02219 lres = copy_servername_from_name(pName, NULL); 02220 if (lres) { 02221 FIXME("server %s not supported\n", debugstr_w(pName)); 02222 SetLastError(RPC_S_SERVER_UNAVAILABLE); 02223 return FALSE; 02224 } 02225 02226 env = validate_envW(pEnvironment); 02227 if (!env) 02228 return FALSE; /* ERROR_INVALID_ENVIRONMENT */ 02229 02230 /* GetSystemDirectoryW returns number of WCHAR including the '\0' */ 02231 needed = GetSystemDirectoryW(NULL, 0); 02232 /* add the Size for the Subdirectories */ 02233 needed += lstrlenW(spoolprtprocsW); 02234 needed += lstrlenW(env->subdir); 02235 needed *= sizeof(WCHAR); /* return-value is size in Bytes */ 02236 02237 *pcbNeeded = needed; 02238 02239 if (needed > cbBuf) { 02240 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02241 return FALSE; 02242 } 02243 02244 GetSystemDirectoryW((LPWSTR) pPPInfo, cbBuf/sizeof(WCHAR)); 02245 /* add the Subdirectories */ 02246 lstrcatW((LPWSTR) pPPInfo, spoolprtprocsW); 02247 lstrcatW((LPWSTR) pPPInfo, env->subdir); 02248 TRACE("==> %s\n", debugstr_w((LPWSTR) pPPInfo)); 02249 return TRUE; 02250 } 02251 02252 /****************************************************************************** 02253 * fpOpenPrinter [exported through PRINTPROVIDOR] 02254 * 02255 * Open a Printer / Printserver or a Printer-Object 02256 * 02257 * PARAMS 02258 * lpPrinterName [I] Name of Printserver, Printer, or Printer-Object 02259 * pPrinter [O] The resulting Handle is stored here 02260 * pDefaults [I] PTR to Default Printer Settings or NULL 02261 * 02262 * RETURNS 02263 * Success: TRUE 02264 * Failure: FALSE 02265 * 02266 * NOTES 02267 * lpPrinterName is one of: 02268 *| Printserver (NT only): "Servername" or NULL for the local Printserver 02269 *| Printer: "PrinterName" 02270 *| Printer-Object: "PrinterName,Job xxx" 02271 *| XcvMonitor: "Servername,XcvMonitor MonitorName" 02272 *| XcvPort: "Servername,XcvPort PortName" 02273 * 02274 * 02275 */ 02276 static BOOL WINAPI fpOpenPrinter(LPWSTR lpPrinterName, HANDLE *pPrinter, 02277 LPPRINTER_DEFAULTSW pDefaults) 02278 { 02279 02280 TRACE("(%s, %p, %p)\n", debugstr_w(lpPrinterName), pPrinter, pDefaults); 02281 02282 *pPrinter = printer_alloc_handle(lpPrinterName, pDefaults); 02283 02284 return (*pPrinter != 0); 02285 } 02286 02287 /****************************************************************************** 02288 * fpXcvData [exported through PRINTPROVIDOR] 02289 * 02290 * Execute commands in the Printmonitor DLL 02291 * 02292 * PARAMS 02293 * hXcv [i] Handle from fpOpenPrinter (with XcvMonitor or XcvPort) 02294 * pszDataName [i] Name of the command to execute 02295 * pInputData [i] Buffer for extra Input Data (needed only for some commands) 02296 * cbInputData [i] Size in Bytes of Buffer at pInputData 02297 * pOutputData [o] Buffer to receive additional Data (needed only for some commands) 02298 * cbOutputData [i] Size in Bytes of Buffer at pOutputData 02299 * pcbOutputNeeded [o] PTR to receive the minimal Size in Bytes of the Buffer at pOutputData 02300 * pdwStatus [o] PTR to receive the win32 error code from the Printmonitor DLL 02301 * 02302 * RETURNS 02303 * Success: TRUE 02304 * Failure: FALSE 02305 * 02306 * NOTES 02307 * Returning "TRUE" does mean, that the Printmonitor DLL was called successful. 02308 * The execution of the command can still fail (check pdwStatus for ERROR_SUCCESS). 02309 * 02310 * Minimal List of commands, that a Printmonitor DLL should support: 02311 * 02312 *| "MonitorUI" : Return the Name of the Userinterface-DLL as WSTR in pOutputData 02313 *| "AddPort" : Add a Port 02314 *| "DeletePort": Delete a Port 02315 * 02316 * Many Printmonitors support additional commands. Examples for localspl.dll: 02317 * "GetDefaultCommConfig", "SetDefaultCommConfig", 02318 * "GetTransmissionRetryTimeout", "ConfigureLPTPortCommandOK" 02319 * 02320 */ 02321 static BOOL WINAPI fpXcvData(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData, 02322 DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, 02323 PDWORD pcbOutputNeeded, PDWORD pdwStatus) 02324 { 02325 printer_t *printer = (printer_t * ) hXcv; 02326 02327 TRACE("(%p, %s, %p, %d, %p, %d, %p, %p)\n", hXcv, debugstr_w(pszDataName), 02328 pInputData, cbInputData, pOutputData, 02329 cbOutputData, pcbOutputNeeded, pdwStatus); 02330 02331 if (!printer || (!printer->hXcv)) { 02332 SetLastError(ERROR_INVALID_HANDLE); 02333 return FALSE; 02334 } 02335 02336 if (!pcbOutputNeeded) { 02337 SetLastError(ERROR_INVALID_PARAMETER); 02338 return FALSE; 02339 } 02340 02341 if (!pszDataName || !pdwStatus || (!pOutputData && (cbOutputData > 0))) { 02342 SetLastError(RPC_X_NULL_REF_POINTER); 02343 return FALSE; 02344 } 02345 02346 *pcbOutputNeeded = 0; 02347 02348 *pdwStatus = printer->pm->monitor->pfnXcvDataPort(printer->hXcv, pszDataName, 02349 pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded); 02350 02351 return TRUE; 02352 } 02353 02354 /***************************************************** 02355 * setup_provider [internal] 02356 */ 02357 void setup_provider(void) 02358 { 02359 static const PRINTPROVIDOR backend = { 02360 fpOpenPrinter, 02361 NULL, /* fpSetJob */ 02362 NULL, /* fpGetJob */ 02363 NULL, /* fpEnumJobs */ 02364 NULL, /* fpAddPrinter */ 02365 NULL, /* fpDeletePrinter */ 02366 NULL, /* fpSetPrinter */ 02367 NULL, /* fpGetPrinter */ 02368 NULL, /* fpEnumPrinters */ 02369 NULL, /* fpAddPrinterDriver */ 02370 NULL, /* fpEnumPrinterDrivers */ 02371 NULL, /* fpGetPrinterDriver */ 02372 fpGetPrinterDriverDirectory, 02373 NULL, /* fpDeletePrinterDriver */ 02374 NULL, /* fpAddPrintProcessor */ 02375 fpEnumPrintProcessors, 02376 fpGetPrintProcessorDirectory, 02377 NULL, /* fpDeletePrintProcessor */ 02378 NULL, /* fpEnumPrintProcessorDatatypes */ 02379 NULL, /* fpStartDocPrinter */ 02380 NULL, /* fpStartPagePrinter */ 02381 NULL, /* fpWritePrinter */ 02382 NULL, /* fpEndPagePrinter */ 02383 NULL, /* fpAbortPrinter */ 02384 NULL, /* fpReadPrinter */ 02385 NULL, /* fpEndDocPrinter */ 02386 NULL, /* fpAddJob */ 02387 NULL, /* fpScheduleJob */ 02388 NULL, /* fpGetPrinterData */ 02389 NULL, /* fpSetPrinterData */ 02390 NULL, /* fpWaitForPrinterChange */ 02391 fpClosePrinter, 02392 NULL, /* fpAddForm */ 02393 NULL, /* fpDeleteForm */ 02394 NULL, /* fpGetForm */ 02395 NULL, /* fpSetForm */ 02396 NULL, /* fpEnumForms */ 02397 fpEnumMonitors, 02398 fpEnumPorts, 02399 fpAddPort, 02400 fpConfigurePort, 02401 fpDeletePort, 02402 NULL, /* fpCreatePrinterIC */ 02403 NULL, /* fpPlayGdiScriptOnPrinterIC */ 02404 NULL, /* fpDeletePrinterIC */ 02405 NULL, /* fpAddPrinterConnection */ 02406 NULL, /* fpDeletePrinterConnection */ 02407 NULL, /* fpPrinterMessageBox */ 02408 fpAddMonitor, 02409 fpDeleteMonitor, 02410 NULL, /* fpResetPrinter */ 02411 NULL, /* fpGetPrinterDriverEx */ 02412 NULL, /* fpFindFirstPrinterChangeNotification */ 02413 NULL, /* fpFindClosePrinterChangeNotification */ 02414 fpAddPortEx, 02415 NULL, /* fpShutDown */ 02416 NULL, /* fpRefreshPrinterChangeNotification */ 02417 NULL, /* fpOpenPrinterEx */ 02418 NULL, /* fpAddPrinterEx */ 02419 NULL, /* fpSetPort */ 02420 NULL, /* fpEnumPrinterData */ 02421 NULL, /* fpDeletePrinterData */ 02422 NULL, /* fpClusterSplOpen */ 02423 NULL, /* fpClusterSplClose */ 02424 NULL, /* fpClusterSplIsAlive */ 02425 NULL, /* fpSetPrinterDataEx */ 02426 NULL, /* fpGetPrinterDataEx */ 02427 NULL, /* fpEnumPrinterDataEx */ 02428 NULL, /* fpEnumPrinterKey */ 02429 NULL, /* fpDeletePrinterDataEx */ 02430 NULL, /* fpDeletePrinterKey */ 02431 NULL, /* fpSeekPrinter */ 02432 NULL, /* fpDeletePrinterDriverEx */ 02433 NULL, /* fpAddPerMachineConnection */ 02434 NULL, /* fpDeletePerMachineConnection */ 02435 NULL, /* fpEnumPerMachineConnections */ 02436 fpXcvData, 02437 fpAddPrinterDriverEx, 02438 NULL, /* fpSplReadPrinter */ 02439 NULL, /* fpDriverUnloadComplete */ 02440 NULL, /* fpGetSpoolFileInfo */ 02441 NULL, /* fpCommitSpoolData */ 02442 NULL, /* fpCloseSpoolFileHandle */ 02443 NULL, /* fpFlushPrinter */ 02444 NULL, /* fpSendRecvBidiData */ 02445 NULL /* fpAddDriverCatalog */ 02446 }; 02447 pprovider = &backend; 02448 02449 } 02450 02451 /***************************************************** 02452 * InitializePrintProvidor (localspl.@) 02453 * 02454 * Initialize the Printprovider 02455 * 02456 * PARAMS 02457 * pPrintProvidor [I] Buffer to fill with a struct PRINTPROVIDOR 02458 * cbPrintProvidor [I] Size of Buffer in Bytes 02459 * pFullRegistryPath [I] Registry-Path for the Printprovidor 02460 * 02461 * RETURNS 02462 * Success: TRUE and pPrintProvidor filled 02463 * Failure: FALSE 02464 * 02465 * NOTES 02466 * The RegistryPath should be: 02467 * "System\CurrentControlSet\Control\Print\Providers<providername>", 02468 * but this Parameter is ignored in "localspl.dll". 02469 * 02470 */ 02471 02472 BOOL WINAPI InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, 02473 DWORD cbPrintProvidor, LPWSTR pFullRegistryPath) 02474 { 02475 02476 TRACE("(%p, %u, %s)\n", pPrintProvidor, cbPrintProvidor, debugstr_w(pFullRegistryPath)); 02477 memcpy(pPrintProvidor, pprovider, 02478 (cbPrintProvidor < sizeof(PRINTPROVIDOR)) ? cbPrintProvidor : sizeof(PRINTPROVIDOR)); 02479 02480 return TRUE; 02481 } Generated on Fri May 25 2012 04:19:42 for ReactOS by
1.7.6.1
|