Changeset 21305 for trunk/src


Ignore:
Timestamp:
Jun 18, 2009, 12:15:47 PM (16 years ago)
Author:
ydario
Message:

winspool updates.

Location:
trunk/src/winspool
Files:
5 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/winspool/makefile

    r10234 r21305  
    1 # $Id: makefile,v 1.24 2003-08-14 10:43:26 sandervl Exp $
    21
    32#
     
    1110# Compiler, tools, and interference rules.
    1211#
     12!if "$(DEBUG)" == "1"
     13DEFFILE    = winspooldbg.def
     14ORGDEFFILE = winspool.def
     15!endif
     16
     17WRC_PREFIX_RESOURCE=1
    1318!include ../../makefile.inc
    1419
     
    2025$(OBJDIR)\winspool.obj \
    2126$(OBJDIR)\oslibspl.obj \
    22 $(OBJDIR)\winspoolrsrc.obj  \
    23 $(DLLENTRY)
     27$(OBJDIR)\winspoolrsrc.obj \
     28$(OBJDIR)\initwinspool.obj \
     29!ifdef DEBUG
     30$(OBJDIR)\dbgwrap.obj \
     31!endif
     32$(OBJDIR)\stubs.obj \
     33$(OBJDIR)\initterm.obj
    2434
    2535
     
    2939LIBS = \
    3040$(ODIN32_LIB)/kernel32.lib \
    31 $(ODIN32_LIB)/pmwinx.lib \
    3241$(ODIN32_LIB)/user32.lib \
    3342$(ODIN32_LIB)/gdi32.lib \
     43$(ODIN32_LIB)/wgss50.lib \
    3444$(ODIN32_LIB)/libwrap.lib \
    3545$(ODIN32_LIB)/$(ODINCRT).lib \
  • trunk/src/winspool/oslibspl.cpp

    r4594 r21305  
    1 /* $Id: oslibspl.cpp,v 1.1 2000-11-15 10:54:23 sandervl Exp $ */
    21
    32/*
     
    1110#define  INCL_SPL
    1211#define  INCL_SPLERRORS
     12#define  INCL_SPLDOSPRINT
    1313#define  INCL_DOSERRORS
    1414#define  INCL_GPI
    1515#define  INCL_WIN
     16#define  INCL_DEV
     17
    1618#include <os2wrap.h>    //Odin32 OS/2 api wrappers
    1719#include <stdlib.h>
     20#include <pmspl.h>
    1821#include <string.h>
    1922#include <win32type.h>
     23#include <winuser32.h>
    2024#include <misc.h>
     25#include <wprocess.h>
    2126#include "oslibspl.h"
     27
     28/**
     29 * Enumerate printers.
     30 * @returns Pointer to requested data.
     31 * @returns NULL on failure.
     32 * @param   pszComputer Computer name.
     33 * @param   flType      Flags.
     34 * @param   pcReturned  Number of structures returned.
     35 * @param   pcTotal     Total number of structures available.
     36 */
     37void * OSLibSplEnumPrinter(LPSTR pszComputer, DWORD flType, PDWORD pcReturned, PDWORD pcTotal)
     38{
     39    ULONG   cbNeeded = 0;
     40    SPLERR  rc = SplEnumPrinter(NULL, 0, flType, NULL, 0, pcReturned, pcTotal, &cbNeeded, NULL);
     41    if (!rc || rc == ERROR_MORE_DATA || rc == NERR_BufTooSmall)
     42    {
     43        void *pv = malloc(cbNeeded+1);
     44        rc = SplEnumPrinter(pszComputer, 0, flType, pv, cbNeeded, pcReturned, pcTotal, &cbNeeded, NULL);
     45        if (!rc || rc == ERROR_MORE_DATA)
     46            return pv;
     47        free(pv);
     48    }
     49    return NULL;
     50}
    2251
    2352//******************************************************************************
    2453//******************************************************************************
    25 BOOL OSLibSplEnumPrinters(DWORD flType, OSLIB_PRINTERINFO *pBuf, DWORD cbSize,
    26                           DWORD *pcReturned, DWORD *pcTotal, DWORD *pcbNeeded)
    27 {
    28   SPLERR rc;
    29 
    30     rc = SplEnumPrinter(NULL, 0, flType, (PVOID)pBuf, cbSize, pcReturned, pcTotal, pcbNeeded, 0);
    31 
    32     if(rc == 0 || (pBuf == NULL && (rc == ERROR_MORE_DATA || rc == NERR_BufTooSmall))) {
    33         return TRUE;
    34     }
    35     return FALSE;
    36 }
     54ULONG OSLibShowPrinterDialog(HWND hWnd, LPSTR printerName)
     55{
     56    HAB hab;
     57    ULONG cReturned, cTotal, cbNeeded, flType,cbBuf, ulrc;
     58    int   devNum = -1;
     59    OSLIB_PRQINFO3 *queueInfo;
     60    char *pszTmp, *pszDeviceName;
     61    SPLERR     rc;
     62
     63    hab = WinQueryAnchorBlock(Win32ToOS2Handle(hWnd));
     64
     65    rc = SplEnumQueue(NULL, 3, NULL, 0, &cReturned, &cTotal, &cbNeeded, NULL);
     66    if (rc && rc != ERROR_MORE_DATA && rc != NERR_BufTooSmall)
     67    {
     68        dprintf(("OSLibSplEnumQueue failed"));
     69        return -1;
     70    }
     71    if (cTotal == 0)
     72    {//no printers installed
     73        return -1;
     74    }
     75    queueInfo = (OSLIB_PRQINFO3*)malloc(cbNeeded);
     76
     77    rc = SplEnumQueue(NULL, 3, queueInfo, cbNeeded, &cReturned, &cTotal, &cbNeeded, NULL);
     78    if (rc)
     79    {
     80        free(queueInfo);
     81        dprintf(("OSLibSplEnumQueue failed"));
     82        return -1;
     83    }
     84
     85    for (int i = 0; i < cReturned; i++)
     86        if (!strcmp(queueInfo[i].pszName, printerName))
     87        {
     88            devNum = i;
     89            break;
     90        }
     91
     92    if (devNum == -1)
     93    {
     94        free(queueInfo);
     95        return -1;
     96    }
     97    /* Use the first device name in the PRQINFO3 structure                 */
     98    pszTmp = strchr(queueInfo[devNum].pszPrinters, ',');
     99    if (pszTmp)
     100        *pszTmp = '\0';
     101
     102    /* Use just the driver name from the driver.device string              */
     103    pszDeviceName = strchr(queueInfo[devNum].pszDriverName, '.');
     104    if (pszDeviceName)
     105    {
     106        *pszDeviceName = '\0';
     107        pszDeviceName++;
     108    }
     109
     110    /* Check size of buffer required for job properties                    */
     111    cbBuf = DevPostDeviceModes( hab,
     112                                (PDRIVDATA)NULL,
     113                                queueInfo[devNum].pszDriverName,
     114                                pszDeviceName,
     115                                queueInfo[devNum].pszPrinters,
     116                                DPDM_POSTJOBPROP
     117                              );
     118
     119    /* Return error to caller                                              */
     120    if (cbBuf<=0)
     121    {
     122        free(queueInfo);
     123        return(-1);
     124    }
     125
     126    /* Display job properties dialog & get updated job properties from driver */
     127    ulrc = DevPostDeviceModes( hab,
     128                               (PDRIVDATA)queueInfo[devNum].pDriverData,
     129                               queueInfo[devNum].pszDriverName,
     130                               pszDeviceName,
     131                               queueInfo[devNum].pszPrinters,
     132                               DPDM_POSTJOBPROP);
     133
     134    if (pszDeviceName)
     135        *(--pszDeviceName) = '.';
     136
     137    ulrc = SplSetQueue(NULL, printerName, 3, (PVOID)&queueInfo[devNum], cbBuf, 0);
     138    if (ulrc)
     139        dprintf(("Spooler Set Queue error %d",ulrc));
     140
     141    free(queueInfo);
     142    return(1);
     143}
     144
     145/**
     146 * Enumerate queues.
     147 * @returns Pointer to requested data.
     148 * @returns NULL on failure.
     149 * @param   pszComputer Computer name.
     150 * @param   ulLevel     Information level.
     151 * @param   pcReturned  Number of structures returned.
     152 * @param   pcTotal     Total number of structures available.
     153 */
     154void * OSLibSplEnumQueue(LPSTR pszComputer, DWORD ulLevel, DWORD *pcReturned, DWORD *pcTotal)
     155{
     156    ULONG   cbNeeded = 0;
     157    SPLERR  rc = SplEnumQueue(pszComputer, ulLevel, NULL, 0, pcReturned, pcTotal, &cbNeeded, NULL);
     158    if (!rc || rc == ERROR_MORE_DATA || rc == NERR_BufTooSmall)
     159    {
     160        void *pv = malloc(cbNeeded+1);
     161        SPLERR  rc = SplEnumQueue(pszComputer, ulLevel, pv, cbNeeded, pcReturned, pcTotal, &cbNeeded, NULL);
     162        if (!rc || rc == ERROR_MORE_DATA)
     163            return pv;
     164        free(pv);
     165    }
     166    return NULL;
     167}
     168
     169/**
     170 * Enumerate devices.
     171 * @returns Pointer to requested data.
     172 * @returns NULL on failure.
     173 * @param   pszComputer Computer name.
     174 * @param   ulLevel     Information level.
     175 * @param   pcReturned  Number of structures returned.
     176 * @param   pcTotal     Total number of structures available.
     177 */
     178void * OSLibSplEnumDevice(LPSTR pszComputer, DWORD ulLevel, DWORD *pcReturned, DWORD *pcTotal)
     179{
     180    ULONG   cbNeeded = 0;
     181    SPLERR  rc = SplEnumDevice(pszComputer, ulLevel, NULL, 0, pcReturned, pcTotal, &cbNeeded, NULL);
     182    if (!rc || rc == ERROR_MORE_DATA || rc == NERR_BufTooSmall)
     183    {
     184        void *pv = malloc(cbNeeded+1);
     185        SPLERR  rc = SplEnumDevice(pszComputer, ulLevel, pv, cbNeeded, pcReturned, pcTotal, &cbNeeded, NULL);
     186        if (!rc || rc == ERROR_MORE_DATA)
     187            return pv;
     188        free(pv);
     189    }
     190    return NULL;
     191}
     192
    37193//******************************************************************************
    38194//******************************************************************************
     195/**
     196 * @remark bird: This a nasty thing. Any chance we could use the app default flag for the queue?
     197 */
     198BOOL OSLibSplFindDefaultPrinter(LPSTR lpszPortName, LPSTR lpszDriverName, LPSTR lpszQueueName)
     199{
     200        /*
     201         * OS/2 stores the default printer as a combination of printerdevice and queue.
     202         *
     203         *   Printer Device is related to one port. It may have multiple printer
     204         *       drivers because the port may serve multiple queues with different drivers.
     205         *   The Ports are related to multiple queues.
     206         *
     207         * So we take the default default printer+queue combination and finds the
     208         */
     209        char szDefPrnDev[20];
     210        char szDefPrnQue[20];
     211        if (PrfQueryProfileString(HINI_PROFILE, "PM_SPOOLER", "PRINTER", "",
     212                                  szDefPrnDev, sizeof(szDefPrnDev)) > 1
     213            &&  PrfQueryProfileString(HINI_PROFILE, "PM_SPOOLER", "QUEUE", "",
     214                                      szDefPrnQue, sizeof(szDefPrnQue)) > 1
     215            &&  szDefPrnDev[0]
     216            &&  szDefPrnQue[0]
     217           )
     218        {
     219            char *psz;
     220            /* remove everything beyond the first ';' */
     221            if ((psz = strchr(szDefPrnDev, ';')) != NULL)
     222                *psz = '\0';
     223            if ((psz = strchr(szDefPrnQue, ';')) != NULL)
     224                *psz = '\0';
     225
     226            /*
     227             * Now we must lookup the port name from the device settings.
     228             *  This is a string of this form:
     229             *      <port>;<driver1>[,<driver2>;<queue1>[,<queue2>];?;?;
     230             */
     231            ULONG   cb = 0;
     232            if (PrfQueryProfileSize(HINI_SYSTEMPROFILE, "PM_SPOOLER_PRINTER", szDefPrnDev, &cb)
     233                &&  cb > 0)
     234            {
     235                char *pszBufD = (char*)malloc(cb + 1);
     236                if (pszBufD
     237                    &&  PrfQueryProfileString(HINI_SYSTEMPROFILE, "PM_SPOOLER_PRINTER", szDefPrnDev,
     238                                              NULL, pszBufD, cb + 1)
     239                    > 1
     240                   )
     241                {
     242                    /*
     243                     * Now get the Default printer driver for the queue.
     244                     *  This is stored as a ';' separated list of drivers, the first one is the default.
     245                     */
     246                    if (PrfQueryProfileSize(HINI_SYSTEMPROFILE, "PM_SPOOLER_QUEUE_DD", szDefPrnQue, &cb)
     247                        &&  cb > 0)
     248                    {
     249                        char *pszBufQ = (char*)malloc(cb + 1);
     250                        if (pszBufQ
     251                            &&  PrfQueryProfileString(HINI_SYSTEMPROFILE, "PM_SPOOLER_QUEUE_DD", szDefPrnQue,
     252                                                      NULL, pszBufQ, cb + 1)
     253                            > 1
     254                           )
     255                        {
     256                            /*
     257                             * We got everything now. just find the parts we need.
     258                             *  First printer driver from QUEUE_DD
     259                             *  Port name of the device.
     260                             */
     261                            if ((psz = strchr(pszBufQ, ';')) != NULL)
     262                                *psz = '\0';
     263                            if ((psz = strchr(pszBufQ, ',')) != NULL) //paranoia! in case comman separated list of some kind.
     264                                *psz = '\0';
     265                            if ((psz = strchr(pszBufD, ';')) != NULL)
     266                                *psz = '\0';
     267                            if ((psz = strchr(pszBufD, ',')) != NULL) //paranoia in case comman separated list of some kind.
     268                                *psz = '\0';
     269
     270                            /*
     271                             * Now make default printer string for the win.ini.
     272                             */
     273                            strcpy(lpszPortName, pszBufD);
     274                            strcat(lpszQueueName, szDefPrnQue);
     275                            strcat(lpszDriverName, pszBufQ);
     276                            dprintf(("OSLibSplFindDefaultPrinter: Successfully found default printer.'%s-%s-%s'", szDefPrnQue, lpszDriverName, pszBufQ));
     277                            free(pszBufQ);
     278                            return TRUE;
     279                        }
     280                    }
     281                    else
     282                    {
     283                        /* OS/2 the device may exist though the default queue is destroyed.
     284                         * it may still exist even if there are no queues on the system at all!
     285                         */
     286                        dprintf(("OSLibSplFindDefaultPrinter: no queue driver entry for '%s'.", szDefPrnQue));
     287                    }
     288
     289                    free(pszBufD);
     290                }
     291            }
     292            else
     293            {
     294                /* OS/2 doesn't remove the default settings if the default queue/printer is deleted. */
     295                dprintf(("OSLibSplFindDefaultPrinter: can't find device settings for '%s'.", szDefPrnDev));
     296            }
     297        }
     298        else
     299        {
     300            dprintf(("OSLibSplFindDefaultPrinter: no default printer? szDefPrnDev='%s' szDefPrnQue='%s'.", szDefPrnDev, szDefPrnQue));
     301        }
     302        return FALSE;
     303}
     304
     305
     306/**
     307 * Does SplQueryQueue allocating a sufficent buffer of the default heap.
     308 *
     309 * @returns pointer to queue info.
     310 * @returns NULL on failure.
     311 * @param   pszComputerName See SplQueryQueue.
     312 * @param   pszQueueName    See SplQueryQueue.
     313 * @param   ulLevel         See SplQueryQueue.
     314 */
     315void * OSLibSplQueryQueue(LPSTR pszComputerName, LPSTR pszQueueName, ULONG ulLevel)
     316{
     317    ULONG   cbNeeded = 0;
     318    SPLERR rc = SplQueryQueue(pszComputerName, pszQueueName, ulLevel, NULL, 0, &cbNeeded);
     319    if (rc && rc != ERROR_MORE_DATA && rc != NERR_BufTooSmall)
     320        return NULL;
     321
     322    void *pv = malloc(cbNeeded);
     323    rc = SplQueryQueue(pszComputerName, pszQueueName, ulLevel, pv, cbNeeded, &cbNeeded);
     324    if (rc)
     325    {
     326        free(pv);
     327        return NULL;
     328    }
     329    return pv;
     330}
     331
     332
     333/**
     334 * see pmref.
     335 * @returns see pmref.
     336 * @param   pszToken    see pmref.
     337 * @param   lCount      see pmref.
     338 * @param   pqmdopData  see pmref.
     339 */
     340HSPL OSLibSplQmOpen(LPSTR pszToken, LONG lCount, LPSTR* pqmdopData)
     341{
     342    return SplQmOpen(pszToken, lCount, pqmdopData);
     343}
     344
     345
     346/**
     347 * see pmref.
     348 * @returns see pmref.
     349 * @param   hspl        see pmref.
     350 */
     351BOOL OSLibSplQmClose(HANDLE hspl)
     352{
     353    return SplQmClose(hspl);
     354}
     355
     356
     357/**
     358 * see pmref.
     359 * @returns see pmref.
     360 * @param   hspl        see pmref.
     361 * @param   pszDocName  see pmref.
     362 */
     363BOOL OSLibSplQmStartDoc(HANDLE hspl, LPSTR pszDocName)
     364{
     365    return SplQmStartDoc(hspl, pszDocName);
     366}
     367
     368
     369/**
     370 * see pmref.
     371 * @returns see pmref.
     372 * @param   hspl        see pmref.
     373 */
     374BOOL OSLibSplQmEndDoc(HANDLE hspl)
     375{
     376    return SplQmEndDoc(hspl);
     377}
     378
     379
     380/**
     381 * see pmref
     382 * @returns see pmref
     383 * @param   hspl    see pmref
     384 * @param   cbData  see pmref
     385 * @param   pvData  see pmref
     386 */
     387BOOL OSLibSplQmWrite(HANDLE hspl, LONG cbData, PVOID pvData)
     388{
     389    return SplQmWrite(hspl, cbData, pvData);
     390}
     391
     392
     393/**
     394 * see pmref.
     395 * @returns see pmref.
     396 * @param   hspl        see pmref.
     397 * @param   ulPageNo    see pmref.
     398 */
     399BOOL OSLibSplQmNewPage(HANDLE hspl, ULONG ulPageNo)
     400{
     401    return SplQmNewPage(hspl, ulPageNo);
     402}
     403
     404
     405/**
     406 * Some spooler apis sets the last error.
     407 *
     408 * @returns last error.
     409 */
     410ULONG OSLibSplWinGetLastError(void)
     411{
     412    TEB *teb = GetThreadTEB();
     413    return WinGetLastError(teb ? teb->o.odin.hab : 0) & 0xFFFF;
     414}
     415
  • trunk/src/winspool/oslibspl.h

    r4594 r21305  
    1 /* $Id: oslibspl.h,v 1.1 2000-11-15 10:54:24 sandervl Exp $ */
    21#ifndef __OSLIBSPL_H__
    32#define __OSLIBSPL_H__
    43
     4
     5/*******************************************************************************
     6*   Structures and Typedefs                                                    *
     7*******************************************************************************/
     8typedef struct
     9{
     10    ULONG   flType;
     11    LPSTR   pszComputerName;
     12    LPSTR   pszPrintDestinationName;
     13    LPSTR   pszDescription;
     14    LPSTR   pszLocalName;
     15} OSLIB_PRINTERINFO, *POSLIB_PRINTERINFO;
     16
     17typedef struct
     18{
     19    LONG    cb;
     20    LONG    lVersion;
     21    CHAR    szDeviceName[32];
     22    CHAR    abGeneralData[1];
     23} OSLIB_DRIVDATA;
     24
     25typedef struct
     26{
     27    LPSTR     pszName;
     28    USHORT  uPriority;
     29    USHORT  uStartTime;
     30    USHORT  uUntilTime;
     31    USHORT  fsType;
     32    LPSTR     pszSepFile;
     33    LPSTR     pszPrProc;
     34    LPSTR     pszParms;
     35    LPSTR     pszComment;
     36    USHORT  fsStatus;
     37    USHORT  cJobs;
     38    LPSTR     pszPrinters;
     39    LPSTR     pszDriverName;
     40    OSLIB_DRIVDATA *pDriverData;
     41} OSLIB_PRQINFO3, *POSLIB_PRQINFO3;
     42
    543typedef struct {
    6          ULONG   flType;
    7          LPSTR   pszComputerName;
    8          LPSTR   pszPrintDestinationName;
    9          LPSTR   pszDescription;
    10          LPSTR   pszLocalName;
    11 } OSLIB_PRINTERINFO, *POSLIB_PRINTERINFO;
     44    LPSTR        pszPrinterName;  /*  Print device name. */
     45    LPSTR        pszUserName;     /*  User who submitted job. */
     46    LPSTR        pszLogAddr;      /*  Logical address (for example LPT1). */
     47    USHORT     uJobId;          /*  Identity of current job. */
     48    USHORT     fsStatus;        /*  Print destination status. */
     49    LPSTR        pszStatus;       /*  Print device comment while printing. */
     50    LPSTR        pszComment;      /*  Print device description. */
     51    LPSTR        pszDrivers;      /*  Drivers supported by print device. */
     52    USHORT     time;            /*  Time job has been printing (minutes) */
     53    USHORT     usTimeOut;       /*  Device timeout (seconds) */
     54} OSLIB_PRDINFO3, *POSLIB_PRDINFO3;
     55
     56typedef struct
     57{
     58    LPSTR       pszLogAddress;
     59    LPSTR       pszDriverName;
     60    void *        pdriv;
     61    LPSTR       pszDataType;
     62    LPSTR       pszComment;
     63    LPSTR       pszQueueProcName;
     64    LPSTR       pszQueueProcParams;
     65    LPSTR       pszSpoolerParams;
     66    LPSTR       pszNetworkParams;
     67} OSLIB_DEVOPENSTRUC, *POSLIB_DEVOPENSTRUC;
    1268
    1369/*** Flags for flType in  PRINTERINFO and SplEnumPrinter *************/
     
    1975#define OSLIB_SPL_PR_ALL       (OSLIB_SPL_PR_QUEUE|OSLIB_SPL_PR_DIRECT_DEVICE|OSLIB_SPL_PR_QUEUED_DEVICE)
    2076
    21 BOOL OSLibSplEnumPrinters(DWORD flType, OSLIB_PRINTERINFO *pBuf, DWORD cbSize,
    22                           DWORD *pcReturned, DWORD *pcTotal, DWORD *pcbNeeded);
     77#define OSLIB_PRQ3_TYPE_RAW         0x0001 /* spools printer-specific data */
     78#define OSLIB_PRQ3_TYPE_BYPASS      0x0002 /* allow print while spooling   */
     79#define OSLIB_PRQ3_TYPE_APPDEFAULT  0x0004 /* set for Application default Q*/
    2380
     81void * OSLibSplEnumPrinter(LPSTR pszComputer, DWORD flType, PDWORD pcReturned, PDWORD pcTotal);
     82void * OSLibSplEnumDevice(LPSTR pszComputer, DWORD ulLevel, DWORD *pcReturned, DWORD *pcTotal);
     83void * OSLibSplEnumQueue(LPSTR pszComputer, DWORD ulLevel, DWORD *pcReturned, DWORD *pcTotal);
     84
     85BOOL ExportPrintersToRegistry(void);
     86ULONG OSLibShowPrinterDialog(HWND, LPSTR printerName);
     87
     88BOOL OSLibSplFindDefaultPrinter(LPSTR lpszPortName, LPSTR lpszDriverName, LPSTR lpszQueueName);
     89void * OSLibSplQueryQueue(LPSTR pszComputerName, LPSTR pszQueueName, ULONG ulLevel);
     90
     91HANDLE  OSLibSplQmOpen(LPSTR pszToken, LONG lCount, LPSTR* pqmdopData);
     92BOOL    OSLibSplQmClose(HANDLE hspl);
     93BOOL    OSLibSplQmStartDoc(HANDLE hspl, LPSTR pszDocName);
     94BOOL    OSLibSplQmEndDoc(HANDLE hspl);
     95BOOL    OSLibSplQmWrite(HANDLE hspl, LONG cbData, PVOID pvData);
     96BOOL    OSLibSplQmNewPage(HANDLE hspl, ULONG ulPageNo);
     97
     98ULONG OSLibSplWinGetLastError(void);
    2499
    25100#endif
  • trunk/src/winspool/winspool.DEF

    r4594 r21305  
    1 ; $Id: winspool.DEF,v 1.4 2000-11-15 10:54:24 sandervl Exp $
    21
    32;
     
    146145; WaitForPrinterChange                                                          @240
    147146  WritePrinter                          = _WritePrinter@16                      @241
     147
     148  SplQueryPMQueueName                   = _SplQueryPMQueueName@12               @250
  • trunk/src/winspool/winspool.cpp

    r6336 r21305  
    1 /* $Id: winspool.cpp,v 1.7 2001-07-15 14:35:51 sandervl Exp $ */
    21
    32/*
     
    54 * Project Odin Software License can be found in LICENSE.TXT
    65 *
    7  * WINSPOOL stubs
     6 * WINSPOOL implemention
    87 *
    98 * Copyright 1998 Patrick Haller
    109 * Copyright 2000 Sander van Leeuwen (sandervl@xs4all.nl)
    11  *
    12  *
    13  * Partially based on Wine code (dlls\winspool\info.c (EnumPrinters, DeviceCapabilitiesA/W)
     10 * Copyright 2003-2004 InnoTek Systemberatung GmbH
     11 *
     12 *
     13 * Partially based on WineX code (dlls\winspool\info.c (EnumPrinters, DeviceCapabilitiesA/W)
    1414 *
    1515 * Copyright 1996 John Harvey
     
    1818 * Copyright 1999, 2000 Huw D M Davies
    1919 *
    20  * TODO: far from complete (although the Spl API seems to provide everything we need!)
    21  *
    22  */
    23 
    24 /****************************************************************************
    25  * Includes                                                                 *
    26  ****************************************************************************/
    27 
     20 *
     21 */
     22
     23/*******************************************************************************
     24*   Header Files                                                               *
     25*******************************************************************************/
     26#include <windows.h>
    2827#include <os2win.h>
    2928#include <winspool.h>
     
    3130#include <heapstring.h>
    3231#include <win\winnls.h>
     32#include <win\debugstr.h>
     33#include <win\debugtools.h>
    3334
    3435#include <stdio.h>
     
    3738#include <string.h>
    3839#include <misc.h>
     40#ifdef __WIN32OS2__
     41# include <vmutex.h>
     42# include <unicode.h>
     43#endif
    3944#include "oslibspl.h"
    4045
     46
     47/*******************************************************************************
     48*   Defined Constants And Macros                                               *
     49*******************************************************************************/
     50#ifdef __WIN32OS2__
     51/**
     52 * Debug assertion macro.
     53 * @param   expr    Assert that this expression is true.
     54 * @param   msg     Message to print if expr isn't true. It's given to dprintf,
     55 *                  and must be inclosed in paratheses.
     56 * @todo move this to some header in /include.
     57 */
     58#ifdef DEBUG
     59#define DebugAssert(expr, msg) \
     60    do { if (expr) break; \
     61         dprintf(("!!!ASSERTION FAILED!!!\nFILE=%s\nLINE=%d\nFUNCTION=%s\n", __FILE__, __LINE__, __FUNCTION__)); \
     62         dprintf(msg); DebugInt3(); \
     63       } while (0)
     64#else
     65#define DebugAssert(expr, msg) do {} while (0)
     66#endif
     67
     68/**
     69 * Debug assertion failed macro.
     70 * @param   msg     Message to print if expr isn't true. It's given to dprintf,
     71 *                  and must be inclosed in paratheses.
     72 * @todo move this to some header in /include.
     73 */
     74#ifdef DEBUG
     75#define DebugAssertFailed(msg) \
     76    do { dprintf(("!!!ASSERTION FAILED!!!\nFILE=%s\nLINE=%d\nFUNCTION=%s\n", __FILE__, __LINE__, __FUNCTION__)); \
     77         dprintf(msg); DebugInt3(); \
     78       } while (0)
     79#else
     80#define DebugAssertFailed(msg) do {} while (0)
     81#endif
     82
     83#endif
     84
     85/** Define this to use the OS/2 printer driver names. */
     86#define USE_OS2_DRIVERNAME
     87
     88/*******************************************************************************
     89*   Structures and Typedefs                                                    *
     90*******************************************************************************/
     91#ifdef __WIN32OS2__
     92/**
     93 * Open printer instance.
     94 * @todo protect the structure while using it. (probably not an issue)
     95 */
     96typedef struct _OpenPrinter
     97{
     98    /** The handle of this instance. */
     99    HANDLE      hOpenPrinter;
     100    /** Pointer to the next entry. */
     101    struct _OpenPrinter *pNext;
     102    /** Printer name. */
     103    LPWSTR      pwszPrinterName;
     104
     105    /** Open spool file. */
     106    HANDLE      hspl;
     107    /** Current page number in the job (for StartPagePrinter()). */
     108    ULONG       ulCurPage;
     109} OPENPRINTER, *POPENPRINTER;
     110#endif
     111
     112
     113/*******************************************************************************
     114*   Global Variables                                                           *
     115*******************************************************************************/
     116#ifdef __WIN32OS2__
     117/** LIFO of open printers. */
     118POPENPRINTER    gpOpenPrinters;
     119/** Last Printer handle.
     120 * This assumes that 4G open printers are enough and that the caller accepts high
     121 * values. */
     122HANDLE          ghOpenPrintersLast;
     123/** Mutex protecting gpOpenPrinters and ghOpenPrintersLast.
     124  * This protects only the list, not the entries themself. */
     125VMutex          gOpenPrintersMutex;
     126#endif
     127
     128
     129static char Printers[] =
     130"System\\CurrentControlSet\\control\\Print\\Printers\\";
     131static char Drivers[] =
     132"System\\CurrentControlSet\\control\\Print\\Environments\\%s\\Drivers\\";
     133
     134WINAPI GDI_CallExtDeviceMode16 ( HWND hwnd, LPDEVMODEA lpdmOutput,
     135                                              LPSTR lpszDevice, LPSTR lpszPort,
     136                                              LPDEVMODEA lpdmInput, LPSTR lpszProfile,
     137                                              DWORD fwMode );
     138#ifndef __WIN32OS2__
     139static LPWSTR *printer_array;
     140static int nb_printers;
     141#endif
     142static WCHAR DefaultEnvironmentW[] = {'W','i','n','e',0};
     143
     144static WCHAR Configuration_FileW[] = {'C','o','n','f','i','g','u','r','a','t',
     145                                      'i','o','n',' ','F','i','l','e',0};
     146static WCHAR DatatypeW[] = {'D','a','t','a','t','y','p','e',0};
     147static WCHAR Data_FileW[] = {'D','a','t','a',' ','F','i','l','e',0};
     148static WCHAR Default_DevModeW[] = {'D','e','f','a','u','l','t',' ','D','e','v',
     149                                   'M','o','d','e',0};
     150static WCHAR Dependent_FilesW[] = {'D','e','p','e','n','d','e','n','t',' ','F',
     151                                   'i','l','e','s',0};
     152static WCHAR DescriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
     153static WCHAR DriverW[] = {'D','r','i','v','e','r',0};
     154static WCHAR Help_FileW[] = {'H','e','l','p',' ','F','i','l','e',0};
     155static WCHAR LocationW[] = {'L','o','c','a','t','i','o','n',0};
     156static WCHAR MonitorW[] = {'M','o','n','i','t','o','r',0};
     157static WCHAR NameW[] = {'N','a','m','e',0};
     158static WCHAR ParametersW[] = {'P','a','r','a','m','e','t','e','r','s',0};
     159static WCHAR PortW[] = {'P','o','r','t',0};
     160static WCHAR Print_ProcessorW[] = {'P','r','i','n','t',' ','P','r','o','c','e',
     161                                   's','s','o','r',0};
     162static WCHAR Printer_DriverW[] = {'P','r','i','n','t','e','r',' ','D','r','i',
     163                                  'v','e','r',0};
     164static WCHAR PrinterDriverDataW[] = {'P','r','i','n','t','e','r','D','r','i',
     165                                     'v','e','r','D','a','t','a',0};
     166static WCHAR Separator_FileW[] = {'S','e','p','a','r','a','t','o','r',' ','F',
     167                                  'i','l','e',0};
     168static WCHAR Share_NameW[] = {'S','h','a','r','e',' ','N','a','m','e',0};
     169static WCHAR WinPrintW[] = {'W','i','n','P','r','i','n','t',0};
     170
    41171ODINDEBUGCHANNEL(WINSPOOL)
    42172
    43 
    44 /*****************************************************************************
    45  * Name      : BOOL EnumPrintersA
    46  * Purpose   :
    47  * Parameters:
    48  * Variables :
    49  * Result    :
    50  * Remark    :
    51  * Status    :
    52  *
    53  * Author    : SvL
    54  *****************************************************************************/
    55 
    56 ODINFUNCTION7(BOOL,    EnumPrintersA,
    57               DWORD,   dwType,
    58               LPTSTR,  lpszName,
    59               DWORD,   dwLevel,
    60               LPBYTE,  lpbPrinters,
    61               DWORD,   cbBuf,
    62               LPDWORD, lpdwNeeded,
    63               LPDWORD, lpdwReturned)
    64 {
    65  ULONG cReturned, cTotal, cbNeeded, flType;
    66  int   used, nameoff;
    67  OSLIB_PRINTERINFO *printerInfo;
    68  PRINTER_INFO_1A *pi1;
    69  PRINTER_INFO_2A *pi2;
    70  PRINTER_INFO_4A *pi4;
    71  PRINTER_INFO_5A *pi5;
    72  LPSTR lpszPrinterStrings;
    73 
    74     if(lpbPrinters)
    75         memset(lpbPrinters, 0, cbBuf);
    76 
    77     if(lpdwReturned)
    78         *lpdwReturned = 0;
    79 
    80     if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME)))
    81     {
    82         dprintf(("Invalid parameters !(PRINTER_ENUM_LOCAL & PRINTER_ENUM_NAME)!!"));
    83         SetLastError(ERROR_INVALID_FLAGS);
    84         return FALSE;
    85     }
    86 
    87     if(lpszName) {//TODO:
    88         dprintf(("remote printer enumeration not (yet) supported!!"));
    89         flType = OSLIB_SPL_PR_ALL;
    90     }
    91     else flType = OSLIB_SPL_PR_LOCAL_ONLY | OSLIB_SPL_PR_ALL;
    92 
    93     if(OSLibSplEnumPrinters(flType, NULL, 0, &cReturned, &cTotal, &cbNeeded) == FALSE) {
    94         SetLastError(ERROR_FILE_NOT_FOUND); //todo wrong error
    95         return FALSE;
    96     }
    97     if(cTotal == 0) {//no printers installed
    98         SetLastError(ERROR_SUCCESS);
    99         return TRUE;
    100     }
    101 
    102     switch(dwLevel) {
    103     case 1:
    104         used = cTotal * sizeof(PRINTER_INFO_1A);
    105         break;
    106 
    107     case 2:
    108         used = cTotal * sizeof(PRINTER_INFO_2A);
    109         break;
    110 
    111     case 4:
    112         used = cTotal * sizeof(PRINTER_INFO_4A);
    113         break;
    114 
    115     case 5:
    116         used = cTotal * sizeof(PRINTER_INFO_5A);
    117         break;
    118 
    119     default:
    120         dprintf(("ERROR: EnumPrintersA: Unknown level %d!", dwLevel));
    121         SetLastError(ERROR_INVALID_LEVEL);
    122         return FALSE;
    123     }
    124     nameoff = used;
    125     used   += cbNeeded;   //add size of printer names
    126 
    127     if(used > cbBuf) {
    128         if(lpdwNeeded)
    129             *lpdwNeeded = used;
    130         SetLastError(ERROR_INSUFFICIENT_BUFFER);
    131         return FALSE;
    132     }
    133 
    134     printerInfo = (OSLIB_PRINTERINFO *)malloc(cbNeeded);
    135     if(OSLibSplEnumPrinters(flType, printerInfo, cbNeeded, &cReturned, &cTotal, &cbNeeded) == FALSE) {
    136         free(printerInfo);
    137         SetLastError(ERROR_FILE_NOT_FOUND);
    138         return FALSE;
    139     }
    140     lpszPrinterStrings = (char *)lpbPrinters + nameoff;
    141 
    142     for(int i=0;i<cReturned;i++) {
    143         switch(dwLevel) {
    144         case 1:
    145             pi1 = (PRINTER_INFO_1A *)lpbPrinters;
    146             lpbPrinters += sizeof(PRINTER_INFO_1A);
    147 
    148             pi1->Flags = PRINTER_ENUM_ICON8;
    149             pi1->pName = lpszPrinterStrings;
    150             strcpy(lpszPrinterStrings, printerInfo[i].pszPrintDestinationName);
    151             lpszPrinterStrings += strlen(printerInfo[i].pszPrintDestinationName)+1;
    152 
    153             if(printerInfo[i].pszDescription) {
    154                 pi1->pDescription = lpszPrinterStrings;
    155                 strcpy(lpszPrinterStrings, printerInfo[i].pszDescription);
    156                 lpszPrinterStrings += strlen(printerInfo[i].pszDescription)+1;
     173/*******************************************************************************
     174*   Internal Functions                                                         *
     175*******************************************************************************/
     176#ifdef __WIN32OS2__
     177BOOL WIN32API SplQueryPMQueueFromHandle(HANDLE hPrinter, char *pszQueue, unsigned cchQueue);
     178BOOL WIN32API SplQueryPMQueueName(LPSTR pszPrinterName, LPSTR pszQueue, INT cchQueue);
     179static POPENPRINTER openprinterNew(LPCWSTR pwszPrinterName);
     180static POPENPRINTER openprinterFind(HANDLE hHandle);
     181static void         openprinterDelete(POPENPRINTER pOpenPrinter);
     182static int          openprinterOpenSpoolFile(POPENPRINTER pOpenPrinter);
     183
     184
     185/**
     186 * Allocates, copies the data from pOpenPrinter into the new node and
     187 * inserts it into the list.
     188 *
     189 * @returns Pointer to the inserted node.
     190 * @returns NULL on failure (i.e. out of memory).
     191 * @param   pwszPrinterName     Pointer to printer name. (Duplicated)
     192 *
     193 */
     194static POPENPRINTER openprinterNew(LPCWSTR pwszPrinterName)
     195{
     196    POPENPRINTER    pNew = (POPENPRINTER)malloc(sizeof(*pNew));
     197    if (pNew)
     198    {
     199        memset(pNew, 0, sizeof(*pNew));
     200        pNew->pwszPrinterName = HEAP_strdupW(GetProcessHeap(), 0, pwszPrinterName);
     201        if (pNew->pwszPrinterName)
     202        {
     203            gOpenPrintersMutex.enter();
     204            pNew->hOpenPrinter = ++ghOpenPrintersLast;
     205            pNew->pNext = gpOpenPrinters;
     206            gpOpenPrinters = pNew;
     207            gOpenPrintersMutex.leave();
     208        }
     209        else
     210        {
     211            free(pNew);
     212            pNew = NULL;
     213        }
     214    }
     215    return pNew;
     216}
     217
     218
     219/**
     220 * Finds the data associated with an open printer handle.
     221 *
     222 * @returns Pointer to the data associated with the handle.
     223 * @param   hHandle     The handle of the open printer.
     224 */
     225static POPENPRINTER openprinterFind(HANDLE hHandle)
     226{
     227    POPENPRINTER pOpenPrinter;
     228
     229    gOpenPrintersMutex.enter();
     230    for (pOpenPrinter = gpOpenPrinters; pOpenPrinter; pOpenPrinter = pOpenPrinter->pNext)
     231        if (pOpenPrinter->hOpenPrinter == hHandle)
     232            break;
     233    gOpenPrintersMutex.leave();
     234    return pOpenPrinter;
     235}
     236
     237
     238/**
     239 * Unlinks and frees an open printer node.
     240 * The caller must release any other resources associated with it.
     241 *
     242 * @param   pOpenPrinter    Pointer to the node to delete.
     243 */
     244static void         openprinterDelete(POPENPRINTER pOpenPrinter)
     245{
     246    /*
     247     * Unlink it.
     248     */
     249    gOpenPrintersMutex.enter();
     250    if (gpOpenPrinters == pOpenPrinter)
     251        gpOpenPrinters = gpOpenPrinters->pNext;
     252    else
     253    {
     254        POPENPRINTER p;
     255        for (p = gpOpenPrinters; p->pNext; p = pOpenPrinter->pNext)
     256        {
     257            if (p->pNext == pOpenPrinter)
     258            {
     259                p->pNext = pOpenPrinter->pNext;
     260                break;
    157261            }
    158             //pComment empty
    159             break;
    160 
    161         case 2:
    162             pi2 = (PRINTER_INFO_2A *)lpbPrinters;
    163             lpbPrinters += sizeof(PRINTER_INFO_2A);
    164 
    165             pi2->pPrinterName = lpszPrinterStrings;
    166             strcpy(lpszPrinterStrings, printerInfo[i].pszPrintDestinationName);
    167             lpszPrinterStrings += strlen(printerInfo[i].pszPrintDestinationName)+1;
    168             pi2->pDriverName = pi2->pPrinterName;   //TODO:might not be correct!
    169 
    170             if(printerInfo[i].pszLocalName) {
    171                 pi2->pPortName = lpszPrinterStrings;
    172                 strcpy(lpszPrinterStrings, printerInfo[i].pszLocalName);
    173                 lpszPrinterStrings += strlen(printerInfo[i].pszLocalName)+1;
     262        }
     263        if (!p->pNext)
     264            pOpenPrinter = NULL;
     265    }
     266    gOpenPrintersMutex.leave();
     267
     268    /*
     269     * Delete it.
     270     */
     271    DebugAssert(pOpenPrinter, ("the node %p was not found!\n", pOpenPrinter));
     272    if (pOpenPrinter)
     273    {
     274        pOpenPrinter->pNext = NULL;
     275        free(pOpenPrinter);
     276    }
     277}
     278
     279/**
     280 * Opens the OS/2 spool file associated with the open printer if not
     281 * already opened.
     282 *
     283 * @returns NO_ERROR on success.
     284 * @returns OS/2 error code. May have changed the last error.
     285 * @param   pOpenPrinter    Open printer instance.
     286 */
     287static int        openprinterOpenSpoolFile(POPENPRINTER pOpenPrinter)
     288{
     289    if (pOpenPrinter->hspl)
     290        return NO_ERROR;
     291
     292    /*
     293     * First, get the queue name.
     294     */
     295    char    szQueue[16];
     296    int     rc = NO_ERROR;
     297    if (SplQueryPMQueueFromHandle(pOpenPrinter->hOpenPrinter, &szQueue[0], sizeof(szQueue)))
     298    {
     299        POSLIB_PRQINFO3 pPrqInfo3 = (POSLIB_PRQINFO3)OSLibSplQueryQueue(NULL, &szQueue[0], 3);
     300        if (pPrqInfo3)
     301        {
     302            OSLIB_DEVOPENSTRUC  DevOpen = {0};
     303            DevOpen.pszLogAddress = &szQueue[0];
     304            DevOpen.pszDriverName = pPrqInfo3->pszDriverName; /* always use default driver */
     305            pOpenPrinter->hspl = OSLibSplQmOpen(NULL, 4 /* must be 4 or more */, &DevOpen.pszLogAddress);
     306            if (pOpenPrinter->hspl)
     307            {
     308                dprintf(("WINSPOOL: openprinterOpenSpoolFile: handle %d -> hspl %#x\n",
     309                         pOpenPrinter->hOpenPrinter, pOpenPrinter->hspl));
     310                rc = NO_ERROR;
    174311            }
    175 
    176             if(printerInfo[i].pszComputerName) {
    177                 pi2->pServerName = lpszPrinterStrings;
    178                 strcpy(lpszPrinterStrings, printerInfo[i].pszComputerName);
    179                 lpszPrinterStrings += strlen(printerInfo[i].pszComputerName)+1;
     312            else
     313            {
     314                rc = OSLibSplWinGetLastError();
     315                DebugAssertFailed(("OSLibSplQmOpen failed! rc=%#x\n", rc));
    180316            }
    181 
    182             pi2->Attributes   = PRINTER_ATTRIBUTE_QUEUED;   //todo
    183 
    184             dprintf(("EnumPrinters level 2 NOT COMPLETE!!"));
    185             //todo not complete
    186             break;
    187 
    188         case 4:
    189             pi4 = (PRINTER_INFO_4A *)lpbPrinters;
    190             lpbPrinters += sizeof(PRINTER_INFO_4A);
    191 
    192             pi4->Attributes   = PRINTER_ATTRIBUTE_QUEUED;   //todo
    193             pi4->pPrinterName = lpszPrinterStrings;
    194             strcpy(lpszPrinterStrings, printerInfo[i].pszPrintDestinationName);
    195             lpszPrinterStrings += strlen(printerInfo[i].pszPrintDestinationName)+1;
    196 
    197             if(printerInfo[i].pszComputerName) {
    198                 pi4->pServerName = lpszPrinterStrings;
    199                 strcpy(lpszPrinterStrings, printerInfo[i].pszComputerName);
    200                 lpszPrinterStrings += strlen(printerInfo[i].pszComputerName)+1;
     317            free(pPrqInfo3);
     318        }
     319        else
     320        {
     321            rc = ERROR_GEN_FAILURE;
     322            DebugAssertFailed(("OSLibSplQueryQueue(,%s,3) failed\n", szQueue));
     323        }
     324    }
     325    else
     326    {
     327        rc = ERROR_GEN_FAILURE;
     328        DebugAssertFailed(("SplQueryPMQueueFromHandle failed\n"));
     329    }
     330    return rc;
     331}
     332
     333
     334/**
     335 * Gets the OS/2 queue name for an open printer device.
     336 *
     337 * @returns Success indicator.
     338 * @param   hPrinter    Printer handle.
     339 * @param   pszQueue    Where to put the queue name.
     340 * @param   cchQueue    Size of the queue buffer pointed to by pszQueue.
     341 */
     342BOOL WIN32API SplQueryPMQueueFromHandle(HANDLE hPrinter, char *pszQueue, unsigned cchQueue)
     343{
     344    BOOL            fRc = FALSE;
     345    DRIVER_INFO_1A *pInfo;
     346    DWORD           cbNeeded = 0;
     347
     348#ifdef USE_OS2_DRIVERNAME
     349    /*
     350     * Validate the handle.
     351     */
     352    POPENPRINTER   pPrt = openprinterFind(hPrinter);
     353    if (pPrt)
     354    {
     355        /*
     356         * Open the printer key in the registry.
     357         */
     358        HKEY hkeyPrinters;
     359        if (RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) == ERROR_SUCCESS)
     360        {
     361            HKEY hkeyPrinter;
     362            if (RegOpenKeyW(hkeyPrinters, pPrt->pwszPrinterName, &hkeyPrinter) == ERROR_SUCCESS)
     363            {
     364                /*
     365                 * Get the queue name.
     366                 */
     367                DWORD   cb = cchQueue;
     368                DWORD   dwType = 0;
     369                if (RegQueryValueExA(hkeyPrinter, "Description", NULL, &dwType, (LPBYTE)pszQueue, &cb) == ERROR_SUCCESS)
     370                {
     371                    pszQueue[cb] = '\0';    /* paranoia!!!! */
     372                    dprintf(("WINSPOOL: SplQueryPMQueueFromHandle: queuename=%s\n", pszQueue));
     373                    fRc = TRUE;
     374                }
     375                else
     376                {
     377                    DebugAssertFailed(("Could not query value 'Comment'\n"));
     378                    SetLastError(ERROR_GEN_FAILURE);
     379                }
     380                RegCloseKey(hkeyPrinter);
    201381            }
    202             dprintf(("EnumPrinters level 4 NOT COMPLETE!!"));
    203             break;
    204 
    205         case 5:
    206             pi5 = (PRINTER_INFO_5A *)lpbPrinters;
    207             lpbPrinters += sizeof(PRINTER_INFO_5A);
    208 
    209             pi5->Attributes   = PRINTER_ATTRIBUTE_QUEUED;   //todo
    210             pi5->pPrinterName = lpszPrinterStrings;
    211             strcpy(lpszPrinterStrings, printerInfo[i].pszPrintDestinationName);
    212             lpszPrinterStrings += strlen(printerInfo[i].pszPrintDestinationName)+1;
    213 
    214             if(printerInfo[i].pszLocalName) {
    215                 pi5->pPortName = lpszPrinterStrings;
    216                 strcpy(lpszPrinterStrings, printerInfo[i].pszLocalName);
    217                 lpszPrinterStrings += strlen(printerInfo[i].pszLocalName)+1;
     382            else
     383            {
     384                DebugAssertFailed(("Could not open printer '%ls' in the registry!!!\n",
     385                                   pPrt->pwszPrinterName));
     386                SetLastError(ERROR_INVALID_PRINTER_NAME);
    218387            }
    219             dprintf(("EnumPrinters level 5 NOT COMPLETE!!"));
    220             break;
     388            RegCloseKey(hkeyPrinters);
    221389        }
    222     }
    223     free(printerInfo);
    224 
    225     if(lpdwNeeded)
    226         *lpdwNeeded = used;
    227 
    228     if(lpdwReturned)
    229         *lpdwReturned = cReturned;
    230     SetLastError(ERROR_SUCCESS);
    231     return TRUE;
    232 }
    233 
    234 
    235 /*****************************************************************************
    236  * Name      : BOOL ClosePrinter
    237  * Purpose   :
    238  * Parameters:
    239  * Variables :
    240  * Result    :
    241  * Remark    :
    242  * Status    : UNTESTED STUB
    243  *
    244  * Author    : Markus Montkowski [09.07.98 13:39:08]
    245  *****************************************************************************/
    246 
    247 ODINFUNCTION1(BOOL, ClosePrinter,
    248               HANDLE, hPrinter)
    249 {
    250   dprintf(("ClosePrinter, not implemented\n"));
    251   return(TRUE);
    252 }
    253 
    254 
    255 /*****************************************************************************
    256  * Name      : BOOL OpenPrinterA
    257  * Purpose   :
    258  * Parameters:
    259  * Variables :
    260  * Result    :
    261  * Remark    :
    262  * Status    : UNTESTED STUB
    263  *
    264  * Author    : Markus Montkowski [09.07.98 13:39:08]
    265  *****************************************************************************/
    266 
    267 ODINFUNCTION3(BOOL, OpenPrinterA,
    268               LPSTR, pPrinterName,
    269               HANDLE *, phPrinter,
    270               PRINTER_DEFAULTSA *, pDefault)
    271 {
    272   dprintf(("OpenPrinterA, not implemented\n"));
    273   return(FALSE);
    274 }
    275 
    276 
    277 /*****************************************************************************
    278  * Name      : LONG DocumentPropertiesA
    279  * Purpose   :
    280  * Parameters:
    281  * Variables :
    282  * Result    :
    283  * Remark    :
    284  * Status    : UNTESTED STUB
    285  *
    286  * Author    : Markus Montkowski [09.07.98 13:39:08]
    287  *****************************************************************************/
    288 
    289 ODINFUNCTION6(LONG, DocumentPropertiesA,
    290               HWND, hwnd,
    291               HANDLE, hPrinter,
    292               LPSTR, lpszDeviceName,
    293               LPDEVMODEA, pdmOutput,
    294               LPDEVMODEA, pdmInput,
    295               DWORD, fMode)
    296 {
    297   dprintf(("DocumentPropertiesA, not implemented\n"));
    298   return(-1);
    299 }
    300 
    301 
    302 /*****************************************************************************
    303  * Name      : BOOL AbortPrinter
    304  * Purpose   :
    305  * Parameters: HANDLE hPrinter  handle to printer object
    306  * Variables :
    307  * Result    :
    308  * Remark    :
    309  * Status    : UNTESTED STUB
    310  *
    311  * Stub Generated through PE2LX Stubwizard 0.01 from Markus Montkowski
    312  *
    313  * Author    : Markus Montkowski [09.07.98 13:39:08]
    314  *****************************************************************************/
    315 
    316 ODINFUNCTION1(BOOL, AbortPrinter,
    317               HANDLE, hPrinter)
    318 
    319 {
    320   dprintf(("WINSPOOL: AbortPrinter not implemented\n"));
    321   return (FALSE);
    322 }
    323 
    324 
    325 
    326 /*****************************************************************************
    327  * Name      : BOOL AddFormA
    328  * Purpose   :
    329  * Parameters: HANDLE hPrinter  handle to printer object
    330  *             DWORD  Level     data-structure level
    331  *             LPBYTE pForm     pointer to form info. data structure
    332  * Variables :
    333  * Result    :
    334  * Remark    :
    335  * Status    : UNTESTED STUB
    336  *
    337  * Stub Generated through PE2LX Stubwizard 0.01 from Markus Montkowski
    338  *
    339  * Author    : Markus Montkowski [09.07.98 13:47:45]
    340  *****************************************************************************/
    341 
    342 ODINFUNCTION3(BOOL, AddFormA,
    343               HANDLE, hPrinter,
    344               DWORD, Level,
    345               LPBYTE, pForm)
    346 {
    347   dprintf(("WINSPOOL: AddFormA not implemented\n"));
    348   return (FALSE);
    349 }
    350 
    351 /*****************************************************************************
    352  * Name      : BOOL AddFormW
    353  * Purpose   :
    354  * Parameters: HANDLE hPrinter  handle to printer object
    355  *             DWORD  Level     data-structure level
    356  *             LPBYTE pForm     pointer to form info. data structure
    357  * Variables :
    358  * Result    :
    359  * Remark    :
    360  * Status    : UNTESTED STUB
    361  *
    362  * Stub Generated through PE2LX Stubwizard 0.01 from Markus Montkowski
    363  *
    364  * Author    : Markus Montkowski [09.07.98 13:47:45]
    365  *****************************************************************************/
    366 
    367 ODINFUNCTION3(BOOL, AddFormW,
    368               HANDLE, hPrinter,
    369               DWORD, Level,
    370               LPBYTE, pForm)
    371 {
    372   dprintf(("WINSPOOL: AddFormW not implemented\n"));
    373   return (FALSE);
    374 }
    375 
    376 
    377 /*****************************************************************************
    378  * Name      : BOOL AddJobA
    379  * Purpose   :
    380  * Parameters: HANDLE hPrinter  specifies printer for the print job
    381  *             DWORD Level  specifies version of print job information data structure
    382  *             LPBYTE pData  pointer to buffer to receive print job information data
    383  *             DWORD cbBuf  specifies size of buffer pointed to by pData
    384  *             LPDWORD pcbNeeded  pointer to variable to receive size of print job information data
    385  * Variables :
    386  * Result    :
    387  * Remark    :
    388  * Status    : UNTESTED STUB
    389  *
    390  * Stub Generated through PE2LX Stubwizard 0.01 from Markus Montkowski
    391  *
    392  * Author    : Markus Montkowski [09.07.98 13:50:28]
    393  *****************************************************************************/
    394 
    395 ODINFUNCTION5(BOOL, AddJobA,
    396               HANDLE, hPrinter,
    397               DWORD, Level,
    398               LPBYTE, pData,
    399               DWORD, cbBuf,
    400               LPDWORD, pcbNeeded)
    401 {
    402   dprintf(("WINSPOOL: AddJobA not implemented\n"));
    403   return (FALSE);
    404 }
    405 
    406 /*****************************************************************************
    407  * Name      : BOOL AddJobW
    408  * Purpose   :
    409  * Parameters: HANDLE  hPrinter   specifies printer for the print job
    410  *             DWORD   Level      specifies version of print job information
    411  *                                data structure
    412  *             LPBYTE  pData      pointer to buffer to receive print job
    413  *                                information data
    414  *             DWORD   cbBuf      specifies size of buffer pointed to by pData
    415  *             LPDWORD pcbNeeded  pointer to variable to receive size of print
    416  *                                job information data
    417  * Variables :
    418  * Result    :
    419  * Remark    :
    420  * Status    : UNTESTED STUB
    421  *
    422  * Stub Generated through PE2LX Stubwizard 0.01 from Markus Montkowski
    423  *
    424  * Author    : Markus Montkowski [09.07.98 13:50:28]
    425  *****************************************************************************/
    426 
    427 ODINFUNCTION5(BOOL, AddJobW,
    428               HANDLE, hPrinter,
    429               DWORD, Level,
    430               LPBYTE, pData,
    431               DWORD, cbBuf,
    432               LPDWORD, pcbNeeded)
    433 {
    434   dprintf(("WINSPOOL: AddJobW not implemented\n"));
    435   return (FALSE);
    436 }
    437 
    438 
    439 /*****************************************************************************
    440  * Name      : BOOL AddMonitorA
    441  * Purpose   :
    442  * Parameters: LPSTR pName  pointer to server name
    443  *             DWORD Level  monitor info. structure level
    444  *             LPBYTE pMonitors  pointer to monitor info. structure
    445  * Variables :
    446  * Result    :
    447  * Remark    :
    448  * Status    : UNTESTED STUB
    449  *
    450  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    451  *
    452  * Author    : Markus Montkowski [09.07.98 14:15:55]
    453  *****************************************************************************/
    454 
    455 ODINFUNCTION3(BOOL, AddMonitorA,
    456               LPSTR, pName,
    457               DWORD, Level,
    458               LPBYTE, pMonitors)
    459 {
    460   dprintf(("WINSPOOL: AddMonitorA not implemented\n"));
    461   return (FALSE);
    462 }
    463 
    464 
    465 /*****************************************************************************
    466  * Name      : BOOL AddMonitorW
    467  * Purpose   :
    468  * Parameters: LPWSTR pName  pointer to server name
    469  *             DWORD Level  monitor info. structure level
    470  *             LPBYTE pMonitors  pointer to monitor info. structure
    471  * Variables :
    472  * Result    :
    473  * Remark    :
    474  * Status    : UNTESTED STUB
    475  *
    476  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    477  *
    478  * Author    : Markus Montkowski [09.07.98 14:15:55]
    479  *****************************************************************************/
    480 
    481 ODINFUNCTION3(BOOL, AddMonitorW,
    482               LPWSTR, pName,
    483               DWORD, Level,
    484               LPBYTE, pMonitors)
    485 {
    486   dprintf(("WINSPOOL: AddMonitorW not implemented\n"));
    487   return (FALSE);
    488 }
    489 
    490 
    491 /*****************************************************************************
    492  * Name      : BOOL AddPortA
    493  * Purpose   :
    494  * Parameters: LPSTR pName  pointer to a server name
    495  *             HWND hWnd  handle to parent window
    496  *             LPSTR pMonitorName  pointer to a monitor name
    497  * Variables :
    498  * Result    :
    499  * Remark    :
    500  * Status    : UNTESTED STUB
    501  *
    502  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    503  *
    504  * Author    : Markus Montkowski [09.07.98 14:16:31]
    505  *****************************************************************************/
    506 
    507 ODINFUNCTION3(BOOL, AddPortA,
    508               LPSTR, pName,
    509               HWND, hWnd,
    510               LPSTR, pMonitorName)
    511 {
    512   dprintf(("WINSPOOL: AddPortA not implemented\n"));
    513   return (FALSE);
    514 }
    515 
    516 
    517 /*****************************************************************************
    518  * Name      : BOOL AddPortW
    519  * Purpose   :
    520  * Parameters: LPWSTR pName  pointer to a server name
    521  *             HWND hWnd  handle to parent window
    522  *             LPWSTR pMonitorName  pointer to a monitor name
    523  * Variables :
    524  * Result    :
    525  * Remark    :
    526  * Status    : UNTESTED STUB
    527  *
    528  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    529  *
    530  * Author    : Markus Montkowski [09.07.98 14:16:31]
    531  *****************************************************************************/
    532 
    533 ODINFUNCTION3(BOOL, AddPortW,
    534               LPWSTR, pName,
    535               HWND, hWnd,
    536               LPWSTR, pMonitorName)
    537 {
    538   dprintf(("WINSPOOL: AddPortW not implemented\n"));
    539   return (FALSE);
    540 }
    541 
    542 
    543 /*****************************************************************************
    544  * Name      : BOOL AddPrintProcessorA
    545  * Purpose   :
    546  * Parameters: LPSTR pName  pointer to server name
    547  *             LPSTR pEnvironment  pointer to environment name
    548  *             LPSTR pPathName  pointer to path
    549  *             LPSTR pPrintProcessorName  pointer to print-processor name
    550  * Variables :
    551  * Result    :
    552  * Remark    :
    553  * Status    : UNTESTED STUB
    554  *
    555  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    556  *
    557  * Author    : Markus Montkowski [09.07.98 14:17:46]
    558  *****************************************************************************/
    559 
    560 ODINFUNCTION4(BOOL, AddPrintProcessorA,
    561               LPSTR, pName,
    562               LPSTR, pEnvironment,
    563               LPSTR, pPathName,
    564               LPSTR, pPrintProcessorName)
    565 {
    566   dprintf(("WINSPOOL: AddPrintProcessorA not implemented\n"));
    567   return (FALSE);
    568 }
    569 
    570 
    571 /*****************************************************************************
    572  * Name      : BOOL AddPrintProcessorW
    573  * Purpose   :
    574  * Parameters: LPWSTR pName  pointer to server name
    575  *             LPWSTR pEnvironment  pointer to environment name
    576  *             LPWSTR pPathName  pointer to path
    577  *             LPWSTR pPrintProcessorName  pointer to print-processor name
    578  * Variables :
    579  * Result    :
    580  * Remark    :
    581  * Status    : UNTESTED STUB
    582  *
    583  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    584  *
    585  * Author    : Markus Montkowski [09.07.98 14:17:46]
    586  *****************************************************************************/
    587 
    588 ODINFUNCTION4(BOOL, AddPrintProcessorW,
    589               LPWSTR, pName,
    590               LPWSTR, pEnvironment,
    591               LPWSTR, pPathName,
    592               LPWSTR, pPrintProcessorName)
    593 {
    594   dprintf(("WINSPOOL: AddPrintProcessorW not implemented\n"));
    595   return (FALSE);
    596 }
    597 
    598 
    599 /*****************************************************************************
    600  * Name      : BOOL AddPrintProvidorA
    601  * Purpose   :
    602  * Parameters: LPSTR pName  pointer to server name
    603  *             DWORD Level  provider information structure level
    604  *             LPBYTE pProvidorInfo  pointer to provider information structure
    605  * Variables :
    606  * Result    :
    607  * Remark    :
    608  * Status    : UNTESTED STUB
    609  *
    610  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    611  *
    612  * Author    : Markus Montkowski [09.07.98 14:18:16]
    613  *****************************************************************************/
    614 
    615 ODINFUNCTION3(BOOL, AddPrintProvidorA,
    616               LPSTR, pName,
    617               DWORD, Level,
    618               LPBYTE, pProvidorInfo)
    619 {
    620   dprintf(("WINSPOOL: AddPrintProvidorA not implemented\n"));
    621   return (FALSE);
    622 }
    623 
    624 
    625 /*****************************************************************************
    626  * Name      : BOOL AddPrintProvidorW
    627  * Purpose   :
    628  * Parameters: LPWSTR pName  pointer to server name
    629  *             DWORD Level  provider information structure level
    630  *             LPBYTE pProvidorInfo  pointer to provider information structure
    631  * Variables :
    632  * Result    :
    633  * Remark    :
    634  * Status    : UNTESTED STUB
    635  *
    636  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    637  *
    638  * Author    : Markus Montkowski [09.07.98 14:18:16]
    639  *****************************************************************************/
    640 
    641 ODINFUNCTION3(BOOL, AddPrintProvidorW,
    642               LPWSTR, pName,
    643               DWORD, Level,
    644               LPBYTE, pProvidorInfo)
    645 {
    646   dprintf(("WINSPOOL: AddPrintProvidorW not implemented\n"));
    647   return (FALSE);
    648 }
    649 
    650 
    651 /*****************************************************************************
    652  * Name      : HANDLE AddPrinterA
    653  * Purpose   :
    654  * Parameters: LPSTR pName  pointer to server name
    655  *             DWORD Level  printer info. structure level
    656  *             LPBYTE pPrinter  pointer to structure
    657  * Variables :
    658  * Result    :
    659  * Remark    :
    660  * Status    : UNTESTED STUB
    661  *
    662  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    663  *
    664  * Author    : Markus Montkowski [09.07.98 14:18:56]
    665  *****************************************************************************/
    666 
    667 ODINFUNCTION3(HANDLE, AddPrinterA,
    668               LPSTR, pName,
    669               DWORD, Level,
    670               LPBYTE, pPrinter)
    671 {
    672   dprintf(("WINSPOOL: AddPrinterA not implemented\n"));
    673   return (NULL);
    674 }
    675 
    676 
    677 /*****************************************************************************
    678  * Name      : HANDLE AddPrinterW
    679  * Purpose   :
    680  * Parameters: LPWSTR pName  pointer to server name
    681  *             DWORD Level  printer info. structure level
    682  *             LPBYTE pPrinter  pointer to structure
    683  * Variables :
    684  * Result    :
    685  * Remark    :
    686  * Status    : UNTESTED STUB
    687  *
    688  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    689  *
    690  * Author    : Markus Montkowski [09.07.98 14:18:56]
    691  *****************************************************************************/
    692 
    693 ODINFUNCTION3(HANDLE, AddPrinterW,
    694               LPWSTR, pName,
    695               DWORD, Level,
    696               LPBYTE, pPrinter)
    697 {
    698   dprintf(("WINSPOOL: AddPrinterW not implemented\n"));
    699   return (NULL);
    700 }
    701 
    702 
    703 /*****************************************************************************
    704  * Name      : BOOL AddPrinterConnectionA
    705  * Purpose   :
    706  * Parameters: LPSTR pName  pointer to printer name
    707  * Variables :
    708  * Result    :
    709  * Remark    :
    710  * Status    : UNTESTED STUB
    711  *
    712  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    713  *
    714  * Author    : Markus Montkowski [09.07.98 14:19:22]
    715  *****************************************************************************/
    716 
    717 ODINFUNCTION1(BOOL, AddPrinterConnectionA,
    718               LPSTR, pName)
    719 {
    720   dprintf(("WINSPOOL: AddPrinterConnectionA not implemented\n"));
    721   return (FALSE);
    722 }
    723 
    724 
    725 /*****************************************************************************
    726  * Name      : BOOL AddPrinterConnectionW
    727  * Purpose   :
    728  * Parameters: LPWSTR pName  pointer to printer name
    729  * Variables :
    730  * Result    :
    731  * Remark    :
    732  * Status    : UNTESTED STUB
    733  *
    734  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    735  *
    736  * Author    : Markus Montkowski [09.07.98 14:19:22]
    737  *****************************************************************************/
    738 
    739 ODINFUNCTION1(BOOL, AddPrinterConnectionW,
    740               LPWSTR, pName)
    741 {
    742   dprintf(("WINSPOOL: AddPrinterConnectionW not implemented\n"));
    743   return (FALSE);
    744 }
    745 
    746 
    747 /*****************************************************************************
    748  * Name      : BOOL AddPrinterDriverA
    749  * Purpose   :
    750  * Parameters: LPSTR pName  pointer to server name
    751  *             DWORD Level  printer info. structure level
    752  *             LPBYTE pDriverInfo  pointer to printer info. structure
    753  * Variables :
    754  * Result    :
    755  * Remark    :
    756  * Status    : UNTESTED STUB
    757  *
    758  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    759  *
    760  * Author    : Markus Montkowski [09.07.98 14:20:04]
    761  *****************************************************************************/
    762 
    763 ODINFUNCTION3(BOOL, AddPrinterDriverA,
    764               LPSTR, pName,
    765               DWORD, Level,
    766               LPBYTE, pDriverInfo)
    767 {
    768   dprintf(("WINSPOOL: AddPrinterDriverA not implemented\n"));
    769   return (FALSE);
    770 }
    771 
    772 
    773 /*****************************************************************************
    774  * Name      : BOOL AddPrinterDriverW
    775  * Purpose   :
    776  * Parameters: LPWSTR pName  pointer to server name
    777  *             DWORD Level  printer info. structure level
    778  *             LPBYTE pDriverInfo  pointer to printer info. structure
    779  * Variables :
    780  * Result    :
    781  * Remark    :
    782  * Status    : UNTESTED STUB
    783  *
    784  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    785  *
    786  * Author    : Markus Montkowski [09.07.98 14:20:04]
    787  *****************************************************************************/
    788 
    789 ODINFUNCTION3(BOOL, AddPrinterDriverW,
    790               LPWSTR, pName,
    791               DWORD, Level,
    792               LPBYTE, pDriverInfo)
    793 {
    794   dprintf(("WINSPOOL: AddPrinterDriverW not implemented\n"));
    795   return (FALSE);
    796 }
    797 
    798 
    799 /*****************************************************************************
    800  * Name      : LONG AdvancedDocumentPropertiesA
    801  * Purpose   :
    802  * Parameters: HWND hWnd  handle to dialog box's parent window
    803  *             HANDLE hPrinter  handle to printer object
    804  *             LPSTR pDeviceName  pointer to driver name
    805  *             LPDEVMODEA pDevModeInput  pointer to modified device mode structure
    806  *             LPDEVMODEA pDevModeInput  pointer to original device mode structure
    807  * Variables :
    808  * Result    :
    809  * Remark    :
    810  * Status    : UNTESTED STUB
    811  *
    812  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    813  *
    814  * Author    : Markus Montkowski [09.07.98 14:21:59]
    815  *****************************************************************************/
    816 
    817 ODINFUNCTION5(LONG, AdvancedDocumentPropertiesA,
    818               HWND, hWnd,
    819               HANDLE, hPrinter,
    820               LPSTR, pDeviceName,
    821               LPDEVMODEA, pDevModeOutput,
    822               LPDEVMODEA, pDevModeInput)
    823 {
    824   dprintf(("WINSPOOL: AdvancedDocumentPropertiesA not implemented\n"));
    825   return (0);
    826 }
    827 
    828 
    829 /*****************************************************************************
    830  * Name      : LONG AdvancedDocumentPropertiesW
    831  * Purpose   :
    832  * Parameters: HWND hWnd  handle to dialog box's parent window
    833  *             HANDLE hPrinter  handle to printer object
    834  *             LPWSTR pDeviceName  pointer to driver name
    835  *             LPDEVMODEW pDevModeOutput  pointer to modified device mode structure
    836  *             LPDEVMODEW pDevModeInput  pointer to original device mode structure
    837  * Variables :
    838  * Result    :
    839  * Remark    :
    840  * Status    : UNTESTED STUB
    841  *
    842  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    843  *
    844  * Author    : Markus Montkowski [09.07.98 14:21:59]
    845  *****************************************************************************/
    846 
    847 ODINFUNCTION5(LONG, AdvancedDocumentPropertiesW,
    848               HWND, hWnd,
    849               HANDLE, hPrinter,
    850               LPWSTR, pDeviceName,
    851               LPDEVMODEW, pDevModeOutput,
    852               LPDEVMODEW, pDevModeInput)
    853 {
    854   dprintf(("WINSPOOL: AdvancedDocumentPropertiesW not implemented\n"));
    855   return (0);
    856 }
    857 
    858 
    859 /*****************************************************************************
    860  * Name      : BOOL ConfigurePortA
    861  * Purpose   :
    862  * Parameters: LPSTR pName  pointer to server name
    863  *             HWND hWnd  handle to parent window of the dialog box
    864  *             LPSTR pPortName  pointer to port name
    865  * Variables :
    866  * Result    :
    867  * Remark    :
    868  * Status    : UNTESTED STUB
    869  *
    870  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    871  *
    872  * Author    : Markus Montkowski [09.07.98 14:24:42]
    873  *****************************************************************************/
    874 
    875 ODINFUNCTION3(BOOL, ConfigurePortA,
    876               LPSTR, pName,
    877               HWND, hWnd,
    878               LPSTR, pPortName)
    879 {
    880   dprintf(("WINSPOOL: ConfigurePortA not implemented\n"));
    881   return (FALSE);
    882 }
    883 
    884 
    885 /*****************************************************************************
    886  * Name      : BOOL ConfigurePortW
    887  * Purpose   :
    888  * Parameters: LPWSTR pName  pointer to server name
    889  *             HWND hWnd  handle to parent window of the dialog box
    890  *             LPWSTR pPortName  pointer to port name
    891  * Variables :
    892  * Result    :
    893  * Remark    :
    894  * Status    : UNTESTED STUB
    895  *
    896  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    897  *
    898  * Author    : Markus Montkowski [09.07.98 14:24:43]
    899  *****************************************************************************/
    900 
    901 ODINFUNCTION3(BOOL, ConfigurePortW,
    902               LPWSTR, pName,
    903               HWND, hWnd,
    904               LPWSTR, pPortName)
    905 {
    906   dprintf(("WINSPOOL: ConfigurePortW not implemented\n"));
    907   return (FALSE);
    908 }
    909 
    910 
    911 /*****************************************************************************
    912  * Name      : HANDLE ConnectToPrinterDlg
    913  * Purpose   :
    914  * Parameters: HWND hwnd  handle to parent window of dialog box
    915  *             DWORD Flags  reserved for future use, must be zero
    916  * Variables :
    917  * Result    :
    918  * Remark    :
    919  * Status    : UNTESTED STUB
    920  *
    921  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    922  *
    923  * Author    : Markus Montkowski [09.07.98 14:25:13]
    924  *****************************************************************************/
    925 
    926 ODINFUNCTION2(HANDLE, ConnectToPrinterDlg,
    927               HWND, hwnd,
    928               DWORD, Flags)
    929 {
    930   dprintf(("WINSPOOL: ConnectToPrinterDlg not implemented\n"));
    931   return (NULL);
    932 }
    933 
     390        else
     391            SetLastError(ERROR_GEN_FAILURE);
     392    }
     393    else
     394        DebugAssertFailed(("Invalid handle %#x\n", hPrinter));
     395#else
     396    /* the old method of storing it in the printer driver name. */
     397    GetPrinterDriverA(hPrinter, NULL, 1, NULL, 0, &cbNeeded);
     398    pInfo = (DRIVER_INFO_1A *)malloc(cbNeeded);
     399    if (pInfo)
     400    {
     401        fRc = GetPrinterDriverA(hPrinter, NULL, 1, (LPBYTE)pInfo, cbNeeded, &cbNeeded)
     402            &&  cbNeeded - sizeof(DRIVER_INFO_1A) < cchQueue;
     403        DebugAssert(fRc, ("GetPrinterDriverA failed or buffer to small.\n"));
     404        if (fRc)
     405            strcpy(pszQueue, pInfo->pName);
     406        free(pInfo);
     407    }
     408#endif
     409
     410    if (!fRc)
     411        dprintf(("WINSPOOL: SplQueryPMQueueFromHandle failed!\n"));
     412    return fRc;
     413}
     414
     415/**
     416 * Get the PM printer queue name associated with the printer name
     417 *
     418 * @returns Success indicator.
     419 * @param   pszPrinterName  Printer device name.
     420 * @param   pszQueue        Where to put the queue name.
     421 * @param   cchQueue        Size of the queue buffer pointed to by pszQueue.
     422 */
     423BOOL WIN32API SplQueryPMQueueName(LPSTR pszPrinterName, LPSTR pszQueue, INT cchQueue)
     424{
     425    BOOL   fRc = FALSE;
     426    HANDLE hPrinter;
     427
     428    // Get the PM Queue name corresponding to the printer device
     429    if (OpenPrinterA(pszPrinterName, &hPrinter, NULL))
     430    {
     431        fRc = SplQueryPMQueueFromHandle(hPrinter, pszQueue, cchQueue);
     432        ClosePrinter(hPrinter);
     433    }
     434
     435    return fRc;
     436}
     437
     438/*************************************************************************
     439 * SHDeleteKeyA   [SHLWAPI.@]
     440 *
     441 * Delete a registry key and any sub keys/values present
     442 *
     443 * PARAMS
     444 *   hKey       [I] Handle to registry key
     445 *   lpszSubKey [I] Name of sub key to delete
     446 *
     447 * RETURNS
     448 *   Success: ERROR_SUCCESS. The key is deleted.
     449 *   Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
     450 *          RegEnumKeyExA or RegDeleteKeyA.
     451 *
     452 *
     453 * (Rewind code)
     454 *
     455 * NOTE: I don't want a dependency on shlwapi in winspool
     456 *
     457 */
     458static DWORD SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
     459{
     460  DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
     461  WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
     462  HKEY hSubKey = 0;
     463
     464  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
     465  if(!dwRet)
     466  {
     467    /* Find how many subkeys there are */
     468    dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
     469                             &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
     470    if(!dwRet)
     471    {
     472      dwMaxSubkeyLen++;
     473      if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
     474        /* Name too big: alloc a buffer for it */
     475        lpszName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
     476
     477      if(!lpszName)
     478        dwRet = ERROR_NOT_ENOUGH_MEMORY;
     479      else
     480      {
     481        /* Recursively delete all the subkeys */
     482        for(i = 0; i < dwKeyCount && !dwRet; i++)
     483        {
     484          dwSize = dwMaxSubkeyLen;
     485          dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
     486          if(!dwRet)
     487            dwRet = SHDeleteKeyW(hSubKey, lpszName);
     488        }
     489
     490        if (lpszName != szNameBuf)
     491          HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
     492      }
     493    }
     494
     495    RegCloseKey(hSubKey);
     496    if(!dwRet)
     497      dwRet = RegDeleteKeyW(hKey, lpszSubKey);
     498  }
     499  return dwRet;
     500}
     501
     502#endif /* __WIN32OS2__ */
     503
     504
     505static inline DWORD set_reg_szW(HKEY hkey, WCHAR *keyname, WCHAR *value)
     506{
     507#if 0 /* bird: On OS/2 the API expects number of chars of unicode strings.
     508       * On Win32 you are required to include the '\0' in the count. */
     509    return RegSetValueExW(hkey, keyname, 0, REG_SZ, (LPBYTE)value,
     510                   lstrlenW(value) * sizeof(WCHAR));
     511#else
     512    return RegSetValueExW(hkey, keyname, 0, REG_SZ, (LPBYTE)value, lstrlenW(value) + 1);
     513#endif
     514}
     515
     516/***********************************************************
     517 *      DEVMODEcpyAtoW
     518 */
     519static LPDEVMODEW DEVMODEcpyAtoW(DEVMODEW *dmW, const DEVMODEA *dmA)
     520{
     521    BOOL Formname;
     522    ptrdiff_t off_formname = (char *)dmA->dmFormName - (char *)dmA;
     523    DWORD size;
     524
     525    Formname = (dmA->dmSize > off_formname);
     526    size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
     527    MultiByteToWideChar(CP_ACP, 0, (LPCSTR)dmA->dmDeviceName, -1, dmW->dmDeviceName,
     528                        CCHDEVICENAME);
     529    if(!Formname) {
     530      memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
     531             dmA->dmSize - CCHDEVICENAME);
     532    } else {
     533      memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
     534             off_formname - CCHDEVICENAME);
     535      MultiByteToWideChar(CP_ACP, 0, (LPCSTR)dmA->dmFormName, -1, dmW->dmFormName,
     536                          CCHFORMNAME);
     537      memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA->dmSize -
     538             (off_formname + CCHFORMNAME));
     539    }
     540    dmW->dmSize = size;
     541    memcpy((char *)dmW + dmW->dmSize, (char *)dmA + dmA->dmSize,
     542           dmA->dmDriverExtra);
     543    return dmW;
     544}
     545
     546/***********************************************************
     547 *      DEVMODEdupAtoW
     548 * Creates a unicode copy of supplied devmode on heap
     549 */
     550static LPDEVMODEW DEVMODEdupAtoW(HANDLE heap, const DEVMODEA *dmA)
     551{
     552    LPDEVMODEW dmW;
     553    DWORD size;
     554    BOOL Formname;
     555    ptrdiff_t off_formname;
     556
     557    if(!dmA) return NULL;
     558
     559    off_formname = (char *)dmA->dmFormName - (char *)dmA;
     560    Formname = (dmA->dmSize > off_formname);
     561    size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
     562    dmW = (LPDEVMODEW) HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmA->dmDriverExtra);
     563    return DEVMODEcpyAtoW(dmW, dmA);
     564}
    934565
    935566/***********************************************************
     
    967598}
    968599
     600/******************************************************************
     601 *  WINSPOOL_GetOpenedPrinter
     602 *  Get the pointer to the opened printer referred by the handle
     603 */
     604static LPCWSTR WINSPOOL_GetOpenedPrinter(HANDLE printerHandle)
     605{
     606#ifdef __WIN32OS2__
     607    POPENPRINTER    p = openprinterFind(printerHandle);
     608    if (p)
     609        return p->pwszPrinterName;
     610    SetLastError(ERROR_INVALID_HANDLE);
     611    return NULL;
     612#else
     613    int idx = (int)printerHandle;
     614    if ((idx <= 0) || (idx > nb_printers))
     615    {
     616        SetLastError(ERROR_INVALID_HANDLE);
     617        return NULL;
     618    }
     619    return printer_array[idx - 1];
     620#endif
     621}
     622
     623
     624/*****************************************************************************
     625 *          WINSPOOL_OpenDriverReg [internal]
     626 *
     627 * opens the registry for the printer drivers depending on the given input
     628 * variable pEnvironment
     629 *
     630 * RETURNS:
     631 *    the opened hkey on success
     632 *    NULL on error
     633 */
     634static HKEY WINSPOOL_OpenDriverReg( LPVOID pEnvironment, BOOL unicode)
     635{   HKEY  retval;
     636    LPSTR lpKey, p = NULL;
     637
     638#ifdef DEBUG                            /* __WIN32OS2__ */
     639    dprintf(("%s\n",
     640          (unicode) ? debugstr_w((LPCWSTR)pEnvironment) : debugstr_a((LPCSTR)pEnvironment)));
     641#endif                                  /* __WIN32OS2__ */
     642
     643    if(pEnvironment)
     644        p = (unicode) ? (LPSTR)HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)pEnvironment) :
     645                       (LPSTR) pEnvironment;
     646    else {
     647        OSVERSIONINFOA ver;
     648        ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
     649
     650        if(!GetVersionExA( &ver))
     651            return 0;
     652
     653        switch (ver.dwPlatformId) {
     654             case VER_PLATFORM_WIN32s:
     655                  ERR("win32 style printing used with 16 bits app, try specifying 'win95' Windows version\n");
     656                  return 0;
     657
     658             case VER_PLATFORM_WIN32_NT:
     659                  p = "Windows NT x86";
     660                  break;
     661             default:
     662                  p = "Windows 4.0";
     663                  break;
     664        }
     665        TRACE("set environment to %s\n", p);
     666    }
     667
     668    lpKey = (char*) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
     669                       strlen(p) + strlen(Drivers));
     670    sprintf( lpKey, Drivers, p);
     671
     672    TRACE("%s\n", lpKey);
     673
     674    if(RegCreateKeyA(HKEY_LOCAL_MACHINE, lpKey, &retval) !=
     675       ERROR_SUCCESS)
     676       retval = 0;
     677
     678    if(pEnvironment && unicode)
     679       HeapFree( GetProcessHeap(), 0, p);
     680    HeapFree( GetProcessHeap(), 0, lpKey);
     681
     682    return retval;
     683}
     684
     685
     686/*****************************************************************************
     687 *    WINSPOOL_GetStringFromReg
     688 *
     689 * Get ValueName from hkey storing result in ptr.  buflen is space left in ptr
     690 * String is stored either as unicode or ascii.
     691 * Bit of a hack here to get the ValueName if we want ascii.
     692 */
     693static BOOL WINSPOOL_GetStringFromReg(HKEY hkey, LPCWSTR ValueName, LPBYTE ptr,
     694                                      DWORD buflen, DWORD *needed,
     695                                      BOOL unicode)
     696{
     697    DWORD sz = buflen, type;
     698    LONG ret;
     699
     700    if(unicode)
     701        ret = RegQueryValueExW(hkey, (LPWSTR)ValueName, 0, &type, ptr, &sz);
     702    else {
     703        LPSTR ValueNameA = HEAP_strdupWtoA(GetProcessHeap(),0,ValueName);
     704        ret = RegQueryValueExA(hkey, ValueNameA, 0, &type, ptr, &sz);
     705        HeapFree(GetProcessHeap(),0,ValueNameA);
     706    }
     707    if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
     708        WARN("Got ret = %ld\n", ret);
     709        *needed = 0;
     710        return FALSE;
     711    }
     712    *needed = sz;
     713    return TRUE;
     714}
     715
     716
     717/*****************************************************************************
     718 *    WINSPOOL_SetDevModeFromReg
     719 *
     720 * Get ValueName from hkey storing result in ptr.  buflen is space left in ptr
     721 * DevMode is stored either as unicode or ascii.
     722 */
     723static BOOL WINSPOOL_SetDevModeFromReg(HKEY hkey, LPCWSTR ValueName,
     724                                       LPBYTE ptr, DWORD buflen)
     725{
     726    DWORD sz = buflen, type;
     727    LONG ret;
     728
     729    ret = RegSetValueExW(hkey, (LPWSTR)ValueName, 0, REG_BINARY, ptr, sz);
     730    if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0;
     731    if (sz < sizeof(DEVMODEA))
     732    {
     733        ERR("failed to write DEVMODEA for %s ( size %ld)\n",debugstr_w(ValueName),sz);
     734        return FALSE;
     735    }
     736    return TRUE;
     737}
     738
     739/*****************************************************************************
     740 *    WINSPOOL_GetDevModeFromReg
     741 *
     742 * Get ValueName from hkey storing result in ptr.  buflen is space left in ptr
     743 * DevMode is stored either as unicode or ascii.
     744 */
     745static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName,
     746                                       LPBYTE ptr,
     747                                       DWORD buflen, DWORD *needed,
     748                                       BOOL unicode)
     749{
     750    DWORD sz = buflen, type;
     751    LONG ret;
     752
     753    if (ptr && buflen>=sizeof(DEVMODEA)) memset(ptr, 0, sizeof(DEVMODEA));
     754    ret = RegQueryValueExW(hkey, (LPWSTR)ValueName, 0, &type, ptr, &sz);
     755    if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0;
     756    if (sz < sizeof(DEVMODEA))
     757    {
     758        ERR("corrupted registry for %s ( size %ld)\n",debugstr_w(ValueName),sz);
     759        return FALSE;
     760    }
     761    /* ensures that dmSize is not erratically bogus if registry is invalid */
     762    if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA))
     763        ((DEVMODEA*)ptr)->dmSize = sizeof(DEVMODEA);
     764    if(unicode) {
     765        sz += (CCHDEVICENAME + CCHFORMNAME);
     766        if(buflen >= sz) {
     767            DEVMODEW *dmW = DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA*)ptr);
     768            memcpy(ptr, dmW, sz);
     769            HeapFree(GetProcessHeap(),0,dmW);
     770        }
     771    }
     772    *needed = sz;
     773    return TRUE;
     774}
     775
     776/*****************************************************************************
     777 *    WINSPOOL_GetDWORDFromReg
     778 *
     779 * Return DWORD associated with ValueName from hkey.
     780 */
     781static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName)
     782{
     783    DWORD sz = sizeof(DWORD), type, value = 0;
     784    LONG ret;
     785
     786    ret = RegQueryValueExA(hkey, (LPSTR)ValueName, 0, &type, (LPBYTE)&value, &sz);
     787
     788    if(ret != ERROR_SUCCESS) {
     789        WARN("Got ret = %ld on name %s\n", ret, ValueName);
     790        return 0;
     791    }
     792    if(type != REG_DWORD) {
     793        ERR("Got type %ld\n", type);
     794        return 0;
     795    }
     796    return value;
     797}
     798
     799/*****************************************************************************
     800 *    WINSPOOL_GetDefaultDevMode
     801 *
     802 * Get a default DevMode values for wineps.
     803 * FIXME - use ppd.
     804 */
     805
     806static void WINSPOOL_GetDefaultDevMode(
     807        LPBYTE ptr,
     808        DWORD buflen, DWORD *needed,
     809        BOOL unicode)
     810{
     811    DEVMODEA    dm;
     812
     813        /* fill default DEVMODE - should be read from ppd... */
     814        ZeroMemory( &dm, sizeof(dm) );
     815        strcpy((char*)dm.dmDeviceName,"wineps");
     816        dm.dmSpecVersion = DM_SPECVERSION;
     817        dm.dmDriverVersion = 1;
     818        dm.dmSize = sizeof(DEVMODEA);
     819        dm.dmDriverExtra = 0;
     820        dm.dmFields =
     821                DM_ORIENTATION | DM_PAPERSIZE |
     822                DM_PAPERLENGTH | DM_PAPERWIDTH |
     823                DM_SCALE | DM_COLLATE |
     824                DM_COPIES |
     825                DM_DEFAULTSOURCE | DM_PRINTQUALITY |
     826                DM_YRESOLUTION | DM_TTOPTION;
     827
     828        dm.s1.dmOrientation = DMORIENT_PORTRAIT;
     829        dm.s1.dmPaperSize = DMPAPER_A4;
     830        dm.s1.dmPaperLength = 2970;
     831        dm.s1.dmPaperWidth = 2100;
     832
     833        dm.dmScale = 100;
     834        dm.dmCopies = 1;
     835        dm.dmDefaultSource = DMBIN_AUTO;
     836        dm.dmPrintQuality = DMRES_MEDIUM;
     837        /* dm.dmColor */
     838        /* dm.dmDuplex */
     839        dm.dmYResolution = 300; /* 300dpi */
     840        dm.dmTTOption = DMTT_BITMAP;
     841        dm.dmCollate = 1;
     842        /* dm.dmFormName */
     843        /* dm.dmLogPixels */
     844        /* dm.dmBitsPerPel */
     845        /* dm.dmPelsWidth */
     846        /* dm.dmPelsHeight */
     847        /* dm.dmDisplayFlags */
     848        /* dm.dmDisplayFrequency */
     849        /* dm.dmICMMethod */
     850        /* dm.dmICMIntent */
     851        /* dm.dmMediaType */
     852        /* dm.dmDitherType */
     853        /* dm.dmReserved1 */
     854        /* dm.dmReserved2 */
     855        /* dm.dmPanningWidth */
     856        /* dm.dmPanningHeight */
     857
     858    if(unicode) {
     859        if(buflen >= sizeof(DEVMODEW)) {
     860            DEVMODEW *pdmW = DEVMODEdupAtoW(GetProcessHeap(), &dm );
     861            memcpy(ptr, pdmW, sizeof(DEVMODEW));
     862            HeapFree(GetProcessHeap(),0,pdmW);
     863        }
     864        *needed = sizeof(DEVMODEW);
     865    }
     866    else
     867    {
     868        if(buflen >= sizeof(DEVMODEA)) {
     869            memcpy(ptr, &dm, sizeof(DEVMODEA));
     870        }
     871        *needed = sizeof(DEVMODEA);
     872    }
     873}
     874
     875
     876/*********************************************************************
     877 *    WINSPOOL_GetPrinter_2
     878 *
     879 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
     880 * The strings are either stored as unicode or ascii.
     881 */
     882static BOOL WINSPOOL_GetPrinter_2(HKEY hkeyPrinter, PRINTER_INFO_2W *pi2,
     883                                  LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
     884                                  BOOL unicode)
     885{
     886    DWORD size, left = cbBuf;
     887    BOOL space = (cbBuf > 0);
     888    LPBYTE ptr = buf;
     889
     890    *pcbNeeded = 0;
     891
     892    if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
     893                                 unicode)) {
     894        if(space && size <= left) {
     895            pi2->pPrinterName = (LPWSTR)ptr;
     896            ptr += size;
     897            left -= size;
     898        } else
     899            space = FALSE;
     900        *pcbNeeded += size;
     901    }
     902    if(WINSPOOL_GetStringFromReg(hkeyPrinter, Share_NameW, ptr, left, &size,
     903                                 unicode)) {
     904        if(space && size <= left) {
     905            pi2->pShareName = (LPWSTR)ptr;
     906            ptr += size;
     907            left -= size;
     908        } else
     909            space = FALSE;
     910        *pcbNeeded += size;
     911    }
     912    if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
     913                                 unicode)) {
     914        if(space && size <= left) {
     915            pi2->pPortName = (LPWSTR)ptr;
     916            ptr += size;
     917            left -= size;
     918        } else
     919            space = FALSE;
     920        *pcbNeeded += size;
     921    }
     922    if(WINSPOOL_GetStringFromReg(hkeyPrinter, Printer_DriverW, ptr, left,
     923                                 &size, unicode)) {
     924        if(space && size <= left) {
     925            pi2->pDriverName = (LPWSTR)ptr;
     926            ptr += size;
     927            left -= size;
     928        } else
     929            space = FALSE;
     930        *pcbNeeded += size;
     931    }
     932    if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size,
     933                                 unicode)) {
     934        if(space && size <= left) {
     935            pi2->pComment = (LPWSTR)ptr;
     936            ptr += size;
     937            left -= size;
     938        } else
     939            space = FALSE;
     940        *pcbNeeded += size;
     941    }
     942    if(WINSPOOL_GetStringFromReg(hkeyPrinter, LocationW, ptr, left, &size,
     943                                 unicode)) {
     944        if(space && size <= left) {
     945            pi2->pLocation = (LPWSTR)ptr;
     946            ptr += size;
     947            left -= size;
     948        } else
     949            space = FALSE;
     950        *pcbNeeded += size;
     951    }
     952    if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, ptr, left,
     953                                  &size, unicode)) {
     954        if(space && size <= left) {
     955            pi2->pDevMode = (LPDEVMODEW)ptr;
     956            ptr += size;
     957            left -= size;
     958        } else
     959            space = FALSE;
     960        *pcbNeeded += size;
     961    }
     962    else
     963    {
     964        MESSAGE( "no DevMode in registry. please setup your printer again.\n"
     965                 "use the default hard-coded DevMode(wineps/A4/300dpi).\n" );
     966        WINSPOOL_GetDefaultDevMode(ptr, left, &size, unicode);
     967        if(space && size <= left) {
     968            pi2->pDevMode = (LPDEVMODEW)ptr;
     969            ptr += size;
     970            left -= size;
     971        } else
     972            space = FALSE;
     973        *pcbNeeded += size;
     974    }
     975    if(WINSPOOL_GetStringFromReg(hkeyPrinter, Separator_FileW, ptr, left,
     976                                 &size, unicode)) {
     977        if(space && size <= left) {
     978            pi2->pSepFile = (LPWSTR)ptr;
     979            ptr += size;
     980            left -= size;
     981        } else
     982            space = FALSE;
     983        *pcbNeeded += size;
     984    }
     985    if(WINSPOOL_GetStringFromReg(hkeyPrinter, Print_ProcessorW, ptr, left,
     986                                 &size, unicode)) {
     987        if(space && size <= left) {
     988            pi2->pPrintProcessor = (LPWSTR)ptr;
     989            ptr += size;
     990            left -= size;
     991        } else
     992            space = FALSE;
     993        *pcbNeeded += size;
     994    }
     995    if(WINSPOOL_GetStringFromReg(hkeyPrinter, DatatypeW, ptr, left,
     996                                 &size, unicode)) {
     997        if(space && size <= left) {
     998            pi2->pDatatype = (LPWSTR)ptr;
     999            ptr += size;
     1000            left -= size;
     1001        } else
     1002            space = FALSE;
     1003        *pcbNeeded += size;
     1004    }
     1005    if(WINSPOOL_GetStringFromReg(hkeyPrinter, ParametersW, ptr, left,
     1006                                 &size, unicode)) {
     1007        if(space && size <= left) {
     1008            pi2->pParameters = (LPWSTR)ptr;
     1009            ptr += size;
     1010            left -= size;
     1011        } else
     1012            space = FALSE;
     1013        *pcbNeeded += size;
     1014    }
     1015    if(pi2) {
     1016        pi2->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
     1017        pi2->Priority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Priority");
     1018        pi2->DefaultPriority = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
     1019                                                        "Default Priority");
     1020        pi2->StartTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "StartTime");
     1021        pi2->UntilTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "UntilTime");
     1022    }
     1023
     1024    if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
     1025        memset(pi2, 0, sizeof(*pi2));
     1026
     1027    return space;
     1028}
     1029
     1030/*********************************************************************
     1031 *    WINSPOOL_GetPrinter_4
     1032 *
     1033 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
     1034 */
     1035static BOOL WINSPOOL_GetPrinter_4(HKEY hkeyPrinter, PRINTER_INFO_4W *pi4,
     1036                                  LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
     1037                                  BOOL unicode)
     1038{
     1039    DWORD size, left = cbBuf;
     1040    BOOL space = (cbBuf > 0);
     1041    LPBYTE ptr = buf;
     1042
     1043    *pcbNeeded = 0;
     1044
     1045    if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
     1046                                 unicode)) {
     1047        if(space && size <= left) {
     1048            pi4->pPrinterName = (LPWSTR)ptr;
     1049            ptr += size;
     1050            left -= size;
     1051        } else
     1052            space = FALSE;
     1053        *pcbNeeded += size;
     1054    }
     1055    if(pi4) {
     1056        pi4->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
     1057    }
     1058
     1059    if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
     1060        memset(pi4, 0, sizeof(*pi4));
     1061
     1062    return space;
     1063}
     1064
     1065/*********************************************************************
     1066 *    WINSPOOL_GetPrinter_5
     1067 *
     1068 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
     1069 */
     1070static BOOL WINSPOOL_GetPrinter_5(HKEY hkeyPrinter, PRINTER_INFO_5W *pi5,
     1071                                  LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
     1072                                  BOOL unicode)
     1073{
     1074    DWORD size, left = cbBuf;
     1075    BOOL space = (cbBuf > 0);
     1076    LPBYTE ptr = buf;
     1077
     1078    *pcbNeeded = 0;
     1079
     1080    if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
     1081                                 unicode)) {
     1082        if(space && size <= left) {
     1083            pi5->pPrinterName = (LPWSTR)ptr;
     1084            ptr += size;
     1085            left -= size;
     1086        } else
     1087            space = FALSE;
     1088        *pcbNeeded += size;
     1089    }
     1090    if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
     1091                                 unicode)) {
     1092        if(space && size <= left) {
     1093            pi5->pPortName = (LPWSTR)ptr;
     1094            ptr += size;
     1095            left -= size;
     1096        } else
     1097            space = FALSE;
     1098        *pcbNeeded += size;
     1099    }
     1100    if(pi5) {
     1101        pi5->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
     1102        pi5->DeviceNotSelectedTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
     1103                                                                "dnsTimeout");
     1104        pi5->TransmissionRetryTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
     1105                                                                 "txTimeout");
     1106    }
     1107
     1108    if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
     1109        memset(pi5, 0, sizeof(*pi5));
     1110
     1111    return space;
     1112}
     1113
     1114
     1115/*****************************************************************************
     1116 *          WINSPOOL_GetPrinter
     1117 *
     1118 *    Implementation of GetPrinterA|W.  Relies on PRINTER_INFO_*W being
     1119 *    essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
     1120 *    just a collection of pointers to strings.
     1121 */
     1122static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
     1123                                DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode)
     1124{
     1125    LPCWSTR name;
     1126    DWORD size, needed = 0;
     1127    LPBYTE ptr = NULL;
     1128    HKEY hkeyPrinter, hkeyPrinters;
     1129    BOOL ret;
     1130
     1131    TRACE("(%p,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
     1132
     1133    if (!(name = WINSPOOL_GetOpenedPrinter(hPrinter))) return FALSE;
     1134
     1135    if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
     1136       ERROR_SUCCESS) {
     1137        ERR("Can't create Printers key\n");
     1138        return FALSE;
     1139    }
     1140    if(RegOpenKeyW(hkeyPrinters, name, &hkeyPrinter) != ERROR_SUCCESS)
     1141    {
     1142        ERR("Can't find opened printer %s in registry\n", debugstr_w(name));
     1143        RegCloseKey(hkeyPrinters);
     1144        SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
     1145        return FALSE;
     1146    }
     1147
     1148    switch(Level) {
     1149    case 2:
     1150      {
     1151        PRINTER_INFO_2W *pi2 = (PRINTER_INFO_2W *)pPrinter;
     1152
     1153        size = sizeof(PRINTER_INFO_2W);
     1154        if(size <= cbBuf) {
     1155            ptr = pPrinter + size;
     1156            cbBuf -= size;
     1157            memset(pPrinter, 0, size);
     1158        } else {
     1159            pi2 = NULL;
     1160            cbBuf = 0;
     1161        }
     1162        ret = WINSPOOL_GetPrinter_2(hkeyPrinter, pi2, ptr, cbBuf, &needed,
     1163                                    unicode);
     1164        needed += size;
     1165        break;
     1166      }
     1167
     1168    case 4:
     1169      {
     1170        PRINTER_INFO_4W *pi4 = (PRINTER_INFO_4W *)pPrinter;
     1171
     1172        size = sizeof(PRINTER_INFO_4W);
     1173        if(size <= cbBuf) {
     1174            ptr = pPrinter + size;
     1175            cbBuf -= size;
     1176            memset(pPrinter, 0, size);
     1177        } else {
     1178            pi4 = NULL;
     1179            cbBuf = 0;
     1180        }
     1181        ret = WINSPOOL_GetPrinter_4(hkeyPrinter, pi4, ptr, cbBuf, &needed,
     1182                                    unicode);
     1183        needed += size;
     1184        break;
     1185      }
     1186
     1187
     1188    case 5:
     1189      {
     1190        PRINTER_INFO_5W *pi5 = (PRINTER_INFO_5W *)pPrinter;
     1191
     1192        size = sizeof(PRINTER_INFO_5W);
     1193        if(size <= cbBuf) {
     1194            ptr = pPrinter + size;
     1195            cbBuf -= size;
     1196            memset(pPrinter, 0, size);
     1197        } else {
     1198            pi5 = NULL;
     1199            cbBuf = 0;
     1200        }
     1201
     1202        ret = WINSPOOL_GetPrinter_5(hkeyPrinter, pi5, ptr, cbBuf, &needed,
     1203                                    unicode);
     1204        needed += size;
     1205        break;
     1206      }
     1207
     1208    default:
     1209        FIXME("Unimplemented level %ld\n", Level);
     1210        SetLastError(ERROR_INVALID_LEVEL);
     1211        RegCloseKey(hkeyPrinters);
     1212        RegCloseKey(hkeyPrinter);
     1213        return FALSE;
     1214    }
     1215
     1216    RegCloseKey(hkeyPrinter);
     1217    RegCloseKey(hkeyPrinters);
     1218
     1219    TRACE("returing %d needed = %ld\n", ret, needed);
     1220    if(pcbNeeded) *pcbNeeded = needed;
     1221    if(!ret)
     1222        SetLastError(ERROR_INSUFFICIENT_BUFFER);
     1223    return ret;
     1224}
     1225
     1226
     1227/*****************************************************************************
     1228 *          WINSPOOL_GetDriverInfoFromReg [internal]
     1229 *
     1230 *    Enters the information from the registry into the DRIVER_INFO struct
     1231 *
     1232 * RETURNS
     1233 *    zero if the printer driver does not exist in the registry
     1234 *    (only if Level > 1) otherwise nonzero
     1235 */
     1236static BOOL WINSPOOL_GetDriverInfoFromReg(
     1237                            HKEY    hkeyDrivers,
     1238                            LPWSTR  DriverName,
     1239                            LPWSTR  pEnvironment,
     1240                            DWORD   Level,
     1241                            LPBYTE  ptr,            /* DRIVER_INFO */
     1242                            LPBYTE  pDriverStrings, /* strings buffer */
     1243                            DWORD   cbBuf,          /* size of string buffer */
     1244                            LPDWORD pcbNeeded,      /* space needed for str. */
     1245                            BOOL    unicode)        /* type of strings */
     1246{   DWORD  dw, size, tmp, type;
     1247    HKEY   hkeyDriver;
     1248    LPBYTE strPtr = pDriverStrings;
     1249
     1250    TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
     1251          debugstr_w(DriverName), debugstr_w(pEnvironment),
     1252          Level, ptr, pDriverStrings, cbBuf, unicode);
     1253
     1254    if(unicode) {
     1255        *pcbNeeded = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
     1256            if (*pcbNeeded <= cbBuf)
     1257               strcpyW((LPWSTR)strPtr, DriverName);
     1258    } else {
     1259        *pcbNeeded = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0,
     1260                                          NULL, NULL);
     1261        if(*pcbNeeded <= cbBuf)
     1262            WideCharToMultiByte(CP_ACP, 0, DriverName, -1, (LPSTR)strPtr, *pcbNeeded,
     1263                                NULL, NULL);
     1264    }
     1265    if(Level == 1) {
     1266       if(ptr)
     1267          ((PDRIVER_INFO_1W) ptr)->pName = (LPWSTR) strPtr;
     1268       return TRUE;
     1269    } else {
     1270       if(ptr)
     1271          ((PDRIVER_INFO_3W) ptr)->pName = (LPWSTR) strPtr;
     1272       strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
     1273    }
     1274
     1275    if(!DriverName[0] || RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver) != ERROR_SUCCESS) {
     1276        ERR("Can't find driver '%s' in registry\n", debugstr_w(DriverName));
     1277        SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
     1278        return FALSE;
     1279    }
     1280
     1281    size = sizeof(dw);
     1282    if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw, &size) !=
     1283        ERROR_SUCCESS)
     1284         WARN("Can't get Version\n");
     1285    else if(ptr)
     1286         ((PDRIVER_INFO_3A) ptr)->cVersion = dw;
     1287
     1288    if(!pEnvironment)
     1289        pEnvironment = DefaultEnvironmentW;
     1290    if(unicode)
     1291        size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
     1292    else
     1293        size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
     1294                                   NULL, NULL);
     1295    *pcbNeeded += size;
     1296    if(*pcbNeeded <= cbBuf) {
     1297        if(unicode)
     1298            strcpyW((LPWSTR)strPtr, pEnvironment);
     1299        else
     1300            WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, (LPSTR)strPtr, size,
     1301                                NULL, NULL);
     1302        if(ptr)
     1303            ((PDRIVER_INFO_3W) ptr)->pEnvironment = (LPWSTR)strPtr;
     1304        strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
     1305    }
     1306
     1307    if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, 0, &size,
     1308                                 unicode)) {
     1309        *pcbNeeded += size;
     1310        if(*pcbNeeded <= cbBuf)
     1311            WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, size, &tmp,
     1312                                      unicode);
     1313        if(ptr)
     1314            ((PDRIVER_INFO_3W) ptr)->pDriverPath = (LPWSTR)strPtr;
     1315        strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
     1316    }
     1317
     1318    if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, 0, &size,
     1319                                 unicode)) {
     1320        *pcbNeeded += size;
     1321        if(*pcbNeeded <= cbBuf)
     1322            WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, size,
     1323                                      &tmp, unicode);
     1324        if(ptr)
     1325            ((PDRIVER_INFO_3W) ptr)->pDataFile = (LPWSTR)strPtr;
     1326        strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
     1327    }
     1328
     1329    if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
     1330                                 0, &size, unicode)) {
     1331        *pcbNeeded += size;
     1332        if(*pcbNeeded <= cbBuf)
     1333            WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
     1334                                      size, &tmp, unicode);
     1335        if(ptr)
     1336            ((PDRIVER_INFO_3W) ptr)->pConfigFile = (LPWSTR)strPtr;
     1337        strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
     1338    }
     1339
     1340    if(Level == 2 ) {
     1341        RegCloseKey(hkeyDriver);
     1342        TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
     1343        return TRUE;
     1344    }
     1345
     1346    if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr, 0, &size,
     1347                                 unicode)) {
     1348        *pcbNeeded += size;
     1349        if(*pcbNeeded <= cbBuf)
     1350            WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr,
     1351                                      size, &tmp, unicode);
     1352        if(ptr)
     1353            ((PDRIVER_INFO_3W) ptr)->pHelpFile = (LPWSTR)strPtr;
     1354        strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
     1355    }
     1356
     1357    if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr, 0,
     1358                             &size, unicode)) {
     1359        *pcbNeeded += size;
     1360        if(*pcbNeeded <= cbBuf)
     1361            WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr,
     1362                                      size, &tmp, unicode);
     1363        if(ptr)
     1364            ((PDRIVER_INFO_3W) ptr)->pDependentFiles = (LPWSTR)strPtr;
     1365        strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
     1366    }
     1367
     1368    if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size,
     1369                                 unicode)) {
     1370        *pcbNeeded += size;
     1371        if(*pcbNeeded <= cbBuf)
     1372            WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
     1373                                      size, &tmp, unicode);
     1374        if(ptr)
     1375            ((PDRIVER_INFO_3W) ptr)->pMonitorName = (LPWSTR)strPtr;
     1376        strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
     1377    }
     1378
     1379    if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size,
     1380                                 unicode)) {
     1381        *pcbNeeded += size;
     1382        if(*pcbNeeded <= cbBuf)
     1383            WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
     1384                                      size, &tmp, unicode);
     1385        if(ptr)
     1386            ((PDRIVER_INFO_3W) ptr)->pDefaultDataType = (LPWSTR)strPtr;
     1387        strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
     1388    }
     1389
     1390    TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
     1391    RegCloseKey(hkeyDriver);
     1392    return TRUE;
     1393}
     1394
     1395/*****************************************************************************
     1396 *          WINSPOOL_GetPrinterDriver
     1397 */
     1398static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
     1399                                      DWORD Level, LPBYTE pDriverInfo,
     1400                                      DWORD cbBuf, LPDWORD pcbNeeded,
     1401                                      BOOL unicode)
     1402{
     1403    LPCWSTR name;
     1404    WCHAR DriverName[100];
     1405    DWORD ret, type, size, needed = 0;
     1406    LPBYTE ptr = NULL;
     1407    HKEY hkeyPrinter, hkeyPrinters, hkeyDrivers;
     1408
     1409    TRACE("(%p,%s,%ld,%p,%ld,%p)\n",hPrinter,debugstr_w(pEnvironment),
     1410          Level,pDriverInfo,cbBuf, pcbNeeded);
     1411
     1412    ZeroMemory(pDriverInfo, cbBuf);
     1413
     1414    if (!(name = WINSPOOL_GetOpenedPrinter(hPrinter))) return FALSE;
     1415
     1416    if(Level < 1 || Level > 3) {
     1417        SetLastError(ERROR_INVALID_LEVEL);
     1418        return FALSE;
     1419    }
     1420    if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
     1421       ERROR_SUCCESS) {
     1422        ERR("Can't create Printers key\n");
     1423        return FALSE;
     1424    }
     1425    if(RegOpenKeyW(hkeyPrinters, name, &hkeyPrinter)
     1426       != ERROR_SUCCESS) {
     1427        ERR("Can't find opened printer %s in registry\n", debugstr_w(name));
     1428        RegCloseKey(hkeyPrinters);
     1429        SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
     1430        return FALSE;
     1431    }
     1432    size = sizeof(DriverName);
     1433    DriverName[0] = 0;
     1434    ret = RegQueryValueExW(hkeyPrinter, Printer_DriverW, 0, &type,
     1435                           (LPBYTE)DriverName, &size);
     1436    RegCloseKey(hkeyPrinter);
     1437    RegCloseKey(hkeyPrinters);
     1438    if(ret != ERROR_SUCCESS) {
     1439        ERR("Can't get DriverName for printer %s\n", debugstr_w(name));
     1440        return FALSE;
     1441    }
     1442
     1443    hkeyDrivers = WINSPOOL_OpenDriverReg( pEnvironment, TRUE);
     1444    if(!hkeyDrivers) {
     1445        ERR("Can't create Drivers key\n");
     1446        return FALSE;
     1447    }
     1448
     1449    switch(Level) {
     1450    case 1:
     1451        size = sizeof(DRIVER_INFO_1W);
     1452        break;
     1453    case 2:
     1454        size = sizeof(DRIVER_INFO_2W);
     1455        break;
     1456    case 3:
     1457        size = sizeof(DRIVER_INFO_3W);
     1458        break;
     1459    default:
     1460        ERR("Invalid level\n");
     1461        return FALSE;
     1462    }
     1463
     1464    if(size <= cbBuf)
     1465        ptr = pDriverInfo + size;
     1466
     1467    if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverName,
     1468                         pEnvironment, Level, pDriverInfo,
     1469                         (cbBuf < size) ? NULL : ptr,
     1470                         (cbBuf < size) ? 0 : cbBuf - size,
     1471                         &needed, unicode)) {
     1472            RegCloseKey(hkeyDrivers);
     1473            return FALSE;
     1474    }
     1475
     1476    RegCloseKey(hkeyDrivers);
     1477
     1478    if(pcbNeeded) *pcbNeeded = size + needed;
     1479    TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
     1480    if(cbBuf >= needed) return TRUE;
     1481    SetLastError(ERROR_INSUFFICIENT_BUFFER);
     1482    return FALSE;
     1483}
     1484
     1485/*****************************************************************************
     1486 *          WINSPOOL_EnumPrinters
     1487 *
     1488 *    Implementation of EnumPrintersA|W
     1489 */
     1490static BOOL WINSPOOL_EnumPrinters(DWORD dwType, LPWSTR lpszName,
     1491                                  DWORD dwLevel, LPBYTE lpbPrinters,
     1492                                  DWORD cbBuf, LPDWORD lpdwNeeded,
     1493                                  LPDWORD lpdwReturned, BOOL unicode)
     1494
     1495{
     1496    HKEY hkeyPrinters, hkeyPrinter;
     1497    WCHAR PrinterName[255];
     1498    DWORD needed = 0, number = 0;
     1499    DWORD used, i, left;
     1500    PBYTE pi, buf;
     1501
     1502    if(lpbPrinters)
     1503        memset(lpbPrinters, 0, cbBuf);
     1504    if(lpdwReturned)
     1505        *lpdwReturned = 0;
     1506    if(lpdwNeeded)
     1507        *lpdwNeeded = 0;
     1508
     1509    /* PRINTER_ENUM_DEFAULT is only supported under win9x, we behave like NT */
     1510    if(dwType == PRINTER_ENUM_DEFAULT)
     1511        return TRUE;
     1512
     1513    if (dwType & PRINTER_ENUM_CONNECTIONS) {
     1514        FIXME("We dont handle PRINTER_ENUM_CONNECTIONS\n");
     1515        dwType &= ~PRINTER_ENUM_CONNECTIONS; /* we dont handle that */
     1516        if(!dwType) return TRUE;
     1517    }
     1518
     1519    if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
     1520        FIXME("dwType = %08lx\n", dwType);
     1521        SetLastError(ERROR_INVALID_FLAGS);
     1522        return FALSE;
     1523    }
     1524
     1525    if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
     1526       ERROR_SUCCESS) {
     1527        ERR("Can't create Printers key\n");
     1528        return FALSE;
     1529    }
     1530
     1531    if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
     1532                        NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
     1533        RegCloseKey(hkeyPrinters);
     1534        ERR("Can't query Printers key\n");
     1535        return FALSE;
     1536    }
     1537    TRACE("Found %ld printers\n", number);
     1538
     1539    switch(dwLevel) {
     1540    case 1:
     1541        RegCloseKey(hkeyPrinters);
     1542        if (lpdwReturned)
     1543            *lpdwReturned = number;
     1544        return TRUE;
     1545
     1546    case 2:
     1547        used = number * sizeof(PRINTER_INFO_2W);
     1548        break;
     1549    case 4:
     1550        used = number * sizeof(PRINTER_INFO_4W);
     1551        break;
     1552    case 5:
     1553        used = number * sizeof(PRINTER_INFO_5W);
     1554        break;
     1555
     1556    default:
     1557        SetLastError(ERROR_INVALID_LEVEL);
     1558        RegCloseKey(hkeyPrinters);
     1559        return FALSE;
     1560    }
     1561    pi = (used <= cbBuf) ? lpbPrinters : NULL;
     1562
     1563    for(i = 0; i < number; i++) {
     1564        if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
     1565           ERROR_SUCCESS) {
     1566            ERR("Can't enum key number %ld\n", i);
     1567            RegCloseKey(hkeyPrinters);
     1568            return FALSE;
     1569        }
     1570        TRACE("Printer %ld is %s\n", i, debugstr_w(PrinterName));
     1571        if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkeyPrinter) !=
     1572           ERROR_SUCCESS) {
     1573            ERR("Can't open key %s\n", debugstr_w(PrinterName));
     1574            RegCloseKey(hkeyPrinters);
     1575            return FALSE;
     1576        }
     1577
     1578        if(cbBuf > used) {
     1579            buf = lpbPrinters + used;
     1580            left = cbBuf - used;
     1581        } else {
     1582            buf = NULL;
     1583            left = 0;
     1584        }
     1585
     1586        switch(dwLevel) {
     1587        case 2:
     1588            WINSPOOL_GetPrinter_2(hkeyPrinter, (PRINTER_INFO_2W *)pi, buf,
     1589                                  left, &needed, unicode);
     1590            used += needed;
     1591            if(pi) pi += sizeof(PRINTER_INFO_2W);
     1592            break;
     1593        case 4:
     1594            WINSPOOL_GetPrinter_4(hkeyPrinter, (PRINTER_INFO_4W *)pi, buf,
     1595                                  left, &needed, unicode);
     1596            used += needed;
     1597            if(pi) pi += sizeof(PRINTER_INFO_4W);
     1598            break;
     1599        case 5:
     1600            WINSPOOL_GetPrinter_5(hkeyPrinter, (PRINTER_INFO_5W *)pi, buf,
     1601                                  left, &needed, unicode);
     1602            used += needed;
     1603            if(pi) pi += sizeof(PRINTER_INFO_5W);
     1604            break;
     1605        default:
     1606            ERR("Shouldn't be here!\n");
     1607            RegCloseKey(hkeyPrinter);
     1608            RegCloseKey(hkeyPrinters);
     1609            return FALSE;
     1610        }
     1611        RegCloseKey(hkeyPrinter);
     1612    }
     1613    RegCloseKey(hkeyPrinters);
     1614
     1615    if(lpdwNeeded)
     1616        *lpdwNeeded = used;
     1617
     1618    if(used > cbBuf) {
     1619        if(lpbPrinters)
     1620            memset(lpbPrinters, 0, cbBuf);
     1621        SetLastError(ERROR_INSUFFICIENT_BUFFER);
     1622        return FALSE;
     1623    }
     1624    if(lpdwReturned)
     1625        *lpdwReturned = number;
     1626    SetLastError(ERROR_SUCCESS);
     1627    return TRUE;
     1628}
     1629
     1630
     1631/******************************************************************
     1632 *              EnumPrintersA        [WINSPOOL.@]
     1633 *
     1634 */
     1635BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName,
     1636                          DWORD dwLevel, LPBYTE lpbPrinters,
     1637                          DWORD cbBuf, LPDWORD lpdwNeeded,
     1638                          LPDWORD lpdwReturned)
     1639{
     1640    BOOL ret;
     1641    LPWSTR pwstrNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpszName);
     1642
     1643    ret = WINSPOOL_EnumPrinters(dwType, pwstrNameW, dwLevel, lpbPrinters, cbBuf,
     1644                                lpdwNeeded, lpdwReturned, FALSE);
     1645    HeapFree(GetProcessHeap(),0,pwstrNameW);
     1646    return ret;
     1647}
     1648
     1649
     1650/*****************************************************************************
     1651 * Name      : BOOL ClosePrinter
     1652 * Purpose   :
     1653 * Parameters:
     1654 * Variables :
     1655 * Result    :
     1656 * Remark    :
     1657 * Status    : UNTESTED STUB
     1658 *
     1659 * Author    : Markus Montkowski [09.07.98 13:39:08]
     1660 *****************************************************************************/
     1661
     1662BOOL WIN32API ClosePrinter(HANDLE hPrinter)
     1663{
     1664#ifdef __WIN32OS2__
     1665    /*
     1666     * Validate handle and get instance data.
     1667     */
     1668    POPENPRINTER    p = openprinterFind(hPrinter);
     1669    if (!p)
     1670    {
     1671        dprintf(("WINSPOOL: ClosePrinter Invalid handle %d\n", hPrinter));
     1672        SetLastError(ERROR_INVALID_HANDLE);
     1673        return FALSE;
     1674    }
     1675    dprintf(("WINSPOOL: ClosePrinter(%d) name=%ls\n", hPrinter, p->pwszPrinterName));
     1676
     1677    /*
     1678     * Close any open OS/2 spool file.
     1679     */
     1680    if (p->hspl)
     1681    {
     1682        dprintf(("WINSPOOL: ClosePrinter closing OS/2 spool file %#x\n", p->hspl));
     1683        if (!OSLibSplQmClose(p->hspl))
     1684           DebugAssertFailed(("OSLibSplQmClose(%#x) failed!!!\n", p->hspl));
     1685        p->hspl = 0;
     1686    }
     1687    openprinterDelete(p);
     1688    return TRUE;
     1689#else
     1690    int i = (int)hPrinter;
     1691
     1692    TRACE("Handle %p\n", hPrinter);
     1693
     1694    if ((i <= 0) || (i > nb_printers)) return FALSE;
     1695    HeapFree( GetProcessHeap(), 0, printer_array[i - 1] );
     1696    printer_array[i - 1] = NULL;
     1697    return TRUE;
     1698#endif
     1699}
     1700
     1701
     1702/**
     1703 * Opens a printer.
     1704 *
     1705 * @returns Success indicator, last error set on failure.
     1706 * @param   lpPrinterName   Pointer to printer name.
     1707 * @param   phPrinter       Where to store the handle to the opned printer instance.
     1708 * @param   pDefault        Printer defaults. (Current ignored)
     1709 * @status  partially implemented.
     1710 * @author  Wine???
     1711 */
     1712BOOL WIN32API OpenPrinterA(LPSTR lpPrinterName, HANDLE * phPrinter,
     1713                           PRINTER_DEFAULTSA * pDefault)
     1714{
     1715    LPWSTR lpPrinterNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName);
     1716    PRINTER_DEFAULTSW DefaultW, *pDefaultW = NULL;
     1717    BOOL ret;
     1718
     1719    if(pDefault) {
     1720        DefaultW.pDatatype = HEAP_strdupAtoW(GetProcessHeap(), 0,
     1721                                             pDefault->pDatatype);
     1722        DefaultW.pDevMode = DEVMODEdupAtoW(GetProcessHeap(),
     1723                                           pDefault->pDevMode);
     1724        DefaultW.DesiredAccess = pDefault->DesiredAccess;
     1725        pDefaultW = &DefaultW;
     1726    }
     1727    ret = OpenPrinterW(lpPrinterNameW, phPrinter, pDefaultW);
     1728    if(pDefault) {
     1729        HeapFree(GetProcessHeap(), 0, DefaultW.pDatatype);
     1730        HeapFree(GetProcessHeap(), 0, DefaultW.pDevMode);
     1731    }
     1732    HeapFree(GetProcessHeap(), 0, lpPrinterNameW);
     1733    return ret;
     1734}
     1735
     1736
     1737/*****************************************************************************
     1738 * Name      : LONG DocumentPropertiesA
     1739 * Purpose   :
     1740 * Parameters:
     1741 * Variables :
     1742 * Result    :
     1743 * Remark    :
     1744 * Status    : UNTESTED STUB
     1745 *
     1746 * Author    : Markus Montkowski [09.07.98 13:39:08]
     1747 *****************************************************************************/
     1748
     1749LONG WIN32API DocumentPropertiesA(HWND hWnd, HANDLE hPrinter,
     1750                                  LPSTR pDeviceName,
     1751                                  LPDEVMODEA pDevModeOutput,
     1752                                  LPDEVMODEA pDevModeInput,
     1753                                  DWORD fMode)
     1754{
     1755    LPSTR lpName = pDeviceName;
     1756    LONG  ret;
     1757
     1758    dprintf(("DocumentPropertiesA(%p,%p,%s,%p,%p,%ld)\n",
     1759        hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
     1760    ));
     1761
     1762    if (hWnd)
     1763    {
     1764        char szPMQueue[256];
     1765        if(SplQueryPMQueueName(pDeviceName, szPMQueue, sizeof(szPMQueue)) == TRUE) {
     1766            ret = OSLibShowPrinterDialog(hWnd, szPMQueue);
     1767        }
     1768    }
     1769
     1770    if(!pDeviceName) {
     1771        LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter);
     1772        if(!lpNameW) {
     1773                ERR("no name from hPrinter?\n");
     1774                return -1;
     1775        }
     1776        lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW);
     1777    }
     1778
     1779#if 0
     1780    ret = GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, "LPT1:",
     1781                                  pDevModeInput, NULL, fMode);
     1782#endif
     1783
     1784    switch (fMode & ~DM_PROMPT) {
     1785    case 0:
     1786            /* TODO - Printer driver specific data */
     1787            ret = (sizeof(DEVMODEA));
     1788            break;
     1789
     1790    case DM_IN_BUFFER:
     1791    case DM_IN_BUFFER | DM_OUT_BUFFER:
     1792    {
     1793             HKEY hkey,hkeyPrinters,hkeyPrinter;
     1794
     1795             if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
     1796                              ERROR_SUCCESS)
     1797             {
     1798                ERR("Can't open Printers key\n");
     1799                SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
     1800                ret = -1;
     1801                break;
     1802             }
     1803
     1804             if(RegOpenKeyA(hkeyPrinters, lpName, &hkeyPrinter) != ERROR_SUCCESS)
     1805             {
     1806                ERR("Can't find opened printer %s in registry\n", lpName);
     1807                RegCloseKey(hkeyPrinters);
     1808                SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
     1809                ret = -1;
     1810                break;
     1811             }
     1812
     1813             WINSPOOL_SetDevModeFromReg(hkeyPrinter, Default_DevModeW, (LPBYTE)pDevModeInput,
     1814                                        sizeof(DEVMODEA));
     1815             if (pDevModeOutput) {
     1816                memcpy(pDevModeOutput, pDevModeInput, sizeof(DEVMODEA));
     1817             }
     1818             RegCloseKey(hkeyPrinter);
     1819             RegCloseKey(hkeyPrinters);
     1820             ret = IDOK;
     1821             break;
     1822    }
     1823
     1824    case DM_OUT_BUFFER:
     1825            if(pDevModeOutput)
     1826            {
     1827                PRINTER_INFO_2A *pInfo;
     1828                DWORD needed;
     1829
     1830                GetPrinterA(hPrinter, 2, NULL, 0, &needed);
     1831                pInfo = (PRINTER_INFO_2A*)HeapAlloc(GetProcessHeap(),0,needed);
     1832                if(GetPrinterA(hPrinter, 2, (LPBYTE)pInfo, needed, &needed) == FALSE) {
     1833                    dprintf(("GetPrinterA failed"));
     1834                    ret = -1;
     1835                    break;
     1836                }
     1837                if (pInfo->pDevMode) {
     1838                  memcpy(pDevModeOutput, pInfo->pDevMode, sizeof(DEVMODEA));
     1839                }
     1840                HeapFree(GetProcessHeap(),0,pInfo);
     1841            }
     1842            ret = IDOK;
     1843            break;
     1844
     1845    default:
     1846        dprintf(("Unsupported fMode = %d",fMode));
     1847        ret = -1;
     1848        break;
     1849    }
     1850
     1851    if(!pDeviceName)
     1852        HeapFree(GetProcessHeap(),0,lpName);
     1853    return ret;
     1854}
     1855
     1856
     1857
     1858/***********************************************************
     1859 *             PRINTER_INFO_2AtoW
     1860 * Creates a unicode copy of PRINTER_INFO_2A on heap
     1861 */
     1862static LPPRINTER_INFO_2W PRINTER_INFO_2AtoW(HANDLE heap, LPPRINTER_INFO_2A piA)
     1863{
     1864    LPPRINTER_INFO_2W piW;
     1865    if(!piA) return NULL;
     1866    piW = (LPPRINTER_INFO_2W) HeapAlloc(heap, 0, sizeof(*piW));
     1867    memcpy(piW, piA, sizeof(*piW)); /* copy everything first */
     1868    piW->pServerName = HEAP_strdupAtoW(heap, 0, piA->pServerName);
     1869    piW->pPrinterName = HEAP_strdupAtoW(heap, 0, piA->pPrinterName);
     1870    piW->pShareName = HEAP_strdupAtoW(heap, 0, piA->pShareName);
     1871    piW->pPortName = HEAP_strdupAtoW(heap, 0, piA->pPortName);
     1872    piW->pDriverName = HEAP_strdupAtoW(heap, 0, piA->pDriverName);
     1873    piW->pComment = HEAP_strdupAtoW(heap, 0, piA->pComment);
     1874    piW->pLocation = HEAP_strdupAtoW(heap, 0, piA->pLocation);
     1875    piW->pDevMode = DEVMODEdupAtoW(heap, piA->pDevMode);
     1876    piW->pSepFile = HEAP_strdupAtoW(heap, 0, piA->pSepFile);
     1877    piW->pPrintProcessor = HEAP_strdupAtoW(heap, 0, piA->pPrintProcessor);
     1878    piW->pDatatype = HEAP_strdupAtoW(heap, 0, piA->pDatatype);
     1879    piW->pParameters = HEAP_strdupAtoW(heap, 0, piA->pParameters);
     1880    return piW;
     1881}
     1882
     1883/***********************************************************
     1884 *       FREE_PRINTER_INFO_2W
     1885 * Free PRINTER_INFO_2W and all strings
     1886 */
     1887static void FREE_PRINTER_INFO_2W(HANDLE heap, LPPRINTER_INFO_2W piW)
     1888{
     1889    if(!piW) return;
     1890
     1891    HeapFree(heap,0,piW->pServerName);
     1892    HeapFree(heap,0,piW->pPrinterName);
     1893    HeapFree(heap,0,piW->pShareName);
     1894    HeapFree(heap,0,piW->pPortName);
     1895    HeapFree(heap,0,piW->pDriverName);
     1896    HeapFree(heap,0,piW->pComment);
     1897    HeapFree(heap,0,piW->pLocation);
     1898    HeapFree(heap,0,piW->pDevMode);
     1899    HeapFree(heap,0,piW->pSepFile);
     1900    HeapFree(heap,0,piW->pPrintProcessor);
     1901    HeapFree(heap,0,piW->pDatatype);
     1902    HeapFree(heap,0,piW->pParameters);
     1903    HeapFree(heap,0,piW);
     1904    return;
     1905}
     1906
     1907
     1908/*****************************************************************************
     1909 * Name      : HANDLE AddPrinterA
     1910 * Purpose   :
     1911 * Parameters: LPSTR pName  pointer to server name
     1912 *             DWORD Level  printer info. structure level
     1913 *             LPBYTE pPrinter  pointer to structure
     1914 * Variables :
     1915 * Result    :
     1916 * Remark    :
     1917 * Status    : UNTESTED STUB
     1918 *
     1919 * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
     1920 *
     1921 * Author    : Markus Montkowski [09.07.98 14:18:56]
     1922 *****************************************************************************/
     1923
     1924HANDLE WIN32API AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
     1925{
     1926    WCHAR *pNameW = NULL;
     1927    PRINTER_INFO_2W *piW;
     1928    PRINTER_INFO_2A *piA = (PRINTER_INFO_2A*)pPrinter;
     1929    HANDLE ret;
     1930
     1931    TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName), Level, pPrinter);
     1932    if(Level != 2) {
     1933        ERR("Level = %ld, unsupported!\n", Level);
     1934        SetLastError(ERROR_INVALID_LEVEL);
     1935        return 0;
     1936    }
     1937    if (pName)
     1938      pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
     1939    piW = PRINTER_INFO_2AtoW(GetProcessHeap(), piA);
     1940
     1941    ret = AddPrinterW(pNameW, Level, (LPBYTE)piW);
     1942
     1943    FREE_PRINTER_INFO_2W(GetProcessHeap(), piW);
     1944    HeapFree(GetProcessHeap(),0,pNameW);
     1945    return ret;
     1946}
     1947
     1948
     1949/*****************************************************************************
     1950 * Name      : HANDLE AddPrinterW
     1951 * Purpose   :
     1952 * Parameters: LPWSTR pName  pointer to server name
     1953 *             DWORD Level  printer info. structure level
     1954 *             LPBYTE pPrinter  pointer to structure
     1955 * Variables :
     1956 * Result    :
     1957 * Remark    :
     1958 * Status    : UNTESTED STUB
     1959 *
     1960 * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
     1961 *
     1962 * Author    : Markus Montkowski [09.07.98 14:18:56]
     1963 *****************************************************************************/
     1964
     1965HANDLE WIN32API AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
     1966{
     1967    PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
     1968    LPDEVMODEA dmA;
     1969    LPDEVMODEW dmW;
     1970    HANDLE retval;
     1971    HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
     1972    LONG size;
     1973
     1974    TRACE("(%s,%ld,%p)\n", debugstr_w(pName), Level, pPrinter);
     1975
     1976    if(pName != NULL) {
     1977        ERR("pName = %s - unsupported\n", debugstr_w(pName));
     1978        SetLastError(ERROR_INVALID_PARAMETER);
     1979        return 0;
     1980    }
     1981    if(Level != 2) {
     1982        ERR("Level = %ld, unsupported!\n", Level);
     1983        SetLastError(ERROR_INVALID_LEVEL);
     1984        return 0;
     1985    }
     1986#if 0
     1987    // SvL: OS/2 printer names can be up to 48 characters, whereas this limit
     1988    //      is 32 chars. We don't actually copy the full printer name into the
     1989    //      dmDeviceName string, so it's fairly safe to remove this check.
     1990    //      (Acrobat Reader Defect 937)
     1991    if (strlenW(pi->pPrinterName) >= CCHDEVICENAME) {
     1992        ERR("Printername %s must not exceed length of DEVMODE.dmDeviceName !\n",
     1993                debugstr_w(pi->pPrinterName)
     1994        );
     1995        SetLastError(ERROR_INVALID_LEVEL);
     1996        return 0;
     1997    }
     1998#endif
     1999    if(!pPrinter) {
     2000        SetLastError(ERROR_INVALID_PARAMETER);
     2001        return 0;
     2002    }
     2003    if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
     2004       ERROR_SUCCESS) {
     2005        ERR("Can't create Printers key\n");
     2006        return 0;
     2007    }
     2008    if(!RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter)) {
     2009        if (!RegQueryValueA(hkeyPrinter,"Attributes",NULL,NULL)) {
     2010            SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
     2011            RegCloseKey(hkeyPrinter);
     2012            RegCloseKey(hkeyPrinters);
     2013            return 0;
     2014        }
     2015        RegCloseKey(hkeyPrinter);
     2016    }
     2017    hkeyDrivers = WINSPOOL_OpenDriverReg( NULL, TRUE);
     2018    if(!hkeyDrivers) {
     2019        ERR("Can't create Drivers key\n");
     2020        RegCloseKey(hkeyPrinters);
     2021        return 0;
     2022    }
     2023    if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
     2024       ERROR_SUCCESS) {
     2025        WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
     2026        RegCloseKey(hkeyPrinters);
     2027        RegCloseKey(hkeyDrivers);
     2028        SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
     2029        return 0;
     2030    }
     2031    RegCloseKey(hkeyDriver);
     2032    RegCloseKey(hkeyDrivers);
     2033
     2034    if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) {  /* FIXME */
     2035        FIXME("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
     2036        SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
     2037        RegCloseKey(hkeyPrinters);
     2038        return 0;
     2039    }
     2040
     2041    if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
     2042       ERROR_SUCCESS) {
     2043        FIXME("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
     2044        SetLastError(ERROR_INVALID_PRINTER_NAME);
     2045        RegCloseKey(hkeyPrinters);
     2046        return 0;
     2047    }
     2048    RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
     2049                   (LPBYTE)&pi->Attributes, sizeof(DWORD));
     2050    set_reg_szW(hkeyPrinter, DatatypeW, pi->pDatatype);
     2051
     2052    /* See if we can load the driver.  We may need the devmode structure anyway
     2053     *
     2054     * FIXME:
     2055     * Note that DocumentPropertiesW will briefly try to open the printer we
     2056     * just create to find a DEVMODEA struct (it will use the WINEPS default
     2057     * one in case it is not there, so we are ok).
     2058     */
     2059    size = DocumentPropertiesW(0, 0, pi->pPrinterName, NULL, NULL, 0);
     2060    if(size < 0) {
     2061        FIXME("DocumentPropertiesW on printer '%s' fails\n", debugstr_w(pi->pPrinterName));
     2062        size = sizeof(DEVMODEW);
     2063    }
     2064#if 0
     2065    if(pi->pDevMode)
     2066        dmW = pi->pDevMode;
     2067    else {
     2068        dmW = (LPDEVMODEW) HeapAlloc(GetProcessHeap(), 0, size);
     2069        dmW->dmSize = size;
     2070        if (0>DocumentPropertiesW(0,0,pi->pPrinterName,dmW,NULL,DM_OUT_BUFFER)) {
     2071            ERR("DocumentPropertiesW on printer '%s' failed!\n", debugstr_w(pi->pPrinterName));
     2072            SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
     2073            return 0;
     2074        }
     2075        /* set devmode to printer name */
     2076        strcpyW(dmW->dmDeviceName,pi->pPrinterName);
     2077    }
     2078
     2079    /* Write DEVMODEA not DEVMODEW into reg.  This is what win9x does
     2080       and we support these drivers.  NT writes DEVMODEW so somehow
     2081       we'll need to distinguish between these when we support NT
     2082       drivers */
     2083    dmA = DEVMODEdupWtoA(GetProcessHeap(), dmW);
     2084    RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY, (LPBYTE)dmA,
     2085                   dmA->dmSize + dmA->dmDriverExtra);
     2086    HeapFree(GetProcessHeap(), 0, dmA);
     2087    if(!pi->pDevMode)
     2088        HeapFree(GetProcessHeap(), 0, dmW);
     2089#endif
     2090    set_reg_szW(hkeyPrinter, DescriptionW, pi->pComment);
     2091    set_reg_szW(hkeyPrinter, LocationW, pi->pLocation);
     2092    set_reg_szW(hkeyPrinter, NameW, pi->pPrinterName);
     2093    set_reg_szW(hkeyPrinter, ParametersW, pi->pParameters);
     2094
     2095    set_reg_szW(hkeyPrinter, PortW, pi->pPortName);
     2096    set_reg_szW(hkeyPrinter, Print_ProcessorW, pi->pPrintProcessor);
     2097    set_reg_szW(hkeyPrinter, Printer_DriverW, pi->pDriverName);
     2098    RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
     2099                   (LPBYTE)&pi->Priority, sizeof(DWORD));
     2100    set_reg_szW(hkeyPrinter, Separator_FileW, pi->pSepFile);
     2101    set_reg_szW(hkeyPrinter, Share_NameW, pi->pShareName);
     2102    RegSetValueExA(hkeyPrinter, "StartTime", 0, REG_DWORD,
     2103                   (LPBYTE)&pi->StartTime, sizeof(DWORD));
     2104    RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
     2105                   (LPBYTE)&pi->Status, sizeof(DWORD));
     2106    RegSetValueExA(hkeyPrinter, "UntilTime", 0, REG_DWORD,
     2107                   (LPBYTE)&pi->UntilTime, sizeof(DWORD));
     2108
     2109    RegCloseKey(hkeyPrinter);
     2110    RegCloseKey(hkeyPrinters);
     2111    if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) {
     2112        ERR("OpenPrinter failing\n");
     2113        return 0;
     2114    }
     2115    return retval;
     2116}
     2117
     2118
     2119
     2120/*****************************************************************************
     2121 * Name      : BOOL AddPrinterDriverA
     2122 * Purpose   :
     2123 * Parameters: LPSTR pName  pointer to server name
     2124 *             DWORD Level  printer info. structure level
     2125 *             LPBYTE pDriverInfo  pointer to printer info. structure
     2126 * Variables :
     2127 * Result    :
     2128 * Remark    :
     2129 * Status    : UNTESTED STUB
     2130 *
     2131 * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
     2132 *
     2133 * Author    : Markus Montkowski [09.07.98 14:20:04]
     2134 *****************************************************************************/
     2135
     2136BOOL WIN32API AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
     2137{
     2138    DRIVER_INFO_3A di3;
     2139    HKEY hkeyDrivers, hkeyName;
     2140
     2141    TRACE("(%s,%ld,%p)\n",debugstr_a(pName),level,pDriverInfo);
     2142
     2143    if(level != 2 && level != 3) {
     2144        SetLastError(ERROR_INVALID_LEVEL);
     2145        return FALSE;
     2146    }
     2147    if(pName != NULL) {
     2148        FIXME("pName= %s - unsupported\n", debugstr_a(pName));
     2149        SetLastError(ERROR_INVALID_PARAMETER);
     2150        return FALSE;
     2151    }
     2152    if(!pDriverInfo) {
     2153        WARN("pDriverInfo == NULL\n");
     2154        SetLastError(ERROR_INVALID_PARAMETER);
     2155        return FALSE;
     2156    }
     2157
     2158    if(level == 3)
     2159        di3 = *(DRIVER_INFO_3A *)pDriverInfo;
     2160    else {
     2161        memset(&di3, 0, sizeof(di3));
     2162        *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
     2163    }
     2164
     2165    if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
     2166       !di3.pDataFile) {
     2167        SetLastError(ERROR_INVALID_PARAMETER);
     2168        return FALSE;
     2169    }
     2170    if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
     2171    if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
     2172    if(!di3.pHelpFile) di3.pHelpFile = "";
     2173    if(!di3.pMonitorName) di3.pMonitorName = "";
     2174
     2175    hkeyDrivers = WINSPOOL_OpenDriverReg(di3.pEnvironment, FALSE);
     2176
     2177    if(!hkeyDrivers) {
     2178        ERR("Can't create Drivers key\n");
     2179        return FALSE;
     2180    }
     2181
     2182    if(level == 2) { /* apparently can't overwrite with level2 */
     2183        if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
     2184            RegCloseKey(hkeyName);
     2185            RegCloseKey(hkeyDrivers);
     2186            WARN("Trying to create existing printer driver %s\n", debugstr_a(di3.pName));
     2187            SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
     2188            return FALSE;
     2189        }
     2190    }
     2191    if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
     2192        RegCloseKey(hkeyDrivers);
     2193        ERR("Can't create Name key\n");
     2194        return FALSE;
     2195    }
     2196    RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, (LPBYTE)di3.pConfigFile,
     2197                   strlen(di3.pConfigFile)+1);
     2198    RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, (LPBYTE)di3.pDataFile, strlen(di3.pDataFile)+1);
     2199    RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, (LPBYTE)di3.pDriverPath, strlen(di3.pDriverPath)+1);
     2200    RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPBYTE)&di3.cVersion,
     2201                   sizeof(DWORD));
     2202    RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, (LPBYTE)di3.pDefaultDataType, strlen(di3.pDefaultDataType)+1);
     2203    RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
     2204                   (LPBYTE)di3.pDependentFiles, strlen(di3.pDependentFiles)+1);
     2205    RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, (LPBYTE)di3.pHelpFile, strlen(di3.pHelpFile)+1);
     2206    RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, (LPBYTE)di3.pMonitorName, strlen(di3.pMonitorName)+1);
     2207    RegCloseKey(hkeyName);
     2208    RegCloseKey(hkeyDrivers);
     2209
     2210    return TRUE;
     2211}
     2212
     2213
     2214/*****************************************************************************
     2215 * Name      : BOOL AddPrinterDriverW
     2216 * Purpose   :
     2217 * Parameters: LPWSTR pName  pointer to server name
     2218 *             DWORD Level  printer info. structure level
     2219 *             LPBYTE pDriverInfo  pointer to printer info. structure
     2220 * Variables :
     2221 * Result    :
     2222 * Remark    :
     2223 * Status    : UNTESTED STUB
     2224 *
     2225 * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
     2226 *
     2227 * Author    : Markus Montkowski [09.07.98 14:20:04]
     2228 *****************************************************************************/
     2229
     2230BOOL WIN32API AddPrinterDriverW(LPWSTR pName, DWORD Level, LPBYTE pDriverInfo)
     2231{
     2232  dprintf(("WINSPOOL: AddPrinterDriverW not implemented\n"));
     2233  return (FALSE);
     2234}
     2235
     2236/*****************************************************************************
     2237 * Name      : BOOL DeletePrinter
     2238 * Purpose   :
     2239 * Parameters: HANDLE hPrinter  handle to printer object
     2240 * Variables :
     2241 * Result    :
     2242 * Remark    :
     2243 * Status    : UNTESTED STUB
     2244 *
     2245 * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
     2246 *
     2247 * Author    : Markus Montkowski [09.07.98 14:30:50]
     2248 *****************************************************************************/
     2249
     2250BOOL WIN32API DeletePrinter(HANDLE hPrinter)
     2251{
     2252    LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter);
     2253    HKEY hkeyPrinters;
     2254
     2255    if(!lpNameW) return FALSE;
     2256
     2257    if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) == ERROR_SUCCESS) {
     2258        SHDeleteKeyW(hkeyPrinters, lpNameW);
     2259        RegCloseKey(hkeyPrinters);
     2260        return TRUE;
     2261    }
     2262    else {
     2263        dprintf(("Can't open Printers key"));
     2264        return FALSE;
     2265    }
     2266}
     2267
     2268
    9692269/*****************************************************************************
    9702270 * Name      : DWORD DeviceCapabilitiesA
     
    9852285 *****************************************************************************/
    9862286
    987 ODINFUNCTION5(INT, DeviceCapabilitiesA,
    988               LPCSTR, pDevice,
    989               LPCSTR, pPort,
    990               WORD, fwCapability,
    991               LPSTR, pOutput,
    992               DEVMODEA *, pDevMode)
    993 {
    994   dprintf(("WINSPOOL: DeviceCapabilitiesA %s %s %x %x %x", pDevice, pPort, fwCapability, pOutput, pDevMode));
    995   return O32_DeviceCapabilities(pDevice, pPort, fwCapability, pOutput, pDevMode);
     2287INT WIN32API DeviceCapabilitiesA(LPCSTR pDevice,
     2288                                 LPCSTR pPort,
     2289                                 WORD fwCapability,
     2290                                 LPSTR pOutput,
     2291                                 DEVMODEA * pDevMode)
     2292{
     2293    char szPMQueue[256];
     2294
     2295    dprintf(("WINSPOOL: DeviceCapabilitiesA %s %s %x %x %x", pDevice, pPort, fwCapability, pOutput, pDevMode));
     2296
     2297    //Get the PM Queue name corresponding to the printer device
     2298    if(SplQueryPMQueueName((LPSTR)pDevice, szPMQueue, sizeof(szPMQueue)) == TRUE) {
     2299        return O32_DeviceCapabilities(szPMQueue, pPort, fwCapability, pOutput, pDevMode);
     2300    }
     2301    return -1;
    9962302}
    9972303
     
    10032309 *
    10042310 */
    1005 ODINFUNCTION5(INT, DeviceCapabilitiesW, LPCWSTR, pDevice, LPCWSTR, pPort,
    1006                                   WORD, fwCapability, LPWSTR, pOutput,
    1007                                  CONST DEVMODEW *, pDevMode)
     2311INT WIN32API DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
     2312                                 WORD fwCapability, LPWSTR pOutput,
     2313                                 CONST DEVMODEW * pDevMode)
    10082314{
    10092315    LPDEVMODEA dmA = DEVMODEdupWtoA(GetProcessHeap(), pDevMode);
     
    10492355
    10502356
    1051 /*****************************************************************************
    1052  * Name      : BOOL DeleteFormA
    1053  * Purpose   :
    1054  * Parameters: HANDLE hPrinter  handle to printer object
    1055  *             LPSTR pFormName  pointer to form name
    1056  * Variables :
    1057  * Result    :
    1058  * Remark    :
    1059  * Status    : UNTESTED STUB
    1060  *
    1061  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1062  *
    1063  * Author    : Markus Montkowski [09.07.98 14:28:10]
    1064  *****************************************************************************/
    1065 
    1066 ODINFUNCTION2(BOOL, DeleteFormA,
    1067               HANDLE, hPrinter,
    1068               LPSTR, pFormName)
    1069 {
    1070   dprintf(("WINSPOOL: DeleteFormA not implemented\n"));
    1071   return (FALSE);
    1072 }
    1073 
    1074 
    1075 /*****************************************************************************
    1076  * Name      : BOOL DeleteFormW
    1077  * Purpose   :
    1078  * Parameters: HANDLE hPrinter  handle to printer object
    1079  *             LPWSTR pFormName  pointer to form name
    1080  * Variables :
    1081  * Result    :
    1082  * Remark    :
    1083  * Status    : UNTESTED STUB
    1084  *
    1085  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1086  *
    1087  * Author    : Markus Montkowski [09.07.98 14:28:10]
    1088  *****************************************************************************/
    1089 
    1090 ODINFUNCTION2(BOOL, DeleteFormW,
    1091               HANDLE, hPrinter,
    1092               LPWSTR, pFormName)
    1093 {
    1094   dprintf(("WINSPOOL: DeleteFormW not implemented\n"));
    1095   return (FALSE);
    1096 }
    1097 
    1098 
    1099 /*****************************************************************************
    1100  * Name      : BOOL DeleteMonitorA
    1101  * Purpose   :
    1102  * Parameters: LPSTR pName  pointer to server name
    1103  *             LPSTR pEnvironment  pointer to environment string
    1104  *             LPSTR pMonitorName  pointer to monitor name
    1105  * Variables :
    1106  * Result    :
    1107  * Remark    :
    1108  * Status    : UNTESTED STUB
    1109  *
    1110  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1111  *
    1112  * Author    : Markus Montkowski [09.07.98 14:28:35]
    1113  *****************************************************************************/
    1114 
    1115 ODINFUNCTION3(BOOL, DeleteMonitorA,
    1116               LPSTR, pName,
    1117               LPSTR, pEnvironment,
    1118               LPSTR, pMonitorName)
    1119 {
    1120   dprintf(("WINSPOOL: DeleteMonitorA not implemented\n"));
    1121   return (FALSE);
    1122 }
    1123 
    1124 
    1125 /*****************************************************************************
    1126  * Name      : BOOL DeleteMonitorW
    1127  * Purpose   :
    1128  * Parameters: LPWSTR pName  pointer to server name
    1129  *             LPWSTR pEnvironment  pointer to environment string
    1130  *             LPWSTR pMonitorName  pointer to monitor name
    1131  * Variables :
    1132  * Result    :
    1133  * Remark    :
    1134  * Status    : UNTESTED STUB
    1135  *
    1136  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1137  *
    1138  * Author    : Markus Montkowski [09.07.98 14:28:35]
    1139  *****************************************************************************/
    1140 
    1141 ODINFUNCTION3(BOOL, DeleteMonitorW,
    1142               LPWSTR, pName,
    1143               LPWSTR, pEnvironment,
    1144               LPWSTR, pMonitorName)
    1145 {
    1146   dprintf(("WINSPOOL: DeleteMonitorW not implemented\n"));
    1147   return (FALSE);
    1148 }
    1149 
    1150 
    1151 /*****************************************************************************
    1152  * Name      : BOOL DeletePortA
    1153  * Purpose   :
    1154  * Parameters: LPSTR pName  pointer to server name
    1155  *             HWND hWnd  handle to window that displays dialog box
    1156  *             LPSTR pPortName  pointer to port name
    1157  * Variables :
    1158  * Result    :
    1159  * Remark    :
    1160  * Status    : UNTESTED STUB
    1161  *
    1162  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1163  *
    1164  * Author    : Markus Montkowski [09.07.98 14:28:58]
    1165  *****************************************************************************/
    1166 
    1167 ODINFUNCTION3(BOOL, DeletePortA,
    1168               LPSTR, pName,
    1169               HWND, hWnd,
    1170               LPSTR, pPortName)
    1171 {
    1172   dprintf(("WINSPOOL: DeletePortA not implemented\n"));
    1173   return (FALSE);
    1174 }
    1175 
    1176 
    1177 /*****************************************************************************
    1178  * Name      : BOOL DeletePortW
    1179  * Purpose   :
    1180  * Parameters: LPWSTR pName  pointer to server name
    1181  *             HWND hWnd  handle to window that displays dialog box
    1182  *             LPWSTR pPortName  pointer to port name
    1183  * Variables :
    1184  * Result    :
    1185  * Remark    :
    1186  * Status    : UNTESTED STUB
    1187  *
    1188  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1189  *
    1190  * Author    : Markus Montkowski [09.07.98 14:28:58]
    1191  *****************************************************************************/
    1192 
    1193 ODINFUNCTION3(BOOL, DeletePortW,
    1194               LPWSTR, pName,
    1195               HWND, hWnd,
    1196               LPWSTR, pPortName)
    1197 {
    1198   dprintf(("WINSPOOL: DeletePortW not implemented\n"));
    1199   return (FALSE);
    1200 }
    1201 
    1202 
    1203 /*****************************************************************************
    1204  * Name      : BOOL DeletePrintProcessorA
    1205  * Purpose   :
    1206  * Parameters: LPSTR pName  pointer to server name
    1207  *             LPSTR pEnvironment  pointer to environment string
    1208  *             LPSTR pPrintProcessorName  pointer to processor name
    1209  * Variables :
    1210  * Result    :
    1211  * Remark    :
    1212  * Status    : UNTESTED STUB
    1213  *
    1214  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1215  *
    1216  * Author    : Markus Montkowski [09.07.98 14:30:08]
    1217  *****************************************************************************/
    1218 
    1219 ODINFUNCTION3(BOOL, DeletePrintProcessorA,
    1220               LPSTR, pName,
    1221               LPSTR, pEnvironment,
    1222               LPSTR, pPrintProcessorName)
    1223 {
    1224   dprintf(("WINSPOOL: DeletePrintProcessorA not implemented\n"));
    1225   return (FALSE);
    1226 }
    1227 
    1228 
    1229 /*****************************************************************************
    1230  * Name      : BOOL DeletePrintProcessorW
    1231  * Purpose   :
    1232  * Parameters: LPWSTR pName  pointer to server name
    1233  *             LPWSTR pEnvironment  pointer to environment string
    1234  *             LPWSTR pPrintProcessorName  pointer to processor name
    1235  * Variables :
    1236  * Result    :
    1237  * Remark    :
    1238  * Status    : UNTESTED STUB
    1239  *
    1240  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1241  *
    1242  * Author    : Markus Montkowski [09.07.98 14:30:08]
    1243  *****************************************************************************/
    1244 
    1245 ODINFUNCTION3(BOOL, DeletePrintProcessorW,
    1246               LPWSTR, pName,
    1247               LPWSTR, pEnvironment,
    1248               LPWSTR, pPrintProcessorName)
    1249 {
    1250   dprintf(("WINSPOOL: DeletePrintProcessorW not implemented\n"));
    1251   return (FALSE);
    1252 }
    1253 
    1254 
    1255 /*****************************************************************************
    1256  * Name      : BOOL DeletePrintProvidorA
    1257  * Purpose   :
    1258  * Parameters: LPSTR pName  pointer to server name
    1259  *             LPSTR pEnvironment  pointer to environment string
    1260  *             LPSTR pPrintProvidorName  pointer to provider name
    1261  * Variables :
    1262  * Result    :
    1263  * Remark    :
    1264  * Status    : UNTESTED STUB
    1265  *
    1266  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1267  *
    1268  * Author    : Markus Montkowski [09.07.98 14:30:29]
    1269  *****************************************************************************/
    1270 
    1271 ODINFUNCTION3(BOOL, DeletePrintProvidorA,
    1272               LPSTR, pName,
    1273               LPSTR, pEnvironment,
    1274               LPSTR, pPrintProvidorName)
    1275 {
    1276   dprintf(("WINSPOOL: DeletePrintProvidorA not implemented\n"));
    1277   return (FALSE);
    1278 }
    1279 
    1280 
    1281 /*****************************************************************************
    1282  * Name      : BOOL DeletePrintProvidorW
    1283  * Purpose   :
    1284  * Parameters: LPWSTR pName  pointer to server name
    1285  *             LPWSTR pEnvironment  pointer to environment string
    1286  *             LPWSTR pPrintProvidorName  pointer to provider name
    1287  * Variables :
    1288  * Result    :
    1289  * Remark    :
    1290  * Status    : UNTESTED STUB
    1291  *
    1292  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1293  *
    1294  * Author    : Markus Montkowski [09.07.98 14:30:29]
    1295  *****************************************************************************/
    1296 
    1297 ODINFUNCTION3(BOOL, DeletePrintProvidorW,
    1298               LPWSTR, pName,
    1299               LPWSTR, pEnvironment,
    1300               LPWSTR, pPrintProvidorName)
    1301 {
    1302   dprintf(("WINSPOOL: DeletePrintProvidorW not implemented\n"));
    1303   return (FALSE);
    1304 }
    1305 
    1306 
    1307 /*****************************************************************************
    1308  * Name      : BOOL DeletePrinter
    1309  * Purpose   :
    1310  * Parameters: HANDLE hPrinter  handle to printer object
    1311  * Variables :
    1312  * Result    :
    1313  * Remark    :
    1314  * Status    : UNTESTED STUB
    1315  *
    1316  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1317  *
    1318  * Author    : Markus Montkowski [09.07.98 14:30:50]
    1319  *****************************************************************************/
    1320 
    1321 ODINFUNCTION1(BOOL, DeletePrinter,
    1322               HANDLE, hPrinter)
    1323 {
    1324   dprintf(("WINSPOOL: DeletePrinter not implemented\n"));
    1325   return (FALSE);
    1326 }
    1327 
    1328 
    1329 /*****************************************************************************
    1330  * Name      : BOOL DeletePrinterConnectionA
    1331  * Purpose   :
    1332  * Parameters: LPSTR pName  pointer to printer name
    1333  * Variables :
    1334  * Result    :
    1335  * Remark    :
    1336  * Status    : UNTESTED STUB
    1337  *
    1338  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1339  *
    1340  * Author    : Markus Montkowski [09.07.98 14:31:48]
    1341  *****************************************************************************/
    1342 
    1343 ODINFUNCTION1(BOOL, DeletePrinterConnectionA,
    1344               LPSTR, pName)
    1345 {
    1346   dprintf(("WINSPOOL: DeletePrinterConnectionA not implemented\n"));
    1347   return (FALSE);
    1348 }
    1349 
    1350 
    1351 /*****************************************************************************
    1352  * Name      : BOOL DeletePrinterConnectionW
    1353  * Purpose   :
    1354  * Parameters: LPWSTR pName  pointer to printer name
    1355  * Variables :
    1356  * Result    :
    1357  * Remark    :
    1358  * Status    : UNTESTED STUB
    1359  *
    1360  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1361  *
    1362  * Author    : Markus Montkowski [09.07.98 14:31:48]
    1363  *****************************************************************************/
    1364 
    1365 ODINFUNCTION1(BOOL, DeletePrinterConnectionW,
    1366               LPWSTR, pName)
    1367 {
    1368   dprintf(("WINSPOOL: DeletePrinterConnectionW not implemented\n"));
    1369   return (FALSE);
    1370 }
    1371 
    1372 
    1373 /*****************************************************************************
    1374  * Name      : BOOL DeletePrinterDriverA
    1375  * Purpose   :
    1376  * Parameters: LPSTR pName  pointer to server name
    1377  *             LPSTR pEnvironment  pointer to environment
    1378  *             LPSTR pDriverName  pointer to driver name
    1379  * Variables :
    1380  * Result    :
    1381  * Remark    :
    1382  * Status    : UNTESTED STUB
    1383  *
    1384  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1385  *
    1386  * Author    : Markus Montkowski [09.07.98 14:32:38]
    1387  *****************************************************************************/
    1388 
    1389 ODINFUNCTION3(BOOL, DeletePrinterDriverA,
    1390               LPSTR, pName,
    1391               LPSTR, pEnvironment,
    1392               LPSTR, pDriverName)
    1393 {
    1394   dprintf(("WINSPOOL: DeletePrinterDriverA not implemented\n"));
    1395   return (FALSE);
    1396 }
    1397 
    1398 
    1399 /*****************************************************************************
    1400  * Name      : BOOL DeletePrinterDriverW
    1401  * Purpose   :
    1402  * Parameters: LPWSTR pName  pointer to server name
    1403  *             LPWSTR pEnvironment  pointer to environment
    1404  *             LPWSTR pDriverName  pointer to driver name
    1405  * Variables :
    1406  * Result    :
    1407  * Remark    :
    1408  * Status    : UNTESTED STUB
    1409  *
    1410  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1411  *
    1412  * Author    : Markus Montkowski [09.07.98 14:32:38]
    1413  *****************************************************************************/
    1414 
    1415 ODINFUNCTION3(BOOL, DeletePrinterDriverW,
    1416               LPWSTR, pName,
    1417               LPWSTR, pEnvironment,
    1418               LPWSTR, pDriverName)
    1419 {
    1420   dprintf(("WINSPOOL: DeletePrinterDriverW not implemented\n"));
    1421   return (FALSE);
    1422 }
    1423 
    1424 
    1425 /*****************************************************************************
    1426  * Name      : BOOL EndDocPrinter
    1427  * Purpose   :
    1428  * Parameters: HANDLE hPrinter  handle to printer object
    1429  * Variables :
    1430  * Result    :
    1431  * Remark    :
    1432  * Status    : UNTESTED STUB
    1433  *
    1434  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1435  *
    1436  * Author    : Markus Montkowski [09.07.98 14:34:09]
    1437  *****************************************************************************/
    1438 
    1439 ODINFUNCTION1(BOOL, EndDocPrinter,
    1440               HANDLE, hPrinter)
    1441 {
    1442   dprintf(("WINSPOOL: EndDocPrinter not implemented\n"));
    1443   return (FALSE);
    1444 }
    1445 
    1446 
    1447 /*****************************************************************************
    1448  * Name      : BOOL EndPagePrinter
    1449  * Purpose   :
    1450  * Parameters: HANDLE hPrinter  handle to printer object
    1451  * Variables :
    1452  * Result    :
    1453  * Remark    :
    1454  * Status    : UNTESTED STUB
    1455  *
    1456  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1457  *
    1458  * Author    : Markus Montkowski [09.07.98 14:34:27]
    1459  *****************************************************************************/
    1460 
    1461 ODINFUNCTION1(BOOL, EndPagePrinter,
    1462               HANDLE, hPrinter)
    1463 {
    1464   dprintf(("WINSPOOL: EndPagePrinter not implemented\n"));
    1465   return (FALSE);
    1466 }
    1467 
    1468 
    1469 /*****************************************************************************
    1470  * Name      : BOOL EnumFormsA
    1471  * Purpose   :
    1472  * Parameters: HANDLE hPrinter  handle to printer object
    1473  *             DWORD Level  data-structure level
    1474  *             LPBYTE pForm  points to buffer that receives form info. structure array
    1475  *             DWORD cbBuf  count of bytes in buffer
    1476  *             LPDWORD pcbNeeded  points to variable to receive count of bytes copied or required
    1477  *             LPDWORD pcReturned  points to variable to receive count of structures copied
    1478  * Variables :
    1479  * Result    :
    1480  * Remark    :
    1481  * Status    : UNTESTED STUB
    1482  *
    1483  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1484  *
    1485  * Author    : Markus Montkowski [09.07.98 14:35:07]
    1486  *****************************************************************************/
    1487 
    1488 ODINFUNCTION6(BOOL, EnumFormsA,
    1489               HANDLE, hPrinter,
    1490               DWORD, Level,
    1491               LPBYTE, pForm,
    1492               DWORD, cbBuf,
    1493               LPDWORD, pcbNeeded,
    1494               LPDWORD, pcReturned)
    1495 {
    1496   dprintf(("WINSPOOL: EnumFormsA not implemented\n"));
    1497   return (FALSE);
    1498 }
    1499 
    1500 
    1501 /*****************************************************************************
    1502  * Name      : BOOL EnumFormsW
    1503  * Purpose   :
    1504  * Parameters: HANDLE hPrinter  handle to printer object
    1505  *             DWORD Level  data-structure level
    1506  *             LPBYTE pForm  points to buffer that receives form info. structure array
    1507  *             DWORD cbBuf  count of bytes in buffer
    1508  *             LPDWORD pcbNeeded  points to variable to receive count of bytes copied or required
    1509  *             LPDWORD pcReturned  points to variable to receive count of structures copied
    1510  * Variables :
    1511  * Result    :
    1512  * Remark    :
    1513  * Status    : UNTESTED STUB
    1514  *
    1515  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1516  *
    1517  * Author    : Markus Montkowski [09.07.98 14:35:07]
    1518  *****************************************************************************/
    1519 
    1520 ODINFUNCTION6(BOOL, EnumFormsW,
    1521               HANDLE, hPrinter,
    1522               DWORD, Level,
    1523               LPBYTE, pForm,
    1524               DWORD, cbBuf,
    1525               LPDWORD, pcbNeeded,
    1526               LPDWORD, pcReturned)
    1527 {
    1528   dprintf(("WINSPOOL: EnumFormsW not implemented\n"));
    1529 
    1530   return (FALSE);
    1531 }
    1532 
    1533 
    1534 /*****************************************************************************
    1535  * Name      : BOOL EnumJobsA
    1536  * Purpose   :
    1537  * Parameters: HANDLE hPrinter  handle to printer object
    1538  *             DWORD FirstJob  location of first job in print queue to enumerate
    1539  *             DWORD NoJobs  number of jobs to enumerate
    1540  *             DWORD Level  structure level
    1541  *             LPBYTE pJob  pointer to structure array
    1542  *             DWORD cbBuf  size of array, in bytes
    1543  *             LPDWORD pcbNeeded  addr. of variable with no. of bytes copied (or required)
    1544  *             LPDWORD pcReturned  addr. of variable with no. of job info. structures copied
    1545  * Variables :
    1546  * Result    :
    1547  * Remark    :
    1548  * Status    : UNTESTED STUB
    1549  *
    1550  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1551  *
    1552  * Author    : Markus Montkowski [09.07.98 14:36:24]
    1553  *****************************************************************************/
    1554 
    1555 ODINFUNCTION8(BOOL, EnumJobsA,
    1556               HANDLE, hPrinter,
    1557               DWORD, FirstJob,
    1558               DWORD, NoJobs,
    1559               DWORD, Level,
    1560               LPBYTE, pJob,
    1561               DWORD, cbBuf,
    1562               LPDWORD, pcbNeeded,
    1563               LPDWORD, pcReturned)
    1564 {
    1565   dprintf(("WINSPOOL: EnumJobsA not implemented\n"));
    1566   return (FALSE);
    1567 }
    1568 
    1569 
    1570 /*****************************************************************************
    1571  * Name      : BOOL EnumJobsW
    1572  * Purpose   :
    1573  * Parameters: HANDLE hPrinter  handle to printer object
    1574  *             DWORD FirstJob  location of first job in print queue to enumerate
    1575  *             DWORD NoJobs  number of jobs to enumerate
    1576  *             DWORD Level  structure level
    1577  *             LPBYTE pJob  pointer to structure array
    1578  *             DWORD cbBuf  size of array, in bytes
    1579  *             LPDWORD pcbNeeded  addr. of variable with no. of bytes copied (or required)
    1580  *             LPDWORD pcReturned  addr. of variable with no. of job info. structures copied
    1581  * Variables :
    1582  * Result    :
    1583  * Remark    :
    1584  * Status    : UNTESTED STUB
    1585  *
    1586  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1587  *
    1588  * Author    : Markus Montkowski [09.07.98 14:36:24]
    1589  *****************************************************************************/
    1590 
    1591 ODINFUNCTION8(BOOL, EnumJobsW,
    1592               HANDLE, hPrinter,
    1593               DWORD, FirstJob,
    1594               DWORD, NoJobs,
    1595               DWORD, Level,
    1596               LPBYTE, pJob,
    1597               DWORD, cbBuf,
    1598               LPDWORD, pcbNeeded,
    1599               LPDWORD, pcReturned)
    1600 {
    1601   dprintf(("WINSPOOL: EnumJobsW not implemented\n"));
    1602   return (FALSE);
    1603 }
    1604 
    1605 
    1606 /*****************************************************************************
    1607  * Name      : BOOL EnumMonitorsA
    1608  * Purpose   :
    1609  * Parameters: LPSTR pName  pointer to server name
    1610  *             DWORD Level  structure level
    1611  *             LPBYTE pMonitors  pointer to structure array
    1612  *             DWORD cbBuf  size, in bytes, of buffer
    1613  *             LPDWORD pcbNeeded  addr. of variable with no. of bytes copied (or required)
    1614  *             LPDWORD pcReturned  addr. of variable with no. of job info. structures copied
    1615  * Variables :
    1616  * Result    :
    1617  * Remark    :
    1618  * Status    : UNTESTED STUB
    1619  *
    1620  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1621  *
    1622  * Author    : Markus Montkowski [09.07.98 14:38:50]
    1623  *****************************************************************************/
    1624 
    1625 ODINFUNCTION6(BOOL, EnumMonitorsA,
    1626               LPSTR, pName,
    1627               DWORD, Level,
    1628               LPBYTE, pMonitors,
    1629               DWORD, cbBuf,
    1630               LPDWORD, pcbNeeded,
    1631               LPDWORD, pcReturned)
    1632 {
    1633   dprintf(("WINSPOOL: EnumMonitorsA not implemented\n"));
    1634   return (FALSE);
    1635 }
    1636 
    1637 
    1638 /*****************************************************************************
    1639  * Name      : BOOL EnumMonitorsW
    1640  * Purpose   :
    1641  * Parameters: LPWSTR pName  pointer to server name
    1642  *             DWORD Level  structure level
    1643  *             LPBYTE pMonitors  pointer to structure array
    1644  *             DWORD cbBuf  size, in bytes, of buffer
    1645  *             LPDWORD pcbNeeded  addr. of variable with no. of bytes copied (or required)
    1646  *             LPDWORD pcReturned  addr. of variable with no. of job info. structures copied
    1647  * Variables :
    1648  * Result    :
    1649  * Remark    :
    1650  * Status    : UNTESTED STUB
    1651  *
    1652  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1653  *
    1654  * Author    : Markus Montkowski [09.07.98 14:38:50]
    1655  *****************************************************************************/
    1656 
    1657 ODINFUNCTION6(BOOL, EnumMonitorsW,
    1658               LPWSTR, pName,
    1659               DWORD, Level,
    1660               LPBYTE, pMonitors,
    1661               DWORD, cbBuf,
    1662               LPDWORD, pcbNeeded,
    1663               LPDWORD, pcReturned)
    1664 {
    1665   dprintf(("WINSPOOL: EnumMonitorsW not implemented\n"));
    1666   return (FALSE);
    1667 }
    1668 
    1669 
    1670 /*****************************************************************************
    1671  * Name      : BOOL EnumPortsA
    1672  * Purpose   :
    1673  * Parameters: LPSTR pName  pointer to server name
    1674  *             DWORD Level  specifies type of port info structure
    1675  *             LPBYTE pPorts  pointer to buffer to receive array of port info. structures
    1676  *             DWORD cbBuf  specifies size, in bytes, of buffer
    1677  *             LPDWORD pcbNeeded  buffer size)
    1678  *             LPDWORD pcReturned  pointer to number of PORT_INFO_*. structures stored into buffer
    1679  * Variables :
    1680  * Result    :
    1681  * Remark    :
    1682  * Status    : UNTESTED STUB
    1683  *
    1684  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1685  *
    1686  * Author    : Markus Montkowski [09.07.98 14:39:09]
    1687  *****************************************************************************/
    1688 
    1689 ODINFUNCTION6(BOOL, EnumPortsA,
    1690               LPSTR, pName,
    1691               DWORD, Level,
    1692               LPBYTE, pPorts,
    1693               DWORD, cbBuf,
    1694               LPDWORD, pcbNeeded,
    1695               LPDWORD, pcReturned)
    1696 {
    1697   dprintf(("WINSPOOL: EnumPortsA not implemented\n"));
    1698   return (FALSE);
    1699 }
    1700 
    1701 
    1702 /*****************************************************************************
    1703  * Name      : BOOL EnumPortsW
    1704  * Purpose   :
    1705  * Parameters: LPWSTR pName  pointer to server name
    1706  *             DWORD Level  specifies type of port info structure
    1707  *             LPBYTE pPorts  pointer to buffer to receive array of port info. structures
    1708  *             DWORD cbBuf  specifies size, in bytes, of buffer
    1709  *             LPDWORD pcbNeeded  buffer size)
    1710  *             LPDWORD pcReturned  pointer to number of PORT_INFO_*. structures stored into buffer
    1711  * Variables :
    1712  * Result    :
    1713  * Remark    :
    1714  * Status    : UNTESTED STUB
    1715  *
    1716  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1717  *
    1718  * Author    : Markus Montkowski [09.07.98 14:39:09]
    1719  *****************************************************************************/
    1720 
    1721 ODINFUNCTION6(BOOL, EnumPortsW,
    1722               LPWSTR, pName,
    1723               DWORD, Level,
    1724               LPBYTE, pPorts,
    1725               DWORD, cbBuf,
    1726               LPDWORD, pcbNeeded,
    1727               LPDWORD, pcReturned)
    1728 {
    1729   dprintf(("WINSPOOL: EnumPortsW not implemented\n"));
    1730   return (FALSE);
    1731 }
    1732 
    1733 
    1734 /*****************************************************************************
    1735  * Name      : BOOL EnumPrintProcessorDatatypesA
    1736  * Purpose   :
    1737  * Parameters: LPSTR pName  points to server name string
    1738  *             LPSTR pPrintProcessorName  points to print processor name string
    1739  *             DWORD Level  specifies version of print processor data type structures
    1740  *             LPBYTE pDatatypes  points to buffer to receive print processor data type structures
    1741  *             DWORD cbBuf  specifies size, in bytes, of buffer
    1742  *             LPDWORD pcbNeeded  points to number of bytes copied (or required)
    1743  *             LPDWORD pcReturned  points to number of data structures obtained
    1744  * Variables :
    1745  * Result    :
    1746  * Remark    :
    1747  * Status    : UNTESTED STUB
    1748  *
    1749  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1750  *
    1751  * Author    : Markus Montkowski [09.07.98 14:39:29]
    1752  *****************************************************************************/
    1753 
    1754 ODINFUNCTION7(BOOL, EnumPrintProcessorDatatypesA,
    1755               LPSTR, pName,
    1756               LPSTR, pPrintProcessorName,
    1757               DWORD, Level,
    1758               LPBYTE, pDatatypes,
    1759               DWORD, cbBuf,
    1760               LPDWORD, pcbNeeded,
    1761               LPDWORD, pcReturned)
    1762 {
    1763   dprintf(("WINSPOOL: EnumPrintProcessorDatatypesA not implemented\n"));
    1764   return (FALSE);
    1765 }
    1766 
    1767 
    1768 /*****************************************************************************
    1769  * Name      : BOOL EnumPrintProcessorDatatypesW
    1770  * Purpose   :
    1771  * Parameters: LPWSTR pName  points to server name string
    1772  *             LPWSTR pPrintProcessorName  points to print processor name string
    1773  *             DWORD Level  specifies version of print processor data type structures
    1774  *             LPBYTE pDatatypes  points to buffer to receive print processor data type structures
    1775  *             DWORD cbBuf  specifies size, in bytes, of buffer
    1776  *             LPDWORD pcbNeeded  points to number of bytes copied (or required)
    1777  *             LPDWORD pcReturned  points to number of data structures obtained
    1778  * Variables :
    1779  * Result    :
    1780  * Remark    :
    1781  * Status    : UNTESTED STUB
    1782  *
    1783  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1784  *
    1785  * Author    : Markus Montkowski [09.07.98 14:39:30]
    1786  *****************************************************************************/
    1787 
    1788 ODINFUNCTION7(BOOL, EnumPrintProcessorDatatypesW,
    1789               LPWSTR, pName,
    1790               LPWSTR, pPrintProcessorName,
    1791               DWORD, Level,
    1792               LPBYTE, pDatatypes,
    1793               DWORD, cbBuf,
    1794               LPDWORD, pcbNeeded,
    1795               LPDWORD, pcReturned)
    1796 {
    1797   dprintf(("WINSPOOL: EnumPrintProcessorDatatypesW not implemented\n"));
    1798   return (FALSE);
    1799 }
    1800 
    1801 
    1802 /*****************************************************************************
    1803  * Name      : BOOL EnumPrintProcessorsA
    1804  * Purpose   :
    1805  * Parameters: LPSTR pName  points to server name
    1806  *             LPSTR pEnvironment  points to environment name
    1807  *             DWORD Level  structure level
    1808  *             LPBYTE pPrintProcessorInfo  points to structure array
    1809  *             DWORD cbBuf  array length in bytes
    1810  *             LPDWORD pcbNeeded  points to number of bytes copied (or required)
    1811  *             LPDWORD pcReturned  points to number of job info. structures copied
    1812  * Variables :
    1813  * Result    :
    1814  * Remark    :
    1815  * Status    : UNTESTED STUB
    1816  *
    1817  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1818  *
    1819  * Author    : Markus Montkowski [09.07.98 14:39:52]
    1820  *****************************************************************************/
    1821 
    1822 ODINFUNCTION7(BOOL, EnumPrintProcessorsA,
    1823               LPSTR, pName,
    1824               LPSTR, pEnvironment,
    1825               DWORD, Level,
    1826               LPBYTE, pPrintProcessorInfo,
    1827               DWORD, cbBuf,
    1828               LPDWORD, pcbNeeded,
    1829               LPDWORD, pcReturned)
    1830 {
    1831   dprintf(("WINSPOOL: EnumPrintProcessorsA not implemented\n"));
    1832   return (FALSE);
    1833 }
    1834 
    1835 
    1836 /*****************************************************************************
    1837  * Name      : BOOL EnumPrintProcessorsW
    1838  * Purpose   :
    1839  * Parameters: LPWSTR pName  points to server name
    1840  *             LPWSTR pEnvironment  points to environment name
    1841  *             DWORD Level  structure level
    1842  *             LPBYTE pPrintProcessorInfo  points to structure array
    1843  *             DWORD cbBuf  array length in bytes
    1844  *             LPDWORD pcbNeeded  points to number of bytes copied (or required)
    1845  *             LPDWORD pcReturned  points to number of job info. structures copied
    1846  * Variables :
    1847  * Result    :
    1848  * Remark    :
    1849  * Status    : UNTESTED STUB
    1850  *
    1851  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1852  *
    1853  * Author    : Markus Montkowski [09.07.98 14:39:52]
    1854  *****************************************************************************/
    1855 
    1856 ODINFUNCTION7(BOOL, EnumPrintProcessorsW,
    1857               LPWSTR, pName,
    1858               LPWSTR, pEnvironment,
    1859               DWORD, Level,
    1860               LPBYTE, pPrintProcessorInfo,
    1861               DWORD, cbBuf,
    1862               LPDWORD, pcbNeeded,
    1863               LPDWORD, pcReturned)
    1864 {
    1865   dprintf(("WINSPOOL: EnumPrintProcessorsW not implemented\n"));
    1866   return (FALSE);
    1867 }
    1868 
    1869 
    1870 /*****************************************************************************
    1871  * Name      : BOOL EnumPrinterDriversA
    1872  * Purpose   :
    1873  * Parameters: LPSTR pName  pointer to server name
    1874  *             LPSTR pEnvironment  pointer to environment name
    1875  *             DWORD Level  structure level
    1876  *             LPBYTE pDriverInfo  pointer to an array of structures
    1877  *             DWORD cbBuf  size, in bytes, of array
    1878  *             LPDWORD pcbNeeded  pointer to number of bytes copied (or required)
    1879  *             LPDWORD pcReturned  pointer to number of DRIVER_INFO. structures
    1880  * Variables :
    1881  * Result    :
    1882  * Remark    :
    1883  * Status    : UNTESTED STUB
    1884  *
    1885  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1886  *
    1887  * Author    : Markus Montkowski [09.07.98 14:40:23]
    1888  *****************************************************************************/
    1889 
    1890 ODINFUNCTION7(BOOL, EnumPrinterDriversA,
    1891               LPSTR, pName,
    1892               LPSTR, pEnvironment,
    1893               DWORD, Level,
    1894               LPBYTE, pDriverInfo,
    1895               DWORD, cbBuf,
    1896               LPDWORD, pcbNeeded,
    1897               LPDWORD, pcReturned)
    1898 {
    1899   dprintf(("WINSPOOL: EnumPrinterDriversA not implemented\n"));
    1900   return (FALSE);
    1901 }
    1902 
    1903 
    1904 /*****************************************************************************
    1905  * Name      : BOOL EnumPrinterDriversW
    1906  * Purpose   :
    1907  * Parameters: LPWSTR pName  pointer to server name
    1908  *             LPWSTR pEnvironment  pointer to environment name
    1909  *             DWORD Level  structure level
    1910  *             LPBYTE pDriverInfo  pointer to an array of structures
    1911  *             DWORD cbBuf  size, in bytes, of array
    1912  *             LPDWORD pcbNeeded  pointer to number of bytes copied (or required)
    1913  *             LPDWORD pcReturned  pointer to number of DRIVER_INFO. structures
    1914  * Variables :
    1915  * Result    :
    1916  * Remark    :
    1917  * Status    : UNTESTED STUB
    1918  *
    1919  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1920  *
    1921  * Author    : Markus Montkowski [09.07.98 14:40:24]
    1922  *****************************************************************************/
    1923 
    1924 ODINFUNCTION7(BOOL, EnumPrinterDriversW,
    1925               LPWSTR, pName,
    1926               LPWSTR, pEnvironment,
    1927               DWORD, Level,
    1928               LPBYTE, pDriverInfo,
    1929               DWORD, cbBuf,
    1930               LPDWORD, pcbNeeded,
    1931               LPDWORD, pcReturned)
    1932 {
    1933   dprintf(("WINSPOOL: EnumPrinterDriversW not implemented\n"));
    1934   return (FALSE);
    1935 }
    1936 
    1937 
    1938 /*****************************************************************************
    1939  * Name      : BOOL EnumPrintersW
    1940  * Purpose   :
    1941  * Parameters: DWORD Flags  types of printer objects to enumerate
    1942  *             LPWSTR Name  name of printer object
    1943  *             DWORD Level  specifies type of printer info structure
    1944  *             LPBYTE pPrinterEnum  pointer to buffer to receive printer info structures
    1945  *             DWORD cbBuf  size, in bytes, of array
    1946  *             LPDWORD pcbNeeded  pointer to variable with no. of bytes copied (or required)
    1947  *             LPDWORD pcReturned  pointer to variable with no. of printer info. structures copied
    1948  * Variables :
    1949  * Result    :
    1950  * Remark    :
    1951  * Status    : UNTESTED STUB
    1952  *
    1953  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1954  *
    1955  * Author    : Markus Montkowski [09.07.98 14:40:55]
    1956  *****************************************************************************/
    1957 
    1958 ODINFUNCTION7(BOOL, EnumPrintersW,
    1959               DWORD, Flags,
    1960               LPWSTR, Name,
    1961               DWORD, Level,
    1962               LPBYTE, pPrinterEnum,
    1963               DWORD, cbBuf,
    1964               LPDWORD, pcbNeeded,
    1965               LPDWORD, pcReturned)
    1966 {
    1967   dprintf(("WINSPOOL: EnumPrintersW not implemented\n"));
    1968   return (FALSE);
    1969 }
    1970 
    1971 
    1972 /*****************************************************************************
    1973  * Name      : BOOL FindClosePrinterChangeNotification
    1974  * Purpose   :
    1975  * Parameters: HANDLE hChange  handle to change notification object to close
    1976  * Variables :
    1977  * Result    :
    1978  * Remark    :
    1979  * Status    : UNTESTED STUB
    1980  *
    1981  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    1982  *
    1983  * Author    : Markus Montkowski [09.07.98 14:41:51]
    1984  *****************************************************************************/
    1985 
    1986 ODINFUNCTION1(BOOL, FindClosePrinterChangeNotification,
    1987               HANDLE, hChange)
    1988 {
    1989   dprintf(("WINSPOOL: FindClosePrinterChangeNotification not implemented\n"));
    1990   return (FALSE);
    1991 }
    1992 
    1993 
    1994 /*****************************************************************************
    1995  * Name      : HANDLE FindFirstPrinterChangeNotification
    1996  * Purpose   :
    1997  * Parameters: HANDLE hPrinter  handle to printer or print server to monitor for changes
    1998  *             DWORD fdwFlags  flags that specify the conditions to monitor
    1999  *             DWORD fdwOptions  reserved, must be zero
    2000  *             LPVOID pPrinterNotifyOptions  pointer to structure specifying printer information to monitor
    2001  * Variables :
    2002  * Result    :
    2003  * Remark    :
    2004  * Status    : UNTESTED STUB
    2005  *
    2006  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2007  *
    2008  * Author    : Markus Montkowski [09.07.98 14:42:05]
    2009  *****************************************************************************/
    2010 
    2011 ODINFUNCTION4(HANDLE, FindFirstPrinterChangeNotification,
    2012               HANDLE, hPrinter,
    2013               DWORD, fdwFlags,
    2014               DWORD, fdwOptions,
    2015               LPPRINTER_NOTIFY_INFO, pPrinterNotifyOptions)
    2016 {
    2017   dprintf(("WINSPOOL: FindFirstPrinterChangeNotification not implemented\n"));
    2018   return (NULL);
    2019 }
    2020 
    2021 
    2022 /*****************************************************************************
    2023  * Name      : BOOL FindNextPrinterChangeNotification
    2024  * Purpose   :
    2025  * Parameters: HANDLE hChange  handle to change notification object of interest
    2026  *             PDWORD pdwChange  pointer to a value that indicates the condition that changed
    2027  *             LPVOID pPrinterNotifyOptions  pointer to a structure that specifies a refresh flag
    2028  *             LPVOID *ppPrinterNotifyInfo  pointer to a pointer that receives printer information buffer
    2029  * Variables :
    2030  * Result    :
    2031  * Remark    :
    2032  * Status    : UNTESTED STUB
    2033  *
    2034  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2035  *
    2036  * Author    : Markus Montkowski [09.07.98 14:42:20]
    2037  *****************************************************************************/
    2038 
    2039 ODINFUNCTION4(BOOL, FindNextPrinterChangeNotification,
    2040               HANDLE, hChange,
    2041               PDWORD, pdwChange,
    2042               LPVOID, pPrinterNotifyOptions,
    2043               LPPRINTER_NOTIFY_INFO *, ppPrinterNotifyInfo)
    2044 {
    2045   dprintf(("WINSPOOL: FindNextPrinterChangeNotification not implemented\n"));
    2046   return (FALSE);
    2047 }
    2048 
    2049 
    2050 /*****************************************************************************
    2051  * Name      : BOOL FreePrinterNotifyInfo
    2052  * Purpose   :
    2053  * Parameters: PPRINTER_NOTIFY_INFO pPrinterNotifyInfo  pointer to a PRINTER_NOTIFY_INFO buffer
    2054  * Variables :
    2055  * Result    :
    2056  * Remark    :
    2057  * Status    : UNTESTED STUB
    2058  *
    2059  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2060  *
    2061  * Author    : Markus Montkowski [09.07.98 14:43:02]
    2062  *****************************************************************************/
    2063 
    2064 ODINFUNCTION1(BOOL, FreePrinterNotifyInfo,
    2065               LPPRINTER_NOTIFY_INFO, pPrinterNotifyInfo)
    2066 {
    2067   dprintf(("WINSPOOL: FreePrinterNotifyInfo not implemented\n"));
    2068   return (FALSE);
    2069 }
    2070 
    2071 
    2072 /*****************************************************************************
    2073  * Name      : BOOL GetFormA
    2074  * Purpose   :
    2075  * Parameters: HANDLE hPrinter  handle of printer
    2076  *             LPSTR pFormName  address of form name
    2077  *             DWORD Level  structure level
    2078  *             LPBYTE pForm  address of structure array
    2079  *             DWORD cbBuf  count of bytes in array
    2080  *             LPDWORD pcbNeeded  addr. of variable with count of bytes retrieved (or required)
    2081  * Variables :
    2082  * Result    :
    2083  * Remark    :
    2084  * Status    : UNTESTED STUB
    2085  *
    2086  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2087  *
    2088  * Author    : Markus Montkowski [09.07.98 14:43:32]
    2089  *****************************************************************************/
    2090 
    2091 ODINFUNCTION6(BOOL, GetFormA,
    2092               HANDLE, hPrinter,
    2093               LPSTR, pFormName,
    2094               DWORD, Level,
    2095               LPBYTE, pForm,
    2096               DWORD, cbBuf,
    2097               LPDWORD, pcbNeeded)
    2098 {
    2099   dprintf(("WINSPOOL: GetFormA not implemented\n"));
    2100   return (FALSE);
    2101 }
    2102 
    2103 
    2104 /*****************************************************************************
    2105  * Name      : BOOL GetFormW
    2106  * Purpose   :
    2107  * Parameters: HANDLE hPrinter  handle of printer
    2108  *             LPWSTR pFormName  address of form name
    2109  *             DWORD Level  structure level
    2110  *             LPBYTE pForm  address of structure array
    2111  *             DWORD cbBuf  count of bytes in array
    2112  *             LPDWORD pcbNeeded  addr. of variable with count of bytes retrieved (or required)
    2113  * Variables :
    2114  * Result    :
    2115  * Remark    :
    2116  * Status    : UNTESTED STUB
    2117  *
    2118  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2119  *
    2120  * Author    : Markus Montkowski [09.07.98 14:43:32]
    2121  *****************************************************************************/
    2122 
    2123 ODINFUNCTION6(BOOL, GetFormW,
    2124               HANDLE, hPrinter,
    2125               LPWSTR, pFormName,
    2126               DWORD, Level,
    2127               LPBYTE, pForm,
    2128               DWORD, cbBuf,
    2129               LPDWORD, pcbNeeded)
    2130 {
    2131   dprintf(("WINSPOOL: GetFormW not implemented\n"));
    2132   return (FALSE);
    2133 }
    2134 
    2135 
    2136 /*****************************************************************************
    2137  * Name      : BOOL GetJobA
    2138  * Purpose   :
    2139  * Parameters: HANDLE hPrinter  handle of printer
    2140  *             DWORD JobId  job identifier value
    2141  *             DWORD Level  data-structure level
    2142  *             LPBYTE pJob  address of data-structure array
    2143  *             DWORD cbBuf  count of bytes in array
    2144  *             LPDWORD pcbNeeded  address of value that contains count of bytes retrieved (or required)
    2145  * Variables :
    2146  * Result    :
    2147  * Remark    :
    2148  * Status    : UNTESTED STUB
    2149  *
    2150  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2151  *
    2152  * Author    : Markus Montkowski [09.07.98 14:43:50]
    2153  *****************************************************************************/
    2154 
    2155 ODINFUNCTION6(BOOL, GetJobA,
    2156               HANDLE, hPrinter,
    2157               DWORD, JobId,
    2158               DWORD, Level,
    2159               LPBYTE, pJob,
    2160               DWORD, cbBuf,
    2161               LPDWORD, pcbNeeded)
    2162 {
    2163   dprintf(("WINSPOOL: GetJobA not implemented\n"));
    2164   return (FALSE);
    2165 }
    2166 
    2167 
    2168 /*****************************************************************************
    2169  * Name      : BOOL GetJobW
    2170  * Purpose   :
    2171  * Parameters: HANDLE hPrinter  handle of printer
    2172  *             DWORD JobId  job identifier value
    2173  *             DWORD Level  data-structure level
    2174  *             LPBYTE pJob  address of data-structure array
    2175  *             DWORD cbBuf  count of bytes in array
    2176  *             LPDWORD pcbNeeded  address of value that contains count of bytes retrieved (or required)
    2177  * Variables :
    2178  * Result    :
    2179  * Remark    :
    2180  * Status    : UNTESTED STUB
    2181  *
    2182  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2183  *
    2184  * Author    : Markus Montkowski [09.07.98 14:43:50]
    2185  *****************************************************************************/
    2186 
    2187 ODINFUNCTION6(BOOL, GetJobW,
    2188               HANDLE, hPrinter,
    2189               DWORD, JobId,
    2190               DWORD, Level,
    2191               LPBYTE, pJob,
    2192               DWORD, cbBuf,
    2193               LPDWORD, pcbNeeded)
    2194 {
    2195   dprintf(("WINSPOOL: GetJobW not implemented\n"));
    2196   return (FALSE);
    2197 }
    2198 
    2199 
    2200 /*****************************************************************************
    2201  * Name      : BOOL GetPrintProcessorDirectoryA
    2202  * Purpose   :
    2203  * Parameters: LPSTR pName  address of server name
    2204  *             LPSTR pEnvironment  address of environment
    2205  *             DWORD Level  structure level
    2206  *             LPBYTE pPrintProcessorInfo  address of structure array
    2207  *             DWORD cbBuf  size, in bytes, of array
    2208  *             LPDWORD pcbNeeded  address of variable with number of bytes retrieved (or required)
    2209  * Variables :
    2210  * Result    :
    2211  * Remark    :
    2212  * Status    : UNTESTED STUB
    2213  *
    2214  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2215  *
    2216  * Author    : Markus Montkowski [09.07.98 14:45:14]
    2217  *****************************************************************************/
    2218 
    2219 ODINFUNCTION6(BOOL, GetPrintProcessorDirectoryA,
    2220               LPSTR, pName,
    2221               LPSTR, pEnvironment,
    2222               DWORD, Level,
    2223               LPBYTE, pPrintProcessorInfo,
    2224               DWORD, cbBuf,
    2225               LPDWORD, pcbNeeded)
    2226 {
    2227   dprintf(("WINSPOOL: GetPrintProcessorDirectoryA not implemented\n"));
    2228   return (FALSE);
    2229 }
    2230 
    2231 
    2232 /*****************************************************************************
    2233  * Name      : BOOL GetPrintProcessorDirectoryW
    2234  * Purpose   :
    2235  * Parameters: LPWSTR pName  address of server name
    2236  *             LPWSTR pEnvironment  address of environment
    2237  *             DWORD Level  structure level
    2238  *             LPBYTE pPrintProcessorInfo  address of structure array
    2239  *             DWORD cbBuf  size, in bytes, of array
    2240  *             LPDWORD pcbNeeded  address of variable with number of bytes retrieved (or required)
    2241  * Variables :
    2242  * Result    :
    2243  * Remark    :
    2244  * Status    : UNTESTED STUB
    2245  *
    2246  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2247  *
    2248  * Author    : Markus Montkowski [09.07.98 14:45:14]
    2249  *****************************************************************************/
    2250 
    2251 ODINFUNCTION6(BOOL, GetPrintProcessorDirectoryW,
    2252               LPWSTR, pName,
    2253               LPWSTR, pEnvironment,
    2254               DWORD, Level,
    2255               LPBYTE, pPrintProcessorInfo,
    2256               DWORD, cbBuf,
    2257               LPDWORD, pcbNeeded)
    2258 {
    2259   dprintf(("WINSPOOL: GetPrintProcessorDirectoryW not implemented\n"));
    2260   return (FALSE);
    2261 }
     2357
     2358
     2359/******************************************************************
     2360 *              EnumPrintersW        [WINSPOOL.@]
     2361 *
     2362 *    Enumerates the available printers, print servers and print
     2363 *    providers, depending on the specified flags, name and level.
     2364 *
     2365 * RETURNS:
     2366 *
     2367 *    If level is set to 1:
     2368 *      Not implemented yet!
     2369 *      Returns TRUE with an empty list.
     2370 *
     2371 *    If level is set to 2:
     2372 *              Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
     2373 *      Returns an array of PRINTER_INFO_2 data structures in the
     2374 *      lpbPrinters buffer. Note that according to MSDN also an
     2375 *      OpenPrinter should be performed on every remote printer.
     2376 *
     2377 *    If level is set to 4 (officially WinNT only):
     2378 *              Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
     2379 *      Fast: Only the registry is queried to retrieve printer names,
     2380 *      no connection to the driver is made.
     2381 *      Returns an array of PRINTER_INFO_4 data structures in the
     2382 *      lpbPrinters buffer.
     2383 *
     2384 *    If level is set to 5 (officially WinNT4/Win9x only):
     2385 *      Fast: Only the registry is queried to retrieve printer names,
     2386 *      no connection to the driver is made.
     2387 *      Returns an array of PRINTER_INFO_5 data structures in the
     2388 *      lpbPrinters buffer.
     2389 *
     2390 *    If level set to 3 or 6+:
     2391 *          returns zero (failure!)
     2392 *
     2393 *    Returns nonzero (TRUE) on success, or zero on failure, use GetLastError
     2394 *    for information.
     2395 *
     2396 * BUGS:
     2397 *    - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
     2398 *    - Only levels 2, 4 and 5 are implemented at the moment.
     2399 *    - 16-bit printer drivers are not enumerated.
     2400 *    - Returned amount of bytes used/needed does not match the real Windoze
     2401 *      implementation (as in this implementation, all strings are part
     2402 *      of the buffer, whereas Win32 keeps them somewhere else)
     2403 *    - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
     2404 *
     2405 * NOTE:
     2406 *    - In a regular Wine installation, no registry settings for printers
     2407 *      exist, which makes this function return an empty list.
     2408 */
     2409BOOL  WINAPI EnumPrintersW(
     2410                DWORD dwType,        /* [in] Types of print objects to enumerate */
     2411                LPWSTR lpszName,     /* [in] name of objects to enumerate */
     2412                DWORD dwLevel,       /* [in] type of printer info structure */
     2413                LPBYTE lpbPrinters,  /* [out] buffer which receives info */
     2414                DWORD cbBuf,         /* [in] max size of buffer in bytes */
     2415                LPDWORD lpdwNeeded,  /* [out] pointer to var: # bytes used/needed */
     2416                LPDWORD lpdwReturned /* [out] number of entries returned */
     2417                )
     2418{
     2419    return WINSPOOL_EnumPrinters(dwType, lpszName, dwLevel, lpbPrinters, cbBuf,
     2420                                 lpdwNeeded, lpdwReturned, TRUE);
     2421}
     2422
     2423
    22622424
    22632425
     
    22802442 *****************************************************************************/
    22812443
    2282 ODINFUNCTION5(BOOL, GetPrinterA,
    2283               HANDLE, hPrinter,
    2284               DWORD, Level,
    2285               LPBYTE, pPrinter,
    2286               DWORD, cbBuf,
    2287               LPDWORD, pcbNeeded)
    2288 {
    2289   dprintf(("WINSPOOL: GetPrinterA not implemented\n"));
    2290   return (FALSE);
     2444BOOL WIN32API GetPrinterA(
     2445              HANDLE hPrinter,
     2446              DWORD Level,
     2447              LPBYTE pPrinter,
     2448              DWORD cbBuf,
     2449              LPDWORD pcbNeeded)
     2450{
     2451    return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
     2452                               FALSE);
    22912453}
    22922454
     
    23102472 *****************************************************************************/
    23112473
    2312 ODINFUNCTION5(BOOL, GetPrinterW,
    2313               HANDLE, hPrinter,
    2314               DWORD, Level,
    2315               LPBYTE, pPrinter,
    2316               DWORD, cbBuf,
    2317               LPDWORD, pcbNeeded)
     2474BOOL WIN32API GetPrinterW(
     2475              HANDLE hPrinter,
     2476              DWORD Level,
     2477              LPBYTE pPrinter,
     2478              DWORD cbBuf,
     2479              LPDWORD pcbNeeded)
    23182480{
    23192481  dprintf(("WINSPOOL: GetPrinterW not implemented\n"));
     
    23212483}
    23222484
    2323 
    2324 /*****************************************************************************
    2325  * Name      : DWORD GetPrinterDataA
    2326  * Purpose   :
    2327  * Parameters: HANDLE hPrinter  handle of printer object
    2328  *             LPSTR pValueName  address of data type
    2329  *             LPDWORD pType  reserved
    2330  *             LPBYTE pData  address of array of bytes that receives data
    2331  *             DWORD nSize  size, in bytes, of array
    2332  *             LPDWORD pcbNeeded  address of variable with number of bytes retrieved (or required)
    2333  * Variables :
    2334  * Result    :
    2335  * Remark    :
    2336  * Status    : UNTESTED STUB
    2337  *
    2338  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2339  *
    2340  * Author    : Markus Montkowski [09.07.98 14:46:35]
    2341  *****************************************************************************/
    2342 
    2343 ODINFUNCTION6(DWORD, GetPrinterDataA,
    2344               HANDLE, hPrinter,
    2345               LPSTR, pValueName,
    2346               LPDWORD, pType,
    2347               LPBYTE, pData,
    2348               DWORD, nSize,
    2349               LPDWORD, pcbNeeded)
    2350 {
    2351   dprintf(("WINSPOOL: GetPrinterDataA not implemented\n"));
    2352   return (0);
    2353 }
    2354 
    2355 
    2356 /*****************************************************************************
    2357  * Name      : DWORD GetPrinterDataW
    2358  * Purpose   :
    2359  * Parameters: HANDLE hPrinter  handle of printer object
    2360  *             LPWSTR pValueName  address of data type
    2361  *             LPDWORD pType  reserved
    2362  *             LPBYTE pData  address of array of bytes that receives data
    2363  *             DWORD nSize  size, in bytes, of array
    2364  *             LPDWORD pcbNeeded  address of variable with number of bytes retrieved (or required)
    2365  * Variables :
    2366  * Result    :
    2367  * Remark    :
    2368  * Status    : UNTESTED STUB
    2369  *
    2370  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2371  *
    2372  * Author    : Markus Montkowski [09.07.98 14:46:35]
    2373  *****************************************************************************/
    2374 
    2375 ODINFUNCTION6(DWORD, GetPrinterDataW,
    2376               HANDLE, hPrinter,
    2377               LPWSTR, pValueName,
    2378               LPDWORD, pType,
    2379               LPBYTE, pData,
    2380               DWORD, nSize,
    2381               LPDWORD, pcbNeeded)
    2382 {
    2383   dprintf(("WINSPOOL: GetPrinterDataW not implemented\n"));
    2384   return (0);
    2385 }
    23862485
    23872486
     
    24052504 *****************************************************************************/
    24062505
    2407 ODINFUNCTION6(BOOL, GetPrinterDriverA,
    2408               HANDLE, hPrinter,
    2409               LPSTR, pEnvironment,
    2410               DWORD, Level,
    2411               LPBYTE, pDriverInfo,
    2412               DWORD, cbBuf,
    2413               LPDWORD, pcbNeeded)
    2414 {
    2415   dprintf(("WINSPOOL: GetPrinterDriverA not implemented\n"));
    2416   return (FALSE);
     2506BOOL WIN32API GetPrinterDriverA(
     2507              HANDLE hPrinter,
     2508              LPSTR pEnvironment,
     2509              DWORD Level,
     2510              LPBYTE pDriverInfo,
     2511              DWORD cbBuf,
     2512              LPDWORD pcbNeeded)
     2513{
     2514    BOOL ret;
     2515    LPWSTR pEnvW = HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment);
     2516    ret = WINSPOOL_GetPrinterDriver(hPrinter, pEnvW, Level, pDriverInfo,
     2517                                    cbBuf, pcbNeeded, FALSE);
     2518    HeapFree(GetProcessHeap(),0,pEnvW);
     2519    return ret;
    24172520}
    24182521
     
    24372540 *****************************************************************************/
    24382541
    2439 ODINFUNCTION6(BOOL, GetPrinterDriverW,
    2440               HANDLE, hPrinter,
    2441               LPWSTR, pEnvironment,
    2442               DWORD, Level,
    2443               LPBYTE, pDriverInfo,
    2444               DWORD, cbBuf,
    2445               LPDWORD, pcbNeeded)
     2542BOOL WIN32API GetPrinterDriverW(
     2543              HANDLE hPrinter,
     2544              LPWSTR pEnvironment,
     2545              DWORD Level,
     2546              LPBYTE pDriverInfo,
     2547              DWORD cbBuf,
     2548              LPDWORD pcbNeeded)
    24462549{
    24472550  dprintf(("WINSPOOL: GetPrinterDriverW not implemented\n"));
     
    24692572 *****************************************************************************/
    24702573
    2471 ODINFUNCTION6(BOOL, GetPrinterDriverDirectoryA,
    2472               LPSTR, pName,
    2473               LPSTR, pEnvironment,
    2474               DWORD, Level,
    2475               LPBYTE, pDriverDirectory,
    2476               DWORD, cbBuf,
    2477               LPDWORD, pcbNeeded)
    2478 {
    2479   dprintf(("WINSPOOL: GetPrinterDriverDirectoryA not implemented\n"));
    2480   return (FALSE);
     2574BOOL WIN32API GetPrinterDriverDirectoryA(
     2575              LPSTR pName,
     2576              LPSTR pEnvironment,
     2577              DWORD Level,
     2578              LPBYTE pDriverDirectory,
     2579              DWORD cbBuf,
     2580              LPDWORD pcbNeeded)
     2581{
     2582    DWORD needed;
     2583
     2584    TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
     2585          pDriverDirectory, cbBuf, pcbNeeded);
     2586    if(pName != NULL) {
     2587        FIXME("pName = `%s' - unsupported\n", pName);
     2588        SetLastError(ERROR_INVALID_PARAMETER);
     2589        return FALSE;
     2590    }
     2591    if(pEnvironment != NULL) {
     2592        FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
     2593        SetLastError(ERROR_INVALID_ENVIRONMENT);
     2594        return FALSE;
     2595    }
     2596    if(Level != 1)  /* win95 ignores this so we just carry on */
     2597        WARN("Level = %ld - assuming 1\n", Level);
     2598
     2599    /* FIXME should read from registry */
     2600    needed = GetSystemDirectoryA((LPSTR)pDriverDirectory, cbBuf);
     2601    needed++;
     2602    if(pcbNeeded)
     2603        *pcbNeeded = needed;
     2604    if(needed > cbBuf) {
     2605        SetLastError(ERROR_INSUFFICIENT_BUFFER);
     2606        return FALSE;
     2607    }
     2608    return TRUE;
     2609
    24812610}
    24822611
     
    25012630 *****************************************************************************/
    25022631
    2503 ODINFUNCTION6(BOOL, GetPrinterDriverDirectoryW,
    2504               LPWSTR, pName,
    2505               LPWSTR, pEnvironment,
    2506               DWORD, Level,
    2507               LPBYTE, pDriverDirectory,
    2508               DWORD, cbBuf,
    2509               LPDWORD, pcbNeeded)
     2632BOOL WIN32API GetPrinterDriverDirectoryW(
     2633              LPWSTR pName,
     2634              LPWSTR pEnvironment,
     2635              DWORD Level,
     2636              LPBYTE pDriverDirectory,
     2637              DWORD cbBuf,
     2638              LPDWORD pcbNeeded)
    25102639{
    25112640  dprintf(("WINSPOOL: GetPrinterDriverDirectoryW not implemented\n"));
     
    25132642}
    25142643
    2515 
    2516 
    2517 /*****************************************************************************
    2518  * Name      : BOOL OpenPrinterW
    2519  * Purpose   :
    2520  * Parameters: LPWSTR pPrinterName  pointer to printer or server name
    2521  *             HANDLE * phPrinter  pointer to printer or server handle
    2522  *             PRINTER_DEFAULTSW * pDefault  pointer to printer defaults structure
    2523  * Variables :
    2524  * Result    :
    2525  * Remark    :
    2526  * Status    : UNTESTED STUB
    2527  *
    2528  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2529  *
    2530  * Author    : Markus Montkowski [09.07.98 14:48:19]
    2531  *****************************************************************************/
    2532 
    2533 ODINFUNCTION3(BOOL, OpenPrinterW,
    2534               LPWSTR, pPrinterName,
    2535               HANDLE *, phPrinter,
    2536               PRINTER_DEFAULTSW *, pDefault)
    2537 {
    2538   dprintf(("WINSPOOL: OpenPrinterW not implemented\n"));
    2539   return (FALSE);
    2540 }
    2541 
    2542 
    2543 /*****************************************************************************
    2544  * Name      : HPRINTER PrinterMessageBoxA
    2545  * Purpose   :
    2546  * Parameters: HANDLE hPrinter  handle of printer
    2547  *             DWORD Error  error identifier
    2548  *             HWND hWnd  handle of owner window
    2549  *             LPSTR pText  pointer to message box text
    2550  *             LPSTR pCaption  pointer to message box title
    2551  *             DWORD dwType  style of message box
    2552  * Variables :
    2553  * Result    :
    2554  * Remark    :
    2555  * Status    : UNTESTED STUB
    2556  *
    2557  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2558  *
    2559  * Author    : Markus Montkowski [09.07.98 14:50:13]
    2560  *****************************************************************************/
    2561 
    2562 ODINFUNCTION6(HPRINTER, PrinterMessageBoxA,
    2563               HANDLE, hPrinter,
    2564               DWORD, Error,
    2565               HWND, hWnd,
    2566               LPSTR, pText,
    2567               LPSTR, pCaption,
    2568               DWORD, dwType)
    2569 {
    2570   dprintf(("WINSPOOL: PrinterMessageBoxA not implemented\n"));
    2571   return (0);
    2572 }
    2573 
    2574 
    2575 /*****************************************************************************
    2576  * Name      : HPRINTER PrinterMessageBoxW
    2577  * Purpose   :
    2578  * Parameters: HANDLE hPrinter  handle of printer
    2579  *             DWORD Error  error identifier
    2580  *             HWND hWnd  handle of owner window
    2581  *             LPWSTR pText  pointer to message box text
    2582  *             LPWSTR pCaption  pointer to message box title
    2583  *             DWORD dwType  style of message box
    2584  * Variables :
    2585  * Result    :
    2586  * Remark    :
    2587  * Status    : UNTESTED STUB
    2588  *
    2589  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2590  *
    2591  * Author    : Markus Montkowski [09.07.98 14:50:13]
    2592  *****************************************************************************/
    2593 
    2594 ODINFUNCTION6(HPRINTER, PrinterMessageBoxW,
    2595               HANDLE, hPrinter,
    2596               DWORD, Error,
    2597               HWND, hWnd,
    2598               LPWSTR, pText,
    2599               LPWSTR, pCaption,
    2600               DWORD, dwType)
    2601 {
    2602   dprintf(("WINSPOOL: PrinterMessageBoxW not implemented\n"));
    2603   return (0);
    2604 }
    2605 
    2606 
    2607 /*****************************************************************************
    2608  * Name      : BOOL PrinterProperties
    2609  * Purpose   :
    2610  * Parameters: HWND hWnd  handle of parent window
    2611  *             HANDLE hPrinter  handle of printer object
    2612  * Variables :
    2613  * Result    :
    2614  * Remark    :
    2615  * Status    : UNTESTED STUB
    2616  *
    2617  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2618  *
    2619  * Author    : Markus Montkowski [09.07.98 14:50:49]
    2620  *****************************************************************************/
    2621 
    2622 ODINFUNCTION2(BOOL, PrinterProperties,
    2623               HWND, hWnd,
    2624               HANDLE, hPrinter)
    2625 {
    2626   dprintf(("WINSPOOL: PrinterProperties not implemented\n"));
    2627   return (FALSE);
    2628 }
    2629 
    2630 
    2631 /*****************************************************************************
    2632  * Name      : BOOL ReadPrinter
    2633  * Purpose   :
    2634  * Parameters: HANDLE hPrinter  handle of printer object
    2635  *             LPVOID pBuf  address of array of bytes that receives data
    2636  *             DWORD cbBuf  size, in bytes, of array
    2637  *             LPDWORD pNoBytesRead  address of variable with number of bytes retrieved
    2638  * Variables :
    2639  * Result    :
    2640  * Remark    :
    2641  * Status    : UNTESTED STUB
    2642  *
    2643  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2644  *
    2645  * Author    : Markus Montkowski [09.07.98 14:51:17]
    2646  *****************************************************************************/
    2647 ODINFUNCTION4(BOOL, ReadPrinter,
    2648               HANDLE, hPrinter,
    2649               LPVOID, pBuf,
    2650               DWORD, cbBuf,
    2651               LPDWORD, pNoBytesRead)
    2652 {
    2653   dprintf(("WINSPOOL: ReadPrinter not implemented\n"));
    2654   return (FALSE);
    2655 }
    2656 
    2657 
    2658 /*****************************************************************************
    2659  * Name      : BOOL ResetPrinterA
    2660  * Purpose   :
    2661  * Parameters: HANDLE hPrinter  printer handle
    2662  *             PRINTER_DEFAULTSA * pDefault  address of printer defaults structure
    2663  * Variables :
    2664  * Result    :
    2665  * Remark    :
    2666  * Status    : UNTESTED STUB
    2667  *
    2668  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2669  *
    2670  * Author    : Markus Montkowski [09.07.98 14:51:52]
    2671  *****************************************************************************/
    2672 
    2673 ODINFUNCTION2(BOOL, ResetPrinterA,
    2674               HANDLE, hPrinter,
    2675               PRINTER_DEFAULTSA *, pDefault)
    2676 {
    2677   dprintf(("WINSPOOL: ResetPrinterA not implemented\n"));
    2678   return (FALSE);
    2679 }
    2680 
    2681 
    2682 /*****************************************************************************
    2683  * Name      : BOOL ResetPrinterW
    2684  * Purpose   :
    2685  * Parameters: HANDLE hPrinter  printer handle
    2686  *             PRINTER_DEFAULTSW * pDefault  address of printer defaults structure
    2687  * Variables :
    2688  * Result    :
    2689  * Remark    :
    2690  * Status    : UNTESTED STUB
    2691  *
    2692  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2693  *
    2694  * Author    : Markus Montkowski [09.07.98 14:51:52]
    2695  *****************************************************************************/
    2696 
    2697 ODINFUNCTION2(BOOL, ResetPrinterW,
    2698               HANDLE, hPrinter,
    2699               PRINTER_DEFAULTSW *, pDefault)
    2700 {
    2701   dprintf(("WINSPOOL: ResetPrinterW not implemented\n"));
    2702   return (FALSE);
    2703 }
    2704 
    2705 /*****************************************************************************
    2706  * Name      : BOOL ScheduleJob
    2707  * Purpose   :
    2708  * Parameters: HANDLE hPrinter  specifies printer for the print job
    2709  *             DWORD dwJobID  print job identifier
    2710  * Variables :
    2711  * Result    :
    2712  * Remark    :
    2713  * Status    : UNTESTED STUB
    2714  *
    2715  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2716  *
    2717  * Author    : Markus Montkowski [09.07.98 14:52:39]
    2718  *****************************************************************************/
    2719 
    2720 ODINFUNCTION2(BOOL, ScheduleJob,
    2721               HANDLE, hPrinter,
    2722               DWORD, dwJobID)
    2723 {
    2724   dprintf(("WINSPOOL: ScheduleJob not implemented\n"));
    2725   return (FALSE);
    2726 }
    2727 
    2728 
    2729 /*****************************************************************************
    2730  * Name      : BOOL SetFormA
    2731  * Purpose   :
    2732  * Parameters: HANDLE hPrinter  handle of printer object
    2733  *             LPSTR pFormName  address of form name
    2734  *             DWORD Level  structure level
    2735  *             LPBYTE pForm  address of structure array
    2736  * Variables :
    2737  * Result    :
    2738  * Remark    :
    2739  * Status    : UNTESTED STUB
    2740  *
    2741  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2742  *
    2743  * Author    : Markus Montkowski [09.07.98 14:53:20]
    2744  *****************************************************************************/
    2745 
    2746 ODINFUNCTION4(BOOL, SetFormA,
    2747               HANDLE, hPrinter,
    2748               LPSTR, pFormName,
    2749               DWORD, Level,
    2750               LPBYTE, pForm)
    2751 {
    2752   dprintf(("WINSPOOL: SetFormA not implemented\n"));
    2753   return (FALSE);
    2754 }
    2755 
    2756 
    2757 /*****************************************************************************
    2758  * Name      : BOOL SetFormW
    2759  * Purpose   :
    2760  * Parameters: HANDLE hPrinter  handle of printer object
    2761  *             LPWSTR pFormName  address of form name
    2762  *             DWORD Level  structure level
    2763  *             LPBYTE pForm  address of structure array
    2764  * Variables :
    2765  * Result    :
    2766  * Remark    :
    2767  * Status    : UNTESTED STUB
    2768  *
    2769  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2770  *
    2771  * Author    : Markus Montkowski [09.07.98 14:53:20]
    2772  *****************************************************************************/
    2773 
    2774 ODINFUNCTION4(BOOL, SetFormW,
    2775               HANDLE, hPrinter,
    2776               LPWSTR, pFormName,
    2777               DWORD, Level,
    2778               LPBYTE, pForm)
    2779 {
    2780   dprintf(("WINSPOOL: SetFormW not implemented\n"));
    2781   return (FALSE);
    2782 }
    2783 
    2784 
    2785 /*****************************************************************************
    2786  * Name      : BOOL SetJobA
    2787  * Purpose   :
    2788  * Parameters: HANDLE hPrinter  handle to printer object
    2789  *             DWORD JobId  print job identifier
    2790  *             DWORD Level  specifies type of job information structure
    2791  *             LPBYTE  pJob  pointer to job information structure
    2792  *             DWORD Command  job command value
    2793  * Variables :
    2794  * Result    :
    2795  * Remark    :
    2796  * Status    : UNTESTED STUB
    2797  *
    2798  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2799  *
    2800  * Author    : Markus Montkowski [09.07.98 14:53:47]
    2801  *****************************************************************************/
    2802 
    2803 ODINFUNCTION5(BOOL, SetJobA,
    2804               HANDLE, hPrinter,
    2805               DWORD, JobId,
    2806               DWORD, Level,
    2807               LPBYTE, pJob,
    2808               DWORD, Command)
    2809 {
    2810   dprintf(("WINSPOOL: SetJobA not implemented\n"));
    2811   return (FALSE);
    2812 }
    2813 
    2814 
    2815 /*****************************************************************************
    2816  * Name      : BOOL SetJobW
    2817  * Purpose   :
    2818  * Parameters: HANDLE hPrinter  handle to printer object
    2819  *             DWORD JobId  print job identifier
    2820  *             DWORD Level  specifies type of job information structure
    2821  *             LPBYTE  pJob  pointer to job information structure
    2822  *             DWORD Command  job command value
    2823  * Variables :
    2824  * Result    :
    2825  * Remark    :
    2826  * Status    : UNTESTED STUB
    2827  *
    2828  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2829  *
    2830  * Author    : Markus Montkowski [09.07.98 14:53:47]
    2831  *****************************************************************************/
    2832 
    2833 ODINFUNCTION5(BOOL, SetJobW,
    2834               HANDLE, hPrinter,
    2835               DWORD, JobId,
    2836               DWORD, Level,
    2837               LPBYTE, pJob,
    2838               DWORD, Command)
    2839 {
    2840   dprintf(("WINSPOOL: SetJobW not implemented\n"));
    2841   return (FALSE);
    2842 }
    2843 
    2844 /*****************************************************************************
    2845  * Name      : BOOL SetPrinterA
    2846  * Purpose   :
    2847  * Parameters: HANDLE hPrinter  handle of printer object
    2848  *             DWORD Level  structure level
    2849  *             LPBYTE pPrinter  address of array containing printer data
    2850  *             DWORD Command  printer-state command
    2851  * Variables :
    2852  * Result    :
    2853  * Remark    :
    2854  * Status    : UNTESTED STUB
    2855  *
    2856  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2857  *
    2858  * Author    : Markus Montkowski [09.07.98 14:55:03]
    2859  *****************************************************************************/
    2860 
    2861 ODINFUNCTION4(BOOL, SetPrinterA,
    2862               HANDLE, hPrinter,
    2863               DWORD, Level,
    2864               LPBYTE, pPrinter,
    2865               DWORD, Command)
    2866 {
    2867   dprintf(("WINSPOOL: SetPrinterA not implemented\n"));
    2868   return (FALSE);
    2869 }
    2870 
    2871 
    2872 /*****************************************************************************
    2873  * Name      : BOOL SetPrinterW
    2874  * Purpose   :
    2875  * Parameters: HANDLE hPrinter  handle of printer object
    2876  *             DWORD Level  structure level
    2877  *             LPBYTE pPrinter  address of array containing printer data
    2878  *             DWORD Command  printer-state command
    2879  * Variables :
    2880  * Result    :
    2881  * Remark    :
    2882  * Status    : UNTESTED STUB
    2883  *
    2884  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2885  *
    2886  * Author    : Markus Montkowski [09.07.98 14:55:03]
    2887  *****************************************************************************/
    2888 
    2889 ODINFUNCTION4(BOOL, SetPrinterW,
    2890               HANDLE, hPrinter,
    2891               DWORD, Level,
    2892               LPBYTE, pPrinter,
    2893               DWORD, Command)
    2894 {
    2895   dprintf(("WINSPOOL: SetPrinterW not implemented\n"));
    2896   return (FALSE);
    2897 }
    2898 
    2899 
    2900 /*****************************************************************************
    2901  * Name      : DWORD SetPrinterDataA
    2902  * Purpose   :
    2903  * Parameters: HANDLE hPrinter  handle of printer object
    2904  *             LPSTR pValueName  address of data type
    2905  *             DWORD Type  flag for value type
    2906  *             LPBYTE pData  address of array that specifies printer data
    2907  *             DWORD cbData  size, in bytes, of array
    2908  * Variables :
    2909  * Result    :
    2910  * Remark    :
    2911  * Status    : UNTESTED STUB
    2912  *
    2913  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2914  *
    2915  * Author    : Markus Montkowski [09.07.98 14:55:52]
    2916  *****************************************************************************/
    2917 
    2918 ODINFUNCTION5(DWORD, SetPrinterDataA,
    2919               HANDLE, hPrinter,
    2920               LPSTR, pValueName,
    2921               DWORD, Type,
    2922               LPBYTE, pData,
    2923               DWORD, cbData)
    2924 {
    2925   dprintf(("WINSPOOL: SetPrinterDataA not implemented\n"));
    2926   return (0);
    2927 }
    2928 
    2929 
    2930 /*****************************************************************************
    2931  * Name      : DWORD SetPrinterDataW
    2932  * Purpose   :
    2933  * Parameters: HANDLE hPrinter  handle of printer object
    2934  *             LPWSTR pValueName  address of data type
    2935  *             DWORD Type  flag for value type
    2936  *             LPBYTE pData  address of array that specifies printer data
    2937  *             DWORD cbData  size, in bytes, of array
    2938  * Variables :
    2939  * Result    :
    2940  * Remark    :
    2941  * Status    : UNTESTED STUB
    2942  *
    2943  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2944  *
    2945  * Author    : Markus Montkowski [09.07.98 14:55:52]
    2946  *****************************************************************************/
    2947 
    2948 ODINFUNCTION5(DWORD, SetPrinterDataW,
    2949               HANDLE, hPrinter,
    2950               LPWSTR, pValueName,
    2951               DWORD, Type,
    2952               LPBYTE, pData,
    2953               DWORD, cbData)
    2954 {
    2955   dprintf(("WINSPOOL: SetPrinterDataW not implemented\n"));
    2956   return (0);
    2957 }
    2958 
    2959 
    2960 /*****************************************************************************
    2961  * Name      : DWORD StartDocPrinterA
    2962  * Purpose   :
    2963  * Parameters: HANDLE hPrinter  handle of printer object
    2964  *             DWORD Level  structure level
    2965  *             LPBYTE pDocInfo  address of structure
    2966  * Variables :
    2967  * Result    :
    2968  * Remark    :
    2969  * Status    : UNTESTED STUB
    2970  *
    2971  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2972  *
    2973  * Author    : Markus Montkowski [09.07.98 14:56:45]
    2974  *****************************************************************************/
    2975 
    2976 ODINFUNCTION3(DWORD, StartDocPrinterA,
    2977               HANDLE, hPrinter,
    2978               DWORD, Level,
    2979               LPBYTE, pDocInfo)
    2980 {
    2981   dprintf(("WINSPOOL: StartDocPrinterA not implemented\n"));
    2982   return (0);
    2983 }
    2984 
    2985 
    2986 /*****************************************************************************
    2987  * Name      : DWORD StartDocPrinterW
    2988  * Purpose   :
    2989  * Parameters: HANDLE hPrinter  handle of printer object
    2990  *             DWORD Level  structure level
    2991  *             LPBYTE pDocInfo  address of structure
    2992  * Variables :
    2993  * Result    :
    2994  * Remark    :
    2995  * Status    : UNTESTED STUB
    2996  *
    2997  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    2998  *
    2999  * Author    : Markus Montkowski [09.07.98 14:56:45]
    3000  *****************************************************************************/
    3001 
    3002 ODINFUNCTION3(DWORD, StartDocPrinterW,
    3003               HANDLE, hPrinter,
    3004               DWORD, Level,
    3005               LPBYTE, pDocInfo)
    3006 {
    3007   dprintf(("WINSPOOL: StartDocPrinterW not implemented\n"));
    3008   return (0);
    3009 }
    3010 
    3011 /*****************************************************************************
    3012  * Name      : BOOL StartPagePrinter
    3013  * Purpose   :
    3014  * Parameters: HANDLE hPrinter  handle of printer object
    3015  * Variables :
    3016  * Result    :
    3017  * Remark    :
    3018  * Status    : UNTESTED STUB
    3019  *
    3020  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    3021  *
    3022  * Author    : Markus Montkowski [09.07.98 14:57:38]
    3023  *****************************************************************************/
    3024 
    3025 ODINFUNCTION1(BOOL, StartPagePrinter,
    3026               HANDLE, hPrinter)
    3027 {
    3028   dprintf(("WINSPOOL: StartPagePrinter not implemented\n"));
    3029   return (FALSE);
    3030 }
    3031 
    3032 
    3033 /*****************************************************************************
    3034  * Name      : BOOL WritePrinter
    3035  * Purpose   :
    3036  * Parameters: HANDLE hPrinter  handle to printer object
    3037  *             LPVOID pBuf  pointer to array that contains printer data
    3038  *             DWORD cbBuf  size, in bytes, of array
    3039  *             LPDWORD pcWritten  addr. of variable with count of bytes written
    3040  * Variables :
    3041  * Result    :
    3042  * Remark    :
    3043  * Status    : UNTESTED STUB
    3044  *
    3045  * Stub Generated through PE2LX Stubwizard 0.02 from Markus Montkowski
    3046  *
    3047  * Author    : Markus Montkowski [09.07.98 14:58:49]
    3048  *****************************************************************************/
    3049 
    3050 ODINFUNCTION4(BOOL, WritePrinter,
    3051               HANDLE, hPrinter,
    3052               LPVOID, pBuf,
    3053               DWORD, cbBuf,
    3054               LPDWORD, pcWritten)
    3055 {
    3056   dprintf(("WINSPOOL: WritePrinter not implemented\n"));
    3057   return (FALSE);
    3058 }
    3059 
    3060 
    3061 /*********************************************************************
    3062  *                  DeletePrinterDataA   (WINSPOOL.152)
    3063  */
    3064 ODINFUNCTION2(DWORD, DeletePrinterDataA,
    3065           HANDLE, hPrinter,
    3066           LPSTR, pValueName)
    3067 {
    3068   dprintf(("WINSPOOL: DeletePrinterDataA not implemented\n"));
    3069   return (FALSE);
    3070 }
    3071 
    3072 
    3073 /*********************************************************************
    3074  *                  DeletePrinterDataW   (WINSPOOL.153)
    3075  */
    3076 ODINFUNCTION2(DWORD, DeletePrinterDataW,
    3077           HANDLE, hPrinter,
    3078           LPWSTR, pValueName)
    3079 {
    3080   dprintf(("WINSPOOL: DeletePrinterDataW not implemented\n"));
    3081   return (FALSE);
    3082 }
     2644#ifndef __WIN32OS2__
     2645/******************************************************************
     2646 *  WINSPOOL_GetOpenedPrinterEntry
     2647 *  Get the first place empty in the opened printer table
     2648 */
     2649static HANDLE WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name )
     2650{
     2651    int i;
     2652
     2653    for (i = 0; i < nb_printers; i++) if (!printer_array[i]) break;
     2654
     2655    if (i >= nb_printers)
     2656    {
     2657        LPWSTR *new_array = (LPWSTR*)HeapReAlloc( GetProcessHeap(), 0, printer_array,
     2658                                         (nb_printers + 16) * sizeof(*new_array) );
     2659        if (!new_array) return 0;
     2660        printer_array = new_array;
     2661        nb_printers += 16;
     2662    }
     2663
     2664    if ((printer_array[i] = (WCHAR*)HeapAlloc( GetProcessHeap(), 0, (strlenW(name)+1)*sizeof(WCHAR) )) != NULL)
     2665    {
     2666        strcpyW( printer_array[i], name );
     2667        return (HANDLE)(i + 1);
     2668    }
     2669    return 0;
     2670}
     2671#endif
     2672
     2673/**
     2674 * Opens a printer.
     2675 *
     2676 * @returns Success indicator, last error set on failure.
     2677 * @param   lpPrinterName   Pointer to printer name.
     2678 * @param   phPrinter       Where to store the handle to the opned printer instance.
     2679 * @param   pDefault        Printer defaults. (Current ignored)
     2680 * @status  partially implemented.
     2681 * @author  ???
     2682 * @author  knut st. osmundsen <bird-srcspam@anduin.net>
     2683 */
     2684BOOL WIN32API OpenPrinterW(LPWSTR lpPrinterName, HANDLE *phPrinter, PRINTER_DEFAULTSW *pDefault)
     2685{
     2686    HKEY hkeyPrinters, hkeyPrinter;
     2687
     2688    /*
     2689     * Validate input.
     2690     */
     2691    if (!lpPrinterName)
     2692    {
     2693        dprintf(("WINSPOOL: OpenPrinterW:  printerName=NULL pDefault=%p returning false!\n", pDefault));
     2694        SetLastError(ERROR_INVALID_PARAMETER);
     2695        return FALSE;
     2696    }
     2697    dprintf(("WINSPOOL: OpenPrinterW: printerName='%ls' pDefault=%p\n", lpPrinterName, pDefault));
     2698
     2699    /*
     2700     * Check if the Printer exists.
     2701     */
     2702    if (RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) != ERROR_SUCCESS)
     2703    {
     2704        dprintf(("Can't create Printers key\n"));
     2705        SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
     2706        return FALSE;
     2707    }
     2708
     2709    if (    lpPrinterName[0] == '\0' /* explicitly fail on "" */
     2710        ||  RegOpenKeyW(hkeyPrinters, lpPrinterName, &hkeyPrinter) != ERROR_SUCCESS)
     2711    {
     2712        dprintf(("Can't find printer '%ls' in registry\n", lpPrinterName));
     2713        RegCloseKey(hkeyPrinters);
     2714        SetLastError(ERROR_INVALID_PRINTER_NAME);
     2715        return FALSE;
     2716    }
     2717    RegCloseKey(hkeyPrinter);
     2718    RegCloseKey(hkeyPrinters);
     2719
     2720    /*
     2721     * Seems like win95 doesn't care if there is no where to store
     2722     * the handle. We'll do the same.
     2723     */
     2724    if (!phPrinter) /* This seems to be what win95 does anyway */
     2725    {
     2726        dprintf(("WINSPOOL: OpenPrinterW: phPrinter is NULL, returning succesfully anyhow\n"));
     2727        return TRUE;
     2728    }
     2729
     2730    /*
     2731     * Create a handle for this open instance.
     2732     */
     2733    *phPrinter = NULL;                  /* crash here */
     2734#ifdef __WIN32OS2__
     2735    POPENPRINTER p = openprinterNew(lpPrinterName);
     2736    if (!p)
     2737    {
     2738        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
     2739        dprintf(("WINSPOOL: OpenPrinterW: out of memory allocating handle\n"));
     2740        return FALSE;
     2741    }
     2742    *phPrinter = p->hOpenPrinter;
     2743#else
     2744    *phPrinter = WINSPOOL_GetOpenedPrinterEntry( lpPrinterName );
     2745#endif
     2746
     2747    if (pDefault != NULL)
     2748        dprintf(("Not handling pDefault\n"));
     2749
     2750    dprintf(("WINSPOOL: OpenPrinterW: returning successfully *phPrinter=%d\n", *phPrinter));
     2751    return TRUE;
     2752}
     2753
     2754
    30832755
    30842756
     
    30862758 *                  DocumentPropertiesW   (WINSPOOL.166)
    30872759 */
    3088 ODINFUNCTION6(LONG, DocumentPropertiesW,
    3089           HWND,      hWnd,
    3090           HANDLE,    hPrinter,
    3091           LPWSTR,    pDeviceName,
    3092           PDEVMODEW, pDevModeOutput,
    3093           PDEVMODEW, pDevModeInput,
    3094           DWORD,     fMode)
    3095 {
    3096   dprintf(("WINSPOOL: DocumentPropertiesW not implemented\n"));
    3097   return (FALSE);
    3098 }
    3099 
    3100 
    3101 /*********************************************************************
    3102  *                  EnumPrinterDataA   (WINSPOOL.183)
    3103  */
    3104 ODINFUNCTION9(DWORD, EnumPrinterDataA,
    3105     HANDLE,   hPrinter,
    3106     DWORD,    dwIndex,
    3107     LPSTR,    pValueName,
    3108     DWORD,    cbValueName,
    3109     LPDWORD,  pcbValueName,
    3110     LPDWORD,  pType,
    3111     LPBYTE,   pData,
    3112     DWORD,    cbData,
    3113     LPDWORD,  pcbData)
    3114 {
    3115   dprintf(("WINSPOOL: EnumPrinterDataA not implemented\n"));
    3116   return (FALSE);
    3117 }
    3118 
    3119 
    3120 /*********************************************************************
    3121  *                  EnumPrinterDataW   (WINSPOOL.184)
    3122  */
    3123 ODINFUNCTION9(DWORD, EnumPrinterDataW,
    3124     HANDLE,   hPrinter,
    3125     DWORD,    dwIndex,
    3126     LPWSTR,   pValueName,
    3127     DWORD,    cbValueName,
    3128     LPDWORD,  pcbValueName,
    3129     LPDWORD,  pType,
    3130     LPBYTE,   pData,
    3131     DWORD,    cbData,
    3132     LPDWORD,  pcbData)
    3133 {
    3134   dprintf(("WINSPOOL: EnumPrinterDataW not implemented\n"));
    3135   return (FALSE);
    3136 }
    3137 
    3138 
    3139 /*********************************************************************
    3140  *                  SetPortA   (WINSPOOL.226)
    3141  */
    3142 ODINFUNCTION4(BOOL, SetPortA,
    3143     LPSTR,     pName,
    3144     LPSTR,     pPortName,
    3145     DWORD,     dwLevel,
    3146     LPBYTE,    pPortInfo)
    3147 {
    3148   dprintf(("WINSPOOL: SetPortA not implemented\n"));
    3149   return (FALSE);
    3150 }
    3151 
    3152 
    3153 /*********************************************************************
    3154  *                  SetPortW   (WINSPOOL.227)
    3155  */
    3156 ODINFUNCTION4(BOOL, SetPortW,
    3157     LPWSTR,     pName,
    3158     LPWSTR,     pPortName,
    3159     DWORD,      dwLevel,
    3160     LPBYTE,     pPortInfo)
    3161 {
    3162   dprintf(("WINSPOOL: SetPortW not implemented\n"));
    3163   return (FALSE);
    3164 }
     2760LONG WIN32API DocumentPropertiesW(
     2761          HWND      hWnd,
     2762          HANDLE    hPrinter,
     2763          LPWSTR    pDeviceName,
     2764          PDEVMODEW pDevModeOutput,
     2765          PDEVMODEW pDevModeInput,
     2766          DWORD     fMode)
     2767{
     2768    LPSTR pDeviceNameA = HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName);
     2769    LPDEVMODEA pDevModeInputA = DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput);
     2770    LPDEVMODEA pDevModeOutputA = NULL;
     2771    LONG ret;
     2772
     2773    TRACE("(%p,%p,%s,%p,%p,%ld)\n",
     2774          hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
     2775          fMode);
     2776    if(pDevModeOutput) {
     2777        ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, NULL, NULL, 0);
     2778        if(ret < 0) return ret;
     2779        pDevModeOutputA = (LPDEVMODEA)HeapAlloc(GetProcessHeap(), 0, ret);
     2780    }
     2781    ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, pDevModeOutputA,
     2782                              pDevModeInputA, fMode);
     2783    if(ret < 0) return ret;
     2784
     2785    if(pDevModeOutput) {
     2786        DEVMODEcpyAtoW(pDevModeOutput, pDevModeOutputA);
     2787        HeapFree(GetProcessHeap(),0,pDevModeOutputA);
     2788    }
     2789    if(fMode == 0 && ret > 0)
     2790        ret += (CCHDEVICENAME + CCHFORMNAME);
     2791    HeapFree(GetProcessHeap(),0,pDevModeInputA);
     2792    HeapFree(GetProcessHeap(),0,pDeviceNameA);
     2793    return ret;
     2794}
     2795
     2796
     2797
     2798#ifdef __WIN32OS2__
     2799
     2800/**
     2801 * Start a new printer job.
     2802 *
     2803 * @returns Print job identifier.
     2804 * @returns 0 on failure with last error set.
     2805 * @param   hPrinter    Handle to the printer object.
     2806 * @param   Level       Structure level.
     2807 * @param   pDocInfo    Pointer to structure.
     2808 * @status  partially implemented.
     2809 * @author  knut st. osmundsen <bird-srcspam@anduin.net>
     2810 */
     2811DWORD WIN32API StartDocPrinterA(
     2812              HANDLE hPrinter,
     2813              DWORD Level,
     2814              LPBYTE pDocInfo)
     2815{
     2816    DWORD   rc = 0;
     2817    dprintf(("WINSPOOL: StartDocPrinterA\n"));
     2818
     2819    /*
     2820     * Get printer instance data.
     2821     */
     2822    POPENPRINTER    pPrt = openprinterFind(hPrinter);
     2823    if (!pPrt)
     2824    {
     2825        dprintf(("WINSPOOL: StartDocPrinterA: Invalid handle %d\n", hPrinter));
     2826        SetLastError(ERROR_INVALID_HANDLE);
     2827        return 0;
     2828    }
     2829
     2830    /*
     2831     * Switch out based on input data.
     2832     */
     2833    switch (Level)
     2834    {
     2835        case 1:
     2836        {
     2837            PDOC_INFO_1A pDocInfoA = (PDOC_INFO_1A)pDocInfo;
     2838            dprintf(("WINSPOOL: pDocName   =%s\n", pDocInfoA->pDocName));
     2839            dprintf(("WINSPOOL: pDatatype  =%s\n", pDocInfoA->pDatatype));
     2840            dprintf(("WINSPOOL: pOutputFile=%s\n", pDocInfoA->pOutputFile));
     2841
     2842            /*
     2843             * Validate input.
     2844             *  ASSUMES: default is RAW as it is on OS/2.
     2845             */
     2846            if (    pDocInfoA->pDatatype
     2847                &&  !strstr(pDocInfoA->pDatatype, "RAW"))
     2848            {
     2849                SetLastError(ERROR_INVALID_PARAMETER);
     2850                dprintf(("WINSPOOL: data type not supported\n"));
     2851                break;
     2852            }
     2853
     2854            /*
     2855             * Make sure the OS/2 spool file is opened.
     2856             */
     2857            int rcOs2 = openprinterOpenSpoolFile(pPrt);
     2858            if (!rcOs2)
     2859            {
     2860                /*
     2861                 * Start the document.
     2862                 */
     2863                if (OSLibSplQmStartDoc(pPrt->hspl, pDocInfoA->pDocName))
     2864                {
     2865                    rc = (DWORD)pPrt->hspl; /** @todo get the proper job id! */
     2866                    pPrt->ulCurPage = 0; //reset current page counter
     2867                    dprintf(("WINSPOOL: StartDocPrinterA: returning jobid %d\n", rc));
     2868                    return rc;
     2869                }
     2870                else
     2871                    SetLastError(OSLibSplWinGetLastError()); /** @todo convert error code!!!!!!!! */
     2872            }
     2873            else
     2874                SetLastError(rcOs2); /** @todo convert error code!!!!!!!! */
     2875            break;
     2876        }
     2877
     2878        default:
     2879            dprintf(("WINSPOOL: level %d is not supported\n", Level));
     2880            SetLastError(ERROR_INVALID_LEVEL); /* not verified. */
     2881            break;
     2882    }
     2883    dprintf(("WINSPOOL: returning failure\n"));
     2884    return 0;
     2885}
     2886
     2887
     2888/**
     2889 * Start a new printer job.
     2890 *
     2891 * @returns Print job identifier.
     2892 * @returns 0 on failure with last error set.
     2893 * @param   hPrinter    Handle to the printer object.
     2894 * @param   Level       Structure level.
     2895 * @param   pDocInfo    Pointer to structure.
     2896 * @status  partially implemented.
     2897 * @author  knut st. osmundsen <bird-srcspam@anduin.net>
     2898 */
     2899DWORD WIN32API StartDocPrinterW(
     2900              HANDLE hPrinter,
     2901              DWORD Level,
     2902              LPBYTE pDocInfo)
     2903{
     2904    DWORD   rc = 0;
     2905    dprintf(("WINSPOOL: StartDocPrinterW\n"));
     2906    switch (Level)
     2907    {
     2908        case 1:
     2909        {
     2910            PDOC_INFO_1W    pDocInfoW = (PDOC_INFO_1W)pDocInfo;
     2911
     2912            DOC_INFO_1A     DocInfoA;
     2913            DocInfoA.pDocName    = UnicodeToAsciiString(pDocInfoW->pDocName);
     2914            DocInfoA.pDatatype   = UnicodeToAsciiString(pDocInfoW->pDatatype);
     2915            DocInfoA.pOutputFile = UnicodeToAsciiString(pDocInfoW->pOutputFile);
     2916            rc = StartDocPrinterA(hPrinter, Level, (LPBYTE)&DocInfoA);
     2917            FreeAsciiString(DocInfoA.pOutputFile);
     2918            FreeAsciiString(DocInfoA.pDatatype);
     2919            FreeAsciiString(DocInfoA.pDocName);
     2920            break;
     2921        }
     2922
     2923        default:
     2924            dprintf(("WINSPOOL: level %d is not supported\n", Level));
     2925            SetLastError(ERROR_INVALID_LEVEL); /* not verified. */
     2926            break;
     2927    }
     2928    dprintf(("WINSPOOL: returns %d\n", rc));
     2929    return rc;
     2930}
     2931
     2932
     2933/**
     2934 * Notifies the spooler that a new page is to be written to the
     2935 * current printer job.
     2936 *
     2937 * This is an informational API without much significance I think.
     2938 * The implementation assumes StartDocPrinterA/W() must be called first.
     2939 *
     2940 * @returns Success indicator. last error set on failure.
     2941 * @param   hPrinter    Handle to printer object.
     2942 * @status  completely implemented.
     2943 * @author  knut st. osmundsen <bird-srcspam@anduin.net>
     2944 */
     2945BOOL WIN32API StartPagePrinter(HANDLE hPrinter)
     2946{
     2947    dprintf(("WINSPOOL: StartPagePrinter: hPrinter=%d\n", hPrinter));
     2948    /*
     2949     * Get printer instance data.
     2950     */
     2951    POPENPRINTER    pPrt = openprinterFind(hPrinter);
     2952    if (!pPrt)
     2953    {
     2954        dprintf(("WINSPOOL: StartPagePrinter: Invalid handle %d\n", hPrinter));
     2955        SetLastError(ERROR_INVALID_HANDLE);
     2956        return FALSE;
     2957    }
     2958
     2959    /*
     2960     * Not quite sure what should happen here if no StartDocPrinter was issued.
     2961     * For now we'll just freak out.
     2962     */
     2963    if (!pPrt->hspl)
     2964    {
     2965        DebugAssertFailed(("StartPagePrinter called with no StartDocPrinter issued\n"));
     2966        SetLastError(ERROR_INVALID_PRINTER_STATE); /** @todo test on w2k */
     2967        return FALSE;
     2968    }
     2969
     2970    if (OSLibSplQmNewPage(pPrt->hspl, pPrt->ulCurPage + 1))
     2971    {
     2972        pPrt->ulCurPage++;
     2973        dprintf(("WINSPOOL: StartPagePrinter: returning successfully (ulCurPage=%lu)\n", pPrt->ulCurPage));
     2974        return TRUE;
     2975    }
     2976
     2977    /* failure */
     2978    SetLastError(OSLibSplWinGetLastError()); /** @todo convert error code!!! */
     2979    dprintf(("WINSPOOL: StartPagePrinter failed. last err=%#x\n", OSLibSplWinGetLastError()));
     2980    return FALSE;
     2981}
     2982
     2983
     2984/**
     2985 * Write raw data to printer.
     2986 * @returns Successindicator. lasterr set on failure.
     2987 * @param   hPrinter    Handle to printer object.
     2988 * @param   pBuf        Pointer to the data to write.
     2989 * @param   cbBuf       Size of the data to write.
     2990 * @param   pcWritten   Where to put the number of bytes actually written.
     2991 * @status  partially implemented.
     2992 * @author  knut st. osmundsen <bird-srcspam@anduin.net>
     2993 * @remark  Current implementation relies on StartDocPrinterA/W being called first.
     2994 */
     2995BOOL WIN32API WritePrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, LPDWORD pcWritten)
     2996{
     2997    BOOL    fRc = FALSE;
     2998    dprintf(("WINSPOOL: WritePrinter hPrinter=%#x pBuf=%p cbBuf=%d pcWritten=%p\n",
     2999             hPrinter, pBuf, cbBuf, pcWritten));
     3000
     3001    /*
     3002     * Get printer instance data.
     3003     */
     3004    POPENPRINTER    pPrt = openprinterFind(hPrinter);
     3005    if (!pPrt)
     3006    {
     3007        dprintf(("WINSPOOL: WritePrinter: Invalid handle %d\n", hPrinter));
     3008        SetLastError(ERROR_INVALID_HANDLE);
     3009        return FALSE;
     3010    }
     3011
     3012    /*
     3013     * Not quite sure what should happen here if no StartDocPrinter was issued.
     3014     * For now we'll just freak out.
     3015     */
     3016    if (!pPrt->hspl)
     3017    {
     3018        DebugAssertFailed(("WritePrinter called with no StartDocPrinter issued\n"));
     3019        SetLastError(ERROR_INVALID_PRINTER_STATE); /** @todo test on w2k */
     3020        return FALSE;
     3021    }
     3022
     3023    /*
     3024     * Push the data thru to the spooler.
     3025     */
     3026    if (OSLibSplQmWrite(pPrt->hspl, cbBuf, pBuf))
     3027    {
     3028        if (pcWritten)
     3029            *pcWritten = cbBuf;
     3030        dprintf(("WINSPOOL: WritePrinter succceeded writing %d bytes\n", cbBuf));
     3031        return TRUE;
     3032    }
     3033
     3034    /* failure */
     3035    SetLastError(OSLibSplWinGetLastError()); /** @todo convert error code!!! */
     3036    dprintf(("WINSPOOL: WritePrinter failed. last err=%#x\n", OSLibSplWinGetLastError()));
     3037    return FALSE;
     3038}
     3039
     3040
     3041/**
     3042 * Notifies the spooler that the writing of a page to the current
     3043 * printer job is completed.
     3044 *
     3045 * This is an informational API without much significance I think.
     3046 * The implementation assumes StartDocPrinterA/W() must be called first.
     3047 *
     3048 * @returns Success indicator, last error set on failure.
     3049 * @param   hPrinter    Handle to printer object which job is to be ended (completed.
     3050 * @status  partially implemented
     3051 * @author  knut st. osmundsen <bird-srcspam@anduin.net>
     3052 * @remark  Current implementation relies on StartDocPrinterA/W being called first.
     3053 */
     3054BOOL WIN32API EndPagePrinter(HANDLE hPrinter)
     3055{
     3056    dprintf(("WINSPOOL: EndPagePrinter: hPrinter=%d\n", hPrinter));
     3057
     3058    /*
     3059     * Get printer instance data.
     3060     */
     3061    POPENPRINTER    pPrt = openprinterFind(hPrinter);
     3062    if (!pPrt)
     3063    {
     3064        dprintf(("WINSPOOL: EndPagePrinter: Invalid handle %d\n", hPrinter));
     3065        SetLastError(ERROR_INVALID_HANDLE);
     3066        return FALSE;
     3067    }
     3068
     3069    /*
     3070     * Not quite sure what should happen here if no StartDocPrinter was issued.
     3071     * For now we'll just freak out.
     3072     */
     3073    if (!pPrt->hspl)
     3074    {
     3075        DebugAssertFailed(("EndPagePrinter called with no StartDocPrinter issued\n"));
     3076        SetLastError(ERROR_INVALID_PRINTER_STATE); /** @todo test on w2k */
     3077        return FALSE;
     3078    }
     3079
     3080    /* There is no OS/2 equivalent. */
     3081    dprintf(("WINSPOOL: EndPagePrinter: returning successfully (ulCurPage=%lu)\n", pPrt->ulCurPage));
     3082    return TRUE;
     3083}
     3084
     3085
     3086/**
     3087 * Ends a printer job.
     3088 *
     3089 * @returns Success indicator, last error set on failure.
     3090 * @param   hPrinter    Handle to printer object which job is to be ended (completed.
     3091 * @status  partially implemented
     3092 * @author  knut st. osmundsen <bird-srcspam@anduin.net>
     3093 * @remark  Current implementation relies on StartDocPrinterA/W being called first.
     3094 */
     3095BOOL WIN32API EndDocPrinter(HANDLE hPrinter)
     3096{
     3097    BOOL    fRc = FALSE;
     3098    dprintf(("WINSPOOL: WritePrinter hPrinter=%#x\n", hPrinter));
     3099
     3100    /*
     3101     * Get printer instance data.
     3102     */
     3103    POPENPRINTER    pPrt = openprinterFind(hPrinter);
     3104    if (!pPrt)
     3105    {
     3106        dprintf(("WINSPOOL: WritePrinter: Invalid handle %d\n", hPrinter));
     3107        SetLastError(ERROR_INVALID_HANDLE);
     3108        return FALSE;
     3109    }
     3110
     3111    /*
     3112     * Not quite sure what should happen here if no StartDocPrinter was issued.
     3113     * For now we'll just freak out.
     3114     */
     3115    if (!pPrt->hspl)
     3116    {
     3117        DebugAssertFailed(("EndDocPrinter called with no StartDocPrinter issued\n"));
     3118        SetLastError(ERROR_INVALID_PRINTER_STATE); /** @todo test on w2k */
     3119        return FALSE;
     3120    }
     3121
     3122    /*
     3123     * End the document, thus closing all Spl related stuff.
     3124     */
     3125    if (OSLibSplQmEndDoc(pPrt->hspl))
     3126    {
     3127        dprintf(("WINSPOOL: EndDocPrinter returns successfully\n"));
     3128        return TRUE;
     3129    }
     3130
     3131    SetLastError(OSLibSplWinGetLastError()); /** @todo convert error code!!! */
     3132    dprintf(("WINSPOOL: EndDocPrinter returns failure\n"));
     3133    return FALSE;
     3134}
     3135
     3136
     3137
     3138/**
     3139 * Setup the OS/2 Printer Information in the registry and profile.
     3140 *
     3141 * We will only enumerate local printer queues.
     3142 *
     3143 * The mapping between Odin32 and OS/2 is as follows:
     3144 *      Odin32              OS/2
     3145 *      Printer Name        Queue Comment (WPS object title)
     3146 *      Driver Name         Queue Name
     3147 *      Printer Comment     Queue Comment (= WPS object title)
     3148 *      Printer Location    Device Logical address (port sort of)
     3149 *      Printer Port        Device Logical address (port sort of)
     3150 *
     3151 * On OS/2 only queue names are unique. It's very easy to make duplicate
     3152 * printer names, just create printer objects in more than one WPS folder.
     3153 * For duplicate names the queue name will be appended to the name in
     3154 * paratheses so the user can actually print to both printers. (Odin32
     3155 * only have a concept of printer names and they must thus be unique.)
     3156 *
     3157 * @returns Success indicator. May possibly have changed the last error on
     3158 *          both failure and success.
     3159 *
     3160 * @remark  We're only enumerating local printers. This makes sense as remote
     3161 *          printers (on Lan Servers/Managers) isn't normally stored in the
     3162 *          registry (IIRC).
     3163 */
     3164BOOL ExportPrintersToRegistry(void)
     3165{
     3166    BOOL            fRc = FALSE;
     3167    DWORD           cbNeeded;
     3168    DWORD           cUnused;
     3169
     3170    dprintf(("WINSPOOL: ExportPrintersToRegistry"));
     3171
     3172    /*
     3173     * Get printers.
     3174     */
     3175    ULONG           cQueues = 0;
     3176    POSLIB_PRQINFO3 paQueues;
     3177    paQueues = (POSLIB_PRQINFO3)OSLibSplEnumQueue(NULL, 3, &cQueues, &cUnused);
     3178    if (paQueues)
     3179    {
     3180        /*
     3181         * Get printer devices.
     3182         */
     3183        ULONG   cDevices;
     3184        POSLIB_PRDINFO3 paDevices;
     3185        paDevices = (POSLIB_PRDINFO3)OSLibSplEnumDevice(NULL, 3, &cDevices, &cUnused);
     3186        if (paDevices)
     3187        {
     3188            fRc = TRUE;             /* getting this far is pretty much a success I'd say.... */
     3189
     3190            /*
     3191             * Make printer WPS names (queue comment) unique by appending the
     3192             * queuename for conflicting names.
     3193             */
     3194            unsigned    i;
     3195            char **papszNewNames = (char**)calloc(sizeof(char*), cQueues);
     3196            for (i = 0; i < cQueues; i++)
     3197            {
     3198                char *psz = paQueues[i].pszComment;
     3199                for (unsigned j = 0; j < cQueues; j++)
     3200                    if (j != i && !stricmp(paQueues[j].pszComment, psz))
     3201                    {
     3202                        dprintf(("duplicate printer names '%s'. appending queue name", psz));
     3203                        papszNewNames[i] = (char*)malloc(strlen(psz) + strlen(paQueues[i].pszName) + 4);
     3204                        sprintf(papszNewNames[i], "%s (%s)", psz, paQueues[i].pszName);
     3205                        paQueues[i].pszComment = papszNewNames[i];
     3206
     3207                        papszNewNames[j] = (char*)malloc(strlen(psz) + strlen(paQueues[j].pszName) + 4);
     3208                        sprintf(papszNewNames[j], "%s (%s)", psz, paQueues[j].pszName);
     3209                        paQueues[j].pszComment = papszNewNames[j];
     3210                    }
     3211            }
     3212
     3213            /*
     3214             * Add the printers.
     3215             */
     3216            PRINTER_INFO_2A *papi2 = (PRINTER_INFO_2A *)calloc(cQueues, sizeof(PRINTER_INFO_2A));
     3217            dprintf(("cQueues=%d cDevices=%d", cQueues, cDevices));
     3218            for (i = 0; i < cQueues; i++)
     3219            {
     3220                /* Make printer driver. */
     3221                DRIVER_INFO_3A      di3 = {0};
     3222                di3.cVersion           = 0x400;
     3223                #ifdef USE_OS2_DRIVERNAME
     3224                char *pszDot = strchr(paQueues[i].pszDriverName, '.');
     3225                if (pszDot && pszDot != paQueues[i].pszDriverName)  /* we're very careful :-) */
     3226                {   /* split the driver name, getting something very similar to window.s */
     3227                    *pszDot++ = '\0';
     3228                    di3.pName          = pszDot;
     3229                    di3.pDriverPath    = paQueues[i].pszDriverName; /* This is important! */
     3230                }
     3231                else
     3232                {   /* bad printer driver name? try cover up. */
     3233                    di3.pName          = paQueues[i].pszDriverName;
     3234                    di3.pDriverPath    = "WINSPOOL";   /* This is important! */
     3235                }
     3236                #else
     3237                di3.pName              = paQueues[i].pszName; /* printer driver == queue name */
     3238                di3.pDriverPath        = "WINSPOOL";   /* This is important! */
     3239                #endif
     3240                di3.pEnvironment       = NULL;         /* NULL means auto */
     3241                di3.pDataFile          = "<datafile?>";
     3242                di3.pConfigFile        = "winodin.drv";
     3243                di3.pHelpFile          = "<helpfile?>";
     3244                di3.pDependentFiles    = "<dependend files?>";
     3245                di3.pMonitorName       = "<monitor name?>";
     3246                di3.pDefaultDataType   = "RAW";
     3247                if (!AddPrinterDriverA(NULL, 3, (LPBYTE)&di3))
     3248                {
     3249                    DebugAssertFailed(("Failed adding Driver (%ld)\n", GetLastError()));
     3250                    fRc = FALSE;
     3251                }
     3252
     3253                /* Make printer. */
     3254                papi2[i].pDatatype    = "RAW";
     3255                papi2[i].pPrintProcessor = "WinPrint";
     3256                #ifdef USE_OS2_DRIVERNAME
     3257                papi2[i].pComment     = paQueues[i].pszName;    /* Queue name. Don't allow any changes of the comment! */
     3258                #else
     3259                papi2[i].pComment     = paQueues[i].pszComment; /* WPS printer name */
     3260                #endif
     3261                papi2[i].pDriverName  = di3.pName;
     3262                papi2[i].pParameters  = "<parameters?>";
     3263                papi2[i].pShareName   = "<share name?>";
     3264                papi2[i].pSepFile     = "<sep file?>";
     3265                #if 0 /* only 'local', remember */
     3266                if (paPrinters[i].pszComputerName) /* this is currnetly not used as we only enum locals. */
     3267                {
     3268                    papi2[i].Attributes |= PRINTER_ATTRIBUTE_NETWORK;
     3269                    papi2[i].pServerName = paPrinters[i].pszComputerName; /** @todo: format!! */
     3270                }
     3271                #endif
     3272
     3273                /*
     3274                 * We need to make sure the name is valid.
     3275                 * The registry decides what's illegal, slashes evedently are.
     3276                 */
     3277                papi2[i].pPrinterName = paQueues[i].pszComment;
     3278                char *psz = papi2[i].pPrinterName;
     3279                while ((psz = strpbrk(psz, "/\\")) != NULL)
     3280                       *psz = '|';      /* change slashes to pipes... */
     3281
     3282
     3283                /*
     3284                 * The queue pszPrinters member links with pszPrinterName of the device.
     3285                 * pszPrinters can contain several printer (device) names, separated by commas.
     3286                 * - We only handle the first printer listed. No idea how to get more than one
     3287                 *   the anyway.
     3288                 */
     3289                papi2[i].pLocation    = "";
     3290                papi2[i].pPortName    = "";
     3291                psz = strchr(paQueues[i].pszPrinters, ',');
     3292                if (psz)
     3293                    *psz = '\0';
     3294                for (unsigned k = 0; k < cDevices; k++)
     3295                {
     3296                    if (!stricmp(paDevices[k].pszPrinterName, paQueues[i].pszPrinters))
     3297                    {
     3298                        papi2[i].pLocation    = paDevices[k].pszLogAddr;
     3299                        papi2[i].pPortName    = paDevices[k].pszLogAddr;
     3300                        break;
     3301                    }
     3302                }
     3303
     3304                /*
     3305                 * Check if default printer and set attribute and write to profile.
     3306                 */
     3307                if (paQueues[i].fsType & OSLIB_PRQ3_TYPE_APPDEFAULT)
     3308                {
     3309                    char    szWinDefPrn[256];
     3310                    dprintf(("Default printer %s,%s,%s", papi2[i].pPrinterName, papi2[i].pDriverName, papi2[i].pPortName));
     3311                    sprintf(szWinDefPrn, "%s,%s,%s", papi2[i].pPrinterName, papi2[i].pDriverName, papi2[i].pPortName);
     3312                    WriteProfileStringA("windows", "device", szWinDefPrn);
     3313                    papi2[i].Attributes |= PRINTER_ATTRIBUTE_DEFAULT;
     3314                }
     3315
     3316                /*
     3317                 * Finally, we can add the printer
     3318                 */
     3319                dprintf(("Add printer %s,%s,%s", papi2[i].pPrinterName, papi2[i].pDriverName, papi2[i].pPortName));
     3320                if (!AddPrinterA(NULL, 2, (LPBYTE)&papi2[i]))
     3321                {
     3322                    DebugAssert(GetLastError() == ERROR_PRINTER_ALREADY_EXISTS,
     3323                                ("AddPrinterA(%s) failed with rc=%ld\n", papi2[i].pPrinterName, GetLastError()));
     3324                    fRc = FALSE;
     3325                }
     3326            } /* loop thru printers */
     3327
     3328
     3329            /*
     3330             * Purge dead printers.
     3331             * (It's important that we don't bail out before this when there is zero printers/devices!)
     3332             */
     3333            PPRINTER_INFO_2A    pi2;
     3334            DWORD               cOdinPrinters = 0;
     3335            cbNeeded = 0;
     3336            if (    EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &cbNeeded, &cOdinPrinters)
     3337                ||  GetLastError() == ERROR_INSUFFICIENT_BUFFER)
     3338            {
     3339                pi2 = (PPRINTER_INFO_2A)malloc(cbNeeded);
     3340                if (EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi2, cbNeeded, &cbNeeded, &cOdinPrinters))
     3341                {
     3342                    for (i = 0; i < cOdinPrinters; i++)
     3343                    {
     3344                        /* look if we added it */
     3345                        BOOL fFound = FALSE;
     3346                        for (unsigned j = 0; j < cQueues && !fFound; j++)
     3347                            fFound = !strcmp(papi2[j].pPrinterName,pi2[i].pPrinterName)
     3348                                &&   !strcmp(papi2[j].pDriverName, pi2[i].pDriverName)
     3349                                &&   !strcmp(papi2[j].pPortName,   pi2[i].pPortName);
     3350                        /* nuke it */
     3351                        if (!fFound)
     3352                        {
     3353                            HANDLE hPrinter;
     3354                            if (OpenPrinterA(pi2[i].pPrinterName, &hPrinter, NULL) == TRUE)
     3355                            {
     3356                                dprintf(("Delete printer %s,%s,%s", papi2[i].pPrinterName, papi2[i].pDriverName, papi2[i].pPortName));
     3357                                DeletePrinter(hPrinter);
     3358                                ClosePrinter(hPrinter);
     3359                            }
     3360                            else
     3361                            {
     3362                                DebugAssertFailed(("Failed to open a printer returned by EnumPrintersA, %s\n",
     3363                                                pi2[i].pPrinterName));
     3364                                fRc = FALSE;
     3365                            }
     3366                        }
     3367                    }
     3368                }
     3369                else
     3370                {
     3371                    DebugAssertFailed(("EnumPrintersA failed!\n"));
     3372                    fRc = FALSE;
     3373                }
     3374                free(pi2);
     3375            }
     3376            else
     3377            {
     3378                DebugAssertFailed(("EnumPrintersA failed!\n"));
     3379                fRc = FALSE;
     3380            }
     3381            free(papi2);
     3382            free(paDevices);
     3383            for (i = 0; i < cQueues; i++)
     3384                if (papszNewNames[i])
     3385                    free(papszNewNames[i]);
     3386        }
     3387        else
     3388            dprintf(("OSLibSplEnumDevice -> %d, cDevices=%d", fRc, cDevices));
     3389    }
     3390    else
     3391        dprintf(("OSLibSplEnumPrinter failed\n"));
     3392
     3393    free(paQueues);
     3394    dprintf(("ExportPrintersToRegistry returns %s", fRc ? "success" : "failure"));
     3395    return fRc;
     3396}
     3397
     3398#endif /* __WIN32OS2__ */
  • trunk/src/winspool/winspoolrsrc.orc

    r3031 r21305  
    1 /* $Id: winspoolrsrc.orc,v 1.1 2000-03-06 23:39:18 bird Exp $ */
    21
    32#include "winuser.h"
Note: See TracChangeset for help on using the changeset viewer.