2002-02-01 19:15:53 +03:00
/*
Unix SMB / CIFS implementation .
2002-02-01 19:58:01 +03:00
ads ( active directory ) printer utility library
2003-08-01 19:21:20 +04:00
Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2002
2002-02-01 19:15:53 +03:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2002-02-01 19:15:53 +03:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2002-02-01 19:15:53 +03:00
*/
# include "includes.h"
2009-11-26 20:21:28 +03:00
# include "../librpc/gen_ndr/cli_spoolss.h"
2010-05-18 20:26:48 +04:00
# include "rpc_client/cli_spoolss.h"
2009-10-02 02:17:06 +04:00
# include "registry.h"
2002-02-01 19:15:53 +03:00
# ifdef HAVE_ADS
2002-02-02 05:04:01 +03:00
/*
find a printer given the name and the hostname
Note that results " res " may be allocated on return so that the
results can be used . It should be freed using ads_msgfree .
*/
2006-09-04 01:07:16 +04:00
ADS_STATUS ads_find_printer_on_server ( ADS_STRUCT * ads , LDAPMessage * * res ,
const char * printer ,
const char * servername )
2002-02-02 05:04:01 +03:00
{
ADS_STATUS status ;
2008-12-23 22:27:19 +03:00
char * srv_dn , * * srv_cn , * s = NULL ;
2002-02-02 05:04:01 +03:00
const char * attrs [ ] = { " * " , " nTSecurityDescriptor " , NULL } ;
status = ads_find_machine_acct ( ads , res , servername ) ;
if ( ! ADS_ERR_OK ( status ) ) {
2004-09-23 23:24:02 +04:00
DEBUG ( 1 , ( " ads_find_printer_on_server: cannot find host %s in ads \n " ,
2002-02-02 05:04:01 +03:00
servername ) ) ;
return status ;
}
2006-10-02 16:06:49 +04:00
if ( ads_count_replies ( ads , * res ) ! = 1 ) {
2008-12-23 22:27:19 +03:00
if ( res ) {
ads_msgfree ( ads , * res ) ;
* res = NULL ;
}
2006-10-02 16:06:49 +04:00
return ADS_ERROR ( LDAP_NO_SUCH_OBJECT ) ;
}
2007-07-16 15:08:00 +04:00
srv_dn = ldap_get_dn ( ads - > ldap . ld , * res ) ;
2006-10-02 16:06:49 +04:00
if ( srv_dn = = NULL ) {
2008-12-23 22:27:19 +03:00
if ( res ) {
ads_msgfree ( ads , * res ) ;
* res = NULL ;
}
2006-10-02 16:06:49 +04:00
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
2002-07-15 14:35:28 +04:00
srv_cn = ldap_explode_dn ( srv_dn , 1 ) ;
2006-10-02 16:06:49 +04:00
if ( srv_cn = = NULL ) {
ldap_memfree ( srv_dn ) ;
2008-12-23 22:27:19 +03:00
if ( res ) {
ads_msgfree ( ads , * res ) ;
* res = NULL ;
}
2006-10-02 16:06:49 +04:00
return ADS_ERROR ( LDAP_INVALID_DN_SYNTAX ) ;
}
2008-12-23 22:27:19 +03:00
if ( res ) {
ads_msgfree ( ads , * res ) ;
* res = NULL ;
}
2002-02-02 05:04:01 +03:00
2008-12-23 22:27:19 +03:00
if ( asprintf ( & s , " (cn=%s-%s) " , srv_cn [ 0 ] , printer ) = = - 1 ) {
ldap_memfree ( srv_dn ) ;
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
2003-06-13 08:29:20 +04:00
status = ads_search ( ads , res , s , attrs ) ;
2002-02-02 05:04:01 +03:00
2002-07-15 14:35:28 +04:00
ldap_memfree ( srv_dn ) ;
ldap_value_free ( srv_cn ) ;
2008-12-23 22:27:19 +03:00
SAFE_FREE ( s ) ;
2002-02-02 05:04:01 +03:00
return status ;
}
2006-09-04 01:07:16 +04:00
ADS_STATUS ads_find_printers ( ADS_STRUCT * ads , LDAPMessage * * res )
2003-07-03 09:08:51 +04:00
{
2005-07-21 13:28:12 +04:00
const char * ldap_expr ;
2003-07-03 09:08:51 +04:00
const char * attrs [ ] = { " objectClass " , " printerName " , " location " , " driverName " ,
" serverName " , " description " , NULL } ;
/* For the moment only display all printers */
2005-05-31 17:46:45 +04:00
ldap_expr = " (&(!(showInAdvancedViewOnly=TRUE))(uncName=*) "
" (objectCategory=printQueue)) " ;
2003-07-03 09:08:51 +04:00
return ads_search ( ads , res , ldap_expr , attrs ) ;
}
2002-02-01 19:15:53 +03:00
/*
2002-11-18 22:59:58 +03:00
modify a printer entry in the directory
2002-02-01 19:15:53 +03:00
*/
ADS_STATUS ads_mod_printer_entry ( ADS_STRUCT * ads , char * prt_dn ,
2002-11-18 22:59:58 +03:00
TALLOC_CTX * ctx , const ADS_MODLIST * mods )
2002-02-01 19:15:53 +03:00
{
2002-11-18 22:59:58 +03:00
return ads_gen_mod ( ads , prt_dn , * mods ) ;
2002-02-01 19:15:53 +03:00
}
/*
add a printer to the directory
*/
2002-11-18 22:59:58 +03:00
ADS_STATUS ads_add_printer_entry ( ADS_STRUCT * ads , char * prt_dn ,
TALLOC_CTX * ctx , ADS_MODLIST * mods )
2002-02-01 19:15:53 +03:00
{
2002-11-18 22:59:58 +03:00
ads_mod_str ( ctx , mods , " objectClass " , " printQueue " ) ;
return ads_gen_add ( ads , prt_dn , * mods ) ;
}
2002-02-12 21:22:47 +03:00
2002-11-18 22:59:58 +03:00
/*
map a REG_SZ to an ldap mod
*/
2007-10-19 04:40:25 +04:00
static bool map_sz ( TALLOC_CTX * ctx , ADS_MODLIST * mods ,
2009-03-24 00:27:59 +03:00
const struct regval_blob * value )
2002-11-18 22:59:58 +03:00
{
char * str_value = NULL ;
2008-04-30 01:36:24 +04:00
size_t converted_size ;
2002-11-18 23:45:46 +03:00
ADS_STATUS status ;
2002-02-12 21:22:47 +03:00
2002-11-18 22:59:58 +03:00
if ( value - > type ! = REG_SZ )
2008-04-30 01:36:24 +04:00
return false ;
2002-02-12 21:22:47 +03:00
2002-11-18 22:59:58 +03:00
if ( value - > size & & * ( ( smb_ucs2_t * ) value - > data_p ) ) {
2008-04-30 01:36:24 +04:00
if ( ! pull_ucs2_talloc ( ctx , & str_value ,
( const smb_ucs2_t * ) value - > data_p ,
& converted_size ) )
{
return false ;
}
2002-11-18 23:45:46 +03:00
status = ads_mod_str ( ctx , mods , value - > valuename , str_value ) ;
return ADS_ERR_OK ( status ) ;
2002-11-18 22:59:58 +03:00
}
2008-04-30 01:36:24 +04:00
return true ;
2002-11-18 22:59:58 +03:00
}
2002-02-12 21:22:47 +03:00
2002-11-18 22:59:58 +03:00
/*
map a REG_DWORD to an ldap mod
*/
2007-10-19 04:40:25 +04:00
static bool map_dword ( TALLOC_CTX * ctx , ADS_MODLIST * mods ,
2009-03-24 00:27:59 +03:00
const struct regval_blob * value )
2002-11-18 22:59:58 +03:00
{
char * str_value = NULL ;
2002-11-18 23:45:46 +03:00
ADS_STATUS status ;
2002-02-12 21:22:47 +03:00
2002-11-18 22:59:58 +03:00
if ( value - > type ! = REG_DWORD )
return False ;
str_value = talloc_asprintf ( ctx , " %d " , * ( ( uint32 * ) value - > data_p ) ) ;
2006-06-17 03:26:48 +04:00
if ( ! str_value ) {
return False ;
}
2002-11-18 23:45:46 +03:00
status = ads_mod_str ( ctx , mods , value - > valuename , str_value ) ;
return ADS_ERR_OK ( status ) ;
2002-11-18 22:59:58 +03:00
}
2002-02-12 21:22:47 +03:00
2002-11-18 22:59:58 +03:00
/*
map a boolean REG_BINARY to an ldap mod
*/
2007-10-19 04:40:25 +04:00
static bool map_bool ( TALLOC_CTX * ctx , ADS_MODLIST * mods ,
2009-03-24 00:27:59 +03:00
const struct regval_blob * value )
2002-11-18 22:59:58 +03:00
{
char * str_value ;
2002-11-18 23:45:46 +03:00
ADS_STATUS status ;
2002-02-01 19:15:53 +03:00
2002-11-18 22:59:58 +03:00
if ( ( value - > type ! = REG_BINARY ) | | ( value - > size ! = 1 ) )
return False ;
str_value = talloc_asprintf ( ctx , " %s " ,
* ( value - > data_p ) ? " TRUE " : " FALSE " ) ;
2006-06-17 03:26:48 +04:00
if ( ! str_value ) {
return False ;
}
2002-11-18 23:45:46 +03:00
status = ads_mod_str ( ctx , mods , value - > valuename , str_value ) ;
return ADS_ERR_OK ( status ) ;
2002-02-01 19:15:53 +03:00
}
/*
2002-11-18 22:59:58 +03:00
map a REG_MULTI_SZ to an ldap mod
2002-02-01 19:15:53 +03:00
*/
2007-10-19 04:40:25 +04:00
static bool map_multi_sz ( TALLOC_CTX * ctx , ADS_MODLIST * mods ,
2009-03-24 00:27:59 +03:00
const struct regval_blob * value )
2002-02-01 19:15:53 +03:00
{
2002-11-18 22:59:58 +03:00
char * * str_values = NULL ;
2008-04-30 01:36:24 +04:00
size_t converted_size ;
2002-11-18 22:59:58 +03:00
smb_ucs2_t * cur_str = ( smb_ucs2_t * ) value - > data_p ;
uint32 size = 0 , num_vals = 0 , i = 0 ;
2002-11-18 23:45:46 +03:00
ADS_STATUS status ;
2002-11-18 22:59:58 +03:00
if ( value - > type ! = REG_MULTI_SZ )
return False ;
while ( cur_str & & * cur_str & & ( size < value - > size ) ) {
size + = 2 * ( strlen_w ( cur_str ) + 1 ) ;
cur_str + = strlen_w ( cur_str ) + 1 ;
num_vals + + ;
} ;
if ( num_vals ) {
2004-12-07 21:25:53 +03:00
str_values = TALLOC_ARRAY ( ctx , char * , num_vals + 1 ) ;
2006-06-17 03:26:48 +04:00
if ( ! str_values ) {
return False ;
}
2002-11-18 22:59:58 +03:00
memset ( str_values , ' \0 ' ,
2004-12-07 21:25:53 +03:00
( num_vals + 1 ) * sizeof ( char * ) ) ;
2002-11-18 22:59:58 +03:00
cur_str = ( smb_ucs2_t * ) value - > data_p ;
2008-04-30 01:36:24 +04:00
for ( i = 0 ; i < num_vals ; i + + ) {
2003-02-19 15:31:16 +03:00
cur_str + = pull_ucs2_talloc ( ctx , & str_values [ i ] ,
2008-04-30 01:36:24 +04:00
cur_str , & converted_size ) ?
converted_size : ( size_t ) - 1 ;
}
2002-11-18 22:59:58 +03:00
2002-11-18 23:45:46 +03:00
status = ads_mod_strlist ( ctx , mods , value - > valuename ,
( const char * * ) str_values ) ;
return ADS_ERR_OK ( status ) ;
2002-11-18 22:59:58 +03:00
}
return True ;
}
2002-02-01 19:15:53 +03:00
2002-11-18 22:59:58 +03:00
struct valmap_to_ads {
2003-01-03 11:28:12 +03:00
const char * valname ;
2009-03-24 00:27:59 +03:00
bool ( * fn ) ( TALLOC_CTX * , ADS_MODLIST * , const struct regval_blob * ) ;
2002-11-18 22:59:58 +03:00
} ;
/*
map a REG_SZ to an ldap mod
*/
static void map_regval_to_ads ( TALLOC_CTX * ctx , ADS_MODLIST * mods ,
2009-03-24 00:27:59 +03:00
struct regval_blob * value )
2002-11-18 22:59:58 +03:00
{
2003-01-03 11:28:12 +03:00
const struct valmap_to_ads map [ ] = {
2002-12-03 22:42:39 +03:00
{ SPOOL_REG_ASSETNUMBER , map_sz } ,
{ SPOOL_REG_BYTESPERMINUTE , map_dword } ,
{ SPOOL_REG_DEFAULTPRIORITY , map_dword } ,
2002-12-05 22:13:40 +03:00
{ SPOOL_REG_DESCRIPTION , map_sz } ,
2002-12-03 22:42:39 +03:00
{ SPOOL_REG_DRIVERNAME , map_sz } ,
{ SPOOL_REG_DRIVERVERSION , map_dword } ,
{ SPOOL_REG_FLAGS , map_dword } ,
{ SPOOL_REG_LOCATION , map_sz } ,
{ SPOOL_REG_OPERATINGSYSTEM , map_sz } ,
{ SPOOL_REG_OPERATINGSYSTEMHOTFIX , map_sz } ,
{ SPOOL_REG_OPERATINGSYSTEMSERVICEPACK , map_sz } ,
{ SPOOL_REG_OPERATINGSYSTEMVERSION , map_sz } ,
{ SPOOL_REG_PORTNAME , map_multi_sz } ,
{ SPOOL_REG_PRINTATTRIBUTES , map_dword } ,
{ SPOOL_REG_PRINTBINNAMES , map_multi_sz } ,
{ SPOOL_REG_PRINTCOLLATE , map_bool } ,
{ SPOOL_REG_PRINTCOLOR , map_bool } ,
{ SPOOL_REG_PRINTDUPLEXSUPPORTED , map_bool } ,
{ SPOOL_REG_PRINTENDTIME , map_dword } ,
{ SPOOL_REG_PRINTFORMNAME , map_sz } ,
{ SPOOL_REG_PRINTKEEPPRINTEDJOBS , map_bool } ,
{ SPOOL_REG_PRINTLANGUAGE , map_multi_sz } ,
{ SPOOL_REG_PRINTMACADDRESS , map_sz } ,
{ SPOOL_REG_PRINTMAXCOPIES , map_sz } ,
{ SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED , map_dword } ,
{ SPOOL_REG_PRINTMAXXEXTENT , map_dword } ,
{ SPOOL_REG_PRINTMAXYEXTENT , map_dword } ,
{ SPOOL_REG_PRINTMEDIAREADY , map_multi_sz } ,
{ SPOOL_REG_PRINTMEDIASUPPORTED , map_multi_sz } ,
{ SPOOL_REG_PRINTMEMORY , map_dword } ,
{ SPOOL_REG_PRINTMINXEXTENT , map_dword } ,
{ SPOOL_REG_PRINTMINYEXTENT , map_dword } ,
{ SPOOL_REG_PRINTNETWORKADDRESS , map_sz } ,
{ SPOOL_REG_PRINTNOTIFY , map_sz } ,
{ SPOOL_REG_PRINTNUMBERUP , map_dword } ,
{ SPOOL_REG_PRINTORIENTATIONSSUPPORTED , map_multi_sz } ,
{ SPOOL_REG_PRINTOWNER , map_sz } ,
{ SPOOL_REG_PRINTPAGESPERMINUTE , map_dword } ,
{ SPOOL_REG_PRINTRATE , map_dword } ,
{ SPOOL_REG_PRINTRATEUNIT , map_sz } ,
{ SPOOL_REG_PRINTSEPARATORFILE , map_sz } ,
{ SPOOL_REG_PRINTSHARENAME , map_sz } ,
{ SPOOL_REG_PRINTSPOOLING , map_sz } ,
{ SPOOL_REG_PRINTSTAPLINGSUPPORTED , map_bool } ,
{ SPOOL_REG_PRINTSTARTTIME , map_dword } ,
{ SPOOL_REG_PRINTSTATUS , map_sz } ,
{ SPOOL_REG_PRIORITY , map_dword } ,
{ SPOOL_REG_SERVERNAME , map_sz } ,
{ SPOOL_REG_SHORTSERVERNAME , map_sz } ,
{ SPOOL_REG_UNCNAME , map_sz } ,
{ SPOOL_REG_URL , map_sz } ,
{ SPOOL_REG_VERSIONNUMBER , map_dword } ,
2002-11-18 22:59:58 +03:00
{ NULL , NULL }
} ;
int i ;
for ( i = 0 ; map [ i ] . valname ; i + + ) {
if ( StrCaseCmp ( map [ i ] . valname , value - > valuename ) = = 0 ) {
if ( ! map [ i ] . fn ( ctx , mods , value ) ) {
DEBUG ( 5 , ( " Add of value %s to modlist failed \n " , value - > valuename ) ) ;
} else {
DEBUG ( 7 , ( " Mapped value %s \n " , value - > valuename ) ) ;
}
2002-02-01 19:15:53 +03:00
}
}
2002-11-18 22:59:58 +03:00
}
2002-02-01 19:15:53 +03:00
2005-09-30 21:13:37 +04:00
WERROR get_remote_printer_publishing_data ( struct rpc_pipe_client * cli ,
2002-11-18 22:59:58 +03:00
TALLOC_CTX * mem_ctx ,
ADS_MODLIST * mods ,
2003-01-03 11:28:12 +03:00
const char * printer )
2002-11-18 22:59:58 +03:00
{
WERROR result ;
2009-02-09 20:10:18 +03:00
char * printername ;
2009-03-18 04:33:18 +03:00
struct spoolss_PrinterEnumValues * info ;
uint32_t count ;
2005-07-20 19:35:29 +04:00
uint32 i ;
2009-03-19 00:49:41 +03:00
struct policy_handle pol ;
2002-11-18 22:59:58 +03:00
2009-02-09 20:10:18 +03:00
if ( ( asprintf ( & printername , " %s \\ %s " , cli - > srv_name_slash , printer ) = = - 1 ) ) {
2002-11-18 22:59:58 +03:00
DEBUG ( 3 , ( " Insufficient memory \n " ) ) ;
return WERR_NOMEM ;
}
2009-02-09 20:49:34 +03:00
result = rpccli_spoolss_openprinter_ex ( cli , mem_ctx ,
printername ,
SEC_FLAG_MAXIMUM_ALLOWED ,
& pol ) ;
2002-11-18 22:59:58 +03:00
if ( ! W_ERROR_IS_OK ( result ) ) {
DEBUG ( 3 , ( " Unable to open printer %s, error is %s. \n " ,
2008-11-01 19:19:26 +03:00
printername , win_errstr ( result ) ) ) ;
2009-02-10 12:45:55 +03:00
SAFE_FREE ( printername ) ;
2002-11-18 22:59:58 +03:00
return result ;
}
2005-08-29 18:55:40 +04:00
2009-03-18 04:33:18 +03:00
result = rpccli_spoolss_enumprinterdataex ( cli , mem_ctx , & pol ,
SPOOL_DSDRIVER_KEY ,
0 ,
& count ,
& info ) ;
2002-11-18 22:59:58 +03:00
if ( ! W_ERROR_IS_OK ( result ) ) {
DEBUG ( 3 , ( " Unable to do enumdataex on %s, error is %s. \n " ,
2008-11-01 19:19:26 +03:00
printername , win_errstr ( result ) ) ) ;
2002-12-03 22:42:39 +03:00
} else {
/* Have the data we need now, so start building */
2009-03-18 04:33:18 +03:00
for ( i = 0 ; i < count ; i + + ) {
2009-03-24 00:27:59 +03:00
struct regval_blob v ;
2010-03-04 19:58:49 +03:00
fstrcpy ( v . valuename , info [ i ] . value_name ) ;
v . type = info [ i ] . type ;
v . data_p = info [ i ] . data - > data ;
v . size = info [ i ] . data - > length ;
map_regval_to_ads ( mem_ctx , mods , & v ) ;
2005-08-29 18:55:40 +04:00
}
2002-12-03 22:42:39 +03:00
}
2002-11-18 22:59:58 +03:00
2009-03-18 04:33:18 +03:00
result = rpccli_spoolss_enumprinterdataex ( cli , mem_ctx , & pol ,
SPOOL_DSSPOOLER_KEY ,
0 ,
& count ,
& info ) ;
2002-11-18 22:59:58 +03:00
if ( ! W_ERROR_IS_OK ( result ) ) {
DEBUG ( 3 , ( " Unable to do enumdataex on %s, error is %s. \n " ,
2008-11-01 19:19:26 +03:00
printername , win_errstr ( result ) ) ) ;
2002-12-03 22:42:39 +03:00
} else {
2009-03-18 04:33:18 +03:00
for ( i = 0 ; i < count ; i + + ) {
2009-03-24 00:27:59 +03:00
struct regval_blob v ;
2010-03-04 19:58:49 +03:00
fstrcpy ( v . valuename , info [ i ] . value_name ) ;
v . type = info [ i ] . type ;
v . data_p = info [ i ] . data - > data ;
v . size = info [ i ] . data - > length ;
map_regval_to_ads ( mem_ctx , mods , & v ) ;
2005-08-29 18:55:40 +04:00
}
2002-02-11 18:48:01 +03:00
}
2009-03-18 04:33:18 +03:00
ads_mod_str ( mem_ctx , mods , SPOOL_REG_PRINTERNAME , printer ) ;
2005-08-29 18:55:40 +04:00
2008-11-15 01:58:26 +03:00
rpccli_spoolss_ClosePrinter ( cli , mem_ctx , & pol , NULL ) ;
2009-02-10 12:45:55 +03:00
SAFE_FREE ( printername ) ;
2002-02-11 18:48:01 +03:00
2002-11-18 22:59:58 +03:00
return result ;
}
2002-02-01 19:15:53 +03:00
2007-10-19 04:40:25 +04:00
bool get_local_printer_publishing_data ( TALLOC_CTX * mem_ctx ,
2002-11-18 22:59:58 +03:00
ADS_MODLIST * mods ,
NT_PRINTER_DATA * data )
{
uint32 key , val ;
for ( key = 0 ; key < data - > num_keys ; key + + ) {
2009-03-23 20:14:17 +03:00
struct regval_ctr * ctr = data - > keys [ key ] . values ;
2005-08-29 18:55:40 +04:00
for ( val = 0 ; val < ctr - > num_values ; val + + )
map_regval_to_ads ( mem_ctx , mods , ctr - > values [ val ] ) ;
2002-11-18 22:59:58 +03:00
}
return True ;
2002-02-01 19:15:53 +03:00
}
# endif