s3-smbd provide struct smbd_server_connection * to conn_snum_used
[nivanova/samba-autobuild/.git] / source3 / smbd / lanman.c
index 0c866da7069b5fd7de1fc1bb2036f2db8f256689..5958bb9746da1f8ee19c58b48dca3f0ce1ea4577 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    Inter-process communication and named pipe handling
    Copyright (C) Andrew Tridgell 1992-1998
@@ -6,17 +6,17 @@
 
    SMB Version handling
    Copyright (C) John H Terpstra 1995-1998
-   
+
    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
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */
    */
 
 #include "includes.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "rpc_client/rpc_client.h"
+#include "../librpc/gen_ndr/ndr_samr_c.h"
+#include "../librpc/gen_ndr/ndr_spoolss_c.h"
+#include "rpc_client/cli_spoolss.h"
+#include "rpc_client/init_spoolss.h"
+#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
+#include "../librpc/gen_ndr/rap.h"
+#include "../lib/util/binsearch.h"
+#include "../libcli/auth/libcli_auth.h"
+#include "rpc_client/init_lsa.h"
+#include "../libcli/security/security.h"
+#include "printing.h"
+#include "passdb/machine_sid.h"
+#include "auth.h"
+#include "rpc_server/rpc_ncacn_np.h"
 
 #ifdef CHECK_TYPES
 #undef CHECK_TYPES
@@ -61,14 +78,16 @@ static char *smb_realloc_limit(void *ptr, size_t size)
        return val;
 }
 
-static bool api_Unsupported(connection_struct *conn, uint16 vuid,
+static bool api_Unsupported(struct smbd_server_connection *sconn,
+                           connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt, int mprcnt,
                                char **rdata, char **rparam,
                                int *rdata_len, int *rparam_len);
 
-static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
+static bool api_TooSmall(struct smbd_server_connection *sconn,
+                        connection_struct *conn, uint16 vuid, char *param, char *data,
                         int mdrcnt, int mprcnt,
                         char **rdata, char **rparam,
                         int *rdata_len, int *rparam_len);
@@ -98,11 +117,11 @@ static int CopyExpanded(connection_struct *conn,
        }
        buf = talloc_sub_advanced(ctx,
                                lp_servicename(SNUM(conn)),
-                               conn->server_info->unix_name,
+                               conn->session_info->unix_name,
                                conn->connectpath,
-                               conn->server_info->utok.gid,
-                               conn->server_info->sanitized_username,
-                               pdb_get_domain(conn->server_info->sam_account),
+                               conn->session_info->utok.gid,
+                               conn->session_info->sanitized_username,
+                               conn->session_info->info3->base.domain.string,
                                buf);
        if (!buf) {
                *p_space_remaining = 0;
@@ -149,11 +168,11 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s)
        }
        buf = talloc_sub_advanced(ctx,
                                lp_servicename(SNUM(conn)),
-                               conn->server_info->unix_name,
+                               conn->session_info->unix_name,
                                conn->connectpath,
-                               conn->server_info->utok.gid,
-                               conn->server_info->sanitized_username,
-                               pdb_get_domain(conn->server_info->sam_account),
+                               conn->session_info->utok.gid,
+                               conn->session_info->sanitized_username,
+                               conn->session_info->info3->base.domain.string,
                                buf);
        if (!buf) {
                return 0;
@@ -161,32 +180,6 @@ static int StrlenExpanded(connection_struct *conn, int snum, char *s)
        return strlen(buf) + 1;
 }
 
-static char *Expand(connection_struct *conn, int snum, char *s)
-{
-       TALLOC_CTX *ctx = talloc_tos();
-       char *buf = NULL;
-
-       if (!s) {
-               return NULL;
-       }
-       buf = talloc_strdup(ctx,s);
-       if (!buf) {
-               return 0;
-       }
-       buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
-       if (!buf) {
-               return 0;
-       }
-       return talloc_sub_advanced(ctx,
-                               lp_servicename(SNUM(conn)),
-                               conn->server_info->unix_name,
-                               conn->connectpath,
-                               conn->server_info->utok.gid,
-                               conn->server_info->sanitized_username,
-                               pdb_get_domain(conn->server_info->sam_account),
-                               buf);
-}
-
 /*******************************************************************
  Check a API string for validity when we only need to check the prefix.
 ******************************************************************/
@@ -203,7 +196,7 @@ struct pack_desc {
        int buflen;        /* remaining size for fixed part; on init: length of base */
        int subcount;       /* count of substructures */
        char *structbuf;  /* pointer into buffer for remaining fixed part */
-       int stringlen;    /* remaining size for variable part */                
+       int stringlen;    /* remaining size for variable part */
        char *stringbuf;  /* pointer into buffer for remaining variable part */
        int neededlen;    /* total needed size */
        int usedlen;        /* total used size (usedlen <= neededlen and usedlen <= buflen) */
@@ -524,74 +517,71 @@ static int check_printq_info(struct pack_desc* desc,
 #define RAP_QUEUE_STATUS_PAUSED 1
 #define RAP_QUEUE_STATUS_ERROR 2
 
-/* turn a print job status into a on the wire status 
+/* turn a print job status into a on the wire status
 */
-static int printj_status(int v)
+static int printj_spoolss_status(int v)
 {
-       switch (v) {
-       case LPQ_QUEUED:
+       if (v == JOB_STATUS_QUEUED)
                return RAP_JOB_STATUS_QUEUED;
-       case LPQ_PAUSED:
+       if (v & JOB_STATUS_PAUSED)
                return RAP_JOB_STATUS_PAUSED;
-       case LPQ_SPOOLING:
+       if (v & JOB_STATUS_SPOOLING)
                return RAP_JOB_STATUS_SPOOLING;
-       case LPQ_PRINTING:
+       if (v & JOB_STATUS_PRINTING)
                return RAP_JOB_STATUS_PRINTING;
-       }
        return 0;
 }
 
-/* turn a print queue status into a on the wire status 
+/* turn a print queue status into a on the wire status
 */
-static int printq_status(int v)
+static int printq_spoolss_status(int v)
 {
-       switch (v) {
-       case LPQ_QUEUED:
+       if (v == PRINTER_STATUS_OK)
                return 0;
-       case LPQ_PAUSED:
+       if (v & PRINTER_STATUS_PAUSED)
                return RAP_QUEUE_STATUS_PAUSED;
-       }
        return RAP_QUEUE_STATUS_ERROR;
 }
 
-static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
-                              struct pack_desc *desc,
-                              print_queue_struct *queue, int n)
+static void fill_spoolss_printjob_info(int uLevel,
+                                      struct pack_desc *desc,
+                                      struct spoolss_JobInfo2 *info2,
+                                      int n)
 {
-       time_t t = queue->time;
+       time_t t = spoolss_Time_to_time_t(&info2->submitted);
 
        /* the client expects localtime */
        t -= get_time_zone(t);
 
-       PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
+       PACKI(desc,"W",pjobid_to_rap(info2->printer_name, info2->job_id)); /* uJobId */
        if (uLevel == 1) {
-               PACKS(desc,"B21",queue->fs_user); /* szUserName */
+               PACKS(desc,"B21", info2->user_name); /* szUserName */
                PACKS(desc,"B","");             /* pad */
                PACKS(desc,"B16","");   /* szNotifyName */
                PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
                PACKS(desc,"z","");             /* pszParms */
                PACKI(desc,"W",n+1);            /* uPosition */
-               PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
+               PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
                PACKS(desc,"z","");             /* pszStatus */
-               PACKI(desc,"D",t); /* ulSubmitted */
-               PACKI(desc,"D",queue->size); /* ulSize */
-               PACKS(desc,"z",queue->fs_file); /* pszComment */
+               PACKI(desc,"D", t); /* ulSubmitted */
+               PACKI(desc,"D", info2->size); /* ulSize */
+               PACKS(desc,"z", info2->document_name); /* pszComment */
        }
        if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
-               PACKI(desc,"W",queue->priority);                /* uPriority */
-               PACKS(desc,"z",queue->fs_user); /* pszUserName */
+               PACKI(desc,"W", info2->priority);               /* uPriority */
+               PACKS(desc,"z", info2->user_name); /* pszUserName */
                PACKI(desc,"W",n+1);            /* uPosition */
-               PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
+               PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
                PACKI(desc,"D",t); /* ulSubmitted */
-               PACKI(desc,"D",queue->size); /* ulSize */
+               PACKI(desc,"D", info2->size); /* ulSize */
                PACKS(desc,"z","Samba");        /* pszComment */
-               PACKS(desc,"z",queue->fs_file); /* pszDocument */
+               PACKS(desc,"z", info2->document_name); /* pszDocument */
                if (uLevel == 3) {
                        PACKS(desc,"z","");     /* pszNotifyName */
                        PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
                        PACKS(desc,"z","");     /* pszParms */
                        PACKS(desc,"z","");     /* pszStatus */
-                       PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
+                       PACKS(desc,"z", info2->printer_name); /* pszQueue */
                        PACKS(desc,"z","lpd");  /* pszQProcName */
                        PACKS(desc,"z","");     /* pszQProcParms */
                        PACKS(desc,"z","NULL"); /* pszDriverName */
@@ -612,90 +602,48 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
        }
 }
 
-/********************************************************************
- Return a driver name given an snum.
- Returns True if from tdb, False otherwise.
- ********************************************************************/
-
-static bool get_driver_name(int snum, char **pp_drivername)
-{
-       NT_PRINTER_INFO_LEVEL *info = NULL;
-       bool in_tdb = false;
-
-       get_a_printer (NULL, &info, 2, lp_servicename(snum));
-       if (info != NULL) {
-               *pp_drivername = talloc_strdup(talloc_tos(),
-                                       info->info_2->drivername);
-               in_tdb = true;
-               free_a_printer(&info, 2);
-               if (!*pp_drivername) {
-                       return false;
-               }
-       }
-
-       return in_tdb;
-}
-
 /********************************************************************
  Respond to the DosPrintQInfo command with a level of 52
  This is used to get printer driver information for Win9x clients
  ********************************************************************/
-static void fill_printq_info_52(connection_struct *conn, int snum, 
-                               struct pack_desc* desc, int count )
+static void fill_printq_info_52(struct spoolss_DriverInfo3 *driver,
+                               struct pack_desc* desc, int count,
+                               const char *printer_name)
 {
        int                             i;
        fstring                         location;
-       NT_PRINTER_DRIVER_INFO_LEVEL    driver;
-       NT_PRINTER_INFO_LEVEL           *printer = NULL;
-
-       ZERO_STRUCT(driver);
-
-       if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
-               DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", 
-                       lp_servicename(snum)));
-               goto err;
-       }
-
-       if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 
-               "Windows 4.0", 0)) )
-       {
-               DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n", 
-                       printer->info_2->drivername));
-               goto err;
-       }
-
-       trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
-       trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
-       trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
+       trim_string(discard_const_p(char, driver->driver_path), "\\print$\\WIN40\\0\\", 0);
+       trim_string(discard_const_p(char, driver->data_file), "\\print$\\WIN40\\0\\", 0);
+       trim_string(discard_const_p(char, driver->help_file), "\\print$\\WIN40\\0\\", 0);
 
        PACKI(desc, "W", 0x0400);                     /* don't know */
-       PACKS(desc, "z", driver.info_3->name);        /* long printer name */
-       PACKS(desc, "z", driver.info_3->driverpath);  /* Driverfile Name */
-       PACKS(desc, "z", driver.info_3->datafile);    /* Datafile name */
-       PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
+       PACKS(desc, "z", driver->driver_name);        /* long printer name */
+       PACKS(desc, "z", driver->driver_path);  /* Driverfile Name */
+       PACKS(desc, "z", driver->data_file);    /* Datafile name */
+       PACKS(desc, "z", driver->monitor_name); /* language monitor */
 
        fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
        standard_sub_basic( "", "", location, sizeof(location)-1 );
        PACKS(desc,"z", location);                          /* share to retrieve files */
 
-       PACKS(desc,"z", driver.info_3->defaultdatatype);    /* default data type */
-       PACKS(desc,"z", driver.info_3->helpfile);           /* helpfile name */
-       PACKS(desc,"z", driver.info_3->driverpath);               /* driver name */
+       PACKS(desc,"z", driver->default_datatype);    /* default data type */
+       PACKS(desc,"z", driver->help_file);           /* helpfile name */
+       PACKS(desc,"z", driver->driver_path);               /* driver name */
 
-       DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
-       DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
-       DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
-       DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
+       DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
+       DEBUG(3,("Driver: %s:\n",driver->driver_path));
+       DEBUG(3,("Data File: %s:\n",driver->data_file));
+       DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
        DEBUG(3,("Driver Location: %s:\n",location));
-       DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
-       DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
+       DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
+       DEBUG(3,("Help File: %s:\n",driver->help_file));
        PACKI(desc,"N",count);                     /* number of files to copy */
 
-       for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++) 
+       for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
        {
-               trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
-               PACKS(desc,"z",driver.info_3->dependentfiles[i]);         /* driver files to copy */
-               DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
+               trim_string(discard_const_p(char, driver->dependent_files[i]), "\\print$\\WIN40\\0\\", 0);
+               PACKS(desc,"z",driver->dependent_files[i]);         /* driver files to copy */
+               DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
        }
 
        /* sanity check */
@@ -703,41 +651,47 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
                DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
                        count, i));
 
-       DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
+       DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name, i));
 
         desc->errcode=NERR_Success;
-       goto done;
 
-err:
-       DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
-       desc->errcode=NERR_notsupported;
+}
+
+static const char *strip_unc(const char *unc)
+{
+       char *p;
+
+       if (unc == NULL) {
+               return NULL;
+       }
 
-done:
-       if ( printer )
-               free_a_printer( &printer, 2 );
+       if ((p = strrchr(unc, '\\')) != NULL) {
+               return p+1;
+       }
 
-       if ( driver.info_3 )
-               free_a_printer_driver( driver, 3 );
+       return unc;
 }
 
-
-static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
+static void fill_printq_info(int uLevel,
                             struct pack_desc* desc,
-                            int count, print_queue_struct* queue,
-                            print_status_struct* status)
+                            int count,
+                            union spoolss_JobInfo *job_info,
+                            struct spoolss_DriverInfo3 *driver_info,
+                            struct spoolss_PrinterInfo2 *printer_info)
 {
        switch (uLevel) {
+       case 0:
        case 1:
        case 2:
-               PACKS(desc,"B13",SERVICE(snum));
+               PACKS(desc,"B13", strip_unc(printer_info->printername));
                break;
        case 3:
        case 4:
        case 5:
-               PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
+               PACKS(desc,"z", strip_unc(printer_info->printername));
                break;
        case 51:
-               PACKI(desc,"K",printq_status(status->status));
+               PACKI(desc,"K", printq_spoolss_status(printer_info->status));
                break;
        }
 
@@ -748,25 +702,19 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
                PACKI(desc,"W",0);              /* until time */
                PACKS(desc,"z","");             /* pSepFile */
                PACKS(desc,"z","lpd");  /* pPrProc */
-               PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
+               PACKS(desc,"z", strip_unc(printer_info->printername)); /* pDestinations */
                PACKS(desc,"z","");             /* pParms */
-               if (snum < 0) {
+               if (printer_info->printername == NULL) {
                        PACKS(desc,"z","UNKNOWN PRINTER");
                        PACKI(desc,"W",LPSTAT_ERROR);
-               }
-               else if (!status || !status->message[0]) {
-                       PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
-                       PACKI(desc,"W",LPSTAT_OK); /* status */
                } else {
-                       PACKS(desc,"z",status->message);
-                       PACKI(desc,"W",printq_status(status->status)); /* status */
+                       PACKS(desc,"z", printer_info->comment);
+                       PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* status */
                }
                PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
        }
 
        if (uLevel == 3 || uLevel == 4) {
-               char *drivername = NULL;
-
                PACKI(desc,"W",5);              /* uPriority */
                PACKI(desc,"W",0);              /* uStarttime */
                PACKI(desc,"W",0);              /* uUntiltime */
@@ -777,69 +725,38 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
                PACKS(desc,"z",NULL);           /* pszComment - don't ask.... JRA */
                /* "don't ask" that it's done this way to fix corrupted
                   Win9X/ME printer comments. */
-               if (!status) {
-                       PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
-               } else {
-                       PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
-               }
+               PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* fsStatus */
                PACKI(desc,(uLevel == 3 ? "W" : "N"),count);    /* cJobs */
-               PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
-               get_driver_name(snum,&drivername);
-               if (!drivername) {
-                       return;
-               }
-               PACKS(desc,"z",drivername);             /* pszDriverName */
+               PACKS(desc,"z", strip_unc(printer_info->printername)); /* pszPrinters */
+               PACKS(desc,"z", printer_info->drivername);              /* pszDriverName */
                PackDriverData(desc);   /* pDriverData */
        }
 
        if (uLevel == 2 || uLevel == 4) {
                int i;
-               for (i=0;i<count;i++)
-                       fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
+               for (i = 0; i < count; i++) {
+                       fill_spoolss_printjob_info(uLevel == 2 ? 1 : 2, desc, &job_info[i].info2, i);
+               }
        }
 
        if (uLevel==52)
-               fill_printq_info_52( conn, snum, desc, count );
+               fill_printq_info_52(driver_info, desc, count, printer_info->printername);
 }
 
 /* This function returns the number of files for a given driver */
-static int get_printerdrivernumber(int snum)
+static int get_printerdrivernumber(const struct spoolss_DriverInfo3 *driver)
 {
        int                             result = 0;
-       NT_PRINTER_DRIVER_INFO_LEVEL    driver;
-       NT_PRINTER_INFO_LEVEL           *printer = NULL;
-
-       ZERO_STRUCT(driver);
-
-       if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
-               DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n", 
-                       lp_servicename(snum)));
-               goto done;
-       }
-
-       if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 
-               "Windows 4.0", 0)) )
-       {
-               DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n", 
-                       printer->info_2->drivername));
-               goto done;
-       }
 
        /* count the number of files */
-       while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
-                       result++;
-                       \
- done:
-       if ( printer )
-               free_a_printer( &printer, 2 );
-
-       if ( driver.info_3 )
-               free_a_printer_driver( driver, 3 );
+       while (driver->dependent_files && *driver->dependent_files[result])
+               result++;
 
        return result;
 }
 
-static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
+static bool api_DosPrintQGetInfo(struct smbd_server_connection *sconn,
+                                connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -851,18 +768,25 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
        char *p = skip_string(param,tpscnt,str2);
        char *QueueName = p;
        unsigned int uLevel;
-       int count=0;
-       int snum;
+       uint32_t count = 0;
        char *str3;
        struct pack_desc desc;
-       print_queue_struct *queue=NULL;
-       print_status_struct status;
        char* tmpdata=NULL;
 
+       WERROR werr = WERR_OK;
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
+       struct policy_handle handle;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       union spoolss_DriverInfo driver_info;
+       union spoolss_JobInfo *job_info = NULL;
+       union spoolss_PrinterInfo printer_info;
+
        if (!str1 || !str2 || !p) {
                return False;
        }
-       memset((char *)&status,'\0',sizeof(status));
        memset((char *)&desc,'\0',sizeof(desc));
 
        p = skip_string(param,tpscnt,p);
@@ -876,9 +800,9 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
        /* remove any trailing username */
        if ((p = strchr_m(QueueName,'%')))
                *p = 0;
+
        DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
+
        /* check it's a supported varient */
        if (!prefix_ok(str1,"zWrLh"))
                return False;
@@ -899,22 +823,98 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
                SSVAL(*rparam,4,0);
                return(True);
        }
-       snum = find_service(QueueName);
-       if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
-               return False;
-               
+
+       ZERO_STRUCT(handle);
+
+       if (QueueName == NULL || (strlen(QueueName) < 1)) {
+               desc.errcode = W_ERROR_V(WERR_INVALID_PARAM);
+               goto out;
+       }
+
+       status = rpc_pipe_open_interface(conn,
+                                        &ndr_table_spoolss.syntax_id,
+                                        conn->session_info,
+                                        &conn->sconn->client_id,
+                                        conn->sconn->msg_ctx,
+                                        &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
+                         nt_errstr(status)));
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       b = cli->binding_handle;
+
+       ZERO_STRUCT(devmode_ctr);
+
+       status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
+                                           QueueName,
+                                           "RAW",
+                                           devmode_ctr,
+                                           PRINTER_ACCESS_USE,
+                                           &handle,
+                                           &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               desc.errcode = W_ERROR_V(werr);
+               goto out;
+       }
+
+       werr = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                        &handle,
+                                        2,
+                                        0,
+                                        &printer_info);
+       if (!W_ERROR_IS_OK(werr)) {
+               desc.errcode = W_ERROR_V(werr);
+               goto out;
+       }
+
        if (uLevel==52) {
-               count = get_printerdrivernumber(snum);
+               uint32_t server_major_version;
+               uint32_t server_minor_version;
+
+               werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
+                                                       &handle,
+                                                       "Windows 4.0",
+                                                       3, /* level */
+                                                       0,
+                                                       0, /* version */
+                                                       0,
+                                                       &driver_info,
+                                                       &server_major_version,
+                                                       &server_minor_version);
+               if (!W_ERROR_IS_OK(werr)) {
+                       desc.errcode = W_ERROR_V(werr);
+                       goto out;
+               }
+
+               count = get_printerdrivernumber(&driver_info.info3);
                DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
        } else {
-               count = print_queue_status(snum, &queue,&status);
+               uint32_t num_jobs;
+               werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
+                                              &handle,
+                                              0, /* firstjob */
+                                              0xff, /* numjobs */
+                                              2, /* level */
+                                              0, /* offered */
+                                              &num_jobs,
+                                              &job_info);
+               if (!W_ERROR_IS_OK(werr)) {
+                       desc.errcode = W_ERROR_V(werr);
+                       goto out;
+               }
+
+               count = num_jobs;
        }
 
        if (mdrcnt > 0) {
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
-                       SAFE_FREE(queue);
                        return False;
                }
                desc.base = *rdata;
@@ -930,11 +930,11 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
 
        if (init_package(&desc,1,count)) {
                desc.subcount = count;
-               fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
+               fill_printq_info(uLevel,&desc,count, job_info, &driver_info.info3, &printer_info.info2);
        }
 
        *rdata_len = desc.usedlen;
-  
+
        /*
         * We must set the return code to ERRbuftoosmall
         * in order to support lanman style printing with Win NT/2k
@@ -942,22 +942,25 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
         */
        if (!mdrcnt && lp_disable_spoolss())
                desc.errcode = ERRbuftoosmall;
+
+ out:
+       if (b && is_valid_policy_hnd(&handle)) {
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
+       }
+
        *rdata_len = desc.usedlen;
        *rparam_len = 6;
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
-               SAFE_FREE(queue);
                SAFE_FREE(tmpdata);
                return False;
        }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,desc.neededlen);
-  
+
        DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
 
-       SAFE_FREE(queue);
        SAFE_FREE(tmpdata);
 
        return(True);
@@ -967,7 +970,8 @@ static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
  View list of all print jobs on all queues.
 ****************************************************************************/
 
-static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
+static bool api_DosPrintQEnum(struct smbd_server_connection *sconn,
+                             connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt, int mprcnt,
@@ -979,14 +983,22 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
        char *p = skip_string(param,tpscnt,output_format1);
        unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
-       int services = lp_numservices();
-       int i, n;
+       int i;
        struct pack_desc desc;
-       print_queue_struct **queue = NULL;
-       print_status_struct *status = NULL;
        int *subcntarr = NULL;
        int queuecnt = 0, subcnt = 0, succnt = 0;
+
+       WERROR werr = WERR_OK;
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       uint32_t num_printers;
+       union spoolss_PrinterInfo *printer_info;
+       union spoolss_DriverInfo *driver_info;
+       union spoolss_JobInfo **job_info;
+
        if (!param_format || !output_format1 || !p) {
                return False;
        }
@@ -994,7 +1006,7 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
        memset((char *)&desc,'\0',sizeof(desc));
 
        DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
+
        if (!prefix_ok(param_format,"WrLeh")) {
                return False;
        }
@@ -1016,37 +1028,49 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
                return(True);
        }
 
-       for (i = 0; i < services; i++) {
-               if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
-                       queuecnt++;
-               }
+       status = rpc_pipe_open_interface(conn,
+                                        &ndr_table_spoolss.syntax_id,
+                                        conn->session_info,
+                                        &conn->sconn->client_id,
+                                        conn->sconn->msg_ctx,
+                                        &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
+                         nt_errstr(status)));
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       b = cli->binding_handle;
+
+       werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
+                                          PRINTER_ENUM_LOCAL,
+                                          cli->srv_name_slash,
+                                          2,
+                                          0,
+                                          &num_printers,
+                                          &printer_info);
+       if (!W_ERROR_IS_OK(werr)) {
+               desc.errcode = W_ERROR_V(werr);
+               goto out;
        }
 
-       if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
-               DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
+       queuecnt = num_printers;
+
+       job_info = talloc_array(mem_ctx, union spoolss_JobInfo *, num_printers);
+       if (job_info == NULL) {
                goto err;
        }
-       memset(queue,0,queuecnt*sizeof(print_queue_struct*));
-       if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
-               DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
+
+       driver_info = talloc_array(mem_ctx, union spoolss_DriverInfo, num_printers);
+       if (driver_info == NULL) {
                goto err;
        }
-       memset(status,0,queuecnt*sizeof(print_status_struct));
+
        if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
                DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
                goto err;
        }
 
-       subcnt = 0;
-       n = 0;
-       for (i = 0; i < services; i++) {
-               if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
-                       subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
-                       subcnt += subcntarr[n];
-                       n++;
-               }
-       }
-
        if (mdrcnt > 0) {
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
@@ -1056,22 +1080,87 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
        desc.base = *rdata;
        desc.buflen = mdrcnt;
 
+       subcnt = 0;
+       for (i = 0; i < num_printers; i++) {
+
+               uint32_t num_jobs;
+               struct policy_handle handle;
+               const char *printername;
+
+               printername = talloc_strdup(mem_ctx, printer_info[i].info2.printername);
+               if (printername == NULL) {
+                       goto err;
+               }
+
+               ZERO_STRUCT(handle);
+               ZERO_STRUCT(devmode_ctr);
+
+               status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
+                                                   printername,
+                                                   "RAW",
+                                                   devmode_ctr,
+                                                   PRINTER_ACCESS_USE,
+                                                   &handle,
+                                                   &werr);
+               if (!NT_STATUS_IS_OK(status)) {
+                       desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+                       goto out;
+               }
+               if (!W_ERROR_IS_OK(werr)) {
+                       desc.errcode = W_ERROR_V(werr);
+                       goto out;
+               }
+
+               werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
+                                              &handle,
+                                              0, /* firstjob */
+                                              0xff, /* numjobs */
+                                              2, /* level */
+                                              0, /* offered */
+                                              &num_jobs,
+                                              &job_info[i]);
+               if (!W_ERROR_IS_OK(werr)) {
+                       desc.errcode = W_ERROR_V(werr);
+                       goto out;
+               }
+
+               if (uLevel==52) {
+                       uint32_t server_major_version;
+                       uint32_t server_minor_version;
+
+                       werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
+                                                               &handle,
+                                                               "Windows 4.0",
+                                                               3, /* level */
+                                                               0,
+                                                               0, /* version */
+                                                               0,
+                                                               &driver_info[i],
+                                                               &server_major_version,
+                                                               &server_minor_version);
+                       if (!W_ERROR_IS_OK(werr)) {
+                               desc.errcode = W_ERROR_V(werr);
+                               goto out;
+                       }
+               }
+
+               subcntarr[i] = num_jobs;
+               subcnt += subcntarr[i];
+
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
+       }
+
        if (init_package(&desc,queuecnt,subcnt)) {
-               n = 0;
-               succnt = 0;
-               for (i = 0; i < services; i++) {
-                       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
-                               fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
-                               n++;
-                               if (desc.errcode == NERR_Success) {
-                                       succnt = n;
-                               }
+               for (i = 0; i < num_printers; i++) {
+                       fill_printq_info(uLevel,&desc,subcntarr[i], job_info[i], &driver_info[i].info3, &printer_info[i].info2);
+                       if (desc.errcode == NERR_Success) {
+                               succnt = i;
                        }
                }
        }
 
        SAFE_FREE(subcntarr);
+ out:
        *rdata_len = desc.usedlen;
        *rparam_len = 8;
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
@@ -1082,28 +1171,12 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,succnt);
        SSVAL(*rparam,6,queuecnt);
-  
-       for (i = 0; i < queuecnt; i++) {
-               if (queue) {
-                       SAFE_FREE(queue[i]);
-               }
-       }
 
-       SAFE_FREE(queue);
-       SAFE_FREE(status);
-  
        return True;
 
   err:
 
        SAFE_FREE(subcntarr);
-       for (i = 0; i < queuecnt; i++) {
-               if (queue) {
-                       SAFE_FREE(queue[i]);
-               }
-       }
-       SAFE_FREE(queue);
-       SAFE_FREE(status);
 
        return False;
 }
@@ -1112,7 +1185,7 @@ static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
  Get info level for a server list query.
 ****************************************************************************/
 
-static bool check_server_info(int uLevel, char* id)
+static bool check_session_info(int uLevel, char* id)
 {
        switch( uLevel ) {
                case 0:
@@ -1125,7 +1198,7 @@ static bool check_server_info(int uLevel, char* id)
                                return False;
                        }
                        break;
-               default: 
+               default:
                        return False;
        }
        return True;
@@ -1144,7 +1217,7 @@ struct srv_info_struct {
  number of entries.
 ******************************************************************/
 
-static int get_server_info(uint32 servertype, 
+static int get_session_info(uint32 servertype,
                           struct srv_info_struct **servers,
                           const char *domain)
 {
@@ -1154,9 +1227,9 @@ static int get_server_info(uint32 servertype,
        bool local_list_only;
        int i;
 
-       lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0, NULL);
+       lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
        if (!lines) {
-               DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
+               DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
                return 0;
        }
 
@@ -1185,7 +1258,7 @@ static int get_server_info(uint32 servertype,
                        alloced += 10;
                        *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
                        if (!*servers) {
-                               DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
+                               DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
                                TALLOC_FREE(lines);
                                return 0;
                        }
@@ -1214,6 +1287,7 @@ static int get_server_info(uint32 servertype,
                        continue;
                }
                fstrcpy(s->comment, p);
+               string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
 
                s->domain[0] = '\0';
                if (!next_token_talloc(frame,&ptr,&p, NULL)) {
@@ -1243,16 +1317,16 @@ static int get_server_info(uint32 servertype,
                        ok = False;
                }
 
-               if ((servertype & SV_TYPE_DOMAIN_ENUM) != 
+               if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
                                (s->type & SV_TYPE_DOMAIN_ENUM)) {
                        DEBUG(4,("s: dom mismatch "));
                        ok = False;
                }
-    
+
                if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
                        ok = False;
                }
-    
+
                /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
                s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
 
@@ -1266,7 +1340,7 @@ static int get_server_info(uint32 servertype,
                                s->name, s->type, s->comment, s->domain));
                }
        }
-  
+
        TALLOC_FREE(lines);
        return count;
 }
@@ -1275,8 +1349,8 @@ static int get_server_info(uint32 servertype,
  Fill in a server info structure.
 ******************************************************************/
 
-static int fill_srv_info(struct srv_info_struct *service, 
-                        int uLevel, char **buf, int *buflen, 
+static int fill_srv_info(struct srv_info_struct *service,
+                        int uLevel, char **buf, int *buflen,
                         char **stringbuf, int *stringspace, char *baseaddr)
 {
        int struct_len;
@@ -1284,7 +1358,7 @@ static int fill_srv_info(struct srv_info_struct *service,
        char* p2;
        int l2;
        int len;
+
        switch (uLevel) {
                case 0:
                        struct_len = 16;
@@ -1295,7 +1369,7 @@ static int fill_srv_info(struct srv_info_struct *service,
                default:
                        return -1;
        }
+
        if (!buf) {
                len = 0;
                switch (uLevel) {
@@ -1308,7 +1382,7 @@ static int fill_srv_info(struct srv_info_struct *service,
                *stringspace = len;
                return struct_len + len;
        }
-  
+
        len = struct_len;
        p = *buf;
        if (*buflen < struct_len) {
@@ -1324,7 +1398,7 @@ static int fill_srv_info(struct srv_info_struct *service,
        if (!baseaddr) {
                baseaddr = p;
        }
-  
+
        switch (uLevel) {
                case 0:
                        push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
@@ -1351,9 +1425,9 @@ static int fill_srv_info(struct srv_info_struct *service,
 }
 
 
-static bool srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
+static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
 {
-       return(strcmp(s1->name,s2->name));
+       return strcasecmp_m(s1->name,s2->name);
 }
 
 /****************************************************************************
@@ -1361,10 +1435,11 @@ static bool srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
  extracted from lists saved by nmbd on the local host.
 ****************************************************************************/
 
-static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
+static bool api_RNetServerEnum2(struct smbd_server_connection *sconn,
+                               connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
-                               int mdrcnt, int mprcnt, char **rdata, 
+                               int mdrcnt, int mprcnt, char **rdata,
                                char **rparam, int *rdata_len, int *rparam_len)
 {
        char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
@@ -1396,9 +1471,9 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
        }
 
        /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
-          any other bit (they may just set this bit on its own) they 
-          want all the locally seen servers. However this bit can be 
-          set on its own so set the requested servers to be 
+          any other bit (they may just set this bit on its own) they
+          want all the locally seen servers. However this bit can be
+          set on its own so set the requested servers to be
           ALL - DOMAIN_ENUM. */
 
        if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
@@ -1413,10 +1488,10 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
        if (!prefix_ok(str1,"WrLehD")) {
                return False;
        }
-       if (!check_server_info(uLevel,str2)) {
+       if (!check_session_info(uLevel,str2)) {
                return False;
        }
-  
+
        DEBUG(4, ("server request level: %s %8x ", str2, servertype));
        DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
        DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
@@ -1430,16 +1505,16 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
                fstrcpy(domain, lp_workgroup());
        }
 
+       DEBUG(4, ("domain [%s]\n", domain));
+
        if (lp_browse_list()) {
-               total = get_server_info(servertype,&servers,domain);
+               total = get_session_info(servertype,&servers,domain);
        }
 
        data_len = fixed_len = string_len = 0;
        missed = 0;
 
-       if (total > 0) {
-               qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
-       }
+       TYPESAFE_QSORT(servers, total, srv_comp);
 
        {
                char *lastname=NULL;
@@ -1452,10 +1527,10 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
                        }
                        lastname = s->name;
                        data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
-                       DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
-                               s->name, s->type, s->comment, s->domain));
-      
-                       if (data_len <= buf_len) {
+                       DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
+                               i, s->name, s->type, s->comment, s->domain));
+
+                       if (data_len < buf_len) {
                                counted++;
                                fixed_len += f_len;
                                string_len += s_len;
@@ -1470,7 +1545,7 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
        if (!*rdata) {
                return False;
        }
-  
+
        p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
        p = *rdata;
        f_len = fixed_len;
@@ -1488,12 +1563,12 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
                        }
                        lastname = s->name;
                        fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
-                       DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
-                               s->name, s->type, s->comment, s->domain));
+                       DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
+                               i, s->name, s->type, s->comment, s->domain));
                        count2--;
                }
        }
-  
+
        *rparam_len = 8;
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
@@ -1506,71 +1581,281 @@ static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
 
        SAFE_FREE(servers);
 
-       DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
+       DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
                domain,uLevel,counted,counted+missed));
 
        return True;
 }
 
-/****************************************************************************
-  command 0x34 - suspected of being a "Lookup Names" stub api
-  ****************************************************************************/
+static int srv_name_match(const char *n1, const char *n2)
+{
+       /*
+        * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
+        *
+        *  In Windows, FirstNameToReturn need not be an exact match:
+        *  the server will return a list of servers that exist on
+        *  the network greater than or equal to the FirstNameToReturn.
+        */
+       int ret = strcasecmp_m(n1, n2);
+
+       if (ret <= 0) {
+               return 0;
+       }
+
+       return ret;
+}
 
-static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
+static bool api_RNetServerEnum3(struct smbd_server_connection *sconn,
+                               connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
-                               int mdrcnt, int mprcnt, char **rdata, 
+                               int mdrcnt, int mprcnt, char **rdata,
                                char **rparam, int *rdata_len, int *rparam_len)
 {
-       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
        char *str2 = skip_string(param,tpscnt,str1);
        char *p = skip_string(param,tpscnt,str2);
-       int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
-       int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
-       int counted=0;
-       int missed=0;
+       int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
+       int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
+       uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
+       char *p2;
+       int data_len, fixed_len, string_len;
+       int f_len = 0, s_len = 0;
+       struct srv_info_struct *servers=NULL;
+       int counted=0,first=0,total=0;
+       int i,missed;
+       fstring domain;
+       fstring first_name;
+       bool domain_request;
+       bool local_request;
 
        if (!str1 || !str2 || !p) {
                return False;
        }
 
-       DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
-               str1, str2, p, uLevel, buf_len));
+       /* If someone sets all the bits they don't really mean to set
+          DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
+          known servers. */
 
-       if (!prefix_ok(str1,"zWrLeh")) {
+       if (servertype == SV_TYPE_ALL) {
+               servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+       }
+
+       /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
+          any other bit (they may just set this bit on its own) they
+          want all the locally seen servers. However this bit can be
+          set on its own so set the requested servers to be
+          ALL - DOMAIN_ENUM. */
+
+       if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
+               servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
+       }
+
+       domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
+       local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
+
+       p += 8;
+
+       if (strcmp(str1, "WrLehDzz") != 0) {
+               return false;
+       }
+       if (!check_session_info(uLevel,str2)) {
                return False;
        }
-  
-       *rdata_len = 0;
-  
-       *rparam_len = 8;
-       *rparam = smb_realloc_limit(*rparam,*rparam_len);
-       if (!*rparam) {
+
+       DEBUG(4, ("server request level: %s %8x ", str2, servertype));
+       DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
+       DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
+
+       if (skip_string(param,tpscnt,p) == NULL) {
+               return False;
+       }
+       pull_ascii_fstring(domain, p);
+       if (domain[0] == '\0') {
+               fstrcpy(domain, lp_workgroup());
+       }
+       p = skip_string(param,tpscnt,p);
+       if (skip_string(param,tpscnt,p) == NULL) {
                return False;
        }
+       pull_ascii_fstring(first_name, p);
 
-       SSVAL(*rparam,0,0x08AC); /* informational warning message */
-       SSVAL(*rparam,2,0);
-       SSVAL(*rparam,4,counted);
-       SSVAL(*rparam,6,counted+missed);
+       DEBUG(4, ("domain: '%s' first_name: '%s'\n",
+                 domain, first_name));
 
-       return True;
-}
+       if (lp_browse_list()) {
+               total = get_session_info(servertype,&servers,domain);
+       }
 
-/****************************************************************************
-  get info about a share
-  ****************************************************************************/
+       data_len = fixed_len = string_len = 0;
+       missed = 0;
 
-static bool check_share_info(int uLevel, char* id)
-{
-       switch( uLevel ) {
-               case 0:
-                       if (strcmp(id,"B13") != 0) {
-                               return False;
-                       }
-                       break;
+       TYPESAFE_QSORT(servers, total, srv_comp);
+
+       if (first_name[0] != '\0') {
+               struct srv_info_struct *first_server = NULL;
+
+               BINARY_ARRAY_SEARCH(servers, total, name, first_name,
+                                   srv_name_match, first_server);
+               if (first_server) {
+                       first = PTR_DIFF(first_server, servers) / sizeof(*servers);
+                       /*
+                        * The binary search may not find the exact match
+                        * so we need to search backward to find the first match
+                        *
+                        * This implements the strange matching windows
+                        * implements. (see the comment in srv_name_match().
+                        */
+                       for (;first > 0;) {
+                               int ret;
+                               ret = strcasecmp_m(first_name,
+                                                servers[first-1].name);
+                               if (ret > 0) {
+                                       break;
+                               }
+                               first--;
+                       }
+               } else {
+                       /* we should return no entries */
+                       first = total;
+               }
+       }
+
+       {
+               char *lastname=NULL;
+
+               for (i=first;i<total;i++) {
+                       struct srv_info_struct *s = &servers[i];
+
+                       if (lastname && strequal(lastname,s->name)) {
+                               continue;
+                       }
+                       lastname = s->name;
+                       data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
+                       DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
+                               i, s->name, s->type, s->comment, s->domain));
+
+                       if (data_len < buf_len) {
+                               counted++;
+                               fixed_len += f_len;
+                               string_len += s_len;
+                       } else {
+                               missed++;
+                       }
+               }
+       }
+
+       *rdata_len = fixed_len + string_len;
+       *rdata = smb_realloc_limit(*rdata,*rdata_len);
+       if (!*rdata) {
+               return False;
+       }
+
+       p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
+       p = *rdata;
+       f_len = fixed_len;
+       s_len = string_len;
+
+       {
+               char *lastname=NULL;
+               int count2 = counted;
+
+               for (i = first; i < total && count2;i++) {
+                       struct srv_info_struct *s = &servers[i];
+
+                       if (lastname && strequal(lastname,s->name)) {
+                               continue;
+                       }
+                       lastname = s->name;
+                       fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
+                       DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
+                               i, s->name, s->type, s->comment, s->domain));
+                       count2--;
+               }
+       }
+
+       *rparam_len = 8;
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
+       SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,counted);
+       SSVAL(*rparam,6,counted+missed);
+
+       DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
+               domain,uLevel,first,first_name,
+               first < total ? servers[first].name : "",
+               counted,counted+missed));
+
+       SAFE_FREE(servers);
+
+       return True;
+}
+
+/****************************************************************************
+  command 0x34 - suspected of being a "Lookup Names" stub api
+  ****************************************************************************/
+
+static bool api_RNetGroupGetUsers(struct smbd_server_connection *sconn,
+                                 connection_struct *conn, uint16 vuid,
+                               char *param, int tpscnt,
+                               char *data, int tdscnt,
+                               int mdrcnt, int mprcnt, char **rdata,
+                               char **rparam, int *rdata_len, int *rparam_len)
+{
+       char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+       char *str2 = skip_string(param,tpscnt,str1);
+       char *p = skip_string(param,tpscnt,str2);
+       int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+       int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
+       int counted=0;
+       int missed=0;
+
+       if (!str1 || !str2 || !p) {
+               return False;
+       }
+
+       DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
+               str1, str2, p, uLevel, buf_len));
+
+       if (!prefix_ok(str1,"zWrLeh")) {
+               return False;
+       }
+
+       *rdata_len = 0;
+
+       *rparam_len = 8;
+       *rparam = smb_realloc_limit(*rparam,*rparam_len);
+       if (!*rparam) {
+               return False;
+       }
+
+       SSVAL(*rparam,0,0x08AC); /* informational warning message */
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,counted);
+       SSVAL(*rparam,6,counted+missed);
+
+       return True;
+}
+
+/****************************************************************************
+  get info about a share
+  ****************************************************************************/
+
+static bool check_share_info(int uLevel, char* id)
+{
+       switch( uLevel ) {
+               case 0:
+                       if (strcmp(id,"B13") != 0) {
+                               return False;
+                       }
+                       break;
                case 1:
-                       if (strcmp(id,"B13BWz") != 0) {
+                       /* Level-2 descriptor is allowed (and ignored) */
+                       if (strcmp(id,"B13BWz") != 0 &&
+                           strcmp(id,"B13BWzWWWzB9B") != 0) {
                                return False;
                        }
                        break;
@@ -1599,7 +1884,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
        char* p2;
        int l2;
        int len;
+
        switch( uLevel ) {
                case 0:
                        struct_len = 13;
@@ -1616,8 +1901,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                default:
                        return -1;
        }
-  
+
        if (!buf) {
                len = 0;
 
@@ -1635,7 +1919,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                }
                return struct_len + len;
        }
-  
+
        len = struct_len;
        p = *buf;
        if ((*buflen) < struct_len) {
@@ -1653,9 +1937,9 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
        if (!baseaddr) {
                baseaddr = p;
        }
-  
+
        push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
-  
+
        if (uLevel > 0) {
                int type;
 
@@ -1671,7 +1955,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                SIVAL(p,16,PTR_DIFF(p2,baseaddr));
                len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
        }
-  
+
        if (uLevel > 1) {
                SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
                SSVALS(p,22,-1);                /* max uses */
@@ -1680,7 +1964,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
                memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
        }
-  
+
        if (uLevel > 2) {
                memset(p+40,0,SHPWLEN+2);
                SSVAL(p,50,0);
@@ -1691,7 +1975,7 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                SSVAL(p,64,0);
                SSVAL(p,66,0);
        }
-       
+
        if (stringbuf) {
                (*buf) = p + struct_len;
                (*buflen) -= struct_len;
@@ -1705,7 +1989,8 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
        return len;
 }
 
-static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
+static bool api_RNetShareGetInfo(struct smbd_server_connection *sconn,
+                                connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -1714,20 +1999,21 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
 {
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
        char *str2 = skip_string(param,tpscnt,str1);
-       char *netname = skip_string(param,tpscnt,str2);
+       char *netname_in = skip_string(param,tpscnt,str2);
+       char *netname = NULL;
        char *p = skip_string(param,tpscnt,netname);
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        int snum;
-  
-       if (!str1 || !str2 || !netname || !p) {
+
+       if (!str1 || !str2 || !netname_in || !p) {
                return False;
        }
 
-       snum = find_service(netname);
-       if (snum < 0) {
+       snum = find_service(talloc_tos(), netname_in, &netname);
+       if (snum < 0 || !netname) {
                return False;
        }
-  
+
        /* check it's a supported varient */
        if (!prefix_ok(str1,"zWrLh")) {
                return False;
@@ -1735,7 +2021,7 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
        if (!check_share_info(uLevel,str2)) {
                return False;
        }
+
        *rdata = smb_realloc_limit(*rdata,mdrcnt);
        if (!*rdata) {
                return False;
@@ -1745,7 +2031,7 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
        if (*rdata_len < 0) {
                return False;
        }
+
        *rparam_len = 6;
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
@@ -1754,7 +2040,7 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
        SSVAL(*rparam,0,NERR_Success);
        SSVAL(*rparam,2,0);             /* converter word */
        SSVAL(*rparam,4,*rdata_len);
+
        return True;
 }
 
@@ -1768,7 +2054,8 @@ static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
   Share names longer than 12 bytes must be skipped.
  ****************************************************************************/
 
-static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
+static bool api_RNetShareEnum(struct smbd_server_connection *sconn,
+                             connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int                mdrcnt,
@@ -1790,7 +2077,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
        int i;
        int data_len, fixed_len, string_len;
        int f_len = 0, s_len = 0;
+
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -1801,11 +2088,11 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
        if (!check_share_info(uLevel,str2)) {
                return False;
        }
-  
+
        /* Ensure all the usershares are loaded. */
        become_root();
        load_registry_shares();
-       count = load_usershare_shares();
+       count = load_usershare_shares(sconn);
        unbecome_root();
 
        data_len = fixed_len = string_len = 0;
@@ -1819,7 +2106,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
                if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
                        total++;
                        data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
-                       if (data_len <= buf_len) {
+                       if (data_len < buf_len) {
                                counted++;
                                fixed_len += f_len;
                                string_len += s_len;
@@ -1834,7 +2121,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
        if (!*rdata) {
                return False;
        }
+
        p2 = (*rdata) + fixed_len;      /* auxiliary data (strings) will go here */
        p = *rdata;
        f_len = fixed_len;
@@ -1853,7 +2140,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
                        }
                }
        }
-  
+
        *rparam_len = 8;
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
@@ -1863,7 +2150,7 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,counted);
        SSVAL(*rparam,6,total);
-  
+
        DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
                counted,total,uLevel,
                buf_len,*rdata_len,mdrcnt));
@@ -1875,7 +2162,8 @@ static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
   Add a share
   ****************************************************************************/
 
-static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
+static bool api_RNetShareAdd(struct smbd_server_connection *sconn,
+                            connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -1889,12 +2177,18 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
        fstring sharename;
        fstring comment;
        char *pathname = NULL;
-       char *command, *cmdname;
        unsigned int offset;
-       int snum;
        int res = ERRunsup;
        size_t converted_size;
 
+       WERROR werr = WERR_OK;
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       union srvsvc_NetShareInfo info;
+       struct srvsvc_NetShareInfo2 info2;
+       struct dcerpc_binding_handle *b;
+
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -1915,11 +2209,6 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
                return False;
        }
        pull_ascii_fstring(sharename,data);
-       snum = find_service(sharename);
-       if (snum >= 0) { /* already exists */
-               res = ERRfilexists;
-               goto error_exit;
-       }
 
        if (mdrcnt < 28) {
                return False;
@@ -1933,7 +2222,7 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
        offset = IVAL(data, 16);
        if (offset >= mdrcnt) {
                res = ERRinvalidparam;
-               goto error_exit;
+               goto out;
        }
 
        /* Do we have a string ? */
@@ -1946,7 +2235,7 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
 
        if (offset >= mdrcnt) {
                res = ERRinvalidparam;
-               goto error_exit;
+               goto out;
        }
 
        /* Do we have a string ? */
@@ -1965,34 +2254,44 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
                return false;
        }
 
-       string_replace(sharename, '"', ' ');
-       string_replace(pathname, '"', ' ');
-       string_replace(comment, '"', ' ');
-
-       cmdname = lp_add_share_cmd();
-
-       if (!cmdname || *cmdname == '\0') {
-               return False;
+       status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id,
+                                       conn->session_info,
+                                       &conn->sconn->client_id,
+                                       conn->sconn->msg_ctx,
+                                       &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
+                         nt_errstr(status)));
+               res = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
        }
 
-       if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
-                    lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
-                    pathname, comment) == -1) {
-               return false;
-       }
+       b = cli->binding_handle;
 
-       DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
+       info2.name              = sharename;
+       info2.type              = STYPE_DISKTREE;
+       info2.comment           = comment;
+       info2.permissions       = 0;
+       info2.max_users         = 0;
+       info2.current_users     = 0;
+       info2.path              = pathname;
+       info2.password          = NULL;
 
-       if ((res = smbrun(command, NULL)) != 0) {
-               DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
-                        command, res ));
-               SAFE_FREE(command);
-               res = ERRnoaccess;
-               goto error_exit;
-       } else {
-               SAFE_FREE(command);
-               message_send_all(smbd_messaging_context(),
-                                MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
+       info.info2 = &info2;
+
+       status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
+                                          cli->srv_name_slash,
+                                          2,
+                                          &info,
+                                          NULL,
+                                          &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               res = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               res = W_ERROR_V(werr);
+               goto out;
        }
 
        *rparam_len = 6;
@@ -2004,10 +2303,10 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
        SSVAL(*rparam,2,0);             /* converter word */
        SSVAL(*rparam,4,*rdata_len);
        *rdata_len = 0;
-  
+
        return True;
 
-  error_exit:
+  out:
 
        *rparam_len = 4;
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
@@ -2024,7 +2323,8 @@ static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
   view list of groups available
   ****************************************************************************/
 
-static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
+static bool api_RNetGroupEnum(struct smbd_server_connection *sconn,
+                             connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2038,11 +2338,13 @@ static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
        char *str2 = skip_string(param,tpscnt,str1);
        char *p = skip_string(param,tpscnt,str2);
 
-       struct pdb_search *search;
-       struct samr_displayentry *entries;
+       uint32_t num_groups;
+       uint32_t resume_handle;
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle samr_handle, domain_handle;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b;
 
-       int num_entries;
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -2051,9 +2353,9 @@ static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
                return False;
        }
 
-       /* parameters  
+       /* parameters
         * W-> resume context (number of users to skip)
-        * r -> return parameter pointer to receive buffer 
+        * r -> return parameter pointer to receive buffer
         * L -> length of receive buffer
         * e -> return parameter number of entries
         * h -> return parameter total number of users
@@ -2063,14 +2365,47 @@ static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
                return False;
        }
 
-       /* get list of domain groups SID_DOMAIN_GRP=2 */
-       become_root();
-       search = pdb_search_groups();
-       unbecome_root();
+       status = rpc_pipe_open_interface(
+               talloc_tos(), &ndr_table_samr.syntax_id,
+               conn->session_info, &conn->sconn->client_id,
+               conn->sconn->msg_ctx, &samr_pipe);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
+                         nt_errstr(status)));
+               return false;
+       }
 
-       if (search == NULL) {
-               DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
-               return False;
+       b = samr_pipe->binding_handle;
+
+       status = dcerpc_samr_Connect2(b, talloc_tos(), global_myname(),
+                                     SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
+                                     &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
+                         nt_errstr(status)));
+               return false;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
+                         nt_errstr(result)));
+               return false;
+       }
+
+       status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
+                                       SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
+                                       get_global_sam_sid(), &domain_handle,
+                                       &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
+                         nt_errstr(status)));
+               dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
+               return false;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
+                         nt_errstr(result)));
+               dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
+               return false;
        }
 
        resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
@@ -2078,11 +2413,6 @@ static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
        DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
                  "%d\n", resume_context, cli_buf_size));
 
-       become_root();
-       num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
-                                        &entries);
-       unbecome_root();
-
        *rdata_len = cli_buf_size;
        *rdata = smb_realloc_limit(*rdata,*rdata_len);
        if (!*rdata) {
@@ -2091,25 +2421,70 @@ static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
 
        p = *rdata;
 
-       for(i=0; i<num_entries; i++) {
-               fstring name;
-               fstrcpy(name, entries[i].account_name);
-               if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
+       errflags = NERR_Success;
+       num_groups = 0;
+       resume_handle = 0;
+
+       while (true) {
+               struct samr_SamArray *sam_entries;
+               uint32_t num_entries;
+
+               status = dcerpc_samr_EnumDomainGroups(b, talloc_tos(),
+                                                     &domain_handle,
+                                                     &resume_handle,
+                                                     &sam_entries, 1,
+                                                     &num_entries,
+                                                     &result);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
+                                  "%s\n", nt_errstr(status)));
+                       break;
+               }
+               if (!NT_STATUS_IS_OK(result)) {
+                       status = result;
+                       DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
+                                  "%s\n", nt_errstr(result)));
+                       break;
+               }
+
+               if (num_entries == 0) {
+                       DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
+                                  "no entries -- done\n"));
+                       break;
+               }
+
+               for(i=0; i<num_entries; i++) {
+                       const char *name;
+
+                       name = sam_entries->entries[i].name.string;
+
+                       if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
+                               /* set overflow error */
+                               DEBUG(3,("overflow on entry %d group %s\n", i,
+                                        name));
+                               errflags=234;
+                               break;
+                       }
+
                        /* truncate the name at 21 chars. */
-                       memcpy(p, name, 21); 
+                       memset(p, 0, 21);
+                       strlcpy(p, name, 21);
                        DEBUG(10,("adding entry %d group %s\n", i, p));
                        p += 21;
-                       p += 5; /* Both NT4 and W2k3SP1 do padding here.
-                                  No idea why... */
-               } else {
-                       /* set overflow error */
-                       DEBUG(3,("overflow on entry %d group %s\n", i, name));
-                       errflags=234;
+                       p += 5; /* Both NT4 and W2k3SP1 do padding here.  No
+                                * idea why... */
+                       num_groups += 1;
+               }
+
+               if (errflags != NERR_Success) {
                        break;
                }
+
+               TALLOC_FREE(sam_entries);
        }
 
-       pdb_search_destroy(search);
+       dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
+       dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
 
        *rdata_len = PTR_DIFF(p,*rdata);
 
@@ -2120,8 +2495,8 @@ static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
        }
        SSVAL(*rparam, 0, errflags);
        SSVAL(*rparam, 2, 0);           /* converter word */
-       SSVAL(*rparam, 4, i);   /* is this right?? */
-       SSVAL(*rparam, 6, resume_context+num_entries);  /* is this right?? */
+       SSVAL(*rparam, 4, num_groups);  /* is this right?? */
+       SSVAL(*rparam, 6, resume_context+num_groups);   /* is this right?? */
 
        return(True);
 }
@@ -2130,7 +2505,8 @@ static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
  Get groups that a user is a member of.
 ******************************************************************/
 
-static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
+static bool api_NetUserGetGroups(struct smbd_server_connection *sconn,
+                                connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2144,17 +2520,18 @@ static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
        int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
        const char *level_string;
        int count=0;
-       struct samu *sampw = NULL;
        bool ret = False;
-       DOM_SID *sids;
-       gid_t *gids;
-       size_t num_groups;
-       size_t i;
-       NTSTATUS result;
-       DOM_SID user_sid;
-       enum lsa_SidType type;
+       uint32_t i;
        char *endp = NULL;
-       TALLOC_CTX *mem_ctx;
+
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle samr_handle, domain_handle, user_handle;
+       struct lsa_String name;
+       struct lsa_Strings names;
+       struct samr_Ids type, rid;
+       struct samr_RidWithAttributeArray *rids;
+       NTSTATUS status, result;
+       struct dcerpc_binding_handle *b;
 
        if (!str1 || !str2 || !UserName || !p) {
                return False;
@@ -2194,59 +2571,109 @@ static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
        p = *rdata;
        endp = *rdata + *rdata_len;
 
-       mem_ctx = talloc_new(NULL);
-       if (mem_ctx == NULL) {
-               DEBUG(0, ("talloc_new failed\n"));
-               return False;
+       status = rpc_pipe_open_interface(
+               talloc_tos(), &ndr_table_samr.syntax_id,
+               conn->session_info, &conn->sconn->client_id,
+               conn->sconn->msg_ctx, &samr_pipe);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
+                         nt_errstr(status)));
+               return false;
        }
 
-       if ( !(sampw = samu_new(mem_ctx)) ) {
-               DEBUG(0, ("samu_new() failed!\n"));
-               TALLOC_FREE(mem_ctx);
-               return False;
+       b = samr_pipe->binding_handle;
+
+       status = dcerpc_samr_Connect2(b, talloc_tos(), global_myname(),
+                                     SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
+                                     &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
+                         nt_errstr(status)));
+               return false;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
+                         nt_errstr(result)));
+               return false;
        }
 
-       /* Lookup the user information; This should only be one of
-          our accounts (not remote domains) */
+       status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
+                                       SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+                                       get_global_sam_sid(), &domain_handle,
+                                       &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
+                         nt_errstr(status)));
+               goto close_sam;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
+                         nt_errstr(result)));
+               goto close_sam;
+       }
 
-       become_root();                                  /* ROOT BLOCK */
+       name.string = UserName;
 
-       if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
-                        NULL, NULL, &user_sid, &type)) {
-               DEBUG(10, ("lookup_name(%s) failed\n", UserName));
-               goto done;
+       status = dcerpc_samr_LookupNames(b, talloc_tos(),
+                                        &domain_handle, 1, &name,
+                                        &rid, &type,
+                                        &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
+                         nt_errstr(status)));
+               goto close_domain;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
+                         nt_errstr(result)));
+               goto close_domain;
        }
 
-       if (type != SID_NAME_USER) {
+       if (type.ids[0] != SID_NAME_USER) {
                DEBUG(10, ("%s is a %s, not a user\n", UserName,
-                          sid_type_lookup(type)));
-               goto done;
+                          sid_type_lookup(type.ids[0])));
+               goto close_domain;
        }
 
-       if ( !pdb_getsampwsid(sampw, &user_sid) ) {
-               DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
-                          sid_string_dbg(&user_sid), UserName));
-               goto done;
+       status = dcerpc_samr_OpenUser(b, talloc_tos(),
+                                     &domain_handle,
+                                     SAMR_USER_ACCESS_GET_GROUPS,
+                                     rid.ids[0], &user_handle,
+                                     &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
+                         nt_errstr(status)));
+               goto close_domain;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
+                         nt_errstr(result)));
+               goto close_domain;
        }
 
-       gids = NULL;
-       sids = NULL;
-       num_groups = 0;
-
-       result = pdb_enum_group_memberships(mem_ctx, sampw,
-                                           &sids, &gids, &num_groups);
-
+       status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
+                                             &user_handle, &rids,
+                                             &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
+                         nt_errstr(status)));
+               goto close_user;
+       }
        if (!NT_STATUS_IS_OK(result)) {
-               DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
-                          UserName));
-               goto done;
+               DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
+                         nt_errstr(result)));
+               goto close_user;
        }
 
-       for (i=0; i<num_groups; i++) {
-               const char *grp_name;
+       for (i=0; i<rids->count; i++) {
 
-               if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
-                       strlcpy(p, grp_name, PTR_DIFF(endp,p));
+               status = dcerpc_samr_LookupRids(b, talloc_tos(),
+                                               &domain_handle,
+                                               1, &rids->rids[i].rid,
+                                               &names, &type,
+                                               &result);
+               if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result) && (names.count == 1)) {
+                       strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
                        p += 21;
                        count++;
                }
@@ -2259,10 +2686,12 @@ static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
 
        ret = True;
 
-done:
-       unbecome_root();                                /* END ROOT BLOCK */
-
-       TALLOC_FREE(mem_ctx);
+ close_user:
+       dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
+ close_domain:
+       dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
+ close_sam:
+       dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
 
        return ret;
 }
@@ -2271,7 +2700,8 @@ done:
  Get all users.
 ******************************************************************/
 
-static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
+static bool api_RNetUserEnum(struct smbd_server_connection *sconn,
+                            connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2282,14 +2712,19 @@ static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
        int num_users=0;
        int errflags=0;
        int i, resume_context, cli_buf_size;
-       struct pdb_search *search;
-       struct samr_displayentry *users;
+       uint32_t resume_handle;
+
+       struct rpc_pipe_client *samr_pipe;
+       struct policy_handle samr_handle, domain_handle;
+       NTSTATUS status, result;
 
        char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
        char *str2 = skip_string(param,tpscnt,str1);
        char *p = skip_string(param,tpscnt,str2);
        char *endp = NULL;
 
+       struct dcerpc_binding_handle *b;
+
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -2328,40 +2763,111 @@ static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
        p = *rdata;
        endp = *rdata + *rdata_len;
 
-       become_root();
-       search = pdb_search_users(ACB_NORMAL);
-       unbecome_root();
-       if (search == NULL) {
-               DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
-               return False;
+       status = rpc_pipe_open_interface(
+               talloc_tos(), &ndr_table_samr.syntax_id,
+               conn->session_info, &conn->sconn->client_id,
+               conn->sconn->msg_ctx, &samr_pipe);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
+                         nt_errstr(status)));
+               return false;
        }
 
-       become_root();
-       num_users = pdb_search_entries(search, resume_context, 0xffffffff,
-                                      &users);
-       unbecome_root();
+       b = samr_pipe->binding_handle;
+
+       status = dcerpc_samr_Connect2(b, talloc_tos(), global_myname(),
+                                     SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
+                                     &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
+                         nt_errstr(status)));
+               return false;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
+                         nt_errstr(result)));
+               return false;
+       }
+
+       status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
+                                       SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
+                                       get_global_sam_sid(), &domain_handle,
+                                       &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
+                         nt_errstr(status)));
+               dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
+               return false;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
+                         nt_errstr(result)));
+               dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
+               return false;
+       }
 
        errflags=NERR_Success;
 
-       for (i=0; i<num_users; i++) {
-               const char *name = users[i].account_name;
+       resume_handle = 0;
 
-               if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
-                       strlcpy(p,name,PTR_DIFF(endp,p));
-                       DEBUG(10,("api_RNetUserEnum:adding entry %d username "
-                                 "%s\n",count_sent,p));
-                       p += 21;
-                       count_sent++;
-               } else {
-                       /* set overflow error */
-                       DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
-                                 "username %s\n",count_sent,name));
-                       errflags=234;
+       while (true) {
+               struct samr_SamArray *sam_entries;
+               uint32_t num_entries;
+
+               status = dcerpc_samr_EnumDomainUsers(b, talloc_tos(),
+                                                    &domain_handle,
+                                                    &resume_handle,
+                                                    0, &sam_entries, 1,
+                                                    &num_entries,
+                                                    &result);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
+                                  "%s\n", nt_errstr(status)));
+                       break;
+               }
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
+                                  "%s\n", nt_errstr(result)));
+                       break;
+               }
+
+               if (num_entries == 0) {
+                       DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
+                                  "no entries -- done\n"));
                        break;
                }
+
+               for (i=0; i<num_entries; i++) {
+                       const char *name;
+
+                       name = sam_entries->entries[i].name.string;
+
+                       if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
+                          &&(strlen(name)<=21)) {
+                               strlcpy(p,name,PTR_DIFF(endp,p));
+                               DEBUG(10,("api_RNetUserEnum:adding entry %d "
+                                         "username %s\n",count_sent,p));
+                               p += 21;
+                               count_sent++;
+                       } else {
+                               /* set overflow error */
+                               DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
+                                         "username %s\n",count_sent,name));
+                               errflags=234;
+                               break;
+                       }
+               }
+
+               if (errflags != NERR_Success) {
+                       break;
+               }
+
+               TALLOC_FREE(sam_entries);
        }
 
-       pdb_search_destroy(search);
+       dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
+       dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
 
        *rdata_len = PTR_DIFF(p,*rdata);
 
@@ -2377,7 +2883,8 @@ static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
  Get the time of day info.
 ****************************************************************************/
 
-static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
+static bool api_NetRemoteTOD(struct smbd_server_connection *sconn,
+                            connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2409,7 +2916,7 @@ static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
                                            by NT in a "net time" operation,
                                            it seems to ignore the one below */
 
-       /* the client expects to get localtime, not GMT, in this bit 
+       /* the client expects to get localtime, not GMT, in this bit
                (I think, this needs testing) */
        t = localtime(&unixdate);
        if (!t) {
@@ -2435,7 +2942,8 @@ static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
  Set the user password.
 *****************************************************************************/
 
-static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
+static bool api_SetUserPassword(struct smbd_server_connection *sconn,
+                               connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2446,6 +2954,22 @@ static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
        char *p = NULL;
        fstring user;
        fstring pass1,pass2;
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       NTSTATUS status, result;
+       struct rpc_pipe_client *cli = NULL;
+       struct policy_handle connect_handle, domain_handle, user_handle;
+       struct lsa_String domain_name;
+       struct dom_sid2 *domain_sid;
+       struct lsa_String names;
+       struct samr_Ids rids;
+       struct samr_Ids types;
+       struct samr_Password old_lm_hash;
+       struct samr_Password new_lm_hash;
+       int errcode = NERR_badpass;
+       uint32_t rid;
+       int encrypted;
+       int min_pwd_length;
+       struct dcerpc_binding_handle *b = NULL;
 
        /* Skip 2 strings. */
        p = skip_string(param,tpscnt,np);
@@ -2478,6 +3002,18 @@ static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
        memcpy(pass1,p,16);
        memcpy(pass2,p+16,16);
 
+       encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1);
+       if (encrypted == -1) {
+               errcode = W_ERROR_V(WERR_INVALID_PARAM);
+               goto out;
+       }
+
+       min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1);
+       if (min_pwd_length == -1) {
+               errcode = W_ERROR_V(WERR_INVALID_PARAM);
+               goto out;
+       }
+
        *rparam_len = 4;
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
@@ -2486,59 +3022,172 @@ static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
 
        *rdata_len = 0;
 
-       SSVAL(*rparam,0,NERR_badpass);
-       SSVAL(*rparam,2,0);             /* converter word */
+       DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
+               user, encrypted, min_pwd_length));
+
+       ZERO_STRUCT(connect_handle);
+       ZERO_STRUCT(domain_handle);
+       ZERO_STRUCT(user_handle);
+
+       status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id,
+                                       conn->session_info,
+                                       &conn->sconn->client_id,
+                                       conn->sconn->msg_ctx,
+                                       &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
+                         nt_errstr(status)));
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
 
-       DEBUG(3,("Set password for <%s>\n",user));
+       b = cli->binding_handle;
 
-       /*
-        * Attempt to verify the old password against smbpasswd entries
-        * Win98 clients send old and new password in plaintext for this call.
-        */
+       status = dcerpc_samr_Connect2(b, mem_ctx,
+                                     global_myname(),
+                                     SAMR_ACCESS_CONNECT_TO_SERVER |
+                                     SAMR_ACCESS_ENUM_DOMAINS |
+                                     SAMR_ACCESS_LOOKUP_DOMAIN,
+                                     &connect_handle,
+                                     &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
 
-       {
-               auth_serversupplied_info *server_info = NULL;
-               DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
+       init_lsa_String(&domain_name, get_global_sam_name());
 
-               if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
+       status = dcerpc_samr_LookupDomain(b, mem_ctx,
+                                         &connect_handle,
+                                         &domain_name,
+                                         &domain_sid,
+                                         &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
 
-                       become_root();
-                       if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
-                               SSVAL(*rparam,0,NERR_Success);
-                       }
-                       unbecome_root();
+       status = dcerpc_samr_OpenDomain(b, mem_ctx,
+                                       &connect_handle,
+                                       SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+                                       domain_sid,
+                                       &domain_handle,
+                                       &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
 
-                       TALLOC_FREE(server_info);
-               }
-               data_blob_clear_free(&password);
+       init_lsa_String(&names, user);
+
+       status = dcerpc_samr_LookupNames(b, mem_ctx,
+                                        &domain_handle,
+                                        1,
+                                        &names,
+                                        &rids,
+                                        &types,
+                                        &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
        }
 
-       /*
-        * If the plaintext change failed, attempt
-        * the old encrypted method. NT will generate this
-        * after trying the samr method. Note that this
-        * method is done as a last resort as this
-        * password change method loses the NT password hash
-        * and cannot change the UNIX password as no plaintext
-        * is received.
-        */
+       if (rids.count != 1) {
+               errcode = W_ERROR_V(WERR_NO_SUCH_USER);
+               goto out;
+       }
+       if (rids.count != types.count) {
+               errcode = W_ERROR_V(WERR_INVALID_PARAM);
+               goto out;
+       }
+       if (types.ids[0] != SID_NAME_USER) {
+               errcode = W_ERROR_V(WERR_INVALID_PARAM);
+               goto out;
+       }
 
-       if(SVAL(*rparam,0) != NERR_Success) {
-               struct samu *hnd = NULL;
+       rid = rids.ids[0];
 
-               if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
-                       become_root();
-                       if (change_lanman_password(hnd,(uchar *)pass2)) {
-                               SSVAL(*rparam,0,NERR_Success);
-                       }
-                       unbecome_root();
-                       TALLOC_FREE(hnd);
-               }
+       status = dcerpc_samr_OpenUser(b, mem_ctx,
+                                     &domain_handle,
+                                     SAMR_USER_ACCESS_CHANGE_PASSWORD,
+                                     rid,
+                                     &user_handle,
+                                     &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
+
+       if (encrypted == 0) {
+               E_deshash(pass1, old_lm_hash.hash);
+               E_deshash(pass2, new_lm_hash.hash);
+       } else {
+               ZERO_STRUCT(old_lm_hash);
+               ZERO_STRUCT(new_lm_hash);
+               memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16));
+               memcpy(new_lm_hash.hash, pass1, MIN(strlen(pass2), 16));
+       }
+
+       status = dcerpc_samr_ChangePasswordUser(b, mem_ctx,
+                                               &user_handle,
+                                               true, /* lm_present */
+                                               &old_lm_hash,
+                                               &new_lm_hash,
+                                               false, /* nt_present */
+                                               NULL, /* old_nt_crypted */
+                                               NULL, /* new_nt_crypted */
+                                               false, /* cross1_present */
+                                               NULL, /* nt_cross */
+                                               false, /* cross2_present */
+                                               NULL, /* lm_cross */
+                                               &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
+
+       errcode = NERR_Success;
+ out:
+
+       if (b && is_valid_policy_hnd(&user_handle)) {
+               dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
+       }
+       if (b && is_valid_policy_hnd(&domain_handle)) {
+               dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result);
+       }
+       if (b && is_valid_policy_hnd(&connect_handle)) {
+               dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result);
        }
 
        memset((char *)pass1,'\0',sizeof(fstring));
-       memset((char *)pass2,'\0',sizeof(fstring));      
-        
+       memset((char *)pass2,'\0',sizeof(fstring));
+
+       SSVAL(*rparam,0,errcode);
+       SSVAL(*rparam,2,0);             /* converter word */
        return(True);
 }
 
@@ -2546,7 +3195,8 @@ static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
   Set the user password (SamOEM version - gets plaintext).
 ****************************************************************************/
 
-static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
+static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn,
+                                    connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2555,7 +3205,18 @@ static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
 {
        fstring user;
        char *p = get_safe_str_ptr(param,tpscnt,param,2);
-       *rparam_len = 2;
+
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       NTSTATUS status, result;
+       struct rpc_pipe_client *cli = NULL;
+       struct lsa_AsciiString server, account;
+       struct samr_CryptPassword password;
+       struct samr_Password hash;
+       int errcode = NERR_badpass;
+       int bufsize;
+       struct dcerpc_binding_handle *b;
+
+       *rparam_len = 4;
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
                return False;
@@ -2605,26 +3266,67 @@ static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
 
        DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
 
-       /*
-        * Pass the user through the NT -> unix user mapping
-        * function.
-        */
+       if (tdscnt != 532) {
+               errcode = W_ERROR_V(WERR_INVALID_PARAM);
+               goto out;
+       }
 
-       (void)map_username(user);
+       bufsize = get_safe_SVAL(param,tpscnt,p,0,-1);
+       if (bufsize != 532) {
+               errcode = W_ERROR_V(WERR_INVALID_PARAM);
+               goto out;
+       }
 
-       if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
-               SSVAL(*rparam,0,NERR_Success);
+       memcpy(password.data, data, 516);
+       memcpy(hash.hash, data+516, 16);
+
+       status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id,
+                                       conn->session_info,
+                                       &conn->sconn->client_id,
+                                       conn->sconn->msg_ctx,
+                                       &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
+                         nt_errstr(status)));
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
        }
 
+       b = cli->binding_handle;
+
+       init_lsa_AsciiString(&server, global_myname());
+       init_lsa_AsciiString(&account, user);
+
+       status = dcerpc_samr_OemChangePasswordUser2(b, mem_ctx,
+                                                   &server,
+                                                   &account,
+                                                   &password,
+                                                   &hash,
+                                                   &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
+
+       errcode = NERR_Success;
+ out:
+       SSVAL(*rparam,0,errcode);
+       SSVAL(*rparam,2,0);             /* converter word */
+
        return(True);
 }
 
 /****************************************************************************
   delete a print job
-  Form: <W> <> 
+  Form: <W> <>
   ****************************************************************************/
 
-static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
+static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn,
+                               connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2636,11 +3338,18 @@ static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
        char *str2 = skip_string(param,tpscnt,str1);
        char *p = skip_string(param,tpscnt,str2);
        uint32 jobid;
-       int snum;
        fstring sharename;
        int errcode;
        WERROR werr = WERR_OK;
 
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
+       struct policy_handle handle;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       enum spoolss_JobControl command;
+
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -2665,39 +3374,81 @@ static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
        }
        *rdata_len = 0;
 
-       if (!print_job_exists(sharename, jobid)) {
-               errcode = NERR_JobNotFound;
+       ZERO_STRUCT(handle);
+
+       status = rpc_pipe_open_interface(conn,
+                                        &ndr_table_spoolss.syntax_id,
+                                        conn->session_info,
+                                        &conn->sconn->client_id,
+                                        conn->sconn->msg_ctx,
+                                        &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
+                         nt_errstr(status)));
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
                goto out;
        }
+       b = cli->binding_handle;
+
+       ZERO_STRUCT(devmode_ctr);
 
-       snum = lp_servicenumber( sharename);
-       if (snum == -1) {
-               errcode = NERR_DestNotFound;
+       status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
+                                           sharename,
+                                           "RAW",
+                                           devmode_ctr,
+                                           JOB_ACCESS_ADMINISTER,
+                                           &handle,
+                                           &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               errcode = W_ERROR_V(werr);
                goto out;
        }
 
-       errcode = NERR_notsupported;
-       
+       /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
+        * and NERR_DestNotFound if share did not exist */
+
+       errcode = NERR_Success;
+
        switch (function) {
-       case 81:                /* delete */ 
-               if (print_job_delete(conn->server_info, snum, jobid, &werr))
-                       errcode = NERR_Success;
+       case 81:                /* delete */
+               command = SPOOLSS_JOB_CONTROL_DELETE;
                break;
        case 82:                /* pause */
-               if (print_job_pause(conn->server_info, snum, jobid, &werr))
-                       errcode = NERR_Success;
+               command = SPOOLSS_JOB_CONTROL_PAUSE;
                break;
        case 83:                /* resume */
-               if (print_job_resume(conn->server_info, snum, jobid, &werr))
-                       errcode = NERR_Success;
+               command = SPOOLSS_JOB_CONTROL_RESUME;
                break;
+       default:
+               errcode = NERR_notsupported;
+               goto out;
        }
 
-       if (!W_ERROR_IS_OK(werr))
+       status = dcerpc_spoolss_SetJob(b, mem_ctx,
+                                      &handle,
+                                      jobid,
+                                      NULL, /* unique ptr ctr */
+                                      command,
+                                      &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
                errcode = W_ERROR_V(werr);
-       
+               goto out;
+       }
+
  out:
-       SSVAL(*rparam,0,errcode);       
+       if (b && is_valid_policy_hnd(&handle)) {
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
+       }
+
+       SSVAL(*rparam,0,errcode);
        SSVAL(*rparam,2,0);             /* converter word */
 
        return(True);
@@ -2707,7 +3458,8 @@ static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
   Purge a print queue - or pause or resume it.
   ****************************************************************************/
 
-static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
+static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn,
+                               connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2719,8 +3471,17 @@ static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
        char *str2 = skip_string(param,tpscnt,str1);
        char *QueueName = skip_string(param,tpscnt,str2);
        int errcode = NERR_notsupported;
-       int snum;
        WERROR werr = WERR_OK;
+       NTSTATUS status;
+
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
+       struct policy_handle handle;
+       struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct sec_desc_buf secdesc_ctr;
+       enum spoolss_PrinterControl command;
 
        if (!str1 || !str2 || !QueueName) {
                return False;
@@ -2740,34 +3501,88 @@ static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
        if (skip_string(param,tpscnt,QueueName) == NULL) {
                return False;
        }
-       snum = print_queue_snum(QueueName);
 
-       if (snum == -1) {
-               errcode = NERR_JobNotFound;
+       ZERO_STRUCT(handle);
+
+       status = rpc_pipe_open_interface(conn,
+                                        &ndr_table_spoolss.syntax_id,
+                                        conn->session_info,
+                                        &conn->sconn->client_id,
+                                        conn->sconn->msg_ctx,
+                                        &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
+                         nt_errstr(status)));
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       b = cli->binding_handle;
+
+       ZERO_STRUCT(devmode_ctr);
+
+       status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
+                                           QueueName,
+                                           NULL,
+                                           devmode_ctr,
+                                           SEC_FLAG_MAXIMUM_ALLOWED,
+                                           &handle,
+                                           &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               errcode = W_ERROR_V(werr);
                goto out;
        }
 
        switch (function) {
        case 74: /* Pause queue */
-               if (print_queue_pause(conn->server_info, snum, &werr)) {
-                       errcode = NERR_Success;
-               }
+               command = SPOOLSS_PRINTER_CONTROL_PAUSE;
                break;
        case 75: /* Resume queue */
-               if (print_queue_resume(conn->server_info, snum, &werr)) {
-                       errcode = NERR_Success;
-               }
+               command = SPOOLSS_PRINTER_CONTROL_RESUME;
                break;
        case 103: /* Purge */
-               if (print_queue_purge(conn->server_info, snum, &werr)) {
-                       errcode = NERR_Success;
-               }
+               command = SPOOLSS_PRINTER_CONTROL_PURGE;
+               break;
+       default:
+               werr = WERR_NOT_SUPPORTED;
                break;
        }
 
-       if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
+       if (!W_ERROR_IS_OK(werr)) {
+               errcode = W_ERROR_V(werr);
+               goto out;
+       }
+
+       ZERO_STRUCT(info_ctr);
+       ZERO_STRUCT(secdesc_ctr);
+
+       status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
+                                          &handle,
+                                          &info_ctr,
+                                          &devmode_ctr,
+                                          &secdesc_ctr,
+                                          command,
+                                          &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               errcode = W_ERROR_V(werr);
+               goto out;
+       }
+
+       errcode = W_ERROR_V(werr);
 
  out:
+
+       if (b && is_valid_policy_hnd(&handle)) {
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
+       }
+
        SSVAL(*rparam,0,errcode);
        SSVAL(*rparam,2,0);             /* converter word */
 
@@ -2778,8 +3593,8 @@ static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
   set the property of a print job (undocumented?)
   ? function = 0xb -> set name of print job
   ? function = 0x6 -> move print job up/down
-  Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz> 
-  or   <WWsTP> <WB21BB16B10zWWzDDz> 
+  Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
+  or   <WWsTP> <WB21BB16B10zWWzDDz>
 ****************************************************************************/
 
 static int check_printjob_info(struct pack_desc* desc,
@@ -2805,7 +3620,8 @@ static int check_printjob_info(struct pack_desc* desc,
        return True;
 }
 
-static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
+static bool api_PrintJobInfo(struct smbd_server_connection *sconn,
+                            connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2820,7 +3636,18 @@ static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
        fstring sharename;
        int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
        int function = get_safe_SVAL(param,tpscnt,p,4,-1);
-       int place, errcode;
+       int errcode;
+
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       WERROR werr;
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
+       struct policy_handle handle;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct spoolss_JobInfoContainer ctr;
+       union spoolss_JobInfo info;
+       struct spoolss_SetJobInfo1 info1;
 
        if (!str1 || !str2 || !p) {
                return False;
@@ -2840,51 +3667,111 @@ static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
                return False;
        }
 
-       if (!share_defined(sharename)) {
-               DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
-                        sharename));
-               return False;
-       }
-  
        *rdata_len = 0;
-       
+
        /* check it's a supported varient */
-       if ((strcmp(str1,"WWsTP")) || 
+       if ((strcmp(str1,"WWsTP")) ||
            (!check_printjob_info(&desc,uLevel,str2)))
                return(False);
 
-       if (!print_job_exists(sharename, jobid)) {
-               errcode=NERR_JobNotFound;
+       errcode = NERR_notsupported;
+
+       switch (function) {
+       case 0xb:
+               /* change print job name, data gives the name */
+               break;
+       default:
+               goto out;
+       }
+
+       ZERO_STRUCT(handle);
+
+       status = rpc_pipe_open_interface(conn,
+                                        &ndr_table_spoolss.syntax_id,
+                                        conn->session_info,
+                                        &conn->sconn->client_id,
+                                        conn->sconn->msg_ctx,
+                                        &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
+                         nt_errstr(status)));
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
                goto out;
        }
+       b = cli->binding_handle;
 
-       errcode = NERR_notsupported;
+       ZERO_STRUCT(devmode_ctr);
 
-       switch (function) {
-       case 0x6:
-               /* change job place in the queue, 
-                  data gives the new place */
-               place = SVAL(data,0);
-               if (print_job_set_place(sharename, jobid, place)) {
-                       errcode=NERR_Success;
-               }
-               break;
+       status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
+                                           sharename,
+                                           "RAW",
+                                           devmode_ctr,
+                                           PRINTER_ACCESS_USE,
+                                           &handle,
+                                           &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               errcode = W_ERROR_V(werr);
+               goto out;
+       }
 
-       case 0xb:   
-               /* change print job name, data gives the name */
-               if (print_job_set_name(sharename, jobid, data)) {
-                       errcode=NERR_Success;
-               }
-               break;
+       werr = rpccli_spoolss_getjob(cli, mem_ctx,
+                                    &handle,
+                                    jobid,
+                                    1, /* level */
+                                    0, /* offered */
+                                    &info);
+       if (!W_ERROR_IS_OK(werr)) {
+               errcode = W_ERROR_V(werr);
+               goto out;
+       }
 
-       default:
-               return False;
+       ZERO_STRUCT(ctr);
+
+       info1.job_id            = info.info1.job_id;
+       info1.printer_name      = info.info1.printer_name;
+       info1.user_name         = info.info1.user_name;
+       info1.document_name     = data;
+       info1.data_type         = info.info1.data_type;
+       info1.text_status       = info.info1.text_status;
+       info1.status            = info.info1.status;
+       info1.priority          = info.info1.priority;
+       info1.position          = info.info1.position;
+       info1.total_pages       = info.info1.total_pages;
+       info1.pages_printed     = info.info1.pages_printed;
+       info1.submitted         = info.info1.submitted;
+
+       ctr.level = 1;
+       ctr.info.info1 = &info1;
+
+       status = dcerpc_spoolss_SetJob(b, mem_ctx,
+                                      &handle,
+                                      jobid,
+                                      &ctr,
+                                      0,
+                                      &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               errcode = W_ERROR_V(werr);
+               goto out;
        }
 
+       errcode = NERR_Success;
  out:
+
+       if (b && is_valid_policy_hnd(&handle)) {
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
+       }
+
        SSVALS(*rparam,0,errcode);
        SSVAL(*rparam,2,0);             /* converter word */
-       
+
        return(True);
 }
 
@@ -2893,7 +3780,8 @@ static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
  Get info about the server.
 ****************************************************************************/
 
-static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
+static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
+                                 connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -2907,6 +3795,14 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
        char *p2;
        int struct_len;
 
+       NTSTATUS status;
+       WERROR werr;
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       struct rpc_pipe_client *cli = NULL;
+       union srvsvc_NetSrvInfo info;
+       int errcode;
+       struct dcerpc_binding_handle *b;
+
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -2967,64 +3863,59 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
 
        p = *rdata;
        p2 = p + struct_len;
+
+       status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id,
+                                       conn->session_info,
+                                       &conn->sconn->client_id,
+                                       conn->sconn->msg_ctx,
+                                       &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
+                         nt_errstr(status)));
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+
+       b = cli->binding_handle;
+
+       status = dcerpc_srvsvc_NetSrvGetInfo(b, mem_ctx,
+                                            NULL,
+                                            101,
+                                            &info,
+                                            &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               errcode = W_ERROR_V(werr);
+               goto out;
+       }
+
+       if (info.info101 == NULL) {
+               errcode = W_ERROR_V(WERR_INVALID_PARAM);
+               goto out;
+       }
+
        if (uLevel != 20) {
-               srvstr_push(NULL, 0, p,global_myname(),16,
+               srvstr_push(NULL, 0, p, info.info101->server_name, 16,
                        STR_ASCII|STR_UPPER|STR_TERMINATE);
        }
        p += 16;
        if (uLevel > 0) {
-               struct srv_info_struct *servers=NULL;
-               int i,count;
-               char *comment = NULL;
-               TALLOC_CTX *ctx = talloc_tos();
-               uint32 servertype= lp_default_server_announce();
-
-               comment = talloc_strdup(ctx,lp_serverstring());
-               if (!comment) {
-                       return false;
-               }
-
-               if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
-                       for (i=0;i<count;i++) {
-                               if (strequal(servers[i].name,global_myname())) {
-                                       servertype = servers[i].type;
-                                       TALLOC_FREE(comment);
-                                       comment = talloc_strdup(ctx,
-                                                       servers[i].comment);
-                                       if (comment) {
-                                               return false;
-                                       }
-                               }
-                       }
-               }
-
-               SAFE_FREE(servers);
-
-               SCVAL(p,0,lp_major_announce_version());
-               SCVAL(p,1,lp_minor_announce_version());
-               SIVAL(p,2,servertype);
+               SCVAL(p,0,info.info101->version_major);
+               SCVAL(p,1,info.info101->version_minor);
+               SIVAL(p,2,info.info101->server_type);
 
                if (mdrcnt == struct_len) {
                        SIVAL(p,6,0);
                } else {
                        SIVAL(p,6,PTR_DIFF(p2,*rdata));
-                       comment = talloc_sub_advanced(
-                               ctx,
-                               lp_servicename(SNUM(conn)),
-                               conn->server_info->unix_name,
-                               conn->connectpath,
-                               conn->server_info->utok.gid,
-                               conn->server_info->sanitized_username,
-                               pdb_get_domain(conn->server_info->sam_account),
-                               comment);
-                       if (comment) {
-                               return false;
-                       }
                        if (mdrcnt - struct_len <= 0) {
                                return false;
                        }
                        push_ascii(p2,
-                               comment,
+                               info.info101->comment,
                                MIN(mdrcnt - struct_len,
                                        MAX_SERVER_STRING_LENGTH),
                                STR_TERMINATE);
@@ -3039,6 +3930,10 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
                return False;           /* not yet implemented */
        }
 
+       errcode = NERR_Success;
+
+ out:
+
        *rdata_len = PTR_DIFF(p2,*rdata);
 
        *rparam_len = 6;
@@ -3046,7 +3941,7 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
        if (!*rparam) {
                return False;
        }
-       SSVAL(*rparam,0,NERR_Success);
+       SSVAL(*rparam,0,errcode);
        SSVAL(*rparam,2,0);             /* converter word */
        SSVAL(*rparam,4,*rdata_len);
 
@@ -3057,7 +3952,8 @@ static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
  Get info about the server.
 ****************************************************************************/
 
-static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
+static bool api_NetWkstaGetInfo(struct smbd_server_connection *sconn,
+                               connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3115,7 +4011,7 @@ static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
        p += 4;
 
        SIVAL(p,0,PTR_DIFF(p2,*rdata));
-       strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
+       strlcpy(p2,conn->session_info->sanitized_username,PTR_DIFF(endp,p2));
        p2 = skip_string(*rdata,*rdata_len,p2);
        if (!p2) {
                return False;
@@ -3162,9 +4058,9 @@ static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
   get info about a user
 
     struct user_info_11 {
-        char                usri11_name[21];  0-20 
-        char                usri11_pad;       21 
-        char                *usri11_comment;  22-25 
+        char                usri11_name[21];  0-20
+        char                usri11_pad;       21
+        char                *usri11_comment;  22-25
         char            *usri11_usr_comment;  26-29
         unsigned short      usri11_priv;      30-31
         unsigned long       usri11_auth_flags; 32-35
@@ -3295,7 +4191,7 @@ There is no auxiliary data in the response.
 
   ****************************************************************************/
 
-#define usri11_name           0 
+#define usri11_name           0
 #define usri11_pad            21
 #define usri11_comment        22
 #define usri11_usr_comment    26
@@ -3318,17 +4214,8 @@ There is no auxiliary data in the response.
 #define usri11_code_page      84
 #define usri11_end            86
 
-#define USER_PRIV_GUEST 0
-#define USER_PRIV_USER 1
-#define USER_PRIV_ADMIN 2
-
-#define AF_OP_PRINT     0 
-#define AF_OP_COMM      1
-#define AF_OP_SERVER    2
-#define AF_OP_ACCOUNTS  3
-
-
-static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
+static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn,
+                               connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3344,15 +4231,19 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
        char *endp;
        const char *level_string;
 
-       /* get NIS home of a previously validated user - simeon */
-       /* With share level security vuid will always be zero.
-          Don't depend on vuser being non-null !!. JRA */
-       user_struct *vuser = get_valid_user_struct(vuid);
-       if(vuser != NULL) {
-               DEBUG(3,("  Username of UID %d is %s\n",
-                        (int)vuser->server_info->utok.uid,
-                        vuser->server_info->unix_name));
-       }
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       NTSTATUS status, result;
+       struct rpc_pipe_client *cli = NULL;
+       struct policy_handle connect_handle, domain_handle, user_handle;
+       struct lsa_String domain_name;
+       struct dom_sid2 *domain_sid;
+       struct lsa_String names;
+       struct samr_Ids rids;
+       struct samr_Ids types;
+       int errcode = W_ERROR_V(WERR_USER_NOT_FOUND);
+       uint32_t rid;
+       union samr_UserInfo *info;
+       struct dcerpc_binding_handle *b = NULL;
 
        if (!str1 || !str2 || !UserName || !p) {
                return False;
@@ -3389,9 +4280,6 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                return False;
        }
 
-       SSVAL(*rparam,0,NERR_Success);
-       SSVAL(*rparam,2,0);             /* converter word */
-
        p = *rdata;
        endp = *rdata + *rdata_len;
        p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
@@ -3399,6 +4287,138 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                return False;
        }
 
+       ZERO_STRUCT(connect_handle);
+       ZERO_STRUCT(domain_handle);
+       ZERO_STRUCT(user_handle);
+
+       status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id,
+                                       conn->session_info,
+                                       &conn->sconn->client_id,
+                                       conn->sconn->msg_ctx,
+                                       &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
+                         nt_errstr(status)));
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+
+       b = cli->binding_handle;
+
+       status = dcerpc_samr_Connect2(b, mem_ctx,
+                                     global_myname(),
+                                     SAMR_ACCESS_CONNECT_TO_SERVER |
+                                     SAMR_ACCESS_ENUM_DOMAINS |
+                                     SAMR_ACCESS_LOOKUP_DOMAIN,
+                                     &connect_handle,
+                                     &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
+
+       init_lsa_String(&domain_name, get_global_sam_name());
+
+       status = dcerpc_samr_LookupDomain(b, mem_ctx,
+                                         &connect_handle,
+                                         &domain_name,
+                                         &domain_sid,
+                                         &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
+
+       status = dcerpc_samr_OpenDomain(b, mem_ctx,
+                                       &connect_handle,
+                                       SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+                                       domain_sid,
+                                       &domain_handle,
+                                       &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
+
+       init_lsa_String(&names, UserName);
+
+       status = dcerpc_samr_LookupNames(b, mem_ctx,
+                                        &domain_handle,
+                                        1,
+                                        &names,
+                                        &rids,
+                                        &types,
+                                        &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
+
+       if (rids.count != 1) {
+               errcode = W_ERROR_V(WERR_NO_SUCH_USER);
+               goto out;
+       }
+       if (rids.count != types.count) {
+               errcode = W_ERROR_V(WERR_INVALID_PARAM);
+               goto out;
+       }
+       if (types.ids[0] != SID_NAME_USER) {
+               errcode = W_ERROR_V(WERR_INVALID_PARAM);
+               goto out;
+       }
+
+       rid = rids.ids[0];
+
+       status = dcerpc_samr_OpenUser(b, mem_ctx,
+                                     &domain_handle,
+                                     SAMR_USER_ACCESS_GET_LOCALE |
+                                     SAMR_USER_ACCESS_GET_LOGONINFO |
+                                     SAMR_USER_ACCESS_GET_ATTRIBUTES |
+                                     SAMR_USER_ACCESS_GET_GROUPS |
+                                     SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP |
+                                     SEC_STD_READ_CONTROL,
+                                     rid,
+                                     &user_handle,
+                                     &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
+
+       status = dcerpc_samr_QueryUserInfo2(b, mem_ctx,
+                                           &user_handle,
+                                           UserAllInformation,
+                                           &info,
+                                           &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!NT_STATUS_IS_OK(result)) {
+               errcode = W_ERROR_V(ntstatus_to_werror(result));
+               goto out;
+       }
+
        memset(p,0,21);
        fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
 
@@ -3424,9 +4444,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
 
                /* EEK! the cifsrap.txt doesn't have this in!!!! */
                SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
-               strlcpy(p2,((vuser != NULL)
-                           ? pdb_get_fullname(vuser->server_info->sam_account)
-                           : UserName),PTR_DIFF(endp,p2));
+               strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
@@ -3434,13 +4452,11 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
        }
 
        if (uLevel == 11) {
-               const char *homedir = "";
-               if (vuser != NULL) {
-                       homedir = pdb_get_homedir(
-                               vuser->server_info->sam_account);
-               }
+               const char *homedir = info->info21.home_directory.string;
                /* modelled after NTAS 3.51 reply */
-               SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 
+               SSVAL(p,usri11_priv,
+                       (get_current_uid(conn) == sec_initial_uid())?
+                       USER_PRIV_ADMIN:USER_PRIV_USER);
                SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
                SIVALS(p,usri11_password_age,-1);               /* password age */
                SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
@@ -3493,10 +4509,10 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                memset(p+22,' ',16);    /* password */
                SIVALS(p,38,-1);                /* password age */
                SSVAL(p,42,
-               conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+                       (get_current_uid(conn) == sec_initial_uid())?
+                       USER_PRIV_ADMIN:USER_PRIV_USER);
                SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
-               strlcpy(p2, vuser ? pdb_get_homedir(
-                               vuser->server_info->sam_account) : "",
+               strlcpy(p2, info->info21.home_directory.string,
                        PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
@@ -3506,42 +4522,39 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                *p2++ = 0;
                SSVAL(p,52,0);          /* flags */
                SIVAL(p,54,PTR_DIFF(p2,*rdata));                /* script_path */
-               strlcpy(p2, vuser ? pdb_get_logon_script(
-                               vuser->server_info->sam_account) : "",
+               strlcpy(p2, info->info21.logon_script.string,
                        PTR_DIFF(endp,p2));
                p2 = skip_string(*rdata,*rdata_len,p2);
                if (!p2) {
                        return False;
                }
                if (uLevel == 2) {
-                       SIVAL(p,60,0);          /* auth_flags */
-                       SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
-                       strlcpy(p2,((vuser != NULL)
-                                   ? pdb_get_fullname(vuser->server_info->sam_account)
-                                   : UserName),PTR_DIFF(endp,p2));
+                       SIVAL(p,58,0);          /* auth_flags */
+                       SIVAL(p,62,PTR_DIFF(p2,*rdata)); /* full_name */
+                       strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
                        p2 = skip_string(*rdata,*rdata_len,p2);
                        if (!p2) {
                                return False;
                        }
-                       SIVAL(p,68,0);          /* urs_comment */
-                       SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
+                       SIVAL(p,66,0);          /* urs_comment */
+                       SIVAL(p,70,PTR_DIFF(p2,*rdata)); /* parms */
                        strlcpy(p2,"",PTR_DIFF(endp,p2));
                        p2 = skip_string(*rdata,*rdata_len,p2);
                        if (!p2) {
                                return False;
                        }
-                       SIVAL(p,76,0);          /* workstations */
-                       SIVAL(p,80,0);          /* last_logon */
-                       SIVAL(p,84,0);          /* last_logoff */
-                       SIVALS(p,88,-1);                /* acct_expires */
-                       SIVALS(p,92,-1);                /* max_storage */
-                       SSVAL(p,96,168);        /* units_per_week */
-                       SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
+                       SIVAL(p,74,0);          /* workstations */
+                       SIVAL(p,78,0);          /* last_logon */
+                       SIVAL(p,82,0);          /* last_logoff */
+                       SIVALS(p,86,-1);                /* acct_expires */
+                       SIVALS(p,90,-1);                /* max_storage */
+                       SSVAL(p,94,168);        /* units_per_week */
+                       SIVAL(p,96,PTR_DIFF(p2,*rdata)); /* logon_hours */
                        memset(p2,-1,21);
                        p2 += 21;
-                       SSVALS(p,102,-1);       /* bad_pw_count */
-                       SSVALS(p,104,-1);       /* num_logons */
-                       SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
+                       SSVALS(p,100,-1);       /* bad_pw_count */
+                       SSVALS(p,102,-1);       /* num_logons */
+                       SIVAL(p,104,PTR_DIFF(p2,*rdata)); /* logon_server */
                        {
                                TALLOC_CTX *ctx = talloc_tos();
                                int space_rem = *rdata_len - (p2 - *rdata);
@@ -3571,19 +4584,35 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
                        if (!p2) {
                                return False;
                        }
-                       SSVAL(p,110,49);        /* country_code */
-                       SSVAL(p,112,860);       /* code page */
+                       SSVAL(p,108,49);        /* country_code */
+                       SSVAL(p,110,860);       /* code page */
                }
        }
 
+       errcode = NERR_Success;
+
+ out:
        *rdata_len = PTR_DIFF(p2,*rdata);
 
+       if (b && is_valid_policy_hnd(&user_handle)) {
+               dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
+       }
+       if (b && is_valid_policy_hnd(&domain_handle)) {
+               dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result);
+       }
+       if (b && is_valid_policy_hnd(&connect_handle)) {
+               dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result);
+       }
+
+       SSVAL(*rparam,0,errcode);
+       SSVAL(*rparam,2,0);             /* converter word */
        SSVAL(*rparam,4,*rdata_len);    /* is this right?? */
 
        return(True);
 }
 
-static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
+static bool api_WWkstaUserLogon(struct smbd_server_connection *sconn,
+                               connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3598,7 +4627,7 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
        char* name;
                /* With share level security vuid will always be zero.
                   Don't depend on vuser being non-null !!. JRA */
-       user_struct *vuser = get_valid_user_struct(vuid);
+       user_struct *vuser = get_valid_user_struct(sconn, vuid);
 
        if (!str1 || !str2 || !p) {
                return False;
@@ -3606,8 +4635,8 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
 
        if(vuser != NULL) {
                DEBUG(3,("  Username of UID %d is %s\n",
-                        (int)vuser->server_info->utok.uid,
-                        vuser->server_info->unix_name));
+                        (int)vuser->session_info->utok.uid,
+                        vuser->session_info->unix_name));
        }
 
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
@@ -3638,12 +4667,14 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
        desc.buflen = mdrcnt;
        desc.subformat = NULL;
        desc.format = str2;
-  
+
        if (init_package(&desc,1,0)) {
                PACKI(&desc,"W",0);             /* code */
                PACKS(&desc,"B21",name);        /* eff. name */
                PACKS(&desc,"B","");            /* pad */
-               PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+               PACKI(&desc,"W",
+                       (get_current_uid(conn) == sec_initial_uid())?
+                       USER_PRIV_ADMIN:USER_PRIV_USER);
                PACKI(&desc,"D",0);             /* auth flags XXX */
                PACKI(&desc,"W",0);             /* num logons */
                PACKI(&desc,"W",0);             /* bad pw count */
@@ -3664,8 +4695,9 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
                }
 
                PACKS(&desc,"z",lp_workgroup());/* domain */
-               PACKS(&desc,"z", vuser ? pdb_get_logon_script(
-                             vuser->server_info->sam_account) : ""); /* script path */
+               PACKS(&desc,"z", vuser ?
+                       vuser->session_info->info3->base.logon_script.string
+                       : ""); /* script path */
                PACKI(&desc,"D",0x00000000);            /* reserved */
        }
 
@@ -3688,7 +4720,8 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
  api_WAccessGetUserPerms
 ****************************************************************************/
 
-static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
+static bool api_WAccessGetUserPerms(struct smbd_server_connection *sconn,
+                                   connection_struct *conn,uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3733,7 +4766,8 @@ static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
   api_WPrintJobEnumerate
   ****************************************************************************/
 
-static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
+static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn,
+                                connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3744,16 +4778,20 @@ static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
        char *str2 = skip_string(param,tpscnt,str1);
        char *p = skip_string(param,tpscnt,str2);
        int uLevel;
-       int count;
-       int i;
-       int snum;
        fstring sharename;
        uint32 jobid;
        struct pack_desc desc;
-       print_queue_struct *queue=NULL;
-       print_status_struct status;
        char *tmpdata=NULL;
 
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       WERROR werr;
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
+       struct policy_handle handle;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       union spoolss_JobInfo info;
+
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -3777,16 +4815,49 @@ static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
                return False;
        }
 
-       snum = lp_servicenumber( sharename);
-       if (snum < 0 || !VALID_SNUM(snum)) {
-               return(False);
+       ZERO_STRUCT(handle);
+
+       status = rpc_pipe_open_interface(conn,
+                                        &ndr_table_spoolss.syntax_id,
+                                        conn->session_info,
+                                        &conn->sconn->client_id,
+                                        conn->sconn->msg_ctx,
+                                        &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
+                         nt_errstr(status)));
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
        }
+       b = cli->binding_handle;
 
-       count = print_queue_status(snum,&queue,&status);
-       for (i = 0; i < count; i++) {
-               if (queue[i].job == jobid) {
-                       break;
-               }
+       ZERO_STRUCT(devmode_ctr);
+
+       status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
+                                           sharename,
+                                           "RAW",
+                                           devmode_ctr,
+                                           PRINTER_ACCESS_USE,
+                                           &handle,
+                                           &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               desc.errcode = W_ERROR_V(werr);
+               goto out;
+       }
+
+       werr = rpccli_spoolss_getjob(cli, mem_ctx,
+                                    &handle,
+                                    jobid,
+                                    2, /* level */
+                                    0, /* offered */
+                                    &info);
+       if (!W_ERROR_IS_OK(werr)) {
+               desc.errcode = W_ERROR_V(werr);
+               goto out;
        }
 
        if (mdrcnt > 0) {
@@ -3806,13 +4877,15 @@ static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
        }
 
        if (init_package(&desc,1,0)) {
-               if (i < count) {
-                       fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
-                       *rdata_len = desc.usedlen;
-               } else {
-                       desc.errcode = NERR_JobNotFound;
-                       *rdata_len = 0;
-               }
+               fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
+               *rdata_len = desc.usedlen;
+       } else {
+               desc.errcode = NERR_JobNotFound;
+               *rdata_len = 0;
+       }
+ out:
+       if (b && is_valid_policy_hnd(&handle)) {
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
        }
 
        *rparam_len = 6;
@@ -3824,7 +4897,6 @@ static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
        SSVAL(*rparam,2,0);
        SSVAL(*rparam,4,desc.neededlen);
 
-       SAFE_FREE(queue);
        SAFE_FREE(tmpdata);
 
        DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
@@ -3832,7 +4904,8 @@ static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
        return True;
 }
 
-static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
+static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn,
+                                  connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -3844,19 +4917,24 @@ static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
        char *p = skip_string(param,tpscnt,str2);
        char *name = p;
        int uLevel;
-       int count;
        int i, succnt=0;
-       int snum;
        struct pack_desc desc;
-       print_queue_struct *queue=NULL;
-       print_status_struct status;
+
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       WERROR werr;
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
+       struct policy_handle handle;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       uint32_t count = 0;
+       union spoolss_JobInfo *info;
 
        if (!str1 || !str2 || !p) {
                return False;
        }
 
        memset((char *)&desc,'\0',sizeof(desc));
-       memset((char *)&status,'\0',sizeof(status));
 
        p = skip_string(param,tpscnt,p);
        if (!p) {
@@ -3870,21 +4948,62 @@ static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
        if (strcmp(str1,"zWrLeh") != 0) {
                return False;
        }
-    
+
        if (uLevel > 2) {
                return False;   /* defined only for uLevel 0,1,2 */
        }
-    
-       if (!check_printjob_info(&desc,uLevel,str2)) { 
+
+       if (!check_printjob_info(&desc,uLevel,str2)) {
                return False;
        }
 
-       snum = find_service(name);
-       if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
-               return False;
+       ZERO_STRUCT(handle);
+
+       status = rpc_pipe_open_interface(conn,
+                                        &ndr_table_spoolss.syntax_id,
+                                        conn->session_info,
+                                        &conn->sconn->client_id,
+                                        conn->sconn->msg_ctx,
+                                        &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
+                         nt_errstr(status)));
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       b = cli->binding_handle;
+
+       ZERO_STRUCT(devmode_ctr);
+
+       status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
+                                           name,
+                                           NULL,
+                                           devmode_ctr,
+                                           SEC_FLAG_MAXIMUM_ALLOWED,
+                                           &handle,
+                                           &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               desc.errcode = W_ERROR_V(werr);
+               goto out;
+       }
+
+       werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
+                                      &handle,
+                                      0, /* firstjob */
+                                      0xff, /* numjobs */
+                                      2, /* level */
+                                      0, /* offered */
+                                      &count,
+                                      &info);
+       if (!W_ERROR_IS_OK(werr)) {
+               desc.errcode = W_ERROR_V(werr);
+               goto out;
        }
 
-       count = print_queue_status(snum,&queue,&status);
        if (mdrcnt > 0) {
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
@@ -3897,12 +5016,16 @@ static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
        if (init_package(&desc,count,0)) {
                succnt = 0;
                for (i = 0; i < count; i++) {
-                       fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
+                       fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
                        if (desc.errcode == NERR_Success) {
                                succnt = i+1;
                        }
                }
        }
+ out:
+       if (b && is_valid_policy_hnd(&handle)) {
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
+       }
 
        *rdata_len = desc.usedlen;
 
@@ -3916,8 +5039,6 @@ static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
        SSVAL(*rparam,4,succnt);
        SSVAL(*rparam,6,count);
 
-       SAFE_FREE(queue);
-
        DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
 
        return True;
@@ -3946,19 +5067,19 @@ static int check_printdest_info(struct pack_desc* desc,
                        return False;
        }
        if (id == NULL || strcmp(desc->format,id) != 0) {
-               DEBUG(0,("check_printdest_info: invalid string %s\n", 
+               DEBUG(0,("check_printdest_info: invalid string %s\n",
                        id ? id : "<NULL>" ));
                return False;
        }
        return True;
 }
 
-static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
+static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
                                struct pack_desc* desc)
 {
        char buf[100];
 
-       strncpy(buf,SERVICE(snum),sizeof(buf)-1);
+       strncpy(buf, info2->printername, sizeof(buf)-1);
        buf[sizeof(buf)-1] = 0;
        strupper_m(buf);
 
@@ -3989,7 +5110,8 @@ static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
        }
 }
 
-static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
+static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn,
+                                 connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -4002,9 +5124,17 @@ static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
        char* PrinterName = p;
        int uLevel;
        struct pack_desc desc;
-       int snum;
        char *tmpdata=NULL;
 
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       WERROR werr;
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
+       struct policy_handle handle;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       union spoolss_PrinterInfo info;
+
        if (!str1 || !str2 || !p) {
                return False;
        }
@@ -4027,33 +5157,82 @@ static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
                return False;
        }
 
-       snum = find_service(PrinterName);
-       if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
+       ZERO_STRUCT(handle);
+
+       status = rpc_pipe_open_interface(conn,
+                                        &ndr_table_spoolss.syntax_id,
+                                        conn->session_info,
+                                        &conn->sconn->client_id,
+                                        conn->sconn->msg_ctx,
+                                        &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
+                         nt_errstr(status)));
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       b = cli->binding_handle;
+
+       ZERO_STRUCT(devmode_ctr);
+
+       status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
+                                           PrinterName,
+                                           NULL,
+                                           devmode_ctr,
+                                           SEC_FLAG_MAXIMUM_ALLOWED,
+                                           &handle,
+                                           &werr);
+       if (!NT_STATUS_IS_OK(status)) {
                *rdata_len = 0;
                desc.errcode = NERR_DestNotFound;
                desc.neededlen = 0;
-       } else {
-               if (mdrcnt > 0) {
-                       *rdata = smb_realloc_limit(*rdata,mdrcnt);
-                       if (!*rdata) {
-                               return False;
-                       }
-                       desc.base = *rdata;
-                       desc.buflen = mdrcnt;
-               } else {
-                       /*
-                        * Don't return data but need to get correct length
-                        * init_package will return wrong size if buflen=0
-                        */
-                       desc.buflen = getlen(desc.format);
-                       desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
-               }
-               if (init_package(&desc,1,0)) {
-                       fill_printdest_info(conn,snum,uLevel,&desc);
+               goto out;
+       }
+       if (!W_ERROR_IS_OK(werr)) {
+               *rdata_len = 0;
+               desc.errcode = NERR_DestNotFound;
+               desc.neededlen = 0;
+               goto out;
+       }
+
+       werr = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                        &handle,
+                                        2,
+                                        0,
+                                        &info);
+       if (!W_ERROR_IS_OK(werr)) {
+               *rdata_len = 0;
+               desc.errcode = NERR_DestNotFound;
+               desc.neededlen = 0;
+               goto out;
+       }
+
+       if (mdrcnt > 0) {
+               *rdata = smb_realloc_limit(*rdata,mdrcnt);
+               if (!*rdata) {
+                       return False;
                }
-               *rdata_len = desc.usedlen;
+               desc.base = *rdata;
+               desc.buflen = mdrcnt;
+       } else {
+               /*
+                * Don't return data but need to get correct length
+                * init_package will return wrong size if buflen=0
+                */
+               desc.buflen = getlen(desc.format);
+               desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
+       }
+       if (init_package(&desc,1,0)) {
+               fill_printdest_info(&info.info2, uLevel,&desc);
        }
 
+ out:
+       if (b && is_valid_policy_hnd(&handle)) {
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
+       }
+
+       *rdata_len = desc.usedlen;
+
        *rparam_len = 6;
        *rparam = smb_realloc_limit(*rparam,*rparam_len);
        if (!*rparam) {
@@ -4069,7 +5248,8 @@ static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
        return True;
 }
 
-static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
+static bool api_WPrintDestEnum(struct smbd_server_connection *sconn,
+                              connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -4083,7 +5263,13 @@ static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
        int queuecnt;
        int i, n, succnt=0;
        struct pack_desc desc;
-       int services = lp_numservices();
+
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       WERROR werr;
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       union spoolss_PrinterInfo *info;
+       uint32_t count;
 
        if (!str1 || !str2 || !p) {
                return False;
@@ -4104,12 +5290,37 @@ static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
        }
 
        queuecnt = 0;
-       for (i = 0; i < services; i++) {
-               if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
-                       queuecnt++;
-               }
+
+       status = rpc_pipe_open_interface(conn,
+                                        &ndr_table_spoolss.syntax_id,
+                                        conn->session_info,
+                                        &conn->sconn->client_id,
+                                        conn->sconn->msg_ctx,
+                                        &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
+                         nt_errstr(status)));
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+
+       werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
+                                          PRINTER_ENUM_LOCAL,
+                                          cli->srv_name_slash,
+                                          2,
+                                          0,
+                                          &count,
+                                          &info);
+       if (!W_ERROR_IS_OK(werr)) {
+               desc.errcode = W_ERROR_V(werr);
+               *rdata_len = 0;
+               desc.errcode = NERR_DestNotFound;
+               desc.neededlen = 0;
+               goto out;
        }
 
+       queuecnt = count;
+
        if (mdrcnt > 0) {
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
@@ -4119,20 +5330,18 @@ static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
 
        desc.base = *rdata;
        desc.buflen = mdrcnt;
-       if (init_package(&desc,queuecnt,0)) {    
+       if (init_package(&desc,queuecnt,0)) {
                succnt = 0;
                n = 0;
-               for (i = 0; i < services; i++) {
-                       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
-                               fill_printdest_info(conn,i,uLevel,&desc);
-                               n++;
-                               if (desc.errcode == NERR_Success) {
-                                       succnt = n;
-                               }
+               for (i = 0; i < count; i++) {
+                       fill_printdest_info(&info[i].info2, uLevel,&desc);
+                       n++;
+                       if (desc.errcode == NERR_Success) {
+                               succnt = n;
                        }
                }
        }
-
+ out:
        *rdata_len = desc.usedlen;
 
        *rparam_len = 8;
@@ -4150,7 +5359,8 @@ static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
        return True;
 }
 
-static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
+static bool api_WPrintDriverEnum(struct smbd_server_connection *sconn,
+                                connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -4213,7 +5423,8 @@ static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
        return True;
 }
 
-static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
+static bool api_WPrintQProcEnum(struct smbd_server_connection *sconn,
+                               connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -4276,7 +5487,8 @@ static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
        return True;
 }
 
-static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
+static bool api_WPrintPortEnum(struct smbd_server_connection *sconn,
+                              connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -4345,7 +5557,8 @@ static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
  List open sessions
  ****************************************************************************/
 
-static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
+static bool api_RNetSessionEnum(struct smbd_server_connection *sconn,
+                               connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt,int mprcnt,
@@ -4358,14 +5571,22 @@ static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
        char *p = skip_string(param,tpscnt,str2);
        int uLevel;
        struct pack_desc desc;
-       struct sessionid *session_list;
-       int i, num_sessions;
+       int i;
+
+       TALLOC_CTX *mem_ctx = talloc_tos();
+       WERROR werr;
+       NTSTATUS status;
+       struct rpc_pipe_client *cli = NULL;
+       struct dcerpc_binding_handle *b = NULL;
+       struct srvsvc_NetSessInfoCtr info_ctr;
+       uint32_t totalentries, resume_handle = 0;
+       uint32_t count = 0;
 
        if (!str1 || !str2 || !p) {
                return False;
        }
 
-       memset((char *)&desc,'\0',sizeof(desc));
+       ZERO_STRUCT(desc);
 
        uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
 
@@ -4381,27 +5602,72 @@ static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
                return False;
        }
 
-       num_sessions = list_sessions(talloc_tos(), &session_list);
+       status = rpc_pipe_open_interface(conn,
+                                        &ndr_table_srvsvc.syntax_id,
+                                        conn->session_info,
+                                        &conn->sconn->client_id,
+                                        conn->sconn->msg_ctx,
+                                        &cli);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
+                         nt_errstr(status)));
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+       b = cli->binding_handle;
+
+       info_ctr.level = 1;
+       info_ctr.ctr.ctr1 = talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1);
+       if (info_ctr.ctr.ctr1 == NULL) {
+               desc.errcode = W_ERROR_V(WERR_NOMEM);
+               goto out;
+       }
+
+       status = dcerpc_srvsvc_NetSessEnum(b, mem_ctx,
+                                          cli->srv_name_slash,
+                                          NULL, /* client */
+                                          NULL, /* user */
+                                          &info_ctr,
+                                          (uint32_t)-1, /* max_buffer */
+                                          &totalentries,
+                                          &resume_handle,
+                                          &werr);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
+                         nt_errstr(status)));
+               desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
+               goto out;
+       }
+
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
+                         win_errstr(werr)));
+               desc.errcode = W_ERROR_V(werr);
+               goto out;
+       }
+
+       count = info_ctr.ctr.ctr1->count;
 
+ out:
        if (mdrcnt > 0) {
                *rdata = smb_realloc_limit(*rdata,mdrcnt);
                if (!*rdata) {
                        return False;
                }
        }
-       memset((char *)&desc,'\0',sizeof(desc));
+
        desc.base = *rdata;
        desc.buflen = mdrcnt;
        desc.format = str2;
-       if (!init_package(&desc,num_sessions,0)) {
+       if (!init_package(&desc, count,0)) {
                return False;
        }
 
-       for(i=0; i<num_sessions; i++) {
-               PACKS(&desc, "z", session_list[i].remote_machine);
-               PACKS(&desc, "z", session_list[i].username);
+       for(i=0; i < count; i++) {
+               PACKS(&desc, "z", info_ctr.ctr.ctr1->array[i].client);
+               PACKS(&desc, "z", info_ctr.ctr.ctr1->array[i].user);
                PACKI(&desc, "W", 1); /* num conns */
-               PACKI(&desc, "W", 0); /* num opens */
+               PACKI(&desc, "W", info_ctr.ctr.ctr1->array[i].num_open);
                PACKI(&desc, "W", 1); /* num users */
                PACKI(&desc, "D", 0); /* session time */
                PACKI(&desc, "D", 0); /* idle time */
@@ -4418,7 +5684,7 @@ static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
        }
        SSVALS(*rparam,0,desc.errcode);
        SSVAL(*rparam,2,0); /* converter */
-       SSVAL(*rparam,4,num_sessions); /* count */
+       SSVAL(*rparam,4, count); /* count */
 
        DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
 
@@ -4430,7 +5696,8 @@ static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
  The buffer was too small.
  ****************************************************************************/
 
-static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
+static bool api_TooSmall(struct smbd_server_connection *sconn,
+                        connection_struct *conn,uint16 vuid, char *param, char *data,
                         int mdrcnt, int mprcnt,
                         char **rdata, char **rparam,
                         int *rdata_len, int *rparam_len)
@@ -4454,7 +5721,8 @@ static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char
  The request is not supported.
  ****************************************************************************/
 
-static bool api_Unsupported(connection_struct *conn, uint16 vuid,
+static bool api_Unsupported(struct smbd_server_connection *sconn,
+                           connection_struct *conn, uint16 vuid,
                                char *param, int tpscnt,
                                char *data, int tdscnt,
                                int mdrcnt, int mprcnt,
@@ -4480,7 +5748,8 @@ static bool api_Unsupported(connection_struct *conn, uint16 vuid,
 static const struct {
        const char *name;
        int id;
-       bool (*fn)(connection_struct *, uint16,
+       bool (*fn)(struct smbd_server_connection *sconn,
+                  connection_struct *, uint16,
                        char *, int,
                        char *, int,
                        int,int,char **,char **,int *,int *);
@@ -4510,7 +5779,8 @@ static const struct {
        {"WPrintDestGetInfo",   RAP_WPrintDestGetInfo,  api_WPrintDestGetInfo},
        {"NetRemoteTOD",        RAP_NetRemoteTOD,       api_NetRemoteTOD},
        {"WPrintQueuePurge",    RAP_WPrintQPurge,       api_WPrintQueueCtrl},
-       {"NetServerEnum",       RAP_NetServerEnum2,     api_RNetServerEnum}, /* anon OK */
+       {"NetServerEnum2",      RAP_NetServerEnum2,     api_RNetServerEnum2}, /* anon OK */
+       {"NetServerEnum3",      RAP_NetServerEnum3,     api_RNetServerEnum3}, /* anon OK */
        {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
        {"SetUserPassword",     RAP_WUserPasswordSet2,  api_SetUserPassword},
        {"WWkstaUserLogon",     RAP_WWkstaUserLogon,    api_WWkstaUserLogon},
@@ -4522,7 +5792,7 @@ static const struct {
        {NULL,          -1,     api_Unsupported}
        /*  The following RAP calls are not implemented by Samba:
 
-       RAP_WFileEnum2 - anon not OK 
+       RAP_WFileEnum2 - anon not OK
        */
 };
 
@@ -4585,9 +5855,9 @@ void api_reply(connection_struct *conn, uint16 vuid,
        /* Check whether this api call can be done anonymously */
 
        if (api_commands[i].auth_user && lp_restrict_anonymous()) {
-               user_struct *user = get_valid_user_struct(vuid);
+               user_struct *user = get_valid_user_struct(req->sconn, vuid);
 
-               if (!user || user->server_info->guest) {
+               if (!user || user->session_info->guest) {
                        reply_nterror(req, NT_STATUS_ACCESS_DENIED);
                        return;
                }
@@ -4611,7 +5881,7 @@ void api_reply(connection_struct *conn, uint16 vuid,
                return;
        }
 
-       reply = api_commands[i].fn(conn,
+       reply = api_commands[i].fn(req->sconn, conn,
                                vuid,
                                params,tpscnt,  /* params + length */
                                data,tdscnt,    /* data + length */
@@ -4620,19 +5890,22 @@ void api_reply(connection_struct *conn, uint16 vuid,
 
 
        if (rdata_len > mdrcnt || rparam_len > mprcnt) {
-               reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
+               reply = api_TooSmall(req->sconn,conn,vuid,params,data,
+                                    mdrcnt,mprcnt,
                                        &rdata,&rparam,&rdata_len,&rparam_len);
        }
 
        /* if we get False back then it's actually unsupported */
        if (!reply) {
-               reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
+               reply = api_Unsupported(req->sconn,conn,vuid,params,tpscnt,
+                                       data,
+                                       tdscnt,mdrcnt,mprcnt,
                        &rdata,&rparam,&rdata_len,&rparam_len);
        }
 
        /* If api_Unsupported returns false we can't return anything. */
        if (reply) {
-               send_trans_reply(conn, req->inbuf, rparam, rparam_len,
+               send_trans_reply(conn, req, rparam, rparam_len,
                                 rdata, rdata_len, False);
        }