Browse Source

Add new NT4 LDAP Service, used by windows sync

David Boreham 20 years ago
parent
commit
951b86ef83

+ 73 - 0
ldap/servers/ntds/Makefile

@@ -0,0 +1,73 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# 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; version 2 of the License.
+# 
+# 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., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+# 
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception. 
+# 
+# 
+# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+# GNU Makefile for ldap/servers
+#
+
+BUILD_ROOT = ../../..
+LDAP_SRC = $(BUILD_ROOT)/ldap
+
+NOSTDCLEAN=true # don't let nsconfig.mk define target clean
+NOSTDSTRIP=true # don't let nsconfig.mk define target strip
+
+include $(BUILD_ROOT)/nsdefs.mk
+include $(BUILD_ROOT)/nsconfig.mk
+include $(LDAP_SRC)/nsldap.mk
+
+ifeq ($(BUILD_NTDS),1)
+all:	_netman _apacheds _wrapper
+else
+all:
+	echo set BUILD_NTDS=1 to build NTDS
+endif
+
+_netman:
+	cd netman; $(MAKE) $(MFLAGS) all	
+
+_apacheds:
+	cd apacheds; $(MAKE) $(MFLAGS) all	
+
+_wrapper:
+	cd wrapper; $(MAKE) $(MFLAGS) all	
+
+
+clean:
+	cd netman; $(MAKE) $(MFLAGS) clean
+	cd apacheds; $(MAKE) $(MFLAGS) clean
+	cd wrapper; $(MAKE) $(MFLAGS) clean

+ 81 - 0
ldap/servers/ntds/apacheds/Makefile

@@ -0,0 +1,81 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# 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; version 2 of the License.
+# 
+# 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., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+# 
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception. 
+# 
+# 
+# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+# 
+LDAP_SRC = ../../..
+BUILD_ROOT = ../../../..
+
+OBJDEST = $(OBJDIR)/lib/netman
+LIBDIR = $(LIB_RELDIR)
+
+NOSTDCLEAN=true # don't let nsconfig.mk define target clean
+NOSTDSTRIP=true # don't let nsconfig.mk define target strip
+include $(BUILD_ROOT)/nsconfig.mk
+include $(LDAP_SRC)/nsldap.mk
+include $(LDAP_SRC)/javarules.mk
+
+export JAVA_HOME=$(JDKPRELIB)/../
+export MAVEN_HOME
+
+USERSYNCJAR=$(JAVA_DEST_DIR)/ntds/usersync.jar
+all: $(USERSYNCJAR)
+
+#no banner on maven
+MAVEN_OPTS=-b 
+
+ifeq ($(BUILD_NTDS_OFFLINE),1)
+MAVEN_OPTS+=-o
+endif
+
+export CLASSPATH=$(APACHEDS_FILE);$(JAVA_DEST_DIR)/ntds/jnetman.jar 
+
+$(APACHEDSSOURCE)/core/target: $(JAVA_DEST_DIR)/ntds/jnetman.jar
+	$(CP) project.properties $(APACHEDSSOURCE)/core 
+	$(CP) usersync.schema $(APACHEDSSOURCE)/core/src/main/schema
+	$(MAVEN_EXE) $(MAVEN_OPTS) -d $(APACHEDSSOURCE)/core -e directory:schema 
+	$(JAVAC) -classpath $(APACHEDS_FILE) $(APACHEDSSOURCE)/core/target/schema/org/apache/ldap/server/schema/bootstrap/*.java
+	$(JAVAC) -d $(APACHEDSSOURCE)/core/target/schema/ org/apache/ldap/server/*.java
+	$(RM) $(APACHEDSSOURCE)/core/target/schema/org/apache/ldap/server/schema/bootstrap/*.java
+
+$(USERSYNCJAR): $(APACHEDSSOURCE)/core/target 
+	( cd  $(APACHEDSSOURCE)/core/target/schema && pwd && jar cf  usersync.jar org)
+	$(MV) $(APACHEDSSOURCE)/core/target/schema/usersync.jar $(USERSYNCJAR) 
+
+clean:
+	$(RM) $(APACHEDSSOURCE)/core/target
+	$(RM) $(USERSYNCJAR) 

+ 1561 - 0
ldap/servers/ntds/apacheds/org/apache/ldap/server/NetAPIPartition.java

@@ -0,0 +1,1561 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * 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; version 2 of the License.
+ * 
+ * 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., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ * 
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception. 
+ * 
+ * 
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
+/*
+ * NetAPIPartition.java
+ *
+ * Created on February 22, 2005, 9:34 AM
+ */
+package org.apache.ldap.server;
+
+import java.util.Map;
+//import java.util.Collection;
+import java.util.Date;
+import java.util.Properties;
+import java.io.File;
+import java.io.FileWriter;
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+
+import org.apache.ldap.common.name.LdapName;
+//import org.apache.ldap.common.util.PropertiesUtils;
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.server.ContextPartition;
+//import org.apache.ldap.common.message.Control;
+import org.apache.ldap.common.filter.PresenceNode;
+
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.SearchResult;
+import javax.naming.directory.DirContext;
+import java.util.StringTokenizer;
+import java.util.HashSet;
+import org.bpi.jnetman.*;
+
+/**
+ *
+ * @author scott
+ */
+public class NetAPIPartition implements ContextPartition {
+
+    static {
+        System.loadLibrary("jnetman");
+        System.out.println("dll loaded");
+    }
+	
+    //private LdapName suffix;
+    private String suffix;
+    private static final String container = new String("cn=users").toLowerCase();
+    private static final String logFilename = new String("../logs/usersync.log");
+    private static final int GLOBAL_FLAG = 0x00000002;
+    private static final int DOMAINLOCAL_FLAG = 0x00000004;
+    private FileWriter outLog;
+    
+    /** Creates a new instance of NetAPIPartition */
+    public NetAPIPartition(Name upSuffix, Name normSuffix, String properties) {
+        try {
+        	outLog = new FileWriter(new File(logFilename));
+        }
+        catch(Exception e) {
+        }
+        
+        try {
+        	outLog.write(new Date() + ": reached NetAPIPartition");
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition");
+        suffix = normSuffix.toString();
+    }
+
+    /**
+     * Deletes a leaf entry from this BackingStore: non-leaf entries cannot be 
+     * deleted until this operation has been applied to their children.
+     *
+     * @param name the normalized distinguished/absolute name of the entry to
+     * delete from this BackingStore.
+     * @throws NamingException if there are any problems
+     */ 
+    public void delete( Name name ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.delete: " + name);
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.delete: " + name);
+        
+        String rdn = getRDN(name.toString());
+        boolean deletedSomthing = false;
+        NTUser user = new NTUser();
+        NTGroup group = new NTGroup();
+        NTLocalGroup localGroup = new NTLocalGroup();
+        
+        if(name.toString().toLowerCase().startsWith(new String("sAMAccountName").toLowerCase())) {
+        	if(user.RetriveUserByAccountName(rdn) == 0) {
+        		if(user.DeleteUser(user.GetAccountName()) == 0) {
+        			deletedSomthing = true;
+        		}
+        	}
+        	if(group.RetriveGroupByAccountName(rdn) == 0) {
+        		if(group.DeleteGroup(group.GetAccountName()) == 0) {
+        			deletedSomthing = true;
+        		}
+        	}
+        	if(localGroup.RetriveLocalGroupByAccountName(rdn) == 0) {
+        		if(localGroup.DeleteLocalGroup(localGroup.GetAccountName()) == 0) {
+        			deletedSomthing = true;
+        		}
+        	}
+        }
+        else if((name.toString().toLowerCase().startsWith(new String("objectGUID").toLowerCase())) ||
+        		(name.toString().toLowerCase().startsWith(new String("GUID").toLowerCase()))) {
+        	
+        	if(user.RetriveUserBySIDHexStr(rdn) == 0) {
+        		if(user.DeleteUser(user.GetAccountName()) == 0) {
+        			deletedSomthing = true;
+        		}
+        	}
+        	if(group.RetriveGroupBySIDHexStr(rdn) == 0) {
+        		if(group.DeleteGroup(group.GetAccountName()) == 0) {
+        			deletedSomthing = true;
+        		}
+        	}
+        	if(localGroup.RetriveLocalGroupBySIDHexStr(rdn) == 0) {
+        		if(localGroup.DeleteLocalGroup(localGroup.GetAccountName()) == 0) {
+        			deletedSomthing = true;
+        		}
+        	}
+        }
+        else {
+        	throw new NamingException("Can not delete DN: " + name);
+        }
+        
+        if(!deletedSomthing) {
+            throw new NamingException("No matching users or groups: " + rdn);
+        }
+    }
+
+    /**
+     * Adds an entry to this BackingStore.
+     *
+     * @param upName the user provided distinguished/absolute name of the entry
+     * @param normName the normalized distinguished/absolute name of the entry
+     * @param entry the entry to add to this BackingStore
+     * @throws NamingException if there are any problems
+     */
+    public void add( String upName, Name normName, Attributes entry ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.add: " + normName);
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.add: " + normName);
+        
+        String rdn = getRDN(normName.toString());
+        Attribute attribute = entry.get("objectClass");
+        Attribute groupType;
+        ModificationItem[] modItems = new ModificationItem[entry.size()];
+        NamingEnumeration modAttributes = entry.getAll();
+        NTUser user = new NTUser();
+        NTGroup group = new NTGroup();
+        NTLocalGroup localGroup = new NTLocalGroup();
+        int result;
+
+        for(int i = 0; i < entry.size(); i++) {
+        	modItems[i] = new ModificationItem(DirContext.ADD_ATTRIBUTE, (Attribute)modAttributes.next());
+        }
+
+        if(normName.toString().compareToIgnoreCase(suffix) == 0) {
+        	// Gets us past the CoreContestFactory.startUpAppPartitions
+        }
+        else if((normName.toString().toLowerCase().endsWith(container + "," + suffix)) &&
+        		(normName.toString().toLowerCase().startsWith(new String("sAMAccountName").toLowerCase()))) {
+        	
+            if(attribute.contains("user")) {
+                user.NewUser(rdn);
+                modNTUserAttributes(user, modItems);
+                result = user.AddUser();
+                if(result != 0) {
+                	throw new NamingException("Failed to add new user: " + normName + " (" + result + ")");
+                }
+            }
+            else if(attribute.contains("group")) {
+            	attribute = entry.get("groupType");
+            	if(((new Integer((String)attribute.get())).intValue() & GLOBAL_FLAG) == GLOBAL_FLAG) {
+            		group.NewGroup(rdn);
+                    modNTGroupAttributes(group, modItems);
+                    if(group.AddGroup() != 0) {
+                    	throw new NamingException("Failed to add new group: " + normName);
+                    }
+            	}
+            	else if(((new Integer((String)attribute.get())).intValue() & DOMAINLOCAL_FLAG) == DOMAINLOCAL_FLAG) {
+                    localGroup.NewLocalGroup(rdn);
+                    modNTLocalGroupAttributes(localGroup, modItems);
+                    if(localGroup.AddLocalGroup() != 0) {
+                    	throw new NamingException("Failed add new local group: " + normName);
+                    }
+            	}
+            	else {
+            		throw new NamingException("Unknown group type: " + (Integer)attribute.get());
+            	}
+            }
+            else {
+                throw new NamingException("No matching objectClass");
+            }
+        }
+        else {
+            throw new NamingException("Attempt to add an entry outside partition scope: " + normName);
+        }
+    }
+
+    /**
+     * Modifies an entry by adding, removing or replacing a set of attributes.
+     *
+     * @param name the normalized distinguished/absolute name of the entry to
+     * modify
+     * @param modOp the modification operation to perform on the entry which
+     * is one of constants specified by the DirContext interface:
+     * <code>ADD_ATTRIBUTE, REMOVE_ATTRIBUTE, REPLACE_ATTRIBUTE</code>.
+     * @param mods the attributes and their values used to affect the
+     * modification with.
+     * @throws NamingException if there are any problems
+     * @see javax.naming.directory.DirContext
+     * @see javax.naming.directory.DirContext.ADD_ATTRIBUTE
+     * @see javax.naming.directory.DirContext.REMOVE_ATTRIBUTE
+     * @see javax.naming.directory.DirContext.REPLACE_ATTRIBUTE
+     */
+    public void modify( Name name, int modOp, Attributes mods ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.modify1: " + name);
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.modify1: " + name);
+        
+        ModificationItem[] modItems = new ModificationItem[mods.size()];
+        NamingEnumeration modAttributes = mods.getAll();
+
+        for(int i = 0; i < mods.size(); i++) {
+        	modItems[i] = new ModificationItem(modOp, (Attribute)modAttributes.next());
+        }
+        
+        modify(name, modItems);
+    }
+
+    /**
+     * Modifies an entry by using a combination of adds, removes or replace 
+     * operations using a set of ModificationItems.
+     *
+     * @param name the normalized distinguished/absolute name of the entry to modify
+     * @param mods the ModificationItems used to affect the modification with
+     * @throws NamingException if there are any problems
+     * @see ModificationItem
+     */
+    public void modify( Name name, ModificationItem [] mods ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.modify2: " + name);
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.modify2: " + name);
+
+        String rdn = getRDN(name.toString());
+        boolean modifiedSomething = false;
+        NTUser user = new NTUser();
+        NTGroup group = new NTGroup();
+        NTLocalGroup localGroup = new NTLocalGroup();
+
+        if(name.toString().toLowerCase().startsWith(new String("sAMAccountName").toLowerCase())) {
+            if(user.RetriveUserByAccountName(rdn) == 0) {
+                modNTUserAttributes(user, mods);
+                if(user.StoreUser() != 0) {
+                	throw new NamingException("Failed to commit modified user information: " + name);
+                }
+                
+                modifiedSomething = true;
+            }
+            else if(group.RetriveGroupByAccountName(rdn) == 0) {
+                modNTGroupAttributes(group, mods);
+                if(group.StoreGroup() != 0) {
+                	throw new NamingException("Failed to commit modified group information: " + name);
+                }
+                
+                modifiedSomething = true;
+            }
+            else if(localGroup.RetriveLocalGroupByAccountName(rdn) == 0) {
+                modNTLocalGroupAttributes(localGroup, mods);
+                if(localGroup.StoreLocalGroup() != 0) {
+                	throw new NamingException("Failed to commit modified local group information: " + name);
+                }
+                
+                modifiedSomething = true;
+            }
+        }
+        else if((name.toString().toLowerCase().startsWith(new String("objectGUID").toLowerCase())) ||
+        		(name.toString().toLowerCase().startsWith(new String("GUID").toLowerCase()))) {
+        	
+        	if(user.RetriveUserBySIDHexStr(rdn) == 0) {
+                modNTUserAttributes(user, mods);
+                if(user.StoreUser() != 0) {
+                	throw new NamingException("Failed to commit modified user information: " + name);
+                }
+                
+                modifiedSomething = true;
+            }
+            else if(group.RetriveGroupBySIDHexStr(rdn) == 0) {
+                modNTGroupAttributes(group, mods);
+                if(group.StoreGroup() != 0) {
+                	throw new NamingException("Failed to commit modified group information: " + name);
+                }
+                
+                modifiedSomething = true;
+            }
+            else if(localGroup.RetriveLocalGroupBySIDHexStr(rdn) == 0) {
+                modNTLocalGroupAttributes(localGroup, mods);
+                if(localGroup.StoreLocalGroup() != 0) {
+                	throw new NamingException("Failed to commit modified local group information: " + name);
+                }
+                
+                modifiedSomething = true;
+            }
+        }
+        else {
+            throw new NamingException("Can not delete DN: " + name);
+        }
+        
+        if(!modifiedSomething) {
+            throw new NamingException("No matching users or groups: " + rdn);
+        }
+    }
+
+    /**
+     * A specialized form of one level search used to return a minimal set of 
+     * information regarding child entries under a base.  Convenience method
+     * used to optimize operations rather than conducting a full search with 
+     * retrieval.
+     *
+     * @param base the base distinguished/absolute name for the search/listing
+     * @return a NamingEnumeration containing objects of type
+     * {@link org.apache.ldap.server.db.DbSearchResult}
+     * @throws NamingException if there are any problems
+     */
+    public NamingEnumeration list( Name base ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.list");
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.list");
+
+        return new BasicAttribute(base.toString()).getAll();
+    }
+    
+    /**
+     * Conducts a search against this BackingStore.  Namespace specific
+     * parameters for search are contained within the environment using
+     * namespace specific keys into the hash.  For example in the LDAP namespace
+     * a BackingStore implementation may look for search Controls using a
+     * namespace specific or implementation specific key for the set of LDAP
+     * Controls.
+     *
+     * @param base the normalized distinguished/absolute name of the search base
+     * @param env the environment under which operation occurs
+     * @param filter the root node of the filter expression tree
+     * @param searchCtls the search controls
+     * @throws NamingException if there are any problems
+     * @return a NamingEnumeration containing objects of type 
+     * <a href="http://java.sun.com/j2se/1.4.2/docs/api/
+     * javax/naming/directory/SearchResult.html">SearchResult</a>.
+     */
+    public NamingEnumeration search( Name base, Map env, ExprNode filter,
+        SearchControls searchCtls ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.search: " + base);
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.search: " + base + " " + filter);
+        
+        BasicAttribute results = new BasicAttribute(null);
+        SearchResult result;
+        BasicAttributes attributes;
+        BasicAttribute attribute;
+        String rdn = getRDN(base.toString());
+        NTUser user = new NTUser();
+        NTGroup group = new NTGroup();
+        NTLocalGroup localGroup = new NTLocalGroup();
+        
+        // base equals suffix
+        if(base.toString().compareToIgnoreCase(suffix) == 0) {
+        	// object scope
+        	if(((searchCtls.getSearchScope() == SearchControls.OBJECT_SCOPE) ||
+        			(searchCtls.getSearchScope() == SearchControls.SUBTREE_SCOPE)) &&
+        			(filter.toString().toLowerCase().startsWith(new String("(objectClass=*)").toLowerCase()))) {
+        		
+                attributes = new BasicAttributes();
+
+                attribute = new BasicAttribute("objectClass");
+                attribute.add("top");
+                attribute.add("domain");
+                attributes.put(attribute);
+
+                result = new SearchResult(suffix, null, attributes);
+                results.add(result);
+        	}
+        	
+        	// one level or subtree scope
+        	if(((searchCtls.getSearchScope() == SearchControls.ONELEVEL_SCOPE) ||
+					(searchCtls.getSearchScope() == SearchControls.SUBTREE_SCOPE)) &&
+        			(filter.toString().toLowerCase().startsWith(new String("(objectClass=*)").toLowerCase()))) {
+                
+                result = new SearchResult(container + "," + suffix, null, new BasicAttributes());
+                results.add(result);
+        	}
+        	
+        	// subtree scope
+        	if(searchCtls.getSearchScope() == SearchControls.SUBTREE_SCOPE) {
+        		searchAccounts(base, env, filter, searchCtls, results);
+        	}
+        }
+        // base equals container plus suffix 
+        else if(base.toString().compareToIgnoreCase(container + "," + suffix) == 0) {
+        	// object scope
+        	if(((searchCtls.getSearchScope() == SearchControls.OBJECT_SCOPE) ||
+					(searchCtls.getSearchScope() == SearchControls.SUBTREE_SCOPE)) &&
+        			(filter.toString().toLowerCase().startsWith(new String("(objectClass=*)").toLowerCase()))) {
+        		
+        		attributes = new BasicAttributes();
+
+                attribute = new BasicAttribute("objectClass");
+                attribute.add("top");
+                attribute.add("domain");
+                attributes.put(attribute);
+
+                result = new SearchResult(container + "," + suffix, null, attributes);
+                results.add(result);
+        	}
+        	
+        	// one level or subtree scope
+        	if((searchCtls.getSearchScope() == SearchControls.ONELEVEL_SCOPE) ||
+					(searchCtls.getSearchScope() == SearchControls.SUBTREE_SCOPE)) {
+        		
+        		searchAccounts(base, env, filter, searchCtls, results);
+        	}
+        	
+        	// subtree scope
+        	if(searchCtls.getSearchScope() == SearchControls.SUBTREE_SCOPE) {
+        		// Nothing that OVELEVEL_SCOPE || SUBTREE_SCOPE doesn't already cover
+        	}
+        }
+        // base ends with container plus suffix
+        else if(base.toString().toLowerCase().endsWith(new String(container + "," + suffix).toLowerCase())) {
+        	// object scope
+        	if((searchCtls.getSearchScope() == SearchControls.OBJECT_SCOPE) ||
+					(searchCtls.getSearchScope() == SearchControls.SUBTREE_SCOPE)) {
+        		
+        		searchAccounts(base, env, filter, searchCtls, results);
+        	}
+        	
+        	// one level or subtree scope
+        	if((searchCtls.getSearchScope() == SearchControls.ONELEVEL_SCOPE) ||
+					(searchCtls.getSearchScope() == SearchControls.SUBTREE_SCOPE)) {
+        		// Empty set
+        	}
+        	
+        	// subtree scope
+        	if(searchCtls.getSearchScope() == SearchControls.SUBTREE_SCOPE) {
+        		// Nothing that OBJECT_SCOPE || SUBTREE_SCOPE doesn't already cover
+        	}
+        }
+        // unknown base
+        else {
+        	throw new NamingException("Attempt to search for an entry outside partition scope: " + base);
+        }
+        
+        return results.getAll();
+    }
+
+    /**
+     * Looks up an entry by distinguished/absolute name.  This is a simplified
+     * version of the search operation used to point read an entry used for
+     * convenience.
+     *
+     * @param name the normalized distinguished name of the object to lookup
+     * @return an Attributes object representing the entry
+     * @throws NamingException if there are any problems
+     */
+    public Attributes lookup( Name name ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.lookup1: " + name);
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.lookup1: " + name);
+        
+        BasicAttributes attributes = null;
+        BasicAttribute attribute;
+        String rdn = getRDN(name.toString());
+        NTUser user = new NTUser();
+        NTGroup group = new NTGroup();
+        NTLocalGroup localGroup = new NTLocalGroup();
+        
+        if(name.toString().compareToIgnoreCase(suffix) == 0) {
+            attributes = new BasicAttributes();
+
+            attribute = new BasicAttribute("objectClass");
+            attribute.add("top");
+            attribute.add("domain");
+            attributes.put(attribute);
+        }
+        else if(name.toString().compareToIgnoreCase(container + "," + suffix) == 0) {
+            attributes = new BasicAttributes();
+
+            attribute = new BasicAttribute("objectClass");
+            attribute.add("top");
+            attribute.add("domain");
+            attributes.put(attribute);
+        }
+        else if(name.toString().toLowerCase().endsWith(container + "," + suffix)) {
+	        if(user.RetriveUserByAccountName(rdn) == 0) {
+	            attributes = getNTUserAttributes(user, rdn);
+	        }
+	        else if(group.RetriveGroupByAccountName(rdn) == 0) {
+	            attributes = getNTGroupAttributes(group, rdn);
+	        }
+	        else if(localGroup.RetriveLocalGroupByAccountName(rdn) == 0) {
+	            attributes = getNTLocalGroupAttributes(localGroup, rdn);
+	        }
+        }
+        else {
+            throw new NamingException("Attempt to look up an entry outside partition scope: " + name);
+        }
+        
+        return attributes;
+    }
+
+    /**
+     * Looks up an entry by distinguished name.  This is a simplified version
+     * of the search operation used to point read an entry used for convenience
+     * with a set of attributes to return.  If the attributes are null or emty
+     * this defaults to the lookup opertion without the attributes.
+     *
+     * @param dn the normalized distinguished name of the object to lookup
+     * @param attrIds the set of attributes to return
+     * @return an Attributes object representing the entry
+     * @throws NamingException if there are any problems
+     */
+    public Attributes lookup( Name dn, String [] attrIds ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.lookup2: " + dn);
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.lookup2: " + dn);
+        
+        return lookup(dn);
+    }
+
+    /**
+     * Fast operation to check and see if a particular entry exists.
+     *
+     * @param name the normalized distinguished/absolute name of the object to
+     * check for existance
+     * @return true if the entry exists, false if it does not
+     * @throws NamingException if there are any problems
+     */
+    public boolean hasEntry( Name name ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.hasEntry: " + name);
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.hasEntry: " + name);
+
+        boolean result = false;
+        String rdn = getRDN(name.toString());
+        NTUser user = new NTUser();
+        NTGroup group = new NTGroup();
+        NTLocalGroup localGroup = new NTLocalGroup();
+
+        if(name.toString().compareToIgnoreCase(suffix) == 0) {
+            result = true;
+        }
+        else if(name.toString().compareToIgnoreCase(container + "," + suffix) == 0) {
+            result = true;
+        }
+        
+        // Ae exception raised in searchAccounts is treated as a false hasEntry result
+        try {
+        	if(searchAccounts(name, new Properties(), new PresenceNode(null), new SearchControls(), new BasicAttribute(null)) > 0) {
+            	result = true;
+        	}
+        }
+        catch(Exception e) {
+        }
+
+        return result;
+    }
+
+    /**
+     * Checks to see if name is a context suffix.
+     *
+     * @param name the normalized distinguished/absolute name of the context
+     * @return true if the name is a context suffix, false if it is not.
+     * @throws NamingException if there are any problems
+     */
+    public boolean isSuffix( Name name ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.isSuffix");
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.isSuffix");
+
+        return false;
+    }
+
+    /**
+     * Modifies an entry by changing its relative name. Optionally attributes
+     * associated with the old relative name can be removed from the entry.
+     * This makes sense only in certain namespaces like LDAP and will be ignored
+     * if it is irrelavent.
+     *
+     * @param name the normalized distinguished/absolute name of the entry to
+     * modify the RN of.
+     * @param newRn the new RN of the entry specified by name
+     * @param deleteOldRn boolean flag which removes the old RN attribute
+     * from the entry if set to true, and has no affect if set to false
+     * @throws NamingException if there are any problems
+     */
+    public void modifyRn( Name name, String newRn, boolean deleteOldRn )
+        throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.modifyRn");
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.modifyRn");
+
+    }
+
+    /**
+     * Transplants a child entry, to a position in the namespace under a new
+     * parent entry.
+     *
+     * @param newParentName the normalized distinguished/absolute name of the
+     * new parent to move the target entry to
+     * @param oriChildName the normalized distinguished/absolute name of the
+     * original child name representing the child entry to move
+     * @throws NamingException if there are any problems
+     */
+    public void move( Name oriChildName, Name newParentName ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.move1");
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.move1");
+
+    }
+
+    /**
+     * Transplants a child entry, to a position in the namespace under a new
+     * parent entry and changes the RN of the child entry which can optionally
+     * have its old RN attributes removed.  The removal of old RN attributes
+     * may not make sense in all namespaces.  If the concept is undefined in a
+     * namespace this parameters is ignored.  An example of a namespace where
+     * this parameter is significant is the LDAP namespace.
+     *
+     * @param oriChildName the normalized distinguished/absolute name of the
+     * original child name representing the child entry to move
+     * @param newParentName the normalized distinguished/absolute name of the
+     * new parent to move the targeted entry to
+     * @param newRn the new RN of the entry
+     * @param deleteOldRn boolean flag which removes the old RN attribute
+     * from the entry if set to true, and has no affect if set to false
+     * @throws NamingException if there are any problems
+     */
+    public void move( Name oriChildName, Name newParentName, String newRn,
+               boolean deleteOldRn ) throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.move2");
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.move2");
+
+    }
+
+    /**
+     * Cue to BackingStores with caches to flush entry and index changes to disk.
+     *
+     * @throws NamingException if there are problems flushing caches
+     */
+    public void sync() throws NamingException {
+    }
+
+    /**
+     * Closes or shuts down this BackingStore.  Operations against closed
+     * BackingStores will fail.
+     *
+     * @throws NamingException if there are problems shutting down
+     */
+    public void close() throws NamingException {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.close");
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.close");
+
+    }
+
+    /**
+     * Checks to see if this BackingStore has been closed or shut down.
+     * Operations against closed BackingStores will fail.
+     *
+     * @return true if shut down, false otherwise
+     */
+    public boolean isClosed() {
+    	try {
+        	outLog.write(new Date() + ": reached NetAPIPartition.isClosed");
+        	outLog.flush();
+        }
+        catch(Exception e) {
+        }
+        System.out.println("reached NetAPIPartition.isClosed");
+
+        return true;
+    }
+    
+    /**
+     * Gets the distinguished/absolute name of the suffix for all entries
+     * stored within this BackingStore.
+     *
+     * @param normalized boolean value used to control the normalization of the
+     * returned Name.  If true the normalized Name is returned, otherwise the 
+     * original user provided Name without normalization is returned.
+     * @return Name representing the distinguished/absolute name of this
+     * BackingStores root context.
+     */
+    public Name getSuffix( boolean normalized ) {
+    	LdapName name = null; 
+    	
+    	try {
+    		name = new LdapName(suffix);
+    	}
+    	catch(NamingException ne) {
+    	}
+    	
+    	return name;
+    }
+    
+    private String getRDN(String dn) {
+        StringTokenizer tokenizer;
+        String rdn;
+
+        tokenizer = new StringTokenizer(dn, "(),=<>");
+        rdn = tokenizer.nextToken();
+        rdn = tokenizer.nextToken();
+        
+        return rdn;
+    }
+    
+    private int searchAccounts(Name base, Map env, ExprNode filter,
+            SearchControls searchCtls, BasicAttribute results) throws NamingException {
+    	
+    	int resultCount = 0;
+    	SearchResult result;
+    	BasicAttributes attributes;
+        String rdn = getRDN(base.toString());
+
+        NTUser user = new NTUser();
+        NTGroup group = new NTGroup();
+        NTLocalGroup localGroup = new NTLocalGroup();
+        
+        if(base.toString().toLowerCase().startsWith(new String("sAMAccountName").toLowerCase())) {
+        	if(user.RetriveUserByAccountName(rdn) == 0) {
+        		attributes = new BasicAttributes();
+	            
+	            attributes = getNTUserAttributes(user, rdn);
+	            result = new SearchResult("sAMAccountName=" + user.GetAccountName() + "," + container + "," + suffix, null, attributes);
+	            results.add(result);
+	            resultCount++;
+        	}
+        	else if(group.RetriveGroupByAccountName(rdn) == 0) {
+        		attributes = new BasicAttributes();
+	            
+	            attributes = getNTGroupAttributes(group, rdn);
+	            result = new SearchResult("sAMAccountName=" + group.GetAccountName() + "," + container + "," + suffix, null, attributes);
+	            results.add(result);
+	            resultCount++;
+        	}
+        	else if(localGroup.RetriveLocalGroupByAccountName(rdn) == 0) {
+        		attributes = new BasicAttributes();
+	            
+	            attributes = getNTLocalGroupAttributes(localGroup, rdn);
+	            result = new SearchResult("sAMAccountName=" + localGroup.GetAccountName() + "," + container + "," + suffix, null, attributes);
+	            results.add(result);
+	            resultCount++;
+        	}
+        	else {
+        		// empty set
+        	}
+        }
+        else if((base.toString().toLowerCase().startsWith(new String("objectGUID").toLowerCase())) ||
+        		(base.toString().toLowerCase().startsWith(new String("GUID").toLowerCase()))) {
+        	if(user.RetriveUserBySIDHexStr(rdn) == 0) {
+        		attributes = new BasicAttributes();
+	            
+	            attributes = getNTUserAttributes(user, rdn);
+	            result = new SearchResult("sAMAccountName=" + user.GetAccountName() + "," + container + "," + suffix, null, attributes);
+	            results.add(result);
+	            resultCount++;
+        	}
+        	else if(group.RetriveGroupBySIDHexStr(rdn) == 0) {
+        		attributes = new BasicAttributes();
+	            
+	            attributes = getNTGroupAttributes(group, rdn);
+	            result = new SearchResult("sAMAccountName=" + group.GetAccountName() + "," + container + "," + suffix, null, attributes);
+	            results.add(result);
+	            resultCount++;
+        	}
+        	else if(localGroup.RetriveLocalGroupBySIDHexStr(rdn) == 0) {
+        		attributes = new BasicAttributes();
+	            
+	            attributes = getNTLocalGroupAttributes(localGroup, rdn);
+	            result = new SearchResult("sAMAccountName=" + localGroup.GetAccountName() + "," + container + "," + suffix, null, attributes);
+	            results.add(result);
+	            resultCount++;
+        	}
+        	else {
+        		// empty set
+        	}
+        }
+        else if((base.toString().compareToIgnoreCase(suffix) == 0) ||
+        		base.toString().compareToIgnoreCase(container + "," + suffix) == 0) {
+        	if(filter.toString().toLowerCase().startsWith(new String("(sAMAccountName=").toLowerCase())) {
+        		rdn = getRDN(filter.toString());
+        		
+            	if(user.RetriveUserByAccountName(rdn) == 0) {
+            		attributes = new BasicAttributes();
+    	            
+    	            attributes = getNTUserAttributes(user, rdn);
+    	            result = new SearchResult("sAMAccountName=" + user.GetAccountName() + "," + container + "," + suffix, null, attributes);
+    	            results.add(result);
+    	            resultCount++;
+            	}
+            	else if(group.RetriveGroupByAccountName(rdn) == 0) {
+            		attributes = new BasicAttributes();
+    	            
+    	            attributes = getNTGroupAttributes(group, rdn);
+    	            result = new SearchResult("sAMAccountName=" + group.GetAccountName() + "," + container + "," + suffix, null, attributes);
+    	            results.add(result);
+    	            resultCount++;
+            	}
+            	else if(localGroup.RetriveLocalGroupByAccountName(rdn) == 0) {
+            		attributes = new BasicAttributes();
+    	            
+    	            attributes = getNTLocalGroupAttributes(localGroup, rdn);
+    	            result = new SearchResult("sAMAccountName=" + localGroup.GetAccountName() + "," + container + "," + suffix, null, attributes);
+    	            results.add(result);
+    	            resultCount++;
+            	}
+            	else {
+            		// empty set
+            	}
+        	}
+        	else if((filter.toString().toLowerCase().startsWith(new String("(objectGUID=").toLowerCase())) ||
+        			(filter.toString().toLowerCase().startsWith(new String("(GUID=").toLowerCase()))) {
+        		rdn = getRDN(filter.toString());
+        		
+            	if(user.RetriveUserBySIDHexStr(rdn) == 0) {
+            		attributes = new BasicAttributes();
+    	            
+    	            attributes = getNTUserAttributes(user, rdn);
+    	            result = new SearchResult("sAMAccountName=" + user.GetAccountName() + "," + container + "," + suffix, null, attributes);
+    	            results.add(result);
+    	            resultCount++;
+            	}
+            	else if(group.RetriveGroupBySIDHexStr(rdn) == 0) {
+            		attributes = new BasicAttributes();
+    	            
+    	            attributes = getNTGroupAttributes(group, rdn);
+    	            result = new SearchResult("sAMAccountName=" + group.GetAccountName() + "," + container + "," + suffix, null, attributes);
+    	            results.add(result);
+    	            resultCount++;
+            	}
+            	else if(localGroup.RetriveLocalGroupBySIDHexStr(rdn) == 0) {
+            		attributes = new BasicAttributes();
+    	            
+    	            attributes = getNTLocalGroupAttributes(localGroup, rdn);
+    	            result = new SearchResult("sAMAccountName=" + localGroup.GetAccountName() + "," + container + "," + suffix, null, attributes);
+    	            results.add(result);
+    	            resultCount++;
+            	}
+            	else {
+            		// empty set
+            	}
+        	}
+        	else if(filter.toString().toLowerCase().startsWith(new String("(objectClass=*)").toLowerCase())) {
+		    	NTUserList users = new NTUserList();
+		        if(users.loadList() != 0) {
+		            throw new NamingException("Failed to load user list");
+		        }
+		        while(users.hasMore()) {
+		            attributes = new BasicAttributes();
+		            
+		            rdn = users.nextUsername();
+		            if(!rdn.endsWith("$")) {
+			            user.RetriveUserByAccountName(rdn);
+			            attributes = getNTUserAttributes(user, rdn);
+			            result = new SearchResult("sAMAccountName=" + user.GetAccountName() + "," + container + "," + suffix, null, attributes);
+			            results.add(result);
+			            resultCount++;
+		            }
+		        }
+		        
+		        NTGroupList groups = new NTGroupList();
+		        if(groups.loadList() != 0) {
+		            throw new NamingException("Failed to load group list");
+		        }
+		        while(groups.hasMore()) {
+		            attributes = new BasicAttributes();
+		            
+		            rdn = groups.nextGroupName();
+		            if(!rdn.endsWith("$")) {
+		            	group.RetriveGroupByAccountName(rdn);
+		            	attributes = getNTGroupAttributes(group, rdn);
+		            	result = new SearchResult("sAMAccountName=" + group.GetAccountName() + "," + container + "," + suffix, null, attributes);
+		            	results.add(result);
+		            	resultCount++;
+		            }
+		        }
+		        
+		        NTLocalGroupList localGroups = new NTLocalGroupList();
+		        if(localGroups.loadList() != 0) {
+		            throw new NamingException("Failed to load local group list");
+		        }
+		        while(localGroups.hasMore()) {
+		            attributes = new BasicAttributes();
+		            
+		            if(!rdn.endsWith("$")) {
+			            rdn = localGroups.nextLocalGroupName();
+			            localGroup.RetriveLocalGroupByAccountName(rdn);
+			            attributes = getNTLocalGroupAttributes(localGroup, rdn);
+			            result = new SearchResult("sAMAccountName=" + localGroup.GetAccountName() + "," + container + "," + suffix, null, attributes);
+			            results.add(result);
+			            resultCount++;
+		            }
+		        }
+        	}
+        	else {
+        		throw new NamingException("Unsupported search filter: " + filter);
+        	}
+        }
+        else {
+        	throw new NamingException("Bad base DN: " + base);
+        }
+        
+        return resultCount;
+    }
+    
+    private BasicAttributes getNTUserAttributes(NTUser user, String username) throws NamingException {
+    	int result = 0;
+        BasicAttributes attributes = new BasicAttributes();
+        BasicAttribute attribute;
+        String tempName;
+        
+        attribute = new BasicAttribute("objectClass");
+        attribute.add("top");
+        attribute.add("person");
+        attribute.add("organizationalPerson");
+        attribute.add("user");
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("objectGUID");
+        attribute.add(user.GetSIDHexStr());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("objectSid");
+        attribute.add(user.GetSIDHexStr());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("accountExpires");
+        attribute.add(new Long(user.GetAccountExpires()).toString());
+        attributes.put(attribute);
+
+        attribute = new BasicAttribute("badPwdCount");
+        attribute.add(new Long(user.GetBadPasswordCount()).toString());
+        attributes.put(attribute);
+
+        attribute = new BasicAttribute("codePage");
+        attribute.add(new Long(user.GetCodePage()).toString());
+        attributes.put(attribute);
+
+        attribute = new BasicAttribute("description");
+        attribute.add(user.GetComment());
+        attributes.put(attribute);
+
+        attribute = new BasicAttribute("countryCode");
+        attribute.add(new Long(user.GetCountryCode()).toString());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("userAccountControl");
+        attribute.add(new Long(user.GetFlags()).toString());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("homeDirectory");
+        attribute.add(user.GetHomeDir());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("homeDrive");
+        attribute.add(user.GetHomeDirDrive());
+        attributes.put(attribute);
+
+        attribute = new BasicAttribute("lastLogoff");
+        attribute.add(new Long(user.GetLastLogoff()).toString());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("lastLogon");
+        attribute.add(new Long(user.GetLastLogon()).toString());
+        attributes.put(attribute);
+
+        attribute = new BasicAttribute("logonHours");
+        attribute.add(user.GetLogonHours());
+        attributes.put(attribute);
+
+        attribute = new BasicAttribute("maxStorage");
+        attribute.add(new Long(user.GetMaxStorage()).toString());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("logonCount");
+        attribute.add(new Long(user.GetNumLogons()).toString());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("profilePath");
+        attribute.add(user.GetProfile());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("scriptPath");
+        attribute.add(user.GetScriptPath());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("sAMAccountName");
+        attribute.add(username);
+        attributes.put(attribute);
+
+        attribute = new BasicAttribute("userWorkstations");
+        attribute.add(user.GetWorkstations());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("cn");
+        attribute.add(username);
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("name");
+        attribute.add(user.GetFullname());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("memberOf");
+        result = user.LoadGroups();
+        if(result != 0) {
+        	throw new NamingException("Could not load groups: " + result);
+        }
+        while(user.HasMoreGroups()) {
+        	tempName = user.NextGroupName();
+        	if(!tempName.endsWith("$")) {
+        		attribute.add("sAMAccountName=" + tempName + "," + container + "," + suffix);
+        	}
+        }
+        result = user.LoadLocalGroups();
+        if(result != 0) {
+        	throw new NamingException("Could not load local groups: " + result);
+        }
+        while(user.HasMoreLocalGroups()) {
+        	tempName = user.NextLocalGroupName();
+        	if(!tempName.endsWith("$")) {
+        		attribute.add("sAMAccountName=" + tempName + "," + container + "," + suffix);
+        	}
+        }
+        attributes.put(attribute);
+        
+        return attributes;
+    }
+    
+    private BasicAttributes getNTGroupAttributes(NTGroup group, String groupName) throws NamingException {
+        BasicAttributes attributes = new BasicAttributes();
+        BasicAttribute attribute;
+        String tempName;
+        int result = 0;
+        
+        attribute = new BasicAttribute("objectClass");
+        attribute.add("top");
+        attribute.add("group");
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("objectGUID");
+        attribute.add(group.GetSIDHexStr());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("objectSid");
+        attribute.add(group.GetSIDHexStr());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("name");
+        attribute.add(groupName);
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("sAMAccountName");
+        attribute.add(groupName);
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("cn");
+        attribute.add(groupName);
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("groupType");
+        attribute.add(new Long(GLOBAL_FLAG).toString());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("member");
+        result = group.LoadUsers();
+        if(result != 0) {
+        	throw new NamingException("Could not load users: " + result);
+        }
+        while(group.HasMoreUsers()) {
+        	tempName = group.NextUserName();
+        	// members that end with '$' are supposed to be hidden
+        	if(!tempName.endsWith("$")) {
+        		attribute.add("sAMAccountName=" + tempName + "," + container + "," + suffix);
+        	}
+        }
+        attributes.put(attribute);
+        
+        return attributes;
+    }
+    
+    private BasicAttributes getNTLocalGroupAttributes(NTLocalGroup localGroup, String localGroupName) throws NamingException {
+        BasicAttributes attributes = new BasicAttributes();
+        BasicAttribute attribute;
+        String tempName;
+        int result = 0;
+        
+        attribute = new BasicAttribute("objectClass");
+        attribute.add("top");
+        attribute.add("group");
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("objectGUID");
+        attribute.add(localGroup.GetSIDHexStr());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("objectSid");
+        attribute.add(localGroup.GetSIDHexStr());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("name");
+        attribute.add(localGroupName);
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("sAMAccountName");
+        attribute.add(localGroupName);
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("cn");
+        attribute.add(localGroupName);
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("groupType");
+        attribute.add(new Long(DOMAINLOCAL_FLAG).toString());
+        attributes.put(attribute);
+        
+        attribute = new BasicAttribute("member");
+        result = localGroup.LoadUsers();
+        if(result != 0) {
+        	throw new NamingException("Could not load users: " + result);
+        }
+        while(localGroup.HasMoreUsers()) {
+        	tempName = localGroup.NextUserName();
+        	// members that end with '$' are supposed to be hidden
+        	if(!tempName.endsWith("$")) {
+        		attribute.add("sAMAccountName=" + tempName + "," + container + "," + suffix);
+        	}
+        }
+        attributes.put(attribute);
+        
+        return attributes;
+    }
+    
+    private void modNTUserAttributes(NTUser user, ModificationItem[] mods) throws NamingException {
+        for(int i = 0; i < mods.length; i++) {
+        	
+        	if(mods[i].getAttribute().getID().compareToIgnoreCase("accountExpires") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetAccountExpires(new Long((String)mods[i].getAttribute().get()).longValue());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetAccountExpires(new Long(-1).longValue());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetAccountExpires(new Long((String)mods[i].getAttribute().get()).longValue());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("codePage") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetCodePage(new Long((String)mods[i].getAttribute().get()).longValue());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetCodePage(new Long(0).longValue());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetCodePage(new Long((String)mods[i].getAttribute().get()).longValue());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("description") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetComment((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetComment("");
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetComment((String)mods[i].getAttribute().get());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("countryCode") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetCountryCode(new Long((String)mods[i].getAttribute().get()).longValue());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetCountryCode(new Long(0).longValue());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetCountryCode(new Long((String)mods[i].getAttribute().get()).longValue());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("userAccountControl") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetFlags(new Long((String)mods[i].getAttribute().get()).longValue());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetFlags(new Long(1).longValue());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetFlags(new Long((String)mods[i].getAttribute().get()).longValue());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("homeDirectory") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetHomeDir((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetHomeDir("");
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetHomeDir((String)mods[i].getAttribute().get());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("homeDrive") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetHomeDirDrive((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetHomeDirDrive("");
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetHomeDirDrive((String)mods[i].getAttribute().get());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("logonHours") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetLogonHours((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetLogonHours("");
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetLogonHours((String)mods[i].getAttribute().get());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("maxStorage") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetMaxStorage(new Long((String)mods[i].getAttribute().get()).longValue());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetMaxStorage(new Long(-1).longValue());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetMaxStorage(new Long((String)mods[i].getAttribute().get()).longValue());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("profilePath") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetProfile((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetProfile("");
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetProfile((String)mods[i].getAttribute().get());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("scriptPath") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetScriptPath((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetScriptPath((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetScriptPath((String)mods[i].getAttribute().get());
+        		}
+        	}
+        	else if(mods[i].getAttribute().getID().compareToIgnoreCase("userWorkstations") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetWorkstations((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetWorkstations("");
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetWorkstations((String)mods[i].getAttribute().get());
+        		}
+        	}
+            else if(mods[i].getAttribute().getID().compareToIgnoreCase("cn") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetFullname((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetFullname("");
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetFullname((String)mods[i].getAttribute().get());
+        		}
+            }
+            else if(mods[i].getAttribute().getID().compareToIgnoreCase("name") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetFullname((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			user.SetFullname("");
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetFullname((String)mods[i].getAttribute().get());
+        		}
+            }
+            else if(mods[i].getAttribute().getID().compareToIgnoreCase("unicodePwd") == 0) {
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			user.SetPassword((String)mods[i].getAttribute().get());
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			// Do nothing
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			user.SetPassword((String)mods[i].getAttribute().get());
+        		}
+            }
+            else if(mods[i].getAttribute().getID().compareToIgnoreCase("memberOf") == 0) {
+            	String tempName;
+            	
+        		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+        			for(int j = 0; j < mods[i].getAttribute().size(); j++) {
+        				tempName = getRDN((String)mods[i].getAttribute().get(j));
+        				user.AddToGroup(tempName);
+        				user.AddToLocalGroup(tempName);
+            		}
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+        			for(int j = 0; j < mods[i].getAttribute().size(); j++) {
+	    				tempName = getRDN((String)mods[i].getAttribute().get(j));
+	        			user.RemoveFromGroup(tempName);
+	        			user.RemoveFromLocalGroup(tempName);
+        			}
+        		}
+        		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+        			HashSet groups = new HashSet();
+        			Object[] deletedGroups;
+        			
+        			user.LoadGroups();
+        			while(user.HasMoreGroups()) {
+        				tempName = user.NextGroupName();
+        				if(!tempName.endsWith("$")) {
+        					groups.add(tempName);
+        				}
+        			}
+        			
+        			user.LoadLocalGroups();
+        			while(user.HasMoreLocalGroups()) {
+        				tempName = user.NextLocalGroupName();
+        				if(!tempName.endsWith("$")) {
+        					groups.add(tempName);
+        				}
+        			}
+        			
+        			for(int j = 0; j < mods[i].getAttribute().size(); j++) {
+        				tempName = getRDN((String)mods[i].getAttribute().get(j));
+        				if(groups.contains(tempName)) {
+        					groups.remove(tempName);
+        				}
+        				else {
+        					user.AddToGroup(tempName);
+            				user.AddToLocalGroup(tempName);
+        				}
+            		}
+        			
+        			deletedGroups = groups.toArray();
+        			for(int j = 0; j < deletedGroups.length; j++) {
+        				user.RemoveFromGroup((String)deletedGroups[j]);
+        				user.RemoveFromLocalGroup((String)deletedGroups[j]);
+        			}
+        		}
+            }
+        }
+    }
+    
+    private void modNTGroupAttributes(NTGroup group, ModificationItem[] mods) throws NamingException {
+    	for(int i = 0; i < mods.length; i++) {
+	    	if(mods[i].getAttribute().getID().compareToIgnoreCase("member") == 0) {	
+	    		String tempName;
+	    		
+	    		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+	    			for(int j = 0; j < mods[i].getAttribute().size(); j++) {
+	    				tempName = getRDN((String)mods[i].getAttribute().get(j));
+	    				group.AddUser((String)mods[i].getAttribute().get(j));
+	        		}
+	    		}
+	    		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+	    			tempName = getRDN((String)mods[i].getAttribute().get());
+	    			group.RemoveUser(tempName);
+	    		}
+	    		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+	    			HashSet users = new HashSet();
+	    			Object[] deletedUsers;
+		    		
+	    			group.LoadUsers();
+	    			while(group.HasMoreUsers()) {
+	    				tempName = group.NextUserName();
+						if(!tempName.endsWith("$")) {
+							users.add(tempName);
+						}
+	    			}
+	    			
+	    			for(int j = 0; j < mods[i].getAttribute().size(); j++) {
+	    				tempName = getRDN((String)mods[i].getAttribute().get(j));
+	    				if(users.contains(tempName)) {
+	    					users.remove(tempName);
+	    				}
+	    				else {
+	    					group.AddUser(tempName);
+	    				}
+	        		}
+	    			
+	    			deletedUsers = users.toArray();
+	    			for(int j = 0; j < deletedUsers.length; j++) {
+        				group.RemoveUser((String)deletedUsers[j]);
+        			}
+	    		}
+	        }
+    	}
+    }
+    
+    private void modNTLocalGroupAttributes(NTLocalGroup localGroup, ModificationItem[] mods) throws NamingException {
+    	for(int i = 0; i < mods.length; i++) {
+    		if(mods[i].getAttribute().getID().compareToIgnoreCase("member") == 0) {	
+	    		String tempName;
+	    		
+	    		if(mods[i].getModificationOp() == DirContext.ADD_ATTRIBUTE) {
+	    			for(int j = 0; j < mods[i].getAttribute().size(); j++) {
+	    				tempName = getRDN((String)mods[i].getAttribute().get(j));
+	    				localGroup.AddUser((String)mods[i].getAttribute().get(j));
+	        		}
+	    		}
+	    		else if(mods[i].getModificationOp() == DirContext.REMOVE_ATTRIBUTE) {
+	    			tempName = getRDN((String)mods[i].getAttribute().get());
+	    			localGroup.RemoveUser(tempName);
+	    		}
+	    		else if(mods[i].getModificationOp() == DirContext.REPLACE_ATTRIBUTE) {
+	    			HashSet users = new HashSet();
+	    			Object[] deletedUsers;
+		    		
+	    			localGroup.LoadUsers();
+	    			while(localGroup.HasMoreUsers()) {
+	    				tempName = localGroup.NextUserName();
+						if(!tempName.endsWith("$")) {
+							users.add(tempName);
+						}
+	    			}
+	    			
+	    			for(int j = 0; j < mods[i].getAttribute().size(); j++) {
+	    				tempName = getRDN((String)mods[i].getAttribute().get(j));
+	    				if(users.contains(tempName)) {
+	    					users.remove(tempName);
+	    				}
+	    				else {
+	    					localGroup.AddUser(tempName);
+	    				}
+	        		}
+	    			
+	    			deletedUsers = users.toArray();
+	    			for(int j = 0; j < deletedUsers.length; j++) {
+        				localGroup.RemoveUser((String)deletedUsers[j]);
+        			}
+	    		}
+	        }
+    	}
+    }
+}

+ 88 - 0
ldap/servers/ntds/apacheds/project.properties

@@ -0,0 +1,88 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# 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; version 2 of the License.
+# 
+# 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., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+# 
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception. 
+# 
+# 
+# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+maven.compile.source = 1.4
+maven.compile.target = 1.4
+maven.compile.debug=on
+maven.compile.optimize=on
+maven.compile.deprecation=on
+
+#maven.junit.fork=yes
+maven.xdoc.includeProjectDocumentation=yes
+
+#maven.javadoc.private=true
+
+# AspectJ Properties
+# =======================
+
+#maven.aspectj.verbose=true
+#maven.aspectj.incremental=true
+maven.aspectj.time=true
+
+
+# schema class generation
+# =======================
+
+maven.ldap.server.schemas=apachedns,autofs,core,cosine,corba,apache,inetorgperson,java,krb5kdc,nis,system,dhcp,samba,usersync
+
+maven.ldap.server.schema.deps.apachedns=system,core
+maven.ldap.server.schema.deps.autofs=system,core,cosine
+maven.ldap.server.schema.deps.corba=system,core
+maven.ldap.server.schema.deps.core=system
+maven.ldap.server.schema.deps.cosine=system,core
+maven.ldap.server.schema.deps.apache=system
+maven.ldap.server.schema.deps.inetorgperson=system,core,cosine
+maven.ldap.server.schema.deps.java=system,core
+maven.ldap.server.schema.deps.krb5kdc=system,core
+maven.ldap.server.schema.deps.nis=system,core,cosine
+maven.ldap.server.schema.deps.system=
+maven.ldap.server.schema.deps.dhcp=system,core
+maven.ldap.server.schema.deps.samba=cosine,inetorg,nis
+maven.ldap.server.schema.deps.usersync=
+
+maven.license.licenseFile=${basedir}/../LICENSE.txt
+
+maven.junit.sysproperties=java.util.prefs.PreferencesFactory
+java.util.prefs.PreferencesFactory=org.apache.ldap.server.prefs.ServerPreferencesFactory
+
+maven.eclipse.classpath.include=${basedir}/target/schema,${basedir}/src/main/aspects
+
+# Disabled temporarilly; Eclipse build doesn't work.
+#maven.eclipse.buildcommands=org.eclipse.ajdt.core.ajbuilder
+#maven.eclipse.projectnatures=org.eclipse.ajdt.ui.ajnature

+ 575 - 0
ldap/servers/ntds/apacheds/usersync.schema

@@ -0,0 +1,575 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# 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; version 2 of the License.
+# 
+# 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., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+# 
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception. 
+# 
+# 
+# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+# mystery section attributes
+attributetype ( 1.3.6.1.4.1.7114.2.1.10 NAME 'changetype'
+        DESC 'AD ubiquitous changetype attribute'
+        EQUALITY caseIgnoreIA5Match
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{8} SINGLE-VALUE )
+
+# Microsoft attributes
+#
+# Here follows definitions from schema/microsoft.schema
+# if you don't have the file o dont like the OIDs or so,
+# you MUST copy and paste this list attribute definition:
+#
+# SYNTAX changes:
+#
+# Large-Integer: 1.3.6.1.4.1.1466.115.121.1.27
+# Encoded as an Integer (OID 1.3.6.1.4.1.1466.115.121.1.27), but guaranteed
+# to support 64 bit numbers.
+
+# user attrs
+
+attributetype ( 1.2.840.113556.1.4.8  NAME 'userAccountControl'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.166
+        NAME 'groupMembershipSAM'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.213
+        NAME 'defaultClassStore'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attributetype ( 1.2.840.113556.1.4.656
+        NAME 'userPrincipalName'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.86
+        NAME 'userWorkstations'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.65
+        NAME 'logonWorkstation'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.751
+        NAME 'userSharedFolder'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.49
+        NAME 'badPasswordTime'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.302
+        NAME 'sAMAccountType'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.98
+        NAME 'primaryGroupID'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.159
+        NAME 'accountExpires'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.346
+        NAME 'desktopProfile'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.782
+        NAME 'objectCategory'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.221
+        NAME 'sAMAccountName'
+		EQUALITY caseIgnoreMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.144
+        NAME 'operatorCount'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.44
+        NAME 'homeDirectory'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.772
+        NAME 'aCSPolicyName'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.94
+        NAME 'ntPwdHistory'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
+ 
+
+attributetype ( 1.2.840.113556.1.4.160
+        NAME 'lmPwdHistory'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
+
+attributetype ( 1.2.840.113556.1.2.1
+        NAME 'instanceType'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE
+        NO-USER-MODIFICATION )
+
+attributetype ( 1.2.840.113556.1.4.97
+        NAME 'preferredOU'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.662
+        NAME 'lockoutTime'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.25
+        NAME 'countryCode'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.139
+        NAME 'profilePath'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.12
+        NAME 'badPwdCount'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.2.13
+        NAME 'displayName'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.2.3
+        NAME 'whenChanged'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.2.19
+        NAME 'uSNCreated'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.64
+        NAME 'logonHours'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.96
+        NAME 'pwdLastSet'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.169
+        NAME 'logonCount'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.90
+        NAME 'unicodePwd'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.62
+        NAME 'scriptPath'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.76
+        NAME 'maxStorage'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.51
+        NAME 'lastLogoff'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.2.120
+        NAME 'uSNChanged'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.2
+        NAME 'objectGUID'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.52
+        NAME 'lastLogon'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.45
+        NAME 'homeDrive'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.2.102
+        NAME 'memberOf'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+        NO-USER-MODIFICATION )
+
+attributetype ( 1.2.840.113556.1.4.58
+        NAME 'localeID'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.2.840.113556.1.4.16
+        NAME 'codePage'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.55
+        NAME 'dBCSPwd'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.91
+        NAME 'otherLoginWorkstations'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.2.840.113556.1.4.752
+        NAME 'userSharedFolderOther'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.2.840.113556.1.2.353
+        NAME 'displayNamePrintable'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.771
+        NAME 'servicePrincipalName'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.2.840.113556.1.4.200
+        NAME 'controlAccessRights'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
+
+# computer attrs
+attributetype ( 1.2.840.113556.1.4.669
+        NAME 'rIDSetReferences'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+        NO-USER-MODIFICATION )
+
+attributetype ( 1.2.840.113556.1.4.56
+        NAME 'localPolicyFlags'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.363
+        NAME 'operatingSystem'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.507
+        NAME 'volumeCount'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.619
+        NAME 'dNSHostName'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.71
+        NAME 'machineRole'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.365
+        NAME 'operatingSystemServicePack'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.364
+        NAME 'operatingSystemVersion'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.868
+        NAME 'isCriticalSystemObject'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.514
+        NAME 'physicalLocationObject'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.415
+        NAME 'operatingSystemHotfix'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.2.2
+        NAME 'whenCreated'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+        SINGLE-VALUE
+        NO-USER-MODIFICATION )
+
+# group attrs
+attributetype ( 1.2.840.113556.1.4.375
+        NAME 'systemFlags'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE
+        NO-USER-MODIFICATION )
+ 
+
+attributetype ( 1.2.840.113556.1.4.150
+        NAME 'adminCount'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.750
+        NAME 'groupType'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.146
+        NAME 'objectSid'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+        SINGLE-VALUE )
+ 
+
+attributetype ( 1.2.840.113556.1.2.169
+        NAME 'showInAdvancedViewOnly'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+        SINGLE-VALUE )
+
+# ridSet attrs
+attributetype ( 1.2.840.113556.1.4.371
+        NAME 'rIDAllocationPool'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE
+        NO-USER-MODIFICATION )
+
+attributetype ( 1.2.840.113556.1.4.373
+        NAME 'rIDUsedPool'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE
+        NO-USER-MODIFICATION )
+
+attributetype ( 1.2.840.113556.1.4.372
+        NAME 'rIDPreviousAllocationPool'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE
+        NO-USER-MODIFICATION )
+
+attributetype ( 1.2.840.113556.1.4.374
+        NAME 'rIDNextRID'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE
+        NO-USER-MODIFICATION )
+
+# ridManager attrs
+attributetype ( 1.2.840.113556.1.4.370
+        NAME 'rIDAvailablePool'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+        SINGLE-VALUE )
+
+attributetype ( 1.2.840.113556.1.4.369
+        NAME 'fSMORoleOwner'
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+        SINGLE-VALUE )
+ 
+
+# objectClass defs
+
+objectclass ( 1.3.6.1.4.1.7114.2.2.10
+    NAME 'user'
+    SUP organizationalPerson
+    STRUCTURAL
+    MUST ( objectSid $ objectClass $ cn )
+    MAY (
+        accountExpires $
+        aCSPolicyName $
+        adminCount $
+        badPasswordTime $
+        badPwdCount $
+        changetype $
+        codePage $
+        controlAccessRights $
+        countryCode $
+        dBCSPwd $
+        defaultClassStore $
+        description $
+        desktopProfile $
+        displayName $
+        distinguishedName $
+        givenName $
+        groupMembershipSAM $
+        homeDirectory $
+        homeDrive $
+        instanceType $
+        lastLogoff $
+        lastLogon $
+        lmPwdHistory $
+        localeID $
+        lockoutTime $
+        logonCount $
+        logonHours $
+        logonWorkstation $
+        maxStorage $
+        memberOf $
+        name $
+        ntPwdHistory $
+        objectCategory $
+        objectGUID $
+        operatorCount $
+        otherLoginWorkstations $
+        preferredOU $
+        primaryGroupID $
+        profilePath $
+        pwdLastSet $
+        sAMAccountName $
+        sAMAccountType $
+        scriptPath $
+        servicePrincipalName $
+        unicodePwd $
+        userAccountControl $
+        userPrincipalName $
+        userSharedFolder $
+        userSharedFolderOther $
+        userWorkstations $
+        uSNChanged $
+        uSNCreated $
+        whenChanged $
+        whenCreated ) )
+
+objectclass ( 1.3.6.1.4.1.7114.2.2.11
+    NAME 'computer'
+    SUP user
+    STRUCTURAL
+    MAY (
+        description $
+        dNSHostName $
+        isCriticalSystemObject $
+        localPolicyFlags $
+        machineRole $
+        operatingSystem $
+        operatingSystemHotfix $
+        operatingSystemServicePack $
+        operatingSystemVersion $
+        physicalLocationObject $
+        rIDSetReferences $
+        volumeCount ) )
+ 
+
+objectclass ( 1.3.6.1.4.1.7114.2.2.12
+    NAME 'group'
+    SUP top
+    STRUCTURAL
+    MUST (groupType $ cn )
+    MAY (
+        adminCount $
+        changetype $
+        controlAccessRights $
+        description $
+        distinguishedName $
+        instanceType $
+        isCriticalSystemObject $
+        member $
+        name $
+        groupType $
+        showInAdvancedViewOnly $
+        systemFlags $
+        objectCategory $
+        objectGUID $
+        objectSid $
+        sAMAccountName $
+        sAMAccountType $
+        uSNChanged $
+        uSNCreated $
+        whenChanged $
+        whenCreated ) )
+
+objectclass ( 1.3.6.1.4.1.7114.2.2.13
+    NAME 'rIDManager'
+    SUP top
+    STRUCTURAL
+    MUST (rIDAvailablePool )
+    MAY (
+        changetype $
+        cn $
+        fSMORoleOwner $
+        instanceType $
+        isCriticalSystemObject $
+        distinguishedName $
+        objectCategory $
+        objectGUID $
+        name $
+        showInAdvancedViewOnly $
+        systemFlags $
+        uSNChanged $
+        uSNCreated $
+        whenChanged $
+        whenCreated ) )
+ 
+
+objectclass ( 1.3.6.1.4.1.7114.2.2.14
+    NAME 'rIDSet'
+    SUP top
+    STRUCTURAL
+    MUST (
+        cn $
+        rIDAllocationPool $
+        rIDPreviousAllocationPool $
+        rIDUsedPool $
+        rIDNextRID )
+    MAY (
+        instanceType $
+        distinguishedName $
+        objectCategory $
+        objectGUID $
+        name $
+        showInAdvancedViewOnly $
+        uSNChanged $
+        uSNCreated $
+        whenChanged $
+        whenCreated $
+        changetype ) )

+ 96 - 0
ldap/servers/ntds/netman/Makefile

@@ -0,0 +1,96 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# 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; version 2 of the License.
+# 
+# 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., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+# 
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception. 
+# 
+# 
+# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+LDAP_SRC = ../../..
+BUILD_ROOT = ../../../..
+
+NOSTDCLEAN=true # don't let nsconfig.mk define target clean
+NOSTDSTRIP=true # don't let nsconfig.mk define target strip
+
+OBJDEST = $(OBJDIR)/lib/netman
+LIBDIR = $(LIB_RELDIR)
+
+include $(BUILD_ROOT)/nsconfig.mk
+include $(LDAP_SRC)/nsldap.mk
+include $(LDAP_SRC)/javarules.mk
+JAR=jar
+SWIG_OPTS=-v -outdir $(OBJDEST)
+JNETDEST=$(JAVA_DEST_DIR)/jnetman
+JAVA_HOME=$(JDKPRELIB)/..
+
+
+CPP_PROJ=$(CFLAGS)
+
+all:	$(OBJDEST) $(OBJDEST)/jnetman_wrap.cxx $(OBJDEST)/jnetman.dll  $(JAVA_DEST_DIR)/ntds/jnetman.jar 
+
+$(OBJDEST):
+	$(MKDIR) $(OBJDEST)
+
+$(OBJDEST)/jnetman_wrap.cxx:
+	$(SWIG_EXE) $(SWIG_OPTS) -java -package org.bpi.jnetman -c++ jnetman.i
+	$(MV) jnetman_wrap.cxx $(OBJDEST)
+
+$(JAVA_DEST_DIR)/ntds/jnetman.jar:	$(OBJDEST)/jnetman_wrap.cxx
+	$(MKDIR) $(JAVA_DEST_DIR)/ntds 
+	$(JAVAC) -d $(JAVA_DEST_DIR)/ntds $(OBJDEST)/*.java
+	( cd  $(JAVA_DEST_DIR)/ntds && jar cf $(JAVA_DEST_DIR)/ntds/jnetman.jar org)
+	#$(JAR) cf $(JAVA_DEST_DIR)/ntds/jnetman.jar $(JAVA_DEST_DIR)/ntds 
+
+
+$(OBJDEST)/jnetman.dll:  $(OBJDEST)/netman.obj $(OBJDEST)/jnetman_wrap.obj
+	$(LINK_DLL) /out:$(OBJDEST)/jnetman.dll    $(EXTRA_LIBS) netapi32.lib  $(OBJDEST)/netman.obj $(OBJDEST)/jnetman_wrap.obj
+
+$(OBJDEST)/netman.obj:
+	$(CC) -c netman.cpp $(CFLAGS)   $(MCC_INCLUDE) -Fo$(OBJDEST)/ $(CBSCFLAGS)
+
+$(OBJDEST)/jnetman_wrap.obj:
+	$(CC) -c  $(OBJDEST)/jnetman_wrap.cxx $(CFLAGS)   $(MCC_INCLUDE) -Fo$(OBJDEST)/ $(CBSCFLAGS) /I$(JAVA_HOME)/include /I$(JAVA_HOME)/include/win32 /I.
+
+veryclean: clean
+
+clean:
+	$(RM) $(OBJDEST)/jnetman_wrap.cxx 
+	$(RM) $(OBJDEST)/jnetman.dll  
+	$(RM) $(OBJDEST)/jnetman.lib  
+	$(RM) $(OBJDEST)/*.obj
+	$(RM) $(OBJDEST)/*.java
+	$(RM) $(JAVA_DEST_DIR)/ntds/jnetman.jar 
+
+
+

+ 53 - 0
ldap/servers/ntds/netman/jnetman.i

@@ -0,0 +1,53 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * 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; version 2 of the License.
+ * 
+ * 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., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ * 
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception. 
+ * 
+ * 
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
+ %module jnetman
+
+ %include "typemaps.i"
+ %include "cpointer.i"
+ %pragma(java) jniclassclassmodifiers="public class"
+
+ /* swig -java -package org.bpi -c++ jnetman.i */
+
+ %{
+ /* Includes the header in the wrapper code */
+ #include "netman.h"
+
+ %}
+ 
+ /* Parse the header file to generate wrappers */
+ %include "netman.h"

+ 1946 - 0
ldap/servers/ntds/netman/netman.cpp

@@ -0,0 +1,1946 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * 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; version 2 of the License.
+ * 
+ * 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., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ * 
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception. 
+ * 
+ * 
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
+// ****************************************************************
+// netman.cpp
+// ****************************************************************
+#include "netman.h"
+
+// ****************************************************************
+// UTF16ToUTF8
+// ****************************************************************
+char* UTF16ToUTF8(unsigned short* inString)
+{
+	int length = WideCharToMultiByte(CP_ACP, 0, inString, -1, 0, 0, 0, 0);
+	char* outString = NULL;
+
+	outString =	(char*)malloc(length);
+
+	WideCharToMultiByte(CP_ACP, 0, inString, -1, outString, length, 0, 0);
+
+	return outString;
+}
+
+// ****************************************************************
+// UTF8ToUTF16
+// ****************************************************************
+unsigned short* UTF8ToUTF16(char* inString)
+{
+	unsigned short* outString = NULL;
+	int length = MultiByteToWideChar(CP_ACP, 0, inString, -1, 0, 0);
+
+	outString =	(unsigned short*)malloc(length * 2);
+
+	MultiByteToWideChar(CP_ACP, 0, inString, -1, outString, length);
+
+	return outString;
+}
+
+// ****************************************************************
+// SIDToHexStr
+// ****************************************************************
+int SIDToHexStr(char* sid, unsigned long sidLen, char** hexStr)
+{
+	int hexStrLen = sidLen * 2 + 1;
+
+	*hexStr = (char*)calloc(hexStrLen, sizeof(char));
+
+	for(unsigned long i = 0; i < sidLen; i++)
+	{
+		sprintf(&(*hexStr)[i * 2], "%02X", (unsigned char)sid[i]);
+	}
+
+	return 0;
+}
+
+// ****************************************************************
+// HexStrToSID
+// ****************************************************************
+int HexStrToSID(char* hexStr, char** sid, unsigned long* sidLen)
+{
+	int temp;
+	*sidLen = strlen(hexStr) / 2;
+
+	*sid = (char*)malloc(*sidLen);
+
+	for(unsigned long i = 0; i < *sidLen; i++)
+	{
+		sscanf(&hexStr[i * 2], "%02X", &temp);
+		(*sid)[i] = (unsigned char)temp;
+	}
+
+	return 0;
+}
+
+// ****************************************************************
+// GetSIDByAccountName
+// ****************************************************************
+int GetSIDByAccountName(char* accountName, char** sid)
+{
+	int result = 0;
+	unsigned long sidLen = 0;
+	char* domain;
+	unsigned long domainLen = 0;
+	SID_NAME_USE testType;
+
+	if(LookupAccountName(NULL, accountName, NULL, &sidLen, NULL, &domainLen, &testType) == 0)
+	{
+		result = GetLastError();
+	}
+
+	*sid = (char*)malloc(sidLen);
+	domain = (char*)malloc(domainLen);
+
+	if(LookupAccountName(NULL, accountName, *sid, &sidLen, domain, &domainLen, &testType) == 0)
+	{
+		result = GetLastError();
+	}
+	else
+	{
+		result = 0;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// GetAccountNameBySID
+// ****************************************************************
+int GetAccountNameBySID(char* sid, char** accountName)
+{
+	int result = 0;
+	unsigned long sidLen = 0;
+	char* domain;
+	unsigned long domainLen = 0;
+	SID_NAME_USE testType;
+
+	unsigned long accountNameLen = 0;
+
+	if(LookupAccountSid(NULL, sid, NULL, &accountNameLen, NULL, &domainLen, &testType) == 0)
+	{
+		result = GetLastError();
+	}
+
+	domain = (char*)malloc(domainLen);
+	*accountName = (char*)calloc(accountNameLen, sizeof(char));
+
+	if(LookupAccountSid(NULL, sid, *accountName, &accountNameLen, domain, &domainLen, &testType) == 0)
+	{
+		result = GetLastError();
+	}
+	else
+	{
+		result = 0;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// GetSIDHexStrByAccountName
+// ****************************************************************
+int GetSIDHexStrByAccountName(char* accountName, char** sidHexStr)
+{
+	int result = 0;
+	char* sid;
+	unsigned long sidLen = 0;
+	char* domain;
+	unsigned long domainLen = 0;
+	SID_NAME_USE testType;
+
+	if(LookupAccountName(NULL, accountName, NULL, &sidLen, NULL, &domainLen, &testType) == 0)
+	{
+		result = GetLastError();
+	}
+
+	sid = (char*)malloc(sidLen);
+	domain = (char*)malloc(domainLen);
+
+	if(LookupAccountName(NULL, accountName, sid, &sidLen, domain, &domainLen, &testType) == 0)
+	{
+		result = GetLastError();
+	}
+	else
+	{
+		result = 0;
+	}
+
+
+	SIDToHexStr(sid, sidLen, sidHexStr);
+
+	return result;
+}
+
+// ****************************************************************
+// GetAccountNameBySIDHexStr
+// ****************************************************************
+int GetAccountNameBySIDHexStr(char* sidHexStr, char** accountName)
+{
+	int result = 0;
+	char* sid;
+	unsigned long sidLen = 0;
+	char* domain;
+	unsigned long domainLen = 0;
+	SID_NAME_USE testType;
+
+	unsigned long accountNameLen = 0;
+
+	HexStrToSID(sidHexStr, &sid, &sidLen);
+
+	if(LookupAccountSid(NULL, sid, NULL, &accountNameLen, NULL, &domainLen, &testType) == 0)
+	{
+		result = GetLastError();
+	}
+
+	domain = (char*)malloc(domainLen);
+	*accountName = (char*)calloc(accountNameLen, sizeof(char));
+
+	if(LookupAccountSid(NULL, sid, *accountName, &accountNameLen, domain, &domainLen, &testType) == 0)
+	{
+		result = GetLastError();
+	}
+	else
+	{
+		result = 0;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::NTUser
+// ****************************************************************
+NTUser::NTUser()
+{
+	userInfo = NULL;
+
+	groupsInfo = NULL;
+	currentGroupEntry = 0;
+	groupEntriesRead = 0;
+	groupEntriesTotal = 0;
+
+	localGroupsInfo = NULL;
+	currentLocalGroupEntry = 0;
+	localGroupEntriesRead = 0;
+	localGroupEntriesTotal = 0;
+}
+
+// ****************************************************************
+// NTUser::~NTUser
+// ****************************************************************
+NTUser::~NTUser()
+{
+	if(userInfo != NULL)
+	{
+		NetApiBufferFree(userInfo);
+		userInfo = NULL;
+	}
+	if(groupsInfo != NULL)
+	{
+		NetApiBufferFree(groupsInfo);
+		groupsInfo = NULL;
+	}
+	if(localGroupsInfo != NULL)
+	{
+		NetApiBufferFree(localGroupsInfo);
+		localGroupsInfo = NULL;
+	}
+}
+
+// ****************************************************************
+// NTUser::NewUser
+// ****************************************************************
+void NTUser::NewUser(char* username)
+{
+	if(userInfo != NULL)
+	{
+		NetApiBufferFree(userInfo);
+		userInfo = NULL;
+	}
+
+	userInfo = (USER_INFO_3*)malloc(sizeof(USER_INFO_3));
+	memset(userInfo, 0, sizeof(USER_INFO_3));
+	userInfo->usri3_name = UTF8ToUTF16(username);
+
+	// Possible required inits for AddUser
+	//userInfo->usri3_priv = USER_PRIV_USER;
+	//userInfo->usri3_home_dir = NULL;
+	//userInfo->usri3_comment = NULL;
+	//userInfo->usri3_script_path = NULL;
+
+	// NT4 required inits for AddUser
+	userInfo->usri3_flags = UF_SCRIPT;
+	userInfo->usri3_primary_group_id = DOMAIN_GROUP_RID_USERS;
+
+	// Other inits
+	userInfo->usri3_acct_expires = (unsigned long)-1;
+}
+
+// ****************************************************************
+// NTUser::RetriveUserByUsername
+// ****************************************************************
+int NTUser::RetriveUserByAccountName(char* username)
+{
+	int result;
+
+	if(userInfo != NULL)
+	{
+		NetApiBufferFree(userInfo);
+		userInfo = NULL;
+	}
+
+	result = NetUserGetInfo(NULL, UTF8ToUTF16(username), USER_INFO_LEVEL, (unsigned char**)&userInfo);
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::RetriveUserBySIDHexStr
+// ****************************************************************
+int NTUser::RetriveUserBySIDHexStr(char* sidHexStr)
+{
+	int result = 0;
+	char* username;
+
+	if(userInfo != NULL)
+	{
+		NetApiBufferFree(userInfo);
+		userInfo = NULL;
+	}
+
+	if(GetAccountNameBySIDHexStr(sidHexStr, &username) != 0)
+	{
+		result = -1;
+		goto exit;
+	}
+
+	if(RetriveUserByAccountName(username) != 0)
+	{
+		result =-1;
+		goto exit;
+	}
+
+exit:
+	return result;
+}
+
+// ****************************************************************
+// NTUser::StoreUser
+// ****************************************************************
+int NTUser::StoreUser()
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = NetUserSetInfo(NULL, userInfo->usri3_name, USER_INFO_LEVEL, (unsigned char*)userInfo, NULL);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::AddUser
+// ****************************************************************
+int NTUser::AddUser()
+{
+	int result;
+	DWORD badParam = 0;
+
+	result = NetUserAdd(NULL, USER_INFO_LEVEL, (unsigned char*)userInfo, &badParam);
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::DeleteUser
+// ****************************************************************
+int NTUser::DeleteUser(char* username)
+{
+	int result;
+
+	result = NetUserDel(NULL, UTF8ToUTF16(username));
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::ChangeUsername
+// ****************************************************************
+int NTUser::ChangeUsername(char* oldUsername, char* newUsername)
+{
+	int result;
+
+	if((result = RetriveUserByAccountName(oldUsername)) == 0)
+	{
+		userInfo->usri3_name = UTF8ToUTF16(newUsername);
+		if((result = AddUser()) == 0)
+		{
+			if((result = DeleteUser(oldUsername)) != 0)
+			{
+				DeleteUser(newUsername);
+			}
+		}
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetAccountName
+// ****************************************************************
+char* NTUser::GetAccountName()
+{
+	char* result = NULL;
+
+	if(userInfo != NULL)
+	{
+		result = UTF16ToUTF8(userInfo->usri3_name);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetSIDHexStr
+// ****************************************************************
+char* NTUser::GetSIDHexStr()
+{
+	char* result = NULL;
+
+	if(userInfo != NULL)
+	{
+		GetSIDHexStrByAccountName(UTF16ToUTF8(userInfo->usri3_name), &result);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetAccountExpires
+// ****************************************************************
+unsigned long NTUser::GetAccountExpires()
+{
+	unsigned long result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = userInfo->usri3_acct_expires;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetAccountExpires
+// ****************************************************************
+int NTUser::SetAccountExpires(unsigned long accountExpires)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_acct_expires = accountExpires;
+	}
+	else
+	{
+		result = -1;
+	}
+	
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetBadPasswordCount
+// ****************************************************************
+unsigned long NTUser::GetBadPasswordCount()
+{
+	unsigned long result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = userInfo->usri3_bad_pw_count;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetCodePage
+// ****************************************************************
+unsigned long NTUser::GetCodePage()
+{
+	unsigned long result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = userInfo->usri3_code_page;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetCodePage
+// ****************************************************************
+int NTUser::SetCodePage(unsigned long codePage)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_code_page = codePage;
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetComment
+// ****************************************************************
+char* NTUser::GetComment()
+{
+	char* result = NULL;
+
+	if(userInfo != NULL)
+	{
+		result =  UTF16ToUTF8(userInfo->usri3_comment);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetComment
+// ****************************************************************
+int NTUser::SetComment(char* comment)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_comment = UTF8ToUTF16(comment);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetCountryCode
+// ****************************************************************
+unsigned long NTUser::GetCountryCode()
+{
+	unsigned long result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = userInfo->usri3_country_code;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetCountryCode
+// ****************************************************************
+int NTUser::SetCountryCode(unsigned long countryCode)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_country_code = countryCode;
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetFlags
+// ****************************************************************
+unsigned long NTUser::GetFlags()
+{
+	unsigned long result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = userInfo->usri3_flags;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetFlags
+// ****************************************************************
+int NTUser::SetFlags(unsigned long flags)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_flags = flags;
+	}
+	else
+	{
+		result = -1;
+	}
+	
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetHomeDir
+// ****************************************************************
+char* NTUser::GetHomeDir()
+{
+	char* result = NULL;
+
+	if(userInfo != NULL)
+	{
+		result = UTF16ToUTF8(userInfo->usri3_home_dir);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetHomeDir
+// ****************************************************************
+int NTUser::SetHomeDir(char* path)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_home_dir = UTF8ToUTF16(path);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetHomeDirDrive
+// ****************************************************************
+char* NTUser::GetHomeDirDrive()
+{
+	char* result = NULL;
+
+	if(userInfo != NULL)
+	{
+		result = UTF16ToUTF8(userInfo->usri3_home_dir_drive);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetHomeDirDrive
+// ****************************************************************
+int NTUser::SetHomeDirDrive(char* path)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_home_dir_drive = UTF8ToUTF16(path);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetLastLogoff
+// ****************************************************************
+unsigned long NTUser::GetLastLogoff()
+{
+	unsigned long result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = userInfo->usri3_last_logoff;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetLastLogon
+// ****************************************************************
+unsigned long NTUser::GetLastLogon()
+{
+	unsigned long result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = userInfo->usri3_last_logon;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetLogonHours
+// ****************************************************************
+char* NTUser::GetLogonHours()
+{
+	char* result = NULL;
+
+	if(userInfo != NULL)
+	{
+		result = (char*)userInfo->usri3_logon_hours;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetLogonHours
+// ****************************************************************
+int NTUser::SetLogonHours(char* logonHours)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_logon_hours = (unsigned char*)logonHours;
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetMaxStorage
+// ****************************************************************
+unsigned long NTUser::GetMaxStorage()
+{
+	unsigned long result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = userInfo->usri3_max_storage;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetMaxStorage
+// ****************************************************************
+int NTUser::SetMaxStorage(unsigned long maxStorage)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_max_storage = maxStorage;
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetNumLogons
+// ****************************************************************
+unsigned long NTUser::GetNumLogons()
+{
+	unsigned long result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = userInfo->usri3_num_logons;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetProfile
+// ****************************************************************
+char* NTUser::GetProfile()
+{
+	char* result = NULL;
+
+	if(userInfo != NULL)
+	{
+		result = UTF16ToUTF8(userInfo->usri3_profile);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetProfile
+// ****************************************************************
+int NTUser::SetProfile(char* path)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_profile = UTF8ToUTF16(path);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetScriptPath
+// ****************************************************************
+char* NTUser::GetScriptPath()
+{
+	char* result = NULL;
+
+	if(userInfo != NULL)
+	{
+		result = UTF16ToUTF8(userInfo->usri3_script_path);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetScriptPath
+// ****************************************************************
+int NTUser::SetScriptPath(char* path)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_script_path = UTF8ToUTF16(path);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetWorkstations
+// ****************************************************************
+char* NTUser::GetWorkstations()
+{
+	char* result = NULL;
+
+	if(userInfo != NULL)
+	{
+		result = UTF16ToUTF8(userInfo->usri3_workstations);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetWorkstations
+// ****************************************************************
+int NTUser::SetWorkstations(char* workstations)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_workstations = UTF8ToUTF16(workstations);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::GetFullname
+// ****************************************************************
+char* NTUser::GetFullname()
+{
+	char* result = NULL;
+
+	if(userInfo != NULL)
+	{
+		result = UTF16ToUTF8(userInfo->usri3_full_name);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetFullname
+// ****************************************************************
+int NTUser::SetFullname(char* fullname)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_full_name = UTF8ToUTF16(fullname);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::SetPassword
+// ****************************************************************
+int NTUser::SetPassword(char* password)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		userInfo->usri3_password = UTF8ToUTF16(password);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::AddToGroup
+// ****************************************************************
+int NTUser::AddToGroup(char* groupName)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = NetGroupAddUser(NULL, UTF8ToUTF16(groupName), userInfo->usri3_name);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::RemoveFromGroup
+// ****************************************************************
+int NTUser::RemoveFromGroup(char* groupName)
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		result = NetGroupDelUser(NULL, UTF8ToUTF16(groupName), userInfo->usri3_name);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::LoadGroups
+// ****************************************************************
+int NTUser::LoadGroups()
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		if(groupsInfo != NULL)
+		{
+			NetApiBufferFree(groupsInfo);
+			groupsInfo = NULL;
+			currentGroupEntry = 0;
+			groupEntriesRead = 0;
+			groupEntriesTotal = 0;
+		}
+		result = NetUserGetGroups(NULL, userInfo->usri3_name, USER_GROUPS_INFO_LEVEL, (unsigned char**)&groupsInfo, MAX_PREFERRED_LENGTH, &groupEntriesRead, &groupEntriesTotal);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::HasMoreGroups
+// ****************************************************************
+bool NTUser::HasMoreGroups()
+{
+	bool result;
+
+	if(currentGroupEntry < groupEntriesRead)
+	{
+		result = true;
+	}
+	else
+	{
+		result = false; 
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::NextGroupName
+// ****************************************************************
+char* NTUser::NextGroupName()
+{
+	char* groupName = NULL;
+	GROUP_USERS_INFO_0* thisEntry;
+
+	if(currentGroupEntry < groupEntriesRead)
+	{
+		thisEntry = &(groupsInfo[currentGroupEntry]);
+		groupName = UTF16ToUTF8(thisEntry->grui0_name);
+		currentGroupEntry++;
+	}
+
+	return groupName;
+}
+
+// ****************************************************************
+// NTUser::AddToLocalGroup
+// ****************************************************************
+int NTUser::AddToLocalGroup(char* localGroupName)
+{
+	int result = 0;
+	char userSID[256];
+	wchar_t domain[256];
+	DWORD SIDLen = sizeof(userSID);
+	DWORD domainLen = sizeof(domain);
+	SID_NAME_USE SIDUseIndicator;
+	LOCALGROUP_MEMBERS_INFO_0 membersbuf[1];
+
+	memset(&domain, 0, sizeof(domain));
+	memset(&userSID, 0, sizeof(userSID));
+
+	if(userInfo != NULL)
+	{
+		result = LookupAccountName(NULL, UTF16ToUTF8(userInfo->usri3_name), &userSID, &SIDLen, (LPTSTR)&domain, &domainLen, &SIDUseIndicator);
+
+		if(result != 0)
+		{
+			membersbuf[0].lgrmi0_sid = &userSID;
+			result = NetLocalGroupAddMembers(NULL, UTF8ToUTF16(localGroupName), 0, (LPBYTE)&membersbuf, 1);
+		}
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::RemoveFromLocalGroup
+// ****************************************************************
+int NTUser::RemoveFromLocalGroup(char* localGroupName)
+{
+	int result = 0;
+	char userSID[256];
+	wchar_t domain[256];
+	DWORD SIDLen = sizeof(userSID);
+	DWORD domainLen = sizeof(domain);
+	SID_NAME_USE SIDUseIndicator;
+	LOCALGROUP_MEMBERS_INFO_0 membersbuf[1];
+
+	memset(&domain, 0, sizeof(domain));
+	memset(&userSID, 0, sizeof(userSID));
+
+	if(userInfo != NULL)
+	{
+		result = LookupAccountName(NULL, UTF16ToUTF8(userInfo->usri3_name), &userSID, &SIDLen, (LPTSTR)&domain, &domainLen, &SIDUseIndicator);
+
+		if(result != 0)
+		{
+			membersbuf[0].lgrmi0_sid = &userSID;
+			result = NetLocalGroupDelMembers(NULL, UTF8ToUTF16(localGroupName), 0, (LPBYTE)&membersbuf, 1);
+		}
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::LoadLocalGroups
+// ****************************************************************
+int NTUser::LoadLocalGroups()
+{
+	int result = 0;
+
+	if(userInfo != NULL)
+	{
+		if(localGroupsInfo != NULL)
+		{
+			NetApiBufferFree(localGroupsInfo);
+			localGroupsInfo = NULL;
+			currentLocalGroupEntry = 0;
+			localGroupEntriesRead = 0;
+			localGroupEntriesTotal = 0;
+		}
+
+		result = NetUserGetLocalGroups(NULL, userInfo->usri3_name, 0, USER_LOCALGROUPS_INFO_LEVEL, (unsigned char**)&localGroupsInfo, MAX_PREFERRED_LENGTH, &localGroupEntriesRead, &localGroupEntriesTotal);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::HasMoreLocalGroups
+// ****************************************************************
+bool NTUser::HasMoreLocalGroups()
+{
+	bool result;
+
+	if(currentLocalGroupEntry < localGroupEntriesRead)
+	{
+		result = true;
+	}
+	else
+	{
+		result = false;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUser::NextLocalGroupName
+// ****************************************************************
+char* NTUser::NextLocalGroupName()
+{
+	char* localGroupName = NULL;
+	LOCALGROUP_USERS_INFO_0* thisEntry;
+
+	if(currentLocalGroupEntry < localGroupEntriesRead)
+	{
+		thisEntry = &(localGroupsInfo[currentLocalGroupEntry]);
+		localGroupName = UTF16ToUTF8(thisEntry->lgrui0_name);
+		currentLocalGroupEntry++;
+	}
+
+	return localGroupName;
+}
+
+// ****************************************************************
+// NTUserList::NTUserList
+// ****************************************************************
+NTUserList::NTUserList()
+{
+	bufptr = NULL;
+	currentEntry = 0;
+	resumeHandle = 0;
+}
+
+// ****************************************************************
+// NTUserList::~NTUserList
+// ****************************************************************
+NTUserList::~NTUserList()
+{
+	if(bufptr != NULL)
+	{
+		NetApiBufferFree(bufptr);
+		bufptr = NULL;
+	}
+}
+
+// ****************************************************************
+// NTUserList::loadList
+// ****************************************************************
+int NTUserList::loadList()
+{
+	int result;
+
+	result = NetUserEnum(NULL, USER_INFO_LEVEL, 0, (LPBYTE*)&bufptr, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resumeHandle);
+
+	return result;
+}
+
+// ****************************************************************
+// NTUserList::hasMore
+// ****************************************************************
+bool NTUserList::hasMore()
+{
+	bool result;
+
+	if(currentEntry < entriesRead)
+	{
+		result = true;
+	}
+	else
+	{
+		result = false;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTUserList::nextUsername
+// ****************************************************************
+char* NTUserList::nextUsername()
+{
+	char* username = NULL;
+	USER_INFO_3* thisEntry;
+
+	if(currentEntry < entriesRead)
+	{
+		thisEntry = &(bufptr[currentEntry]);
+		username = UTF16ToUTF8(thisEntry->usri3_name);
+		currentEntry++;
+	}
+
+	return username;
+}
+
+// ****************************************************************
+// NTGroup::NTGroup
+// ****************************************************************
+NTGroup::NTGroup()
+{
+	groupInfo = NULL;
+}
+
+// ****************************************************************
+// NTGroup::~NTGroup
+// ****************************************************************
+NTGroup::~NTGroup()
+{
+	if(groupInfo != NULL)
+	{
+		NetApiBufferFree(groupInfo);
+		groupInfo = NULL;
+	}
+}
+
+// ****************************************************************
+// NTGroup::NewGroup
+// ****************************************************************
+void NTGroup::NewGroup(char* groupName)
+{
+	if(groupInfo != NULL)
+	{
+		NetApiBufferFree(groupInfo);
+		groupInfo = NULL;
+	}
+
+	groupInfo = (GROUP_INFO_2*)malloc(sizeof(GROUP_INFO_2));
+	memset(groupInfo, 0, sizeof(GROUP_INFO_2));
+	groupInfo->grpi2_name = UTF8ToUTF16(groupName);
+}
+
+// ****************************************************************
+// NTGroup::DeleteGroup
+// ****************************************************************
+int NTGroup::DeleteGroup(char* groupName)
+{
+	int result;
+
+	result = NetGroupDel(NULL, UTF8ToUTF16(groupName));
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::RetriveGroup
+// ****************************************************************
+int NTGroup::RetriveGroupByAccountName(char* groupName)
+{
+	int result;
+
+	if(groupInfo != NULL)
+	{
+		NetApiBufferFree(groupInfo);
+		groupInfo = NULL;
+	}
+
+	result = NetGroupGetInfo(NULL, UTF8ToUTF16(groupName), GROUP_INFO_LEVEL, (unsigned char**)&groupInfo);
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::RetriveGroupBySIDHexStr
+// ****************************************************************
+int NTGroup::RetriveGroupBySIDHexStr(char* sidHexStr)
+{
+	int result = 0;
+	char* groupName;
+
+	if(groupInfo != NULL)
+	{
+		NetApiBufferFree(groupInfo);
+		groupInfo = NULL;
+	}
+
+	if(GetAccountNameBySIDHexStr(sidHexStr, &groupName) != 0)
+	{
+		result = -1;
+		goto exit;
+	}
+
+	if(RetriveGroupByAccountName(groupName) != 0)
+	{
+		result =-1;
+		goto exit;
+	}
+
+exit:
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::AddGroup
+// ****************************************************************
+int NTGroup::AddGroup()
+{
+	int result;
+	DWORD badParam = 0;
+
+	result = NetGroupAdd(NULL, GROUP_INFO_LEVEL, (unsigned char*)groupInfo, &badParam);
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::StoreGroup
+// ****************************************************************
+int NTGroup::StoreGroup()
+{
+	int result = -1;
+
+	if(groupInfo != NULL)
+	{
+		result = NetGroupSetInfo(NULL, groupInfo->grpi2_name, GROUP_INFO_LEVEL, (unsigned char*)groupInfo, NULL);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::GetAccountName
+// ****************************************************************
+char* NTGroup::GetAccountName()
+{
+	char* result = NULL;
+
+	if(groupInfo != NULL)
+	{
+		result = UTF16ToUTF8(groupInfo->grpi2_name);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::GetSIDHexStr
+// ****************************************************************
+char* NTGroup::GetSIDHexStr()
+{
+	char* result = NULL;
+
+	if(groupInfo != NULL)
+	{
+		GetSIDHexStrByAccountName(UTF16ToUTF8(groupInfo->grpi2_name), &result);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::AddUser
+// ****************************************************************
+int NTGroup::AddUser(char* userName)
+{
+	int result = 0;
+
+	if(groupInfo != NULL)
+	{
+		result = NetGroupAddUser(NULL, groupInfo->grpi2_name, UTF8ToUTF16(userName));
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::RemoveUser
+// ****************************************************************
+int NTGroup::RemoveUser(char* userName)
+{
+	int result = 0;
+
+	if(groupInfo != NULL)
+	{
+		result = NetGroupDelUser(NULL, groupInfo->grpi2_name, UTF8ToUTF16(userName));
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::LoadUsers
+// ****************************************************************
+int NTGroup::LoadUsers()
+{
+	int result = 0;
+
+	if(groupInfo != NULL)
+	{
+		if(usersInfo != NULL)
+		{
+			NetApiBufferFree(usersInfo);
+			usersInfo = NULL;
+			currentUserEntry = 0;
+			userEntriesRead = 0;
+			userEntriesTotal = 0;
+		}
+		result = NetGroupGetUsers(NULL, groupInfo->grpi2_name, GROUP_USERS_INFO_LEVEL, (unsigned char**)&usersInfo, MAX_PREFERRED_LENGTH, &userEntriesRead, &userEntriesTotal, NULL);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::HasMoreUsers
+// ****************************************************************
+bool NTGroup::HasMoreUsers()
+{
+	bool result;
+
+	if(currentUserEntry < userEntriesRead)
+	{
+		result = true;
+	}
+	else
+	{
+		result = false; 
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::NextUserName
+// ****************************************************************
+char* NTGroup::NextUserName()
+{
+	char* userName = NULL;
+	LOCALGROUP_USERS_INFO_0* thisEntry;
+
+	if(currentUserEntry < userEntriesRead)
+	{
+		thisEntry = &(usersInfo[currentUserEntry]);
+		userName = UTF16ToUTF8(thisEntry->lgrui0_name);
+		currentUserEntry++;
+	}
+
+	return userName;
+}
+
+// ****************************************************************
+// NTGroupList::NTGroupList
+// ****************************************************************
+NTGroupList::NTGroupList()
+{
+	bufptr = NULL;
+	currentEntry = 0;
+	resumeHandle = 0;
+}
+
+// ****************************************************************
+// NTGroupList::~NTGroupList
+// ****************************************************************
+NTGroupList::~NTGroupList()
+{
+	if(bufptr != NULL)
+	{
+		NetApiBufferFree(bufptr);
+		bufptr = NULL;
+	}
+}
+
+// ****************************************************************
+// NTGroupList::loadList
+// ****************************************************************
+int NTGroupList::loadList()
+{
+	int result;
+
+	result = NetGroupEnum(NULL, GROUP_INFO_LEVEL, (LPBYTE*)&bufptr, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resumeHandle);
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroupList::hasMore
+// ****************************************************************
+bool NTGroupList::hasMore()
+{
+	bool result;
+
+	if(currentEntry < entriesRead)
+	{
+		result = true;
+	}
+	else
+	{
+		result = false;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroupList::nextGroupName
+// ****************************************************************
+char* NTGroupList::nextGroupName()
+{
+	char* groupName = NULL;
+	GROUP_INFO_2* thisEntry;
+
+	if(currentEntry < entriesRead)
+	{
+		thisEntry = &(bufptr[currentEntry]);
+		groupName = UTF16ToUTF8(thisEntry->grpi2_name);
+		currentEntry++;
+	}
+
+	return groupName;
+}
+
+// ****************************************************************
+// NTLocalGroup::NTLocalGroup
+// ****************************************************************
+NTLocalGroup::NTLocalGroup()
+{
+	localGroupInfo = NULL;
+}
+
+// ****************************************************************
+// NTLocalGroup::~NTLocalGroup
+// ****************************************************************
+NTLocalGroup::~NTLocalGroup()
+{
+	if(localGroupInfo != NULL)
+	{
+		NetApiBufferFree(localGroupInfo);
+		localGroupInfo = NULL;
+	}
+}
+
+// ****************************************************************
+// NTLocalGroup::NewLocalGroup
+// ****************************************************************
+void NTLocalGroup::NewLocalGroup(char* localGroupName)
+{
+	if(localGroupInfo != NULL)
+	{
+		NetApiBufferFree(localGroupInfo);
+		localGroupInfo = NULL;
+	}
+
+	localGroupInfo = (LOCALGROUP_INFO_1*)malloc(sizeof(LOCALGROUP_INFO_1));
+	memset(localGroupInfo, 0, sizeof(LOCALGROUP_INFO_1));
+	localGroupInfo->lgrpi1_name = UTF8ToUTF16(localGroupName);
+}
+
+// ****************************************************************
+// NTLocalGroup::DeleteLocalGroup
+// ****************************************************************
+int NTLocalGroup::DeleteLocalGroup(char* localGroupName)
+{
+	int result;
+
+	result = NetLocalGroupDel(NULL, UTF8ToUTF16(localGroupName));
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroup::RetriveLocalGroup
+// ****************************************************************
+int NTLocalGroup::RetriveLocalGroupByAccountName(char* localGroupName)
+{
+	int result;
+
+	if(localGroupInfo != NULL)
+	{
+		NetApiBufferFree(localGroupInfo);
+		localGroupInfo = NULL;
+	}
+
+	result = NetLocalGroupGetInfo(NULL, UTF8ToUTF16(localGroupName), LOCALGROUP_INFO_LEVEL, (unsigned char**)&localGroupInfo);
+
+	return result;
+}
+
+// ****************************************************************
+// NTGroup::RetriveLocalGroupBySIDHexStr
+// ****************************************************************
+int NTLocalGroup::RetriveLocalGroupBySIDHexStr(char* sidHexStr)
+{
+	int result = 0;
+	char* localGroupName;
+
+	if(localGroupInfo != NULL)
+	{
+		NetApiBufferFree(localGroupInfo);
+		localGroupInfo = NULL;
+	}
+
+	if(GetAccountNameBySIDHexStr(sidHexStr, &localGroupName) != 0)
+	{
+		result = -1;
+		goto exit;
+	}
+
+	if(RetriveLocalGroupByAccountName(localGroupName) != 0)
+	{
+		result =-1;
+		goto exit;
+	}
+
+exit:
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroup::AddLocalGroup
+// ****************************************************************
+int NTLocalGroup::AddLocalGroup()
+{
+	int result;
+	DWORD badParam = 0;
+
+	result = NetLocalGroupAdd(NULL, LOCALGROUP_INFO_LEVEL, (unsigned char*)localGroupInfo, &badParam);
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroup::StoreLocalGroup
+// ****************************************************************
+int NTLocalGroup::StoreLocalGroup()
+{
+	int result = 0;
+
+	if(localGroupInfo != NULL)
+	{
+		result = NetLocalGroupSetInfo(NULL, localGroupInfo->lgrpi1_name, LOCALGROUP_INFO_LEVEL, (unsigned char*)localGroupInfo, NULL);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroup::GetAccountName
+// ****************************************************************
+char* NTLocalGroup::GetAccountName()
+{
+	char* result = NULL;
+
+	if(localGroupInfo != NULL)
+	{
+		result = UTF16ToUTF8(localGroupInfo->lgrpi1_name);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroup::GetSIDHexStr
+// ****************************************************************
+char* NTLocalGroup::GetSIDHexStr()
+{
+	char* result = NULL;
+
+	if(localGroupInfo != NULL)
+	{
+		GetSIDHexStrByAccountName(UTF16ToUTF8(localGroupInfo->lgrpi1_name), &result);
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroup::AddUser
+// ****************************************************************
+int NTLocalGroup::AddUser(char* username)
+{
+	int result = 0;
+	LOCALGROUP_MEMBERS_INFO_0 members[1];
+
+	if(localGroupInfo != NULL)
+	{
+		GetSIDByAccountName(username, (char**)&members[0].lgrmi0_sid);
+		result = NetLocalGroupAddMembers(NULL, localGroupInfo->lgrpi1_name, 0, (unsigned char*)&members, 1);
+		free(members[0].lgrmi0_sid);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroup::RemoveUser
+// ****************************************************************
+int NTLocalGroup::RemoveUser(char* username)
+{
+	int result = 0;
+	LOCALGROUP_MEMBERS_INFO_0 members[1];
+
+	if(localGroupInfo != NULL)
+	{
+		GetSIDByAccountName(username, (char**)&members[0].lgrmi0_sid);
+		result = NetLocalGroupDelMembers(NULL, localGroupInfo->lgrpi1_name, 0, (unsigned char*)&members, 1);
+		free(members[0].lgrmi0_sid);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroup::LoadUsers
+// ****************************************************************
+int NTLocalGroup::LoadUsers()
+{
+	int result = 0;
+
+	if(localGroupInfo != NULL)
+	{
+		if(usersInfo != NULL)
+		{
+			NetApiBufferFree(usersInfo);
+			usersInfo = NULL;
+			currentUserEntry = 0;
+			userEntriesRead = 0;
+			userEntriesTotal = 0;
+		}
+		result = NetLocalGroupGetMembers(NULL, localGroupInfo->lgrpi1_name, LOCALGROUP_USERS_INFO_LEVEL, (unsigned char**)&usersInfo, MAX_PREFERRED_LENGTH, &userEntriesRead, &userEntriesTotal, NULL);
+	}
+	else
+	{
+		result = -1;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroup::HasMoreUsers
+// ****************************************************************
+bool NTLocalGroup::HasMoreUsers()
+{
+	bool result;
+
+	if(currentUserEntry < userEntriesRead)
+	{
+		result = true;
+	}
+	else
+	{
+		result = false; 
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroup::NextUserName
+// ****************************************************************
+char* NTLocalGroup::NextUserName()
+{
+	char* username = NULL;
+	LOCALGROUP_MEMBERS_INFO_0* thisEntry;
+
+	if(currentUserEntry < userEntriesRead)
+	{
+		thisEntry = &(usersInfo[currentUserEntry]);
+		GetAccountNameBySID((char*)thisEntry->lgrmi0_sid, &username);
+		currentUserEntry++;
+	}
+
+	return username;
+}
+
+// ****************************************************************
+// NTLocalGroupList::NTLocalGroupList
+// ****************************************************************
+NTLocalGroupList::NTLocalGroupList()
+{
+	bufptr = NULL;
+	currentEntry = 0;
+	resumeHandle = 0;
+}
+
+// ****************************************************************
+// NTLocalGroupList::~NTLocalGroupList
+// ****************************************************************
+NTLocalGroupList::~NTLocalGroupList()
+{
+	if(bufptr != NULL)
+	{
+		NetApiBufferFree(bufptr);
+		bufptr = NULL;
+	}
+}
+
+// ****************************************************************
+// NTLocalGroupList::loadList
+// ****************************************************************
+int NTLocalGroupList::loadList()
+{
+	int result;
+
+	result = NetLocalGroupEnum(NULL, LOCALGROUP_INFO_LEVEL, (LPBYTE*)&bufptr, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resumeHandle);
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroupList::hasMore
+// ****************************************************************
+bool NTLocalGroupList::hasMore()
+{
+	bool result;
+
+	if(currentEntry < entriesRead)
+	{
+		result = true;
+	}
+	else
+	{
+		result = false;
+	}
+
+	return result;
+}
+
+// ****************************************************************
+// NTLocalGroupList::nextLocalGroupName
+// ****************************************************************
+char* NTLocalGroupList::nextLocalGroupName()
+{
+	char* localGroupName = NULL;
+	LOCALGROUP_INFO_1* thisEntry;
+
+	if(currentEntry < entriesRead)
+	{
+		thisEntry = &(bufptr[currentEntry]);
+		localGroupName = UTF16ToUTF8(thisEntry->lgrpi1_name);
+		currentEntry++;
+	}
+
+	return localGroupName;
+}

+ 262 - 0
ldap/servers/ntds/netman/netman.h

@@ -0,0 +1,262 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * 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; version 2 of the License.
+ * 
+ * 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., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ * 
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception. 
+ * 
+ * 
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
+// ****************************************************************
+// netman.h
+// ****************************************************************
+#include <windows.h>
+#include <lm.h>
+#include <stdio.h>
+
+#define USER_INFO_LEVEL 3
+#define USER_GROUPS_INFO_LEVEL 0
+#define USER_LOCALGROUPS_INFO_LEVEL 0
+
+#define GROUP_INFO_LEVEL 2
+#define GROUP_USERS_INFO_LEVEL 0
+
+#define LOCALGROUP_INFO_LEVEL 1
+#define LOCALGROUP_USERS_INFO_LEVEL 0
+
+#define NETMAN_BUF_LEN 256
+
+// ****************************************************************
+// NTUser
+// ****************************************************************
+class NTUser
+{
+public:
+	NTUser();
+	~NTUser();
+
+	void NewUser(char* username);
+	int RetriveUserByAccountName(char* username);
+	int RetriveUserBySIDHexStr(char* sidHexStr);
+	int StoreUser();
+	int AddUser();
+	int DeleteUser(char* username);
+	int ChangeUsername(char* oldUsername, char* newUsername);
+	char* GetAccountName();
+	char* GetSIDHexStr();
+
+	unsigned long GetAccountExpires();
+	int SetAccountExpires(unsigned long accountExpires);
+	unsigned long GetBadPasswordCount();
+	unsigned long GetCodePage();
+	int SetCodePage(unsigned long codePage);
+	char* GetComment();
+	int SetComment(char* comment);
+	unsigned long GetCountryCode();
+	int SetCountryCode(unsigned long countryCode);
+	unsigned long GetFlags();
+	int SetFlags(unsigned long flags);
+	char* GetHomeDir();
+	int SetHomeDir(char* path);
+	char* GetHomeDirDrive();
+	int SetHomeDirDrive(char* path);
+	unsigned long GetLastLogoff();
+	unsigned long GetLastLogon();
+	char* GetLogonHours();
+	int SetLogonHours(char* logonHours);
+	unsigned long GetMaxStorage();
+	int SetMaxStorage(unsigned long maxStorage);
+	unsigned long GetNumLogons();
+	char* GetProfile();
+	int SetProfile(char* path);
+	char* GetScriptPath();
+	int SetScriptPath(char* path);
+	char* GetWorkstations();
+	int SetWorkstations(char* workstations);
+	char* GetFullname();
+	int SetFullname(char* fullname);
+	int SetPassword(char* password);
+
+	int AddToGroup(char* groupName);
+	int RemoveFromGroup(char* groupName);
+	int LoadGroups();
+	bool HasMoreGroups();
+	char* NextGroupName();
+
+	int AddToLocalGroup(char* localGroupName);
+	int RemoveFromLocalGroup(char* localGroupName);
+	int LoadLocalGroups();
+	bool HasMoreLocalGroups();
+	char* NextLocalGroupName();
+
+private:
+	USER_INFO_3* userInfo;
+
+	GROUP_USERS_INFO_0* groupsInfo;
+	DWORD currentGroupEntry;
+	DWORD groupEntriesRead;
+	DWORD groupEntriesTotal;
+
+	LOCALGROUP_USERS_INFO_0* localGroupsInfo;
+	DWORD currentLocalGroupEntry;
+	DWORD localGroupEntriesRead;
+	DWORD localGroupEntriesTotal;
+};
+
+// ****************************************************************
+// NTUserList
+// ****************************************************************
+class NTUserList
+{
+public:
+	NTUserList();
+	~NTUserList();
+
+	int loadList();
+	bool hasMore();
+	char* nextUsername();
+
+private:
+	USER_INFO_3*  bufptr;
+	DWORD entriesRead;
+	DWORD totalEntries;
+	DWORD resumeHandle;
+	DWORD currentEntry;
+};
+
+// ****************************************************************
+// NTGroup
+// ****************************************************************
+class NTGroup
+{
+public:
+	NTGroup();
+	~NTGroup();
+
+	void NewGroup(char* groupName);
+	int DeleteGroup(char* groupName);
+	int RetriveGroupByAccountName(char* groupName);
+	int RetriveGroupBySIDHexStr(char* sidHexStr);
+	int AddGroup();
+	int StoreGroup();
+	char* GetAccountName();
+	char* GetSIDHexStr();
+
+	int AddUser(char* username);
+	int RemoveUser(char* username);
+	int LoadUsers();
+	bool HasMoreUsers();
+	char* NextUserName();
+
+private:
+	GROUP_INFO_2* groupInfo;
+
+	LOCALGROUP_USERS_INFO_0* usersInfo;
+	DWORD currentUserEntry;
+	DWORD userEntriesRead;
+	DWORD userEntriesTotal;
+
+};
+
+// ****************************************************************
+// NTGroupList
+// ****************************************************************
+class NTGroupList
+{
+public:
+	NTGroupList();
+	~NTGroupList();
+
+	int loadList();
+	bool hasMore();
+	char* nextGroupName();
+
+private:
+	GROUP_INFO_2* bufptr;
+	DWORD entriesRead;
+	DWORD totalEntries;
+	DWORD resumeHandle;
+	DWORD currentEntry;
+};
+
+// ****************************************************************
+// NTLocalGroup
+// ****************************************************************
+class NTLocalGroup
+{
+public:
+	NTLocalGroup();
+	~NTLocalGroup();
+
+	void NewLocalGroup(char* localGroupName);
+	int DeleteLocalGroup(char* localGroupName);
+	int RetriveLocalGroupByAccountName(char* localGroupName);
+	int RetriveLocalGroupBySIDHexStr(char* sidHexStr);
+	int AddLocalGroup();
+	int StoreLocalGroup();
+	char* GetAccountName();
+	char* GetSIDHexStr();
+
+	int AddUser(char* username);
+	int RemoveUser(char* username);
+	int LoadUsers();
+	bool HasMoreUsers();
+	char* NextUserName();
+
+private:
+	LOCALGROUP_INFO_1* localGroupInfo;
+
+	LOCALGROUP_MEMBERS_INFO_0* usersInfo;
+	DWORD currentUserEntry;
+	DWORD userEntriesRead;
+	DWORD userEntriesTotal;
+};
+
+// ****************************************************************
+// NTLocalGroupList
+// ****************************************************************
+class NTLocalGroupList
+{
+public:
+	NTLocalGroupList();
+	~NTLocalGroupList();
+
+	int loadList();
+	bool hasMore();
+	char* nextLocalGroupName();
+
+private:
+	LOCALGROUP_INFO_1* bufptr;
+	DWORD entriesRead;
+	DWORD totalEntries;
+	DWORD resumeHandle;
+	DWORD currentEntry;
+};

+ 90 - 0
ldap/servers/ntds/wrapper/Makefile

@@ -0,0 +1,90 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# 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; version 2 of the License.
+# 
+# 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., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+# 
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception. 
+# 
+# 
+# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+LDAP_SRC = ../../..
+BUILD_ROOT = ../../../..
+
+OBJDEST = $(OBJDIR)/usersync
+LIBDIR = $(LIB_RELDIR)
+
+NOSTDCLEAN=true # don't let nsconfig.mk define target clean
+NOSTDSTRIP=true # don't let nsconfig.mk define target strip
+include $(BUILD_ROOT)/nsconfig.mk
+include $(LDAP_SRC)/nsldap.mk
+include $(LDAP_SRC)/javarules.mk
+
+PRODUCT=ntds
+WRAPPER_FILES=$(WRAPPER_DEST)/$(WRAPPER_REL_DIR)
+
+all: $(PRODUCT).msi
+
+$(OBJDEST):
+	$(MKDIR) $(OBJDEST)
+
+layout: $(OBJDEST)
+	$(MKDIR) $(OBJDEST)/bin
+	$(CP) $(WRAPPER_FILES)/bin/wrapper.exe $(OBJDEST)/bin/
+	$(CP) $(WRAPPER_FILES)/bin/InstallTestWrapper-NT.bat $(OBJDEST)/bin/installusersync.bat
+	$(CP) $(WRAPPER_FILES)/bin/UninstallTestWrapper-NT.bat $(OBJDEST)/bin/uninstallusersync.bat
+	$(CP) usersync.bat $(OBJDEST)/bin/
+	$(CP) $(JAVA_DEST_DIR)/ntds/usersync.jar $(OBJDEST)/bin
+	$(CP) $(JAVA_DEST_DIR)/ntds/jnetman.jar $(OBJDEST)/bin
+	$(CP) $(APACHEDS_FILE) $(OBJDEST)/bin/apacheds-main.jar
+	
+	$(MKDIR) $(OBJDEST)/conf
+	$(CP) wrapper.conf $(OBJDEST)/conf
+	$(CP) usersync.conf $(OBJDEST)/conf
+
+	$(MKDIR) $(OBJDEST)/lib
+	$(CP) $(OBJDIR)/lib/netman/jnetman.dll $(OBJDEST)/lib
+	$(CP) $(WRAPPER_FILES)/lib/wrapper.dll $(OBJDEST)/lib
+	$(CP) $(WRAPPER_FILES)/lib/wrapper.jar $(OBJDEST)/lib
+
+	$(MKDIR) $(OBJDEST)/logs
+
+
+$(PRODUCT).msi:	layout
+	$(CP) $(OBJDEST)/* wix
+	# Do not allow MAKEFLAGS or other environment variables to influence nmake.
+	env -i PATH="${PATH}" LIB="${LIB}" INCLUDE="${INCLUDE}" BUILD_DEBUG=${BUILD_DEBUG} build.bat
+	
+clean:
+	$(RM) wix/$(PRODUCT)*.msi wix/ntds.wixobj
+	$(RM) $(OBJDEST)
+	$(RM) wix/bin wix/conf wix/lib wix/logs/

+ 38 - 0
ldap/servers/ntds/wrapper/build.bat

@@ -0,0 +1,38 @@
+@rem //
+@rem // BEGIN COPYRIGHT BLOCK
+@rem // Copyright (C) 2005 Red Hat, Inc.
+@rem // All rights reserved.
+@rem // END COPYRIGHT BLOCK
+@rem //
+
+@echo off
+
+pushd
+
+if NOT [%BUILD_DEBUG%] == [] (
+    if [%BUILD_DEBUG%] == [optimize] (
+        set LIBROOT=..\..\..\..\..\dist\WINNT5.0_OPT.OBJ
+    ) else (
+        set LIBROOT=..\..\..\..\..\dist\WINNT5.0_DBG.OBJ
+    )
+)
+
+set PATH=%PATH%;%CD%\%LIBROOT%\wix
+
+set OK=0
+cd wix
+
+candle ntds.wxs
+set /a OK=%OK% + %ERRORLEVEL%
+
+light ntds.wixobj
+set /a OK=%OK% + %ERRORLEVEL%
+
+if NOT [%BUILD_DEBUG%] == [] (
+    if EXIST ntds.msi (move /Y ntds.msi ntds-%BUILD_DEBUG%.msi)
+)
+
+:END
+popd
+if %OK% GTR 1 (set OK=1)
+exit %OK%

+ 77 - 0
ldap/servers/ntds/wrapper/usersync.bat

@@ -0,0 +1,77 @@
+@rem // --- BEGIN COPYRIGHT BLOCK ---
+@rem // This Program is free software; you can redistribute it and/or modify it under
+@rem // the terms of the GNU General Public License as published by the Free Software
+@rem // Foundation; version 2 of the License.
+@rem // 
+@rem // This Program is distributed in the hope that it will be useful, but WITHOUT
+@rem // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+@rem // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+@rem // 
+@rem // You should have received a copy of the GNU General Public License along with
+@rem // this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+@rem // Place, Suite 330, Boston, MA 02111-1307 USA.
+@rem // 
+@rem // In addition, as a special exception, Red Hat, Inc. gives You the additional
+@rem // right to link the code of this Program with code not covered under the GNU
+@rem // General Public License ("Non-GPL Code") and to distribute linked combinations
+@rem // including the two, subject to the limitations in this paragraph. Non-GPL Code
+@rem // permitted under this exception must only link to the code of this Program
+@rem // through those well defined interfaces identified in the file named EXCEPTION
+@rem // found in the source code files (the "Approved Interfaces"). The files of
+@rem // Non-GPL Code may instantiate templates or use macros or inline functions from
+@rem // the Approved Interfaces without causing the resulting work to be covered by
+@rem // the GNU General Public License. Only Red Hat, Inc. may make changes or
+@rem // additions to the list of Approved Interfaces. You must obey the GNU General
+@rem // Public License in all respects for all of the Program code and other code used
+@rem // in conjunction with the Program except the Non-GPL Code covered by this
+@rem // exception. If you modify this file, you may extend this exception to your
+@rem // version of the file, but you are not obligated to do so. If you do not wish to
+@rem // provide this exception without modification, you must delete this exception
+@rem // statement from your version and license this file solely under the GPL without
+@rem // exception. 
+@rem // 
+@rem // 
+@rem // Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+@rem // Copyright (C) 2005 Red Hat, Inc.
+@rem // All rights reserved.
+@rem // --- END COPYRIGHT BLOCK ---
+@echo off
+setlocal
+
+rem
+rem Java Service Wrapper general startup script
+rem
+
+rem
+rem Resolve the real path of the Wrapper.exe
+rem  For non NT systems, the _REALPATH and _WRAPPER_CONF values
+rem  can be hard-coded below and the following test removed.
+rem
+if "%OS%"=="Windows_NT" goto nt
+echo This script only works with NT-based versions of Windows.
+goto :eof
+
+:nt
+rem
+rem Find the application home.
+rem
+rem %~dp0 is location of current script under NT
+set _REALPATH=%~dp0
+set _WRAPPER_EXE=%_REALPATH%Wrapper.exe
+
+rem
+rem Find the wrapper.conf
+rem
+:conf
+set _WRAPPER_CONF="%~f1"
+if not %_WRAPPER_CONF%=="" goto startup
+set _WRAPPER_CONF="%_REALPATH%..\conf\wrapper.conf"
+
+rem
+rem Start the Wrapper
+rem
+:startup
+"%_WRAPPER_EXE%" -c %_WRAPPER_CONF%
+if not errorlevel 1 goto :eof
+pause
+

+ 50 - 0
ldap/servers/ntds/wrapper/usersync.conf

@@ -0,0 +1,50 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# 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; version 2 of the License.
+# 
+# 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., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+# 
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception. 
+# 
+# 
+# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+server.net.ldap.port=1024
+server.net.ldaps.port=1025
+server.db.partition.suffix.usersync=dc=example,dc=com
+
+# do not modify beyond this point
+server.schemas = org.apache.ldap.server.schema.bootstrap.CoreSchema org.apache.ldap.server.schema.bootstrap.CosineSchema org.apache.ldap.server.schema.bootstrap.ApacheSchema org.apache.ldap.server.schema.bootstrap.InetorgpersonSchema org.apache.ldap.server.schema.bootstrap.JavaSchema org.apache.ldap.server.schema.bootstrap.SystemSchema org.apache.ldap.server.schema.bootstrap.UsersyncSchema
+server.db.partitions=usersync
+server.db.partition.class.usersync=org.apache.ldap.server.NetAPIPartition
+server.db.partition.indices.usersync=ou objectClass
+server.db.partition.attributes.usersync.ou=usersync
+server.db.partition.attributes.usersync.objectClass=top organizationalUnit extensibleObject

+ 105 - 0
ldap/servers/ntds/wrapper/wix/ntds.wxs

@@ -0,0 +1,105 @@
+<?xml version='1.0' encoding='windows-1252'?>
+<!-- BEGIN COPYRIGHT BLOCK
+ 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; version 2 of the License.
+ 
+ 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., 59 Temple
+ Place, Suite 330, Boston, MA 02111-1307 USA.
+
+ In addition, as a special exception, Red Hat, Inc. gives You the additional
+ right to link the code of this Program with code not covered under the GNU
+ General Public License ("Non-GPL Code") and to distribute linked combinations
+ including the two, subject to the limitations in this paragraph. Non-GPL Code
+ permitted under this exception must only link to the code of this Program
+ through those well defined interfaces identified in the file named EXCEPTION
+ found in the source code files (the "Approved Interfaces"). The files of
+ Non-GPL Code may instantiate templates or use macros or inline functions from
+ the Approved Interfaces without causing the resulting work to be covered by
+ the GNU General Public License. Only Red Hat, Inc. may make changes or
+ additions to the list of Approved Interfaces. You must obey the GNU General
+ Public License in all respects for all of the Program code and other code used
+ in conjunction with the Program except the Non-GPL Code covered by this
+ exception. If you modify this file, you may extend this exception to your
+ version of the file, but you are not obligated to do so. If you do not wish to
+ provide this exception without modification, you must delete this exception
+ statement from your version and license this file solely under the GPL without
+ exception. 
+
+
+ Copyright (C) 2005 Red Hat, Inc.
+ All rights reserved.
+ END COPYRIGHT BLOCK -->
+<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
+  <Product Name='NT User Synchronization' Id='DB501C18-86C7-4D14-AEC0-86416A69ABD0'
+    Language='1033' Codepage='1252'
+    Version='1.0.0' Manufacturer='Brandx'>
+
+    <Package Id='????????-????-????-????-????????????' Keywords='Installer'
+      Description="User Synchronization Installer"
+      Manufacturer='Brandx'
+      InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
+
+    <Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" />
+    <Property Id='DiskPrompt' Value="User Sync Installation [1]" />
+
+<Directory Id='ProgramFilesFolder' Name='PFiles'>
+
+<Directory Id='INSTALLDIR' Name='UserSync' LongName='NT User Synchronization'>
+
+<Directory Id='bin' Name='bin'>
+<Component Id='bin'>
+<File Id='apachejar' Name='apache~1.jar' LongName='apacheds-main.jar' DiskId='1' src='bin\apacheds-main.jar' Vital='yes' />
+<File Id='install' Name='instal~1.bat' LongName='installuseresync.bat' DiskId='1' src='bin\installusersync.bat' Vital='yes' />
+<File Id='jnetmanjar' Name='jnetman.jar' DiskId='1' src='bin\jnetman.jar' Vital='yes' />
+<File Id='uninstall' Name='uninst~1.bat' LongName='uninstalluseresync.bat' DiskId='1' src='bin\uninstallusersync.bat' Vital='yes' />
+<File Id='usersync' Name='usersync.bat' DiskId='1' src='bin\usersync.bat' Vital='yes' />
+<File Id='usersyncjar' Name='usersync.jar' DiskId='1' src='bin\usersync.jar' Vital='yes' />
+<File Id='wrapperbin' Name='wrapper.exe' DiskId='1' src='bin\wrapper.exe' Vital='yes' />
+</Component>
+</Directory>
+
+<Directory Id='conf' Name='conf'>
+<Component Id='conf'>
+<File Id='usersyncconf' Name='usersy~1.con' LongName='usersync.conf' DiskId='1' src='conf\usersync.conf' Vital='yes' />
+<File Id='wrapperconf' Name='wrappe~1.con' LongName='wrapper.conf' DiskId='1' src='conf\wrapper.conf' Vital='yes' />
+</Component>
+</Directory>
+
+<Directory Id='lib' Name='lib'>
+<Component Id='lib'>
+<File Id='netmandll' Name='jnetman.dll' DiskId='1' src='lib\jnetman.dll' Vital='yes' />
+<File Id='wrapperlib' Name='wrapper.dll' DiskId='1' src='lib\wrapper.dll' Vital='yes' />
+<File Id='wrapperjar' Name='wrapper.jar' DiskId='1' src='lib\wrapper.jar' Vital='yes' />
+</Component>
+</Directory>
+
+
+<Directory Id='logs' Name='logs'>
+<Component Id='logs' SharedDllRefCount='no' KeyPath='no' NeverOverwrite='no' Permanent='no' Transitive='no'
+        Win64='no' Location='either'>
+<CreateFolder/>
+</Component>
+</Directory>
+
+
+
+</Directory>
+</Directory>
+
+<Feature Id='All' Title='NT User Synchronization' Description='The complete package.'
+  TypicalDefault='install' Display='expand' Level='1'
+  ConfigurableDirectory='INSTALLDIR'>
+  <ComponentRef Id='bin'/>
+  <ComponentRef Id='conf'/>
+  <ComponentRef Id='lib'/>
+  <ComponentRef Id='logs'/>
+</Feature>
+
+</Product>
+</Wix>

+ 136 - 0
ldap/servers/ntds/wrapper/wrapper.conf

@@ -0,0 +1,136 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# 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; version 2 of the License.
+# 
+# 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., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+# 
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception. 
+# 
+# 
+# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+#********************************************************************
+# Wrapper Properties
+#********************************************************************
+# Java Application
+wrapper.java.command=java
+
+# Java Main class.  This class must implement the WrapperListener interface
+#  or guarantee that the WrapperManager class is initialized.  Helper
+#  classes are provided to do this for you.  See the Integration section
+#  of the documentation for details.
+wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
+
+# Java Classpath (include wrapper.jar)  Add class path elements as
+#  needed starting from 1
+wrapper.java.classpath.1=../lib/wrapper.jar
+wrapper.java.classpath.2=./jnetman.jar
+wrapper.java.classpath.3=./usersync.jar
+wrapper.java.classpath.4=./apacheds-main.jar
+
+# Java Library Path (location of Wrapper.DLL or libwrapper.so)
+wrapper.java.library.path.1=../lib
+
+# Java Additional Parameters
+#wrapper.java.additional.1=
+
+# Initial Java Heap Size (in MB)
+#wrapper.java.initmemory=3
+
+# Maximum Java Heap Size (in MB)
+#wrapper.java.maxmemory=64
+
+# Application parameters.  Add parameters as needed starting from 1
+wrapper.app.parameter.1=org.apache.ldap.server.ServerMain
+wrapper.app.parameter.2=../conf/usersync.conf
+
+#********************************************************************
+# Wrapper Logging Properties
+#********************************************************************
+# Format of output for the console.  (See docs for formats)
+wrapper.console.format=PM
+
+# Log Level for console output.  (See docs for log levels)
+wrapper.console.loglevel=INFO
+
+# Log file to use for wrapper output logging.
+wrapper.logfile=../logs/wrapper.log
+
+# Format of output for the log file.  (See docs for formats)
+wrapper.logfile.format=LPTM
+
+# Log Level for log file output.  (See docs for log levels)
+wrapper.logfile.loglevel=INFO
+
+# Maximum size that the log file will be allowed to grow to before
+#  the log is rolled. Size is specified in bytes.  The default value
+#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or
+#  'm' (mb) suffix.  For example: 10m = 10 megabytes.
+wrapper.logfile.maxsize=0
+
+# Maximum number of rolled log files which will be allowed before old
+#  files are deleted.  The default value of 0 implies no limit.
+wrapper.logfile.maxfiles=0
+
+# Log Level for sys/event log output.  (See docs for log levels)
+wrapper.syslog.loglevel=NONE
+
+#********************************************************************
+# Wrapper Windows Properties
+#********************************************************************
+# Title to use when running as a console
+wrapper.console.title=UserSync
+
+#********************************************************************
+# Wrapper Windows NT/2000/XP Service Properties
+#********************************************************************
+# WARNING - Do not modify any of these properties when an application
+#  using this configuration file has been installed as a service.
+#  Please uninstall the service before modifying this section.  The
+#  service can then be reinstalled.
+
+# Name of the service
+wrapper.ntservice.name=UserSync
+
+# Display name of the service
+wrapper.ntservice.displayname=User Sync Service
+
+# Description of the service
+wrapper.ntservice.description=User Sync Service
+
+# Service dependencies.  Add dependencies as needed starting from 1
+wrapper.ntservice.dependency.1=
+
+# Mode in which the service is installed.  AUTO_START or DEMAND_START
+wrapper.ntservice.starttype=AUTO_START
+
+# Allow the service to interact with the desktop.
+wrapper.ntservice.interactive=false