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

📄 srv_spoolss_nt.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *******************************************************************/static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode){	DEVICEMODE *d;	int len;	if (!devmode)		return NULL;			DEBUG (8,("dup_devmode\n"));		/* bulk copy first */		d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));	if (!d)		return NULL;			/* dup the pointer members separately */		len = unistrlen(devmode->devicename.buffer);	if (len != -1) {		d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);		if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)			return NULL;	}			len = unistrlen(devmode->formname.buffer);	if (len != -1) {		d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);		if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)			return NULL;	}	d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);		return d;}static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr){	if (!new_ctr || !ctr)		return;			DEBUG(8,("copy_devmode_ctr\n"));		new_ctr->size = ctr->size;	new_ctr->devmode_ptr = ctr->devmode_ptr;		if(ctr->devmode_ptr)		new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);}static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def){	if (!new_def || !def)		return;		DEBUG(8,("copy_printer_defaults\n"));		new_def->datatype_ptr = def->datatype_ptr;		if (def->datatype_ptr)		copy_unistr2(&new_def->datatype, &def->datatype);		copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);		new_def->access_required = def->access_required;}/******************************************************************** * Convert a SPOOL_Q_OPEN_PRINTER structure to a  * SPOOL_Q_OPEN_PRINTER_EX structure ********************************************************************/static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u){	if (!q_u_ex || !q_u)		return WERR_OK;	DEBUG(8,("convert_to_openprinterex\n"));					if ( q_u->printername ) {		q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );		if (q_u_ex->printername == NULL)			return WERR_NOMEM;		copy_unistr2(q_u_ex->printername, q_u->printername);	}		copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);	return WERR_OK;}/******************************************************************** * spoolss_open_printer * * called from the spoolss dispatcher ********************************************************************/WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u){	SPOOL_Q_OPEN_PRINTER_EX q_u_ex;	SPOOL_R_OPEN_PRINTER_EX r_u_ex;		if (!q_u || !r_u)		return WERR_NOMEM;		ZERO_STRUCT(q_u_ex);	ZERO_STRUCT(r_u_ex);		/* convert the OpenPrinter() call to OpenPrinterEx() */		r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);	if (!W_ERROR_IS_OK(r_u_ex.status))		return r_u_ex.status;		r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);		/* convert back to OpenPrinter() */		memcpy(r_u, &r_u_ex, sizeof(*r_u));		return r_u->status;}/******************************************************************** * spoolss_open_printer * * If the openprinterex rpc call contains a devmode, * it's a per-user one. This per-user devmode is derivated * from the global devmode. Openprinterex() contains a per-user  * devmode for when you do EMF printing and spooling. * In the EMF case, the NT workstation is only doing half the job * of rendering the page. The other half is done by running the printer * driver on the server. * The EMF file doesn't contain the page description (paper size, orientation, ...). * The EMF file only contains what is to be printed on the page. * So in order for the server to know how to print, the NT client sends * a devicemode attached to the openprinterex call. * But this devicemode is short lived, it's only valid for the current print job. * * If Samba would have supported EMF spooling, this devicemode would * have been attached to the handle, to sent it to the driver to correctly * rasterize the EMF file. * * As Samba only supports RAW spooling, we only receive a ready-to-print file, * we just act as a pass-thru between windows and the printer. * * In order to know that Samba supports only RAW spooling, NT has to call * getprinter() at level 2 (attribute field) or NT has to call startdoc() * and until NT sends a RAW job, we refuse it. * * But to call getprinter() or startdoc(), you first need a valid handle, * and to get an handle you have to call openprintex(). Hence why you have * a devicemode in the openprinterex() call. * * * Differences between NT4 and NT 2000. * NT4: * --- * On NT4, you only have a global devicemode. This global devicemode can be changed * by the administrator (or by a user with enough privs). Everytime a user * wants to print, the devicemode is resetted to the default. In Word, everytime * you print, the printer's characteristics are always reset to the global devicemode. * * NT 2000: * ------- * In W2K, there is the notion of per-user devicemode. The first time you use * a printer, a per-user devicemode is build from the global devicemode. * If you change your per-user devicemode, it is saved in the registry, under the * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default * printer preferences available. * * To change the per-user devicemode: it's the "Printing Preferences ..." button * on the General Tab of the printer properties windows. * * To change the global devicemode: it's the "Printing Defaults..." button * on the Advanced Tab of the printer properties window. * * JFM. ********************************************************************/WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u){	PRINTER_DEFAULT 	*printer_default = &q_u->printer_default;	POLICY_HND 		*handle = &r_u->handle;	fstring name;	int snum;	struct current_user user;	Printer_entry *Printer=NULL;	if ( !q_u->printername )		return WERR_INVALID_PRINTER_NAME;	/* some sanity check because you can open a printer or a print server */	/* aka: \\server\printer or \\server */	unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);	DEBUGADD(3,("checking name: %s\n",name));	if (!open_printer_hnd(p, handle, name, 0))		return WERR_INVALID_PRINTER_NAME;		Printer=find_printer_index_by_hnd(p, handle);	if ( !Printer ) {		DEBUG(0,(" _spoolss_open_printer_ex: logic error.  Can't find printer "			"handle we created for printer %s\n", name ));		close_printer_handle(p,handle);		return WERR_INVALID_PRINTER_NAME;	}	get_current_user(&user, p);	/*	 * First case: the user is opening the print server:	 *	 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k	 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.	 *	 * Then both Win2k and WinNT clients try an OpenPrinterEx with	 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)	 * or if the user is listed in the smb.conf printer admin parameter.	 *	 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the	 * client view printer folder, but does not show the MSAPW.	 *	 * Note: this test needs code to check access rights here too. Jeremy	 * could you look at this?	 * 	 * Second case: the user is opening a printer:	 * NT doesn't let us connect to a printer if the connecting user	 * doesn't have print permission.	 */	if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) 	{		/* Printserver handles use global struct... */		snum = -1;		/* Map standard access rights to object specific access rights */				se_map_standard(&printer_default->access_required, 				&printserver_std_mapping);			/* Deny any object specific bits that don't apply to print		   servers (i.e printer and job specific bits) */		printer_default->access_required &= SPECIFIC_RIGHTS_MASK;		if (printer_default->access_required &		    ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {			DEBUG(3, ("access DENIED for non-printserver bits\n"));			close_printer_handle(p, handle);			return WERR_ACCESS_DENIED;		}		/* Allow admin access */		if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER ) 		{			SE_PRIV se_printop = SE_PRINT_OPERATOR;			if (!lp_ms_add_printer_wizard()) {				close_printer_handle(p, handle);				return WERR_ACCESS_DENIED;			}			/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,			   and not a printer admin, then fail */						if ( user.uid != 0				&& !user_has_privileges( user.nt_user_token, &se_printop )				&& !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )			{				close_printer_handle(p, handle);				return WERR_ACCESS_DENIED;			}						printer_default->access_required = SERVER_ACCESS_ADMINISTER;		}		else		{			printer_default->access_required = SERVER_ACCESS_ENUMERATE;		}		DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER) 			? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));					/* We fall through to return WERR_OK */			}	else	{		/* NT doesn't let us connect to a printer if the connecting user		   doesn't have print permission.  */		if (!get_printer_snum(p, handle, &snum)) {			close_printer_handle(p, handle);			return WERR_BADFID;		}		se_map_standard(&printer_default->access_required, &printer_std_mapping);				/* map an empty access mask to the minimum access mask */		if (printer_default->access_required == 0x0)			printer_default->access_required = PRINTER_ACCESS_USE;		/*		 * If we are not serving the printer driver for this printer,		 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This		 * will keep NT clients happy  --jerry			 */		 		if (lp_use_client_driver(snum) 			&& (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))		{			printer_default->access_required = PRINTER_ACCESS_USE;		}		/* check smb.conf parameters and the the sec_desc */				if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {    			DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));			return WERR_ACCESS_DENIED;		}		if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {			DEBUG(3, ("access DENIED for printer open\n"));			close_printer_handle(p, handle);			return WERR_ACCESS_DENIED;		}		if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {			DEBUG(3, ("access DENIED for printer open - unknown bits\n"));			close_printer_handle(p, handle);			return WERR_ACCESS_DENIED;		}		if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)			printer_default->access_required = PRINTER_ACCESS_ADMINISTER;		else			printer_default->access_required = PRINTER_ACCESS_USE;		DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER) 			? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));	}		Printer->access_granted = printer_default->access_required;		/* 	 * If the client sent a devmode in the OpenPrinter() call, then	 * save it here in case we get a job submission on this handle	 */		 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)	 	&& q_u->printer_default.devmode_cont.devmode_ptr )	 { 	 	convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,			&Printer->nt_devmode );	 }#if 0	/* JERRY -- I'm doubtful this is really effective */	/* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN 	   optimization in Windows 2000 clients  --jerry */	if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER) 		&& (RA_WIN2K == get_remote_arch()) )	{		DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));		sys_usleep( 500000 );	}#endif	return WERR_OK;}/********************************************************************************************************************************************************/static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,				NT_PRINTER_INFO_LEVEL *printer, uint32 level){	BOOL ret;	switch (level) {		case 2:			/* allocate memory if needed.  Messy because 			   convert_printer_info is used to update an existing 			   printer or build a new one */			if ( !printer->info_2 ) {				printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );				if ( !printer->info_2 ) {					DEBUG(0,("convert_printer_info: talloc() failed!\n"));					return False;				}			}			ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);			printer->info_2->setuptime = time(NULL);			return ret;	}	return False;}static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,                                 	NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level){	BOOL result = True;	switch (level) {		case 3:			printer->info_3=NULL;			if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))				result = False;			break;		case 6:			printer->info_6=NULL;			if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))				result = False;			break;		default:			break;	}	return result;}BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,				NT_DEVICEMODE **pp_nt_devmode){	NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;	/*	 * Ensure nt_devmode is a valid pointer	 * as we will be overwriting it.	 */			if (nt_devmode == NULL) {		DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));		if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)

⌨️ 快捷键说明

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