endpoint server for the spoolss pipe
Copyright (C) Tim Potter 2004
+ Copyright (C) Stefan Metzmacher 2005
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
#include "rpc_server/dcerpc_server.h"
#include "librpc/gen_ndr/ndr_spoolss.h"
#include "rpc_server/common/common.h"
-#include "rpc_server/spoolss/dcesrv_spoolss.h"
+#include "ntptr/ntptr.h"
+#include "lib/socket/socket.h"
+#include "smbd/service_stream.h"
-/*
- spoolss_EnumPrinters
-*/
-static WERROR spoolss_EnumPrinters(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct spoolss_EnumPrinters *r)
+#define SPOOLSS_BUFFER_UNION(fn,info,level) \
+ ((info)?ndr_size_##fn(info, level, 0):0)
+
+#define SPOOLSS_BUFFER_UNION_ARRAY(fn,info,level,count) \
+ ((info)?ndr_size_##fn##_info(dce_call, level, count, info):0)
+
+#define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= r->out.needed)?val_true:val_false)
+
+static WERROR spoolss_parse_printer_name(TALLOC_CTX *mem_ctx, const char *name,
+ const char **_server_name,
+ const char **_object_name,
+ enum ntptr_HandleType *_object_type)
{
- void *spoolss_ctx;
- struct ldb_message **msgs;
- int count;
- int i;
- union spoolss_PrinterInfo *info;
+ char *p;
+ char *server = NULL;
+ char *server_unc = NULL;
+ const char *object = name;
+
+ /* no printername is there it's like open server */
+ if (!name) {
+ *_server_name = NULL;
+ *_object_name = NULL;
+ *_object_type = NTPTR_HANDLE_SERVER;
+ return WERR_OK;
+ }
- r->out.info = NULL;
- *r->out.buf_size = 0;
- r->out.count = 0;
+ /* just "\\" is invalid */
+ if (strequal("\\\\", name)) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
- spoolss_ctx = spoolssdb_connect();
- W_ERROR_HAVE_NO_MEMORY(spoolss_ctx);
+ if (strncmp("\\\\", name, 2) == 0) {
+ server_unc = talloc_strdup(mem_ctx, name);
+ W_ERROR_HAVE_NO_MEMORY(server_unc);
+ server = server_unc + 2;
- count = spoolssdb_search(spoolss_ctx, mem_ctx, NULL, &msgs, NULL,
- "(&(objectclass=printer))");
- spoolssdb_close(spoolss_ctx);
+ /* here we know we have "\\" in front not followed
+ * by '\0', now see if we have another "\" in the string
+ */
+ p = strchr_m(server, '\\');
+ if (!p) {
+ /* there's no other "\", so it's ("\\%s",server)
+ */
+ *_server_name = server_unc;
+ *_object_name = NULL;
+ *_object_type = NTPTR_HANDLE_SERVER;
+ return WERR_OK;
+ }
+ /* here we know that we have ("\\%s\",server),
+ * if we have '\0' as next then it's an invalid name
+ * otherwise the printer_name
+ */
+ p[0] = '\0';
+ /* everything that follows is the printer name */
+ p++;
+ object = p;
- if (count == 0) return WERR_OK;
- if (count < 0) return WERR_GENERAL_FAILURE;
+ /* just "" as server is invalid */
+ if (strequal(server, "")) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
+ }
- info = talloc_array(mem_ctx, union spoolss_PrinterInfo, count);
- W_ERROR_HAVE_NO_MEMORY(info);
+ /* just "" is invalid */
+ if (strequal(object, "")) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
- switch(r->in.level) {
- case 1:
- for (i = 0; i < count; i++) {
- info[i].info1.flags = samdb_result_uint(msgs[i], "flags", 0);
+#define XCV_PORT ",XcvPort "
+#define XCV_MONITOR ",XcvMonitor "
+ if (strncmp(object, XCV_PORT, strlen(XCV_PORT)) == 0) {
+ object += strlen(XCV_PORT);
- info[i].info1.name = samdb_result_string(msgs[i], "name", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info1.name);
+ /* just "" is invalid */
+ if (strequal(object, "")) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
- info[i].info1.description = samdb_result_string(msgs[i], "description", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info1.description);
+ *_server_name = server_unc;
+ *_object_name = object;
+ *_object_type = NTPTR_HANDLE_PORT;
+ return WERR_OK;
+ } else if (strncmp(object, XCV_MONITOR, strlen(XCV_MONITOR)) == 0) {
+ object += strlen(XCV_MONITOR);
- info[i].info1.comment = samdb_result_string(msgs[i], "comment", NULL);
+ /* just "" is invalid */
+ if (strequal(object, "")) {
+ return WERR_INVALID_PRINTER_NAME;
}
+
+ *_server_name = server_unc;
+ *_object_name = object;
+ *_object_type = NTPTR_HANDLE_MONITOR;
return WERR_OK;
- case 2:
- for (i = 0; i < count; i++) {
- info[i].info2.servername = samdb_result_string(msgs[i], "servername", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);
+ }
- info[i].info2.printername = samdb_result_string(msgs[i], "printername", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);
+ *_server_name = server_unc;
+ *_object_name = object;
+ *_object_type = NTPTR_HANDLE_PRINTER;
+ return WERR_OK;
+}
- info[i].info2.sharename = samdb_result_string(msgs[i], "sharename", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info2.sharename);
+/*
+ * Check server_name is:
+ * - "" , functions that don't allow "",
+ * should check that on their own, before calling this function
+ * - our name (only netbios yet, TODO: need to test dns name!)
+ * - our ip address of the current use socket
+ * otherwise return WERR_INVALID_PRINTER_NAME
+ */
+static WERROR spoolss_check_server_name(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ const char *server_name)
+{
+ BOOL ret;
+ char *str;
- info[i].info2.portname = samdb_result_string(msgs[i], "portname", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info2.portname);
+ /* NULL is ok */
+ if (!server_name) return WERR_OK;
- info[i].info2.drivername = samdb_result_string(msgs[i], "drivername", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info2.drivername);
+ /* "" is ok */
+ ret = strequal("",server_name);
+ if (ret) return WERR_OK;
- info[i].info2.comment = samdb_result_string(msgs[i], "comment", NULL);
+ /* just "\\" is invalid */
+ if (strequal("\\\\", server_name)) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
- info[i].info2.location = samdb_result_string(msgs[i], "location", NULL);
+ /* then we need "\\" */
+ if (strncmp("\\\\", server_name, 2) != 0) {
+ return WERR_INVALID_PRINTER_NAME;
+ }
- info[i].info2.devmode = NULL;
+ server_name += 2;
- info[i].info2.sepfile = samdb_result_string(msgs[i], "sepfile", NULL);
+ /* NETBIOS NAME is ok */
+ ret = strequal(lp_netbios_name(), server_name);
+ if (ret) return WERR_OK;
- info[i].info2.printprocessor = samdb_result_string(msgs[i], "printprocessor", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info2.printprocessor);
+ /* DNS NAME is ok
+ * TODO: we need to check if aliases are also ok
+ */
+ if (lp_realm()) {
+ str = talloc_asprintf(mem_ctx, "%s.%s",
+ lp_netbios_name(),
+ lp_realm());
+ W_ERROR_HAVE_NO_MEMORY(str);
+
+ ret = strequal(str, server_name);
+ talloc_free(str);
+ if (ret) return WERR_OK;
+ }
- info[i].info2.datatype = samdb_result_string(msgs[i], "datatype", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info2.datatype);
+ str = socket_get_my_addr(dce_call->conn->srv_conn->socket, mem_ctx);
+ W_ERROR_HAVE_NO_MEMORY(str);
- info[i].info2.parameters = samdb_result_string(msgs[i], "parameters", NULL);
+ ret = strequal(str, server_name);
+ talloc_free(str);
+ if (ret) return WERR_OK;
- info[i].info2.secdesc = NULL;
+ return WERR_INVALID_PRINTER_NAME;
+}
- info[i].info2.attributes = samdb_result_uint(msgs[i], "attributes", 0);
- info[i].info2.priority = samdb_result_uint(msgs[i], "priority", 0);
- info[i].info2.defaultpriority = samdb_result_uint(msgs[i], "defaultpriority", 0);
- info[i].info2.starttime = samdb_result_uint(msgs[i], "starttime", 0);
- info[i].info2.untiltime = samdb_result_uint(msgs[i], "untiltime", 0);
- info[i].info2.status = samdb_result_uint(msgs[i], "status", 0);
- info[i].info2.cjobs = samdb_result_uint(msgs[i], "cjobs", 0);
- info[i].info2.averageppm = samdb_result_uint(msgs[i], "averageppm", 0);
- }
- return WERR_OK;
- case 4:
- for (i = 0; i < count; i++) {
- info[i].info4.printername = samdb_result_string(msgs[i], "printername", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);
+static NTSTATUS dcerpc_spoolss_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
+{
+ NTSTATUS status;
+ struct ntptr_context *ntptr;
- info[i].info4.servername = samdb_result_string(msgs[i], "servername", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);
+ status = ntptr_init_context(dce_call->context, lp_ntptr_providor(), &ntptr);
+ NT_STATUS_NOT_OK_RETURN(status);
- info[i].info4.attributes = samdb_result_uint(msgs[i], "attributes", 0);
- }
- return WERR_OK;
- case 5:
- for (i = 0; i < count; i++) {
- info[i].info5.printername = samdb_result_string(msgs[i], "name", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info5.printername);
+ dce_call->context->private = ntptr;
- info[i].info5.portname = samdb_result_string(msgs[i], "port", "");
- W_ERROR_HAVE_NO_MEMORY(info[i].info5.portname);
+ return NT_STATUS_OK;
+}
- info[i].info5.attributes = samdb_result_uint(msgs[i], "attributes", 0);
- info[i].info5.device_not_selected_timeout = samdb_result_uint(msgs[i], "device_not_selected_timeout", 0);
- info[i].info5.transmission_retry_timeout = samdb_result_uint(msgs[i], "transmission_retry_timeout", 0);
- }
- return WERR_OK;
- }
+#define DCESRV_INTERFACE_SPOOLSS_BIND dcerpc_spoolss_bind
+
+/*
+ spoolss_EnumPrinters
+*/
+static WERROR spoolss_EnumPrinters(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct spoolss_EnumPrinters *r)
+{
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ WERROR status;
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = ntptr_EnumPrinters(ntptr, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
- return WERR_UNKNOWN_LEVEL;
+ r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinters, r->out.info, r->in.level, r->out.count);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
static WERROR spoolss_EnumJobs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumJobs *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ return WERR_OK;
}
static WERROR spoolss_EnumPrinterDrivers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinterDrivers *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ WERROR status;
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = ntptr_EnumPrinterDrivers(ntptr, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinterDrivers, r->out.info, r->in.level, r->out.count);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
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);
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ WERROR status;
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = ntptr_GetPrinterDriverDirectory(ntptr, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, r->out.info, r->in.level);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
static WERROR spoolss_EnumPrintProcessors(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrintProcessors *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ return WERR_OK;
}
static WERROR spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterData *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_GetPrintServerData(handle, mem_ctx, r);
+ break;
+ default:
+ status = WERR_FOOBAR;
+ break;
+ }
+
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = ndr_size_spoolss_PrinterData(&r->out.data, r->out.type, 0);
+ r->out.type = SPOOLSS_BUFFER_OK(r->out.type, SPOOLSS_PRINTER_DATA_TYPE_NULL);
+ r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
}
static WERROR spoolss_AddForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_AddForm *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_AddPrintServerForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_AddPrinterForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ return WERR_OK;
}
static WERROR spoolss_DeleteForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_DeleteForm *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_DeletePrintServerForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_DeletePrinterForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ return WERR_OK;
}
static WERROR spoolss_GetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_GetForm *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ /*
+ * stupid, but w2k3 returns WERR_BADFID here?
+ */
+ return WERR_BADFID;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_GetPrinterForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, r->out.info, r->in.level);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
static WERROR spoolss_SetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_SetForm *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_SetPrintServerForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_SetPrinterForm(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ return WERR_OK;
}
static WERROR spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumForms *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ WERROR status;
+
+ DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
+ handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
+
+ switch (handle->type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_EnumPrintServerForms(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_EnumPrinterForms(handle, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
+ }
+
+ r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumForms, r->out.info, r->in.level, r->out.count);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
static WERROR spoolss_EnumPorts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPorts *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ WERROR status;
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, r->in.servername);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = ntptr_EnumPorts(ntptr, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPorts, r->out.info, r->in.level, r->out.count);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
static WERROR spoolss_EnumMonitors(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumMonitors *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ WERROR status;
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, r->in.servername);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = ntptr_EnumMonitors(ntptr, mem_ctx, r);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumMonitors, r->out.info, r->in.level, r->out.count);
+ r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+ r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
+ return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
static WERROR spoolss_AddPort(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_AddPort *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ return WERR_NOT_SUPPORTED;
}
static WERROR spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ /*
+ * TODO: for now just return ok,
+ * to keep the w2k3 PrintServer
+ * happy to allow to open the Add Printer GUI
+ */
+ return WERR_OK;
}
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
-
-static WERROR spoolss_OpenPrinterEx_server(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct spoolss_OpenPrinterEx *r,
- const char *server_name)
-{
- struct spoolss_handle_server *state;
- struct dcesrv_handle *handle;
- BOOL ret;
-
- /* Check printername is our name or our ip address
- */
- ret = strequal(server_name, lp_netbios_name());
- if (!ret) {
- /* TODO:
- ret = strequal(server_name, ...our_ip...);*/
- if (!ret) {
- return WERR_INVALID_PRINTER_NAME;
- }
- }
-
- handle = dcesrv_handle_new(dce_call->context, SPOOLSS_HANDLE_SERVER);
- W_ERROR_HAVE_NO_MEMORY(handle);
-
- state = talloc(handle, struct spoolss_handle_server);
- W_ERROR_HAVE_NO_MEMORY(state);
-
- handle->data = state;
-
- state->handle_type = SPOOLSS_HANDLE_SERVER;
- state->access_mask = r->in.access_mask;
-
- *r->out.handle = handle->wire_handle;
-
- return WERR_OK;
-}
-
-static WERROR spoolss_OpenPrinterEx_printer(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct spoolss_OpenPrinterEx *r,
- const char *printer_name)
-{
- DEBUG(0, ("looking for printer %s\n", printer_name));
-
- return WERR_INVALID_PRINTER_NAME;
-}
-
/*
spoolss_OpenPrinterEx
*/
static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r)
{
- const char *p;
- const char *printer = r->in.printername;
+ struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
+ struct ntptr_GenericHandle *handle;
+ struct dcesrv_handle *h;
+ const char *server;
+ const char *object;
+ enum ntptr_HandleType type;
+ WERROR status;
+
ZERO_STRUCTP(r->out.handle);
- /* just "\\" is invalid */
- if (strequal(r->in.printername, "\\\\")) {
- return WERR_INVALID_PRINTER_NAME;
+ status = spoolss_parse_printer_name(mem_ctx, r->in.printername, &server, &object, &type);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ status = spoolss_check_server_name(dce_call, mem_ctx, server);
+ W_ERROR_NOT_OK_RETURN(status);
+
+ switch (type) {
+ case NTPTR_HANDLE_SERVER:
+ status = ntptr_OpenPrintServer(ntptr, mem_ctx, r, server, &handle);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PORT:
+ status = ntptr_OpenPort(ntptr, mem_ctx, r, object, &handle);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_MONITOR:
+ status = ntptr_OpenMonitor(ntptr, mem_ctx, r, object, &handle);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ case NTPTR_HANDLE_PRINTER:
+ status = ntptr_OpenPrinter(ntptr, mem_ctx, r, object, &handle);
+ W_ERROR_NOT_OK_RETURN(status);
+ break;
+ default:
+ return WERR_FOOBAR;
}
- if (strncmp(r->in.printername, "\\\\", 2) == 0) {
- /* here we know we have "\\" in front not followed
- * by '\0', now see if we have another "\" in the string
- */
- p = strchr_m(r->in.printername + 2, '\\');
- if (!p) {
- /* there's no other "\", so it's ("\\%s",server)
- */
- const char *server = r->in.printername + 2;
- DEBUG(0,("print server: [%s][%s]\n", r->in.printername, server));
- return spoolss_OpenPrinterEx_server(dce_call, mem_ctx, r, server);
- }
- /* here we know that we have ("\\%s\",server),
- * if we have '\0' as next then it's an invalid name
- * otherwise the printer_name
- */
- p++;
- if (p[0] == '\0') {
- return WERR_INVALID_PRINTER_NAME;
- }
- printer = p;
- }
+ h = dcesrv_handle_new(dce_call->context, handle->type);
+ W_ERROR_HAVE_NO_MEMORY(h);
- DEBUG(0,("printer: [%s][%s]\n", r->in.printername, printer));
- return spoolss_OpenPrinterEx_printer(dce_call, mem_ctx, r, printer);
-}
+ h->data = talloc_steal(h, handle);
+
+ *r->out.handle = h->wire_handle;
+ return WERR_OK;
+}
/*
spoolss_AddPrinterEx