Automatic printer publishing when using APW or choosing 'list in the directory' in...
authorJim McDonough <jmcd@samba.org>
Wed, 4 Dec 2002 17:28:51 +0000 (17:28 +0000)
committerJim McDonough <jmcd@samba.org>
Wed, 4 Dec 2002 17:28:51 +0000 (17:28 +0000)
source/include/rpc_spoolss.h
source/printing/nt_printing.c
source/rpc_server/srv_spoolss_nt.c

index 067acd6c0f3efb071f18e86376a9ea6b08304c07..3a6d6eb9ec62aed4ca2898cece8c6760ebdd4100 100755 (executable)
@@ -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 */
index 1460bea084b2787337899b23d7305742793eced9..e37238c2ce9b05f24c5f90b0f7499e5a04f47331 100644 (file)
@@ -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
+}
+
 /****************************************************************************
  ***************************************************************************/
  
index 126427258f677f01f3eeeffceed762ffe929dcaa..fd223304498f1b82a7a357cf7d260443d502e725 100644 (file)
@@ -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;
@@ -4121,6 +4147,18 @@ static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)
        return True;
 }
 
+/********************************************************************
+ * 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;
 }      
@@ -5850,6 +5921,34 @@ done:
        return result;
 }
 
+/****************************************************************************
+****************************************************************************/
+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
+}
 /****************************************************************************
 ****************************************************************************/
 
@@ -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;
        }