#include #pragma hdrstop #include #include "trkwks.hxx" #include "trksvr.hxx" #include "dltadmin.hxx" void CDomainRelativeObjId::FillLdapIdtKeyBuffer(TCHAR * const pchCN, DWORD cch) const { TCHAR *pchBuf = pchCN; _tcscpy(pchBuf, TEXT("CN=")); pchBuf = pchBuf + 3; _volume.Stringize(pchBuf); _object.Stringize(pchBuf); TrkAssert(pchBuf <= pchCN+cch); } void ShowMoveCounter( const TCHAR *ptszHostName ) { CDbConnection dbc; dbc.Initialize( NULL, ptszHostName ); CTrkSvrConfiguration configSvr; configSvr.Initialize(); BOOL fSuccess = FALSE; struct berval** ppbvCounter = NULL; TCHAR* rgtszAttrs[2]; LDAPMessage* pRes = NULL; int ldapRV; int cEntries = 0; LDAPMessage* pEntry = NULL; CLdapQuotaCounterKeyDn dnKeyCounter(dbc.GetBaseDn()); DWORD dwCounter = 0; __try { rgtszAttrs[0] = const_cast(s_volumeSecret); rgtszAttrs[1] = NULL; ldapRV = ldap_search_s(dbc.Ldap(), dnKeyCounter, LDAP_SCOPE_BASE, TEXT("(ObjectClass=*)"), rgtszAttrs, 0, &pRes); if( LDAP_NO_SUCH_OBJECT == ldapRV ) { printf( "Move table counter doesn't exist\n" ); __leave; } else if( LDAP_SUCCESS != ldapRV ) { printf( "Couldn't read move table counter (%d)\n", ldapRV ); __leave; } cEntries = ldap_count_entries(dbc.Ldap(), pRes); if( 0 == cEntries ) { printf( "Move table counter didn't exist or couldn't be read\n" ); __leave; } else if( 1 != cEntries ) { printf( "Too many move table counters (%d)!\n", cEntries ); __leave; } pEntry = ldap_first_entry(dbc.Ldap(), pRes); if(NULL == pEntry) { printf( "Entries couldn't be read from result\n" ); __leave; } ppbvCounter = ldap_get_values_len(dbc.Ldap(), pEntry, const_cast(s_volumeSecret) ); if (ppbvCounter == NULL) { _tprintf( TEXT("Move table counter is corrupt, missing %s attribute\n"), s_volumeSecret ); __leave; } if ((*ppbvCounter)->bv_len < sizeof(DWORD)) { _tprintf( TEXT("Move table counter attribute %s has wrong type (%d)\n"), s_volumeSecret, (*ppbvCounter)->bv_len ); __leave; } memcpy( (PCHAR)&dwCounter, (*ppbvCounter)->bv_val, sizeof(DWORD) ); printf( "Move table counter (in DS) %lu\n", dwCounter ); } __finally { if(NULL != pRes) { ldap_msgfree(pRes); } if (ppbvCounter != NULL) { ldap_value_free_len(ppbvCounter); } } } /* ShowDcEntries( const TCHAR *ptszHostName ) { TCHAR* rgptszAttrs[4]; LDAPMessage* pRes = NULL; int ldapRV; HRESULT hr = E_FAIL; CDbConnection dbc; dbc.Initialize( NULL, ptszHostName ); CLdapVolumeKeyDn dnKey(dbc.GetBaseDn()); LONGLONG llCreationTime, llLastAliveTime; CFILETIME cftNow; CTrkSvrConfiguration configSvr; configSvr.Initialize(); struct berval ** ppbvMachineId = NULL; TCHAR** pptszCreationTime = NULL; TCHAR** pptszLastAliveTime = NULL; LDAPMessage * pEntry = NULL; struct SDcEntries { CMachineId mcid; BOOL fSuspended; CFILETIME cftCreation; CFILETIME cftLastAlive; }; SDcEntries rgsDcEntries[ 100 ]; ULONG cDcEntries = 0; CMachineId mcidDesignated; ULONG cEntries = 0; __try { rgptszAttrs[0] = const_cast(s_Cn); rgptszAttrs[1] = const_cast(s_timeVolChange); rgptszAttrs[2] = const_cast(s_timeRefresh); rgptszAttrs[3] = NULL; ldapRV = ldap_search_s( dbc.Ldap(), dnKey, LDAP_SCOPE_ONELEVEL, TEXT("(cn=QTDC_*)"), rgptszAttrs, 0, &pRes); if(LDAP_SUCCESS != ldapRV) { printf( "Failed ldap_search_s (%lu)\n", LdapMapErrorToWin32(ldapRV) ); hr = HRESULT_FROM_WIN32(LdapMapErrorToWin32(ldapRV) ); __leave; } cEntries = ldap_count_entries( dbc.Ldap(), pRes ); if(cEntries < 1) __leave; pEntry = ldap_first_entry( dbc.Ldap(), pRes ); if(NULL == pEntry) { printf( "Invalid ldap_first_entry\n" ); __leave; } // Loop through the results. while(TRUE) { // Get the machine id. ppbvMachineId = ldap_get_values_len( dbc.Ldap(), pEntry, const_cast(s_Cn) ); if(NULL == ppbvMachineId) { printf( "Couldn't get machine ID\n" ); hr = TRK_E_CORRUPT_VOLTAB; __leave; } if((*ppbvMachineId)->bv_val == NULL) { printf( "Couldn't get machine ID\n" ); hr = TRK_E_CORRUPT_VOLTAB; __leave; } memcpy( &rgsDcEntries[cDcEntries].mcid, (*ppbvMachineId)->bv_val + 5, strlen((*ppbvMachineId)->bv_val+5)); // Get the creation time. pptszCreationTime = ldap_get_values(dbc.Ldap(), pEntry, const_cast(s_timeVolChange) ); if(NULL == pptszCreationTime) { printf( "Couldn't get the creation time\n" ); hr = TRK_E_CORRUPT_VOLTAB; __leave; } _stscanf(*pptszCreationTime, TEXT("%I64u"), &llCreationTime); rgsDcEntries[cDcEntries].cftCreation = CFILETIME(llCreationTime); // Get the last alive time. pptszLastAliveTime = ldap_get_values(dbc.Ldap(), pEntry, const_cast(s_timeRefresh) ); if(NULL == pptszLastAliveTime) { printf( "Couldn't get last alive time\n" ); hr = TRK_E_CORRUPT_VOLTAB; __leave; } _stscanf(*pptszLastAliveTime, TEXT("%I64u"), &llLastAliveTime); rgsDcEntries[cDcEntries].cftLastAlive = CFILETIME(llLastAliveTime); rgsDcEntries[cDcEntries].fSuspended = FALSE; if(((LONGLONG)cftNow - (LONGLONG)rgsDcEntries[cDcEntries].cftCreation) / 10000000 < configSvr.GetDcSuspensionPeriod() || ((LONGLONG)cftNow - (LONGLONG)rgsDcEntries[cDcEntries].cftLastAlive) / 10000000 > configSvr.GetDcSuspensionPeriod() ) { rgsDcEntries[cDcEntries].fSuspended = TRUE; } else if( rgsDcEntries[cDcEntries].mcid > mcidDesignated ) { mcidDesignated = rgsDcEntries[cDcEntries].mcid; } if (ppbvMachineId != NULL) { ldap_value_free_len(ppbvMachineId); ppbvMachineId = NULL; } if (pptszCreationTime != NULL) { ldap_value_free(pptszCreationTime); pptszCreationTime = NULL; } if (pptszLastAliveTime != NULL) { ldap_value_free(pptszLastAliveTime); pptszLastAliveTime = NULL; } cDcEntries++; pEntry = ldap_next_entry(dbc.Ldap(), pEntry); if(!pEntry) { break; } } // while( TRUE ) for( int iEntry = 0; iEntry < cDcEntries; iEntry++ ) { CFILETIME cftLocal; TCHAR tszTime[ 80 ]; printf( " %-16s ", &rgsDcEntries[iEntry].mcid ); if( rgsDcEntries[iEntry].mcid == mcidDesignated ) printf( " (** Designated **)\n" ); else if( rgsDcEntries[iEntry].fSuspended ) printf(" (suspended)\n" ); else printf(" (not suspended)\n" ); cftLocal = rgsDcEntries[iEntry].cftCreation.ConvertUtcToLocal(); cftLocal.Stringize( ELEMENTS(tszTime), tszTime ); _tprintf( TEXT(" Create = %s\n"), tszTime ); cftLocal = rgsDcEntries[iEntry].cftLastAlive.ConvertUtcToLocal(); cftLocal.Stringize( ELEMENTS(tszTime), tszTime ); _tprintf( TEXT(" Alive = %s\n"), tszTime ); } } __finally { if (ppbvMachineId != NULL) { ldap_value_free_len(ppbvMachineId); } if (pptszCreationTime != NULL) { ldap_value_free(pptszCreationTime); } if (pptszLastAliveTime != NULL) { ldap_value_free(pptszLastAliveTime); } if( NULL != pRes ) ldap_msgfree(pRes); } return hr; } */ BOOL DltAdminSvrStat( ULONG cArgs, const TCHAR * const rgptszArgs[], ULONG *pcEaten ) { NTSTATUS status; HRESULT hr = S_OK;; RPC_BINDING_HANDLE BindingHandle; BOOL fBound = FALSE; BOOL fShowDsInfo = FALSE; ULONG iDcName = 0; if( 1 <= cArgs && IsHelpArgument( rgptszArgs[0] )) { printf( "\nOption SvrStat\n" " Purpose: Query a DC for TrkSvr statistics\n" " Usage: -svrstat [options] \n" " E.g.: -svrstat ntdsdc0\n" " Note: To find a DC name for a domain, use the nltest tool\n" ); *pcEaten = 1; return( TRUE ); } _tprintf( TEXT("Checking for TrkSvr statistics\n"), rgptszArgs[0] ); if( 1 > cArgs ) { printf( "Invalid parameters. Use -? for usage info\n" ); *pcEaten = 0; return( FALSE ); } *pcEaten = 1; if( 2 <= cArgs && TEXT('-') == rgptszArgs[0][0] ) { if( TEXT('d') == rgptszArgs[0][1] || TEXT('D') == rgptszArgs[0][1] ) { fShowDsInfo = TRUE; } else { printf( "Invalid option. Use -? for help\n" ); return( FALSE ); } iDcName = 1; (*pcEaten)++; } __try { CFILETIME cftLocal(0); TCHAR tszLocalFileTime[ 80 ]; WCHAR wszAuthName[ 80 ]; WCHAR wszUser[ 80 ]; WCHAR wszDomain[ 80 ]; RPC_STATUS rpcstatus = RPC_S_OK; RPC_TCHAR * ptszStringBinding = NULL; TRKSVR_MESSAGE_UNION Msg; memset( &Msg, 0, sizeof(Msg) ); Msg.MessageType = STATISTICS; Msg.Priority = PRI_0; // Create a binding string rpcstatus = RpcStringBindingCompose(NULL, L"ncacn_np", const_cast(rgptszArgs[iDcName]), L"\\pipe\\trksvr", NULL, &ptszStringBinding); if( RPC_S_OK != rpcstatus ) { hr = HRESULT_FROM_WIN32( rpcstatus ); _tprintf( TEXT("Failed RpcStringBindingCompose (%d)\n"), rpcstatus ); goto Exit; } _tprintf( TEXT("String binding = %s\n"), ptszStringBinding ); // Get a client binding handle. rpcstatus = RpcBindingFromStringBinding(ptszStringBinding, &BindingHandle); RpcStringFree(&ptszStringBinding); if( RPC_S_OK != rpcstatus ) { _tprintf( TEXT("Failed RpcBindingFromStringBinding (%d)\n"), rpcstatus ); hr = HRESULT_FROM_WIN32( rpcstatus ); goto Exit; } fBound = TRUE; // Call up to TrkSvr __try { hr = LnkSvrMessage(BindingHandle, &Msg); } __except( EXCEPTION_EXECUTE_HANDLER ) { hr = HRESULT_FROM_WIN32( GetExceptionCode() ); } if( FAILED(hr) ) { _tprintf( TEXT("Failed LnkSvrMessage RPC (%08x)\n"), hr ); goto Exit; } // Dump the results _tprintf( TEXT("\n") ); _tprintf( TEXT("%-35s\t%d.%d (Build %d)\n"), TEXT("Version"), Msg.Statistics.Version.dwMajor, Msg.Statistics.Version.dwMinor, Msg.Statistics.Version.dwBuildNumber ); _tprintf( TEXT("\n") ); _tprintf( TEXT("%-35s\t%d\t%d\t%d\n"), TEXT("SyncVolume Requests/Errors/Threads"), Msg.Statistics.cSyncVolumeRequests, Msg.Statistics.cSyncVolumeErrors, Msg.Statistics.cSyncVolumeThreads ); _tprintf( TEXT("%-35s\t%d\t%d\n"), TEXT(" CreateVolume Requests/Errors"), Msg.Statistics.cCreateVolumeRequests, Msg.Statistics.cCreateVolumeErrors ); _tprintf( TEXT("%-35s\t%d\t%d\n"), TEXT(" ClaimVolume Requests/Errors"), Msg.Statistics.cClaimVolumeRequests, Msg.Statistics.cClaimVolumeErrors ); _tprintf( TEXT("%-35s\t%d\t%d\n"), TEXT(" QueryVolume Requests/Errors"), Msg.Statistics.cQueryVolumeRequests, Msg.Statistics.cQueryVolumeErrors ); _tprintf( TEXT("%-35s\t%d\t%d\n"), TEXT(" FindVolume Requests/Errors"), Msg.Statistics.cFindVolumeRequests, Msg.Statistics.cFindVolumeErrors ); _tprintf( TEXT("%-35s\t%d\t%d\n"), TEXT(" TestVolume Requests/Errors"), Msg.Statistics.cTestVolumeRequests, Msg.Statistics.cTestVolumeErrors ); _tprintf( TEXT("%-35s\t%d\t%d\t%d\n"), TEXT("Search Requests/Errors/Threads"), Msg.Statistics.cSearchRequests, Msg.Statistics.cSearchErrors, Msg.Statistics.cSearchThreads ); _tprintf( TEXT("%-35s\t%d\t%d\t%d\n"), TEXT("MoveNotify Requests/Errors/Threads"), Msg.Statistics.cMoveNotifyRequests, Msg.Statistics.cMoveNotifyErrors, Msg.Statistics.cMoveNotifyThreads ); _tprintf( TEXT("%-35s\t%d\t%d\t%d\n"), TEXT("Refresh Requests/Errors/Threads"), Msg.Statistics.cRefreshRequests, Msg.Statistics.cRefreshErrors, Msg.Statistics.cRefreshThreads ); _tprintf( TEXT("%-35s\t%d\t%d\t%d\n"), TEXT("DeleteNotify Requests/Errors/Threads"), Msg.Statistics.cDeleteNotifyRequests, Msg.Statistics.cDeleteNotifyErrors, Msg.Statistics.cDeleteNotifyThreads ); _tprintf( TEXT("\n") ); cftLocal = static_cast(Msg.Statistics.ftServiceStart).ConvertUtcToLocal(); cftLocal.Stringize( ELEMENTS(tszLocalFileTime), tszLocalFileTime ); _tprintf( TEXT("%-35s\t%08x:%08x\n%35s\t(%s local time)\n"), TEXT("Service start"), Msg.Statistics.ftServiceStart.dwHighDateTime, Msg.Statistics.ftServiceStart.dwLowDateTime, TEXT(""), tszLocalFileTime ); cftLocal = static_cast(Msg.Statistics.ftLastSuccessfulRequest).ConvertUtcToLocal(); cftLocal.Stringize( ELEMENTS(tszLocalFileTime), tszLocalFileTime ); _tprintf( TEXT("%-35s\t%08x:%08x\n%35s\t(%s local time)\n"), TEXT("Last successful request"), Msg.Statistics.ftLastSuccessfulRequest.dwHighDateTime, Msg.Statistics.ftLastSuccessfulRequest.dwLowDateTime, TEXT(""), tszLocalFileTime ); _tprintf( TEXT("%-35s\t%08x\n"), TEXT("Last Error"), Msg.Statistics.hrLastError ); _tprintf( TEXT("\nQuota Information:\n") ); _tprintf( TEXT(" %-32s\t%d\n"), TEXT("Move Limit"), Msg.Statistics.dwMoveLimit ); _tprintf( TEXT(" %-32s\t%d\n"), TEXT("Volume table cached count"), Msg.Statistics.dwCachedVolumeTableCount ); _tprintf( TEXT(" %-32s\t%d\n"), TEXT("Move table cached count"), Msg.Statistics.dwCachedMoveTableCount ); cftLocal = static_cast(Msg.Statistics.ftCacheLastUpdated).ConvertUtcToLocal(); cftLocal.Stringize( ELEMENTS(tszLocalFileTime), tszLocalFileTime ); _tprintf( TEXT(" %-32s\t%08x:%08x\n%35s\t(%s local time)\n"), TEXT("Cache counts last updated"), Msg.Statistics.ftCacheLastUpdated.dwHighDateTime, Msg.Statistics.ftCacheLastUpdated.dwLowDateTime, TEXT(""), tszLocalFileTime ); _tprintf( TEXT(" %-32s\t%s\n"), TEXT("Is designated DC"), Msg.Statistics.fIsDesignatedDc ? TEXT("Yes") : TEXT("No") ); _tprintf( TEXT("\n") ); cftLocal = static_cast(Msg.Statistics.ftNextGC).ConvertUtcToLocal(); cftLocal.Stringize( ELEMENTS(tszLocalFileTime), tszLocalFileTime ); _tprintf( TEXT("%-35s\t%08x:%08x\n%35s\t(%s local time)\n"), TEXT("Next GC"), Msg.Statistics.ftNextGC.dwHighDateTime, Msg.Statistics.ftNextGC.dwLowDateTime, TEXT(""), tszLocalFileTime ); _tprintf( TEXT("%-35s\t%d\n"), TEXT("Entries GC-ed"), Msg.Statistics.cEntriesGCed); _tprintf( TEXT("%-35s\t%d\n"), TEXT("Max DS write events"), Msg.Statistics.cMaxDsWriteEvents); _tprintf( TEXT("%-35s\t%d\n"), TEXT("Current failed writes"), Msg.Statistics.cCurrentFailedWrites); _tprintf( TEXT("\n") ); _tprintf( TEXT("%-35s\t%d\n"), TEXT("Refresh counter"), Msg.Statistics.lRefreshCounter ); _tprintf( TEXT("%-35s\t%d/%d/%d\n"), TEXT("Available/least/max RPC server threads"), Msg.Statistics.cAvailableRpcThreads, Msg.Statistics.cLowestAvailableRpcThreads, Msg.Statistics.cMaxRpcThreads ); _tprintf( TEXT("%-35s\t%d/%d\n"), TEXT("Current/most thread pool threads"), Msg.Statistics.cNumThreadPoolThreads, Msg.Statistics.cMostThreadPoolThreads ); /* _tprintf( TEXT("%-35s\t%s\n"), TEXT("Service controller state"), CDebugString( static_cast(Msg.Statistics.SvcCtrlState))._tsz ); */ //ShowMoveCounter( rgptszArgs[iDcName] ); } __except( EXCEPTION_EXECUTE_HANDLER ) { hr = GetExceptionCode(); } Exit: if( fBound ) RpcBindingFree( &BindingHandle ); return( SUCCEEDED(hr) ); } BOOL SetRefreshCounter( CDbConnection &dbc, CLdapVolumeKeyDn dnKey, const SequenceNumber seq ) { int ldapRV; HRESULT hr = E_FAIL; CTrkSvrConfiguration configSvr; configSvr.Initialize(); LDAPMod * mods[2]; __try { CLdapSeqNum lsn(seq); CLdapStringMod lsmSequence(s_timeRefresh, lsn, LDAP_MOD_REPLACE ); mods[0] = &lsmSequence._mod; mods[1] = 0; ldapRV = ldap_modify_s(dbc.Ldap(), dnKey, mods); if(LDAP_SUCCESS != ldapRV) { printf( "Failed ldap_modify_s(%lu)\n", LdapMapErrorToWin32(ldapRV) ); hr = HRESULT_FROM_WIN32(LdapMapErrorToWin32(ldapRV) ); __leave; } } __finally { } return SUCCEEDED(hr); } class CLdapSecret { public: CLdapSecret() { memset(_abPad,0,sizeof(_abPad)); } CLdapSecret(const CVolumeSecret &secret) { _secret = secret; memset(_abPad,0,sizeof(_abPad)); } CVolumeSecret _secret; BYTE _abPad[sizeof(GUID) - sizeof(CVolumeSecret)]; }; BOOL DltAdminSetVolumeSeqNumber( ULONG cArgs, const TCHAR * const rgptszArgs[], ULONG *pcEaten ) { NTSTATUS status; HRESULT hr = S_OK;; SequenceNumber seq; CVolumeId volid; CStringize stringize; if( 1 <= cArgs && IsHelpArgument( rgptszArgs[0] )) { printf( "\nOption SetVolSeq\n" " Purpose: Set the sequence number in a volume table entry\n" " Usage: -setvolseq \n" " E.g.: -setvolseq ntdsdc0 90 {d763433c-73a3-48c7-88a5-d6f3552835c6}\n" " Note: Requires write access to volume table in DS.\n" ); *pcEaten = 1; return( TRUE ); } _tprintf( TEXT("Setting sequence number in volume table\n"), rgptszArgs[0] ); if( 3 > cArgs ) { printf( "Invalid parameters. Use -? for usage info\n" ); *pcEaten = 0; return( FALSE ); } *pcEaten = 1; // Get the sequence number if( 1 != _stscanf( rgptszArgs[1], TEXT("%d"), &seq )) { printf( "Invalid sequence number. Use -? for usage info\n" ); return FALSE; } // Get the volid // mikehill_test DebugBreak(); stringize.Use( rgptszArgs[2] ); volid = stringize; /* { RPC_STATUS rpc_status = RPC_S_INVALID_STRING_UUID; TCHAR tszTemp[ MAX_PATH ]; TCHAR *ptszTemp = NULL; if( TEXT('{') == rgptszArgs[2][0] ) { _tcscpy( tszTemp, &rgptszArgs[2][1] ); ptszTemp = _tcschr( tszTemp, TEXT('}') ); if( NULL != ptszTemp ) { *ptszTemp = TEXT('\0'); rpc_status = UuidFromString( tszTemp, (GUID*)&volid ); } } if( RPC_S_OK != rpc_status ) { _tprintf( TEXT("Error: Invalid volume ID\n") ); return FALSE; } } */ // Set the sequence CDbConnection dbc; dbc.Initialize( NULL, rgptszArgs[0] ); CLdapVolumeKeyDn dnKey(dbc.GetBaseDn(), volid); return SetRefreshCounter( dbc, dnKey, seq ); } BOOL SetRefreshCounter2( CDbConnection &dbc, CLdapIdtKeyDn dnKey, const SequenceNumber seq ) { int ldapRV; HRESULT hr = E_FAIL; CTrkSvrConfiguration configSvr; configSvr.Initialize(); LDAPMod * mods[2]; __try { CLdapSeqNum lsn(seq); CLdapStringMod lsmSequence(s_timeRefresh, lsn, LDAP_MOD_REPLACE ); mods[0] = &lsmSequence._mod; mods[1] = 0; ldapRV = ldap_modify_s(dbc.Ldap(), dnKey, mods); if(LDAP_SUCCESS != ldapRV) { printf( "Failed ldap_modify_s(%lu)\n", LdapMapErrorToWin32(ldapRV) ); hr = HRESULT_FROM_WIN32(LdapMapErrorToWin32(ldapRV) ); __leave; } } __finally { } return SUCCEEDED(hr); } BOOL DltAdminSetDroidSeqNumber( ULONG cArgs, const TCHAR * const rgptszArgs[], ULONG *pcEaten ) { NTSTATUS status; HRESULT hr = S_OK;; SequenceNumber seq; CDomainRelativeObjId droid; CStringize stringize; if( 1 <= cArgs && IsHelpArgument( rgptszArgs[0] )) { printf( "\nOption SetDroidSeq\n" " Purpose: Set the sequence number in a move table entry\n" " Usage: -setdroidseq \n" " E.g.: -setdroidseq ntdsdc0 90 {d763433c-73a3-48c7-88a5-d6f3552835c6}{183c8367-a392-c784-88a5-d6f3552835c6}\n" " Note: Requires write access to volume table in DS.\n" ); *pcEaten = 1; return( TRUE ); } _tprintf( TEXT("Setting sequence number in move table\n"), rgptszArgs[0] ); if( 3 > cArgs ) { printf( "Invalid parameters. Use -? for usage info\n" ); *pcEaten = 0; return( FALSE ); } *pcEaten = 1; // Get the sequence number if( 1 != _stscanf( rgptszArgs[1], TEXT("%d"), &seq )) { printf( "Invalid sequence number. Use -? for usage info\n" ); return FALSE; } // Get the droid stringize.Use( rgptszArgs[2] ); droid = stringize; if( CDomainRelativeObjId() == droid ) { _tprintf( TEXT("Error: Invalid DROID\n") ); return FALSE; } // Set the sequence CDbConnection dbc; dbc.Initialize( NULL, rgptszArgs[0] ); CLdapIdtKeyDn dnKey(dbc.GetBaseDn(), droid); return SetRefreshCounter2( dbc, dnKey, seq ); }