Sample Code
-----------
   //--dsexport-mod.c--------------------------------------------------
    // 
    //  MODIFIED Directory Service Export Sample.
    // 
    // Copyright (C) Microsoft Corp. 1986-1996.  All Rights Reserved.
    // 
    // Modified to allow the export of user defined attributes of
    // objects.
    // This code is not guaranteed to be memory safe.
    //------------------------------------------------------------------
    #include "edk.h"
    #include "dapi.h"
    // 
    // Names of Command Line Arguments
    // 
    #define ARG_FILE              "FILE"
    #define ARG_BASEPOINT         "BASEPOINT"
    #define ARG_CONTAINER         "CONTAINER"
    #define ARG_CLASSES           "CLASSES"
    #define ARG_DSA               "DSA"
    #define ARG_HELP1             "?"
    #define ARG_HELP2             "HELP"
    #define ARG_SERVER            "SERVER"
    #define ARG_ALL_RECIPIENTS    "ALL_RECIPIENTS"
    #define ARG_ONLY_BASEPOINT    "ONLY_BASEPOINT"
    #define ARG_DIST_LIST         "DIST_LIST"
    #define ARG_MAILBOX           "MAILBOX"
    #define ARG_REMOTE_ADDRESS    "REMOTE_ADDRESS"
    #define ARG_ALL_CLASSES       "ALL_CLASSES"
    #define ARG_HIDDEN            "HIDDEN"
    #define ARG_SUBTREE           "SUBTREE"
    #define ARG_EXPLIST           "EXPLIST"
    // 
    // Table of Command Line Switches for _HrExpandCommandLineArgument()
    // 
    static char * rgpszArgArray[] = {
        ARG_FILE,
        ARG_BASEPOINT,
        ARG_CONTAINER,
        ARG_CLASSES,
        ARG_DSA,
        ARG_HELP1,
        ARG_HELP2,
        ARG_SERVER,
        ARG_ALL_RECIPIENTS,
        ARG_ONLY_BASEPOINT,
        ARG_DIST_LIST,
        ARG_MAILBOX,
        ARG_REMOTE_ADDRESS,
        ARG_ALL_CLASSES,
        ARG_HIDDEN,
        ARG_SUBTREE,
        ARG_EXPLIST
    };
    // 
    // Variables For Command Line Arguments
    // 
    char    szExportFile[MAX_PATH+1]     = {0};
    char    szDsaName[MAX_PATH+1]        = {0};
    char    szServerName[MAX_PATH+1]     = {0};
    char    szBasePoint[MAX_PATH+1]      = {0};
    char    szParentContainer[MAX_PATH+1]= {0};
    DWORD   ControlFlags                 = 0;
    ULONG   cClasses                     = 0;
    LPSTR*  lppszClasses                 = NULL;
    char    szExportList[MAX_PATH+1]     = {0};
    // 
    // Other Variables
    // 
    BOOL fDisplayedHelp                  = FALSE;
    DWORD cLoggedErrors                  = 0;
    // 
    // Function Declarations
    // 
    static HRESULT HrParseCommandLine(
        IN int argc,
        IN char *argv[]);
    static VOID ShowUsage(
        void);
    static VOID ShowHelp(
        void);
    static HRESULT HrDoBatchExport(
        void);
    // 
    // Functions
    // 
    //$--main------------------------------------------------------
    //  Main function that performs directory export.
    //-------------------------------------------------------------
    int main(               // RETURNS: exit code
        IN int argc,        // number of arguments on command line
        IN char *argv[])    // array of command line arguments
    {
        HRESULT hr          = NOERROR;
        BOOL    IsMAPIInit  = FALSE;
        DEBUGPUBLIC("main()\n");
        printf( "\n" );
        hr = MAPIInitialize(NULL);
        if(FAILED(hr))
        {
            goto cleanup;
        }
        IsMAPIInit = TRUE;
        // Get export parameters from the command line.
        hr = HrParseCommandLine(argc, argv);
        if (FAILED(hr))
        {
             goto cleanup;
        }
        // Do batch export.
        hr = HrDoBatchExport();
        if (FAILED(hr))
        {
             goto cleanup;
        }
    cleanup:
        if(IsMAPIInit == TRUE)
        {
            MAPIUninitialize();
        }
        // Successful completion.
        if (fDisplayedHelp)
        {
            hr = NOERROR;
        }
        else if (SUCCEEDED(hr))
        {
            fprintf(stderr,
                "Export operation completed successfully.\n");
        }
        // Error completion.
        else if (cLoggedErrors == 1)
        {
            fprintf(stderr,
                "ERROR: 1 error written to NT Event Log.\n");
        }
        else if (cLoggedErrors > 1)
        {
            fprintf(stderr,
                "ERROR: %d errors written to NT Event Log.\n",
                cLoggedErrors);
        }
        MAPIFREEBUFFER(lppszClasses);
        return _nEcFromHr(hr);
    }
    //$--HrParseCommandLine---------------------------------------------
    //  Read export configuration from command line.
    //------------------------------------------------------------------
    static HRESULT HrParseCommandLine(      // RETURNS: HRESULT
        IN int argc,          // Number of arguments on command line
        IN char *argv[])      // Array of command line arguments
    {
        HRESULT      hr             = NOERROR;
        HRESULT      hrT            = NOERROR;
        char *       pszArgument    = NULL;
        char *       pszValue       = NULL;
        int          i              = 0;
        LPTSTR       lpszSep        = "%\0";
        DEBUGPRIVATE("HrParseCommandLine()\n");
        // If there are no command line arguments then show a usage
        // message.
        if (argc < 2)
        {
            ShowUsage();
            hr = E_FAIL;
            goto cleanup;
        }
        // Do an initial check for /? or /HELP. If found, show a help
        // message and do not do any other parsing.
        for (i = 1; i < argc; i++)
        {
            hr = _HrExpandCommandLineArgument(
                        argv[i], rgpszArgArray,
                        ARRAY_CNT(rgpszArgArray), NULL,
                        &pszArgument, &pszValue);
            if (SUCCEEDED(hr) && pszArgument &&
                (!_stricmp(pszArgument,ARG_HELP1) ||
                !_stricmp(pszArgument,ARG_HELP2)))
            {
                ShowHelp();
                hr = E_FAIL;
                goto cleanup;
            }
        }
        // Loop through and parse all the command line arguments.
        for (i = 1; i < argc; i++)
        {
            hrT = _HrExpandCommandLineArgument(
                        argv[i], rgpszArgArray,
                        ARRAY_CNT(rgpszArgArray), NULL,
                        &pszArgument, &pszValue);
            if (FAILED(hrT))
            {
                hr = hrT;
                if (hr == EDK_E_NOT_FOUND)
                {
                    fprintf(stderr,
                        "ERROR: unknown command line flag: %s\n",
                        argv[i]);
                    continue;
                }
                else
                {
                    fprintf(stderr,
                        "ERROR: unable to parse command line.\n");
                    goto cleanup;
                }
            }
            // Parse flag arguments that do not take a value.
            if (pszArgument != NULL && pszValue == NULL)
            {
                // ALL_RECIPIENTS
                if (!_stricmp(pszArgument,ARG_ALL_RECIPIENTS))
                {
                    ControlFlags |= DAPI_EXPORT_RECIPIENTS;
                }
                // ONLY_BASEPOINT
                else if (!_stricmp(pszArgument,ARG_ONLY_BASEPOINT))
                {
                    ControlFlags |= DAPI_EXPORT_BASEPOINT_ONLY;
                }
                // DIST_LIST
                else if (!_stricmp(pszArgument,ARG_DIST_LIST))
                {
                    ControlFlags |= DAPI_EXPORT_DIST_LIST;
                }
                // MAILBOX
                else if (!_stricmp(pszArgument,ARG_MAILBOX))
                {
                    ControlFlags |= DAPI_EXPORT_MAILBOX;
                }
                // REMOTE_ADDRESS
                else if (!_stricmp(pszArgument,ARG_REMOTE_ADDRESS))
                {
                    ControlFlags |= DAPI_EXPORT_CUSTOM;
                }
                // ALL_CLASSES
                else if (!_stricmp(pszArgument,ARG_ALL_CLASSES))
                {
                    ControlFlags |= DAPI_EXPORT_ALL_CLASSES;
                }
                // HIDDEN
                else if (!_stricmp(pszArgument,ARG_HIDDEN))
                {
                    ControlFlags |= DAPI_EXPORT_HIDDEN;
                }
                // SUBTREE
                else if (!_stricmp(pszArgument,ARG_SUBTREE))
                {
                    ControlFlags |= DAPI_EXPORT_SUBTREE;
                }
                // Other flag (must take a value).
                else
                {
                    fprintf(stderr,
                        "ERROR: flag /%s requires a value\n",pszArgument);
                    hr = HR_LOG(E_FAIL);
                }
            }
            // Parse flag arguments that take a value.
            else if (pszArgument != NULL && pszValue != NULL)
            {
                if (!_stricmp(pszArgument,ARG_DSA))
                {
                    strncpy(szDsaName, pszValue, MAX_PATH);
                    szDsaName[MAX_PATH] = 0;
                }
                else if (!_stricmp(pszArgument,ARG_SERVER))
                {
                    strncpy(szServerName, pszValue, MAX_PATH);
                    szServerName[MAX_PATH] = 0;
                }
                else if (!_stricmp(pszArgument,ARG_FILE))
                {
                    strncpy(szExportFile, pszValue, MAX_PATH);
                    szExportFile[MAX_PATH] = 0;
                }
                else if (!_stricmp(pszArgument,ARG_BASEPOINT))
                {
                    strncpy(szBasePoint, pszValue, MAX_PATH);
                    szBasePoint[MAX_PATH] = 0;
                }
                else if (!_stricmp(pszArgument,ARG_CONTAINER))
                {
                    strncpy(szParentContainer, pszValue, MAX_PATH);
                    szParentContainer[MAX_PATH] = 0;
                }
                else if (!_stricmp(pszArgument,ARG_CLASSES))
                {
                    hr = HrStrTokAll(pszValue,
                                     lpszSep,
                                     &cClasses,
                                     &lppszClasses);
                    if(FAILED(hr))
                    {
                        fprintf(stderr,
                            "ERROR: syntax error in /%s\n",
                            pszArgument);
                        goto cleanup;
                    }
                }
                // EXPLIST
                else if (!_stricmp(pszArgument,ARG_EXPLIST))
                {
                    strncpy(szExportList, pszValue, MAX_PATH);
                }
                // Other flag (must not take a value).
                else
                {
                    fprintf(stderr,
                        "ERROR: flag /%s does not take a value\n",
                        pszArgument);
                    hr = HR_LOG(E_FAIL);
                }
            }
            // Catch unknown arguments.
            else
            {
                fprintf(stderr, "ERROR: unknown argument %s\n", argv[i]);
                hr = HR_LOG(E_FAIL);
            }
        }
        // Make sure we have all the info we need.
        if (SUCCEEDED(hr))
        {
            if (*szDsaName == 0)
            {
                fprintf(stderr, "ERROR: please specify /%s\n", ARG_DSA);
                hr = HR_LOG(E_FAIL);
            }
            if (*szExportFile == 0)
            {
                fprintf(stderr, "ERROR: please specify /%s\n", ARG_FILE);
                hr = HR_LOG(E_FAIL);
            }
        }
    cleanup:
        RETURN(hr);
    }
    //$--ShowUsage-----------------------------------------------------
    //  Show usage information.
    //-----------------------------------------------------------------
    static VOID ShowUsage(void)            // RETURNS: nothing
    {
        DEBUGPRIVATE("ShowUsage()\n");
        printf("USAGE: DSEXPORT [Flags]\n\n");
        printf("  [Flags]        Enter DSEXPORT /? for details\n");
        fDisplayedHelp = TRUE;
    }
    //$--ShowHelp------------------------------------------------------
    //  Show help information.
    //-----------------------------------------------------------------
    static VOID ShowHelp(void)            // RETURNS: nothing
    {
        DEBUGPRIVATE("ShowHelp()\n");
        printf(
            "Directory Service Export sample.\n\n");
        printf(
            "USAGE: DSEXPORT [Flags]\n\n");
        printf(
            "  /FILE=            Name of export file\n");
        printf(
            "  /SERVER=          Exchange server name\n");
        printf(
            "  /DSA=             Directory Service Agent name\n");
        printf(
            "  /BASEPOINT=       DN of Directory basepoint object\n");
        printf(
            "  /CONTAINER=       RDN of Directory container beneath "
            "BASEPOINT\n");
        printf(
            "  /CLASSES=         Object classes (separated by '%%')\n");
        printf(
            "  /EXPLIST=         Attribute list for Export\n");
        printf(
            "  /HELP or /?       Display help screen\n");
        printf(
            "  /ONLY_BASEPOINT   Export only the BASEPOINT object\n");
        printf(
            "  /ALL_RECIPIENTS   Export all recipients\n");
        printf(
            "  /DIST_LIST        Export distribution list "
            "recipients\n");
        printf(
            "  /MAILBOX          Export mailbox recipients\n");
        printf(
            "  /REMOTE_ADDRESS   Export remote address recipients\n");
        printf(
            "  /ALL_CLASSES      Export all classes\n");
        printf(
            "  /HIDDEN           Export hidden objects of the selected "
            "classes\n");
        printf(
            "  /SUBTREE          Export subtree\n");
        fDisplayedHelp = TRUE;
    }
    //$--DoBatchExport-------------------------------------------------
    //  Do batch export of directory objects.
    //-----------------------------------------------------------------
    static HRESULT HrDoBatchExport(void)   // RETURNS: HRESULT
    {
        HRESULT          hr                  = NOERROR;
        BEXPORT_PARMS    BexportParms        = {0};
        LPBEXPORT_PARMS  lpBexportParms      = {0};
        DAPI_ENTRY       AttributesEntry     = {0};
        ATT_VALUE        AttributesValue     = {0};
        LPTSTR           pszExportListCopy   = NULL;
        hr = MAPIAllocateBuffer(strlen(szExportList) + 200,
                                &pszExportListCopy);
        DEBUGPRIVATE("HrDoBatchExport()\n");
        lpBexportParms = &BexportParms;
        lpBexportParms->dwDAPISignature = DAPI_SIGNATURE;
        lpBexportParms->pszExportFile = szExportFile;
        lpBexportParms->pszBasePoint = szBasePoint;
        lpBexportParms->dwFlags = ControlFlags | DAPI_EVENT_ALL;
        if (*szParentContainer)
        {
            lpBexportParms->pszContainer = szParentContainer;
        }
        if (*szDsaName)
        {
            lpBexportParms->pszDSAName = szDsaName;
        }
        if (*szServerName)
        {
            lpBexportParms->pszHomeServer = szServerName;
        }
        if(lppszClasses != NULL)
        {
            lpBexportParms->rgpszClasses = lppszClasses;
        }
        if(&AttributesEntry != NULL)
        {
            strcpy(pszExportListCopy, "Obj-Class,");
            strcat(pszExportListCopy, szExportList);
            lpBexportParms->pAttributes = &AttributesEntry;
            AttributesEntry.unAttributes = 1;
            AttributesEntry.ulEvalTag = TEXT_LINE;
            AttributesEntry.rgEntryValues = &AttributesValue;
            AttributesValue.DapiType = DAPI_TEXT;
            AttributesValue.Value.pszValue = pszExportListCopy;
            AttributesValue.size = lstrlen(pszExportListCopy);
        }
        lpBexportParms->chColSep = DAPI_DEFAULT_DELIM;
        lpBexportParms->chQuote = DAPI_DEFAULT_QUOTE;
        lpBexportParms->chMVSep = DAPI_DEFAULT_MV_SEP;
        cLoggedErrors = BatchExport(lpBexportParms);
        if (cLoggedErrors)
        {
            hr = HR_LOG(E_FAIL);
        }
        RETURN(hr);
    }