diff options
-rwxr-xr-x | source3/include/rpc_spoolss.h | 5 | ||||
-rw-r--r-- | source3/printing/nt_printing.c | 144 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 207 |
3 files changed, 302 insertions, 54 deletions
diff --git a/source3/include/rpc_spoolss.h b/source3/include/rpc_spoolss.h index 067acd6c0f..3a6d6eb9ec 100755 --- a/source3/include/rpc_spoolss.h +++ b/source3/include/rpc_spoolss.h @@ -989,6 +989,11 @@ typedef struct printer_info_5 } PRINTER_INFO_5; +#define SPOOL_DS_PUBLISH 1 +#define SPOOL_DS_UPDATE 2 +#define SPOOL_DS_UNPUBLISH 3 +#define SPOOL_DS_REPUBLISH 4 + typedef struct printer_info_7 { UNISTR guid; /* text form of printer guid */ diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 1460bea084..e37238c2ce 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -2442,7 +2442,149 @@ uint32 get_printer_subkeys( NT_PRINTER_DATA *data, char* key, fstring **subkeys return num_subkeys; } - + +/**************************************************************************** + * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing. + * + * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified + * @return BOOL indicating success or failure + ***************************************************************************/ + +static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2) +{ + REGVAL_CTR *ctr = NULL; + smb_ucs2_t conv_str[1024]; + size_t str_size; + fstring longname; + char *uncname; + uint32 dword; + int i; + + for (i=0; i < info2->data.num_keys; i++) + if (!(StrCaseCmp(SPOOL_DSSPOOLER_KEY, + info2->data.keys[i].name))) + ctr = &info2->data.keys[i].values; + + if (!ctr) { + add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY); + ctr = &info2->data.keys[info2->data.num_keys - 1].values; + } + + regval_ctr_delvalue(ctr, SPOOL_REG_PRINTERNAME); + str_size = push_ucs2(NULL, conv_str, info2->sharename, + sizeof(conv_str), STR_TERMINATE | STR_NOALIGN); + regval_ctr_addvalue(ctr, SPOOL_REG_PRINTERNAME, REG_SZ, + (char *) conv_str, str_size); + + regval_ctr_delvalue(ctr, SPOOL_REG_SHORTSERVERNAME); + str_size = push_ucs2(NULL, conv_str, global_myname(), sizeof(conv_str), + STR_TERMINATE | STR_NOALIGN); + regval_ctr_addvalue(ctr, SPOOL_REG_SHORTSERVERNAME, REG_SZ, + (char *) conv_str, str_size); + + regval_ctr_delvalue(ctr, SPOOL_REG_SERVERNAME); + get_myfullname(longname); + str_size = push_ucs2(NULL, conv_str, longname, sizeof(conv_str), + STR_TERMINATE | STR_NOALIGN); + regval_ctr_addvalue(ctr, SPOOL_REG_SERVERNAME, REG_SZ, + (char *) conv_str, str_size); + + regval_ctr_delvalue(ctr, SPOOL_REG_VERSIONNUMBER); + dword = 4; + regval_ctr_addvalue(ctr, SPOOL_REG_VERSIONNUMBER, REG_DWORD, + (char *) &dword, sizeof(dword)); + + regval_ctr_delvalue(ctr, SPOOL_REG_UNCNAME); + asprintf(&uncname, "\\\\%s\\%s", longname, info2->sharename); + str_size = push_ucs2(NULL, conv_str, uncname, sizeof(conv_str), + STR_TERMINATE | STR_NOALIGN); + regval_ctr_addvalue(ctr, SPOOL_REG_UNCNAME, REG_SZ, (char *) conv_str, + str_size); + + return True; +} + +/**************************************************************************** + * Publish a printer in the directory + * + * @param snum describing printer service + * @return WERROR indicating status of publishing + ***************************************************************************/ + +WERROR nt_printer_publish(int snum, int action) +{ +#ifdef HAVE_ADS + NT_PRINTER_INFO_LEVEL *printer = NULL; + WERROR win_rc; + ADS_STATUS ads_rc; + TALLOC_CTX *ctx = talloc_init(); + ADS_MODLIST mods = ads_init_mods(ctx); + char *prt_dn = NULL, *srv_dn, **srv_cn; + void *res = NULL; + ADS_STRUCT *ads; + + win_rc = get_a_printer(&printer, 2, lp_servicename(snum)); + if (!W_ERROR_IS_OK(win_rc)) + return win_rc; + + if ((SPOOL_DS_PUBLISH == action) || (SPOOL_DS_UPDATE == action) || + (SPOOL_DS_REPUBLISH == action)) { + if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) + return WERR_NOMEM; + + win_rc = mod_a_printer(*printer, 2); + if (!W_ERROR_IS_OK(win_rc)) { + DEBUG(3, ("nt_printer_publish: err %d saving data\n", + W_ERROR_V(win_rc))); + free_a_printer(&printer, 2); + return win_rc; + } + + get_local_printer_publishing_data(ctx, &mods, + &printer->info_2->data); + ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, + lp_servicename(snum)); + } + + ads = ads_init(NULL, NULL, lp_ads_server()); + + ads_rc = ads_connect(ads); + + if ((SPOOL_DS_UNPUBLISH == action) || (SPOOL_DS_REPUBLISH == action)) { + ads_rc = ads_find_printer_on_server(ads, &res, + printer->info_2->sharename, global_myname()); + if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) { + prt_dn = ads_get_dn(ads, res); + ads_msgfree(ads, res); + ads_rc = ads_del_dn(ads, prt_dn); + ads_memfree(ads, prt_dn); + } + } + + if ((SPOOL_DS_PUBLISH == action) || (SPOOL_DS_UPDATE == action) || + (SPOOL_DS_REPUBLISH == action)) { + ads_find_machine_acct(ads, &res, global_myname()); + srv_dn = ldap_get_dn(ads->ld, res); + ads_msgfree(ads, res); + srv_cn = ldap_explode_dn(srv_dn, 1); + asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], + printer->info_2->sharename, srv_dn); + ads_memfree(ads, srv_dn); + + ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods); + if (LDAP_ALREADY_EXISTS == ads_rc.err.rc) + ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods); + safe_free(prt_dn); + ads_destroy(&ads); + } + + free_a_printer(&printer, 2); + return WERR_OK; +#else + return WERR_OK; +#endif +} + /**************************************************************************** ***************************************************************************/ diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 9e4b31813f..fd22330449 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -30,7 +30,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV -/* #define EMULATE_WIN2K_HACK 1 */ #ifndef MAX_OPEN_PRINTER_EXS #define MAX_OPEN_PRINTER_EXS 50 @@ -962,60 +961,60 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx ) { SPOOLSS_NOTIFY_MSG *msg = &messages[i]; - /* Are we monitoring this event? */ + /* Are we monitoring this event? */ - if (!is_monitoring_event(p, msg->type, msg->field)) - continue; + if (!is_monitoring_event(p, msg->type, msg->field)) + continue; - DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n", - msg->type, msg->field, p->dev.handlename)); + DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n", + msg->type, msg->field, p->dev.handlename)); - /* - * if the is a printer notification handle and not a job notification - * type, then set the id to 0. Other wise just use what was specified - * in the message. - * - * When registering change notification on a print server handle - * we always need to send back the id (snum) matching the printer - * for which the change took place. For change notify registered - * on a printer handle, this does not matter and the id should be 0. - * - * --jerry - */ + /* + * if the is a printer notification handle and not a job notification + * type, then set the id to 0. Other wise just use what was specified + * in the message. + * + * When registering change notification on a print server handle + * we always need to send back the id (snum) matching the printer + * for which the change took place. For change notify registered + * on a printer handle, this does not matter and the id should be 0. + * + * --jerry + */ - if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) ) - id = 0; - else - id = msg->id; + if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) ) + id = 0; + else + id = msg->id; - /* Convert unix jobid to smb jobid */ + /* Convert unix jobid to smb jobid */ if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) { - id = sysjob_to_jobid(msg->id); + id = sysjob_to_jobid(msg->id); - if (id == -1) { - DEBUG(3, ("no such unix jobid %d\n", msg->id)); - goto done; + if (id == -1) { + DEBUG(3, ("no such unix jobid %d\n", msg->id)); + goto done; + } } - } construct_info_data( &data[data_len], msg->type, msg->field, id ); - switch(msg->type) { - case PRINTER_NOTIFY_TYPE: + switch(msg->type) { + case PRINTER_NOTIFY_TYPE: if ( !printer_notify_table[msg->field].fn ) - goto done; - printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx); + goto done; + printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx); - break; + break; - case JOB_NOTIFY_TYPE: + case JOB_NOTIFY_TYPE: if ( !job_notify_table[msg->field].fn ) - goto done; - job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx); + goto done; + job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx); break; @@ -2153,7 +2152,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint DEBUG(8,("getprinterdata_printer_server:%s\n", value)); - if (!strcmp(value, "W3SvcInstalled")) { + if (!StrCaseCmp(value, "W3SvcInstalled")) { *type = 0x4; if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL) return WERR_NOMEM; @@ -2161,7 +2160,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint return WERR_OK; } - if (!strcmp(value, "BeepEnabled")) { + if (!StrCaseCmp(value, "BeepEnabled")) { *type = 0x4; if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL) return WERR_NOMEM; @@ -2170,7 +2169,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint return WERR_OK; } - if (!strcmp(value, "EventLog")) { + if (!StrCaseCmp(value, "EventLog")) { *type = 0x4; if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL) return WERR_NOMEM; @@ -2180,7 +2179,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint return WERR_OK; } - if (!strcmp(value, "NetPopup")) { + if (!StrCaseCmp(value, "NetPopup")) { *type = 0x4; if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL) return WERR_NOMEM; @@ -2189,20 +2188,20 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint return WERR_OK; } - if (!strcmp(value, "MajorVersion")) { + if (!StrCaseCmp(value, "MajorVersion")) { *type = 0x4; if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL) return WERR_NOMEM; -#ifndef EMULATE_WIN2K_HACK /* JERRY */ - SIVAL(*data, 0, 2); -#else +#ifdef HAVE_ADS SIVAL(*data, 0, 3); +#else + SIVAL(*data, 0, 2); #endif *needed = 0x4; return WERR_OK; } - if (!strcmp(value, "DefaultSpoolDirectory")) { + if (!StrCaseCmp(value, "DefaultSpoolDirectory")) { fstring string; fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); @@ -2220,7 +2219,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint return WERR_OK; } - if (!strcmp(value, "Architecture")) { + if (!StrCaseCmp(value, "Architecture")) { pstring string="Windows NT x86"; *type = 0x1; *needed = 2*(strlen(string)+1); @@ -2233,8 +2232,35 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint } return WERR_OK; } - - return WERR_INVALID_PARAM; + + if (!StrCaseCmp(value, "DsPresent")) { + *type = 0x4; + if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL) + return WERR_NOMEM; + SIVAL(*data, 0, 0x01); + *needed = 0x4; + return WERR_OK; + } + + if (!StrCaseCmp(value, "DNSMachineName")) { + pstring hostname; + + if (!get_myfullname(hostname)) + return WERR_BADFILE; + *type = 0x1; + *needed = 2*(strlen(hostname)+1); + if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL) + return WERR_NOMEM; + memset(*data, 0, (*needed > in_size) ? *needed:in_size); + for (i=0; i<strlen(hostname); i++) { + (*data)[2*i]=hostname[i]; + (*data)[2*i+1]='\0'; + } + return WERR_OK; + } + + + return WERR_BADFILE; } /******************************************************************** @@ -2315,7 +2341,7 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO done: if ( !W_ERROR_IS_OK(status) ) { - DEBUG(5, ("error: allocating %d\n", *out_size)); + DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size)); /* reply this param doesn't exist */ @@ -3789,12 +3815,12 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum) printer->global_counter = global_counter; printer->total_pages = 0; -#ifndef EMULATE_WIN2K_HACK /* JERRY */ - printer->major_version = 0x0004; /* NT 4 */ - printer->build_version = 0x0565; /* build 1381 */ -#else +#ifdef HAVE_ADS printer->major_version = 0x0005; /* NT 5 */ printer->build_version = 0x0893; /* build 2195 */ +#else + printer->major_version = 0x0004; /* NT 4 */ + printer->build_version = 0x0565; /* build 1381 */ #endif printer->unknown7 = 0x1; printer->unknown8 = 0x0; @@ -4122,6 +4148,18 @@ static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum) } /******************************************************************** + * construct_printer_info_5 + * fill a printer_info_5 struct + ********************************************************************/ + +static BOOL construct_printer_info_7(PRINTER_INFO_7 *printer) +{ + init_unistr(&printer->guid, ""); + printer->action = 0; + return True; +} + +/******************************************************************** Spoolss_enumprinters. ********************************************************************/ @@ -4677,6 +4715,37 @@ static WERROR getprinter_level_5(int snum, NEW_BUFFER *buffer, uint32 offered, u return WERR_OK; } +static WERROR getprinter_level_7(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +{ + PRINTER_INFO_7 *printer=NULL; + + if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL) + return WERR_NOMEM; + + if (!construct_printer_info_7(printer)) + return WERR_NOMEM; + + /* check the required size. */ + *needed += spoolss_size_printer_info_7(printer); + + if (!alloc_buffer_size(buffer, *needed)) { + free_printer_info_7(printer); + return WERR_INSUFFICIENT_BUFFER; + } + + /* fill the buffer with the structures */ + smb_io_printer_info_7("", buffer, printer, 0); + + /* clear memory */ + free_printer_info_7(printer); + + if (*needed > offered) { + return WERR_INSUFFICIENT_BUFFER; + } + + return WERR_OK; +} + /**************************************************************************** ****************************************************************************/ @@ -4712,6 +4781,8 @@ WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GET return getprinter_level_4(snum, buffer, offered, needed); case 5: return getprinter_level_5(snum, buffer, offered, needed); + case 7: + return getprinter_level_7(snum, buffer, offered, needed); } return WERR_UNKNOWN_LEVEL; } @@ -5852,6 +5923,34 @@ done: /**************************************************************************** ****************************************************************************/ +static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle, + const SPOOL_PRINTER_INFO_LEVEL *info) +{ +#ifdef HAVE_ADS + SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7; + int snum; + Printer_entry *Printer = find_printer_index_by_hnd(p, handle); + WERROR result; + + DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action)); + + result = WERR_OK; + + if (!Printer) + return WERR_BADFID; + + if (!get_printer_snum(p, handle, &snum)) + return WERR_BADFID; + + nt_printer_publish(snum, info7->action); + + return WERR_OK; +#else + return WERR_UNKNOWN_LEVEL; +#endif +} +/**************************************************************************** +****************************************************************************/ WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u) { @@ -5878,6 +5977,8 @@ WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SET case 3: return update_printer_sec(handle, level, info, p, secdesc_ctr); + case 7: + return publish_or_unpublish_printer(p, handle, info); default: return WERR_UNKNOWN_LEVEL; } |