dpnet: Assign to structs instead of using memcpy.
[wine.git] / dlls / localspl / localspl_main.c
blob77fb730bf3782b3d095ebc252f62b70eb9d95d87
1 /*
2 * Implementation of the Local Printmonitor
4 * Copyright 2006-2008 Detlef Riekenberg
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winreg.h"
30 #include "winspool.h"
31 #include "ddk/winsplp.h"
32 #include "winuser.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36 #include "localspl_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(localspl);
40 /* ############################### */
42 typedef struct {
43 WCHAR src[MAX_PATH+MAX_PATH];
44 WCHAR dst[MAX_PATH+MAX_PATH];
45 DWORD srclen;
46 DWORD dstlen;
47 DWORD copyflags;
48 BOOL lazy;
49 } apd_data_t;
51 typedef struct {
52 LPCWSTR envname;
53 LPCWSTR subdir;
54 DWORD driverversion;
55 LPCWSTR versionregpath;
56 LPCWSTR versionsubdir;
57 } printenv_t;
59 /* ############################### */
61 HINSTANCE LOCALSPL_hInstance = NULL;
63 static const PRINTPROVIDOR * pp = NULL;
66 static const WCHAR backslashW[] = {'\\',0};
67 static const WCHAR configuration_fileW[] = {'C','o','n','f','i','g','u','r','a','t','i','o','n',' ','F','i','l','e',0};
68 static const WCHAR datatypeW[] = {'D','a','t','a','t','y','p','e',0};
69 static const WCHAR data_fileW[] = {'D','a','t','a',' ','F','i','l','e',0};
70 static const WCHAR default_devmodeW[] = {'D','e','f','a','u','l','t',' ','D','e','v','M','o','d','e',0};
71 static const WCHAR dependent_filesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0};
72 static const WCHAR descriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
73 static const WCHAR driverW[] = {'D','r','i','v','e','r',0};
74 static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\',
75 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
76 'c','o','n','t','r','o','l','\\',
77 'P','r','i','n','t','\\',
78 'E','n','v','i','r','o','n','m','e','n','t','s','\\',
79 '%','s','\\','D','r','i','v','e','r','s','%','s',0 };
80 static const WCHAR hardwareidW[] = {'H','a','r','d','w','a','r','e','I','D',0};
81 static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0};
82 static const WCHAR locationW[] = {'L','o','c','a','t','i','o','n',0};
83 static const WCHAR manufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
84 static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0};
85 static const WCHAR monitorUIW[] = {'M','o','n','i','t','o','r','U','I',0};
86 static const WCHAR nameW[] = {'N','a','m','e',0};
87 static const WCHAR oem_urlW[] = {'O','E','M',' ','U','r','l',0};
88 static const WCHAR parametersW[] = {'P','a','r','a','m','e','t','e','r','s',0};
89 static const WCHAR portW[] = {'P','o','r','t',0};
90 static const WCHAR previous_namesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0};
91 static const WCHAR spooldriversW[] = {'\\','s','p','o','o','l','\\','d','r','i','v','e','r','s','\\',0};
92 static const WCHAR versionW[] = {'V','e','r','s','i','o','n',0};
94 static const WCHAR win40_envnameW[] = {'W','i','n','d','o','w','s',' ','4','.','0',0};
95 static const WCHAR win40_subdirW[] = {'w','i','n','4','0',0};
96 static const WCHAR version0_regpathW[] = {'\\','V','e','r','s','i','o','n','-','0',0};
97 static const WCHAR version0_subdirW[] = {'\\','0',0};
99 static const WCHAR x86_envnameW[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0};
100 static const WCHAR x86_subdirW[] = {'w','3','2','x','8','6',0};
101 static const WCHAR version3_regpathW[] = {'\\','V','e','r','s','i','o','n','-','3',0};
102 static const WCHAR version3_subdirW[] = {'\\','3',0};
105 static const printenv_t env_x86 = {x86_envnameW, x86_subdirW, 3,
106 version3_regpathW, version3_subdirW};
108 static const printenv_t env_win40 = {win40_envnameW, win40_subdirW, 0,
109 version0_regpathW, version0_subdirW};
111 static const printenv_t * const all_printenv[] = {&env_x86, &env_win40};
114 static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_2W),
115 sizeof(DRIVER_INFO_3W), sizeof(DRIVER_INFO_4W),
116 sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W),
117 0, sizeof(DRIVER_INFO_8W)};
119 /******************************************************************
120 * apd_copyfile [internal]
122 * Copy a file from the driverdirectory to the versioned directory
124 * RETURNS
125 * Success: TRUE
126 * Failure: FALSE
129 static BOOL apd_copyfile(LPWSTR filename, apd_data_t *apd)
131 LPWSTR ptr;
132 LPWSTR srcname;
133 DWORD res;
135 apd->src[apd->srclen] = '\0';
136 apd->dst[apd->dstlen] = '\0';
138 if (!filename || !filename[0]) {
139 /* nothing to copy */
140 return TRUE;
143 ptr = strrchrW(filename, '\\');
144 if (ptr) {
145 ptr++;
147 else
149 ptr = filename;
152 if (apd->copyflags & APD_COPY_FROM_DIRECTORY) {
153 /* we have an absolute Path */
154 srcname = filename;
156 else
158 srcname = apd->src;
159 lstrcatW(srcname, ptr);
161 lstrcatW(apd->dst, ptr);
163 TRACE("%s => %s\n", debugstr_w(filename), debugstr_w(apd->dst));
165 /* FIXME: handle APD_COPY_NEW_FILES */
166 res = CopyFileW(srcname, apd->dst, FALSE);
167 TRACE("got %u with %u\n", res, GetLastError());
169 return (apd->lazy) ? TRUE : res;
172 /******************************************************************
173 * copy_servername_from_name (internal)
175 * for an external server, the serverpart from the name is copied.
177 * RETURNS
178 * the length (in WCHAR) of the serverpart (0 for the local computer)
179 * (-length), when the name is to long
182 static LONG copy_servername_from_name(LPCWSTR name, LPWSTR target)
184 LPCWSTR server;
185 LPWSTR ptr;
186 WCHAR buffer[MAX_COMPUTERNAME_LENGTH +1];
187 DWORD len;
188 DWORD serverlen;
190 if (target) *target = '\0';
192 if (name == NULL) return 0;
193 if ((name[0] != '\\') || (name[1] != '\\')) return 0;
195 server = &name[2];
196 /* skip over both backslash, find separator '\' */
197 ptr = strchrW(server, '\\');
198 serverlen = (ptr) ? ptr - server : lstrlenW(server);
200 /* servername is empty or to long */
201 if (serverlen == 0) return 0;
203 TRACE("found %s\n", debugstr_wn(server, serverlen));
205 if (serverlen > MAX_COMPUTERNAME_LENGTH) return -serverlen;
207 len = sizeof(buffer) / sizeof(buffer[0]);
208 if (GetComputerNameW(buffer, &len)) {
209 if ((serverlen == len) && (strncmpiW(server, buffer, len) == 0)) {
210 /* The requested Servername is our computername */
211 if (target) {
212 memcpy(target, server, serverlen * sizeof(WCHAR));
213 target[serverlen] = '\0';
215 return serverlen;
218 return 0;
221 /******************************************************************
222 * Return the number of bytes for an multi_sz string.
223 * The result includes all \0s
224 * (specifically the extra \0, that is needed as multi_sz terminator).
226 static int multi_sz_lenW(const WCHAR *str)
228 const WCHAR *ptr = str;
229 if (!str) return 0;
232 ptr += lstrlenW(ptr) + 1;
233 } while (*ptr);
235 return (ptr - str + 1) * sizeof(WCHAR);
238 /******************************************************************
239 * validate_envW [internal]
241 * validate the user-supplied printing-environment
243 * PARAMS
244 * env [I] PTR to Environment-String or NULL
246 * RETURNS
247 * Success: PTR to printenv_t
248 * Failure: NULL and ERROR_INVALID_ENVIRONMENT
250 * NOTES
251 * An empty string is handled the same way as NULL.
255 static const printenv_t * validate_envW(LPCWSTR env)
257 const printenv_t *result = NULL;
258 unsigned int i;
260 TRACE("(%s)\n", debugstr_w(env));
261 if (env && env[0])
263 for (i = 0; i < sizeof(all_printenv)/sizeof(all_printenv[0]); i++)
265 if (lstrcmpiW(env, all_printenv[i]->envname) == 0)
267 result = all_printenv[i];
268 break;
271 if (result == NULL) {
272 FIXME("unsupported Environment: %s\n", debugstr_w(env));
273 SetLastError(ERROR_INVALID_ENVIRONMENT);
275 /* on win9x, only "Windows 4.0" is allowed, but we ignore this */
277 else
279 result = (GetVersion() & 0x80000000) ? &env_win40 : &env_x86;
282 TRACE("=> using %p: %s\n", result, debugstr_w(result ? result->envname : NULL));
283 return result;
286 /*****************************************************************************
287 * open_driver_reg [internal]
289 * opens the registry for the printer drivers depending on the given input
290 * variable pEnvironment
292 * RETURNS:
293 * Success: the opened hkey
294 * Failure: NULL
296 static HKEY open_driver_reg(LPCWSTR pEnvironment)
298 HKEY retval = NULL;
299 LPWSTR buffer;
300 const printenv_t * env;
302 TRACE("(%s)\n", debugstr_w(pEnvironment));
304 env = validate_envW(pEnvironment);
305 if (!env) return NULL;
307 buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(fmt_driversW) +
308 (lstrlenW(env->envname) + lstrlenW(env->versionregpath)) * sizeof(WCHAR));
310 if (buffer) {
311 wsprintfW(buffer, fmt_driversW, env->envname, env->versionregpath);
312 RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval);
313 HeapFree(GetProcessHeap(), 0, buffer);
315 return retval;
318 /*****************************************************************************
319 * fpGetPrinterDriverDirectory [exported through PRINTPROVIDOR]
321 * Return the PATH for the Printer-Drivers
323 * PARAMS
324 * pName [I] Servername (NT only) or NULL (local Computer)
325 * pEnvironment [I] Printing-Environment (see below) or NULL (Default)
326 * Level [I] Structure-Level (must be 1)
327 * pDriverDirectory [O] PTR to Buffer that receives the Result
328 * cbBuf [I] Size of Buffer at pDriverDirectory
329 * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used /
330 * required for pDriverDirectory
332 * RETURNS
333 * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory
334 * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory,
335 * if cbBuf is too small
337 * Native Values returned in pDriverDirectory on Success:
338 *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86"
339 *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40"
340 *| win9x(Windows 4.0): "%winsysdir%"
342 * "%winsysdir%" is the Value from GetSystemDirectoryW()
345 static BOOL WINAPI fpGetPrinterDriverDirectory(LPWSTR pName, LPWSTR pEnvironment,
346 DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded)
348 DWORD needed;
349 const printenv_t * env;
351 TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName),
352 debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded);
354 if (pName != NULL && pName[0]) {
355 FIXME("server %s not supported\n", debugstr_w(pName));
356 SetLastError(ERROR_INVALID_PARAMETER);
357 return FALSE;
360 env = validate_envW(pEnvironment);
361 if (!env) return FALSE; /* pEnvironment invalid or unsupported */
364 /* GetSystemDirectoryW returns number of WCHAR including the '\0' */
365 needed = GetSystemDirectoryW(NULL, 0);
366 /* add the Size for the Subdirectories */
367 needed += lstrlenW(spooldriversW);
368 needed += lstrlenW(env->subdir);
369 needed *= sizeof(WCHAR); /* return-value is size in Bytes */
371 *pcbNeeded = needed;
373 if (needed > cbBuf) {
374 SetLastError(ERROR_INSUFFICIENT_BUFFER);
375 return FALSE;
378 if (pDriverDirectory == NULL) {
379 /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */
380 SetLastError(ERROR_INVALID_USER_BUFFER);
381 return FALSE;
384 GetSystemDirectoryW((LPWSTR) pDriverDirectory, cbBuf/sizeof(WCHAR));
385 /* add the Subdirectories */
386 lstrcatW((LPWSTR) pDriverDirectory, spooldriversW);
387 lstrcatW((LPWSTR) pDriverDirectory, env->subdir);
389 TRACE("=> %s\n", debugstr_w((LPWSTR) pDriverDirectory));
390 return TRUE;
393 /******************************************************************************
394 * myAddPrinterDriverEx [internal]
396 * Install a Printer Driver with the Option to upgrade / downgrade the Files
397 * and a special mode with lazy error ckecking
400 static BOOL WINAPI myAddPrinterDriverEx(DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags, BOOL lazy)
402 const printenv_t *env;
403 apd_data_t apd;
404 DRIVER_INFO_8W di;
405 LPWSTR ptr;
406 HKEY hroot;
407 HKEY hdrv;
408 DWORD disposition;
409 DWORD len;
410 LONG lres;
412 /* we need to set all entries in the Registry, independent from the Level of
413 DRIVER_INFO, that the caller supplied */
415 ZeroMemory(&di, sizeof(di));
416 if (pDriverInfo && (level < (sizeof(di_sizeof) / sizeof(di_sizeof[0])))) {
417 memcpy(&di, pDriverInfo, di_sizeof[level]);
420 /* dump the most used infos */
421 TRACE("%p: .cVersion : 0x%x/%d\n", pDriverInfo, di.cVersion, di.cVersion);
422 TRACE("%p: .pName : %s\n", di.pName, debugstr_w(di.pName));
423 TRACE("%p: .pEnvironment: %s\n", di.pEnvironment, debugstr_w(di.pEnvironment));
424 TRACE("%p: .pDriverPath : %s\n", di.pDriverPath, debugstr_w(di.pDriverPath));
425 TRACE("%p: .pDataFile : %s\n", di.pDataFile, debugstr_w(di.pDataFile));
426 TRACE("%p: .pConfigFile : %s\n", di.pConfigFile, debugstr_w(di.pConfigFile));
427 TRACE("%p: .pHelpFile : %s\n", di.pHelpFile, debugstr_w(di.pHelpFile));
428 /* dump only the first of the additional Files */
429 TRACE("%p: .pDependentFiles: %s\n", di.pDependentFiles, debugstr_w(di.pDependentFiles));
432 /* check environment */
433 env = validate_envW(di.pEnvironment);
434 if (env == NULL) return FALSE; /* ERROR_INVALID_ENVIRONMENT */
436 /* fill the copy-data / get the driverdir */
437 len = sizeof(apd.src) - sizeof(version3_subdirW) - sizeof(WCHAR);
438 if (!fpGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1,
439 (LPBYTE) apd.src, len, &len)) {
440 /* Should never Fail */
441 return FALSE;
443 memcpy(apd.dst, apd.src, len);
444 lstrcatW(apd.src, backslashW);
445 apd.srclen = lstrlenW(apd.src);
446 lstrcatW(apd.dst, env->versionsubdir);
447 lstrcatW(apd.dst, backslashW);
448 apd.dstlen = lstrlenW(apd.dst);
449 apd.copyflags = dwFileCopyFlags;
450 apd.lazy = lazy;
451 CreateDirectoryW(apd.src, NULL);
452 CreateDirectoryW(apd.dst, NULL);
454 hroot = open_driver_reg(env->envname);
455 if (!hroot) {
456 ERR("Can't create Drivers key\n");
457 return FALSE;
460 /* Fill the Registry for the Driver */
461 if ((lres = RegCreateKeyExW(hroot, di.pName, 0, NULL, REG_OPTION_NON_VOLATILE,
462 KEY_WRITE | KEY_QUERY_VALUE, NULL,
463 &hdrv, &disposition)) != ERROR_SUCCESS) {
465 ERR("can't create driver %s: %u\n", debugstr_w(di.pName), lres);
466 RegCloseKey(hroot);
467 SetLastError(lres);
468 return FALSE;
470 RegCloseKey(hroot);
472 if (disposition == REG_OPENED_EXISTING_KEY) {
473 TRACE("driver %s already installed\n", debugstr_w(di.pName));
474 RegCloseKey(hdrv);
475 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
476 return FALSE;
479 /* Verified with the Adobe PS Driver, that w2k does not use di.Version */
480 RegSetValueExW(hdrv, versionW, 0, REG_DWORD, (LPBYTE) &env->driverversion,
481 sizeof(DWORD));
483 RegSetValueExW(hdrv, driverW, 0, REG_SZ, (LPBYTE) di.pDriverPath,
484 (lstrlenW(di.pDriverPath)+1)* sizeof(WCHAR));
485 apd_copyfile(di.pDriverPath, &apd);
487 RegSetValueExW(hdrv, data_fileW, 0, REG_SZ, (LPBYTE) di.pDataFile,
488 (lstrlenW(di.pDataFile)+1)* sizeof(WCHAR));
489 apd_copyfile(di.pDataFile, &apd);
491 RegSetValueExW(hdrv, configuration_fileW, 0, REG_SZ, (LPBYTE) di.pConfigFile,
492 (lstrlenW(di.pConfigFile)+1)* sizeof(WCHAR));
493 apd_copyfile(di.pConfigFile, &apd);
495 /* settings for level 3 */
496 RegSetValueExW(hdrv, help_fileW, 0, REG_SZ, (LPBYTE) di.pHelpFile,
497 di.pHelpFile ? (lstrlenW(di.pHelpFile)+1)* sizeof(WCHAR) : 0);
498 apd_copyfile(di.pHelpFile, &apd);
501 ptr = di.pDependentFiles;
502 RegSetValueExW(hdrv, dependent_filesW, 0, REG_MULTI_SZ, (LPBYTE) di.pDependentFiles,
503 di.pDependentFiles ? multi_sz_lenW(di.pDependentFiles) : 0);
504 while ((ptr != NULL) && (ptr[0])) {
505 if (apd_copyfile(ptr, &apd)) {
506 ptr += lstrlenW(ptr) + 1;
508 else
510 WARN("Failed to copy %s\n", debugstr_w(ptr));
511 ptr = NULL;
514 /* The language-Monitor was already copied by the caller to "%SystemRoot%\system32" */
515 RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (LPBYTE) di.pMonitorName,
516 di.pMonitorName ? (lstrlenW(di.pMonitorName)+1)* sizeof(WCHAR) : 0);
518 RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (LPBYTE) di.pDefaultDataType,
519 di.pDefaultDataType ? (lstrlenW(di.pDefaultDataType)+1)* sizeof(WCHAR) : 0);
521 /* settings for level 4 */
522 RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (LPBYTE) di.pszzPreviousNames,
523 di.pszzPreviousNames ? multi_sz_lenW(di.pszzPreviousNames) : 0);
525 if (level > 5) TRACE("level %u for Driver %s is incomplete\n", level, debugstr_w(di.pName));
527 RegCloseKey(hdrv);
528 TRACE("### DrvDriverEvent(...,DRIVEREVENT_INITIALIZE) not implemented yet\n");
530 TRACE("=> TRUE with %u\n", GetLastError());
531 return TRUE;
535 /******************************************************************************
536 * fpAddPrinterDriverEx [exported through PRINTPROVIDOR]
538 * Install a Printer Driver with the Option to upgrade / downgrade the Files
540 * PARAMS
541 * pName [I] Servername or NULL (local Computer)
542 * level [I] Level for the supplied DRIVER_INFO_*W struct
543 * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter
544 * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files
546 * RESULTS
547 * Success: TRUE
548 * Failure: FALSE
551 static BOOL WINAPI fpAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags)
553 LONG lres;
555 TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags);
556 lres = copy_servername_from_name(pName, NULL);
557 if (lres) {
558 FIXME("server %s not supported\n", debugstr_w(pName));
559 SetLastError(ERROR_ACCESS_DENIED);
560 return FALSE;
563 if ((dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY) != APD_COPY_ALL_FILES) {
564 TRACE("Flags 0x%x ignored (using APD_COPY_ALL_FILES)\n", dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY);
567 return myAddPrinterDriverEx(level, pDriverInfo, dwFileCopyFlags, TRUE);
570 /*****************************************************
571 * get_backend [internal]
573 static const PRINTPROVIDOR * get_backend(void)
575 static const PRINTPROVIDOR backend = {
576 NULL, /* fpOpenPrinter */
577 NULL, /* fpSetJob */
578 NULL, /* fpGetJob */
579 NULL, /* fpEnumJobs */
580 NULL, /* fpAddPrinter */
581 NULL, /* fpDeletePrinter */
582 NULL, /* fpSetPrinter */
583 NULL, /* fpGetPrinter */
584 NULL, /* fpEnumPrinters */
585 NULL, /* fpAddPrinterDriver */
586 NULL, /* fpEnumPrinterDrivers */
587 NULL, /* fpGetPrinterDriver */
588 fpGetPrinterDriverDirectory,
589 NULL, /* fpDeletePrinterDriver */
590 NULL, /* fpAddPrintProcessor */
591 NULL, /* fpEnumPrintProcessors */
592 NULL, /* fpGetPrintProcessorDirectory */
593 NULL, /* fpDeletePrintProcessor */
594 NULL, /* fpEnumPrintProcessorDatatypes */
595 NULL, /* fpStartDocPrinter */
596 NULL, /* fpStartPagePrinter */
597 NULL, /* fpWritePrinter */
598 NULL, /* fpEndPagePrinter */
599 NULL, /* fpAbortPrinter */
600 NULL, /* fpReadPrinter */
601 NULL, /* fpEndDocPrinter */
602 NULL, /* fpAddJob */
603 NULL, /* fpScheduleJob */
604 NULL, /* fpGetPrinterData */
605 NULL, /* fpSetPrinterData */
606 NULL, /* fpWaitForPrinterChange */
607 NULL, /* fpClosePrinter */
608 NULL, /* fpAddForm */
609 NULL, /* fpDeleteForm */
610 NULL, /* fpGetForm */
611 NULL, /* fpSetForm */
612 NULL, /* fpEnumForms */
613 NULL, /* fpEnumMonitors */
614 NULL, /* fpEnumPorts */
615 NULL, /* fpAddPort */
616 NULL, /* fpConfigurePort */
617 NULL, /* fpDeletePort */
618 NULL, /* fpCreatePrinterIC */
619 NULL, /* fpPlayGdiScriptOnPrinterIC */
620 NULL, /* fpDeletePrinterIC */
621 NULL, /* fpAddPrinterConnection */
622 NULL, /* fpDeletePrinterConnection */
623 NULL, /* fpPrinterMessageBox */
624 NULL, /* fpAddMonitor */
625 NULL, /* fpDeleteMonitor */
626 NULL, /* fpResetPrinter */
627 NULL, /* fpGetPrinterDriverEx */
628 NULL, /* fpFindFirstPrinterChangeNotification */
629 NULL, /* fpFindClosePrinterChangeNotification */
630 NULL, /* fpAddPortEx */
631 NULL, /* fpShutDown */
632 NULL, /* fpRefreshPrinterChangeNotification */
633 NULL, /* fpOpenPrinterEx */
634 NULL, /* fpAddPrinterEx */
635 NULL, /* fpSetPort */
636 NULL, /* fpEnumPrinterData */
637 NULL, /* fpDeletePrinterData */
638 NULL, /* fpClusterSplOpen */
639 NULL, /* fpClusterSplClose */
640 NULL, /* fpClusterSplIsAlive */
641 NULL, /* fpSetPrinterDataEx */
642 NULL, /* fpGetPrinterDataEx */
643 NULL, /* fpEnumPrinterDataEx */
644 NULL, /* fpEnumPrinterKey */
645 NULL, /* fpDeletePrinterDataEx */
646 NULL, /* fpDeletePrinterKey */
647 NULL, /* fpSeekPrinter */
648 NULL, /* fpDeletePrinterDriverEx */
649 NULL, /* fpAddPerMachineConnection */
650 NULL, /* fpDeletePerMachineConnection */
651 NULL, /* fpEnumPerMachineConnections */
652 NULL, /* fpXcvData */
653 fpAddPrinterDriverEx,
654 NULL, /* fpSplReadPrinter */
655 NULL, /* fpDriverUnloadComplete */
656 NULL, /* fpGetSpoolFileInfo */
657 NULL, /* fpCommitSpoolData */
658 NULL, /* fpCloseSpoolFileHandle */
659 NULL, /* fpFlushPrinter */
660 NULL, /* fpSendRecvBidiData */
661 NULL /* fpAddDriverCatalog */
663 TRACE("=> %p\n", &backend);
664 return &backend;
668 /*****************************************************
669 * DllMain
671 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
673 TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved);
675 switch(fdwReason)
677 case DLL_WINE_PREATTACH:
678 return FALSE; /* prefer native version */
680 case DLL_PROCESS_ATTACH:
681 DisableThreadLibraryCalls( hinstDLL );
682 LOCALSPL_hInstance = hinstDLL;
683 pp = get_backend();
684 break;
686 return TRUE;
690 /*****************************************************
691 * InitializePrintProvidor (localspl.@)
693 * Initialize the Printprovider
695 * PARAMS
696 * pPrintProvidor [I] Buffer to fill with a struct PRINTPROVIDOR
697 * cbPrintProvidor [I] Size of Buffer in Bytes
698 * pFullRegistryPath [I] Registry-Path for the Printprovidor
700 * RETURNS
701 * Success: TRUE and pPrintProvidor filled
702 * Failure: FALSE
704 * NOTES
705 * The RegistryPath should be:
706 * "System\CurrentControlSet\Control\Print\Providers\<providername>",
707 * but this Parameter is ignored in "localspl.dll".
711 BOOL WINAPI InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor,
712 DWORD cbPrintProvidor, LPWSTR pFullRegistryPath)
715 TRACE("(%p, %u, %s)\n", pPrintProvidor, cbPrintProvidor, debugstr_w(pFullRegistryPath));
716 memcpy(pPrintProvidor, pp, (cbPrintProvidor < sizeof(PRINTPROVIDOR)) ? cbPrintProvidor : sizeof(PRINTPROVIDOR));
718 return TRUE;