From 3bf9a29f34ee4ade5180c5a0b0b9ff4aca7f0f08 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 8 Aug 2000 06:57:48 +0000 Subject: [PATCH] All changes related to rpcclient... - cleaned up some code - Fixed a few memory leaks of my own making - Add AddPrinterDriver(); I'm missing some of the semantics here as the call is done correctly, but I'm not getting all the information right in the DRIVER_INFO_3 struct I think. Will work on it tomorrow some more... --jerry --- source/include/rpc_misc.h | 1 - source/include/rpc_spoolss.h | 23 ++++ source/lib/msrpc-client.c | 4 +- source/rpc_client/cli_connect.c | 2 +- source/rpc_client/cli_spoolss.c | 52 +++++++++ source/rpc_parse/parse_spoolss.c | 177 ++++++++++++++++++++++++++++- source/rpcclient/cmd_spoolss.c | 239 ++++++++++++++++++++++++++++++++++++++- 7 files changed, 487 insertions(+), 11 deletions(-) diff --git a/source/include/rpc_misc.h b/source/include/rpc_misc.h index 6fb2d63ed48..d3e56634a93 100644 --- a/source/include/rpc_misc.h +++ b/source/include/rpc_misc.h @@ -306,7 +306,6 @@ typedef struct _cli_auth_fns cli_auth_fns; struct user_creds; struct cli_connection { - uint32 num_connections; char *srv_name; char *pipe_name; struct user_creds usr_creds; diff --git a/source/include/rpc_spoolss.h b/source/include/rpc_spoolss.h index bf854492aff..ead4c6cbc14 100755 --- a/source/include/rpc_spoolss.h +++ b/source/include/rpc_spoolss.h @@ -889,11 +889,34 @@ typedef struct driver_info_3 } DRIVER_INFO_3; +typedef struct driver_info_6 +{ + uint32 version; + UNISTR name; + UNISTR architecture; + UNISTR driverpath; + UNISTR datafile; + UNISTR configfile; + UNISTR helpfile; + uint16 *dependentfiles; + UNISTR monitorname; + UNISTR defaultdatatype; + uint16* previousdrivernames; + NTTIME driver_date; + uint32 driver_version; + UNISTR mfgname; + UNISTR oem_url; + UNISTR hardware_id; + UNISTR provider; +} +DRIVER_INFO_6; + typedef struct driver_info_info { DRIVER_INFO_1 *info1; DRIVER_INFO_2 *info2; DRIVER_INFO_3 *info3; + DRIVER_INFO_6 *info6; } PRINTER_DRIVER_CTR; diff --git a/source/lib/msrpc-client.c b/source/lib/msrpc-client.c index ee3ee0adcc7..867094a2c60 100644 --- a/source/lib/msrpc-client.c +++ b/source/lib/msrpc-client.c @@ -181,7 +181,7 @@ void msrpc_sockopt(struct msrpc_state *msrpc, char *options) static BOOL msrpc_authenticate(struct msrpc_state *msrpc, - const struct user_creds *usr) + struct user_creds *usr) { struct msrpc_state msrpc_redir; @@ -247,7 +247,7 @@ static BOOL msrpc_authenticate(struct msrpc_state *msrpc, static BOOL msrpc_init_redirect(struct msrpc_state *msrpc, const char* pipe_name, - const struct user_creds *usr) + struct user_creds *usr) { int sock; fstring path; diff --git a/source/rpc_client/cli_connect.c b/source/rpc_client/cli_connect.c index 16279488e82..6dcf92c57d5 100644 --- a/source/rpc_client/cli_connect.c +++ b/source/rpc_client/cli_connect.c @@ -108,7 +108,7 @@ void free_connections(void) } static struct cli_connection *cli_con_get(const char *srv_name, - const char *pipe_name, + char *pipe_name, cli_auth_fns * auth, void *auth_creds, BOOL reuse) { diff --git a/source/rpc_client/cli_spoolss.c b/source/rpc_client/cli_spoolss.c index 21e87b57999..1bfdf6a4685 100644 --- a/source/rpc_client/cli_spoolss.c +++ b/source/rpc_client/cli_spoolss.c @@ -613,6 +613,7 @@ BOOL spoolss_addprinterex(POLICY_HND *hnd, const char* srv_name, PRINTER_INFO_2 prs_mem_free(&rbuf); prs_mem_free(&buf ); + free_spoolss_q_addprinterex(&q_o); if (mem_ctx) talloc_destroy(mem_ctx); @@ -804,4 +805,55 @@ uint32 spoolss_getprinterdriverdir(fstring srv_name, fstring env_name, uint32 le return r_o.status; } +/****************************************************************************** + AddPrinterDriver() + *****************************************************************************/ +uint32 spoolss_addprinterdriver(const char *srv_name, uint32 level, PRINTER_DRIVER_CTR *info) +{ + prs_struct rbuf; + prs_struct buf; + SPOOL_Q_ADDPRINTERDRIVER q_o; + SPOOL_R_ADDPRINTERDRIVER r_o; + TALLOC_CTX *mem_ctx = NULL; + struct cli_connection *con = NULL; + + if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con)) + return False; + + if ((mem_ctx=talloc_init()) == NULL) + { + DEBUG(0,("msrpc_spoolss_enum_jobs: talloc_init failed!\n")); + return False; + } + prs_init(&buf , MAX_PDU_FRAG_LEN, 4, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, 4, mem_ctx, UNMARSHALL); + + /* make the ADDPRINTERDRIVER PDU */ + make_spoolss_q_addprinterdriver(&q_o, srv_name, level, info); + + /* turn the data into an io stream */ + if (spoolss_io_q_addprinterdriver("", &q_o, &buf, 0) && + rpc_con_pipe_req(con, SPOOLSS_ADDPRINTERDRIVER, &buf, &rbuf)) + { + ZERO_STRUCT(r_o); + + if(!spoolss_io_r_addprinterdriver("", &r_o, &rbuf, 0)) + { + /* report error code */ + DEBUG(5,("SPOOLSS_ADDPRINTEREX: %s\n", get_nt_error_msg(r_o.status))); + } + } + + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + free_spool_driver_info_3(q_o.info.info_3); + + if (mem_ctx) + talloc_destroy(mem_ctx); + + return r_o.status; + +} + diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c index 033b680e645..8ebdd55473d 100644 --- a/source/rpc_parse/parse_spoolss.c +++ b/source/rpc_parse/parse_spoolss.c @@ -772,6 +772,41 @@ BOOL make_spoolss_q_addprinterex(SPOOL_Q_ADDPRINTEREX *q_u, const char *srv_name return True; } + +/******************************************************************* + free dynamically allocated members + ********************************************************************/ +void free_spoolss_q_addprinterex(SPOOL_Q_ADDPRINTEREX *q_u) +{ + switch (q_u->info.level) + { + case 1: + if (q_u->info.info_1 != NULL) + { + free(q_u->info.info_1); + q_u->info.info_1 = NULL; + } + break; + case 2: + if (q_u->info.info_2 != NULL) + { + free(q_u->info.info_2); + q_u->info.info_2 = NULL; + } + break; + case 3: + if (q_u->info.info_3 != NULL) + { + free(q_u->info.info_3); + q_u->info.info_3 = NULL; + } + break; + } + + return; + +} + /******************************************************************* create a SPOOL_PRINTER_INFO_2 stuct from a PRINTER_INFO_2 struct *******************************************************************/ @@ -898,8 +933,7 @@ BOOL spoolss_io_r_open_printer_ex(char *desc, SPOOL_R_OPEN_PRINTER_EX *r_u, prs_ ********************************************************************/ BOOL make_spoolss_q_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u, const POLICY_HND *handle, - const UNISTR2 *valuename, - uint32 size) + UNISTR2 *valuename, uint32 size) { if (q_u == NULL) return False; @@ -4243,7 +4277,143 @@ void free_spool_printer_driver_info_level(SPOOL_PRINTER_DRIVER_INFO_LEVEL *il) } /******************************************************************* -********************************************************************/ + init a SPOOL_Q_ADDPRINTERDRIVER struct + ******************************************************************/ +BOOL make_spoolss_q_addprinterdriver(SPOOL_Q_ADDPRINTERDRIVER *q_u, + const char* srv_name, uint32 level, + PRINTER_DRIVER_CTR *info) +{ + DEBUG(5,("make_spoolss_q_addprinterdriver\n")); + + q_u->server_name_ptr = (srv_name!=NULL)?1:0; + init_unistr2(&q_u->server_name, srv_name, strlen(srv_name)+1); + + q_u->level = level; + + q_u->info.level = level; + q_u->info.ptr = (info!=NULL)?1:0; + switch (level) + { + /* info level 3 is supported by Windows 95/98, + WinNT and Win2k */ + case 3 : + q_u->info.info_3=(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3*) + malloc(sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3)); + make_spool_driver_info_3(q_u->info.info_3, info->info3); + break; + + /* info level 6 is supported by WinME and Win2k */ + case 6: + /* WRITEME!! will add later --jerry */ + break; + default: + DEBUG(0,("make_spoolss_q_addprinterdriver: Unknown \ +info level [%d]\n", level)); + break; + + } + + return True; +} + +BOOL make_spool_driver_info_3(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *spool_drv_info, + DRIVER_INFO_3 *info3) +{ + uint32 len = 0; + uint16 *ptr = info3->dependentfiles; + BOOL done = False; + BOOL null_char = False; + + spool_drv_info->cversion = info3->version; + spool_drv_info->name_ptr = (info3->name.buffer!=NULL)?1:0; + spool_drv_info->environment_ptr = (info3->architecture.buffer!=NULL)?1:0; + spool_drv_info->driverpath_ptr = (info3->driverpath.buffer!=NULL)?1:0; + spool_drv_info->datafile_ptr = (info3->datafile.buffer!=NULL)?1:0; + spool_drv_info->configfile_ptr = (info3->configfile.buffer!=NULL)?1:0; + spool_drv_info->helpfile_ptr = (info3->helpfile.buffer!=NULL)?1:0; + spool_drv_info->monitorname_ptr = (info3->monitorname.buffer!=NULL)?1:0; + spool_drv_info->defaultdatatype_ptr = (info3->defaultdatatype.buffer!=NULL)?1:0; + + init_unistr2_from_unistr(&spool_drv_info->name, &info3->name); + init_unistr2_from_unistr(&spool_drv_info->environment, &info3->architecture); + init_unistr2_from_unistr(&spool_drv_info->driverpath, &info3->driverpath); + init_unistr2_from_unistr(&spool_drv_info->datafile, &info3->datafile); + init_unistr2_from_unistr(&spool_drv_info->configfile, &info3->configfile); + init_unistr2_from_unistr(&spool_drv_info->helpfile, &info3->helpfile); + init_unistr2_from_unistr(&spool_drv_info->monitorname, &info3->monitorname); + init_unistr2_from_unistr(&spool_drv_info->defaultdatatype, &info3->defaultdatatype); + + while (!done) + { + switch (*ptr) + { + case 0: + /* the null_char BOOL is used to help locate + two '\0's back to back */ + if (null_char) + done = True; + else + null_char = True; + break; + + default: + null_char = False; + ;; + break; + } + len++; + ptr++; + } + spool_drv_info->dependentfiles_ptr = (info3->dependentfiles!=NULL)?1:0; + spool_drv_info->dependentfilessize = len; + make_spool_buffer5(&spool_drv_info->dependentfiles, len, info3->dependentfiles); + + return True; +} + +void free_spool_driver_info_3 (SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *info) +{ + if (info != NULL) + { + free_spool_buffer5(&info->dependentfiles); + } + + return; +} + +/******************************************************************* + make a BUFFER5 struct from a uint16* + ******************************************************************/ +BOOL make_spool_buffer5(BUFFER5 *buf5, uint32 len, uint16 *src) +{ + + buf5->buf_len = len; + if((buf5->buffer=(uint16*)malloc(sizeof(uint16)*len)) == NULL) + { + DEBUG(0,("make_spool_buffer5: Unable to malloc memory for buffer!\n")); + return False; + } + + memcpy(buf5->buffer, src, sizeof(uint16)*len); + + return True; +} + + +void free_spool_buffer5(BUFFER5 *buf) +{ + if (buf != NULL) + { + free(buf->buffer); + buf->buffer = NULL; + } + + return; +} + +/******************************************************************* + fill in the prs_struct for a ADDPRINTERDRIVER request PDU + ********************************************************************/ BOOL spoolss_io_q_addprinterdriver(char *desc, SPOOL_Q_ADDPRINTERDRIVER *q_u, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "spoolss_io_q_addprinterdriver"); @@ -4855,6 +5025,7 @@ BOOL spoolss_io_r_setprinterdata(char *desc, SPOOL_R_SETPRINTERDATA *r_u, prs_st return True; } + /******************************************************************* ********************************************************************/ BOOL convert_specific_param(NT_PRINTER_PARAM **param, const UNISTR2 *value, diff --git a/source/rpcclient/cmd_spoolss.c b/source/rpcclient/cmd_spoolss.c index f79a7042d2e..35e09c76e13 100644 --- a/source/rpcclient/cmd_spoolss.c +++ b/source/rpcclient/cmd_spoolss.c @@ -37,6 +37,49 @@ extern FILE* out_hnd; extern struct user_creds *usr_creds; /**************************************************************************** +function to do the mapping between the long architecture name and +the short one. +****************************************************************************/ +static BOOL get_short_archi(char *short_archi, char *long_archi) +{ + struct table { + char *long_archi; + char *short_archi; + }; + + struct table archi_table[]= + { + {"Windows 4.0", "WIN40" }, + {"Windows NT x86", "W32X86" }, + {"Windows NT R4000", "W32MIPS" }, + {"Windows NT Alpha_AXP", "W32ALPHA" }, + {"Windows NT PowerPC", "W32PPC" }, + {NULL, "" } + }; + + int i=-1; + + DEBUG(107,("Getting architecture dependant directory\n")); + do { + i++; + } while ( (archi_table[i].long_archi!=NULL ) && + StrCaseCmp(long_archi, archi_table[i].long_archi) ); + + if (archi_table[i].long_archi==NULL) { + DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi)); + return FALSE; + } + + StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi)); + + DEBUGADD(108,("index: [%d]\n", i)); + DEBUGADD(108,("long architecture: [%s]\n", long_archi)); + DEBUGADD(108,("short architecture: [%s]\n", short_archi)); + + return TRUE; +} + +/**************************************************************************** nt spoolss query ****************************************************************************/ uint32 cmd_spoolss_enum_printers(struct client_info *info, int argc, char *argv[]) @@ -520,7 +563,7 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[] /* check (and copy) the command line arguments */ if (argc < 3) { report(out_hnd, "spooladdprinterex \n"); - return NT_STATUS_NOPROBLEMO; + return NT_STATUS_INVALID_PARAMETER; } else { @@ -559,7 +602,6 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[] report (out_hnd, "cmd_spoolss_addprinterex: FAILED to enumerate ports\n"); return NT_STATUS_NOPROBLEMO; } - } /* @@ -584,7 +626,6 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[] return NT_STATUS_NOPROBLEMO; } - /* * Need to build the PRINTER_INFO_2 struct here. * I think it would be better only to deal with a PRINTER_INFO_2 @@ -641,6 +682,196 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[] ********************************************************************************/ uint32 cmd_spoolss_addprinterdriver(struct client_info *info, int argc, char *argv[]) { + PRINTER_DRIVER_CTR driver_info; + DRIVER_INFO_3 info3; + fstring arch; + fstring srv_name; + uint32 result = NT_STATUS_NO_PROBLEMO; + + /* parse the command arguements */ + if (argc < 2) + { + report (out_hnd, "spooladdprinterdriver \\\n"); + report (out_hnd, "\t:::\\\n"); + report (out_hnd, "\t:::\\\n"); + report (out_hnd, "\t:\n"); - return NT_STATUS_NOPROBLEMO; + return NT_STATUS_INVALID_PARAMETER; + } + else + { + ZERO_STRUCT(info3); + + /* get the enviorment for the driver */ + if (!get_short_archi(arch, argv[1])) + { + report (out_hnd, "Unknown architechture [%s]\n", argv[1]); + return NT_STATUS_INVALID_PARAMETER; + + } + else + { + set_drv_info_3_env(&info3, arch); + } + + /* fill in the other struct members */ + if (!init_drv_info_3_members(&info3, argv[2])) + { + report (out_hnd, "Invalid parameter list.\n"); + return NT_STATUS_INVALID_PARAMETER; + } + } + + /* get the server name */ + fstrcpy(srv_name, "\\\\"); + fstrcat(srv_name, info->dest_host); + strupper(srv_name); + + /* call AddPrinterDriver() woth an info level 3 */ + driver_info.info3 = &info3; + if ((result=spoolss_addprinterdriver(srv_name, 3, &driver_info)) != NT_STATUS_NO_PROBLEMO) + { + report( out_hnd, "spoolss_addprinterdriver: Add Printer failed [%d]\n", + result); + } + + free_drv_info_3(&info3); + + return result; } + +/******************************************************************************* + set the version and environment fields of a DRIVER_INFO_3 struct + ******************************************************************************/ +void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch) +{ + if (strcmp(arch, "WIN40") == 0) + { + info->version = 0; + init_unistr(&info->architecture, "Windows 4.0"); + } + else if (strcmp(arch, "W32X86") == 0) + { + info->version = 2; + init_unistr(&info->architecture, "Windows NT x86"); + } + else if (strcmp(arch, "W32MIPS") == 0) + { + info->version = 2; + init_unistr(&info->architecture, "Windows NT R4000"); + } + else if (strcmp(arch, "W32ALPHA") == 0) + { + info->version = 2; + init_unistr(&info->architecture, "Windows NT Alpha_AXP"); + } + else if (strcmp(arch, "W32PPC") == 0) + { + info->version = 2; + init_unistr(&info->architecture, "Windows NT PowerPC"); + } + else + { + DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch)); + } + + return; +} + +/******************************************************************************** + fill in the members of a DRIVER_INFO_3 struct using a character + string in the form of + :::\ + :::\ + : + *******************************************************************************/ +BOOL init_drv_info_3_members (DRIVER_INFO_3 *info, char *args) +{ + char *str, *str2; + uint32 len, i; + + /* */ + if ((str = strtok(args, ":")) == NULL) + return False; + else + init_unistr(&info->name, str); + + /* */ + if ((str = strtok(NULL, ":")) == NULL) + return False; + else + init_unistr(&info->driverpath, str); + + /* */ + if ((str = strtok(NULL, ":")) == NULL) + return False; + else + init_unistr(&info->datafile, str); + + /* */ + if ((str = strtok(NULL, ":")) == NULL) + return False; + else + init_unistr(&info->configfile, str); + + /* */ + if ((str = strtok(NULL, ":")) == NULL) + return False; + else + init_unistr(&info->helpfile, str); + + /* */ + if ((str = strtok(NULL, ":")) == NULL) + return False; + else + init_unistr(&info->monitorname, str); + + /* */ + if ((str = strtok(NULL, ":")) == NULL) + return False; + else + init_unistr(&info->defaultdatatype, str); + + /* */ + str = strtok(NULL, ":"); /* get the list of dependent files */ + str2 = str; /* save the beginning of the string */ + str = strtok(str, ","); /* begin to strip out each filename */ + len = 0; + while (str != NULL) + { + /* keep a cumlative count of the str lengths */ + len += strlen(str)+1; + str = strtok(NULL, ","); + } + + /* allocate the space; add one extra slot for a terminating NULL. + Each filename is NULL terminated and the end contains a double + NULL */ + if ((info->dependentfiles=(uint16*)malloc((len+1)*sizeof(uint16))) == NULL) + { + DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n")); + return False; + } + for (i=0; idependentfiles[i] = (uint16)str2[i]; + info->dependentfiles[i] = info->dependentfiles[i] << 8; + } + info->dependentfiles[len+1] = '\0'; + + return True; +} + +/***************************************************************************** + free any dynamically allocated members + ****************************************************************************/ +void free_drv_info_3 (DRIVER_INFO_3 *info) +{ + if (info->dependentfiles != NULL) + { + free(info->dependentfiles); + info->dependentfiles = NULL; + } + + return; +} -- 2.11.4.GIT