Microsoft KB Archive/284199

From BetaArchive Wiki

PSS ID Number: 284199

Article Last Modified on 7/13/2004



The information in this article applies to:

  • Microsoft Exchange Server 5.5
  • Microsoft Active Directory Services Interface, System Component
  • Microsoft Active Directory Client Extension, when used with:
    • the operating system: Microsoft Windows 98
    • the operating system: Microsoft Windows NT 4.0
  • Microsoft Lightweight Directory Access Protocol (LDAP) API



This article was previously published under Q284199

SYMPTOMS

If you use Active Directory Services Interface (ADSI) or Lightweight Directory Access Protocol (LDAP) API to delete Microsoft Exchange Server 5.5 mailboxes, information store resources will be orphaned. While the directory object will be deleted, the store resources are not deleted and become orphaned.

RESOLUTION

Microsoft does not recommend or support the deletion of Exchange 5.5 mailboxes through the use of ADSI or LDAP. The supported method of deleting the mailbox is to use the Exchange Administrator program or by writing an application that uses the Directory API (DAPI). An example of using DAPI is shown later in this article under "Deleting the Exchange 5.5 Mailbox."

If, however, you have already deleted the Exchange 5.5 mailbox by using ADSI or LDAP, the only way to delete the orphaned store resources is to recreate the directory object and then again delete the mailbox.

Re-creating the Exchange 5.5 mailbox directory object

The easiest way to recreate the Exchange mailbox directory object is to run the DS/IS Consistency Checker. If you choose not to use the DS/IS Consistency Checker, you can also recreate the exchange mailbox directory object by using Directory Import from the Tools menu in the Exchange Administrator program or programmatically by using ADSI, LDAP, or DAPI. For additional information, click the following article numbers to view the articles in the Microsoft Knowledge Base:

182979 Function and effects of running the DS/IS consistency adjuster


244595 How to create mailboxes by means of a .csv file


194954 How to create a mailbox using DAPI


Also see the following Microsoft Web site:

When you recreate the directory object, it must have the exact directory name and be made in the same container that the deleted one was in. It also must have the HomeMDB attribute set to be the same value that the original object had. The directory name is often, but not always, the same as the alias name. In most circumstances, you view the directory name of a mailbox from the mailbox object's Advanced Properties page. In this case, the mailbox no longer exists in the directory, but its resources are orphaned inside the information store database. You may still be able to view the information about the mailbox through the Mailbox Resources page that is found under the server's Private Information Store object. The directory name for the mailbox is not displayed by default in Mailbox Resources. You can add the directory name to the display through the View menu's Column dialog box. The full directory name displayed will be similar to:

/O=ORGANIZATION/OU=SITE/CN=RECIPIENTS CONTAINER/CN=DIRECTORY NAME


The final CN= value is the directory name that must be entered for the mailbox. You must also create the mailbox in the same container where it previously existed. The container where the mailbox object used to reside in can also be verified by viewing the full directory name.

The HomeMDB attribute must be set to the full directory name of the information store where the orphaned resources are located. To determine what this value should be, look at the Obj-Dist-Name attribute on the private information store object that contains the orphaned store resources. For additional information about how to do this, click the following article number to view the article in the Microsoft Knowledge Base:

237682 How to determine LDAP name for Exchange Server objects


The HomeMDB attribute will look similar to this:

/O=ORGANIZATION/OU=SITE/CN=SERVERS/CN=SERVER NAME/CN=Microsoft Private MDB


The following sample code recreates a mailbox by using ADSI so that later it can be properly deleted:

'The mailbox was in the container o=MyOrganization,ou=Mysite,cn=Recipients
Set obj = GetObject("LDAP://MyServer/cn=Recipients,ou=MySite,o=MyOrganization")

'The mailbox had a cn=MyMailbox
Set objNewUser = obj.Create("organizationalPerson", "cn=MyMailbox")
objNewUser.Put "cn", "MyMailbox"
objNewUser.Put "uid", "MyMailbox"
objNewUser.Put "mailPreferenceOption", 0

'The mailbox has resources in the Private MDB on the server MyServer in the site MySite
objNewUser.Put "Home-MDB", "cn=Microsoft MTA,cn=MyServer,cn=Servers,cn=Configuration," & _
               "ou=MySite,o=MyOrganization"
objNewUser.SetInfo
                

Deleting the Exchange 5.5 mailbox

Once you have recreated the mailbox directory object, you can delete the mailbox directory object and the associated store resources through the Microsoft Exchange Administrator program by using Directory Import from the Tools menu to import a .csv file (see "References") or by using DAPI to delete the mailbox directory object and its associated store properly.

The following is an example of how to delete a mailbox by using DAPI:

 // 
 // DAPIDel.cpp : Defines the entry point for the console application.
 // Dapi.lib is the only additional library required to compile the code.
 // 
 
 #include <windows.h>
 #include <stdio.h>
 #include <string.h>
 #include <lmcons.h>
 #include <tchar.h>
 
 #include <dapi.h>
 
 #include <dapimsg.h> // error codes 
 
 void DAPIDelObj(DAPI_HANDLE hDAPISession, char * szCN, char * szObjectClass);
 void ReportDAPIEvent(DAPI_EVENT* pDAPIEvent);
 
 
 void main(int argc, char* argv[])
 {
    DAPI_HANDLE hDAPISession;
    DAPI_EVENT* pDAPIEvent = NULL;
    DAPI_PARMS DAPIParms = {0};
 
    if (5 > argc) 
    {
        printf("\nDAPIDel ExchangeServerName ContainerDN CN ObjectClass");
        printf("\n\nExample:");
        printf("\nDAPIDel myserver /O=org/OU=site/CN=recipients commonname mailbox");
        return;
    }
    else
    {
        printf("\nExchange Server: %s", argv[1]);
        printf("\nBasePoint Container DN: %s", argv[2]);
        printf("\nCommon Name: %s", argv[3]);
        printf("\nObjectClass: %s", argv[4]);
    }
 
    // start DAPI for this session
    //initialize the the DAPI Parms structure and the DAPI operation session
    DAPIParms.dwDAPISignature = DAPI_SIGNATURE;
    DAPIParms.dwFlags = DAPI_EVENT_ALL|DAPI_MODIFY_REPLACE_PROPERTIES|DAPI_RAW_MODE ;
    DAPIParms.pszDSAName = argv[1];
    DAPIParms.pszBasePoint = argv[2];
    DAPIParms.pszContainer = NULL;
    DAPIParms.pszNTDomain = NULL;
    DAPIParms.pszCreateTemplate = NULL;
    DAPIParms.pAttributes = NULL;
 
    pDAPIEvent = DAPIStart(&hDAPISession, &DAPIParms);  //struct with DAPI params
 
    if(pDAPIEvent) 
    {
        printf("\nDAPIStart() returned %08x - check app eventlog", pDAPIEvent->dwDAPIError);
        ReportDAPIEvent(pDAPIEvent);
        // Note: dwDAPIError < 0 does NOT necessarily mean DAPIStart failed
        if (0==hDAPISession || INVALID_HANDLE_VALUE == hDAPISession) return;
    } 
    else 
        printf("\nDAPIStart() was successful");    
    DAPIDelObj(hDAPISession, argv[3], argv[4]);     
    DAPIEnd(&hDAPISession);
    printf("\nEND PROGRAM");
 }
 
 ATT_VALUE * AddStrAttr(_TINT i, LPCTSTR szClass, LPCTSTR szValue,
                        DAPI_ENTRY * dapiAttr, DAPI_ENTRY * dapiValues) 
 {
    ATT_VALUE * AttName = &(dapiAttr->rgEntryValues[i]);
    AttName->DapiType = DAPI_STRING8;
    AttName->Value.pszValue = const_cast <LPTSTR> (szClass);
    AttName->size = _tcslen(AttName->Value.pszValue);
    AttName->pNextValue = NULL;
 
    ATT_VALUE * AttValue = &(dapiValues->rgEntryValues[i]);
    AttValue->DapiType = DAPI_STRING8;
    AttValue->Value.pszValue = const_cast <LPTSTR> (szValue);
    AttValue->size = _tcslen(AttValue->Value.pszValue);
    AttValue->pNextValue = NULL;        
     
    return AttValue;
 }
 
 
 void DAPIDelObj(DAPI_HANDLE hDAPISession, char * szCN, 
                 char * szObjectClass)
 {
    DAPI_EVENT* pDAPIEvent = NULL;
    DAPI_ENTRY Attributes;
    DAPI_ENTRY Values;
    ATT_VALUE AttName[3];
    ATT_VALUE AttValue[3];
    int i=0;
 
    printf("\nIN DAPIDelObj()");
 
    //set up the account information
 
    Attributes.unAttributes = 2;                        //# of attributes
    Attributes.ulEvalTag = TEXT_VALUE_ARRAY;            //Value Type
    Attributes.rgEntryValues = &AttName[0];
 
    Values.unAttributes = 2;                            //# of attributes
    Values.ulEvalTag = VALUE_ARRAY;                     //Value Type
 
    Values.rgEntryValues = (ATT_VALUE*)&AttValue;
    
    AddStrAttr( i++, "Obj-Class", szObjectClass, &Attributes, &Values);
    AddStrAttr( i, "Directory Name", szCN, &Attributes, &Values);
     
     // delete the mailbox
    printf("\nDeleting %s object /cn=\"%s\"", szObjectClass, szCN);
    pDAPIEvent = DAPIWrite(hDAPISession,    
                           DAPI_WRITE_DELETE,
                           &Attributes,      
                           &Values,          
                           NULL,            
                           NULL,           
                           NULL);            
 
    if(pDAPIEvent) 
    {
        // write FAILED
        printf("\nDAPIWrite ERROR %08x check app eventlog", pDAPIEvent->dwDAPIError);
        ReportDAPIEvent(pDAPIEvent);
    } 
    else 
        printf("\nDAPIWrite() was successful");
 
 }
 
 void ReportDAPIEvent(DAPI_EVENT* pDAPIEvent)
 {
    HANDLE hDAPIEventSource = RegisterEventSource(NULL, TEXT("MSExchangeDSImp"));
    
    ReportEvent(hDAPIEventSource, 
                (WORD)EVENTLOG_ERROR_TYPE, 
                0xFFFF, 
                pDAPIEvent->dwDAPIError, 
                NULL, 
                (WORD)pDAPIEvent->unSubst, 
                0, 
                (const char**) pDAPIEvent->rgpszSubst, 
                NULL);
 
    DAPIFreeMemory(pDAPIEvent);
 
    DeregisterEventSource(hDAPIEventSource);
 }
                

REFERENCES

For additional information, click the following article numbers to view the articles in the Microsoft Knowledge Base:

182508 How to delete a user using a .csv file import


184160 Messages left after deleting mailbox with directory import


242221 List of bugs fixed in Exchange Server 5.5 Service Pack 1


169551 Items required to use DAPI


252988 BUG: Deleting Exchange 5.5 Mailbox with LDAP poses security risk


179573 Orphaned objects and Exchange Server directory


183739 Identifying and removing large numbers of orphaned objects


237682 How to determine LDAP name for Exchange Server objects


DAPIWrite

Keywords: kbDSWADSI2003Swept kbprb KB284199
Technology: kbADSIActiveDirectory kbADSISearch kbADSISysComp kbAudDeveloper kbExchange550 kbExchangeSearch kbLDAPAPI kbLDAPSearch kbOSWin98 kbOSWinNT400 kbOSWinNTSearch kbOSWinSearch kbwin2000Search kbZNotKeyword2