msvcrt: Use EOF from public header.
[wine/zf.git] / dlls / gdi.exe16 / printdrv.c
blobb0e1e31600803b2a77affb87e5e1fb677a15fa2a
1 /*
2 * Implementation of some printer driver bits
4 * Copyright 1996 John Harvey
5 * Copyright 1998 Huw Davies
6 * Copyright 1998 Andreas Mohr
7 * Copyright 1999 Klaas van Gend
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <signal.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "wine/winbase16.h"
34 #include "wine/wingdi16.h"
35 #include "winspool.h"
36 #include "winerror.h"
37 #include "winreg.h"
38 #include "wownt32.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(print);
43 static const char PrinterModel[] = "Printer Model";
44 static const char DefaultDevMode[] = "Default DevMode";
45 static const char PrinterDriverData[] = "PrinterDriverData";
46 static const char Printers[] = "System\\CurrentControlSet\\Control\\Print\\Printers\\";
48 /****************** misc. printer related functions */
51 * The following function should implement a queuing system
53 struct hpq
55 struct hpq *next;
56 int tag;
57 int key;
60 static struct hpq *hpqueue;
62 /**********************************************************************
63 * CreatePQ (GDI.230)
66 HPQ16 WINAPI CreatePQ16(INT16 size)
68 #if 0
69 HGLOBAL16 hpq = 0;
70 WORD tmp_size;
71 LPWORD pPQ;
73 tmp_size = size << 2;
74 if (!(hpq = GlobalAlloc16(GMEM_SHARE|GMEM_MOVEABLE, tmp_size + 8)))
75 return 0xffff;
76 pPQ = GlobalLock16(hpq);
77 *pPQ++ = 0;
78 *pPQ++ = tmp_size;
79 *pPQ++ = 0;
80 *pPQ++ = 0;
81 GlobalUnlock16(hpq);
83 return (HPQ16)hpq;
84 #else
85 FIXME("(%d): stub\n",size);
86 return 1;
87 #endif
90 /**********************************************************************
91 * DeletePQ (GDI.235)
94 INT16 WINAPI DeletePQ16(HPQ16 hPQ)
96 return GlobalFree16(hPQ);
99 /**********************************************************************
100 * ExtractPQ (GDI.232)
103 INT16 WINAPI ExtractPQ16(HPQ16 hPQ)
105 struct hpq *queue, *prev, *current, *currentPrev;
106 int key = 0, tag = -1;
107 prev = NULL;
108 queue = current = hpqueue;
109 if (current)
110 key = current->key;
112 while (current)
114 currentPrev = current;
115 current = current->next;
116 if (current)
118 if (current->key < key)
120 queue = current;
121 prev = currentPrev;
125 if (queue)
127 tag = queue->tag;
129 if (prev)
130 prev->next = queue->next;
131 else
132 hpqueue = queue->next;
133 HeapFree(GetProcessHeap(), 0, queue);
136 TRACE("%x got tag %d key %d\n", hPQ, tag, key);
138 return tag;
141 /**********************************************************************
142 * InsertPQ (GDI.233)
145 INT16 WINAPI InsertPQ16(HPQ16 hPQ, INT16 tag, INT16 key)
147 struct hpq *queueItem = HeapAlloc(GetProcessHeap(), 0, sizeof(struct hpq));
148 if(queueItem == NULL) {
149 ERR("Memory exhausted!\n");
150 return FALSE;
152 queueItem->next = hpqueue;
153 hpqueue = queueItem;
154 queueItem->key = key;
155 queueItem->tag = tag;
157 FIXME("(%x %d %d): stub???\n", hPQ, tag, key);
158 return TRUE;
161 /**********************************************************************
162 * MinPQ (GDI.231)
165 INT16 WINAPI MinPQ16(HPQ16 hPQ)
167 FIXME("(%x): stub\n", hPQ);
168 return 0;
171 /**********************************************************************
172 * SizePQ (GDI.234)
175 INT16 WINAPI SizePQ16(HPQ16 hPQ, INT16 sizechange)
177 FIXME("(%x %d): stub\n", hPQ, sizechange);
178 return -1;
184 * The following functions implement part of the spooling process to
185 * print manager. I would like to see wine have a version of print managers
186 * that used LPR/LPD. For simplicity print jobs will be sent to a file for
187 * now.
189 typedef struct PRINTJOB
191 HDC16 hDC;
192 HANDLE16 hHandle;
193 int nIndex;
194 int id;
195 } PRINTJOB, *PPRINTJOB;
197 #define MAX_PRINT_JOBS 1
198 #define SP_OK 1
200 static PPRINTJOB gPrintJobsTable[MAX_PRINT_JOBS];
203 static PPRINTJOB FindPrintJobFromHandle(HANDLE16 hHandle)
205 return gPrintJobsTable[0];
208 /**********************************************************************
209 * OpenJob (GDI.240)
212 HPJOB16 WINAPI OpenJob16(LPCSTR lpOutput, LPCSTR lpTitle, HDC16 hDC)
214 HPJOB16 hHandle = (HPJOB16)SP_ERROR;
215 PPRINTJOB pPrintJob;
217 TRACE("'%s' '%s' %04x\n", lpOutput, lpTitle, hDC);
219 pPrintJob = gPrintJobsTable[0];
220 if (pPrintJob == NULL)
222 DOCINFOA info = { sizeof(info), lpTitle, lpOutput, NULL, 0 };
223 int id;
225 id = StartDocA( HDC_32(hDC), &info );
226 if (id > 0)
228 pPrintJob = HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTJOB));
229 if(pPrintJob == NULL) {
230 WARN("Memory exhausted!\n");
231 return hHandle;
234 hHandle = 1;
236 pPrintJob->hDC = hDC;
237 pPrintJob->id = id;
238 pPrintJob->nIndex = 0;
239 pPrintJob->hHandle = hHandle;
240 gPrintJobsTable[pPrintJob->nIndex] = pPrintJob;
243 TRACE("return %04x\n", hHandle);
244 return hHandle;
247 /**********************************************************************
248 * CloseJob (GDI.243)
251 INT16 WINAPI CloseJob16(HPJOB16 hJob)
253 int nRet = SP_ERROR;
254 PPRINTJOB pPrintJob;
256 TRACE("%04x\n", hJob);
258 pPrintJob = FindPrintJobFromHandle(hJob);
259 if (pPrintJob != NULL) nRet = EndDoc( HDC_32(pPrintJob->hDC) );
260 return nRet;
263 /**********************************************************************
264 * WriteSpool (GDI.241)
267 INT16 WINAPI WriteSpool16(HPJOB16 hJob, LPSTR lpData, INT16 cch)
269 int nRet = SP_ERROR;
270 PPRINTJOB pPrintJob;
272 TRACE("%04x %p %04x\n", hJob, lpData, cch);
274 pPrintJob = FindPrintJobFromHandle(hJob);
275 if (pPrintJob != NULL && cch)
277 WORD *data = HeapAlloc( GetProcessHeap(), 0, cch + 2 );
279 if (!data) return SP_OUTOFDISK;
280 *data = cch;
281 memcpy( data + 1, lpData, cch );
282 ExtEscape( HDC_32(pPrintJob->hDC), PASSTHROUGH, cch + 2, (char *)data, 0, NULL );
283 HeapFree( GetProcessHeap(), 0, data );
284 nRet = cch;
286 return nRet;
289 typedef INT (WINAPI *MSGBOX_PROC)( HWND, LPCSTR, LPCSTR, UINT );
291 /**********************************************************************
292 * WriteDialog (GDI.242)
295 INT16 WINAPI WriteDialog16(HPJOB16 hJob, LPSTR lpMsg, INT16 cchMsg)
297 HMODULE mod;
298 MSGBOX_PROC pMessageBoxA;
299 INT16 ret = 0;
301 TRACE("%04x %04x '%s'\n", hJob, cchMsg, lpMsg);
303 if ((mod = GetModuleHandleA("user32.dll")))
305 if ((pMessageBoxA = (MSGBOX_PROC)GetProcAddress( mod, "MessageBoxA" )))
306 ret = pMessageBoxA(0, lpMsg, "Printing Error", MB_OKCANCEL);
308 return ret;
312 /**********************************************************************
313 * DeleteJob (GDI.244)
316 INT16 WINAPI DeleteJob16(HPJOB16 hJob, INT16 nNotUsed)
318 TRACE("%04x\n", hJob);
320 return CloseJob16( hJob );
324 * The following two function would allow a page to be sent to the printer
325 * when it has been processed. For simplicity they haven't been implemented.
326 * This means a whole job has to be processed before it is sent to the printer.
329 /**********************************************************************
330 * StartSpoolPage (GDI.246)
333 INT16 WINAPI StartSpoolPage16(HPJOB16 hJob)
335 FIXME("StartSpoolPage GDI.246 unimplemented\n");
336 return 1;
341 /**********************************************************************
342 * EndSpoolPage (GDI.247)
345 INT16 WINAPI EndSpoolPage16(HPJOB16 hJob)
347 FIXME("EndSpoolPage GDI.247 unimplemented\n");
348 return 1;
352 /**********************************************************************
353 * GetSpoolJob (GDI.245)
356 DWORD WINAPI GetSpoolJob16(int nOption, LONG param)
358 TRACE("In GetSpoolJob param 0x%x noption %d\n",param, nOption);
359 return 0;
363 /******************************************************************
364 * DrvGetPrinterDataInternal
366 * Helper for DrvGetPrinterData
368 static DWORD DrvGetPrinterDataInternal(LPCSTR RegStr_Printer,
369 LPBYTE lpPrinterData, int cbData, int what)
371 DWORD res = -1;
372 HKEY hkey;
373 DWORD dwType, cbQueryData;
375 if (!(RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey))) {
376 if (what == INT_PD_DEFAULT_DEVMODE) { /* "Default DevMode" */
377 if (!(RegQueryValueExA(hkey, DefaultDevMode, 0, &dwType, 0, &cbQueryData))) {
378 if (!lpPrinterData)
379 res = cbQueryData;
380 else if ((cbQueryData) && (cbQueryData <= cbData)) {
381 cbQueryData = cbData;
382 if (RegQueryValueExA(hkey, DefaultDevMode, 0,
383 &dwType, lpPrinterData, &cbQueryData))
384 res = cbQueryData;
387 } else { /* "Printer Driver" */
388 cbQueryData = 32;
389 RegQueryValueExA(hkey, "Printer Driver", 0,
390 &dwType, lpPrinterData, &cbQueryData);
391 res = cbQueryData;
394 if (hkey) RegCloseKey(hkey);
395 return res;
398 /******************************************************************
399 * DrvGetPrinterData (GDI.282)
402 DWORD WINAPI DrvGetPrinterData16(LPSTR lpPrinter, LPSTR lpProfile,
403 LPDWORD lpType, LPBYTE lpPrinterData,
404 int cbData, LPDWORD lpNeeded)
406 LPSTR RegStr_Printer;
407 HKEY hkey = 0, hkey2 = 0;
408 DWORD res = 0;
409 DWORD dwType, PrinterAttr, cbPrinterAttr, SetData, size;
411 if (HIWORD(lpPrinter))
412 TRACE("printer %s\n",lpPrinter);
413 else
414 TRACE("printer %p\n",lpPrinter);
415 if (HIWORD(lpProfile))
416 TRACE("profile %s\n",lpProfile);
417 else
418 TRACE("profile %p\n",lpProfile);
419 TRACE("lpType %p\n",lpType);
421 if ((!lpPrinter) || (!lpProfile) || (!lpNeeded))
422 return ERROR_INVALID_PARAMETER;
424 RegStr_Printer = HeapAlloc(GetProcessHeap(), 0,
425 strlen(Printers) + strlen(lpPrinter) + 2);
426 strcpy(RegStr_Printer, Printers);
427 strcat(RegStr_Printer, lpPrinter);
429 if ((PtrToUlong(lpProfile) == INT_PD_DEFAULT_DEVMODE) || (HIWORD(lpProfile) &&
430 (!strcmp(lpProfile, DefaultDevMode)))) {
431 size = DrvGetPrinterDataInternal(RegStr_Printer, lpPrinterData, cbData,
432 INT_PD_DEFAULT_DEVMODE);
433 if (size+1) {
434 *lpNeeded = size;
435 if ((lpPrinterData) && (*lpNeeded > cbData))
436 res = ERROR_MORE_DATA;
438 else res = ERROR_INVALID_PRINTER_NAME;
440 else
441 if ((PtrToUlong(lpProfile) == INT_PD_DEFAULT_MODEL) || (HIWORD(lpProfile) &&
442 (!strcmp(lpProfile, PrinterModel)))) {
443 *lpNeeded = 32;
444 if (!lpPrinterData) goto failed;
445 if (cbData < 32) {
446 res = ERROR_MORE_DATA;
447 goto failed;
449 size = DrvGetPrinterDataInternal(RegStr_Printer, lpPrinterData, cbData,
450 INT_PD_DEFAULT_MODEL);
451 if ((size+1) && (lpType))
452 *lpType = REG_SZ;
453 else
454 res = ERROR_INVALID_PRINTER_NAME;
456 else
458 if ((res = RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey)))
459 goto failed;
460 cbPrinterAttr = 4;
461 if ((res = RegQueryValueExA(hkey, "Attributes", 0,
462 &dwType, (LPBYTE)&PrinterAttr, &cbPrinterAttr)))
463 goto failed;
464 if ((res = RegOpenKeyA(hkey, PrinterDriverData, &hkey2)))
465 goto failed;
466 *lpNeeded = cbData;
467 res = RegQueryValueExA(hkey2, lpProfile, 0,
468 lpType, lpPrinterData, lpNeeded);
469 if ((res != ERROR_CANTREAD) &&
470 ((PrinterAttr &
471 (PRINTER_ATTRIBUTE_ENABLE_BIDI|PRINTER_ATTRIBUTE_NETWORK))
472 == PRINTER_ATTRIBUTE_NETWORK))
474 if (!(res) && (*lpType == REG_DWORD) && (*(LPDWORD)lpPrinterData == -1))
475 res = ERROR_INVALID_DATA;
477 else
479 SetData = -1;
480 RegSetValueExA(hkey2, lpProfile, 0, REG_DWORD, (LPBYTE)&SetData, 4); /* no result returned */
484 failed:
485 if (hkey2) RegCloseKey(hkey2);
486 if (hkey) RegCloseKey(hkey);
487 HeapFree(GetProcessHeap(), 0, RegStr_Printer);
488 return res;
492 /******************************************************************
493 * DrvSetPrinterData (GDI.281)
496 DWORD WINAPI DrvSetPrinterData16(LPSTR lpPrinter, LPSTR lpProfile,
497 DWORD lpType, LPBYTE lpPrinterData,
498 DWORD dwSize)
500 LPSTR RegStr_Printer;
501 HKEY hkey = 0;
502 DWORD res = 0;
504 if (HIWORD(lpPrinter))
505 TRACE("printer %s\n",lpPrinter);
506 else
507 TRACE("printer %p\n",lpPrinter);
508 if (HIWORD(lpProfile))
509 TRACE("profile %s\n",lpProfile);
510 else
511 TRACE("profile %p\n",lpProfile);
512 TRACE("lpType %08x\n",lpType);
514 if ((!lpPrinter) || (!lpProfile) ||
515 (PtrToUlong(lpProfile) == INT_PD_DEFAULT_MODEL) || (HIWORD(lpProfile) &&
516 (!strcmp(lpProfile, PrinterModel))))
517 return ERROR_INVALID_PARAMETER;
519 RegStr_Printer = HeapAlloc(GetProcessHeap(), 0,
520 strlen(Printers) + strlen(lpPrinter) + 2);
521 strcpy(RegStr_Printer, Printers);
522 strcat(RegStr_Printer, lpPrinter);
524 if ((PtrToUlong(lpProfile) == INT_PD_DEFAULT_DEVMODE) || (HIWORD(lpProfile) &&
525 (!strcmp(lpProfile, DefaultDevMode)))) {
526 if ( RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey)
527 != ERROR_SUCCESS ||
528 RegSetValueExA(hkey, DefaultDevMode, 0, REG_BINARY,
529 lpPrinterData, dwSize) != ERROR_SUCCESS )
530 res = ERROR_INVALID_PRINTER_NAME;
532 else
534 strcat(RegStr_Printer, "\\");
536 if( (res = RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey)) ==
537 ERROR_SUCCESS ) {
539 if (!lpPrinterData)
540 res = RegDeleteValueA(hkey, lpProfile);
541 else
542 res = RegSetValueExA(hkey, lpProfile, 0, lpType,
543 lpPrinterData, dwSize);
547 if (hkey) RegCloseKey(hkey);
548 HeapFree(GetProcessHeap(), 0, RegStr_Printer);
549 return res;