Merge branch 'master' of git://git.samba.org/samba into teventfix
authorJelmer Vernooij <jelmer@samba.org>
Sun, 1 Mar 2009 15:39:35 +0000 (16:39 +0100)
committerJelmer Vernooij <jelmer@samba.org>
Sun, 1 Mar 2009 15:39:35 +0000 (16:39 +0100)
Conflicts:
lib/tevent/pytevent.c

343 files changed:
WHATSNEW4.txt
docs-xml/archives/THANKS
docs-xml/manpages-3/ldbrename.1.xml [new file with mode: 0644]
docs-xml/manpages-3/mount.cifs.8.xml
docs-xml/manpages-3/vfs_acl_tdb.8.xml [new file with mode: 0644]
docs-xml/manpages-3/vfs_acl_xattr.8.xml [new file with mode: 0644]
docs-xml/smbdotconf/browse/enhancedbrowsing.xml
docs-xml/smbdotconf/locking/strictlocking.xml
docs-xml/smbdotconf/misc/remoteannounce.xml
docs-xml/smbdotconf/misc/usershareallowguests.xml
docs-xml/smbdotconf/misc/usershareprefixallowlist.xml
docs-xml/smbdotconf/misc/usersharetemplateshare.xml
docs-xml/smbdotconf/printing/useclientdriver.xml
docs-xml/smbdotconf/protocol/aclcheckpermissions.xml
docs-xml/smbdotconf/protocol/enableasusupport.xml
docs-xml/smbdotconf/security/clientlanmanauth.xml
docs-xml/smbdotconf/security/clientsigning.xml
docs-xml/smbdotconf/security/lanmanauth.xml
docs-xml/smbdotconf/security/passwordserver.xml
docs-xml/smbdotconf/security/security.xml
docs-xml/smbdotconf/security/serverschannel.xml
docs-xml/smbdotconf/security/serversigning.xml
docs-xml/smbdotconf/security/smbencrypt.xml
docs-xml/smbdotconf/security/updateencrypted.xml
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
lib/async_req/async_sock.c
lib/async_req/async_sock.h
lib/replace/getifaddrs.c
lib/replace/libreplace_ld.m4
lib/replace/system/network.h
lib/smbconf/smbconf.c
lib/smbconf/smbconf.h
lib/smbconf/smbconf_private.h
lib/smbconf/smbconf_txt.c
lib/tdb/common/open.c
lib/tevent/libtevent.m4
lib/tevent/tevent.h
lib/tevent/tevent_queue.c [new file with mode: 0644]
lib/tevent/tevent_req.c
lib/torture/config.mk
lib/util/become_daemon.c
lib/util/system.c
lib/util/tevent_ntstatus.c [new file with mode: 0644]
lib/util/tevent_ntstatus.h [new file with mode: 0644]
lib/util/tevent_unix.c [new file with mode: 0644]
lib/util/tevent_unix.h [new file with mode: 0644]
lib/util/util.c
lib/util/util.h
libcli/ldap/config.mk [new file with mode: 0644]
libcli/ldap/ldap_errors.h [moved from source4/libcli/ldap/ldap_errors.h with 98% similarity]
libcli/ldap/ldap_message.c [moved from source4/libcli/ldap/ldap.c with 88% similarity]
libcli/ldap/ldap_message.h [moved from source3/include/smb_ldap.h with 70% similarity]
libcli/ldap/ldap_ndr.c [moved from source4/libcli/ldap/ldap_ndr.c with 98% similarity]
libcli/ldap/ldap_ndr.h [moved from source4/libcli/ldap/ldap_ndr.h with 100% similarity]
libcli/util/doserr.c
libcli/util/werror.h
librpc/gen_ndr/cli_eventlog.c
librpc/gen_ndr/cli_eventlog.h
librpc/gen_ndr/cli_spoolss.c
librpc/gen_ndr/cli_spoolss.h
librpc/gen_ndr/dfs.h
librpc/gen_ndr/drsblobs.h
librpc/gen_ndr/drsuapi.h
librpc/gen_ndr/dssetup.h
librpc/gen_ndr/echo.h
librpc/gen_ndr/epmapper.h
librpc/gen_ndr/eventlog.h
librpc/gen_ndr/initshutdown.h
librpc/gen_ndr/krb5pac.h
librpc/gen_ndr/lsa.h
librpc/gen_ndr/misc.h
librpc/gen_ndr/named_pipe_auth.h
librpc/gen_ndr/nbt.h
librpc/gen_ndr/ndr_eventlog.c
librpc/gen_ndr/ndr_eventlog.h
librpc/gen_ndr/ndr_spoolss.c
librpc/gen_ndr/ndr_spoolss.h
librpc/gen_ndr/netlogon.h
librpc/gen_ndr/ntsvcs.h
librpc/gen_ndr/samr.h
librpc/gen_ndr/security.h
librpc/gen_ndr/spoolss.h
librpc/gen_ndr/srv_eventlog.c
librpc/gen_ndr/srv_eventlog.h
librpc/gen_ndr/srv_spoolss.c
librpc/gen_ndr/srvsvc.h
librpc/gen_ndr/svcctl.h
librpc/gen_ndr/winreg.h
librpc/gen_ndr/wkssvc.h
librpc/gen_ndr/xattr.h
librpc/idl/eventlog.idl
librpc/idl/spoolss.idl
librpc/ndr/ndr_sec_helper.c
librpc/ndr/ndr_spoolss_buf.c
librpc/ndr/ndr_spoolss_buf.h
pidl/lib/Parse/Pidl/Samba4/Header.pm
pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm
pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
pidl/lib/Parse/Pidl/Samba4/Python.pm
selftest/target/Samba4.pm
source3/Makefile.in
source3/auth/auth.c
source3/auth/auth_compat.c
source3/auth/auth_ntlmssp.c
source3/auth/auth_util.c
source3/auth/auth_wbc.c [new file with mode: 0644]
source3/client/client.c
source3/client/mount.cifs.c
source3/configure.in
source3/include/auth.h
source3/include/dbwrap.h
source3/include/includes.h
source3/include/libsmbclient.h
source3/include/locking.h
source3/include/nt_printing.h
source3/include/ntlmssp.h
source3/include/proto.h
source3/include/reg_db.h
source3/include/reg_objects.h
source3/include/regfio.h
source3/include/rpc_secdes.h
source3/include/rpc_spoolss.h
source3/include/smb.h
source3/include/smb_share_modes.h
source3/include/smbprofile.h
source3/include/vfs.h
source3/include/vfs_macros.h
source3/lib/dbwrap.c
source3/lib/dbwrap_tdb.c
source3/lib/display_sec.c
source3/lib/events.c
source3/lib/fault.c
source3/lib/file_id.c
source3/lib/ldap_debug_handler.c
source3/lib/secdesc.c
source3/lib/smbconf/smbconf_reg.c
source3/lib/smbldap.c
source3/lib/system.c
source3/lib/tdb_validate.c
source3/lib/util.c
source3/lib/util_sock.c
source3/lib/util_str.c
source3/lib/wb_reqtrans.c
source3/lib/wbclient.c
source3/libaddns/dns.h
source3/libads/disp_sec.c
source3/libgpo/gpo_reg.c
source3/libgpo/gpo_sec.c
source3/libnet/libnet_join.c
source3/librpc/gen_ndr/ndr_notify.c
source3/librpc/gen_ndr/notify.h
source3/librpc/idl/notify.idl
source3/librpc/ndr/util.c
source3/libsmb/cliconnect.c
source3/libsmb/libsmb_context.c
source3/libsmb/libsmb_dir.c
source3/libsmb/libsmb_file.c
source3/libsmb/libsmb_path.c
source3/libsmb/libsmb_server.c
source3/libsmb/libsmb_stat.c
source3/libsmb/nmblib.c
source3/libsmb/ntlmssp.c
source3/libsmb/smb_share_modes.c
source3/locking/brlock.c
source3/locking/locking.c
source3/modules/nfs4_acls.c
source3/modules/nfs4_acls.h
source3/modules/onefs.h
source3/modules/onefs_acl.c
source3/modules/onefs_cbrl.c
source3/modules/onefs_notify.c [new file with mode: 0644]
source3/modules/onefs_shadow_copy.c [new file with mode: 0644]
source3/modules/onefs_shadow_copy.h [new file with mode: 0644]
source3/modules/onefs_streams.c
source3/modules/onefs_system.c
source3/modules/vfs_acl_tdb.c
source3/modules/vfs_acl_xattr.c
source3/modules/vfs_default.c
source3/modules/vfs_extd_audit.c
source3/modules/vfs_fileid.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_onefs.c
source3/modules/vfs_onefs_shadow_copy.c [new file with mode: 0644]
source3/modules/vfs_solarisacl.c
source3/modules/vfs_streams_depot.c
source3/modules/vfs_streams_xattr.c
source3/modules/vfs_xattr_tdb.c
source3/nmbd/nmbd.c
source3/param/loadparm.c
source3/passdb/pdb_interface.c
source3/passdb/pdb_ldap.c
source3/passdb/pdb_wbc_sam.c [new file with mode: 0644]
source3/printing/notify.c
source3/printing/nt_printing.c
source3/printing/printfsp.c
source3/printing/printing.c
source3/printing/tests/vlp.c
source3/profile/profile.c
source3/registry/reg_api.c
source3/registry/reg_backend_current_version.c
source3/registry/reg_backend_db.c
source3/registry/reg_backend_hkpt_params.c
source3/registry/reg_backend_netlogon_params.c
source3/registry/reg_backend_perflib.c
source3/registry/reg_backend_printing.c
source3/registry/reg_backend_prod_options.c
source3/registry/reg_backend_shares.c
source3/registry/reg_backend_smbconf.c
source3/registry/reg_backend_tcpip_params.c
source3/registry/reg_dispatcher.c
source3/registry/reg_eventlog.c
source3/registry/reg_objects.c
source3/registry/regfio.c
source3/rpc_client/cli_spoolss.c
source3/rpc_client/cli_spoolss_notify.c [deleted file]
source3/rpc_client/rpc_transport_sock.c
source3/rpc_parse/parse_sec.c
source3/rpc_parse/parse_spoolss.c
source3/rpc_server/srv_eventlog_nt.c
source3/rpc_server/srv_netlog_nt.c
source3/rpc_server/srv_pipe_hnd.c
source3/rpc_server/srv_spoolss.c
source3/rpc_server/srv_spoolss_nt.c
source3/rpc_server/srv_svcctl_nt.c
source3/rpcclient/cmd_eventlog.c
source3/rpcclient/cmd_netlogon.c
source3/rpcclient/cmd_samr.c
source3/rpcclient/cmd_spoolss.c
source3/services/services_db.c
source3/smbd/close.c
source3/smbd/fileio.c
source3/smbd/files.c
source3/smbd/globals.c
source3/smbd/negprot.c
source3/smbd/notify.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/oplock.c
source3/smbd/oplock_irix.c
source3/smbd/oplock_onefs.c
source3/smbd/posix_acls.c
source3/smbd/reply.c
source3/smbd/server.c
source3/smbd/sesssetup.c
source3/smbd/trans2.c
source3/smbd/vfs.c
source3/utils/net_conf.c
source3/utils/net_rpc_printer.c
source3/utils/net_rpc_registry.c
source3/utils/profiles.c
source3/utils/sharesec.c
source3/utils/smbfilter.c
source3/utils/smbget.c
source3/winbindd/idmap_ldap.c
source3/winbindd/winbindd.c
source3/winbindd/winbindd_cache.c
source3/winbindd/winbindd_dual.c
source4/Makefile
source4/VERSION
source4/build/m4/public.m4
source4/client/mount.cifs.c
source4/configure.ac
source4/dsdb/samdb/ldb_modules/config.mk
source4/dsdb/samdb/ldb_modules/linked_attributes.c
source4/dsdb/samdb/ldb_modules/objectclass.c
source4/dsdb/samdb/ldb_modules/ranged_results.c
source4/dsdb/samdb/ldb_modules/samba3sam.c
source4/dsdb/samdb/ldb_modules/update_keytab.c
source4/dsdb/schema/schema_set.c
source4/headermap.txt
source4/heimdal/kuser/kinit.c
source4/heimdal/kuser/kuser_locl.h
source4/heimdal/lib/krb5/context.c
source4/heimdal/lib/krb5/krb5_locl.h
source4/heimdal_build/internal.m4
source4/heimdal_build/internal.mk
source4/ldap_server/ldap_server.c
source4/lib/events/tevent_s4.c
source4/lib/ldb/Makefile.in
source4/lib/ldb/common/ldb.c
source4/lib/ldb/common/ldb_modules.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/include/ldb_includes.h
source4/lib/ldb/include/ldb_private.h
source4/lib/ldb/ldb_ildap/ldb_ildap.c
source4/lib/ldb/ldb_ldap/ldb_ldap.c
source4/lib/ldb/ldb_map/ldb_map.c
source4/lib/ldb/ldb_map/ldb_map.h
source4/lib/ldb/ldb_map/ldb_map_inbound.c
source4/lib/ldb/ldb_map/ldb_map_outbound.c
source4/lib/ldb/ldb_map/ldb_map_private.h
source4/lib/ldb/ldb_tdb/ldb_index.c
source4/lib/ldb/ldb_tdb/ldb_tdb.c
source4/lib/ldb/ldb_tdb/ldb_tdb.h
source4/lib/ldb/modules/operational.c
source4/lib/ldb/modules/paged_results.c
source4/lib/ldb/modules/rdn_name.c
source4/lib/ldb/tools/cmdline.c
source4/lib/ldb/tools/ldbedit.c
source4/lib/ldb/tools/ldbsearch.c
source4/lib/ldb/tools/ldbtest.c
source4/lib/tls/config.m4
source4/lib/tls/config.mk
source4/libcli/cldap/cldap.c
source4/libcli/ldap/config.mk
source4/libcli/ldap/ldap.h
source4/libcli/ldap/ldap_client.c
source4/libcli/ldap/ldap_controls.c
source4/libcli/ldap/ldap_msg.c [deleted file]
source4/libcli/util/nterr.c
source4/main.mk
source4/ntptr/ntptr.h
source4/ntptr/ntptr_interface.c
source4/ntptr/simple_ldb/ntptr_simple_ldb.c
source4/rpc_server/netlogon/dcerpc_netlogon.c
source4/rpc_server/spoolss/dcesrv_spoolss.c
source4/scripting/python/samba/__init__.py
source4/scripting/python/samba/provision.py
source4/scripting/python/samba/samdb.py
source4/scripting/python/samba/tests/__init__.py
source4/scripting/python/samba/tests/provision.py
source4/selftest/tests.sh
source4/setup/DB_CONFIG
source4/setup/mmr_serverids.conf
source4/setup/olc_acl.conf [new file with mode: 0644]
source4/setup/olc_mmr.conf [new file with mode: 0644]
source4/setup/olc_pass.conf [new file with mode: 0644]
source4/setup/olc_seed.ldif [new file with mode: 0644]
source4/setup/olc_serverid.conf [new file with mode: 0644]
source4/setup/olc_syncrepl.conf [new file with mode: 0644]
source4/setup/olc_syncrepl_seed.conf [new file with mode: 0644]
source4/setup/provision-backend
source4/setup/slapd.conf
source4/smbd/server.c
source4/torture/raw/notify.c
source4/torture/raw/rename.c
source4/torture/raw/samba3misc.c
source4/torture/raw/streams.c
source4/torture/rpc/eventlog.c
source4/torture/rpc/spoolss.c
source4/utils/net/net.c
source4/utils/net/net_join.c

index 03cd72c518636c4a41f9a76e3a85dc9f164ac6de..7c637ccd6601f7dd070d197c835f13223628c97b 100644 (file)
@@ -1,4 +1,4 @@
-What's new in Samba 4 alpha6
+What's new in Samba 4 alpha7
 ============================
 
 Samba 4 is the ambitious next version of the Samba suite that is being
@@ -6,13 +6,13 @@ developed in parallel to the stable 3.0 series. The main emphasis in
 this branch is support for the Active Directory logon protocols used
 by Windows 2000 and above.
 
-Samba4 alpha6 follows on from the alpha release series we have been
+Samba4 alpha7 follows on from the alpha release series we have been
 publishing since September 2007
 
 WARNINGS
 ========
 
-Samba4 alpha6 is not a final Samba release.  That is more a reference
+Samba4 alpha7 is not a final Samba release.  That is more a reference
 to Samba4's lack of the features we expect you will need than a
 statement of code quality, but clearly it hasn't seen a broad
 deployment yet.  If you were to upgrade Samba3 (or indeed Windows) to
@@ -62,85 +62,35 @@ working on modules to map between AD-like behaviours and this backend.
 We are aiming for Samba 4 to be powerful frontend to large
 directories.
 
-CHANGES SINCE Alpha5
+CHANGES SINCE alpha6
 =====================
 
-In the time since Samba4 Alpha5 was released in June 2008, Samba has
+In the time since Samba4 alpha6 was released in Janurary 2009, Samba has
 continued to evolve, but you may particularly notice these areas 
 (in no particular order):
 
- The source code for various libraries that are used by both Samba 3 and 
- Samba 4 are now shared between the two rather than duplicated 
- (and being slightly diverged).
+ Multi Master Replication (MMR) configuration can now be generated 
+ for the OpenLDAP-Backend.
 
- The tevent library has been split out and is now usable on its own.
+ OpenLDAP-Online-Configuration (olc) can now be generated for the 
+ OpenLDAP-Backend. (OpenLDAP-Versions >=2.4.15 required).
 
- Several crash bugs and memory leaks in the registry library have been fixed.
+ Support for Windows 7 beta as a member of the Samba4 domain
 
- The Python modules have been extended and are no longer generated using SWIG.
+ Issues with the nesting of LDB transactions have been fixed
 
- Stream renames are now supported.
+ A number of internal libraries (tevent, auth in particular has been
+ updated for easier use outside Samba4
 
- The provision script now has an interactive mode.
+ spoolss IDL updates to bring Samba3 to use PIDL code, and to merge
+ the corrected IDL back into Samba4
+ Fixes to allow use of C++ compilers and to increase portability
 
- The (broken) copy of CTDB has been removed.
-
- More work towards supporting an OpenLDAP backend. 
-
- Initial work on using the Microsoft LDAP schema.
-
- The storage of schemas in LDB is now much more efficient.
-
- Support for extended DNs in LDB has been added.
-
- Incoming trusts are now supported.
-
- Compatibility of the registry server with several Windows versions has been 
- improved.
-
- Improvements to LSA.idl for better functionality in the usrmgr.exe.
-
- Improved handling of non-standard characters in passwords.
-
- The embedded JavaScript library has been removed in favor of Python.
-
- The WMI implementation has been re-added, but does not completely work yet.
-
- xpress compression is now supported in the NDR layer.
-
- The main binary is now named "samba" rather than "smbd".
-
- A simple script for setting the expiration of a user was added.
-
- The LDB library is now completely asynchronous internally.
-
- Various unknowns and correctness issues in the drsblobs and drsuapi RPC 
- interface implementations have been fixed.
-
- It is now possible to connect to an LDAP backend using SASL credentials.
-
- Multi-fragment NTtrans request support has been added.
-
- The DCE/RPC server can now listen on a separate pipe to allow DCE/RPC 
- connections forwarded from Samba 3. The user credentials are provided 
- by the client.
-
- A large number of bugs in the SMB2 implementation have been fixed.
-
- Auxiliary classes in LDAP schema conversion are now collapsed.
-
- Several tests have been added to the SMB testsuite.
-
- Object GUIDs in DCE/RPC connections are now dealt with properly.
-
- The correctness of the LSA and NETLOGON implementations has been 
- improved.
-
- Multi Master Replication configuration can now be generated 
- for OpenLDAP.
-
-These are just some of the highlights of the work done in the past few
-months.  More details can be found in our GIT history.
+ Fixed TLS (SSL) support with modern versions of GnuTLS
+These are just some of the highlights of the work done in the past 
+month.  More details can be found in our GIT history.
 
 
 CHANGES
@@ -163,17 +113,13 @@ KNOWN ISSUES
 
 - Clock Synchronisation is critical.  Many 'wrong password' errors are
   actually due to Kerberos objecting to a clock skew between client
-  and server.  (The NTP work in the previous alpha is partly to assist
+  and server.  (The NTP work in the previous alphas are partly to assist
   with this problem).
 
-- Samba4 alpha6 is currently only portable to recent Linux
+- Samba4 alpha7 is currently only portable to recent Linux
   distributions.  Work to return support for other Unix varients is
-  expected during the next alpha cycle
+  expected during the next alpha cycles
 
-- Samba4 alpha6 is incompatible with GnuTLS 2.0, found in Fedora 9 and
-  recent Ubuntu releases.  GnuTLS use may be disabled using the
-  --disable-gnutls argument to ./configure. (otherwise 'make test' and
-  LDAPS operations will hang).
 
 RUNNING Samba4
 ==============
index 789042f78e186a47ae6c18216348afc4bf64a22f..37ecc99eebb95102a7113d6445b06eb4c779e37f 100644 (file)
@@ -86,7 +86,7 @@ Tom Haapanen (tomh@metrics.com)
     consulting firm located in Waterloo, Ontario, Canada.  We work
     with a variety of environments (such as Windows, Windows NT and
     Unix), tools and application areas, and can provide assistance for
-    development work ranging from a few days to to multiple man-year
+    development work ranging from a few days to multiple man-year
     projects.  You can find more information at http://www.metrics.com/.
     
 
diff --git a/docs-xml/manpages-3/ldbrename.1.xml b/docs-xml/manpages-3/ldbrename.1.xml
new file mode 100644 (file)
index 0000000..391ec84
--- /dev/null
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<refentry id="ldbrename.1">
+
+<refmeta>
+       <refentrytitle>ldbrename</refentrytitle>
+       <manvolnum>1</manvolnum>
+</refmeta>
+
+
+<refnamediv>
+       <refname>ldbrename</refname>
+       <refpurpose>Edit LDB databases using your favorite editor</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+       <cmdsynopsis>
+               <command>ldbrename</command>
+               <arg choice="opt">-h</arg>
+               <arg choice="opt">-o options</arg>
+               <arg choice="req">olddn</arg>
+               <arg choice="req">newdb</arg>
+       </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1>
+       <title>DESCRIPTION</title>
+
+       <para>ldbrename is a utility that allows you to rename trees in 
+               an LDB database based by DN. This utility takes 
+               two arguments: the original 
+               DN name of the top element and the DN to change it to.
+       </para>
+
+</refsect1>
+
+
+<refsect1>
+       <title>OPTIONS</title>
+
+       <variablelist>
+               <varlistentry>
+               <term>-h</term>
+               <listitem><para>
+               Show list of available options.</para></listitem>
+               </varlistentry>
+
+               <varlistentry>
+                       <term>-H &lt;ldb-url&gt;</term>
+                       <listitem><para>
+                               LDB URL to connect to. See ldb(7) for details.
+                       </para></listitem>
+               </varlistentry>
+
+               <varlistentry>
+                       <term>-o options</term>
+                       <listitem><para>Extra ldb options, such as 
+                       modules.</para></listitem>
+               </varlistentry>
+               
+       </variablelist>
+       
+</refsect1>
+
+<refsect1>
+       <title>ENVIRONMENT</title>
+
+       <variablelist>
+               <varlistentry><term>LDB_URL</term>
+                       <listitem><para>LDB URL to connect to (can be overrided by using the 
+                                       -H command-line option.)</para></listitem>
+               </varlistentry>
+       </variablelist>
+       
+</refsect1>
+
+<refsect1>
+       <title>VERSION</title>
+
+       <para>This man page is correct for version 4.0 of the Samba suite.</para>
+</refsect1>
+
+<refsect1>
+       <title>SEE ALSO</title>
+
+       <para>ldb(7), ldbmodify, ldbdel, ldif(5)</para>
+
+</refsect1>
+
+<refsect1>
+       <title>AUTHOR</title>
+
+       <para> ldb was written by 
+                <ulink url="http://samba.org/~tridge/">Andrew Tridgell</ulink>.
+       </para>
+
+       <para>
+If you wish to report a problem or make a suggestion then please see
+the <ulink url="http://ldb.samba.org/"/> web site for
+current contact and maintainer information.
+       </para>
+
+       <para>This manpage was written by Jelmer Vernooij.</para>
+       
+</refsect1>
+
+</refentry>
index c386592f1df4622b844e0ff63888ad064cc9bcfa..ca8ae5f4bf7d4ebe9083254861b53d0dca24079d 100644 (file)
@@ -140,7 +140,7 @@ credentials file properly.
                 same domain (e.g. running winbind or nss_ldap) and
                 the server supports the Unix Extensions then the uid
                 and gid can be retrieved from the server (and uid
-                and gid would not have to be specifed on the mount. 
+                and gid would not have to be specified on the mount.
                 For servers which do not support the CIFS Unix
                 extensions, the default uid (and gid) returned on lookup 
                 of existing files will be the uid (gid) of the person
diff --git a/docs-xml/manpages-3/vfs_acl_tdb.8.xml b/docs-xml/manpages-3/vfs_acl_tdb.8.xml
new file mode 100644 (file)
index 0000000..086b86f
--- /dev/null
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
+<refentry id="vfs_acl_tdb.8">
+
+<refmeta>
+       <refentrytitle>vfs_acl_tdb</refentrytitle>
+       <manvolnum>8</manvolnum>
+       <refmiscinfo class="source">Samba</refmiscinfo>
+       <refmiscinfo class="manual">System Administration tools</refmiscinfo>
+       <refmiscinfo class="version">3.3</refmiscinfo>
+</refmeta>
+
+
+<refnamediv>
+       <refname>vfs_acl_tdb</refname>
+       <refpurpose>Save NTFS-ACLs in a tdb file</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+       <cmdsynopsis>
+               <command>vfs objects = acl_tdb</command>
+       </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1>
+       <title>DESCRIPTION</title>
+
+       <para>This VFS module is part of the
+       <citerefentry><refentrytitle>samba</refentrytitle>
+       <manvolnum>7</manvolnum></citerefentry> suite.</para>
+
+       <para>The <command>vfs_acl_tdb</command> VFS module stores
+       NTFS Access Control Lists (ACLs) in a tdb file.
+       This enables the full mapping of Windows ACLs on Samba
+       servers.
+       </para>
+
+       <para>
+       The ACL settings are stored in
+       <filename>$LOCKDIR/file_ntacls.tdb</filename>.
+       </para>
+
+       <para>Please note that this module is
+       <emphasis>experimental</emphasis>!
+       </para>
+
+       <para>This module is stackable.</para>
+</refsect1>
+
+<refsect1>
+       <title>OPTIONS</title>
+       <para>
+       There are no options for <command>vfs_acl_tdb</command>.
+       </para>
+</refsect1>
+
+<refsect1>
+       <title>AUTHOR</title>
+
+       <para>The original Samba software and related utilities
+       were created by Andrew Tridgell. Samba is now developed
+       by the Samba Team as an Open Source project similar
+       to the way the Linux kernel is developed.</para>
+</refsect1>
+
+</refentry>
diff --git a/docs-xml/manpages-3/vfs_acl_xattr.8.xml b/docs-xml/manpages-3/vfs_acl_xattr.8.xml
new file mode 100644 (file)
index 0000000..7387824
--- /dev/null
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
+<refentry id="vfs_acl_xattr.8">
+
+<refmeta>
+       <refentrytitle>vfs_acl_xattr</refentrytitle>
+       <manvolnum>8</manvolnum>
+       <refmiscinfo class="source">Samba</refmiscinfo>
+       <refmiscinfo class="manual">System Administration tools</refmiscinfo>
+       <refmiscinfo class="version">3.3</refmiscinfo>
+</refmeta>
+
+
+<refnamediv>
+       <refname>vfs_acl_xattr</refname>
+       <refpurpose>Save NTFS-ACLs in Extended Attributes (EAs)</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+       <cmdsynopsis>
+               <command>vfs objects = acl_xattr</command>
+       </cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1>
+       <title>DESCRIPTION</title>
+
+       <para>This VFS module is part of the
+       <citerefentry><refentrytitle>samba</refentrytitle>
+       <manvolnum>7</manvolnum></citerefentry> suite.</para>
+
+       <para>The <command>vfs_acl_xattr</command> VFS module stores
+       NTFS Access Control Lists (ACLs) in Extended Attributes (EAs).
+       This enables the full mapping of Windows ACLs on Samba
+       servers.
+       </para>
+
+       <para>The ACLs are stored in the Extended Attribute
+       <parameter>security.NTACL</parameter> of a file or directory.
+       This Attribute is <emphasis>not</emphasis> listed by
+       <command>getfattr -d <filename>filename</filename></command>.
+       To show the current value, the name of the EA must be specified
+       (e.g. <command>getfattr -n security.NTACL <filename>filename</filename>
+       </command>).
+       </para>
+
+       <para>Please note that this module is
+       <emphasis>experimental</emphasis>!
+       </para>
+
+       <para>This module is stackable.</para>
+</refsect1>
+
+<refsect1>
+       <title>OPTIONS</title>
+       <para>
+       There are no options for <command>vfs_acl_xattr</command>.
+       </para>
+</refsect1>
+
+<refsect1>
+       <title>AUTHOR</title>
+
+       <para>The original Samba software and related utilities
+       were created by Andrew Tridgell. Samba is now developed
+       by the Samba Team as an Open Source project similar
+       to the way the Linux kernel is developed.</para>
+</refsect1>
+
+</refentry>
index 13f2cd644643f8db31d4fbaff9f0a371263fb1f7..7f85616c22287502ef25cb2ce06739a9eb946f2c 100644 (file)
@@ -17,7 +17,7 @@
 
        <para>You may wish to disable this option if you have a problem with empty
        workgroups not disappearing from browse lists. Due to the restrictions
-       of the browse protocols these enhancements can cause a empty workgroup
+       of the browse protocols, these enhancements can cause a empty workgroup
        to stay around forever which can be annoying.</para>
 
        <para>In general you should leave this option enabled as it makes
index e3a0ed7b4c5035b44052decd338cfc8f2a58fec4..15ad0ad07394e4c99baab0f40451209768ab4316 100644 (file)
@@ -12,7 +12,7 @@
        <para>
        When strict locking is set to Auto (the default), the server performs file lock checks only on non-oplocked files.
        As most Windows redirectors perform file locking checks locally on oplocked files this is a good trade off for
-       inproved performance.
+       improved performance.
        </para>
 
        <para>
index f23968b5015a5cdd205ea1a50fe40de93f25903c..a6bf0c546f5cabd89d347dafd888c10f1c1a2f47 100644 (file)
@@ -6,7 +6,7 @@
 <description>
        <para>
        This option allows you to setup <citerefentry><refentrytitle>nmbd</refentrytitle>
-       <manvolnum>8</manvolnum></citerefentry>to periodically announce itself 
+       <manvolnum>8</manvolnum></citerefentry> to periodically announce itself 
        to arbitrary IP addresses with an arbitrary workgroup name.
        </para>
 
@@ -23,7 +23,7 @@
 </programlisting>
        the above line would cause <command moreinfo="none">nmbd</command> to announce itself 
        to the two given IP addresses using the given workgroup names. If you leave out the 
-       workgroup name then the one given in the <smbconfoption name="workgroup"/> parameter 
+       workgroup name, then the one given in the <smbconfoption name="workgroup"/> parameter 
        is used instead.
        </para>
 
index 738f3a11bad1fa971412229682e92e255a746c5a..a3ae5183b090b8f74350ac323d1f439dad02489a 100644 (file)
@@ -8,7 +8,7 @@
        to be accessed by non-authenticated users or not. It is the equivalent
        of allowing people who can create a share the option of setting
        <parameter moreinfo="none">guest ok = yes</parameter> in a share
-       definition. Due to the security sensitive nature of this the default
+       definition. Due to its security sensitive nature, the default
        is set to off.</para>
 
 </description>
index bacc2e9530eafbbbdb2b792de7e05aac456c3679..6c1822a16583aa86a1c648df79c8ea748d7ab10c 100644 (file)
@@ -6,8 +6,8 @@
 <description>
        <para>This parameter specifies a list of absolute pathnames
        the root of which are allowed to be exported by user defined share definitions.
-       If the pathname exported doesn't start with one of the strings in this
-       list the user defined share will not be allowed. This allows the Samba
+       If the pathname to be exported doesn't start with one of the strings in this
+       list, the user defined share will not be allowed. This allows the Samba
        administrator to restrict the directories on the system that can be
        exported by user defined shares.
        </para>
index efe2e81d22c6268bec7cc0949db9c5085a74cdc0..9593a6c7e4a2faeb848d6e3254aae014a85db665 100644 (file)
@@ -5,7 +5,7 @@
                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
        <para>User defined shares only have limited possible parameters
-       such as path, guest ok etc. This parameter allows usershares to
+       such as path, guest ok, etc. This parameter allows usershares to
        "cloned" from an existing share. If "usershare template share"
        is set to the name of an existing share, then all usershares
        created have their defaults set from the parameters set on this
index 99e85568110cc0020f72f944763f15ae01f40ec2..4d9b7abfccc406c77d6078150a941132e5a95acc 100644 (file)
@@ -29,7 +29,7 @@
     <para>If this parameter is enabled for a printer, then any attempt
     to open the printer with the PRINTER_ACCESS_ADMINISTER right is mapped
     to PRINTER_ACCESS_USE instead.  Thus allowing the OpenPrinterEx()
-    call to succeed.  <emphasis>This parameter MUST not be able enabled
+    call to succeed.  <emphasis>This parameter MUST not be enabled
     on a print share which has valid print driver installed on the Samba 
        server.</emphasis></para>
 </description>
index 69162617596cb4b5737fd21d8f046691f50cc062..79b6da7afa5edaaaf5ec0520a4d039867cec550c 100644 (file)
@@ -21,7 +21,7 @@
     and allows the open. If the user doesn't have permission to delete the file this will only be
     discovered at close time, which is too late for the Windows user tools to display an error message
     to the user. The symptom of this is files that appear to have been deleted "magically" re-appearing
-    on a Windows explorer refersh. This is an extremely advanced protocol option which should not
+    on a Windows explorer refresh. This is an extremely advanced protocol option which should not
     need to be changed. This parameter was introduced in its final form in 3.0.21, an earlier version
     with slightly different semantics was introduced in 3.0.20. That older version is not documented here.
     </para>
index cd4f30fb8d62bda31079ec8ee9479e1cb28dd2e5..bb56b5ad0bd1ead56710e00a51f6b8696fd30cb6 100644 (file)
@@ -5,7 +5,7 @@
                  xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
     <para>Hosts running the "Advanced Server for Unix (ASU)" product 
-    require some special accomodations such as creating a builting [ADMIN$] 
+    require some special accomodations such as creating a builtin [ADMIN$] 
     share that only supports IPC connections.  The has been the default
     behavior in smbd for many years.  However, certain Microsoft applications
     such as the Print Migrator tool require that the remote server support
index 5266fef6a24ee50529baf298c061e9d839592cc5..967eacf85bb199bff4011b88a71589f44c1b307d 100644 (file)
@@ -11,7 +11,7 @@
     password hashes (e.g. Windows NT/2000, Samba, etc... but not 
     Windows 95/98) will be able to be connected from the Samba client.</para>
 
-    <para>The LANMAN encrypted response is easily broken, due to it's
+    <para>The LANMAN encrypted response is easily broken, due to its
     case-insensitive nature, and the choice of algorithm.  Clients
     without Windows 95/98 servers are advised to disable
     this option.  </para>
index bf37cbb8746476d53434ce0f7270e47829b716df..c657e057118f66d5139d35ca489e6eadb3653e8c 100644 (file)
@@ -4,8 +4,7 @@
                  basic="1"
                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
-    <para>This controls whether the client offers or requires
-    the server it talks to to use SMB signing. Possible values 
+    <para>This controls whether the client is allowed or required to use SMB signing. Possible values 
     are <emphasis>auto</emphasis>, <emphasis>mandatory</emphasis> 
     and <emphasis>disabled</emphasis>. 
     </para>
index 341952205f6940809a41f84cd703c7e7bcb40155..4e68c5e03aa16b5c5529343c475f7f75e2cf7911 100644 (file)
@@ -12,7 +12,7 @@
     Windows 95/98 or the MS DOS network client) will be able to
     connect to the Samba host.</para>
 
-    <para>The LANMAN encrypted response is easily broken, due to it's
+    <para>The LANMAN encrypted response is easily broken, due to its
     case-insensitive nature, and the choice of algorithm.  Servers
     without Windows 95/98/ME or MS DOS clients are advised to disable
     this option.  </para>
index 0da247d27d5d0d4514569197bd9a0ba78a0811bf..0e92af9ebaeaff76dda2deb34c4e4066357dcc86 100644 (file)
@@ -7,7 +7,7 @@
     <para>By specifying the name of another SMB server 
     or Active Directory domain controller with this option, 
     and using <command moreinfo="none">security = [ads|domain|server]</command> 
-    it is possible to get Samba to 
+    it is possible to get Samba
     to do all its username/password validation using a specific remote server.</para>
 
     <para>This option sets the name or IP address of the password server to use. 
index 3ad5175712e7e1bf126e684568a9b14dce7ef4cd..514ea54e0ff65231255a54ad0c8abc1a26941fed 100644 (file)
@@ -47,7 +47,7 @@
     want to mainly setup shares without a password (guest shares). This 
     is commonly used for a shared printer server. It is more difficult 
     to setup guest shares with <command moreinfo="none">security = user</command>, see 
-    the <smbconfoption name="map to guest"/>parameter for details.</para>
+    the <smbconfoption name="map to guest"/> parameter for details.</para>
                
     <para>It is possible to use <command moreinfo="none">smbd</command> in a <emphasis>
     hybrid mode</emphasis> where it is offers both user and share 
@@ -58,7 +58,7 @@
 
     <para><anchor id="SECURITYEQUALSSHARE"/><emphasis>SECURITY = SHARE</emphasis></para> 
                
-    <para>When clients connect to a share level security server they 
+    <para>When clients connect to a share level security server, they 
     need not log onto the server with a valid username and password before 
     attempting to connect to a shared resource (although modern clients 
     such as Windows 95/98 and Windows NT will send a logon request with 
        </para></note>
 
        <note><para>From the client's point of 
-    view <command moreinfo="none">security = server</command> is the
+    view, <command moreinfo="none">security = server</command> is the
     same as <command moreinfo="none">security = user</command>.  It
     only affects how the server deals  with the authentication, it does
        not in any way affect what the  client sees.</para></note>
index 6317448fb62ecb89f353dfa836004c6ee95d81da..655463576f3540a45886d87c8e21f6457ce66fb6 100644 (file)
@@ -13,7 +13,7 @@
        </para>
 
     <para>
-       Please note that with this set to <literal>no</literal> you will have to apply the WindowsXP
+       Please note that with this set to <literal>no</literal>, you will have to apply the WindowsXP
        <filename>WinXP_SignOrSeal.reg</filename> registry patch found in the docs/registry subdirectory of the Samba distribution tarball.
        </para>
 </description>
index f2f5629586150f8e95d5748974c267b226c9d599..ea21a2c6f64d487b0ae9261d42a64c8f62f44ccd 100644 (file)
@@ -5,8 +5,7 @@
                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
 
-    <para>This controls whether the server offers or requires
-    the client it talks to to use SMB signing. Possible values 
+    <para>This controls whether the client is allowed or required to use SMB signing. Possible values 
     are <emphasis>auto</emphasis>, <emphasis>mandatory</emphasis> 
     and <emphasis>disabled</emphasis>. 
     </para>
index eb91ce51fa3ce389445ca5064c5bea2be8465750..d556166953697a54d384a9c50430d81a61367ed0 100644 (file)
@@ -16,8 +16,7 @@
     and MacOS/X clients. Windows clients do not support this feature.
     </para>
 
-    <para>This controls whether the server offers or requires
-    the client it talks to to use SMB encryption. Possible values 
+    <para>This controls whether the remote client is allowed or required to use SMB encryption. Possible values 
     are <emphasis>auto</emphasis>, <emphasis>mandatory</emphasis> 
     and <emphasis>disabled</emphasis>. This may be set on a per-share
     basis, but clients may chose to encrypt the entire session, not
index da493665cf2333448652ba0de77ef86ee7287084..eb54ed9bab6592e8a35b7d1bc9d62fc9ff7eda37 100644 (file)
@@ -9,7 +9,7 @@
        This boolean parameter allows a user logging on with a plaintext password to have their encrypted (hashed)
        password in the smbpasswd file to be updated automatically as they log on. This option allows a site to
        migrate from plaintext password authentication (users authenticate with plaintext password over the
-       wire, and are checked against a UNIX account atabase) to encrypted password authentication (the SMB
+       wire, and are checked against a UNIX account database) to encrypted password authentication (the SMB
        challenge/response authentication mechanism) without forcing all users to re-enter their passwords via
        smbpasswd at the time the change is made. This is a convenience option to allow the change over to encrypted
        passwords to be made over a longer period.  Once all users have encrypted representations of their passwords
@@ -24,7 +24,7 @@
        </para>
 
     <para>
-       Note that even when this parameter is set a user authenticating to <command moreinfo="none">smbd</command>
+       Note that even when this parameter is set, a user authenticating to <command moreinfo="none">smbd</command>
        must still enter a valid password in order to connect correctly, and to update their hashed (smbpasswd)
        passwords.
        </para>
index 2eb7a9477634729ad266037ffd77496d43928e24..118a5b9da7b888b274d365a8a84f291f36b03e5b 100644 (file)
@@ -85,9 +85,11 @@ static SMB_STRUCT_DIR *skel_opendir(vfs_handle_struct *handle,  const char *fnam
        return vfswrap_opendir(NULL,  fname, mask, attr);
 }
 
-static SMB_STRUCT_DIRENT *skel_readdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
+static SMB_STRUCT_DIRENT *skel_readdir(vfs_handle_struct *handle,
+                                      SMB_STRUCT_DIR *dirp,
+                                      SMB_STRUCT_STAT *sbuf)
 {
-       return vfswrap_readdir(NULL,  dirp);
+       return vfswrap_readdir(NULL,  dirp, sbuf);
 }
 
 static void skel_seekdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp, long offset)
@@ -292,7 +294,7 @@ static int skel_chflags(vfs_handle_struct *handle,  const char *path, uint flags
 }
 
 static struct file_id skel_file_id_create(vfs_handle_struct *handle,
-                                         SMB_DEV_T dev, SMB_INO_T inode)
+                                         const SMB_STRUCT_STAT *sbuf)
 {
        struct file_id id_zero;
        ZERO_STRUCT(id_zero);
index 5670965417277617b7c4cf0a8ee416750365b2e5..a95b5ae6cd21192e275f18dbaab802b4c24fcb9a 100644 (file)
@@ -79,9 +79,11 @@ static SMB_STRUCT_DIR *skel_opendir(vfs_handle_struct *handle,  const char *fnam
        return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
 }
 
-static SMB_STRUCT_DIRENT *skel_readdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
+static SMB_STRUCT_DIRENT *skel_readdir(vfs_handle_struct *handle,
+                                      SMB_STRUCT_DIR *dirp,
+                                      SMB_STRUCT_STAT *sbuf)
 {
-       return SMB_VFS_NEXT_READDIR(handle, dirp);
+       return SMB_VFS_NEXT_READDIR(handle, dirp, sbuf);
 }
 
 static void skel_seekdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp, long offset)
@@ -284,9 +286,9 @@ static int skel_chflags(vfs_handle_struct *handle,  const char *path, uint flags
 }
 
 static struct file_id skel_file_id_create(vfs_handle_struct *handle,
-                                         SMB_DEV_T dev, SMB_INO_T inode)
+                                         const SMB_STRUCT_STAT *sbuf)
 {
-       return SMB_VFS_NEXT_FILE_ID_CREATE(handle, dev, inode);
+       return SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf);
 }
 
 static NTSTATUS skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
index 02ae88068380406366af07c4f6f665f668e31a73..1f48697f26f825a729c618165b36f0846de4fd9e 100644 (file)
 #include "lib/tevent/tevent.h"
 #include "lib/async_req/async_req.h"
 #include "lib/async_req/async_sock.h"
+#include "lib/util/tevent_unix.h"
 #include <fcntl.h>
 
 #ifndef TALLOC_FREE
 #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
 #endif
 
-/**
- * Discriminator for async_syscall_state
- */
-enum async_syscall_type {
-       ASYNC_SYSCALL_SEND,
-       ASYNC_SYSCALL_SENDALL,
-       ASYNC_SYSCALL_RECV,
-       ASYNC_SYSCALL_RECVALL,
-       ASYNC_SYSCALL_CONNECT
-};
-
-/**
- * Holder for syscall arguments and the result
- */
-
-struct async_syscall_state {
-       enum async_syscall_type syscall_type;
-       struct tevent_fd *fde;
-
-       union {
-               struct param_send {
-                       int fd;
-                       const void *buffer;
-                       size_t length;
-                       int flags;
-               } param_send;
-               struct param_sendall {
-                       int fd;
-                       const void *buffer;
-                       size_t length;
-                       int flags;
-                       size_t sent;
-               } param_sendall;
-               struct param_recv {
-                       int fd;
-                       void *buffer;
-                       size_t length;
-                       int flags;
-               } param_recv;
-               struct param_recvall {
-                       int fd;
-                       void *buffer;
-                       size_t length;
-                       int flags;
-                       size_t received;
-               } param_recvall;
-               struct param_connect {
-                       /**
-                        * connect needs to be done on a nonblocking
-                        * socket. Keep the old flags around
-                        */
-                       long old_sockflags;
-                       int fd;
-                       const struct sockaddr *address;
-                       socklen_t address_len;
-               } param_connect;
-       } param;
-
-       union {
-               ssize_t result_ssize_t;
-               size_t result_size_t;
-               int result_int;
-       } result;
-       int sys_errno;
-};
-
 /**
  * @brief Map async_req states to unix-style errnos
  * @param[in]  req     The async req to get the state from
@@ -143,470 +78,138 @@ int async_req_simple_recv_errno(struct async_req *req)
        return 0;
 }
 
-/**
- * @brief Create a new async syscall req
- * @param[in] mem_ctx  The memory context to hang the result off
- * @param[in] ev       The event context to work from
- * @param[in] type     Which syscall will this be
- * @param[in] pstate   Where to put the newly created private_data state
- * @retval The new request
- *
- * This is a helper function to prepare a new struct async_req with an
- * associated struct async_syscall_state. The async_syscall_state will be put
- * into the async_req as private_data.
- */
-
-static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx,
-                                          struct tevent_context *ev,
-                                          enum async_syscall_type type,
-                                          struct async_syscall_state **pstate)
-{
-       struct async_req *result;
-       struct async_syscall_state *state;
-
-       if (!async_req_setup(mem_ctx, &result, &state,
-                            struct async_syscall_state)) {
-               return NULL;
-       }
-       state->syscall_type = type;
-
-       result->private_data = state;
-
-       *pstate = state;
+struct async_send_state {
+       int fd;
+       const void *buf;
+       size_t len;
+       int flags;
+       ssize_t sent;
+};
 
-       return result;
-}
+static void async_send_handler(struct tevent_context *ev,
+                              struct tevent_fd *fde,
+                              uint16_t flags, void *private_data);
 
-/**
- * @brief Create a new async syscall req based on a fd
- * @param[in] mem_ctx  The memory context to hang the result off
- * @param[in] ev       The event context to work from
- * @param[in] type     Which syscall will this be
- * @param[in] fd       The file descriptor we work on
- * @param[in] fde_flags TEVENT_FD_READ/WRITE -- what are we interested in?
- * @param[in] fde_cb   The callback function for the file descriptor event
- * @param[in] pstate   Where to put the newly created private_data state
- * @retval The new request
- *
- * This is a helper function to prepare a new struct async_req with an
- * associated struct async_syscall_state and an associated file descriptor
- * event.
- */
-
-static struct async_req *async_fde_syscall_new(
-       TALLOC_CTX *mem_ctx,
-       struct tevent_context *ev,
-       enum async_syscall_type type,
-       int fd,
-       uint16_t fde_flags,
-       void (*fde_cb)(struct tevent_context *ev,
-                      struct tevent_fd *fde, uint16_t flags,
-                      void *priv),
-       struct async_syscall_state **pstate)
+struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx,
+                                  struct tevent_context *ev,
+                                  int fd, const void *buf, size_t len,
+                                  int flags)
 {
-       struct async_req *result;
-       struct async_syscall_state *state;
+       struct tevent_req *result;
+       struct async_send_state *state;
+       struct tevent_fd *fde;
 
-       result = async_syscall_new(mem_ctx, ev, type, &state);
+       result = tevent_req_create(mem_ctx, &state, struct async_send_state);
        if (result == NULL) {
-               return NULL;
+               return result;
        }
+       state->fd = fd;
+       state->buf = buf;
+       state->len = len;
+       state->flags = flags;
 
-       state->fde = tevent_add_fd(ev, state, fd, fde_flags, fde_cb, result);
-       if (state->fde == NULL) {
+       fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, async_send_handler,
+                           result);
+       if (fde == NULL) {
                TALLOC_FREE(result);
                return NULL;
        }
-       *pstate = state;
        return result;
 }
 
-/**
- * Retrieve a ssize_t typed result from an async syscall
- * @param[in] req      The syscall that has just finished
- * @param[out] perrno  Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno)
-{
-       struct async_syscall_state *state = talloc_get_type_abort(
-               req->private_data, struct async_syscall_state);
-
-       *perrno = state->sys_errno;
-       return state->result.result_ssize_t;
-}
-
-/**
- * Retrieve a size_t typed result from an async syscall
- * @param[in] req      The syscall that has just finished
- * @param[out] perrno  Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-size_t async_syscall_result_size_t(struct async_req *req, int *perrno)
-{
-       struct async_syscall_state *state = talloc_get_type_abort(
-               req->private_data, struct async_syscall_state);
-
-       *perrno = state->sys_errno;
-       return state->result.result_size_t;
-}
-
-/**
- * Retrieve a int typed result from an async syscall
- * @param[in] req      The syscall that has just finished
- * @param[out] perrno  Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-int async_syscall_result_int(struct async_req *req, int *perrno)
-{
-       struct async_syscall_state *state = talloc_get_type_abort(
-               req->private_data, struct async_syscall_state);
-
-       *perrno = state->sys_errno;
-       return state->result.result_int;
-}
-
-/**
- * fde event handler for the "send" syscall
- * @param[in] ev       The event context that sent us here
- * @param[in] fde      The file descriptor event associated with the send
- * @param[in] flags    Can only be TEVENT_FD_WRITE here
- * @param[in] priv     private data, "struct async_req *" in this case
- */
-
-static void async_send_callback(struct tevent_context *ev,
-                               struct tevent_fd *fde, uint16_t flags,
-                               void *priv)
+static void async_send_handler(struct tevent_context *ev,
+                              struct tevent_fd *fde,
+                              uint16_t flags, void *private_data)
 {
-       struct async_req *req = talloc_get_type_abort(
-               priv, struct async_req);
-       struct async_syscall_state *state = talloc_get_type_abort(
-               req->private_data, struct async_syscall_state);
-       struct param_send *p = &state->param.param_send;
-
-       if (state->syscall_type != ASYNC_SYSCALL_SEND) {
-               async_req_error(req, EIO);
+       struct tevent_req *req = talloc_get_type_abort(
+               private_data, struct tevent_req);
+       struct async_send_state *state = talloc_get_type_abort(
+               req->private_state, struct async_send_state);
+
+       state->sent = send(state->fd, state->buf, state->len, state->flags);
+       if (state->sent == -1) {
+               tevent_req_error(req, errno);
                return;
        }
-
-       state->result.result_ssize_t = send(p->fd, p->buffer, p->length,
-                                           p->flags);
-       state->sys_errno = errno;
-
-       TALLOC_FREE(state->fde);
-
-       async_req_done(req);
+       tevent_req_done(req);
 }
 
-/**
- * Async version of send(2)
- * @param[in] mem_ctx  The memory context to hang the result off
- * @param[in] ev       The event context to work from
- * @param[in] fd       The socket to send to
- * @param[in] buffer   The buffer to send
- * @param[in] length   How many bytes to send
- * @param[in] flags    flags passed to send(2)
- *
- * This function is a direct counterpart of send(2)
- */
-
-struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-                            int fd, const void *buffer, size_t length,
-                            int flags)
+ssize_t async_send_recv(struct tevent_req *req, int *perrno)
 {
-       struct async_req *result;
-       struct async_syscall_state *state;
+       struct async_send_state *state = talloc_get_type_abort(
+               req->private_state, struct async_send_state);
 
-       result = async_fde_syscall_new(
-               mem_ctx, ev, ASYNC_SYSCALL_SEND,
-               fd, TEVENT_FD_WRITE, async_send_callback,
-               &state);
-       if (result == NULL) {
-               return NULL;
+       if (tevent_req_is_unix_error(req, perrno)) {
+               return -1;
        }
-
-       state->param.param_send.fd = fd;
-       state->param.param_send.buffer = buffer;
-       state->param.param_send.length = length;
-       state->param.param_send.flags = flags;
-
-       return result;
+       return state->sent;
 }
 
-/**
- * fde event handler for the "sendall" syscall group
- * @param[in] ev       The event context that sent us here
- * @param[in] fde      The file descriptor event associated with the send
- * @param[in] flags    Can only be TEVENT_FD_WRITE here
- * @param[in] priv     private data, "struct async_req *" in this case
- */
-
-static void async_sendall_callback(struct tevent_context *ev,
-                                  struct tevent_fd *fde, uint16_t flags,
-                                  void *priv)
-{
-       struct async_req *req = talloc_get_type_abort(
-               priv, struct async_req);
-       struct async_syscall_state *state = talloc_get_type_abort(
-               req->private_data, struct async_syscall_state);
-       struct param_sendall *p = &state->param.param_sendall;
-
-       if (state->syscall_type != ASYNC_SYSCALL_SENDALL) {
-               async_req_error(req, EIO);
-               return;
-       }
-
-       state->result.result_ssize_t = send(p->fd,
-                                           (const char *)p->buffer + p->sent,
-                                           p->length - p->sent, p->flags);
-       state->sys_errno = errno;
-
-       if (state->result.result_ssize_t == -1) {
-               async_req_error(req, state->sys_errno);
-               return;
-       }
-
-       if (state->result.result_ssize_t == 0) {
-               async_req_error(req, EOF);
-               return;
-       }
-
-       p->sent += state->result.result_ssize_t;
-       if (p->sent > p->length) {
-               async_req_error(req, EIO);
-               return;
-       }
+struct async_recv_state {
+       int fd;
+       void *buf;
+       size_t len;
+       int flags;
+       ssize_t received;
+};
 
-       if (p->sent == p->length) {
-               TALLOC_FREE(state->fde);
-               async_req_done(req);
-       }
-}
+static void async_recv_handler(struct tevent_context *ev,
+                              struct tevent_fd *fde,
+                              uint16_t flags, void *private_data);
 
-/**
- * @brief Send all bytes to a socket
- * @param[in] mem_ctx  The memory context to hang the result off
- * @param[in] ev       The event context to work from
- * @param[in] fd       The socket to send to
- * @param[in] buffer   The buffer to send
- * @param[in] length   How many bytes to send
- * @param[in] flags    flags passed to send(2)
- *
- * async_sendall calls send(2) as long as it is necessary to send all of the
- * "length" bytes
- */
-
-struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-                              int fd, const void *buffer, size_t length,
-                              int flags)
+struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx,
+                                  struct tevent_context *ev,
+                                  int fd, void *buf, size_t len, int flags)
 {
-       struct async_req *result;
-       struct async_syscall_state *state;
+       struct tevent_req *result;
+       struct async_recv_state *state;
+       struct tevent_fd *fde;
 
-       result = async_fde_syscall_new(
-               mem_ctx, ev, ASYNC_SYSCALL_SENDALL,
-               fd, TEVENT_FD_WRITE, async_sendall_callback,
-               &state);
+       result = tevent_req_create(mem_ctx, &state, struct async_recv_state);
        if (result == NULL) {
-               return NULL;
-       }
-
-       state->param.param_sendall.fd = fd;
-       state->param.param_sendall.buffer = buffer;
-       state->param.param_sendall.length = length;
-       state->param.param_sendall.flags = flags;
-       state->param.param_sendall.sent = 0;
-
-       return result;
-}
-
-ssize_t sendall_recv(struct async_req *req, int *perr)
-{
-       struct async_syscall_state *state = talloc_get_type_abort(
-               req->private_data, struct async_syscall_state);
-       int err;
-
-       err = async_req_simple_recv_errno(req);
-
-       if (err != 0) {
-               *perr = err;
-               return -1;
-       }
-
-       return state->result.result_ssize_t;
-}
-
-/**
- * fde event handler for the "recv" syscall
- * @param[in] ev       The event context that sent us here
- * @param[in] fde      The file descriptor event associated with the recv
- * @param[in] flags    Can only be TEVENT_FD_READ here
- * @param[in] priv     private data, "struct async_req *" in this case
- */
-
-static void async_recv_callback(struct tevent_context *ev,
-                               struct tevent_fd *fde, uint16_t flags,
-                               void *priv)
-{
-       struct async_req *req = talloc_get_type_abort(
-               priv, struct async_req);
-       struct async_syscall_state *state = talloc_get_type_abort(
-               req->private_data, struct async_syscall_state);
-       struct param_recv *p = &state->param.param_recv;
-
-       if (state->syscall_type != ASYNC_SYSCALL_RECV) {
-               async_req_error(req, EIO);
-               return;
+               return result;
        }
+       state->fd = fd;
+       state->buf = buf;
+       state->len = len;
+       state->flags = flags;
 
-       state->result.result_ssize_t = recv(p->fd, p->buffer, p->length,
-                                           p->flags);
-       state->sys_errno = errno;
-
-       TALLOC_FREE(state->fde);
-
-       async_req_done(req);
-}
-
-/**
- * Async version of recv(2)
- * @param[in] mem_ctx  The memory context to hang the result off
- * @param[in] ev       The event context to work from
- * @param[in] fd       The socket to recv from
- * @param[in] buffer   The buffer to recv into
- * @param[in] length   How many bytes to recv
- * @param[in] flags    flags passed to recv(2)
- *
- * This function is a direct counterpart of recv(2)
- */
-
-struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-                            int fd, void *buffer, size_t length,
-                            int flags)
-{
-       struct async_req *result;
-       struct async_syscall_state *state;
-
-       result = async_fde_syscall_new(
-               mem_ctx, ev, ASYNC_SYSCALL_RECV,
-               fd, TEVENT_FD_READ, async_recv_callback,
-               &state);
-
-       if (result == NULL) {
+       fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, async_recv_handler,
+                           result);
+       if (fde == NULL) {
+               TALLOC_FREE(result);
                return NULL;
        }
-
-       state->param.param_recv.fd = fd;
-       state->param.param_recv.buffer = buffer;
-       state->param.param_recv.length = length;
-       state->param.param_recv.flags = flags;
-
        return result;
 }
 
-/**
- * fde event handler for the "recvall" syscall group
- * @param[in] ev       The event context that sent us here
- * @param[in] fde      The file descriptor event associated with the recv
- * @param[in] flags    Can only be TEVENT_FD_READ here
- * @param[in] priv     private data, "struct async_req *" in this case
- */
-
-static void async_recvall_callback(struct tevent_context *ev,
-                                  struct tevent_fd *fde, uint16_t flags,
-                                  void *priv)
+static void async_recv_handler(struct tevent_context *ev,
+                              struct tevent_fd *fde,
+                              uint16_t flags, void *private_data)
 {
-       struct async_req *req = talloc_get_type_abort(
-               priv, struct async_req);
-       struct async_syscall_state *state = talloc_get_type_abort(
-               req->private_data, struct async_syscall_state);
-       struct param_recvall *p = &state->param.param_recvall;
-
-       if (state->syscall_type != ASYNC_SYSCALL_RECVALL) {
-               async_req_error(req, EIO);
-               return;
-       }
-
-       state->result.result_ssize_t = recv(p->fd,
-                                           (char *)p->buffer + p->received,
-                                           p->length - p->received, p->flags);
-       state->sys_errno = errno;
-
-       if (state->result.result_ssize_t == -1) {
-               async_req_error(req, state->sys_errno);
+       struct tevent_req *req = talloc_get_type_abort(
+               private_data, struct tevent_req);
+       struct async_recv_state *state = talloc_get_type_abort(
+               req->private_state, struct async_recv_state);
+
+       state->received = recv(state->fd, state->buf, state->len,
+                              state->flags);
+       if (state->received == -1) {
+               tevent_req_error(req, errno);
                return;
        }
-
-       if (state->result.result_ssize_t == 0) {
-               async_req_error(req, EIO);
-               return;
-       }
-
-       p->received += state->result.result_ssize_t;
-       if (p->received > p->length) {
-               async_req_error(req, EIO);
-               return;
-       }
-
-       if (p->received == p->length) {
-               TALLOC_FREE(state->fde);
-               async_req_done(req);
-       }
-}
-
-/**
- * Receive a specified number of bytes from a socket
- * @param[in] mem_ctx  The memory context to hang the result off
- * @param[in] ev       The event context to work from
- * @param[in] fd       The socket to recv from
- * @param[in] buffer   The buffer to recv into
- * @param[in] length   How many bytes to recv
- * @param[in] flags    flags passed to recv(2)
- *
- * async_recvall will call recv(2) until "length" bytes are received
- */
-
-struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-                              int fd, void *buffer, size_t length,
-                              int flags)
-{
-       struct async_req *result;
-       struct async_syscall_state *state;
-
-       result = async_fde_syscall_new(
-               mem_ctx, ev, ASYNC_SYSCALL_RECVALL,
-               fd, TEVENT_FD_READ, async_recvall_callback,
-               &state);
-       if (result == NULL) {
-               return NULL;
-       }
-
-       state->param.param_recvall.fd = fd;
-       state->param.param_recvall.buffer = buffer;
-       state->param.param_recvall.length = length;
-       state->param.param_recvall.flags = flags;
-       state->param.param_recvall.received = 0;
-
-       return result;
+       tevent_req_done(req);
 }
 
-ssize_t recvall_recv(struct async_req *req, int *perr)
+ssize_t async_recv_recv(struct tevent_req *req, int *perrno)
 {
-       struct async_syscall_state *state = talloc_get_type_abort(
-               req->private_data, struct async_syscall_state);
-       int err;
+       struct async_recv_state *state = talloc_get_type_abort(
+               req->private_state, struct async_recv_state);
 
-       err = async_req_simple_recv_errno(req);
-
-       if (err != 0) {
-               *perr = err;
+       if (tevent_req_is_unix_error(req, perrno)) {
                return -1;
        }
-
-       return state->result.result_ssize_t;
+       return state->received;
 }
 
 struct async_connect_state {
@@ -633,17 +236,18 @@ static void async_connect_connected(struct tevent_context *ev,
  * connect in an async state. This will be reset when the request is finished.
  */
 
-struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
-                                    struct tevent_context *ev,
-                                    int fd, const struct sockaddr *address,
-                                    socklen_t address_len)
+struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx,
+                                     struct tevent_context *ev,
+                                     int fd, const struct sockaddr *address,
+                                     socklen_t address_len)
 {
-       struct async_req *result;
+       struct tevent_req *result;
        struct async_connect_state *state;
        struct tevent_fd *fde;
 
-       if (!async_req_setup(mem_ctx, &result, &state,
-                            struct async_connect_state)) {
+       result = tevent_req_create(
+               mem_ctx, &state, struct async_connect_state);
+       if (result == NULL) {
                return NULL;
        }
 
@@ -664,8 +268,8 @@ struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
 
        state->result = connect(fd, address, address_len);
        if (state->result == 0) {
-               state->sys_errno = 0;
-               goto post_status;
+               tevent_req_done(result);
+               goto done;
        }
 
        /**
@@ -680,6 +284,7 @@ struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
              errno == EISCONN ||
 #endif
              errno == EAGAIN || errno == EINTR)) {
+               state->sys_errno = errno;
                goto post_errno;
        }
 
@@ -687,21 +292,15 @@ struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
                           async_connect_connected, result);
        if (fde == NULL) {
                state->sys_errno = ENOMEM;
-               goto post_status;
+               goto post_errno;
        }
        return result;
 
  post_errno:
-       state->sys_errno = errno;
post_status:
+       tevent_req_error(result, state->sys_errno);
done:
        fcntl(fd, F_SETFL, state->old_sockflags);
-       if (!async_post_error(result, ev, state->sys_errno)) {
-               goto fail;
-       }
-       return result;
- fail:
-       TALLOC_FREE(result);
-       return NULL;
+       return tevent_req_post(result, ev);
 }
 
 /**
@@ -716,10 +315,10 @@ static void async_connect_connected(struct tevent_context *ev,
                                    struct tevent_fd *fde, uint16_t flags,
                                    void *priv)
 {
-       struct async_req *req = talloc_get_type_abort(
-               priv, struct async_req);
+       struct tevent_req *req = talloc_get_type_abort(
+               priv, struct tevent_req);
        struct async_connect_state *state = talloc_get_type_abort(
-               req->private_data, struct async_connect_state);
+               req->private_state, struct async_connect_state);
 
        TALLOC_FREE(fde);
 
@@ -743,27 +342,27 @@ static void async_connect_connected(struct tevent_context *ev,
                DEBUG(10, ("connect returned %s\n", strerror(errno)));
 
                fcntl(state->fd, F_SETFL, state->old_sockflags);
-               async_req_error(req, state->sys_errno);
+               tevent_req_error(req, state->sys_errno);
                return;
        }
 
        state->sys_errno = 0;
-       async_req_done(req);
+       tevent_req_done(req);
 }
 
-int async_connect_recv(struct async_req *req, int *perrno)
+int async_connect_recv(struct tevent_req *req, int *perrno)
 {
        struct async_connect_state *state = talloc_get_type_abort(
-               req->private_data, struct async_connect_state);
+               req->private_state, struct async_connect_state);
        int err;
 
        fcntl(state->fd, F_SETFL, state->old_sockflags);
 
-
-       if (async_req_is_errno(req, &err)) {
+       if (tevent_req_is_unix_error(req, &err)) {
                *perrno = err;
                return -1;
        }
+
        if (state->sys_errno == 0) {
                return 0;
        }
@@ -771,3 +370,226 @@ int async_connect_recv(struct async_req *req, int *perrno)
        *perrno = state->sys_errno;
        return -1;
 }
+
+struct writev_state {
+       struct tevent_context *ev;
+       int fd;
+       struct iovec *iov;
+       int count;
+       size_t total_size;
+};
+
+static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde,
+                          uint16_t flags, void *private_data);
+
+struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+                              int fd, struct iovec *iov, int count)
+{
+       struct tevent_req *result;
+       struct writev_state *state;
+       struct tevent_fd *fde;
+
+       result = tevent_req_create(mem_ctx, &state, struct writev_state);
+       if (result == NULL) {
+               return NULL;
+       }
+       state->ev = ev;
+       state->fd = fd;
+       state->total_size = 0;
+       state->count = count;
+       state->iov = (struct iovec *)talloc_memdup(
+               state, iov, sizeof(struct iovec) * count);
+       if (state->iov == NULL) {
+               goto fail;
+       }
+
+       fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, writev_handler,
+                           result);
+       if (fde == NULL) {
+               goto fail;
+       }
+       return result;
+
+ fail:
+       TALLOC_FREE(result);
+       return NULL;
+}
+
+static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde,
+                          uint16_t flags, void *private_data)
+{
+       struct tevent_req *req = talloc_get_type_abort(
+               private_data, struct tevent_req);
+       struct writev_state *state = talloc_get_type_abort(
+               req->private_state, struct writev_state);
+       size_t to_write, written;
+       int i;
+
+       to_write = 0;
+
+       for (i=0; i<state->count; i++) {
+               to_write += state->iov[i].iov_len;
+       }
+
+       written = sys_writev(state->fd, state->iov, state->count);
+       if (written == -1) {
+               tevent_req_error(req, errno);
+               return;
+       }
+       if (written == 0) {
+               tevent_req_error(req, EPIPE);
+               return;
+       }
+       state->total_size += written;
+
+       if (written == to_write) {
+               tevent_req_done(req);
+               return;
+       }
+
+       /*
+        * We've written less than we were asked to, drop stuff from
+        * state->iov.
+        */
+
+       while (written > 0) {
+               if (written < state->iov[0].iov_len) {
+                       state->iov[0].iov_base =
+                               (char *)state->iov[0].iov_base + written;
+                       state->iov[0].iov_len -= written;
+                       break;
+               }
+               written = state->iov[0].iov_len;
+               state->iov += 1;
+               state->count -= 1;
+       }
+}
+
+ssize_t writev_recv(struct tevent_req *req, int *perrno)
+{
+       struct writev_state *state = talloc_get_type_abort(
+               req->private_state, struct writev_state);
+
+       if (tevent_req_is_unix_error(req, perrno)) {
+               return -1;
+       }
+       return state->total_size;
+}
+
+struct read_packet_state {
+       int fd;
+       uint8_t *buf;
+       size_t nread;
+       ssize_t (*more)(uint8_t *buf, size_t buflen, void *private_data);
+       void *private_data;
+};
+
+static void read_packet_handler(struct tevent_context *ev,
+                               struct tevent_fd *fde,
+                               uint16_t flags, void *private_data);
+
+struct tevent_req *read_packet_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   int fd, size_t initial,
+                                   ssize_t (*more)(uint8_t *buf,
+                                                   size_t buflen,
+                                                   void *private_data),
+                                   void *private_data)
+{
+       struct tevent_req *result;
+       struct read_packet_state *state;
+       struct tevent_fd *fde;
+
+       result = tevent_req_create(mem_ctx, &state, struct read_packet_state);
+       if (result == NULL) {
+               return NULL;
+       }
+       state->fd = fd;
+       state->nread = 0;
+       state->more = more;
+       state->private_data = private_data;
+
+       state->buf = talloc_array(state, uint8_t, initial);
+       if (state->buf == NULL) {
+               goto fail;
+       }
+
+       fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, read_packet_handler,
+                           result);
+       if (fde == NULL) {
+               goto fail;
+       }
+       return result;
+ fail:
+       TALLOC_FREE(result);
+       return NULL;
+}
+
+static void read_packet_handler(struct tevent_context *ev,
+                               struct tevent_fd *fde,
+                               uint16_t flags, void *private_data)
+{
+       struct tevent_req *req = talloc_get_type_abort(
+               private_data, struct tevent_req);
+       struct read_packet_state *state = talloc_get_type_abort(
+               req->private_state, struct read_packet_state);
+       size_t total = talloc_get_size(state->buf);
+       ssize_t nread, more;
+       uint8_t *tmp;
+
+       nread = read(state->fd, state->buf+state->nread, total-state->nread);
+       if (nread == -1) {
+               tevent_req_error(req, errno);
+               return;
+       }
+       if (nread == 0) {
+               tevent_req_error(req, EPIPE);
+               return;
+       }
+
+       state->nread += nread;
+       if (state->nread < total) {
+               /* Come back later */
+               return;
+       }
+
+       /*
+        * We got what was initially requested. See if "more" asks for -- more.
+        */
+       if (state->more == NULL) {
+               /* Nobody to ask, this is a async read_data */
+               tevent_req_done(req);
+               return;
+       }
+
+       more = state->more(state->buf, total, state->private_data);
+       if (more == -1) {
+               /* We got an invalid packet, tell the caller */
+               tevent_req_error(req, EIO);
+               return;
+       }
+       if (more == 0) {
+               /* We're done, full packet received */
+               tevent_req_done(req);
+               return;
+       }
+
+       tmp = TALLOC_REALLOC_ARRAY(state, state->buf, uint8_t, total+more);
+       if (tevent_req_nomem(tmp, req)) {
+               return;
+       }
+       state->buf = tmp;
+}
+
+ssize_t read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+                        uint8_t **pbuf, int *perrno)
+{
+       struct read_packet_state *state = talloc_get_type_abort(
+               req->private_state, struct read_packet_state);
+
+       if (tevent_req_is_unix_error(req, perrno)) {
+               return -1;
+       }
+       *pbuf = talloc_move(mem_ctx, &state->buf);
+       return talloc_get_size(*pbuf);
+}
index c8739e9ed6b3c383388065b674aa6caae7e13df7..e001709d2783b4f5696875e208bab330bc55fb9f 100644 (file)
 bool async_req_is_errno(struct async_req *req, int *err);
 int async_req_simple_recv_errno(struct async_req *req);
 
-ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno);
-size_t async_syscall_result_size_t(struct async_req *req, int *perrno);
-int async_syscall_result_int(struct async_req *req, int *perrno);
-
-struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-                            int fd, const void *buffer, size_t length,
-                            int flags);
-struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-                            int fd, void *buffer, size_t length,
-                            int flags);
-struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
-                                    struct tevent_context *ev,
-                                    int fd, const struct sockaddr *address,
-                                    socklen_t address_len);
-int async_connect_recv(struct async_req *req, int *perrno);
-
-struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-                              int fd, const void *buffer, size_t length,
-                              int flags);
-ssize_t sendall_recv(struct async_req *req, int *perr);
-
-struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-                              int fd, void *buffer, size_t length,
-                              int flags);
-ssize_t recvall_recv(struct async_req *req, int *perr);
+struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx,
+                                  struct tevent_context *ev,
+                                  int fd, const void *buf, size_t len,
+                                  int flags);
+ssize_t async_send_recv(struct tevent_req *req, int *perrno);
+
+struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx,
+                                  struct tevent_context *ev,
+                                  int fd, void *buf, size_t len, int flags);
+ssize_t async_recv_recv(struct tevent_req *req, int *perrno);
+
+struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx,
+                                     struct tevent_context *ev,
+                                     int fd, const struct sockaddr *address,
+                                     socklen_t address_len);
+int async_connect_recv(struct tevent_req *req, int *perrno);
+
+struct tevent_req *writev_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+                              int fd, struct iovec *iov, int count);
+ssize_t writev_recv(struct tevent_req *req, int *perrno);
+
+struct tevent_req *read_packet_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   int fd, size_t initial,
+                                   ssize_t (*more)(uint8_t *buf,
+                                                   size_t buflen,
+                                                   void *private_data),
+                                   void *private_data);
+ssize_t read_packet_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+                        uint8_t **pbuf, int *perrno);
 
 #endif
index f6f0ec080c2e48ef085635c04c6af7d87c61753d..3a91bb40d2ac44c87b8ff1885d8ca0be22b23f5b 100644 (file)
@@ -84,9 +84,6 @@ int rep_getifaddrs(struct ifaddrs **ifap)
        char buff[8192];
        int fd, i, n;
        struct ifreq *ifr=NULL;
-       struct in_addr ipaddr;
-       struct in_addr nmask;
-       char *iname;
        struct ifaddrs *curif;
        struct ifaddrs *lastif = NULL;
 
@@ -164,9 +161,6 @@ int rep_getifaddrs(struct ifaddrs **ifap)
        char buff[8192];
        int fd, i, n;
        struct ifreq *ifr=NULL;
-       struct in_addr ipaddr;
-       struct in_addr nmask;
-       char *iname;
        struct ifaddrs *curif;
        struct ifaddrs *lastif = NULL;
 
@@ -265,9 +259,6 @@ int rep_getifaddrs(struct ifaddrs **ifap)
        int fd, i;
        struct ifconf ifc;
        struct ifreq *ifr=NULL;
-       struct in_addr ipaddr;
-       struct in_addr nmask;
-       char *iname;
        struct ifaddrs *curif;
        struct ifaddrs *lastif = NULL;
 
index 81bde46219e8e0dcba72230904ed46b95b5e09c7..9529c5e0a53db7b5d3907c626786bddeb4caebd4 100644 (file)
@@ -292,7 +292,7 @@ AC_DEFUN([AC_LIBREPLACE_RUNTIME_LIB_PATH_VAR],
                *linux*)
                        LIB_PATH_VAR=LD_LIBRARY_PATH
                ;;
-               *netbsd*)
+               *bsd*)
                        LIB_PATH_VAR=LD_LIBRARY_PATH
                ;;
                *solaris*)
index 40d20db2d4a4ac7fc3504f8e092cf7a80d47c5d9..f135d175d43dcecfc6a2ec7bc92eb5d805528ce3 100644 (file)
@@ -327,10 +327,12 @@ struct addrinfo {
 #endif
 
 #ifdef SOCKET_WRAPPER
+#ifndef SOCKET_WRAPPER_DISABLE
 #ifndef SOCKET_WRAPPER_NOT_REPLACE
 #define SOCKET_WRAPPER_REPLACE
-#endif
+#endif /* SOCKET_WRAPPER_NOT_REPLACE */
 #include "../socket_wrapper/socket_wrapper.h"
-#endif
+#endif /* SOCKET_WRAPPER_DISABLE */
+#endif /* SOCKET_WRAPPER */
 
 #endif
index bcab0b97cd9afd276ac956dc1441dd35094735aa..f25ccae0d41c9f819bb8256ec3824e904ff41dcd 100644 (file)
@@ -203,10 +203,6 @@ WERROR smbconf_get_share(struct smbconf_ctx *ctx,
                         const char *servicename,
                         struct smbconf_service **service)
 {
-       if (!smbconf_share_exists(ctx, servicename)) {
-               return WERR_NO_SUCH_SERVICE;
-       }
-
        return ctx->ops->get_share(ctx, mem_ctx, servicename, service);
 }
 
@@ -403,3 +399,18 @@ WERROR smbconf_delete_global_includes(struct smbconf_ctx *ctx)
 
        return werr;
 }
+
+WERROR smbconf_transaction_start(struct smbconf_ctx *ctx)
+{
+       return ctx->ops->transaction_start(ctx);
+}
+
+WERROR smbconf_transaction_commit(struct smbconf_ctx *ctx)
+{
+       return ctx->ops->transaction_commit(ctx);
+}
+
+WERROR smbconf_transaction_cancel(struct smbconf_ctx *ctx)
+{
+       return ctx->ops->transaction_cancel(ctx);
+}
index 106fae6431d7f7ab65f4a0edd741888dc2a1e13f..517302ac883acf5cb54a6ca4664159adefdfc8ed 100644 (file)
@@ -94,4 +94,8 @@ WERROR smbconf_set_global_includes(struct smbconf_ctx *ctx,
 WERROR smbconf_delete_includes(struct smbconf_ctx *ctx, const char *service);
 WERROR smbconf_delete_global_includes(struct smbconf_ctx *ctx);
 
+WERROR smbconf_transaction_start(struct smbconf_ctx *ctx);
+WERROR smbconf_transaction_commit(struct smbconf_ctx *ctx);
+WERROR smbconf_transaction_cancel(struct smbconf_ctx *ctx);
+
 #endif /*  _LIBSMBCONF_H_  */
index c9e44181c6e57e1ff7c12daa6b6af55b57a16bed..e6998ad6392241a794167074a4adaefa7d7eacc3 100644 (file)
@@ -68,6 +68,9 @@ struct smbconf_ops {
                               uint32_t num_includes, const char **includes);
        WERROR (*delete_includes)(struct smbconf_ctx *ctx,
                                  const char *service);
+       WERROR (*transaction_start)(struct smbconf_ctx *ctx);
+       WERROR (*transaction_commit)(struct smbconf_ctx *ctx);
+       WERROR (*transaction_cancel)(struct smbconf_ctx *ctx);
 };
 
 struct smbconf_ctx {
index 1df4a9fdb73c0a5dd3ddf65f9d11969d65b335d1..501382cc5fd0416ab50fe61f69ffe7bc9ba69092 100644 (file)
@@ -612,6 +612,20 @@ static WERROR smbconf_txt_delete_includes(struct smbconf_ctx *ctx,
        return WERR_NOT_SUPPORTED;
 }
 
+static WERROR smbconf_txt_transaction_start(struct smbconf_ctx *ctx)
+{
+       return WERR_OK;
+}
+
+static WERROR smbconf_txt_transaction_commit(struct smbconf_ctx *ctx)
+{
+       return WERR_OK;
+}
+
+static WERROR smbconf_txt_transaction_cancel(struct smbconf_ctx *ctx)
+{
+       return WERR_OK;
+}
 
 static struct smbconf_ops smbconf_ops_txt = {
        .init                   = smbconf_txt_init,
@@ -633,6 +647,9 @@ static struct smbconf_ops smbconf_ops_txt = {
        .get_includes           = smbconf_txt_get_includes,
        .set_includes           = smbconf_txt_set_includes,
        .delete_includes        = smbconf_txt_delete_includes,
+       .transaction_start      = smbconf_txt_transaction_start,
+       .transaction_commit     = smbconf_txt_transaction_commit,
+       .transaction_cancel     = smbconf_txt_transaction_cancel,
 };
 
 
index b19e4cea293df769a588db89c71df25529d677ec..e58c8ca7ff3c5b309a164199d5dc457b34686054 100644 (file)
@@ -461,6 +461,10 @@ fail:
 /* reopen all tdb's */
 int tdb_reopen_all(int parent_longlived)
 {
+#if defined(LIBREPLACE_PREAD_NOT_REPLACED) && \
+       defined(LIBREPLACE_PWRITE_NOT_REPLACED)
+       return 0;
+#else
        struct tdb_context *tdb;
 
        for (tdb=tdbs; tdb; tdb = tdb->next) {
@@ -483,6 +487,7 @@ int tdb_reopen_all(int parent_longlived)
                if (tdb_reopen(tdb) != 0)
                        return -1;
        }
+#endif
 
        return 0;
 }
index 29a64ae3b3b822307666ed07dfaf35950171f7ab..c316823a715c42928d95288591b372b6b72ecf63 100644 (file)
@@ -27,7 +27,7 @@ AC_SUBST(TEVENT_LIBS)
 TEVENT_CFLAGS="-I$teventdir"
 
 TEVENT_OBJ="tevent.o tevent_fd.o tevent_timed.o tevent_signal.o tevent_debug.o tevent_util.o"
-TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o"
+TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o tevent_queue.o"
 TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o"
 
 AC_CHECK_HEADERS(sys/epoll.h)
index 16fac7327f05b73db3e587b69e924456457b16d3..8c119ffb8ed032fcdaa1a716d38148fb526a6c92 100644 (file)
@@ -31,6 +31,7 @@
 #include <stdint.h>
 #include <talloc.h>
 #include <sys/time.h>
+#include <stdbool.h>
 
 struct tevent_context;
 struct tevent_ops;
@@ -210,6 +211,15 @@ struct tevent_req {
         */
        void *private_state;
 
+       /**
+        * @brief A function to overwrite the default print function
+        *
+        * The implementation doing the work may want to imeplement a
+        * custom function to print the text representation of the async
+        * request.
+        */
+       char *(*private_print)(struct tevent_req *req, TALLOC_CTX *mem_ctx);
+
        /**
         * @brief Internal state of the request
         *
@@ -266,6 +276,8 @@ struct tevent_req {
        } internal;
 };
 
+char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx);
+
 char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req);
 
 struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
@@ -295,6 +307,9 @@ struct tevent_req *tevent_req_post(struct tevent_req *req,
 
 bool tevent_req_is_in_progress(struct tevent_req *req);
 
+bool tevent_req_poll(struct tevent_req *req,
+                    struct tevent_context *ev);
+
 bool tevent_req_is_error(struct tevent_req *req,
                         enum tevent_req_state *state,
                         uint64_t *error);
@@ -323,6 +338,28 @@ struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs,
 
 struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs);
 
+struct tevent_queue;
+
+struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx,
+                                         const char *name,
+                                         const char *location);
+
+#define tevent_queue_create(_mem_ctx, _name) \
+       _tevent_queue_create((_mem_ctx), (_name), __location__)
+
+typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req,
+                                         void *private_data);
+bool tevent_queue_add(struct tevent_queue *queue,
+                     struct tevent_context *ev,
+                     struct tevent_req *req,
+                     tevent_queue_trigger_fn_t trigger,
+                     void *private_data);
+bool tevent_queue_start(struct tevent_queue *queue,
+                       struct tevent_context *ev);
+void tevent_queue_stop(struct tevent_queue *queue);
+
+size_t tevent_queue_length(struct tevent_queue *queue);
+
 #ifdef TEVENT_COMPAT_DEFINES
 
 #define event_context  tevent_context
diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c
new file mode 100644 (file)
index 0000000..6c8fbe4
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+   Unix SMB/CIFS implementation.
+   Infrastructure for async requests
+   Copyright (C) Volker Lendecke 2008
+   Copyright (C) Stefan Metzmacher 2009
+
+     ** NOTE! The following LGPL license applies to the tevent
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+#include "tevent_util.h"
+
+struct tevent_queue_entry {
+       struct tevent_queue_entry *prev, *next;
+       struct tevent_queue *queue;
+
+       bool triggered;
+
+       struct tevent_req *req;
+
+       tevent_queue_trigger_fn_t trigger;
+       void *private_data;
+};
+
+struct tevent_queue {
+       const char *name;
+       const char *location;
+
+       bool running;
+       struct tevent_timer *timer;
+
+       size_t length;
+       struct tevent_queue_entry *list;
+};
+
+static int tevent_queue_entry_destructor(struct tevent_queue_entry *e)
+{
+       struct tevent_queue *q = e->queue;
+
+       if (!q) {
+               return 0;
+       }
+
+       DLIST_REMOVE(q->list, e);
+       q->length--;
+
+       if (e->triggered &&
+           q->running &&
+           q->list) {
+               q->list->triggered = true;
+               q->list->trigger(q->list->req,
+                                q->list->private_data);
+       }
+
+       return 0;
+}
+
+static int tevent_queue_destructor(struct tevent_queue *q)
+{
+       q->running = false;
+
+       while (q->list) {
+               struct tevent_queue_entry *e = q->list;
+               talloc_free(e);
+       }
+
+       return 0;
+}
+
+struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx,
+                                         const char *name,
+                                         const char *location)
+{
+       struct tevent_queue *queue;
+
+       queue = talloc_zero(mem_ctx, struct tevent_queue);
+       if (!queue) {
+               return NULL;
+       }
+
+       queue->name = talloc_strdup(queue, name);
+       if (!queue->name) {
+               talloc_free(queue);
+               return NULL;
+       }
+
+       queue->location = location;
+
+       /* queue is running by default */
+       queue->running = true;
+
+       talloc_set_destructor(queue, tevent_queue_destructor);
+       return queue;
+}
+
+static void tevent_queue_timer_start(struct tevent_context *ev,
+                                    struct tevent_timer *te,
+                                    struct timeval now,
+                                    void *private_data)
+{
+       struct tevent_queue *q = talloc_get_type(private_data,
+                                 struct tevent_queue);
+
+       talloc_free(te);
+       q->timer = NULL;
+
+       q->list->triggered = true;
+       q->list->trigger(q->list->req, q->list->private_data);
+}
+
+bool tevent_queue_add(struct tevent_queue *queue,
+                     struct tevent_context *ev,
+                     struct tevent_req *req,
+                     tevent_queue_trigger_fn_t trigger,
+                     void *private_data)
+{
+       struct tevent_queue_entry *e;
+
+       e = talloc_zero(req, struct tevent_queue_entry);
+       if (e == NULL) {
+               return false;
+       }
+
+       e->queue = queue;
+       e->req = req;
+       e->trigger = trigger;
+       e->private_data = private_data;
+
+       if (queue->running &&
+           !queue->timer &&
+           !queue->list) {
+               queue->timer = tevent_add_timer(ev, queue, tevent_timeval_zero(),
+                                               tevent_queue_timer_start,
+                                               queue);
+               if (!queue->timer) {
+                       talloc_free(e);
+                       return false;
+               }
+       }
+
+       DLIST_ADD_END(queue->list, e, struct tevent_queue_entry *);
+       queue->length++;
+       talloc_set_destructor(e, tevent_queue_entry_destructor);
+
+       return true;
+}
+
+bool tevent_queue_start(struct tevent_queue *queue,
+                       struct tevent_context *ev)
+{
+       if (queue->running) {
+               /* already started */
+               return true;
+       }
+
+       if (!queue->timer &&
+           queue->list) {
+               queue->timer = tevent_add_timer(ev, queue, tevent_timeval_zero(),
+                                               tevent_queue_timer_start,
+                                               queue);
+               if (!queue->timer) {
+                       return false;
+               }
+       }
+
+       queue->running = true;
+
+       return true;
+}
+
+void tevent_queue_stop(struct tevent_queue *queue)
+{
+       queue->running = false;
+       talloc_free(queue->timer);
+       queue->timer = NULL;
+}
+
+size_t tevent_queue_length(struct tevent_queue *queue)
+{
+       return queue->length;
+}
index 800e3855d1985ba0aa34ce13a5b202016590842c..e243c7de5de3d4787bf4a3a962be9022dfe5c42c 100644 (file)
 #include "tevent_util.h"
 
 /**
- * @brief Print an tevent_req structure in debug messages
- * @param[in] mem_ctx  The memory context for the result
+ * @brief The default print function for creating debug messages
  * @param[in] req      The request to be printed
+ * @param[in] mem_ctx  The memory context for the result
  * @retval             Text representation of req
  *
+ * The function should not be used by users of the asynx API,
+ * but custom print function can use it and append custom text
+ * to the string.
  */
 
-char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
+char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx)
 {
        return talloc_asprintf(mem_ctx,
                               "tevent_req[%p/%s]: state[%d] error[%lld (0x%llX)] "
@@ -50,6 +53,24 @@ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
                               );
 }
 
+/**
+ * @brief Print an tevent_req structure in debug messages
+ * @param[in] mem_ctx  The memory context for the result
+ * @param[in] req      The request to be printed
+ * @retval             Text representation of req
+ *
+ * This function should be used by callers of the async API
+ */
+
+char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
+{
+       if (!req->private_print) {
+               return tevent_req_default_print(req, mem_ctx);
+       }
+
+       return req->private_print(req, mem_ctx);
+}
+
 /**
  * @brief Create an async request
  * @param[in] mem_ctx  The memory context for the result
@@ -235,6 +256,21 @@ bool tevent_req_is_in_progress(struct tevent_req *req)
        return false;
 }
 
+bool tevent_req_poll(struct tevent_req *req,
+                    struct tevent_context *ev)
+{
+       while (tevent_req_is_in_progress(req)) {
+               int ret;
+
+               ret = tevent_loop_once(ev);
+               if (ret != 0) {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
 bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state,
                        uint64_t *error)
 {
index abd89260f676233b08f8a749f9678693e1fd3b30..b4ad9ae17f1c54448462359ad781d3aa723c632d 100644 (file)
@@ -3,7 +3,9 @@
 PUBLIC_DEPENDENCIES = \
                LIBSAMBA-HOSTCONFIG \
                LIBSAMBA-UTIL \
-               LIBTALLOC
+               LIBSAMBA-ERRORS \
+               LIBTALLOC \
+               LIBTEVENT
 CFLAGS = -I$(libtorturesrcdir) -I$(libtorturesrcdir)/../
 
 torture_VERSION = 0.0.1
index 034114eadedafa031b79f3284fb9843d85fb552a..3d06a4363df9b9097ac8dabe04e78de196ee0b95 100644 (file)
 /*******************************************************************
  Close the low 3 fd's and open dev/null in their place.
 ********************************************************************/
-static void close_low_fds(bool stderr_too)
+
+_PUBLIC_ void close_low_fds(bool stderr_too)
 {
 #ifndef VALGRIND
        int fd;
        int i;
 
        close(0);
-       close(1); 
+       close(1);
 
        if (stderr_too)
                close(2);
@@ -61,26 +62,26 @@ static void close_low_fds(bool stderr_too)
 #endif
 }
 
-/**
+/****************************************************************************
  Become a daemon, discarding the controlling terminal.
-**/
+****************************************************************************/
 
-_PUBLIC_ void become_daemon(bool Fork)
+_PUBLIC_ void become_daemon(bool do_fork, bool no_process_group)
 {
-       if (Fork) {
-               if (fork()) {
+       if (do_fork) {
+               if (sys_fork()) {
                        _exit(0);
                }
        }
 
-  /* detach from the terminal */
+       /* detach from the terminal */
 #ifdef HAVE_SETSID
-       setsid();
+       if (!no_process_group) setsid();
 #elif defined(TIOCNOTTY)
-       {
-               int i = open("/dev/tty", O_RDWR, 0);
+       if (!no_process_group) {
+               int i = sys_open("/dev/tty", O_RDWR, 0);
                if (i != -1) {
-                       ioctl(i, (int) TIOCNOTTY, (char *)0);      
+                       ioctl(i, (int) TIOCNOTTY, (char *)0);
                        close(i);
                }
        }
@@ -90,4 +91,3 @@ _PUBLIC_ void become_daemon(bool Fork)
        close_low_fds(false);  /* Don't close stderr, let the debug system
                                  attach it to the logfile */
 }
-
index 9bd180023356cff1970acf352e9c1776ddbe37b6..9bf5de1a83ee7ca605ffea6ba653585cd0ad7b39 100644 (file)
@@ -88,3 +88,32 @@ _PUBLIC_ struct in_addr sys_inet_makeaddr(int net, int host)
        return in2;
 }
 
+/**************************************************************************
+ Wrapper for fork. Ensures we clear our pid cache.
+****************************************************************************/
+
+static pid_t mypid = (pid_t)-1;
+
+_PUBLIC_ pid_t sys_fork(void)
+{
+       pid_t forkret = fork();
+
+       if (forkret == (pid_t)0) {
+               /* Child - reset mypid so sys_getpid does a system call. */
+               mypid = (pid_t) -1;
+       }
+
+       return forkret;
+}
+
+/**************************************************************************
+ Wrapper for getpid. Ensures we only do a system call *once*.
+****************************************************************************/
+
+_PUBLIC_ pid_t sys_getpid(void)
+{
+       if (mypid == (pid_t)-1)
+               mypid = getpid();
+
+       return mypid;
+}
diff --git a/lib/util/tevent_ntstatus.c b/lib/util/tevent_ntstatus.c
new file mode 100644 (file)
index 0000000..1a34e9c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+   Unix SMB/CIFS implementation.
+   Wrap unix errno around tevent_req
+   Copyright (C) Volker Lendecke 2009
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "tevent_ntstatus.h"
+#include "../replace/replace.h"
+
+bool tevent_req_nterror(struct tevent_req *req,        NTSTATUS status)
+{
+       return tevent_req_error(req, NT_STATUS_V(status));
+}
+
+bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *status)
+{
+       enum tevent_req_state state;
+       uint64_t err;
+
+       if (!tevent_req_is_error(req, &state, &err)) {
+               return false;
+       }
+       switch (state) {
+       case TEVENT_REQ_TIMED_OUT:
+               *status = NT_STATUS_IO_TIMEOUT;
+               break;
+       case TEVENT_REQ_NO_MEMORY:
+               *status = NT_STATUS_NO_MEMORY;
+               break;
+       case TEVENT_REQ_USER_ERROR:
+               *status = NT_STATUS(err);
+               break;
+       default:
+               *status = NT_STATUS_INTERNAL_ERROR;
+               break;
+       }
+       return true;
+}
diff --git a/lib/util/tevent_ntstatus.h b/lib/util/tevent_ntstatus.h
new file mode 100644 (file)
index 0000000..84c275f
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+   Unix SMB/CIFS implementation.
+   Wrap unix errno around tevent_req
+   Copyright (C) Volker Lendecke 2009
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _TEVENT_NTSTATUS_H
+#define _TEVENT_NTSTATUS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "config.h"
+#include "../libcli/util/ntstatus.h"
+#include "../tevent/tevent.h"
+
+bool tevent_req_nterror(struct tevent_req *req, NTSTATUS status);
+bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *pstatus);
+
+#endif
diff --git a/lib/util/tevent_unix.c b/lib/util/tevent_unix.c
new file mode 100644 (file)
index 0000000..b89d5cd
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+   Unix SMB/CIFS implementation.
+   Wrap unix errno around tevent_req
+   Copyright (C) Volker Lendecke 2009
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "tevent_unix.h"
+#include "../replace/replace.h"
+
+bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno)
+{
+       enum tevent_req_state state;
+       uint64_t err;
+
+       if (!tevent_req_is_error(req, &state, &err)) {
+               return false;
+       }
+       switch (state) {
+       case TEVENT_REQ_TIMED_OUT:
+               *perrno = ETIMEDOUT;
+               break;
+       case TEVENT_REQ_NO_MEMORY:
+               *perrno = ENOMEM;
+               break;
+       case TEVENT_REQ_USER_ERROR:
+               *perrno = err;
+               break;
+       default:
+               *perrno = EINVAL;
+               break;
+       }
+       return true;
+}
diff --git a/lib/util/tevent_unix.h b/lib/util/tevent_unix.h
new file mode 100644 (file)
index 0000000..dc3ffae
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+   Unix SMB/CIFS implementation.
+   Wrap unix errno around tevent_req
+   Copyright (C) Volker Lendecke 2009
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _TEVENT_UNIX_H
+#define _TEVENT_UNIX_H
+
+#include "../tevent/tevent.h"
+
+bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno);
+
+#endif
index 988d8f9fa02a479d05fc81a72af3905c3c35e12b..1f31f55e8b2fd1a39e3c545fe733cf4370682d04 100644 (file)
@@ -836,4 +836,104 @@ _PUBLIC_ size_t utf16_len_n(const void *src, size_t n)
        return len;
 }
 
+/**
+ * @file
+ * @brief String utilities.
+ **/
+
+static bool next_token_internal_talloc(TALLOC_CTX *ctx,
+                               const char **ptr,
+                                char **pp_buff,
+                                const char *sep,
+                                bool ltrim)
+{
+       char *s;
+       char *saved_s;
+       char *pbuf;
+       bool quoted;
+       size_t len=1;
+
+       *pp_buff = NULL;
+       if (!ptr) {
+               return(false);
+       }
+
+       s = (char *)*ptr;
+
+       /* default to simple separators */
+       if (!sep) {
+               sep = " \t\n\r";
+       }
+
+       /* find the first non sep char, if left-trimming is requested */
+       if (ltrim) {
+               while (*s && strchr_m(sep,*s)) {
+                       s++;
+               }
+       }
+
+       /* nothing left? */
+       if (!*s) {
+               return false;
+       }
+
+       /* When restarting we need to go from here. */
+       saved_s = s;
+
+       /* Work out the length needed. */
+       for (quoted = false; *s &&
+                       (quoted || !strchr_m(sep,*s)); s++) {
+               if (*s == '\"') {
+                       quoted = !quoted;
+               } else {
+                       len++;
+               }
+       }
+
+       /* We started with len = 1 so we have space for the nul. */
+       *pp_buff = talloc_array(ctx, char, len);
+       if (!*pp_buff) {
+               return false;
+       }
+
+       /* copy over the token */
+       pbuf = *pp_buff;
+       s = saved_s;
+       for (quoted = false; *s &&
+                       (quoted || !strchr_m(sep,*s)); s++) {
+               if ( *s == '\"' ) {
+                       quoted = !quoted;
+               } else {
+                       *pbuf++ = *s;
+               }
+       }
+
+       *ptr = (*s) ? s+1 : s;
+       *pbuf = 0;
+
+       return true;
+}
+
+bool next_token_talloc(TALLOC_CTX *ctx,
+                       const char **ptr,
+                       char **pp_buff,
+                       const char *sep)
+{
+       return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);
+}
+
+/*
+ * Get the next token from a string, return false if none found.  Handles
+ * double-quotes.  This version does not trim leading separator characters
+ * before looking for a token.
+ */
+
+bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
+                       const char **ptr,
+                       char **pp_buff,
+                       const char *sep)
+{
+       return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);
+}
+
 
index 7873f0e769f34c407e834636d80caff38362755d..1f6e3b193b3d0a9f9970428e19c45611e7401fca 100644 (file)
@@ -134,6 +134,16 @@ apparent reason.
 _PUBLIC_ struct hostent *sys_gethostbyname(const char *name);
 _PUBLIC_ struct in_addr sys_inet_makeaddr(int net, int host);
 
+/**
+ * Wrapper for fork used to invalid pid cache.
+ **/
+_PUBLIC_ pid_t sys_fork(void);
+
+/**
+ * Wrapper for getpid. Ensures we only do a system call *once*.
+ **/
+_PUBLIC_ pid_t sys_getpid(void);
+
 /* The following definitions come from lib/util/genrand.c  */
 
 /**
@@ -194,6 +204,21 @@ _PUBLIC_ void display_set_stderr(void);
 
 /* The following definitions come from lib/util/util_str.c  */
 
+bool next_token_talloc(TALLOC_CTX *ctx,
+                       const char **ptr,
+                       char **pp_buff,
+                       const char *sep);
+
+/**
+ * Get the next token from a string, return false if none found.  Handles
+ * double-quotes.  This version does not trim leading separator characters
+ * before looking for a token.
+ */
+bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
+                       const char **ptr,
+                       char **pp_buff,
+                       const char *sep);
+
 
 /**
  Trim the specified elements off the front and back of a string.
@@ -724,12 +749,15 @@ _PUBLIC_ int idr_remove(struct idr_context *idp, int id);
 
 /* The following definitions come from lib/util/become_daemon.c  */
 
-#if _SAMBA_BUILD_ == 4
+/**
+ Close the low 3 fd's and open dev/null in their place
+**/
+_PUBLIC_ void close_low_fds(bool stderr_too);
+
 /**
  Become a daemon, discarding the controlling terminal.
 **/
-_PUBLIC_ void become_daemon(bool fork);
-#endif
+_PUBLIC_ void become_daemon(bool do_fork, bool no_process_group);
 
 /**
  * Load a ini-style file.
diff --git a/libcli/ldap/config.mk b/libcli/ldap/config.mk
new file mode 100644 (file)
index 0000000..22cad8c
--- /dev/null
@@ -0,0 +1,15 @@
+[SUBSYSTEM::LIBCLI_LDAP_MESSAGE]
+PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBTALLOC LIBLDB
+PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL ASN1_UTIL
+
+LIBCLI_LDAP_MESSAGE_OBJ_FILES = $(addprefix ../libcli/ldap/, \
+                                               ldap_message.o)
+PUBLIC_HEADERS += ../libcli/ldap/ldap_message.h ../libcli/ldap/ldap_errors.h
+
+[SUBSYSTEM::LIBCLI_LDAP_NDR]
+PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBTALLOC
+PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL LIBLDB NDR_MISC NDR_SECURITY
+
+LIBCLI_LDAP_NDR_OBJ_FILES = ../libcli/ldap/ldap_ndr.o
+PUBLIC_HEADERS += ../libcli/ldap/ldap_ndr.h
+
similarity index 98%
rename from source4/libcli/ldap/ldap_errors.h
rename to libcli/ldap/ldap_errors.h
index 17ac43814c30d18bd0e4e7a2b77ed87a07baef41..fa929c69364e80b95a2b4a864d1a10f2b4cdec8d 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef _SMB_LDAP_ERRORS_H_
 #define _SMB_LDAP_ERRORS_H_
 
+#ifndef LDAP_SUCCESS
 enum ldap_result_code {
        LDAP_SUCCESS                            = 0,
        LDAP_OPERATIONS_ERROR                   = 1,
@@ -62,5 +63,6 @@ enum ldap_result_code {
        LDAP_AFFECTS_MULTIPLE_DSAS              = 71,
        LDAP_OTHER                              = 80
 };
+#endif
 
 #endif /* _SMB_LDAP_ERRORS_H_ */
similarity index 88%
rename from source4/libcli/ldap/ldap.c
rename to libcli/ldap/ldap_message.c
index 7a65cc5c2746fad95cebc851d4a1240930a29488..9b00d0188d1ca0cb92071e0b2d1f8bcac2b79899 100644 (file)
 
 #include "includes.h"
 #include "../lib/util/asn1.h"
-#include "libcli/ldap/ldap.h"
-#include "libcli/ldap/ldap_proto.h"
+#include "../libcli/ldap/ldap_message.h"
 
+_PUBLIC_ struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
+{
+       return talloc_zero(mem_ctx, struct ldap_message);
+}
+
+
+static bool add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
+                               struct ldb_message_element *attrib)
+{
+       attrib->values = talloc_realloc(mem_ctx,
+                                       attrib->values,
+                                       DATA_BLOB,
+                                       attrib->num_values+1);
+       if (attrib->values == NULL)
+               return false;
+
+       attrib->values[attrib->num_values].data = talloc_steal(attrib->values,
+                                                              value->data);
+       attrib->values[attrib->num_values].length = value->length;
+       attrib->num_values += 1;
+       return true;
+}
+
+static bool add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
+                                      const struct ldb_message_element *attrib,
+                                      struct ldb_message_element **attribs,
+                                      int *num_attribs)
+{
+       *attribs = talloc_realloc(mem_ctx,
+                                 *attribs,
+                                 struct ldb_message_element,
+                                 *num_attribs+1);
+
+       if (*attribs == NULL)
+               return false;
+
+       (*attribs)[*num_attribs] = *attrib;
+       talloc_steal(*attribs, attrib->values);
+       talloc_steal(*attribs, attrib->name);
+       *num_attribs += 1;
+       return true;
+}
+
+static bool add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
+                                   struct ldap_mod *mod,
+                                   struct ldap_mod **mods,
+                                   int *num_mods)
+{
+       *mods = talloc_realloc(mem_ctx, *mods, struct ldap_mod, (*num_mods)+1);
+
+       if (*mods == NULL)
+               return false;
+
+       (*mods)[*num_mods] = *mod;
+       *num_mods += 1;
+       return true;
+}
+
+static bool ldap_decode_control_value(void *mem_ctx, DATA_BLOB value,
+                                     const struct ldap_control_handler *handlers,
+                                     struct ldb_control *ctrl)
+{
+       int i;
+
+       if (!handlers) {
+               return true;
+       }
+
+       for (i = 0; handlers[i].oid != NULL; i++) {
+               if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
+                       if (!handlers[i].decode || !handlers[i].decode(mem_ctx, value, &ctrl->data)) {
+                               return false;
+                       }
+                       break;
+               }
+       }
+       if (handlers[i].oid == NULL) {
+               return false;
+       }
+
+       return true;
+}
+
+static bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data,
+                                       struct ldb_control *ctrl, DATA_BLOB *value)
+{
+       DATA_BLOB oid;
+
+       if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
+               return false;
+       }
+
+       if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
+               return false;
+       }
+       ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
+       if (!ctrl->oid) {
+               return false;
+       }
+
+       if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
+               bool critical;
+               if (!asn1_read_BOOLEAN(data, &critical)) {
+                       return false;
+               }
+               ctrl->critical = critical;
+       } else {
+               ctrl->critical = false;
+       }
+
+       ctrl->data = NULL;
+
+       if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
+               *value = data_blob(NULL, 0);
+               goto end_tag;
+       }
+
+       if (!asn1_read_OctetString(data, mem_ctx, value)) {
+               return false;
+       }
+
+end_tag:
+       if (!asn1_end_tag(data)) {
+               return false;
+       }
+
+       return true;
+}
+
+static bool ldap_encode_control(void *mem_ctx, struct asn1_data *data,
+                               const struct ldap_control_handler *handlers,
+                               struct ldb_control *ctrl)
+{
+       DATA_BLOB value;
+       int i;
+
+       if (!handlers) {
+               return false;
+       }
+
+       for (i = 0; handlers[i].oid != NULL; i++) {
+               if (strcmp(handlers[i].oid, ctrl->oid) == 0) {
+                       if (!handlers[i].encode) {
+                               if (ctrl->critical) {
+                                       return false;
+                               } else {
+                                       /* not encoding this control */
+                                       return true;
+                               }
+                       }
+                       if (!handlers[i].encode(mem_ctx, ctrl->data, &value)) {
+                               return false;
+                       }
+                       break;
+               }
+       }
+       if (handlers[i].oid == NULL) {
+               return false;
+       }
+
+       if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
+               return false;
+       }
+
+       if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
+               return false;
+       }
+
+       if (ctrl->critical) {
+               if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
+                       return false;
+               }
+       }
+
+       if (!ctrl->data) {
+               goto pop_tag;
+       }
+
+       if (!asn1_write_OctetString(data, value.data, value.length)) {
+               return false;
+       }
+
+pop_tag:
+       if (!asn1_pop_tag(data)) {
+               return false;
+       }
+
+       return true;
+}
 
 static bool ldap_push_filter(struct asn1_data *data, struct ldb_parse_tree *tree)
 {
@@ -188,7 +376,9 @@ static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *res
        }
 }
 
-_PUBLIC_ bool ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CTX *mem_ctx)
+_PUBLIC_ bool ldap_encode(struct ldap_message *msg,
+                         const struct ldap_control_handler *control_handlers,
+                         DATA_BLOB *result, TALLOC_CTX *mem_ctx)
 {
        struct asn1_data *data = asn1_init(mem_ctx);
        int i, j;
@@ -475,7 +665,9 @@ _PUBLIC_ bool ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CT
                asn1_push_tag(data, ASN1_CONTEXT(0));
                
                for (i = 0; msg->controls[i] != NULL; i++) {
-                       if (!ldap_encode_control(mem_ctx, data, msg->controls[i])) {
+                       if (!ldap_encode_control(mem_ctx, data,
+                                                control_handlers,
+                                                msg->controls[i])) {
                                return false;
                        }
                }
@@ -867,13 +1059,13 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
                                ret->u.extended.attr = talloc_strdup(ret, "*");
                        }
                        ret->u.extended.rule_id      = talloc_steal(ret, oid);
-                       ret->u.extended.value.data   = talloc_steal(ret, value);
+                       ret->u.extended.value.data   = (uint8_t *)talloc_steal(ret, value);
                        ret->u.extended.value.length = strlen(value);
                        ret->u.extended.dnAttributes = dnAttributes;
                } else {
                        ret->operation               = LDB_OP_EQUALITY;
                        ret->u.equality.attr         = talloc_steal(ret, attr);
-                       ret->u.equality.value.data   = talloc_steal(ret, value);
+                       ret->u.equality.value.data   = (uint8_t *)talloc_steal(ret, value);
                        ret->u.equality.value.length = strlen(value);
                }
                if (!asn1_end_tag(data)) {
@@ -883,7 +1075,6 @@ static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx,
        }
 
        default:
-               DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));
                goto failed;
        }
        
@@ -926,9 +1117,9 @@ void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
 }
 
 /* Decode a set of LDAP attributes, as found in a search entry */
-void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
-                        struct ldb_message_element **attributes,
-                        int *num_attributes)
+static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
+                               struct ldb_message_element **attributes,
+                               int *num_attributes)
 {
        asn1_start_tag(data, ASN1_SEQUENCE(0));
        ldap_decode_attribs_bare(mem_ctx, data, 
@@ -938,7 +1129,9 @@ void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
 
 /* This routine returns LDAP status codes */
 
-_PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
+_PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data,
+                             const struct ldap_control_handler *control_handlers,
+                             struct ldap_message *msg)
 {
        uint8_t tag;
 
@@ -1032,13 +1225,17 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
 
        case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
                struct ldap_SearchRequest *r = &msg->r.SearchRequest;
+               int sizelimit, timelimit;
+               const char **attrs = NULL;
                msg->type = LDAP_TAG_SearchRequest;
                asn1_start_tag(data, tag);
                asn1_read_OctetString_talloc(msg, data, &r->basedn);
                asn1_read_enumerated(data, (int *)&(r->scope));
                asn1_read_enumerated(data, (int *)&(r->deref));
-               asn1_read_Integer(data, &r->sizelimit);
-               asn1_read_Integer(data, &r->timelimit);
+               asn1_read_Integer(data, &sizelimit);
+               r->sizelimit = sizelimit;
+               asn1_read_Integer(data, &timelimit);
+               r->timelimit = timelimit;
                asn1_read_BOOLEAN(data, &r->attributesonly);
 
                r->tree = ldap_decode_filter_tree(msg, data);
@@ -1058,10 +1255,11 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
                                                          &attr))
                                return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
                        if (!add_string_to_array(msg, attr,
-                                                &r->attributes,
+                                                &attrs,
                                                 &r->num_attributes))
                                return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
                }
+               r->attributes = attrs;
 
                asn1_end_tag(data);
                asn1_end_tag(data);
@@ -1368,7 +1566,9 @@ _PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg)
                                return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
                        }
                        
-                       if (!ldap_decode_control_value(ctrl, value, ctrl[i])) {
+                       if (!ldap_decode_control_value(ctrl, value,
+                                                      control_handlers,
+                                                      ctrl[i])) {
                                if (ctrl[i]->critical) {
                                        ctrl[i]->data = NULL;
                                        decoded[i] = false;
similarity index 70%
rename from source3/include/smb_ldap.h
rename to libcli/ldap/ldap_message.h
index a3c270d95c1e9f630858bcdbbae7e9ebeef21be0..c50018465c88d83c30fbcd28d1336338e1bd2f9a 100644 (file)
    
 */
 
-#ifndef _SMB_LDAP_H
-#define _SMB_LDAP_H
+#ifndef _LIBCLI_LDAP_MESSAGE_H_
+#define _LIBCLI_LDAP_MESSAGE_H_
+
+#include "../libcli/ldap/ldap_errors.h"
+#include "lib/ldb/include/ldb.h"
 
 enum ldap_request_tag {
        LDAP_TAG_BindRequest = 0,
@@ -49,15 +52,6 @@ enum ldap_auth_mechanism {
        LDAP_AUTH_MECH_SASL = 3
 };
 
-#ifndef LDAP_SUCCESS
-enum ldap_result_code {
-       LDAP_SUCCESS = 0,
-       LDAP_SASL_BIND_IN_PROGRESS = 0x0e,
-       LDAP_INVALID_CREDENTIALS = 0x31,
-       LDAP_OTHER = 0x50
-};
-#endif /* LDAP_SUCCESS */
-
 struct ldap_Result {
        int resultcode;
        const char *dn;
@@ -65,12 +59,6 @@ struct ldap_Result {
        const char *referral;
 };
 
-struct ldap_attribute {
-       const char *name;
-       int num_values;
-       DATA_BLOB *values;
-};
-
 struct ldap_BindRequest {
        int version;
        const char *dn;
@@ -79,7 +67,7 @@ struct ldap_BindRequest {
                const char *password;
                struct {
                        const char *mechanism;
-                       DATA_BLOB secblob;
+                       DATA_BLOB *secblob;/* optional */
                } SASL;
        } creds;
 };
@@ -87,12 +75,12 @@ struct ldap_BindRequest {
 struct ldap_BindResponse {
        struct ldap_Result response;
        union {
-               DATA_BLOB secblob;
+               DATA_BLOB *secblob;/* optional */
        } SASL;
 };
 
 struct ldap_UnbindRequest {
-       uint8 __dummy;
+       uint8_t __dummy;
 };
 
 enum ldap_scope {
@@ -112,23 +100,22 @@ struct ldap_SearchRequest {
        const char *basedn;
        enum ldap_scope scope;
        enum ldap_deref deref;
-       uint32 timelimit;
-       uint32 sizelimit;
+       uint32_t timelimit;
+       uint32_t sizelimit;
        bool attributesonly;
-       char *filter;
+       struct ldb_parse_tree *tree;
        int num_attributes;
-       const char **attributes;
+       const char * const *attributes;
 };
 
 struct ldap_SearchResEntry {
        const char *dn;
        int num_attributes;
-       struct ldap_attribute *attributes;
+       struct ldb_message_element *attributes;
 };
 
 struct ldap_SearchResRef {
-       int num_referrals;
-       const char **referrals;
+       const char *referral;
 };
 
 enum ldap_modify_type {
@@ -140,7 +127,7 @@ enum ldap_modify_type {
 
 struct ldap_mod {
        enum ldap_modify_type type;
-       struct ldap_attribute attrib;
+       struct ldb_message_element attrib;
 };
 
 struct ldap_ModifyRequest {
@@ -152,7 +139,7 @@ struct ldap_ModifyRequest {
 struct ldap_AddRequest {
        const char *dn;
        int num_attributes;
-       struct ldap_attribute *attributes;
+       struct ldb_message_element *attributes;
 };
 
 struct ldap_DelRequest {
@@ -163,31 +150,32 @@ struct ldap_ModifyDNRequest {
        const char *dn;
        const char *newrdn;
        bool deleteolddn;
-       const char *newsuperior;
+       const char *newsuperior;/* optional */
 };
 
 struct ldap_CompareRequest {
        const char *dn;
        const char *attribute;
-       const char *value;
+       DATA_BLOB value;
 };
 
 struct ldap_AbandonRequest {
-       uint32 messageid;
+       int messageid;
 };
 
 struct ldap_ExtendedRequest {
        const char *oid;
-       DATA_BLOB value;
+       DATA_BLOB *value;/* optional */
 };
 
 struct ldap_ExtendedResponse {
        struct ldap_Result response;
-       const char *name;
-       DATA_BLOB value;
+       const char *oid;/* optional */
+       DATA_BLOB *value;/* optional */
 };
 
 union ldap_Request {
+       struct ldap_Result              GeneralResult;
        struct ldap_BindRequest         BindRequest;
        struct ldap_BindResponse        BindResponse;
        struct ldap_UnbindRequest       UnbindRequest;
@@ -210,46 +198,38 @@ union ldap_Request {
        struct ldap_ExtendedResponse    ExtendedResponse;
 };
 
-struct ldap_Control {
-       const char *oid;
-       bool        critical;
-       DATA_BLOB   value;
-};
 
 struct ldap_message {
-       TALLOC_CTX             *mem_ctx;
-       uint32                  messageid;
-       uint8                   type;
-       union  ldap_Request     r;
-       int                     num_controls;
-       struct ldap_Control    *controls;
+       int                     messageid;
+       enum ldap_request_tag   type;
+       union ldap_Request      r;
+       struct ldb_control    **controls;
+       bool                   *controls_decoded;
 };
 
-struct ldap_queue_entry {
-       struct ldap_queue_entry *next, *prev;
-       int msgid;
-       struct ldap_message *msg;
+struct ldap_control_handler {
+       const char *oid;
+       bool (*decode)(void *mem_ctx, DATA_BLOB in, void *_out);
+       bool (*encode)(void *mem_ctx, void *in, DATA_BLOB *out);
 };
 
-struct ldap_connection {
-       TALLOC_CTX *mem_ctx;
-       int sock;
-       int next_msgid;
-       char *host;
-       uint16 port;
-       bool ldaps;
-
-       const char *auth_dn;
-       const char *simple_pw;
+struct asn1_data;
 
-       /* Current outstanding search entry */
-       int searchid;
+struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx);
+NTSTATUS ldap_decode(struct asn1_data *data,
+                    const struct ldap_control_handler *control_handlers,
+                    struct ldap_message *msg);
+bool ldap_encode(struct ldap_message *msg,
+                const struct ldap_control_handler *control_handlers,
+                DATA_BLOB *result, TALLOC_CTX *mem_ctx);
+NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size);
 
-       /* List for incoming search entries */
-       struct ldap_queue_entry *search_entries;
+bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
+                                 struct asn1_data *data,
+                                 const char **result);
 
-       /* Outstanding LDAP requests that have not yet been replied to */
-       struct ldap_queue_entry *outstanding;
-};
+void ldap_decode_attribs_bare(TALLOC_CTX *mem_ctx, struct asn1_data *data,
+                             struct ldb_message_element **attributes,
+                             int *num_attributes);
 
-#endif
+#endif 
similarity index 98%
rename from source4/libcli/ldap/ldap_ndr.c
rename to libcli/ldap/ldap_ndr.c
index f0a11ba41fd0e632e3576889e51b015d36f123bc..dd820ff8d5fcde86cb695061ce2218543ef41095 100644 (file)
@@ -21,7 +21,7 @@
 */
 
 #include "includes.h"
-#include "libcli/ldap/ldap.h"
+#include "lib/ldb/include/ldb.h"
 #include "librpc/gen_ndr/ndr_security.h"
 #include "librpc/gen_ndr/ndr_misc.h"
 #include "libcli/ldap/ldap_ndr.h"
index 160e7bc3e0bb7ca7014beccbd9eb9f0dbb70b89a..1044ab351a125f55bc2dba637a3da552eff46fb2 100644 (file)
@@ -135,6 +135,7 @@ static const struct werror_code_struct dos_errs[] =
        { "WERR_INVALID_FLAGS", WERR_INVALID_FLAGS },
        { "WERR_NOT_FOUND", WERR_NOT_FOUND },
        { "WERR_SERVER_UNAVAILABLE", WERR_SERVER_UNAVAILABLE },
+       { "WERR_INVALID_USER_BUFFER", WERR_INVALID_USER_BUFFER },
        { "WERR_NO_TRUST_SAM_ACCOUNT", WERR_NO_TRUST_SAM_ACCOUNT },
        { "WERR_CLASS_NOT_REGISTERED", WERR_CLASS_NOT_REGISTERED },
        { "WERR_NO_SHUTDOWN_IN_PROGRESS", WERR_NO_SHUTDOWN_IN_PROGRESS },
@@ -168,6 +169,7 @@ static const struct werror_code_struct dos_errs[] =
        { "WERR_SERVICE_NEVER_STARTED", WERR_SERVICE_NEVER_STARTED },
        { "WERR_PASSWORD_MUST_CHANGE", WERR_PASSWORD_MUST_CHANGE },
        { "WERR_ACCOUNT_LOCKED_OUT", WERR_ACCOUNT_LOCKED_OUT },
+       { "WERR_UNKNOWN_PRINT_MONITOR", WERR_UNKNOWN_PRINT_MONITOR },
        { NULL, W_ERROR(0) }
 };
 
index d22516ae5c4aecebe46cffff80974e5be1453be3..15251a44fc8e0d14721b6c07254ad6e81f153320 100644 (file)
@@ -60,6 +60,18 @@ typedef uint32_t WERROR;
        }\
 } while (0)
 
+#define W_ERROR_NOT_OK_GOTO_DONE(x) do { \
+       if (!W_ERROR_IS_OK(x)) {\
+               goto done;\
+       }\
+} while (0)
+
+#define W_ERROR_NOT_OK_GOTO(x, y) do {\
+       if (!W_ERROR_IS_OK(x)) {\
+               goto y;\
+       }\
+} while(0)
+
 /* these are win32 error codes. There are only a few places where
    these matter for Samba, primarily in the NT printing code */
 #define WERR_OK W_ERROR(0)
@@ -136,6 +148,7 @@ typedef uint32_t WERROR;
 #define WERR_TIME_SKEW W_ERROR(1398)
 #define WERR_EVENTLOG_FILE_CORRUPT W_ERROR(1500)
 #define WERR_SERVER_UNAVAILABLE W_ERROR(1722)
+#define WERR_INVALID_USER_BUFFER W_ERROR(1784)
 #define WERR_NO_TRUST_SAM_ACCOUNT W_ERROR(1787)
 #define WERR_INVALID_FORM_NAME W_ERROR(1902)
 #define WERR_INVALID_FORM_SIZE W_ERROR(1903)
index 6b084d22171c9cb2870fbd92a1587b9af653296f..b9cf39dea0a2d4610d44e532a1c377e2b143036c 100644 (file)
@@ -902,7 +902,7 @@ NTSTATUS rpccli_eventlog_WriteClusterEvents(struct rpc_pipe_client *cli,
        return r.out.result;
 }
 
-NTSTATUS rpccli_eventlog_GetLogIntormation(struct rpc_pipe_client *cli,
+NTSTATUS rpccli_eventlog_GetLogInformation(struct rpc_pipe_client *cli,
                                           TALLOC_CTX *mem_ctx,
                                           struct policy_handle *handle /* [in] [ref] */,
                                           uint32_t level /* [in]  */,
@@ -910,7 +910,7 @@ NTSTATUS rpccli_eventlog_GetLogIntormation(struct rpc_pipe_client *cli,
                                           uint32_t buf_size /* [in] [range(0,1024)] */,
                                           uint32_t *bytes_needed /* [out] [ref] */)
 {
-       struct eventlog_GetLogIntormation r;
+       struct eventlog_GetLogInformation r;
        NTSTATUS status;
 
        /* In parameters */
@@ -919,13 +919,13 @@ NTSTATUS rpccli_eventlog_GetLogIntormation(struct rpc_pipe_client *cli,
        r.in.buf_size = buf_size;
 
        if (DEBUGLEVEL >= 10) {
-               NDR_PRINT_IN_DEBUG(eventlog_GetLogIntormation, &r);
+               NDR_PRINT_IN_DEBUG(eventlog_GetLogInformation, &r);
        }
 
        status = cli->dispatch(cli,
                                mem_ctx,
                                &ndr_table_eventlog,
-                               NDR_EVENTLOG_GETLOGINTORMATION,
+                               NDR_EVENTLOG_GETLOGINFORMATION,
                                &r);
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -933,7 +933,7 @@ NTSTATUS rpccli_eventlog_GetLogIntormation(struct rpc_pipe_client *cli,
        }
 
        if (DEBUGLEVEL >= 10) {
-               NDR_PRINT_OUT_DEBUG(eventlog_GetLogIntormation, &r);
+               NDR_PRINT_OUT_DEBUG(eventlog_GetLogInformation, &r);
        }
 
        if (NT_STATUS_IS_ERR(status)) {
index ae5544daf3aaeae7c622ed7e37de3efcee4775fc..d905676041afd94573f7b6da74e0ef151c9d4cc8 100644 (file)
@@ -93,7 +93,7 @@ NTSTATUS rpccli_eventlog_DeregisterClusterSvc(struct rpc_pipe_client *cli,
                                              TALLOC_CTX *mem_ctx);
 NTSTATUS rpccli_eventlog_WriteClusterEvents(struct rpc_pipe_client *cli,
                                            TALLOC_CTX *mem_ctx);
-NTSTATUS rpccli_eventlog_GetLogIntormation(struct rpc_pipe_client *cli,
+NTSTATUS rpccli_eventlog_GetLogInformation(struct rpc_pipe_client *cli,
                                           TALLOC_CTX *mem_ctx,
                                           struct policy_handle *handle /* [in] [ref] */,
                                           uint32_t level /* [in]  */,
index 02a05b94ff85a1ce918cbd519cfd40ab83fb35ca..2aa42b93bfb092a9d79aaa135877c5f9d367fe0b 100644 (file)
@@ -2540,7 +2540,7 @@ NTSTATUS rpccli_spoolss_GetPrinterDriver2(struct rpc_pipe_client *cli,
                                          uint32_t offered /* [in]  */,
                                          uint32_t client_major_version /* [in]  */,
                                          uint32_t client_minor_version /* [in]  */,
-                                         DATA_BLOB *info /* [out] [unique] */,
+                                         union spoolss_DriverInfo *info /* [out] [unique,subcontext_size(offered),subcontext(4),switch_is(level)] */,
                                          uint32_t *needed /* [out] [ref] */,
                                          uint32_t *server_major_version /* [out] [ref] */,
                                          uint32_t *server_minor_version /* [out] [ref] */,
index bb38d59cfb1680e38d8d6689b937d5ab2af78062..83b2e28729ec4292cf39ba2fbb7ffa059d64b233 100644 (file)
@@ -331,7 +331,7 @@ NTSTATUS rpccli_spoolss_GetPrinterDriver2(struct rpc_pipe_client *cli,
                                          uint32_t offered /* [in]  */,
                                          uint32_t client_major_version /* [in]  */,
                                          uint32_t client_minor_version /* [in]  */,
-                                         DATA_BLOB *info /* [out] [unique] */,
+                                         union spoolss_DriverInfo *info /* [out] [unique,subcontext_size(offered),subcontext(4),switch_is(level)] */,
                                          uint32_t *needed /* [out] [ref] */,
                                          uint32_t *server_major_version /* [out] [ref] */,
                                          uint32_t *server_minor_version /* [out] [ref] */,
index 07548c3742cb8771fe123e13a92da7bfb5e9c865..41be3bd28d84b34cab08c1c8eaf72fd14cbee5e9 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/misc.h"
 #ifndef _HEADER_netdfs
 #define _HEADER_netdfs
index bb33464c76778e4b92e0e52f7a0ab8328d9fda54..190e012cb524687cdf646ac5ce478dbcf0f8f4a6 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/drsuapi.h"
 #include "librpc/gen_ndr/misc.h"
 #include "librpc/gen_ndr/samr.h"
index e3d480365e460ba2db0ba30246c873c2849a2974..8f9b165631e0dc4cfdbc0a35399f89f493485cfa 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/security.h"
 #include "librpc/gen_ndr/misc.h"
 #include "librpc/gen_ndr/samr.h"
index d284a63375c47ff8c810b220e007a23a80336ff6..5d254fe92e6bbb275cf9b11c525d83442a6220dc 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/misc.h"
 #ifndef _HEADER_dssetup
 #define _HEADER_dssetup
index 79d4220714d40b121272919be953cb96ab69057f..9c783046f3b74d2fb245edf6674ab57900563157 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #ifndef _HEADER_rpcecho
 #define _HEADER_rpcecho
 
index e5155a8cad7f9bf4ef27dc61352fb86c5b913b14..ff80fbb4fd781e83bde9772b39850c96df6001c5 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/misc.h"
 #ifndef _HEADER_epmapper
 #define _HEADER_epmapper
index 94da688f5c846b3dd88870f37fb96eac7b1449ec..b6e792fdd37bca457898565f323609c3029834ba 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/lsa.h"
 #include "librpc/gen_ndr/security.h"
 #ifndef _HEADER_eventlog
@@ -39,32 +41,6 @@ struct eventlog_OpenUnknown0 {
        uint16_t unknown1;
 };
 
-struct eventlog_Record {
-       uint32_t size;
-       const char *reserved;/* [value("eLfL"),charset(DOS)] */
-       uint32_t record_number;
-       time_t time_generated;
-       time_t time_written;
-       uint32_t event_id;
-       enum eventlogEventTypes event_type;
-       uint16_t num_of_strings;/* [range(0,256)] */
-       uint16_t event_category;
-       uint16_t reserved_flags;
-       uint32_t closing_record_number;
-       uint32_t stringoffset;
-       uint32_t sid_size;/* [value(ndr_size_dom_sid0(&sid,ndr->flags))] */
-       uint32_t sid_offset;
-       uint32_t data_length;
-       uint32_t data_offset;
-       const char * source_name;/* [flag(LIBNDR_FLAG_STR_NULLTERM)] */
-       const char * computer_name;/* [flag(LIBNDR_FLAG_STR_NULLTERM)] */
-       struct dom_sid0 sid;/* [subcontext_size(sid_size),subcontext(0)] */
-       const char * *strings;/* [flag(LIBNDR_FLAG_STR_NULLTERM)] */
-       const char * raw_data;/* [flag(LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM)] */
-       DATA_BLOB _padding;/* [flag(LIBNDR_FLAG_ALIGN4)] */
-       uint32_t size2;/* [value(size)] */
-}/* [public,flag(LIBNDR_FLAG_NOALIGN)] */;
-
 struct eventlog_Record_tdb {
        uint32_t size;
        const char *reserved;/* [value("eLfL"),charset(DOS)] */
@@ -437,7 +413,7 @@ struct eventlog_WriteClusterEvents {
 };
 
 
-struct eventlog_GetLogIntormation {
+struct eventlog_GetLogInformation {
        struct {
                struct policy_handle *handle;/* [ref] */
                uint32_t level;
index 014e2fe6898d7a87e71b9e07e08d705b8e58c80a..913eb8f740025a994f8ab292c0021b1f5f0e5693 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/lsa.h"
 #ifndef _HEADER_initshutdown
 #define _HEADER_initshutdown
index 73bd0d95bb1fd97c1f62b6fd3853e4e5c210123e..03b23bdaaeb99be287949dc8206bb21f5912990a 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/security.h"
 #include "librpc/gen_ndr/netlogon.h"
 #include "librpc/gen_ndr/samr.h"
index 03a0464d5bd791f20ba5509fcebfb5128aff1ffb..a6da7a6cef98e18b4c91266f209b85a18dd212d1 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/misc.h"
 #include "librpc/gen_ndr/security.h"
 #ifndef _HEADER_lsarpc
index e000cb0624e84e7f518e322802d2be2503406f5f..824483d29206a63de54cc8ae31ca9b1539fa2d29 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #ifndef _HEADER_misc
 #define _HEADER_misc
 
index 7ca7444c92703f2d2d903611d62181d23d94ecad..e35c22111866463aa672bc9d8de5540061c510b7 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/netlogon.h"
 #ifndef _HEADER_named_pipe_auth
 #define _HEADER_named_pipe_auth
index 1f3ad37d9bf5aa6c544a2592edab46828fd639e2..affbeffa08651a63de2f04ee7eaccd38d1033b77 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/misc.h"
 #include "librpc/gen_ndr/security.h"
 #include "librpc/gen_ndr/svcctl.h"
index 0d5654c6401430660536f902f970f7f276f98a93..3f19902690d6dc27ae94511c2a42cd782e063780 100644 (file)
@@ -92,201 +92,6 @@ _PUBLIC_ void ndr_print_eventlog_OpenUnknown0(struct ndr_print *ndr, const char
        ndr->depth--;
 }
 
-_PUBLIC_ enum ndr_err_code ndr_push_eventlog_Record(struct ndr_push *ndr, int ndr_flags, const struct eventlog_Record *r)
-{
-       uint32_t cntr_strings_0;
-       {
-               uint32_t _flags_save_STRUCT = ndr->flags;
-               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
-               if (ndr_flags & NDR_SCALARS) {
-                       NDR_CHECK(ndr_push_align(ndr, 4));
-                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size));
-                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, "eLfL", 4, sizeof(uint8_t), CH_DOS));
-                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->record_number));
-                       NDR_CHECK(ndr_push_time_t(ndr, NDR_SCALARS, r->time_generated));
-                       NDR_CHECK(ndr_push_time_t(ndr, NDR_SCALARS, r->time_written));
-                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->event_id));
-                       NDR_CHECK(ndr_push_eventlogEventTypes(ndr, NDR_SCALARS, r->event_type));
-                       NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->num_of_strings));
-                       NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->event_category));
-                       NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r->reserved_flags));
-                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->closing_record_number));
-                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->stringoffset));
-                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_size_dom_sid0(&r->sid, ndr->flags)));
-                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sid_offset));
-                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->data_length));
-                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->data_offset));
-                       {
-                               uint32_t _flags_save_string = ndr->flags;
-                               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
-                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->source_name));
-                               ndr->flags = _flags_save_string;
-                       }
-                       {
-                               uint32_t _flags_save_string = ndr->flags;
-                               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
-                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->computer_name));
-                               ndr->flags = _flags_save_string;
-                       }
-                       {
-                               struct ndr_push *_ndr_sid;
-                               NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_sid, 0, ndr_size_dom_sid0(&r->sid, ndr->flags)));
-                               NDR_CHECK(ndr_push_dom_sid0(_ndr_sid, NDR_SCALARS|NDR_BUFFERS, &r->sid));
-                               NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_sid, 0, ndr_size_dom_sid0(&r->sid, ndr->flags)));
-                       }
-                       {
-                               uint32_t _flags_save_string = ndr->flags;
-                               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
-                               for (cntr_strings_0 = 0; cntr_strings_0 < r->num_of_strings; cntr_strings_0++) {
-                                       NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->strings[cntr_strings_0]));
-                               }
-                               ndr->flags = _flags_save_string;
-                       }
-                       {
-                               uint32_t _flags_save_string = ndr->flags;
-                               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
-                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->raw_data));
-                               ndr->flags = _flags_save_string;
-                       }
-                       {
-                               uint32_t _flags_save_DATA_BLOB = ndr->flags;
-                               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4);
-                               NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->_padding));
-                               ndr->flags = _flags_save_DATA_BLOB;
-                       }
-                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size));
-               }
-               if (ndr_flags & NDR_BUFFERS) {
-               }
-               ndr->flags = _flags_save_STRUCT;
-       }
-       return NDR_ERR_SUCCESS;
-}
-
-_PUBLIC_ enum ndr_err_code ndr_pull_eventlog_Record(struct ndr_pull *ndr, int ndr_flags, struct eventlog_Record *r)
-{
-       uint32_t cntr_strings_0;
-       TALLOC_CTX *_mem_save_strings_0;
-       {
-               uint32_t _flags_save_STRUCT = ndr->flags;
-               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
-               if (ndr_flags & NDR_SCALARS) {
-                       NDR_CHECK(ndr_pull_align(ndr, 4));
-                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->size));
-                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->reserved, 4, sizeof(uint8_t), CH_DOS));
-                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->record_number));
-                       NDR_CHECK(ndr_pull_time_t(ndr, NDR_SCALARS, &r->time_generated));
-                       NDR_CHECK(ndr_pull_time_t(ndr, NDR_SCALARS, &r->time_written));
-                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->event_id));
-                       NDR_CHECK(ndr_pull_eventlogEventTypes(ndr, NDR_SCALARS, &r->event_type));
-                       NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->num_of_strings));
-                       if (r->num_of_strings > 256) {
-                               return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
-                       }
-                       NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->event_category));
-                       NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->reserved_flags));
-                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->closing_record_number));
-                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->stringoffset));
-                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sid_size));
-                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sid_offset));
-                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->data_length));
-                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->data_offset));
-                       {
-                               uint32_t _flags_save_string = ndr->flags;
-                               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
-                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->source_name));
-                               ndr->flags = _flags_save_string;
-                       }
-                       {
-                               uint32_t _flags_save_string = ndr->flags;
-                               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
-                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->computer_name));
-                               ndr->flags = _flags_save_string;
-                       }
-                       {
-                               struct ndr_pull *_ndr_sid;
-                               NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_sid, 0, r->sid_size));
-                               NDR_CHECK(ndr_pull_dom_sid0(_ndr_sid, NDR_SCALARS|NDR_BUFFERS, &r->sid));
-                               NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_sid, 0, r->sid_size));
-                       }
-                       {
-                               uint32_t _flags_save_string = ndr->flags;
-                               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
-                               NDR_PULL_ALLOC_N(ndr, r->strings, r->num_of_strings);
-                               _mem_save_strings_0 = NDR_PULL_GET_MEM_CTX(ndr);
-                               NDR_PULL_SET_MEM_CTX(ndr, r->strings, 0);
-                               for (cntr_strings_0 = 0; cntr_strings_0 < r->num_of_strings; cntr_strings_0++) {
-                                       NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->strings[cntr_strings_0]));
-                               }
-                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_strings_0, 0);
-                               ndr->flags = _flags_save_string;
-                       }
-                       {
-                               uint32_t _flags_save_string = ndr->flags;
-                               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
-                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->raw_data));
-                               ndr->flags = _flags_save_string;
-                       }
-                       {
-                               uint32_t _flags_save_DATA_BLOB = ndr->flags;
-                               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4);
-                               NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->_padding));
-                               ndr->flags = _flags_save_DATA_BLOB;
-                       }
-                       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->size2));
-               }
-               if (ndr_flags & NDR_BUFFERS) {
-               }
-               ndr->flags = _flags_save_STRUCT;
-       }
-       return NDR_ERR_SUCCESS;
-}
-
-_PUBLIC_ void ndr_print_eventlog_Record(struct ndr_print *ndr, const char *name, const struct eventlog_Record *r)
-{
-       uint32_t cntr_strings_0;
-       ndr_print_struct(ndr, name, "eventlog_Record");
-       {
-               uint32_t _flags_save_STRUCT = ndr->flags;
-               ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
-               ndr->depth++;
-               ndr_print_uint32(ndr, "size", r->size);
-               ndr_print_string(ndr, "reserved", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?"eLfL":r->reserved);
-               ndr_print_uint32(ndr, "record_number", r->record_number);
-               ndr_print_time_t(ndr, "time_generated", r->time_generated);
-               ndr_print_time_t(ndr, "time_written", r->time_written);
-               ndr_print_uint32(ndr, "event_id", r->event_id);
-               ndr_print_eventlogEventTypes(ndr, "event_type", r->event_type);
-               ndr_print_uint16(ndr, "num_of_strings", r->num_of_strings);
-               ndr_print_uint16(ndr, "event_category", r->event_category);
-               ndr_print_uint16(ndr, "reserved_flags", r->reserved_flags);
-               ndr_print_uint32(ndr, "closing_record_number", r->closing_record_number);
-               ndr_print_uint32(ndr, "stringoffset", r->stringoffset);
-               ndr_print_uint32(ndr, "sid_size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?ndr_size_dom_sid0(&r->sid, ndr->flags):r->sid_size);
-               ndr_print_uint32(ndr, "sid_offset", r->sid_offset);
-               ndr_print_uint32(ndr, "data_length", r->data_length);
-               ndr_print_uint32(ndr, "data_offset", r->data_offset);
-               ndr_print_string(ndr, "source_name", r->source_name);
-               ndr_print_string(ndr, "computer_name", r->computer_name);
-               ndr_print_dom_sid0(ndr, "sid", &r->sid);
-               ndr->print(ndr, "%s: ARRAY(%d)", "strings", (int)r->num_of_strings);
-               ndr->depth++;
-               for (cntr_strings_0=0;cntr_strings_0<r->num_of_strings;cntr_strings_0++) {
-                       char *idx_0=NULL;
-                       if (asprintf(&idx_0, "[%d]", cntr_strings_0) != -1) {
-                               ndr_print_string(ndr, "strings", r->strings[cntr_strings_0]);
-                               free(idx_0);
-                       }
-               }
-               ndr->depth--;
-               ndr_print_string(ndr, "raw_data", r->raw_data);
-               ndr_print_DATA_BLOB(ndr, "_padding", r->_padding);
-               ndr_print_uint32(ndr, "size2", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?r->size:r->size2);
-               ndr->depth--;
-               ndr->flags = _flags_save_STRUCT;
-       }
-}
-
 _PUBLIC_ enum ndr_err_code ndr_push_eventlog_Record_tdb(struct ndr_push *ndr, int ndr_flags, const struct eventlog_Record_tdb *r)
 {
        uint32_t cntr_strings_0;
@@ -2589,7 +2394,7 @@ _PUBLIC_ void ndr_print_eventlog_WriteClusterEvents(struct ndr_print *ndr, const
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_eventlog_GetLogIntormation(struct ndr_push *ndr, int flags, const struct eventlog_GetLogIntormation *r)
+static enum ndr_err_code ndr_push_eventlog_GetLogInformation(struct ndr_push *ndr, int flags, const struct eventlog_GetLogInformation *r)
 {
        if (flags & NDR_IN) {
                if (r->in.handle == NULL) {
@@ -2614,7 +2419,7 @@ static enum ndr_err_code ndr_push_eventlog_GetLogIntormation(struct ndr_push *nd
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_eventlog_GetLogIntormation(struct ndr_pull *ndr, int flags, struct eventlog_GetLogIntormation *r)
+static enum ndr_err_code ndr_pull_eventlog_GetLogInformation(struct ndr_pull *ndr, int flags, struct eventlog_GetLogInformation *r)
 {
        TALLOC_CTX *_mem_save_handle_0;
        TALLOC_CTX *_mem_save_bytes_needed_0;
@@ -2659,15 +2464,15 @@ static enum ndr_err_code ndr_pull_eventlog_GetLogIntormation(struct ndr_pull *nd
        return NDR_ERR_SUCCESS;
 }
 
-_PUBLIC_ void ndr_print_eventlog_GetLogIntormation(struct ndr_print *ndr, const char *name, int flags, const struct eventlog_GetLogIntormation *r)
+_PUBLIC_ void ndr_print_eventlog_GetLogInformation(struct ndr_print *ndr, const char *name, int flags, const struct eventlog_GetLogInformation *r)
 {
-       ndr_print_struct(ndr, name, "eventlog_GetLogIntormation");
+       ndr_print_struct(ndr, name, "eventlog_GetLogInformation");
        ndr->depth++;
        if (flags & NDR_SET_VALUES) {
                ndr->flags |= LIBNDR_PRINT_SET_VALUES;
        }
        if (flags & NDR_IN) {
-               ndr_print_struct(ndr, "in", "eventlog_GetLogIntormation");
+               ndr_print_struct(ndr, "in", "eventlog_GetLogInformation");
                ndr->depth++;
                ndr_print_ptr(ndr, "handle", r->in.handle);
                ndr->depth++;
@@ -2678,7 +2483,7 @@ _PUBLIC_ void ndr_print_eventlog_GetLogIntormation(struct ndr_print *ndr, const
                ndr->depth--;
        }
        if (flags & NDR_OUT) {
-               ndr_print_struct(ndr, "out", "eventlog_GetLogIntormation");
+               ndr_print_struct(ndr, "out", "eventlog_GetLogInformation");
                ndr->depth++;
                ndr_print_ptr(ndr, "buffer", r->out.buffer);
                ndr->depth++;
@@ -3267,11 +3072,11 @@ static const struct ndr_interface_call eventlog_calls[] = {
                false,
        },
        {
-               "eventlog_GetLogIntormation",
-               sizeof(struct eventlog_GetLogIntormation),
-               (ndr_push_flags_fn_t) ndr_push_eventlog_GetLogIntormation,
-               (ndr_pull_flags_fn_t) ndr_pull_eventlog_GetLogIntormation,
-               (ndr_print_function_t) ndr_print_eventlog_GetLogIntormation,
+               "eventlog_GetLogInformation",
+               sizeof(struct eventlog_GetLogInformation),
+               (ndr_push_flags_fn_t) ndr_push_eventlog_GetLogInformation,
+               (ndr_pull_flags_fn_t) ndr_pull_eventlog_GetLogInformation,
+               (ndr_print_function_t) ndr_print_eventlog_GetLogInformation,
                false,
        },
        {
index 34e6e09637c38f4c85e11c64f651ab9142f38c83..39f5f1bbc8ca3479bef805cc15e3e9b153b3f409 100644 (file)
@@ -55,7 +55,7 @@ extern const struct ndr_interface_table ndr_table_eventlog;
 
 #define NDR_EVENTLOG_WRITECLUSTEREVENTS (0x15)
 
-#define NDR_EVENTLOG_GETLOGINTORMATION (0x16)
+#define NDR_EVENTLOG_GETLOGINFORMATION (0x16)
 
 #define NDR_EVENTLOG_FLUSHEVENTLOG (0x17)
 
@@ -67,9 +67,6 @@ enum ndr_err_code ndr_push_eventlogEventTypes(struct ndr_push *ndr, int ndr_flag
 enum ndr_err_code ndr_pull_eventlogEventTypes(struct ndr_pull *ndr, int ndr_flags, enum eventlogEventTypes *r);
 void ndr_print_eventlogEventTypes(struct ndr_print *ndr, const char *name, enum eventlogEventTypes r);
 void ndr_print_eventlog_OpenUnknown0(struct ndr_print *ndr, const char *name, const struct eventlog_OpenUnknown0 *r);
-enum ndr_err_code ndr_push_eventlog_Record(struct ndr_push *ndr, int ndr_flags, const struct eventlog_Record *r);
-enum ndr_err_code ndr_pull_eventlog_Record(struct ndr_pull *ndr, int ndr_flags, struct eventlog_Record *r);
-void ndr_print_eventlog_Record(struct ndr_print *ndr, const char *name, const struct eventlog_Record *r);
 enum ndr_err_code ndr_push_eventlog_Record_tdb(struct ndr_push *ndr, int ndr_flags, const struct eventlog_Record_tdb *r);
 enum ndr_err_code ndr_pull_eventlog_Record_tdb(struct ndr_pull *ndr, int ndr_flags, struct eventlog_Record_tdb *r);
 void ndr_print_eventlog_Record_tdb(struct ndr_print *ndr, const char *name, const struct eventlog_Record_tdb *r);
@@ -109,7 +106,7 @@ void ndr_print_eventlog_ReportEventA(struct ndr_print *ndr, const char *name, in
 void ndr_print_eventlog_RegisterClusterSvc(struct ndr_print *ndr, const char *name, int flags, const struct eventlog_RegisterClusterSvc *r);
 void ndr_print_eventlog_DeregisterClusterSvc(struct ndr_print *ndr, const char *name, int flags, const struct eventlog_DeregisterClusterSvc *r);
 void ndr_print_eventlog_WriteClusterEvents(struct ndr_print *ndr, const char *name, int flags, const struct eventlog_WriteClusterEvents *r);
-void ndr_print_eventlog_GetLogIntormation(struct ndr_print *ndr, const char *name, int flags, const struct eventlog_GetLogIntormation *r);
+void ndr_print_eventlog_GetLogInformation(struct ndr_print *ndr, const char *name, int flags, const struct eventlog_GetLogInformation *r);
 void ndr_print_eventlog_FlushEventLog(struct ndr_print *ndr, const char *name, int flags, const struct eventlog_FlushEventLog *r);
 void ndr_print_eventlog_ReportEventAndSourceW(struct ndr_print *ndr, const char *name, int flags, const struct eventlog_ReportEventAndSourceW *r);
 #endif /* _HEADER_NDR_eventlog */
index 9ec3f35930a88a9a10a50aa50303e945d801c0ca..31220edc6223e25ec63ecff77578c5817441dd13 100644 (file)
@@ -2520,6 +2520,40 @@ _PUBLIC_ void ndr_print_spoolss_DevmodeContainer(struct ndr_print *ndr, const ch
        ndr->depth--;
 }
 
+static enum ndr_err_code ndr_push_spoolss_JobStatus(struct ndr_push *ndr, int ndr_flags, uint32_t r)
+{
+       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_JobStatus(struct ndr_pull *ndr, int ndr_flags, uint32_t *r)
+{
+       uint32_t v;
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+       *r = v;
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_JobStatus(struct ndr_print *ndr, const char *name, uint32_t r)
+{
+       ndr_print_uint32(ndr, name, r);
+       ndr->depth++;
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_PAUSED", JOB_STATUS_PAUSED, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_ERROR", JOB_STATUS_ERROR, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_DELETING", JOB_STATUS_DELETING, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_SPOOLING", JOB_STATUS_SPOOLING, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_PRINTING", JOB_STATUS_PRINTING, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_OFFLINE", JOB_STATUS_OFFLINE, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_PAPEROUT", JOB_STATUS_PAPEROUT, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_PRINTED", JOB_STATUS_PRINTED, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_DELETED", JOB_STATUS_DELETED, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_BLOCKED_DEVQ", JOB_STATUS_BLOCKED_DEVQ, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_USER_INTERVENTION", JOB_STATUS_USER_INTERVENTION, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_RESTART", JOB_STATUS_RESTART, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_STATUS_COMPLETE", JOB_STATUS_COMPLETE, r);
+       ndr->depth--;
+}
+
 static enum ndr_err_code ndr_push_spoolss_JobInfo1(struct ndr_push *ndr, int ndr_flags, const struct spoolss_JobInfo1 *r)
 {
        if (ndr_flags & NDR_SCALARS) {
@@ -2561,12 +2595,12 @@ static enum ndr_err_code ndr_push_spoolss_JobInfo1(struct ndr_push *ndr, int ndr
                        NDR_CHECK(ndr_push_relative_ptr1(ndr, r->text_status));
                        ndr->flags = _flags_save_string;
                }
-               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->status));
+               NDR_CHECK(ndr_push_spoolss_JobStatus(ndr, NDR_SCALARS, r->status));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->priority));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->position));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->total_pages));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->pages_printed));
-               NDR_CHECK(ndr_push_spoolss_Time(ndr, NDR_SCALARS, &r->time));
+               NDR_CHECK(ndr_push_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
        }
        if (ndr_flags & NDR_BUFFERS) {
                {
@@ -2716,12 +2750,12 @@ static enum ndr_err_code ndr_pull_spoolss_JobInfo1(struct ndr_pull *ndr, int ndr
                        }
                        ndr->flags = _flags_save_string;
                }
-               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->status));
+               NDR_CHECK(ndr_pull_spoolss_JobStatus(ndr, NDR_SCALARS, &r->status));
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->priority));
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->position));
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->total_pages));
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->pages_printed));
-               NDR_CHECK(ndr_pull_spoolss_Time(ndr, NDR_SCALARS, &r->time));
+               NDR_CHECK(ndr_pull_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
        }
        if (ndr_flags & NDR_BUFFERS) {
                {
@@ -2859,78 +2893,2593 @@ _PUBLIC_ void ndr_print_spoolss_JobInfo1(struct ndr_print *ndr, const char *name
                ndr_print_string(ndr, "text_status", r->text_status);
        }
        ndr->depth--;
-       ndr_print_uint32(ndr, "status", r->status);
+       ndr_print_spoolss_JobStatus(ndr, "status", r->status);
        ndr_print_uint32(ndr, "priority", r->priority);
        ndr_print_uint32(ndr, "position", r->position);
        ndr_print_uint32(ndr, "total_pages", r->total_pages);
        ndr_print_uint32(ndr, "pages_printed", r->pages_printed);
-       ndr_print_spoolss_Time(ndr, "time", &r->time);
+       ndr_print_spoolss_Time(ndr, "submitted", &r->submitted);
        ndr->depth--;
 }
 
-_PUBLIC_ enum ndr_err_code ndr_push_spoolss_JobInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_JobInfo *r)
+static enum ndr_err_code ndr_push_spoolss_JobInfo2(struct ndr_push *ndr, int ndr_flags, const struct spoolss_JobInfo2 *r)
 {
-       uint32_t _save_relative_base_offset = ndr_push_get_relative_base_offset(ndr);
        if (ndr_flags & NDR_SCALARS) {
-               int level = ndr_push_get_switch_value(ndr, r);
-               switch (level) {
-                       case 1: {
-                               NDR_CHECK(ndr_push_align(ndr, 4));
-                               NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));
-                               NDR_CHECK(ndr_push_spoolss_JobInfo1(ndr, NDR_SCALARS, &r->info1));
-                       break; }
-
-                       case 2: {
-                       break; }
-
-                       case 3: {
-                       break; }
-
-                       default: {
-                       break; }
-
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->job_id));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->printer_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->server_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->user_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->document_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->notify_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->data_type));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->print_processor));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->parameters));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->driver_name));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_relative_ptr1(ndr, r->devmode));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->text_status));
+                       ndr->flags = _flags_save_string;
                }
+               NDR_CHECK(ndr_push_relative_ptr1(ndr, r->secdesc));
+               NDR_CHECK(ndr_push_spoolss_JobStatus(ndr, NDR_SCALARS, r->status));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->priority));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->position));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->start_time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->until_time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->total_pages));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size));
+               NDR_CHECK(ndr_push_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->pages_printed));
        }
        if (ndr_flags & NDR_BUFFERS) {
-               int level = ndr_push_get_switch_value(ndr, r);
-               NDR_CHECK(ndr_push_setup_relative_base_offset2(ndr, r));
-               switch (level) {
-                       case 1:
-                               NDR_CHECK(ndr_push_spoolss_JobInfo1(ndr, NDR_BUFFERS, &r->info1));
-                       break;
-
-                       case 2:
-                       break;
-
-                       case 3:
-                       break;
-
-                       default:
-                       break;
-
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->printer_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->printer_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->printer_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->server_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->server_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->server_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->user_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->user_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->user_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->document_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->document_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->document_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->notify_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->notify_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->notify_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->data_type) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->data_type));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->data_type));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->print_processor) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->print_processor));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->print_processor));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->parameters) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->parameters));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->parameters));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->driver_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->driver_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->driver_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->devmode) {
+                       NDR_CHECK(ndr_push_relative_ptr2(ndr, r->devmode));
+                       NDR_CHECK(ndr_push_spoolss_DeviceMode(ndr, NDR_SCALARS, r->devmode));
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->text_status) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->text_status));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->text_status));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->secdesc) {
+                       NDR_CHECK(ndr_push_relative_ptr2(ndr, r->secdesc));
+                       NDR_CHECK(ndr_push_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
                }
        }
-       ndr_push_restore_relative_base_offset(ndr, _save_relative_base_offset);
        return NDR_ERR_SUCCESS;
 }
 
-_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_JobInfo(struct ndr_pull *ndr, int ndr_flags, union spoolss_JobInfo *r)
+static enum ndr_err_code ndr_pull_spoolss_JobInfo2(struct ndr_pull *ndr, int ndr_flags, struct spoolss_JobInfo2 *r)
 {
-       uint32_t _save_relative_base_offset = ndr_pull_get_relative_base_offset(ndr);
-       int level;
-       level = ndr_pull_get_switch_value(ndr, r);
+       uint32_t _ptr_printer_name;
+       TALLOC_CTX *_mem_save_printer_name_0;
+       uint32_t _ptr_server_name;
+       TALLOC_CTX *_mem_save_server_name_0;
+       uint32_t _ptr_user_name;
+       TALLOC_CTX *_mem_save_user_name_0;
+       uint32_t _ptr_document_name;
+       TALLOC_CTX *_mem_save_document_name_0;
+       uint32_t _ptr_notify_name;
+       TALLOC_CTX *_mem_save_notify_name_0;
+       uint32_t _ptr_data_type;
+       TALLOC_CTX *_mem_save_data_type_0;
+       uint32_t _ptr_print_processor;
+       TALLOC_CTX *_mem_save_print_processor_0;
+       uint32_t _ptr_parameters;
+       TALLOC_CTX *_mem_save_parameters_0;
+       uint32_t _ptr_driver_name;
+       TALLOC_CTX *_mem_save_driver_name_0;
+       uint32_t _ptr_devmode;
+       TALLOC_CTX *_mem_save_devmode_0;
+       uint32_t _ptr_text_status;
+       TALLOC_CTX *_mem_save_text_status_0;
+       uint32_t _ptr_secdesc;
+       TALLOC_CTX *_mem_save_secdesc_0;
        if (ndr_flags & NDR_SCALARS) {
-               switch (level) {
-                       case 1: {
-                               NDR_CHECK(ndr_pull_align(ndr, 4));
-                               NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
-                               NDR_CHECK(ndr_pull_spoolss_JobInfo1(ndr, NDR_SCALARS, &r->info1));
-                       break; }
-
-                       case 2: {
-                       break; }
-
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->job_id));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_printer_name));
+                       if (_ptr_printer_name) {
+                               NDR_PULL_ALLOC(ndr, r->printer_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->printer_name, _ptr_printer_name));
+                       } else {
+                               r->printer_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+                       if (_ptr_server_name) {
+                               NDR_PULL_ALLOC(ndr, r->server_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->server_name, _ptr_server_name));
+                       } else {
+                               r->server_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user_name));
+                       if (_ptr_user_name) {
+                               NDR_PULL_ALLOC(ndr, r->user_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->user_name, _ptr_user_name));
+                       } else {
+                               r->user_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_document_name));
+                       if (_ptr_document_name) {
+                               NDR_PULL_ALLOC(ndr, r->document_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->document_name, _ptr_document_name));
+                       } else {
+                               r->document_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_notify_name));
+                       if (_ptr_notify_name) {
+                               NDR_PULL_ALLOC(ndr, r->notify_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->notify_name, _ptr_notify_name));
+                       } else {
+                               r->notify_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_data_type));
+                       if (_ptr_data_type) {
+                               NDR_PULL_ALLOC(ndr, r->data_type);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->data_type, _ptr_data_type));
+                       } else {
+                               r->data_type = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_print_processor));
+                       if (_ptr_print_processor) {
+                               NDR_PULL_ALLOC(ndr, r->print_processor);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->print_processor, _ptr_print_processor));
+                       } else {
+                               r->print_processor = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_parameters));
+                       if (_ptr_parameters) {
+                               NDR_PULL_ALLOC(ndr, r->parameters);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->parameters, _ptr_parameters));
+                       } else {
+                               r->parameters = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_driver_name));
+                       if (_ptr_driver_name) {
+                               NDR_PULL_ALLOC(ndr, r->driver_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->driver_name, _ptr_driver_name));
+                       } else {
+                               r->driver_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_devmode));
+               if (_ptr_devmode) {
+                       NDR_PULL_ALLOC(ndr, r->devmode);
+                       NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->devmode, _ptr_devmode));
+               } else {
+                       r->devmode = NULL;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_text_status));
+                       if (_ptr_text_status) {
+                               NDR_PULL_ALLOC(ndr, r->text_status);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->text_status, _ptr_text_status));
+                       } else {
+                               r->text_status = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_secdesc));
+               if (_ptr_secdesc) {
+                       NDR_PULL_ALLOC(ndr, r->secdesc);
+                       NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->secdesc, _ptr_secdesc));
+               } else {
+                       r->secdesc = NULL;
+               }
+               NDR_CHECK(ndr_pull_spoolss_JobStatus(ndr, NDR_SCALARS, &r->status));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->priority));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->position));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->start_time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->until_time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->total_pages));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->size));
+               NDR_CHECK(ndr_pull_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->pages_printed));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->printer_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->printer_name));
+                               _mem_save_printer_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->printer_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->printer_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_printer_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->server_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->server_name));
+                               _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->server_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->server_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->user_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->user_name));
+                               _mem_save_user_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->user_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->user_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->document_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->document_name));
+                               _mem_save_document_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->document_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->document_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_document_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->notify_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->notify_name));
+                               _mem_save_notify_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->notify_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->notify_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_notify_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->data_type) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->data_type));
+                               _mem_save_data_type_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->data_type, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->data_type));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_data_type_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->print_processor) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->print_processor));
+                               _mem_save_print_processor_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->print_processor, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->print_processor));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_print_processor_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->parameters) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->parameters));
+                               _mem_save_parameters_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->parameters, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->parameters));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_parameters_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->driver_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->driver_name));
+                               _mem_save_driver_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->driver_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->driver_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_driver_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->devmode) {
+                       uint32_t _relative_save_offset;
+                       _relative_save_offset = ndr->offset;
+                       NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->devmode));
+                       _mem_save_devmode_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->devmode, 0);
+                       NDR_CHECK(ndr_pull_spoolss_DeviceMode(ndr, NDR_SCALARS, r->devmode));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_devmode_0, 0);
+                       ndr->offset = _relative_save_offset;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->text_status) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->text_status));
+                               _mem_save_text_status_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->text_status, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->text_status));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_text_status_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->secdesc) {
+                       uint32_t _relative_save_offset;
+                       _relative_save_offset = ndr->offset;
+                       NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->secdesc));
+                       _mem_save_secdesc_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->secdesc, 0);
+                       NDR_CHECK(ndr_pull_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_secdesc_0, 0);
+                       ndr->offset = _relative_save_offset;
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_JobInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_JobInfo2 *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_JobInfo2");
+       ndr->depth++;
+       ndr_print_uint32(ndr, "job_id", r->job_id);
+       ndr_print_ptr(ndr, "printer_name", r->printer_name);
+       ndr->depth++;
+       if (r->printer_name) {
+               ndr_print_string(ndr, "printer_name", r->printer_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "server_name", r->server_name);
+       ndr->depth++;
+       if (r->server_name) {
+               ndr_print_string(ndr, "server_name", r->server_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "user_name", r->user_name);
+       ndr->depth++;
+       if (r->user_name) {
+               ndr_print_string(ndr, "user_name", r->user_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "document_name", r->document_name);
+       ndr->depth++;
+       if (r->document_name) {
+               ndr_print_string(ndr, "document_name", r->document_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "notify_name", r->notify_name);
+       ndr->depth++;
+       if (r->notify_name) {
+               ndr_print_string(ndr, "notify_name", r->notify_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "data_type", r->data_type);
+       ndr->depth++;
+       if (r->data_type) {
+               ndr_print_string(ndr, "data_type", r->data_type);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "print_processor", r->print_processor);
+       ndr->depth++;
+       if (r->print_processor) {
+               ndr_print_string(ndr, "print_processor", r->print_processor);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "parameters", r->parameters);
+       ndr->depth++;
+       if (r->parameters) {
+               ndr_print_string(ndr, "parameters", r->parameters);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "driver_name", r->driver_name);
+       ndr->depth++;
+       if (r->driver_name) {
+               ndr_print_string(ndr, "driver_name", r->driver_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "devmode", r->devmode);
+       ndr->depth++;
+       if (r->devmode) {
+               ndr_print_spoolss_DeviceMode(ndr, "devmode", r->devmode);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "text_status", r->text_status);
+       ndr->depth++;
+       if (r->text_status) {
+               ndr_print_string(ndr, "text_status", r->text_status);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "secdesc", r->secdesc);
+       ndr->depth++;
+       if (r->secdesc) {
+               ndr_print_security_descriptor(ndr, "secdesc", r->secdesc);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_JobStatus(ndr, "status", r->status);
+       ndr_print_uint32(ndr, "priority", r->priority);
+       ndr_print_uint32(ndr, "position", r->position);
+       ndr_print_uint32(ndr, "start_time", r->start_time);
+       ndr_print_uint32(ndr, "until_time", r->until_time);
+       ndr_print_uint32(ndr, "total_pages", r->total_pages);
+       ndr_print_uint32(ndr, "size", r->size);
+       ndr_print_spoolss_Time(ndr, "submitted", &r->submitted);
+       ndr_print_uint32(ndr, "time", r->time);
+       ndr_print_uint32(ndr, "pages_printed", r->pages_printed);
+       ndr->depth--;
+}
+
+static enum ndr_err_code ndr_push_spoolss_JobInfo3(struct ndr_push *ndr, int ndr_flags, const struct spoolss_JobInfo3 *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->job_id));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->next_job_id));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->reserved));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_JobInfo3(struct ndr_pull *ndr, int ndr_flags, struct spoolss_JobInfo3 *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->job_id));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->next_job_id));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->reserved));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_JobInfo3(struct ndr_print *ndr, const char *name, const struct spoolss_JobInfo3 *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_JobInfo3");
+       ndr->depth++;
+       ndr_print_uint32(ndr, "job_id", r->job_id);
+       ndr_print_uint32(ndr, "next_job_id", r->next_job_id);
+       ndr_print_uint32(ndr, "reserved", r->reserved);
+       ndr->depth--;
+}
+
+static enum ndr_err_code ndr_push_spoolss_JobInfo4(struct ndr_push *ndr, int ndr_flags, const struct spoolss_JobInfo4 *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->job_id));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->printer_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->server_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->user_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->document_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->notify_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->data_type));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->print_processor));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->parameters));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->driver_name));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_relative_ptr1(ndr, r->devmode));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->text_status));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_relative_ptr1(ndr, r->secdesc));
+               NDR_CHECK(ndr_push_spoolss_JobStatus(ndr, NDR_SCALARS, r->status));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->priority));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->position));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->start_time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->until_time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->total_pages));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size));
+               NDR_CHECK(ndr_push_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->pages_printed));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size_high));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->printer_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->printer_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->printer_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->server_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->server_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->server_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->user_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->user_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->user_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->document_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->document_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->document_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->notify_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->notify_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->notify_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->data_type) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->data_type));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->data_type));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->print_processor) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->print_processor));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->print_processor));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->parameters) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->parameters));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->parameters));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->driver_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->driver_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->driver_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->devmode) {
+                       NDR_CHECK(ndr_push_relative_ptr2(ndr, r->devmode));
+                       NDR_CHECK(ndr_push_spoolss_DeviceMode(ndr, NDR_SCALARS, r->devmode));
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->text_status) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->text_status));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->text_status));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->secdesc) {
+                       NDR_CHECK(ndr_push_relative_ptr2(ndr, r->secdesc));
+                       NDR_CHECK(ndr_push_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_JobInfo4(struct ndr_pull *ndr, int ndr_flags, struct spoolss_JobInfo4 *r)
+{
+       uint32_t _ptr_printer_name;
+       TALLOC_CTX *_mem_save_printer_name_0;
+       uint32_t _ptr_server_name;
+       TALLOC_CTX *_mem_save_server_name_0;
+       uint32_t _ptr_user_name;
+       TALLOC_CTX *_mem_save_user_name_0;
+       uint32_t _ptr_document_name;
+       TALLOC_CTX *_mem_save_document_name_0;
+       uint32_t _ptr_notify_name;
+       TALLOC_CTX *_mem_save_notify_name_0;
+       uint32_t _ptr_data_type;
+       TALLOC_CTX *_mem_save_data_type_0;
+       uint32_t _ptr_print_processor;
+       TALLOC_CTX *_mem_save_print_processor_0;
+       uint32_t _ptr_parameters;
+       TALLOC_CTX *_mem_save_parameters_0;
+       uint32_t _ptr_driver_name;
+       TALLOC_CTX *_mem_save_driver_name_0;
+       uint32_t _ptr_devmode;
+       TALLOC_CTX *_mem_save_devmode_0;
+       uint32_t _ptr_text_status;
+       TALLOC_CTX *_mem_save_text_status_0;
+       uint32_t _ptr_secdesc;
+       TALLOC_CTX *_mem_save_secdesc_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->job_id));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_printer_name));
+                       if (_ptr_printer_name) {
+                               NDR_PULL_ALLOC(ndr, r->printer_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->printer_name, _ptr_printer_name));
+                       } else {
+                               r->printer_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+                       if (_ptr_server_name) {
+                               NDR_PULL_ALLOC(ndr, r->server_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->server_name, _ptr_server_name));
+                       } else {
+                               r->server_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user_name));
+                       if (_ptr_user_name) {
+                               NDR_PULL_ALLOC(ndr, r->user_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->user_name, _ptr_user_name));
+                       } else {
+                               r->user_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_document_name));
+                       if (_ptr_document_name) {
+                               NDR_PULL_ALLOC(ndr, r->document_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->document_name, _ptr_document_name));
+                       } else {
+                               r->document_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_notify_name));
+                       if (_ptr_notify_name) {
+                               NDR_PULL_ALLOC(ndr, r->notify_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->notify_name, _ptr_notify_name));
+                       } else {
+                               r->notify_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_data_type));
+                       if (_ptr_data_type) {
+                               NDR_PULL_ALLOC(ndr, r->data_type);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->data_type, _ptr_data_type));
+                       } else {
+                               r->data_type = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_print_processor));
+                       if (_ptr_print_processor) {
+                               NDR_PULL_ALLOC(ndr, r->print_processor);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->print_processor, _ptr_print_processor));
+                       } else {
+                               r->print_processor = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_parameters));
+                       if (_ptr_parameters) {
+                               NDR_PULL_ALLOC(ndr, r->parameters);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->parameters, _ptr_parameters));
+                       } else {
+                               r->parameters = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_driver_name));
+                       if (_ptr_driver_name) {
+                               NDR_PULL_ALLOC(ndr, r->driver_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->driver_name, _ptr_driver_name));
+                       } else {
+                               r->driver_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_devmode));
+               if (_ptr_devmode) {
+                       NDR_PULL_ALLOC(ndr, r->devmode);
+                       NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->devmode, _ptr_devmode));
+               } else {
+                       r->devmode = NULL;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_text_status));
+                       if (_ptr_text_status) {
+                               NDR_PULL_ALLOC(ndr, r->text_status);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->text_status, _ptr_text_status));
+                       } else {
+                               r->text_status = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_secdesc));
+               if (_ptr_secdesc) {
+                       NDR_PULL_ALLOC(ndr, r->secdesc);
+                       NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->secdesc, _ptr_secdesc));
+               } else {
+                       r->secdesc = NULL;
+               }
+               NDR_CHECK(ndr_pull_spoolss_JobStatus(ndr, NDR_SCALARS, &r->status));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->priority));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->position));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->start_time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->until_time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->total_pages));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->size));
+               NDR_CHECK(ndr_pull_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->pages_printed));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->size_high));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->printer_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->printer_name));
+                               _mem_save_printer_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->printer_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->printer_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_printer_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->server_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->server_name));
+                               _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->server_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->server_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->user_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->user_name));
+                               _mem_save_user_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->user_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->user_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->document_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->document_name));
+                               _mem_save_document_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->document_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->document_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_document_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->notify_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->notify_name));
+                               _mem_save_notify_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->notify_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->notify_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_notify_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->data_type) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->data_type));
+                               _mem_save_data_type_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->data_type, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->data_type));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_data_type_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->print_processor) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->print_processor));
+                               _mem_save_print_processor_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->print_processor, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->print_processor));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_print_processor_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->parameters) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->parameters));
+                               _mem_save_parameters_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->parameters, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->parameters));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_parameters_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->driver_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->driver_name));
+                               _mem_save_driver_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->driver_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->driver_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_driver_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->devmode) {
+                       uint32_t _relative_save_offset;
+                       _relative_save_offset = ndr->offset;
+                       NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->devmode));
+                       _mem_save_devmode_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->devmode, 0);
+                       NDR_CHECK(ndr_pull_spoolss_DeviceMode(ndr, NDR_SCALARS, r->devmode));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_devmode_0, 0);
+                       ndr->offset = _relative_save_offset;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->text_status) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->text_status));
+                               _mem_save_text_status_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->text_status, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->text_status));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_text_status_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->secdesc) {
+                       uint32_t _relative_save_offset;
+                       _relative_save_offset = ndr->offset;
+                       NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->secdesc));
+                       _mem_save_secdesc_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->secdesc, 0);
+                       NDR_CHECK(ndr_pull_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_secdesc_0, 0);
+                       ndr->offset = _relative_save_offset;
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_JobInfo4(struct ndr_print *ndr, const char *name, const struct spoolss_JobInfo4 *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_JobInfo4");
+       ndr->depth++;
+       ndr_print_uint32(ndr, "job_id", r->job_id);
+       ndr_print_ptr(ndr, "printer_name", r->printer_name);
+       ndr->depth++;
+       if (r->printer_name) {
+               ndr_print_string(ndr, "printer_name", r->printer_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "server_name", r->server_name);
+       ndr->depth++;
+       if (r->server_name) {
+               ndr_print_string(ndr, "server_name", r->server_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "user_name", r->user_name);
+       ndr->depth++;
+       if (r->user_name) {
+               ndr_print_string(ndr, "user_name", r->user_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "document_name", r->document_name);
+       ndr->depth++;
+       if (r->document_name) {
+               ndr_print_string(ndr, "document_name", r->document_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "notify_name", r->notify_name);
+       ndr->depth++;
+       if (r->notify_name) {
+               ndr_print_string(ndr, "notify_name", r->notify_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "data_type", r->data_type);
+       ndr->depth++;
+       if (r->data_type) {
+               ndr_print_string(ndr, "data_type", r->data_type);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "print_processor", r->print_processor);
+       ndr->depth++;
+       if (r->print_processor) {
+               ndr_print_string(ndr, "print_processor", r->print_processor);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "parameters", r->parameters);
+       ndr->depth++;
+       if (r->parameters) {
+               ndr_print_string(ndr, "parameters", r->parameters);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "driver_name", r->driver_name);
+       ndr->depth++;
+       if (r->driver_name) {
+               ndr_print_string(ndr, "driver_name", r->driver_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "devmode", r->devmode);
+       ndr->depth++;
+       if (r->devmode) {
+               ndr_print_spoolss_DeviceMode(ndr, "devmode", r->devmode);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "text_status", r->text_status);
+       ndr->depth++;
+       if (r->text_status) {
+               ndr_print_string(ndr, "text_status", r->text_status);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "secdesc", r->secdesc);
+       ndr->depth++;
+       if (r->secdesc) {
+               ndr_print_security_descriptor(ndr, "secdesc", r->secdesc);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_JobStatus(ndr, "status", r->status);
+       ndr_print_uint32(ndr, "priority", r->priority);
+       ndr_print_uint32(ndr, "position", r->position);
+       ndr_print_uint32(ndr, "start_time", r->start_time);
+       ndr_print_uint32(ndr, "until_time", r->until_time);
+       ndr_print_uint32(ndr, "total_pages", r->total_pages);
+       ndr_print_uint32(ndr, "size", r->size);
+       ndr_print_spoolss_Time(ndr, "submitted", &r->submitted);
+       ndr_print_uint32(ndr, "time", r->time);
+       ndr_print_uint32(ndr, "pages_printed", r->pages_printed);
+       ndr_print_uint32(ndr, "size_high", r->size_high);
+       ndr->depth--;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_JobInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_JobInfo *r)
+{
+       uint32_t _save_relative_base_offset = ndr_push_get_relative_base_offset(ndr);
+       if (ndr_flags & NDR_SCALARS) {
+               int level = ndr_push_get_switch_value(ndr, r);
+               switch (level) {
+                       case 1: {
+                               NDR_CHECK(ndr_push_align(ndr, 4));
+                               NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_push_spoolss_JobInfo1(ndr, NDR_SCALARS, &r->info1));
+                       break; }
+
+                       case 2: {
+                               NDR_CHECK(ndr_push_align(ndr, 4));
+                               NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_push_spoolss_JobInfo2(ndr, NDR_SCALARS, &r->info2));
+                       break; }
+
+                       case 3: {
+                               NDR_CHECK(ndr_push_align(ndr, 4));
+                               NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_push_spoolss_JobInfo3(ndr, NDR_SCALARS, &r->info3));
+                       break; }
+
+                       case 4: {
+                               NDR_CHECK(ndr_push_align(ndr, 4));
+                               NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_push_spoolss_JobInfo4(ndr, NDR_SCALARS, &r->info4));
+                       break; }
+
+                       default: {
+                       break; }
+
+               }
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               int level = ndr_push_get_switch_value(ndr, r);
+               NDR_CHECK(ndr_push_setup_relative_base_offset2(ndr, r));
+               switch (level) {
+                       case 1:
+                               NDR_CHECK(ndr_push_spoolss_JobInfo1(ndr, NDR_BUFFERS, &r->info1));
+                       break;
+
+                       case 2:
+                               NDR_CHECK(ndr_push_spoolss_JobInfo2(ndr, NDR_BUFFERS, &r->info2));
+                       break;
+
+                       case 3:
+                       break;
+
+                       case 4:
+                               NDR_CHECK(ndr_push_spoolss_JobInfo4(ndr, NDR_BUFFERS, &r->info4));
+                       break;
+
+                       default:
+                       break;
+
+               }
+       }
+       ndr_push_restore_relative_base_offset(ndr, _save_relative_base_offset);
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_JobInfo(struct ndr_pull *ndr, int ndr_flags, union spoolss_JobInfo *r)
+{
+       uint32_t _save_relative_base_offset = ndr_pull_get_relative_base_offset(ndr);
+       int level;
+       level = ndr_pull_get_switch_value(ndr, r);
+       if (ndr_flags & NDR_SCALARS) {
+               switch (level) {
+                       case 1: {
+                               NDR_CHECK(ndr_pull_align(ndr, 4));
+                               NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_pull_spoolss_JobInfo1(ndr, NDR_SCALARS, &r->info1));
+                       break; }
+
+                       case 2: {
+                               NDR_CHECK(ndr_pull_align(ndr, 4));
+                               NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_pull_spoolss_JobInfo2(ndr, NDR_SCALARS, &r->info2));
+                       break; }
+
+                       case 3: {
+                               NDR_CHECK(ndr_pull_align(ndr, 4));
+                               NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_pull_spoolss_JobInfo3(ndr, NDR_SCALARS, &r->info3));
+                       break; }
+
+                       case 4: {
+                               NDR_CHECK(ndr_pull_align(ndr, 4));
+                               NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_pull_spoolss_JobInfo4(ndr, NDR_SCALARS, &r->info4));
+                       break; }
+
+                       default: {
+                       break; }
+
+               }
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               NDR_CHECK(ndr_pull_setup_relative_base_offset2(ndr, r));
+               switch (level) {
+                       case 1:
+                               NDR_CHECK(ndr_pull_spoolss_JobInfo1(ndr, NDR_BUFFERS, &r->info1));
+                       break;
+
+                       case 2:
+                               NDR_CHECK(ndr_pull_spoolss_JobInfo2(ndr, NDR_BUFFERS, &r->info2));
+                       break;
+
+                       case 3:
+                       break;
+
+                       case 4:
+                               NDR_CHECK(ndr_pull_spoolss_JobInfo4(ndr, NDR_BUFFERS, &r->info4));
+                       break;
+
+                       default:
+                       break;
+
+               }
+       }
+       ndr_pull_restore_relative_base_offset(ndr, _save_relative_base_offset);
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_JobInfo(struct ndr_print *ndr, const char *name, const union spoolss_JobInfo *r)
+{
+       int level;
+       level = ndr_print_get_switch_value(ndr, r);
+       ndr_print_union(ndr, name, level, "spoolss_JobInfo");
+       switch (level) {
+               case 1:
+                       ndr_print_spoolss_JobInfo1(ndr, "info1", &r->info1);
+               break;
+
+               case 2:
+                       ndr_print_spoolss_JobInfo2(ndr, "info2", &r->info2);
+               break;
+
+               case 3:
+                       ndr_print_spoolss_JobInfo3(ndr, "info3", &r->info3);
+               break;
+
+               case 4:
+                       ndr_print_spoolss_JobInfo4(ndr, "info4", &r->info4);
+               break;
+
+               default:
+               break;
+
+       }
+}
+
+static enum ndr_err_code ndr_push_spoolss_SetJobInfo1(struct ndr_push *ndr, int ndr_flags, const struct spoolss_SetJobInfo1 *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->job_id));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->printer_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->server_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->user_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->document_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->data_type));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->text_status));
+               NDR_CHECK(ndr_push_spoolss_JobStatus(ndr, NDR_SCALARS, r->status));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->priority));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->position));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->total_pages));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->pages_printed));
+               NDR_CHECK(ndr_push_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               if (r->printer_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->printer_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->printer_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->printer_name, ndr_charset_length(r->printer_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->server_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->server_name, ndr_charset_length(r->server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->user_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->user_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->user_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->user_name, ndr_charset_length(r->user_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->document_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->document_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->document_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->document_name, ndr_charset_length(r->document_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->data_type) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->data_type, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->data_type, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->data_type, ndr_charset_length(r->data_type, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->text_status) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->text_status, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->text_status, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->text_status, ndr_charset_length(r->text_status, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_SetJobInfo1(struct ndr_pull *ndr, int ndr_flags, struct spoolss_SetJobInfo1 *r)
+{
+       uint32_t _ptr_printer_name;
+       TALLOC_CTX *_mem_save_printer_name_0;
+       uint32_t _ptr_server_name;
+       TALLOC_CTX *_mem_save_server_name_0;
+       uint32_t _ptr_user_name;
+       TALLOC_CTX *_mem_save_user_name_0;
+       uint32_t _ptr_document_name;
+       TALLOC_CTX *_mem_save_document_name_0;
+       uint32_t _ptr_data_type;
+       TALLOC_CTX *_mem_save_data_type_0;
+       uint32_t _ptr_text_status;
+       TALLOC_CTX *_mem_save_text_status_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->job_id));
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_printer_name));
+               if (_ptr_printer_name) {
+                       NDR_PULL_ALLOC(ndr, r->printer_name);
+               } else {
+                       r->printer_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+               if (_ptr_server_name) {
+                       NDR_PULL_ALLOC(ndr, r->server_name);
+               } else {
+                       r->server_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user_name));
+               if (_ptr_user_name) {
+                       NDR_PULL_ALLOC(ndr, r->user_name);
+               } else {
+                       r->user_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_document_name));
+               if (_ptr_document_name) {
+                       NDR_PULL_ALLOC(ndr, r->document_name);
+               } else {
+                       r->document_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_data_type));
+               if (_ptr_data_type) {
+                       NDR_PULL_ALLOC(ndr, r->data_type);
+               } else {
+                       r->data_type = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_text_status));
+               if (_ptr_text_status) {
+                       NDR_PULL_ALLOC(ndr, r->text_status);
+               } else {
+                       r->text_status = NULL;
+               }
+               NDR_CHECK(ndr_pull_spoolss_JobStatus(ndr, NDR_SCALARS, &r->status));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->priority));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->position));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->total_pages));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->pages_printed));
+               NDR_CHECK(ndr_pull_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               if (r->printer_name) {
+                       _mem_save_printer_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->printer_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->printer_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->printer_name));
+                       if (ndr_get_array_length(ndr, &r->printer_name) > ndr_get_array_size(ndr, &r->printer_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->printer_name), ndr_get_array_length(ndr, &r->printer_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->printer_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->printer_name, ndr_get_array_length(ndr, &r->printer_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_printer_name_0, 0);
+               }
+               if (r->server_name) {
+                       _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->server_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->server_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->server_name));
+                       if (ndr_get_array_length(ndr, &r->server_name) > ndr_get_array_size(ndr, &r->server_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->server_name), ndr_get_array_length(ndr, &r->server_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->server_name, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+               }
+               if (r->user_name) {
+                       _mem_save_user_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->user_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->user_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->user_name));
+                       if (ndr_get_array_length(ndr, &r->user_name) > ndr_get_array_size(ndr, &r->user_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->user_name), ndr_get_array_length(ndr, &r->user_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->user_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->user_name, ndr_get_array_length(ndr, &r->user_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user_name_0, 0);
+               }
+               if (r->document_name) {
+                       _mem_save_document_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->document_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->document_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->document_name));
+                       if (ndr_get_array_length(ndr, &r->document_name) > ndr_get_array_size(ndr, &r->document_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->document_name), ndr_get_array_length(ndr, &r->document_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->document_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->document_name, ndr_get_array_length(ndr, &r->document_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_document_name_0, 0);
+               }
+               if (r->data_type) {
+                       _mem_save_data_type_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->data_type, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->data_type));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->data_type));
+                       if (ndr_get_array_length(ndr, &r->data_type) > ndr_get_array_size(ndr, &r->data_type)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->data_type), ndr_get_array_length(ndr, &r->data_type));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->data_type), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->data_type, ndr_get_array_length(ndr, &r->data_type), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_data_type_0, 0);
+               }
+               if (r->text_status) {
+                       _mem_save_text_status_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->text_status, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->text_status));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->text_status));
+                       if (ndr_get_array_length(ndr, &r->text_status) > ndr_get_array_size(ndr, &r->text_status)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->text_status), ndr_get_array_length(ndr, &r->text_status));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->text_status), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->text_status, ndr_get_array_length(ndr, &r->text_status), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_text_status_0, 0);
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_SetJobInfo1(struct ndr_print *ndr, const char *name, const struct spoolss_SetJobInfo1 *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_SetJobInfo1");
+       ndr->depth++;
+       ndr_print_uint32(ndr, "job_id", r->job_id);
+       ndr_print_ptr(ndr, "printer_name", r->printer_name);
+       ndr->depth++;
+       if (r->printer_name) {
+               ndr_print_string(ndr, "printer_name", r->printer_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "server_name", r->server_name);
+       ndr->depth++;
+       if (r->server_name) {
+               ndr_print_string(ndr, "server_name", r->server_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "user_name", r->user_name);
+       ndr->depth++;
+       if (r->user_name) {
+               ndr_print_string(ndr, "user_name", r->user_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "document_name", r->document_name);
+       ndr->depth++;
+       if (r->document_name) {
+               ndr_print_string(ndr, "document_name", r->document_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "data_type", r->data_type);
+       ndr->depth++;
+       if (r->data_type) {
+               ndr_print_string(ndr, "data_type", r->data_type);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "text_status", r->text_status);
+       ndr->depth++;
+       if (r->text_status) {
+               ndr_print_string(ndr, "text_status", r->text_status);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_JobStatus(ndr, "status", r->status);
+       ndr_print_uint32(ndr, "priority", r->priority);
+       ndr_print_uint32(ndr, "position", r->position);
+       ndr_print_uint32(ndr, "total_pages", r->total_pages);
+       ndr_print_uint32(ndr, "pages_printed", r->pages_printed);
+       ndr_print_spoolss_Time(ndr, "submitted", &r->submitted);
+       ndr->depth--;
+}
+
+static enum ndr_err_code ndr_push_spoolss_SetJobInfo2(struct ndr_push *ndr, int ndr_flags, const struct spoolss_SetJobInfo2 *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->job_id));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->printer_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->server_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->user_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->document_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->notify_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->data_type));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->print_processor));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->parameters));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->driver_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->devmode));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->text_status));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->secdesc));
+               NDR_CHECK(ndr_push_spoolss_JobStatus(ndr, NDR_SCALARS, r->status));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->priority));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->position));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->start_time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->until_time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->total_pages));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size));
+               NDR_CHECK(ndr_push_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->pages_printed));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               if (r->printer_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->printer_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->printer_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->printer_name, ndr_charset_length(r->printer_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->server_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->server_name, ndr_charset_length(r->server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->user_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->user_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->user_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->user_name, ndr_charset_length(r->user_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->document_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->document_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->document_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->document_name, ndr_charset_length(r->document_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->notify_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->notify_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->notify_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->notify_name, ndr_charset_length(r->notify_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->data_type) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->data_type, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->data_type, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->data_type, ndr_charset_length(r->data_type, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->print_processor) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->print_processor, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->print_processor, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->print_processor, ndr_charset_length(r->print_processor, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->parameters) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->parameters, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->parameters, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->parameters, ndr_charset_length(r->parameters, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->driver_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->driver_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->driver_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->driver_name, ndr_charset_length(r->driver_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->devmode) {
+                       NDR_CHECK(ndr_push_spoolss_DeviceMode(ndr, NDR_SCALARS, r->devmode));
+               }
+               if (r->text_status) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->text_status, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->text_status, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->text_status, ndr_charset_length(r->text_status, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->secdesc) {
+                       NDR_CHECK(ndr_push_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_SetJobInfo2(struct ndr_pull *ndr, int ndr_flags, struct spoolss_SetJobInfo2 *r)
+{
+       uint32_t _ptr_printer_name;
+       TALLOC_CTX *_mem_save_printer_name_0;
+       uint32_t _ptr_server_name;
+       TALLOC_CTX *_mem_save_server_name_0;
+       uint32_t _ptr_user_name;
+       TALLOC_CTX *_mem_save_user_name_0;
+       uint32_t _ptr_document_name;
+       TALLOC_CTX *_mem_save_document_name_0;
+       uint32_t _ptr_notify_name;
+       TALLOC_CTX *_mem_save_notify_name_0;
+       uint32_t _ptr_data_type;
+       TALLOC_CTX *_mem_save_data_type_0;
+       uint32_t _ptr_print_processor;
+       TALLOC_CTX *_mem_save_print_processor_0;
+       uint32_t _ptr_parameters;
+       TALLOC_CTX *_mem_save_parameters_0;
+       uint32_t _ptr_driver_name;
+       TALLOC_CTX *_mem_save_driver_name_0;
+       uint32_t _ptr_devmode;
+       TALLOC_CTX *_mem_save_devmode_0;
+       uint32_t _ptr_text_status;
+       TALLOC_CTX *_mem_save_text_status_0;
+       uint32_t _ptr_secdesc;
+       TALLOC_CTX *_mem_save_secdesc_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->job_id));
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_printer_name));
+               if (_ptr_printer_name) {
+                       NDR_PULL_ALLOC(ndr, r->printer_name);
+               } else {
+                       r->printer_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+               if (_ptr_server_name) {
+                       NDR_PULL_ALLOC(ndr, r->server_name);
+               } else {
+                       r->server_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user_name));
+               if (_ptr_user_name) {
+                       NDR_PULL_ALLOC(ndr, r->user_name);
+               } else {
+                       r->user_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_document_name));
+               if (_ptr_document_name) {
+                       NDR_PULL_ALLOC(ndr, r->document_name);
+               } else {
+                       r->document_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_notify_name));
+               if (_ptr_notify_name) {
+                       NDR_PULL_ALLOC(ndr, r->notify_name);
+               } else {
+                       r->notify_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_data_type));
+               if (_ptr_data_type) {
+                       NDR_PULL_ALLOC(ndr, r->data_type);
+               } else {
+                       r->data_type = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_print_processor));
+               if (_ptr_print_processor) {
+                       NDR_PULL_ALLOC(ndr, r->print_processor);
+               } else {
+                       r->print_processor = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_parameters));
+               if (_ptr_parameters) {
+                       NDR_PULL_ALLOC(ndr, r->parameters);
+               } else {
+                       r->parameters = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_driver_name));
+               if (_ptr_driver_name) {
+                       NDR_PULL_ALLOC(ndr, r->driver_name);
+               } else {
+                       r->driver_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_devmode));
+               if (_ptr_devmode) {
+                       NDR_PULL_ALLOC(ndr, r->devmode);
+               } else {
+                       r->devmode = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_text_status));
+               if (_ptr_text_status) {
+                       NDR_PULL_ALLOC(ndr, r->text_status);
+               } else {
+                       r->text_status = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_secdesc));
+               if (_ptr_secdesc) {
+                       NDR_PULL_ALLOC(ndr, r->secdesc);
+               } else {
+                       r->secdesc = NULL;
+               }
+               NDR_CHECK(ndr_pull_spoolss_JobStatus(ndr, NDR_SCALARS, &r->status));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->priority));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->position));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->start_time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->until_time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->total_pages));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->size));
+               NDR_CHECK(ndr_pull_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->pages_printed));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               if (r->printer_name) {
+                       _mem_save_printer_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->printer_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->printer_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->printer_name));
+                       if (ndr_get_array_length(ndr, &r->printer_name) > ndr_get_array_size(ndr, &r->printer_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->printer_name), ndr_get_array_length(ndr, &r->printer_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->printer_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->printer_name, ndr_get_array_length(ndr, &r->printer_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_printer_name_0, 0);
+               }
+               if (r->server_name) {
+                       _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->server_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->server_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->server_name));
+                       if (ndr_get_array_length(ndr, &r->server_name) > ndr_get_array_size(ndr, &r->server_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->server_name), ndr_get_array_length(ndr, &r->server_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->server_name, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+               }
+               if (r->user_name) {
+                       _mem_save_user_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->user_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->user_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->user_name));
+                       if (ndr_get_array_length(ndr, &r->user_name) > ndr_get_array_size(ndr, &r->user_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->user_name), ndr_get_array_length(ndr, &r->user_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->user_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->user_name, ndr_get_array_length(ndr, &r->user_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user_name_0, 0);
+               }
+               if (r->document_name) {
+                       _mem_save_document_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->document_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->document_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->document_name));
+                       if (ndr_get_array_length(ndr, &r->document_name) > ndr_get_array_size(ndr, &r->document_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->document_name), ndr_get_array_length(ndr, &r->document_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->document_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->document_name, ndr_get_array_length(ndr, &r->document_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_document_name_0, 0);
+               }
+               if (r->notify_name) {
+                       _mem_save_notify_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->notify_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->notify_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->notify_name));
+                       if (ndr_get_array_length(ndr, &r->notify_name) > ndr_get_array_size(ndr, &r->notify_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->notify_name), ndr_get_array_length(ndr, &r->notify_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->notify_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->notify_name, ndr_get_array_length(ndr, &r->notify_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_notify_name_0, 0);
+               }
+               if (r->data_type) {
+                       _mem_save_data_type_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->data_type, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->data_type));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->data_type));
+                       if (ndr_get_array_length(ndr, &r->data_type) > ndr_get_array_size(ndr, &r->data_type)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->data_type), ndr_get_array_length(ndr, &r->data_type));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->data_type), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->data_type, ndr_get_array_length(ndr, &r->data_type), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_data_type_0, 0);
+               }
+               if (r->print_processor) {
+                       _mem_save_print_processor_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->print_processor, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->print_processor));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->print_processor));
+                       if (ndr_get_array_length(ndr, &r->print_processor) > ndr_get_array_size(ndr, &r->print_processor)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->print_processor), ndr_get_array_length(ndr, &r->print_processor));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->print_processor), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->print_processor, ndr_get_array_length(ndr, &r->print_processor), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_print_processor_0, 0);
+               }
+               if (r->parameters) {
+                       _mem_save_parameters_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->parameters, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->parameters));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->parameters));
+                       if (ndr_get_array_length(ndr, &r->parameters) > ndr_get_array_size(ndr, &r->parameters)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->parameters), ndr_get_array_length(ndr, &r->parameters));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->parameters), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->parameters, ndr_get_array_length(ndr, &r->parameters), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_parameters_0, 0);
+               }
+               if (r->driver_name) {
+                       _mem_save_driver_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->driver_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->driver_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->driver_name));
+                       if (ndr_get_array_length(ndr, &r->driver_name) > ndr_get_array_size(ndr, &r->driver_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->driver_name), ndr_get_array_length(ndr, &r->driver_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->driver_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->driver_name, ndr_get_array_length(ndr, &r->driver_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_driver_name_0, 0);
+               }
+               if (r->devmode) {
+                       _mem_save_devmode_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->devmode, 0);
+                       NDR_CHECK(ndr_pull_spoolss_DeviceMode(ndr, NDR_SCALARS, r->devmode));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_devmode_0, 0);
+               }
+               if (r->text_status) {
+                       _mem_save_text_status_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->text_status, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->text_status));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->text_status));
+                       if (ndr_get_array_length(ndr, &r->text_status) > ndr_get_array_size(ndr, &r->text_status)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->text_status), ndr_get_array_length(ndr, &r->text_status));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->text_status), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->text_status, ndr_get_array_length(ndr, &r->text_status), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_text_status_0, 0);
+               }
+               if (r->secdesc) {
+                       _mem_save_secdesc_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->secdesc, 0);
+                       NDR_CHECK(ndr_pull_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_secdesc_0, 0);
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_SetJobInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_SetJobInfo2 *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_SetJobInfo2");
+       ndr->depth++;
+       ndr_print_uint32(ndr, "job_id", r->job_id);
+       ndr_print_ptr(ndr, "printer_name", r->printer_name);
+       ndr->depth++;
+       if (r->printer_name) {
+               ndr_print_string(ndr, "printer_name", r->printer_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "server_name", r->server_name);
+       ndr->depth++;
+       if (r->server_name) {
+               ndr_print_string(ndr, "server_name", r->server_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "user_name", r->user_name);
+       ndr->depth++;
+       if (r->user_name) {
+               ndr_print_string(ndr, "user_name", r->user_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "document_name", r->document_name);
+       ndr->depth++;
+       if (r->document_name) {
+               ndr_print_string(ndr, "document_name", r->document_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "notify_name", r->notify_name);
+       ndr->depth++;
+       if (r->notify_name) {
+               ndr_print_string(ndr, "notify_name", r->notify_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "data_type", r->data_type);
+       ndr->depth++;
+       if (r->data_type) {
+               ndr_print_string(ndr, "data_type", r->data_type);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "print_processor", r->print_processor);
+       ndr->depth++;
+       if (r->print_processor) {
+               ndr_print_string(ndr, "print_processor", r->print_processor);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "parameters", r->parameters);
+       ndr->depth++;
+       if (r->parameters) {
+               ndr_print_string(ndr, "parameters", r->parameters);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "driver_name", r->driver_name);
+       ndr->depth++;
+       if (r->driver_name) {
+               ndr_print_string(ndr, "driver_name", r->driver_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "devmode", r->devmode);
+       ndr->depth++;
+       if (r->devmode) {
+               ndr_print_spoolss_DeviceMode(ndr, "devmode", r->devmode);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "text_status", r->text_status);
+       ndr->depth++;
+       if (r->text_status) {
+               ndr_print_string(ndr, "text_status", r->text_status);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "secdesc", r->secdesc);
+       ndr->depth++;
+       if (r->secdesc) {
+               ndr_print_security_descriptor(ndr, "secdesc", r->secdesc);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_JobStatus(ndr, "status", r->status);
+       ndr_print_uint32(ndr, "priority", r->priority);
+       ndr_print_uint32(ndr, "position", r->position);
+       ndr_print_uint32(ndr, "start_time", r->start_time);
+       ndr_print_uint32(ndr, "until_time", r->until_time);
+       ndr_print_uint32(ndr, "total_pages", r->total_pages);
+       ndr_print_uint32(ndr, "size", r->size);
+       ndr_print_spoolss_Time(ndr, "submitted", &r->submitted);
+       ndr_print_uint32(ndr, "time", r->time);
+       ndr_print_uint32(ndr, "pages_printed", r->pages_printed);
+       ndr->depth--;
+}
+
+static enum ndr_err_code ndr_push_spoolss_SetJobInfo4(struct ndr_push *ndr, int ndr_flags, const struct spoolss_SetJobInfo4 *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->job_id));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->printer_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->server_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->user_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->document_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->notify_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->data_type));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->print_processor));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->parameters));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->driver_name));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->devmode));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->text_status));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->secdesc));
+               NDR_CHECK(ndr_push_spoolss_JobStatus(ndr, NDR_SCALARS, r->status));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->priority));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->position));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->start_time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->until_time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->total_pages));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size));
+               NDR_CHECK(ndr_push_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->time));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->pages_printed));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->size_high));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               if (r->printer_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->printer_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->printer_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->printer_name, ndr_charset_length(r->printer_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->server_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->server_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->server_name, ndr_charset_length(r->server_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->user_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->user_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->user_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->user_name, ndr_charset_length(r->user_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->document_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->document_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->document_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->document_name, ndr_charset_length(r->document_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->notify_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->notify_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->notify_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->notify_name, ndr_charset_length(r->notify_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->data_type) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->data_type, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->data_type, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->data_type, ndr_charset_length(r->data_type, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->print_processor) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->print_processor, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->print_processor, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->print_processor, ndr_charset_length(r->print_processor, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->parameters) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->parameters, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->parameters, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->parameters, ndr_charset_length(r->parameters, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->driver_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->driver_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->driver_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->driver_name, ndr_charset_length(r->driver_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->devmode) {
+                       NDR_CHECK(ndr_push_spoolss_DeviceMode(ndr, NDR_SCALARS, r->devmode));
+               }
+               if (r->text_status) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->text_status, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->text_status, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->text_status, ndr_charset_length(r->text_status, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->secdesc) {
+                       NDR_CHECK(ndr_push_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_SetJobInfo4(struct ndr_pull *ndr, int ndr_flags, struct spoolss_SetJobInfo4 *r)
+{
+       uint32_t _ptr_printer_name;
+       TALLOC_CTX *_mem_save_printer_name_0;
+       uint32_t _ptr_server_name;
+       TALLOC_CTX *_mem_save_server_name_0;
+       uint32_t _ptr_user_name;
+       TALLOC_CTX *_mem_save_user_name_0;
+       uint32_t _ptr_document_name;
+       TALLOC_CTX *_mem_save_document_name_0;
+       uint32_t _ptr_notify_name;
+       TALLOC_CTX *_mem_save_notify_name_0;
+       uint32_t _ptr_data_type;
+       TALLOC_CTX *_mem_save_data_type_0;
+       uint32_t _ptr_print_processor;
+       TALLOC_CTX *_mem_save_print_processor_0;
+       uint32_t _ptr_parameters;
+       TALLOC_CTX *_mem_save_parameters_0;
+       uint32_t _ptr_driver_name;
+       TALLOC_CTX *_mem_save_driver_name_0;
+       uint32_t _ptr_devmode;
+       TALLOC_CTX *_mem_save_devmode_0;
+       uint32_t _ptr_text_status;
+       TALLOC_CTX *_mem_save_text_status_0;
+       uint32_t _ptr_secdesc;
+       TALLOC_CTX *_mem_save_secdesc_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->job_id));
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_printer_name));
+               if (_ptr_printer_name) {
+                       NDR_PULL_ALLOC(ndr, r->printer_name);
+               } else {
+                       r->printer_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_server_name));
+               if (_ptr_server_name) {
+                       NDR_PULL_ALLOC(ndr, r->server_name);
+               } else {
+                       r->server_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_user_name));
+               if (_ptr_user_name) {
+                       NDR_PULL_ALLOC(ndr, r->user_name);
+               } else {
+                       r->user_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_document_name));
+               if (_ptr_document_name) {
+                       NDR_PULL_ALLOC(ndr, r->document_name);
+               } else {
+                       r->document_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_notify_name));
+               if (_ptr_notify_name) {
+                       NDR_PULL_ALLOC(ndr, r->notify_name);
+               } else {
+                       r->notify_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_data_type));
+               if (_ptr_data_type) {
+                       NDR_PULL_ALLOC(ndr, r->data_type);
+               } else {
+                       r->data_type = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_print_processor));
+               if (_ptr_print_processor) {
+                       NDR_PULL_ALLOC(ndr, r->print_processor);
+               } else {
+                       r->print_processor = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_parameters));
+               if (_ptr_parameters) {
+                       NDR_PULL_ALLOC(ndr, r->parameters);
+               } else {
+                       r->parameters = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_driver_name));
+               if (_ptr_driver_name) {
+                       NDR_PULL_ALLOC(ndr, r->driver_name);
+               } else {
+                       r->driver_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_devmode));
+               if (_ptr_devmode) {
+                       NDR_PULL_ALLOC(ndr, r->devmode);
+               } else {
+                       r->devmode = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_text_status));
+               if (_ptr_text_status) {
+                       NDR_PULL_ALLOC(ndr, r->text_status);
+               } else {
+                       r->text_status = NULL;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_secdesc));
+               if (_ptr_secdesc) {
+                       NDR_PULL_ALLOC(ndr, r->secdesc);
+               } else {
+                       r->secdesc = NULL;
+               }
+               NDR_CHECK(ndr_pull_spoolss_JobStatus(ndr, NDR_SCALARS, &r->status));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->priority));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->position));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->start_time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->until_time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->total_pages));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->size));
+               NDR_CHECK(ndr_pull_spoolss_Time(ndr, NDR_SCALARS, &r->submitted));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->time));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->pages_printed));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->size_high));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               if (r->printer_name) {
+                       _mem_save_printer_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->printer_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->printer_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->printer_name));
+                       if (ndr_get_array_length(ndr, &r->printer_name) > ndr_get_array_size(ndr, &r->printer_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->printer_name), ndr_get_array_length(ndr, &r->printer_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->printer_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->printer_name, ndr_get_array_length(ndr, &r->printer_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_printer_name_0, 0);
+               }
+               if (r->server_name) {
+                       _mem_save_server_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->server_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->server_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->server_name));
+                       if (ndr_get_array_length(ndr, &r->server_name) > ndr_get_array_size(ndr, &r->server_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->server_name), ndr_get_array_length(ndr, &r->server_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->server_name, ndr_get_array_length(ndr, &r->server_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_server_name_0, 0);
+               }
+               if (r->user_name) {
+                       _mem_save_user_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->user_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->user_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->user_name));
+                       if (ndr_get_array_length(ndr, &r->user_name) > ndr_get_array_size(ndr, &r->user_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->user_name), ndr_get_array_length(ndr, &r->user_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->user_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->user_name, ndr_get_array_length(ndr, &r->user_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_user_name_0, 0);
+               }
+               if (r->document_name) {
+                       _mem_save_document_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->document_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->document_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->document_name));
+                       if (ndr_get_array_length(ndr, &r->document_name) > ndr_get_array_size(ndr, &r->document_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->document_name), ndr_get_array_length(ndr, &r->document_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->document_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->document_name, ndr_get_array_length(ndr, &r->document_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_document_name_0, 0);
+               }
+               if (r->notify_name) {
+                       _mem_save_notify_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->notify_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->notify_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->notify_name));
+                       if (ndr_get_array_length(ndr, &r->notify_name) > ndr_get_array_size(ndr, &r->notify_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->notify_name), ndr_get_array_length(ndr, &r->notify_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->notify_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->notify_name, ndr_get_array_length(ndr, &r->notify_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_notify_name_0, 0);
+               }
+               if (r->data_type) {
+                       _mem_save_data_type_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->data_type, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->data_type));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->data_type));
+                       if (ndr_get_array_length(ndr, &r->data_type) > ndr_get_array_size(ndr, &r->data_type)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->data_type), ndr_get_array_length(ndr, &r->data_type));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->data_type), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->data_type, ndr_get_array_length(ndr, &r->data_type), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_data_type_0, 0);
+               }
+               if (r->print_processor) {
+                       _mem_save_print_processor_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->print_processor, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->print_processor));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->print_processor));
+                       if (ndr_get_array_length(ndr, &r->print_processor) > ndr_get_array_size(ndr, &r->print_processor)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->print_processor), ndr_get_array_length(ndr, &r->print_processor));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->print_processor), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->print_processor, ndr_get_array_length(ndr, &r->print_processor), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_print_processor_0, 0);
+               }
+               if (r->parameters) {
+                       _mem_save_parameters_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->parameters, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->parameters));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->parameters));
+                       if (ndr_get_array_length(ndr, &r->parameters) > ndr_get_array_size(ndr, &r->parameters)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->parameters), ndr_get_array_length(ndr, &r->parameters));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->parameters), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->parameters, ndr_get_array_length(ndr, &r->parameters), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_parameters_0, 0);
+               }
+               if (r->driver_name) {
+                       _mem_save_driver_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->driver_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->driver_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->driver_name));
+                       if (ndr_get_array_length(ndr, &r->driver_name) > ndr_get_array_size(ndr, &r->driver_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->driver_name), ndr_get_array_length(ndr, &r->driver_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->driver_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->driver_name, ndr_get_array_length(ndr, &r->driver_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_driver_name_0, 0);
+               }
+               if (r->devmode) {
+                       _mem_save_devmode_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->devmode, 0);
+                       NDR_CHECK(ndr_pull_spoolss_DeviceMode(ndr, NDR_SCALARS, r->devmode));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_devmode_0, 0);
+               }
+               if (r->text_status) {
+                       _mem_save_text_status_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->text_status, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->text_status));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->text_status));
+                       if (ndr_get_array_length(ndr, &r->text_status) > ndr_get_array_size(ndr, &r->text_status)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->text_status), ndr_get_array_length(ndr, &r->text_status));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->text_status), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->text_status, ndr_get_array_length(ndr, &r->text_status), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_text_status_0, 0);
+               }
+               if (r->secdesc) {
+                       _mem_save_secdesc_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->secdesc, 0);
+                       NDR_CHECK(ndr_pull_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_secdesc_0, 0);
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_SetJobInfo4(struct ndr_print *ndr, const char *name, const struct spoolss_SetJobInfo4 *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_SetJobInfo4");
+       ndr->depth++;
+       ndr_print_uint32(ndr, "job_id", r->job_id);
+       ndr_print_ptr(ndr, "printer_name", r->printer_name);
+       ndr->depth++;
+       if (r->printer_name) {
+               ndr_print_string(ndr, "printer_name", r->printer_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "server_name", r->server_name);
+       ndr->depth++;
+       if (r->server_name) {
+               ndr_print_string(ndr, "server_name", r->server_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "user_name", r->user_name);
+       ndr->depth++;
+       if (r->user_name) {
+               ndr_print_string(ndr, "user_name", r->user_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "document_name", r->document_name);
+       ndr->depth++;
+       if (r->document_name) {
+               ndr_print_string(ndr, "document_name", r->document_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "notify_name", r->notify_name);
+       ndr->depth++;
+       if (r->notify_name) {
+               ndr_print_string(ndr, "notify_name", r->notify_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "data_type", r->data_type);
+       ndr->depth++;
+       if (r->data_type) {
+               ndr_print_string(ndr, "data_type", r->data_type);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "print_processor", r->print_processor);
+       ndr->depth++;
+       if (r->print_processor) {
+               ndr_print_string(ndr, "print_processor", r->print_processor);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "parameters", r->parameters);
+       ndr->depth++;
+       if (r->parameters) {
+               ndr_print_string(ndr, "parameters", r->parameters);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "driver_name", r->driver_name);
+       ndr->depth++;
+       if (r->driver_name) {
+               ndr_print_string(ndr, "driver_name", r->driver_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "devmode", r->devmode);
+       ndr->depth++;
+       if (r->devmode) {
+               ndr_print_spoolss_DeviceMode(ndr, "devmode", r->devmode);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "text_status", r->text_status);
+       ndr->depth++;
+       if (r->text_status) {
+               ndr_print_string(ndr, "text_status", r->text_status);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "secdesc", r->secdesc);
+       ndr->depth++;
+       if (r->secdesc) {
+               ndr_print_security_descriptor(ndr, "secdesc", r->secdesc);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_JobStatus(ndr, "status", r->status);
+       ndr_print_uint32(ndr, "priority", r->priority);
+       ndr_print_uint32(ndr, "position", r->position);
+       ndr_print_uint32(ndr, "start_time", r->start_time);
+       ndr_print_uint32(ndr, "until_time", r->until_time);
+       ndr_print_uint32(ndr, "total_pages", r->total_pages);
+       ndr_print_uint32(ndr, "size", r->size);
+       ndr_print_spoolss_Time(ndr, "submitted", &r->submitted);
+       ndr_print_uint32(ndr, "time", r->time);
+       ndr_print_uint32(ndr, "pages_printed", r->pages_printed);
+       ndr_print_uint32(ndr, "size_high", r->size_high);
+       ndr->depth--;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_SetJobInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_SetJobInfo *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               int level = ndr_push_get_switch_value(ndr, r);
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, level));
+               switch (level) {
+                       case 1: {
+                               NDR_CHECK(ndr_push_unique_ptr(ndr, r->info1));
+                       break; }
+
+                       case 2: {
+                               NDR_CHECK(ndr_push_unique_ptr(ndr, r->info2));
+                       break; }
+
                        case 3: {
+                               NDR_CHECK(ndr_push_unique_ptr(ndr, r->info3));
+                       break; }
+
+                       case 4: {
+                               NDR_CHECK(ndr_push_unique_ptr(ndr, r->info4));
                        break; }
 
                        default: {
@@ -2939,16 +5488,30 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_JobInfo(struct ndr_pull *ndr, int nd
                }
        }
        if (ndr_flags & NDR_BUFFERS) {
-               NDR_CHECK(ndr_pull_setup_relative_base_offset2(ndr, r));
+               int level = ndr_push_get_switch_value(ndr, r);
                switch (level) {
                        case 1:
-                               NDR_CHECK(ndr_pull_spoolss_JobInfo1(ndr, NDR_BUFFERS, &r->info1));
+                               if (r->info1) {
+                                       NDR_CHECK(ndr_push_spoolss_SetJobInfo1(ndr, NDR_SCALARS|NDR_BUFFERS, r->info1));
+                               }
                        break;
 
                        case 2:
+                               if (r->info2) {
+                                       NDR_CHECK(ndr_push_spoolss_SetJobInfo2(ndr, NDR_SCALARS|NDR_BUFFERS, r->info2));
+                               }
                        break;
 
                        case 3:
+                               if (r->info3) {
+                                       NDR_CHECK(ndr_push_spoolss_JobInfo3(ndr, NDR_SCALARS, r->info3));
+                               }
+                       break;
+
+                       case 4:
+                               if (r->info4) {
+                                       NDR_CHECK(ndr_push_spoolss_SetJobInfo4(ndr, NDR_SCALARS|NDR_BUFFERS, r->info4));
+                               }
                        break;
 
                        default:
@@ -2956,24 +5519,155 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_JobInfo(struct ndr_pull *ndr, int nd
 
                }
        }
-       ndr_pull_restore_relative_base_offset(ndr, _save_relative_base_offset);
        return NDR_ERR_SUCCESS;
 }
 
-_PUBLIC_ void ndr_print_spoolss_JobInfo(struct ndr_print *ndr, const char *name, const union spoolss_JobInfo *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_SetJobInfo(struct ndr_pull *ndr, int ndr_flags, union spoolss_SetJobInfo *r)
+{
+       int level;
+       uint32_t _level;
+       TALLOC_CTX *_mem_save_info1_0;
+       TALLOC_CTX *_mem_save_info2_0;
+       TALLOC_CTX *_mem_save_info3_0;
+       TALLOC_CTX *_mem_save_info4_0;
+       level = ndr_pull_get_switch_value(ndr, r);
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &_level));
+               if (_level != level) {
+                       return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u for r", _level);
+               }
+               switch (level) {
+                       case 1: {
+                               uint32_t _ptr_info1;
+                               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info1));
+                               if (_ptr_info1) {
+                                       NDR_PULL_ALLOC(ndr, r->info1);
+                               } else {
+                                       r->info1 = NULL;
+                               }
+                       break; }
+
+                       case 2: {
+                               uint32_t _ptr_info2;
+                               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info2));
+                               if (_ptr_info2) {
+                                       NDR_PULL_ALLOC(ndr, r->info2);
+                               } else {
+                                       r->info2 = NULL;
+                               }
+                       break; }
+
+                       case 3: {
+                               uint32_t _ptr_info3;
+                               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info3));
+                               if (_ptr_info3) {
+                                       NDR_PULL_ALLOC(ndr, r->info3);
+                               } else {
+                                       r->info3 = NULL;
+                               }
+                       break; }
+
+                       case 4: {
+                               uint32_t _ptr_info4;
+                               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info4));
+                               if (_ptr_info4) {
+                                       NDR_PULL_ALLOC(ndr, r->info4);
+                               } else {
+                                       r->info4 = NULL;
+                               }
+                       break; }
+
+                       default: {
+                       break; }
+
+               }
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               switch (level) {
+                       case 1:
+                               if (r->info1) {
+                                       _mem_save_info1_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                                       NDR_PULL_SET_MEM_CTX(ndr, r->info1, 0);
+                                       NDR_CHECK(ndr_pull_spoolss_SetJobInfo1(ndr, NDR_SCALARS|NDR_BUFFERS, r->info1));
+                                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info1_0, 0);
+                               }
+                       break;
+
+                       case 2:
+                               if (r->info2) {
+                                       _mem_save_info2_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                                       NDR_PULL_SET_MEM_CTX(ndr, r->info2, 0);
+                                       NDR_CHECK(ndr_pull_spoolss_SetJobInfo2(ndr, NDR_SCALARS|NDR_BUFFERS, r->info2));
+                                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info2_0, 0);
+                               }
+                       break;
+
+                       case 3:
+                               if (r->info3) {
+                                       _mem_save_info3_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                                       NDR_PULL_SET_MEM_CTX(ndr, r->info3, 0);
+                                       NDR_CHECK(ndr_pull_spoolss_JobInfo3(ndr, NDR_SCALARS, r->info3));
+                                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info3_0, 0);
+                               }
+                       break;
+
+                       case 4:
+                               if (r->info4) {
+                                       _mem_save_info4_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                                       NDR_PULL_SET_MEM_CTX(ndr, r->info4, 0);
+                                       NDR_CHECK(ndr_pull_spoolss_SetJobInfo4(ndr, NDR_SCALARS|NDR_BUFFERS, r->info4));
+                                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info4_0, 0);
+                               }
+                       break;
+
+                       default:
+                       break;
+
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_SetJobInfo(struct ndr_print *ndr, const char *name, const union spoolss_SetJobInfo *r)
 {
        int level;
        level = ndr_print_get_switch_value(ndr, r);
-       ndr_print_union(ndr, name, level, "spoolss_JobInfo");
+       ndr_print_union(ndr, name, level, "spoolss_SetJobInfo");
        switch (level) {
                case 1:
-                       ndr_print_spoolss_JobInfo1(ndr, "info1", &r->info1);
+                       ndr_print_ptr(ndr, "info1", r->info1);
+                       ndr->depth++;
+                       if (r->info1) {
+                               ndr_print_spoolss_SetJobInfo1(ndr, "info1", r->info1);
+                       }
+                       ndr->depth--;
                break;
 
                case 2:
+                       ndr_print_ptr(ndr, "info2", r->info2);
+                       ndr->depth++;
+                       if (r->info2) {
+                               ndr_print_spoolss_SetJobInfo2(ndr, "info2", r->info2);
+                       }
+                       ndr->depth--;
                break;
 
                case 3:
+                       ndr_print_ptr(ndr, "info3", r->info3);
+                       ndr->depth++;
+                       if (r->info3) {
+                               ndr_print_spoolss_JobInfo3(ndr, "info3", r->info3);
+                       }
+                       ndr->depth--;
+               break;
+
+               case 4:
+                       ndr_print_ptr(ndr, "info4", r->info4);
+                       ndr->depth++;
+                       if (r->info4) {
+                               ndr_print_spoolss_SetJobInfo4(ndr, "info4", r->info4);
+                       }
+                       ndr->depth--;
                break;
 
                default:
@@ -2988,10 +5682,10 @@ static enum ndr_err_code ndr_push_spoolss_JobInfoContainer(struct ndr_push *ndr,
                NDR_CHECK(ndr_push_align(ndr, 4));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->level));
                NDR_CHECK(ndr_push_set_switch_value(ndr, &r->info, r->level));
-               NDR_CHECK(ndr_push_spoolss_JobInfo(ndr, NDR_SCALARS, &r->info));
+               NDR_CHECK(ndr_push_spoolss_SetJobInfo(ndr, NDR_SCALARS, &r->info));
        }
        if (ndr_flags & NDR_BUFFERS) {
-               NDR_CHECK(ndr_push_spoolss_JobInfo(ndr, NDR_BUFFERS, &r->info));
+               NDR_CHECK(ndr_push_spoolss_SetJobInfo(ndr, NDR_BUFFERS, &r->info));
        }
        return NDR_ERR_SUCCESS;
 }
@@ -3002,10 +5696,10 @@ static enum ndr_err_code ndr_pull_spoolss_JobInfoContainer(struct ndr_pull *ndr,
                NDR_CHECK(ndr_pull_align(ndr, 4));
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->level));
                NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->info, r->level));
-               NDR_CHECK(ndr_pull_spoolss_JobInfo(ndr, NDR_SCALARS, &r->info));
+               NDR_CHECK(ndr_pull_spoolss_SetJobInfo(ndr, NDR_SCALARS, &r->info));
        }
        if (ndr_flags & NDR_BUFFERS) {
-               NDR_CHECK(ndr_pull_spoolss_JobInfo(ndr, NDR_BUFFERS, &r->info));
+               NDR_CHECK(ndr_pull_spoolss_SetJobInfo(ndr, NDR_BUFFERS, &r->info));
        }
        return NDR_ERR_SUCCESS;
 }
@@ -3016,7 +5710,7 @@ _PUBLIC_ void ndr_print_spoolss_JobInfoContainer(struct ndr_print *ndr, const ch
        ndr->depth++;
        ndr_print_uint32(ndr, "level", r->level);
        ndr_print_set_switch_value(ndr, &r->info, r->level);
-       ndr_print_spoolss_JobInfo(ndr, "info", &r->info);
+       ndr_print_spoolss_SetJobInfo(ndr, "info", &r->info);
        ndr->depth--;
 }
 
@@ -3046,6 +5740,8 @@ _PUBLIC_ void ndr_print_spoolss_JobControl(struct ndr_print *ndr, const char *na
                case SPOOLSS_JOB_CONTROL_DELETE: val = "SPOOLSS_JOB_CONTROL_DELETE"; break;
                case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER: val = "SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER"; break;
                case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED: val = "SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED"; break;
+               case SPOOLSS_JOB_CONTROL_RETAIN: val = "SPOOLSS_JOB_CONTROL_RETAIN"; break;
+               case SPOOLSS_JOB_CONTROL_RELEASE: val = "SPOOLSS_JOB_CONTROL_RELEASE"; break;
        }
        ndr_print_enum(ndr, name, "ENUM", val, r);
 }
@@ -3867,36 +6563,20 @@ static enum ndr_err_code ndr_push_spoolss_SetPrinterInfo3(struct ndr_push *ndr,
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
-               NDR_CHECK(ndr_push_unique_ptr(ndr, r->secdesc));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sec_desc_ptr));
        }
        if (ndr_flags & NDR_BUFFERS) {
-               if (r->secdesc) {
-                       NDR_CHECK(ndr_push_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
-               }
        }
        return NDR_ERR_SUCCESS;
 }
 
 static enum ndr_err_code ndr_pull_spoolss_SetPrinterInfo3(struct ndr_pull *ndr, int ndr_flags, struct spoolss_SetPrinterInfo3 *r)
 {
-       uint32_t _ptr_secdesc;
-       TALLOC_CTX *_mem_save_secdesc_0;
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_pull_align(ndr, 4));
-               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_secdesc));
-               if (_ptr_secdesc) {
-                       NDR_PULL_ALLOC(ndr, r->secdesc);
-               } else {
-                       r->secdesc = NULL;
-               }
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sec_desc_ptr));
        }
        if (ndr_flags & NDR_BUFFERS) {
-               if (r->secdesc) {
-                       _mem_save_secdesc_0 = NDR_PULL_GET_MEM_CTX(ndr);
-                       NDR_PULL_SET_MEM_CTX(ndr, r->secdesc, 0);
-                       NDR_CHECK(ndr_pull_security_descriptor(ndr, NDR_SCALARS|NDR_BUFFERS, r->secdesc));
-                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_secdesc_0, 0);
-               }
        }
        return NDR_ERR_SUCCESS;
 }
@@ -3905,12 +6585,7 @@ _PUBLIC_ void ndr_print_spoolss_SetPrinterInfo3(struct ndr_print *ndr, const cha
 {
        ndr_print_struct(ndr, name, "spoolss_SetPrinterInfo3");
        ndr->depth++;
-       ndr_print_ptr(ndr, "secdesc", r->secdesc);
-       ndr->depth++;
-       if (r->secdesc) {
-               ndr_print_security_descriptor(ndr, "secdesc", r->secdesc);
-       }
-       ndr->depth--;
+       ndr_print_uint32(ndr, "sec_desc_ptr", r->sec_desc_ptr);
        ndr->depth--;
 }
 
@@ -4279,7 +6954,7 @@ static enum ndr_err_code ndr_push_spoolss_SetPrinterInfo(struct ndr_push *ndr, i
 
                        case 3:
                                if (r->info3) {
-                                       NDR_CHECK(ndr_push_spoolss_SetPrinterInfo3(ndr, NDR_SCALARS|NDR_BUFFERS, r->info3));
+                                       NDR_CHECK(ndr_push_spoolss_SetPrinterInfo3(ndr, NDR_SCALARS, r->info3));
                                }
                        break;
 
@@ -4486,7 +7161,7 @@ static enum ndr_err_code ndr_pull_spoolss_SetPrinterInfo(struct ndr_pull *ndr, i
                                if (r->info3) {
                                        _mem_save_info3_0 = NDR_PULL_GET_MEM_CTX(ndr);
                                        NDR_PULL_SET_MEM_CTX(ndr, r->info3, 0);
-                                       NDR_CHECK(ndr_pull_spoolss_SetPrinterInfo3(ndr, NDR_SCALARS|NDR_BUFFERS, r->info3));
+                                       NDR_CHECK(ndr_pull_spoolss_SetPrinterInfo3(ndr, NDR_SCALARS, r->info3));
                                        NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info3_0, 0);
                                }
                        break;
@@ -4796,13 +7471,13 @@ _PUBLIC_ void ndr_print_spoolss_AddDriverInfo1(struct ndr_print *ndr, const char
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_spoolss_DriverOSVersion(struct ndr_push *ndr, int ndr_flags, enum spoolss_DriverOSVersion r)
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverOSVersion(struct ndr_push *ndr, int ndr_flags, enum spoolss_DriverOSVersion r)
 {
        NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_spoolss_DriverOSVersion(struct ndr_pull *ndr, int ndr_flags, enum spoolss_DriverOSVersion *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverOSVersion(struct ndr_pull *ndr, int ndr_flags, enum spoolss_DriverOSVersion *r)
 {
        uint32_t v;
        NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
@@ -5704,7 +8379,7 @@ static enum ndr_err_code ndr_push_spoolss_AddDriverInfo6(struct ndr_push *ndr, i
                NDR_CHECK(ndr_push_unique_ptr(ndr, r->dependent_files));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ((ndr_size_spoolss_StringArray(r->previous_names, ndr->iconv_convenience, ndr->flags) - 4) / 2)));
                NDR_CHECK(ndr_push_unique_ptr(ndr, r->previous_names));
-               NDR_CHECK(ndr_push_NTTIME(ndr, NDR_SCALARS, r->driver_data));
+               NDR_CHECK(ndr_push_NTTIME(ndr, NDR_SCALARS, r->driver_date));
                NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, r->driver_version));
                NDR_CHECK(ndr_push_unique_ptr(ndr, r->manufacturer_name));
                NDR_CHECK(ndr_push_unique_ptr(ndr, r->manufacturer_url));
@@ -5889,7 +8564,7 @@ static enum ndr_err_code ndr_pull_spoolss_AddDriverInfo6(struct ndr_pull *ndr, i
                } else {
                        r->previous_names = NULL;
                }
-               NDR_CHECK(ndr_pull_NTTIME(ndr, NDR_SCALARS, &r->driver_data));
+               NDR_CHECK(ndr_pull_NTTIME(ndr, NDR_SCALARS, &r->driver_date));
                NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &r->driver_version));
                NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_manufacturer_name));
                if (_ptr_manufacturer_name) {
@@ -6144,7 +8819,7 @@ _PUBLIC_ void ndr_print_spoolss_AddDriverInfo6(struct ndr_print *ndr, const char
                ndr_print_spoolss_StringArray(ndr, "previous_names", r->previous_names);
        }
        ndr->depth--;
-       ndr_print_NTTIME(ndr, "driver_data", r->driver_data);
+       ndr_print_NTTIME(ndr, "driver_date", r->driver_date);
        ndr_print_hyper(ndr, "driver_version", r->driver_version);
        ndr_print_ptr(ndr, "manufacturer_name", r->manufacturer_name);
        ndr->depth++;
@@ -6190,7 +8865,7 @@ static enum ndr_err_code ndr_push_spoolss_AddDriverInfo8(struct ndr_push *ndr, i
                NDR_CHECK(ndr_push_unique_ptr(ndr, r->dependent_files));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ((ndr_size_spoolss_StringArray(r->previous_names, ndr->iconv_convenience, ndr->flags) - 4) / 2)));
                NDR_CHECK(ndr_push_unique_ptr(ndr, r->previous_names));
-               NDR_CHECK(ndr_push_NTTIME(ndr, NDR_SCALARS, r->driver_data));
+               NDR_CHECK(ndr_push_NTTIME(ndr, NDR_SCALARS, r->driver_date));
                NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, r->driver_version));
                NDR_CHECK(ndr_push_unique_ptr(ndr, r->manufacturer_name));
                NDR_CHECK(ndr_push_unique_ptr(ndr, r->manufacturer_url));
@@ -6419,7 +9094,7 @@ static enum ndr_err_code ndr_pull_spoolss_AddDriverInfo8(struct ndr_pull *ndr, i
                } else {
                        r->previous_names = NULL;
                }
-               NDR_CHECK(ndr_pull_NTTIME(ndr, NDR_SCALARS, &r->driver_data));
+               NDR_CHECK(ndr_pull_NTTIME(ndr, NDR_SCALARS, &r->driver_date));
                NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &r->driver_version));
                NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_manufacturer_name));
                if (_ptr_manufacturer_name) {
@@ -6757,7 +9432,7 @@ _PUBLIC_ void ndr_print_spoolss_AddDriverInfo8(struct ndr_print *ndr, const char
                ndr_print_spoolss_StringArray(ndr, "previous_names", r->previous_names);
        }
        ndr->depth--;
-       ndr_print_NTTIME(ndr, "driver_data", r->driver_data);
+       ndr_print_NTTIME(ndr, "driver_date", r->driver_date);
        ndr_print_hyper(ndr, "driver_version", r->driver_version);
        ndr_print_ptr(ndr, "manufacturer_name", r->manufacturer_name);
        ndr->depth++;
@@ -7148,7 +9823,7 @@ _PUBLIC_ void ndr_print_spoolss_AddDriverInfoCtr(struct ndr_print *ndr, const ch
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_spoolss_DriverInfo1(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo1 *r)
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo1(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo1 *r)
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
@@ -7173,7 +9848,7 @@ static enum ndr_err_code ndr_push_spoolss_DriverInfo1(struct ndr_push *ndr, int
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_spoolss_DriverInfo1(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo1 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo1(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo1 *r)
 {
        uint32_t _ptr_driver_name;
        TALLOC_CTX *_mem_save_driver_name_0;
@@ -7225,7 +9900,12 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo1(struct ndr_print *ndr, const char *n
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_spoolss_DriverInfo2(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo2 *r)
+_PUBLIC_ size_t ndr_size_spoolss_DriverInfo1(const struct spoolss_DriverInfo1 *r, struct smb_iconv_convenience *ic, int flags)
+{
+       return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_spoolss_DriverInfo1, ic);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo2(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo2 *r)
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
@@ -7311,7 +9991,7 @@ static enum ndr_err_code ndr_push_spoolss_DriverInfo2(struct ndr_push *ndr, int
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_spoolss_DriverInfo2(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo2 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo2(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo2 *r)
 {
        uint32_t _ptr_driver_name;
        TALLOC_CTX *_mem_save_driver_name_0;
@@ -7505,7 +10185,12 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo2(struct ndr_print *ndr, const char *n
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_spoolss_DriverInfo3(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo3 *r)
+_PUBLIC_ size_t ndr_size_spoolss_DriverInfo2(const struct spoolss_DriverInfo2 *r, struct smb_iconv_convenience *ic, int flags)
+{
+       return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_spoolss_DriverInfo2, ic);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo3(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo3 *r)
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
@@ -7651,7 +10336,7 @@ static enum ndr_err_code ndr_push_spoolss_DriverInfo3(struct ndr_push *ndr, int
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_spoolss_DriverInfo3(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo3 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo3(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo3 *r)
 {
        uint32_t _ptr_driver_name;
        TALLOC_CTX *_mem_save_driver_name_0;
@@ -7985,7 +10670,12 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo3(struct ndr_print *ndr, const char *n
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_spoolss_DriverInfo4(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo4 *r)
+_PUBLIC_ size_t ndr_size_spoolss_DriverInfo3(const struct spoolss_DriverInfo3 *r, struct smb_iconv_convenience *ic, int flags)
+{
+       return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_spoolss_DriverInfo3, ic);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo4(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo4 *r)
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
@@ -8146,7 +10836,7 @@ static enum ndr_err_code ndr_push_spoolss_DriverInfo4(struct ndr_push *ndr, int
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_spoolss_DriverInfo4(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo4 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo4(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo4 *r)
 {
        uint32_t _ptr_driver_name;
        TALLOC_CTX *_mem_save_driver_name_0;
@@ -8515,7 +11205,12 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo4(struct ndr_print *ndr, const char *n
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_spoolss_DriverInfo5(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo5 *r)
+_PUBLIC_ size_t ndr_size_spoolss_DriverInfo4(const struct spoolss_DriverInfo4 *r, struct smb_iconv_convenience *ic, int flags)
+{
+       return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_spoolss_DriverInfo4, ic);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo5(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo5 *r)
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
@@ -8604,7 +11299,7 @@ static enum ndr_err_code ndr_push_spoolss_DriverInfo5(struct ndr_push *ndr, int
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_spoolss_DriverInfo5(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo5 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo5(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo5 *r)
 {
        uint32_t _ptr_driver_name;
        TALLOC_CTX *_mem_save_driver_name_0;
@@ -8804,7 +11499,12 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo5(struct ndr_print *ndr, const char *n
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_spoolss_DriverInfo6(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo6 *r)
+_PUBLIC_ size_t ndr_size_spoolss_DriverInfo5(const struct spoolss_DriverInfo5 *r, struct smb_iconv_convenience *ic, int flags)
+{
+       return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_spoolss_DriverInfo5, ic);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo6(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo6 *r)
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 8));
@@ -8869,7 +11569,7 @@ static enum ndr_err_code ndr_push_spoolss_DriverInfo6(struct ndr_push *ndr, int
                        NDR_CHECK(ndr_push_relative_ptr1(ndr, r->previous_names));
                        ndr->flags = _flags_save_string_array;
                }
-               NDR_CHECK(ndr_push_NTTIME(ndr, NDR_SCALARS, r->driver_data));
+               NDR_CHECK(ndr_push_NTTIME(ndr, NDR_SCALARS, r->driver_date));
                NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, r->driver_version));
                {
                        uint32_t _flags_save_string = ndr->flags;
@@ -9027,7 +11727,7 @@ static enum ndr_err_code ndr_push_spoolss_DriverInfo6(struct ndr_push *ndr, int
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_spoolss_DriverInfo6(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo6 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo6(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo6 *r)
 {
        uint32_t _ptr_driver_name;
        TALLOC_CTX *_mem_save_driver_name_0;
@@ -9180,7 +11880,7 @@ static enum ndr_err_code ndr_pull_spoolss_DriverInfo6(struct ndr_pull *ndr, int
                        }
                        ndr->flags = _flags_save_string_array;
                }
-               NDR_CHECK(ndr_pull_NTTIME(ndr, NDR_SCALARS, &r->driver_data));
+               NDR_CHECK(ndr_pull_NTTIME(ndr, NDR_SCALARS, &r->driver_date));
                NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &r->driver_version));
                {
                        uint32_t _flags_save_string = ndr->flags;
@@ -9511,7 +12211,7 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo6(struct ndr_print *ndr, const char *n
                ndr_print_string_array(ndr, "previous_names", r->previous_names);
        }
        ndr->depth--;
-       ndr_print_NTTIME(ndr, "driver_data", r->driver_data);
+       ndr_print_NTTIME(ndr, "driver_date", r->driver_date);
        ndr_print_hyper(ndr, "driver_version", r->driver_version);
        ndr_print_ptr(ndr, "manufacturer_name", r->manufacturer_name);
        ndr->depth++;
@@ -9540,7 +12240,12 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo6(struct ndr_print *ndr, const char *n
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_spoolss_DriverInfo8(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo8 *r)
+_PUBLIC_ size_t ndr_size_spoolss_DriverInfo6(const struct spoolss_DriverInfo6 *r, struct smb_iconv_convenience *ic, int flags)
+{
+       return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_spoolss_DriverInfo6, ic);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo8(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo8 *r)
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 8));
@@ -9605,7 +12310,7 @@ static enum ndr_err_code ndr_push_spoolss_DriverInfo8(struct ndr_push *ndr, int
                        NDR_CHECK(ndr_push_relative_ptr1(ndr, r->previous_names));
                        ndr->flags = _flags_save_string_array;
                }
-               NDR_CHECK(ndr_push_NTTIME(ndr, NDR_SCALARS, r->driver_data));
+               NDR_CHECK(ndr_push_NTTIME(ndr, NDR_SCALARS, r->driver_date));
                NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, r->driver_version));
                {
                        uint32_t _flags_save_string = ndr->flags;
@@ -9841,7 +12546,7 @@ static enum ndr_err_code ndr_push_spoolss_DriverInfo8(struct ndr_push *ndr, int
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_spoolss_DriverInfo8(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo8 *r)
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo8(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo8 *r)
 {
        uint32_t _ptr_driver_name;
        TALLOC_CTX *_mem_save_driver_name_0;
@@ -10004,7 +12709,7 @@ static enum ndr_err_code ndr_pull_spoolss_DriverInfo8(struct ndr_pull *ndr, int
                        }
                        ndr->flags = _flags_save_string_array;
                }
-               NDR_CHECK(ndr_pull_NTTIME(ndr, NDR_SCALARS, &r->driver_data));
+               NDR_CHECK(ndr_pull_NTTIME(ndr, NDR_SCALARS, &r->driver_date));
                NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &r->driver_version));
                {
                        uint32_t _flags_save_string = ndr->flags;
@@ -10372,45 +13077,289 @@ static enum ndr_err_code ndr_pull_spoolss_DriverInfo8(struct ndr_pull *ndr, int
                                NDR_PULL_SET_MEM_CTX(ndr, _mem_save_color_profiles_0, 0);
                                ndr->offset = _relative_save_offset;
                        }
-                       ndr->flags = _flags_save_string_array;
+                       ndr->flags = _flags_save_string_array;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->inf_path) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->inf_path));
+                               _mem_save_inf_path_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->inf_path, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->inf_path));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_inf_path_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string_array = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->core_driver_dependencies) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->core_driver_dependencies));
+                               _mem_save_core_driver_dependencies_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->core_driver_dependencies, 0);
+                               NDR_CHECK(ndr_pull_string_array(ndr, NDR_SCALARS, &r->core_driver_dependencies));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_core_driver_dependencies_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string_array;
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_DriverInfo8(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo8 *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_DriverInfo8");
+       ndr->depth++;
+       ndr_print_spoolss_DriverOSVersion(ndr, "version", r->version);
+       ndr_print_ptr(ndr, "driver_name", r->driver_name);
+       ndr->depth++;
+       if (r->driver_name) {
+               ndr_print_string(ndr, "driver_name", r->driver_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "architecture", r->architecture);
+       ndr->depth++;
+       if (r->architecture) {
+               ndr_print_string(ndr, "architecture", r->architecture);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "driver_path", r->driver_path);
+       ndr->depth++;
+       if (r->driver_path) {
+               ndr_print_string(ndr, "driver_path", r->driver_path);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "data_file", r->data_file);
+       ndr->depth++;
+       if (r->data_file) {
+               ndr_print_string(ndr, "data_file", r->data_file);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "config_file", r->config_file);
+       ndr->depth++;
+       if (r->config_file) {
+               ndr_print_string(ndr, "config_file", r->config_file);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "help_file", r->help_file);
+       ndr->depth++;
+       if (r->help_file) {
+               ndr_print_string(ndr, "help_file", r->help_file);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "monitor_name", r->monitor_name);
+       ndr->depth++;
+       if (r->monitor_name) {
+               ndr_print_string(ndr, "monitor_name", r->monitor_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "default_datatype", r->default_datatype);
+       ndr->depth++;
+       if (r->default_datatype) {
+               ndr_print_string(ndr, "default_datatype", r->default_datatype);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "dependent_files", r->dependent_files);
+       ndr->depth++;
+       if (r->dependent_files) {
+               ndr_print_string_array(ndr, "dependent_files", r->dependent_files);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "previous_names", r->previous_names);
+       ndr->depth++;
+       if (r->previous_names) {
+               ndr_print_string_array(ndr, "previous_names", r->previous_names);
+       }
+       ndr->depth--;
+       ndr_print_NTTIME(ndr, "driver_date", r->driver_date);
+       ndr_print_hyper(ndr, "driver_version", r->driver_version);
+       ndr_print_ptr(ndr, "manufacturer_name", r->manufacturer_name);
+       ndr->depth++;
+       if (r->manufacturer_name) {
+               ndr_print_string(ndr, "manufacturer_name", r->manufacturer_name);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "manufacturer_url", r->manufacturer_url);
+       ndr->depth++;
+       if (r->manufacturer_url) {
+               ndr_print_string(ndr, "manufacturer_url", r->manufacturer_url);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "hardware_id", r->hardware_id);
+       ndr->depth++;
+       if (r->hardware_id) {
+               ndr_print_string(ndr, "hardware_id", r->hardware_id);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "provider", r->provider);
+       ndr->depth++;
+       if (r->provider) {
+               ndr_print_string(ndr, "provider", r->provider);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "print_processor", r->print_processor);
+       ndr->depth++;
+       if (r->print_processor) {
+               ndr_print_string(ndr, "print_processor", r->print_processor);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "vendor_setup", r->vendor_setup);
+       ndr->depth++;
+       if (r->vendor_setup) {
+               ndr_print_string(ndr, "vendor_setup", r->vendor_setup);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "color_profiles", r->color_profiles);
+       ndr->depth++;
+       if (r->color_profiles) {
+               ndr_print_string_array(ndr, "color_profiles", r->color_profiles);
+       }
+       ndr->depth--;
+       ndr_print_ptr(ndr, "inf_path", r->inf_path);
+       ndr->depth++;
+       if (r->inf_path) {
+               ndr_print_string(ndr, "inf_path", r->inf_path);
+       }
+       ndr->depth--;
+       ndr_print_uint32(ndr, "printer_driver_attributes", r->printer_driver_attributes);
+       ndr_print_ptr(ndr, "core_driver_dependencies", r->core_driver_dependencies);
+       ndr->depth++;
+       if (r->core_driver_dependencies) {
+               ndr_print_string_array(ndr, "core_driver_dependencies", r->core_driver_dependencies);
+       }
+       ndr->depth--;
+       ndr_print_NTTIME(ndr, "min_inbox_driver_ver_date", r->min_inbox_driver_ver_date);
+       ndr_print_hyper(ndr, "min_inbox_driver_ver_version", r->min_inbox_driver_ver_version);
+       ndr->depth--;
+}
+
+_PUBLIC_ size_t ndr_size_spoolss_DriverInfo8(const struct spoolss_DriverInfo8 *r, struct smb_iconv_convenience *ic, int flags)
+{
+       return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_spoolss_DriverInfo8, ic);
+}
+
+static enum ndr_err_code ndr_push_spoolss_DriverFileType(struct ndr_push *ndr, int ndr_flags, enum spoolss_DriverFileType r)
+{
+       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_DriverFileType(struct ndr_pull *ndr, int ndr_flags, enum spoolss_DriverFileType *r)
+{
+       uint32_t v;
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+       *r = v;
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_DriverFileType(struct ndr_print *ndr, const char *name, enum spoolss_DriverFileType r)
+{
+       const char *val = NULL;
+
+       switch (r) {
+               case SPOOLSS_DRIVER_FILE_TYPE_RENDERING: val = "SPOOLSS_DRIVER_FILE_TYPE_RENDERING"; break;
+               case SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION: val = "SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION"; break;
+               case SPOOLSS_DRIVER_FILE_TYPE_DATA: val = "SPOOLSS_DRIVER_FILE_TYPE_DATA"; break;
+               case SPOOLSS_DRIVER_FILE_TYPE_HELP: val = "SPOOLSS_DRIVER_FILE_TYPE_HELP"; break;
+               case SPOOLSS_DRIVER_FILE_TYPE_OTHER: val = "SPOOLSS_DRIVER_FILE_TYPE_OTHER"; break;
+       }
+       ndr_print_enum(ndr, name, "ENUM", val, r);
+}
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverFileInfo(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverFileInfo *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->file_name));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_spoolss_DriverFileType(ndr, NDR_SCALARS, r->file_type));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->file_version));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->file_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->file_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->file_name));
+                       }
+                       ndr->flags = _flags_save_string;
                }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverFileInfo(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverFileInfo *r)
+{
+       uint32_t _ptr_file_name;
+       TALLOC_CTX *_mem_save_file_name_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
                {
                        uint32_t _flags_save_string = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
-                       if (r->inf_path) {
-                               uint32_t _relative_save_offset;
-                               _relative_save_offset = ndr->offset;
-                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->inf_path));
-                               _mem_save_inf_path_0 = NDR_PULL_GET_MEM_CTX(ndr);
-                               NDR_PULL_SET_MEM_CTX(ndr, r->inf_path, 0);
-                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->inf_path));
-                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_inf_path_0, 0);
-                               ndr->offset = _relative_save_offset;
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_file_name));
+                       if (_ptr_file_name) {
+                               NDR_PULL_ALLOC(ndr, r->file_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->file_name, _ptr_file_name));
+                       } else {
+                               r->file_name = NULL;
                        }
                        ndr->flags = _flags_save_string;
                }
+               NDR_CHECK(ndr_pull_spoolss_DriverFileType(ndr, NDR_SCALARS, &r->file_type));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->file_version));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
                {
-                       uint32_t _flags_save_string_array = ndr->flags;
+                       uint32_t _flags_save_string = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
-                       if (r->core_driver_dependencies) {
+                       if (r->file_name) {
                                uint32_t _relative_save_offset;
                                _relative_save_offset = ndr->offset;
-                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->core_driver_dependencies));
-                               _mem_save_core_driver_dependencies_0 = NDR_PULL_GET_MEM_CTX(ndr);
-                               NDR_PULL_SET_MEM_CTX(ndr, r->core_driver_dependencies, 0);
-                               NDR_CHECK(ndr_pull_string_array(ndr, NDR_SCALARS, &r->core_driver_dependencies));
-                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_core_driver_dependencies_0, 0);
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->file_name));
+                               _mem_save_file_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->file_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->file_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_file_name_0, 0);
                                ndr->offset = _relative_save_offset;
                        }
-                       ndr->flags = _flags_save_string_array;
+                       ndr->flags = _flags_save_string;
                }
        }
        return NDR_ERR_SUCCESS;
 }
 
-_PUBLIC_ void ndr_print_spoolss_DriverInfo8(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo8 *r)
+_PUBLIC_ void ndr_print_spoolss_DriverFileInfo(struct ndr_print *ndr, const char *name, const struct spoolss_DriverFileInfo *r)
 {
-       ndr_print_struct(ndr, name, "spoolss_DriverInfo8");
+       ndr_print_struct(ndr, name, "spoolss_DriverFileInfo");
+       ndr->depth++;
+       ndr_print_ptr(ndr, "file_name", r->file_name);
+       ndr->depth++;
+       if (r->file_name) {
+               ndr_print_string(ndr, "file_name", r->file_name);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_DriverFileType(ndr, "file_type", r->file_type);
+       ndr_print_uint32(ndr, "file_version", r->file_version);
+       ndr->depth--;
+}
+
+_PUBLIC_ void ndr_print_spoolss_DriverInfo101(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo101 *r)
+{
+       uint32_t cntr_file_info_1;
+       ndr_print_struct(ndr, name, "spoolss_DriverInfo101");
        ndr->depth++;
        ndr_print_spoolss_DriverOSVersion(ndr, "version", r->version);
        ndr_print_ptr(ndr, "driver_name", r->driver_name);
@@ -10425,30 +13374,22 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo8(struct ndr_print *ndr, const char *n
                ndr_print_string(ndr, "architecture", r->architecture);
        }
        ndr->depth--;
-       ndr_print_ptr(ndr, "driver_path", r->driver_path);
-       ndr->depth++;
-       if (r->driver_path) {
-               ndr_print_string(ndr, "driver_path", r->driver_path);
-       }
-       ndr->depth--;
-       ndr_print_ptr(ndr, "data_file", r->data_file);
-       ndr->depth++;
-       if (r->data_file) {
-               ndr_print_string(ndr, "data_file", r->data_file);
-       }
-       ndr->depth--;
-       ndr_print_ptr(ndr, "config_file", r->config_file);
-       ndr->depth++;
-       if (r->config_file) {
-               ndr_print_string(ndr, "config_file", r->config_file);
-       }
-       ndr->depth--;
-       ndr_print_ptr(ndr, "help_file", r->help_file);
+       ndr_print_ptr(ndr, "file_info", r->file_info);
        ndr->depth++;
-       if (r->help_file) {
-               ndr_print_string(ndr, "help_file", r->help_file);
+       if (r->file_info) {
+               ndr->print(ndr, "%s: ARRAY(%d)", "file_info", (int)r->file_count);
+               ndr->depth++;
+               for (cntr_file_info_1=0;cntr_file_info_1<r->file_count;cntr_file_info_1++) {
+                       char *idx_1=NULL;
+                       if (asprintf(&idx_1, "[%d]", cntr_file_info_1) != -1) {
+                               ndr_print_spoolss_DriverFileInfo(ndr, "file_info", &r->file_info[cntr_file_info_1]);
+                               free(idx_1);
+                       }
+               }
+               ndr->depth--;
        }
        ndr->depth--;
+       ndr_print_uint32(ndr, "file_count", r->file_count);
        ndr_print_ptr(ndr, "monitor_name", r->monitor_name);
        ndr->depth++;
        if (r->monitor_name) {
@@ -10461,19 +13402,13 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo8(struct ndr_print *ndr, const char *n
                ndr_print_string(ndr, "default_datatype", r->default_datatype);
        }
        ndr->depth--;
-       ndr_print_ptr(ndr, "dependent_files", r->dependent_files);
-       ndr->depth++;
-       if (r->dependent_files) {
-               ndr_print_string_array(ndr, "dependent_files", r->dependent_files);
-       }
-       ndr->depth--;
        ndr_print_ptr(ndr, "previous_names", r->previous_names);
        ndr->depth++;
        if (r->previous_names) {
                ndr_print_string_array(ndr, "previous_names", r->previous_names);
        }
        ndr->depth--;
-       ndr_print_NTTIME(ndr, "driver_data", r->driver_data);
+       ndr_print_NTTIME(ndr, "driver_date", r->driver_date);
        ndr_print_hyper(ndr, "driver_version", r->driver_version);
        ndr_print_ptr(ndr, "manufacturer_name", r->manufacturer_name);
        ndr->depth++;
@@ -10499,42 +13434,14 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo8(struct ndr_print *ndr, const char *n
                ndr_print_string(ndr, "provider", r->provider);
        }
        ndr->depth--;
-       ndr_print_ptr(ndr, "print_processor", r->print_processor);
-       ndr->depth++;
-       if (r->print_processor) {
-               ndr_print_string(ndr, "print_processor", r->print_processor);
-       }
-       ndr->depth--;
-       ndr_print_ptr(ndr, "vendor_setup", r->vendor_setup);
-       ndr->depth++;
-       if (r->vendor_setup) {
-               ndr_print_string(ndr, "vendor_setup", r->vendor_setup);
-       }
-       ndr->depth--;
-       ndr_print_ptr(ndr, "color_profiles", r->color_profiles);
-       ndr->depth++;
-       if (r->color_profiles) {
-               ndr_print_string_array(ndr, "color_profiles", r->color_profiles);
-       }
-       ndr->depth--;
-       ndr_print_ptr(ndr, "inf_path", r->inf_path);
-       ndr->depth++;
-       if (r->inf_path) {
-               ndr_print_string(ndr, "inf_path", r->inf_path);
-       }
-       ndr->depth--;
-       ndr_print_uint32(ndr, "printer_driver_attributes", r->printer_driver_attributes);
-       ndr_print_ptr(ndr, "core_driver_dependencies", r->core_driver_dependencies);
-       ndr->depth++;
-       if (r->core_driver_dependencies) {
-               ndr_print_string_array(ndr, "core_driver_dependencies", r->core_driver_dependencies);
-       }
-       ndr->depth--;
-       ndr_print_NTTIME(ndr, "min_inbox_driver_ver_date", r->min_inbox_driver_ver_date);
-       ndr_print_hyper(ndr, "min_inbox_driver_ver_version", r->min_inbox_driver_ver_version);
        ndr->depth--;
 }
 
+_PUBLIC_ size_t ndr_size_spoolss_DriverInfo101(const struct spoolss_DriverInfo101 *r, struct smb_iconv_convenience *ic, int flags)
+{
+       return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_spoolss_DriverInfo101, ic);
+}
+
 _PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_DriverInfo *r)
 {
        uint32_t _save_relative_base_offset = ndr_push_get_relative_base_offset(ndr);
@@ -10583,6 +13490,12 @@ _PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo(struct ndr_push *ndr, int
                                NDR_CHECK(ndr_push_spoolss_DriverInfo8(ndr, NDR_SCALARS, &r->info8));
                        break; }
 
+                       case 101: {
+                               NDR_CHECK(ndr_push_align(ndr, 8));
+                               NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_push_spoolss_DriverInfo101(ndr, NDR_SCALARS, &r->info101));
+                       break; }
+
                        default: {
                        break; }
 
@@ -10620,6 +13533,10 @@ _PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo(struct ndr_push *ndr, int
                                NDR_CHECK(ndr_push_spoolss_DriverInfo8(ndr, NDR_BUFFERS, &r->info8));
                        break;
 
+                       case 101:
+                               NDR_CHECK(ndr_push_spoolss_DriverInfo101(ndr, NDR_BUFFERS, &r->info101));
+                       break;
+
                        default:
                        break;
 
@@ -10678,6 +13595,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo(struct ndr_pull *ndr, int
                                NDR_CHECK(ndr_pull_spoolss_DriverInfo8(ndr, NDR_SCALARS, &r->info8));
                        break; }
 
+                       case 101: {
+                               NDR_CHECK(ndr_pull_align(ndr, 8));
+                               NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_pull_spoolss_DriverInfo101(ndr, NDR_SCALARS, &r->info101));
+                       break; }
+
                        default: {
                        break; }
 
@@ -10714,6 +13637,10 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo(struct ndr_pull *ndr, int
                                NDR_CHECK(ndr_pull_spoolss_DriverInfo8(ndr, NDR_BUFFERS, &r->info8));
                        break;
 
+                       case 101:
+                               NDR_CHECK(ndr_pull_spoolss_DriverInfo101(ndr, NDR_BUFFERS, &r->info101));
+                       break;
+
                        default:
                        break;
 
@@ -10757,6 +13684,10 @@ _PUBLIC_ void ndr_print_spoolss_DriverInfo(struct ndr_print *ndr, const char *na
                        ndr_print_spoolss_DriverInfo8(ndr, "info8", &r->info8);
                break;
 
+               case 101:
+                       ndr_print_spoolss_DriverInfo101(ndr, "info101", &r->info101);
+               break;
+
                default:
                break;
 
@@ -11121,6 +14052,9 @@ _PUBLIC_ enum ndr_err_code ndr_push_spoolss_PrintProcessorDirectoryInfo(struct n
                        break; }
 
                        default: {
+                               NDR_CHECK(ndr_push_align(ndr, 4));
+                               NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_push_spoolss_PrintProcessorDirectoryInfo1(ndr, NDR_SCALARS, &r->info1));
                        break; }
 
                }
@@ -11155,6 +14089,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_PrintProcessorDirectoryInfo(struct n
                        break; }
 
                        default: {
+                               NDR_CHECK(ndr_pull_align(ndr, 4));
+                               NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_pull_spoolss_PrintProcessorDirectoryInfo1(ndr, NDR_SCALARS, &r->info1));
                        break; }
 
                }
@@ -11185,6 +14122,7 @@ _PUBLIC_ void ndr_print_spoolss_PrintProcessorDirectoryInfo(struct ndr_print *nd
                break;
 
                default:
+                       ndr_print_spoolss_PrintProcessorDirectoryInfo1(ndr, "info1", &r->info1);
                break;
 
        }
@@ -11863,55 +14801,165 @@ static enum ndr_err_code ndr_pull_spoolss_FormSize(struct ndr_pull *ndr, int ndr
        return NDR_ERR_SUCCESS;
 }
 
-_PUBLIC_ void ndr_print_spoolss_FormSize(struct ndr_print *ndr, const char *name, const struct spoolss_FormSize *r)
+_PUBLIC_ void ndr_print_spoolss_FormSize(struct ndr_print *ndr, const char *name, const struct spoolss_FormSize *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_FormSize");
+       ndr->depth++;
+       ndr_print_uint32(ndr, "width", r->width);
+       ndr_print_uint32(ndr, "height", r->height);
+       ndr->depth--;
+}
+
+static enum ndr_err_code ndr_push_spoolss_FormArea(struct ndr_push *ndr, int ndr_flags, const struct spoolss_FormArea *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->left));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->top));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->right));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->bottom));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_FormArea(struct ndr_pull *ndr, int ndr_flags, struct spoolss_FormArea *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->left));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->top));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->right));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->bottom));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_FormArea(struct ndr_print *ndr, const char *name, const struct spoolss_FormArea *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_FormArea");
+       ndr->depth++;
+       ndr_print_uint32(ndr, "left", r->left);
+       ndr_print_uint32(ndr, "top", r->top);
+       ndr_print_uint32(ndr, "right", r->right);
+       ndr_print_uint32(ndr, "bottom", r->bottom);
+       ndr->depth--;
+}
+
+static enum ndr_err_code ndr_push_spoolss_FormInfo1(struct ndr_push *ndr, int ndr_flags, const struct spoolss_FormInfo1 *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_spoolss_FormFlags(ndr, NDR_SCALARS, r->flags));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->form_name));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_spoolss_FormSize(ndr, NDR_SCALARS, &r->size));
+               NDR_CHECK(ndr_push_spoolss_FormArea(ndr, NDR_SCALARS, &r->area));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->form_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->form_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->form_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_FormInfo1(struct ndr_pull *ndr, int ndr_flags, struct spoolss_FormInfo1 *r)
+{
+       uint32_t _ptr_form_name;
+       TALLOC_CTX *_mem_save_form_name_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_spoolss_FormFlags(ndr, NDR_SCALARS, &r->flags));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_form_name));
+                       if (_ptr_form_name) {
+                               NDR_PULL_ALLOC(ndr, r->form_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->form_name, _ptr_form_name));
+                       } else {
+                               r->form_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_spoolss_FormSize(ndr, NDR_SCALARS, &r->size));
+               NDR_CHECK(ndr_pull_spoolss_FormArea(ndr, NDR_SCALARS, &r->area));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->form_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->form_name));
+                               _mem_save_form_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->form_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->form_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_form_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_FormInfo1(struct ndr_print *ndr, const char *name, const struct spoolss_FormInfo1 *r)
 {
-       ndr_print_struct(ndr, name, "spoolss_FormSize");
+       ndr_print_struct(ndr, name, "spoolss_FormInfo1");
        ndr->depth++;
-       ndr_print_uint32(ndr, "width", r->width);
-       ndr_print_uint32(ndr, "height", r->height);
+       ndr_print_spoolss_FormFlags(ndr, "flags", r->flags);
+       ndr_print_ptr(ndr, "form_name", r->form_name);
+       ndr->depth++;
+       if (r->form_name) {
+               ndr_print_string(ndr, "form_name", r->form_name);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_FormSize(ndr, "size", &r->size);
+       ndr_print_spoolss_FormArea(ndr, "area", &r->area);
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_spoolss_FormArea(struct ndr_push *ndr, int ndr_flags, const struct spoolss_FormArea *r)
+static enum ndr_err_code ndr_push_spoolss_FormStringType(struct ndr_push *ndr, int ndr_flags, uint32_t r)
 {
-       if (ndr_flags & NDR_SCALARS) {
-               NDR_CHECK(ndr_push_align(ndr, 4));
-               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->left));
-               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->top));
-               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->right));
-               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->bottom));
-       }
-       if (ndr_flags & NDR_BUFFERS) {
-       }
+       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_spoolss_FormArea(struct ndr_pull *ndr, int ndr_flags, struct spoolss_FormArea *r)
+static enum ndr_err_code ndr_pull_spoolss_FormStringType(struct ndr_pull *ndr, int ndr_flags, uint32_t *r)
 {
-       if (ndr_flags & NDR_SCALARS) {
-               NDR_CHECK(ndr_pull_align(ndr, 4));
-               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->left));
-               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->top));
-               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->right));
-               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->bottom));
-       }
-       if (ndr_flags & NDR_BUFFERS) {
-       }
+       uint32_t v;
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+       *r = v;
        return NDR_ERR_SUCCESS;
 }
 
-_PUBLIC_ void ndr_print_spoolss_FormArea(struct ndr_print *ndr, const char *name, const struct spoolss_FormArea *r)
+_PUBLIC_ void ndr_print_spoolss_FormStringType(struct ndr_print *ndr, const char *name, uint32_t r)
 {
-       ndr_print_struct(ndr, name, "spoolss_FormArea");
+       ndr_print_uint32(ndr, name, r);
        ndr->depth++;
-       ndr_print_uint32(ndr, "left", r->left);
-       ndr_print_uint32(ndr, "top", r->top);
-       ndr_print_uint32(ndr, "right", r->right);
-       ndr_print_uint32(ndr, "bottom", r->bottom);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SPOOLSS_FORM_STRING_TYPE_NONE", SPOOLSS_FORM_STRING_TYPE_NONE, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SPOOLSS_FORM_STRING_TYPE_MUI_DLL", SPOOLSS_FORM_STRING_TYPE_MUI_DLL, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "SPOOLSS_FORM_STRING_TYPE_LANG_PAIR", SPOOLSS_FORM_STRING_TYPE_LANG_PAIR, r);
        ndr->depth--;
 }
 
-static enum ndr_err_code ndr_push_spoolss_FormInfo1(struct ndr_push *ndr, int ndr_flags, const struct spoolss_FormInfo1 *r)
+static enum ndr_err_code ndr_push_spoolss_FormInfo2(struct ndr_push *ndr, int ndr_flags, const struct spoolss_FormInfo2 *r)
 {
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
@@ -11924,6 +14972,27 @@ static enum ndr_err_code ndr_push_spoolss_FormInfo1(struct ndr_push *ndr, int nd
                }
                NDR_CHECK(ndr_push_spoolss_FormSize(ndr, NDR_SCALARS, &r->size));
                NDR_CHECK(ndr_push_spoolss_FormArea(ndr, NDR_SCALARS, &r->area));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->keyword));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_spoolss_FormStringType(ndr, NDR_SCALARS, r->string_type));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->mui_dll));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->ressource_id));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->display_name));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->lang_id));
        }
        if (ndr_flags & NDR_BUFFERS) {
                {
@@ -11935,14 +15004,47 @@ static enum ndr_err_code ndr_push_spoolss_FormInfo1(struct ndr_push *ndr, int nd
                        }
                        ndr->flags = _flags_save_string;
                }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->keyword) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->keyword));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->keyword));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->mui_dll) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->mui_dll));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->mui_dll));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->display_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->display_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->display_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
        }
        return NDR_ERR_SUCCESS;
 }
 
-static enum ndr_err_code ndr_pull_spoolss_FormInfo1(struct ndr_pull *ndr, int ndr_flags, struct spoolss_FormInfo1 *r)
+static enum ndr_err_code ndr_pull_spoolss_FormInfo2(struct ndr_pull *ndr, int ndr_flags, struct spoolss_FormInfo2 *r)
 {
        uint32_t _ptr_form_name;
        TALLOC_CTX *_mem_save_form_name_0;
+       uint32_t _ptr_keyword;
+       TALLOC_CTX *_mem_save_keyword_0;
+       uint32_t _ptr_mui_dll;
+       TALLOC_CTX *_mem_save_mui_dll_0;
+       uint32_t _ptr_display_name;
+       TALLOC_CTX *_mem_save_display_name_0;
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_pull_align(ndr, 4));
                NDR_CHECK(ndr_pull_spoolss_FormFlags(ndr, NDR_SCALARS, &r->flags));
@@ -11960,6 +15062,45 @@ static enum ndr_err_code ndr_pull_spoolss_FormInfo1(struct ndr_pull *ndr, int nd
                }
                NDR_CHECK(ndr_pull_spoolss_FormSize(ndr, NDR_SCALARS, &r->size));
                NDR_CHECK(ndr_pull_spoolss_FormArea(ndr, NDR_SCALARS, &r->area));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_keyword));
+                       if (_ptr_keyword) {
+                               NDR_PULL_ALLOC(ndr, r->keyword);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->keyword, _ptr_keyword));
+                       } else {
+                               r->keyword = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_spoolss_FormStringType(ndr, NDR_SCALARS, &r->string_type));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_mui_dll));
+                       if (_ptr_mui_dll) {
+                               NDR_PULL_ALLOC(ndr, r->mui_dll);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->mui_dll, _ptr_mui_dll));
+                       } else {
+                               r->mui_dll = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->ressource_id));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_display_name));
+                       if (_ptr_display_name) {
+                               NDR_PULL_ALLOC(ndr, r->display_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->display_name, _ptr_display_name));
+                       } else {
+                               r->display_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->lang_id));
        }
        if (ndr_flags & NDR_BUFFERS) {
                {
@@ -11977,13 +15118,58 @@ static enum ndr_err_code ndr_pull_spoolss_FormInfo1(struct ndr_pull *ndr, int nd
                        }
                        ndr->flags = _flags_save_string;
                }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->keyword) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->keyword));
+                               _mem_save_keyword_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->keyword, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->keyword));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_keyword_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->mui_dll) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->mui_dll));
+                               _mem_save_mui_dll_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->mui_dll, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->mui_dll));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_mui_dll_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->display_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->display_name));
+                               _mem_save_display_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->display_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->display_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_display_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
        }
        return NDR_ERR_SUCCESS;
 }
 
-_PUBLIC_ void ndr_print_spoolss_FormInfo1(struct ndr_print *ndr, const char *name, const struct spoolss_FormInfo1 *r)
+_PUBLIC_ void ndr_print_spoolss_FormInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_FormInfo2 *r)
 {
-       ndr_print_struct(ndr, name, "spoolss_FormInfo1");
+       ndr_print_struct(ndr, name, "spoolss_FormInfo2");
        ndr->depth++;
        ndr_print_spoolss_FormFlags(ndr, "flags", r->flags);
        ndr_print_ptr(ndr, "form_name", r->form_name);
@@ -11994,6 +15180,27 @@ _PUBLIC_ void ndr_print_spoolss_FormInfo1(struct ndr_print *ndr, const char *nam
        ndr->depth--;
        ndr_print_spoolss_FormSize(ndr, "size", &r->size);
        ndr_print_spoolss_FormArea(ndr, "area", &r->area);
+       ndr_print_ptr(ndr, "keyword", r->keyword);
+       ndr->depth++;
+       if (r->keyword) {
+               ndr_print_string(ndr, "keyword", r->keyword);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_FormStringType(ndr, "string_type", r->string_type);
+       ndr_print_ptr(ndr, "mui_dll", r->mui_dll);
+       ndr->depth++;
+       if (r->mui_dll) {
+               ndr_print_string(ndr, "mui_dll", r->mui_dll);
+       }
+       ndr->depth--;
+       ndr_print_uint32(ndr, "ressource_id", r->ressource_id);
+       ndr_print_ptr(ndr, "display_name", r->display_name);
+       ndr->depth++;
+       if (r->display_name) {
+               ndr_print_string(ndr, "display_name", r->display_name);
+       }
+       ndr->depth--;
+       ndr_print_uint32(ndr, "lang_id", r->lang_id);
        ndr->depth--;
 }
 
@@ -12009,6 +15216,12 @@ _PUBLIC_ enum ndr_err_code ndr_push_spoolss_FormInfo(struct ndr_push *ndr, int n
                                NDR_CHECK(ndr_push_spoolss_FormInfo1(ndr, NDR_SCALARS, &r->info1));
                        break; }
 
+                       case 2: {
+                               NDR_CHECK(ndr_push_align(ndr, 4));
+                               NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_push_spoolss_FormInfo2(ndr, NDR_SCALARS, &r->info2));
+                       break; }
+
                        default: {
                        break; }
 
@@ -12022,6 +15235,10 @@ _PUBLIC_ enum ndr_err_code ndr_push_spoolss_FormInfo(struct ndr_push *ndr, int n
                                NDR_CHECK(ndr_push_spoolss_FormInfo1(ndr, NDR_BUFFERS, &r->info1));
                        break;
 
+                       case 2:
+                               NDR_CHECK(ndr_push_spoolss_FormInfo2(ndr, NDR_BUFFERS, &r->info2));
+                       break;
+
                        default:
                        break;
 
@@ -12044,6 +15261,12 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_FormInfo(struct ndr_pull *ndr, int n
                                NDR_CHECK(ndr_pull_spoolss_FormInfo1(ndr, NDR_SCALARS, &r->info1));
                        break; }
 
+                       case 2: {
+                               NDR_CHECK(ndr_pull_align(ndr, 4));
+                               NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_pull_spoolss_FormInfo2(ndr, NDR_SCALARS, &r->info2));
+                       break; }
+
                        default: {
                        break; }
 
@@ -12056,6 +15279,10 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_FormInfo(struct ndr_pull *ndr, int n
                                NDR_CHECK(ndr_pull_spoolss_FormInfo1(ndr, NDR_BUFFERS, &r->info1));
                        break;
 
+                       case 2:
+                               NDR_CHECK(ndr_pull_spoolss_FormInfo2(ndr, NDR_BUFFERS, &r->info2));
+                       break;
+
                        default:
                        break;
 
@@ -12075,6 +15302,10 @@ _PUBLIC_ void ndr_print_spoolss_FormInfo(struct ndr_print *ndr, const char *name
                        ndr_print_spoolss_FormInfo1(ndr, "info1", &r->info1);
                break;
 
+               case 2:
+                       ndr_print_spoolss_FormInfo2(ndr, "info2", &r->info2);
+               break;
+
                default:
                break;
 
@@ -12155,6 +15386,183 @@ _PUBLIC_ void ndr_print_spoolss_AddFormInfo1(struct ndr_print *ndr, const char *
        ndr->depth--;
 }
 
+static enum ndr_err_code ndr_push_spoolss_AddFormInfo2(struct ndr_push *ndr, int ndr_flags, const struct spoolss_AddFormInfo2 *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_spoolss_FormFlags(ndr, NDR_SCALARS, r->flags));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->form_name));
+               NDR_CHECK(ndr_push_spoolss_FormSize(ndr, NDR_SCALARS, &r->size));
+               NDR_CHECK(ndr_push_spoolss_FormArea(ndr, NDR_SCALARS, &r->area));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->keyword));
+               NDR_CHECK(ndr_push_spoolss_FormStringType(ndr, NDR_SCALARS, r->string_type));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->mui_dll));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->ressource_id));
+               NDR_CHECK(ndr_push_unique_ptr(ndr, r->display_name));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->lang_id));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               if (r->form_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->form_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->form_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->form_name, ndr_charset_length(r->form_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->keyword) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->keyword, CH_DOS)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->keyword, CH_DOS)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->keyword, ndr_charset_length(r->keyword, CH_DOS), sizeof(uint8_t), CH_DOS));
+               }
+               if (r->mui_dll) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->mui_dll, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->mui_dll, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->mui_dll, ndr_charset_length(r->mui_dll, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+               if (r->display_name) {
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->display_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_charset_length(r->display_name, CH_UTF16)));
+                       NDR_CHECK(ndr_push_charset(ndr, NDR_SCALARS, r->display_name, ndr_charset_length(r->display_name, CH_UTF16), sizeof(uint16_t), CH_UTF16));
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_AddFormInfo2(struct ndr_pull *ndr, int ndr_flags, struct spoolss_AddFormInfo2 *r)
+{
+       uint32_t _ptr_form_name;
+       TALLOC_CTX *_mem_save_form_name_0;
+       uint32_t _ptr_keyword;
+       TALLOC_CTX *_mem_save_keyword_0;
+       uint32_t _ptr_mui_dll;
+       TALLOC_CTX *_mem_save_mui_dll_0;
+       uint32_t _ptr_display_name;
+       TALLOC_CTX *_mem_save_display_name_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_spoolss_FormFlags(ndr, NDR_SCALARS, &r->flags));
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_form_name));
+               if (_ptr_form_name) {
+                       NDR_PULL_ALLOC(ndr, r->form_name);
+               } else {
+                       r->form_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_spoolss_FormSize(ndr, NDR_SCALARS, &r->size));
+               NDR_CHECK(ndr_pull_spoolss_FormArea(ndr, NDR_SCALARS, &r->area));
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_keyword));
+               if (_ptr_keyword) {
+                       NDR_PULL_ALLOC(ndr, r->keyword);
+               } else {
+                       r->keyword = NULL;
+               }
+               NDR_CHECK(ndr_pull_spoolss_FormStringType(ndr, NDR_SCALARS, &r->string_type));
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_mui_dll));
+               if (_ptr_mui_dll) {
+                       NDR_PULL_ALLOC(ndr, r->mui_dll);
+               } else {
+                       r->mui_dll = NULL;
+               }
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->ressource_id));
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_display_name));
+               if (_ptr_display_name) {
+                       NDR_PULL_ALLOC(ndr, r->display_name);
+               } else {
+                       r->display_name = NULL;
+               }
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->lang_id));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               if (r->form_name) {
+                       _mem_save_form_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->form_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->form_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->form_name));
+                       if (ndr_get_array_length(ndr, &r->form_name) > ndr_get_array_size(ndr, &r->form_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->form_name), ndr_get_array_length(ndr, &r->form_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->form_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->form_name, ndr_get_array_length(ndr, &r->form_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_form_name_0, 0);
+               }
+               if (r->keyword) {
+                       _mem_save_keyword_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->keyword, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->keyword));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->keyword));
+                       if (ndr_get_array_length(ndr, &r->keyword) > ndr_get_array_size(ndr, &r->keyword)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->keyword), ndr_get_array_length(ndr, &r->keyword));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->keyword), sizeof(uint8_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->keyword, ndr_get_array_length(ndr, &r->keyword), sizeof(uint8_t), CH_DOS));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_keyword_0, 0);
+               }
+               if (r->mui_dll) {
+                       _mem_save_mui_dll_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->mui_dll, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->mui_dll));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->mui_dll));
+                       if (ndr_get_array_length(ndr, &r->mui_dll) > ndr_get_array_size(ndr, &r->mui_dll)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->mui_dll), ndr_get_array_length(ndr, &r->mui_dll));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->mui_dll), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->mui_dll, ndr_get_array_length(ndr, &r->mui_dll), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_mui_dll_0, 0);
+               }
+               if (r->display_name) {
+                       _mem_save_display_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->display_name, 0);
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->display_name));
+                       NDR_CHECK(ndr_pull_array_length(ndr, &r->display_name));
+                       if (ndr_get_array_length(ndr, &r->display_name) > ndr_get_array_size(ndr, &r->display_name)) {
+                               return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size %u should exceed array length %u", ndr_get_array_size(ndr, &r->display_name), ndr_get_array_length(ndr, &r->display_name));
+                       }
+                       NDR_CHECK(ndr_check_string_terminator(ndr, ndr_get_array_length(ndr, &r->display_name), sizeof(uint16_t)));
+                       NDR_CHECK(ndr_pull_charset(ndr, NDR_SCALARS, &r->display_name, ndr_get_array_length(ndr, &r->display_name), sizeof(uint16_t), CH_UTF16));
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_display_name_0, 0);
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_AddFormInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_AddFormInfo2 *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_AddFormInfo2");
+       ndr->depth++;
+       ndr_print_spoolss_FormFlags(ndr, "flags", r->flags);
+       ndr_print_ptr(ndr, "form_name", r->form_name);
+       ndr->depth++;
+       if (r->form_name) {
+               ndr_print_string(ndr, "form_name", r->form_name);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_FormSize(ndr, "size", &r->size);
+       ndr_print_spoolss_FormArea(ndr, "area", &r->area);
+       ndr_print_ptr(ndr, "keyword", r->keyword);
+       ndr->depth++;
+       if (r->keyword) {
+               ndr_print_string(ndr, "keyword", r->keyword);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_FormStringType(ndr, "string_type", r->string_type);
+       ndr_print_ptr(ndr, "mui_dll", r->mui_dll);
+       ndr->depth++;
+       if (r->mui_dll) {
+               ndr_print_string(ndr, "mui_dll", r->mui_dll);
+       }
+       ndr->depth--;
+       ndr_print_uint32(ndr, "ressource_id", r->ressource_id);
+       ndr_print_ptr(ndr, "display_name", r->display_name);
+       ndr->depth++;
+       if (r->display_name) {
+               ndr_print_string(ndr, "display_name", r->display_name);
+       }
+       ndr->depth--;
+       ndr_print_uint32(ndr, "lang_id", r->lang_id);
+       ndr->depth--;
+}
+
 static enum ndr_err_code ndr_push_spoolss_AddFormInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_AddFormInfo *r)
 {
        if (ndr_flags & NDR_SCALARS) {
@@ -12165,6 +15573,10 @@ static enum ndr_err_code ndr_push_spoolss_AddFormInfo(struct ndr_push *ndr, int
                                NDR_CHECK(ndr_push_unique_ptr(ndr, r->info1));
                        break; }
 
+                       case 2: {
+                               NDR_CHECK(ndr_push_unique_ptr(ndr, r->info2));
+                       break; }
+
                        default:
                                return ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
                }
@@ -12178,6 +15590,12 @@ static enum ndr_err_code ndr_push_spoolss_AddFormInfo(struct ndr_push *ndr, int
                                }
                        break;
 
+                       case 2:
+                               if (r->info2) {
+                                       NDR_CHECK(ndr_push_spoolss_AddFormInfo2(ndr, NDR_SCALARS|NDR_BUFFERS, r->info2));
+                               }
+                       break;
+
                        default:
                                return ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
                }
@@ -12190,6 +15608,7 @@ static enum ndr_err_code ndr_pull_spoolss_AddFormInfo(struct ndr_pull *ndr, int
        int level;
        uint32_t _level;
        TALLOC_CTX *_mem_save_info1_0;
+       TALLOC_CTX *_mem_save_info2_0;
        level = ndr_pull_get_switch_value(ndr, r);
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &_level));
@@ -12207,6 +15626,16 @@ static enum ndr_err_code ndr_pull_spoolss_AddFormInfo(struct ndr_pull *ndr, int
                                }
                        break; }
 
+                       case 2: {
+                               uint32_t _ptr_info2;
+                               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_info2));
+                               if (_ptr_info2) {
+                                       NDR_PULL_ALLOC(ndr, r->info2);
+                               } else {
+                                       r->info2 = NULL;
+                               }
+                       break; }
+
                        default:
                                return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
                }
@@ -12222,6 +15651,15 @@ static enum ndr_err_code ndr_pull_spoolss_AddFormInfo(struct ndr_pull *ndr, int
                                }
                        break;
 
+                       case 2:
+                               if (r->info2) {
+                                       _mem_save_info2_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                                       NDR_PULL_SET_MEM_CTX(ndr, r->info2, 0);
+                                       NDR_CHECK(ndr_pull_spoolss_AddFormInfo2(ndr, NDR_SCALARS|NDR_BUFFERS, r->info2));
+                                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info2_0, 0);
+                               }
+                       break;
+
                        default:
                                return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, "Bad switch value %u", level);
                }
@@ -12244,6 +15682,15 @@ _PUBLIC_ void ndr_print_spoolss_AddFormInfo(struct ndr_print *ndr, const char *n
                        ndr->depth--;
                break;
 
+               case 2:
+                       ndr_print_ptr(ndr, "info2", r->info2);
+                       ndr->depth++;
+                       if (r->info2) {
+                               ndr_print_spoolss_AddFormInfo2(ndr, "info2", r->info2);
+                       }
+                       ndr->depth--;
+               break;
+
                default:
                        ndr_print_bad_level(ndr, name, level);
        }
@@ -12534,6 +15981,231 @@ _PUBLIC_ void ndr_print_spoolss_PortInfo2(struct ndr_print *ndr, const char *nam
        ndr->depth--;
 }
 
+static enum ndr_err_code ndr_push_spoolss_PortStatus(struct ndr_push *ndr, int ndr_flags, enum spoolss_PortStatus r)
+{
+       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_PortStatus(struct ndr_pull *ndr, int ndr_flags, enum spoolss_PortStatus *r)
+{
+       uint32_t v;
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+       *r = v;
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_PortStatus(struct ndr_print *ndr, const char *name, enum spoolss_PortStatus r)
+{
+       const char *val = NULL;
+
+       switch (r) {
+               case PORT_STATUS_CLEAR: val = "PORT_STATUS_CLEAR"; break;
+               case PORT_STATUS_OFFLINE: val = "PORT_STATUS_OFFLINE"; break;
+               case PORT_STATUS_PAPER_JAM: val = "PORT_STATUS_PAPER_JAM"; break;
+               case PORT_STATUS_PAPER_OUT: val = "PORT_STATUS_PAPER_OUT"; break;
+               case PORT_STATUS_OUTPUT_BIN_FULL: val = "PORT_STATUS_OUTPUT_BIN_FULL"; break;
+               case PORT_STATUS_PAPER_PROBLEM: val = "PORT_STATUS_PAPER_PROBLEM"; break;
+               case PORT_STATUS_NO_TONER: val = "PORT_STATUS_NO_TONER"; break;
+               case PORT_STATUS_DOOR_OPEN: val = "PORT_STATUS_DOOR_OPEN"; break;
+               case PORT_STATUS_USER_INTERVENTION: val = "PORT_STATUS_USER_INTERVENTION"; break;
+               case PORT_STATUS_OUT_OF_MEMORY: val = "PORT_STATUS_OUT_OF_MEMORY"; break;
+               case PORT_STATUS_TONER_LOW: val = "PORT_STATUS_TONER_LOW"; break;
+               case PORT_STATUS_WARMING_UP: val = "PORT_STATUS_WARMING_UP"; break;
+               case PORT_STATUS_POWER_SAVE: val = "PORT_STATUS_POWER_SAVE"; break;
+       }
+       ndr_print_enum(ndr, name, "ENUM", val, r);
+}
+
+static enum ndr_err_code ndr_push_spoolss_PortSeverity(struct ndr_push *ndr, int ndr_flags, enum spoolss_PortSeverity r)
+{
+       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_PortSeverity(struct ndr_pull *ndr, int ndr_flags, enum spoolss_PortSeverity *r)
+{
+       uint32_t v;
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+       *r = v;
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_PortSeverity(struct ndr_print *ndr, const char *name, enum spoolss_PortSeverity r)
+{
+       const char *val = NULL;
+
+       switch (r) {
+               case PORT_STATUS_TYPE_ERROR: val = "PORT_STATUS_TYPE_ERROR"; break;
+               case PORT_STATUS_TYPE_WARNING: val = "PORT_STATUS_TYPE_WARNING"; break;
+               case PORT_STATUS_TYPE_INFO: val = "PORT_STATUS_TYPE_INFO"; break;
+       }
+       ndr_print_enum(ndr, name, "ENUM", val, r);
+}
+
+static enum ndr_err_code ndr_push_spoolss_PortInfo3(struct ndr_push *ndr, int ndr_flags, const struct spoolss_PortInfo3 *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_spoolss_PortStatus(ndr, NDR_SCALARS, r->status));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->status_string));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_spoolss_PortSeverity(ndr, NDR_SCALARS, r->severity));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->status_string) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->status_string));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->status_string));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_PortInfo3(struct ndr_pull *ndr, int ndr_flags, struct spoolss_PortInfo3 *r)
+{
+       uint32_t _ptr_status_string;
+       TALLOC_CTX *_mem_save_status_string_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_spoolss_PortStatus(ndr, NDR_SCALARS, &r->status));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_status_string));
+                       if (_ptr_status_string) {
+                               NDR_PULL_ALLOC(ndr, r->status_string);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->status_string, _ptr_status_string));
+                       } else {
+                               r->status_string = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_spoolss_PortSeverity(ndr, NDR_SCALARS, &r->severity));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->status_string) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->status_string));
+                               _mem_save_status_string_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->status_string, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->status_string));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_status_string_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_PortInfo3(struct ndr_print *ndr, const char *name, const struct spoolss_PortInfo3 *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_PortInfo3");
+       ndr->depth++;
+       ndr_print_spoolss_PortStatus(ndr, "status", r->status);
+       ndr_print_ptr(ndr, "status_string", r->status_string);
+       ndr->depth++;
+       if (r->status_string) {
+               ndr_print_string(ndr, "status_string", r->status_string);
+       }
+       ndr->depth--;
+       ndr_print_spoolss_PortSeverity(ndr, "severity", r->severity);
+       ndr->depth--;
+}
+
+static enum ndr_err_code ndr_push_spoolss_PortInfoFF(struct ndr_push *ndr, int ndr_flags, const struct spoolss_PortInfoFF *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->port_name));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->monitor_data));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->port_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->port_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->port_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolss_PortInfoFF(struct ndr_pull *ndr, int ndr_flags, struct spoolss_PortInfoFF *r)
+{
+       uint32_t _ptr_port_name;
+       TALLOC_CTX *_mem_save_port_name_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_port_name));
+                       if (_ptr_port_name) {
+                               NDR_PULL_ALLOC(ndr, r->port_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->port_name, _ptr_port_name));
+                       } else {
+                               r->port_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->monitor_data));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->port_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->port_name));
+                               _mem_save_port_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->port_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->port_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_port_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolss_PortInfoFF(struct ndr_print *ndr, const char *name, const struct spoolss_PortInfoFF *r)
+{
+       ndr_print_struct(ndr, name, "spoolss_PortInfoFF");
+       ndr->depth++;
+       ndr_print_ptr(ndr, "port_name", r->port_name);
+       ndr->depth++;
+       if (r->port_name) {
+               ndr_print_string(ndr, "port_name", r->port_name);
+       }
+       ndr->depth--;
+       ndr_print_DATA_BLOB(ndr, "monitor_data", r->monitor_data);
+       ndr->depth--;
+}
+
 _PUBLIC_ enum ndr_err_code ndr_push_spoolss_PortInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_PortInfo *r)
 {
        uint32_t _save_relative_base_offset = ndr_push_get_relative_base_offset(ndr);
@@ -12553,6 +16225,15 @@ _PUBLIC_ enum ndr_err_code ndr_push_spoolss_PortInfo(struct ndr_push *ndr, int n
                        break; }
 
                        case 3: {
+                               NDR_CHECK(ndr_push_align(ndr, 4));
+                               NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_push_spoolss_PortInfo3(ndr, NDR_SCALARS, &r->info3));
+                       break; }
+
+                       case 0xff: {
+                               NDR_CHECK(ndr_push_align(ndr, 4));
+                               NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_push_spoolss_PortInfoFF(ndr, NDR_SCALARS, &r->infoFF));
                        break; }
 
                        default: {
@@ -12573,6 +16254,11 @@ _PUBLIC_ enum ndr_err_code ndr_push_spoolss_PortInfo(struct ndr_push *ndr, int n
                        break;
 
                        case 3:
+                               NDR_CHECK(ndr_push_spoolss_PortInfo3(ndr, NDR_BUFFERS, &r->info3));
+                       break;
+
+                       case 0xff:
+                               NDR_CHECK(ndr_push_spoolss_PortInfoFF(ndr, NDR_BUFFERS, &r->infoFF));
                        break;
 
                        default:
@@ -12604,6 +16290,15 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_PortInfo(struct ndr_pull *ndr, int n
                        break; }
 
                        case 3: {
+                               NDR_CHECK(ndr_pull_align(ndr, 4));
+                               NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_pull_spoolss_PortInfo3(ndr, NDR_SCALARS, &r->info3));
+                       break; }
+
+                       case 0xff: {
+                               NDR_CHECK(ndr_pull_align(ndr, 4));
+                               NDR_CHECK(ndr_pull_setup_relative_base_offset1(ndr, r, ndr->offset));
+                               NDR_CHECK(ndr_pull_spoolss_PortInfoFF(ndr, NDR_SCALARS, &r->infoFF));
                        break; }
 
                        default: {
@@ -12623,6 +16318,11 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_PortInfo(struct ndr_pull *ndr, int n
                        break;
 
                        case 3:
+                               NDR_CHECK(ndr_pull_spoolss_PortInfo3(ndr, NDR_BUFFERS, &r->info3));
+                       break;
+
+                       case 0xff:
+                               NDR_CHECK(ndr_pull_spoolss_PortInfoFF(ndr, NDR_BUFFERS, &r->infoFF));
                        break;
 
                        default:
@@ -12649,6 +16349,11 @@ _PUBLIC_ void ndr_print_spoolss_PortInfo(struct ndr_print *ndr, const char *name
                break;
 
                case 3:
+                       ndr_print_spoolss_PortInfo3(ndr, "info3", &r->info3);
+               break;
+
+               case 0xff:
+                       ndr_print_spoolss_PortInfoFF(ndr, "infoFF", &r->infoFF);
                break;
 
                default:
@@ -13053,6 +16758,7 @@ _PUBLIC_ void ndr_print_spoolss_PrinterChangeFlags(struct ndr_print *ndr, const
        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "PRINTER_CHANGE_DELETE_PORT", PRINTER_CHANGE_DELETE_PORT, r);
        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "PRINTER_CHANGE_ADD_PRINT_PROCESSOR", PRINTER_CHANGE_ADD_PRINT_PROCESSOR, r);
        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "PRINTER_CHANGE_DELETE_PRINT_PROCESSOR", PRINTER_CHANGE_DELETE_PRINT_PROCESSOR, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "PRINTER_CHANGE_SERVER", PRINTER_CHANGE_SERVER, r);
        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "PRINTER_CHANGE_ADD_PRINTER_DRIVER", PRINTER_CHANGE_ADD_PRINTER_DRIVER, r);
        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "PRINTER_CHANGE_SET_PRINTER_DRIVER", PRINTER_CHANGE_SET_PRINTER_DRIVER, r);
        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "PRINTER_CHANGE_DELETE_PRINTER_DRIVER", PRINTER_CHANGE_DELETE_PRINTER_DRIVER, r);
@@ -13226,13 +16932,35 @@ _PUBLIC_ void ndr_print_spoolss_NotifyOptionType(struct ndr_print *ndr, const ch
        ndr->depth--;
 }
 
+static enum ndr_err_code ndr_push_spoolssNotifyOptionFlags(struct ndr_push *ndr, int ndr_flags, uint32_t r)
+{
+       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r));
+       return NDR_ERR_SUCCESS;
+}
+
+static enum ndr_err_code ndr_pull_spoolssNotifyOptionFlags(struct ndr_pull *ndr, int ndr_flags, uint32_t *r)
+{
+       uint32_t v;
+       NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
+       *r = v;
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ void ndr_print_spoolssNotifyOptionFlags(struct ndr_print *ndr, const char *name, uint32_t r)
+{
+       ndr_print_uint32(ndr, name, r);
+       ndr->depth++;
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "PRINTER_NOTIFY_OPTIONS_REFRESH", PRINTER_NOTIFY_OPTIONS_REFRESH, r);
+       ndr->depth--;
+}
+
 static enum ndr_err_code ndr_push_spoolss_NotifyOption(struct ndr_push *ndr, int ndr_flags, const struct spoolss_NotifyOption *r)
 {
        uint32_t cntr_types_1;
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_push_align(ndr, 4));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 2));
-               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->flags));
+               NDR_CHECK(ndr_push_spoolssNotifyOptionFlags(ndr, NDR_SCALARS, r->flags));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->count));
                NDR_CHECK(ndr_push_unique_ptr(ndr, r->types));
        }
@@ -13259,7 +16987,7 @@ static enum ndr_err_code ndr_pull_spoolss_NotifyOption(struct ndr_pull *ndr, int
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_pull_align(ndr, 4));
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->version));
-               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->flags));
+               NDR_CHECK(ndr_pull_spoolssNotifyOptionFlags(ndr, NDR_SCALARS, &r->flags));
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->count));
                NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_types));
                if (_ptr_types) {
@@ -13298,7 +17026,7 @@ _PUBLIC_ void ndr_print_spoolss_NotifyOption(struct ndr_print *ndr, const char *
        ndr_print_struct(ndr, name, "spoolss_NotifyOption");
        ndr->depth++;
        ndr_print_uint32(ndr, "version", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?2:r->version);
-       ndr_print_uint32(ndr, "flags", r->flags);
+       ndr_print_spoolssNotifyOptionFlags(ndr, "flags", r->flags);
        ndr_print_uint32(ndr, "count", r->count);
        ndr_print_ptr(ndr, "types", r->types);
        ndr->depth++;
@@ -13423,7 +17151,7 @@ static enum ndr_err_code ndr_push_spoolss_NotifyData(struct ndr_push *ndr, int n
                        break; }
 
                        case 3: {
-                               NDR_CHECK(ndr_push_unique_ptr(ndr, r->devmode));
+                               NDR_CHECK(ndr_push_spoolss_DevmodeContainer(ndr, NDR_SCALARS, &r->devmode));
                        break; }
 
                        case 4: {
@@ -13449,9 +17177,7 @@ static enum ndr_err_code ndr_push_spoolss_NotifyData(struct ndr_push *ndr, int n
                        break;
 
                        case 3:
-                               if (r->devmode) {
-                                       NDR_CHECK(ndr_push_spoolss_DeviceMode(ndr, NDR_SCALARS, r->devmode));
-                               }
+                               NDR_CHECK(ndr_push_spoolss_DevmodeContainer(ndr, NDR_BUFFERS, &r->devmode));
                        break;
 
                        case 4:
@@ -13473,7 +17199,6 @@ static enum ndr_err_code ndr_pull_spoolss_NotifyData(struct ndr_pull *ndr, int n
 {
        int level;
        uint32_t _level;
-       TALLOC_CTX *_mem_save_devmode_0;
        level = ndr_pull_get_switch_value(ndr, r);
        if (ndr_flags & NDR_SCALARS) {
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &_level));
@@ -13493,13 +17218,7 @@ static enum ndr_err_code ndr_pull_spoolss_NotifyData(struct ndr_pull *ndr, int n
                        break; }
 
                        case 3: {
-                               uint32_t _ptr_devmode;
-                               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_devmode));
-                               if (_ptr_devmode) {
-                                       NDR_PULL_ALLOC(ndr, r->devmode);
-                               } else {
-                                       r->devmode = NULL;
-                               }
+                               NDR_CHECK(ndr_pull_spoolss_DevmodeContainer(ndr, NDR_SCALARS, &r->devmode));
                        break; }
 
                        case 4: {
@@ -13524,12 +17243,7 @@ static enum ndr_err_code ndr_pull_spoolss_NotifyData(struct ndr_pull *ndr, int n
                        break;
 
                        case 3:
-                               if (r->devmode) {
-                                       _mem_save_devmode_0 = NDR_PULL_GET_MEM_CTX(ndr);
-                                       NDR_PULL_SET_MEM_CTX(ndr, r->devmode, 0);
-                                       NDR_CHECK(ndr_pull_spoolss_DeviceMode(ndr, NDR_SCALARS, r->devmode));
-                                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_devmode_0, 0);
-                               }
+                               NDR_CHECK(ndr_pull_spoolss_DevmodeContainer(ndr, NDR_BUFFERS, &r->devmode));
                        break;
 
                        case 4:
@@ -13572,12 +17286,7 @@ _PUBLIC_ void ndr_print_spoolss_NotifyData(struct ndr_print *ndr, const char *na
                break;
 
                case 3:
-                       ndr_print_ptr(ndr, "devmode", r->devmode);
-                       ndr->depth++;
-                       if (r->devmode) {
-                               ndr_print_spoolss_DeviceMode(ndr, "devmode", r->devmode);
-                       }
-                       ndr->depth--;
+                       ndr_print_spoolss_DevmodeContainer(ndr, "devmode", &r->devmode);
                break;
 
                case 4:
@@ -14320,6 +18029,7 @@ _PUBLIC_ void ndr_print_spoolss_AccessRights(struct ndr_print *ndr, const char *
        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "PRINTER_ACCESS_ADMINISTER", PRINTER_ACCESS_ADMINISTER, r);
        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "PRINTER_ACCESS_USE", PRINTER_ACCESS_USE, r);
        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_ACCESS_ADMINISTER", JOB_ACCESS_ADMINISTER, r);
+       ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "JOB_ACCESS_READ", JOB_ACCESS_READ, r);
        ndr->depth--;
 }
 
@@ -16809,7 +20519,7 @@ static enum ndr_err_code ndr_push_spoolss_GetPrintProcessorDirectory(struct ndr_
                                struct ndr_push *_ndr_info;
                                NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_info, 4, r->in.offered));
                                NDR_CHECK(ndr_push_set_switch_value(_ndr_info, r->out.info, r->in.level));
-                               NDR_CHECK(ndr_push_spoolss_PrintProcessorDirectoryInfo(_ndr_info, NDR_SCALARS|NDR_BUFFERS, r->out.info));
+                               NDR_CHECK(ndr_push_spoolss_PrintProcessorDirectoryInfo(_ndr_info, NDR_SCALARS, r->out.info));
                                NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_info, 4, r->in.offered));
                        }
                }
@@ -16903,7 +20613,7 @@ static enum ndr_err_code ndr_pull_spoolss_GetPrintProcessorDirectory(struct ndr_
                                struct ndr_pull *_ndr_info;
                                NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_info, 4, r->in.offered));
                                NDR_CHECK(ndr_pull_set_switch_value(_ndr_info, r->out.info, r->in.level));
-                               NDR_CHECK(ndr_pull_spoolss_PrintProcessorDirectoryInfo(_ndr_info, NDR_SCALARS|NDR_BUFFERS, r->out.info));
+                               NDR_CHECK(ndr_pull_spoolss_PrintProcessorDirectoryInfo(_ndr_info, NDR_SCALARS, r->out.info));
                                NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_info, 4, r->in.offered));
                        }
                        NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info_0, 0);
@@ -19836,7 +23546,13 @@ static enum ndr_err_code ndr_push_spoolss_GetPrinterDriver2(struct ndr_push *ndr
        if (flags & NDR_OUT) {
                NDR_CHECK(ndr_push_unique_ptr(ndr, r->out.info));
                if (r->out.info) {
-                       NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, *r->out.info));
+                       {
+                               struct ndr_push *_ndr_info;
+                               NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_info, 4, r->in.offered));
+                               NDR_CHECK(ndr_push_set_switch_value(_ndr_info, r->out.info, r->in.level));
+                               NDR_CHECK(ndr_push_spoolss_DriverInfo(_ndr_info, NDR_SCALARS|NDR_BUFFERS, r->out.info));
+                               NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_info, 4, r->in.offered));
+                       }
                }
                if (r->out.needed == NULL) {
                        return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, "NULL [ref] pointer");
@@ -19928,7 +23644,13 @@ static enum ndr_err_code ndr_pull_spoolss_GetPrinterDriver2(struct ndr_pull *ndr
                if (r->out.info) {
                        _mem_save_info_0 = NDR_PULL_GET_MEM_CTX(ndr);
                        NDR_PULL_SET_MEM_CTX(ndr, r->out.info, 0);
-                       NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, r->out.info));
+                       {
+                               struct ndr_pull *_ndr_info;
+                               NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_info, 4, r->in.offered));
+                               NDR_CHECK(ndr_pull_set_switch_value(_ndr_info, r->out.info, r->in.level));
+                               NDR_CHECK(ndr_pull_spoolss_DriverInfo(_ndr_info, NDR_SCALARS|NDR_BUFFERS, r->out.info));
+                               NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_info, 4, r->in.offered));
+                       }
                        NDR_PULL_SET_MEM_CTX(ndr, _mem_save_info_0, 0);
                }
                if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {
@@ -19995,7 +23717,8 @@ _PUBLIC_ void ndr_print_spoolss_GetPrinterDriver2(struct ndr_print *ndr, const c
                ndr_print_ptr(ndr, "info", r->out.info);
                ndr->depth++;
                if (r->out.info) {
-                       ndr_print_DATA_BLOB(ndr, "info", *r->out.info);
+                       ndr_print_set_switch_value(ndr, r->out.info, r->in.level);
+                       ndr_print_spoolss_DriverInfo(ndr, "info", r->out.info);
                }
                ndr->depth--;
                ndr_print_ptr(ndr, "needed", r->out.needed);
index f8d97c19a72ccaf2b05783e18c643ed906c4ec9e..84ab8b7d0566b954aeb3b48a61a6ab5d811cf7d7 100644 (file)
@@ -235,10 +235,20 @@ enum ndr_err_code ndr_push_spoolss_PrinterInfo(struct ndr_push *ndr, int ndr_fla
 enum ndr_err_code ndr_pull_spoolss_PrinterInfo(struct ndr_pull *ndr, int ndr_flags, union spoolss_PrinterInfo *r);
 void ndr_print_spoolss_PrinterInfo(struct ndr_print *ndr, const char *name, const union spoolss_PrinterInfo *r);
 void ndr_print_spoolss_DevmodeContainer(struct ndr_print *ndr, const char *name, const struct spoolss_DevmodeContainer *r);
+void ndr_print_spoolss_JobStatus(struct ndr_print *ndr, const char *name, uint32_t r);
 void ndr_print_spoolss_JobInfo1(struct ndr_print *ndr, const char *name, const struct spoolss_JobInfo1 *r);
+void ndr_print_spoolss_JobInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_JobInfo2 *r);
+void ndr_print_spoolss_JobInfo3(struct ndr_print *ndr, const char *name, const struct spoolss_JobInfo3 *r);
+void ndr_print_spoolss_JobInfo4(struct ndr_print *ndr, const char *name, const struct spoolss_JobInfo4 *r);
 enum ndr_err_code ndr_push_spoolss_JobInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_JobInfo *r);
 enum ndr_err_code ndr_pull_spoolss_JobInfo(struct ndr_pull *ndr, int ndr_flags, union spoolss_JobInfo *r);
 void ndr_print_spoolss_JobInfo(struct ndr_print *ndr, const char *name, const union spoolss_JobInfo *r);
+void ndr_print_spoolss_SetJobInfo1(struct ndr_print *ndr, const char *name, const struct spoolss_SetJobInfo1 *r);
+void ndr_print_spoolss_SetJobInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_SetJobInfo2 *r);
+void ndr_print_spoolss_SetJobInfo4(struct ndr_print *ndr, const char *name, const struct spoolss_SetJobInfo4 *r);
+enum ndr_err_code ndr_push_spoolss_SetJobInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_SetJobInfo *r);
+enum ndr_err_code ndr_pull_spoolss_SetJobInfo(struct ndr_pull *ndr, int ndr_flags, union spoolss_SetJobInfo *r);
+void ndr_print_spoolss_SetJobInfo(struct ndr_print *ndr, const char *name, const union spoolss_SetJobInfo *r);
 void ndr_print_spoolss_JobInfoContainer(struct ndr_print *ndr, const char *name, const struct spoolss_JobInfoContainer *r);
 void ndr_print_spoolss_JobControl(struct ndr_print *ndr, const char *name, enum spoolss_JobControl r);
 void ndr_print_spoolss_PrinterControl(struct ndr_print *ndr, const char *name, enum spoolss_PrinterControl r);
@@ -256,6 +266,8 @@ enum ndr_err_code ndr_push_spoolss_StringArray(struct ndr_push *ndr, int ndr_fla
 enum ndr_err_code ndr_pull_spoolss_StringArray(struct ndr_pull *ndr, int ndr_flags, struct spoolss_StringArray *r);
 void ndr_print_spoolss_StringArray(struct ndr_print *ndr, const char *name, const struct spoolss_StringArray *r);
 void ndr_print_spoolss_AddDriverInfo1(struct ndr_print *ndr, const char *name, const struct spoolss_AddDriverInfo1 *r);
+enum ndr_err_code ndr_push_spoolss_DriverOSVersion(struct ndr_push *ndr, int ndr_flags, enum spoolss_DriverOSVersion r);
+enum ndr_err_code ndr_pull_spoolss_DriverOSVersion(struct ndr_pull *ndr, int ndr_flags, enum spoolss_DriverOSVersion *r);
 void ndr_print_spoolss_DriverOSVersion(struct ndr_print *ndr, const char *name, enum spoolss_DriverOSVersion r);
 void ndr_print_spoolss_AddDriverInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_AddDriverInfo2 *r);
 void ndr_print_spoolss_AddDriverInfo3(struct ndr_print *ndr, const char *name, const struct spoolss_AddDriverInfo3 *r);
@@ -264,13 +276,42 @@ void ndr_print_spoolss_AddDriverInfo6(struct ndr_print *ndr, const char *name, c
 void ndr_print_spoolss_AddDriverInfo8(struct ndr_print *ndr, const char *name, const struct spoolss_AddDriverInfo8 *r);
 void ndr_print_spoolss_AddDriverInfo(struct ndr_print *ndr, const char *name, const union spoolss_AddDriverInfo *r);
 void ndr_print_spoolss_AddDriverInfoCtr(struct ndr_print *ndr, const char *name, const struct spoolss_AddDriverInfoCtr *r);
+enum ndr_err_code ndr_push_spoolss_DriverInfo1(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo1 *r);
+enum ndr_err_code ndr_pull_spoolss_DriverInfo1(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo1 *r);
 void ndr_print_spoolss_DriverInfo1(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo1 *r);
+size_t ndr_size_spoolss_DriverInfo1(const struct spoolss_DriverInfo1 *r, struct smb_iconv_convenience *ic, int flags);
+enum ndr_err_code ndr_push_spoolss_DriverInfo2(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo2 *r);
+enum ndr_err_code ndr_pull_spoolss_DriverInfo2(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo2 *r);
 void ndr_print_spoolss_DriverInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo2 *r);
+size_t ndr_size_spoolss_DriverInfo2(const struct spoolss_DriverInfo2 *r, struct smb_iconv_convenience *ic, int flags);
+enum ndr_err_code ndr_push_spoolss_DriverInfo3(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo3 *r);
+enum ndr_err_code ndr_pull_spoolss_DriverInfo3(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo3 *r);
 void ndr_print_spoolss_DriverInfo3(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo3 *r);
+size_t ndr_size_spoolss_DriverInfo3(const struct spoolss_DriverInfo3 *r, struct smb_iconv_convenience *ic, int flags);
+enum ndr_err_code ndr_push_spoolss_DriverInfo4(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo4 *r);
+enum ndr_err_code ndr_pull_spoolss_DriverInfo4(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo4 *r);
 void ndr_print_spoolss_DriverInfo4(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo4 *r);
+size_t ndr_size_spoolss_DriverInfo4(const struct spoolss_DriverInfo4 *r, struct smb_iconv_convenience *ic, int flags);
+enum ndr_err_code ndr_push_spoolss_DriverInfo5(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo5 *r);
+enum ndr_err_code ndr_pull_spoolss_DriverInfo5(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo5 *r);
 void ndr_print_spoolss_DriverInfo5(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo5 *r);
+size_t ndr_size_spoolss_DriverInfo5(const struct spoolss_DriverInfo5 *r, struct smb_iconv_convenience *ic, int flags);
+enum ndr_err_code ndr_push_spoolss_DriverInfo6(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo6 *r);
+enum ndr_err_code ndr_pull_spoolss_DriverInfo6(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo6 *r);
 void ndr_print_spoolss_DriverInfo6(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo6 *r);
+size_t ndr_size_spoolss_DriverInfo6(const struct spoolss_DriverInfo6 *r, struct smb_iconv_convenience *ic, int flags);
+enum ndr_err_code ndr_push_spoolss_DriverInfo8(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo8 *r);
+enum ndr_err_code ndr_pull_spoolss_DriverInfo8(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo8 *r);
 void ndr_print_spoolss_DriverInfo8(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo8 *r);
+size_t ndr_size_spoolss_DriverInfo8(const struct spoolss_DriverInfo8 *r, struct smb_iconv_convenience *ic, int flags);
+void ndr_print_spoolss_DriverFileType(struct ndr_print *ndr, const char *name, enum spoolss_DriverFileType r);
+enum ndr_err_code ndr_push_spoolss_DriverFileInfo(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverFileInfo *r);
+enum ndr_err_code ndr_pull_spoolss_DriverFileInfo(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverFileInfo *r);
+void ndr_print_spoolss_DriverFileInfo(struct ndr_print *ndr, const char *name, const struct spoolss_DriverFileInfo *r);
+enum ndr_err_code ndr_push_spoolss_DriverInfo101(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo101 *r);
+enum ndr_err_code ndr_pull_spoolss_DriverInfo101(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo101 *r);
+void ndr_print_spoolss_DriverInfo101(struct ndr_print *ndr, const char *name, const struct spoolss_DriverInfo101 *r);
+size_t ndr_size_spoolss_DriverInfo101(const struct spoolss_DriverInfo101 *r, struct smb_iconv_convenience *ic, int flags);
 enum ndr_err_code ndr_push_spoolss_DriverInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_DriverInfo *r);
 enum ndr_err_code ndr_pull_spoolss_DriverInfo(struct ndr_pull *ndr, int ndr_flags, union spoolss_DriverInfo *r);
 void ndr_print_spoolss_DriverInfo(struct ndr_print *ndr, const char *name, const union spoolss_DriverInfo *r);
@@ -313,15 +354,22 @@ void ndr_print_spoolss_FormFlags(struct ndr_print *ndr, const char *name, enum s
 void ndr_print_spoolss_FormSize(struct ndr_print *ndr, const char *name, const struct spoolss_FormSize *r);
 void ndr_print_spoolss_FormArea(struct ndr_print *ndr, const char *name, const struct spoolss_FormArea *r);
 void ndr_print_spoolss_FormInfo1(struct ndr_print *ndr, const char *name, const struct spoolss_FormInfo1 *r);
+void ndr_print_spoolss_FormStringType(struct ndr_print *ndr, const char *name, uint32_t r);
+void ndr_print_spoolss_FormInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_FormInfo2 *r);
 enum ndr_err_code ndr_push_spoolss_FormInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_FormInfo *r);
 enum ndr_err_code ndr_pull_spoolss_FormInfo(struct ndr_pull *ndr, int ndr_flags, union spoolss_FormInfo *r);
 void ndr_print_spoolss_FormInfo(struct ndr_print *ndr, const char *name, const union spoolss_FormInfo *r);
 size_t ndr_size_spoolss_FormInfo(const union spoolss_FormInfo *r, uint32_t level, struct smb_iconv_convenience *ic, int flags);
 void ndr_print_spoolss_AddFormInfo1(struct ndr_print *ndr, const char *name, const struct spoolss_AddFormInfo1 *r);
+void ndr_print_spoolss_AddFormInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_AddFormInfo2 *r);
 void ndr_print_spoolss_AddFormInfo(struct ndr_print *ndr, const char *name, const union spoolss_AddFormInfo *r);
 void ndr_print_spoolss_PortInfo1(struct ndr_print *ndr, const char *name, const struct spoolss_PortInfo1 *r);
 void ndr_print_spoolss_PortType(struct ndr_print *ndr, const char *name, uint32_t r);
 void ndr_print_spoolss_PortInfo2(struct ndr_print *ndr, const char *name, const struct spoolss_PortInfo2 *r);
+void ndr_print_spoolss_PortStatus(struct ndr_print *ndr, const char *name, enum spoolss_PortStatus r);
+void ndr_print_spoolss_PortSeverity(struct ndr_print *ndr, const char *name, enum spoolss_PortSeverity r);
+void ndr_print_spoolss_PortInfo3(struct ndr_print *ndr, const char *name, const struct spoolss_PortInfo3 *r);
+void ndr_print_spoolss_PortInfoFF(struct ndr_print *ndr, const char *name, const struct spoolss_PortInfoFF *r);
 enum ndr_err_code ndr_push_spoolss_PortInfo(struct ndr_push *ndr, int ndr_flags, const union spoolss_PortInfo *r);
 enum ndr_err_code ndr_pull_spoolss_PortInfo(struct ndr_pull *ndr, int ndr_flags, union spoolss_PortInfo *r);
 void ndr_print_spoolss_PortInfo(struct ndr_print *ndr, const char *name, const union spoolss_PortInfo *r);
@@ -334,6 +382,7 @@ void ndr_print_spoolss_PrinterChangeFlags(struct ndr_print *ndr, const char *nam
 void ndr_print_spoolss_Field(struct ndr_print *ndr, const char *name, enum spoolss_Field r);
 void ndr_print_spoolss_NotifyType(struct ndr_print *ndr, const char *name, enum spoolss_NotifyType r);
 void ndr_print_spoolss_NotifyOptionType(struct ndr_print *ndr, const char *name, const struct spoolss_NotifyOptionType *r);
+void ndr_print_spoolssNotifyOptionFlags(struct ndr_print *ndr, const char *name, uint32_t r);
 void ndr_print_spoolss_NotifyOption(struct ndr_print *ndr, const char *name, const struct spoolss_NotifyOption *r);
 void ndr_print_spoolss_NotifyString(struct ndr_print *ndr, const char *name, const struct spoolss_NotifyString *r);
 void ndr_print_spoolss_NotifyTable(struct ndr_print *ndr, const char *name, enum spoolss_NotifyTable r);
index d1038d76c82383314a3c3addc60c08305e3ada54..892e770bad1a3ce1c9c567b354dffa93c1008d1f 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/misc.h"
 #include "librpc/gen_ndr/lsa.h"
 #include "librpc/gen_ndr/samr.h"
index 5021aa225271adcff7cd3173978c0ca4dd777cd9..804c452816d71594cf89f517887c0bca71740c7a 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/winreg.h"
 #ifndef _HEADER_ntsvcs
 #define _HEADER_ntsvcs
index 782987de1cbb057cee6e145fb63100b098ae6520..044756469e961cd118da04cb51afe96726e34d80 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/misc.h"
 #include "librpc/gen_ndr/lsa.h"
 #include "librpc/gen_ndr/security.h"
index 4fa9a8084cf97462a794f97c9d9dcea6e3984622..32ea2eaacd9c1931c285cd2c99f63bde2915d216 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/misc.h"
 #define dom_sid2 dom_sid
 #define dom_sid28 dom_sid
index 2faeea2e4064069731e2e3af4017908a691a5b77..b66e4ab2a85e4c8abc33f2507b793d44aa67778b 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/misc.h"
 #include "librpc/gen_ndr/security.h"
 #include "librpc/gen_ndr/winreg.h"
 #define _HEADER_spoolss
 
 #define PRINTER_ENUM_ICONMASK  ( (PRINTER_ENUM_ICON1|PRINTER_ENUM_ICON2|PRINTER_ENUM_ICON3|PRINTER_ENUM_ICON4|PRINTER_ENUM_ICON5|PRINTER_ENUM_ICON6|PRINTER_ENUM_ICON7|PRINTER_ENUM_ICON8) )
+#define JOB_STATUS_QUEUED      ( 0x0000 )
 #define SPOOLSS_ARCHITECTURE_NT_X86    ( "Windows NT x86" )
-#define PRINTER_CHANGE_PRINTER ( (PRINTER_CHANGE_ADD_PRINTER|PRINTER_CHANGE_SET_PRINTER|PRINTER_CHANGE_DELETE_PRINTER|PRINTER_CHANGE_FAILED_CONNECTION_PRINTER) )
-#define PRINTER_CHANGE_JOB     ( (PRINTER_CHANGE_ADD_JOB|PRINTER_CHANGE_SET_JOB|PRINTER_CHANGE_DELETE_JOB|PRINTER_CHANGE_WRITE_JOB) )
+#define SPOOLSS_DEFAULT_SERVER_PATH    ( "C:\\WINDOWS\\system32\\spool" )
+#define PRINTER_CHANGE_PRINTER ( 0x000000FF )
+#define PRINTER_CHANGE_JOB     ( 0x0000FF00 )
 #define PRINTER_CHANGE_FORM    ( (PRINTER_CHANGE_ADD_FORM|PRINTER_CHANGE_SET_FORM|PRINTER_CHANGE_DELETE_FORM) )
 #define PRINTER_CHANGE_PORT    ( (PRINTER_CHANGE_ADD_PORT|PRINTER_CHANGE_CONFIGURE_PORT|PRINTER_CHANGE_DELETE_PORT) )
-#define PRINTER_CHANGE_PRINT_PROCESSOR ( (PRINTER_CHANGE_ADD_PRINT_PROCESSOR|PRINTER_CHANGE_DELETE_PRINT_PROCESSOR) )
+#define PRINTER_CHANGE_PRINT_PROCESSOR ( 0x07000000 )
 #define PRINTER_CHANGE_PRINTER_DRIVER  ( (PRINTER_CHANGE_ADD_PRINTER_DRIVER|PRINTER_CHANGE_SET_PRINTER_DRIVER|PRINTER_CHANGE_DELETE_PRINTER_DRIVER) )
-#define PRINTER_CHANGE_ALL     ( (PRINTER_CHANGE_JOB|PRINTER_CHANGE_FORM|PRINTER_CHANGE_PORT|PRINTER_CHANGE_PRINT_PROCESSOR|PRINTER_CHANGE_PRINTER_DRIVER) )
+#define PRINTER_CHANGE_ALL     ( (PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB|PRINTER_CHANGE_FORM|PRINTER_CHANGE_PORT|PRINTER_CHANGE_PRINT_PROCESSOR|PRINTER_CHANGE_PRINTER_DRIVER) )
 #define SERVER_ALL_ACCESS      ( SEC_STD_REQUIRED|SERVER_ACCESS_ADMINISTER|SERVER_ACCESS_ENUMERATE )
 #define SERVER_READ    ( SEC_STD_READ_CONTROL|SERVER_ACCESS_ENUMERATE )
 #define SERVER_WRITE   ( STANDARD_RIGHTS_WRITE_ACCESS|SERVER_ACCESS_ADMINISTER|SERVER_ACCESS_ENUMERATE )
@@ -369,6 +373,21 @@ struct spoolss_DevmodeContainer {
        struct spoolss_DeviceMode *devmode;/* [unique,subcontext_size(_ndr_size),subcontext(4)] */
 };
 
+/* bitmap spoolss_JobStatus */
+#define JOB_STATUS_PAUSED ( 0x00000001 )
+#define JOB_STATUS_ERROR ( 0x00000002 )
+#define JOB_STATUS_DELETING ( 0x00000004 )
+#define JOB_STATUS_SPOOLING ( 0x00000008 )
+#define JOB_STATUS_PRINTING ( 0x00000010 )
+#define JOB_STATUS_OFFLINE ( 0x00000020 )
+#define JOB_STATUS_PAPEROUT ( 0x00000040 )
+#define JOB_STATUS_PRINTED ( 0x00000080 )
+#define JOB_STATUS_DELETED ( 0x00000100 )
+#define JOB_STATUS_BLOCKED_DEVQ ( 0x00000200 )
+#define JOB_STATUS_USER_INTERVENTION ( 0x00000400 )
+#define JOB_STATUS_RESTART ( 0x00000800 )
+#define JOB_STATUS_COMPLETE ( 0x00001000 )
+
 struct spoolss_JobInfo1 {
        uint32_t job_id;
        const char * printer_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
@@ -382,16 +401,154 @@ struct spoolss_JobInfo1 {
        uint32_t position;
        uint32_t total_pages;
        uint32_t pages_printed;
-       struct spoolss_Time time;
+       struct spoolss_Time submitted;
+};
+
+struct spoolss_JobInfo2 {
+       uint32_t job_id;
+       const char * printer_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * server_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * user_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * document_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * notify_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * data_type;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * print_processor;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * parameters;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * driver_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       struct spoolss_DeviceMode *devmode;/* [relative] */
+       const char * text_status;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       struct security_descriptor *secdesc;/* [relative] */
+       uint32_t status;
+       uint32_t priority;
+       uint32_t position;
+       uint32_t start_time;
+       uint32_t until_time;
+       uint32_t total_pages;
+       uint32_t size;
+       struct spoolss_Time submitted;
+       uint32_t time;
+       uint32_t pages_printed;
+};
+
+struct spoolss_JobInfo3 {
+       uint32_t job_id;
+       uint32_t next_job_id;
+       uint32_t reserved;
+};
+
+struct spoolss_JobInfo4 {
+       uint32_t job_id;
+       const char * printer_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * server_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * user_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * document_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * notify_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * data_type;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * print_processor;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * parameters;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * driver_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       struct spoolss_DeviceMode *devmode;/* [relative] */
+       const char * text_status;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       struct security_descriptor *secdesc;/* [relative] */
+       uint32_t status;
+       uint32_t priority;
+       uint32_t position;
+       uint32_t start_time;
+       uint32_t until_time;
+       uint32_t total_pages;
+       uint32_t size;
+       struct spoolss_Time submitted;
+       uint32_t time;
+       uint32_t pages_printed;
+       uint32_t size_high;
 };
 
 union spoolss_JobInfo {
        struct spoolss_JobInfo1 info1;/* [case] */
+       struct spoolss_JobInfo2 info2;/* [case(2)] */
+       struct spoolss_JobInfo3 info3;/* [case(3)] */
+       struct spoolss_JobInfo4 info4;/* [case(4)] */
 }/* [relative_base,nodiscriminant,public] */;
 
+struct spoolss_SetJobInfo1 {
+       uint32_t job_id;
+       const char *printer_name;/* [unique,charset(UTF16)] */
+       const char *server_name;/* [unique,charset(UTF16)] */
+       const char *user_name;/* [unique,charset(UTF16)] */
+       const char *document_name;/* [unique,charset(UTF16)] */
+       const char *data_type;/* [unique,charset(UTF16)] */
+       const char *text_status;/* [unique,charset(UTF16)] */
+       uint32_t status;
+       uint32_t priority;
+       uint32_t position;
+       uint32_t total_pages;
+       uint32_t pages_printed;
+       struct spoolss_Time submitted;
+};
+
+struct spoolss_SetJobInfo2 {
+       uint32_t job_id;
+       const char *printer_name;/* [unique,charset(UTF16)] */
+       const char *server_name;/* [unique,charset(UTF16)] */
+       const char *user_name;/* [unique,charset(UTF16)] */
+       const char *document_name;/* [unique,charset(UTF16)] */
+       const char *notify_name;/* [unique,charset(UTF16)] */
+       const char *data_type;/* [unique,charset(UTF16)] */
+       const char *print_processor;/* [unique,charset(UTF16)] */
+       const char *parameters;/* [unique,charset(UTF16)] */
+       const char *driver_name;/* [unique,charset(UTF16)] */
+       struct spoolss_DeviceMode *devmode;/* [unique] */
+       const char *text_status;/* [unique,charset(UTF16)] */
+       struct security_descriptor *secdesc;/* [unique] */
+       uint32_t status;
+       uint32_t priority;
+       uint32_t position;
+       uint32_t start_time;
+       uint32_t until_time;
+       uint32_t total_pages;
+       uint32_t size;
+       struct spoolss_Time submitted;
+       uint32_t time;
+       uint32_t pages_printed;
+};
+
+struct spoolss_SetJobInfo4 {
+       uint32_t job_id;
+       const char *printer_name;/* [unique,charset(UTF16)] */
+       const char *server_name;/* [unique,charset(UTF16)] */
+       const char *user_name;/* [unique,charset(UTF16)] */
+       const char *document_name;/* [unique,charset(UTF16)] */
+       const char *notify_name;/* [unique,charset(UTF16)] */
+       const char *data_type;/* [unique,charset(UTF16)] */
+       const char *print_processor;/* [unique,charset(UTF16)] */
+       const char *parameters;/* [unique,charset(UTF16)] */
+       const char *driver_name;/* [unique,charset(UTF16)] */
+       struct spoolss_DeviceMode *devmode;/* [unique] */
+       const char *text_status;/* [unique,charset(UTF16)] */
+       struct security_descriptor *secdesc;/* [unique] */
+       uint32_t status;
+       uint32_t priority;
+       uint32_t position;
+       uint32_t start_time;
+       uint32_t until_time;
+       uint32_t total_pages;
+       uint32_t size;
+       struct spoolss_Time submitted;
+       uint32_t time;
+       uint32_t pages_printed;
+       uint32_t size_high;
+};
+
+union spoolss_SetJobInfo {
+       struct spoolss_SetJobInfo1 *info1;/* [unique,case] */
+       struct spoolss_SetJobInfo2 *info2;/* [unique,case(2)] */
+       struct spoolss_JobInfo3 *info3;/* [unique,case(3)] */
+       struct spoolss_SetJobInfo4 *info4;/* [unique,case(4)] */
+}/* [public] */;
+
 struct spoolss_JobInfoContainer {
        uint32_t level;
-       union spoolss_JobInfo info;/* [switch_is(level)] */
+       union spoolss_SetJobInfo info;/* [switch_is(level)] */
 };
 
 enum spoolss_JobControl
@@ -403,7 +560,9 @@ enum spoolss_JobControl
        SPOOLSS_JOB_CONTROL_RESTART=4,
        SPOOLSS_JOB_CONTROL_DELETE=5,
        SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER=6,
-       SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED=7
+       SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED=7,
+       SPOOLSS_JOB_CONTROL_RETAIN=8,
+       SPOOLSS_JOB_CONTROL_RELEASE=9
 }
 #else
  { __donnot_use_enum_spoolss_JobControl=0x7FFFFFFF}
@@ -414,6 +573,8 @@ enum spoolss_JobControl
 #define SPOOLSS_JOB_CONTROL_DELETE ( 5 )
 #define SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER ( 6 )
 #define SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED ( 7 )
+#define SPOOLSS_JOB_CONTROL_RETAIN ( 8 )
+#define SPOOLSS_JOB_CONTROL_RELEASE ( 9 )
 #endif
 ;
 
@@ -500,7 +661,7 @@ struct spoolss_SetPrinterInfo2 {
 };
 
 struct spoolss_SetPrinterInfo3 {
-       struct security_descriptor *secdesc;/* [unique] */
+       uint32_t sec_desc_ptr;
 };
 
 struct spoolss_SetPrinterInfo4 {
@@ -635,7 +796,7 @@ struct spoolss_AddDriverInfo6 {
        struct spoolss_StringArray *dependent_files;/* [unique] */
        uint32_t _ndr_size_previous_names;/* [value(((ndr_size_spoolss_StringArray(previous_names,ndr->iconv_convenience,ndr->flags)-4)/2))] */
        struct spoolss_StringArray *previous_names;/* [unique] */
-       NTTIME driver_data;
+       NTTIME driver_date;
        uint64_t driver_version;
        const char *manufacturer_name;/* [unique,charset(UTF16)] */
        const char *manufacturer_url;/* [unique,charset(UTF16)] */
@@ -657,7 +818,7 @@ struct spoolss_AddDriverInfo8 {
        struct spoolss_StringArray *dependent_files;/* [unique] */
        uint32_t _ndr_size_previous_names;/* [value(((ndr_size_spoolss_StringArray(previous_names,ndr->iconv_convenience,ndr->flags)-4)/2))] */
        struct spoolss_StringArray *previous_names;/* [unique] */
-       NTTIME driver_data;
+       NTTIME driver_date;
        uint64_t driver_version;
        const char *manufacturer_name;/* [unique,charset(UTF16)] */
        const char *manufacturer_url;/* [unique,charset(UTF16)] */
@@ -691,7 +852,7 @@ struct spoolss_AddDriverInfoCtr {
 
 struct spoolss_DriverInfo1 {
        const char * driver_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
-};
+}/* [gensize,public] */;
 
 struct spoolss_DriverInfo2 {
        enum spoolss_DriverOSVersion version;
@@ -700,7 +861,7 @@ struct spoolss_DriverInfo2 {
        const char * driver_path;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char * data_file;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char * config_file;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
-};
+}/* [gensize,public] */;
 
 struct spoolss_DriverInfo3 {
        enum spoolss_DriverOSVersion version;
@@ -713,7 +874,7 @@ struct spoolss_DriverInfo3 {
        const char ** dependent_files;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char * monitor_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char * default_datatype;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
-};
+}/* [gensize,public] */;
 
 struct spoolss_DriverInfo4 {
        enum spoolss_DriverOSVersion version;
@@ -727,7 +888,7 @@ struct spoolss_DriverInfo4 {
        const char * monitor_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char * default_datatype;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char ** previous_names;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
-};
+}/* [gensize,public] */;
 
 struct spoolss_DriverInfo5 {
        enum spoolss_DriverOSVersion version;
@@ -739,7 +900,7 @@ struct spoolss_DriverInfo5 {
        uint32_t driver_attributes;
        uint32_t config_version;
        uint32_t driver_version;
-};
+}/* [gensize,public] */;
 
 struct spoolss_DriverInfo6 {
        enum spoolss_DriverOSVersion version;
@@ -753,13 +914,13 @@ struct spoolss_DriverInfo6 {
        const char * monitor_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char * default_datatype;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char ** previous_names;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
-       NTTIME driver_data;
+       NTTIME driver_date;
        uint64_t driver_version;
        const char * manufacturer_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char * manufacturer_url;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char * hardware_id;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char * provider;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
-};
+}/* [gensize,public] */;
 
 struct spoolss_DriverInfo8 {
        enum spoolss_DriverOSVersion version;
@@ -773,7 +934,7 @@ struct spoolss_DriverInfo8 {
        const char * default_datatype;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char ** dependent_files;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char ** previous_names;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
-       NTTIME driver_data;
+       NTTIME driver_date;
        uint64_t driver_version;
        const char * manufacturer_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        const char * manufacturer_url;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
@@ -787,7 +948,49 @@ struct spoolss_DriverInfo8 {
        const char ** core_driver_dependencies;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
        NTTIME min_inbox_driver_ver_date;
        uint64_t min_inbox_driver_ver_version;
-};
+}/* [gensize,public] */;
+
+enum spoolss_DriverFileType
+#ifndef USE_UINT_ENUMS
+ {
+       SPOOLSS_DRIVER_FILE_TYPE_RENDERING=0x00000000,
+       SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION=0x00000001,
+       SPOOLSS_DRIVER_FILE_TYPE_DATA=0x00000002,
+       SPOOLSS_DRIVER_FILE_TYPE_HELP=0x00000003,
+       SPOOLSS_DRIVER_FILE_TYPE_OTHER=0x00000004
+}
+#else
+ { __donnot_use_enum_spoolss_DriverFileType=0x7FFFFFFF}
+#define SPOOLSS_DRIVER_FILE_TYPE_RENDERING ( 0x00000000 )
+#define SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION ( 0x00000001 )
+#define SPOOLSS_DRIVER_FILE_TYPE_DATA ( 0x00000002 )
+#define SPOOLSS_DRIVER_FILE_TYPE_HELP ( 0x00000003 )
+#define SPOOLSS_DRIVER_FILE_TYPE_OTHER ( 0x00000004 )
+#endif
+;
+
+struct spoolss_DriverFileInfo {
+       const char * file_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       enum spoolss_DriverFileType file_type;
+       uint32_t file_version;
+}/* [public] */;
+
+struct spoolss_DriverInfo101 {
+       enum spoolss_DriverOSVersion version;
+       const char * driver_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * architecture;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       struct spoolss_DriverFileInfo *file_info;/* [relative,size_is(file_count)] */
+       uint32_t file_count;
+       const char * monitor_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * default_datatype;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char ** previous_names;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       NTTIME driver_date;
+       uint64_t driver_version;
+       const char * manufacturer_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * manufacturer_url;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * hardware_id;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       const char * provider;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+}/* [gensize,nopush,public,nopull] */;
 
 union spoolss_DriverInfo {
        struct spoolss_DriverInfo1 info1;/* [case] */
@@ -797,6 +1000,7 @@ union spoolss_DriverInfo {
        struct spoolss_DriverInfo5 info5;/* [case(5)] */
        struct spoolss_DriverInfo6 info6;/* [case(6)] */
        struct spoolss_DriverInfo8 info8;/* [case(8)] */
+       struct spoolss_DriverInfo101 info101;/* [case(101)] */
 }/* [relative_base,nodiscriminant,public] */;
 
 struct spoolss_DriverDirectoryInfo1 {
@@ -914,8 +1118,27 @@ struct spoolss_FormInfo1 {
        struct spoolss_FormArea area;
 };
 
+/* bitmap spoolss_FormStringType */
+#define SPOOLSS_FORM_STRING_TYPE_NONE ( 0x00000001 )
+#define SPOOLSS_FORM_STRING_TYPE_MUI_DLL ( 0x00000002 )
+#define SPOOLSS_FORM_STRING_TYPE_LANG_PAIR ( 0x00000004 )
+
+struct spoolss_FormInfo2 {
+       enum spoolss_FormFlags flags;
+       const char * form_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       struct spoolss_FormSize size;
+       struct spoolss_FormArea area;
+       const char * keyword;/* [relative,flag(LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM)] */
+       uint32_t string_type;
+       const char * mui_dll;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       uint32_t ressource_id;
+       const char * display_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       uint32_t lang_id;
+};
+
 union spoolss_FormInfo {
        struct spoolss_FormInfo1 info1;/* [case] */
+       struct spoolss_FormInfo2 info2;/* [case(2)] */
 }/* [relative_base,gensize,public,nodiscriminant] */;
 
 struct spoolss_AddFormInfo1 {
@@ -925,8 +1148,22 @@ struct spoolss_AddFormInfo1 {
        struct spoolss_FormArea area;
 };
 
+struct spoolss_AddFormInfo2 {
+       enum spoolss_FormFlags flags;
+       const char *form_name;/* [unique,charset(UTF16)] */
+       struct spoolss_FormSize size;
+       struct spoolss_FormArea area;
+       const char *keyword;/* [unique,charset(DOS)] */
+       uint32_t string_type;
+       const char *mui_dll;/* [unique,charset(UTF16)] */
+       uint32_t ressource_id;
+       const char *display_name;/* [unique,charset(UTF16)] */
+       uint32_t lang_id;
+};
+
 union spoolss_AddFormInfo {
        struct spoolss_AddFormInfo1 *info1;/* [unique,case] */
+       struct spoolss_AddFormInfo2 *info2;/* [unique,case(2)] */
 }/* [switch_type(uint32)] */;
 
 struct spoolss_PortInfo1 {
@@ -947,9 +1184,72 @@ struct spoolss_PortInfo2 {
        uint32_t reserved;
 };
 
+enum spoolss_PortStatus
+#ifndef USE_UINT_ENUMS
+ {
+       PORT_STATUS_CLEAR=0x00000000,
+       PORT_STATUS_OFFLINE=0x00000001,
+       PORT_STATUS_PAPER_JAM=0x00000002,
+       PORT_STATUS_PAPER_OUT=0x00000003,
+       PORT_STATUS_OUTPUT_BIN_FULL=0x00000004,
+       PORT_STATUS_PAPER_PROBLEM=0x00000005,
+       PORT_STATUS_NO_TONER=0x00000006,
+       PORT_STATUS_DOOR_OPEN=0x00000007,
+       PORT_STATUS_USER_INTERVENTION=0x00000008,
+       PORT_STATUS_OUT_OF_MEMORY=0x00000009,
+       PORT_STATUS_TONER_LOW=0x0000000A,
+       PORT_STATUS_WARMING_UP=0x0000000B,
+       PORT_STATUS_POWER_SAVE=0x0000000C
+}
+#else
+ { __donnot_use_enum_spoolss_PortStatus=0x7FFFFFFF}
+#define PORT_STATUS_CLEAR ( 0x00000000 )
+#define PORT_STATUS_OFFLINE ( 0x00000001 )
+#define PORT_STATUS_PAPER_JAM ( 0x00000002 )
+#define PORT_STATUS_PAPER_OUT ( 0x00000003 )
+#define PORT_STATUS_OUTPUT_BIN_FULL ( 0x00000004 )
+#define PORT_STATUS_PAPER_PROBLEM ( 0x00000005 )
+#define PORT_STATUS_NO_TONER ( 0x00000006 )
+#define PORT_STATUS_DOOR_OPEN ( 0x00000007 )
+#define PORT_STATUS_USER_INTERVENTION ( 0x00000008 )
+#define PORT_STATUS_OUT_OF_MEMORY ( 0x00000009 )
+#define PORT_STATUS_TONER_LOW ( 0x0000000A )
+#define PORT_STATUS_WARMING_UP ( 0x0000000B )
+#define PORT_STATUS_POWER_SAVE ( 0x0000000C )
+#endif
+;
+
+enum spoolss_PortSeverity
+#ifndef USE_UINT_ENUMS
+ {
+       PORT_STATUS_TYPE_ERROR=0x00000001,
+       PORT_STATUS_TYPE_WARNING=0x00000002,
+       PORT_STATUS_TYPE_INFO=0x00000003
+}
+#else
+ { __donnot_use_enum_spoolss_PortSeverity=0x7FFFFFFF}
+#define PORT_STATUS_TYPE_ERROR ( 0x00000001 )
+#define PORT_STATUS_TYPE_WARNING ( 0x00000002 )
+#define PORT_STATUS_TYPE_INFO ( 0x00000003 )
+#endif
+;
+
+struct spoolss_PortInfo3 {
+       enum spoolss_PortStatus status;
+       const char * status_string;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       enum spoolss_PortSeverity severity;
+};
+
+struct spoolss_PortInfoFF {
+       const char * port_name;/* [relative,flag(LIBNDR_FLAG_STR_NULLTERM)] */
+       DATA_BLOB monitor_data;
+};
+
 union spoolss_PortInfo {
        struct spoolss_PortInfo1 info1;/* [case] */
        struct spoolss_PortInfo2 info2;/* [case(2)] */
+       struct spoolss_PortInfo3 info3;/* [case(3)] */
+       struct spoolss_PortInfoFF infoFF;/* [case(0xff)] */
 }/* [relative_base,nodiscriminant,public] */;
 
 struct spoolss_MonitorInfo1 {
@@ -984,6 +1284,7 @@ union spoolss_MonitorInfo {
 #define PRINTER_CHANGE_DELETE_PORT ( 0x00400000 )
 #define PRINTER_CHANGE_ADD_PRINT_PROCESSOR ( 0x01000000 )
 #define PRINTER_CHANGE_DELETE_PRINT_PROCESSOR ( 0x04000000 )
+#define PRINTER_CHANGE_SERVER ( 0x08000000 )
 #define PRINTER_CHANGE_ADD_PRINTER_DRIVER ( 0x10000000 )
 #define PRINTER_CHANGE_SET_PRINTER_DRIVER ( 0x20000000 )
 #define PRINTER_CHANGE_DELETE_PRINTER_DRIVER ( 0x40000000 )
@@ -1072,6 +1373,9 @@ struct spoolss_NotifyOptionType {
        enum spoolss_Field *fields;/* [unique,size_is(count)] */
 };
 
+/* bitmap spoolssNotifyOptionFlags */
+#define PRINTER_NOTIFY_OPTIONS_REFRESH ( 0x00000001 )
+
 struct spoolss_NotifyOption {
        uint32_t version;/* [value(2)] */
        uint32_t flags;
@@ -1106,7 +1410,7 @@ enum spoolss_NotifyTable
 union spoolss_NotifyData {
        uint32_t integer[2];/* [case] */
        struct spoolss_NotifyString string;/* [case(2)] */
-       struct spoolss_DeviceMode *devmode;/* [unique,case(3)] */
+       struct spoolss_DevmodeContainer devmode;/* [case(3)] */
        struct spoolss_TimeCtr time;/* [case(4)] */
        struct sec_desc_buf sd;/* [case(5)] */
 }/* [switch_type(uint32)] */;
@@ -1179,6 +1483,7 @@ struct spoolss_UserLevelCtr {
 #define PRINTER_ACCESS_ADMINISTER ( 0x00000004 )
 #define PRINTER_ACCESS_USE ( 0x00000008 )
 #define JOB_ACCESS_ADMINISTER ( 0x00000010 )
+#define JOB_ACCESS_READ ( 0x00000020 )
 
 /* bitmap spoolss_DeleteDriverFlags */
 #define DPD_DELETE_UNUSED_FILES ( 0x00000001 )
@@ -2235,7 +2540,7 @@ struct spoolss_GetPrinterDriver2 {
        } in;
 
        struct {
-               DATA_BLOB *info;/* [unique] */
+               union spoolss_DriverInfo *info;/* [unique,subcontext_size(offered),subcontext(4),switch_is(level)] */
                uint32_t *needed;/* [ref] */
                uint32_t *server_major_version;/* [ref] */
                uint32_t *server_minor_version;/* [ref] */
index 795afc9a5ada6ac2620a83d5c73cb8c3bf76e1ed..2cab792adf9b146f935d0792be71f986ca626be7 100644 (file)
@@ -1673,18 +1673,18 @@ static bool api_eventlog_WriteClusterEvents(pipes_struct *p)
        return true;
 }
 
-static bool api_eventlog_GetLogIntormation(pipes_struct *p)
+static bool api_eventlog_GetLogInformation(pipes_struct *p)
 {
        const struct ndr_interface_call *call;
        struct ndr_pull *pull;
        struct ndr_push *push;
        enum ndr_err_code ndr_err;
        DATA_BLOB blob;
-       struct eventlog_GetLogIntormation *r;
+       struct eventlog_GetLogInformation *r;
 
-       call = &ndr_table_eventlog.calls[NDR_EVENTLOG_GETLOGINTORMATION];
+       call = &ndr_table_eventlog.calls[NDR_EVENTLOG_GETLOGINFORMATION];
 
-       r = talloc(talloc_tos(), struct eventlog_GetLogIntormation);
+       r = talloc(talloc_tos(), struct eventlog_GetLogInformation);
        if (r == NULL) {
                return false;
        }
@@ -1708,7 +1708,7 @@ static bool api_eventlog_GetLogIntormation(pipes_struct *p)
        }
 
        if (DEBUGLEVEL >= 10) {
-               NDR_PRINT_IN_DEBUG(eventlog_GetLogIntormation, r);
+               NDR_PRINT_IN_DEBUG(eventlog_GetLogInformation, r);
        }
 
        ZERO_STRUCT(r->out);
@@ -1724,7 +1724,7 @@ static bool api_eventlog_GetLogIntormation(pipes_struct *p)
                return false;
        }
 
-       r->out.result = _eventlog_GetLogIntormation(p, r);
+       r->out.result = _eventlog_GetLogInformation(p, r);
 
        if (p->rng_fault_state) {
                talloc_free(r);
@@ -1733,7 +1733,7 @@ static bool api_eventlog_GetLogIntormation(pipes_struct *p)
        }
 
        if (DEBUGLEVEL >= 10) {
-               NDR_PRINT_OUT_DEBUG(eventlog_GetLogIntormation, r);
+               NDR_PRINT_OUT_DEBUG(eventlog_GetLogInformation, r);
        }
 
        push = ndr_push_init_ctx(r, NULL);
@@ -1934,7 +1934,7 @@ static struct api_struct api_eventlog_cmds[] =
        {"EVENTLOG_REGISTERCLUSTERSVC", NDR_EVENTLOG_REGISTERCLUSTERSVC, api_eventlog_RegisterClusterSvc},
        {"EVENTLOG_DEREGISTERCLUSTERSVC", NDR_EVENTLOG_DEREGISTERCLUSTERSVC, api_eventlog_DeregisterClusterSvc},
        {"EVENTLOG_WRITECLUSTEREVENTS", NDR_EVENTLOG_WRITECLUSTEREVENTS, api_eventlog_WriteClusterEvents},
-       {"EVENTLOG_GETLOGINTORMATION", NDR_EVENTLOG_GETLOGINTORMATION, api_eventlog_GetLogIntormation},
+       {"EVENTLOG_GETLOGINFORMATION", NDR_EVENTLOG_GETLOGINFORMATION, api_eventlog_GetLogInformation},
        {"EVENTLOG_FLUSHEVENTLOG", NDR_EVENTLOG_FLUSHEVENTLOG, api_eventlog_FlushEventLog},
        {"EVENTLOG_REPORTEVENTANDSOURCEW", NDR_EVENTLOG_REPORTEVENTANDSOURCEW, api_eventlog_ReportEventAndSourceW},
 };
@@ -2138,8 +2138,8 @@ NTSTATUS rpc_eventlog_dispatch(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                        return NT_STATUS_OK;
                }
 
-               case NDR_EVENTLOG_GETLOGINTORMATION: {
-                       struct eventlog_GetLogIntormation *r = (struct eventlog_GetLogIntormation *)_r;
+               case NDR_EVENTLOG_GETLOGINFORMATION: {
+                       struct eventlog_GetLogInformation *r = (struct eventlog_GetLogInformation *)_r;
                        ZERO_STRUCT(r->out);
                        r->out.buffer = talloc_zero_array(mem_ctx, uint8_t, r->in.buf_size);
                        if (r->out.buffer == NULL) {
@@ -2151,7 +2151,7 @@ NTSTATUS rpc_eventlog_dispatch(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                        return NT_STATUS_NO_MEMORY;
                        }
 
-                       r->out.result = _eventlog_GetLogIntormation(cli->pipes_struct, r);
+                       r->out.result = _eventlog_GetLogInformation(cli->pipes_struct, r);
                        return NT_STATUS_OK;
                }
 
index 11d6886a24e0de36218f4463e3329c655a9288f5..7da7cddbd23214993c55fe1d0c2914bf916cdffd 100644 (file)
@@ -23,7 +23,7 @@ NTSTATUS _eventlog_ReportEventA(pipes_struct *p, struct eventlog_ReportEventA *r
 NTSTATUS _eventlog_RegisterClusterSvc(pipes_struct *p, struct eventlog_RegisterClusterSvc *r);
 NTSTATUS _eventlog_DeregisterClusterSvc(pipes_struct *p, struct eventlog_DeregisterClusterSvc *r);
 NTSTATUS _eventlog_WriteClusterEvents(pipes_struct *p, struct eventlog_WriteClusterEvents *r);
-NTSTATUS _eventlog_GetLogIntormation(pipes_struct *p, struct eventlog_GetLogIntormation *r);
+NTSTATUS _eventlog_GetLogInformation(pipes_struct *p, struct eventlog_GetLogInformation *r);
 NTSTATUS _eventlog_FlushEventLog(pipes_struct *p, struct eventlog_FlushEventLog *r);
 NTSTATUS _eventlog_ReportEventAndSourceW(pipes_struct *p, struct eventlog_ReportEventAndSourceW *r);
 void eventlog_get_pipe_fns(struct api_struct **fns, int *n_fns);
@@ -50,7 +50,7 @@ NTSTATUS _eventlog_ReportEventA(pipes_struct *p, struct eventlog_ReportEventA *r
 NTSTATUS _eventlog_RegisterClusterSvc(pipes_struct *p, struct eventlog_RegisterClusterSvc *r);
 NTSTATUS _eventlog_DeregisterClusterSvc(pipes_struct *p, struct eventlog_DeregisterClusterSvc *r);
 NTSTATUS _eventlog_WriteClusterEvents(pipes_struct *p, struct eventlog_WriteClusterEvents *r);
-NTSTATUS _eventlog_GetLogIntormation(pipes_struct *p, struct eventlog_GetLogIntormation *r);
+NTSTATUS _eventlog_GetLogInformation(pipes_struct *p, struct eventlog_GetLogInformation *r);
 NTSTATUS _eventlog_FlushEventLog(pipes_struct *p, struct eventlog_FlushEventLog *r);
 NTSTATUS _eventlog_ReportEventAndSourceW(pipes_struct *p, struct eventlog_ReportEventAndSourceW *r);
 NTSTATUS rpc_eventlog_init(void);
index f6c17cb1faa84871b81f30390f2de778782e84bb..891be8537670b266405a799525f0e7c8386e1797 100644 (file)
@@ -4169,7 +4169,7 @@ static bool api_spoolss_GetPrinterDriver2(pipes_struct *p)
        }
 
        ZERO_STRUCT(r->out);
-       r->out.info = talloc_zero(r, DATA_BLOB);
+       r->out.info = talloc_zero(r, union spoolss_DriverInfo);
        if (r->out.info == NULL) {
                talloc_free(r);
                return false;
@@ -8080,7 +8080,7 @@ NTSTATUS rpc_spoolss_dispatch(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                case NDR_SPOOLSS_GETPRINTERDRIVER2: {
                        struct spoolss_GetPrinterDriver2 *r = (struct spoolss_GetPrinterDriver2 *)_r;
                        ZERO_STRUCT(r->out);
-                       r->out.info = talloc_zero(mem_ctx, DATA_BLOB);
+                       r->out.info = talloc_zero(mem_ctx, union spoolss_DriverInfo);
                        if (r->out.info == NULL) {
                        return NT_STATUS_NO_MEMORY;
                        }
index 6467f72a5be45f21c42cb866fabd867ca16c29a6..4a8fd051f6bd0ea4b0efae5bc410fca99388da39 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/security.h"
 #include "librpc/gen_ndr/svcctl.h"
 #ifndef _HEADER_srvsvc
index 328d8ab517fb239d46d09ae4691c0cd119d7b57c..6ba0e4f3785ef8cc2f40a1c192c7e51466bedc77 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/misc.h"
 #include "librpc/gen_ndr/security.h"
 #ifndef _HEADER_svcctl
index 79cf33e769f1ed32649e7ba781ae3bd5885a3b3e..e0300fd0e7a7d3ff24cd49b0f84859634d540384 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/lsa.h"
 #include "librpc/gen_ndr/security.h"
 #ifndef _HEADER_winreg
index dc12fe2a3f6f1ccd55e62f6d902f0228493d4339..19aa12632284395e5687f8366966b351be1b2944 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/srvsvc.h"
 #include "librpc/gen_ndr/lsa.h"
 #ifndef _HEADER_wkssvc
index 1148a0acecbc9ea63cfa40bccac96f5e93aada38..1ce58f7ec685e04e0cd202a9ac97a55bdd43d550 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <stdint.h>
 
+#include "libcli/util/ntstatus.h"
+
 #include "librpc/gen_ndr/security.h"
 #ifndef _HEADER_xattr
 #define _HEADER_xattr
index c7524f3c3884afc871f74b1c39c9d85d231cad69..6b46acec7d9ee909abad789b65994e89e1abe4b3 100644 (file)
@@ -31,32 +31,6 @@ import "lsa.idl", "security.idl";
                uint16 unknown0;
                uint16 unknown1;
        } eventlog_OpenUnknown0;
-       
-       typedef [flag(NDR_NOALIGN),public] struct {
-               uint32 size;
-               [charset(DOS),value("eLfL")] uint8 reserved[4];
-               uint32 record_number;
-               time_t time_generated;
-               time_t time_written;
-               uint32 event_id;
-               eventlogEventTypes event_type;
-               [range(0,256)] uint16 num_of_strings;
-               uint16 event_category;
-               uint16 reserved_flags;
-               uint32 closing_record_number;
-               uint32 stringoffset;
-               [value(ndr_size_dom_sid0(&sid, ndr->flags))] uint32 sid_size;
-               uint32 sid_offset;
-               uint32 data_length;
-               uint32 data_offset;
-               nstring source_name;
-               nstring computer_name;
-               [subcontext(0),subcontext_size(sid_size)] dom_sid0 sid;
-               nstring strings[num_of_strings];
-               astring raw_data;
-               [flag(NDR_ALIGN4)] DATA_BLOB _padding;
-               [value(size)] uint32 size2;
-       } eventlog_Record;
 
        /* compat structure for samba3 on-disc eventlog format,
           this is *NOT* used on the wire. - gd */
@@ -314,7 +288,7 @@ import "lsa.idl", "security.idl";
                boolean32 full;
        } EVENTLOG_FULL_INFORMATION;
 
-       NTSTATUS eventlog_GetLogIntormation(
+       NTSTATUS eventlog_GetLogInformation(
                [in] policy_handle *handle,
                [in] uint32 level,
                [out,ref] [size_is(buf_size)] uint8 *buffer,
index 4bb68fac007a4b2a5d7d0fd3d05487f3bff0e8d5..f2944b0f3938bd73aa60b403ccb4073afbc2bd61 100644 (file)
@@ -378,6 +378,27 @@ import "misc.idl", "security.idl", "winreg.idl";
 
        /******************/
        /* Function: 0x02 */
+
+       /* JOB status codes. */
+
+       const int JOB_STATUS_QUEUED = 0x0000;
+
+       typedef [bitmap32bit] bitmap {
+               JOB_STATUS_PAUSED               = 0x00000001,
+               JOB_STATUS_ERROR                = 0x00000002,
+               JOB_STATUS_DELETING             = 0x00000004,
+               JOB_STATUS_SPOOLING             = 0x00000008,
+               JOB_STATUS_PRINTING             = 0x00000010,
+               JOB_STATUS_OFFLINE              = 0x00000020,
+               JOB_STATUS_PAPEROUT             = 0x00000040,
+               JOB_STATUS_PRINTED              = 0x00000080,
+               JOB_STATUS_DELETED              = 0x00000100,
+               JOB_STATUS_BLOCKED_DEVQ         = 0x00000200,
+               JOB_STATUS_USER_INTERVENTION    = 0x00000400,
+               JOB_STATUS_RESTART              = 0x00000800,
+               JOB_STATUS_COMPLETE             = 0x00001000
+       } spoolss_JobStatus;
+
        typedef struct {
                uint32 job_id;
                [relative] nstring *printer_name;
@@ -386,24 +407,161 @@ import "misc.idl", "security.idl", "winreg.idl";
                [relative] nstring *document_name;
                [relative] nstring *data_type;
                [relative] nstring *text_status;
-               uint32 status;
+               spoolss_JobStatus status;
                uint32 priority;
                uint32 position;
                uint32 total_pages;
                uint32 pages_printed;
-               spoolss_Time time;
+               spoolss_Time submitted;
        } spoolss_JobInfo1;
 
+       typedef struct {
+               uint32 job_id;
+               [relative] nstring *printer_name;
+               [relative] nstring *server_name;
+               [relative] nstring *user_name;
+               [relative] nstring *document_name;
+               [relative] nstring *notify_name;
+               [relative] nstring *data_type;
+               [relative] nstring *print_processor;
+               [relative] nstring *parameters;
+               [relative] nstring *driver_name;
+               [relative] spoolss_DeviceMode *devmode;
+               [relative] nstring *text_status;
+               [relative] security_descriptor *secdesc;
+               spoolss_JobStatus status;
+               uint32 priority;
+               uint32 position;
+               uint32 start_time;
+               uint32 until_time;
+               uint32 total_pages;
+               uint32 size;
+               spoolss_Time submitted;
+               uint32 time;
+               uint32 pages_printed;
+       } spoolss_JobInfo2;
+
+       typedef struct {
+               uint32 job_id;
+               uint32 next_job_id;
+               uint32 reserved;
+       } spoolss_JobInfo3;
+
+       typedef struct {
+               uint32 job_id;
+               [relative] nstring *printer_name;
+               [relative] nstring *server_name;
+               [relative] nstring *user_name;
+               [relative] nstring *document_name;
+               [relative] nstring *notify_name;
+               [relative] nstring *data_type;
+               [relative] nstring *print_processor;
+               [relative] nstring *parameters;
+               [relative] nstring *driver_name;
+               [relative] spoolss_DeviceMode *devmode;
+               [relative] nstring *text_status;
+               [relative] security_descriptor *secdesc;
+               spoolss_JobStatus status;
+               uint32 priority;
+               uint32 position;
+               uint32 start_time;
+               uint32 until_time;
+               uint32 total_pages;
+               uint32 size;
+               spoolss_Time submitted;
+               uint32 time;
+               uint32 pages_printed;
+               uint32 size_high;
+       } spoolss_JobInfo4;
+
        typedef [nodiscriminant,relative_base,public] union {
                [case(1)] spoolss_JobInfo1 info1;
-               [case(2)]; /* TODO */
-               [case(3)]; /* TODO */
+               [case(2)] spoolss_JobInfo2 info2;
+               [case(3)] spoolss_JobInfo3 info3;
+               [case(4)] spoolss_JobInfo4 info4;
                [default];
        } spoolss_JobInfo;
 
+       typedef struct {
+               uint32 job_id;
+               [string,charset(UTF16)] uint16 *printer_name;
+               [string,charset(UTF16)] uint16 *server_name;
+               [string,charset(UTF16)] uint16 *user_name;
+               [string,charset(UTF16)] uint16 *document_name;
+               [string,charset(UTF16)] uint16 *data_type;
+               [string,charset(UTF16)] uint16 *text_status;
+               spoolss_JobStatus status;
+               uint32 priority;
+               uint32 position;
+               uint32 total_pages;
+               uint32 pages_printed;
+               spoolss_Time submitted;
+       } spoolss_SetJobInfo1;
+
+       typedef struct {
+               uint32 job_id;
+               [string,charset(UTF16)] uint16 *printer_name;
+               [string,charset(UTF16)] uint16 *server_name;
+               [string,charset(UTF16)] uint16 *user_name;
+               [string,charset(UTF16)] uint16 *document_name;
+               [string,charset(UTF16)] uint16 *notify_name;
+               [string,charset(UTF16)] uint16 *data_type;
+               [string,charset(UTF16)] uint16 *print_processor;
+               [string,charset(UTF16)] uint16 *parameters;
+               [string,charset(UTF16)] uint16 *driver_name;
+               spoolss_DeviceMode *devmode;
+               [string,charset(UTF16)] uint16 *text_status;
+               security_descriptor *secdesc;
+               spoolss_JobStatus status;
+               uint32 priority;
+               uint32 position;
+               uint32 start_time;
+               uint32 until_time;
+               uint32 total_pages;
+               uint32 size;
+               spoolss_Time submitted;
+               uint32 time;
+               uint32 pages_printed;
+       } spoolss_SetJobInfo2;
+
+       typedef struct {
+               uint32 job_id;
+               [string,charset(UTF16)] uint16 *printer_name;
+               [string,charset(UTF16)] uint16 *server_name;
+               [string,charset(UTF16)] uint16 *user_name;
+               [string,charset(UTF16)] uint16 *document_name;
+               [string,charset(UTF16)] uint16 *notify_name;
+               [string,charset(UTF16)] uint16 *data_type;
+               [string,charset(UTF16)] uint16 *print_processor;
+               [string,charset(UTF16)] uint16 *parameters;
+               [string,charset(UTF16)] uint16 *driver_name;
+               spoolss_DeviceMode *devmode;
+               [string,charset(UTF16)] uint16 *text_status;
+               security_descriptor *secdesc;
+               spoolss_JobStatus status;
+               uint32 priority;
+               uint32 position;
+               uint32 start_time;
+               uint32 until_time;
+               uint32 total_pages;
+               uint32 size;
+               spoolss_Time submitted;
+               uint32 time;
+               uint32 pages_printed;
+               uint32 size_high;
+       } spoolss_SetJobInfo4;
+
+       typedef [public] union {
+               [case(1)] spoolss_SetJobInfo1 *info1;
+               [case(2)] spoolss_SetJobInfo2 *info2;
+               [case(3)] spoolss_JobInfo3    *info3;
+               [case(4)] spoolss_SetJobInfo4 *info4;
+               [default];
+       } spoolss_SetJobInfo;
+
        typedef struct {
                uint32 level;
-               [switch_is(level)] spoolss_JobInfo info;
+               [switch_is(level)] spoolss_SetJobInfo info;
        } spoolss_JobInfoContainer;
 
        typedef [v1_enum] enum {
@@ -413,7 +571,9 @@ import "misc.idl", "security.idl", "winreg.idl";
                SPOOLSS_JOB_CONTROL_RESTART             = 4,
                SPOOLSS_JOB_CONTROL_DELETE              = 5,
                SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER     = 6,
-               SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED   = 7
+               SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED   = 7,
+               SPOOLSS_JOB_CONTROL_RETAIN              = 8,
+               SPOOLSS_JOB_CONTROL_RELEASE             = 9
        } spoolss_JobControl;
 
        WERROR spoolss_SetJob(
@@ -552,7 +712,7 @@ import "misc.idl", "security.idl", "winreg.idl";
        } spoolss_SetPrinterInfo2;
 
        typedef struct {
-               security_descriptor *secdesc;
+               uint32 sec_desc_ptr;
        } spoolss_SetPrinterInfo3;
 
        typedef struct {
@@ -628,7 +788,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                [string,charset(UTF16)] uint16 *driver_name;
        } spoolss_AddDriverInfo1;
 
-       typedef [v1_enum] enum {
+       typedef [v1_enum,public] enum {
                SPOOLSS_DRIVER_VERSION_9X       = 0,
                SPOOLSS_DRIVER_VERSION_NT35     = 1,
                SPOOLSS_DRIVER_VERSION_NT4      = 2,
@@ -700,7 +860,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                spoolss_StringArray *dependent_files;
                [value(((ndr_size_spoolss_StringArray(previous_names, ndr->iconv_convenience, ndr->flags)-4)/2))] uint32 _ndr_size_previous_names;
                spoolss_StringArray *previous_names;
-               NTTIME driver_data;
+               NTTIME driver_date;
                hyper driver_version;
                [string,charset(UTF16)] uint16 *manufacturer_name;
                [string,charset(UTF16)] uint16 *manufacturer_url;
@@ -722,7 +882,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                spoolss_StringArray *dependent_files;
                [value(((ndr_size_spoolss_StringArray(previous_names, ndr->iconv_convenience, ndr->flags)-4)/2))] uint32 _ndr_size_previous_names;
                spoolss_StringArray *previous_names;
-               NTTIME driver_data;
+               NTTIME driver_date;
                hyper driver_version;
                [string,charset(UTF16)] uint16 *manufacturer_name;
                [string,charset(UTF16)] uint16 *manufacturer_url;
@@ -759,11 +919,11 @@ import "misc.idl", "security.idl", "winreg.idl";
                [in,ref] spoolss_AddDriverInfoCtr *info_ctr
        );
 
-       typedef struct {
+       typedef [public,gensize] struct {
                [relative] nstring *driver_name;
        } spoolss_DriverInfo1;
 
-       typedef struct {
+       typedef [public,gensize] struct {
                spoolss_DriverOSVersion version;
                [relative] nstring *driver_name;
                [relative] nstring *architecture;
@@ -772,7 +932,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                [relative] nstring *config_file;
        } spoolss_DriverInfo2;
 
-       typedef struct {
+       typedef [public,gensize] struct {
                spoolss_DriverOSVersion version;
                [relative] nstring *driver_name;
                [relative] nstring *architecture;
@@ -785,7 +945,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                [relative] nstring *default_datatype;
        } spoolss_DriverInfo3;
 
-       typedef struct {
+       typedef [public,gensize] struct {
                spoolss_DriverOSVersion version;
                [relative] nstring *driver_name;
                [relative] nstring *architecture;
@@ -799,7 +959,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                [relative] nstring_array *previous_names;
        } spoolss_DriverInfo4;
 
-       typedef struct {
+       typedef [public,gensize] struct {
                spoolss_DriverOSVersion version;
                [relative] nstring *driver_name;
                [relative] nstring *architecture;
@@ -811,7 +971,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                uint32 driver_version;
        } spoolss_DriverInfo5;
 
-       typedef struct {
+       typedef [public,gensize] struct {
                spoolss_DriverOSVersion version;
                [relative] nstring *driver_name;
                [relative] nstring *architecture;
@@ -823,7 +983,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                [relative] nstring *monitor_name;
                [relative] nstring *default_datatype;
                [relative] nstring_array *previous_names;
-               NTTIME driver_data;
+               NTTIME driver_date;
                hyper driver_version;
                [relative] nstring *manufacturer_name;
                [relative] nstring *manufacturer_url;
@@ -831,7 +991,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                [relative] nstring *provider;
        } spoolss_DriverInfo6;
 
-       typedef struct {
+       typedef [public,gensize] struct {
                spoolss_DriverOSVersion version;
                [relative] nstring *driver_name;
                [relative] nstring *architecture;
@@ -843,7 +1003,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                [relative] nstring *default_datatype;
                [relative] nstring_array *dependent_files;
                [relative] nstring_array *previous_names;
-               NTTIME driver_data;
+               NTTIME driver_date;
                hyper driver_version;
                [relative] nstring *manufacturer_name;
                [relative] nstring *manufacturer_url;
@@ -859,6 +1019,37 @@ import "misc.idl", "security.idl", "winreg.idl";
                hyper min_inbox_driver_ver_version;
        } spoolss_DriverInfo8;
 
+       typedef [v1_enum] enum {
+               SPOOLSS_DRIVER_FILE_TYPE_RENDERING      = 0x00000000,
+               SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION  = 0x00000001,
+               SPOOLSS_DRIVER_FILE_TYPE_DATA           = 0x00000002,
+               SPOOLSS_DRIVER_FILE_TYPE_HELP           = 0x00000003,
+               SPOOLSS_DRIVER_FILE_TYPE_OTHER          = 0x00000004
+       } spoolss_DriverFileType;
+
+       typedef [public] struct {
+               [relative] nstring *file_name;
+               spoolss_DriverFileType file_type;
+               uint32 file_version;
+       } spoolss_DriverFileInfo;
+
+       typedef [public,gensize,nopush,nopull] struct {
+               spoolss_DriverOSVersion version;
+               [relative] nstring *driver_name;
+               [relative] nstring *architecture;
+               [relative] [size_is(file_count)] spoolss_DriverFileInfo *file_info;
+               uint32 file_count;
+               [relative] nstring *monitor_name;
+               [relative] nstring *default_datatype;
+               [relative] nstring_array *previous_names;
+               NTTIME driver_date;
+               hyper driver_version;
+               [relative] nstring *manufacturer_name;
+               [relative] nstring *manufacturer_url;
+               [relative] nstring *hardware_id;
+               [relative] nstring *provider;
+       } spoolss_DriverInfo101;
+
        typedef [nodiscriminant,relative_base,public] union {
                [case(1)] spoolss_DriverInfo1 info1;
                [case(2)] spoolss_DriverInfo2 info2;
@@ -867,6 +1058,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                [case(5)] spoolss_DriverInfo5 info5;
                [case(6)] spoolss_DriverInfo6 info6;
                [case(8)] spoolss_DriverInfo8 info8;
+               [case(101)] spoolss_DriverInfo101 info101;
                [default];
        } spoolss_DriverInfo;
 
@@ -989,7 +1181,7 @@ import "misc.idl", "security.idl", "winreg.idl";
 
        typedef [nodiscriminant,relative_base,gensize,public] union {
                [case(1)] spoolss_PrintProcessorDirectoryInfo1 info1;
-               [default];
+               [default] spoolss_PrintProcessorDirectoryInfo1 info1;
        } spoolss_PrintProcessorDirectoryInfo;
 
        WERROR spoolss_GetPrintProcessorDirectory(
@@ -1086,6 +1278,7 @@ import "misc.idl", "security.idl", "winreg.idl";
        /******************/
        /* Function: 0x1a */
        const string SPOOLSS_ARCHITECTURE_NT_X86                = "Windows NT x86";
+       const string SPOOLSS_DEFAULT_SERVER_PATH                = "C:\\WINDOWS\\system32\\spool";
 
        typedef [public,gensize] struct {
                [value(ndr_size_spoolss_OSVersion(r,ndr->iconv_convenience,ndr->flags))] uint32 _ndr_size;
@@ -1204,8 +1397,28 @@ import "misc.idl", "security.idl", "winreg.idl";
                spoolss_FormArea area;
        } spoolss_FormInfo1;
 
+       typedef [bitmap32bit] bitmap {
+               SPOOLSS_FORM_STRING_TYPE_NONE           = 0x00000001,
+               SPOOLSS_FORM_STRING_TYPE_MUI_DLL        = 0x00000002,
+               SPOOLSS_FORM_STRING_TYPE_LANG_PAIR      = 0x00000004
+       } spoolss_FormStringType;
+
+       typedef struct {
+               spoolss_FormFlags flags;
+               [relative] nstring *form_name;
+               spoolss_FormSize size;
+               spoolss_FormArea area;
+               [relative] astring *keyword;
+               spoolss_FormStringType string_type;
+               [relative] nstring *mui_dll;
+               uint32 ressource_id;
+               [relative] nstring *display_name;
+               uint32 lang_id;
+       } spoolss_FormInfo2;
+
        typedef [nodiscriminant,relative_base,public,gensize] union {
                [case(1)] spoolss_FormInfo1 info1;
+               [case(2)] spoolss_FormInfo2 info2;
                [default];
        } spoolss_FormInfo;
 
@@ -1216,8 +1429,22 @@ import "misc.idl", "security.idl", "winreg.idl";
                spoolss_FormArea area;
        } spoolss_AddFormInfo1;
 
+       typedef struct {
+               spoolss_FormFlags flags;
+               [string,charset(UTF16)] uint16 *form_name;
+               spoolss_FormSize size;
+               spoolss_FormArea area;
+               [string,charset(DOS)] uint8 *keyword;
+               spoolss_FormStringType string_type;
+               [string,charset(UTF16)] uint16 *mui_dll;
+               uint32 ressource_id;
+               [string,charset(UTF16)] uint16 *display_name;
+               uint32 lang_id;
+       } spoolss_AddFormInfo2;
+
        typedef [switch_type(uint32)] union {
                [case(1)] spoolss_AddFormInfo1 *info1;
+               [case(2)] spoolss_AddFormInfo2 *info2;
        } spoolss_AddFormInfo;
 
        WERROR spoolss_AddForm(
@@ -1299,10 +1526,44 @@ import "misc.idl", "security.idl", "winreg.idl";
                uint32 reserved;
        } spoolss_PortInfo2;
 
+       typedef [v1_enum] enum {
+               PORT_STATUS_CLEAR               = 0x00000000,
+               PORT_STATUS_OFFLINE             = 0x00000001,
+               PORT_STATUS_PAPER_JAM           = 0x00000002,
+               PORT_STATUS_PAPER_OUT           = 0x00000003,
+               PORT_STATUS_OUTPUT_BIN_FULL     = 0x00000004,
+               PORT_STATUS_PAPER_PROBLEM       = 0x00000005,
+               PORT_STATUS_NO_TONER            = 0x00000006,
+               PORT_STATUS_DOOR_OPEN           = 0x00000007,
+               PORT_STATUS_USER_INTERVENTION   = 0x00000008,
+               PORT_STATUS_OUT_OF_MEMORY       = 0x00000009,
+               PORT_STATUS_TONER_LOW           = 0x0000000A,
+               PORT_STATUS_WARMING_UP          = 0x0000000B,
+               PORT_STATUS_POWER_SAVE          = 0x0000000C
+       } spoolss_PortStatus;
+
+       typedef [v1_enum] enum {
+               PORT_STATUS_TYPE_ERROR          = 0x00000001,
+               PORT_STATUS_TYPE_WARNING        = 0x00000002,
+               PORT_STATUS_TYPE_INFO           = 0x00000003
+       } spoolss_PortSeverity;
+
+       typedef struct {
+               spoolss_PortStatus status;
+               [relative] nstring *status_string;
+               spoolss_PortSeverity severity;
+       } spoolss_PortInfo3;
+
+       typedef struct {
+               [relative] nstring *port_name;
+               DATA_BLOB monitor_data; /* relative ?? */
+       } spoolss_PortInfoFF;
+
        typedef [nodiscriminant,relative_base,public] union {
                [case(1)] spoolss_PortInfo1 info1;
                [case(2)] spoolss_PortInfo2 info2;
-               [case(3)]; /* TODO */
+               [case(3)] spoolss_PortInfo3 info3;
+               [case(0xff)] spoolss_PortInfoFF infoFF;
                [default];
        } spoolss_PortInfo;
 
@@ -1472,7 +1733,7 @@ import "misc.idl", "security.idl", "winreg.idl";
                [in]     uint32 offered,
                [in]     uint32 client_major_version,
                [in]     uint32 client_minor_version,
-               [out,unique] DATA_BLOB *info,
+               [out,unique,subcontext(4),subcontext_size(offered),switch_is(level)] spoolss_DriverInfo *info,
                [out,ref] uint32 *needed,
                [out,ref] uint32 *server_major_version,
                [out,ref] uint32 *server_minor_version
@@ -1530,21 +1791,16 @@ import "misc.idl", "security.idl", "winreg.idl";
                PRINTER_CHANGE_DELETE_PORT                      = 0x00400000,
                PRINTER_CHANGE_ADD_PRINT_PROCESSOR              = 0x01000000,
                PRINTER_CHANGE_DELETE_PRINT_PROCESSOR           = 0x04000000,
+               PRINTER_CHANGE_SERVER                           = 0x08000000,
                PRINTER_CHANGE_ADD_PRINTER_DRIVER               = 0x10000000,
                PRINTER_CHANGE_SET_PRINTER_DRIVER               = 0x20000000,
                PRINTER_CHANGE_DELETE_PRINTER_DRIVER            = 0x40000000,
                PRINTER_CHANGE_TIMEOUT                          = 0x80000000
        } spoolss_PrinterChangeFlags;
 
-       const int PRINTER_CHANGE_PRINTER                        = (PRINTER_CHANGE_ADD_PRINTER |
-                                                                  PRINTER_CHANGE_SET_PRINTER |
-                                                                  PRINTER_CHANGE_DELETE_PRINTER |
-                                                                  PRINTER_CHANGE_FAILED_CONNECTION_PRINTER); /* 0x000000FF */
+       const int PRINTER_CHANGE_PRINTER                        = 0x000000FF;
 
-       const int PRINTER_CHANGE_JOB                            = (PRINTER_CHANGE_ADD_JOB |
-                                                                  PRINTER_CHANGE_SET_JOB |
-                                                                  PRINTER_CHANGE_DELETE_JOB |
-                                                                  PRINTER_CHANGE_WRITE_JOB); /* 0x0000FF00 */
+       const int PRINTER_CHANGE_JOB                            = 0x0000FF00;
 
        const int PRINTER_CHANGE_FORM                           = (PRINTER_CHANGE_ADD_FORM |
                                                                   PRINTER_CHANGE_SET_FORM |
@@ -1554,14 +1810,14 @@ import "misc.idl", "security.idl", "winreg.idl";
                                                                   PRINTER_CHANGE_CONFIGURE_PORT |
                                                                   PRINTER_CHANGE_DELETE_PORT); /* 0x00700000 */
 
-       const int PRINTER_CHANGE_PRINT_PROCESSOR                = (PRINTER_CHANGE_ADD_PRINT_PROCESSOR |
-                                                                  PRINTER_CHANGE_DELETE_PRINT_PROCESSOR); /* 0x07000000 */
+       const int PRINTER_CHANGE_PRINT_PROCESSOR                = 0x07000000;
 
        const int PRINTER_CHANGE_PRINTER_DRIVER                 = (PRINTER_CHANGE_ADD_PRINTER_DRIVER |
                                                                   PRINTER_CHANGE_SET_PRINTER_DRIVER |
                                                                   PRINTER_CHANGE_DELETE_PRINTER_DRIVER); /* 0x70000000 */
 
-       const int PRINTER_CHANGE_ALL                            = (PRINTER_CHANGE_JOB |
+       const int PRINTER_CHANGE_ALL                            = (PRINTER_CHANGE_PRINTER |
+                                                                  PRINTER_CHANGE_JOB |
                                                                   PRINTER_CHANGE_FORM |
                                                                   PRINTER_CHANGE_PORT |
                                                                   PRINTER_CHANGE_PRINT_PROCESSOR |
@@ -1644,9 +1900,13 @@ import "misc.idl", "security.idl", "winreg.idl";
                [size_is(count)] spoolss_Field *fields;
        } spoolss_NotifyOptionType;
 
+       typedef [bitmap32bit] bitmap {
+               PRINTER_NOTIFY_OPTIONS_REFRESH  = 0x00000001
+       } spoolssNotifyOptionFlags;
+
        typedef struct {
                [value(2)] uint32 version;
-               uint32 flags;
+               spoolssNotifyOptionFlags flags;
                uint32 count;
                [size_is(count)] spoolss_NotifyOptionType *types;
        } spoolss_NotifyOption;
@@ -1679,7 +1939,7 @@ import "misc.idl", "security.idl", "winreg.idl";
        typedef [switch_type(uint32)] union {
                [case(1)] uint32 integer[2];
                [case(2)] spoolss_NotifyString string;
-               [case(3)] spoolss_DeviceMode *devmode;
+               [case(3)] spoolss_DevmodeContainer devmode;
                [case(4)] spoolss_TimeCtr time;
                [case(5)] sec_desc_buf sd;
        } spoolss_NotifyData;
@@ -1775,7 +2035,8 @@ import "misc.idl", "security.idl", "winreg.idl";
                SERVER_ACCESS_ENUMERATE         = 0x00000002,
                PRINTER_ACCESS_ADMINISTER       = 0x00000004,
                PRINTER_ACCESS_USE              = 0x00000008,
-               JOB_ACCESS_ADMINISTER           = 0x00000010
+               JOB_ACCESS_ADMINISTER           = 0x00000010,
+               JOB_ACCESS_READ                 = 0x00000020
        } spoolss_AccessRights;
 
        /* Access rights for print servers */
index 8f84c02f911724a66a79d424dd020e5d35e31af3..62194707c20314a259bffce8dd4013e4a6baa43e 100644 (file)
@@ -91,14 +91,14 @@ enum ndr_err_code ndr_pull_security_ace(struct ndr_pull *ndr, int ndr_flags, str
 /*
   return the wire size of a security_acl
 */
-size_t ndr_size_security_acl(const struct security_acl *acl, struct smb_iconv_convenience *ic, int flags)
+size_t ndr_size_security_acl(const struct security_acl *theacl, struct smb_iconv_convenience *ic, int flags)
 {
        size_t ret;
        int i;
-       if (!acl) return 0;
+       if (!theacl) return 0;
        ret = 8;
-       for (i=0;i<acl->num_aces;i++) {
-               ret += ndr_size_security_ace(&acl->aces[i], ic, flags);
+       for (i=0;i<theacl->num_aces;i++) {
+               ret += ndr_size_security_ace(&theacl->aces[i], ic, flags);
        }
        return ret;
 }
index d7e28ccf0e7f5aa31fd2a4e95bfbef38398617d2..afc06be4e0d70a67a195632c8fd944b71abecf69 100644 (file)
@@ -544,3 +544,481 @@ _PUBLIC_ size_t ndr_size_spoolss_StringArray(const struct spoolss_StringArray *r
        return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_spoolss_StringArray, ic);
 }
 
+/* hand marshall as pidl cannot (yet) generate a relative pointer to a fixed array of
+ * structs */
+
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo101(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo101 *r)
+{
+       uint32_t cntr_file_info_1;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 8));
+               NDR_CHECK(ndr_push_spoolss_DriverOSVersion(ndr, NDR_SCALARS, r->version));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->driver_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->architecture));
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_push_relative_ptr1(ndr, r->file_info));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->file_count));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->monitor_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->default_datatype));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string_array = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->previous_names));
+                       ndr->flags = _flags_save_string_array;
+               }
+               NDR_CHECK(ndr_push_NTTIME(ndr, NDR_SCALARS, r->driver_date));
+               NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, r->driver_version));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->manufacturer_name));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->manufacturer_url));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->hardware_id));
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_push_relative_ptr1(ndr, r->provider));
+                       ndr->flags = _flags_save_string;
+               }
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->driver_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->driver_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->driver_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->architecture) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->architecture));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->architecture));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->file_info) {
+                       NDR_CHECK(ndr_push_relative_ptr2(ndr, r->file_info));
+#if 0
+                       NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->file_count));
+#endif
+                       for (cntr_file_info_1 = 0; cntr_file_info_1 < r->file_count; cntr_file_info_1++) {
+                               NDR_CHECK(ndr_push_spoolss_DriverFileInfo(ndr, NDR_SCALARS, &r->file_info[cntr_file_info_1]));
+                       }
+                       for (cntr_file_info_1 = 0; cntr_file_info_1 < r->file_count; cntr_file_info_1++) {
+                               NDR_CHECK(ndr_push_spoolss_DriverFileInfo(ndr, NDR_BUFFERS, &r->file_info[cntr_file_info_1]));
+                       }
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->monitor_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->monitor_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->monitor_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->default_datatype) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->default_datatype));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->default_datatype));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string_array = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->previous_names) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->previous_names));
+                               NDR_CHECK(ndr_push_string_array(ndr, NDR_SCALARS, r->previous_names));
+                       }
+                       ndr->flags = _flags_save_string_array;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->manufacturer_name) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->manufacturer_name));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->manufacturer_name));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->manufacturer_url) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->manufacturer_url));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->manufacturer_url));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->hardware_id) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->hardware_id));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->hardware_id));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->provider) {
+                               NDR_CHECK(ndr_push_relative_ptr2(ndr, r->provider));
+                               NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->provider));
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo101(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo101 *r)
+{
+       uint32_t _ptr_driver_name;
+       TALLOC_CTX *_mem_save_driver_name_0;
+       uint32_t _ptr_architecture;
+       TALLOC_CTX *_mem_save_architecture_0;
+       uint32_t _ptr_file_info;
+       uint32_t cntr_file_info_1;
+       TALLOC_CTX *_mem_save_file_info_0;
+       TALLOC_CTX *_mem_save_file_info_1;
+       uint32_t _ptr_monitor_name;
+       TALLOC_CTX *_mem_save_monitor_name_0;
+       uint32_t _ptr_default_datatype;
+       TALLOC_CTX *_mem_save_default_datatype_0;
+       uint32_t _ptr_previous_names;
+       TALLOC_CTX *_mem_save_previous_names_0;
+       uint32_t _ptr_manufacturer_name;
+       TALLOC_CTX *_mem_save_manufacturer_name_0;
+       uint32_t _ptr_manufacturer_url;
+       TALLOC_CTX *_mem_save_manufacturer_url_0;
+       uint32_t _ptr_hardware_id;
+       TALLOC_CTX *_mem_save_hardware_id_0;
+       uint32_t _ptr_provider;
+       TALLOC_CTX *_mem_save_provider_0;
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 8));
+               NDR_CHECK(ndr_pull_spoolss_DriverOSVersion(ndr, NDR_SCALARS, &r->version));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_driver_name));
+                       if (_ptr_driver_name) {
+                               NDR_PULL_ALLOC(ndr, r->driver_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->driver_name, _ptr_driver_name));
+                       } else {
+                               r->driver_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_architecture));
+                       if (_ptr_architecture) {
+                               NDR_PULL_ALLOC(ndr, r->architecture);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->architecture, _ptr_architecture));
+                       } else {
+                               r->architecture = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_file_info));
+               if (_ptr_file_info) {
+                       NDR_PULL_ALLOC(ndr, r->file_info);
+                       NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->file_info, _ptr_file_info));
+               } else {
+                       r->file_info = NULL;
+               }
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->file_count));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_monitor_name));
+                       if (_ptr_monitor_name) {
+                               NDR_PULL_ALLOC(ndr, r->monitor_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->monitor_name, _ptr_monitor_name));
+                       } else {
+                               r->monitor_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_default_datatype));
+                       if (_ptr_default_datatype) {
+                               NDR_PULL_ALLOC(ndr, r->default_datatype);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->default_datatype, _ptr_default_datatype));
+                       } else {
+                               r->default_datatype = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string_array = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_previous_names));
+                       if (_ptr_previous_names) {
+                               NDR_PULL_ALLOC(ndr, r->previous_names);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->previous_names, _ptr_previous_names));
+                       } else {
+                               r->previous_names = NULL;
+                       }
+                       ndr->flags = _flags_save_string_array;
+               }
+               NDR_CHECK(ndr_pull_NTTIME(ndr, NDR_SCALARS, &r->driver_date));
+               NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &r->driver_version));
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_manufacturer_name));
+                       if (_ptr_manufacturer_name) {
+                               NDR_PULL_ALLOC(ndr, r->manufacturer_name);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->manufacturer_name, _ptr_manufacturer_name));
+                       } else {
+                               r->manufacturer_name = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_manufacturer_url));
+                       if (_ptr_manufacturer_url) {
+                               NDR_PULL_ALLOC(ndr, r->manufacturer_url);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->manufacturer_url, _ptr_manufacturer_url));
+                       } else {
+                               r->manufacturer_url = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_hardware_id));
+                       if (_ptr_hardware_id) {
+                               NDR_PULL_ALLOC(ndr, r->hardware_id);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->hardware_id, _ptr_hardware_id));
+                       } else {
+                               r->hardware_id = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_provider));
+                       if (_ptr_provider) {
+                               NDR_PULL_ALLOC(ndr, r->provider);
+                               NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->provider, _ptr_provider));
+                       } else {
+                               r->provider = NULL;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->driver_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->driver_name));
+                               _mem_save_driver_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->driver_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->driver_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_driver_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->architecture) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->architecture));
+                               _mem_save_architecture_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->architecture, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->architecture));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_architecture_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->file_info) {
+                       uint32_t _relative_save_offset;
+                       _relative_save_offset = ndr->offset;
+                       NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->file_info));
+                       _mem_save_file_info_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->file_info, 0);
+#if 0
+                       NDR_CHECK(ndr_pull_array_size(ndr, &r->file_info));
+#else
+                       NDR_CHECK(ndr_token_store(ndr, &ndr->array_size_list, &r->file_info, r->file_count));
+#endif
+                       NDR_PULL_ALLOC_N(ndr, r->file_info, ndr_get_array_size(ndr, &r->file_info));
+                       _mem_save_file_info_1 = NDR_PULL_GET_MEM_CTX(ndr);
+                       NDR_PULL_SET_MEM_CTX(ndr, r->file_info, 0);
+                       for (cntr_file_info_1 = 0; cntr_file_info_1 < r->file_count; cntr_file_info_1++) {
+                               NDR_CHECK(ndr_pull_spoolss_DriverFileInfo(ndr, NDR_SCALARS, &r->file_info[cntr_file_info_1]));
+                       }
+                       for (cntr_file_info_1 = 0; cntr_file_info_1 < r->file_count; cntr_file_info_1++) {
+                               NDR_CHECK(ndr_pull_spoolss_DriverFileInfo(ndr, NDR_BUFFERS, &r->file_info[cntr_file_info_1]));
+                       }
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_file_info_1, 0);
+                       NDR_PULL_SET_MEM_CTX(ndr, _mem_save_file_info_0, 0);
+                       ndr->offset = _relative_save_offset;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->monitor_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->monitor_name));
+                               _mem_save_monitor_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->monitor_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->monitor_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_monitor_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->default_datatype) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->default_datatype));
+                               _mem_save_default_datatype_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->default_datatype, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->default_datatype));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_default_datatype_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string_array = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->previous_names) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->previous_names));
+                               _mem_save_previous_names_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->previous_names, 0);
+                               NDR_CHECK(ndr_pull_string_array(ndr, NDR_SCALARS, &r->previous_names));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_previous_names_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string_array;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->manufacturer_name) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->manufacturer_name));
+                               _mem_save_manufacturer_name_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->manufacturer_name, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->manufacturer_name));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_manufacturer_name_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->manufacturer_url) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->manufacturer_url));
+                               _mem_save_manufacturer_url_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->manufacturer_url, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->manufacturer_url));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_manufacturer_url_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->hardware_id) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->hardware_id));
+                               _mem_save_hardware_id_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->hardware_id, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->hardware_id));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_hardware_id_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               {
+                       uint32_t _flags_save_string = ndr->flags;
+                       ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
+                       if (r->provider) {
+                               uint32_t _relative_save_offset;
+                               _relative_save_offset = ndr->offset;
+                               NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->provider));
+                               _mem_save_provider_0 = NDR_PULL_GET_MEM_CTX(ndr);
+                               NDR_PULL_SET_MEM_CTX(ndr, r->provider, 0);
+                               NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->provider));
+                               NDR_PULL_SET_MEM_CTX(ndr, _mem_save_provider_0, 0);
+                               ndr->offset = _relative_save_offset;
+                       }
+                       ndr->flags = _flags_save_string;
+               }
+               if (r->file_info) {
+                       NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->file_info, r->file_count));
+               }
+       }
+       return NDR_ERR_SUCCESS;
+}
index 801737610fc23c1bfb6c04206a63b130bf1aefe0..5ed848d7e0786195402cf8e5a10a4ca7a61bf4a1 100644 (file)
@@ -39,6 +39,9 @@ enum ndr_err_code ndr_pull_spoolss_GetPrinterData(struct ndr_pull *ndr, int flag
 enum ndr_err_code ndr_push_spoolss_SetPrinterData(struct ndr_push *ndr, int flags, const struct spoolss_SetPrinterData *r);
 uint32_t _ndr_size_spoolss_DeviceMode(struct spoolss_DeviceMode *devmode, struct smb_iconv_convenience *ic, uint32_t flags);
 size_t ndr_size_spoolss_StringArray(const struct spoolss_StringArray *r, struct smb_iconv_convenience *ic, int flags);
+_PUBLIC_ enum ndr_err_code ndr_push_spoolss_DriverInfo101(struct ndr_push *ndr, int ndr_flags, const struct spoolss_DriverInfo101 *r);
+_PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo101(struct ndr_pull *ndr, int ndr_flags, struct spoolss_DriverInfo101 *r);
+
 #undef _PRINTF_ATTRIBUTE
 #define _PRINTF_ATTRIBUTE(a1, a2)
 
index 0411466c8251bf55f7adbe97113347ac97d62390..53159579463368b518ce4ded67e1d9a9d918e8e0 100644 (file)
@@ -407,6 +407,9 @@ sub Parse($)
        }
        pidl "#include <stdint.h>\n";
        pidl "\n";
+       # FIXME: Include this only if NTSTATUS was actually used
+       pidl choose_header("libcli/util/ntstatus.h", "core/ntstatus.h") . "\n";
+       pidl "\n";
 
        foreach (@{$ndr}) {
                ($_->{TYPE} eq "CPP_QUOTE") && HeaderQuote($_);
index f8209be654b4134ddf06915cf082f70c22970231..f2a96a303778279d06dba71582d3318f674e9f8b 100644 (file)
@@ -131,7 +131,9 @@ sub Parse($$$$)
        if (is_intree()) {
                $res .= "#include \"includes.h\"\n";
        } else {
+               $res .= "#ifndef _GNU_SOURCE\n";
                $res .= "#define _GNU_SOURCE\n";
+               $res .= "#endif\n";
                $res .= "#include <stdio.h>\n";
                $res .= "#include <stdbool.h>\n";
                $res .= "#include <stdlib.h>\n";
index af6885f67a6815d94cd89c4485a2fee8168471d5..0e4a7e22894b6b12ef01dd4890e2fed723c45cf2 100644 (file)
@@ -2548,7 +2548,9 @@ sub GenerateIncludes($)
        if (is_intree()) {
                $self->pidl("#include \"includes.h\"");
        } else {
+               $self->pidl("#ifndef _GNU_SOURCE");
                $self->pidl("#define _GNU_SOURCE");
+               $self->pidl("#endif");
                $self->pidl("#include <stdint.h>");
                $self->pidl("#include <stdlib.h>");
                $self->pidl("#include <stdio.h>");
index 48785f5b0ac517951c6c7b509b8d4066a8d9dcea..6099fe5caefeb9ebff05a77fccd82261f41bee71 100644 (file)
@@ -275,7 +275,24 @@ sub PythonStruct($$$$$$)
                $self->pidl("if (!PyArg_ParseTuple(args, \"s#:__ndr_unpack__\", &blob.data, &blob.length))");
                $self->pidl("\treturn NULL;");
                $self->pidl("");
-               $self->pidl("err = ndr_pull_struct_blob_all(&blob, py_talloc_get_mem_ctx(py_obj), NULL, object, (ndr_pull_flags_fn_t)ndr_pull_$name);");
+
+               # This disgusting hack works around the fact that ndr_pull_struct_blob_all will always fail on structures with relative pointers.  
+                # So, map ndr_unpack to ndr_pull_struct_blob_all only if we don't have any relative pointers in this
+               my $got_relative = 0;
+               if ($#{$d->{ELEMENTS}} > -1) {
+                       foreach my $e (@{$d->{ELEMENTS}}) {
+                               my $l = $e->{LEVELS}[0];
+                               if ($l->{TYPE} eq "POINTER" and ($l->{POINTER_TYPE} eq "relative")) {
+                                       $got_relative = 1;
+                                       last;
+                               }
+                       }
+               }
+               if ($got_relative == 0) {
+                       $self->pidl("err = ndr_pull_struct_blob_all(&blob, py_talloc_get_mem_ctx(py_obj), NULL, object, (ndr_pull_flags_fn_t)ndr_pull_$name);");
+               } else {
+                       $self->pidl("err = ndr_pull_struct_blob(&blob, py_talloc_get_mem_ctx(py_obj), NULL, object, (ndr_pull_flags_fn_t)ndr_pull_$name);");
+               }
                $self->pidl("if (err != NDR_ERR_SUCCESS) {");
                $self->indent;
                $self->pidl("PyErr_SetNdrError(err);");
index 7264ddbcb952bd91ddd11b9861704d22fc89fd1f..71dddf69392d99a85aa9f8eb10ec1373b94bcb9d 100644 (file)
@@ -242,77 +242,32 @@ sub mk_openldap($$$)
        $ENV{PATH} = "$olpath/usr/local/sbin:/usr/sbin:/sbin:$ENV{PATH}";
 
        unlink($modconf);
-       open(CONF, ">$modconf"); close(CONF);
 
-       if (system("slaptest -u -f $slapd_conf >&2") != 0) {
-               open(CONF, ">$modconf"); 
-               # enable slapd modules
-               print CONF "
-modulepath      $olroot/libexec/openldap
-moduleload     syncprov
-moduleload      memberof
-moduleload      refint
-";
-               close(CONF);
-       }
-       if (system("slaptest -u -f $slapd_conf >&2") != 0) {
-               open(CONF, ">$modconf"); 
-               # enable slapd modules
-               print CONF "
-modulepath      $olroot/libexec/openldap
-moduleload     back_hdb
-moduleload     syncprov
-moduleload      memberof
-moduleload      refint
-";
-               close(CONF);
-       }
+       #This code tries to guess what modules we need to load (if any) by trying different combinations in the modules.conf
 
-       if (system("slaptest -u -f $slapd_conf >&2") != 0) {
-               open(CONF, ">$modconf"); 
-               # enable slapd modules
-               print CONF "
-moduleload     back_hdb
-moduleload     syncprov
-moduleload      memberof
-moduleload      refint
-";
-               close(CONF);
-       }
+       # Try without any slapd modules
+       open(CONF, ">$modconf"); close(CONF);
 
        if (system("slaptest -u -f $slapd_conf >&2") != 0) {
                open(CONF, ">$modconf"); 
                # enable slapd modules
                print CONF "
-modulepath     /usr/lib/ldap
-moduleload     back_hdb
 moduleload     syncprov
 moduleload      memberof
 moduleload      refint
+moduleload      deref
 ";
                close(CONF);
        }
-
        if (system("slaptest -u -f $slapd_conf >&2") != 0) {
                open(CONF, ">$modconf"); 
-               # enable slapd modules (Fedora layout)
+               # enable slapd modules, and the module for back_hdb
                print CONF "
-modulepath     /usr/lib/openldap
-moduleload     syncprov
-moduleload      memberof
-moduleload      refint
-";
-               close(CONF);
-       }
-
-       if (system("slaptest -u -f $slapd_conf >&2") != 0) {
-               open(CONF, ">$modconf"); 
-               # enable slapd modules (Fedora x86_64 layout)
-               print CONF "
-modulepath     /usr/lib64/openldap
+moduleload     back_hdb
 moduleload     syncprov
 moduleload      memberof
 moduleload      refint
+moduleload      deref
 ";
                close(CONF);
        }
@@ -578,7 +533,7 @@ sub provision_raw_prepare($$$$$$$)
        push (@provision_options, "NSS_WRAPPER_PASSWD=\"$ctx->{nsswrap_passwd}\"");
        push (@provision_options, "NSS_WRAPPER_GROUP=\"$ctx->{nsswrap_group}\"");
        if (defined($ENV{GDB_PROVISION})) {
-               push (@provision_options, "gdb --args python");
+               push (@provision_options, "gdb --args");
        }
        if (defined($ENV{VALGRIND_PROVISION})) {
                push (@provision_options, "valgrind");
index 9bac7191fa65875d73d6d1d3e5c0a45e1ba6427c..d957d70edb5408497f63a637467f661a48642b3d 100644 (file)
@@ -197,7 +197,7 @@ BIN_PROGS3 = bin/smbpasswd@EXEEXT@ bin/rpcclient@EXEEXT@ bin/smbcacls@EXEEXT@ \
        bin/profiles@EXEEXT@ bin/ntlm_auth@EXEEXT@ bin/sharesec@EXEEXT@ \
        bin/smbcquotas@EXEEXT@ bin/eventlogadm@EXEEXT@
 BIN_PROGS4 = bin/ldbedit@EXEEXT@ bin/ldbsearch@EXEEXT@ bin/ldbadd@EXEEXT@ \
-       bin/ldbdel@EXEEXT@ bin/ldbmodify@EXEEXT@
+       bin/ldbdel@EXEEXT@ bin/ldbmodify@EXEEXT@ bin/ldbrename@EXEEXT@
 
 TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \
        bin/masktest@EXEEXT@ bin/locktest@EXEEXT@ \
@@ -338,7 +338,9 @@ UTIL_OBJ = ../lib/util/rbtree.o ../lib/util/signal.o ../lib/util/time.o \
                   ../lib/util/util_file.o ../lib/util/data_blob.o \
                   ../lib/util/util.o ../lib/util/fsusage.o \
                   ../lib/util/params.o ../lib/util/talloc_stack.o \
-                  ../lib/util/genrand.o ../lib/util/util_net.o
+                  ../lib/util/genrand.o ../lib/util/util_net.o \
+                  ../lib/util/become_daemon.o ../lib/util/system.o \
+                  ../lib/util/tevent_unix.o ../lib/util/tevent_ntstatus.o
 
 CRYPTO_OBJ = ../lib/crypto/crc32.o ../lib/crypto/md5.o \
                         ../lib/crypto/hmacmd5.o ../lib/crypto/arcfour.o \
@@ -443,7 +445,10 @@ LIBSMB_OBJ0 = \
 LIBSAMBA_OBJ = $(LIBSMB_OBJ0) \
               $(LIBSMB_ERR_OBJ)
 
-CLDAP_OBJ = libads/cldap.o
+LIBCLI_LDAP_MESSAGE_OBJ = ../libcli/ldap/ldap_message.o
+LIBCLI_LDAP_NDR_OBJ = ../libcli/ldap/ldap_ndr.o
+
+CLDAP_OBJ = libads/cldap.o $(LIBCLI_LDAP_MESSAGE_OBJ) $(LIBCLI_LDAP_NDR_OBJ)
 
 LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
             libsmb/clikrb5.o libsmb/clispnego.o ../lib/util/asn1.o \
@@ -464,7 +469,7 @@ RPC_CLIENT_OBJ1 = rpc_client/cli_netlogon.o
 
 LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
               $(RPC_CLIENT_OBJ1) rpc_client/cli_reg.o $(RPC_CLIENT_OBJ) \
-              rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o  \
+              rpc_client/cli_spoolss.o \
               rpc_client/init_spoolss.o \
               rpc_client/init_samr.o \
                   librpc/rpc/dcerpc.o \
@@ -621,7 +626,8 @@ PROFILES_OBJ = utils/profiles.o \
                $(LIB_OBJ) $(LIB_DUMMY_OBJ) \
                $(POPT_LIB_OBJ)
 
-OPLOCK_OBJ = smbd/oplock.o smbd/oplock_irix.o smbd/oplock_linux.o smbd/oplock_onefs.o
+OPLOCK_OBJ = smbd/oplock.o smbd/oplock_irix.o smbd/oplock_linux.o \
+            smbd/oplock_onefs.o
 
 NOTIFY_OBJ = smbd/notify.o smbd/notify_inotify.o smbd/notify_internal.o
 
@@ -666,7 +672,8 @@ VFS_ACL_TDB_OBJ = modules/vfs_acl_tdb.o
 VFS_SMB_TRAFFIC_ANALYZER_OBJ = modules/vfs_smb_traffic_analyzer.o
 VFS_ONEFS_OBJ = modules/vfs_onefs.o modules/onefs_acl.o modules/onefs_system.o \
                modules/onefs_open.o modules/onefs_streams.o modules/onefs_dir.c \
-               modules/onefs_cbrl.o
+               modules/onefs_cbrl.o modules/onefs_notify.o
+VFS_ONEFS_SHADOW_COPY_OBJ = modules/vfs_onefs_shadow_copy.o modules/onefs_shadow_copy.o
 PERFCOUNT_ONEFS_OBJ = modules/perfcount_onefs.o
 PERFCOUNT_TEST_OBJ = modules/perfcount_test.o
 
@@ -682,6 +689,7 @@ AUTH_SAM_OBJ = auth/auth_sam.o
 AUTH_SERVER_OBJ = auth/auth_server.o
 AUTH_UNIX_OBJ = auth/auth_unix.o
 AUTH_WINBIND_OBJ = auth/auth_winbind.o
+AUTH_WBC_OBJ = auth/auth_wbc.o
 AUTH_SCRIPT_OBJ = auth/auth_script.o
 AUTH_NETLOGOND_OBJ = auth/auth_netlogond.o
 
@@ -752,7 +760,7 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
             nmbd/nmbd_subnetdb.o nmbd/nmbd_winsproxy.o nmbd/nmbd_winsserver.o \
             nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o smbd/connection.o
 
-NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIENT_OBJ) \
            $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
           $(LIBNDR_GEN_OBJ0)
 
@@ -931,7 +939,7 @@ NET_OBJ = $(NET_OBJ1) \
          $(PRIVILEGES_BASIC_OBJ) @LIBLUA_STATIC@ \
          $(LIB_EVENTLOG_OBJ)
 
-CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
+CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) \
          $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \
          $(LIBNDR_GEN_OBJ0)
 
@@ -948,24 +956,24 @@ SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/uta
                torture/denytest.o torture/mangle_test.o
 
 SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) \
-       $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \
+       $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \
        lib/wb_reqtrans.o lib/wbclient.o \
        @LIBWBCLIENT_STATIC@ \
        $(LIBNDR_GEN_OBJ0)
 
-MASKTEST_OBJ = torture/masktest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+MASKTEST_OBJ = torture/masktest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIENT_OBJ) \
                  $(LIB_NONSMBD_OBJ) \
                 $(LIBNDR_GEN_OBJ0)
 
-MSGTEST_OBJ = torture/msgtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+MSGTEST_OBJ = torture/msgtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIENT_OBJ) \
                  $(LIB_NONSMBD_OBJ) \
                 $(LIBNDR_GEN_OBJ0)
 
 LOCKTEST_OBJ = torture/locktest.o $(PARAM_OBJ) $(LOCKING_OBJ) $(KRBCLIENT_OBJ) \
-               $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) \
+               $(LIBSMB_OBJ) $(LDB_OBJ) $(LIB_NONSMBD_OBJ) \
                $(LIBNDR_GEN_OBJ0)
 
-NSSTEST_OBJ = torture/nsstest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
+NSSTEST_OBJ = torture/nsstest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIENT_OBJ) \
                  $(LIB_NONSMBD_OBJ) \
                 $(LIBNDR_GEN_OBJ0)
 
@@ -980,7 +988,7 @@ SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ
 
 LOG2PCAP_OBJ = utils/log2pcaphex.o
 
-LOCKTEST2_OBJ = torture/locktest2.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \
+LOCKTEST2_OBJ = torture/locktest2.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) \
                $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \
                $(LIBNDR_GEN_OBJ0)
 
@@ -1020,7 +1028,7 @@ REPLACETORT_OBJ = @libreplacedir@/test/testsuite.o \
 
 DEBUG2HTML_OBJ = utils/debug2html.o utils/debugparse.o
 
-SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
+SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) \
                  $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
                 $(LIBNDR_GEN_OBJ0)
 
@@ -1124,6 +1132,7 @@ LDBSEARCH_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbsearch.o
 LDBADD_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbadd.o
 LDBDEL_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbdel.o
 LDBMODIFY_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbmodify.o
+LDBRENAME_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbrename.o
 
 WINBIND_KRB5_LOCATOR_OBJ1 = ../nsswitch/winbind_krb5_locator.o
 WINBIND_KRB5_LOCATOR_OBJ = $(WINBIND_KRB5_LOCATOR_OBJ1) $(LIBREPLACE_OBJ)
@@ -1615,6 +1624,12 @@ bin/ldbdel: $(BINARY_PREREQS) $(LDBDEL_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIB
                $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \
                $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS)
 
+bin/ldbrename: $(BINARY_PREREQS) $(LDBRENAME_OBJ) @BUILD_POPT@ @LIBTALLOC_SHARED@ @LIBTDB_SHARED@ @LIBWBCLIENT_SHARED@
+       @echo Linking $@
+       @$(CC) $(FLAGS) -o $@ $(LDBRENAME_OBJ) $(DYNEXP) $(LDFLAGS) \
+               $(LIBS) $(POPT_LIBS) $(LDAP_LIBS) \
+               $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) $(WINBIND_LIBS)
+
 
 #####################################################################
 #
@@ -2340,6 +2355,10 @@ bin/winbind.@SHLIBEXT@: $(BINARY_PREREQS) $(AUTH_WINBIND_OBJ)
        @echo "Building plugin $@"
        @$(SHLD_MODULE) $(AUTH_WINBIND_OBJ)
 
+bin/wbc.@SHLIBEXT@: $(BINARY_PREREQS) $(AUTH_WBC_OBJ)
+       @echo "Building plugin $@"
+       @$(SHLD_MODULE) $(AUTH_WBC_OBJ)
+
 bin/unix.@SHLIBEXT@: $(BINARY_PREREQS) $(AUTH_UNIX_OBJ)
        @echo "Building plugin $@"
        @$(SHLD_MODULE) $(AUTH_UNIX_OBJ)
@@ -2356,6 +2375,10 @@ bin/tdbsam.@SHLIBEXT@: $(BINARY_PREREQS) passdb/pdb_tdb.o
        @echo "Building plugin $@"
        @$(SHLD_MODULE) passdb/pdb_tdb.o
 
+bin/wbc_sam.@SHLIBEXT@: $(BINARY_PREREQS) passdb/pdb_wbc_sam.o
+       @echo "Building plugin $@"
+       @$(SHLD_MODULE) passdb/pdb_wbc_sam.o
+
 bin/smbpasswd.@SHLIBEXT@: $(BINARY_PREREQS) passdb/pdb_smbpasswd.o
        @echo "Building plugin $@"
        @$(SHLD_MODULE) passdb/pdb_smbpasswd.o
@@ -2559,6 +2582,10 @@ bin/onefs.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_ONEFS_OBJ)
        @echo "Building plugin $@"
        @$(SHLD_MODULE) $(VFS_ONEFS_OBJ) @ONEFS_LIBS@
 
+bin/onefs_shadow_copy.@SHLIBEXT@: $(BINARY_PREREQS) $(VFS_ONEFS_SHADOW_COPY_OBJ)
+       @echo "Building plugin $@"
+       @$(SHLD_MODULE) $(VFS_ONEFS_SHADOW_COPY_OBJ)
+
 bin/pc_onefs.@SHLIBEXT@: $(BINARY_PREREQS) $(PERFCOUNT_ONEFS_OBJ)
        @echo "Building plugin $@"
        @$(SHLD_MODULE) $(PERFCOUNT_ONEFS_OBJ)
index 505098c76ac26b93d390d72a24f46b6ee6a60f71..fd4c50375258875052c5046e792de58c2c500d51 100644 (file)
@@ -2,17 +2,17 @@
    Unix SMB/CIFS implementation.
    Password and authentication handling
    Copyright (C) Andrew Bartlett         2001-2002
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
@@ -49,7 +49,7 @@ NTSTATUS smb_register_auth(int version, const char *name, auth_init_function ini
                DEBUG(0,("There already is an auth method registered with the name %s!\n", name));
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
-       
+
        entry = SMB_XMALLOC_P(struct auth_init_function_entry);
        entry->name = smb_xstrdup(name);
        entry->init = init;
@@ -67,7 +67,7 @@ static struct auth_init_function_entry *auth_find_backend_entry(const char *name
                if (strcmp(entry->name, name)==0) return entry;
                entry = entry->next;
        }
-       
+
        return NULL;
 }
 
@@ -76,7 +76,8 @@ static struct auth_init_function_entry *auth_find_backend_entry(const char *name
  Returns a const char of length 8 bytes.
 ****************************************************************************/
 
-static const uint8 *get_ntlm_challenge(struct auth_context *auth_context) 
+static void get_ntlm_challenge(struct auth_context *auth_context,
+                              uint8_t chal[8])
 {
        DATA_BLOB challenge = data_blob_null;
        const char *challenge_set_by = NULL;
@@ -86,7 +87,8 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context)
        if (auth_context->challenge.length) {
                DEBUG(5, ("get_ntlm_challenge (auth subsystem): returning previous challenge by module %s (normal)\n", 
                          auth_context->challenge_set_by));
-               return auth_context->challenge.data;
+               memcpy(chal, auth_context->challenge.data, 8);
+               return;
        }
 
        auth_context->challenge_may_be_modified = False;
@@ -108,7 +110,7 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context)
                if (!mem_ctx) {
                        smb_panic("talloc_init() failed!");
                }
-               
+
                challenge = auth_method->get_chal(auth_context, &auth_method->private_data, mem_ctx);
                if (!challenge.length) {
                        DEBUG(3, ("auth_get_challenge: getting challenge from authentication method %s FAILED.\n", 
@@ -121,27 +123,27 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context)
                }
                talloc_destroy(mem_ctx);
        }
-       
+
        if (!challenge_set_by) {
-               uchar chal[8];
-               
-               generate_random_buffer(chal, sizeof(chal));
+               uchar tmp[8];
+
+               generate_random_buffer(tmp, sizeof(tmp));
                auth_context->challenge = data_blob_talloc(auth_context->mem_ctx, 
-                                                          chal, sizeof(chal));
-               
+                                                          tmp, sizeof(tmp));
+
                challenge_set_by = "random";
                auth_context->challenge_may_be_modified = True;
        } 
-       
+
        DEBUG(5, ("auth_context challenge created by %s\n", challenge_set_by));
        DEBUG(5, ("challenge is: \n"));
        dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
-       
+
        SMB_ASSERT(auth_context->challenge.length == 8);
 
        auth_context->challenge_set_by=challenge_set_by;
 
-       return auth_context->challenge.data;
+       memcpy(chal, auth_context->challenge.data, 8);
 }
 
 
@@ -249,7 +251,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
 
        for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) {
                NTSTATUS result;
-               
+
                mem_ctx = talloc_init("%s authentication for user %s\\%s", auth_method->name, 
                                            user_info->domain, user_info->smb_name);
 
@@ -281,7 +283,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
        }
 
        /* successful authentication */
-       
+
        if (NT_STATUS_IS_OK(nt_status)) {
                unix_username = (*server_info)->unix_name;
                if (!(*server_info)->guest) {
@@ -289,7 +291,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
                        become_root();
                        nt_status = smb_pam_accountcheck(unix_username);
                        unbecome_root();
-                       
+
                        if (NT_STATUS_IS_OK(nt_status)) {
                                DEBUG(5, ("check_ntlm_password:  PAM Account for user [%s] succeeded\n", 
                                          unix_username));
@@ -298,7 +300,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
                                          unix_username, nt_errstr(nt_status)));
                        } 
                }
-               
+
                if (NT_STATUS_IS_OK(nt_status)) {
                        DEBUG((*server_info)->guest ? 5 : 2, 
                              ("check_ntlm_password:  %sauthentication for user [%s] -> [%s] -> [%s] succeeded\n", 
@@ -307,17 +309,17 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
                               user_info->internal_username, 
                               unix_username));
                }
-               
+
                return nt_status;
        }
-       
+
        /* failed authentication; check for guest lapping */
-       
+
        DEBUG(2, ("check_ntlm_password:  Authentication for user [%s] -> [%s] FAILED with error %s\n", 
                  user_info->smb_name, user_info->internal_username, 
                  nt_errstr(nt_status)));
        ZERO_STRUCTP(server_info); 
-       
+
        return nt_status;
 }
 
@@ -349,7 +351,7 @@ static NTSTATUS make_auth_context(struct auth_context **auth_context)
        TALLOC_CTX *mem_ctx;
 
        mem_ctx = talloc_init("authentication context");
-       
+
        *auth_context = TALLOC_P(mem_ctx, struct auth_context);
        if (!*auth_context) {
                DEBUG(0,("make_auth_context: talloc failed!\n"));
@@ -362,7 +364,7 @@ static NTSTATUS make_auth_context(struct auth_context **auth_context)
        (*auth_context)->check_ntlm_password = check_ntlm_password;
        (*auth_context)->get_ntlm_challenge = get_ntlm_challenge;
        (*auth_context)->free = free_auth_context;
-       
+
        return NT_STATUS_OK;
 }
 
@@ -382,21 +384,21 @@ bool load_auth_module(struct auth_context *auth_context,
                static_init_auth;
                initialised_static_modules = True;
        }
-       
+
        DEBUG(5,("load_auth_module: Attempting to find an auth method to match %s\n",
                 module));
-       
+
        p = strchr(module_name, ':');
        if (p) {
                *p = 0;
                module_params = p+1;
                trim_char(module_params, ' ', ' ');
        }
-       
+
        trim_char(module_name, ' ', ' ');
-       
+
        entry = auth_find_backend_entry(module_name);
-       
+
        if (entry == NULL) {
                if (NT_STATUS_IS_OK(smb_probe_module("auth", module_name))) {
                        entry = auth_find_backend_entry(module_name);
@@ -434,7 +436,7 @@ static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context,
                DEBUG(2,("make_auth_context_text_list: No auth method list!?\n"));
                return NT_STATUS_UNSUCCESSFUL;
        }
-       
+
        if (!NT_STATUS_IS_OK(nt_status = make_auth_context(auth_context)))
                return nt_status;
 
@@ -443,9 +445,9 @@ static NTSTATUS make_auth_context_text_list(struct auth_context **auth_context,
                    DLIST_ADD_END(list, t, auth_methods *);
                }
        }
-       
+
        (*auth_context)->auth_method_list = list;
-       
+
        return nt_status;
 }
 
@@ -523,7 +525,7 @@ NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context)
        } else {
                DEBUG(5,("Using specified auth order\n"));
        }
-       
+
        nt_status = make_auth_context_text_list(auth_context,
                                                auth_method_list);
 
@@ -541,7 +543,7 @@ NTSTATUS make_auth_context_fixed(struct auth_context **auth_context, uchar chal[
        if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(auth_context))) {
                return nt_status;
        }
-       
+
        (*auth_context)->challenge = data_blob_talloc((*auth_context)->mem_ctx, chal, 8);
        (*auth_context)->challenge_set_by = "fixed";
        return nt_status;
index 00d9dea816cd8eb42b49b5412bf336ba455f2d6a..925c0d4f815789234dd5d139b34da3abde1e0a69 100644 (file)
@@ -39,13 +39,14 @@ NTSTATUS check_plaintext_password(const char *smb_name, DATA_BLOB plaintext_pass
 {
        struct auth_context *plaintext_auth_context = NULL;
        auth_usersupplied_info *user_info = NULL;
-       const uint8 *chal;
+       uint8_t chal[8];
        NTSTATUS nt_status;
        if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
                return nt_status;
        }
 
-       chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
+       plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context,
+                                                  chal);
 
        if (!make_user_info_for_reply(&user_info, 
                                      smb_name, lp_workgroup(), chal,
index 0d46b14f97e54f1e560c7f2216d45c13905fc5e6..034d354a33712e3a9c665247ae7b5e823580776f 100644 (file)
  * @return an 8 byte random challenge
  */
 
-static const uint8 *auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state)
+static void auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state,
+                                      uint8_t chal[8])
 {
        AUTH_NTLMSSP_STATE *auth_ntlmssp_state =
                (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context;
-       return auth_ntlmssp_state->auth_context->get_ntlm_challenge(auth_ntlmssp_state->auth_context);
+       auth_ntlmssp_state->auth_context->get_ntlm_challenge(
+               auth_ntlmssp_state->auth_context, chal);
 }
 
 /**
index 0dab05b97c5c072454222fab3e62ab3af19fc2c1..c39aa8501d28359d002e396bf8d55168b7094bd2 100644 (file)
@@ -710,8 +710,6 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info)
        NTSTATUS status;
        size_t i;
        struct dom_sid tmp_sid;
-       const char *name_to_use;
-       bool force_nss;
 
        /*
         * If winbind is not around, we can not make much use of the SIDs the
@@ -719,22 +717,11 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info)
         * mapped to some local unix user.
         */
 
-       DEBUG(10, ("creating token for %s (SAM: %s)\n", server_info->unix_name,
-               server_info->sam_account->username));
-
-       force_nss = lp_force_username_map() && !server_info->nss_token;
        if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
-           server_info->nss_token || force_nss) {
-               if (force_nss)
-                       name_to_use =
-                           pdb_get_username(server_info->sam_account);
-               else
-                       name_to_use = server_info->unix_name;
-
+           (server_info->nss_token)) {
                status = create_token_from_username(server_info,
-                                                   name_to_use,
+                                                   server_info->unix_name,
                                                    server_info->guest,
-                                                   force_nss,
                                                    &server_info->utok.uid,
                                                    &server_info->utok.gid,
                                                    &server_info->unix_name,
@@ -819,7 +806,7 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info)
 }
 
 /*
- * Create an artificial NT token given just a username. (Initially indended
+ * Create an artificial NT token given just a username. (Initially intended
  * for force user)
  *
  * We go through lookup_name() to avoid problems we had with 'winbind use
@@ -839,7 +826,6 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info)
 
 NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
                                    bool is_guest,
-                                   bool force_nss,
                                    uid_t *uid, gid_t *gid,
                                    char **found_username,
                                    struct nt_user_token **token)
@@ -855,9 +841,6 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
        size_t num_gids;
        size_t i;
 
-       DEBUG(10, ("creating token for %s,%s guest,%s forcing NSS lookup\n",
-               username, is_guest ? "" : " not", force_nss ? "" : " not"));
-
        tmp_ctx = talloc_new(NULL);
        if (tmp_ctx == NULL) {
                DEBUG(0, ("talloc_new failed\n"));
@@ -876,13 +859,7 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
                goto done;
        }
 
-       if (!sid_to_uid(&user_sid, uid)) {
-               DEBUG(1, ("sid_to_uid for %s (%s) failed\n",
-                         username, sid_string_dbg(&user_sid)));
-               goto done;
-       }
-
-       if (sid_check_is_in_our_domain(&user_sid) && !force_nss) {
+       if (sid_check_is_in_our_domain(&user_sid)) {
                bool ret;
 
                /* This is a passdb user, so ask passdb */
@@ -924,7 +901,7 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
                *found_username = talloc_strdup(mem_ctx,
                                                pdb_get_username(sam_acct));
 
-       } else  if (force_nss || sid_check_is_in_unix_users(&user_sid)) {
+       } else  if (sid_check_is_in_unix_users(&user_sid)) {
 
                /* This is a unix user not in passdb. We need to ask nss
                 * directly, without consulting passdb */
@@ -939,6 +916,12 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
 
        unix_user:
 
+               if (!sid_to_uid(&user_sid, uid)) {
+                       DEBUG(1, ("sid_to_uid for %s (%s) failed\n",
+                                 username, sid_string_dbg(&user_sid)));
+                       goto done;
+               }
+
                uid_to_unix_users_sid(*uid, &user_sid);
 
                pass = getpwuid_alloc(tmp_ctx, *uid);
@@ -1080,7 +1063,6 @@ bool user_in_group_sid(const char *username, const DOM_SID *group_sid)
        }
 
        status = create_token_from_username(mem_ctx, username, False,
-                                           lp_force_username_map(),
                                            &uid, &gid, &found_username,
                                            &token);
 
diff --git a/source3/auth/auth_wbc.c b/source3/auth/auth_wbc.c
new file mode 100644 (file)
index 0000000..580c8b5
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Winbind client authentication mechanism designed to defer all
+   authentication to the winbind daemon.
+
+   Copyright (C) Tim Potter 2000
+   Copyright (C) Andrew Bartlett 2001 - 2002
+   Copyright (C) Dan Sledz 2009
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* This auth module is very similar to auth_winbind with 3 distinct
+ * differences.
+ *
+ *      1) Does not fallback to another auth module if winbindd is unavailable
+ *      2) Does not validate the domain of the user
+ *      3) Handles unencrypted passwords
+ *
+ * The purpose of this module is to defer all authentication decisions (ie:
+ * local user vs NIS vs LDAP vs AD; encrypted vs plaintext) to the wbc
+ * compatible daemon.  This centeralizes all authentication decisions to a
+ * single provider.
+ *
+ * This auth backend is most useful when used in conjunction with pdb_wbc_sam.
+ */
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_AUTH
+
+/* Authenticate a user with a challenge/response */
+
+static NTSTATUS check_wbc_security(const struct auth_context *auth_context,
+                                      void *my_private_data,
+                                      TALLOC_CTX *mem_ctx,
+                                      const auth_usersupplied_info *user_info,
+                                      auth_serversupplied_info **server_info)
+{
+       NTSTATUS nt_status;
+       wbcErr wbc_status;
+       struct wbcAuthUserParams params;
+       struct wbcAuthUserInfo *info = NULL;
+       struct wbcAuthErrorInfo *err = NULL;
+
+       if (!user_info || !auth_context || !server_info) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       /* Send off request */
+
+       params.account_name     = user_info->smb_name;
+       params.domain_name      = user_info->domain;
+       params.workstation_name = user_info->wksta_name;
+
+       params.flags            = 0;
+       params.parameter_control= user_info->logon_parameters;
+
+       /* Handle plaintext */
+       if (!user_info->encrypted) {
+               DEBUG(3,("Checking plaintext password for %s.\n",
+                        user_info->internal_username));
+               params.level = WBC_AUTH_USER_LEVEL_PLAIN;
+
+               params.password.plaintext = (char *)user_info->plaintext_password.data;
+       } else {
+               DEBUG(3,("Checking encrypted password for %s.\n",
+                        user_info->internal_username));
+               params.level = WBC_AUTH_USER_LEVEL_RESPONSE;
+
+               memcpy(params.password.response.challenge,
+                   auth_context->challenge.data,
+                   sizeof(params.password.response.challenge));
+
+               params.password.response.nt_length = user_info->nt_resp.length;
+               params.password.response.nt_data = user_info->nt_resp.data;
+               params.password.response.lm_length = user_info->lm_resp.length;
+               params.password.response.lm_data = user_info->lm_resp.data;
+
+       }
+
+       /* we are contacting the privileged pipe */
+       become_root();
+       wbc_status = wbcAuthenticateUserEx(&params, &info, &err);
+       unbecome_root();
+
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               DEBUG(10,("wbcAuthenticateUserEx failed (%d): %s\n",
+                       wbc_status, wbcErrorString(wbc_status)));
+       }
+
+       if (wbc_status == WBC_ERR_NO_MEMORY) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (wbc_status == WBC_ERR_AUTH_ERROR) {
+               nt_status = NT_STATUS(err->nt_status);
+               wbcFreeMemory(err);
+               return nt_status;
+       }
+
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       DEBUG(10,("wbcAuthenticateUserEx succeeded\n"));
+
+       nt_status = make_server_info_wbcAuthUserInfo(mem_ctx,
+                                                    user_info->smb_name,
+                                                    user_info->domain,
+                                                    info, server_info);
+       wbcFreeMemory(info);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
+       }
+
+       (*server_info)->nss_token |= user_info->was_mapped;
+
+        return nt_status;
+}
+
+/* module initialisation */
+static NTSTATUS auth_init_wbc(struct auth_context *auth_context, const char *param, auth_methods **auth_method)
+{
+       if (!make_auth_methods(auth_context, auth_method)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       (*auth_method)->name = "wbc";
+       (*auth_method)->auth = check_wbc_security;
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS auth_wbc_init(void)
+{
+       return smb_register_auth(AUTH_INTERFACE_VERSION, "wbc", auth_init_wbc);
+}
index 2f9e3c0d49716299ea5b5f46c5339601309d188d..aaa9e35d9689bdc8768db5b99f81aa90cb4cce78 100644 (file)
@@ -1784,13 +1784,13 @@ static struct file_list {
  Free a file_list structure.
 ****************************************************************************/
 
-static void free_file_list (struct file_list *list_head)
+static void free_file_list (struct file_list *l_head)
 {
        struct file_list *list, *next;
 
-       for (list = list_head; list; list = next) {
+       for (list = l_head; list; list = next) {
                next = list->next;
-               DLIST_REMOVE(list_head, list);
+               DLIST_REMOVE(l_head, list);
                SAFE_FREE(list->file_path);
                SAFE_FREE(list);
        }
index a73660958055f72559c2edcb32a8ff44cd0ca95c..8623d3c04b537d3022f23b62e2da3aaca40f29ef 100644 (file)
@@ -179,7 +179,6 @@ static void mount_cifs_usage(void)
        printf("\n\t%s -V\n",thisprogram);
 
        SAFE_FREE(mountpassword);
-       exit(EX_USAGE);
 }
 
 /* caller frees username if necessary */
@@ -650,7 +649,9 @@ static int parse_options(char ** optionsp, int * filesys_flags)
                } else if (strncmp(data, "exec", 4) == 0) {
                        *filesys_flags &= ~MS_NOEXEC;
                } else if (strncmp(data, "guest", 5) == 0) {
-                       got_password=1;
+                       user_name = (char *)calloc(1, 1);
+                       got_user = 1;
+                       got_password = 1;
                } else if (strncmp(data, "ro", 2) == 0) {
                        *filesys_flags |= MS_RDONLY;
                } else if (strncmp(data, "rw", 2) == 0) {
@@ -1017,6 +1018,14 @@ uppercase_string(char *string)
        return 1;
 }
 
+static void print_cifs_mount_version(void)
+{
+       printf("mount.cifs version: %s.%s%s\n",
+               MOUNT_CIFS_VERSION_MAJOR,
+               MOUNT_CIFS_VERSION_MINOR,
+               MOUNT_CIFS_VENDOR_SUFFIX);
+}
+
 int main(int argc, char ** argv)
 {
        int c;
@@ -1078,6 +1087,24 @@ int main(int argc, char ** argv)
                        exit(EX_SYSERR);
                }
                mountpoint = argv[2];
+       } else if (argc == 2) {
+               if ((strcmp(argv[1], "-V") == 0) ||
+                   (strcmp(argv[1], "--version") == 0))
+               {
+                       print_cifs_mount_version();
+                       exit(0);
+               }
+
+               if ((strcmp(argv[1], "-h") == 0) ||
+                   (strcmp(argv[1], "-?") == 0) ||
+                   (strcmp(argv[1], "--help") == 0))
+               {
+                       mount_cifs_usage();
+                       exit(0);
+               }
+
+               mount_cifs_usage();
+               exit(EX_USAGE);
        } else {
                mount_cifs_usage();
                exit(EX_USAGE);
@@ -1102,7 +1129,7 @@ int main(int argc, char ** argv)
                case '?':
                case 'h':        /* help */
                        mount_cifs_usage ();
-                       exit(EX_USAGE);
+                       exit(0);
                case 'n':
                        ++nomtab;
                        break;
@@ -1134,11 +1161,8 @@ int main(int argc, char ** argv)
                case 'v':
                        ++verboseflag;
                        break;
-               case 'V':          
-                       printf ("mount.cifs version: %s.%s%s\n",
-                       MOUNT_CIFS_VERSION_MAJOR,
-                       MOUNT_CIFS_VERSION_MINOR,
-                       MOUNT_CIFS_VENDOR_SUFFIX);
+               case 'V':
+                       print_cifs_mount_version();
                        exit (0);
                case 'w':
                        flags &= ~MS_RDONLY;
index 57d475fcc58455e6d5a130131ef1bb3dd3d6ed44..d67feccb9b518a56a4c621991dc82b10195e7e0c 100644 (file)
@@ -414,7 +414,7 @@ AC_SUBST(DYNEXP)
 
 dnl Add modules that have to be built by default here
 dnl These have to be built static:
-default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsarpc rpc_samr rpc_winreg rpc_initshutdown rpc_dssetup rpc_wkssvc rpc_svcctl rpc_ntsvcs rpc_netlogon rpc_netdfs rpc_srvsvc rpc_spoolss2 rpc_eventlog auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin auth_netlogond vfs_default nss_info_template"
+default_static_modules="pdb_smbpasswd pdb_tdbsam pdb_wbc_sam rpc_lsarpc rpc_samr rpc_winreg rpc_initshutdown rpc_dssetup rpc_wkssvc rpc_svcctl rpc_ntsvcs rpc_netlogon rpc_netdfs rpc_srvsvc rpc_spoolss2 rpc_eventlog auth_sam auth_unix auth_winbind auth_wbc auth_server auth_domain auth_builtin auth_netlogond vfs_default nss_info_template"
 
 dnl These are preferably build shared, and static if dlopen() is not available
 default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_xattr_tdb vfs_streams_xattr vfs_streams_depot vfs_acl_xattr vfs_acl_tdb vfs_smb_traffic_analyzer"
@@ -1044,6 +1044,9 @@ AC_SEARCH_LIBS(backtrace_symbols, [execinfo])
 AC_CHECK_FUNCS(backtrace_symbols)
 AC_CHECK_LIB(exc, trace_back_stack)
 
+# check for sysctlbyname for BSD systems
+AC_CHECK_FUNCS(sysctlbyname)
+
 printf "%s" "checking for GPFS GPL libs... "
 save_LIBS="$LIBS"
 LIBS="$LIBS -lgpfs_gpl"
@@ -1084,7 +1087,8 @@ AC_TRY_LINK([#include <isi_version/isi_version.h>],
 echo $samba_cv_HAVE_ONEFS
 if test x"$samba_cv_HAVE_ONEFS" = x"yes"; then
     AC_DEFINE(HAVE_ONEFS,1,[Whether building on Isilon OneFS])
-    default_shared_modules="$default_shared_modules vfs_onefs perfcount_onefs"
+    default_shared_modules="$default_shared_modules vfs_onefs vfs_onefs_shadow_copy perfcount_onefs"
+    default_static_modules="$default_static_modules"
     ONEFS_LIBS="-lisi_acl -lisi_ecs -lisi_event -lisi_util"
     # Need to also add general libs for oplocks support
     save_LIBS="$save_LIBS -lisi_ecs -lisi_event -lisi_util -ldevstat"
@@ -5713,6 +5717,34 @@ AC_MSG_CHECKING(whether to build winbind)
 # Initially, the value of $host_os decides whether winbind is supported
 
 HAVE_WINBIND=yes
+HAVE_WBCLIENT=no
+
+# Define external wbclient library to link against.  This disables winbind.
+# We define this here so --with-winbind can override it.
+AC_ARG_WITH(wbclient,
+[AS_HELP_STRING([--with-wbclient], [Use external wbclient (optional)])],
+[
+  case "$withval" in
+        no)
+               HAVE_WBCLIENT=no
+               ;;
+       yes)
+               HAVE_WBCLIENT=yes
+               HAVE_WINBIND=no
+               ;;
+        *)
+               HAVE_WBCLIENT=yes
+               HAVE_WINBIND=no
+               WBCLIENT_INCLUDES="-I$withval/include"
+               WBCLIENT_LDFLAGS="-L$withval/lib"
+               ;;
+  esac ],
+)
+
+AC_SUBST(WBCLIENT_INCLUDES)
+AC_SUBST(WBCLIENT_LDFLAGS)
+AC_SUBST(WBCLIENT_LIBS)
+
 
 # Define the winbind shared library name and any specific linker flags
 # it needs to be built with.
@@ -5794,6 +5826,7 @@ AC_ARG_WITH(winbind,
   case "$withval" in
        yes)
                HAVE_WINBIND=yes
+               HAVE_WBCLIENT=no
                ;;
         no)
                HAVE_WINBIND=no
@@ -5817,27 +5850,35 @@ if test x"$HAVE_WINBIND" = x"no"; then
        WINBIND_NSS=""
        WINBIND_WINS_NSS=""
 fi
-
-if test x"$enable_developer" = x"yes" -a x"$LINK_LIBWBCLIENT" = x"STATIC" ; then
-       BUILD_LIBWBCLIENT_SHARED=no
-else
-       BUILD_LIBWBCLIENT_SHARED=yes
-fi
-
-LIBWBCLIENT_SHARED_TARGET=bin/libwbclient.$SHLIBEXT
-LIBWBCLIENT_STATIC_TARGET=bin/libwbclient.a
-LIBWBCLIENT_SOVER=0
-if test $BLDSHARED = true -a x"$HAVE_WINBIND" = x"yes" -a x"$BUILD_LIBWBCLIENT_SHARED" = x"yes"; then
-       NSS_MODULES="${WINBIND_NSS} ${WINBIND_WINS_NSS}"
-       ## Only worry about libwbclient if we have shared library support
-       ## and winbindd
-        LIBWBCLIENT_SHARED=$LIBWBCLIENT_SHARED_TARGET
-        LIBWBCLIENT=libwbclient
-       INSTALL_LIBWBCLIENT=installlibwbclient
-       UNINSTALL_LIBWBCLIENT=uninstalllibwbclient
-       WINBIND_LIBS="-lwbclient"
+if test x"$HAVE_WBCLIENT" = x"yes"; then
+        AC_CHECK_LIB(wbclient, wbcInterfaceDetails,
+                    [WINBIND_LIBS="-lwbclient"], AC_MSG_ERROR([Could not find wbclient]), [$WBCLIENT_LDFLAGS])
+       WINBIND_LIBS="$WINBIND_LIBS $WBCLIENT_LDFLAGS"
+       AC_MSG_RESULT(yes)
+       AC_DEFINE(WITH_WINBIND,1,[Whether to link to wbclient])
+       EXTRA_BIN_PROGS="$EXTRA_BIN_PROGS bin/wbinfo\$(EXEEXT)"
 else
-       LIBWBCLIENT_STATIC=$LIBWBCLIENT_STATIC_TARGET
+       if test x"$enable_developer" = x"yes" -a x"$LINK_LIBWBCLIENT" = x"STATIC" ; then
+               BUILD_LIBWBCLIENT_SHARED=no
+       else
+               BUILD_LIBWBCLIENT_SHARED=yes
+       fi
+
+       LIBWBCLIENT_SHARED_TARGET=bin/libwbclient.$SHLIBEXT
+       LIBWBCLIENT_STATIC_TARGET=bin/libwbclient.a
+       LIBWBCLIENT_SOVER=0
+       if test $BLDSHARED = true -a x"$HAVE_WINBIND" = x"yes" -a x"$BUILD_LIBWBCLIENT_SHARED" = x"yes"; then
+               NSS_MODULES="${WINBIND_NSS} ${WINBIND_WINS_NSS}"
+               ## Only worry about libwbclient if we have shared
+               # library support
+               LIBWBCLIENT_SHARED=$LIBWBCLIENT_SHARED_TARGET
+               LIBWBCLIENT=libwbclient
+               INSTALL_LIBWBCLIENT=installlibwbclient
+               UNINSTALL_LIBWBCLIENT=uninstalllibwbclient
+               WINBIND_LIBS="-lwbclient"
+       else
+               LIBWBCLIENT_STATIC=$LIBWBCLIENT_STATIC_TARGET
+       fi
 fi
 
 if test x"$HAVE_WINBIND" = x"yes"; then
@@ -6089,6 +6130,7 @@ SMB_MODULE(pdb_ldap, passdb/pdb_ldap.o passdb/pdb_nds.o, "bin/ldapsam.$SHLIBEXT"
                   [ PASSDB_LIBS="$PASSDB_LIBS $LDAP_LIBS" ] )
 SMB_MODULE(pdb_smbpasswd, passdb/pdb_smbpasswd.o, "bin/smbpasswd.$SHLIBEXT", PDB)
 SMB_MODULE(pdb_tdbsam, passdb/pdb_tdb.o, "bin/tdbsam.$SHLIBEXT", PDB)
+SMB_MODULE(pdb_wbc_sam, passdb/pdb_wbc_sam.o, "bin/wbc_sam.$SHLIBEXT", PDB)
 SMB_SUBSYSTEM(PDB,passdb/pdb_interface.o)
 
 
@@ -6131,6 +6173,7 @@ SMB_SUBSYSTEM(CHARSET,lib/iconv.o)
 SMB_MODULE(auth_sam, \$(AUTH_SAM_OBJ), "bin/sam.$SHLIBEXT", AUTH)
 SMB_MODULE(auth_unix, \$(AUTH_UNIX_OBJ), "bin/unix.$SHLIBEXT", AUTH)
 SMB_MODULE(auth_winbind, \$(AUTH_WINBIND_OBJ), "bin/winbind.$SHLIBEXT", AUTH)
+SMB_MODULE(auth_wbc, \$(AUTH_WBC_OBJ), "bin/wbc.$SHLIBEXT", AUTH)
 SMB_MODULE(auth_server, \$(AUTH_SERVER_OBJ), "bin/smbserver.$SHLIBEXT", AUTH)
 SMB_MODULE(auth_domain, \$(AUTH_DOMAIN_OBJ), "bin/domain.$SHLIBEXT", AUTH)
 SMB_MODULE(auth_builtin, \$(AUTH_BUILTIN_OBJ), "bin/builtin.$SHLIBEXT", AUTH)
@@ -6178,6 +6221,7 @@ SMB_MODULE(vfs_acl_xattr, \$(VFS_ACL_XATTR_OBJ), "bin/acl_xattr.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_acl_tdb, \$(VFS_ACL_TDB_OBJ), "bin/acl_tdb.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_smb_traffic_analyzer, \$(VFS_SMB_TRAFFIC_ANALYZER_OBJ), "bin/smb_traffic_analyzer.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_onefs, \$(VFS_ONEFS), "bin/onefs.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_onefs_shadow_copy, \$(VFS_ONEFS_SHADOW_COPY), "bin/onefs_shadow_copy.$SHLIBEXT", VFS)
 
 SMB_SUBSYSTEM(VFS,smbd/vfs.o)
 
index 17bccce3d75979d629ceceb2e4eb26e18d592055..7d778b92d0c1b40f2026542b3b4e1b10b4e2e4b4 100644 (file)
@@ -92,7 +92,8 @@ struct auth_context {
        struct auth_methods *auth_method_list;  
 
        TALLOC_CTX *mem_ctx;
-       const uint8 *(*get_ntlm_challenge)(struct auth_context *auth_context);
+       void (*get_ntlm_challenge)(struct auth_context *auth_context,
+                                  uint8_t chal[8]);
        NTSTATUS (*check_ntlm_password)(const struct auth_context *auth_context,
                                        const struct auth_usersupplied_info *user_info, 
                                        struct auth_serversupplied_info **server_info);
index aad4ccd721e08715432f8330a21d67d4e8a78c7d..16f10cc1252d3a9ab2a4d2bb7b0a2cff1242ea77 100644 (file)
@@ -46,6 +46,10 @@ struct db_context {
        int (*transaction_start)(struct db_context *db);
        int (*transaction_commit)(struct db_context *db);
        int (*transaction_cancel)(struct db_context *db);
+       int (*parse_record)(struct db_context *db, TDB_DATA key,
+                           int (*parser)(TDB_DATA key, TDB_DATA data,
+                                         void *private_data),
+                           void *private_data);
        void *private_data;
        bool persistent;
 };
index 1906830d485aba9b85b3ee212eaf19c868fc1e9e..523a11e255da3c7b66d3a1d5ccc94c82d491b1f4 100644 (file)
@@ -190,12 +190,12 @@ typedef int ber_int_t;
 #undef HAVE_LDAP
 #endif
 
-#if HAVE_GSSAPI_H
-#include <gssapi.h>
-#elif HAVE_GSSAPI_GSSAPI_H
+#if HAVE_GSSAPI_GSSAPI_H
 #include <gssapi/gssapi.h>
 #elif HAVE_GSSAPI_GSSAPI_GENERIC_H
 #include <gssapi/gssapi_generic.h>
+#elif HAVE_GSSAPI_H
+#include <gssapi.h>
 #endif
 
 #if HAVE_COM_ERR_H
@@ -577,6 +577,8 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx);
 #include "../talloc/talloc.h"
 
 #include "event.h"
+#include "../lib/util/tevent_unix.h"
+#include "../lib/util/tevent_ntstatus.h"
 
 #include "../lib/util/data_blob.h"
 #include "../lib/util/time.h"
@@ -677,8 +679,6 @@ struct printjob;
 
 #include "smbldap.h"
 
-#include "smb_ldap.h"
-
 /*
  * Reasons for cache flush.
  */
index f8a6c8a235ece049b2e3b96bc6d4188bbdb67446..869aeb6a032336512c101f528e61f07041cc95c5 100644 (file)
@@ -2677,12 +2677,24 @@ smbc_version(void);
  */
 
 void
-smbc_set_credentials(char *workgroup,
-                     char *user,
-                     char *password,
+smbc_set_credentials(const char *workgroup,
+                     const char *user,
+                     const char *password,
                      smbc_bool use_kerberos,
-                     char *signing_state);
+                     const char *signing_state);
 
+/*
+ * Wrapper around smbc_set_credentials.
+ * Used to set correct credentials that will
+ * be used to connect to DFS target share 
+ * in libsmbclient
+ */
+
+void
+smbc_set_credentials_with_fallback(SMBCCTX *ctx,
+                                  const char *workgroup,
+                                  const char *user,
+                                  const char *password);
 
 /**
  * @ingroup structure
index 3fd5b94de7c23c0c79cfc23882ee2ef791525625..1833ba3f80e9147d568f866759791eefac26cffe 100644 (file)
@@ -49,6 +49,7 @@ struct file_id {
           other than a dev_t for the device */
        uint64_t devid;
        uint64_t inode;
+       uint64_t extid; /* Support systems that use an extended id (e.g. snapshots). */
 };
 
 struct byte_range_lock {
index 3bf51f2c9d884116ef92f04cde250403992533f6..43fd363b55486398492941218c5b31ffb5d7fff2 100644 (file)
@@ -439,7 +439,7 @@ typedef struct _Printer{
                uint32 options;
                fstring localmachine;
                uint32 printerlocal;
-               SPOOL_NOTIFY_OPTION *option;
+               struct spoolss_NotifyOption *option;
                POLICY_HND client_hnd;
                bool client_connected;
                uint32 change;
index 55b9249ea7a4cb1bcb140a8aff518aa18b430dd1..f3414fe92837d8c4fcd0dfe4577715ee52de3a7e 100644 (file)
@@ -109,7 +109,8 @@ typedef struct ntlmssp_state
         * @return 8 bytes of challnege data, determined by the server to be the challenge for NTLM authentication
         *
         */
-       const uint8 *(*get_challenge)(const struct ntlmssp_state *ntlmssp_state);
+       void (*get_challenge)(const struct ntlmssp_state *ntlmssp_state,
+                             uint8_t challenge[8]);
 
        /**
         * Callback to find if the challenge used by NTLM authentication may be modified 
index 3806c9657e33efe06c0ac3926e52cb2faf9fabbb..5bae973c3d1531a07f2f54a833fb09c7962584b3 100644 (file)
@@ -110,7 +110,6 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
 NTSTATUS create_local_token(auth_serversupplied_info *server_info);
 NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
                                    bool is_guest,
-                                   bool force_nss,
                                    uid_t *uid, gid_t *gid,
                                    char **found_username,
                                    struct nt_user_token **token);
@@ -508,12 +507,12 @@ void dump_core_setup(const char *progname);
 
 /* The following definitions come from lib/file_id.c  */
 
-struct file_id file_id_create_dev(SMB_DEV_T dev, SMB_INO_T inode);
 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf);
 bool file_id_equal(const struct file_id *id1, const struct file_id *id2);
 const char *file_id_string_tos(const struct file_id *id);
 void push_file_id_16(char *buf, const struct file_id *id);
-void pull_file_id_16(char *buf, struct file_id *id);
+void push_file_id_24(char *buf, const struct file_id *id);
+void pull_file_id_24(char *buf, struct file_id *id);
 
 /* The following definitions come from lib/gencache.c  */
 
@@ -696,8 +695,13 @@ SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src);
 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
                           struct security_descriptor *secdesc,
                           uint8 **data, size_t *len);
+NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
+                              struct sec_desc_buf *secdesc_buf,
+                              uint8_t **data, size_t *len);
 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
                             struct security_descriptor **psecdesc);
+NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
+                                struct sec_desc_buf **psecdesc_buf);
 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *grp_sid,
                                 SEC_ACL *dacl, size_t *sd_size);
 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc);
@@ -973,8 +977,6 @@ struct passwd *sys_getpwnam(const char *name);
 struct passwd *sys_getpwuid(uid_t uid);
 struct group *sys_getgrnam(const char *name);
 struct group *sys_getgrgid(gid_t gid);
-pid_t sys_fork(void);
-pid_t sys_getpid(void);
 int sys_popen(const char *command);
 int sys_pclose(int fd);
 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size);
@@ -1139,11 +1141,9 @@ int set_message_bcc(char *buf,int num_bytes);
 ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob);
 char *unix_clean_name(TALLOC_CTX *ctx, const char *s);
 char *clean_name(TALLOC_CTX *ctx, const char *s);
-void close_low_fds(bool stderr_too);
 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos);
 int set_blocking(int fd, bool set);
 void smb_msleep(unsigned int t);
-void become_daemon(bool Fork, bool no_process_group);
 bool reinit_after_fork(struct messaging_context *msg_ctx,
                       struct event_context *ev_ctx,
                       bool parent_longlived);
@@ -1243,15 +1243,6 @@ bool is_valid_policy_hnd(const POLICY_HND *hnd);
 bool policy_hnd_equal(const struct policy_handle *hnd1,
                      const struct policy_handle *hnd2);
 const char *strip_hostname(const char *s);
-struct async_req *read_pkt_send(TALLOC_CTX *mem_ctx,
-                               struct event_context *ev,
-                               int fd, size_t initial,
-                               ssize_t (*more)(uint8_t *buf, size_t buflen,
-                                               void *priv),
-                               void *priv);
-ssize_t read_pkt_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
-                     uint8_t **pbuf, int *perr);
-
 
 /* The following definitions come from lib/util_file.c  */
 
@@ -1432,12 +1423,12 @@ int open_socket_in(int type,
                bool rebind);
 NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
                         int timeout, int *pfd);
-struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
-                                      struct event_context *ev,
-                                      const struct sockaddr_storage *pss,
-                                      uint16_t port,
-                                      int timeout);
-NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd);
+struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
+                                       struct event_context *ev,
+                                       const struct sockaddr_storage *pss,
+                                       uint16_t port,
+                                       int timeout);
+NTSTATUS open_socket_out_recv(struct tevent_req *req, int *pfd);
 struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
                                             struct event_context *ev,
                                             struct timeval wait_time,
@@ -2283,6 +2274,9 @@ ADS_STATUS gp_get_machine_token(ADS_STRUCT *ads,
 enum ndr_err_code ndr_push_server_id(struct ndr_push *ndr, int ndr_flags, const struct server_id *r);
 enum ndr_err_code ndr_pull_server_id(struct ndr_pull *ndr, int ndr_flags, struct server_id *r);
 void ndr_print_server_id(struct ndr_print *ndr, const char *name, const struct server_id *r);
+enum ndr_err_code ndr_push_file_id(struct ndr_push *ndr, int ndr_flags, const struct file_id *r);
+enum ndr_err_code ndr_pull_file_id(struct ndr_pull *ndr, int ndr_flags, struct file_id *r);
+void ndr_print_file_id(struct ndr_print *ndr, const char *name, const struct file_id *r);
 _PUBLIC_ void ndr_print_bool(struct ndr_print *ndr, const char *name, const bool b);
 _PUBLIC_ void ndr_print_sockaddr_storage(struct ndr_print *ndr, const char *name, const struct sockaddr_storage *ss);
 const char *ndr_errstr(enum ndr_err_code err);
@@ -3114,7 +3108,7 @@ struct packet_struct *receive_dgram_packet(int fd, int t,
 bool match_mailslot_name(struct packet_struct *p, const char *mailslot_name);
 int matching_len_bits(unsigned char *p1, unsigned char *p2, size_t len);
 void sort_query_replies(char *data, int n, struct in_addr ip);
-int name_mangle( char *In, char *Out, char name_type );
+char *name_mangle(TALLOC_CTX *mem_ctx, char *In, char name_type);
 int name_extract(char *buf,int ofs, fstring name);
 int name_len(char *s1);
 
@@ -3970,7 +3964,6 @@ const char *lp_afs_username_map(void);
 int lp_afs_token_lifetime(void);
 char *lp_log_nt_token_command(void);
 char *lp_username_map(void);
-bool lp_force_username_map(void);
 const char *lp_logon_script(void);
 const char *lp_logon_path(void);
 const char *lp_logon_drive(void);
@@ -4700,6 +4693,10 @@ NTSTATUS pdb_nds_init(void);
 
 NTSTATUS pdb_smbpasswd_init(void) ;
 
+/* The following definitions come from passdb/pdb_wbc_sam.c  */
+
+NTSTATUS pdb_wbc_sam_init(void);
+
 /* The following definitions come from passdb/pdb_tdb.c  */
 
 bool init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen);
@@ -5052,12 +5049,15 @@ WERROR init_registry_data(void);
 WERROR regdb_init(void);
 WERROR regdb_open( void );
 int regdb_close( void );
+WERROR regdb_transaction_start(void);
+WERROR regdb_transaction_commit(void);
+WERROR regdb_transaction_cancel(void);
 int regdb_get_seqnum(void);
-bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr);
-int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr);
+bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr);
+int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr);
 int regdb_fetch_values( const char* key, REGVAL_CTR *values );
 bool regdb_store_values( const char *key, REGVAL_CTR *values );
-bool regdb_subkeys_need_update(REGSUBKEY_CTR *subkeys);
+bool regdb_subkeys_need_update(struct regsubkey_ctr *subkeys);
 bool regdb_values_need_update(REGVAL_CTR *values);
 
 /* The following definitions come from registry/reg_backend_hkpt_params.c  */
@@ -5093,9 +5093,11 @@ void reghook_dump_cache( int debuglevel );
 
 /* The following definitions come from registry/reg_dispatcher.c  */
 
-bool store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys );
+bool store_reg_keys( REGISTRY_KEY *key, struct regsubkey_ctr *subkeys );
 bool store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val );
-int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr );
+WERROR create_reg_subkey(REGISTRY_KEY *key, const char *subkey);
+WERROR delete_reg_subkey(REGISTRY_KEY *key, const char *subkey);
+int fetch_reg_keys( REGISTRY_KEY *key, struct regsubkey_ctr *subkey_ctr );
 int fetch_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val );
 bool regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted,
                          const struct nt_user_token *token );
@@ -5103,7 +5105,7 @@ WERROR regkey_get_secdesc(TALLOC_CTX *mem_ctx, REGISTRY_KEY *key,
                          struct security_descriptor **psecdesc);
 WERROR regkey_set_secdesc(REGISTRY_KEY *key,
                          struct security_descriptor *psecdesc);
-bool reg_subkeys_need_update(REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys);
+bool reg_subkeys_need_update(REGISTRY_KEY *key, struct regsubkey_ctr *subkeys);
 bool reg_values_need_update(REGISTRY_KEY *key, REGVAL_CTR *values);
 
 /* The following definitions come from registry/reg_eventlog.c  */
@@ -5129,11 +5131,14 @@ WERROR registry_init_smbconf(const char *keyname);
 
 /* The following definitions come from registry/reg_objects.c  */
 
-WERROR regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname );
-int regsubkey_ctr_delkey( REGSUBKEY_CTR *ctr, const char *keyname );
-bool regsubkey_ctr_key_exists( REGSUBKEY_CTR *ctr, const char *keyname );
-int regsubkey_ctr_numkeys( REGSUBKEY_CTR *ctr );
-char* regsubkey_ctr_specific_key( REGSUBKEY_CTR *ctr, uint32 key_index );
+WERROR regsubkey_ctr_init(TALLOC_CTX *mem_ctx, struct regsubkey_ctr **ctr);
+WERROR regsubkey_ctr_set_seqnum(struct regsubkey_ctr *ctr, int seqnum);
+int regsubkey_ctr_get_seqnum(struct regsubkey_ctr *ctr);
+WERROR regsubkey_ctr_addkey( struct regsubkey_ctr *ctr, const char *keyname );
+WERROR regsubkey_ctr_delkey( struct regsubkey_ctr *ctr, const char *keyname );
+bool regsubkey_ctr_key_exists( struct regsubkey_ctr *ctr, const char *keyname );
+int regsubkey_ctr_numkeys( struct regsubkey_ctr *ctr );
+char* regsubkey_ctr_specific_key( struct regsubkey_ctr *ctr, uint32 key_index );
 int regval_ctr_numvals( REGVAL_CTR *ctr );
 REGISTRY_VALUE* dup_registry_value( REGISTRY_VALUE *val );
 void free_registry_value( REGISTRY_VALUE *val );
@@ -5472,40 +5477,49 @@ WERROR rpccli_spoolss_openprinter_ex(struct rpc_pipe_client *cli,
                                     const char *printername,
                                     uint32_t access_desired,
                                     struct policy_handle *handle);
+WERROR rpccli_spoolss_getprinterdriver2(struct rpc_pipe_client *cli,
+                                       TALLOC_CTX *mem_ctx,
+                                       struct policy_handle *handle,
+                                       const char *architecture,
+                                       uint32_t level,
+                                       uint32_t offered,
+                                       uint32_t client_major_version,
+                                       uint32_t client_minor_version,
+                                       union spoolss_DriverInfo *info,
+                                       uint32_t *server_major_version,
+                                       uint32_t *server_minor_version);
+WERROR rpccli_spoolss_addprinterex(struct rpc_pipe_client *cli,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct spoolss_SetPrinterInfoCtr *info_ctr);
+WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli,
+                                TALLOC_CTX *mem_ctx,
+                                struct policy_handle *handle,
+                                uint32_t level,
+                                uint32_t offered,
+                                union spoolss_PrinterInfo *info);
+WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli,
+                            TALLOC_CTX *mem_ctx,
+                            struct policy_handle *handle,
+                            uint32_t job_id,
+                            uint32_t level,
+                            uint32_t offered,
+                            union spoolss_JobInfo *info);
 WERROR rpccli_spoolss_enum_printers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 char *name, uint32 flags, uint32 level,
                                 uint32 *num_printers, PRINTER_INFO_CTR *ctr);
 WERROR rpccli_spoolss_enum_ports(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              uint32 level, uint32 *num_ports, PORT_INFO_CTR *ctr);
-WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                             POLICY_HND *pol, uint32 level, 
-                             PRINTER_INFO_CTR *ctr);
-WERROR rpccli_spoolss_setprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                             POLICY_HND *pol, uint32 level, 
-                             PRINTER_INFO_CTR *ctr, uint32 command);
-WERROR rpccli_spoolss_getprinterdriver(struct rpc_pipe_client *cli, 
-                                   TALLOC_CTX *mem_ctx, 
-                                   POLICY_HND *pol, uint32 level, 
-                                   const char *env, int version, PRINTER_DRIVER_CTR *ctr);
 WERROR rpccli_spoolss_enumprinterdrivers (struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx,
                                       uint32 level, const char *env,
                                       uint32 *num_drivers,
                                       PRINTER_DRIVER_CTR *ctr);
-WERROR rpccli_spoolss_addprinterdriver (struct rpc_pipe_client *cli, 
-                                    TALLOC_CTX *mem_ctx, uint32 level,
-                                    PRINTER_DRIVER_CTR *ctr);
-WERROR rpccli_spoolss_addprinterex (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                                uint32 level, PRINTER_INFO_CTR*ctr);
 WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             POLICY_HND *handle, int level, uint32 *num_forms,
                             FORM_1 **forms);
 WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                            POLICY_HND *hnd, uint32 level, uint32 firstjob, 
                            uint32 num_jobs, uint32 *returned, JOB_INFO_CTR *ctr);
-WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                         POLICY_HND *hnd, uint32 jobid, uint32 level,
-                         JOB_INFO_CTR *ctr);
 WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *hnd, const char *valuename, 
                                  REGISTRY_VALUE *value);
@@ -5523,17 +5537,6 @@ WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *me
                                  POLICY_HND *hnd, const char *keyname,
                                  uint16 **keylist, uint32 *len);
 
-/* The following definitions come from rpc_client/cli_spoolss_notify.c  */
-
-WERROR rpccli_spoolss_rrpcn(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
-                        POLICY_HND *pol, uint32 notify_data_len,
-                        SPOOL_NOTIFY_INFO_DATA *notify_data,
-                        uint32 change_low, uint32 change_high);
-WERROR rpccli_spoolss_rffpcnex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                           POLICY_HND *pol, uint32 flags, uint32 options,
-                           const char *localmachine, uint32 printerlocal,
-                           SPOOL_NOTIFY_OPTION *option);
-
 /* The following definitions come from rpc_client/init_spoolss.c  */
 
 bool init_systemtime(struct spoolss_Time *r,
@@ -5818,28 +5821,12 @@ bool sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int
 
 bool spoolss_io_system_time(const char *desc, prs_struct *ps, int depth, SYSTEMTIME *systime);
 bool make_systemtime(SYSTEMTIME *systime, struct tm *unixtime);
-bool smb_io_notify_info_data_strings(const char *desc,SPOOL_NOTIFY_INFO_DATA *data,
-                                     prs_struct *ps, int depth);
-bool spool_io_user_level_1( const char *desc, prs_struct *ps, int depth, SPOOL_USER_1 *q_u );
 bool spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE *devmode);
-bool make_spoolss_q_addprinterex( TALLOC_CTX *mem_ctx, SPOOL_Q_ADDPRINTEREX *q_u, 
-       const char *srv_name, const char* clientname, const char* user_name,
-       uint32 level, PRINTER_INFO_CTR *ctr);
-bool make_spoolss_printer_info_2(TALLOC_CTX *ctx, SPOOL_PRINTER_INFO_LEVEL_2 **spool_info2, 
-                               PRINTER_INFO_2 *info);
-bool make_spoolss_printer_info_3(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_3 **spool_info3, 
-                               PRINTER_INFO_3 *info);
-bool make_spoolss_printer_info_7(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_7 **spool_info7, 
-                               PRINTER_INFO_7 *info);
 bool make_spoolss_q_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u,
                                   const POLICY_HND *handle,
                                   const char *valuename, uint32 size);
 bool spoolss_io_q_getprinterdata(const char *desc, SPOOL_Q_GETPRINTERDATA *q_u, prs_struct *ps, int depth);
 bool spoolss_io_r_getprinterdata(const char *desc, SPOOL_R_GETPRINTERDATA *r_u, prs_struct *ps, int depth);
-bool spoolss_io_q_rffpcnex(const char *desc, SPOOL_Q_RFFPCNEX *q_u, prs_struct *ps, int depth);
-bool spoolss_io_r_rffpcnex(const char *desc, SPOOL_R_RFFPCNEX *r_u, prs_struct *ps, int depth);
-bool spoolss_io_q_rfnpcnex(const char *desc, SPOOL_Q_RFNPCNEX *q_u, prs_struct *ps, int depth);
-bool spoolss_io_r_rfnpcnex(const char *desc, SPOOL_R_RFNPCNEX *r_u, prs_struct *ps, int depth);
 bool smb_io_printer_info_0(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_0 *info, int depth);
 bool smb_io_printer_info_1(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_1 *info, int depth);
 bool smb_io_printer_info_2(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_2 *info, int depth);
@@ -5887,11 +5874,6 @@ uint32 spoolss_size_printprocdatatype_info_1(PRINTPROCDATATYPE_1 *info);
 uint32 spoolss_size_printer_enum_values(PRINTER_ENUM_VALUES *p);
 uint32 spoolss_size_printmonitor_info_1(PRINTMONITOR_1 *info);
 uint32 spoolss_size_printmonitor_info_2(PRINTMONITOR_2 *info);
-bool make_spoolss_q_getprinterdriver2(SPOOL_Q_GETPRINTERDRIVER2 *q_u, 
-                              const POLICY_HND *hnd,
-                              const fstring architecture,
-                              uint32 level, uint32 clientmajor, uint32 clientminor,
-                              RPC_BUFFER *buffer, uint32 offered);
 bool spoolss_io_q_getprinterdriver2(const char *desc, SPOOL_Q_GETPRINTERDRIVER2 *q_u, prs_struct *ps, int depth);
 bool spoolss_io_r_getprinterdriver2(const char *desc, SPOOL_R_GETPRINTERDRIVER2 *r_u, prs_struct *ps, int depth);
 bool make_spoolss_q_enumprinters(
@@ -5909,19 +5891,6 @@ bool spoolss_io_q_enumprinters(const char *desc, SPOOL_Q_ENUMPRINTERS *q_u, prs_
 bool spoolss_io_r_enumprinters(const char *desc, SPOOL_R_ENUMPRINTERS *r_u, prs_struct *ps, int depth);
 bool spoolss_io_r_getprinter(const char *desc, SPOOL_R_GETPRINTER *r_u, prs_struct *ps, int depth);
 bool spoolss_io_q_getprinter(const char *desc, SPOOL_Q_GETPRINTER *q_u, prs_struct *ps, int depth);
-bool make_spoolss_q_getprinter(
-       TALLOC_CTX *mem_ctx,
-       SPOOL_Q_GETPRINTER *q_u, 
-       const POLICY_HND *hnd, 
-       uint32 level, 
-       RPC_BUFFER *buffer, 
-       uint32 offered
-);
-bool make_spoolss_q_setprinter(TALLOC_CTX *mem_ctx, SPOOL_Q_SETPRINTER *q_u, 
-                               const POLICY_HND *hnd, uint32 level, PRINTER_INFO_CTR *info, 
-                               uint32 command);
-bool spoolss_io_r_setprinter(const char *desc, SPOOL_R_SETPRINTER *r_u, prs_struct *ps, int depth);
-bool spoolss_io_q_setprinter(const char *desc, SPOOL_Q_SETPRINTER *q_u, prs_struct *ps, int depth);
 bool spoolss_io_r_enumjobs(const char *desc, SPOOL_R_ENUMJOBS *r_u, prs_struct *ps, int depth);
 bool make_spoolss_q_enumjobs(SPOOL_Q_ENUMJOBS *q_u, const POLICY_HND *hnd,
                                uint32 firstjob,
@@ -5941,31 +5910,7 @@ bool spoolss_io_q_enumforms(const char *desc, SPOOL_Q_ENUMFORMS *q_u, prs_struct
 bool spoolss_io_r_enumforms(const char *desc, SPOOL_R_ENUMFORMS *r_u, prs_struct *ps, int depth);
 bool spoolss_io_r_enumports(const char *desc, SPOOL_R_ENUMPORTS *r_u, prs_struct *ps, int depth);
 bool spoolss_io_q_enumports(const char *desc, SPOOL_Q_ENUMPORTS *q_u, prs_struct *ps, int depth);
-bool spool_io_printer_info_level_1(const char *desc, SPOOL_PRINTER_INFO_LEVEL_1 *il, prs_struct *ps, int depth);
-bool spool_io_printer_info_level_3(const char *desc, SPOOL_PRINTER_INFO_LEVEL_3 *il, prs_struct *ps, int depth);
-bool spool_io_printer_info_level_2(const char *desc, SPOOL_PRINTER_INFO_LEVEL_2 *il, prs_struct *ps, int depth);
-bool spool_io_printer_info_level_7(const char *desc, SPOOL_PRINTER_INFO_LEVEL_7 *il, prs_struct *ps, int depth);
-bool spool_io_printer_info_level(const char *desc, SPOOL_PRINTER_INFO_LEVEL *il, prs_struct *ps, int depth);
-bool spoolss_io_q_addprinterex(const char *desc, SPOOL_Q_ADDPRINTEREX *q_u, prs_struct *ps, int depth);
-bool spoolss_io_r_addprinterex(const char *desc, SPOOL_R_ADDPRINTEREX *r_u, 
-                              prs_struct *ps, int depth);
-bool spool_io_printer_driver_info_level_3(const char *desc, SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 **q_u, 
-                                          prs_struct *ps, int depth);
-bool spool_io_printer_driver_info_level_6(const char *desc, SPOOL_PRINTER_DRIVER_INFO_LEVEL_6 **q_u, 
-                                          prs_struct *ps, int depth);
-bool smb_io_unibuffer(const char *desc, UNISTR2 *buffer, prs_struct *ps, int depth);
-bool spool_io_printer_driver_info_level(const char *desc, SPOOL_PRINTER_DRIVER_INFO_LEVEL *il, prs_struct *ps, int depth);
-bool make_spoolss_q_addprinterdriver(TALLOC_CTX *mem_ctx,
-                               SPOOL_Q_ADDPRINTERDRIVER *q_u, const char* srv_name, 
-                               uint32 level, PRINTER_DRIVER_CTR *info);
-bool make_spoolss_driver_info_3(TALLOC_CTX *mem_ctx,
-       SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 **spool_drv_info,
-                               DRIVER_INFO_3 *info3);
 bool make_spoolss_buffer5(TALLOC_CTX *mem_ctx, BUFFER5 *buf5, uint32 len, uint16 *src);
-bool spoolss_io_q_addprinterdriver(const char *desc, SPOOL_Q_ADDPRINTERDRIVER *q_u, prs_struct *ps, int depth);
-bool spoolss_io_r_addprinterdriver(const char *desc, SPOOL_R_ADDPRINTERDRIVER *q_u, prs_struct *ps, int depth);
-bool uni_2_asc_printer_info_2(const SPOOL_PRINTER_INFO_LEVEL_2 *uni,
-                              NT_PRINTER_INFO_LEVEL_2  *d);
 bool spoolss_io_r_enumprintprocessors(const char *desc, SPOOL_R_ENUMPRINTPROCESSORS *r_u, prs_struct *ps, int depth);
 bool spoolss_io_q_enumprintprocessors(const char *desc, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, prs_struct *ps, int depth);
 bool spoolss_io_r_enumprintprocdatatypes(const char *desc, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u, prs_struct *ps, int depth);
@@ -5995,11 +5940,6 @@ void free_printer_info_5(PRINTER_INFO_5 *printer);
 void free_printer_info_6(PRINTER_INFO_6 *printer);
 void free_printer_info_7(PRINTER_INFO_7 *printer);
 void free_job_info_2(JOB_INFO_2 *job);
-bool make_spoolss_q_reply_rrpcn(SPOOL_Q_REPLY_RRPCN *q_u, POLICY_HND *hnd,
-                               uint32 change_low, uint32 change_high,
-                               SPOOL_NOTIFY_INFO *info);
-bool spoolss_io_q_reply_rrpcn(const char *desc, SPOOL_Q_REPLY_RRPCN *q_u, prs_struct *ps, int depth);
-bool spoolss_io_r_reply_rrpcn(const char *desc, SPOOL_R_REPLY_RRPCN *r_u, prs_struct *ps, int depth);
 bool make_spoolss_q_enumprinterkey(SPOOL_Q_ENUMPRINTERKEY *q_u, 
                                   POLICY_HND *hnd, const char *key, 
                                   uint32 size);
@@ -6010,12 +5950,6 @@ bool spoolss_io_r_enumprinterdataex(const char *desc, SPOOL_R_ENUMPRINTERDATAEX
 bool make_spoolss_q_enumforms(SPOOL_Q_ENUMFORMS *q_u, POLICY_HND *handle, 
                              uint32 level, RPC_BUFFER *buffer,
                              uint32 offered);
-bool make_spoolss_q_getjob(SPOOL_Q_GETJOB *q_u, POLICY_HND *handle, 
-                          uint32 jobid, uint32 level, RPC_BUFFER *buffer,
-                          uint32 offered);
-bool make_spoolss_q_rffpcnex(SPOOL_Q_RFFPCNEX *q_u, POLICY_HND *handle,
-                            uint32 flags, uint32 options, const char *localmachine,
-                            uint32 printerlocal, SPOOL_NOTIFY_OPTION *option);
 
 /* The following definitions come from rpc_server/srv_eventlog_lib.c  */
 
@@ -6141,74 +6075,75 @@ bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
                                   uint32 type, uint8 *data, int real_len  );
 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u);
-WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u);
 void spoolss_notify_server_name(int snum,
-                                      SPOOL_NOTIFY_INFO_DATA *data,
+                                      struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       NT_PRINTER_INFO_LEVEL *printer,
                                       TALLOC_CTX *mem_ctx);
 void spoolss_notify_printer_name(int snum,
-                                       SPOOL_NOTIFY_INFO_DATA *data,
+                                       struct spoolss_Notify *data,
                                        print_queue_struct *queue,
                                        NT_PRINTER_INFO_LEVEL *printer,
                                        TALLOC_CTX *mem_ctx);
 void spoolss_notify_share_name(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx);
 void spoolss_notify_port_name(int snum,
-                                    SPOOL_NOTIFY_INFO_DATA *data,
+                                    struct spoolss_Notify *data,
                                     print_queue_struct *queue,
                                     NT_PRINTER_INFO_LEVEL *printer,
                                     TALLOC_CTX *mem_ctx);
 void spoolss_notify_driver_name(int snum,
-                                      SPOOL_NOTIFY_INFO_DATA *data,
+                                      struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       NT_PRINTER_INFO_LEVEL *printer,
                                       TALLOC_CTX *mem_ctx);
 void spoolss_notify_comment(int snum,
-                                  SPOOL_NOTIFY_INFO_DATA *data,
+                                  struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   NT_PRINTER_INFO_LEVEL *printer,
                                   TALLOC_CTX *mem_ctx);
 void spoolss_notify_location(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx);
 void spoolss_notify_sepfile(int snum,
-                                  SPOOL_NOTIFY_INFO_DATA *data,
+                                  struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   NT_PRINTER_INFO_LEVEL *printer,
                                   TALLOC_CTX *mem_ctx);
 void spoolss_notify_print_processor(int snum,
-                                          SPOOL_NOTIFY_INFO_DATA *data,
+                                          struct spoolss_Notify *data,
                                           print_queue_struct *queue,
                                           NT_PRINTER_INFO_LEVEL *printer,
                                           TALLOC_CTX *mem_ctx);
 void spoolss_notify_parameters(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx);
 void spoolss_notify_datatype(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx);
 void spoolss_notify_attributes(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx);
 void spoolss_notify_cjobs(int snum,
-                                SPOOL_NOTIFY_INFO_DATA *data,
+                                struct spoolss_Notify *data,
                                 print_queue_struct *queue,
                                 NT_PRINTER_INFO_LEVEL *printer,
                                 TALLOC_CTX *mem_ctx);
-void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id);
-WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u);
+void construct_info_data(struct spoolss_Notify *info_data,
+                        enum spoolss_NotifyType type,
+                        enum spoolss_Field field,
+                        int id);
 DEVICEMODE *construct_dev_mode(const char *servicename);
 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u);
 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u);
@@ -6263,7 +6198,6 @@ bool init_service_op_table( void );
 
 /* The following definitions come from rpcclient/cmd_spoolss.c  */
 
-void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch);
 
 /* The following definitions come from rpcclient/cmd_srvsvc.c  */
 
@@ -6587,6 +6521,7 @@ files_struct *file_find_fsp(files_struct *orig_fsp);
 files_struct *file_find_di_first(struct file_id id);
 files_struct *file_find_di_next(files_struct *start_fsp);
 files_struct *file_find_print(void);
+bool file_find_subpath(files_struct *dir_fsp);
 void file_sync_all(connection_struct *conn);
 void file_free(struct smb_request *req, files_struct *fsp);
 files_struct *file_fnum(uint16 fnum);
index 92448ae5437c9c467946cd8fa82729ea03041b69..5cafa0a5fbf7d4cadbabe0ce3ee5034985b0d28b 100644 (file)
@@ -26,5 +26,6 @@
 
 #define REG_VALUE_PREFIX    "SAMBA_REGVAL"
 #define REG_SECDESC_PREFIX  "SAMBA_SECDESC"
+#define REG_SORTED_SUBKEYS_PREFIX  "SAMBA_SORTED_SUBKEYS"
 
 #endif /* _REG_DB_H */
index d9159dd464ded4f62cf4a198ae1bd3536f3810a1..a03ac1bff461f0e4b45f4b42ee75ca50dbd2233a 100644 (file)
@@ -66,11 +66,7 @@ typedef struct {
 
 /* container for registry subkey names */
 
-typedef struct {
-       uint32          num_subkeys;
-       char            **subkeys;
-       int seqnum;
-} REGSUBKEY_CTR;
+struct regsubkey_ctr;
 
 /*
  *
@@ -132,9 +128,11 @@ typedef struct {
  
 typedef struct {
        /* functions for enumerating subkeys and values */      
-       int     (*fetch_subkeys)( const char *key, REGSUBKEY_CTR *subkeys);
+       int     (*fetch_subkeys)( const char *key, struct regsubkey_ctr *subkeys);
        int     (*fetch_values) ( const char *key, REGVAL_CTR *val );
-       bool    (*store_subkeys)( const char *key, REGSUBKEY_CTR *subkeys );
+       bool    (*store_subkeys)( const char *key, struct regsubkey_ctr *subkeys );
+       WERROR  (*create_subkey)(const char *key, const char *subkey);
+       WERROR  (*delete_subkey)(const char *key, const char *subkey);
        bool    (*store_values)( const char *key, REGVAL_CTR *val );
        bool    (*reg_access_check)( const char *keyname, uint32 requested,
                                     uint32 *granted,
@@ -143,7 +141,7 @@ typedef struct {
                              struct security_descriptor **psecdesc);
        WERROR (*set_secdesc)(const char *key,
                              struct security_descriptor *sec_desc);
-       bool    (*subkeys_need_update)(REGSUBKEY_CTR *subkeys);
+       bool    (*subkeys_need_update)(struct regsubkey_ctr *subkeys);
        bool    (*values_need_update)(REGVAL_CTR *values);
 } REGISTRY_OPS;
 
@@ -164,7 +162,7 @@ typedef struct _RegistryKey {
 
 struct registry_key {
        REGISTRY_KEY *key;
-       REGSUBKEY_CTR *subkeys;
+       struct regsubkey_ctr *subkeys;
        REGVAL_CTR *values;
        struct nt_user_token *token;
 };
index 63516a358dc3621cd8d3ab6c25ce3e3a7d6b5ad1..0e957d51e51be5c76cda083f9ab648161ad7f6ae 100644 (file)
@@ -214,7 +214,7 @@ int           regfio_close( REGF_FILE *r );
 REGF_NK_REC*  regfio_rootkey( REGF_FILE *file );
 REGF_NK_REC*  regfio_fetch_subkey( REGF_FILE *file, REGF_NK_REC *nk );
 REGF_NK_REC*  regfio_write_key ( REGF_FILE *file, const char *name,
-                                 REGVAL_CTR *values, REGSUBKEY_CTR *subkeys,
+                                 REGVAL_CTR *values, struct regsubkey_ctr *subkeys,
                                  SEC_DESC *sec_desc, REGF_NK_REC *parent );
 
 
index a1cfad90031c796a7c46b6611a9ba8f4414bff97..4bf0d9cb9d6d4c525a625acb44290035d0bf523b 100644 (file)
@@ -39,9 +39,6 @@
 #define        SEC_RIGHTS_RESET_PASSWD         SEC_RIGHTS_EXTENDED
 #define SEC_RIGHTS_FULL_CTRL           0xf01ff
 
-#define SEC_ACE_OBJECT_PRESENT           0x00000001 /* thanks for Jim McDonough <jmcd@us.ibm.com> */
-#define SEC_ACE_OBJECT_INHERITED_PRESENT 0x00000002
-
 /*
  * New Windows 2000 bits.
  */
index 99da007d32d98952d68c48bbc40d4409abded3e9..798bbf922c1e535ee312ade010673cd6d5013232 100644 (file)
 
 
 #define PRINTER_STATUS_OK               0x00000000
-#define JOB_ACCESS_READ                        0x00000020
-
-/* JOB status codes. */
-
-#define JOB_STATUS_QUEUED               0x0000
-#define JOB_STATUS_PAUSED              0x0001
-#define JOB_STATUS_ERROR               0x0002
-#define JOB_STATUS_DELETING            0x0004
-#define JOB_STATUS_SPOOLING            0x0008
-#define JOB_STATUS_PRINTING            0x0010
-#define JOB_STATUS_OFFLINE             0x0020
-#define JOB_STATUS_PAPEROUT            0x0040
-#define JOB_STATUS_PRINTED             0x0080
-#define JOB_STATUS_DELETED             0x0100
-#define JOB_STATUS_BLOCKED             0x0200
-#define JOB_STATUS_USER_INTERVENTION   0x0400
 
 /* Notify field types */
 
-#define NOTIFY_ONE_VALUE 1             /* Notify data is stored in value1 */
-#define NOTIFY_TWO_VALUE 2             /* Notify data is stored in value2 */
-#define NOTIFY_POINTER   3             /* Data is a pointer to a buffer */
-#define NOTIFY_STRING    4             /* Data is a pointer to a buffer w/length */
-#define NOTIFY_SECDESC   5             /* Data is a security descriptor */
-
 #define PRINTER_NOTIFY_TYPE 0x00
 #define JOB_NOTIFY_TYPE     0x01
-#define PRINT_TABLE_END     0xFF
-
-#define MAX_PRINTER_NOTIFY 26
-#define MAX_JOB_NOTIFY 24
-
-#define MAX_NOTIFY_TYPE_FOR_NOW 26
 
 #define PRINTER_NOTIFY_SERVER_NAME             0x00
 #define PRINTER_NOTIFY_PRINTER_NAME            0x01
 #define JOB_NOTIFY_TOTAL_BYTES                 0x16
 #define JOB_NOTIFY_BYTES_PRINTED               0x17
 
-#define PRINTER_NOTIFY_OPTIONS_REFRESH         0x01
-
 /*
  * Set of macros for flagging what changed in the PRINTER_INFO_2 struct
  * when sending messages to other smbd's
@@ -263,25 +233,6 @@ PRINTER_MESSAGE_INFO;
 #define DRIVER_MAX_VERSION             4
 
 
-/* this struct is undocumented */
-/* thanks to the ddk ... */
-typedef struct {
-       uint32 size;            /* length of user_name & client_name + 2? */
-       UNISTR2 *client_name;
-       UNISTR2 *user_name;
-       uint32 build;
-       uint32 major;
-       uint32 minor;
-       uint32 processor;
-} SPOOL_USER_1;
-
-typedef struct {
-       uint32 level;
-       union {
-               SPOOL_USER_1 *user1;
-       } user;
-} SPOOL_USER_CTR;
-
 /* 
  * Devicemode structure
  */
@@ -345,41 +296,6 @@ PRINTER_DEFAULT;
 
 /********************************************/
 
-typedef struct spool_notify_option_type
-{
-       uint16 type;
-       uint16 reserved0;
-       uint32 reserved1;
-       uint32 reserved2;
-       uint32 count;
-       uint32 fields_ptr;
-       uint32 count2;
-       uint16 fields[MAX_NOTIFY_TYPE_FOR_NOW];
-}
-SPOOL_NOTIFY_OPTION_TYPE;
-
-typedef struct spool_notify_option_type_ctr
-{
-       uint32 count;
-       SPOOL_NOTIFY_OPTION_TYPE *type;
-}
-SPOOL_NOTIFY_OPTION_TYPE_CTR;
-
-
-
-typedef struct s_header_type
-{
-       uint32 type;
-       union
-       {
-               uint32 value;
-               UNISTR string;
-       }
-       data;
-}
-HEADER_TYPE;
-
-
 typedef struct spool_q_getprinterdata
 {
        POLICY_HND handle;
@@ -398,86 +314,6 @@ typedef struct spool_r_getprinterdata
 }
 SPOOL_R_GETPRINTERDATA;
 
-typedef struct spool_notify_option
-{
-       uint32 version;
-       uint32 flags;
-       uint32 count;
-       uint32 option_type_ptr;
-       SPOOL_NOTIFY_OPTION_TYPE_CTR ctr;
-}
-SPOOL_NOTIFY_OPTION;
-
-typedef struct spool_notify_info_data
-{
-       uint16 type;
-       uint16 field;
-       uint32 reserved;
-       uint32 id;
-       union {
-               uint32 value[2];
-               struct {
-                       uint32 length;
-                       uint16 *string;
-               } data;
-               struct {
-                       uint32  size;
-                       SEC_DESC *desc;
-               } sd;
-       }
-       notify_data;
-       uint32 size;
-       uint32 enc_type;
-} SPOOL_NOTIFY_INFO_DATA;
-
-typedef struct spool_notify_info
-{
-       uint32 version;
-       uint32 flags;
-       uint32 count;
-       SPOOL_NOTIFY_INFO_DATA *data;
-}
-SPOOL_NOTIFY_INFO;
-
-/* If the struct name looks obscure, yes it is ! */
-/* RemoteFindFirstPrinterChangeNotificationEx query struct */
-typedef struct spoolss_q_rffpcnex
-{
-       POLICY_HND handle;
-       uint32 flags;
-       uint32 options;
-       uint32 localmachine_ptr;
-       UNISTR2 localmachine;
-       uint32 printerlocal;
-       uint32 option_ptr;
-       SPOOL_NOTIFY_OPTION *option;
-}
-SPOOL_Q_RFFPCNEX;
-
-typedef struct spool_r_rffpcnex
-{
-       WERROR status;
-}
-SPOOL_R_RFFPCNEX;
-
-/* Remote Find Next Printer Change Notify Ex */
-typedef struct spool_q_rfnpcnex
-{
-       POLICY_HND handle;
-       uint32 change;
-       uint32 option_ptr;
-       SPOOL_NOTIFY_OPTION *option;
-}
-SPOOL_Q_RFNPCNEX;
-
-typedef struct spool_r_rfnpcnex
-{
-       uint32 info_ptr;
-       SPOOL_NOTIFY_INFO info;
-       WERROR status;
-}
-SPOOL_R_RFNPCNEX;
-
 typedef struct printer_info_0
 {
        UNISTR printername;
@@ -592,11 +428,6 @@ typedef struct printer_info_6
 }
 PRINTER_INFO_6;
 
-#define SPOOL_DS_PUBLISH       1
-#define SPOOL_DS_UPDATE                2
-#define SPOOL_DS_UNPUBLISH     4
-#define SPOOL_DS_PENDING        0x80000000
-
 typedef struct printer_info_7
 {
        UNISTR guid; /* text form of printer guid */
@@ -976,208 +807,8 @@ typedef struct spool_r_enumforms
 }
 SPOOL_R_ENUMFORMS;
 
-typedef struct spool_printer_info_level_1
-{
-       uint32 flags;
-       uint32 description_ptr;
-       uint32 name_ptr;
-       uint32 comment_ptr;
-       UNISTR2 description;
-       UNISTR2 name;
-       UNISTR2 comment;        
-} SPOOL_PRINTER_INFO_LEVEL_1;
-
-typedef struct spool_printer_info_level_2
-{
-       uint32 servername_ptr;
-       uint32 printername_ptr;
-       uint32 sharename_ptr;
-       uint32 portname_ptr;
-       uint32 drivername_ptr;
-       uint32 comment_ptr;
-       uint32 location_ptr;
-       uint32 devmode_ptr;
-       uint32 sepfile_ptr;
-       uint32 printprocessor_ptr;
-       uint32 datatype_ptr;
-       uint32 parameters_ptr;
-       uint32 secdesc_ptr;
-       uint32 attributes;
-       uint32 priority;
-       uint32 default_priority;
-       uint32 starttime;
-       uint32 untiltime;
-       uint32 status;
-       uint32 cjobs;
-       uint32 averageppm;
-       UNISTR2 servername;
-       UNISTR2 printername;
-       UNISTR2 sharename;
-       UNISTR2 portname;
-       UNISTR2 drivername;
-       UNISTR2 comment;
-       UNISTR2 location;
-       UNISTR2 sepfile;
-       UNISTR2 printprocessor;
-       UNISTR2 datatype;
-       UNISTR2 parameters;
-}
-SPOOL_PRINTER_INFO_LEVEL_2;
-
-typedef struct spool_printer_info_level_3
-{
-       uint32 secdesc_ptr;
-}
-SPOOL_PRINTER_INFO_LEVEL_3;
-
-typedef struct spool_printer_info_level_7
-{
-       uint32 guid_ptr;
-       uint32 action;
-       UNISTR2 guid;
-}
-SPOOL_PRINTER_INFO_LEVEL_7;
-
-typedef struct spool_printer_info_level
-{
-       uint32 level;
-       uint32 info_ptr;
-       SPOOL_PRINTER_INFO_LEVEL_1 *info_1;
-       SPOOL_PRINTER_INFO_LEVEL_2 *info_2;
-       SPOOL_PRINTER_INFO_LEVEL_3 *info_3;
-       SPOOL_PRINTER_INFO_LEVEL_7 *info_7;
-}
-SPOOL_PRINTER_INFO_LEVEL;
-
-typedef struct spool_printer_driver_info_level_3
-{
-       uint32 cversion;
-       uint32 name_ptr;
-       uint32 environment_ptr;
-       uint32 driverpath_ptr;
-       uint32 datafile_ptr;
-       uint32 configfile_ptr;
-       uint32 helpfile_ptr;
-       uint32 monitorname_ptr;
-       uint32 defaultdatatype_ptr;
-       uint32 dependentfilessize;
-       uint32 dependentfiles_ptr;
-
-       UNISTR2 name;
-       UNISTR2 environment;
-       UNISTR2 driverpath;
-       UNISTR2 datafile;
-       UNISTR2 configfile;
-       UNISTR2 helpfile;
-       UNISTR2 monitorname;
-       UNISTR2 defaultdatatype;
-       BUFFER5 dependentfiles;
-
-}
-SPOOL_PRINTER_DRIVER_INFO_LEVEL_3;
-
-/* SPOOL_PRINTER_DRIVER_INFO_LEVEL_6 structure */
-typedef struct {
-       uint32 version;
-       uint32 name_ptr;
-       uint32 environment_ptr;
-       uint32 driverpath_ptr;
-       uint32 datafile_ptr;
-       uint32 configfile_ptr;
-       uint32 helpfile_ptr;
-       uint32 monitorname_ptr;
-       uint32 defaultdatatype_ptr;
-       uint32 dependentfiles_len;
-       uint32 dependentfiles_ptr;
-       uint32 previousnames_len;
-       uint32 previousnames_ptr;
-       NTTIME  driverdate;
-       uint64  driverversion;
-       uint32  dummy4;
-       uint32 mfgname_ptr;
-       uint32 oemurl_ptr;
-       uint32 hardwareid_ptr;
-       uint32 provider_ptr;
-       UNISTR2 name;
-       UNISTR2 environment;
-       UNISTR2 driverpath;
-       UNISTR2 datafile;
-       UNISTR2 configfile;
-       UNISTR2 helpfile;
-       UNISTR2 monitorname;
-       UNISTR2 defaultdatatype;
-       BUFFER5 dependentfiles;
-       BUFFER5 previousnames;
-       UNISTR2 mfgname;
-       UNISTR2 oemurl;
-       UNISTR2 hardwareid;
-       UNISTR2 provider;
-} SPOOL_PRINTER_DRIVER_INFO_LEVEL_6;
-
-
-typedef struct spool_printer_driver_info_level
-{
-       uint32 level;
-       uint32 ptr;
-       SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *info_3;
-       SPOOL_PRINTER_DRIVER_INFO_LEVEL_6 *info_6;
-}
-SPOOL_PRINTER_DRIVER_INFO_LEVEL;
-
-
-typedef struct spool_q_setprinter
-{
-       POLICY_HND handle;
-       uint32 level;
-       SPOOL_PRINTER_INFO_LEVEL info;
-       SEC_DESC_BUF *secdesc_ctr;
-       DEVMODE_CTR devmode_ctr;
-
-       uint32 command;
-
-}
-SPOOL_Q_SETPRINTER;
-
-typedef struct spool_r_setprinter
-{
-       WERROR status;
-}
-SPOOL_R_SETPRINTER;
-
-/********************************************/
-
-typedef struct {
-       UNISTR2 *server_name;
-       uint32 level;
-       SPOOL_PRINTER_INFO_LEVEL info;
-       DEVMODE_CTR devmode_ctr;
-       SEC_DESC_BUF *secdesc_ctr;
-       uint32 user_switch;
-       SPOOL_USER_CTR user_ctr;
-} SPOOL_Q_ADDPRINTEREX;
-
-typedef struct {
-       POLICY_HND handle;
-       WERROR status;
-} SPOOL_R_ADDPRINTEREX;
-
 /********************************************/
 
-typedef struct spool_q_addprinterdriver
-{
-       uint32 server_name_ptr;
-       UNISTR2 server_name;
-       uint32 level;
-       SPOOL_PRINTER_DRIVER_INFO_LEVEL info;
-}
-SPOOL_Q_ADDPRINTERDRIVER;
-
-typedef struct spool_r_addprinterdriver
-{
-       WERROR status;
-}
-SPOOL_R_ADDPRINTERDRIVER;
-
 typedef struct spool_q_enumprintprocessors
 {
        uint32 name_ptr;
@@ -1351,25 +982,6 @@ typedef struct spool_r_getjob
 }
 SPOOL_R_GETJOB;
 
-typedef struct spool_q_rrpcn
-{
-       POLICY_HND handle;
-       uint32 change_low;
-       uint32 change_high;
-       uint32 unknown0;
-       uint32 unknown1;
-       uint32 info_ptr;
-       SPOOL_NOTIFY_INFO info; 
-}
-SPOOL_Q_REPLY_RRPCN;
-
-typedef struct spool_r_rrpcn
-{
-       uint32 unknown0;
-       WERROR status;
-}
-SPOOL_R_REPLY_RRPCN;
-
 typedef struct spool_q_enumprinterkey
 {
        POLICY_HND handle;
index bef0fd177b3b5cfbad7e0d724e623f74078a0d07..f02088731d75b08e7352bda9c9a21e87220f8ea8 100644 (file)
@@ -758,18 +758,19 @@ Offset  Data                      length.
 16     uint32 private_options  4
 20     uint32 time sec         4
 24     uint32 time usec        4
-28     SMB_DEV_T dev           8 bytes.
-36     SMB_INO_T inode         8 bytes
-44     unsigned long file_id   4 bytes
-48     uint32 uid              4 bytes
-52     uint16 flags            2 bytes
-54
+28     uint64 dev              8 bytes
+36     uint64 inode            8 bytes
+44     uint64 extid            8 bytes
+52     unsigned long file_id   4 bytes
+56     uint32 uid              4 bytes
+60     uint16 flags            2 bytes
+62
 
 */
 #ifdef CLUSTER_SUPPORT
-#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 58
+#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 66
 #else
-#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 54
+#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 62
 #endif
 
 struct share_mode_lock {
@@ -1620,48 +1621,43 @@ enum acl_compatibility {ACL_COMPAT_AUTO, ACL_COMPAT_WINNT, ACL_COMPAT_WIN2K};
 #define BATCH_OPLOCK_TYPE(lck) ((lck) & (unsigned int)BATCH_OPLOCK)
 #define LEVEL_II_OPLOCK_TYPE(lck) ((lck) & ((unsigned int)LEVEL_II_OPLOCK|(unsigned int)FAKE_LEVEL_II_OPLOCK))
 
-struct inform_level2_message {
-       SMB_DEV_T dev;
-       SMB_INO_T inode;
-       uint16 mid;
-       unsigned long target_file_id;
-       unsigned long source_file_id;
-};
-
 /* kernel_oplock_message definition.
 
 struct kernel_oplock_message {
-       SMB_DEV_T dev;
-       SMB_INO_T inode;
+       uint64_t dev;
+       uint64_t inode;
+       unit64_t extid;
        unsigned long file_id;
 };
 
 Offset  Data                  length.
-0     SMB_DEV_T dev           8 bytes.
-8     SMB_INO_T inode         8 bytes
-16    unsigned long file_id   4 bytes
-20
+0     uint64_t dev            8 bytes
+8     uint64_t inode          8 bytes
+16    uint64_t extid          8 bytes
+24    unsigned long file_id   4 bytes
+28
 
 */
-#define MSG_SMB_KERNEL_BREAK_SIZE 20
+#define MSG_SMB_KERNEL_BREAK_SIZE 28
 
 /* file_renamed_message definition.
 
 struct file_renamed_message {
-       SMB_DEV_T dev;
-       SMB_INO_T inode;
+       uint64_t dev;
+       uint64_t inode;
        char names[1]; A variable area containing sharepath and filename.
 };
 
 Offset  Data                   length.
-0      SMB_DEV_T dev           8 bytes.
-8      SMB_INO_T inode         8 bytes
-16     char [] name            zero terminated namelen bytes
-minimum length == 18.
+0      uint64_t dev            8 bytes
+8      uint64_t inode          8 bytes
+16      unit64_t extid          8 bytes
+24     char [] name            zero terminated namelen bytes
+minimum length == 24.
 
 */
 
-#define MSG_FILE_RENAMED_MIN_SIZE 16
+#define MSG_FILE_RENAMED_MIN_SIZE 24
 
 /*
  * On the wire return values for oplock types.
index 101bec824536f21034194919414a9c802adc1358..4a2d832cc2cfa4c2a846fcfff5bbcc182512031b 100644 (file)
@@ -46,6 +46,7 @@ struct smbdb_ctx;
 struct smb_share_mode_entry {
        uint64_t dev;
        uint64_t ino;
+       uint64_t extid;
        uint32_t share_access;
        uint32_t access_mask;
        struct timeval open_time;
@@ -66,11 +67,13 @@ int smb_share_mode_db_close(struct smbdb_ctx *db_ctx);
 
 int smb_lock_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
-                               uint64_t ino);
+                               uint64_t ino,
+                               uint64_t extid);
 
 int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
-                               uint64_t ino);
+                               uint64_t ino,
+                               uint64_t extid);
 
 /*
  * Share mode database accessor functions.
@@ -79,23 +82,27 @@ int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx,
 int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino,
+                               uint64_t extid,
                                struct smb_share_mode_entry **pp_list,
                                unsigned char *p_delete_on_close);
 
 int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino,
+                               uint64_t extid,
                                const struct smb_share_mode_entry *set_entry,
                                const char *path);
 
 int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino,
+                               uint64_t extid,
                                const struct smb_share_mode_entry *set_entry);
 
 int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino,
+                               uint64_t extid,
                                const struct smb_share_mode_entry *set_entry,
                                const struct smb_share_mode_entry *new_entry);
 
index 131416b68520258e0525bffe5e8252f3aaae2d56..f9a0436546fa52355b43b427d529cec215114750 100644 (file)
@@ -75,6 +75,10 @@ enum profile_stats_values
 #define syscall_open_count __profile_stats_value(PR_VALUE_SYSCALL_OPEN, count)
 #define syscall_open_time __profile_stats_value(PR_VALUE_SYSCALL_OPEN, time)
 
+       PR_VALUE_SYSCALL_CREATEFILE,
+#define syscall_createfile_count __profile_stats_value(PR_VALUE_SYSCALL_CREATEFILE, count)
+#define syscall_createfile_time __profile_stats_value(PR_VALUE_SYSCALL_CREATEFILE, time)
+
        PR_VALUE_SYSCALL_CLOSE,
 #define syscall_close_count __profile_stats_value(PR_VALUE_SYSCALL_CLOSE, count)
 #define syscall_close_time __profile_stats_value(PR_VALUE_SYSCALL_CLOSE, time)
@@ -111,6 +115,10 @@ enum profile_stats_values
 #define syscall_rename_count __profile_stats_value(PR_VALUE_SYSCALL_RENAME, count)
 #define syscall_rename_time __profile_stats_value(PR_VALUE_SYSCALL_RENAME, time)
 
+       PR_VALUE_SYSCALL_RENAME_AT,
+#define syscall_rename_at_count __profile_stats_value(PR_VALUE_SYSCALL_RENAME_AT, count)
+#define syscall_rename_at_time __profile_stats_value(PR_VALUE_SYSCALL_RENAME_AT, time)
+
        PR_VALUE_SYSCALL_FSYNC,
 #define syscall_fsync_count __profile_stats_value(PR_VALUE_SYSCALL_FSYNC, count)
 #define syscall_fsync_time __profile_stats_value(PR_VALUE_SYSCALL_FSYNC, time)
@@ -215,6 +223,26 @@ enum profile_stats_values
 #define syscall_set_quota_count __profile_stats_value(PR_VALUE_SYSCALL_SET_QUOTA, count)
 #define syscall_set_quota_time __profile_stats_value(PR_VALUE_SYSCALL_SET_QUOTA, time)
 
+       PR_VALUE_SYSCALL_GET_SD,
+#define syscall_get_sd_count __profile_stats_value(PR_VALUE_SYSCALL_GET_SD, count)
+#define syscall_get_sd_time __profile_stats_value(PR_VALUE_SYSCALL_GET_SD, time)
+
+       PR_VALUE_SYSCALL_SET_SD,
+#define syscall_set_sd_count __profile_stats_value(PR_VALUE_SYSCALL_SET_SD, count)
+#define syscall_set_sd_time __profile_stats_value(PR_VALUE_SYSCALL_SET_SD, time)
+
+       PR_VALUE_SYSCALL_BRL_LOCK,
+#define syscall_brl_lock_count __profile_stats_value(PR_VALUE_SYSCALL_BRL_LOCK, count)
+#define syscall_brl_lock_time __profile_stats_value(PR_VALUE_SYSCALL_BRL_LOCK, time)
+
+       PR_VALUE_SYSCALL_BRL_UNLOCK,
+#define syscall_brl_unlock_count __profile_stats_value(PR_VALUE_SYSCALL_BRL_UNLOCK, count)
+#define syscall_brl_unlock_time __profile_stats_value(PR_VALUE_SYSCALL_BRL_UNLOCK, time)
+
+       PR_VALUE_SYSCALL_BRL_CANCEL,
+#define syscall_brl_cancel_count __profile_stats_value(PR_VALUE_SYSCALL_BRL_CANCEL, count)
+#define syscall_brl_cancel_time __profile_stats_value(PR_VALUE_SYSCALL_BRL_CANCEL, time)
+
 /* counters for individual SMB types */
        PR_VALUE_SMBMKDIR,
 #define SMBmkdir_count __profile_stats_value(PR_VALUE_SMBMKDIR, count)
index ffa1a95ed0281326a2c8fe3801cd33af73ae8cd2..0ee7f236b07346d780f1401cbcb3ad78b1cbf9da 100644 (file)
@@ -383,7 +383,8 @@ struct vfs_ops {
                                                          struct notify_event *ev),
                                         void *private_data, void *handle_p);
                int (*chflags)(struct vfs_handle_struct *handle, const char *path, unsigned int flags);
-               struct file_id (*file_id_create)(struct vfs_handle_struct *handle, SMB_DEV_T dev, SMB_INO_T inode);
+               struct file_id (*file_id_create)(struct vfs_handle_struct *handle,
+                                                const SMB_STRUCT_STAT *sbuf);
 
                NTSTATUS (*streaminfo)(struct vfs_handle_struct *handle,
                                       struct files_struct *fsp,
index 3af612375b0f3218b985f80083f7a997058c8b9f..7dacd2319ab980ee932ba2614582d6975178f535 100644 (file)
@@ -85,7 +85,7 @@
 #define SMB_VFS_REALPATH(conn, path, resolved_path) ((conn)->vfs.ops.realpath((conn)->vfs.handles.realpath, (path), (resolved_path)))
 #define SMB_VFS_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs.ops.notify_watch((conn)->vfs.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
 #define SMB_VFS_CHFLAGS(conn, path, flags) ((conn)->vfs.ops.chflags((conn)->vfs.handles.chflags, (path), (flags)))
-#define SMB_VFS_FILE_ID_CREATE(conn, dev, inode) ((conn)->vfs.ops.file_id_create((conn)->vfs.handles.file_id_create, (dev), (inode)))
+#define SMB_VFS_FILE_ID_CREATE(conn, sbuf) ((conn)->vfs.ops.file_id_create((conn)->vfs.handles.file_id_create, (sbuf)))
 #define SMB_VFS_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams) ((conn)->vfs.ops.streaminfo((conn)->vfs.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
 #define SMB_VFS_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name) ((conn)->vfs.ops.get_real_filename((conn)->vfs.handles.get_real_filename, (path), (name), (mem_ctx), (found_name)))
 #define SMB_VFS_BRL_LOCK_WINDOWS(conn, br_lck, plock, blocking_lock, blr) ((conn)->vfs.ops.brl_lock_windows((conn)->vfs.handles.brl_lock_windows, (br_lck), (plock), (blocking_lock), (blr)))
 #define SMB_VFS_OPAQUE_REALPATH(conn, path, resolved_path) ((conn)->vfs_opaque.ops.realpath((conn)->vfs_opaque.handles.realpath, (path), (resolved_path)))
 #define SMB_VFS_OPAQUE_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs_opaque.ops.notify_watch((conn)->vfs_opaque.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
 #define SMB_VFS_OPAQUE_CHFLAGS(conn, path, flags) ((conn)->vfs_opaque.ops.chflags((conn)->vfs_opaque.handles.chflags, (path), (flags)))
-#define SMB_VFS_OPAQUE_FILE_ID_CREATE(conn, dev, inode) ((conn)->vfs.ops_opaque.file_id_create((conn)->vfs_opaque.handles.file_id_create, (dev), (inode)))
+#define SMB_VFS_OPAQUE_FILE_ID_CREATE(conn, sbuf) ((conn)->vfs.ops_opaque.file_id_create((conn)->vfs_opaque.handles.file_id_create, (sbuf)))
 #define SMB_VFS_OPAQUE_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams) ((conn)->vfs_opaque.ops.streaminfo((conn)->vfs_opaque.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
 #define SMB_VFS_OPAQUE_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name) ((conn)->vfs_opaque.ops.get_real_filename((conn)->vfs_opaque.handles.get_real_filename, (path), (name), (mem_ctx), (found_name)))
 #define SMB_VFS_OPAQUE_BRL_LOCK_WINDOWS(conn, br_lck, plock, blocking_lock, blr) ((conn)->vfs_opaque.ops.brl_lock_windows((conn)->vfs_opaque.handles.brl_lock_windows, (br_lck), (plock), (blocking_lock), (blr)))
 #define SMB_VFS_NEXT_REALPATH(handle, path, resolved_path) ((handle)->vfs_next.ops.realpath((handle)->vfs_next.handles.realpath, (path), (resolved_path)))
 #define SMB_VFS_NEXT_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs_next.ops.notify_watch((conn)->vfs_next.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
 #define SMB_VFS_NEXT_CHFLAGS(handle, path, flags) ((handle)->vfs_next.ops.chflags((handle)->vfs_next.handles.chflags, (path), (flags)))
-#define SMB_VFS_NEXT_FILE_ID_CREATE(handle, dev, inode) ((handle)->vfs_next.ops.file_id_create((handle)->vfs_next.handles.file_id_create, (dev), (inode)))
+#define SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf) ((handle)->vfs_next.ops.file_id_create((handle)->vfs_next.handles.file_id_create, (sbuf)))
 #define SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, num_streams, streams) ((handle)->vfs_next.ops.streaminfo((handle)->vfs_next.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
 #define SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name, mem_ctx, found_name) ((handle)->vfs_next.ops.get_real_filename((handle)->vfs_next.handles.get_real_filename, (path), (name), (mem_ctx), (found_name)))
 #define SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock, blocking_lock, blr) ((handle)->vfs_next.ops.brl_lock_windows((handle)->vfs_next.handles.brl_lock_windows, (br_lck), (plock), (blocking_lock), (blr)))
index a57b7c97a5dc4690c53027e76d73b875852d1c6f..5e7ce6099fc486004d737304f01e784639379675 100644 (file)
@@ -42,6 +42,29 @@ static int dbwrap_fallback_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
        return 0;
 }
 
+/*
+ * Fall back using fetch if no genuine parse operation is provided
+ */
+
+static int dbwrap_fallback_parse_record(struct db_context *db, TDB_DATA key,
+                                       int (*parser)(TDB_DATA key,
+                                                     TDB_DATA data,
+                                                     void *private_data),
+                                       void *private_data)
+{
+       TDB_DATA data;
+       int res;
+
+       res = db->fetch(db, talloc_tos(), key, &data);
+       if (res != 0) {
+               return res;
+       }
+
+       res = parser(key, data, private_data);
+       TALLOC_FREE(data.dptr);
+       return res;
+}
+
 /**
  * open a database
  */
@@ -101,6 +124,9 @@ struct db_context *db_open(TALLOC_CTX *mem_ctx,
        if ((result != NULL) && (result->fetch == NULL)) {
                result->fetch = dbwrap_fallback_fetch;
        }
+       if ((result != NULL) && (result->parse_record == NULL)) {
+               result->parse_record = dbwrap_fallback_parse_record;
+       }
 
        return result;
 }
index b5eb1881d42169c6575d24327907761e04bc6ec6..c71e073b41e5110626ee942a12b7009c7d462951 100644 (file)
@@ -176,6 +176,17 @@ static int db_tdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
        return 0;
 }
 
+static int db_tdb_parse(struct db_context *db, TDB_DATA key,
+                       int (*parser)(TDB_DATA key, TDB_DATA data,
+                                     void *private_data),
+                       void *private_data)
+{
+       struct db_tdb_ctx *ctx = talloc_get_type_abort(
+               db->private_data, struct db_tdb_ctx);
+
+       return tdb_parse_record(ctx->wtdb->tdb, key, parser, private_data);
+}
+
 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
 {
        struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
@@ -351,6 +362,7 @@ struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
        result->fetch = db_tdb_fetch;
        result->traverse = db_tdb_traverse;
        result->traverse_read = db_tdb_traverse_read;
+       result->parse_record = db_tdb_parse;
        result->get_seqnum = db_tdb_get_seqnum;
        result->get_flags = db_tdb_get_flags;
        result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
index 636639c11d8e36c94b572b7b9e2d14bba4e9df77..fe1ae77eddfe111a1638c37cafa0cd4e66a44369 100644 (file)
@@ -155,13 +155,13 @@ void display_sec_ace_flags(uint8_t flags)
  ****************************************************************************/
 static void disp_sec_ace_object(struct security_ace_object *object)
 {
-       if (object->flags & SEC_ACE_OBJECT_PRESENT) {
-               printf("Object type: SEC_ACE_OBJECT_PRESENT\n");
+       if (object->flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
+               printf("Object type: SEC_ACE_OBJECT_TYPE_PRESENT\n");
                printf("Object GUID: %s\n", GUID_string(talloc_tos(),
                        &object->type.type));
        }
-       if (object->flags & SEC_ACE_OBJECT_INHERITED_PRESENT) {
-               printf("Object type: SEC_ACE_OBJECT_INHERITED_PRESENT\n");
+       if (object->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
+               printf("Object type: SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT\n");
                printf("Object GUID: %s\n", GUID_string(talloc_tos(), 
                        &object->inherited_type.inherited_type));
        }
index 44b45627577044be7faabacaed11a0315db23305..9e81a4779611c01ba6fc66582ae919189b50b703 100644 (file)
@@ -282,7 +282,7 @@ static void s3_event_debug(void *context, enum tevent_debug_level level,
                samba_level = 2;
                break;
        case TEVENT_DEBUG_TRACE:
-               samba_level = 5;
+               samba_level = 10;
                break;
 
        };
index a1530987f3b1ea4c4309d6a347a0a27f4c51a0a0..efd1dddfd40aaee3f9f048c7345fcf6a906807b0 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    Critical Fault handling
    Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Tim Prouty 2009
    
    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
@@ -87,6 +88,128 @@ void fault_setup(void (*fn)(void *))
 #endif
 }
 
+/**
+ * Build up the default corepath as "<logbase>/cores/<progname>"
+ */
+static char *get_default_corepath(const char *logbase, const char *progname)
+{
+       char *tmp_corepath;
+
+       /* Setup core dir in logbase. */
+       tmp_corepath = talloc_asprintf(NULL, "%s/cores", logbase);
+       if (!tmp_corepath)
+               return NULL;
+
+       if ((mkdir(tmp_corepath, 0700) == -1) && errno != EEXIST)
+               goto err_out;
+
+       if (chmod(tmp_corepath, 0700) == -1)
+               goto err_out;
+
+       talloc_free(tmp_corepath);
+
+       /* Setup progname-specific core subdir */
+       tmp_corepath = talloc_asprintf(NULL, "%s/cores/%s", logbase, progname);
+       if (!tmp_corepath)
+               return NULL;
+
+       if (mkdir(tmp_corepath, 0700) == -1 && errno != EEXIST)
+               goto err_out;
+
+       if (chown(tmp_corepath, getuid(), getgid()) == -1)
+               goto err_out;
+
+       if (chmod(tmp_corepath, 0700) == -1)
+               goto err_out;
+
+       return tmp_corepath;
+
+ err_out:
+       talloc_free(tmp_corepath);
+       return NULL;
+}
+
+/**
+ * Get the FreeBSD corepath.
+ *
+ * On FreeBSD the current working directory is ignored when creating a core
+ * file.  Instead the core directory is controlled via sysctl.  This consults
+ * the value of "kern.corefile" so the correct corepath can be printed out
+ * before dump_core() calls abort.
+ */
+#if (defined(FREEBSD) && defined(HAVE_SYSCTLBYNAME))
+static char *get_freebsd_corepath(void)
+{
+       char *tmp_corepath = NULL;
+       char *end = NULL;
+       size_t len = 128;
+       int ret;
+
+       /* Loop with increasing sizes so we don't allocate too much. */
+       do {
+               if (len > 1024)  {
+                       goto err_out;
+               }
+
+               tmp_corepath = (char *)talloc_realloc(NULL, tmp_corepath,
+                                                     char, len);
+               if (!tmp_corepath) {
+                       return NULL;
+               }
+
+               ret = sysctlbyname("kern.corefile", tmp_corepath, &len, NULL,
+                                  0);
+               if (ret == -1) {
+                       if (errno != ENOMEM) {
+                               DEBUG(0, ("sysctlbyname failed getting "
+                                         "kern.corefile %s\n",
+                                         strerror(errno)));
+                               goto err_out;
+                       }
+
+                       /* Not a large enough array, try a bigger one. */
+                       len = len << 1;
+               }
+       } while (ret == -1);
+
+       /* Strip off the common filename expansion */
+       if ((end = strrchr_m(tmp_corepath, '/'))) {
+               *end = '\0';
+       }
+
+       return tmp_corepath;
+
+ err_out:
+       if (tmp_corepath) {
+               talloc_free(tmp_corepath);
+       }
+       return NULL;
+}
+#endif
+
+/**
+ * Try getting system-specific corepath if one exists.
+ *
+ * If the system doesn't define a corepath, then the default is used.
+ */
+static char *get_corepath(const char *logbase, const char *progname)
+{
+       char *tmp_corepath = NULL;
+
+       /* @todo: Add support for the linux corepath. */
+#if (defined(FREEBSD) && defined(HAVE_SYSCTLBYNAME))
+       tmp_corepath = get_freebsd_corepath();
+#endif
+
+       /* If this has been set correctly, we're done. */
+       if (tmp_corepath) {
+               return tmp_corepath;
+       }
+
+       /* Fall back to the default. */
+       return get_default_corepath(logbase, progname);
+}
+
 /*******************************************************************
 make all the preparations to safely dump a core file
 ********************************************************************/
@@ -104,7 +227,7 @@ void dump_core_setup(const char *progname)
                        *end = '\0';
                }
        } else {
-               /* We will end up here is the log file is given on the command
+               /* We will end up here if the log file is given on the command
                 * line by the -l option but the "log file" option is not set
                 * in smb.conf.
                 */
@@ -115,50 +238,13 @@ void dump_core_setup(const char *progname)
 
        SMB_ASSERT(progname != NULL);
 
-       if (asprintf(&corepath, "%s/cores", logbase) < 0) {
-               SAFE_FREE(logbase);
-               return;
-       }
-       if (mkdir(corepath,0700) == -1) {
-               if (errno != EEXIST) {
-                       SAFE_FREE(corepath);
-                       SAFE_FREE(logbase);
-                       return;
-               }
-       }
-       if (chmod(corepath,0700) == -1) {
-               SAFE_FREE(corepath);
-               SAFE_FREE(logbase);
-               return;
-       }
-
-       SAFE_FREE(corepath);
-       if (asprintf(&corepath, "%s/cores/%s",
-                       logbase, progname) < 0) {
-               SAFE_FREE(logbase);
-               return;
-       }
-       if (mkdir(corepath,0700) == -1) {
-               if (errno != EEXIST) {
-                       SAFE_FREE(corepath);
-                       SAFE_FREE(logbase);
-                       return;
-               }
-       }
-
-       if (chown(corepath,getuid(),getgid()) == -1) {
-               SAFE_FREE(corepath);
-               SAFE_FREE(logbase);
-               return;
-       }
-       if (chmod(corepath,0700) == -1) {
-               SAFE_FREE(corepath);
-               SAFE_FREE(logbase);
-               return;
+       corepath = get_corepath(logbase, progname);
+       if (!corepath) {
+               DEBUG(0, ("Unable to setup corepath for %s: %s\n", progname,
+                         strerror(errno)));
+               goto out;
        }
 
-       SAFE_FREE(corepath);
-       SAFE_FREE(logbase);
 
 #ifdef HAVE_GETRLIMIT
 #ifdef RLIMIT_CORE
@@ -185,6 +271,8 @@ void dump_core_setup(const char *progname)
        /* FIXME: if we have a core-plus-pid facility, configurably set
         * this up here.
         */
+ out:
+       SAFE_FREE(logbase);
 }
 
  void dump_core(void)
index 0633d4b88d6e1136c609ac74de0eff5d70d48f2f..0902e3d2244207ad379292335b2a2b72218e34d6 100644 (file)
 
 #include "includes.h"
 
-/*
-  return a file_id which gives a unique ID for a file given the device and
-  inode numbers
- */
-struct file_id file_id_create_dev(SMB_DEV_T dev, SMB_INO_T inode)
-{
-       struct file_id key;
-       /* the ZERO_STRUCT ensures padding doesn't break using the key as a
-        * blob */
-       ZERO_STRUCT(key);
-       key.devid = dev;
-       key.inode = inode;
-       return key;
-}
-
 /*
   generate a file_id from a stat structure
  */
 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
 {
-       return SMB_VFS_FILE_ID_CREATE(conn, sbuf->st_dev, sbuf->st_ino);
+       return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
 }
 
 /*
@@ -49,7 +34,8 @@ struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_S
  */
 bool file_id_equal(const struct file_id *id1, const struct file_id *id2)
 {
-       return id1->inode == id2->inode && id1->devid == id2->devid;
+       return id1->inode == id2->inode && id1->devid == id2->devid &&
+           id1->extid == id2->extid;
 }
 
 /*
@@ -57,15 +43,17 @@ bool file_id_equal(const struct file_id *id1, const struct file_id *id2)
  */
 const char *file_id_string_tos(const struct file_id *id)
 {
-       char *result = talloc_asprintf(talloc_tos(), "%llx:%llx", 
+       char *result = talloc_asprintf(talloc_tos(), "%llx:%llx:%llx",
                                       (unsigned long long)id->devid, 
-                                      (unsigned long long)id->inode);
+                                      (unsigned long long)id->inode,
+                                      (unsigned long long)id->extid);
        SMB_ASSERT(result != NULL);
        return result;
 }
 
 /*
-  push a 16 byte version of a file id into a buffer
+  push a 16 byte version of a file id into a buffer.  This ignores the extid
+  and is needed when dev/inodes are stored in persistent storage (tdbs).
  */
 void push_file_id_16(char *buf, const struct file_id *id)
 {
@@ -76,13 +64,28 @@ void push_file_id_16(char *buf, const struct file_id *id)
 }
 
 /*
-  pul a 16 byte version of a file id from a buffer
+  push a 24 byte version of a file id into a buffer
+ */
+void push_file_id_24(char *buf, const struct file_id *id)
+{
+       SIVAL(buf,  0, id->devid&0xFFFFFFFF);
+       SIVAL(buf,  4, id->devid>>32);
+       SIVAL(buf,  8, id->inode&0xFFFFFFFF);
+       SIVAL(buf, 12, id->inode>>32);
+       SIVAL(buf, 16, id->extid&0xFFFFFFFF);
+       SIVAL(buf, 20, id->extid>>32);
+}
+
+/*
+  pull a 24 byte version of a file id from a buffer
  */
-void pull_file_id_16(char *buf, struct file_id *id)
+void pull_file_id_24(char *buf, struct file_id *id)
 {
        ZERO_STRUCTP(id);
        id->devid  = IVAL(buf,  0);
        id->devid |= ((uint64_t)IVAL(buf,4))<<32;
        id->inode  = IVAL(buf,  8);
        id->inode |= ((uint64_t)IVAL(buf,12))<<32;
+       id->extid  = IVAL(buf,  16);
+       id->extid |= ((uint64_t)IVAL(buf,20))<<32;
 }
index 2181ff014d26777d26a01e8ddb2b7f29e5cc91c0..98623d1985c8b70e69cdf235f9ae4854c27473ac 100644 (file)
 
 #include "includes.h"
 
-#if HAVE_LDAP
-
+#if defined(HAVE_LDAP) && defined(HAVE_LBER_LOG_PRINT_FN)
 static void samba_ldap_log_print_fn(LDAP_CONST char *data)
 {
        DEBUG(lp_ldap_debug_threshold(), ("[LDAP] %s", data));
 }
-
 #endif
 
 void init_ldap_debugging(void)
index 232bbca43c876d4b62766de73beef013bfb3fc64..a81c4ae82a2e3ba8150527af896ffa8e382d4ac9 100644 (file)
@@ -290,6 +290,32 @@ NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
+/*******************************************************************
+ Convert a secdesc_buf into a byte stream
+********************************************************************/
+
+NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
+                              struct sec_desc_buf *secdesc_buf,
+                              uint8_t **data, size_t *len)
+{
+       DATA_BLOB blob;
+       enum ndr_err_code ndr_err;
+
+       ndr_err = ndr_push_struct_blob(
+               &blob, mem_ctx, NULL, secdesc_buf,
+               (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
+
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
+                         ndr_errstr(ndr_err)));
+               return ndr_map_error2ntstatus(ndr_err);;
+       }
+
+       *data = blob.data;
+       *len = blob.length;
+       return NT_STATUS_OK;
+}
+
 /*******************************************************************
  Parse a byte stream into a secdesc
 ********************************************************************/
@@ -326,6 +352,43 @@ NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
        return NT_STATUS_OK;
 }
 
+/*******************************************************************
+ Parse a byte stream into a sec_desc_buf
+********************************************************************/
+
+NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
+                                struct sec_desc_buf **psecdesc_buf)
+{
+       DATA_BLOB blob;
+       enum ndr_err_code ndr_err;
+       struct sec_desc_buf *result;
+
+       if ((data == NULL) || (len == 0)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       result = TALLOC_ZERO_P(mem_ctx, struct sec_desc_buf);
+       if (result == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       blob = data_blob_const(data, len);
+
+       ndr_err = ndr_pull_struct_blob(
+               &blob, result, NULL, result,
+               (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
+
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
+                         ndr_errstr(ndr_err)));
+               TALLOC_FREE(result);
+               return ndr_map_error2ntstatus(ndr_err);;
+       }
+
+       *psecdesc_buf = result;
+       return NT_STATUS_OK;
+}
+
 /*******************************************************************
  Creates a SEC_DESC structure with typical defaults.
 ********************************************************************/
index e36fa8a2a12ce8d625fce911e5c7caa51322a392..5a5c0ead654516414db37f6ad1bd3de31f78784a 100644 (file)
@@ -23,7 +23,7 @@
 #define INCLUDES_VALNAME "includes"
 
 struct reg_private_data {
-       NT_USER_TOKEN *token;
+       struct registry_key *base_key;
        bool open;              /* did _we_ open the registry? */
 };
 
@@ -71,54 +71,6 @@ static bool smbconf_reg_valname_valid(const char *valname)
                lp_parameter_is_valid(valname));
 }
 
-/**
- * Open a registry key specified by "path"
- */
-static WERROR smbconf_reg_open_path(TALLOC_CTX *mem_ctx,
-                                   struct smbconf_ctx *ctx,
-                                   const char *path,
-                                   uint32 desired_access,
-                                   struct registry_key **key)
-{
-       WERROR werr = WERR_OK;
-
-       if (ctx == NULL) {
-               DEBUG(1, ("Error: configuration is not open!\n"));
-               werr = WERR_INVALID_PARAM;
-               goto done;
-       }
-
-       if (rpd(ctx)->token == NULL) {
-               DEBUG(1, ("Error: token missing from smbconf_ctx. "
-                         "was smbconf_init() called?\n"));
-               werr = WERR_INVALID_PARAM;
-               goto done;
-       }
-
-       werr = ctx->ops->open_conf(ctx);
-       if (!W_ERROR_IS_OK(werr)) {
-               DEBUG(1, ("Error opening the registry.\n"));
-               goto done;
-       }
-
-       if (path == NULL) {
-               DEBUG(1, ("Error: NULL path string given\n"));
-               werr = WERR_INVALID_PARAM;
-               goto done;
-       }
-
-       werr = reg_open_path(mem_ctx, path, desired_access, rpd(ctx)->token,
-                            key);
-
-       if (!W_ERROR_IS_OK(werr)) {
-               DEBUG(5, ("Error opening registry path '%s': %s\n",
-                         path, win_errstr(werr)));
-       }
-
-done:
-       return werr;
-}
-
 /**
  * Open a subkey of the base key (i.e a service)
  */
@@ -128,37 +80,12 @@ static WERROR smbconf_reg_open_service_key(TALLOC_CTX *mem_ctx,
                                           uint32 desired_access,
                                           struct registry_key **key)
 {
-       WERROR werr = WERR_OK;
-       char *path = NULL;
-
        if (servicename == NULL) {
-               path = talloc_strdup(mem_ctx, ctx->path);
-       } else {
-               path = talloc_asprintf(mem_ctx, "%s\\%s", ctx->path,
-                                      servicename);
-       }
-       if (path == NULL) {
-               werr = WERR_NOMEM;
-               goto done;
+               *key = rpd(ctx)->base_key;
+               return WERR_OK;
        }
-
-       werr = smbconf_reg_open_path(mem_ctx, ctx, path, desired_access, key);
-
-done:
-       talloc_free(path);
-       return werr;
-}
-
-/**
- * open the base key
- */
-static WERROR smbconf_reg_open_base_key(TALLOC_CTX *mem_ctx,
-                                       struct smbconf_ctx *ctx,
-                                       uint32 desired_access,
-                                       struct registry_key **key)
-{
-       return smbconf_reg_open_path(mem_ctx, ctx, ctx->path, desired_access,
-                                    key);
+       return reg_openkey(mem_ctx, rpd(ctx)->base_key, servicename,
+                          desired_access, key);
 }
 
 /**
@@ -189,7 +116,6 @@ static WERROR smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
                                             struct registry_key **newkey)
 {
        WERROR werr = WERR_OK;
-       struct registry_key *create_parent = NULL;
        TALLOC_CTX *create_ctx;
        enum winreg_CreateAction action = REG_ACTION_NONE;
 
@@ -198,13 +124,7 @@ static WERROR smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
         * and will be destroyed when leaving this function... */
        create_ctx = talloc_stackframe();
 
-       werr = smbconf_reg_open_base_key(create_ctx, ctx, REG_KEY_WRITE,
-                                        &create_parent);
-       if (!W_ERROR_IS_OK(werr)) {
-               goto done;
-       }
-
-       werr = reg_createkey(mem_ctx, create_parent, subkeyname,
+       werr = reg_createkey(mem_ctx, rpd(ctx)->base_key, subkeyname,
                             REG_KEY_WRITE, newkey, &action);
        if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
                DEBUG(10, ("Key '%s' already exists.\n", subkeyname));
@@ -215,7 +135,6 @@ static WERROR smbconf_reg_create_service_key(TALLOC_CTX *mem_ctx,
                         subkeyname, win_errstr(werr)));
        }
 
-done:
        talloc_free(create_ctx);
        return werr;
 }
@@ -608,6 +527,7 @@ done:
 static WERROR smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
 {
        WERROR werr = WERR_OK;
+       struct nt_user_token *token;
 
        if (path == NULL) {
                path = KEY_SMBCONF;
@@ -620,8 +540,7 @@ static WERROR smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
 
        ctx->data = TALLOC_ZERO_P(ctx, struct reg_private_data);
 
-       werr = ntstatus_to_werror(registry_create_admin_token(ctx,
-                                                       &(rpd(ctx)->token)));
+       werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
        if (!W_ERROR_IS_OK(werr)) {
                DEBUG(1, ("Error creating admin token\n"));
                goto done;
@@ -633,6 +552,19 @@ static WERROR smbconf_reg_init(struct smbconf_ctx *ctx, const char *path)
                goto done;
        }
 
+       werr = ctx->ops->open_conf(ctx);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, ("Error opening the registry.\n"));
+               goto done;
+       }
+
+       werr = reg_open_path(ctx, ctx->path,
+                            SEC_RIGHTS_ENUM_SUBKEYS | REG_KEY_WRITE,
+                            token, &rpd(ctx)->base_key);
+       if (!W_ERROR_IS_OK(werr)) {
+               goto done;
+       }
+
 done:
        return werr;
 }
@@ -723,6 +655,13 @@ static WERROR smbconf_reg_drop(struct smbconf_ctx *ctx)
        struct registry_key *new_key = NULL;
        TALLOC_CTX* mem_ctx = talloc_stackframe();
        enum winreg_CreateAction action;
+       struct nt_user_token *token;
+
+       werr = ntstatus_to_werror(registry_create_admin_token(ctx, &token));
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, ("Error creating admin token\n"));
+               goto done;
+       }
 
        path = talloc_strdup(mem_ctx, ctx->path);
        if (path == NULL) {
@@ -731,8 +670,8 @@ static WERROR smbconf_reg_drop(struct smbconf_ctx *ctx)
        }
        p = strrchr(path, '\\');
        *p = '\0';
-       werr = smbconf_reg_open_path(mem_ctx, ctx, path, REG_KEY_WRITE,
-                                    &parent_key);
+       werr = reg_open_path(mem_ctx, path, REG_KEY_WRITE, token,
+                            &parent_key);
 
        if (!W_ERROR_IS_OK(werr)) {
                goto done;
@@ -765,7 +704,6 @@ static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
        uint32_t added_count = 0;
        TALLOC_CTX *tmp_ctx = NULL;
        WERROR werr = WERR_OK;
-       struct registry_key *key = NULL;
        char *subkey_name = NULL;
        char **tmp_share_names = NULL;
 
@@ -777,13 +715,8 @@ static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
        tmp_ctx = talloc_stackframe();
 
        /* if there are values in the base key, return NULL as share name */
-       werr = smbconf_reg_open_base_key(tmp_ctx, ctx,
-                                        SEC_RIGHTS_ENUM_SUBKEYS, &key);
-       if (!W_ERROR_IS_OK(werr)) {
-               goto done;
-       }
 
-       if (smbconf_reg_key_has_values(key)) {
+       if (smbconf_reg_key_has_values(rpd(ctx)->base_key)) {
                werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
                                                   0, NULL);
                if (!W_ERROR_IS_OK(werr)) {
@@ -803,7 +736,8 @@ static WERROR smbconf_reg_get_share_names(struct smbconf_ctx *ctx,
        }
 
        for (count = 0;
-            werr = reg_enumkey(tmp_ctx, key, count, &subkey_name, NULL),
+            werr = reg_enumkey(tmp_ctx, rpd(ctx)->base_key, count,
+                               &subkey_name, NULL),
             W_ERROR_IS_OK(werr);
             count++)
        {
@@ -865,18 +799,16 @@ static WERROR smbconf_reg_create_share(struct smbconf_ctx *ctx,
                                       const char *servicename)
 {
        WERROR werr;
-       TALLOC_CTX *mem_ctx = talloc_stackframe();
        struct registry_key *key = NULL;
 
        if (servicename == NULL) {
-               werr = smbconf_reg_open_base_key(mem_ctx, ctx, REG_KEY_WRITE,
-                                                &key);
-       } else {
-               werr = smbconf_reg_create_service_key(mem_ctx, ctx,
-                                                     servicename, &key);
+               return WERR_OK;
        }
 
-       talloc_free(mem_ctx);
+       werr = smbconf_reg_create_service_key(talloc_tos(), ctx,
+                                             servicename, &key);
+
+       talloc_free(key);
        return werr;
 }
 
@@ -896,6 +828,9 @@ static WERROR smbconf_reg_get_share(struct smbconf_ctx *ctx,
        werr = smbconf_reg_open_service_key(tmp_ctx, ctx, servicename,
                                            REG_KEY_READ, &key);
        if (!W_ERROR_IS_OK(werr)) {
+               if (W_ERROR_EQUAL(werr, WERR_BADFILE)) {
+                       werr = WERR_NO_SUCH_SERVICE;
+               }
                goto done;
        }
 
@@ -934,21 +869,15 @@ static WERROR smbconf_reg_delete_share(struct smbconf_ctx *ctx,
                                       const char *servicename)
 {
        WERROR werr = WERR_OK;
-       struct registry_key *key = NULL;
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       werr = smbconf_reg_open_base_key(mem_ctx, ctx, REG_KEY_WRITE, &key);
-       if (!W_ERROR_IS_OK(werr)) {
-               goto done;
-       }
-
        if (servicename != NULL) {
-               werr = reg_deletekey_recursive(key, key, servicename);
+               werr = reg_deletekey_recursive(mem_ctx, rpd(ctx)->base_key,
+                                              servicename);
        } else {
-               werr = smbconf_reg_delete_values(key);
+               werr = smbconf_reg_delete_values(rpd(ctx)->base_key);
        }
 
-done:
        talloc_free(mem_ctx);
        return werr;
 }
@@ -1137,6 +1066,21 @@ done:
        return werr;
 }
 
+static WERROR smbconf_reg_transaction_start(struct smbconf_ctx *ctx)
+{
+       return regdb_transaction_start();
+}
+
+static WERROR smbconf_reg_transaction_commit(struct smbconf_ctx *ctx)
+{
+       return regdb_transaction_commit();
+}
+
+static WERROR smbconf_reg_transaction_cancel(struct smbconf_ctx *ctx)
+{
+       return regdb_transaction_cancel();
+}
+
 struct smbconf_ops smbconf_ops_reg = {
        .init                   = smbconf_reg_init,
        .shutdown               = smbconf_reg_shutdown,
@@ -1157,6 +1101,9 @@ struct smbconf_ops smbconf_ops_reg = {
        .get_includes           = smbconf_reg_get_includes,
        .set_includes           = smbconf_reg_set_includes,
        .delete_includes        = smbconf_reg_delete_includes,
+       .transaction_start      = smbconf_reg_transaction_start,
+       .transaction_commit     = smbconf_reg_transaction_commit,
+       .transaction_cancel     = smbconf_reg_transaction_cancel,
 };
 
 
index f0561a5081ef8d8812f315cf9d4faec764c84a8e..e24d35818c78944cd6f754f685868a037323ac37 100644 (file)
@@ -581,7 +581,9 @@ static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
 
 int smb_ldap_start_tls(LDAP *ldap_struct, int version)
 { 
+#ifdef LDAP_OPT_X_TLS
        int rc;
+#endif
        
        if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
                return LDAP_SUCCESS;
index ed66666ddb018d2ca84ce3d2f8de84a7f3ca176f..10b55f662d274f905f7105072c2a48bd28201bee 100644 (file)
@@ -1042,35 +1042,6 @@ static char **extract_args(TALLOC_CTX *mem_ctx, const char *command)
        return NULL;
 }
 
-/**************************************************************************
- Wrapper for fork. Ensures that mypid is reset. Used so we can write
- a sys_getpid() that only does a system call *once*.
-****************************************************************************/
-
-static pid_t mypid = (pid_t)-1;
-
-pid_t sys_fork(void)
-{
-       pid_t forkret = fork();
-
-       if (forkret == (pid_t)0) /* Child - reset mypid so sys_getpid does a system call. */
-               mypid = (pid_t) -1;
-
-       return forkret;
-}
-
-/**************************************************************************
- Wrapper for getpid. Ensures we only do a system call *once*.
-****************************************************************************/
-
-pid_t sys_getpid(void)
-{
-       if (mypid == (pid_t)-1)
-               mypid = getpid();
-
-       return mypid;
-}
-
 /**************************************************************************
  Wrapper for popen. Safer as it doesn't search a path.
  Modified from the glibc sources.
@@ -2008,7 +1979,6 @@ static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
 {
        ssize_t len = 0;
-       int stop = 0;
        DIR *dirp;
        struct dirent *de;
        int newfd = dup(attrdirfd);
@@ -2080,7 +2050,7 @@ static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
 {
        int filedes = openat(fildes, path, oflag, mode);
        if (filedes == -1) {
-               DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
+               DEBUG(10,("openat FAILED: fd: %d, path: %s, errno: %s\n",filedes,path,strerror(errno)));
                if (errno == EINVAL) {
                        errno = ENOTSUP;
                } else {
index 1f5dfe4d258b4928e55442fba286ec75c5e08450..092546e3eb53b6df077f8286c7f3e962bc0f72b4 100644 (file)
@@ -118,7 +118,8 @@ int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn)
 
        /* parent */
 
-       DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n",child_pid));
+       DEBUG(10, ("tdb_validate: fork succeeded, child PID = %u\n",
+               (unsigned int)child_pid));
 
        DEBUG(10, ("tdb_validate: waiting for child to finish...\n"));
        while  ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) {
@@ -134,7 +135,7 @@ int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn)
        }
        if (wait_pid != child_pid) {
                DEBUG(1, ("tdb_validate: waitpid returned pid %d, "
-                         "but %d was expected\n", wait_pid, child_pid));
+                         "but %u was expected\n", wait_pid, (unsigned int)child_pid));
                goto done;
        }
 
index 6079e710633bdce131bf1c1c58fda13aa203958e..89f7be8e6ce3e48b463b9b3fecd90f4d948b1c1b 100644 (file)
@@ -797,43 +797,6 @@ char *clean_name(TALLOC_CTX *ctx, const char *s)
        return unix_clean_name(ctx, str);
 }
 
-/*******************************************************************
- Close the low 3 fd's and open dev/null in their place.
-********************************************************************/
-
-void close_low_fds(bool stderr_too)
-{
-#ifndef VALGRIND
-       int fd;
-       int i;
-
-       close(0);
-       close(1);
-
-       if (stderr_too)
-               close(2);
-
-       /* try and use up these file descriptors, so silly
-               library routines writing to stdout etc won't cause havoc */
-       for (i=0;i<3;i++) {
-               if (i == 2 && !stderr_too)
-                       continue;
-
-               fd = sys_open("/dev/null",O_RDWR,0);
-               if (fd < 0)
-                       fd = sys_open("/dev/null",O_WRONLY,0);
-               if (fd < 0) {
-                       DEBUG(0,("Can't open /dev/null\n"));
-                       return;
-               }
-               if (fd != i) {
-                       DEBUG(0,("Didn't get file descriptor %d\n",i));
-                       return;
-               }
-       }
-#endif
-}
-
 /*******************************************************************
  Write data into an fd at a given offset. Ignore seek errors.
 ********************************************************************/
@@ -924,36 +887,6 @@ void smb_msleep(unsigned int t)
 #endif
 }
 
-/****************************************************************************
- Become a daemon, discarding the controlling terminal.
-****************************************************************************/
-
-void become_daemon(bool Fork, bool no_process_group)
-{
-       if (Fork) {
-               if (sys_fork()) {
-                       _exit(0);
-               }
-       }
-
-  /* detach from the terminal */
-#ifdef HAVE_SETSID
-       if (!no_process_group) setsid();
-#elif defined(TIOCNOTTY)
-       if (!no_process_group) {
-               int i = sys_open("/dev/tty", O_RDWR, 0);
-               if (i != -1) {
-                       ioctl(i, (int) TIOCNOTTY, (char *)0);      
-                       close(i);
-               }
-       }
-#endif /* HAVE_SETSID */
-
-       /* Close fd's 0,1,2. Needed if started by rsh */
-       close_low_fds(False);  /* Don't close stderr, let the debug system
-                                 attach it to the logfile */
-}
-
 bool reinit_after_fork(struct messaging_context *msg_ctx,
                       struct event_context *ev_ctx,
                       bool parent_longlived)
@@ -966,6 +899,13 @@ bool reinit_after_fork(struct messaging_context *msg_ctx,
         * numbers as each other */
        set_need_random_reseed();
 
+#ifdef WITH_MADVISE_PROTECTED
+       /* Protect parent process from being killed by kernel when system
+        * memory is low.  Child processes can still be killed */
+       if(!parent_longlived)
+               madvise(NULL,0,MADV_PROTECT);
+#endif
+
        /* tdb needs special fork handling */
        if (tdb_reopen_all(parent_longlived ? 1 : 0) == -1) {
                DEBUG(0,("tdb_reopen_all failed.\n"));
@@ -3205,102 +3145,3 @@ const char *strip_hostname(const char *s)
 
        return s;
 }
-
-struct read_pkt_state {
-       struct event_context *ev;
-       int fd;
-       uint8_t *buf;
-       ssize_t (*more)(uint8_t *buf, size_t buflen, void *priv);
-       void *priv;
-};
-
-static void read_pkt_done(struct async_req *subreq);
-
-struct async_req *read_pkt_send(TALLOC_CTX *mem_ctx,
-                               struct event_context *ev,
-                               int fd, size_t initial,
-                               ssize_t (*more)(uint8_t *buf, size_t buflen,
-                                               void *priv),
-                               void *priv)
-{
-       struct async_req *result, *subreq;
-       struct read_pkt_state *state;
-
-       if (!async_req_setup(mem_ctx, &result, &state,
-                            struct read_pkt_state)) {
-               return NULL;
-       }
-       state->ev = ev;
-       state->fd = fd;
-       state->more = more;
-
-       state->buf = talloc_array(state, uint8_t, initial);
-       if (state->buf == NULL) {
-               goto fail;
-       }
-       subreq = recvall_send(state, ev, fd, state->buf, initial, 0);
-       if (subreq == NULL) {
-               goto fail;
-       }
-       subreq->async.fn = read_pkt_done;
-       subreq->async.priv = result;
-       return result;
- fail:
-       TALLOC_FREE(result);
-       return NULL;
-}
-
-static void read_pkt_done(struct async_req *subreq)
-{
-       struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
-       struct read_pkt_state *state = talloc_get_type_abort(
-               req->private_data, struct read_pkt_state);
-       size_t current_size;
-       ssize_t received;
-       ssize_t more;
-       int err;
-
-       received = recvall_recv(subreq, &err);
-       TALLOC_FREE(subreq);
-       if (received == -1) {
-               async_req_error(req, err);
-               return;
-       }
-       current_size = talloc_get_size(state->buf);
-
-       more = state->more(state->buf, current_size, state->priv);
-       if (more < 0) {
-               async_req_error(req, EIO);
-               return;
-       }
-       if (more == 0) {
-               async_req_done(req);
-               return;
-       }
-       state->buf = TALLOC_REALLOC_ARRAY(state, state->buf, uint8_t,
-                                         current_size + more);
-       if (async_req_nomem(state->buf, req)) {
-               return;
-       }
-       subreq = recvall_send(state, state->ev, state->fd,
-                             state->buf + current_size, more, 0);
-       if (async_req_nomem(subreq, req)) {
-               return;
-       }
-       subreq->async.fn = read_pkt_done;
-       subreq->async.priv = req;
-}
-
-ssize_t read_pkt_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
-                     uint8_t **pbuf, int *perr)
-{
-       struct read_pkt_state *state = talloc_get_type_abort(
-               req->private_data, struct read_pkt_state);
-
-       if (async_req_is_errno(req, perr)) {
-               return -1;
-       }
-       *pbuf = talloc_move(mem_ctx, &state->buf);
-       return talloc_get_size(*pbuf);
-}
index c46aa2ac49b75c7b43f5fd66416473a894b2853f..6e75a67a85b41ac8f3a6c9f055aa80d19a62cdf2 100644 (file)
@@ -953,7 +953,7 @@ struct open_socket_out_state {
        int wait_nsec;
 };
 
-static void open_socket_out_connected(struct async_req *subreq);
+static void open_socket_out_connected(struct tevent_req *subreq);
 
 static int open_socket_out_state_destructor(struct open_socket_out_state *s)
 {
@@ -967,19 +967,20 @@ static int open_socket_out_state_destructor(struct open_socket_out_state *s)
  Create an outgoing socket. timeout is in milliseconds.
 **************************************************************************/
 
-struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
-                                      struct event_context *ev,
-                                      const struct sockaddr_storage *pss,
-                                      uint16_t port,
-                                      int timeout)
+struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
+                                       struct event_context *ev,
+                                       const struct sockaddr_storage *pss,
+                                       uint16_t port,
+                                       int timeout)
 {
        char addr[INET6_ADDRSTRLEN];
-       struct async_req *result, *subreq;
+       struct tevent_req *result, *subreq;
        struct open_socket_out_state *state;
        NTSTATUS status;
 
-       if (!async_req_setup(mem_ctx, &result, &state,
-                            struct open_socket_out_state)) {
+       result = tevent_req_create(mem_ctx, &state,
+                                  struct open_socket_out_state);
+       if (result == NULL) {
                return NULL;
        }
        state->ev = ev;
@@ -995,7 +996,8 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
        }
        talloc_set_destructor(state, open_socket_out_state_destructor);
 
-       if (!async_req_set_timeout(result, ev, timeval_set(0, timeout*1000))) {
+       if (!tevent_req_set_endtime(
+                   result, ev, timeval_current_ofs(0, timeout*1000))) {
                goto fail;
        }
 
@@ -1026,38 +1028,36 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
                                    (struct sockaddr *)&state->ss,
                                    state->salen);
        if ((subreq == NULL)
-           || !async_req_set_timeout(subreq, state->ev,
-                                     timeval_set(0, state->wait_nsec))) {
-               status = NT_STATUS_NO_MEMORY;
-               goto post_status;
+           || !tevent_req_set_endtime(
+                   subreq, state->ev,
+                   timeval_current_ofs(0, state->wait_nsec))) {
+               goto fail;
        }
        subreq->async.fn = open_socket_out_connected;
-       subreq->async.priv = result;
+       subreq->async.private_data = result;
        return result;
 
  post_status:
-       if (!async_post_ntstatus(result, ev, status)) {
-               goto fail;
-       }
-       return result;
+       tevent_req_nterror(result, status);
+       return tevent_req_post(result, ev);
  fail:
        TALLOC_FREE(result);
        return NULL;
 }
 
-static void open_socket_out_connected(struct async_req *subreq)
+static void open_socket_out_connected(struct tevent_req *subreq)
 {
-       struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
+       struct tevent_req *req = talloc_get_type_abort(
+               subreq->async.private_data, struct tevent_req);
        struct open_socket_out_state *state = talloc_get_type_abort(
-               req->private_data, struct open_socket_out_state);
-       int err;
+               req->private_state, struct open_socket_out_state);
+       int ret;
        int sys_errno;
 
-       err = async_connect_recv(subreq, &sys_errno);
+       ret = async_connect_recv(subreq, &sys_errno);
        TALLOC_FREE(subreq);
-       if (err == 0) {
-               async_req_done(req);
+       if (ret == 0) {
+               tevent_req_done(req);
                return;
        }
 
@@ -1080,38 +1080,39 @@ static void open_socket_out_connected(struct async_req *subreq)
                subreq = async_connect_send(state, state->ev, state->fd,
                                            (struct sockaddr *)&state->ss,
                                            state->salen);
-               if (async_req_nomem(subreq, req)) {
+               if (tevent_req_nomem(subreq, req)) {
                        return;
                }
-               if (!async_req_set_timeout(subreq, state->ev,
-                                          timeval_set(0, state->wait_nsec))) {
-                       async_req_error(req, ENOMEM);
+               if (!tevent_req_set_endtime(
+                           subreq, state->ev,
+                           timeval_current_ofs(0, state->wait_nsec))) {
+                       tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
                        return;
                }
                subreq->async.fn = open_socket_out_connected;
-               subreq->async.priv = req;
+               subreq->async.private_data = req;
                return;
        }
 
 #ifdef EISCONN
        if (sys_errno == EISCONN) {
-               async_req_done(req);
+               tevent_req_done(req);
                return;
        }
 #endif
 
        /* real error */
-       async_req_error(req, sys_errno);
+       tevent_req_nterror(req, map_nt_error_from_unix(sys_errno));
 }
 
-NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd)
+NTSTATUS open_socket_out_recv(struct tevent_req *req, int *pfd)
 {
        struct open_socket_out_state *state = talloc_get_type_abort(
-               req->private_data, struct open_socket_out_state);
-       int err;
+               req->private_state, struct open_socket_out_state);
+       NTSTATUS status;
 
-       if (async_req_is_errno(req, &err)) {
-               return map_nt_error_from_unix(err);
+       if (tevent_req_is_nterror(req, &status)) {
+               return status;
        }
        *pfd = state->fd;
        state->fd = -1;
@@ -1123,7 +1124,7 @@ NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
 {
        TALLOC_CTX *frame = talloc_stackframe();
        struct event_context *ev;
-       struct async_req *req;
+       struct tevent_req *req;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
 
        ev = event_context_init(frame);
@@ -1135,10 +1136,10 @@ NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
        if (req == NULL) {
                goto fail;
        }
-       while (req->state < ASYNC_REQ_DONE) {
-               event_loop_once(ev);
+       if (!tevent_req_poll(req, ev)) {
+               status = NT_STATUS_INTERNAL_ERROR;
+               goto fail;
        }
-
        status = open_socket_out_recv(req, pfd);
  fail:
        TALLOC_FREE(frame);
@@ -1154,7 +1155,7 @@ struct open_socket_out_defer_state {
 };
 
 static void open_socket_out_defer_waited(struct async_req *subreq);
-static void open_socket_out_defer_connected(struct async_req *subreq);
+static void open_socket_out_defer_connected(struct tevent_req *subreq);
 
 struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
                                             struct event_context *ev,
@@ -1201,6 +1202,7 @@ static void open_socket_out_defer_waited(struct async_req *subreq)
                subreq->async.priv, struct async_req);
        struct open_socket_out_defer_state *state = talloc_get_type_abort(
                req->private_data, struct open_socket_out_defer_state);
+       struct tevent_req *subreq2;
        bool ret;
 
        ret = async_wait_recv(subreq);
@@ -1210,19 +1212,19 @@ static void open_socket_out_defer_waited(struct async_req *subreq)
                return;
        }
 
-       subreq = open_socket_out_send(state, state->ev, &state->ss,
-                                     state->port, state->timeout);
-       if (async_req_nomem(subreq, req)) {
+       subreq2 = open_socket_out_send(state, state->ev, &state->ss,
+                                      state->port, state->timeout);
+       if (async_req_nomem(subreq2, req)) {
                return;
        }
-       subreq->async.fn = open_socket_out_defer_connected;
-       subreq->async.priv = req;
+       subreq2->async.fn = open_socket_out_defer_connected;
+       subreq2->async.private_data = req;
 }
 
-static void open_socket_out_defer_connected(struct async_req *subreq)
+static void open_socket_out_defer_connected(struct tevent_req *subreq)
 {
        struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
+               subreq->async.private_data, struct async_req);
        struct open_socket_out_defer_state *state = talloc_get_type_abort(
                req->private_data, struct open_socket_out_defer_state);
        NTSTATUS status;
index 9358061797abd36cf9f811eb1d5e45cc7703468f..b9ccb83e556134a2a54a717b7f3811d943c7870d 100644 (file)
@@ -35,118 +35,6 @@ const char toupper_ascii_fast_table[128] = {
        0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
 };
 
-/**
- * @file
- * @brief String utilities.
- **/
-
-static bool next_token_internal_talloc(TALLOC_CTX *ctx,
-                               const char **ptr,
-                                char **pp_buff,
-                                const char *sep,
-                                bool ltrim)
-{
-       char *s;
-       char *saved_s;
-       char *pbuf;
-       bool quoted;
-       size_t len=1;
-
-       *pp_buff = NULL;
-       if (!ptr) {
-               return(false);
-       }
-
-       s = (char *)*ptr;
-
-       /* default to simple separators */
-       if (!sep) {
-               sep = " \t\n\r";
-       }
-
-       /* find the first non sep char, if left-trimming is requested */
-       if (ltrim) {
-               while (*s && strchr_m(sep,*s)) {
-                       s++;
-               }
-       }
-
-       /* nothing left? */
-       if (!*s) {
-               return false;
-       }
-
-       /* When restarting we need to go from here. */
-       saved_s = s;
-
-       /* Work out the length needed. */
-       for (quoted = false; *s &&
-                       (quoted || !strchr_m(sep,*s)); s++) {
-               if (*s == '\"') {
-                       quoted = !quoted;
-               } else {
-                       len++;
-               }
-       }
-
-       /* We started with len = 1 so we have space for the nul. */
-       *pp_buff = TALLOC_ARRAY(ctx, char, len);
-       if (!*pp_buff) {
-               return false;
-       }
-
-       /* copy over the token */
-       pbuf = *pp_buff;
-       s = saved_s;
-       for (quoted = false; *s &&
-                       (quoted || !strchr_m(sep,*s)); s++) {
-               if ( *s == '\"' ) {
-                       quoted = !quoted;
-               } else {
-                       *pbuf++ = *s;
-               }
-       }
-
-       *ptr = (*s) ? s+1 : s;
-       *pbuf = 0;
-
-       return true;
-}
-
-#if 0
-/*
- * Get the next token from a string, return false if none found.  Handles
- * double-quotes.  This version trims leading separator characters before
- * looking for a token.
- */
-bool next_token(const char **ptr, char *buff, const char *sep, size_t bufsize)
-{
-       return next_token_internal(ptr, buff, sep, bufsize, true);
-}
-#endif
-
-bool next_token_talloc(TALLOC_CTX *ctx,
-                       const char **ptr,
-                       char **pp_buff,
-                       const char *sep)
-{
-       return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);
-}
-
-/*
- * Get the next token from a string, return false if none found.  Handles
- * double-quotes.  This version does not trim leading separator characters
- * before looking for a token.
- */
-
-bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
-                       const char **ptr,
-                       char **pp_buff,
-                       const char *sep)
-{
-       return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);
-}
-
 /**
  * Case insensitive string compararison.
  *
index 9bf6f29105f006a745b6c099cfc2e30610068a30..65906dcb91b52fefb9a8a7fe41f967f07586ca7e 100644 (file)
@@ -27,9 +27,7 @@
 
 struct req_read_state {
        struct winbindd_request *wb_req;
-       struct tevent_context *ev;
        size_t max_extra_data;
-       int fd;
 };
 
 bool async_req_is_wbcerr(struct async_req *req, wbcErr *pwbc_err)
@@ -83,145 +81,91 @@ wbcErr async_req_simple_recv_wbcerr(struct async_req *req)
        return WBC_ERR_SUCCESS;
 }
 
-static void wb_req_read_len(struct async_req *subreq);
-static void wb_req_read_main(struct async_req *subreq);
-static void wb_req_read_extra(struct async_req *subreq);
+static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data);
+static void wb_req_read_done(struct tevent_req *subreq);
 
 struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
                                   struct tevent_context *ev,
                                   int fd, size_t max_extra_data)
 {
-       struct async_req *result, *subreq;
+       struct async_req *result;
+       struct tevent_req *subreq;
        struct req_read_state *state;
 
        if (!async_req_setup(mem_ctx, &result, &state,
                             struct req_read_state)) {
                return NULL;
        }
-       state->fd = fd;
-       state->ev = ev;
        state->max_extra_data = max_extra_data;
-       state->wb_req = talloc(state, struct winbindd_request);
-       if (state->wb_req == NULL) {
-               goto nomem;
-       }
 
-       subreq = recvall_send(state, ev, state->fd, &(state->wb_req->length),
-                             sizeof(state->wb_req->length), 0);
+       subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state);
        if (subreq == NULL) {
                goto nomem;
        }
 
-       subreq->async.fn = wb_req_read_len;
-       subreq->async.priv = result;
+       subreq->async.fn = wb_req_read_done;
+       subreq->async.private_data = result;
        return result;
-
  nomem:
        TALLOC_FREE(result);
        return NULL;
 }
 
-static void wb_req_read_len(struct async_req *subreq)
+static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data)
 {
-       struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
        struct req_read_state *state = talloc_get_type_abort(
-               req->private_data, struct req_read_state);
-       int err;
-       ssize_t ret;
-
-       ret = recvall_recv(subreq, &err);
-       TALLOC_FREE(subreq);
-       if (ret < 0) {
-               async_req_error(req, map_wbc_err_from_errno(err));
-               return;
-       }
+               private_data, struct req_read_state);
+       struct winbindd_request *req = (struct winbindd_request *)buf;
 
-       if (state->wb_req->length != sizeof(struct winbindd_request)) {
-               DEBUG(0, ("wb_req_read_len: Invalid request size received: "
-                         "%d (expected %d)\n", (int)state->wb_req->length,
-                         (int)sizeof(struct winbindd_request)));
-               async_req_error(req, WBC_ERR_INVALID_RESPONSE);
-               return;
+       if (buflen == 4) {
+               if (req->length != sizeof(struct winbindd_request)) {
+                       DEBUG(0, ("wb_req_read_len: Invalid request size "
+                                 "received: %d (expected %d)\n",
+                                 (int)req->length,
+                                 (int)sizeof(struct winbindd_request)));
+                       return -1;
+               }
+               return sizeof(struct winbindd_request) - 4;
        }
 
-       subreq = recvall_send(
-               req, state->ev, state->fd, (uint32 *)(state->wb_req)+1,
-               sizeof(struct winbindd_request) - sizeof(uint32), 0);
-       if (async_req_nomem(subreq, req)) {
-               return;
+       if ((state->max_extra_data != 0)
+           && (req->extra_len > state->max_extra_data)) {
+               DEBUG(3, ("Got request with %d bytes extra data on "
+                         "unprivileged socket\n", (int)req->extra_len));
+               return -1;
        }
 
-       subreq->async.fn = wb_req_read_main;
-       subreq->async.priv = req;
+       return req->extra_len;
 }
 
-static void wb_req_read_main(struct async_req *subreq)
+static void wb_req_read_done(struct tevent_req *subreq)
 {
        struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
+               subreq->async.private_data, struct async_req);
        struct req_read_state *state = talloc_get_type_abort(
                req->private_data, struct req_read_state);
        int err;
        ssize_t ret;
+       uint8_t *buf;
 
-       ret = recvall_recv(subreq, &err);
+       ret = read_packet_recv(subreq, state, &buf, &err);
        TALLOC_FREE(subreq);
-       if (ret < 0) {
+       if (ret == -1) {
                async_req_error(req, map_wbc_err_from_errno(err));
                return;
        }
 
-       if ((state->max_extra_data != 0)
-           && (state->wb_req->extra_len > state->max_extra_data)) {
-               DEBUG(3, ("Got request with %d bytes extra data on "
-                         "unprivileged socket\n",
-                         (int)state->wb_req->extra_len));
-               async_req_error(req, WBC_ERR_INVALID_RESPONSE);
-               return;
-       }
-
-       if (state->wb_req->extra_len == 0) {
-               async_req_done(req);
-               return;
-       }
-
-       state->wb_req->extra_data.data = TALLOC_ARRAY(
-               state->wb_req, char, state->wb_req->extra_len + 1);
-       if (async_req_nomem(state->wb_req->extra_data.data, req)) {
-               return;
-       }
-
-       state->wb_req->extra_data.data[state->wb_req->extra_len] = 0;
-
-       subreq = recvall_send(
-               req, state->ev, state->fd, state->wb_req->extra_data.data,
-               state->wb_req->extra_len, 0);
-       if (async_req_nomem(subreq, req)) {
-               return;
-       }
-
-       subreq->async.fn = wb_req_read_extra;
-       subreq->async.priv = req;
-}
-
-static void wb_req_read_extra(struct async_req *subreq)
-{
-       struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
-       int err;
-       ssize_t ret;
+       state->wb_req = (struct winbindd_request *)buf;
 
-       ret = recvall_recv(subreq, &err);
-       TALLOC_FREE(subreq);
-       if (ret < 0) {
-               async_req_error(req, map_wbc_err_from_errno(err));
-               return;
+       if (state->wb_req->extra_len != 0) {
+               state->wb_req->extra_data.data =
+                       (char *)buf + sizeof(struct winbindd_request);
+       } else {
+               state->wb_req->extra_data.data = NULL;
        }
        async_req_done(req);
 }
 
-
 wbcErr wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
                        struct winbindd_request **preq)
 {
@@ -237,90 +181,60 @@ wbcErr wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
 }
 
 struct req_write_state {
-       struct winbindd_request *wb_req;
-       struct tevent_context *ev;
-       int fd;
+       struct iovec iov[2];
 };
 
-static void wb_req_write_main(struct async_req *subreq);
-static void wb_req_write_extra(struct async_req *subreq);
+static void wb_req_write_done(struct tevent_req *subreq);
 
 struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
                                    struct tevent_context *ev, int fd,
                                    struct winbindd_request *wb_req)
 {
-       struct async_req *result, *subreq;
+       struct async_req *result;
+       struct tevent_req *subreq;
        struct req_write_state *state;
+       int count = 1;
 
        if (!async_req_setup(mem_ctx, &result, &state,
                             struct req_write_state)) {
                return NULL;
        }
-       state->fd = fd;
-       state->ev = ev;
-       state->wb_req = wb_req;
 
-       subreq = sendall_send(state, state->ev, state->fd, state->wb_req,
-                             sizeof(struct winbindd_request), 0);
-       if (subreq == NULL) {
-               goto nomem;
+       state->iov[0].iov_base = wb_req;
+       state->iov[0].iov_len = sizeof(struct winbindd_request);
+
+       if (wb_req->extra_len != 0) {
+               state->iov[1].iov_base = wb_req->extra_data.data;
+               state->iov[1].iov_len = wb_req->extra_len;
+               count = 2;
        }
 
-       subreq->async.fn = wb_req_write_main;
-       subreq->async.priv = result;
+       subreq = writev_send(state, ev, fd, state->iov, count);
+       if (subreq == NULL) {
+               goto fail;
+       }
+       subreq->async.fn = wb_req_write_done;
+       subreq->async.private_data = result;
        return result;
 
nomem:
fail:
        TALLOC_FREE(result);
        return NULL;
 }
 
-static void wb_req_write_main(struct async_req *subreq)
-{
-       struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
-       struct req_write_state *state = talloc_get_type_abort(
-               req->private_data, struct req_write_state);
-       int err;
-       ssize_t ret;
-
-       ret = sendall_recv(subreq, &err);
-       TALLOC_FREE(subreq);
-       if (ret < 0) {
-               async_req_error(req, map_wbc_err_from_errno(err));
-               return;
-       }
-
-       if (state->wb_req->extra_len == 0) {
-               async_req_done(req);
-               return;
-       }
-
-       subreq = sendall_send(state, state->ev, state->fd,
-                             state->wb_req->extra_data.data,
-                             state->wb_req->extra_len, 0);
-       if (async_req_nomem(subreq, req)) {
-               return;
-       }
-
-       subreq->async.fn = wb_req_write_extra;
-       subreq->async.priv = req;
-}
-
-static void wb_req_write_extra(struct async_req *subreq)
+static void wb_req_write_done(struct tevent_req *subreq)
 {
        struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
+               subreq->async.private_data, struct async_req);
        int err;
        ssize_t ret;
 
-       ret = sendall_recv(subreq, &err);
+       ret = writev_recv(subreq, &err);
        TALLOC_FREE(subreq);
        if (ret < 0) {
                async_req_error(req, map_wbc_err_from_errno(err));
                return;
        }
-
        async_req_done(req);
 }
 
@@ -331,40 +245,29 @@ wbcErr wb_req_write_recv(struct async_req *req)
 
 struct resp_read_state {
        struct winbindd_response *wb_resp;
-       struct tevent_context *ev;
-       size_t max_extra_data;
-       int fd;
 };
 
-static void wb_resp_read_len(struct async_req *subreq);
-static void wb_resp_read_main(struct async_req *subreq);
-static void wb_resp_read_extra(struct async_req *subreq);
+static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data);
+static void wb_resp_read_done(struct tevent_req *subreq);
 
 struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
                                    struct tevent_context *ev, int fd)
 {
-       struct async_req *result, *subreq;
+       struct async_req *result;
+       struct tevent_req *subreq;
        struct resp_read_state *state;
 
        if (!async_req_setup(mem_ctx, &result, &state,
                             struct resp_read_state)) {
                return NULL;
        }
-       state->fd = fd;
-       state->ev = ev;
-       state->wb_resp = talloc(state, struct winbindd_response);
-       if (state->wb_resp == NULL) {
-               goto nomem;
-       }
 
-       subreq = recvall_send(state, ev, state->fd, &(state->wb_resp->length),
-                             sizeof(state->wb_resp->length), 0);
+       subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state);
        if (subreq == NULL) {
                goto nomem;
        }
-
-       subreq->async.fn = wb_resp_read_len;
-       subreq->async.priv = result;
+       subreq->async.fn = wb_resp_read_done;
+       subreq->async.private_data = result;
        return result;
 
  nomem:
@@ -372,100 +275,50 @@ struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
        return NULL;
 }
 
-static void wb_resp_read_len(struct async_req *subreq)
+static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data)
 {
-       struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
-       struct resp_read_state *state = talloc_get_type_abort(
-               req->private_data, struct resp_read_state);
-       int err;
-       ssize_t ret;
-
-       ret = recvall_recv(subreq, &err);
-       TALLOC_FREE(subreq);
-       if (ret < 0) {
-               async_req_error(req, map_wbc_err_from_errno(err));
-               return;
-       }
-
-       if (state->wb_resp->length < sizeof(struct winbindd_response)) {
-               DEBUG(0, ("wb_resp_read_len: Invalid response size received: "
-                         "%d (expected at least%d)\n",
-                         (int)state->wb_resp->length,
-                         (int)sizeof(struct winbindd_response)));
-               async_req_error(req, WBC_ERR_INVALID_RESPONSE);
-               return;
-       }
-
-       subreq = recvall_send(
-               req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1,
-               sizeof(struct winbindd_response) - sizeof(uint32), 0);
-       if (async_req_nomem(subreq, req)) {
-               return;
-       }
-
-       subreq->async.fn = wb_resp_read_main;
-       subreq->async.priv = req;
+       struct winbindd_response *resp = (struct winbindd_response *)buf;
+
+       if (buflen == 4) {
+               if (resp->length < sizeof(struct winbindd_response)) {
+                       DEBUG(0, ("wb_resp_read_len: Invalid response size "
+                                 "received: %d (expected at least%d)\n",
+                                 (int)resp->length,
+                                 (int)sizeof(struct winbindd_response)));
+                       return -1;
+               }
+       }
+       return resp->length - buflen;
 }
 
-static void wb_resp_read_main(struct async_req *subreq)
+static void wb_resp_read_done(struct tevent_req *subreq)
 {
        struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
+               subreq->async.private_data, struct async_req);
        struct resp_read_state *state = talloc_get_type_abort(
                req->private_data, struct resp_read_state);
+       uint8_t *buf;
        int err;
        ssize_t ret;
-       size_t extra_len;
 
-       ret = recvall_recv(subreq, &err);
+       ret = read_packet_recv(subreq, state, &buf, &err);
        TALLOC_FREE(subreq);
-       if (ret < 0) {
+       if (ret == -1) {
                async_req_error(req, map_wbc_err_from_errno(err));
                return;
        }
 
-       extra_len = state->wb_resp->length - sizeof(struct winbindd_response);
-       if (extra_len == 0) {
-               async_req_done(req);
-               return;
-       }
-
-       state->wb_resp->extra_data.data = TALLOC_ARRAY(
-               state->wb_resp, char, extra_len+1);
-       if (async_req_nomem(state->wb_resp->extra_data.data, req)) {
-               return;
-       }
-       ((char *)state->wb_resp->extra_data.data)[extra_len] = 0;
-
-       subreq = recvall_send(
-               req, state->ev, state->fd, state->wb_resp->extra_data.data,
-               extra_len, 0);
-       if (async_req_nomem(subreq, req)) {
-               return;
-       }
-
-       subreq->async.fn = wb_resp_read_extra;
-       subreq->async.priv = req;
-}
-
-static void wb_resp_read_extra(struct async_req *subreq)
-{
-       struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
-       int err;
-       ssize_t ret;
+       state->wb_resp = (struct winbindd_response *)buf;
 
-       ret = recvall_recv(subreq, &err);
-       TALLOC_FREE(subreq);
-       if (ret < 0) {
-               async_req_error(req, map_wbc_err_from_errno(err));
-               return;
+       if (state->wb_resp->length > sizeof(struct winbindd_response)) {
+               state->wb_resp->extra_data.data =
+                       (char *)buf + sizeof(struct winbindd_response);
+       } else {
+               state->wb_resp->extra_data.data = NULL;
        }
        async_req_done(req);
 }
 
-
 wbcErr wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
                         struct winbindd_response **presp)
 {
@@ -481,91 +334,61 @@ wbcErr wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
 }
 
 struct resp_write_state {
-       struct winbindd_response *wb_resp;
-       struct tevent_context *ev;
-       int fd;
+       struct iovec iov[2];
 };
 
-static void wb_resp_write_main(struct async_req *subreq);
-static void wb_resp_write_extra(struct async_req *subreq);
+static void wb_resp_write_done(struct tevent_req *subreq);
 
 struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
                                    struct tevent_context *ev, int fd,
                                    struct winbindd_response *wb_resp)
 {
-       struct async_req *result, *subreq;
+       struct async_req *result;
+       struct tevent_req *subreq;
        struct resp_write_state *state;
+       int count = 1;
 
        if (!async_req_setup(mem_ctx, &result, &state,
                             struct resp_write_state)) {
                return NULL;
        }
-       state->fd = fd;
-       state->ev = ev;
-       state->wb_resp = wb_resp;
 
-       subreq = sendall_send(state, state->ev, state->fd, state->wb_resp,
-                             sizeof(struct winbindd_response), 0);
-       if (subreq == NULL) {
-               goto nomem;
+       state->iov[0].iov_base = wb_resp;
+       state->iov[0].iov_len = sizeof(struct winbindd_response);
+
+       if (wb_resp->length > sizeof(struct winbindd_response)) {
+               state->iov[1].iov_base = wb_resp->extra_data.data;
+               state->iov[1].iov_len =
+                       wb_resp->length - sizeof(struct winbindd_response);
+               count = 2;
        }
 
-       subreq->async.fn = wb_resp_write_main;
-       subreq->async.priv = result;
+       subreq = writev_send(state, ev, fd, state->iov, count);
+       if (subreq == NULL) {
+               goto fail;
+       }
+       subreq->async.fn = wb_resp_write_done;
+       subreq->async.private_data = result;
        return result;
 
nomem:
fail:
        TALLOC_FREE(result);
        return NULL;
 }
 
-static void wb_resp_write_main(struct async_req *subreq)
+static void wb_resp_write_done(struct tevent_req *subreq)
 {
        struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
-       struct resp_write_state *state = talloc_get_type_abort(
-               req->private_data, struct resp_write_state);
+               subreq->async.private_data, struct async_req);
        int err;
        ssize_t ret;
 
-       ret = sendall_recv(subreq, &err);
+       ret = writev_recv(subreq, &err);
        TALLOC_FREE(subreq);
        if (ret < 0) {
                async_req_error(req, map_wbc_err_from_errno(err));
                return;
        }
-
-       if (state->wb_resp->length == sizeof(struct winbindd_response)) {
-               async_req_done(req);
-               return;
-       }
-
-       subreq = sendall_send(
-               state, state->ev, state->fd,
-               state->wb_resp->extra_data.data,
-               state->wb_resp->length - sizeof(struct winbindd_response), 0);
-       if (async_req_nomem(subreq, req)) {
-               return;
-       }
-
-       subreq->async.fn = wb_resp_write_extra;
-       subreq->async.priv = req;
-}
-
-static void wb_resp_write_extra(struct async_req *subreq)
-{
-       struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
-       int err;
-       ssize_t ret;
-
-       ret = sendall_recv(subreq, &err);
-       TALLOC_FREE(subreq);
-       if (err < 0) {
-               async_req_error(req, map_wbc_err_from_errno(err));
-               return;
-       }
-
        async_req_done(req);
 }
 
index 4d3a6095301dba783ef07c25d9c9091346337c08..b8d55a944a479edf92aaf295c8c02fff2a892be5 100644 (file)
@@ -147,17 +147,30 @@ struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx)
        return result;
 }
 
+struct wb_connect_state {
+       int dummy;
+};
+
+static void wbc_connect_connected(struct tevent_req *subreq);
+
 static struct async_req *wb_connect_send(TALLOC_CTX *mem_ctx,
-                                        struct tevent_context *ev,
-                                        struct wb_context *wb_ctx,
-                                        const char *dir)
+                                         struct tevent_context *ev,
+                                         struct wb_context *wb_ctx,
+                                         const char *dir)
 {
-       struct async_req *req;
+       struct async_req *result;
+       struct tevent_req *subreq;
+       struct wb_connect_state *state;
        struct sockaddr_un sunaddr;
        struct stat st;
        char *path = NULL;
        wbcErr wbc_err;
 
+       if (!async_req_setup(mem_ctx, &result, &state,
+                            struct wb_connect_state)) {
+               return NULL;
+       }
+
        if (wb_ctx->fd != -1) {
                close(wb_ctx->fd);
                wb_ctx->fd = -1;
@@ -205,33 +218,46 @@ static struct async_req *wb_connect_send(TALLOC_CTX *mem_ctx,
                goto post_status;
        }
 
-       req = async_connect_send(mem_ctx, ev, wb_ctx->fd,
-                                (struct sockaddr *)&sunaddr,
-                                sizeof(sunaddr));
-       if (req == NULL) {
+       subreq = async_connect_send(mem_ctx, ev, wb_ctx->fd,
+                                   (struct sockaddr *)&sunaddr,
+                                   sizeof(sunaddr));
+       if (subreq == NULL) {
                goto nomem;
        }
-       if (!async_req_set_timeout(req, ev, timeval_set(30, 0))) {
-               TALLOC_FREE(req);
+       subreq->async.fn = wbc_connect_connected;
+       subreq->async.private_data = result;
+
+       if (!tevent_req_set_endtime(subreq, ev, timeval_current_ofs(30, 0))) {
                goto nomem;
        }
 
-       return req;
+       return result;
 
  nomem:
        wbc_err = WBC_ERR_NO_MEMORY;
  post_status:
-       req = async_req_new(mem_ctx);
-       if (req == NULL) {
-               return NULL;
-       }
-       if (async_post_error(req, ev, wbc_err)) {
-               return req;
+       if (async_post_error(result, ev, wbc_err)) {
+               return result;
        }
-       TALLOC_FREE(req);
+       TALLOC_FREE(result);
        return NULL;
 }
 
+static void wbc_connect_connected(struct tevent_req *subreq)
+{
+       struct async_req *req = talloc_get_type_abort(
+               subreq->async.private_data, struct async_req);
+       int res, err;
+
+       res = async_connect_recv(subreq, &err);
+       TALLOC_FREE(subreq);
+       if (res == -1) {
+               async_req_error(req, map_wbc_err_from_errno(err));
+               return;
+       }
+       async_req_done(req);
+}
+
 static wbcErr wb_connect_recv(struct async_req *req)
 {
        return async_req_simple_recv_wbcerr(req);
index 42662a224b0259de41692e0bd9ae5c0d0054f059..57a9b6a0020d6c74ef4690c64b1ccb26a2300d2a 100644 (file)
 #include <krb5.h>
 #endif
 
-#if HAVE_GSSAPI_H
-#include <gssapi.h>
-#elif HAVE_GSSAPI_GSSAPI_H
+#if HAVE_GSSAPI_GSSAPI_H
 #include <gssapi/gssapi.h>
 #elif HAVE_GSSAPI_GSSAPI_GENERIC_H
 #include <gssapi/gssapi_generic.h>
+#elif HAVE_GSSAPI_H
+#include <gssapi.h>
 #endif
 
 #if defined(HAVE_GSSAPI_H) || defined(HAVE_GSSAPI_GSSAPI_H) || defined(HAVE_GSSAPI_GSSAPI_GENERIC_H)
index a5e04a4a6c49e3b72e62ea80bb97bc17175f8324..3bf0b6f7a7d9cff1926048510e35216fa392a15e 100644 (file)
@@ -112,15 +112,15 @@ static void ads_disp_sec_ace_object(ADS_STRUCT *ads,
                                    TALLOC_CTX *mem_ctx, 
                                    struct security_ace_object *object)
 {
-       if (object->flags & SEC_ACE_OBJECT_PRESENT) {
-               printf("Object type: SEC_ACE_OBJECT_PRESENT\n");
+       if (object->flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
+               printf("Object type: SEC_ACE_OBJECT_TYPE_PRESENT\n");
                printf("Object GUID: %s (%s)\n", GUID_string(mem_ctx, 
                        &object->type.type), 
                        ads_interprete_guid_from_object(ads, mem_ctx, 
                                &object->type.type));
        }
-       if (object->flags & SEC_ACE_OBJECT_INHERITED_PRESENT) {
-               printf("Object type: SEC_ACE_OBJECT_INHERITED_PRESENT\n");
+       if (object->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
+               printf("Object type: SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT\n");
                printf("Object GUID: %s (%s)\n", GUID_string(mem_ctx,
                        &object->inherited_type.inherited_type),
                        ads_interprete_guid_from_object(ads, mem_ctx, 
index 3d385dec1407cde1bb09e5496c7f38f15cd55015..9367bcae9c24b644d737dd169c32b25476fe5830 100644 (file)
@@ -691,7 +691,7 @@ static WERROR gp_reg_generate_sd(TALLOC_CTX *mem_ctx,
        SEC_ACE ace[6];
        uint32_t mask;
 
-       SEC_ACL *acl = NULL;
+       SEC_ACL *theacl = NULL;
 
        uint8_t inherit_flags;
 
@@ -735,15 +735,15 @@ static WERROR gp_reg_generate_sd(TALLOC_CTX *mem_ctx,
                     SEC_ACE_TYPE_ACCESS_ALLOWED,
                     mask, inherit_flags);
 
-       acl = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 6, ace);
-       W_ERROR_HAVE_NO_MEMORY(acl);
+       theacl = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 6, ace);
+       W_ERROR_HAVE_NO_MEMORY(theacl);
 
        *sd = make_sec_desc(mem_ctx, SEC_DESC_REVISION,
                            SEC_DESC_SELF_RELATIVE |
                            SEC_DESC_DACL_AUTO_INHERITED | /* really ? */
                            SEC_DESC_DACL_AUTO_INHERIT_REQ, /* really ? */
                            NULL, NULL, NULL,
-                           acl, sd_size);
+                           theacl, sd_size);
        W_ERROR_HAVE_NO_MEMORY(*sd);
 
        return WERR_OK;
index 42ab72a99bb3d59fc865957049da8e127873f874..c72bb2673240535461dfb7023eb4da3e7f1f49cc 100644 (file)
@@ -38,12 +38,12 @@ static bool gpo_sd_check_agp_object_guid(const struct security_ace_object *objec
        }
 
        switch (object->flags) {
-               case SEC_ACE_OBJECT_PRESENT:
+               case SEC_ACE_OBJECT_TYPE_PRESENT:
                        if (GUID_equal(&object->type.type,
                                       &ext_right_apg_guid)) {
                                return True;
                        }
-               case SEC_ACE_OBJECT_INHERITED_PRESENT:
+               case SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT:
                        if (GUID_equal(&object->inherited_type.inherited_type,
                                       &ext_right_apg_guid)) {
                                return True;
index 20f7b97745abdffda825d8606b4e081bea2f8e27..117178f3766812d7526bd25c46dbb3470d059c59 100644 (file)
 #define LIBNET_UNJOIN_OUT_DUMP_CTX(ctx, r) \
        LIBNET_UNJOIN_DUMP_CTX(ctx, r, NDR_OUT)
 
-#define W_ERROR_NOT_OK_GOTO_DONE(x) do { \
-       if (!W_ERROR_IS_OK(x)) {\
-               goto done;\
-       }\
-} while (0)
-
 /****************************************************************
 ****************************************************************/
 
index 00ba8bc29329107c6c0c5e9e0ac91a657109a40b..d4ac42e96146ee7c1ffc4ca56e7bb78afa995a56 100644 (file)
@@ -10,6 +10,8 @@ _PUBLIC_ enum ndr_err_code ndr_push_notify_entry(struct ndr_push *ndr, int ndr_f
                NDR_CHECK(ndr_push_server_id(ndr, NDR_SCALARS, &r->server));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->filter));
                NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->subdir_filter));
+               NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->dir_fd));
+               NDR_CHECK(ndr_push_file_id(ndr, NDR_SCALARS, &r->dir_id));
                {
                        uint32_t _flags_save_string = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM);
@@ -21,6 +23,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_notify_entry(struct ndr_push *ndr, int ndr_f
        }
        if (ndr_flags & NDR_BUFFERS) {
                NDR_CHECK(ndr_push_server_id(ndr, NDR_BUFFERS, &r->server));
+               NDR_CHECK(ndr_push_file_id(ndr, NDR_BUFFERS, &r->dir_id));
        }
        return NDR_ERR_SUCCESS;
 }
@@ -32,6 +35,8 @@ _PUBLIC_ enum ndr_err_code ndr_pull_notify_entry(struct ndr_pull *ndr, int ndr_f
                NDR_CHECK(ndr_pull_server_id(ndr, NDR_SCALARS, &r->server));
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->filter));
                NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->subdir_filter));
+               NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->dir_fd));
+               NDR_CHECK(ndr_pull_file_id(ndr, NDR_SCALARS, &r->dir_id));
                {
                        uint32_t _flags_save_string = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM);
@@ -43,6 +48,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_notify_entry(struct ndr_pull *ndr, int ndr_f
        }
        if (ndr_flags & NDR_BUFFERS) {
                NDR_CHECK(ndr_pull_server_id(ndr, NDR_BUFFERS, &r->server));
+               NDR_CHECK(ndr_pull_file_id(ndr, NDR_BUFFERS, &r->dir_id));
        }
        return NDR_ERR_SUCCESS;
 }
@@ -54,6 +60,8 @@ _PUBLIC_ void ndr_print_notify_entry(struct ndr_print *ndr, const char *name, co
        ndr_print_server_id(ndr, "server", &r->server);
        ndr_print_uint32(ndr, "filter", r->filter);
        ndr_print_uint32(ndr, "subdir_filter", r->subdir_filter);
+       ndr_print_uint32(ndr, "dir_fd", r->dir_fd);
+       ndr_print_file_id(ndr, "dir_id", &r->dir_id);
        ndr_print_string(ndr, "path", r->path);
        ndr_print_uint32(ndr, "path_len", r->path_len);
        ndr_print_pointer(ndr, "private_data", r->private_data);
index c809702e5d509e555b4eec66d8656e4af79dfe15..a5ec4a46e6e7a335bc999249e8d8f6773c1ebcda 100644 (file)
@@ -9,6 +9,8 @@ struct notify_entry {
        struct server_id server;
        uint32_t filter;
        uint32_t subdir_filter;
+       uint32_t dir_fd;
+       struct file_id dir_id;
        const char * path;/* [flag(LIBNDR_FLAG_STR_UTF8|LIBNDR_FLAG_STR_NULLTERM)] */
        uint32_t path_len;
        void* private_data;
index c4e633c254fe2890555ea96ca71c3e34d5c527b6..550783b5cd3a99b46b8cf6787a8533afb8bab346 100644 (file)
@@ -18,6 +18,8 @@ interface notify
                server_id server;
                uint32 filter; /* filter to apply in this directory */
                uint32 subdir_filter; /* filter to apply in child directories */
+               uint32 dir_fd;   /* fd of open directory */
+               file_id dir_id;  /* file_id of open directory */
                utf8string path;
                uint32 path_len; /* saves some computation on search */
                pointer private_data;
index 5afc4f4f5adc0d39f0d3cfd057b50ba2700ba35d..8fac5eadd4cdc8c2c4c3ff7bdf1a337304bc56cd 100644 (file)
@@ -155,6 +155,45 @@ void ndr_print_server_id(struct ndr_print *ndr, const char *name, const struct s
        ndr->depth--;
 }
 
+enum ndr_err_code ndr_push_file_id(struct ndr_push *ndr, int ndr_flags, const struct file_id *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_push_align(ndr, 4));
+               NDR_CHECK(ndr_push_udlong(ndr, NDR_SCALARS,
+                                         (uint64_t)r->devid));
+               NDR_CHECK(ndr_push_udlong(ndr, NDR_SCALARS,
+                                         (uint64_t)r->inode));
+               NDR_CHECK(ndr_push_udlong(ndr, NDR_SCALARS,
+                                         (uint64_t)r->extid));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+enum ndr_err_code ndr_pull_file_id(struct ndr_pull *ndr, int ndr_flags, struct file_id *r)
+{
+       if (ndr_flags & NDR_SCALARS) {
+               NDR_CHECK(ndr_pull_align(ndr, 4));
+               NDR_CHECK(ndr_pull_udlong(ndr, NDR_SCALARS, &r->devid));
+               NDR_CHECK(ndr_pull_udlong(ndr, NDR_SCALARS, &r->inode));
+               NDR_CHECK(ndr_pull_udlong(ndr, NDR_SCALARS, &r->extid));
+       }
+       if (ndr_flags & NDR_BUFFERS) {
+       }
+       return NDR_ERR_SUCCESS;
+}
+
+void ndr_print_file_id(struct ndr_print *ndr, const char *name, const struct file_id *r)
+{
+       ndr_print_struct(ndr, name, "file_id");
+       ndr->depth++;
+       ndr_print_udlong(ndr, "devid", (uint64_t)r->devid);
+       ndr_print_udlong(ndr, "inode", (uint64_t)r->inode);
+       ndr_print_udlong(ndr, "extid", (uint64_t)r->extid);
+       ndr->depth--;
+}
+
 _PUBLIC_ void ndr_print_bool(struct ndr_print *ndr, const char *name, const bool b)
 {
        ndr->print(ndr, "%-25s: %s", name, b?"true":"false");
index dabfc398ced293703dff0bc0f4fd9d85a616b4cd..ad11ee0ed411fe6dabfe57e4df4b514679f845c4 100644 (file)
@@ -1642,6 +1642,7 @@ bool cli_session_request(struct cli_state *cli,
 {
        char *p;
        int len = 4;
+       char *tmp;
 
        /* 445 doesn't have session request */
        if (cli->port == 445)
@@ -1651,14 +1652,30 @@ bool cli_session_request(struct cli_state *cli,
        memcpy(&(cli->called ), called , sizeof(*called ));
 
        /* put in the destination name */
+
+       tmp = name_mangle(talloc_tos(), cli->called.name,
+                         cli->called.name_type);
+       if (tmp == NULL) {
+               return false;
+       }
+
        p = cli->outbuf+len;
-       name_mangle(cli->called .name, p, cli->called .name_type);
-       len += name_len(p);
+       memcpy(p, tmp, name_len(tmp));
+       len += name_len(tmp);
+       TALLOC_FREE(tmp);
 
        /* and my name */
+
+       tmp = name_mangle(talloc_tos(), cli->calling.name,
+                         cli->calling.name_type);
+       if (tmp == NULL) {
+               return false;
+       }
+
        p = cli->outbuf+len;
-       name_mangle(cli->calling.name, p, cli->calling.name_type);
-       len += name_len(p);
+       memcpy(p, tmp, name_len(tmp));
+       len += name_len(tmp);
+       TALLOC_FREE(tmp);
 
        /* send a session request (RFC 1002) */
        /* setup the packet length
index c1af48507c8adaee15482c4ff1c715e978baebf2..4c12d18ab7b62a7dca92a2f22e671f6a9e27ab61 100644 (file)
@@ -630,11 +630,11 @@ smbc_version(void)
  * Set the credentials so DFS will work when following referrals.
  */
 void
-smbc_set_credentials(char *workgroup,
-                     char *user,
-                     char *password,
+smbc_set_credentials(const char *workgroup,
+                     const char *user,
+                     const char *password,
                      smbc_bool use_kerberos,
-                     char *signing_state)
+                     const char *signing_state)
 {
         struct user_auth_info *auth_info;
 
@@ -652,3 +652,39 @@ smbc_set_credentials(char *workgroup,
         cli_cm_set_credentials(auth_info);
        TALLOC_FREE(auth_info);
 }
+
+void smbc_set_credentials_with_fallback(SMBCCTX *context,
+                                       const char *workgroup,
+                                       const char *user,
+                                       const char *password)
+{
+       smbc_bool use_kerberos = false;
+       const char *signing_state = "off";
+       
+       if (! context ||
+           ! workgroup || ! *workgroup ||
+           ! user || ! *user ||
+           ! password || ! *password) {
+
+               return;
+       }
+
+       if (smbc_getOptionUseKerberos(context)) {
+               use_kerberos = True;
+       }
+
+       if (lp_client_signing()) {
+               signing_state = "on";
+       }
+
+       if (lp_client_signing() == Required) {
+               signing_state = "force";
+       }
+
+       smbc_set_credentials(workgroup, user, password,
+                             use_kerberos, signing_state);
+
+       if (smbc_getOptionFallbackAfterKerberos(context)) {
+               cli_cm_set_fallback_after_kerberos();
+       }
+}
index e9b7b4f95a9a22806906cb9d071f987b0602b99f..56661af70b02b37493b3f3c96077829c43106218 100644 (file)
@@ -1500,6 +1500,8 @@ SMBC_chmod_ctx(SMBCCTX *context,
         char *user = NULL;
         char *password = NULL;
         char *workgroup = NULL;
+       char *targetpath = NULL;
+       struct cli_state *targetcli = NULL;
        char *path = NULL;
        uint16 mode;
        TALLOC_CTX *frame = talloc_stackframe();
@@ -1517,7 +1519,7 @@ SMBC_chmod_ctx(SMBCCTX *context,
                return -1;
        }
 
-       DEBUG(4, ("smbc_chmod(%s, 0%3o)\n", fname, newmode));
+       DEBUG(4, ("smbc_chmod(%s, 0%3o)\n", fname, (unsigned int)newmode));
 
        if (SMBC_parse_path(frame,
                             context,
@@ -1550,6 +1552,14 @@ SMBC_chmod_ctx(SMBCCTX *context,
                TALLOC_FREE(frame);
                return -1;  /* errno set by SMBC_server */
        }
+       
+       /*d_printf(">>>unlink: resolving %s\n", path);*/
+       if (!cli_resolve_path(frame, "", srv->cli, path,
+                              &targetcli, &targetpath)) {
+               d_printf("Could not resolve %s\n", path);
+               TALLOC_FREE(frame);
+               return -1;
+       }
 
        mode = 0;
 
@@ -1558,8 +1568,8 @@ SMBC_chmod_ctx(SMBCCTX *context,
        if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
        if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
 
-       if (!cli_setatr(srv->cli, path, mode, 0)) {
-               errno = SMBC_errno(context, srv->cli);
+       if (!cli_setatr(targetcli, targetpath, mode, 0)) {
+               errno = SMBC_errno(context, targetcli);
                TALLOC_FREE(frame);
                return -1;
        }
@@ -1900,6 +1910,12 @@ SMBC_rename_ctx(SMBCCTX *ocontext,
 
        }
 
+       /* set the credentials to make DFS work */
+       smbc_set_credentials_with_fallback(ocontext,
+                                          workgroup,
+                                          user1,
+                                          password1);
+
        /*d_printf(">>>rename: resolving %s\n", path1);*/
        if (!cli_resolve_path(frame, "", srv->cli, path1,
                               &targetcli1, &targetpath1)) {
@@ -1907,6 +1923,13 @@ SMBC_rename_ctx(SMBCCTX *ocontext,
                TALLOC_FREE(frame);
                return -1;
        }
+       
+       /* set the credentials to make DFS work */
+       smbc_set_credentials_with_fallback(ncontext,
+                                          workgroup,
+                                          user2,
+                                          password2);
+       
        /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/
        /*d_printf(">>>rename: resolving %s\n", path2);*/
        if (!cli_resolve_path(frame, "", srv->cli, path2,
index ece056db87f1ea8d03b4ec925314e05a7f1bc7ee..28256bb24133467f7aa3baf6fefed453ec3a8b61 100644 (file)
@@ -382,7 +382,7 @@ SMBC_write_ctx(SMBCCTX *context,
                TALLOC_FREE(frame);
                 return -1;
         }
-        
+
        /*d_printf(">>>write: resolving %s\n", path);*/
        if (!cli_resolve_path(frame, "", file->srv->cli, path,
                               &targetcli, &targetpath)) {
index 6d69924231b61b77014386e40771152ef93f1718..6a59a12ed06648d87ff7013bbaba79497c17aa00 100644 (file)
@@ -216,7 +216,7 @@ smbc_urlencode(char *dest,
  * are supported.
  */
 
-static const char *smbc_prefix = "smb:";
+#define SMBC_PREFIX "smb:"
 
 int
 SMBC_parse_path(TALLOC_CTX *ctx,
@@ -233,6 +233,7 @@ SMBC_parse_path(TALLOC_CTX *ctx,
        char *s;
        const char *p;
        char *q, *r;
+       char *workgroup = NULL;
        int len;
         
        /* Ensure these returns are at least valid pointers. */
@@ -262,8 +263,8 @@ SMBC_parse_path(TALLOC_CTX *ctx,
        s = talloc_strdup(ctx, fname);
         
        /* see if it has the right prefix */
-       len = strlen(smbc_prefix);
-       if (strncmp(s,smbc_prefix,len) || (s[len] != '/' && s[len] != 0)) {
+       len = strlen(SMBC_PREFIX);
+       if (strncmp(s,SMBC_PREFIX,len) || (s[len] != '/' && s[len] != 0)) {
                 return -1; /* What about no smb: ? */
         }
         
@@ -332,7 +333,6 @@ SMBC_parse_path(TALLOC_CTX *ctx,
                u = userinfo;
                 
                if (strchr_m(u, ';')) {
-                       char *workgroup;
                        next_token_no_ltrim_talloc(ctx, &u, &workgroup, ";");
                        if (!workgroup) {
                                return -1;
@@ -394,6 +394,19 @@ decoding:
        (void) urldecode_talloc(ctx, pp_share, *pp_share);
        (void) urldecode_talloc(ctx, pp_user, *pp_user);
        (void) urldecode_talloc(ctx, pp_password, *pp_password);
+
+       if (!workgroup) {
+               workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context));
+       }
+       if (!workgroup) {
+               return -1;
+       }
+
+       /* set the credentials to make DFS work */
+       smbc_set_credentials_with_fallback(context,
+                                          workgroup,
+                                          *pp_user,
+                                          *pp_password);
         
        return 0;
 }
index 6d7a86241a8cc5c3b3284b21c73c2f18b292f7d7..eda37f2187f2ab5db0bcfaf9afbe3af71a276e61 100644 (file)
@@ -238,6 +238,7 @@ SMBC_server(TALLOC_CTX *ctx,
             char **pp_password)
 {
        SMBCSRV *srv=NULL;
+       char *workgroup = NULL;
        struct cli_state *c;
        struct nmb_name called, calling;
        const char *server_n = server;
@@ -359,7 +360,7 @@ SMBC_server(TALLOC_CTX *ctx,
         if (srv) {
 
                 /* ... then we're done here.  Give 'em what they came for. */
-                return srv;
+                goto done;
         }
 
         /* If we're not asked to connect when a connection doesn't exist... */
@@ -601,6 +602,22 @@ again:
                  server, share, srv));
 
        DLIST_ADD(context->internal->servers, srv);
+done:
+       if (!pp_workgroup || !*pp_workgroup || !**pp_workgroup) {
+               workgroup = talloc_strdup(ctx, smbc_getWorkgroup(context));
+       } else {
+               workgroup = *pp_workgroup;
+       }
+       if(!workgroup) {
+               return NULL;
+       }
+       
+       /* set the credentials to make DFS work */
+       smbc_set_credentials_with_fallback(context,
+                                          workgroup,
+                                          *pp_username,
+                                          *pp_password);
+       
        return srv;
 
 failed:
index 1ffe1417961a4bb30620940edef208d3b58b3d58..f8571ff11083deaf558d855e5e04b3f4d71c85c2 100644 (file)
@@ -155,7 +155,7 @@ SMBC_stat_ctx(SMBCCTX *context,
                TALLOC_FREE(frame);
                 return -1;
         }
-        
+
        if (!user || user[0] == (char)0) {
                user = talloc_strdup(frame, smbc_getUser(context));
                if (!user) {
index 02b13ae63e9718b968a82634174e192521edef40..5f3eda44fe2960300e2e2e79fc42016b550c3c57 100644 (file)
@@ -1279,12 +1279,19 @@ static int name_interpret(char *in, fstring name)
  Note:  <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
 ****************************************************************************/
 
-int name_mangle( char *In, char *Out, char name_type )
+char *name_mangle(TALLOC_CTX *mem_ctx, char *In, char name_type)
 {
        int   i;
        int   len;
        nstring buf;
-       char *p = Out;
+       char *result;
+       char *p;
+
+       result = talloc_array(mem_ctx, char, 33 + strlen(global_scope()) + 2);
+       if (result == NULL) {
+               return NULL;
+       }
+       p = result;
 
        /* Safely copy the input string, In, into buf[]. */
        if (strcmp(In,"*") == 0)
@@ -1321,7 +1328,7 @@ int name_mangle( char *In, char *Out, char name_type )
                                p[0] = len;
                                if( len > 0 )
                                        p[len+1] = 0;
-                               return( name_len(Out) );
+                               return result;
                        case '.':
                                p[0] = len;
                                p   += (len + 1);
@@ -1333,7 +1340,7 @@ int name_mangle( char *In, char *Out, char name_type )
                }
        }
 
-       return( name_len(Out) );
+       return result;
 }
 
 /****************************************************************************
index cc13476935ce5543b843b0fae10f9776932df350..0764f97d859c38db7e6e35f36ed0821d7f1baaaa 100644 (file)
@@ -110,12 +110,10 @@ void debug_ntlmssp_flags(uint32 neg_flags)
  *
  */
 
-static const uint8 *get_challenge(const struct ntlmssp_state *ntlmssp_state)
+static void get_challenge(const struct ntlmssp_state *ntlmssp_state,
+                         uint8_t chal[8])
 {
-       static uchar chal[8];
-       generate_random_buffer(chal, sizeof(chal));
-
-       return chal;
+       generate_random_buffer(chal, 8);
 }
 
 /**
@@ -517,7 +515,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
        char *dnsdomname = NULL;
        uint32 neg_flags = 0;
        uint32 ntlmssp_command, chal_flags;
-       const uint8 *cryptkey;
+       uint8_t cryptkey[8];
        const char *target_name;
 
        /* parse the NTLMSSP packet */
@@ -541,7 +539,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
        ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, lp_lanman_auth());
 
        /* Ask our caller what challenge they would like in the packet */
-       cryptkey = ntlmssp_state->get_challenge(ntlmssp_state);
+       ntlmssp_state->get_challenge(ntlmssp_state, cryptkey);
 
        /* Check if we may set the challenge */
        if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) {
index af3f7b0dd588a984683e1f9db1f1f2e784e7e387..177e0114b3de25d5011bd61e7f1accf31edce1f0 100644 (file)
@@ -38,7 +38,8 @@ struct smbdb_ctx {
 #endif
 
 int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, uint64_t dev,
-                               uint64_t ino, const struct smb_share_mode_entry *new_entry,
+                               uint64_t ino, uint64_t extid,
+                               const struct smb_share_mode_entry *new_entry,
                                const char *sharepath, const char *filename);
 
 static bool sharemodes_procid_equal(const struct server_id *p1, const struct server_id *p2)
@@ -83,6 +84,7 @@ struct smbdb_ctx *smb_share_mode_db_open(const char *db_path)
 struct locking_key {
         SMB_DEV_T dev;
         SMB_INO_T inode;
+       uint64_t extid;
 };
 
 int smb_share_mode_db_close(struct smbdb_ctx *db_ctx)
@@ -93,13 +95,14 @@ int smb_share_mode_db_close(struct smbdb_ctx *db_ctx)
 }
 
 static TDB_DATA get_locking_key(struct locking_key *lk, uint64_t dev,
-                               uint64_t ino)
+                               uint64_t ino, uint64_t extid)
 {
        TDB_DATA ld;
 
        memset(lk, '\0', sizeof(*lk));
        lk->dev = (SMB_DEV_T)dev;
        lk->inode = (SMB_INO_T)ino;
+       lk->extid = extid;
        ld.dptr = (uint8 *)lk;
        ld.dsize = sizeof(*lk);
        return ld;
@@ -111,19 +114,22 @@ static TDB_DATA get_locking_key(struct locking_key *lk, uint64_t dev,
 
 int smb_lock_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
-                               uint64_t ino)
+                               uint64_t ino,
+                               uint64_t extid)
 {
        struct locking_key lk;
-       return tdb_chainlock(db_ctx->smb_tdb, get_locking_key(&lk, dev, ino));
+       return tdb_chainlock(db_ctx->smb_tdb, get_locking_key(&lk, dev, ino,
+                                                             extid));
 }
 
 int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx,
                                 uint64_t dev,
-                                uint64_t ino)
+                                uint64_t ino,
+                                uint64_t extid)
 {
        struct locking_key lk;
        return tdb_chainunlock(db_ctx->smb_tdb,
-                              get_locking_key(&lk, dev, ino));
+                              get_locking_key(&lk, dev, ino, extid));
 }
 
 /*
@@ -140,7 +146,8 @@ static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry,
                e_entry->share_access == (uint32_t)entry->share_access &&
                e_entry->access_mask == (uint32_t)entry->access_mask &&
                e_entry->dev == entry->id.devid && 
-               e_entry->ino == entry->id.inode);
+               e_entry->ino == entry->id.inode &&
+               e_entry->extid == entry->id.extid);
 }
 
 /*
@@ -160,6 +167,7 @@ static void create_share_mode_entry(struct share_mode_entry *out,
        out->access_mask = in->access_mask;
        out->id.devid = in->dev;
        out->id.inode = in->ino;
+       out->id.extid = in->extid;
        out->uid = (uint32)geteuid();
        out->flags = 0;
 }
@@ -172,6 +180,7 @@ static void create_share_mode_entry(struct share_mode_entry *out,
 int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino,
+                               uint64_t extid,
                                struct smb_share_mode_entry **pp_list,
                                unsigned char *p_delete_on_close)
 {
@@ -187,7 +196,8 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
        *pp_list = NULL;
        *p_delete_on_close = 0;
 
-       db_data = tdb_fetch(db_ctx->smb_tdb, get_locking_key(&lk, dev, ino));
+       db_data = tdb_fetch(db_ctx->smb_tdb, get_locking_key(&lk, dev, ino,
+                                                            extid));
        if (!db_data.dptr) {
                return 0;
        }
@@ -229,6 +239,7 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
                /* Copy into the external list. */
                sme->dev = share->id.devid;
                sme->ino = share->id.inode;
+               sme->extid = share->id.extid;
                sme->share_access = (uint32_t)share->share_access;
                sme->access_mask = (uint32_t)share->access_mask;
                sme->open_time.tv_sec = share->time.tv_sec;
@@ -257,13 +268,14 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
 int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino,
+                               uint64_t extid,
                                const struct smb_share_mode_entry *new_entry,
                                const char *sharepath, /* Must be absolute utf8 path. */
                                const char *filename) /* Must be relative utf8 path. */
 {
        TDB_DATA db_data;
        struct locking_key lk;
-       TDB_DATA locking_key =  get_locking_key(&lk, dev, ino);
+       TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
        int orig_num_share_modes = 0;
        struct locking_data *ld = NULL; /* internal samba db state. */
        struct share_mode_entry *shares = NULL;
@@ -360,24 +372,26 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
 int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino,
+                               uint64_t extid,
                                const struct smb_share_mode_entry *new_entry,
                                const char *filename) /* Must be absolute utf8 path. */
 {
        if (*filename != '/') {
                abort();
        }
-       return smb_create_share_mode_entry_ex(db_ctx, dev, ino, new_entry,
+       return smb_create_share_mode_entry_ex(db_ctx, dev, ino, extid, new_entry,
                                                "/", &filename[1]);
 }
 
 int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino,
+                               uint64_t extid,
                                const struct smb_share_mode_entry *del_entry)
 {
        TDB_DATA db_data;
        struct locking_key lk;
-       TDB_DATA locking_key =  get_locking_key(&lk, dev, ino);
+       TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
        int orig_num_share_modes = 0;
        struct locking_data *ld = NULL; /* internal samba db state. */
        struct share_mode_entry *shares = NULL;
@@ -475,12 +489,13 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
 int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx,
                                uint64_t dev,
                                uint64_t ino,
+                               uint64_t extid,
                                const struct smb_share_mode_entry *set_entry,
                                const struct smb_share_mode_entry *new_entry)
 {
        TDB_DATA db_data;
        struct locking_key lk;
-       TDB_DATA locking_key =  get_locking_key(&lk, dev, ino);
+       TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
        int num_share_modes = 0;
        struct locking_data *ld = NULL; /* internal samba db state. */
        struct share_mode_entry *shares = NULL;
index d12c4affc38f946358831d2f4ddfc17933959797..aa522ac7801ebc77f34c51f0760f9bfaa28be9ab 100644 (file)
@@ -74,6 +74,7 @@ bool brl_same_context(const struct lock_context *ctx1,
 static bool brl_overlap(const struct lock_struct *lck1,
                         const struct lock_struct *lck2)
 {
+       /* XXX Remove for Win7 compatibility. */
        /* this extra check is not redundent - it copes with locks
           that go beyond the end of 64 bit file space */
        if (lck1->size != 0 &&
@@ -105,8 +106,11 @@ static bool brl_conflict(const struct lock_struct *lck1,
                return False;
        }
 
-       if (brl_same_context(&lck1->context, &lck2->context) &&
-           lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) {
+       /* A READ lock can stack on top of a WRITE lock if they have the same
+        * context & fnum. */
+       if (lck1->lock_type == WRITE_LOCK && lck2->lock_type == READ_LOCK &&
+           brl_same_context(&lck1->context, &lck2->context) &&
+           lck1->fnum == lck2->fnum) {
                return False;
        }
 
index cc0295e74970e0d64b71e86a3ac74ed64cf4f9ec..1737eab1c6f32df43ac205b09d98002d3455fcba 100644 (file)
@@ -923,12 +923,12 @@ bool rename_share_filename(struct messaging_context *msg_ctx,
                return False;
        }
 
-       push_file_id_16(frm, &lck->id);
+       push_file_id_24(frm, &lck->id);
 
        DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len ));
 
-       safe_strcpy(&frm[16], lck->servicepath, sp_len);
-       safe_strcpy(&frm[16 + sp_len + 1], lck->filename, fn_len);
+       safe_strcpy(&frm[24], lck->servicepath, sp_len);
+       safe_strcpy(&frm[24 + sp_len + 1], lck->filename, fn_len);
 
        /* Send the messages. */
        for (i=0; i<lck->num_share_modes; i++) {
index 556dad6b5e5c91684a191529e51466eb09f1499f..7756f8f3abff372a3992dcc88794abec0e9d6c02 100644 (file)
@@ -44,10 +44,10 @@ typedef struct _SMB_ACL4_INT_T
        SMB_ACE4_INT_T  *last;
 } SMB_ACL4_INT_T;
 
-static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *acl)
+static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *theacl)
 {
-       SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl;
-       if (acl==NULL)
+       SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)theacl;
+       if (theacl==NULL)
        {
                DEBUG(2, ("acl is NULL\n"));
                errno = EINVAL;
@@ -83,21 +83,21 @@ static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace)
 SMB4ACL_T *smb_create_smb4acl(void)
 {
        TALLOC_CTX *mem_ctx = talloc_tos();
-       SMB_ACL4_INT_T  *acl = (SMB_ACL4_INT_T *)TALLOC_ZERO_SIZE(mem_ctx, sizeof(SMB_ACL4_INT_T));
-       if (acl==NULL)
+       SMB_ACL4_INT_T  *theacl = (SMB_ACL4_INT_T *)TALLOC_ZERO_SIZE(mem_ctx, sizeof(SMB_ACL4_INT_T));
+       if (theacl==NULL)
        {
                DEBUG(0, ("TALLOC_SIZE failed\n"));
                errno = ENOMEM;
                return NULL;
        }
-       acl->magic = SMB_ACL4_INT_MAGIC;
-       /* acl->first, last = NULL not needed */
-       return (SMB4ACL_T *)acl;
+       theacl->magic = SMB_ACL4_INT_MAGIC;
+       /* theacl->first, last = NULL not needed */
+       return (SMB4ACL_T *)theacl;
 }
 
-SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop)
+SMB4ACE_T *smb_add_ace4(SMB4ACL_T *theacl, SMB_ACE4PROP_T *prop)
 {
-       SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+       SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
        TALLOC_CTX *mem_ctx = talloc_tos();
        SMB_ACE4_INT_T *ace;
 
@@ -143,18 +143,18 @@ SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace)
        return (SMB4ACE_T *)aceint->next;
 }
 
-SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl)
+SMB4ACE_T *smb_first_ace4(SMB4ACL_T *theacl)
 {
-       SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+       SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
        if (aclint==NULL)
                return NULL;
 
        return (SMB4ACE_T *)aclint->first;
 }
 
-uint32 smb_get_naces(SMB4ACL_T *acl)
+uint32 smb_get_naces(SMB4ACL_T *theacl)
 {
-       SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+       SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
        if (aclint==NULL)
                return 0;
 
@@ -195,22 +195,23 @@ static int smbacl4_fGetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf)
        return 0;
 }
 
-static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */
+static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *theacl, /* in */
        DOM_SID *psid_owner, /* in */
        DOM_SID *psid_group, /* in */
+       bool is_directory, /* in */
        SEC_ACE **ppnt_ace_list, /* out */
        int *pgood_aces /* out */
 )
 {
-       SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl;
+       SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)theacl;
        SMB_ACE4_INT_T *aceint;
        SEC_ACE *nt_ace_list = NULL;
        int good_aces = 0;
 
        DEBUG(10, ("smbacl_nfs42win entered"));
 
-       aclint = get_validated_aclint(acl);
-       /* We do not check for naces being 0 or acl being NULL here because it is done upstream */
+       aclint = get_validated_aclint(theacl);
+       /* We do not check for naces being 0 or theacl being NULL here because it is done upstream */
        /* in smb_get_nt_acl_nfs4(). */
        nt_ace_list = (SEC_ACE *)TALLOC_ZERO_SIZE(mem_ctx, aclint->naces * sizeof(SEC_ACE));
        if (nt_ace_list==NULL)
@@ -256,6 +257,10 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */
                DEBUG(10, ("mapped %d to %s\n", ace->who.id,
                           sid_string_dbg(&sid)));
 
+               if (is_directory && (ace->aceMask & SMB_ACE4_ADD_FILE)) {
+                       ace->aceMask |= SMB_ACE4_DELETE_CHILD;
+               }
+
                mask = ace->aceMask;
                init_sec_ace(&nt_ace_list[good_aces++], &sid,
                        ace->aceType, mask,
@@ -270,7 +275,7 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */
 
 static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
        uint32 security_info,
-       SEC_DESC **ppdesc, SMB4ACL_T *acl)
+       SEC_DESC **ppdesc, SMB4ACL_T *theacl)
 {
        int     good_aces = 0;
        DOM_SID sid_owner, sid_group;
@@ -279,7 +284,7 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
        SEC_ACL *psa = NULL;
        TALLOC_CTX *mem_ctx = talloc_tos();
 
-       if (acl==NULL || smb_get_naces(acl)==0)
+       if (theacl==NULL || smb_get_naces(theacl)==0)
                return NT_STATUS_ACCESS_DENIED; /* special because we
                                                 * shouldn't alloc 0 for
                                                 * win */
@@ -287,7 +292,8 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
        uid_to_sid(&sid_owner, sbuf->st_uid);
        gid_to_sid(&sid_group, sbuf->st_gid);
 
-       if (smbacl4_nfs42win(mem_ctx, acl, &sid_owner, &sid_group, &nt_ace_list, &good_aces)==False) {
+       if (smbacl4_nfs42win(mem_ctx, theacl, &sid_owner, &sid_group, S_ISDIR(sbuf->st_mode),
+                               &nt_ace_list, &good_aces)==False) {
                DEBUG(8,("smbacl4_nfs42win failed\n"));
                return map_nt_error_from_unix(errno);
        }
@@ -316,7 +322,7 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
 
 NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
                               uint32 security_info,
-                              SEC_DESC **ppdesc, SMB4ACL_T *acl)
+                              SEC_DESC **ppdesc, SMB4ACL_T *theacl)
 {
        SMB_STRUCT_STAT sbuf;
 
@@ -326,13 +332,13 @@ NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
                return map_nt_error_from_unix(errno);
        }
 
-       return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, acl);
+       return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, theacl);
 }
 
 NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
                              const char *name,
                              uint32 security_info,
-                             SEC_DESC **ppdesc, SMB4ACL_T *acl)
+                             SEC_DESC **ppdesc, SMB4ACL_T *theacl)
 {
        SMB_STRUCT_STAT sbuf;
 
@@ -342,7 +348,7 @@ NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
                return map_nt_error_from_unix(errno);
        }
 
-       return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, acl);
+       return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, theacl);
 }
 
 enum smbacl4_mode_enum {e_simple=0, e_special=1};
@@ -393,9 +399,9 @@ static int smbacl4_get_vfs_params(
        return 0;
 }
 
-static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *acl)
+static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *theacl)
 {
-       SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+       SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
        SMB_ACE4_INT_T *aceint;
 
        DEBUG(level, ("NFS4ACL: size=%d\n", aclint->naces));
@@ -417,10 +423,10 @@ static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *acl)
  * return ace if found matching; otherwise NULL
  */
 static SMB_ACE4PROP_T *smbacl4_find_equal_special(
-       SMB4ACL_T *acl,
+       SMB4ACL_T *theacl,
        SMB_ACE4PROP_T *aceNew)
 {
-       SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+       SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
        SMB_ACE4_INT_T *aceint;
 
        for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
@@ -612,14 +618,14 @@ static bool smbacl4_fill_ace4(
 
 static int smbacl4_MergeIgnoreReject(
        enum smbacl4_acedup_enum acedup,
-       SMB4ACL_T *acl, /* may modify it */
+       SMB4ACL_T *theacl, /* may modify it */
        SMB_ACE4PROP_T *ace, /* the "new" ACE */
        bool    *paddNewACE,
        int     i
 )
 {
        int     result = 0;
-       SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(acl, ace);
+       SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace);
        if (ace4found)
        {
                switch(acedup)
@@ -652,14 +658,14 @@ static SMB4ACL_T *smbacl4_win2nfs4(
        gid_t ownerGID
 )
 {
-       SMB4ACL_T *acl;
+       SMB4ACL_T *theacl;
        uint32  i;
        TALLOC_CTX *mem_ctx = talloc_tos();
 
        DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
 
-       acl = smb_create_smb4acl();
-       if (acl==NULL)
+       theacl = smb_create_smb4acl();
+       if (theacl==NULL)
                return NULL;
 
        for(i=0; i<dacl->num_aces; i++) {
@@ -676,16 +682,16 @@ static SMB4ACL_T *smbacl4_win2nfs4(
                }
 
                if (pparams->acedup!=e_dontcare) {
-                       if (smbacl4_MergeIgnoreReject(pparams->acedup, acl,
+                       if (smbacl4_MergeIgnoreReject(pparams->acedup, theacl,
                                &ace_v4, &addNewACE, i))
                                return NULL;
                }
 
                if (addNewACE)
-                       smb_add_ace4(acl, &ace_v4);
+                       smb_add_ace4(theacl, &ace_v4);
        }
 
-       return acl;
+       return theacl;
 }
 
 NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
@@ -694,7 +700,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
        set_nfs4acl_native_fn_t set_nfs4_native)
 {
        smbacl4_vfs_params params;
-       SMB4ACL_T *acl = NULL;
+       SMB4ACL_T *theacl = NULL;
        bool    result;
 
        SMB_STRUCT_STAT sbuf;
@@ -753,16 +759,16 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
                return NT_STATUS_OK;
        }
 
-       acl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, &params, sbuf.st_uid, sbuf.st_gid);
-       if (!acl)
+       theacl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, &params, sbuf.st_uid, sbuf.st_gid);
+       if (!theacl)
                return map_nt_error_from_unix(errno);
 
-       smbacl4_dump_nfs4acl(10, acl);
+       smbacl4_dump_nfs4acl(10, theacl);
 
        if (set_acl_as_root) {
                become_root();
        }
-       result = set_nfs4_native(fsp, acl);
+       result = set_nfs4_native(fsp, theacl);
        saved_errno = errno;
        if (set_acl_as_root) {
                unbecome_root();
index a227c6e0fcaac486ec0e210e338fb688dc65e819..b2d1196b26050f16f1a030b66240a3b05187eed9 100644 (file)
@@ -117,26 +117,26 @@ SMB4ACL_T *smb_create_smb4acl(void);
 
 /* prop's contents are copied */
 /* it doesn't change the order, appends */
-SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop);
+SMB4ACE_T *smb_add_ace4(SMB4ACL_T *theacl, SMB_ACE4PROP_T *prop);
 
 SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace);
 
 /* Returns NULL if none - or error */
-SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl);
+SMB4ACE_T *smb_first_ace4(SMB4ACL_T *theacl);
 
 /* Returns NULL in the end - or error */
 SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace);
 
-uint32 smb_get_naces(SMB4ACL_T *acl);
+uint32 smb_get_naces(SMB4ACL_T *theacl);
 
 NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
        uint32 security_info,
-       SEC_DESC **ppdesc, SMB4ACL_T *acl);
+       SEC_DESC **ppdesc, SMB4ACL_T *theacl);
 
 NTSTATUS smb_get_nt_acl_nfs4(connection_struct *conn,
        const char *name,
        uint32 security_info,
-       SEC_DESC **ppdesc, SMB4ACL_T *acl);
+       SEC_DESC **ppdesc, SMB4ACL_T *theacl);
 
 /* Callback function needed to set the native acl
  * when applicable */
index c002739f1f762a0f3b9f421a7fd5cb905f7dbeb8..a0f4fe37dee0da4734ddc067355f91cd9c6ead8a 100644 (file)
@@ -41,18 +41,32 @@ enum onefs_acl_wire_format
 #define PARM_ONEFS_TYPE "onefs"
 #define PARM_ACL_WIRE_FORMAT "acl wire format"
 #define PARM_ACL_WIRE_FORMAT_DEFAULT ACL_FORMAT_WINDOWS_SD
+#define PARM_ALLOW_EXECUTE_ALWAYS "allow execute always"
+#define PARM_ALLOW_EXECUTE_ALWAYS_DEFAULT false
 #define PARM_ATIME_NOW         "atime now files"
 #define PARM_ATIME_NOW_DEFAULT  NULL
 #define PARM_ATIME_STATIC      "atime static files"
 #define PARM_ATIME_STATIC_DEFAULT NULL
 #define PARM_ATIME_SLOP                "atime now slop"
 #define PARM_ATIME_SLOP_DEFAULT         0
+#define PARM_ATOMIC_SENDFILE "atomic sendfile"
+#define PARM_ATOMIC_SENDFILE_DEFAULT true
 #define PARM_CREATOR_OWNER_GETS_FULL_CONTROL "creator owner gets full control"
 #define PARM_CREATOR_OWNER_GETS_FULL_CONTROL_DEFAULT true
 #define PARM_CTIME_NOW         "ctime now files"
 #define PARM_CTIME_NOW_DEFAULT  NULL
 #define PARM_CTIME_SLOP                "ctime now slop"
 #define PARM_CTIME_SLOP_DEFAULT        0
+#define PARM_DOT_SNAP_CHILD_ACCESSIBLE "dot snap child accessible"
+#define PARM_DOT_SNAP_CHILD_ACCESSIBLE_DEFAULT true
+#define PARM_DOT_SNAP_CHILD_VISIBLE "dot snap child visible"
+#define PARM_DOT_SNAP_CHILD_VISIBLE_DEFAULT false
+#define PARM_DOT_SNAP_ROOT_ACCESSIBLE "dot snap root accessible"
+#define PARM_DOT_SNAP_ROOT_ACCESSIBLE_DEFAULT true
+#define PARM_DOT_SNAP_ROOT_VISIBLE "dot snap root visible"
+#define PARM_DOT_SNAP_ROOT_VISIBLE_DEFAULT true
+#define PARM_DOT_SNAP_TILDE "dot snap tilde"
+#define PARM_DOT_SNAP_TILDE_DEFAULT true
 #define PARM_IGNORE_SACLS "ignore sacls"
 #define PARM_IGNORE_SACLS_DEFAULT false
 #define PARM_MTIME_NOW         "mtime now files"
@@ -63,6 +77,10 @@ enum onefs_acl_wire_format
 #define PARM_MTIME_SLOP_DEFAULT        0
 #define PARM_USE_READDIRPLUS "use readdirplus"
 #define PARM_USE_READDIRPLUS_DEFAULT true
+#define PARM_SENDFILE_LARGE_READS "sendfile large reads"
+#define PARM_SENDFILE_LARGE_READS_DEFAULT false
+#define PARM_SENDFILE_SAFE "sendfile safe"
+#define PARM_SENDFILE_SAFE_DEFAULT true
 #define PARM_SIMPLE_FILE_SHARING_COMPATIBILITY_MODE "simple file sharing compatibility mode"
 #define PARM_SIMPLE_FILE_SHARING_COMPATIBILITY_MODE_DEFAULT false
 #define PARM_UNMAPPABLE_SIDS_DENY_EVERYONE "unmappable sids deny everyone"
@@ -91,9 +109,9 @@ enum onefs_acl_wire_format
 
 #define ONEFS_VFS_CONFIG_FAKETIMESTAMPS        0x00000001
 
-struct onefs_vfs_config
+struct onefs_vfs_share_config
 {
-       int32 init_flags;
+       uint32_t init_flags;
 
        /* data for fake timestamps */
        int atime_slop;
@@ -119,6 +137,18 @@ struct onefs_vfs_config
        name_compare_entry *atime_static_list;
 };
 
+struct onefs_vfs_global_config
+{
+       uint32_t init_flags;
+
+       /* Snapshot options */
+       bool dot_snap_child_accessible;
+       bool dot_snap_child_visible;
+       bool dot_snap_root_accessible;
+       bool dot_snap_root_visible;
+       bool dot_snap_tilde;
+};
+
 /*
  * vfs interface handlers
  */
@@ -204,6 +234,15 @@ bool onefs_brl_cancel_windows(vfs_handle_struct *handle,
                              struct lock_struct *plock,
                              struct blocking_lock_record *blr);
 
+NTSTATUS onefs_notify_watch(vfs_handle_struct *vfs_handle,
+                           struct sys_notify_context *ctx,
+                           struct notify_entry *e,
+                           void (*callback)(struct sys_notify_context *ctx,
+                                       void *private_data,
+                                       struct notify_event *ev),
+                           void *private_data,
+                           void *handle_p);
+
 NTSTATUS onefs_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                           uint32 security_info, SEC_DESC **ppdesc);
 
@@ -223,7 +262,7 @@ NTSTATUS onefs_split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
                                      char **pbase, char **pstream);
 
 bool onefs_get_config(int snum, int config_type,
-                     struct onefs_vfs_config *cfg);
+                     struct onefs_vfs_share_config *cfg);
 
 int onefs_rdp_add_dir_state(connection_struct *conn, SMB_STRUCT_DIR *dirp);
 
@@ -245,7 +284,15 @@ int onefs_sys_create_file(connection_struct *conn,
                          uint32_t ntfs_flags,
                          int *granted_oplock);
 
+ssize_t onefs_sys_sendfile(connection_struct *conn, int tofd, int fromfd,
+                          const DATA_BLOB *header, SMB_OFF_T offset,
+                          size_t count);
+
 ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
                           size_t count);
 
+void onefs_sys_config_enc(void);
+void onefs_sys_config_snap_opt(struct onefs_vfs_global_config *global_config);
+void onefs_sys_config_tilde(struct onefs_vfs_global_config *global_config);
+
 #endif /* _ONEFS_H */
index 7bc4a1728f1d6e8282e26356e1fc0f43d2bfb71e..a1bfa6e121e19659605d2a53fbf1d696374ac478 100644 (file)
@@ -273,9 +273,6 @@ onefs_samba_acl_to_acl(SEC_ACL *samba_acl, struct ifs_security_acl **acl,
                if (aclu_initialize_acl(acl, aces, num_aces))
                        goto err_free;
 
-       if (aclu_initialize_acl(acl, aces, num_aces))
-               goto err_free;
-
        /* Currently aclu_initialize_acl should copy the aces over, allowing
         * us to immediately free */
        free(aces);
@@ -614,6 +611,8 @@ onefs_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
        bool fopened = false;
        NTSTATUS status = NT_STATUS_OK;
 
+       START_PROFILE(syscall_get_sd);
+
        *ppdesc = NULL;
 
        DEBUG(5, ("Getting sd for file %s. security_info=%u\n",
@@ -753,6 +752,9 @@ onefs_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
        DEBUG(5, ("Finished retrieving/canonicalizing SD!\n"));
        /* FALLTHROUGH */
 out:
+
+       END_PROFILE(syscall_get_sd);
+
        if (alloced && sd) {
                if (new_aces_alloced && sd->dacl->aces)
                        SAFE_FREE(sd->dacl->aces);
@@ -888,18 +890,20 @@ onefs_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                  uint32 security_info_sent, SEC_DESC *psd)
 {
        struct ifs_security_descriptor sd = {};
-       int fd;
+       int fd = -1;
        bool fopened = false;
        NTSTATUS status;
 
+       START_PROFILE(syscall_set_sd);
+
        DEBUG(5,("Setting SD on file %s.\n", fsp->fsp_name ));
 
        status = onefs_samba_sd_to_sd(security_info_sent, psd, &sd,
                                      SNUM(handle->conn));
 
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(3, ("SD initialization failure: %s", nt_errstr(status)));
-               return status;
+               DEBUG(3, ("SD initialization failure: %s\n", nt_errstr(status)));
+               goto out;
        }
 
        fd = fsp->fh->fd;
@@ -938,6 +942,8 @@ onefs_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
 
        /* FALLTHROUGH */
 out:
+       END_PROFILE(syscall_set_sd);
+
        if (fopened)
                close(fd);
 
index a860023764257686fbd78c5ad6eb5380c1e011d1..2c5e39c3596192ce63411c4ef9427fa92cded60a 100644 (file)
@@ -255,6 +255,8 @@ NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle,
        struct onefs_cbrl_blr_state *bs;
        NTSTATUS status;
 
+       START_PROFILE(syscall_brl_lock);
+
        SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
        SMB_ASSERT(plock->lock_type != UNLOCK_LOCK);
 
@@ -301,10 +303,13 @@ NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle,
                /* ASYNC still in progress: The process_* calls will keep
                 * calling even if we haven't gotten the lock. Keep erroring
                 * without calling ifs_cbrl, or getting/setting an id. */
-               if (bs->state == ONEFS_CBRL_ASYNC)
+               if (bs->state == ONEFS_CBRL_ASYNC) {
                        goto failure;
-               else if (bs->state == ONEFS_CBRL_ERROR)
+               }
+               else if (bs->state == ONEFS_CBRL_ERROR) {
+                       END_PROFILE(syscall_brl_lock);
                        return NT_STATUS_NO_MEMORY;
+               }
 
                SMB_ASSERT(bs->state == ONEFS_CBRL_NONE);
                async = true;
@@ -343,6 +348,9 @@ NTSTATUS onefs_brl_lock_windows(vfs_handle_struct *handle,
        }
 
 failure:
+
+       END_PROFILE(syscall_brl_lock);
+
        /* Failure - error or async. */
        plock->context.smbpid = (uint32) ONEFS_BLOCKING_PID;
 
@@ -355,6 +363,9 @@ failure:
        return status;
 
 success:
+
+       END_PROFILE(syscall_brl_lock);
+
        /* Success. */
        onefs_cbrl_enumerate_blq("onefs_brl_unlock_windows");
        DEBUG(10, ("returning NT_STATUS_OK.\n"));
@@ -371,6 +382,8 @@ bool onefs_brl_unlock_windows(vfs_handle_struct *handle,
        int error;
        int fd = br_lck->fsp->fh->fd;
 
+       START_PROFILE(syscall_brl_unlock);
+
        SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
        SMB_ASSERT(plock->lock_type == UNLOCK_LOCK);
 
@@ -378,6 +391,9 @@ bool onefs_brl_unlock_windows(vfs_handle_struct *handle,
        error = ifs_cbrl(fd, CBRL_OP_UNLOCK, CBRL_NOTYPE,
            plock->start, plock->size, CBRL_NOTYPE, 0, plock->context.smbpid,
            plock->context.tid, plock->fnum);
+
+       END_PROFILE(syscall_brl_unlock);
+
        if (error) {
                DEBUG(10, ("returning false.\n"));
                return false;
@@ -404,6 +420,8 @@ bool onefs_brl_cancel_windows(vfs_handle_struct *handle,
        int fd = br_lck->fsp->fh->fd;
        struct onefs_cbrl_blr_state *bs;
 
+       START_PROFILE(syscall_brl_cancel);
+
        SMB_ASSERT(plock);
        SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
        SMB_ASSERT(blr);
@@ -416,6 +434,7 @@ bool onefs_brl_cancel_windows(vfs_handle_struct *handle,
        if (bs->state == ONEFS_CBRL_DONE) {
                /* No-op. */
                DEBUG(10, ("State=DONE, returning true\n"));
+               END_PROFILE(syscall_brl_cancel);
                return true;
        }
 
@@ -427,6 +446,9 @@ bool onefs_brl_cancel_windows(vfs_handle_struct *handle,
        error = ifs_cbrl(fd, CBRL_OP_CANCEL, CBRL_NOTYPE, plock->start,
            plock->size, CBRL_NOTYPE, bs->id, plock->context.smbpid,
            plock->context.tid, plock->fnum);
+
+       END_PROFILE(syscall_brl_cancel);
+
        if (error) {
                DEBUG(10, ("returning false\n"));
                bs->state = ONEFS_CBRL_ERROR;
diff --git a/source3/modules/onefs_notify.c b/source3/modules/onefs_notify.c
new file mode 100644 (file)
index 0000000..40f6908
--- /dev/null
@@ -0,0 +1,680 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Support for change notify using OneFS's file event notification system
+ *
+ * Copyright (C) Andrew Tridgell, 2006
+ * Copyright (C) Steven Danneman, 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Implement handling of change notify requests on files and directories using
+ * Isilon OneFS's "ifs event" file notification system.
+ *
+ * The structure of this file is based off the implementation of change notify
+ * using the inotify system calls in smbd/notify_inotify.c */
+
+/* TODO: We could reduce the number of file descriptors used by merging
+ * multiple watch requests on the same directory into the same
+ * onefs_notify_watch_context.  To do this we'd need mux/demux routines that
+ * when receiving an event on that watch context would check it against the
+ * CompletionFilter and WatchTree of open SMB requests, and return notify
+ * events back to the proper SMB requests */
+
+#include "onefs.h"
+
+#include <ifs/ifs_types.h>
+#include <ifs/ifs_syscalls.h>
+#include <isi_util/syscalls.h>
+
+#include <sys/event.h>
+
+#define ONEFS_IFS_EVENT_MAX_NUM 8
+#define ONEFS_IFS_EVENT_MAX_BYTES (ONEFS_IFS_EVENT_MAX_NUM * \
+                                  sizeof(struct ifs_event))
+
+struct onefs_notify_watch_context {
+       struct sys_notify_context *ctx;
+       int watch_fd;
+       ino_t watch_lin;
+       const char *path;
+       int ifs_event_fd;
+       uint32_t ifs_filter; /* the ifs event mask */
+       uint32_t smb_filter; /* the windows completion filter */
+       void (*callback)(struct sys_notify_context *ctx,
+                        void *private_data,
+                        struct notify_event *ev);
+       void *private_data;
+};
+
+/**
+ * Conversion map from a SMB completion filter to an IFS event mask.
+ */
+static const struct {
+       uint32_t smb_filter;
+       uint32_t ifs_filter;
+} onefs_notify_conv[] = {
+       {FILE_NOTIFY_CHANGE_FILE_NAME,
+           NOTE_CREATE | NOTE_DELETE | NOTE_RENAME_FROM | NOTE_RENAME_TO},
+       {FILE_NOTIFY_CHANGE_DIR_NAME,
+           NOTE_CREATE | NOTE_DELETE | NOTE_RENAME_FROM | NOTE_RENAME_TO},
+       {FILE_NOTIFY_CHANGE_ATTRIBUTES,
+           NOTE_CREATE | NOTE_DELETE | NOTE_RENAME_FROM | NOTE_RENAME_TO |
+           NOTE_ATTRIB},
+       {FILE_NOTIFY_CHANGE_SIZE,
+           NOTE_SIZE | NOTE_EXTEND},
+       {FILE_NOTIFY_CHANGE_LAST_WRITE,
+           NOTE_WRITE | NOTE_ATTRIB},
+       /* OneFS doesn't set atime by default, but we can somewhat fake it by
+        * notifying for other events that imply ACCESS */
+       {FILE_NOTIFY_CHANGE_LAST_ACCESS,
+           NOTE_WRITE | NOTE_ATTRIB},
+       /* We don't have an ifs_event for the setting of create time, but we
+        * can fake by notifying when a "new" file is created via rename */
+       {FILE_NOTIFY_CHANGE_CREATION,
+           NOTE_RENAME_TO},
+       {FILE_NOTIFY_CHANGE_SECURITY,
+           NOTE_SECURITY},
+       /* Unsupported bits
+       FILE_NOTIFY_CHANGE_EA            (no EAs in OneFS)
+       FILE_NOTIFY_CHANGE_STREAM_NAME   (no ifs_event equivalent)
+       FILE_NOTIFY_CHANGE_STREAM_SIZE   (no ifs_event equivalent)
+       FILE_NOTIFY_CHANGE_STREAM_WRITE  (no ifs_event equivalent) */
+};
+
+#define ONEFS_NOTIFY_UNSUPPORTED  (FILE_NOTIFY_CHANGE_LAST_ACCESS | \
+                                  FILE_NOTIFY_CHANGE_CREATION    | \
+                                  FILE_NOTIFY_CHANGE_EA          | \
+                                  FILE_NOTIFY_CHANGE_STREAM_NAME | \
+                                  FILE_NOTIFY_CHANGE_STREAM_SIZE | \
+                                  FILE_NOTIFY_CHANGE_STREAM_WRITE)
+
+/**
+ * Convert Windows/SMB filter/flags to IFS event filter.
+ *
+ * @param[in] smb_filter Windows Completion Filter sent in the SMB
+ *
+ * @return ifs event filter mask
+ */
+static uint32_t
+onefs_notify_smb_filter_to_ifs_filter(uint32_t smb_filter)
+{
+       int i;
+       uint32_t ifs_filter = 0x0;
+
+       for (i=0;i<ARRAY_SIZE(onefs_notify_conv);i++) {
+               if (onefs_notify_conv[i].smb_filter & smb_filter) {
+                       ifs_filter |= onefs_notify_conv[i].ifs_filter;
+               }
+       }
+
+       return ifs_filter;
+}
+
+/**
+ * Convert IFS filter/flags to a Windows notify action.
+ *
+ * Returns Win notification actions, types (1-5).
+ *
+ * @param[in] smb_filter Windows Completion Filter sent in the SMB
+ * @param[in] ifs_filter Returned from the kernel in the ifs_event
+ *
+ * @return 0 if there are no more relevant flags.
+ */
+static int
+onefs_notify_ifs_filter_to_smb_action(uint32_t smb_filter, uint32_t ifs_filter)
+{
+       /* Handle Windows special cases, before modifying events bitmask */
+
+       /* Special case 1: win32api->MoveFile needs to send a modified
+        * notification on the new file, if smb_filter == ATTRIBUTES.
+        * Here we handle the case where two separate ATTR & NAME notifications
+        * have been registered.  We handle the case where both bits are set in
+        * the same registration in onefs_notify_dispatch() */
+       if ((smb_filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) &&
+               !(smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
+               (ifs_filter & NOTE_FILE) && (ifs_filter & NOTE_RENAME_TO))
+       {
+               return NOTIFY_ACTION_MODIFIED;
+       }
+
+       /* Special case 2: Writes need to send a modified
+        * notification on the file, if smb_filter = ATTRIBUTES. */
+       if ((smb_filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) &&
+               (ifs_filter & NOTE_FILE) && (ifs_filter & NOTE_WRITE))
+       {
+               return NOTIFY_ACTION_MODIFIED;
+       }
+
+       /* Loop because some events may be filtered out. Eventually all
+        * relevant events will be taken care of and returned. */
+       while (1) {
+               if (ifs_filter & NOTE_CREATE) {
+                       ifs_filter &= ~NOTE_CREATE;
+                       if ((smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
+                               (ifs_filter & NOTE_FILE))
+                               return NOTIFY_ACTION_ADDED;
+                       if ((smb_filter & FILE_NOTIFY_CHANGE_DIR_NAME) &&
+                               (ifs_filter & NOTE_DIRECTORY))
+                               return NOTIFY_ACTION_ADDED;
+               }
+               else if (ifs_filter & NOTE_DELETE) {
+                       ifs_filter &= ~NOTE_DELETE;
+                       if ((smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
+                               (ifs_filter & NOTE_FILE))
+                               return NOTIFY_ACTION_REMOVED;
+                       if ((smb_filter & FILE_NOTIFY_CHANGE_DIR_NAME) &&
+                               (ifs_filter & NOTE_DIRECTORY))
+                               return NOTIFY_ACTION_REMOVED;
+               }
+               else if (ifs_filter & NOTE_WRITE) {
+                       ifs_filter &= ~NOTE_WRITE;
+                       if ((smb_filter & FILE_NOTIFY_CHANGE_LAST_WRITE) ||
+                               (smb_filter & FILE_NOTIFY_CHANGE_LAST_ACCESS))
+                               return NOTIFY_ACTION_MODIFIED;
+               }
+               else if ((ifs_filter & NOTE_SIZE) || (ifs_filter & NOTE_EXTEND)) {
+                       ifs_filter &= ~NOTE_SIZE;
+                       ifs_filter &= ~NOTE_EXTEND;
+
+                       /* TODO: Do something on NOTE_DIR? */
+                       if ((smb_filter & FILE_NOTIFY_CHANGE_SIZE) &&
+                           (ifs_filter & NOTE_FILE))
+                               return NOTIFY_ACTION_MODIFIED;
+               }
+               else if (ifs_filter & NOTE_ATTRIB) {
+                       ifs_filter &= ~NOTE_ATTRIB;
+                       /* NOTE_ATTRIB needs to be converted to a
+                        * LAST_WRITE as well, because we need to send
+                        * LAST_WRITE when the mtime changes. Looking into
+                        * better alternatives as this causes extra LAST_WRITE
+                        * notifications. We also return LAST_ACCESS as a
+                        * modification to attribs implies this. */
+                       if ((smb_filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) ||
+                               (smb_filter & FILE_NOTIFY_CHANGE_LAST_WRITE) ||
+                               (smb_filter & FILE_NOTIFY_CHANGE_LAST_ACCESS))
+                               return NOTIFY_ACTION_MODIFIED;
+               }
+               else if (ifs_filter & NOTE_LINK) {
+                       ifs_filter &= ~NOTE_LINK;
+                       /* NOTE_LINK will send out NO notifications */
+               }
+               else if (ifs_filter & NOTE_REVOKE) {
+                       ifs_filter &= ~NOTE_REVOKE;
+                       /* NOTE_REVOKE will send out NO notifications */
+               }
+               else if (ifs_filter & NOTE_RENAME_FROM)  {
+                       ifs_filter &= ~NOTE_RENAME_FROM;
+
+                       if (((smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
+                                (ifs_filter & NOTE_FILE)) ||
+                               ((smb_filter & FILE_NOTIFY_CHANGE_DIR_NAME) &&
+                                (ifs_filter & NOTE_DIRECTORY))) {
+                               /* Check if this is a RENAME, not a MOVE */
+                               if (ifs_filter & NOTE_RENAME_SAMEDIR) {
+                                       /* Remove the NOTE_RENAME_SAMEDIR, IFF
+                                        * RENAME_TO is not in this event */
+                                       if (!(ifs_filter & NOTE_RENAME_TO))
+                                               ifs_filter &=
+                                                   ~NOTE_RENAME_SAMEDIR;
+                                       return NOTIFY_ACTION_OLD_NAME;
+                               }
+                               return NOTIFY_ACTION_REMOVED;
+                       }
+               }
+               else if (ifs_filter & NOTE_RENAME_TO) {
+                       ifs_filter &= ~NOTE_RENAME_TO;
+
+                       if (((smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
+                                (ifs_filter & NOTE_FILE)) ||
+                               ((smb_filter & FILE_NOTIFY_CHANGE_DIR_NAME) &&
+                                (ifs_filter & NOTE_DIRECTORY))) {
+                               /* Check if this is a RENAME, not a MOVE */
+                               if (ifs_filter & NOTE_RENAME_SAMEDIR) {
+                                       /* Remove the NOTE_RENAME_SAMEDIR, IFF
+                                        * RENAME_FROM is not in this event */
+                                       if (!(ifs_filter & NOTE_RENAME_FROM))
+                                               ifs_filter &=
+                                                   ~NOTE_RENAME_SAMEDIR;
+                                       return NOTIFY_ACTION_NEW_NAME;
+                               }
+                               return NOTIFY_ACTION_ADDED;
+                       }
+                       /* RAW-NOTIFY shows us that a rename triggers a
+                        * creation time change */
+                       if ((smb_filter & FILE_NOTIFY_CHANGE_CREATION) &&
+                               (ifs_filter & NOTE_FILE))
+                               return NOTIFY_ACTION_MODIFIED;
+               }
+               else if (ifs_filter & NOTE_SECURITY) {
+                       ifs_filter &= ~NOTE_SECURITY;
+
+                       if (smb_filter & FILE_NOTIFY_CHANGE_SECURITY)
+                               return NOTIFY_ACTION_MODIFIED;
+               } else {
+                       /* No relevant flags found */
+                       return 0;
+               }
+       }
+}
+
+/**
+ * Retrieve a directory path of a changed file, relative to the watched dir
+ *
+ * @param[in] wc watch context for the returned event
+ * @param[in] e ifs_event notification returned from the kernel
+ * @param[out] path name relative to the watched dir. This is talloced
+ *                 off of wc and needs to be freed by the caller.
+ *
+ * @return true on success
+ *
+ * TODO: This function currently doesn't handle path names with multiple
+ * encodings.  enc_get_lin_path() should be used in the future to convert
+ * each path segment's encoding to UTF-8
+ */
+static bool
+get_ifs_event_path(struct onefs_notify_watch_context *wc, struct ifs_event *e,
+                  char **path)
+{
+       char *path_buf = NULL;
+       size_t pathlen = 0;
+       int error = 0;
+
+       SMB_ASSERT(path);
+
+       /* Lookup the path from watch_dir through our parent dir */
+       if (e->namelen > 0) {
+               error = lin_get_path(wc->watch_lin,
+                                    e->parent_lin,
+                                    HEAD_SNAPID,
+                                    e->parent_parent_lin,
+                                    e->parent_name_hash,
+                                    &pathlen, &path_buf);
+               if (!error) {
+                       /* Only add slash if a path exists in path_buf from
+                        * lin_get_path call. Windows does not expect a
+                        * leading '/' */
+                       if (pathlen > 0)
+                               *path = talloc_asprintf(wc, "%s/%s",
+                                                       path_buf, e->name);
+                       else
+                               *path = talloc_asprintf(wc, "%s", e->name);
+                       SAFE_FREE(path_buf);
+               }
+       }
+
+       /* If ifs_event didn't return a name, or we errored out of our intial
+        * path lookup, try again using the lin of the changed file */
+       if (!(*path)) {
+               error = lin_get_path(wc->watch_lin,
+                                    e->lin,
+                                    HEAD_SNAPID,
+                                    e->parent_lin,
+                                    e->name_hash,
+                                    &pathlen, &path_buf);
+               if (error) {
+                       /* It's possible that both the lin and the parent lin
+                        * are invalid (or not given) -- we will skip these
+                        * events. */
+                       DEBUG(3,("Path lookup failed. LINS are invalid: "
+                                "e->lin: 0x%llu, e->parent_lin: 0x%llu, "
+                                "e->parent_parent_lin: 0x%llu\n",
+                                e->lin, e->parent_lin, e->parent_parent_lin));
+                       SAFE_FREE(path_buf);
+                       return false;
+               } else {
+                       *path = talloc_asprintf(wc, "%s", path_buf);
+                       DEBUG(5, ("Using path from event LIN = %s\n",
+                           path_buf));
+                       SAFE_FREE(path_buf);
+               }
+       }
+
+       /* Replacement of UNIX slashes with WIN slashes is handled at a
+        * higher layer. */
+
+       return true;
+}
+
+/**
+ * Dispatch one OneFS notify event to the general Samba code
+ *
+ * @param[in] wc watch context for the returned event
+ * @param[in] e event returned from the kernel
+ *
+ * @return nothing
+ */
+static void
+onefs_notify_dispatch(struct onefs_notify_watch_context *wc,
+                     struct ifs_event *e)
+{
+       char *path = NULL;
+       struct notify_event ne;
+
+       DEBUG(5, ("Retrieved ifs event from kernel: lin=%#llx, ifs_events=%#x, "
+                "parent_lin=%#llx, namelen=%d, name=\"%s\"\n",
+                e->lin, e->events, e->parent_lin, e->namelen, e->name));
+
+       /* Check validity of event returned from kernel */
+       if (e->lin == 0) {
+               /* The lin == 0 specifies 1 of 2 cases:
+                * 1) We are out of events. The kernel has a limited
+                *    amount (somewhere near 90000)
+                * 2) Split nodes have merged back and had data written
+                *    to them -- thus we've missed some of those events.  */
+               DEBUG(3, ("We've missed some kernel ifs events!\n"));
+
+               /* Alert higher level to the problem so it returns catch-all
+                * response to the client */
+               ne.path = NULL;
+               ne.action = 0;
+               wc->callback(wc->ctx, wc->private_data, &ne);
+       }
+
+       if (e->lin == wc->watch_lin) {
+               /* Windows doesn't report notifications on root
+                * watched directory */
+               /* TODO: This should be abstracted out to the general layer
+                * instead of being handled in every notify provider */
+               DEBUG(5, ("Skipping notification on root of the watched "
+                        "path.\n"));
+               return;
+       }
+
+       /* Retrieve the full path for the ifs event name */
+       if(!get_ifs_event_path(wc, e, &path)) {
+               DEBUG(3, ("Failed to convert the ifs_event lins to a path. "
+                        "Skipping this event\n"));
+               return;
+       }
+
+       if (!strncmp(path, ".ifsvar", 7)) {
+               /* Skip notifications on file if its in ifs configuration
+                * directory */
+               goto clean;
+       }
+
+       ne.path = path;
+
+       /* Convert ifs event mask to an smb action mask */
+       ne.action = onefs_notify_ifs_filter_to_smb_action(wc->smb_filter,
+                                                         e->events);
+
+       DEBUG(5, ("Converted smb_filter=%#x, ifs_events=%#x, to "
+                 "ne.action = %d, for ne.path = %s\n",
+                 wc->smb_filter, e->events, ne.action, ne.path));
+
+       if (!ne.action)
+               goto clean;
+
+       /* Return notify_event to higher level */
+       wc->callback(wc->ctx, wc->private_data, &ne);
+
+        /* SMB expects a file rename/move to generate three actions, a
+        * rename_from/delete on the from file, a rename_to/create on the to
+        * file, and a modify for the rename_to file. If we have two separate
+        * notifications registered for ATTRIBUTES and FILENAME, this case will
+        * be handled by separate ifs_events in
+        * onefs_notify_ifs_filter_to_smb_action(). If both bits are registered
+        * in the same notification, we must send an extra MODIFIED action
+        * here. */
+       if ((wc->smb_filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) &&
+           (wc->smb_filter & FILE_NOTIFY_CHANGE_FILE_NAME) &&
+           (e->events & NOTE_FILE) && (e->events & NOTE_RENAME_TO))
+       {
+               ne.action = NOTIFY_ACTION_MODIFIED;
+               wc->callback(wc->ctx, wc->private_data, &ne);
+       }
+
+       /* FALLTHROUGH */
+clean:
+       talloc_free(path);
+       return;
+}
+
+/**
+ * Callback when the kernel has some events for us
+ *
+ * Read events off ifs event fd and pass them to our dispatch function
+ *
+ * @param ev context of all tevents registered in the smbd
+ * @param fde tevent struct specific to one ifs event channel
+ * @param flags tevent flags passed when we added our ifs event channel fd to
+ *             the main loop
+ * @param private_data onefs_notify_watch_context specific to this ifs event
+ *                    channel
+ *
+ * @return nothing
+ */
+static void
+onefs_notify_handler(struct event_context *ev,
+                    struct fd_event *fde,
+                    uint16_t flags,
+                    void *private_data)
+{
+       struct onefs_notify_watch_context *wc = NULL;
+       struct ifs_event ifs_events[ONEFS_IFS_EVENT_MAX_NUM];
+       ssize_t nread = 0;
+       int count = 0;
+       int i = 0;
+
+       wc = talloc_get_type(private_data, struct onefs_notify_watch_context);
+
+       /* Read as many ifs events from the notify channel as we can */
+       nread = sys_read(wc->ifs_event_fd, &ifs_events,
+                        ONEFS_IFS_EVENT_MAX_BYTES);
+       if (nread == 0) {
+               DEBUG(0,("No data found while reading ifs event fd?!\n"));
+               return;
+       }
+       if (nread < 0) {
+               DEBUG(0,("Failed to read ifs event data: %s\n",
+                       strerror(errno)));
+               return;
+       }
+
+       count = nread / sizeof(struct ifs_event);
+
+       DEBUG(5, ("Got %d notification events in %d bytes.\n", count, nread));
+
+       /* Dispatch ifs_events one-at-a-time to higher level */
+       for (i=0; i < count; i++) {
+               onefs_notify_dispatch(wc, &ifs_events[i]);
+       }
+}
+
+/**
+ * Destroy the ifs event channel
+ *
+ * This is called from talloc_free() when the generic Samba notify layer frees
+ * the onefs_notify_watch_context.
+ *
+ * @param[in] wc pointer to watch context which is being destroyed
+ *
+ * return 0 on success
+*/
+static int
+onefs_watch_destructor(struct onefs_notify_watch_context *wc)
+{
+       /* The ifs_event_fd will re de-registered from the event loop by
+        * another destructor triggered from the freeing of this wc */
+       close(wc->ifs_event_fd);
+       return 0;
+}
+
+/**
+ * Register a single change notify watch request.
+ *
+ * Open an event listener on a directory to watch for modifications. This
+ * channel is closed by a destructor when the caller calls talloc_free()
+ * on *handle.
+ *
+ * @param[in] vfs_handle handle given to most VFS operations
+ * @param[in] ctx context (conn and tevent) for this connection
+ * @param[in] e filter and path of client's notify request
+ * @param[in] callback function to call when file notification event is received
+ *                    from the kernel, passing that event up to Samba's
+ *                    generalized change notify layer
+ * @param[in] private_data opaque data given to us by the general change notify
+ *                        layer which must be returned in the callback function
+ * @param[out] handle_p handle returned to generalized change notify layer used
+ *                     to close the event channel when notification is
+ *                     cancelled
+ *
+ * @return NT_STATUS_OK unless error
+ */
+NTSTATUS
+onefs_notify_watch(vfs_handle_struct *vfs_handle,
+                  struct sys_notify_context *ctx,
+                  struct notify_entry *e,
+                  void (*callback)(struct sys_notify_context *ctx,
+                                   void *private_data,
+                                   struct notify_event *ev),
+                  void *private_data,
+                  void *handle_p)
+{
+       int ifs_event_fd = -1;
+       uint32_t ifs_filter = 0;
+       uint32_t smb_filter = e->filter;
+       bool watch_tree = !!e->subdir_filter;
+       struct onefs_notify_watch_context *wc = NULL;
+       void **handle = (void **)handle_p;
+       SMB_STRUCT_STAT sbuf;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+
+       /* Fallback to default Samba implementation if kernel CN is disabled */
+       if (!lp_kernel_change_notify(vfs_handle->conn->params)) {
+               (*handle) = NULL;
+               return NT_STATUS_OK;
+       }
+
+       /* The OneFS open path should always give us a valid fd on a directory*/
+       SMB_ASSERT(e->dir_fd >= 0);
+
+       /* Always set e->filter to 0 so we don't fallback on the default change
+        * notify backend. It's not cluster coherent or cross-protocol so we
+        * can't guarantee correctness using it. */
+       e->filter = 0;
+       e->subdir_filter = 0;
+
+       /* Snapshots do not currently allow event listeners. See Isilon
+        * bug 33476 for an example of .snapshot debug spew that can occur. */
+       if (e->dir_id.extid != HEAD_SNAPID)
+               return NT_STATUS_INVALID_PARAMETER;
+
+       /* Convert Completion Filter mask to IFS Event mask */
+       ifs_filter = onefs_notify_smb_filter_to_ifs_filter(smb_filter);
+
+       if (smb_filter & ONEFS_NOTIFY_UNSUPPORTED) {
+               /* One or more of the filter bits could not be fully handled by
+                * the ifs_event system. To be correct, if we cannot service a
+                * bit in the completion filter we should return
+                * NT_STATUS_NOT_IMPLEMENTED to let the client know that they
+                * won't be receiving all the notify events that they asked for.
+                * Unfortunately, WinXP clients cache this error message, stop
+                * trying to send any notify requests at all, and instead return
+                * NOT_IMPLEMENTED to all requesting apps without ever sending a
+                * message to us. Thus we lie, and say we can service all bits,
+                * but simply don't return actions for the filter bits we can't
+                * detect or fully implement. */
+               DEBUG(3,("One or more of the Windows completion filter bits "
+                        "for \"%s\" could not be fully handled by the "
+                        "ifs_event system. The failed bits are "
+                        "smb_filter=%#x\n",
+                        e->path, smb_filter & ONEFS_NOTIFY_UNSUPPORTED));
+       }
+
+       if (ifs_filter == 0) {
+               /* None of the filter bits given are supported by the ifs_event
+                * system. Don't create a kernel notify channel, but mock
+                * up a fake handle for the caller. */
+               DEBUG(3,("No bits in the Windows completion filter could be "
+                        "translated to ifs_event mask for \"%s\", "
+                        "smb_filter=%#x\n", e->path, smb_filter));
+               (*handle) = NULL;
+               return NT_STATUS_OK;
+       }
+
+       /* Register an ifs event channel for this watch request */
+       ifs_event_fd = ifs_create_listener(watch_tree ?
+                                          EVENT_RECURSIVE :
+                                          EVENT_CHILDREN,
+                                          ifs_filter,
+                                          e->dir_fd);
+       if (ifs_event_fd < 0) {
+               DEBUG(0,("Failed to create listener for %s with \"%s\". "
+                       "smb_filter=0x%x, ifs_filter=0x%x, watch_tree=%u\n",
+                       strerror(errno), e->path, smb_filter, ifs_filter,
+                       watch_tree));
+               return map_nt_error_from_unix(errno);
+       }
+
+       /* Create a watch context to track this change notify request */
+       wc = talloc(ctx, struct onefs_notify_watch_context);
+       if (wc == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto err;
+       }
+
+       /* Get LIN for directory */
+       if (sys_fstat(e->dir_fd, &sbuf)) {
+               DEBUG(0, ("stat on directory fd failed: %s\n",
+                         strerror(errno)));
+               status = map_nt_error_from_unix(errno);
+               goto err;
+       }
+
+       if (sbuf.st_ino == 0) {
+               DEBUG(0, ("0 LIN found!\n"));
+               goto err;
+       }
+
+       wc->ctx = ctx;
+       wc->watch_fd = e->dir_fd;
+       wc->watch_lin = sbuf.st_ino;
+       wc->ifs_event_fd = ifs_event_fd;
+       wc->ifs_filter = ifs_filter;
+       wc->smb_filter = smb_filter;
+       wc->callback = callback;
+       wc->private_data = private_data;
+       wc->path = talloc_strdup(wc, e->path);
+       if (wc->path == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto err;
+       }
+
+       (*handle) = wc;
+
+       /* The caller frees the handle to stop watching */
+       talloc_set_destructor(wc, onefs_watch_destructor);
+
+       /* Add a tevent waiting for the ifs event fd to be readable */
+       event_add_fd(ctx->ev, wc, wc->ifs_event_fd, EVENT_FD_READ,
+                    onefs_notify_handler, wc);
+
+       DEBUG(10, ("Watching for changes on \"%s\" smb_filter=0x%x, "
+                  "ifs_filter=0x%x, watch_tree=%d, ifs_event_fd=%d, "
+                  "dir_fd=%d, dir_lin=0x%llx\n",
+                  e->path, smb_filter, ifs_filter, watch_tree,
+                  ifs_event_fd, e->dir_fd, sbuf.st_ino));
+
+       return NT_STATUS_OK;
+
+err:
+       talloc_free(wc);
+       SMB_ASSERT(ifs_event_fd >= 0);
+       close(ifs_event_fd);
+       return status;
+}
diff --git a/source3/modules/onefs_shadow_copy.c b/source3/modules/onefs_shadow_copy.c
new file mode 100644 (file)
index 0000000..5b02534
--- /dev/null
@@ -0,0 +1,782 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * OneFS shadow copy implementation that utilizes the file system's native
+ * snapshot support. This file does all of the heavy lifting.
+ *
+ * Copyright (C) Dave Richards, 2007
+ * Copyright (C) Tim Prouty, 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ifs/ifs_syscalls.h>
+#include <sys/types.h>
+#include <sys/isi_enc.h>
+#include <sys/module.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <search.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "onefs_shadow_copy.h"
+
+/* Copied from ../include/proto.h */
+void become_root(void);
+void unbecome_root(void);
+
+#define        SNAPSHOT_DIRECTORY      ".snapshot"
+
+#define        MAX_VERSIONS            64
+
+/**
+ * A snapshot object.
+ *
+ * During snapshot enumeration, snapshots are represented by snapshot objects
+ * and are stored in a snapshot set.  The snapshot object represents one
+ * snapshot within the set.  An important thing to note about the set is that
+ * the key of the snapshot object is the tv_sec component of the is_time
+ * member.  What this means is that we only store one snapshot for each
+ * second.  If multiple snapshots were created within the same second, we'll
+ * keep the earliest one and ignore the rest.  Thus, not all snapshots are
+ * necessarily retained.
+ */
+struct osc_snapshot {
+       char *                  is_name;
+       struct timespec         is_time;
+       struct osc_snapshot *   is_next;
+};
+
+/**
+ * A snapshot context object.
+ *
+ * Snapshot contexts are used to pass information throughout the snapshot
+ * enumeration routines.  As a result, snapshot contexts are stored on the
+ * stack and are both created and destroyed within a single API function.
+ */
+struct osc_snapshot_ctx {
+       void *          osc_set;
+       struct timespec osc_mtime;
+};
+
+/**
+ * A directory context.
+ *
+ * Directory contexts are the underlying data structured used to enumerate
+ * snapshot versions.  An opendir()-, readdir()- and closedir()-like interface
+ * is provided that utilizes directory contexts.  At the API level, directory
+ * contexts are passed around as void pointers.  Directory contexts are
+ * allocated on the heap and their lifetime is dictated by the calling
+ * routine.
+ */
+struct osc_directory_ctx {
+       size_t          idc_pos;
+       size_t          idc_len;
+       size_t          idc_size;
+       char **         idc_version;
+};
+
+/**
+ * Return a file descriptor to the STF names directory.
+ *
+ * Opens the STF names directory and returns a file descriptor to it.
+ * Subsequent calls return the same value (avoiding the need to re-open the
+ * directory repeatedly).  Caveat caller: don't close the file descriptor or
+ * you will be shot!
+ */
+static int
+osc_get_names_directory_fd(void)
+{
+       static int fd = -1;
+
+       if (fd == -1) {
+               become_root();
+               fd = pctl2_lin_open(STF_NAMES_LIN, HEAD_SNAPID, O_RDONLY);
+               unbecome_root();
+       }
+
+       return fd;
+}
+
+/**
+ * Compare two time values.
+ *
+ * Accepts two struct timespecs and compares the tv_sec components of these
+ * values.  It returns -1 if the first value preceeds the second, 0 if they
+ * are equal and +1 if the first values succeeds the second.
+ */
+static int
+osc_time_compare(const struct timespec *tsp1, const struct timespec *tsp2)
+{
+       return (tsp1->tv_sec < tsp2->tv_sec) ? -1 :
+              (tsp1->tv_sec > tsp2->tv_sec) ? +1 : 0;
+}
+
+/**
+ * Compare two timespec values.
+ *
+ * Compares two timespec values.  It returns -1 if the first value preceeds
+ * the second, 0 if they are equal and +1 if the first values succeeds the
+ * second.
+ */
+static int
+osc_timespec_compare(const struct timespec *tsp1, const struct timespec *tsp2)
+{
+       return (tsp1->tv_sec  < tsp2->tv_sec)  ? -1 :
+              (tsp1->tv_sec  > tsp2->tv_sec)  ? +1 :
+              (tsp1->tv_nsec < tsp2->tv_nsec) ? -1 :
+              (tsp1->tv_nsec > tsp2->tv_nsec) ? +1 : 0;
+}
+
+/**
+ * Determine whether a timespec value is zero.
+ *
+ * Return 1 if the struct timespec provided is zero and 0 otherwise.
+ */
+static int
+osc_timespec_is_zero(const struct timespec *tsp)
+{
+       return (tsp->tv_sec  == 0) &&
+              (tsp->tv_nsec == 0);
+}
+
+/**
+ * Create a snapshot object.
+ *
+ * Allocates and initializes a new snapshot object.  In addition to allocating
+ * space for the snapshot object itself, space is allocated for the snapshot
+ * name.  Both the name and time are then copied to the new object.
+ */
+static struct osc_snapshot *
+osc_snapshot_create(const char *name, const struct timespec *tsp)
+{
+       struct osc_snapshot *isp;
+
+       isp = malloc(sizeof *isp);
+       if (isp == NULL)
+               goto out;
+
+       isp->is_name = malloc(strlen(name) + 1);
+       if (isp->is_name == NULL) {
+               free(isp);
+               isp = NULL;
+               goto out;
+       }
+
+       strcpy(isp->is_name, name);
+       isp->is_time = *tsp;
+       isp->is_next = NULL;
+
+ out:
+       return isp;
+}
+
+/**
+ * Destroy a snapshot object.
+ *
+ * Frees both the name and the snapshot object itself.  Appropriate NULL
+ * checking is performed because counting on free to do so is immoral.
+ */
+static void
+osc_snapshot_destroy(struct osc_snapshot *isp)
+{
+       if (isp != NULL) {
+               if (isp->is_name != NULL)
+                       free(isp->is_name);
+               free(isp);
+       }
+}
+
+/**
+ * Destroy all snapshots in the snapshot list.
+ *
+ * Calls osc_snapshot_destroy() on each snapshot in the list.
+ */
+static void
+osc_snapshot_destroy_list(struct osc_snapshot *isp)
+{
+       struct osc_snapshot *tmp;
+
+       while (isp != NULL) {
+               tmp = isp;
+               isp = isp->is_next;
+               osc_snapshot_destroy(tmp);
+       }
+}
+
+/**
+ * Compare two snapshot objects.
+ *
+ * Compare two snapshot objects.  It is really just a wrapper for
+ * osc_time_compare(), which compare the time value of the two snapshots.
+ * N.B. time value in this context refers only to the tv_sec component.
+ */
+static int
+osc_snapshot_compare(const void *vp1, const void *vp2)
+{
+       const struct osc_snapshot *isp1 = vp1;
+       const struct osc_snapshot *isp2 = vp2;
+
+       return -osc_time_compare(&isp1->is_time, &isp2->is_time);
+}
+
+/**
+ * Insert a snapshot into the snapshot set.
+ *
+ * Inserts a new snapshot into the snapshot set.  The key for snapshots is
+ * their creation time (it's actually the seconds portion of the creation
+ * time).  If a duplicate snapshot is found in the set, the new snapshot is
+ * added to a linked list of snapshots for that second.
+ */
+static void
+osc_snapshot_insert(struct osc_snapshot_ctx *oscp, const char *name,
+    const struct timespec *tsp, int *errorp)
+{
+       struct osc_snapshot *isp1;
+       struct osc_snapshot **ispp;
+
+       isp1 = osc_snapshot_create(name, tsp);
+       if (isp1 == NULL) {
+               *errorp = 1;
+               return;
+       }
+
+       ispp = tsearch(isp1, &oscp->osc_set, osc_snapshot_compare);
+       if (ispp != NULL) {
+               struct osc_snapshot *isp2 = *ispp;
+
+               /* If this is the only snapshot for this second, we're done. */
+               if (isp2 == isp1)
+                       return;
+
+               /* Collision: add the new snapshot to the list. */
+               isp1->is_next = isp2->is_next;
+               isp2->is_next = isp1;
+
+       } else
+               *errorp = 1;
+
+}
+
+/**
+ * Process the next snapshot.
+ *
+ * Called for (almost) every entry in a .snapshot directory, ("." and ".." are
+ * ignored in osc_process_snapshot_directory()).  All other entries are passed
+ * to osc_process_snapshot(), however.  These entries can fall into one of two
+ * categories: snapshot names and snapshot aliases.  We only care about
+ * snapshot names (as aliases are just redundant entries).  Once it verifies
+ * that name represents a valid snapshot name, it calls fstat() to get the
+ * creation time of the snapshot and then calls osc_snapshot_insert() to add
+ * this entry to the snapshot set.
+ */
+static void
+osc_process_snapshot(struct osc_snapshot_ctx *oscp, const char *name,
+    int *errorp)
+{
+       int fd;
+       struct stf_stat stf_stat;
+       struct stat stbuf;
+
+       fd = osc_get_names_directory_fd();
+       if (fd == -1)
+               goto out;
+
+       fd = enc_openat(fd, name, ENC_DEFAULT, O_RDONLY);
+       if (fd == -1)
+               goto out;
+
+       memset(&stf_stat, 0, sizeof stf_stat);
+       if (ifs_snap_stat(fd, &stf_stat) == -1)
+               goto out;
+
+       if (stf_stat.sf_type != SF_STF)
+               goto out;
+
+       if (fstat(fd, &stbuf) == -1)
+               goto out;
+
+       osc_snapshot_insert(oscp, name, &stbuf.st_birthtimespec, errorp);
+
+ out:
+       if (fd != -1)
+               close(fd);
+}
+
+/**
+ * Process a snapshot directory.
+ *
+ * Opens the snapshot directory and calls osc_process_snapshot() for each
+ * entry.  (Well ok, "." and ".."  are ignored.)  The goal here is to add all
+ * snapshots in the directory to the snapshot set.
+ */
+static void
+osc_process_snapshot_directory(struct osc_snapshot_ctx *oscp, int *errorp)
+{
+       int fd;
+       struct stat stbuf;
+       DIR *dirp;
+       struct dirent *dp;
+
+       fd = osc_get_names_directory_fd();
+       if (fd == -1)
+               goto out;
+
+       if (fstat(fd, &stbuf) == -1)
+               goto out;
+
+       dirp = opendir(SNAPSHOT_DIRECTORY);
+       if (dirp == NULL)
+               goto out;
+
+       for (;;) {
+               dp = readdir(dirp);
+               if (dp == NULL)
+                       break;
+
+               if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+                   (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+                       continue;
+
+               osc_process_snapshot(oscp, dp->d_name, errorp);
+               if (*errorp)
+                       break;
+       }
+
+       closedir(dirp);
+
+       if (!*errorp)
+               oscp->osc_mtime = stbuf.st_mtimespec;
+
+ out:
+       return;
+}
+
+/**
+ * Initialize a snapshot context object.
+ *
+ * Clears all members of the context object.
+ */
+static void
+osc_snapshot_ctx_init(struct osc_snapshot_ctx *oscp)
+{
+       memset(oscp, 0, sizeof *oscp);
+}
+
+/**
+ * Desoy a snapshot context object.
+ *
+ * Frees all snapshots associated with the snapshot context and then calls
+ * osc_snapshot_ctx_init() to re-initialize the context object.
+ */
+static void
+osc_snapshot_ctx_clean(struct osc_snapshot_ctx *oscp)
+{
+       struct osc_snapshot *tmp;
+
+       while (oscp->osc_set != NULL) {
+               tmp = *(void **)oscp->osc_set;
+               tdelete(tmp, &oscp->osc_set, osc_snapshot_compare);
+               osc_snapshot_destroy_list(tmp);
+       }
+
+       osc_snapshot_ctx_init(oscp);
+}
+
+/**
+ * Return the "global" snapshot context.
+ *
+ * We maintain a single open snapshot context.  Return a pointer to it.
+ */
+static struct osc_snapshot_ctx *
+osc_get_snapshot_ctx(void)
+{
+       static struct osc_snapshot_ctx osc = { 0, { 0, 0 } };
+
+       return &osc;
+}
+
+/**
+ * Determine whether a snapshot context is still valid.
+ *
+ * "Valid" in this context means "reusable".  We can re-use a previous
+ * snapshot context iff we successfully built a previous snapshot context
+ * and no snapshots have been created or deleted since we did so.
+ * A "names" directory exists within our snapshot
+ * implementation in which all snapshot names are entered.  Each time a
+ * snapshot is created or deleted, an entry must be added or removed.
+ * When this happens the modification time on the "names" directory
+ * changes.  Therefore, a snapshot context is valid iff the context
+ * pointer is non-NULL, the cached modification time is non-zero
+ * (zero means uninitialized), and the modification time of the "names"
+ * directory matches the cached value.
+ */
+static int
+osc_snapshot_ctx_is_valid(struct osc_snapshot_ctx *oscp)
+{
+       int fd;
+       struct stat stbuf;
+
+       if (oscp == NULL)
+               return 0;
+
+       if (osc_timespec_is_zero(&oscp->osc_mtime))
+               return 0;
+
+       fd = osc_get_names_directory_fd();
+       if (fd == -1)
+               return 0;
+
+       if (fstat(fd, &stbuf) == -1)
+               return 0;
+
+       if (osc_timespec_compare(&oscp->osc_mtime, &stbuf.st_mtimespec) != 0)
+               return 0;
+
+       return 1;
+}
+
+/**
+ * Create and initialize a directory context.
+ *
+ * Allocates a directory context from the heap and initializes it.
+ */
+static struct osc_directory_ctx *
+osc_directory_ctx_create(void)
+{
+       struct osc_directory_ctx *idcp;
+
+       idcp = malloc(sizeof *idcp);
+       if (idcp != NULL)
+               memset(idcp, 0, sizeof *idcp);
+
+       return idcp;
+}
+
+/**
+ * Destroy a directory context.
+ *
+ * Frees any versions associated with the directory context and then frees the
+ * context itself.
+ */
+static void
+osc_directory_ctx_destroy(struct osc_directory_ctx *idcp)
+{
+       int i;
+
+       if (idcp == NULL)
+               return;
+
+       for (i = 0; i < idcp->idc_len; i++)
+               free(idcp->idc_version[i]);
+
+       free(idcp);
+}
+
+/**
+ * Expand the size of a directory context's version list.
+ *
+ * If osc_directory_ctx_append_version() detects that the version list is too
+ * small to accomodate a new version string, it called
+ * osc_directory_ctx_expand_version_list() to expand the version list.
+ */
+static void
+osc_directory_ctx_expand_version_list(struct osc_snapshot_ctx *oscp,
+    struct osc_directory_ctx *idcp, int *errorp)
+{
+       size_t size;
+       char **cpp;
+
+       size = idcp->idc_size * 2 ?: 1;
+
+       cpp = realloc(idcp->idc_version, size * sizeof (char *));
+       if (cpp == NULL) {
+               *errorp = 1;
+               return;
+       }
+
+       idcp->idc_size = size;
+       idcp->idc_version = cpp;
+}
+
+/**
+ * Append a new version to a directory context.
+ *
+ * Appends a snapshot version to the
+ * directory context's version list.
+ */
+static void
+osc_directory_ctx_append_version(struct osc_snapshot_ctx *oscp,
+    struct osc_directory_ctx *idcp, const struct timespec *tsp, int *errorp)
+{
+       char *cp;
+       struct tm *tmp;
+       char text[64];
+
+       if (idcp->idc_len >= MAX_VERSIONS)
+               return;
+
+       if (idcp->idc_len >= idcp->idc_size) {
+               osc_directory_ctx_expand_version_list(oscp, idcp, errorp);
+               if (*errorp)
+                       return;
+       }
+
+       tmp = gmtime(&tsp->tv_sec);
+       if (tmp == NULL) {
+               *errorp = 1;
+               return;
+       }
+
+       snprintf(text, sizeof text,
+           "@GMT-%04u.%02u.%02u-%02u.%02u.%02u",
+           tmp->tm_year + 1900,
+           tmp->tm_mon + 1,
+           tmp->tm_mday,
+           tmp->tm_hour,
+           tmp->tm_min,
+           tmp->tm_sec);
+
+       cp = malloc(strlen(text) + 1);
+       if (cp == NULL) {
+               *errorp = 1;
+               return;
+       }
+
+       strcpy(cp, text);
+
+       idcp->idc_version[idcp->idc_len++] = cp;
+}
+
+/**
+ * Make a directory context from a snapshot context.
+ *
+ * Once a snapshot context has been completely filled-in,
+ * osc_make_directory_ctx() is used to build a directory context from it.  The
+ * idea here is to create version for each snapshot in the snapshot set.
+ */
+static void
+osc_make_directory_ctx(struct osc_snapshot_ctx *oscp,
+    struct osc_directory_ctx *idcp, int *errorp)
+{
+       static void
+       walk(const void *vp, VISIT v, int level)
+       {
+               const struct osc_snapshot *isp;
+
+               if ((v != postorder && v != leaf) || *errorp)
+                       return;
+
+               isp = *(const struct osc_snapshot **)(u_long)vp;
+
+               osc_directory_ctx_append_version(oscp, idcp, &isp->is_time,
+                   errorp);
+       }
+
+       twalk(oscp->osc_set, walk);
+}
+
+/**
+ * Open a version directory.
+ *
+ * Opens a version directory.  What this really means is that
+ * osc_version_opendir() returns a handle to a directory context, which can be
+ * used to retrieve version strings.
+ */
+void *
+osc_version_opendir(void)
+{
+       int error = 0;
+       struct osc_directory_ctx *idcp;
+       struct osc_snapshot_ctx *oscp;
+
+       idcp = osc_directory_ctx_create();
+       if (idcp == NULL)
+               goto error_out;
+
+       oscp = osc_get_snapshot_ctx();
+
+       if (!osc_snapshot_ctx_is_valid(oscp)) {
+               osc_snapshot_ctx_clean(oscp);
+               osc_process_snapshot_directory(oscp, &error);
+               if (error)
+                       goto error_out;
+       }
+
+       osc_make_directory_ctx(oscp, idcp, &error);
+       if (error)
+               goto error_out;
+
+       goto out;
+
+ error_out:
+       if (idcp != NULL) {
+               osc_directory_ctx_destroy(idcp);
+               idcp = NULL;
+       }
+
+ out:
+       return (void *)idcp;
+}
+
+/**
+ * Read the next version directory entry.
+ *
+ * Returns the name of the next version in the version directory, or NULL if
+ * we're at the end of the directory.  What this really does is return the
+ * next version from the version list stored in the directory context.
+ */
+char *
+osc_version_readdir(void *vp)
+{
+       struct osc_directory_ctx *idcp = vp;
+
+       if (idcp == NULL)
+               return NULL;
+
+       if (idcp->idc_pos >= idcp->idc_len)
+               return NULL;
+
+       return idcp->idc_version[idcp->idc_pos++];
+}
+
+/**
+ * Close the version directory.
+ *
+ * Destroys the underlying directory context.
+ */
+void
+osc_version_closedir(void *vp)
+{
+       struct osc_directory_ctx *idcp = vp;
+
+       if (idcp != NULL)
+               osc_directory_ctx_destroy(idcp);
+}
+
+/**
+ * Canonicalize a path.
+ *
+ * Converts paths of the form @GMT-.. to paths of the form ../.snapshot/..
+ * It's not the prettiest routine I've ever written, but what the heck?
+ */
+char *
+osc_canonicalize_path(const char *path, char *snap_component)
+{
+       int error = 0;
+       struct osc_snapshot_ctx *oscp;
+       struct tm tm;
+       int n;
+       struct osc_snapshot is;
+       struct osc_snapshot **ispp;
+       struct osc_snapshot *isp;
+       char *cpath = NULL;
+       char *cpath2 = NULL;
+       const char *snap_component_orig = snap_component;
+       struct stat sb;
+
+       oscp = osc_get_snapshot_ctx();
+
+       if (!osc_snapshot_ctx_is_valid(oscp)) {
+               osc_snapshot_ctx_clean(oscp);
+               osc_process_snapshot_directory(oscp, &error);
+               if (error)
+                       goto out;
+       }
+
+       memset(&tm, 0, sizeof tm);
+       n = sscanf(snap_component,
+           "@GMT-%4u.%2u.%2u-%2u.%2u.%2u",
+           &tm.tm_year,
+           &tm.tm_mon,
+           &tm.tm_mday,
+           &tm.tm_hour,
+           &tm.tm_min,
+           &tm.tm_sec);
+       if (n != 6)
+               goto out;
+
+       tm.tm_year -= 1900;
+       tm.tm_mon -= 1;
+
+       is.is_name = NULL;
+       is.is_time.tv_sec = timegm(&tm);
+       is.is_time.tv_nsec = 0;
+
+       ispp = tfind(&is, &oscp->osc_set, osc_snapshot_compare);
+       if (ispp == NULL)
+               goto out;
+       isp = *ispp;
+
+       /* Determine the path after "@GMT-..." */
+       while (*snap_component != '/' && *snap_component != '\0')
+               snap_component++;
+
+       while (*snap_component == '/')
+               snap_component++;
+
+       cpath = malloc(strlen(SNAPSHOT_DIRECTORY) + strlen(isp->is_name) +
+           strlen(path) + 3);
+
+       if (cpath == NULL)
+               goto out;
+
+       /*
+        * Use the first snapshot that has a successful stat for the requested
+        * path.
+        */
+       while (true) {
+
+               sprintf(cpath, "%s/%s", SNAPSHOT_DIRECTORY, isp->is_name);
+
+               /* Append path before "@GMT-..." */
+               if (snap_component_orig != path) {
+                       strcat(cpath, "/");
+                       strncat(cpath, path, snap_component_orig - path);
+               }
+
+               /* Append path after "@GMT-..." */
+               if (*snap_component != '\0') {
+                       strcat(cpath, "/");
+                       strcat(cpath, snap_component);
+               }
+
+               /* If there is a valid snapshot for this file, we're done. */
+               if (stat(cpath, &sb) == 0)
+                       break;
+
+               /* Try the next snapshot. If this was the last one, give up. */
+               isp = isp->is_next;
+               if (isp == NULL)
+                       break;
+
+               /* If the realloc fails, give up. */
+               cpath2 = realloc(cpath, strlen(SNAPSHOT_DIRECTORY) +
+                   strlen(isp->is_name) + strlen(path) + 3);
+               if (cpath2 == NULL)
+                       break;
+               cpath = cpath2;
+       }
+
+ out:
+       return cpath;
+}
diff --git a/source3/modules/onefs_shadow_copy.h b/source3/modules/onefs_shadow_copy.h
new file mode 100644 (file)
index 0000000..6415a4b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * OneFS shadow copy implementation that utilizes the file system's native
+ * snapshot support.
+ *
+ * Copyright (C) Dave Richards, 2007
+ * Copyright (C) Tim Prouty, 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ONEFS_SHADOW_COPY_H
+#define         ONEFS_SHADOW_COPY_H
+
+void *osc_version_opendir(void);
+char *osc_version_readdir(void *vp);
+void osc_version_closedir(void *vp);
+char *osc_canonicalize_path(const char *path, char *snap_component);
+
+#endif /* ONEFS_SHADOW_COPY_H */
index 9616ca48d568395855612015b5c074840335d45e..6e2794399d8afe9fad4aec282c137f969a4c3e02 100644 (file)
@@ -160,18 +160,26 @@ int onefs_rename(vfs_handle_struct *handle, const char *oldname,
        char *nbase = NULL;
        char *nsname = NULL;
 
+       START_PROFILE(syscall_rename_at);
+
        frame = talloc_stackframe();
 
        ret = onefs_is_stream(oldname, &obase, &osname, &old_is_stream);
-       if (ret)
+       if (ret) {
+               END_PROFILE(syscall_rename_at);
                return ret;
+       }
 
        ret = onefs_is_stream(newname, &nbase, &nsname, &new_is_stream);
-       if (ret)
+       if (ret) {
+               END_PROFILE(syscall_rename_at);
                return ret;
+       }
 
        if (!old_is_stream && !new_is_stream) {
-               return SMB_VFS_NEXT_RENAME(handle, oldname, newname);
+               ret = SMB_VFS_NEXT_RENAME(handle, oldname, newname);
+               END_PROFILE(syscall_rename_at);
+               return ret;
        }
 
        dir_fd = get_stream_dir_fd(handle->conn, obase, NULL);
@@ -192,6 +200,8 @@ int onefs_rename(vfs_handle_struct *handle, const char *oldname,
        }
 
  done:
+       END_PROFILE(syscall_rename_at);
+
        saved_errno = errno;
        if (dir_fd >= 0) {
                close(dir_fd);
@@ -220,7 +230,7 @@ static void merge_stat(SMB_STRUCT_STAT *stream_sbuf,
 static void onefs_adjust_stat_time(vfs_handle_struct *handle, const char *fname,
                                   SMB_STRUCT_STAT *sbuf)
 {
-       struct onefs_vfs_config cfg;
+       struct onefs_vfs_share_config cfg;
        struct timeval tv_now = {0, 0};
        bool static_mtime = False;
        bool static_atime = False;
index 6f93d9ff971a915735aeb618e737cae25b0c463c..43ebed8d443c3c7ccd23a86931415d22e32add8d 100644 (file)
@@ -95,6 +95,8 @@ int onefs_sys_create_file(connection_struct *conn,
        uint32_t onefs_dos_attributes;
        struct ifs_createfile_flags cf_flags = CF_FLAGS_NONE;
 
+       START_PROFILE(syscall_createfile);
+
        /* Setup security descriptor and get secinfo. */
        if (sd != NULL) {
                NTSTATUS status;
@@ -123,17 +125,53 @@ int onefs_sys_create_file(connection_struct *conn,
        /* Convert samba dos flags to UF_DOS_* attributes. */
        onefs_dos_attributes = dos_attributes_to_stat_dos_flags(dos_flags);
 
+       /**
+        * Deal with kernel creating Default ACLs. (Isilon bug 47447.)
+        *
+        * 1) "nt acl support = no", default_acl = no
+        * 2) "inherit permissions = yes", default_acl = no
+        */
+       if (lp_nt_acl_support(SNUM(conn)) && !lp_inherit_perms(SNUM(conn)))
+               cf_flags = cf_flags_or(cf_flags, CF_FLAGS_DEFAULT_ACL);
+
+       /*
+        * Some customer workflows require the execute bit to be ignored.
+        */
+       if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
+                        PARM_ALLOW_EXECUTE_ALWAYS,
+                        PARM_ALLOW_EXECUTE_ALWAYS_DEFAULT) &&
+           (open_access_mask & FILE_EXECUTE)) {
+
+               DEBUG(3, ("Stripping execute bit from %s: (0x%x)\n", path,
+                         open_access_mask));
+
+               /* Strip execute. */
+               open_access_mask &= ~FILE_EXECUTE;
+
+               /*
+                * Add READ_DATA, so we're not left with desired_access=0. An
+                * execute call should imply the client will read the data.
+                */
+               open_access_mask |= FILE_READ_DATA;
+
+               DEBUGADD(3, ("New stripped access mask: 0x%x\n",
+                            open_access_mask));
+       }
+
        DEBUG(10,("onefs_sys_create_file: base_fd = %d, "
-                 "open_access_mask = 0x%x, flags = 0x%x, mode = 0x%x, "
+                 "open_access_mask = 0x%x, flags = 0x%x, mode = 0%o, "
                  "desired_oplock = %s, id = 0x%x, secinfo = 0x%x, sd = %p, "
-                 "dos_attributes = 0x%x, path = %s\n", base_fd,
+                 "dos_attributes = 0x%x, path = %s, "
+                 "default_acl=%s\n", base_fd,
                  (unsigned int)open_access_mask,
                  (unsigned int)flags,
                  (unsigned int)mode,
                  onefs_oplock_str(onefs_oplock),
                  (unsigned int)id,
                  (unsigned int)secinfo, sd,
-                 (unsigned int)onefs_dos_attributes, path));
+                 (unsigned int)onefs_dos_attributes, path,
+                 cf_flags_and_bool(cf_flags, CF_FLAGS_DEFAULT_ACL) ?
+                     "true" : "false"));
 
        /* Initialize smlock struct for files/dirs but not internal opens */
        if (!(oplock_request & INTERNAL_OPEN_ONLY)) {
@@ -144,15 +182,6 @@ int onefs_sys_create_file(connection_struct *conn,
 
        smlock_dump(10, psml);
 
-       /**
-        * Deal with kernel creating Default ACLs. (Isilon bug 47447.)
-        *
-        * 1) "nt acl support = no", default_acl = no
-        * 2) "inherit permissions = yes", default_acl = no
-        */
-       if (lp_nt_acl_support(SNUM(conn)) && !lp_inherit_perms(SNUM(conn)))
-               cf_flags = cf_flags_or(cf_flags, CF_FLAGS_DEFAULT_ACL);
-
        ret_fd = ifs_createfile(base_fd, path,
            (enum ifs_ace_rights)open_access_mask, flags & ~O_ACCMODE, mode,
            onefs_oplock, id, psml, secinfo, pifs_sd, onefs_dos_attributes,
@@ -169,11 +198,278 @@ int onefs_sys_create_file(connection_struct *conn,
        }
 
  out:
+       END_PROFILE(syscall_createfile);
        aclu_free_sd(pifs_sd, false);
 
        return ret_fd;
 }
 
+/**
+ * FreeBSD based sendfile implementation that allows for atomic semantics.
+ */
+static ssize_t onefs_sys_do_sendfile(int tofd, int fromfd,
+    const DATA_BLOB *header, SMB_OFF_T offset, size_t count, bool atomic)
+{
+       size_t total=0;
+       struct sf_hdtr hdr;
+       struct iovec hdtrl;
+       size_t hdr_len = 0;
+       int flags = 0;
+
+       if (atomic) {
+               flags = SF_ATOMIC;
+       }
+
+       hdr.headers = &hdtrl;
+       hdr.hdr_cnt = 1;
+       hdr.trailers = NULL;
+       hdr.trl_cnt = 0;
+
+       /* Set up the header iovec. */
+       if (header) {
+               hdtrl.iov_base = header->data;
+               hdtrl.iov_len = hdr_len = header->length;
+       } else {
+               hdtrl.iov_base = NULL;
+               hdtrl.iov_len = 0;
+       }
+
+       total = count;
+       while (total + hdtrl.iov_len) {
+               SMB_OFF_T nwritten;
+               int ret;
+
+               /*
+                * FreeBSD sendfile returns 0 on success, -1 on error.
+                * Remember, the tofd and fromfd are reversed..... :-).
+                * nwritten includes the header data sent.
+                */
+
+               do {
+                       ret = sendfile(fromfd, tofd, offset, total, &hdr,
+                                      &nwritten, flags);
+               } while (ret == -1 && errno == EINTR);
+
+               /* On error we're done. */
+               if (ret == -1) {
+                       return -1;
+               }
+
+               /*
+                * If this was an ATOMIC sendfile, nwritten doesn't
+                * necessarily indicate an error.  It could mean count > than
+                * what sendfile can handle atomically (usually 64K) or that
+                * there was a short read due to the file being truncated.
+                */
+               if (nwritten == 0) {
+                       return atomic ? 0 : -1;
+               }
+
+               /*
+                * An atomic sendfile should never send partial data!
+                */
+               if (atomic && nwritten != total + hdtrl.iov_len) {
+                       DEBUG(0,("Atomic sendfile() sent partial data: "
+                                "%llu of %d\n", nwritten,
+                                total + hdtrl.iov_len));
+                       return -1;
+               }
+
+               /*
+                * If this was a short (signal interrupted) write we may need
+                * to subtract it from the header data, or null out the header
+                * data altogether if we wrote more than hdtrl.iov_len bytes.
+                * We change nwritten to be the number of file bytes written.
+                */
+
+               if (hdtrl.iov_base && hdtrl.iov_len) {
+                       if (nwritten >= hdtrl.iov_len) {
+                               nwritten -= hdtrl.iov_len;
+                               hdtrl.iov_base = NULL;
+                               hdtrl.iov_len = 0;
+                       } else {
+                               hdtrl.iov_base =
+                                   (caddr_t)hdtrl.iov_base + nwritten;
+                               hdtrl.iov_len -= nwritten;
+                               nwritten = 0;
+                       }
+               }
+               total -= nwritten;
+               offset += nwritten;
+       }
+       return count + hdr_len;
+}
+
+/**
+ * Handles the subtleties of using sendfile with CIFS.
+ */
+ssize_t onefs_sys_sendfile(connection_struct *conn, int tofd, int fromfd,
+                          const DATA_BLOB *header, SMB_OFF_T offset,
+                          size_t count)
+{
+       bool atomic = false;
+       ssize_t ret = 0;
+
+       START_PROFILE_BYTES(syscall_sendfile, count);
+
+       if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
+                        PARM_ATOMIC_SENDFILE,
+                        PARM_ATOMIC_SENDFILE_DEFAULT)) {
+               atomic = true;
+       }
+
+       /* Try the sendfile */
+       ret = onefs_sys_do_sendfile(tofd, fromfd, header, offset, count,
+                                   atomic);
+
+       /* If the sendfile wasn't atomic, we're done. */
+       if (!atomic) {
+               DEBUG(10, ("non-atomic sendfile read %ul bytes", ret));
+               END_PROFILE(syscall_sendfile);
+               return ret;
+       }
+
+       /*
+        * Atomic sendfile takes care to not write anything to the socket
+        * until all of the requested bytes have been read from the file.
+        * There are two atomic cases that need to be handled.
+        *
+        *  1. The file was truncated causing less data to be read than was
+        *     requested.  In this case, we return back to the caller to
+        *     indicate 0 bytes were written to the socket.  This should
+        *     prompt the caller to fallback to the standard read path: read
+        *     the data, create a header that indicates how many bytes were
+        *     actually read, and send the header/data back to the client.
+        *
+        *     This saves us from standard sendfile behavior of sending a
+        *     header promising more data then will actually be sent.  The
+        *     only two options are to close the socket and kill the client
+        *     connection, or write a bunch of 0s.  Closing the client
+        *     connection is bad because there could actually be multiple
+        *     sessions multiplexed from the same client that are all dropped
+        *     because of a truncate.  Writing the remaining data as 0s also
+        *     isn't good, because the client will have an incorrect version
+        *     of the file.  If the file is written back to the server, the 0s
+        *     will be written back.  Fortunately, atomic sendfile allows us
+        *     to avoid making this choice in most cases.
+        *
+        *  2. One downside of atomic sendfile, is that there is a limit on
+        *     the number of bytes that can be sent atomically.  The kernel
+        *     has a limited amount of mbuf space that it can read file data
+        *     into without exhausting the system's mbufs, so a buffer of
+        *     length xfsize is used.  The xfsize at the time of writing this
+        *     is 64K.  xfsize bytes are read from the file, and subsequently
+        *     written to the socket.  This makes it impossible to do the
+        *     sendfile atomically for a byte count > xfsize.
+        *
+        *     To cope with large requests, atomic sendfile returns -1 with
+        *     errno set to E2BIG.  Since windows maxes out at 64K writes,
+        *     this is currently only a concern with non-windows clients.
+        *     Posix extensions allow the full 24bit bytecount field to be
+        *     used in ReadAndX, and clients such as smbclient and the linux
+        *     cifs client can request up to 16MB reads!  There are a few
+        *     options for handling large sendfile requests.
+        *
+        *      a. Fall back to the standard read path.  This is unacceptable
+        *         because it would require prohibitively large mallocs.
+        *
+        *      b. Fall back to using samba's fake_send_file which emulates
+        *         the kernel sendfile in userspace.  This still has the same
+        *         problem of sending the header before all of the data has
+        *         been read, so it doesn't buy us anything, and has worse
+        *         performance than the kernel's zero-copy sendfile.
+        *
+        *      c. Use non-atomic sendfile syscall to attempt a zero copy
+        *         read, and hope that there isn't a short read due to
+        *         truncation.  In the case of a short read, there are two
+        *         options:
+        *
+        *          1. Kill the client connection
+        *
+        *          2. Write zeros to the socket for the remaining bytes
+        *             promised in the header.
+        *
+        *         It is safer from a data corruption perspective to kill the
+        *         client connection, so this is our default behavior, but if
+        *         this causes problems this can be configured to write zeros
+        *         via smb.conf.
+        */
+
+       /* Handle case 1: short read -> truncated file. */
+       if (ret == 0) {
+               END_PROFILE(syscall_sendfile);
+               return ret;
+       }
+
+       /* Handle case 2: large read. */
+       if (ret == -1 && errno == E2BIG) {
+
+               if (!lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
+                                PARM_SENDFILE_LARGE_READS,
+                                PARM_SENDFILE_LARGE_READS_DEFAULT)) {
+                       DEBUG(3, ("Not attempting non-atomic large sendfile: "
+                                 "%lu bytes\n", count));
+                       END_PROFILE(syscall_sendfile);
+                       return 0;
+               }
+
+               if (count < 0x10000) {
+                       DEBUG(0, ("Count < 2^16 and E2BIG was returned! %lu",
+                                 count));
+               }
+
+               DEBUG(10, ("attempting non-atomic large sendfile: %lu bytes\n",
+                          count));
+
+               /* Try a non-atomic sendfile. */
+               ret = onefs_sys_do_sendfile(tofd, fromfd, header, offset,
+                                           count, false);
+               /* Real error: kill the client connection. */
+               if (ret == -1) {
+                       DEBUG(1, ("error on non-atomic large sendfile "
+                                 "(%lu bytes): %s\n", count,
+                                 strerror(errno)));
+                       END_PROFILE(syscall_sendfile);
+                       return ret;
+               }
+
+               /* Short read: kill the client connection. */
+               if (ret != count + header->length) {
+                       DEBUG(1, ("short read on non-atomic large sendfile "
+                                 "(%lu of %lu bytes): %s\n", ret, count,
+                                 strerror(errno)));
+
+                       /*
+                        * Returning ret here would cause us to drop into the
+                        * codepath that calls sendfile_short_send, which
+                        * sends the client a bunch of zeros instead.
+                        * Returning -1 kills the connection.
+                        */
+                       if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
+                               PARM_SENDFILE_SAFE,
+                               PARM_SENDFILE_SAFE_DEFAULT)) {
+                               END_PROFILE(syscall_sendfile);
+                               return -1;
+                       }
+
+                       END_PROFILE(syscall_sendfile);
+                       return ret;
+               }
+
+               DEBUG(10, ("non-atomic large sendfile successful\n"));
+       }
+
+       /* There was error in the atomic sendfile. */
+       if (ret == -1) {
+               DEBUG(1, ("error on %s sendfile (%lu bytes): %s\n",
+                         atomic ? "atomic" : "non-atomic",
+                         count, strerror(errno)));
+       }
+
+       END_PROFILE(syscall_sendfile);
+       return ret;
+}
+
 /**
  * Only talloc the spill buffer once (reallocing when necessary).
  */
@@ -225,10 +521,13 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
        off_t rbytes;
        off_t wbytes;
 
+       START_PROFILE_BYTES(syscall_recvfile, count);
+
        DEBUG(10,("onefs_recvfile: from = %d, to = %d, offset=%llu, count = "
                  "%lu\n", fromfd, tofd, offset, count));
 
        if (count == 0) {
+               END_PROFILE(syscall_recvfile);
                return 0;
        }
 
@@ -340,6 +639,9 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
        ret = total_wbytes;
 
 out:
+
+       END_PROFILE(syscall_recvfile);
+
        /* Make sure we always try to drain the socket. */
        if (!socket_drained && count - total_rbytes) {
                int saved_errno = errno;
@@ -354,3 +656,53 @@ out:
 
        return ret;
 }
+
+/**
+ * Set the per-process encoding, ignoring errors.
+ */
+void onefs_sys_config_enc(void)
+{
+       int ret;
+
+       ret = enc_set_proc(ENC_UTF8);
+       if (ret) {
+               DEBUG(0, ("Setting process encoding failed: %s",
+                       strerror(errno)));
+       }
+}
+
+/**
+ * Set the per-process .snpashot directory options, ignoring errors.
+ */
+void onefs_sys_config_snap_opt(struct onefs_vfs_global_config *global_config)
+{
+       struct ifs_dotsnap_options dso;
+       int ret;
+
+       dso.per_proc = 1;
+       dso.sub_accessible = global_config->dot_snap_child_accessible;
+       dso.sub_visible = global_config->dot_snap_child_visible;
+       dso.root_accessible = global_config->dot_snap_root_accessible;
+       dso.root_visible = global_config->dot_snap_root_visible;
+
+       ret = ifs_set_dotsnap_options(&dso);
+       if (ret) {
+               DEBUG(0, ("Setting snapshot visibility/accessibility "
+                       "failed: %s", strerror(errno)));
+       }
+}
+
+/**
+ * Set the per-process flag saying whether or not to accept ~snapshot
+ * as an alternative name for .snapshot directories.
+ */
+void onefs_sys_config_tilde(struct onefs_vfs_global_config *global_config)
+{
+       int ret;
+
+       ret = ifs_tilde_snapshot(global_config->dot_snap_tilde);
+       if (ret) {
+               DEBUG(0, ("Setting snapshot tilde failed: %s",
+                       strerror(errno)));
+       }
+}
index 57fe73c814cfe41e2a4e5483f57ffe1c8e632adb..73dbca4809b00f25e714f2448f5203e75b99b2a4 100644 (file)
@@ -94,6 +94,8 @@ static struct db_record *acl_tdb_lock(TALLOC_CTX *mem_ctx,
                                        const struct file_id *id)
 {
        uint8 id_buf[16];
+
+       /* For backwards compatibility only store the dev/inode. */
        push_file_id_16((char *)id_buf, id);
        return db->fetch_locked(db,
                                mem_ctx,
@@ -184,22 +186,29 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
        TDB_DATA data;
        struct file_id id;
        struct db_context *db;
+       int ret = -1;
        SMB_STRUCT_STAT sbuf;
 
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
                return NT_STATUS_INTERNAL_DB_CORRUPTION);
 
        if (fsp && fsp->fh->fd != -1) {
-               if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
-                       return map_nt_error_from_unix(errno);
-               }
+               ret = SMB_VFS_FSTAT(fsp, &sbuf);
        } else {
-               if (SMB_VFS_STAT(handle->conn, name, &sbuf) == -1) {
-                       return map_nt_error_from_unix(errno);
+               if (fsp->posix_open) {
+                       ret = SMB_VFS_LSTAT(handle->conn, name, &sbuf);
+               } else {
+                       ret = SMB_VFS_STAT(handle->conn, name, &sbuf);
                }
        }
+
+       if (ret == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+
        id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
 
+       /* For backwards compatibility only store the dev/inode. */
        push_file_id_16((char *)id_buf, &id);
 
        if (db->fetch(db,
@@ -267,6 +276,7 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
        TDB_DATA data;
        struct db_context *db;
        struct db_record *rec;
+       int ret = -1;
 
        DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n",
                        (unsigned int)pblob->length, fsp->fsp_name));
@@ -275,16 +285,22 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
                return NT_STATUS_INTERNAL_DB_CORRUPTION);
 
        if (fsp->fh->fd != -1) {
-               if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
-                       return map_nt_error_from_unix(errno);
-               }
+               ret = SMB_VFS_FSTAT(fsp, &sbuf);
        } else {
-               if (SMB_VFS_STAT(handle->conn, fsp->fsp_name, &sbuf) == -1) {
-                       return map_nt_error_from_unix(errno);
+               if (fsp->posix_open) {
+                       ret = SMB_VFS_LSTAT(handle->conn, fsp->fsp_name, &sbuf);
+               } else {
+                       ret = SMB_VFS_STAT(handle->conn, fsp->fsp_name, &sbuf);
                }
        }
+
+       if (ret == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+
        id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
 
+       /* For backwards compatibility only store the dev/inode. */
        push_file_id_16((char *)id_buf, &id);
        rec = db->fetch_locked(db, talloc_tos(),
                                make_tdb_data(id_buf,
@@ -312,6 +328,7 @@ static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle,
        SMB_STRUCT_STAT sbuf;
        struct db_context *db;
        struct db_record *rec;
+       int ret = -1;
 
        DEBUG(10,("store_acl_blob_pathname: storing blob "
                        "length %u on file %s\n",
@@ -320,11 +337,19 @@ static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle,
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
                return NT_STATUS_INTERNAL_DB_CORRUPTION);
 
-       if (SMB_VFS_STAT(handle->conn, fname, &sbuf) == -1) {
+       if (lp_posix_pathnames()) {
+               ret = SMB_VFS_LSTAT(handle->conn, fname, &sbuf);
+       } else {
+               ret = SMB_VFS_STAT(handle->conn, fname, &sbuf);
+       }
+
+       if (ret == -1) {
                return map_nt_error_from_unix(errno);
        }
 
        id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
+
+       /* For backwards compatibility only store the dev/inode. */
        push_file_id_16((char *)id_buf, &id);
 
        rec = db->fetch_locked(db, talloc_tos(),
@@ -488,7 +513,11 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
                if (fsp && !fsp->is_directory && fsp->fh->fd != -1) {
                        ret = SMB_VFS_FSTAT(fsp, &sbuf);
                } else {
-                       ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
+                       if (fsp->posix_open) {
+                               ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf);
+                       } else {
+                               ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
+                       }
                }
                if (ret == -1) {
                        return map_nt_error_from_unix(errno);
@@ -577,11 +606,17 @@ static int unlink_acl_tdb(vfs_handle_struct *handle, const char *path)
 {
        SMB_STRUCT_STAT sbuf;
        struct db_context *db;
-       int ret;
+       int ret = -1;
 
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
-       if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
+       if (lp_posix_pathnames()) {
+               ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
+       } else {
+               ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
+       }
+
+       if (ret == -1) {
                return -1;
        }
 
@@ -620,11 +655,17 @@ static int rmdir_acl_tdb(vfs_handle_struct *handle, const char *path)
 
        SMB_STRUCT_STAT sbuf;
        struct db_context *db;
-       int ret;
+       int ret = -1;
 
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
-       if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
+       if (lp_posix_pathnames()) {
+               ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
+       } else {
+               ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
+       }
+
+       if (ret == -1) {
                return -1;
        }
 
@@ -722,7 +763,11 @@ static NTSTATUS fset_nt_acl_tdb(vfs_handle_struct *handle, files_struct *fsp,
                        return NT_STATUS_OK;
                }
                if (fsp->is_directory || fsp->fh->fd == -1) {
-                       ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
+                       if (fsp->posix_open) {
+                               ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
+                       } else {
+                               ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
+                       }
                } else {
                        ret = SMB_VFS_FSTAT(fsp, &sbuf);
                }
@@ -807,11 +852,17 @@ static int sys_acl_set_file_tdb(vfs_handle_struct *handle,
 {
        SMB_STRUCT_STAT sbuf;
        struct db_context *db;
-       int ret;
+       int ret = -1;
 
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
-       if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
+       if (lp_posix_pathnames()) {
+               ret = SMB_VFS_LSTAT(handle->conn, path, &sbuf);
+       } else {
+               ret = SMB_VFS_STAT(handle->conn, path, &sbuf);
+       }
+
+       if (ret == -1) {
                return -1;
        }
 
@@ -842,7 +893,11 @@ static int sys_acl_set_fd_tdb(vfs_handle_struct *handle,
        SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
 
        if (fsp->is_directory || fsp->fh->fd == -1) {
-               ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
+               if (fsp->posix_open) {
+                       ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
+               } else {
+                       ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
+               }
        } else {
                ret = SMB_VFS_FSTAT(fsp, &sbuf);
        }
index 7c78b506f094392ea3d8e4642b8da82f292a27df..039e469426bdc5801248f1dbf66d403cfe7caabd 100644 (file)
@@ -381,7 +381,11 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
                if (fsp && !fsp->is_directory && fsp->fh->fd != -1) {
                        ret = SMB_VFS_FSTAT(fsp, &sbuf);
                } else {
-                       ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
+                       if (fsp->posix_open) {
+                               ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf);
+                       } else {
+                               ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
+                       }
                }
                if (ret == -1) {
                        return map_nt_error_from_unix(errno);
@@ -559,7 +563,11 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
                        return NT_STATUS_OK;
                }
                if (fsp->is_directory || fsp->fh->fd == -1) {
-                       ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
+                       if (fsp->posix_open) {
+                               ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
+                       } else {
+                               ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
+                       }
                } else {
                        ret = SMB_VFS_FSTAT(fsp, &sbuf);
                }
index f52ca09c0846a56c1866a21dd62c83af6d590f7d..7384268dae405587c9faa21e535760c57be3db82 100644 (file)
@@ -1042,9 +1042,20 @@ static int vfswrap_chflags(vfs_handle_struct *handle, const char *path, int flag
 #endif
 }
 
-static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle, SMB_DEV_T dev, SMB_INO_T inode)
+static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
+                                            SMB_STRUCT_STAT *sbuf)
 {
-       return file_id_create_dev(dev, inode);
+       struct file_id key;
+
+       /* the ZERO_STRUCT ensures padding doesn't break using the key as a
+        * blob */
+       ZERO_STRUCT(key);
+
+       key.devid = sbuf->st_dev;
+       key.inode = sbuf->st_ino;
+       /* key.extid is unused by default. */
+
+       return key;
 }
 
 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
index d7c9d39c5e96afea88c87b6f0b100528d74d45fd..b59a780f52ebf0225443610381069cadd8265450 100644 (file)
@@ -310,7 +310,7 @@ static int audit_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
                       (result < 0) ? strerror(errno) : "");
        }
        DEBUG(1, ("vfs_extd_audit: chmod %s mode 0x%x %s %s\n",
-              path, mode,
+              path, (unsigned int)mode,
               (result < 0) ? "failed: " : "",
               (result < 0) ? strerror(errno) : ""));
 
@@ -330,7 +330,7 @@ static int audit_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t m
                       (result < 0) ? strerror(errno) : "");
        }
        DEBUG(1, ("vfs_extd_audit: chmod_acl %s mode 0x%x %s %s\n",
-               path, mode,
+               path, (unsigned int)mode,
               (result < 0) ? "failed: " : "",
               (result < 0) ? strerror(errno) : ""));
 
@@ -350,7 +350,7 @@ static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mod
                       (result < 0) ? strerror(errno) : "");
        }
        DEBUG(1, ("vfs_extd_audit: fchmod %s mode 0x%x %s %s",
-              fsp->fsp_name,  mode,
+              fsp->fsp_name,  (unsigned int)mode,
               (result < 0) ? "failed: " : "",
               (result < 0) ? strerror(errno) : ""));
 
@@ -370,7 +370,7 @@ static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t
                       (result < 0) ? strerror(errno) : "");
        }
        DEBUG(1, ("vfs_extd_audit: fchmod_acl %s mode 0x%x %s %s",
-              fsp->fsp_name,  mode,
+              fsp->fsp_name,  (unsigned int)mode,
               (result < 0) ? "failed: " : "",
               (result < 0) ? strerror(errno) : ""));
 
index 787a49f36b6e6d76c996d289b5bff59cc456d314..8152c5477e8e2ee93c9ee746df7ed95d92f5a8c8 100644 (file)
@@ -226,7 +226,7 @@ static void fileid_disconnect(struct vfs_handle_struct *handle)
 }
 
 static struct file_id fileid_file_id_create(struct vfs_handle_struct *handle,
-                                           SMB_DEV_T dev, SMB_INO_T inode)
+                                           const SMB_STRUCT_STAT *sbuf)
 {
        struct fileid_handle_data *data;
        struct file_id id;
@@ -237,8 +237,8 @@ static struct file_id fileid_file_id_create(struct vfs_handle_struct *handle,
                                struct fileid_handle_data,
                                return id);
 
-       id.devid        = data->device_mapping_fn(data, dev);
-       id.inode        = inode;
+       id.devid        = data->device_mapping_fn(data, sbuf->st_dev);
+       id.inode        = sbuf->st_ino;
 
        return id;
 }
index 15eafc1b56a5117826a2bf0178b258f3e8a85b97..3c159f10eb1ec1369873fe493134ad155e8a382d 100644 (file)
@@ -209,7 +209,7 @@ static NTSTATUS smb_full_audit_notify_watch(struct vfs_handle_struct *handle,
 static int smb_full_audit_chflags(vfs_handle_struct *handle,
                            const char *path, unsigned int flags);
 static struct file_id smb_full_audit_file_id_create(struct vfs_handle_struct *handle,
-                                                   SMB_DEV_T dev, SMB_INO_T inode);
+                                                   const SMB_STRUCT_STAT *sbuf);
 static NTSTATUS smb_full_audit_streaminfo(vfs_handle_struct *handle,
                                          struct files_struct *fsp,
                                          const char *fname,
@@ -1664,14 +1664,14 @@ static int smb_full_audit_chflags(vfs_handle_struct *handle,
 }
 
 static struct file_id smb_full_audit_file_id_create(struct vfs_handle_struct *handle,
-                                                   SMB_DEV_T dev, SMB_INO_T inode)
+                                                   const SMB_STRUCT_STAT *sbuf)
 {
        struct file_id id_zero;
        struct file_id result;
 
        ZERO_STRUCT(id_zero);
 
-       result = SMB_VFS_NEXT_FILE_ID_CREATE(handle, dev, inode);
+       result = SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf);
 
        do_log(SMB_VFS_OP_FILE_ID_CREATE,
               !file_id_equal(&id_zero, &result),
index 9667d86dbad6d7cbb485896736064518a5547b60..f81134909f8329b6f80808a6415f617c32555ccb 100644 (file)
 
 #define ONEFS_DATA_FASTBUF     10
 
-struct onefs_vfs_config share_config[ONEFS_DATA_FASTBUF];
-struct onefs_vfs_config *pshare_config;
+struct onefs_vfs_share_config vfs_share_config[ONEFS_DATA_FASTBUF];
+struct onefs_vfs_share_config *pvfs_share_config;
 
-static void onefs_load_faketimestamp_config(struct vfs_handle_struct *handle,
-                                           struct onefs_vfs_config *cfg)
+static void onefs_load_faketimestamp_config(struct connection_struct *conn,
+                                           struct onefs_vfs_share_config *cfg)
 {
        const char **parm;
-       int snum = SNUM(handle->conn);
+       int snum = SNUM(conn);
 
        parm = lp_parm_string_list(snum, PARM_ONEFS_TYPE, PARM_ATIME_NOW,
                                   PARM_ATIME_NOW_DEFAULT);
@@ -83,46 +83,141 @@ static void onefs_load_faketimestamp_config(struct vfs_handle_struct *handle,
                                      PARM_MTIME_SLOP_DEFAULT);
 }
 
+/**
+ * Set onefs-specific vfs global config parameters.
+ *
+ * Since changes in these parameters require calling syscalls, we only want to
+ * call them when the configuration actually changes.
+ */
+static void onefs_load_global_config(connection_struct *conn)
+{
+       static struct onefs_vfs_global_config global_config;
+       bool dot_snap_child_accessible;
+       bool dot_snap_child_visible;
+       bool dot_snap_root_accessible;
+       bool dot_snap_root_visible;
+       bool dot_snap_tilde;
+       bool reconfig_dso = false;
+       bool reconfig_tilde = false;
+
+       /* Check if this is the first time setting the config options. */
+       if (!(global_config.init_flags & ONEFS_VFS_CONFIG_INITIALIZED)) {
+               global_config.init_flags |= ONEFS_VFS_CONFIG_INITIALIZED;
+
+               /* Set process encoding */
+               onefs_sys_config_enc();
+
+               reconfig_dso = true;
+               reconfig_tilde = true;
+       }
+
+       /* Get the dot snap options from the conf. */
+       dot_snap_child_accessible =
+           lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
+                        PARM_DOT_SNAP_CHILD_ACCESSIBLE,
+                        PARM_DOT_SNAP_CHILD_ACCESSIBLE_DEFAULT);
+       dot_snap_child_visible =
+           lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
+                        PARM_DOT_SNAP_CHILD_VISIBLE,
+                        PARM_DOT_SNAP_CHILD_VISIBLE_DEFAULT);
+       dot_snap_root_accessible =
+           lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
+                        PARM_DOT_SNAP_ROOT_ACCESSIBLE,
+                        PARM_DOT_SNAP_ROOT_ACCESSIBLE_DEFAULT);
+       dot_snap_root_visible =
+           lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
+                        PARM_DOT_SNAP_ROOT_VISIBLE,
+                        PARM_DOT_SNAP_ROOT_VISIBLE_DEFAULT);
+       dot_snap_tilde =
+           lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
+                        PARM_DOT_SNAP_TILDE,
+                        PARM_DOT_SNAP_TILDE_DEFAULT);
+
+       /* Check if any of the dot snap options need updating. */
+       if (dot_snap_child_accessible !=
+           global_config.dot_snap_child_accessible) {
+               global_config.dot_snap_child_accessible =
+                   dot_snap_child_accessible;
+               reconfig_dso = true;
+       }
+       if (dot_snap_child_visible !=
+           global_config.dot_snap_child_visible) {
+               global_config.dot_snap_child_visible =
+                   dot_snap_child_visible;
+               reconfig_dso = true;
+       }
+       if (dot_snap_root_accessible !=
+           global_config.dot_snap_root_accessible) {
+               global_config.dot_snap_root_accessible =
+                   dot_snap_root_accessible;
+               reconfig_dso = true;
+       }
+       if (dot_snap_root_visible !=
+           global_config.dot_snap_root_visible) {
+               global_config.dot_snap_root_visible =
+                   dot_snap_root_visible;
+               reconfig_dso = true;
+       }
+       if (dot_snap_tilde != global_config.dot_snap_tilde) {
+               global_config.dot_snap_tilde = dot_snap_tilde;
+               reconfig_tilde = true;
+       }
+
+       /* If a dot snap option has changed update the process.  */
+       if (reconfig_dso) {
+               onefs_sys_config_snap_opt(&global_config);
+       }
 
-static int onefs_load_config(struct vfs_handle_struct *handle)
+       /* If the dot snap tilde option has changed update the process.  */
+       if (reconfig_tilde) {
+               onefs_sys_config_tilde(&global_config);
+       }
+}
+
+static int onefs_load_config(connection_struct *conn)
 {
-       int snum = SNUM(handle->conn);
+       int snum = SNUM(conn);
        int share_count = lp_numservices();
 
-       if (!pshare_config) {
+       /* Share config */
+       if (!pvfs_share_config) {
 
                if (share_count <= ONEFS_DATA_FASTBUF)
-                       pshare_config = share_config;
+                       pvfs_share_config = vfs_share_config;
                else {
-                       pshare_config =
-                           SMB_MALLOC_ARRAY(struct onefs_vfs_config,
+                       pvfs_share_config =
+                           SMB_MALLOC_ARRAY(struct onefs_vfs_share_config,
                                             share_count);
-                       if (!pshare_config) {
+                       if (!pvfs_share_config) {
                                errno = ENOMEM;
                                return -1;
                        }
 
-                       memset(pshare_config, 0,
-                           (sizeof(struct onefs_vfs_config) * share_count));
+                       memset(pvfs_share_config, 0,
+                           (sizeof(struct onefs_vfs_share_config) *
+                                   share_count));
                }
        }
 
-       if ((pshare_config[snum].init_flags &
+       if ((pvfs_share_config[snum].init_flags &
                ONEFS_VFS_CONFIG_INITIALIZED) == 0) {
-                       pshare_config[snum].init_flags =
+                       pvfs_share_config[snum].init_flags =
                            ONEFS_VFS_CONFIG_INITIALIZED;
-                       onefs_load_faketimestamp_config(handle,
-                                                       &pshare_config[snum]);
+                       onefs_load_faketimestamp_config(conn,
+                                                       &pvfs_share_config[snum]);
        }
 
+       /* Global config */
+       onefs_load_global_config(conn);
+
        return 0;
 }
 
 bool onefs_get_config(int snum, int config_type,
-                     struct onefs_vfs_config *cfg)
+                     struct onefs_vfs_share_config *cfg)
 {
-       if (share_config[snum].init_flags & config_type)
-               *cfg = share_config[snum];
+       if (vfs_share_config[snum].init_flags & config_type)
+               *cfg = vfs_share_config[snum];
        else
                return false;
 
@@ -132,10 +227,13 @@ bool onefs_get_config(int snum, int config_type,
 static int onefs_connect(struct vfs_handle_struct *handle, const char *service,
                         const char *user)
 {
-       int ret = onefs_load_config(handle);
+       int ret;
 
-       if (ret)
+       ret = onefs_load_config(handle->conn);
+       if (ret) {
+               DEBUG(3, ("Load config failed: %s\n", strerror(errno)));
                return ret;
+       }
 
        return SMB_VFS_NEXT_CONNECT(handle, service, user);
 }
@@ -156,6 +254,19 @@ static int onefs_open(vfs_handle_struct *handle, const char *fname,
        return SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
 }
 
+static ssize_t onefs_sendfile(vfs_handle_struct *handle, int tofd,
+                             files_struct *fromfsp, const DATA_BLOB *header,
+                             SMB_OFF_T offset, size_t count)
+{
+       ssize_t result;
+
+       START_PROFILE_BYTES(syscall_sendfile, count);
+       result = onefs_sys_sendfile(handle->conn, tofd, fromfsp->fh->fd,
+                                   header, offset, count);
+       END_PROFILE(syscall_sendfile);
+       return result;
+}
+
 static ssize_t onefs_recvfile(vfs_handle_struct *handle, int fromfd,
                              files_struct *tofsp, SMB_OFF_T offset,
                              size_t count)
@@ -194,6 +305,22 @@ static uint64_t onefs_get_alloc_size(struct vfs_handle_struct *handle,
        return result;
 }
 
+static struct file_id onefs_file_id_create(struct vfs_handle_struct *handle,
+                                            SMB_STRUCT_STAT *sbuf)
+{
+       struct file_id key;
+
+       /* the ZERO_STRUCT ensures padding doesn't break using the key as a
+        * blob */
+       ZERO_STRUCT(key);
+
+       key.devid = sbuf->st_dev;
+       key.inode = sbuf->st_ino;
+       key.extid = sbuf->st_snapid;
+
+       return key;
+}
+
 static int onefs_statvfs(vfs_handle_struct *handle, const char *path,
                         vfs_statvfs_struct *statbuf)
 {
@@ -324,6 +451,8 @@ static vfs_op_tuple onefs_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(onefs_close), SMB_VFS_OP_CLOSE,
         SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_sendfile), SMB_VFS_OP_SENDFILE,
+        SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(onefs_recvfile), SMB_VFS_OP_RECVFILE,
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(onefs_rename), SMB_VFS_OP_RENAME,
@@ -342,6 +471,8 @@ static vfs_op_tuple onefs_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(onefs_chflags), SMB_VFS_OP_CHFLAGS,
         SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_file_id_create), SMB_VFS_OP_FILE_ID_CREATE,
+        SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(onefs_streaminfo), SMB_VFS_OP_STREAMINFO,
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(onefs_brl_lock_windows), SMB_VFS_OP_BRL_LOCK_WINDOWS,
@@ -350,6 +481,8 @@ static vfs_op_tuple onefs_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(onefs_brl_cancel_windows), SMB_VFS_OP_BRL_CANCEL_WINDOWS,
         SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(onefs_notify_watch), SMB_VFS_OP_NOTIFY_WATCH,
+        SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(onefs_fget_nt_acl), SMB_VFS_OP_FGET_NT_ACL,
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(onefs_get_nt_acl), SMB_VFS_OP_GET_NT_ACL,
diff --git a/source3/modules/vfs_onefs_shadow_copy.c b/source3/modules/vfs_onefs_shadow_copy.c
new file mode 100644 (file)
index 0000000..28bc0c5
--- /dev/null
@@ -0,0 +1,717 @@
+/*
+ * OneFS shadow copy implementation that utilizes the file system's native
+ * snapshot support. This is based on the original shadow copy module from
+ * 2004.
+ *
+ * Copyright (C) Stefan Metzmacher     2003-2004
+ * Copyright (C) Tim Prouty            2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+#include "onefs_shadow_copy.h"
+
+static int vfs_onefs_shadow_copy_debug_level = DBGC_VFS;
+
+#undef DBGC_CLASS
+#define DBGC_CLASS vfs_onefs_shadow_copy_debug_level
+
+#define SHADOW_COPY_PREFIX "@GMT-"
+#define SHADOW_COPY_SAMPLE "@GMT-2004.02.18-15.44.00"
+
+bool
+shadow_copy_match_name(const char *name, char **snap_component)
+{
+       uint32  i = 0;
+       char delim[] = SHADOW_COPY_PREFIX;
+       char* start;
+
+       start = strstr( name, delim );
+
+       /*
+        * The name could have SHADOW_COPY_PREFIX in it so we need to keep
+        * trying until we get something that is the full length of the
+        * SHADOW_COPY_SAMPLE.
+        */
+       while (start != NULL) {
+
+               DEBUG(10,("Processing %s\n", name));
+
+               /* size / correctness check */
+               *snap_component = start;
+               for ( i = sizeof(SHADOW_COPY_PREFIX);
+                     i < sizeof(SHADOW_COPY_SAMPLE); i++) {
+                       if (start[i] == '/') {
+                               if (i == sizeof(SHADOW_COPY_SAMPLE) - 1)
+                                       return true;
+                               else
+                                       break;
+                       } else if (start[i] == '\0')
+                               return (i == sizeof(SHADOW_COPY_SAMPLE) - 1);
+               }
+
+               start = strstr( start, delim );
+       }
+
+       return false;
+}
+
+static int
+onefs_shadow_copy_get_shadow_copy_data(vfs_handle_struct *handle,
+                                      files_struct *fsp,
+                                      SHADOW_COPY_DATA *shadow_copy_data,
+                                      bool labels)
+{
+       void *p = osc_version_opendir();
+       char *snap_component = NULL;
+       shadow_copy_data->num_volumes = 0;
+       shadow_copy_data->labels = NULL;
+
+       if (!p) {
+               DEBUG(0, ("shadow_copy_get_shadow_copy_data: osc_opendir() "
+                         "failed for [%s]\n",fsp->conn->connectpath));
+               return -1;
+       }
+
+       while (true) {
+               SHADOW_COPY_LABEL *tlabels;
+               char *d;
+
+               d = osc_version_readdir(p);
+               if (d == NULL)
+                       break;
+
+               if (!shadow_copy_match_name(d, &snap_component)) {
+                       DEBUG(10,("shadow_copy_get_shadow_copy_data: ignore "
+                                 "[%s]\n",d));
+                       continue;
+               }
+
+               DEBUG(7,("shadow_copy_get_shadow_copy_data: not ignore "
+                        "[%s]\n",d));
+
+               if (!labels) {
+                       shadow_copy_data->num_volumes++;
+                       continue;
+               }
+
+               tlabels = (SHADOW_COPY_LABEL *)TALLOC_REALLOC(
+                       shadow_copy_data->mem_ctx,
+                       shadow_copy_data->labels,
+                       (shadow_copy_data->num_volumes+1) *
+                       sizeof(SHADOW_COPY_LABEL));
+
+               if (tlabels == NULL) {
+                       DEBUG(0,("shadow_copy_get_shadow_copy_data: Out of "
+                                "memory\n"));
+                       osc_version_closedir(p);
+                       return -1;
+               }
+
+               snprintf(tlabels[shadow_copy_data->num_volumes++],
+                        sizeof(*tlabels), "%s",d);
+
+               shadow_copy_data->labels = tlabels;
+       }
+
+       osc_version_closedir(p);
+
+       return 0;
+}
+
+#define SHADOW_NEXT(op, args, rtype) do {                            \
+       char *cpath = NULL;                                           \
+       char *snap_component = NULL;                                  \
+       rtype ret;                                                    \
+       if (shadow_copy_match_name(path, &snap_component))            \
+               cpath = osc_canonicalize_path(path, snap_component); \
+       ret = SMB_VFS_NEXT_ ## op args;                               \
+       SAFE_FREE(cpath);                                             \
+       return ret;                                                   \
+       } while (0)                                                   \
+
+
+
+static uint64_t
+onefs_shadow_copy_disk_free(vfs_handle_struct *handle, const char *path,
+                           bool small_query, uint64_t *bsize, uint64_t *dfree,
+                           uint64_t *dsize)
+{
+
+       SHADOW_NEXT(DISK_FREE,
+                   (handle, cpath ?: path, small_query, bsize, dfree, dsize),
+                   uint64_t);
+
+}
+
+static int
+onefs_shadow_copy_statvfs(struct vfs_handle_struct *handle, const char *path,
+                         struct vfs_statvfs_struct *statbuf)
+{
+       SHADOW_NEXT(STATVFS,
+                   (handle, cpath ?: path, statbuf),
+                   int);
+}
+
+static SMB_STRUCT_DIR *
+onefs_shadow_copy_opendir(vfs_handle_struct *handle, const char *path,
+                         const char *mask, uint32_t attr)
+{
+       SHADOW_NEXT(OPENDIR,
+                   (handle, cpath ?: path, mask, attr),
+                   SMB_STRUCT_DIR *);
+}
+
+static int
+onefs_shadow_copy_mkdir(vfs_handle_struct *handle, const char *path,
+                       mode_t mode)
+{
+       SHADOW_NEXT(MKDIR,
+                   (handle, cpath ?: path, mode),
+                   int);
+}
+
+static int
+onefs_shadow_copy_rmdir(vfs_handle_struct *handle, const char *path)
+{
+       SHADOW_NEXT(RMDIR,
+                   (handle, cpath ?: path),
+                   int);
+}
+
+static int
+onefs_shadow_copy_open(vfs_handle_struct *handle, const char *path,
+                      files_struct *fsp, int flags, mode_t mode)
+{
+       SHADOW_NEXT(OPEN,
+                   (handle, cpath ?: path, fsp, flags, mode),
+                   int);
+}
+
+static NTSTATUS
+onefs_shadow_copy_create_file(vfs_handle_struct *handle,
+                             struct smb_request *req,
+                             uint16_t root_dir_fid,
+                             const char *path,
+                             uint32_t create_file_flags,
+                             uint32_t access_mask,
+                             uint32_t share_access,
+                             uint32_t create_disposition,
+                             uint32_t create_options,
+                             uint32_t file_attributes,
+                             uint32_t oplock_request,
+                             uint64_t allocation_size,
+                             struct security_descriptor *sd,
+                             struct ea_list *ea_list,
+                             files_struct **result,
+                             int *pinfo,
+                             SMB_STRUCT_STAT *psbuf)
+{
+       SHADOW_NEXT(CREATE_FILE,
+                   (handle, req, root_dir_fid, cpath ?: path,
+                       create_file_flags, access_mask, share_access,
+                       create_disposition, create_options, file_attributes,
+                       oplock_request, allocation_size, sd, ea_list, result,
+                       pinfo, psbuf),
+                   NTSTATUS);
+}
+
+/**
+ * XXX: macro-ize
+ */
+static int
+onefs_shadow_copy_rename(vfs_handle_struct *handle, const char *old_name,
+                        const char *new_name)
+{
+       char *old_cpath = NULL;
+       char *old_snap_component = NULL;
+       char *new_cpath = NULL;
+       char *new_snap_component = NULL;
+       int ret;
+
+       if (shadow_copy_match_name(old_name, &old_snap_component))
+               old_cpath = osc_canonicalize_path(old_name, old_snap_component);
+
+       if (shadow_copy_match_name(new_name, &new_snap_component))
+               new_cpath = osc_canonicalize_path(new_name, new_snap_component);
+
+        ret = SMB_VFS_NEXT_RENAME(handle, old_cpath ?: old_name,
+           new_cpath ?: new_name);
+
+       SAFE_FREE(old_cpath);
+       SAFE_FREE(new_cpath);
+
+       return ret;
+}
+
+static int
+onefs_shadow_copy_stat(vfs_handle_struct *handle, const char *path,
+                      SMB_STRUCT_STAT *sbuf)
+{
+       SHADOW_NEXT(STAT,
+                   (handle, cpath ?: path, sbuf),
+                   int);
+}
+
+static int
+onefs_shadow_copy_lstat(vfs_handle_struct *handle, const char *path,
+                       SMB_STRUCT_STAT *sbuf)
+{
+       SHADOW_NEXT(LSTAT,
+                   (handle, cpath ?: path, sbuf),
+                   int);
+}
+
+static int
+onefs_shadow_copy_unlink(vfs_handle_struct *handle, const char *path)
+{
+       SHADOW_NEXT(UNLINK,
+                   (handle, cpath ?: path),
+                   int);
+}
+
+static int
+onefs_shadow_copy_chmod(vfs_handle_struct *handle, const char *path,
+                       mode_t mode)
+{
+       SHADOW_NEXT(CHMOD,
+                   (handle, cpath ?: path, mode),
+                   int);
+}
+
+static int
+onefs_shadow_copy_chown(vfs_handle_struct *handle, const char *path,
+                       uid_t uid, gid_t gid)
+{
+       SHADOW_NEXT(CHOWN,
+                   (handle, cpath ?: path, uid, gid),
+                   int);
+}
+
+static int
+onefs_shadow_copy_lchown(vfs_handle_struct *handle, const char *path,
+                        uid_t uid, gid_t gid)
+{
+       SHADOW_NEXT(LCHOWN,
+                   (handle, cpath ?: path, uid, gid),
+                   int);
+}
+
+static int
+onefs_shadow_copy_chdir(vfs_handle_struct *handle, const char *path)
+{
+       SHADOW_NEXT(CHDIR,
+                   (handle, cpath ?: path),
+                   int);
+}
+
+static int
+onefs_shadow_copy_ntimes(vfs_handle_struct *handle, const char *path,
+                       struct smb_file_time *ft)
+{
+       SHADOW_NEXT(NTIMES,
+                   (handle, cpath ?: path, ft),
+                   int);
+
+}
+
+/**
+ * XXX: macro-ize
+ */
+static bool
+onefs_shadow_copy_symlink(vfs_handle_struct *handle,
+    const char *oldpath, const char *newpath)
+{
+       char *old_cpath = NULL;
+       char *old_snap_component = NULL;
+       char *new_cpath = NULL;
+       char *new_snap_component = NULL;
+       bool ret;
+
+       if (shadow_copy_match_name(oldpath, &old_snap_component))
+               old_cpath = osc_canonicalize_path(oldpath, old_snap_component);
+
+       if (shadow_copy_match_name(newpath, &new_snap_component))
+               new_cpath = osc_canonicalize_path(newpath, new_snap_component);
+
+        ret = SMB_VFS_NEXT_SYMLINK(handle, old_cpath ?: oldpath,
+           new_cpath ?: newpath);
+
+       SAFE_FREE(old_cpath);
+       SAFE_FREE(new_cpath);
+
+       return ret;
+}
+
+static bool
+onefs_shadow_copy_readlink(vfs_handle_struct *handle, const char *path,
+                          char *buf, size_t bufsiz)
+{
+       SHADOW_NEXT(READLINK,
+                   (handle, cpath ?: path, buf, bufsiz),
+                   bool);
+}
+
+/**
+ * XXX: macro-ize
+ */
+static int
+onefs_shadow_copy_link(vfs_handle_struct *handle, const char *oldpath,
+                      const char *newpath)
+{
+       char *old_cpath = NULL;
+       char *old_snap_component = NULL;
+       char *new_cpath = NULL;
+       char *new_snap_component = NULL;
+       int ret;
+
+       if (shadow_copy_match_name(oldpath, &old_snap_component))
+               old_cpath = osc_canonicalize_path(oldpath, old_snap_component);
+
+       if (shadow_copy_match_name(newpath, &new_snap_component))
+               new_cpath = osc_canonicalize_path(newpath, new_snap_component);
+
+        ret = SMB_VFS_NEXT_LINK(handle, old_cpath ?: oldpath,
+           new_cpath ?: newpath);
+
+       SAFE_FREE(old_cpath);
+       SAFE_FREE(new_cpath);
+
+       return ret;
+}
+
+static int
+onefs_shadow_copy_mknod(vfs_handle_struct *handle, const char *path,
+                       mode_t mode, SMB_DEV_T dev)
+{
+       SHADOW_NEXT(MKNOD,
+                   (handle, cpath ?: path, mode, dev),
+                   int);
+}
+
+static char *
+onefs_shadow_copy_realpath(vfs_handle_struct *handle, const char *path,
+                          char *resolved_path)
+{
+       SHADOW_NEXT(REALPATH,
+                   (handle, cpath ?: path, resolved_path),
+                   char *);
+}
+
+static int onefs_shadow_copy_chflags(struct vfs_handle_struct *handle,
+                                    const char *path, unsigned int flags)
+{
+       SHADOW_NEXT(CHFLAGS,
+                   (handle, cpath ?: path, flags),
+                   int);
+}
+
+static NTSTATUS
+onefs_shadow_copy_streaminfo(struct vfs_handle_struct *handle,
+                            struct files_struct *fsp,
+                            const char *path,
+                            TALLOC_CTX *mem_ctx,
+                            unsigned int *num_streams,
+                            struct stream_struct **streams)
+{
+       SHADOW_NEXT(STREAMINFO,
+                   (handle, fsp, cpath ?: path, mem_ctx, num_streams,
+                       streams),
+                   NTSTATUS);
+}
+
+static int
+onefs_shadow_copy_get_real_filename(struct vfs_handle_struct *handle,
+                                   const char *full_path,
+                                   const char *path,
+                                   TALLOC_CTX *mem_ctx,
+                                   char **found_name)
+{
+       SHADOW_NEXT(GET_REAL_FILENAME,
+                   (handle, full_path, cpath ?: path, mem_ctx, found_name),
+                   int);
+}
+
+static NTSTATUS
+onefs_shadow_copy_get_nt_acl(struct vfs_handle_struct *handle,
+                           const char *path, uint32 security_info,
+                           struct security_descriptor **ppdesc)
+{
+       SHADOW_NEXT(GET_NT_ACL,
+                   (handle, cpath ?: path, security_info, ppdesc),
+                   NTSTATUS);
+}
+
+static int
+onefs_shadow_copy_chmod_acl(vfs_handle_struct *handle, const char *path,
+                           mode_t mode)
+{
+       SHADOW_NEXT(CHMOD_ACL,
+                   (handle, cpath ?: path, mode),
+                   int);
+}
+
+static SMB_ACL_T
+onefs_shadow_copy_sys_acl_get_file(vfs_handle_struct *handle,
+                                  const char *path, SMB_ACL_TYPE_T type)
+{
+       SHADOW_NEXT(SYS_ACL_GET_FILE,
+                   (handle, cpath ?: path, type),
+                   SMB_ACL_T);
+}
+
+static int
+onefs_shadow_copy_sys_acl_set_file(vfs_handle_struct *handle, const char *path,
+                                  SMB_ACL_TYPE_T type, SMB_ACL_T theacl)
+{
+       SHADOW_NEXT(SYS_ACL_SET_FILE,
+                   (handle, cpath ?: path, type, theacl),
+                   int);
+}
+
+static int
+onefs_shadow_copy_sys_acl_delete_def_file(vfs_handle_struct *handle,
+                                         const char *path)
+{
+       SHADOW_NEXT(SYS_ACL_DELETE_DEF_FILE,
+                   (handle, cpath ?: path),
+                   int);
+}
+
+static ssize_t
+onefs_shadow_copy_getxattr(vfs_handle_struct *handle, const char *path,
+                          const char *name, void *value, size_t size)
+{
+       SHADOW_NEXT(GETXATTR,
+                   (handle, cpath ?: path, name, value, size),
+                   ssize_t);
+}
+
+static ssize_t
+onefs_shadow_copy_lgetxattr(vfs_handle_struct *handle, const char *path,
+                           const char *name, void *value, size_t size)
+{
+       SHADOW_NEXT(LGETXATTR,
+                   (handle, cpath ?: path, name, value, size),
+                   ssize_t);
+}
+
+static ssize_t
+onefs_shadow_copy_listxattr(vfs_handle_struct *handle, const char *path,
+                           char *list, size_t size)
+{
+       SHADOW_NEXT(LISTXATTR,
+                   (handle, cpath ?: path, list, size),
+                   ssize_t);
+}
+
+static ssize_t
+onefs_shadow_copy_llistxattr(vfs_handle_struct *handle, const char *path,
+                            char *list, size_t size)
+{
+       SHADOW_NEXT(LLISTXATTR,
+                   (handle, cpath ?: path, list, size),
+                   ssize_t);
+}
+
+static int
+onefs_shadow_copy_removexattr(vfs_handle_struct *handle, const char *path,
+                             const char *name)
+{
+       SHADOW_NEXT(REMOVEXATTR,
+                   (handle, cpath ?: path, name),
+                   int);
+}
+
+static int
+onefs_shadow_copy_lremovexattr(vfs_handle_struct *handle, const char *path,
+                              const char *name)
+{
+       SHADOW_NEXT(LREMOVEXATTR,
+                   (handle, cpath ?: path, name),
+                   int);
+}
+
+static int
+onefs_shadow_copy_setxattr(vfs_handle_struct *handle, const char *path,
+                          const char *name, const void *value, size_t size,
+                          int flags)
+{
+       SHADOW_NEXT(SETXATTR,
+                   (handle, cpath ?: path, name, value, size, flags),
+                   int);
+}
+
+static int
+onefs_shadow_copy_lsetxattr(vfs_handle_struct *handle, const char *path,
+                           const char *name, const void *value, size_t size,
+                           int flags)
+{
+       SHADOW_NEXT(LSETXATTR,
+                   (handle, cpath ?: path, name, value, size, flags),
+                   int);
+}
+
+static bool
+onefs_shadow_copy_is_offline(struct vfs_handle_struct *handle,
+                            const char *path, SMB_STRUCT_STAT *sbuf)
+{
+       SHADOW_NEXT(IS_OFFLINE,
+                   (handle, cpath ?: path, sbuf),
+                   bool);
+}
+
+static int
+onefs_shadow_copy_set_offline(struct vfs_handle_struct *handle,
+                             const char *path)
+{
+       SHADOW_NEXT(SET_OFFLINE,
+                   (handle, cpath ?: path),
+                   int);
+}
+
+/* VFS operations structure */
+
+static vfs_op_tuple onefs_shadow_copy_ops[] = {
+
+       /* Disk operations */
+
+       {SMB_VFS_OP(onefs_shadow_copy_disk_free), SMB_VFS_OP_DISK_FREE,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_get_shadow_copy_data),
+        SMB_VFS_OP_GET_SHADOW_COPY_DATA, SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(onefs_shadow_copy_statvfs), SMB_VFS_OP_STATVFS,
+        SMB_VFS_LAYER_TRANSPARENT},
+
+       /* Directory operations */
+
+       {SMB_VFS_OP(onefs_shadow_copy_opendir), SMB_VFS_OP_OPENDIR,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_mkdir), SMB_VFS_OP_MKDIR,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_rmdir), SMB_VFS_OP_RMDIR,
+        SMB_VFS_LAYER_TRANSPARENT},
+
+       /* File operations */
+
+       {SMB_VFS_OP(onefs_shadow_copy_open), SMB_VFS_OP_OPEN,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_create_file), SMB_VFS_OP_CREATE_FILE,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_rename), SMB_VFS_OP_RENAME,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_stat), SMB_VFS_OP_STAT,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_stat), SMB_VFS_OP_STAT,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_lstat), SMB_VFS_OP_LSTAT,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_unlink), SMB_VFS_OP_UNLINK,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_chmod), SMB_VFS_OP_CHMOD,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_chown), SMB_VFS_OP_CHOWN,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_lchown), SMB_VFS_OP_LCHOWN,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_chdir), SMB_VFS_OP_CHDIR,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_ntimes), SMB_VFS_OP_NTIMES,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_symlink), SMB_VFS_OP_SYMLINK,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_readlink), SMB_VFS_OP_READLINK,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_link), SMB_VFS_OP_LINK,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_mknod), SMB_VFS_OP_MKNOD,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_realpath), SMB_VFS_OP_REALPATH,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_chflags), SMB_VFS_OP_CHFLAGS,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_streaminfo), SMB_VFS_OP_STREAMINFO,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_get_real_filename),
+        SMB_VFS_OP_GET_REAL_FILENAME, SMB_VFS_LAYER_TRANSPARENT},
+
+       /* NT File ACL operations */
+
+       {SMB_VFS_OP(onefs_shadow_copy_get_nt_acl), SMB_VFS_OP_GET_NT_ACL,
+        SMB_VFS_LAYER_TRANSPARENT},
+
+       /* POSIX ACL operations */
+
+       {SMB_VFS_OP(onefs_shadow_copy_chmod_acl), SMB_VFS_OP_CHMOD_ACL,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_sys_acl_get_file),
+        SMB_VFS_OP_SYS_ACL_GET_FILE, SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_sys_acl_set_file),
+        SMB_VFS_OP_SYS_ACL_SET_FILE, SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_sys_acl_delete_def_file),
+        SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, SMB_VFS_LAYER_TRANSPARENT},
+
+        /* EA operations. */
+
+       {SMB_VFS_OP(onefs_shadow_copy_getxattr), SMB_VFS_OP_GETXATTR,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_lgetxattr), SMB_VFS_OP_LGETXATTR,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_listxattr), SMB_VFS_OP_LISTXATTR,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_llistxattr), SMB_VFS_OP_LLISTXATTR,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_removexattr), SMB_VFS_OP_REMOVEXATTR,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_lremovexattr), SMB_VFS_OP_LREMOVEXATTR,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_setxattr), SMB_VFS_OP_SETXATTR,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_lsetxattr), SMB_VFS_OP_LSETXATTR,
+        SMB_VFS_LAYER_TRANSPARENT},
+
+       /* offline operations */
+       {SMB_VFS_OP(onefs_shadow_copy_is_offline), SMB_VFS_OP_IS_OFFLINE,
+        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(onefs_shadow_copy_set_offline), SMB_VFS_OP_SET_OFFLINE,
+        SMB_VFS_LAYER_TRANSPARENT},
+
+       {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
+};
+
+NTSTATUS vfs_shadow_copy_init(void)
+{
+       NTSTATUS ret;
+
+       ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
+                              "onefs_shadow_copy",
+                              onefs_shadow_copy_ops);
+
+       if (!NT_STATUS_IS_OK(ret))
+               return ret;
+
+       vfs_onefs_shadow_copy_debug_level = debug_add_class("onefs_shadow_copy");
+
+       if (vfs_onefs_shadow_copy_debug_level == -1) {
+               vfs_onefs_shadow_copy_debug_level = DBGC_VFS;
+               DEBUG(0, ("Couldn't register custom debugging class!\n"));
+       } else {
+               DEBUG(10, ("Debug class number of 'onefs_shadow_copy': %d\n",
+                          vfs_onefs_shadow_copy_debug_level));
+       }
+
+       return ret;
+}
index 7bdfe8465b1bbdba5380c6bc68ef17cf49980ef8..cafb077555d3e677e907eb91c6744e5301d74640 100644 (file)
@@ -51,11 +51,12 @@ static bool solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
 static bool solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solarisacl, 
                int *count);
 static bool solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solarisacl, int *count);
-static bool solaris_acl_sort(SOLARIS_ACL_T acl, int count);
+static bool solaris_acl_sort(SOLARIS_ACL_T theacl, int count);
 static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm);
 static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm);
+#if 0
 static bool solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count);
-
+#endif
 
 /* public functions - the api */
 
@@ -347,7 +348,6 @@ static bool smb_acl_to_solaris_acl(SMB_ACL_T smb_acl,
 {
        bool ret = False;
        int i;
-       int check_which, check_rc;
 
        DEBUG(10, ("entering smb_acl_to_solaris_acl\n"));
        
@@ -717,6 +717,7 @@ static bool solaris_acl_sort(SOLARIS_ACL_T solaris_acl, int count)
        return True;
 }
 
+#if 0
 /*
  * acl check function:
  *   unused at the moment but could be used to get more
@@ -746,7 +747,7 @@ static bool solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count)
        }
        return True;
 }
-
+#endif
 
 /* VFS operations structure */
 
index 1c2c0e5f77cfd2977b6e5dfa79d139892c3baf16..023d2b9ec0a66ff5a867d41b95b0d417d4a81632 100644 (file)
@@ -153,8 +153,7 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path,
                base_sbuf = &sbuf;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, base_sbuf->st_dev,
-                                   base_sbuf->st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, base_sbuf);
 
        push_file_id_16((char *)id_buf, &id);
 
@@ -495,7 +494,13 @@ static int streams_depot_unlink(vfs_handle_struct *handle,  const char *fname)
         * We potentially need to delete the per-inode streams directory
         */
 
-       if (SMB_VFS_NEXT_STAT(handle, fname, &sbuf) == -1) {
+       if (lp_posix_pathnames()) {
+               ret = SMB_VFS_NEXT_LSTAT(handle, fname, &sbuf);
+       } else {
+               ret = SMB_VFS_NEXT_STAT(handle, fname, &sbuf);
+       }
+
+       if (ret == -1) {
                return -1;
        }
 
@@ -679,7 +684,11 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle,
                if (is_ntfs_stream_name(fname)) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
-               ret = SMB_VFS_NEXT_STAT(handle, fname, &sbuf);
+               if (lp_posix_pathnames()) {
+                       ret = SMB_VFS_NEXT_LSTAT(handle, fname, &sbuf);
+               } else {
+                       ret = SMB_VFS_NEXT_STAT(handle, fname, &sbuf);
+               }
        }
 
        if (ret == -1) {
index 77ffff5fb5a70642990e3538a9c5479d178301cb..3d5478d7a259a3ff3a864a4a98d916b85b2fb5fd 100644 (file)
@@ -135,6 +135,7 @@ static bool streams_xattr_recheck(struct stream_io *sio)
 static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
                               SMB_STRUCT_STAT *sbuf)
 {
+       int ret = -1;
        struct stream_io *io = (struct stream_io *)
                VFS_FETCH_FSP_EXTENSION(handle, fsp);
 
@@ -148,7 +149,13 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
                return -1;
        }
 
-       if (SMB_VFS_STAT(handle->conn, io->base, sbuf) == -1) {
+       if (lp_posix_pathnames()) {
+               ret = SMB_VFS_LSTAT(handle->conn, io->base, sbuf);
+       } else {
+               ret = SMB_VFS_STAT(handle->conn, io->base, sbuf);
+       }
+
+       if (ret == -1) {
                return -1;
        }
 
@@ -719,7 +726,11 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle,
                if (is_ntfs_stream_name(fname)) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
-               ret = SMB_VFS_STAT(handle->conn, fname, &sbuf);
+               if (lp_posix_pathnames()) {
+                       ret = SMB_VFS_LSTAT(handle->conn, fname, &sbuf);
+               } else {
+                       ret = SMB_VFS_STAT(handle->conn, fname, &sbuf);
+               }
        }
 
        if (ret == -1) {
index 44bfffb94eaf33255e55fbc1b6d7407fa1b83fb3..4e37ed6477bd0a1eed7171c5a45df52b1491b189 100644 (file)
@@ -100,6 +100,7 @@ static NTSTATUS xattr_tdb_load_attrs(TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        TDB_DATA data;
 
+       /* For backwards compatibility only store the dev/inode. */
        push_file_id_16((char *)id_buf, id);
 
        if (db_ctx->fetch(db_ctx, mem_ctx,
@@ -122,6 +123,8 @@ static struct db_record *xattr_tdb_lock_attrs(TALLOC_CTX *mem_ctx,
                                              const struct file_id *id)
 {
        uint8 id_buf[16];
+
+       /* For backwards compatibility only store the dev/inode. */
        push_file_id_16((char *)id_buf, id);
        return db_ctx->fetch_locked(db_ctx, mem_ctx,
                                    make_tdb_data(id_buf, sizeof(id_buf)));
@@ -216,7 +219,7 @@ static ssize_t xattr_tdb_getxattr(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
        return xattr_tdb_getattr(db, &id, name, value, size);
 }
@@ -235,7 +238,7 @@ static ssize_t xattr_tdb_fgetxattr(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
        return xattr_tdb_getattr(db, &id, name, value, size);
 }
@@ -338,7 +341,7 @@ static int xattr_tdb_setxattr(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
        return xattr_tdb_setattr(db, &id, name, value, size, flags);
 }
@@ -358,7 +361,7 @@ static int xattr_tdb_fsetxattr(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
        return xattr_tdb_setattr(db, &id, name, value, size, flags);
 }
@@ -443,7 +446,7 @@ static ssize_t xattr_tdb_listxattr(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
        return xattr_tdb_listattr(db, &id, list, size);
 }
@@ -462,7 +465,7 @@ static ssize_t xattr_tdb_flistxattr(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
        return xattr_tdb_listattr(db, &id, list, size);
 }
@@ -543,7 +546,7 @@ static int xattr_tdb_removexattr(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
        return xattr_tdb_removeattr(db, &id, name);
 }
@@ -561,7 +564,7 @@ static int xattr_tdb_fremovexattr(struct vfs_handle_struct *handle,
                return -1;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
        return xattr_tdb_removeattr(db, &id, name);
 }
@@ -628,7 +631,7 @@ static int xattr_tdb_unlink(vfs_handle_struct *handle, const char *path)
                return -1;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
        rec = xattr_tdb_lock_attrs(talloc_tos(), db, &id);
 
@@ -667,7 +670,7 @@ static int xattr_tdb_rmdir(vfs_handle_struct *handle, const char *path)
                return -1;
        }
 
-       id = SMB_VFS_FILE_ID_CREATE(handle->conn, sbuf.st_dev, sbuf.st_ino);
+       id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf);
 
        rec = xattr_tdb_lock_attrs(talloc_tos(), db, &id);
 
index adefb7d94f244c4149cfbaf5626e7280be98fda0..3279466602aa3756e716de901d996a617aad1de5 100644 (file)
@@ -412,18 +412,18 @@ static void msg_nmbd_send_packet(struct messaging_context *msg,
        const struct sockaddr_storage *pss;
        const struct in_addr *local_ip;
 
-       DEBUG(10, ("Received send_packet from %d\n", procid_to_pid(&src)));
+       DEBUG(10, ("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src)));
 
        if (data->length != sizeof(struct packet_struct)) {
-               DEBUG(2, ("Discarding invalid packet length from %d\n",
-                         procid_to_pid(&src)));
+               DEBUG(2, ("Discarding invalid packet length from %u\n",
+                         (unsigned int)procid_to_pid(&src)));
                return;
        }
 
        if ((p->packet_type != NMB_PACKET) &&
            (p->packet_type != DGRAM_PACKET)) {
-               DEBUG(2, ("Discarding invalid packet type from %d: %d\n",
-                         procid_to_pid(&src), p->packet_type));
+               DEBUG(2, ("Discarding invalid packet type from %u: %d\n",
+                         (unsigned int)procid_to_pid(&src), p->packet_type));
                return;
        }
 
@@ -431,8 +431,8 @@ static void msg_nmbd_send_packet(struct messaging_context *msg,
        pss = iface_ip((struct sockaddr *)&ss);
 
        if (pss == NULL) {
-               DEBUG(2, ("Could not find ip for packet from %d\n",
-                         procid_to_pid(&src)));
+               DEBUG(2, ("Could not find ip for packet from %u\n",
+                         (unsigned int)procid_to_pid(&src)));
                return;
        }
 
index 37af7038c1e09cddef711bf3d6a9f5d46209c2a4..89c706d874683e91fee681d74e1b4b5abd0ba48c 100644 (file)
@@ -144,7 +144,6 @@ struct global {
        int iAfsTokenLifetime;
        char *szLogNtTokenCommand;
        char *szUsernameMap;
-       bool bForceUsernameMap;
        char *szLogonScript;
        char *szLogonPath;
        char *szLogonDrive;
@@ -1282,15 +1281,6 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
-       {
-               .label          = "force username map",
-               .type           = P_BOOL,
-               .p_class        = P_GLOBAL,
-               .ptr            = &Globals.bForceUsernameMap,
-               .special        = NULL,
-               .enum_list      = NULL,
-               .flags          = FLAG_ADVANCED,
-       },
        {
                .label          = "password level",
                .type           = P_INTEGER,
@@ -4657,6 +4647,41 @@ static void init_printer_values(struct service *pService)
 
        }
 }
+/**
+ *  Function to return the default value for the maximum number of open
+ *  file descriptors permitted.  This function tries to consult the
+ *  kernel-level (sysctl) and ulimit (getrlimit()) values and goes
+ *  the smaller of those.
+ */
+static int max_open_files(void)
+{
+       int sysctl_max = MAX_OPEN_FILES;
+       int rlimit_max = MAX_OPEN_FILES;
+
+#ifdef HAVE_SYSCTLBYNAME
+       {
+               size_t size = sizeof(sysctl_max);
+               sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
+                            0);
+       }
+#endif
+
+#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
+       {
+               struct rlimit rl = {};
+
+               if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
+                       rlimit_max = rl.rlim_cur;
+
+#if defined(RLIM_INFINITY)
+               if(rl.rlim_cur == RLIM_INFINITY)
+                       rlimit_max = MAX_OPEN_FILES;
+       }
+#endif
+#endif
+
+       return MIN(sysctl_max, rlimit_max);
+}
 
 /**
  * Common part of freeing allocated data for one parameter.
@@ -4880,7 +4905,7 @@ static void init_globals(bool first_time_only)
        Globals.getwd_cache = true;
        Globals.bLargeReadwrite = True;
        Globals.max_log_size = 5000;
-       Globals.max_open_files = MAX_OPEN_FILES;
+       Globals.max_open_files = max_open_files();
        Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
        Globals.maxprotocol = PROTOCOL_NT1;
        Globals.minprotocol = PROTOCOL_CORE;
@@ -5210,7 +5235,6 @@ FN_GLOBAL_CONST_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap)
 FN_GLOBAL_INTEGER(lp_afs_token_lifetime, &Globals.iAfsTokenLifetime)
 FN_GLOBAL_STRING(lp_log_nt_token_command, &Globals.szLogNtTokenCommand)
 FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
-FN_GLOBAL_BOOL(lp_force_username_map, &Globals.bForceUsernameMap)
 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
index 486b5b1b80cd8f6a803a583dd4cf38d2ddc23acc..e618b425e0ceeb9561765155b472657b4345f370 100644 (file)
@@ -1947,7 +1947,7 @@ void pdb_search_destroy(struct pdb_search *search)
 }
 
 /*******************************************************************
- trustodm methods
+ trustdom methods
  *******************************************************************/
 
 bool pdb_get_trusteddom_pw(const char *domain, char** pwd, DOM_SID *sid, 
index 043b6207560c5f71906c0ea47aee6c95b6541e7f..70a1c62bef8f447031a09e1469c32c832f6ad5c4 100644 (file)
@@ -1249,7 +1249,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), 
                        pdb_get_profile_path(sampass));
 
-       if (asprintf(&temp, "%li", pdb_get_logon_time(sampass)) < 0) {
+       if (asprintf(&temp, "%li", (long int)pdb_get_logon_time(sampass)) < 0) {
                return false;
        }
        if (need_update(sampass, PDB_LOGONTIME))
@@ -1257,7 +1257,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp);
        SAFE_FREE(temp);
 
-       if (asprintf(&temp, "%li", pdb_get_logoff_time(sampass)) < 0) {
+       if (asprintf(&temp, "%li", (long int)pdb_get_logoff_time(sampass)) < 0) {
                return false;
        }
        if (need_update(sampass, PDB_LOGOFFTIME))
@@ -1265,7 +1265,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp);
        SAFE_FREE(temp);
 
-       if (asprintf(&temp, "%li", pdb_get_kickoff_time(sampass)) < 0) {
+       if (asprintf(&temp, "%li", (long int)pdb_get_kickoff_time(sampass)) < 0) {
                return false;
        }
        if (need_update(sampass, PDB_KICKOFFTIME))
@@ -1273,7 +1273,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
        SAFE_FREE(temp);
 
-       if (asprintf(&temp, "%li", pdb_get_pass_can_change_time_noncalc(sampass)) < 0) {
+       if (asprintf(&temp, "%li", (long int)pdb_get_pass_can_change_time_noncalc(sampass)) < 0) {
                return false;
        }
        if (need_update(sampass, PDB_CANCHANGETIME))
@@ -1281,7 +1281,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                        get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
        SAFE_FREE(temp);
 
-       if (asprintf(&temp, "%li", pdb_get_pass_must_change_time(sampass)) < 0) {
+       if (asprintf(&temp, "%li", (long int)pdb_get_pass_must_change_time(sampass)) < 0) {
                return false;
        }
        if (need_update(sampass, PDB_MUSTCHANGETIME))
@@ -1361,7 +1361,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
 
                if (need_update(sampass, PDB_PASSLASTSET)) {
                        if (asprintf(&temp, "%li",
-                               pdb_get_pass_last_set_time(sampass)) < 0) {
+                               (long int)pdb_get_pass_last_set_time(sampass)) < 0) {
                                return false;
                        }
                        smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
@@ -1423,7 +1423,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                                temp);
                        SAFE_FREE(temp);
 
-                       if (asprintf(&temp, "%li", badtime) < 0) {
+                       if (asprintf(&temp, "%li", (long int)badtime) < 0) {
                                return false;
                        }
                        smbldap_make_mod(
@@ -5941,7 +5941,7 @@ static bool ldapsam_set_trusteddom_pw(struct pdb_methods *methods,
        smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaSID",
                         sid_string_tos(sid));
        smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaPwdLastSet",
-                        talloc_asprintf(talloc_tos(), "%li", time(NULL)));
+                        talloc_asprintf(talloc_tos(), "%li", (long int)time(NULL)));
        smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
                         "sambaClearTextPassword", pwd);
 
diff --git a/source3/passdb/pdb_wbc_sam.c b/source3/passdb/pdb_wbc_sam.c
new file mode 100644 (file)
index 0000000..d2c7fda
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Password and authentication handling by wbclient
+
+   Copyright (C) Andrew Bartlett                       2002
+   Copyright (C) Jelmer Vernooij                       2002
+   Copyright (C) Simo Sorce                            2003
+   Copyright (C) Volker Lendecke                       2006
+   Copyright (C) Dan Sledz                             2009
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* This passdb module retrieves full passdb information for local users and
+ * groups from a wbclient compatible daemon.
+ *
+ * The purpose of this module is to defer all SAM authorization information
+ * storage and retrieval to a wbc compatible daemon.
+ *
+ * This passdb backend is most useful when used in conjunction with auth_wbc.
+ *
+ * A few current limitations of this module are:
+ *   - read only interface
+ *   - no privileges
+ */
+
+#include "includes.h"
+
+/***************************************************************************
+  Default implementations of some functions.
+ ****************************************************************************/
+static NTSTATUS _pdb_wbc_sam_getsampw(struct pdb_methods *methods,
+                                      struct samu *user,
+                                      const struct passwd *pwd)
+{
+       NTSTATUS result = NT_STATUS_OK;
+
+       if (pwd == NULL)
+               return NT_STATUS_NO_SUCH_USER;
+
+       memset(user, 0, sizeof(user));
+
+        /* Can we really get away with this little of information */
+       user->methods = methods;
+       result = samu_set_unix(user, pwd);
+
+       return result;
+}
+
+static NTSTATUS pdb_wbc_sam_getsampwnam(struct pdb_methods *methods, struct samu *user, const char *sname)
+{
+       return _pdb_wbc_sam_getsampw(methods, user, winbind_getpwnam(sname));
+}
+
+static NTSTATUS pdb_wbc_sam_getsampwsid(struct pdb_methods *methods, struct samu *user, const DOM_SID *sid)
+{
+       return _pdb_wbc_sam_getsampw(methods, user, winbind_getpwsid(sid));
+}
+
+static bool pdb_wbc_sam_uid_to_sid(struct pdb_methods *methods, uid_t uid,
+                                  DOM_SID *sid)
+{
+       return winbind_uid_to_sid(sid, uid);
+}
+
+static bool pdb_wbc_sam_gid_to_sid(struct pdb_methods *methods, gid_t gid,
+                                  DOM_SID *sid)
+{
+       return winbind_gid_to_sid(sid, gid);
+}
+
+static bool pdb_wbc_sam_sid_to_id(struct pdb_methods *methods,
+                                 const DOM_SID *sid,
+                                 union unid_t *id, enum lsa_SidType *type)
+{
+       if (winbind_sid_to_uid(&id->uid, sid)) {
+               *type = SID_NAME_USER;
+       } else if (winbind_sid_to_gid(&id->gid, sid)) {
+               /* We assume all gids are groups, not aliases */
+               *type = SID_NAME_DOM_GRP;
+       } else {
+               return false;
+       }
+
+       return true;
+}
+
+static NTSTATUS pdb_wbc_sam_enum_group_members(struct pdb_methods *methods,
+                                              TALLOC_CTX *mem_ctx,
+                                              const DOM_SID *group,
+                                              uint32 **pp_member_rids,
+                                              size_t *p_num_members)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_wbc_sam_enum_group_memberships(struct pdb_methods *methods,
+                                                  TALLOC_CTX *mem_ctx,
+                                                  struct samu *user,
+                                                  DOM_SID **pp_sids,
+                                                  gid_t **pp_gids,
+                                                  size_t *p_num_groups)
+{
+       size_t i;
+       const char *username = pdb_get_username(user);
+       uint32_t num_groups;
+
+       if (!winbind_get_groups(mem_ctx, username, &num_groups, pp_gids)) {
+               return NT_STATUS_NO_SUCH_USER;
+       }
+       *p_num_groups = num_groups;
+
+       if (*p_num_groups == 0) {
+               smb_panic("primary group missing");
+       }
+
+       *pp_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *p_num_groups);
+
+       if (*pp_sids == NULL) {
+               TALLOC_FREE(*pp_gids);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i < *p_num_groups; i++) {
+               gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]);
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_wbc_sam_lookup_rids(struct pdb_methods *methods,
+                                       const DOM_SID *domain_sid,
+                                       int num_rids,
+                                       uint32 *rids,
+                                       const char **names,
+                                       enum lsa_SidType *attrs)
+{
+       NTSTATUS result = NT_STATUS_OK;
+       char *domain = NULL;
+       char **account_names = NULL;
+       char name[256];
+       enum lsa_SidType *attr_list = NULL;
+       int i;
+
+       if (!winbind_lookup_rids(talloc_tos(), domain_sid, num_rids, rids,
+                                (const char **)&domain,
+                                (const char ***)&account_names, &attr_list))
+       {
+               result = NT_STATUS_NONE_MAPPED;
+               goto done;
+       }
+
+       memcpy(attrs, attr_list, num_rids * sizeof(enum lsa_SidType));
+
+       for (i=0; i<num_rids; i++) {
+               if (attrs[i] == SID_NAME_UNKNOWN) {
+                       names[i] = NULL;
+               } else {
+                       snprintf(name, sizeof(name), "%s%c%s", domain,
+                                *lp_winbind_separator(), account_names[i]);
+                       names[i] = talloc_strdup(names, name);
+               }
+       }
+
+done:
+       TALLOC_FREE(account_names);
+       TALLOC_FREE(domain);
+       TALLOC_FREE(attrs);
+       return result;
+}
+
+static NTSTATUS pdb_wbc_sam_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value)
+{
+       return NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS pdb_wbc_sam_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value)
+{
+       return NT_STATUS_UNSUCCESSFUL;
+}
+
+static bool pdb_wbc_sam_search_groups(struct pdb_methods *methods,
+                                     struct pdb_search *search)
+{
+       return false;
+}
+
+static bool pdb_wbc_sam_search_aliases(struct pdb_methods *methods,
+                                      struct pdb_search *search,
+                                      const DOM_SID *sid)
+{
+
+       return false;
+}
+
+static bool pdb_wbc_sam_get_trusteddom_pw(struct pdb_methods *methods,
+                                         const char *domain,
+                                         char **pwd,
+                                         DOM_SID *sid,
+                                         time_t *pass_last_set_time)
+{
+       return false;
+
+}
+
+static bool pdb_wbc_sam_set_trusteddom_pw(struct pdb_methods *methods,
+                                         const char *domain,
+                                         const char *pwd,
+                                         const DOM_SID *sid)
+{
+       return false;
+}
+
+static bool pdb_wbc_sam_del_trusteddom_pw(struct pdb_methods *methods,
+                                         const char *domain)
+{
+       return false;
+}
+
+static NTSTATUS pdb_wbc_sam_enum_trusteddoms(struct pdb_methods *methods,
+                                            TALLOC_CTX *mem_ctx,
+                                            uint32 *num_domains,
+                                            struct trustdom_info ***domains)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static bool _make_group_map(struct pdb_methods *methods, const char *domain, const char *name, enum lsa_SidType name_type, gid_t gid, DOM_SID *sid, GROUP_MAP *map)
+{
+       snprintf(map->nt_name, sizeof(map->nt_name), "%s%c%s",
+               domain, *lp_winbind_separator(), name);
+       map->sid_name_use = name_type;
+       map->sid = *sid;
+       map->gid = gid;
+       return true;
+}
+
+static NTSTATUS pdb_wbc_sam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
+                                DOM_SID sid)
+{
+       NTSTATUS result = NT_STATUS_OK;
+       char *name = NULL;
+       char *domain = NULL;
+       enum lsa_SidType name_type;
+       gid_t gid;
+
+       if (!winbind_lookup_sid(talloc_tos(), &sid, (const char **)&domain,
+                               (const char **) &name, &name_type)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+       if ((name_type != SID_NAME_DOM_GRP) &&
+           (name_type != SID_NAME_DOMAIN) &&
+           (name_type != SID_NAME_ALIAS) &&
+           (name_type != SID_NAME_WKN_GRP)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+       if (!winbind_sid_to_gid(&gid, &sid)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+       if (!_make_group_map(methods, domain, name, name_type, gid, &sid, map)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+done:
+       TALLOC_FREE(name);
+       TALLOC_FREE(domain);
+       return result;
+}
+
+static NTSTATUS pdb_wbc_sam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
+                                gid_t gid)
+{
+       NTSTATUS result = NT_STATUS_OK;
+       char *name = NULL;
+       char *domain = NULL;
+       DOM_SID sid;
+       enum lsa_SidType name_type;
+
+       if (!winbind_gid_to_sid(&sid, gid)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+       if (!winbind_lookup_sid(talloc_tos(), &sid, (const char **)&domain,
+                               (const char **)&name, &name_type)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+       if ((name_type != SID_NAME_DOM_GRP) &&
+           (name_type != SID_NAME_DOMAIN) &&
+           (name_type != SID_NAME_ALIAS) &&
+           (name_type != SID_NAME_WKN_GRP)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+       if (!_make_group_map(methods, domain, name, name_type, gid, &sid, map)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+done:
+       TALLOC_FREE(name);
+       TALLOC_FREE(domain);
+
+       return result;
+}
+
+static NTSTATUS pdb_wbc_sam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
+                                const char *name)
+{
+       NTSTATUS result = NT_STATUS_OK;
+       char *user_name = NULL;
+       char *domain = NULL;
+       DOM_SID sid;
+       gid_t gid;
+       enum lsa_SidType name_type;
+
+       if (!winbind_lookup_name(domain, user_name, &sid, &name_type)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+       if ((name_type != SID_NAME_DOM_GRP) &&
+           (name_type != SID_NAME_DOMAIN) &&
+           (name_type != SID_NAME_ALIAS) &&
+           (name_type != SID_NAME_WKN_GRP)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+       if (!winbind_sid_to_gid(&gid, &sid)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+       if (!_make_group_map(methods, domain, user_name, name_type, gid, &sid, map)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+done:
+
+       return result;
+}
+
+static NTSTATUS pdb_wbc_sam_enum_group_mapping(struct pdb_methods *methods,
+                                          const DOM_SID *sid, enum lsa_SidType sid_name_use,
+                                          GROUP_MAP **pp_rmap, size_t *p_num_entries,
+                                          bool unix_only)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_wbc_sam_get_aliasinfo(struct pdb_methods *methods,
+                                  const DOM_SID *sid,
+                                  struct acct_info *info)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_wbc_sam_enum_aliasmem(struct pdb_methods *methods,
+                                  const DOM_SID *alias, DOM_SID **pp_members,
+                                  size_t *p_num_members)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_wbc_sam_alias_memberships(struct pdb_methods *methods,
+                                      TALLOC_CTX *mem_ctx,
+                                      const DOM_SID *domain_sid,
+                                      const DOM_SID *members,
+                                      size_t num_members,
+                                      uint32 **pp_alias_rids,
+                                      size_t *p_num_alias_rids)
+{
+       if (!winbind_get_sid_aliases(mem_ctx, domain_sid,
+                   members, num_members, pp_alias_rids, p_num_alias_rids))
+               return NT_STATUS_UNSUCCESSFUL;
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_init_wbc_sam(struct pdb_methods **pdb_method, const char *location)
+{
+       NTSTATUS result;
+
+       if (!NT_STATUS_IS_OK(result = make_pdb_method( pdb_method))) {
+               return result;
+       }
+
+       (*pdb_method)->name = "wbc_sam";
+
+       (*pdb_method)->getsampwnam = pdb_wbc_sam_getsampwnam;
+       (*pdb_method)->getsampwsid = pdb_wbc_sam_getsampwsid;
+
+       (*pdb_method)->getgrsid = pdb_wbc_sam_getgrsid;
+       (*pdb_method)->getgrgid = pdb_wbc_sam_getgrgid;
+       (*pdb_method)->getgrnam = pdb_wbc_sam_getgrnam;
+       (*pdb_method)->enum_group_mapping = pdb_wbc_sam_enum_group_mapping;
+       (*pdb_method)->enum_group_members = pdb_wbc_sam_enum_group_members;
+       (*pdb_method)->enum_group_memberships = pdb_wbc_sam_enum_group_memberships;
+       (*pdb_method)->get_aliasinfo = pdb_wbc_sam_get_aliasinfo;
+       (*pdb_method)->enum_aliasmem = pdb_wbc_sam_enum_aliasmem;
+       (*pdb_method)->enum_alias_memberships = pdb_wbc_sam_alias_memberships;
+       (*pdb_method)->lookup_rids = pdb_wbc_sam_lookup_rids;
+       (*pdb_method)->get_account_policy = pdb_wbc_sam_get_account_policy;
+       (*pdb_method)->set_account_policy = pdb_wbc_sam_set_account_policy;
+       (*pdb_method)->uid_to_sid = pdb_wbc_sam_uid_to_sid;
+       (*pdb_method)->gid_to_sid = pdb_wbc_sam_gid_to_sid;
+       (*pdb_method)->sid_to_id = pdb_wbc_sam_sid_to_id;
+
+       (*pdb_method)->search_groups = pdb_wbc_sam_search_groups;
+       (*pdb_method)->search_aliases = pdb_wbc_sam_search_aliases;
+
+       (*pdb_method)->get_trusteddom_pw = pdb_wbc_sam_get_trusteddom_pw;
+       (*pdb_method)->set_trusteddom_pw = pdb_wbc_sam_set_trusteddom_pw;
+       (*pdb_method)->del_trusteddom_pw = pdb_wbc_sam_del_trusteddom_pw;
+       (*pdb_method)->enum_trusteddoms  = pdb_wbc_sam_enum_trusteddoms;
+
+       (*pdb_method)->private_data = NULL;
+       (*pdb_method)->free_private_data = NULL;
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS pdb_wbc_sam_init(void)
+{
+       return smb_register_passdb(PASSDB_INTERFACE_VERSION, "wbc_sam", pdb_init_wbc_sam);
+}
index d478b86f9142bb65f88a2a69c08897d2d0330548..e19212eea8c74f97e0d6d4475d21d3e19c134ad8 100644 (file)
@@ -397,8 +397,10 @@ void notify_printer_status_byname(const char *sharename, uint32 status)
 {
        /* Printer status stored in value1 */
 
+       int snum = print_queue_snum(sharename);
+
        send_notify_field_values(sharename, PRINTER_NOTIFY_TYPE, 
-                                PRINTER_NOTIFY_STATUS, 0, 
+                                PRINTER_NOTIFY_STATUS, snum,
                                 status, 0, 0);
 }
 
index ad3a95826a2ffa2512ca63c8841e1620152e6a04..d8658e9280f569c290121107e384fa9ee9820666 100644 (file)
@@ -1381,7 +1381,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                                 goto error_exit;
                        }
                        old_create_time = st.st_mtime;
-                       DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
+                       DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
+                               (long)old_create_time));
                }
        }
        close_file(NULL, fsp, NORMAL_CLOSE);
@@ -1432,7 +1433,8 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
                                goto error_exit;
                        }
                        new_create_time = st.st_mtime;
-                       DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
+                       DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
+                               (long)new_create_time));
                }
        }
        close_file(NULL, fsp, NORMAL_CLOSE);
@@ -3423,8 +3425,8 @@ WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
                goto done;
 
        switch (action) {
-       case SPOOL_DS_PUBLISH:
-       case SPOOL_DS_UPDATE:
+       case DSPRINT_PUBLISH:
+       case DSPRINT_UPDATE:
                /* set the DsSpooler info and attributes */
                if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
                        win_rc = WERR_NOMEM;
@@ -3433,7 +3435,7 @@ WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
 
                printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
                break;
-       case SPOOL_DS_UNPUBLISH:
+       case DSPRINT_UNPUBLISH:
                printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
                break;
        default:
@@ -3467,11 +3469,11 @@ WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
        }
 
        switch (action) {
-       case SPOOL_DS_PUBLISH:
-       case SPOOL_DS_UPDATE:
+       case DSPRINT_PUBLISH:
+       case DSPRINT_UPDATE:
                win_rc = nt_printer_publish_ads(ads, printer);
                break;
-       case SPOOL_DS_UNPUBLISH:
+       case DSPRINT_UNPUBLISH:
                win_rc = nt_printer_unpublish_ads(ads, printer);
                break;
        }
@@ -5408,11 +5410,12 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
 {
        SEC_DESC_BUF *new_secdesc_ctr = NULL;
        SEC_DESC_BUF *old_secdesc_ctr = NULL;
-       prs_struct ps;
-       bool prs_init_done = false;
        TALLOC_CTX *mem_ctx = NULL;
        TDB_DATA kbuf;
+       TDB_DATA dbuf;
+       DATA_BLOB blob;
        WERROR status;
+       NTSTATUS nt_status;
 
        mem_ctx = talloc_init("nt_printing_setsec");
        if (mem_ctx == NULL)
@@ -5474,26 +5477,19 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
 
        /* Store the security descriptor in a tdb */
 
-       if (!prs_init(&ps,
-               (uint32_t)ndr_size_security_descriptor(new_secdesc_ctr->sd,
-                                                    NULL, 0)
-               + sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL) ) {
-               status = WERR_NOMEM;
-               goto out;
-       }
-
-
-       prs_init_done = true;
-
-       if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
-                            &ps, 1)) {
-               status = WERR_BADFUNC;
+       nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
+                                         &blob.data, &blob.length);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               status = ntstatus_to_werror(nt_status);
                goto out;
        }
 
        kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
 
-       if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
+       dbuf.dptr = (unsigned char *)blob.data;
+       dbuf.dsize = blob.length;
+
+       if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
                status = WERR_OK;
        } else {
                DEBUG(1,("Failed to store secdesc for %s\n", sharename));
@@ -5501,12 +5497,10 @@ WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
        }
 
        /* Free malloc'ed memory */
+       talloc_free(blob.data);
 
  out:
 
-       if (prs_init_done) {
-               prs_mem_free(&ps);
-       }
        if (mem_ctx)
                talloc_destroy(mem_ctx);
        return status;
@@ -5602,47 +5596,45 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
 
 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
 {
-       prs_struct ps;
        TDB_DATA kbuf;
+       TDB_DATA dbuf;
+       DATA_BLOB blob;
        char *temp;
+       NTSTATUS status;
 
        if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
                sharename = temp + 1;
        }
 
-       ZERO_STRUCT(ps);
-
        /* Fetch security descriptor from tdb */
 
-       kbuf = make_printers_secdesc_tdbkey(ctx, sharename  );
-
-       if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
-           !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
-
-               prs_mem_free(&ps);
-
-               DEBUG(4,("using default secdesc for %s\n", sharename));
+       kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
 
-               if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
-                       return False;
-               }
-
-               /* Save default security descriptor for later */
+       dbuf = tdb_fetch(tdb_printers, kbuf);
+       if (dbuf.dptr) {
 
-               if (!prs_init(&ps, (uint32_t)ndr_size_security_descriptor((*secdesc_ctr)->sd, NULL, 0) +
-                       sizeof(SEC_DESC_BUF), ctx, MARSHALL))
-                       return False;
+               status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
+                                                secdesc_ctr);
+               SAFE_FREE(dbuf.dptr);
 
-               if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
-                       tdb_prs_store(tdb_printers, kbuf, &ps);
+               if (NT_STATUS_IS_OK(status)) {
+                       return true;
                }
+       }
 
-               prs_mem_free(&ps);
-
-               return True;
+       *secdesc_ctr = construct_default_printer_sdb(ctx);
+       if (!*secdesc_ctr) {
+               return false;
        }
 
-       prs_mem_free(&ps);
+       status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
+                                      &blob.data, &blob.length);
+       if (NT_STATUS_IS_OK(status)) {
+               dbuf.dptr = (unsigned char *)blob.data;
+               dbuf.dsize = blob.length;
+               tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
+               talloc_free(blob.data);
+       }
 
        /* If security descriptor is owned by S-1-1-0 and winbindd is up,
           this security descriptor has been created when winbindd was
index b485711f910bd67203f80463e67c4780501c62ad..243b8ea03b7763538bcdb53427b1ca4daa624aba 100644 (file)
@@ -88,7 +88,6 @@ NTSTATUS print_fsp_open(struct smb_request *req, connection_struct *conn,
 void print_fsp_end(files_struct *fsp, enum file_close_type close_type)
 {
        uint32 jobid;
-       fstring sharename;
 
        if (fsp->fh->private_options & FILE_DELETE_ON_CLOSE) {
                /*
@@ -102,7 +101,7 @@ void print_fsp_end(files_struct *fsp, enum file_close_type close_type)
                string_free(&fsp->fsp_name);
        }
 
-       if (!rap_to_pjobid(fsp->rap_print_jobid, sharename, &jobid)) {
+       if (!rap_to_pjobid(fsp->rap_print_jobid, NULL, &jobid)) {
                DEBUG(3,("print_fsp_end: Unable to convert RAP jobid %u to print jobid.\n",
                        (unsigned int)fsp->rap_print_jobid ));
                return;
index 7179184b735542a5b9dc6ef63a99fd9823b828d6..fc3667ea3a959ff5a0041ed28ab6a4d99be34d56 100644 (file)
@@ -117,7 +117,9 @@ bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
        if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
        {
                struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
-               fstrcpy( sharename, jinfo->sharename );
+               if (sharename != NULL) {
+                       fstrcpy( sharename, jinfo->sharename );
+               }
                *pjobid = jinfo->jobid;
                DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
                        (unsigned int)*pjobid, (unsigned int)rap_jobid));
@@ -447,7 +449,7 @@ static const struct {
        { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
        { LPQ_PRINTED, JOB_STATUS_PRINTED },
        { LPQ_DELETED, JOB_STATUS_DELETED },
-       { LPQ_BLOCKED, JOB_STATUS_BLOCKED },
+       { LPQ_BLOCKED, JOB_STATUS_BLOCKED_DEVQ },
        { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
        { -1, 0 }
 };
index 15459889e9fc50ffd55171b8e14eefbc158d4bc6..286e4a4b39bd532d82fd6c7be8a659fbd599f181 100644 (file)
@@ -168,7 +168,7 @@ static int lpq_command(int argc, char **argv)
                       job_list[i].size, 
                       (i == 0 && job_list[i].status == LPQ_QUEUED) ? 
                       LPQ_SPOOLING : job_list[i].status,
-                      job_list[i].submit_time, job_list[i].owner, 
+                      (long int)job_list[i].submit_time, job_list[i].owner, 
                       job_list[i].jobname);
                job_count++;
        }
index bdbd8057183b835abb14c2680bc12f83672f0e12..6d2d5ae06d8ebda6b9b38aecc47767904e66b08e 100644 (file)
@@ -290,6 +290,7 @@ bool profile_setup(struct messaging_context *msg_ctx, bool rdonly)
            "syscall_rmdir",            /* PR_VALUE_SYSCALL_RMDIR */
            "syscall_closedir",         /* PR_VALUE_SYSCALL_CLOSEDIR */
            "syscall_open",             /* PR_VALUE_SYSCALL_OPEN */
+           "syscall_createfile",       /* PR_VALUE_SYSCALL_CREATEFILE */
            "syscall_close",            /* PR_VALUE_SYSCALL_CLOSE */
            "syscall_read",             /* PR_VALUE_SYSCALL_READ */
            "syscall_pread",            /* PR_VALUE_SYSCALL_PREAD */
@@ -299,6 +300,7 @@ bool profile_setup(struct messaging_context *msg_ctx, bool rdonly)
            "syscall_sendfile",         /* PR_VALUE_SYSCALL_SENDFILE */
            "syscall_recvfile",         /* PR_VALUE_SYSCALL_RECVFILE */
            "syscall_rename",           /* PR_VALUE_SYSCALL_RENAME */
+           "syscall_rename_at",        /* PR_VALUE_SYSCALL_RENAME_AT */
            "syscall_fsync",            /* PR_VALUE_SYSCALL_FSYNC */
            "syscall_stat",             /* PR_VALUE_SYSCALL_STAT */
            "syscall_fstat",            /* PR_VALUE_SYSCALL_FSTAT */
@@ -323,6 +325,11 @@ bool profile_setup(struct messaging_context *msg_ctx, bool rdonly)
            "syscall_realpath",         /* PR_VALUE_SYSCALL_REALPATH */
            "syscall_get_quota",        /* PR_VALUE_SYSCALL_GET_QUOTA */
            "syscall_set_quota",        /* PR_VALUE_SYSCALL_SET_QUOTA */
+           "syscall_get_sd",           /* PR_VALUE_SYSCALL_GET_SD */
+           "syscall_set_sd",           /* PR_VALUE_SYSCALL_SET_SD */
+           "syscall_brl_lock",         /* PR_VALUE_SYSCALL_BRL_LOCK */
+           "syscall_brl_unlock",       /* PR_VALUE_SYSCALL_BRL_UNLOCK */
+           "syscall_brl_cancel",       /* PR_VALUE_SYSCALL_BRL_CANCEL */
            "SMBmkdir",         /* PR_VALUE_SMBMKDIR */
            "SMBrmdir",         /* PR_VALUE_SMBRMDIR */
            "SMBopen",          /* PR_VALUE_SMBOPEN */
index a5f3935821b4827364942d54bbbe930083fb77af..67767a2e561ae9b0f58c6f79f2e5d2fd1ca8a042 100644 (file)
@@ -94,15 +94,16 @@ static WERROR fill_value_cache(struct registry_key *key)
 
 static WERROR fill_subkey_cache(struct registry_key *key)
 {
+       WERROR werr;
+
        if (key->subkeys != NULL) {
                if (!reg_subkeys_need_update(key->key, key->subkeys)) {
                        return WERR_OK;
                }
        }
 
-       if (!(key->subkeys = TALLOC_ZERO_P(key, REGSUBKEY_CTR))) {
-               return WERR_NOMEM;
-       }
+       werr = regsubkey_ctr_init(key, &(key->subkeys));
+       W_ERROR_NOT_OK_RETURN(werr);
 
        if (fetch_reg_keys(key->key, key->subkeys) == -1) {
                TALLOC_FREE(key->subkeys);
@@ -127,7 +128,7 @@ static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
        WERROR          result = WERR_OK;
        struct registry_key *regkey;
        REGISTRY_KEY *key;
-       REGSUBKEY_CTR   *subkeys = NULL;
+       struct regsubkey_ctr    *subkeys = NULL;
 
        DEBUG(7,("regkey_open_onelevel: name = [%s]\n", name));
 
@@ -193,8 +194,8 @@ static WERROR regkey_open_onelevel(TALLOC_CTX *mem_ctx,
        /* check if the path really exists; failed is indicated by -1 */
        /* if the subkey count failed, bail out */
 
-       if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) {
-               result = WERR_NOMEM;
+       result = regsubkey_ctr_init(key, &subkeys);
+       if (!W_ERROR_IS_OK(result)) {
                goto done;
        }
 
@@ -308,11 +309,13 @@ WERROR reg_enumkey(TALLOC_CTX *mem_ctx, struct registry_key *key,
                return err;
        }
 
-       if (idx >= key->subkeys->num_subkeys) {
+       if (idx >= regsubkey_ctr_numkeys(key->subkeys)) {
                return WERR_NO_MORE_ITEMS;
        }
 
-       if (!(*name = talloc_strdup(mem_ctx, key->subkeys->subkeys[idx]))) {
+       if (!(*name = talloc_strdup(mem_ctx,
+                       regsubkey_ctr_specific_key(key->subkeys, idx))))
+       {
                return WERR_NOMEM;
        }
 
@@ -406,11 +409,12 @@ WERROR reg_queryinfokey(struct registry_key *key, uint32_t *num_subkeys,
        }
 
        max_len = 0;
-       for (i=0; i<key->subkeys->num_subkeys; i++) {
-               max_len = MAX(max_len, strlen(key->subkeys->subkeys[i]));
+       for (i=0; i< regsubkey_ctr_numkeys(key->subkeys); i++) {
+               max_len = MAX(max_len,
+                       strlen(regsubkey_ctr_specific_key(key->subkeys, i)));
        }
 
-       *num_subkeys = key->subkeys->num_subkeys;
+       *num_subkeys = regsubkey_ctr_numkeys(key->subkeys);
        *max_subkeylen = max_len;
        *max_subkeysize = 0;    /* Class length? */
 
@@ -520,14 +524,8 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
        err = fill_subkey_cache(create_parent);
        if (!W_ERROR_IS_OK(err)) goto done;
 
-       err = regsubkey_ctr_addkey(create_parent->subkeys, path);
-       if (!W_ERROR_IS_OK(err)) goto done;
-
-       if (!store_reg_keys(create_parent->key, create_parent->subkeys)) {
-               TALLOC_FREE(create_parent->subkeys);
-               err = WERR_REG_IO_FAILURE;
-               goto done;
-       }
+       err = create_reg_subkey(key->key, path);
+       W_ERROR_NOT_OK_GOTO_DONE(err);
 
        /*
         * Now open the newly created key
@@ -546,40 +544,36 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
 WERROR reg_deletekey(struct registry_key *parent, const char *path)
 {
        WERROR err;
-       TALLOC_CTX *mem_ctx;
        char *name, *end;
-       int num_subkeys;
        struct registry_key *tmp_key, *key;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
 
-       if (!(mem_ctx = talloc_init("reg_createkey"))) return WERR_NOMEM;
-
-       if (!(name = talloc_strdup(mem_ctx, path))) {
+       name = talloc_strdup(mem_ctx, path);
+       if (name == NULL) {
                err = WERR_NOMEM;
-               goto error;
+               goto done;
        }
 
        /* check if the key has subkeys */
        err = reg_openkey(mem_ctx, parent, name, REG_KEY_READ, &key);
-       if (!W_ERROR_IS_OK(err)) {
-               goto error;
-       }
-       if (!W_ERROR_IS_OK(err = fill_subkey_cache(key))) {
-               goto error;
-       }
-       if (key->subkeys->num_subkeys > 0) {
+       W_ERROR_NOT_OK_GOTO_DONE(err);
+
+       err = fill_subkey_cache(key);
+       W_ERROR_NOT_OK_GOTO_DONE(err);
+
+       if (regsubkey_ctr_numkeys(key->subkeys) > 0) {
                err = WERR_ACCESS_DENIED;
-               goto error;
+               goto done;
        }
 
        /* no subkeys - proceed with delete */
-       if ((end = strrchr(name, '\\')) != NULL) {
+       end = strrchr(name, '\\');
+       if (end != NULL) {
                *end = '\0';
 
                err = reg_openkey(mem_ctx, parent, name,
                                  SEC_RIGHTS_CREATE_SUBKEY, &tmp_key);
-               if (!W_ERROR_IS_OK(err)) {
-                       goto error;
-               }
+               W_ERROR_NOT_OK_GOTO_DONE(err);
 
                parent = tmp_key;
                name = end+1;
@@ -587,31 +581,12 @@ WERROR reg_deletekey(struct registry_key *parent, const char *path)
 
        if (name[0] == '\0') {
                err = WERR_INVALID_PARAM;
-               goto error;
-       }
-
-       if (!W_ERROR_IS_OK(err = fill_subkey_cache(parent))) {
-               goto error;
-       }
-
-       num_subkeys = parent->subkeys->num_subkeys;
-
-       if (regsubkey_ctr_delkey(parent->subkeys, name) == num_subkeys) {
-               err = WERR_BADFILE;
-               goto error;
-       }
-
-       if (!store_reg_keys(parent->key, parent->subkeys)) {
-               TALLOC_FREE(parent->subkeys);
-               err = WERR_REG_IO_FAILURE;
-               goto error;
+               goto done;
        }
 
-       regkey_set_secdesc(key->key, NULL);
-
-       err = WERR_OK;
+       err = delete_reg_subkey(parent->key, name);
 
- error:
+done:
        TALLOC_FREE(mem_ctx);
        return err;
 }
@@ -726,7 +701,7 @@ static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
        REGF_NK_REC *subkey;
        REGISTRY_KEY registry_key;
        REGVAL_CTR *values;
-       REGSUBKEY_CTR *subkeys;
+       struct regsubkey_ctr *subkeys;
        int i;
        char *path = NULL;
        WERROR result = WERR_OK;
@@ -748,10 +723,8 @@ static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
 
        /* now start parsing the values and subkeys */
 
-       subkeys = TALLOC_ZERO_P(regfile->mem_ctx, REGSUBKEY_CTR);
-       if (subkeys == NULL) {
-               return WERR_NOMEM;
-       }
+       result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
+       W_ERROR_NOT_OK_RETURN(result);
 
        values = TALLOC_ZERO_P(subkeys, REGVAL_CTR);
        if (values == NULL) {
@@ -767,7 +740,7 @@ static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
                                    (key->values[i].data_size & ~VK_DATA_IN_OFFSET));
        }
 
-       /* copy subkeys into the REGSUBKEY_CTR */
+       /* copy subkeys into the struct regsubkey_ctr */
 
        key->subkey_index = 0;
        while ((subkey = regfio_fetch_subkey( regfile, key ))) {
@@ -861,7 +834,7 @@ static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath,
 {
        REGF_NK_REC *key;
        REGVAL_CTR *values;
-       REGSUBKEY_CTR *subkeys;
+       struct regsubkey_ctr *subkeys;
        int i, num_subkeys;
        char *key_tmp = NULL;
        char *keyname, *parentpath;
@@ -909,10 +882,8 @@ static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath,
 
        /* lookup the values and subkeys */
 
-       subkeys = TALLOC_ZERO_P(regfile->mem_ctx, REGSUBKEY_CTR);
-       if (subkeys == NULL) {
-               return WERR_NOMEM;
-       }
+       result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
+       W_ERROR_NOT_OK_RETURN(result);
 
        values = TALLOC_ZERO_P(subkeys, REGVAL_CTR);
        if (values == NULL) {
@@ -1091,6 +1062,7 @@ static WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
        WERROR werr = WERR_OK;
        struct registry_key *key;
        char *subkey_name = NULL;
+       uint32 i;
 
        mem_ctx = talloc_new(ctx);
        if (mem_ctx == NULL) {
@@ -1104,25 +1076,21 @@ static WERROR reg_deletekey_recursive_internal(TALLOC_CTX *ctx,
                goto done;
        }
 
-       while (W_ERROR_IS_OK(werr = reg_enumkey(mem_ctx, key, 0,
-                                               &subkey_name, NULL)))
-       {
+       werr = fill_subkey_cache(key);
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
+
+       /*
+        * loop from top to bottom for perfomance:
+        * this way, we need to rehash the regsubkey containers less
+        */
+       for (i = regsubkey_ctr_numkeys(key->subkeys) ; i > 0; i--) {
+               subkey_name = regsubkey_ctr_specific_key(key->subkeys, i-1);
                werr = reg_deletekey_recursive_internal(mem_ctx, key,
-                                                       subkey_name,
-                                                       true);
-               if (!W_ERROR_IS_OK(werr)) {
-                       goto done;
-               }
-       }
-       if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
-               DEBUG(1, ("reg_deletekey_recursive_internal: "
-                         "Error enumerating subkeys: %s\n",
-                         win_errstr(werr)));
-               goto done;
+                                       subkey_name,
+                                       true);
+               W_ERROR_NOT_OK_GOTO_DONE(werr);
        }
 
-       werr = WERR_OK;
-
        if (del_key) {
                /* now delete the actual key */
                werr = reg_deletekey(parent, path);
@@ -1133,18 +1101,57 @@ done:
        return werr;
 }
 
+static WERROR reg_deletekey_recursive_trans(TALLOC_CTX *ctx,
+                                           struct registry_key *parent,
+                                           const char *path,
+                                           bool del_key)
+{
+       WERROR werr;
+
+       werr = regdb_transaction_start();
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0, ("reg_deletekey_recursive_trans: "
+                         "error starting transaction: %s\n",
+                         win_errstr(werr)));
+               return werr;
+       }
+
+       werr = reg_deletekey_recursive_internal(ctx, parent, path, del_key);
+
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, (__location__ " failed to delete key '%s' from key "
+                         "'%s': %s\n", path, parent->key->name,
+                         win_errstr(werr)));
+               werr = regdb_transaction_cancel();
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG(0, ("reg_deletekey_recursive_trans: "
+                                 "error cancelling transaction: %s\n",
+                                 win_errstr(werr)));
+               }
+       } else {
+               werr = regdb_transaction_commit();
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG(0, ("reg_deletekey_recursive_trans: "
+                                 "error committing transaction: %s\n",
+                                 win_errstr(werr)));
+               }
+       }
+
+       return werr;
+}
+
 WERROR reg_deletekey_recursive(TALLOC_CTX *ctx,
                               struct registry_key *parent,
                               const char *path)
 {
-       return reg_deletekey_recursive_internal(ctx, parent, path, true);
+       return reg_deletekey_recursive_trans(ctx, parent, path, true);
 }
 
 WERROR reg_deletesubkeys_recursive(TALLOC_CTX *ctx,
                                   struct registry_key *parent,
                                   const char *path)
 {
-       return reg_deletekey_recursive_internal(ctx, parent, path, false);
+       return reg_deletekey_recursive_trans(ctx, parent, path, false);
 }
 
 #if 0
index 04cc0ebfa723513b53993a3e20836cde5c69ecf5..f76840ee227c79dc591b2125540faea132ab2ed1 100644 (file)
@@ -70,7 +70,7 @@ static int current_version_fetch_values(const char *key, REGVAL_CTR *values)
 }
 
 static int current_version_fetch_subkeys(const char *key,
-                                        REGSUBKEY_CTR *subkey_ctr)
+                                        struct regsubkey_ctr *subkey_ctr)
 {
        return regdb_ops.fetch_subkeys(key, subkey_ctr);
 }
index fe5f19271395c5158da2e71e1be68551cf5dad56..30f1db9c530c2bff08d9e57c825768f222f84650 100644 (file)
@@ -103,7 +103,7 @@ static WERROR init_registry_key_internal(const char *add_path)
        char *remaining = NULL;
        char *keyname;
        char *subkeyname;
-       REGSUBKEY_CTR *subkeys;
+       struct regsubkey_ctr *subkeys;
        const char *p, *p2;
 
        DEBUG(6, ("init_registry_key: Adding [%s]\n", add_path));
@@ -167,9 +167,9 @@ static WERROR init_registry_key_internal(const char *add_path)
                 * since we are about to update the record.
                 * We just want any subkeys already present */
 
-               if (!(subkeys = TALLOC_ZERO_P(frame, REGSUBKEY_CTR))) {
+               werr = regsubkey_ctr_init(frame, &subkeys);
+               if (!W_ERROR_IS_OK(werr)) {
                        DEBUG(0,("talloc() failure!\n"));
-                       werr = WERR_NOMEM;
                        goto fail;
                }
 
@@ -482,6 +482,24 @@ int regdb_close( void )
        return 0;
 }
 
+WERROR regdb_transaction_start(void)
+{
+       return (regdb->transaction_start(regdb) == 0) ?
+               WERR_OK : WERR_REG_IO_FAILURE;
+}
+
+WERROR regdb_transaction_commit(void)
+{
+       return (regdb->transaction_commit(regdb) == 0) ?
+               WERR_OK : WERR_REG_IO_FAILURE;
+}
+
+WERROR regdb_transaction_cancel(void)
+{
+       return (regdb->transaction_cancel(regdb) == 0) ?
+               WERR_OK : WERR_REG_IO_FAILURE;
+}
+
 /***********************************************************************
  return the tdb sequence number of the registry tdb.
  this is an indicator for the content of the registry
@@ -492,13 +510,97 @@ int regdb_get_seqnum(void)
        return regdb->get_seqnum(regdb);
 }
 
+
+static WERROR regdb_delete_key_with_prefix(const char *keyname,
+                                          const char *prefix)
+{
+       char *path;
+       WERROR werr = WERR_NOMEM;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+       if (keyname == NULL) {
+               werr = WERR_INVALID_PARAM;
+               goto done;
+       }
+
+       if (prefix == NULL) {
+               path = discard_const_p(char, keyname);
+       } else {
+               path = talloc_asprintf(mem_ctx, "%s/%s", prefix, keyname);
+               if (path == NULL) {
+                       goto done;
+               }
+       }
+
+       path = normalize_reg_path(mem_ctx, path);
+       if (path == NULL) {
+               goto done;
+       }
+
+       werr = ntstatus_to_werror(dbwrap_delete_bystring(regdb, path));
+
+       /* treat "not" found" as ok */
+       if (W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) {
+               werr = WERR_OK;
+       }
+
+done:
+       talloc_free(mem_ctx);
+       return werr;
+}
+
+
+static WERROR regdb_delete_values(const char *keyname)
+{
+       return regdb_delete_key_with_prefix(keyname, REG_VALUE_PREFIX);
+}
+
+static WERROR regdb_delete_secdesc(const char *keyname)
+{
+       return regdb_delete_key_with_prefix(keyname, REG_SECDESC_PREFIX);
+}
+
+static WERROR regdb_delete_subkeylist(const char *keyname)
+{
+       return regdb_delete_key_with_prefix(keyname, NULL);
+}
+
+static WERROR regdb_delete_key_lists(const char *keyname)
+{
+       WERROR werr;
+
+       werr = regdb_delete_values(keyname);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
+                         REG_VALUE_PREFIX, keyname, win_errstr(werr)));
+               goto done;
+       }
+
+       werr = regdb_delete_secdesc(keyname);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
+                         REG_SECDESC_PREFIX, keyname, win_errstr(werr)));
+               goto done;
+       }
+
+       werr = regdb_delete_subkeylist(keyname);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, (__location__ " Deleting %s failed: %s\n",
+                         keyname, win_errstr(werr)));
+               goto done;
+       }
+
+done:
+       return werr;
+}
+
 /***********************************************************************
  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
  ***********************************************************************/
 
-static bool regdb_store_keys_internal(const char *key, REGSUBKEY_CTR *ctr)
+static bool regdb_store_keys_internal(const char *key, struct regsubkey_ctr *ctr)
 {
        TDB_DATA dbuf;
        uint8 *buffer = NULL;
@@ -550,8 +652,8 @@ static bool regdb_store_keys_internal(const char *key, REGSUBKEY_CTR *ctr)
                                                   (len+thistime)*2);
                        if(buffer == NULL) {
                                DEBUG(0, ("regdb_store_keys: Failed to realloc "
-                                         "memory of size [%d]\n",
-                                         (len+thistime)*2));
+                                         "memory of size [%u]\n",
+                                         (unsigned int)(len+thistime)*2));
                                ret = false;
                                goto done;
                        }
@@ -578,6 +680,16 @@ static bool regdb_store_keys_internal(const char *key, REGSUBKEY_CTR *ctr)
                goto done;
        }
 
+       /*
+        * Delete a sorted subkey cache for regdb_key_exists, will be
+        * recreated automatically
+        */
+       keyname = talloc_asprintf(ctx, "%s/%s", REG_SORTED_SUBKEYS_PREFIX,
+                                 keyname);
+       if (keyname != NULL) {
+               dbwrap_delete_bystring(regdb, keyname);
+       }
+
 done:
        TALLOC_FREE(ctx);
        SAFE_FREE(buffer);
@@ -589,14 +701,14 @@ done:
  do not currently exist
  ***********************************************************************/
 
-bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
+bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr)
 {
-       int num_subkeys, i;
+       int num_subkeys, old_num_subkeys, i;
        char *path = NULL;
-       REGSUBKEY_CTR *subkeys = NULL, *old_subkeys = NULL;
+       struct regsubkey_ctr *subkeys = NULL, *old_subkeys = NULL;
        char *oldkeyname = NULL;
        TALLOC_CTX *ctx = talloc_stackframe();
-       NTSTATUS status;
+       WERROR werr;
 
        if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) {
                goto fail;
@@ -607,23 +719,28 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
         * changed
         */
 
-       if (!(old_subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR))) {
+       werr = regsubkey_ctr_init(ctx, &old_subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
                DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
                return false;
        }
 
        regdb_fetch_keys(key, old_subkeys);
 
-       if ((ctr->num_subkeys && old_subkeys->num_subkeys) &&
-           (ctr->num_subkeys == old_subkeys->num_subkeys)) {
-
-               for (i = 0; i<ctr->num_subkeys; i++) {
-                       if (strcmp(ctr->subkeys[i],
-                                  old_subkeys->subkeys[i]) != 0) {
+       num_subkeys = regsubkey_ctr_numkeys(ctr);
+       old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
+       if ((num_subkeys && old_num_subkeys) &&
+           (num_subkeys == old_num_subkeys)) {
+
+               for (i = 0; i < num_subkeys; i++) {
+                       if (strcmp(regsubkey_ctr_specific_key(ctr, i),
+                                  regsubkey_ctr_specific_key(old_subkeys, i))
+                           != 0)
+                       {
                                break;
                        }
                }
-               if (i == ctr->num_subkeys) {
+               if (i == num_subkeys) {
                        /*
                         * Nothing changed, no point to even start a tdb
                         * transaction
@@ -644,7 +761,8 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
         * Re-fetch the old keys inside the transaction
         */
 
-       if (!(old_subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR))) {
+       werr = regsubkey_ctr_init(ctx, &old_subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
                DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
                goto cancel;
        }
@@ -686,66 +804,14 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
                        continue;
                }
 
-               /* (a) Delete the value list for this key */
-
-               path = talloc_asprintf(ctx, "%s/%s/%s",
-                               REG_VALUE_PREFIX,
-                               key,
-                               oldkeyname );
-               if (!path) {
-                       goto cancel;
-               }
-               path = normalize_reg_path(ctx, path);
-               if (!path) {
-                       goto cancel;
-               }
-               /* Ignore errors here, we might have no values around */
-               dbwrap_delete_bystring(regdb, path);
-               TALLOC_FREE(path);
-
-               /* (b) Delete the secdesc for this key */
-
-               path = talloc_asprintf(ctx, "%s/%s/%s",
-                               REG_SECDESC_PREFIX,
-                               key,
-                               oldkeyname );
-               if (!path) {
-                       goto cancel;
-               }
-               path = normalize_reg_path(ctx, path);
+               path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname);
                if (!path) {
                        goto cancel;
                }
-               status = dbwrap_delete_bystring(regdb, path);
-               /* Don't fail if there are no values around. */
-               if (!NT_STATUS_IS_OK(status) &&
-                   !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND))
-               {
-                       DEBUG(1, ("Deleting %s failed: %s\n", path,
-                                 nt_errstr(status)));
-                       goto cancel;
-               }
-               TALLOC_FREE(path);
 
-               /* (c) Delete the list of subkeys of this key */
+               werr = regdb_delete_key_lists(path);
+               W_ERROR_NOT_OK_GOTO(werr, cancel);
 
-               path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname);
-               if (!path) {
-                       goto cancel;
-               }
-               path = normalize_reg_path(ctx, path);
-               if (!path) {
-                       goto cancel;
-               }
-               status = dbwrap_delete_bystring(regdb, path);
-               /* Don't fail if the subkey record was not found. */
-               if (!NT_STATUS_IS_OK(status) &&
-                   !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND))
-               {
-                       DEBUG(1, ("Deleting %s failed: %s\n", path,
-                                 nt_errstr(status)));
-                       goto cancel;
-               }
                TALLOC_FREE(path);
        }
 
@@ -764,7 +830,8 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
        num_subkeys = regsubkey_ctr_numkeys(ctr);
 
        if (num_subkeys == 0) {
-               if (!(subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR)) ) {
+               werr = regsubkey_ctr_init(ctx, &subkeys);
+               if (!W_ERROR_IS_OK(werr)) {
                        DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
                        goto cancel;
                }
@@ -785,7 +852,8 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr)
                if (!path) {
                        goto cancel;
                }
-               if (!(subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR)) ) {
+               werr = regsubkey_ctr_init(ctx, &subkeys);
+               if (!W_ERROR_IS_OK(werr)) {
                        DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
                        goto cancel;
                }
@@ -822,6 +890,139 @@ fail:
        return false;
 }
 
+static WERROR regdb_create_subkey(const char *key, const char *subkey)
+{
+       WERROR werr;
+       struct regsubkey_ctr *subkeys;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+       if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) {
+               werr = WERR_NOT_FOUND;
+               goto done;
+       }
+
+       werr = regsubkey_ctr_init(mem_ctx, &subkeys);
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
+
+       if (regdb_fetch_keys(key, subkeys) < 0) {
+               werr = WERR_REG_IO_FAILURE;
+               goto done;
+       }
+
+       if (regsubkey_ctr_key_exists(subkeys, subkey)) {
+               werr = WERR_OK;
+               goto done;
+       }
+
+       talloc_free(subkeys);
+
+       werr = regdb_transaction_start();
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
+
+       werr = regsubkey_ctr_init(mem_ctx, &subkeys);
+       W_ERROR_NOT_OK_GOTO(werr, cancel);
+
+       if (regdb_fetch_keys(key, subkeys) < 0) {
+               werr = WERR_REG_IO_FAILURE;
+               goto cancel;
+       }
+
+       werr = regsubkey_ctr_addkey(subkeys, subkey);
+       W_ERROR_NOT_OK_GOTO(werr, cancel);
+
+       if (!regdb_store_keys_internal(key, subkeys)) {
+               DEBUG(0, (__location__ " failed to store new subkey list for "
+                        "parent key %s\n", key));
+               werr = WERR_REG_IO_FAILURE;
+               goto cancel;
+       }
+
+       werr = regdb_transaction_commit();
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0, (__location__ " failed to commit transaction: %s\n",
+                        win_errstr(werr)));
+       }
+
+       goto done;
+
+cancel:
+       werr = regdb_transaction_cancel();
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0, (__location__ " failed to cancel transaction: %s\n",
+                        win_errstr(werr)));
+       }
+
+done:
+       talloc_free(mem_ctx);
+       return werr;
+}
+
+static WERROR regdb_delete_subkey(const char *key, const char *subkey)
+{
+       WERROR werr, werr2;
+       struct regsubkey_ctr *subkeys;
+       char *path;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+       if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) {
+               werr = WERR_NOT_FOUND;
+               goto done;
+       }
+
+       path = talloc_asprintf(mem_ctx, "%s/%s", key, subkey);
+       if (path == NULL) {
+               werr = WERR_NOMEM;
+               goto done;
+       }
+
+       if (!regdb_key_exists(path)) {
+               werr = WERR_OK;
+               goto done;
+       }
+
+       werr = regdb_transaction_start();
+       W_ERROR_NOT_OK_GOTO_DONE(werr);
+
+       werr = regdb_delete_key_lists(path);
+       W_ERROR_NOT_OK_GOTO(werr, cancel);
+
+       werr = regsubkey_ctr_init(mem_ctx, &subkeys);
+       W_ERROR_NOT_OK_GOTO(werr, cancel);
+
+       if (regdb_fetch_keys(key, subkeys) < 0) {
+               werr = WERR_REG_IO_FAILURE;
+               goto cancel;
+       }
+
+       werr = regsubkey_ctr_delkey(subkeys, subkey);
+       W_ERROR_NOT_OK_GOTO(werr, cancel);
+
+       if (!regdb_store_keys_internal(key, subkeys)) {
+               DEBUG(0, (__location__ " failed to store new subkey_list for "
+                        "parent key %s\n", key));
+               werr = WERR_REG_IO_FAILURE;
+               goto cancel;
+       }
+
+       werr = regdb_transaction_commit();
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0, (__location__ " failed to commit transaction: %s\n",
+                        win_errstr(werr)));
+       }
+
+       goto done;
+
+cancel:
+       werr2 = regdb_transaction_cancel();
+       if (!W_ERROR_IS_OK(werr2)) {
+               DEBUG(0, (__location__ " failed to cancel transaction: %s\n",
+                        win_errstr(werr2)));
+       }
+
+done:
+       talloc_free(mem_ctx);
+       return werr;
+}
 
 static TDB_DATA regdb_fetch_key_internal(TALLOC_CTX *mem_ctx, const char *key)
 {
@@ -871,6 +1072,223 @@ done:
        return ret;
 }
 
+/*
+ * regdb_key_exists() is a very frequent operation. It can be quite
+ * time-consuming to fully fetch the parent's subkey list, talloc_strdup all
+ * subkeys and then compare the keyname linearly to all the parent's subkeys.
+ *
+ * The following code tries to make this operation as efficient as possible:
+ * Per registry key we create a list of subkeys that is very efficient to
+ * search for existence of a subkey. Its format is:
+ *
+ * 4 bytes num_subkeys
+ * 4*num_subkey bytes offset into the string array
+ * then follows a sorted list of subkeys in uppercase
+ *
+ * This record is created by create_sorted_subkeys() on demand if it does not
+ * exist. scan_parent_subkeys() uses regdb->parse_record to search the sorted
+ * list, the parsing code and the binary search can be found in
+ * parent_subkey_scanner. The code uses parse_record() to avoid a memcpy of
+ * the potentially large subkey record.
+ *
+ * The sorted subkey record is deleted in regdb_store_keys_internal and
+ * recreated on demand.
+ */
+
+static int cmp_keynames(const void *p1, const void *p2)
+{
+       return StrCaseCmp(*((char **)p1), *((char **)p2));
+}
+
+static bool create_sorted_subkeys(const char *key, const char *sorted_keyname)
+{
+       char **sorted_subkeys;
+       struct regsubkey_ctr *ctr;
+       bool result = false;
+       NTSTATUS status;
+       char *buf;
+       char *p;
+       int i, res;
+       size_t len;
+       int num_subkeys;
+       WERROR werr;
+
+       if (regdb->transaction_start(regdb) != 0) {
+               DEBUG(0, ("create_sorted_subkeys: transaction_start "
+                         "failed\n"));
+               return false;
+       }
+
+       werr = regsubkey_ctr_init(talloc_tos(), &ctr);
+       if (!W_ERROR_IS_OK(werr)) {
+               goto fail;
+       }
+
+       res = regdb_fetch_keys(key, ctr);
+       if (res == -1) {
+               goto fail;
+       }
+
+       num_subkeys = regsubkey_ctr_numkeys(ctr);
+       sorted_subkeys = talloc_array(ctr, char *, num_subkeys);
+       if (sorted_subkeys == NULL) {
+               goto fail;
+       }
+
+       len = 4 + 4*num_subkeys;
+
+       for (i = 0; i < num_subkeys; i++) {
+               sorted_subkeys[i] = talloc_strdup_upper(sorted_subkeys,
+                                       regsubkey_ctr_specific_key(ctr, i));
+               if (sorted_subkeys[i] == NULL) {
+                       goto fail;
+               }
+               len += strlen(sorted_subkeys[i])+1;
+       }
+
+       qsort(sorted_subkeys, num_subkeys, sizeof(char *), cmp_keynames);
+
+       buf = talloc_array(ctr, char, len);
+       if (buf == NULL) {
+               goto fail;
+       }
+       p = buf + 4 + 4*num_subkeys;
+
+       SIVAL(buf, 0, num_subkeys);
+
+       for (i=0; i < num_subkeys; i++) {
+               ptrdiff_t offset = p - buf;
+               SIVAL(buf, 4 + 4*i, offset);
+               strlcpy(p, sorted_subkeys[i], len-offset);
+               p += strlen(sorted_subkeys[i]) + 1;
+       }
+
+       status = dbwrap_store_bystring(
+               regdb, sorted_keyname, make_tdb_data((uint8_t *)buf, len),
+               TDB_REPLACE);
+       if (!NT_STATUS_IS_OK(status)) {
+               /*
+                * Don't use a "goto fail;" here, this would commit the broken
+                * transaction. See below for an explanation.
+                */
+               if (regdb->transaction_cancel(regdb) == -1) {
+                       DEBUG(0, ("create_sorted_subkeys: transaction_cancel "
+                                 "failed\n"));
+               }
+               TALLOC_FREE(ctr);
+               return false;
+       }
+
+       result = true;
+ fail:
+       /*
+        * We only get here via the "goto fail" when we did not write anything
+        * yet. Using transaction_commit even in a failure case is necessary
+        * because this (disposable) call might be nested in other
+        * transactions. Doing a cancel here would destroy the possibility of
+        * a transaction_commit for transactions that we might be wrapped in.
+        */
+       if (regdb->transaction_commit(regdb) == -1) {
+               DEBUG(0, ("create_sorted_subkeys: transaction_start "
+                         "failed\n"));
+               goto fail;
+       }
+
+       TALLOC_FREE(ctr);
+       return result;
+}
+
+struct scan_subkey_state {
+       char *name;
+       bool scanned;
+       bool found;
+};
+
+static int parent_subkey_scanner(TDB_DATA key, TDB_DATA data,
+                                void *private_data)
+{
+       struct scan_subkey_state *state =
+               (struct scan_subkey_state *)private_data;
+       uint32_t num_subkeys;
+       uint32_t l, u;
+
+       if (data.dsize < sizeof(uint32_t)) {
+               return -1;
+       }
+
+       state->scanned = true;
+       state->found = false;
+
+       tdb_unpack(data.dptr, data.dsize, "d", &num_subkeys);
+
+       l = 0;
+       u = num_subkeys;
+
+       while (l < u) {
+               uint32_t idx = (l+u)/2;
+               char *s = (char *)data.dptr + IVAL(data.dptr, 4 + 4*idx);
+               int comparison = strcmp(state->name, s);
+
+               if (comparison < 0) {
+                       u = idx;
+               } else if (comparison > 0) {
+                       l = idx + 1;
+               } else {
+                       state->found = true;
+                       return 0;
+               }
+       }
+       return 0;
+}
+
+static bool scan_parent_subkeys(const char *parent, const char *name)
+{
+       char *path = NULL;
+       char *key = NULL;
+       struct scan_subkey_state state = { 0, };
+       bool result = false;
+       int res;
+
+       state.name = NULL;
+
+       path = normalize_reg_path(talloc_tos(), parent);
+       if (path == NULL) {
+               goto fail;
+       }
+
+       key = talloc_asprintf(talloc_tos(), "%s/%s",
+                             REG_SORTED_SUBKEYS_PREFIX, path);
+       if (key == NULL) {
+               goto fail;
+       }
+
+       state.name = talloc_strdup_upper(talloc_tos(), name);
+       if (state.name == NULL) {
+               goto fail;
+       }
+       state.scanned = false;
+
+       res = regdb->parse_record(regdb, string_term_tdb_data(key),
+                                 parent_subkey_scanner, &state);
+
+       if (state.scanned) {
+               result = state.found;
+       } else {
+               if (!create_sorted_subkeys(path, key)) {
+                       goto fail;
+               }
+               res = regdb->parse_record(regdb, string_term_tdb_data(key),
+                                         parent_subkey_scanner, &state);
+               if ((res == 0) && (state.scanned)) {
+                       result = state.found;
+               }
+       }
+
+ fail:
+       TALLOC_FREE(path);
+       TALLOC_FREE(state.name);
+       return result;
+}
 
 /**
  * Check for the existence of a key.
@@ -907,26 +1325,8 @@ static bool regdb_key_exists(const char *key)
                value = regdb_fetch_key_internal(mem_ctx, path);
                ret = (value.dptr != NULL);
        } else {
-               /* get the list of subkeys of the parent key */
-               uint32 num_items, len, i;
-               fstring subkeyname;
-
                *p = '\0';
-               p++;
-               value = regdb_fetch_key_internal(mem_ctx, path);
-               if (value.dptr == NULL) {
-                       goto done;
-               }
-
-               len = tdb_unpack(value.dptr, value.dsize, "d", &num_items);
-               for (i = 0; i < num_items; i++) {
-                       len += tdb_unpack(value.dptr +len, value.dsize -len,
-                                         "f", &subkeyname);
-                       if (strequal(subkeyname, p)) {
-                               ret = true;
-                               goto done;
-                       }
-               }
+               ret = scan_parent_subkeys(path, p+1);
        }
 
 done:
@@ -940,8 +1340,9 @@ done:
  released by the caller.
  ***********************************************************************/
 
-int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr)
+int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr)
 {
+       WERROR werr;
        uint32 num_items;
        uint8 *buf;
        uint32 buflen, len;
@@ -957,7 +1358,10 @@ int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr)
                goto done;
        }
 
-       ctr->seqnum = regdb_get_seqnum();
+       werr = regsubkey_ctr_set_seqnum(ctr, regdb_get_seqnum());
+       if (!W_ERROR_IS_OK(werr)) {
+               goto done;
+       }
 
        value = regdb_fetch_key_internal(frame, key);
 
@@ -972,35 +1376,12 @@ int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr)
        buflen = value.dsize;
        len = tdb_unpack( buf, buflen, "d", &num_items);
 
-       /*
-        * The following code breaks the abstraction that reg_objects.c sets
-        * up with regsubkey_ctr_addkey(). But if we use that with the current
-        * data structure of ctr->subkeys being an unsorted array, we end up
-        * with an O(n^2) algorithm for retrieving keys from the tdb
-        * file. This is pretty pointless, as we have to trust the data
-        * structure on disk not to have duplicates anyway. The alternative to
-        * breaking this abstraction would be to set up a more sophisticated
-        * data structure in REGSUBKEY_CTR.
-        *
-        * This makes "net conf list" for a registry with >1000 shares
-        * actually usable :-)
-        */
-
-       ctr->subkeys = talloc_array(ctr, char *, num_items);
-       if (ctr->subkeys == NULL) {
-               DEBUG(5, ("regdb_fetch_keys: could not allocate subkeys\n"));
-               goto done;
-       }
-       ctr->num_subkeys = num_items;
-
        for (i=0; i<num_items; i++) {
                len += tdb_unpack(buf+len, buflen-len, "f", subkeyname);
-               ctr->subkeys[i] = talloc_strdup(ctr->subkeys, subkeyname);
-               if (ctr->subkeys[i] == NULL) {
-                       DEBUG(5, ("regdb_fetch_keys: could not allocate "
-                                 "subkeyname\n"));
-                       TALLOC_FREE(ctr->subkeys);
-                       ctr->num_subkeys = 0;
+               werr = regsubkey_ctr_addkey(ctr, subkeyname);
+               if (!W_ERROR_IS_OK(werr)) {
+                       DEBUG(5, ("regdb_fetch_keys: regsubkey_ctr_addkey "
+                                 "failed: %s\n", win_errstr(werr)));
                        goto done;
                }
        }
@@ -1238,7 +1619,6 @@ static WERROR regdb_set_secdesc(const char *key,
 {
        TALLOC_CTX *mem_ctx = talloc_stackframe();
        char *tdbkey;
-       NTSTATUS status;
        WERROR err = WERR_NOMEM;
        TDB_DATA tdbdata;
 
@@ -1255,36 +1635,27 @@ static WERROR regdb_set_secdesc(const char *key,
 
        if (secdesc == NULL) {
                /* assuming a delete */
-               status = dbwrap_trans_delete_bystring(regdb, tdbkey);
-               if (NT_STATUS_IS_OK(status)) {
-                       err = WERR_OK;
-               } else {
-                       err = ntstatus_to_werror(status);
-               }
+               err = ntstatus_to_werror(dbwrap_trans_delete_bystring(regdb,
+                                                                     tdbkey));
                goto done;
        }
 
        err = ntstatus_to_werror(marshall_sec_desc(mem_ctx, secdesc,
                                                   &tdbdata.dptr,
                                                   &tdbdata.dsize));
-       if (!W_ERROR_IS_OK(err)) {
-               goto done;
-       }
+       W_ERROR_NOT_OK_GOTO_DONE(err);
 
-       status = dbwrap_trans_store_bystring(regdb, tdbkey, tdbdata, 0);
-       if (!NT_STATUS_IS_OK(status)) {
-               err = ntstatus_to_werror(status);
-               goto done;
-       }
+       err = ntstatus_to_werror(dbwrap_trans_store_bystring(regdb, tdbkey,
+                                                            tdbdata, 0));
 
  done:
        TALLOC_FREE(mem_ctx);
        return err;
 }
 
-bool regdb_subkeys_need_update(REGSUBKEY_CTR *subkeys)
+bool regdb_subkeys_need_update(struct regsubkey_ctr *subkeys)
 {
-       return (regdb_get_seqnum() != subkeys->seqnum);
+       return (regdb_get_seqnum() != regsubkey_ctr_get_seqnum(subkeys));
 }
 
 bool regdb_values_need_update(REGVAL_CTR *values)
@@ -1301,6 +1672,8 @@ REGISTRY_OPS regdb_ops = {
        .fetch_values = regdb_fetch_values,
        .store_subkeys = regdb_store_keys,
        .store_values = regdb_store_values,
+       .create_subkey = regdb_create_subkey,
+       .delete_subkey = regdb_delete_subkey,
        .get_secdesc = regdb_get_secdesc,
        .set_secdesc = regdb_set_secdesc,
        .subkeys_need_update = regdb_subkeys_need_update,
index 2ed5e78e1ca0b1a2b14cb340fa92ae29b5f87639..c67f7b3ea4486ad5314657fb366e5e7de20cef51 100644 (file)
@@ -59,7 +59,7 @@ static int hkpt_params_fetch_values(const char *key, REGVAL_CTR *regvals)
 }
 
 static int hkpt_params_fetch_subkeys(const char *key,
-                                        REGSUBKEY_CTR *subkey_ctr)
+                                        struct regsubkey_ctr *subkey_ctr)
 {
        return regdb_ops.fetch_subkeys(key, subkey_ctr);
 }
index 71f88144c831ae7c04da833e574f63f1496a0fb4..17abf038a6a307afd5407e589a8f5b84ef1d24a8 100644 (file)
@@ -46,7 +46,7 @@ static int netlogon_params_fetch_values(const char *key, REGVAL_CTR *regvals)
 }
 
 static int netlogon_params_fetch_subkeys(const char *key,
-                                        REGSUBKEY_CTR *subkey_ctr)
+                                        struct regsubkey_ctr *subkey_ctr)
 {
        return regdb_ops.fetch_subkeys(key, subkey_ctr);
 }
index 999bca2682965b5d4807309d8667287d36d06b5d..e23c87efe8b93e7dc1262c32b51fb09dd90f3176 100644 (file)
@@ -95,7 +95,7 @@ static int perflib_fetch_values(const char *key, REGVAL_CTR *regvals)
 }
 
 static int perflib_fetch_subkeys(const char *key,
-                                        REGSUBKEY_CTR *subkey_ctr)
+                                struct regsubkey_ctr *subkey_ctr)
 {
        return regdb_ops.fetch_subkeys(key, subkey_ctr);
 }
index 5c1e6eb54305144b2d6e9a3b3855a824a6708b72..192bc78e09f864d0a9e17c546a9d5a938bd20a42 100644 (file)
@@ -42,8 +42,8 @@ struct reg_dyn_tree {
        const char *path;
 
        /* callbscks for fetch/store operations */
-       int ( *fetch_subkeys) ( const char *path, REGSUBKEY_CTR *subkeys );
-       bool (*store_subkeys) ( const char *path, REGSUBKEY_CTR *subkeys );
+       int ( *fetch_subkeys) ( const char *path, struct regsubkey_ctr *subkeys );
+       bool (*store_subkeys) ( const char *path, struct regsubkey_ctr *subkeys );
        int  (*fetch_values)  ( const char *path, REGVAL_CTR *values );
        bool (*store_values)  ( const char *path, REGVAL_CTR *values );
 };
@@ -77,7 +77,7 @@ static const char *dos_basename(const char *path)
  *********************************************************************
  *********************************************************************/
 
-static int key_forms_fetch_keys(const char *key, REGSUBKEY_CTR *subkeys)
+static int key_forms_fetch_keys(const char *key, struct regsubkey_ctr *subkeys)
 {
        char *p = reg_remaining_path(talloc_tos(), key + strlen(KEY_FORMS));
 
@@ -196,7 +196,7 @@ static char *strip_printers_prefix(const char *key)
 /*********************************************************************
  *********************************************************************/
 
-static int key_printers_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
+static int key_printers_fetch_keys( const char *key, struct regsubkey_ctr *subkeys )
 {
        int n_services = lp_numservices();
        int snum;
@@ -275,7 +275,7 @@ done:
  keyname is the sharename and not the printer name.
  *********************************************************************/
 
-static bool add_printers_by_registry( REGSUBKEY_CTR *subkeys )
+static bool add_printers_by_registry( struct regsubkey_ctr *subkeys )
 {
        int i, num_keys, snum;
        char *printername;
@@ -310,7 +310,7 @@ static bool add_printers_by_registry( REGSUBKEY_CTR *subkeys )
 /**********************************************************************
  *********************************************************************/
 
-static bool key_printers_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
+static bool key_printers_store_keys( const char *key, struct regsubkey_ctr *subkeys )
 {
        char *printers_key;
        char *printername, *printerdatakey;
@@ -738,7 +738,7 @@ static bool key_printers_store_values( const char *key, REGVAL_CTR *values )
  *********************************************************************
  *********************************************************************/
 
-static int key_driver_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
+static int key_driver_fetch_keys( const char *key, struct regsubkey_ctr *subkeys )
 {
        const char *environments[] = {
                "Windows 4.0",
@@ -1085,7 +1085,7 @@ static int key_driver_fetch_values( const char *key, REGVAL_CTR *values )
  *********************************************************************
  *********************************************************************/
 
-static int key_print_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
+static int key_print_fetch_keys( const char *key, struct regsubkey_ctr *subkeys )
 {
        int key_len = strlen(key);
 
@@ -1192,7 +1192,7 @@ static int match_registry_path(const char *key)
 /***********************************************************************
  **********************************************************************/
 
-static int regprint_fetch_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
+static int regprint_fetch_reg_keys( const char *key, struct regsubkey_ctr *subkeys )
 {
        int i = match_registry_path( key );
 
@@ -1208,7 +1208,7 @@ static int regprint_fetch_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
 /**********************************************************************
  *********************************************************************/
 
-static bool regprint_store_reg_keys( const char *key, REGSUBKEY_CTR *subkeys )
+static bool regprint_store_reg_keys( const char *key, struct regsubkey_ctr *subkeys )
 {
        int i = match_registry_path( key );
 
index 7ac5c5b4b9d8f7e24fb36a090a8f1242bbaa182e..3e9d32cd9791b327e19d9fceccdb2015f4a8c8d3 100644 (file)
@@ -59,7 +59,7 @@ static int prod_options_fetch_values(const char *key, REGVAL_CTR *regvals)
 }
 
 static int prod_options_fetch_subkeys(const char *key,
-                                     REGSUBKEY_CTR *subkey_ctr)
+                                     struct regsubkey_ctr *subkey_ctr)
 {
        return regdb_ops.fetch_subkeys(key, subkey_ctr);
 }
index ee9e5dc5a1848e675e34c1bcc85795567f3ad3d7..a30ae34b4e2ab76ea804c62dc8ca58fbeb77ed2e 100644 (file)
@@ -66,7 +66,7 @@ static char* trim_reg_path( const char *path )
  Caller is responsible for freeing memory to **subkeys
  *********************************************************************/
  
-static int shares_subkey_info( const char *key, REGSUBKEY_CTR *subkey_ctr )
+static int shares_subkey_info( const char *key, struct regsubkey_ctr *subkey_ctr )
 {
        char            *path;
        bool            top_level = False;
@@ -134,7 +134,7 @@ static int shares_value_info( const char *key, REGVAL_CTR *val )
  (for now at least)
  *********************************************************************/
 
-static bool shares_store_subkey( const char *key, REGSUBKEY_CTR *subkeys )
+static bool shares_store_subkey( const char *key, struct regsubkey_ctr *subkeys )
 {
        return False;
 }
index 2e4a5f1c1d7ec84e9113177e398fa01d2627321f..8e1bbcab6fcee6171ad97c37eaaafa036a9766d5 100644 (file)
 
 extern REGISTRY_OPS regdb_ops;         /* these are the default */
 
-static int smbconf_fetch_keys( const char *key, REGSUBKEY_CTR *subkey_ctr )
+static int smbconf_fetch_keys( const char *key, struct regsubkey_ctr *subkey_ctr )
 {
        return regdb_ops.fetch_subkeys(key, subkey_ctr);
 }
 
-static bool smbconf_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
+static bool smbconf_store_keys( const char *key, struct regsubkey_ctr *subkeys )
 {
        return regdb_ops.store_subkeys(key, subkeys);
 }
 
+static WERROR smbconf_create_subkey(const char *key, const char *subkey)
+{
+       return regdb_ops.create_subkey(key, subkey);
+}
+
+static WERROR smbconf_delete_subkey(const char *key, const char *subkey)
+{
+       return regdb_ops.delete_subkey(key, subkey);
+}
+
 static int smbconf_fetch_values( const char *key, REGVAL_CTR *val )
 {
        return regdb_ops.fetch_values(key, val);
@@ -79,6 +89,8 @@ REGISTRY_OPS smbconf_reg_ops = {
        .fetch_values = smbconf_fetch_values,
        .store_subkeys = smbconf_store_keys,
        .store_values = smbconf_store_values,
+       .create_subkey = smbconf_create_subkey,
+       .delete_subkey = smbconf_delete_subkey,
        .reg_access_check = smbconf_reg_access_check,
        .get_secdesc = smbconf_get_secdesc,
        .set_secdesc = smbconf_set_secdesc,
index db7df5dd8ffecb1cdf8ad79c5a6a48d7bf89bd16..a6aa2fc2eaf118c50460ad07aa8440373eb1ad3c 100644 (file)
@@ -56,7 +56,7 @@ static int tcpip_params_fetch_values(const char *key, REGVAL_CTR *regvals)
 }
 
 static int tcpip_params_fetch_subkeys(const char *key,
-                                        REGSUBKEY_CTR *subkey_ctr)
+                                     struct regsubkey_ctr *subkey_ctr)
 {
        return regdb_ops.fetch_subkeys(key, subkey_ctr);
 }
index 7d950c3c4e85c7f3bcc04db8cefe161d8d502039..f8c382536fadac9e708c790b0d5903f11de47745 100644 (file)
@@ -39,7 +39,7 @@ static WERROR construct_registry_sd(TALLOC_CTX *ctx, SEC_DESC **psd)
        SEC_ACE ace[3];
        size_t i = 0;
        SEC_DESC *sd;
-       SEC_ACL *acl;
+       SEC_ACL *theacl;
        size_t sd_size;
 
        /* basic access for Everyone */
@@ -59,14 +59,14 @@ static WERROR construct_registry_sd(TALLOC_CTX *ctx, SEC_DESC **psd)
 
        /* create the security descriptor */
 
-       acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace);
-       if (acl == NULL) {
+       theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace);
+       if (theacl == NULL) {
                return WERR_NOMEM;
        }
 
        sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
                           &global_sid_Builtin_Administrators,
-                          &global_sid_System, NULL, acl,
+                          &global_sid_System, NULL, theacl,
                           &sd_size);
        if (sd == NULL) {
                return WERR_NOMEM;
@@ -80,7 +80,7 @@ static WERROR construct_registry_sd(TALLOC_CTX *ctx, SEC_DESC **psd)
  High level wrapper function for storing registry subkeys
  ***********************************************************************/
 
-bool store_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys )
+bool store_reg_keys( REGISTRY_KEY *key, struct regsubkey_ctr *subkeys )
 {
        if (key->ops && key->ops->store_subkeys)
                return key->ops->store_subkeys(key->name, subkeys);
@@ -100,12 +100,30 @@ bool store_reg_values( REGISTRY_KEY *key, REGVAL_CTR *val )
        return false;
 }
 
+WERROR create_reg_subkey(REGISTRY_KEY *key, const char *subkey)
+{
+       if (key->ops && key->ops->create_subkey) {
+               return key->ops->create_subkey(key->name, subkey);
+       }
+
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR delete_reg_subkey(REGISTRY_KEY *key, const char *subkey)
+{
+       if (key->ops && key->ops->delete_subkey) {
+               return key->ops->delete_subkey(key->name, subkey);
+       }
+
+       return WERR_NOT_SUPPORTED;
+}
+
 /***********************************************************************
  High level wrapper function for enumerating registry subkeys
  Initialize the TALLOC_CTX if necessary
  ***********************************************************************/
 
-int fetch_reg_keys( REGISTRY_KEY *key, REGSUBKEY_CTR *subkey_ctr )
+int fetch_reg_keys( REGISTRY_KEY *key, struct regsubkey_ctr *subkey_ctr )
 {
        int result = -1;
 
@@ -143,7 +161,6 @@ bool regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted,
        SEC_DESC *sec_desc;
        NTSTATUS status;
        WERROR err;
-       TALLOC_CTX *mem_ctx;
 
        /* use the default security check if the backend has not defined its
         * own */
@@ -153,30 +170,20 @@ bool regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted,
                                                  granted, token);
        }
 
-       /*
-        * The secdesc routines can't yet cope with a NULL talloc ctx sanely.
-        */
-
-       if (!(mem_ctx = talloc_init("regkey_access_check"))) {
-               return false;
-       }
-
-       err = regkey_get_secdesc(mem_ctx, key, &sec_desc);
+       err = regkey_get_secdesc(talloc_tos(), key, &sec_desc);
 
        if (!W_ERROR_IS_OK(err)) {
-               TALLOC_FREE(mem_ctx);
                return false;
        }
 
        se_map_generic( &requested, &reg_generic_map );
 
        status =se_access_check(sec_desc, token, requested, granted);
+       TALLOC_FREE(sec_desc);
        if (!NT_STATUS_IS_OK(status)) {
-               TALLOC_FREE(mem_ctx);
                return false;
        }
 
-       TALLOC_FREE(mem_ctx);
        return NT_STATUS_IS_OK(status);
 }
 
@@ -216,7 +223,7 @@ WERROR regkey_set_secdesc(REGISTRY_KEY *key,
  * Check whether the in-memory version of the subkyes of a
  * registry key needs update from disk.
  */
-bool reg_subkeys_need_update(REGISTRY_KEY *key, REGSUBKEY_CTR *subkeys)
+bool reg_subkeys_need_update(REGISTRY_KEY *key, struct regsubkey_ctr *subkeys)
 {
        if (key->ops && key->ops->subkeys_need_update)
        {
index 8994acf107ec43d1b7a7f6bee9a7469eebcb3c2c..c02318beacb734306feb73e7b50a0d9d2f8405cd 100644 (file)
@@ -35,16 +35,18 @@ bool eventlog_init_keys(void)
        const char **elogs = lp_eventlog_list();
        char *evtlogpath = NULL;
        char *evtfilepath = NULL;
-       REGSUBKEY_CTR *subkeys;
+       struct regsubkey_ctr *subkeys;
        REGVAL_CTR *values;
        uint32 uiMaxSize;
        uint32 uiRetention;
        uint32 uiCategoryCount;
        UNISTR2 data;
        TALLOC_CTX *ctx = talloc_tos();
+       WERROR werr;
 
        while (elogs && *elogs) {
-               if (!(subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR ) ) ) {
+               werr = regsubkey_ctr_init(ctx, &subkeys);
+               if (!W_ERROR_IS_OK(werr)) {
                        DEBUG( 0, ( "talloc() failure!\n" ) );
                        return False;
                }
@@ -70,7 +72,8 @@ bool eventlog_init_keys(void)
                DEBUG( 5,
                       ( "Adding key of [%s] to path of [%s]\n", *elogs,
                         evtlogpath ) );
-               if (!(subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR))) {
+               werr = regsubkey_ctr_init(ctx, &subkeys);
+               if (!W_ERROR_IS_OK(werr)) {
                        DEBUG( 0, ( "talloc() failure!\n" ) );
                        return False;
                }
@@ -197,7 +200,7 @@ bool eventlog_add_source( const char *eventlog, const char *sourcename,
        const char **elogs = lp_eventlog_list(  );
        char **wrklist, **wp;
        char *evtlogpath = NULL;
-       REGSUBKEY_CTR *subkeys;
+       struct regsubkey_ctr *subkeys;
        REGVAL_CTR *values;
        REGISTRY_VALUE *rval;
        UNISTR2 data;
@@ -207,6 +210,7 @@ bool eventlog_add_source( const char *eventlog, const char *sourcename,
        int i;
        int numsources;
        TALLOC_CTX *ctx = talloc_tos();
+       WERROR werr;
 
        if (!elogs) {
                return False;
@@ -315,7 +319,8 @@ bool eventlog_add_source( const char *eventlog, const char *sourcename,
        TALLOC_FREE(values);
        TALLOC_FREE(wrklist);   /*  */
 
-       if ( !( subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR ) ) ) {
+       werr = regsubkey_ctr_init(ctx, &subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
                DEBUG( 0, ( "talloc() failure!\n" ) );
                return False;
        }
@@ -342,7 +347,8 @@ bool eventlog_add_source( const char *eventlog, const char *sourcename,
 
        /* now allocate room for the source's subkeys */
 
-       if ( !( subkeys = TALLOC_ZERO_P(ctx, REGSUBKEY_CTR ) ) ) {
+       werr = regsubkey_ctr_init(ctx, &subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
                DEBUG( 0, ( "talloc() failure!\n" ) );
                return False;
        }
index 47122ccad2a20739e0c1483403eed89300b7e099..b975ced3249420e2629eb2c070e5bfb23f9f744a 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_REGISTRY
 
+struct regsubkey_ctr {
+       uint32_t        num_subkeys;
+       char            **subkeys;
+       struct db_context *subkeys_hash;
+       int seqnum;
+};
+
 /**********************************************************************
 
- Note that the REGSUB_CTR and REGVAL_CTR objects *must* be talloc()'d
- since the methods use the object pointer as the talloc context for
- internal private data.
+ Note that the struct regsubkey_ctr and REGVAL_CTR objects *must* be
+ talloc()'d since the methods use the object pointer as the talloc
context for internal private data.
 
- There is no longer a regXXX_ctr_intit() and regXXX_ctr_destroy()
+ There is no longer a regval_ctr_intit() and regval_ctr_destroy()
  pair of functions.  Simply TALLOC_ZERO_P() and TALLOC_FREE() the
  object.
 
  **********************************************************************/
 
+WERROR regsubkey_ctr_init(TALLOC_CTX *mem_ctx, struct regsubkey_ctr **ctr)
+{
+       if (ctr == NULL) {
+               return WERR_INVALID_PARAM;
+       }
+
+       *ctr = talloc_zero(mem_ctx, struct regsubkey_ctr);
+       if (*ctr == NULL) {
+               return WERR_NOMEM;
+       }
+
+       (*ctr)->subkeys_hash = db_open_rbt(*ctr);
+       if ((*ctr)->subkeys_hash == NULL) {
+               talloc_free(*ctr);
+               return WERR_NOMEM;
+       }
+
+       return WERR_OK;
+}
+
+WERROR regsubkey_ctr_set_seqnum(struct regsubkey_ctr *ctr, int seqnum)
+{
+       if (ctr == NULL) {
+               return WERR_INVALID_PARAM;
+       }
+
+       ctr->seqnum = seqnum;
+
+       return WERR_OK;
+}
+
+int regsubkey_ctr_get_seqnum(struct regsubkey_ctr *ctr)
+{
+       if (ctr == NULL) {
+               return -1;
+       }
+
+       return ctr->seqnum;
+}
+
+static WERROR regsubkey_ctr_hash_keyname(struct regsubkey_ctr *ctr,
+                                        const char *keyname,
+                                        uint32 idx)
+{
+       WERROR werr;
+
+       werr = ntstatus_to_werror(dbwrap_store_bystring(ctr->subkeys_hash,
+                                               keyname,
+                                               make_tdb_data((uint8 *)&idx,
+                                                             sizeof(idx)),
+                                               TDB_REPLACE));
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, ("error hashing new key '%s' in container: %s\n",
+                         keyname, win_errstr(werr)));
+       }
+
+       return werr;
+}
+
+static WERROR regsubkey_ctr_unhash_keyname(struct regsubkey_ctr *ctr,
+                                          const char *keyname)
+{
+       WERROR werr;
+
+       werr = ntstatus_to_werror(dbwrap_delete_bystring(ctr->subkeys_hash,
+                                 keyname));
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(1, ("error unhashing key '%s' in container: %s\n",
+                         keyname, win_errstr(werr)));
+       }
+
+       return werr;
+}
+
+static WERROR regsubkey_ctr_index_for_keyname(struct regsubkey_ctr *ctr,
+                                             const char *keyname,
+                                             uint32 *idx)
+{
+       TDB_DATA data;
+
+       if ((ctr == NULL) || (keyname == NULL)) {
+               return WERR_INVALID_PARAM;
+       }
+
+       data = dbwrap_fetch_bystring(ctr->subkeys_hash, ctr, keyname);
+       if (data.dptr == NULL) {
+               return WERR_NOT_FOUND;
+       }
+
+       if (data.dsize != sizeof(*idx)) {
+               talloc_free(data.dptr);
+               return WERR_INVALID_DATATYPE;
+       }
+
+       if (idx != NULL) {
+               *idx = *(uint32 *)data.dptr;
+       }
+
+       talloc_free(data.dptr);
+       return WERR_OK;
+}
+
 /***********************************************************************
  Add a new key to the array
  **********************************************************************/
 
-WERROR regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
+WERROR regsubkey_ctr_addkey( struct regsubkey_ctr *ctr, const char *keyname )
 {
        char **newkeys;
+       WERROR werr;
 
        if ( !keyname ) {
                return WERR_OK;
@@ -68,6 +178,10 @@ WERROR regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
                 */
                return WERR_NOMEM;
        }
+
+       werr = regsubkey_ctr_hash_keyname(ctr, keyname, ctr->num_subkeys);
+       W_ERROR_NOT_OK_RETURN(werr);
+
        ctr->num_subkeys++;
 
        return WERR_OK;
@@ -77,57 +191,64 @@ WERROR regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
  Delete a key from the array
  **********************************************************************/
 
-int regsubkey_ctr_delkey( REGSUBKEY_CTR *ctr, const char *keyname )
+WERROR regsubkey_ctr_delkey( struct regsubkey_ctr *ctr, const char *keyname )
 {
-       int i;
+       WERROR werr;
+       uint32 idx, j;
 
-       if ( !keyname )
-               return ctr->num_subkeys;
+       if (keyname == NULL) {
+               return WERR_INVALID_PARAM;
+       }
 
        /* make sure the keyname is actually already there */
 
-       for ( i=0; i<ctr->num_subkeys; i++ ) {
-               if ( strequal( ctr->subkeys[i], keyname ) )
-                       break;
-       }
+       werr = regsubkey_ctr_index_for_keyname(ctr, keyname, &idx);
+       W_ERROR_NOT_OK_RETURN(werr);
 
-       if ( i == ctr->num_subkeys )
-               return ctr->num_subkeys;
+       werr = regsubkey_ctr_unhash_keyname(ctr, keyname);
+       W_ERROR_NOT_OK_RETURN(werr);
 
        /* update if we have any keys left */
        ctr->num_subkeys--;
-       if ( i < ctr->num_subkeys )
-               memmove(&ctr->subkeys[i], &ctr->subkeys[i+1],
-                       sizeof(char*) * (ctr->num_subkeys-i));
+       if (idx < ctr->num_subkeys) {
+               memmove(&ctr->subkeys[idx], &ctr->subkeys[idx+1],
+                       sizeof(char *) * (ctr->num_subkeys - idx));
+
+               /* we have to re-hash rest of the array...  :-( */
+               for (j = idx; j < ctr->num_subkeys; j++) {
+                       werr = regsubkey_ctr_hash_keyname(ctr, ctr->subkeys[j], j);
+                       W_ERROR_NOT_OK_RETURN(werr);
+               }
+       }
 
-       return ctr->num_subkeys;
+       return WERR_OK;
 }
 
 /***********************************************************************
  Check for the existance of a key
  **********************************************************************/
 
-bool regsubkey_ctr_key_exists( REGSUBKEY_CTR *ctr, const char *keyname )
+bool regsubkey_ctr_key_exists( struct regsubkey_ctr *ctr, const char *keyname )
 {
-       int     i;
+       WERROR werr;
 
        if (!ctr->subkeys) {
                return False;
        }
 
-       for ( i=0; i<ctr->num_subkeys; i++ ) {
-               if ( strequal( ctr->subkeys[i],keyname ) )
-                       return True;
+       werr = regsubkey_ctr_index_for_keyname(ctr, keyname, NULL);
+       if (!W_ERROR_IS_OK(werr)) {
+               return false;
        }
 
-       return False;
+       return true;
 }
 
 /***********************************************************************
  How many keys does the container hold ?
  **********************************************************************/
 
-int regsubkey_ctr_numkeys( REGSUBKEY_CTR *ctr )
+int regsubkey_ctr_numkeys( struct regsubkey_ctr *ctr )
 {
        return ctr->num_subkeys;
 }
@@ -136,7 +257,7 @@ int regsubkey_ctr_numkeys( REGSUBKEY_CTR *ctr )
  Retreive a specific key string
  **********************************************************************/
 
-char* regsubkey_ctr_specific_key( REGSUBKEY_CTR *ctr, uint32 key_index )
+char* regsubkey_ctr_specific_key( struct regsubkey_ctr *ctr, uint32_t key_index )
 {
        if ( ! (key_index < ctr->num_subkeys) )
                return NULL;
index 5395f225f18fa2e8e74438c4b08fcf3a043847df..d002bd72e7cbbaada54601b38231c6dec1a368f0 100644 (file)
@@ -1693,7 +1693,7 @@ static int hashrec_cmp( REGF_HASH_REC *h1, REGF_HASH_REC *h2 )
 *******************************************************************/
 
  REGF_NK_REC* regfio_write_key( REGF_FILE *file, const char *name, 
-                               REGVAL_CTR *values, REGSUBKEY_CTR *subkeys, 
+                               REGVAL_CTR *values, struct regsubkey_ctr *subkeys,
                                SEC_DESC *sec_desc, REGF_NK_REC *parent )
 {
        REGF_NK_REC *nk;
index 489b9ca2ffe77f99372b852f1f4d87b6a8508737..d76d20c96223bf3f004a26210eb463be630447a7 100644 (file)
@@ -44,7 +44,8 @@ WERROR rpccli_spoolss_openprinter_ex(struct rpc_pipe_client *cli,
        ZERO_STRUCT(devmode_ctr);
 
        level1.size     = 28;
-       level1.client   = cli->srv_name_slash;
+       level1.client   = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
+       W_ERROR_HAVE_NO_MEMORY(level1.client);
        level1.user     = cli->auth->user_name;
        level1.build    = 1381;
        level1.major    = 2;
@@ -74,6 +75,211 @@ WERROR rpccli_spoolss_openprinter_ex(struct rpc_pipe_client *cli,
        return WERR_OK;
 }
 
+/**********************************************************************
+ convencience wrapper around rpccli_spoolss_GetPrinterDriver2
+**********************************************************************/
+
+WERROR rpccli_spoolss_getprinterdriver2(struct rpc_pipe_client *cli,
+                                       TALLOC_CTX *mem_ctx,
+                                       struct policy_handle *handle,
+                                       const char *architecture,
+                                       uint32_t level,
+                                       uint32_t offered,
+                                       uint32_t client_major_version,
+                                       uint32_t client_minor_version,
+                                       union spoolss_DriverInfo *info,
+                                       uint32_t *server_major_version,
+                                       uint32_t *server_minor_version)
+{
+       NTSTATUS status;
+       WERROR werror;
+       uint32_t needed;
+       DATA_BLOB buffer;
+
+       if (offered > 0) {
+               buffer = data_blob_talloc_zero(mem_ctx, offered);
+               W_ERROR_HAVE_NO_MEMORY(buffer.data);
+       }
+
+       status = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx,
+                                                 handle,
+                                                 architecture,
+                                                 level,
+                                                 (offered > 0) ? &buffer : NULL,
+                                                 offered,
+                                                 client_major_version,
+                                                 client_minor_version,
+                                                 info,
+                                                 &needed,
+                                                 server_major_version,
+                                                 server_minor_version,
+                                                 &werror);
+       if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
+               offered = needed;
+               buffer = data_blob_talloc_zero(mem_ctx, needed);
+               W_ERROR_HAVE_NO_MEMORY(buffer.data);
+
+               status = rpccli_spoolss_GetPrinterDriver2(cli, mem_ctx,
+                                                         handle,
+                                                         architecture,
+                                                         level,
+                                                         &buffer,
+                                                         offered,
+                                                         client_major_version,
+                                                         client_minor_version,
+                                                         info,
+                                                         &needed,
+                                                         server_major_version,
+                                                         server_minor_version,
+                                                         &werror);
+       }
+
+       return werror;
+}
+
+/**********************************************************************
+ convencience wrapper around rpccli_spoolss_AddPrinterEx
+**********************************************************************/
+
+WERROR rpccli_spoolss_addprinterex(struct rpc_pipe_client *cli,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct spoolss_SetPrinterInfoCtr *info_ctr)
+{
+       WERROR result;
+       NTSTATUS status;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct sec_desc_buf secdesc_ctr;
+       struct spoolss_UserLevelCtr userlevel_ctr;
+       struct spoolss_UserLevel1 level1;
+       struct policy_handle handle;
+
+       ZERO_STRUCT(devmode_ctr);
+       ZERO_STRUCT(secdesc_ctr);
+
+       level1.size             = 28;
+       level1.build            = 1381;
+       level1.major            = 2;
+       level1.minor            = 0;
+       level1.processor        = 0;
+       level1.client           = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
+       W_ERROR_HAVE_NO_MEMORY(level1.client);
+       level1.user             = cli->auth->user_name;
+
+       userlevel_ctr.level = 1;
+       userlevel_ctr.user_info.level1 = &level1;
+
+       status = rpccli_spoolss_AddPrinterEx(cli, mem_ctx,
+                                            cli->srv_name_slash,
+                                            info_ctr,
+                                            &devmode_ctr,
+                                            &secdesc_ctr,
+                                            &userlevel_ctr,
+                                            &handle,
+                                            &result);
+       return result;
+}
+
+/**********************************************************************
+ convencience wrapper around rpccli_spoolss_GetPrinter
+**********************************************************************/
+
+WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli,
+                                TALLOC_CTX *mem_ctx,
+                                struct policy_handle *handle,
+                                uint32_t level,
+                                uint32_t offered,
+                                union spoolss_PrinterInfo *info)
+{
+       NTSTATUS status;
+       WERROR werror;
+       DATA_BLOB buffer;
+       uint32_t needed;
+
+       if (offered > 0) {
+               buffer = data_blob_talloc_zero(mem_ctx, offered);
+               W_ERROR_HAVE_NO_MEMORY(buffer.data);
+       }
+
+       status = rpccli_spoolss_GetPrinter(cli, mem_ctx,
+                                          handle,
+                                          level,
+                                          (offered > 0) ? &buffer : NULL,
+                                          offered,
+                                          info,
+                                          &needed,
+                                          &werror);
+
+       if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
+
+               offered = needed;
+               buffer = data_blob_talloc_zero(mem_ctx, offered);
+               W_ERROR_HAVE_NO_MEMORY(buffer.data);
+
+               status = rpccli_spoolss_GetPrinter(cli, mem_ctx,
+                                                  handle,
+                                                  level,
+                                                  &buffer,
+                                                  offered,
+                                                  info,
+                                                  &needed,
+                                                  &werror);
+       }
+
+       return werror;
+}
+
+/**********************************************************************
+ convencience wrapper around rpccli_spoolss_GetJob
+**********************************************************************/
+
+WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli,
+                            TALLOC_CTX *mem_ctx,
+                            struct policy_handle *handle,
+                            uint32_t job_id,
+                            uint32_t level,
+                            uint32_t offered,
+                            union spoolss_JobInfo *info)
+{
+       NTSTATUS status;
+       WERROR werror;
+       uint32_t needed;
+       DATA_BLOB buffer;
+
+       if (offered > 0) {
+               buffer = data_blob_talloc_zero(mem_ctx, offered);
+               W_ERROR_HAVE_NO_MEMORY(buffer.data);
+       }
+
+       status = rpccli_spoolss_GetJob(cli, mem_ctx,
+                                      handle,
+                                      job_id,
+                                      level,
+                                      (offered > 0) ? &buffer : NULL,
+                                      offered,
+                                      info,
+                                      &needed,
+                                      &werror);
+
+       if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
+               offered = needed;
+               buffer = data_blob_talloc_zero(mem_ctx, needed);
+               W_ERROR_HAVE_NO_MEMORY(buffer.data);
+
+               status = rpccli_spoolss_GetJob(cli, mem_ctx,
+                                              handle,
+                                              job_id,
+                                              level,
+                                              &buffer,
+                                              offered,
+                                              info,
+                                              &needed,
+                                              &werror);
+       }
+
+       return werror;
+}
+
+
 /*********************************************************************
  Decode various spoolss rpc's and info levels
  ********************************************************************/
@@ -205,38 +411,6 @@ static bool decode_printer_info_3(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
        return True;
 }
 
-/**********************************************************************
-**********************************************************************/
-
-static bool decode_printer_info_7(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
-                               uint32 returned, PRINTER_INFO_7 **info)
-{
-       uint32 i;
-       PRINTER_INFO_7  *inf;
-
-       if (returned) {
-               inf=TALLOC_ARRAY(mem_ctx, PRINTER_INFO_7, returned);
-               if (!inf) {
-                       return False;
-               }
-               memset(inf, 0, returned*sizeof(PRINTER_INFO_7));
-       } else {
-               inf = NULL;
-       }
-
-       prs_set_offset(&buffer->prs,0);
-
-       for (i=0; i<returned; i++) {
-               if (!smb_io_printer_info_7("", buffer, &inf[i], 0)) {
-                       return False;
-               }
-       }
-
-       *info=inf;
-       return True;
-}
-
-
 /**********************************************************************
 **********************************************************************/
 
@@ -628,195 +802,6 @@ WERROR rpccli_spoolss_enum_ports(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ct
 /**********************************************************************
 **********************************************************************/
 
-WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                             POLICY_HND *pol, uint32 level, 
-                             PRINTER_INFO_CTR *ctr)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_GETPRINTER in;
-       SPOOL_R_GETPRINTER out;
-       RPC_BUFFER buffer;
-       uint32 offered;
-
-       ZERO_STRUCT(in);
-       ZERO_STRUCT(out);
-
-       /* Initialise input parameters */
-
-       offered = 0;
-       if (!rpcbuf_init(&buffer, offered, mem_ctx))
-               return WERR_NOMEM;
-       make_spoolss_q_getprinter( mem_ctx, &in, pol, level, &buffer, offered );
-       
-       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTER,
-                   in, out, 
-                   qbuf, rbuf,
-                   spoolss_io_q_getprinter,
-                   spoolss_io_r_getprinter, 
-                   WERR_GENERAL_FAILURE );
-
-       if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
-               offered = out.needed;
-               
-               ZERO_STRUCT(in);
-               ZERO_STRUCT(out);
-               
-               if (!rpcbuf_init(&buffer, offered, mem_ctx))
-                       return WERR_NOMEM;
-               make_spoolss_q_getprinter( mem_ctx, &in, pol, level, &buffer, offered );
-
-               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTER,
-                           in, out, 
-                           qbuf, rbuf,
-                           spoolss_io_q_getprinter,
-                           spoolss_io_r_getprinter, 
-                           WERR_GENERAL_FAILURE );
-       }
-       
-       if ( !W_ERROR_IS_OK(out.status) )
-               return out.status;
-               
-       switch (level) {
-       case 0:
-               if (!decode_printer_info_0(mem_ctx, out.buffer, 1, &ctr->printers_0)) {
-                       return WERR_GENERAL_FAILURE;
-               }
-               break;
-       case 1:
-               if (!decode_printer_info_1(mem_ctx, out.buffer, 1, &ctr->printers_1)) {
-                       return WERR_GENERAL_FAILURE;
-               }
-               break;
-       case 2:
-               if (!decode_printer_info_2(mem_ctx, out.buffer, 1, &ctr->printers_2)) {
-                       return WERR_GENERAL_FAILURE;
-               }
-               break;
-       case 3:
-               if (!decode_printer_info_3(mem_ctx, out.buffer, 1, &ctr->printers_3)) {
-                       return WERR_GENERAL_FAILURE;
-               }
-               break;
-       case 7:
-               if (!decode_printer_info_7(mem_ctx, out.buffer, 1, &ctr->printers_7)) {
-                       return WERR_GENERAL_FAILURE;
-               }
-               break;
-       default:
-               return WERR_UNKNOWN_LEVEL;
-       }
-
-       return out.status;
-}
-
-/**********************************************************************
-**********************************************************************/
-
-WERROR rpccli_spoolss_setprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                             POLICY_HND *pol, uint32 level, 
-                             PRINTER_INFO_CTR *ctr, uint32 command)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_SETPRINTER in;
-       SPOOL_R_SETPRINTER out;
-
-       ZERO_STRUCT(in);
-       ZERO_STRUCT(out);
-
-       make_spoolss_q_setprinter( mem_ctx, &in, pol, level, ctr, command );
-
-       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_SETPRINTER,
-                   in, out, 
-                   qbuf, rbuf,
-                   spoolss_io_q_setprinter,
-                   spoolss_io_r_setprinter, 
-                   WERR_GENERAL_FAILURE );
-
-       return out.status;
-}
-
-/**********************************************************************
-**********************************************************************/
-
-WERROR rpccli_spoolss_getprinterdriver(struct rpc_pipe_client *cli, 
-                                   TALLOC_CTX *mem_ctx, 
-                                   POLICY_HND *pol, uint32 level, 
-                                   const char *env, int version, PRINTER_DRIVER_CTR *ctr)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_GETPRINTERDRIVER2 in;
-        SPOOL_R_GETPRINTERDRIVER2 out;
-       RPC_BUFFER buffer;
-       fstring server;
-       uint32 offered;
-
-       ZERO_STRUCT(in);
-       ZERO_STRUCT(out);
-
-       fstrcpy(server, cli->desthost);
-       strupper_m(server);
-
-       offered = 0;
-       if (!rpcbuf_init(&buffer, offered, mem_ctx))
-               return WERR_NOMEM;
-       make_spoolss_q_getprinterdriver2( &in, pol, env, level, 
-               version, 2, &buffer, offered);
-
-       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDRIVER2,
-                   in, out, 
-                   qbuf, rbuf,
-                   spoolss_io_q_getprinterdriver2,
-                   spoolss_io_r_getprinterdriver2, 
-                   WERR_GENERAL_FAILURE );
-                   
-       if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
-               offered = out.needed;
-               
-               ZERO_STRUCT(in);
-               ZERO_STRUCT(out);
-               
-               if (!rpcbuf_init(&buffer, offered, mem_ctx))
-                       return WERR_NOMEM;
-               make_spoolss_q_getprinterdriver2( &in, pol, env, level, 
-                       version, 2, &buffer, offered);
-
-               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETPRINTERDRIVER2,
-                           in, out, 
-                           qbuf, rbuf,
-                           spoolss_io_q_getprinterdriver2,
-                           spoolss_io_r_getprinterdriver2, 
-                           WERR_GENERAL_FAILURE );
-       }
-               
-       if ( !W_ERROR_IS_OK(out.status) )
-               return out.status;
-
-       switch (level) {
-       case 1:
-               if (!decode_printer_driver_1(mem_ctx, out.buffer, 1, &ctr->info1)) {
-                       return WERR_GENERAL_FAILURE;
-               }
-               break;
-       case 2:
-               if (!decode_printer_driver_2(mem_ctx, out.buffer, 1, &ctr->info2)) {
-                       return WERR_GENERAL_FAILURE;
-               }
-               break;
-       case 3:
-               if (!decode_printer_driver_3(mem_ctx, out.buffer, 1, &ctr->info3)) {
-                       return WERR_GENERAL_FAILURE;
-               }
-               break;
-       default:
-               return WERR_UNKNOWN_LEVEL;
-       }
-
-       return out.status;      
-}
-
-/**********************************************************************
-**********************************************************************/
-
 WERROR rpccli_spoolss_enumprinterdrivers (struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx,
                                       uint32 level, const char *env,
@@ -902,71 +887,6 @@ WERROR rpccli_spoolss_enumprinterdrivers (struct rpc_pipe_client *cli,
 /**********************************************************************
 **********************************************************************/
 
-WERROR rpccli_spoolss_addprinterdriver (struct rpc_pipe_client *cli, 
-                                    TALLOC_CTX *mem_ctx, uint32 level,
-                                    PRINTER_DRIVER_CTR *ctr)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_ADDPRINTERDRIVER in;
-        SPOOL_R_ADDPRINTERDRIVER out;
-       fstring server;
-
-       ZERO_STRUCT(in);
-       ZERO_STRUCT(out);
-       
-        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-        strupper_m(server);
-
-       make_spoolss_q_addprinterdriver( mem_ctx, &in, server, level, ctr );
-
-       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ADDPRINTERDRIVER,
-                   in, out, 
-                   qbuf, rbuf,
-                   spoolss_io_q_addprinterdriver,
-                   spoolss_io_r_addprinterdriver, 
-                   WERR_GENERAL_FAILURE );
-
-       return out.status;                  
-}
-
-/**********************************************************************
-**********************************************************************/
-
-WERROR rpccli_spoolss_addprinterex (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                                uint32 level, PRINTER_INFO_CTR*ctr)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_ADDPRINTEREX in;
-        SPOOL_R_ADDPRINTEREX out;
-       fstring server, client, user;
-
-       ZERO_STRUCT(in);
-       ZERO_STRUCT(out);
-       
-        slprintf(client, sizeof(fstring)-1, "\\\\%s", global_myname());
-        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-       
-        strupper_m(client);
-        strupper_m(server);
-
-       fstrcpy  (user, cli->auth->user_name);
-
-       make_spoolss_q_addprinterex( mem_ctx, &in, server, client, 
-               user, level, ctr);
-
-       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_ADDPRINTEREX,
-                   in, out, 
-                   qbuf, rbuf,
-                   spoolss_io_q_addprinterex,
-                   spoolss_io_r_addprinterex, 
-                   WERR_GENERAL_FAILURE );
-
-       return out.status;      
-}
-
-/**********************************************************************
-**********************************************************************/
-
 WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             POLICY_HND *handle, int level, uint32 *num_forms,
                             FORM_1 **forms)
@@ -1097,73 +1017,6 @@ WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                         POLICY_HND *hnd, uint32 jobid, uint32 level,
-                         JOB_INFO_CTR *ctr)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_GETJOB in;
-       SPOOL_R_GETJOB out;
-       RPC_BUFFER buffer;
-       uint32 offered;
-
-       ZERO_STRUCT(in);
-       ZERO_STRUCT(out);
-
-       offered = 0;
-       if (!rpcbuf_init(&buffer, offered, mem_ctx))
-               return WERR_NOMEM;
-       make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
-
-       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETJOB,
-                   in, out, 
-                   qbuf, rbuf,
-                   spoolss_io_q_getjob,
-                   spoolss_io_r_getjob, 
-                   WERR_GENERAL_FAILURE );
-
-       if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
-               offered = out.needed;
-               
-               ZERO_STRUCT(in);
-               ZERO_STRUCT(out);
-               
-               if (!rpcbuf_init(&buffer, offered, mem_ctx))
-                       return WERR_NOMEM;
-               make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
-
-               CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_GETJOB,
-                           in, out, 
-                           qbuf, rbuf,
-                           spoolss_io_q_getjob,
-                           spoolss_io_r_getjob, 
-                           WERR_GENERAL_FAILURE );
-       }
-
-       if (!W_ERROR_IS_OK(out.status))
-               return out.status;
-
-       switch(level) {
-       case 1:
-               if (!decode_jobs_1(mem_ctx, out.buffer, 1, &ctr->job.job_info_1)) {
-                       return WERR_GENERAL_FAILURE;
-               }
-               break;
-       case 2:
-               if (!decode_jobs_2(mem_ctx, out.buffer, 1, &ctr->job.job_info_2)) {
-                       return WERR_GENERAL_FAILURE;
-               }
-               break;
-       default:
-               return WERR_UNKNOWN_LEVEL;
-       }
-
-       return out.status;
-}
-
-/**********************************************************************
-**********************************************************************/
-
 WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *hnd, const char *valuename, 
                                  REGISTRY_VALUE *value)
@@ -1405,5 +1258,4 @@ WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *me
 
        return out.status;
 }
-
 /** @} **/
diff --git a/source3/rpc_client/cli_spoolss_notify.c b/source3/rpc_client/cli_spoolss_notify.c
deleted file mode 100644 (file)
index 8ae7835..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/* 
-   Unix SMB/CIFS implementation.
-   RPC pipe client
-
-   Copyright (C) Gerald Carter                2001-2002,
-   Copyright (C) Tim Potter                   2000-2002,
-   Copyright (C) Andrew Tridgell              1994-2000,
-   Copyright (C) Jean-Francois Micouleau      1999-2000.
-   Copyright (C) Jeremy Allison                    2005.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-
-/*
- * SPOOLSS Client RPC's used by servers as the notification
- * back channel.
- */
-
-/*********************************************************************
- This SPOOLSS_REPLY_RRPCN function is used to send a change 
- notification event when the registration **did** use 
- SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor
- Also see cli_spoolss_routereplyprinter()
- *********************************************************************/
-
-WERROR rpccli_spoolss_rrpcn(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
-                        POLICY_HND *pol, uint32 notify_data_len,
-                        SPOOL_NOTIFY_INFO_DATA *notify_data,
-                        uint32 change_low, uint32 change_high)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_REPLY_RRPCN q;
-       SPOOL_R_REPLY_RRPCN r;
-       WERROR result = W_ERROR(ERRgeneral);
-       SPOOL_NOTIFY_INFO       notify_info;
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       ZERO_STRUCT(notify_info);
-
-       /* Initialise input parameters */
-
-       notify_info.version = 0x2;
-       notify_info.flags   = 0x00020000;       /* ?? */
-       notify_info.count   = notify_data_len;
-       notify_info.data    = notify_data;
-
-       /* create and send a MSRPC command with api  */
-       /* store the parameters */
-
-       make_spoolss_q_reply_rrpcn(&q, pol, change_low, change_high, 
-                                  &notify_info);
-
-       /* Marshall data and send request */
-
-       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_RRPCN,
-               q, r,
-               qbuf, rbuf,
-               spoolss_io_q_reply_rrpcn,
-               spoolss_io_r_reply_rrpcn,
-               WERR_GENERAL_FAILURE );
-
-       if (r.unknown0 == 0x00080000)
-               DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n"));
-       else if ( r.unknown0 != 0x0 )
-               DEBUG(8,("cli_spoolss_reply_rrpcn: unknown0 is non-zero [0x%x]\n", r.unknown0));
-       
-       result = r.status;
-       return result;
-}
-
-/*********************************************************************
- *********************************************************************/
-WERROR rpccli_spoolss_rffpcnex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                           POLICY_HND *pol, uint32 flags, uint32 options,
-                           const char *localmachine, uint32 printerlocal,
-                           SPOOL_NOTIFY_OPTION *option)
-{
-       prs_struct qbuf, rbuf;
-       SPOOL_Q_RFFPCNEX q;
-       SPOOL_R_RFFPCNEX r;
-       WERROR result = W_ERROR(ERRgeneral);
-
-       ZERO_STRUCT(q);
-       ZERO_STRUCT(r);
-
-       /* Initialise input parameters */
-
-       make_spoolss_q_rffpcnex(
-               &q, pol, flags, options, localmachine, printerlocal,
-               option);
-
-       /* Marshall data and send request */
-
-       CLI_DO_RPC_WERR( cli, mem_ctx, &syntax_spoolss, SPOOLSS_RFFPCNEX,
-               q, r,
-               qbuf, rbuf,
-               spoolss_io_q_rffpcnex,
-               spoolss_io_r_rffpcnex,
-               WERR_GENERAL_FAILURE );
-
-       result = r.status;
-       return result;
-}
index c0fa41b0de0427860495a0af600f5c4af6e3cd83..658ffe30d6d5e54a9951ac8cbf232373b1c968ac 100644 (file)
@@ -35,6 +35,12 @@ static int rpc_transport_sock_state_destructor(struct rpc_transport_sock_state *
        return 0;
 }
 
+struct rpc_sock_read_state {
+       ssize_t received;
+};
+
+static void rpc_sock_read_done(struct tevent_req *subreq);
+
 static struct async_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx,
                                            struct event_context *ev,
                                            uint8_t *data, size_t size,
@@ -42,25 +48,62 @@ static struct async_req *rpc_sock_read_send(TALLOC_CTX *mem_ctx,
 {
        struct rpc_transport_sock_state *sock_transp = talloc_get_type_abort(
                priv, struct rpc_transport_sock_state);
-       return async_recv(mem_ctx, ev, sock_transp->fd, data, size, 0);
+       struct async_req *result;
+       struct tevent_req *subreq;
+       struct rpc_sock_read_state *state;
+
+       if (!async_req_setup(mem_ctx, &result, &state,
+                            struct rpc_sock_read_state)) {
+               return NULL;
+       }
+
+       subreq = async_recv_send(state, ev, sock_transp->fd, data, size, 0);
+       if (subreq == NULL) {
+               goto fail;
+       }
+       subreq->async.fn = rpc_sock_read_done;
+       subreq->async.private_data = result;
+       return result;
+ fail:
+       TALLOC_FREE(result);
+       return NULL;
 }
 
-static NTSTATUS rpc_sock_read_recv(struct async_req *req, ssize_t *preceived)
+static void rpc_sock_read_done(struct tevent_req *subreq)
 {
-       ssize_t received;
-       int sys_errno;
+       struct async_req *req = talloc_get_type_abort(
+               subreq->async.private_data, struct async_req);
+       struct rpc_sock_read_state *state = talloc_get_type_abort(
+               req->private_data, struct rpc_sock_read_state);
+       int err;
 
-       received = async_syscall_result_ssize_t(req, &sys_errno);
-       if (received == -1) {
-               return map_nt_error_from_unix(sys_errno);
+       state->received = async_recv_recv(subreq, &err);
+       if (state->received == -1) {
+               async_req_nterror(req, map_nt_error_from_unix(err));
+               return;
        }
-       if (received == 0) {
-               return NT_STATUS_END_OF_FILE;
+       async_req_done(req);
+}
+
+static NTSTATUS rpc_sock_read_recv(struct async_req *req, ssize_t *preceived)
+{
+       struct rpc_sock_read_state *state = talloc_get_type_abort(
+               req->private_data, struct rpc_sock_read_state);
+       NTSTATUS status;
+
+       if (async_req_is_nterror(req, &status)) {
+               return status;
        }
-       *preceived = received;
+       *preceived = state->received;
        return NT_STATUS_OK;
 }
 
+struct rpc_sock_write_state {
+       ssize_t sent;
+};
+
+static void rpc_sock_write_done(struct tevent_req *subreq);
+
 static struct async_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx,
                                             struct event_context *ev,
                                             const uint8_t *data, size_t size,
@@ -68,19 +111,52 @@ static struct async_req *rpc_sock_write_send(TALLOC_CTX *mem_ctx,
 {
        struct rpc_transport_sock_state *sock_transp = talloc_get_type_abort(
                priv, struct rpc_transport_sock_state);
-       return async_send(mem_ctx, ev, sock_transp->fd, data, size, 0);
+       struct async_req *result;
+       struct tevent_req *subreq;
+       struct rpc_sock_write_state *state;
+
+       if (!async_req_setup(mem_ctx, &result, &state,
+                            struct rpc_sock_write_state)) {
+               return NULL;
+       }
+       subreq = async_send_send(state, ev, sock_transp->fd, data, size, 0);
+       if (subreq == NULL) {
+               goto fail;
+       }
+       subreq->async.fn = rpc_sock_write_done;
+       subreq->async.private_data = result;
+       return result;
+ fail:
+       TALLOC_FREE(result);
+       return NULL;
+}
+
+static void rpc_sock_write_done(struct tevent_req *subreq)
+{
+       struct async_req *req = talloc_get_type_abort(
+               subreq->async.private_data, struct async_req);
+       struct rpc_sock_write_state *state = talloc_get_type_abort(
+               req->private_data, struct rpc_sock_write_state);
+       int err;
+
+       state->sent = async_send_recv(subreq, &err);
+       if (state->sent == -1) {
+               async_req_nterror(req, map_nt_error_from_unix(err));
+               return;
+       }
+       async_req_done(req);
 }
 
 static NTSTATUS rpc_sock_write_recv(struct async_req *req, ssize_t *psent)
 {
-       ssize_t sent;
-       int sys_errno;
+       struct rpc_sock_write_state *state = talloc_get_type_abort(
+               req->private_data, struct rpc_sock_write_state);
+       NTSTATUS status;
 
-       sent = async_syscall_result_ssize_t(req, &sys_errno);
-       if (sent == -1) {
-               return map_nt_error_from_unix(sys_errno);
+       if (async_req_is_nterror(req, &status)) {
+               return status;
        }
-       *psent = sent;
+       *psent = state->sent;
        return NT_STATUS_OK;
 }
 
index 23c96103811eb19cd77bbd01e5856d9da53cacba..91d8591a05d3dba41e98ab28b7b78e3c71a118c2 100644 (file)
@@ -73,11 +73,11 @@ static bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps,
                if (!prs_uint32("obj_flags", ps, depth, &psa->object.object.flags))
                        return False;
 
-               if (psa->object.object.flags & SEC_ACE_OBJECT_PRESENT)
+               if (psa->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT)
                        if (!smb_io_uuid("obj_guid", &psa->object.object.type.type, ps,depth))
                                return False;
 
-               if (psa->object.object.flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
+               if (psa->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)
                        if (!smb_io_uuid("inh_guid", &psa->object.object.inherited_type.inherited_type, ps,depth))
                                return False;
 
index 577ba73a42c516fbee922c76880acf874dfc974d..78c041f863ac80bb118706b8f320e494d0c9e934 100644 (file)
@@ -71,2461 +71,1281 @@ bool make_systemtime(SYSTEMTIME *systime, struct tm *unixtime)
 }
 
 /*******************************************************************
-reads or writes an NOTIFY OPTION TYPE structure.
-********************************************************************/  
+ * read or write a DEVICEMODE struct.
+ * on reading allocate memory for the private member
+ ********************************************************************/
 
-/* NOTIFY_OPTION_TYPE and NOTIFY_OPTION_TYPE_DATA are really one
-   structure.  The _TYPE structure is really the deferred referrants (i.e
-   the notify fields array) of the _TYPE structure. -tpot */
+#define DM_NUM_OPTIONAL_FIELDS                 8
 
-static bool smb_io_notify_option_type(const char *desc, SPOOL_NOTIFY_OPTION_TYPE *type, prs_struct *ps, int depth)
+bool spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE *devmode)
 {
-       prs_debug(ps, depth, desc, "smb_io_notify_option_type");
+       int available_space;            /* size of the device mode left to parse */
+                                       /* only important on unmarshalling       */
+       int i = 0;
+       uint16 *unistr_buffer;
+       int j;
+                                       
+       struct optional_fields {
+               fstring         name;
+               uint32*         field;
+       } opt_fields[DM_NUM_OPTIONAL_FIELDS] = {
+               { "icmmethod",          NULL },
+               { "icmintent",          NULL },
+               { "mediatype",          NULL },
+               { "dithertype",         NULL },
+               { "reserved1",          NULL },
+               { "reserved2",          NULL },
+               { "panningwidth",       NULL },
+               { "panningheight",      NULL }
+       };
+
+       /* assign at run time to keep non-gcc compilers happy */
+
+       opt_fields[0].field = &devmode->icmmethod;
+       opt_fields[1].field = &devmode->icmintent;
+       opt_fields[2].field = &devmode->mediatype;
+       opt_fields[3].field = &devmode->dithertype;
+       opt_fields[4].field = &devmode->reserved1;
+       opt_fields[5].field = &devmode->reserved2;
+       opt_fields[6].field = &devmode->panningwidth;
+       opt_fields[7].field = &devmode->panningheight;
+               
+       
+       prs_debug(ps, depth, desc, "spoolss_io_devmode");
        depth++;
-       if (!prs_align(ps))
-               return False;
 
-       if(!prs_uint16("type", ps, depth, &type->type))
+       if (UNMARSHALLING(ps)) {
+               devmode->devicename.buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
+               if (devmode->devicename.buffer == NULL)
+                       return False;
+               unistr_buffer = devmode->devicename.buffer;
+       }
+       else {
+               /* devicename is a static sized string but the buffer we set is not */
+               unistr_buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
+               memset( unistr_buffer, 0x0, MAXDEVICENAME );
+               for ( j=0; devmode->devicename.buffer[j]; j++ )
+                       unistr_buffer[j] = devmode->devicename.buffer[j];
+       }
+               
+       if (!prs_uint16uni(True,"devicename", ps, depth, unistr_buffer, MAXDEVICENAME))
                return False;
-       if(!prs_uint16("reserved0", ps, depth, &type->reserved0))
+       
+       if (!prs_uint16("specversion",      ps, depth, &devmode->specversion))
                return False;
-       if(!prs_uint32("reserved1", ps, depth, &type->reserved1))
+               
+       if (!prs_uint16("driverversion",    ps, depth, &devmode->driverversion))
                return False;
-       if(!prs_uint32("reserved2", ps, depth, &type->reserved2))
+       if (!prs_uint16("size",             ps, depth, &devmode->size))
                return False;
-       if(!prs_uint32("count", ps, depth, &type->count))
+       if (!prs_uint16("driverextra",      ps, depth, &devmode->driverextra))
                return False;
-       if(!prs_uint32("fields_ptr", ps, depth, &type->fields_ptr))
+       if (!prs_uint32("fields",           ps, depth, &devmode->fields))
                return False;
-
-       return True;
-}
-
-/*******************************************************************
-reads or writes an NOTIFY OPTION TYPE DATA.
-********************************************************************/  
-
-static bool smb_io_notify_option_type_data(const char *desc, SPOOL_NOTIFY_OPTION_TYPE *type, prs_struct *ps, int depth)
-{
-       int i;
-
-       prs_debug(ps, depth, desc, "smb_io_notify_option_type_data");
-       depth++;
-       /* if there are no fields just return */
-       if (type->fields_ptr==0)
-               return True;
-
-       if(!prs_align(ps))
+       if (!prs_uint16("orientation",      ps, depth, &devmode->orientation))
+               return False;
+       if (!prs_uint16("papersize",        ps, depth, &devmode->papersize))
+               return False;
+       if (!prs_uint16("paperlength",      ps, depth, &devmode->paperlength))
+               return False;
+       if (!prs_uint16("paperwidth",       ps, depth, &devmode->paperwidth))
+               return False;
+       if (!prs_uint16("scale",            ps, depth, &devmode->scale))
+               return False;
+       if (!prs_uint16("copies",           ps, depth, &devmode->copies))
+               return False;
+       if (!prs_uint16("defaultsource",    ps, depth, &devmode->defaultsource))
+               return False;
+       if (!prs_uint16("printquality",     ps, depth, &devmode->printquality))
+               return False;
+       if (!prs_uint16("color",            ps, depth, &devmode->color))
+               return False;
+       if (!prs_uint16("duplex",           ps, depth, &devmode->duplex))
+               return False;
+       if (!prs_uint16("yresolution",      ps, depth, &devmode->yresolution))
+               return False;
+       if (!prs_uint16("ttoption",         ps, depth, &devmode->ttoption))
+               return False;
+       if (!prs_uint16("collate",          ps, depth, &devmode->collate))
                return False;
 
-       if(!prs_uint32("count2", ps, depth, &type->count2))
+       if (UNMARSHALLING(ps)) {
+               devmode->formname.buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
+               if (devmode->formname.buffer == NULL)
+                       return False;
+               unistr_buffer = devmode->formname.buffer;
+       }
+       else {
+               /* devicename is a static sized string but the buffer we set is not */
+               unistr_buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
+               memset( unistr_buffer, 0x0, MAXDEVICENAME );
+               for ( j=0; devmode->formname.buffer[j]; j++ )
+                       unistr_buffer[j] = devmode->formname.buffer[j];
+       }
+       
+       if (!prs_uint16uni(True, "formname",  ps, depth, unistr_buffer, MAXDEVICENAME))
+               return False;
+       if (!prs_uint16("logpixels",        ps, depth, &devmode->logpixels))
+               return False;
+       if (!prs_uint32("bitsperpel",       ps, depth, &devmode->bitsperpel))
+               return False;
+       if (!prs_uint32("pelswidth",        ps, depth, &devmode->pelswidth))
+               return False;
+       if (!prs_uint32("pelsheight",       ps, depth, &devmode->pelsheight))
+               return False;
+       if (!prs_uint32("displayflags",     ps, depth, &devmode->displayflags))
+               return False;
+       if (!prs_uint32("displayfrequency", ps, depth, &devmode->displayfrequency))
                return False;
+       /* 
+        * every device mode I've ever seen on the wire at least has up 
+        * to the displayfrequency field.   --jerry (05-09-2002)
+        */
+        
+       /* add uint32's + uint16's + two UNICODE strings */
+        
+       available_space = devmode->size - (sizeof(uint32)*6 + sizeof(uint16)*18 + sizeof(uint16)*64);
+       
+       /* Sanity check - we only have uint32's left tp parse */
        
-       if (type->count2 != type->count)
-               DEBUG(4,("What a mess, count was %x now is %x !\n", type->count, type->count2));
+       if ( available_space && ((available_space % sizeof(uint32)) != 0) ) {
+               DEBUG(0,("spoolss_io_devmode: available_space [%d] no in multiple of 4 bytes (size = %d)!\n",
+                       available_space, devmode->size));
+               DEBUG(0,("spoolss_io_devmode: please report to samba-technical@samba.org!\n"));
+               return False;
+       }
 
-       if (type->count2 > MAX_NOTIFY_TYPE_FOR_NOW) {
+       /* 
+        * Conditional parsing.  Assume that the DeviceMode has been 
+        * zero'd by the caller. 
+        */
+       
+       while ((available_space > 0)  && (i < DM_NUM_OPTIONAL_FIELDS))
+       {
+               DEBUG(11, ("spoolss_io_devmode: [%d] bytes left to parse in devmode\n", available_space));
+               if (!prs_uint32(opt_fields[i].name, ps, depth, opt_fields[i].field))
+                       return False;
+               available_space -= sizeof(uint32);
+               i++;
+       }        
+       
+       /* Sanity Check - we should no available space at this point unless 
+          MS changes the device mode structure */
+               
+       if (available_space) {
+               DEBUG(0,("spoolss_io_devmode: I've parsed all I know and there is still stuff left|\n"));
+               DEBUG(0,("spoolss_io_devmode: available_space = [%d], devmode_size = [%d]!\n",
+                       available_space, devmode->size));
+               DEBUG(0,("spoolss_io_devmode: please report to samba-technical@samba.org!\n"));
                return False;
        }
 
-       /* parse the option type data */
-       for(i=0;i<type->count2;i++)
-               if(!prs_uint16("fields",ps,depth,&type->fields[i]))
+
+       if (devmode->driverextra!=0) {
+               if (UNMARSHALLING(ps)) {
+                       devmode->dev_private=PRS_ALLOC_MEM(ps, uint8, devmode->driverextra);
+                       if(devmode->dev_private == NULL)
+                               return False;
+                       DEBUG(7,("spoolss_io_devmode: allocated memory [%d] for dev_private\n",devmode->driverextra)); 
+               }
+                       
+               DEBUG(7,("spoolss_io_devmode: parsing [%d] bytes of dev_private\n",devmode->driverextra));
+               if (!prs_uint8s(False, "dev_private",  ps, depth,
+                               devmode->dev_private, devmode->driverextra))
                        return False;
+       }
+
        return True;
 }
 
 /*******************************************************************
-reads or writes an NOTIFY OPTION structure.
-********************************************************************/  
+ * make a structure.
+ ********************************************************************/
 
-static bool smb_io_notify_option_type_ctr(const char *desc, SPOOL_NOTIFY_OPTION_TYPE_CTR *ctr , prs_struct *ps, int depth)
-{              
-       int i;
-       
-       prs_debug(ps, depth, desc, "smb_io_notify_option_type_ctr");
-       depth++;
-       if(!prs_uint32("count", ps, depth, &ctr->count))
-               return False;
+bool make_spoolss_q_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u,
+                                  const POLICY_HND *handle,
+                                  const char *valuename, uint32 size)
+{
+        if (q_u == NULL) return False;
 
-       /* reading */
-       if (UNMARSHALLING(ps) && ctr->count)
-               if((ctr->type=PRS_ALLOC_MEM(ps,SPOOL_NOTIFY_OPTION_TYPE,ctr->count)) == NULL)
-                       return False;
-               
-       /* the option type struct */
-       for(i=0;i<ctr->count;i++)
-               if(!smb_io_notify_option_type("", &ctr->type[i] , ps, depth))
-                       return False;
+        DEBUG(5,("make_spoolss_q_getprinterdata\n"));
 
-       /* the type associated with the option type struct */
-       for(i=0;i<ctr->count;i++)
-               if(!smb_io_notify_option_type_data("", &ctr->type[i] , ps, depth))
-                       return False;
-       
-       return True;
+        q_u->handle = *handle;
+       init_unistr2(&q_u->valuename, valuename, UNI_STR_TERMINATE);
+        q_u->size = size;
+
+        return True;
 }
 
 /*******************************************************************
-reads or writes an NOTIFY OPTION structure.
-********************************************************************/  
+ * read a structure.
+ * called from spoolss_q_getprinterdata (srv_spoolss.c)
+ ********************************************************************/
 
-static bool smb_io_notify_option(const char *desc, SPOOL_NOTIFY_OPTION *option, prs_struct *ps, int depth)
+bool spoolss_io_q_getprinterdata(const char *desc, SPOOL_Q_GETPRINTERDATA *q_u, prs_struct *ps, int depth)
 {
-       prs_debug(ps, depth, desc, "smb_io_notify_option");
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "spoolss_io_q_getprinterdata");
        depth++;
-       
-       if(!prs_uint32("version", ps, depth, &option->version))
+
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint32("flags", ps, depth, &option->flags))
+       if (!smb_io_pol_hnd("printer handle",&q_u->handle,ps,depth))
                return False;
-       if(!prs_uint32("count", ps, depth, &option->count))
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint32("option_type_ptr", ps, depth, &option->option_type_ptr))
+       if (!smb_io_unistr2("valuename", &q_u->valuename,True,ps,depth))
                return False;
-       
-       /* marshalling or unmarshalling, that would work */     
-       if (option->option_type_ptr!=0) {
-               if(!smb_io_notify_option_type_ctr("", &option->ctr ,ps, depth))
-                       return False;
-       }
-       else {
-               option->ctr.type=NULL;
-               option->ctr.count=0;
-       }
-       
+       if (!prs_align(ps))
+               return False;
+       if (!prs_uint32("size", ps, depth, &q_u->size))
+               return False;
+
        return True;
 }
 
 /*******************************************************************
-reads or writes an NOTIFY INFO DATA structure.
-********************************************************************/  
+ * write a structure.
+ * called from spoolss_r_getprinterdata (srv_spoolss.c)
+ ********************************************************************/
 
-static bool smb_io_notify_info_data(const char *desc,SPOOL_NOTIFY_INFO_DATA *data, prs_struct *ps, int depth)
+bool spoolss_io_r_getprinterdata(const char *desc, SPOOL_R_GETPRINTERDATA *r_u, prs_struct *ps, int depth)
 {
-       uint32 useless_ptr=0x0FF0ADDE;
+       if (r_u == NULL)
+               return False;
 
-       prs_debug(ps, depth, desc, "smb_io_notify_info_data");
+       prs_debug(ps, depth, desc, "spoolss_io_r_getprinterdata");
        depth++;
 
-       if(!prs_align(ps))
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint16("type",           ps, depth, &data->type))
+       if (!prs_uint32("type", ps, depth, &r_u->type))
                return False;
-       if(!prs_uint16("field",          ps, depth, &data->field))
+       if (!prs_uint32("size", ps, depth, &r_u->size))
                return False;
+       
+       if (UNMARSHALLING(ps) && r_u->size) {
+               r_u->data = PRS_ALLOC_MEM(ps, unsigned char, r_u->size);
+               if(!r_u->data)
+                       return False;
+       }
 
-       if(!prs_uint32("how many words", ps, depth, &data->size))
+       if (!prs_uint8s( False, "data", ps, depth, r_u->data, r_u->size ))
+               return False;
+               
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint32("id",             ps, depth, &data->id))
+       
+       if (!prs_uint32("needed", ps, depth, &r_u->needed))
                return False;
-       if(!prs_uint32("how many words", ps, depth, &data->size))
+       if (!prs_werror("status", ps, depth, &r_u->status))
                return False;
+               
+       return True;
+}
 
-       switch (data->enc_type) {
-
-               /* One and two value data has two uint32 values */
-
-       case NOTIFY_ONE_VALUE:
-       case NOTIFY_TWO_VALUE:
-
-               if(!prs_uint32("value[0]", ps, depth, &data->notify_data.value[0]))
-                       return False;
-               if(!prs_uint32("value[1]", ps, depth, &data->notify_data.value[1]))
-                       return False;
-               break;
-
-               /* Pointers and strings have a string length and a
-                  pointer.  For a string the length is expressed as
-                  the number of uint16 characters plus a trailing
-                  \0\0. */
-
-       case NOTIFY_POINTER:
-
-               if(!prs_uint32("string length", ps, depth, &data->notify_data.data.length ))
-                       return False;
-               if(!prs_uint32("pointer", ps, depth, &useless_ptr))
-                       return False;
-
-               break;
-
-       case NOTIFY_STRING:
-
-               if(!prs_uint32("string length", ps, depth, &data->notify_data.data.length))
-                       return False;
-
-               if(!prs_uint32("pointer", ps, depth, &useless_ptr))
-                       return False;
-
-               break;
-
-       case NOTIFY_SECDESC:
-               if( !prs_uint32( "sd size", ps, depth, &data->notify_data.sd.size ) )
-                       return False;
-               if( !prs_uint32( "pointer", ps, depth, &useless_ptr ) )
-                       return False;
-               
-               break;
-
-       default:
-               DEBUG(3, ("invalid enc_type %d for smb_io_notify_info_data\n",
-                         data->enc_type));
-               break;
-       }
+/*******************************************************************
+ * return the length of a uint16 (obvious, but the code is clean)
+ ********************************************************************/
 
-       return True;
+static uint32 size_of_uint16(uint16 *value)
+{
+       return (sizeof(*value));
 }
 
 /*******************************************************************
-reads or writes an NOTIFY INFO DATA structure.
-********************************************************************/  
+ * return the length of a uint32 (obvious, but the code is clean)
+ ********************************************************************/
 
-bool smb_io_notify_info_data_strings(const char *desc,SPOOL_NOTIFY_INFO_DATA *data,
-                                     prs_struct *ps, int depth)
+static uint32 size_of_uint32(uint32 *value)
 {
-       prs_debug(ps, depth, desc, "smb_io_notify_info_data_strings");
-       depth++;
-       
-       if(!prs_align(ps))
-               return False;
+       return (sizeof(*value));
+}
 
-       switch(data->enc_type) {
+/*******************************************************************
+ * return the length of a NTTIME (obvious, but the code is clean)
+ ********************************************************************/
 
-               /* No data for values */
+static uint32 size_of_nttime(NTTIME *value)
+{
+       return (sizeof(*value));
+}
 
-       case NOTIFY_ONE_VALUE:
-       case NOTIFY_TWO_VALUE:
+/*******************************************************************
+ * return the length of a uint32 (obvious, but the code is clean)
+ ********************************************************************/
 
-               break;
+static uint32 size_of_device_mode(DEVICEMODE *devmode)
+{
+       if (devmode==NULL)
+               return (4);
+       else 
+               return (4+devmode->size+devmode->driverextra);
+}
 
-               /* Strings start with a length in uint16s */
+/*******************************************************************
+ * return the length of a uint32 (obvious, but the code is clean)
+ ********************************************************************/
 
-       case NOTIFY_STRING:
+static uint32 size_of_systemtime(SYSTEMTIME *systime)
+{
+       if (systime==NULL)
+               return (4);
+       else 
+               return (sizeof(SYSTEMTIME) +4);
+}
 
-               if (MARSHALLING(ps))
-                       data->notify_data.data.length /= 2;
+/*******************************************************************
+ Parse a DEVMODE structure and its relative pointer.
+********************************************************************/
 
-               if(!prs_uint32("string length", ps, depth, &data->notify_data.data.length))
-                       return False;
+static bool smb_io_reldevmode(const char *desc, RPC_BUFFER *buffer, int depth, DEVICEMODE **devmode)
+{
+       prs_struct *ps=&buffer->prs;
 
-               if (UNMARSHALLING(ps) && data->notify_data.data.length) {
-                       data->notify_data.data.string = PRS_ALLOC_MEM(ps, uint16,
-                                                               data->notify_data.data.length);
+       prs_debug(ps, depth, desc, "smb_io_reldevmode");
+       depth++;
 
-                       if (!data->notify_data.data.string) 
+       if (MARSHALLING(ps)) {
+               uint32 struct_offset = prs_offset(ps);
+               uint32 relative_offset;
+               
+               if (*devmode == NULL) {
+                       relative_offset=0;
+                       if (!prs_uint32("offset", ps, depth, &relative_offset))
                                return False;
+                       DEBUG(8, ("boing, the devmode was NULL\n"));
+                       
+                       return True;
                }
+               
+               buffer->string_at_end -= ((*devmode)->size + (*devmode)->driverextra);
 
-               if (!prs_uint16uni(True, "string", ps, depth, data->notify_data.data.string,
-                                  data->notify_data.data.length))
-                       return False;
-
-               if (MARSHALLING(ps))
-                       data->notify_data.data.length *= 2;
-
-               break;
-
-       case NOTIFY_POINTER:
-
-               if (UNMARSHALLING(ps) && data->notify_data.data.length) {
-                       data->notify_data.data.string = PRS_ALLOC_MEM(ps, uint16,
-                                                               data->notify_data.data.length);
-
-                       if (!data->notify_data.data.string) 
-                               return False;
+               /* mz:  we have to align the device mode for VISTA */
+               if (buffer->string_at_end % 4) {
+                       buffer->string_at_end += 4 - (buffer->string_at_end % 4);
                }
 
-               if(!prs_uint8s(True,"buffer",ps,depth,(uint8*)data->notify_data.data.string,data->notify_data.data.length))
+               if(!prs_set_offset(ps, buffer->string_at_end))
+                       return False;
+               
+               /* write the DEVMODE */
+               if (!spoolss_io_devmode(desc, ps, depth, *devmode))
                        return False;
 
-               break;
-
-       case NOTIFY_SECDESC:    
-               if( !prs_uint32("secdesc size ", ps, depth, &data->notify_data.sd.size ) )
+               if(!prs_set_offset(ps, struct_offset))
                        return False;
-               if ( !sec_io_desc( "sec_desc", &data->notify_data.sd.desc, ps, depth ) )
+               
+               relative_offset=buffer->string_at_end - buffer->struct_start;
+               /* write its offset */
+               if (!prs_uint32("offset", ps, depth, &relative_offset))
                        return False;
-               break;
-
-       default:
-               DEBUG(3, ("invalid enc_type %d for smb_io_notify_info_data_strings\n",
-                         data->enc_type));
-               break;
        }
-
-#if 0
-       if (isvalue==False) {
-
-               /* length of string in unicode include \0 */
-               x=data->notify_data.data.length+1;
-
-               if (data->field != 16)
-               if(!prs_uint32("string length", ps, depth, &x ))
+       else {
+               uint32 old_offset;
+               
+               /* read the offset */
+               if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
                        return False;
-
-               if (MARSHALLING(ps)) {
-                       /* These are already in little endian format. Don't byte swap. */
-                       if (x == 1) {
-
-                               /* No memory allocated for this string
-                                  therefore following the data.string
-                                  pointer is a bad idea.  Use a pointer to
-                                  the uint32 length union member to
-                                  provide a source for a unicode NULL */
-
-                               if(!prs_uint8s(True,"string",ps,depth, (uint8 *)&data->notify_data.data.length,x*2)) 
-                                       return False;
-                       } else {
-
-                               if (data->field == 16)
-                                       x /= 2;
-
-                               if(!prs_uint16uni(True,"string",ps,depth,data->notify_data.data.string,x))
-                                       return False;
-                       }
-               } else {
-
-                       /* Tallocate memory for string */
-
-                       if (x) {
-                               data->notify_data.data.string = PRS_ALLOC_MEM(ps, uint16, x * 2);
-                               if (!data->notify_data.data.string) 
-                                       return False;
-                       } else {
-                               data->notify_data.data.string = NULL;
-                       }
-
-                       if(!prs_uint16uni(True,"string",ps,depth,data->notify_data.data.string,x))
-                               return False;
+               if (buffer->string_at_end == 0) {
+                       *devmode = NULL;
+                       return True;
                }
-       }
 
-#endif
+               old_offset = prs_offset(ps);
+               if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
+                       return False;
 
-#if 0  /* JERRY */
-       /* Win2k does not seem to put this parse align here */
-       if(!prs_align(ps))
-               return False;
-#endif
+               /* read the string */
+               if((*devmode=PRS_ALLOC_MEM(ps,DEVICEMODE,1)) == NULL)
+                       return False;
+               if (!spoolss_io_devmode(desc, ps, depth, *devmode))
+                       return False;
 
+               if(!prs_set_offset(ps, old_offset))
+                       return False;
+       }
        return True;
 }
 
 /*******************************************************************
-reads or writes an NOTIFY INFO structure.
+ Parse a PRINTER_INFO_0 structure.
 ********************************************************************/  
 
-static bool smb_io_notify_info(const char *desc, SPOOL_NOTIFY_INFO *info, prs_struct *ps, int depth)
+bool smb_io_printer_info_0(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_0 *info, int depth)
 {
-       int i;
+       prs_struct *ps=&buffer->prs;
 
-       prs_debug(ps, depth, desc, "smb_io_notify_info");
-       depth++;
-       if(!prs_align(ps))
-               return False;
+       prs_debug(ps, depth, desc, "smb_io_printer_info_0");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
 
-       if(!prs_uint32("count", ps, depth, &info->count))
+       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
                return False;
-       if(!prs_uint32("version", ps, depth, &info->version))
+       if (!smb_io_relstr("servername", buffer, depth, &info->servername))
                return False;
-       if(!prs_uint32("flags", ps, depth, &info->flags))
+       
+       if(!prs_uint32("cjobs", ps, depth, &info->cjobs))
                return False;
-       if(!prs_uint32("count", ps, depth, &info->count))
+       if(!prs_uint32("total_jobs", ps, depth, &info->total_jobs))
                return False;
-
-       for (i=0;i<info->count;i++) {
-               if(!smb_io_notify_info_data(desc, &info->data[i], ps, depth))
-                       return False;
-       }
-
-       /* now do the strings at the end of the stream */       
-       for (i=0;i<info->count;i++) {
-               if(!smb_io_notify_info_data_strings(desc, &info->data[i], ps, depth))
-                       return False;
-       }
-
-       return True;
-}
-
-/*******************************************************************
-********************************************************************/  
-
-bool spool_io_user_level_1( const char *desc, prs_struct *ps, int depth, SPOOL_USER_1 *q_u )
-{
-       prs_debug(ps, depth, desc, "");
-       depth++;
-
-       if (!prs_align(ps))
+       if(!prs_uint32("total_bytes", ps, depth, &info->total_bytes))
                return False;
 
-       if (!prs_uint32("size", ps, depth, &q_u->size))
+       if(!prs_uint16("year", ps, depth, &info->year))
                return False;
-
-       if (!prs_io_unistr2_p("", ps, depth, &q_u->client_name))
+       if(!prs_uint16("month", ps, depth, &info->month))
                return False;
-       if (!prs_io_unistr2_p("", ps, depth, &q_u->user_name))
+       if(!prs_uint16("dayofweek", ps, depth, &info->dayofweek))
                return False;
-
-       if (!prs_uint32("build", ps, depth, &q_u->build))
+       if(!prs_uint16("day", ps, depth, &info->day))
+               return False;
+       if(!prs_uint16("hour", ps, depth, &info->hour))
                return False;
-       if (!prs_uint32("major", ps, depth, &q_u->major))
+       if(!prs_uint16("minute", ps, depth, &info->minute))
                return False;
-       if (!prs_uint32("minor", ps, depth, &q_u->minor))
+       if(!prs_uint16("second", ps, depth, &info->second))
                return False;
-       if (!prs_uint32("processor", ps, depth, &q_u->processor))
+       if(!prs_uint16("milliseconds", ps, depth, &info->milliseconds))
                return False;
 
-       if (!prs_io_unistr2("", ps, depth, q_u->client_name))
+       if(!prs_uint32("global_counter", ps, depth, &info->global_counter))
                return False;
-       if (!prs_align(ps))
+       if(!prs_uint32("total_pages", ps, depth, &info->total_pages))
                return False;
 
-       if (!prs_io_unistr2("", ps, depth, q_u->user_name))
+       if(!prs_uint16("major_version", ps, depth, &info->major_version))
+               return False;
+       if(!prs_uint16("build_version", ps, depth, &info->build_version))
+               return False;
+       if(!prs_uint32("unknown7", ps, depth, &info->unknown7))
+               return False;
+       if(!prs_uint32("unknown8", ps, depth, &info->unknown8))
+               return False;
+       if(!prs_uint32("unknown9", ps, depth, &info->unknown9))
+               return False;
+       if(!prs_uint32("session_counter", ps, depth, &info->session_counter))
+               return False;
+       if(!prs_uint32("unknown11", ps, depth, &info->unknown11))
+               return False;
+       if(!prs_uint32("printer_errors", ps, depth, &info->printer_errors))
+               return False;
+       if(!prs_uint32("unknown13", ps, depth, &info->unknown13))
+               return False;
+       if(!prs_uint32("unknown14", ps, depth, &info->unknown14))
+               return False;
+       if(!prs_uint32("unknown15", ps, depth, &info->unknown15))
+               return False;
+       if(!prs_uint32("unknown16", ps, depth, &info->unknown16))
+               return False;
+       if(!prs_uint32("change_id", ps, depth, &info->change_id))
+               return False;
+       if(!prs_uint32("unknown18", ps, depth, &info->unknown18))
+               return False;
+       if(!prs_uint32("status"   , ps, depth, &info->status))
+               return False;
+       if(!prs_uint32("unknown20", ps, depth, &info->unknown20))
+               return False;
+       if(!prs_uint32("c_setprinter", ps, depth, &info->c_setprinter))
+               return False;
+       if(!prs_uint16("unknown22", ps, depth, &info->unknown22))
+               return False;
+       if(!prs_uint16("unknown23", ps, depth, &info->unknown23))
+               return False;
+       if(!prs_uint16("unknown24", ps, depth, &info->unknown24))
+               return False;
+       if(!prs_uint16("unknown25", ps, depth, &info->unknown25))
+               return False;
+       if(!prs_uint16("unknown26", ps, depth, &info->unknown26))
+               return False;
+       if(!prs_uint16("unknown27", ps, depth, &info->unknown27))
+               return False;
+       if(!prs_uint16("unknown28", ps, depth, &info->unknown28))
+               return False;
+       if(!prs_uint16("unknown29", ps, depth, &info->unknown29))
                return False;
 
        return True;
 }
 
 /*******************************************************************
+ Parse a PRINTER_INFO_1 structure.
 ********************************************************************/  
 
-static bool spool_io_user_level(const char *desc, SPOOL_USER_CTR *q_u, prs_struct *ps, int depth)
+bool smb_io_printer_info_1(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_1 *info, int depth)
 {
-       if (q_u==NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "spool_io_user_level");
-       depth++;
+       prs_struct *ps=&buffer->prs;
 
-       if (!prs_align(ps))
-               return False;
+       prs_debug(ps, depth, desc, "smb_io_printer_info_1");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
 
-       if (!prs_uint32("level", ps, depth, &q_u->level))
+       if (!prs_uint32("flags", ps, depth, &info->flags))
                return False;
-       
-       switch ( q_u->level ) 
-       {       
-               case 1:
-                       if ( !prs_pointer( "" , ps, depth, (void*)&q_u->user.user1, 
-                               sizeof(SPOOL_USER_1), (PRS_POINTER_CAST)spool_io_user_level_1 )) 
-                       {
-                               return False;
-                       }
-                       break;
-               default:
-                       return False;   
-       }       
+       if (!smb_io_relstr("description", buffer, depth, &info->description))
+               return False;
+       if (!smb_io_relstr("name", buffer, depth, &info->name))
+               return False;
+       if (!smb_io_relstr("comment", buffer, depth, &info->comment))
+               return False;   
 
        return True;
 }
 
 /*******************************************************************
- * read or write a DEVICEMODE struct.
- * on reading allocate memory for the private member
- ********************************************************************/
-
-#define DM_NUM_OPTIONAL_FIELDS                 8
+ Parse a PRINTER_INFO_2 structure.
+********************************************************************/  
 
-bool spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE *devmode)
+bool smb_io_printer_info_2(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_2 *info, int depth)
 {
-       int available_space;            /* size of the device mode left to parse */
-                                       /* only important on unmarshalling       */
-       int i = 0;
-       uint16 *unistr_buffer;
-       int j;
-                                       
-       struct optional_fields {
-               fstring         name;
-               uint32*         field;
-       } opt_fields[DM_NUM_OPTIONAL_FIELDS] = {
-               { "icmmethod",          NULL },
-               { "icmintent",          NULL },
-               { "mediatype",          NULL },
-               { "dithertype",         NULL },
-               { "reserved1",          NULL },
-               { "reserved2",          NULL },
-               { "panningwidth",       NULL },
-               { "panningheight",      NULL }
-       };
-
-       /* assign at run time to keep non-gcc compilers happy */
+       prs_struct *ps=&buffer->prs;
+       uint32 dm_offset, sd_offset, current_offset;
+       uint32 dummy_value = 0, has_secdesc = 0;
 
-       opt_fields[0].field = &devmode->icmmethod;
-       opt_fields[1].field = &devmode->icmintent;
-       opt_fields[2].field = &devmode->mediatype;
-       opt_fields[3].field = &devmode->dithertype;
-       opt_fields[4].field = &devmode->reserved1;
-       opt_fields[5].field = &devmode->reserved2;
-       opt_fields[6].field = &devmode->panningwidth;
-       opt_fields[7].field = &devmode->panningheight;
-               
+       prs_debug(ps, depth, desc, "smb_io_printer_info_2");
+       depth++;        
        
-       prs_debug(ps, depth, desc, "spoolss_io_devmode");
-       depth++;
-
-       if (UNMARSHALLING(ps)) {
-               devmode->devicename.buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
-               if (devmode->devicename.buffer == NULL)
-                       return False;
-               unistr_buffer = devmode->devicename.buffer;
-       }
-       else {
-               /* devicename is a static sized string but the buffer we set is not */
-               unistr_buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
-               memset( unistr_buffer, 0x0, MAXDEVICENAME );
-               for ( j=0; devmode->devicename.buffer[j]; j++ )
-                       unistr_buffer[j] = devmode->devicename.buffer[j];
-       }
-               
-       if (!prs_uint16uni(True,"devicename", ps, depth, unistr_buffer, MAXDEVICENAME))
-               return False;
+       buffer->struct_start=prs_offset(ps);
        
-       if (!prs_uint16("specversion",      ps, depth, &devmode->specversion))
-               return False;
-               
-       if (!prs_uint16("driverversion",    ps, depth, &devmode->driverversion))
-               return False;
-       if (!prs_uint16("size",             ps, depth, &devmode->size))
-               return False;
-       if (!prs_uint16("driverextra",      ps, depth, &devmode->driverextra))
+       if (!smb_io_relstr("servername", buffer, depth, &info->servername))
                return False;
-       if (!prs_uint32("fields",           ps, depth, &devmode->fields))
+       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
                return False;
-       if (!prs_uint16("orientation",      ps, depth, &devmode->orientation))
+       if (!smb_io_relstr("sharename", buffer, depth, &info->sharename))
                return False;
-       if (!prs_uint16("papersize",        ps, depth, &devmode->papersize))
+       if (!smb_io_relstr("portname", buffer, depth, &info->portname))
                return False;
-       if (!prs_uint16("paperlength",      ps, depth, &devmode->paperlength))
+       if (!smb_io_relstr("drivername", buffer, depth, &info->drivername))
                return False;
-       if (!prs_uint16("paperwidth",       ps, depth, &devmode->paperwidth))
+       if (!smb_io_relstr("comment", buffer, depth, &info->comment))
                return False;
-       if (!prs_uint16("scale",            ps, depth, &devmode->scale))
+       if (!smb_io_relstr("location", buffer, depth, &info->location))
                return False;
-       if (!prs_uint16("copies",           ps, depth, &devmode->copies))
+
+       /* save current offset and wind forwared by a uint32 */
+       dm_offset = prs_offset(ps);
+       if (!prs_uint32("devmode", ps, depth, &dummy_value))
                return False;
-       if (!prs_uint16("defaultsource",    ps, depth, &devmode->defaultsource))
+       
+       if (!smb_io_relstr("sepfile", buffer, depth, &info->sepfile))
                return False;
-       if (!prs_uint16("printquality",     ps, depth, &devmode->printquality))
+       if (!smb_io_relstr("printprocessor", buffer, depth, &info->printprocessor))
                return False;
-       if (!prs_uint16("color",            ps, depth, &devmode->color))
+       if (!smb_io_relstr("datatype", buffer, depth, &info->datatype))
                return False;
-       if (!prs_uint16("duplex",           ps, depth, &devmode->duplex))
+       if (!smb_io_relstr("parameters", buffer, depth, &info->parameters))
                return False;
-       if (!prs_uint16("yresolution",      ps, depth, &devmode->yresolution))
+
+       /* save current offset for the sec_desc */
+       sd_offset = prs_offset(ps);
+       if (!prs_uint32("sec_desc", ps, depth, &has_secdesc))
                return False;
-       if (!prs_uint16("ttoption",         ps, depth, &devmode->ttoption))
+
+       
+       /* save current location so we can pick back up here */
+       current_offset = prs_offset(ps);
+       
+       /* parse the devmode */
+       if (!prs_set_offset(ps, dm_offset))
                return False;
-       if (!prs_uint16("collate",          ps, depth, &devmode->collate))
+       if (!smb_io_reldevmode("devmode", buffer, depth, &info->devmode))
                return False;
-
-       if (UNMARSHALLING(ps)) {
-               devmode->formname.buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
-               if (devmode->formname.buffer == NULL)
+       
+       /* parse the sec_desc */
+       if (info->secdesc) {
+               if (!prs_set_offset(ps, sd_offset))
+                       return False;
+               if (!smb_io_relsecdesc("secdesc", buffer, depth, &info->secdesc))
                        return False;
-               unistr_buffer = devmode->formname.buffer;
-       }
-       else {
-               /* devicename is a static sized string but the buffer we set is not */
-               unistr_buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
-               memset( unistr_buffer, 0x0, MAXDEVICENAME );
-               for ( j=0; devmode->formname.buffer[j]; j++ )
-                       unistr_buffer[j] = devmode->formname.buffer[j];
        }
-       
-       if (!prs_uint16uni(True, "formname",  ps, depth, unistr_buffer, MAXDEVICENAME))
+
+       /* pick up where we left off */
+       if (!prs_set_offset(ps, current_offset))
                return False;
-       if (!prs_uint16("logpixels",        ps, depth, &devmode->logpixels))
+
+       if (!prs_uint32("attributes", ps, depth, &info->attributes))
                return False;
-       if (!prs_uint32("bitsperpel",       ps, depth, &devmode->bitsperpel))
+       if (!prs_uint32("priority", ps, depth, &info->priority))
                return False;
-       if (!prs_uint32("pelswidth",        ps, depth, &devmode->pelswidth))
+       if (!prs_uint32("defpriority", ps, depth, &info->defaultpriority))
                return False;
-       if (!prs_uint32("pelsheight",       ps, depth, &devmode->pelsheight))
+       if (!prs_uint32("starttime", ps, depth, &info->starttime))
                return False;
-       if (!prs_uint32("displayflags",     ps, depth, &devmode->displayflags))
+       if (!prs_uint32("untiltime", ps, depth, &info->untiltime))
                return False;
-       if (!prs_uint32("displayfrequency", ps, depth, &devmode->displayfrequency))
+       if (!prs_uint32("status", ps, depth, &info->status))
                return False;
-       /* 
-        * every device mode I've ever seen on the wire at least has up 
-        * to the displayfrequency field.   --jerry (05-09-2002)
-        */
-        
-       /* add uint32's + uint16's + two UNICODE strings */
-        
-       available_space = devmode->size - (sizeof(uint32)*6 + sizeof(uint16)*18 + sizeof(uint16)*64);
-       
-       /* Sanity check - we only have uint32's left tp parse */
-       
-       if ( available_space && ((available_space % sizeof(uint32)) != 0) ) {
-               DEBUG(0,("spoolss_io_devmode: available_space [%d] no in multiple of 4 bytes (size = %d)!\n",
-                       available_space, devmode->size));
-               DEBUG(0,("spoolss_io_devmode: please report to samba-technical@samba.org!\n"));
+       if (!prs_uint32("jobs", ps, depth, &info->cjobs))
                return False;
-       }
-
-       /* 
-        * Conditional parsing.  Assume that the DeviceMode has been 
-        * zero'd by the caller. 
-        */
-       
-       while ((available_space > 0)  && (i < DM_NUM_OPTIONAL_FIELDS))
-       {
-               DEBUG(11, ("spoolss_io_devmode: [%d] bytes left to parse in devmode\n", available_space));
-               if (!prs_uint32(opt_fields[i].name, ps, depth, opt_fields[i].field))
-                       return False;
-               available_space -= sizeof(uint32);
-               i++;
-       }        
-       
-       /* Sanity Check - we should no available space at this point unless 
-          MS changes the device mode structure */
-               
-       if (available_space) {
-               DEBUG(0,("spoolss_io_devmode: I've parsed all I know and there is still stuff left|\n"));
-               DEBUG(0,("spoolss_io_devmode: available_space = [%d], devmode_size = [%d]!\n",
-                       available_space, devmode->size));
-               DEBUG(0,("spoolss_io_devmode: please report to samba-technical@samba.org!\n"));
+       if (!prs_uint32("averageppm", ps, depth, &info->averageppm))
                return False;
-       }
-
-
-       if (devmode->driverextra!=0) {
-               if (UNMARSHALLING(ps)) {
-                       devmode->dev_private=PRS_ALLOC_MEM(ps, uint8, devmode->driverextra);
-                       if(devmode->dev_private == NULL)
-                               return False;
-                       DEBUG(7,("spoolss_io_devmode: allocated memory [%d] for dev_private\n",devmode->driverextra)); 
-               }
-                       
-               DEBUG(7,("spoolss_io_devmode: parsing [%d] bytes of dev_private\n",devmode->driverextra));
-               if (!prs_uint8s(False, "dev_private",  ps, depth,
-                               devmode->dev_private, devmode->driverextra))
-                       return False;
-       }
 
        return True;
 }
 
 /*******************************************************************
- Read or write a DEVICEMODE container
+ Parse a PRINTER_INFO_3 structure.
 ********************************************************************/  
 
-static bool spoolss_io_devmode_cont(const char *desc, DEVMODE_CTR *dm_c, prs_struct *ps, int depth)
+bool smb_io_printer_info_3(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_3 *info, int depth)
 {
-       if (dm_c==NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "spoolss_io_devmode_cont");
-       depth++;
+       uint32 offset = 0;
+       prs_struct *ps=&buffer->prs;
 
-       if(!prs_align(ps))
-               return False;
+       prs_debug(ps, depth, desc, "smb_io_printer_info_3");
+       depth++;        
        
-       if (!prs_uint32("size", ps, depth, &dm_c->size))
-               return False;
+       buffer->struct_start=prs_offset(ps);
+       
+       if (MARSHALLING(ps)) {
+               /* Ensure the SD is 8 byte aligned in the buffer. */
+               uint32 start = prs_offset(ps); /* Remember the start position. */
+               uint32 off_val = 0;
 
-       if (!prs_uint32("devmode_ptr", ps, depth, &dm_c->devmode_ptr))
-               return False;
+               /* Write a dummy value. */
+               if (!prs_uint32("offset", ps, depth, &off_val))
+                       return False;
 
-       if (dm_c->size==0 || dm_c->devmode_ptr==0) {
-               if (UNMARSHALLING(ps))
-                       /* if while reading there is no DEVMODE ... */
-                       dm_c->devmode=NULL;
-               return True;
-       }
-       
-       /* so we have a DEVICEMODE to follow */         
-       if (UNMARSHALLING(ps)) {
-               DEBUG(9,("Allocating memory for spoolss_io_devmode\n"));
-               dm_c->devmode=PRS_ALLOC_MEM(ps,DEVICEMODE,1);
-               if(dm_c->devmode == NULL)
+               /* 8 byte align. */
+               if (!prs_align_uint64(ps))
                        return False;
-       }
-       
-       /* this is bad code, shouldn't be there */
-       if (!prs_uint32("size", ps, depth, &dm_c->size))
-               return False;
-               
-       if (!spoolss_io_devmode(desc, ps, depth, dm_c->devmode))
-               return False;
+
+               /* Remember where we must seek back to write the SD. */
+               offset = prs_offset(ps);
+
+               /* Calculate the real offset for the SD. */
+
+               off_val = offset - start;
+
+               /* Seek back to where we store the SD offset & store. */
+               prs_set_offset(ps, start);
+               if (!prs_uint32("offset", ps, depth, &off_val))
+                       return False;
+
+               /* Return to after the 8 byte align. */
+               prs_set_offset(ps, offset);
+
+       } else {
+               if (!prs_uint32("offset", ps, depth, &offset))
+                       return False;
+               /* Seek within the buffer. */
+               if (!prs_set_offset(ps, offset))
+                       return False;
+       }
+       if (!sec_io_desc("sec_desc", &info->secdesc, ps, depth))
+               return False;
 
        return True;
 }
 
 /*******************************************************************
* init a structure.
- ********************************************************************/
Parse a PRINTER_INFO_4 structure.
+********************************************************************/  
 
-bool make_spoolss_q_addprinterex( TALLOC_CTX *mem_ctx, SPOOL_Q_ADDPRINTEREX *q_u, 
-       const char *srv_name, const char* clientname, const char* user_name,
-       uint32 level, PRINTER_INFO_CTR *ctr)
+bool smb_io_printer_info_4(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_4 *info, int depth)
 {
-       DEBUG(5,("make_spoolss_q_addprinterex\n"));
+       prs_struct *ps=&buffer->prs;
+
+       prs_debug(ps, depth, desc, "smb_io_printer_info_4");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
        
-       if (!ctr || !ctr->printers_2) 
+       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
                return False;
-
-       ZERO_STRUCTP(q_u);
-
-       q_u->server_name = TALLOC_P( mem_ctx, UNISTR2 );
-       if (!q_u->server_name) {
+       if (!smb_io_relstr("servername", buffer, depth, &info->servername))
                return False;
-       }
-       init_unistr2(q_u->server_name, srv_name, UNI_FLAGS_NONE);
+       if (!prs_uint32("attributes", ps, depth, &info->attributes))
+               return False;
+       return True;
+}
 
-       q_u->level = level;
-       
-       q_u->info.level = level;
-       q_u->info.info_ptr = (ctr->printers_2!=NULL)?1:0;
-       switch (level) {
-               case 2:
-                       /* init q_u->info.info2 from *info */
-                       if (!make_spoolss_printer_info_2(mem_ctx, &q_u->info.info_2, ctr->printers_2)) {
-                               DEBUG(0,("make_spoolss_q_addprinterex: Unable to fill SPOOL_Q_ADDPRINTEREX struct!\n"));
-                               return False;
-                       }
-                       break;
-               default :
-                       break;
-       }
+/*******************************************************************
+ Parse a PRINTER_INFO_5 structure.
+********************************************************************/  
 
-       q_u->user_switch=1;
+bool smb_io_printer_info_5(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_5 *info, int depth)
+{
+       prs_struct *ps=&buffer->prs;
 
-       q_u->user_ctr.level                 = 1;
-       q_u->user_ctr.user.user1            = TALLOC_P( talloc_tos(), SPOOL_USER_1 );
-       if (!q_u->user_ctr.user.user1) {
+       prs_debug(ps, depth, desc, "smb_io_printer_info_5");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
+       
+       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
                return False;
-       }
-       q_u->user_ctr.user.user1->build     = 1381;
-       q_u->user_ctr.user.user1->major     = 2; 
-       q_u->user_ctr.user.user1->minor     = 0;
-       q_u->user_ctr.user.user1->processor = 0;
-
-       q_u->user_ctr.user.user1->client_name = TALLOC_P( mem_ctx, UNISTR2 );
-       if (!q_u->user_ctr.user.user1->client_name) {
+       if (!smb_io_relstr("portname", buffer, depth, &info->portname))
                return False;
-       }
-       q_u->user_ctr.user.user1->user_name   = TALLOC_P( mem_ctx, UNISTR2 );
-       if (!q_u->user_ctr.user.user1->user_name) {
+       if (!prs_uint32("attributes", ps, depth, &info->attributes))
+               return False;
+       if (!prs_uint32("device_not_selected_timeout", ps, depth, &info->device_not_selected_timeout))
+               return False;
+       if (!prs_uint32("transmission_retry_timeout", ps, depth, &info->transmission_retry_timeout))
                return False;
-       }
-       init_unistr2(q_u->user_ctr.user.user1->client_name, clientname, UNI_STR_TERMINATE);
-       init_unistr2(q_u->user_ctr.user.user1->user_name, user_name, UNI_STR_TERMINATE);
-
-       q_u->user_ctr.user.user1->size = q_u->user_ctr.user.user1->user_name->uni_str_len +
-                                  q_u->user_ctr.user.user1->client_name->uni_str_len + 2;
-       
        return True;
 }
-       
+
 /*******************************************************************
-create a SPOOL_PRINTER_INFO_2 stuct from a PRINTER_INFO_2 struct
-*******************************************************************/
+ Parse a PRINTER_INFO_6 structure.
+********************************************************************/  
 
-bool make_spoolss_printer_info_2(TALLOC_CTX *ctx, SPOOL_PRINTER_INFO_LEVEL_2 **spool_info2, 
-                               PRINTER_INFO_2 *info)
+bool smb_io_printer_info_6(const char *desc, RPC_BUFFER *buffer,
+                          PRINTER_INFO_6 *info, int depth)
 {
+       prs_struct *ps=&buffer->prs;
 
-       SPOOL_PRINTER_INFO_LEVEL_2 *inf;
-
-       /* allocate the necessary memory */
-       if (!(inf=TALLOC_P(ctx, SPOOL_PRINTER_INFO_LEVEL_2))) {
-               DEBUG(0,("make_spoolss_printer_info_2: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_2 sruct!\n"));
+       prs_debug(ps, depth, desc, "smb_io_printer_info_6");
+       depth++;        
+       
+       if (!prs_uint32("status", ps, depth, &info->status))
                return False;
-       }
-
-       inf->servername_ptr     = (info->servername.buffer!=NULL)?1:0;
-       inf->printername_ptr    = (info->printername.buffer!=NULL)?1:0;
-       inf->sharename_ptr      = (info->sharename.buffer!=NULL)?1:0;
-       inf->portname_ptr       = (info->portname.buffer!=NULL)?1:0;
-       inf->drivername_ptr     = (info->drivername.buffer!=NULL)?1:0;
-       inf->comment_ptr        = (info->comment.buffer!=NULL)?1:0;
-       inf->location_ptr       = (info->location.buffer!=NULL)?1:0;
-       inf->devmode_ptr        = (info->devmode!=NULL)?1:0;
-       inf->sepfile_ptr        = (info->sepfile.buffer!=NULL)?1:0;
-       inf->printprocessor_ptr = (info->printprocessor.buffer!=NULL)?1:0;
-       inf->datatype_ptr       = (info->datatype.buffer!=NULL)?1:0;
-       inf->parameters_ptr     = (info->parameters.buffer!=NULL)?1:0;
-       inf->secdesc_ptr        = (info->secdesc!=NULL)?1:0;
-       inf->attributes         = info->attributes;
-       inf->priority           = info->priority;
-       inf->default_priority   = info->defaultpriority;
-       inf->starttime          = info->starttime;
-       inf->untiltime          = info->untiltime;
-       inf->cjobs              = info->cjobs;
-       inf->averageppm = info->averageppm;
-       init_unistr2_from_unistr(inf, &inf->servername, &info->servername);
-       init_unistr2_from_unistr(inf, &inf->printername, &info->printername);
-       init_unistr2_from_unistr(inf, &inf->sharename, &info->sharename);
-       init_unistr2_from_unistr(inf, &inf->portname, &info->portname);
-       init_unistr2_from_unistr(inf, &inf->drivername, &info->drivername);
-       init_unistr2_from_unistr(inf, &inf->comment, &info->comment);
-       init_unistr2_from_unistr(inf, &inf->location, &info->location);
-       init_unistr2_from_unistr(inf, &inf->sepfile, &info->sepfile);
-       init_unistr2_from_unistr(inf, &inf->printprocessor, &info->printprocessor);
-       init_unistr2_from_unistr(inf, &inf->datatype, &info->datatype);
-       init_unistr2_from_unistr(inf, &inf->parameters, &info->parameters);
-       init_unistr2_from_unistr(inf, &inf->datatype, &info->datatype);
-
-       *spool_info2 = inf;
 
        return True;
 }
 
 /*******************************************************************
-create a SPOOL_PRINTER_INFO_3 struct from a PRINTER_INFO_3 struct
-*******************************************************************/
+ Parse a PRINTER_INFO_7 structure.
+********************************************************************/  
 
-bool make_spoolss_printer_info_3(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_3 **spool_info3, 
-                               PRINTER_INFO_3 *info)
+bool smb_io_printer_info_7(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_7 *info, int depth)
 {
+       prs_struct *ps=&buffer->prs;
 
-       SPOOL_PRINTER_INFO_LEVEL_3 *inf;
-
-       /* allocate the necessary memory */
-       if (!(inf=TALLOC_P(mem_ctx, SPOOL_PRINTER_INFO_LEVEL_3))) {
-               DEBUG(0,("make_spoolss_printer_info_3: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_3 sruct!\n"));
-               return False;
-       }
+       prs_debug(ps, depth, desc, "smb_io_printer_info_7");
+       depth++;        
        
-       inf->secdesc_ptr        = (info->secdesc!=NULL)?1:0;
-
-       *spool_info3 = inf;
-
+       buffer->struct_start=prs_offset(ps);
+       
+       if (!smb_io_relstr("guid", buffer, depth, &info->guid))
+               return False;
+       if (!prs_uint32("action", ps, depth, &info->action))
+               return False;
        return True;
 }
 
 /*******************************************************************
-create a SPOOL_PRINTER_INFO_7 struct from a PRINTER_INFO_7 struct
-*******************************************************************/
+ Parse a PORT_INFO_1 structure.
+********************************************************************/  
 
-bool make_spoolss_printer_info_7(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_7 **spool_info7, 
-                               PRINTER_INFO_7 *info)
+bool smb_io_port_info_1(const char *desc, RPC_BUFFER *buffer, PORT_INFO_1 *info, int depth)
 {
+       prs_struct *ps=&buffer->prs;
 
-       SPOOL_PRINTER_INFO_LEVEL_7 *inf;
-
-       /* allocate the necessary memory */
-       if (!(inf=TALLOC_P(mem_ctx, SPOOL_PRINTER_INFO_LEVEL_7))) {
-               DEBUG(0,("make_spoolss_printer_info_7: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_7 struct!\n"));
+       prs_debug(ps, depth, desc, "smb_io_port_info_1");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
+       
+       if (!smb_io_relstr("port_name", buffer, depth, &info->port_name))
                return False;
-       }
-
-       inf->guid_ptr = (info->guid.buffer!=NULL)?1:0;
-       inf->action = info->action;
-       init_unistr2_from_unistr(inf, &inf->guid, &info->guid);
-
-       *spool_info7 = inf;
 
        return True;
 }
 
 /*******************************************************************
* make a structure.
- ********************************************************************/
Parse a PORT_INFO_2 structure.
+********************************************************************/  
 
-bool make_spoolss_q_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u,
-                                  const POLICY_HND *handle,
-                                  const char *valuename, uint32 size)
+bool smb_io_port_info_2(const char *desc, RPC_BUFFER *buffer, PORT_INFO_2 *info, int depth)
 {
-        if (q_u == NULL) return False;
-
-        DEBUG(5,("make_spoolss_q_getprinterdata\n"));
+       prs_struct *ps=&buffer->prs;
 
-        q_u->handle = *handle;
-       init_unistr2(&q_u->valuename, valuename, UNI_STR_TERMINATE);
-        q_u->size = size;
+       prs_debug(ps, depth, desc, "smb_io_port_info_2");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
+       
+       if (!smb_io_relstr("port_name", buffer, depth, &info->port_name))
+               return False;
+       if (!smb_io_relstr("monitor_name", buffer, depth, &info->monitor_name))
+               return False;
+       if (!smb_io_relstr("description", buffer, depth, &info->description))
+               return False;
+       if (!prs_uint32("port_type", ps, depth, &info->port_type))
+               return False;
+       if (!prs_uint32("reserved", ps, depth, &info->reserved))
+               return False;
 
-        return True;
+       return True;
 }
 
 /*******************************************************************
- * read a structure.
- * called from spoolss_q_getprinterdata (srv_spoolss.c)
- ********************************************************************/
+ Parse a DRIVER_INFO_1 structure.
+********************************************************************/
 
-bool spoolss_io_q_getprinterdata(const char *desc, SPOOL_Q_GETPRINTERDATA *q_u, prs_struct *ps, int depth)
+bool smb_io_printer_driver_info_1(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_1 *info, int depth) 
 {
-       if (q_u == NULL)
-               return False;
+       prs_struct *ps=&buffer->prs;
 
-       prs_debug(ps, depth, desc, "spoolss_io_q_getprinterdata");
-       depth++;
+       prs_debug(ps, depth, desc, "smb_io_printer_driver_info_1");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
 
-       if (!prs_align(ps))
-               return False;
-       if (!smb_io_pol_hnd("printer handle",&q_u->handle,ps,depth))
-               return False;
-       if (!prs_align(ps))
-               return False;
-       if (!smb_io_unistr2("valuename", &q_u->valuename,True,ps,depth))
-               return False;
-       if (!prs_align(ps))
-               return False;
-       if (!prs_uint32("size", ps, depth, &q_u->size))
+       if (!smb_io_relstr("name", buffer, depth, &info->name))
                return False;
 
        return True;
 }
 
 /*******************************************************************
- * write a structure.
- * called from spoolss_r_getprinterdata (srv_spoolss.c)
- ********************************************************************/
+ Parse a DRIVER_INFO_2 structure.
+********************************************************************/
 
-bool spoolss_io_r_getprinterdata(const char *desc, SPOOL_R_GETPRINTERDATA *r_u, prs_struct *ps, int depth)
+bool smb_io_printer_driver_info_2(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_2 *info, int depth) 
 {
-       if (r_u == NULL)
-               return False;
+       prs_struct *ps=&buffer->prs;
 
-       prs_debug(ps, depth, desc, "spoolss_io_r_getprinterdata");
-       depth++;
+       prs_debug(ps, depth, desc, "smb_io_printer_driver_info_2");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
 
-       if (!prs_align(ps))
-               return False;
-       if (!prs_uint32("type", ps, depth, &r_u->type))
+       if (!prs_uint32("version", ps, depth, &info->version))
                return False;
-       if (!prs_uint32("size", ps, depth, &r_u->size))
+       if (!smb_io_relstr("name", buffer, depth, &info->name))
                return False;
-       
-       if (UNMARSHALLING(ps) && r_u->size) {
-               r_u->data = PRS_ALLOC_MEM(ps, unsigned char, r_u->size);
-               if(!r_u->data)
-                       return False;
-       }
-
-       if (!prs_uint8s( False, "data", ps, depth, r_u->data, r_u->size ))
+       if (!smb_io_relstr("architecture", buffer, depth, &info->architecture))
                return False;
-               
-       if (!prs_align(ps))
+       if (!smb_io_relstr("driverpath", buffer, depth, &info->driverpath))
                return False;
-       
-       if (!prs_uint32("needed", ps, depth, &r_u->needed))
+       if (!smb_io_relstr("datafile", buffer, depth, &info->datafile))
                return False;
-       if (!prs_werror("status", ps, depth, &r_u->status))
+       if (!smb_io_relstr("configfile", buffer, depth, &info->configfile))
                return False;
-               
+
        return True;
 }
 
 /*******************************************************************
- * read a structure.
- * called from spoolss_q_rffpcnex (srv_spoolss.c)
- ********************************************************************/
+ Parse a DRIVER_INFO_3 structure.
+********************************************************************/
 
-bool spoolss_io_q_rffpcnex(const char *desc, SPOOL_Q_RFFPCNEX *q_u, prs_struct *ps, int depth)
+bool smb_io_printer_driver_info_3(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_3 *info, int depth)
 {
-       prs_debug(ps, depth, desc, "spoolss_io_q_rffpcnex");
-       depth++;
+       prs_struct *ps=&buffer->prs;
 
-       if(!prs_align(ps))
-               return False;
+       prs_debug(ps, depth, desc, "smb_io_printer_driver_info_3");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
 
-       if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
+       if (!prs_uint32("version", ps, depth, &info->version))
                return False;
-       if(!prs_uint32("flags", ps, depth, &q_u->flags))
+       if (!smb_io_relstr("name", buffer, depth, &info->name))
                return False;
-       if(!prs_uint32("options", ps, depth, &q_u->options))
+       if (!smb_io_relstr("architecture", buffer, depth, &info->architecture))
                return False;
-       if(!prs_uint32("localmachine_ptr", ps, depth, &q_u->localmachine_ptr))
+       if (!smb_io_relstr("driverpath", buffer, depth, &info->driverpath))
                return False;
-       if(!smb_io_unistr2("localmachine", &q_u->localmachine, q_u->localmachine_ptr, ps, depth))
+       if (!smb_io_relstr("datafile", buffer, depth, &info->datafile))
                return False;
-
-       if(!prs_align(ps))
+       if (!smb_io_relstr("configfile", buffer, depth, &info->configfile))
                return False;
-               
-       if(!prs_uint32("printerlocal", ps, depth, &q_u->printerlocal))
+       if (!smb_io_relstr("helpfile", buffer, depth, &info->helpfile))
                return False;
 
-       if(!prs_uint32("option_ptr", ps, depth, &q_u->option_ptr))
+       if (!smb_io_relarraystr("dependentfiles", buffer, depth, &info->dependentfiles))
                return False;
-       
-       if (q_u->option_ptr!=0) {
-       
-               if (UNMARSHALLING(ps))
-                       if((q_u->option=PRS_ALLOC_MEM(ps,SPOOL_NOTIFY_OPTION,1)) == NULL)
-                               return False;
-       
-               if(!smb_io_notify_option("notify option", q_u->option, ps, depth))
-                       return False;
-       }
-       
-       return True;
-}
 
-/*******************************************************************
- * write a structure.
- * called from spoolss_r_rffpcnex (srv_spoolss.c)
- ********************************************************************/
-
-bool spoolss_io_r_rffpcnex(const char *desc, SPOOL_R_RFFPCNEX *r_u, prs_struct *ps, int depth)
-{
-       prs_debug(ps, depth, desc, "spoolss_io_r_rffpcnex");
-       depth++;
-
-       if(!prs_werror("status", ps, depth, &r_u->status))
+       if (!smb_io_relstr("monitorname", buffer, depth, &info->monitorname))
+               return False;
+       if (!smb_io_relstr("defaultdatatype", buffer, depth, &info->defaultdatatype))
                return False;
 
        return True;
 }
 
 /*******************************************************************
- * read a structure.
- * called from spoolss_q_rfnpcnex (srv_spoolss.c)
- ********************************************************************/
+ Parse a DRIVER_INFO_6 structure.
+********************************************************************/
 
-bool spoolss_io_q_rfnpcnex(const char *desc, SPOOL_Q_RFNPCNEX *q_u, prs_struct *ps, int depth)
+bool smb_io_printer_driver_info_6(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_6 *info, int depth)
 {
-       prs_debug(ps, depth, desc, "spoolss_io_q_rfnpcnex");
-       depth++;
+       prs_struct *ps=&buffer->prs;
 
-       if(!prs_align(ps))
+       prs_debug(ps, depth, desc, "smb_io_printer_driver_info_6");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
+
+       if (!prs_uint32("version", ps, depth, &info->version))
+               return False;
+       if (!smb_io_relstr("name", buffer, depth, &info->name))
+               return False;
+       if (!smb_io_relstr("architecture", buffer, depth, &info->architecture))
+               return False;
+       if (!smb_io_relstr("driverpath", buffer, depth, &info->driverpath))
+               return False;
+       if (!smb_io_relstr("datafile", buffer, depth, &info->datafile))
+               return False;
+       if (!smb_io_relstr("configfile", buffer, depth, &info->configfile))
+               return False;
+       if (!smb_io_relstr("helpfile", buffer, depth, &info->helpfile))
                return False;
 
-       if(!smb_io_pol_hnd("printer handle",&q_u->handle,ps,depth))
+       if (!smb_io_relarraystr("dependentfiles", buffer, depth, &info->dependentfiles))
                return False;
 
-       if(!prs_uint32("change", ps, depth, &q_u->change))
+       if (!smb_io_relstr("monitorname", buffer, depth, &info->monitorname))
                return False;
-       
-       if(!prs_uint32("option_ptr", ps, depth, &q_u->option_ptr))
+       if (!smb_io_relstr("defaultdatatype", buffer, depth, &info->defaultdatatype))
                return False;
-       
-       if (q_u->option_ptr!=0) {
-       
-               if (UNMARSHALLING(ps))
-                       if((q_u->option=PRS_ALLOC_MEM(ps,SPOOL_NOTIFY_OPTION,1)) == NULL)
-                               return False;
-       
-               if(!smb_io_notify_option("notify option", q_u->option, ps, depth))
-                       return False;
-       }
 
+       if (!smb_io_relarraystr("previousdrivernames", buffer, depth, &info->previousdrivernames))
+               return False;
+
+       if (!prs_uint64("date", ps, depth, &info->driver_date))
+               return False;
+
+       if (!prs_uint32("padding", ps, depth, &info->padding))
+               return False;
+
+       if (!prs_uint32("driver_version_low", ps, depth, &info->driver_version_low))
+               return False;
+
+       if (!prs_uint32("driver_version_high", ps, depth, &info->driver_version_high))
+               return False;
+
+       if (!smb_io_relstr("mfgname", buffer, depth, &info->mfgname))
+               return False;
+       if (!smb_io_relstr("oem_url", buffer, depth, &info->oem_url))
+               return False;
+       if (!smb_io_relstr("hardware_id", buffer, depth, &info->hardware_id))
+               return False;
+       if (!smb_io_relstr("provider", buffer, depth, &info->provider))
+               return False;
+       
        return True;
 }
 
 /*******************************************************************
- * write a structure.
- * called from spoolss_r_rfnpcnex (srv_spoolss.c)
- ********************************************************************/
+ Parse a JOB_INFO_1 structure.
+********************************************************************/  
 
-bool spoolss_io_r_rfnpcnex(const char *desc, SPOOL_R_RFNPCNEX *r_u, prs_struct *ps, int depth)
+bool smb_io_job_info_1(const char *desc, RPC_BUFFER *buffer, JOB_INFO_1 *info, int depth)
 {
-       prs_debug(ps, depth, desc, "spoolss_io_r_rfnpcnex");
-       depth++;
+       prs_struct *ps=&buffer->prs;
 
-       if(!prs_align(ps))
+       prs_debug(ps, depth, desc, "smb_io_job_info_1");
+       depth++;        
+       
+       buffer->struct_start=prs_offset(ps);
+
+       if (!prs_uint32("jobid", ps, depth, &info->jobid))
                return False;
-               
-       if (!prs_uint32("info_ptr", ps, depth, &r_u->info_ptr))
+       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
                return False;
-
-       if(!smb_io_notify_info("notify info", &r_u->info ,ps,depth))
+       if (!smb_io_relstr("machinename", buffer, depth, &info->machinename))
                return False;
-       
-       if(!prs_align(ps))
+       if (!smb_io_relstr("username", buffer, depth, &info->username))
                return False;
-       if(!prs_werror("status", ps, depth, &r_u->status))
+       if (!smb_io_relstr("document", buffer, depth, &info->document))
+               return False;
+       if (!smb_io_relstr("datatype", buffer, depth, &info->datatype))
+               return False;
+       if (!smb_io_relstr("text_status", buffer, depth, &info->text_status))
+               return False;
+       if (!prs_uint32("status", ps, depth, &info->status))
+               return False;
+       if (!prs_uint32("priority", ps, depth, &info->priority))
+               return False;
+       if (!prs_uint32("position", ps, depth, &info->position))
+               return False;
+       if (!prs_uint32("totalpages", ps, depth, &info->totalpages))
+               return False;
+       if (!prs_uint32("pagesprinted", ps, depth, &info->pagesprinted))
+               return False;
+       if (!spoolss_io_system_time("submitted", ps, depth, &info->submitted))
                return False;
 
        return True;
 }
 
 /*******************************************************************
- * return the length of a uint16 (obvious, but the code is clean)
- ********************************************************************/
+ Parse a JOB_INFO_2 structure.
+********************************************************************/  
 
-static uint32 size_of_uint16(uint16 *value)
-{
-       return (sizeof(*value));
-}
+bool smb_io_job_info_2(const char *desc, RPC_BUFFER *buffer, JOB_INFO_2 *info, int depth)
+{      
+       uint32 pipo=0;
+       prs_struct *ps=&buffer->prs;
+       
+       prs_debug(ps, depth, desc, "smb_io_job_info_2");
+       depth++;        
 
-/*******************************************************************
- * return the length of a uint32 (obvious, but the code is clean)
- ********************************************************************/
+       buffer->struct_start=prs_offset(ps);
+       
+       if (!prs_uint32("jobid",ps, depth, &info->jobid))
+               return False;
+       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
+               return False;
+       if (!smb_io_relstr("machinename", buffer, depth, &info->machinename))
+               return False;
+       if (!smb_io_relstr("username", buffer, depth, &info->username))
+               return False;
+       if (!smb_io_relstr("document", buffer, depth, &info->document))
+               return False;
+       if (!smb_io_relstr("notifyname", buffer, depth, &info->notifyname))
+               return False;
+       if (!smb_io_relstr("datatype", buffer, depth, &info->datatype))
+               return False;
 
-static uint32 size_of_uint32(uint32 *value)
-{
-       return (sizeof(*value));
-}
+       if (!smb_io_relstr("printprocessor", buffer, depth, &info->printprocessor))
+               return False;
+       if (!smb_io_relstr("parameters", buffer, depth, &info->parameters))
+               return False;
+       if (!smb_io_relstr("drivername", buffer, depth, &info->drivername))
+               return False;
+       if (!smb_io_reldevmode("devmode", buffer, depth, &info->devmode))
+               return False;
+       if (!smb_io_relstr("text_status", buffer, depth, &info->text_status))
+               return False;
 
-/*******************************************************************
* return the length of a NTTIME (obvious, but the code is clean)
- ********************************************************************/
+/*     SEC_DESC sec_desc;*/
      if (!prs_uint32("Hack! sec desc", ps, depth, &pipo))
+               return False;
 
-static uint32 size_of_nttime(NTTIME *value)
-{
-       return (sizeof(*value));
+       if (!prs_uint32("status",ps, depth, &info->status))
+               return False;
+       if (!prs_uint32("priority",ps, depth, &info->priority))
+               return False;
+       if (!prs_uint32("position",ps, depth, &info->position)) 
+               return False;
+       if (!prs_uint32("starttime",ps, depth, &info->starttime))
+               return False;
+       if (!prs_uint32("untiltime",ps, depth, &info->untiltime))       
+               return False;
+       if (!prs_uint32("totalpages",ps, depth, &info->totalpages))
+               return False;
+       if (!prs_uint32("size",ps, depth, &info->size))
+               return False;
+       if (!spoolss_io_system_time("submitted", ps, depth, &info->submitted) )
+               return False;
+       if (!prs_uint32("timeelapsed",ps, depth, &info->timeelapsed))
+               return False;
+       if (!prs_uint32("pagesprinted",ps, depth, &info->pagesprinted))
+               return False;
+
+       return True;
 }
 
 /*******************************************************************
- * return the length of a uint32 (obvious, but the code is clean)
- ********************************************************************/
+********************************************************************/  
 
-static uint32 size_of_device_mode(DEVICEMODE *devmode)
+bool smb_io_form_1(const char *desc, RPC_BUFFER *buffer, FORM_1 *info, int depth)
 {
-       if (devmode==NULL)
-               return (4);
-       else 
-               return (4+devmode->size+devmode->driverextra);
+       prs_struct *ps=&buffer->prs;
+       
+       prs_debug(ps, depth, desc, "smb_io_form_1");
+       depth++;
+               
+       buffer->struct_start=prs_offset(ps);
+       
+       if (!prs_uint32("flag", ps, depth, &info->flag))
+               return False;
+               
+       if (!smb_io_relstr("name", buffer, depth, &info->name))
+               return False;
+
+       if (!prs_uint32("width", ps, depth, &info->width))
+               return False;
+       if (!prs_uint32("length", ps, depth, &info->length))
+               return False;
+       if (!prs_uint32("left", ps, depth, &info->left))
+               return False;
+       if (!prs_uint32("top", ps, depth, &info->top))
+               return False;
+       if (!prs_uint32("right", ps, depth, &info->right))
+               return False;
+       if (!prs_uint32("bottom", ps, depth, &info->bottom))
+               return False;
+
+       return True;
 }
 
 /*******************************************************************
- * return the length of a uint32 (obvious, but the code is clean)
- ********************************************************************/
+ Parse a PORT_INFO_1 structure.
+********************************************************************/  
 
-static uint32 size_of_systemtime(SYSTEMTIME *systime)
+bool smb_io_port_1(const char *desc, RPC_BUFFER *buffer, PORT_INFO_1 *info, int depth)
 {
-       if (systime==NULL)
-               return (4);
-       else 
-               return (sizeof(SYSTEMTIME) +4);
+       prs_struct *ps=&buffer->prs;
+
+       prs_debug(ps, depth, desc, "smb_io_port_1");
+       depth++;
+
+       buffer->struct_start=prs_offset(ps);
+
+       if(!smb_io_relstr("port_name", buffer, depth, &info->port_name))
+               return False;
+
+       return True;
 }
 
 /*******************************************************************
- Parse a DEVMODE structure and its relative pointer.
-********************************************************************/
+ Parse a PORT_INFO_2 structure.
+********************************************************************/  
 
-static bool smb_io_reldevmode(const char *desc, RPC_BUFFER *buffer, int depth, DEVICEMODE **devmode)
+bool smb_io_port_2(const char *desc, RPC_BUFFER *buffer, PORT_INFO_2 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
-       prs_debug(ps, depth, desc, "smb_io_reldevmode");
+       prs_debug(ps, depth, desc, "smb_io_port_2");
        depth++;
 
-       if (MARSHALLING(ps)) {
-               uint32 struct_offset = prs_offset(ps);
-               uint32 relative_offset;
-               
-               if (*devmode == NULL) {
-                       relative_offset=0;
-                       if (!prs_uint32("offset", ps, depth, &relative_offset))
-                               return False;
-                       DEBUG(8, ("boing, the devmode was NULL\n"));
-                       
-                       return True;
-               }
-               
-               buffer->string_at_end -= ((*devmode)->size + (*devmode)->driverextra);
-
-               /* mz:  we have to align the device mode for VISTA */
-               if (buffer->string_at_end % 4) {
-                       buffer->string_at_end += 4 - (buffer->string_at_end % 4);
-               }
-
-               if(!prs_set_offset(ps, buffer->string_at_end))
-                       return False;
-               
-               /* write the DEVMODE */
-               if (!spoolss_io_devmode(desc, ps, depth, *devmode))
-                       return False;
-
-               if(!prs_set_offset(ps, struct_offset))
-                       return False;
-               
-               relative_offset=buffer->string_at_end - buffer->struct_start;
-               /* write its offset */
-               if (!prs_uint32("offset", ps, depth, &relative_offset))
-                       return False;
-       }
-       else {
-               uint32 old_offset;
-               
-               /* read the offset */
-               if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
-                       return False;
-               if (buffer->string_at_end == 0) {
-                       *devmode = NULL;
-                       return True;
-               }
-
-               old_offset = prs_offset(ps);
-               if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
-                       return False;
+       buffer->struct_start=prs_offset(ps);
 
-               /* read the string */
-               if((*devmode=PRS_ALLOC_MEM(ps,DEVICEMODE,1)) == NULL)
-                       return False;
-               if (!spoolss_io_devmode(desc, ps, depth, *devmode))
-                       return False;
+       if(!smb_io_relstr("port_name", buffer, depth, &info->port_name))
+               return False;
+       if(!smb_io_relstr("monitor_name", buffer, depth, &info->monitor_name))
+               return False;
+       if(!smb_io_relstr("description", buffer, depth, &info->description))
+               return False;
+       if(!prs_uint32("port_type", ps, depth, &info->port_type))
+               return False;
+       if(!prs_uint32("reserved", ps, depth, &info->reserved))
+               return False;
 
-               if(!prs_set_offset(ps, old_offset))
-                       return False;
-       }
        return True;
 }
 
 /*******************************************************************
- Parse a PRINTER_INFO_0 structure.
 ********************************************************************/  
 
-bool smb_io_printer_info_0(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_0 *info, int depth)
+bool smb_io_printprocessor_info_1(const char *desc, RPC_BUFFER *buffer, PRINTPROCESSOR_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
-       prs_debug(ps, depth, desc, "smb_io_printer_info_0");
+       prs_debug(ps, depth, desc, "smb_io_printprocessor_info_1");
        depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
 
-       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
-               return False;
-       if (!smb_io_relstr("servername", buffer, depth, &info->servername))
-               return False;
+       buffer->struct_start=prs_offset(ps);
        
-       if(!prs_uint32("cjobs", ps, depth, &info->cjobs))
-               return False;
-       if(!prs_uint32("total_jobs", ps, depth, &info->total_jobs))
-               return False;
-       if(!prs_uint32("total_bytes", ps, depth, &info->total_bytes))
+       if (smb_io_relstr("name", buffer, depth, &info->name))
                return False;
 
-       if(!prs_uint16("year", ps, depth, &info->year))
-               return False;
-       if(!prs_uint16("month", ps, depth, &info->month))
-               return False;
-       if(!prs_uint16("dayofweek", ps, depth, &info->dayofweek))
-               return False;
-       if(!prs_uint16("day", ps, depth, &info->day))
-               return False;
-       if(!prs_uint16("hour", ps, depth, &info->hour))
-               return False;
-       if(!prs_uint16("minute", ps, depth, &info->minute))
-               return False;
-       if(!prs_uint16("second", ps, depth, &info->second))
-               return False;
-       if(!prs_uint16("milliseconds", ps, depth, &info->milliseconds))
-               return False;
+       return True;
+}
 
-       if(!prs_uint32("global_counter", ps, depth, &info->global_counter))
-               return False;
-       if(!prs_uint32("total_pages", ps, depth, &info->total_pages))
-               return False;
+/*******************************************************************
+********************************************************************/  
 
-       if(!prs_uint16("major_version", ps, depth, &info->major_version))
-               return False;
-       if(!prs_uint16("build_version", ps, depth, &info->build_version))
-               return False;
-       if(!prs_uint32("unknown7", ps, depth, &info->unknown7))
-               return False;
-       if(!prs_uint32("unknown8", ps, depth, &info->unknown8))
-               return False;
-       if(!prs_uint32("unknown9", ps, depth, &info->unknown9))
-               return False;
-       if(!prs_uint32("session_counter", ps, depth, &info->session_counter))
-               return False;
-       if(!prs_uint32("unknown11", ps, depth, &info->unknown11))
-               return False;
-       if(!prs_uint32("printer_errors", ps, depth, &info->printer_errors))
-               return False;
-       if(!prs_uint32("unknown13", ps, depth, &info->unknown13))
-               return False;
-       if(!prs_uint32("unknown14", ps, depth, &info->unknown14))
-               return False;
-       if(!prs_uint32("unknown15", ps, depth, &info->unknown15))
-               return False;
-       if(!prs_uint32("unknown16", ps, depth, &info->unknown16))
-               return False;
-       if(!prs_uint32("change_id", ps, depth, &info->change_id))
-               return False;
-       if(!prs_uint32("unknown18", ps, depth, &info->unknown18))
-               return False;
-       if(!prs_uint32("status"   , ps, depth, &info->status))
-               return False;
-       if(!prs_uint32("unknown20", ps, depth, &info->unknown20))
-               return False;
-       if(!prs_uint32("c_setprinter", ps, depth, &info->c_setprinter))
-               return False;
-       if(!prs_uint16("unknown22", ps, depth, &info->unknown22))
-               return False;
-       if(!prs_uint16("unknown23", ps, depth, &info->unknown23))
-               return False;
-       if(!prs_uint16("unknown24", ps, depth, &info->unknown24))
-               return False;
-       if(!prs_uint16("unknown25", ps, depth, &info->unknown25))
-               return False;
-       if(!prs_uint16("unknown26", ps, depth, &info->unknown26))
-               return False;
-       if(!prs_uint16("unknown27", ps, depth, &info->unknown27))
-               return False;
-       if(!prs_uint16("unknown28", ps, depth, &info->unknown28))
-               return False;
-       if(!prs_uint16("unknown29", ps, depth, &info->unknown29))
+bool smb_io_printprocdatatype_info_1(const char *desc, RPC_BUFFER *buffer, PRINTPROCDATATYPE_1 *info, int depth)
+{
+       prs_struct *ps=&buffer->prs;
+
+       prs_debug(ps, depth, desc, "smb_io_printprocdatatype_info_1");
+       depth++;        
+
+       buffer->struct_start=prs_offset(ps);
+       
+       if (smb_io_relstr("name", buffer, depth, &info->name))
                return False;
 
        return True;
 }
 
 /*******************************************************************
- Parse a PRINTER_INFO_1 structure.
 ********************************************************************/  
 
-bool smb_io_printer_info_1(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_1 *info, int depth)
+bool smb_io_printmonitor_info_1(const char *desc, RPC_BUFFER *buffer, PRINTMONITOR_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
-       prs_debug(ps, depth, desc, "smb_io_printer_info_1");
+       prs_debug(ps, depth, desc, "smb_io_printmonitor_info_1");
        depth++;        
-       
+
        buffer->struct_start=prs_offset(ps);
 
-       if (!prs_uint32("flags", ps, depth, &info->flags))
-               return False;
-       if (!smb_io_relstr("description", buffer, depth, &info->description))
-               return False;
        if (!smb_io_relstr("name", buffer, depth, &info->name))
                return False;
-       if (!smb_io_relstr("comment", buffer, depth, &info->comment))
-               return False;   
 
        return True;
 }
 
 /*******************************************************************
- Parse a PRINTER_INFO_2 structure.
 ********************************************************************/  
 
-bool smb_io_printer_info_2(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_2 *info, int depth)
+bool smb_io_printmonitor_info_2(const char *desc, RPC_BUFFER *buffer, PRINTMONITOR_2 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
-       uint32 dm_offset, sd_offset, current_offset;
-       uint32 dummy_value = 0, has_secdesc = 0;
 
-       prs_debug(ps, depth, desc, "smb_io_printer_info_2");
+       prs_debug(ps, depth, desc, "smb_io_printmonitor_info_2");
        depth++;        
-       
+
        buffer->struct_start=prs_offset(ps);
-       
-       if (!smb_io_relstr("servername", buffer, depth, &info->servername))
-               return False;
-       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
-               return False;
-       if (!smb_io_relstr("sharename", buffer, depth, &info->sharename))
-               return False;
-       if (!smb_io_relstr("portname", buffer, depth, &info->portname))
-               return False;
-       if (!smb_io_relstr("drivername", buffer, depth, &info->drivername))
-               return False;
-       if (!smb_io_relstr("comment", buffer, depth, &info->comment))
-               return False;
-       if (!smb_io_relstr("location", buffer, depth, &info->location))
-               return False;
 
-       /* save current offset and wind forwared by a uint32 */
-       dm_offset = prs_offset(ps);
-       if (!prs_uint32("devmode", ps, depth, &dummy_value))
-               return False;
-       
-       if (!smb_io_relstr("sepfile", buffer, depth, &info->sepfile))
-               return False;
-       if (!smb_io_relstr("printprocessor", buffer, depth, &info->printprocessor))
+       if (!smb_io_relstr("name", buffer, depth, &info->name))
                return False;
-       if (!smb_io_relstr("datatype", buffer, depth, &info->datatype))
+       if (!smb_io_relstr("environment", buffer, depth, &info->environment))
                return False;
-       if (!smb_io_relstr("parameters", buffer, depth, &info->parameters))
+       if (!smb_io_relstr("dll_name", buffer, depth, &info->dll_name))
                return False;
 
-       /* save current offset for the sec_desc */
-       sd_offset = prs_offset(ps);
-       if (!prs_uint32("sec_desc", ps, depth, &has_secdesc))
-               return False;
+       return True;
+}
 
+/*******************************************************************
+return the size required by a struct in the stream
+********************************************************************/  
+
+uint32 spoolss_size_printer_info_0(PRINTER_INFO_0 *info)
+{
+       int size=0;
        
-       /* save current location so we can pick back up here */
-       current_offset = prs_offset(ps);
-       
-       /* parse the devmode */
-       if (!prs_set_offset(ps, dm_offset))
-               return False;
-       if (!smb_io_reldevmode("devmode", buffer, depth, &info->devmode))
-               return False;
-       
-       /* parse the sec_desc */
-       if (info->secdesc) {
-               if (!prs_set_offset(ps, sd_offset))
-                       return False;
-               if (!smb_io_relsecdesc("secdesc", buffer, depth, &info->secdesc))
-                       return False;
-       }
+       size+=size_of_relative_string( &info->printername );
+       size+=size_of_relative_string( &info->servername );
 
-       /* pick up where we left off */
-       if (!prs_set_offset(ps, current_offset))
-               return False;
+       size+=size_of_uint32( &info->cjobs);
+       size+=size_of_uint32( &info->total_jobs);
+       size+=size_of_uint32( &info->total_bytes);
 
-       if (!prs_uint32("attributes", ps, depth, &info->attributes))
-               return False;
-       if (!prs_uint32("priority", ps, depth, &info->priority))
-               return False;
-       if (!prs_uint32("defpriority", ps, depth, &info->defaultpriority))
-               return False;
-       if (!prs_uint32("starttime", ps, depth, &info->starttime))
-               return False;
-       if (!prs_uint32("untiltime", ps, depth, &info->untiltime))
-               return False;
-       if (!prs_uint32("status", ps, depth, &info->status))
-               return False;
-       if (!prs_uint32("jobs", ps, depth, &info->cjobs))
-               return False;
-       if (!prs_uint32("averageppm", ps, depth, &info->averageppm))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a PRINTER_INFO_3 structure.
-********************************************************************/  
-
-bool smb_io_printer_info_3(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_3 *info, int depth)
-{
-       uint32 offset = 0;
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printer_info_3");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-       
-       if (MARSHALLING(ps)) {
-               /* Ensure the SD is 8 byte aligned in the buffer. */
-               uint32 start = prs_offset(ps); /* Remember the start position. */
-               uint32 off_val = 0;
-
-               /* Write a dummy value. */
-               if (!prs_uint32("offset", ps, depth, &off_val))
-                       return False;
-
-               /* 8 byte align. */
-               if (!prs_align_uint64(ps))
-                       return False;
-
-               /* Remember where we must seek back to write the SD. */
-               offset = prs_offset(ps);
-
-               /* Calculate the real offset for the SD. */
-
-               off_val = offset - start;
-
-               /* Seek back to where we store the SD offset & store. */
-               prs_set_offset(ps, start);
-               if (!prs_uint32("offset", ps, depth, &off_val))
-                       return False;
-
-               /* Return to after the 8 byte align. */
-               prs_set_offset(ps, offset);
-
-       } else {
-               if (!prs_uint32("offset", ps, depth, &offset))
-                       return False;
-               /* Seek within the buffer. */
-               if (!prs_set_offset(ps, offset))
-                       return False;
-       }
-       if (!sec_io_desc("sec_desc", &info->secdesc, ps, depth))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a PRINTER_INFO_4 structure.
-********************************************************************/  
-
-bool smb_io_printer_info_4(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_4 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printer_info_4");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-       
-       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
-               return False;
-       if (!smb_io_relstr("servername", buffer, depth, &info->servername))
-               return False;
-       if (!prs_uint32("attributes", ps, depth, &info->attributes))
-               return False;
-       return True;
-}
-
-/*******************************************************************
- Parse a PRINTER_INFO_5 structure.
-********************************************************************/  
-
-bool smb_io_printer_info_5(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_5 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printer_info_5");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-       
-       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
-               return False;
-       if (!smb_io_relstr("portname", buffer, depth, &info->portname))
-               return False;
-       if (!prs_uint32("attributes", ps, depth, &info->attributes))
-               return False;
-       if (!prs_uint32("device_not_selected_timeout", ps, depth, &info->device_not_selected_timeout))
-               return False;
-       if (!prs_uint32("transmission_retry_timeout", ps, depth, &info->transmission_retry_timeout))
-               return False;
-       return True;
-}
-
-/*******************************************************************
- Parse a PRINTER_INFO_6 structure.
-********************************************************************/  
-
-bool smb_io_printer_info_6(const char *desc, RPC_BUFFER *buffer,
-                          PRINTER_INFO_6 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printer_info_6");
-       depth++;        
-       
-       if (!prs_uint32("status", ps, depth, &info->status))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a PRINTER_INFO_7 structure.
-********************************************************************/  
-
-bool smb_io_printer_info_7(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_7 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printer_info_7");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-       
-       if (!smb_io_relstr("guid", buffer, depth, &info->guid))
-               return False;
-       if (!prs_uint32("action", ps, depth, &info->action))
-               return False;
-       return True;
-}
-
-/*******************************************************************
- Parse a PORT_INFO_1 structure.
-********************************************************************/  
-
-bool smb_io_port_info_1(const char *desc, RPC_BUFFER *buffer, PORT_INFO_1 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_port_info_1");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-       
-       if (!smb_io_relstr("port_name", buffer, depth, &info->port_name))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a PORT_INFO_2 structure.
-********************************************************************/  
-
-bool smb_io_port_info_2(const char *desc, RPC_BUFFER *buffer, PORT_INFO_2 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_port_info_2");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-       
-       if (!smb_io_relstr("port_name", buffer, depth, &info->port_name))
-               return False;
-       if (!smb_io_relstr("monitor_name", buffer, depth, &info->monitor_name))
-               return False;
-       if (!smb_io_relstr("description", buffer, depth, &info->description))
-               return False;
-       if (!prs_uint32("port_type", ps, depth, &info->port_type))
-               return False;
-       if (!prs_uint32("reserved", ps, depth, &info->reserved))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a DRIVER_INFO_1 structure.
-********************************************************************/
-
-bool smb_io_printer_driver_info_1(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_1 *info, int depth) 
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printer_driver_info_1");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-
-       if (!smb_io_relstr("name", buffer, depth, &info->name))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a DRIVER_INFO_2 structure.
-********************************************************************/
-
-bool smb_io_printer_driver_info_2(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_2 *info, int depth) 
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printer_driver_info_2");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-
-       if (!prs_uint32("version", ps, depth, &info->version))
-               return False;
-       if (!smb_io_relstr("name", buffer, depth, &info->name))
-               return False;
-       if (!smb_io_relstr("architecture", buffer, depth, &info->architecture))
-               return False;
-       if (!smb_io_relstr("driverpath", buffer, depth, &info->driverpath))
-               return False;
-       if (!smb_io_relstr("datafile", buffer, depth, &info->datafile))
-               return False;
-       if (!smb_io_relstr("configfile", buffer, depth, &info->configfile))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a DRIVER_INFO_3 structure.
-********************************************************************/
-
-bool smb_io_printer_driver_info_3(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_3 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printer_driver_info_3");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-
-       if (!prs_uint32("version", ps, depth, &info->version))
-               return False;
-       if (!smb_io_relstr("name", buffer, depth, &info->name))
-               return False;
-       if (!smb_io_relstr("architecture", buffer, depth, &info->architecture))
-               return False;
-       if (!smb_io_relstr("driverpath", buffer, depth, &info->driverpath))
-               return False;
-       if (!smb_io_relstr("datafile", buffer, depth, &info->datafile))
-               return False;
-       if (!smb_io_relstr("configfile", buffer, depth, &info->configfile))
-               return False;
-       if (!smb_io_relstr("helpfile", buffer, depth, &info->helpfile))
-               return False;
-
-       if (!smb_io_relarraystr("dependentfiles", buffer, depth, &info->dependentfiles))
-               return False;
-
-       if (!smb_io_relstr("monitorname", buffer, depth, &info->monitorname))
-               return False;
-       if (!smb_io_relstr("defaultdatatype", buffer, depth, &info->defaultdatatype))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a DRIVER_INFO_6 structure.
-********************************************************************/
-
-bool smb_io_printer_driver_info_6(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_6 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printer_driver_info_6");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-
-       if (!prs_uint32("version", ps, depth, &info->version))
-               return False;
-       if (!smb_io_relstr("name", buffer, depth, &info->name))
-               return False;
-       if (!smb_io_relstr("architecture", buffer, depth, &info->architecture))
-               return False;
-       if (!smb_io_relstr("driverpath", buffer, depth, &info->driverpath))
-               return False;
-       if (!smb_io_relstr("datafile", buffer, depth, &info->datafile))
-               return False;
-       if (!smb_io_relstr("configfile", buffer, depth, &info->configfile))
-               return False;
-       if (!smb_io_relstr("helpfile", buffer, depth, &info->helpfile))
-               return False;
-
-       if (!smb_io_relarraystr("dependentfiles", buffer, depth, &info->dependentfiles))
-               return False;
-
-       if (!smb_io_relstr("monitorname", buffer, depth, &info->monitorname))
-               return False;
-       if (!smb_io_relstr("defaultdatatype", buffer, depth, &info->defaultdatatype))
-               return False;
-
-       if (!smb_io_relarraystr("previousdrivernames", buffer, depth, &info->previousdrivernames))
-               return False;
-
-       if (!prs_uint64("date", ps, depth, &info->driver_date))
-               return False;
-
-       if (!prs_uint32("padding", ps, depth, &info->padding))
-               return False;
-
-       if (!prs_uint32("driver_version_low", ps, depth, &info->driver_version_low))
-               return False;
-
-       if (!prs_uint32("driver_version_high", ps, depth, &info->driver_version_high))
-               return False;
-
-       if (!smb_io_relstr("mfgname", buffer, depth, &info->mfgname))
-               return False;
-       if (!smb_io_relstr("oem_url", buffer, depth, &info->oem_url))
-               return False;
-       if (!smb_io_relstr("hardware_id", buffer, depth, &info->hardware_id))
-               return False;
-       if (!smb_io_relstr("provider", buffer, depth, &info->provider))
-               return False;
-       
-       return True;
-}
-
-/*******************************************************************
- Parse a JOB_INFO_1 structure.
-********************************************************************/  
-
-bool smb_io_job_info_1(const char *desc, RPC_BUFFER *buffer, JOB_INFO_1 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_job_info_1");
-       depth++;        
-       
-       buffer->struct_start=prs_offset(ps);
-
-       if (!prs_uint32("jobid", ps, depth, &info->jobid))
-               return False;
-       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
-               return False;
-       if (!smb_io_relstr("machinename", buffer, depth, &info->machinename))
-               return False;
-       if (!smb_io_relstr("username", buffer, depth, &info->username))
-               return False;
-       if (!smb_io_relstr("document", buffer, depth, &info->document))
-               return False;
-       if (!smb_io_relstr("datatype", buffer, depth, &info->datatype))
-               return False;
-       if (!smb_io_relstr("text_status", buffer, depth, &info->text_status))
-               return False;
-       if (!prs_uint32("status", ps, depth, &info->status))
-               return False;
-       if (!prs_uint32("priority", ps, depth, &info->priority))
-               return False;
-       if (!prs_uint32("position", ps, depth, &info->position))
-               return False;
-       if (!prs_uint32("totalpages", ps, depth, &info->totalpages))
-               return False;
-       if (!prs_uint32("pagesprinted", ps, depth, &info->pagesprinted))
-               return False;
-       if (!spoolss_io_system_time("submitted", ps, depth, &info->submitted))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a JOB_INFO_2 structure.
-********************************************************************/  
-
-bool smb_io_job_info_2(const char *desc, RPC_BUFFER *buffer, JOB_INFO_2 *info, int depth)
-{      
-       uint32 pipo=0;
-       prs_struct *ps=&buffer->prs;
-       
-       prs_debug(ps, depth, desc, "smb_io_job_info_2");
-       depth++;        
-
-       buffer->struct_start=prs_offset(ps);
-       
-       if (!prs_uint32("jobid",ps, depth, &info->jobid))
-               return False;
-       if (!smb_io_relstr("printername", buffer, depth, &info->printername))
-               return False;
-       if (!smb_io_relstr("machinename", buffer, depth, &info->machinename))
-               return False;
-       if (!smb_io_relstr("username", buffer, depth, &info->username))
-               return False;
-       if (!smb_io_relstr("document", buffer, depth, &info->document))
-               return False;
-       if (!smb_io_relstr("notifyname", buffer, depth, &info->notifyname))
-               return False;
-       if (!smb_io_relstr("datatype", buffer, depth, &info->datatype))
-               return False;
-
-       if (!smb_io_relstr("printprocessor", buffer, depth, &info->printprocessor))
-               return False;
-       if (!smb_io_relstr("parameters", buffer, depth, &info->parameters))
-               return False;
-       if (!smb_io_relstr("drivername", buffer, depth, &info->drivername))
-               return False;
-       if (!smb_io_reldevmode("devmode", buffer, depth, &info->devmode))
-               return False;
-       if (!smb_io_relstr("text_status", buffer, depth, &info->text_status))
-               return False;
-
-/*     SEC_DESC sec_desc;*/
-       if (!prs_uint32("Hack! sec desc", ps, depth, &pipo))
-               return False;
-
-       if (!prs_uint32("status",ps, depth, &info->status))
-               return False;
-       if (!prs_uint32("priority",ps, depth, &info->priority))
-               return False;
-       if (!prs_uint32("position",ps, depth, &info->position)) 
-               return False;
-       if (!prs_uint32("starttime",ps, depth, &info->starttime))
-               return False;
-       if (!prs_uint32("untiltime",ps, depth, &info->untiltime))       
-               return False;
-       if (!prs_uint32("totalpages",ps, depth, &info->totalpages))
-               return False;
-       if (!prs_uint32("size",ps, depth, &info->size))
-               return False;
-       if (!spoolss_io_system_time("submitted", ps, depth, &info->submitted) )
-               return False;
-       if (!prs_uint32("timeelapsed",ps, depth, &info->timeelapsed))
-               return False;
-       if (!prs_uint32("pagesprinted",ps, depth, &info->pagesprinted))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
-********************************************************************/  
-
-bool smb_io_form_1(const char *desc, RPC_BUFFER *buffer, FORM_1 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-       
-       prs_debug(ps, depth, desc, "smb_io_form_1");
-       depth++;
-               
-       buffer->struct_start=prs_offset(ps);
-       
-       if (!prs_uint32("flag", ps, depth, &info->flag))
-               return False;
-               
-       if (!smb_io_relstr("name", buffer, depth, &info->name))
-               return False;
-
-       if (!prs_uint32("width", ps, depth, &info->width))
-               return False;
-       if (!prs_uint32("length", ps, depth, &info->length))
-               return False;
-       if (!prs_uint32("left", ps, depth, &info->left))
-               return False;
-       if (!prs_uint32("top", ps, depth, &info->top))
-               return False;
-       if (!prs_uint32("right", ps, depth, &info->right))
-               return False;
-       if (!prs_uint32("bottom", ps, depth, &info->bottom))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a PORT_INFO_1 structure.
-********************************************************************/  
-
-bool smb_io_port_1(const char *desc, RPC_BUFFER *buffer, PORT_INFO_1 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_port_1");
-       depth++;
-
-       buffer->struct_start=prs_offset(ps);
-
-       if(!smb_io_relstr("port_name", buffer, depth, &info->port_name))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a PORT_INFO_2 structure.
-********************************************************************/  
-
-bool smb_io_port_2(const char *desc, RPC_BUFFER *buffer, PORT_INFO_2 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_port_2");
-       depth++;
-
-       buffer->struct_start=prs_offset(ps);
-
-       if(!smb_io_relstr("port_name", buffer, depth, &info->port_name))
-               return False;
-       if(!smb_io_relstr("monitor_name", buffer, depth, &info->monitor_name))
-               return False;
-       if(!smb_io_relstr("description", buffer, depth, &info->description))
-               return False;
-       if(!prs_uint32("port_type", ps, depth, &info->port_type))
-               return False;
-       if(!prs_uint32("reserved", ps, depth, &info->reserved))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
-********************************************************************/  
-
-bool smb_io_printprocessor_info_1(const char *desc, RPC_BUFFER *buffer, PRINTPROCESSOR_1 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printprocessor_info_1");
-       depth++;        
-
-       buffer->struct_start=prs_offset(ps);
-       
-       if (smb_io_relstr("name", buffer, depth, &info->name))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
-********************************************************************/  
-
-bool smb_io_printprocdatatype_info_1(const char *desc, RPC_BUFFER *buffer, PRINTPROCDATATYPE_1 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printprocdatatype_info_1");
-       depth++;        
-
-       buffer->struct_start=prs_offset(ps);
-       
-       if (smb_io_relstr("name", buffer, depth, &info->name))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
-********************************************************************/  
-
-bool smb_io_printmonitor_info_1(const char *desc, RPC_BUFFER *buffer, PRINTMONITOR_1 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printmonitor_info_1");
-       depth++;        
-
-       buffer->struct_start=prs_offset(ps);
-
-       if (!smb_io_relstr("name", buffer, depth, &info->name))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
-********************************************************************/  
-
-bool smb_io_printmonitor_info_2(const char *desc, RPC_BUFFER *buffer, PRINTMONITOR_2 *info, int depth)
-{
-       prs_struct *ps=&buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_printmonitor_info_2");
-       depth++;        
-
-       buffer->struct_start=prs_offset(ps);
-
-       if (!smb_io_relstr("name", buffer, depth, &info->name))
-               return False;
-       if (!smb_io_relstr("environment", buffer, depth, &info->environment))
-               return False;
-       if (!smb_io_relstr("dll_name", buffer, depth, &info->dll_name))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/  
-
-uint32 spoolss_size_printer_info_0(PRINTER_INFO_0 *info)
-{
-       int size=0;
-       
-       size+=size_of_relative_string( &info->printername );
-       size+=size_of_relative_string( &info->servername );
-
-       size+=size_of_uint32( &info->cjobs);
-       size+=size_of_uint32( &info->total_jobs);
-       size+=size_of_uint32( &info->total_bytes);
-
-       size+=size_of_uint16( &info->year);
-       size+=size_of_uint16( &info->month);
-       size+=size_of_uint16( &info->dayofweek);
-       size+=size_of_uint16( &info->day);
-       size+=size_of_uint16( &info->hour);
-       size+=size_of_uint16( &info->minute);
-       size+=size_of_uint16( &info->second);
-       size+=size_of_uint16( &info->milliseconds);
-
-       size+=size_of_uint32( &info->global_counter);
-       size+=size_of_uint32( &info->total_pages);
-
-       size+=size_of_uint16( &info->major_version);
-       size+=size_of_uint16( &info->build_version);
-
-       size+=size_of_uint32( &info->unknown7);
-       size+=size_of_uint32( &info->unknown8);
-       size+=size_of_uint32( &info->unknown9);
-       size+=size_of_uint32( &info->session_counter);
-       size+=size_of_uint32( &info->unknown11);
-       size+=size_of_uint32( &info->printer_errors);
-       size+=size_of_uint32( &info->unknown13);
-       size+=size_of_uint32( &info->unknown14);
-       size+=size_of_uint32( &info->unknown15);
-       size+=size_of_uint32( &info->unknown16);
-       size+=size_of_uint32( &info->change_id);
-       size+=size_of_uint32( &info->unknown18);
-       size+=size_of_uint32( &info->status);
-       size+=size_of_uint32( &info->unknown20);
-       size+=size_of_uint32( &info->c_setprinter);
-       
-       size+=size_of_uint16( &info->unknown22);
-       size+=size_of_uint16( &info->unknown23);
-       size+=size_of_uint16( &info->unknown24);
-       size+=size_of_uint16( &info->unknown25);
-       size+=size_of_uint16( &info->unknown26);
-       size+=size_of_uint16( &info->unknown27);
-       size+=size_of_uint16( &info->unknown28);
-       size+=size_of_uint16( &info->unknown29);
-       
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/  
-
-uint32 spoolss_size_printer_info_1(PRINTER_INFO_1 *info)
-{
-       int size=0;
-               
-       size+=size_of_uint32( &info->flags );   
-       size+=size_of_relative_string( &info->description );
-       size+=size_of_relative_string( &info->name );
-       size+=size_of_relative_string( &info->comment );
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_printer_info_2(PRINTER_INFO_2 *info)
-{
-       uint32 size=0;
-               
-       size += 4;
-       
-       size += ndr_size_security_descriptor( info->secdesc, NULL, 0 );
-
-       size+=size_of_device_mode( info->devmode );
-       
-       size+=size_of_relative_string( &info->servername );
-       size+=size_of_relative_string( &info->printername );
-       size+=size_of_relative_string( &info->sharename );
-       size+=size_of_relative_string( &info->portname );
-       size+=size_of_relative_string( &info->drivername );
-       size+=size_of_relative_string( &info->comment );
-       size+=size_of_relative_string( &info->location );
-       
-       size+=size_of_relative_string( &info->sepfile );
-       size+=size_of_relative_string( &info->printprocessor );
-       size+=size_of_relative_string( &info->datatype );
-       size+=size_of_relative_string( &info->parameters );
-
-       size+=size_of_uint32( &info->attributes );
-       size+=size_of_uint32( &info->priority );
-       size+=size_of_uint32( &info->defaultpriority );
-       size+=size_of_uint32( &info->starttime );
-       size+=size_of_uint32( &info->untiltime );
-       size+=size_of_uint32( &info->status );
-       size+=size_of_uint32( &info->cjobs );
-       size+=size_of_uint32( &info->averageppm );      
-               
-       /* 
-        * add any adjustments for alignment.  This is
-        * not optimal since we could be calling this
-        * function from a loop (e.g. enumprinters), but 
-        * it is easier to maintain the calculation here and
-        * not place the burden on the caller to remember.   --jerry
-        */
-       if ((size % 4) != 0)
-               size += 4 - (size % 4);
-       
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_printer_info_4(PRINTER_INFO_4 *info)
-{
-       uint32 size=0;
-               
-       size+=size_of_relative_string( &info->printername );
-       size+=size_of_relative_string( &info->servername );
-
-       size+=size_of_uint32( &info->attributes );
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_printer_info_5(PRINTER_INFO_5 *info)
-{
-       uint32 size=0;
-               
-       size+=size_of_relative_string( &info->printername );
-       size+=size_of_relative_string( &info->portname );
-
-       size+=size_of_uint32( &info->attributes );
-       size+=size_of_uint32( &info->device_not_selected_timeout );
-       size+=size_of_uint32( &info->transmission_retry_timeout );
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_printer_info_6(PRINTER_INFO_6 *info)
-{
-       return sizeof(uint32);
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_printer_info_3(PRINTER_INFO_3 *info)
-{
-       /* The 8 is for the self relative pointer - 8 byte aligned.. */
-       return 8 + (uint32)ndr_size_security_descriptor( info->secdesc, NULL, 0 );
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_printer_info_7(PRINTER_INFO_7 *info)
-{
-       uint32 size=0;
-               
-       size+=size_of_relative_string( &info->guid );
-       size+=size_of_uint32( &info->action );
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_printer_driver_info_1(DRIVER_INFO_1 *info)
-{
-       int size=0;
-       size+=size_of_relative_string( &info->name );
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_printer_driver_info_2(DRIVER_INFO_2 *info)
-{
-       int size=0;
-       size+=size_of_uint32( &info->version ); 
-       size+=size_of_relative_string( &info->name );
-       size+=size_of_relative_string( &info->architecture );
-       size+=size_of_relative_string( &info->driverpath );
-       size+=size_of_relative_string( &info->datafile );
-       size+=size_of_relative_string( &info->configfile );
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a string array.
-********************************************************************/
-
-uint32 spoolss_size_string_array(uint16 *string)
-{
-       uint32 i = 0;
-
-       if (string) {
-               for (i=0; (string[i]!=0x0000) || (string[i+1]!=0x0000); i++);
-       }
-       i=i+2; /* to count all chars including the leading zero */
-       i=2*i; /* because we need the value in bytes */
-       i=i+4; /* the offset pointer size */
-
-       return i;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_printer_driver_info_3(DRIVER_INFO_3 *info)
-{
-       int size=0;
-
-       size+=size_of_uint32( &info->version ); 
-       size+=size_of_relative_string( &info->name );
-       size+=size_of_relative_string( &info->architecture );
-       size+=size_of_relative_string( &info->driverpath );
-       size+=size_of_relative_string( &info->datafile );
-       size+=size_of_relative_string( &info->configfile );
-       size+=size_of_relative_string( &info->helpfile );
-       size+=size_of_relative_string( &info->monitorname );
-       size+=size_of_relative_string( &info->defaultdatatype );
-       
-       size+=spoolss_size_string_array(info->dependentfiles);
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_printer_driver_info_6(DRIVER_INFO_6 *info)
-{
-       uint32 size=0;
-
-       size+=size_of_uint32( &info->version ); 
-       size+=size_of_relative_string( &info->name );
-       size+=size_of_relative_string( &info->architecture );
-       size+=size_of_relative_string( &info->driverpath );
-       size+=size_of_relative_string( &info->datafile );
-       size+=size_of_relative_string( &info->configfile );
-       size+=size_of_relative_string( &info->helpfile );
-
-       size+=spoolss_size_string_array(info->dependentfiles);
-
-       size+=size_of_relative_string( &info->monitorname );
-       size+=size_of_relative_string( &info->defaultdatatype );
-       
-       size+=spoolss_size_string_array(info->previousdrivernames);
-
-       size+=size_of_nttime(&info->driver_date);
-       size+=size_of_uint32( &info->padding ); 
-       size+=size_of_uint32( &info->driver_version_low );      
-       size+=size_of_uint32( &info->driver_version_high );     
-       size+=size_of_relative_string( &info->mfgname );
-       size+=size_of_relative_string( &info->oem_url );
-       size+=size_of_relative_string( &info->hardware_id );
-       size+=size_of_relative_string( &info->provider );
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/  
-
-uint32 spoolss_size_job_info_1(JOB_INFO_1 *info)
-{
-       int size=0;
-       size+=size_of_uint32( &info->jobid );
-       size+=size_of_relative_string( &info->printername );
-       size+=size_of_relative_string( &info->machinename );
-       size+=size_of_relative_string( &info->username );
-       size+=size_of_relative_string( &info->document );
-       size+=size_of_relative_string( &info->datatype );
-       size+=size_of_relative_string( &info->text_status );
-       size+=size_of_uint32( &info->status );
-       size+=size_of_uint32( &info->priority );
-       size+=size_of_uint32( &info->position );
-       size+=size_of_uint32( &info->totalpages );
-       size+=size_of_uint32( &info->pagesprinted );
-       size+=size_of_systemtime( &info->submitted );
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/  
-
-uint32 spoolss_size_job_info_2(JOB_INFO_2 *info)
-{
-       int size=0;
-
-       size+=4; /* size of sec desc ptr */
-
-       size+=size_of_uint32( &info->jobid );
-       size+=size_of_relative_string( &info->printername );
-       size+=size_of_relative_string( &info->machinename );
-       size+=size_of_relative_string( &info->username );
-       size+=size_of_relative_string( &info->document );
-       size+=size_of_relative_string( &info->notifyname );
-       size+=size_of_relative_string( &info->datatype );
-       size+=size_of_relative_string( &info->printprocessor );
-       size+=size_of_relative_string( &info->parameters );
-       size+=size_of_relative_string( &info->drivername );
-       size+=size_of_device_mode( info->devmode );
-       size+=size_of_relative_string( &info->text_status );
-/*     SEC_DESC sec_desc;*/
-       size+=size_of_uint32( &info->status );
-       size+=size_of_uint32( &info->priority );
-       size+=size_of_uint32( &info->position );
-       size+=size_of_uint32( &info->starttime );
-       size+=size_of_uint32( &info->untiltime );
-       size+=size_of_uint32( &info->totalpages );
-       size+=size_of_uint32( &info->size );
-       size+=size_of_systemtime( &info->submitted );
-       size+=size_of_uint32( &info->timeelapsed );
-       size+=size_of_uint32( &info->pagesprinted );
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/
-
-uint32 spoolss_size_form_1(FORM_1 *info)
-{
-       int size=0;
-
-       size+=size_of_uint32( &info->flag );
-       size+=size_of_relative_string( &info->name );
-       size+=size_of_uint32( &info->width );
-       size+=size_of_uint32( &info->length );
-       size+=size_of_uint32( &info->left );
-       size+=size_of_uint32( &info->top );
-       size+=size_of_uint32( &info->right );
-       size+=size_of_uint32( &info->bottom );
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/  
-
-uint32 spoolss_size_port_info_1(PORT_INFO_1 *info)
-{
-       int size=0;
-
-       size+=size_of_relative_string( &info->port_name );
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/  
-
-uint32 spoolss_size_port_info_2(PORT_INFO_2 *info)
-{
-       int size=0;
-
-       size+=size_of_relative_string( &info->port_name );
-       size+=size_of_relative_string( &info->monitor_name );
-       size+=size_of_relative_string( &info->description );
-
-       size+=size_of_uint32( &info->port_type );
-       size+=size_of_uint32( &info->reserved );
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/  
-
-uint32 spoolss_size_printprocessor_info_1(PRINTPROCESSOR_1 *info)
-{
-       int size=0;
-       size+=size_of_relative_string( &info->name );
-
-       return size;
-}
-
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/  
+       size+=size_of_uint16( &info->year);
+       size+=size_of_uint16( &info->month);
+       size+=size_of_uint16( &info->dayofweek);
+       size+=size_of_uint16( &info->day);
+       size+=size_of_uint16( &info->hour);
+       size+=size_of_uint16( &info->minute);
+       size+=size_of_uint16( &info->second);
+       size+=size_of_uint16( &info->milliseconds);
 
-uint32 spoolss_size_printprocdatatype_info_1(PRINTPROCDATATYPE_1 *info)
-{
-       int size=0;
-       size+=size_of_relative_string( &info->name );
+       size+=size_of_uint32( &info->global_counter);
+       size+=size_of_uint32( &info->total_pages);
 
-       return size;
-}
+       size+=size_of_uint16( &info->major_version);
+       size+=size_of_uint16( &info->build_version);
 
-/*******************************************************************
-return the size required by a struct in the stream
-********************************************************************/  
-uint32 spoolss_size_printer_enum_values(PRINTER_ENUM_VALUES *p)
-{
-       uint32  size = 0; 
-       
-       if (!p)
-               return 0;
+       size+=size_of_uint32( &info->unknown7);
+       size+=size_of_uint32( &info->unknown8);
+       size+=size_of_uint32( &info->unknown9);
+       size+=size_of_uint32( &info->session_counter);
+       size+=size_of_uint32( &info->unknown11);
+       size+=size_of_uint32( &info->printer_errors);
+       size+=size_of_uint32( &info->unknown13);
+       size+=size_of_uint32( &info->unknown14);
+       size+=size_of_uint32( &info->unknown15);
+       size+=size_of_uint32( &info->unknown16);
+       size+=size_of_uint32( &info->change_id);
+       size+=size_of_uint32( &info->unknown18);
+       size+=size_of_uint32( &info->status);
+       size+=size_of_uint32( &info->unknown20);
+       size+=size_of_uint32( &info->c_setprinter);
        
-       /* uint32(offset) + uint32(length) + length) */
-       size += (size_of_uint32(&p->value_len)*2) + p->value_len;
-       size += (size_of_uint32(&p->data_len)*2) + p->data_len + (p->data_len%2) ;
+       size+=size_of_uint16( &info->unknown22);
+       size+=size_of_uint16( &info->unknown23);
+       size+=size_of_uint16( &info->unknown24);
+       size+=size_of_uint16( &info->unknown25);
+       size+=size_of_uint16( &info->unknown26);
+       size+=size_of_uint16( &info->unknown27);
+       size+=size_of_uint16( &info->unknown28);
+       size+=size_of_uint16( &info->unknown29);
        
-       size += size_of_uint32(&p->type);
-                      
        return size;
 }
 
@@ -2533,740 +1353,467 @@ uint32 spoolss_size_printer_enum_values(PRINTER_ENUM_VALUES *p)
 return the size required by a struct in the stream
 ********************************************************************/  
 
-uint32 spoolss_size_printmonitor_info_1(PRINTMONITOR_1 *info)
+uint32 spoolss_size_printer_info_1(PRINTER_INFO_1 *info)
 {
        int size=0;
+               
+       size+=size_of_uint32( &info->flags );   
+       size+=size_of_relative_string( &info->description );
        size+=size_of_relative_string( &info->name );
+       size+=size_of_relative_string( &info->comment );
 
        return size;
 }
 
 /*******************************************************************
 return the size required by a struct in the stream
-********************************************************************/  
-
-uint32 spoolss_size_printmonitor_info_2(PRINTMONITOR_2 *info)
-{
-       int size=0;
-       size+=size_of_relative_string( &info->name);
-       size+=size_of_relative_string( &info->environment);
-       size+=size_of_relative_string( &info->dll_name);
-
-       return size;
-}
-
-/*******************************************************************
- * init a structure.
- ********************************************************************/
-
-bool make_spoolss_q_getprinterdriver2(SPOOL_Q_GETPRINTERDRIVER2 *q_u, 
-                              const POLICY_HND *hnd,
-                              const fstring architecture,
-                              uint32 level, uint32 clientmajor, uint32 clientminor,
-                              RPC_BUFFER *buffer, uint32 offered)
-{      
-       if (q_u == NULL)
-               return False;
-
-       memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
-
-       init_buf_unistr2(&q_u->architecture, &q_u->architecture_ptr, architecture);
-
-       q_u->level=level;
-       q_u->clientmajorversion=clientmajor;
-       q_u->clientminorversion=clientminor;
-
-       q_u->buffer=buffer;
-       q_u->offered=offered;
-
-       return True;
-}
-
-/*******************************************************************
- * read a structure.
- * called from spoolss_getprinterdriver2 (srv_spoolss.c)
- ********************************************************************/
+********************************************************************/
 
-bool spoolss_io_q_getprinterdriver2(const char *desc, SPOOL_Q_GETPRINTERDRIVER2 *q_u, prs_struct *ps, int depth)
+uint32 spoolss_size_printer_info_2(PRINTER_INFO_2 *info)
 {
-       prs_debug(ps, depth, desc, "spoolss_io_q_getprinterdriver2");
-       depth++;
+       uint32 size=0;
+               
+       size += 4;
+       
+       size += ndr_size_security_descriptor( info->secdesc, NULL, 0 );
 
-       if(!prs_align(ps))
-               return False;
+       size+=size_of_device_mode( info->devmode );
        
-       if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
-               return False;
-       if(!prs_uint32("architecture_ptr", ps, depth, &q_u->architecture_ptr))
-               return False;
-       if(!smb_io_unistr2("architecture", &q_u->architecture, q_u->architecture_ptr, ps, depth))
-               return False;
+       size+=size_of_relative_string( &info->servername );
+       size+=size_of_relative_string( &info->printername );
+       size+=size_of_relative_string( &info->sharename );
+       size+=size_of_relative_string( &info->portname );
+       size+=size_of_relative_string( &info->drivername );
+       size+=size_of_relative_string( &info->comment );
+       size+=size_of_relative_string( &info->location );
        
-       if(!prs_align(ps))
-               return False;
-       if(!prs_uint32("level", ps, depth, &q_u->level))
-               return False;
-               
-       if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
-               return False;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("offered", ps, depth, &q_u->offered))
-               return False;
-               
-       if(!prs_uint32("clientmajorversion", ps, depth, &q_u->clientmajorversion))
-               return False;
-       if(!prs_uint32("clientminorversion", ps, depth, &q_u->clientminorversion))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- * read a structure.
- * called from spoolss_getprinterdriver2 (srv_spoolss.c)
- ********************************************************************/
-
-bool spoolss_io_r_getprinterdriver2(const char *desc, SPOOL_R_GETPRINTERDRIVER2 *r_u, prs_struct *ps, int depth)
-{
-       prs_debug(ps, depth, desc, "spoolss_io_r_getprinterdriver2");
-       depth++;
+       size+=size_of_relative_string( &info->sepfile );
+       size+=size_of_relative_string( &info->printprocessor );
+       size+=size_of_relative_string( &info->datatype );
+       size+=size_of_relative_string( &info->parameters );
 
-       if (!prs_align(ps))
-               return False;
+       size+=size_of_uint32( &info->attributes );
+       size+=size_of_uint32( &info->priority );
+       size+=size_of_uint32( &info->defaultpriority );
+       size+=size_of_uint32( &info->starttime );
+       size+=size_of_uint32( &info->untiltime );
+       size+=size_of_uint32( &info->status );
+       size+=size_of_uint32( &info->cjobs );
+       size+=size_of_uint32( &info->averageppm );      
                
-       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
-               return False;
-
-       if (!prs_align(ps))
-               return False;
-       if (!prs_uint32("needed", ps, depth, &r_u->needed))
-               return False;
-       if (!prs_uint32("servermajorversion", ps, depth, &r_u->servermajorversion))
-               return False;
-       if (!prs_uint32("serverminorversion", ps, depth, &r_u->serverminorversion))
-               return False;           
-       if (!prs_werror("status", ps, depth, &r_u->status))
-               return False;
-
-       return True;            
-}
-
-/*******************************************************************
- * init a structure.
- ********************************************************************/
-
-bool make_spoolss_q_enumprinters(
-       SPOOL_Q_ENUMPRINTERS *q_u, 
-       uint32 flags, 
-       char *servername, 
-       uint32 level, 
-       RPC_BUFFER *buffer, 
-       uint32 offered
-)
-{
-       q_u->flags=flags;
+       /* 
+        * add any adjustments for alignment.  This is
+        * not optimal since we could be calling this
+        * function from a loop (e.g. enumprinters), but 
+        * it is easier to maintain the calculation here and
+        * not place the burden on the caller to remember.   --jerry
+        */
+       if ((size % 4) != 0)
+               size += 4 - (size % 4);
        
-       q_u->servername_ptr = (servername != NULL) ? 1 : 0;
-       init_buf_unistr2(&q_u->servername, &q_u->servername_ptr, servername);
-
-       q_u->level=level;
-       q_u->buffer=buffer;
-       q_u->offered=offered;
-
-       return True;
+       return size;
 }
 
 /*******************************************************************
- * init a structure.
- ********************************************************************/
+return the size required by a struct in the stream
+********************************************************************/
 
-bool make_spoolss_q_enumports(SPOOL_Q_ENUMPORTS *q_u, 
-                               fstring servername, uint32 level, 
-                               RPC_BUFFER *buffer, uint32 offered)
+uint32 spoolss_size_printer_info_4(PRINTER_INFO_4 *info)
 {
-       q_u->name_ptr = (servername != NULL) ? 1 : 0;
-       init_buf_unistr2(&q_u->name, &q_u->name_ptr, servername);
-
-       q_u->level=level;
-       q_u->buffer=buffer;
-       q_u->offered=offered;
+       uint32 size=0;
+               
+       size+=size_of_relative_string( &info->printername );
+       size+=size_of_relative_string( &info->servername );
 
-       return True;
+       size+=size_of_uint32( &info->attributes );
+       return size;
 }
 
 /*******************************************************************
- * read a structure.
- * called from spoolss_enumprinters (srv_spoolss.c)
- ********************************************************************/
-
-bool spoolss_io_q_enumprinters(const char *desc, SPOOL_Q_ENUMPRINTERS *q_u, prs_struct *ps, int depth)
-{
-       prs_debug(ps, depth, desc, "spoolss_io_q_enumprinters");
-       depth++;
-
-       if (!prs_align(ps))
-               return False;
-
-       if (!prs_uint32("flags", ps, depth, &q_u->flags))
-               return False;
-       if (!prs_uint32("servername_ptr", ps, depth, &q_u->servername_ptr))
-               return False;
-
-       if (!smb_io_unistr2("", &q_u->servername, q_u->servername_ptr, ps, depth))
-               return False;
-               
-       if (!prs_align(ps))
-               return False;
-       if (!prs_uint32("level", ps, depth, &q_u->level))
-               return False;
-
-       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
-               return False;
-
-       if (!prs_align(ps))
-               return False;
-       if (!prs_uint32("offered", ps, depth, &q_u->offered))
-               return False;
+return the size required by a struct in the stream
+********************************************************************/
 
-       return True;
+uint32 spoolss_size_printer_info_5(PRINTER_INFO_5 *info)
+{
+       uint32 size=0;
+               
+       size+=size_of_relative_string( &info->printername );
+       size+=size_of_relative_string( &info->portname );
+
+       size+=size_of_uint32( &info->attributes );
+       size+=size_of_uint32( &info->device_not_selected_timeout );
+       size+=size_of_uint32( &info->transmission_retry_timeout );
+       return size;
 }
 
 /*******************************************************************
- Parse a SPOOL_R_ENUMPRINTERS structure.
- ********************************************************************/
+return the size required by a struct in the stream
+********************************************************************/
 
-bool spoolss_io_r_enumprinters(const char *desc, SPOOL_R_ENUMPRINTERS *r_u, prs_struct *ps, int depth)
+uint32 spoolss_size_printer_info_6(PRINTER_INFO_6 *info)
 {
-       prs_debug(ps, depth, desc, "spoolss_io_r_enumprinters");
-       depth++;
-
-       if (!prs_align(ps))
-               return False;
-               
-       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
-               return False;
+       return sizeof(uint32);
+}
 
-       if (!prs_align(ps))
-               return False;
-               
-       if (!prs_uint32("needed", ps, depth, &r_u->needed))
-               return False;
-               
-       if (!prs_uint32("returned", ps, depth, &r_u->returned))
-               return False;
-               
-       if (!prs_werror("status", ps, depth, &r_u->status))
-               return False;
+/*******************************************************************
+return the size required by a struct in the stream
+********************************************************************/
 
-       return True;            
+uint32 spoolss_size_printer_info_3(PRINTER_INFO_3 *info)
+{
+       /* The 8 is for the self relative pointer - 8 byte aligned.. */
+       return 8 + (uint32)ndr_size_security_descriptor( info->secdesc, NULL, 0 );
 }
 
 /*******************************************************************
- * write a structure.
- * called from spoolss_r_enum_printers (srv_spoolss.c)
- *
- ********************************************************************/
-
-bool spoolss_io_r_getprinter(const char *desc, SPOOL_R_GETPRINTER *r_u, prs_struct *ps, int depth)
-{      
-       prs_debug(ps, depth, desc, "spoolss_io_r_getprinter");
-       depth++;
+return the size required by a struct in the stream
+********************************************************************/
 
-       if (!prs_align(ps))
-               return False;
+uint32 spoolss_size_printer_info_7(PRINTER_INFO_7 *info)
+{
+       uint32 size=0;
                
-       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
-               return False;
+       size+=size_of_relative_string( &info->guid );
+       size+=size_of_uint32( &info->action );
+       return size;
+}
 
-       if (!prs_align(ps))
-               return False;
+/*******************************************************************
+return the size required by a struct in the stream
+********************************************************************/
 
-       if (!prs_uint32("needed", ps, depth, &r_u->needed))
-               return False;
-               
-       if (!prs_werror("status", ps, depth, &r_u->status))
-               return False;
+uint32 spoolss_size_printer_driver_info_1(DRIVER_INFO_1 *info)
+{
+       int size=0;
+       size+=size_of_relative_string( &info->name );
 
-       return True;            
+       return size;
 }
 
 /*******************************************************************
- * read a structure.
- * called from spoolss_getprinter (srv_spoolss.c)
- ********************************************************************/
+return the size required by a struct in the stream
+********************************************************************/
 
-bool spoolss_io_q_getprinter(const char *desc, SPOOL_Q_GETPRINTER *q_u, prs_struct *ps, int depth)
+uint32 spoolss_size_printer_driver_info_2(DRIVER_INFO_2 *info)
 {
-       prs_debug(ps, depth, desc, "spoolss_io_q_getprinter");
-       depth++;
+       int size=0;
+       size+=size_of_uint32( &info->version ); 
+       size+=size_of_relative_string( &info->name );
+       size+=size_of_relative_string( &info->architecture );
+       size+=size_of_relative_string( &info->driverpath );
+       size+=size_of_relative_string( &info->datafile );
+       size+=size_of_relative_string( &info->configfile );
 
-       if (!prs_align(ps))
-               return False;
+       return size;
+}
 
-       if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
-               return False;
-       if (!prs_uint32("level", ps, depth, &q_u->level))
-               return False;
+/*******************************************************************
+return the size required by a string array.
+********************************************************************/
 
-       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
-               return False;
+uint32 spoolss_size_string_array(uint16 *string)
+{
+       uint32 i = 0;
 
-       if (!prs_align(ps))
-               return False;
-       if (!prs_uint32("offered", ps, depth, &q_u->offered))
-               return False;
+       if (string) {
+               for (i=0; (string[i]!=0x0000) || (string[i+1]!=0x0000); i++);
+       }
+       i=i+2; /* to count all chars including the leading zero */
+       i=2*i; /* because we need the value in bytes */
+       i=i+4; /* the offset pointer size */
 
-       return True;
+       return i;
 }
 
 /*******************************************************************
- * init a structure.
- ********************************************************************/
+return the size required by a struct in the stream
+********************************************************************/
 
-bool make_spoolss_q_getprinter(
-       TALLOC_CTX *mem_ctx,
-       SPOOL_Q_GETPRINTER *q_u, 
-       const POLICY_HND *hnd, 
-       uint32 level, 
-       RPC_BUFFER *buffer, 
-       uint32 offered
-)
+uint32 spoolss_size_printer_driver_info_3(DRIVER_INFO_3 *info)
 {
-       if (q_u == NULL)
-       {
-               return False;
-       }
-       memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
+       int size=0;
 
-       q_u->level=level;
-       q_u->buffer=buffer;
-       q_u->offered=offered;
+       size+=size_of_uint32( &info->version ); 
+       size+=size_of_relative_string( &info->name );
+       size+=size_of_relative_string( &info->architecture );
+       size+=size_of_relative_string( &info->driverpath );
+       size+=size_of_relative_string( &info->datafile );
+       size+=size_of_relative_string( &info->configfile );
+       size+=size_of_relative_string( &info->helpfile );
+       size+=size_of_relative_string( &info->monitorname );
+       size+=size_of_relative_string( &info->defaultdatatype );
+       
+       size+=spoolss_size_string_array(info->dependentfiles);
 
-       return True;
+       return size;
 }
 
 /*******************************************************************
- * init a structure.
- ********************************************************************/
-bool make_spoolss_q_setprinter(TALLOC_CTX *mem_ctx, SPOOL_Q_SETPRINTER *q_u, 
-                               const POLICY_HND *hnd, uint32 level, PRINTER_INFO_CTR *info, 
-                               uint32 command)
+return the size required by a struct in the stream
+********************************************************************/
+
+uint32 spoolss_size_printer_driver_info_6(DRIVER_INFO_6 *info)
 {
-       SEC_DESC *secdesc;
-       DEVICEMODE *devmode;
+       uint32 size=0;
 
-       if (!q_u || !info)
-               return False;
+       size+=size_of_uint32( &info->version ); 
+       size+=size_of_relative_string( &info->name );
+       size+=size_of_relative_string( &info->architecture );
+       size+=size_of_relative_string( &info->driverpath );
+       size+=size_of_relative_string( &info->datafile );
+       size+=size_of_relative_string( &info->configfile );
+       size+=size_of_relative_string( &info->helpfile );
+
+       size+=spoolss_size_string_array(info->dependentfiles);
+
+       size+=size_of_relative_string( &info->monitorname );
+       size+=size_of_relative_string( &info->defaultdatatype );
        
-       memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
+       size+=spoolss_size_string_array(info->previousdrivernames);
 
-       q_u->level = level;
-       q_u->info.level = level;
-       q_u->info.info_ptr = 1; /* Info is != NULL, see above */
-       switch (level) {
+       size+=size_of_nttime(&info->driver_date);
+       size+=size_of_uint32( &info->padding ); 
+       size+=size_of_uint32( &info->driver_version_low );      
+       size+=size_of_uint32( &info->driver_version_high );     
+       size+=size_of_relative_string( &info->mfgname );
+       size+=size_of_relative_string( &info->oem_url );
+       size+=size_of_relative_string( &info->hardware_id );
+       size+=size_of_relative_string( &info->provider );
+
+       return size;
+}
 
-         /* There's no such thing as a setprinter level 1 */
+/*******************************************************************
+return the size required by a struct in the stream
+********************************************************************/  
 
-       case 2:
-               secdesc = info->printers_2->secdesc;
-               devmode = info->printers_2->devmode;
-               
-               make_spoolss_printer_info_2 (mem_ctx, &q_u->info.info_2, info->printers_2);
-#if 1  /* JERRY TEST */
-               q_u->secdesc_ctr = SMB_MALLOC_P(SEC_DESC_BUF);
-               if (!q_u->secdesc_ctr)
-                       return False;
-               q_u->secdesc_ctr->sd = secdesc;
-               q_u->secdesc_ctr->sd_size = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
-
-               q_u->devmode_ctr.devmode_ptr = (devmode != NULL) ? 1 : 0;
-               q_u->devmode_ctr.size = (devmode != NULL) ? sizeof(DEVICEMODE) + (3*sizeof(uint32)) : 0;
-               q_u->devmode_ctr.devmode = devmode;
-#else
-               q_u->secdesc_ctr = NULL;
-       
-               q_u->devmode_ctr.devmode_ptr = 0;
-               q_u->devmode_ctr.size = 0;
-               q_u->devmode_ctr.devmode = NULL;
-#endif
-               break;
-       case 3:
-               secdesc = info->printers_3->secdesc;
-               
-               make_spoolss_printer_info_3 (mem_ctx, &q_u->info.info_3, info->printers_3);
-               
-               q_u->secdesc_ctr = SMB_MALLOC_P(SEC_DESC_BUF);
-               if (!q_u->secdesc_ctr)
-                       return False;
-               q_u->secdesc_ctr->sd_size = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
-               q_u->secdesc_ctr->sd = secdesc;
+uint32 spoolss_size_job_info_1(JOB_INFO_1 *info)
+{
+       int size=0;
+       size+=size_of_uint32( &info->jobid );
+       size+=size_of_relative_string( &info->printername );
+       size+=size_of_relative_string( &info->machinename );
+       size+=size_of_relative_string( &info->username );
+       size+=size_of_relative_string( &info->document );
+       size+=size_of_relative_string( &info->datatype );
+       size+=size_of_relative_string( &info->text_status );
+       size+=size_of_uint32( &info->status );
+       size+=size_of_uint32( &info->priority );
+       size+=size_of_uint32( &info->position );
+       size+=size_of_uint32( &info->totalpages );
+       size+=size_of_uint32( &info->pagesprinted );
+       size+=size_of_systemtime( &info->submitted );
 
-               break;
-       case 7:
-               make_spoolss_printer_info_7 (mem_ctx, &q_u->info.info_7, info->printers_7);
-               break;
+       return size;
+}
 
-       default: 
-               DEBUG(0,("make_spoolss_q_setprinter: Unknown info level [%d]\n", level));
-                       break;
-       }
+/*******************************************************************
+return the size required by a struct in the stream
+********************************************************************/  
 
-       
-       q_u->command = command;
+uint32 spoolss_size_job_info_2(JOB_INFO_2 *info)
+{
+       int size=0;
+
+       size+=4; /* size of sec desc ptr */
+
+       size+=size_of_uint32( &info->jobid );
+       size+=size_of_relative_string( &info->printername );
+       size+=size_of_relative_string( &info->machinename );
+       size+=size_of_relative_string( &info->username );
+       size+=size_of_relative_string( &info->document );
+       size+=size_of_relative_string( &info->notifyname );
+       size+=size_of_relative_string( &info->datatype );
+       size+=size_of_relative_string( &info->printprocessor );
+       size+=size_of_relative_string( &info->parameters );
+       size+=size_of_relative_string( &info->drivername );
+       size+=size_of_device_mode( info->devmode );
+       size+=size_of_relative_string( &info->text_status );
+/*     SEC_DESC sec_desc;*/
+       size+=size_of_uint32( &info->status );
+       size+=size_of_uint32( &info->priority );
+       size+=size_of_uint32( &info->position );
+       size+=size_of_uint32( &info->starttime );
+       size+=size_of_uint32( &info->untiltime );
+       size+=size_of_uint32( &info->totalpages );
+       size+=size_of_uint32( &info->size );
+       size+=size_of_systemtime( &info->submitted );
+       size+=size_of_uint32( &info->timeelapsed );
+       size+=size_of_uint32( &info->pagesprinted );
 
-       return True;
+       return size;
 }
 
-
 /*******************************************************************
-********************************************************************/  
+return the size required by a struct in the stream
+********************************************************************/
 
-bool spoolss_io_r_setprinter(const char *desc, SPOOL_R_SETPRINTER *r_u, prs_struct *ps, int depth)
-{              
-       prs_debug(ps, depth, desc, "spoolss_io_r_setprinter");
-       depth++;
+uint32 spoolss_size_form_1(FORM_1 *info)
+{
+       int size=0;
 
-       if(!prs_align(ps))
-               return False;
-       
-       if(!prs_werror("status", ps, depth, &r_u->status))
-               return False;
+       size+=size_of_uint32( &info->flag );
+       size+=size_of_relative_string( &info->name );
+       size+=size_of_uint32( &info->width );
+       size+=size_of_uint32( &info->length );
+       size+=size_of_uint32( &info->left );
+       size+=size_of_uint32( &info->top );
+       size+=size_of_uint32( &info->right );
+       size+=size_of_uint32( &info->bottom );
 
-       return True;
+       return size;
 }
 
 /*******************************************************************
- Marshall/unmarshall a SPOOL_Q_SETPRINTER struct.
+return the size required by a struct in the stream
 ********************************************************************/  
 
-bool spoolss_io_q_setprinter(const char *desc, SPOOL_Q_SETPRINTER *q_u, prs_struct *ps, int depth)
+uint32 spoolss_size_port_info_1(PORT_INFO_1 *info)
 {
-       uint32 ptr_sec_desc = 0;
-
-       prs_debug(ps, depth, desc, "spoolss_io_q_setprinter");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!smb_io_pol_hnd("printer handle", &q_u->handle ,ps, depth))
-               return False;
-       if(!prs_uint32("level", ps, depth, &q_u->level))
-               return False;
-       
-       /* check for supported levels and structures we know about */
-               
-       switch ( q_u->level ) {
-               case 0:
-               case 2:
-               case 3:
-               case 7:
-                       /* supported levels */
-                       break;
-               default:
-                       DEBUG(0,("spoolss_io_q_setprinter: unsupported printer info level [%d]\n", 
-                               q_u->level));
-                       return True;
-       }
-                       
-
-       if(!spool_io_printer_info_level("", &q_u->info, ps, depth))
-               return False;
-
-       if (!spoolss_io_devmode_cont(desc, &q_u->devmode_ctr, ps, depth))
-               return False;
-       
-       if(!prs_align(ps))
-               return False;
-
-       switch (q_u->level)
-       {
-               case 2:
-               {
-                       ptr_sec_desc = q_u->info.info_2->secdesc_ptr;
-                       break;
-               }
-               case 3:
-               {
-                       /* FIXME ! Our parsing here is wrong I think,
-                        * but for a level3 it makes no sense for
-                        * ptr_sec_desc to be NULL. JRA. Based on
-                        * a Vista sniff from Martin Zielinski <mz@seh.de>.
-                        */
-                       if (UNMARSHALLING(ps)) {
-                               ptr_sec_desc = 1;
-                       } else {
-                               ptr_sec_desc = q_u->info.info_3->secdesc_ptr;
-                       }
-                       break;
-               }
-       }
-       if (ptr_sec_desc)
-       {
-               if (!sec_io_desc_buf(desc, &q_u->secdesc_ctr, ps, depth))
-                       return False;
-       } else {
-               uint32 dummy = 0;
-
-               /* Parse a NULL security descriptor.  This should really
-                  happen inside the sec_io_desc_buf() function. */
+       int size=0;
 
-               prs_debug(ps, depth, "", "sec_io_desc_buf");
-               if (!prs_uint32("size", ps, depth + 1, &dummy))
-                       return False;
-               if (!prs_uint32("ptr", ps, depth + 1, &dummy))
-                       return False;
-       }
-       
-       if(!prs_uint32("command", ps, depth, &q_u->command))
-               return False;
+       size+=size_of_relative_string( &info->port_name );
 
-       return True;
+       return size;
 }
 
 /*******************************************************************
+return the size required by a struct in the stream
 ********************************************************************/  
 
-bool spoolss_io_r_enumjobs(const char *desc, SPOOL_R_ENUMJOBS *r_u, prs_struct *ps, int depth)
-{              
-       prs_debug(ps, depth, desc, "spoolss_io_r_enumjobs");
-       depth++;
+uint32 spoolss_size_port_info_2(PORT_INFO_2 *info)
+{
+       int size=0;
 
-       if (!prs_align(ps))
-               return False;
-               
-       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
-               return False;
+       size+=size_of_relative_string( &info->port_name );
+       size+=size_of_relative_string( &info->monitor_name );
+       size+=size_of_relative_string( &info->description );
 
-       if (!prs_align(ps))
-               return False;
-               
-       if (!prs_uint32("needed", ps, depth, &r_u->needed))
-               return False;
-               
-       if (!prs_uint32("returned", ps, depth, &r_u->returned))
-               return False;
-               
-       if (!prs_werror("status", ps, depth, &r_u->status))
-               return False;
+       size+=size_of_uint32( &info->port_type );
+       size+=size_of_uint32( &info->reserved );
 
-       return True;            
+       return size;
 }
 
 /*******************************************************************
+return the size required by a struct in the stream
 ********************************************************************/  
 
-bool make_spoolss_q_enumjobs(SPOOL_Q_ENUMJOBS *q_u, const POLICY_HND *hnd,
-                               uint32 firstjob,
-                               uint32 numofjobs,
-                               uint32 level,
-                               RPC_BUFFER *buffer,
-                               uint32 offered)
+uint32 spoolss_size_printprocessor_info_1(PRINTPROCESSOR_1 *info)
 {
-       if (q_u == NULL)
-       {
-               return False;
-       }
-       memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
-       q_u->firstjob = firstjob;
-       q_u->numofjobs = numofjobs;
-       q_u->level = level;
-       q_u->buffer= buffer;
-       q_u->offered = offered;
-       return True;
+       int size=0;
+       size+=size_of_relative_string( &info->name );
+
+       return size;
 }
 
 /*******************************************************************
+return the size required by a struct in the stream
 ********************************************************************/  
 
-bool spoolss_io_q_enumjobs(const char *desc, SPOOL_Q_ENUMJOBS *q_u, prs_struct *ps, int depth)
+uint32 spoolss_size_printprocdatatype_info_1(PRINTPROCDATATYPE_1 *info)
 {
-       prs_debug(ps, depth, desc, "spoolss_io_q_enumjobs");
-       depth++;
-
-       if (!prs_align(ps))
-               return False;
-
-       if (!smb_io_pol_hnd("printer handle",&q_u->handle, ps, depth))
-               return False;
-               
-       if (!prs_uint32("firstjob", ps, depth, &q_u->firstjob))
-               return False;
-       if (!prs_uint32("numofjobs", ps, depth, &q_u->numofjobs))
-               return False;
-       if (!prs_uint32("level", ps, depth, &q_u->level))
-               return False;
-
-       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
-               return False;   
-
-       if(!prs_align(ps))
-               return False;
-
-       if (!prs_uint32("offered", ps, depth, &q_u->offered))
-               return False;
+       int size=0;
+       size+=size_of_relative_string( &info->name );
 
-       return True;
+       return size;
 }
 
 /*******************************************************************
- Parse a SPOOL_R_ENUMPRINTERDRIVERS structure.
+return the size required by a struct in the stream
 ********************************************************************/  
-
-bool spoolss_io_r_enumprinterdrivers(const char *desc, SPOOL_R_ENUMPRINTERDRIVERS *r_u, prs_struct *ps, int depth)
+uint32 spoolss_size_printer_enum_values(PRINTER_ENUM_VALUES *p)
 {
-       prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterdrivers");
-       depth++;
-
-       if (!prs_align(ps))
-               return False;
-               
-       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
-               return False;
-
-       if (!prs_align(ps))
-               return False;
-               
-       if (!prs_uint32("needed", ps, depth, &r_u->needed))
-               return False;
-               
-       if (!prs_uint32("returned", ps, depth, &r_u->returned))
-               return False;
-               
-       if (!prs_werror("status", ps, depth, &r_u->status))
-               return False;
-
-       return True;            
+       uint32  size = 0; 
+       
+       if (!p)
+               return 0;
+       
+       /* uint32(offset) + uint32(length) + length) */
+       size += (size_of_uint32(&p->value_len)*2) + p->value_len;
+       size += (size_of_uint32(&p->data_len)*2) + p->data_len + (p->data_len%2) ;
+       
+       size += size_of_uint32(&p->type);
+                      
+       return size;
 }
 
 /*******************************************************************
- * init a structure.
- ********************************************************************/
+return the size required by a struct in the stream
+********************************************************************/  
 
-bool make_spoolss_q_enumprinterdrivers(SPOOL_Q_ENUMPRINTERDRIVERS *q_u,
-                                const char *name,
-                                const char *environment,
-                                uint32 level,
-                                RPC_BUFFER *buffer, uint32 offered)
+uint32 spoolss_size_printmonitor_info_1(PRINTMONITOR_1 *info)
 {
-        init_buf_unistr2(&q_u->name, &q_u->name_ptr, name);
-        init_buf_unistr2(&q_u->environment, &q_u->environment_ptr, environment);
-
-        q_u->level=level;
-        q_u->buffer=buffer;
-        q_u->offered=offered;
+       int size=0;
+       size+=size_of_relative_string( &info->name );
 
-        return True;
+       return size;
 }
 
 /*******************************************************************
- Parse a SPOOL_Q_ENUMPRINTERDRIVERS structure.
+return the size required by a struct in the stream
 ********************************************************************/  
 
-bool spoolss_io_q_enumprinterdrivers(const char *desc, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, prs_struct *ps, int depth)
+uint32 spoolss_size_printmonitor_info_2(PRINTMONITOR_2 *info)
 {
+       int size=0;
+       size+=size_of_relative_string( &info->name);
+       size+=size_of_relative_string( &info->environment);
+       size+=size_of_relative_string( &info->dll_name);
 
-       prs_debug(ps, depth, desc, "spoolss_io_q_enumprinterdrivers");
-       depth++;
-
-       if (!prs_align(ps))
-               return False;
-               
-       if (!prs_uint32("name_ptr", ps, depth, &q_u->name_ptr))
-               return False;
-       if (!smb_io_unistr2("", &q_u->name, q_u->name_ptr,ps, depth))
-               return False;
-               
-       if (!prs_align(ps))
-               return False;
-       if (!prs_uint32("environment_ptr", ps, depth, &q_u->environment_ptr))
-               return False;
-       if (!smb_io_unistr2("", &q_u->environment, q_u->environment_ptr, ps, depth))
-               return False;
-               
-       if (!prs_align(ps))
-               return False;
-       if (!prs_uint32("level", ps, depth, &q_u->level))
-               return False;
-               
-       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
-               return False;
-
-       if (!prs_align(ps))
-               return False;
-               
-       if (!prs_uint32("offered", ps, depth, &q_u->offered))
-               return False;
-
-       return True;
+       return size;
 }
 
 /*******************************************************************
-********************************************************************/  
+ * read a structure.
+ * called from spoolss_getprinterdriver2 (srv_spoolss.c)
+ ********************************************************************/
 
-bool spoolss_io_q_enumforms(const char *desc, SPOOL_Q_ENUMFORMS *q_u, prs_struct *ps, int depth)
+bool spoolss_io_q_getprinterdriver2(const char *desc, SPOOL_Q_GETPRINTERDRIVER2 *q_u, prs_struct *ps, int depth)
 {
-
-       prs_debug(ps, depth, desc, "spoolss_io_q_enumforms");
+       prs_debug(ps, depth, desc, "spoolss_io_q_getprinterdriver2");
        depth++;
 
-       if (!prs_align(ps))
-               return False;                   
-       if (!smb_io_pol_hnd("printer handle",&q_u->handle,ps,depth))
-               return False;           
-       if (!prs_uint32("level", ps, depth, &q_u->level))
-               return False;   
+       if(!prs_align(ps))
+               return False;
        
-       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
+       if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
                return False;
-
-       if (!prs_align(ps))
+       if(!prs_uint32("architecture_ptr", ps, depth, &q_u->architecture_ptr))
                return False;
-       if (!prs_uint32("offered", ps, depth, &q_u->offered))
+       if(!smb_io_unistr2("architecture", &q_u->architecture, q_u->architecture_ptr, ps, depth))
                return False;
-
-       return True;
-}
-
-/*******************************************************************
-********************************************************************/  
-
-bool spoolss_io_r_enumforms(const char *desc, SPOOL_R_ENUMFORMS *r_u, prs_struct *ps, int depth)
-{
-       prs_debug(ps, depth, desc, "spoolss_io_r_enumforms");
-       depth++;
-
-       if (!prs_align(ps))
+       
+       if(!prs_align(ps))
+               return False;
+       if(!prs_uint32("level", ps, depth, &q_u->level))
                return False;
                
-       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
+       if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
-       if (!prs_align(ps))
+       if(!prs_align(ps))
                return False;
-               
-       if (!prs_uint32("size of buffer needed", ps, depth, &r_u->needed))
+
+       if(!prs_uint32("offered", ps, depth, &q_u->offered))
                return False;
                
-       if (!prs_uint32("numofforms", ps, depth, &r_u->numofforms))
+       if(!prs_uint32("clientmajorversion", ps, depth, &q_u->clientmajorversion))
                return False;
-               
-       if (!prs_werror("status", ps, depth, &r_u->status))
+       if(!prs_uint32("clientminorversion", ps, depth, &q_u->clientminorversion))
                return False;
 
        return True;
 }
 
 /*******************************************************************
- Parse a SPOOL_R_ENUMPORTS structure.
-********************************************************************/  
+ * read a structure.
+ * called from spoolss_getprinterdriver2 (srv_spoolss.c)
+ ********************************************************************/
 
-bool spoolss_io_r_enumports(const char *desc, SPOOL_R_ENUMPORTS *r_u, prs_struct *ps, int depth)
+bool spoolss_io_r_getprinterdriver2(const char *desc, SPOOL_R_GETPRINTERDRIVER2 *r_u, prs_struct *ps, int depth)
 {
-       prs_debug(ps, depth, desc, "spoolss_io_r_enumports");
+       prs_debug(ps, depth, desc, "spoolss_io_r_getprinterdriver2");
        depth++;
 
        if (!prs_align(ps))
@@ -3277,13 +1824,12 @@ bool spoolss_io_r_enumports(const char *desc, SPOOL_R_ENUMPORTS *r_u, prs_struct
 
        if (!prs_align(ps))
                return False;
-               
        if (!prs_uint32("needed", ps, depth, &r_u->needed))
                return False;
-               
-       if (!prs_uint32("returned", ps, depth, &r_u->returned))
+       if (!prs_uint32("servermajorversion", ps, depth, &r_u->servermajorversion))
                return False;
-               
+       if (!prs_uint32("serverminorversion", ps, depth, &r_u->serverminorversion))
+               return False;           
        if (!prs_werror("status", ps, depth, &r_u->status))
                return False;
 
@@ -3291,729 +1837,465 @@ bool spoolss_io_r_enumports(const char *desc, SPOOL_R_ENUMPORTS *r_u, prs_struct
 }
 
 /*******************************************************************
-********************************************************************/  
+ * init a structure.
+ ********************************************************************/
 
-bool spoolss_io_q_enumports(const char *desc, SPOOL_Q_ENUMPORTS *q_u, prs_struct *ps, int depth)
+bool make_spoolss_q_enumprinters(
+       SPOOL_Q_ENUMPRINTERS *q_u, 
+       uint32 flags, 
+       char *servername, 
+       uint32 level, 
+       RPC_BUFFER *buffer, 
+       uint32 offered
+)
 {
-       prs_debug(ps, depth, desc, "");
-       depth++;
-
-       if (!prs_align(ps))
-               return False;
-
-       if (!prs_uint32("", ps, depth, &q_u->name_ptr))
-               return False;
-       if (!smb_io_unistr2("", &q_u->name,True,ps,depth))
-               return False;
-
-       if (!prs_align(ps))
-               return False;
-       if (!prs_uint32("level", ps, depth, &q_u->level))
-               return False;
-               
-       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
-               return False;
+       q_u->flags=flags;
+       
+       q_u->servername_ptr = (servername != NULL) ? 1 : 0;
+       init_buf_unistr2(&q_u->servername, &q_u->servername_ptr, servername);
 
-       if (!prs_align(ps))
-               return False;
-       if (!prs_uint32("offered", ps, depth, &q_u->offered))
-               return False;
+       q_u->level=level;
+       q_u->buffer=buffer;
+       q_u->offered=offered;
 
        return True;
 }
 
 /*******************************************************************
Parse a SPOOL_PRINTER_INFO_LEVEL_1 structure.
-********************************************************************/  
* init a structure.
+ ********************************************************************/
 
-bool spool_io_printer_info_level_1(const char *desc, SPOOL_PRINTER_INFO_LEVEL_1 *il, prs_struct *ps, int depth)
-{      
-       prs_debug(ps, depth, desc, "spool_io_printer_info_level_1");
-       depth++;
-               
-       if(!prs_align(ps))
-               return False;
+bool make_spoolss_q_enumports(SPOOL_Q_ENUMPORTS *q_u, 
+                               fstring servername, uint32 level, 
+                               RPC_BUFFER *buffer, uint32 offered)
+{
+       q_u->name_ptr = (servername != NULL) ? 1 : 0;
+       init_buf_unistr2(&q_u->name, &q_u->name_ptr, servername);
 
-       if(!prs_uint32("flags", ps, depth, &il->flags))
-               return False;
-       if(!prs_uint32("description_ptr", ps, depth, &il->description_ptr))
-               return False;
-       if(!prs_uint32("name_ptr", ps, depth, &il->name_ptr))
-               return False;
-       if(!prs_uint32("comment_ptr", ps, depth, &il->comment_ptr))
-               return False;
-               
-       if(!smb_io_unistr2("description", &il->description, il->description_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("name", &il->name, il->name_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("comment", &il->comment, il->comment_ptr, ps, depth))
-               return False;
+       q_u->level=level;
+       q_u->buffer=buffer;
+       q_u->offered=offered;
 
        return True;
 }
 
 /*******************************************************************
- Parse a SPOOL_PRINTER_INFO_LEVEL_3 structure.
-********************************************************************/  
+ * read a structure.
+ * called from spoolss_enumprinters (srv_spoolss.c)
+ ********************************************************************/
 
-bool spool_io_printer_info_level_3(const char *desc, SPOOL_PRINTER_INFO_LEVEL_3 *il, prs_struct *ps, int depth)
-{      
-       prs_debug(ps, depth, desc, "spool_io_printer_info_level_3");
+bool spoolss_io_q_enumprinters(const char *desc, SPOOL_Q_ENUMPRINTERS *q_u, prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "spoolss_io_q_enumprinters");
        depth++;
-               
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("secdesc_ptr", ps, depth, &il->secdesc_ptr))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Parse a SPOOL_PRINTER_INFO_LEVEL_2 structure.
-********************************************************************/  
 
-bool spool_io_printer_info_level_2(const char *desc, SPOOL_PRINTER_INFO_LEVEL_2 *il, prs_struct *ps, int depth)
-{      
-       prs_debug(ps, depth, desc, "spool_io_printer_info_level_2");
-       depth++;
-               
-       if(!prs_align(ps))
+       if (!prs_align(ps))
                return False;
 
-       if(!prs_uint32("servername_ptr", ps, depth, &il->servername_ptr))
-               return False;
-       if(!prs_uint32("printername_ptr", ps, depth, &il->printername_ptr))
-               return False;
-       if(!prs_uint32("sharename_ptr", ps, depth, &il->sharename_ptr))
+       if (!prs_uint32("flags", ps, depth, &q_u->flags))
                return False;
-       if(!prs_uint32("portname_ptr", ps, depth, &il->portname_ptr))
+       if (!prs_uint32("servername_ptr", ps, depth, &q_u->servername_ptr))
                return False;
 
-       if(!prs_uint32("drivername_ptr", ps, depth, &il->drivername_ptr))
-               return False;
-       if(!prs_uint32("comment_ptr", ps, depth, &il->comment_ptr))
-               return False;
-       if(!prs_uint32("location_ptr", ps, depth, &il->location_ptr))
-               return False;
-       if(!prs_uint32("devmode_ptr", ps, depth, &il->devmode_ptr))
-               return False;
-       if(!prs_uint32("sepfile_ptr", ps, depth, &il->sepfile_ptr))
-               return False;
-       if(!prs_uint32("printprocessor_ptr", ps, depth, &il->printprocessor_ptr))
-               return False;
-       if(!prs_uint32("datatype_ptr", ps, depth, &il->datatype_ptr))
+       if (!smb_io_unistr2("", &q_u->servername, q_u->servername_ptr, ps, depth))
                return False;
-       if(!prs_uint32("parameters_ptr", ps, depth, &il->parameters_ptr))
+               
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint32("secdesc_ptr", ps, depth, &il->secdesc_ptr))
+       if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
 
-       if(!prs_uint32("attributes", ps, depth, &il->attributes))
-               return False;
-       if(!prs_uint32("priority", ps, depth, &il->priority))
-               return False;
-       if(!prs_uint32("default_priority", ps, depth, &il->default_priority))
-               return False;
-       if(!prs_uint32("starttime", ps, depth, &il->starttime))
-               return False;
-       if(!prs_uint32("untiltime", ps, depth, &il->untiltime))
-               return False;
-       if(!prs_uint32("status", ps, depth, &il->status))
-               return False;
-       if(!prs_uint32("cjobs", ps, depth, &il->cjobs))
-               return False;
-       if(!prs_uint32("averageppm", ps, depth, &il->averageppm))
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
-       if(!smb_io_unistr2("servername", &il->servername, il->servername_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("printername", &il->printername, il->printername_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("sharename", &il->sharename, il->sharename_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("portname", &il->portname, il->portname_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("drivername", &il->drivername, il->drivername_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("comment", &il->comment, il->comment_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("location", &il->location, il->location_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("sepfile", &il->sepfile, il->sepfile_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("printprocessor", &il->printprocessor, il->printprocessor_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("datatype", &il->datatype, il->datatype_ptr, ps, depth))
+       if (!prs_align(ps))
                return False;
-       if(!smb_io_unistr2("parameters", &il->parameters, il->parameters_ptr, ps, depth))
+       if (!prs_uint32("offered", ps, depth, &q_u->offered))
                return False;
 
        return True;
 }
 
-bool spool_io_printer_info_level_7(const char *desc, SPOOL_PRINTER_INFO_LEVEL_7 *il, prs_struct *ps, int depth)
-{      
-       prs_debug(ps, depth, desc, "spool_io_printer_info_level_7");
+/*******************************************************************
+ Parse a SPOOL_R_ENUMPRINTERS structure.
+ ********************************************************************/
+
+bool spoolss_io_r_enumprinters(const char *desc, SPOOL_R_ENUMPRINTERS *r_u, prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "spoolss_io_r_enumprinters");
        depth++;
+
+       if (!prs_align(ps))
+               return False;
                
-       if(!prs_align(ps))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
-       if(!prs_uint32("guid_ptr", ps, depth, &il->guid_ptr))
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint32("action", ps, depth, &il->action))
+               
+       if (!prs_uint32("needed", ps, depth, &r_u->needed))
                return False;
-
-       if(!smb_io_unistr2("servername", &il->guid, il->guid_ptr, ps, depth))
+               
+       if (!prs_uint32("returned", ps, depth, &r_u->returned))
                return False;
-       return True;
+               
+       if (!prs_werror("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;            
 }
 
 /*******************************************************************
-********************************************************************/  
+ * write a structure.
+ * called from spoolss_r_enum_printers (srv_spoolss.c)
+ *
+ ********************************************************************/
 
-bool spool_io_printer_info_level(const char *desc, SPOOL_PRINTER_INFO_LEVEL *il, prs_struct *ps, int depth)
-{
-       prs_debug(ps, depth, desc, "spool_io_printer_info_level");
+bool spoolss_io_r_getprinter(const char *desc, SPOOL_R_GETPRINTER *r_u, prs_struct *ps, int depth)
+{      
+       prs_debug(ps, depth, desc, "spoolss_io_r_getprinter");
        depth++;
 
-       if(!prs_align(ps))
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint32("level", ps, depth, &il->level))
+               
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
-       if(!prs_uint32("info_ptr", ps, depth, &il->info_ptr))
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_uint32("needed", ps, depth, &r_u->needed))
+               return False;
+               
+       if (!prs_werror("status", ps, depth, &r_u->status))
                return False;
-       
-       /* if no struct inside just return */
-       if (il->info_ptr==0) {
-               if (UNMARSHALLING(ps)) {
-                       il->info_1=NULL;
-                       il->info_2=NULL;
-               }
-               return True;
-       }
-                       
-       switch (il->level) {
-               /*
-                * level 0 is used by setprinter when managing the queue
-                * (hold, stop, start a queue)
-                */
-               case 0:
-                       break;
-               /* DOCUMENT ME!!! What is level 1 used for? */
-               case 1:
-               {
-                       if (UNMARSHALLING(ps)) {
-                               if ((il->info_1=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_INFO_LEVEL_1,1)) == NULL)
-                                       return False;
-                       }
-                       if (!spool_io_printer_info_level_1("", il->info_1, ps, depth))
-                               return False;
-                       break;          
-               }
-               /* 
-                * level 2 is used by addprinter
-                * and by setprinter when updating printer's info
-                */     
-               case 2:
-                       if (UNMARSHALLING(ps)) {
-                               if ((il->info_2=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_INFO_LEVEL_2,1)) == NULL)
-                                       return False;
-                       }
-                       if (!spool_io_printer_info_level_2("", il->info_2, ps, depth))
-                               return False;
-                       break;          
-               /* DOCUMENT ME!!! What is level 3 used for? */
-               case 3:
-               {
-                       if (UNMARSHALLING(ps)) {
-                               if ((il->info_3=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_INFO_LEVEL_3,1)) == NULL)
-                                       return False;
-                       }
-                       if (!spool_io_printer_info_level_3("", il->info_3, ps, depth))
-                               return False;
-                       break;          
-               }
-               case 7:
-                       if (UNMARSHALLING(ps))
-                               if ((il->info_7=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_INFO_LEVEL_7,1)) == NULL)
-                                       return False;
-                       if (!spool_io_printer_info_level_7("", il->info_7, ps, depth))
-                               return False;
-                       break;
-       }
 
-       return True;
+       return True;            
 }
 
 /*******************************************************************
-********************************************************************/  
+ * read a structure.
+ * called from spoolss_getprinter (srv_spoolss.c)
+ ********************************************************************/
 
-bool spoolss_io_q_addprinterex(const char *desc, SPOOL_Q_ADDPRINTEREX *q_u, prs_struct *ps, int depth)
+bool spoolss_io_q_getprinter(const char *desc, SPOOL_Q_GETPRINTER *q_u, prs_struct *ps, int depth)
 {
-       uint32 ptr_sec_desc = 0;
-
-       prs_debug(ps, depth, desc, "spoolss_io_q_addprinterex");
+       prs_debug(ps, depth, desc, "spoolss_io_q_getprinter");
        depth++;
 
-       if(!prs_align(ps))
+       if (!prs_align(ps))
                return False;
 
-       if (!prs_io_unistr2_p("ptr", ps, depth, &q_u->server_name))
+       if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
                return False;
-       if (!prs_io_unistr2("servername", ps, depth, q_u->server_name))
+       if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
 
-       if(!prs_align(ps))
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
-       if(!prs_uint32("info_level", ps, depth, &q_u->level))
-               return False;
-       
-       if(!spool_io_printer_info_level("", &q_u->info, ps, depth))
+       if (!prs_align(ps))
                return False;
-       
-       if (!spoolss_io_devmode_cont(desc, &q_u->devmode_ctr, ps, depth))
+       if (!prs_uint32("offered", ps, depth, &q_u->offered))
                return False;
 
-       if(!prs_align(ps))
-               return False;
+       return True;
+}
 
-       switch (q_u->level) {
-               case 2:
-                       ptr_sec_desc = q_u->info.info_2->secdesc_ptr;
-                       break;
-               case 3:
-                       ptr_sec_desc = q_u->info.info_3->secdesc_ptr;
-                       break;
-       }
-       if (ptr_sec_desc) {
-               if (!sec_io_desc_buf(desc, &q_u->secdesc_ctr, ps, depth))
-                       return False;
-       } else {
-               uint32 dummy = 0;
+/*******************************************************************
+********************************************************************/  
 
-               /* Parse a NULL security descriptor.  This should really
-                       happen inside the sec_io_desc_buf() function. */
+bool spoolss_io_r_enumjobs(const char *desc, SPOOL_R_ENUMJOBS *r_u, prs_struct *ps, int depth)
+{              
+       prs_debug(ps, depth, desc, "spoolss_io_r_enumjobs");
+       depth++;
 
-               prs_debug(ps, depth, "", "sec_io_desc_buf");
-               if (!prs_uint32("size", ps, depth + 1, &dummy))
-                       return False;
-               if (!prs_uint32("ptr", ps, depth + 1, &dummy))
-                       return False;
-       }
+       if (!prs_align(ps))
+               return False;
+               
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
+               return False;
 
-       if(!prs_uint32("user_switch", ps, depth, &q_u->user_switch))
+       if (!prs_align(ps))
+               return False;
+               
+       if (!prs_uint32("needed", ps, depth, &r_u->needed))
                return False;
-       if(!spool_io_user_level("", &q_u->user_ctr, ps, depth))
+               
+       if (!prs_uint32("returned", ps, depth, &r_u->returned))
+               return False;
+               
+       if (!prs_werror("status", ps, depth, &r_u->status))
                return False;
 
-       return True;
+       return True;            
 }
 
 /*******************************************************************
 ********************************************************************/  
 
-bool spoolss_io_r_addprinterex(const char *desc, SPOOL_R_ADDPRINTEREX *r_u, 
-                              prs_struct *ps, int depth)
+bool make_spoolss_q_enumjobs(SPOOL_Q_ENUMJOBS *q_u, const POLICY_HND *hnd,
+                               uint32 firstjob,
+                               uint32 numofjobs,
+                               uint32 level,
+                               RPC_BUFFER *buffer,
+                               uint32 offered)
 {
-       prs_debug(ps, depth, desc, "spoolss_io_r_addprinterex");
-       depth++;
-       
-       if(!smb_io_pol_hnd("printer handle",&r_u->handle,ps,depth))
-               return False;
-
-       if(!prs_werror("status", ps, depth, &r_u->status))
+       if (q_u == NULL)
+       {
                return False;
-
+       }
+       memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
+       q_u->firstjob = firstjob;
+       q_u->numofjobs = numofjobs;
+       q_u->level = level;
+       q_u->buffer= buffer;
+       q_u->offered = offered;
        return True;
 }
 
 /*******************************************************************
 ********************************************************************/  
 
-bool spool_io_printer_driver_info_level_3(const char *desc, SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 **q_u, 
-                                          prs_struct *ps, int depth)
-{      
-       SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *il;
-       
-       prs_debug(ps, depth, desc, "spool_io_printer_driver_info_level_3");
+bool spoolss_io_q_enumjobs(const char *desc, SPOOL_Q_ENUMJOBS *q_u, prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "spoolss_io_q_enumjobs");
        depth++;
-               
-       /* reading */
-       if (UNMARSHALLING(ps)) {
-               il=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_DRIVER_INFO_LEVEL_3,1);
-               if(il == NULL)
-                       return False;
-               *q_u=il;
-       }
-       else {
-               il=*q_u;
-       }
-       
-       if(!prs_align(ps))
-               return False;
 
-       if(!prs_uint32("cversion", ps, depth, &il->cversion))
-               return False;
-       if(!prs_uint32("name", ps, depth, &il->name_ptr))
-               return False;
-       if(!prs_uint32("environment", ps, depth, &il->environment_ptr))
-               return False;
-       if(!prs_uint32("driverpath", ps, depth, &il->driverpath_ptr))
-               return False;
-       if(!prs_uint32("datafile", ps, depth, &il->datafile_ptr))
-               return False;
-       if(!prs_uint32("configfile", ps, depth, &il->configfile_ptr))
-               return False;
-       if(!prs_uint32("helpfile", ps, depth, &il->helpfile_ptr))
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint32("monitorname", ps, depth, &il->monitorname_ptr))
+
+       if (!smb_io_pol_hnd("printer handle",&q_u->handle, ps, depth))
                return False;
-       if(!prs_uint32("defaultdatatype", ps, depth, &il->defaultdatatype_ptr))
+               
+       if (!prs_uint32("firstjob", ps, depth, &q_u->firstjob))
                return False;
-       if(!prs_uint32("dependentfilessize", ps, depth, &il->dependentfilessize))
+       if (!prs_uint32("numofjobs", ps, depth, &q_u->numofjobs))
                return False;
-       if(!prs_uint32("dependentfiles", ps, depth, &il->dependentfiles_ptr))
+       if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
 
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
+               return False;   
+
        if(!prs_align(ps))
                return False;
-       
-       if(!smb_io_unistr2("name", &il->name, il->name_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("environment", &il->environment, il->environment_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("driverpath", &il->driverpath, il->driverpath_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("datafile", &il->datafile, il->datafile_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("configfile", &il->configfile, il->configfile_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("helpfile", &il->helpfile, il->helpfile_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("monitorname", &il->monitorname, il->monitorname_ptr, ps, depth))
-               return False;
-       if(!smb_io_unistr2("defaultdatatype", &il->defaultdatatype, il->defaultdatatype_ptr, ps, depth))
-               return False;
 
-       if(!prs_align(ps))
+       if (!prs_uint32("offered", ps, depth, &q_u->offered))
                return False;
-               
-       if (il->dependentfiles_ptr)
-               smb_io_buffer5("", &il->dependentfiles, ps, depth);
 
        return True;
 }
 
 /*******************************************************************
-parse a SPOOL_PRINTER_DRIVER_INFO_LEVEL_6 structure
+ Parse a SPOOL_R_ENUMPRINTERDRIVERS structure.
 ********************************************************************/  
 
-bool spool_io_printer_driver_info_level_6(const char *desc, SPOOL_PRINTER_DRIVER_INFO_LEVEL_6 **q_u, 
-                                          prs_struct *ps, int depth)
-{      
-       SPOOL_PRINTER_DRIVER_INFO_LEVEL_6 *il;
-       
-       prs_debug(ps, depth, desc, "spool_io_printer_driver_info_level_6");
+bool spoolss_io_r_enumprinterdrivers(const char *desc, SPOOL_R_ENUMPRINTERDRIVERS *r_u, prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterdrivers");
        depth++;
-               
-       /* reading */
-       if (UNMARSHALLING(ps)) {
-               il=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_DRIVER_INFO_LEVEL_6,1);
-               if(il == NULL)
-                       return False;
-               *q_u=il;
-       }
-       else {
-               il=*q_u;
-       }
-       
-       if(!prs_align(ps))
-               return False;
-
-       /* 
-        * I know this seems weird, but I have no other explanation.
-        * This is observed behavior on both NT4 and 2K servers.
-        * --jerry
-        */
-        
-       if (!prs_align_uint64(ps))
-               return False;
 
-       /* parse the main elements the packet */
-
-       if(!prs_uint32("cversion       ", ps, depth, &il->version))
-               return False;
-       if(!prs_uint32("name           ", ps, depth, &il->name_ptr))
-               return False;
-       if(!prs_uint32("environment    ", ps, depth, &il->environment_ptr))
-               return False;
-       if(!prs_uint32("driverpath     ", ps, depth, &il->driverpath_ptr))
-               return False;
-       if(!prs_uint32("datafile       ", ps, depth, &il->datafile_ptr))
-               return False;
-       if(!prs_uint32("configfile     ", ps, depth, &il->configfile_ptr))
-               return False;
-       if(!prs_uint32("helpfile       ", ps, depth, &il->helpfile_ptr))
-               return False;
-       if(!prs_uint32("monitorname    ", ps, depth, &il->monitorname_ptr))
-               return False;
-       if(!prs_uint32("defaultdatatype", ps, depth, &il->defaultdatatype_ptr))
-               return False;
-       if(!prs_uint32("dependentfiles ", ps, depth, &il->dependentfiles_len))
-               return False;
-       if(!prs_uint32("dependentfiles ", ps, depth, &il->dependentfiles_ptr))
-               return False;
-       if(!prs_uint32("previousnames  ", ps, depth, &il->previousnames_len))
-               return False;
-       if(!prs_uint32("previousnames  ", ps, depth, &il->previousnames_ptr))
-               return False;
-       if(!smb_io_time("driverdate    ", &il->driverdate, ps, depth))
-               return False;
-       if(!prs_uint32("dummy4         ", ps, depth, &il->dummy4))
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint64("driverversion  ", ps, depth, &il->driverversion))
+               
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
-       if(!prs_uint32("mfgname        ", ps, depth, &il->mfgname_ptr))
+
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint32("oemurl         ", ps, depth, &il->oemurl_ptr))
+               
+       if (!prs_uint32("needed", ps, depth, &r_u->needed))
                return False;
-       if(!prs_uint32("hardwareid     ", ps, depth, &il->hardwareid_ptr))
+               
+       if (!prs_uint32("returned", ps, depth, &r_u->returned))
                return False;
-       if(!prs_uint32("provider       ", ps, depth, &il->provider_ptr))
+               
+       if (!prs_werror("status", ps, depth, &r_u->status))
                return False;
 
-       /* parse the structures in the packet */
+       return True;            
+}
 
-       if(!smb_io_unistr2("name", &il->name, il->name_ptr, ps, depth))
-               return False;
-       if(!prs_align(ps))
-               return False;
+/*******************************************************************
+ * init a structure.
+ ********************************************************************/
 
-       if(!smb_io_unistr2("environment", &il->environment, il->environment_ptr, ps, depth))
-               return False;
-       if(!prs_align(ps))
-               return False;
+bool make_spoolss_q_enumprinterdrivers(SPOOL_Q_ENUMPRINTERDRIVERS *q_u,
+                                const char *name,
+                                const char *environment,
+                                uint32 level,
+                                RPC_BUFFER *buffer, uint32 offered)
+{
+        init_buf_unistr2(&q_u->name, &q_u->name_ptr, name);
+        init_buf_unistr2(&q_u->environment, &q_u->environment_ptr, environment);
 
-       if(!smb_io_unistr2("driverpath", &il->driverpath, il->driverpath_ptr, ps, depth))
-               return False;
-       if(!prs_align(ps))
-               return False;
+        q_u->level=level;
+        q_u->buffer=buffer;
+        q_u->offered=offered;
 
-       if(!smb_io_unistr2("datafile", &il->datafile, il->datafile_ptr, ps, depth))
-               return False;
-       if(!prs_align(ps))
-               return False;
+        return True;
+}
 
-       if(!smb_io_unistr2("configfile", &il->configfile, il->configfile_ptr, ps, depth))
-               return False;
-       if(!prs_align(ps))
-               return False;
+/*******************************************************************
+ Parse a SPOOL_Q_ENUMPRINTERDRIVERS structure.
+********************************************************************/  
+
+bool spoolss_io_q_enumprinterdrivers(const char *desc, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, prs_struct *ps, int depth)
+{
+
+       prs_debug(ps, depth, desc, "spoolss_io_q_enumprinterdrivers");
+       depth++;
 
-       if(!smb_io_unistr2("helpfile", &il->helpfile, il->helpfile_ptr, ps, depth))
+       if (!prs_align(ps))
                return False;
-       if(!prs_align(ps))
+               
+       if (!prs_uint32("name_ptr", ps, depth, &q_u->name_ptr))
                return False;
-
-       if(!smb_io_unistr2("monitorname", &il->monitorname, il->monitorname_ptr, ps, depth))
+       if (!smb_io_unistr2("", &q_u->name, q_u->name_ptr,ps, depth))
                return False;
-       if(!prs_align(ps))
+               
+       if (!prs_align(ps))
                return False;
-
-       if(!smb_io_unistr2("defaultdatatype", &il->defaultdatatype, il->defaultdatatype_ptr, ps, depth))
+       if (!prs_uint32("environment_ptr", ps, depth, &q_u->environment_ptr))
                return False;
-       if(!prs_align(ps))
+       if (!smb_io_unistr2("", &q_u->environment, q_u->environment_ptr, ps, depth))
                return False;
-       if (il->dependentfiles_ptr) {
-               if(!smb_io_buffer5("dependentfiles", &il->dependentfiles, ps, depth))
-                       return False;
-               if(!prs_align(ps))
-                       return False;
-       }
-       if (il->previousnames_ptr) {
-               if(!smb_io_buffer5("previousnames", &il->previousnames, ps, depth))
-                       return False;
-               if(!prs_align(ps))
-                       return False;
-       }
-       if(!smb_io_unistr2("mfgname", &il->mfgname, il->mfgname_ptr, ps, depth))
+               
+       if (!prs_align(ps))
                return False;
-       if(!prs_align(ps))
+       if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
-       if(!smb_io_unistr2("oemurl", &il->oemurl, il->oemurl_ptr, ps, depth))
+               
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
-       if(!prs_align(ps))
+
+       if (!prs_align(ps))
+               return False;
+               
+       if (!prs_uint32("offered", ps, depth, &q_u->offered))
                return False;
-       if(!smb_io_unistr2("hardwareid", &il->hardwareid, il->hardwareid_ptr, ps, depth))
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/  
+
+bool spoolss_io_q_enumforms(const char *desc, SPOOL_Q_ENUMFORMS *q_u, prs_struct *ps, int depth)
+{
+
+       prs_debug(ps, depth, desc, "spoolss_io_q_enumforms");
+       depth++;
+
+       if (!prs_align(ps))
+               return False;                   
+       if (!smb_io_pol_hnd("printer handle",&q_u->handle,ps,depth))
+               return False;           
+       if (!prs_uint32("level", ps, depth, &q_u->level))
+               return False;   
+       
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
-       if(!prs_align(ps))
+
+       if (!prs_align(ps))
                return False;
-       if(!smb_io_unistr2("provider", &il->provider, il->provider_ptr, ps, depth))
+       if (!prs_uint32("offered", ps, depth, &q_u->offered))
                return False;
 
        return True;
 }
 
 /*******************************************************************
- read a UNICODE array with null terminated strings 
- and null terminated array 
- and size of array at beginning
 ********************************************************************/  
 
-bool smb_io_unibuffer(const char *desc, UNISTR2 *buffer, prs_struct *ps, int depth)
+bool spoolss_io_r_enumforms(const char *desc, SPOOL_R_ENUMFORMS *r_u, prs_struct *ps, int depth)
 {
-       if (buffer==NULL) return False;
+       prs_debug(ps, depth, desc, "spoolss_io_r_enumforms");
+       depth++;
 
-       buffer->offset=0;
-       buffer->uni_str_len=buffer->uni_max_len;
-       
-       if(!prs_uint32("buffer_size", ps, depth, &buffer->uni_max_len))
+       if (!prs_align(ps))
+               return False;
+               
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
-       if(!prs_unistr2(True, "buffer     ", ps, depth, buffer))
+       if (!prs_align(ps))
+               return False;
+               
+       if (!prs_uint32("size of buffer needed", ps, depth, &r_u->needed))
+               return False;
+               
+       if (!prs_uint32("numofforms", ps, depth, &r_u->numofforms))
+               return False;
+               
+       if (!prs_werror("status", ps, depth, &r_u->status))
                return False;
 
        return True;
 }
 
 /*******************************************************************
+ Parse a SPOOL_R_ENUMPORTS structure.
 ********************************************************************/  
 
-bool spool_io_printer_driver_info_level(const char *desc, SPOOL_PRINTER_DRIVER_INFO_LEVEL *il, prs_struct *ps, int depth)
+bool spoolss_io_r_enumports(const char *desc, SPOOL_R_ENUMPORTS *r_u, prs_struct *ps, int depth)
 {
-       prs_debug(ps, depth, desc, "spool_io_printer_driver_info_level");
+       prs_debug(ps, depth, desc, "spoolss_io_r_enumports");
        depth++;
 
-       if(!prs_align(ps))
-               return False;
-       if(!prs_uint32("level", ps, depth, &il->level))
+       if (!prs_align(ps))
                return False;
-       if(!prs_uint32("ptr", ps, depth, &il->ptr))
+               
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
-       if (il->ptr==0)
-               return True;
+       if (!prs_align(ps))
+               return False;
                
-       switch (il->level) {
-               case 3:
-                       if(!spool_io_printer_driver_info_level_3("", &il->info_3, ps, depth))
-                               return False;
-                       break;          
-               case 6:
-                       if(!spool_io_printer_driver_info_level_6("", &il->info_6, ps, depth))
-                               return False;
-                       break;          
-       default:
+       if (!prs_uint32("needed", ps, depth, &r_u->needed))
+               return False;
+               
+       if (!prs_uint32("returned", ps, depth, &r_u->returned))
+               return False;
+               
+       if (!prs_werror("status", ps, depth, &r_u->status))
                return False;
-       }
 
-       return True;
+       return True;            
 }
 
 /*******************************************************************
- init a SPOOL_Q_ADDPRINTERDRIVER struct
- ******************************************************************/
+********************************************************************/  
 
-bool make_spoolss_q_addprinterdriver(TALLOC_CTX *mem_ctx,
-                               SPOOL_Q_ADDPRINTERDRIVER *q_u, const char* srv_name, 
-                               uint32 level, PRINTER_DRIVER_CTR *info)
+bool spoolss_io_q_enumports(const char *desc, SPOOL_Q_ENUMPORTS *q_u, prs_struct *ps, int depth)
 {
-       DEBUG(5,("make_spoolss_q_addprinterdriver\n"));
-       
-       if (!srv_name || !info) {
+       prs_debug(ps, depth, desc, "");
+       depth++;
+
+       if (!prs_align(ps))
                return False;
-       }
 
-       q_u->server_name_ptr = 1; /* srv_name is != NULL, see above */
-       init_unistr2(&q_u->server_name, srv_name, UNI_STR_TERMINATE);
-       
-       q_u->level = level;
-       
-       q_u->info.level = level;
-       q_u->info.ptr = 1;      /* Info is != NULL, see above */
-       switch (level)
-       {
-       /* info level 3 is supported by Windows 95/98, WinNT and Win2k */
-       case 3 :
-               make_spoolss_driver_info_3(mem_ctx, &q_u->info.info_3, info->info3);
-               break;
-               
-       default:
-               DEBUG(0,("make_spoolss_q_addprinterdriver: Unknown info level [%d]\n", level));
-               break;
-       }
-       
-       return True;
-}
+       if (!prs_uint32("", ps, depth, &q_u->name_ptr))
+               return False;
+       if (!smb_io_unistr2("", &q_u->name,True,ps,depth))
+               return False;
 
-bool make_spoolss_driver_info_3(TALLOC_CTX *mem_ctx,
-       SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 **spool_drv_info,
-                               DRIVER_INFO_3 *info3)
-{
-       uint32          len = 0;
-       SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *inf;
-
-       if (!(inf=TALLOC_ZERO_P(mem_ctx, SPOOL_PRINTER_DRIVER_INFO_LEVEL_3)))
-               return False;
-
-       inf->cversion   = info3->version;
-       inf->name_ptr   = (info3->name.buffer!=NULL)?1:0;
-       inf->environment_ptr    = (info3->architecture.buffer!=NULL)?1:0;
-       inf->driverpath_ptr     = (info3->driverpath.buffer!=NULL)?1:0;
-       inf->datafile_ptr       = (info3->datafile.buffer!=NULL)?1:0;
-       inf->configfile_ptr     = (info3->configfile.buffer!=NULL)?1:0;
-       inf->helpfile_ptr       = (info3->helpfile.buffer!=NULL)?1:0;
-       inf->monitorname_ptr    = (info3->monitorname.buffer!=NULL)?1:0;
-       inf->defaultdatatype_ptr        = (info3->defaultdatatype.buffer!=NULL)?1:0;
-
-       init_unistr2_from_unistr(inf, &inf->name, &info3->name);
-       init_unistr2_from_unistr(inf, &inf->environment, &info3->architecture);
-       init_unistr2_from_unistr(inf, &inf->driverpath, &info3->driverpath);
-       init_unistr2_from_unistr(inf, &inf->datafile, &info3->datafile);
-       init_unistr2_from_unistr(inf, &inf->configfile, &info3->configfile);
-       init_unistr2_from_unistr(inf, &inf->helpfile, &info3->helpfile);
-       init_unistr2_from_unistr(inf, &inf->monitorname, &info3->monitorname);
-       init_unistr2_from_unistr(inf, &inf->defaultdatatype, &info3->defaultdatatype);
-
-       if (info3->dependentfiles) {
-               bool done = False;
-               bool null_char = False;
-               uint16 *ptr = info3->dependentfiles;
-
-               while (!done) {
-                       switch (*ptr) {
-                               case 0:
-                                       /* the null_char bool is used to help locate
-                                          two '\0's back to back */
-                                       if (null_char) {
-                                               done = True;
-                                       } else {
-                                               null_char = True;
-                                       }
-                                       break;
-                                       
-                               default:
-                                       null_char = False;
-                                       break;                          
-                       }
-                       len++;
-                       ptr++;
-               }
-       }
+       if (!prs_align(ps))
+               return False;
+       if (!prs_uint32("level", ps, depth, &q_u->level))
+               return False;
+               
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
+               return False;
 
-       inf->dependentfiles_ptr = (info3->dependentfiles != NULL) ? 1 : 0;
-       inf->dependentfilessize = (info3->dependentfiles != NULL) ? len : 0;
-       if(!make_spoolss_buffer5(mem_ctx, &inf->dependentfiles, len, info3->dependentfiles)) {
-               SAFE_FREE(inf);
+       if (!prs_align(ps))
                return False;
-       }
-       
-       *spool_drv_info = inf;
-       
+       if (!prs_uint32("offered", ps, depth, &q_u->offered))
+               return False;
+
        return True;
 }
 
@@ -4041,79 +2323,6 @@ bool make_spoolss_buffer5(TALLOC_CTX *mem_ctx, BUFFER5 *buf5, uint32 len, uint16
        return True;
 }
 
-/*******************************************************************
- fill in the prs_struct for a ADDPRINTERDRIVER request PDU
- ********************************************************************/  
-
-bool spoolss_io_q_addprinterdriver(const char *desc, SPOOL_Q_ADDPRINTERDRIVER *q_u, prs_struct *ps, int depth)
-{
-       prs_debug(ps, depth, desc, "spoolss_io_q_addprinterdriver");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("server_name_ptr", ps, depth, &q_u->server_name_ptr))
-               return False;
-       if(!smb_io_unistr2("server_name", &q_u->server_name, q_u->server_name_ptr, ps, depth))
-               return False;
-               
-       if(!prs_align(ps))
-               return False;
-       if(!prs_uint32("info_level", ps, depth, &q_u->level))
-               return False;
-
-       if(!spool_io_printer_driver_info_level("", &q_u->info, ps, depth))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
-********************************************************************/  
-
-bool spoolss_io_r_addprinterdriver(const char *desc, SPOOL_R_ADDPRINTERDRIVER *q_u, prs_struct *ps, int depth)
-{
-       prs_debug(ps, depth, desc, "spoolss_io_r_addprinterdriver");
-       depth++;
-
-       if(!prs_werror("status", ps, depth, &q_u->status))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- ********************************************************************/  
-
-bool uni_2_asc_printer_info_2(const SPOOL_PRINTER_INFO_LEVEL_2 *uni,
-                              NT_PRINTER_INFO_LEVEL_2  *d)
-{
-       DEBUG(7,("Converting from UNICODE to ASCII\n"));
-       
-       d->attributes=uni->attributes;
-       d->priority=uni->priority;
-       d->default_priority=uni->default_priority;
-       d->starttime=uni->starttime;
-       d->untiltime=uni->untiltime;
-       d->status=uni->status;
-       d->cjobs=uni->cjobs;
-       
-       unistr2_to_ascii(d->servername, &uni->servername, sizeof(d->servername));
-       unistr2_to_ascii(d->printername, &uni->printername, sizeof(d->printername));
-       unistr2_to_ascii(d->sharename, &uni->sharename, sizeof(d->sharename));
-       unistr2_to_ascii(d->portname, &uni->portname, sizeof(d->portname));
-       unistr2_to_ascii(d->drivername, &uni->drivername, sizeof(d->drivername));
-       unistr2_to_ascii(d->comment, &uni->comment, sizeof(d->comment));
-       unistr2_to_ascii(d->location, &uni->location, sizeof(d->location));
-       unistr2_to_ascii(d->sepfile, &uni->sepfile, sizeof(d->sepfile));
-       unistr2_to_ascii(d->printprocessor, &uni->printprocessor, sizeof(d->printprocessor));
-       unistr2_to_ascii(d->datatype, &uni->datatype, sizeof(d->datatype));
-       unistr2_to_ascii(d->parameters, &uni->parameters, sizeof(d->parameters));
-
-       return True;
-}
-
 /*******************************************************************
 ********************************************************************/  
 
@@ -4619,170 +2828,6 @@ void free_job_info_2(JOB_INFO_2 *job)
         free_devmode(job->devmode);
 }
 
-#if 0  /* JERRY - not currently used but could be :-) */
-
-/*******************************************************************
- Deep copy a SPOOL_NOTIFY_INFO_DATA structure
- ******************************************************************/
-static bool copy_spool_notify_info_data(SPOOL_NOTIFY_INFO_DATA *dst, 
-                               SPOOL_NOTIFY_INFO_DATA *src, int n)
-{
-       int i;
-
-       memcpy(dst, src, sizeof(SPOOL_NOTIFY_INFO_DATA)*n);
-       
-       for (i=0; i<n; i++) {
-               int len;
-               uint16 *s = NULL;
-               
-               if (src->size != POINTER) 
-                       continue;
-               len = src->notify_data.data.length;
-               s = SMB_MALLOC_ARRAY(uint16, len);
-               if (s == NULL) {
-                       DEBUG(0,("copy_spool_notify_info_data: malloc() failed!\n"));
-                       return False;
-               }
-               
-               memcpy(s, src->notify_data.data.string, len*2);
-               dst->notify_data.data.string = s;
-       }
-       
-       return True;
-}
-
-/*******************************************************************
- Deep copy a SPOOL_NOTIFY_INFO structure
- ******************************************************************/
-static bool copy_spool_notify_info(SPOOL_NOTIFY_INFO *dst, SPOOL_NOTIFY_INFO *src)
-{
-       if (!dst) {
-               DEBUG(0,("copy_spool_notify_info: NULL destination pointer!\n"));
-               return False;
-       }
-               
-       dst->version = src->version;
-       dst->flags   = src->flags;
-       dst->count   = src->count;
-       
-       if (dst->count) 
-       {
-               dst->data = SMB_MALLOC_ARRAY(SPOOL_NOTIFY_INFO_DATA, dst->count);
-               
-               DEBUG(10,("copy_spool_notify_info: allocating space for [%d] PRINTER_NOTIFY_INFO_DATA entries\n",
-                       dst->count));
-
-               if (dst->data == NULL) {
-                       DEBUG(0,("copy_spool_notify_info: malloc() failed for [%d] entries!\n", 
-                               dst->count));
-                       return False;
-               }
-               
-               return (copy_spool_notify_info_data(dst->data, src->data, src->count));
-       }
-       
-       return True;
-}
-#endif /* JERRY */
-
-/*******************************************************************
- * init a structure.
- ********************************************************************/
-
-bool make_spoolss_q_reply_rrpcn(SPOOL_Q_REPLY_RRPCN *q_u, POLICY_HND *hnd,
-                               uint32 change_low, uint32 change_high,
-                               SPOOL_NOTIFY_INFO *info)
-{      
-       if (q_u == NULL)
-               return False;
-
-       memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
-
-       q_u->change_low=change_low;
-       q_u->change_high=change_high;
-
-       q_u->unknown0=0x0;
-       q_u->unknown1=0x0;
-
-       q_u->info_ptr=0x0FF0ADDE;
-
-       q_u->info.version=2;
-       
-       if (info->count) {
-               DEBUG(10,("make_spoolss_q_reply_rrpcn: [%d] PRINTER_NOTIFY_INFO_DATA\n",
-                       info->count));
-               q_u->info.version = info->version;
-               q_u->info.flags   = info->flags;
-               q_u->info.count   = info->count;
-               /* pointer field - be careful! */
-               q_u->info.data    = info->data;
-       }
-       else  {
-       q_u->info.flags=PRINTER_NOTIFY_INFO_DISCARDED;
-       q_u->info.count=0;
-       }
-
-       return True;
-}
-
-/*******************************************************************
- Parse a SPOOL_Q_REPLY_RRPCN structure.
-********************************************************************/  
-
-bool spoolss_io_q_reply_rrpcn(const char *desc, SPOOL_Q_REPLY_RRPCN *q_u, prs_struct *ps, int depth)
-{
-       prs_debug(ps, depth, desc, "spoolss_io_q_reply_rrpcn");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!smb_io_pol_hnd("printer handle",&q_u->handle,ps,depth))
-               return False;
-
-       if (!prs_uint32("change_low", ps, depth, &q_u->change_low))
-               return False;
-
-       if (!prs_uint32("change_high", ps, depth, &q_u->change_high))
-               return False;
-
-       if (!prs_uint32("unknown0", ps, depth, &q_u->unknown0))
-               return False;
-
-       if (!prs_uint32("unknown1", ps, depth, &q_u->unknown1))
-               return False;
-
-       if (!prs_uint32("info_ptr", ps, depth, &q_u->info_ptr))
-               return False;
-
-       if(q_u->info_ptr!=0)
-               if(!smb_io_notify_info(desc, &q_u->info, ps, depth))
-                       return False;
-               
-       return True;
-}
-
-/*******************************************************************
- Parse a SPOOL_R_REPLY_RRPCN structure.
-********************************************************************/  
-
-bool spoolss_io_r_reply_rrpcn(const char *desc, SPOOL_R_REPLY_RRPCN *r_u, prs_struct *ps, int depth)
-{              
-       prs_debug(ps, depth, desc, "spoolss_io_r_reply_rrpcn");
-       depth++;
-
-       if (!prs_align(ps))
-               return False;
-
-       if (!prs_uint32("unknown0", ps, depth, &r_u->unknown0))
-               return False;
-
-       if (!prs_werror("status", ps, depth, &r_u->status))
-               return False;
-
-       return True;            
-}
-
 /*******************************************************************
  * read a structure.
  ********************************************************************/  
@@ -5054,47 +3099,3 @@ bool make_spoolss_q_enumforms(SPOOL_Q_ENUMFORMS *q_u, POLICY_HND *handle,
 
        return True;
 }
-
-/*******************************************************************
- * init a structure.
- ********************************************************************/
-
-bool make_spoolss_q_getjob(SPOOL_Q_GETJOB *q_u, POLICY_HND *handle, 
-                          uint32 jobid, uint32 level, RPC_BUFFER *buffer,
-                          uint32 offered)
-{
-        memcpy(&q_u->handle, handle, sizeof(POLICY_HND));
-        q_u->jobid = jobid;
-        q_u->level = level;
-        q_u->buffer = buffer;
-        q_u->offered = offered;
-
-       return True;
-}
-
-/*******************************************************************
- * init a structure.
- ********************************************************************/
-
-bool make_spoolss_q_rffpcnex(SPOOL_Q_RFFPCNEX *q_u, POLICY_HND *handle,
-                            uint32 flags, uint32 options, const char *localmachine,
-                            uint32 printerlocal, SPOOL_NOTIFY_OPTION *option)
-{
-        memcpy(&q_u->handle, handle, sizeof(POLICY_HND));
-
-       q_u->flags = flags;
-       q_u->options = options;
-
-       q_u->localmachine_ptr = 1;
-
-       init_unistr2(&q_u->localmachine, localmachine, UNI_STR_TERMINATE);
-
-       q_u->printerlocal = printerlocal;
-
-       if (option)
-               q_u->option_ptr = 1;
-
-       q_u->option = option;
-
-       return True;
-}
index 697457888ee9af6b425ca70cb7ae1dd9ad883077..2f163a379fba9c3ef3fe3daf4e606ead5297fe47 100644 (file)
@@ -706,7 +706,7 @@ NTSTATUS _eventlog_WriteClusterEvents(pipes_struct *p, struct eventlog_WriteClus
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS _eventlog_GetLogIntormation(pipes_struct *p, struct eventlog_GetLogIntormation *r)
+NTSTATUS _eventlog_GetLogInformation(pipes_struct *p, struct eventlog_GetLogInformation *r)
 {
        p->rng_fault_state = True;
        return NT_STATUS_NOT_IMPLEMENTED;
index a38c7176650a6dcda71ee4611cf51e55b3e45c53..0c83144a908e81443e4954bcc941b26b7b8e342e 100644 (file)
@@ -990,13 +990,13 @@ NTSTATUS _netr_LogonSamLogon(pipes_struct *p,
                   this to challenge/response for the auth subsystem to chew
                   on */
        {
-               const uint8 *chal;
+               uint8_t chal[8];
 
                if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) {
                        return status;
                }
 
-               chal = auth_context->get_ntlm_challenge(auth_context);
+               auth_context->get_ntlm_challenge(auth_context, chal);
 
                if (!make_user_info_netlogon_interactive(&user_info,
                                                         nt_username, nt_domain,
index 6dead2d26491ee38e9adf14e73b59b082effbc33..33e89c8acbc600272b749a4de4b96c97c890c29c 100644 (file)
@@ -1171,13 +1171,12 @@ NTSTATUS np_open(TALLOC_CTX *mem_ctx, const char *name,
 struct np_write_state {
        struct event_context *ev;
        struct np_proxy_state *p;
-       const uint8_t *data;
-       size_t len;
+       struct iovec iov;
        ssize_t nwritten;
 };
 
 static void np_write_trigger(struct async_req *req);
-static void np_write_done(struct async_req *subreq);
+static void np_write_done(struct tevent_req *subreq);
 
 struct async_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
                                struct fake_file_handle *handle,
@@ -1218,8 +1217,8 @@ struct async_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
 
                state->ev = ev;
                state->p = p;
-               state->data = data;
-               state->len = len;
+               state->iov.iov_base = CONST_DISCARD(void *, data);
+               state->iov.iov_len = len;
 
                if (!async_req_enqueue(p->write_queue, ev, result,
                                       np_write_trigger)) {
@@ -1242,27 +1241,26 @@ static void np_write_trigger(struct async_req *req)
 {
        struct np_write_state *state = talloc_get_type_abort(
                req->private_data, struct np_write_state);
-       struct async_req *subreq;
+       struct tevent_req *subreq;
 
-       subreq = sendall_send(state, state->ev, state->p->fd, state->data,
-                             state->len, 0);
+       subreq = writev_send(state, state->ev, state->p->fd, &state->iov, 1);
        if (async_req_nomem(subreq, req)) {
                return;
        }
        subreq->async.fn = np_write_done;
-       subreq->async.priv = req;
+       subreq->async.private_data = req;
 }
 
-static void np_write_done(struct async_req *subreq)
+static void np_write_done(struct tevent_req *subreq)
 {
        struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
+               subreq->async.private_data, struct async_req);
        struct np_write_state *state = talloc_get_type_abort(
                req->private_data, struct np_write_state);
        ssize_t received;
        int err;
 
-       received = sendall_recv(subreq, &err);
+       received = writev_recv(subreq, &err);
        if (received < 0) {
                async_req_nterror(req, map_nt_error_from_unix(err));
                return;
@@ -1316,7 +1314,7 @@ struct np_read_state {
 };
 
 static void np_read_trigger(struct async_req *req);
-static void np_read_done(struct async_req *subreq);
+static void np_read_done(struct tevent_req *subreq);
 
 struct async_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
                               struct fake_file_handle *handle,
@@ -1393,28 +1391,28 @@ static void np_read_trigger(struct async_req *req)
 {
        struct np_read_state *state = talloc_get_type_abort(
                req->private_data, struct np_read_state);
-       struct async_req *subreq;
+       struct tevent_req *subreq;
 
-       subreq = read_pkt_send(state, state->ev, state->p->fd, RPC_HEADER_LEN,
-                              rpc_frag_more_fn, NULL);
+       subreq = read_packet_send(state, state->ev, state->p->fd,
+                                 RPC_HEADER_LEN, rpc_frag_more_fn, NULL);
        if (async_req_nomem(subreq, req)) {
                return;
        }
        subreq->async.fn = np_read_done;
-       subreq->async.priv = req;
+       subreq->async.private_data = req;
 }
 
-static void np_read_done(struct async_req *subreq)
+static void np_read_done(struct tevent_req *subreq)
 {
        struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
+               subreq->async.private_data, struct async_req);
        struct np_read_state *state = talloc_get_type_abort(
                req->private_data, struct np_read_state);
        ssize_t received;
        size_t thistime;
        int err;
 
-       received = read_pkt_recv(subreq, state->p, &state->p->msg, &err);
+       received = read_packet_recv(subreq, state->p, &state->p->msg, &err);
        TALLOC_FREE(subreq);
        if (received == -1) {
                async_req_nterror(req, map_nt_error_from_unix(err));
index 7bb71ab89f00a4ce166dbedf9c724ff223f3cf96..ee36f04c6d6c34133b8b24e1bb90c4015216f950 100644 (file)
@@ -161,27 +161,7 @@ static bool api_spoolss_deleteprinterdriver(pipes_struct *p)
 
 static bool api_spoolss_rffpcnex(pipes_struct *p)
 {
-       SPOOL_Q_RFFPCNEX q_u;
-       SPOOL_R_RFFPCNEX 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_rffpcnex("", &q_u, data, 0)) {
-               DEBUG(0,("spoolss_io_q_rffpcnex: unable to unmarshall SPOOL_Q_RFFPCNEX.\n"));
-               return False;
-       }
-
-       r_u.status = _spoolss_rffpcnex(p, &q_u, &r_u);
-
-       if (!spoolss_io_r_rffpcnex("", &r_u, rdata, 0)) {
-               DEBUG(0,("spoolss_io_r_rffpcnex: unable to marshall SPOOL_R_RFFPCNEX.\n"));
-               return False;
-       }
-
-       return True;
+       return proxy_spoolss_call(p, NDR_SPOOLSS_REMOTEFINDFIRSTPRINTERCHANGENOTIFYEX);
 }
 
 
@@ -198,30 +178,7 @@ static bool api_spoolss_rffpcnex(pipes_struct *p)
 
 static bool api_spoolss_rfnpcnex(pipes_struct *p)
 {
-       SPOOL_Q_RFNPCNEX q_u;
-       SPOOL_R_RFNPCNEX 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_rfnpcnex("", &q_u, data, 0)) {
-               DEBUG(0,("spoolss_io_q_rfnpcnex: unable to unmarshall SPOOL_Q_RFNPCNEX.\n"));
-               return False;
-       }
-
-       r_u.status = _spoolss_rfnpcnex(p, &q_u, &r_u);
-
-       if (!spoolss_io_r_rfnpcnex("", &r_u, rdata, 0)) {
-               SAFE_FREE(r_u.info.data);
-               DEBUG(0,("spoolss_io_r_rfnpcnex: unable to marshall SPOOL_R_RFNPCNEX.\n"));
-               return False;
-       }
-
-       SAFE_FREE(r_u.info.data);
-
-       return True;
+       return proxy_spoolss_call(p, NDR_SPOOLSS_ROUTERREFRESHPRINTERCHANGENOTIFY);
 }
 
 
index 7439fe51a50875513f28b6e25f79437a0cc8dffb..814f406e8702948eb6302bb48aeae24806278a33 100644 (file)
@@ -110,7 +110,7 @@ static int nt_printj_status(int v)
        case LPQ_DELETED:
                return JOB_STATUS_DELETED;
        case LPQ_BLOCKED:
-               return JOB_STATUS_BLOCKED;
+               return JOB_STATUS_BLOCKED_DEVQ;
        case LPQ_USER_INTERVENTION:
                return JOB_STATUS_USER_INTERVENTION;
        }
@@ -130,19 +130,6 @@ static int nt_printq_status(int v)
        return 0;
 }
 
-/****************************************************************************
- Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
-****************************************************************************/
-
-static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
-{
-       if (*pp == NULL)
-               return;
-
-       SAFE_FREE((*pp)->ctr.type);
-       SAFE_FREE(*pp);
-}
-
 /***************************************************************************
  Disconnect from the client
 ****************************************************************************/
@@ -215,8 +202,7 @@ static int printer_entry_destructor(Printer_entry *Printer)
        Printer->notify.options=0;
        Printer->notify.localmachine[0]='\0';
        Printer->notify.printerlocal=0;
-       free_spool_notify_option(&Printer->notify.option);
-       Printer->notify.option=NULL;
+       TALLOC_FREE(Printer->notify.option);
        Printer->notify.client_connected=False;
 
        free_nt_devicemode( &Printer->nt_devmode );
@@ -227,35 +213,6 @@ static int printer_entry_destructor(Printer_entry *Printer)
        return 0;
 }
 
-/****************************************************************************
- Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
-****************************************************************************/
-
-static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
-{
-       SPOOL_NOTIFY_OPTION *new_sp = NULL;
-
-       if (!sp)
-               return NULL;
-
-       new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
-       if (!new_sp)
-               return NULL;
-
-       *new_sp = *sp;
-
-       if (sp->ctr.count) {
-               new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
-
-               if (!new_sp->ctr.type) {
-                       SAFE_FREE(new_sp);
-                       return NULL;
-               }
-       }
-
-       return new_sp;
-}
-
 /****************************************************************************
   find printer index by handle
 ****************************************************************************/
@@ -633,7 +590,7 @@ static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
                                uint16 notify_field)
 {
-       SPOOL_NOTIFY_OPTION *option = p->notify.option;
+       struct spoolss_NotifyOption *option = p->notify.option;
        uint32 i, j;
 
        /*
@@ -655,13 +612,13 @@ static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
 
                /* Check match for notify_type */
 
-               if (option->ctr.type[i].type != notify_type)
+               if (option->types[i].type != notify_type)
                        continue;
 
                /* Check match for field */
 
-               for (j = 0; j < option->ctr.type[i].count; j++) {
-                       if (option->ctr.type[i].fields[j] == notify_field) {
+               for (j = 0; j < option->types[i].count; j++) {
+                       if (option->types[i].fields[j] == notify_field) {
                                return True;
                        }
                }
@@ -673,43 +630,93 @@ static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
        return False;
 }
 
-/* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
+#define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
+       _data->data.integer[0] = _integer; \
+       _data->data.integer[1] = 0;
+
+
+#define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
+       _data->data.string.string = talloc_strdup(mem_ctx, _p); \
+       if (!_data->data.string.string) {\
+               _data->data.string.size = 0; \
+       } \
+       _data->data.string.size = strlen_m_term(_p) * 2;
+
+#define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
+       _data->data.devmode.devmode = _devmode;
+
+#define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
+       _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
+       if (!_data->data.sd.sd) { \
+               _data->data.sd.sd_size = 0; \
+       } \
+       _data->data.sd.sd_size = _size;
+
+static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
+                                  struct tm *t,
+                                  const char **pp,
+                                  uint32_t *plen)
+{
+       struct spoolss_Time st;
+       uint32_t len = 16;
+       char *p;
+
+       if (!init_systemtime(&st, t)) {
+               return;
+       }
+
+       p = talloc_array(mem_ctx, char, len);
+       if (!p) {
+               return;
+       }
+
+       /*
+        * Systemtime must be linearized as a set of UINT16's.
+        * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
+        */
+
+       SSVAL(p, 0, st.year);
+       SSVAL(p, 2, st.month);
+       SSVAL(p, 4, st.day_of_week);
+       SSVAL(p, 6, st.day);
+       SSVAL(p, 8, st.hour);
+       SSVAL(p, 10, st.minute);
+       SSVAL(p, 12, st.second);
+       SSVAL(p, 14, st.millisecond);
+
+       *pp = p;
+       *plen = len;
+}
+
+/* Convert a notification message to a struct spoolss_Notify */
 
 static void notify_one_value(struct spoolss_notify_msg *msg,
-                            SPOOL_NOTIFY_INFO_DATA *data,
+                            struct spoolss_Notify *data,
                             TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = msg->notify.value[0];
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
 }
 
 static void notify_string(struct spoolss_notify_msg *msg,
-                         SPOOL_NOTIFY_INFO_DATA *data,
+                         struct spoolss_Notify *data,
                          TALLOC_CTX *mem_ctx)
 {
-       UNISTR2 unistr;
-
        /* The length of the message includes the trailing \0 */
 
-       init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
-
-       data->notify_data.data.length = msg->len * 2;
-       data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
-
-       if (!data->notify_data.data.string) {
-               data->notify_data.data.length = 0;
+       data->data.string.size = msg->len * 2;
+       data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
+       if (!data->data.string.string) {
+               data->data.string.size = 0;
                return;
        }
-
-       memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
 }
 
 static void notify_system_time(struct spoolss_notify_msg *msg,
-                              SPOOL_NOTIFY_INFO_DATA *data,
+                              struct spoolss_Notify *data,
                               TALLOC_CTX *mem_ctx)
 {
-       SYSTEMTIME systime;
-       prs_struct ps;
+       data->data.string.string = NULL;
+       data->data.string.size = 0;
 
        if (msg->len != sizeof(time_t)) {
                DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
@@ -717,42 +724,15 @@ static void notify_system_time(struct spoolss_notify_msg *msg,
                return;
        }
 
-       if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
-               DEBUG(5, ("notify_system_time: prs_init() failed\n"));
-               return;
-       }
-
-       if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
-               DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
-               prs_mem_free(&ps);
-               return;
-       }
-
-       if (!spoolss_io_system_time("", &ps, 0, &systime)) {
-               prs_mem_free(&ps);
-               return;
-       }
-
-       data->notify_data.data.length = prs_offset(&ps);
-       if (prs_offset(&ps)) {
-               data->notify_data.data.string = (uint16 *)
-                       TALLOC(mem_ctx, prs_offset(&ps));
-               if (!data->notify_data.data.string) {
-                       prs_mem_free(&ps);
-                       return;
-               }
-               prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
-       } else {
-               data->notify_data.data.string = NULL;
-       }
-
-       prs_mem_free(&ps);
+       init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
+                              &data->data.string.string,
+                              &data->data.string.size);
 }
 
 struct notify2_message_table {
        const char *name;
        void (*fn)(struct spoolss_notify_msg *msg,
-                  SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
+                  struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
 };
 
 static struct notify2_message_table printer_notify_table[] = {
@@ -966,9 +946,9 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
        /* loop over all printers */
 
        for (p = printers_list; p; p = p->next) {
-               SPOOL_NOTIFY_INFO_DATA *data;
-               uint32  data_len = 0;
-               uint32  id;
+               struct spoolss_Notify *notifies;
+               uint32_t count = 0;
+               uint32_t id;
                int     i;
 
                /* Is there notification on this handle? */
@@ -989,13 +969,11 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
 
                /* allocate the max entries possible */
 
-               data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
-               if (!data) {
+               notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
+               if (!notifies) {
                        return;
                }
 
-               ZERO_STRUCTP(data);
-
                /* build the array of change notifications */
 
                sending_msg_count = 0;
@@ -1044,17 +1022,17 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
                                }
                        }
 
-                       construct_info_data( &data[data_len], msg->type, msg->field, id );
+                       construct_info_data( &notifies[count], msg->type, msg->field, id );
 
                        switch(msg->type) {
                        case PRINTER_NOTIFY_TYPE:
                                if ( printer_notify_table[msg->field].fn )
-                                       printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
+                                       printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
                                break;
 
                        case JOB_NOTIFY_TYPE:
                                if ( job_notify_table[msg->field].fn )
-                                       job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
+                                       job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
                                break;
 
                        default:
@@ -1062,12 +1040,46 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
                                goto done;
                        }
 
-                       data_len++;
+                       count++;
                }
 
                if ( sending_msg_count ) {
-                       rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
-                                       data_len, data, p->notify.change, 0 );
+                       NTSTATUS status;
+                       WERROR werr;
+                       union spoolss_ReplyPrinterInfo info;
+                       struct spoolss_NotifyInfo info0;
+                       uint32_t reply_result;
+
+                       info0.version   = 0x2;
+                       info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
+                       info0.count     = count;
+                       info0.notifies  = notifies;
+
+                       info.info0 = &info0;
+
+                       status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
+                                                                    &p->notify.client_hnd,
+                                                                    p->notify.change, /* color */
+                                                                    p->notify.flags,
+                                                                    &reply_result,
+                                                                    0, /* reply_type, must be 0 */
+                                                                    info,
+                                                                    &werr);
+                       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
+                               DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
+                                       notify_cli_pipe->srv_name_slash,
+                                       win_errstr(werr)));
+                       }
+                       switch (reply_result) {
+                               case 0:
+                                       break;
+                               case PRINTER_NOTIFY_INFO_DISCARDED:
+                               case PRINTER_NOTIFY_INFO_DISCARDNOTED:
+                               case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
+                                       break;
+                               default:
+                                       break;
+                       }
                }
        }
 
@@ -2830,26 +2842,73 @@ static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
        return (W_ERROR_IS_OK(result));
 }
 
-/********************************************************************
- * _spoolss_rffpcnex
- * ReplyFindFirstPrinterChangeNotifyEx
+/****************************************************************
+ ****************************************************************/
+
+static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
+                                                            const struct spoolss_NotifyOption *r)
+{
+       struct spoolss_NotifyOption *option;
+       uint32_t i,k;
+
+       if (!r) {
+               return NULL;
+       }
+
+       option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
+       if (!option) {
+               return NULL;
+       }
+
+       *option = *r;
+
+       if (!option->count) {
+               return option;
+       }
+
+       option->types = talloc_zero_array(option,
+               struct spoolss_NotifyOptionType, option->count);
+       if (!option->types) {
+               talloc_free(option);
+               return NULL;
+       }
+
+       for (i=0; i < option->count; i++) {
+               option->types[i] = r->types[i];
+
+               if (option->types[i].count) {
+                       option->types[i].fields = talloc_zero_array(option,
+                               enum spoolss_Field, option->types[i].count);
+                       if (!option->types[i].fields) {
+                               talloc_free(option);
+                               return NULL;
+                       }
+                       for (k=0; k<option->types[i].count; k++) {
+                               option->types[i].fields[k] =
+                                       r->types[i].fields[k];
+                       }
+               }
+       }
+
+       return option;
+}
+
+/****************************************************************
+ * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
  *
  * before replying OK: status=0 a rpc call is made to the workstation
  * asking ReplyOpenPrinter
  *
  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
  * called from api_spoolss_rffpcnex
- ********************************************************************/
+****************************************************************/
 
-WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
+WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
+                                                    struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
 {
-       POLICY_HND *handle = &q_u->handle;
-       uint32 flags = q_u->flags;
-       uint32 options = q_u->options;
-       UNISTR2 *localmachine = &q_u->localmachine;
-       uint32 printerlocal = q_u->printerlocal;
+       POLICY_HND *handle = r->in.handle;
        int snum = -1;
-       SPOOL_NOTIFY_OPTION *option = q_u->option;
+       struct spoolss_NotifyOption *option = r->in.notify_options;
        struct sockaddr_storage client_ss;
 
        /* store the notify value in the printer struct */
@@ -2857,21 +2916,19 @@ WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNE
        Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
 
        if (!Printer) {
-               DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+               DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
+                       "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
                return WERR_BADFID;
        }
 
-       Printer->notify.flags=flags;
-       Printer->notify.options=options;
-       Printer->notify.printerlocal=printerlocal;
-
-       if (Printer->notify.option)
-               free_spool_notify_option(&Printer->notify.option);
+       Printer->notify.flags           = r->in.flags;
+       Printer->notify.options         = r->in.options;
+       Printer->notify.printerlocal    = r->in.printer_local;
 
-       Printer->notify.option=dup_spool_notify_option(option);
+       TALLOC_FREE(Printer->notify.option);
+       Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
 
-       unistr2_to_ascii(Printer->notify.localmachine, localmachine,
-                      sizeof(Printer->notify.localmachine));
+       fstrcpy(Printer->notify.localmachine, r->in.local_machine);
 
        /* Connect to the client machine and send a ReplyOpenPrinter */
 
@@ -2901,25 +2958,12 @@ WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNE
  ********************************************************************/
 
 void spoolss_notify_server_name(int snum,
-                                      SPOOL_NOTIFY_INFO_DATA *data,
+                                      struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       NT_PRINTER_INFO_LEVEL *printer,
                                       TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
 }
 
 /*******************************************************************
@@ -2927,14 +2971,11 @@ void spoolss_notify_server_name(int snum,
  ********************************************************************/
 
 void spoolss_notify_printer_name(int snum,
-                                       SPOOL_NOTIFY_INFO_DATA *data,
+                                       struct spoolss_Notify *data,
                                        print_queue_struct *queue,
                                        NT_PRINTER_INFO_LEVEL *printer,
                                        TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
        /* the notify name should not contain the \\server\ part */
        char *p = strrchr(printer->info_2->printername, '\\');
 
@@ -2944,17 +2985,7 @@ void spoolss_notify_printer_name(int snum,
                p++;
        }
 
-       len = rpcstr_push_talloc(mem_ctx, &temp, p);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
 }
 
 /*******************************************************************
@@ -2962,26 +2993,12 @@ void spoolss_notify_printer_name(int snum,
  ********************************************************************/
 
 void spoolss_notify_share_name(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
-
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
 }
 
 /*******************************************************************
@@ -2989,27 +3006,12 @@ void spoolss_notify_share_name(int snum,
  ********************************************************************/
 
 void spoolss_notify_port_name(int snum,
-                                    SPOOL_NOTIFY_INFO_DATA *data,
+                                    struct spoolss_Notify *data,
                                     print_queue_struct *queue,
                                     NT_PRINTER_INFO_LEVEL *printer,
                                     TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       /* even if it's strange, that's consistant in all the code */
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
 }
 
 /*******************************************************************
@@ -3018,25 +3020,12 @@ void spoolss_notify_port_name(int snum,
  ********************************************************************/
 
 void spoolss_notify_driver_name(int snum,
-                                      SPOOL_NOTIFY_INFO_DATA *data,
+                                      struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       NT_PRINTER_INFO_LEVEL *printer,
                                       TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
 }
 
 /*******************************************************************
@@ -3044,28 +3033,20 @@ void spoolss_notify_driver_name(int snum,
  ********************************************************************/
 
 void spoolss_notify_comment(int snum,
-                                  SPOOL_NOTIFY_INFO_DATA *data,
+                                  struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   NT_PRINTER_INFO_LEVEL *printer,
                                   TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       if (*printer->info_2->comment == '\0')
-               len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
-       else
-               len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
+       char *p;
 
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
+       if (*printer->info_2->comment == '\0') {
+               p = lp_comment(snum);
        } else {
-               data->notify_data.data.string = NULL;
+               p = printer->info_2->comment;
        }
+
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
 }
 
 /*******************************************************************
@@ -3074,25 +3055,12 @@ void spoolss_notify_comment(int snum,
  ********************************************************************/
 
 void spoolss_notify_location(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
 }
 
 /*******************************************************************
@@ -3101,14 +3069,13 @@ void spoolss_notify_location(int snum,
  ********************************************************************/
 
 static void spoolss_notify_devmode(int snum,
-                                  SPOOL_NOTIFY_INFO_DATA *data,
+                                  struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   NT_PRINTER_INFO_LEVEL *printer,
                                   TALLOC_CTX *mem_ctx)
 {
        /* for a dummy implementation we have to zero the fields */
-       data->notify_data.data.length = 0;
-       data->notify_data.data.string = NULL;
+       SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
 }
 
 /*******************************************************************
@@ -3116,25 +3083,12 @@ static void spoolss_notify_devmode(int snum,
  ********************************************************************/
 
 void spoolss_notify_sepfile(int snum,
-                                  SPOOL_NOTIFY_INFO_DATA *data,
+                                  struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   NT_PRINTER_INFO_LEVEL *printer,
                                   TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
 }
 
 /*******************************************************************
@@ -3143,25 +3097,12 @@ void spoolss_notify_sepfile(int snum,
  ********************************************************************/
 
 void spoolss_notify_print_processor(int snum,
-                                          SPOOL_NOTIFY_INFO_DATA *data,
+                                          struct spoolss_Notify *data,
                                           print_queue_struct *queue,
                                           NT_PRINTER_INFO_LEVEL *printer,
                                           TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
 }
 
 /*******************************************************************
@@ -3170,25 +3111,12 @@ void spoolss_notify_print_processor(int snum,
  ********************************************************************/
 
 void spoolss_notify_parameters(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
 }
 
 /*******************************************************************
@@ -3197,25 +3125,12 @@ void spoolss_notify_parameters(int snum,
  ********************************************************************/
 
 void spoolss_notify_datatype(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
 }
 
 /*******************************************************************
@@ -3225,13 +3140,14 @@ void spoolss_notify_datatype(int snum,
  ********************************************************************/
 
 static void spoolss_notify_security_desc(int snum,
-                                        SPOOL_NOTIFY_INFO_DATA *data,
+                                        struct spoolss_Notify *data,
                                         print_queue_struct *queue,
                                         NT_PRINTER_INFO_LEVEL *printer,
                                         TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
-       data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
+       SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
+                                         printer->info_2->secdesc_buf->sd_size,
+                                         printer->info_2->secdesc_buf->sd);
 }
 
 /*******************************************************************
@@ -3240,13 +3156,12 @@ static void spoolss_notify_security_desc(int snum,
  ********************************************************************/
 
 void spoolss_notify_attributes(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = printer->info_2->attributes;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
 }
 
 /*******************************************************************
@@ -3254,13 +3169,12 @@ void spoolss_notify_attributes(int snum,
  ********************************************************************/
 
 static void spoolss_notify_priority(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = printer->info_2->priority;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
 }
 
 /*******************************************************************
@@ -3268,13 +3182,12 @@ static void spoolss_notify_priority(int snum,
  ********************************************************************/
 
 static void spoolss_notify_default_priority(int snum,
-                                           SPOOL_NOTIFY_INFO_DATA *data,
+                                           struct spoolss_Notify *data,
                                            print_queue_struct *queue,
                                            NT_PRINTER_INFO_LEVEL *printer,
                                            TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = printer->info_2->default_priority;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
 }
 
 /*******************************************************************
@@ -3282,13 +3195,12 @@ static void spoolss_notify_default_priority(int snum,
  ********************************************************************/
 
 static void spoolss_notify_start_time(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = printer->info_2->starttime;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
 }
 
 /*******************************************************************
@@ -3296,13 +3208,12 @@ static void spoolss_notify_start_time(int snum,
  ********************************************************************/
 
 static void spoolss_notify_until_time(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = printer->info_2->untiltime;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
 }
 
 /*******************************************************************
@@ -3310,7 +3221,7 @@ static void spoolss_notify_until_time(int snum,
  ********************************************************************/
 
 static void spoolss_notify_status(int snum,
-                                 SPOOL_NOTIFY_INFO_DATA *data,
+                                 struct spoolss_Notify *data,
                                  print_queue_struct *queue,
                                  NT_PRINTER_INFO_LEVEL *printer,
                                  TALLOC_CTX *mem_ctx)
@@ -3318,8 +3229,7 @@ static void spoolss_notify_status(int snum,
        print_status_struct status;
 
        print_queue_length(snum, &status);
-       data->notify_data.value[0]=(uint32) status.status;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
 }
 
 /*******************************************************************
@@ -3327,13 +3237,12 @@ static void spoolss_notify_status(int snum,
  ********************************************************************/
 
 void spoolss_notify_cjobs(int snum,
-                                SPOOL_NOTIFY_INFO_DATA *data,
+                                struct spoolss_Notify *data,
                                 print_queue_struct *queue,
                                 NT_PRINTER_INFO_LEVEL *printer,
                                 TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = print_queue_length(snum, NULL);
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
 }
 
 /*******************************************************************
@@ -3341,15 +3250,14 @@ void spoolss_notify_cjobs(int snum,
  ********************************************************************/
 
 static void spoolss_notify_average_ppm(int snum,
-                                      SPOOL_NOTIFY_INFO_DATA *data,
+                                      struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       NT_PRINTER_INFO_LEVEL *printer,
                                       TALLOC_CTX *mem_ctx)
 {
        /* always respond 8 pages per minutes */
        /* a little hard ! */
-       data->notify_data.value[0] = printer->info_2->averageppm;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
 }
 
 /*******************************************************************
@@ -3357,25 +3265,12 @@ static void spoolss_notify_average_ppm(int snum,
  ********************************************************************/
 
 static void spoolss_notify_username(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
 }
 
 /*******************************************************************
@@ -3383,13 +3278,12 @@ static void spoolss_notify_username(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_status(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=nt_printj_status(queue->status);
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
 }
 
 /*******************************************************************
@@ -3397,25 +3291,12 @@ static void spoolss_notify_job_status(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_name(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
 }
 
 /*******************************************************************
@@ -3423,7 +3304,7 @@ static void spoolss_notify_job_name(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_status_string(int snum,
-                                            SPOOL_NOTIFY_INFO_DATA *data,
+                                            struct spoolss_Notify *data,
                                             print_queue_struct *queue,
                                             NT_PRINTER_INFO_LEVEL *printer,
                                             TALLOC_CTX *mem_ctx)
@@ -3433,8 +3314,6 @@ static void spoolss_notify_job_status_string(int snum,
         */
 
        const char *p = "";
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
 
 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
        p = "unknown";
@@ -3455,17 +3334,7 @@ static void spoolss_notify_job_status_string(int snum,
        }
 #endif /* NO LONGER NEEDED. */
 
-       len = rpcstr_push_talloc(mem_ctx, &temp, p);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
 }
 
 /*******************************************************************
@@ -3473,13 +3342,12 @@ static void spoolss_notify_job_status_string(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_time(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=0x0;
-       data->notify_data.value[1]=0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
 }
 
 /*******************************************************************
@@ -3487,39 +3355,37 @@ static void spoolss_notify_job_time(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_size(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=queue->size;
-       data->notify_data.value[1]=0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
 }
 
 /*******************************************************************
  * fill a notify_info_data with page info
  ********************************************************************/
 static void spoolss_notify_total_pages(int snum,
-                               SPOOL_NOTIFY_INFO_DATA *data,
+                               struct spoolss_Notify *data,
                                print_queue_struct *queue,
                                NT_PRINTER_INFO_LEVEL *printer,
                                TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=queue->page_count;
-       data->notify_data.value[1]=0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
 }
 
 /*******************************************************************
  * fill a notify_info_data with pages printed info.
  ********************************************************************/
 static void spoolss_notify_pages_printed(int snum,
-                               SPOOL_NOTIFY_INFO_DATA *data,
+                               struct spoolss_Notify *data,
                                print_queue_struct *queue,
                                NT_PRINTER_INFO_LEVEL *printer,
                                TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=0;  /* Add code when back-end tracks this */
-       data->notify_data.value[1]=0;
+       /* Add code when back-end tracks this */
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
 }
 
 /*******************************************************************
@@ -3527,13 +3393,12 @@ static void spoolss_notify_pages_printed(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_position(int snum,
-                                       SPOOL_NOTIFY_INFO_DATA *data,
+                                       struct spoolss_Notify *data,
                                        print_queue_struct *queue,
                                        NT_PRINTER_INFO_LEVEL *printer,
                                        TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=queue->job;
-       data->notify_data.value[1]=0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
 }
 
 /*******************************************************************
@@ -3541,53 +3406,27 @@ static void spoolss_notify_job_position(int snum,
  ********************************************************************/
 
 static void spoolss_notify_submitted_time(int snum,
-                                         SPOOL_NOTIFY_INFO_DATA *data,
+                                         struct spoolss_Notify *data,
                                          print_queue_struct *queue,
                                          NT_PRINTER_INFO_LEVEL *printer,
                                          TALLOC_CTX *mem_ctx)
 {
-       struct tm *t;
-       uint32 len;
-       SYSTEMTIME st;
-       char *p;
+       data->data.string.string = NULL;
+       data->data.string.size = 0;
 
-       t=gmtime(&queue->time);
+       init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
+                              &data->data.string.string,
+                              &data->data.string.size);
 
-       len = sizeof(SYSTEMTIME);
-
-       data->notify_data.data.length = len;
-       data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
-
-       if (!data->notify_data.data.string) {
-               data->notify_data.data.length = 0;
-               return;
-       }
-
-       make_systemtime(&st, t);
-
-       /*
-        * Systemtime must be linearized as a set of UINT16's.
-        * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
-        */
-
-       p = (char *)data->notify_data.data.string;
-       SSVAL(p, 0, st.year);
-       SSVAL(p, 2, st.month);
-       SSVAL(p, 4, st.dayofweek);
-       SSVAL(p, 6, st.day);
-       SSVAL(p, 8, st.hour);
-        SSVAL(p, 10, st.minute);
-       SSVAL(p, 12, st.second);
-       SSVAL(p, 14, st.milliseconds);
 }
 
 struct s_notify_info_data_table
 {
-       uint16 type;
-       uint16 field;
+       enum spoolss_NotifyType type;
+       enum spoolss_Field field;
        const char *name;
-       uint32 size;
-       void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
+       enum spoolss_NotifyTable variable_type;
+       void (*fn) (int snum, struct spoolss_Notify *data,
                    print_queue_struct *queue,
                    NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
 };
@@ -3598,86 +3437,70 @@ struct s_notify_info_data_table
 
 static const struct s_notify_info_data_table notify_info_data_table[] =
 {
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_STRING,   spoolss_notify_server_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_STRING,   spoolss_notify_printer_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_STRING,   spoolss_notify_share_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_STRING,   spoolss_notify_port_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_STRING,   spoolss_notify_driver_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_STRING,   spoolss_notify_comment },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_STRING,   spoolss_notify_location },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_POINTER,   spoolss_notify_devmode },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_STRING,   spoolss_notify_sepfile },
-{ 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_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 },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_start_time },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_until_time },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_ONE_VALUE, spoolss_notify_status },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_POINTER,   NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_POINTER,   NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_POINTER,   NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_POINTER,   NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_POINTER,   NULL },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_STRING,   spoolss_notify_printer_name },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_STRING,   spoolss_notify_server_name },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_STRING,   spoolss_notify_port_name },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_STRING,   spoolss_notify_username },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_STRING,   spoolss_notify_username },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_STRING,   spoolss_notify_datatype },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_STRING,   spoolss_notify_print_processor },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_STRING,   spoolss_notify_parameters },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_STRING,   spoolss_notify_driver_name },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_POINTER,   spoolss_notify_devmode },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_ONE_VALUE, spoolss_notify_job_status },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_STRING,   spoolss_notify_job_status_string },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_POINTER,   NULL },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_STRING,   spoolss_notify_job_name },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_ONE_VALUE, spoolss_notify_priority },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_ONE_VALUE, spoolss_notify_job_position },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_POINTER,   spoolss_notify_submitted_time },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_start_time },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_until_time },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_ONE_VALUE, spoolss_notify_job_time },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
-{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_ONE_VALUE, spoolss_notify_job_size },
-{ PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
+{ JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
 };
 
 /*******************************************************************
- Return the size of info_data structure.
+ Return the variable_type of info_data structure.
 ********************************************************************/
 
-static uint32 size_of_notify_info_data(uint16 type, uint16 field)
+static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
+                                                 enum spoolss_Field field)
 {
        int i=0;
 
-       for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_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;
-                               case NOTIFY_STRING:
-                                       return 2;
-
-                               /* The only pointer notify data I have seen on
-                                  the wire is the submitted time and this has
-                                  the notify size set to 4. -tpot */
-
-                               case NOTIFY_POINTER:
-                                       return 4;
-
-                               case NOTIFY_SECDESC:
-                                       return 5;
-                       }
+       for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
+               if ( (notify_info_data_table[i].type == type) &&
+                    (notify_info_data_table[i].field == field) ) {
+                       return notify_info_data_table[i].variable_type;
                }
        }
 
@@ -3686,31 +3509,16 @@ static uint32 size_of_notify_info_data(uint16 type, uint16 field)
        return 0;
 }
 
-/*******************************************************************
- Return the type of notify_info_data.
-********************************************************************/
-
-static uint32 type_of_notify_info_data(uint16 type, uint16 field)
-{
-       uint32 i=0;
-
-       for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
-               if (notify_info_data_table[i].type == type &&
-                   notify_info_data_table[i].field == field)
-                       return notify_info_data_table[i].size;
-       }
-
-       return 0;
-}
-
 /****************************************************************************
 ****************************************************************************/
 
-static bool search_notify(uint16 type, uint16 field, int *value)
+static bool search_notify(enum spoolss_NotifyType type,
+                         enum spoolss_Field field,
+                         int *value)
 {
        int i;
 
-       for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
+       for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
                if (notify_info_data_table[i].type == type &&
                    notify_info_data_table[i].field == field &&
                    notify_info_data_table[i].fn != NULL) {
@@ -3725,16 +3533,15 @@ static bool search_notify(uint16 type, uint16 field, int *value)
 /****************************************************************************
 ****************************************************************************/
 
-void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
+void construct_info_data(struct spoolss_Notify *info_data,
+                        enum spoolss_NotifyType type,
+                        enum spoolss_Field field,
+                        int id)
 {
-       info_data->type     = type;
-       info_data->field    = field;
-       info_data->reserved = 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;
+       info_data->type                 = type;
+       info_data->field                = field;
+       info_data->variable_type        = variable_type_of_notify_info_data(type, field);
+       info_data->job_id               = id;
 }
 
 /*******************************************************************
@@ -3743,29 +3550,31 @@ void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16
  *
  ********************************************************************/
 
-static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
-                                         snum, SPOOL_NOTIFY_OPTION_TYPE
-                                         *option_type, uint32 id,
+static bool construct_notify_printer_info(Printer_entry *print_hnd,
+                                         struct spoolss_NotifyInfo *info,
+                                         int snum,
+                                         const struct spoolss_NotifyOptionType *option_type,
+                                         uint32_t id,
                                          TALLOC_CTX *mem_ctx)
 {
        int field_num,j;
-       uint16 type;
-       uint16 field;
+       enum spoolss_NotifyType type;
+       enum spoolss_Field field;
 
-       SPOOL_NOTIFY_INFO_DATA *current_data;
+       struct spoolss_Notify *current_data;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
        print_queue_struct *queue=NULL;
 
-       type=option_type->type;
+       type = option_type->type;
 
        DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
-               (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
+               (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
                option_type->count, lp_servicename(snum)));
 
        if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_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));
@@ -3773,13 +3582,16 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY
                if (!search_notify(type, field, &j) )
                        continue;
 
-               if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
+               info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
+                                                     struct spoolss_Notify,
+                                                     info->count + 1);
+               if (info->notifies == NULL) {
                        DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
                        free_a_printer(&printer, 2);
                        return False;
                }
 
-               current_data = &info->data[info->count];
+               current_data = &info->notifies[info->count];
 
                construct_info_data(current_data, type, field, id);
 
@@ -3803,24 +3615,24 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY
  ********************************************************************/
 
 static bool construct_notify_jobs_info(print_queue_struct *queue,
-                                      SPOOL_NOTIFY_INFO *info,
+                                      struct spoolss_NotifyInfo *info,
                                       NT_PRINTER_INFO_LEVEL *printer,
-                                      int snum, SPOOL_NOTIFY_OPTION_TYPE
-                                      *option_type, uint32 id,
+                                      int snum,
+                                      const struct spoolss_NotifyOptionType *option_type,
+                                      uint32_t id,
                                       TALLOC_CTX *mem_ctx)
 {
        int field_num,j;
-       uint16 type;
-       uint16 field;
-
-       SPOOL_NOTIFY_INFO_DATA *current_data;
+       enum spoolss_NotifyType type;
+       enum spoolss_Field field;
+       struct spoolss_Notify *current_data;
 
        DEBUG(4,("construct_notify_jobs_info\n"));
 
        type = option_type->type;
 
        DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
-               (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
+               (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
                option_type->count));
 
        for(field_num=0; field_num<option_type->count; field_num++) {
@@ -3829,12 +3641,15 @@ static bool construct_notify_jobs_info(print_queue_struct *queue,
                if (!search_notify(type, field, &j) )
                        continue;
 
-               if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
+               info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
+                                                     struct spoolss_Notify,
+                                                     info->count + 1);
+               if (info->notifies == NULL) {
                        DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
                        return False;
                }
 
-               current_data=&(info->data[info->count]);
+               current_data=&(info->notifies[info->count]);
 
                construct_info_data(current_data, type, field, id);
                notify_info_data_table[j].fn(snum, current_data, queue,
@@ -3876,25 +3691,26 @@ static bool construct_notify_jobs_info(print_queue_struct *queue,
  ********************************************************************/
 
 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
-                                     SPOOL_NOTIFY_INFO *info,
+                                     struct spoolss_NotifyInfo *info,
                                      TALLOC_CTX *mem_ctx)
 {
        int snum;
        Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
        int n_services=lp_numservices();
        int i;
-       SPOOL_NOTIFY_OPTION *option;
-       SPOOL_NOTIFY_OPTION_TYPE *option_type;
+       struct spoolss_NotifyOption *option;
+       struct spoolss_NotifyOptionType option_type;
 
        DEBUG(4,("printserver_notify_info\n"));
 
        if (!Printer)
                return WERR_BADFID;
 
-       option=Printer->notify.option;
-       info->version=2;
-       info->data=NULL;
-       info->count=0;
+       option = Printer->notify.option;
+
+       info->version   = 2;
+       info->notifies  = NULL;
+       info->count     = 0;
 
        /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
           sending a ffpcn() request first */
@@ -3903,15 +3719,15 @@ static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
                return WERR_BADFID;
 
        for (i=0; i<option->count; i++) {
-               option_type=&(option->ctr.type[i]);
+               option_type = option->types[i];
 
-               if (option_type->type!=PRINTER_NOTIFY_TYPE)
+               if (option_type.type != PRINTER_NOTIFY_TYPE)
                        continue;
 
                for (snum=0; snum<n_services; snum++)
                {
                        if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
-                               construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
+                               construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
                }
        }
 
@@ -3940,15 +3756,15 @@ static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
  *
  ********************************************************************/
 
-static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
+static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
                                  TALLOC_CTX *mem_ctx)
 {
        int snum;
        Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
        int i;
        uint32 id;
-       SPOOL_NOTIFY_OPTION *option;
-       SPOOL_NOTIFY_OPTION_TYPE *option_type;
+       struct spoolss_NotifyOption *option;
+       struct spoolss_NotifyOptionType option_type;
        int count,j;
        print_queue_struct *queue=NULL;
        print_status_struct status;
@@ -3958,11 +3774,12 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY
        if (!Printer)
                return WERR_BADFID;
 
-       option=Printer->notify.option;
+       option = Printer->notify.option;
        id = 0x0;
-       info->version=2;
-       info->data=NULL;
-       info->count=0;
+
+       info->version   = 2;
+       info->notifies  = NULL;
+       info->count     = 0;
 
        /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
           sending a ffpcn() request first */
@@ -3973,12 +3790,12 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY
        get_printer_snum(p, hnd, &snum, NULL);
 
        for (i=0; i<option->count; i++) {
-               option_type=&option->ctr.type[i];
+               option_type = option->types[i];
 
-               switch ( option_type->type ) {
+               switch (option_type.type) {
                case PRINTER_NOTIFY_TYPE:
                        if(construct_notify_printer_info(Printer, info, snum,
-                                                        option_type, id,
+                                                        &option_type, id,
                                                         mem_ctx))
                                id--;
                        break;
@@ -3994,7 +3811,7 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY
                        for (j=0; j<count; j++) {
                                construct_notify_jobs_info(&queue[j], info,
                                                           printer, snum,
-                                                          option_type,
+                                                          &option_type,
                                                           queue[j].job,
                                                           mem_ctx);
                        }
@@ -4025,24 +3842,31 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY
        return WERR_OK;
 }
 
-/********************************************************************
- * spoolss_rfnpcnex
- ********************************************************************/
+/****************************************************************
+ _spoolss_RouterRefreshPrinterChangeNotify
+****************************************************************/
 
-WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
+WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
+                                                struct spoolss_RouterRefreshPrinterChangeNotify *r)
 {
-       POLICY_HND *handle = &q_u->handle;
-       SPOOL_NOTIFY_INFO *info = &r_u->info;
+       POLICY_HND *handle = r->in.handle;
+       struct spoolss_NotifyInfo *info;
 
        Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
        WERROR result = WERR_BADFID;
 
-       /* we always have a NOTIFY_INFO struct */
-       r_u->info_ptr=0x1;
+       /* we always have a spoolss_NotifyInfo struct */
+       info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
+       if (!info) {
+               result = WERR_NOMEM;
+               goto done;
+       }
+
+       *r->out.info = info;
 
        if (!Printer) {
-               DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
-                        OUR_HANDLE(handle)));
+               DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
+                       "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
                goto done;
        }
 
@@ -4061,11 +3885,13 @@ WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCN
        Printer->notify.fnpcn = True;
 
        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;
+               DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
+                       "Saving change value in request [%x]\n",
+                       r->in.change_low));
+               Printer->notify.change = r->in.change_low;
        }
 
-       /* just ignore the SPOOL_NOTIFY_OPTION */
+       /* just ignore the spoolss_NotifyOption */
 
        switch (Printer->printer_type) {
                case SPLHND_SERVER:
@@ -4527,10 +4353,10 @@ static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *p
                strupper_m(guid_str);
                init_unistr(&printer->guid, guid_str);
                SAFE_FREE(guid_str);
-               printer->action = SPOOL_DS_PUBLISH;
+               printer->action = DSPRINT_PUBLISH;
        } else {
                init_unistr(&printer->guid, "");
-               printer->action = SPOOL_DS_UNPUBLISH;
+               printer->action = DSPRINT_UNPUBLISH;
        }
 
        return True;
@@ -6772,8 +6598,7 @@ WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
        Printer->notify.options=0;
        Printer->notify.localmachine[0]='\0';
        Printer->notify.printerlocal=0;
-       if (Printer->notify.option)
-               free_spool_notify_option(&Printer->notify.option);
+       TALLOC_FREE(Printer->notify.option);
        Printer->notify.client_connected=False;
 
        return WERR_OK;
@@ -6793,6 +6618,10 @@ WERROR _spoolss_AddJob(pipes_struct *p,
        /* this is what a NT server returns for AddJob. AddJob must fail on
         * non-local printers */
 
+       if (r->in.level != 1) {
+               return WERR_UNKNOWN_LEVEL;
+       }
+
        return WERR_INVALID_PARAM;
 }
 
@@ -8233,45 +8062,106 @@ WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
+struct _spoolss_paths {
+       int type;
+       const char *share;
+       const char *dir;
+};
+
+enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
+
+static const struct _spoolss_paths spoolss_paths[]= {
+       { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
+       { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
+};
+
+static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
                                          const char *servername,
                                          const char *environment,
-                                         struct spoolss_DriverDirectoryInfo1 *info1,
-                                         uint32_t offered,
-                                         uint32_t *needed)
+                                         int component,
+                                         char **path)
 {
-       char *path = NULL;
        const char *pservername = NULL;
        const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
        const char *short_archi;
 
-       if (environment) {
+       *path = NULL;
+
+       /* environment may be empty */
+       if (environment && strlen(environment)) {
                long_archi = environment;
        }
 
-       pservername = canon_servername(servername);
+       /* servername may be empty */
+       if (servername && strlen(servername)) {
+               pservername = canon_servername(servername);
 
-       if ( !is_myname_or_ipaddr(pservername))
-               return WERR_INVALID_PARAM;
+               if (!is_myname_or_ipaddr(pservername)) {
+                       return WERR_INVALID_PARAM;
+               }
+       }
 
-       if (!(short_archi = get_short_archi(long_archi)))
+       if (!(short_archi = get_short_archi(long_archi))) {
                return WERR_INVALID_ENVIRONMENT;
+       }
 
-       path = talloc_asprintf(mem_ctx,
-                       "\\\\%s\\print$\\%s", pservername, short_archi);
-       if (!path) {
+       switch (component) {
+       case SPOOLSS_PRTPROCS_PATH:
+       case SPOOLSS_DRIVER_PATH:
+               if (pservername) {
+                       *path = talloc_asprintf(mem_ctx,
+                                       "\\\\%s\\%s\\%s",
+                                       pservername,
+                                       spoolss_paths[component].share,
+                                       short_archi);
+               } else {
+                       *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
+                                       SPOOLSS_DEFAULT_SERVER_PATH,
+                                       spoolss_paths[component].dir,
+                                       short_archi);
+               }
+               break;
+       default:
+               return WERR_INVALID_PARAM;
+       }
+
+       if (!*path) {
                return WERR_NOMEM;
        }
 
+       return WERR_OK;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
+                                         const char *servername,
+                                         const char *environment,
+                                         struct spoolss_DriverDirectoryInfo1 *r,
+                                         uint32_t offered,
+                                         uint32_t *needed)
+{
+       WERROR werr;
+       char *path = NULL;
+
+       werr = compose_spoolss_server_path(mem_ctx,
+                                          servername,
+                                          environment,
+                                          SPOOLSS_DRIVER_PATH,
+                                          &path);
+       if (!W_ERROR_IS_OK(werr)) {
+               return werr;
+       }
+
        DEBUG(4,("printer driver directory: [%s]\n", path));
 
-       info1->directory_name = path;
+       r->directory_name = path;
 
-       *needed += ndr_size_spoolss_DriverDirectoryInfo1(info1, NULL, 0);
+       *needed += ndr_size_spoolss_DriverDirectoryInfo1(r, NULL, 0);
 
        if (*needed > offered) {
                talloc_free(path);
-               ZERO_STRUCTP(info1);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -8293,28 +8183,21 @@ WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
                return WERR_INVALID_PARAM;
        }
 
-       if (r->in.offered > MAX_RPC_DATA_SIZE) {
-               return WERR_INVALID_PARAM;
-       }
-
-       DEBUG(4,("_spoolss_GetPrinterDriverDirectory\n"));
+       DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
+               r->in.level));
 
        *r->out.needed = 0;
 
-       switch (r->in.level) {
-       case 1:
-               werror = getprinterdriverdir_level_1(p->mem_ctx,
-                                                    r->in.server,
-                                                    r->in.environment,
-                                                    &r->out.info->info1,
-                                                    r->in.offered,
-                                                    r->out.needed);
-               if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
-                       TALLOC_FREE(r->out.info);
-               }
-               break;
-       default:
-               return WERR_UNKNOWN_LEVEL;
+       /* r->in.level is ignored */
+
+       werror = getprinterdriverdir_level_1(p->mem_ctx,
+                                            r->in.server,
+                                            r->in.environment,
+                                            &r->out.info->info1,
+                                            r->in.offered,
+                                            r->out.needed);
+       if (!W_ERROR_IS_OK(werror)) {
+               TALLOC_FREE(r->out.info);
        }
 
        return werror;
@@ -9902,36 +9785,30 @@ done:
 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
                                                 const char *servername,
                                                 const char *environment,
-                                                struct spoolss_PrintProcessorDirectoryInfo1 *info1,
+                                                struct spoolss_PrintProcessorDirectoryInfo1 *r,
                                                 uint32_t offered,
                                                 uint32_t *needed)
 {
-       const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
-       const char *short_archi;
-
-       if (environment) {
-               long_archi = environment;
-       }
+       WERROR werr;
+       char *path = NULL;
 
-       short_archi = get_short_archi(long_archi);
-       if (!short_archi) {
-               return WERR_INVALID_ENVIRONMENT;
+       werr = compose_spoolss_server_path(mem_ctx,
+                                          servername,
+                                          environment,
+                                          SPOOLSS_PRTPROCS_PATH,
+                                          &path);
+       if (!W_ERROR_IS_OK(werr)) {
+               return werr;
        }
 
-       /* I think this should look like this - gd
-       info1->directory_name = talloc_asprintf(mem_ctx,
-               "C:\\WINNT\\System32\\spool\\PRTPROCS\\%s", short_archi);
-       */
-       info1->directory_name = talloc_strdup(mem_ctx,
-               "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
+       DEBUG(4,("print processor directory: [%s]\n", path));
 
-       if (!info1->directory_name) {
-               return WERR_NOMEM;
-       }
+       r->directory_name = path;
 
-       *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(info1, NULL, 0);
+       *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(r, NULL, 0);
 
        if (*needed > offered) {
+               talloc_free(path);
                return WERR_INSUFFICIENT_BUFFER;
        }
 
@@ -9953,28 +9830,21 @@ WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
                return WERR_INVALID_PARAM;
        }
 
-       if (r->in.offered > MAX_RPC_DATA_SIZE) {
-               return WERR_INVALID_PARAM;
-       }
-
-       DEBUG(5,("_spoolss_GetPrintProcessorDirectory\n"));
+       DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
+               r->in.level));
 
        *r->out.needed = 0;
 
-       switch (r->in.level) {
-       case 1:
-               result = getprintprocessordirectory_level_1(p->mem_ctx,
-                                                           r->in.server,
-                                                           r->in.environment,
-                                                           &r->out.info->info1,
-                                                           r->in.offered,
-                                                           r->out.needed);
-               if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
-                       TALLOC_FREE(r->out.info);
-               }
-               break;
-       default:
-               result = WERR_UNKNOWN_LEVEL;
+       /* r->in.level is ignored */
+
+       result = getprintprocessordirectory_level_1(p->mem_ctx,
+                                                   r->in.server,
+                                                   r->in.environment,
+                                                   &r->out.info->info1,
+                                                   r->in.offered,
+                                                   r->out.needed);
+       if (!W_ERROR_IS_OK(result)) {
+               TALLOC_FREE(r->out.info);
        }
 
        return result;
@@ -10761,17 +10631,6 @@ WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_RemoteFindFirstPrinterChangeNotifyEx
-****************************************************************/
-
-WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
-                                                    struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_RouterReplyPrinterEx
 ****************************************************************/
@@ -10783,17 +10642,6 @@ WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _dcesrv_spoolss_RouterRefreshPrinterChangeNotify
-****************************************************************/
-
-WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
-                                                struct spoolss_RouterRefreshPrinterChangeNotify *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_44
 ****************************************************************/
index 33bf3d0098af555a15f7607c834cc199ea6a33a9..b90a189f7e3fcb14361af9caedcc2f9d0b7197a7 100644 (file)
@@ -139,7 +139,7 @@ static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx )
        SEC_ACE ace[2];
        size_t i = 0;
        SEC_DESC *sd;
-       SEC_ACL *acl;
+       SEC_ACL *theacl;
        size_t sd_size;
 
        /* basic access for Everyone */
@@ -155,12 +155,12 @@ static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx )
 
        /* create the security descriptor */
 
-       if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
+       if ( !(theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
                return NULL;
 
        if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
                                  SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
-                                 acl, &sd_size)) )
+                                 theacl, &sd_size)) )
                return NULL;
 
        return sd;
index e212452e5d64634f7c757303a8c7469aa0c5537b..d839bf426329271344fe289aa6ce28f280cf7cef 100644 (file)
@@ -454,7 +454,7 @@ static NTSTATUS cmd_eventlog_loginfo(struct rpc_pipe_client *cli,
                return status;
        }
 
-       status = rpccli_eventlog_GetLogIntormation(cli, mem_ctx,
+       status = rpccli_eventlog_GetLogInformation(cli, mem_ctx,
                                                   &handle,
                                                   0, /* level */
                                                   buffer,
@@ -472,7 +472,7 @@ static NTSTATUS cmd_eventlog_loginfo(struct rpc_pipe_client *cli,
                goto done;
        }
 
-       status = rpccli_eventlog_GetLogIntormation(cli, mem_ctx,
+       status = rpccli_eventlog_GetLogInformation(cli, mem_ctx,
                                                   &handle,
                                                   0, /* level */
                                                   buffer,
index 9955d2d3fa4f94214e330b28900b150c1c9366aa..45df48801848df83db4e26288a29ca08ef7408f2 100644 (file)
@@ -1107,6 +1107,49 @@ static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli,
        return status;
 }
 
+static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli,
+                                         TALLOC_CTX *mem_ctx, int argc,
+                                         const char **argv)
+{
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       struct netr_Authenticator credential;
+       struct netr_Authenticator return_authenticator;
+       union netr_Capabilities capabilities;
+       uint32_t level = 1;
+
+       if (argc > 2) {
+               fprintf(stderr, "Usage: %s <level>\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       if (argc == 2) {
+               level = atoi(argv[1]);
+       }
+
+#if 0
+       netlogon_creds_client_step(cli->dc, &credential);
+#else
+       ZERO_STRUCT(credential);
+#endif
+
+       status = rpccli_netr_LogonGetCapabilities(cli, mem_ctx,
+                                                 cli->desthost,
+                                                 global_myname(),
+                                                 &credential,
+                                                 &return_authenticator,
+                                                 level,
+                                                 &capabilities);
+#if 0
+       if (!netlogon_creds_client_check(cli->dc,
+                                        &return_authenticator.cred)) {
+               DEBUG(0,("credentials chain check failed\n"));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+#endif
+
+       return status;
+}
+
 /* List of commands exported by this module */
 
 struct cmd_set netlogon_commands[] = {
@@ -1134,6 +1177,7 @@ struct cmd_set netlogon_commands[] = {
        { "netrenumtrusteddomainsex", RPC_RTYPE_WERROR, NULL, cmd_netlogon_enumtrusteddomainsex, &ndr_table_netlogon.syntax_id, NULL, "Enumerate trusted domains",     "" },
        { "getdcsitecoverage", RPC_RTYPE_WERROR, NULL, cmd_netlogon_getdcsitecoverage, &ndr_table_netlogon.syntax_id, NULL, "Get the Site-Coverage from a DC",     "" },
        { "database_redo", RPC_RTYPE_NTSTATUS, cmd_netlogon_database_redo, NULL, &ndr_table_netlogon.syntax_id, NULL, "Replicate single object from a DC",     "" },
+       { "capabilities", RPC_RTYPE_NTSTATUS, cmd_netlogon_capabilities, NULL, &ndr_table_netlogon.syntax_id, NULL, "Return Capabilities",     "" },
 
        { NULL }
 };
index 31977e955467c8db6b2bb9b6a985b829e486c3c8..936c2081f3676e01bf42c8d9f0427742d77d45e5 100644 (file)
@@ -789,7 +789,6 @@ static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli,
        struct samr_SamArray *dom_users = NULL;
        uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
        uint32 acb_mask = ACB_NORMAL;
-       bool got_connect_pol = False, got_domain_pol = False;
 
        if ((argc < 1) || (argc > 3)) {
                printf("Usage: %s [access_mask] [acb_mask]\n", argv[0]);
@@ -811,8 +810,6 @@ static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       got_connect_pol = True;
-
        /* Get domain policy handle */
 
        result = rpccli_samr_OpenDomain(cli, mem_ctx,
@@ -824,8 +821,6 @@ static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       got_domain_pol = True;
-
        /* Enumerate domain users */
 
        start_idx = 0;
@@ -852,10 +847,10 @@ static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli,
        } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
 
  done:
-       if (got_domain_pol)
+       if (is_valid_policy_hnd(&domain_pol))
                rpccli_samr_Close(cli, mem_ctx, &domain_pol);
 
-       if (got_connect_pol)
+       if (is_valid_policy_hnd(&connect_pol))
                rpccli_samr_Close(cli, mem_ctx, &connect_pol);
 
        return result;
@@ -872,7 +867,6 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli,
        uint32 start_idx, size, num_dom_groups, i;
        uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
        struct samr_SamArray *dom_groups = NULL;
-       bool got_connect_pol = False, got_domain_pol = False;
 
        if ((argc < 1) || (argc > 2)) {
                printf("Usage: %s [access_mask]\n", argv[0]);
@@ -891,8 +885,6 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       got_connect_pol = True;
-
        /* Get domain policy handle */
 
        result = rpccli_samr_OpenDomain(cli, mem_ctx,
@@ -904,8 +896,6 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       got_domain_pol = True;
-
        /* Enumerate domain groups */
 
        start_idx = 0;
@@ -930,10 +920,10 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli,
        } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
 
  done:
-       if (got_domain_pol)
+       if (is_valid_policy_hnd(&domain_pol))
                rpccli_samr_Close(cli, mem_ctx, &domain_pol);
 
-       if (got_connect_pol)
+       if (is_valid_policy_hnd(&connect_pol))
                rpccli_samr_Close(cli, mem_ctx, &connect_pol);
 
        return result;
@@ -950,7 +940,6 @@ static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli,
        uint32 start_idx, size, num_als_groups, i;
        uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
        struct samr_SamArray *als_groups = NULL;
-       bool got_connect_pol = False, got_domain_pol = False;
 
        if ((argc < 2) || (argc > 3)) {
                printf("Usage: %s builtin|domain [access mask]\n", argv[0]);
@@ -969,8 +958,6 @@ static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       got_connect_pol = True;
-
        /* Get domain policy handle */
 
        result = get_domain_handle(cli, mem_ctx, argv[1],
@@ -982,8 +969,6 @@ static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       got_domain_pol = True;
-
        /* Enumerate alias groups */
 
        start_idx = 0;
@@ -1008,10 +993,10 @@ static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli,
        } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
 
  done:
-       if (got_domain_pol)
+       if (is_valid_policy_hnd(&domain_pol))
                rpccli_samr_Close(cli, mem_ctx, &domain_pol);
 
-       if (got_connect_pol)
+       if (is_valid_policy_hnd(&connect_pol))
                rpccli_samr_Close(cli, mem_ctx, &connect_pol);
 
        return result;
@@ -1027,7 +1012,6 @@ static NTSTATUS cmd_samr_enum_domains(struct rpc_pipe_client *cli,
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        uint32 start_idx, size, num_entries, i;
        uint32 access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
-       bool got_connect_pol = false;
        struct samr_SamArray *sam = NULL;
 
        if ((argc < 1) || (argc > 2)) {
@@ -1049,8 +1033,6 @@ static NTSTATUS cmd_samr_enum_domains(struct rpc_pipe_client *cli,
                goto done;
        }
 
-       got_connect_pol = true;
-
        /* Enumerate alias groups */
 
        start_idx = 0;
@@ -1075,7 +1057,7 @@ static NTSTATUS cmd_samr_enum_domains(struct rpc_pipe_client *cli,
        } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES));
 
  done:
-       if (got_connect_pol) {
+       if (is_valid_policy_hnd(&connect_pol)) {
                rpccli_samr_Close(cli, mem_ctx, &connect_pol);
        }
 
index 944bac7731b465e43b26b839fe25bc45c57d8232..c68cf00530de09ffa2c0e9d00d124ceaa792a335 100644 (file)
@@ -283,12 +283,10 @@ static void display_print_info_3(PRINTER_INFO_3 *i3)
 /****************************************************************************
 ****************************************************************************/
 
-static void display_print_info_7(PRINTER_INFO_7 *i7)
+static void display_print_info7(struct spoolss_PrinterInfo7 *r)
 {
-       fstring guid = "";
-       rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
-       printf("\tguid:[%s]\n", guid);
-       printf("\taction:[0x%x]\n", i7->action);
+       printf("\tguid:[%s]\n", r->guid);
+       printf("\taction:[0x%x]\n", r->action);
 }
 
 
@@ -469,10 +467,13 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
 {
        POLICY_HND      pol;
        WERROR          result;
+       NTSTATUS        status;
        uint32          info_level = 2;
-       bool            opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
+       union spoolss_PrinterInfo info;
+       struct spoolss_SetPrinterInfoCtr info_ctr;
        const char      *printername, *comment = NULL;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct sec_desc_buf secdesc_ctr;
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s printername comment\n", argv[0]);
@@ -485,6 +486,9 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
                comment = argv[2];
        }
 
+       ZERO_STRUCT(devmode_ctr);
+       ZERO_STRUCT(secdesc_ctr);
+
        RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
        /* get a printer handle */
@@ -495,26 +499,34 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
        /* Get printer info */
-        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          info_level,
+                                          0,
+                                          &info);
         if (!W_ERROR_IS_OK(result))
                 goto done;
 
 
        /* Modify the comment. */
-       init_unistr(&ctr.printers_2->comment, comment);
-       ctr.printers_2->devmode = NULL;
-       ctr.printers_2->secdesc = NULL;
+       info.info2.comment = comment;
 
-       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+       info_ctr.level = 2;
+       info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
+
+       status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
+                                          &pol,
+                                          &info_ctr,
+                                          &devmode_ctr,
+                                          &secdesc_ctr,
+                                          0, /* command */
+                                          &result);
        if (W_ERROR_IS_OK(result))
                printf("Success in setting comment.\n");
 
  done:
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -529,11 +541,17 @@ static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
 {
        POLICY_HND      pol;
        WERROR          result;
+       NTSTATUS        status;
        uint32          info_level = 2;
-       bool            opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
+       union spoolss_PrinterInfo info;
        const char      *printername,
                        *new_printername = NULL;
+       struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct sec_desc_buf secdesc_ctr;
+
+       ZERO_STRUCT(devmode_ctr);
+       ZERO_STRUCT(secdesc_ctr);
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s printername new_printername\n", argv[0]);
@@ -556,25 +574,35 @@ static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
        /* Get printer info */
-        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          info_level,
+                                          0,
+                                          &info);
         if (!W_ERROR_IS_OK(result))
                 goto done;
 
        /* Modify the printername. */
-       init_unistr(&ctr.printers_2->printername, new_printername);
-       ctr.printers_2->devmode = NULL;
-       ctr.printers_2->secdesc = NULL;
-
-       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+       info.info2.printername = new_printername;
+       info.info2.devmode = NULL;
+       info.info2.secdesc = NULL;
+
+       info_ctr.level = info_level;
+       info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
+
+       status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
+                                          &pol,
+                                          &info_ctr,
+                                          &devmode_ctr,
+                                          &secdesc_ctr,
+                                          0, /* command */
+                                          &result);
        if (W_ERROR_IS_OK(result))
                printf("Success in setting printername.\n");
 
  done:
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -590,9 +618,8 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
        POLICY_HND      pol;
        WERROR          result;
        uint32          info_level = 1;
-       bool            opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
        const char      *printername;
+       union spoolss_PrinterInfo info;
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s <printername> [level]\n", argv[0]);
@@ -615,18 +642,19 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
        /* Get printer info */
 
-       result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          info_level,
+                                          0,
+                                          &info);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        /* Display printer info */
-
        switch (info_level) {
+#if 0 /* FIXME GD */
        case 0:
                display_print_info_0(ctr.printers_0);
                break;
@@ -639,16 +667,16 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
        case 3:
                display_print_info_3(ctr.printers_3);
                break;
+#endif
        case 7:
-               display_print_info_7(ctr.printers_7);
+               display_print_info7(&info.info7);
                break;
        default:
                printf("unknown info level %d\n", info_level);
                break;
        }
-
  done:
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -724,7 +752,6 @@ static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
 {
        POLICY_HND      pol;
        WERROR          result;
-       bool            opened_hnd = False;
        fstring         printername;
        const char *valuename;
        REGISTRY_VALUE value;
@@ -753,8 +780,6 @@ static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
        /* Get printer info */
 
        result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
@@ -769,7 +794,7 @@ static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
 
 
  done:
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -785,7 +810,6 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
        POLICY_HND      pol;
        WERROR          result;
        NTSTATUS        status;
-       bool            opened_hnd = False;
        fstring         printername;
        const char *valuename, *keyname;
        REGISTRY_VALUE value;
@@ -821,8 +845,6 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
        /* Get printer info */
 
        status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
@@ -870,7 +892,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
        display_reg_value(value);
 
  done:
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -986,6 +1008,68 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1)
        return;
 }
 
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_driver1(struct spoolss_DriverInfo1 *r)
+{
+       if (!r) {
+               return;
+       }
+
+       printf("Printer Driver Info 1:\n");
+       printf("\tDriver Name: [%s]\n\n", r->driver_name);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_driver2(struct spoolss_DriverInfo2 *r)
+{
+       if (!r) {
+               return;
+       }
+
+       printf("Printer Driver Info 2:\n");
+       printf("\tVersion: [%x]\n", r->version);
+       printf("\tDriver Name: [%s]\n", r->driver_name);
+       printf("\tArchitecture: [%s]\n", r->architecture);
+       printf("\tDriver Path: [%s]\n", r->driver_path);
+       printf("\tDatafile: [%s]\n", r->data_file);
+       printf("\tConfigfile: [%s]\n\n", r->config_file);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_driver3(struct spoolss_DriverInfo3 *r)
+{
+       int i;
+
+       if (!r) {
+               return;
+       }
+
+       printf("Printer Driver Info 3:\n");
+       printf("\tVersion: [%x]\n", r->version);
+       printf("\tDriver Name: [%s]\n", r->driver_name);
+       printf("\tArchitecture: [%s]\n", r->architecture);
+       printf("\tDriver Path: [%s]\n", r->driver_path);
+       printf("\tDatafile: [%s]\n", r->data_file);
+       printf("\tConfigfile: [%s]\n\n", r->config_file);
+       printf("\tHelpfile: [%s]\n\n", r->help_file);
+
+       for (i=0; r->dependent_files[i] != NULL; i++) {
+               printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
+       }
+
+       printf("\n");
+
+       printf("\tMonitorname: [%s]\n", r->monitor_name);
+       printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
+}
+
+
 /****************************************************************************
 ****************************************************************************/
 
@@ -996,11 +1080,12 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
        POLICY_HND      pol;
        WERROR          werror;
        uint32          info_level = 3;
-       bool            opened_hnd = False;
-       PRINTER_DRIVER_CTR      ctr;
        const char      *printername;
        uint32          i;
        bool            success = False;
+       union spoolss_DriverInfo info;
+       uint32_t server_major_version;
+       uint32_t server_minor_version;
 
        if ((argc == 1) || (argc > 3))
        {
@@ -1026,16 +1111,20 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
                return werror;
        }
 
-       opened_hnd = True;
-
        /* loop through and print driver info level for each architecture */
 
        for (i=0; archi_table[i].long_archi!=NULL; i++) {
 
-               werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level,
-                       archi_table[i].long_archi, archi_table[i].version,
-                       &ctr);
-
+               werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
+                                                         &pol,
+                                                         archi_table[i].long_archi,
+                                                         info_level,
+                                                         0, /* offered */
+                                                         archi_table[i].version,
+                                                         2,
+                                                         &info,
+                                                         &server_major_version,
+                                                         &server_minor_version);
                if (!W_ERROR_IS_OK(werror))
                        continue;
 
@@ -1047,13 +1136,13 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
 
                switch (info_level) {
                case 1:
-                       display_print_driver_1 (ctr.info1);
+                       display_print_driver1(&info.info1);
                        break;
                case 2:
-                       display_print_driver_2 (ctr.info2);
+                       display_print_driver2(&info.info2);
                        break;
                case 3:
-                       display_print_driver_3 (ctr.info3);
+                       display_print_driver3(&info.info3);
                        break;
                default:
                        printf("unknown info level %d\n", info_level);
@@ -1063,7 +1152,7 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
 
        /* Cleanup */
 
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        if ( success )
@@ -1219,7 +1308,9 @@ static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
+static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
+                              struct spoolss_AddDriverInfo3 *info,
+                              const char *arch)
 {
 
        int i;
@@ -1229,7 +1320,7 @@ void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
                if (strcmp(arch, archi_table[i].short_archi) == 0)
                {
                        info->version = archi_table[i].version;
-                       init_unistr (&info->architecture, archi_table[i].long_archi);
+                       info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
                        break;
                }
        }
@@ -1248,8 +1339,9 @@ void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
  Needed to handle the empty parameter string denoted by "NULL"
  *************************************************************************/
 
-static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest,
-                                char **saveptr)
+static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
+                               const char *delim, const char **dest,
+                               char **saveptr)
 {
        char    *ptr;
 
@@ -1260,70 +1352,80 @@ static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest,
           parameter because two consecutive delimiters
           will not return an empty string.  See man strtok(3)
           for details */
-       if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
+       if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
                ptr = NULL;
+       }
 
-       if (dest != NULL)
-               init_unistr(dest, ptr);
+       if (dest != NULL) {
+               *dest = talloc_strdup(mem_ctx, ptr);
+       }
 
        return ptr;
 }
 
 /********************************************************************************
- fill in the members of a DRIVER_INFO_3 struct using a character
+ fill in the members of a spoolss_AddDriverInfo3 struct using a character
  string in the form of
         <Long Printer Name>:<Driver File Name>:<Data File Name>:\
             <Config File Name>:<Help File Name>:<Language Monitor Name>:\
             <Default Data Type>:<Comma Separated list of Files>
  *******************************************************************************/
-static bool init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
-                                      char *args )
+
+static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
+                                    char *args)
 {
        char    *str, *str2;
-       uint32  len, i;
+       int count = 0;
        char *saveptr = NULL;
+       struct spoolss_StringArray *deps;
+       const char **file_array = NULL;
+       int i;
 
        /* fill in the UNISTR fields */
-       str = get_driver_3_param (args, ":", &info->name, &saveptr);
-       str = get_driver_3_param (NULL, ":", &info->driverpath, &saveptr);
-       str = get_driver_3_param (NULL, ":", &info->datafile, &saveptr);
-       str = get_driver_3_param (NULL, ":", &info->configfile, &saveptr);
-       str = get_driver_3_param (NULL, ":", &info->helpfile, &saveptr);
-       str = get_driver_3_param (NULL, ":", &info->monitorname, &saveptr);
-       str = get_driver_3_param (NULL, ":", &info->defaultdatatype, &saveptr);
+       str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
 
        /* <Comma Separated List of Dependent Files> */
        /* save the beginning of the string */
-       str2 = get_driver_3_param (NULL, ":", NULL, &saveptr);
+       str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
        str = str2;
 
        /* begin to strip out each filename */
        str = strtok_r(str, ",", &saveptr);
-       len = 0;
-       while (str != NULL)
-       {
-               /* keep a cumlative count of the str lengths */
-               len += strlen(str)+1;
+
+       /* no dependent files, we are done */
+       if (!str) {
+               return true;
+       }
+
+       deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
+       if (!deps) {
+               return false;
+       }
+
+       while (str != NULL) {
+               add_string_to_array(deps, str, &file_array, &count);
                str = strtok_r(NULL, ",", &saveptr);
        }
 
-       /* allocate the space; add one extra slot for a terminating NULL.
-          Each filename is NULL terminated and the end contains a double
-          NULL */
-       if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
-       {
-               DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
-               return False;
+       deps->string = talloc_zero_array(deps, const char *, count + 1);
+       if (!deps->string) {
+               return false;
        }
-       for (i=0; i<len; i++)
-       {
-               SSVAL(&info->dependentfiles[i], 0, str2[i]);
+
+       for (i=0; i < count; i++) {
+               deps->string[i] = file_array[i];
        }
-       info->dependentfiles[len] = '\0';
 
-       return True;
-}
+       r->dependent_files = deps;
 
+       return true;
+}
 
 /****************************************************************************
 ****************************************************************************/
@@ -1333,11 +1435,11 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
                                              int argc, const char **argv)
 {
        WERROR result;
+       NTSTATUS status;
        uint32                  level = 3;
-       PRINTER_DRIVER_CTR      ctr;
-       DRIVER_INFO_3           info3;
+       struct spoolss_AddDriverInfoCtr info_ctr;
+       struct spoolss_AddDriverInfo3 info3;
        const char              *arch;
-       fstring                 driver_name;
        char                    *driver_args;
 
        /* parse the command arguments */
@@ -1352,15 +1454,16 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
             return WERR_OK;
         }
 
-       /* Fill in the DRIVER_INFO_3 struct */
+       /* Fill in the spoolss_AddDriverInfo3 struct */
        ZERO_STRUCT(info3);
-       if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
-       {
+
+       arch = cmd_spoolss_get_short_archi(argv[1]);
+       if (!arch) {
                printf ("Error Unknown architechture [%s]\n", argv[1]);
                return WERR_INVALID_PARAM;
        }
-       else
-               set_drv_info_3_env(&info3, arch);
+
+       set_drv_info_3_env(mem_ctx, &info3, arch);
 
        driver_args = talloc_strdup( mem_ctx, argv[2] );
        if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
@@ -1378,14 +1481,19 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
        }
 
 
-       ctr.info3 = &info3;
-       result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
+       info_ctr.level          = level;
+       info_ctr.info.info3     = &info3;
 
+       status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
+                                                cli->srv_name_slash,
+                                                &info_ctr,
+                                                &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               return ntstatus_to_werror(status);
+       }
        if (W_ERROR_IS_OK(result)) {
-               rpcstr_pull(driver_name, info3.name.buffer,
-                           sizeof(driver_name), -1, STR_TERMINATE);
                printf ("Printer Driver %s successfully installed.\n",
-                       driver_name);
+                       info3.driver_name);
        }
 
        return result;
@@ -1400,14 +1508,8 @@ static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
                                          int argc, const char **argv)
 {
        WERROR result;
-       NTSTATUS status;
        struct spoolss_SetPrinterInfoCtr info_ctr;
        struct spoolss_SetPrinterInfo2 info2;
-       struct policy_handle handle;
-       struct spoolss_DevmodeContainer devmode_ctr;
-       struct sec_desc_buf sd;
-       struct spoolss_UserLevelCtr userlevel_ctr;
-       struct spoolss_UserLevel1 level1;
 
        /* parse the command arguments */
        if (argc != 5)
@@ -1417,9 +1519,7 @@ static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
         }
 
        /* Fill in the DRIVER_INFO_2 struct */
-       ZERO_STRUCT(devmode_ctr);
        ZERO_STRUCT(info2);
-       ZERO_STRUCT(sd);
 
        info2.printername       = argv[1];
        info2.drivername        = argv[3];
@@ -1447,25 +1547,8 @@ static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
        info_ctr.level = 2;
        info_ctr.info.info2 = &info2;
 
-       level1.size             = 28; /* wild guess */
-       level1.build            = 1381;
-       level1.major            = 2;
-       level1.minor            = 0;
-       level1.processor        = 0;
-       level1.client           = global_myname();
-       level1.user             = cli->auth->user_name;
-
-       userlevel_ctr.level = 1;
-       userlevel_ctr.user_info.level1 = &level1;
-
-       status = rpccli_spoolss_AddPrinterEx(cli, mem_ctx,
-                                            cli->srv_name_slash,
-                                            &info_ctr,
-                                            &devmode_ctr,
-                                            &sd,
-                                            &userlevel_ctr,
-                                            &handle,
-                                            &result);
+       result = rpccli_spoolss_addprinterex(cli, mem_ctx,
+                                            &info_ctr);
        if (W_ERROR_IS_OK(result))
                printf ("Printer %s successfully installed.\n", argv[1]);
 
@@ -1481,11 +1564,16 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
 {
        POLICY_HND              pol;
        WERROR                  result;
+       NTSTATUS                status;
        uint32                  level = 2;
-       bool                    opened_hnd = False;
-       PRINTER_INFO_CTR        ctr;
-       PRINTER_INFO_2          info2;
        const char              *printername;
+       union spoolss_PrinterInfo info;
+       struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct sec_desc_buf secdesc_ctr;
+
+       ZERO_STRUCT(devmode_ctr);
+       ZERO_STRUCT(secdesc_ctr);
 
        /* parse the command arguments */
        if (argc != 3)
@@ -1505,15 +1593,13 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
        /* Get printer info */
 
-       ZERO_STRUCT (info2);
-       ctr.printers_2 = &info2;
-
-       result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          level,
+                                          0,
+                                          &info);
        if (!W_ERROR_IS_OK(result)) {
                printf ("Unable to retrieve printer information!\n");
                goto done;
@@ -1521,10 +1607,17 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
 
        /* Set the printer driver */
 
-       init_unistr(&ctr.printers_2->drivername, argv[2]);
-
-       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
-
+       info.info2.drivername = argv[2];
+       info_ctr.level = 2;
+       info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
+
+       status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
+                                          &pol,
+                                          &info_ctr,
+                                          &devmode_ctr,
+                                          &secdesc_ctr,
+                                          0, /* command */
+                                          &result);
        if (!W_ERROR_IS_OK(result)) {
                printf("SetPrinter call failed!\n");
                goto done;;
@@ -1535,7 +1628,7 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
 done:
        /* Cleanup */
 
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -1719,14 +1812,15 @@ static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        WERROR werror;
        NTSTATUS status;
        const char *printername;
-       bool got_handle = False;
        union spoolss_AddFormInfo info;
        struct spoolss_AddFormInfo1 info1;
+       struct spoolss_AddFormInfo2 info2;
+       uint32_t level = 1;
 
        /* Parse the command arguments */
 
-       if (argc != 3) {
-               printf ("Usage: %s <printer> <formname>\n", argv[0]);
+       if (argc < 3 || argc > 5) {
+               printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
                return WERR_OK;
         }
 
@@ -1741,32 +1835,58 @@ static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
-
        /* Dummy up some values for the form data */
 
-       info1.flags             = FORM_USER;
-       info1.form_name         = argv[2];
-       info1.size.width        = 100;
-       info1.size.height       = 100;
-       info1.area.left         = 0;
-       info1.area.top          = 10;
-       info1.area.right        = 20;
-       info1.area.bottom       = 30;
+       if (argc == 4) {
+               level = atoi(argv[3]);
+       }
 
-       info.info1 = &info1;
+       switch (level) {
+       case 1:
+               info1.flags             = FORM_USER;
+               info1.form_name         = argv[2];
+               info1.size.width        = 100;
+               info1.size.height       = 100;
+               info1.area.left         = 0;
+               info1.area.top          = 10;
+               info1.area.right        = 20;
+               info1.area.bottom       = 30;
+
+               info.info1 = &info1;
+
+               break;
+       case 2:
+               info2.flags             = FORM_USER;
+               info2.form_name         = argv[2];
+               info2.size.width        = 100;
+               info2.size.height       = 100;
+               info2.area.left         = 0;
+               info2.area.top          = 10;
+               info2.area.right        = 20;
+               info2.area.bottom       = 30;
+               info2.keyword           = argv[2];
+               info2.string_type       = SPOOLSS_FORM_STRING_TYPE_NONE;
+               info2.mui_dll           = NULL;
+               info2.ressource_id      = 0;
+               info2.display_name      = argv[2];
+               info2.lang_id           = 0;
+
+               info.info2 = &info2;
+
+               break;
+       }
 
        /* Add the form */
 
 
        status = rpccli_spoolss_AddForm(cli, mem_ctx,
                                        &handle,
-                                       1,
+                                       level,
                                        info,
                                        &werror);
 
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        return werror;
@@ -1782,7 +1902,6 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        WERROR werror;
        NTSTATUS status;
        const char *printername;
-       bool got_handle = False;
        union spoolss_AddFormInfo info;
        struct spoolss_AddFormInfo1 info1;
 
@@ -1804,8 +1923,6 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
-
        /* Dummy up some values for the form data */
 
        info1.flags             = FORM_PRINTER;
@@ -1829,7 +1946,7 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
                                        &werror);
 
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        return werror;
@@ -1891,6 +2008,28 @@ static void display_form_info1(struct spoolss_FormInfo1 *r)
 /****************************************************************************
 ****************************************************************************/
 
+static void display_form_info2(struct spoolss_FormInfo2 *r)
+{
+       printf("%s\n" \
+               "\tflag: %s (%d)\n" \
+               "\twidth: %d, length: %d\n" \
+               "\tleft: %d, right: %d, top: %d, bottom: %d\n",
+               r->form_name, get_form_flag(r->flags), r->flags,
+               r->size.width, r->size.height,
+               r->area.left, r->area.right,
+               r->area.top, r->area.bottom);
+       printf("\tkeyword: %s\n", r->keyword);
+       printf("\tstring_type: 0x%08x\n", r->string_type);
+       printf("\tmui_dll: %s\n", r->mui_dll);
+       printf("\tressource_id: 0x%08x\n", r->ressource_id);
+       printf("\tdisplay_name: %s\n", r->display_name);
+       printf("\tlang_id: %d\n", r->lang_id);
+       printf("\n");
+}
+
+/****************************************************************************
+****************************************************************************/
+
 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
@@ -1898,16 +2037,16 @@ static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        WERROR werror;
        NTSTATUS status;
        const char *printername;
-       bool got_handle = False;
        DATA_BLOB buffer;
        uint32_t offered = 0;
        union spoolss_FormInfo info;
        uint32_t needed;
+       uint32_t level = 1;
 
        /* Parse the command arguments */
 
-       if (argc != 3) {
-               printf ("Usage: %s <printer> <formname>\n", argv[0]);
+       if (argc < 3 || argc > 5) {
+               printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
                return WERR_OK;
         }
 
@@ -1922,26 +2061,28 @@ static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
+       if (argc == 4) {
+               level = atoi(argv[3]);
+       }
 
        /* Get the form */
 
        status = rpccli_spoolss_GetForm(cli, mem_ctx,
                                        &handle,
                                        argv[2],
-                                       1,
+                                       level,
                                        NULL,
                                        offered,
                                        &info,
                                        &needed,
                                        &werror);
        if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
-               buffer = data_blob_talloc(mem_ctx, NULL, needed);
+               buffer = data_blob_talloc_zero(mem_ctx, needed);
                offered = needed;
                status = rpccli_spoolss_GetForm(cli, mem_ctx,
                                                &handle,
                                                argv[2],
-                                               1,
+                                               level,
                                                &buffer,
                                                offered,
                                                &info,
@@ -1953,9 +2094,17 @@ static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
                return werror;
        }
 
-       display_form_info1(&info.info1);
+       switch (level) {
+       case 1:
+               display_form_info1(&info.info1);
+               break;
+       case 2:
+               display_form_info2(&info.info2);
+               break;
+       }
+
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        return werror;
@@ -1972,7 +2121,6 @@ static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
        WERROR werror;
        NTSTATUS status;
        const char *printername;
-       bool got_handle = False;
 
        /* Parse the command arguments */
 
@@ -1992,8 +2140,6 @@ static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
-
        /* Delete the form */
 
        status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
@@ -2005,7 +2151,7 @@ static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
        }
 
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        return werror;
@@ -2021,7 +2167,6 @@ static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
        POLICY_HND handle;
        WERROR werror;
        const char *printername;
-       bool got_handle = False;
        uint32 num_forms, level = 1, i;
        FORM_1 *forms;
 
@@ -2043,8 +2188,6 @@ static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
-
        /* Enumerate forms */
 
        werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
@@ -2061,7 +2204,7 @@ static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
        }
 
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        return werror;
@@ -2077,9 +2220,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
        WERROR result;
        const char *printername;
        POLICY_HND pol;
-       bool opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
-       PRINTER_INFO_0 info;
+       union spoolss_PrinterInfo info;
        REGISTRY_VALUE value;
        TALLOC_CTX *tmp_ctx = talloc_stackframe();
 
@@ -2127,17 +2268,16 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
-       ctr.printers_0 = &info;
-
-        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          0,
+                                          0,
+                                          &info);
         if (!W_ERROR_IS_OK(result))
                 goto done;
 
        printf("%s\n", current_timestring(tmp_ctx, True));
-       printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
+       printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
 
        /* Set the printer data */
 
@@ -2217,18 +2357,21 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
        }
        printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
 
-        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          0,
+                                          0,
+                                          &info);
         if (!W_ERROR_IS_OK(result))
                 goto done;
 
        printf("%s\n", current_timestring(tmp_ctx, True));
-       printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
+       printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
 
 done:
        /* cleanup */
        TALLOC_FREE(tmp_ctx);
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -2279,13 +2422,53 @@ static void display_job_info_2(JOB_INFO_2 *job)
 /****************************************************************************
 ****************************************************************************/
 
+static void display_job_info1(struct spoolss_JobInfo1 *r)
+{
+       printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
+              r->user_name, r->document_name, r->text_status, r->pages_printed,
+              r->total_pages);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_job_info2(struct spoolss_JobInfo2 *r)
+{
+       printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
+              r->position, r->job_id,
+              r->user_name, r->document_name, r->text_status, r->pages_printed,
+              r->total_pages, r->size);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_job_info3(struct spoolss_JobInfo3 *r)
+{
+       printf("jobid[%d], next_jobid[%d]\n",
+               r->job_id, r->next_job_id);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_job_info4(struct spoolss_JobInfo4 *r)
+{
+       printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
+              r->position, r->job_id,
+              r->user_name, r->document_name, r->text_status, r->pages_printed,
+              r->total_pages, r->size, r->size_high);
+}
+
+/****************************************************************************
+****************************************************************************/
+
 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
                                      TALLOC_CTX *mem_ctx, int argc,
                                      const char **argv)
 {
        WERROR result;
        uint32 level = 1, num_jobs, i;
-       bool got_hnd = False;
        const char *printername;
        POLICY_HND hnd;
        JOB_INFO_CTR ctr;
@@ -2309,8 +2492,6 @@ static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       got_hnd = True;
-
        /* Enumerate ports */
 
        result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
@@ -2334,12 +2515,89 @@ static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
        }
 
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd))
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+
+       return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
+                                 TALLOC_CTX *mem_ctx, int argc,
+                                 const char **argv)
+{
+       WERROR result;
+       const char *printername;
+       struct policy_handle hnd;
+       uint32_t job_id;
+       uint32_t level = 1;
+       union spoolss_JobInfo info;
+
+       if (argc < 3 || argc > 4) {
+               printf("Usage: %s printername job_id [level]\n", argv[0]);
+               return WERR_OK;
+       }
+
+       job_id = atoi(argv[2]);
+
+       if (argc == 4) {
+               level = atoi(argv[3]);
+       }
+
+       /* Open printer handle */
+
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
+
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &hnd);
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+       /* Enumerate ports */
+
+       result = rpccli_spoolss_getjob(cli, mem_ctx,
+                                      &hnd,
+                                      job_id,
+                                      level,
+                                      0,
+                                      &info);
+
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+       switch (level) {
+       case 1:
+               display_job_info1(&info.info1);
+               break;
+       case 2:
+               display_job_info2(&info.info2);
+               break;
+       case 3:
+               display_job_info3(&info.info3);
+               break;
+       case 4:
+               display_job_info4(&info.info4);
+               break;
+       default:
+               d_printf("unknown info level %d\n", level);
+               break;
+       }
+
+done:
+       if (is_valid_policy_hnd(&hnd)) {
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+       }
 
        return result;
 }
 
+
 /****************************************************************************
 ****************************************************************************/
 
@@ -2349,7 +2607,6 @@ static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
 {
        WERROR result;
        uint32 i=0, val_needed, data_needed;
-       bool got_hnd = False;
        const char *printername;
        POLICY_HND hnd;
 
@@ -2369,8 +2626,6 @@ static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       got_hnd = True;
-
        /* Enumerate data */
 
        result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
@@ -2388,7 +2643,7 @@ static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
                result = W_ERROR(ERRsuccess);
 
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
@@ -2403,7 +2658,6 @@ static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
 {
        WERROR result;
        uint32 i;
-       bool got_hnd = False;
        const char *printername;
        const char *keyname = NULL;
        POLICY_HND hnd;
@@ -2427,8 +2681,6 @@ static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       got_hnd = True;
-
        /* Enumerate subkeys */
 
        if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
@@ -2446,7 +2698,7 @@ static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
        TALLOC_FREE( ctr );
 
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
@@ -2460,7 +2712,6 @@ static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
                                             const char **argv)
 {
        WERROR result;
-       bool got_hnd = False;
        const char *printername;
        const char *keyname = NULL;
        POLICY_HND hnd;
@@ -2487,8 +2738,6 @@ static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       got_hnd = True;
-
        /* Enumerate subkeys */
 
        result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
@@ -2512,7 +2761,7 @@ done:
 
        SAFE_FREE(keylist);
 
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
@@ -2526,8 +2775,8 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
                                     const char **argv)
 {
        const char *printername;
+       const char *clientname;
        POLICY_HND hnd;
-       bool got_hnd = False;
        WERROR result;
        NTSTATUS status;
        struct spoolss_NotifyOption option;
@@ -2551,8 +2800,6 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
                goto done;
        }
 
-       got_hnd = True;
-
        /* Create spool options */
 
        option.version = 2;
@@ -2582,13 +2829,19 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
        }
        option.types[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
 
+       clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
+       if (!clientname) {
+               result = WERR_NOMEM;
+               goto done;
+       }
+
        /* Send rffpcnex */
 
        status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
                                                                     &hnd,
                                                                     0,
                                                                     0,
-                                                                    cli->srv_name_slash,
+                                                                    clientname,
                                                                     123,
                                                                     &option,
                                                                     &result);
@@ -2598,7 +2851,7 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
        }
 
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
@@ -2610,12 +2863,16 @@ done:
 static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
                              struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
 {
-       PRINTER_INFO_CTR ctr1, ctr2;
+       union spoolss_PrinterInfo info1, info2;
        WERROR werror;
        TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
 
        printf("Retrieving printer propertiesfor %s...", cli1->desthost);
-       werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
+       werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
+                                          hnd1,
+                                          2,
+                                          0,
+                                          &info1);
        if ( !W_ERROR_IS_OK(werror) ) {
                printf("failed (%s)\n", win_errstr(werror));
                talloc_destroy(mem_ctx);
@@ -2624,7 +2881,11 @@ static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
        printf("ok\n");
 
        printf("Retrieving printer properties for %s...", cli2->desthost);
-       werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
+       werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
+                                          hnd2,
+                                          2,
+                                          0,
+                                          &info2);
        if ( !W_ERROR_IS_OK(werror) ) {
                printf("failed (%s)\n", win_errstr(werror));
                talloc_destroy(mem_ctx);
@@ -2643,7 +2904,7 @@ static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
 static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
                                      struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
 {
-       PRINTER_INFO_CTR ctr1, ctr2;
+       union spoolss_PrinterInfo info1, info2;
        WERROR werror;
        TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
        SEC_DESC *sd1, *sd2;
@@ -2651,7 +2912,11 @@ static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *h
 
 
        printf("Retrieving printer security for %s...", cli1->desthost);
-       werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
+       werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
+                                          hnd1,
+                                          3,
+                                          0,
+                                          &info1);
        if ( !W_ERROR_IS_OK(werror) ) {
                printf("failed (%s)\n", win_errstr(werror));
                result = False;
@@ -2660,7 +2925,11 @@ static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *h
        printf("ok\n");
 
        printf("Retrieving printer security for %s...", cli2->desthost);
-       werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
+       werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
+                                          hnd2,
+                                          3,
+                                          0,
+                                          &info2);
        if ( !W_ERROR_IS_OK(werror) ) {
                printf("failed (%s)\n", win_errstr(werror));
                result = False;
@@ -2671,14 +2940,8 @@ static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *h
 
        printf("++ ");
 
-       if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
-               printf("NULL PRINTER_INFO_3!\n");
-               result = False;
-               goto done;
-       }
-
-       sd1 = ctr1.printers_3->secdesc;
-       sd2 = ctr2.printers_3->secdesc;
+       sd1 = info1.info3.secdesc;
+       sd2 = info2.info3.secdesc;
 
        if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
                printf("NULL secdesc!\n");
@@ -2809,6 +3072,7 @@ struct cmd_set spoolss_commands[] = {
        { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &syntax_spoolss, NULL, "Enumerate printer data for a key",    "" },
        { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &syntax_spoolss, NULL, "Enumerate printer keys",              "" },
        { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &syntax_spoolss, NULL, "Enumerate print jobs",                "" },
+       { "getjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job,            &syntax_spoolss, NULL, "Get print job",                       "" },
        { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &syntax_spoolss, NULL, "Enumerate printer ports",             "" },
        { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
        { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &syntax_spoolss, NULL, "Enumerate printers",                  "" },
index 6d1b5d5b952dde365c0c0d73ba0a8b052311755b..7a4b90c7cf523e38d8027f1382143dafcebc5050 100644 (file)
@@ -91,7 +91,7 @@ static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx )
        SEC_ACE ace[4];
        size_t i = 0;
        SEC_DESC *sd = NULL;
-       SEC_ACL *acl = NULL;
+       SEC_ACL *theacl = NULL;
        size_t sd_size;
 
        /* basic access for Everyone */
@@ -109,12 +109,12 @@ static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx )
 
        /* create the security descriptor */
 
-       if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
+       if ( !(theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
                return NULL;
 
        if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
                                  SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
-                                 acl, &sd_size)) )
+                                 theacl, &sd_size)) )
                return NULL;
 
        return sd;
@@ -332,14 +332,14 @@ static void fill_service_values( const char *name, REGVAL_CTR *values )
 /********************************************************************
 ********************************************************************/
 
-static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys,
+static void add_new_svc_name( REGISTRY_KEY *key_parent, struct regsubkey_ctr *subkeys,
                               const char *name )
 {
        REGISTRY_KEY *key_service = NULL, *key_secdesc = NULL;
        WERROR wresult;
        char *path = NULL;
        REGVAL_CTR *values = NULL;
-       REGSUBKEY_CTR *svc_subkeys = NULL;
+       struct regsubkey_ctr *svc_subkeys = NULL;
        SEC_DESC *sd = NULL;
        DATA_BLOB sd_blob;
        NTSTATUS status;
@@ -366,7 +366,8 @@ static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys,
 
        /* add the 'Security' key */
 
-       if ( !(svc_subkeys = TALLOC_ZERO_P( key_service, REGSUBKEY_CTR )) ) {
+       wresult = regsubkey_ctr_init(key_service, &svc_subkeys);
+       if (!W_ERROR_IS_OK(wresult)) {
                DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
                TALLOC_FREE( key_service );
                return;
@@ -444,7 +445,7 @@ void svcctl_init_keys( void )
 {
        const char **service_list = lp_svcctl_list();
        int i;
-       REGSUBKEY_CTR *subkeys = NULL;
+       struct regsubkey_ctr *subkeys = NULL;
        REGISTRY_KEY *key = NULL;
        WERROR wresult;
 
@@ -461,7 +462,8 @@ void svcctl_init_keys( void )
 
        /* lookup the available subkeys */
 
-       if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) {
+       wresult = regsubkey_ctr_init(key, &subkeys);
+       if (!W_ERROR_IS_OK(wresult)) {
                DEBUG(0,("svcctl_init_keys: talloc() failed!\n"));
                TALLOC_FREE( key );
                return;
index 78b8123680f050748dffaeefe743104d35c2f7ea..d23b509af2dd16d82cc7f2ca9c6c5eaa00c82049 100644 (file)
@@ -471,6 +471,7 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
        SMB_STRUCT_STAT sbuf;
        struct smb_file_time ft;
        NTSTATUS status;
+       int ret = -1;
 
        ZERO_STRUCT(sbuf);
        ZERO_STRUCT(ft);
@@ -485,15 +486,19 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
 
        /* Ensure we have a valid stat struct for the source. */
        if (fsp->fh->fd != -1) {
-               if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
-                       return map_nt_error_from_unix(errno);
-               }
+               ret = SMB_VFS_FSTAT(fsp, &sbuf);
        } else {
-               if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf) == -1) {
-                       return map_nt_error_from_unix(errno);
+               if (fsp->posix_open) {
+                       ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name,&sbuf);
+               } else {
+                       ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf);
                }
        }
 
+       if (ret == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+
        if (!VALID_STAT(sbuf)) {
                /* if it doesn't seem to be a real file */
                return NT_STATUS_OK;
@@ -581,6 +586,13 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
         */
 
        saved_status4 = update_write_time_on_close(fsp);
+       if (NT_STATUS_EQUAL(saved_status4, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+               /* Someone renamed the file or a parent directory containing
+                * this file. We can't do anything about this, we don't have
+                * an "update timestamp by fd" call in POSIX. Eat the error. */
+
+               saved_status4 = NT_STATUS_OK;
+       }
 
        if (NT_STATUS_IS_OK(status)) {
                if (!NT_STATUS_IS_OK(saved_status1)) {
index a9a97a2d14a133759dff5f54778c2dca769b2bd5..adf664b3960301da1713a81589b8b8e75a6f9307 100644 (file)
@@ -256,10 +256,9 @@ ssize_t write_file(struct smb_request *req,
        int write_path = -1;
 
        if (fsp->print_file) {
-               fstring sharename;
                uint32 jobid;
 
-               if (!rap_to_pjobid(fsp->rap_print_jobid, sharename, &jobid)) {
+               if (!rap_to_pjobid(fsp->rap_print_jobid, NULL, &jobid)) {
                        DEBUG(3,("write_file: Unable to map RAP jobid %u to jobid.\n",
                                                (unsigned int)fsp->rap_print_jobid ));
                        errno = EBADF;
index efaadffc061cda7569db49ce9186d0af951f76d1..36e80a086ac26cb957c5f408442a2867f3f7c56a 100644 (file)
@@ -355,6 +355,49 @@ files_struct *file_find_print(void)
        return NULL;
 }
 
+/****************************************************************************
+ Find any fsp open with a pathname below that of an already open path.
+****************************************************************************/
+
+bool file_find_subpath(files_struct *dir_fsp)
+{
+       files_struct *fsp;
+       size_t dlen;
+       char *d_fullname = talloc_asprintf(talloc_tos(),
+                                       "%s/%s",
+                                       dir_fsp->conn->connectpath,
+                                       dir_fsp->fsp_name);
+
+       if (!d_fullname) {
+               return false;
+       }
+
+       dlen = strlen(d_fullname);
+
+       for (fsp=Files;fsp;fsp=fsp->next) {
+               char *d1_fullname;
+
+               if (fsp == dir_fsp) {
+                       continue;
+               }
+
+               d1_fullname = talloc_asprintf(talloc_tos(),
+                                       "%s/%s",
+                                       fsp->conn->connectpath,
+                                       fsp->fsp_name);
+
+               if (strnequal(d_fullname, d1_fullname, dlen)) {
+                       TALLOC_FREE(d_fullname);
+                       TALLOC_FREE(d1_fullname);
+                       return true;
+               }
+               TALLOC_FREE(d1_fullname);
+       } 
+
+       TALLOC_FREE(d_fullname);
+       return false;
+}
+
 /****************************************************************************
  Sync open files on a connection.
 ****************************************************************************/
index 3f8cb411e562b289014583392719b5db67bd84da..9e7d1035624079e616ef5b2c1422d154c313974a 100644 (file)
@@ -66,7 +66,8 @@ struct fsp_singleton_cache fsp_fi_cache = {
        .fsp = NULL,
        .id = {
                .devid = 0,
-               .inode = 0
+               .inode = 0,
+               .extid = 0
        }
 };
 unsigned long file_gen_counter = 0;
index 57608a9b406785b507a29af8fe74b7b4ecebac02..a921954c49c4f162645b79991d6845a844bbb007 100644 (file)
@@ -27,7 +27,6 @@ extern enum protocol_types Protocol;
 static void get_challenge(uint8 buff[8])
 {
        NTSTATUS nt_status;
-       const uint8 *cryptkey;
 
        /* We might be called more than once, multiple negprots are
         * permitted */
@@ -42,8 +41,8 @@ static void get_challenge(uint8 buff[8])
                smb_panic("cannot make_negprot_global_auth_context!");
        }
        DEBUG(10, ("get challenge: getting challenge\n"));
-       cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
-       memcpy(buff, cryptkey, 8);
+       negprot_global_auth_context->get_ntlm_challenge(
+               negprot_global_auth_context, buff);
 }
 
 /****************************************************************************
index 1d4f5e8c5b3f6e9c22ecb8ad45d7285bc22eabf3..8ceeaf5f5588ae4e5d5c091a3379ce944c00bc88 100644 (file)
@@ -214,6 +214,8 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
 
        ZERO_STRUCT(e);
        e.path = fullpath;
+       e.dir_fd = fsp->fh->fd;
+       e.dir_id = fsp->file_id;
        e.filter = filter;
        e.subdir_filter = 0;
        if (recursive) {
@@ -370,13 +372,26 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
        if ((fsp->notify->num_changes > 1000) || (name == NULL)) {
                /*
                 * The real number depends on the client buf, just provide a
-                * guard against a DoS here.
+                * guard against a DoS here.  If name == NULL the CN backend is
+                * alerting us to a problem.  Possibly dropped events.  Clear
+                * queued changes and send the catch-all response to the client
+                * if a request is pending.
                 */
                TALLOC_FREE(fsp->notify->changes);
                fsp->notify->num_changes = -1;
+               if (fsp->notify->requests != NULL) {
+                       change_notify_reply(fsp->conn,
+                                           fsp->notify->requests->req,
+                                           fsp->notify->requests->max_param,
+                                           fsp->notify);
+                       change_notify_remove_request(fsp->notify->requests);
+               }
                return;
        }
 
+       /* If we've exceeded the server side queue or received a NULL name
+        * from the underlying CN implementation, don't queue up any more
+        * requests until we can send a catch-all response to the client */
        if (fsp->notify->num_changes == -1) {
                return;
        }
index ad2366efae446276e5dc02632d9e1d7ff2cefaed..86a46505a2f1e4ba228a856179fbdf0c15791a41 100644 (file)
@@ -1856,6 +1856,8 @@ static void call_nt_transact_ioctl(connection_struct *conn,
                        reply_nterror(req, NT_STATUS_NO_MEMORY);
                        return;
                }
+
+               /* For backwards compatibility only store the dev/inode. */
                push_file_id_16(pdata, &fsp->file_id);
                memcpy(pdata+16,create_volume_objectid(conn,objid),16);
                push_file_id_16(pdata+32, &fsp->file_id);
index 9971ffa6798287c106124b578cceced3476dca99..569c2603192f811aef1c35299bda198a5e0e02ab 100644 (file)
@@ -132,6 +132,18 @@ static NTSTATUS fd_open(struct connection_struct *conn,
        fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode);
        if (fsp->fh->fd == -1) {
                status = map_nt_error_from_unix(errno);
+               if (errno == EMFILE) {
+                       static time_t last_warned = 0L;
+
+                       if (time((time_t *) NULL) > last_warned) {
+                               DEBUG(0,("Too many open files, unable "
+                                       "to open more!  smbd's max "
+                                       "open files = %d\n",
+                                       lp_max_open_files()));
+                               last_warned = time((time_t *) NULL);
+                       }
+               }
+
        }
 
        DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n",
@@ -1428,7 +1440,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                   "create_disposition = 0x%x create_options=0x%x "
                   "unix mode=0%o oplock_request=%d\n",
                   fname, new_dos_attributes, access_mask, share_access,
-                  create_disposition, create_options, unx_mode,
+                  create_disposition, create_options, (unsigned int)unx_mode,
                   oplock_request));
 
        if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) {
@@ -2445,6 +2457,25 @@ static NTSTATUS open_directory(connection_struct *conn,
                                        fname,
                                        access_mask,
                                        &access_granted);
+
+               /* Were we trying to do a directory open
+                * for delete and didn't get DELETE
+                * access (only) ? Check if the
+                * directory allows DELETE_CHILD.
+                * See here:
+                * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx
+                * for details. */
+
+               if ((NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
+                               (access_mask & DELETE_ACCESS) &&
+                               (access_granted == DELETE_ACCESS) &&
+                               can_delete_file_in_directory(conn, fname))) {
+                       DEBUG(10,("open_directory: overrode ACCESS_DENIED "
+                               "on directory %s\n",
+                               fname ));
+                       status = NT_STATUS_OK;
+               }
+
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(10, ("open_directory: check_open_rights on "
                                "file %s failed with %s\n",
@@ -2597,8 +2628,8 @@ void msg_file_was_renamed(struct messaging_context *msg,
         }
 
        /* Unpack the message. */
-       pull_file_id_16(frm, &id);
-       sharepath = &frm[16];
+       pull_file_id_24(frm, &id);
+       sharepath = &frm[24];
        newname = sharepath + strlen(sharepath) + 1;
        sp_len = strlen(sharepath);
 
index b39e5bf6349d852bca47a837ccf9365c81c2878d..22870283fa5996d2e519096ca8ba319d7ea7f144 100644 (file)
@@ -40,8 +40,8 @@ void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp)
        uint8_t msg[MSG_SMB_KERNEL_BREAK_SIZE];
 
        /* Put the kernel break info into the message. */
-       push_file_id_16((char *)msg, &fsp->file_id);
-       SIVAL(msg,16,fsp->fh->gen_id);
+       push_file_id_24((char *)msg, &fsp->file_id);
+       SIVAL(msg,24,fsp->fh->gen_id);
 
        /* Don't need to be root here as we're only ever
           sending to ourselves. */
@@ -583,8 +583,8 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
        }
 
        /* Pull the data from the message. */
-       pull_file_id_16((char *)data->data, &id);
-       file_id = (unsigned long)IVAL(data->data, 16);
+       pull_file_id_24((char *)data->data, &id);
+       file_id = (unsigned long)IVAL(data->data, 24);
 
        DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n",
                   (int)procid_to_pid(&src), file_id_string_tos(&id),
@@ -865,12 +865,12 @@ void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e)
        SIVAL(msg,16,e->private_options);
        SIVAL(msg,20,(uint32)e->time.tv_sec);
        SIVAL(msg,24,(uint32)e->time.tv_usec);
-       push_file_id_16(msg+28, &e->id);
-       SIVAL(msg,44,e->share_file_id);
-       SIVAL(msg,48,e->uid);
-       SSVAL(msg,52,e->flags);
+       push_file_id_24(msg+28, &e->id);
+       SIVAL(msg,52,e->share_file_id);
+       SIVAL(msg,56,e->uid);
+       SSVAL(msg,60,e->flags);
 #ifdef CLUSTER_SUPPORT
-       SIVAL(msg,54,e->pid.vnn);
+       SIVAL(msg,62,e->pid.vnn);
 #endif
 }
 
@@ -888,12 +888,12 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg)
        e->private_options = IVAL(msg,16);
        e->time.tv_sec = (time_t)IVAL(msg,20);
        e->time.tv_usec = (int)IVAL(msg,24);
-       pull_file_id_16(msg+28, &e->id);
-       e->share_file_id = (unsigned long)IVAL(msg,44);
-       e->uid = (uint32)IVAL(msg,48);
-       e->flags = (uint16)SVAL(msg,52);
+       pull_file_id_24(msg+28, &e->id);
+       e->share_file_id = (unsigned long)IVAL(msg,52);
+       e->uid = (uint32)IVAL(msg,56);
+       e->flags = (uint16)SVAL(msg,60);
 #ifdef CLUSTER_SUPPORT
-       e->pid.vnn = IVAL(msg,54);
+       e->pid.vnn = IVAL(msg,62);
 #endif
 }
 
index bbc9132a08f8e628888de920f49ce8f9a13fad13..89b8e0f7b58489c738c8d1f693c24e06f222bd72 100644 (file)
@@ -103,6 +103,24 @@ static bool irix_oplocks_available(void)
        return True;
 }
 
+/*
+ * This is bad because the file_id should always be created through the vfs
+ * layer!  Unfortunately, a conn struct isn't available here.
+ */
+static struct file_id file_id_create_dev(SMB_DEV_T dev, SMB_INO_T inode)
+{
+       struct file_id key;
+
+       /* the ZERO_STRUCT ensures padding doesn't break using the key as a
+        * blob */
+       ZERO_STRUCT(key);
+
+       key.devid = dev;
+       key.inode = inode;
+
+       return key;
+}
+
 /****************************************************************************
  * Deal with the IRIX kernel <--> smbd
  * oplock break protocol.
index 0908ce4386dae8343a48b5296603f2b50fb834a6..d4f181fc472f410217630f6fc1ea34ff669e396b 100644 (file)
@@ -744,13 +744,13 @@ struct kernel_oplocks *onefs_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
        po.po_flags_on |= P_NON_BLOCKING_SEMLOCK;
        if (setprocoptions(&po) != 0) {
                DEBUG(0, ("setprocoptions failed: %s.\n", strerror(errno)));
-               goto err_out;
+               return NULL;
        }
 
        /* Setup the oplock contexts */
        _ctx = talloc_zero(mem_ctx, struct kernel_oplocks);
        if (!_ctx) {
-               goto err_out;
+               return NULL;
        }
 
        ctx = talloc_zero(_ctx, struct onefs_oplocks_context);
@@ -788,7 +788,6 @@ struct kernel_oplocks *onefs_init_kernel_oplocks(TALLOC_CTX *mem_ctx)
 
  err_out:
        talloc_free(_ctx);
-       talloc_free(ctx);
        return NULL;
 }
 
index e9b581efe82a44e67e3bfb86886f44fd9f2ffbe8..2f84a831c6c30737f15a01058dbcc83857fb490a 100644 (file)
@@ -719,12 +719,12 @@ static struct pai_val *load_inherited_info(const struct connection_struct *conn,
  Count a linked list of canonical ACE entries.
 ****************************************************************************/
 
-static size_t count_canon_ace_list( canon_ace *list_head )
+static size_t count_canon_ace_list( canon_ace *l_head )
 {
        size_t count = 0;
        canon_ace *ace;
 
-       for (ace = list_head; ace; ace = ace->next)
+       for (ace = l_head; ace; ace = ace->next)
                count++;
 
        return count;
@@ -734,13 +734,13 @@ static size_t count_canon_ace_list( canon_ace *list_head )
  Free a linked list of canonical ACE entries.
 ****************************************************************************/
 
-static void free_canon_ace_list( canon_ace *list_head )
+static void free_canon_ace_list( canon_ace *l_head )
 {
        canon_ace *list, *next;
 
-       for (list = list_head; list; list = next) {
+       for (list = l_head; list; list = next) {
                next = list->next;
-               DLIST_REMOVE(list_head, list);
+               DLIST_REMOVE(l_head, list);
                SAFE_FREE(list);
        }
 }
@@ -916,7 +916,7 @@ static bool identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2)
 
 static void merge_aces( canon_ace **pp_list_head )
 {
-       canon_ace *list_head = *pp_list_head;
+       canon_ace *l_head = *pp_list_head;
        canon_ace *curr_ace_outer;
        canon_ace *curr_ace_outer_next;
 
@@ -925,7 +925,7 @@ static void merge_aces( canon_ace **pp_list_head )
         * with identical SIDs.
         */
 
-       for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
+       for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
                canon_ace *curr_ace;
                canon_ace *curr_ace_next;
 
@@ -947,7 +947,7 @@ static void merge_aces( canon_ace **pp_list_head )
                                /* Merge two allow or two deny ACE's. */
 
                                curr_ace_outer->perms |= curr_ace->perms;
-                               DLIST_REMOVE(list_head, curr_ace);
+                               DLIST_REMOVE(l_head, curr_ace);
                                SAFE_FREE(curr_ace);
                                curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
                        }
@@ -960,7 +960,7 @@ static void merge_aces( canon_ace **pp_list_head )
         * appears only once in the list.
         */
 
-       for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
+       for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
                canon_ace *curr_ace;
                canon_ace *curr_ace_next;
 
@@ -992,7 +992,7 @@ static void merge_aces( canon_ace **pp_list_head )
                                         * The deny overrides the allow. Remove the allow.
                                         */
 
-                                       DLIST_REMOVE(list_head, curr_ace);
+                                       DLIST_REMOVE(l_head, curr_ace);
                                        SAFE_FREE(curr_ace);
                                        curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
 
@@ -1008,7 +1008,7 @@ static void merge_aces( canon_ace **pp_list_head )
                                         * before we can get to an allow ace.
                                         */
 
-                                       DLIST_REMOVE(list_head, curr_ace_outer);
+                                       DLIST_REMOVE(l_head, curr_ace_outer);
                                        SAFE_FREE(curr_ace_outer);
                                        break;
                                }
@@ -1019,7 +1019,7 @@ static void merge_aces( canon_ace **pp_list_head )
 
        /* We may have modified the list. */
 
-       *pp_list_head = list_head;
+       *pp_list_head = l_head;
 }
 
 /****************************************************************************
@@ -2305,12 +2305,12 @@ static bool unpack_canon_ace(files_struct *fsp,
 
 static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head)
 {
-       canon_ace *list_head = *pp_list_head;
+       canon_ace *l_head = *pp_list_head;
        canon_ace *owner_ace = NULL;
        canon_ace *other_ace = NULL;
        canon_ace *ace = NULL;
 
-       for (ace = list_head; ace; ace = ace->next) {
+       for (ace = l_head; ace; ace = ace->next) {
                if (ace->type == SMB_ACL_USER_OBJ)
                        owner_ace = ace;
                else if (ace->type == SMB_ACL_OTHER) {
@@ -2331,16 +2331,16 @@ static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head)
         */
 
        if (owner_ace) {
-               DLIST_PROMOTE(list_head, owner_ace);
+               DLIST_PROMOTE(l_head, owner_ace);
        }
 
        if (other_ace) {
-               DLIST_DEMOTE(list_head, other_ace, canon_ace *);
+               DLIST_DEMOTE(l_head, other_ace, canon_ace *);
        }
 
        /* We have probably changed the head of the list. */
 
-       *pp_list_head = list_head;
+       *pp_list_head = l_head;
 }
 
 /****************************************************************************
@@ -2353,7 +2353,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                                   const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
 {
        mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR);
-       canon_ace *list_head = NULL;
+       canon_ace *l_head = NULL;
        canon_ace *ace = NULL;
        canon_ace *next_ace = NULL;
        int entry_id = SMB_ACL_FIRST_ENTRY;
@@ -2457,14 +2457,14 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                ace->owner_type = owner_type;
                ace->ace_flags = get_pai_flags(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT));
 
-               DLIST_ADD(list_head, ace);
+               DLIST_ADD(l_head, ace);
        }
 
        /*
         * This next call will ensure we have at least a user/group/world set.
         */
 
-       if (!ensure_canon_entry_valid(&list_head, conn->params,
+       if (!ensure_canon_entry_valid(&l_head, conn->params,
                                      S_ISDIR(psbuf->st_mode), powner, pgroup,
                                      psbuf, False))
                goto fail;
@@ -2476,7 +2476,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
 
        DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", the_acl_type == SMB_ACL_TYPE_ACCESS ? "Access" : "Default" ));
 
-       for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) {
+       for ( ace_count = 0, ace = l_head; ace; ace = next_ace, ace_count++) {
                next_ace = ace->next;
 
                /* Masks are only applied to entries other than USER_OBJ and OTHER. */
@@ -2484,7 +2484,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                        ace->perms &= acl_mask;
 
                if (ace->perms == 0) {
-                       DLIST_PROMOTE(list_head, ace);
+                       DLIST_PROMOTE(l_head, ace);
                }
 
                if( DEBUGLVL( 10 ) ) {
@@ -2492,15 +2492,15 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
                }
        }
 
-       arrange_posix_perms(fname,&list_head );
+       arrange_posix_perms(fname,&l_head );
 
-       print_canon_ace_list( "canonicalise_acl: ace entries after arrange", list_head );
+       print_canon_ace_list( "canonicalise_acl: ace entries after arrange", l_head );
 
-       return list_head;
+       return l_head;
 
   fail:
 
-       free_canon_ace_list(list_head);
+       free_canon_ace_list(l_head);
        return NULL;
 }
 
index 457f9412a91d0bbe771c56437c0868c38061f825..22e4c1aad7fb6b50ef9f0bb633f9b68e3933f6da 100644 (file)
@@ -2214,6 +2214,16 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
        }
 
        if (S_ISDIR(pst->st_mode)) {
+               if (fsp->posix_open) {
+                       return NT_STATUS_OK;
+               }
+
+               /* If no pathnames are open below this
+                  directory, allow the rename. */
+
+               if (file_find_subpath(fsp)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
                return NT_STATUS_OK;
        }
 
@@ -2788,6 +2798,18 @@ static void send_file_readbraw(connection_struct *conn,
                        DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
                                fsp->fsp_name, strerror(errno) ));
                        exit_server_cleanly("send_file_readbraw sendfile failed");
+               } else if (sendfile_read == 0) {
+                       /*
+                        * Some sendfile implementations return 0 to indicate
+                        * that there was a short read, but nothing was
+                        * actually written to the socket.  In this case,
+                        * fallback to the normal read path so the header gets
+                        * the correct byte count.
+                        */
+                       DEBUG(3, ("send_file_readbraw: sendfile sent zero "
+                                 "bytes falling back to the normal read: "
+                                 "%s\n", fsp->fsp_name));
+                       goto normal_readbraw;
                }
 
                /* Deal with possible short send. */
@@ -2796,9 +2818,9 @@ static void send_file_readbraw(connection_struct *conn,
                }
                return;
        }
-#endif
 
 normal_readbraw:
+#endif
 
        outbuf = TALLOC_ARRAY(NULL, char, nread+4);
        if (!outbuf) {
@@ -3284,6 +3306,18 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
                        DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
                                fsp->fsp_name, strerror(errno) ));
                        exit_server_cleanly("send_file_readX sendfile failed");
+               } else if (nread == 0) {
+                       /*
+                        * Some sendfile implementations return 0 to indicate
+                        * that there was a short read, but nothing was
+                        * actually written to the socket.  In this case,
+                        * fallback to the normal read path so the header gets
+                        * the correct byte count.
+                        */
+                       DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
+                                 "falling back to the normal read: %s\n",
+                                 fsp->fsp_name));
+                       goto normal_read;
                }
 
                DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
index e8ccba0873aef5bd4ee968ede959fb6ec17bd745..538e04938e917c6e7434783ba35a67acf643917f 100644 (file)
@@ -212,7 +212,7 @@ static void remove_child_pid(pid_t pid, bool unclean_shutdown)
                /* a child terminated uncleanly so tickle all processes to see 
                   if they can grab any of the pending locks
                */
-               DEBUG(3,(__location__ " Unclean shutdown of pid %u\n", pid));
+               DEBUG(3,(__location__ " Unclean shutdown of pid %u\n", (unsigned int)pid));
                messaging_send_buf(smbd_messaging_context(), procid_self(), 
                                   MSG_SMB_BRL_VALIDATE, NULL, 0);
                message_send_all(smbd_messaging_context(), 
@@ -359,10 +359,6 @@ static void smbd_accept_connection(struct tevent_context *ev,
                /* Child code ... */
                am_parent = 0;
 
-#ifdef WITH_MADVISE_PROTECTED
-               madvise(NULL,0,MADV_PROTECT);
-#endif
-
                /* Stop zombies, the parent explicitly handles
                 * them, counting worker smbds. */
                CatchChild();
@@ -451,7 +447,6 @@ static bool smbd_open_one_socket(struct smbd_parent_context *parent,
        if (s->fd == -1) {
                DEBUG(0,("smbd_open_once_socket: open_socket_in: "
                        "%s\n", strerror(errno)));
-                       close(s->fd);
                TALLOC_FREE(s);
                /*
                 * We ignore an error here, as we've done before
@@ -735,7 +730,7 @@ void reload_printers(void)
                        DEBUG(3, ("removing stale printer %s\n", pname));
 
                        if (is_printer_published(NULL, snum, NULL))
-                               nt_printer_publish(NULL, snum, SPOOL_DS_UNPUBLISH);
+                               nt_printer_publish(NULL, snum, DSPRINT_UNPUBLISH);
                        del_a_printer(pname);
                        lp_killservice(snum);
                }
@@ -1135,9 +1130,6 @@ extern void build_options(bool screen);
        if (is_daemon && !interactive) {
                DEBUG( 3, ( "Becoming a daemon.\n" ) );
                become_daemon(Fork, no_process_group);
-#ifdef WITH_MADVISE_PROTECTED
-               madvise(NULL,0,MADV_PROTECT);
-#endif
        }
 
 #if HAVE_SETPGID
index 7a03ef7f3cc6a324a5e8d4b3a3fedefd2eebfc7c..2c29192220b1958d0c47ae1eb51faac6bfb0d147 100644 (file)
@@ -1352,8 +1352,8 @@ static int shutdown_other_smbds(struct db_record *rec,
                return 0;
        }
 
-       DEBUG(0,("shutdown_other_smbds: shutting down pid %d "
-                "(IP %s)\n", procid_to_pid(&crec->pid), ip));
+       DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
+                "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
 
        messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
                       &data_blob_null);
@@ -1691,14 +1691,15 @@ void reply_sesssetup_and_X(struct smb_request *req)
                }
        } else {
                struct auth_context *plaintext_auth_context = NULL;
-               const uint8 *chal;
 
                nt_status = make_auth_context_subsystem(
                                &plaintext_auth_context);
 
                if (NT_STATUS_IS_OK(nt_status)) {
-                       chal = plaintext_auth_context->get_ntlm_challenge(
-                                       plaintext_auth_context);
+                       uint8_t chal[8];
+
+                       plaintext_auth_context->get_ntlm_challenge(
+                                       plaintext_auth_context, chal);
 
                        if (!make_user_info_for_reply(&user_info,
                                                      user, domain, chal,
index 759e520866cc90ba3778efbdccb03efce37f619d..ee1dda98b22c3ca3d982e60ddc71dadd49921447 100644 (file)
@@ -4972,6 +4972,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
 ****************************************************************************/
 
 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
+                               files_struct *fsp,
                                const char *fname,
                                SMB_STRUCT_STAT *psbuf,
                                uint32 dosmode)
@@ -4980,6 +4981,14 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
+       if (fsp) {
+               if (fsp->base_fsp) {
+                       fname = fsp->base_fsp->fsp_name;
+               } else {
+                       fname = fsp->fsp_name;
+               }
+       }
+               
        if (dosmode) {
                if (S_ISDIR(psbuf->st_mode)) {
                        dosmode |= aDIR;
@@ -5723,12 +5732,11 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
 
        /* Set the attributes */
        dosmode = IVAL(pdata,32);
-       status = smb_set_file_dosmode(conn, fname, psbuf, dosmode);
+       status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-
        /* access time */
        ft.atime = interpret_long_date(pdata+8);
 
@@ -6415,6 +6423,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                create_disp = FILE_OVERWRITE_IF;
        } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
                create_disp = FILE_OPEN_IF;
+       } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
+               create_disp = FILE_OPEN;
        } else {
                DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
                        (unsigned int)wire_open_mode ));
index 95802473680764df8c46cf29695b5e6730654ca5..426772889c7a30c5f38700a5a940b6a0132e8a8d 100644 (file)
@@ -766,18 +766,13 @@ int vfs_ChDir(connection_struct *conn, const char *path)
  format. Note this can be called with conn == NULL.
 ********************************************************************/
 
-struct getwd_cache_key {
-       SMB_DEV_T dev;
-       SMB_INO_T ino;
-};
-
 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
 {
         char s[PATH_MAX+1];
        SMB_STRUCT_STAT st, st2;
        char *result;
        DATA_BLOB cache_value;
-       struct getwd_cache_key key;
+       struct file_id key;
 
        *s = 0;
 
@@ -797,9 +792,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
                goto nocache;
        }
 
-       ZERO_STRUCT(key); /* unlikely, but possible padding */
-       key.dev = st.st_dev;
-       key.ino = st.st_ino;
+       key = vfs_file_id_from_sbuf(conn, &st);
 
        if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
                             data_blob_const(&key, sizeof(key)),
@@ -838,9 +831,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
        }
 
        if (lp_getwd_cache() && VALID_STAT(st)) {
-               ZERO_STRUCT(key); /* unlikely, but possible padding */
-               key.dev = st.st_dev;
-               key.ino = st.st_ino;
+               key = vfs_file_id_from_sbuf(conn, &st);
 
                memcache_add(smbd_memcache(), GETWD_CACHE,
                             data_blob_const(&key, sizeof(key)),
index 0c2cd24fb2e2aa573617d72a54ad2822caab54e5..05b552c00def11f67cdfb313ac7c719c2a814a43 100644 (file)
@@ -331,6 +331,12 @@ static int net_conf_import(struct net_context *c, struct smbconf_ctx *conf_ctx,
                         "would import the following configuration:\n\n");
        }
 
+       werr = smbconf_transaction_start(conf_ctx);
+       if (!W_ERROR_IS_OK(werr)) {
+               d_printf("error starting transaction: %s\n", win_errstr(werr));
+               goto done;
+       }
+
        if (servicename != NULL) {
                struct smbconf_service *service = NULL;
 
@@ -338,11 +344,11 @@ static int net_conf_import(struct net_context *c, struct smbconf_ctx *conf_ctx,
                                         servicename,
                                         &service);
                if (!W_ERROR_IS_OK(werr)) {
-                       goto done;
+                       goto cancel;
                }
                werr = import_process_service(c, conf_ctx, service);
                if (!W_ERROR_IS_OK(werr)) {
-                       goto done;
+                       goto cancel;
                }
        } else {
                struct smbconf_service **services = NULL;
@@ -352,24 +358,39 @@ static int net_conf_import(struct net_context *c, struct smbconf_ctx *conf_ctx,
                                          &num_shares,
                                          &services);
                if (!W_ERROR_IS_OK(werr)) {
-                       goto done;
+                       goto cancel;
                }
                if (!c->opt_testmode) {
                        werr = smbconf_drop(conf_ctx);
                        if (!W_ERROR_IS_OK(werr)) {
-                               goto done;
+                               goto cancel;
                        }
                }
                for (sidx = 0; sidx < num_shares; sidx++) {
                        werr = import_process_service(c, conf_ctx,
                                                      services[sidx]);
                        if (!W_ERROR_IS_OK(werr)) {
-                               goto done;
+                               goto cancel;
                        }
                }
        }
 
-       ret = 0;
+       werr = smbconf_transaction_commit(conf_ctx);
+       if (!W_ERROR_IS_OK(werr)) {
+               d_printf("error committing transaction: %s\n",
+                        win_errstr(werr));
+       } else {
+               ret = 0;
+       }
+
+       goto done;
+
+cancel:
+       werr = smbconf_transaction_cancel(conf_ctx);
+       if (!W_ERROR_IS_OK(werr)) {
+               d_printf("error cancelling transaction: %s\n",
+                        win_errstr(werr));
+       }
 
 done:
        TALLOC_FREE(mem_ctx);
index bb8747ede3bfdd99e01acb4d133848c3e40b4f1b..8116764d9b34f8d4c7accca3d040213b41ae952a 100644 (file)
@@ -50,6 +50,33 @@ static const struct table_node archi_table[]= {
  Printer info level 3 display function.
 ****************************************************************************/
 
+static void display_print_driver3(struct spoolss_DriverInfo3 *r)
+{
+       int i;
+
+       if (!r) {
+               return;
+       }
+
+       printf("Printer Driver Info 3:\n");
+       printf("\tVersion: [%x]\n", r->version);
+       printf("\tDriver Name: [%s]\n", r->driver_name);
+       printf("\tArchitecture: [%s]\n", r->architecture);
+       printf("\tDriver Path: [%s]\n", r->driver_path);
+       printf("\tDatafile: [%s]\n", r->data_file);
+       printf("\tConfigfile: [%s]\n\n", r->config_file);
+       printf("\tHelpfile: [%s]\n\n", r->help_file);
+
+       for (i=0; r->dependent_files[i] != NULL; i++) {
+               printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
+       }
+
+       printf("\n");
+
+       printf("\tMonitorname: [%s]\n", r->monitor_name);
+       printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
+}
+
 static void display_print_driver_3(DRIVER_INFO_3 *i1)
 {
        fstring name = "";
@@ -513,7 +540,7 @@ static NTSTATUS net_copy_driverfile(struct net_context *c,
                                    TALLOC_CTX *mem_ctx,
                                    struct cli_state *cli_share_src,
                                    struct cli_state *cli_share_dst,
-                                   char *file, const char *short_archi) {
+                                   const char *file, const char *short_archi) {
 
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        const char *p;
@@ -523,6 +550,10 @@ static NTSTATUS net_copy_driverfile(struct net_context *c,
        char *filename;
        char *tok;
 
+       if (!file) {
+               return NT_STATUS_OK;
+       }
+
        /* scroll through the file until we have the part
           beyond archi_table.short_archi */
        p = file;
@@ -617,67 +648,47 @@ static NTSTATUS copy_print_driver_3(struct net_context *c,
                    TALLOC_CTX *mem_ctx,
                    struct cli_state *cli_share_src,
                    struct cli_state *cli_share_dst,
-                   const char *short_archi, DRIVER_INFO_3 *i1)
+                   const char *short_archi,
+                   struct spoolss_DriverInfo3 *r)
 {
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-       int length = 0;
-       bool valid = true;
-
-       fstring name = "";
-       fstring driverpath = "";
-       fstring datafile = "";
-       fstring configfile = "";
-       fstring helpfile = "";
-       fstring dependentfiles = "";
+       int i;
 
-       if (i1 == NULL)
+       if (r == NULL) {
                return nt_status;
-
-       rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
-       rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
-       rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
-       rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
-       rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
-
+       }
 
        if (c->opt_verbose)
                d_printf("copying driver: [%s], for architecture: [%s], version: [%d]\n",
-                         name, short_archi, i1->version);
+                         r->driver_name, short_archi, r->version);
 
        nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
-               driverpath, short_archi);
+               r->driver_path, short_archi);
        if (!NT_STATUS_IS_OK(nt_status))
                return nt_status;
 
        nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
-               datafile, short_archi);
+               r->data_file, short_archi);
        if (!NT_STATUS_IS_OK(nt_status))
                return nt_status;
 
        nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
-               configfile, short_archi);
+               r->config_file, short_archi);
        if (!NT_STATUS_IS_OK(nt_status))
                return nt_status;
 
        nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
-               helpfile, short_archi);
+               r->help_file, short_archi);
        if (!NT_STATUS_IS_OK(nt_status))
                return nt_status;
 
-       while (valid) {
-
-               rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
-               length += strlen(dependentfiles)+1;
+       for (i=0; r->dependent_files[i] != NULL; i++) {
 
-               if (strlen(dependentfiles) > 0) {
-
-                       nt_status = net_copy_driverfile(c, mem_ctx,
-                                       cli_share_src, cli_share_dst,
-                                       dependentfiles, short_archi);
-                       if (!NT_STATUS_IS_OK(nt_status))
-                               return nt_status;
-               } else {
-                       valid = false;
+               nt_status = net_copy_driverfile(c, mem_ctx,
+                               cli_share_src, cli_share_dst,
+                               r->dependent_files[i], short_archi);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
                }
        }
 
@@ -764,13 +775,16 @@ static bool net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
                                TALLOC_CTX *mem_ctx,
                                POLICY_HND *hnd,
                                uint32 level,
-                               PRINTER_INFO_CTR *ctr)
+                               union spoolss_PrinterInfo *info)
 {
        WERROR result;
 
        /* getprinter call */
-       result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx, hnd, level, ctr);
-
+       result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx,
+                                          hnd,
+                                          level,
+                                          0, /* offered */
+                                          info);
        if (!W_ERROR_IS_OK(result)) {
                printf("cannot get printer-info: %s\n", win_errstr(result));
                return false;
@@ -783,12 +797,64 @@ static bool net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
                                TALLOC_CTX *mem_ctx,
                                POLICY_HND *hnd,
                                uint32 level,
-                               PRINTER_INFO_CTR *ctr)
+                               union spoolss_PrinterInfo *info)
 {
        WERROR result;
+       NTSTATUS status;
+       struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct sec_desc_buf secdesc_ctr;
+
+       ZERO_STRUCT(devmode_ctr);
+       ZERO_STRUCT(secdesc_ctr);
 
        /* setprinter call */
-       result = rpccli_spoolss_setprinter(pipe_hnd, mem_ctx, hnd, level, ctr, 0);
+
+       info_ctr.level = level;
+       switch (level) {
+       case 0:
+               info_ctr.info.info0 = (struct spoolss_SetPrinterInfo0 *)&info->info0;
+               break;
+       case 1:
+               info_ctr.info.info1 = (struct spoolss_SetPrinterInfo1 *)&info->info1;
+               break;
+       case 2:
+               info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info->info2;
+               break;
+       case 3:
+               info_ctr.info.info3 = (struct spoolss_SetPrinterInfo3 *)&info->info3;
+               break;
+       case 4:
+               info_ctr.info.info4 = (struct spoolss_SetPrinterInfo4 *)&info->info4;
+               break;
+       case 5:
+               info_ctr.info.info5 = (struct spoolss_SetPrinterInfo5 *)&info->info5;
+               break;
+       case 6:
+               info_ctr.info.info6 = (struct spoolss_SetPrinterInfo6 *)&info->info6;
+               break;
+       case 7:
+               info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)&info->info7;
+               break;
+#if 0 /* FIXME GD */
+       case 8:
+               info_ctr.info.info8 = (struct spoolss_SetPrinterInfo8 *)&info->info8;
+               break;
+       case 9:
+               info_ctr.info.info9 = (struct spoolss_SetPrinterInfo9 *)&info->info9;
+               break;
+#endif
+       default:
+               break; /* FIXME */
+       }
+
+       status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
+                                          hnd,
+                                          &info_ctr,
+                                          &devmode_ctr,
+                                          &secdesc_ctr,
+                                          0, /* command */
+                                          &result);
 
        if (!W_ERROR_IS_OK(result)) {
                printf("cannot set printer-info: %s\n", win_errstr(result));
@@ -930,15 +996,23 @@ static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
                             TALLOC_CTX *mem_ctx,
                             POLICY_HND *hnd, uint32 level,
                             const char *env, int version,
-                            PRINTER_DRIVER_CTR *ctr)
+                            union spoolss_DriverInfo *info)
 {
        WERROR result;
+       uint32_t server_major_version;
+       uint32_t server_minor_version;
 
        /* getprinterdriver call */
-       result = rpccli_spoolss_getprinterdriver(
-                       pipe_hnd, mem_ctx, hnd, level,
-                       env, version, ctr);
-
+       result = rpccli_spoolss_getprinterdriver2(pipe_hnd, mem_ctx,
+                                                 hnd,
+                                                 env,
+                                                 level,
+                                                 0,
+                                                 version,
+                                                 2,
+                                                 info,
+                                                 &server_major_version,
+                                                 &server_minor_version);
        if (!W_ERROR_IS_OK(result)) {
                DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
                        env, win_errstr(result)));
@@ -955,13 +1029,31 @@ static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
 
 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
                             TALLOC_CTX *mem_ctx, uint32 level,
-                            PRINTER_DRIVER_CTR *ctr)
+                            union spoolss_DriverInfo *info)
 {
        WERROR result;
+       NTSTATUS status;
+       struct spoolss_AddDriverInfoCtr info_ctr;
 
-       /* addprinterdriver call */
-       result = rpccli_spoolss_addprinterdriver(pipe_hnd, mem_ctx, level, ctr);
+       info_ctr.level = level;
+
+       switch (level) {
+       case 2:
+               info_ctr.info.info2 = (struct spoolss_AddDriverInfo2 *)&info->info2;
+               break;
+       case 3:
+               info_ctr.info.info3 = (struct spoolss_AddDriverInfo3 *)&info->info3;
+               break;
+       default:
+               printf("unsupported info level: %d\n", level);
+               return false;
+       }
 
+       /* addprinterdriver call */
+       status = rpccli_spoolss_AddPrinterDriver(pipe_hnd, mem_ctx,
+                                                pipe_hnd->srv_name_slash,
+                                                &info_ctr,
+                                                &result);
        /* be more verbose */
        if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
                printf("You are not allowed to add drivers\n");
@@ -990,6 +1082,7 @@ static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
 {
 
        POLICY_HND hnd;
+       union spoolss_PrinterInfo info;
 
        /* no arguments given, enumerate all printers */
        if (argc == 0) {
@@ -1002,6 +1095,8 @@ static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
                goto out;
        }
 
+       /* FIXME GD */
+       return false;
 
        /* argument given, get a single printer by name */
        if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
@@ -1010,7 +1105,7 @@ static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
                                         &hnd))
                return false;
 
-       if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, ctr)) {
+       if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info)) {
                rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
                return false;
        }
@@ -1179,9 +1274,12 @@ static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_
        uint32 i, num_printers;
        uint32 level = 7;
        char *printername, *sharename;
-       PRINTER_INFO_CTR ctr, ctr_pub;
+       PRINTER_INFO_CTR ctr;
+       union spoolss_PrinterInfo info;
+       struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct sec_desc_buf secdesc_ctr;
        POLICY_HND hnd;
-       bool got_hnd = false;
        WERROR result;
        const char *action_str;
 
@@ -1209,21 +1307,19 @@ static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_
                        PRINTER_ALL_ACCESS, pipe_hnd->auth->user_name, &hnd))
                        goto done;
 
-               got_hnd = true;
-
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub))
+               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
                        goto done;
 
                /* check action and set string */
                switch (action) {
-               case SPOOL_DS_PUBLISH:
+               case DSPRINT_PUBLISH:
                        action_str = "published";
                        break;
-               case SPOOL_DS_UPDATE:
+               case DSPRINT_UPDATE:
                        action_str = "updated";
                        break;
-               case SPOOL_DS_UNPUBLISH:
+               case DSPRINT_UNPUBLISH:
                        action_str = "unpublished";
                        break;
                default:
@@ -1232,9 +1328,21 @@ static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_
                        break;
                }
 
-               ctr_pub.printers_7->action = action;
+               info.info7.action = action;
+               info_ctr.level = 7;
+               info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)&info.info7;
+
+               ZERO_STRUCT(devmode_ctr);
+               ZERO_STRUCT(secdesc_ctr);
+
+               nt_status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
+                                                     &hnd,
+                                                     &info_ctr,
+                                                     &devmode_ctr,
+                                                     &secdesc_ctr,
+                                                     0, /* command */
+                                                     &result);
 
-               result = rpccli_spoolss_setprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub, 0);
                if (!W_ERROR_IS_OK(result) && (W_ERROR_V(result) != W_ERROR_V(WERR_IO_PENDING))) {
                        printf("cannot set printer-info: %s\n", win_errstr(result));
                        goto done;
@@ -1246,7 +1354,7 @@ static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_
        nt_status = NT_STATUS_OK;
 
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
 
        return nt_status;
@@ -1261,7 +1369,7 @@ NTSTATUS rpc_printer_publish_publish_internals(struct net_context *c,
                                                int argc,
                                                const char **argv)
 {
-       return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_PUBLISH);
+       return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_PUBLISH);
 }
 
 NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
@@ -1273,7 +1381,7 @@ NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
                                                int argc,
                                                const char **argv)
 {
-       return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_UNPUBLISH);
+       return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UNPUBLISH);
 }
 
 NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
@@ -1285,7 +1393,7 @@ NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
                                                int argc,
                                                const char **argv)
 {
-       return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_UPDATE);
+       return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UPDATE);
 }
 
 /**
@@ -1318,10 +1426,9 @@ NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
        uint32 i, num_printers;
        uint32 level = 7;
        char *printername, *sharename;
-       char *guid;
        PRINTER_INFO_CTR ctr, ctr_pub;
+       union spoolss_PrinterInfo info;
        POLICY_HND hnd;
-       bool got_hnd = false;
        int state;
 
        if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &ctr))
@@ -1350,32 +1457,25 @@ NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
                        PRINTER_ALL_ACCESS, cli->user_name, &hnd))
                        goto done;
 
-               got_hnd = true;
-
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub))
+               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
                        goto done;
 
-               rpcstr_pull_talloc(mem_ctx,
-                               &guid,
-                               ctr_pub.printers_7->guid.buffer,
-                               -1,
-                               STR_TERMINATE);
-               if (!guid) {
+               if (!info.info7.guid) {
                        goto done;
                }
-               state = ctr_pub.printers_7->action;
+               state = info.info7.action;
                switch (state) {
-                       case SPOOL_DS_PUBLISH:
+                       case DSPRINT_PUBLISH:
                                printf("printer [%s] is published", sharename);
                                if (c->opt_verbose)
-                                       printf(", guid: %s", guid);
+                                       printf(", guid: %s", info.info7.guid);
                                printf("\n");
                                break;
-                       case SPOOL_DS_UNPUBLISH:
+                       case DSPRINT_UNPUBLISH:
                                printf("printer [%s] is unpublished\n", sharename);
                                break;
-                       case SPOOL_DS_UPDATE:
+                       case DSPRINT_UPDATE:
                                printf("printer [%s] is currently updating\n", sharename);
                                break;
                        default:
@@ -1387,7 +1487,7 @@ NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
        nt_status = NT_STATUS_OK;
 
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
 
        return nt_status;
@@ -1427,12 +1527,11 @@ NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
        uint32 num_printers;
        uint32 level = 2;
        char *printername, *sharename;
-       bool got_hnd_src = false;
-       bool got_hnd_dst = false;
        struct rpc_pipe_client *pipe_hnd_dst = NULL;
        POLICY_HND hnd_src, hnd_dst;
-       PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
+       PRINTER_INFO_CTR ctr_src, ctr_enum;
        struct cli_state *cli_dst = NULL;
+       union spoolss_PrinterInfo info_src, info_dst;
 
        ZERO_STRUCT(ctr_src);
 
@@ -1493,47 +1592,41 @@ NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
                        MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
                        goto done;
 
-               got_hnd_src = true;
-
                /* open dst printer handle */
                if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
                        PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
                        goto done;
 
-               got_hnd_dst = true;
-
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst))
+               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
                        goto done;
 
                /* check for existing src printer */
-               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &ctr_src))
+               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &info_src))
                        goto done;
 
                /* Copy Security Descriptor */
 
                /* copy secdesc (info level 2) */
-               ctr_dst.printers_2->devmode = NULL;
-               ctr_dst.printers_2->secdesc = dup_sec_desc(mem_ctx, ctr_src.printers_3->secdesc);
+               info_dst.info2.devmode = NULL;
+               info_dst.info2.secdesc = dup_sec_desc(mem_ctx, info_src.info3.secdesc);
 
                if (c->opt_verbose)
-                       display_sec_desc(ctr_dst.printers_2->secdesc);
+                       display_sec_desc(info_dst.info2.secdesc);
 
-               if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &ctr_dst))
+               if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
                        goto done;
 
                DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
 
 
                /* close printer handles here */
-               if (got_hnd_src) {
+               if (is_valid_policy_hnd(&hnd_src)) {
                        rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
-                       got_hnd_src = false;
                }
 
-               if (got_hnd_dst) {
+               if (is_valid_policy_hnd(&hnd_dst)) {
                        rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
-                       got_hnd_dst = false;
                }
 
        }
@@ -1542,11 +1635,11 @@ NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
 
 done:
 
-       if (got_hnd_src) {
+       if (is_valid_policy_hnd(&hnd_src)) {
                rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
        }
 
-       if (got_hnd_dst) {
+       if (is_valid_policy_hnd(&hnd_dst)) {
                rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
        }
 
@@ -1588,11 +1681,10 @@ NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
        uint32 num_printers;
        uint32 level = 1;
        char *printername, *sharename;
-       bool got_hnd_src = false;
-       bool got_hnd_dst = false;
        struct rpc_pipe_client *pipe_hnd_dst = NULL;
        POLICY_HND hnd_src, hnd_dst;
-       PRINTER_INFO_CTR ctr_enum, ctr_dst;
+       PRINTER_INFO_CTR ctr_enum;
+       union spoolss_PrinterInfo info_dst;
        uint32 num_forms;
        FORM_1 *forms;
        struct cli_state *cli_dst = NULL;
@@ -1649,19 +1741,13 @@ NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
                        MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
                        goto done;
 
-               got_hnd_src = true;
-
-
                /* open dst printer handle */
                if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
                        PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
                        goto done;
 
-               got_hnd_dst = true;
-
-
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst))
+               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
                        goto done;
 
                /* finally migrate forms */
@@ -1721,14 +1807,12 @@ NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
 
 
                /* close printer handles here */
-               if (got_hnd_src) {
+               if (is_valid_policy_hnd(&hnd_src)) {
                        rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
-                       got_hnd_src = false;
                }
 
-               if (got_hnd_dst) {
+               if (is_valid_policy_hnd(&hnd_dst)) {
                        rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
-                       got_hnd_dst = false;
                }
        }
 
@@ -1736,10 +1820,10 @@ NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
 
 done:
 
-       if (got_hnd_src)
+       if (is_valid_policy_hnd(&hnd_src))
                rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
 
-       if (got_hnd_dst)
+       if (is_valid_policy_hnd(&hnd_dst))
                rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
 
        if (cli_dst) {
@@ -1779,21 +1863,18 @@ NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
        uint32 num_printers;
        uint32 level = 3;
        char *printername, *sharename;
-       bool got_hnd_src = false;
-       bool got_hnd_dst = false;
        bool got_src_driver_share = false;
        bool got_dst_driver_share = false;
        struct rpc_pipe_client *pipe_hnd_dst = NULL;
        POLICY_HND hnd_src, hnd_dst;
-       PRINTER_DRIVER_CTR drv_ctr_src, drv_ctr_dst;
+       union spoolss_DriverInfo drv_info_src;
        PRINTER_INFO_CTR info_ctr_enum, info_ctr_dst;
+       union spoolss_PrinterInfo info_dst;
        struct cli_state *cli_dst = NULL;
        struct cli_state *cli_share_src = NULL;
        struct cli_state *cli_share_dst = NULL;
-       fstring drivername = "";
+       const char *drivername = NULL;
 
-       ZERO_STRUCT(drv_ctr_src);
-       ZERO_STRUCT(drv_ctr_dst);
        ZERO_STRUCT(info_ctr_enum);
        ZERO_STRUCT(info_ctr_dst);
 
@@ -1865,10 +1946,8 @@ NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
                        PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
                        goto done;
 
-               got_hnd_dst = true;
-
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst))
+               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
                        goto done;
 
 
@@ -1879,9 +1958,6 @@ NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
                                                 &hnd_src))
                        goto done;
 
-               got_hnd_src = true;
-
-
                /* in a first step call getdriver for each shared printer (per arch)
                   to get a list of all files that have to be copied */
 
@@ -1890,15 +1966,13 @@ NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
                        /* getdriver src */
                        if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src,
                                        level, archi_table[i].long_archi,
-                                       archi_table[i].version, &drv_ctr_src))
+                                       archi_table[i].version, &drv_info_src))
                                continue;
 
-                       rpcstr_pull(drivername, drv_ctr_src.info3->name.buffer,
-                                       sizeof(drivername), -1, STR_TERMINATE);
+                       drivername = drv_info_src.info3.driver_name;
 
                        if (c->opt_verbose)
-                               display_print_driver_3(drv_ctr_src.info3);
-
+                               display_print_driver3(&drv_info_src.info3);
 
                        /* check arch dir */
                        nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
@@ -1909,13 +1983,13 @@ NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
                        /* copy driver-files */
                        nt_status = copy_print_driver_3(c, mem_ctx, cli_share_src, cli_share_dst,
                                                        archi_table[i].short_archi,
-                                                       drv_ctr_src.info3);
+                                                       &drv_info_src.info3);
                        if (!NT_STATUS_IS_OK(nt_status))
                                goto done;
 
 
                        /* adddriver dst */
-                       if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_ctr_src)) {
+                       if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_info_src)) {
                                nt_status = NT_STATUS_UNSUCCESSFUL;
                                goto done;
                        }
@@ -1932,9 +2006,9 @@ NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
                }
 
                /* setdriver dst */
-               init_unistr(&info_ctr_dst.printers_2->drivername, drivername);
+               info_dst.info2.drivername = drivername;
 
-               if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) {
+               if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst)) {
                        nt_status = NT_STATUS_UNSUCCESSFUL;
                        goto done;
                }
@@ -1943,15 +2017,13 @@ NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
                        drivername, printername));
 
                /* close dst */
-               if (got_hnd_dst) {
+               if (is_valid_policy_hnd(&hnd_dst)) {
                        rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
-                       got_hnd_dst = false;
                }
 
                /* close src */
-               if (got_hnd_src) {
+               if (is_valid_policy_hnd(&hnd_src)) {
                        rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
-                       got_hnd_src = false;
                }
        }
 
@@ -1959,10 +2031,10 @@ NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
 
 done:
 
-       if (got_hnd_src)
+       if (is_valid_policy_hnd(&hnd_src))
                rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
 
-       if (got_hnd_dst)
+       if (is_valid_policy_hnd(&hnd_dst))
                rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
 
        if (cli_dst) {
@@ -2010,13 +2082,13 @@ NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        uint32 i = 0, num_printers;
        uint32 level = 2;
-       PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
+       PRINTER_INFO_CTR ctr_enum;
+       union spoolss_PrinterInfo info_dst, info_src;
        struct cli_state *cli_dst = NULL;
        POLICY_HND hnd_dst, hnd_src;
        char *printername, *sharename;
-       bool got_hnd_src = false;
-       bool got_hnd_dst = false;
        struct rpc_pipe_client *pipe_hnd_dst = NULL;
+       struct spoolss_SetPrinterInfoCtr info_ctr;
 
        DEBUG(3,("copying printers\n"));
 
@@ -2067,19 +2139,16 @@ NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
                        PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
 
                        DEBUG(1,("could not open printer: %s\n", sharename));
-               } else {
-                       got_hnd_dst = true;
                }
 
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) {
+               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
                        printf ("could not get printer, creating printer.\n");
                } else {
                        DEBUG(1,("printer already exists: %s\n", sharename));
                        /* close printer handle here - dst only, not got src yet. */
-                       if (got_hnd_dst) {
+                       if (is_valid_policy_hnd(&hnd_dst)) {
                                rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
-                               got_hnd_dst = false;
                        }
                        continue;
                }
@@ -2092,16 +2161,20 @@ NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
                        MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
                        goto done;
 
-               got_hnd_src = true;
-
                /* getprinter on the src server */
-               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &ctr_src))
+               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
                        goto done;
 
                /* copy each src printer to a dst printer 1:1,
                   maybe some values have to be changed though */
                d_printf("creating printer: %s\n", printername);
-               result = rpccli_spoolss_addprinterex (pipe_hnd_dst, mem_ctx, level, &ctr_src);
+
+               info_ctr.level = level;
+               info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info_src.info2;
+
+               result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
+                                                    mem_ctx,
+                                                    &info_ctr);
 
                if (W_ERROR_IS_OK(result))
                        d_printf ("printer [%s] successfully added.\n", printername);
@@ -2113,24 +2186,22 @@ NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
                }
 
                /* close printer handles here */
-               if (got_hnd_src) {
+               if (is_valid_policy_hnd(&hnd_src)) {
                        rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
-                       got_hnd_src = false;
                }
 
-               if (got_hnd_dst) {
+               if (is_valid_policy_hnd(&hnd_dst)) {
                        rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
-                       got_hnd_dst = false;
                }
        }
 
        nt_status = NT_STATUS_OK;
 
 done:
-       if (got_hnd_src)
+       if (is_valid_policy_hnd(&hnd_src))
                rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
 
-       if (got_hnd_dst)
+       if (is_valid_policy_hnd(&hnd_dst))
                rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
 
        if (cli_dst) {
@@ -2175,11 +2246,10 @@ NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
        uint32 num_printers, val_needed, data_needed;
        uint32 level = 2;
        char *printername, *sharename;
-       bool got_hnd_src = false;
-       bool got_hnd_dst = false;
        struct rpc_pipe_client *pipe_hnd_dst = NULL;
        POLICY_HND hnd_src, hnd_dst;
-       PRINTER_INFO_CTR ctr_enum, ctr_dst, ctr_dst_publish;
+       PRINTER_INFO_CTR ctr_enum;
+       union spoolss_PrinterInfo info_dst_publish, info_dst;
        REGVAL_CTR *reg_ctr;
        struct cli_state *cli_dst = NULL;
        char *devicename = NULL, *unc_name = NULL, *url = NULL;
@@ -2188,6 +2258,8 @@ NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
        uint16 *keylist = NULL, *curkey;
 
        ZERO_STRUCT(ctr_enum);
+       /* FIXME GD */
+       ZERO_STRUCT(info_dst_publish);
 
        DEBUG(3,("copying printer settings\n"));
 
@@ -2247,44 +2319,39 @@ NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
                        MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
                        goto done;
 
-               got_hnd_src = true;
-
-
                /* open dst printer handle */
                if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
                        PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
                        goto done;
 
-               got_hnd_dst = true;
-
-
                /* check for existing dst printer */
                if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
-                               level, &ctr_dst))
+                               level, &info_dst))
                        goto done;
 
+#if 0 /* FIXME GD */
 
                /* STEP 1: COPY DEVICE-MODE and other
                           PRINTER_INFO_2-attributes
                */
 
-               ctr_dst.printers_2 = &ctr_enum.printers_2[i];
+               info_dst.info2 = &ctr_enum.printers_2[i];
 
                /* why is the port always disconnected when the printer
                   is correctly installed (incl. driver ???) */
-               init_unistr( &ctr_dst.printers_2->portname, SAMBA_PRINTER_PORT_NAME);
+               info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
 
                /* check if printer is published */
                if (ctr_enum.printers_2[i].attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
 
                        /* check for existing dst printer */
-                       if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish))
+                       if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
                                goto done;
 
-                       ctr_dst_publish.printers_7->action = SPOOL_DS_PUBLISH;
+                       info_dst_publish.info7.action = DSPRINT_PUBLISH;
 
                        /* ignore false from setprinter due to WERR_IO_PENDING */
-                       net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish);
+                       net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
 
                        DEBUG(3,("republished printer\n"));
                }
@@ -2292,14 +2359,14 @@ NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
                if (ctr_enum.printers_2[i].devmode != NULL) {
 
                        /* copy devmode (info level 2) */
-                       ctr_dst.printers_2->devmode = (DEVICEMODE *)
+                       info_dst.info2.devmode = (DEVICEMODE *)
                                TALLOC_MEMDUP(mem_ctx,
                                              ctr_enum.printers_2[i].devmode,
                                              sizeof(DEVICEMODE));
 
                        /* do not copy security descriptor (we have another
                         * command for that) */
-                       ctr_dst.printers_2->secdesc = NULL;
+                       info_dst.info2.secdesc = NULL;
 
 #if 0
                        if (asprintf(&devicename, "\\\\%s\\%s", longname,
@@ -2312,12 +2379,12 @@ NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
                                    devicename);
 #endif
                        if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
-                                                   level, &ctr_dst))
+                                                   level, &info_dst))
                                goto done;
 
                        DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
                }
-
+#endif
                /* STEP 2: COPY REGISTRY VALUES */
 
                /* please keep in mind that samba parse_spools gives horribly
@@ -2496,14 +2563,12 @@ NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
                SAFE_FREE(keylist);
 
                /* close printer handles here */
-               if (got_hnd_src) {
+               if (is_valid_policy_hnd(&hnd_src)) {
                        rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
-                       got_hnd_src = false;
                }
 
-               if (got_hnd_dst) {
+               if (is_valid_policy_hnd(&hnd_dst)) {
                        rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
-                       got_hnd_dst = false;
                }
 
        }
@@ -2515,10 +2580,10 @@ done:
        SAFE_FREE(url);
        SAFE_FREE(unc_name);
 
-       if (got_hnd_src)
+       if (is_valid_policy_hnd(&hnd_src))
                rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
 
-       if (got_hnd_dst)
+       if (is_valid_policy_hnd(&hnd_dst))
                rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
 
        if (cli_dst) {
index 005e3ca556085c831f543c07f6d7d00ad9090000..00c827928eac1a4b06f2ac9b54d50b08b6ddfe08 100644 (file)
@@ -971,12 +971,15 @@ static bool write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
 {
        REGF_NK_REC *key, *subkey;
        REGVAL_CTR *values = NULL;
-       REGSUBKEY_CTR *subkeys = NULL;
+       struct regsubkey_ctr *subkeys = NULL;
        int i;
        char *path = NULL;
+       WERROR werr;
 
-       if ( !( subkeys = TALLOC_ZERO_P( infile->mem_ctx, REGSUBKEY_CTR )) ) {
-               DEBUG(0,("write_registry_tree: talloc() failed!\n"));
+       werr = regsubkey_ctr_init(infile->mem_ctx, &subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
+               DEBUG(0, ("write_registry_tree: regsubkey_ctr_init failed: "
+                         "%s\n", win_errstr(werr)));
                return false;
        }
 
@@ -993,7 +996,7 @@ static bool write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
                        (const char *)nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
        }
 
-       /* copy subkeys into the REGSUBKEY_CTR */
+       /* copy subkeys into the struct regsubkey_ctr */
 
        while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
                regsubkey_ctr_addkey( subkeys, subkey->keyname );
index 5dd788ad5ff937eac2c7d13d40422083ab280c2f..0ac93dedeb8beb6a0c9caf49353489bcc91466e1 100644 (file)
@@ -57,7 +57,7 @@ static void verbose_output(const char *format, ...)
 
 static bool swap_sid_in_acl( SEC_DESC *sd, DOM_SID *s1, DOM_SID *s2 )
 {
-       SEC_ACL *acl;
+       SEC_ACL *theacl;
        int i;
        bool update = False;
 
@@ -78,30 +78,30 @@ static bool swap_sid_in_acl( SEC_DESC *sd, DOM_SID *s1, DOM_SID *s2 )
                        sid_string_tos(sd->group_sid));
        }
 
-       acl = sd->dacl;
-       verbose_output("  DACL: %d entries:\n", acl->num_aces);
-       for ( i=0; i<acl->num_aces; i++ ) {
+       theacl = sd->dacl;
+       verbose_output("  DACL: %d entries:\n", theacl->num_aces);
+       for ( i=0; i<theacl->num_aces; i++ ) {
                verbose_output("    Trustee SID: %s\n", 
-                       sid_string_tos(&acl->aces[i].trustee));
-               if ( sid_equal( &acl->aces[i].trustee, s1 ) ) {
-                       sid_copy( &acl->aces[i].trustee, s2 );
+                       sid_string_tos(&theacl->aces[i].trustee));
+               if ( sid_equal( &theacl->aces[i].trustee, s1 ) ) {
+                       sid_copy( &theacl->aces[i].trustee, s2 );
                        update = True;
                        verbose_output("    New Trustee SID: %s\n", 
-                               sid_string_tos(&acl->aces[i].trustee));
+                               sid_string_tos(&theacl->aces[i].trustee));
                }
        }
 
 #if 0
-       acl = sd->sacl;
-       verbose_output("  SACL: %d entries: \n", acl->num_aces);
-       for ( i=0; i<acl->num_aces; i++ ) {
+       theacl = sd->sacl;
+       verbose_output("  SACL: %d entries: \n", theacl->num_aces);
+       for ( i=0; i<theacl->num_aces; i++ ) {
                verbose_output("    Trustee SID: %s\n", 
-                       sid_string_tos(&acl->aces[i].trustee));
-               if ( sid_equal( &acl->aces[i].trustee, s1 ) ) {
-                       sid_copy( &acl->aces[i].trustee, s2 );
+                       sid_string_tos(&theacl->aces[i].trustee));
+               if ( sid_equal( &theacl->aces[i].trustee, s1 ) ) {
+                       sid_copy( &theacl->aces[i].trustee, s2 );
                        update = True;
                        verbose_output("    New Trustee SID: %s\n", 
-                               sid_string_tos(&acl->aces[i].trustee));
+                               sid_string_tos(&theacl->aces[i].trustee));
                }
        }
 #endif
@@ -118,9 +118,10 @@ static bool copy_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
        REGF_NK_REC *key, *subkey;
        SEC_DESC *new_sd;
        REGVAL_CTR *values;
-       REGSUBKEY_CTR *subkeys;
+       struct regsubkey_ctr *subkeys;
        int i;
        char *path;
+       WERROR werr;
 
        /* swap out the SIDs in the security descriptor */
 
@@ -132,7 +133,8 @@ static bool copy_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
        verbose_output("ACL for %s%s%s\n", parentpath, parent ? "\\" : "", nk->keyname);
        swap_sid_in_acl( new_sd, &old_sid, &new_sid );
 
-       if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) {
+       werr = regsubkey_ctr_init(NULL, &subkeys);
+       if (!W_ERROR_IS_OK(werr)) {
                DEBUG(0,("copy_registry_tree: talloc() failure!\n"));
                return False;
        }
@@ -150,7 +152,7 @@ static bool copy_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
                        (const char *)nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
        }
 
-       /* copy subkeys into the REGSUBKEY_CTR */
+       /* copy subkeys into the struct regsubkey_ctr */
 
        while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
                regsubkey_ctr_addkey( subkeys, subkey->keyname );
index ae2a9adf6497ae0bab8bd13ef7da85694e6e0428..4be77ecadd633f888ad79ea18506a1bfc03a2fe0 100644 (file)
@@ -298,7 +298,7 @@ static SEC_DESC* parse_acl_string(TALLOC_CTX *mem_ctx, const char *szACL, size_t
 {
        SEC_DESC *sd = NULL;
        SEC_ACE *ace;
-       SEC_ACL *acl;
+       SEC_ACL *theacl;
        int num_ace;
        const char *pacl;
        int i;
@@ -326,11 +326,11 @@ static SEC_DESC* parse_acl_string(TALLOC_CTX *mem_ctx, const char *szACL, size_t
                pacl++;
        }
 
-       if ( !(acl = make_sec_acl( mem_ctx, NT4_ACL_REVISION, num_ace, ace )) )
+       if ( !(theacl = make_sec_acl( mem_ctx, NT4_ACL_REVISION, num_ace, ace )) )
                return NULL;
 
        sd = make_sec_desc( mem_ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
-               NULL, NULL, NULL, acl, sd_size);
+               NULL, NULL, NULL, theacl, sd_size);
 
        return sd;
 }
index 1fdea818d6e47ae3a5d4ade03a4bc5c44678bfc9..39a264011eed4cf90acd6d9ac47893f096d30711 100644 (file)
@@ -91,8 +91,15 @@ static void filter_request(char *buf)
                        d_printf("sesion_request: %s -> %s\n",
                                 name1, name2);
                        if (netbiosname) {
-                               /* replace the destination netbios name */
-                               name_mangle(netbiosname, buf+4, 0x20);
+                               char *mangled = name_mangle(
+                                       talloc_tos(), netbiosname, 0x20);
+                               if (mangled != NULL) {
+                                       /* replace the destination netbios
+                                        * name */
+                                       memcpy(buf+4, mangled,
+                                              name_len(mangled));
+                                       TALLOC_FREE(mangled);
+                               }
                        }
                }
                return;
index c062134a55eb19eab5306bee9dac66338f34b2a0..042f3a98f712b2fab26770b60059d9802f2971d2 100644 (file)
@@ -194,7 +194,8 @@ static int smb_download_dir(const char *base, const char *name, int resume)
                }
                
                if(chmod(relname, remotestat.st_mode) < 0) {
-                       fprintf(stderr, "Unable to change mode of local dir %s to %o\n", relname, remotestat.st_mode);
+                       fprintf(stderr, "Unable to change mode of local dir %s to %o\n", relname,
+                               (unsigned int)remotestat.st_mode);
                        smbc_closedir(dirhandle);
                        return 0;
                }
@@ -471,7 +472,8 @@ static int smb_download_file(const char *base, const char *name, int recursive,
 
        if(keep_permissions && !send_stdout) {
                if(fchmod(localhandle, remotestat.st_mode) < 0) {
-                       fprintf(stderr, "Unable to change mode of local file %s to %o\n", path, remotestat.st_mode);
+                       fprintf(stderr, "Unable to change mode of local file %s to %o\n", path,
+                               (unsigned int)remotestat.st_mode);
                        smbc_close(remotehandle);
                        close(localhandle);
                        return 0;
@@ -487,7 +489,8 @@ static void clean_exit(void)
 {
        char bs[100];
        human_readable(total_bytes, bs, sizeof(bs));
-       if(!quiet)fprintf(stderr, "Downloaded %s in %lu seconds\n", bs, time(NULL) - total_start_time);
+       if(!quiet)fprintf(stderr, "Downloaded %s in %lu seconds\n", bs,
+               (unsigned long)(time(NULL) - total_start_time));
        exit(0);
 }
 
index c86a5023d0c372bae2a427ec872eeff68650fd3e..7224589076e1157b5901c5dcea834f3d16e7c198 100644 (file)
@@ -935,6 +935,10 @@ static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom,
                multi = True;
        }
 
+       for (i = 0; ids[i]; i++) {
+               ids[i]->status = ID_UNKNOWN;
+       }
+
 again:
        if (multi) {
 
@@ -1156,6 +1160,10 @@ static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom,
                multi = True;
        }
 
+       for (i = 0; ids[i]; i++) {
+               ids[i]->status = ID_UNKNOWN;
+       }
+
 again:
        if (multi) {
 
index be91611bfb99f0965f4b2276b273857b3acb5ba4..dbe83152dd3baec9bec712f12331896752198909 100644 (file)
@@ -386,7 +386,7 @@ static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
        if (child_pid != 0) {
                /* parent */
                DEBUG(5, ("winbind_msg_validate_cache: child created with "
-                         "pid %d.\n", child_pid));
+                         "pid %d.\n", (int)child_pid));
                return;
        }
 
index 8326aba40a0039ca84ff676d8c747d062a04d9cc..02d0b5bc4e4a67611ce51bfe8697e15311284595 100644 (file)
@@ -2625,9 +2625,9 @@ void cache_store_response(pid_t pid, struct winbindd_response *response)
                return;
 
        DEBUG(10, ("Storing response for pid %d, len %d\n",
-                  pid, response->length));
+                  (int)pid, response->length));
 
-       fstr_sprintf(key_str, "DR/%d", pid);
+       fstr_sprintf(key_str, "DR/%d", (int)pid);
        if (tdb_store(wcache->tdb, string_tdb_data(key_str), 
                      make_tdb_data((uint8 *)response, sizeof(*response)),
                      TDB_REPLACE) == -1)
@@ -2641,7 +2641,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response)
        DEBUG(10, ("Storing extra data: len=%d\n",
                   (int)(response->length - sizeof(*response))));
 
-       fstr_sprintf(key_str, "DE/%d", pid);
+       fstr_sprintf(key_str, "DE/%d", (int)pid);
        if (tdb_store(wcache->tdb, string_tdb_data(key_str),
                      make_tdb_data((uint8 *)response->extra_data.data,
                                    response->length - sizeof(*response)),
@@ -2651,7 +2651,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response)
        /* We could not store the extra data, make sure the tdb does not
         * contain a main record with wrong dangling extra data */
 
-       fstr_sprintf(key_str, "DR/%d", pid);
+       fstr_sprintf(key_str, "DR/%d", (int)pid);
        tdb_delete(wcache->tdb, string_tdb_data(key_str));
 
        return;
@@ -2665,9 +2665,9 @@ bool cache_retrieve_response(pid_t pid, struct winbindd_response * response)
        if (!init_wcache())
                return false;
 
-       DEBUG(10, ("Retrieving response for pid %d\n", pid));
+       DEBUG(10, ("Retrieving response for pid %d\n", (int)pid));
 
-       fstr_sprintf(key_str, "DR/%d", pid);
+       fstr_sprintf(key_str, "DR/%d", (int)pid);
        data = tdb_fetch(wcache->tdb, string_tdb_data(key_str));
 
        if (data.dptr == NULL)
@@ -2689,7 +2689,7 @@ bool cache_retrieve_response(pid_t pid, struct winbindd_response * response)
        DEBUG(10, ("Retrieving extra data length=%d\n",
                   (int)(response->length - sizeof(*response))));
 
-       fstr_sprintf(key_str, "DE/%d", pid);
+       fstr_sprintf(key_str, "DE/%d", (int)pid);
        data = tdb_fetch(wcache->tdb, string_tdb_data(key_str));
 
        if (data.dptr == NULL) {
@@ -2716,10 +2716,10 @@ void cache_cleanup_response(pid_t pid)
        if (!init_wcache())
                return;
 
-       fstr_sprintf(key_str, "DR/%d", pid);
+       fstr_sprintf(key_str, "DR/%d", (int)pid);
        tdb_delete(wcache->tdb, string_tdb_data(key_str));
 
-       fstr_sprintf(key_str, "DE/%d", pid);
+       fstr_sprintf(key_str, "DE/%d", (int)pid);
        tdb_delete(wcache->tdb, string_tdb_data(key_str));
 
        return;
index d40bab94ef9e5b33ed54ce729ee8f19bac348732..f56a63faa0cbdbaa2a1d7a2c37a141775de3b43c 100644 (file)
@@ -183,7 +183,7 @@ static void async_request_timeout_handler(struct event_context *ctx,
 
        DEBUG(0,("async_request_timeout_handler: child pid %u is not responding. "
                "Closing connection to it.\n",
-               state->child_pid ));
+               (unsigned int)state->child_pid ));
 
        /* Deal with the reply - set to error. */
        async_reply_recv(private_data, False);
index 508836f6da00d835515bd85339ed2c53e5eb6fa1..15b1b8ba40382573716ed20fd20566f360e14ff9 100644 (file)
@@ -146,7 +146,7 @@ endif
 clean::
        @find ../lib ../libcli ../librpc ../nsswitch -name '*.o' -o -name '*.ho' | xargs rm -f
 
-PUBLIC_HEADERS += $(srcdir)/version.h
+PUBLIC_HEADERS += ./version.h
 
 libraries:: $(STATIC_LIBS) $(SHARED_LIBS)
 modules:: $(PLUGINS)
index e7d05f6a09a15ab78d6bd852eac2b4b613ec16fe..58f8cc169dbe1a720290c91b6af312029a2b760d 100644 (file)
@@ -57,7 +57,7 @@ SAMBA_VERSION_TP_RELEASE=
 # e.g. SAMBA_VERSION_ALPHA_RELEASE=1                   #
 #  ->  "4.0.0alpha1"                                   #
 ########################################################
-SAMBA_VERSION_ALPHA_RELEASE=7
+SAMBA_VERSION_ALPHA_RELEASE=8
 
 ########################################################
 # For 'pre' releases the version will be               #
index 1823f1ba97989f1997b5a187d48d68b200e33b18..ffdf92f78444a100315be4579b8f4a8e607ceb62 100644 (file)
@@ -6,6 +6,8 @@ dnl Published under the GPL
 dnl
 dnl SMB_EXT_LIB_FROM_PKGCONFIG(name,pkg-config name,[ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
 dnl
+dnl SMB_INCLUDED_LIB_PKGCONFIG(name,pkg-config name,[ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
+dnl
 dnl SMB_EXT_LIB(name,libs,cflags,cppflags,ldflags)
 dnl
 dnl SMB_ENABLE(name,default_build)
@@ -125,6 +127,28 @@ AC_DEFUN([SMB_EXT_LIB_FROM_PKGCONFIG],
        fi
 ])
 
+dnl SMB_INCLUDED_LIB_PKGCONFIG(name,pkg-config name,[ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
+AC_DEFUN([SMB_INCLUDED_LIB_PKGCONFIG],
+[
+       AC_ARG_ENABLE([external-]translit($1,`A-Z',`a-z'),
+               AS_HELP_STRING([--enable-external-]translit($1,`A-Z',`a-z'), [Use external $1 instead of built-in (default=ifelse([$5],[],auto,$5))]), [], [enableval=ifelse([$5],[],auto,$5)])
+
+       if test $enableval = yes -o $enableval = auto; then
+               SMB_EXT_LIB_FROM_PKGCONFIG([$1], [$2], [$3], [
+                       if test $enableval = yes; then
+                               AC_MSG_ERROR([Unable to find external $1])
+                       fi
+                       enableval=no
+               ])
+       fi
+       if test $enableval = no; then
+               ifelse([$4], [], [
+                         SMB_EXT_LIB($1)
+                         SMB_ENABLE($1, NO)
+               ], [$4])
+       fi
+])
+
 dnl SMB_INCLUDE_MK(file)
 AC_DEFUN([SMB_INCLUDE_MK],
 [
@@ -133,6 +157,13 @@ mkinclude $1
 "
 ])
 
+dnl
+dnl SMB_EXT_LIB() just specifies the details of the library.
+dnl Note: the library isn't enabled by default.
+dnl You need to enable it with SMB_ENABLE(name) if configure
+dnl find it should be used. E.g. it should not be enabled
+dnl if the library is present, but the header file is missing.
+dnl
 dnl SMB_EXT_LIB(name,libs,cflags,cppflags,ldflags)
 AC_DEFUN([SMB_EXT_LIB],
 [
index 7167859d7b2e6fa403c604b0205c367da00dfa2b..899c90cefd28a18e9276b8c551fcf09c64622137 100644 (file)
@@ -313,8 +313,10 @@ int main(int argc, char ** argv)
        FILE * pmntfile;
 
        /* setlocale(LC_ALL, "");
+#if defined(LOCALEDIR)
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE); */
+#endif
 
        if(argc && argv) {
                thisprogram = argv[0];
index 85ea44f570fe6a2ac57f41bc73e44e73aeacb02c..54ca9108b14d0d7857d34c06e772781f93a72188 100644 (file)
@@ -42,15 +42,14 @@ AC_CONFIG_FILES(param/samba-hostconfig.pc)
 AC_CONFIG_FILES(librpc/dcerpc_samr.pc)
 AC_CONFIG_FILES(librpc/dcerpc_atsvc.pc)
 
-SMB_EXT_LIB_FROM_PKGCONFIG(LIBTALLOC, talloc >= 1.2.0,
-       [],
+SMB_INCLUDED_LIB_PKGCONFIG(LIBTALLOC, talloc >= 1.2.0, [],
        [
                m4_include(../lib/talloc/libtalloc.m4)
                SMB_INCLUDE_MK(../lib/talloc/config.mk)
        ]
 )
 
-SMB_EXT_LIB_FROM_PKGCONFIG(LIBTDB, tdb >= 1.1.3,
+SMB_INCLUDED_LIB_PKGCONFIG(LIBTDB, tdb >= 1.1.3,
        [],
        [
                m4_include(../lib/tdb/libtdb.m4)
@@ -60,13 +59,13 @@ SMB_EXT_LIB_FROM_PKGCONFIG(LIBTDB, tdb >= 1.1.3,
 
 SMB_INCLUDE_MK(../lib/tdb/python.mk) 
 
-SMB_EXT_LIB_FROM_PKGCONFIG(LIBTEVENT, tevent = 0.9.3,
+SMB_INCLUDED_LIB_PKGCONFIG(LIBTEVENT, tevent = 0.9.3,
        [],[m4_include(../lib/tevent/samba.m4)]
 )
 
 SMB_INCLUDE_MK(../lib/tevent/python.mk) 
 
-SMB_EXT_LIB_FROM_PKGCONFIG(LIBLDB, ldb = 0.9.3,
+SMB_INCLUDED_LIB_PKGCONFIG(LIBLDB, ldb = 0.9.3,
        [
                SMB_INCLUDE_MK(lib/ldb/ldb_ildap/config.mk)
                SMB_INCLUDE_MK(lib/ldb/tools/config.mk)
@@ -96,8 +95,7 @@ SMB_EXT_LIB_FROM_PKGCONFIG(LIBLDB, ldb = 0.9.3,
                m4_include(lib/ldb/libldb.m4)
                SMB_INCLUDE_MK(lib/ldb/config.mk)
                AC_CONFIG_FILES(lib/ldb/ldb.pc)
-       ]
-)
+       ], [no])
 SMB_INCLUDE_MK(lib/ldb/python.mk) 
 
 m4_include(lib/tls/config.m4)
index 01f5188b6f45c25512b7fd8a1c0d603e0f092784..583d1dcf042e1a2a7bfc7dfa006132e4d5729386 100644 (file)
@@ -89,7 +89,7 @@ ldb_samldb_OBJ_FILES = \
 [MODULE::ldb_samba3sam]
 SUBSYSTEM = LIBLDB
 INIT_FUNCTION = LDB_MODULE(samba3sam)
-PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS SMBPASSWD \
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS LIBLDB SMBPASSWD \
                        NSS_WRAPPER LIBSECURITY NDR_SECURITY
 # End MODULE ldb_samldb
 ################################################
@@ -102,7 +102,7 @@ ldb_samba3sam_OBJ_FILES = \
 [MODULE::ldb_simple_ldap_map]
 SUBSYSTEM = LIBLDB
 INIT_FUNCTION = LDB_MODULE(entryuuid),LDB_MODULE(nsuniqueid)
-PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS LIBNDR
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS LIBLDB LIBNDR
 ENABLE = YES
 ALIASES = entryuuid nsuniqueid
 # End MODULE ldb_entryuuid
index 2365a58f78ac3f88dc38bebf22d1b58420d12eb8..4e28c8a1496b8d85846ffdcd67412caba845bda5 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "includes.h"
 #include "ldb_module.h"
+#include "dlinklist.h"
 #include "dsdb/samdb/samdb.h"
 
 struct la_op_store {
index 0261bb32e9274d6026f2234cdb1373d8c3a3f370..898d9139659598745acebe4ebb554e23aa4bdb7f 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "includes.h"
 #include "ldb_module.h"
+#include "dlinklist.h"
 #include "dsdb/samdb/samdb.h"
 #include "librpc/ndr/libndr.h"
 #include "librpc/gen_ndr/ndr_security.h"
index 8f36baa7d6382e654a75c0c26c26748c6c6dc94b..5ce69a26a2f1958c80ceae7e09105eed388b7af5 100644 (file)
@@ -29,6 +29,7 @@
  *  Author: Andrew Bartlett
  */
 
+#include "includes.h"
 #include "ldb_module.h"
 
 struct rr_context {
index 3f10748085305a202501aaf0edb578cd1b979f7a..59cb9de71701fc1ae70970a0dd58c122fcc47613 100644 (file)
@@ -6,7 +6,7 @@
 */
 
 #include "includes.h"
-#include "ldb/include/ldb_module.h"
+#include "ldb_module.h"
 #include "ldb/ldb_map/ldb_map.h"
 #include "system/passwd.h"
 
index 8920afee71a439641649666559ef9ca6c58221bc..f1b6863cdbe0ea6ecb269930b331b0bb9ec6f044 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "includes.h"
 #include "ldb_module.h"
+#include "dlinklist.h"
 #include "auth/credentials/credentials.h"
 #include "auth/credentials/credentials_krb5.h"
 #include "system/kerberos.h"
index d6b3e40e1afbf40739f1f3c2d0e14a86bbe20e70..6abd8a8f883e3f0e49097eeb91b2892b6735c047 100644 (file)
@@ -21,6 +21,7 @@
 */
 
 #include "includes.h"
+#include "dlinklist.h"
 #include "dsdb/samdb/samdb.h"
 #include "lib/ldb/include/ldb_module.h"
 #include "param/param.h"
index 8f3749a3b5dff29bb95c47aa6a57cfce56e3b222..82870446223ef7d715aa70b601e684af1ba31cfa 100644 (file)
@@ -49,7 +49,9 @@ param/share.h: share.h
 ../lib/util/util_tdb.h: util_tdb.h
 ../lib/util/util_ldb.h: util_ldb.h
 ../lib/util/wrap_xattr.h: wrap_xattr.h
-libcli/ldap/ldap_ndr.h: ldap_ndr.h
+../libcli/ldap/ldap_message.h: ldap_message.h
+../libcli/ldap/ldap_errors.h: ldap_errors.h
+../libcli/ldap/ldap_ndr.h: ldap_ndr.h
 ../lib/tevent/tevent.h: tevent.h
 ../lib/tevent/tevent_internal.h: tevent_internal.h
 auth/session.h: samba/session.h
index d1ef7767161647ee8878080f488e9757caf95564..fbb2d2287bcd012b4b2d7cda162b98742b768ae7 100644 (file)
@@ -726,8 +726,10 @@ main (int argc, char **argv)
     setprogname (argv[0]);
 
     setlocale (LC_ALL, "");
+#if defined(HEIMDAL_LOCALEDIR)
     bindtextdomain ("heimdal_kuser", HEIMDAL_LOCALEDIR);
     textdomain("heimdal_kuser");
+#endif
 
     ret = krb5_init_context (&context);
     if (ret == KRB5_CONFIG_BADFORMAT)
index 21e977697575f3d04121c38f0f8e117e2dea1f8e..eed9e00af6bf9e05f437b9f73202c59d73c713b0 100644 (file)
@@ -88,7 +88,7 @@
 #include <locale.h>
 #endif
 
-#ifdef LIBINTL
+#ifdef HAVE_LIBINTL_H
 #include <libintl.h>
 #define N_(x,y) gettext(x)
 #define NP_(x,y) (x)
index aa35a184c050fc4c67dfcd8c97e6c9d81525ed91..127dfa117dc83b2dd22d402775826c17db0e9684 100644 (file)
@@ -295,7 +295,9 @@ krb5_init_context(krb5_context *context)
     *context = NULL;
 
     /* should have a run_once */
+#if defined(HEIMDAL_LOCALEDIR)
     bindtextdomain(HEIMDAL_TEXTDOMAIN, HEIMDAL_LOCALEDIR);
+#endif
 
     p = calloc(1, sizeof(*p));
     if(!p)
@@ -836,20 +838,30 @@ krb5_init_ets(krb5_context context)
 {
     if(context->et_list == NULL){
        krb5_add_et_list(context, initialize_krb5_error_table_r);
+#if defined(HEIMDAL_LOCALEDIR)
        bindtextdomain(COM_ERR_BINDDOMAIN_krb5, HEIMDAL_LOCALEDIR);
+#endif
 
        krb5_add_et_list(context, initialize_asn1_error_table_r);
+#if defined(HEIMDAL_LOCALEDIR)
        bindtextdomain(COM_ERR_BINDDOMAIN_asn1, HEIMDAL_LOCALEDIR);
+#endif
 
        krb5_add_et_list(context, initialize_heim_error_table_r);
+#if defined(HEIMDAL_LOCALEDIR)
        bindtextdomain(COM_ERR_BINDDOMAIN_heim, HEIMDAL_LOCALEDIR);
+#endif
 
        krb5_add_et_list(context, initialize_k524_error_table_r);
+#if defined(HEIMDAL_LOCALEDIR)
        bindtextdomain(COM_ERR_BINDDOMAIN_k524, HEIMDAL_LOCALEDIR);
+#endif
 
 #ifdef PKINIT
        krb5_add_et_list(context, initialize_hx_error_table_r);
+#if defined(HEIMDAL_LOCALEDIR)
        bindtextdomain(COM_ERR_BINDDOMAIN_hx, HEIMDAL_LOCALEDIR);
+#endif
 #endif
     }
 }
index 1a490392a92b4e0a5f6a96e9ceb2e25c78f854f9..ced722f2d9c05f4a58dabe5ba8cf7d1a06b1ba8a 100644 (file)
@@ -118,7 +118,7 @@ struct sockaddr_dl;
 
 #define HEIMDAL_TEXTDOMAIN "heimdal_krb5"
 
-#ifdef LIBINTL
+#ifdef HAVE_LIBINTL_H
 #include <libintl.h>
 #define N_(x,y) dgettext(HEIMDAL_TEXTDOMAIN, x)
 #else
index b2f64a6825b27e807c7622cf6379e04ad424f17f..4cd7521c3781f02082357b2334f1de4169598fd7 100644 (file)
@@ -69,13 +69,15 @@ AC_CHECK_HEADERS([                          \
        ttyname.h                               \
        netinet/in.h                            \
        netinet/in6.h                           \
-       netinet6/in6.h
+       netinet6/in6.h                          \
+       libintl.h
 ])
 
 AC_CHECK_FUNCS([                               \
        atexit                                  \
        cgetent                                 \
        getprogname                             \
+       setprogname                             \
        inet_aton                               \
        gethostname                             \
        getnameinfo                             \
@@ -169,6 +171,12 @@ SMB_ENABLE(OPENPTY,YES)
 
 SMB_EXT_LIB(OPENPTY,[${OPENPTY_LIBS}],[${OPENPTY_CFLAGS}],[${OPENPTY_CPPFLAGS}],[${OPENPTY_LDFLAGS}])
 
+AC_CHECK_LIB_EXT(intl, INTL_LIBS, gettext)
+
+SMB_ENABLE(INTL,YES)
+
+SMB_EXT_LIB(INTL, $INTL_LIBS)
+
 smb_save_LIBS=$LIBS
 RESOLV_LIBS=""
 LIBS=""
@@ -261,16 +269,18 @@ SMB_ENABLE(compile_et, YES)
 
 # only add closefrom if needed
 SMB_ENABLE(HEIMDAL_ROKEN_CLOSEFROM, NO)
+SMB_ENABLE(HEIMDAL_ROKEN_CLOSEFROM_H, NO)
 if test t$ac_cv_func_closefrom != tyes; then
        SMB_ENABLE(HEIMDAL_ROKEN_CLOSEFROM, YES)
+       SMB_ENABLE(HEIMDAL_ROKEN_CLOSEFROM_H, YES)
 fi
 
 # only add getprogname if needed
-SMB_ENABLE(HEIMDAL_ROKEN_GETPROGNAME, NO)
-SMB_ENABLE(HEIMDAL_ROKEN_GETPROGNAME_H, NO)
+SMB_ENABLE(HEIMDAL_ROKEN_PROGNAME, NO)
+SMB_ENABLE(HEIMDAL_ROKEN_PROGNAME_H, NO)
 if test t$ac_cv_func_getprogname != tyes; then
-       SMB_ENABLE(HEIMDAL_ROKEN_GETPROGNAME, YES)
-       SMB_ENABLE(HEIMDAL_ROKEN_GETPROGNAME_H, YES)
+       SMB_ENABLE(HEIMDAL_ROKEN_PROGNAME, YES)
+       SMB_ENABLE(HEIMDAL_ROKEN_PROGNAME_H, YES)
 fi
 
 VPATH="$VPATH:\$(HEIMDAL_VPATH)"
index 9e32898a0757d4622cd12683e7a86575d8994c69..ea8d4731dbf95976e2c06054861af7fef22ddb25 100644 (file)
@@ -255,7 +255,7 @@ HEIMDAL_GSSAPI_OBJ_FILES = \
 CFLAGS = -I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/krb5 -I$(heimdalsrcdir)/lib/asn1 -I$(heimdalsrcdir)/lib/com_err 
 PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN HEIMDAL_PKINIT_ASN1 HEIMDAL_WIND \
                HEIMDAL_KRB5_ASN1 HEIMDAL_HX509 HEIMDAL_HCRYPTO \
-               LIBNETIF LIBSAMBA-HOSTCONFIG
+               LIBNETIF LIBSAMBA-HOSTCONFIG INTL
 PUBLIC_DEPENDENCIES = HEIMDAL_COM_ERR
 # End SUBSYSTEM HEIMDAL_KRB5
 #######################
@@ -568,27 +568,36 @@ $(heimdalsrcdir)/lib/wind/bidi_table.h $(heimdalsrcdir)/lib/wind/bidi_table.c: $
 clean::
        @rm -f $(heimdalsrcdir)/lib/wind/bidi_table.h $(heimdalsrcdir)/lib/wind/bidi_table.c
 
-[SUBSYSTEM::HEIMDAL_ROKEN_GETPROGNAME]
+[SUBSYSTEM::HEIMDAL_ROKEN_PROGNAME]
 
-HEIMDAL_ROKEN_GETPROGNAME_OBJ_FILES = $(heimdalsrcdir)/lib/roken/getprogname.o
-$(HEIMDAL_ROKEN_GETPROGNAME_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken  -I$(socketwrappersrcdir)
+HEIMDAL_ROKEN_PROGNAME_OBJ_FILES = \
+                       $(heimdalsrcdir)/lib/roken/getprogname.o \
+                       $(heimdalsrcdir)/lib/roken/setprogname.o
+$(HEIMDAL_ROKEN_PROGNAME_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken  -I$(socketwrappersrcdir)
 
 [SUBSYSTEM::HEIMDAL_ROKEN_CLOSEFROM] 
 
 HEIMDAL_ROKEN_CLOSEFROM_OBJ_FILES = $(heimdalsrcdir)/lib/roken/closefrom.o
 $(HEIMDAL_ROKEN_CLOSEFROM_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken  -I$(socketwrappersrcdir)
 
-[SUBSYSTEM::HEIMDAL_ROKEN_GETPROGNAME_H] 
+[SUBSYSTEM::HEIMDAL_ROKEN_PROGNAME_H]
 
-HEIMDAL_ROKEN_GETPROGNAME_H_OBJ_FILES = $(heimdalsrcdir)/lib/roken/getprogname.ho
-$(HEIMDAL_ROKEN_GETPROGNAME_H_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken  -I$(socketwrappersrcdir)
+HEIMDAL_ROKEN_PROGNAME_H_OBJ_FILES = \
+                       $(heimdalsrcdir)/lib/roken/getprogname.ho \
+                       $(heimdalsrcdir)/lib/roken/setprogname.ho
+$(HEIMDAL_ROKEN_PROGNAME_H_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken -DSOCKET_WRAPPER_DISABLE=1
+
+[SUBSYSTEM::HEIMDAL_ROKEN_CLOSEFROM_H]
+
+HEIMDAL_ROKEN_CLOSEFROM_H_OBJ_FILES = $(heimdalsrcdir)/lib/roken/closefrom.ho
+$(HEIMDAL_ROKEN_CLOSEFROM_H_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken -DSOCKET_WRAPPER_DISABLE=1
 
 #######################
 # Start SUBSYSTEM HEIMDAL_ROKEN
 [SUBSYSTEM::HEIMDAL_ROKEN]
 CFLAGS =  -I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken -I$(socketwrappersrcdir)
 PRIVATE_DEPENDENCIES = \
-                       HEIMDAL_ROKEN_GETPROGNAME \
+                       HEIMDAL_ROKEN_PROGNAME \
                        HEIMDAL_ROKEN_CLOSEFROM \
                        RESOLV \
                        LIBREPLACE_NETWORK
@@ -615,7 +624,6 @@ HEIMDAL_ROKEN_OBJ_FILES = \
        $(heimdalsrcdir)/lib/roken/roken_gethostby.o \
        $(heimdalsrcdir)/lib/roken/signal.o \
        $(heimdalsrcdir)/lib/roken/vis.o \
-       $(heimdalsrcdir)/lib/roken/setprogname.o \
        $(heimdalsrcdir)/lib/roken/strlwr.o \
        $(heimdalsrcdir)/lib/roken/strsep_copy.o \
        $(heimdalsrcdir)/lib/roken/strsep.o \
@@ -631,7 +639,17 @@ HEIMDAL_ROKEN_OBJ_FILES = \
        $(heimdalbuildsrcdir)/replace.o
 
 $(HEIMDAL_ROKEN_OBJ_FILES) $(HEIMDAL_ROKEN_OBJ_FILES:.o=.d):: $(heimdalsrcdir)/lib/roken/roken.h
-$(HEIMDAL_ROKEN_OBJ_FILES:.o=.ho) $(HEIMDAL_ROKEN_OBJ_FILES:.o=.hd):: $(heimdalsrcdir)/lib/roken/roken.h
+
+[SUBSYSTEM::HEIMDAL_ROKEN_H]
+CFLAGS =  -I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/roken -DSOCKET_WRAPPER_DISABLE=1
+PRIVATE_DEPENDENCIES = \
+                       HEIMDAL_ROKEN_PROGNAME_H \
+                       HEIMDAL_ROKEN_CLOSEFROM_H \
+                       RESOLV \
+                       LIBREPLACE_NETWORK
+
+HEIMDAL_ROKEN_H_OBJ_FILES = $(HEIMDAL_ROKEN_OBJ_FILES:.o=.ho)
+$(HEIMDAL_ROKEN_H_OBJ_FILES:.ho=.hd):: $(heimdalsrcdir)/lib/roken/roken.h
 
 $(heimdalsrcdir)/lib/roken/roken.h:
        @echo 'Creating $(heimdalsrcdir)/lib/roken/roken.h'
@@ -656,7 +674,7 @@ HEIMDAL_COM_ERR_OBJ_FILES = \
 # Start BINARY asn1_compile
 [BINARY::asn1_compile]
 USE_HOSTCC = YES
-PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN
+PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN_H
 
 ASN1C = $(builddir)/bin/asn1_compile
 
@@ -680,10 +698,9 @@ dist:: $(heimdalsrcdir)/lib/asn1/lex.c
 
 asn1_compile_OBJ_FILES = \
        $(asn1_compile_ASN1_OBJ_FILES) \
-       $(heimdalsrcdir)/lib/vers/print_version.ho \
-       $(socketwrappersrcdir)/socket_wrapper.ho \
+       $(heimdalsrcdir)/lib/vers/print_version.ho
 
-$(asn1_compile_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/asn1 -I$(heimdalsrcdir)/lib/roken -I$(socketwrappersrcdir)
+$(asn1_compile_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/asn1 -I$(heimdalsrcdir)/lib/roken -DSOCKET_WRAPPER_DISABLE=1
 
 $(eval $(call heimdal_proto_header_template, \
   $(heimdalsrcdir)/lib/asn1/der-protos.h, \
@@ -699,7 +716,7 @@ $(eval $(call heimdal_proto_header_template, \
 # Start BINARY compile_et
 [BINARY::compile_et]
 USE_HOSTCC = YES
-PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN
+PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN_H
 # End BINARY compile_et
 #######################
 
@@ -708,10 +725,9 @@ ET_COMPILER = $(builddir)/bin/compile_et
 compile_et_OBJ_FILES = $(heimdalsrcdir)/lib/vers/print_version.ho \
        $(heimdalsrcdir)/lib/com_err/parse.ho \
        $(heimdalsrcdir)/lib/com_err/lex.ho \
-       $(heimdalsrcdir)/lib/com_err/compile_et.ho \
-       $(socketwrappersrcdir)/socket_wrapper.ho \
+       $(heimdalsrcdir)/lib/com_err/compile_et.ho
 
-$(compile_et_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/com_err -I$(heimdalsrcdir)/lib/roken  -I$(socketwrappersrcdir)
+$(compile_et_OBJ_FILES): CFLAGS+=-I$(heimdalbuildsrcdir) -I$(heimdalsrcdir)/lib/com_err -I$(heimdalsrcdir)/lib/roken -DSOCKET_WRAPPER_DISABLE=1
 
 $(heimdalsrcdir)/lib/com_err/lex.c:: $(heimdalsrcdir)/lib/com_err/parse.c
 dist:: $(heimdalsrcdir)/lib/com_err/lex.c
index da44c02aa85075d5c3eb88ae85d91ab269ce7520..a924024160326914492db016087603fc5abed5a5 100644 (file)
@@ -104,7 +104,7 @@ static void ldapsrv_process_message(struct ldapsrv_connection *conn,
                bool ret;
 
                msg = call->replies->msg;
-               if (!ldap_encode(msg, &b, call)) {
+               if (!ldap_encode(msg, samba_ldap_control_handlers(), &b, call)) {
                        DEBUG(0,("Failed to encode ldap reply of type %d\n", msg->type));
                        talloc_free(call);
                        return;
@@ -150,7 +150,7 @@ static NTSTATUS ldapsrv_decode(void *private_data, DATA_BLOB blob)
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = ldap_decode(asn1, msg);
+       status = ldap_decode(asn1, samba_ldap_control_handlers(), msg);
        if (!NT_STATUS_IS_OK(status)) {
                asn1_free(asn1);
                return status;
index a05ac0796fc8311e022a035e9290a7b983ab7a5b..89ca7bbe5ca6833c7c05c52f3adc27958485094e 100644 (file)
@@ -41,7 +41,7 @@ static void ev_wrap_debug(void *context, enum tevent_debug_level level,
                samba_level = 2;
                break;
        case TEVENT_DEBUG_TRACE:
-               samba_level = 5;
+               samba_level = 10;
                break;
 
        };
index 7f00e8ebee4f8f3aa3d5b8eca840249e3ba08753..663dea9f807d5481692d229c0b15628fa180619c 100644 (file)
@@ -67,7 +67,7 @@ MDLD_FLAGS = @MDLD_FLAGS@
 
 OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) $(TDB_OBJ) $(TEVENT_OBJ) $(TALLOC_OBJ) $(POPT_OBJ) $(LDB_MAP_OBJ) @LIBREPLACEOBJ@ $(EXTRA_OBJ) 
 
-headers = $(srcdir)/include/ldb.h $(srcdir)/include/ldb_errors.h $(srcdir)/include/ldb_handlers.h $(srcdir)/include/ldb_includes.h $(srcdir)/include/ldb_module.h
+headers = $(srcdir)/include/ldb.h $(srcdir)/include/ldb_errors.h $(srcdir)/include/ldb_handlers.h $(srcdir)/include/ldb_module.h
 
 BINS = bin/ldbadd bin/ldbsearch bin/ldbdel bin/ldbmodify bin/ldbedit bin/ldbrename bin/ldbtest
 
index 2fb5a8f9be6868b359398592760c5964668a91ba..f1b28b6819b7cb20152d44a232b5d4c3d2d1ea79 100644 (file)
 
 #include "ldb_private.h"
 
+static int ldb_context_destructor(void *ptr)
+{
+       struct ldb_context *ldb = talloc_get_type(ptr, struct ldb_context);
+
+       if (ldb->transaction_active) {
+               ldb_debug(ldb, LDB_DEBUG_FATAL,
+                         "A transaction is still active in ldb context [%p]",
+                         ldb);
+       }
+
+       return 0;
+}
+
 /*
    initialise a ldb context
    The mem_ctx is required
@@ -65,6 +78,8 @@ struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx)
        /* TODO: get timeout from options if available there */
        ldb->default_timeout = 300; /* set default to 5 minutes */
 
+       talloc_set_destructor((TALLOC_CTX *)ldb, ldb_context_destructor);
+
        return ldb;
 }
 
@@ -242,10 +257,24 @@ void ldb_reset_err_string(struct ldb_context *ldb)
 /*
   start a transaction
 */
-static int ldb_transaction_start_internal(struct ldb_context *ldb)
+int ldb_transaction_start(struct ldb_context *ldb)
 {
        struct ldb_module *module;
        int status;
+
+       ldb_debug(ldb, LDB_DEBUG_TRACE,
+                 "start ldb transaction (nesting: %d)",
+                 ldb->transaction_active);
+
+       /* explicit transaction active, count nested requests */
+       if (ldb->transaction_active) {
+               ldb->transaction_active++;
+               return LDB_SUCCESS;
+       }
+
+       /* start a new transaction */
+       ldb->transaction_active++;
+
        FIRST_OP(ldb, start_transaction);
 
        ldb_reset_err_string(ldb);
@@ -266,10 +295,29 @@ static int ldb_transaction_start_internal(struct ldb_context *ldb)
 /*
   commit a transaction
 */
-static int ldb_transaction_commit_internal(struct ldb_context *ldb)
+int ldb_transaction_commit(struct ldb_context *ldb)
 {
        struct ldb_module *module;
        int status;
+
+       ldb->transaction_active--;
+
+       ldb_debug(ldb, LDB_DEBUG_TRACE,
+                 "commit ldb transaction (nesting: %d)",
+                 ldb->transaction_active);
+
+       /* commit only when all nested transactions are complete */
+       if (ldb->transaction_active > 0) {
+               return LDB_SUCCESS;
+       }
+
+       if (ldb->transaction_active < 0) {
+               ldb_debug(ldb, LDB_DEBUG_FATAL,
+                         "commit called but no ldb transactions are active!");
+               ldb->transaction_active = 0;
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
        FIRST_OP(ldb, end_transaction);
 
        ldb_reset_err_string(ldb);
@@ -290,10 +338,29 @@ static int ldb_transaction_commit_internal(struct ldb_context *ldb)
 /*
   cancel a transaction
 */
-static int ldb_transaction_cancel_internal(struct ldb_context *ldb)
+int ldb_transaction_cancel(struct ldb_context *ldb)
 {
        struct ldb_module *module;
        int status;
+
+       ldb->transaction_active--;
+
+       ldb_debug(ldb, LDB_DEBUG_TRACE,
+                 "cancel ldb transaction (nesting: %d)",
+                 ldb->transaction_active);
+
+       /* really cancel only if all nested transactions are complete */
+       if (ldb->transaction_active > 0) {
+               return LDB_SUCCESS;
+       }
+
+       if (ldb->transaction_active < 0) {
+               ldb_debug(ldb, LDB_DEBUG_FATAL,
+                         "commit called but no ldb transactions are active!");
+               ldb->transaction_active = 0;
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
        FIRST_OP(ldb, del_transaction);
 
        status = module->ops->del_transaction(module);
@@ -309,66 +376,13 @@ static int ldb_transaction_cancel_internal(struct ldb_context *ldb)
        return status;
 }
 
-int ldb_transaction_start(struct ldb_context *ldb)
-{
-       /* disable autotransactions */
-       ldb->transaction_active++;
-
-       return ldb_transaction_start_internal(ldb);
-}
-
-int ldb_transaction_commit(struct ldb_context *ldb)
-{
-       /* renable autotransactions (when we reach 0) */
-       if (ldb->transaction_active > 0)
-               ldb->transaction_active--;
-
-       return ldb_transaction_commit_internal(ldb);
-}
-
-int ldb_transaction_cancel(struct ldb_context *ldb)
-{
-       /* renable autotransactions (when we reach 0) */
-       if (ldb->transaction_active > 0)
-               ldb->transaction_active--;
-
-       return ldb_transaction_cancel_internal(ldb);
-}
-
-static int ldb_autotransaction_start(struct ldb_context *ldb)
-{
-       /* explicit transaction active, ignore autotransaction request */
-       if (ldb->transaction_active)
-               return LDB_SUCCESS;
-
-       return ldb_transaction_start_internal(ldb);
-}
-
-static int ldb_autotransaction_commit(struct ldb_context *ldb)
-{
-       /* explicit transaction active, ignore autotransaction request */
-       if (ldb->transaction_active)
-               return LDB_SUCCESS;
-
-       return ldb_transaction_commit_internal(ldb);
-}
-
-static int ldb_autotransaction_cancel(struct ldb_context *ldb)
-{
-       /* explicit transaction active, ignore autotransaction request */
-       if (ldb->transaction_active)
-               return LDB_SUCCESS;
-
-       return ldb_transaction_cancel_internal(ldb);
-}
-
 /* autostarts a transacion if none active */
 static int ldb_autotransaction_request(struct ldb_context *ldb,
                                       struct ldb_request *req)
 {
        int ret;
 
-       ret = ldb_autotransaction_start(ldb);
+       ret = ldb_transaction_start(ldb);
        if (ret != LDB_SUCCESS) {
                return ret;
        }
@@ -379,9 +393,9 @@ static int ldb_autotransaction_request(struct ldb_context *ldb,
        }
 
        if (ret == LDB_SUCCESS) {
-               return ldb_autotransaction_commit(ldb);
+               return ldb_transaction_commit(ldb);
        }
-       ldb_autotransaction_cancel(ldb);
+       ldb_transaction_cancel(ldb);
 
        if (ldb->err_string == NULL) {
                /* no error string was setup by the backend */
index 99a47767e12a7f65a14b62c3330c36573b43c4cd..ae97ef4cced4db84ed7490aee01167165f32abb4 100644 (file)
  */
 
 #include "ldb_private.h"
-
-#if (_SAMBA_BUILD_ >= 4)
-#include "includes.h"
-#endif
+#include "dlinklist.h"
 
 #define LDB_MODULE_PREFIX      "modules:"
 #define LDB_MODULE_PREFIX_LEN  8
index 6990397a741caa5ad58bd97deb95e40cef582b49..be41151409a73813e3635f186c9bb6cdfc1d0eb2 100644 (file)
 #define _LDB_H_ 1
 /*! \endcond */
 
-#include "ldb_includes.h"
+#include <stdbool.h>
+#include "talloc.h"
+#include "tevent.h"
+#include "ldb_errors.h"
 
 /*
   major restrictions as compared to normal LDAP:
index a2927139c877855ef496e5254b814fc02f07f238..602bbec32cc25b0ace09cde7dc533370940f3f02 100644 (file)
@@ -4,11 +4,6 @@
   a temporary includes file until I work on the ldb build system
 */
 
-#if (_SAMBA_BUILD_ >= 4)
-/* tell ldb we have the internal ldap code */
-#define HAVE_ILDAP 1
-#endif
-
 #if (_SAMBA_BUILD_ <= 3)
 /* allow forbidden string functions - should be replaced with _m functions */
 #undef strcasecmp
@@ -19,9 +14,5 @@
 #include "replace.h"
 #include "system/filesys.h"
 #include "system/time.h"
-#include <talloc.h>
-#include <tevent.h>
-#include "ldb_errors.h"
-#include "dlinklist.h"
 
 #endif /*_LDB_PRIVATE_INCLUDES_H_*/
index 1ce9e9ecfd51dbb039f061216611e16bbc0ccf26..2e8da9941ca8e38a713969216f9b81bc5d51f6c9 100644 (file)
@@ -37,6 +37,7 @@
 #ifndef _LDB_PRIVATE_H_
 #define _LDB_PRIVATE_H_ 1
 
+#include "ldb_includes.h"
 #include "ldb.h"
 #include "ldb_module.h"
 
@@ -109,10 +110,6 @@ struct ldb_context {
        struct tevent_context *ev_ctx;
 };
 
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
-#endif
-
 /* The following definitions come from lib/ldb/common/ldb.c  */
 
 int ldb_connect_backend(struct ldb_context *ldb, const char *url, const char *options[],
index b13440504893946ebbc79663006ae3fb6f4f2d69..4447d0e09a473b8af1ca6983d73ff8d5f3394f0a 100644 (file)
  *    author: Simo Sorce
  */
 
-
 #include "includes.h"
 #include "ldb_module.h"
+#include "dlinklist.h"
 
-#include "tevent.h"
 #include "libcli/ldap/ldap.h"
 #include "libcli/ldap/ldap_client.h"
 #include "auth/auth.h"
index e1fcdb13531ec13d481f4da5f09faa930d992af6..43a01f75a73baa5f7c3805c745bd6c0ddac07bdb 100644 (file)
@@ -38,6 +38,7 @@
  *    author: Simo Sorce
  */
 
+#include "ldb_includes.h"
 #include "ldb_module.h"
 
 #define LDAP_DEPRECATED 1
index ea2bfd1dc14c3bbaeb1fa03c83c91aacc5435633..5b4ea7910a75137c8ddea361620d64491e71162d 100644 (file)
@@ -35,8 +35,7 @@
  *  Author: Jelmer Vernooij, Martin Kuehl
  */
 
-#include "ldb_module.h"
-
+#include "ldb_includes.h"
 #include "ldb_map.h"
 #include "ldb_map_private.h"
 
index 872208174ea9c13eb614727e351f82b6e32efb53..3c1fe808957d435f87333e3944fe4616ac4a978b 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef __LDB_MAP_H__
 #define __LDB_MAP_H__
 
+#include "ldb_module.h"
+
 /* ldb_map is a skeleton LDB module that can be used for any other modules
  * that need to map attributes.
  *
index e915a5f46a38fe073c51f37010ca8dddd896917b..455740ce590ee27dc0f54a8af5a0072c5da77daa 100644 (file)
@@ -24,8 +24,7 @@
 
 */
 
-#include "ldb_module.h"
-
+#include "ldb_includes.h"
 #include "ldb_map.h"
 #include "ldb_map_private.h"
 
index 327fa92f8d206e868a9d47d194bec2ec1eb420e1..ffcefad6be6fdf066cb4b3552f11d5d4e75d6ff5 100644 (file)
@@ -25,8 +25,7 @@
 
 */
 
-#include "ldb_module.h"
-
+#include "ldb_includes.h"
 #include "ldb_map.h"
 #include "ldb_map_private.h"
 
index 0c46443253738870a605d2309e84259e45050010..612d215ae95b6965a09844b70155f34e8930f25c 100644 (file)
@@ -1,3 +1,4 @@
+#include "ldb_includes.h"
 
 /* A handy macro to report Out of Memory conditions */
 #define map_oom(module) ldb_set_errstring(ldb_module_get_ctx(module), talloc_asprintf(module, "Out of Memory"));
index cdbef3944b531fa70922d43e5cc9970d69f4e93d..ad27c9a9a9a9d77f7b8a9b397f30451731852ca5 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include "ldb_tdb.h"
+#include "dlinklist.h"
 
 /*
   the idxptr code is a bit unusual. The way it works is to replace
index d6276c4b8600c5c75cd546aed949096b933b08df..24ec06ea32056cfe1d9ef2a9b5cbc34097bff326 100644 (file)
@@ -865,6 +865,7 @@ static int ltdb_end_trans(struct ldb_module *module)
        ltdb->in_transaction--;
 
        if (ltdb_index_transaction_commit(module) != 0) {
+               tdb_transaction_cancel(ltdb->tdb);
                return ltdb_err_map(tdb_error(ltdb->tdb));
        }
 
@@ -883,6 +884,7 @@ static int ltdb_del_trans(struct ldb_module *module)
        ltdb->in_transaction--;
 
        if (ltdb_index_transaction_cancel(module) != 0) {
+               tdb_transaction_cancel(ltdb->tdb);
                return ltdb_err_map(tdb_error(ltdb->tdb));
        }
 
index 7ebf199f6f5c3a64a418ef81229d50cc809f272d..0a06cdb1b0816583b5bf74f3266227948bdc7146 100644 (file)
@@ -1,11 +1,5 @@
-#if (_SAMBA_BUILD_ == 3)
-#include "tdb/include/tdb.h"
-#else
-#include "replace.h"
-#include "system/wait.h"
+#include "ldb_includes.h"
 #include "tdb.h"
-#endif
-
 #include "ldb_module.h"
 
 /* this private structure is used by the ltdb backend in the
index d862638389ca6302f8c7d4fd4afda52976a336cc..43b223b52e19f078a5adaf483a5123d8352a3e32 100644 (file)
   modifiersName: not supported by w2k3?
 */
 
+#include "ldb_includes.h"
 #include "ldb_module.h"
 
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+#endif
+
 /*
   construct a canonical name from a message
 */
index 7d7cdf66a059e7f439f2d1c5febf443765f5245f..2a06c5e6c5d62a89124bfb3f755a7da073843255 100644 (file)
@@ -32,6 +32,7 @@
  *  Author: Simo Sorce
  */
 
+#include "ldb_includes.h"
 #include "ldb_module.h"
 
 struct message_store {
index a5ffcc034a092a2e807a44c755ab9e893b7249ef..880678d89de4f576dd808573babdffca2e456724 100644 (file)
@@ -36,6 +36,7 @@
  *      Simo Sorce Mar 2006
  */
 
+#include "ldb_includes.h"
 #include "ldb_module.h"
 
 struct rename_context {
index 3dce9b187bab72471aeb82651c1bf1eaed3ba692..2701de5a481dcf7cca4dc757053c2dc0e3b059b4 100644 (file)
@@ -21,6 +21,7 @@
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 
+#include "ldb_includes.h"
 #include "ldb.h"
 #include "tools/cmdline.h"
 
index 3a915f8bea9ecca9af8d7427138bc4471322d979..9d3bd27983a11af5a449195bcb0d2a0a68a4384c 100644 (file)
@@ -30,7 +30,7 @@
  *
  *  Author: Andrew Tridgell
  */
-
+#include "ldb_includes.h"
 #include "ldb.h"
 #include "tools/cmdline.h"
 
index 35d4ac70021bea0aea60dbfd05a869ba04b0f41e..ba0a2a892711dd3ee7889c28237c77dcbc4e2304 100644 (file)
@@ -31,6 +31,7 @@
  *  Author: Andrew Tridgell
  */
 
+#include "ldb_includes.h"
 #include "ldb.h"
 #include "tools/cmdline.h"
 
index edaa9fb85c0cbff2dd0fcdcafffab8acdd5e4f98..6af0ee933633c9283d4c61a18a532bdc985f12b0 100644 (file)
@@ -31,6 +31,7 @@
  *  Author: Andrew Tridgell
  */
 
+#include "ldb_includes.h"
 #include "ldb.h"
 #include "tools/cmdline.h"
 
index 0bafc5ddf14d035fd558c64547403720526ec7e1..c46a009e3df5b7104be8c56a75927f708dc8911a 100644 (file)
@@ -40,4 +40,6 @@ if test x$use_gnutls = xyes; then
        AC_CHECK_TYPES([gnutls_datum_t],,,[#include "gnutls/gnutls.h"])
        AC_DEFINE(ENABLE_GNUTLS,1,[Whether we have gnutls support (SSL)])
        AC_CHECK_HEADERS(gcrypt.h)
+       AC_CHECK_LIB_EXT(gcrypt, GCRYPT_LIBS, gcry_control)
+       SMB_EXT_LIB(GCRYPT, $GCRYPT_LIBS)
 fi
index ff1eedfd5dac8cf200a8884254338269e9ac2b46..0e1978cc1b0aafd3a1936e34576a2cf69c46c87f 100644 (file)
@@ -1,5 +1,5 @@
 [SUBSYSTEM::LIBTLS]
 PUBLIC_DEPENDENCIES = \
-               LIBTALLOC GNUTLS LIBSAMBA-HOSTCONFIG samba_socket
+               LIBTALLOC GNUTLS GCRYPT LIBSAMBA-HOSTCONFIG samba_socket
 
 LIBTLS_OBJ_FILES = $(addprefix $(libtlssrcdir)/, tls.o tlscert.o)
index 8d2e2e374c886e72b5b3aa1092cc4c52290bb94c..b18ba12b1fc2ac8a77681bed834c6a1154fa2fcc 100644 (file)
@@ -108,7 +108,7 @@ static void cldap_socket_recv(struct cldap_socket *cldap)
        }
 
        /* this initial decode is used to find the message id */
-       status = ldap_decode(asn1, ldap_msg);
+       status = ldap_decode(asn1, NULL, ldap_msg);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(2,("Failed to decode ldap message: %s\n", nt_errstr(status)));
                talloc_free(tmp_ctx);
@@ -343,7 +343,7 @@ struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
                goto failed;
        }
 
-       if (!ldap_encode(msg, &req->encoded, req)) {
+       if (!ldap_encode(msg, NULL, &req->encoded, req)) {
                DEBUG(0,("Failed to encode cldap message to %s:%d\n",
                         req->dest->addr, req->dest->port));
                goto failed;
@@ -396,7 +396,7 @@ NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
                msg->type = LDAP_TAG_SearchResultEntry;
                msg->r.SearchResultEntry = *io->response;
 
-               if (!ldap_encode(msg, &blob1, req)) {
+               if (!ldap_encode(msg, NULL, &blob1, req)) {
                        DEBUG(0,("Failed to encode cldap message to %s:%d\n",
                                 req->dest->addr, req->dest->port));
                        status = NT_STATUS_INVALID_PARAMETER;
@@ -409,7 +409,7 @@ NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
        msg->type = LDAP_TAG_SearchResultDone;
        msg->r.SearchResultDone = *io->result;
 
-       if (!ldap_encode(msg, &blob2, req)) {
+       if (!ldap_encode(msg, NULL, &blob2, req)) {
                DEBUG(0,("Failed to encode cldap message to %s:%d\n",
                         req->dest->addr, req->dest->port));
                status = NT_STATUS_INVALID_PARAMETER;
@@ -463,7 +463,7 @@ NTSTATUS cldap_search_recv(struct cldap_request *req,
        ldap_msg = talloc(mem_ctx, struct ldap_message);
        NT_STATUS_HAVE_NO_MEMORY(ldap_msg);
 
-       status = ldap_decode(req->asn1, ldap_msg);
+       status = ldap_decode(req->asn1, NULL, ldap_msg);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(2,("Failed to decode cldap search reply: %s\n", nt_errstr(status)));
                talloc_free(req);
@@ -479,7 +479,7 @@ NTSTATUS cldap_search_recv(struct cldap_request *req,
                *io->out.response = ldap_msg->r.SearchResultEntry;
 
                /* decode the 2nd part */
-               status = ldap_decode(req->asn1, ldap_msg);
+               status = ldap_decode(req->asn1, NULL, ldap_msg);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(2,("Failed to decode cldap search result entry: %s\n", nt_errstr(status)));
                        talloc_free(req);
index 2708c66b68dc84984a66672141561037748d4950..f0c0f5295d1c133d238be5cb02fa3951a89449e2 100644 (file)
@@ -1,18 +1,12 @@
 [SUBSYSTEM::LIBCLI_LDAP]
 PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBTEVENT LIBPACKET
-PRIVATE_DEPENDENCIES = LIBCLI_COMPOSITE samba_socket NDR_SAMR LIBTLS ASN1_UTIL \
-                                          LDAP_ENCODE LIBNDR LP_RESOLVE gensec
+PRIVATE_DEPENDENCIES = LIBCLI_COMPOSITE samba_socket NDR_SAMR LIBTLS \
+                      LIBCLI_LDAP_NDR LIBNDR LP_RESOLVE gensec LIBCLI_LDAP_MESSAGE
 
 LIBCLI_LDAP_OBJ_FILES = $(addprefix $(libclisrcdir)/ldap/, \
-                                          ldap.o ldap_client.o ldap_bind.o \
-                                          ldap_msg.o ldap_ildap.o ldap_controls.o)
-
-
-PUBLIC_HEADERS += $(libclisrcdir)/ldap/ldap.h $(libclisrcdir)/ldap/ldap_ndr.h
+                                          ldap_client.o ldap_bind.o \
+                                          ldap_ildap.o ldap_controls.o)
+PUBLIC_HEADERS += $(libclisrcdir)/ldap/ldap.h
 
 $(eval $(call proto_header_template,$(libclisrcdir)/ldap/ldap_proto.h,$(LIBCLI_LDAP_OBJ_FILES:.o=.c)))
 
-[SUBSYSTEM::LDAP_ENCODE]
-PRIVATE_DEPENDENCIES = LIBLDB
-
-LDAP_ENCODE_OBJ_FILES = $(libclisrcdir)/ldap/ldap_ndr.o
index 3d99d6f47d1d88556626e81d4a71786b01b0d327..79cfef2128ee402c7c9cfac40871bede87612252 100644 (file)
 #ifndef _SMB_LDAP_H_
 #define _SMB_LDAP_H_
 
-#include "libcli/ldap/ldap_errors.h"
-#include "lib/ldb/include/ldb.h"
+#include "../libcli/ldap/ldap_message.h"
 #include "librpc/gen_ndr/misc.h"
 
-enum ldap_request_tag {
-       LDAP_TAG_BindRequest = 0,
-       LDAP_TAG_BindResponse = 1,
-       LDAP_TAG_UnbindRequest = 2,
-       LDAP_TAG_SearchRequest = 3,
-       LDAP_TAG_SearchResultEntry = 4,
-       LDAP_TAG_SearchResultDone = 5,
-       LDAP_TAG_ModifyRequest = 6,
-       LDAP_TAG_ModifyResponse = 7,
-       LDAP_TAG_AddRequest = 8,
-       LDAP_TAG_AddResponse = 9,
-       LDAP_TAG_DelRequest = 10,
-       LDAP_TAG_DelResponse = 11,
-       LDAP_TAG_ModifyDNRequest = 12,
-       LDAP_TAG_ModifyDNResponse = 13,
-       LDAP_TAG_CompareRequest = 14,
-       LDAP_TAG_CompareResponse = 15,
-       LDAP_TAG_AbandonRequest = 16,
-       LDAP_TAG_SearchResultReference = 19,
-       LDAP_TAG_ExtendedRequest = 23,
-       LDAP_TAG_ExtendedResponse = 24
-};
-
-enum ldap_auth_mechanism {
-       LDAP_AUTH_MECH_SIMPLE = 0,
-       LDAP_AUTH_MECH_SASL = 3
-};
-
-struct ldap_Result {
-       int resultcode;
-       const char *dn;
-       const char *errormessage;
-       const char *referral;
-};
-
-struct ldap_BindRequest {
-       int version;
-       const char *dn;
-       enum ldap_auth_mechanism mechanism;
-       union {
-               const char *password;
-               struct {
-                       const char *mechanism;
-                       DATA_BLOB *secblob;/* optional */
-               } SASL;
-       } creds;
-};
-
-struct ldap_BindResponse {
-       struct ldap_Result response;
-       union {
-               DATA_BLOB *secblob;/* optional */
-       } SASL;
-};
-
-struct ldap_UnbindRequest {
-       uint8_t __dummy;
-};
-
-enum ldap_scope {
-       LDAP_SEARCH_SCOPE_BASE = 0,
-       LDAP_SEARCH_SCOPE_SINGLE = 1,
-       LDAP_SEARCH_SCOPE_SUB = 2
-};
-
-enum ldap_deref {
-       LDAP_DEREFERENCE_NEVER = 0,
-       LDAP_DEREFERENCE_IN_SEARCHING = 1,
-       LDAP_DEREFERENCE_FINDING_BASE = 2,
-       LDAP_DEREFERENCE_ALWAYS
-};
-
-struct ldap_SearchRequest {
-       const char *basedn;
-       enum ldap_scope scope;
-       enum ldap_deref deref;
-       uint32_t timelimit;
-       uint32_t sizelimit;
-       bool attributesonly;
-       struct ldb_parse_tree *tree;
-       int num_attributes;
-       const char * const *attributes;
-};
-
-struct ldap_SearchResEntry {
-       const char *dn;
-       int num_attributes;
-       struct ldb_message_element *attributes;
-};
-
-struct ldap_SearchResRef {
-       const char *referral;
-};
-
-enum ldap_modify_type {
-       LDAP_MODIFY_NONE = -1,
-       LDAP_MODIFY_ADD = 0,
-       LDAP_MODIFY_DELETE = 1,
-       LDAP_MODIFY_REPLACE = 2
-};
-
-struct ldap_mod {
-       enum ldap_modify_type type;
-       struct ldb_message_element attrib;
-};
-
-struct ldap_ModifyRequest {
-       const char *dn;
-       int num_mods;
-       struct ldap_mod *mods;
-};
-
-struct ldap_AddRequest {
-       const char *dn;
-       int num_attributes;
-       struct ldb_message_element *attributes;
-};
-
-struct ldap_DelRequest {
-       const char *dn;
-};
-
-struct ldap_ModifyDNRequest {
-       const char *dn;
-       const char *newrdn;
-       bool deleteolddn;
-       const char *newsuperior;/* optional */
-};
-
-struct ldap_CompareRequest {
-       const char *dn;
-       const char *attribute;
-       DATA_BLOB value;
-};
-
-struct ldap_AbandonRequest {
-       uint32_t messageid;
-};
-
-struct ldap_ExtendedRequest {
-       const char *oid;
-       DATA_BLOB *value;/* optional */
-};
-
-struct ldap_ExtendedResponse {
-       struct ldap_Result response;
-       const char *oid;/* optional */
-       DATA_BLOB *value;/* optional */
-};
-
-union ldap_Request {
-       struct ldap_Result              GeneralResult;
-       struct ldap_BindRequest         BindRequest;
-       struct ldap_BindResponse        BindResponse;
-       struct ldap_UnbindRequest       UnbindRequest;
-       struct ldap_SearchRequest       SearchRequest;
-       struct ldap_SearchResEntry      SearchResultEntry;
-       struct ldap_Result              SearchResultDone;
-       struct ldap_SearchResRef        SearchResultReference;
-       struct ldap_ModifyRequest       ModifyRequest;
-       struct ldap_Result              ModifyResponse;
-       struct ldap_AddRequest          AddRequest;
-       struct ldap_Result              AddResponse;
-       struct ldap_DelRequest          DelRequest;
-       struct ldap_Result              DelResponse;
-       struct ldap_ModifyDNRequest     ModifyDNRequest;
-       struct ldap_Result              ModifyDNResponse;
-       struct ldap_CompareRequest      CompareRequest;
-       struct ldap_Result              CompareResponse;
-       struct ldap_AbandonRequest      AbandonRequest;
-       struct ldap_ExtendedRequest     ExtendedRequest;
-       struct ldap_ExtendedResponse    ExtendedResponse;
-};
-
-
-struct ldap_message {
-       int                     messageid;
-       enum ldap_request_tag   type;
-       union ldap_Request      r;
-       struct ldb_control    **controls;
-       bool                   *controls_decoded;
-};
-
 struct tevent_context;
 struct cli_credentials;
 struct dom_sid;
-struct asn1_data;
-
-struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx);
-NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg);
-bool ldap_encode(struct ldap_message *msg, DATA_BLOB *result, TALLOC_CTX *mem_ctx);
 
 #endif 
index 3e54d7fff0212d727459187d75e499d8e6b90cbd..304a2e1253d30f66945d5e3f6dec407e845122fa 100644 (file)
@@ -200,7 +200,7 @@ static NTSTATUS ldap_recv_handler(void *private_data, DATA_BLOB blob)
                return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
        }
        
-       status = ldap_decode(asn1, msg);
+       status = ldap_decode(asn1, samba_ldap_control_handlers(), msg);
        if (!NT_STATUS_IS_OK(status)) {
                asn1_free(asn1);
                return status;
@@ -608,7 +608,7 @@ _PUBLIC_ struct ldap_request *ldap_request_send(struct ldap_connection *conn,
 
        msg->messageid = req->messageid;
 
-       if (!ldap_encode(msg, &req->data, req)) {
+       if (!ldap_encode(msg, samba_ldap_control_handlers(), &req->data, req)) {
                status = NT_STATUS_INTERNAL_ERROR;
                goto failed;            
        }
index 109837c2bf2f155e675fc6dbca9739cdd3bf401a..7949758a80c48200246c70d108cca0616b10eb3e 100644 (file)
 #include "libcli/ldap/ldap_proto.h"
 #include "dsdb/samdb/samdb.h"
 
-struct control_handler {
-       const char *oid;
-       bool (*decode)(void *mem_ctx, DATA_BLOB in, void **out);
-       bool (*encode)(void *mem_ctx, void *in, DATA_BLOB *out);
-};
-
-static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        DATA_BLOB attr;
        struct asn1_data *data = asn1_init(mem_ctx);
        struct ldb_sort_resp_control *lsrc;
@@ -77,8 +72,9 @@ static bool decode_server_sort_response(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        DATA_BLOB attr;
        DATA_BLOB rule;
        struct asn1_data *data = asn1_init(mem_ctx);
@@ -156,8 +152,9 @@ static bool decode_server_sort_request(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        struct asn1_data *data;
        struct ldb_extended_dn_control *ledc;
 
@@ -196,8 +193,9 @@ static bool decode_extended_dn_request(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        struct asn1_data *data = asn1_init(mem_ctx);
        struct ldb_sd_flags_control *lsdfc;
 
@@ -229,8 +227,9 @@ static bool decode_sd_flags_request(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        struct asn1_data *data = asn1_init(mem_ctx);
        struct ldb_search_options_control *lsoc;
 
@@ -262,8 +261,9 @@ static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void **ou
        return true;
 }
 
-static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        DATA_BLOB cookie;
        struct asn1_data *data = asn1_init(mem_ctx);
        struct ldb_paged_control *lprc;
@@ -310,8 +310,9 @@ static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void **out
        return true;
 }
 
-static bool decode_dirsync_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_dirsync_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        DATA_BLOB cookie;
        struct asn1_data *data = asn1_init(mem_ctx);
        struct ldb_dirsync_control *ldc;
@@ -365,8 +366,9 @@ static bool decode_dirsync_request(void *mem_ctx, DATA_BLOB in, void **out)
 /* seem that this controls has 2 forms one in case it is used with
  * a Search Request and another when used ina Search Response
  */
-static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        DATA_BLOB source_attribute;
        struct asn1_data *data = asn1_init(mem_ctx);
        struct ldb_asq_control *lac;
@@ -425,7 +427,7 @@ static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-static bool decode_domain_scope_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_domain_scope_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
        if (in.length != 0) {
                return false;
@@ -434,7 +436,7 @@ static bool decode_domain_scope_request(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-static bool decode_notification_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_notification_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
        if (in.length != 0) {
                return false;
@@ -443,7 +445,7 @@ static bool decode_notification_request(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-static bool decode_show_deleted_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_show_deleted_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
        if (in.length != 0) {
                return false;
@@ -452,7 +454,7 @@ static bool decode_show_deleted_request(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-static bool decode_permissive_modify_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_permissive_modify_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
        if (in.length != 0) {
                return false;
@@ -461,7 +463,7 @@ static bool decode_permissive_modify_request(void *mem_ctx, DATA_BLOB in, void *
        return true;
 }
 
-static bool decode_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
        if (in.length != 0) {
                return false;
@@ -470,8 +472,9 @@ static bool decode_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        DATA_BLOB assertion_value, context_id;
        struct asn1_data *data = asn1_init(mem_ctx);
        struct ldb_vlv_req_control *lvrc;
@@ -582,8 +585,9 @@ static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_vlv_response(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        DATA_BLOB context_id;
        struct asn1_data *data = asn1_init(mem_ctx);
        struct ldb_vlv_resp_control *lvrc;
@@ -1132,8 +1136,9 @@ static bool encode_openldap_dereference(void *mem_ctx, void *in, DATA_BLOB *out)
        return true;
 }
 
-static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void **out)
+static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void *_out)
 {
+       void **out = (void **)_out;
        struct asn1_data *data = asn1_init(mem_ctx);
        struct dsdb_openldap_dereference_result_control *control;
        struct dsdb_openldap_dereference_result **r = NULL;
@@ -1201,7 +1206,7 @@ static bool decode_openldap_dereference(void *mem_ctx, DATA_BLOB in, void **out)
        return true;
 }
 
-struct control_handler ldap_known_controls[] = {
+static const struct ldap_control_handler ldap_known_controls[] = {
        { "1.2.840.113556.1.4.319", decode_paged_results_request, encode_paged_results_request },
        { "1.2.840.113556.1.4.529", decode_extended_dn_request, encode_extended_dn_request },
        { "1.2.840.113556.1.4.473", decode_server_sort_request, encode_server_sort_request },
@@ -1225,121 +1230,8 @@ struct control_handler ldap_known_controls[] = {
        { NULL, NULL, NULL }
 };
 
-bool ldap_decode_control_value(void *mem_ctx, DATA_BLOB value, struct ldb_control *ctrl)
+const struct ldap_control_handler *samba_ldap_control_handlers(void)
 {
-       int i;
-
-       for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
-               if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
-                       if (!ldap_known_controls[i].decode || !ldap_known_controls[i].decode(mem_ctx, value, &ctrl->data)) {
-                               return false;
-                       }
-                       break;
-               }
-       }
-       if (ldap_known_controls[i].oid == NULL) {
-               return false;
-       }
-
-       return true;
+       return ldap_known_controls;
 }
 
-bool ldap_decode_control_wrapper(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl, DATA_BLOB *value)
-{
-       DATA_BLOB oid;
-
-       if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
-               return false;
-       }
-
-       if (!asn1_read_OctetString(data, mem_ctx, &oid)) {
-               return false;
-       }
-       ctrl->oid = talloc_strndup(mem_ctx, (char *)oid.data, oid.length);
-       if (!ctrl->oid) {
-               return false;
-       }
-
-       if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
-               bool critical;
-               if (!asn1_read_BOOLEAN(data, &critical)) {
-                       return false;
-               }
-               ctrl->critical = critical;
-       } else {
-               ctrl->critical = false;
-       }
-
-       ctrl->data = NULL;
-
-       if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
-               *value = data_blob(NULL, 0);
-               goto end_tag;
-       }
-
-       if (!asn1_read_OctetString(data, mem_ctx, value)) {
-               return false;
-       }
-
-end_tag:
-       if (!asn1_end_tag(data)) {
-               return false;
-       }
-
-       return true;
-}
-
-bool ldap_encode_control(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl)
-{
-       DATA_BLOB value;
-       int i;
-
-       for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
-               if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
-                       if (!ldap_known_controls[i].encode) {
-                               if (ctrl->critical) {
-                                       return false;
-                               } else {
-                                       /* not encoding this control */
-                                       return true;
-                               }
-                       }
-                       if (!ldap_known_controls[i].encode(mem_ctx, ctrl->data, &value)) {
-                               return false;
-                       }
-                       break;
-               }
-       }
-       if (ldap_known_controls[i].oid == NULL) {
-               return false;
-       }
-
-       if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
-               return false;
-       }
-
-       if (!asn1_write_OctetString(data, ctrl->oid, strlen(ctrl->oid))) {
-               return false;
-       }
-
-       if (ctrl->critical) {
-               if (!asn1_write_BOOLEAN(data, ctrl->critical)) {
-                       return false;
-               }
-       }
-
-       if (!ctrl->data) {
-               goto pop_tag;
-       }
-
-       if (!asn1_write_OctetString(data, value.data, value.length)) {
-               return false;
-       }
-
-pop_tag:
-       if (!asn1_pop_tag(data)) {
-               return false;
-       }
-
-       return true;
-}
diff --git a/source4/libcli/ldap/ldap_msg.c b/source4/libcli/ldap/ldap_msg.c
deleted file mode 100644 (file)
index e45213c..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* 
-   Unix SMB/CIFS mplementation.
-
-   LDAP protocol helper functions for SAMBA
-   
-   Copyright (C) Andrew Tridgell  2005
-   Copyright (C) Volker Lendecke 2004
-    
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-   
-*/
-
-#include "includes.h"
-#include "libcli/ldap/ldap.h"
-#include "libcli/ldap/ldap_client.h"
-#include "libcli/ldap/ldap_proto.h"
-
-
-_PUBLIC_ struct ldap_message *new_ldap_message(TALLOC_CTX *mem_ctx)
-{
-       return talloc_zero(mem_ctx, struct ldap_message);
-}
-
-
-bool add_value_to_attrib(TALLOC_CTX *mem_ctx, struct ldb_val *value,
-                        struct ldb_message_element *attrib)
-{
-       attrib->values = talloc_realloc(mem_ctx, 
-                                         attrib->values,
-                                         DATA_BLOB,
-                                         attrib->num_values+1);
-       if (attrib->values == NULL)
-               return false;
-
-       attrib->values[attrib->num_values].data = talloc_steal(attrib->values, 
-                                                              value->data);
-       attrib->values[attrib->num_values].length = value->length;
-       attrib->num_values += 1;
-       return true;
-}
-
-bool add_attrib_to_array_talloc(TALLOC_CTX *mem_ctx,
-                                      const struct ldb_message_element *attrib,
-                                      struct ldb_message_element **attribs,
-                                      int *num_attribs)
-{
-       *attribs = talloc_realloc(mem_ctx,
-                                   *attribs,
-                                   struct ldb_message_element,
-                                   *num_attribs+1);
-
-       if (*attribs == NULL)
-               return false;
-
-       (*attribs)[*num_attribs] = *attrib;
-       talloc_steal(*attribs, attrib->values);
-       talloc_steal(*attribs, attrib->name);
-       *num_attribs += 1;
-       return true;
-}
-
-bool add_mod_to_array_talloc(TALLOC_CTX *mem_ctx,
-                                   struct ldap_mod *mod,
-                                   struct ldap_mod **mods,
-                                   int *num_mods)
-{
-       *mods = talloc_realloc(mem_ctx, *mods, struct ldap_mod, (*num_mods)+1);
-
-       if (*mods == NULL)
-               return false;
-
-       (*mods)[*num_mods] = *mod;
-       *num_mods += 1;
-       return true;
-}
-
index 8371837dcb574d682f5282996053e5c201dae3a1..4e7cdf5c3aa61e07536aaf59cb8c725734dac7a3 100644 (file)
@@ -20,7 +20,7 @@
 /* NT error codes.  please read nterr.h */
 
 #include "includes.h"
-#include "libcli/ldap/ldap_errors.h"
+#include "../libcli/ldap/ldap_errors.h"
 #undef strcasecmp
 
 typedef struct
index 04f7a36a5f26d121a03caae81bd5c28fce482462..ee2018fb694f7dae00683c77eba272f8aac6a6a4 100644 (file)
@@ -50,3 +50,5 @@ mkinclude kdc/config.mk
 mkinclude ../lib/smbconf/config.mk
 mkinclude ../lib/async_req/config.mk
 mkinclude ../libcli/security/config.mk
+mkinclude ../libcli/ldap/config.mk
+
index 24c467fe6519caa9c0a03b3d7a9c2fce26d14df6..91817a202f2592c8092088de989bb3dcf2a8e892 100644 (file)
@@ -74,6 +74,7 @@ struct spoolss_EnumForms;
 struct spoolss_EnumPorts;
 struct spoolss_EnumPrintProcessors;
 struct spoolss_XcvData;
+struct spoolss_GetPrintProcessorDirectory;
 
 /* the ntptr operations structure - contains function pointers to 
    the backend implementations of each operation */
@@ -144,6 +145,8 @@ struct ntptr_ops {
        /* PrintProcessor functions */
        WERROR (*EnumPrintProcessors)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
                                      struct spoolss_EnumPrintProcessors *r);
+       WERROR (*GetPrintProcessorDirectory)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
+                                            struct spoolss_GetPrintProcessorDirectory *r);
 
        /* Printer functions */
        WERROR (*EnumPrinters)(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
index 109a9f560b4552e270bb6f19e691accb13654ead..b65a2e32cd52314728b732e19a16139e47e850ca 100644 (file)
@@ -263,6 +263,15 @@ WERROR ntptr_EnumPrintProcessors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ct
        return ntptr->ops->EnumPrintProcessors(ntptr, mem_ctx, r);
 }
 
+WERROR ntptr_GetPrintProcessorDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
+                                       struct spoolss_GetPrintProcessorDirectory *r)
+{
+       if (!ntptr->ops->GetPrintProcessorDirectory) {
+               return WERR_NOT_SUPPORTED;
+       }
+       return ntptr->ops->GetPrintProcessorDirectory(ntptr, mem_ctx, r);
+}
+
 
 /* Printer functions */
 WERROR ntptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
index c570b03a35c02b333f3b6b35ca6b1e2cb8b86669..459babce0ee5d1d344bf70a7b0089c3678a49d9b 100644 (file)
@@ -750,6 +750,47 @@ static WERROR sptr_GetPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CT
        return WERR_OK;
 }
 
+static WERROR sptr_GetPrintProcessorDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
+                                             struct spoolss_GetPrintProcessorDirectory *r)
+{
+       union spoolss_PrintProcessorDirectoryInfo *info;
+       const char *prefix;
+       const char *postfix;
+
+       /*
+        * NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a
+        *        are ignoring the r->in.level completely, so we do :-)
+        */
+
+       /*
+        * TODO: check the server name is ours
+        * - if it's a invalid UNC then return WERR_INVALID_NAME
+        * - if it's the wrong host name return WERR_INVALID_PARAM
+        * - if it's "" then we need to return a local WINDOWS path
+        */
+       if (!r->in.server || !r->in.server[0]) {
+               prefix = "C:\\PRTPROCS";
+       } else {
+               prefix = talloc_asprintf(mem_ctx, "%s\\prnproc$", r->in.server);
+               W_ERROR_HAVE_NO_MEMORY(prefix);
+       }
+
+       if (r->in.environment && strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) {
+               postfix = "W32X86";
+       } else {
+               return WERR_INVALID_ENVIRONMENT;
+       }
+
+       info = talloc(mem_ctx, union spoolss_PrintProcessorDirectoryInfo);
+       W_ERROR_HAVE_NO_MEMORY(info);
+
+       info->info1.directory_name      = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix);
+       W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name);
+
+       r->out.info = info;
+       return WERR_OK;
+}
+
 
 /*
   initialialise the simble ldb backend, registering ourselves with the ntptr subsystem
@@ -793,6 +834,8 @@ static const struct ntptr_ops ntptr_simple_ldb_ops = {
        /* PrintProcessor functions */
 /*     .EnumPrintProcessors            = sptr_EnumPrintProcessors,
 */
+       .GetPrintProcessorDirectory     = sptr_GetPrintProcessorDirectory,
+
        /* Printer functions */
        .EnumPrinters                   = sptr_EnumPrinters,
        .OpenPrinter                    = sptr_OpenPrinter,
index 0fa638e863c2ca8f7199a1b44147b13788020626..2efddc74fc71523b92e86d3994e9f986b4272ad7 100644 (file)
@@ -47,7 +47,8 @@ struct server_pipe_state {
 static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                        struct netr_ServerReqChallenge *r)
 {
-       struct server_pipe_state *pipe_state = dce_call->context->private_data;
+       struct server_pipe_state *pipe_state =
+               (struct server_pipe_state *)dce_call->context->private_data;
 
        ZERO_STRUCTP(r->out.return_credentials);
 
@@ -76,7 +77,8 @@ static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_cal
 static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                         struct netr_ServerAuthenticate3 *r)
 {
-       struct server_pipe_state *pipe_state = dce_call->context->private_data;
+       struct server_pipe_state *pipe_state =
+               (struct server_pipe_state *)dce_call->context->private_data;
        struct creds_CredentialState *creds;
        void *sam_ctx;
        struct samr_Password *mach_pwd;
@@ -148,7 +150,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
                }
 
                /* pull the user attributes */
-               num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, trust_dom_attrs,
+               num_records = gendb_search((struct ldb_context *)sam_ctx,
+                                          mem_ctx, NULL, &msgs,
+                                          trust_dom_attrs,
                                           "(&(trustPartner=%s)(objectclass=trustedDomain))", 
                                           encoded_account);
                
@@ -179,7 +183,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
        }
        
        /* pull the user attributes */
-       num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
+       num_records = gendb_search((struct ldb_context *)sam_ctx, mem_ctx,
+                                  NULL, &msgs, attrs,
                                   "(&(sAMAccountName=%s)(objectclass=user))", 
                                   ldb_binary_encode_string(mem_ctx, account_name));
 
@@ -848,13 +853,14 @@ static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_C
                return WERR_DS_SERVICE_UNAVAILABLE;
        }
 
-       domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
+       domain_dn = samdb_domain_to_dn((struct ldb_context *)sam_ctx, mem_ctx,
                                       r->in.domainname);
        if (domain_dn == NULL) {
                return WERR_DS_SERVICE_UNAVAILABLE;
        }
 
-       ret = gendb_search_dn(sam_ctx, mem_ctx, domain_dn, &res, attrs);
+       ret = gendb_search_dn((struct ldb_context *)sam_ctx, mem_ctx,
+                             domain_dn, &res, attrs);
        if (ret != 1) {
                return WERR_NO_SUCH_DOMAIN;
        }
@@ -1214,17 +1220,19 @@ static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TA
 
        /* Win7-beta will send the domain name in the form the user typed, so we have to cope
           with both the short and long form here */
-       if (strcasecmp(r->in.domain_name, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx)) == 0) {
+       if (r->in.domain_name == NULL || strcasecmp(r->in.domain_name, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx)) == 0) {
                r->in.domain_name = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
        }
 
-       domain_dn = samdb_dns_domain_to_dn(sam_ctx, mem_ctx,
+       domain_dn = samdb_dns_domain_to_dn((struct ldb_context *)sam_ctx,
+                                          mem_ctx,
                                           r->in.domain_name);   
        if (domain_dn == NULL) {
                return WERR_DS_SERVICE_UNAVAILABLE;
        }
 
-       ret = gendb_search_dn(sam_ctx, mem_ctx, domain_dn, &res, attrs);
+       ret = gendb_search_dn((struct ldb_context *)sam_ctx, mem_ctx,
+                             domain_dn, &res, attrs);
        if (ret != 1) {
                return WERR_NO_SUCH_DOMAIN;
        }
@@ -1377,9 +1385,11 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce
                return WERR_GENERAL_FAILURE;
        }
 
-       partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
+       partitions_basedn = samdb_partitions_dn((struct ldb_context *)sam_ctx,
+                                               mem_ctx);
 
-       ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
+       ret = gendb_search_dn((struct ldb_context *)sam_ctx, mem_ctx, NULL,
+                             &dom_res, dom_attrs);
        if (ret == -1) {
                return WERR_GENERAL_FAILURE;            
        }
@@ -1387,7 +1397,8 @@ static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce
                return WERR_GENERAL_FAILURE;
        }
 
-       ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &ref_res, ref_attrs,
+       ret = gendb_search((struct ldb_context *)sam_ctx, mem_ctx,
+                          partitions_basedn, &ref_res, ref_attrs,
                           "(&(objectClass=crossRef)(ncName=%s))",
                           ldb_dn_get_linearized(dom_res[0]->dn));
        if (ret == -1) {
index 33c657cc1b5d9467b1e6d4133b0b7668f5f37aa1..f1ef2f0acb95f54bb5feaef2954e0355aca001c5 100644 (file)
@@ -454,7 +454,19 @@ static WERROR dcesrv_spoolss_EnumPrintProcessors(struct dcesrv_call_state *dce_c
 static WERROR dcesrv_spoolss_GetPrintProcessorDirectory(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct spoolss_GetPrintProcessorDirectory *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private_data, struct ntptr_context);
+       WERROR status;
+       struct smb_iconv_convenience *ic = lp_iconv_convenience(ntptr->lp_ctx);
+
+       status = dcesrv_spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
+       W_ERROR_NOT_OK_RETURN(status);
+
+       status = ntptr_GetPrintProcessorDirectory(ntptr, mem_ctx, r);
+       W_ERROR_NOT_OK_RETURN(status);
+
+       *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, ic, r->out.info, r->in.level);
+       r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
+       return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
 }
 
 
@@ -534,7 +546,11 @@ static WERROR dcesrv_spoolss_EndDocPrinter(struct dcesrv_call_state *dce_call, T
 static WERROR dcesrv_spoolss_AddJob(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct spoolss_AddJob *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       if (r->in.level != 1) {
+               return WERR_UNKNOWN_LEVEL;
+       }
+
+       return WERR_INVALID_PARAM;
 }
 
 
index e9fc26af20b846a470d3994807f260a4dfc799a1..a49e6e1eadb7460476b7cc2bb5838465574c473f 100644 (file)
@@ -223,7 +223,7 @@ def check_all_substituted(text):
     :param text: The text to search for substitution variables
     """
     if not "${" in text:
-       return
+        return
     
     var_start = text.find("${")
     var_end = text.find("}", var_start)
index a5b3e8322faec34404bd83ca2a06d0ddb8313f43..0aa84ec6db7fbe07e2488244c4cec0beee005207 100644 (file)
@@ -4,6 +4,7 @@
 
 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
+# Copyright (C) Oliver Liebel <oliver@itc.li> 2008-2009
 #
 # Based on the original in EJS:
 # Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
@@ -26,6 +27,7 @@
 
 from base64 import b64encode
 import os
+import sys
 import pwd
 import grp
 import time
@@ -50,7 +52,7 @@ def find_setup_dir():
     """Find the setup directory used by provision."""
     dirname = os.path.dirname(__file__)
     if "/site-packages/" in dirname:
-        prefix = dirname[:dirname.index("/site-packages/")]
+        prefix = "/".join(dirname[:dirname.index("/site-packages/")].split("/")[:-2])
         for suffix in ["share/setup", "share/samba/setup", "setup"]:
             ret = os.path.join(prefix, suffix)
             if os.path.isdir(ret):
@@ -93,9 +95,12 @@ class ProvisionPaths(object):
         self.memberofconf = None
         self.fedoradsinf = None
         self.fedoradspartitions = None
-       self.olmmron = None
-       self.olmmrserveridsconf = None
-       self.olmmrsyncreplconf = None
+        self.olmmron = None
+        self.olmmrserveridsconf = None
+        self.olmmrsyncreplconf = None
+        self.olcdir = None
+        self.olslaptest = None
+        self.olcseedldif = None
 
 
 class ProvisionNames(object):
@@ -268,6 +273,10 @@ def provision_paths_from_lp(lp, dnsdomain):
                                             "mmr_serverids.conf")
     paths.olmmrsyncreplconf = os.path.join(paths.ldapdir, 
                                            "mmr_syncrepl.conf")
+    paths.olcdir = os.path.join(paths.ldapdir, 
+                                 "slapd.d")
+    paths.olcseedldif = os.path.join(paths.ldapdir, 
+                                 "olc_seed.ldif")
     paths.hklm = "hklm.ldb"
     paths.hkcr = "hkcr.ldb"
     paths.hkcu = "hkcu.ldb"
@@ -1178,7 +1187,7 @@ def provision_backend(setup_dir=None, message=None,
                       rootdn=None, domaindn=None, schemadn=None, configdn=None,
                       domain=None, hostname=None, adminpass=None, root=None, serverrole=None, 
                       ldap_backend_type=None, ldap_backend_port=None,
-                     ol_mmr_urls=None):
+                      ol_mmr_urls=None,ol_olc=None,ol_slaptest=None):
 
     def setup_path(file):
         return os.path.join(setup_dir, file)
@@ -1205,6 +1214,19 @@ def provision_backend(setup_dir=None, message=None,
         make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, 
                      targetdir)
 
+    # openldap-online-configuration: validation of olc and slaptest
+    if ol_olc == "yes" and ol_slaptest is None: 
+        sys.exit("Warning: OpenLDAP-Online-Configuration cant be setup without path to slaptest-Binary!")
+
+    if ol_olc == "yes" and ol_slaptest is not None:
+        ol_slaptest = ol_slaptest + "/slaptest"
+        if not os.path.exists(ol_slaptest):
+            message (ol_slaptest)
+            sys.exit("Warning: Given Path to slaptest-Binary does not exist!")
+    ###
+
+
+
     lp = param.LoadParm()
     lp.load(smbconf)
 
@@ -1300,52 +1322,95 @@ def provision_backend(setup_dir=None, message=None,
                                             { "LINK_ATTRS" : refint_attributes})
 
 # generate serverids, ldap-urls and syncrepl-blocks for mmr hosts
-       mmr_on_config = ""
-       mmr_replicator_acl = ""
-       mmr_serverids_config = ""
+        mmr_on_config = ""
+        mmr_replicator_acl = ""
+        mmr_serverids_config = ""
         mmr_syncrepl_schema_config = "" 
-       mmr_syncrepl_config_config = "" 
-       mmr_syncrepl_user_config = "" 
-       
-       if ol_mmr_urls is not None:
+        mmr_syncrepl_config_config = "" 
+        mmr_syncrepl_user_config = "" 
+       
+        if ol_mmr_urls is not None:
                 # For now, make these equal
                 mmr_pass = adminpass
 
-               url_list=filter(None,ol_mmr_urls.split(' ')) 
+                url_list=filter(None,ol_mmr_urls.split(' ')) 
                 if (len(url_list) == 1):
                     url_list=filter(None,ol_mmr_urls.split(',')) 
                      
 
-               mmr_on_config = "MirrorMode On"
-               mmr_replicator_acl = "  by dn=cn=replicator,cn=samba read"
-               serverid=0
-               for url in url_list:
-                       serverid=serverid+1
-                       mmr_serverids_config += read_and_sub_file(setup_path("mmr_serverids.conf"),
-                                                                    { "SERVERID" : str(serverid),
-                                                                      "LDAPSERVER" : url })
+                mmr_on_config = "MirrorMode On"
+                mmr_replicator_acl = "  by dn=cn=replicator,cn=samba read"
+                serverid=0
+                for url in url_list:
+                        serverid=serverid+1
+                        mmr_serverids_config += read_and_sub_file(setup_path("mmr_serverids.conf"),
+                                                                     { "SERVERID" : str(serverid),
+                                                                       "LDAPSERVER" : url })
                         rid=serverid*10
-                       rid=rid+1
-                       mmr_syncrepl_schema_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
-                                                                    {  "RID" : str(rid),
-                                                                       "MMRDN": names.schemadn,
-                                                                       "LDAPSERVER" : url,
+                        rid=rid+1
+                        mmr_syncrepl_schema_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
+                                                                     {  "RID" : str(rid),
+                                                                        "MMRDN": names.schemadn,
+                                                                        "LDAPSERVER" : url,
                                                                         "MMR_PASSWORD": mmr_pass})
 
-                       rid=rid+1
-                       mmr_syncrepl_config_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
-                                                                    {  "RID" : str(rid),
-                                                                       "MMRDN": names.configdn,
-                                                                       "LDAPSERVER" : url,
+                        rid=rid+1
+                        mmr_syncrepl_config_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
+                                                                     {  "RID" : str(rid),
+                                                                        "MMRDN": names.configdn,
+                                                                        "LDAPSERVER" : url,
                                                                         "MMR_PASSWORD": mmr_pass})
 
-                       rid=rid+1
-                       mmr_syncrepl_user_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
-                                                                    {  "RID" : str(rid),
-                                                                       "MMRDN": names.domaindn,
-                                                                       "LDAPSERVER" : url,
+                        rid=rid+1
+                        mmr_syncrepl_user_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
+                                                                     {  "RID" : str(rid),
+                                                                        "MMRDN": names.domaindn,
+                                                                        "LDAPSERVER" : url,
                                                                         "MMR_PASSWORD": mmr_pass })
+        # olc = yes?
+        olc_config_pass = ""
+        olc_config_acl = ""
+        olc_syncrepl_config = ""
+        olc_mmr_config = "" 
+        if ol_olc == "yes":
+                olc_config_pass += read_and_sub_file(setup_path("olc_pass.conf"),
+                                                                { "OLC_PW": adminpass })
+                olc_config_acl += read_and_sub_file(setup_path("olc_acl.conf"),{})
+                
+            # if olc = yes + mmr = yes, generate cn=config-replication directives
+            # and  olc_seed.lif for the other mmr-servers
+                if ol_olc == "yes" and ol_mmr_urls is not None:
+                        serverid=0
+                        olc_serverids_config = ""
+                        olc_syncrepl_config = ""
+                        olc_syncrepl_seed_config = ""
+                        olc_mmr_config = "" 
+                        olc_mmr_config += read_and_sub_file(setup_path("olc_mmr.conf"),{})
+                        rid=1000
+                        for url in url_list:
+                                serverid=serverid+1
+                                olc_serverids_config += read_and_sub_file(setup_path("olc_serverid.conf"),
+                                                                     { "SERVERID" : str(serverid),
+                                                                       "LDAPSERVER" : url })
+                        
+                                rid=rid+1
+                                olc_syncrepl_config += read_and_sub_file(setup_path("olc_syncrepl.conf"),
+                                                                     {  "RID" : str(rid),
+                                                                        "LDAPSERVER" : url,
+                                                                        "MMR_PASSWORD": adminpass})
+
+                                olc_syncrepl_seed_config += read_and_sub_file(setup_path("olc_syncrepl_seed.conf"),
+                                                                     {  "RID" : str(rid),
+                                                                        "LDAPSERVER" : url})
+
+                                setup_file(setup_path("olc_seed.ldif"), paths.olcseedldif,
+                                                                     {"OLC_SERVER_ID_CONF": olc_serverids_config,
+                                                                      "OLC_PW": adminpass,
+                                                                      "OLC_SYNCREPL_CONF": olc_syncrepl_seed_config})
+        
 
+                # end olc
 
         setup_file(setup_path("slapd.conf"), paths.slapdconf,
                    {"DNSDOMAIN": names.dnsdomain,
@@ -1360,8 +1425,12 @@ def provision_backend(setup_dir=None, message=None,
                     "MMR_SYNCREPL_SCHEMA_CONFIG": mmr_syncrepl_schema_config,
                     "MMR_SYNCREPL_CONFIG_CONFIG": mmr_syncrepl_config_config,
                     "MMR_SYNCREPL_USER_CONFIG": mmr_syncrepl_user_config,
+                    "OLC_CONFIG_PASS": olc_config_pass,
+                    "OLC_SYNCREPL_CONFIG": olc_syncrepl_config,
+                    "OLC_CONFIG_ACL": olc_config_acl,
+                    "OLC_MMR_CONFIG": olc_mmr_config,
                     "REFINT_CONFIG": refint_config})
-       setup_file(setup_path("modules.conf"), paths.modulesconf,
+        setup_file(setup_path("modules.conf"), paths.modulesconf,
                    {"REALM": names.realm})
         
         setup_db_config(setup_path, os.path.join(paths.ldapdir, "db", "user"))
@@ -1380,16 +1449,15 @@ def provision_backend(setup_dir=None, message=None,
                               {"LDAPADMINPASS_B64": b64encode(adminpass),
                                "UUID": str(uuid.uuid4()), 
                                "LDAPTIME": timestring(int(time.time()))} )
-       
-       if ol_mmr_urls is not None:
-          setup_file(setup_path("cn=replicator.ldif"),
+        
+        if ol_mmr_urls is not None:
+           setup_file(setup_path("cn=replicator.ldif"),
                               os.path.join(paths.ldapdir, "db", "samba",  "cn=samba", "cn=replicator.ldif"),
                               {"MMR_PASSWORD_B64": b64encode(mmr_pass),
                                "UUID": str(uuid.uuid4()),
                                "LDAPTIME": timestring(int(time.time()))} )
 
 
-
         mapping = "schema-map-openldap-2.3"
         backend_schema = "backend-schema.schema"
 
@@ -1399,7 +1467,18 @@ def provision_backend(setup_dir=None, message=None,
         else:
             server_port_string = ""
 
-        slapdcommand="Start slapd with:    slapd -f " + paths.ldapdir + "/slapd.conf -h " + ldapi_uri + server_port_string
+        if ol_olc != "yes" and ol_mmr_urls is None:
+          slapdcommand="Start slapd with:    slapd -f " + paths.ldapdir + "/slapd.conf -h " + ldapi_uri + server_port_string
+
+        if ol_olc == "yes" and ol_mmr_urls is None:
+          slapdcommand="Start slapd with:    slapd -F " + paths.olcdir + " -h \"" + ldapi_uri + " ldap://<FQHN>:<PORT>\"" 
+
+        if ol_olc != "yes" and ol_mmr_urls is not None:
+          slapdcommand="Start slapd with:    slapd -f " + paths.ldapdir + "/slapd.conf -h \"" + ldapi_uri + " ldap://<FQHN>:<PORT>\""
+
+        if ol_olc == "yes" and ol_mmr_urls is not None:
+          slapdcommand="Start slapd with:    slapd -F " + paths.olcdir + " -h \"" + ldapi_uri + " ldap://<FQHN>:<PORT>\""
+
 
         ldapuser = "--username=samba-admin"
 
@@ -1421,6 +1500,8 @@ def provision_backend(setup_dir=None, message=None,
 
     message("LDAP admin password: %s" % adminpass)
     message(slapdcommand)
+    if ol_olc == "yes" or ol_mmr_urls is not None:
+        message("Attention to slapd-Port: <PORT> must be different than 389!")
     assert isinstance(ldap_backend_type, str)
     assert isinstance(ldapuser, str)
     assert isinstance(adminpass, str)
@@ -1437,6 +1518,18 @@ def provision_backend(setup_dir=None, message=None,
     message("Run provision with: " + " ".join(args))
 
 
+    # if --ol-olc=yes, generate online-configuration in ../private/ldap/slapd.d 
+    if ol_olc == "yes":
+          if not os.path.isdir(paths.olcdir):
+             os.makedirs(paths.olcdir, 0770)
+          paths.olslaptest = str(ol_slaptest)
+          olc_command = paths.olslaptest + " -f" + paths.slapdconf + " -F" +  paths.olcdir + " >/dev/null 2>&1"
+          os.system(olc_command)
+          os.remove(paths.slapdconf)        
+          # use line below for debugging during olc-conversion with slaptest, instead of olc_command above 
+          #olc_command = paths.olslaptest + " -f" + paths.slapdconf + " -F" +  paths.olcdir"
+
+
 def create_phpldapadmin_config(path, setup_path, ldapi_uri):
     """Create a PHP LDAP admin configuration file.
 
index 9cc55e5629e829b5dd3b7f7af6a9e453f0e29aba..614970d3ec5b6bfadd144853fd29d99ebfcb76ef 100644 (file)
@@ -201,11 +201,11 @@ userAccountControl: %u
         glue.dsdb_attach_schema_from_ldif_file(self, pf, df)
 
     def set_invocation_id(self, invocation_id):
-       """Set the invocation id for this SamDB handle.
-       
-       :param invocation_id: GUID of the invocation id.
-       """
-       glue.dsdb_set_ntds_invocation_id(self, invocation_id)
+        """Set the invocation id for this SamDB handle.
+        
+        :param invocation_id: GUID of the invocation id.
+        """
+        glue.dsdb_set_ntds_invocation_id(self, invocation_id)
 
     def setexpiry(self, user, expiry_seconds, noexpiry):
         """Set the password expiry for a user
index d827bfa0044926e4c6e9d56052392fab03e078b4..b342b93c498d008f25f7ca7b7287af31ec5bc595 100644 (file)
@@ -70,8 +70,8 @@ class SubstituteVarTestCase(unittest.TestCase):
                 samba.substitute_var("foo ${bla} gsff", {"bar": "bla"}))
                 
     def test_check_all_substituted(self):
-       samba.check_all_substituted("nothing to see here")
-       self.assertRaises(Exception, samba.check_all_substituted, "Not subsituted: ${FOOBAR}")
+        samba.check_all_substituted("nothing to see here")
+        self.assertRaises(Exception, samba.check_all_substituted, "Not subsituted: ${FOOBAR}")
 
 
 class LdbExtensionTests(TestCaseInTempDir):
index 352357f6942046f25de75f35e9eb84fa811419fb..fdac9d4ea2193f877a9a981eadecad87fa8c33ac 100644 (file)
@@ -56,7 +56,7 @@ class ProvisionTestCase(samba.tests.TestCaseInTempDir):
                            machinepass="machinepass", dnsdomain="example.com")
             self.assertEquals(1, 
                     len(secrets_ldb.search("samAccountName=krbtgt,flatname=EXAMPLE,CN=Principals")))
-           self.assertEquals("keytab.path",
+            self.assertEquals("keytab.path",
                     secrets_ldb.searchone(basedn="flatname=EXAMPLE,CN=primary domains", 
                                           expression="(privateKeytab=*)", 
                                           attribute="privateKeytab"))
index 36e3bbe364ce206eb98298c1d6fa4467081733f1..99e530ec3853de79ab6d5bc57f684a5d227060e1 100755 (executable)
@@ -23,6 +23,11 @@ then
        PERL=perl
 fi
 
+if [ ! -n "$PYTHON" ]
+then
+       PYTHON=python
+fi
+
 plantest() {
        name=$1
        env=$2
@@ -394,7 +399,6 @@ then
        plantest "nss.test using winbind" member $VALGRIND $nsstest4 $samba4bindir/shared/libnss_winbind.so
 fi
 
-PYTHON=/usr/bin/python
 SUBUNITRUN="$VALGRIND $PYTHON $samba4srcdir/scripting/bin/subunitrun"
 plantest "ldb.python" none PYTHONPATH="$PYTHONPATH:$samba4srcdir/lib/ldb/tests/python/" $SUBUNITRUN api
 plantest "credentials.python" none PYTHONPATH="$PYTHONPATH:$samba4srcdir/auth/credentials/tests" $SUBUNITRUN bindings
index b4d2bfa868343d1bd8655992b3f085f8118b9ccf..74bb09d8009d9c2f5df59a8532321260e9c057f4 100644 (file)
@@ -1,17 +1,6 @@
-#
-# Set the database in memory cache size.
-#
 set_cachesize   0       524288        0
-
-#
-# Set log values.
-#
 set_lg_regionmax        104857
 set_lg_max              1048576
 set_lg_bsize            209715
 set_lg_dir              ${LDAPDBDIR}/bdb-logs
-
-#
-# Set temporary file creation directory.
-#                      
 set_tmp_dir             ${LDAPDBDIR}/tmp
index c6d14010b4b7e7aaddbe5389f16f9c4b11530676..e4daf2028a6ec7c3fa7cbecc0788888dc7974adc 100644 (file)
@@ -1,2 +1 @@
-# Generated from template mmr_serverids.conf
 ServerID ${SERVERID} "${LDAPSERVER}"
diff --git a/source4/setup/olc_acl.conf b/source4/setup/olc_acl.conf
new file mode 100644 (file)
index 0000000..c248b30
--- /dev/null
@@ -0,0 +1,4 @@
+access to dn.sub="cn=config"
+       by dn="cn=samba-admin,cn=samba" write
+       by dn="cn=replicator,cn=samba" read
+
diff --git a/source4/setup/olc_mmr.conf b/source4/setup/olc_mmr.conf
new file mode 100644 (file)
index 0000000..2f60df1
--- /dev/null
@@ -0,0 +1,3 @@
+overlay syncprov
+MirrorMode on
diff --git a/source4/setup/olc_pass.conf b/source4/setup/olc_pass.conf
new file mode 100644 (file)
index 0000000..4c66c1c
--- /dev/null
@@ -0,0 +1,3 @@
+database       config
+rootdn         cn=config
+
diff --git a/source4/setup/olc_seed.ldif b/source4/setup/olc_seed.ldif
new file mode 100644 (file)
index 0000000..afc3abe
--- /dev/null
@@ -0,0 +1,16 @@
+dn: cn=config
+objectClass: olcGlobal
+cn: config
+${OLC_SERVER_ID_CONF}
+
+dn: olcDatabase={0}config,cn=config
+objectClass: olcDatabaseConfig
+olcDatabase: {0}config
+olcRootDN: cn=config
+olcRootPW: ${OLC_PW}
+${OLC_SYNCREPL_CONF}olcMirrorMode: TRUE
+
+dn: olcOverlay=syncprov,olcDatabase={0}config,cn=config
+objectClass: olcSyncProvConfig
+olcOverlay: syncprov
diff --git a/source4/setup/olc_serverid.conf b/source4/setup/olc_serverid.conf
new file mode 100644 (file)
index 0000000..3d28acb
--- /dev/null
@@ -0,0 +1 @@
+olcServerID: ${SERVERID} "${LDAPSERVER}"
diff --git a/source4/setup/olc_syncrepl.conf b/source4/setup/olc_syncrepl.conf
new file mode 100644 (file)
index 0000000..fd7a58d
--- /dev/null
@@ -0,0 +1,13 @@
+# Generated from template olc_syncrepl.conf 
+
+syncrepl rid=${RID} 
+       provider="${LDAPSERVER}"
+       searchbase="cn=config"
+       filter="(!(olcDatabase={0}config))"
+       type=refreshAndPersist
+       retry="10 +"
+       bindmethod=sasl
+       saslmech=DIGEST-MD5
+       authcid="replicator"
+       credentials="${MMR_PASSWORD}"
+
diff --git a/source4/setup/olc_syncrepl_seed.conf b/source4/setup/olc_syncrepl_seed.conf
new file mode 100644 (file)
index 0000000..1833fb9
--- /dev/null
@@ -0,0 +1,5 @@
+olcSyncRepl: rid=${RID} provider="${LDAPSERVER}"
+  binddn="cn=config" bindmethod=sasl saslmech=DIGEST-MD5
+  authcid="replicator" credentials="linux"
+  searchbase="cn=config" filter="(!(olcDatabase={0}config))"
+  type=refreshAndPersist retry="10 +"
index eca209cb187ebe4c56081d1eeecd7303ad7be5a1..28e73ae3022f4bb975b56ff14e7c989e2e52e3d9 100755 (executable)
@@ -4,6 +4,7 @@
 # provision a Samba4 server
 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
+# Copyright (C) Oliver Liebel <oliver@itc.li> 2008-2009
 #
 # Based on the original in EJS:
 # Copyright (C) Andrew Tridgell 2005
@@ -65,8 +66,12 @@ parser.add_option("--server-role", type="choice", metavar="ROLE",
 parser.add_option("--targetdir", type="string", metavar="DIR", 
                          help="Set target directory")
 parser.add_option("--ol-mmr-urls", type="string", metavar="LDAPSERVER",
-                help="List of LDAP-URLS [ ldap://<FQDN>:port/  (where port != 389) ] separated with whitespaces for use with OpenLDAP-MMR")
-
+                help="List of LDAP-URLS [ ldap://<FQHN>:<PORT>/  (where <PORT> has to be different from 389!) ] separated with whitespaces for use with OpenLDAP-MMR (Multi-Master-Replication)")
+parser.add_option("--ol-olc", type="choice", metavar="OPENLDAP-OLC", 
+               help="To setup OpenLDAP-Backend with Online-Configuration [slapd.d] choose 'yes'. Note: Only OpenLDAP-Versions greater or equal 2.4.15 should be used!",
+               choices=["yes", "no"])
+parser.add_option("--ol-slaptest", type="string", metavar="SLAPTEST-PATH", 
+               help="Path to slaptest-binary [e.g.:'/usr/local/sbin']. Only for use with --ol-olc='yes'")
 
 opts = parser.parse_args()[0]
 
@@ -103,5 +108,7 @@ provision_backend(setup_dir=setup_dir, message=message, smbconf=smbconf, targetd
                  root=opts.root, serverrole=server_role, 
                  ldap_backend_type=opts.ldap_backend_type,
                  ldap_backend_port=opts.ldap_backend_port,
-                 ol_mmr_urls=opts.ol_mmr_urls)
+                 ol_mmr_urls=opts.ol_mmr_urls,
+                 ol_olc=opts.ol_olc,
+                 ol_slaptest=opts.ol_slaptest)
 
index 506dc504b4983590066719ac5d2df508142ff856..09dffbbfa3f9fcc3848692707a3ac14fa64994fa 100644 (file)
@@ -7,7 +7,6 @@ sizelimit unlimited
 
 ${MMR_SERVERIDS_CONFIG}
 
-
 include ${LDAPDIR}/backend-schema.schema
 
 pidfile                ${LDAPDIR}/slapd.pid
@@ -62,6 +61,13 @@ suffix               cn=Samba
 directory       ${LDAPDIR}/db/samba
 rootdn          cn=Manager,cn=Samba
 
+########################################
+## olc - configuration ###
+${OLC_CONFIG_PASS}
+${OLC_SYNCREPL_CONFIG}
+${OLC_MMR_CONFIG}
+${OLC_CONFIG_ACL}
+
 ########################################
 ### cn=schema ###
 database        hdb
@@ -78,10 +84,10 @@ index cn eq
 index entryUUID,entryCSN eq
 
 #syncprov is stable in OpenLDAP 2.3, and available in 2.2.  
-#We only need this for the contextCSN attribute anyway....
+#We need this for the contextCSN attribute and mmr.
 overlay syncprov
 syncprov-sessionlog 100
-syncprov-checkpoint 100 10
+syncprov-checkpoint 100 10
 
 
 ### Multimaster-Replication of cn=schema Subcontext ###
@@ -107,10 +113,10 @@ index cn eq
 index entryUUID,entryCSN eq
 
 #syncprov is stable in OpenLDAP 2.3, and available in 2.2.  
-#We only need this for the contextCSN attribute anyway....
+#We need this for the contextCSN attribute and mmr.
 overlay syncprov
 syncprov-sessionlog 100
-syncprov-checkpoint 100 10
+syncprov-checkpoint 100 10
 
 ### Multimaster-Replication of cn=config Subcontext ###
 ${MMR_SYNCREPL_CONFIG_CONFIG}
@@ -139,10 +145,10 @@ index cn eq
 index entryUUID,entryCSN eq
 
 #syncprov is stable in OpenLDAP 2.3, and available in 2.2.  
-#We only need this for the contextCSN attribute anyway....
+#We need this for the contextCSN attribute and mmr.
 overlay syncprov
 syncprov-sessionlog 100
-syncprov-checkpoint 100 10
+syncprov-checkpoint 100 10
 
 ### Multimaster-Replication of cn=user/base-dn context ###
 ${MMR_SYNCREPL_USER_CONFIG}
index 247a10f60f6734690b1aff238804eaff669a2e21..d576782ab1f0f189ec0a25500aecfb73c6886782 100644 (file)
@@ -277,7 +277,7 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[
 
        if (opt_daemon) {
                DEBUG(3,("Becoming a daemon.\n"));
-               become_daemon(true);
+               become_daemon(true, false);
        }
 
        cleanup_tmp_files(cmdline_lp_ctx);
index 82f7d1832367e757d5acf2d0155211079b536fc1..3ffc58dbe67d68a0ea577037904e04c7f3987879 100644 (file)
@@ -561,7 +561,7 @@ static bool test_notify_mask(struct smbcli_state *cli, struct torture_context *t
 
        tv = timeval_current_ofs(1000, 0);
        t = timeval_to_nttime(&tv);
-               
+
        /*
          get a handle on the directory
        */
@@ -1283,6 +1283,152 @@ done:
        return ret;
 }
 
+/*
+   Test response when cached server events exceed single NT NOTFIY response
+   packet size.
+*/
+static bool test_notify_overflow(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+{
+       bool ret = true;
+       NTSTATUS status;
+       union smb_notify notify;
+       union smb_open io;
+       int fnum, fnum2;
+       int count = 100;
+       struct smbcli_request *req1;
+       int i;
+
+       printf("TESTING CHANGE NOTIFY EVENT OVERFLOW\n");
+
+       /* get a handle on the directory */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.flags = 0;
+       io.ntcreatex.in.access_mask = SEC_FILE_ALL;
+       io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+           NTCREATEX_SHARE_ACCESS_WRITE;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = BASEDIR;
+
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+
+       /* ask for a change notify, on name changes. */
+       notify.nttrans.level = RAW_NOTIFY_NTTRANS;
+       notify.nttrans.in.buffer_size = 1000;
+       notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
+       notify.nttrans.in.file.fnum = fnum;
+
+       notify.nttrans.in.recursive = true;
+       req1 = smb_raw_changenotify_send(cli->tree, &notify);
+
+       /* cancel initial requests so the buffer is setup */
+       smb_raw_ntcancel(req1);
+       status = smb_raw_changenotify_recv(req1, mem_ctx, &notify);
+       CHECK_STATUS(status, NT_STATUS_CANCELLED);
+
+       /* open a lot of files, filling up the server side notify buffer */
+       printf("testing overflowed buffer notify on create of %d files\n",
+              count);
+       for (i=0;i<count;i++) {
+               char *fname = talloc_asprintf(cli, BASEDIR "\\test%d.txt", i);
+               int fnum2 = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR,
+                                       DENY_NONE);
+               if (fnum2 == -1) {
+                       printf("Failed to create %s - %s\n",
+                              fname, smbcli_errstr(cli->tree));
+                       ret = false;
+                       goto done;
+               }
+               talloc_free(fname);
+               smbcli_close(cli->tree, fnum2);
+       }
+
+       /* expect that 0 events will be returned with NT_STATUS_OK */
+       req1 = smb_raw_changenotify_send(cli->tree, &notify);
+       status = smb_raw_changenotify_recv(req1, mem_ctx, &notify);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       CHECK_VAL(notify.nttrans.out.num_changes, 0);
+
+done:
+       smb_raw_exit(cli->session);
+       return ret;
+}
+
+/*
+   Test if notifications are returned for changes to the base directory.
+   They shouldn't be.
+*/
+static bool test_notify_basedir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+{
+       bool ret = true;
+       NTSTATUS status;
+       union smb_notify notify;
+       union smb_open io;
+       int fnum, fnum2;
+       int count = 100;
+       struct smbcli_request *req1;
+       int i;
+
+       printf("TESTING CHANGE NOTIFY BASEDIR EVENTS\n");
+
+       /* get a handle on the directory */
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.flags = 0;
+       io.ntcreatex.in.access_mask = SEC_FILE_ALL;
+       io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+       io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+       io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+           NTCREATEX_SHARE_ACCESS_WRITE;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = BASEDIR;
+
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       fnum = io.ntcreatex.out.file.fnum;
+
+       /* create a test file that will also be modified */
+       smbcli_close(cli->tree, smbcli_open(cli->tree, BASEDIR "\\tname1",
+                                           O_CREAT, 0));
+
+       /* ask for a change notify, on attribute changes. */
+       notify.nttrans.level = RAW_NOTIFY_NTTRANS;
+       notify.nttrans.in.buffer_size = 1000;
+       notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_ATTRIBUTES;
+       notify.nttrans.in.file.fnum = fnum;
+       notify.nttrans.in.recursive = true;
+
+       req1 = smb_raw_changenotify_send(cli->tree, &notify);
+
+       /* set attribute on the base dir */
+       smbcli_setatr(cli->tree, BASEDIR, FILE_ATTRIBUTE_HIDDEN, 0);
+
+       /* set attribute on a file to assure we receive a notification */
+       smbcli_setatr(cli->tree, BASEDIR "\\tname1", FILE_ATTRIBUTE_HIDDEN, 0);
+       msleep(200);
+
+       /* check how many responses were given, expect only 1 for the file */
+       status = smb_raw_changenotify_recv(req1, mem_ctx, &notify);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       CHECK_VAL(notify.nttrans.out.num_changes, 1);
+       CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_MODIFIED);
+       CHECK_WSTR(notify.nttrans.out.changes[0].name, "tname1", STR_UNICODE);
+
+done:
+       smb_raw_exit(cli->session);
+       return ret;
+}
+
 /* 
    basic testing of change notify
 */
@@ -1291,7 +1437,7 @@ bool torture_raw_notify(struct torture_context *torture,
                        struct smbcli_state *cli2)
 {
        bool ret = true;
-               
+
        if (!torture_setup_dir(cli, BASEDIR)) {
                return false;
        }
@@ -1307,6 +1453,8 @@ bool torture_raw_notify(struct torture_context *torture,
        ret &= test_notify_tcp_dis(torture);
        ret &= test_notify_double(cli, torture);
        ret &= test_notify_tree(cli, torture);
+       ret &= test_notify_overflow(cli, torture);
+       ret &= test_notify_basedir(cli, torture);
 
        smb_raw_exit(cli->session);
        smbcli_deltree(cli->tree, BASEDIR);
index 9d629f0bbf8f028e75b6b58b8412f78ee9781c5d..951d91a6841b61431bf5866ecd53c3ca240d6efe 100644 (file)
@@ -516,6 +516,91 @@ done:
        return ret;
 }
 
+/*
+  test dir rename.
+*/
+static bool test_dir_rename(struct torture_context *tctx, struct smbcli_state *cli)
+{
+        union smb_open io;
+       union smb_rename ren_io;
+       NTSTATUS status;
+        const char *dname1 = BASEDIR "\\dir_for_rename";
+        const char *dname2 = BASEDIR "\\renamed_dir";
+        const char *fname = BASEDIR "\\dir_for_rename\\file.txt";
+       bool ret = true;
+       int fnum = -1;
+
+        printf("Checking rename on a directory containing an open file.\n");
+
+       if (!torture_setup_dir(cli, BASEDIR)) {
+               return false;
+       }
+
+        /* create a directory */
+        smbcli_rmdir(cli->tree, dname1);
+        smbcli_rmdir(cli->tree, dname2);
+        smbcli_unlink(cli->tree, dname1);
+        smbcli_unlink(cli->tree, dname2);
+
+        ZERO_STRUCT(io);
+        io.generic.level = RAW_OPEN_NTCREATEX;
+        io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+        io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+        io.ntcreatex.in.alloc_size = 0;
+        io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
+        io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+        io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+        io.ntcreatex.in.fname = dname1;
+        status = smb_raw_open(cli->tree, tctx, &io);
+        CHECK_STATUS(status, NT_STATUS_OK);
+
+        fnum = io.ntcreatex.out.file.fnum;
+       smbcli_close(cli->tree, fnum);
+
+        /* Now create and hold open a file. */
+        ZERO_STRUCT(io);
+
+        io.generic.level = RAW_OPEN_NTCREATEX;
+        io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
+        io.ntcreatex.in.root_fid = 0;
+        io.ntcreatex.in.alloc_size = 0;
+        io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+        io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+        io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
+        io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+        io.ntcreatex.in.create_options = 0;
+        io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+        io.ntcreatex.in.security_flags = 0;
+        io.ntcreatex.in.fname = fname;
+
+        /* Create the file. */
+
+        status = smb_raw_open(cli->tree, tctx, &io);
+        CHECK_STATUS(status, NT_STATUS_OK);
+        fnum = io.ntcreatex.out.file.fnum;
+
+        /* Now try and rename the directory. */
+
+        ZERO_STRUCT(ren_io);
+       ren_io.generic.level = RAW_RENAME_RENAME;
+       ren_io.rename.in.pattern1 = dname1;
+       ren_io.rename.in.pattern2 = dname2;
+       ren_io.rename.in.attrib = 0;
+       
+       status = smb_raw_rename(cli->tree, &ren_io);
+       CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
+
+done:
+       
+       if (fnum != -1) {
+               smbcli_close(cli->tree, fnum);
+       }
+       smb_raw_exit(cli->session);
+       smbcli_deltree(cli->tree, BASEDIR);
+       return ret;
+}
+
 extern bool test_trans2rename(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2);
 extern bool test_nttransrename(struct torture_context *tctx, struct smbcli_state *cli1);
 
@@ -533,6 +618,7 @@ struct torture_suite *torture_raw_rename(TALLOC_CTX *mem_ctx)
        torture_suite_add_1smb_test(suite, "nttransrename", test_nttransrename);
        torture_suite_add_1smb_test(suite, "ntrename", test_ntrename);
        torture_suite_add_1smb_test(suite, "osxrename", test_osxrename);
+       torture_suite_add_1smb_test(suite, "directory rename", test_dir_rename);
 
        return suite;
 }
index 8cdccb3906f3f01f1ebbdc9d080850eed1e825cb..c4c790cb0a9dba7c56c74eb3853e75864d5e3068 100644 (file)
@@ -672,6 +672,9 @@ bool torture_samba3_caseinsensitive(struct torture_context *torture)
 /*
  * Check that Samba3 correctly deals with conflicting posix byte range locks
  * on an underlying file
+ *
+ * Note: This test depends on "posix locking = yes".
+ * Note: To run this test, use "--option=torture:localdir=<LOCALDIR>"
  */
 
 bool torture_samba3_posixtimedlock(struct torture_context *tctx)
index 0622e0809d0bb579b6510dab5c8db1fa576b331b..d0d21ccc06cfd8e59d3794c20fb397692fc98073 100644 (file)
@@ -1454,7 +1454,7 @@ static bool test_stream_create_disposition(struct torture_context *tctx,
        status = smb_raw_open(cli->tree, mem_ctx, &io);
        CHECK_STATUS(status, NT_STATUS_OK);
        smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
-       if (!check_stream_list(cli, fname, 2, &default_stream_name)) {
+       if (!check_stream_list(cli, fname, 1, &default_stream_name)) {
                goto done;
        }
 
@@ -1535,6 +1535,121 @@ static bool test_stream_large_streaminfo(struct torture_context *tctx,
        return ret;
 }
 
+/* Test the effect of setting attributes on a stream. */
+static bool test_stream_attributes(struct torture_context *tctx,
+                                        struct smbcli_state *cli,
+                                        TALLOC_CTX *mem_ctx)
+{
+       bool ret = true;
+       NTSTATUS status;
+       union smb_open io;
+       const char *fname = BASEDIR "\\stream_attr.txt";
+       const char *stream = "Stream One:$DATA";
+       const char *fname_stream;
+       int fnum = -1;
+       union smb_fileinfo finfo;
+       union smb_setfileinfo sfinfo;
+       time_t basetime = (time(NULL) - 86400) & ~1;
+
+       printf ("(%s) testing attribute setting on stream\n", __location__);
+
+       fname_stream = talloc_asprintf(mem_ctx, "%s:%s", fname, stream);
+
+       /* Create a file with a stream with attribute FILE_ATTRIBUTE_ARCHIVE. */
+       ret = create_file_with_stream(tctx, cli, mem_ctx, fname,
+                                     fname_stream);
+       if (!ret) {
+               goto done;
+       }
+
+       ZERO_STRUCT(finfo);
+       finfo.generic.level = RAW_FILEINFO_BASIC_INFO;
+       finfo.generic.in.file.path = fname;
+       status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       if (finfo.basic_info.out.attrib != FILE_ATTRIBUTE_ARCHIVE) {
+               printf("(%s) Incorrect attrib %x - should be %x\n", \
+                      __location__, (unsigned int)finfo.basic_info.out.attrib,
+                       (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
+               ret = false;
+               goto done;
+       }
+
+       /* Now open the stream name. */
+
+       io.generic.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.flags = 0;
+       io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|
+           SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL|SEC_FILE_WRITE_ATTRIBUTE);
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.file_attr = 0;
+       io.ntcreatex.in.share_access = 0;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = fname_stream;
+
+       status = smb_raw_open(cli->tree, mem_ctx, &io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       fnum = io.ntcreatex.out.file.fnum;
+
+       /* Change the attributes + time on the stream fnum. */
+       ZERO_STRUCT(sfinfo);
+       sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY;
+       unix_to_nt_time(&sfinfo.basic_info.in.write_time, basetime);
+
+        sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFORMATION;
+        sfinfo.generic.in.file.fnum = fnum;
+        status = smb_raw_setfileinfo(cli->tree, &sfinfo);
+        if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) { 
+                printf("(%s) %s - %s (should be %s)\n", __location__, "SETATTR", 
+                        nt_errstr(status), nt_errstr(NT_STATUS_OK));
+                ret = false;
+               goto done;
+        }
+
+       smbcli_close(cli->tree, fnum);
+       fnum = -1;
+
+       ZERO_STRUCT(finfo);
+       finfo.generic.level = RAW_FILEINFO_ALL_INFO;
+       finfo.generic.in.file.path = fname;
+       status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("(%s) %s pathinfo - %s\n", __location__, "SETATTRE", nt_errstr(status));
+               ret = false;
+               goto done;
+       }
+
+       if (finfo.all_info.out.attrib != FILE_ATTRIBUTE_READONLY) {
+               printf("(%s) attrib incorrect. Was 0x%x, should be 0x%x\n",
+                       __location__,
+                       (unsigned int)finfo.all_info.out.attrib,
+                       (unsigned int)FILE_ATTRIBUTE_READONLY);
+               ret = false;
+               goto done;
+       }
+
+       if (nt_time_to_unix(finfo.all_info.out.write_time) != basetime) {
+               printf("(%s) time incorrect.\n",
+                       __location__);
+               ret = false;
+               goto done;
+       }
+
+ done:
+
+       if (fnum != -1) {
+               smbcli_close(cli->tree, fnum);
+       }
+       smbcli_unlink(cli->tree, fname);
+       return ret;
+}
+
 /* 
    basic testing of streams calls
 */
@@ -1566,6 +1681,10 @@ bool torture_raw_streams(struct torture_context *torture,
        smb_raw_exit(cli->session);
        ret &= test_stream_create_disposition(torture, cli, torture);
        smb_raw_exit(cli->session);
+
+       ret &= test_stream_attributes(torture, cli, torture);
+       smb_raw_exit(cli->session);
+
        /* ret &= test_stream_large_streaminfo(torture, cli, torture); */
 /*     smb_raw_exit(cli->session); */
 
index 2fd9d923f1e54671e749799c0de25f73b41569d6..10c4886259be251a5260ca98b15448637fa53a00 100644 (file)
@@ -306,7 +306,7 @@ static bool test_GetLogInformation(struct torture_context *tctx,
                                   struct dcerpc_pipe *p)
 {
        NTSTATUS status;
-       struct eventlog_GetLogIntormation r;
+       struct eventlog_GetLogInformation r;
        struct eventlog_CloseEventLog cr;
        struct policy_handle handle;
        uint32_t bytes_needed = 0;
@@ -320,14 +320,14 @@ static bool test_GetLogInformation(struct torture_context *tctx,
        r.out.buffer = NULL;
        r.out.bytes_needed = &bytes_needed;
 
-       status = dcerpc_eventlog_GetLogIntormation(p, tctx, &r);
+       status = dcerpc_eventlog_GetLogInformation(p, tctx, &r);
 
        torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_LEVEL,
                                      "GetLogInformation failed");
 
        r.in.level = 0;
 
-       status = dcerpc_eventlog_GetLogIntormation(p, tctx, &r);
+       status = dcerpc_eventlog_GetLogInformation(p, tctx, &r);
 
        torture_assert_ntstatus_equal(tctx, status, NT_STATUS_BUFFER_TOO_SMALL,
                                      "GetLogInformation failed");
@@ -335,7 +335,7 @@ static bool test_GetLogInformation(struct torture_context *tctx,
        r.in.buf_size = bytes_needed;
        r.out.buffer = talloc_array(tctx, uint8_t, bytes_needed);
 
-       status = dcerpc_eventlog_GetLogIntormation(p, tctx, &r);
+       status = dcerpc_eventlog_GetLogInformation(p, tctx, &r);
 
        torture_assert_ntstatus_ok(tctx, status, "GetLogInformation failed");
 
index de600e8fb3f0a531d8bc0ddc492e8b9e8e95b2f9..9d8bc4b186e517fe7b8ee03e673d8cd078eb6ae9 100644 (file)
@@ -168,6 +168,69 @@ static bool test_EnumPorts(struct torture_context *tctx,
        return true;
 }
 
+static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
+                                           struct dcerpc_pipe *p,
+                                           struct test_spoolss_context *ctx)
+{
+       NTSTATUS status;
+       struct spoolss_GetPrintProcessorDirectory r;
+       struct {
+               uint16_t level;
+               const char *server;
+       } levels[] = {{
+                       .level  = 1,
+                       .server = NULL
+               },{
+                       .level  = 1,
+                       .server = ""
+               },{
+                       .level  = 78,
+                       .server = ""
+               },{
+                       .level  = 1,
+                       .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
+               },{
+                       .level  = 1024,
+                       .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
+               }
+       };
+       int i;
+       uint32_t needed;
+
+       for (i=0;i<ARRAY_SIZE(levels);i++) {
+               int level = levels[i].level;
+               DATA_BLOB blob;
+
+               r.in.server             = levels[i].server;
+               r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
+               r.in.level              = level;
+               r.in.buffer             = NULL;
+               r.in.offered            = 0;
+               r.out.needed            = &needed;
+
+               torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
+
+               status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
+               torture_assert_ntstatus_ok(tctx, status,
+                       "dcerpc_spoolss_GetPrintProcessorDirectory failed");
+               torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
+                       "GetPrintProcessorDirectory unexpected return code");
+
+               blob = data_blob_talloc(ctx, NULL, needed);
+               data_blob_clear(&blob);
+               r.in.buffer = &blob;
+               r.in.offered = needed;
+
+               status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
+
+               torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
+       }
+
+       return true;
+}
+
+
 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx, 
                                           struct dcerpc_pipe *p, 
                                           struct test_spoolss_context *ctx)
@@ -679,7 +742,8 @@ static bool test_ClosePrinter(struct torture_context *tctx,
 static bool test_GetForm(struct torture_context *tctx, 
                         struct dcerpc_pipe *p, 
                         struct policy_handle *handle, 
-                        const char *form_name)
+                        const char *form_name,
+                        uint32_t level)
 {
        NTSTATUS status;
        struct spoolss_GetForm r;
@@ -687,12 +751,12 @@ static bool test_GetForm(struct torture_context *tctx,
 
        r.in.handle = handle;
        r.in.form_name = form_name;
-       r.in.level = 1;
+       r.in.level = level;
        r.in.buffer = NULL;
        r.in.offered = 0;
        r.out.needed = &needed;
 
-       torture_comment(tctx, "Testing GetForm\n");
+       torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
 
        status = dcerpc_spoolss_GetForm(p, tctx, &r);
        torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
@@ -724,45 +788,54 @@ static bool test_EnumForms(struct torture_context *tctx,
        bool ret = true;
        uint32_t needed;
        uint32_t count;
+       uint32_t levels[] = { 1, 2 };
+       int i;
 
-       r.in.handle = handle;
-       r.in.level = 1;
-       r.in.buffer = NULL;
-       r.in.offered = 0;
-       r.out.needed = &needed;
-       r.out.count = &count;
+       for (i=0; i<ARRAY_SIZE(levels); i++) {
+
+               r.in.handle = handle;
+               r.in.level = levels[i];
+               r.in.buffer = NULL;
+               r.in.offered = 0;
+               r.out.needed = &needed;
+               r.out.count = &count;
 
-       torture_comment(tctx, "Testing EnumForms\n");
+               torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
 
-       status = dcerpc_spoolss_EnumForms(p, tctx, &r);
-       torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
+               status = dcerpc_spoolss_EnumForms(p, tctx, &r);
+               torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
 
-       if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
-               torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
+               if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
+                       break;
+               }
 
-       if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
-               union spoolss_FormInfo *info;
-               int j;
-               DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
-               data_blob_clear(&blob);
-               r.in.buffer = &blob;
-               r.in.offered = needed;
+               if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
+                       torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
 
-               status = dcerpc_spoolss_EnumForms(p, tctx, &r);
+               if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
+                       union spoolss_FormInfo *info;
+                       int j;
+                       DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
+                       data_blob_clear(&blob);
+                       r.in.buffer = &blob;
+                       r.in.offered = needed;
 
-               torture_assert(tctx, r.out.info, "No forms returned");
+                       status = dcerpc_spoolss_EnumForms(p, tctx, &r);
 
-               info = r.out.info;
+                       torture_assert(tctx, r.out.info, "No forms returned");
 
-               for (j = 0; j < count; j++) {
-                       if (!print_server) 
-                               ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name);
+                       info = r.out.info;
+
+                       for (j = 0; j < count; j++) {
+                               if (!print_server)
+                                       ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
+                       }
                }
-       }
 
-       torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
+               torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
 
-       torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
+               torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
+       }
 
        return true;
 }
@@ -815,7 +888,7 @@ static bool test_AddForm(struct torture_context *tctx,
 
        torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
 
-       if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name);
+       if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
 
        {
                struct spoolss_SetForm sf;
@@ -839,7 +912,7 @@ static bool test_AddForm(struct torture_context *tctx,
                torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
        }
 
-       if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name);
+       if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
 
        if (!test_DeleteForm(tctx, p, handle, form_name)) {
                ret = false;
@@ -972,6 +1045,33 @@ static bool test_SetJob(struct torture_context *tctx,
        return true;
 }
 
+static bool test_AddJob(struct torture_context *tctx,
+                       struct dcerpc_pipe *p,
+                       struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct spoolss_AddJob r;
+       uint32_t needed;
+
+       r.in.level = 0;
+       r.in.handle = handle;
+       r.in.offered = 0;
+       r.out.needed = &needed;
+
+       torture_comment(tctx, "Testing AddJob\n");
+
+       status = dcerpc_spoolss_AddJob(p, tctx, &r);
+       torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
+
+       r.in.level = 1;
+
+       status = dcerpc_spoolss_AddJob(p, tctx, &r);
+       torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
+
+       return true;
+}
+
+
 static bool test_EnumJobs(struct torture_context *tctx, 
                          struct dcerpc_pipe *p, 
                          struct policy_handle *handle)
@@ -1011,6 +1111,7 @@ static bool test_EnumJobs(struct torture_context *tctx,
                info = r.out.info;
 
                for (j = 0; j < count; j++) {
+
                        test_GetJob(tctx, p, handle, info[j].info1.job_id);
                        test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
                        test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
@@ -1090,6 +1191,7 @@ static bool test_DoPrintTest(struct torture_context *tctx,
        torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
        torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
 
+       ret &= test_AddJob(tctx, p, handle);
        ret &= test_EnumJobs(tctx, p, handle);
 
        ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
@@ -1831,6 +1933,7 @@ bool torture_rpc_spoolss(struct torture_context *torture)
        ret &= test_AddForm(torture, p, &ctx->server_handle, true);
        ret &= test_EnumPorts(torture, p, ctx);
        ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
+       ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
        ret &= test_EnumPrinterDrivers(torture, p, ctx);
        ret &= test_EnumMonitors(torture, p, ctx);
        ret &= test_EnumPrintProcessors(torture, p, ctx);
index ba5296fd97d9ed46a9dc0b5c60a952fea5d6adf1..d934403ade2105e23ca5c82030f52c87f5203e15 100644 (file)
@@ -107,7 +107,7 @@ static const struct net_functable net_functable[] = {
        {"vampire", "join and syncronise an AD domain onto the local server\n", net_vampire, net_vampire_usage},
        {"samsync", "synchronise into the local ldb the sam of an NT4 domain\n", net_samsync_ldb, net_samsync_ldb_usage},
        {"user", "manage user accounts\n", net_user, net_user_usage},
-       {"machinepw", "Get a machine password out of our SAM", net_machinepw,
+       {"machinepw", "Get a machine password out of our SAM\n", net_machinepw,
         net_machinepw_usage},
        {NULL, NULL, NULL, NULL}
 };
index ad63340089907b550122218fdd5bb8e2ef440113..b0a25bb7c067ae6d28e4ce0b45890fce069d7f6d 100644 (file)
@@ -126,7 +126,7 @@ int net_vampire(struct net_context *ctx, int argc, const char **argv)
 
        domain_name = tmp;
 
-       libnetctx = libnet_context_init(NULL, ctx->lp_ctx);
+       libnetctx = libnet_context_init(ctx->event_ctx, ctx->lp_ctx);
        if (!libnetctx) {
                return -1;      
        }