mirror of
https://github.com/samba-team/samba.git
synced 2025-02-24 13:57:43 +03:00
r7580: - add GetPrinterDriverDirectory() idl, torture test and server code
- add EnumMonitors() server code and return "Standard TCP/IP Port" - add parsing for opening Ports and Monitors with OpenPrinterEx() metze (This used to be commit 08e6de37bc293e2f000d03b51642964d92d6e95e)
This commit is contained in:
parent
bc1f32b8ad
commit
056d63c62f
@ -573,7 +573,26 @@
|
||||
|
||||
/******************/
|
||||
/* Function: 0x0c */
|
||||
typedef struct {
|
||||
nstring directory_name;
|
||||
} spoolss_DriverDirectoryInfo1;
|
||||
|
||||
/* NOTE: it's seems that w2k3 completly ignores the level
|
||||
in its server code
|
||||
*/
|
||||
typedef [nodiscriminant,relative_base,gensize,public] union {
|
||||
[case(1)] spoolss_DriverDirectoryInfo1 info1;
|
||||
[default] spoolss_DriverDirectoryInfo1 info1;
|
||||
} spoolss_DriverDirectoryInfo;
|
||||
|
||||
WERROR spoolss_GetPrinterDriverDirectory(
|
||||
[in] unistr *server,
|
||||
[in] unistr *environment,
|
||||
[in] uint32 level,
|
||||
[in] DATA_BLOB *buffer,
|
||||
[in] uint32 offered,
|
||||
[out,subcontext(4),switch_is(level)] spoolss_DriverDirectoryInfo *info,
|
||||
[out] uint32 needed
|
||||
);
|
||||
|
||||
/******************/
|
||||
|
@ -356,7 +356,43 @@ static WERROR spoolss_GetPrinterDriver(struct dcesrv_call_state *dce_call, TALLO
|
||||
static WERROR spoolss_GetPrinterDriverDirectory(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct spoolss_GetPrinterDriverDirectory *r)
|
||||
{
|
||||
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
|
||||
union spoolss_DriverDirectoryInfo *info;
|
||||
const char *prefix;
|
||||
const char *postfix;
|
||||
|
||||
/*
|
||||
* NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a
|
||||
* are ignoring the r->in.level completely, so we do :-)
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO: check the server name is ours
|
||||
* - if it's a invalid UNC then return WERR_INVALID_NAME
|
||||
* - if it's the wrong host name return WERR_INVALID_PARAM
|
||||
* - if it's "" then we need to return a local WINDOWS path
|
||||
*/
|
||||
if (strcmp("", r->in.server) == 0) {
|
||||
prefix = "C:\\DRIVERS";
|
||||
} else {
|
||||
prefix = talloc_asprintf(mem_ctx, "%s\\print$", r->in.server);
|
||||
W_ERROR_HAVE_NO_MEMORY(prefix);
|
||||
}
|
||||
|
||||
if (strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) {
|
||||
postfix = "W32X86";
|
||||
} else {
|
||||
return WERR_INVALID_ENVIRONMENT;
|
||||
}
|
||||
|
||||
info = talloc(mem_ctx, union spoolss_DriverDirectoryInfo);
|
||||
W_ERROR_HAVE_NO_MEMORY(info);
|
||||
|
||||
info->info1.directory_name = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix);
|
||||
W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name);
|
||||
|
||||
r->out.needed = ndr_size_spoolss_DriverDirectoryInfo(info, r->in.level, 0);
|
||||
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
|
||||
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
|
||||
|
||||
@ -666,16 +702,16 @@ static WERROR spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLOC_CTX *
|
||||
for (i=0; i < count; i++) {
|
||||
info[i].info1.flags = SPOOLSS_FORM_PRINTER;
|
||||
|
||||
info[i].info1.form_name = talloc_strdup(mem_ctx, "Samba Printer Form");
|
||||
info[i].info1.form_name = talloc_strdup(mem_ctx, "Letter");
|
||||
W_ERROR_HAVE_NO_MEMORY(info[i].info1.form_name);
|
||||
|
||||
info[i].info1.size.width = 30;
|
||||
info[i].info1.size.height = 40;
|
||||
info[i].info1.size.width = 0x34b5c;
|
||||
info[i].info1.size.height = 0x44368;
|
||||
|
||||
info[i].info1.area.left = 0;
|
||||
info[i].info1.area.top = 0;
|
||||
info[i].info1.area.right = 30;
|
||||
info[i].info1.area.bottom = 40;
|
||||
info[i].info1.area.right = 0x34b5c;
|
||||
info[i].info1.area.bottom = 0x44368;
|
||||
}
|
||||
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumForms, r->in.level, count, info);
|
||||
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
|
||||
@ -745,7 +781,46 @@ static WERROR spoolss_EnumPorts(struct dcesrv_call_state *dce_call, TALLOC_CTX *
|
||||
static WERROR spoolss_EnumMonitors(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct spoolss_EnumMonitors *r)
|
||||
{
|
||||
return WERR_OK;
|
||||
union spoolss_MonitorInfo *info;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
count = 1;
|
||||
|
||||
if (count == 0) return WERR_OK;
|
||||
if (count < 0) return WERR_GENERAL_FAILURE;
|
||||
|
||||
info = talloc_array(mem_ctx, union spoolss_MonitorInfo, count);
|
||||
W_ERROR_HAVE_NO_MEMORY(info);
|
||||
|
||||
switch (r->in.level) {
|
||||
case 1:
|
||||
for (i=0; i < count; i++) {
|
||||
info[i].info1.monitor_name = talloc_strdup(mem_ctx, "Standard TCP/IP Port");
|
||||
W_ERROR_HAVE_NO_MEMORY(info[i].info1.monitor_name);
|
||||
}
|
||||
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumMonitors, r->in.level, count, info);
|
||||
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
|
||||
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
|
||||
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
|
||||
case 2:
|
||||
for (i=0; i < count; i++) {
|
||||
info[i].info2.monitor_name = talloc_strdup(mem_ctx, "Standard TCP/IP Port");
|
||||
W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name);
|
||||
|
||||
info[i].info2.environment = talloc_strdup(mem_ctx, SPOOLSS_ARCHITECTURE_NT_X86);
|
||||
W_ERROR_HAVE_NO_MEMORY(info[i].info2.environment);
|
||||
|
||||
info[i].info2.dll_name = talloc_strdup(mem_ctx, "tcpmon.dll");
|
||||
W_ERROR_HAVE_NO_MEMORY(info[i].info2.dll_name);
|
||||
}
|
||||
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumMonitors, r->in.level, count, info);
|
||||
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
|
||||
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
|
||||
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
|
||||
return WERR_UNKNOWN_LEVEL;
|
||||
}
|
||||
|
||||
|
||||
@ -1108,6 +1183,41 @@ static WERROR spoolss_OpenPrinterEx_server(struct dcesrv_call_state *dce_call,
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
static WERROR spoolss_OpenPrinterEx_port(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct spoolss_OpenPrinterEx *r,
|
||||
const char *server_name,
|
||||
const char *port_name)
|
||||
{
|
||||
DEBUG(1, ("looking for port [%s] (server[%s])\n", port_name, server_name));
|
||||
|
||||
return WERR_INVALID_PRINTER_NAME;
|
||||
}
|
||||
|
||||
static WERROR spoolss_OpenPrinterEx_monitor(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct spoolss_OpenPrinterEx *r,
|
||||
const char *server_name,
|
||||
const char *monitor_name)
|
||||
{
|
||||
if (strequal("Standard TCP/IP Port", monitor_name)) {
|
||||
struct dcesrv_handle *handle;
|
||||
|
||||
handle = dcesrv_handle_new(dce_call->context, SPOOLSS_HANDLE_MONITOR);
|
||||
W_ERROR_HAVE_NO_MEMORY(handle);
|
||||
|
||||
handle->data = NULL;
|
||||
|
||||
*r->out.handle = handle->wire_handle;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
|
||||
DEBUG(1, ("looking for monitor [%s] (server[%s])\n", monitor_name, server_name));
|
||||
|
||||
return WERR_INVALID_PRINTER_NAME;
|
||||
}
|
||||
|
||||
static WERROR spoolss_OpenPrinterEx_printer(struct dcesrv_call_state *dce_call,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct spoolss_OpenPrinterEx *r,
|
||||
@ -1127,7 +1237,7 @@ static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_C
|
||||
{
|
||||
char *p;
|
||||
char *server = NULL;
|
||||
const char *printer = r->in.printername;
|
||||
const char *object = r->in.printername;
|
||||
ZERO_STRUCTP(r->out.handle);
|
||||
|
||||
/* no printername is there it's like open server */
|
||||
@ -1160,25 +1270,49 @@ static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_C
|
||||
p[0] = '\0';
|
||||
/* everything that follows is the printer name */
|
||||
p++;
|
||||
printer = p;
|
||||
object = p;
|
||||
|
||||
/* just "" as server is invalid */
|
||||
if (strequal(server, "")) {
|
||||
DEBUG(2,("ivalid server: [%s][%s][%s]\n", r->in.printername, server, printer));
|
||||
DEBUG(2,("OpenPrinterEx invalid print server: [%s][%s][%s]\n", r->in.printername, server, object));
|
||||
return WERR_INVALID_PRINTER_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
/* just "" is invalid */
|
||||
if (strequal(printer, "")) {
|
||||
DEBUG(2,("invalid printer: [%s][%s][%s]\n", r->in.printername, server, printer));
|
||||
if (strequal(object, "")) {
|
||||
DEBUG(2,("OpenPrinterEx invalid object: [%s][%s][%s]\n", r->in.printername, server, object));
|
||||
return WERR_INVALID_PRINTER_NAME;
|
||||
}
|
||||
|
||||
DEBUG(3,("printer: [%s][%s][%s]\n", r->in.printername, server, printer));
|
||||
return spoolss_OpenPrinterEx_printer(dce_call, mem_ctx, r, server, printer);
|
||||
}
|
||||
DEBUG(3,("OpenPrinterEx object: [%s][%s][%s]\n", r->in.printername, server, object));
|
||||
|
||||
#define XCV_PORT ",XcvPort "
|
||||
#define XCV_MONITOR ",XcvMonitor "
|
||||
if (strncmp(object, XCV_PORT, strlen(XCV_PORT)) == 0) {
|
||||
object += strlen(XCV_PORT);
|
||||
|
||||
/* just "" is invalid */
|
||||
if (strequal(object, "")) {
|
||||
DEBUG(2,("OpenPrinterEx invalid port: [%s][%s][%s]\n", r->in.printername, server, object));
|
||||
return WERR_INVALID_PRINTER_NAME;
|
||||
}
|
||||
|
||||
return spoolss_OpenPrinterEx_port(dce_call, mem_ctx, r, server, object);
|
||||
} else if (strncmp(object, XCV_MONITOR, strlen(XCV_MONITOR)) == 0) {
|
||||
object += strlen(XCV_MONITOR);
|
||||
|
||||
/* just "" is invalid */
|
||||
if (strequal(object, "")) {
|
||||
DEBUG(2,("OpenPrinterEx invalid monitor: [%s][%s][%s]\n", r->in.printername, server, object));
|
||||
return WERR_INVALID_PRINTER_NAME;
|
||||
}
|
||||
|
||||
return spoolss_OpenPrinterEx_monitor(dce_call, mem_ctx, r, server, object);
|
||||
}
|
||||
|
||||
return spoolss_OpenPrinterEx_printer(dce_call, mem_ctx, r, server, object);
|
||||
}
|
||||
|
||||
/*
|
||||
spoolss_AddPrinterEx
|
||||
|
@ -25,7 +25,9 @@
|
||||
*/
|
||||
enum spoolss_handle_type {
|
||||
SPOOLSS_HANDLE_SERVER,
|
||||
SPOOLSS_HANDLE_PRINTER
|
||||
SPOOLSS_HANDLE_PRINTER,
|
||||
SPOOLSS_HANDLE_PORT,
|
||||
SPOOLSS_HANDLE_MONITOR
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -211,6 +211,78 @@ static BOOL test_EnumPorts(struct test_spoolss_context *ctx)
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_GetPrinterDriverDirectory(struct test_spoolss_context *ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct spoolss_GetPrinterDriverDirectory r;
|
||||
struct {
|
||||
uint16_t level;
|
||||
const char *server;
|
||||
} levels[] = {{
|
||||
.level = 1,
|
||||
.server = ""
|
||||
},{
|
||||
.level = 78,
|
||||
.server = ""
|
||||
},{
|
||||
.level = 1,
|
||||
.server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(ctx->p))
|
||||
},{
|
||||
.level = 1024,
|
||||
.server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(ctx->p))
|
||||
}
|
||||
};
|
||||
int i;
|
||||
BOOL ret = True;
|
||||
|
||||
for (i=0;i<ARRAY_SIZE(levels);i++) {
|
||||
int level = levels[i].level;
|
||||
DATA_BLOB blob;
|
||||
|
||||
r.in.server = levels[i].server;
|
||||
r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
|
||||
r.in.level = level;
|
||||
r.in.buffer = NULL;
|
||||
r.in.offered = 0;
|
||||
|
||||
printf("Testing GetPrinterDriverDirectory level %u\n", r.in.level);
|
||||
|
||||
status = dcerpc_spoolss_GetPrinterDriverDirectory(ctx->p, ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("dcerpc_spoolss_GetPrinterDriverDirectory failed - %s\n", nt_errstr(status));
|
||||
ret = False;
|
||||
continue;
|
||||
}
|
||||
if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
|
||||
printf("GetPrinterDriverDirectory unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
|
||||
win_errstr(r.out.result));
|
||||
ret = False;
|
||||
continue;
|
||||
}
|
||||
|
||||
blob = data_blob_talloc(ctx, NULL, r.out.needed);
|
||||
data_blob_clear(&blob);
|
||||
r.in.buffer = &blob;
|
||||
r.in.offered = r.out.needed;
|
||||
|
||||
status = dcerpc_spoolss_GetPrinterDriverDirectory(ctx->p, ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
printf("dcerpc_spoolss_GetPrinterDriverDirectory failed - %s\n", nt_errstr(status));
|
||||
ret = False;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
printf("GetPrinterDriverDirectory failed - %s\n",
|
||||
win_errstr(r.out.result));
|
||||
ret = False;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL test_EnumPrinterDrivers(struct test_spoolss_context *ctx)
|
||||
{
|
||||
NTSTATUS status;
|
||||
@ -223,11 +295,11 @@ static BOOL test_EnumPrinterDrivers(struct test_spoolss_context *ctx)
|
||||
int level = levels[i];
|
||||
DATA_BLOB blob;
|
||||
|
||||
r.in.server = "";
|
||||
r.in.environment = "Windows NT x86";
|
||||
r.in.level = level;
|
||||
r.in.buffer = NULL;
|
||||
r.in.offered = 0;
|
||||
r.in.server = "";
|
||||
r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
|
||||
r.in.level = level;
|
||||
r.in.buffer = NULL;
|
||||
r.in.offered = 0;
|
||||
|
||||
printf("Testing EnumPrinterDrivers level %u\n", r.in.level);
|
||||
|
||||
@ -1994,6 +2066,8 @@ BOOL torture_rpc_spoolss(void)
|
||||
|
||||
ret &= test_EnumPorts(ctx);
|
||||
|
||||
ret &= test_GetPrinterDriverDirectory(ctx);
|
||||
|
||||
ret &= test_EnumPrinterDrivers(ctx);
|
||||
|
||||
ret &= test_EnumMonitors(ctx);
|
||||
|
Loading…
x
Reference in New Issue
Block a user