summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/rpc_client/cli_spoolss.c68
-rw-r--r--source3/rpc_parse/parse_spoolss.c119
-rw-r--r--source3/rpcclient/cmd_spoolss.c18
3 files changed, 178 insertions, 27 deletions
diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c
index 5dda49b4b5..902f6e2bfe 100644
--- a/source3/rpc_client/cli_spoolss.c
+++ b/source3/rpc_client/cli_spoolss.c
@@ -545,31 +545,77 @@ BOOL spoolss_open_printer_ex( const char *printername,
do a SPOOLSS AddPrinterEx()
**ALWAYS** uses as PRINTER_INFO level 2 struct
****************************************************************************/
-BOOL spoolss_addprinterex(POLICY_HND *hnd, PRINTER_INFO_2 *info2)
+uint32 spoolss_addprinterex(POLICY_HND *hnd,const char* srv_name, PRINTER_INFO_2 *info2)
{
-#if 0
prs_struct rbuf;
prs_struct buf;
SPOOL_Q_ADDPRINTEREX q_o;
+ SPOOL_R_ADDPRINTEREX r_o;
BOOL valid_pol = False;
- fstring srv_name;
char *s = NULL;
struct cli_connection *con = NULL;
+ TALLOC_CTX *mem_ctx = NULL;
+ fstring client_name;
- memset(srv_name, 0, sizeof(srv_name));
- unistr_to_ascii(srv_name, info2->servername.buffer, sizeof(srv_name));
+
+ /* memset(srv_name, 0, sizeof(srv_name));
+ unistr_to_ascii(srv_name, info2->servername.buffer, sizeof(srv_name)); */
if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con))
- return False;
+ return NT_STATUS_ACCESS_DENIED;
+
+ if (hnd == NULL)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ if ((mem_ctx=talloc_init()) == NULL)
+ {
+ DEBUG(0,("spoolss_addprinterex: talloc_init() failed!\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ prs_init(&buf , MAX_PDU_FRAG_LEN, 4, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, 4, mem_ctx, UNMARSHALL);
+
+ /* create and send a MSRPC command with api SPOOLSS_ENUMPORTS */
+ DEBUG(5,("SPOOLSS Add Printer Ex (Server: %s)\n", srv_name));
+
+ fstrcpy(client_name, "\\\\");
+ fstrcat(client_name, con->pCli_state->desthost);
+ strupper(client_name);
+
+
+ make_spoolss_q_addprinterex(&q_o, srv_name, client_name,
+ "Administrator", 2, info2);
+
+ /* turn parameters into data stream */
+ if (!spoolss_io_q_addprinterex("", &q_o, &buf, 0) ) {
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+ cli_connection_unlink(con);
+ }
- if (hnd == NULL) return False;
+ if(!rpc_con_pipe_req(con, SPOOLSS_ADDPRINTEREX, &buf, &rbuf)) {
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
- prs_init(&buf , MAX_PDU_FRAG_LEN, 4, MARSHALL);
- prs_init(&rbuf, 0, 4, UNMARSHALL);
-#endif
+ cli_connection_unlink(con);
+ }
+
+ prs_mem_free(&buf );
+ ZERO_STRUCT(r_o);
- return True;
+ if(!spoolss_io_r_addprinterex("", &r_o, &rbuf, 0)) {
+ prs_mem_free(&rbuf);
+ cli_connection_unlink(con);
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+ cli_connection_unlink(con);
+
+ return r_o.status;
}
/****************************************************************************
diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c
index bd33b634f8..033b680e64 100644
--- a/source3/rpc_parse/parse_spoolss.c
+++ b/source3/rpc_parse/parse_spoolss.c
@@ -5,6 +5,7 @@
* Copyright (C) Andrew Tridgell 1992-2000,
* Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
* Copyright (C) Jean François Micouleau 1998-2000.
+ * Copyright (C) Gerald Carter 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
@@ -724,6 +725,112 @@ BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u,
}
/*******************************************************************
+ * init a structure.
+ ********************************************************************/
+BOOL make_spoolss_q_addprinterex(SPOOL_Q_ADDPRINTEREX *q_u, const char *srv_name,
+ const char* clientname, const char* user_name,
+ uint32 level, PRINTER_INFO_2 *info)
+{
+ DEBUG(5,("make_spoolss_q_addprinterex\n"));
+
+ q_u->server_name_ptr = (srv_name!=NULL)?1:0;
+ init_unistr2(&q_u->server_name, srv_name, strlen(srv_name));
+
+ q_u->level = level;
+
+ q_u->info.level = level;
+ q_u->info.info_ptr = (info!=NULL)?1:0;
+ switch (level)
+ {
+ case 2:
+ /* init q_u->info.info2 from *info */
+ if (!make_spool_printer_info_2( &q_u->info.info_2, info))
+ {
+ DEBUG(0,("make_spoolss_q_addprinterex: Unable to fill SPOOL_Q_ADDPRINTEREX struct!\n"));
+ return False;
+ }
+ break;
+ default :
+ break;
+ }
+
+ q_u->unk0 = q_u->unk1 = q_u->unk2 = q_u->unk3 = 0;
+
+ q_u->user_switch=1;
+
+ q_u->user_ctr.level=1;
+ q_u->user_ctr.ptr=1;
+ q_u->user_ctr.user1.size=strlen(clientname)+strlen(user_name)+8;
+ q_u->user_ctr.user1.client_name_ptr = (clientname!=NULL)?1:0;
+ q_u->user_ctr.user1.user_name_ptr = (user_name!=NULL)?1:0;
+ q_u->user_ctr.user1.build=1381;
+ q_u->user_ctr.user1.major=2;
+ q_u->user_ctr.user1.minor=0;
+ q_u->user_ctr.user1.processor=0;
+ init_unistr2(&q_u->user_ctr.user1.client_name, clientname, strlen(clientname));
+ init_unistr2(&q_u->user_ctr.user1.user_name, user_name, strlen(user_name));
+
+ return True;
+}
+/*******************************************************************
+create a SPOOL_PRINTER_INFO_2 stuct from a PRINTER_INFO_2 struct
+*******************************************************************/
+BOOL make_spool_printer_info_2(SPOOL_PRINTER_INFO_LEVEL_2 **spool_info2,
+ PRINTER_INFO_2 *info)
+{
+
+ SPOOL_PRINTER_INFO_LEVEL_2 *inf;
+
+ /* allocate the necessary memory */
+ inf = (SPOOL_PRINTER_INFO_LEVEL_2*)malloc(sizeof(SPOOL_PRINTER_INFO_LEVEL_2));
+ if (spool_info2 == NULL)
+ {
+ DEBUG(0,("make_spool_printer_info_2: Unable to malloc SPOOL_PRINTER_INFO_LEVEL_2 sruct!\n"));
+ return False;
+ }
+
+ ZERO_STRUCTP(inf);
+
+ inf->servername_ptr = (info->servername.buffer!=NULL)?1:0;
+ inf->printername_ptr = (info->printername.buffer!=NULL)?1:0;
+ inf->sharename_ptr = (info->sharename.buffer!=NULL)?1:0;
+ inf->portname_ptr = (info->portname.buffer!=NULL)?1:0;
+ inf->drivername_ptr = (info->drivername.buffer!=NULL)?1:0;
+ inf->comment_ptr = (info->comment.buffer!=NULL)?1:0;
+ inf->location_ptr = (info->location.buffer!=NULL)?1:0;
+ inf->devmode_ptr = (info->devmode!=NULL)?1:0;
+ inf->sepfile_ptr = (info->sepfile.buffer!=NULL)?1:0;
+ inf->printprocessor_ptr = (info->printprocessor.buffer!=NULL)?1:0;
+ inf->datatype_ptr = (info->datatype.buffer!=NULL)?1:0;
+ inf->parameters_ptr = (info->parameters.buffer!=NULL)?1:0;
+ inf->secdesc_ptr = (info->secdesc!=NULL)?1:0;
+ inf->attributes = info->attributes;
+ inf->priority = info->priority;
+ inf->default_priority = info->defaultpriority;
+ inf->starttime = info->starttime;
+ inf->untiltime = info->untiltime;
+ inf->cjobs = info->cjobs;
+ inf->averageppm = info->averageppm;
+ init_unistr2_from_unistr(&inf->servername, &info->servername);
+ init_unistr2_from_unistr(&inf->printername, &info->printername);
+ init_unistr2_from_unistr(&inf->sharename, &info->sharename);
+ init_unistr2_from_unistr(&inf->portname, &info->portname);
+ init_unistr2_from_unistr(&inf->drivername, &info->drivername);
+ init_unistr2_from_unistr(&inf->comment, &info->comment);
+ init_unistr2_from_unistr(&inf->location, &info->location);
+ init_unistr2_from_unistr(&inf->sepfile, &info->sepfile);
+ init_unistr2_from_unistr(&inf->printprocessor, &info->printprocessor);
+ init_unistr2_from_unistr(&inf->datatype, &info->datatype);
+ init_unistr2_from_unistr(&inf->parameters, &info->parameters);
+ init_unistr2_from_unistr(&inf->datatype, &info->datatype);
+ inf->secdesc = NULL;
+
+ *spool_info2 = inf;
+
+ return True;
+}
+
+/*******************************************************************
* read a structure.
* called from spoolss_q_open_printer_ex (srv_spoolss.c)
********************************************************************/
@@ -3741,12 +3848,6 @@ BOOL spoolss_io_q_addprinterex(char *desc, SPOOL_Q_ADDPRINTEREX *q_u, prs_struct
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.
- */
-
if(!prs_align(ps))
return False;
if(!prs_uint32("", ps, depth, &q_u->server_name_ptr))
@@ -3772,6 +3873,8 @@ BOOL spoolss_io_q_addprinterex(char *desc, SPOOL_Q_ADDPRINTEREX *q_u, prs_struct
* et le security descriptor.
*/
+ if(!prs_align(ps))
+ return False;
if(!prs_uint32("unk0", ps, depth, &q_u->unk0))
return False;
if(!prs_uint32("unk1", ps, depth, &q_u->unk1))
@@ -3789,10 +3892,10 @@ BOOL spoolss_io_q_addprinterex(char *desc, SPOOL_Q_ADDPRINTEREX *q_u, prs_struct
return True;
}
-
/*******************************************************************
********************************************************************/
-BOOL spoolss_io_r_addprinterex(char *desc, SPOOL_R_ADDPRINTEREX *r_u, prs_struct *ps, int depth)
+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++;
diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c
index 5a614a38b5..058c6db457 100644
--- a/source3/rpcclient/cmd_spoolss.c
+++ b/source3/rpcclient/cmd_spoolss.c
@@ -512,6 +512,7 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[]
fstring srv_port_name;
BOOL valid_port = False;
TALLOC_CTX *mem_ctx = NULL;
+ uint32 result;
fstrcpy(srv_name, "\\\\");
fstrcat(srv_name, info->dest_host);
@@ -589,21 +590,22 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[]
* Need to build the PRINTER_INFO_2 struct here.
* I think it would be better only to deal with a PRINTER_INFO_2
* and the abstract the creation of a SPOOL_PRINTER_INFO_LEVEL_2
- * from that rather than dealing with the struct passed dircetly
+ * from that rather than dealing with the struct passed directly
* on the wire. We don't need the extra *_ptr fields, etc...
* here anyways. --jerry
*/
- init_unistr( &print_info_2.servername, srv_name);
+ ZERO_STRUCTP(&print_info_2);
+ /* init_unistr( &print_info_2.servername, srv_name); */
init_unistr( &print_info_2.printername, printer_name);
- init_unistr( &print_info_2.sharename, printer_name);
+ /* init_unistr( &print_info_2.sharename, share_name); */
init_unistr( &print_info_2.portname, port_name);
init_unistr( &print_info_2.drivername, driver_name);
init_unistr( &print_info_2.comment, "Created by rpcclient");
- init_unistr( &print_info_2.location, "");
- init_unistr (&print_info_2.sepfile, "");
+ /* init_unistr( &print_info_2.location, "");
+ init_unistr( &print_info_2.sepfile, ""); */
init_unistr( &print_info_2.printprocessor, "winprint");
init_unistr( &print_info_2.datatype, "RAW");
- init_unistr( &print_info_2.parameters, "");
+ /* init_unistr( &print_info_2.parameters, ""); */
print_info_2.devmode = NULL;
print_info_2.secdesc = NULL;
print_info_2.attributes = 0;
@@ -618,7 +620,7 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[]
/* if successful, spoolss_addprinterex() should return True and hnd
should be a valid handle to an open printer */
- if (spoolss_addprinterex(&hnd, &print_info_2))
+ if ((result = spoolss_addprinterex(&hnd, srv_name, &print_info_2)) == NT_STATUS_NOPROBLEMO)
{
if (!spoolss_closeprinter( &hnd ))
{
@@ -627,7 +629,7 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[]
}
else
{
- report (out_hnd, "cmd_spoolss_addprinterex: spoolss_addprinterex FAILED!\n");
+ report (out_hnd, "cmd_spoolss_addprinterex: spoolss_addprinterex FAILED! [%d]\n", result);
}