Round and round we go....
[ira/wip.git] / source3 / printing / nt_printing.c
index 028f449479bf43436973d84bf2527fc1925bd21b..0f02266c0fe8acaae5bb1d4f4d53621c5c2d8ffc 100644 (file)
@@ -22,7 +22,6 @@
 
 #include "includes.h"
 
-extern pstring global_myname;
 extern DOM_SID global_sid_World;
 
 static TDB_CONTEXT *tdb_forms; /* used for forms files */
@@ -37,8 +36,9 @@ static TDB_CONTEXT *tdb_printers; /* used for printers files */
  
 #define NTDRIVERS_DATABASE_VERSION_1 1
 #define NTDRIVERS_DATABASE_VERSION_2 2
+#define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
  
-#define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_2
+#define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
 
 /* Map generic permissions to printer object specific permissions */
 
@@ -174,49 +174,49 @@ static nt_forms_struct default_forms[] = {
        {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
 };
 
-static BOOL upgrade_to_version_2(void)
+static BOOL upgrade_to_version_3(void)
 {
        TDB_DATA kbuf, newkey, dbuf;
  
-       DEBUG(0,("upgrade_to_version_2: upgrading print tdb's to version 2\n"));
+       DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
  
        for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
-                       newkey = tdb_nextkey(tdb_drivers, kbuf), SAFE_FREE(kbuf.dptr), kbuf=newkey) {
+                       newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
 
                dbuf = tdb_fetch(tdb_drivers, kbuf);
 
                if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
-                       DEBUG(0,("upgrade_to_version_2:moving form\n"));
+                       DEBUG(0,("upgrade_to_version_3:moving form\n"));
                        if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
-                               DEBUG(0,("upgrade_to_version_2: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
+                               DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
                                return False;
                        }
                        if (tdb_delete(tdb_drivers, kbuf) != 0) {
-                               DEBUG(0,("upgrade_to_version_2: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
+                               DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
                                return False;
                        }
                }
  
                if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
-                       DEBUG(0,("upgrade_to_version_2:moving printer\n"));
+                       DEBUG(0,("upgrade_to_version_3:moving printer\n"));
                        if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
-                               DEBUG(0,("upgrade_to_version_2: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
+                               DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
                                return False;
                        }
                        if (tdb_delete(tdb_drivers, kbuf) != 0) {
-                               DEBUG(0,("upgrade_to_version_2: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
+                               DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
                                return False;
                        }
                }
  
                if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
-                       DEBUG(0,("upgrade_to_version_2:moving secdesc\n"));
+                       DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
                        if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
-                               DEBUG(0,("upgrade_to_version_2: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
+                               DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
                                return False;
                        }
                        if (tdb_delete(tdb_drivers, kbuf) != 0) {
-                               DEBUG(0,("upgrade_to_version_2: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
+                               DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
                                return False;
                        }
                }
@@ -228,8 +228,9 @@ static BOOL upgrade_to_version_2(void)
 }
 
 /****************************************************************************
-open the NT printing tdb
+ Open the NT printing tdb.
 ****************************************************************************/
+
 BOOL nt_printing_init(void)
 {
        static pid_t local_pid;
@@ -263,15 +264,28 @@ BOOL nt_printing_init(void)
  
        /* handle a Samba upgrade */
        tdb_lock_bystring(tdb_drivers, vstring);
-       if (tdb_fetch_int(tdb_drivers, vstring) != NTDRIVERS_DATABASE_VERSION) {
-               if (tdb_fetch_int(tdb_drivers, vstring) == NTDRIVERS_DATABASE_VERSION_1) {
-                       if (!upgrade_to_version_2())
-                               return False;
-               } else
-                       tdb_traverse(tdb_drivers, (tdb_traverse_func)tdb_delete, NULL);
+       {
+               int32 vers_id;
+
+               /* Cope with byte-reversed older versions of the db. */
+               vers_id = tdb_fetch_int32(tdb_drivers, vstring);
+               if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
+                       /* Written on a bigendian machine with old fetch_int code. Save as le. */
+                       /* The only upgrade between V2 and V3 is to save the version in little-endian. */
+                       tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
+                       vers_id = NTDRIVERS_DATABASE_VERSION;
+               }
+
+               if (vers_id != NTDRIVERS_DATABASE_VERSION) {
  
-               tdb_store_int(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
+                       if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
+                               if (!upgrade_to_version_3())
+                                       return False;
+                       } else
+                               tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
+
+                       tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
+               }
        }
        tdb_unlock_bystring(tdb_drivers, vstring);
 
@@ -323,7 +337,7 @@ int get_ntforms(nt_forms_struct **list)
 
        for (kbuf = tdb_firstkey(tdb_forms);
             kbuf.dptr;
-            newkey = tdb_nextkey(tdb_forms, kbuf), SAFE_FREE(kbuf.dptr), kbuf=newkey) {
+            newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
                if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
                
                dbuf = tdb_fetch(tdb_forms, kbuf);
@@ -510,7 +524,7 @@ int get_ntdrivers(fstring **list, char *architecture, uint32 version)
 
        for (kbuf = tdb_firstkey(tdb_drivers);
             kbuf.dptr;
-            newkey = tdb_nextkey(tdb_drivers, kbuf), SAFE_FREE(kbuf.dptr), kbuf=newkey) {
+            newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
                if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
                
                if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
@@ -570,13 +584,14 @@ BOOL get_short_archi(char *short_archi, char *long_archi)
 }
 
 /****************************************************************************
-Version information in Microsoft files is held in a VS_VERSION_INFO structure.
-There are two case to be covered here: PE (Portable Executable) and NE (New
-Executable) files. Both files support the same INFO structure, but PE files
-store the signature in unicode, and NE files store it as !unicode.
+ Version information in Microsoft files is held in a VS_VERSION_INFO structure.
+ There are two case to be covered here: PE (Portable Executable) and NE (New
+ Executable) files. Both files support the same INFO structure, but PE files
+ store the signature in unicode, and NE files store it as !unicode.
+ returns -1 on error, 1 on version info found, and 0 on no version info found.
 ****************************************************************************/
-static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
-                                                        uint32 *minor)
+
+static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
 {
        int     i;
        char    *buf;
@@ -690,7 +705,7 @@ static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
                                                                          (*major>>16)&0xffff, *major&0xffff,
                                                                          (*minor>>16)&0xffff, *minor&0xffff));
                                                        SAFE_FREE(buf);
-                                                       return True;
+                                                       return 1;
                                                }
                                        }
                                }
@@ -700,7 +715,7 @@ static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
                /* Version info not found, fall back to origin date/time */
                DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
                SAFE_FREE(buf);
-               return False;
+               return 0;
 
        } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
                if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
@@ -767,7 +782,7 @@ static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
                                                          (*major>>16)&0xffff, *major&0xffff,
                                                          (*minor>>16)&0xffff, *minor&0xffff));
                                        SAFE_FREE(buf);
-                                       return True;
+                                       return 1;
                                }
                        }
                }
@@ -775,7 +790,7 @@ static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
                /* Version info not found, fall back to origin date/time */
                DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
                SAFE_FREE(buf);
-               return False;
+               return 0;
 
        } else
                /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
@@ -784,7 +799,7 @@ static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
 
        no_version_info:
                SAFE_FREE(buf);
-               return False;
+               return 0;
 
        error_exit:
                SAFE_FREE(buf);
@@ -935,9 +950,12 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
 
        ZERO_STRUCT(st);
 
+       *perr = WERR_INVALID_PARAM;
+
        /* If architecture is Windows 95/98/ME, the version is always 0. */
        if (strcmp(architecture, "WIN40") == 0) {
                DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
+               *perr = WERR_OK;
                return 0;
        }
 
@@ -1018,6 +1036,7 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
        close_file(fsp, True);
        close_cnum(conn, user->vuid);
        unbecome_user();
+       *perr = WERR_OK;
        return cversion;
 
   error_exit:
@@ -2091,7 +2110,7 @@ NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
        nt_devmode->paperlength      = 0;
        nt_devmode->paperwidth       = 0;
        nt_devmode->scale            = 0x64;
-       nt_devmode->copies           = 01;
+       nt_devmode->copies           = 1;
        nt_devmode->defaultsource    = BIN_FORMSOURCE;
        nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
        nt_devmode->color            = COLOR_MONOCHROME;
@@ -2376,7 +2395,6 @@ get a default printer info 2 struct
 ****************************************************************************/
 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
 {
-       extern pstring global_myname;
        int snum;
        NT_PRINTER_INFO_LEVEL_2 info;
 
@@ -2384,9 +2402,9 @@ static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstrin
 
        snum = lp_servicenumber(sharename);
 
-       slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
+       slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
        slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s", 
-                global_myname, sharename);
+                get_called_name(), sharename);
        fstrcpy(info.sharename, sharename);
        fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
        fstrcpy(info.drivername, lp_printerdriver(snum));
@@ -2464,8 +2482,7 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen
 {
        pstring key;
        NT_PRINTER_INFO_LEVEL_2 info;
-       int             len = 0,
-                       devmode_length = 0;
+       int             len = 0;
        TDB_DATA kbuf, dbuf;
        fstring printername;
                
@@ -2508,8 +2525,8 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen
        info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
 
        /* Restore the stripped strings. */
-       slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
-       slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
+       slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
+       slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
                        info.printername);
        fstrcpy(info.printername, printername);
 
@@ -2573,7 +2590,7 @@ static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
                                DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
                                DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
                                DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
-                               DEBUGADD(106,("status:[%s]\n", werror_str(info2->status)));
+                               DEBUGADD(106,("status:[%d]\n", info2->status));
                                DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
                                DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
                                DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
@@ -2624,6 +2641,23 @@ void get_printer_subst_params(int snum, fstring *printername, fstring *sharename
        free_a_printer(&printer, 2);
 }
 
+/****************************************************************************
+ Update the changeid time.
+ This is SO NASTY as some drivers need this to change, others need it
+ static. This value will change every second, and I must hope that this
+ is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
+ UTAH ! JRA.
+****************************************************************************/
+
+static uint32 rev_changeid(void)
+{
+       struct timeval tv;
+
+       get_process_uptime(&tv);
+       /* This value is in ms * 100 */
+       return (((tv.tv_sec * 1000000) + tv.tv_usec)/100);
+}
+
 /*
  * The function below are the high level ones.
  * only those ones must be called from the spoolss code.
@@ -2644,7 +2678,37 @@ WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
        {
                case 2:
                {
-                       printer.info_2->c_setprinter++;
+                       /*
+                        * Update the changestamp.  Emperical tests show that the
+                        * ChangeID is always updated,but c_setprinter is only 
+                        * incremented on a SetPrinter() call.
+                        */
+
+                       /* ChangeID **must** be increasing over the lifetime
+                          of client's spoolss service in order for the
+                          client's cache to show updates */
+
+                       printer.info_2->changeid = rev_changeid();
+
+                       /*
+                        * Because one day someone will ask:
+                        * NT->NT       An admin connection to a remote
+                        *              printer show changes imeediately in
+                        *              the properities dialog
+                        *      
+                        *              A non-admin connection will only show the
+                        *              changes after viewing the properites page
+                        *              2 times.  Seems to be related to a
+                        *              race condition in the client between the spooler
+                        *              updating the local cache and the Explorer.exe GUI
+                        *              actually displaying the properties.
+                        *
+                        *              This is fixed in Win2k.  admin/non-admin
+                        *              connections both display changes immediately.
+                        *
+                        * 14/12/01     --jerry
+                        */
+
                        result=update_a_printer_2(printer.info_2);
                        break;
                }
@@ -2672,17 +2736,11 @@ WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
                case 2:
                {
                        /*
-                        * Update the changestamp.
-                        * Note we must *not* do this in mod_a_printer().
+                        * Update the changestamp.  See comments in mod_a_printer()
+                        * --jerry
                         */
-                       NTTIME time_nt;
-                       time_t time_unix = time(NULL);
-                       unix_to_nt_time(&time_nt, time_unix);
-                       if (printer.info_2->changeid==time_nt.low)
-                               printer.info_2->changeid++;
-                       else
-                               printer.info_2->changeid=time_nt.low;
 
+                       printer.info_2->changeid = rev_changeid();
                        printer.info_2->c_setprinter++;
 
                        result=update_a_printer_2(printer.info_2);
@@ -3203,7 +3261,7 @@ BOOL printer_driver_in_use (char *arch, char *driver)
        
        /* loop through the printers.tdb and check for the drivername */
        for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
-            newkey = tdb_nextkey(tdb_printers, kbuf), SAFE_FREE(kbuf.dptr), kbuf=newkey) 
+            newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) 
        {
 
                dbuf = tdb_fetch(tdb_printers, kbuf);
@@ -3524,7 +3582,7 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
        }
 
        if (!psd) {
-               DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
+               DEBUG(0,("construct_default_printer_sdb: Failed to make SEC_DESC.\n"));
                return NULL;
        }
 
@@ -3563,6 +3621,16 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secde
                        return False;
                }
 
+                /* Save default security descriptor for later */
+
+                prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
+                         sizeof(SEC_DESC_BUF), ctx, MARSHALL);
+
+                if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1))
+                        tdb_prs_store(tdb_printers, key, &ps);
+
+                prs_mem_free(&ps);
+
                return True;
        }
 
@@ -3615,7 +3683,7 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secde
                for (i = 0; i < the_acl->num_aces; i++) {
                        fstring sid_str;
 
-                       sid_to_string(sid_str, &the_acl->ace[i].sid);
+                       sid_to_string(sid_str, &the_acl->ace[i].trustee);
 
                        DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
                                   the_acl->ace[i].type, the_acl->ace[i].flags,