diff options
-rw-r--r-- | source3/include/nt_printing.h | 102 | ||||
-rwxr-xr-x | source3/include/rpc_spoolss.h | 1413 | ||||
-rw-r--r-- | source3/printing/nt_printing.c | 1289 | ||||
-rw-r--r-- | source3/rpc_parse/parse_spoolss.c | 3389 | ||||
-rwxr-xr-x | source3/rpc_server/srv_spoolss.c | 3415 |
5 files changed, 9608 insertions, 0 deletions
diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h new file mode 100644 index 0000000000..a575c01e49 --- /dev/null +++ b/source3/include/nt_printing.h @@ -0,0 +1,102 @@ +typedef struct nt_printer_driver_info_level_3 +{ + uint32 cversion; + + fstring name; + fstring environment; + fstring driverpath; + fstring datafile; + fstring configfile; + fstring helpfile; + fstring monitorname; + fstring defaultdatatype; + char **dependentfiles; + +} NT_PRINTER_DRIVER_INFO_LEVEL_3; + +typedef struct nt_printer_driver_info_level +{ + NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3; +} NT_PRINTER_DRIVER_INFO_LEVEL; + +typedef struct nt_printer_param +{ + fstring value; + uint32 type; + uint8 *data; + int data_len; + struct nt_printer_param *next; +} NT_PRINTER_PARAM; + +typedef struct ntdevicemode +{ + fstring devicename; + uint16 specversion; + uint16 driverversion; + uint16 size; + uint16 driverextra; + uint32 fields; + uint16 orientation; + uint16 papersize; + uint16 paperlength; + uint16 paperwidth; + uint16 scale; + uint16 copies; + uint16 defaultsource; + uint16 printquality; + uint16 color; + uint16 duplex; + uint16 yresolution; + uint16 ttoption; + uint16 collate; + fstring formname; + uint16 logpixels; + uint32 bitsperpel; + uint32 pelswidth; + uint32 pelsheight; + uint32 displayflags; + uint32 displayfrequency; + uint32 icmmethod; + uint32 icmintent; + uint32 mediatype; + uint32 dithertype; + uint32 reserved1; + uint32 reserved2; + uint32 panningwidth; + uint32 panningheight; + uint8 *private; +} NT_DEVICEMODE; + +typedef struct nt_printer_info_level_2 +{ + uint32 attributes; + uint32 priority; + uint32 default_priority; + uint32 starttime; + uint32 untiltime; + uint32 status; + uint32 cjobs; + uint32 averageppm; + fstring servername; + fstring printername; + fstring sharename; + fstring portname; + fstring drivername; + fstring comment; + fstring location; + NT_DEVICEMODE *devmode; + fstring sepfile; + fstring printprocessor; + fstring datatype; + fstring parameters; + NT_PRINTER_PARAM *specific; + /* SEC_DESC_BUF *secdesc; */ + /* not used but ... and how ??? */ +} NT_PRINTER_INFO_LEVEL_2; + +typedef struct nt_printer_info_level +{ + NT_PRINTER_INFO_LEVEL_2 *info_2; +} NT_PRINTER_INFO_LEVEL; + + diff --git a/source3/include/rpc_spoolss.h b/source3/include/rpc_spoolss.h new file mode 100755 index 0000000000..91c018a669 --- /dev/null +++ b/source3/include/rpc_spoolss.h @@ -0,0 +1,1413 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Luke Kenneth Casson Leighton 1996-1998 + Copyright (C) Jean Francois Micouleau 1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _RPC_SPOOLSS_H /* _RPC_SPOOLSS_H */ +#define _RPC_SPOOLSS_H + +#define INTEGER 1 +#define STRING 2 + +/* spoolss pipe: this are the calls which are not implemented ... +#define SPOOLSS_OPENPRINTER 0x01 +#define SPOOLSS_GETJOB 0x03 +#define SPOOLSS_DELETEPRINTER 0x06 +#define SPOOLSS_GETPRINTERDRIVER 0x0b +#define SPOOLSS_DELETEPRINTERDRIVER 0x0d +#define SPOOLSS_ADDPRINTPROCESSOR 0x0e +#define SPOOLSS_GETPRINTPROCESSORDIRECTORY 0x10 +#define SPOOLSS_ABORTPRINTER 0x15 +#define SPOOLSS_READPRINTER 0x16 +#define SPOOLSS_WAITFORPRINTERCHANGE 0x1c +#define SPOOLSS_ADDFORM 0x1e +#define SPOOLSS_DELETEFORM 0x1f +#define SPOOLSS_GETFORM 0x20 +#define SPOOLSS_SETFORM 0x21 +#define SPOOLSS_ENUMMONITORS 0x24 +#define SPOOLSS_ADDPORT 0x25 +#define SPOOLSS_CONFIGUREPORT 0x26 +#define SPOOLSS_DELETEPORT 0x27 +#define SPOOLSS_CREATEPRINTERIC 0x28 +#define SPOOLSS_PLAYGDISCRIPTONPRINTERIC 0x29 +#define SPOOLSS_DELETEPRINTERIC 0x2a +#define SPOOLSS_ADDPRINTERCONNECTION 0x2b +#define SPOOLSS_DELETEPRINTERCONNECTION 0x2c +#define SPOOLSS_PRINTERMESSAGEBOX 0x2d +#define SPOOLSS_ADDMONITOR 0x2e +#define SPOOLSS_DELETEMONITOR 0x2f +#define SPOOLSS_DELETEPRINTPROCESSOR 0x30 +#define SPOOLSS_ADDPRINTPROVIDOR 0x31 +#define SPOOLSS_DELETEPRINTPROVIDOR 0x32 +#define SPOOLSS_RESETPRINTER 0x34 +#define SPOOLSS_FINDFIRSTPRINTERCHANGENOTIFICATION 0x36 +#define SPOOLSS_FINDNEXTPRINTERCHANGENOTIFICATION 0x37 +#define SPOOLSS_ROUTERFINDFIRSTPRINTERNOTIFICATIONOLD 0x39 +#define SPOOLSS_REPLYOPENPRINTER 0x3a +#define SPOOLSS_ROUTERREPLYPRINTER 0x3b +#define SPOOLSS_REPLYCLOSEPRINTER 0x3c +#define SPOOLSS_ADDPORTEX 0x3d +#define SPOOLSS_REMOTEFINDFIRSTPRINTERCHANGENOTIFICATION0x3e +#define SPOOLSS_SPOOLERINIT 0x3f +#define SPOOLSS_RESETPRINTEREX 0x40 +#define SPOOLSS_ROUTERREFRESHPRINTERCHANGENOTIFICATION 0x42 +*/ + +/* those are implemented */ + +#define SPOOLSS_ENUMPRINTERS 0x00 +#define SPOOLSS_SETJOB 0x02 +#define SPOOLSS_ENUMJOBS 0x04 +#define SPOOLSS_ADDPRINTER 0x05 +#define SPOOLSS_SETPRINTER 0x07 +#define SPOOLSS_GETPRINTER 0x08 +#define SPOOLSS_ADDPRINTERDRIVER 0x09 +#define SPOOLSS_ENUMPRINTERDRIVERS 0x0a +#define SPOOLSS_GETPRINTERDRIVERDIRECTORY 0x0c +#define SPOOLSS_ENUMPRINTPROCESSORS 0x0f +#define SPOOLSS_STARTDOCPRINTER 0x11 +#define SPOOLSS_STARTPAGEPRINTER 0x12 +#define SPOOLSS_WRITEPRINTER 0x13 +#define SPOOLSS_ENDPAGEPRINTER 0x14 +#define SPOOLSS_ENDDOCPRINTER 0x17 +#define SPOOLSS_ADDJOB 0x18 +#define SPOOLSS_SCHEDULEJOB 0x19 +#define SPOOLSS_GETPRINTERDATA 0x1a +#define SPOOLSS_SETPRINTERDATA 0x1b +#define SPOOLSS_CLOSEPRINTER 0x1d +#define SPOOLSS_ENUMFORMS 0x22 +#define SPOOLSS_ENUMPORTS 0x23 +#define SPOOLSS_ENUMPRINTPROCESSORDATATYPES 0x33 +#define SPOOLSS_GETPRINTERDRIVER2 0x35 +/* find close printer notification */ +#define SPOOLSS_FCPN 0x38 +/* remote find first printer change notifyEx */ +#define SPOOLSS_RFFPCNEX 0x41 +/* remote find next printer change notifyEx */ +#define SPOOLSS_RFNPCNEX 0x43 +#define SPOOLSS_OPENPRINTEREX 0x45 +#define SPOOLSS_ADDPRINTEREX 0x46 +#define SPOOLSS_ENUMPRINTERDATA 0x48 + + +#define SERVER_ACCESS_ADMINISTER 0x00000001 +#define SERVER_ACCESS_ENUMERATE 0x00000002 + +#define PRINTER_ACCESS_ADMINISTER 0x00000004 +#define PRINTER_ACCESS_USE 0x00000008 + +#define PRINTER_CONTROL_UNPAUSE 0x00000000 +#define PRINTER_CONTROL_PAUSE 0x00000001 +#define PRINTER_CONTROL_RESUME 0x00000002 +#define PRINTER_CONTROL_PURGE 0x00000003 +#define PRINTER_CONTROL_SET_STATUS 0x00000004 + +#define PRINTER_STATUS_PAUSED 0x00000001 +#define PRINTER_STATUS_ERROR 0x00000002 +#define PRINTER_STATUS_PENDING_DELETION 0x00000004 +#define PRINTER_STATUS_PAPER_JAM 0x00000008 + +#define PRINTER_STATUS_PAPER_OUT 0x00000010 +#define PRINTER_STATUS_MANUAL_FEED 0x00000020 +#define PRINTER_STATUS_PAPER_PROBLEM 0x00000040 +#define PRINTER_STATUS_OFFLINE 0x00000080 + +#define PRINTER_STATUS_IO_ACTIVE 0x00000100 +#define PRINTER_STATUS_BUSY 0x00000200 +#define PRINTER_STATUS_PRINTING 0x00000400 +#define PRINTER_STATUS_OUTPUT_BIN_FULL 0x00000800 + +#define PRINTER_STATUS_NOT_AVAILABLE 0x00001000 +#define PRINTER_STATUS_WAITING 0x00002000 +#define PRINTER_STATUS_PROCESSING 0x00004000 +#define PRINTER_STATUS_INITIALIZING 0x00008000 + +#define PRINTER_STATUS_WARMING_UP 0x00010000 +#define PRINTER_STATUS_TONER_LOW 0x00020000 +#define PRINTER_STATUS_NO_TONER 0x00040000 +#define PRINTER_STATUS_PAGE_PUNT 0x00080000 + +#define PRINTER_STATUS_USER_INTERVENTION 0x00100000 +#define PRINTER_STATUS_OUT_OF_MEMORY 0x00200000 +#define PRINTER_STATUS_DOOR_OPEN 0x00400000 +#define PRINTER_STATUS_SERVER_UNKNOWN 0x00800000 + +#define PRINTER_STATUS_POWER_SAVE 0x01000000 + +#define JOB_ACCESS_ADMINISTER 0x00000010 + +#define STANDARD_RIGHTS_READ 0x00020000 +#define STANDARD_RIGHTS_WRITE STANDARD_RIGHTS_READ +#define STANDARD_RIGHTS_EXECUTE STANDARD_RIGHTS_READ +#define STANDARD_RIGHTS_REQUIRED 0x000F0000 + +/* Access rights for print servers */ +#define SERVER_ALL_ACCESS STANDARD_RIGHTS_REQUIRED|SERVER_ACCESS_ADMINISTER|SERVER_ACCESS_ENUMERATE +#define SERVER_READ STANDARD_RIGHTS_READ|SERVER_ACCESS_ENUMERATE +#define SERVER_WRITE STANDARD_RIGHTS_WRITE|SERVER_ACCESS_ADMINISTER|SERVER_ACCESS_ENUMERATE +#define SERVER_EXECUTE STANDARD_RIGHTS_EXECUTE|SERVER_ACCESS_ENUMERATE + +/* Access rights for printers */ +#define PRINTER_ALL_ACCESS STANDARD_RIGHTS_REQUIRED|PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE +#define PRINTER_READ STANDARD_RIGHTS_READ|PRINTER_ACCESS_USE +#define PRINTER_WRITE STANDARD_RIGHTS_WRITE|PRINTER_ACCESS_USE +#define PRINTER_EXECUTE STANDARD_RIGHTS_EXECUTE|PRINTER_ACCESS_USE + +/* Access rights for jobs */ +#define JOB_ALL_ACCESS STANDARD_RIGHTS_REQUIRED|JOB_ACCESS_ADMINISTER +#define JOB_READ STANDARD_RIGHTS_READ|JOB_ACCESS_ADMINISTER +#define JOB_WRITE STANDARD_RIGHTS_WRITE|JOB_ACCESS_ADMINISTER +#define JOB_EXECUTE STANDARD_RIGHTS_EXECUTE|JOB_ACCESS_ADMINISTER + +#define PRINTER_HND_SIZE 20 + +#define ONE_VALUE 01 +#define TWO_VALUE 02 +#define POINTER 03 + +#define PRINTER_NOTIFY_TYPE 0x00 +#define JOB_NOTIFY_TYPE 0x01 + +#define MAX_PRINTER_NOTIFY 26 + +#define PRINTER_NOTIFY_SERVER_NAME 0x00 +#define PRINTER_NOTIFY_PRINTER_NAME 0x01 +#define PRINTER_NOTIFY_SHARE_NAME 0x02 +#define PRINTER_NOTIFY_PORT_NAME 0x03 +#define PRINTER_NOTIFY_DRIVER_NAME 0x04 +#define PRINTER_NOTIFY_COMMENT 0x05 +#define PRINTER_NOTIFY_LOCATION 0x06 +#define PRINTER_NOTIFY_DEVMODE 0x07 +#define PRINTER_NOTIFY_SEPFILE 0x08 +#define PRINTER_NOTIFY_PRINT_PROCESSOR 0x09 +#define PRINTER_NOTIFY_PARAMETERS 0x0A +#define PRINTER_NOTIFY_DATATYPE 0x0B +#define PRINTER_NOTIFY_SECURITY_DESCRIPTOR 0x0C +#define PRINTER_NOTIFY_ATTRIBUTES 0x0D +#define PRINTER_NOTIFY_PRIORITY 0x0E +#define PRINTER_NOTIFY_DEFAULT_PRIORITY 0x0F +#define PRINTER_NOTIFY_START_TIME 0x10 +#define PRINTER_NOTIFY_UNTIL_TIME 0x11 +#define PRINTER_NOTIFY_STATUS 0x12 +#define PRINTER_NOTIFY_STATUS_STRING 0x13 +#define PRINTER_NOTIFY_CJOBS 0x14 +#define PRINTER_NOTIFY_AVERAGE_PPM 0x15 +#define PRINTER_NOTIFY_TOTAL_PAGES 0x16 +#define PRINTER_NOTIFY_PAGES_PRINTED 0x17 +#define PRINTER_NOTIFY_TOTAL_BYTES 0x18 +#define PRINTER_NOTIFY_BYTES_PRINTED 0x19 + +#define MAX_JOB_NOTIFY 24 + +#define JOB_NOTIFY_PRINTER_NAME 0x00 +#define JOB_NOTIFY_MACHINE_NAME 0x01 +#define JOB_NOTIFY_PORT_NAME 0x02 +#define JOB_NOTIFY_USER_NAME 0x03 +#define JOB_NOTIFY_NOTIFY_NAME 0x04 +#define JOB_NOTIFY_DATATYPE 0x05 +#define JOB_NOTIFY_PRINT_PROCESSOR 0x06 +#define JOB_NOTIFY_PARAMETERS 0x07 +#define JOB_NOTIFY_DRIVER_NAME 0x08 +#define JOB_NOTIFY_DEVMODE 0x09 +#define JOB_NOTIFY_STATUS 0x0A +#define JOB_NOTIFY_STATUS_STRING 0x0B +#define JOB_NOTIFY_SECURITY_DESCRIPTOR 0x0C +#define JOB_NOTIFY_DOCUMENT 0x0D +#define JOB_NOTIFY_PRIORITY 0x0E +#define JOB_NOTIFY_POSITION 0x0F +#define JOB_NOTIFY_SUBMITTED 0x10 +#define JOB_NOTIFY_START_TIME 0x11 +#define JOB_NOTIFY_UNTIL_TIME 0x12 +#define JOB_NOTIFY_TIME 0x13 +#define JOB_NOTIFY_TOTAL_PAGES 0x14 +#define JOB_NOTIFY_PAGES_PRINTED 0x15 +#define JOB_NOTIFY_TOTAL_BYTES 0x16 +#define JOB_NOTIFY_BYTES_PRINTED 0x17 + +/* + * The printer attributes. + * I #defined all of them (grabbed form MSDN) + * I'm only using: + * ( SHARED | NETWORK | RAW_ONLY ) + * RAW_ONLY _MUST_ be present otherwise NT will send an EMF file + */ + +#define PRINTER_ATTRIBUTE_QUEUED 0x00000001 +#define PRINTER_ATTRIBUTE_DIRECT 0x00000002 +#define PRINTER_ATTRIBUTE_DEFAULT 0x00000004 +#define PRINTER_ATTRIBUTE_SHARED 0x00000008 + +#define PRINTER_ATTRIBUTE_NETWORK 0x00000010 +#define PRINTER_ATTRIBUTE_HIDDEN 0x00000020 +#define PRINTER_ATTRIBUTE_LOCAL 0x00000040 +#define PRINTER_ATTRIBUTE_ENABLE_DEVQ 0x00000080 + +#define PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS 0x00000100 +#define PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST 0x00000200 +#define PRINTER_ATTRIBUTE_WORK_OFFLINE 0x00000400 +#define PRINTER_ATTRIBUTE_ENABLE_BIDI 0x00000800 + +#define PRINTER_ATTRIBUTE_RAW_ONLY 0x00001000 + +#define NO_PRIORITY 0 +#define MAX_PRIORITY 99 +#define MIN_PRIORITY 1 +#define DEF_PRIORITY 1 + +#define PRINTER_ENUM_DEFAULT 0x00000001 +#define PRINTER_ENUM_LOCAL 0x00000002 +#define PRINTER_ENUM_CONNECTIONS 0x00000004 +#define PRINTER_ENUM_FAVORITE 0x00000004 +#define PRINTER_ENUM_NAME 0x00000008 +#define PRINTER_ENUM_REMOTE 0x00000010 +#define PRINTER_ENUM_SHARED 0x00000020 +#define PRINTER_ENUM_NETWORK 0x00000040 + +#define PRINTER_ENUM_EXPAND 0x00004000 +#define PRINTER_ENUM_CONTAINER 0x00008000 + +#define PRINTER_ENUM_ICONMASK 0x00ff0000 +#define PRINTER_ENUM_ICON1 0x00010000 +#define PRINTER_ENUM_ICON2 0x00020000 +#define PRINTER_ENUM_ICON3 0x00040000 +#define PRINTER_ENUM_ICON4 0x00080000 +#define PRINTER_ENUM_ICON5 0x00100000 +#define PRINTER_ENUM_ICON6 0x00200000 +#define PRINTER_ENUM_ICON7 0x00400000 +#define PRINTER_ENUM_ICON8 0x00800000 + +typedef struct +{ + char name[100]; + uint32 flag; + uint32 width; + uint32 length; + uint32 left; + uint32 top; + uint32 right; + uint32 bottom; +} nt_forms_struct; + +typedef struct +{ + char name[100]; + char architecture[100]; + uint32 version; + char default_form[30]; + uint32 color_flag; + char driver[100]; + char datafile[100]; + char configfile[100]; + char helpfile[100]; + char monitor[100]; + char monitor_name[100]; + char **dependant; +} nt_drivers_struct; + +typedef struct devicemode +{ + UNISTR devicename; + uint16 specversion; + uint16 driverversion; + uint16 size; + uint16 driverextra; + uint32 fields; + uint16 orientation; + uint16 papersize; + uint16 paperlength; + uint16 paperwidth; + uint16 scale; + uint16 copies; + uint16 defaultsource; + uint16 printquality; + uint16 color; + uint16 duplex; + uint16 yresolution; + uint16 ttoption; + uint16 collate; + UNISTR formname; + uint16 logpixels; + uint32 bitsperpel; + uint32 pelswidth; + uint32 pelsheight; + uint32 displayflags; + uint32 displayfrequency; + uint32 icmmethod; + uint32 icmintent; + uint32 mediatype; + uint32 dithertype; + uint32 reserved1; + uint32 reserved2; + uint32 panningwidth; + uint32 panningheight; + uint8 *private; +} DEVICEMODE; + +typedef struct devicemode_container +{ + DEVICEMODE *dm; + uint8 *buffer; + uint32 size_of_buffer; +} DEVICEMODE_CONTAINER; + +#define ORIENTATION 0x00000001L +#define PAPERSIZE 0x00000002L +#define PAPERLENGTH 0x00000004L +#define PAPERWIDTH 0x00000008L +#define SCALE 0x00000010L +#define COPIES 0x00000100L +#define DEFAULTSOURCE 0x00000200L +#define PRINTQUALITY 0x00000400L +#define COLOR 0x00000800L +#define DUPLEX 0x00001000L +#define YRESOLUTION 0x00002000L +#define TTOPTION 0x00004000L +#define COLLATE 0x00008000L +#define FORMNAME 0x00010000L +#define LOGPIXELS 0x00020000L +#define BITSPERPEL 0x00040000L +#define PELSWIDTH 0x00080000L +#define PELSHEIGHT 0x00100000L +#define DISPLAYFLAGS 0x00200000L +#define DISPLAYFREQUENCY 0x00400000L +#define PANNINGWIDTH 0x00800000L +#define PANNINGHEIGHT 0x01000000L + +#define ORIENT_PORTRAIT 1 +#define ORIENT_LANDSCAPE 2 + +#define PAPER_FIRST PAPER_LETTER +#define PAPER_LETTER 1 /* Letter 8 1/2 x 11 in */ +#define PAPER_LETTERSMALL 2 /* Letter Small 8 1/2 x 11 in */ +#define PAPER_TABLOID 3 /* Tabloid 11 x 17 in */ +#define PAPER_LEDGER 4 /* Ledger 17 x 11 in */ +#define PAPER_LEGAL 5 /* Legal 8 1/2 x 14 in */ +#define PAPER_STATEMENT 6 /* Statement 5 1/2 x 8 1/2 in */ +#define PAPER_EXECUTIVE 7 /* Executive 7 1/4 x 10 1/2 in */ +#define PAPER_A3 8 /* A3 297 x 420 mm */ +#define PAPER_A4 9 /* A4 210 x 297 mm */ +#define PAPER_A4SMALL 10 /* A4 Small 210 x 297 mm */ +#define PAPER_A5 11 /* A5 148 x 210 mm */ +#define PAPER_B4 12 /* B4 (JIS) 250 x 354 */ +#define PAPER_B5 13 /* B5 (JIS) 182 x 257 mm */ +#define PAPER_FOLIO 14 /* Folio 8 1/2 x 13 in */ +#define PAPER_QUARTO 15 /* Quarto 215 x 275 mm */ +#define PAPER_10X14 16 /* 10x14 in */ +#define PAPER_11X17 17 /* 11x17 in */ +#define PAPER_NOTE 18 /* Note 8 1/2 x 11 in */ +#define PAPER_ENV_9 19 /* Envelope #9 3 7/8 x 8 7/8 */ +#define PAPER_ENV_10 20 /* Envelope #10 4 1/8 x 9 1/2 */ +#define PAPER_ENV_11 21 /* Envelope #11 4 1/2 x 10 3/8 */ +#define PAPER_ENV_12 22 /* Envelope #12 4 \276 x 11 */ +#define PAPER_ENV_14 23 /* Envelope #14 5 x 11 1/2 */ +#define PAPER_CSHEET 24 /* C size sheet */ +#define PAPER_DSHEET 25 /* D size sheet */ +#define PAPER_ESHEET 26 /* E size sheet */ +#define PAPER_ENV_DL 27 /* Envelope DL 110 x 220mm */ +#define PAPER_ENV_C5 28 /* Envelope C5 162 x 229 mm */ +#define PAPER_ENV_C3 29 /* Envelope C3 324 x 458 mm */ +#define PAPER_ENV_C4 30 /* Envelope C4 229 x 324 mm */ +#define PAPER_ENV_C6 31 /* Envelope C6 114 x 162 mm */ +#define PAPER_ENV_C65 32 /* Envelope C65 114 x 229 mm */ +#define PAPER_ENV_B4 33 /* Envelope B4 250 x 353 mm */ +#define PAPER_ENV_B5 34 /* Envelope B5 176 x 250 mm */ +#define PAPER_ENV_B6 35 /* Envelope B6 176 x 125 mm */ +#define PAPER_ENV_ITALY 36 /* Envelope 110 x 230 mm */ +#define PAPER_ENV_MONARCH 37 /* Envelope Monarch 3.875 x 7.5 in */ +#define PAPER_ENV_PERSONAL 38 /* 6 3/4 Envelope 3 5/8 x 6 1/2 in */ +#define PAPER_FANFOLD_US 39 /* US Std Fanfold 14 7/8 x 11 in */ +#define PAPER_FANFOLD_STD_GERMAN 40 /* German Std Fanfold 8 1/2 x 12 in */ +#define PAPER_FANFOLD_LGL_GERMAN 41 /* German Legal Fanfold 8 1/2 x 13 in */ + +#define PAPER_LAST PAPER_FANFOLD_LGL_GERMAN +#define PAPER_USER 256 + +#define BIN_FIRST BIN_UPPER +#define BIN_UPPER 1 +#define BIN_ONLYONE 1 +#define BIN_LOWER 2 +#define BIN_MIDDLE 3 +#define BIN_MANUAL 4 +#define BIN_ENVELOPE 5 +#define BIN_ENVMANUAL 6 +#define BIN_AUTO 7 +#define BIN_TRACTOR 8 +#define BIN_SMALLFMT 9 +#define BIN_LARGEFMT 10 +#define BIN_LARGECAPACITY 11 +#define BIN_CASSETTE 14 +#define BIN_FORMSOURCE 15 +#define BIN_LAST BIN_FORMSOURCE + +#define BIN_USER 256 /* device specific bins start here */ + +#define RES_DRAFT (-1) +#define RES_LOW (-2) +#define RES_MEDIUM (-3) +#define RES_HIGH (-4) + +#define COLOR_MONOCHROME 1 +#define COLOR_COLOR 2 + +#define DUP_SIMPLEX 1 +#define DUP_VERTICAL 2 +#define DUP_HORIZONTAL 3 + +#define TT_BITMAP 1 /* print TT fonts as graphics */ +#define TT_DOWNLOAD 2 /* download TT fonts as soft fonts */ +#define TT_SUBDEV 3 /* substitute device fonts for TT fonts */ + +#define COLLATE_FALSE 0 +#define COLLATE_TRUE 1 + +#define ERROR_INVALID_HANDLE 6 +#define ERROR_INVALID_PARAMETER 87 +#define ERROR_INSUFFICIENT_BUFFER 122 + +typedef struct s_header_type +{ + uint32 type; + union + { + uint32 value; + UNISTR string; + } data; +} HEADER_TYPE; + +typedef struct s_buffer +{ + uint32 ptr; + uint32 size; + uint32 count; + uint8 *data; + HEADER_TYPE *header; +} BUFFER; + + +/* PRINTER_HND */ +typedef struct printer_policy_info +{ + uint8 data[PRINTER_HND_SIZE]; /* printer handle */ +} PRINTER_HND; + +/* SPOOL_Q_OPEN_PRINTER request to open a printer */ +typedef struct spool_q_open_printer +{ + uint32 unknown0; + UNISTR2 printername; + uint32 unknown1; + uint32 cbbuf; + uint32 devmod; + uint32 access_required; + uint32 unknown2; /* 0x0000 0001 */ + uint32 unknown3; /* 0x0000 0001 */ + uint32 unknown4; /* ??? */ + uint32 unknown5; /* 0x0000 001c */ + uint32 unknown6; /* ??? */ + uint32 unknown7; /* ??? */ + uint32 unknown8; /* 0x0000 0565 */ + uint32 unknown9; /* 0x0000 0002 */ + uint32 unknown10; /* 0x0000 0000 */ + uint32 unknown11; /* ??? */ + UNISTR2 station; + UNISTR2 username; +} SPOOL_Q_OPEN_PRINTER; + +/* SPOOL_Q_OPEN_PRINTER reply to an open printer */ +typedef struct spool_r_open_printer +{ + PRINTER_HND handle; /* handle used along all transactions (20*uint8) */ + uint32 status; +} SPOOL_R_OPEN_PRINTER; + +typedef struct spool_q_getprinterdata +{ + PRINTER_HND handle; + UNISTR2 valuename; + uint32 size; +} SPOOL_Q_GETPRINTERDATA; + +typedef struct spool_r_getprinterdata +{ + uint32 type; + uint32 size; + uint8 *data; + uint32 numeric_data; + uint32 needed; + uint32 status; +} SPOOL_R_GETPRINTERDATA; + +typedef struct spool_q_closeprinter +{ + PRINTER_HND handle; +} SPOOL_Q_CLOSEPRINTER; + +typedef struct spool_r_closeprinter +{ + PRINTER_HND handle; + uint32 status; +} SPOOL_R_CLOSEPRINTER; + +typedef struct spool_q_startpageprinter +{ + PRINTER_HND handle; +} SPOOL_Q_STARTPAGEPRINTER; + +typedef struct spool_r_startpageprinter +{ + uint32 status; +} SPOOL_R_STARTPAGEPRINTER; + +typedef struct spool_q_endpageprinter +{ + PRINTER_HND handle; +} SPOOL_Q_ENDPAGEPRINTER; + +typedef struct spool_r_endpageprinter +{ + uint32 status; +} SPOOL_R_ENDPAGEPRINTER; + +typedef struct spool_doc_info_1 +{ + uint32 p_docname; + uint32 p_outputfile; + uint32 p_datatype; + UNISTR2 docname; + UNISTR2 outputfile; + UNISTR2 datatype; +} DOC_INFO_1; + +typedef struct spool_doc_info +{ + uint32 switch_value; + DOC_INFO_1 doc_info_1; +} DOC_INFO; + +typedef struct spool_doc_info_container +{ + uint32 level; + DOC_INFO docinfo; +} DOC_INFO_CONTAINER; + +typedef struct spool_q_startdocprinter +{ + PRINTER_HND handle; + DOC_INFO_CONTAINER doc_info_container; +} SPOOL_Q_STARTDOCPRINTER; + +typedef struct spool_r_startdocprinter +{ + uint32 jobid; + uint32 status; +} SPOOL_R_STARTDOCPRINTER; + +typedef struct spool_q_enddocprinter +{ + PRINTER_HND handle; +} SPOOL_Q_ENDDOCPRINTER; + +typedef struct spool_r_enddocprinter +{ + uint32 status; +} SPOOL_R_ENDDOCPRINTER; + +typedef struct spool_q_writeprinter +{ + PRINTER_HND handle; + uint32 buffer_size; + uint8 *buffer; + uint32 buffer_size2; +} SPOOL_Q_WRITEPRINTER; + +typedef struct spool_r_writeprinter +{ + uint32 buffer_written; + uint32 status; +} SPOOL_R_WRITEPRINTER; + +typedef struct spool_notify_option_type +{ + uint16 type; + uint16 reserved0; + uint32 reserved1; + uint32 reserved2; + uint32 count; + uint16 fields[16]; +} SPOOL_NOTIFY_OPTION_TYPE; + +typedef struct spool_notify_option +{ + uint32 version; + uint32 reserved; + uint32 count; + SPOOL_NOTIFY_OPTION_TYPE type[16]; /* totally arbitrary !!! */ +} SPOOL_NOTIFY_OPTION; + +typedef struct spool_notify_info_data +{ + uint16 type; + uint16 field; + uint32 reserved; + uint32 id; + union + { + uint32 value[2]; + struct + { + uint32 length; + uint16 string[1024]; + } data; + } notify_data; + uint32 size; + BOOL enc_type; +} SPOOL_NOTIFY_INFO_DATA; + +typedef struct spool_notify_info +{ + uint32 version; + uint32 flags; + uint32 count; + SPOOL_NOTIFY_INFO_DATA data[26*16]; + /* 26 differents data types */ + /* so size it for 16 printers at max */ + /* jfmxxxx: Have to make it dynamic !!!*/ +} SPOOL_NOTIFY_INFO; + +/* If the struct name looks obscure, yes it is ! */ +/* RemoteFindFirstPrinterChangeNotificationEx query struct */ +typedef struct spoolss_q_rffpcnex +{ + PRINTER_HND handle; + uint32 flags; + uint32 options; + UNISTR2 localmachine; + uint32 printerlocal; + SPOOL_NOTIFY_OPTION option; +} SPOOL_Q_RFFPCNEX; + +typedef struct spool_r_rffpcnex +{ + uint32 status; +} SPOOL_R_RFFPCNEX; + +/* Remote Find Next Printer Change Notify Ex */ +typedef struct spool_q_rfnpcnex +{ + PRINTER_HND handle; + uint32 change; + SPOOL_NOTIFY_OPTION option; +} SPOOL_Q_RFNPCNEX; + +typedef struct spool_r_rfnpcnex +{ + uint32 count; + SPOOL_NOTIFY_INFO info; +} SPOOL_R_RFNPCNEX; + +/* Find Close Printer Notify */ +typedef struct spool_q_fcpn +{ + PRINTER_HND handle; +} SPOOL_Q_FCPN; + +typedef struct spool_r_fcpn +{ + uint32 status; +} SPOOL_R_FCPN; + + +typedef struct printer_info_0 +{ + UNISTR printername; + UNISTR servername; + uint32 cjobs; + uint32 attributes; + uint32 unknown0; + uint32 unknown1; + uint32 unknown2; + uint32 unknown3; + uint32 unknown4; + uint32 unknown5; + uint32 unknown6; + uint16 majorversion; + uint16 buildversion; + uint32 unknown7; + uint32 unknown8; + uint32 unknown9; + uint32 unknown10; + uint32 unknown11; + uint32 unknown12; + uint32 unknown13; + uint32 unknown14; + uint32 unknown15; + uint32 unknown16; + uint32 unknown17; + uint32 unknown18; + uint32 status; + uint32 unknown20; + uint32 unknown21; + uint16 unknown22; + uint32 unknown23; +} PRINTER_INFO_0; + +typedef struct printer_info_1 +{ + uint32 flags; + UNISTR description; + UNISTR name; + UNISTR comment; +} PRINTER_INFO_1; + +typedef struct printer_info_2 +{ + UNISTR servername; + UNISTR printername; + UNISTR sharename; + UNISTR portname; + UNISTR drivername; + UNISTR comment; + UNISTR location; + DEVICEMODE *devmode; + UNISTR sepfile; + UNISTR printprocessor; + UNISTR datatype; + UNISTR parameters; + /*SECURITY_DESCRIPTOR securitydescriptor;*/ + uint32 attributes; + uint32 priority; + uint32 defaultpriority; + uint32 starttime; + uint32 untiltime; + uint32 status; + uint32 cjobs; + uint32 averageppm; +} PRINTER_INFO_2; + +typedef struct spool_q_enumprinters +{ + uint32 flags; + UNISTR2 servername; + uint32 level; + BUFFER buffer; +/* uint32 buf_size;*/ +} SPOOL_Q_ENUMPRINTERS; + +typedef struct spool_r_enumprinters +{ + uint32 offered; /* number of bytes offered */ + uint32 needed; /* bytes needed */ + uint32 returned; /* number of printers */ + uint32 status; + uint32 level; + UNISTR servername; + union { + PRINTER_INFO_1 **printers_1; + PRINTER_INFO_2 **printers_2; + } printer; +} SPOOL_R_ENUMPRINTERS; + + +typedef struct spool_q_getprinter +{ + PRINTER_HND handle; + uint32 level; + uint32 offered; +} SPOOL_Q_GETPRINTER; + +typedef struct spool_r_getprinter +{ + PRINTER_HND handle; + uint32 level; + + uint32 offered; + uint32 needed; + uint32 status; + union { + PRINTER_INFO_0 *info0; + PRINTER_INFO_1 *info1; + PRINTER_INFO_2 *info2; + } printer; +} SPOOL_R_GETPRINTER; + +struct s_notify_info_data_table +{ + uint16 type; + uint16 field; + char *name; + uint32 size; + void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer); +}; + +typedef struct spool_q_getprinterdriver2 +{ + PRINTER_HND handle; + UNISTR2 architecture; + uint32 level; + BUFFER buffer; + uint32 buf_size; + uint32 status; +} SPOOL_Q_GETPRINTERDRIVER2; + +typedef struct driver_info_1 +{ + UNISTR name; +} DRIVER_INFO_1; + +typedef struct driver_info_2 +{ + uint32 version; + UNISTR name; + UNISTR architecture; + UNISTR driverpath; + UNISTR datafile; + UNISTR configfile; +} DRIVER_INFO_2; + +typedef struct driver_info_3 +{ + uint32 version; + UNISTR name; + UNISTR architecture; + UNISTR driverpath; + UNISTR datafile; + UNISTR configfile; + UNISTR helpfile; + UNISTR dependentfiles; + UNISTR monitorname; + UNISTR defaultdatatype; +} DRIVER_INFO_3; + +typedef struct spool_r_getprinterdriver2 +{ + uint32 needed; + uint32 offered; + uint32 returned; + uint32 status; + uint32 level; + union { + DRIVER_INFO_1 *info1; + DRIVER_INFO_2 *info2; + DRIVER_INFO_3 *info3; + } printer; +} SPOOL_R_GETPRINTERDRIVER2; + +typedef struct add_jobinfo_1 +{ + UNISTR path; + uint32 job_number; +} ADD_JOBINFO_1; + + +typedef struct spool_q_addjob +{ + PRINTER_HND handle; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_ADDJOB; + +typedef struct spool_r_addjob +{ + uint32 status; +} SPOOL_R_ADDJOB; + +/* + * I'm really wondering how many different time formats + * I will have to cope with + * + * JFM, 09/13/98 In a mad mood ;-( +*/ +typedef struct systemtime +{ + uint16 year; + uint16 month; + uint16 dayofweek; + uint16 day; + uint16 hour; + uint16 minute; + uint16 second; + uint16 milliseconds; +} SYSTEMTIME; + +typedef struct s_job_info_1 +{ + uint32 jobid; + UNISTR printername; + UNISTR machinename; + UNISTR username; + UNISTR document; + UNISTR datatype; + UNISTR text_status; + uint32 status; + uint32 priority; + uint32 position; + uint32 totalpages; + uint32 pagesprinted; + SYSTEMTIME submitted; +} JOB_INFO_1; + +typedef struct s_job_info_2 +{ + uint32 jobid; + UNISTR printername; + UNISTR machinename; + UNISTR username; + UNISTR document; + UNISTR notifyname; + UNISTR datatype; + UNISTR printprocessor; + UNISTR parameters; + UNISTR drivername; + DEVICEMODE devmode; + UNISTR text_status; +/* SEC_DESC sec_desc;*/ + uint32 status; + uint32 priority; + uint32 position; + uint32 starttime; + uint32 untiltime; + uint32 totalpages; + uint32 size; + SYSTEMTIME submitted; + uint32 timeelapsed; + uint32 pagesprinted; +} JOB_INFO_2; + +typedef struct spool_q_enumjobs +{ + PRINTER_HND handle; + uint32 firstjob; + uint32 numofjobs; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_ENUMJOBS; + +typedef struct spool_r_enumjobs +{ + uint32 level; + union { + JOB_INFO_1 *job_info_1; + JOB_INFO_2 *job_info_2; + } job; + uint32 offered; + uint32 numofjobs; + uint32 status; +} SPOOL_R_ENUMJOBS; + +typedef struct spool_q_schedulejob +{ + PRINTER_HND handle; + uint32 jobid; +} SPOOL_Q_SCHEDULEJOB; + +typedef struct spool_r_schedulejob +{ + uint32 status; +} SPOOL_R_SCHEDULEJOB; + +typedef struct s_port_info_1 +{ + UNISTR port_name; +} PORT_INFO_1; + +typedef struct s_port_info_2 +{ + UNISTR port_name; + UNISTR monitor_name; + UNISTR description; + uint32 port_type; + uint32 reserved; +} PORT_INFO_2; + +typedef struct spool_q_enumports +{ + UNISTR2 name; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_ENUMPORTS; + +typedef struct spool_r_enumports +{ + uint32 level; + union { + PORT_INFO_1 *port_info_1; + PORT_INFO_2 *port_info_2; + } port; + uint32 offered; + uint32 numofports; + uint32 status; +} SPOOL_R_ENUMPORTS; + +#define JOB_CONTROL_PAUSE 1 +#define JOB_CONTROL_RESUME 2 +#define JOB_CONTROL_CANCEL 3 +#define JOB_CONTROL_RESTART 4 +#define JOB_CONTROL_DELETE 5 + +typedef struct spool_q_setjob +{ + PRINTER_HND handle; + uint32 jobid; + uint32 level; + union { + JOB_INFO_1 job_info_1; + JOB_INFO_2 job_info_2; + } job; + uint32 command; +} SPOOL_Q_SETJOB; + +typedef struct spool_r_setjob +{ + uint32 status; +} SPOOL_R_SETJOB; + +typedef struct spool_q_enumprinterdrivers +{ + UNISTR2 name; + UNISTR2 environment; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_ENUMPRINTERDRIVERS; + +typedef struct spool_r_enumprinterdrivers +{ + uint32 level; + union { + DRIVER_INFO_1 *driver_info_1; + DRIVER_INFO_2 *driver_info_2; + DRIVER_INFO_3 *driver_info_3; + } driver; + uint32 offered; + uint32 numofdrivers; + uint32 status; +} SPOOL_R_ENUMPRINTERDRIVERS; + +typedef struct spool_form_1 +{ + uint32 flag; + UNISTR name; + uint32 width; + uint32 length; + uint32 left; + uint32 top; + uint32 right; + uint32 bottom; +} FORM_1; + +typedef struct spool_q_enumforms +{ + PRINTER_HND handle; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_ENUMFORMS; + +typedef struct spool_r_enumforms +{ + uint32 level; + FORM_1 *forms_1; + uint32 offered; + uint32 numofforms; + uint32 status; +} SPOOL_R_ENUMFORMS; + + +typedef struct spool_printer_info_level_2 +{ + uint32 servername_ptr; + uint32 printername_ptr; + uint32 sharename_ptr; + uint32 portname_ptr; + uint32 drivername_ptr; + uint32 comment_ptr; + uint32 location_ptr; + uint32 devmode_ptr; + uint32 sepfile_ptr; + uint32 printprocessor_ptr; + uint32 datatype_ptr; + uint32 parameters_ptr; + uint32 secdesc_ptr; + uint32 attributes; + uint32 priority; + uint32 default_priority; + uint32 starttime; + uint32 untiltime; + uint32 status; + uint32 cjobs; + uint32 averageppm; + UNISTR2 servername; + UNISTR2 printername; + UNISTR2 sharename; + UNISTR2 portname; + UNISTR2 drivername; + UNISTR2 comment; + UNISTR2 location; + UNISTR2 sepfile; + UNISTR2 printprocessor; + UNISTR2 datatype; + UNISTR2 parameters; + SEC_DESC_BUF *secdesc; +} SPOOL_PRINTER_INFO_LEVEL_2; + +typedef struct spool_printer_info_level +{ + SPOOL_PRINTER_INFO_LEVEL_2 *info_2; +} SPOOL_PRINTER_INFO_LEVEL; + +typedef struct spool_printer_driver_info_level_3 +{ + uint32 cversion; + uint32 name_ptr; + uint32 environment_ptr; + uint32 driverpath_ptr; + uint32 datafile_ptr; + uint32 configfile_ptr; + uint32 helpfile_ptr; + uint32 monitorname_ptr; + uint32 defaultdatatype_ptr; + uint32 dependentfilessize; + uint32 dependentfiles_ptr; + + UNISTR2 name; + UNISTR2 environment; + UNISTR2 driverpath; + UNISTR2 datafile; + UNISTR2 configfile; + UNISTR2 helpfile; + UNISTR2 monitorname; + UNISTR2 defaultdatatype; + BUFFER5 dependentfiles; + +} SPOOL_PRINTER_DRIVER_INFO_LEVEL_3; + +typedef struct spool_printer_driver_info_level +{ + SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *info_3; +} SPOOL_PRINTER_DRIVER_INFO_LEVEL; + + +/* this struct is undocumented */ +/* thanks to the ddk ... */ +typedef struct spool_user_level_1 +{ + uint32 size; + uint32 client_name_ptr; + uint32 user_name_ptr; + uint32 build; + uint32 major; + uint32 minor; + uint32 processor; + UNISTR2 client_name; + UNISTR2 user_name; +} SPOOL_USER_LEVEL_1; + +typedef struct spool_user_level +{ + SPOOL_USER_LEVEL_1 *user_level_1; +} SPOOL_USER_LEVEL; + +typedef struct spool_q_setprinter +{ + PRINTER_HND handle; + uint32 level; + SPOOL_PRINTER_INFO_LEVEL info; + + DEVICEMODE *devmode; + struct + { + uint32 size_of_buffer; + uint32 data; + } security; + + uint32 command; +} SPOOL_Q_SETPRINTER; + +typedef struct spool_r_setprinter +{ + uint32 status; +} SPOOL_R_SETPRINTER; + +typedef struct spool_q_addprinter +{ + UNISTR2 server_name; + uint32 level; + SPOOL_PRINTER_INFO_LEVEL info; + uint32 unk0; + uint32 unk1; + uint32 unk2; + uint32 unk3; + uint32 user_level; + SPOOL_USER_LEVEL user; +} SPOOL_Q_ADDPRINTER; + +typedef struct spool_r_addprinter +{ + uint32 status; +} SPOOL_R_ADDPRINTER; + +typedef struct spool_q_addprinterex +{ + UNISTR2 server_name; + uint32 level; + SPOOL_PRINTER_INFO_LEVEL info; + uint32 unk0; + uint32 unk1; + uint32 unk2; + uint32 unk3; + uint32 user_level; + SPOOL_USER_LEVEL user; +} SPOOL_Q_ADDPRINTEREX; + + +typedef struct spool_r_addprinterex +{ + PRINTER_HND handle; + uint32 status; +} SPOOL_R_ADDPRINTEREX; + +typedef struct spool_q_addprinterdriver +{ + UNISTR2 server_name; + uint32 level; + SPOOL_PRINTER_DRIVER_INFO_LEVEL info; +} SPOOL_Q_ADDPRINTERDRIVER; + +typedef struct spool_r_addprinterdriver +{ + uint32 status; +} SPOOL_R_ADDPRINTERDRIVER; + +typedef struct spool_q_getprinterdriverdirectory +{ + UNISTR2 name; + UNISTR2 environment; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_GETPRINTERDRIVERDIR; + +typedef struct driver_directory_1 +{ + UNISTR name; +} DRIVER_DIRECTORY_1 ; + +typedef struct spool_r_getprinterdriverdirectory +{ + uint32 level; + union { + DRIVER_DIRECTORY_1 driver_info_1; + } driver; + uint32 offered; + uint32 status; +} SPOOL_R_GETPRINTERDRIVERDIR; + +typedef struct spool_q_enumprintprocessors +{ + UNISTR2 name; + UNISTR2 environment; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_ENUMPRINTPROCESSORS; + +typedef struct printprocessor_1 +{ + UNISTR name; +} PRINTPROCESSOR_1; + +typedef struct spool_r_enumprintprocessors +{ + uint32 level; + PRINTPROCESSOR_1 *info_1; + uint32 offered; + uint32 numofprintprocessors; + uint32 status; +} SPOOL_R_ENUMPRINTPROCESSORS; + +typedef struct spool_q_enumprintprocessordatatypes +{ + UNISTR2 name; + UNISTR2 printprocessor; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_ENUMPRINTPROCESSORDATATYPES; + +typedef struct ppdatatype_1 +{ + UNISTR name; +} PPDATATYPE_1; + +typedef struct spool_r_enumprintprocessordatatypes +{ + uint32 level; + PPDATATYPE_1 *info_1; + uint32 offered; + uint32 numofppdatatypes; + uint32 status; +} SPOOL_R_ENUMPRINTPROCESSORDATATYPES; + +typedef struct spool_q_enumprinterdata +{ + PRINTER_HND handle; + uint32 index; + uint32 valuesize; + uint32 datasize; +} SPOOL_Q_ENUMPRINTERDATA; + +typedef struct spool_r_enumprinterdata +{ + uint32 valuesize; + UNISTR value; + uint32 realvaluesize; + uint32 type; + uint32 datasize; + uint8 *data; + uint32 realdatasize; + uint32 status; +} SPOOL_R_ENUMPRINTERDATA; + +typedef struct spool_q_setprinterdata +{ + PRINTER_HND handle; + UNISTR2 value; + uint32 type; + uint32 max_len; + uint8 *data; + uint32 real_len; + uint32 numeric_data; +}SPOOL_Q_SETPRINTERDATA; + +typedef struct spool_r_setprinterdata +{ + uint32 status; +}SPOOL_R_SETPRINTERDATA; + +#define PRINTER_DRIVER_VERSION 2 +#define PRINTER_DRIVER_ARCHITECTURE "Windows NT x86" + + +#endif /* _RPC_SPOOLSS_H */ + diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c new file mode 100644 index 0000000000..75dd2d2551 --- /dev/null +++ b/source3/printing/nt_printing.c @@ -0,0 +1,1289 @@ +#include "includes.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + +/**************************************************************************** +parse a form line. +****************************************************************************/ +static BOOL parse_form_entry(char *line, nt_forms_struct *buf) +{ +#define NAMETOK 0 +#define FLAGTOK 1 +#define WIDTHTOK 2 +#define LENGTHTOK 3 +#define LEFTTOK 4 +#define TOPTOK 5 +#define RIGHTTOK 6 +#define BOTTOMTOK 7 +#define MAXTOK 8 + char *tok[MAXTOK]; + int count = 0; + + tok[count] = strtok(line,":"); + + /* strip the comment lines */ + if (tok[0][0]=='#') return (False); + count++; + + while ( ((tok[count] = strtok(NULL,":")) != NULL ) && count<MAXTOK-1) + { + count++; + } + + DEBUG(6,("Found [%d] tokens\n", count)); + + StrnCpy(buf->name,tok[NAMETOK],sizeof(buf->name)-1); + buf->flag=atoi(tok[FLAGTOK]); + buf->width=atoi(tok[WIDTHTOK]); + buf->length=atoi(tok[LENGTHTOK]); + buf->left=atoi(tok[LEFTTOK]); + buf->top=atoi(tok[TOPTOK]); + buf->right=atoi(tok[RIGHTTOK]); + buf->bottom=atoi(tok[BOTTOMTOK]); + + return(True); +} + +/**************************************************************************** +get a form struct list +****************************************************************************/ +int get_ntforms(nt_forms_struct **list) +{ + FILE *f; + pstring line; + char *lp_forms = lp_nt_forms(); + int total=0; + int grandtotal=0; + *line=0; + + f = sys_fopen(lp_forms,"r"); + if (!f) + { + return(0); + } + + while ( fgets(line, sizeof(pstring), f) ) + { + DEBUG(5,("%s\n",line)); + + *list = Realloc(*list, sizeof(nt_forms_struct)*(total+1)); + if (! *list) + { + total = 0; + break; + } + bzero( (char *)&(*list)[total], sizeof(nt_forms_struct) ); + if ( parse_form_entry(line, &(*list)[total] ) ) + { + total++; + } + grandtotal++; + } + fclose(f); + + DEBUG(4,("%d info lines on %d\n",total, grandtotal)); + + return(total); +} + + +/**************************************************************************** +get the nt drivers list + +open the rectory and look-up the matching names +****************************************************************************/ +int get_ntdrivers(fstring **list, char *architecture) +{ + void *dirp; + char *dpname; + fstring name_match; + fstring short_archi; + fstring driver_name; + int match_len; + int total=0; + + DEBUG(5,("Getting the driver list from directory: [%s]\n", lp_nt_drivers_file())); + + *list=NULL; + dirp = OpenDir(NULL, lp_nt_drivers_file(), False); + + if (!dirp) + { + DEBUG(0,("Error opening driver directory [%s]\n",lp_nt_drivers_file())); + return(-1); + } + + get_short_archi(short_archi, architecture); + slprintf(name_match, sizeof(name_match)-1, "NTdriver_%s_", short_archi); + match_len=strlen(name_match); + + + while ((dpname = ReadDirName(dirp)) != NULL) + { + if (strncmp(dpname, name_match, match_len)==0) + { + DEBUGADD(7,("Found: [%s]\n", dpname)); + + StrCpy(driver_name, dpname+match_len); + all_string_sub(driver_name, "#", "/"); + *list = Realloc(*list, sizeof(fstring)*(total+1)); + StrnCpy((*list)[total], driver_name, strlen(driver_name)); + DEBUGADD(6,("Added: [%s]\n", driver_name)); + total++; + } + } + + CloseDir(dirp); + return(total); +} + +/**************************************************************************** +function to do the mapping between the long architecture name and +the short one. +****************************************************************************/ +void get_short_archi(char *short_archi, char *long_archi) +{ + struct table { + char *long_archi; + char *short_archi; + }; + + struct table archi_table[]= + { + {"Windows 4.0", "" }, + {"Windows NT x86", "W32X86" }, + {"Windows NT R4000", "" }, + {"Windows NT Alpha_AXP", "" }, + {"Windows NT PowerPC", "" }, + {NULL, "" } + }; + + int i=-1; + + DEBUG(7,("Getting architecture dependant directory\n")); + do { + i++; + } while ( (archi_table[i].long_archi!=NULL ) && strncmp(long_archi, archi_table[i].long_archi, strlen(long_archi)) ); + + if (archi_table[i].long_archi==NULL) + { + DEBUGADD(7,("Unknown architecture [%s] !\n", long_archi)); + } + StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi)); + + DEBUGADD(8,("index: [%d]\n", i)); + DEBUGADD(8,("long architecture: [%s]\n", long_archi)); + DEBUGADD(8,("short architecture: [%s]\n", short_archi)); +} + +/**************************************************************************** +****************************************************************************/ +static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver) +{ + FILE *f; + pstring file; + fstring architecture; + fstring driver_name; + char **dependentfiles; + + /* create a file in the dir lp_nt_driver_file */ + /* with the full printer DRIVER name */ + /* eg: "/usr/local/samba/lib/NTdriver_HP LaserJet 6MP" */ + /* each name is really defining an *unique* printer model */ + /* I don't want to mangle the name to find it back when enumerating */ + + /* il faut substituer les / par 1 autre caractere d'abord */ + /* dans le nom de l'imprimante par un # ???*/ + + StrnCpy(driver_name, driver->name, sizeof(driver_name)-1); + + all_string_sub(driver_name, "/", "#"); + + get_short_archi(architecture, driver->environment); + + slprintf(file, sizeof(file)-1, "%s/NTdriver_%s_%s", + lp_nt_drivers_file(), architecture, driver_name); + + if((f = sys_fopen(file, "w")) == NULL) + { + DEBUG(1, ("cannot create driver file [%s]\n", file)); + return(2); + } + + /* + * cversion must be 2. + * when adding a printer ON the SERVER + * rpcAddPrinterDriver defines it to zero + * which is wrong !!! + * + * JFM, 4/14/99 + */ + driver->cversion=2; + + fprintf(f, "version: %d\n", driver->cversion); + fprintf(f, "name: %s\n", driver->name); + fprintf(f, "environment: %s\n", driver->environment); + fprintf(f, "driverpath: %s\n", driver->driverpath); + fprintf(f, "datafile: %s\n", driver->datafile); + fprintf(f, "configfile: %s\n", driver->configfile); + fprintf(f, "helpfile: %s\n", driver->helpfile); + fprintf(f, "monitorname: %s\n", driver->monitorname); + fprintf(f, "defaultdatatype: %s\n", driver->defaultdatatype); + + /* and the dependants files */ + + dependentfiles=driver->dependentfiles; + + while ( **dependentfiles != '\0' ) + { + fprintf(f, "dependentfile: %s\n", *dependentfiles); + dependentfiles++; + } + + fclose(f); + return(0); +} + +/**************************************************************************** +****************************************************************************/ +static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch) +{ + FILE *f; + pstring file; + fstring driver_name; + fstring architecture; + NT_PRINTER_DRIVER_INFO_LEVEL_3 *info; + char *line; + fstring p; + char *v; + int i=0; + char **dependentfiles=NULL; + + /* + * replace all the / by # in the driver name + * get the short architecture name + * construct the driver file name + */ + StrnCpy(driver_name, in_prt, sizeof(driver_name)-1); + all_string_sub(driver_name, "/", "#"); + + get_short_archi(architecture, in_arch); + + slprintf(file, sizeof(file)-1, "%s/NTdriver_%s_%s", + lp_nt_drivers_file(), architecture, driver_name); + + if((f = sys_fopen(file, "r")) == NULL) + { + DEBUG(2, ("cannot open printer driver file [%s]\n", file)); + return(2); + } + + /* the file exists, allocate some memory */ + info=(NT_PRINTER_DRIVER_INFO_LEVEL_3 *)malloc(sizeof(NT_PRINTER_DRIVER_INFO_LEVEL_3)); + ZERO_STRUCTP(info); + + /* allocate a 4Kbytes buffer for parsing lines */ + line=(char *)malloc(4096*sizeof(char)); + + while ( fgets(line, 4095, f) ) + { + + v=strncpyn(p, line, sizeof(p), ':'); + if (v==NULL) + { + DEBUG(1, ("malformed printer entry (no :)\n")); + continue; + } + + v++; + + trim_string(v, " ", NULL); + trim_string(v, NULL, " "); + trim_string(v, NULL, "\n"); + /* don't check if v==NULL as an empty arg is valid */ + + if (!strncmp(p, "version", strlen("version"))) + info->cversion=atoi(v); + + if (!strncmp(p, "name", strlen("name"))) + StrnCpy(info->name, v, strlen(v)); + + if (!strncmp(p, "environment", strlen("environment"))) + StrnCpy(info->environment, v, strlen(v)); + + if (!strncmp(p, "driverpath", strlen("driverpath"))) + StrnCpy(info->driverpath, v, strlen(v)); + + if (!strncmp(p, "datafile", strlen("datafile"))) + StrnCpy(info->datafile, v, strlen(v)); + + if (!strncmp(p, "configfile", strlen("configfile"))) + StrnCpy(info->configfile, v, strlen(v)); + + if (!strncmp(p, "helpfile", strlen("helpfile"))) + StrnCpy(info->helpfile, v, strlen(v)); + + if (!strncmp(p, "monitorname", strlen("monitorname"))) + StrnCpy(info->monitorname, v, strlen(v)); + + if (!strncmp(p, "defaultdatatype", strlen("defaultdatatype"))) + StrnCpy(info->defaultdatatype, v, strlen(v)); + + if (!strncmp(p, "dependentfile", strlen("dependentfile"))) + { + dependentfiles=(char **)Realloc(dependentfiles, sizeof(char *)*(i+1)); + + dependentfiles[i]=(char *)malloc( sizeof(char)* (strlen(v)+1) ); + + StrnCpy(dependentfiles[i], v, strlen(v) ); + i++; + } + + } + + free(line); + + fclose(f); + + dependentfiles=(char **)Realloc(dependentfiles, sizeof(char *)*(i+1)); + dependentfiles[i]=(char *)malloc( sizeof(char) ); + *dependentfiles[i]='\0'; + + info->dependentfiles=dependentfiles; + + *info_ptr=info; + + return (0); +} + +/**************************************************************************** +debugging function, dump at level 6 the struct in the logs +****************************************************************************/ +static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) +{ + uint32 success; + NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3; + char **dependentfiles; + + DEBUG(6,("Dumping printer driver at level [%d]\n", level)); + + switch (level) + { + case 3: + { + if (driver.info_3 == NULL) + { + DEBUGADD(3,("NULL pointer, memory not alloced ?\n")); + success=5; + } + else + { + info3=driver.info_3; + + DEBUGADD(6,("version:[%d]\n", info3->cversion)); + DEBUGADD(6,("name:[%s]\n", info3->name)); + DEBUGADD(6,("environment:[%s]\n", info3->environment)); + DEBUGADD(6,("driverpath:[%s]\n", info3->driverpath)); + DEBUGADD(6,("datafile:[%s]\n", info3->datafile)); + DEBUGADD(6,("configfile:[%s]\n", info3->configfile)); + DEBUGADD(6,("helpfile:[%s]\n", info3->helpfile)); + DEBUGADD(6,("monitorname:[%s]\n", info3->monitorname)); + DEBUGADD(6,("defaultdatatype:[%s]\n", info3->defaultdatatype)); + + dependentfiles=info3->dependentfiles; + + while ( **dependentfiles != '\0' ) + { + DEBUGADD(6,("dependentfile:[%s]\n", *dependentfiles)); + dependentfiles++; + } + success=0; + } + break; + } + default: + DEBUGADD(1,("Level not implemented\n")); + success=1; + break; + } + + return (success); +} + +/**************************************************************************** +****************************************************************************/ +static void add_a_devicemode(NT_DEVICEMODE *nt_devmode, FILE *f) +{ + int i; + + fprintf(f, "formname: %s\n", nt_devmode->formname); + fprintf(f, "specversion: %d\n", nt_devmode->specversion); + fprintf(f, "driverversion: %d\n", nt_devmode->driverversion); + fprintf(f, "size: %d\n", nt_devmode->size); + fprintf(f, "driverextra: %d\n", nt_devmode->driverextra); + fprintf(f, "fields: %d\n", nt_devmode->fields); + fprintf(f, "orientation: %d\n", nt_devmode->orientation); + fprintf(f, "papersize: %d\n", nt_devmode->papersize); + fprintf(f, "paperlength: %d\n", nt_devmode->paperlength); + fprintf(f, "paperwidth: %d\n", nt_devmode->paperwidth); + fprintf(f, "scale: %d\n", nt_devmode->scale); + fprintf(f, "copies: %d\n", nt_devmode->copies); + fprintf(f, "defaultsource: %d\n", nt_devmode->defaultsource); + fprintf(f, "printquality: %d\n", nt_devmode->printquality); + fprintf(f, "color: %d\n", nt_devmode->color); + fprintf(f, "duplex: %d\n", nt_devmode->duplex); + fprintf(f, "yresolution: %d\n", nt_devmode->yresolution); + fprintf(f, "ttoption: %d\n", nt_devmode->ttoption); + fprintf(f, "collate: %d\n", nt_devmode->collate); + fprintf(f, "icmmethod: %d\n", nt_devmode->icmmethod); + fprintf(f, "icmintent: %d\n", nt_devmode->icmintent); + fprintf(f, "mediatype: %d\n", nt_devmode->mediatype); + fprintf(f, "dithertype: %d\n", nt_devmode->dithertype); + + if (nt_devmode->private != NULL) + { + fprintf(f, "private: "); + for (i=0; i<nt_devmode->driverextra; i++) + fprintf(f, "%02X", nt_devmode->private[i]); + fprintf(f, "\n"); + } +} + +/**************************************************************************** +****************************************************************************/ +static void save_specifics(NT_PRINTER_PARAM *param, FILE *f) +{ + int i; + + while (param != NULL) + { + fprintf(f, "specific: %s#%d#%d#", param->value, param->type, param->data_len); + + for (i=0; i<param->data_len; i++) + fprintf(f, "%02X", param->data[i]); + + fprintf(f, "\n"); + + param=param->next; + } +} + +/**************************************************************************** +****************************************************************************/ +static uint32 add_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) +{ + FILE *f; + pstring file; + fstring printer_name; + NT_DEVICEMODE *nt_devmode; + + /* + * JFM: one day I'll forget. + * below that's info->portname because that's the SAMBA sharename + * and I made NT 'thinks' it's the portname + * the info->sharename is the thing you can name when you add a printer + * that's the short-name when you create shared printer for 95/98 + * So I've made a limitation in SAMBA: you can only have 1 printer model + * behind a SAMBA share. + */ + + + StrnCpy(printer_name, info->portname, sizeof(printer_name)-1); + + slprintf(file, sizeof(file)-1, "%s/NTprinter_%s", + lp_nt_drivers_file(), printer_name); + + /* create a file in the dir lp_nt_driver_file */ + /* with the full printer name */ + /* eg: "/usr/local/samba/lib/NTprinter_HP LaserJet 6MP" */ + /* each name is really defining an *unique* printer model */ + /* I don't want to mangle the name to find it back when enumerating */ + + if((f = sys_fopen(file, "w")) == NULL) + { + DEBUG(1, ("cannot create printer file [%s]\n", file)); + return(2); + } + + fprintf(f, "attributes: %d\n", info->attributes); + fprintf(f, "priority: %d\n", info->priority); + fprintf(f, "default_priority: %d\n", info->default_priority); + fprintf(f, "starttime: %d\n", info->starttime); + fprintf(f, "untiltime: %d\n", info->untiltime); + fprintf(f, "status: %d\n", info->status); + fprintf(f, "cjobs: %d\n", info->cjobs); + fprintf(f, "averageppm: %d\n", info->averageppm); + + /* + * in addprinter: no servername and the printer is the name + * in setprinter: servername is \\server + * and printer is \\server\\printer + * + * Samba manages only local printers. + * we currently don't support things like path=\\other_server\printer + */ + + if (info->servername[0]!='\0') + { + trim_string(info->printername, info->servername, NULL); + trim_string(info->printername, "\\", NULL); + info->servername[0]='\0'; + } + + fprintf(f, "servername: %s\n", info->servername); + fprintf(f, "printername: %s\n", info->printername); + fprintf(f, "sharename: %s\n", info->sharename); + fprintf(f, "portname: %s\n", info->portname); + fprintf(f, "drivername: %s\n", info->drivername); + fprintf(f, "comment: %s\n", info->comment); + fprintf(f, "location: %s\n", info->location); + fprintf(f, "sepfile: %s\n", info->sepfile); + fprintf(f, "printprocessor: %s\n", info->printprocessor); + fprintf(f, "datatype: %s\n", info->datatype); + fprintf(f, "parameters: %s\n", info->parameters); + + /* store the devmode and the private part if it exist */ + nt_devmode=info->devmode; + if (nt_devmode!=NULL) + { + add_a_devicemode(nt_devmode, f); + } + + /* and store the specific parameters */ + if (info->specific != NULL) + { + save_specifics(info->specific, f); + } + + fclose(f); + + return (0); +} + +/**************************************************************************** +fill a NT_PRINTER_PARAM from a text file + +used when reading from disk. +****************************************************************************/ +static void dissect_and_fill_a_param(NT_PRINTER_PARAM *param, char *v) +{ + char *tok[5]; + int count = 0; + + DEBUG(5,("dissect_and_fill_a_param\n")); + + tok[count] = strtok(v,"#"); + count++; + + while ( ((tok[count] = strtok(NULL,"#")) != NULL ) && count<4) + { + count++; + } + + StrnCpy(param->value, tok[0], sizeof(param->value)-1); + param->type=atoi(tok[1]); + param->data_len=atoi(tok[2]); + param->data=(uint8 *)malloc(param->data_len * sizeof(uint8)); + strhex_to_str(param->data, 2*(param->data_len), tok[3]); + param->next=NULL; + + DEBUGADD(5,("value:[%s], len:[%d]\n", param->value, param->data_len)); +} + +/**************************************************************************** +fill a NT_PRINTER_PARAM from a text file + +used when reading from disk. +****************************************************************************/ +void dump_a_param(NT_PRINTER_PARAM *param) +{ + DEBUG(5,("dump_a_param\n")); + DEBUGADD(6,("value [%s]\n", param->value)); + DEBUGADD(6,("type [%d]\n", param->type)); + DEBUGADD(6,("data len [%d]\n", param->data_len)); +} + +/**************************************************************************** +****************************************************************************/ +BOOL add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param) +{ + NT_PRINTER_PARAM *current; + + DEBUG(8,("add_a_specific_param\n")); + + param->next=NULL; + + if (info_2->specific == NULL) + { + info_2->specific=param; + } + else + { + current=info_2->specific; + while (current->next != NULL) { + current=current->next; + } + current->next=param; + } + return (True); +} + +/**************************************************************************** +****************************************************************************/ +BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param) +{ + NT_PRINTER_PARAM *current; + NT_PRINTER_PARAM *previous; + + current=info_2->specific; + previous=current; + + if (current==NULL) return (False); + + if ( !strcmp(current->value, param->value) && + (strlen(current->value)==strlen(param->value)) ) + { + DEBUG(9,("deleting first value\n")); + info_2->specific=current->next; + free(current); + DEBUG(9,("deleted first value\n")); + return (True); + } + + current=previous->next; + + while ( current!=NULL ) + { + if (!strcmp(current->value, param->value) && + strlen(current->value)==strlen(param->value) ) + { + DEBUG(9,("deleting current value\n")); + previous->next=current->next; + free(current); + DEBUG(9,("deleted current value\n")); + return(True); + } + + previous=previous->next; + current=current->next; + } + return (False); +} + +/**************************************************************************** +****************************************************************************/ +static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename) +{ + FILE *f; + pstring file; + fstring printer_name; + NT_PRINTER_INFO_LEVEL_2 *info; + NT_DEVICEMODE *nt_devmode; + NT_PRINTER_PARAM *param; + char *line; + fstring p; + char *v; + + /* + * the sharename argument is the SAMBA sharename + */ + StrnCpy(printer_name, sharename, sizeof(printer_name)-1); + + slprintf(file, sizeof(file)-1, "%s/NTprinter_%s", + lp_nt_drivers_file(), printer_name); + + if((f = sys_fopen(file, "r")) == NULL) + { + DEBUG(2, ("cannot open printer file [%s]\n", file)); + return(2); + } + + /* the file exists, allocate some memory */ + info=(NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2)); + ZERO_STRUCTP(info); + + nt_devmode=(NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE)); + ZERO_STRUCTP(nt_devmode); + init_devicemode(nt_devmode); + + info->devmode=nt_devmode; + + line=(char *)malloc(4096*sizeof(char)); + + while ( fgets(line, 4095, f) ) + { + + v=strncpyn(p, line, sizeof(p), ':'); + if (v==NULL) + { + DEBUG(1, ("malformed printer entry (no `:')\n")); + DEBUGADD(2, ("line [%s]\n", line)); + continue; + } + + v++; + + trim_string(v, " ", NULL); + trim_string(v, NULL, " "); + trim_string(v, NULL, "\n"); + + /* don't check if v==NULL as an empty arg is valid */ + + DEBUGADD(15, ("[%s]:[%s]\n", p, v)); + + /* + * The PRINTER_INFO_2 fields + */ + + if (!strncmp(p, "attributes", strlen("attributes"))) + info->attributes=atoi(v); + + if (!strncmp(p, "priority", strlen("priority"))) + info->priority=atoi(v); + + if (!strncmp(p, "default_priority", strlen("default_priority"))) + info->default_priority=atoi(v); + + if (!strncmp(p, "starttime", strlen("starttime"))) + info->starttime=atoi(v); + + if (!strncmp(p, "untiltime", strlen("untiltime"))) + info->untiltime=atoi(v); + + if (!strncmp(p, "status", strlen("status"))) + info->status=atoi(v); + + if (!strncmp(p, "cjobs", strlen("cjobs"))) + info->cjobs=atoi(v); + + if (!strncmp(p, "averageppm", strlen("averageppm"))) + info->averageppm=atoi(v); + + if (!strncmp(p, "servername", strlen("servername"))) + StrnCpy(info->servername, v, strlen(v)); + + if (!strncmp(p, "printername", strlen("printername"))) + StrnCpy(info->printername, v, strlen(v)); + + if (!strncmp(p, "sharename", strlen("sharename"))) + StrnCpy(info->sharename, v, strlen(v)); + + if (!strncmp(p, "portname", strlen("portname"))) + StrnCpy(info->portname, v, strlen(v)); + + if (!strncmp(p, "drivername", strlen("drivername"))) + StrnCpy(info->drivername, v, strlen(v)); + + if (!strncmp(p, "comment", strlen("comment"))) + StrnCpy(info->comment, v, strlen(v)); + + if (!strncmp(p, "location", strlen("location"))) + StrnCpy(info->location, v, strlen(v)); + + if (!strncmp(p, "sepfile", strlen("sepfile"))) + StrnCpy(info->sepfile, v, strlen(v)); + + if (!strncmp(p, "printprocessor", strlen("printprocessor"))) + StrnCpy(info->printprocessor, v, strlen(v)); + + if (!strncmp(p, "datatype", strlen("datatype"))) + StrnCpy(info->datatype, v, strlen(v)); + + if (!strncmp(p, "parameters", strlen("parameters"))) + StrnCpy(info->parameters, v, strlen(v)); + + /* + * The DEVICEMODE fields + */ + + if (!strncmp(p, "formname", strlen("formname"))) + StrnCpy(nt_devmode->formname, v, strlen(v)); + + if (!strncmp(p, "specversion", strlen("specversion"))) + nt_devmode->specversion=atoi(v); + + if (!strncmp(p, "driverversion", strlen("driverversion"))) + nt_devmode->driverversion=atoi(v); + + if (!strncmp(p, "size", strlen("size"))) + nt_devmode->size=atoi(v); + + if (!strncmp(p, "driverextra", strlen("driverextra"))) + nt_devmode->driverextra=atoi(v); + + if (!strncmp(p, "fields", strlen("fields"))) + nt_devmode->fields=atoi(v); + + if (!strncmp(p, "orientation", strlen("orientation"))) + nt_devmode->orientation=atoi(v); + + if (!strncmp(p, "papersize", strlen("papersize"))) + nt_devmode->papersize=atoi(v); + + if (!strncmp(p, "paperlength", strlen("paperlength"))) + nt_devmode->paperlength=atoi(v); + + if (!strncmp(p, "paperwidth", strlen("paperwidth"))) + nt_devmode->paperwidth=atoi(v); + + if (!strncmp(p, "scale", strlen("scale"))) + nt_devmode->scale=atoi(v); + + if (!strncmp(p, "copies", strlen("copies"))) + nt_devmode->copies=atoi(v); + + if (!strncmp(p, "defaultsource", strlen("defaultsource"))) + nt_devmode->defaultsource=atoi(v); + + if (!strncmp(p, "printquality", strlen("printquality"))) + nt_devmode->printquality=atoi(v); + + if (!strncmp(p, "color", strlen("color"))) + nt_devmode->color=atoi(v); + + if (!strncmp(p, "duplex", strlen("duplex"))) + nt_devmode->duplex=atoi(v); + + if (!strncmp(p, "yresolution", strlen("yresolution"))) + nt_devmode->yresolution=atoi(v); + + if (!strncmp(p, "ttoption", strlen("ttoption"))) + nt_devmode->ttoption=atoi(v); + + if (!strncmp(p, "collate", strlen("collate"))) + nt_devmode->collate=atoi(v); + + if (!strncmp(p, "icmmethod", strlen("icmmethod"))) + nt_devmode->icmmethod=atoi(v); + + if (!strncmp(p, "icmintent", strlen("icmintent"))) + nt_devmode->icmintent=atoi(v); + + if (!strncmp(p, "mediatype", strlen("mediatype"))) + nt_devmode->mediatype=atoi(v); + + if (!strncmp(p, "dithertype", strlen("dithertype"))) + nt_devmode->dithertype=atoi(v); + + if (!strncmp(p, "private", strlen("private"))) + { + nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra*sizeof(uint8)); + strhex_to_str(nt_devmode->private, 2*nt_devmode->driverextra, v); + } + + /* the specific */ + + if (!strncmp(p, "specific", strlen("specific"))) + { + param=(NT_PRINTER_PARAM *)malloc(sizeof(NT_PRINTER_PARAM)); + ZERO_STRUCTP(param); + + dissect_and_fill_a_param(param, v); + + dump_a_param(param); + + add_a_specific_param(info, param); + } + + } + fclose(f); + free(line); + + *info_ptr=info; + + return (0); +} + +/**************************************************************************** +debugging function, dump at level 6 the struct in the logs +****************************************************************************/ +static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) +{ + uint32 success; + NT_PRINTER_INFO_LEVEL_2 *info2; + + DEBUG(6,("Dumping printer at level [%d]\n", level)); + + switch (level) + { + case 2: + { + if (printer.info_2 == NULL) + { + DEBUGADD(3,("NULL pointer, memory not alloced ?\n")); + success=5; + } + else + { + info2=printer.info_2; + + DEBUGADD(6,("attributes:[%d]\n", info2->attributes)); + DEBUGADD(6,("priority:[%d]\n", info2->priority)); + DEBUGADD(6,("default_priority:[%d]\n", info2->default_priority)); + DEBUGADD(6,("starttime:[%d]\n", info2->starttime)); + DEBUGADD(6,("untiltime:[%d]\n", info2->untiltime)); + DEBUGADD(6,("status:[%d]\n", info2->status)); + DEBUGADD(6,("cjobs:[%d]\n", info2->cjobs)); + DEBUGADD(6,("averageppm:[%d]\n", info2->averageppm)); + + DEBUGADD(6,("servername:[%s]\n", info2->servername)); + DEBUGADD(6,("printername:[%s]\n", info2->printername)); + DEBUGADD(6,("sharename:[%s]\n", info2->sharename)); + DEBUGADD(6,("portname:[%s]\n", info2->portname)); + DEBUGADD(6,("drivername:[%s]\n", info2->drivername)); + DEBUGADD(6,("comment:[%s]\n", info2->comment)); + DEBUGADD(6,("location:[%s]\n", info2->location)); + DEBUGADD(6,("sepfile:[%s]\n", info2->sepfile)); + DEBUGADD(6,("printprocessor:[%s]\n", info2->printprocessor)); + DEBUGADD(6,("datatype:[%s]\n", info2->datatype)); + DEBUGADD(6,("parameters:[%s]\n", info2->parameters)); + success=0; + } + break; + } + default: + DEBUGADD(1,("Level not implemented\n")); + success=1; + break; + } + + return (success); +} + +/* + * The function below are the high level ones. + * only those ones must be called from the spoolss code. + * JFM. + */ + + +/**************************************************************************** +****************************************************************************/ +uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) +{ + uint32 success; + + dump_a_printer(printer, level); + + switch (level) + { + case 2: + { + success=add_a_printer_2(printer.info_2); + break; + } + default: + success=1; + break; + } + + return (success); +} + +/**************************************************************************** +****************************************************************************/ +uint32 get_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level, fstring sharename) +{ + uint32 success; + + switch (level) + { + case 2: + { + printer->info_2=NULL; + success=get_a_printer_2(&(printer->info_2), sharename); + break; + } + default: + success=1; + break; + } + + dump_a_printer(*printer, level); + return (success); +} + +/**************************************************************************** +****************************************************************************/ +uint32 free_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) +{ + uint32 success; + DEBUG(4,("freeing a printer at level [%d]\n", level)); + + switch (level) + { + case 2: + { + if (printer.info_2 != NULL) + { + if ((printer.info_2)->devmode != NULL) + { + DEBUG(6,("deleting DEVMODE\n")); + if ((printer.info_2)->devmode->private !=NULL ) + free((printer.info_2)->devmode->private); + free((printer.info_2)->devmode); + } + + if ((printer.info_2)->specific != NULL) + { + NT_PRINTER_PARAM *param; + NT_PRINTER_PARAM *next_param; + + param=(printer.info_2)->specific; + + while ( param != NULL) + { + next_param=param->next; + DEBUG(6,("deleting param [%s]\n", param->value)); + free(param); + param=next_param; + } + } + + free(printer.info_2); + success=0; + } + else + { + success=4; + } + break; + } + default: + success=1; + break; + } + return (success); +} + +/**************************************************************************** +****************************************************************************/ +uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) +{ + uint32 success; + DEBUG(4,("adding a printer at level [%d]\n", level)); + dump_a_printer_driver(driver, level); + + switch (level) + { + case 3: + { + success=add_a_printer_driver_3(driver.info_3); + break; + } + default: + success=1; + break; + } + + return (success); +} +/**************************************************************************** +****************************************************************************/ +uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, + fstring printername, fstring architecture) +{ + uint32 success; + + switch (level) + { + case 3: + { + success=get_a_printer_driver_3(&(driver->info_3), + printername, + architecture); + break; + } + default: + success=1; + break; + } + + dump_a_printer_driver(*driver, level); + return (success); +} + +/**************************************************************************** +****************************************************************************/ +uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) +{ + uint32 success; + + switch (level) + { + case 3: + { + if (driver.info_3 != NULL) + { + free(driver.info_3); + success=0; + } + else + { + success=4; + } + break; + } + default: + success=1; + break; + } + return (success); +} + +/**************************************************************************** +****************************************************************************/ +BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index, + fstring value, uint8 **data, uint32 *type, uint32 *len) +{ + /* right now that's enough ! */ + NT_PRINTER_PARAM *param; + int i=0; + + param=printer.info_2->specific; + + while (param != NULL && i < param_index) + { + param=param->next; + i++; + } + + if (param != NULL) + { + /* exited because it exist */ + *type=param->type; + StrnCpy(value, param->value, sizeof(value)-1); + *data=(uint8 *)malloc(param->data_len*sizeof(uint8)); + memcpy(*data, param->data, param->data_len); + *len=param->data_len; + return (True); + } + return (False); +} + +/**************************************************************************** +****************************************************************************/ +BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level, + fstring value, uint8 **data, uint32 *type, uint32 *len) +{ + /* right now that's enough ! */ + NT_PRINTER_PARAM *param; + + DEBUG(5, ("get_specific_param\n")); + + param=printer.info_2->specific; + + while (param != NULL) + { + if ( !strcmp(value, param->value) + && strlen(value)==strlen(param->value)) + break; + + param=param->next; + } + + DEBUG(6, ("found one param\n")); + if (param != NULL) + { + /* exited because it exist */ + *type=param->type; + + *data=(uint8 *)malloc(param->data_len*sizeof(uint8)); + memcpy(*data, param->data, param->data_len); + *len=param->data_len; + + DEBUG(6, ("exit of get_specific_param:true\n")); + return (True); + } + DEBUG(6, ("exit of get_specific_param:false\n")); + return (False); +} + +/**************************************************************************** +****************************************************************************/ +void init_devicemode(NT_DEVICEMODE *nt_devmode) +{ +/* + * should I init this ones ??? + nt_devmode->devicename +*/ + StrCpy(nt_devmode->formname, "A4"); + + nt_devmode->specversion = 0x0401; + nt_devmode->driverversion = 0x0400; + nt_devmode->size = 0x00DC; + nt_devmode->driverextra = 0x0000; + nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY | + DEFAULTSOURCE | COPIES | SCALE | + PAPERSIZE | ORIENTATION; + nt_devmode->orientation = 2; + nt_devmode->papersize = PAPER_A4; + nt_devmode->paperlength = 0; + nt_devmode->paperwidth = 0; + nt_devmode->scale = 0x64; + nt_devmode->copies = 01; + nt_devmode->defaultsource = BIN_FORMSOURCE; + nt_devmode->printquality = 0x0258; + nt_devmode->color = COLOR_MONOCHROME; + nt_devmode->duplex = DUP_SIMPLEX; + nt_devmode->yresolution = 0; + nt_devmode->ttoption = TT_SUBDEV; + nt_devmode->collate = COLLATE_FALSE; + nt_devmode->icmmethod = 0; + nt_devmode->icmintent = 0; + nt_devmode->mediatype = 0; + nt_devmode->dithertype = 0; + + /* non utilisés par un driver d'imprimante */ + nt_devmode->logpixels = 0; + nt_devmode->bitsperpel = 0; + nt_devmode->pelswidth = 0; + nt_devmode->pelsheight = 0; + nt_devmode->displayflags = 0; + nt_devmode->displayfrequency = 0; + nt_devmode->reserved1 = 0; + nt_devmode->reserved2 = 0; + nt_devmode->panningwidth = 0; + nt_devmode->panningheight = 0; + + nt_devmode->private=NULL; +} + +/* error code: + 0: everything OK + 1: level not implemented + 2: file doesn't exist + 3: can't allocate memory + 4: can't free memory + 5: non existant struct +*/ + +/* + A printer and a printer driver are 2 different things. + NT manages them separatelly, Samba does the same. + Why ? Simply because it's easier and it makes sense ! + + Now explanation: You have 3 printers behind your samba server, + 2 of them are the same make and model (laser A and B). But laser B + has an 3000 sheet feeder and laser A doesn't such an option. + Your third printer is an old dot-matrix model for the accounting :-). + + If the /usr/local/samba/lib directory (default dir), you will have + 5 files to describe all of this. + + 3 files for the printers (1 by printer): + NTprinter_laser A + NTprinter_laser B + NTprinter_accounting + 2 files for the drivers (1 for the laser and 1 for the dot matrix) + NTdriver_printer model X + NTdriver_printer model Y + +jfm: I should use this comment for the text file to explain + same thing for the forms BTW. + Je devrais mettre mes commentaires en francais, ca serait mieux :-) + +*/ + + diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c new file mode 100644 index 0000000000..8f5c85c158 --- /dev/null +++ b/source3/rpc_parse/parse_spoolss.c @@ -0,0 +1,3389 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Jean François Micouleau 1998. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "includes.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + + +/******************************************************************* +return the length of a UNISTR string. +********************************************************************/ +static uint32 str_len_uni(UNISTR *source) +{ + uint32 i=0; + + while (source->buffer[i]!=0x0000) + { + i++; + } + return i; +} + +/******************************************************************* +This should be moved in a more generic lib. +********************************************************************/ +static void spoolss_io_system_time(char *desc, prs_struct *ps, int depth, SYSTEMTIME *systime) +{ + prs_uint16("year", ps, depth, &(systime->year)); + prs_uint16("month", ps, depth, &(systime->month)); + prs_uint16("dayofweek", ps, depth, &(systime->dayofweek)); + prs_uint16("day", ps, depth, &(systime->day)); + prs_uint16("hour", ps, depth, &(systime->hour)); + prs_uint16("minute", ps, depth, &(systime->minute)); + prs_uint16("second", ps, depth, &(systime->second)); + prs_uint16("milliseconds", ps, depth, &(systime->milliseconds)); +} + +/******************************************************************* +********************************************************************/ +void make_systemtime(SYSTEMTIME *systime, struct tm *unixtime) +{ + systime->year=unixtime->tm_year+1900; + systime->month=unixtime->tm_mon+1; + systime->dayofweek=unixtime->tm_wday; + systime->day=unixtime->tm_mday; + systime->hour=unixtime->tm_hour; + systime->minute=unixtime->tm_min; + systime->second=unixtime->tm_sec; + systime->milliseconds=0; +} + +/******************************************************************* +reads or writes an PRINTER_HND structure. +********************************************************************/ +static void smb_io_prt_hnd(char *desc, PRINTER_HND *hnd, prs_struct *ps, int depth) +{ + if (hnd == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_prt_hnd"); + depth++; + + prs_align(ps); + + prs_uint8s (False, "data", ps, depth, hnd->data, PRINTER_HND_SIZE); +} + +/******************************************************************* +reads or writes an DOC_INFO structure. +********************************************************************/ +static void smb_io_doc_info_1(char *desc, DOC_INFO_1 *info_1, prs_struct *ps, int depth) +{ + if (info_1 == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_doc_info_1"); + depth++; + + prs_align(ps); + + prs_uint32("p_docname", ps, depth, &(info_1->p_docname)); + prs_uint32("p_outputfile", ps, depth, &(info_1->p_outputfile)); + prs_uint32("p_datatype", ps, depth, &(info_1->p_datatype)); + + if (info_1->p_docname) + smb_io_unistr2("", &(info_1->docname),True,ps,depth); + if (info_1->p_outputfile) + smb_io_unistr2("", &(info_1->outputfile),True,ps,depth); + if (info_1->p_datatype) + smb_io_unistr2("", &(info_1->datatype),True,ps,depth); +} + +/******************************************************************* +reads or writes an DOC_INFO structure. +********************************************************************/ +static void smb_io_doc_info(char *desc, DOC_INFO *info, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0; + + if (info == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_doc_info"); + depth++; + + prs_align(ps); + + prs_uint32("switch_value", ps, depth, &(info->switch_value)); + + prs_uint32("doc_info_X ptr", ps, depth, &(useless_ptr)); + + switch (info->switch_value) + { + case 1: + smb_io_doc_info_1("",&(info->doc_info_1), ps, depth); + break; + case 2: + /* + this is just a placeholder + + MSDN July 1998 says doc_info_2 is only on + Windows 95, and as Win95 doesn't do RPC to print + this case is nearly impossible + + Maybe one day with Windows for dishwasher 2037 ... + + */ + /* smb_io_doc_info_2("",&(info->doc_info_2), ps, depth); */ + break; + default: + DEBUG(0,("Something is obviously wrong somewhere !\n")); + break; + } +} + +/******************************************************************* +reads or writes an DOC_INFO_CONTAINER structure. +********************************************************************/ +static void smb_io_doc_info_container(char *desc, DOC_INFO_CONTAINER *cont, prs_struct *ps, int depth) +{ + if (cont == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_doc_info_container"); + depth++; + + prs_align(ps); + + prs_uint32("level", ps, depth, &(cont->level)); + + smb_io_doc_info("",&(cont->docinfo), ps, depth); +} + +/******************************************************************* +reads or writes an NOTIFY OPTION TYPE structure. +********************************************************************/ +static void smb_io_notify_option_type(char *desc, + SPOOL_NOTIFY_OPTION_TYPE *type, + prs_struct *ps, int depth) +{ + uint32 useless_ptr; + + prs_debug(ps, depth, desc, "smb_io_notify_option_type"); + depth++; + + prs_align(ps); + + prs_uint16("type", ps, depth, &(type->type)); + prs_uint16("reserved0", ps, depth, &(type->reserved0)); + prs_uint32("reserved1", ps, depth, &(type->reserved1)); + prs_uint32("reserved2", ps, depth, &(type->reserved2)); + prs_uint32("count", ps, depth, &(type->count)); + prs_uint32("useless ptr", ps, depth, &useless_ptr); + +} + +/******************************************************************* +reads or writes an NOTIFY OPTION TYPE DATA. +********************************************************************/ +static void smb_io_notify_option_type_data(char *desc, + SPOOL_NOTIFY_OPTION_TYPE *type, + prs_struct *ps, int depth) +{ + uint32 count; + int i; + + prs_debug(ps, depth, desc, "smb_io_notify_option_type_data"); + depth++; + + prs_align(ps); + + prs_uint32("count", ps, depth, &count); + + if (count != type->count) + { + DEBUG(4,("What a mess, count was %x now is %x !\n",type->count,count)); + type->count=count; + } + for(i=0;i<count;i++) + { + /* read the option type struct */ + prs_uint16("fields",ps,depth,&(type->fields[i])); + } +} + +/******************************************************************* +reads or writes an NOTIFY OPTION structure. +********************************************************************/ +static void smb_io_notify_option(char *desc, SPOOL_NOTIFY_OPTION *option, + prs_struct *ps, int depth) +{ + uint32 useless_ptr; + int i; + + prs_debug(ps, depth, desc, "smb_io_notify_option"); + depth++; + + prs_align(ps); + + /* memory pointer to the struct */ + prs_uint32("useless ptr", ps, depth, &useless_ptr); + + prs_uint32("version", ps, depth, &(option->version)); + prs_uint32("reserved", ps, depth, &(option->reserved)); + prs_uint32("count", ps, depth, &(option->count)); + prs_uint32("useless ptr", ps, depth, &useless_ptr); + prs_uint32("count", ps, depth, &(option->count)); + + /* read the option type struct */ + for(i=0;i<option->count;i++) + { + smb_io_notify_option_type("",&(option->type[i]) ,ps, depth); + } + + /* now read the type associated with the option type struct */ + for(i=0;i<option->count;i++) + { + smb_io_notify_option_type_data("",&(option->type[i]) ,ps, depth); + } + +} + + +/******************************************************************* +reads or writes an NOTIFY INFO DATA structure. +********************************************************************/ +static void smb_io_notify_info_data(char *desc,SPOOL_NOTIFY_INFO_DATA *data, + prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + + uint32 how_many_words; + BOOL isvalue; + uint32 x; + + prs_debug(ps, depth, desc, "smb_io_notify_info_data"); + depth++; + + how_many_words=data->size; + if (how_many_words==POINTER) + { + how_many_words=TWO_VALUE; + } + + isvalue=data->enc_type; + + prs_align(ps); + prs_uint16("type", ps, depth, &(data->type)); + prs_uint16("field", ps, depth, &(data->field)); + /*prs_align(ps);*/ + + prs_uint32("how many words", ps, depth, &how_many_words); + prs_uint32("id", ps, depth, &(data->id)); + prs_uint32("how many words", ps, depth, &how_many_words); + /*prs_align(ps);*/ + + if (isvalue==True) + { + prs_uint32("value[0]", ps, depth, &(data->notify_data.value[0])); + prs_uint32("value[1]", ps, depth, &(data->notify_data.value[1])); + /*prs_align(ps);*/ + } + else + { + /* it's a string */ + /* length in ascii including \0 */ + x=2*(data->notify_data.data.length+1); + prs_uint32("string length", ps, depth, &x ); + prs_uint32("pointer", ps, depth, &useless_ptr); + /*prs_align(ps);*/ + } +} + +/******************************************************************* +reads or writes an NOTIFY INFO DATA structure. +********************************************************************/ +void smb_io_notify_info_data_strings(char *desc,SPOOL_NOTIFY_INFO_DATA *data, + prs_struct *ps, int depth) +{ + uint32 x; + BOOL isvalue; + + prs_debug(ps, depth, desc, "smb_io_notify_info_data"); + depth++; + + prs_align(ps); + isvalue=data->enc_type; + + if (isvalue==False) + { + /* length of string in unicode include \0 */ + x=data->notify_data.data.length+1; + prs_uint32("string length", ps, depth, &x ); + prs_uint16s(True,"string",ps,depth,data->notify_data.data.string,x); + } + prs_align(ps); +} + +/******************************************************************* +reads or writes an NOTIFY INFO structure. +********************************************************************/ +static void smb_io_notify_info(char *desc, SPOOL_NOTIFY_INFO *info, + prs_struct *ps, int depth) +{ + uint32 useless_ptr=0x0001; + int i; + + info->version=0x02; + prs_debug(ps, depth, desc, "smb_io_notify_info"); + depth++; + + prs_align(ps); + + prs_uint32("pointer", ps, depth, &useless_ptr); + prs_uint32("count", ps, depth, &(info->count)); + prs_uint32("version", ps, depth, &(info->version)); + prs_uint32("flags", ps, depth, &(info->flags)); + prs_uint32("count", ps, depth, &(info->count)); + + for (i=0;i<info->count;i++) + { + prs_grow(ps); + smb_io_notify_info_data(desc, &(info->data[i]), ps, depth); + } + + /* now do the strings at the end of the stream */ + for (i=0;i<info->count;i++) + { + prs_grow(ps); + smb_io_notify_info_data_strings(desc, &(info->data[i]), + ps, depth); + } +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_open_printer (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_open_printer(char *desc, SPOOL_R_OPEN_PRINTER *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_io_r_open_printer"); + depth++; + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(r_u->handle),ps,depth); + +/* prs_align(ps);*/ + + prs_uint32("status code", ps, depth, &(r_u->status)); + +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_open_printer (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_open_printer(char *desc, SPOOL_Q_OPEN_PRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_io_q_open_printer"); + depth++; + + prs_align(ps); + + prs_uint32("unknown0", ps, depth, &(q_u->unknown0)); + smb_io_unistr2("", &(q_u->printername),True,ps,depth); + + prs_align(ps); + + prs_uint32("unknown1", ps, depth, &(q_u->unknown1)); + prs_uint32("cbbuf", ps, depth, &(q_u->cbbuf)); + prs_uint32("devmod", ps, depth, &(q_u->devmod)); + prs_uint32("access required", ps, depth, &(q_u->access_required)); + + /* don't care to decode end of packet by now */ + /* but when acl will be implemented, it will be useful */ + + prs_uint32("unknown2", ps, depth, &(q_u->unknown2)); + prs_uint32("unknown3", ps, depth, &(q_u->unknown3)); + prs_uint32("unknown4", ps, depth, &(q_u->unknown4)); + prs_uint32("unknown5", ps, depth, &(q_u->unknown5)); + prs_uint32("unknown6", ps, depth, &(q_u->unknown6)); + prs_uint32("unknown7", ps, depth, &(q_u->unknown7)); + prs_uint32("unknown8", ps, depth, &(q_u->unknown8)); + prs_uint32("unknown9", ps, depth, &(q_u->unknown9)); + prs_uint32("unknown10", ps, depth, &(q_u->unknown10)); + prs_uint32("unknown11", ps, depth, &(q_u->unknown11)); + + smb_io_unistr2("", &(q_u->station),True,ps,depth); + prs_align(ps); + smb_io_unistr2("", &(q_u->username),True,ps,depth); +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_getprinterdata (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_getprinterdata(char *desc, SPOOL_Q_GETPRINTERDATA *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_io_q_getprinterdata"); + depth++; + + prs_align(ps); + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_align(ps); + smb_io_unistr2("", &(q_u->valuename),True,ps,depth); + prs_align(ps); + prs_uint32("size", ps, depth, &(q_u->size)); +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_getprinterdata (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_getprinterdata(char *desc, SPOOL_R_GETPRINTERDATA *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_io_r_getprinterdata"); + depth++; + + prs_align(ps); + prs_uint32("type", ps, depth, &(r_u->type)); + prs_uint32("size", ps, depth, &(r_u->size)); + + switch (r_u->type) + { + case 0x1: + case 0x3: + case 0x4: + prs_uint8s(False,"data", ps, depth, r_u->data, r_u->size); + prs_align(ps); + break; + } + + prs_uint32("needed", ps, depth, &(r_u->needed)); + prs_uint32("status", ps, depth, &(r_u->status)); + prs_align(ps); +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_closeprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_closeprinter(char *desc, SPOOL_Q_CLOSEPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_io_q_closeprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_closeprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_closeprinter(char *desc, SPOOL_R_CLOSEPRINTER *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_closeprinter"); + depth++; + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(r_u->handle),ps,depth); + prs_uint32("status", ps, depth, &(r_u->status)); + +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_startdocprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_startdocprinter(char *desc, SPOOL_Q_STARTDOCPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_io_q_startdocprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + + smb_io_doc_info_container("",&(q_u->doc_info_container), ps, depth); +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_startdocprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_startdocprinter(char *desc, SPOOL_R_STARTDOCPRINTER *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_startdocprinter"); + depth++; + prs_uint32("jobid", ps, depth, &(r_u->jobid)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_enddocprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_enddocprinter(char *desc, SPOOL_Q_ENDDOCPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_io_q_enddocprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_enddocprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_enddocprinter(char *desc, SPOOL_R_ENDDOCPRINTER *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_enddocprinter"); + depth++; + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_startpageprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_startpageprinter(char *desc, SPOOL_Q_STARTPAGEPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_io_q_startpageprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_startpageprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_startpageprinter(char *desc, SPOOL_R_STARTPAGEPRINTER *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_startpageprinter"); + depth++; + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_endpageprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_endpageprinter(char *desc, SPOOL_Q_ENDPAGEPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_io_q_endpageprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_endpageprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_endpageprinter(char *desc, SPOOL_R_ENDPAGEPRINTER *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_endpageprinter"); + depth++; + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_writeprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_writeprinter(char *desc, SPOOL_Q_WRITEPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_io_q_writeprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_uint32("buffer_size", ps, depth, &(q_u->buffer_size)); + + if (q_u->buffer_size!=0) + { + q_u->buffer=(uint8 *)malloc(q_u->buffer_size*sizeof(uint8)); + prs_uint8s(True, "buffer", ps, depth, q_u->buffer, q_u->buffer_size); + } + prs_align(ps); + prs_uint32("buffer_size2", ps, depth, &(q_u->buffer_size2)); +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_writeprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_writeprinter(char *desc, SPOOL_R_WRITEPRINTER *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_writeprinter"); + depth++; + prs_uint32("buffer_written", ps, depth, &(r_u->buffer_written)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_rffpcnex (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_rffpcnex(char *desc, SPOOL_Q_RFFPCNEX *q_u, + prs_struct *ps, int depth) +{ + uint32 useless_ptr; + + prs_debug(ps, depth, desc, "spoolss_io_q_rffpcnex"); + depth++; + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_uint32("flags", ps, depth, &(q_u->flags)); + prs_uint32("options", ps, depth, &(q_u->options)); + prs_uint32("useless ptr", ps, depth, &useless_ptr); + /*prs_align(ps);*/ + + smb_io_unistr2("", &(q_u->localmachine), True, ps, depth); + + prs_align(ps); + prs_uint32("printerlocal", ps, depth, &(q_u->printerlocal)); + + smb_io_notify_option("notify option", &(q_u->option), ps, depth); + +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_rffpcnex (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_rffpcnex(char *desc, SPOOL_R_RFFPCNEX *r_u, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_rffpcnex"); + depth++; + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_rfnpcnex (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_rfnpcnex(char *desc, SPOOL_Q_RFNPCNEX *q_u, + prs_struct *ps, int depth) +{ + + prs_debug(ps, depth, desc, "spoolss_io_q_rfnpcnex"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + + prs_uint32("change", ps, depth, &(q_u->change)); + + smb_io_notify_option("notify option",&(q_u->option),ps,depth); +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_rfnpcnex (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_rfnpcnex(char *desc, + SPOOL_R_RFNPCNEX *r_u, + prs_struct *ps, int depth) +{ + uint32 x=0x0; + + prs_debug(ps, depth, desc, "spoolss_io_r_rfnpcnex"); + depth++; + + prs_align(ps); + + smb_io_notify_info("notify info",&(r_u->info),ps,depth); + prs_align(ps); + prs_uint32("status", ps, depth, &(x)); +} + +/******************************************************************* + * return the length of a uint32 (obvious, but the code is clean) + ********************************************************************/ +static uint32 size_of_uint32(uint32 *value) +{ + return (sizeof(*value)); +} + +/******************************************************************* + * return the length of a UNICODE string in number of char, includes: + * - the leading zero + * - the relative pointer size + ********************************************************************/ +static uint32 size_of_relative_string(UNISTR *string) +{ + uint32 size=0; + + size=str_len_uni(string); /* the string length */ + size=size+1; /* add the leading zero */ + size=size*2; /* convert in char */ + size=size+4; /* add the size of the ptr */ + return (size); +} + +/******************************************************************* + * return the length of a uint32 (obvious, but the code is clean) + ********************************************************************/ +static uint32 size_of_device_mode(DEVICEMODE *devmode) +{ + if (devmode==NULL) + return (4); + else + return (0xDC+4); +} + +/******************************************************************* + * return the length of a uint32 (obvious, but the code is clean) + ********************************************************************/ +static uint32 size_of_systemtime(SYSTEMTIME *systime) +{ + if (systime==NULL) + return (4); + else + return (sizeof(SYSTEMTIME) +4); +} + +/******************************************************************* + * write a UNICODE string. + * used by all the RPC structs passing a buffer + ********************************************************************/ +static void spoolss_smb_io_unistr(char *desc, UNISTR *uni, prs_struct *ps, int depth) +{ + if (uni == NULL) return; + + prs_debug(ps, depth, desc, "spoolss_smb_io_unistr"); + depth++; + prs_unistr("unistr", ps, depth, uni); +} + + +/******************************************************************* + * write a UNICODE string and its relative pointer. + * used by all the RPC structs passing a buffer + ********************************************************************/ +static void smb_io_relstr(char *desc, prs_struct *ps, int depth, UNISTR *buffer, + uint32 *start_offset, uint32 *end_offset) +{ + uint32 struct_offset; + uint32 relative_offset; + + struct_offset=ps->offset; + *end_offset-= 2*(str_len_uni(buffer)+1); + ps->offset=*end_offset; + spoolss_smb_io_unistr(desc, buffer, ps, depth); + + ps->offset=struct_offset; + relative_offset=*end_offset-*start_offset; + + prs_uint32("offset", ps, depth, &(relative_offset)); +} + +/******************************************************************* + * write a DEVICEMODE struct. + * on reading allocate memory for the private member + ********************************************************************/ +static void smb_io_devmode(char *desc, prs_struct *ps, int depth, DEVICEMODE *devmode) +{ + prs_debug(ps, depth, desc, "smb_io_devmode"); + depth++; + + prs_uint16s(True,"devicename", ps, depth, devmode->devicename.buffer, 32); + prs_uint16("specversion", ps, depth, &(devmode->specversion)); + prs_uint16("driverversion", ps, depth, &(devmode->driverversion)); + prs_uint16("size", ps, depth, &(devmode->size)); + prs_uint16("driverextra", ps, depth, &(devmode->driverextra)); + prs_uint32("fields", ps, depth, &(devmode->fields)); + prs_uint16("orientation", ps, depth, &(devmode->orientation)); + prs_uint16("papersize", ps, depth, &(devmode->papersize)); + prs_uint16("paperlength", ps, depth, &(devmode->paperlength)); + prs_uint16("paperwidth", ps, depth, &(devmode->paperwidth)); + prs_uint16("scale", ps, depth, &(devmode->scale)); + prs_uint16("copies", ps, depth, &(devmode->copies)); + prs_uint16("defaultsource", ps, depth, &(devmode->defaultsource)); + prs_uint16("printquality", ps, depth, &(devmode->printquality)); + prs_uint16("color", ps, depth, &(devmode->color)); + prs_uint16("duplex", ps, depth, &(devmode->duplex)); + prs_uint16("yresolution", ps, depth, &(devmode->yresolution)); + prs_uint16("ttoption", ps, depth, &(devmode->ttoption)); + prs_uint16("collate", ps, depth, &(devmode->collate)); + prs_uint16s(True, "formname", ps, depth, devmode->formname.buffer, 32); + prs_uint16("logpixels", ps, depth, &(devmode->logpixels)); + prs_uint32("bitsperpel", ps, depth, &(devmode->bitsperpel)); + prs_uint32("pelswidth", ps, depth, &(devmode->pelswidth)); + prs_uint32("pelsheight", ps, depth, &(devmode->pelsheight)); + prs_uint32("displayflags", ps, depth, &(devmode->displayflags)); + prs_uint32("displayfrequency", ps, depth, &(devmode->displayfrequency)); + prs_uint32("icmmethod", ps, depth, &(devmode->icmmethod)); + prs_uint32("icmintent", ps, depth, &(devmode->icmintent)); + prs_uint32("mediatype", ps, depth, &(devmode->mediatype)); + prs_uint32("dithertype", ps, depth, &(devmode->dithertype)); + prs_uint32("reserved1", ps, depth, &(devmode->reserved1)); + prs_uint32("reserved2", ps, depth, &(devmode->reserved2)); + prs_uint32("panningwidth", ps, depth, &(devmode->panningwidth)); + prs_uint32("panningheight", ps, depth, &(devmode->panningheight)); + + if (devmode->driverextra!=0) + { + if (ps->io) + { + devmode->private=(uint8 *)malloc(devmode->driverextra*sizeof(uint8)); + DEBUG(7,("smb_io_devmode: allocated memory [%d] for private\n",devmode->driverextra)); + } + DEBUG(7,("smb_io_devmode: parsing [%d] bytes of private\n",devmode->driverextra)); + + prs_uint8s(True, "private", ps, depth, devmode->private, devmode->driverextra); + DEBUG(8,("smb_io_devmode: parsed\n")); + } +} + +/******************************************************************* + * write a DEVMODE struct and its relative pointer. + * used by all the RPC structs passing a buffer + ********************************************************************/ +static void smb_io_reldevmode(char *desc, prs_struct *ps, int depth, DEVICEMODE *devmode, + uint32 *start_offset, uint32 *end_offset) +{ + uint32 struct_offset; + uint32 relative_offset; + + prs_debug(ps, depth, desc, "smb_io_reldevmode"); + depth++; + + struct_offset=ps->offset; + *end_offset-= (devmode->size+devmode->driverextra); + ps->offset=*end_offset; + + smb_io_devmode(desc, ps, depth, devmode); + + ps->offset=struct_offset; + relative_offset=*end_offset-*start_offset; + + prs_uint32("offset", ps, depth, &(relative_offset)); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_printer_info_0(char *desc, PRINTER_INFO_0 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_printer_info_0"); + depth++; + *start_offset=ps->offset; + + smb_io_relstr("printername",ps, depth, &(info->printername), start_offset, end_offset); + smb_io_relstr("servername",ps, depth, &(info->servername), start_offset, end_offset); + prs_uint32("cjobs", ps, depth, &(info->cjobs)); + prs_uint32("attributes", ps, depth, &(info->attributes)); + + prs_uint32("unknown0", ps, depth, &(info->unknown0)); + prs_uint32("unknown1", ps, depth, &(info->unknown1)); + prs_uint32("unknown2", ps, depth, &(info->unknown2)); + prs_uint32("unknown3", ps, depth, &(info->unknown3)); + prs_uint32("unknown4", ps, depth, &(info->unknown4)); + prs_uint32("unknown5", ps, depth, &(info->unknown5)); + prs_uint32("unknown6", ps, depth, &(info->unknown6)); + prs_uint16("majorversion", ps, depth, &(info->majorversion)); + prs_uint16("buildversion", ps, depth, &(info->buildversion)); + prs_uint32("unknown7", ps, depth, &(info->unknown7)); + prs_uint32("unknown8", ps, depth, &(info->unknown8)); + prs_uint32("unknown9", ps, depth, &(info->unknown9)); + prs_uint32("unknown10", ps, depth, &(info->unknown10)); + prs_uint32("unknown11", ps, depth, &(info->unknown11)); + prs_uint32("unknown12", ps, depth, &(info->unknown12)); + prs_uint32("unknown13", ps, depth, &(info->unknown13)); + prs_uint32("unknown14", ps, depth, &(info->unknown14)); + prs_uint32("unknown15", ps, depth, &(info->unknown15)); + prs_uint32("unknown16", ps, depth, &(info->unknown16)); + prs_uint32("unknown17", ps, depth, &(info->unknown17)); + prs_uint32("unknown18", ps, depth, &(info->unknown18)); + prs_uint32("status" , ps, depth, &(info->status)); + prs_uint32("unknown20", ps, depth, &(info->unknown20)); + prs_uint32("unknown21", ps, depth, &(info->unknown21)); + prs_uint16("unknown22", ps, depth, &(info->unknown22)); + prs_uint32("unknown23", ps, depth, &(info->unknown23)); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_printer_info_1(char *desc, PRINTER_INFO_1 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_printer_info_1"); + depth++; + *start_offset=ps->offset; + + prs_uint32("flags", ps, depth, &(info->flags)); + smb_io_relstr("description",ps, depth, &(info->description), start_offset, end_offset); + smb_io_relstr("name",ps, depth, &(info->name), start_offset, end_offset); + smb_io_relstr("comment",ps, depth, &(info->comment), start_offset, end_offset); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_printer_info_2(char *desc, PRINTER_INFO_2 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + uint32 pipo=0; + + prs_debug(ps, depth, desc, "smb_io_printer_info_2"); + depth++; + *start_offset=ps->offset; + + smb_io_relstr("servername", ps, depth, &(info->servername), start_offset, end_offset); + smb_io_relstr("printername", ps, depth, &(info->printername), start_offset, end_offset); + smb_io_relstr("sharename", ps, depth, &(info->sharename), start_offset, end_offset); + smb_io_relstr("portname", ps, depth, &(info->portname), start_offset, end_offset); + smb_io_relstr("drivername", ps, depth, &(info->drivername), start_offset, end_offset); + smb_io_relstr("comment", ps, depth, &(info->comment), start_offset, end_offset); + smb_io_relstr("location", ps, depth, &(info->location), start_offset, end_offset); + + smb_io_reldevmode("devmode", ps, depth, info->devmode, start_offset, end_offset); + + smb_io_relstr("sepfile", ps, depth, &(info->sepfile), start_offset, end_offset); + smb_io_relstr("printprocessor",ps, depth, &(info->printprocessor), start_offset, end_offset); + smb_io_relstr("datatype", ps, depth, &(info->datatype), start_offset, end_offset); + smb_io_relstr("parameters", ps, depth, &(info->parameters), start_offset, end_offset); + + prs_uint32("security descriptor", ps, depth, &(pipo)); + + prs_uint32("attributes", ps, depth, &(info->attributes)); + prs_uint32("priority", ps, depth, &(info->priority)); + prs_uint32("defpriority", ps, depth, &(info->defaultpriority)); + prs_uint32("starttime", ps, depth, &(info->starttime)); + prs_uint32("untiltime", ps, depth, &(info->untiltime)); + prs_uint32("status", ps, depth, &(info->status)); + prs_uint32("jobs", ps, depth, &(info->cjobs)); + prs_uint32("averageppm", ps, depth, &(info->averageppm)); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_printer_driver_info_1(char *desc, DRIVER_INFO_1 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_printer_driver_info_1"); + depth++; + *start_offset=ps->offset; + + smb_io_relstr("name", ps, depth, &(info->name), start_offset, end_offset); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_printer_driver_info_2(char *desc, DRIVER_INFO_2 *info,prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_printer_xxx"); + depth++; + *start_offset=ps->offset; + + prs_uint32("version", ps, depth, &(info->version)); + smb_io_relstr("name", ps, depth, &(info->name), start_offset, end_offset); + smb_io_relstr("architecture", ps, depth, &(info->architecture), start_offset, end_offset); + smb_io_relstr("driverpath", ps, depth, &(info->driverpath), start_offset, end_offset); + smb_io_relstr("datafile", ps, depth, &(info->datafile), start_offset, end_offset); + smb_io_relstr("configfile", ps, depth, &(info->configfile), start_offset, end_offset); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_printer_driver_info_3(char *desc, DRIVER_INFO_3 *info,prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_printer_driver_info_3"); + depth++; + *start_offset=ps->offset; + + prs_uint32("version", ps, depth, &(info->version)); + smb_io_relstr("name", ps, depth, &(info->name), start_offset, end_offset); + smb_io_relstr("architecture", ps, depth, &(info->architecture), start_offset, end_offset); + smb_io_relstr("driverpath", ps, depth, &(info->driverpath), start_offset, end_offset); + smb_io_relstr("datafile", ps, depth, &(info->datafile), start_offset, end_offset); + smb_io_relstr("configfile", ps, depth, &(info->configfile), start_offset, end_offset); + smb_io_relstr("helpfile", ps, depth, &(info->helpfile), start_offset, end_offset); + smb_io_relstr("dependentfiles", ps, depth, &(info->dependentfiles), start_offset, end_offset); + smb_io_relstr("monitorname", ps, depth, &(info->monitorname), start_offset, end_offset); + smb_io_relstr("defaultdatatype", ps, depth, &(info->defaultdatatype), start_offset, end_offset); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_job_info_1(char *desc, JOB_INFO_1 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_job_info_1"); + depth++; + *start_offset=ps->offset; + + prs_uint32("jobid", ps, depth, &(info->jobid)); + smb_io_relstr("printername",ps, depth, &(info->printername), start_offset, end_offset); + smb_io_relstr("machinename",ps, depth, &(info->machinename), start_offset, end_offset); + smb_io_relstr("username",ps, depth, &(info->username), start_offset, end_offset); + smb_io_relstr("document",ps, depth, &(info->document), start_offset, end_offset); + smb_io_relstr("datatype",ps, depth, &(info->datatype), start_offset, end_offset); + smb_io_relstr("text_status",ps, depth, &(info->text_status), start_offset, end_offset); + prs_uint32("status", ps, depth, &(info->status)); + prs_uint32("priority", ps, depth, &(info->priority)); + prs_uint32("position", ps, depth, &(info->position)); + prs_uint32("totalpages", ps, depth, &(info->totalpages)); + prs_uint32("pagesprinted", ps, depth, &(info->pagesprinted)); + spoolss_io_system_time("submitted", ps, depth, &(info->submitted) ); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_job_info_2(char *desc, JOB_INFO_2 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + int pipo=0; + prs_debug(ps, depth, desc, "smb_io_job_info_2"); + depth++; + *start_offset=ps->offset; + + prs_uint32("jobid", ps, depth, &(info->jobid)); + smb_io_relstr("printername",ps, depth, &(info->printername), start_offset, end_offset); + smb_io_relstr("machinename",ps, depth, &(info->machinename), start_offset, end_offset); + smb_io_relstr("username",ps, depth, &(info->username), start_offset, end_offset); + smb_io_relstr("document",ps, depth, &(info->document), start_offset, end_offset); + smb_io_relstr("notifyname",ps, depth, &(info->notifyname), start_offset, end_offset); + smb_io_relstr("datatype",ps, depth, &(info->datatype), start_offset, end_offset); + + smb_io_relstr("printprocessor",ps, depth, &(info->printprocessor), start_offset, end_offset); + smb_io_relstr("parameters",ps, depth, &(info->parameters), start_offset, end_offset); + smb_io_relstr("drivername",ps, depth, &(info->drivername), start_offset, end_offset); + smb_io_reldevmode("devmode", ps, depth, &(info->devmode), start_offset, end_offset); + smb_io_relstr("text_status",ps, depth, &(info->text_status), start_offset, end_offset); + +/* SEC_DESC sec_desc;*/ + prs_uint32("Hack! sec desc", ps, depth, &pipo); + + prs_uint32("status", ps, depth, &(info->status)); + prs_uint32("priority", ps, depth, &(info->priority)); + prs_uint32("position", ps, depth, &(info->position)); + prs_uint32("starttime", ps, depth, &(info->starttime)); + prs_uint32("untiltime", ps, depth, &(info->untiltime)); + prs_uint32("totalpages", ps, depth, &(info->totalpages)); + prs_uint32("size", ps, depth, &(info->size)); + spoolss_io_system_time("submitted", ps, depth, &(info->submitted) ); + prs_uint32("timeelapsed", ps, depth, &(info->timeelapsed)); + prs_uint32("pagesprinted", ps, depth, &(info->pagesprinted)); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_form_1(char *desc, FORM_1 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_form_1"); + depth++; + *start_offset=ps->offset; + + prs_uint32("flag", ps, depth, &(info->flag)); + smb_io_relstr("name",ps, depth, &(info->name), start_offset, end_offset); + prs_uint32("width", ps, depth, &(info->width)); + prs_uint32("length", ps, depth, &(info->length)); + prs_uint32("left", ps, depth, &(info->left)); + prs_uint32("top", ps, depth, &(info->top)); + prs_uint32("right", ps, depth, &(info->right)); + prs_uint32("bottom", ps, depth, &(info->bottom)); +} + +/******************************************************************* +********************************************************************/ +static void smb_io_port_2(char *desc, PORT_INFO_2 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_form_1"); + depth++; + *start_offset=ps->offset; + + smb_io_relstr("port_name",ps, depth, &(info->port_name), start_offset, end_offset); + smb_io_relstr("monitor_name",ps, depth, &(info->monitor_name), start_offset, end_offset); + smb_io_relstr("description",ps, depth, &(info->description), start_offset, end_offset); + prs_uint32("port_type", ps, depth, &(info->port_type)); + prs_uint32("reserved", ps, depth, &(info->reserved)); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_printer_info_0(PRINTER_INFO_0 *info) +{ + int size=0; + + size+=size_of_uint32( &(info->attributes) ); + size+=size_of_relative_string( &(info->printername) ); + size+=size_of_relative_string( &(info->servername) ); + return (size); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_printer_info_1(PRINTER_INFO_1 *info) +{ + int size=0; + + size+=size_of_uint32( &(info->flags) ); + size+=size_of_relative_string( &(info->description) ); + size+=size_of_relative_string( &(info->name) ); + size+=size_of_relative_string( &(info->comment) ); + return (size); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_printer_info_2(PRINTER_INFO_2 *info) +{ + int size=0; + + size+=4; /* the security descriptor */ + size+=0xDC+4; /* size of the devmode and the ptr */ + + size+=size_of_relative_string( &(info->servername) ); + size+=size_of_relative_string( &(info->printername) ); + size+=size_of_relative_string( &(info->sharename) ); + size+=size_of_relative_string( &(info->portname) ); + size+=size_of_relative_string( &(info->drivername) ); + size+=size_of_relative_string( &(info->comment) ); + size+=size_of_relative_string( &(info->location) ); + + size+=size_of_relative_string( &(info->sepfile) ); + size+=size_of_relative_string( &(info->printprocessor) ); + size+=size_of_relative_string( &(info->datatype) ); + size+=size_of_relative_string( &(info->parameters) ); + + size+=size_of_uint32( &(info->attributes) ); + size+=size_of_uint32( &(info->priority) ); + size+=size_of_uint32( &(info->defaultpriority) ); + size+=size_of_uint32( &(info->starttime) ); + size+=size_of_uint32( &(info->untiltime) ); + size+=size_of_uint32( &(info->status) ); + size+=size_of_uint32( &(info->cjobs) ); + size+=size_of_uint32( &(info->averageppm) ); + return (size); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_printer_driver_info_1(DRIVER_INFO_1 *info) +{ + int size=0; + DEBUG(9,("Sizing driver info_1\n")); + size+=size_of_relative_string( &(info->name) ); + + DEBUGADD(9,("size: [%d]\n", size)); + return (size); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_printer_driver_info_2(DRIVER_INFO_2 *info) +{ + int size=0; + DEBUG(9,("Sizing driver info_2\n")); + size+=size_of_uint32( &(info->version) ); + size+=size_of_relative_string( &(info->name) ); + size+=size_of_relative_string( &(info->architecture) ); + size+=size_of_relative_string( &(info->driverpath) ); + size+=size_of_relative_string( &(info->datafile) ); + size+=size_of_relative_string( &(info->configfile) ); + + DEBUGADD(9,("size: [%d]\n", size)); + return (size); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_printer_driver_info_3(DRIVER_INFO_3 *info) +{ + int size=0; + DEBUG(9,("Sizing driver info_3\n")); + size+=size_of_uint32( &(info->version) ); + size+=size_of_relative_string( &(info->name) ); + size+=size_of_relative_string( &(info->architecture) ); + size+=size_of_relative_string( &(info->driverpath) ); + size+=size_of_relative_string( &(info->datafile) ); + size+=size_of_relative_string( &(info->configfile) ); + size+=size_of_relative_string( &(info->helpfile) ); + size+=size_of_relative_string( &(info->dependentfiles) ); + size+=size_of_relative_string( &(info->monitorname) ); + size+=size_of_relative_string( &(info->defaultdatatype) ); + + DEBUGADD(9,("size: [%d]\n", size)); + return (size); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_job_info_1(JOB_INFO_1 *info) +{ + int size=0; + size+=size_of_uint32( &(info->jobid) ); + size+=size_of_relative_string( &(info->printername) ); + size+=size_of_relative_string( &(info->machinename) ); + size+=size_of_relative_string( &(info->username) ); + size+=size_of_relative_string( &(info->document) ); + size+=size_of_relative_string( &(info->datatype) ); + size+=size_of_relative_string( &(info->text_status) ); + size+=size_of_uint32( &(info->status) ); + size+=size_of_uint32( &(info->priority) ); + size+=size_of_uint32( &(info->position) ); + size+=size_of_uint32( &(info->totalpages) ); + size+=size_of_uint32( &(info->pagesprinted) ); + size+=size_of_systemtime( &(info->submitted) ); + return (size); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_job_info_2(JOB_INFO_2 *info) +{ + int size=0; + + size+=4; /* size of sec desc ptr */ + + size+=size_of_uint32( &(info->jobid) ); + size+=size_of_relative_string( &(info->printername) ); + size+=size_of_relative_string( &(info->machinename) ); + size+=size_of_relative_string( &(info->username) ); + size+=size_of_relative_string( &(info->document) ); + size+=size_of_relative_string( &(info->notifyname) ); + size+=size_of_relative_string( &(info->datatype) ); + size+=size_of_relative_string( &(info->printprocessor) ); + size+=size_of_relative_string( &(info->parameters) ); + size+=size_of_relative_string( &(info->drivername) ); + size+=size_of_device_mode( &(info->devmode) ); + size+=size_of_relative_string( &(info->text_status) ); +/* SEC_DESC sec_desc;*/ + size+=size_of_uint32( &(info->status) ); + size+=size_of_uint32( &(info->priority) ); + size+=size_of_uint32( &(info->position) ); + size+=size_of_uint32( &(info->starttime) ); + size+=size_of_uint32( &(info->untiltime) ); + size+=size_of_uint32( &(info->totalpages) ); + size+=size_of_uint32( &(info->size) ); + size+=size_of_systemtime( &(info->submitted) ); + size+=size_of_uint32( &(info->timeelapsed) ); + size+=size_of_uint32( &(info->pagesprinted) ); + return (size); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_form_1(FORM_1 *info) +{ + int size=0; + + size+=size_of_uint32( &(info->flag) ); + size+=size_of_relative_string( &(info->name) ); + size+=size_of_uint32( &(info->width) ); + size+=size_of_uint32( &(info->length) ); + size+=size_of_uint32( &(info->left) ); + size+=size_of_uint32( &(info->top) ); + size+=size_of_uint32( &(info->right) ); + size+=size_of_uint32( &(info->bottom) ); + + return (size); +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_port_info_2(PORT_INFO_2 *info) +{ + int size=0; + + size+=size_of_relative_string( &(info->port_name) ); + size+=size_of_relative_string( &(info->monitor_name) ); + size+=size_of_relative_string( &(info->description) ); + + size+=size_of_uint32( &(info->port_type) ); + size+=size_of_uint32( &(info->reserved) ); + + return (size); +} + +/******************************************************************* + * read a uint8 buffer of size *size. + * allocate memory for it + * return a pointer to the allocated memory and the size + * return NULL and a size of 0 if the buffer is empty + * + * jfmxxxx: fix it to also write a buffer + ********************************************************************/ +static void spoolss_io_read_buffer(char *desc, prs_struct *ps, int depth, BUFFER *buffer) +{ + prs_debug(ps, depth, desc, "spoolss_io_read_buffer"); + depth++; + + prs_align(ps); + + prs_uint32("pointer", ps, depth, &(buffer->ptr)); + + if (buffer->ptr != 0x0000) + { + prs_uint32("size", ps, depth, &(buffer->size)); + buffer->data=(uint8 *)malloc( (buffer->size) * sizeof(uint8) ); + prs_uint8s(True,"buffer", ps, depth, buffer->data, buffer->size); + prs_align(ps); + + } + else + { + buffer->data=0x0000; + buffer->size=0x0000; + } +} + + +/******************************************************************* + * read a structure. + * called from spoolss_getprinterdriver2 (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_getprinterdriver2(char *desc, + SPOOL_Q_GETPRINTERDRIVER2 *q_u, + prs_struct *ps, int depth) +{ + uint32 useless_ptr; + prs_debug(ps, depth, desc, "spoolss_io_q_getprinterdriver2"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_uint32("pointer", ps, depth, &useless_ptr); + smb_io_unistr2("architecture", &(q_u->architecture),True,ps,depth); + + prs_align(ps); + + prs_uint32("level", ps, depth, &(q_u->level)); + spoolss_io_read_buffer("", ps, depth, &(q_u->buffer)); + + prs_align(ps); + + prs_uint32("buffer size", ps, depth, &(q_u->buf_size)); + prs_uint32("status", ps, depth, &(q_u->status)); + +} + +/******************************************************************* + * read a structure. + * called from spoolss_getprinterdriver2 (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_r_getprinterdriver2(char *desc, SPOOL_R_GETPRINTERDRIVER2 *r_u, + prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + uint32 pipo=0; + DRIVER_INFO_1 *info1; + DRIVER_INFO_2 *info2; + DRIVER_INFO_3 *info3; + + prs_debug(ps, depth, desc, "spoolss_io_r_getprinterdriver2"); + depth++; + + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + + info1 = r_u->printer.info1; + info2 = r_u->printer.info2; + info3 = r_u->printer.info3; + + switch (r_u->level) + { + case 1: + { + bufsize_required += spoolss_size_printer_driver_info_1(info1); + break; + } + case 2: + { + bufsize_required += spoolss_size_printer_driver_info_2(info2); + break; + } + case 3: + { + bufsize_required += spoolss_size_printer_driver_info_3(info3); + break; + } + } + + DEBUG(4,("spoolss_io_r_getprinterdriver2, size needed: %d\n",bufsize_required)); + DEBUG(4,("spoolss_io_r_getprinterdriver2, size offered: %d\n",r_u->offered)); + + /* check if the buffer is big enough for the datas */ + if (r_u->offered<bufsize_required) + { + /* it's too small */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; /* say so */ + r_u->offered=0; /* don't send back the buffer */ + + DEBUG(4,("spoolss_io_r_getprinterdriver2, buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUG(4,("spoolss_io_r_getprinterdriver2, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + smb_io_printer_driver_info_1(desc, + info1, + ps, + depth, + &start_offset, + &end_offset); + break; + } + case 2: + { + smb_io_printer_driver_info_2(desc, + info2, + ps, + depth, + &start_offset, + &end_offset); + break; + } + case 3: + { + smb_io_printer_driver_info_3(desc, + info3, + ps, + depth, + &start_offset, + &end_offset); + break; + } + + } + + ps->offset=beginning+r_u->offered; + prs_align(ps); + } + + /* + * if the buffer was too small, send the minimum required size + * if it was too large, send the real needed size + */ + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("pipo", ps, depth, &pipo); + prs_uint32("pipo", ps, depth, &pipo); + prs_uint32("status", ps, depth, &(r_u->status)); + +} + +/******************************************************************* + * read a structure. + * called from spoolss_enumprinters (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_enumprinters(char *desc, SPOOL_Q_ENUMPRINTERS *q_u, + prs_struct *ps, int depth) +{ + uint32 useless_ptr; + prs_debug(ps, depth, desc, "spoolss_io_q_enumprinters"); + depth++; + + prs_align(ps); + + prs_uint32("flags", ps, depth, &(q_u->flags)); + + prs_uint32("useless ptr", ps, depth, &useless_ptr); + + smb_io_unistr2("", &(q_u->servername),True,ps,depth); + + prs_align(ps); + + prs_uint32("level", ps, depth, &(q_u->level)); + + spoolss_io_read_buffer("buffer", ps, depth, &(q_u->buffer)); +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_enum_printers (srv_spoolss.c) + * + ********************************************************************/ +void spoolss_io_r_enumprinters(char *desc, + SPOOL_R_ENUMPRINTERS *r_u, + prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + int i; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + + PRINTER_INFO_1 *info1; + PRINTER_INFO_2 *info2; + + prs_debug(ps, depth, desc, "spoolss_io_r_enumprinters"); + depth++; + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + + for(i=0;i<r_u->returned;i++) + { + switch (r_u->level) + { + case 1: + info1 = r_u->printer.printers_1[i]; + bufsize_required += spoolss_size_printer_info_1(info1); + break; + case 2: + info2 = r_u->printer.printers_2[i]; + bufsize_required += spoolss_size_printer_info_2(info2); + break; + } + } + + DEBUG(4,("spoolss_io_r_enumprinters, size needed: %d\n",bufsize_required)); + DEBUG(4,("spoolss_io_r_enumprinters, size offered: %d\n",r_u->offered)); + + if (r_u->offered<bufsize_required) + { + /* + * so the buffer is too small to handle datas + * reply the minimum size required in the status + * make the buffer equal 0 + * and reply no printers in buffer + */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; + r_u->offered=0; + /*r_u->returned=0;*/ + + DEBUG(4,("spoolss_io_r_enumprinters, buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("count", ps, depth, &(r_u->returned)); + prs_uint32("status", ps, depth, &(r_u->status)); + return; + } + + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUG(4,("spoolss_io_r_enumprinters, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + for(i=0;i<r_u->returned;i++) + { + switch (r_u->level) + { + case 1: + info1=r_u->printer.printers_1[i]; + smb_io_printer_info_1(desc, info1, ps, depth, + &start_offset, &end_offset); + break; + case 2: + info2=r_u->printer.printers_2[i]; + smb_io_printer_info_2(desc, info2, ps, depth, + &start_offset, &end_offset); + break; + } + } + + ps->offset=beginning+r_u->offered; + prs_align(ps); + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("count", ps, depth, &(r_u->returned)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_enum_printers (srv_spoolss.c) + * + ********************************************************************/ +void spoolss_io_r_getprinter(char *desc, + SPOOL_R_GETPRINTER *r_u, + prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + + prs_debug(ps, depth, desc, "spoolss_io_r_getprinter"); + depth++; + + prs_align(ps); + + prs_uint32("pointer", ps, depth, &useless_ptr); + + switch (r_u->level) + { + case 0: + { + PRINTER_INFO_0 *info; + info = r_u->printer.info0; + bufsize_required += spoolss_size_printer_info_0(info); + break; + } + case 1: + { + PRINTER_INFO_1 *info; + info = r_u->printer.info1; + bufsize_required += spoolss_size_printer_info_1(info); + break; + } + case 2: + { + PRINTER_INFO_2 *info; + info = r_u->printer.info2; + bufsize_required += spoolss_size_printer_info_2(info); + break; + } + } + + DEBUG(4,("spoolss_io_r_getprinter, size needed: %d\n",bufsize_required)); + DEBUG(4,("spoolss_io_r_getprinter, size offered: %d\n",r_u->offered)); + + /* check if the buffer is big enough for the datas */ + if (r_u->offered<bufsize_required) + { + /* it's too small */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; /* say so */ + r_u->offered=0; /* don't send back the buffer */ + + DEBUG(4,("spoolss_io_r_getprinter, buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUG(4,("spoolss_io_r_getprinter, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 0: + { + PRINTER_INFO_0 *info; + info = r_u->printer.info0; + smb_io_printer_info_0(desc, + info, + ps, + depth, + &start_offset, + &end_offset); + break; + } + case 1: + { + PRINTER_INFO_1 *info; + info = r_u->printer.info1; + smb_io_printer_info_1(desc, + info, + ps, + depth, + &start_offset, + &end_offset); + break; + } + case 2: + { + PRINTER_INFO_2 *info; + info = r_u->printer.info2; + smb_io_printer_info_2(desc, + info, + ps, + depth, + &start_offset, + &end_offset); + break; + } + + } + + ps->offset=beginning+r_u->offered; + prs_align(ps); + } + + /* + * if the buffer was too small, send the minimum required size + * if it was too large, send the real needed size + */ + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("status", ps, depth, &(r_u->status)); + +} + +/******************************************************************* + * read a uint8 buffer of size *size. + * allocate memory for it + * return a pointer to the allocated memory and the size + * return NULL and a size of 0 if the buffer is empty + * + * jfmxxxx: fix it to also write a buffer + ********************************************************************/ +static void spoolss_io_read_buffer8(char *desc, prs_struct *ps, uint8 **buffer, uint32 *size,int depth) +{ + uint32 useless_ptr; + + prs_debug(ps, depth, desc, "spoolss_io_read_buffer8"); + depth++; + + prs_align(ps); + + prs_uint32("buffer pointer", ps, depth, &useless_ptr); + + if (useless_ptr != 0x0000) + { + prs_uint32("buffer size", ps, depth, size); + *buffer=(uint8 *)malloc( (*size) * sizeof(uint8) ); + prs_uint8s(True,"buffer",ps,depth,*buffer,*size); + prs_align(ps); + } + else + { + *buffer=0x0000; + *size=0x0000; + } +} + +/******************************************************************* + * read a structure. + * called from spoolss_getprinter (srv_spoolss.c) + ********************************************************************/ +void spoolss_io_q_getprinter(char *desc, SPOOL_Q_GETPRINTER *q_u, + prs_struct *ps, int depth) +{ + uint32 count; + uint8 *buffer; + prs_debug(ps, depth, desc, "spoolss_io_q_getprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + + prs_uint32("level", ps, depth, &(q_u->level)); + + spoolss_io_read_buffer8("",ps, &buffer, &count,depth); + if (buffer != 0x0000) + { + free(buffer); + } + + prs_uint32("buffer size", ps, depth, &(q_u->offered)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_setprinter(char *desc, SPOOL_R_SETPRINTER *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_setprinter"); + depth++; + + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +static void spoolss_io_devmode(char *desc, prs_struct *ps, int depth, DEVICEMODE **devmode) +{ + uint32 devmode_size=0x0; + uint32 useless_ptr=0x0; + + prs_debug(ps, depth, desc, "spoolss_io_devmode"); + depth++; + + prs_uint32("devmode_size", ps, depth, &(devmode_size)); + prs_uint32("useless_ptr", ps, depth, &(useless_ptr)); + + if (devmode_size!=0 && useless_ptr!=0) + { + /* so we have a DEVICEMODE to follow */ + if (ps->io) + { + DEBUG(9,("Allocating memory for spoolss_io_devmode\n")); + *devmode=(DEVICEMODE *)malloc(sizeof(DEVICEMODE)); + ZERO_STRUCTP(*devmode); + } + + /* this is bad code, shouldn't be there */ + prs_uint32("devmode_size", ps, depth, &(devmode_size)); + + smb_io_devmode(desc, ps, depth, *devmode); + } +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_setprinter(char *desc, SPOOL_Q_SETPRINTER *q_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_q_setprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle", &(q_u->handle),ps,depth); + prs_uint32("level", ps, depth, &(q_u->level)); + + /* again a designed mess */ + /* sometimes I'm wondering how all of this work ! */ + + /* To be correct it need to be split in 3 functions */ + + spool_io_printer_info_level("", &(q_u->info), ps, depth); + + spoolss_io_devmode(desc, ps, depth, &(q_u->devmode)); + + prs_uint32("security.size_of_buffer", ps, depth, &(q_u->security.size_of_buffer)); + prs_uint32("security.data", ps, depth, &(q_u->security.data)); + + prs_uint32("command", ps, depth, &(q_u->command)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_fcpn(char *desc, SPOOL_R_FCPN *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_fcpn"); + depth++; + + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_fcpn(char *desc, SPOOL_Q_FCPN *q_u, prs_struct *ps, int depth) +{ + + prs_debug(ps, depth, desc, "spoolss_io_q_fcpn"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); +} + + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_addjob(char *desc, SPOOL_R_ADDJOB *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_addjob(char *desc, SPOOL_Q_ADDJOB *q_u, prs_struct *ps, int depth) +{ + + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_uint32("level", ps, depth, &(q_u->level)); + + spoolss_io_read_buffer("", ps, depth, &(q_u->buffer)); + + prs_align(ps); + + prs_uint32("buf_size", ps, depth, &(q_u->buf_size)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_enumjobs(char *desc, SPOOL_R_ENUMJOBS *r_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + int i; + + prs_debug(ps, depth, desc, "spoolss_io_r_enumjobs"); + depth++; + + prs_align(ps); + + prs_uint32("pointer", ps, depth, &useless_ptr); + + switch (r_u->level) + { + case 1: + { + JOB_INFO_1 *info; + info=r_u->job.job_info_1; + + for (i=0; i<r_u->numofjobs; i++) + { + bufsize_required += spoolss_size_job_info_1(&(info[i])); + } + break; + } + case 2: + { + JOB_INFO_2 *info; + info=r_u->job.job_info_2; + + for (i=0; i<r_u->numofjobs; i++) + { + bufsize_required += spoolss_size_job_info_2(&(info[i])); + } + break; + } + } + + DEBUG(4,("spoolss_io_r_enumjobs, size needed: %d\n",bufsize_required)); + DEBUG(4,("spoolss_io_r_enumjobs, size offered: %d\n",r_u->offered)); + + /* check if the buffer is big enough for the datas */ + if (r_u->offered<bufsize_required) + { + /* it's too small */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; /* say so */ + r_u->offered=0; /* don't send back the buffer */ + + DEBUG(4,("spoolss_io_r_enumjobs, buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUG(4,("spoolss_io_r_enumjobs, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + JOB_INFO_1 *info; + for (i=0; i<r_u->numofjobs; i++) + { + info = &(r_u->job.job_info_1[i]); + smb_io_job_info_1(desc, + info, + ps, + depth, + &start_offset, + &end_offset); + } + break; + } + case 2: + { + JOB_INFO_2 *info; + for (i=0; i<r_u->numofjobs; i++) + { + info = &(r_u->job.job_info_2[i]); + smb_io_job_info_2(desc, + info, + ps, + depth, + &start_offset, + &end_offset); + } + break; + } + + } + ps->offset=beginning+r_u->offered; + prs_align(ps); + } + + /* + * if the buffer was too small, send the minimum required size + * if it was too large, send the real needed size + */ + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("numofjobs", ps, depth, &(r_u->numofjobs)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_enumjobs(char *desc, SPOOL_Q_ENUMJOBS *q_u, prs_struct *ps, int depth) +{ + + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_uint32("firstjob", ps, depth, &(q_u->firstjob)); + prs_uint32("numofjobs", ps, depth, &(q_u->numofjobs)); + prs_uint32("level", ps, depth, &(q_u->level)); + + spoolss_io_read_buffer("", ps, depth, &(q_u->buffer)); + + prs_align(ps); + + prs_uint32("buf_size", ps, depth, &(q_u->buf_size)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_schedulejob(char *desc, SPOOL_R_SCHEDULEJOB *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_schedulejob"); + depth++; + + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_schedulejob(char *desc, SPOOL_Q_SCHEDULEJOB *q_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_q_schedulejob"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_uint32("jobid", ps, depth, &(q_u->jobid)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_setjob(char *desc, SPOOL_R_SETJOB *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_setjob"); + depth++; + + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_setjob(char *desc, SPOOL_Q_SETJOB *q_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_q_setjob"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_uint32("jobid", ps, depth, &(q_u->jobid)); + /* + * level is usually 0. If (level!=0) then I'm in trouble ! + * I will try to generate setjob command with level!=0, one day. + */ + prs_uint32("level", ps, depth, &(q_u->level)); + prs_uint32("command", ps, depth, &(q_u->command)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_enumdrivers(char *desc, SPOOL_R_ENUMPRINTERDRIVERS *r_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + int i; + + prs_debug(ps, depth, desc, "spoolss_io_r_enumdrivers"); + depth++; + + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + + DEBUG(7,("Level [%d], number [%d]\n", r_u->level, r_u->numofdrivers)); + switch (r_u->level) + { + case 1: + { + DRIVER_INFO_1 *driver_info_1; + driver_info_1=r_u->driver.driver_info_1; + + for (i=0; i<r_u->numofdrivers; i++) + { + bufsize_required += spoolss_size_printer_driver_info_1(&(driver_info_1[i])); + } + break; + } + case 2: + { + DRIVER_INFO_2 *driver_info_2; + driver_info_2=r_u->driver.driver_info_2; + + for (i=0; i<r_u->numofdrivers; i++) + { + bufsize_required += spoolss_size_printer_driver_info_2(&(driver_info_2[2])); + } + break; + } + case 3: + { + DRIVER_INFO_3 *driver_info_3; + driver_info_3=r_u->driver.driver_info_3; + + for (i=0; i<r_u->numofdrivers; i++) + { + bufsize_required += spoolss_size_printer_driver_info_3(&(driver_info_3[i])); + } + break; + } + } + + DEBUGADD(7,("size needed: %d\n",bufsize_required)); + DEBUGADD(7,("size offered: %d\n",r_u->offered)); + + /* check if the buffer is big enough for the datas */ + + if (r_u->offered<bufsize_required) + { + + /* it's too small */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; /* say so */ + r_u->offered=0; /* don't send back the buffer */ + DEBUGADD(8,("buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUGADD(8,("buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + DRIVER_INFO_1 *info; + for (i=0; i<r_u->numofdrivers; i++) + { + info = &(r_u->driver.driver_info_1[i]); + smb_io_printer_driver_info_1(desc, info, ps, depth, &start_offset, &end_offset); + } + break; + } + case 2: + { + DRIVER_INFO_2 *info; + for (i=0; i<r_u->numofdrivers; i++) + { + info = &(r_u->driver.driver_info_2[i]); + smb_io_printer_driver_info_2(desc, info, ps, depth, &start_offset, &end_offset); + } + break; + } + case 3: + { + DRIVER_INFO_3 *info; + for (i=0; i<r_u->numofdrivers; i++) + { + info = &(r_u->driver.driver_info_3[i]); + smb_io_printer_driver_info_3(desc, info, ps, depth, &start_offset, &end_offset); + } + break; + } + } + ps->offset=beginning+r_u->offered; + prs_align(ps); + } + + /* + * if the buffer was too small, send the minimum required size + * if it was too large, send the real needed size + */ + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("numofdrivers", ps, depth, &(r_u->numofdrivers)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_enumprinterdrivers(char *desc, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, prs_struct *ps, int depth) +{ + + uint32 useless_ptr=0xADDE0FF0; + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + smb_io_unistr2("", &(q_u->name),True,ps,depth); + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + smb_io_unistr2("", &(q_u->environment),True,ps,depth); + prs_align(ps); + prs_uint32("level", ps, depth, &(q_u->level)); + spoolss_io_read_buffer("", ps, depth, &(q_u->buffer)); + prs_align(ps); + prs_uint32("buf_size", ps, depth, &(q_u->buf_size)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_enumforms(char *desc, SPOOL_R_ENUMFORMS *r_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + int i; + + prs_debug(ps, depth, desc, "spoolss_io_r_enumforms"); + depth++; + + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + switch (r_u->level) + { + case 1: + { + FORM_1 *forms_1; + forms_1=r_u->forms_1; + + for (i=0; i<r_u->numofforms; i++) + { + bufsize_required += spoolss_size_form_1(&(forms_1[i])); + } + break; + } + } + + DEBUG(4,("spoolss_io_r_enumforms, size needed: %d\n",bufsize_required)); + DEBUG(4,("spoolss_io_r_enumforms, size offered: %d\n",r_u->offered)); + + /* check if the buffer is big enough for the datas */ + + if (r_u->offered<bufsize_required) + { + + /* it's too small */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; /* say so */ + r_u->offered=0; /* don't send back the buffer */ + + DEBUG(4,("spoolss_io_r_enumforms, buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUG(4,("spoolss_io_r_enumforms, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + + if (r_u->offered!=0) + { + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + FORM_1 *info; + for (i=0; i<r_u->numofforms; i++) + { + info = &(r_u->forms_1[i]); + smb_io_form_1(desc, info, ps, depth, &start_offset, &end_offset); + } + break; + } + } + ps->offset=beginning+r_u->offered; + prs_align(ps); + } + } + + /* + * if the buffer was too small, send the minimum required size + * if it was too large, send the real needed size + */ + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("numofforms", ps, depth, &(r_u->numofforms)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_enumforms(char *desc, SPOOL_Q_ENUMFORMS *q_u, prs_struct *ps, int depth) +{ + + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_uint32("level", ps, depth, &(q_u->level)); + spoolss_io_read_buffer("", ps, depth, &(q_u->buffer)); + prs_align(ps); + prs_uint32("buf_size", ps, depth, &(q_u->buf_size)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_enumports(char *desc, SPOOL_R_ENUMPORTS *r_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + int i; + + prs_debug(ps, depth, desc, "spoolss_io_r_enumports"); + depth++; + + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + switch (r_u->level) + { + case 2: + { + PORT_INFO_2 *port_2; + port_2=r_u->port.port_info_2; + + for (i=0; i<r_u->numofports; i++) + { + bufsize_required += spoolss_size_port_info_2(&(port_2[i])); + } + break; + } + } + + DEBUG(4,("size needed: %d\n",bufsize_required)); + DEBUG(4,("size offered: %d\n",r_u->offered)); + + /* check if the buffer is big enough for the datas */ + if (r_u->offered<bufsize_required) + { + + /* it's too small */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; /* say so */ + r_u->offered=0; /* don't send back the buffer */ + + DEBUG(4,("buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUG(4,("buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 2: + { + PORT_INFO_2 *info; + for (i=0; i<r_u->numofports; i++) + { + info = &(r_u->port.port_info_2[i]); + smb_io_port_2(desc, info, ps, depth, &start_offset, &end_offset); + } + break; + } + } + ps->offset=beginning+r_u->offered; + prs_align(ps); + } + + /* + * if the buffer was too small, send the minimum required size + * if it was too large, send the real needed size + */ + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("numofports", ps, depth, &(r_u->numofports)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_enumports(char *desc, SPOOL_Q_ENUMPORTS *q_u, prs_struct *ps, int depth) +{ + uint32 useless; + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + prs_uint32("useless", ps, depth, &useless); + smb_io_unistr2("", &(q_u->name),True,ps,depth); + prs_align(ps); + prs_uint32("level", ps, depth, &(q_u->level)); + spoolss_io_read_buffer("", ps, depth, &(q_u->buffer)); + prs_align(ps); + prs_uint32("buf_size", ps, depth, &(q_u->buf_size)); +} + + +/******************************************************************* +********************************************************************/ +void spool_io_printer_info_level_2(char *desc, SPOOL_PRINTER_INFO_LEVEL_2 **q_u, prs_struct *ps, int depth) +{ + SPOOL_PRINTER_INFO_LEVEL_2 *il; + + prs_debug(ps, depth, desc, ""); + depth++; + + /* reading */ + if (ps->io) + { + il=(SPOOL_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(SPOOL_PRINTER_INFO_LEVEL_2)); + ZERO_STRUCTP(il); + *q_u=il; + DEBUG(7,("lecture: memoire ok\n")); + } + else + { + il=*q_u; + } + + prs_align(ps); + + prs_uint32("servername_ptr", ps, depth, &(il->servername_ptr)); + prs_uint32("printername_ptr", ps, depth, &(il->printername_ptr)); + prs_uint32("sharename_ptr", ps, depth, &(il->sharename_ptr)); + prs_uint32("portname_ptr", ps, depth, &(il->portname_ptr)); + prs_uint32("drivername_ptr", ps, depth, &(il->drivername_ptr)); + prs_uint32("comment_ptr", ps, depth, &(il->comment_ptr)); + prs_uint32("location_ptr", ps, depth, &(il->location_ptr)); + prs_uint32("devmode_ptr", ps, depth, &(il->devmode_ptr)); + prs_uint32("sepfile_ptr", ps, depth, &(il->sepfile_ptr)); + prs_uint32("printprocessor_ptr", ps, depth, &(il->printprocessor_ptr)); + prs_uint32("datatype_ptr", ps, depth, &(il->datatype_ptr)); + prs_uint32("parameters_ptr", ps, depth, &(il->parameters_ptr)); + prs_uint32("secdesc_ptr", ps, depth, &(il->secdesc_ptr)); + + prs_uint32("attributes", ps, depth, &(il->attributes)); + prs_uint32("priority", ps, depth, &(il->priority)); + prs_uint32("default_priority", ps, depth, &(il->default_priority)); + prs_uint32("starttime", ps, depth, &(il->starttime)); + prs_uint32("untiltime", ps, depth, &(il->untiltime)); + prs_uint32("status", ps, depth, &(il->status)); + prs_uint32("cjobs", ps, depth, &(il->cjobs)); + prs_uint32("averageppm", ps, depth, &(il->averageppm)); + + smb_io_unistr2("", &(il->servername), il->servername_ptr, ps, depth); + smb_io_unistr2("", &(il->printername), il->printername_ptr, ps, depth); + smb_io_unistr2("", &(il->sharename), il->sharename_ptr, ps, depth); + smb_io_unistr2("", &(il->portname), il->portname_ptr, ps, depth); + smb_io_unistr2("", &(il->drivername), il->drivername_ptr, ps, depth); + smb_io_unistr2("", &(il->comment), il->comment_ptr, ps, depth); + smb_io_unistr2("", &(il->location), il->location_ptr, ps, depth); + smb_io_unistr2("", &(il->sepfile), il->sepfile_ptr, ps, depth); + smb_io_unistr2("", &(il->printprocessor), il->printprocessor_ptr, ps, depth); + smb_io_unistr2("", &(il->datatype), il->datatype_ptr, ps, depth); + smb_io_unistr2("", &(il->parameters), il->parameters_ptr, ps, depth); + + prs_align(ps); + + /* this code as nothing to do here !!! + + if (il->secdesc_ptr) + { + il->secdesc=NULL; + sec_io_desc_buf("", &(il->secdesc), ps, depth); + } + + */ +} + +/******************************************************************* +********************************************************************/ +void spool_io_printer_info_level(char *desc, SPOOL_PRINTER_INFO_LEVEL *il, prs_struct *ps, int depth) +{ + uint32 useless; + uint32 level; + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + prs_uint32("info level", ps, depth, &level); + prs_uint32("useless", ps, depth, &useless); + + switch (level) + { + /* + * level 0 is used by setprinter when managing the queue + * (hold, stop, start a queue) + */ + case 0: + break; + /* + * level 2 is used by addprinter + * and by setprinter when updating printer's info + */ + case 2: + spool_io_printer_info_level_2("", &(il->info_2), ps, depth); + break; + } + +} + +/******************************************************************* +********************************************************************/ +void spool_io_user_level_1(char *desc, SPOOL_USER_LEVEL_1 **q_u, prs_struct *ps, int depth) +{ + SPOOL_USER_LEVEL_1 *il; + prs_debug(ps, depth, desc, ""); + depth++; + + /* reading */ + if (ps->io) + { + il=(SPOOL_USER_LEVEL_1 *)malloc(sizeof(SPOOL_USER_LEVEL_1)); + ZERO_STRUCTP(il); + *q_u=il; + } + else + { + il=*q_u; + } + + prs_align(ps); + prs_uint32("size", ps, depth, &(il->size)); + prs_uint32("client_name_ptr", ps, depth, &(il->client_name_ptr)); + prs_uint32("user_name_ptr", ps, depth, &(il->user_name_ptr)); + prs_uint32("build", ps, depth, &(il->build)); + prs_uint32("major", ps, depth, &(il->major)); + prs_uint32("minor", ps, depth, &(il->minor)); + prs_uint32("processor", ps, depth, &(il->processor)); + + smb_io_unistr2("", &(il->client_name), il->client_name_ptr, ps, depth); + prs_align(ps); + smb_io_unistr2("", &(il->user_name), il->user_name_ptr, ps, depth); +} + +/******************************************************************* +********************************************************************/ +void spool_io_user_level(char *desc, SPOOL_USER_LEVEL *q_u, prs_struct *ps, int depth) +{ + uint32 useless; + uint32 level; + prs_debug(ps, depth, desc, "spool_io_user_level"); + depth++; + + prs_align(ps); + prs_uint32("info_level", ps, depth, &level); + prs_uint32("useless", ps, depth, &useless); + + switch (level) + { + case 1: + spool_io_user_level_1("", &(q_u->user_level_1), ps, depth); + break; + + } +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_addprinterex(char *desc, SPOOL_Q_ADDPRINTEREX *q_u, prs_struct *ps, int depth) +{ + uint32 useless; + prs_debug(ps, depth, desc, "spoolss_io_q_addprinterex"); + depth++; + + /* + * I think that's one of the few well written functions. + * the sub-structures are correctly parsed and analysed + * the info level are handled in a nice way. + */ + + prs_align(ps); + prs_uint32("useless", ps, depth, &useless); + smb_io_unistr2("", &(q_u->server_name),True,ps,depth); + prs_align(ps); + + prs_uint32("info_level", ps, depth, &(q_u->level)); + + spool_io_printer_info_level("", &(q_u->info), ps, depth); + + /* the 4 unknown are all 0 */ + + /* + * en fait ils sont pas inconnu + * par recoupement avec rpcSetPrinter + * c'est le devicemode + * et le security descriptor. + */ + + prs_uint32("unk0", ps, depth, &(q_u->unk0)); + prs_uint32("unk1", ps, depth, &(q_u->unk1)); + prs_uint32("unk2", ps, depth, &(q_u->unk2)); + prs_uint32("unk3", ps, depth, &(q_u->unk3)); + + prs_uint32("info_level", ps, depth, &(q_u->user_level)); + + spool_io_user_level("", &(q_u->user), ps, depth); +} + + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_addprinterex(char *desc, SPOOL_R_ADDPRINTEREX *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_addprinterex"); + depth++; + + smb_io_prt_hnd("printer handle",&(r_u->handle),ps,depth); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spool_io_printer_driver_info_level_3(char *desc, SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 **q_u, + prs_struct *ps, int depth) +{ + SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *il; + + prs_debug(ps, depth, desc, ""); + depth++; + + /* reading */ + if (ps->io) + { + il=(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *)malloc(sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3)); + ZERO_STRUCTP(il); + *q_u=il; + DEBUG(1,("lecture: memoire ok\n")); + } + else + { + il=*q_u; + } + + prs_align(ps); + + prs_uint32("cversion", ps, depth, &(il->cversion)); + prs_uint32("name", ps, depth, &(il->name_ptr)); + prs_uint32("environment", ps, depth, &(il->environment_ptr)); + prs_uint32("driverpath", ps, depth, &(il->driverpath_ptr)); + prs_uint32("datafile", ps, depth, &(il->datafile_ptr)); + prs_uint32("configfile", ps, depth, &(il->configfile_ptr)); + prs_uint32("helpfile", ps, depth, &(il->helpfile_ptr)); + prs_uint32("monitorname", ps, depth, &(il->monitorname_ptr)); + prs_uint32("defaultdatatype", ps, depth, &(il->defaultdatatype_ptr)); + prs_uint32("dependentfilessize", ps, depth, &(il->dependentfilessize)); + prs_uint32("dependentfiles", ps, depth, &(il->dependentfiles_ptr)); + + prs_align(ps); + + smb_io_unistr2("", &(il->name), il->name_ptr, ps, depth); + smb_io_unistr2("", &(il->environment), il->environment_ptr, ps, depth); + smb_io_unistr2("", &(il->driverpath), il->driverpath_ptr, ps, depth); + smb_io_unistr2("", &(il->datafile), il->datafile_ptr, ps, depth); + smb_io_unistr2("", &(il->configfile), il->configfile_ptr, ps, depth); + smb_io_unistr2("", &(il->helpfile), il->helpfile_ptr, ps, depth); + smb_io_unistr2("", &(il->monitorname), il->monitorname_ptr, ps, depth); + smb_io_unistr2("", &(il->defaultdatatype), il->defaultdatatype_ptr, ps, depth); + + prs_align(ps); + if (il->dependentfiles_ptr) + smb_io_buffer5("", &(il->dependentfiles), ps, depth); + +} + + +/******************************************************************* + convert a buffer of UNICODE strings null terminated + the buffer is terminated by a NULL + + convert to an ascii array (null terminated) + + dynamically allocate memory + +********************************************************************/ +void uniarray_2_ascarray(BUFFER5 *buf5, char ***ar) +{ + char **array; + char *string; + char *destend; + char *dest; + uint32 n; + uint32 i; + + uint16 *src; + + if (buf5==NULL) return; + + array=NULL; + n=0; + i=0; + src=buf5->buffer; + + string=(char *)malloc(sizeof(char)*buf5->buf_len); + + destend = string + buf5->buf_len; + dest=string; + + while (dest < destend) + { + *(dest++) = (char)*(src++); + } + + /* that ugly for the first one but that's working */ + array=(char **)Realloc(array, sizeof(char *)*(i+1)); + array[i++]=string; + + while ( n < buf5->buf_len ) + { + if ( *(string++) == '\0' ) + { + array=(char **)Realloc(array, sizeof(char *)*(i+1)); + array[i++]=string; + } + n++; + } + *ar=array; + + DEBUG(10,("Number of dependent files: [%d]\n", i-1)); +} + +/******************************************************************* + read a UNICODE array with null terminated strings + and null terminated array + and size of array at beginning +********************************************************************/ +void smb_io_unibuffer(char *desc, UNISTR2 *buffer, prs_struct *ps, int depth) +{ + + if (buffer==NULL) return; + + buffer->undoc=0; + buffer->uni_str_len=buffer->uni_max_len; + + prs_uint32("buffer_size", ps, depth, &(buffer->uni_max_len)); + + prs_unistr2(True, "buffer ", ps, depth, buffer); + +} + +/******************************************************************* +********************************************************************/ +void spool_io_printer_driver_info_level(char *desc, SPOOL_PRINTER_DRIVER_INFO_LEVEL *il, prs_struct *ps, int depth) +{ + uint32 useless; + uint32 level; + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + prs_uint32("info level", ps, depth, &level); + prs_uint32("useless", ps, depth, &useless); + + switch (level) + { + case 3: + spool_io_printer_driver_info_level_3("", &(il->info_3), ps, depth); + break; + } + +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_addprinterdriver(char *desc, SPOOL_Q_ADDPRINTERDRIVER *q_u, prs_struct *ps, int depth) +{ + uint32 useless; + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + prs_uint32("useless", ps, depth, &useless); + smb_io_unistr2("", &(q_u->server_name),True,ps,depth); + prs_align(ps); + prs_uint32("info_level", ps, depth, &(q_u->level)); + + spool_io_printer_driver_info_level("", &(q_u->info), ps, depth); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_addprinterdriver(char *desc, SPOOL_R_ADDPRINTERDRIVER *q_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, ""); + depth++; + + prs_uint32("status", ps, depth, &(q_u->status)); +} + + +/******************************************************************* +********************************************************************/ +void uni_2_asc_printer_driver_3(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *uni, + NT_PRINTER_DRIVER_INFO_LEVEL_3 **asc) +{ + NT_PRINTER_DRIVER_INFO_LEVEL_3 *d; + + DEBUG(7,("uni_2_asc_printer_driver_3: Converting from UNICODE to ASCII\n")); + + if (*asc==NULL) + { + *asc=(NT_PRINTER_DRIVER_INFO_LEVEL_3 *)malloc(sizeof(NT_PRINTER_DRIVER_INFO_LEVEL_3)); + ZERO_STRUCTP(*asc); + } + + d=*asc; + + d->cversion=uni->cversion; + + unistr2_to_ascii(d->name, &(uni->name), sizeof(d->name)-1); + unistr2_to_ascii(d->environment, &(uni->environment), sizeof(d->environment)-1); + unistr2_to_ascii(d->driverpath, &(uni->driverpath), sizeof(d->driverpath)-1); + unistr2_to_ascii(d->datafile, &(uni->datafile), sizeof(d->datafile)-1); + unistr2_to_ascii(d->configfile, &(uni->configfile), sizeof(d->configfile)-1); + unistr2_to_ascii(d->helpfile, &(uni->helpfile), sizeof(d->helpfile)-1); + unistr2_to_ascii(d->monitorname, &(uni->monitorname), sizeof(d->monitorname)-1); + unistr2_to_ascii(d->defaultdatatype, &(uni->defaultdatatype), sizeof(d->defaultdatatype)-1); + + DEBUGADD(8,( "version: %d\n", d->cversion)); + DEBUGADD(8,( "name: %s\n", d->name)); + DEBUGADD(8,( "environment: %s\n", d->environment)); + DEBUGADD(8,( "driverpath: %s\n", d->driverpath)); + DEBUGADD(8,( "datafile: %s\n", d->datafile)); + DEBUGADD(8,( "configfile: %s\n", d->configfile)); + DEBUGADD(8,( "helpfile: %s\n", d->helpfile)); + DEBUGADD(8,( "monitorname: %s\n", d->monitorname)); + DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype)); + + uniarray_2_ascarray(&(uni->dependentfiles), &(d->dependentfiles) ); +} + +void uni_2_asc_printer_info_2(SPOOL_PRINTER_INFO_LEVEL_2 *uni, + NT_PRINTER_INFO_LEVEL_2 **asc) +{ + NT_PRINTER_INFO_LEVEL_2 *d; + + DEBUG(7,("Converting from UNICODE to ASCII\n")); + + if (*asc==NULL) + { + DEBUGADD(8,("allocating memory\n")); + + *asc=(NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2)); + ZERO_STRUCTP(*asc); + } + DEBUGADD(8,("start converting\n")); + + d=*asc; + + d->attributes=uni->attributes; + d->priority=uni->priority; + d->default_priority=uni->default_priority; + d->starttime=uni->starttime; + d->untiltime=uni->untiltime; + d->status=uni->status; + d->cjobs=uni->cjobs; + + unistr2_to_ascii(d->servername, &(uni->servername), sizeof(d->servername)-1); + unistr2_to_ascii(d->printername, &(uni->printername), sizeof(d->printername)-1); + unistr2_to_ascii(d->sharename, &(uni->sharename), sizeof(d->sharename)-1); + unistr2_to_ascii(d->portname, &(uni->portname), sizeof(d->portname)-1); + unistr2_to_ascii(d->drivername, &(uni->drivername), sizeof(d->drivername)-1); + unistr2_to_ascii(d->comment, &(uni->comment), sizeof(d->comment)-1); + unistr2_to_ascii(d->location, &(uni->location), sizeof(d->location)-1); + unistr2_to_ascii(d->sepfile, &(uni->sepfile), sizeof(d->sepfile)-1); + unistr2_to_ascii(d->printprocessor, &(uni->printprocessor), sizeof(d->printprocessor)-1); + unistr2_to_ascii(d->datatype, &(uni->datatype), sizeof(d->datatype)-1); + unistr2_to_ascii(d->parameters, &(uni->parameters), sizeof(d->parameters)-1); +} + +void convert_printer_info(SPOOL_PRINTER_INFO_LEVEL uni, + NT_PRINTER_INFO_LEVEL *printer, + uint32 level) +{ + switch (level) + { + case 2: + { + uni_2_asc_printer_info_2(uni.info_2, &(printer->info_2)); + break; + } + default: + break; + } + + +} + +void convert_printer_driver_info(SPOOL_PRINTER_DRIVER_INFO_LEVEL uni, + NT_PRINTER_DRIVER_INFO_LEVEL *printer, + uint32 level) +{ + switch (level) + { + case 3: + { + printer->info_3=NULL; + uni_2_asc_printer_driver_3(uni.info_3, &(printer->info_3)); + break; + } + default: + break; + } + + +} + +void convert_devicemode(DEVICEMODE devmode, NT_DEVICEMODE *nt_devmode) +{ + unistr_to_ascii(nt_devmode->devicename, + devmode.devicename.buffer, + 31); + + unistr_to_ascii(nt_devmode->formname, + devmode.formname.buffer, + 31); + + nt_devmode->specversion=devmode.specversion; + nt_devmode->driverversion=devmode.driverversion; + nt_devmode->size=devmode.size; + nt_devmode->driverextra=devmode.driverextra; + nt_devmode->fields=devmode.fields; + nt_devmode->orientation=devmode.orientation; + nt_devmode->papersize=devmode.papersize; + nt_devmode->paperlength=devmode.paperlength; + nt_devmode->paperwidth=devmode.paperwidth; + nt_devmode->scale=devmode.scale; + nt_devmode->copies=devmode.copies; + nt_devmode->defaultsource=devmode.defaultsource; + nt_devmode->printquality=devmode.printquality; + nt_devmode->color=devmode.color; + nt_devmode->duplex=devmode.duplex; + nt_devmode->yresolution=devmode.yresolution; + nt_devmode->ttoption=devmode.ttoption; + nt_devmode->collate=devmode.collate; + + nt_devmode->logpixels=devmode.logpixels; + nt_devmode->bitsperpel=devmode.bitsperpel; + nt_devmode->pelswidth=devmode.pelswidth; + nt_devmode->pelsheight=devmode.pelsheight; + nt_devmode->displayflags=devmode.displayflags; + nt_devmode->displayfrequency=devmode.displayfrequency; + nt_devmode->icmmethod=devmode.icmmethod; + nt_devmode->icmintent=devmode.icmintent; + nt_devmode->mediatype=devmode.mediatype; + nt_devmode->dithertype=devmode.dithertype; + nt_devmode->reserved1=devmode.reserved1; + nt_devmode->reserved2=devmode.reserved2; + nt_devmode->panningwidth=devmode.panningwidth; + nt_devmode->panningheight=devmode.panningheight; + + if (nt_devmode->driverextra != 0) + { + /* if we had a previous private delete it and make a new one */ + if (nt_devmode->private != NULL) + free(nt_devmode->private); + nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8)); + memcpy(nt_devmode->private, devmode.private, nt_devmode->driverextra); + } + +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_getprinterdriverdir(char *desc, SPOOL_R_GETPRINTERDRIVERDIR *r_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + + prs_debug(ps, depth, desc, "spoolss_io_r_getprinterdriverdir"); + depth++; + + prs_align(ps); + + prs_uint32("pointer", ps, depth, &useless_ptr); + + switch (r_u->level) + { + case 1: + { + DRIVER_DIRECTORY_1 *driver_info_1; + driver_info_1=&(r_u->driver.driver_info_1); + + bufsize_required = size_of_relative_string(&(driver_info_1->name)); + break; + } + } + + DEBUG(4,("spoolss_io_r_getprinterdriverdir, size needed: %d\n",bufsize_required)); + DEBUG(4,("spoolss_io_r_getprinterdriverdir, size offered: %d\n",r_u->offered)); + + /* check if the buffer is big enough for the datas */ + + if (r_u->offered<bufsize_required) + { + + /* it's too small */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; /* say so */ + r_u->offered=0; /* don't send back the buffer */ + DEBUG(4,("spoolss_io_r_getprinterdriverdir, buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUG(4,("spoolss_io_r_getprinterdriverdir, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + DRIVER_DIRECTORY_1 *info; + info = &(r_u->driver.driver_info_1); + prs_unistr("name", ps, depth, &(info->name)); + /*smb_io_printer_driver_dir_1(desc, info, ps, depth, &start_offset, &end_offset);*/ + break; + } + } + ps->offset=beginning+r_u->offered; + prs_align(ps); + } + + /* + * if the buffer was too small, send the minimum required size + * if it was too large, send the real needed size + */ + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_getprinterdriverdir(char *desc, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, prs_struct *ps, int depth) +{ + + uint32 useless_ptr=0xADDE0FF0; + prs_debug(ps, depth, desc, ""); + depth++; + + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + smb_io_unistr2("", &(q_u->name),True,ps,depth); + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + smb_io_unistr2("", &(q_u->environment),True,ps,depth); + prs_align(ps); + prs_uint32("level", ps, depth, &(q_u->level)); + spoolss_io_read_buffer("", ps, depth, &(q_u->buffer)); + prs_align(ps); + prs_uint32("buf_size", ps, depth, &(q_u->buf_size)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_enumprintprocessors(char *desc, SPOOL_R_ENUMPRINTPROCESSORS *r_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0xADDE0FF0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + + prs_debug(ps, depth, desc, "spoolss_io_r_enumprintprocessors"); + depth++; + + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + switch (r_u->level) + { + case 1: + { + PRINTPROCESSOR_1 *info_1; + info_1=r_u->info_1; +/* + for (i=0; i<r_u->numofprintprocessors; i++) + { + bufsize_required += spoolss_size_port_info_2(&(info_1[i])); + } +*/ break; + } + } + + DEBUG(4,("size needed: %d\n",bufsize_required)); + DEBUG(4,("size offered: %d\n",r_u->offered)); + + /* check if the buffer is big enough for the datas */ + if (r_u->offered<bufsize_required) + { + + /* it's too small */ + r_u->status=ERROR_INSUFFICIENT_BUFFER; /* say so */ + r_u->offered=0; /* don't send back the buffer */ + + DEBUG(4,("buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + mem_grow_data(&(ps->data), ps->io, r_u->offered, 0); + + DEBUG(4,("buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=ps->offset; + start_offset=ps->offset; + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 2: + { +/* PORT_INFO_2 *info; + for (i=0; i<r_u->numofports; i++) + { + info = &(r_u->port.port_info_2[i]); + smb_io_port_2(desc, info, ps, depth, &start_offset, &end_offset); + }*/ + break; + } + } + ps->offset=beginning+r_u->offered; + prs_align(ps); + } + + /* + * if the buffer was too small, send the minimum required size + * if it was too large, send the real needed size + */ + + prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_uint32("numofprintprocessors", ps, depth, &(r_u->numofprintprocessors)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_enumprintprocessors(char *desc, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, prs_struct *ps, int depth) +{ + uint32 useless; + prs_debug(ps, depth, desc, "spoolss_io_q_enumprintprocessors"); + depth++; + + prs_align(ps); + prs_uint32("useless", ps, depth, &useless); + smb_io_unistr2("", &(q_u->name),True,ps,depth); + prs_align(ps); + prs_uint32("useless", ps, depth, &useless); + smb_io_unistr2("", &(q_u->environment),True,ps,depth); + prs_align(ps); + prs_uint32("level", ps, depth, &(q_u->level)); + spoolss_io_read_buffer("", ps, depth, &(q_u->buffer)); + prs_align(ps); + prs_uint32("buf_size", ps, depth, &(q_u->buf_size)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_enumprinterdata(char *desc, SPOOL_R_ENUMPRINTERDATA *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_enumprintprocessors"); + depth++; + + prs_align(ps); + prs_uint32("valuesize", ps, depth, &(r_u->valuesize)); + prs_unistr("value", ps, depth, &(r_u->value)); + prs_uint32("realvaluesize", ps, depth, &(r_u->realvaluesize)); + + prs_uint32("type", ps, depth, &(r_u->type)); + + prs_uint32("datasize", ps, depth, &(r_u->datasize)); + prs_uint8s(False, "data", ps, depth, r_u->data, r_u->datasize); + prs_uint32("realdatasize", ps, depth, &(r_u->realdatasize)); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_enumprinterdata(char *desc, SPOOL_Q_ENUMPRINTERDATA *q_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_q_enumprinterdata"); + depth++; + + prs_align(ps); + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + prs_uint32("index", ps, depth, &(q_u->index)); + prs_uint32("valuesize", ps, depth, &(q_u->valuesize)); + prs_uint32("datasize", ps, depth, &(q_u->datasize)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_q_setprinterdata(char *desc, SPOOL_Q_SETPRINTERDATA *q_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_q_setprinterdata"); + depth++; + + prs_align(ps); + smb_io_prt_hnd("printer handle", &(q_u->handle), ps, depth); + smb_io_unistr2("", &(q_u->value), True, ps, depth); + + prs_align(ps); + + prs_uint32("type", ps, depth, &(q_u->type)); + + prs_uint32("max_len", ps, depth, &(q_u->max_len)); + + switch (q_u->type) + { + case 0x1: + case 0x3: + case 0x4: + q_u->data=(uint8 *)malloc(q_u->max_len * sizeof(uint8)); + prs_uint8s(False,"data", ps, depth, q_u->data, q_u->max_len); + prs_align(ps); + break; + } + + prs_uint32("real_len", ps, depth, &(q_u->real_len)); +} + +/******************************************************************* +********************************************************************/ +void spoolss_io_r_setprinterdata(char *desc, SPOOL_R_SETPRINTERDATA *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_setprinterdata"); + depth++; + + prs_align(ps); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +********************************************************************/ +void convert_specific_param(NT_PRINTER_PARAM **param, UNISTR2 value , uint32 type, uint8 *data, uint32 len) +{ + DEBUG(5,("converting a specific param struct\n")); + + if (*param == NULL) + { + *param=(NT_PRINTER_PARAM *)malloc(sizeof(NT_PRINTER_PARAM)); + ZERO_STRUCTP(*param); + DEBUGADD(6,("Allocated a new PARAM struct\n")); + } + unistr2_to_ascii((*param)->value, &value, sizeof((*param)->value)-1); + (*param)->type = type; + + /* le champ data n'est pas NULL termine */ + /* on stocke donc la longueur */ + + (*param)->data_len=len; + + (*param)->data=(uint8 *)malloc(len * sizeof(uint8)); + + memcpy((*param)->data, data, len); + + DEBUGADD(6,("\tvalue:[%s], len:[%d]\n",(*param)->value, (*param)->data_len)); +} diff --git a/source3/rpc_server/srv_spoolss.c b/source3/rpc_server/srv_spoolss.c new file mode 100755 index 0000000000..52b60c5017 --- /dev/null +++ b/source3/rpc_server/srv_spoolss.c @@ -0,0 +1,3415 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Jean François Micouleau 1998. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "includes.h" +#include "nterr.h" + +extern int DEBUGLEVEL; +extern pstring global_myname; + +#ifndef MAX_OPEN_PRINTERS +#define MAX_OPEN_PRINTERS 50 +#endif + +#define PRINTER_HANDLE_IS_PRINTER 0 +#define PRINTER_HANDLE_IS_PRINTSERVER 1 + + +/* structure to store the printer handles */ +/* and a reference to what it's pointing to */ +/* and the notify info asked about */ +/* that's the central struct */ +static struct +{ + BOOL open; + BOOL document_started; + BOOL page_started; + uint32 current_jobid; + uint32 document_fd; + uint32 document_lastwritten; + pstring document_name; + pstring job_name; + PRINTER_HND printer_hnd; + BOOL printer_type; + union + { + fstring printername; + fstring printerservername; + } dev; + uint32 type; + uint32 access; + uint32 number_of_notify; + SPOOL_NOTIFY_OPTION_TYPE notify_info[MAX_PRINTER_NOTIFY+MAX_JOB_NOTIFY]; +} Printer[MAX_OPEN_PRINTERS]; + +#define VALID_HANDLE(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PRINTERS)) +#define OPEN_HANDLE(pnum) (VALID_HANDLE(pnum) && Printer[pnum].open) + +/**************************************************************************** + initialise printer handle states... +****************************************************************************/ +void init_printer_hnd(void) +{ + int i; + for (i = 0; i < MAX_OPEN_PRINTERS; i++) + { + Printer[i].open = False; + } +} + + +/**************************************************************************** + create a unique printer handle +****************************************************************************/ +static void create_printer_hnd(PRINTER_HND *hnd) +{ + static uint32 prt_hnd_low = 0; + static uint32 prt_hnd_high = 0; + + if (hnd == NULL) return; + + /* i severely doubt that prt_hnd_high will ever be non-zero... */ + prt_hnd_low++; + if (prt_hnd_low == 0) prt_hnd_high++; + + SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */ + SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */ + SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */ + SIVAL(hnd->data, 12, time(NULL)); /* something random */ + SIVAL(hnd->data, 16, getpid()); /* something more random */ +} + +/**************************************************************************** + clear an handle +****************************************************************************/ +static void clear_handle(PRINTER_HND *hnd) +{ + bzero(hnd->data, PRINTER_HND_SIZE); +} + +/**************************************************************************** + find first available printer slot. creates a printer handle for you. + ****************************************************************************/ +static BOOL open_printer_hnd(PRINTER_HND *hnd) +{ + int i; + + for (i = 0; i < MAX_OPEN_PRINTERS; i++) + { + if (!Printer[i].open) + { + Printer[i].open = True; + create_printer_hnd(hnd); + memcpy(&(Printer[i].printer_hnd), hnd, sizeof(*hnd)); + + DEBUG(4,("Opened printer handle[%x] ", i)); + dump_data(4, hnd->data, sizeof(hnd->data)); + return True; + } + } + DEBUG(1,("ERROR - open_printer_hnd: out of Printers Handles!\n")); + return False; +} + +/**************************************************************************** + find printer index by handle +****************************************************************************/ +static int find_printer_index_by_hnd(PRINTER_HND *hnd) +{ + int i; + + for (i = 0; i < MAX_OPEN_PRINTERS; i++) + { + if (memcmp(&(Printer[i].printer_hnd), hnd, sizeof(*hnd)) == 0) + { + DEBUG(4,("Found printer handle[%x] ", i)); + dump_data(4, hnd->data, sizeof(hnd->data)); + return i; + } + } + DEBUG(3,("Whoops, Printer handle not found: ")); + dump_data(4, hnd->data, sizeof(hnd->data)); + return -1; +} + +/**************************************************************************** + set printer handle type. +****************************************************************************/ +static BOOL set_printer_hnd_accesstype(PRINTER_HND *hnd, uint32 access_required) +{ + int pnum = find_printer_index_by_hnd(hnd); + + if (OPEN_HANDLE(pnum)) + { + DEBUG(4,("Setting printer access=%x (pnum=%x)\n", + access_required, pnum)); + + + + Printer[pnum].access = access_required; + return True; + } + else + { + DEBUG(4,("Error setting printer type=%x (pnum=%x)", + access_required, pnum)); + return False; + } + return False; +} + +/**************************************************************************** + set printer handle type. +****************************************************************************/ +static BOOL set_printer_hnd_printertype(PRINTER_HND *hnd, char *printername) +{ + int pnum = find_printer_index_by_hnd(hnd); + + if (OPEN_HANDLE(pnum)) + { + DEBUG(3,("Setting printer type=%s (pnum=%x)\n", printername, pnum)); + + if ( strlen(printername) < 3 ) + { + DEBUGADD(4,("A print server must have at least 1 char ! %s\n", printername)); + return False; + } + + /* check if it's \\server or \\server\printer */ + /* +2 is to skip the leading \\ */ + if (!strchr(printername+2, '\\')) + { + /* it's a print server */ + DEBUGADD(4,("Printer is a print server\n")); + Printer[pnum].printer_type = PRINTER_HANDLE_IS_PRINTSERVER; + return True; + } + else + { + /* it's a printer */ + DEBUGADD(4,("Printer is a printer\n")); + Printer[pnum].printer_type = PRINTER_HANDLE_IS_PRINTER; + return True; + } + } + else + { + DEBUGADD(4,("Error setting printer name %s (pnum=%x)", + printername, pnum)); + return False; + } + return False; +} + +/**************************************************************************** + set printer handle printername. +****************************************************************************/ +static BOOL set_printer_hnd_printername(PRINTER_HND *hnd, char *printername) +{ + int pnum = find_printer_index_by_hnd(hnd); + char *back; + NT_PRINTER_INFO_LEVEL printer; + int snum; + int n_services=lp_numservices(); + uint32 marche; + + if (OPEN_HANDLE(pnum)) + { + DEBUG(4,("Setting printer name=%s (len=%d) (pnum=%x)\n", + printername,strlen(printername), pnum)); + + switch (Printer[pnum].printer_type) + { + case PRINTER_HANDLE_IS_PRINTER: + back=strchr(printername+2, '\\'); + back=back+1; + DEBUGADD(5,("searching for %s (len=%d)\n", back,strlen(back))); + /* + * store the Samba share name in it + * in back we have the long printer name + * need to iterate all the snum and do a + * get_a_printer each time to find the printer + * faster to do it here than later. + */ + for (snum=0;snum<n_services; snum++) + { + if (lp_browseable(snum) && + lp_snum_ok(snum) && + lp_print_ok(snum) ) + { + DEBUGADD(5,("get_printer_snum, share:%s\n",lp_servicename(snum))); + + marche=get_a_printer(&printer, 2, lp_servicename(snum)); + DEBUGADD(6,("get_printer_snum, marche:%d\n",marche)); + + if ( marche==0 && ( strlen(printer.info_2->printername) == strlen(back) ) + && ( !strncasecmp(printer.info_2->printername, back, strlen(back))) + ) + { + DEBUGADD(4,("Printer found: %s[%x]\n",lp_servicename(snum),snum)); + strncpy(Printer[pnum].dev.printername, lp_servicename(snum), strlen(lp_servicename(snum))); + return True; + break; + } + free_a_printer(printer, 2); + } + } + + return False; + break; + case PRINTER_HANDLE_IS_PRINTSERVER: + strncpy(Printer[pnum].dev.printerservername, printername, strlen(printername)); + return True; + break; + default: + return False; + break; + } + } + else + { + DEBUG(0,("Error setting printer name=%s (pnum=%x)\n", + printername , pnum)); + return False; + } +} + +/**************************************************************************** + return the snum of a printer corresponding to an handle +****************************************************************************/ +static BOOL get_printer_snum(PRINTER_HND *hnd, int *number) +{ + int snum; + int pnum = find_printer_index_by_hnd(hnd); + int n_services=lp_numservices(); + + if (OPEN_HANDLE(pnum)) + { + switch (Printer[pnum].printer_type) + { + case PRINTER_HANDLE_IS_PRINTER: + DEBUG(4,("get_printer_snum, short name:%s\n", Printer[pnum].dev.printername)); + for (snum=0;snum<n_services; snum++) + { + if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) + { + DEBUG(4,("get_printer_snum, share:%s\n",lp_servicename(snum))); + if ( ( strlen(lp_servicename(snum)) == strlen( Printer[pnum].dev.printername ) ) + && ( !strncasecmp(lp_servicename(snum), + Printer[pnum].dev.printername, + strlen( lp_servicename(snum) ))) + ) + { + DEBUG(4,("Printer found: %s[%x]\n",lp_servicename(snum),snum)); + *number=snum; + return True; + break; + } + } + } + return False; + break; + case PRINTER_HANDLE_IS_PRINTSERVER: + return False; + break; + default: + return False; + break; + } + } + else + { + DEBUG(3,("Error getting printer - take a nap quickly !\n")); + return False; + } +} + +/******************************************************************** + ********************************************************************/ +static BOOL handle_is_printserver(PRINTER_HND *handle) +{ + int pnum=find_printer_index_by_hnd(handle); + + if (OPEN_HANDLE(pnum)) + { + switch (Printer[pnum].printer_type) + { + case PRINTER_HANDLE_IS_PRINTSERVER: + return True; + break; + case PRINTER_HANDLE_IS_PRINTER: + return False; + break; + } + } + return False; +} + +/******************************************************************** + ********************************************************************/ +/* +static BOOL handle_is_printer(PRINTER_HND *handle) +{ + return (!handle_is_printserver(handle)); +} +*/ + +/******************************************************************** + * api_spoolss_open_printer + * + * called from the spoolss dispatcher + ********************************************************************/ +static void spoolss_reply_open_printer(SPOOL_Q_OPEN_PRINTER *q_u, prs_struct *rdata) +{ + SPOOL_R_OPEN_PRINTER r_u; + BOOL printer_open = False; + fstring name; + + /* some sanity check because you can open a printer or a print server */ + /* aka: \\server\printer or \\server */ + unistr2_to_ascii(name, &(q_u->printername), sizeof(name)-1); + + DEBUGADD(3,("checking name: %s\n",name)); + + /* now the response */ + r_u.status=0x00000000; + + printer_open = open_printer_hnd(&(r_u.handle)); + set_printer_hnd_printertype(&(r_u.handle), name); + + if ( !set_printer_hnd_printername(&(r_u.handle), name) ) + { + r_u.status=0xC0000000|NT_STATUS_ACCESS_DENIED; + } + + set_printer_hnd_accesstype(&(r_u.handle), q_u->access_required); + + spoolss_io_r_open_printer("",&r_u,rdata,0); +} + +/******************************************************************** + * api_spoolss_open_printer + * + * called from the spoolss dispatcher + ********************************************************************/ +static void api_spoolss_open_printer(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_OPEN_PRINTER q_u; + + /* grab the spoolss open policy */ + spoolss_io_q_open_printer("", &q_u, data, 0); + + /* construct reply. always indicate success */ + spoolss_reply_open_printer(&q_u, rdata); +} + +/******************************************************************** + ********************************************************************/ +static BOOL getprinterdata_printer_server(fstring value, uint32 size, uint32 *type, + uint32 *numeric_data, uint8 **data, uint32 *needed) +{ + + if (!strcmp(value, "BeepEnabled")) + { + *type = 0x4; + *data = (uint8 *)malloc( 4*sizeof(uint8) ); + ZERO_STRUCTP(*data); + (*data)[0]=0x01; + (*data)[1]=0x00; + (*data)[2]=0x00; + (*data)[3]=0x00; + *numeric_data = 0x1; /* beep enabled */ + *needed = 0x4; + return True; + } + + if (!strcmp(value, "EventLog")) + { + *type = 0x4; + *data = (uint8 *)malloc( 4*sizeof(uint8) ); + ZERO_STRUCTP(*data); + (*data)[0]=0x1B; + (*data)[1]=0x00; + (*data)[2]=0x00; + (*data)[3]=0x00; + *numeric_data = 0x1B; /* Don't know ??? */ + *needed = 0x4; + return True; + } + + if (!strcmp(value, "NetPopup")) + { + *type = 0x4; + *data = (uint8 *)malloc( 4*sizeof(uint8) ); + ZERO_STRUCTP(*data); + (*data)[0]=0x01; + (*data)[1]=0x00; + (*data)[2]=0x00; + (*data)[3]=0x00; + *numeric_data = 0x1; /* popup enabled */ + *needed = 0x4; + return True; + } + + if (!strcmp(value, "MajorVersion")) + { + *type = 0x4; + *data = (uint8 *)malloc( 4*sizeof(uint8) ); + (*data)[0]=0x02; + (*data)[1]=0x00; + (*data)[2]=0x00; + (*data)[3]=0x00; + *numeric_data = 0x2; /* it's 2, period. */ + *needed = 0x4; + return True; + } + + if (!strcmp(value, "DefaultSpoolDirectory")) + { + pstring directory="You are using a Samba server"; + *type = 0x1; + *data = (uint8 *)malloc( size*sizeof(uint8) ); + ZERO_STRUCTP(*data); + make_unistr((UNISTR *)*data, directory); + *needed = 2*(strlen(directory)+1); + return True; + } + + if (!strcmp(value, "Architecture")) + { + pstring directory="Windows NT x86"; + *type = 0x1; + *data = (uint8 *)malloc( size*sizeof(uint8) ); + ZERO_STRUCTP(*data); + make_unistr((UNISTR *)*data, directory); + *needed = 2*(strlen(directory)+1); + return True; + } + + return False; +} + +static BOOL getprinterdata_printer(PRINTER_HND *handle, fstring value, uint32 size, uint32 *type, + uint32 *numeric_data, uint8 **data, uint32 *needed ) +{ + NT_PRINTER_INFO_LEVEL printer; + int pnum=0; + int snum=0; + uint8 *idata; + uint32 len; + + DEBUG(5,("getprinterdata_printer\n")); + + pnum = find_printer_index_by_hnd(handle); + if (OPEN_HANDLE(pnum)) + { + get_printer_snum(handle, &snum); + get_a_printer(&printer, 2, lp_servicename(snum)); + + if (get_specific_param(printer, 2, value, &idata, type, &len)) + { + switch (*type) + { + case 1: + case 3: + case 4: + *data = (uint8 *)malloc( size*sizeof(uint8) ); + bzero(*data, sizeof(uint8)*size); + memcpy(*data, idata, len>size?size:len); + *needed = len; + break; + /*case 4: + *numeric_data=atoi(idata); + break;*/ + } + return (True); + } + + } + + return (False); +} + +/******************************************************************** + * api_spoolss_reply_getprinterdata + * + * called from api_spoolss_getprinterdata + ********************************************************************/ +static void spoolss_reply_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u, prs_struct *rdata) +{ + SPOOL_R_GETPRINTERDATA r_u; + fstring value; + BOOL found; + int pnum = find_printer_index_by_hnd(&(q_u->handle)); + + /* + * Reminder: when it's a string, the length is in BYTES + * even if UNICODE is negociated. + * + * r_u.type is the kind of data + * 1 is a string + * 4 is a uint32 + * + * I think it's documented in MSDN somewhere in + * the registry data type (yep it's linked ...) + * + * JFM, 4/19/1999 + */ + + if (OPEN_HANDLE(pnum)) + { + r_u.size = q_u->size; + r_u.status = 0x0; + + unistr2_to_ascii(value, &(q_u->valuename), sizeof(value)-1); + + if (handle_is_printserver(&(q_u->handle))) + { + found=getprinterdata_printer_server(value, r_u.size, + &(r_u.type), &(r_u.numeric_data), + &(r_u.data), &(r_u.needed)); + } + else + { + found=getprinterdata_printer(&(q_u->handle), value, r_u.size, + &(r_u.type), &(r_u.numeric_data), + &(r_u.data), &(r_u.needed)); + } + + if (found==False) + { + /* reply this param doesn't exist */ + r_u.type = 0x4; + r_u.size = 0x0; + r_u.data = NULL; + r_u.numeric_data=0x0; + r_u.needed = 0x0; + r_u.status = ERROR_INVALID_PARAMETER; + } + + spoolss_io_r_getprinterdata("", &r_u, rdata, 0); + } +} + +/******************************************************************** + * api_spoolss_getprinterdata + * + * called from the spoolss dispatcher + ********************************************************************/ +static void api_spoolss_getprinterdata(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_GETPRINTERDATA q_u; + + /* read the stream and fill the struct */ + spoolss_io_q_getprinterdata("", &q_u, data, 0); + + spoolss_reply_getprinterdata(&q_u,rdata); +} + +/******************************************************************** + * api_spoolss_reply_closeprinter + * + * called from api_spoolss_closeprinter + ********************************************************************/ +static void spoolss_reply_closeprinter(SPOOL_Q_CLOSEPRINTER *q_u, prs_struct *rdata) +{ + SPOOL_R_CLOSEPRINTER r_u; + + int pnum = find_printer_index_by_hnd(&(q_u->handle)); + + clear_handle(&(r_u.handle)); + + if (OPEN_HANDLE(pnum)) + { + Printer[pnum].open=False; + r_u.status=0x0; + spoolss_io_r_closeprinter("",&r_u,rdata,0); + } + else + { + r_u.status= 0xC0000000 | NT_STATUS_INVALID_HANDLE; + DEBUG(3,("Error closing printer handle (pnum=%x)\n", pnum)); + } + + spoolss_io_r_closeprinter("",&r_u,rdata,0); +} + +/******************************************************************** + * api_spoolss_closeprinter + * + * called from the spoolss dispatcher + ********************************************************************/ +static void api_spoolss_closeprinter(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_CLOSEPRINTER q_u; + + spoolss_io_q_closeprinter("", &q_u, data, 0); + + spoolss_reply_closeprinter(&q_u,rdata); +} + +/******************************************************************** + * api_spoolss_reply_rffpcnex + * + * called from api_spoolss_rffpcnex (see this to understand) + ********************************************************************/ +static void spoolss_reply_rffpcnex(SPOOL_Q_RFFPCNEX *q_u, prs_struct *rdata) +{ + SPOOL_R_RFFPCNEX r_u; + + r_u.status = 0x0000; + + spoolss_io_r_rffpcnex("",&r_u,rdata,0); +} + +/******************************************************************** + * api_spoolss_rffpcnex + * ReplyFindFirstPrinterChangeNotifyEx + * called from the spoolss dispatcher + * + * jfmxxxx: before replying OK: status=0 + * should do a rpc call to the workstation asking ReplyOpenPrinter + * have to code it, later. + * + * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe + ********************************************************************/ +static void api_spoolss_rffpcnex(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_RFFPCNEX q_u; + + int i,j,k; + + spoolss_io_q_rffpcnex("", &q_u, data, 0); + + /* store the notify value in the printer struct */ + + i=find_printer_index_by_hnd(&(q_u.handle)); + + Printer[i].number_of_notify=q_u.option.count; + + DEBUG(3,("Copying %x notify option info\n",Printer[i].number_of_notify)); + + for (j=0;j<Printer[i].number_of_notify;j++) + { + Printer[i].notify_info[j].count=q_u.option.type[j].count; + Printer[i].notify_info[j].type=q_u.option.type[j].type ; + + DEBUG(4,("Copying %x info fields of type %x\n", + Printer[i].notify_info[j].count, + Printer[i].notify_info[j].type)); + for(k=0;k<Printer[i].notify_info[j].count;k++) + { + Printer[i].notify_info[j].fields[k]=q_u.option.type[j].fields[k]; + } + } + spoolss_reply_rffpcnex(&q_u,rdata); +} + +/******************************************************************* + * fill a notify_info_data with the servername + ********************************************************************/ +static void spoolss_notify_server_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + pstring temp_name; + + snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname); + + data->notify_data.data.length=strlen(temp_name); + ascii_to_unistr(data->notify_data.data.string, temp_name, sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the servicename + * jfmxxxx: it's incorrect should be long_printername + ********************************************************************/ +static void spoolss_notify_printer_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ +/* + data->notify_data.data.length=strlen(lp_servicename(snum)); + ascii_to_unistr(data->notify_data.data.string, lp_servicename(snum), sizeof(data->notify_data.data.string)-1); +*/ + data->notify_data.data.length=strlen(printer->info_2->printername); + ascii_to_unistr(data->notify_data.data.string, + printer->info_2->printername, + sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the servicename + ********************************************************************/ +static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen(lp_servicename(snum)); + ascii_to_unistr(data->notify_data.data.string, + lp_servicename(snum), + sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the port name + ********************************************************************/ +static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + /* even if it's strange, that's consistant in all the code */ + + data->notify_data.data.length=strlen(lp_servicename(snum)); + ascii_to_unistr(data->notify_data.data.string, + lp_servicename(snum), + sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the printername + * jfmxxxx: it's incorrect, should be lp_printerdrivername() + * but it doesn't exist, have to see what to do + ********************************************************************/ +static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen(printer->info_2->drivername); + ascii_to_unistr(data->notify_data.data.string, + printer->info_2->drivername, + sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the comment + ********************************************************************/ +static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen(lp_comment(snum)); + ascii_to_unistr(data->notify_data.data.string, + lp_comment(snum), + sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the comment + * jfm:xxxx incorrect, have to create a new smb.conf option + * location = "Room 1, floor 2, building 3" + ********************************************************************/ +static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen(printer->info_2->location); + ascii_to_unistr(data->notify_data.data.string, + printer->info_2->location, + sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the device mode + * jfm:xxxx don't to it for know but that's a real problem !!! + ********************************************************************/ +static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ +} + +/******************************************************************* + * fill a notify_info_data with the separator file name + * jfm:xxxx just return no file could add an option to smb.conf + * separator file = "separator.txt" + ********************************************************************/ +static void spoolss_notify_sepfile(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen(printer->info_2->sepfile); + ascii_to_unistr(data->notify_data.data.string, + printer->info_2->sepfile, + sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the print processor + * jfm:xxxx return always winprint to indicate we don't do anything to it + ********************************************************************/ +static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen(printer->info_2->printprocessor); + ascii_to_unistr(data->notify_data.data.string, + printer->info_2->printprocessor, + sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the print processor options + * jfm:xxxx send an empty string + ********************************************************************/ +static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen(printer->info_2->parameters); + ascii_to_unistr(data->notify_data.data.string, + printer->info_2->parameters, + sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the data type + * jfm:xxxx always send RAW as data type + ********************************************************************/ +static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen(printer->info_2->datatype); + ascii_to_unistr(data->notify_data.data.string, + printer->info_2->datatype, + sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with the security descriptor + * jfm:xxxx send an null pointer to say no security desc + * have to implement security before ! + ********************************************************************/ +static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=0; + data->notify_data.data.string[0]=0x00; +} + +/******************************************************************* + * fill a notify_info_data with the attributes + * jfm:xxxx a samba printer is always shared + ********************************************************************/ +static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.value[0] = PRINTER_ATTRIBUTE_SHARED \ + | PRINTER_ATTRIBUTE_NETWORK \ + | PRINTER_ATTRIBUTE_RAW_ONLY ; +} + +/******************************************************************* + * fill a notify_info_data with the priority + ********************************************************************/ +static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.value[0] = printer->info_2->priority; +} + +/******************************************************************* + * fill a notify_info_data with the default priority + ********************************************************************/ +static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.value[0] = printer->info_2->default_priority; +} + +/******************************************************************* + * fill a notify_info_data with the start time + ********************************************************************/ +static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.value[0] = printer->info_2->starttime; +} + +/******************************************************************* + * fill a notify_info_data with the until time + ********************************************************************/ +static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.value[0] = printer->info_2->untiltime; +} + +/******************************************************************* + * fill a notify_info_data with the status + ********************************************************************/ +static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + int count; + print_queue_struct *q=NULL; + print_status_struct status; + + bzero(&status,sizeof(status)); + + count=get_printqueue(snum,0,&q,&status); + + data->notify_data.value[0]=(uint32) status.status; +} + +/******************************************************************* + * fill a notify_info_data with the number of jobs queued + ********************************************************************/ +static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + print_queue_struct *q=NULL; + print_status_struct status; + + bzero(&status,sizeof(status)); + + data->notify_data.value[0]=get_printqueue(snum,0,&q,&status); +} + +/******************************************************************* + * fill a notify_info_data with the average ppm + ********************************************************************/ +static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + /* always respond 8 pages per minutes */ + /* a little hard ! */ + data->notify_data.value[0] = printer->info_2->averageppm; +} + +/******************************************************************* + * fill a notify_info_data with + ********************************************************************/ +static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen(queue->user); + ascii_to_unistr(data->notify_data.data.string, queue->user, sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with + ********************************************************************/ +static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.value[0]=queue->status; +} + +/******************************************************************* + * fill a notify_info_data with + ********************************************************************/ +static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen(queue->file); + ascii_to_unistr(data->notify_data.data.string, queue->file, sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with + ********************************************************************/ +static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.data.length=strlen("En attente"); + ascii_to_unistr(data->notify_data.data.string, "En attente", sizeof(data->notify_data.data.string)-1); +} + +/******************************************************************* + * fill a notify_info_data with + ********************************************************************/ +static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.value[0]=0x0; +} + +/******************************************************************* + * fill a notify_info_data with + ********************************************************************/ +static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.value[0]=queue->size; +} + +/******************************************************************* + * fill a notify_info_data with + ********************************************************************/ +static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer) +{ + data->notify_data.value[0]=queue->job; +} + +#define END 65535 + +struct s_notify_info_data_table notify_info_data_table[] = +{ +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL }, +{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, NULL }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size }, +{ JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL }, +{ END, END, "", END, NULL } +}; + +/******************************************************************* +return the size of info_data structure +********************************************************************/ +uint32 size_of_notify_info_data(uint16 type, uint16 field) +{ + int i=0; + + while (notify_info_data_table[i].type != END) + { + if ( (notify_info_data_table[i].type == type ) && + (notify_info_data_table[i].field == field ) ) + { + return (notify_info_data_table[i].size); + continue; + } + i++; + } + return (65535); +} + +/******************************************************************* +return the type of notify_info_data +********************************************************************/ +BOOL type_of_notify_info_data(uint16 type, uint16 field) +{ + int i=0; + + while (notify_info_data_table[i].type != END) + { + if ( (notify_info_data_table[i].type == type ) && + (notify_info_data_table[i].field == field ) ) + { + if (notify_info_data_table[i].size == POINTER) + { + return (False); + } + else + { + return (True); + } + continue; + } + i++; + } + return (False); +} + +/**************************************************************************** +****************************************************************************/ +static int search_notify(uint16 type, uint16 field, int *value) +{ + int j; + BOOL found; + + DEBUG(4,("\tsearch_notify: in\n")); + for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++) + { + if ( (notify_info_data_table[j].type == type ) && + (notify_info_data_table[j].field == field ) ) + { + found=True; + } + } + *value=--j; + + if ( found && (notify_info_data_table[j].fn != NULL) ) + { + DEBUG(4,("\tsearch_notify: out TRUE\n")); + return (True); + } + else + { + DEBUG(4,("\tsearch_notify: out FALSE\n")); + return (False); + } +} + +/**************************************************************************** +****************************************************************************/ +static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id) +{ + DEBUG(4,("\tconstruct_info_data: in\n")); + info_data->type = type; + info_data->field = field; + info_data->id = id; + info_data->size = size_of_notify_info_data(type, field); + info_data->enc_type = type_of_notify_info_data(type, field); + DEBUG(4,("\tconstruct_info_data: out\n")); +} + + +/******************************************************************* + * + * fill a notify_info struct with info asked + * + ********************************************************************/ +static void construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int pnum, + int snum, int i, uint32 id) +{ + + int k,j; + uint16 type; + uint16 field; + + SPOOL_NOTIFY_INFO_DATA *info_data; + print_queue_struct *queue=NULL; + NT_PRINTER_INFO_LEVEL printer; + + DEBUG(4,("construct_notify_printer_info\n")); + + info_data=&(info->data[info->count]); + + type = Printer[pnum].notify_info[i].type; + + DEBUGADD(4,("Notify number %d -> number of notify info: %d\n",i,Printer[pnum].notify_info[i].count)); + + if (!get_a_printer(&printer, 2, lp_servicename(snum))) + { + + for(k=0; k<Printer[pnum].notify_info[i].count; k++) + { + field = Printer[pnum].notify_info[i].fields[k]; + DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", k, type, field)); + + if (search_notify(type, field, &j) ) + { + DEBUGADD(4,("j=[%d]:%s\n", j, notify_info_data_table[j].name)); + construct_info_data(info_data, type, field, id); + + DEBUGADD(4,("notify_info_data_table: in\n")); + notify_info_data_table[j].fn(snum, info_data, queue, &printer); + DEBUGADD(4,("notify_info_data_table: out\n")); + info->count++; + info_data=&(info->data[info->count]); + } + } + + free_a_printer(printer, 2); + } +} + +/******************************************************************* + * + * fill a notify_info struct with info asked + * + ********************************************************************/ +static void construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, + int pnum, int snum, int i, uint32 id) +{ + + int k,j; + uint16 type; + uint16 field; + + SPOOL_NOTIFY_INFO_DATA *info_data; + NT_PRINTER_INFO_LEVEL printer; + + DEBUG(4,("construct_notify_jobs_info\n")); + info_data=&(info->data[info->count]); + + type = Printer[pnum].notify_info[i].type; + + DEBUGADD(4,("Notify number %d -> number of notify info: %d\n",i,Printer[pnum].notify_info[i].count)); + + if (!get_a_printer(&printer, 2, lp_servicename(snum))) + { + for(k=0; k<Printer[pnum].notify_info[i].count; k++) + { + field = Printer[pnum].notify_info[i].fields[k]; + DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n",k, type, field)); + + if (search_notify(type, field, &j) ) + { + DEBUGADD(4,("j=[%d]:%s\n", j, notify_info_data_table[j].name)); + construct_info_data(info_data, type, field, id); + DEBUGADD(4,("notify_info_data_table: in\n")); + notify_info_data_table[j].fn(snum, info_data, queue, &printer); + DEBUGADD(4,("notify_info_data_table: out\n")); + info->count++; + info_data=&(info->data[info->count]); + } + } + free_a_printer(printer, 2); + } +} + + +/******************************************************************* + * + * enumerate all printers on the printserver + * fill a notify_info struct with info asked + * + ********************************************************************/ +static void printserver_notify_info(PRINTER_HND *hnd, SPOOL_NOTIFY_INFO *info) +{ + int snum; + int pnum=find_printer_index_by_hnd(hnd); + int n_services=lp_numservices(); + int i=0; + uint32 id=1; + info->count=0; + + DEBUG(4,("Enumerating printers\n")); + + for (i=0; i<Printer[pnum].number_of_notify; i++) + { + if ( Printer[pnum].notify_info[i].type == PRINTER_NOTIFY_TYPE ) + { + for (snum=0; snum<n_services; snum++) + { + if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) + { + construct_notify_printer_info(info, pnum, snum, i, id); + id++; + } + } + } + } + DEBUG(4,("All printers enumerated\n")); +} + +/******************************************************************* + * + * fill a notify_info struct with info asked + * + ********************************************************************/ +static void printer_notify_info(PRINTER_HND *hnd, SPOOL_NOTIFY_INFO *info) +{ + int snum; + int pnum=find_printer_index_by_hnd(hnd); + int i=0, j; + uint32 id=0xFFFF; + + info->count=0; + + if (get_printer_snum(hnd, &snum) ) + { + for (i=0; i<Printer[pnum].number_of_notify; i++) + { + switch ( Printer[pnum].notify_info[i].type ) + { + case PRINTER_NOTIFY_TYPE: + { + construct_notify_printer_info(info, pnum, snum, i, id); + id--; + break; + } + case JOB_NOTIFY_TYPE: + { + int count; + print_queue_struct *queue=NULL; + print_status_struct status; + bzero(&status, sizeof(status)); + count=get_printqueue(snum, 0, &queue, &status); + for (j=0; j<count; j++) + { + construct_notify_jobs_info(&(queue[j]), info, pnum, snum, i, queue[j].job); + } + break; + } + } + } + } +} + +/******************************************************************** + * api_spoolss_reply_rfnpcnex + * + * called from api_spoolss_rfnpcnex (see this to understand) + ********************************************************************/ +static void spoolss_reply_rfnpcnex(SPOOL_Q_RFNPCNEX *q_u, prs_struct *rdata) +{ + SPOOL_R_RFNPCNEX r_u; + int pnum=find_printer_index_by_hnd(&(q_u->handle)); + + if (OPEN_HANDLE(pnum)) + { + DEBUG(4,("Printer %x of type %x\n",pnum,Printer[pnum].printer_type)); + switch (Printer[pnum].printer_type) + { + case PRINTER_HANDLE_IS_PRINTSERVER: + printserver_notify_info(&(q_u->handle), &(r_u.info)); + break; + case PRINTER_HANDLE_IS_PRINTER: + printer_notify_info(&(q_u->handle), &(r_u.info)); + break; + } + + spoolss_io_r_rfnpcnex("", &r_u, rdata, 0); + } +} + +/******************************************************************** + * api_spoolss_rfnpcnex + * ReplyFindNextPrinterChangeNotifyEx + * called from the spoolss dispatcher + * + ********************************************************************/ +static void api_spoolss_rfnpcnex(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_RFNPCNEX q_u; + + spoolss_io_q_rfnpcnex("", &q_u, data, 0); + + spoolss_reply_rfnpcnex(&q_u,rdata); +} + +/******************************************************************** + * construct_printer_info_0 + * fill a printer_info_1 struct + ********************************************************************/ +static void construct_printer_info_0(PRINTER_INFO_0 *printer,int snum, pstring servername) +{ + pstring chaine; + int count; + + print_queue_struct *queue=NULL; + print_status_struct status; + bzero(&status,sizeof(status)); + count=get_printqueue(snum,0,&queue,&status); + + /* the description and the name are of the form \\server\share */ + slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, lp_servicename(snum)); + + make_unistr(&(printer->printername), chaine); + + slprintf(chaine,sizeof(chaine)-1,"\\\\%s", servername); + make_unistr(&(printer->servername), chaine); + + printer->cjobs = count; + printer->attributes = PRINTER_ATTRIBUTE_SHARED \ + | PRINTER_ATTRIBUTE_NETWORK \ + | PRINTER_ATTRIBUTE_RAW_ONLY ; + printer->unknown0 = 0x1; /* pointer */ + printer->unknown1 = 0x000A07CE; /* don't known */ + printer->unknown2 = 0x00020005; + printer->unknown3 = 0x0006000D; + printer->unknown4 = 0x02180026; + printer->unknown5 = 0x09; + printer->unknown6 = 0x36; + printer->majorversion = 0x0004; /* NT 4 */ + printer->buildversion = 0x0565; /* build 1381 */ + printer->unknown7 = 0x1; + printer->unknown8 = 0x0; + printer->unknown9 = 0x2; + printer->unknown10 = 0x3; + printer->unknown11 = 0x0; + printer->unknown12 = 0x0; + printer->unknown13 = 0x0; + printer->unknown14 = 0x1; + printer->unknown15 = 0x024a; /*586 Pentium ? */ + printer->unknown16 = 0x0; + printer->unknown17 = 0x423ed444; + printer->unknown18 = 0x0; + printer->status = status.status; + printer->unknown20 = 0x0; + printer->unknown21 = 0x0648; + printer->unknown22 = 0x0; + printer->unknown23 = 0x5; + +} + +/******************************************************************** + * construct_printer_info_1 + * fill a printer_info_1 struct + ********************************************************************/ +static BOOL construct_printer_info_1(PRINTER_INFO_1 *printer,int snum, pstring servername) +{ + pstring chaine; + NT_PRINTER_INFO_LEVEL ntprinter; + + if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0) + { + return (False); + } + + printer->flags=PRINTER_ENUM_NAME; + + /* the description and the name are of the form \\server\share */ + slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s,%s,%s",servername, + ntprinter.info_2->printername, + ntprinter.info_2->drivername, + lp_comment(snum)); + make_unistr(&(printer->description), chaine); + + slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s", servername, ntprinter.info_2->printername); + make_unistr(&(printer->name), chaine); + + make_unistr(&(printer->comment), lp_comment(snum)); + + free_a_printer(ntprinter, 2); + return (True); +} + +/**************************************************************************** +****************************************************************************/ +static void construct_dev_mode(DEVICEMODE *devmode, int snum, char *servername) +{ + char adevice[32]; + char aform[32]; + NT_PRINTER_INFO_LEVEL printer; + NT_DEVICEMODE *ntdevmode; + + DEBUG(7,("construct_dev_mode\n")); + + bzero(&(devmode->devicename), 2*sizeof(adevice)); + bzero(&(devmode->formname), 2*sizeof(aform)); + + DEBUGADD(8,("getting printer characteristics\n")); + + get_a_printer(&printer, 2, lp_servicename(snum)); + ntdevmode=(printer.info_2)->devmode; + + DEBUGADD(8,("loading DEVICEMODE\n")); + snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, + printer.info_2->printername); + make_unistr(&(devmode->devicename), adevice); + + snprintf(aform, sizeof(aform), ntdevmode->formname); + make_unistr(&(devmode->formname), aform); + + devmode->specversion = ntdevmode->specversion; + devmode->driverversion = ntdevmode->driverversion; + devmode->size = ntdevmode->size; + devmode->driverextra = ntdevmode->driverextra; + devmode->fields = ntdevmode->fields; + + devmode->orientation = ntdevmode->orientation; + devmode->papersize = ntdevmode->papersize; + devmode->paperlength = ntdevmode->paperlength; + devmode->paperwidth = ntdevmode->paperwidth; + devmode->scale = ntdevmode->scale; + devmode->copies = ntdevmode->copies; + devmode->defaultsource = ntdevmode->defaultsource; + devmode->printquality = ntdevmode->printquality; + devmode->color = ntdevmode->color; + devmode->duplex = ntdevmode->duplex; + devmode->yresolution = ntdevmode->yresolution; + devmode->ttoption = ntdevmode->ttoption; + devmode->collate = ntdevmode->collate; + devmode->icmmethod = ntdevmode->icmmethod; + devmode->icmintent = ntdevmode->icmintent; + devmode->mediatype = ntdevmode->mediatype; + devmode->dithertype = ntdevmode->dithertype; + + if (ntdevmode->private != NULL) + { + devmode->private=(uint8 *)malloc(devmode->driverextra*sizeof(uint8)); + memcpy(devmode->private, ntdevmode->private, devmode->driverextra); + } + + free_a_printer(printer, 2); +} + +/******************************************************************** + * construct_printer_info_2 + * fill a printer_info_2 struct + ********************************************************************/ +static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum, pstring servername) +{ + pstring chaine; + int count; + DEVICEMODE *devmode; + NT_PRINTER_INFO_LEVEL ntprinter; + + print_queue_struct *queue=NULL; + print_status_struct status; + bzero(&status, sizeof(status)); + count=get_printqueue(snum, 0, &queue, &status); + + if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 ) + { + return (False); + } + + snprintf(chaine, sizeof(chaine)-1, "\\\\%s", servername); + make_unistr(&(printer->servername), chaine); /* servername*/ + + snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", servername, ntprinter.info_2->printername); + make_unistr(&(printer->printername), chaine); /* printername*/ + + make_unistr(&(printer->sharename), lp_servicename(snum)); /* sharename */ + + make_unistr(&(printer->portname), lp_servicename(snum)); /* port */ + make_unistr(&(printer->drivername), ntprinter.info_2->drivername); /* drivername */ + + make_unistr(&(printer->comment), ntprinter.info_2->comment); /* comment */ + make_unistr(&(printer->location), ntprinter.info_2->location); /* location */ + make_unistr(&(printer->sepfile), ntprinter.info_2->sepfile); /* separator file */ + make_unistr(&(printer->printprocessor), ntprinter.info_2->printprocessor);/* print processor */ + make_unistr(&(printer->datatype), ntprinter.info_2->datatype); /* datatype */ + make_unistr(&(printer->parameters), ntprinter.info_2->parameters); /* parameters (of print processor) */ + + printer->attributes = PRINTER_ATTRIBUTE_SHARED \ + | PRINTER_ATTRIBUTE_NETWORK \ + | PRINTER_ATTRIBUTE_RAW_ONLY ; /* attributes */ + + printer->priority = ntprinter.info_2->priority; /* priority */ + printer->defaultpriority = ntprinter.info_2->default_priority; /* default priority */ + printer->starttime = ntprinter.info_2->starttime; /* starttime */ + printer->untiltime = ntprinter.info_2->untiltime; /* untiltime */ + printer->status = status.status; /* status */ + printer->cjobs = count; /* jobs */ + printer->averageppm = ntprinter.info_2->averageppm; /* average pages per minute */ + + devmode=(DEVICEMODE *)malloc(sizeof(DEVICEMODE)); + ZERO_STRUCTP(devmode); + construct_dev_mode(devmode, snum, servername); + printer->devmode=devmode; + + return (True); +} + +/******************************************************************** + * enum_printer_info_1 + * glue between spoolss_reply_enumprinters and construct_printer_info_1 + ********************************************************************/ +static BOOL enum_printer_info_1(PRINTER_INFO_1 **printer, int snum, int number) +{ + pstring servername; + + *printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1)); + DEBUG(4,("Allocated memory for ONE PRINTER_INFO_1 at [%p]\n", *printer)); + pstrcpy(servername, global_myname); + if (!construct_printer_info_1(*printer, snum, servername)) + { + free(*printer); + return (False); + } + else + { + return (True); + } +} + +/******************************************************************** + * enum_printer_info_2 + * glue between spoolss_reply_enumprinters and construct_printer_info_2 + ********************************************************************/ +static BOOL enum_printer_info_2(PRINTER_INFO_2 **printer, int snum, int number) +{ + pstring servername; + + *printer=(PRINTER_INFO_2 *)malloc(sizeof(PRINTER_INFO_2)); + DEBUG(4,("Allocated memory for ONE PRINTER_INFO_2 at [%p]\n", *printer)); + pstrcpy(servername, global_myname); + if (!construct_printer_info_2(*printer, snum, servername)) + { + free(*printer); + return (False); + } + else + { + return (True); + } +} + +/******************************************************************** + * api_spoolss_reply_enumprinters + * + * called from api_spoolss_enumprinters (see this to understand) + ********************************************************************/ +static void enum_all_printers_info_1(PRINTER_INFO_1 ***printers, uint32 *number) +{ + int snum; + int n_services=lp_numservices(); + *printers=NULL; + *number=0; + + for (snum=0;snum<n_services; snum++) + { + if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) + { + DEBUG(4,("Found a printer: %s[%x]\n",lp_servicename(snum),snum)); + *printers=Realloc(*printers, (*number+1)*sizeof(PRINTER_INFO_1 *)); + DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1 pointers at [%p]\n", *number+1, *printers)); + if (enum_printer_info_1( &((*printers)[*number]), snum, *number) ) + { + (*number)++; + } + } + } +} + +/******************************************************************** + * api_spoolss_reply_enumprinters + * + * called from api_spoolss_enumprinters (see this to understand) + ********************************************************************/ +static void enum_all_printers_info_2(PRINTER_INFO_2 ***printers, uint32 *number) +{ + int snum; + int n_services=lp_numservices(); + *printers=NULL; + *number=0; + + for (snum=0;snum<n_services; snum++) + { + if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) + { + DEBUG(4,("Found a printer: %s[%x]\n",lp_servicename(snum),snum)); + *printers=Realloc(*printers, (*number+1)*sizeof(PRINTER_INFO_2 *)); + DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1 pointers at [%p]\n", *number+1, *printers)); + if (enum_printer_info_2( &((*printers)[*number]), snum, *number) ) + { + (*number)++; + } + } + } +} + +/**************************************************************************** +****************************************************************************/ +static void free_enum_printers_info_1(PRINTER_INFO_1 **printers, uint32 total) +{ + int number=0; + if (printers != NULL) + { + for (number=0; number<total; number++) + { + if (printers[number] != NULL) + { + free(printers[number]); + } + } + free(printers); + } +} + +/**************************************************************************** +****************************************************************************/ +static void free_enum_printers_info_2(PRINTER_INFO_2 **printers, uint32 total) +{ + int number=0; + if (printers != NULL) + { + for (number=0; number<total; number++) + { + if (printers[number] != NULL) + { + free(printers[number]->devmode); + free(printers[number]); + } + } + free(printers); + } +} + +/**************************************************************************** +****************************************************************************/ +static void free_enum_printers_info(SPOOL_R_ENUMPRINTERS *r_u) +{ + DEBUG(4,("free_enum_printers_info: [%d] structs to free at level [%d]\n", r_u->returned, r_u->level)); + switch (r_u->level) + { + case 1: + free_enum_printers_info_1(r_u->printer.printers_1, r_u->returned); + break; + case 2: + free_enum_printers_info_2(r_u->printer.printers_2, r_u->returned); + break; + } +} + +/******************************************************************** + * api_spoolss_reply_enumprinters + * + * called from api_spoolss_enumprinters (see this to understand) + ********************************************************************/ +static void spoolss_reply_enumprinters(SPOOL_Q_ENUMPRINTERS *q_u, prs_struct *rdata) +{ + SPOOL_R_ENUMPRINTERS r_u; + + DEBUG(4,("Enumerating printers\n")); + + memcpy(r_u.servername.buffer,q_u->servername.buffer,2*q_u->servername.uni_str_len); + r_u.servername.buffer[q_u->servername.uni_str_len]=0x0000; + r_u.returned=0; + + switch (q_u->level) + { + case 1: + if ( (q_u->flags==PRINTER_ENUM_NAME) || (q_u->flags==PRINTER_ENUM_NETWORK) ) + /*if (is_a_printerserver(q_u->servername))*/ + enum_all_printers_info_1(&(r_u.printer.printers_1), &(r_u.returned) ); + /*else + enum_one_printer_info_1(&r_u);*/ + break; + case 2: + if ( (q_u->flags==PRINTER_ENUM_NAME) || (q_u->flags==PRINTER_ENUM_NETWORK) ) + /*if (is_a_printerserver(q_u->servername))*/ + enum_all_printers_info_2(&(r_u.printer.printers_2), &(r_u.returned) ); + /*else + enum_one_printer_info_2(&r_u);*/ + break; + case 3: /* doesn't exist */ + break; + case 4: /* can't, always on local machine */ + break; + case 5: + break; + + } + DEBUG(4,("%d printers enumerated\n", r_u.returned)); + r_u.offered=q_u->buffer.size; + r_u.level=q_u->level; + r_u.status=0x0000; + + spoolss_io_r_enumprinters("",&r_u,rdata,0); + free_enum_printers_info(&r_u); +} + +/******************************************************************** + * api_spoolss_enumprinters + * called from the spoolss dispatcher + * + ********************************************************************/ +static void api_spoolss_enumprinters(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ENUMPRINTERS q_u; + + spoolss_io_q_enumprinters("", &q_u, data, 0); + + spoolss_reply_enumprinters(&q_u,rdata); +} + + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_getprinter(SPOOL_Q_GETPRINTER *q_u, prs_struct *rdata) +{ + SPOOL_R_GETPRINTER r_u; + int snum; + pstring servername; + + pstrcpy(servername, global_myname); + + get_printer_snum(&(q_u->handle),&snum); + + switch (q_u->level) + { + case 0: + { + PRINTER_INFO_0 *printer; + + printer=(PRINTER_INFO_0 *)malloc(sizeof(PRINTER_INFO_0)); + + construct_printer_info_0(printer, snum, servername); + r_u.printer.info0=printer; + r_u.status=0x0000; + r_u.offered=q_u->offered; + r_u.level=q_u->level; + + spoolss_io_r_getprinter("",&r_u,rdata,0); + + free(printer); + + break; + } + case 1: + { + PRINTER_INFO_1 *printer; + + printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1)); + + construct_printer_info_1(printer, snum, servername); + + r_u.printer.info1=printer; + r_u.status=0x0000; + r_u.offered=q_u->offered; + r_u.level=q_u->level; + spoolss_io_r_getprinter("",&r_u,rdata,0); + + free(printer); + + break; + } + case 2: + { + PRINTER_INFO_2 *printer; + + printer=(PRINTER_INFO_2 *)malloc(sizeof(PRINTER_INFO_2)); + construct_printer_info_2(printer, snum, servername); + + r_u.printer.info2=printer; + r_u.status=0x0000; + r_u.offered=q_u->offered; + r_u.level=q_u->level; + spoolss_io_r_getprinter("",&r_u,rdata,0); + + free(printer->devmode); + free(printer); + + break; + } + } +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static void api_spoolss_getprinter(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_GETPRINTER q_u; + + spoolss_io_q_getprinter("", &q_u, data, 0); + + spoolss_reply_getprinter(&q_u, rdata); +} + +/******************************************************************** + * construct_printer_driver_info_1 + * fill a construct_printer_driver_info_1 struct + ********************************************************************/ +static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, + NT_PRINTER_DRIVER_INFO_LEVEL driver, + pstring servername, fstring architecture) +{ + make_unistr( &(info->name), driver.info_3->name); +} + +static void construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, + pstring servername, fstring architecture) +{ + NT_PRINTER_INFO_LEVEL printer; + NT_PRINTER_DRIVER_INFO_LEVEL driver; + + get_a_printer(&printer, 2, lp_servicename(snum) ); + get_a_printer_driver(&driver, 3, printer.info_2->drivername, architecture); + + fill_printer_driver_info_1(info, driver, servername, architecture); + + free_a_printer_driver(driver, 3); + free_a_printer(printer, 2); +} + +/******************************************************************** + * construct_printer_driver_info_2 + * fill a printer_info_2 struct + ********************************************************************/ +static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, + NT_PRINTER_DRIVER_INFO_LEVEL driver, + pstring servername, fstring architecture) +{ + pstring where; + pstring temp_driverpath; + pstring temp_datafile; + pstring temp_configfile; + fstring short_archi; + + get_short_archi(short_archi,architecture); + + snprintf(where,sizeof(where)-1,"\\\\%s\\print$\\%s\\", servername, short_archi); + + info->version=driver.info_3->cversion; + + make_unistr( &(info->name), driver.info_3->name ); + make_unistr( &(info->architecture), architecture ); + + snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "%s%s", where, + driver.info_3->driverpath); + make_unistr( &(info->driverpath), temp_driverpath ); + + snprintf(temp_datafile, sizeof(temp_driverpath)-1, "%s%s", where, + driver.info_3->datafile); + make_unistr( &(info->datafile), temp_datafile ); + + snprintf(temp_configfile, sizeof(temp_driverpath)-1, "%s%s", where, + driver.info_3->configfile); + make_unistr( &(info->configfile), temp_configfile ); +} + +/******************************************************************** + * construct_printer_driver_info_2 + * fill a printer_info_2 struct + ********************************************************************/ +static void construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, + pstring servername, fstring architecture) +{ + NT_PRINTER_INFO_LEVEL printer; + NT_PRINTER_DRIVER_INFO_LEVEL driver; + + get_a_printer(&printer, 2, lp_servicename(snum) ); + get_a_printer_driver(&driver, 3, printer.info_2->drivername, architecture); + + fill_printer_driver_info_2(info, driver, servername, architecture); + + free_a_printer_driver(driver, 3); + free_a_printer(printer, 2); +} + +/******************************************************************** + * construct_printer_info_3 + * fill a printer_info_3 struct + ********************************************************************/ +static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, + NT_PRINTER_DRIVER_INFO_LEVEL driver, + pstring servername, fstring architecture) +{ + pstring where; + pstring temp_driverpath; + pstring temp_datafile; + pstring temp_configfile; + pstring temp_helpfile; + fstring short_archi; + + get_short_archi(short_archi, architecture); + + snprintf(where,sizeof(where)-1,"\\\\%s\\print$\\%s\\", servername, short_archi); + + info->version=driver.info_3->cversion; + + make_unistr( &(info->name), driver.info_3->name ); + make_unistr( &(info->architecture), architecture ); + + snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "%s%s", where, driver.info_3->driverpath); + make_unistr( &(info->driverpath), temp_driverpath ); + + snprintf(temp_datafile, sizeof(temp_datafile)-1, "%s%s", where, driver.info_3->datafile); + make_unistr( &(info->datafile), temp_datafile ); + + snprintf(temp_configfile, sizeof(temp_configfile)-1, "%s%s", where, driver.info_3->configfile); + make_unistr( &(info->configfile), temp_configfile ); + + snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "%s%s", where, driver.info_3->helpfile); + make_unistr( &(info->helpfile), temp_helpfile ); + + make_unistr( &(info->monitorname), driver.info_3->monitorname ); + make_unistr( &(info->defaultdatatype), driver.info_3->defaultdatatype ); + + make_unistr( &(info->dependentfiles), "" ); +} + +/******************************************************************** + * construct_printer_info_3 + * fill a printer_info_3 struct + ********************************************************************/ +static void construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, + pstring servername, fstring architecture) +{ + NT_PRINTER_INFO_LEVEL printer; + NT_PRINTER_DRIVER_INFO_LEVEL driver; + + get_a_printer(&printer, 2, lp_servicename(snum) ); + get_a_printer_driver(&driver, 3, printer.info_2->drivername, architecture); + + fill_printer_driver_info_3(info, driver, servername, architecture); + + free_a_printer_driver(driver, 3); + free_a_printer(printer, 2); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_getprinterdriver2(SPOOL_Q_GETPRINTERDRIVER2 *q_u, prs_struct *rdata) +{ + SPOOL_R_GETPRINTERDRIVER2 r_u; + pstring servername; + fstring architecture; + int snum; + DRIVER_INFO_1 *info1=NULL; + DRIVER_INFO_2 *info2=NULL; + DRIVER_INFO_3 *info3=NULL; + + pstrcpy(servername, global_myname); + get_printer_snum(&(q_u->handle),&snum); + + r_u.offered=q_u->buf_size; + r_u.level=q_u->level; + r_u.status=0x0000; + + unistr2_to_ascii(architecture, &(q_u->architecture), sizeof(architecture) ); + + DEBUG(1,("spoolss_reply_getprinterdriver2:[%d]\n", q_u->level)); + + switch (q_u->level) + { + case 1: + { + info1=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1)); + construct_printer_driver_info_1(info1, snum, servername, architecture); + r_u.printer.info1=info1; + break; + } + case 2: + { + info2=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2)); + construct_printer_driver_info_2(info2, snum, servername, architecture); + r_u.printer.info2=info2; + break; + } + case 3: + { + info3=(DRIVER_INFO_3 *)malloc(sizeof(DRIVER_INFO_3)); + construct_printer_driver_info_3(info3, snum, servername, architecture); + r_u.printer.info3=info3; + break; + } + } + + spoolss_io_r_getprinterdriver2("",&r_u,rdata,0); + + if (info1!=NULL) free(info1); + if (info2!=NULL) free(info2); + if (info3!=NULL) free(info3); + +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static void api_spoolss_getprinterdriver2(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_GETPRINTERDRIVER2 q_u; + + spoolss_io_q_getprinterdriver2("", &q_u, data, 0); + + spoolss_reply_getprinterdriver2(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_startpageprinter(SPOOL_Q_STARTPAGEPRINTER *q_u, prs_struct *rdata) +{ + SPOOL_R_STARTPAGEPRINTER r_u; + int pnum = find_printer_index_by_hnd(&(q_u->handle)); + + if (OPEN_HANDLE(pnum)) + { + Printer[pnum].page_started=True; + r_u.status=0x0; + + spoolss_io_r_startpageprinter("",&r_u,rdata,0); + } + else + { + DEBUG(3,("Error in startpageprinter printer handle (pnum=%x)\n",pnum)); + } +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static void api_spoolss_startpageprinter(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_STARTPAGEPRINTER q_u; + + spoolss_io_q_startpageprinter("", &q_u, data, 0); + + spoolss_reply_startpageprinter(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_endpageprinter(SPOOL_Q_ENDPAGEPRINTER *q_u, prs_struct *rdata) +{ + SPOOL_R_ENDPAGEPRINTER r_u; + int pnum = find_printer_index_by_hnd(&(q_u->handle)); + + if (OPEN_HANDLE(pnum)) + { + Printer[pnum].page_started=False; + r_u.status=0x0; + + spoolss_io_r_endpageprinter("",&r_u,rdata,0); + } + else + { + DEBUG(3,("Error in endpageprinter printer handle (pnum=%x)\n",pnum)); + } +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static void api_spoolss_endpageprinter(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ENDPAGEPRINTER q_u; + + spoolss_io_q_endpageprinter("", &q_u, data, 0); + + spoolss_reply_endpageprinter(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_startdocprinter(SPOOL_Q_STARTDOCPRINTER *q_u, prs_struct *rdata) +{ + SPOOL_R_STARTDOCPRINTER r_u; + int pnum = find_printer_index_by_hnd(&(q_u->handle)); + + if (OPEN_HANDLE(pnum)) + { + r_u.jobid=Printer[pnum].current_jobid; + r_u.status=0x0; + + spoolss_io_r_startdocprinter("",&r_u,rdata,0); + } + else + { + DEBUG(3,("Error in startdocprinter printer handle (pnum=%x)\n",pnum)); + } +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static void api_spoolss_startdocprinter(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_STARTDOCPRINTER q_u; + pstring fname; + pstring tempname; + int fd = -1; + int snum; + int pnum; + + /* decode the stream and fill the struct */ + spoolss_io_q_startdocprinter("", &q_u, data, 0); + + pnum = find_printer_index_by_hnd(&(q_u.handle)); + + if (OPEN_HANDLE(pnum)) + { + /* get the share number of the printer */ + get_printer_snum(&(q_u.handle),&snum); + + /* Create a temporary file in the printer spool directory + * and open it + */ + + slprintf(tempname,sizeof(tempname)-1, "%s/smb_print.XXXXXX",lp_pathname(snum)); + pstrcpy(fname, (char *)mktemp(tempname)); + + fd=open(fname, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); + DEBUG(4,("Temp spool file created: [%s]\n", fname)); + + Printer[pnum].current_jobid=fd; + pstrcpy(Printer[pnum].document_name,fname); + + unistr2_to_ascii(Printer[pnum].job_name, + &(q_u.doc_info_container.docinfo.doc_info_1.docname), + sizeof(Printer[pnum].job_name)); + + Printer[pnum].document_fd=fd; + Printer[pnum].document_started=True; + } + spoolss_reply_startdocprinter(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_enddocprinter(SPOOL_Q_ENDDOCPRINTER *q_u, prs_struct *rdata) +{ + SPOOL_R_ENDDOCPRINTER r_u; + int pnum = find_printer_index_by_hnd(&(q_u->handle)); + + if (OPEN_HANDLE(pnum)) + { + r_u.status=0x0; + + spoolss_io_r_enddocprinter("",&r_u,rdata,0); + } + else + { + DEBUG(3,("Error in enddocprinter printer handle (pnum=%x)\n",pnum)); + } +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static void api_spoolss_enddocprinter(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ENDDOCPRINTER q_u; + int pnum; + int snum; + pstring filename; + pstring filename1; + pstring job_name; + pstring syscmd; + char *tstr; + + spoolss_io_q_enddocprinter("", &q_u, data, 0); + + *syscmd=0; + + pnum = find_printer_index_by_hnd(&(q_u.handle)); + + if (OPEN_HANDLE(pnum)) + { + Printer[pnum].document_started=False; + close(Printer[pnum].document_fd); + DEBUG(4,("Temp spool file closed, printing now ...\n")); + + pstrcpy(filename1, Printer[pnum].document_name); + pstrcpy(job_name, Printer[pnum].job_name); + + get_printer_snum(&(q_u.handle),&snum); + + /* copy the command into the buffer for extensive meddling. */ + StrnCpy(syscmd, lp_printcommand(snum), sizeof(pstring) - 1); + + /* look for "%s" in the string. If there is no %s, we cannot print. */ + if (!strstr(syscmd, "%s") && !strstr(syscmd, "%f")) + { + DEBUG(2,("WARNING! No placeholder for the filename in the print command for service %s!\n", SERVICE(snum))); + } + + if (strstr(syscmd,"%s")) + { + pstrcpy(filename,filename1); + string_sub(syscmd, "%s", filename); + } + + string_sub(syscmd, "%f", filename1); + + /* Does the service have a printername? If not, make a fake and empty */ + /* printer name. That way a %p is treated sanely if no printer */ + /* name was specified to replace it. This eventuality is logged. */ + tstr = lp_printername(snum); + if (tstr == NULL || tstr[0] == '\0') + { + DEBUG(3,( "No printer name - using %s.\n", SERVICE(snum))); + tstr = SERVICE(snum); + } + + string_sub(syscmd, "%p", tstr); + + /* If the lpr command support the 'Job' option replace here */ + string_sub(syscmd, "%j", job_name); + + if ( *syscmd != '\0') + { + int ret = smbrun(syscmd, NULL, False); + DEBUG(3,("Running the command `%s' gave %d\n", syscmd, ret)); + } + else + DEBUG(0,("Null print command?\n")); + + lpq_reset(snum); + } + + spoolss_reply_enddocprinter(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_writeprinter(SPOOL_Q_WRITEPRINTER *q_u, prs_struct *rdata) +{ + SPOOL_R_WRITEPRINTER r_u; + int pnum = find_printer_index_by_hnd(&(q_u->handle)); + + if (OPEN_HANDLE(pnum)) + { + r_u.buffer_written=Printer[pnum].document_lastwritten; + r_u.status=0x0; + + spoolss_io_r_writeprinter("",&r_u,rdata,0); + } + else + { + DEBUG(3,("Error in writeprinter printer handle (pnum=%x)\n",pnum)); + } +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static void api_spoolss_writeprinter(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_WRITEPRINTER q_u; + int pnum; + int fd; + int size; + spoolss_io_q_writeprinter("", &q_u, data, 0); + + pnum = find_printer_index_by_hnd(&(q_u.handle)); + + if (OPEN_HANDLE(pnum)) + { + fd=Printer[pnum].document_fd; + size=write(fd, q_u.buffer, q_u.buffer_size); + Printer[pnum].document_lastwritten=size; + } + + spoolss_reply_writeprinter(&q_u, rdata); +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static void control_printer(PRINTER_HND handle, uint32 command) +{ + int pnum; + int snum; + pnum = find_printer_index_by_hnd(&(handle)); + + if ( get_printer_snum(&handle, &snum) ) + { + /* + * status_printqueue requires a connection_struct + * + * anybody want to explain me what value it has here ??? + */ + + switch (command) + { + case PRINTER_CONTROL_PAUSE: + /* pause the printer here */ + status_printqueue(0, snum, LPSTAT_STOPPED); + break; + + case PRINTER_CONTROL_RESUME: + case PRINTER_CONTROL_UNPAUSE: + /* UN-pause the printer here */ + status_printqueue(0, snum, LPSTAT_OK); + break; + case PRINTER_CONTROL_PURGE: + /* Envoi des dragées FUCA dans l'imprimante */ + break; + } + } +} + +/******************************************************************** + * called by spoolss_api_setprinter + * when updating a printer description + ********************************************************************/ +static void update_printer(PRINTER_HND handle, uint32 level, + SPOOL_PRINTER_INFO_LEVEL info, DEVICEMODE *devmode) +{ + int pnum; + int snum; + NT_PRINTER_INFO_LEVEL printer; + NT_DEVICEMODE *nt_devmode; + + nt_devmode=NULL; + + DEBUG(8,("update_printer\n")); + + if (level!=2) + { + DEBUG(0,("Send a mail to samba-bugs@samba.org\n")); + DEBUGADD(0,("with the following message: update_printer: level!=2\n")); + return; + } + + pnum = find_printer_index_by_hnd(&handle); + + if ( get_printer_snum(&handle, &snum) ) + { + get_a_printer(&printer, level, lp_servicename(snum)); + + DEBUGADD(8,("Converting info_2 struct\n")); + convert_printer_info(info, &printer, level); + + if ((info.info_2)->devmode_ptr != 0) + { + /* we have a valid devmode + convert it and link it*/ + + /* the nt_devmode memory is already alloced + * while doing the get_a_printer call + * but the devmode private part is not + * it's done by convert_devicemode + */ + DEBUGADD(8,("Converting the devicemode struct\n")); + nt_devmode=printer.info_2->devmode; + + init_devicemode(nt_devmode); + + convert_devicemode(*devmode, nt_devmode); + + /* now clear the memory used in + * the RPC parsing routine + */ + if (devmode->private != NULL) + free(devmode->private); + free(devmode); + } + else + { + if (printer.info_2->devmode != NULL) + { + free(printer.info_2->devmode); + } + printer.info_2->devmode=NULL; + } + + add_a_printer(printer, level); + free_a_printer(printer, level); + } +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_setprinter(SPOOL_Q_SETPRINTER *q_u, prs_struct *rdata) +{ + SPOOL_R_SETPRINTER r_u; + + /* + Let's the sun shine !!! + Always respond everything is alright + */ + + r_u.status=0x0; + + spoolss_io_r_setprinter("",&r_u,rdata,0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_setprinter(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_SETPRINTER q_u; + int pnum; + spoolss_io_q_setprinter("", &q_u, data, 0); + + pnum = find_printer_index_by_hnd(&(q_u.handle)); + + if (OPEN_HANDLE(pnum)) + { + /* check the level */ + switch (q_u.level) + { + case 0: + control_printer(q_u.handle, q_u.command); + break; + case 2: + update_printer(q_u.handle, q_u.level, q_u.info, q_u.devmode); + break; + } + } + spoolss_reply_setprinter(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_fcpn(SPOOL_Q_FCPN *q_u, prs_struct *rdata) +{ + SPOOL_R_FCPN r_u; + + r_u.status=0x0; + + spoolss_io_r_fcpn("",&r_u,rdata,0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_fcpn(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_FCPN q_u; + + spoolss_io_q_fcpn("", &q_u, data, 0); + + spoolss_reply_fcpn(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_addjob(SPOOL_Q_ADDJOB *q_u, prs_struct *rdata) +{ + SPOOL_R_ADDJOB r_u; + + r_u.status=0x0; + + spoolss_io_r_addjob("",&r_u,rdata,0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_addjob(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ADDJOB q_u; + + spoolss_io_q_addjob("", &q_u, data, 0); + + spoolss_reply_addjob(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue, + int position, int snum) +{ + pstring temp_name; + + struct tm *t; + time_t unixdate = time(NULL); + + t=gmtime(&unixdate); + snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname); + + job_info->jobid=queue->job; + make_unistr(&(job_info->printername), lp_servicename(snum)); + make_unistr(&(job_info->machinename), temp_name); + make_unistr(&(job_info->username), queue->user); + make_unistr(&(job_info->document), queue->file); + make_unistr(&(job_info->datatype), "RAW"); + make_unistr(&(job_info->text_status), ""); + job_info->status=queue->status; + job_info->priority=queue->priority; + job_info->position=position; + job_info->totalpages=0; + job_info->pagesprinted=0; + + make_systemtime(&(job_info->submitted), t); +} + +/**************************************************************************** +****************************************************************************/ +static void fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue, + int position, int snum) +{ + pstring temp_name; + + struct tm *t; + time_t unixdate = time(NULL); + + t=gmtime(&unixdate); + snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname); + + job_info->jobid=queue->job; + make_unistr(&(job_info->printername), lp_servicename(snum)); + make_unistr(&(job_info->machinename), temp_name); + make_unistr(&(job_info->username), queue->user); + make_unistr(&(job_info->document), queue->file); + make_unistr(&(job_info->notifyname), queue->user); + make_unistr(&(job_info->datatype), "RAW"); + make_unistr(&(job_info->printprocessor), "winprint"); + make_unistr(&(job_info->parameters), ""); + +/* here the devicemode should be filled up */ + + make_unistr(&(job_info->text_status), ""); + +/* and here the security descriptor */ + + job_info->status=queue->status; + job_info->priority=queue->priority; + job_info->position=position; + job_info->starttime=0; + job_info->untiltime=0; + job_info->totalpages=0; + job_info->size=queue->size; + make_systemtime(&(job_info->submitted), t); + job_info->timeelapsed=0; + job_info->pagesprinted=0; +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_enumjobs(SPOOL_Q_ENUMJOBS *q_u, prs_struct *rdata) +{ + SPOOL_R_ENUMJOBS r_u; + int snum; + int count; + int i; + print_queue_struct *queue=NULL; + print_status_struct status; + JOB_INFO_1 *job_info_1=NULL; + JOB_INFO_2 *job_info_2=NULL; + + DEBUG(4,("spoolss_reply_enumjobs\n")); + + bzero(&status,sizeof(status)); + + r_u.offered=q_u->buf_size; + + + if (get_printer_snum(&(q_u->handle), &snum)) + { + count=get_printqueue(snum, 0, &queue, &status); + r_u.numofjobs=count; + + r_u.level=q_u->level; + + DEBUG(4,("count:[%d], status:[%d], [%s]\n", count, status.status, status.message)); + + switch (r_u.level) + { + case 1: + { + job_info_1=(JOB_INFO_1 *)malloc(count*sizeof(JOB_INFO_1)); + + for (i=0; i<count; i++) + { + fill_job_info_1(&(job_info_1[i]), &(queue[i]), i, snum); + } + r_u.job.job_info_1=job_info_1; + break; + } + case 2: + { + job_info_2=(JOB_INFO_2 *)malloc(count*sizeof(JOB_INFO_2)); + + for (i=0; i<count; i++) + { + fill_job_info_2(&(job_info_2[i]), &(queue[i]), i, snum); + } + r_u.job.job_info_2=job_info_2; + break; + } + } + + } + + r_u.status=0x0; + + spoolss_io_r_enumjobs("",&r_u,rdata,0); + switch (r_u.level) + { + case 1: + { + free(job_info_1); + break; + } + case 2: + { + free(job_info_2); + break; + } + } +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_enumjobs(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ENUMJOBS q_u; + + spoolss_io_q_enumjobs("", &q_u, data, 0); + + spoolss_reply_enumjobs(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_schedulejob(SPOOL_Q_SCHEDULEJOB *q_u, prs_struct *rdata) +{ + SPOOL_R_SCHEDULEJOB r_u; + + r_u.status=0x0; + + spoolss_io_r_schedulejob("",&r_u,rdata,0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_schedulejob(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_SCHEDULEJOB q_u; + + spoolss_io_q_schedulejob("", &q_u, data, 0); + + spoolss_reply_schedulejob(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_setjob(SPOOL_Q_SETJOB *q_u, prs_struct *rdata) +{ + SPOOL_R_SETJOB r_u; + int snum; + print_queue_struct *queue=NULL; + print_status_struct status; + int i=0; + BOOL found=False; + int count; + + bzero(&status,sizeof(status)); + + if (get_printer_snum(&(q_u->handle), &snum)) + { + count=get_printqueue(snum, 0, &queue, &status); + while ( (i<count) && found==False ) + { + if ( q_u->jobid == queue[i].job ) + { + found=True; + } + i++; + } + + if (found==True) + { + switch (q_u->command) + { + case JOB_CONTROL_CANCEL: + case JOB_CONTROL_DELETE: + { + del_printqueue(0, snum, q_u->jobid); + break; + } + case JOB_CONTROL_PAUSE: + { + status_printjob(0, snum, q_u->jobid, LPQ_PAUSED); + break; + } + case JOB_CONTROL_RESUME: + { + status_printjob(0, snum, q_u->jobid, LPQ_QUEUED); + break; + } + } + } + } + r_u.status=0x0; + spoolss_io_r_setjob("",&r_u,rdata,0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_setjob(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_SETJOB q_u; + + spoolss_io_q_setjob("", &q_u, data, 0); + + spoolss_reply_setjob(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_enumprinterdrivers(SPOOL_Q_ENUMPRINTERDRIVERS *q_u, prs_struct *rdata) +{ + SPOOL_R_ENUMPRINTERDRIVERS r_u; + NT_PRINTER_DRIVER_INFO_LEVEL driver; + int count; + int i; + fstring *list; + DRIVER_INFO_1 *driver_info_1=NULL; + DRIVER_INFO_2 *driver_info_2=NULL; + DRIVER_INFO_3 *driver_info_3=NULL; + fstring servername; + fstring architecture; + + DEBUG(4,("spoolss_reply_enumdrivers\n")); + fstrcpy(servername, global_myname); + + unistr2_to_ascii(architecture, &(q_u->environment), sizeof(architecture)); + count=get_ntdrivers(&list, architecture); + + DEBUGADD(4,("we have: [%d] drivers on archi [%s]\n",count, architecture)); + for (i=0; i<count; i++) + { + DEBUGADD(5,("driver [%s]\n",list[i])); + } + + r_u.offered=q_u->buf_size; + r_u.numofdrivers=count; + r_u.level=q_u->level; + + switch (r_u.level) + { + case 1: + { + driver_info_1=(DRIVER_INFO_1 *)malloc(count*sizeof(DRIVER_INFO_1)); + + for (i=0; i<count; i++) + { + get_a_printer_driver(&driver, 3, list[i], architecture); + fill_printer_driver_info_1(&(driver_info_1[i]), driver, servername, architecture ); + free_a_printer_driver(driver, 3); + } + r_u.driver.driver_info_1=driver_info_1; + break; + } + case 2: + { + driver_info_2=(DRIVER_INFO_2 *)malloc(count*sizeof(DRIVER_INFO_2)); + + for (i=0; i<count; i++) + { + get_a_printer_driver(&driver, 3, list[i], architecture); + fill_printer_driver_info_2(&(driver_info_2[i]), driver, servername, architecture ); + free_a_printer_driver(driver, 3); + } + r_u.driver.driver_info_2=driver_info_2; + break; + } + case 3: + { + driver_info_3=(DRIVER_INFO_3 *)malloc(count*sizeof(DRIVER_INFO_3)); + + for (i=0; i<count; i++) + { + get_a_printer_driver(&driver, 3, list[i], architecture); + fill_printer_driver_info_3(&(driver_info_3[i]), driver, servername, architecture ); + free_a_printer_driver(driver, 3); + } + r_u.driver.driver_info_3=driver_info_3; + break; + } + } + + r_u.status=0x0; + + spoolss_io_r_enumdrivers("",&r_u,rdata,0); + + switch (r_u.level) + { + case 1: + { + free(driver_info_1); + break; + } + case 2: + { + free(driver_info_2); + break; + } + case 3: + { + free(driver_info_3); + break; + } + } +} + +/**************************************************************************** +****************************************************************************/ + +static void api_spoolss_enumprinterdrivers(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ENUMPRINTERDRIVERS q_u; + + spoolss_io_q_enumprinterdrivers("", &q_u, data, 0); + + spoolss_reply_enumprinterdrivers(&q_u, rdata); +} + + +/**************************************************************************** +****************************************************************************/ +static void fill_form_1(FORM_1 *form, nt_forms_struct *list, int position) +{ + form->flag=list->flag; + make_unistr(&(form->name), list->name); + form->width=list->width; + form->length=list->length; + form->left=list->left; + form->top=list->top; + form->right=list->right; + form->bottom=list->bottom; +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_enumforms(SPOOL_Q_ENUMFORMS *q_u, prs_struct *rdata) +{ + SPOOL_R_ENUMFORMS r_u; + int count; + int i; + nt_forms_struct *list=NULL; + FORM_1 *forms_1=NULL; + + DEBUG(4,("spoolss_reply_enumforms\n")); + + count=get_ntforms(&list); + r_u.offered=q_u->buf_size; + r_u.numofforms=count; + r_u.level=q_u->level; + r_u.status=0x0; + + DEBUGADD(5,("Offered buffer size [%d]\n", r_u.offered)); + DEBUGADD(5,("Number of forms [%d]\n", r_u.numofforms)); + DEBUGADD(5,("Info level [%d]\n", r_u.level)); + + switch (r_u.level) + { + case 1: + { + forms_1=(FORM_1 *)malloc(count*sizeof(FORM_1)); + for (i=0; i<count; i++) + { + DEBUGADD(6,("Filling form number [%d]\n",i)); + fill_form_1(&(forms_1[i]), &(list[i]), i); + } + r_u.forms_1=forms_1; + break; + } + } + spoolss_io_r_enumforms("",&r_u,rdata,0); + switch (r_u.level) + { + case 1: + { + free(forms_1); + break; + } + } + free(list); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_enumforms(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ENUMFORMS q_u; + + spoolss_io_q_enumforms("", &q_u, data, 0); + + spoolss_reply_enumforms(&q_u, rdata); +} + +static void fill_port_2(PORT_INFO_2 *port, char *name) +{ + make_unistr(&(port->port_name), name); + make_unistr(&(port->monitor_name), "Moniteur Local"); + make_unistr(&(port->description), "Local Port"); +#define PORT_TYPE_WRITE 1 + port->port_type=PORT_TYPE_WRITE; + port->reserved=0x0; +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_enumports(SPOOL_Q_ENUMPORTS *q_u, prs_struct *rdata) +{ + SPOOL_R_ENUMPORTS r_u; + int i=0; + PORT_INFO_2 *ports_2=NULL; + int n_services=lp_numservices(); + int snum; + + DEBUG(4,("spoolss_reply_enumports\n")); + + r_u.offered=q_u->buf_size; + r_u.level=q_u->level; + r_u.status=0x0; + + switch (r_u.level) + { + case 2: + { + ports_2=(PORT_INFO_2 *)malloc(n_services*sizeof(PORT_INFO_2)); + for (snum=0; snum<n_services; snum++) + { + if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) + { + DEBUGADD(6,("Filling port number [%d]\n",i)); + fill_port_2(&(ports_2[i]), lp_servicename(snum)); + i++; + } + } + r_u.port.port_info_2=ports_2; + break; + } + } + r_u.numofports=i; + spoolss_io_r_enumports("",&r_u,rdata,0); + switch (r_u.level) + { + case 2: + { + free(ports_2); + break; + } + } +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_enumports(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ENUMPORTS q_u; + + spoolss_io_q_enumports("", &q_u, data, 0); + + spoolss_reply_enumports(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_addprinterex(SPOOL_Q_ADDPRINTEREX *q_u, prs_struct *rdata) +{ + SPOOL_R_ADDPRINTEREX r_u; + BOOL printer_open = False; + fstring ascii_name; + fstring server_name; + fstring share_name; + UNISTR2 *portname; + SPOOL_PRINTER_INFO_LEVEL_2 *info2; + SPOOL_PRINTER_INFO_LEVEL *info; + + info=&(q_u->info); + info2=info->info_2; + portname=&(info2->portname); + + r_u.status=0x0; /* everything is always nice in this world */ + + StrnCpy(server_name, global_myname, strlen(global_myname) ); + unistr2_to_ascii(share_name, portname, sizeof(share_name)-1); + + slprintf(ascii_name, sizeof(ascii_name)-1, "\\\\%s\\%s", + server_name, share_name); + + printer_open = open_printer_hnd(&(r_u.handle)); + set_printer_hnd_printertype(&(r_u.handle), ascii_name); + set_printer_hnd_printername(&(r_u.handle), ascii_name); + + spoolss_io_r_addprinterex("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_addprinterex(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ADDPRINTEREX q_u; + NT_PRINTER_INFO_LEVEL printer; + + /* read the stream and decode */ + spoolss_io_q_addprinterex("", &q_u, data, 0); + + /* NULLify info_2 here */ + /* don't put it in convert_printer_info as it's used also with non-NULL values */ + printer.info_2=NULL; + + /* convert from UNICODE to ASCII */ + convert_printer_info(q_u.info, &printer, q_u.level); + + /* write the ASCII on disk */ + add_a_printer(printer, q_u.level); + + spoolss_reply_addprinterex(&q_u, rdata); + /* free mem used in q_u and r_u */ + + /* free_add_printer(q_u, r_u); */ +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_addprinterdriver(SPOOL_Q_ADDPRINTERDRIVER *q_u, prs_struct *rdata) +{ + SPOOL_R_ADDPRINTERDRIVER r_u; + + r_u.status=0x0; /* everything is always nice in this world */ + + spoolss_io_r_addprinterdriver("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_addprinterdriver(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ADDPRINTERDRIVER q_u; + NT_PRINTER_DRIVER_INFO_LEVEL driver; + + spoolss_io_q_addprinterdriver("", &q_u, data, 0); + + convert_printer_driver_info(q_u.info, &driver, q_u.level); + + add_a_printer_driver(driver, q_u.level); + + spoolss_reply_addprinterdriver(&q_u, rdata); + /* free mem used in q_u and r_u */ +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_getprinterdriverdirectory(SPOOL_Q_GETPRINTERDRIVERDIR *q_u, prs_struct *rdata) +{ + SPOOL_R_GETPRINTERDRIVERDIR r_u; + pstring chaine; + pstring long_archi; + pstring archi; + + r_u.offered=q_u->buf_size; + r_u.level=q_u->level; + r_u.status=0x0; + + unistr2_to_ascii(long_archi, &(q_u->environment), sizeof(long_archi)-1); + get_short_archi(archi, long_archi); + + slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\print$\\%s", global_myname, archi); + + DEBUG(4,("printer driver directory: [%s]\n", chaine)); + + make_unistr(&(r_u.driver.driver_info_1.name), chaine); + + spoolss_io_r_getprinterdriverdir("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_getprinterdriverdirectory(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_GETPRINTERDRIVERDIR q_u; + + spoolss_io_q_getprinterdriverdir("", &q_u, data, 0); + + spoolss_reply_getprinterdriverdirectory(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_enumprinterdata(SPOOL_Q_ENUMPRINTERDATA *q_u, prs_struct *rdata) +{ + SPOOL_R_ENUMPRINTERDATA r_u; + NT_PRINTER_INFO_LEVEL printer; + + uint32 type; + fstring value; + uint8 *data; + + uint32 param_index; + uint32 biggest_valuesize; + uint32 biggest_datasize; + uint32 data_len; + + int pnum = find_printer_index_by_hnd(&(q_u->handle)); + int snum; + + DEBUG(5,("spoolss_reply_enumprinterdata\n")); + + if (OPEN_HANDLE(pnum)) + { + get_printer_snum(&(q_u->handle), &snum); + get_a_printer(&printer, 2, lp_servicename(snum)); + + /* The NT machine wants to know the biggest size of value and data */ + if ( (q_u->valuesize==0) && (q_u->datasize==0) ) + { + DEBUGADD(6,("Activating NT mega-hack to find sizes\n")); + + r_u.valuesize=0; + r_u.realvaluesize=0; + r_u.type=0; + r_u.datasize=0; + r_u.realdatasize=0; + + param_index=0; + biggest_valuesize=0; + biggest_datasize=0; + + while (get_specific_param_by_index(printer, 2, param_index, value, &data, &type, &data_len)) + { + if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value); + if (data_len > biggest_datasize) biggest_datasize=data_len; + + param_index++; + } + + /* I wrote it, I didn't designed the protocol */ + SIVAL(&(r_u.value),0, 2*(biggest_valuesize+1) ); + r_u.data=(uint8 *)malloc(4*sizeof(uint8)); + SIVAL(r_u.data, 0, biggest_datasize ); + } + else + { + /* + * the value len is wrong in NT sp3 + * that's the number of bytes not the number of unicode chars + */ + + r_u.valuesize=q_u->valuesize; + r_u.datasize=q_u->datasize; + + if (get_specific_param_by_index(printer, 2, q_u->index, value, &data, &type, &data_len)) + { + make_unistr(&(r_u.value), value); + r_u.data=data; + + r_u.type=type; + + /* the length are in bytes including leading NULL */ + r_u.realvaluesize=2*(strlen(value)+1); + r_u.realdatasize=data_len; + + r_u.status=0; + } + else + { + r_u.valuesize=0; + r_u.realvaluesize=0; + r_u.datasize=0; + r_u.realdatasize=0; + r_u.type=0; + r_u.status=0x0103; /* ERROR_NO_MORE_ITEMS */ + } + } + + free_a_printer(printer, 2); + } + spoolss_io_r_enumprinterdata("", &r_u, rdata, 0); + free(r_u.data); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_enumprinterdata(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_ENUMPRINTERDATA q_u; + + spoolss_io_q_enumprinterdata("", &q_u, data, 0); + + spoolss_reply_enumprinterdata(&q_u, rdata); +} + +/**************************************************************************** +****************************************************************************/ +static void spoolss_reply_setprinterdata(SPOOL_Q_SETPRINTERDATA *q_u, prs_struct *rdata) +{ + SPOOL_R_SETPRINTERDATA r_u; + NT_PRINTER_INFO_LEVEL printer; + NT_PRINTER_PARAM *param = NULL; + + int pnum=0; + int snum=0; + + DEBUG(5,("spoolss_reply_setprinterdata\n")); + + pnum = find_printer_index_by_hnd(&(q_u->handle)); + + if (OPEN_HANDLE(pnum)) + { + get_printer_snum(&(q_u->handle), &snum); + get_a_printer(&printer, 2, lp_servicename(snum)); + convert_specific_param(¶m, q_u->value , q_u->type, q_u->data, q_u->real_len); + + unlink_specific_param_if_exist(printer.info_2, param); + + add_a_specific_param(printer.info_2, param); + + add_a_printer(printer, 2); + + free_a_printer(printer, 2); + } + + r_u.status = 0x0; + spoolss_io_r_setprinterdata("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static void api_spoolss_setprinterdata(uint16 vuid, prs_struct *data, + prs_struct *rdata) +{ + SPOOL_Q_SETPRINTERDATA q_u; + + spoolss_io_q_setprinterdata("", &q_u, data, 0); + + spoolss_reply_setprinterdata(&q_u, rdata); + + free(q_u.data); +} + +/******************************************************************* +\pipe\spoolss commands +********************************************************************/ +struct api_struct api_spoolss_cmds[] = +{ + {"SPOOLSS_OPENPRINTEREX", SPOOLSS_OPENPRINTEREX, api_spoolss_open_printer }, + {"SPOOLSS_GETPRINTERDATA", SPOOLSS_GETPRINTERDATA, api_spoolss_getprinterdata }, + {"SPOOLSS_CLOSEPRINTER", SPOOLSS_CLOSEPRINTER, api_spoolss_closeprinter }, + {"SPOOLSS_RFFPCNEX", SPOOLSS_RFFPCNEX, api_spoolss_rffpcnex }, + {"SPOOLSS_RFNPCNEX", SPOOLSS_RFNPCNEX, api_spoolss_rfnpcnex }, + {"SPOOLSS_ENUMPRINTERS", SPOOLSS_ENUMPRINTERS, api_spoolss_enumprinters }, + {"SPOOLSS_GETPRINTER", SPOOLSS_GETPRINTER, api_spoolss_getprinter }, + {"SPOOLSS_GETPRINTERDRIVER2", SPOOLSS_GETPRINTERDRIVER2, api_spoolss_getprinterdriver2 }, + {"SPOOLSS_STARTPAGEPRINTER", SPOOLSS_STARTPAGEPRINTER, api_spoolss_startpageprinter }, + {"SPOOLSS_ENDPAGEPRINTER", SPOOLSS_ENDPAGEPRINTER, api_spoolss_endpageprinter }, + {"SPOOLSS_STARTDOCPRINTER", SPOOLSS_STARTDOCPRINTER, api_spoolss_startdocprinter }, + {"SPOOLSS_ENDDOCPRINTER", SPOOLSS_ENDDOCPRINTER, api_spoolss_enddocprinter }, + {"SPOOLSS_WRITEPRINTER", SPOOLSS_WRITEPRINTER, api_spoolss_writeprinter }, + {"SPOOLSS_SETPRINTER", SPOOLSS_SETPRINTER, api_spoolss_setprinter }, + {"SPOOLSS_FCPN", SPOOLSS_FCPN, api_spoolss_fcpn }, + {"SPOOLSS_ADDJOB", SPOOLSS_ADDJOB, api_spoolss_addjob }, + {"SPOOLSS_ENUMJOBS", SPOOLSS_ENUMJOBS, api_spoolss_enumjobs }, + {"SPOOLSS_SCHEDULEJOB", SPOOLSS_SCHEDULEJOB, api_spoolss_schedulejob }, + {"SPOOLSS_SETJOB", SPOOLSS_SETJOB, api_spoolss_setjob }, + {"SPOOLSS_ENUMFORMS", SPOOLSS_ENUMFORMS, api_spoolss_enumforms }, + {"SPOOLSS_ENUMPORTS", SPOOLSS_ENUMPORTS, api_spoolss_enumports }, + {"SPOOLSS_ENUMPRINTERDRIVERS", SPOOLSS_ENUMPRINTERDRIVERS, api_spoolss_enumprinterdrivers }, + {"SPOOLSS_ADDPRINTEREX", SPOOLSS_ADDPRINTEREX, api_spoolss_addprinterex }, + {"SPOOLSS_ADDPRINTERDRIVER", SPOOLSS_ADDPRINTERDRIVER, api_spoolss_addprinterdriver }, + {"SPOOLSS_GETPRINTERDRIVERDIRECTORY", SPOOLSS_GETPRINTERDRIVERDIRECTORY, api_spoolss_getprinterdriverdirectory }, + {"SPOOLSS_ENUMPRINTERDATA", SPOOLSS_ENUMPRINTERDATA, api_spoolss_enumprinterdata }, + {"SPOOLSS_SETPRINTERDATA", SPOOLSS_SETPRINTERDATA, api_spoolss_setprinterdata }, + { NULL, 0, NULL } +}; + +/******************************************************************* +receives a spoolss pipe and responds. +********************************************************************/ +BOOL api_spoolss_rpc(pipes_struct *p, prs_struct *data) +{ + return api_rpcTNP(p, "api_spoolss_rpc", api_spoolss_cmds, data); +} + |