Welcome to TechNet Blogs Sign in | Join | Help

provtest AllAboutHMC.xml

HMC releated matters.
HMC Resource Management - Part #2 - HMC Resource Management and Active Directory

Things have been busy for me and i haven't had the time to complete this series in a timely fashion. In part #1, we briefly talked about what’s in the PlanManager and ResourceManager databases from a very high level. In the next few parts, we will go in a little bit further to discuss how HMC manage the resource allocation in Exchange, SharePoint and also OCS.

Before we get into that, I think it is essential to talk about how HMC database, PlanManager is linked with the Active Directory. It is important to understand that it isn't the purpose of this article to discuss about the database schema but I will discuss briefly how they are linked.

The best way to explain this, in my humble opinion is to walk through the provisioning process. As we walk through them, I will explain how the data is being stored in the database and then I will provide some examples and discuss about some of the tables and their purpose.

As you all know, the first thing you need to do before mailbox enable a user, or enabling the user for OCS or creating the appropriate SharePoint site for the organization is to create the organization itself and the appropriate users for that organization. In the HMC world, an Organization means a company and all the users and groups in that organization are grouped under an Active Directory container or Organizational Unit (OU).

So, let's take a closer look and see what is being inserted into the database. Note:

Creating Organization

Procedure: To create an organization, you called Hosted Active Directory::CreateOrganization.

1.       What is created in Active Directory? When this procedure is called,

a.       It creates the Organization OU container in the Hosting container.

b.      it will also create some of the system container and objects such as,

_Private

Allusers@<org>

Admins@<org>

CSRAdmins@<org>

c.       AD object creation is one thing; the procedure will also stamp the appropriate permissions to ensure that only users in this Org should have access to objects underneath this OU.

 

2.       What you should know about otherWellKnownObjects? OtherWellKnownObjects are heavily used in HMC to 'extend' the Active Directory schema to link with other objects. For example, MPS will use otherWellKnownObjects to link the _Private folder, the Admins, the CSRAdmins, the parent folder to this organization. This is important to know because a number of the procedures in MPS will use this reference.

Note: You should know that however Allusers@<org> are not 'linked' in this otherWellKnownObjects. This is one of the common issues where renaming of Org will cause problem.

 

3.       What is in the database then? There aren't many things being put into the database during Org creation. Because otherWellKnownObjects are used to link most of the things like Admins, CSRAdmins and _Private folder, there is no reason to keep any one of those in the database. Hence, you won't any record of those admins account in the database.

PlanManager is the only database that you need to look at this point. When an organization is created, it will create a record in the Customers table in the PlanManager database. Say if you create a new Organization called TestOrg, if you perform a query like this,

SELECT * FROM [PlanManager].[dbo].[Customers] WHERE CommonName = 'TestOrg'

You will one record being retrieved showing you the following fields,

CustomerID -> This will match it to the objectGUID of the OU container or the object.

ParentID -> This will match it to the object GUID of the Parent OU or holding OU

StatusTypeCode -> This will tell you if this Org or object is still active or enabled.

CustomerTypeCode -> This will tell you the type of Object is this. For example,

        - BU is business user

        - BZ is business organization

        - CT is contact object

        - GP is group object

        - CU is consumer user

        - RO is Reseller organization

        - IR is Information Worker

CommonName -> This stores the name of the organization. If it is a user, it will store the user email or contact email for Contact object or group name if it is a group object.

Note: You should know that Customer table does not just contain the Organization OU object. It consists of almost everything that is created in the Active Directory, such as OU, User, Contact, Distribution Groups.

Also, the database has been designed to cater for customization and extension. You can define your own type if necessary and you can find out all the types that are available from the CustomerTypes table.

The above doesn't cover in detail everything is being executed by the procedure and it also does not cover some of the hidden things written into the database. For example, there is difference between creating a reseller organization and a normal business organization. A consumer organization is also different compared to a business organization. You can see they are being differentiated by the CustomerTypeCode. You should also know when you create a Business Org for example, it will also subscribe the Organization to a BusinessPlan which is a default plan for Business.

In short, the mapping is by GUID and it creates only the OU record and subscribed the OU to a business plan if it is a business Org. Now, in the later parts, I will also go a little bit deeper into the plans in the database and how each service like Exchange has Org plan as well as user plan. For now, from Active Directory standpoint, it is quite straightforward and it won't touch ResourceManager database at all.

Creating a User

1.       What is created in Active Directory? When this procedure is called,

a.       It creates the user object in the Organization OU. Obviously prior to executing the creation, it will perform some checks such as whether the path being passed in is correct or not.

b.      It doesn't create anything else other than the user object but what it does do is that will insert this user to the appropriate security groups such as the AllUsers group created during the Org creation.

c.       It will then perform the appropriate permissions hardening.

 

2.       What is in the database then? Creation of the AD user object will create a record on the Customer table in the PlanManager database.

 

Creating a Group

1.       What is created in Active Directory? When this procedure is called,

a.       It creates the group object in the Organization OU. Obviously prior to executing the creation, it will perform some checks such as whether the path being passed in is correct or not.

b.      It will create a group object in the Active Directory.

c.       It will then perform the appropriate permissions hardening.

2.       What is in the database then? Creation of the AD group object will create a record on the Customer table in the PlanManager database.

 

Creating a Contact

1.       What is created in Active Directory? When this procedure is called,

a.       It creates the contact object in the Organization OU. Obviously prior to executing the creation, it will perform some checks such as whether the path being passed in is correct or not.

b.      It doesn't create anything else other than the contact object but what it does do is that will insert this user to the appropriate security groups such as the AllUsers group created during the Org creation.

c.       It will then perform the appropriate permissions hardening.

 

2.       What is in the database then? Creation of the AD contact object will create a record on the Customer table in the PlanManager database.

 

So, there you go. I think it is pretty straightforward. As you can see, creation of objects in Active Directory, from MPS standpoint does not create anything outside of PlanManager database. It does not touch the ResourceManager database at all. You should also see that all the records created, uses the Active Directory object GUID as the primary reference in the MPS's PlanManager database.

 

Hosted Messaging and Collaboration Knowledge Base Articles

This page used to provide just the HMC related updates but now it has been updated to provide the specific product service packs, rollup updates, hotfixes that have been tested by the HMC product group. With this, I will no longer provide any quarterly list of updates on what hotfixes have been tested like I used to. :) Here is the link,

http://technet.microsoft.com/en-us/serviceproviders/cc563918.aspx

For example, you can see the Update Rollup 9 for Exchange Server 2007 Service Pack 1 (KB970162) have been tested for HMC 4.x.

HMC Resource Management - Part #1 - PlanManager and ResourceManager – Overall Concept

I believe one of the most mysterious parts of HMC is about the MPS engine and the Resource Management databases. Between last December and January, I blogged about how different products (Exchange, SharePoint and OCS) integrate in a HMC Solution. However, understanding just the integration points without knowing the resource management portion definitely does not paint a complete picture of what HMC is.

Since then, I have received requests to discuss a bit about the resource management in HMC and what those databases that shipped with HMC are storing and being used. So, in my next few entries, I intend to spend some time talking about the following,

1.       PlanManager and ResourceManager – Overall Concept

2.       HMC Resource Management and Active Directory

3.       HMC Resource Management and Exchange

4.       HMC Resource Management and Windows SharePoint Services

5.       HMC Resource Management and Office Communication Servers

The aim for this is not to go crazily in-depth nor is it meant to discuss the full database schema and etc. I realize most of our HMC administrators come from an infrastructure background (in fact, mostly from AD and Exchange) and find it difficult to manage the environment (or sometime even fearful to do anything) because there has been very little about how those databases work in the HMC environment.

My objective is to help the HMC administrators to better understand the relationship and hence able to better plan for recovery, database integrity checking, have better process on how to troubleshoot and handling issues and not blindly go into a HMC environment doing things that may potentially mess up the environment. For example, moving mailbox from one database to another using cmdlets, reconnecting a mailbox to another user, re-enabling sip user and etc.

Let’s get started. This introduction is going to be something extremely light. I want to talk briefly about the purposes of these databases and what things are being stored in it on a very high level.

When you install HMC 4.5, it creates 5 databases. They are MPFConfig, MPFAudit, MPFTranLogData, PlanManager and ResourceManager databases.

The first 3 are used by the MPF engine and I will talk about that some other time as there are tons to talk about too on those. Some of those databases can be used to better analyze the history of all the transactions, used for better performance analysis and also to configure some advance configurations not shown in the interface.

For now, we will discuss about the last 2 databases, PlanManager and ResourceManager.

 

PlanManager Database

PlanManager used to be called HeCustomerDB in HMC 3.5. While, the concept hasn’t changed much since HMC 3.5, I am going to refer to just the PlanManager which is what HMC 4.5 is using today. There is obviously a big change from HMC 3.5 to HMC 4.5 such as introduction of organization and user plans in HMC 4.5 and also support of different version of the hosted products. So those have resulted in additional categories and features and etc.

PlanManager stores more than just plans (I personally think it should be named something else). On a high level, it has the following,

1.       Active Directory Object reference. It consists of all the references to all the objects created in AD. Such as, OUs, Users, Contacts, Groups, SMTP domains. Something that I will go into greater depth in when I discuss about the Resource Management and Active Directory.

 

2.       Mailbox assignment. It also consists of information of mailbox GUID linkage to the respective AD objects. I will also discuss that further in the Resource Management and Exchange later.

 

3.       Plans information. It consists of all the plan information, including all the features of each plan. For example what mail feature or quota is tied to which plan. Different product tends to be slightly different and I will discuss that accordingly when I discuss about different products.

 

4.       Plan Assignment. It also consists of what plans are those organizations assigned to.

 

I think it should also be noted that you can further ‘extend’ the capability of the database yourself. Such as you can add additional feature, add in additional customer type or asset type and etc. which your control panel can use if needed.

 

ResourceManager Database

ResourceManager database right now is primarily used by Hosted Exchange only. The complexity and the need of tracking the resource allocation for individual organization, for public folder, for OAB, for individual mailbox user, for different mailbox store created has created the need to track that on a separate database.

As I walk through different products in the next few entries, you may realize that WSS and OCS are not using the ResourceManager database as they are less complex in terms of the needs for resource allocation and management.

ResourceManager, on a high level has the following,

1.       Mailbox Stores and their sizes. It consists of all the mailbox stores and their available size.

2.       Public Folder Stores and their sizes.

3.       OAB Servers.

4.       Public Folder allocation for each organization.

5.       Organization’s OAB assignment

6.       Organizations and their allocated size.

7.       Organizations and their assigned mail stores.

8.       Individual mailbox and the mailbox size assigned to them.

 

Now, I should also highlight that the reference to AD objects are often using GUID and I also blogged about this earlier this month (http://blogs.technet.com/provtest/archive/2009/07/15/matching-the-guid-from-ad-with-mps.aspx).

There you go; this is a simple overview of the 2 mysterious databases that has so often make HMC looks more complicated than it really is.  I believe once you understand what’s in the databases, you will find that it isn’t that bad at all.

 

Troubleshooting HMC OCS’s Address Book Segregation

HMC 4.5 has been out for a while now. We are beginning to see more and more people deploying OCS into the HMC environment as the concept of using IM as one of the corporate communication tools getting better acceptance.

One of the most common issues when setting up the OCS in HMC is configuring the address book segregation. To be honest, that’s really the only major customization you need to do to have OCS in HMC environment. If you want to know more about what are the customizations we have in HMC, you can refer to my previous blog, HMC 4.5 and Office Communications Server 2007.

In my previous blog, I talked about the address book segregation customization introduced by HMC into the OCS 2007 on a very high level. Here, we will take a closer look at the mechanism, how it should work and what are the things to look at if it doesn’t work.

1.       Address Book Generation or Synchronization.

So, firstly, in order for you to have address book segregation, obviously you need to have different address book for different organizations, just like Global Address List in Hosted Exchange. Once you have completed the installation of the OCS servers, by default, it generates one address book. Think of it like the Default Global Address Book in Exchange. Now, we really don’t want that. If you have that, you should delete those to avoid confusion.

Go to the server where you have your OCS address book, such as \\OCSPOOLWEB01\ABS

If there are files there, you should remove them all.

Then by following one of the deployment steps in HMC deployment guide, Procedure W08-DWHO.66: To enable Address Book Isolation, to be specific, you will use a tool called ABSConfig.exe from the OCS  2007 ResKit and through WMI to enable the feature called Partition ABS data by Organizational Unit and create individual ABS files per OU.

Essentially, with this option enabled, when the OCS tries to perform the address book synchronization, it will generate address book based on OU instead of everyone in one big address book. So, if you want to find out if the address book generation is working accordingly right now (assuming you currently have sip enabled users in your environment), look at the ABS output location. It should have a structure following your domain OU like the following,

\\ OCSPOOLWEB01

\ABS

            \fabrikam.com

                        \Hosting

                                    \ConsolidatedMessanger

                                                \AlpineSkiHouse

                                                            *.dabs

                                                            *.lsabs

                                                \Tailspin

                                                            *.dabs

                                                            *.lsabs

 

If it does not have any of the OU structure and just have the plain .lsabs and .dabs files in the root of ABS folder, then it probably means the feature has not been activated.

You can force a call to generate or synchronize address book by calling the following,

C:\Program Files\Microsoft Office Communication Server 2007\Server\Core>ABServer.exe -syncNow

Of course, if you have absolutely zero sip enabled users in the environment then nothing will be generated.

 

2.       Address Book Redirection

Once the address book has been generated, of course the next thing is to make sure that it should redirect to the user to the appropriate address book according to the location of the user. This is documented in the following steps, Procedure W08-DWHO.68: To enable redirection on the external Address Book Website.

Now, here I want to highlight a couple of things which I think has kind of being left out in the deployment guide.

a.       Configuring Redirection. The deployment guide only request you to configure web.config file in the C:\Program Files\Microsoft Office Communications Server 2007\Web Components\Address Book Files\Ext\Handler

 

This is the External handler. This handler will be used only if the connection is through external (based on the configuration of the Office Communicator client). This is where sometimes things get slightly confusing because when you are setting up stuff, you tend to try connecting through the internal server name and that will trigger the internal handler instead.

 

So, if you may actually want to configure the internal handler as well, which is the web.config file in C:\Program Files\Microsoft Office Communications Server 2007\Web Components\Address Book Files\Int\Handler

 

So, once all these have been setup, when you try to download the address book from Office Communicator, it will send you to the IIS location containing the address book. Authentication will take place and based on the authentication, it will redirect you to the appropriate path containing the address book. If you look at the IIS log, you find something like the following,

 

2009-06-05 10:14:04 W3SVC1 192.168.45.20 GET /Abs/Int/Handler/D-0c03-0c04.lsabs - 443 - 192.168.45.1 Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+5.2;+.NET+CLR+1.1.4322;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506.30;+MS-RTC+LM+8) 401 2 2148074254

 

2009-06-05 10:14:04 W3SVC1 192.168.45.20 GET /Abs/Int/Handler/D-0c03-0c04.lsabs - 443 HMC45\johnc_AlpineSkiHouse 192.168.45.1 Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+5.2;+.NET+CLR+1.1.4322;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506.30;+MS-RTC+LM+8) 302 0 0

 

2009-06-05 10:14:04 W3SVC1 192.168.45.20 GET /Abs/Int/Files/hmc45.com/Hosting/ConsolidatedMessenger/AlpineSkiHouse/D-0c03-0c04.lsabs - 443 HMC45\johnc_AlpineSkiHouse 192.168.45.1 Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+5.2;+.NET+CLR+1.1.4322;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506.30;+MS-RTC+LM+8) 200 0 0

 

 

Note: See how Communicator will first request for /Abs/Int/Handler/D-0c03-0c04.lsabs and then authentication happened and when it finally got authenticated, it got redirected (302) and it goes to /Abs/Int/Files/hmc45.com/Hosting/ConsolidatedMessenger/AlpineSkiHouse/D-0c03-0c04.lsabs.

 

b.      Configuring Application Pool account. Now, everything is in IIS and the redirection happens in IIS through an application pool created by OCS installation.

 

If you note the IIS log above, you will find that the Office Communicator client isn’t the one that will send you to the exact path but it was the application pool that is serving the directory that figures out which path to redirect you to.  

 

If you right click at the application pool (LSGroupExpAppPool) in the IIS, you will find the identity running this pool is RTCComponentService.

 

This is important, in order for the redirection to work; the RTCComponentService must have the appropriate permissions to know where those accounts are from (when they authenticate). By default, this account has no permission to the Hosting container in HMC because of how we harden the Hosting container. Hence, in order for it to work, RTCComponentService should be part of the Windows-based hosting Service Accounts. If it is not there, you need to add it to the group and then restart the IIS.

 

c.       ABS location and connection.

 

The last thing to check is how the IIS able to connect to the address book file share. If you look at the Abs\Ext\Files properties in IIS Manager, you will find that it is pointing to a network directory for the ABS. Click on Connect As button to find out what user it is using to connect to the file share. It is important to make sure that the password for that user is correctly set AND also that the account has not been disabled or locked out.

 

 

3.       Quick Tests using Internet Explorer

To find out if the redirection is working.

a.       Find out a .lsabs file in the ABS folder, say in  

 

\\OCSPOOLWEB01\ABS\fabrikam.com\Hosting\ConsolidatedMessanger\AlpineSkiHouse\F-0b72.lsabs

 

b.      Then go to the web site where your address book is being published, say, https://web.consolidatedmessenger.com/Abs/Ext/Handler/F-0b72.lsabs

 

c.       It should prompt you for user name and password. Enter a sip enabled user in the AlpineSkiHouse.

 

d.      It will then redirect you to  https://web.consolidatedmessenger.com/Abs/fabrikam.com/Hosting/ ConsolidatedMessenger/Alpineskihouse/F-0b72.lsabs and allow you to download the file.

 

e.      If it doesn’t work, then check the IIS log to find out why.

 

 

Yes, you should use web-based distribution OAB.

HMC has been in the market for a while and as it grows, we are beginning to see many HMC providers are expanding their infrastructure and having more users and companies subscribing to their environment.

I also observed that the growth is especially obvious recently with the current economy situation where it makes so much sense for many companies to move their email, their SharePoint and corporate IM to the hosted model because of low startup cost and a low and predictable maintenance cost. Not to mention, it is much more feasible to do so nowadays with the current bandwidth and technology.

I noticed that the growth is particularly strong in the MAPI space. Customers are demanding better and richer Outlook email, communication and collaboration experience which HMC offers today rather than those simple POP3 and IMAP4 email technology.

Now, because of the growth in MAPI organizations, I feel that it is probably important for me to briefly talk about the need to move towards web-based distribution OAB instead of continuing scaling out the number of OAB Public Folder server.

We all know that in order to host MAPI clients, having Outlook to access the address list offline, we need to make sure each organization has an Offline Address Book available to be downloaded. Prior to Exchange Server 2007, the storage of the OAB is only in Public Folder Server. In HMC, it is recommended to dedicate Public Folder servers to host OAB and each OAB PF server shouldn’t have anything more than 1000 OABs. If you have more than that, you should either scale out by creating a new OAB PF server to host the new OABs or you can consider increasing the MaxPageSize in Active Directory. The latter, in my opinion is slightly dangerous as it may potentially generate performance impact to your whole Active Directory infrastructure.

So, everything sounds logical here, what’s the concern here? Well, the primary concern is that each Public Folder OAB created consumes a Replication ID (ReplID) in the Public Folder Hierarchy. The Replication ID has a limitation of approximately 32k. What does that mean? It means if you have more than 32k OABs in the environment, you may have problem with your OAB generation and download if they are in Public Folder.

It should also be noted that ReplIDs do not get cleaned up. Once it is created, it stays in the Public Folder Hierarchy until you refresh the Public Folder Hierarchy (which can be a rather tedious exercise) even if you delete the OAB. So, it means, if you create a new OAB and then delete it, it will still take up 1 count.

How do you know how many ReplID count you have now? Easy, go to your Exchange Server, look at the perfmon counter, MSExchangeIS Public\ReplID Count, you should be able to find your ReplID Count there.

I know some of you are probably getting worried knowing that there is a limit there. Good news is, there is a default quota limit being set as documented in this article, you should also take a look at this article, http://technet.microsoft.com/en-us/library/bb851493.aspx. So, chances are, you probably know about this ReplID by now if you have exceeded the limit.

You can definitely increase the default quota limit to allow things to get going as long as it is not over 32k. The long term solution is to move to Web-based distribution which doesn’t have such limitation.

Obviously the caveats of moving towards a pure Web-based distribution OAB is that the environment needs to be upgraded to HMC 4.5 (if you are already running HMC 4.0, moving to 4.5 is a piece of cake but if you are running HMC 3.5, then it needs a bit of planning but not end of the world) and it requires the client to be Outlook 2007 and above. Older version of Outlook will still work for all their functionalities except when it comes to downloading Offline Address Book (OAB) and also any feature that may require OAB (such as selecting contact when you are offline).

Consider the fact that the process to reset the Replication ID should you exceed the limit may require you to reset the whole Public Folder Hierarchy; I will start thinking

1.       Switching all my clients to Outlook 2007 only (after all, there is no reason not to do that as Outlook 2007 provides better OOF functionalities and also better free busy and availability data).

2.       Move to HMC 4.5 if you haven’t already done so.

3.       Then, enable Web-Based Distribution OAB and use that only. You may need to change your control panel to set it to only create Web-based Distribution OAB or something.

It should be noted that this is only applicable to OAB creation; it is not applicable to the normal Public Folder creation.

So, there you go. If you are not using Web-based Distribution OAB today in your HMC environment and you are anticipating rapid growth, you should.

Tip: How do you find out who are the users in your HMC environment doing MAPI access?

Typically in a corporate environment, to find out who are the users using Outlook MAPI access and the version, you can Microsoft Exchange Server User Monitor, or ExMon (http://www.microsoft.com/downloads/details.aspx?familyid=9A49C22E-E0C7-4B7C-ACEF-729D48AF7BC9&displaylang=en).

ExMon is really good to gather real time data but may not be good tool if you want to find out who has been doing MAPI access for the past say 3 months. Unfortunately, there is really no good tool to do that right now in a corporate environment. In HMC, the story may be a bit different because one of the good things about Hosted Exchange in HMC is that all client traffics will go through CAS, whether it is MAPI, POP3, OWA and etc.

In HMC, MAPI access comes in the form of Outlook Anywhere or RPC over HTTPs. Because of that, we can harvest the data by looking at the IIS log. When it comes to reviewing the IIS Log, you can't run away from tapping into the power of the LogParser. All you have to do is to identify the specific pattern for example, the following should give you a list of users that have logged on through RPC over HTTPs or Outlook Anywhere.

Logparser.exe" -i:IISW3C -o:CSV "SELECT DISTINCT cs-username from ex090402.log where cs(User-Agent) LIKE '%MSRPC%'"

Of course, you can also run it against a list of files by doing *.log instead of specifying a specific log file.

If you can identify other patterns such as Outlook 2007 will always try to connect to the web services (whereas older versions of Outlook do not do that), then you can do the same as well such as the following,

 Logparser.exe" -i:IISW3C -o:CSV "SELECT DISTINCT cs-username from ex090402.log where cs-uri-stem LIKE '%Exchange.asmx%'"

There are other examples but I will leave it to you all to explore. You can find more examples here too, http://msexchangeteam.com/archive/2007/09/12/446982.aspx.

Messing with otherWellKnownObjects

otherWellKnownObject attributes have been widely used in HMC as a cross reference as well as very much as a kind of a poor man’s AD schema extension strategy. J This blog aims to discuss it and also provide some ways to work with this attribute using HMC procedures.

Firstly, here is a list of common otherWellKnownObjectGUID in HMC,

List of common otherWellKnownObjectGUID in HMC

  • 7DEF010C6019A1458068D74AD1A3C1FA
    •  name="FolderUsers"
    • Eg.:CN=FolderUsers@alpineskihouse.com,OU=ALPINESKIHOUSE,OU=CONSOLIDATEDMESSENGER,OU=Hosting,DC=fabrikam,DC=com
  • A276E3A170F0C24699770F593818501E
    • name="FolderAdmins"
    • Eg.:CN=FolderAdmins@alpineskihouse.com,OU=ALPINESKIHOUSE,OU=CONSOLIDATEDMESSENGER,OU=Hosting,DC=fabrikam,DC=com
  • D22DFCC5B73645E99E16C9AD3D61F34F
    • name="OfflineAddressList"
    • Eg.:CN=ALPINESKIHOUSE OAL,CN=All Offline Address Lists,CN=Address Lists Container,CN=HMC45,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=fabrikam,DC=com
  • 9E444526CB6F4D5C9A59C9A84E26B627
    • name="AddressList"
    • Eg.:CN=ALPINESKIHOUSE AL,CN=All Address Lists,CN=Address Lists Container,CN=HMC45,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=fabrikam,DC=com
  • 89FB25B7DF784FC198A493E2E8A0EE7E
    • name="GlobalAddressList"
    • Eg.:CN=ALPINESKIHOUSE GAL,CN=All Global Address Lists,CN=Address Lists Container,CN=HMC45,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=fabrikam,DC=com
  • 4619BE598BF441DB8C9DB0482E62E386
    • name="MultiGroupPointer"
    • Eg.:CN=MultiGroup,CN=_Private,OU=ALPINESKIHOUSE,OU=CONSOLIDATEDMESSENGER,OU=Hosting,DC=fabrikam,DC=com
  • EA755D448CE64157A20E82B7CCBE14B0
    • name="OrgType"
    • Eg.:CN=customer,CN=WatOrgTypes,CN=_Private,OU=Hosting,DC=fabrikam,DC=com
  • 3B6FF4FA8AA248039AD8F9493A43B704
    • name="ChildOrgCreators"
    • Eg.:CN=CSRAdmins@alpineskihouse.com,OU=ALPINESKIHOUSE,OU=CONSOLIDATEDMESSENGER,OU=Hosting,DC=fabrikam,DC=com
  • 65F37ECB46704F0E9300E1FB48E1096E
    • name="UserCreators"
    • Eg.:CN=Admins@alpineskihouse.com,OU=ALPINESKIHOUSE,OU=CONSOLIDATEDMESSENGER,OU=Hosting,DC=fabrikam,DC=com
  • 58888CFC8F7F430C8183102CD5758D81
    • name="ForeignOwnerOrg"
    • Eg.: OU=CONSOLIDATEDMESSENGER,OU=Hosting,DC=fabrikam,DC=com
  • CC016CF08DEF4EA4A05C9C54B198785A
    • name="ThisOrganizationRoot"
    • Eg.:OU=ALPINESKIHOUSE,OU=CONSOLIDATEDMESSENGER,OU=Hosting,DC=fabrikam,DC=com

 

How to reset the otherWellKnownObject using HMC procedure

Sometimes, you may find it necessary to reset the otherWellKnownObject for whatever reason such as you may accidentally remove the Offline Address Book. This may result in the otherWellKnownObject reference to be invalid.

You can set or reset the otherWellKnownObject attribute by running the following procedure,

Sample Request:

<request>

 

<procedure name="SetOtherWellKnownObject" description="Set WKO" access="private" type="write" perfEnabled="0" saveDataForRollback="0" auditEnabled="0">

                <procedureData>

                                <path>LDAP://OU=alpineskihouse,OU=consolidatedmessenger,OU=Hosting,DC=fabrikam,DC=com</path>

                                <GUID>9E444526CB6F4D5C9A59C9A84E26B627</GUID>

                                <referent>LDAP://CN=Alpineskihouse AL,CN=All Address Lists,CN=Address Lists Container,CN=HMC45,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=fabrikam,DC=com</referent>

                                <preferredDomainController>AD01.fabrikam.com</preferredDomainController>

                </procedureData>

                <before source="data" destination="procedureData" mode="insert"/>

                <execute namespace="Managed Active Directory" procedure="SetOtherWellKnownObject_" impersonate="2">

                                <before source="procedureData" sourcePath="path" destination="executeData"/>

                                <before source="procedureData" sourcePath="GUID" destination="executeData"/>

                                <before source="procedureData" sourcePath="referent" destination="executeData"/>

                                <before source="procedureData" sourcePath="preferredDomainController" destination="executeData"/>

                </execute>

               

</procedure>

</request>

 

 

 

 

If you wish to clear it, you just don’t set anything on the referent.

 

 

How to retrieve the otherWellKnownObject using HMC procedure

<request>

 

<procedure name="GetOtherWellKnownObject" description="Get WKO" access="private" type="write" perfEnabled="0" saveDataForRollback="0" auditEnabled="0">

                <procedureData>

                                <GUID>9E444526CB6F4D5C9A59C9A84E26B627</GUID>

                                <object>LDAP://OU=Alpineskihouse,OU=ConsolidatedMessenger,OU=Hosting,DC=Fabrikam,DC=com

                </object>

                                <preferredDomainController>AD01.fabrikam.,com</preferredDomainController>

                </procedureData>

               

                <execute namespace="Managed Active Directory" procedure="GetOtherWellKnownObject" impersonate="2">

                                <before source="procedureData" sourcePath="object" destination="executeData"/>

                                <before source="procedureData" sourcePath="GUID" destination="executeData"/>

                                <before source="procedureData" sourcePath="preferredDomainController" destination="executeData"/>

                </execute>

               

</procedure>

</request>

 

 

 

 

Sample VBScript to retrieve otherWellKnownObject

strDomain = "fabrikam.com"  

strWKGUID = "D22DFCC5B73645E99E16C9AD3D61F34F"

 

set oab = GetObject("LDAP://<WKGUID=" & _

                             strWKGUID & "," & _

                             "OU=alpineskihouse,OU=consolidatedmessenger,OU=Hosting,DC=fabrikam,DC=com" & ">" )

WScript.Echo oab.Get("distinguishedName")

 

 

 

 

Sample PowerShell to retrieve otherWellKnownObject

# The following script will retrieve all the OABs of each OU

 

$LDAP = "OU=Hosting,dc=hmc45, dc=com"

 

$preferredDC = "AD01.fabrikam.com"

$domain = "LDAP://" + $LDAP

$directoryEntry = New-Object System.DirectoryServices.DirectoryEntry $domain

 

$strWKGUID = "D22DFCC5B73645E99E16C9AD3D61F34F"

 

$query = new-object system.directoryservices.directorysearcher

$query.SearchRoot = $directoryEntry

$query.PageSize = 1000

$query.filter = ("(objectClass=organizationalUnit)")

$orgs = $query.findAll()

 

Foreach($org in $orgs)

{

                $org = $org.GetDirectoryEntry()

 

                $orgDN = $org.distinguishedName

                $orgName = $org.name

 

                $oab = New-Object DirectoryServices.DirectoryEntry "LDAP://<WKGUID=$strWKGUID,$orgDN>"

 

                If($oab.name -ne $null) {

                                "Org DN: $orgDN, "

                                "OAB: " + $oab.name

                               

                                "------------------------------------------"

                                "             "

                }

}

 

 

Matching the GUID from AD with MPS Databases

We all know how the PlanManager database and the ResourceManager database are used to keep track of plans and the relationship between MPS and the Active Directory. We know that each object in the Active Directory has unique objectGUID and hence the objectGUID is being referenced to by both databases.

 

Because objectGUID is unique, it is important to understand that recreating a user, even though it has all the similar display name, last name, password length and all other attributes, it will still be a different object altogether. Knowing this is important because this is how MPS maintain the reference and relationship between AD and MPS.

 

However, if you look at the database, you will realize that the reference of GUID can be somewhat confusing sometimes because depending on different databases, MPS stores the GUID in different format. I am going to attempt to demystify some of those confusions.

 

Let’s start. Most of the time, if the AD Object GUID is not being used as the primary key, then it is being stored as the short format (or unformatted GUID) such as this, a 32 digit alphanumeric (0-F)

 

78CD7DD959FCE840891BA6C698AF1C27

 

If it is being used as a primary key, then it is usually stored in the long format (or formatted GUID), such as this,

 

Also, a 36-digit alphanumeric (including hyphens)

 

7642104C-8DC8-3B4A-A421-A8EFD444CAEE

 

For example,

 

In PlanManager database

 

The Customer table uses the AD Object GUID as the primary key of the table. CustomerID refers to the object GUID of the AD object. The format is in the long GUID format.

 

The MailboxGUID is in the short format as it is referenced as an asset in the CustomerAsset table.

 

AD Items

Sample GUID format stored

OU\Organization Unit

7642104c-8dc8-3b4a-a421-a8efd444caee

User Object

f9924535-7be0-7240-bd26-48063e72a69c

MailboxGUID

78CD7DD959FCE840891BA6C698AF1C27

 

In ResourceManager database

 

All the GUID references are not primary keys of the table. They are being reference usually in instance_name, instance_location. Instead of using the AD object GUID as the primary key, the system will generate their own GUID such as resource ID, consumer ID as unique primary reference. That’s why you will see the reference to Active Directory object GUID is usually in the short format.

 

AD Items

Sample GUID format stored

OU\Organization Unit

7E14E9FE8BDF964186D3ABDDABA27AF1

User Object

A2C07FE63CCECB43B62FAA5210B680DF

Mailbox Database

265F75BCBB614C4C9568B205130E0ECF

 

 

How GUID appears in different Tools

 

Depending on the tool you use, you may see different format and arrangement of the alphanumeric digit as well. Note the following,

 

If you use LDP, when you look at the Active Directory objectGUID, you will see something like the following,

 

B45FC1B6-212F-47F1-88DD-78889D1DD2A9

 

For the same object, if you use ADSIEdit, you will see something like this,

 

B6 C1 5F B4 2F 21 F1 47 88 DD 78 88 9D 1D D2 A9

 

The above are from the same object but being presented differently. Note the front 16 alpha numeric digits have been flipped.

 

Now how is this represented in the database? Basically, MPS stores the format as you are seeing in ADSIEdit. What MPS does is this, for short format, it basically just take the format as in ADSIEdit and remove the space in between, like this, B6C15FB42F21F14788DD78889D1DD2A9.

 

For the long format, this is where it can be confusing. It isn’t following the format as in LDP, instead, it takes the format as in ADSIEdit but slotted the hyphens in accordingly, so it becomes like this,

 

B6C15FB4-2F21-F147-88DD-78889D1DD2A9

 

Note: the highlighted portion was not flipped as in LDP. This is important to note.

 

 

Getting the object GUID from AD

 

Using HMC procedure

 

GUID to LDAP

 

<?xml version="1.0" encoding="utf-8"?>

<request>

  <data>

                         <GUID>1D9DFFDF5E9E9D4E8C8483D2DF151589</GUID>

                         <preferredDomainController>adexbe</preferredDomainController>

  </data>

                        <!--

                        .........................................................

                        GUID: This is the AD GUID that will be resolved to an

                        LDAP path.

                       

                        preferredDomainController: this should be set to the Name,

                        IP Address or FQDN of a domain controller.

                       

                        .........................................................

                        -->

  <!--

  .................................................................

    PROCEDURE CODE BELOW - DO NOT MODIFY

  .................................................................

  -->

  <procedure>

    <execute namespace="Exchange Resource Manager" procedure="GUIDtoLDAP_" impersonate="2">

                        <executeData>

                        </executeData>

    <before source="data" destination="executeData" mode="merge"/>

    <after source="executeData" destination="data" mode="insert" />

    </execute>

  </procedure>

</request>

 

 

 

LDAP to GUID

 

 

<?xml version="1.0" encoding="utf-8"?>

<request>

  <data>

                        <LDAP>LDAP://OU=lgbusorg02,OU=consolidatedmessenger,OU=Hosting,DC=fabrikam,DC=Com</LDAP>

    <preferredDomainController>adexbe</preferredDomainController>

 

  </data>

                        <!--

                        .........................................................

                        LDAP: This is the LDAP Path that will be resolved to an

                        objectGUID.

                       

                        preferredDomainController: this should be set to the Name,

                        IP Address or FQDN of a domain controller.

                       

                        .........................................................

                        -->

  <!--

  .................................................................

    PROCEDURE CODE BELOW - DO NOT MODIFY

  .................................................................

  -->

  <procedure>

    <execute namespace="Managed Active Directory" procedure="LDAPtoGUID_" impersonate="2">

                        <executeData>

                        </executeData>

    <before source="data" destination="executeData" mode="merge"/>

    <after source="executeData" destination="data" mode="insert" />

    </execute>

  </procedure>

</request>

 

 

 

 

 

 

Tip: How do I instruct HMOabUpdate to update all the Offline Address Books in my HMC environment?

Most of you know HMC does not rely on the usual Exchange OAB generation schedule to trigger OABgen. Instead, HMC introduces a custom tool called HMOabUpdate that gets activated based a scheduled time to automate the generation of Offline Address Books. The tool will detected the changes since the last run and will only trigger OABgen on the OABs that requires updates.

HmOABUpdate or sometimes called the HEOabUpdate as well is really a simple tool. What it does in each run is to retrieve the last start and complete date and time and then based on those information, it will then retrieve from the HMC database to find out which organizations' OABs need update and will trigger the OABgen for those OABs accordingly.

So, this is how you can instruct HMOabUpdate to update the offline address books for all the OABs known by the HMC environment.

·         Go to the server where you install HMOabUpdate (usually it is on one of the MPS engines)

·         Start up RegEdit

·         Navigate to HKLM\SOFTWARE\Microsoft\Provisioning\HmOABUpdate

·         You should find 2 keys in that, LastCompleteDate and LastStartDate.

·         Edit the value to a date that is like before you install the HMC environment, something like 01/01/2000 for both of the keys.

·         Then kick start the HmOABUpdate by either starting it from your scheduled tasks or manually running the HmOabUpdate.exe from the cmd line in the directory, C:\Program Files\Microsoft Hosting\Provisioning\Exchange OAB Update.

Of course, you don't always have to modify the date so far back. You can always change it to something like 2-3 days ago if you want to just update OABs again for those changes made 2-3 days ago.

 Hope you find this useful.

 

What's going on to group expansion in HMC 4.5 Office Communications Server (OCS)?

When you are using Office Communicator, one of the nicest features (in my opinion) is the capability to add a group and expand it in the contact list. This feature really makes organization and group of contacts more consistent throughout the company. Unfortunately, this feature didn’t make it into HMC 4.5. As a result, while you still can add group, when you try to expand it, you will see the following message,  

Use of this group is restricted.  Contact your system administrator to request the required permissions.

I did a bit of investigation and found that the primary reason is because the logon user does not have the appropriate AD permission on the Group object, hence it failed to expand the group and resulting in the error shown above.

In my investigation, I also found a quick work around; however, you will have to manually do it. Of course, knowing how smart some of you are, you can probably and easily whip out some clever scripts or to enable the group to be allowed for group expansion in OCS.

This is what you can do,

a. Go to the Group object that you want to expand
b. Open up the security
c. Go to the Advance
d. Add AllUsers@<company domain>
e. Just add "Read Permission"

Once added, voila, any logon user in that organization will be able to expand the group object.

Exchange 2007 SP1 RU8 has been validated for HMC 4.0 and HMC 4.5

On a monthly basis, the HMC test team will conduct a Windows update compatibility test (where the major roll-ups and updates will be tested) on different versions of HMC environment.

Windows update compatibility tests (Exchange 2007 SP1 RU8 was included in this test) on HMC 4.0 as well as HMC 4.5 have completed successfully. This means Exchange 2007 SP1 RU8 has been validated for both HM 4.0 and HMC 4.5.

Click the following for the full list. HMC 4.0 and HMC 4.5.

Hosted Email 2007 Import::ImportMailbox will mess up your CustomerAssets table?

For those who are doing the migration from HMC 3.5 to HMC 4.0 using the HMC 4.0 Migration Kit, you may want to take note of this.

 

One of the tasks executed by the Hosted Email 2007 Import::ImportMailbox procedure is creating the mailbox GUID asset for each mailbox that you are importing into the CustomerAssets table in PlanManager database. The tasks is as follow (extracted from the Hosted Email 2007 Import::ImportMailbox procedure),

 

....

....

....

<execute namespace="Managed Plans" procedure="CreateCustomerAsset" impersonate="1">

                <executeData>

                                <eventTypeName>AssetAdded</eventTypeName>

                                <statusTypeName>Enabled</statusTypeName>

                                <assetTypeName>ExchMailboxGUID</assetTypeName>

                </executeData>

                <before source="procedureData" sourcePath="owningOrganization" destination="executeData" destinationPath="path" mode="merge"/>

                <before source="procedureData" sourcePath="msExchMailboxGUID" destination="executeData" destinationPath="asset" mode="merge"/>

                <before source="data" sourcePath="preferredDomainController" destination="executeData"/>

</execute>

....

....

....

 

This is importing of mailbox, however take note of the highlighted above. The path provided is supposed to be the user, but instead the owningOrganization is provided. As a result, when you use this procedure to perform the import, instead of mapping each user GUID to the appropriate mailbox GUID in the asset table, you are mapping all the mailbox GUID for that organization to the organization GUID.

 

The good news is that the above does not affect the service by the user but it may create some reporting issues and of course incorrect entries in the database. Nobody likes that.

 

So, if you haven't done the import, my suggestion is to change the highlighted portion above to the following so that the creation of the customer asset will pick up the LDAP path of the user instead of the LDAP path of the owningOrganization.

 

<before source="data" sourcePath="user" destination="executeData" destinationPath="path" mode="merge"/>

 

Please take note that the above steps will update the namespace procedure directly. This is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified in the Terms of Use. Please test it thoroughly.

So, what about for those who did the import in the past and you have used the Hosted Email 2007 Import::ImportMailbox procedure for that. Fortunately, while you will have to do some database brain surgery to fix it, it isn't difficult. What you need to do is to find all the mailbox enable user objects and retrieve the msExchMailboxGUID attribute and match it with the Asset field in the CustomerAsset Table. If they match, then update the CustomerID field.

Should I backup my OAB Public Folder Server?

We all know that in HMC environment has recommended that we should have dedicated Exchange Public Folder servers hosting purely just the Offline Address Books (OAB). You need the OAB Public Folder server in HMC 3.5 and HMC 4.0 if you want to allow your users to have the capacity to still access the address book while they are offline.

In HMC 4.5, it is optional. However if you want to support Outlook 2003 clients (let's call it legacy Outlook clients) running in cached mode and you want OAB to be downloadable and be available while they are disconnected, then you will need the OAB Public Folder Server. If your environment is only going to support Outlook 2007 and above, then you do not need OAB Public Folder server because you will be distributing OABs through Client Access Server using Web-based distribution model instead.

All of us know that it is essential to back up the mailbox server and the public folder server. However, when it comes to public folder servers that host purely just the OABs, most will tell you that you don't need it. So, what do you think? Do you think we need to backup those databases too?

Let's look at why it is not needed first. The reason given is simple; you don't really need to back them up because you can always re-run the process to regenerate all the offline address books. Yes, it is true but only to some extents.

I have a problem of not backing up the OAB Public Folder Server. Reason is this, depending on the environment, the regeneration process will take quite a while and depending on your environment it may cause some Active Directory performance issues too during the regeneration process.

So, how long does it really take? Now, when you run through your HEOABUpdate log (which is in C:\Program Files\Microsoft Hosting\Provisioning\Exchange OAB Update\logs), you may find that the OAB Update process consumes a really short time for each company in your environment. You may also find the same if you are to run Update-OfflineAddressBook cmdlet in the Exchange Management Shell, it will complete without error almost immediately. However, it should be noted that, that is only the submission process. What happens is that the cmdlet only submits the request to the queue of the OAB generation server. The OABgen server will then take over and process the queue and generate the OABs. If any error is encountered, you will find it in the event log instead of getting the error while executing the cmdlet.

We have seen in some environments where the number of address lists and global address lists are huge, it may take as much as 2-3 minutes per OAB. Doesn’t sound like a big deal, right? Right but think about this, if you need to rebuild the whole OAB server, and you have 1000 OABs in the server, you may potentially need about 30 hours to complete the rebuild.

So, the question really comes back to what are your RTO and your RPO? If you think you can live with the above and that your helpdesk won’t mind explaining to your customers why they are receiving error in their Outlook while doing Send/Receive during that period, then I say, yeah, you don’t need to back them up. If not, my recommendation is, let's back them up. After all, how difficult is it to back up that small Public Folder database that host only the OABs?

Cheers.

MPFListener.exe crashed because of sqloledb.dll?

Recently, I have seen a couple of our customers encountered the following where the MPFListner.exe (Provisioning Auditing and Recovery Service) crashed immediately after you try to start it. You can try to reboot the machine, or restart the Provisioning Auditing and Recovery Service multiple times; it just won’t recover from it.

The service will get started and then it will crashed right away giving the following error,

Problem Description: Event Type: Error
Event Source: Application Error
Event Category: (100)
Event ID: 1000
Date:  1/1/2009
Time:  1:00:00 PM
User:  N/A
Computer: <ServerName>
Description:
Faulting application MPFListener.exe, version 13.3.609.9, faulting module sqloledb.dll, version 2000.86.3959.0, fault address 0x0004abe4.

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
Data:
0000: 41 70 70 6c 69 63 61 74   Applicat
0008: 69 6f 6e 20 46 61 69 6c   ion Fail
0010: 75 72 65 20 20 4d 50 46   ure  MPF
0018: 4c 69 73 74 65 6e 65 72   Listener
0020: 2e 65 78 65 20 31 33 2e   .exe 13.
0028: 33 2e 36 30 39 2e 39 20   3.609.9
0030: 69 6e 20 73 71 6c 6f 6c   in sqlol
0038: 65 64 62 2e 64 6c 6c 20   edb.dll
0040: 32 30 30 30 2e 38 36 2e   2000.86.
0048: 33 39 35 39 2e 30 20 61   3959.0 a
0050: 74 20 6f 66 66 73 65 74   t offset
0058: 20 30 30 30 34 61 62 65    0004abe
0060: 34                        4

With the help of some of my colleagues, we were able to track the problem down to a null value in the EventDesc field in the Event table in MPFTranLogData database. It seems that the MPFListener crashes when moving Records from MPFTranLogData to MPFAudit database and the sqloledb.dll was not able to handle the null value when it is called and crashed. Hence, as long as the data is still in the MPFTranLogData, the MPFListener will crash the moment it attempts to move the record with the null value.

A hotfix is available for this where the MPFListener will have better intelligence on dealing with this and will continue to move records over to MPFAudit without crashing like this. However, as I am writing this, you will have to contact Microsoft to obtain the hotfix.

To work around right now is this,

1.       To find out if you have such records in your database,

 

SELECT *

 FROM [MPFTranLogData].[dbo].[Events]

WHERE [EventDesc] is null

 

2.       If you find records some there, then try to update those records by setting the EventDesc to ‘N/A’ instead of having it as null like the following,

 

UPDATE [MPFTranLogData].[dbo].[Events]

SET [EventDesc]=’N/A’

WHERE [EventDesc] is null

Please take note that the above steps will update the database directly. This is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified in the Terms of Use.

Thanks to Mike K and Luc G.

Fixing ConvertGlobalToUniversalGroup.vbs in HMC 4.0 Migration Kit

Alright, this is a quick one.

For those who are planning to migrate from HMC 3.5 to HMC 4.0, and if you are using the HMC 4.0 Migration Kit (http://www.microsoft.com/downloads/details.aspx?FamilyId=636571AA-6582-49D6-B59E-81E9C27FE240&displaylang=en), you may want to take note that the ConvertGlobalToUniversalGroup.vbs provided for in-place upgrade in the Sample Migration Scripts does not work well.

The script is supposed to convert the groups in each organization from Global to Universal. However, when you run this VBScript, you will find that it will run and it will complete without error and nothing will be converted.

The problem is in the ConvertGroup function where the MyArray was not properly defined and also the error number is not properly reset when it is called again. However, because On Error Resume Next is in place, the error was skipped. If you want to see the error, comment out “On Error Resume Next”.

To fix it, just add the highlighted area in the function as the following,

Function ConvertGroup(objUser)

Wscript.echo "Converting Group = " & objUser.Name
On Error Resume Next
Err.Number = 0

MyArray = Split(objUser.DistinguishedName, "@")      

 


'if this is a built in MPS group, skip it.
If MyArray(0) = "CN=Admins" Then
       Err.Number = 42
       ConvertGroup = Err.Number
       Exit Function
End If

If MyArray(0) = "CN=CSRAdmins" Then
       Err.Number = 42
       ConvertGroup = Err.Number
       Exit Function
End If   

 

' convert 0067roup

Set objGroup = GetObject ("LDAP://" & objUser.DistinguishedName)

' NOTE: If you want to make this a Security group instead of a Distribtuion group,
'       then simply add the following to the below command: OR ADS_GROUP_TYPE_SECURITY_ENABLED.

objGroup.Put "groupType", ADS_GROUP_TYPE_UNIVERSAL_GROUP
objGroup.SetInfo

ConvertGroup = err.Number

End Function

 

More Posts Next page »
Page view tracker