1
0
mirror of https://github.com/samba-team/samba.git synced 2025-11-09 20:23:51 +03:00

r7643: This patch adds a new NTPTR subsystem:

- this is an abstraction layer for print services,
  like out NTVFS subsystem for file services

- all protocol specific details are still in rpc_server/spoolss/
  - like the stupid in and out Buffer handling
  - checking of the r->in.server_name
  - ...

- this subsystem can have multiple implementation
  selected by the "ntptr providor" global-section parameter

- I currently added a "simple_ldb" backend,
  that stores Printers, Forms, Ports, Monitors, ...
  in the spoolss.db, and does no real printing
  this backend is basicly for testing, how the spoolss protocol
  works

- the interface is just a prototype and will be changed a bit
  the next days or weeks, till the simple_ldb backend can
  handle all calls that are used by normal w2k3/xp clients

- I'll also make the api async, as the ntvfs api
  this will make things like the RemoteFindFirstPrinterChangeNotifyEx(),
  that opens a connection back to the client, easier to implement,
  as we should not block the whole smbd for that

- the idea is to later implement a "unix" backend
  that works like the current samba3 code

- and maybe some embedded print server vendors can write there own
  backend that can directly talk to a printer without having cups or something like this

- the default settings are (it currently makes no sense to change them :-):

ntptr providor = simple_ldb
spoolss database = $private_dir/spoolss.db

metze
This commit is contained in:
Stefan Metzmacher
2005-06-16 17:27:57 +00:00
committed by Gerald (Jerry) Carter
parent fddfe1f04b
commit 455b5536d4
13 changed files with 1852 additions and 682 deletions

View File

@@ -38,6 +38,7 @@ utils/config.mk
ntvfs/posix/config.mk ntvfs/posix/config.mk
ntvfs/config.mk ntvfs/config.mk
ntvfs/unixuid/config.mk ntvfs/unixuid/config.mk
ntptr/config.mk
torture/config.mk torture/config.mk
librpc/config.mk librpc/config.mk
client/config.mk client/config.mk

View File

@@ -37,8 +37,43 @@ union spoolss_FormInfo;
union spoolss_PortInfo; union spoolss_PortInfo;
union spoolss_MonitorInfo; union spoolss_MonitorInfo;
union spoolss_PrintProcessorInfo; union spoolss_PrintProcessorInfo;
struct spoolss_GetPrinterData; struct spoolss_GetPrinterData;
struct spoolss_SetPrinterData; struct spoolss_SetPrinterData;
struct spoolss_OpenPrinterEx;
struct spoolss_EnumPrinterData;
struct spoolss_DeletePrinterData;
struct spoolss_AddForm;
struct spoolss_GetForm;
struct spoolss_SetForm;
struct spoolss_DeleteForm;
struct spoolss_AddPrinterDriver;
struct spoolss_DeletePrinterDriver;
struct spoolss_GetPrinterDriverDirectory;
struct spoolss_AddPrinter;
struct spoolss_GetPrinter;
struct spoolss_SetPrinter;
struct spoolss_DeletePrinter;
struct spoolss_GetPrinterDriver;
struct spoolss_EnumPrinterData;
struct spoolss_DeletePrinterData;
struct spoolss_AddForm;
struct spoolss_GetForm;
struct spoolss_SetForm;
struct spoolss_DeleteForm;
struct spoolss_AddJob;
struct spoolss_ScheduleJob;
struct spoolss_GetJob;
struct spoolss_SetJob;
struct spoolss_StartDocPrinter;
struct spoolss_EndDocPrinter;
struct spoolss_StartPagePrinter;
struct spoolss_EndPagePrinter;
struct spoolss_WritePrinter;
struct spoolss_ReadPrinter;
struct ntptr_context;
struct ntptr_GenericHandle;
struct drsuapi_DsReplicaObjectListItem; struct drsuapi_DsReplicaObjectListItem;
struct drsuapi_DsReplicaObjectListItemEx; struct drsuapi_DsReplicaObjectListItemEx;

View File

@@ -878,7 +878,7 @@
[in,switch_is(level)] spoolss_SetFormInfo info [in,switch_is(level)] spoolss_SetFormInfo info
); );
typedef [nodiscriminant,relative_base,public] union { typedef [nodiscriminant,relative_base,public,gensize] union {
[case(1)] spoolss_FormInfo1 info1; [case(1)] spoolss_FormInfo1 info1;
[default]; [default];
} spoolss_FormInfo; } spoolss_FormInfo;

24
source/ntptr/config.mk Normal file
View File

@@ -0,0 +1,24 @@
# NTPTR Server subsystem
################################################
# Start MODULE ntptr_simple_ldb
[MODULE::ntptr_simple_ldb]
INIT_FUNCTION = ntptr_simple_ldb_init
SUBSYSTEM = NTPTR
INIT_OBJ_FILES = \
ntptr/simple_ldb/ntptr_simple_ldb.o
REQUIRED_SUBSYSTEMS = \
LIBLDB
# End MODULE ntptr_simple_ldb
################################################
################################################
# Start SUBSYSTEM NTPTR
[SUBSYSTEM::NTPTR]
INIT_OBJ_FILES = \
ntptr/ntptr_base.o
ADD_OBJ_FILES = \
ntptr/ntptr_interface.o
#
# End SUBSYSTEM NTPTR
################################################

189
source/ntptr/ntptr.h Normal file
View File

@@ -0,0 +1,189 @@
/*
Unix SMB/CIFS implementation.
NTPTR structures and defines
Copyright (C) Stefan (metze) Metzmacher 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* modules can use the following to determine if the interface has changed */
#define NTPTR_INTERFACE_VERSION 0
struct ntptr_context;
enum ntptr_HandleType {
NTPTR_HANDLE_SERVER,
NTPTR_HANDLE_PRINTER,
NTPTR_HANDLE_PORT,
NTPTR_HANDLE_MONITOR
};
struct ntptr_GenericHandle {
enum ntptr_HandleType type;
struct ntptr_context *ntptr;
uint32_t access_mask;
void *private_data;
};
/* the ntptr operations structure - contains function pointers to
the backend implementations of each operation */
struct ntptr_ops {
const char *name;
/* initial setup */
NTSTATUS (*init_context)(struct ntptr_context *ntptr);
/* PrintServer functions */
WERROR (*OpenPrintServer)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *printer_name,
struct ntptr_GenericHandle **server);
/* PrintServer PrinterData functions */
WERROR (*EnumPrintServerData)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinterData *r);
WERROR (*GetPrintServerData)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterData *r);
WERROR (*SetPrintServerData)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_SetPrinterData *r);
WERROR (*DeletePrintServerData)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_DeletePrinterData *r);
/* PrintServer Form functions */
WERROR (*EnumPrintServerForms)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_EnumForms *r);
WERROR (*AddPrintServerForm)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_AddForm *r);
WERROR (*GetPrintServerForm)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_GetForm *r);
WERROR (*SetPrintServerForm)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_SetForm *r);
WERROR (*DeletePrintServerForm)(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_DeleteForm *r);
/* PrintServer Driver functions */
WERROR (*EnumPrinterDrivers)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinterDrivers *r);
WERROR (*AddPrinterDriver)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_AddPrinterDriver *r);
WERROR (*DeletePrinterDriver)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_DeletePrinterDriver *r);
WERROR (*GetPrinterDriverDirectory)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterDriverDirectory *r);
/* Port functions */
WERROR (*EnumPorts)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPorts *r);
WERROR (*OpenPort)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *port_name,
struct ntptr_GenericHandle **prt);
/* Monitor functions */
WERROR (*EnumMonitors)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumMonitors *r);
WERROR (*OpenMonitor)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *monitor_name,
struct ntptr_GenericHandle **monitor);
/* PrintProcessor functions */
WERROR (*EnumPrintProcessors)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrintProcessors *r);
/* Printer functions */
WERROR (*EnumPrinters)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinters *r);
WERROR (*OpenPrinter)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *printer_name,
struct ntptr_GenericHandle **printer);
WERROR (*AddPrinter)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_AddPrinter *r,
struct ntptr_GenericHandle **printer);
WERROR (*GetPrinter)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinter *r);
WERROR (*SetPrinter)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_SetPrinter *r);
WERROR (*DeletePrinter)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_DeletePrinter *r);
/* Printer Driver functions */
WERROR (*GetPrinterDriver)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterDriver *r);
/* Printer PrinterData functions */
WERROR (*EnumPrinterData)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinterData *r);
WERROR (*GetPrinterData)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterData *r);
WERROR (*SetPrinterData)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_SetPrinterData *r);
WERROR (*DeletePrinterData)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_DeletePrinterData *r);
/* Printer Form functions */
WERROR (*EnumPrinterForms)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_EnumForms *r);
WERROR (*AddPrinterForm)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_AddForm *r);
WERROR (*GetPrinterForm)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_GetForm *r);
WERROR (*SetPrinterForm)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_SetForm *r);
WERROR (*DeletePrinterForm)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_DeleteForm *r);
/* Printer Job functions */
WERROR (*EnumJobs)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_EnumJobs *r);
WERROR (*AddJob)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_AddJob *r);
WERROR (*ScheduleJob)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_ScheduleJob *r);
WERROR (*GetJob)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_GetJob *r);
WERROR (*SetJob)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_SetJob *r);
/* Printer Printing functions */
WERROR (*StartDocPrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_StartDocPrinter *r);
WERROR (*EndDocPrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_EndDocPrinter *r);
WERROR (*StartPagePrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_StartPagePrinter *r);
WERROR (*EndPagePrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_EndPagePrinter *r);
WERROR (*WritePrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_WritePrinter *r);
WERROR (*ReadPrinter)(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_ReadPrinter *r);
};
struct ntptr_context {
const struct ntptr_ops *ops;
void *private_data;
};
/* this structure is used by backends to determine the size of some critical types */
struct ntptr_critical_sizes {
int interface_version;
int sizeof_ntptr_critical_sizes;
int sizeof_ntptr_context;
int sizeof_ntptr_ops;
};

134
source/ntptr/ntptr_base.c Normal file
View File

@@ -0,0 +1,134 @@
/*
Unix SMB/CIFS implementation.
NTPTR base code
Copyright (C) Stefan (metze) Metzmacher 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
this implements the core code for all NTPTR modules. Backends register themselves here.
*/
#include "includes.h"
#include "ntptr/ntptr.h"
#include "dlinklist.h"
/* the list of currently registered NTPTR backends */
static struct ntptr_backend {
const struct ntptr_ops *ops;
} *backends = NULL;
static int num_backends;
/*
register a NTPTR backend.
The 'name' can be later used by other backends to find the operations
structure for this backend.
*/
NTSTATUS ntptr_register(const void *_ops)
{
const struct ntptr_ops *ops = _ops;
struct ntptr_ops *new_ops;
if (ntptr_backend_byname(ops->name) != NULL) {
/* its already registered! */
DEBUG(0,("NTPTR backend '%s' already registered\n",
ops->name));
return NT_STATUS_OBJECT_NAME_COLLISION;
}
backends = realloc_p(backends, struct ntptr_backend, num_backends+1);
if (!backends) {
smb_panic("out of memory in ntptr_register");
}
new_ops = smb_xmemdup(ops, sizeof(*ops));
new_ops->name = smb_xstrdup(ops->name);
backends[num_backends].ops = new_ops;
num_backends++;
DEBUG(3,("NTPTR backend '%s'\n",
ops->name));
return NT_STATUS_OK;
}
/*
return the operations structure for a named backend
*/
const struct ntptr_ops *ntptr_backend_byname(const char *name)
{
int i;
for (i=0;i<num_backends;i++) {
if (strcmp(backends[i].ops->name, name) == 0) {
return backends[i].ops;
}
}
return NULL;
}
/*
return the NTPTR interface version, and the size of some critical types
This can be used by backends to either detect compilation errors, or provide
multiple implementations for different smbd compilation options in one module
*/
static const struct ntptr_critical_sizes critical_sizes = {
.interface_version = NTPTR_INTERFACE_VERSION,
.sizeof_ntptr_critical_sizes = sizeof(struct ntptr_critical_sizes),
.sizeof_ntptr_context = sizeof(struct ntptr_context),
.sizeof_ntptr_ops = sizeof(struct ntptr_ops),
};
const struct ntptr_critical_sizes *ntptr_interface_version(void)
{
return &critical_sizes;
}
/*
create a ntptr_context with a specified NTPTR backend
*/
NTSTATUS ntptr_init_context(TALLOC_CTX *mem_ctx, const char *providor, struct ntptr_context **_ntptr)
{
NTSTATUS status;
struct ntptr_context *ntptr;
if (!providor) {
return NT_STATUS_INTERNAL_ERROR;
}
ntptr = talloc(mem_ctx, struct ntptr_context);
NT_STATUS_HAVE_NO_MEMORY(ntptr);
ntptr->private_data = NULL;
ntptr->ops = ntptr_backend_byname(providor);
if (!ntptr->ops) {
DEBUG(1,("ntptr_init_context: failed to find NTPTR providor='%s'\n",
providor));
return NT_STATUS_INTERNAL_ERROR;
}
status = ntptr->ops->init_context(ntptr);
NT_STATUS_NOT_OK_RETURN(status);
*_ntptr = ntptr;
return NT_STATUS_OK;
}

View File

@@ -0,0 +1,561 @@
/*
Unix SMB/CIFS implementation.
NTPTR interface functions
Copyright (C) Stefan (metze) Metzmacher 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "ntptr/ntptr.h"
/* PrintServer functions */
WERROR ntptr_OpenPrintServer(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *printer_name,
struct ntptr_GenericHandle **server)
{
if (!ntptr->ops->OpenPrintServer) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->OpenPrintServer(ntptr, mem_ctx, r, printer_name, server);
}
/* PrintServer PrinterData functions */
WERROR ntptr_EnumPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinterData *r)
{
if (server->type != NTPTR_HANDLE_SERVER) {
return WERR_FOOBAR;
}
if (!server->ntptr->ops->EnumPrintServerData) {
return WERR_NOT_SUPPORTED;
}
return server->ntptr->ops->EnumPrintServerData(server, mem_ctx, r);
}
WERROR ntptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterData *r)
{
if (server->type != NTPTR_HANDLE_SERVER) {
return WERR_FOOBAR;
}
if (!server->ntptr->ops->GetPrintServerData) {
return WERR_NOT_SUPPORTED;
}
return server->ntptr->ops->GetPrintServerData(server, mem_ctx, r);
}
WERROR ntptr_SetPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_SetPrinterData *r)
{
if (server->type != NTPTR_HANDLE_SERVER) {
return WERR_FOOBAR;
}
if (!server->ntptr->ops->SetPrintServerData) {
return WERR_NOT_SUPPORTED;
}
return server->ntptr->ops->SetPrintServerData(server, mem_ctx, r);
}
WERROR ntptr_DeletePrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_DeletePrinterData *r)
{
if (server->type != NTPTR_HANDLE_SERVER) {
return WERR_FOOBAR;
}
if (!server->ntptr->ops->DeletePrintServerData) {
return WERR_NOT_SUPPORTED;
}
return server->ntptr->ops->DeletePrintServerData(server, mem_ctx, r);
}
/* PrintServer Form functions */
WERROR ntptr_EnumPrintServerForms(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_EnumForms *r)
{
if (server->type != NTPTR_HANDLE_SERVER) {
return WERR_FOOBAR;
}
if (!server->ntptr->ops->EnumPrintServerForms) {
return WERR_NOT_SUPPORTED;
}
return server->ntptr->ops->EnumPrintServerForms(server, mem_ctx, r);
}
WERROR ntptr_AddPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_AddForm *r)
{
if (server->type != NTPTR_HANDLE_SERVER) {
return WERR_FOOBAR;
}
if (!server->ntptr->ops->AddPrintServerForm) {
return WERR_NOT_SUPPORTED;
}
return server->ntptr->ops->AddPrintServerForm(server, mem_ctx, r);
}
WERROR ntptr_GetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_GetForm *r)
{
if (server->type != NTPTR_HANDLE_SERVER) {
return WERR_FOOBAR;
}
if (!server->ntptr->ops->GetPrintServerForm) {
return WERR_NOT_SUPPORTED;
}
return server->ntptr->ops->GetPrintServerForm(server, mem_ctx, r);
}
WERROR ntptr_SetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_SetForm *r)
{
if (server->type != NTPTR_HANDLE_SERVER) {
return WERR_FOOBAR;
}
if (!server->ntptr->ops->SetPrintServerForm) {
return WERR_NOT_SUPPORTED;
}
return server->ntptr->ops->SetPrintServerForm(server, mem_ctx, r);
}
WERROR ntptr_DeletePrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_DeleteForm *r)
{
if (server->type != NTPTR_HANDLE_SERVER) {
return WERR_FOOBAR;
}
if (!server->ntptr->ops->DeletePrintServerForm) {
return WERR_NOT_SUPPORTED;
}
return server->ntptr->ops->DeletePrintServerForm(server, mem_ctx, r);
}
/* PrintServer Driver functions */
WERROR ntptr_EnumPrinterDrivers(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinterDrivers *r)
{
if (!ntptr->ops->EnumPrinterDrivers) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->EnumPrinterDrivers(ntptr, mem_ctx, r);
}
WERROR ntptr_AddPrinterDriver(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_AddPrinterDriver *r)
{
if (!ntptr->ops->AddPrinterDriver) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->AddPrinterDriver(ntptr, mem_ctx, r);
}
WERROR ntptr_DeletePrinterDriver(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_DeletePrinterDriver *r)
{
if (!ntptr->ops->DeletePrinterDriver) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->DeletePrinterDriver(ntptr, mem_ctx, r);
}
WERROR ntptr_GetPrinterDriverDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterDriverDirectory *r)
{
if (!ntptr->ops->GetPrinterDriverDirectory) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->GetPrinterDriverDirectory(ntptr, mem_ctx, r);
}
/* Port functions */
WERROR ntptr_EnumPorts(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPorts *r)
{
if (!ntptr->ops->EnumPorts) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->EnumPorts(ntptr, mem_ctx, r);
}
WERROR ntptr_OpenPort(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *port_name,
struct ntptr_GenericHandle **prt)
{
if (!ntptr->ops->OpenPort) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->OpenPort(ntptr, mem_ctx, r, port_name, prt);
}
/* Monitor functions */
WERROR ntptr_EnumMonitors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumMonitors *r)
{
if (!ntptr->ops->EnumMonitors) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->EnumMonitors(ntptr, mem_ctx, r);
}
WERROR ntptr_OpenMonitor(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *monitor_name,
struct ntptr_GenericHandle **monitor)
{
if (!ntptr->ops->OpenMonitor) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->OpenMonitor(ntptr, mem_ctx, r, monitor_name, monitor);
}
/* PrintProcessor functions */
WERROR ntptr_EnumPrintProcessors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrintProcessors *r)
{
if (!ntptr->ops->EnumPrintProcessors) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->EnumPrintProcessors(ntptr, mem_ctx, r);
}
/* Printer functions */
WERROR ntptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinters *r)
{
if (!ntptr->ops->EnumPrinters) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->EnumPrinters(ntptr, mem_ctx, r);
}
WERROR ntptr_OpenPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *printer_name,
struct ntptr_GenericHandle **printer)
{
if (!ntptr->ops->OpenPrinter) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->OpenPrinter(ntptr, mem_ctx, r, printer_name, printer);
}
WERROR ntptr_AddPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_AddPrinter *r,
struct ntptr_GenericHandle **printer)
{
if (!ntptr->ops->AddPrinter) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->AddPrinter(ntptr, mem_ctx, r, printer);
}
WERROR ntptr_GetPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinter *r)
{
if (!ntptr->ops->GetPrinter) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->GetPrinter(ntptr, mem_ctx, r);
}
WERROR ntptr_SetPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_SetPrinter *r)
{
if (!ntptr->ops->SetPrinter) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->SetPrinter(ntptr, mem_ctx, r);
}
WERROR ntptr_DeletePrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_DeletePrinter *r)
{
if (!ntptr->ops->DeletePrinter) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->DeletePrinter(ntptr, mem_ctx, r);
}
/* Printer Driver functions */
WERROR ntptr_GetPrinterDriver(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterDriver *r)
{
if (!ntptr->ops->GetPrinterDriver) {
return WERR_NOT_SUPPORTED;
}
return ntptr->ops->GetPrinterDriver(ntptr, mem_ctx, r);
}
/* Printer PrinterData functions */
WERROR ntptr_EnumPrinterData(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinterData *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->EnumPrinterData) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->EnumPrinterData(printer, mem_ctx, r);
}
WERROR ntptr_GetPrinterData(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterData *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->GetPrinterData) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->GetPrinterData(printer, mem_ctx, r);
}
WERROR ntptr_SetPrinterData(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_SetPrinterData *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->SetPrinterData) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->SetPrinterData(printer, mem_ctx, r);
}
WERROR ntptr_DeletePrinterData(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_DeletePrinterData *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->DeletePrinterData) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->DeletePrinterData(printer, mem_ctx, r);
}
/* Printer Form functions */
WERROR ntptr_EnumPrinterForms(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_EnumForms *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->EnumPrinterForms) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->EnumPrinterForms(printer, mem_ctx, r);
}
WERROR ntptr_AddPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_AddForm *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->AddPrinterForm) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->AddPrinterForm(printer, mem_ctx, r);
}
WERROR ntptr_GetPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_GetForm *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->GetPrinterForm) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->GetPrinterForm(printer, mem_ctx, r);
}
WERROR ntptr_SetPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_SetForm *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->SetPrinterForm) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->SetPrinterForm(printer, mem_ctx, r);
}
WERROR ntptr_DeletePrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_DeleteForm *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->DeletePrinterForm) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->DeletePrinterForm(printer, mem_ctx, r);
}
/* Printer Job functions */
WERROR ntptr_EnumJobs(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_EnumJobs *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->EnumJobs) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->EnumJobs(printer, mem_ctx, r);
}
WERROR ntptr_AddJob(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_AddJob *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->AddJob) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->AddJob(printer, mem_ctx, r);
}
WERROR ntptr_ScheduleJob(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_ScheduleJob *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->ScheduleJob) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->ScheduleJob(printer, mem_ctx, r);
}
WERROR ntptr_GetJob(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_GetJob *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->GetJob) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->GetJob(printer, mem_ctx, r);
}
WERROR ntptr_SetJob(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_SetJob *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->SetJob) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->SetJob(printer, mem_ctx, r);
}
/* Printer Printing functions */
WERROR ntptr_StartDocPrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_StartDocPrinter *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->StartDocPrinter) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->StartDocPrinter(printer, mem_ctx, r);
}
WERROR ntptr_EndDocPrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_EndDocPrinter *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->EndDocPrinter) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->EndDocPrinter(printer, mem_ctx, r);
}
WERROR ntptr_StartPagePrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_StartPagePrinter *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->StartPagePrinter) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->StartPagePrinter(printer, mem_ctx, r);
}
WERROR ntptr_EndPagePrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_EndPagePrinter *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->EndPagePrinter) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->EndPagePrinter(printer, mem_ctx, r);
}
WERROR ntptr_WritePrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_WritePrinter *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->WritePrinter) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->WritePrinter(printer, mem_ctx, r);
}
WERROR ntptr_ReadPrinter(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
struct spoolss_ReadPrinter *r)
{
if (printer->type != NTPTR_HANDLE_PRINTER) {
return WERR_FOOBAR;
}
if (!printer->ntptr->ops->ReadPrinter) {
return WERR_NOT_SUPPORTED;
}
return printer->ntptr->ops->ReadPrinter(printer, mem_ctx, r);
}

View File

@@ -0,0 +1,596 @@
/*
Unix SMB/CIFS implementation.
Simple LDB NTPTR backend
Copyright (C) Stefan (metze) Metzmacher 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
This implements a NTPTR backend that store
all objects (Printers, Ports, Monitors, PrinterDrivers ...)
in a ldb database, but doesn't do real printing.
This is just used for testing how some of
the SPOOLSS protocol details should work
*/
#include "includes.h"
#include "ntptr/ntptr.h"
#include "librpc/gen_ndr/ndr_spoolss.h"
#include "lib/ldb/include/ldb.h"
#include "db_wrap.h"
/*
connect to the SPOOLSS database
return a ldb_context pointer on success, or NULL on failure
*/
static struct ldb_context *sptr_db_connect(TALLOC_CTX *mem_ctx)
{
return ldb_wrap_connect(mem_ctx, lp_spoolss_url(), 0, NULL);
}
static int sptr_db_search(struct ldb_context *ldb,
TALLOC_CTX *mem_ctx,
const char *basedn,
struct ldb_message ***res,
const char * const *attrs,
const char *format, ...) PRINTF_ATTRIBUTE(6,7);
static int sptr_db_search(struct ldb_context *ldb,
TALLOC_CTX *mem_ctx,
const char *basedn,
struct ldb_message ***res,
const char * const *attrs,
const char *format, ...)
{
va_list ap;
int count;
va_start(ap, format);
count = gendb_search_v(ldb, mem_ctx, basedn, res, attrs, format, ap);
va_end(ap);
return count;
}
static NTSTATUS sptr_init_context(struct ntptr_context *ntptr)
{
struct ldb_context *sptr_db = sptr_db_connect(ntptr);
NT_STATUS_HAVE_NO_MEMORY(sptr_db);
ntptr->private_data = sptr_db;
return NT_STATUS_OK;
}
/* PrintServer functions */
static WERROR sptr_OpenPrintServer(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *server_name,
struct ntptr_GenericHandle **_server)
{
struct ntptr_GenericHandle *server;
/* TODO: do access check here! */
server = talloc(mem_ctx, struct ntptr_GenericHandle);
W_ERROR_HAVE_NO_MEMORY(server);
server->type = NTPTR_HANDLE_SERVER;
server->ntptr = ntptr;
server->access_mask = r->in.access_mask;
server->private_data = NULL;
*_server = server;
return WERR_OK;
}
/*
* PrintServer PrinterData functions
*/
static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterData *r)
{
if (strcmp("W3SvcInstalled", r->in.value_name) == 0) {
r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
r->out.data.value = 0;
return WERR_OK;
} else if (strcmp("BeepEnabled", r->in.value_name) == 0) {
r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
r->out.data.value = 0;
return WERR_OK;
} else if (strcmp("EventLog", r->in.value_name) == 0) {
r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
r->out.data.value = 0;
return WERR_OK;
} else if (strcmp("NetPopup", r->in.value_name) == 0) {
r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
r->out.data.value = 0;
return WERR_OK;
} else if (strcmp("NetPopupToComputer", r->in.value_name) == 0) {
r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
r->out.data.value = 0;
return WERR_OK;
} else if (strcmp("MajorVersion", r->in.value_name) == 0) {
r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
r->out.data.value = 3;
return WERR_OK;
} else if (strcmp("MinorVersion", r->in.value_name) == 0) {
r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
r->out.data.value = 0;
return WERR_OK;
} else if (strcmp("DefaultSpoolDirectory", r->in.value_name) == 0) {
r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING;
r->out.data.string = "C:\\PRINTERS";
return WERR_OK;
} else if (strcmp("Architecture", r->in.value_name) == 0) {
r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING;
r->out.data.string = SPOOLSS_ARCHITECTURE_NT_X86;
return WERR_OK;
} else if (strcmp("DsPresent", r->in.value_name) == 0) {
r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
r->out.data.value = 1;
return WERR_OK;
}
return WERR_INVALID_PARAM;
}
/* PrintServer Form functions */
static WERROR sptr_EnumPrintServerForms(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_EnumForms *r)
{
struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
struct ldb_message **msgs;
int count;
int i;
union spoolss_FormInfo *info;
count = sptr_db_search(sptr_db, mem_ctx, "CN=PrintServer", &msgs, NULL,
"(&(objectclass=form))");
if (count == 0) return WERR_OK;
if (count < 0) return WERR_GENERAL_FAILURE;
info = talloc_array(mem_ctx, union spoolss_FormInfo, count);
W_ERROR_HAVE_NO_MEMORY(info);
switch (r->in.level) {
case 1:
for (i=0; i < count; i++) {
info[i].info1.flags = samdb_result_uint(msgs[i], "flags", SPOOLSS_FORM_PRINTER);
info[i].info1.form_name = samdb_result_string(msgs[i], "form_name", "Letter");
W_ERROR_HAVE_NO_MEMORY(info[i].info1.form_name);
info[i].info1.size.width = samdb_result_uint(msgs[i], "size_widgth", 0x34b5c);
info[i].info1.size.height = samdb_result_uint(msgs[i], "size_height", 0x44368);
info[i].info1.area.left = samdb_result_uint(msgs[i], "area_left", 0);
info[i].info1.area.top = samdb_result_uint(msgs[i], "area_top", 0);
info[i].info1.area.right = samdb_result_uint(msgs[i], "are_right", 0x34b5c);
info[i].info1.area.bottom = samdb_result_uint(msgs[i], "area_bottom", 0x44368);
}
break;
default:
return WERR_UNKNOWN_LEVEL;
}
r->out.info = info;
r->out.count = count;
return WERR_OK;
}
static WERROR sptr_GetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
struct spoolss_GetForm *r)
{
struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
struct ldb_message **msgs;
int count;
union spoolss_FormInfo *info;
count = sptr_db_search(sptr_db, mem_ctx, "CN=PrintServer", &msgs, NULL,
"(&(form_name=%s)(objectclass=form))",
r->in.form_name);
if (count == 0) return WERR_FOOBAR;
if (count > 1) return WERR_FOOBAR;
if (count < 0) return WERR_GENERAL_FAILURE;
info = talloc(mem_ctx, union spoolss_FormInfo);
W_ERROR_HAVE_NO_MEMORY(info);
switch (r->in.level) {
case 1:
info->info1.flags = samdb_result_uint(msgs[0], "flags", SPOOLSS_FORM_PRINTER);
info->info1.form_name = samdb_result_string(msgs[0], "form_name", "Letter");
W_ERROR_HAVE_NO_MEMORY(info->info1.form_name);
info->info1.size.width = samdb_result_uint(msgs[0], "size_widgth", 0x34b5c);
info->info1.size.height = samdb_result_uint(msgs[0], "size_height", 0x44368);
info->info1.area.left = samdb_result_uint(msgs[0], "area_left", 0);
info->info1.area.top = samdb_result_uint(msgs[0], "area_top", 0);
info->info1.area.right = samdb_result_uint(msgs[0], "are_right", 0x34b5c);
info->info1.area.bottom = samdb_result_uint(msgs[0], "area_bottom", 0x44368);
break;
default:
return WERR_UNKNOWN_LEVEL;
}
r->out.info = info;
return WERR_OK;
}
/* PrintServer Driver functions */
static WERROR sptr_EnumPrinterDrivers(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinterDrivers *r)
{
return WERR_OK;
}
static WERROR sptr_GetPrinterDriverDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterDriverDirectory *r)
{
union spoolss_DriverDirectoryInfo *info;
const char *prefix;
const char *postfix;
/*
* NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a
* are ignoring the r->in.level completely, so we do :-)
*/
/*
* TODO: check the server name is ours
* - if it's a invalid UNC then return WERR_INVALID_NAME
* - if it's the wrong host name return WERR_INVALID_PARAM
* - if it's "" then we need to return a local WINDOWS path
*/
if (!r->in.server || !r->in.server[0]) {
prefix = "C:\\DRIVERS";
} else {
prefix = talloc_asprintf(mem_ctx, "%s\\print$", r->in.server);
W_ERROR_HAVE_NO_MEMORY(prefix);
}
if (r->in.environment && strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) {
postfix = "W32X86";
} else {
return WERR_INVALID_ENVIRONMENT;
}
info = talloc(mem_ctx, union spoolss_DriverDirectoryInfo);
W_ERROR_HAVE_NO_MEMORY(info);
info->info1.directory_name = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix);
W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name);
r->out.info = info;
return WERR_OK;
}
/* Printer functions */
static WERROR sptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinters *r)
{
struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
struct ldb_message **msgs;
int count;
int i;
union spoolss_PrinterInfo *info;
count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
"(&(objectclass=printer))");
if (count == 0) return WERR_OK;
if (count < 0) return WERR_GENERAL_FAILURE;
info = talloc_array(mem_ctx, union spoolss_PrinterInfo, count);
W_ERROR_HAVE_NO_MEMORY(info);
switch(r->in.level) {
case 1:
for (i = 0; i < count; i++) {
info[i].info1.flags = samdb_result_uint(msgs[i], "flags", 0);
info[i].info1.name = samdb_result_string(msgs[i], "name", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info1.name);
info[i].info1.description = samdb_result_string(msgs[i], "description", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info1.description);
info[i].info1.comment = samdb_result_string(msgs[i], "comment", NULL);
}
break;
case 2:
for (i = 0; i < count; i++) {
info[i].info2.servername = samdb_result_string(msgs[i], "servername", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);
info[i].info2.printername = samdb_result_string(msgs[i], "printername", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);
info[i].info2.sharename = samdb_result_string(msgs[i], "sharename", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.sharename);
info[i].info2.portname = samdb_result_string(msgs[i], "portname", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.portname);
info[i].info2.drivername = samdb_result_string(msgs[i], "drivername", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.drivername);
info[i].info2.comment = samdb_result_string(msgs[i], "comment", NULL);
info[i].info2.location = samdb_result_string(msgs[i], "location", NULL);
info[i].info2.devmode = NULL;
info[i].info2.sepfile = samdb_result_string(msgs[i], "sepfile", NULL);
info[i].info2.printprocessor = samdb_result_string(msgs[i], "printprocessor", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.printprocessor);
info[i].info2.datatype = samdb_result_string(msgs[i], "datatype", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.datatype);
info[i].info2.parameters = samdb_result_string(msgs[i], "parameters", NULL);
info[i].info2.secdesc = NULL;
info[i].info2.attributes = samdb_result_uint(msgs[i], "attributes", 0);
info[i].info2.priority = samdb_result_uint(msgs[i], "priority", 0);
info[i].info2.defaultpriority = samdb_result_uint(msgs[i], "defaultpriority", 0);
info[i].info2.starttime = samdb_result_uint(msgs[i], "starttime", 0);
info[i].info2.untiltime = samdb_result_uint(msgs[i], "untiltime", 0);
info[i].info2.status = samdb_result_uint(msgs[i], "status", 0);
info[i].info2.cjobs = samdb_result_uint(msgs[i], "cjobs", 0);
info[i].info2.averageppm = samdb_result_uint(msgs[i], "averageppm", 0);
}
break;
case 4:
for (i = 0; i < count; i++) {
info[i].info4.printername = samdb_result_string(msgs[i], "printername", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);
info[i].info4.servername = samdb_result_string(msgs[i], "servername", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);
info[i].info4.attributes = samdb_result_uint(msgs[i], "attributes", 0);
}
break;
case 5:
for (i = 0; i < count; i++) {
info[i].info5.printername = samdb_result_string(msgs[i], "name", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info5.printername);
info[i].info5.portname = samdb_result_string(msgs[i], "port", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info5.portname);
info[i].info5.attributes = samdb_result_uint(msgs[i], "attributes", 0);
info[i].info5.device_not_selected_timeout = samdb_result_uint(msgs[i], "device_not_selected_timeout", 0);
info[i].info5.transmission_retry_timeout = samdb_result_uint(msgs[i], "transmission_retry_timeout", 0);
}
break;
default:
return WERR_UNKNOWN_LEVEL;
}
r->out.info = info;
r->out.count = count;
return WERR_OK;
}
static WERROR sptr_OpenPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *printer_name,
struct ntptr_GenericHandle **printer)
{
return WERR_INVALID_PRINTER_NAME;
}
/* port functions */
static WERROR sptr_EnumPorts(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPorts *r)
{
struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
struct ldb_message **msgs;
int count;
int i;
union spoolss_PortInfo *info;
count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
"(&(objectclass=port))");
if (count == 0) return WERR_OK;
if (count < 0) return WERR_GENERAL_FAILURE;
info = talloc_array(mem_ctx, union spoolss_PortInfo, count);
W_ERROR_HAVE_NO_MEMORY(info);
switch (r->in.level) {
case 1:
for (i = 0; i < count; i++) {
info[i].info1.port_name = samdb_result_string(msgs[i], "port_name", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info1.port_name);
}
break;
case 2:
for (i=0; i < count; i++) {
info[i].info2.port_name = samdb_result_string(msgs[i], "port_name", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.port_name);
info[i].info2.monitor_name = samdb_result_string(msgs[i], "monitor_name", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name);
info[i].info2.description = samdb_result_string(msgs[i], "description", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.description);
info[i].info2.port_type = samdb_result_uint(msgs[i], "port_type", SPOOLSS_PORT_TYPE_WRITE);
info[i].info2.reserved = samdb_result_uint(msgs[i], "reserved", 0);
}
break;
default:
return WERR_UNKNOWN_LEVEL;
}
r->out.info = info;
r->out.count = count;
return WERR_OK;
}
/* monitor functions */
static WERROR sptr_EnumMonitors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
struct spoolss_EnumMonitors *r)
{
struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
struct ldb_message **msgs;
int count;
int i;
union spoolss_MonitorInfo *info;
count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
"(&(objectclass=monitor))");
if (count == 0) return WERR_OK;
if (count < 0) return WERR_GENERAL_FAILURE;
info = talloc_array(mem_ctx, union spoolss_MonitorInfo, count);
W_ERROR_HAVE_NO_MEMORY(info);
switch (r->in.level) {
case 1:
for (i = 0; i < count; i++) {
info[i].info1.monitor_name = samdb_result_string(msgs[i], "monitor_name", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info1.monitor_name);
}
break;
case 2:
for (i=0; i < count; i++) {
info[i].info2.monitor_name = samdb_result_string(msgs[i], "monitor_name", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name);
info[i].info2.environment = samdb_result_string(msgs[i], "environment", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.environment);
info[i].info2.dll_name = samdb_result_string(msgs[i], "dll_name", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.dll_name);
}
break;
default:
return WERR_UNKNOWN_LEVEL;
}
r->out.info = info;
r->out.count = count;
return WERR_OK;
return WERR_OK;
}
/*
initialialise the simble ldb backend, registering ourselves with the ntptr subsystem
*/
static const struct ntptr_ops ntptr_simple_ldb_ops = {
.name = "simple_ldb",
.init_context = sptr_init_context,
/* PrintServer functions */
.OpenPrintServer = sptr_OpenPrintServer,
/* PrintServer PrinterData functions */
/* .EnumPrintServerData = sptr_EnumPrintServerData,
*/ .GetPrintServerData = sptr_GetPrintServerData,
/* .SetPrintServerData = sptr_SetPrintServerData,
.DeletePrintServerData = sptr_DeletePrintServerData,
*/
/* PrintServer Form functions */
.EnumPrintServerForms = sptr_EnumPrintServerForms,
/* .AddPrintServerForm = sptr_AddPrintServerForm,
*/ .GetPrintServerForm = sptr_GetPrintServerForm,
/* .SetPrintServerForm = sptr_SetPrintServerForm,
.DeletePrintServerForm = sptr_DeletePrintServerForm,
*/
/* PrintServer Driver functions */
.EnumPrinterDrivers = sptr_EnumPrinterDrivers,
/* .AddPrinterDriver = sptr_AddPrinterDriver,
.DeletePrinterDriver = sptr_DeletePrinterDriver,
*/ .GetPrinterDriverDirectory = sptr_GetPrinterDriverDirectory,
/* Port functions */
.EnumPorts = sptr_EnumPorts,
/* .OpenPort = sptr_OpenPort,
*/
/* Monitor functions */
.EnumMonitors = sptr_EnumMonitors,
/* .OpenMonitor = sptr_OpenMonitor,
*/
/* PrintProcessor functions */
/* .EnumPrintProcessors = sptr_EnumPrintProcessors,
*/
/* Printer functions */
.EnumPrinters = sptr_EnumPrinters,
.OpenPrinter = sptr_OpenPrinter,
/* .AddPrinter = sptr_AddPrinter,
.GetPrinter = sptr_GetPrinter,
.SetPrinter = sptr_SetPrinter,
.DeletePrinter = sptr_DeletePrinter,
*/
/* Printer Driver functions */
/* .GetPrinterDriver = sptr_GetPrinterDriver,
*/
/* Printer PrinterData functions */
/* .EnumPrinterData = sptr_EnumPrinterData,
.GetPrinterData = sptr_GetPrinterData,
.SetPrinterData = sptr_SetPrinterData,
.DeletePrinterData = sptr_DeletePrinterData,
*/
/* Printer Form functions */
/* .EnumPrinterForms = sptr_EnumPrinterForms,
.AddPrinterForm = sptr_AddPrinterForm,
.GetPrinterForm = sptr_GetPrinterForm,
.SetPrinterForm = sptr_SetPrinterForm,
.DeletePrinterForm = sptr_DeletePrinterForm,
*/
/* Printer Job functions */
/* .EnumJobs = sptr_EnumJobs,
.AddJob = sptr_AddJob,
.ScheduleJob = sptr_ScheduleJob,
.GetJob = sptr_GetJob,
.SetJob = sptr_SetJob,
*/
/* Printer Printing functions */
/* .StartDocPrinter = sptr_StartDocPrinter,
.EndDocPrinter = sptr_EndDocPrinter,
.StartPagePrinter = sptr_StartPagePrinter,
.EndPagePrinter = sptr_EndPagePrinter,
.WritePrinter = sptr_WritePrinter,
.ReadPrinter = sptr_ReadPrinter,
*/};
NTSTATUS ntptr_simple_ldb_init(void)
{
NTSTATUS ret;
ret = ntptr_register(&ntptr_simple_ldb_ops);
if (!NT_STATUS_IS_OK(ret)) {
DEBUG(0,("Failed to register NTPTR '%s' backend!\n",
ntptr_simple_ldb_ops.name));
}
return ret;
}

View File

@@ -167,6 +167,7 @@ typedef struct
char *szWINSPartners; char *szWINSPartners;
char **dcerpc_ep_servers; char **dcerpc_ep_servers;
char **server_services; char **server_services;
char *ntptr_providor;
char *szWinbindUID; char *szWinbindUID;
char *szWinbindGID; char *szWinbindGID;
char *szNonUnixAccountRange; char *szNonUnixAccountRange;
@@ -528,6 +529,7 @@ static struct parm_struct parm_table[] = {
{"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
{"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
{"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED}, {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
{"ntptr providor", P_STRING, P_GLOBAL, &Globals.ntptr_providor, NULL, NULL, FLAG_ADVANCED},
{"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED}, {"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
{"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED}, {"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
@@ -921,6 +923,7 @@ static void init_globals(void)
do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup"); do_parameter("dcerpc endpoint servers", "epmapper srvsvc wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi winreg dssetup");
do_parameter("server services", "smb rpc nbt ldap cldap web"); do_parameter("server services", "smb rpc nbt ldap cldap web");
do_parameter("ntptr providor", "simple_ldb");
do_parameter("auth methods", "anonymous sam_ignoredomain"); do_parameter("auth methods", "anonymous sam_ignoredomain");
do_parameter("smb passwd file", dyn_SMB_PASSWD_FILE); do_parameter("smb passwd file", dyn_SMB_PASSWD_FILE);
do_parameter("private dir", dyn_PRIVATE_DIR); do_parameter("private dir", dyn_PRIVATE_DIR);
@@ -1175,6 +1178,7 @@ FN_GLOBAL_STRING(lp_ncalrpc_dir, &Globals.ncalrpc_dir)
FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir) FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers) FN_GLOBAL_LIST(lp_dcerpc_endpoint_servers, &Globals.dcerpc_ep_servers)
FN_GLOBAL_LIST(lp_server_services, &Globals.server_services) FN_GLOBAL_LIST(lp_server_services, &Globals.server_services)
FN_GLOBAL_STRING(lp_ntptr_providor, &Globals.ntptr_providor)
FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir) FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService) FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv) FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv)

View File

@@ -161,12 +161,12 @@ REQUIRED_SUBSYSTEMS = \
INIT_FUNCTION = dcerpc_server_spoolss_init INIT_FUNCTION = dcerpc_server_spoolss_init
SUBSYSTEM = DCERPC SUBSYSTEM = DCERPC
INIT_OBJ_FILES = \ INIT_OBJ_FILES = \
rpc_server/spoolss/dcesrv_spoolss.o \ rpc_server/spoolss/dcesrv_spoolss.o
rpc_server/spoolss/spoolssdb.o
REQUIRED_SUBSYSTEMS = \ REQUIRED_SUBSYSTEMS = \
DCERPC_COMMON \ DCERPC_COMMON \
NDR_SPOOLSS NDR_SPOOLSS \
# End MODULE dcerpc_lsa NTPTR
# End MODULE dcerpc_spoolss
################################################ ################################################
################################################ ################################################

View File

@@ -25,138 +25,186 @@
#include "rpc_server/dcerpc_server.h" #include "rpc_server/dcerpc_server.h"
#include "librpc/gen_ndr/ndr_spoolss.h" #include "librpc/gen_ndr/ndr_spoolss.h"
#include "rpc_server/common/common.h" #include "rpc_server/common/common.h"
#include "rpc_server/spoolss/dcesrv_spoolss.h" #include "ntptr/ntptr.h"
#include "lib/socket/socket.h" #include "lib/socket/socket.h"
#include "smbd/service_stream.h" #include "smbd/service_stream.h"
#define SPOOLSS_BUFFER_SIZE(fn,level,count,info) \ #define SPOOLSS_BUFFER_UNION(fn,info,level) \
ndr_size_##fn##_info(dce_call, level, count, info) ((info)?ndr_size_##fn(info, level, 0):0)
#define SPOOLSS_BUFFER_UNION_ARRAY(fn,info,level,count) \
((info)?ndr_size_##fn##_info(dce_call, level, count, info):0)
#define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= r->out.needed)?val_true:val_false) #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= r->out.needed)?val_true:val_false)
static WERROR spoolss_parse_printer_name(TALLOC_CTX *mem_ctx, const char *name,
const char **_server_name,
const char **_object_name,
enum ntptr_HandleType *_object_type)
{
char *p;
char *server = NULL;
char *server_unc = NULL;
const char *object = name;
/* no printername is there it's like open server */
if (!name) {
*_server_name = NULL;
*_object_name = NULL;
*_object_type = NTPTR_HANDLE_SERVER;
return WERR_OK;
}
/* just "\\" is invalid */
if (strequal("\\\\", name)) {
return WERR_INVALID_PRINTER_NAME;
}
if (strncmp("\\\\", name, 2) == 0) {
server_unc = talloc_strdup(mem_ctx, name);
W_ERROR_HAVE_NO_MEMORY(server_unc);
server = server_unc + 2;
/* here we know we have "\\" in front not followed
* by '\0', now see if we have another "\" in the string
*/
p = strchr_m(server, '\\');
if (!p) {
/* there's no other "\", so it's ("\\%s",server)
*/
*_server_name = server_unc;
*_object_name = NULL;
*_object_type = NTPTR_HANDLE_SERVER;
return WERR_OK;
}
/* here we know that we have ("\\%s\",server),
* if we have '\0' as next then it's an invalid name
* otherwise the printer_name
*/
p[0] = '\0';
/* everything that follows is the printer name */
p++;
object = p;
/* just "" as server is invalid */
if (strequal(server, "")) {
return WERR_INVALID_PRINTER_NAME;
}
}
/* just "" is invalid */
if (strequal(object, "")) {
return WERR_INVALID_PRINTER_NAME;
}
#define XCV_PORT ",XcvPort "
#define XCV_MONITOR ",XcvMonitor "
if (strncmp(object, XCV_PORT, strlen(XCV_PORT)) == 0) {
object += strlen(XCV_PORT);
/* just "" is invalid */
if (strequal(object, "")) {
return WERR_INVALID_PRINTER_NAME;
}
*_server_name = server_unc;
*_object_name = object;
*_object_type = NTPTR_HANDLE_PORT;
return WERR_OK;
} else if (strncmp(object, XCV_MONITOR, strlen(XCV_MONITOR)) == 0) {
object += strlen(XCV_MONITOR);
/* just "" is invalid */
if (strequal(object, "")) {
return WERR_INVALID_PRINTER_NAME;
}
*_server_name = server_unc;
*_object_name = object;
*_object_type = NTPTR_HANDLE_MONITOR;
return WERR_OK;
}
*_server_name = server_unc;
*_object_name = object;
*_object_type = NTPTR_HANDLE_PRINTER;
return WERR_OK;
}
/*
* Check server_name is:
* - "" , functions that don't allow "",
* should check that on their own, before calling this function
* - our name (only netbios yet, TODO: need to test dns name!)
* - our ip address of the current use socket
* otherwise return WERR_INVALID_PRINTER_NAME
*/
static WERROR spoolss_check_server_name(struct dcesrv_call_state *dce_call,
TALLOC_CTX *mem_ctx,
const char *server_name)
{
BOOL ret;
const char *ip_str;
if (!server_name) return WERR_OK;
ret = strequal("",server_name);
if (ret) return WERR_OK;
if (strncmp("\\\\", server_name, 2) != 0) {
return WERR_INVALID_PRINTER_NAME;
}
server_name += 2;
ret = strequal(lp_netbios_name(), server_name);
if (ret) return WERR_OK;
/* TODO: check dns name here ? */
ip_str = socket_get_my_addr(dce_call->conn->srv_conn->socket, mem_ctx);
W_ERROR_HAVE_NO_MEMORY(ip_str);
ret = strequal(ip_str, server_name);
if (ret) return WERR_OK;
return WERR_INVALID_PRINTER_NAME;
}
static NTSTATUS dcerpc_spoolss_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
{
NTSTATUS status;
struct ntptr_context *ntptr;
status = ntptr_init_context(dce_call->context, lp_ntptr_providor(), &ntptr);
NT_STATUS_NOT_OK_RETURN(status);
dce_call->context->private = ntptr;
return NT_STATUS_OK;
}
#define DCESRV_INTERFACE_SPOOLSS_BIND dcerpc_spoolss_bind
/* /*
spoolss_EnumPrinters spoolss_EnumPrinters
*/ */
static WERROR spoolss_EnumPrinters(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_EnumPrinters(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinters *r) struct spoolss_EnumPrinters *r)
{ {
void *spoolss_ctx; struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
struct ldb_message **msgs; WERROR status;
int count;
int i;
union spoolss_PrinterInfo *info;
spoolss_ctx = spoolssdb_connect(); status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
W_ERROR_HAVE_NO_MEMORY(spoolss_ctx); W_ERROR_NOT_OK_RETURN(status);
count = spoolssdb_search(spoolss_ctx, mem_ctx, NULL, &msgs, NULL, status = ntptr_EnumPrinters(ntptr, mem_ctx, r);
"(&(objectclass=printer))"); W_ERROR_NOT_OK_RETURN(status);
spoolssdb_close(spoolss_ctx);
if (count == 0) return WERR_OK; r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinters, r->out.info, r->in.level, r->out.count);
if (count < 0) return WERR_GENERAL_FAILURE; r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
info = talloc_array(mem_ctx, union spoolss_PrinterInfo, count); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
W_ERROR_HAVE_NO_MEMORY(info);
switch(r->in.level) {
case 1:
for (i = 0; i < count; i++) {
info[i].info1.flags = samdb_result_uint(msgs[i], "flags", 0);
info[i].info1.name = samdb_result_string(msgs[i], "name", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info1.name);
info[i].info1.description = samdb_result_string(msgs[i], "description", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info1.description);
info[i].info1.comment = samdb_result_string(msgs[i], "comment", NULL);
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinters, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 2:
for (i = 0; i < count; i++) {
info[i].info2.servername = samdb_result_string(msgs[i], "servername", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);
info[i].info2.printername = samdb_result_string(msgs[i], "printername", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);
info[i].info2.sharename = samdb_result_string(msgs[i], "sharename", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.sharename);
info[i].info2.portname = samdb_result_string(msgs[i], "portname", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.portname);
info[i].info2.drivername = samdb_result_string(msgs[i], "drivername", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.drivername);
info[i].info2.comment = samdb_result_string(msgs[i], "comment", NULL);
info[i].info2.location = samdb_result_string(msgs[i], "location", NULL);
info[i].info2.devmode = NULL;
info[i].info2.sepfile = samdb_result_string(msgs[i], "sepfile", NULL);
info[i].info2.printprocessor = samdb_result_string(msgs[i], "printprocessor", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.printprocessor);
info[i].info2.datatype = samdb_result_string(msgs[i], "datatype", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.datatype);
info[i].info2.parameters = samdb_result_string(msgs[i], "parameters", NULL);
info[i].info2.secdesc = NULL;
info[i].info2.attributes = samdb_result_uint(msgs[i], "attributes", 0);
info[i].info2.priority = samdb_result_uint(msgs[i], "priority", 0);
info[i].info2.defaultpriority = samdb_result_uint(msgs[i], "defaultpriority", 0);
info[i].info2.starttime = samdb_result_uint(msgs[i], "starttime", 0);
info[i].info2.untiltime = samdb_result_uint(msgs[i], "untiltime", 0);
info[i].info2.status = samdb_result_uint(msgs[i], "status", 0);
info[i].info2.cjobs = samdb_result_uint(msgs[i], "cjobs", 0);
info[i].info2.averageppm = samdb_result_uint(msgs[i], "averageppm", 0);
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinters, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 4:
for (i = 0; i < count; i++) {
info[i].info4.printername = samdb_result_string(msgs[i], "printername", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);
info[i].info4.servername = samdb_result_string(msgs[i], "servername", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);
info[i].info4.attributes = samdb_result_uint(msgs[i], "attributes", 0);
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinters, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 5:
for (i = 0; i < count; i++) {
info[i].info5.printername = samdb_result_string(msgs[i], "name", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info5.printername);
info[i].info5.portname = samdb_result_string(msgs[i], "port", "");
W_ERROR_HAVE_NO_MEMORY(info[i].info5.portname);
info[i].info5.attributes = samdb_result_uint(msgs[i], "attributes", 0);
info[i].info5.device_not_selected_timeout = samdb_result_uint(msgs[i], "device_not_selected_timeout", 0);
info[i].info5.transmission_retry_timeout = samdb_result_uint(msgs[i], "transmission_retry_timeout", 0);
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinters, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
return WERR_UNKNOWN_LEVEL;
} }
static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
@@ -279,64 +327,19 @@ static WERROR spoolss_AddPrinterDriver(struct dcesrv_call_state *dce_call, TALLO
static WERROR spoolss_EnumPrinterDrivers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_EnumPrinterDrivers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPrinterDrivers *r) struct spoolss_EnumPrinterDrivers *r)
{ {
union spoolss_DriverInfo *info; struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
int count; WERROR status;
int i;
count = 0; status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
W_ERROR_NOT_OK_RETURN(status);
if (count == 0) return WERR_OK; status = ntptr_EnumPrinterDrivers(ntptr, mem_ctx, r);
if (count < 0) return WERR_GENERAL_FAILURE; W_ERROR_NOT_OK_RETURN(status);
info = talloc_array(mem_ctx, union spoolss_DriverInfo, count); r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinterDrivers, r->out.info, r->in.level, r->out.count);
W_ERROR_HAVE_NO_MEMORY(info); r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
switch (r->in.level) { return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 1:
for (i=0; i < count; i++) {
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 2:
for (i=0; i < count; i++) {
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 3:
for (i=0; i < count; i++) {
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 4:
for (i=0; i < count; i++) {
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 5:
for (i=0; i < count; i++) {
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 6:
for (i=0; i < count; i++) {
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPrinterDrivers, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
return WERR_UNKNOWN_LEVEL;
} }
@@ -356,42 +359,17 @@ static WERROR spoolss_GetPrinterDriver(struct dcesrv_call_state *dce_call, TALLO
static WERROR spoolss_GetPrinterDriverDirectory(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_GetPrinterDriverDirectory(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterDriverDirectory *r) struct spoolss_GetPrinterDriverDirectory *r)
{ {
union spoolss_DriverDirectoryInfo *info; struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
const char *prefix; WERROR status;
const char *postfix;
/* status = spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
* NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a W_ERROR_NOT_OK_RETURN(status);
* are ignoring the r->in.level completely, so we do :-)
*/
/*
* TODO: check the server name is ours
* - if it's a invalid UNC then return WERR_INVALID_NAME
* - if it's the wrong host name return WERR_INVALID_PARAM
* - if it's "" then we need to return a local WINDOWS path
*/
if (strcmp("", r->in.server) == 0) {
prefix = "C:\\DRIVERS";
} else {
prefix = talloc_asprintf(mem_ctx, "%s\\print$", r->in.server);
W_ERROR_HAVE_NO_MEMORY(prefix);
}
if (strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) { status = ntptr_GetPrinterDriverDirectory(ntptr, mem_ctx, r);
postfix = "W32X86"; W_ERROR_NOT_OK_RETURN(status);
} else {
return WERR_INVALID_ENVIRONMENT;
}
info = talloc(mem_ctx, union spoolss_DriverDirectoryInfo); r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, r->out.info, r->in.level);
W_ERROR_HAVE_NO_MEMORY(info); r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
info->info1.directory_name = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix);
W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name);
r->out.needed = ndr_size_spoolss_DriverDirectoryInfo(info, r->in.level, 0);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
} }
@@ -532,67 +510,28 @@ static WERROR spoolss_ScheduleJob(struct dcesrv_call_state *dce_call, TALLOC_CTX
static WERROR spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_GetPrinterData *r) struct spoolss_GetPrinterData *r)
{ {
struct ntptr_GenericHandle *handle;
struct dcesrv_handle *h; struct dcesrv_handle *h;
WERROR status = WERR_INVALID_PARAM; WERROR status;
enum spoolss_PrinterDataType type = SPOOLSS_PRINTER_DATA_TYPE_NULL;
union spoolss_PrinterData data;
DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
if (h->wire_handle.handle_type == SPOOLSS_HANDLE_SERVER) { switch (handle->type) {
/* TODO: do access check here */ case NTPTR_HANDLE_SERVER:
status = ntptr_GetPrintServerData(handle, mem_ctx, r);
if (strcmp("W3SvcInstalled", r->in.value_name) == 0) { break;
type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; default:
data.value = 0; status = WERR_FOOBAR;
status = WERR_OK; break;
} else if (strcmp("BeepEnabled", r->in.value_name) == 0) {
type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
data.value = 0;
status = WERR_OK;
} else if (strcmp("EventLog", r->in.value_name) == 0) {
type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
data.value = 0;
status = WERR_OK;
} else if (strcmp("NetPopup", r->in.value_name) == 0) {
type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
data.value = 0;
status = WERR_OK;
} else if (strcmp("NetPopupToComputer", r->in.value_name) == 0) {
type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
data.value = 0;
status = WERR_OK;
} else if (strcmp("MajorVersion", r->in.value_name) == 0) {
type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
data.value = 3;
status = WERR_OK;
} else if (strcmp("MinorVersion", r->in.value_name) == 0) {
type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
data.value = 0;
status = WERR_OK;
} else if (strcmp("DefaultSpoolDirectory", r->in.value_name) == 0) {
type = SPOOLSS_PRINTER_DATA_TYPE_STRING;
data.string = "C:\\PRINTERS";
status = WERR_OK;
} else if (strcmp("Architecture", r->in.value_name) == 0) {
type = SPOOLSS_PRINTER_DATA_TYPE_STRING;
data.string = SPOOLSS_ARCHITECTURE_NT_X86;
status = WERR_OK;
} else if (strcmp("DsPresent", r->in.value_name) == 0) {
type = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
data.value = 1;
status = WERR_OK;
}
} }
if (W_ERROR_IS_OK(status)) { W_ERROR_NOT_OK_RETURN(status);
r->out.needed = ndr_size_spoolss_PrinterData(&data, type, 0);
r->out.type = SPOOLSS_BUFFER_OK(type, SPOOLSS_PRINTER_DATA_TYPE_NULL);
r->out.data = SPOOLSS_BUFFER_OK(data, data);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
}
return status; r->out.needed = ndr_size_spoolss_PrinterData(&r->out.data, r->out.type, 0);
r->out.type = SPOOLSS_BUFFER_OK(r->out.type, SPOOLSS_PRINTER_DATA_TYPE_NULL);
r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
} }
@@ -662,7 +601,29 @@ static WERROR spoolss_DeleteForm(struct dcesrv_call_state *dce_call, TALLOC_CTX
static WERROR spoolss_GetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_GetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_GetForm *r) struct spoolss_GetForm *r)
{ {
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); struct ntptr_GenericHandle *handle;
struct dcesrv_handle *h;
WERROR status;
DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
switch (handle->type) {
case NTPTR_HANDLE_SERVER:
status = ntptr_GetPrintServerForm(handle, mem_ctx, r);
W_ERROR_NOT_OK_RETURN(status);
break;
case NTPTR_HANDLE_PRINTER:
status = ntptr_GetPrinterForm(handle, mem_ctx, r);
W_ERROR_NOT_OK_RETURN(status);
break;
default:
return WERR_FOOBAR;
}
r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, r->out.info, r->in.level);
r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
} }
@@ -682,44 +643,30 @@ static WERROR spoolss_SetForm(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
static WERROR spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumForms *r) struct spoolss_EnumForms *r)
{ {
union spoolss_FormInfo *info; struct ntptr_GenericHandle *handle;
int count;
int i;
struct dcesrv_handle *h; struct dcesrv_handle *h;
WERROR status;
DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
handle = talloc_get_type(h->data, struct ntptr_GenericHandle);
count = 1; switch (handle->type) {
case NTPTR_HANDLE_SERVER:
if (count == 0) return WERR_OK; status = ntptr_EnumPrintServerForms(handle, mem_ctx, r);
if (count < 0) return WERR_GENERAL_FAILURE; W_ERROR_NOT_OK_RETURN(status);
break;
info = talloc_array(mem_ctx, union spoolss_FormInfo, count); case NTPTR_HANDLE_PRINTER:
W_ERROR_HAVE_NO_MEMORY(info); status = ntptr_EnumPrinterForms(handle, mem_ctx, r);
W_ERROR_NOT_OK_RETURN(status);
switch (r->in.level) { break;
case 1: default:
for (i=0; i < count; i++) { return WERR_FOOBAR;
info[i].info1.flags = SPOOLSS_FORM_PRINTER;
info[i].info1.form_name = talloc_strdup(mem_ctx, "Letter");
W_ERROR_HAVE_NO_MEMORY(info[i].info1.form_name);
info[i].info1.size.width = 0x34b5c;
info[i].info1.size.height = 0x44368;
info[i].info1.area.left = 0;
info[i].info1.area.top = 0;
info[i].info1.area.right = 0x34b5c;
info[i].info1.area.bottom = 0x44368;
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumForms, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
} }
return WERR_UNKNOWN_LEVEL; r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumForms, r->out.info, r->in.level, r->out.count);
r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
} }
@@ -729,49 +676,19 @@ static WERROR spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLOC_CTX *
static WERROR spoolss_EnumPorts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_EnumPorts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumPorts *r) struct spoolss_EnumPorts *r)
{ {
union spoolss_PortInfo *info; struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
int count; WERROR status;
int i;
count = 1; status = spoolss_check_server_name(dce_call, mem_ctx, r->in.servername);
W_ERROR_NOT_OK_RETURN(status);
if (count == 0) return WERR_OK; status = ntptr_EnumPorts(ntptr, mem_ctx, r);
if (count < 0) return WERR_GENERAL_FAILURE; W_ERROR_NOT_OK_RETURN(status);
info = talloc_array(mem_ctx, union spoolss_PortInfo, count); r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPorts, r->out.info, r->in.level, r->out.count);
W_ERROR_HAVE_NO_MEMORY(info); r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
switch (r->in.level) { return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 1:
for (i=0; i < count; i++) {
info[i].info1.port_name = talloc_strdup(mem_ctx, "Samba Printer Port");
W_ERROR_HAVE_NO_MEMORY(info[i].info1.port_name);
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPorts, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 2:
for (i=0; i < count; i++) {
info[i].info2.port_name = talloc_strdup(mem_ctx, "Samba Printer Port");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.port_name);
info[i].info2.monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name);
info[i].info2.description = talloc_strdup(mem_ctx, "Local Port");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.description);
info[i].info2.port_type = SPOOLSS_PORT_TYPE_WRITE;
info[i].info2.reserved = 0;
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumPorts, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
return WERR_UNKNOWN_LEVEL;
} }
@@ -781,46 +698,19 @@ static WERROR spoolss_EnumPorts(struct dcesrv_call_state *dce_call, TALLOC_CTX *
static WERROR spoolss_EnumMonitors(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_EnumMonitors(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_EnumMonitors *r) struct spoolss_EnumMonitors *r)
{ {
union spoolss_MonitorInfo *info; struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
int count; WERROR status;
int i;
count = 1; status = spoolss_check_server_name(dce_call, mem_ctx, r->in.servername);
W_ERROR_NOT_OK_RETURN(status);
if (count == 0) return WERR_OK; status = ntptr_EnumMonitors(ntptr, mem_ctx, r);
if (count < 0) return WERR_GENERAL_FAILURE; W_ERROR_NOT_OK_RETURN(status);
info = talloc_array(mem_ctx, union spoolss_MonitorInfo, count); r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumMonitors, r->out.info, r->in.level, r->out.count);
W_ERROR_HAVE_NO_MEMORY(info); r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(r->out.count, 0);
switch (r->in.level) { return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 1:
for (i=0; i < count; i++) {
info[i].info1.monitor_name = talloc_strdup(mem_ctx, "Standard TCP/IP Port");
W_ERROR_HAVE_NO_MEMORY(info[i].info1.monitor_name);
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumMonitors, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
case 2:
for (i=0; i < count; i++) {
info[i].info2.monitor_name = talloc_strdup(mem_ctx, "Standard TCP/IP Port");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name);
info[i].info2.environment = talloc_strdup(mem_ctx, SPOOLSS_ARCHITECTURE_NT_X86);
W_ERROR_HAVE_NO_MEMORY(info[i].info2.environment);
info[i].info2.dll_name = talloc_strdup(mem_ctx, "tcpmon.dll");
W_ERROR_HAVE_NO_MEMORY(info[i].info2.dll_name);
}
r->out.needed = SPOOLSS_BUFFER_SIZE(spoolss_EnumMonitors, r->in.level, count, info);
r->out.info = SPOOLSS_BUFFER_OK(info, NULL);
r->out.count = SPOOLSS_BUFFER_OK(count, 0);
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
}
return WERR_UNKNOWN_LEVEL;
} }
@@ -1110,7 +1000,12 @@ static WERROR spoolss_ResetPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_
static WERROR spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r) struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
{ {
return WERR_NOT_SUPPORTED; /*
* TODO: for now just return ok,
* to keep the w2k3 PrintServer
* happy to allow to open the Add Printer GUI
*/
return WERR_OK;
} }
@@ -1143,175 +1038,57 @@ static WERROR spoolss_44(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
} }
static WERROR spoolss_OpenPrinterEx_server(struct dcesrv_call_state *dce_call,
TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *server_name)
{
struct spoolss_handle_server *state;
struct dcesrv_handle *handle;
BOOL ret;
/* Check printername is our name or our ip address
*/
ret = strequal(server_name, lp_netbios_name());
if (!ret) {
const char *ip = socket_get_my_addr(dce_call->conn->srv_conn->socket, mem_ctx);
W_ERROR_HAVE_NO_MEMORY(ip);
ret = strequal(server_name, ip);
if (!ret) {
return WERR_INVALID_PRINTER_NAME;
}
}
/* TODO: do access check here */
handle = dcesrv_handle_new(dce_call->context, SPOOLSS_HANDLE_SERVER);
W_ERROR_HAVE_NO_MEMORY(handle);
state = talloc(handle, struct spoolss_handle_server);
W_ERROR_HAVE_NO_MEMORY(state);
handle->data = state;
state->access_mask = r->in.access_mask;
*r->out.handle = handle->wire_handle;
return WERR_OK;
}
static WERROR spoolss_OpenPrinterEx_port(struct dcesrv_call_state *dce_call,
TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *server_name,
const char *port_name)
{
DEBUG(1, ("looking for port [%s] (server[%s])\n", port_name, server_name));
return WERR_INVALID_PRINTER_NAME;
}
static WERROR spoolss_OpenPrinterEx_monitor(struct dcesrv_call_state *dce_call,
TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *server_name,
const char *monitor_name)
{
if (strequal("Standard TCP/IP Port", monitor_name)) {
struct dcesrv_handle *handle;
handle = dcesrv_handle_new(dce_call->context, SPOOLSS_HANDLE_MONITOR);
W_ERROR_HAVE_NO_MEMORY(handle);
handle->data = NULL;
*r->out.handle = handle->wire_handle;
return WERR_OK;
}
DEBUG(1, ("looking for monitor [%s] (server[%s])\n", monitor_name, server_name));
return WERR_INVALID_PRINTER_NAME;
}
static WERROR spoolss_OpenPrinterEx_printer(struct dcesrv_call_state *dce_call,
TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r,
const char *server_name,
const char *printer_name)
{
DEBUG(3, ("looking for printer [%s] (server[%s])\n", printer_name, server_name));
return WERR_INVALID_PRINTER_NAME;
}
/* /*
spoolss_OpenPrinterEx spoolss_OpenPrinterEx
*/ */
static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR spoolss_OpenPrinterEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct spoolss_OpenPrinterEx *r) struct spoolss_OpenPrinterEx *r)
{ {
char *p; struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private, struct ntptr_context);
char *server = NULL; struct ntptr_GenericHandle *handle;
const char *object = r->in.printername; struct dcesrv_handle *h;
const char *server;
const char *object;
enum ntptr_HandleType type;
WERROR status;
ZERO_STRUCTP(r->out.handle); ZERO_STRUCTP(r->out.handle);
/* no printername is there it's like open server */ status = spoolss_parse_printer_name(mem_ctx, r->in.printername, &server, &object, &type);
if (!r->in.printername) { W_ERROR_NOT_OK_RETURN(status);
return spoolss_OpenPrinterEx_server(dce_call, mem_ctx, r, NULL);
status = spoolss_check_server_name(dce_call, mem_ctx, server);
W_ERROR_NOT_OK_RETURN(status);
switch (type) {
case NTPTR_HANDLE_SERVER:
status = ntptr_OpenPrintServer(ntptr, mem_ctx, r, server, &handle);
W_ERROR_NOT_OK_RETURN(status);
break;
case NTPTR_HANDLE_PORT:
status = ntptr_OpenPort(ntptr, mem_ctx, r, object, &handle);
W_ERROR_NOT_OK_RETURN(status);
break;
case NTPTR_HANDLE_MONITOR:
status = ntptr_OpenMonitor(ntptr, mem_ctx, r, object, &handle);
W_ERROR_NOT_OK_RETURN(status);
break;
case NTPTR_HANDLE_PRINTER:
status = ntptr_OpenPrinter(ntptr, mem_ctx, r, object, &handle);
W_ERROR_NOT_OK_RETURN(status);
break;
default:
return WERR_FOOBAR;
} }
/* just "\\" is invalid */ h = dcesrv_handle_new(dce_call->context, handle->type);
if (strequal(r->in.printername, "\\\\")) { W_ERROR_HAVE_NO_MEMORY(h);
return WERR_INVALID_PRINTER_NAME;
}
if (strncmp(r->in.printername, "\\\\", 2) == 0) { h->data = talloc_steal(h, handle);
server = talloc_strdup(mem_ctx, r->in.printername + 2);
W_ERROR_HAVE_NO_MEMORY(server);
/* here we know we have "\\" in front not followed *r->out.handle = h->wire_handle;
* by '\0', now see if we have another "\" in the string
*/
p = strchr_m(server, '\\');
if (!p) {
/* there's no other "\", so it's ("\\%s",server)
*/
return spoolss_OpenPrinterEx_server(dce_call, mem_ctx, r, server);
}
/* here we know that we have ("\\%s\",server),
* if we have '\0' as next then it's an invalid name
* otherwise the printer_name
*/
p[0] = '\0';
/* everything that follows is the printer name */
p++;
object = p;
/* just "" as server is invalid */ return WERR_OK;
if (strequal(server, "")) {
DEBUG(2,("OpenPrinterEx invalid print server: [%s][%s][%s]\n", r->in.printername, server, object));
return WERR_INVALID_PRINTER_NAME;
}
}
/* just "" is invalid */
if (strequal(object, "")) {
DEBUG(2,("OpenPrinterEx invalid object: [%s][%s][%s]\n", r->in.printername, server, object));
return WERR_INVALID_PRINTER_NAME;
}
DEBUG(3,("OpenPrinterEx object: [%s][%s][%s]\n", r->in.printername, server, object));
#define XCV_PORT ",XcvPort "
#define XCV_MONITOR ",XcvMonitor "
if (strncmp(object, XCV_PORT, strlen(XCV_PORT)) == 0) {
object += strlen(XCV_PORT);
/* just "" is invalid */
if (strequal(object, "")) {
DEBUG(2,("OpenPrinterEx invalid port: [%s][%s][%s]\n", r->in.printername, server, object));
return WERR_INVALID_PRINTER_NAME;
}
return spoolss_OpenPrinterEx_port(dce_call, mem_ctx, r, server, object);
} else if (strncmp(object, XCV_MONITOR, strlen(XCV_MONITOR)) == 0) {
object += strlen(XCV_MONITOR);
/* just "" is invalid */
if (strequal(object, "")) {
DEBUG(2,("OpenPrinterEx invalid monitor: [%s][%s][%s]\n", r->in.printername, server, object));
return WERR_INVALID_PRINTER_NAME;
}
return spoolss_OpenPrinterEx_monitor(dce_call, mem_ctx, r, server, object);
}
return spoolss_OpenPrinterEx_printer(dce_call, mem_ctx, r, server, object);
} }
/* /*

View File

@@ -1,38 +0,0 @@
/*
Unix SMB/CIFS implementation.
endpoint server for the spoolss pipe - definitions
Copyright (C) Tim Potter 2004
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
this type allows us to distinguish handle types
*/
enum spoolss_handle_type {
SPOOLSS_HANDLE_SERVER,
SPOOLSS_HANDLE_PRINTER,
SPOOLSS_HANDLE_PORT,
SPOOLSS_HANDLE_MONITOR
};
/*
state asscoiated with a spoolss_OpenPrinter{,Ex}() operation
*/
struct spoolss_handle_server {
uint32_t access_mask;
};

View File

@@ -1,113 +0,0 @@
/*
Unix SMB/CIFS implementation.
interface functions for the spoolss database
Copyright (C) Andrew Tridgell 2004
Copyright (C) Tim Potter 2004
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "lib/ldb/include/ldb.h"
struct spoolssdb_context {
struct ldb_context *ldb;
};
/*
this is used to catch debug messages from ldb
*/
static void spoolssdb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
static void spoolssdb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
{
char *s = NULL;
if (DEBUGLEVEL < 4 && level > LDB_DEBUG_WARNING) {
return;
}
vasprintf(&s, fmt, ap);
if (!s) return;
DEBUG(level, ("spoolssdb: %s\n", s));
free(s);
}
/*
connect to the spoolss database
return an opaque context pointer on success, or NULL on failure
*/
void *spoolssdb_connect(void)
{
struct spoolssdb_context *ctx;
/*
the way that unix fcntl locking works forces us to have a
static ldb handle here rather than a much more sensible
approach of having the ldb handle as part of the
spoolss_OpenPrinter() pipe state. Otherwise we would try to open
the ldb more than once, and tdb would rightly refuse the
second open due to the broken nature of unix locking.
*/
static struct ldb_context *static_spoolss_db;
if (static_spoolss_db == NULL) {
static_spoolss_db = ldb_connect(lp_spoolss_url(), 0, NULL);
if (static_spoolss_db == NULL) {
return NULL;
}
}
ldb_set_debug(static_spoolss_db, spoolssdb_debug, NULL);
ctx = malloc_p(struct spoolssdb_context);
if (!ctx) {
errno = ENOMEM;
return NULL;
}
ctx->ldb = static_spoolss_db;
return ctx;
}
/* close a connection to the spoolss db */
void spoolssdb_close(void *ctx)
{
struct spoolssdb_context *spoolss_ctx = ctx;
/* we don't actually close due to broken posix locking semantics */
spoolss_ctx->ldb = NULL;
free(spoolss_ctx);
}
/*
search the db for the specified attributes - varargs variant
*/
int spoolssdb_search(void *ctx,
TALLOC_CTX *mem_ctx,
const char *basedn,
struct ldb_message ***res,
const char * const *attrs,
const char *format, ...) _PRINTF_ATTRIBUTE(6,7)
{
struct spoolssdb_context *spoolss_ctx = ctx;
va_list ap;
int count;
va_start(ap, format);
count = gendb_search_v(spoolss_ctx->ldb, mem_ctx, basedn, res, attrs, format, ap);
va_end(ap);
return count;
}