summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim McDonough <jmcd@samba.org>2002-12-04 17:28:51 +0000
committerJim McDonough <jmcd@samba.org>2002-12-04 17:28:51 +0000
commit2dd0e949d0a6bf7cf67250516c7fdc91cda24ea3 (patch)
tree8de09edcd0c56a31d7ab2141e5c4dca5acc02333
parent32750d6f7da4939ac9cf96e524384b22e99eb44d (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 bbd7c8071a095c4e410f92489050b677a0f0ace1)
-rwxr-xr-xsource3/include/rpc_spoolss.h5
-rw-r--r--source3/printing/nt_printing.c144
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c137
3 files changed, 267 insertions, 19 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 126427258f..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
@@ -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;
}