diff --git a/lam/lib/modules/windowsGroup.inc b/lam/lib/modules/windowsGroup.inc
new file mode 100644
index 00000000..a3c930ba
--- /dev/null
+++ b/lam/lib/modules/windowsGroup.inc
@@ -0,0 +1,355 @@
+ "high");
+		// LDAP filter
+		$return["ldap_filter"] = array('or' => "(objectClass=group)");
+		// alias name
+		$return["alias"] = _("Windows");
+		// module dependencies
+		$return['dependencies'] = array('depends' => array(), 'conflicts' => array());
+		// managed object classes
+		$return['objectClasses'] = array('group');
+		// managed attributes
+		$return['attributes'] = array('cn', 'description', 'info', 'mail', 'member', 'sAMAccountName');
+		// help Entries
+		$return['help'] = array(
+			'hiddenOptions' => array(
+				"Headline" => _("Hidden options"),
+				"Text" => _("The selected options will not be managed inside LAM. You can use this to reduce the number of displayed input fields.")
+			),
+			'cn' => array(
+				"Headline" => _('Group name'), 'attr' => 'cn, sAMAccountName',
+				"Text" => _('Please enter the group\'s name.')
+			),
+			'description' => array(
+				"Headline" => _('Description'), 'attr' => 'description',
+				"Text" => _('Group description. If left empty group name will be used.')
+			),
+			'info' => array(
+				"Headline" => _('Notes'), 'attr' => 'info',
+				"Text" => _('Additional notes to describe this entry.')
+			),
+			'mail' => array(
+				"Headline" => _('Email address'), 'attr' => 'mail',
+				"Text" => _('The list\'s email address.')
+			),
+			'member' => array(
+				"Headline" => _('Members'), 'attr' => 'member',
+				"Text" => _('This is a list of members of this group.')
+			),
+		);
+		// configuration settings
+		$configContainer = new htmlTable();
+		$configContainerHead = new htmlTable();
+		$configContainerHead->addElement(new htmlOutputText(_('Hidden options')));
+		$configContainerHead->addElement(new htmlHelpLink('hiddenOptions'));
+		$configContainerOptions = new htmlTable();
+		$configContainer->addElement($configContainerHead, true);
+		$configContainerOptions->addElement(new htmlTableExtendedInputCheckbox('windowsGroup_hidemail', false, _('Email address'), null, false));
+		$configContainer->addElement($configContainerOptions, true);
+		$return['config_options']['all'] = $configContainer;
+		// upload fields
+		$return['upload_columns'] = array(
+		);
+		// available PDF fields
+		$return['PDF_fields'] = array(
+			'cn' => _('Group name'),
+			'description' => _('Description'),
+			'info' => _('Notes'),
+			'member' => _('Members'),
+		);
+		if (!$this->isBooleanConfigOptionSet('windowsGroup_hidemail')) {
+			$return['PDF_fields']['mail'] = _('Email address');
+		}
+		return $return;
+	}
+
+	/**
+	* This function fills the $messages variable with output messages from this module.
+	*/
+	public function load_Messages() {
+		$this->messages['cn'][0] = array('ERROR', _('Group name'), _('Group name contains invalid characters. Valid characters are: a-z, A-Z, 0-9 and .-_ !'));
+		$this->messages['cn'][1] = array('ERROR', _('Account %s:') . ' windowsGroup_cn', _('Group name contains invalid characters. Valid characters are: a-z, A-Z, 0-9 and .-_ !'));
+		$this->messages['mail'][0] = array('ERROR', _('Email address'), _('Please enter a valid email address!'));
+		$this->messages['mail'][1] = array('ERROR', _('Account %s:') . ' windowsGroup_mail', _('Please enter a valid email address!'));
+	}
+
+	/**
+	 * Returns the HTML meta data for the main account page.
+	 * 
+	 * @return htmlElement HTML meta data
+	 */
+	public function display_html_attributes() {
+		$container = new htmlTable();
+		$this->addSimpleInputTextField($container, 'cn', _('Group name'), true);
+		$this->addSimpleInputTextField($container, 'description', _('Description'), false);
+		if (!$this->isBooleanConfigOptionSet('windowsGroup_hidemail')) {
+			$this->addSimpleInputTextField($container, 'mail', _('Email address'), false);
+		}
+		// group members
+		$container->addElement(new htmlSpacer(null, '10px'), true);
+		$container->addElement(new htmlOutputText(_("Group members")));
+		$container->addElement(new htmlAccountPageButton(get_class($this), 'user', 'open', _('Edit members')));
+		$container->addElement(new htmlHelpLink('member'), true);
+		$memberList = array();
+		if (isset($this->attributes['member'])) {
+			for ($i = 0; $i < sizeof($this->attributes['member']); $i++) {
+				$memberList[] = $this->attributes['member'][$i];
+			}
+			usort($memberList, 'compareDN');
+		}
+		$members = new htmlTable();
+		$members->alignment = htmlElement::ALIGN_RIGHT;
+		$members->colspan = 3;
+		for ($i = 0; $i < sizeof($memberList); $i++) {
+			$member = new htmlOutputText(getAbstractDN($memberList[$i]));
+			$member->alignment = htmlElement::ALIGN_RIGHT;
+			$members->addElement($member, true);
+		}
+		$container->addElement(new htmlOutputText(''));
+		$container->addElement($members, true);
+		return $container;
+	}
+
+	/**
+	* Processes user input of the primary module page.
+	* It checks if all input values are correct and updates the associated LDAP attributes.
+	*
+	* @return array list of info/error messages
+	*/
+	public function process_attributes() {
+		$return = array();
+		// cn
+		$this->attributes['cn'][0] = $_POST['cn'];
+		$this->attributes['sAMAccountName'][0] = $_POST['cn'];
+		if (!get_preg($_POST['cn'], 'groupname')) {
+			$return[] = $this->messages['cn'][0];
+		}
+		// description
+		$this->attributes['description'][0] = $_POST['description'];
+		// email
+		if (!$this->isBooleanConfigOptionSet('windowsGroup_hidemail')) {
+			$this->attributes['mail'][0] = $_POST['mail'];
+			if (!empty($_POST['mail']) && !get_preg($_POST['mail'], 'email')) {
+				$return[] = $this->messages['mail'][0];
+			}
+		}
+		return $return;
+	}
+	
+	/**
+	* This function will create the meta HTML code to show a page to change the member attribute.
+	* 
+	* @return htmlElement HTML meta data
+	*/
+	function display_html_user() {
+		$return = new htmlTable();
+		// show list of possible new members
+		if (isset($_POST['form_subpage_' . get_class($this) . '_user_select']) && isset($_POST['type'])) {
+			$options = array();
+			$filter = get_ldap_filter($_POST['type']);
+			$entries = searchLDAPByFilter($filter, array('dn'), array($_POST['type']));
+			for ($i = 0; $i < sizeof($entries); $i++) {
+				$entries[$i] = $entries[$i]['dn'];
+			}
+			// sort by DN
+			usort($entries, 'compareDN');
+			for ($i = 0; $i < sizeof($entries); $i++) {
+				if (!isset($this->attributes['member']) || !in_array($entries[$i], $this->attributes['member'])) {
+					$options[getAbstractDN($entries[$i])] = $entries[$i];
+				}
+			}
+			$size = 20;
+			if (sizeof($options) < 20) $size = sizeof($options);
+			$membersSelect = new htmlSelect('members', $options, array(), $size);
+			$membersSelect->setHasDescriptiveElements(true);
+			$membersSelect->setMultiSelect(true);
+			$membersSelect->setRightToLeftTextDirection(true);
+			$membersSelect->setSortElements(false);
+			$membersSelect->setTransformSingleSelect(false);
+			$return->addElement($membersSelect, true);
+			$buttonTable = new htmlTable();
+			$buttonTable->addElement(new htmlAccountPageButton(get_class($this), 'user', 'addMembers', _('Add')));
+			$buttonTable->addElement(new htmlAccountPageButton(get_class($this), 'user', 'cancel', _('Cancel')));
+			$return->addElement($buttonTable);
+			return $return;
+		}
+		// show existing members
+		$membersTemp = array();
+		if (isset($this->attributes['member'])) {
+			$membersTemp = $this->attributes['member'];
+		}
+		// sort by DN
+		usort($membersTemp, 'compareDN');
+		$members = array();
+		for ($i = 0; $i < sizeof($membersTemp); $i++) {
+			$members[getAbstractDN($membersTemp[$i])] = $membersTemp[$i];
+		}
+		$size = 20;
+		if (isset($this->attributes['member']) && (sizeof($this->attributes['member']) < 20)) {
+			$size = sizeof($this->attributes['member']);
+		}
+		if (sizeof($members) > 0) {
+			$membersSelect = new htmlSelect('members', $members, array(), $size);
+			$membersSelect->setHasDescriptiveElements(true);
+			$membersSelect->setMultiSelect(true);
+			$membersSelect->setRightToLeftTextDirection(true);
+			$membersSelect->setSortElements(false);
+			$membersSelect->setTransformSingleSelect(false);
+			$return->addElement($membersSelect, true);
+			$removeButton = new htmlAccountPageButton(get_class($this), 'user', 'remove', _('Remove selected entries'));
+			$removeButton->colspan = 3;
+			$return->addElement($removeButton, true);
+			$return->addElement(new htmlOutputText(' ', false), true);
+		}
+		$types = $_SESSION['config']->get_ActiveTypes();
+		$options = array();
+		$optionsSelected = array();
+		for ($i = 0; $i < sizeof($types); $i++) {
+			$options[getTypeAlias($types[$i])] = $types[$i];
+			if ($types[$i] == 'user') {
+				$optionsSelected[] = $types[$i];
+			}
+		}
+		$typeTable = new htmlTable();
+		$typeTable->addElement(new htmlOutputText(_('Add entries of this type:') . ' '));
+		$typeSelect = new htmlSelect('type', $options, $optionsSelected);
+		$typeSelect->setHasDescriptiveElements(true);
+		$typeTable->addElement($typeSelect);
+		$typeTable->addElement(new htmlAccountPageButton(get_class($this), 'user', 'select', _('Ok')));
+		$return->addElement($typeTable, true);
+		$return->addElement(new htmlOutputText(' ', false), true);
+		$return->addElement(new htmlAccountPageButton(get_class($this), 'attributes', 'membersBack', _('Back')));
+		return $return;
+	}
+	
+	/**
+	* Processes user input of the members page.
+	* It checks if all input values are correct and updates the associated LDAP attributes.
+	*
+	* @return array list of info/error messages
+	*/
+	function process_user() {
+		$return = array();
+		if (isset($_POST['form_subpage_' . get_class($this) . '_user_remove']) && isset($_POST['members'])) {
+			$members = array_flip($this->attributes['member']);
+			for ($i = 0; $i < sizeof($_POST['members']); $i++) {
+				if (isset($members[$_POST['members'][$i]])) {
+					unset($members[$_POST['members'][$i]]);
+				}
+			}
+			$this->attributes['member'] = array_values(array_flip($members));
+		}
+		elseif (isset($_POST['form_subpage_' . get_class($this) . '_user_addMembers']) && isset($_POST['members'])) {
+			for ($i = 0; $i < sizeof($_POST['members']); $i++) {
+				$this->attributes['member'][] = $_POST['members'][$i];
+				$this->attributes['member'] = array_unique($this->attributes['member']);
+			}
+		}
+		// check input
+		if (!isset($_POST['form_subpage_' . get_class($this) . '_user_select'])) {
+			if (!$this->isBooleanConfigOptionSet('groupOfNames_membersOptional')) {
+				if (!isset($this->attributes['member']) || (sizeof($this->attributes['member']) < 1)) {
+					$return[] = $this->messages['member'][0];
+				}
+			}
+		}
+		return $return;
+	}
+
+	/**
+	* In this function the LDAP account is built up.
+	*
+	* @param array $rawAccounts list of hash arrays (name => value) from user input
+	* @param array $ids list of IDs for column position (e.g. "posixAccount_uid" => 5)
+	* @param array $partialAccounts list of hash arrays (name => value) which are later added to LDAP
+	* @param array $selectedModules list of selected account modules
+	* @return array list of error messages if any
+	*/
+	public function build_uploadAccounts($rawAccounts, $ids, &$partialAccounts, $selectedModules) {
+		$messages = array();
+		for ($i = 0; $i < sizeof($rawAccounts); $i++) {
+			// add object class
+			if (!in_array('group', $partialAccounts[$i]['objectClass'])) $partialAccounts[$i]['objectClass'][] = 'group';
+		}
+		return $messages;
+	}
+	
+	/**
+	* Returns a list of PDF entries
+	*/
+	public function get_pdfEntries() {
+		$return = array();
+		$this->addSimplePDFField($return, 'cn', _('Group name'));
+		$this->addSimplePDFField($return, 'description', _('Description'));
+		$this->addSimplePDFField($return, 'info', _('Notes'));
+		$this->addSimplePDFField($return, 'mail', _('Email address'));
+		// members
+		if (sizeof($this->attributes['member']) > 0) {
+			$memberList = array();
+			if (isset($this->attributes['member']) && is_array($this->attributes['member'])) {
+				$memberList = $this->attributes['member'];
+			}
+			usort($memberList, 'compareDN');
+			$return[get_class($this) . '_member'][0] = '' . _('Members') . '| ' . $memberList[0] . ' | 
';
+			for ($i = 1; $i < sizeof($memberList); $i++) {
+				$return[get_class($this) . '_member'][] = '| ' . $memberList[$i] . ' | 
';
+			}
+		}
+		return $return;
+	}
+
+}
+
+
+?>