diff options
author | Jean-François Micouleau <jfm@samba.org> | 2000-02-07 16:17:59 +0000 |
---|---|---|
committer | Jean-François Micouleau <jfm@samba.org> | 2000-02-07 16:17:59 +0000 |
commit | 6a6749d81e892bb06bfdc0fefdc428e5e6599f71 (patch) | |
tree | 1422ec8d31fc4202f6b565015ac28dd6d0573158 /source3 | |
parent | 868c81eefa72b31023eeac32788eaa439013c0f8 (diff) | |
download | samba-6a6749d81e892bb06bfdc0fefdc428e5e6599f71.tar.gz samba-6a6749d81e892bb06bfdc0fefdc428e5e6599f71.tar.bz2 samba-6a6749d81e892bb06bfdc0fefdc428e5e6599f71.zip |
First commit of the spoolss code to the HEAD branch.
still needs a lot of cleaning/debuging.
J.F.
(This used to be commit bd9d4cdde9193c120c6f4e8cf72f87cd67a9387e)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/nt_printing.h | 237 | ||||
-rwxr-xr-x | source3/include/rpc_spoolss.h | 1441 | ||||
-rw-r--r-- | source3/printing/nt_printing.c | 1413 | ||||
-rw-r--r-- | source3/rpc_parse/parse_spoolss.c | 4806 | ||||
-rwxr-xr-x | source3/rpc_server/srv_spoolss.c | 793 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 3434 |
6 files changed, 12124 insertions, 0 deletions
diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h new file mode 100644 index 0000000000..22c837c748 --- /dev/null +++ b/source3/include/nt_printing.h @@ -0,0 +1,237 @@ +#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 + +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; + +typedef struct +{ + char name[100]; + uint32 flag; + uint32 width; + uint32 length; + uint32 left; + uint32 top; + uint32 right; + uint32 bottom; +} nt_forms_struct; + +/* +typedef struct _form +{ + uint32 flags; + uint32 name_ptr; + uint32 size_x; + uint32 size_y; + uint32 left; + uint32 top; + uint32 right; + uint32 bottom; + UNISTR2 name; +} FORM; +*/ diff --git a/source3/include/rpc_spoolss.h b/source3/include/rpc_spoolss.h new file mode 100755 index 0000000000..5aef2f3f63 --- /dev/null +++ b/source3/include/rpc_spoolss.h @@ -0,0 +1,1441 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-2000, + Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + Copyright (C) Jean Francois Micouleau 1998-2000. + + 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_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_DELETEFORM 0x1f +#define SPOOLSS_GETFORM 0x20 +#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_GETJOB 0x03 +#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_ADDFORM 0x1e +#define SPOOLSS_SETFORM 0x21 +#define SPOOLSS_ENUMFORMS 0x22 +#define SPOOLSS_ENUMPORTS 0x23 +#define SPOOLSS_ENUMMONITORS 0x24 +#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 POLICY_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 + +#define POLICY_HND_SIZE 20 + +/* this struct is undocumented */ +/* thanks to the ddk ... */ +typedef struct spool_user_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_1; + +typedef struct spool_user_ctr_info +{ + uint32 level; + uint32 ptr; + SPOOL_USER_1 user1; +} SPOOL_USER_CTR; + +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 _devmode_cont +{ + uint32 size; + uint32 devmode_ptr; + DEVICEMODE *devmode; +} DEVMODE_CTR; + +typedef struct _printer_default +{ + uint32 datatype_ptr; + UNISTR2 datatype; + DEVMODE_CTR devmode_cont; + uint32 access_required; +} PRINTER_DEFAULT; + +/* SPOOL_Q_OPEN_PRINTER_EX request to open a printer */ +typedef struct spool_q_open_printer_ex +{ + uint32 printername_ptr; + UNISTR2 printername; + PRINTER_DEFAULT printer_default; + uint32 user_switch; + SPOOL_USER_CTR user_ctr; +} SPOOL_Q_OPEN_PRINTER_EX; + +/* SPOOL_Q_OPEN_PRINTER_EX reply to an open printer */ +typedef struct spool_r_open_printer_ex +{ + POLICY_HND handle; /* handle used along all transactions (20*uint8) */ + uint32 status; + +} SPOOL_R_OPEN_PRINTER_EX; + +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 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; + +typedef struct new_buffer +{ + uint32 ptr; + uint32 size; + prs_struct prs; + uint32 struct_start; + uint32 string_at_end; +} NEW_BUFFER; + +typedef struct spool_q_getprinterdata +{ + POLICY_HND handle; + UNISTR2 valuename; + uint32 size; +} SPOOL_Q_GETPRINTERDATA; + +typedef struct spool_r_getprinterdata +{ + uint32 type; + uint32 size; + uint8 *data; + uint32 needed; + uint32 status; +} SPOOL_R_GETPRINTERDATA; + +typedef struct spool_q_closeprinter +{ + POLICY_HND handle; +} SPOOL_Q_CLOSEPRINTER; + +typedef struct spool_r_closeprinter +{ + POLICY_HND handle; + uint32 status; +} SPOOL_R_CLOSEPRINTER; + +typedef struct spool_q_startpageprinter +{ + POLICY_HND handle; +} SPOOL_Q_STARTPAGEPRINTER; + +typedef struct spool_r_startpageprinter +{ + uint32 status; +} SPOOL_R_STARTPAGEPRINTER; + +typedef struct spool_q_endpageprinter +{ + POLICY_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 +{ + POLICY_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 +{ + POLICY_HND handle; +} SPOOL_Q_ENDDOCPRINTER; + +typedef struct spool_r_enddocprinter +{ + uint32 status; +} SPOOL_R_ENDDOCPRINTER; + +typedef struct spool_q_writeprinter +{ + POLICY_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 +{ + 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 +{ + POLICY_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 +{ + POLICY_HND handle; + uint32 change; + SPOOL_NOTIFY_OPTION option; +} SPOOL_Q_RFNPCNEX; + +typedef struct spool_r_rfnpcnex +{ + uint32 count; + SPOOL_NOTIFY_INFO info; + uint32 status; + +} SPOOL_R_RFNPCNEX; + +/* Find Close Printer Notify */ +typedef struct spool_q_fcpn +{ + POLICY_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 printer_info_ctr_info +{ + union { + PRINTER_INFO_1 **printers_1; + PRINTER_INFO_2 **printers_2; + void *info; + } printer; + +} PRINTER_INFO_CTR; + +typedef struct spool_r_enumprinters +{ + uint32 offered; /* number of bytes offered */ + uint32 needed; /* bytes needed */ + uint32 level; + UNISTR servername; + PRINTER_INFO_CTR ctr; + uint32 returned; /* number of printers */ + uint32 status; + +} SPOOL_R_ENUMPRINTERS; + + +typedef struct spool_q_getprinter +{ + POLICY_HND handle; + uint32 level; + uint8* buffer; + uint32 offered; + +} SPOOL_Q_GETPRINTER; + +typedef struct printer_info_info +{ + union { + PRINTER_INFO_0 *info0; + PRINTER_INFO_1 *info1; + PRINTER_INFO_2 *info2; + void *info; + } printer; + +} PRINTER_INFO; + +typedef struct spool_r_getprinter +{ + POLICY_HND handle; + uint32 level; + + PRINTER_INFO ctr; + + uint32 offered; + uint32 needed; + uint32 status; + +} 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 +{ + POLICY_HND handle; + UNISTR2 architecture; + uint32 level; + BUFFER buffer; + uint32 buf_size; + uint32 unknown; + +} 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 driver_info_info +{ + union { + DRIVER_INFO_1 *info1; + DRIVER_INFO_2 *info2; + DRIVER_INFO_3 *info3; + } driver; + +} DRIVER_INFO; + +typedef struct spool_r_getprinterdriver2 +{ + uint32 level; + DRIVER_INFO ctr; + uint32 needed; + uint32 offered; + uint32 returned; + uint32 status; + +} SPOOL_R_GETPRINTERDRIVER2; + +typedef struct add_jobinfo_1 +{ + UNISTR path; + uint32 job_number; +} ADD_JOBINFO_1; + + +typedef struct spool_q_addjob +{ + POLICY_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 +{ + POLICY_HND handle; + uint32 firstjob; + uint32 numofjobs; + uint32 level; + BUFFER buffer; + uint32 buf_size; + +} SPOOL_Q_ENUMJOBS; + +typedef struct job_info_ctr_info +{ + union { + JOB_INFO_1 **job_info_1; + JOB_INFO_2 **job_info_2; + void *info; + } job; + +} JOB_INFO_CTR; + +typedef struct spool_r_enumjobs +{ + uint32 level; + uint32 offered; + JOB_INFO_CTR ctr; + uint32 numofjobs; + uint32 status; + +} SPOOL_R_ENUMJOBS; + +typedef struct spool_q_schedulejob +{ + POLICY_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 port_info_ctr_info +{ + union { + PORT_INFO_1 *info_1; + PORT_INFO_2 *info_2; + } port; + +} PORT_INFO_CTR; + +typedef struct spool_r_enumports +{ + uint32 level; + PORT_INFO_CTR ctr; + 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 job_info_info +{ + union { + JOB_INFO_1 job_info_1; + JOB_INFO_2 job_info_2; + } job; + +} JOB_INFO; + +typedef struct spool_q_setjob +{ + POLICY_HND handle; + uint32 jobid; + uint32 level; + JOB_INFO ctr; + 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; + DRIVER_INFO ctr; + 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 +{ + POLICY_HND handle; + uint32 level; + NEW_BUFFER *buffer; + uint32 offered; +} SPOOL_Q_ENUMFORMS; + +typedef struct spool_r_enumforms +{ + NEW_BUFFER *buffer; + uint32 needed; + 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 +{ + POLICY_HND handle; + uint32 level; + SPOOL_PRINTER_INFO_LEVEL info; + + DEVICEMODE *devmode; + + /* lkclXXXX jean-francois, see SEC_DESC_BUF code */ + 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 +{ + POLICY_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 driver_info_ctr_info +{ + union { + DRIVER_DIRECTORY_1 info_1; + } driver; + +} DRIVER_DIRECTORY_CTR; + +typedef struct spool_r_getprinterdriverdirectory +{ + uint32 level; + DRIVER_DIRECTORY_CTR ctr; + 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_enumprintmonitors +{ + UNISTR2 name; + uint32 level; + BUFFER buffer; + uint32 buf_size; +} SPOOL_Q_ENUMPRINTMONITORS; + +typedef struct printmonitor_1 +{ + UNISTR name; +} PRINTMONITOR_1; + +typedef struct spool_r_enumprintmonitors +{ + uint32 level; + PRINTMONITOR_1 *info_1; + uint32 offered; + uint32 numofprintmonitors; + uint32 status; +} SPOOL_R_ENUMPRINTMONITORS; + +typedef struct spool_q_enumprinterdata +{ + POLICY_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 +{ + POLICY_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; + +typedef struct _form +{ + uint32 flags; + uint32 name_ptr; + uint32 size_x; + uint32 size_y; + uint32 left; + uint32 top; + uint32 right; + uint32 bottom; + UNISTR2 name; +} FORM; + +typedef struct spool_q_addform +{ + POLICY_HND handle; + uint32 level; + uint32 level2; + FORM form; +} SPOOL_Q_ADDFORM; + +typedef struct spool_r_addform +{ + uint32 status; +} SPOOL_R_ADDFORM; + +typedef struct spool_q_setform +{ + POLICY_HND handle; + UNISTR2 name; + uint32 level; + uint32 level2; + FORM form; +} SPOOL_Q_SETFORM; + +typedef struct spool_r_setform +{ + uint32 status; +} SPOOL_R_SETFORM; + +typedef struct spool_q_getjob +{ + POLICY_HND handle; + uint32 jobid; + uint32 level; + BUFFER buffer; + uint32 buf_size; + +} SPOOL_Q_GETJOB; + +typedef struct pjob_info_info +{ + union { + JOB_INFO_1 *job_info_1; + JOB_INFO_2 *job_info_2; + void *info; + } job; + +} PJOB_INFO; + +typedef struct spool_r_getjob +{ + uint32 level; + PJOB_INFO ctr; + uint32 offered; + uint32 status; +} SPOOL_R_GETJOB; + +#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..00e052772e --- /dev/null +++ b/source3/printing/nt_printing.c @@ -0,0 +1,1413 @@ +#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); +} + +/**************************************************************************** +write a form struct list +****************************************************************************/ +int write_ntforms(nt_forms_struct **list, int number) +{ + FILE *f; + pstring line; + char *file = lp_nt_forms(); + int total=0; + int i; + + *line=0; + + DEBUG(6,("write_ntforms\n")); + + if((f = sys_fopen(file, "w")) == NULL) + { + DEBUG(1, ("cannot create forms file [%s]\n", file)); + return(0); + } + + for (i=0; i<number;i++) + { + + fprintf(f,"%s:%d:%d:%d:%d:%d:%d:%d\n", (*list)[i].name, + (*list)[i].flag, (*list)[i].width, (*list)[i].length, + (*list)[i].left, (*list)[i].top, (*list)[i].right, (*list)[i].bottom); + + DEBUGADD(7,("adding entry [%s]\n", (*list)[i].name)); + } + + fclose(f); + DEBUGADD(6,("closing file\n")); + return(total); +} + +/**************************************************************************** +add a form struct at the end of the list +****************************************************************************/ +void add_a_form(nt_forms_struct **list, const FORM *form, int *count) +{ + int n=0; + BOOL update; + fstring form_name; + + /* + * NT tries to add forms even when + * they are already in the base + * only update the values if already present + */ + + update=False; + + unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1); + for (n=0; n<*count && update==False; n++) + { + if (!strncmp((*list)[n].name, form_name, strlen(form_name))) + { + DEBUG(3, ("NT workaround, [%s] already exists\n", form_name)); + update=True; + } + } + + if (update==False) + { + *list=Realloc(*list, (n+1)*sizeof(nt_forms_struct)); + unistr2_to_ascii((*list)[n].name, &(form->name), sizeof((*list)[n].name)-1); + (*count)++; + } + + (*list)[n].flag=form->flags; + (*list)[n].width=form->size_x; + (*list)[n].length=form->size_y; + (*list)[n].left=form->left; + (*list)[n].top=form->top; + (*list)[n].right=form->right; + (*list)[n].bottom=form->bottom; +} + +/**************************************************************************** +update a form struct +****************************************************************************/ +void update_a_form(nt_forms_struct **list, const FORM *form, int count) +{ + int n=0; + fstring form_name; + unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1); + + DEBUG(6, ("[%s]\n", form_name)); + for (n=0; n<count; n++) + { + DEBUGADD(6, ("n [%d]:[%s]\n", n, (*list)[n].name)); + if (!strncmp((*list)[n].name, form_name, strlen(form_name))) + break; + } + + if (n==count) return; + + (*list)[n].flag=form->flags; + (*list)[n].width=form->size_x; + (*list)[n].length=form->size_y; + (*list)[n].left=form->left; + (*list)[n].top=form->top; + (*list)[n].right=form->right; + (*list)[n].bottom=form->bottom; +} + +/**************************************************************************** +get the nt drivers list + +open the directory and look-up the matching names +****************************************************************************/ +int get_ntdrivers(fstring **list, char *architecture) +{ + DIR *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(lp_nt_drivers_file()); + + if (dirp == NULL) + { + 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)); + + fstrcpy(driver_name, dpname+match_len); + all_string_sub(driver_name, "#", "/", 0); + *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, "/", "#", 0); + + 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, "/", "#", 0); + + 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->data); + 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; + NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3; + char **dependentfiles; + + switch (level) + { + case 3: + { + if (driver.info_3 != NULL) + { + info3=driver.info_3; + dependentfiles=info3->dependentfiles; + + while ( **dependentfiles != '\0' ) + { + free (*dependentfiles); + dependentfiles++; + } + + /* the last one (1 char !) */ + free (*dependentfiles); + + dependentfiles=info3->dependentfiles; + free (dependentfiles); + + free(info3); + 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 +*/ + fstrcpy(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 = 1; + 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..a6f72a3181 --- /dev/null +++ b/source3/rpc_parse/parse_spoolss.c @@ -0,0 +1,4806 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-2000, + * Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + * Copyright (C) Jean François Micouleau 1998-2000. + * + * 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 BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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; + + return True; +} + +/******************************************************************* +reads or writes an POLICY_HND structure. +********************************************************************/ +static BOOL smb_io_prt_hnd(char *desc, POLICY_HND *hnd, prs_struct *ps, int depth) +{ + if (hnd == NULL) return False; + + prs_debug(ps, depth, desc, "smb_io_prt_hnd"); + depth++; + + prs_align(ps); + + prs_uint8s (False, "data", ps, depth, hnd->data, POLICY_HND_SIZE); + + return True; +} + +/******************************************************************* +reads or writes an DOC_INFO structure. +********************************************************************/ +static BOOL smb_io_doc_info_1(char *desc, DOC_INFO_1 *info_1, prs_struct *ps, int depth) +{ + if (info_1 == NULL) return False; + + 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)); + + smb_io_unistr2("", &(info_1->docname), info_1->p_docname, ps, depth); + smb_io_unistr2("", &(info_1->outputfile), info_1->p_outputfile, ps, depth); + smb_io_unistr2("", &(info_1->datatype), info_1->p_datatype, ps, depth); + + return True; +} + +/******************************************************************* +reads or writes an DOC_INFO structure. +********************************************************************/ +static BOOL smb_io_doc_info(char *desc, DOC_INFO *info, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0; + + if (info == NULL) return False; + + 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; + } + + return True; +} + +/******************************************************************* +reads or writes an DOC_INFO_CONTAINER structure. +********************************************************************/ +static BOOL smb_io_doc_info_container(char *desc, DOC_INFO_CONTAINER *cont, prs_struct *ps, int depth) +{ + if (cont == NULL) return False; + + 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); + + return True; +} + +/******************************************************************* +reads or writes an NOTIFY OPTION TYPE structure. +********************************************************************/ +static BOOL 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); + + + return True; +} + +/******************************************************************* +reads or writes an NOTIFY OPTION TYPE DATA. +********************************************************************/ +static BOOL 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])); + } + + return True; +} + +/******************************************************************* +reads or writes an NOTIFY OPTION structure. +********************************************************************/ +static BOOL 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); + } + + + return True; +} + + +/******************************************************************* +reads or writes an NOTIFY INFO DATA structure. +********************************************************************/ +static BOOL 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);*/ + } + + return True; +} + +/******************************************************************* +reads or writes an NOTIFY INFO DATA structure. +********************************************************************/ +BOOL 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); + + return True; +} + +/******************************************************************* +reads or writes an NOTIFY INFO structure. +********************************************************************/ +static BOOL 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++) + { + 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++) + { + smb_io_notify_info_data_strings(desc, &(info->data[i]), + ps, depth); + } + + return True; +} + + +/******************************************************************* +********************************************************************/ +static BOOL spool_io_user_level_1(char *desc, SPOOL_USER_1 *q_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, ""); + depth++; + + /* reading */ + if (ps->io) + ZERO_STRUCTP(q_u); + + if (!prs_align(ps)) + return False; + if (!prs_uint32("size", ps, depth, &(q_u->size))) + return False; + if (!prs_uint32("client_name_ptr", ps, depth, &(q_u->client_name_ptr))) + return False; + if (!prs_uint32("user_name_ptr", ps, depth, &(q_u->user_name_ptr))) + return False; + if (!prs_uint32("build", ps, depth, &(q_u->build))) + return False; + if (!prs_uint32("major", ps, depth, &(q_u->major))) + return False; + if (!prs_uint32("minor", ps, depth, &(q_u->minor))) + return False; + if (!prs_uint32("processor", ps, depth, &(q_u->processor))) + return False; + + if (!smb_io_unistr2("", &(q_u->client_name), q_u->client_name_ptr, ps, depth)) + return False; + if (!prs_align(ps)) + return False; + if (!smb_io_unistr2("", &(q_u->user_name), q_u->user_name_ptr, ps, depth)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL spool_io_user_level(char *desc, SPOOL_USER_CTR *q_u, prs_struct *ps, int depth) +{ + if (q_u==NULL) + return False; + + prs_debug(ps, depth, desc, "spool_io_user_level"); + depth++; + + if (!prs_align(ps)) + return False; + if (!prs_uint32("level", ps, depth, &q_u->level)) + return False; + if (!prs_uint32("ptr", ps, depth, &q_u->ptr)) + return False; + + switch (q_u->level) { + case 1: + if (!spool_io_user_level_1("", &(q_u->user1), ps, depth)) + return False; + break; + default: + return False; + } + + return True; +} + +/******************************************************************* + * read or write a DEVICEMODE struct. + * on reading allocate memory for the private member + ********************************************************************/ +static BOOL spoolss_io_devmode(char *desc, prs_struct *ps, int depth, DEVICEMODE *devmode) +{ + prs_debug(ps, depth, desc, "spoolss_io_devmode"); + depth++; + + if (!prs_uint16s(True,"devicename", ps, depth, devmode->devicename.buffer, 32)) + return False; + if (!prs_uint16("specversion", ps, depth, &(devmode->specversion))) + return False; + if (!prs_uint16("driverversion", ps, depth, &(devmode->driverversion))) + return False; + if (!prs_uint16("size", ps, depth, &(devmode->size))) + return False; + if (!prs_uint16("driverextra", ps, depth, &(devmode->driverextra))) + return False; + if (!prs_uint32("fields", ps, depth, &(devmode->fields))) + return False; + if (!prs_uint16("orientation", ps, depth, &(devmode->orientation))) + return False; + if (!prs_uint16("papersize", ps, depth, &(devmode->papersize))) + return False; + if (!prs_uint16("paperlength", ps, depth, &(devmode->paperlength))) + return False; + if (!prs_uint16("paperwidth", ps, depth, &(devmode->paperwidth))) + return False; + if (!prs_uint16("scale", ps, depth, &(devmode->scale))) + return False; + if (!prs_uint16("copies", ps, depth, &(devmode->copies))) + return False; + if (!prs_uint16("defaultsource", ps, depth, &(devmode->defaultsource))) + return False; + if (!prs_uint16("printquality", ps, depth, &(devmode->printquality))) + return False; + if (!prs_uint16("color", ps, depth, &(devmode->color))) + return False; + if (!prs_uint16("duplex", ps, depth, &(devmode->duplex))) + return False; + if (!prs_uint16("yresolution", ps, depth, &(devmode->yresolution))) + return False; + if (!prs_uint16("ttoption", ps, depth, &(devmode->ttoption))) + return False; + if (!prs_uint16("collate", ps, depth, &(devmode->collate))) + return False; + if (!prs_uint16s(True, "formname", ps, depth, devmode->formname.buffer, 32)) + return False; + if (!prs_uint16("logpixels", ps, depth, &(devmode->logpixels))) + return False; + if (!prs_uint32("bitsperpel", ps, depth, &(devmode->bitsperpel))) + return False; + if (!prs_uint32("pelswidth", ps, depth, &(devmode->pelswidth))) + return False; + if (!prs_uint32("pelsheight", ps, depth, &(devmode->pelsheight))) + return False; + if (!prs_uint32("displayflags", ps, depth, &(devmode->displayflags))) + return False; + if (!prs_uint32("displayfrequency", ps, depth, &(devmode->displayfrequency))) + return False; + if (!prs_uint32("icmmethod", ps, depth, &(devmode->icmmethod))) + return False; + if (!prs_uint32("icmintent", ps, depth, &(devmode->icmintent))) + return False; + if (!prs_uint32("mediatype", ps, depth, &(devmode->mediatype))) + return False; + if (!prs_uint32("dithertype", ps, depth, &(devmode->dithertype))) + return False; + if (!prs_uint32("reserved1", ps, depth, &(devmode->reserved1))) + return False; + if (!prs_uint32("reserved2", ps, depth, &(devmode->reserved2))) + return False; + if (!prs_uint32("panningwidth", ps, depth, &(devmode->panningwidth))) + return False; + if (!prs_uint32("panningheight", ps, depth, &(devmode->panningheight))) + return False; + + if (devmode->driverextra!=0) + { + if (UNMARSHALLING(ps)) { + devmode->private=(uint8 *)malloc(devmode->driverextra*sizeof(uint8)); + DEBUG(7,("spoolss_io_devmode: allocated memory [%d] for private\n",devmode->driverextra)); + } + + DEBUG(7,("spoolss_io_devmode: parsing [%d] bytes of private\n",devmode->driverextra)); + if (!prs_uint8s(True, "private", ps, depth, devmode->private, devmode->driverextra)) + return False; + } + + return True; +} + +/******************************************************************* + Read or write a DEVICEMODE container +********************************************************************/ +static BOOL spoolss_io_devmode_cont(char *desc, DEVMODE_CTR *dm_c, prs_struct *ps, int depth) +{ + if (dm_c==NULL) + return False; + + prs_debug(ps, depth, desc, "spoolss_io_devmode_cont"); + depth++; + + if (!prs_uint32("size", ps, depth, &dm_c->size)) + return False; + + if (!prs_uint32("devmode_ptr", ps, depth, &dm_c->devmode_ptr)) + return False; + + if (dm_c->size==0 || dm_c->devmode_ptr==0) { + if (UNMARSHALLING(ps)) + /* if while reading there is no DEVMODE ... */ + dm_c->devmode=NULL; + return True; + } + + /* so we have a DEVICEMODE to follow */ + if (UNMARSHALLING(ps)) { + DEBUG(9,("Allocating memory for spoolss_io_devmode\n")); + dm_c->devmode=(DEVICEMODE *)malloc(sizeof(DEVICEMODE)); + ZERO_STRUCTP(dm_c->devmode); + } + + /* this is bad code, shouldn't be there */ + if (!prs_uint32("size", ps, depth, &dm_c->size)) + return False; + + if (!spoolss_io_devmode(desc, ps, depth, dm_c->devmode)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL spoolss_io_printer_default(char *desc, PRINTER_DEFAULT *pd, prs_struct *ps, int depth) +{ + if (pd==NULL) + return False; + + prs_debug(ps, depth, desc, "spoolss_io_printer_default"); + depth++; + + if (!prs_uint32("datatype_ptr", ps, depth, &pd->datatype_ptr)) + return False; + + if (!smb_io_unistr2("datatype", &(pd->datatype), pd->datatype_ptr, ps,depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!spoolss_io_devmode_cont("", &(pd->devmode_cont), ps, depth)) + return False; + + if (!prs_uint32("access_required", ps, depth, &pd->access_required)) + return False; + + return True; +} + +/******************************************************************* + * make a structure. + ********************************************************************/ +BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u, + const char *printername, + uint32 cbbuf, uint32 devmod, uint32 des_access, + const char *station, + const char *username) +{ + int len_name = printername != NULL ? strlen(printername) : 0; + int len_sta = station != NULL ? strlen(station ) : 0; + int len_user = username != NULL ? strlen(username ) : 0; + + if (q_u == NULL) return False; + + DEBUG(5,("make_spoolss_io_q_open_printer_ex\n")); + + q_u->printername_ptr = 1; + init_unistr2(&(q_u->printername), printername, len_name); + +/* + q_u->unknown0 = 0x0; + q_u->cbbuf = cbbuf; + q_u->devmod = devmod; + q_u->access_required = des_access; +*/ +/* q_u->unknown1 = 0x1; + q_u->unknown2 = 0x1; + q_u->unknown3 = 0x149f7d8; + q_u->unknown4 = 0x1c; + q_u->unknown5 = 0x00b94dd0; + q_u->unknown6 = 0x0149f5cc; + q_u->unknown7 = 0x00000565; + q_u->unknown8 = 0x2; + q_u->unknown9 = 0x0; + q_u->unknown10 = 0x0; + + init_unistr2(&(q_u->station), station, len_sta); + init_unistr2(&(q_u->username), username, len_user); +*/ + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_open_printer_ex (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_q_open_printer_ex(char *desc, SPOOL_Q_OPEN_PRINTER_EX *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "spoolss_io_q_open_printer_ex"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!prs_uint32("printername_ptr", ps, depth, &(q_u->printername_ptr))) + return False; + if (!smb_io_unistr2("", &(q_u->printername), q_u->printername_ptr, ps,depth)) + return False; + + if (!prs_align(ps)) + return False; + + if (!spoolss_io_printer_default("", &(q_u->printer_default), ps, depth)) + return False; + + if (!prs_uint32("user_switch", ps, depth, &(q_u->user_switch))) + return False; + + if (!spool_io_user_level("", &(q_u->user_ctr), ps, depth)) + return False; + + return True; +} + +/******************************************************************* + * write a structure. + * called from static spoolss_r_open_printer_ex (srv_spoolss.c) + * called from spoolss_open_printer_ex (cli_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_r_open_printer_ex(char *desc, SPOOL_R_OPEN_PRINTER_EX *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return False; + + prs_debug(ps, depth, desc, "spoolss_io_r_open_printer_ex"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!smb_io_prt_hnd("printer handle",&(r_u->handle),ps,depth)) + return False; + + if (!prs_uint32("status code", ps, depth, &(r_u->status))) + return False; + + return True; +} +/******************************************************************* + * make a structure. + ********************************************************************/ +BOOL make_spoolss_q_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u, + POLICY_HND *handle, + char *valuename, + uint32 size) +{ + int len_name = valuename != NULL ? strlen(valuename) : 0; + + if (q_u == NULL) return False; + + DEBUG(5,("make_spoolss_q_getprinterdata\n")); + + memcpy(&(q_u->handle), handle, sizeof(q_u->handle)); + init_unistr2(&(q_u->valuename), valuename, len_name); + q_u->size = size; + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_getprinterdata (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_q_getprinterdata(char *desc, SPOOL_Q_GETPRINTERDATA *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return False; + + prs_debug(ps, depth, desc, "spoolss_io_q_getprinterdata"); + depth++; + + if (!prs_align(ps)) + return False; + if (!smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth)) + return False; + if (!prs_align(ps)) + return False; + if (!smb_io_unistr2("valuename", &(q_u->valuename),True,ps,depth)) + return False; + if (!prs_align(ps)) + return False; + if (!prs_uint32("size", ps, depth, &(q_u->size))) + return False; + + return True; +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_getprinterdata (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_r_getprinterdata(char *desc, SPOOL_R_GETPRINTERDATA *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return False; + + 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)); + + prs_uint8s(False,"data", ps, depth, r_u->data, r_u->size); + prs_align(ps); + + prs_uint32("needed", ps, depth, &(r_u->needed)); + prs_uint32("status", ps, depth, &(r_u->status)); + prs_align(ps); + + return True; +} + +/******************************************************************* + * make a structure. + ********************************************************************/ +BOOL make_spoolss_q_closeprinter(SPOOL_Q_CLOSEPRINTER *q_u, POLICY_HND *hnd) +{ + if (q_u == NULL) return False; + + DEBUG(5,("make_spoolss_q_closeprinter\n")); + + memcpy(&(q_u->handle), hnd, sizeof(q_u->handle)); + + return True; +} + +/******************************************************************* + * read a structure. + * called from static spoolss_q_closeprinter (srv_spoolss.c) + * called from spoolss_closeprinter (cli_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_q_closeprinter(char *desc, SPOOL_Q_CLOSEPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return False; + + prs_debug(ps, depth, desc, "spoolss_io_q_closeprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + + return True; +} + +/******************************************************************* + * write a structure. + * called from static spoolss_r_closeprinter (srv_spoolss.c) + * called from spoolss_closeprinter (cli_spoolss.c) + ********************************************************************/ +BOOL 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)); + + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_startdocprinter (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_q_startdocprinter(char *desc, SPOOL_Q_STARTDOCPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return False; + + 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); + + return True; +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_startdocprinter (srv_spoolss.c) + ********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_enddocprinter (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_q_enddocprinter(char *desc, SPOOL_Q_ENDDOCPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return False; + + prs_debug(ps, depth, desc, "spoolss_io_q_enddocprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + + return True; +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_enddocprinter (srv_spoolss.c) + ********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_startpageprinter (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_q_startpageprinter(char *desc, SPOOL_Q_STARTPAGEPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return False; + + prs_debug(ps, depth, desc, "spoolss_io_q_startpageprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + + return True; +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_startpageprinter (srv_spoolss.c) + ********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_endpageprinter (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_q_endpageprinter(char *desc, SPOOL_Q_ENDPAGEPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return False; + + prs_debug(ps, depth, desc, "spoolss_io_q_endpageprinter"); + depth++; + + prs_align(ps); + + smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth); + + return True; +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_endpageprinter (srv_spoolss.c) + ********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_writeprinter (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_q_writeprinter(char *desc, SPOOL_Q_WRITEPRINTER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return False; + + 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)); + + return True; +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_writeprinter (srv_spoolss.c) + ********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_rffpcnex (srv_spoolss.c) + ********************************************************************/ +BOOL 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); + + + return True; +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_rffpcnex (srv_spoolss.c) + ********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_q_rfnpcnex (srv_spoolss.c) + ********************************************************************/ +BOOL 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); + + return True; +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_rfnpcnex (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_r_rfnpcnex(char *desc, + SPOOL_R_RFNPCNEX *r_u, + prs_struct *ps, int depth) +{ + 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, &r_u->status); + + return True; +} + +/******************************************************************* + * return the length of a uint32 (obvious, but the code is clean) + ********************************************************************/ +static uint32 size_of_uint32(uint32 *value) +{ + return (sizeof(*value)); + + return True; +} + +/******************************************************************* + * 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 True; +} + +/******************************************************************* + * 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 True; +} + +/******************************************************************* + * 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); + + return True; +} + +/******************************************************************* + * write a UNICODE string. + * used by all the RPC structs passing a buffer + ********************************************************************/ +static BOOL spoolss_smb_io_unistr(char *desc, UNISTR *uni, prs_struct *ps, int depth) +{ + if (uni == NULL) + return False; + + prs_debug(ps, depth, desc, "spoolss_smb_io_unistr"); + depth++; + if (!prs_unistr("unistr", ps, depth, uni)) + return False; + + return True; +} + + +/******************************************************************* + * write a UNICODE string and its relative pointer. + * used by all the RPC structs passing a buffer + ********************************************************************/ +static BOOL smb_io_relstr(char *desc, prs_struct *ps, int depth, UNISTR *buffer, + uint32 *start_offset, uint32 *end_offset) +{ + if (!ps->io) + { + uint32 struct_offset = prs_offset(ps); + uint32 relative_offset; + + /* writing */ + *end_offset -= 2*(str_len_uni(buffer)+1); + prs_set_offset(ps, *end_offset); + spoolss_smb_io_unistr(desc, buffer, ps, depth); + + prs_set_offset(ps,struct_offset); + relative_offset=*end_offset-*start_offset; + + prs_uint32("offset", ps, depth, &(relative_offset)); + } + else + { + uint32 old_offset; + uint32 relative_offset; + + prs_uint32("offset", ps, depth, &(relative_offset)); + + old_offset = prs_offset(ps); + prs_set_offset(ps, (*start_offset) + relative_offset); + + spoolss_smb_io_unistr(desc, buffer, ps, depth); + + *end_offset = prs_offset(ps); + prs_set_offset(ps, old_offset); + } + return True; +} + +/******************************************************************* + * write a UNICODE string and its relative pointer. + * used by all the RPC structs passing a buffer + * + * As I'm a nice guy, I'm forcing myself to explain this code. + * MS did a good job in the overall spoolss code except in some + * functions where they are passing the API buffer directly in the + * RPC request/reply. That's to maintain compatiility at the API level. + * They could have done it the good way the first time. + * + * So what happen is: the strings are written at the buffer's end, + * in the reverse order of the original structure. Some pointers to + * the strings are also in the buffer. Those are relative to the + * buffer's start. + * + * If you don't understand or want to change that function, + * first get in touch with me: jfm@samba.org + * + ********************************************************************/ +static BOOL new_smb_io_relstr(char *desc, NEW_BUFFER *buffer, int depth, UNISTR *string) +{ + prs_struct *ps=&(buffer->prs); + + if (MARSHALLING(ps)) + { + uint32 struct_offset = prs_offset(ps); + uint32 relative_offset; + + buffer->string_at_end -= 2*(str_len_uni(string)+1); + prs_set_offset(ps, buffer->string_at_end); + + /* write the string */ + if (!spoolss_smb_io_unistr(desc, string, ps, depth)) + return False; + + prs_set_offset(ps, struct_offset); + + relative_offset=buffer->string_at_end-buffer->struct_start; + /* write its offset */ + if (!prs_uint32("offset", ps, depth, &relative_offset)) + return False; + } + else + { + uint32 old_offset; + + /* read the offset */ + if (!prs_uint32("offset", ps, depth, &(buffer->string_at_end))) + return False; + + old_offset = prs_offset(ps); + prs_set_offset(ps, buffer->string_at_end); + + /* read the string */ + if (!spoolss_smb_io_unistr(desc, string, ps, depth)) + return False; + + prs_set_offset(ps, old_offset); + } + return True; +} + + +/******************************************************************* + * write a array UNICODE strings and its relative pointer. + * used by 2 RPC structs + ********************************************************************/ +static BOOL smb_io_relarraystr(char *desc, prs_struct *ps, int depth, UNISTR ***buffer, + uint32 *start_offset, uint32 *end_offset) +{ + int i=0; + uint32 struct_offset; + uint32 relative_offset; + struct_offset=prs_offset(ps); + + while ( (*buffer)[i]!=0x0000 ) + { + i++; + } + + i--; + + /* that's for the ending NULL */ + *end_offset-=2; + + do + { + *end_offset-= 2*(str_len_uni((*buffer)[i])+1); + prs_set_offset(ps, *end_offset); + spoolss_smb_io_unistr(desc, (*buffer)[i], ps, depth); + + i--; + } + while (i>=0); + + prs_set_offset(ps, struct_offset); + relative_offset=*end_offset-*start_offset; + + prs_uint32("offset", ps, depth, &(relative_offset)); + + return True; +} + +/******************************************************************* + * write a DEVMODE struct and its relative pointer. + * used by all the RPC structs passing a buffer + ********************************************************************/ +static BOOL 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=prs_offset(ps); + *end_offset-= (devmode->size+devmode->driverextra); + prs_set_offset(ps, *end_offset); + + spoolss_io_devmode(desc, ps, depth, devmode); + + prs_set_offset(ps, struct_offset); + relative_offset=*end_offset-*start_offset; + + prs_uint32("offset", ps, depth, &(relative_offset)); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL 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=prs_offset(ps); + + 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL 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=prs_offset(ps); + + 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); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL 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; + uint32 devmode_offset; + uint32 backup_offset; + + prs_debug(ps, depth, desc, "smb_io_printer_info_2"); + depth++; + *start_offset=prs_offset(ps); + + 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); + + devmode_offset=prs_offset(ps); + prs_set_offset(ps, prs_offset(ps)+4); + + 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)); + + /* + I'm not sure if putting the devmode at the end the struct is worth it + but NT does it + */ + backup_offset=prs_offset(ps); + prs_set_offset(ps, devmode_offset); + smb_io_reldevmode("devmode", ps, depth, info->devmode, start_offset, end_offset); + prs_set_offset(ps, backup_offset); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL 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=prs_offset(ps); + + smb_io_relstr("name", ps, depth, &(info->name), start_offset, end_offset); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL 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=prs_offset(ps); + + 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); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL 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=prs_offset(ps); + + 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_relarraystr("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); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL 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=prs_offset(ps); + + 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) ); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL 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=prs_offset(ps); + + 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL new_smb_io_form_1(char *desc, NEW_BUFFER *buffer, FORM_1 *info, int depth) +{ + prs_struct *ps=&(buffer->prs); + + prs_debug(ps, depth, desc, "new_smb_io_form_1"); + depth++; + + buffer->struct_start=prs_offset(ps); + + if (!prs_uint32("flag", ps, depth, &(info->flag))) + return False; + + if (!new_smb_io_relstr("name", buffer, depth, &(info->name))) + return False; + + if (!prs_uint32("width", ps, depth, &(info->width))) + return False; + if (!prs_uint32("length", ps, depth, &(info->length))) + return False; + if (!prs_uint32("left", ps, depth, &(info->left))) + return False; + if (!prs_uint32("top", ps, depth, &(info->top))) + return False; + if (!prs_uint32("right", ps, depth, &(info->right))) + return False; + if (!prs_uint32("bottom", ps, depth, &(info->bottom))) + return False; + + return True; +} + +/******************************************************************* + Read/write a BUFFER struct. +********************************************************************/ +static BOOL new_spoolss_io_buffer(char *desc, prs_struct *ps, int depth, NEW_BUFFER *buffer) +{ + if (buffer == NULL) + return False; + + prs_debug(ps, depth, desc, "new_spoolss_io_buffer"); + depth++; + + if (!prs_uint32("ptr", ps, depth, &(buffer->ptr))) + return False; + + /* reading */ + if (UNMARSHALLING(ps)) { + buffer->size=0; + buffer->string_at_end=0; + + if (buffer->ptr==0) { + if (!prs_init(&(buffer->prs), 0, 4, UNMARSHALL)) + return False; + return True; + } + + if (!prs_uint32("size", ps, depth, &(buffer->size))) + return False; + + if (!prs_init(&(buffer->prs), buffer->size, 4, UNMARSHALL)) + return False; + + if (!prs_append_some_prs_data(&(buffer->prs), ps, buffer->size)) + return False; + + prs_set_offset(&(buffer->prs),0); + + prs_set_offset(ps, buffer->size+prs_offset(ps)); + + buffer->string_at_end=buffer->size; + + return True; + } + else { + /* writing */ + if (buffer->ptr==0) + return True; + + if (!prs_uint32("size", ps, depth, &(buffer->size))) + return False; + + if (!prs_append_some_prs_data(ps, &(buffer->prs), buffer->size)) + return False; + } + + return True; +} + +/******************************************************************* + move a BUFFER from the query to the reply. +********************************************************************/ +void new_spoolss_move_buffer(NEW_BUFFER *src, NEW_BUFFER **dest) +{ + prs_switch_type(&(src->prs), MARSHALL); + prs_set_offset(&(src->prs), 0); + prs_force_dynamic(&(src->prs)); + + *dest=src; +} + +/******************************************************************* + create a BUFFER struct. +********************************************************************/ +void new_spoolss_allocate_buffer(NEW_BUFFER **buffer) +{ + if (buffer==NULL) + return; + + *buffer=(NEW_BUFFER *)malloc(sizeof(NEW_BUFFER)); + + (*buffer)->ptr=0x0; + (*buffer)->size=0; + (*buffer)->string_at_end=0; +} + +/******************************************************************* + Destroy a BUFFER struct. +********************************************************************/ +void new_spoolss_free_buffer(NEW_BUFFER *buffer) +{ + if (buffer==NULL) + return; + + prs_mem_free(&(buffer->prs)); + buffer->ptr=0x0; + buffer->size=0; + buffer->string_at_end=0; + + free(buffer); +} + +/******************************************************************* + Get the size of a BUFFER struct. +********************************************************************/ +uint32 new_get_buffer_size(NEW_BUFFER *buffer) +{ + return (buffer->size); +} + +/******************************************************************* +********************************************************************/ +static BOOL 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=prs_offset(ps); + + 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL 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_port_2"); + depth++; + *start_offset=prs_offset(ps); + + 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 True; +} + +/******************************************************************* +********************************************************************/ +static BOOL smb_io_processor_info_1(char *desc, PRINTPROCESSOR_1 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_processor_info_1"); + depth++; + *start_offset=prs_offset(ps); + + smb_io_relstr("name",ps, depth, &(info->name), start_offset, end_offset); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL smb_io_monitor_info_1(char *desc, PRINTMONITOR_1 *info, prs_struct *ps, int depth, + uint32 *start_offset, uint32 *end_offset) +{ + prs_debug(ps, depth, desc, "smb_io_monitor_info_1"); + depth++; + *start_offset=prs_offset(ps); + + smb_io_relstr("name",ps, depth, &(info->name), start_offset, end_offset); + + return True; +} + +/******************************************************************* +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 True; +} + +/******************************************************************* +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 True; +} + +/******************************************************************* +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+=info->devmode->size+4; /* size of the devmode and the ptr */ + size+=info->devmode->driverextra; /* if a devmode->private section exists, add its size */ + + 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 True; +} + +/******************************************************************* +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 True; +} + +/******************************************************************* +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 True; +} + +/******************************************************************* +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; + UNISTR **string; + int i=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->monitorname) ); + size+=size_of_relative_string( &(info->defaultdatatype) ); + + string=info->dependentfiles; + + while ( (string)[i]!=0x0000 ) + { + size+=2*(1+ str_len_uni( string[i] ) ); + i++; + } + size+=6; + + DEBUGADD(9,("size: [%d]\n", size)); + return (size); + + return True; +} + +/******************************************************************* +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 True; +} + +/******************************************************************* +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 True; +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +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 True; +} + +/******************************************************************* +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); + + return True; +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_processor_info_1(PRINTPROCESSOR_1 *info) +{ + int size=0; + size+=size_of_relative_string( &(info->name) ); + + return (size); + + return True; +} + +/******************************************************************* +return the size required by a struct in the stream +********************************************************************/ +static uint32 spoolss_size_monitor_info_1(PRINTMONITOR_1 *info) +{ + int size=0; + size+=size_of_relative_string( &(info->name) ); + + return (size); + + return True; +} + +/******************************************************************* + * make a structure. + ********************************************************************/ +static BOOL make_spoolss_buffer(BUFFER* buffer, uint32 size) +{ + buffer->ptr = (size != 0) ? 1 : 0; + buffer->size = size; + buffer->data = (uint8 *)Realloc( NULL, (buffer->size) * sizeof(uint8) ); + + return (buffer->data != NULL || size == 0); +} + +/******************************************************************* + * 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 BOOL 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)); + if (ps->io) + { + /* reading */ + buffer->data=(uint8 *)Realloc(NULL, buffer->size * sizeof(uint8) ); + } + if (buffer->data == NULL) + { + return False; + } + prs_uint8s(True, "buffer", ps, depth, buffer->data, buffer->size); + prs_align(ps); + + } + else + { + if (ps->io) + { + /* reading */ + buffer->data=0x0000; + buffer->size=0x0000; + } + } + + if (!ps->io) + { + /* writing */ + if (buffer->data != NULL) + { + free(buffer->data); + } + buffer->data = NULL; + } + return True; +} + +/******************************************************************* + * 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 + ********************************************************************/ +BOOL spoolss_io_free_buffer(BUFFER *buffer) +{ + DEBUG(8,("spoolss_io_free_buffer\n")); + + if (buffer->ptr != 0x0000) + { + free(buffer->data); + } + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_getprinterdriver2 (srv_spoolss.c) + ********************************************************************/ +BOOL 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)); + DEBUG(0,("spoolss_io_q_getprinterdriver2: renamed status - unknown\n")); + prs_uint32("unknown", ps, depth, &(q_u->unknown)); + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_getprinterdriver2 (srv_spoolss.c) + ********************************************************************/ +BOOL 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->ctr.driver.info1; + info2 = r_u->ctr.driver.info2; + info3 = r_u->ctr.driver.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; + } + } + + if (ps->io) + { + /* reading */ + r_u->offered = bufsize_required; + } + + 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 + { + DEBUG(4,("spoolss_io_r_getprinterdriver2, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + + beginning=prs_offset(ps); + start_offset=prs_offset(ps); + 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; + } + + } + + prs_set_offset(ps, beginning+r_u->offered); + prs_align(ps); + } + + if (!ps->io) + { + /* writing */ + switch (r_u->level) + { + case 1: + { + safe_free(info1); + break; + } + case 2: + { + safe_free(info2); + break; + } + case 3: + { + if (info3!=NULL) + { + UNISTR **dependentfiles; + int j=0; + dependentfiles=info3->dependentfiles; + while ( dependentfiles[j] != NULL ) + { + free(dependentfiles[j]); + j++; + } + free(dependentfiles); + + free(info3); + } + break; + } + + } + } + + /* + * 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)); + + return True; +} + +/******************************************************************* + * make a structure. + ********************************************************************/ +BOOL make_spoolss_q_enumprinters(SPOOL_Q_ENUMPRINTERS *q_u, + uint32 flags, + const char* servername, + uint32 level, + uint32 size) +{ + size_t len_name = servername != NULL ? strlen(servername) : 0; + + DEBUG(5,("make_spoolss_q_enumprinters. size: %d\n", size)); + + q_u->flags = flags; + + init_unistr2(&q_u->servername, servername, len_name); + + q_u->level = level; + make_spoolss_buffer(&q_u->buffer, size); + q_u->buf_size = size; + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_enumprinters (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_q_enumprinters(char *desc, SPOOL_Q_ENUMPRINTERS *q_u, + prs_struct *ps, int depth) +{ + uint32 useless_ptr = 0x01; + 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)); + + prs_uint32("buf_size", ps, depth, &q_u->buf_size); + + return True; +} + +/**************************************************************************** +****************************************************************************/ +void free_r_enumprinters(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_print1_array(r_u->returned, r_u->ctr.printer.printers_1); + break; + } + case 2: + { + free_print2_array(r_u->returned, r_u->ctr.printer.printers_2); + break; + } + } +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_enum_printers (srv_spoolss.c) + * + ********************************************************************/ +BOOL 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; + uint32 tmp_ct = 0; + + PRINTER_INFO_1 *info1; + PRINTER_INFO_2 *info2; + fstring tmp; + + slprintf(tmp, sizeof(tmp)-1, "spoolss_io_r_enumprinters %d", r_u->level); + + prs_debug(ps, depth, desc, tmp); + depth++; + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + + if (!ps->io) + { + /* writing */ + for(i=0;i<r_u->returned;i++) + { + switch (r_u->level) + { + case 1: + info1 = r_u->ctr.printer.printers_1[i]; + bufsize_required += spoolss_size_printer_info_1(info1); + break; + case 2: + info2 = r_u->ctr.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 False; + } + + DEBUG(4,("spoolss_io_r_enumprinters, buffer large enough\n")); + } + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + + /* have to skip to end of buffer when reading, and have to record + * size of buffer when writing. *shudder*. + */ + + beginning = prs_offset(ps); + start_offset = prs_offset(ps); + end_offset = start_offset + r_u->offered; + + if (ps->io) + { + /* reading */ + prs_set_offset(ps, beginning + r_u->offered); + + prs_align(ps); + prs_uint32("buffer size", ps, depth, &(bufsize_required)); + prs_uint32("count", ps, depth, &(r_u->returned)); + + prs_set_offset(ps, beginning); + } + + for(i=0;i<r_u->returned;i++) + { + + switch (r_u->level) + { + case 1: + { + if (ps->io) + { + /* reading */ +/* r_u->ctr.printer.printers_1[i] = add_print1_to_array(&tmp_ct, &r_u->ctr.printer.printers_1, NULL);*/ + } + info1 = r_u->ctr.printer.printers_1[i]; + if (info1 == NULL) + { + return False; + } + smb_io_printer_info_1(desc, info1, ps, depth, + &start_offset, &end_offset); + break; + } + case 2: + { + if (ps->io) + { + /* reading */ +/* + r_u->ctr.printer.printers_2[i] = add_print2_to_array(&tmp_ct, &r_u->ctr.printer.printers_2, NULL); +*/ } + info2 = r_u->ctr.printer.printers_2[i]; + if (info2 == NULL) + { + return False; + } + smb_io_printer_info_2(desc, info2, ps, depth, + &start_offset, &end_offset); + break; + } + } + } + + prs_set_offset(ps, beginning + r_u->offered); + prs_align(ps); + + prs_uint32("buffer size", ps, depth, &(bufsize_required)); + prs_uint32("count", ps, depth, &(r_u->returned)); + prs_uint32("status", ps, depth, &(r_u->status)); + + if (!ps->io) + { + /* writing */ + free_r_enumprinters(r_u); + } + + return True; +} + +/******************************************************************* + * write a structure. + * called from spoolss_r_enum_printers (srv_spoolss.c) + * + ********************************************************************/ +BOOL 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->ctr.printer.info0; + bufsize_required += spoolss_size_printer_info_0(info); + break; + } + case 1: + { + PRINTER_INFO_1 *info; + info = r_u->ctr.printer.info1; + bufsize_required += spoolss_size_printer_info_1(info); + break; + } + case 2: + { + PRINTER_INFO_2 *info; + info = r_u->ctr.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 + { + DEBUG(4,("spoolss_io_r_getprinter, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + + if (ps->io) + { + /* reading */ + r_u->ctr.printer.info = Realloc(NULL, r_u->offered); + } + + if (bufsize_required <= r_u->offered) + { + beginning=prs_offset(ps); + start_offset=prs_offset(ps); + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 0: + { + PRINTER_INFO_0 *info; + info = r_u->ctr.printer.info0; + smb_io_printer_info_0(desc, + info, + ps, + depth, + &start_offset, + &end_offset); + if (!ps->io) + { + /* writing */ + free(info); + } + break; + } + case 1: + { + PRINTER_INFO_1 *info; + info = r_u->ctr.printer.info1; + smb_io_printer_info_1(desc, + info, + ps, + depth, + &start_offset, + &end_offset); + if (!ps->io) + { + /* writing */ + free(info); + } + break; + } + case 2: + { + PRINTER_INFO_2 *info; + info = r_u->ctr.printer.info2; + smb_io_printer_info_2(desc, + info, + ps, + depth, + &start_offset, + &end_offset); + if (!ps->io) + { + /* writing */ + free_printer_info_2(info); + } + break; + } + + } + + prs_set_offset(ps, 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)); + + return True; +} + +/******************************************************************* + * 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 BOOL spoolss_io_read_buffer8(char *desc, prs_struct *ps, uint8 **buffer, uint32 *size,int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_read_buffer8"); + depth++; + + prs_align(ps); + + prs_uint32("buffer size", ps, depth, size); + *buffer = (uint8 *)Realloc(NULL, (*size) * sizeof(uint8) ); + prs_uint8s(True,"buffer",ps,depth,*buffer,*size); + prs_align(ps); + + return True; +} + +/******************************************************************* + * make a structure. + * called from spoolss_getprinter (srv_spoolss.c) + ********************************************************************/ +BOOL make_spoolss_q_getprinter(SPOOL_Q_GETPRINTER *q_u, + POLICY_HND *hnd, + uint32 level, + uint32 buf_size) +{ + if (q_u == NULL) return False; + + memcpy(&q_u->handle, hnd, sizeof(q_u->handle)); + + q_u->level = level; + q_u->buffer = (uint8 *)Realloc(NULL, (buf_size) * sizeof(uint8) ); + q_u->offered = buf_size; + + return True; +} + +/******************************************************************* + * read a structure. + * called from spoolss_getprinter (srv_spoolss.c) + ********************************************************************/ +BOOL spoolss_io_q_getprinter(char *desc, SPOOL_Q_GETPRINTER *q_u, + prs_struct *ps, int depth) +{ + uint32 count = 0; + uint32 buf_ptr = q_u->buffer != NULL ? 1 : 0; + 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)); + + if (!ps->io) + { + /* writing */ + buf_ptr = q_u->buffer != NULL ? 1 : 0; + } + prs_uint32("buffer pointer", ps, depth, &buf_ptr); + + if (buf_ptr != 0) + { + spoolss_io_read_buffer8("",ps, &q_u->buffer, &count,depth); + } + if (q_u->buffer != NULL) + { + free(q_u->buffer); + } + prs_uint32("buffer size", ps, depth, &(q_u->offered)); + + return count == q_u->offered; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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); + + return True; +} + + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/**************************************************************************** +****************************************************************************/ +void free_job_info_ctr(JOB_INFO_CTR *ctr, uint32 level, uint32 numofjobs) +{ + DEBUG(4,("free_enum_jobs_info: [%d] structs to free at level [%d]\n", + numofjobs, level)); + switch (level) + { + case 1: + { + free_job1_array(numofjobs, + ctr->job.job_info_1); + break; + } + case 2: + { + free_job2_array(numofjobs, + ctr->job.job_info_2); + break; + } + } +} + +/**************************************************************************** +****************************************************************************/ +void free_r_enumjobs(SPOOL_R_ENUMJOBS *r_u) +{ + free_job_info_ctr(&r_u->ctr, r_u->level, r_u->numofjobs); +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_r_enumjobs(char *desc, SPOOL_R_ENUMJOBS *r_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr = 0; + uint32 start_offset, end_offset, beginning; + uint32 bufsize_required=0; + uint32 tmp_ct = 0; + int i; + + prs_debug(ps, depth, desc, "spoolss_io_r_enumjobs"); + depth++; + + prs_align(ps); + + if (!ps->io) + { + /* writing */ + switch (r_u->level) + { + case 1: + { + for (i=0; i<r_u->numofjobs; i++) + { + JOB_INFO_1 *info; + info=r_u->ctr.job.job_info_1[i]; + bufsize_required += spoolss_size_job_info_1(&(info[i])); + } + break; + } + case 2: + { + for (i=0; i<r_u->numofjobs; i++) + { + JOB_INFO_2 *info; + info=r_u->ctr.job.job_info_2[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 = bufsize_required; + useless_ptr = 0; + + DEBUG(4,("spoolss_io_r_enumjobs, buffer too small\n")); + + } + else + { + useless_ptr = 1; + } + } + + prs_uint32("pointer", ps, depth, &useless_ptr); + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + + if (useless_ptr != 0) + { + beginning=prs_offset(ps); + start_offset=prs_offset(ps); + end_offset=start_offset+r_u->offered; + + tmp_ct = 0; + + if (ps->io) + { + /* reading */ + prs_set_offset(ps, beginning + r_u->offered); + + prs_align(ps); + prs_uint32("buffer size", ps, depth, &(bufsize_required)); + prs_uint32("numofjobs", ps, depth, &(r_u->numofjobs)); + + prs_set_offset(ps, beginning); + } + + switch (r_u->level) + { + case 1: + { + JOB_INFO_1 *info; + for (i=0; i<r_u->numofjobs; i++) + { + if (ps->io) + { + /* reading */ +/* r_u->ctr.job.job_info_1[i] = add_job1_to_array(&tmp_ct, &r_u->ctr.job.job_info_1, NULL);*/ + } + info = r_u->ctr.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++) + { + if (ps->io) + { + /* reading */ +/* r_u->ctr.job.job_info_2[i] = add_job2_to_array(&tmp_ct, &r_u->ctr.job.job_info_2, NULL);*/ + } + info = r_u->ctr.job.job_info_2[i]; + smb_io_job_info_2(desc, + info, + ps, + depth, + &start_offset, + &end_offset); + } + break; + } + + } + prs_set_offset(ps, 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("buffer size", ps, depth, &(bufsize_required)); + } + + prs_uint32("numofjobs", ps, depth, &(r_u->numofjobs)); + prs_uint32("status", ps, depth, &(r_u->status)); + + if (!ps->io) + { + /* writing */ + free_r_enumjobs(r_u); + } + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL make_spoolss_q_enumjobs(SPOOL_Q_ENUMJOBS *q_u, const POLICY_HND *hnd, + uint32 firstjob, + uint32 numofjobs, + uint32 level, + uint32 buf_size) +{ + if (q_u == NULL) + { + return False; + } + memcpy(&q_u->handle, hnd, sizeof(q_u->handle)); + q_u->firstjob = firstjob; + q_u->numofjobs = numofjobs; + q_u->level = level; + + if (!make_spoolss_buffer(&q_u->buffer, buf_size)) + { + return False; + } + q_u->buf_size = buf_size; + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_q_enumjobs(char *desc, SPOOL_Q_ENUMJOBS *q_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_q_enumjobs"); + 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_uint32("buf_size", ps, depth, &(q_u->buf_size)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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->ctr.driver.info1; + + 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->ctr.driver.info2; + + for (i=0; i<r_u->numofdrivers; i++) + { + bufsize_required += spoolss_size_printer_driver_info_2(&(driver_info_2[i])); + } + break; + } + case 3: + { + DRIVER_INFO_3 *driver_info_3; + driver_info_3=r_u->ctr.driver.info3; + + 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 + { + DEBUGADD(8,("buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=prs_offset(ps); + start_offset=prs_offset(ps); + 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->ctr.driver.info1[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->ctr.driver.info2[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->ctr.driver.info3[i]); + smb_io_printer_driver_info_3(desc, info, ps, depth, &start_offset, &end_offset); + } + break; + } + } + prs_set_offset(ps, 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)); + + return True; +} + + +void free_spoolss_r_enumdrivers(SPOOL_R_ENUMPRINTERDRIVERS *r_u) +{ + switch (r_u->level) + { + case 1: + { + DRIVER_INFO_1 *driver_info_1; + driver_info_1=r_u->ctr.driver.info1; + + free(driver_info_1); + break; + } + case 2: + { + DRIVER_INFO_2 *driver_info_2; + driver_info_2=r_u->ctr.driver.info2; + + free(driver_info_2); + break; + } + case 3: + { + DRIVER_INFO_3 *driver_info_3; + + UNISTR **dependentfiles; + int i; + + driver_info_3=r_u->ctr.driver.info3; + + for (i=0; i<r_u->numofdrivers; i++) + { + int j=0; + dependentfiles=(driver_info_3[i]).dependentfiles; + while ( dependentfiles[j] != NULL ) + { + free(dependentfiles[j]); + j++; + } + + free(dependentfiles); + } + free(driver_info_3); + break; + } + } +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_q_enumforms(char *desc, SPOOL_Q_ENUMFORMS *q_u, prs_struct *ps, int depth) +{ + + prs_debug(ps, depth, desc, "spoolss_io_q_enumforms"); + depth++; + + if (!prs_align(ps)) + return False; + if (!smb_io_prt_hnd("printer handle",&(q_u->handle),ps,depth)) + return False; + if (!prs_uint32("level", ps, depth, &(q_u->level))) + return False; + + if (!new_spoolss_io_buffer("", ps, depth, q_u->buffer)) + return False; + + if (!prs_align(ps)) + return False; + if (!prs_uint32("offered", ps, depth, &(q_u->offered))) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL new_spoolss_io_r_enumforms(char *desc, SPOOL_R_ENUMFORMS *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "new_spoolss_io_r_enumforms"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!new_spoolss_io_buffer("", ps, depth, r_u->buffer)) + return False; + + if (!prs_align(ps)) + return False; + + if (!prs_uint32("size of buffer needed", ps, depth, &(r_u->needed))) + return False; + + if (!prs_uint32("numofforms", ps, depth, &(r_u->numofforms))) + return False; + + if (!prs_uint32("status", ps, depth, &(r_u->status))) + return False; + + return True; + +} + +/******************************************************************* +********************************************************************/ +BOOL 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->ctr.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 + { + DEBUG(4,("buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=prs_offset(ps); + start_offset=prs_offset(ps); + 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->ctr.port.info_2[i]); + smb_io_port_2(desc, info, ps, depth, &start_offset, &end_offset); + } + break; + } + } + prs_set_offset(ps, 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)); + + return True; +} + +void spoolss_free_r_enumports(SPOOL_R_ENUMPORTS *r_u) +{ + switch (r_u->level) + { + case 2: + { + safe_free(r_u->ctr.port.info_2); + break; + } + } +} +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + + +/******************************************************************* +********************************************************************/ +BOOL 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); + } + + */ + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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; + } + + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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); + + return True; +} + + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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); + + + return True; +} + + +/******************************************************************* + 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 + +********************************************************************/ +BOOL 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 False; + + 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)); + + return True; +} + +/******************************************************************* + read a UNICODE array with null terminated strings + and null terminated array + and size of array at beginning +********************************************************************/ +BOOL smb_io_unibuffer(char *desc, UNISTR2 *buffer, prs_struct *ps, int depth) +{ + if (buffer==NULL) return False; + + 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); + + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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; + } + + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + + +/******************************************************************* +********************************************************************/ +BOOL 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) ); + + return True; +} + +BOOL uni_2_asc_printer_info_2(const 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); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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->ctr.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 + { + DEBUG(4,("spoolss_io_r_getprinterdriverdir, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=prs_offset(ps); + start_offset=prs_offset(ps); + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + DRIVER_DIRECTORY_1 *info; + info = &(r_u->ctr.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; + } + } + prs_set_offset(ps, 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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; + int i; + + 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_processor_info_1(&(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 + { + DEBUG(4,("buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=prs_offset(ps); + start_offset=prs_offset(ps); + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + PRINTPROCESSOR_1 *info_1; + for (i=0; i<r_u->numofprintprocessors; i++) + { + info_1 = &(r_u->info_1[i]); + smb_io_processor_info_1(desc, info_1, ps, depth, &start_offset, &end_offset); + } + break; + } + } + prs_set_offset(ps, 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_r_enumprintmonitors(char *desc, SPOOL_R_ENUMPRINTMONITORS *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_enumprintmonitors"); + depth++; + + prs_align(ps); + prs_uint32("pointer", ps, depth, &useless_ptr); + switch (r_u->level) + { + case 1: + { + PRINTMONITOR_1 *info_1; + info_1=r_u->info_1; + + for (i=0; i<r_u->numofprintmonitors; i++) + { + bufsize_required += spoolss_size_monitor_info_1(&(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 + { + DEBUG(4,("buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=prs_offset(ps); + start_offset=prs_offset(ps); + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + PRINTMONITOR_1 *info_1; + for (i=0; i<r_u->numofprintmonitors; i++) + { + info_1 = &(r_u->info_1[i]); + smb_io_monitor_info_1(desc, info_1, ps, depth, &start_offset, &end_offset); + } + break; + } + } + prs_set_offset(ps, 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("numofprintmonitors", ps, depth, &(r_u->numofprintmonitors)); + prs_uint32("status", ps, depth, &(r_u->status)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_q_enumprintmonitors(char *desc, SPOOL_Q_ENUMPRINTMONITORS *q_u, prs_struct *ps, int depth) +{ + uint32 useless; + prs_debug(ps, depth, desc, "spoolss_io_q_enumprintmonitors"); + 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_r_enumprinterdata(char *desc, SPOOL_R_ENUMPRINTERDATA *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterdata"); + 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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: + case 0x7: + 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL convert_specific_param(NT_PRINTER_PARAM **param, const UNISTR2 *value, + uint32 type, const 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)); + + return True; +} + +/******************************************************************* +********************************************************************/ +static BOOL spoolss_io_addform(char *desc, FORM *f, uint32 ptr, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_addform"); + depth++; + prs_align(ps); + + if (ptr!=0) + { + prs_uint32("flags", ps, depth, &(f->flags)); + prs_uint32("name_ptr", ps, depth, &(f->name_ptr)); + prs_uint32("size_x", ps, depth, &(f->size_x)); + prs_uint32("size_y", ps, depth, &(f->size_y)); + prs_uint32("left", ps, depth, &(f->left)); + prs_uint32("top", ps, depth, &(f->top)); + prs_uint32("right", ps, depth, &(f->right)); + prs_uint32("bottom", ps, depth, &(f->bottom)); + + smb_io_unistr2("", &(f->name), f->name_ptr, ps, depth); + } + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_q_addform(char *desc, SPOOL_Q_ADDFORM *q_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0; + prs_debug(ps, depth, desc, "spoolss_io_q_addform"); + depth++; + + prs_align(ps); + smb_io_prt_hnd("printer handle", &(q_u->handle), ps, depth); + prs_uint32("level", ps, depth, &(q_u->level)); + prs_uint32("level2", ps, depth, &(q_u->level2)); + + if (q_u->level==1) + { + prs_uint32("useless_ptr", ps, depth, &(useless_ptr)); + spoolss_io_addform("", &(q_u->form), useless_ptr, ps, depth); + } + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_r_addform(char *desc, SPOOL_R_ADDFORM *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_addform"); + depth++; + + prs_align(ps); + prs_uint32("status", ps, depth, &(r_u->status)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_q_setform(char *desc, SPOOL_Q_SETFORM *q_u, prs_struct *ps, int depth) +{ + uint32 useless_ptr=0; + prs_debug(ps, depth, desc, "spoolss_io_q_setform"); + depth++; + + prs_align(ps); + smb_io_prt_hnd("printer handle", &(q_u->handle), ps, depth); + smb_io_unistr2("", &(q_u->name), True, ps, depth); + + prs_align(ps); + + prs_uint32("level", ps, depth, &(q_u->level)); + prs_uint32("level2", ps, depth, &(q_u->level2)); + + if (q_u->level==1) + { + prs_uint32("useless_ptr", ps, depth, &(useless_ptr)); + spoolss_io_addform("", &(q_u->form), useless_ptr, ps, depth); + } + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_r_setform(char *desc, SPOOL_R_SETFORM *r_u, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "spoolss_io_r_setform"); + depth++; + + prs_align(ps); + prs_uint32("status", ps, depth, &(r_u->status)); + + return True; +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_r_getjob(char *desc, SPOOL_R_GETJOB *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_getjob"); + depth++; + + prs_align(ps); + + prs_uint32("pointer", ps, depth, &useless_ptr); + + switch (r_u->level) + { + case 1: + { + JOB_INFO_1 *info; + info=r_u->ctr.job.job_info_1; + + bufsize_required += spoolss_size_job_info_1(info); + break; + } + case 2: + { + JOB_INFO_2 *info; + info=r_u->ctr.job.job_info_2; + + bufsize_required += spoolss_size_job_info_2(info); + break; + } + } + + DEBUG(4,("spoolss_io_r_getjob, size needed: %d\n",bufsize_required)); + DEBUG(4,("spoolss_io_r_getjob, 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_getjob, buffer too small\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + } + else + { + DEBUG(4,("spoolss_io_r_enumjobs, buffer large enough\n")); + + prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + beginning=prs_offset(ps); + start_offset=prs_offset(ps); + end_offset=start_offset+r_u->offered; + + switch (r_u->level) + { + case 1: + { + JOB_INFO_1 *info; + info = r_u->ctr.job.job_info_1; + smb_io_job_info_1(desc, info, ps, depth, &start_offset, &end_offset); + break; + } + case 2: + { + JOB_INFO_2 *info; + info = r_u->ctr.job.job_info_2; + smb_io_job_info_2(desc, info, ps, depth, &start_offset, &end_offset); + break; + } + + } + prs_set_offset(ps, 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)); + + return True; +} + +/**************************************************************************** +****************************************************************************/ +void free_spoolss_r_getjob(SPOOL_R_GETJOB *r_u) +{ + switch (r_u->level) + { + case 1: + { + free(r_u->ctr.job.job_info_1); + break; + } + case 2: + { + free_job_info_2(r_u->ctr.job.job_info_2); + break; + } + } +} + +/******************************************************************* +********************************************************************/ +BOOL spoolss_io_q_getjob(char *desc, SPOOL_Q_GETJOB *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("jobid", ps, depth, &(q_u->jobid)); + 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)); + + return True; +} + +void free_devmode(DEVICEMODE *devmode) +{ + if (devmode!=NULL) + { + if (devmode->private!=NULL) + free(devmode->private); + free(devmode); + } +} + +void free_printer_info_2(PRINTER_INFO_2 *printer) +{ + if (printer!=NULL) + { + free_devmode(printer->devmode); + free(printer); + } +} + +static PRINTER_INFO_2 *prt2_dup(const PRINTER_INFO_2* from) +{ + PRINTER_INFO_2 *copy = (PRINTER_INFO_2 *)malloc(sizeof(PRINTER_INFO_2)); + if (copy != NULL) + { + if (from != NULL) + { + memcpy(copy, from, sizeof(*copy)); + } + else + { + ZERO_STRUCTP(copy); + } + } + return copy; +} + +void free_print2_array(uint32 num_entries, PRINTER_INFO_2 **entries) +{ + void(*fn)(void*) = (void(*)(void*))&free_printer_info_2; + free_void_array(num_entries, (void**)entries, *fn); +} + +PRINTER_INFO_2 *add_print2_to_array(uint32 *len, PRINTER_INFO_2 ***array, + const PRINTER_INFO_2 *prt) +{ + void*(*fn)(const void*) = (void*(*)(const void*))&prt2_dup; + return (PRINTER_INFO_2*)add_copy_to_array(len, + (void***)array, (const void*)prt, *fn, True); +} + +static PRINTER_INFO_1 *prt1_dup(const PRINTER_INFO_1* from) +{ + PRINTER_INFO_1 *copy = (PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1)); + if (copy != NULL) + { + if (from != NULL) + { + memcpy(copy, from, sizeof(*copy)); + } + else + { + ZERO_STRUCTP(copy); + } + } + return copy; +} + +void free_print1_array(uint32 num_entries, PRINTER_INFO_1 **entries) +{ + void(*fn)(void*) = (void(*)(void*))&free; + free_void_array(num_entries, (void**)entries, *fn); +} + +PRINTER_INFO_1 *add_print1_to_array(uint32 *len, PRINTER_INFO_1 ***array, + const PRINTER_INFO_1 *prt) +{ + void*(*fn)(const void*) = (void*(*)(const void*))&prt1_dup; + return (PRINTER_INFO_1*)add_copy_to_array(len, + (void***)array, (const void*)prt, *fn, True); +} + +static JOB_INFO_1 *job1_dup(const JOB_INFO_1* from) +{ + JOB_INFO_1 *copy = (JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1)); + if (copy != NULL) + { + if (from != NULL) + { + memcpy(copy, from, sizeof(*copy)); + } + else + { + ZERO_STRUCTP(copy); + } + } + return copy; +} + +void free_job1_array(uint32 num_entries, JOB_INFO_1 **entries) +{ + void(*fn)(void*) = (void(*)(void*))&free; + free_void_array(num_entries, (void**)entries, *fn); +} + +JOB_INFO_1 *add_job1_to_array(uint32 *len, JOB_INFO_1 ***array, + const JOB_INFO_1 *job) +{ + void*(*fn)(const void*) = (void*(*)(const void*))&job1_dup; + return (JOB_INFO_1*)add_copy_to_array(len, + (void***)array, (const void*)job, *fn, True); +} + +static JOB_INFO_2 *job2_dup(const JOB_INFO_2* from) +{ + JOB_INFO_2 *copy = (JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2)); + if (copy != NULL) + { + if (from != NULL) + { + memcpy(copy, from, sizeof(*copy)); + } + else + { + ZERO_STRUCTP(copy); + } + } + return copy; +} + +void free_job_info_2(JOB_INFO_2 *job) +{ + if (job!=NULL) + { + free_devmode(job->devmode); + free(job); + } +} + +void free_job2_array(uint32 num_entries, JOB_INFO_2 **entries) +{ + void(*fn)(void*) = (void(*)(void*))&free_job_info_2; + free_void_array(num_entries, (void**)entries, *fn); +} + +JOB_INFO_2 *add_job2_to_array(uint32 *len, JOB_INFO_2 ***array, + const JOB_INFO_2 *job) +{ + void*(*fn)(const void*) = (void*(*)(const void*))&job2_dup; + return (JOB_INFO_2*)add_copy_to_array(len, + (void***)array, (const void*)job, *fn, True); +} + diff --git a/source3/rpc_server/srv_spoolss.c b/source3/rpc_server/srv_spoolss.c new file mode 100755 index 0000000000..60333e1f3b --- /dev/null +++ b/source3/rpc_server/srv_spoolss.c @@ -0,0 +1,793 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-2000, + * Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + * Copyright (C) Jean François Micouleau 1998-2000. + * + * 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; + +/******************************************************************** + * api_spoolss_open_printer_ex + ********************************************************************/ +static BOOL api_spoolss_open_printer_ex(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_OPEN_PRINTER_EX q_u; + SPOOL_R_OPEN_PRINTER_EX r_u; + UNISTR2 *printername = NULL; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!spoolss_io_q_open_printer_ex("", &q_u, data, 0)) { + DEBUG(0,("spoolss_io_q_open_printer_ex: unable to unmarshall SPOOL_Q_OPEN_PRINTER_EX.\n")); + return False; + } + + if (q_u.printername_ptr != 0) + { + printername = &q_u.printername; + } + + r_u.status = _spoolss_open_printer_ex( printername, + &q_u.printer_default, + q_u.user_switch, q_u.user_ctr, + &r_u.handle); + + if (!spoolss_io_r_open_printer_ex("",&r_u,rdata,0)){ + DEBUG(0,("spoolss_io_r_open_printer_ex: unable to marshall SPOOL_R_OPEN_PRINTER_EX.\n")); + return False; + } + + return True; +} + +/******************************************************************** + * api_spoolss_getprinterdata + * + * called from the spoolss dispatcher + ********************************************************************/ +static BOOL api_spoolss_getprinterdata(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_GETPRINTERDATA q_u; + SPOOL_R_GETPRINTERDATA r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + /* read the stream and fill the struct */ + if (!spoolss_io_q_getprinterdata("", &q_u, data, 0)) { + DEBUG(0,("spoolss_io_q_getprinterdata: unable to unmarshall SPOOL_Q_GETPRINTERDATA.\n")); + return False; + } + + r_u.status = _spoolss_getprinterdata( &q_u.handle, &q_u.valuename, + q_u.size, &r_u.type, &r_u.size, + &r_u.data, &r_u.needed); + + if (!spoolss_io_r_getprinterdata("", &r_u, rdata, 0)) { + DEBUG(0,("spoolss_io_r_getprinterdata: unable to marshall SPOOL_R_GETPRINTERDATA.\n")); + return False; + } + + safe_free(r_u.data); + + return True; +} + +/******************************************************************** + * api_spoolss_closeprinter + * + * called from the spoolss dispatcher + ********************************************************************/ +static BOOL api_spoolss_closeprinter(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_CLOSEPRINTER q_u; + SPOOL_R_CLOSEPRINTER r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_closeprinter("", &q_u, data, 0); + r_u.status = _spoolss_closeprinter(&q_u.handle); + memcpy(&r_u.handle, &q_u.handle, sizeof(r_u.handle)); + spoolss_io_r_closeprinter("",&r_u,rdata,0); +} + +/******************************************************************** + * api_spoolss_rffpcnex + * ReplyFindFirstPrinterChangeNotifyEx + ********************************************************************/ +static BOOL api_spoolss_rffpcnex(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_RFFPCNEX q_u; + SPOOL_R_RFFPCNEX r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_rffpcnex("", &q_u, data, 0); + + r_u.status = _spoolss_rffpcnex(&q_u.handle, q_u.flags, + q_u.options, &q_u.localmachine, + q_u.printerlocal, &q_u.option); + spoolss_io_r_rffpcnex("",&r_u,rdata,0); +} + + +/******************************************************************** + * api_spoolss_rfnpcnex + * ReplyFindNextPrinterChangeNotifyEx + * called from the spoolss dispatcher + * + ********************************************************************/ +static BOOL api_spoolss_rfnpcnex(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_RFNPCNEX q_u; + SPOOL_R_RFNPCNEX r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_rfnpcnex("", &q_u, data, 0); + + r_u.status = _spoolss_rfnpcnex(&q_u.handle, q_u.change, + &q_u.option, &r_u.count, &r_u.info); + spoolss_io_r_rfnpcnex("", &r_u, rdata, 0); +} + + +/******************************************************************** + * api_spoolss_enumprinters + * called from the spoolss dispatcher + * + ********************************************************************/ +static BOOL api_spoolss_enumprinters(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ENUMPRINTERS q_u; + SPOOL_R_ENUMPRINTERS r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_enumprinters("", &q_u, data, 0); + + /* lkclXXX DAMN DAMN DAMN! MICROSOFT @#$%S IT UP, AGAIN, AND WE + HAVE TO DEAL WITH IT! AGH! + */ + r_u.level = q_u.level; + r_u.status = _spoolss_enumprinters( + q_u.flags, + &q_u.servername, + q_u.level, + &q_u.buffer, + q_u.buf_size, + &r_u.offered, + &r_u.needed, + &r_u.ctr, + &r_u.returned); + + 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] = 0; + + spoolss_io_free_buffer(&(q_u.buffer)); + spoolss_io_r_enumprinters("",&r_u,rdata,0); +} + + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static BOOL api_spoolss_getprinter(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_GETPRINTER q_u; + SPOOL_R_GETPRINTER r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_getprinter("", &q_u, data, 0); + + r_u.status = _spoolss_getprinter(&q_u.handle, q_u.level, + &r_u.ctr, &q_u.offered, &r_u.needed); + + memcpy(&r_u.handle, &q_u.handle, sizeof(&r_u.handle)); + r_u.offered = q_u.offered; + r_u.level = q_u.level; + safe_free(q_u.buffer); + + spoolss_io_r_getprinter("",&r_u,rdata,0); +} + + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static BOOL api_spoolss_getprinterdriver2(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_GETPRINTERDRIVER2 q_u; + SPOOL_R_GETPRINTERDRIVER2 r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_getprinterdriver2("", &q_u, data, 0); + + r_u.status = _spoolss_getprinterdriver2(&q_u.handle, + &q_u.architecture, q_u.level, + &r_u.ctr, &q_u.buf_size, + &r_u.needed); + + r_u.offered = q_u.buf_size; + r_u.level = q_u.level; + spoolss_io_free_buffer(&(q_u.buffer)); + + spoolss_io_r_getprinterdriver2("",&r_u,rdata,0); +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static BOOL api_spoolss_startpageprinter(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_STARTPAGEPRINTER q_u; + SPOOL_R_STARTPAGEPRINTER r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_startpageprinter("", &q_u, data, 0); + r_u.status = _spoolss_startpageprinter(&q_u.handle); + spoolss_io_r_startpageprinter("",&r_u,rdata,0); +} + + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static BOOL api_spoolss_endpageprinter(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ENDPAGEPRINTER q_u; + SPOOL_R_ENDPAGEPRINTER r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_endpageprinter("", &q_u, data, 0); + r_u.status = _spoolss_endpageprinter(&q_u.handle); + spoolss_io_r_endpageprinter("",&r_u,rdata,0); +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static BOOL api_spoolss_startdocprinter(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_STARTDOCPRINTER q_u; + SPOOL_R_STARTDOCPRINTER r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_startdocprinter("", &q_u, data, 0); + r_u.status = _spoolss_startdocprinter(&q_u.handle, + q_u.doc_info_container.level, + &q_u.doc_info_container.docinfo, + &r_u.jobid); + spoolss_io_r_startdocprinter("",&r_u,rdata,0); +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static BOOL api_spoolss_enddocprinter(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ENDDOCPRINTER q_u; + SPOOL_R_ENDDOCPRINTER r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_enddocprinter("", &q_u, data, 0); + r_u.status = _spoolss_enddocprinter(&q_u.handle); + spoolss_io_r_enddocprinter("",&r_u,rdata,0); +} + + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static BOOL api_spoolss_writeprinter(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_WRITEPRINTER q_u; + SPOOL_R_WRITEPRINTER r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_writeprinter("", &q_u, data, 0); + r_u.status = _spoolss_writeprinter(&q_u.handle, + q_u.buffer_size, + q_u.buffer, + &q_u.buffer_size2); + r_u.buffer_written = q_u.buffer_size2; + safe_free(q_u.buffer); + spoolss_io_r_writeprinter("",&r_u,rdata,0); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_setprinter(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_SETPRINTER q_u; + SPOOL_R_SETPRINTER r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_setprinter("", &q_u, data, 0); + DEBUG(0,("api_spoolss_setprinter: typecast sec_des to uint8*!\n")); + r_u.status = _spoolss_setprinter(&q_u.handle, + q_u.level, &q_u.info, + q_u.devmode, + q_u.security.size_of_buffer, + (const uint8*)q_u.security.data, + q_u.command); + spoolss_io_r_setprinter("",&r_u,rdata,0); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_fcpn(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_FCPN q_u; + SPOOL_R_FCPN r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_fcpn("", &q_u, data, 0); + r_u.status = _spoolss_fcpn(&q_u.handle); + spoolss_io_r_fcpn("",&r_u,rdata,0); +} + + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_addjob(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ADDJOB q_u; + SPOOL_R_ADDJOB r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_addjob("", &q_u, data, 0); + + r_u.status = _spoolss_addjob(&q_u.handle, q_u.level, + &q_u.buffer, q_u.buf_size); + + spoolss_io_free_buffer(&(q_u.buffer)); + spoolss_io_r_addjob("",&r_u,rdata,0); +} + + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_enumjobs(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ENUMJOBS q_u; + SPOOL_R_ENUMJOBS r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_enumjobs("", &q_u, data, 0); + r_u.offered = q_u.buf_size; + r_u.level = q_u.level; + r_u.status = _spoolss_enumjobs(&q_u.handle, + q_u.firstjob, q_u.numofjobs, q_u.level, + &r_u.ctr, &r_u.offered, &r_u.numofjobs); + spoolss_io_free_buffer(&(q_u.buffer)); + spoolss_io_r_enumjobs("",&r_u,rdata,0); +} + + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_schedulejob(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_SCHEDULEJOB q_u; + SPOOL_R_SCHEDULEJOB r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_schedulejob("", &q_u, data, 0); + r_u.status = _spoolss_schedulejob(&q_u.handle, q_u.jobid); + spoolss_io_r_schedulejob("",&r_u,rdata,0); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_setjob(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_SETJOB q_u; + SPOOL_R_SETJOB r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_setjob("", &q_u, data, 0); + r_u.status = _spoolss_setjob(&q_u.handle, q_u.jobid, + q_u.level, &q_u.ctr, q_u.command); + spoolss_io_r_setjob("",&r_u,rdata,0); +} + +/**************************************************************************** +****************************************************************************/ + +static BOOL api_spoolss_enumprinterdrivers(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ENUMPRINTERDRIVERS q_u; + SPOOL_R_ENUMPRINTERDRIVERS r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_enumprinterdrivers("", &q_u, data, 0); + + r_u.offered = q_u.buf_size; + r_u.level = q_u.level; + r_u.status = _spoolss_enumprinterdrivers(&q_u.name, + &q_u.environment, q_u. level, + &r_u.ctr, &r_u.offered, &r_u.numofdrivers); + + spoolss_io_free_buffer(&q_u.buffer); + spoolss_io_r_enumdrivers("",&r_u,rdata,0); + free_spoolss_r_enumdrivers(&r_u); +} + + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_enumforms(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ENUMFORMS q_u; + SPOOL_R_ENUMFORMS r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + DEBUG(5,("spoolss_io_q_enumforms\n")); + + new_spoolss_allocate_buffer(&q_u.buffer); + + if (!spoolss_io_q_enumforms("", &q_u, data, 0)) + return False; + + /* that's an [in out] buffer */ + new_spoolss_move_buffer(q_u.buffer, &r_u.buffer); + + r_u.status = _new_spoolss_enumforms(&q_u.handle, q_u.level, + r_u.buffer, q_u.offered, + &r_u.needed, &r_u.numofforms); + + if (!new_spoolss_io_r_enumforms("",&r_u,rdata,0)) { + new_spoolss_free_buffer(q_u.buffer); + return False; + } + + new_spoolss_free_buffer(q_u.buffer); + + return True; +} + + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_enumports(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ENUMPORTS q_u; + SPOOL_R_ENUMPORTS r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_enumports("", &q_u, data, 0); + + r_u.offered = q_u.buf_size; + r_u.level = q_u.level; + r_u.status = _spoolss_enumports(&q_u.name, + q_u.level, + &r_u.ctr, + &r_u.offered, + &r_u.numofports); + + spoolss_io_free_buffer(&(q_u.buffer)); + spoolss_io_r_enumports("",&r_u,rdata,0); + spoolss_free_r_enumports(&r_u); +} + + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_addprinterex(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ADDPRINTEREX q_u; + SPOOL_R_ADDPRINTEREX r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_addprinterex("", &q_u, data, 0); + r_u.status = _spoolss_addprinterex(&q_u.server_name, + q_u.level, &q_u.info, + q_u.unk0, q_u.unk1, q_u.unk2, q_u.unk3, + q_u.user_level, &q_u.user, + &r_u.handle); + spoolss_io_r_addprinterex("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_addprinterdriver(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ADDPRINTERDRIVER q_u; + SPOOL_R_ADDPRINTERDRIVER r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_addprinterdriver("", &q_u, data, 0); + r_u.status = _spoolss_addprinterdriver(&q_u.server_name, + q_u.level, &q_u.info); + spoolss_io_r_addprinterdriver("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_getprinterdriverdirectory(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_GETPRINTERDRIVERDIR q_u; + SPOOL_R_GETPRINTERDRIVERDIR r_u; + + spoolss_io_q_getprinterdriverdir("", &q_u, data, 0); + + r_u.offered = q_u.buf_size; + r_u.level = q_u.level; + r_u.status = _spoolss_getprinterdriverdirectory(&q_u.name, + &q_u.environment, + q_u.level, + &r_u.ctr, + &r_u.offered); + spoolss_io_free_buffer(&q_u.buffer); + spoolss_io_r_getprinterdriverdir("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_enumprinterdata(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ENUMPRINTERDATA q_u; + SPOOL_R_ENUMPRINTERDATA r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_enumprinterdata("", &q_u, data, 0); + r_u.valuesize = q_u.valuesize; + r_u.datasize = q_u.datasize; + + r_u.status = _spoolss_enumprinterdata(&q_u.handle, + q_u.index,/* in */ + &r_u.valuesize,/* in out */ + &r_u.value,/* out */ + &r_u.realvaluesize,/* out */ + &r_u.type,/* out */ + &r_u.datasize,/* in out */ + &r_u.data,/* out */ + &r_u.realdatasize);/* out */ + spoolss_io_r_enumprinterdata("", &r_u, rdata, 0); + safe_free(r_u.data); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_setprinterdata(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_SETPRINTERDATA q_u; + SPOOL_R_SETPRINTERDATA r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_setprinterdata("", &q_u, data, 0); + r_u.status = _spoolss_setprinterdata(&q_u.handle, + &q_u.value, q_u.type, q_u.max_len, + q_u.data, q_u.real_len, q_u.numeric_data); + spoolss_io_r_setprinterdata("", &r_u, rdata, 0); + safe_free(q_u.data); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_addform(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ADDFORM q_u; + SPOOL_R_ADDFORM r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_addform("", &q_u, data, 0); + r_u.status = _spoolss_addform(&q_u.handle, q_u.level, &q_u.form); + spoolss_io_r_addform("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_setform(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_SETFORM q_u; + SPOOL_R_SETFORM r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_setform("", &q_u, data, 0); + r_u.status = _spoolss_setform(&q_u.handle, + &q_u.name, q_u.level, &q_u.form); + spoolss_io_r_setform("", &r_u, rdata, 0); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_enumprintprocessors(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ENUMPRINTPROCESSORS q_u; + SPOOL_R_ENUMPRINTPROCESSORS r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_enumprintprocessors("", &q_u, data, 0); + r_u.offered = q_u.buf_size; + r_u.level = q_u.level; + r_u.status = _spoolss_enumprintprocessors(&q_u.name, + &q_u.environment, + q_u.level, + &r_u.info_1, + &r_u.offered, + &r_u.numofprintprocessors); + spoolss_io_free_buffer(&q_u.buffer); + spoolss_io_r_enumprintprocessors("", &r_u, rdata, 0); + safe_free(r_u.info_1); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_enumprintmonitors(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_ENUMPRINTMONITORS q_u; + SPOOL_R_ENUMPRINTMONITORS r_u; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + spoolss_io_q_enumprintmonitors("", &q_u, data, 0); + r_u.offered = q_u.buf_size; + r_u.level = q_u.level; + r_u.status = _spoolss_enumprintmonitors(&q_u.name, + q_u.level, + &r_u.info_1, + &r_u.offered, + &r_u.numofprintmonitors); + spoolss_io_free_buffer(&q_u.buffer); + spoolss_io_r_enumprintmonitors("", &r_u, rdata, 0); + safe_free(r_u.info_1); +} + +/**************************************************************************** +****************************************************************************/ +static BOOL api_spoolss_getjob(uint16 vuid, prs_struct *data, prs_struct *rdata) +{ + SPOOL_Q_GETJOB q_u; + SPOOL_R_GETJOB r_u; + + spoolss_io_q_getjob("", &q_u, data, 0); + + r_u.offered = q_u.buf_size; + r_u.level = q_u.level; + r_u.status = _spoolss_getjob(&q_u.handle, + q_u.jobid, + q_u.level, + &r_u.ctr, + &r_u.offered); + spoolss_io_free_buffer(&(q_u.buffer)); + spoolss_io_r_getjob("",&r_u,rdata,0); + free_spoolss_r_getjob(&r_u); +} + +/******************************************************************* +\pipe\spoolss commands +********************************************************************/ +struct api_struct api_spoolss_cmds[] = +{ + {"SPOOLSS_OPENPRINTEREX", SPOOLSS_OPENPRINTEREX, api_spoolss_open_printer_ex }, + {"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 }, + {"SPOOLSS_ADDFORM", SPOOLSS_ADDFORM, api_spoolss_addform }, + {"SPOOLSS_SETFORM", SPOOLSS_SETFORM, api_spoolss_setform }, + {"SPOOLSS_ENUMPRINTPROCESSORS", SPOOLSS_ENUMPRINTPROCESSORS, api_spoolss_enumprintprocessors }, + {"SPOOLSS_ENUMMONITORS", SPOOLSS_ENUMMONITORS, api_spoolss_enumprintmonitors }, + {"SPOOLSS_GETJOB", SPOOLSS_GETJOB, api_spoolss_getjob }, + { 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); +} + diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c new file mode 100644 index 0000000000..db48fa42ff --- /dev/null +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -0,0 +1,3434 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-2000, + * Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + * Copyright (C) Jean François Micouleau 1998-2000. + * + * 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_PRINTER_EXS +#define MAX_OPEN_PRINTER_EXS 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 ok; + BOOL document_started; + BOOL page_started; + uint32 current_jobid; + uint32 document_fd; + uint32 document_lastwritten; + pstring document_name; + pstring job_name; + POLICY_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_PRINTER_EXS]; + +#define VALID_HANDLE(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PRINTER_EXS)) +#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_PRINTER_EXS; i++) + { + Printer[i].open = False; + } +} + +/**************************************************************************** + create a unique printer handle +****************************************************************************/ +static void create_printer_hnd(POLICY_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 */ +} + +/**************************************************************************** + find printer index by handle +****************************************************************************/ +static int find_printer_index_by_hnd(const POLICY_HND *hnd) +{ + int i; + + for (i = 0; i < MAX_OPEN_PRINTER_EXS; 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; +} + +/**************************************************************************** + clear an handle +****************************************************************************/ +static void clear_handle(POLICY_HND *hnd) +{ + bzero(hnd->data, POLICY_HND_SIZE); +} + +/**************************************************************************** + close printer index by handle +****************************************************************************/ +static BOOL close_printer_handle(POLICY_HND *hnd) +{ + int pnum = find_printer_index_by_hnd(hnd); + + if (pnum == -1) + { + DEBUG(3,("Error closing printer handle (pnum=%x)\n", pnum)); + return False; + } + + Printer[pnum].open=False; + clear_handle(hnd); + + return True; +} + +/**************************************************************************** + return the snum of a printer corresponding to an handle +****************************************************************************/ +static BOOL get_printer_snum(const POLICY_HND *hnd, int *number) +{ + int snum; + int pnum = find_printer_index_by_hnd(hnd); + int n_services=lp_numservices(); + + if (!OPEN_HANDLE(pnum)) { + DEBUG(3,("Error getting printer - take a nap quickly !\n")); + return False; + } + + switch (Printer[pnum].printer_type) { + case PRINTER_HANDLE_IS_PRINTER: + DEBUG(4,("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,("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; + } +} + +/**************************************************************************** + find first available printer slot. creates a printer handle for you. + ****************************************************************************/ +static BOOL open_printer_hnd(POLICY_HND *hnd) +{ + int i; + + for (i = 0; i < MAX_OPEN_PRINTER_EXS; i++) + { + if (!Printer[i].open) + { + Printer[i].open = True; + Printer[i].ok = True; + + 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; +} + +/**************************************************************************** + set printer handle type. +****************************************************************************/ +static BOOL set_printer_hnd_accesstype(POLICY_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; +} + +/**************************************************************************** + . +****************************************************************************/ +static BOOL printer_entry_is_valid(POLICY_HND *hnd) +{ + int pnum = find_printer_index_by_hnd(hnd); + + if (!OPEN_HANDLE(pnum)) + return False; + + if (Printer[pnum].ok == False) + return False; + + return True; +} + +/**************************************************************************** + set printer handle type. + check if it's \\server or \\server\printer +****************************************************************************/ +static BOOL set_printer_hnd_printertype(POLICY_HND *hnd, char *printername) +{ + int pnum = find_printer_index_by_hnd(hnd); + + if (!OPEN_HANDLE(pnum)) { + DEBUGADD(4,("Error setting printer name %s (pnum=%x)", printername, pnum)); + return False; + } + + 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)); + Printer[pnum].ok=False; + return False; + } + + /* it's a print server */ + if (!strchr(printername+2, '\\')) { + DEBUGADD(4,("Printer is a print server\n")); + Printer[pnum].printer_type = PRINTER_HANDLE_IS_PRINTSERVER; + Printer[pnum].ok=True; + + return True; + } + /* it's a printer */ + else { + DEBUGADD(4,("Printer is a printer\n")); + Printer[pnum].printer_type = PRINTER_HANDLE_IS_PRINTER; + Printer[pnum].ok=True; + return True; + } + + return False; +} + +/**************************************************************************** + set printer handle printername. +****************************************************************************/ +static BOOL set_printer_hnd_printername(POLICY_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(0,("Error setting printer name=%s (pnum=%x)\n", printername, pnum)); + return False; + } + + DEBUG(4,("Setting printer name=%s (len=%d) (pnum=%x)\n", printername, strlen(printername), pnum)); + + switch (Printer[pnum].printer_type) { + case PRINTER_HANDLE_IS_PRINTSERVER: + ZERO_STRUCT(Printer[pnum].dev.printerservername); + strncpy(Printer[pnum].dev.printerservername, printername, strlen(printername)); + return True; + break; + + 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,("share:%s\n",lp_servicename(snum))); + + marche=get_a_printer(&printer, 2, lp_servicename(snum)); + DEBUGADD(6,("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)); + ZERO_STRUCT(Printer[pnum].dev.printername); + strncpy(Printer[pnum].dev.printername, lp_servicename(snum), strlen(lp_servicename(snum))); + free_a_printer(printer, 2); + return True; + break; + } + free_a_printer(printer, 2); + } + } + return False; + break; + + default: + return False; + break; + } +} + +/******************************************************************** + ********************************************************************/ +static BOOL handle_is_printserver(const POLICY_HND *handle) +{ + int pnum=find_printer_index_by_hnd(handle); + + if (!OPEN_HANDLE(pnum)) + return False; + + if (Printer[pnum].printer_type != PRINTER_HANDLE_IS_PRINTSERVER) + return False; + + return True; +} + +/******************************************************************** + * spoolss_open_printer + * + * called from the spoolss dispatcher + ********************************************************************/ +uint32 _spoolss_open_printer_ex( const UNISTR2 *printername, + const PRINTER_DEFAULT *printer_default, + uint32 user_switch, SPOOL_USER_CTR user_ctr, + POLICY_HND *handle) +{ + BOOL printer_open = False; + fstring name; + fstring datatype; + + clear_handle(handle); + + if (printername == NULL) + return NT_STATUS_ACCESS_DENIED; + + /* some sanity check because you can open a printer or a print server */ + /* aka: \\server\printer or \\server */ + unistr2_to_ascii(name, printername, sizeof(name)-1); + + DEBUGADD(3,("checking name: %s\n",name)); + + create_printer_hnd(handle); + + open_printer_hnd(handle); + + set_printer_hnd_printertype(handle, name); + + set_printer_hnd_printername(handle, name); + +/* + if (printer_default->datatype_ptr != NULL) + { + unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1); + set_printer_hnd_datatype(handle, datatype); + } + else + set_printer_hnd_datatype(handle, ""); +*/ + + set_printer_hnd_accesstype(handle, printer_default->access_required); + + if (!printer_entry_is_valid(handle)) + { + close_printer_handle(handle); + return NT_STATUS_ACCESS_DENIED; + } + + return NT_STATUS_NO_PROBLEMO; +} + +static BOOL convert_printer_info(const 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; + } + + + + return True; +} + +static BOOL convert_printer_driver_info(const 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; + } + + + + return True; +} + +static BOOL 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); + } + + + return True; +} + +/******************************************************************** + * api_spoolss_closeprinter + ********************************************************************/ +uint32 _spoolss_closeprinter(POLICY_HND *handle) +{ + if (!close_printer_handle(handle)) + return NT_STATUS_INVALID_HANDLE; + + return NT_STATUS_NO_PROBLEMO; +} + +/******************************************************************** + ********************************************************************/ +static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed) +{ + int i; + + if (!strcmp(value, "BeepEnabled")) + { + *type = 0x4; + *data = (uint8 *)malloc( 4*sizeof(uint8) ); + SIVAL(data, 0, 0x01); + *needed = 0x4; + return True; + } + + if (!strcmp(value, "EventLog")) + { + *type = 0x4; + *data = (uint8 *)malloc( 4*sizeof(uint8) ); + SIVAL(data, 0, 0x1B); + *needed = 0x4; + return True; + } + + if (!strcmp(value, "NetPopup")) + { + *type = 0x4; + *data = (uint8 *)malloc( 4*sizeof(uint8) ); + SIVAL(data, 0, 0x01); + *needed = 0x4; + return True; + } + + if (!strcmp(value, "MajorVersion")) + { + *type = 0x4; + *data = (uint8 *)malloc( 4*sizeof(uint8) ); + SIVAL(data, 0, 0x02); + *needed = 0x4; + return True; + } + + if (!strcmp(value, "DefaultSpoolDirectory")) + { + pstring directory="You are using a Samba server"; + *type = 0x1; + *needed = 2*(strlen(directory)+1); + *data = (uint8 *)malloc(*needed *sizeof(uint8)); + ZERO_STRUCTP(*data); + + /* it's done by hand ready to go on the wire */ + for (i=0; i<strlen(directory); i++) + { + (*data)[2*i]=directory[i]; + (*data)[2*i+1]='\0'; + } + return True; + } + + if (!strcmp(value, "Architecture")) + { + pstring directory="Windows NT x86"; + *type = 0x1; + *needed = 2*(strlen(directory)+1); + *data = (uint8 *)malloc(*needed *sizeof(uint8)); + ZERO_STRUCTP(*data); + for (i=0; i<strlen(directory); i++) + { + (*data)[2*i]=directory[i]; + (*data)[2*i+1]='\0'; + } + return True; + } + + return False; +} + +/******************************************************************** + ********************************************************************/ +static BOOL getprinterdata_printer(const POLICY_HND *handle, + fstring value, uint32 *type, + uint8 **data, uint32 *needed ) +{ + NT_PRINTER_INFO_LEVEL printer; + int pnum=0; + int snum=0; + uint8 *idata=NULL; + 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)) + { + *data = (uint8 *)malloc( len*sizeof(uint8) ); + bzero(*data, sizeof(uint8)*len); + memcpy(*data, idata, len); + *needed = len; + + if (idata) free(idata); + return (True); + } + free_a_printer(printer, 2); + } + + return (False); +} + +/******************************************************************** + * spoolss_getprinterdata + ********************************************************************/ +uint32 _spoolss_getprinterdata(const POLICY_HND *handle, UNISTR2 *valuename, + uint32 in_size, + uint32 *type, + uint32 *out_size, + uint8 **data, + uint32 *needed) +{ + fstring value; + BOOL found; + int pnum = find_printer_index_by_hnd(handle); + + /* + * Reminder: when it's a string, the length is in BYTES + * even if UNICODE is negociated. + * + * JFM, 4/19/1999 + */ + + *out_size=in_size; + + /* in case of problem, return some default values */ + *needed=in_size; + *type=4; + + + if (!OPEN_HANDLE(pnum)) { + *data=(uint8 *)malloc(4*sizeof(uint8)); + return NT_STATUS_INVALID_HANDLE; + } + + unistr2_to_ascii(value, valuename, sizeof(value)-1); + + if (handle_is_printserver(handle)) + found=getprinterdata_printer_server(value, type, data, needed); + else + found=getprinterdata_printer(handle, value, type, data, needed); + + if (found==False) { + /* reply this param doesn't exist */ + *data=(uint8 *)malloc(4*sizeof(uint8)); + return ERROR_INVALID_PARAMETER; + } + + if (*needed > *out_size) + return ERROR_INSUFFICIENT_BUFFER; + else + return NT_STATUS_NO_PROBLEMO; +} + +/******************************************************************** + * _spoolss_rffpcnex + * ReplyFindFirstPrinterChangeNotifyEx + * + * 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 + * called from api_spoolss_rffpcnex + ********************************************************************/ +uint32 _spoolss_rffpcnex(const POLICY_HND *handle, + uint32 flags, uint32 options, + const UNISTR2 *localmachine, + uint32 printerlocal, + SPOOL_NOTIFY_OPTION *option) +{ + int i,j,k; + + /* store the notify value in the printer struct */ + + i=find_printer_index_by_hnd(handle); + + if (i == -1) + { + return NT_STATUS_INVALID_HANDLE; + } + + Printer[i].number_of_notify=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=option->type[j].count; + Printer[i].notify_info[j].type=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]=option->type[j].fields[k]; + } + } + + return 0x0; +} + +/******************************************************************* + * 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, NULL, &q, &status); + + data->notify_data.value[0]=(uint32) status.status; + if (q) free(q); +} + +/******************************************************************* + * 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, NULL, &q, &status); + if (q) free(q); +} + +/******************************************************************* + * 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 +********************************************************************/ +static 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 +********************************************************************/ +static 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 uint32 printserver_notify_info(const POLICY_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; + + if (pnum == -1) + { + return NT_STATUS_INVALID_HANDLE; + } + + 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")); + + return 0x0; +} + +/******************************************************************* + * + * fill a notify_info struct with info asked + * + ********************************************************************/ +static uint32 printer_notify_info(const POLICY_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 (pnum == -1 || !get_printer_snum(hnd, &snum) ) + { + return NT_STATUS_INVALID_HANDLE; + } + + 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, NULL, &queue, &status); + for (j=0; j<count; j++) + { + construct_notify_jobs_info(&(queue[j]), info, pnum, snum, i, queue[j].job); + } + safe_free(queue); + break; + } + } + } + + return 0x0; +} + +/******************************************************************** + * spoolss_rfnpcnex + ********************************************************************/ +uint32 _spoolss_rfnpcnex( const POLICY_HND *handle, + uint32 change, + const SPOOL_NOTIFY_OPTION *option, + uint32 *count, + SPOOL_NOTIFY_INFO *info) +{ + int pnum=find_printer_index_by_hnd(handle); + + if (pnum == -1 || !OPEN_HANDLE(pnum)) + { + return NT_STATUS_INVALID_HANDLE; + } + + DEBUG(4,("Printer %x of type %x\n",pnum,Printer[pnum].printer_type)); + + /* lkxlXXXX - jfm, is this right? put a warning in for you to review! */ + DEBUG(0,("_spoolss_rfnpcnex: change, option and count ignored\n")); + + switch (Printer[pnum].printer_type) + { + case PRINTER_HANDLE_IS_PRINTSERVER: + { + return printserver_notify_info(handle, info); + } + case PRINTER_HANDLE_IS_PRINTER: + { + return printer_notify_info(handle, info); + } + } + + return NT_STATUS_INVALID_INFO_CLASS; +} + +/******************************************************************** + * construct_printer_info_0 + * fill a printer_info_1 struct + ********************************************************************/ +static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer,int snum, pstring servername) +{ + pstring chaine; + int count; + NT_PRINTER_INFO_LEVEL ntprinter; + + print_queue_struct *queue=NULL; + print_status_struct status; + bzero(&status,sizeof(status)); + + if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0) + { + return (False); + } + + count=get_printqueue(snum, NULL, &queue, &status); + + /* the description and the name are of the form \\server\share */ + slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, ntprinter.info_2->printername); + + init_unistr(&(printer->printername), chaine); + + slprintf(chaine,sizeof(chaine)-1,"\\\\%s", servername); + init_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; + + safe_free(queue); + + free_a_printer(ntprinter, 2); + return (True); +} + +/******************************************************************** + * 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)); + init_unistr(&(printer->description), chaine); + + slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s", servername, ntprinter.info_2->printername); + init_unistr(&(printer->name), chaine); + + init_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); + init_unistr(&(devmode->devicename), adevice); + + snprintf(aform, sizeof(aform), ntdevmode->formname); + init_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, NULL, &queue, &status); + + if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 ) + { + return (False); + } + + snprintf(chaine, sizeof(chaine)-1, "\\\\%s", servername); + init_unistr(&(printer->servername), chaine); /* servername*/ + + snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", servername, ntprinter.info_2->printername); + init_unistr(&(printer->printername), chaine); /* printername*/ + + init_unistr(&(printer->sharename), lp_servicename(snum)); /* sharename */ + + init_unistr(&(printer->portname), lp_servicename(snum)); /* port */ + init_unistr(&(printer->drivername), ntprinter.info_2->drivername); /* drivername */ + + init_unistr(&(printer->comment), ntprinter.info_2->comment); /* comment */ + init_unistr(&(printer->location), ntprinter.info_2->location); /* location */ + init_unistr(&(printer->sepfile), ntprinter.info_2->sepfile); /* separator file */ + init_unistr(&(printer->printprocessor), ntprinter.info_2->printprocessor);/* print processor */ + init_unistr(&(printer->datatype), ntprinter.info_2->datatype); /* datatype */ + init_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; + + safe_free(queue); + free_a_printer(ntprinter, 2); + return (True); +} + +/******************************************************************** + * enum_printer_info_1 + * glue between spoolss_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_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); + } +} + +/******************************************************************** + * spoolss_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_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_2 pointers at [%p]\n", *number+1, *printers)); + if (enum_printer_info_2( &((*printers)[*number]), snum, *number) ) + { + (*number)++; + } + } + } +} + +/******************************************************************** + * api_spoolss_enumprinters + * + * called from api_spoolss_enumprinters (see this to understand) + ********************************************************************/ +uint32 _spoolss_enumprinters( + uint32 flags, + const UNISTR2 *servername, + uint32 level, + const BUFFER *buffer, + uint32 buf_size, + uint32 *offered, + uint32 *needed, + PRINTER_INFO_CTR *ctr, + uint32 *returned) +{ + DEBUG(4,("Enumerating printers\n")); + + (*returned)=0; + + switch (level) + { + case 1: + if (flags == PRINTER_ENUM_NAME || + flags == PRINTER_ENUM_NETWORK ) + { + /*if (is_a_printerserver(servername))*/ + enum_all_printers_info_1(&ctr->printer.printers_1, returned ); + /*else + enum_one_printer_info_1(&r_u);*/ + break; + } + case 2: + if (flags == PRINTER_ENUM_NAME || + flags == PRINTER_ENUM_NETWORK ) + { + /*if (is_a_printerserver(servername))*/ + enum_all_printers_info_2(&ctr->printer.printers_2, returned ); + /*else + enum_one_printer_info_2(&r_u);*/ + break; + } + case 3: /* doesn't exist */ + return NT_STATUS_INVALID_INFO_CLASS; + case 4: /* can't, always on local machine */ + break; + case 5: + return NT_STATUS_INVALID_INFO_CLASS; + + } + DEBUG(4,("%d printers enumerated\n", *returned)); + (*offered) = buffer->size; + + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_getprinter( POLICY_HND *handle, + uint32 level, + PRINTER_INFO *ctr, + uint32 *offered, + uint32 *needed) +{ + int snum; + pstring servername; + + pstrcpy(servername, global_myname); + + if (!get_printer_snum(handle,&snum)) + { + return NT_STATUS_INVALID_HANDLE; + } + + DEBUG(0,("_spoolss_getprinter: offered and needed params ignored\n")); + + switch (level) + { + case 0: + { + PRINTER_INFO_0 *printer; + + printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0)); + construct_printer_info_0(printer, snum, servername); + ctr->printer.info0=printer; + + return 0x0; + } + case 1: + { + PRINTER_INFO_1 *printer; + + printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1)); + construct_printer_info_1(printer, snum, servername); + ctr->printer.info1=printer; + + return 0x0; + } + case 2: + { + PRINTER_INFO_2 *printer; + + printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)); + construct_printer_info_2(printer, snum, servername); + ctr->printer.info2=printer; + + return 0x0; + } + default: + { + break; + } + } + + return NT_STATUS_INVALID_INFO_CLASS; +} + +/******************************************************************** + * 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) +{ + init_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; + + init_unistr( &(info->name), driver.info_3->name ); + init_unistr( &(info->architecture), architecture ); + + snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "%s%s", where, + driver.info_3->driverpath); + init_unistr( &(info->driverpath), temp_driverpath ); + + snprintf(temp_datafile, sizeof(temp_datafile)-1, "%s%s", where, + driver.info_3->datafile); + init_unistr( &(info->datafile), temp_datafile ); + + snprintf(temp_configfile, sizeof(temp_configfile)-1, "%s%s", where, + driver.info_3->configfile); + init_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); +} + +/******************************************************************** + * copy a strings array and convert to UNICODE + ********************************************************************/ +static void init_unistr_array(UNISTR ***uni_array, char **char_array, char *where) +{ + int i=0; + char *v; + pstring line; + + DEBUG(6,("init_unistr_array\n")); + + for (v=char_array[i]; *v!='\0'; v=char_array[i]) + { + DEBUGADD(6,("i:%d:", i)); + DEBUGADD(6,("%s:%d:", v, strlen(v))); + + *uni_array=(UNISTR **)Realloc(*uni_array, sizeof(UNISTR *)*(i+1)); + DEBUGADD(7,("realloc:[%p],", *uni_array)); + + (*uni_array)[i]=(UNISTR *)malloc( sizeof(UNISTR) ); + DEBUGADD(7,("alloc:[%p],", (*uni_array)[i])); + + snprintf(line, sizeof(line)-1, "%s%s", where, v); + init_unistr( (*uni_array)[i], line ); + DEBUGADD(7,("copy\n")); + + i++; + } + DEBUGADD(7,("last one\n")); + + *uni_array=(UNISTR **)Realloc(*uni_array, sizeof(UNISTR *)*(i+1)); + (*uni_array)[i]=0x0000; + DEBUGADD(6,("last one:done\n")); +} + +/******************************************************************** + * 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; + + init_unistr( &(info->name), driver.info_3->name ); + init_unistr( &(info->architecture), architecture ); + + snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "%s%s", where, driver.info_3->driverpath); + init_unistr( &(info->driverpath), temp_driverpath ); + + snprintf(temp_datafile, sizeof(temp_datafile)-1, "%s%s", where, driver.info_3->datafile); + init_unistr( &(info->datafile), temp_datafile ); + + snprintf(temp_configfile, sizeof(temp_configfile)-1, "%s%s", where, driver.info_3->configfile); + init_unistr( &(info->configfile), temp_configfile ); + + snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "%s%s", where, driver.info_3->helpfile); + init_unistr( &(info->helpfile), temp_helpfile ); + + init_unistr( &(info->monitorname), driver.info_3->monitorname ); + init_unistr( &(info->defaultdatatype), driver.info_3->defaultdatatype ); + + info->dependentfiles=NULL; + init_unistr_array(&(info->dependentfiles), driver.info_3->dependentfiles, where); +} + +/******************************************************************** + * 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); +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_getprinterdriver2( const POLICY_HND *handle, + const UNISTR2 *uni_arch, + uint32 level, + DRIVER_INFO *ctr, + uint32 *offered, + uint32 *needed) +{ + 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); + + if (!get_printer_snum(handle,&snum)) + { + return NT_STATUS_INVALID_HANDLE; + } + + unistr2_to_ascii(architecture, uni_arch, sizeof(architecture) ); + + DEBUG(1,("spoolss_getprinterdriver2:[%d]\n", level)); + + switch (level) + { + case 1: + { + info1=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1)); + construct_printer_driver_info_1(info1, snum, servername, architecture); + ctr->driver.info1=info1; + + return 0x0; + } + case 2: + { + info2=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2)); + construct_printer_driver_info_2(info2, snum, servername, architecture); + ctr->driver.info2=info2; + + return 0x0; + } + case 3: + { + info3=(DRIVER_INFO_3 *)malloc(sizeof(DRIVER_INFO_3)); + construct_printer_driver_info_3(info3, snum, servername, architecture); + ctr->driver.info3=info3; + + return 0x0; + } + default: + { + break; + } + } + return NT_STATUS_INVALID_INFO_CLASS; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_startpageprinter(const POLICY_HND *handle) +{ + int pnum = find_printer_index_by_hnd(handle); + + if (OPEN_HANDLE(pnum)) + { + Printer[pnum].page_started=True; + return 0x0; + } + + DEBUG(3,("Error in startpageprinter printer handle (pnum=%x)\n",pnum)); + return NT_STATUS_INVALID_HANDLE; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_endpageprinter(const POLICY_HND *handle) +{ + int pnum = find_printer_index_by_hnd(handle); + + if (OPEN_HANDLE(pnum)) + { + Printer[pnum].page_started=False; + return 0x0; + } + + DEBUG(3,("Error in endpageprinter printer handle (pnum=%x)\n",pnum)); + return NT_STATUS_INVALID_HANDLE; +} + + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +uint32 _spoolss_startdocprinter( const POLICY_HND *handle, uint32 level, + DOC_INFO *docinfo, uint32 *jobid) +{ + DOC_INFO_1 *info_1 = &docinfo->doc_info_1; + + pstring fname; + pstring tempname; + pstring datatype; + int fd = -1; + int snum; + int pnum; + + pnum = find_printer_index_by_hnd(handle); + + if (!VALID_HANDLE(pnum)) + { + return NT_STATUS_INVALID_HANDLE; + } + + /* + * a nice thing with NT is it doesn't listen to what you tell it. + * when asked to send _only_ RAW datas, it tries to send datas + * in EMF format. + * + * So I add checks like in NT Server ... + * + * lkclXXXX jean-francois, i love this kind of thing. oh, well, + * there's a bug in NT client-side code, so we'll fix it in the + * server-side code. *nnnnnggggh!* + */ + + if (info_1->p_datatype != 0) + { + unistr2_to_ascii(datatype, &(info_1->docname), sizeof(datatype)); + if (strcmp(datatype, "RAW") != 0) + { + (*jobid)=0; + return STATUS_1804; + } + } + + /* get the share number of the printer */ + if (!get_printer_snum(handle, &snum)) + { + return NT_STATUS_INVALID_HANDLE; + } + + /* 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, + &info_1->docname, + sizeof(Printer[pnum].job_name)); + + Printer[pnum].document_fd=fd; + Printer[pnum].document_started=True; + (*jobid) = Printer[pnum].current_jobid; + + return 0x0; +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +uint32 _spoolss_enddocprinter(const POLICY_HND *handle) +{ + int pnum; + int snum; + pstring filename; + pstring filename1; + pstring job_name; + pstring syscmd; + char *tstr; + + *syscmd=0; + + pnum = find_printer_index_by_hnd(handle); + + if (!OPEN_HANDLE(pnum)) + { + DEBUG(3,("Error in enddocprinter handle (pnum=%x)\n",pnum)); + return NT_STATUS_INVALID_HANDLE; + } + 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); + + if (!get_printer_snum(handle,&snum)) + { + return NT_STATUS_INVALID_HANDLE; + } + + /* 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); + pstring_sub(syscmd, "%s", filename); + } + + pstring_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); + } + + pstring_sub(syscmd, "%p", tstr); + + /* If the lpr command support the 'Job' option replace here */ + pstring_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)); + if (ret < 0) + { + lpq_reset(snum); + return NT_STATUS_ACCESS_DENIED; + } + } + else + { + DEBUG(0,("Null print command?\n")); + lpq_reset(snum); + return NT_STATUS_ACCESS_DENIED; + } + + lpq_reset(snum); + + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_writeprinter( const POLICY_HND *handle, + uint32 buffer_size, + const uint8 *buffer, + uint32 *buffer_written) +{ + int pnum; + int fd; + + pnum = find_printer_index_by_hnd(handle); + + if (!OPEN_HANDLE(pnum)) + { + DEBUG(3,("Error in writeprinter handle (pnum=%x)\n",pnum)); + return NT_STATUS_INVALID_HANDLE; + } + + fd = Printer[pnum].document_fd; + (*buffer_written) = write(fd, buffer, buffer_size); + Printer[pnum].document_lastwritten = (*buffer_written); + + return 0x0; +} + +/******************************************************************** + * api_spoolss_getprinter + * called from the spoolss dispatcher + * + ********************************************************************/ +static uint32 control_printer(const POLICY_HND *handle, uint32 command) +{ + int pnum; + int snum; + pnum = find_printer_index_by_hnd(handle); + + if ( pnum == -1 || !get_printer_snum(handle, &snum) ) + { + return NT_STATUS_INVALID_HANDLE; + } + + switch (command) + { + case PRINTER_CONTROL_PAUSE: + /* pause the printer here */ + status_printqueue(NULL, snum, LPSTAT_STOPPED); + return 0x0; + + case PRINTER_CONTROL_RESUME: + case PRINTER_CONTROL_UNPAUSE: + /* UN-pause the printer here */ + status_printqueue(NULL, snum, LPSTAT_OK); + return 0x0; + case PRINTER_CONTROL_PURGE: + /* Envoi des dragées FUCA dans l'imprimante */ + break; + } + + return NT_STATUS_INVALID_INFO_CLASS; +} + +/******************************************************************** + * called by spoolss_api_setprinter + * when updating a printer description + ********************************************************************/ +static uint32 update_printer(const POLICY_HND *handle, uint32 level, + const SPOOL_PRINTER_INFO_LEVEL *info, + const DEVICEMODE *devmode) +{ + int pnum; + int snum; + NT_PRINTER_INFO_LEVEL printer; + NT_DEVICEMODE *nt_devmode; + uint32 status = 0x0; + + 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 NT_STATUS_INVALID_INFO_CLASS; + } + + pnum = find_printer_index_by_hnd(handle); + if ( pnum == -1 || !get_printer_snum(handle, &snum) ) + { + return NT_STATUS_INVALID_HANDLE; + } + 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); + } + else + { + if (printer.info_2->devmode != NULL) + { + free(printer.info_2->devmode); + } + printer.info_2->devmode=NULL; + } + + if (status == 0x0) + { + status = add_a_printer(printer, level); + } + if (status == 0x0) + { + status = free_a_printer(printer, level); + } + + return status; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_setprinter( const POLICY_HND *handle, + uint32 level, + const SPOOL_PRINTER_INFO_LEVEL *info, + const DEVICEMODE *devmode, + uint32 sec_buf_size, + const char *sec_buf, + uint32 command) +{ + int pnum = find_printer_index_by_hnd(handle); + + if (!OPEN_HANDLE(pnum)) + { + return NT_STATUS_INVALID_HANDLE; + } + /* check the level */ + switch (level) + { + case 0: return control_printer(handle, command); + case 2: return update_printer(handle, level, info, devmode); + } + + return NT_STATUS_INVALID_INFO_CLASS; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_fcpn( const POLICY_HND *handle) +{ + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_addjob( const POLICY_HND *handle, uint32 level, + const BUFFER *buffer, + uint32 buf_size) +{ + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +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; + init_unistr(&(job_info->printername), lp_servicename(snum)); + init_unistr(&(job_info->machinename), temp_name); + init_unistr(&(job_info->username), queue->user); + init_unistr(&(job_info->document), queue->file); + init_unistr(&(job_info->datatype), "RAW"); + init_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 BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue, + int position, int snum) +{ + pstring temp_name; + DEVICEMODE *devmode; + NT_PRINTER_INFO_LEVEL ntprinter; + pstring chaine; + + struct tm *t; + time_t unixdate = time(NULL); + + if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 ) + { + return (False); + } + + t=gmtime(&unixdate); + snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname); + + job_info->jobid=queue->job; + + snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter.info_2->printername); + init_unistr(&(job_info->printername), chaine); + + init_unistr(&(job_info->machinename), temp_name); + init_unistr(&(job_info->username), queue->user); + init_unistr(&(job_info->document), queue->file); + init_unistr(&(job_info->notifyname), queue->user); + init_unistr(&(job_info->datatype), "RAW"); + init_unistr(&(job_info->printprocessor), "winprint"); + init_unistr(&(job_info->parameters), ""); + init_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; + + devmode=(DEVICEMODE *)malloc(sizeof(DEVICEMODE)); + ZERO_STRUCTP(devmode); + construct_dev_mode(devmode, snum, global_myname); + job_info->devmode=devmode; + + free_a_printer(ntprinter, 2); + return (True); +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_enumjobs( const POLICY_HND *handle, + uint32 reqfirstjob, + uint32 reqnumofjobs, + uint32 level, + JOB_INFO_CTR *ctr, + uint32 *buf_size, + uint32 *numofjobs) +{ + int snum; + int count; + int i; + print_queue_struct *queue=NULL; + print_status_struct prt_status; + + DEBUG(4,("spoolss_enumjobs\n")); + + ZERO_STRUCT(prt_status); + + if (!get_printer_snum(handle, &snum)) + { + return NT_STATUS_INVALID_HANDLE; + } + + count = get_printqueue(snum, NULL, &queue, &prt_status); + (*numofjobs) = 0; + + DEBUG(4,("count:[%d], status:[%d], [%s]\n", + count, prt_status.status, prt_status.message)); + + switch (level) + { + case 1: + { + for (i=0; i<count; i++) + { + JOB_INFO_1 *job_info_1; + job_info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1)); + add_job1_to_array(numofjobs, + &ctr->job.job_info_1, + job_info_1); + + fill_job_info_1(ctr->job.job_info_1[i], + &(queue[i]), i, snum); + } + safe_free(queue); + return 0x0; + } + case 2: + { + for (i=0; i<count; i++) + { + JOB_INFO_2 *job_info_2; + job_info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2)); + add_job2_to_array(numofjobs, + &ctr->job.job_info_2, + job_info_2); + + fill_job_info_2(ctr->job.job_info_2[i], + &(queue[i]), i, snum); + } + safe_free(queue); + return 0x0; + } + } + + safe_free(queue); + + return NT_STATUS_INVALID_INFO_CLASS; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_schedulejob( const POLICY_HND *handle, uint32 jobid) +{ + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_setjob( const POLICY_HND *handle, + uint32 jobid, + uint32 level, + JOB_INFO *ctr, + uint32 command) + +{ + int snum; + print_queue_struct *queue=NULL; + print_status_struct prt_status; + int i=0; + BOOL found=False; + int count; + + bzero(&prt_status,sizeof(prt_status)); + + if (!get_printer_snum(handle, &snum)) + { + return NT_STATUS_INVALID_HANDLE; + } + + count=get_printqueue(snum, NULL, &queue, &prt_status); + + while ( (i<count) && found==False ) + { + if ( jobid == queue[i].job ) + { + found=True; + } + i++; + } + + if (found==True) + { + switch (command) + { + case JOB_CONTROL_CANCEL: + case JOB_CONTROL_DELETE: + { + del_printqueue(NULL, snum, jobid); + safe_free(queue); + return 0x0; + } + case JOB_CONTROL_PAUSE: + { + status_printjob(NULL, snum, jobid, LPQ_PAUSED); + safe_free(queue); + return 0x0; + } + case JOB_CONTROL_RESUME: + { + status_printjob(NULL, snum, jobid, LPQ_QUEUED); + safe_free(queue); + return 0x0; + } + } + } + safe_free(queue); + return NT_STATUS_INVALID_INFO_CLASS; + +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_enumprinterdrivers( const UNISTR2 *name, + const UNISTR2 *environment, + uint32 level, + DRIVER_INFO *ctr, + uint32 *offered, + uint32 *numofdrivers) +{ + NT_PRINTER_DRIVER_INFO_LEVEL driver; + int count; + int i; + fstring *list; + fstring servername; + fstring architecture; + + DEBUG(4,("spoolss_enumdrivers\n")); + fstrcpy(servername, global_myname); + + unistr2_to_ascii(architecture, 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])); + } + + (*numofdrivers)=count; + + switch (level) + { + case 1: + { + DRIVER_INFO_1 *driver_info_1=NULL; + 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); + } + ctr->driver.info1=driver_info_1; + break; + } + case 2: + { + DRIVER_INFO_2 *driver_info_2=NULL; + 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); + } + ctr->driver.info2=driver_info_2; + break; + } + case 3: + { + DRIVER_INFO_3 *driver_info_3=NULL; + 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); + } + ctr->driver.info3=driver_info_3; + break; + } + default: + { + return NT_STATUS_INVALID_INFO_CLASS; + } + } + return 0x0; + +} + +/**************************************************************************** +****************************************************************************/ +static void fill_form_1(FORM_1 *form, nt_forms_struct *list, int position) +{ + form->flag=list->flag; + init_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 BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size) +{ + prs_struct *ps; + uint32 extra_space; + + ps=&(buffer->prs); + + /* damn, I'm doing the reverse operation of prs_grow() :) */ + extra_space = buffer_size - prs_data_size(ps); + + if (!prs_grow(ps, extra_space)) + return False; + + buffer->string_at_end=buffer_size; + + return True; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _new_spoolss_enumforms( const POLICY_HND *handle, uint32 level, + NEW_BUFFER *buffer, uint32 offered, + uint32 *needed, uint32 *numofforms) +{ + nt_forms_struct *list=NULL; + FORM_1 *forms_1; + int buffer_size=0; + int i; + + + DEBUG(4,("_new_spoolss_enumforms\n")); + DEBUGADD(5,("Offered buffer size [%d]\n", offered)); + DEBUGADD(5,("Info level [%d]\n", level)); + + *numofforms = get_ntforms(&list); + DEBUGADD(5,("Number of forms [%d]\n", *numofforms)); + + switch (level) { + case 1: + forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1)); + + /* construct the list of form structures */ + for (i=0; i<*numofforms; i++) + { + DEBUGADD(6,("Filling form number [%d]\n",i)); + fill_form_1(&(forms_1[i]), &(list[i]), i); + } + + /* check the required size. */ + for (i=0; i<*numofforms; i++) + { + DEBUGADD(6,("adding form [%d]'s size\n",i)); + buffer_size += spoolss_size_form_1(&(forms_1[i])); + } + + *needed=buffer_size; + + if (!alloc_buffer_size(buffer, buffer_size)) + return ERROR_INSUFFICIENT_BUFFER; + + /* fill the buffer with the form structures */ + for (i=0; i<*numofforms; i++) + { + DEBUGADD(6,("adding form [%d] to buffer\n",i)); + new_smb_io_form_1("", buffer, &(forms_1[i]), 0); + } + + safe_free(list); + + if (*needed > offered) + return ERROR_INSUFFICIENT_BUFFER; + else + return NT_STATUS_NO_PROBLEMO; + + default: + safe_free(list); + return NT_STATUS_INVALID_INFO_CLASS; + } + +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_enumforms( const POLICY_HND *handle, + uint32 level, + FORM_1 **forms_1, + uint32 *offered, + uint32 *numofforms) +{ + int count; + int i; + nt_forms_struct *list=NULL; + (*forms_1)=NULL; + + DEBUG(4,("spoolss_enumforms\n")); + + count = get_ntforms(&list); + (*numofforms) = count; + + DEBUGADD(5,("Offered buffer size [%d]\n", *offered)); + DEBUGADD(5,("Number of forms [%d]\n", *numofforms)); + DEBUGADD(5,("Info level [%d]\n", level)); + + switch (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); + } + safe_free(list); + return 0x0; + } + } + + safe_free(list); + return NT_STATUS_INVALID_INFO_CLASS; +} + +/**************************************************************************** +****************************************************************************/ +static void fill_port_2(PORT_INFO_2 *port, char *name) +{ + init_unistr(&(port->port_name), name); + init_unistr(&(port->monitor_name), "Moniteur Local"); + init_unistr(&(port->description), "Local Port"); +#define PORT_TYPE_WRITE 1 + port->port_type=PORT_TYPE_WRITE; + port->reserved=0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_enumports( const UNISTR2 *name, + uint32 level, + PORT_INFO_CTR *ctr, + uint32 *offered, + uint32 *numofports) +{ + int n_services=lp_numservices(); + int snum; + + DEBUG(4,("spoolss_enumports\n")); + + (*numofports) = 0; + + switch (level) + { + case 2: + { + PORT_INFO_2 *ports_2=NULL; + 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 no [%d]\n", + (*numofports))); + fill_port_2(&(ports_2[(*numofports)]), + lp_servicename(snum)); + (*numofports)++; + } + } + ctr->port.info_2=ports_2; + return 0x0; + } + } + + return NT_STATUS_INVALID_INFO_CLASS; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, + uint32 level, + const SPOOL_PRINTER_INFO_LEVEL *info, + uint32 unk0, + uint32 unk1, + uint32 unk2, + uint32 unk3, + uint32 user_level, + const SPOOL_USER_LEVEL *user, + POLICY_HND *handle) +{ + NT_PRINTER_INFO_LEVEL printer; + fstring ascii_name; + fstring server_name; + fstring share_name; + UNISTR2 *portname; + SPOOL_PRINTER_INFO_LEVEL_2 *info2; + uint32 status = 0x0; + + if (!open_printer_hnd(handle)) + { + return NT_STATUS_ACCESS_DENIED; + } + + /* 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(info, &printer, level); + + /* write the ASCII on disk */ + status = add_a_printer(printer, level); + if (status != 0x0) + { + close_printer_handle(handle); + return status; + } + + info2=info->info_2; + portname=&(info2->portname); + + 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); + + if (!set_printer_hnd_printertype(handle, ascii_name) || + !set_printer_hnd_printername(handle, ascii_name)) + { + close_printer_handle(handle); + return NT_STATUS_ACCESS_DENIED; + } + + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_addprinterdriver( const UNISTR2 *server_name, + uint32 level, + const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info) +{ + NT_PRINTER_DRIVER_INFO_LEVEL driver; + convert_printer_driver_info(info, &driver, level); + return add_a_printer_driver(driver, level); +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_getprinterdriverdirectory( const UNISTR2 *name, + const UNISTR2 *uni_environment, + uint32 level, + DRIVER_DIRECTORY_CTR *ctr, + uint32 *offered) +{ + pstring chaine; + pstring long_archi; + pstring archi; + + unistr2_to_ascii(long_archi, uni_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)); + + init_unistr(&(ctr->driver.info_1.name), chaine); + + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_enumprinterdata(const POLICY_HND *handle, + uint32 idx, + uint32 *valuesize, + UNISTR *uni_value, + uint32 *realvaluesize, + uint32 *type, + uint32 *datasize, + uint8 **data, + uint32 *realdatasize) +{ + NT_PRINTER_INFO_LEVEL printer; + + fstring value; + + uint32 param_index; + uint32 biggest_valuesize; + uint32 biggest_datasize; + uint32 data_len; + uint32 status = 0x0; + + int pnum = find_printer_index_by_hnd(handle); + int snum; + + ZERO_STRUCT(printer); + (*data)=NULL; + + DEBUG(5,("spoolss_enumprinterdata\n")); + + if (!OPEN_HANDLE(pnum)) + { + return NT_STATUS_INVALID_HANDLE; + } + if (!get_printer_snum(handle, &snum)) + { + return NT_STATUS_INVALID_HANDLE; + } + status = get_a_printer(&printer, 2, lp_servicename(snum)); + + if (status != 0x0) + { + return status; + } + + /* The NT machine wants to know the biggest size of value and data */ + if ( ((*valuesize)==0) && ((*datasize)==0) ) + { + DEBUGADD(6,("Activating NT mega-hack to find sizes\n")); + + (*valuesize)=0; + (*realvaluesize)=0; + (*type)=0; + (*datasize)=0; + (*realdatasize)=0; + status=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 */ + if (biggest_valuesize!=0) + { + SIVAL(&(value),0, 2*(biggest_valuesize+1) ); + } + (*data)=(uint8 *)malloc(4*sizeof(uint8)); + SIVAL((*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 + */ + + if (get_specific_param_by_index(printer, 2, idx, value, data, type, &data_len)) + { + init_unistr(uni_value, value); + + /* the length are in bytes including leading NULL */ + (*realvaluesize)=2*(strlen(value)+1); + (*realdatasize)=data_len; + + status=0; + } + else + { + (*valuesize)=0; + (*realvaluesize)=0; + (*datasize)=0; + (*realdatasize)=0; + (*type)=0; + status=0x0103; /* ERROR_NO_MORE_ITEMS */ + } + } + + free_a_printer(printer, 2); + + return status; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_setprinterdata( const POLICY_HND *handle, + const UNISTR2 *value, + uint32 type, + uint32 max_len, + const uint8 *data, + uint32 real_len, + uint32 numeric_data) +{ + NT_PRINTER_INFO_LEVEL printer; + NT_PRINTER_PARAM *param = NULL; + + int pnum=0; + int snum=0; + uint32 status = 0x0; + + DEBUG(5,("spoolss_setprinterdata\n")); + + pnum = find_printer_index_by_hnd(handle); + + if (!OPEN_HANDLE(pnum)) + { + return NT_STATUS_INVALID_HANDLE; + } + if (!get_printer_snum(handle, &snum)) + { + return NT_STATUS_INVALID_HANDLE; + } + + status = get_a_printer(&printer, 2, lp_servicename(snum)); + if (status != 0x0) + { + return status; + } + + convert_specific_param(¶m, value , type, data, real_len); + unlink_specific_param_if_exist(printer.info_2, param); + + if (!add_a_specific_param(printer.info_2, param)) + { + status = NT_STATUS_INVALID_PARAMETER; + } + else + { + status = add_a_printer(printer, 2); + } + free_a_printer(printer, 2); + + return status; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_addform( const POLICY_HND *handle, + uint32 level, + const FORM *form) +{ + int pnum=0; + int count=0; + nt_forms_struct *list=NULL; + + DEBUG(5,("spoolss_addform\n")); + + pnum = find_printer_index_by_hnd(handle); + + if (!OPEN_HANDLE(pnum)) + { + return NT_STATUS_INVALID_HANDLE; + } + + count=get_ntforms(&list); + add_a_form(&list, form, &count); + write_ntforms(&list, count); + + safe_free(list); + + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_setform( const POLICY_HND *handle, + const UNISTR2 *uni_name, + uint32 level, + const FORM *form) +{ + int pnum=0; + int count=0; + nt_forms_struct *list=NULL; + + DEBUG(5,("spoolss_setform\n")); + + pnum = find_printer_index_by_hnd(handle); + if (!OPEN_HANDLE(pnum)) + { + return NT_STATUS_INVALID_HANDLE; + } + count=get_ntforms(&list); + update_a_form(&list, form, count); + write_ntforms(&list, count); + + safe_free(list); + + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_enumprintprocessors(const UNISTR2 *name, + const UNISTR2 *environment, + uint32 level, + PRINTPROCESSOR_1 **info_1, + uint32 *offered, + uint32 *numofprintprocessors) +{ + DEBUG(5,("spoolss_enumprintprocessors\n")); + + /* + * Enumerate the print processors ... + * + * Just reply with "winprint", to keep NT happy + * and I can use my nice printer checker. + */ + + (*numofprintprocessors) = 0x1; + (*info_1) = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1)); + + if ((*info_1) == NULL) + { + return NT_STATUS_NO_MEMORY; + } + + init_unistr(&((*info_1)->name), "winprint"); + + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_enumprintmonitors( const UNISTR2 *name, + uint32 level, + PRINTMONITOR_1 **info_1, + uint32 *offered, + uint32 *numofprintmonitors) +{ + DEBUG(5,("spoolss_enumprintmonitors\n")); + + /* + * Enumerate the print monitors ... + * + * Just reply with "Local Port", to keep NT happy + * and I can use my nice printer checker. + */ + + (*numofprintmonitors) = 0x1; + (*info_1) = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1)); + if ((*info_1) == NULL) + { + return NT_STATUS_NO_MEMORY; + } + + init_unistr(&((*info_1)->name), "Local Port"); + + return 0x0; +} + +/**************************************************************************** +****************************************************************************/ +uint32 _spoolss_getjob( const POLICY_HND *handle, + uint32 jobid, + uint32 level, + PJOB_INFO *ctr, + uint32 *offered) +{ + int snum; + int count; + int i; + print_queue_struct *queue=NULL; + print_status_struct prt_status; + + DEBUG(4,("spoolss_getjob\n")); + + bzero(&prt_status,sizeof(prt_status)); + + if (!get_printer_snum(handle, &snum)) + { + return NT_STATUS_INVALID_HANDLE; + } + count=get_printqueue(snum, NULL, &queue, &prt_status); + + DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n", + count, prt_status.status, prt_status.message)); + + switch (level) + { + case 1: + { + JOB_INFO_1 *job_info_1=NULL; + job_info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1)); + + if (job_info_1 == NULL) + { + safe_free(queue); + return NT_STATUS_NO_MEMORY; + } + + for (i=0; i<count; i++) + { + if (queue[i].job==(int)jobid) + { + fill_job_info_1(job_info_1, + &(queue[i]), i, snum); + } + } + ctr->job.job_info_1=job_info_1; + break; + } + case 2: + { + JOB_INFO_2 *job_info_2=NULL; + job_info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2)); + + if (job_info_2 == NULL) + { + safe_free(queue); + return NT_STATUS_NO_MEMORY; + } + + for (i=0; i<count; i++) + { + if (queue[i].job==(int)jobid) + { + fill_job_info_2(job_info_2, + &(queue[i]), i, snum); + } + } + ctr->job.job_info_2=job_info_2; + break; + } + default: + { + safe_free(queue); + return NT_STATUS_INVALID_INFO_CLASS; + } + } + + safe_free(queue); + return 0x0; +} |