summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/rpc_server/srv_lsa.c37
-rw-r--r--source3/rpc_server/srv_lsa_nt.c97
-rw-r--r--source3/rpc_server/srv_netlog_nt.c6
-rw-r--r--source3/rpc_server/srv_reg.c81
-rw-r--r--source3/rpc_server/srv_reg_nt.c730
-rw-r--r--source3/rpc_server/srv_samr.c40
-rw-r--r--source3/rpc_server/srv_samr_nt.c142
-rwxr-xr-xsource3/rpc_server/srv_spoolss.c63
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c1159
-rw-r--r--source3/rpc_server/srv_srvsvc.c31
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c394
-rw-r--r--source3/rpc_server/srv_util.c62
12 files changed, 1614 insertions, 1228 deletions
diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c
index e5a4d3b46d..e3495576c9 100644
--- a/source3/rpc_server/srv_lsa.c
+++ b/source3/rpc_server/srv_lsa.c
@@ -3,8 +3,9 @@
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Paul Ashton 1997.
- * Copyright (C) Jeremy Allison 2001.
+ * Copyright (C) Paul Ashton 1997,
+ * Copyright (C) Jeremy Allison 2001,
+ * Copyright (C) Jim McDonough 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
@@ -610,6 +611,37 @@ static BOOL api_lsa_query_secobj(pipes_struct *p)
}
/***************************************************************************
+ api_lsa_query_dnsdomainfo
+ ***************************************************************************/
+
+static BOOL api_lsa_query_info2(pipes_struct *p)
+{
+ LSA_Q_QUERY_INFO2 q_u;
+ LSA_R_QUERY_INFO2 r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!lsa_io_q_query_info2("", &q_u, data, 0)) {
+ DEBUG(0,("api_lsa_query_info2: failed to unmarshall LSA_Q_QUERY_INFO2.\n"));
+ return False;
+ }
+
+ r_u.status = _lsa_query_info2(p, &q_u, &r_u);
+
+ if (!lsa_io_r_query_info2("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_lsa_query_info2: failed to marshall LSA_R_QUERY_INFO2.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+
+/***************************************************************************
\PIPE\ntlsa commands
***************************************************************************/
@@ -634,6 +666,7 @@ static struct api_struct api_lsa_cmds[] =
{ "LSA_ADDPRIVS" , LSA_ADDPRIVS , api_lsa_addprivs },
{ "LSA_REMOVEPRIVS" , LSA_REMOVEPRIVS , api_lsa_removeprivs },
{ "LSA_QUERYSECOBJ" , LSA_QUERYSECOBJ , api_lsa_query_secobj },
+ { "LSA_QUERYINFO2" , LSA_QUERYINFO2 , api_lsa_query_info2 },
{ NULL , 0 , NULL }
};
diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c
index d072061a5f..f28441886a 100644
--- a/source3/rpc_server/srv_lsa_nt.c
+++ b/source3/rpc_server/srv_lsa_nt.c
@@ -5,7 +5,8 @@
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997,
* Copyright (C) Jeremy Allison 2001,
- * Copyright (C) Rafal Szczesniak 2002.
+ * Copyright (C) Rafal Szczesniak 2002,
+ * Copyright (C) Jim McDonough 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
@@ -342,6 +343,48 @@ static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *s
}
/***************************************************************************
+ init_dns_dom_info.
+ ***************************************************************************/
+static void init_dns_dom_info(LSA_DNS_DOM_INFO *r_l, char *nb_name,
+ char *dns_name, char *forest_name,
+ GUID *dom_guid, DOM_SID *dom_sid)
+{
+ if (nb_name && *nb_name) {
+ init_uni_hdr(&r_l->hdr_nb_dom_name, strlen(nb_name));
+ init_unistr2(&r_l->uni_nb_dom_name, nb_name,
+ strlen(nb_name));
+ r_l->hdr_nb_dom_name.uni_max_len += 2;
+ r_l->uni_nb_dom_name.uni_max_len += 1;
+ }
+
+ if (dns_name && *dns_name) {
+ init_uni_hdr(&r_l->hdr_dns_dom_name, strlen(dns_name));
+ init_unistr2(&r_l->uni_dns_dom_name, dns_name,
+ strlen(dns_name));
+ r_l->hdr_dns_dom_name.uni_max_len += 2;
+ r_l->uni_dns_dom_name.uni_max_len += 1;
+ }
+
+ if (forest_name && *forest_name) {
+ init_uni_hdr(&r_l->hdr_forest_name, strlen(forest_name));
+ init_unistr2(&r_l->uni_forest_name, forest_name,
+ strlen(forest_name));
+ r_l->hdr_forest_name.uni_max_len += 2;
+ r_l->uni_forest_name.uni_max_len += 1;
+ }
+
+ /* how do we init the guid ? probably should write an init fn */
+ if (dom_guid) {
+ memcpy(&r_l->dom_guid, dom_guid, sizeof(GUID));
+ }
+
+ if (dom_sid) {
+ r_l->ptr_dom_sid = 1;
+ init_dom_sid2(&r_l->dom_sid, dom_sid);
+ }
+}
+
+/***************************************************************************
_lsa_open_policy2.
***************************************************************************/
@@ -1166,3 +1209,55 @@ NTSTATUS _lsa_query_secobj(pipes_struct *p, LSA_Q_QUERY_SEC_OBJ *q_u, LSA_R_QUER
}
+NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_INFO2 *r_u)
+{
+ struct lsa_info *handle;
+ char *nb_name = NULL;
+ char *dns_name = NULL;
+ char *forest_name = NULL;
+ DOM_SID *sid = NULL;
+ GUID guid;
+
+ ZERO_STRUCT(guid);
+ r_u->status = NT_STATUS_OK;
+
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
+ return NT_STATUS_INVALID_HANDLE;
+
+ switch (q_u->info_class) {
+ case 0x0c:
+ /* check if the user have enough rights */
+ if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
+ return NT_STATUS_ACCESS_DENIED;
+
+ /* Request PolicyPrimaryDomainInformation. */
+ switch (lp_server_role()) {
+ case ROLE_DOMAIN_PDC:
+ case ROLE_DOMAIN_BDC:
+ nb_name = global_myworkgroup;
+ /* ugly temp hack for these next two */
+ dns_name = lp_realm();
+ forest_name = lp_realm();
+ sid = get_global_sam_sid();
+ secrets_fetch_domain_guid(global_myworkgroup,
+ &guid);
+ break;
+ default:
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ }
+ init_dns_dom_info(&r_u->info.dns_dom_info, nb_name, dns_name,
+ forest_name,&guid,sid);
+ break;
+ default:
+ DEBUG(0,("_lsa_query_info2: unknown info level in Lsa Query: %d\n", q_u->info_class));
+ r_u->status = NT_STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ if (NT_STATUS_IS_OK(r_u->status)) {
+ r_u->ptr = 0x1;
+ r_u->info_class = q_u->info_class;
+ }
+
+ return r_u->status;
+}
diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c
index 4ab9c470d0..8f6011826a 100644
--- a/source3/rpc_server/srv_netlog_nt.c
+++ b/source3/rpc_server/srv_netlog_nt.c
@@ -280,7 +280,7 @@ NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u)
/* from client / server challenges and md4 password, generate sess key */
cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
- (char *)p->dc.md4pw, p->dc.sess_key);
+ p->dc.md4pw, p->dc.sess_key);
/* check that the client credentials are valid */
if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
@@ -342,7 +342,7 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
/* from client / server challenges and md4 password, generate sess key */
cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
- (char *)p->dc.md4pw, p->dc.sess_key);
+ p->dc.md4pw, p->dc.sess_key);
/* check that the client credentials are valid */
if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
@@ -708,7 +708,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
pdb_get_username(sampw),
pdb_get_fullname(sampw),
pdb_get_homedir(sampw),
- pdb_get_dirdrive(sampw),
+ pdb_get_dir_drive(sampw),
pdb_get_logon_script(sampw),
pdb_get_profile_path(sampw),
pdb_get_logon_time(sampw),
diff --git a/source3/rpc_server/srv_reg.c b/source3/rpc_server/srv_reg.c
index a096325860..d0aaf0199b 100644
--- a/source3/rpc_server/srv_reg.c
+++ b/source3/rpc_server/srv_reg.c
@@ -83,7 +83,7 @@ static BOOL api_reg_open_hklm(pipes_struct *p)
}
/*******************************************************************
- api_reg_open_khlm
+ api_reg_open_khu
********************************************************************/
static BOOL api_reg_open_hku(pipes_struct *p)
@@ -108,6 +108,32 @@ static BOOL api_reg_open_hku(pipes_struct *p)
return True;
}
+/*******************************************************************
+ api_reg_open_khcr
+ ********************************************************************/
+
+static BOOL api_reg_open_hkcr(pipes_struct *p)
+{
+ REG_Q_OPEN_HKCR q_u;
+ REG_R_OPEN_HKCR r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ /* grab the reg open */
+ if(!reg_io_q_open_hkcr("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _reg_open_hkcr(p, &q_u, &r_u);
+
+ if(!reg_io_r_open_hkcr("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
/*******************************************************************
api_reg_open_entry
@@ -290,6 +316,56 @@ static BOOL api_reg_enum_key(pipes_struct *p)
return True;
}
+/*******************************************************************
+ api_reg_enum_value
+ ********************************************************************/
+
+static BOOL api_reg_enum_value(pipes_struct *p)
+{
+ REG_Q_ENUM_VALUE q_u;
+ REG_R_ENUM_VALUE r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!reg_io_q_enum_val("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _reg_enum_value(p, &q_u, &r_u);
+
+ if(!reg_io_r_enum_val("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ api_reg_save_key
+ ********************************************************************/
+
+static BOOL api_reg_save_key(pipes_struct *p)
+{
+ REG_Q_SAVE_KEY q_u;
+ REG_R_SAVE_KEY r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!reg_io_q_save_key("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _reg_save_key(p, &q_u, &r_u);
+
+ if(!reg_io_r_save_key("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+
/*******************************************************************
@@ -299,14 +375,17 @@ static struct api_struct api_reg_cmds[] =
{
{ "REG_CLOSE" , REG_CLOSE , api_reg_close },
{ "REG_OPEN_ENTRY" , REG_OPEN_ENTRY , api_reg_open_entry },
+ { "REG_OPEN_HKCR" , REG_OPEN_HKCR , api_reg_open_hkcr },
{ "REG_OPEN_HKLM" , REG_OPEN_HKLM , api_reg_open_hklm },
{ "REG_OPEN_HKU" , REG_OPEN_HKU , api_reg_open_hku },
{ "REG_ENUM_KEY" , REG_ENUM_KEY , api_reg_enum_key },
+ { "REG_ENUM_VALUE" , REG_ENUM_VALUE , api_reg_enum_value },
{ "REG_QUERY_KEY" , REG_QUERY_KEY , api_reg_query_key },
{ "REG_INFO" , REG_INFO , api_reg_info },
{ "REG_SHUTDOWN" , REG_SHUTDOWN , api_reg_shutdown },
{ "REG_ABORT_SHUTDOWN" , REG_ABORT_SHUTDOWN , api_reg_abort_shutdown },
{ "REG_UNKNOWN_1A" , REG_UNKNOWN_1A , api_reg_unknown_1a },
+ { "REG_SAVE_KEY" , REG_SAVE_KEY , api_reg_save_key },
{ NULL , 0 , NULL }
};
diff --git a/source3/rpc_server/srv_reg_nt.c b/source3/rpc_server/srv_reg_nt.c
index 3f07e4aaea..cd9596d2a7 100644
--- a/source3/rpc_server/srv_reg_nt.c
+++ b/source3/rpc_server/srv_reg_nt.c
@@ -1,12 +1,11 @@
/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
- * Copyright (C) Andrew Tridgell 1992-1997,
- * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Paul Ashton 1997.
- * Copyright (C) Hewlett-Packard Company 1999.
- * Copyright (C) Jeremy Allison 2001.
- * Copyright (C) Gerald Carter 2002.
+ * Copyright (C) Andrew Tridgell 1992-1997.
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
+ * Copyright (C) Paul Ashton 1997.
+ * Copyright (C) Jeremy Allison 2001.
+ * Copyright (C) Gerald Carter 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
@@ -30,386 +29,134 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
-#define KEY_HKLM "HKLM"
-#define KEY_HKU "HKU"
+#define REGSTR_PRODUCTTYPE "ProductType"
+#define REG_PT_WINNT "WinNT"
+#define REG_PT_LANMANNT "LanmanNT"
+#define REG_PT_SERVERNT "ServerNT"
#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())
-/* structure to store the registry handles */
-typedef struct _RegistryKey {
- struct _RegistryKey *prev, *next;
+static REGISTRY_KEY *regkeys_list;
- fstring name; /* name of registry key */
- POLICY_HND hnd;
-
-} Registry_Key;
-
-static Registry_Key *regkeys_list;
-static TDB_CONTEXT *tdb_reg;
-/***********************************************************************
- Add subkey strings to the registry tdb under a defined key
- fmt is the same format as tdb_pack except this function only supports
- fstrings
- ***********************************************************************/
+/******************************************************************
+ free() function for REGISTRY_KEY
+ *****************************************************************/
-static BOOL store_reg_keys( TDB_CONTEXT *tdb, char *keyname, char **subkeys, uint32 num_subkeys )
+static void free_regkey_info(void *ptr)
{
- TDB_DATA kbuf, dbuf;
- char *buffer, *tmpbuf;
- int i = 0;
- uint32 len, buflen;
- BOOL ret = True;
-
- if ( !keyname )
- return False;
-
- /* allocate some initial memory */
-
- buffer = malloc(sizeof(pstring));
- buflen = sizeof(pstring);
- len = 0;
-
- /* store the number of subkeys */
-
- len += tdb_pack(buffer+len, buflen-len, "d", num_subkeys);
-
- /* pack all the strings */
-
- for (i=0; i<num_subkeys; i++) {
- len += tdb_pack(buffer+len, buflen-len, "f", subkeys[i]);
- if ( len > buflen ) {
- /* allocate some extra space */
- if ((tmpbuf = Realloc( buffer, len*2 )) == NULL) {
- DEBUG(0,("store_reg_keys: Failed to realloc memory of size [%d]\n", len*2));
- ret = False;
- goto done;
- }
- buffer = tmpbuf;
- buflen = len*2;
-
- len = tdb_pack(buffer+len, buflen-len, "f", subkeys[i]);
- }
- }
-
- /* finally write out the data */
+ REGISTRY_KEY *info = (REGISTRY_KEY*)ptr;
- kbuf.dptr = keyname;
- kbuf.dsize = strlen(keyname)+1;
- dbuf.dptr = buffer;
- dbuf.dsize = len;
- if ( tdb_store( tdb, kbuf, dbuf, TDB_REPLACE ) == -1) {
- ret = False;
- goto done;
- }
+ DLIST_REMOVE(regkeys_list, info);
-done:
- SAFE_FREE( buffer );
- return ret;
+ SAFE_FREE(info);
}
-/***********************************************************************
- Retrieve an array of strings containing subkeys. Memory should be
- released by the caller. The subkeys are stored in a catenated string
- of null terminated character strings
- ***********************************************************************/
+/******************************************************************
+ Find a registry key handle and return a REGISTRY_KEY
+ *****************************************************************/
-static int fetch_reg_keys( TDB_CONTEXT *tdb, char* key, char **subkeys )
+static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
{
- pstring path;
- uint32 num_items;
- TDB_DATA dbuf;
- char *buf;
- uint32 buflen, len;
- int i;
- char *s;
-
-
- pstrcpy( path, key );
-
- /* convert to key format */
- pstring_sub( path, "\\", "/" );
-
- dbuf = tdb_fetch_by_string( tdb, path );
-
- buf = dbuf.dptr;
- buflen = dbuf.dsize;
-
- if ( !buf ) {
- DEBUG(5,("fetch_reg_keys: Failed to fetch any subkeys for [%s]\n", key));
- return 0;
- }
-
- len = tdb_unpack( buf, buflen, "d", &num_items);
- if (num_items) {
- if ( (*subkeys = (char*)malloc(sizeof(fstring)*num_items)) == NULL ) {
- DEBUG(0,("fetch_reg_keys: Failed to malloc memory for subkey array containing [%d] items!\n",
- num_items));
- num_items = -1;
- goto done;
- }
- }
-
- s = *subkeys;
- for (i=0; i<num_items; i++) {
- len += tdb_unpack( buf+len, buflen-len, "f", s );
- s += strlen(s) + 1;
- }
-
-done:
- SAFE_FREE(dbuf.dptr);
- return num_items;
-}
-
-/***********************************************************************
- count the number of subkeys dtored in the registry
- ***********************************************************************/
+ REGISTRY_KEY *regkey = NULL;
-static int fetch_reg_keys_count( TDB_CONTEXT *tdb, char* key )
-{
- pstring path;
- uint32 num_items;
- TDB_DATA dbuf;
- char *buf;
- uint32 buflen, len;
-
-
- pstrcpy( path, key );
-
- /* convert to key format */
- pstring_sub( path, "\\", "/" );
-
- dbuf = tdb_fetch_by_string( tdb, path );
-
- buf = dbuf.dptr;
- buflen = dbuf.dsize;
-
- if ( !buf ) {
- DEBUG(5,("fetch_reg_keys: Failed to fetch any subkeys for [%s]\n", key));
- return 0;
+ if(!find_policy_by_hnd(p,hnd,(void **)&regkey)) {
+ DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
+ return NULL;
}
-
- len = tdb_unpack( buf, buflen, "d", &num_items);
-
- SAFE_FREE( buf );
-
- return num_items;
-}
-/***********************************************************************
- retreive a specific subkey specified by index. The subkey parameter
- is assumed to be an fstring.
- ***********************************************************************/
-
-static BOOL fetch_reg_keys_specific( TDB_CONTEXT *tdb, char* key, char* subkey,
- uint32 key_index )
-{
- int num_subkeys, i;
- char *subkeys = NULL;
- char *s;
-
- num_subkeys = fetch_reg_keys( tdb_reg, key, &subkeys );
- if ( num_subkeys == -1 )
- return False;
-
- s = subkeys;
- for ( i=0; i<num_subkeys; i++ ) {
- /* copy the key if the index matches */
- if ( i == key_index ) {
- fstrcpy( subkey, s );
- break;
- }
-
- /* go onto the next string */
- s += strlen(s) + 1;
- }
-
- SAFE_FREE(subkeys);
-
- return True;
+ return regkey;
}
-/***********************************************************************
- Open the registry database
- ***********************************************************************/
+/*******************************************************************
+ Function for open a new registry handle and creating a handle
+ Note that P should be valid & hnd should already have space
-static BOOL init_registry_data( TDB_CONTEXT* registry_tdb )
+ When we open a key, we store the full path to the key as
+ HK[LM|U]\<key>\<key>\...
+ *******************************************************************/
+
+static NTSTATUS open_registry_key(pipes_struct *p, POLICY_HND *hnd, REGISTRY_KEY *parent,
+ char *subkeyname, uint32 access_granted )
{
- pstring keyname;
- char *subkeys[3];
-
- /* HKEY_LOCAL_MACHINE */
+ REGISTRY_KEY *regkey = NULL;
+ NTSTATUS result = NT_STATUS_OK;
+ REGSUBKEY_CTR subkeys;
- pstrcpy( keyname, KEY_HKLM );
- subkeys[0] = "SYSTEM";
- if ( !store_reg_keys( registry_tdb, keyname, subkeys, 1 ))
- return False;
-
- pstrcpy( keyname, KEY_HKLM );
- pstrcat( keyname, "/SYSTEM" );
- subkeys[0] = "CurrentControlSet";
- if ( !store_reg_keys( registry_tdb, keyname, subkeys, 1 ))
- return False;
-
- pstrcpy( keyname, KEY_HKLM );
- pstrcat( keyname, "/SYSTEM/CurrentControlSet" );
- subkeys[0] = "Control";
- subkeys[1] = "services";
- if ( !store_reg_keys( registry_tdb, keyname, subkeys, 2 ))
- return False;
-
- pstrcpy( keyname, KEY_HKLM );
- pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control" );
- subkeys[0] = "Print";
- subkeys[1] = "ProduceOptions";
- if ( !store_reg_keys( registry_tdb, keyname, subkeys, 2 ))
- return False;
-
- pstrcpy( keyname, KEY_HKLM );
- pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control/Print" );
- subkeys[0] = "Environments";
- subkeys[1] = "Forms";
- subkeys[2] = "Printers";
- if ( !store_reg_keys( registry_tdb, keyname, subkeys, 3 ))
- return False;
-
- pstrcpy( keyname, KEY_HKLM );
- pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control/ProductOptions" );
- if ( !store_reg_keys( registry_tdb, keyname, subkeys, 0 ))
- return False;
-
- pstrcpy( keyname, KEY_HKLM );
- pstrcat( keyname, "/SYSTEM/CurrentControlSet/services" );
- subkeys[0] = "Netlogon";
- if ( !store_reg_keys( registry_tdb, keyname, subkeys, 1 ))
- return False;
-
- pstrcpy( keyname, KEY_HKLM );
- pstrcat( keyname, "/SYSTEM/CurrentControlSet/services/Netlogon" );
- subkeys[0] = "parameters";
- if ( !store_reg_keys( registry_tdb, keyname, subkeys, 1 ))
- return False;
-
- pstrcpy( keyname, KEY_HKLM );
- pstrcat( keyname, "/SYSTEM/CurrentControlSet/services/Netlogon/parameters" );
- if ( !store_reg_keys( registry_tdb, keyname, subkeys, 0 ))
- return False;
+ DEBUG(7,("open_registry_key: name = [%s][%s]\n",
+ parent ? parent->name : "NULL", subkeyname));
-
- /* HKEY_USER */
-
- pstrcpy( keyname, KEY_HKU );
- if ( !store_reg_keys( registry_tdb, keyname, subkeys, 0 ) )
- return False;
+ if ((regkey=(REGISTRY_KEY*)malloc(sizeof(REGISTRY_KEY))) == NULL)
+ return NT_STATUS_NO_MEMORY;
- return True;
-}
-
-/***********************************************************************
- Open the registry database
- ***********************************************************************/
-
-BOOL init_registry( void )
-{
- static pid_t local_pid;
-
+ ZERO_STRUCTP( regkey );
- if (tdb_reg && local_pid == sys_getpid())
- return True;
-
/*
- * try to open first without creating so we can determine
- * if we need to init the data in the registry
+ * very crazy, but regedit.exe on Win2k will attempt to call
+ * REG_OPEN_ENTRY with a keyname of "". We should return a new
+ * (second) handle here on the key->name. regedt32.exe does
+ * not do this stupidity. --jerry
*/
- tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
- if ( !tdb_reg )
- {
- tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
- if ( !tdb_reg ) {
- DEBUG(0,("init_registry: Failed to open registry %s (%s)\n",
- lock_path("registry.tdb"), strerror(errno) ));
- return False;
- }
-
- DEBUG(10,("init_registry: Successfully created registry tdb\n"));
-
- /* create the registry here */
- if ( !init_registry_data( tdb_reg ) ) {
- DEBUG(0,("init_registry: Failed to initiailize data in registry!\n"));
- return False;
+ if (!subkeyname || !*subkeyname ) {
+ pstrcpy( regkey->name, parent->name );
+ }
+ else {
+ pstrcpy( regkey->name, "" );
+ if ( parent ) {
+ pstrcat( regkey->name, parent->name );
+ pstrcat( regkey->name, "\\" );
}
+ pstrcat( regkey->name, subkeyname );
}
-
- local_pid = sys_getpid();
- return True;
-}
+ /* Look up the table of registry I/O operations */
-/******************************************************************
- Find a registry key handle and return a Registry_Key
- *****************************************************************/
-
-static Registry_Key *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
-{
- Registry_Key *regkey = NULL;
-
- if(!find_policy_by_hnd(p,hnd,(void **)&regkey)) {
- DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
- return NULL;
+ if ( !(regkey->hook = reghook_cache_find( regkey->name )) ) {
+ DEBUG(0,("open_registry_key: Failed to assigned a REGISTRY_HOOK to [%s]\n",
+ regkey->name ));
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
-
- return regkey;
-}
-
-
-/******************************************************************
- free() function for Registry_Key
- *****************************************************************/
-
-static void free_reg_info(void *ptr)
-{
- Registry_Key *info = (Registry_Key*)ptr;
- DLIST_REMOVE(regkeys_list, info);
-
- SAFE_FREE(info);
-}
-
-/*******************************************************************
- Function for open a new registry handle and creating a handle
- Note that P should be valid & hnd should already have space
- *******************************************************************/
-
-static BOOL open_registry_key(pipes_struct *p, POLICY_HND *hnd, char *name,
- uint32 access_granted)
-{
- Registry_Key *regkey = NULL;
-
- DEBUG(7,("open_registry_key: name = [%s]\n", name));
+ /* check if the path really exists; failed is indicated by -1 */
+ /* if the subkey count failed, bail out */
- /* All registry keys **must** have a name of non-zero length */
+ ZERO_STRUCTP( &subkeys );
- if (!name || !*name )
- return False;
-
- if ((regkey=(Registry_Key*)malloc(sizeof(Registry_Key))) == NULL)
- return False;
+ regsubkey_ctr_init( &subkeys );
+
+ if ( fetch_reg_keys( regkey, &subkeys ) == -1 ) {
+
+ /* don't really know what to return here */
- ZERO_STRUCTP( regkey );
+ result = NT_STATUS_NO_SUCH_FILE;
+ }
+ else {
+ /*
+ * This would previously return NT_STATUS_TOO_MANY_SECRETS
+ * that doesn't sound quite right to me --jerry
+ */
+
+ if ( !create_policy_hnd( p, hnd, free_regkey_info, regkey ) )
+ result = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
- DLIST_ADD( regkeys_list, regkey );
+ /* clean up */
- /* copy the name and obtain a handle */
+ regsubkey_ctr_destroy( &subkeys );
- fstrcpy( regkey->name, name );
+ if ( ! NT_STATUS_IS_OK(result) )
+ SAFE_FREE( regkey );
+ else
+ DLIST_ADD( regkeys_list, regkey );
+
DEBUG(7,("open_registry_key: exit\n"));
-
- return create_policy_hnd( p, hnd, free_reg_info, regkey );
+
+ return result;
}
/*******************************************************************
@@ -419,7 +166,7 @@ static BOOL open_registry_key(pipes_struct *p, POLICY_HND *hnd, char *name,
static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
{
- Registry_Key *regkey = find_regkey_index_by_hnd(p, hnd);
+ REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
if ( !regkey ) {
DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
@@ -435,35 +182,37 @@ static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
retrieve information about the subkeys
*******************************************************************/
-static BOOL get_subkey_information( Registry_Key *key, uint32 *maxnum, uint32 *maxlen )
+static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
{
- int num_subkeys, i;
- uint32 max_len;
- char *subkeys = NULL;
- uint32 len;
- char *s;
+ int num_subkeys, i;
+ uint32 max_len;
+ REGSUBKEY_CTR subkeys;
+ uint32 len;
if ( !key )
return False;
+
+ ZERO_STRUCTP( &subkeys );
- num_subkeys = fetch_reg_keys( tdb_reg, key->name, &subkeys );
- if ( num_subkeys == -1 )
+ regsubkey_ctr_init( &subkeys );
+
+ if ( fetch_reg_keys( key, &subkeys ) == -1 )
return False;
/* find the longest string */
max_len = 0;
- s = subkeys;
+ num_subkeys = regsubkey_ctr_numkeys( &subkeys );
+
for ( i=0; i<num_subkeys; i++ ) {
- len = strlen(s);
+ len = strlen( regsubkey_ctr_specific_key(&subkeys, i) );
max_len = MAX(max_len, len);
- s += len + 1;
}
*maxnum = num_subkeys;
*maxlen = max_len*2;
- SAFE_FREE(subkeys);
+ regsubkey_ctr_destroy( &subkeys );
return True;
}
@@ -474,30 +223,48 @@ static BOOL get_subkey_information( Registry_Key *key, uint32 *maxnum, uint32 *m
Samba tdb's (such as ntdrivers.tdb).
*******************************************************************/
-static BOOL get_value_information( Registry_Key *key, uint32 *maxnum,
+static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
uint32 *maxlen, uint32 *maxsize )
{
+ REGVAL_CTR values;
+ REGISTRY_VALUE *val;
+ uint32 sizemax, lenmax;
+ int i, num_values;
+
if ( !key )
return False;
- /* Hard coded key names first */
- /* nothing has valuies right now */
-
- *maxnum = 0;
- *maxlen = 0;
- *maxsize = 0;
- return True;
-#if 0 /* JERRY */
- /*
- * FIXME!!! Need to add routines to look up values in other
- * databases --jerry
- */
+ ZERO_STRUCTP( &values );
+
+ regval_ctr_init( &values );
+
+ if ( fetch_reg_values( key, &values ) == -1 )
+ return False;
+
+ lenmax = sizemax = 0;
+ num_values = regval_ctr_numvals( &values );
+
+ val = regval_ctr_specific_value( &values, 0 );
+
+ for ( i=0; i<num_values && val; i++ )
+ {
+ lenmax = MAX(lenmax, strlen(val->valuename)+1 );
+ sizemax = MAX(sizemax, val->size );
+
+ val = regval_ctr_specific_value( &values, i );
+ }
- return False;
-#endif
+ *maxnum = num_values;
+ *maxlen = lenmax;
+ *maxsize = sizemax;
+
+ regval_ctr_destroy( &values );
+
+ return True;
}
+
/********************************************************************
reg_close
********************************************************************/
@@ -515,27 +282,27 @@ NTSTATUS _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
}
/*******************************************************************
- reg_reply_open
********************************************************************/
NTSTATUS _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *r_u)
{
- if (!open_registry_key(p, &r_u->pol, KEY_HKLM, 0x0))
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, 0x0 );
+}
- return NT_STATUS_OK;
+/*******************************************************************
+ ********************************************************************/
+
+NTSTATUS _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HKCR *q_u, REG_R_OPEN_HKCR *r_u)
+{
+ return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, 0x0 );
}
/*******************************************************************
- reg_reply_open
********************************************************************/
NTSTATUS _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HKU *q_u, REG_R_OPEN_HKU *r_u)
{
- if (!open_registry_key(p, &r_u->pol, KEY_HKU, 0x0))
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-
- return NT_STATUS_OK;
+ return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, 0x0 );
}
/*******************************************************************
@@ -546,9 +313,8 @@ NTSTATUS _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTR
{
POLICY_HND pol;
fstring name;
- pstring path;
- int num_subkeys;
- Registry_Key *key = find_regkey_index_by_hnd(p, &q_u->pol);
+ REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->pol);
+ NTSTATUS result;
DEBUG(5,("reg_open_entry: Enter\n"));
@@ -556,26 +322,14 @@ NTSTATUS _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTR
return NT_STATUS_INVALID_HANDLE;
rpcstr_pull(name,q_u->uni_name.buffer,sizeof(name),q_u->uni_name.uni_str_len*2,0);
-
- /* store the full path in the regkey_list */
- pstrcpy( path, key->name );
- pstrcat( path, "\\" );
- pstrcat( path, name );
-
- DEBUG(5,("reg_open_entry: %s\n", path));
-
- /* do a check on the name, here */
+ DEBUG(5,("reg_open_entry: Enter\n"));
+
+ result = open_registry_key( p, &pol, key, name, 0x0 );
- if ( (num_subkeys=fetch_reg_keys_count( tdb_reg, path )) == -1 )
- return NT_STATUS_ACCESS_DENIED;
-
- if (!open_registry_key(p, &pol, path, 0x0))
- return NT_STATUS_TOO_MANY_SECRETS;
+ init_reg_r_open_entry( r_u, &pol, result );
- init_reg_r_open_entry(r_u, &pol, NT_STATUS_OK);
-
- DEBUG(5,("reg_open_entry: Exitn"));
+ DEBUG(5,("reg_open_entry: Exit\n"));
return r_u->status;
}
@@ -586,66 +340,85 @@ NTSTATUS _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTR
NTSTATUS _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
{
- NTSTATUS status = NT_STATUS_OK;
- char *value = NULL;
- uint32 type = 0x1; /* key type: REG_SZ */
- UNISTR2 *uni_key = NULL;
- BUFFER2 *buf = NULL;
- fstring name;
- Registry_Key *key = find_regkey_index_by_hnd( p, &q_u->pol );
+ NTSTATUS status = NT_STATUS_NO_SUCH_FILE;
+ fstring name;
+ REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
+ REGISTRY_VALUE *val = NULL;
+ REGISTRY_VALUE emptyval;
+ REGVAL_CTR regvals;
+ int i;
DEBUG(5,("_reg_info: Enter\n"));
- if ( !key )
+ if ( !regkey )
return NT_STATUS_INVALID_HANDLE;
- DEBUG(7,("_reg_info: policy key name = [%s]\n", key->name));
-
+ DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
+
rpcstr_pull(name, q_u->uni_type.buffer, sizeof(name), q_u->uni_type.uni_str_len*2, 0);
- DEBUG(5,("reg_info: checking subkey: %s\n", name));
+ DEBUG(5,("reg_info: looking up value: [%s]\n", name));
- uni_key = (UNISTR2 *)talloc_zero(p->mem_ctx, sizeof(UNISTR2));
- buf = (BUFFER2 *)talloc_zero(p->mem_ctx, sizeof(BUFFER2));
-
- if (!uni_key || !buf)
- return NT_STATUS_NO_MEMORY;
+ ZERO_STRUCTP( &regvals );
+
+ regval_ctr_init( &regvals );
+ /* couple of hard coded registry values */
+
if ( strequal(name, "RefusePasswordChange") ) {
- type=0xF770;
- status = NT_STATUS_NO_SUCH_FILE;
- init_unistr2(uni_key, "", 0);
- init_buffer2(buf, (uint8*) uni_key->buffer, uni_key->uni_str_len*2);
-
- buf->buf_max_len=4;
+ ZERO_STRUCTP( &emptyval );
+ val = &emptyval;
+
+ goto out;
+ }
+ if ( strequal(name, REGSTR_PRODUCTTYPE) ) {
+ /* This makes the server look like a member server to clients */
+ /* which tells clients that we have our own local user and */
+ /* group databases and helps with ACL support. */
+
+ switch (lp_server_role()) {
+ case ROLE_DOMAIN_PDC:
+ case ROLE_DOMAIN_BDC:
+ regval_ctr_addvalue( &regvals, REGSTR_PRODUCTTYPE, REG_SZ, REG_PT_LANMANNT, strlen(REG_PT_LANMANNT)+1 );
+ break;
+ case ROLE_STANDALONE:
+ regval_ctr_addvalue( &regvals, REGSTR_PRODUCTTYPE, REG_SZ, REG_PT_SERVERNT, strlen(REG_PT_SERVERNT)+1 );
+ break;
+ case ROLE_DOMAIN_MEMBER:
+ regval_ctr_addvalue( &regvals, REGSTR_PRODUCTTYPE, REG_SZ, REG_PT_WINNT, strlen(REG_PT_WINNT)+1 );
+ break;
+ }
+
+ val = dup_registry_value( regval_ctr_specific_value( &regvals, 0 ) );
+
+ status = NT_STATUS_OK;
+
goto out;
}
- switch (lp_server_role()) {
- case ROLE_DOMAIN_PDC:
- case ROLE_DOMAIN_BDC:
- value = "LanmanNT";
- break;
- case ROLE_STANDALONE:
- value = "ServerNT";
- break;
- case ROLE_DOMAIN_MEMBER:
- value = "WinNT";
+ /* else fall back to actually looking up the value */
+
+ for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
+ {
+ DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
+ if ( StrCaseCmp( val->valuename, name ) == 0 ) {
+ DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
+ status = NT_STATUS_OK;
break;
+ }
+
+ free_registry_value( val );
}
- /* This makes the server look like a member server to clients */
- /* which tells clients that we have our own local user and */
- /* group databases and helps with ACL support. */
-
- init_unistr2(uni_key, value, strlen(value)+1);
- init_buffer2(buf, (uint8*)uni_key->buffer, uni_key->uni_str_len*2);
- out:
- init_reg_r_info(q_u->ptr_buf, r_u, buf, type, status);
+out:
+ new_init_reg_r_info(q_u->ptr_buf, r_u, val, status);
+
+ regval_ctr_destroy( &regvals );
+ free_registry_value( val );
- DEBUG(5,("reg_open_entry: Exit\n"));
+ DEBUG(5,("_reg_info: Exit\n"));
return status;
}
@@ -658,7 +431,7 @@ NTSTATUS _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
NTSTATUS _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
{
NTSTATUS status = NT_STATUS_OK;
- Registry_Key *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
+ REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
DEBUG(5,("_reg_query_key: Enter\n"));
@@ -670,6 +443,7 @@ NTSTATUS _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *
if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) )
return NT_STATUS_ACCESS_DENIED;
+
r_u->sec_desc = 0x00000078; /* size for key's sec_desc */
@@ -691,7 +465,7 @@ NTSTATUS _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *
NTSTATUS _reg_unknown_1a(pipes_struct *p, REG_Q_UNKNOWN_1A *q_u, REG_R_UNKNOWN_1A *r_u)
{
NTSTATUS status = NT_STATUS_OK;
- Registry_Key *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
+ REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
DEBUG(5,("_reg_unknown_1a: Enter\n"));
@@ -713,8 +487,8 @@ NTSTATUS _reg_unknown_1a(pipes_struct *p, REG_Q_UNKNOWN_1A *q_u, REG_R_UNKNOWN_1
NTSTATUS _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
{
NTSTATUS status = NT_STATUS_OK;
- Registry_Key *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
- fstring subkey;
+ REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
+ char *subkey = NULL;
DEBUG(5,("_reg_enum_key: Enter\n"));
@@ -724,9 +498,9 @@ NTSTATUS _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u
DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
- if ( !fetch_reg_keys_specific( tdb_reg, regkey->name, subkey, q_u->key_index ) )
+ if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
{
- status = werror_to_ntstatus( WERR_NO_MORE_ITEMS );
+ status = NT_STATUS_NO_MORE_ENTRIES;
goto done;
}
@@ -739,6 +513,46 @@ NTSTATUS _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u
DEBUG(5,("_reg_enum_key: Exit\n"));
done:
+ SAFE_FREE( subkey );
+ return status;
+}
+
+/*****************************************************************************
+ Implementation of REG_ENUM_VALUE
+ ****************************************************************************/
+
+NTSTATUS _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
+ REGISTRY_VALUE *val;
+
+
+ DEBUG(5,("_reg_enum_value: Enter\n"));
+
+ if ( !regkey )
+ return NT_STATUS_INVALID_HANDLE;
+
+ DEBUG(8,("_reg_enum_key: enumerating values for key [%s]\n", regkey->name));
+
+ if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) )
+ {
+ status = NT_STATUS_NO_MORE_ENTRIES;
+ goto done;
+ }
+
+ DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
+
+ /* subkey has the string name now */
+
+ init_reg_r_enum_val( r_u, val );
+
+
+ DEBUG(5,("_reg_enum_value: Exit\n"));
+
+done:
+ free_registry_value( val );
+
return status;
}
@@ -808,4 +622,28 @@ NTSTATUS _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_A
return status;
}
+/*******************************************************************
+ REG_SAVE_KEY (0x14)
+ ********************************************************************/
+
+NTSTATUS _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
+{
+ REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
+
+ DEBUG(5,("_reg_save_key: Enter\n"));
+
+ /*
+ * basically this is a no op function which just gverifies
+ * that the client gave us a valid registry key handle
+ */
+
+ if ( !regkey )
+ return NT_STATUS_INVALID_HANDLE;
+
+ DEBUG(8,("_reg_save_key: berifying backup of key [%s]\n", regkey->name));
+
+
+ return NT_STATUS_OK;
+}
+
diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c
index f002a7d1c9..bc3b8970d6 100644
--- a/source3/rpc_server/srv_samr.c
+++ b/source3/rpc_server/srv_samr.c
@@ -3,9 +3,11 @@
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Paul Ashton 1997.
- * Copyright (C) Marc Jacobsen 1999.
- * Copyright (C) Jean François Micouleau 1998-2001.
+ * Copyright (C) Paul Ashton 1997,
+ * Copyright (C) Marc Jacobsen 1999,
+ * Copyright (C) Jean François Micouleau 1998-2001,
+ * Copyright (C) Anthony Liguori 2002,
+ * Copyright (C) Jim McDonough 2002.
*
* Split into interface and implementation modules by,
*
@@ -652,6 +654,37 @@ static BOOL api_samr_connect(pipes_struct *p)
return True;
}
+/*******************************************************************
+ api_samr_connect4
+ ********************************************************************/
+
+static BOOL api_samr_connect4(pipes_struct *p)
+{
+ SAMR_Q_CONNECT4 q_u;
+ SAMR_R_CONNECT4 r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ /* grab the samr open policy */
+ if(!samr_io_q_connect4("", &q_u, data, 0)) {
+ DEBUG(0,("api_samr_connect4: unable to unmarshall SAMR_Q_CONNECT4.\n"));
+ return False;
+ }
+
+ r_u.status = _samr_connect4(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!samr_io_r_connect4("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_samr_connect4: unable to marshall SAMR_R_CONNECT4.\n"));
+ return False;
+ }
+
+ return True;
+}
+
/**********************************************************************
api_samr_lookup_domain
**********************************************************************/
@@ -1465,6 +1498,7 @@ static struct api_struct api_samr_cmds [] =
{"SAMR_GET_USRDOM_PWINFO" , SAMR_GET_USRDOM_PWINFO, api_samr_get_usrdom_pwinfo},
{"SAMR_UNKNOWN_2E" , SAMR_UNKNOWN_2E , api_samr_unknown_2e },
{"SAMR_SET_DOMAIN_INFO" , SAMR_SET_DOMAIN_INFO , api_samr_set_dom_info },
+ {"SAMR_CONNECT4" , SAMR_CONNECT4 , api_samr_connect4 },
{NULL , 0 , NULL }
};
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index 88d728d810..a30622c600 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -3,10 +3,12 @@
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Paul Ashton 1997.
- * Copyright (C) Marc Jacobsen 1999.
- * Copyright (C) Jeremy Allison 2001-2002.
- * Copyright (C) Jean François Micouleau 1998-2001.
+ * Copyright (C) Paul Ashton 1997,
+ * Copyright (C) Marc Jacobsen 1999,
+ * Copyright (C) Jeremy Allison 2001-2002,
+ * Copyright (C) Jean François Micouleau 1998-2001,
+ * Copyright (C) Anthony Liguori 2002,
+ * Copyright (C) Jim McDonough 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
@@ -727,8 +729,6 @@ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UN
}
for (i = 0; i < num_entries; i++) {
- int len = uni_temp_name.uni_str_len;
-
pwd = disp_user_info[i+start_idx].sam;
temp_name = pdb_get_username(pwd);
init_unistr2(&uni_temp_name, temp_name, strlen(temp_name)+1);
@@ -743,7 +743,7 @@ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UN
return NT_STATUS_UNSUCCESSFUL;
}
- init_sam_entry(&sam[i], len, user_rid);
+ init_sam_entry(&sam[i], uni_temp_name.uni_str_len, user_rid);
copy_unistr2(&uni_name[i], &uni_temp_name);
}
@@ -1081,7 +1081,9 @@ NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAM
DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
/* the domain group array is being allocated in the function below */
- get_group_domain_entries(p->mem_ctx, &grp, &sid, q_u->start_idx, &num_entries, MAX_SAM_ENTRIES);
+ if (!NT_STATUS_IS_OK(r_u->status = get_group_domain_entries(p->mem_ctx, &grp, &sid, q_u->start_idx, &num_entries, MAX_SAM_ENTRIES))) {
+ return r_u->status;
+ }
make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, num_entries, grp);
@@ -2081,6 +2083,8 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
time_t u_logout;
NTTIME nt_logout;
+ uint32 account_policy_temp;
+
uint32 num_users=0, num_groups=0, num_aliases=0;
if ((ctr = (SAM_UNK_CTR *)talloc_zero(p->mem_ctx, sizeof(SAM_UNK_CTR))) == NULL)
@@ -2098,12 +2102,22 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
switch (q_u->switch_value) {
case 0x01:
- account_policy_get(AP_MIN_PASSWORD_LEN, &min_pass_len);
- account_policy_get(AP_PASSWORD_HISTORY, &pass_hist);
- account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &flag);
- account_policy_get(AP_MAX_PASSWORD_AGE, (int *)&u_expire);
- account_policy_get(AP_MIN_PASSWORD_AGE, (int *)&u_min_age);
+
+ account_policy_get(AP_MIN_PASSWORD_LEN, &account_policy_temp);
+ min_pass_len = account_policy_temp;
+ account_policy_get(AP_PASSWORD_HISTORY, &account_policy_temp);
+ pass_hist = account_policy_temp;
+
+ account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
+ flag = account_policy_temp;
+
+ account_policy_get(AP_MAX_PASSWORD_AGE, &account_policy_temp);
+ u_expire = account_policy_temp;
+
+ account_policy_get(AP_MIN_PASSWORD_AGE, &account_policy_temp);
+ u_min_age = account_policy_temp;
+
unix_to_nt_time_abs(&nt_expire, u_expire);
unix_to_nt_time_abs(&nt_min_age, u_min_age);
@@ -2149,10 +2163,15 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
init_unk_info7(&ctr->info.inf7);
break;
case 0x0c:
- account_policy_get(AP_LOCK_ACCOUNT_DURATION, (int *)&u_lock_duration);
- account_policy_get(AP_RESET_COUNT_TIME, (int *)&u_reset_time);
- account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &lockout);
-
+ account_policy_get(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp);
+ u_lock_duration = account_policy_temp;
+
+ account_policy_get(AP_RESET_COUNT_TIME, &account_policy_temp);
+ u_reset_time = account_policy_temp;
+
+ account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp);
+ lockout = account_policy_temp;
+
unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration);
unix_to_nt_time_abs(&nt_reset_time, u_reset_time);
@@ -2344,7 +2363,8 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
}
r_u->user_rid=pdb_get_user_rid(sam_pass);
- r_u->unknown_0 = 0x000703ff;
+
+ r_u->access_granted = acc_granted;
pdb_free_sam(&sam_pass);
@@ -2434,6 +2454,56 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u
return r_u->status;
}
+/*******************************************************************
+ samr_connect4
+ ********************************************************************/
+
+NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 *r_u)
+{
+ struct samr_info *info = NULL;
+ SEC_DESC *psd = NULL;
+ uint32 acc_granted;
+ uint32 des_access = q_u->access_mask;
+ size_t sd_size;
+ NTSTATUS nt_status;
+
+
+ DEBUG(5,("_samr_connect4: %d\n", __LINE__));
+
+ /* Access check */
+
+ if (!pipe_access_check(p)) {
+ DEBUG(3, ("access denied to samr_connect4\n"));
+ r_u->status = NT_STATUS_ACCESS_DENIED;
+ return r_u->status;
+ }
+
+ samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size);
+ se_map_generic(&des_access, &sam_generic_mapping);
+ if (!NT_STATUS_IS_OK(nt_status =
+ access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ des_access, &acc_granted, "_samr_connect"))) {
+ return nt_status;
+ }
+
+ r_u->status = NT_STATUS_OK;
+
+ /* associate the user's SID and access granted with the new handle. */
+ if ((info = get_samr_info_by_sid(NULL)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ info->acc_granted = acc_granted;
+ info->status = q_u->access_mask;
+
+ /* get a (unique) handle. open a policy on it. */
+ if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ DEBUG(5,("_samr_connect: %d\n", __LINE__));
+
+ return r_u->status;
+}
+
/**********************************************************************
api_samr_lookup_domain
**********************************************************************/
@@ -4180,6 +4250,8 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
uint32 num_users=0, num_groups=0, num_aliases=0;
+ uint32 account_policy_temp;
+
if ((ctr = (SAM_UNK_CTR *)talloc_zero(p->mem_ctx, sizeof(SAM_UNK_CTR))) == NULL)
return NT_STATUS_NO_MEMORY;
@@ -4195,11 +4267,20 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
switch (q_u->switch_value) {
case 0x01:
- account_policy_get(AP_MIN_PASSWORD_LEN, &min_pass_len);
- account_policy_get(AP_PASSWORD_HISTORY, &pass_hist);
- account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &flag);
- account_policy_get(AP_MAX_PASSWORD_AGE, (int *)&u_expire);
- account_policy_get(AP_MIN_PASSWORD_AGE, (int *)&u_min_age);
+ account_policy_get(AP_MIN_PASSWORD_LEN, &account_policy_temp);
+ min_pass_len = account_policy_temp;
+
+ account_policy_get(AP_PASSWORD_HISTORY, &account_policy_temp);
+ pass_hist = account_policy_temp;
+
+ account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
+ flag = account_policy_temp;
+
+ account_policy_get(AP_MAX_PASSWORD_AGE, &account_policy_temp);
+ u_expire = account_policy_temp;
+
+ account_policy_get(AP_MIN_PASSWORD_AGE, &account_policy_temp);
+ u_min_age = account_policy_temp;
unix_to_nt_time_abs(&nt_expire, u_expire);
unix_to_nt_time_abs(&nt_min_age, u_min_age);
@@ -4231,7 +4312,9 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
num_users, num_groups, num_aliases);
break;
case 0x03:
- account_policy_get(AP_TIME_TO_LOGOUT, (int *)&u_logout);
+ account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp);
+ u_logout = account_policy_temp;
+
unix_to_nt_time_abs(&nt_logout, u_logout);
init_unk_info3(&ctr->info.inf3, nt_logout);
@@ -4246,9 +4329,14 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
init_unk_info7(&ctr->info.inf7);
break;
case 0x0c:
- account_policy_get(AP_LOCK_ACCOUNT_DURATION, (int *)&u_lock_duration);
- account_policy_get(AP_RESET_COUNT_TIME, (int *)&u_reset_time);
- account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &lockout);
+ account_policy_get(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp);
+ u_lock_duration = account_policy_temp;
+
+ account_policy_get(AP_RESET_COUNT_TIME, &account_policy_temp);
+ u_reset_time = account_policy_temp;
+
+ account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp);
+ lockout = account_policy_temp;
unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration);
unix_to_nt_time_abs(&nt_reset_time, u_reset_time);
diff --git a/source3/rpc_server/srv_spoolss.c b/source3/rpc_server/srv_spoolss.c
index 6e3463e79b..5924c5831b 100755
--- a/source3/rpc_server/srv_spoolss.c
+++ b/source3/rpc_server/srv_spoolss.c
@@ -1515,6 +1515,65 @@ static BOOL api_spoolss_deleteprinterdriverex(pipes_struct *p)
return True;
}
+#if 0
+
+/****************************************************************************
+****************************************************************************/
+
+static BOOL api_spoolss_replyopenprinter(pipes_struct *p)
+{
+ SPOOL_Q_REPLYOPENPRINTER q_u;
+ SPOOL_R_REPLYOPENPRINTER r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!spoolss_io_q_replyopenprinter("", &q_u, data, 0)) {
+ DEBUG(0,("spoolss_io_q_replyopenprinter: unable to unmarshall SPOOL_Q_REPLYOPENPRINTER.\n"));
+ return False;
+ }
+
+ r_u.status = _spoolss_replyopenprinter(p, &q_u, &r_u);
+
+ if(!spoolss_io_r_replyopenprinter("", &r_u, rdata, 0)) {
+ DEBUG(0,("spoolss_io_r_replyopenprinter: unable to marshall SPOOL_R_REPLYOPENPRINTER.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static BOOL api_spoolss_replycloseprinter(pipes_struct *p)
+{
+ SPOOL_Q_REPLYCLOSEPRINTER q_u;
+ SPOOL_R_REPLYCLOSEPRINTER r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!spoolss_io_q_replycloseprinter("", &q_u, data, 0)) {
+ DEBUG(0,("spoolss_io_q_replycloseprinter: unable to unmarshall SPOOL_Q_REPLYCLOSEPRINTER.\n"));
+ return False;
+ }
+
+ r_u.status = _spoolss_replycloseprinter(p, &q_u, &r_u);
+
+ if(!spoolss_io_r_replycloseprinter("", &r_u, rdata, 0)) {
+ DEBUG(0,("spoolss_io_r_replycloseprinter: unable to marshall SPOOL_R_REPLYCLOSEPRINTER.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+#endif
/*******************************************************************
\pipe\spoolss commands
@@ -1573,6 +1632,10 @@ struct api_struct api_spoolss_cmds[] =
{"SPOOLSS_GETPRINTPROCESSORDIRECTORY",SPOOLSS_GETPRINTPROCESSORDIRECTORY,api_spoolss_getprintprocessordirectory},
{"SPOOLSS_ADDPRINTERDRIVEREX", SPOOLSS_ADDPRINTERDRIVEREX, api_spoolss_addprinterdriverex },
{"SPOOLSS_DELETEPRINTERDRIVEREX", SPOOLSS_DELETEPRINTERDRIVEREX, api_spoolss_deleteprinterdriverex },
+#if 0
+ {"SPOOLSS_REPLYOPENPRINTER", SPOOLSS_REPLYOPENPRINTER, api_spoolss_replyopenprinter },
+ {"SPOOLSS_REPLYCLOSEPRINTER", SPOOLSS_REPLYCLOSEPRINTER, api_spoolss_replycloseprinter },
+#endif
{ NULL, 0, NULL }
};
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index 68c792f8b0..7aceaa548f 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -65,7 +65,7 @@ typedef struct _Printer{
struct _Printer *prev, *next;
BOOL document_started;
BOOL page_started;
- int jobid; /* jobid in printing backend */
+ uint32 jobid; /* jobid in printing backend */
BOOL printer_type;
union {
fstring handlename;
@@ -101,7 +101,7 @@ typedef struct _counter_printer_0 {
static ubi_dlList counter_list;
-static struct cli_state cli;
+static struct cli_state notify_cli; /* print notify back-channel */
static uint32 smb_connections=0;
@@ -184,7 +184,7 @@ static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
return;
}
- result = cli_spoolss_reply_close_printer(&cli, cli.mem_ctx, handle);
+ result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
if (!W_ERROR_IS_OK(result))
DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
@@ -192,9 +192,9 @@ static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
/* if it's the last connection, deconnect the IPC$ share */
if (smb_connections==1) {
- cli_nt_session_close(&cli);
- cli_ulogoff(&cli);
- cli_shutdown(&cli);
+ cli_nt_session_close(&notify_cli);
+ cli_ulogoff(&notify_cli);
+ cli_shutdown(&notify_cli);
message_deregister(MSG_PRINTER_NOTIFY2);
}
@@ -668,21 +668,21 @@ struct notify2_message_table {
};
static struct notify2_message_table printer_notify_table[] = {
- /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", NULL },
- /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", NULL },
- /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", NULL },
- /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", NULL },
- /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", NULL },
- /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", NULL },
- /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", NULL },
+ /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
+ /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
+ /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
+ /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
+ /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
+ /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
+ /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
/* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
- /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", NULL },
- /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", NULL },
+ /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
+ /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
/* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
- /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", NULL },
+ /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
/* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
- /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", NULL },
- /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", NULL },
+ /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
+ /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
/* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
/* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
/* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
@@ -726,6 +726,8 @@ static void process_notify2_message(struct spoolss_notify_msg *msg,
{
Printer_entry *p;
+ DEBUG(8,("process_notify2_message: Enter...[%s]\n", msg->printer));
+
for (p = printers_list; p; p = p->next) {
SPOOL_NOTIFY_INFO_DATA *data;
uint32 data_len = 1;
@@ -736,28 +738,52 @@ static void process_notify2_message(struct spoolss_notify_msg *msg,
if (!p->notify.client_connected)
continue;
+ DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
+
/* For this printer? Print servers always receive
notifications. */
- if (p->printer_type == PRINTER_HANDLE_IS_PRINTER &&
- !strequal(msg->printer, p->dev.handlename))
+ if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
+ ( !strequal(msg->printer, p->dev.handlename) ) )
continue;
+ DEBUG(10,("Our printer\n"));
+
/* Are we monitoring this event? */
if (!is_monitoring_event(p, msg->type, msg->field))
continue;
+ DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
+ msg->type, msg->field, p->dev.handlename));
+
/* OK - send the event to the client */
data = talloc(mem_ctx, sizeof(SPOOL_NOTIFY_INFO_DATA));
ZERO_STRUCTP(data);
- /* Convert unix jobid to smb jobid */
+ /*
+ * if the is a printer notification handle and not a job notification
+ * type, then set the id to 0. Other wise just use what was specified
+ * in the message.
+ *
+ * When registering change notification on a print server handle
+ * we always need to send back the id (snum) matching the printer
+ * for which the change took place. For change notify registered
+ * on a printer handle, this does not matter and the id should be 0.
+ *
+ * --jerry
+ */
+ if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
+ id = 0;
+ else
id = msg->id;
+
+ /* Convert unix jobid to smb jobid */
+
if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
id = sysjob_to_jobid(msg->id);
@@ -772,51 +798,31 @@ static void process_notify2_message(struct spoolss_notify_msg *msg,
switch(msg->type) {
case PRINTER_NOTIFY_TYPE:
- if (printer_notify_table[msg->field].fn)
- printer_notify_table[msg->field].fn(
- msg, data, mem_ctx);
- else
+ if ( !printer_notify_table[msg->field].fn )
goto done;
+
+ printer_notify_table[msg->field].fn(msg, data, mem_ctx);
+
break;
+
case JOB_NOTIFY_TYPE:
- if (job_notify_table[msg->field].fn)
- job_notify_table[msg->field].fn(
- msg, data, mem_ctx);
- else
+ if ( !job_notify_table[msg->field].fn )
goto done;
- break;
- default:
- DEBUG(5, ("Unknown notification type %d\n",
- msg->type));
- goto done;
- }
- if (!p->notify.flags)
- cli_spoolss_rrpcn(
- &cli, mem_ctx, &p->notify.client_hnd,
- data_len, data, p->notify.change, 0);
- else {
- NT_PRINTER_INFO_LEVEL *printer = NULL;
+ job_notify_table[msg->field].fn(msg, data, mem_ctx);
- get_a_printer(&printer, 2, msg->printer);
+ break;
- if (!printer) {
- DEBUG(5, ("unable to load info2 for %s\n",
- msg->printer));
+ default:
+ DEBUG(5, ("Unknown notification type %d\n", msg->type));
goto done;
}
- /* XXX: This needs to be updated for
- PRINTER_CHANGE_SET_PRINTER_DRIVER. */
-
- cli_spoolss_routerreplyprinter(
- &cli, mem_ctx, &p->notify.client_hnd,
- 0, printer->info_2->changeid);
-
- free_a_printer(&printer, 2);
- }
+ cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
+ data_len, data, p->notify.change, 0 );
}
done:
+ DEBUG(8,("process_notify2_message: Exit...\n"));
return;
}
@@ -867,30 +873,6 @@ static void receive_notify2_message(int msg_type, pid_t src, void *buf,
talloc_destroy(mem_ctx);
}
-/***************************************************************************
- Server wrapper for cli_spoolss_routerreplyprinter() since the client
- function can only send a single change notification at a time.
-
- FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
- --jerry
- **************************************************************************/
-
-static WERROR srv_spoolss_routerreplyprinter (struct cli_state *reply_cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *pol, PRINTER_MESSAGE_INFO *info,
- NT_PRINTER_INFO_LEVEL *printer)
-{
- WERROR result;
- uint32 condition = 0x0;
-
- if (info->flags & PRINTER_MESSAGE_DRIVER)
- condition = PRINTER_CHANGE_SET_PRINTER_DRIVER;
-
- result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition,
- printer->info_2->changeid);
-
- return result;
-}
-
/********************************************************************
Send a message to ourself about new driver being installed
so we can upgrade the information for each printer bound to this
@@ -962,6 +944,80 @@ void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
}
/********************************************************************
+ Send a message to ourself about new driver being installed
+ so we can upgrade the information for each printer bound to this
+ driver
+ ********************************************************************/
+
+static BOOL srv_spoolss_reset_printerdata(char* drivername)
+{
+ int len = strlen(drivername);
+
+ if (!len)
+ return False;
+
+ DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
+ drivername));
+
+ message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
+
+ return True;
+}
+
+/**********************************************************************
+ callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
+ over all printers, resetting printer data as neessary
+ **********************************************************************/
+
+void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
+{
+ fstring drivername;
+ int snum;
+ int n_services = lp_numservices();
+
+ len = MIN( len, sizeof(drivername)-1 );
+ strncpy( drivername, buf, len );
+
+ DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
+
+ /* Iterate the printer list */
+
+ for ( snum=0; snum<n_services; snum++ )
+ {
+ if ( lp_snum_ok(snum) && lp_print_ok(snum) )
+ {
+ WERROR result;
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+
+ result = get_a_printer( &printer, 2, lp_servicename(snum) );
+ if ( !W_ERROR_IS_OK(result) )
+ continue;
+
+ /*
+ * if the printer is bound to the driver,
+ * then reset to the new driver initdata
+ */
+
+ if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
+ {
+ DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
+
+ if ( !set_driver_init(printer, 2) ) {
+ DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
+ printer->info_2->printername, printer->info_2->drivername));
+ }
+ }
+
+ free_a_printer( &printer, 2 );
+ }
+ }
+
+ /* all done */
+
+ return;
+}
+
+/********************************************************************
Copy routines used by convert_to_openprinterex()
*******************************************************************/
@@ -1094,8 +1150,6 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
{
UNISTR2 *printername = NULL;
PRINTER_DEFAULT *printer_default = &q_u->printer_default;
-/* uint32 user_switch = q_u->user_switch; - notused */
-/* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
POLICY_HND *handle = &r_u->handle;
fstring name;
@@ -1443,14 +1497,18 @@ BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
{
Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
-
+ int snum;
+
if (!Printer) {
DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
return WERR_BADFID;
}
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+
Printer->document_started=False;
- print_job_end(Printer->jobid,True);
+ print_job_end(snum, Printer->jobid,True);
/* error codes unhandled so far ... */
return WERR_OK;
@@ -1740,51 +1798,56 @@ static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND
uint8 **data, uint32 *needed, uint32 in_size )
{
NT_PRINTER_INFO_LEVEL *printer = NULL;
- int snum=0;
- uint8 *idata=NULL;
- uint32 len;
- Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+ int snum=0;
+ Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+ REGISTRY_VALUE *val;
+ int size = 0;
DEBUG(5,("getprinterdata_printer\n"));
- if (!Printer) {
+ if ( !Printer ) {
DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
return False;
}
- if(!get_printer_snum(p, handle, &snum))
+ if ( !get_printer_snum(p, handle, &snum) )
return False;
- if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
+ if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
return False;
- if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
+ if ( !(val = get_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, value)) )
+ {
free_a_printer(&printer, 2);
return False;
}
+
+ *type = regval_type( val );
- free_a_printer(&printer, 2);
DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
- if (in_size) {
- if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
+ if (in_size)
+ {
+ if ( (*data = (uint8 *)talloc(ctx, in_size * sizeof(uint8))) == NULL )
return False;
- }
- memset(*data, 0, in_size *sizeof(uint8));
+ memset( *data, 0, in_size *sizeof(uint8) );
+
/* copy the min(in_size, len) */
- memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
- } else {
- *data = NULL;
+
+ size = regval_size( val );
+ memcpy( *data, regval_data_p(val), (size > in_size) ? in_size : size*sizeof(uint8) );
}
+ else
+ *data = NULL;
- *needed = len;
+ *needed = size;
DEBUG(5,("getprinterdata_printer:copy done\n"));
- SAFE_FREE(idata);
+ free_a_printer(&printer, 2);
return True;
}
@@ -1813,11 +1876,12 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO
* JFM, 4/19/1999
*/
- *out_size=in_size;
+ *out_size = in_size;
/* in case of problem, return some default values */
- *needed=0;
- *type=0;
+
+ *needed = 0;
+ *type = 0;
DEBUG(4,("_spoolss_getprinterdata\n"));
@@ -1831,13 +1895,16 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO
unistr2_to_ascii(value, valuename, sizeof(value)-1);
if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
- found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
+ found = getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
else
- found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
+ found = getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
- if (found==False) {
+ if ( !found )
+ {
DEBUG(5, ("value not found, allocating %d\n", *out_size));
+
/* reply this param doesn't exist */
+
if (*out_size) {
if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
return WERR_NOMEM;
@@ -1966,7 +2033,7 @@ static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uin
fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
- if(!spoolss_connect_to_client(&cli, unix_printer))
+ if(!spoolss_connect_to_client(&notify_cli, unix_printer))
return False;
message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message);
@@ -1974,7 +2041,7 @@ static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uin
smb_connections++;
- result = cli_spoolss_reply_open_printer(&cli, cli.mem_ctx, printer, localprinter,
+ result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
type, handle);
if (!W_ERROR_IS_OK(result))
@@ -2749,7 +2816,7 @@ struct s_notify_info_data_table notify_info_data_table[] =
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, spoolss_notify_security_desc },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
@@ -2796,10 +2863,13 @@ static uint32 size_of_notify_info_data(uint16 type, uint16 field)
{
int i=0;
- for (i = 0; i < sizeof(notify_info_data_table); i++) {
- if (notify_info_data_table[i].type == type &&
- notify_info_data_table[i].field == field) {
- switch(notify_info_data_table[i].size) {
+ for (i = 0; i < sizeof(notify_info_data_table); i++)
+ {
+ if ( (notify_info_data_table[i].type == type)
+ && (notify_info_data_table[i].field == field) )
+ {
+ switch(notify_info_data_table[i].size)
+ {
case NOTIFY_ONE_VALUE:
case NOTIFY_TWO_VALUE:
return 1;
@@ -2812,6 +2882,9 @@ static uint32 size_of_notify_info_data(uint16 type, uint16 field)
case NOTIFY_POINTER:
return 4;
+
+ case NOTIFY_SECDESC:
+ return 5;
}
}
}
@@ -2866,13 +2939,11 @@ void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16
info_data->field = field;
info_data->reserved = 0;
- if (type == JOB_NOTIFY_TYPE)
- info_data->id = id;
- else
- info_data->id = 0;
-
info_data->size = size_of_notify_info_data(type, field);
info_data->enc_type = type_of_notify_info_data(type, field);
+
+ info_data->id = id;
+
}
@@ -2904,20 +2975,24 @@ static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
return False;
- for(field_num=0; field_num<option_type->count; field_num++) {
+ for(field_num=0; field_num<option_type->count; field_num++)
+ {
field = option_type->fields[field_num];
+
DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
if (!search_notify(type, field, &j) )
continue;
- if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
+ if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
+ {
DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
return False;
}
- else info->data = tid;
+ else
+ info->data = tid;
- current_data=&info->data[info->count];
+ current_data = &info->data[info->count];
construct_info_data(current_data, type, field, id);
@@ -3044,16 +3119,17 @@ static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
continue;
for (snum=0; snum<n_services; snum++)
+ {
if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
- if (construct_notify_printer_info
- (info, snum, option_type, id, mem_ctx))
- id++;
+ construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
+ }
}
+#if 0
/*
* Debugging information, don't delete.
*/
- /*
+
DEBUG(1,("dumping the NOTIFY_INFO\n"));
DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
@@ -3063,7 +3139,7 @@ static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
i, info->data[i].type, info->data[i].field, info->data[i].reserved,
info->data[i].id, info->data[i].size, info->data[i].enc_type));
}
- */
+#endif
return WERR_OK;
}
@@ -3161,7 +3237,6 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY
WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
SPOOL_NOTIFY_INFO *info = &r_u->info;
Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
@@ -3188,8 +3263,10 @@ WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCN
/* We need to keep track of the change value to send back in
RRPCN replies otherwise our updates are ignored. */
- if (Printer->notify.client_connected)
+ if (Printer->notify.client_connected) {
+ DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
Printer->notify.change = q_u->change;
+ }
/* just ignore the SPOOL_NOTIFY_OPTION */
@@ -3370,7 +3447,7 @@ static void free_dev_mode(DEVICEMODE *dev)
Create a DEVMODE struct. Returns malloced memory.
****************************************************************************/
-static DEVICEMODE *construct_dev_mode(int snum)
+DEVICEMODE *construct_dev_mode(int snum)
{
char adevice[32];
char aform[32];
@@ -4318,22 +4395,29 @@ static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *ser
DEBUG(6,("init_unistr_array\n"));
*uni_array=NULL;
- while (1) {
+ while (True)
+ {
if (char_array == NULL)
v = "";
else {
v = char_array[i];
if (!v) v = ""; /* hack to handle null lists */
}
- if (strlen(v) == 0) break;
+
+ if ( !strlen(v) )
+ break;
+
slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
+
DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
+
if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
DEBUG(2,("init_unistr_array: Realloc error\n" ));
return;
} else
*uni_array = tuary;
- j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
+
+ j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
i++;
}
@@ -4495,8 +4579,8 @@ static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_IN
init_unistr( &info->monitorname, driver.info_3->monitorname );
init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
- info->dependentfiles=NULL;
- init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
+ info->dependentfiles = NULL;
+ init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
info->previousdrivernames=NULL;
init_unistr_array(&info->previousdrivernames, &nullstr, servername);
@@ -4519,21 +4603,28 @@ static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_IN
* fill a printer_info_6 struct
********************************************************************/
-static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
+static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
+ fstring servername, fstring architecture, uint32 version)
{
- NT_PRINTER_INFO_LEVEL *printer = NULL;
- NT_PRINTER_DRIVER_INFO_LEVEL driver;
- WERROR status;
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ NT_PRINTER_DRIVER_INFO_LEVEL driver;
+ WERROR status;
+
ZERO_STRUCT(driver);
status=get_a_printer(&printer, 2, lp_servicename(snum) );
+
DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
+
if (!W_ERROR_IS_OK(status))
return WERR_INVALID_PRINTER_NAME;
- status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
+ status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
+
DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
- if (!W_ERROR_IS_OK(status)) {
+
+ if (!W_ERROR_IS_OK(status))
+ {
/*
* Is this a W2k client ?
*/
@@ -4728,7 +4819,6 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_
UNISTR2 *uni_arch = &q_u->architecture;
uint32 level = q_u->level;
uint32 clientmajorversion = q_u->clientmajorversion;
-/* uint32 clientminorversion = q_u->clientminorversion; - notused. */
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
uint32 *needed = &r_u->needed;
@@ -4745,9 +4835,9 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_
DEBUG(4,("_spoolss_getprinterdriver2\n"));
- *needed=0;
- *servermajorversion=0;
- *serverminorversion=0;
+ *needed = 0;
+ *servermajorversion = 0;
+ *serverminorversion = 0;
pstrcpy(servername, get_called_name());
unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
@@ -4793,6 +4883,7 @@ WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u,
WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
{
POLICY_HND *handle = &q_u->handle;
+ int snum;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
@@ -4801,8 +4892,11 @@ WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPO
return WERR_BADFID;
}
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+
Printer->page_started=False;
- print_job_endpage(Printer->jobid);
+ print_job_endpage(snum, Printer->jobid);
return WERR_OK;
}
@@ -4816,7 +4910,6 @@ WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPO
WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* uint32 level = q_u->doc_info_container.level; - notused. */
DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
uint32 *jobid = &r_u->jobid;
@@ -4898,7 +4991,7 @@ WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R
uint32 buffer_size = q_u->buffer_size;
uint8 *buffer = q_u->buffer;
uint32 *buffer_written = &q_u->buffer_size2;
-
+ int snum;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
if (!Printer) {
@@ -4907,8 +5000,10 @@ WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R
return WERR_BADFID;
}
- (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+ (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
r_u->buffer_written = q_u->buffer_size2;
@@ -5147,254 +5242,6 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
return True;
}
-#if 0 /* JERRY */
-
-/* Return true if two devicemodes are equal */
-
-#define DEVMODE_CHECK_INT(field) \
- if (d1->field != d2->field) { \
- DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
- d1->field, d2->field)); \
- return False; \
- }
-
-/************************************************************************
- Handy, but currently unused functions
- ***********************************************************************/
-
-static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
-{
- if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
-
- if (!d1 ^ !d2) {
- DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
- return False; /* if either is exclusively NULL are not equal */
- }
-
- if (!strequal(d1->devicename, d2->devicename)) {
- DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
- return False;
- }
-
- if (!strequal(d1->formname, d2->formname)) {
- DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
- return False;
- }
-
- DEVMODE_CHECK_INT(specversion);
- DEVMODE_CHECK_INT(driverversion);
- DEVMODE_CHECK_INT(driverextra);
- DEVMODE_CHECK_INT(orientation);
- DEVMODE_CHECK_INT(papersize);
- DEVMODE_CHECK_INT(paperlength);
- DEVMODE_CHECK_INT(paperwidth);
- DEVMODE_CHECK_INT(scale);
- DEVMODE_CHECK_INT(copies);
- DEVMODE_CHECK_INT(defaultsource);
- DEVMODE_CHECK_INT(printquality);
- DEVMODE_CHECK_INT(color);
- DEVMODE_CHECK_INT(duplex);
- DEVMODE_CHECK_INT(yresolution);
- DEVMODE_CHECK_INT(ttoption);
- DEVMODE_CHECK_INT(collate);
- DEVMODE_CHECK_INT(logpixels);
-
- DEVMODE_CHECK_INT(fields);
- DEVMODE_CHECK_INT(bitsperpel);
- DEVMODE_CHECK_INT(pelswidth);
- DEVMODE_CHECK_INT(pelsheight);
- DEVMODE_CHECK_INT(displayflags);
- DEVMODE_CHECK_INT(displayfrequency);
- DEVMODE_CHECK_INT(icmmethod);
- DEVMODE_CHECK_INT(icmintent);
- DEVMODE_CHECK_INT(mediatype);
- DEVMODE_CHECK_INT(dithertype);
- DEVMODE_CHECK_INT(reserved1);
- DEVMODE_CHECK_INT(reserved2);
- DEVMODE_CHECK_INT(panningwidth);
- DEVMODE_CHECK_INT(panningheight);
-
- /* compare the private data if it exists */
- if (!d1->driverextra && !d2->driverextra) goto equal;
-
-
- DEVMODE_CHECK_INT(driverextra);
-
- if (memcmp(d1->private, d2->private, d1->driverextra)) {
- DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
- return False;
- }
-
- equal:
- DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
- return True;
-}
-
-/* Return true if two NT_PRINTER_PARAM structures are equal */
-
-static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
- NT_PRINTER_PARAM *p2)
-{
- if (!p1 && !p2) goto equal;
-
- if ((!p1 && p2) || (p1 && !p2)) {
- DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
- return False;
- }
-
- /* Compare lists of printer parameters */
-
- while (p1) {
- BOOL found = False;
- NT_PRINTER_PARAM *q = p1;
-
- /* Find the parameter in the second structure */
-
- while(q) {
-
- if (strequal(p1->value, q->value)) {
-
- if (p1->type != q->type) {
- DEBUG(10, ("nt_printer_param_equal():"
- "types for %s differ (%d != %d)\n",
- p1->value, p1->type,
- q->type));
- break;
- }
-
- if (p1->data_len != q->data_len) {
- DEBUG(10, ("nt_printer_param_equal():"
- "len for %s differs (%d != %d)\n",
- p1->value, p1->data_len,
- q->data_len));
- break;
- }
-
- if (memcmp(p1->data, q->data, p1->data_len) == 0) {
- found = True;
- } else {
- DEBUG(10, ("nt_printer_param_equal():"
- "data for %s differs\n", p1->value));
- }
-
- break;
- }
-
- q = q->next;
- }
-
- if (!found) {
- DEBUG(10, ("nt_printer_param_equal(): param %s "
- "does not exist\n", p1->value));
- return False;
- }
-
- p1 = p1->next;
- }
-
- equal:
-
- DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
- return True;
-}
-
-/********************************************************************
- * Called by update_printer when trying to work out whether to
- * actually update printer info.
- ********************************************************************/
-
-#define PI_CHECK_INT(field) \
- if (pi1->field != pi2->field) { \
- DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
- pi1->field, pi2->field)); \
- return False; \
- }
-
-#define PI_CHECK_STR(field) \
- if (!strequal(pi1->field, pi2->field)) { \
- DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
- pi1->field, pi2->field)); \
- return False; \
- }
-
-static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
- NT_PRINTER_INFO_LEVEL *p2)
-{
- NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
-
- /* Trivial conditions */
-
- if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
- goto equal;
- }
-
- if ((!p1 && p2) || (p1 && !p2) ||
- (!p1->info_2 && p2->info_2) ||
- (p1->info_2 && !p2->info_2)) {
- DEBUG(10, ("nt_printer_info_level_equal(): info levels "
- "differ\n"));
- return False;
- }
-
- /* Compare two nt_printer_info_level structures. Don't compare
- status or cjobs as they seem to have something to do with the
- printer queue. */
-
- pi1 = p1->info_2;
- pi2 = p2->info_2;
-
- /* Don't check the attributes as we stomp on the value in
- check_printer_ok() anyway. */
-
-#if 0
- PI_CHECK_INT(attributes);
-#endif
-
- PI_CHECK_INT(priority);
- PI_CHECK_INT(default_priority);
- PI_CHECK_INT(starttime);
- PI_CHECK_INT(untiltime);
- PI_CHECK_INT(averageppm);
-
- /* Yuck - don't check the printername or servername as the
- mod_a_printer() code plays games with them. You can't
- change the printername or the sharename through this interface
- in Samba. */
-
- PI_CHECK_STR(sharename);
- PI_CHECK_STR(portname);
- PI_CHECK_STR(drivername);
- PI_CHECK_STR(comment);
- PI_CHECK_STR(location);
-
- if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
- return False;
- }
-
- PI_CHECK_STR(sepfile);
- PI_CHECK_STR(printprocessor);
- PI_CHECK_STR(datatype);
- PI_CHECK_STR(parameters);
-
- if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
- return False;
- }
-
- if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
- return False;
- }
-
- PI_CHECK_INT(changeid);
- PI_CHECK_INT(c_setprinter);
- PI_CHECK_INT(setuptime);
-
- equal:
- DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
- return True;
-}
-
-#endif
-
/********************************************************************
* Called by spoolss_api_setprinter
* when updating a printer description.
@@ -5507,7 +5354,8 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
* requires Win32 client code (see other notes elsewhere in the code).
*/
if (printer->info_2->devmode &&
- printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
+ printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY)
+ {
DEBUG(10,("update_printer: Save printer driver init data\n"));
printer->info_2->devmode->displayfrequency = 0;
@@ -5517,17 +5365,31 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
result = WERR_ACCESS_DENIED;
goto done;
}
- } else {
+
+ /* we need to reset all driver init data for all printers
+ bound to this driver */
+
+ srv_spoolss_reset_printerdata( printer->info_2->drivername );
+
+ }
+ else
+ {
/*
* When a *new* driver is bound to a printer, the drivername is used to
* lookup previously saved driver initialization info, which is then
* bound to the printer, simulating what happens in the Windows arch.
*/
- if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
- if (!set_driver_init(printer, 2)) {
+ if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
+ {
+ if (!set_driver_init(printer, 2))
+ {
DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
printer->info_2->drivername));
}
+
+ DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
+ printer->info_2->drivername));
+
notify_printer_driver(snum, printer->info_2->drivername);
}
}
@@ -5838,8 +5700,6 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* uint32 firstjob = q_u->firstjob; - notused. */
-/* uint32 numofjobs = q_u->numofjobs; - notused. */
uint32 level = q_u->level;
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
@@ -5907,7 +5767,7 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u
return WERR_BADFID;
}
- if (!print_job_exists(jobid)) {
+ if (!print_job_exists(snum, jobid)) {
return WERR_INVALID_PRINTER_NAME;
}
@@ -5916,18 +5776,18 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u
switch (command) {
case JOB_CONTROL_CANCEL:
case JOB_CONTROL_DELETE:
- if (print_job_delete(&user, jobid, &errcode)) {
+ if (print_job_delete(&user, snum, jobid, &errcode)) {
errcode = WERR_OK;
}
break;
case JOB_CONTROL_PAUSE:
- if (print_job_pause(&user, jobid, &errcode)) {
+ if (print_job_pause(&user, snum, jobid, &errcode)) {
errcode = WERR_OK;
}
break;
case JOB_CONTROL_RESTART:
case JOB_CONTROL_RESUME:
- if (print_job_resume(&user, jobid, &errcode)) {
+ if (print_job_resume(&user, snum, jobid, &errcode)) {
errcode = WERR_OK;
}
break;
@@ -6186,7 +6046,6 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
{
-/* UNISTR2 *name = &q_u->name; - notused. */
UNISTR2 *environment = &q_u->environment;
uint32 level = q_u->level;
NEW_BUFFER *buffer = NULL;
@@ -6243,7 +6102,6 @@ static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
{
-/* POLICY_HND *handle = &q_u->handle; - notused. */
uint32 level = q_u->level;
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
@@ -6344,7 +6202,6 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
{
-/* POLICY_HND *handle = &q_u->handle; - notused. */
uint32 level = q_u->level;
UNISTR2 *uni_formname = &q_u->formname;
NEW_BUFFER *buffer = NULL;
@@ -6640,7 +6497,6 @@ static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *need
WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
{
-/* UNISTR2 *name = &q_u->name; - notused. */
uint32 level = q_u->level;
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
@@ -6804,7 +6660,6 @@ WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_
WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
{
-/* UNISTR2 *server_name = &q_u->server_name; - notused. */
uint32 level = q_u->level;
SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
WERROR err = WERR_OK;
@@ -6952,10 +6807,10 @@ WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *
if ( q_u->copy_flags != APD_COPY_NEW_FILES )
return WERR_ACCESS_DENIED;
- /* just pass the information off to _spoolss_addprinterdriver() */
ZERO_STRUCT(q_u_local);
ZERO_STRUCT(r_u_local);
+ /* just pass the information off to _spoolss_addprinterdriver() */
q_u_local.server_name_ptr = q_u->server_name_ptr;
copy_unistr2(&q_u_local.server_name, &q_u->server_name);
q_u_local.level = q_u->level;
@@ -7047,38 +6902,38 @@ WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRI
WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
{
POLICY_HND *handle = &q_u->handle;
- uint32 idx = q_u->index;
- uint32 in_value_len = q_u->valuesize;
- uint32 in_data_len = q_u->datasize;
- uint32 *out_max_value_len = &r_u->valuesize;
- uint16 **out_value = &r_u->value;
- uint32 *out_value_len = &r_u->realvaluesize;
- uint32 *out_type = &r_u->type;
+ uint32 idx = q_u->index;
+ uint32 in_value_len = q_u->valuesize;
+ uint32 in_data_len = q_u->datasize;
+ uint32 *out_max_value_len= &r_u->valuesize;
+ uint16 **out_value = &r_u->value;
+ uint32 *out_value_len = &r_u->realvaluesize;
+ uint32 *out_type = &r_u->type;
uint32 *out_max_data_len = &r_u->datasize;
- uint8 **data_out = &r_u->data;
- uint32 *out_data_len = &r_u->realdatasize;
+ uint8 **data_out = &r_u->data;
+ uint32 *out_data_len = &r_u->realdatasize;
NT_PRINTER_INFO_LEVEL *printer = NULL;
- fstring value;
+ uint32 param_index;
+ uint32 biggest_valuesize;
+ uint32 biggest_datasize;
+ uint32 data_len;
+ Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+ int snum;
+ WERROR result;
+ REGISTRY_VALUE *val;
+ NT_PRINTER_DATA *p_data;
+ int i, key_index, num_values;
+ int name_length;
- uint32 param_index;
- uint32 biggest_valuesize;
- uint32 biggest_datasize;
- uint32 data_len;
- Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
- int snum;
- uint8 *data=NULL;
- uint32 type;
- WERROR result;
-
- ZERO_STRUCT(printer);
+ ZERO_STRUCT( printer );
- *out_type=0;
+ *out_type = 0;
- *out_max_data_len=0;
- *data_out=NULL;
- *out_data_len=0;
+ *out_max_data_len = 0;
+ *data_out = NULL;
+ *out_data_len = 0;
DEBUG(5,("spoolss_enumprinterdata\n"));
@@ -7093,103 +6948,133 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
result = get_a_printer(&printer, 2, lp_servicename(snum));
if (!W_ERROR_IS_OK(result))
return result;
+
+ p_data = &printer->info_2->data;
+ key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
+
+ result = WERR_OK;
/*
* The NT machine wants to know the biggest size of value and data
*
* cf: MSDN EnumPrinterData remark section
*/
- if ( (in_value_len==0) && (in_data_len==0) ) {
+
+ if ( !in_value_len && !in_data_len )
+ {
DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
- SAFE_FREE(data);
-
- param_index=0;
- biggest_valuesize=0;
- biggest_datasize=0;
+ param_index = 0;
+ biggest_valuesize = 0;
+ biggest_datasize = 0;
+
+ num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
- while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
- if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
- if (data_len > biggest_datasize) biggest_datasize=data_len;
-
- DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
-
- SAFE_FREE(data);
- param_index++;
+ for ( i=0; i<num_values; i++ )
+ {
+ val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
+
+ name_length = strlen(val->valuename);
+ if ( strlen(val->valuename) > biggest_valuesize )
+ biggest_valuesize = name_length;
+
+ if ( val->size > biggest_datasize )
+ biggest_datasize = val->size;
+
+ DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
+ biggest_datasize));
}
- /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
- *out_value_len=2*(1+biggest_valuesize);
- *out_data_len=biggest_datasize;
+ /* the value is an UNICODE string but real_value_size is the length
+ in bytes including the trailing 0 */
+
+ *out_value_len = 2 * (1+biggest_valuesize);
+ *out_data_len = biggest_datasize;
DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
- free_a_printer(&printer, 2);
- return WERR_OK;
+ goto done;
}
/*
* the value len is wrong in NT sp3
* that's the number of bytes not the number of unicode chars
*/
+
+ val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
- if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
-
- SAFE_FREE(data);
- free_a_printer(&printer, 2);
+ if ( !val )
+ {
/* out_value should default to "" or else NT4 has
problems unmarshalling the response */
- *out_max_value_len=(in_value_len/sizeof(uint16));
- if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
- return WERR_NOMEM;
+ *out_max_value_len = (in_value_len/sizeof(uint16));
+
+ if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
+ {
+ result = WERR_NOMEM;
+ goto done;
+ }
*out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
/* the data is counted in bytes */
+
*out_max_data_len = in_data_len;
- *out_data_len = in_data_len;
- if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
- return WERR_NOMEM;
+ *out_data_len = in_data_len;
+
+ /* only allocate when given a non-zero data_len */
+
+ if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
+ {
+ result = WERR_NOMEM;
+ goto done;
+ }
- return WERR_NO_MORE_ITEMS;
+ result = WERR_NO_MORE_ITEMS;
}
-
- free_a_printer(&printer, 2);
-
- /*
- * the value is:
- * - counted in bytes in the request
- * - counted in UNICODE chars in the max reply
- * - counted in bytes in the real size
- *
- * take a pause *before* coding not *during* coding
- */
+ else
+ {
+ /*
+ * the value is:
+ * - counted in bytes in the request
+ * - counted in UNICODE chars in the max reply
+ * - counted in bytes in the real size
+ *
+ * take a pause *before* coding not *during* coding
+ */
- *out_max_value_len=(in_value_len/sizeof(uint16));
- if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
- SAFE_FREE(data);
- return WERR_NOMEM;
- }
+ /* name */
+ *out_max_value_len = ( in_value_len / sizeof(uint16) );
+ if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
+ {
+ result = WERR_NOMEM;
+ goto done;
+ }
- *out_value_len = (uint32)rpcstr_push((char *)*out_value,value, in_value_len, 0);
+ *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
- *out_type=type;
+ /* type */
+
+ *out_type = regval_type( val );
- /* the data is counted in bytes */
- *out_max_data_len=in_data_len;
- if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
- SAFE_FREE(data);
- return WERR_NOMEM;
+ /* data - counted in bytes */
+
+ *out_max_data_len = in_data_len;
+ if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
+ {
+ result = WERR_NOMEM;
+ goto done;
+ }
+ data_len = (size_t)regval_size(val);
+ memcpy( *data_out, regval_data_p(val), data_len );
+ *out_data_len = data_len;
}
-
- memcpy(*data_out, data, (size_t)data_len);
- *out_data_len=data_len;
- SAFE_FREE(data);
-
- return WERR_OK;
+done:
+ free_a_printer(&printer, 2);
+ return result;
}
/****************************************************************************
@@ -7197,17 +7082,17 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
{
- POLICY_HND *handle = &q_u->handle;
- UNISTR2 *value = &q_u->value;
- uint32 type = q_u->type;
- uint8 *data = q_u->data;
- uint32 real_len = q_u->real_len;
+ POLICY_HND *handle = &q_u->handle;
+ UNISTR2 *value = &q_u->value;
+ uint32 type = q_u->type;
+ uint8 *data = q_u->data;
+ uint32 real_len = q_u->real_len;
- NT_PRINTER_INFO_LEVEL *printer = NULL;
- NT_PRINTER_PARAM *param = NULL, old_param;
- int snum=0;
- WERROR status = WERR_OK;
- Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum=0;
+ WERROR status = WERR_OK;
+ Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ fstring valuename;
DEBUG(5,("spoolss_setprinterdata\n"));
@@ -7219,8 +7104,6 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
if (!get_printer_snum(p,handle, &snum))
return WERR_BADFID;
- ZERO_STRUCT(old_param);
-
/*
* Access check : NT returns "access denied" if you make a
* SetPrinterData call without the necessary privildge.
@@ -7235,40 +7118,22 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
goto done;
}
- /* Check if we are making any changes or not. Return true if
- nothing is actually changing. This is not needed anymore but
- has been left in as an optimization to keep from from
- writing to disk as often --jerry */
-
status = get_a_printer(&printer, 2, lp_servicename(snum));
if (!W_ERROR_IS_OK(status))
return status;
- convert_specific_param(&param, value , type, data, real_len);
+ /* save the registry data */
+
+ unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
+ delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename );
+ add_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename, type, data, real_len );
- unlink_specific_param_if_exist(printer->info_2, param);
+ /* write the **entire** printer out to disk.... :-( */
- /*
- * When client side code sets a magic printer data key, detect it and save
- * the current printer data and the magic key's data (its the DEVMODE) for
- * future printer/driver initializations.
- */
- if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
- /*
- * Set devmode and printer initialization info
- */
- status = save_driver_init(printer, 2, param);
- }
- else {
- add_a_specific_param(printer->info_2, &param);
- status = mod_a_printer(*printer, 2);
- }
+ status = mod_a_printer(*printer, 2);
- done:
+done:
free_a_printer(&printer, 2);
- if (param)
- free_nt_printer_param(&param);
- SAFE_FREE(old_param.data);
return status;
}
@@ -7278,9 +7143,9 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
{
- POLICY_HND *handle = &q_u->handle;
- Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
- int snum;
+ POLICY_HND *handle = &q_u->handle;
+ Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ int snum;
DEBUG(5,("_spoolss_resetprinter\n"));
@@ -7304,16 +7169,19 @@ WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R
}
+/****************************************************************************
+****************************************************************************/
+
WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
{
- POLICY_HND *handle = &q_u->handle;
- UNISTR2 *value = &q_u->valuename;
+ POLICY_HND *handle = &q_u->handle;
+ UNISTR2 *value = &q_u->valuename;
- NT_PRINTER_INFO_LEVEL *printer = NULL;
- NT_PRINTER_PARAM param;
- int snum=0;
- WERROR status = WERR_OK;
- Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum=0;
+ WERROR status = WERR_OK;
+ Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ pstring valuename;
DEBUG(5,("spoolss_deleteprinterdata\n"));
@@ -7334,15 +7202,14 @@ WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_
if (!W_ERROR_IS_OK(status))
return status;
- ZERO_STRUCTP(&param);
- unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
+ unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
- if(!unlink_specific_param_if_exist(printer->info_2, &param))
- status = WERR_INVALID_PARAM;
- else
+ status = delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename );
+ if ( NT_STATUS_IS_OK(status) )
status = mod_a_printer(*printer, 2);
free_a_printer(&printer, 2);
+
return status;
}
@@ -7352,7 +7219,6 @@ WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_
WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* uint32 level = q_u->level; - notused. */
FORM *form = &q_u->form;
nt_forms_struct tmpForm;
int snum;
@@ -7971,9 +7837,10 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u,
* (a) DsDriver
* (b) DsSpooler
* (c) PnPData
+ * (d) DsUser
*/
- if (strcmp(key, "PrinterDriverData") != 0)
+ if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
return WERR_BADFILE;
DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
@@ -8019,7 +7886,7 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u,
unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
- if (strcmp(key, "PrinterDriverData") != 0)
+ if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
return WERR_INVALID_PARAM;
ZERO_STRUCT(q_u_local);
@@ -8054,7 +7921,7 @@ WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX
unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
- if (strcmp(key, "PrinterDriverData") != 0)
+ if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
return WERR_INVALID_PARAM;
memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
@@ -8070,57 +7937,66 @@ WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX
* spoolss_enumprinterkey
********************************************************************/
-/* constants for EnumPrinterKey() */
-#define ENUMERATED_KEY_SIZE 19
WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
{
fstring key;
- uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
+ uint16 *enumkeys = NULL;
char* ptr = NULL;
int i;
- char *PrinterKey = "PrinterDriverData";
+ int printerkey_len = strlen(SPOOL_PRINTERDATA_KEY)+1;
DEBUG(4,("_spoolss_enumprinterkey\n"));
- unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
+ unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
/*
* we only support enumating all keys (key == "")
* Of course, the only key we support is the "PrinterDriverData"
* key
- */
- if (strlen(key) == 0)
+ */
+
+ if ( !strlen( key ) )
{
- r_u->needed = ENUMERATED_KEY_SIZE *2;
- if (q_u->size < r_u->needed)
+ r_u->needed = printerkey_len*2;
+
+ if ( q_u->size < r_u->needed )
return WERR_MORE_DATA;
- ptr = PrinterKey;
- for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
+ if ( !(enumkeys = talloc( p->mem_ctx, printerkey_len*2 )) ) {
+ DEBUG(0,("_spoolss_enumprinterkey: talloc() failed for [%d] bytes!\n",
+ printerkey_len));
+ return WERR_NOMEM;
+ }
+
+ ptr = SPOOL_PRINTERDATA_KEY;
+ for ( i=0; i<(printerkey_len-1); i++ )
{
enumkeys[i] = (uint16)(*ptr);
ptr++;
}
- /* tag of with 2 '\0's */
- enumkeys[i++] = '\0';
- enumkeys[i] = '\0';
+ /* tag of '\0's */
+
+ enumkeys[i] = 0x0;
- if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
+ if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys))
return WERR_BADFILE;
return WERR_OK;
}
/* The "PrinterDriverData" key should have no subkeys */
- if (strcmp(key, PrinterKey) == 0)
+ if ( strcmp(key, SPOOL_PRINTERDATA_KEY) == 0 )
{
- r_u-> needed = 2;
+ uint16 dummy_key = 0;
+
+ r_u->needed = 2;
+
if (q_u->size < r_u->needed)
return WERR_MORE_DATA;
- enumkeys[0] = 0x0;
- if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
+
+ if ( !make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, &dummy_key ) )
return WERR_BADFILE;
return WERR_OK;
@@ -8129,6 +8005,7 @@ WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPO
/* The return value for an unknown key is documented in MSDN
EnumPrinterKey description */
+
return WERR_BADFILE;
}
@@ -8148,7 +8025,7 @@ WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u,
unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
- if (strcmp(key, "PrinterDriverData") != 0)
+ if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
return WERR_INVALID_PARAM;
/*
@@ -8172,14 +8049,16 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
needed;
NT_PRINTER_INFO_LEVEL *printer = NULL;
PRINTER_ENUM_VALUES *enum_values = NULL;
- fstring key, value;
+ NT_PRINTER_DATA *p_data;
+ fstring key;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
int snum;
- uint32 param_index,
- data_len,
- type;
WERROR result;
- uint8 *data=NULL;
+ int key_index;
+ int i;
+ REGISTRY_VALUE *val;
+ char *value_name;
+ int data_len;
DEBUG(4,("_spoolss_enumprinterdataex\n"));
@@ -8190,20 +8069,8 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
}
- /*
- * The only key we support is "PrinterDriverData". This should return
- > an array of all the key/value pairs returned by EnumPrinterDataSee
- * _spoolss_getprinterdataex() for details --jerry
- */
-
- unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
- if (strcmp(key, "PrinterDriverData") != 0)
- {
- DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
- return WERR_INVALID_PARAM;
- }
-
-
+ /* first get the printer off of disk */
+
if (!get_printer_snum(p,handle, &snum))
return WERR_BADFID;
@@ -8211,55 +8078,78 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
result = get_a_printer(&printer, 2, lp_servicename(snum));
if (!W_ERROR_IS_OK(result))
return result;
-
- /*
- * loop through all params and build the array to pass
- * back to the client
- */
+ /* now look for a match on the key name */
+
+ p_data = &printer->info_2->data;
+
+ unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
+ if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
+ {
+ DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
+ result = WERR_INVALID_PARAM;
+ goto done;
+ }
+
result = WERR_OK;
- param_index = 0;
- needed = 0;
- num_entries = 0;
+ needed = 0;
- while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
+ /* allocate the memory for the array of pointers -- if necessary */
+
+ num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
+ if ( num_entries )
{
- PRINTER_ENUM_VALUES *ptr;
- uint32 add_len = 0;
-
- DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
-
- if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
+ if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
{
- DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
+ DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
+ num_entries*sizeof(PRINTER_ENUM_VALUES)));
result = WERR_NOMEM;
goto done;
}
- enum_values = ptr;
+
+ memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
+ }
+
+ /*
+ * loop through all params and build the array to pass
+ * back to the client
+ */
+
+ for ( i=0; i<num_entries; i++ )
+ {
+ /* lookup the registry value */
+
+ val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
+ DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
/* copy the data */
- init_unistr(&enum_values[num_entries].valuename, value);
- enum_values[num_entries].value_len = (strlen(value)+1) * 2;
- enum_values[num_entries].type = type;
- if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
- DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
- result = WERR_NOMEM;
- goto done;
+ value_name = regval_name( val );
+ init_unistr( &enum_values[i].valuename, value_name );
+ enum_values[i].value_len = (strlen(value_name)+1) * 2;
+ enum_values[i].type = regval_type( val );
+
+ data_len = regval_size( val );
+ if ( data_len ) {
+ if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
+ {
+ DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
+ data_len ));
+ result = WERR_NOMEM;
+ goto done;
+ }
}
- memcpy(enum_values[num_entries].data, data, data_len);
- enum_values[num_entries].data_len = data_len + add_len;
+ enum_values[i].data_len = data_len;
/* keep track of the size of the array in bytes */
- needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
-
- num_entries++;
- param_index++;
+ needed += spoolss_size_printer_enum_values(&enum_values[i]);
}
- r_u->needed = needed;
- r_u->returned = num_entries;
+ /* housekeeping information in the reply */
+
+ r_u->needed = needed;
+ r_u->returned = num_entries;
if (needed > in_size) {
result = WERR_MORE_DATA;
@@ -8355,4 +8245,23 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
return result;
}
+#if 0
+
+WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
+ SPOOL_R_REPLYOPENPRINTER *r_u)
+{
+ DEBUG(5,("_spoolss_replyopenprinter\n"));
+
+ DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
+
+ return WERR_OK;
+}
+
+WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
+ SPOOL_R_REPLYCLOSEPRINTER *r_u)
+{
+ DEBUG(5,("_spoolss_replycloseprinter\n"));
+ return WERR_OK;
+}
+#endif
diff --git a/source3/rpc_server/srv_srvsvc.c b/source3/rpc_server/srv_srvsvc.c
index 5e1c005d54..4a372de089 100644
--- a/source3/rpc_server/srv_srvsvc.c
+++ b/source3/rpc_server/srv_srvsvc.c
@@ -345,6 +345,36 @@ static BOOL api_srv_net_share_del(pipes_struct *p)
}
/*******************************************************************
+ RPC to delete share information.
+********************************************************************/
+
+static BOOL api_srv_net_share_del_sticky(pipes_struct *p)
+{
+ SRV_Q_NET_SHARE_DEL q_u;
+ SRV_R_NET_SHARE_DEL r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ /* Unmarshall the net server del info. */
+ if(!srv_io_q_net_share_del("", &q_u, data, 0)) {
+ DEBUG(0,("api_srv_net_share_del_sticky: Failed to unmarshall SRV_Q_NET_SHARE_DEL.\n"));
+ return False;
+ }
+
+ r_u.status = _srv_net_share_del_sticky(p, &q_u, &r_u);
+
+ if(!srv_io_r_net_share_del("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_srv_net_share_del_sticky: Failed to marshall SRV_R_NET_SHARE_DEL.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/*******************************************************************
api_srv_net_remote_tod
********************************************************************/
@@ -503,6 +533,7 @@ static const struct api_struct api_srv_cmds[] =
{ "SRV_NET_SHARE_ENUM" , SRV_NET_SHARE_ENUM , api_srv_net_share_enum },
{ "SRV_NET_SHARE_ADD" , SRV_NET_SHARE_ADD , api_srv_net_share_add },
{ "SRV_NET_SHARE_DEL" , SRV_NET_SHARE_DEL , api_srv_net_share_del },
+ { "SRV_NET_SHARE_DEL_STICKY", SRV_NET_SHARE_DEL_STICKY, api_srv_net_share_del_sticky },
{ "SRV_NET_SHARE_GET_INFO", SRV_NET_SHARE_GET_INFO, api_srv_net_share_get_info },
{ "SRV_NET_SHARE_SET_INFO", SRV_NET_SHARE_SET_INFO, api_srv_net_share_set_info },
{ "SRV_NET_FILE_ENUM" , SRV_NET_FILE_ENUM , api_srv_net_file_enum },
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index 202e869d35..5c1038949b 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -3,6 +3,7 @@
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Jeremy Allison 2001.
+ * Copyright (C) Nigel Williams 2001.
*
* 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
@@ -29,32 +30,53 @@
extern pstring global_myname;
/*******************************************************************
+ Utility function to get the 'type' of a share from an snum.
+ ********************************************************************/
+static uint32 get_share_type(int snum)
+{
+ char *net_name = lp_servicename(snum);
+ int len_net_name = strlen(net_name);
+
+ /* work out the share type */
+ uint32 type = STYPE_DISKTREE;
+
+ if (lp_print_ok(snum))
+ type = STYPE_PRINTQ;
+ if (strequal(lp_fstype(snum), "IPC"))
+ type = STYPE_IPC;
+ if (net_name[len_net_name] == '$')
+ type |= STYPE_HIDDEN;
+
+ return type;
+}
+
+/*******************************************************************
+ Fill in a share info level 0 structure.
+ ********************************************************************/
+
+static void init_srv_share_info_0(pipes_struct *p, SRV_SHARE_INFO_0 *sh0, int snum)
+{
+ pstring net_name;
+
+ pstrcpy(net_name, lp_servicename(snum));
+
+ init_srv_share_info0(&sh0->info_0, net_name);
+ init_srv_share_info0_str(&sh0->info_0_str, net_name);
+}
+
+/*******************************************************************
Fill in a share info level 1 structure.
********************************************************************/
static void init_srv_share_info_1(pipes_struct *p, SRV_SHARE_INFO_1 *sh1, int snum)
{
- int len_net_name;
- pstring net_name;
pstring remark;
- uint32 type;
- pstrcpy(net_name, lp_servicename(snum));
+ char *net_name = lp_servicename(snum);
pstrcpy(remark, lp_comment(snum));
standard_sub_conn(p->conn, remark,sizeof(remark));
- len_net_name = strlen(net_name);
-
- /* work out the share type */
- type = STYPE_DISKTREE;
-
- if (lp_print_ok(snum))
- type = STYPE_PRINTQ;
- if (strequal("IPC$", net_name) || strequal("ADMIN$", net_name))
- type = STYPE_IPC;
- if (net_name[len_net_name] == '$')
- type |= STYPE_HIDDEN;
- init_srv_share_info1(&sh1->info_1, net_name, type, remark);
+ init_srv_share_info1(&sh1->info_1, net_name, get_share_type(snum), remark);
init_srv_share_info1_str(&sh1->info_1_str, net_name, remark);
}
@@ -64,14 +86,11 @@ static void init_srv_share_info_1(pipes_struct *p, SRV_SHARE_INFO_1 *sh1, int sn
static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int snum)
{
- int len_net_name;
- pstring net_name;
pstring remark;
pstring path;
pstring passwd;
- uint32 type;
- pstrcpy(net_name, lp_servicename(snum));
+ char *net_name = lp_servicename(snum);
pstrcpy(remark, lp_comment(snum));
standard_sub_conn(p->conn, remark,sizeof(remark));
pstrcpy(path, "C:");
@@ -85,19 +104,8 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
string_replace(path, '/', '\\');
pstrcpy(passwd, "");
- len_net_name = strlen(net_name);
- /* work out the share type */
- type = STYPE_DISKTREE;
-
- if (lp_print_ok(snum))
- type = STYPE_PRINTQ;
- if (strequal("IPC$", net_name) || strequal("ADMIN$", net_name))
- type = STYPE_IPC;
- if (net_name[len_net_name] == '$')
- type |= STYPE_HIDDEN;
-
- init_srv_share_info2(&sh2->info_2, net_name, type, remark, 0, 0xffffffff, 1, path, passwd);
+ init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum), remark, 0, 0xffffffff, 1, path, passwd);
init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd);
}
@@ -251,7 +259,7 @@ static BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC
/* Free malloc'ed memory */
- out:
+out:
prs_mem_free(&ps);
if (mem_ctx)
@@ -337,7 +345,7 @@ BOOL share_access_check(connection_struct *conn, int snum, user_struct *vuser, u
ret = se_access_check(psd, token, desired_access, &granted, &status);
- out:
+out:
talloc_destroy(mem_ctx);
@@ -351,27 +359,15 @@ BOOL share_access_check(connection_struct *conn, int snum, user_struct *vuser, u
static void init_srv_share_info_501(pipes_struct *p, SRV_SHARE_INFO_501 *sh501, int snum)
{
int len_net_name;
- pstring net_name;
pstring remark;
- uint32 type;
- pstrcpy(net_name, lp_servicename(snum));
+ char *net_name = lp_servicename(snum);
pstrcpy(remark, lp_comment(snum));
standard_sub_conn(p->conn, remark, sizeof(remark));
len_net_name = strlen(net_name);
- /* work out the share type */
- type = STYPE_DISKTREE;
-
- if (lp_print_ok(snum))
- type = STYPE_PRINTQ;
- if (strequal("IPC$", net_name) || strequal("ADMIN$", net_name))
- type = STYPE_IPC;
- if (net_name[len_net_name] == '$')
- type |= STYPE_HIDDEN;
-
- init_srv_share_info501(&sh501->info_501, net_name, type, remark, (lp_csc_policy(snum) << 4));
+ init_srv_share_info501(&sh501->info_501, net_name, get_share_type(snum), remark, (lp_csc_policy(snum) << 4));
init_srv_share_info501_str(&sh501->info_501_str, net_name, remark);
}
@@ -386,7 +382,6 @@ static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502,
pstring remark;
pstring path;
pstring passwd;
- uint32 type;
SEC_DESC *sd;
size_t sd_size;
TALLOC_CTX *ctx = p->mem_ctx;
@@ -410,39 +405,86 @@ static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502,
pstrcpy(passwd, "");
len_net_name = strlen(net_name);
- /* work out the share type */
- type = STYPE_DISKTREE;
-
- if (lp_print_ok(snum))
- type = STYPE_PRINTQ;
- if (strequal("IPC$", net_name))
- type = STYPE_IPC;
- if (net_name[len_net_name] == '$')
- type |= STYPE_HIDDEN;
-
sd = get_share_security(ctx, snum, &sd_size);
- init_srv_share_info502(&sh502->info_502, net_name, type, remark, 0, 0xffffffff, 1, path, passwd, sd, sd_size);
- init_srv_share_info502_str(&sh502->info_502_str, &sh502->info_502, net_name, remark, path, passwd, sd, sd_size);
+ init_srv_share_info502(&sh502->info_502, net_name, get_share_type(snum), remark, 0, 0xffffffff, 1, path, passwd, sd, sd_size);
+ init_srv_share_info502_str(&sh502->info_502_str, net_name, remark, path, passwd, sd, sd_size);
+}
+
+/***************************************************************************
+ Fill in a share info level 1004 structure.
+ ***************************************************************************/
+
+static void init_srv_share_info_1004(pipes_struct *p, SRV_SHARE_INFO_1004* sh1004, int snum)
+{
+ pstring remark;
+
+ pstrcpy(remark, lp_comment(snum));
+ standard_sub_conn(p->conn, remark, sizeof(remark));
+
+ ZERO_STRUCTP(sh1004);
+
+ init_srv_share_info1004(&sh1004->info_1004, remark);
+ init_srv_share_info1004_str(&sh1004->info_1004_str, remark);
}
/***************************************************************************
Fill in a share info level 1005 structure.
***************************************************************************/
-static void init_srv_share_info_1005(SRV_SHARE_INFO_1005* sh1005, int snum)
+static void init_srv_share_info_1005(pipes_struct *p, SRV_SHARE_INFO_1005* sh1005, int snum)
{
sh1005->dfs_root_flag = 0;
if(lp_host_msdfs() && lp_msdfs_root(snum))
sh1005->dfs_root_flag = 3;
}
+/***************************************************************************
+ Fill in a share info level 1006 structure.
+ ***************************************************************************/
+
+static void init_srv_share_info_1006(pipes_struct *p, SRV_SHARE_INFO_1006* sh1006, int snum)
+{
+ sh1006->max_uses = -1;
+}
+
+/***************************************************************************
+ Fill in a share info level 1007 structure.
+ ***************************************************************************/
+
+static void init_srv_share_info_1007(pipes_struct *p, SRV_SHARE_INFO_1007* sh1007, int snum)
+{
+ pstring alternate_directory_name = "";
+ uint32 flags = 0;
+
+ ZERO_STRUCTP(sh1007);
+
+ init_srv_share_info1007(&sh1007->info_1007, flags, alternate_directory_name);
+ init_srv_share_info1007_str(&sh1007->info_1007_str, alternate_directory_name);
+}
+
+/*******************************************************************
+ Fill in a share info level 1501 structure.
+ ********************************************************************/
+
+static void init_srv_share_info_1501(pipes_struct *p, SRV_SHARE_INFO_1501 *sh1501, int snum)
+{
+ SEC_DESC *sd;
+ size_t sd_size;
+ TALLOC_CTX *ctx = p->mem_ctx;
+
+ ZERO_STRUCTP(sh1501);
+
+ sd = get_share_security(ctx, snum, &sd_size);
+
+ sh1501->sdb = make_sec_desc_buf(p->mem_ctx, sd_size, sd);
+}
/*******************************************************************
True if it ends in '$'.
********************************************************************/
-static BOOL is_admin_share(int snum)
+static BOOL is_hidden_share(int snum)
{
pstring net_name;
@@ -471,7 +513,7 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
/* Count the number of entries. */
for (snum = 0; snum < num_services; snum++) {
- if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_admin_share(snum)) )
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) )
num_entries++;
}
@@ -483,6 +525,24 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
return True;
switch (info_level) {
+ case 0:
+ {
+ SRV_SHARE_INFO_0 *info0;
+ int i = 0;
+
+ info0 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_0));
+
+ for (snum = *resume_hnd; snum < num_services; snum++) {
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
+ init_srv_share_info_0(p, &info0[i++], snum);
+ }
+ }
+
+ ctr->share.info0 = info0;
+ break;
+
+ }
+
case 1:
{
SRV_SHARE_INFO_1 *info1;
@@ -491,7 +551,7 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
info1 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1));
for (snum = *resume_hnd; snum < num_services; snum++) {
- if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_admin_share(snum)) ) {
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
init_srv_share_info_1(p, &info1[i++], snum);
}
}
@@ -508,7 +568,7 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
info2 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_2));
for (snum = *resume_hnd; snum < num_services; snum++) {
- if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_admin_share(snum)) ) {
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
init_srv_share_info_2(p, &info2[i++], snum);
}
}
@@ -525,7 +585,7 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
info501 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_501));
for (snum = *resume_hnd; snum < num_services; snum++) {
- if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_admin_share(snum)) ) {
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
init_srv_share_info_501(p, &info501[i++], snum);
}
}
@@ -542,7 +602,7 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
info502 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_502));
for (snum = *resume_hnd; snum < num_services; snum++) {
- if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_admin_share(snum)) ) {
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
init_srv_share_info_502(p, &info502[i++], snum);
}
}
@@ -551,6 +611,92 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
break;
}
+ /* here for completeness but not currently used with enum (1004 - 1501)*/
+
+ case 1004:
+ {
+ SRV_SHARE_INFO_1004 *info1004;
+ int i = 0;
+
+ info1004 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1004));
+
+ for (snum = *resume_hnd; snum < num_services; snum++) {
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
+ init_srv_share_info_1004(p, &info1004[i++], snum);
+ }
+ }
+
+ ctr->share.info1004 = info1004;
+ break;
+ }
+
+ case 1005:
+ {
+ SRV_SHARE_INFO_1005 *info1005;
+ int i = 0;
+
+ info1005 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1005));
+
+ for (snum = *resume_hnd; snum < num_services; snum++) {
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
+ init_srv_share_info_1005(p, &info1005[i++], snum);
+ }
+ }
+
+ ctr->share.info1005 = info1005;
+ break;
+ }
+
+ case 1006:
+ {
+ SRV_SHARE_INFO_1006 *info1006;
+ int i = 0;
+
+ info1006 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1006));
+
+ for (snum = *resume_hnd; snum < num_services; snum++) {
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
+ init_srv_share_info_1006(p, &info1006[i++], snum);
+ }
+ }
+
+ ctr->share.info1006 = info1006;
+ break;
+ }
+
+ case 1007:
+ {
+ SRV_SHARE_INFO_1007 *info1007;
+ int i = 0;
+
+ info1007 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1007));
+
+ for (snum = *resume_hnd; snum < num_services; snum++) {
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
+ init_srv_share_info_1007(p, &info1007[i++], snum);
+ }
+ }
+
+ ctr->share.info1007 = info1007;
+ break;
+ }
+
+ case 1501:
+ {
+ SRV_SHARE_INFO_1501 *info1501;
+ int i = 0;
+
+ info1501 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1501));
+
+ for (snum = *resume_hnd; snum < num_services; snum++) {
+ if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
+ init_srv_share_info_1501(p, &info1501[i++], snum);
+ }
+ }
+
+ ctr->share.info1501 = info1501;
+ break;
+ }
default:
DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n", info_level));
return False;
@@ -596,6 +742,9 @@ static void init_srv_r_net_share_get_info(pipes_struct *p, SRV_R_NET_SHARE_GET_I
if (snum >= 0) {
switch (info_level) {
+ case 0:
+ init_srv_share_info_0(p, &r_n->info.share.info0, snum);
+ break;
case 1:
init_srv_share_info_1(p, &r_n->info.share.info1, snum);
break;
@@ -608,8 +757,24 @@ static void init_srv_r_net_share_get_info(pipes_struct *p, SRV_R_NET_SHARE_GET_I
case 502:
init_srv_share_info_502(p, &r_n->info.share.info502, snum);
break;
+
+ /* here for completeness */
+ case 1004:
+ init_srv_share_info_1004(p, &r_n->info.share.info1004, snum);
+ break;
case 1005:
- init_srv_share_info_1005(&r_n->info.share.info1005, snum);
+ init_srv_share_info_1005(p, &r_n->info.share.info1005, snum);
+ break;
+
+ /* here for completeness 1006 - 1501 */
+ case 1006:
+ init_srv_share_info_1006(p, &r_n->info.share.info1006, snum);
+ break;
+ case 1007:
+ init_srv_share_info_1007(p, &r_n->info.share.info1007, snum);
+ break;
+ case 1501:
+ init_srv_share_info_1501(p, &r_n->info.share.info1501, snum);
break;
default:
DEBUG(5,("init_srv_net_share_get_info: unsupported switch value %d\n", info_level));
@@ -955,7 +1120,8 @@ static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n,
********************************************************************/
static WERROR init_srv_file_info_ctr(pipes_struct *p, SRV_FILE_INFO_CTR *ctr,
- int switch_value, uint32 *resume_hnd, uint32 *total_entries)
+ int switch_value, uint32 *resume_hnd,
+ uint32 *total_entries)
{
WERROR status = WERR_OK;
TALLOC_CTX *ctx = p->mem_ctx;
@@ -1206,8 +1372,8 @@ WERROR _srv_net_share_enum(pipes_struct *p, SRV_Q_NET_SHARE_ENUM *q_u, SRV_R_NET
/* Create the list of shares for the response. */
init_srv_r_net_share_enum(p, r_u,
- q_u->ctr.info_level,
- get_enum_hnd(&q_u->enum_hnd), False);
+ q_u->ctr.info_level,
+ get_enum_hnd(&q_u->enum_hnd), False);
DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
@@ -1295,7 +1461,7 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
unistr2_to_ascii(share_name, &q_u->uni_share_name, sizeof(share_name));
- r_u->switch_value = 0;
+ r_u->parm_error = 0;
if (strequal(share_name,"IPC$") || strequal(share_name,"ADMIN$") || strequal(share_name,"global"))
return WERR_ACCESS_DENIED;
@@ -1312,28 +1478,47 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
get_current_user(&user,p);
- if (user.uid != 0)
+ if (user.uid != sec_initial_uid())
return WERR_ACCESS_DENIED;
switch (q_u->info_level) {
case 1:
- /* Not enough info in a level 1 to do anything. */
- return WERR_ACCESS_DENIED;
+ fstrcpy(pathname, lp_pathname(snum));
+ unistr2_to_ascii(comment, &q_u->info.share.info2.info_2_str.uni_remark, sizeof(comment));
+ type = q_u->info.share.info2.info_2.type;
+ psd = NULL;
+ break;
case 2:
- unistr2_to_ascii(comment, &q_u->info.share.info2.info_2_str.uni_remark, sizeof(share_name));
- unistr2_to_ascii(pathname, &q_u->info.share.info2.info_2_str.uni_path, sizeof(share_name));
+ unistr2_to_ascii(comment, &q_u->info.share.info2.info_2_str.uni_remark, sizeof(comment));
+ unistr2_to_ascii(pathname, &q_u->info.share.info2.info_2_str.uni_path, sizeof(pathname));
type = q_u->info.share.info2.info_2.type;
psd = NULL;
break;
+#if 0
+ /* not supported on set but here for completeness */
+ case 501:
+ unistr2_to_ascii(comment, &q_u->info.share.info501.info_501_str.uni_remark, sizeof(comment));
+ type = q_u->info.share.info501.info_501.type;
+ psd = NULL;
+ break;
+#endif
case 502:
- unistr2_to_ascii(comment, &q_u->info.share.info502.info_502_str.uni_remark, sizeof(share_name));
- unistr2_to_ascii(pathname, &q_u->info.share.info502.info_502_str.uni_path, sizeof(share_name));
+ unistr2_to_ascii(comment, &q_u->info.share.info502.info_502_str.uni_remark, sizeof(comment));
+ unistr2_to_ascii(pathname, &q_u->info.share.info502.info_502_str.uni_path, sizeof(pathname));
type = q_u->info.share.info502.info_502.type;
psd = q_u->info.share.info502.info_502_str.sd;
map_generic_share_sd_bits(psd);
break;
+ case 1004:
+ fstrcpy(pathname, lp_pathname(snum));
+ unistr2_to_ascii(comment, &q_u->info.share.info1004.info_1004_str.uni_remark, sizeof(comment));
+ type = STYPE_DISKTREE;
+ break;
case 1005:
+ case 1006:
+ case 1007:
return WERR_ACCESS_DENIED;
+ break;
case 1501:
fstrcpy(pathname, lp_pathname(snum));
fstrcpy(comment, lp_comment(snum));
@@ -1422,12 +1607,12 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
- r_u->switch_value = 0;
+ r_u->parm_error = 0;
get_current_user(&user,p);
- if (user.uid != 0) {
- DEBUG(10,("_srv_net_share_add: uid != 0. Access denied.\n"));
+ if (user.uid != sec_initial_uid()) {
+ DEBUG(10,("_srv_net_share_add: uid != sec_initial_uid(). Access denied.\n"));
return WERR_ACCESS_DENIED;
}
@@ -1437,6 +1622,9 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
}
switch (q_u->info_level) {
+ case 0:
+ /* No path. Not enough info in a level 0 to do anything. */
+ return WERR_ACCESS_DENIED;
case 1:
/* Not enough info in a level 1 to do anything. */
return WERR_ACCESS_DENIED;
@@ -1446,6 +1634,9 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
unistr2_to_ascii(pathname, &q_u->info.share.info2.info_2_str.uni_path, sizeof(share_name));
type = q_u->info.share.info2.info_2.type;
break;
+ case 501:
+ /* No path. Not enough info in a level 501 to do anything. */
+ return WERR_ACCESS_DENIED;
case 502:
unistr2_to_ascii(share_name, &q_u->info.share.info502.info_502_str.uni_netname, sizeof(share_name));
unistr2_to_ascii(comment, &q_u->info.share.info502.info_502_str.uni_remark, sizeof(share_name));
@@ -1454,7 +1645,16 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
psd = q_u->info.share.info502.info_502_str.sd;
map_generic_share_sd_bits(psd);
break;
+
+ /* none of the following contain share names. NetShareAdd does not have a separate parameter for the share name */
+
+ case 1004:
case 1005:
+ case 1006:
+ case 1007:
+ return WERR_ACCESS_DENIED;
+ break;
+ case 1501:
/* DFS only level. */
return WERR_ACCESS_DENIED;
default:
@@ -1544,7 +1744,7 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S
get_current_user(&user,p);
- if (user.uid != 0)
+ if (user.uid != sec_initial_uid())
return WERR_ACCESS_DENIED;
if (!lp_delete_share_cmd() || !*lp_delete_share_cmd())
@@ -1570,6 +1770,13 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S
return WERR_OK;
}
+WERROR _srv_net_share_del_sticky(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_SHARE_DEL *r_u)
+{
+ DEBUG(5,("_srv_net_share_del_stick: %d\n", __LINE__));
+
+ return _srv_net_share_del(p, q_u, r_u);
+}
+
/*******************************************************************
time of day
********************************************************************/
@@ -1703,7 +1910,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
close_cnum(conn, user.vuid);
return r_u->status;
- error_exit:
+error_exit:
if(fsp) {
close_file(fsp, True);
@@ -1799,7 +2006,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
close_cnum(conn, user.vuid);
return r_u->status;
- error_exit:
+error_exit:
if(fsp) {
close_file(fsp, True);
@@ -1864,6 +2071,7 @@ WERROR _srv_net_disk_enum(pipes_struct *p, SRV_Q_NET_DISK_ENUM *q_u, SRV_R_NET_D
{
uint32 i;
const char *disk_name;
+ TALLOC_CTX *ctx = p->mem_ctx;
uint32 resume=get_enum_hnd(&q_u->enum_hnd);
r_u->status=WERR_OK;
@@ -1872,6 +2080,18 @@ WERROR _srv_net_disk_enum(pipes_struct *p, SRV_Q_NET_DISK_ENUM *q_u, SRV_R_NET_D
r_u->disk_enum_ctr.unknown = 0;
+ {
+ DISK_INFO *dinfo;
+
+ int dinfo_size = MAX_SERVER_DISK_ENTRIES * sizeof(*dinfo);
+
+ if(!(dinfo = talloc(ctx, dinfo_size))) {
+ return WERR_NOMEM;
+ }
+
+ r_u->disk_enum_ctr.disk_info = dinfo;
+ }
+
r_u->disk_enum_ctr.disk_info_ptr = r_u->disk_enum_ctr.disk_info ? 1 : 0;
/*allow one DISK_INFO for null terminator*/
@@ -1885,7 +2105,7 @@ WERROR _srv_net_disk_enum(pipes_struct *p, SRV_Q_NET_DISK_ENUM *q_u, SRV_R_NET_D
init_unistr3(&r_u->disk_enum_ctr.disk_info[i].disk_name, disk_name);
}
- /*add a terminating null string. Is this there if there is more data to come?*/
+ /* add a terminating null string. Is this there if there is more data to come? */
r_u->disk_enum_ctr.entries_read++;
diff --git a/source3/rpc_server/srv_util.c b/source3/rpc_server/srv_util.c
index f896d1d9d8..50bf5db4fd 100644
--- a/source3/rpc_server/srv_util.c
+++ b/source3/rpc_server/srv_util.c
@@ -84,10 +84,10 @@ rid_name domain_group_rids[] =
NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, uint32 **prids, DOM_SID *q_sid)
{
SAM_ACCOUNT *sam_pass=NULL;
- struct sys_grent *glist;
- struct sys_grent *grp;
- int i, num, cur_rid=0;
+ int i, cur_rid=0;
gid_t gid;
+ gid_t *groups = NULL;
+ int num_groups;
GROUP_MAP map;
DOM_SID tmp_sid;
fstring user_name;
@@ -130,16 +130,21 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
fstrcpy(user_name, pdb_get_username(sam_pass));
grid=pdb_get_group_rid(sam_pass);
gid=pdb_get_gid(sam_pass);
-
- grp = glist = getgrent_list();
- if (grp == NULL) {
+
+ become_root();
+ /* on some systems this must run as root */
+ num_groups = getgroups_user(user_name, &groups);
+ unbecome_root();
+ if (num_groups == -1) {
+ /* this should never happen */
+ DEBUG(2,("get_alias_user_groups: getgroups_user failed\n"));
pdb_free_sam(&sam_pass);
- return NT_STATUS_NO_MEMORY;
+ return NT_STATUS_UNSUCCESSFUL;
}
-
- for (; grp != NULL; grp = grp->next) {
- if(!get_group_from_gid(grp->gr_gid, &map, MAPPING_WITHOUT_PRIV)) {
- DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)grp->gr_gid));
+
+ for (i=0;i<num_groups;i++) {
+ if(!get_group_from_gid(groups[i], &map, MAPPING_WITHOUT_PRIV)) {
+ DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)groups[i]));
continue;
}
@@ -159,7 +164,7 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
}
/* Don't return winbind groups as they are not local! */
- if (winbind_groups_exist && (grp->gr_gid >= winbind_gid_low) && (grp->gr_gid <= winbind_gid_high)) {
+ if (winbind_groups_exist && (groups[i] >= winbind_gid_low) && (groups[i] <= winbind_gid_high)) {
DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name));
continue;
}
@@ -170,30 +175,21 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
continue;
}
- /* the group is fine, we can check if there is the user we're looking for */
- DEBUG(10,("get_alias_user_groups: checking if the user is a member of %s.\n", map.nt_name));
-
- for(num=0; grp->gr_mem[num]!=NULL; num++) {
- if(strcmp(grp->gr_mem[num], user_name)==0) {
- /* we found the user, add the group to the list */
-
- new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1));
- if (new_rids==NULL) {
- DEBUG(10,("get_alias_user_groups: could not realloc memory\n"));
- pdb_free_sam(&sam_pass);
- return NT_STATUS_NO_MEMORY;
- }
- rids=new_rids;
-
- sid_peek_rid(&map.sid, &(rids[cur_rid]));
- DEBUG(10,("get_alias_user_groups: user found in group %s\n", map.nt_name));
- cur_rid++;
- break;
- }
+ new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1));
+ if (new_rids==NULL) {
+ DEBUG(10,("get_alias_user_groups: could not realloc memory\n"));
+ pdb_free_sam(&sam_pass);
+ free(groups);
+ return NT_STATUS_NO_MEMORY;
}
+ rids=new_rids;
+
+ sid_peek_rid(&map.sid, &(rids[cur_rid]));
+ cur_rid++;
+ break;
}
- grent_free(glist);
+ free(groups);
/* now check for the user's gid (the primary group rid) */
for (i=0; i<cur_rid && grid!=rids[i]; i++)