HOWTO: Use BatchExport to Specify Which Attributes to Export
ID: Q188960
|
The information in this article applies to:
-
Exchange Development Kit (EDK), version 5.0
-
Microsoft Exchange Server, versions 5.0, 5.5
SUMMARY
This article contains a revised version of the Microsoft Developer Network
DSExport.c file. The revised sample allows the user to specify the
attributes that are exported for objects. The new command line parameter to
use is /EXPLIST=list of attributes. If /EXPLIST is not specified and a
header file is not present, then a default set of attributes is exported.
MORE INFORMATION
Sample Code
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);
}
REFERENCES
Another example of BatchExport is in the Dirysnc.c sample found on the
Microsoft Developer Network Library.
Additional query words:
kbEDK500 kbMsg EDKAPI
Keywords : kbAPI kbEDK kbMsg
Version : WINDOWS:5.0; winnt:5.0,5.5
Platform : WINDOWS winnt
Issue type : kbhowto