r11567: Ldb API change patch.
[abartlet/samba.git/.git] / source4 / rpc_server / spoolss / dcesrv_spoolss.c
index fa3a16f7e1557fba8545cba194fed6dec75f425c..c15a7f1d8a4898583aa86671b9012229a994b77e 100644 (file)
@@ -4,6 +4,7 @@
    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,
@@ -203,7 +289,7 @@ static WERROR spoolss_GetJob(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem
 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;
 }
 
 
@@ -263,7 +349,19 @@ static WERROR spoolss_AddPrinterDriver(struct dcesrv_call_state *dce_call, TALLO
 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);
 }
 
 
@@ -283,7 +381,18 @@ 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);
+       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);
 }
 
 
@@ -313,7 +422,7 @@ static WERROR spoolss_AddPrintProcessor(struct dcesrv_call_state *dce_call, TALL
 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;
 }
 
 
@@ -423,7 +532,28 @@ static WERROR spoolss_ScheduleJob(struct dcesrv_call_state *dce_call, TALLOC_CTX
 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);
 }
 
 
@@ -473,7 +603,27 @@ static WERROR spoolss_ClosePrinter(struct dcesrv_call_state *dce_call, TALLOC_CT
 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;
 }
 
 
@@ -483,7 +633,27 @@ static WERROR spoolss_AddForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
 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;
 }
 
 
@@ -493,7 +663,30 @@ static WERROR spoolss_DeleteForm(struct dcesrv_call_state *dce_call, TALLOC_CTX
 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);
 }
 
 
@@ -503,7 +696,27 @@ static WERROR spoolss_GetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
 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;
 }
 
 
@@ -513,7 +726,30 @@ static WERROR spoolss_SetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
 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);
 }
 
 
@@ -523,7 +759,19 @@ static WERROR spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 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);
 }
 
 
@@ -533,7 +781,19 @@ 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)
 {
-       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);
 }
 
 
@@ -543,7 +803,7 @@ static WERROR spoolss_EnumMonitors(struct dcesrv_call_state *dce_call, TALLOC_CT
 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;
 }
 
 
@@ -823,7 +1083,12 @@ static WERROR spoolss_ResetPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_
 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;
 }
 
 
@@ -856,95 +1121,58 @@ static WERROR spoolss_44(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx
        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