Changes from APPLIANCE_HEAD:
[samba.git] / source3 / printing / nt_printing.c
index 895e3c6b0521d249abf1cb6310b4b3da306bd3de..2572a98bdea495315df7d9fa91ddaece0b6511a5 100644 (file)
@@ -35,6 +35,15 @@ static TDB_CONTEXT *tdb; /* used for driver files */
 
 #define DATABASE_VERSION 1
 
+/* Map generic permissions to printer object specific permissions */
+
+struct generic_mapping printer_generic_mapping = {
+       PRINTER_READ,
+       PRINTER_WRITE,
+       PRINTER_EXECUTE,
+       PRINTER_ALL_ACCESS
+};
+
 /* We need one default form to support our default printer. Msoft adds the
 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
 array index). Letter is always first, so (for the current code) additions
@@ -135,6 +144,7 @@ int write_ntforms(nt_forms_struct **list, int number)
                               (*list)[i].bottom);
                if (len > sizeof(buf)) break;
                slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[i].name);
+        dos_to_unix(key, True);            /* Convert key to unix-codepage */
                kbuf.dsize = strlen(key)+1;
                kbuf.dptr = key;
                dbuf.dsize = len;
@@ -163,17 +173,15 @@ BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
        update=False;
        
        unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
-       for (n=0; n<*count && update==False; n++)
-       {
-               if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
-               {
+       for (n=0; n<*count; n++) {
+               if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
                        DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
                        update=True;
+                       break;
                }
        }
 
-       if (update==False)
-       {
+       if (update==False) {
                if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
                        return False;
                unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
@@ -228,6 +236,7 @@ BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32
        }
 
        slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[n].name);
+       dos_to_unix(key, True);                /* Convert key to unix-codepage */
        kbuf.dsize = strlen(key)+1;
        kbuf.dptr = key;
        if (tdb_delete(tdb, kbuf) != 0) {
@@ -355,6 +364,7 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
        fstring           user_name;
        fstring           null_pw;
        files_struct      *fsp = NULL;
+       BOOL              bad_path;
        SMB_STRUCT_STAT   st;
        struct passwd *pass;
        connection_struct *conn;
@@ -406,6 +416,9 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
        /* Open the driver file (Portable Executable format) and determine the
         * deriver the cversion. */
        slprintf(driverpath, sizeof(driverpath), "%s/%s", architecture, driverpath_in);
+
+       unix_convert(driverpath,conn,NULL,&bad_path,&st);
+
        fsp = open_file_shared(conn, driverpath, &st,
                                                   SET_OPEN_MODE(DOS_OPEN_RDONLY),
                                                   (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
@@ -656,14 +669,12 @@ uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
                        driver=driver_abstract.info_3;
                        return clean_up_driver_struct_level_3(driver, user);
-                       break;
                }
                case 6:
                {
                        NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
                        driver=driver_abstract.info_6;
                        return clean_up_driver_struct_level_6(driver, user);
-                       break;
                }
                default:
                        return ERROR_INVALID_PARAMETER;
@@ -713,7 +724,6 @@ 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.
 ****************************************************************************/
-//static BOOL get_file_version(connection_struct *conn, int fd, char *fname,
 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
                                                         uint32 *minor)
 {
@@ -958,7 +968,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file,
        files_struct    *fsp = NULL;
        SMB_STRUCT_STAT st;
        SMB_STRUCT_STAT stat_buf;
-       
+       BOOL bad_path;
+
        ZERO_STRUCT(st);
        ZERO_STRUCT(stat_buf);
        new_create_time = (time_t)0;
@@ -967,6 +978,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file,
        /* Get file version info (if available) for previous file (if it exists) */
        pstrcpy(filepath, old_file);
 
+       unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
+
        fsp = open_file_shared(conn, filepath, &stat_buf,
                                                   SET_OPEN_MODE(DOS_OPEN_RDONLY),
                                                   (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
@@ -996,6 +1009,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file,
 
        /* Get file version info (if available) for new file */
        pstrcpy(filepath, new_file);
+       unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
+
        fsp = open_file_shared(conn, filepath, &stat_buf,
                                                   SET_OPEN_MODE(DOS_OPEN_RDONLY),
                                                   (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
@@ -1288,27 +1303,41 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
 
        slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
 
-       
-       fstrcpy(temp_name, driver->driverpath);
-       slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
+    /* .inf files do not always list a file for each of the four standard files. 
+     * Don't prepend a path to a null filename, or client claims:
+     *   "The server on which the printer resides does not have a suitable 
+     *   <printer driver name> printer driver installed. Click OK if you 
+     *   wish to install the driver on your local machine."
+     */
+       if (strlen(driver->driverpath)) {
+       fstrcpy(temp_name, driver->driverpath);
+       slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
+    }
 
-       fstrcpy(temp_name, driver->datafile);
-       slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
+       if (strlen(driver->datafile)) {
+       fstrcpy(temp_name, driver->datafile);
+       slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
+    }
 
-       fstrcpy(temp_name, driver->configfile);
-       slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
+       if (strlen(driver->configfile)) {
+       fstrcpy(temp_name, driver->configfile);
+       slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
+    }
 
-       fstrcpy(temp_name, driver->helpfile);
-       slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
+       if (strlen(driver->helpfile)) {
+       fstrcpy(temp_name, driver->helpfile);
+       slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
+    }
 
        if (driver->dependentfiles) {
                for (i=0; *driver->dependentfiles[i]; i++) {
-                       fstrcpy(temp_name, driver->dependentfiles[i]);
-                       slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
+            fstrcpy(temp_name, driver->dependentfiles[i]);
+            slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
                }
        }
 
        slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
+       dos_to_unix(key, True);                /* Convert key to unix-codepage */
 
        DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
 
@@ -1537,7 +1566,7 @@ debugging function, dump at level 6 the struct in the logs
 ****************************************************************************/
 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
 {
-       uint32 success;
+       uint32 result;
        NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
        int i;
        
@@ -1548,7 +1577,7 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32
                case 3:
                {
                        if (driver.info_3 == NULL)
-                               success=5;
+                               result=5;
                        else {
                                info3=driver.info_3;
                        
@@ -1567,17 +1596,17 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32
                                        DEBUGADD(106,("dependentfile:[%s]\n",
                                                      info3->dependentfiles[i]));
                                }
-                               success=0;
+                               result=0;
                        }
                        break;
                }
                default:
                        DEBUGADD(1,("Level not implemented\n"));
-                       success=1;
+                       result=1;
                        break;
        }
        
-       return (success);
+       return result;
 }
 
 /****************************************************************************
@@ -1672,8 +1701,8 @@ uint32 del_a_printer(char *sharename)
        pstring key;
        TDB_DATA kbuf;
 
-       slprintf(key, sizeof(key), "%s%s",
-                PRINTERS_PREFIX, sharename);
+       slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
+       dos_to_unix(key, True);                /* Convert key to unix-codepage */
 
        kbuf.dptr=key;
        kbuf.dsize=strlen(key)+1;
@@ -1755,8 +1784,8 @@ static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
        }
        
 
-       slprintf(key, sizeof(key), "%s%s",
-                PRINTERS_PREFIX, info->sharename);
+       slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, info->sharename);
+       dos_to_unix(key, True);                /* Convert key to unix-codepage */
 
        kbuf.dptr = key;
        kbuf.dsize = strlen(key)+1;
@@ -1779,17 +1808,17 @@ static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
 
 /****************************************************************************
 ****************************************************************************/
-BOOL add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
+void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
 {
        NT_PRINTER_PARAM *current;
        
        DEBUG(108,("add_a_specific_param\n"));  
 
-       param->next=NULL;
+       (*param)->next=NULL;
        
        if (info_2->specific == NULL)
        {
-               info_2->specific=param;
+               info_2->specific=*param;
        }
        else
        {
@@ -1797,9 +1826,10 @@ BOOL add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *par
                while (current->next != NULL) {
                        current=current->next;
                }               
-               current->next=param;
+               current->next=*param;
        }
-       return (True);
+
+       *param = NULL;
 }
 
 /****************************************************************************
@@ -1846,7 +1876,7 @@ BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_
 /****************************************************************************
  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
 ****************************************************************************/
-static void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
+void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
 {
        NT_PRINTER_PARAM *param = *param_ptr;
 
@@ -2062,6 +2092,11 @@ static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
                 */
                len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
                devmode.driverextra=(uint16)extra_len;
+               
+               /* check to catch an invalid TDB entry so we don't segfault */
+               if (devmode.driverextra == 0) {
+                       devmode.private = NULL;
+               }
        }
 
        *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
@@ -2177,6 +2212,7 @@ static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen
        ZERO_STRUCT(info);
 
        slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
+       dos_to_unix(key, True);                /* Convert key to unix-codepage */
 
        kbuf.dptr = key;
        kbuf.dsize = strlen(key)+1;
@@ -2238,7 +2274,7 @@ debugging function, dump at level 6 the struct in the logs
 ****************************************************************************/
 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
 {
-       uint32 success;
+       uint32 result;
        NT_PRINTER_INFO_LEVEL_2 *info2;
        
        DEBUG(106,("Dumping printer at level [%d]\n", level));
@@ -2248,7 +2284,7 @@ static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
                case 2:
                {
                        if (printer.info_2 == NULL)
-                               success=5;
+                               result=5;
                        else
                        {
                                info2=printer.info_2;
@@ -2276,17 +2312,17 @@ static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
                                DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
                                DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
                                DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
-                               success=0;
+                               result=0;
                        }
                        break;
                }
                default:
                        DEBUGADD(1,("Level not implemented\n"));
-                       success=1;
+                       result=1;
                        break;
        }
        
-       return (success);
+       return result;
 }
 
 /****************************************************************************
@@ -2321,7 +2357,7 @@ void get_printer_subst_params(int snum, fstring *printername, fstring *sharename
 
 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
 {
-       uint32 success;
+       uint32 result;
        
        dump_a_printer(printer, level); 
        
@@ -2330,15 +2366,15 @@ uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
                case 2:
                {
                        printer.info_2->c_setprinter++;
-                       success=update_a_printer_2(printer.info_2);
+                       result=update_a_printer_2(printer.info_2);
                        break;
                }
                default:
-                       success=1;
+                       result=1;
                        break;
        }
        
-       return (success);
+       return result;
 }
 
 /****************************************************************************
@@ -2348,7 +2384,7 @@ uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
 
 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
 {
-       uint32 success;
+       uint32 result;
        
        dump_a_printer(printer, level); 
        
@@ -2366,15 +2402,15 @@ uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
                        printer.info_2->changeid=time_nt.low;
 
                        printer.info_2->c_setprinter++;
-                       success=update_a_printer_2(printer.info_2);
+                       result=update_a_printer_2(printer.info_2);
                        break;
                }
                default:
-                       success=1;
+                       result=1;
                        break;
        }
        
-       return (success);
+       return result;
 }
 
 /****************************************************************************
@@ -2383,7 +2419,7 @@ uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
 
 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
 {
-       uint32 success;
+       uint32 result;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
        
        *pp_printer = NULL;
@@ -2399,8 +2435,8 @@ uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring s
                                return 1;
                        }
                        ZERO_STRUCTP(printer);
-                       success=get_a_printer_2(&printer->info_2, sharename);
-                       if (success == 0) {
+                       result=get_a_printer_2(&printer->info_2, sharename);
+                       if (result == 0) {
                                dump_a_printer(*printer, level);
                                *pp_printer = printer;
                        } else {
@@ -2409,13 +2445,13 @@ uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring s
                        break;
                }
                default:
-                       success=1;
+                       result=1;
                        break;
        }
        
-       DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)success));
+       DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
 
-       return (success);
+       return result;
 }
 
 /****************************************************************************
@@ -2424,7 +2460,7 @@ uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring s
 
 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
 {
-       uint32 success;
+       uint32 result;
        NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
 
        DEBUG(104,("freeing a printer at level [%d]\n", level));
@@ -2439,29 +2475,29 @@ uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
                        if (printer->info_2 != NULL)
                        {
                                free_nt_printer_info_level_2(&printer->info_2);
-                               success=0;
+                               result=0;
                        }
                        else
                        {
-                               success=4;
+                               result=4;
                        }
                        break;
                }
                default:
-                       success=1;
+                       result=1;
                        break;
        }
 
        safe_free(printer);
        *pp_printer = NULL;
-       return (success);
+       return result;
 }
 
 /****************************************************************************
 ****************************************************************************/
 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
 {
-       uint32 success;
+       uint32 result;
        DEBUG(104,("adding a printer at level [%d]\n", level));
        dump_a_printer_driver(driver, level);
        
@@ -2469,51 +2505,51 @@ uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
        {
                case 3:
                {
-                       success=add_a_printer_driver_3(driver.info_3);
+                       result=add_a_printer_driver_3(driver.info_3);
                        break;
                }
 
                case 6:
                {
-                       success=add_a_printer_driver_6(driver.info_6);
+                       result=add_a_printer_driver_6(driver.info_6);
                        break;
                }
                default:
-                       success=1;
+                       result=1;
                        break;
        }
        
-       return (success);
+       return result;
 }
 /****************************************************************************
 ****************************************************************************/
 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
                             fstring printername, fstring architecture, uint32 version)
 {
-       uint32 success;
+       uint32 result;
        
        switch (level)
        {
                case 3:
                {
-                       success=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
+                       result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
                        break;
                }
                default:
-                       success=1;
+                       result=1;
                        break;
        }
        
-       if (success == 0)
+       if (result == 0)
                dump_a_printer_driver(*driver, level);
-       return (success);
+       return result;
 }
 
 /****************************************************************************
 ****************************************************************************/
 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
 {
-       uint32 success;
+       uint32 result;
        
        switch (level)
        {
@@ -2526,11 +2562,11 @@ uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
                                safe_free(info3->dependentfiles);
                                ZERO_STRUCTP(info3);
                                safe_free(info3);
-                               success=0;
+                               result=0;
                        }
                        else
                        {
-                               success=4;
+                               result=4;
                        }
                        break;
                }
@@ -2544,19 +2580,19 @@ uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
                                safe_free(info6->previousnames);
                                ZERO_STRUCTP(info6);
                                safe_free(info6);
-                               success=0;
+                               result=0;
                        }
                        else
                        {
-                               success=4;
+                               result=4;
                        }
                        break;
                }
                default:
-                       success=1;
+                       result=1;
                        break;
        }
-       return (success);
+       return result;
 }
 
 /****************************************************************************
@@ -2685,7 +2721,6 @@ uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
                /* Make a deep copy of the security descriptor */
 
                psd = make_sec_desc(secdesc_ctr->sec->revision,
-                                   secdesc_ctr->sec->type,
                                    owner_sid, group_sid,
                                    sacl,
                                    dacl,
@@ -2744,7 +2779,7 @@ uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
 
 static SEC_DESC_BUF *construct_default_printer_sdb(void)
 {
-       SEC_ACE ace[2];
+       SEC_ACE ace[3];
        SEC_ACCESS sa;
        SEC_ACL *psa = NULL;
        SEC_DESC_BUF *sdb = NULL;
@@ -2759,7 +2794,6 @@ static SEC_DESC_BUF *construct_default_printer_sdb(void)
        init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
                     sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
 
-
        /* Make the security descriptor owned by the Administrators group
           on the PDC of the domain. */
 
@@ -2779,8 +2813,13 @@ static SEC_DESC_BUF *construct_default_printer_sdb(void)
                }
        }
 
-       init_sec_access(&sa, PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT);
+       init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
        init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
+                    sa, SEC_ACE_FLAG_OBJECT_INHERIT |
+                    SEC_ACE_FLAG_INHERIT_ONLY);
+
+       init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
+       init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
                     sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
 
        /* The ACL revision number in rpc_secdesc.h differs from the one
@@ -2790,10 +2829,8 @@ static SEC_DESC_BUF *construct_default_printer_sdb(void)
 
 #define NT4_ACL_REVISION 0x2
 
-       if ((psa = make_sec_acl(NT4_ACL_REVISION, 2, ace)) != NULL) {
+       if ((psa = make_sec_acl(NT4_ACL_REVISION, 3, ace)) != NULL) {
                psd = make_sec_desc(SEC_DESC_REVISION,
-                                   SEC_DESC_SELF_RELATIVE |
-                                   SEC_DESC_DACL_PRESENT,
                                    &owner_sid, NULL,
                                    NULL, psa, &sd_size);
                free_sec_acl(&psa);
@@ -2822,11 +2859,16 @@ BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
        prs_struct ps;
        TALLOC_CTX *mem_ctx = NULL;
        fstring key;
+       char *temp;
 
        mem_ctx = talloc_init();
        if (mem_ctx == NULL)
                return False;
 
+       if ((temp = strchr(printername + 2, '\\'))) {
+               printername = temp + 1;
+       }
+
        /* Fetch security descriptor from tdb */
 
        slprintf(key, sizeof(key), "SECDESC/%s", printername);
@@ -2866,7 +2908,6 @@ BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
                        sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
 
                        psd = make_sec_desc((*secdesc_ctr)->sec->revision,
-                                           (*secdesc_ctr)->sec->type,
                                            &owner_sid,
                                            (*secdesc_ctr)->sec->grp_sid,
                                            (*secdesc_ctr)->sec->sacl,
@@ -2888,6 +2929,24 @@ BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
                }
        }
 
+       if (DEBUGLEVEL >= 10) {
+               SEC_ACL *acl = (*secdesc_ctr)->sec->dacl;
+               int i;
+
+               DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
+                          printername, acl->num_aces));
+
+               for (i = 0; i < acl->num_aces; i++) {
+                       fstring sid_str;
+
+                       sid_to_string(sid_str, &acl->ace[i].sid);
+
+                       DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
+                                  acl->ace[i].type, acl->ace[i].flags, 
+                                  acl->ace[i].info.mask)); 
+               }
+       }
+
        prs_mem_free(&ps);
        talloc_destroy(mem_ctx);
        return True;
@@ -2929,6 +2988,20 @@ jfm: I should use this comment for the text file to explain
 
 */
 
+/* Convert generic access rights to printer object specific access rights.
+   It turns out that NT4 security descriptors use generic access rights and
+   NT5 the object specific ones. */
+
+void map_printer_permissions(SEC_DESC *sd)
+{
+       int i;
+
+       for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
+               se_map_generic(&sd->dacl->ace[i].info.mask,
+                              &printer_generic_mapping);
+       }
+}
+
 /****************************************************************************
  Check a user has permissions to perform the given operation.  We use some
  constants defined in include/rpc_spoolss.h that look relevant to check
@@ -2942,7 +3015,7 @@ jfm: I should use this comment for the text file to explain
    PRINTER_ACCESS_USE:
        print_job_start
 
-   JOB_ACCESS_ADMINISTER:
+   PRINTER_ACCESS_ADMINISTER (should really be JOB_ACCESS_ADMINISTER):
        print_job_delete, print_job_pause, print_job_resume,
        print_queue_purge
 
@@ -2950,10 +3023,9 @@ jfm: I should use this comment for the text file to explain
 BOOL print_access_check(struct current_user *user, int snum, int access_type)
 {
        SEC_DESC_BUF *secdesc = NULL;
-       uint32 access_granted, status, required_access = 0;
+       uint32 access_granted, status;
        BOOL result;
        char *pname;
-       int i;
        extern struct current_user current_user;
        
        /* If user is NULL then use the current_user structure */
@@ -2982,93 +3054,14 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type)
        /* Get printer security descriptor */
 
        nt_printing_getsec(pname, &secdesc);
+       
+       map_printer_permissions(secdesc->sec);
 
-       /* Check against NT4 ACE mask values.  From observation these
-          values are:
-
-              Access Type       ACE Mask    Constant
-              -------------------------------------
-              Full Control      0x10000000  PRINTER_ACE_FULL_CONTROL
-              Print             0xe0000000  PRINTER_ACE_PRINT
-              Manage Documents  0x00020000  PRINTER_ACE_MANAGE_DOCUMENTS
-       */
-
-       switch (access_type) {
-       case PRINTER_ACCESS_USE:
-               required_access = PRINTER_ACE_PRINT;
-               break;
-       case PRINTER_ACCESS_ADMINISTER:
-               required_access = PRINTER_ACE_MANAGE_DOCUMENTS |
-                       PRINTER_ACE_PRINT;
-               break;
-       case JOB_ACCESS_ADMINISTER:
-               required_access = PRINTER_ACE_MANAGE_DOCUMENTS;
-               break;
-       default:
-               DEBUG(0, ("invalid value passed to print_access_check()\n"));
-               result = False;
-               goto done;
-       }       
-
-       /* The ACE for Full Control in a printer security descriptor
-          doesn't seem to map properly to the access checking model.  For
-          it to work properly it should be the logical OR of all the other
-          values, i.e PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT.
-          This would cause the access check to simply fall out when we
-          check against any subset of these bits.  To get things to work,
-          change every ACE mask of PRINTER_ACE_FULL_CONTROL to
-          PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT before
-          performing the access check.  I'm sure there is a better way to
-          do this! */
-
-       if (secdesc && secdesc->sec && secdesc->sec->dacl &&
-           secdesc->sec->dacl->ace) {
-               for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
-                       if (secdesc->sec->dacl->ace[i].info.mask ==
-                           PRINTER_ACE_FULL_CONTROL) {
-                               secdesc->sec->dacl->ace[i].info.mask =
-                                       PRINTER_ACE_MANAGE_DOCUMENTS |
-                                       PRINTER_ACE_PRINT;
-                       }
-               }
-       }
-
-       if ((result = se_access_check(secdesc->sec, user, required_access,
-                                     &access_granted, &status))) {
-               goto done;
-       }
-
-       /* Check against NT5 ACE mask values.  From observation these
-          values are:
-
-              Access Type       ACE Mask    Constant
-              -------------------------------------
-              Full Control      0x000f000c  PRINTER_ACE_NT5_FULL_CONTROL
-              Print             0x00020008  PRINTER_ACE_NT5_PRINT
-              Manage Documents  0x00020000  PRINTER_ACE_NT5_MANAGE_DOCUMENTS
-
-          NT5 likes to rewrite the security descriptor and change the ACE
-          masks from NT4 format to NT5 format making them unreadable by
-          NT4 clients. */
-
-       switch (access_type) {
-       case PRINTER_ACCESS_USE:
-               required_access = PRINTER_ACE_NT5_PRINT;
-               break;
-       case PRINTER_ACCESS_ADMINISTER:
-               required_access = PRINTER_ACE_NT5_FULL_CONTROL;
-               break;
-       case JOB_ACCESS_ADMINISTER:
-               required_access = PRINTER_ACE_NT5_MANAGE_DOCUMENTS;
-               break;
-       }       
-
-       result = se_access_check(secdesc->sec, user, required_access,
+       result = se_access_check(secdesc->sec, user, access_type,
                                 &access_granted, &status);
 
        /* Check access */
        
- done:
        DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
        
        /* Free mallocated memory */