summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsource3/include/rpc_spoolss.h5
-rw-r--r--source3/printing/nt_printing.c144
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c207
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;
}