return ret;
}
+/***********************************************************************
+ unpack a pjob from a tdb buffer
+***********************************************************************/
+
+int unpack_pjob( char* buf, int buflen, struct printjob *pjob )
+{
+ int len = 0;
+
+ if ( !buf || !pjob )
+ return -1;
+
+ len += tdb_unpack(buf+len, buflen-len, "dddddddddffff",
+ &pjob->pid,
+ &pjob->sysjob,
+ &pjob->fd,
+ &pjob->starttime,
+ &pjob->status,
+ &pjob->size,
+ &pjob->page_count,
+ &pjob->spooled,
+ &pjob->smbjob,
+ pjob->filename,
+ pjob->jobname,
+ pjob->user,
+ pjob->queuename);
+
+
+ len += unpack_devicemode(&pjob->nt_devmode, buf+len, buflen-len);
+
+ return len;
+
+}
+
/****************************************************************************
Useful function to find a print job in the database.
****************************************************************************/
static struct printjob *print_job_find(int snum, uint32 jobid)
{
- static struct printjob pjob;
- TDB_DATA ret;
- struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
+ static struct printjob pjob;
+ TDB_DATA ret;
+ struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
+
if (!pdb)
return NULL;
ret = tdb_fetch(pdb->tdb, print_key(jobid));
release_print_db(pdb);
- if (!ret.dptr || ret.dsize != sizeof(pjob))
+ if (!ret.dptr)
return NULL;
-
- memcpy(&pjob, ret.dptr, sizeof(pjob));
- SAFE_FREE(ret.dptr);
+
+ if ( pjob.nt_devmode )
+ free_nt_devicemode( &pjob.nt_devmode );
+
+ ZERO_STRUCT( pjob );
+
+ unpack_pjob( ret.dptr, ret.dsize, &pjob );
+
+ SAFE_FREE(ret.dptr);
return &pjob;
}
static BOOL pjob_store(int snum, uint32 jobid, struct printjob *pjob)
{
- TDB_DATA old_data, new_data;
- BOOL ret;
- struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
+ TDB_DATA old_data, new_data;
+ BOOL ret = False;
+ struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
+ char *buf = NULL;
+ int len, newlen, buflen;
+
if (!pdb)
return False;
old_data = tdb_fetch(pdb->tdb, print_key(jobid));
+ /* Doh! Now we have to pack/unpack data since the NT_DEVICEMODE was added */
+
+ newlen = 0;
+
+ do {
+ len = 0;
+ buflen = newlen;
+ len += tdb_pack(buf+len, buflen-len, "dddddddddffff",
+ pjob->pid,
+ pjob->sysjob,
+ pjob->fd,
+ pjob->starttime,
+ pjob->status,
+ pjob->size,
+ pjob->page_count,
+ pjob->spooled,
+ pjob->smbjob,
+ pjob->filename,
+ pjob->jobname,
+ pjob->user,
+ pjob->queuename);
+
+ len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len);
+
+ if (buflen != len)
+ {
+ char *tb;
+
+ tb = (char *)Realloc(buf, len);
+ if (!tb) {
+ DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
+ goto done;
+ }
+ else
+ buf = tb;
+ newlen = len;
+ }
+ }
+ while ( buflen != len );
+
+
/* Store new data */
- new_data.dptr = (void *)pjob;
- new_data.dsize = sizeof(*pjob);
+ new_data.dptr = buf;
+ new_data.dsize = len;
ret = (tdb_store(pdb->tdb, print_key(jobid), new_data, TDB_REPLACE) == 0);
release_print_db(pdb);
/* Send notify updates for what has changed */
- if (ret && (old_data.dsize == 0 || old_data.dsize == sizeof(*pjob))) {
- pjob_store_notify(
- snum, jobid, (struct printjob *)old_data.dptr,
- (struct printjob *)new_data.dptr);
- free(old_data.dptr);
- }
+ if ( ret && (old_data.dsize == 0 || old_data.dsize == sizeof(*pjob)) )
+ pjob_store_notify( snum, jobid, (struct printjob *)old_data.dptr, pjob );
+
+done:
+ SAFE_FREE( old_data.dptr );
+ SAFE_FREE( buf );
return ret;
}
return pjob->filename;
}
+
+/****************************************************************************
+ Give the filename used for a jobid.
+ Only valid for the process doing the spooling and when the job
+ has not been spooled.
+****************************************************************************/
+
+NT_DEVICEMODE *print_job_devmode(int snum, uint32 jobid)
+{
+ struct printjob *pjob = print_job_find(snum, jobid);
+
+ if ( !pjob )
+ return NULL;
+
+ return pjob->nt_devmode;
+}
+
/****************************************************************************
Set the place in the queue for a job.
****************************************************************************/
Start spooling a job - return the jobid.
***************************************************************************/
-uint32 print_job_start(struct current_user *user, int snum, char *jobname)
+uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DEVICEMODE *nt_devmode )
{
uint32 jobid;
char *path;
}
/* create the database entry */
+
ZERO_STRUCT(pjob);
+
pjob.pid = local_pid;
pjob.sysjob = -1;
pjob.fd = -1;
pjob.size = 0;
pjob.spooled = False;
pjob.smbjob = True;
-
+ pjob.nt_devmode = nt_devmode;
+
fstrcpy(pjob.jobname, jobname);
if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
int i;
uint32 jobid;
- if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int))
- return 0;
memcpy(&jobid, key.dptr, sizeof(jobid));
- memcpy(&pjob, data.dptr, sizeof(pjob));
+
+ if ( !unpack_pjob( data.dptr, data.dsize, &pjob ) )
+ return 0;
/* maybe it isn't for this queue */
if (ts->snum != lp_servicenumber(pjob.queuename))
struct printjob pjob;
uint32 jobid;
- if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int))
- return 0;
memcpy(&jobid, key.dptr, sizeof(jobid));
- memcpy(&pjob, data.dptr, sizeof(pjob));
+
+ if ( !unpack_pjob( data.dptr, data.dsize, &pjob ) )
+ return 0;
/* maybe it isn't for this queue - this cannot happen with the tdb/printer code. JRA */
if (ts->snum != lp_servicenumber(pjob.queuename))
fstring machine;
fstring user;
} client;
+
+ /* devmode sent in the OpenPrinter() call */
+ NT_DEVICEMODE *nt_devmode;
+
} Printer_entry;
static Printer_entry *printers_list;
free_spool_notify_option(&Printer->notify.option);
Printer->notify.option=NULL;
Printer->notify.client_connected=False;
+
+ free_nt_devicemode( &Printer->nt_devmode );
/* Remove from the internal list. */
DLIST_REMOVE(printers_list, Printer);
WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
{
- UNISTR2 *printername = NULL;
- PRINTER_DEFAULT *printer_default = &q_u->printer_default;
- POLICY_HND *handle = &r_u->handle;
+ UNISTR2 *printername = NULL;
+ PRINTER_DEFAULT *printer_default = &q_u->printer_default;
+ POLICY_HND *handle = &r_u->handle;
fstring name;
int snum;
}
Printer->access_granted = printer_default->access_required;
+
+ /*
+ * If the client sent a devmode in the OpenPrinter() call, then
+ * save it here in case we get a job submission on this handle
+ */
+
+ if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
+ && q_u->printer_default.devmode_cont.devmode_ptr )
+ {
+ convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
+ &Printer->nt_devmode );
+ }
return WERR_OK;
}
SAFE_FREE(dev);
}
+
/****************************************************************************
- Create a DEVMODE struct. Returns malloced memory.
+ Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
+ should be valid upon entry
****************************************************************************/
-DEVICEMODE *construct_dev_mode(int snum)
+static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
{
- char adevice[32];
- char aform[32];
- NT_PRINTER_INFO_LEVEL *printer = NULL;
- NT_DEVICEMODE *ntdevmode = NULL;
- DEVICEMODE *devmode = NULL;
-
- DEBUG(7,("construct_dev_mode\n"));
-
- DEBUGADD(8,("getting printer characteristics\n"));
-
- if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
- DEBUG(2,("construct_dev_mode: malloc fail.\n"));
- return NULL;
- }
-
- ZERO_STRUCTP(devmode);
-
- if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
- goto fail;
-
- if (printer->info_2->devmode)
- ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
-
- if (ntdevmode == NULL) {
- DEBUG(5, ("BONG! There was no device mode!\n"));
- goto fail;
- }
-
- DEBUGADD(8,("loading DEVICEMODE\n"));
-
- slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
- init_unistr(&devmode->devicename, adevice);
+ if ( !devmode || !ntdevmode )
+ return False;
+
+ init_unistr(&devmode->devicename, ntdevmode->devicename);
- slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
- init_unistr(&devmode->formname, aform);
+ init_unistr(&devmode->formname, ntdevmode->formname);
devmode->specversion = ntdevmode->specversion;
devmode->driverversion = ntdevmode->driverversion;
if (ntdevmode->private != NULL) {
if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
- goto fail;
+ return False;
}
+
+ return True;
+}
- free_nt_devicemode(&ntdevmode);
- free_a_printer(&printer,2);
+/****************************************************************************
+ Create a DEVMODE struct. Returns malloced memory.
+****************************************************************************/
- return devmode;
+DEVICEMODE *construct_dev_mode(int snum)
+{
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ DEVICEMODE *devmode = NULL;
+
+ DEBUG(7,("construct_dev_mode\n"));
+
+ DEBUGADD(8,("getting printer characteristics\n"));
- fail:
+ if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
+ return NULL;
- if (ntdevmode)
- free_nt_devicemode(&ntdevmode);
- if (printer)
- free_a_printer(&printer,2);
- free_dev_mode(devmode);
+ if ( !printer->info_2->devmode ) {
+ DEBUG(5, ("BONG! There was no device mode!\n"));
+ goto done;
+ }
+
+ if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
+ DEBUG(2,("construct_dev_mode: malloc fail.\n"));
+ goto done;
+ }
+
+ ZERO_STRUCTP(devmode);
+
+ DEBUGADD(8,("loading DEVICEMODE\n"));
+
+ if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
+ free_dev_mode( devmode );
+ devmode = NULL;
+ }
- return NULL;
+done:
+ free_a_printer(&printer,2);
+
+ return devmode;
}
/********************************************************************
* in EMF format.
*
* So I add checks like in NT Server ...
- *
- * lkclXXXX jean-francois, i love this kind of thing. oh, well,
- * there's a bug in NT client-side code, so we'll fix it in the
- * server-side code. *nnnnnggggh!*
*/
if (info_1->p_datatype != 0) {
unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
- Printer->jobid = print_job_start(&user, snum, jobname);
+ Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
/* An error occured in print_job_start() so return an appropriate
NT error code. */
return WERR_NOMEM;
}
- for (i=0; i<count && found==False; i++) {
+ for (i=0; i<count && found==False; i++) {
if (queue[i].job==(int)jobid)
found=True;
}
static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
{
- int i=0;
- BOOL found=False;
- JOB_INFO_2 *info_2;
+ int i = 0;
+ BOOL found = False;
+ JOB_INFO_2 *info_2;
NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
- WERROR ret;
- DEVICEMODE *devmode = NULL;
+ WERROR ret;
+ DEVICEMODE *devmode = NULL;
+ NT_DEVICEMODE *nt_devmode = NULL;
info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
if (!W_ERROR_IS_OK(ret))
goto done;
-
- if (!(devmode = construct_dev_mode(snum)) ) {
+
+ /*
+ * if the print job does not have a DEVMODE associated with it,
+ * just use the one for the printer
+ */
+
+ if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
+ devmode = construct_dev_mode(snum);
+ else {
+ if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
+ ZERO_STRUCTP( devmode );
+ convert_nt_devicemode( devmode, nt_devmode );
+ }
+ }
+
+ if ( !devmode ) {
ret = WERR_NOMEM;
goto done;
}