⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srv_spoolss_nt.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  Unix SMB/CIFS implementation. *  RPC Pipe client / server routines *  Copyright (C) Andrew Tridgell              1992-2000, *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000, *  Copyright (C) Jean François Micouleau      1998-2000, *  Copyright (C) Jeremy Allison               2001-2002, *  Copyright (C) Gerald Carter		       2000-2004, *  Copyright (C) Tim Potter                   2001-2002. * *  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. *//* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped   up, all the errors returned are DOS errors, not NT status codes. */#include "includes.h"extern userdom_struct current_user_info;#undef DBGC_CLASS#define DBGC_CLASS DBGC_RPC_SRV#ifndef MAX_OPEN_PRINTER_EXS#define MAX_OPEN_PRINTER_EXS 50#endif#define MAGIC_DISPLAY_FREQUENCY 0xfade2bad#define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"/* Table to map the driver version *//* to OS */static const char * drv_ver_to_os[] = {	"WIN9X",   /* driver version/cversion 0 */	"",        /* unused ? */	"WINNT",   /* driver version/cversion 2 */	"WIN2K",   /* driver version/cversion 3 */};static const char *get_drv_ver_to_os(int ver){	if (ver < 0 || ver > 3)		return "";	return drv_ver_to_os[ver];}struct table_node {	const char    *long_archi;	const char    *short_archi;	int     version;};static Printer_entry *printers_list;typedef struct _counter_printer_0 {	struct _counter_printer_0 *next;	struct _counter_printer_0 *prev;		int snum;	uint32 counter;} counter_printer_0;static counter_printer_0 *counter_list;static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/static uint32 smb_connections=0;/* in printing/nt_printing.c */extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;#define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())/* translate between internal status numbers and NT status numbers */static int nt_printj_status(int v){	switch (v) {	case LPQ_QUEUED:		return 0;	case LPQ_PAUSED:		return JOB_STATUS_PAUSED;	case LPQ_SPOOLING:		return JOB_STATUS_SPOOLING;	case LPQ_PRINTING:		return JOB_STATUS_PRINTING;	case LPQ_ERROR:		return JOB_STATUS_ERROR;	case LPQ_DELETING:		return JOB_STATUS_DELETING;	case LPQ_OFFLINE:		return JOB_STATUS_OFFLINE;	case LPQ_PAPEROUT:		return JOB_STATUS_PAPEROUT;	case LPQ_PRINTED:		return JOB_STATUS_PRINTED;	case LPQ_DELETED:		return JOB_STATUS_DELETED;	case LPQ_BLOCKED:		return JOB_STATUS_BLOCKED;	case LPQ_USER_INTERVENTION:		return JOB_STATUS_USER_INTERVENTION;	}	return 0;}static int nt_printq_status(int v){	switch (v) {	case LPQ_PAUSED:		return PRINTER_STATUS_PAUSED;	case LPQ_QUEUED:	case LPQ_SPOOLING:	case LPQ_PRINTING:		return 0;	}	return 0;}/**************************************************************************** Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.****************************************************************************/static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp){	if (*pp == NULL)		return;	SAFE_FREE((*pp)->ctr.type);	SAFE_FREE(*pp);}/*************************************************************************** Disconnect from the client****************************************************************************/static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle){	WERROR result;	/* 	 * Tell the specific printing tdb we no longer want messages for this printer	 * by deregistering our PID.	 */	if (!print_notify_deregister_pid(snum))		DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));	/* weird if the test succeds !!! */	if (smb_connections==0) {		DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));		return;	}	result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);		if (!W_ERROR_IS_OK(result))		DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",			dos_errstr(result)));	/* if it's the last connection, deconnect the IPC$ share */	if (smb_connections==1) {		cli_shutdown( notify_cli_pipe->cli );		notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */		message_deregister(MSG_PRINTER_NOTIFY2);        	/* Tell the connections db we're no longer interested in		 * printer notify messages. */		register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );	}	smb_connections--;}/**************************************************************************** Functions to free a printer entry datastruct.****************************************************************************/static void free_printer_entry(void *ptr){	Printer_entry *Printer = (Printer_entry *)ptr;	if (Printer->notify.client_connected==True) {		int snum = -1;		if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {			snum = -1;			srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);		} else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {			snum = print_queue_snum(Printer->sharename);			if (snum != -1)				srv_spoolss_replycloseprinter(snum,						&Printer->notify.client_hnd);		}	}	Printer->notify.flags=0;	Printer->notify.options=0;	Printer->notify.localmachine[0]='\0';	Printer->notify.printerlocal=0;	free_spool_notify_option(&Printer->notify.option);	Printer->notify.option=NULL;	Printer->notify.client_connected=False;		free_nt_devicemode( &Printer->nt_devmode );	free_a_printer( &Printer->printer_info, 2 );		talloc_destroy( Printer->ctx );	/* Remove from the internal list. */	DLIST_REMOVE(printers_list, Printer);	SAFE_FREE(Printer);}/**************************************************************************** Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.****************************************************************************/static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp){	SPOOL_NOTIFY_OPTION *new_sp = NULL;	if (!sp)		return NULL;	new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);	if (!new_sp)		return NULL;	*new_sp = *sp;	if (sp->ctr.count) {		new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);		if (!new_sp->ctr.type) {			SAFE_FREE(new_sp);			return NULL;		}	}	return new_sp;}/****************************************************************************  find printer index by handle****************************************************************************/static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd){	Printer_entry *find_printer = NULL;	if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {		DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));		return NULL;	}	return find_printer;}/**************************************************************************** Close printer index by handle.****************************************************************************/static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd){	Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);	if (!Printer) {		DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));		return False;	}	close_policy_hnd(p, hnd);	return True;}	/**************************************************************************** Delete a printer given a handle.****************************************************************************/WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename ){	char *cmd = lp_deleteprinter_cmd();	pstring command;	int ret;	SE_PRIV se_printop = SE_PRINT_OPERATOR;	BOOL is_print_op = False;			/* can't fail if we don't try */		if ( !*cmd )		return WERR_OK;			pstr_sprintf(command, "%s \"%s\"", cmd, sharename);	if ( token )		is_print_op = user_has_privileges( token, &se_printop );		DEBUG(10,("Running [%s]\n", command));	/********** BEGIN SePrintOperatorPrivlege BLOCK **********/		if ( is_print_op )		become_root();			if ( (ret = smbrun(command, NULL)) == 0 ) {		/* Tell everyone we updated smb.conf. */		message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);	}			if ( is_print_op )		unbecome_root();	/********** END SePrintOperatorPrivlege BLOCK **********/		DEBUGADD(10,("returned [%d]\n", ret));	if (ret != 0) 		return WERR_BADFID; /* What to return here? */	/* go ahead and re-read the services immediately */	reload_services( False );		if ( lp_servicenumber( sharename )  < 0 )		return WERR_ACCESS_DENIED;			return WERR_OK;}/**************************************************************************** Delete a printer given a handle.****************************************************************************/static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd){	Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);	if (!Printer) {		DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));		return WERR_BADFID;	}	/* 	 * It turns out that Windows allows delete printer on a handle	 * opened by an admin user, then used on a pipe handle created	 * by an anonymous user..... but they're working on security.... riiight !	 * JRA.	 */	if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {		DEBUG(3, ("delete_printer_handle: denied by handle\n"));		return WERR_ACCESS_DENIED;	}		/* this does not need a become root since the access check has been 	   done on the handle already */	   	if (del_a_printer( Printer->sharename ) != 0) {		DEBUG(3,("Error deleting printer %s\n", Printer->sharename));		return WERR_BADFID;	}	return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );}/**************************************************************************** Return the snum of a printer corresponding to an handle.****************************************************************************/static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number){	Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);			if (!Printer) {		DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));		return False;	}		switch (Printer->printer_type) {		case PRINTER_HANDLE_IS_PRINTER:					DEBUG(4,("short name:%s\n", Printer->sharename));						*number = print_queue_snum(Printer->sharename);			return (*number != -1);		case PRINTER_HANDLE_IS_PRINTSERVER:			return False;		default:			return False;	}}/**************************************************************************** Set printer handle type. Check if it's \\server or \\server\printer****************************************************************************/static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename){	DEBUG(3,("Setting printer type=%s\n", handlename));	if ( strlen(handlename) < 3 ) {		DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));		return False;	}	/* it's a print server */	if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {		DEBUGADD(4,("Printer is a print server\n"));		Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;			}	/* it's a printer */	else {		DEBUGADD(4,("Printer is a printer\n"));		Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;	}	return True;}/**************************************************************************** Set printer handle name.****************************************************************************/static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename){	int snum;	int n_services=lp_numservices();	char *aprinter, *printername;	const char *servername;	fstring sname;	BOOL found=False;	NT_PRINTER_INFO_LEVEL *printer;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -