summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim McDonough <jmcd@samba.org>2002-12-04 17:40:50 +0000
committerJim McDonough <jmcd@samba.org>2002-12-04 17:40:50 +0000
commitdae62a3d2ed67998a77ec0ffe4f1540bdcc4fe40 (patch)
tree7dd9129dac416025c2dd62c629939e65c7f19a26
parentc37f794f2218c1d7c574aff8dd8771af6b459ac3 (diff)
Automatic printer publishing when using APW or choosing 'list in the directory' in printer settings. Currently very little is published, and you cannot unpublish because of a bug in win2k clients.
(This used to be commit ca6360e8db30fc9be3fe3718c8b49c92dba5ecac)
-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;
}