mirror of
https://github.com/samba-team/samba.git
synced 2025-01-26 10:04:02 +03:00
r13815: "Into the blind world let us now descend,"
Began the poet, his face as pale as death. "I will go first, and you will follow me." --- Adding XcvDataPort() to the spoolss code for remotely add ports. The design is to allow an intuitive means of creating a new CUPS print queue from the Windows 2000/XP APW without hacks like specifying the deviceURI in the location field of the printer properties dialog. Also set 'default devmode = yes' as the new default since it causes no harm and only is executed when you have a NULL devmode anyways. (This used to be commit 123e478ce5b5f63a61d00197332b847e83722468)
This commit is contained in:
parent
a7552e677e
commit
e33b728c7b
@ -423,6 +423,7 @@ typedef struct {
|
||||
|
||||
#define PRINTER_HANDLE_IS_PRINTER 0
|
||||
#define PRINTER_HANDLE_IS_PRINTSERVER 1
|
||||
#define PRINTER_HANDLE_IS_TCPMON 2
|
||||
|
||||
/* structure to store the printer handles */
|
||||
/* and a reference to what it's pointing to */
|
||||
|
@ -4,7 +4,7 @@
|
||||
Copyright (C) Andrew Tridgell 1992-2000,
|
||||
Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
|
||||
Copyright (C) Jean Francois Micouleau 1998-2000.
|
||||
Copyright (C) Gerald Carter 2001-2005.
|
||||
Copyright (C) Gerald Carter 2001-2006.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -107,8 +107,16 @@
|
||||
#define SPOOLSS_DELETEPRINTERDATAEX 0x51
|
||||
#define SPOOLSS_DELETEPRINTERKEY 0x52
|
||||
#define SPOOLSS_DELETEPRINTERDRIVEREX 0x54
|
||||
#define SPOOLSS_XCVDATAPORT 0x58
|
||||
#define SPOOLSS_ADDPRINTERDRIVEREX 0x59
|
||||
|
||||
/*
|
||||
* Special strings for the OpenPrinter() call. See the MSDN DDK
|
||||
* docs on the XcvDataPort() for more details.
|
||||
*/
|
||||
|
||||
#define SPL_XCV_MONITOR_TCPMON ",XcvMonitor Standard TCP/IP Port"
|
||||
|
||||
|
||||
#define PRINTER_CONTROL_UNPAUSE 0x00000000
|
||||
#define PRINTER_CONTROL_PAUSE 0x00000001
|
||||
@ -2161,6 +2169,24 @@ typedef struct spool_r_getprintprocessordirectory
|
||||
}
|
||||
SPOOL_R_GETPRINTPROCESSORDIRECTORY;
|
||||
|
||||
/**************************************/
|
||||
|
||||
typedef struct spool_q_xcvdataport {
|
||||
POLICY_HND handle;
|
||||
UNISTR2 dataname;
|
||||
RPC_BUFFER indata;
|
||||
uint32 indata_len;
|
||||
uint32 offered;
|
||||
uint32 unknown;
|
||||
} SPOOL_Q_XCVDATAPORT;
|
||||
|
||||
typedef struct spool_r_xcvdataport {
|
||||
RPC_BUFFER outdata;
|
||||
uint32 *unknown1;
|
||||
uint32 *unknown2;
|
||||
WERROR status;
|
||||
} SPOOL_R_XCVDATAPORT;
|
||||
|
||||
#define PRINTER_DRIVER_VERSION 2
|
||||
#define PRINTER_DRIVER_ARCHITECTURE "Windows NT x86"
|
||||
|
||||
|
@ -574,7 +574,7 @@ static service sDefault = {
|
||||
False, /* bInheritOwner */
|
||||
True, /* bMSDfsRoot */
|
||||
False, /* bUseClientDriver */
|
||||
False, /* bDefaultDevmode */
|
||||
True, /* bDefaultDevmode */
|
||||
False, /* bForcePrintername */
|
||||
True, /* bNTAclSupport */
|
||||
False, /* bForceUnknownAclUser */
|
||||
|
@ -7406,3 +7406,67 @@ BOOL make_spoolss_q_rffpcnex(SPOOL_Q_RFFPCNEX *q_u, POLICY_HND *handle,
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
********************************************************************/
|
||||
|
||||
BOOL spoolss_io_q_xcvdataport(const char *desc, SPOOL_Q_XCVDATAPORT *q_u, prs_struct *ps, int depth)
|
||||
{
|
||||
prs_debug(ps, depth, desc, "spoolss_io_q_xcvdataport");
|
||||
depth++;
|
||||
|
||||
if(!prs_align(ps))
|
||||
return False;
|
||||
|
||||
if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
|
||||
return False;
|
||||
|
||||
if(!smb_io_unistr2("", &q_u->dataname, True, ps, depth))
|
||||
return False;
|
||||
|
||||
if (!prs_align(ps))
|
||||
return False;
|
||||
|
||||
if(!prs_rpcbuffer("", ps, depth, &q_u->indata))
|
||||
return False;
|
||||
|
||||
if (!prs_align(ps))
|
||||
return False;
|
||||
|
||||
if (!prs_uint32("indata_len", ps, depth, &q_u->indata_len))
|
||||
return False;
|
||||
if (!prs_uint32("offered", ps, depth, &q_u->offered))
|
||||
return False;
|
||||
if (!prs_uint32("unknown", ps, depth, &q_u->unknown))
|
||||
return False;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
********************************************************************/
|
||||
|
||||
BOOL spoolss_io_r_xcvdataport(const char *desc, SPOOL_R_XCVDATAPORT *r_u, prs_struct *ps, int depth)
|
||||
{
|
||||
prs_debug(ps, depth, desc, "spoolss_io_r_xcvdataport");
|
||||
depth++;
|
||||
|
||||
if(!prs_align(ps))
|
||||
return False;
|
||||
if(!prs_rpcbuffer("", ps, depth, &r_u->outdata))
|
||||
return False;
|
||||
|
||||
if (!prs_align(ps))
|
||||
return False;
|
||||
|
||||
if(!prs_pointer("unknown1", ps, depth, (void**)&r_u->unknown1, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_uint32))
|
||||
return False;
|
||||
if(!prs_pointer("unknown2", ps, depth, (void**)&r_u->unknown2, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_uint32))
|
||||
return False;
|
||||
if(!prs_werror("status", ps, depth, &r_u->status))
|
||||
return False;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
@ -1519,66 +1519,34 @@ static BOOL api_spoolss_deleteprinterdriverex(pipes_struct *p)
|
||||
return True;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/****************************************************************************
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL api_spoolss_replyopenprinter(pipes_struct *p)
|
||||
static BOOL api_spoolss_xcvdataport(pipes_struct *p)
|
||||
{
|
||||
SPOOL_Q_REPLYOPENPRINTER q_u;
|
||||
SPOOL_R_REPLYOPENPRINTER r_u;
|
||||
SPOOL_Q_XCVDATAPORT q_u;
|
||||
SPOOL_R_XCVDATAPORT r_u;
|
||||
prs_struct *data = &p->in_data.data;
|
||||
prs_struct *rdata = &p->out_data.rdata;
|
||||
|
||||
ZERO_STRUCT(q_u);
|
||||
ZERO_STRUCT(r_u);
|
||||
|
||||
if(!spoolss_io_q_replyopenprinter("", &q_u, data, 0)) {
|
||||
DEBUG(0,("spoolss_io_q_replyopenprinter: unable to unmarshall SPOOL_Q_REPLYOPENPRINTER.\n"));
|
||||
if(!spoolss_io_q_xcvdataport("", &q_u, data, 0)) {
|
||||
DEBUG(0,("spoolss_io_q_replyopenprinter: unable to unmarshall SPOOL_Q_XCVDATAPORT.\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
r_u.status = _spoolss_replyopenprinter(p, &q_u, &r_u);
|
||||
r_u.status = _spoolss_xcvdataport(p, &q_u, &r_u);
|
||||
|
||||
if(!spoolss_io_r_replyopenprinter("", &r_u, rdata, 0)) {
|
||||
DEBUG(0,("spoolss_io_r_replyopenprinter: unable to marshall SPOOL_R_REPLYOPENPRINTER.\n"));
|
||||
if(!spoolss_io_r_xcvdataport("", &r_u, rdata, 0)) {
|
||||
DEBUG(0,("spoolss_io_r_replyopenprinter: unable to marshall SPOOL_R_XCVDATAPORT.\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL api_spoolss_replycloseprinter(pipes_struct *p)
|
||||
{
|
||||
SPOOL_Q_REPLYCLOSEPRINTER q_u;
|
||||
SPOOL_R_REPLYCLOSEPRINTER r_u;
|
||||
prs_struct *data = &p->in_data.data;
|
||||
prs_struct *rdata = &p->out_data.rdata;
|
||||
|
||||
ZERO_STRUCT(q_u);
|
||||
ZERO_STRUCT(r_u);
|
||||
|
||||
if(!spoolss_io_q_replycloseprinter("", &q_u, data, 0)) {
|
||||
DEBUG(0,("spoolss_io_q_replycloseprinter: unable to unmarshall SPOOL_Q_REPLYCLOSEPRINTER.\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
r_u.status = _spoolss_replycloseprinter(p, &q_u, &r_u);
|
||||
|
||||
if(!spoolss_io_r_replycloseprinter("", &r_u, rdata, 0)) {
|
||||
DEBUG(0,("spoolss_io_r_replycloseprinter: unable to marshall SPOOL_R_REPLYCLOSEPRINTER.\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*******************************************************************
|
||||
\pipe\spoolss commands
|
||||
********************************************************************/
|
||||
@ -1636,11 +1604,8 @@ static BOOL api_spoolss_replycloseprinter(pipes_struct *p)
|
||||
{"SPOOLSS_GETPRINTPROCESSORDIRECTORY",SPOOLSS_GETPRINTPROCESSORDIRECTORY,api_spoolss_getprintprocessordirectory},
|
||||
{"SPOOLSS_ADDPRINTERDRIVEREX", SPOOLSS_ADDPRINTERDRIVEREX, api_spoolss_addprinterdriverex },
|
||||
{"SPOOLSS_DELETEPRINTERDRIVEREX", SPOOLSS_DELETEPRINTERDRIVEREX, api_spoolss_deleteprinterdriverex },
|
||||
#if 0
|
||||
{"SPOOLSS_REPLYOPENPRINTER", SPOOLSS_REPLYOPENPRINTER, api_spoolss_replyopenprinter },
|
||||
{"SPOOLSS_REPLYCLOSEPRINTER", SPOOLSS_REPLYCLOSEPRINTER, api_spoolss_replycloseprinter }
|
||||
#endif
|
||||
};
|
||||
{"SPOOLSS_XCVDATAPORT", SPOOLSS_XCVDATAPORT, api_spoolss_xcvdataport },
|
||||
};
|
||||
|
||||
void spoolss_get_pipe_fns( struct api_struct **fns, int *n_fns )
|
||||
{
|
||||
|
@ -435,7 +435,10 @@ static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Set printer handle name.
|
||||
Set printer handle name.. Accept names like \\server, \\server\printer,
|
||||
\\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
|
||||
the MSDN docs regarding OpenPrinter() for details on the XcvData() and
|
||||
XcvDataPort() interface.
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
|
||||
@ -477,6 +480,14 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
|
||||
return False;
|
||||
|
||||
DEBUGADD(5, ("searching for [%s]\n", aprinter ));
|
||||
|
||||
/* check for the TCPMON interface */
|
||||
|
||||
if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
|
||||
Printer->printer_type = PRINTER_HANDLE_IS_TCPMON;
|
||||
fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
|
||||
found = True;
|
||||
}
|
||||
|
||||
/* Search all sharenames first as this is easier than pulling
|
||||
the printer_info_2 off of disk. Don't use find_service() since
|
||||
@ -1473,60 +1484,6 @@ WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* spoolss_open_printer
|
||||
*
|
||||
* If the openprinterex rpc call contains a devmode,
|
||||
* it's a per-user one. This per-user devmode is derivated
|
||||
* from the global devmode. Openprinterex() contains a per-user
|
||||
* devmode for when you do EMF printing and spooling.
|
||||
* In the EMF case, the NT workstation is only doing half the job
|
||||
* of rendering the page. The other half is done by running the printer
|
||||
* driver on the server.
|
||||
* The EMF file doesn't contain the page description (paper size, orientation, ...).
|
||||
* The EMF file only contains what is to be printed on the page.
|
||||
* So in order for the server to know how to print, the NT client sends
|
||||
* a devicemode attached to the openprinterex call.
|
||||
* But this devicemode is short lived, it's only valid for the current print job.
|
||||
*
|
||||
* If Samba would have supported EMF spooling, this devicemode would
|
||||
* have been attached to the handle, to sent it to the driver to correctly
|
||||
* rasterize the EMF file.
|
||||
*
|
||||
* As Samba only supports RAW spooling, we only receive a ready-to-print file,
|
||||
* we just act as a pass-thru between windows and the printer.
|
||||
*
|
||||
* In order to know that Samba supports only RAW spooling, NT has to call
|
||||
* getprinter() at level 2 (attribute field) or NT has to call startdoc()
|
||||
* and until NT sends a RAW job, we refuse it.
|
||||
*
|
||||
* But to call getprinter() or startdoc(), you first need a valid handle,
|
||||
* and to get an handle you have to call openprintex(). Hence why you have
|
||||
* a devicemode in the openprinterex() call.
|
||||
*
|
||||
*
|
||||
* Differences between NT4 and NT 2000.
|
||||
* NT4:
|
||||
* ---
|
||||
* On NT4, you only have a global devicemode. This global devicemode can be changed
|
||||
* by the administrator (or by a user with enough privs). Everytime a user
|
||||
* wants to print, the devicemode is resetted to the default. In Word, everytime
|
||||
* you print, the printer's characteristics are always reset to the global devicemode.
|
||||
*
|
||||
* NT 2000:
|
||||
* -------
|
||||
* In W2K, there is the notion of per-user devicemode. The first time you use
|
||||
* a printer, a per-user devicemode is build from the global devicemode.
|
||||
* If you change your per-user devicemode, it is saved in the registry, under the
|
||||
* H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
|
||||
* printer preferences available.
|
||||
*
|
||||
* To change the per-user devicemode: it's the "Printing Preferences ..." button
|
||||
* on the General Tab of the printer properties windows.
|
||||
*
|
||||
* To change the global devicemode: it's the "Printing Defaults..." button
|
||||
* on the Advanced Tab of the printer properties window.
|
||||
*
|
||||
* JFM.
|
||||
********************************************************************/
|
||||
|
||||
WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
|
||||
@ -1581,10 +1538,15 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
|
||||
* Second case: the user is opening a printer:
|
||||
* NT doesn't let us connect to a printer if the connecting user
|
||||
* doesn't have print permission.
|
||||
*
|
||||
* Third case: user is opening the TCP/IP port monitor
|
||||
* access checks same as opening a handle to the print server.
|
||||
*/
|
||||
|
||||
if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
|
||||
switch (Printer->printer_type )
|
||||
{
|
||||
case PRINTER_HANDLE_IS_PRINTSERVER:
|
||||
case PRINTER_HANDLE_IS_TCPMON:
|
||||
/* Printserver handles use global struct... */
|
||||
|
||||
snum = -1;
|
||||
@ -1642,10 +1604,9 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
|
||||
? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
|
||||
|
||||
/* We fall through to return WERR_OK */
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
case PRINTER_HANDLE_IS_PRINTER:
|
||||
/* NT doesn't let us connect to a printer if the connecting user
|
||||
doesn't have print permission. */
|
||||
|
||||
@ -1702,6 +1663,11 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
|
||||
DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
|
||||
? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* sanity check to prevent programmer error */
|
||||
return WERR_BADFID;
|
||||
}
|
||||
|
||||
Printer->access_granted = printer_default->access_required;
|
||||
@ -8496,18 +8462,22 @@ WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDAT
|
||||
|
||||
static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
|
||||
{
|
||||
PRINTMONITOR_1 *info_1=NULL;
|
||||
PRINTMONITOR_1 *info_1;
|
||||
WERROR result = WERR_OK;
|
||||
int i;
|
||||
|
||||
if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
|
||||
if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
|
||||
return WERR_NOMEM;
|
||||
|
||||
(*returned) = 0x1;
|
||||
*returned = 2;
|
||||
|
||||
init_unistr(&info_1->name, "Local Port");
|
||||
|
||||
*needed += spoolss_size_printmonitor_info_1(info_1);
|
||||
init_unistr(&(info_1[0].name), "Local Port");
|
||||
init_unistr(&(info_1[1].name), "Standard TCP/IP Port");
|
||||
|
||||
for ( i=0; i<*returned; i++ ) {
|
||||
*needed += spoolss_size_printmonitor_info_1(&info_1[i]);
|
||||
}
|
||||
|
||||
if (*needed > offered) {
|
||||
result = WERR_INSUFFICIENT_BUFFER;
|
||||
goto out;
|
||||
@ -8518,7 +8488,9 @@ static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint
|
||||
goto out;
|
||||
}
|
||||
|
||||
smb_io_printmonitor_info_1("", buffer, info_1, 0);
|
||||
for ( i=0; i<*returned; i++ ) {
|
||||
smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
|
||||
}
|
||||
|
||||
out:
|
||||
SAFE_FREE(info_1);
|
||||
@ -8535,20 +8507,27 @@ out:
|
||||
|
||||
static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
|
||||
{
|
||||
PRINTMONITOR_2 *info_2=NULL;
|
||||
PRINTMONITOR_2 *info_2;
|
||||
WERROR result = WERR_OK;
|
||||
int i;
|
||||
|
||||
if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
|
||||
if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
|
||||
return WERR_NOMEM;
|
||||
|
||||
(*returned) = 0x1;
|
||||
*returned = 2;
|
||||
|
||||
init_unistr(&info_2->name, "Local Port");
|
||||
init_unistr(&info_2->environment, "Windows NT X86");
|
||||
init_unistr(&info_2->dll_name, "localmon.dll");
|
||||
|
||||
*needed += spoolss_size_printmonitor_info_2(info_2);
|
||||
init_unistr(&(info_2[0].name), "Local Port");
|
||||
init_unistr(&(info_2[0].environment), "Windows NT X86");
|
||||
init_unistr(&(info_2[0].dll_name), "localmon.dll");
|
||||
|
||||
init_unistr(&(info_2[1].name), "Standard TCP/IP Port");
|
||||
init_unistr(&(info_2[1].environment), "Windows NT X86");
|
||||
init_unistr(&(info_2[1].dll_name), "tcpmon.dll");
|
||||
|
||||
for ( i=0; i<*returned; i++ ) {
|
||||
*needed += spoolss_size_printmonitor_info_2(&info_2[i]);
|
||||
}
|
||||
|
||||
if (*needed > offered) {
|
||||
result = WERR_INSUFFICIENT_BUFFER;
|
||||
goto out;
|
||||
@ -8559,7 +8538,9 @@ static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint
|
||||
goto out;
|
||||
}
|
||||
|
||||
smb_io_printmonitor_info_2("", buffer, info_2, 0);
|
||||
for ( i=0; i<*returned; i++ ) {
|
||||
smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
|
||||
}
|
||||
|
||||
out:
|
||||
SAFE_FREE(info_2);
|
||||
@ -9398,23 +9379,9 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
|
||||
SPOOL_R_REPLYOPENPRINTER *r_u)
|
||||
WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
|
||||
{
|
||||
DEBUG(5,("_spoolss_replyopenprinter\n"));
|
||||
|
||||
DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
|
||||
SPOOL_R_REPLYCLOSEPRINTER *r_u)
|
||||
{
|
||||
DEBUG(5,("_spoolss_replycloseprinter\n"));
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user