748 lines
16 KiB
C++
748 lines
16 KiB
C++
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996.
|
|
//
|
|
// File: tldap.cxx
|
|
//
|
|
// Contents: Command line test utility for LDAP link tracking db
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
//
|
|
//
|
|
// History: 18-Nov-96 BillMo Created.
|
|
//
|
|
// Notes:
|
|
//
|
|
// Codework:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
#include "teststub.cxx"
|
|
|
|
#define TRKDATA_ALLOCATE
|
|
#include <trksvr.hxx>
|
|
#undef TRKDATA_ALLOCATE
|
|
|
|
#if DBG
|
|
|
|
class CTestSvrSvc
|
|
{
|
|
public:
|
|
|
|
void Initialize()
|
|
{
|
|
_svc.Initialize(STANDALONE_DEBUGGABLE_PROCESS);
|
|
}
|
|
|
|
void UnInitialize(HRESULT hr)
|
|
{
|
|
_svc.UnInitialize(hr);
|
|
}
|
|
|
|
void DoSwitch(TCHAR ** &tszArgs, int & cArgs, BOOL & fError);
|
|
|
|
private:
|
|
|
|
void DoAdd(TCHAR * pszKey, TCHAR * ptszNew, TCHAR * ptszBirth);
|
|
void DoDelete(TCHAR * ptszKey);
|
|
void DoModify(TCHAR * ptszKey, TCHAR * ptszNew, TCHAR * ptszBirth);
|
|
void DoQuery(TCHAR * ptszKey);
|
|
void DoTouch(TCHAR * ptszKey);
|
|
void DoFill(TCHAR * ptszNum);
|
|
void DoPurge();
|
|
void DoCachePurge();
|
|
void DoVolumeTable();
|
|
void DoShorten();
|
|
void DoRunTests();
|
|
void DoIdt();
|
|
|
|
void TryCreateVolume(const CMachineId & mcid,
|
|
const CVolumeSecret & secret,
|
|
CVolumeId * pVolumeId);
|
|
|
|
inline CIntraDomainTable & idt()
|
|
{
|
|
return(_svc._idt);
|
|
}
|
|
|
|
inline CVolumeTable & voltab()
|
|
{
|
|
return(_svc._voltab);
|
|
}
|
|
|
|
private:
|
|
|
|
CTrkSvrSvc _svc;
|
|
|
|
};
|
|
|
|
void
|
|
CTestSvrSvc::TryCreateVolume(const CMachineId & mcid,
|
|
const CVolumeSecret & secret,
|
|
CVolumeId * pVolumeId)
|
|
{
|
|
__try
|
|
{
|
|
voltab().CreateVolume(mcid, secret, pVolumeId);
|
|
}
|
|
__except(BreakOnDebuggableException())
|
|
{
|
|
printf("Exception %08X caught\n", GetExceptionCode());
|
|
}
|
|
}
|
|
|
|
void
|
|
CTestSvrSvc::DoAdd(TCHAR * ptszKey, TCHAR * ptszNew, TCHAR * ptszBirth)
|
|
{
|
|
__try
|
|
{
|
|
BOOL f = idt().Add(CDomainRelativeObjId(ptszKey), CDomainRelativeObjId(ptszNew), CDomainRelativeObjId(ptszBirth));
|
|
printf("Add returns %s\n", f ? "TRUE" : "FALSE");
|
|
}
|
|
__except (BreakOnDebuggableException())
|
|
{
|
|
printf("Exception %08X caught\n", GetExceptionCode());
|
|
}
|
|
}
|
|
|
|
void
|
|
CTestSvrSvc::DoDelete(TCHAR * ptszKey)
|
|
{
|
|
__try
|
|
{
|
|
BOOL f = idt().Delete(CDomainRelativeObjId(ptszKey));
|
|
printf("Delete returns %s\n", f ? "TRUE" : "FALSE");
|
|
}
|
|
__except (BreakOnDebuggableException())
|
|
{
|
|
printf("Exception %08X caught\n", GetExceptionCode());
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
CTestSvrSvc::DoModify(TCHAR * ptszKey, TCHAR * ptszNew, TCHAR * ptszBirth)
|
|
{
|
|
__try
|
|
{
|
|
BOOL f = idt().Modify(CDomainRelativeObjId(ptszKey), CDomainRelativeObjId(ptszNew), CDomainRelativeObjId(ptszBirth));
|
|
printf("Modify returns %s\n", f ? "TRUE" : "FALSE");
|
|
}
|
|
__except (BreakOnDebuggableException())
|
|
{
|
|
printf("Exception %08X caught\n", GetExceptionCode());
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void
|
|
CTestSvrSvc::DoQuery(TCHAR * ptszKey)
|
|
{
|
|
__try
|
|
{
|
|
CDomainRelativeObjId ldNew;
|
|
CDomainRelativeObjId ldBirth;
|
|
|
|
BOOL f = idt().Query(CDomainRelativeObjId(ptszKey), &ldNew, &ldBirth);
|
|
printf("Query returns %s\n", f ? "TRUE" : "FALSE");
|
|
if (f)
|
|
{
|
|
ldNew.DebugPrint(TEXT("ldNew="));
|
|
ldBirth.DebugPrint(TEXT("ldBirth="));
|
|
}
|
|
}
|
|
__except (BreakOnDebuggableException())
|
|
{
|
|
printf("Exception %08X caught\n", GetExceptionCode());
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
CTestSvrSvc::DoTouch(TCHAR * ptszKey)
|
|
{
|
|
__try
|
|
{
|
|
BOOL f = idt().Touch(CDomainRelativeObjId(ptszKey));
|
|
printf("Touch returns %s\n", f ? "TRUE" : "FALSE");
|
|
}
|
|
__except (BreakOnDebuggableException())
|
|
{
|
|
printf("Exception %08X caught\n", GetExceptionCode());
|
|
}
|
|
|
|
}
|
|
|
|
class CName
|
|
{
|
|
public:
|
|
CName(int i)
|
|
{
|
|
_tsz[0] = i/(26*26) + TEXT('a');
|
|
_tsz[1] = (i%(26*26))/26 + TEXT('a');
|
|
_tsz[2] = i%26 + TEXT('a');
|
|
_tsz[3] = 0;
|
|
}
|
|
|
|
operator TCHAR * ()
|
|
{
|
|
return(_tsz);
|
|
}
|
|
private:
|
|
TCHAR _tsz[10];
|
|
};
|
|
|
|
void
|
|
CTestSvrSvc::DoFill(TCHAR * ptszNum)
|
|
{
|
|
int cEntries;
|
|
|
|
_stscanf(ptszNum, TEXT("%d"), &cEntries);
|
|
|
|
__try
|
|
{
|
|
for (int i=0; i<cEntries; i++)
|
|
{
|
|
CDomainRelativeObjId ldNew, ldBirth;
|
|
idt().Add(CDomainRelativeObjId(CName(i)), ldNew, ldBirth);
|
|
}
|
|
}
|
|
__except (BreakOnDebuggableException())
|
|
{
|
|
printf("Exception %08X caught\n", GetExceptionCode());
|
|
}
|
|
}
|
|
|
|
void
|
|
CTestSvrSvc::DoPurge()
|
|
{
|
|
int cEntries;
|
|
|
|
__try
|
|
{
|
|
idt().PurgeAll();
|
|
voltab().PurgeAll();
|
|
}
|
|
__except (BreakOnDebuggableException())
|
|
{
|
|
printf("Exception %08X caught\n", GetExceptionCode());
|
|
}
|
|
}
|
|
|
|
void
|
|
CTestSvrSvc::DoCachePurge()
|
|
{
|
|
const int size = 64000000;
|
|
LPDWORD p, pOrig;
|
|
|
|
p = pOrig = (LPDWORD)GlobalAlloc(GMEM_FIXED, size);
|
|
if (p)
|
|
{
|
|
for (int i=0; i<size/sizeof(*p); i++)
|
|
{
|
|
*p++ = 0;
|
|
}
|
|
GlobalFree((HGLOBAL)pOrig);
|
|
}
|
|
else
|
|
printf("couldn't alloc 64M");
|
|
}
|
|
|
|
#define Check(exp) TrkAssert(exp)
|
|
|
|
void
|
|
CTestSvrSvc::DoVolumeTable()
|
|
{
|
|
// test out volume table functionality
|
|
HRESULT hr;
|
|
CMachineId mcid1("mcid1");
|
|
CMachineId mcid2("mcid2");
|
|
CMachineId mcid3("mcid3");
|
|
CMachineId mcid4("mcid4");
|
|
CVolumeSecret secret1;
|
|
CVolumeSecret secret2;
|
|
CVolumeSecret secret3;
|
|
CVolumeSecret secret4;
|
|
CVolumeId volume1;
|
|
CVolumeId volume2;
|
|
CVolumeId volume3;
|
|
CVolumeId volume4;
|
|
SequenceNumber seq;
|
|
FILETIME ft;
|
|
|
|
DoPurge();
|
|
|
|
UuidCreate((GUID*)&volume1);
|
|
UuidCreate((GUID*)&volume2);
|
|
UuidCreate((GUID*)&volume3);
|
|
UuidCreate((GUID*)&volume4);
|
|
UuidCreate((GUID*)&secret1);
|
|
UuidCreate((GUID*)&secret2);
|
|
UuidCreate((GUID*)&secret3);
|
|
UuidCreate((GUID*)&secret4);
|
|
|
|
// Check Queries
|
|
|
|
CFILETIME cftStart;
|
|
|
|
// check non-existent volume
|
|
hr = voltab().QueryVolume(mcid1, volume1, &seq, &ft);
|
|
Check(hr == TRK_S_VOLUME_NOT_FOUND);
|
|
|
|
// exception when setting seq number on non-existent volume
|
|
hr = voltab().SetSequenceNumber(volume1, seq);
|
|
Check(hr != S_OK);
|
|
|
|
hr = voltab().QueryVolume(mcid1, volume1, &seq, &ft);
|
|
Check(hr == TRK_S_VOLUME_NOT_FOUND);
|
|
|
|
// exception when setting seq number on non-existent volume
|
|
hr = voltab().SetSequenceNumber(volume1, seq);
|
|
Check(hr != S_OK);
|
|
|
|
// create a volume
|
|
|
|
TryCreateVolume(mcid1, secret1, & volume1);
|
|
|
|
// check we can query it if it is us
|
|
hr = voltab().QueryVolume(mcid1, volume1, &seq, &ft);
|
|
Check(hr == S_OK);
|
|
|
|
// check we can't query it if it isn't us
|
|
hr = voltab().QueryVolume(mcid2, volume1, &seq, &ft);
|
|
Check(hr == TRK_S_VOLUME_NOT_OWNED);
|
|
|
|
// Check Claims
|
|
|
|
// claim a non-existent volume
|
|
hr = voltab().ClaimVolume(mcid1, volume2, secret1, secret1, &seq, &ft);
|
|
Check(hr == TRK_S_VOLUME_NOT_FOUND);
|
|
|
|
// claim an existent volume using the wrong secret
|
|
hr = voltab().ClaimVolume(mcid2, volume1, secret2, secret2, &seq, &ft);
|
|
Check(hr == TRK_E_VOLUME_ACCESS_DENIED);
|
|
|
|
// claim an existent volume using the right secret
|
|
hr = voltab().ClaimVolume(mcid2, volume1, secret1, secret1, &seq, &ft);
|
|
Check(hr == S_OK);
|
|
|
|
// check the query fails from the original machine
|
|
hr = voltab().QueryVolume(mcid1, volume1, &seq, &ft);
|
|
Check(hr == TRK_S_VOLUME_NOT_OWNED);
|
|
|
|
// check the query succeeds from the new machine
|
|
hr = voltab().QueryVolume(mcid2, volume1, &seq, &ft);
|
|
Check(hr == S_OK);
|
|
|
|
// Check sequence numbers
|
|
SequenceNumber seq2 = seq;
|
|
seq ++;
|
|
hr = voltab().SetSequenceNumber(volume1, seq);
|
|
Check(hr == S_OK);
|
|
|
|
SequenceNumber seq3;
|
|
hr = voltab().QueryVolume(mcid2, volume1, &seq3, &ft);
|
|
Check(hr == S_OK);
|
|
|
|
Check(seq3 == seq);
|
|
Check(seq2 + 1 == seq);
|
|
|
|
}
|
|
|
|
class CSegString
|
|
{
|
|
public:
|
|
CSegString(int length);
|
|
~CSegString();
|
|
|
|
|
|
private:
|
|
|
|
};
|
|
|
|
|
|
class CSegment
|
|
{
|
|
public:
|
|
CSegment() { _fInitialized = FALSE; }
|
|
~CSegment();
|
|
|
|
const CDomainRelativeObjId Current();
|
|
const CDomainRelativeObjId New();
|
|
const CDomainRelativeObjId Birth();
|
|
|
|
private:
|
|
BOOL _fInitialized;
|
|
};
|
|
|
|
class COrder
|
|
{
|
|
public:
|
|
COrder(int iLength, int iCurrent) : _iLength(iLength) { }
|
|
~COrder();
|
|
|
|
BOOL GetSegment(CSegment * pSegment);
|
|
|
|
private:
|
|
|
|
int _iLength;
|
|
|
|
};
|
|
|
|
class COrderEnum
|
|
{
|
|
public:
|
|
COrderEnum(int length);
|
|
~COrderEnum();
|
|
|
|
BOOL GetOrder(COrder * pOrder);
|
|
|
|
private:
|
|
int _iCurrent;
|
|
int _iEnd;
|
|
int _iLength;
|
|
};
|
|
|
|
COrderEnum::COrderEnum(int iLength)
|
|
{
|
|
_iLength = iLength;
|
|
_iCurrent = 1;
|
|
_iEnd = 1;
|
|
|
|
while (iLength)
|
|
{
|
|
_iEnd *= iLength;
|
|
iLength --;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
COrderEnum::GetOrder(COrder * pOrder)
|
|
{
|
|
if (_iCurrent > _iEnd)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
void
|
|
CTestSvrSvc::DoIdt()
|
|
{
|
|
int cChanges=0;
|
|
|
|
CDomainRelativeObjId droidCurrent, droidBirth, droidNew;
|
|
|
|
memcpy( &droidCurrent, "12345678", 8 );
|
|
droidBirth = droidCurrent;
|
|
memcpy( &droidNew, "87654321", 8 );
|
|
|
|
_svc.MoveNotify(droidCurrent, droidBirth, droidNew, &cChanges);
|
|
|
|
CDomainRelativeObjId droidNewRead, droidBirthRead;
|
|
|
|
idt().Query(droidBirth, &droidNewRead, &droidBirthRead);
|
|
|
|
Check( droidNewRead == droidNew );
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
// Each letter represents a (volume,oid) pair
|
|
//
|
|
// Various string lengths:
|
|
//
|
|
// Length 1:
|
|
// a->b a (1 order A)
|
|
//
|
|
//
|
|
// Length 2:
|
|
// a->b a, b->c a (2 orders AB, BA)
|
|
//
|
|
//
|
|
// Length 3:
|
|
// a->b a, b->c a, c->d a (6 orders ABC, ACB, BAC, BCA, CAB, CBA)
|
|
//
|
|
//
|
|
// Each combination could have a non-matching birth id which should prevent shortening and search
|
|
// Each segment can be created either through replication (directly to idt) or
|
|
// through MoveNotify.
|
|
// Each segment can be shortened through MoveNotify or Search
|
|
//
|
|
|
|
// three lengths
|
|
for (int l=1; l<=3; l++)
|
|
{
|
|
COrderEnum oe(l);
|
|
COrder o;
|
|
|
|
while (oe.GetOrder(&o))
|
|
{
|
|
CSegString ss(l); // make segment string of length l
|
|
|
|
BOOL fFirst = TRUE;
|
|
CSegment seg, segFirst, segLast;
|
|
int index;
|
|
|
|
while (-1 != (index = o.GetIndex()))
|
|
{
|
|
seg = ss[index];
|
|
|
|
if (fFirst)
|
|
{
|
|
segFirst = seg;
|
|
fFirst = FALSE;
|
|
}
|
|
|
|
TRKSVR_MOVE_NOTIFICATION Notification;
|
|
Notification.ldCurrent = seg.Current();
|
|
Notification.ldNew = seg.New();
|
|
Notification.ldBirth = seg.Birth();
|
|
|
|
_svc.MoveNotify(Notification);
|
|
|
|
segLast = seg;
|
|
}
|
|
|
|
CDomainRelativeObjId ldNew, ldBirth;
|
|
|
|
idt().Query(segFirst.Birth(), &ldNew, &ldBirth);
|
|
|
|
Check(ldNew == segLast.Current());
|
|
}
|
|
}
|
|
|
|
#endif // #if 0
|
|
|
|
}
|
|
|
|
void
|
|
CTestSvrSvc::DoRunTests()
|
|
{
|
|
DoVolumeTable();
|
|
DoIdt();
|
|
}
|
|
|
|
|
|
void
|
|
CTestSvrSvc::DoSwitch(TCHAR ** &tszArgs, int & cArgs, BOOL & fError)
|
|
{
|
|
|
|
if (cArgs == 0)
|
|
{
|
|
return;
|
|
}
|
|
switch (tszArgs[0][1])
|
|
{
|
|
case TEXT('a'):
|
|
case TEXT('A'):
|
|
if (cArgs >= 4)
|
|
{
|
|
DoAdd(tszArgs[1], tszArgs[2], tszArgs[3]);
|
|
cArgs -= 4;
|
|
tszArgs += 4;
|
|
fError = FALSE;
|
|
}
|
|
break;
|
|
case TEXT('d'):
|
|
case TEXT('D'):
|
|
if (cArgs >= 2)
|
|
{
|
|
DoDelete(tszArgs[1]);
|
|
cArgs -= 2;
|
|
tszArgs += 2;
|
|
fError = FALSE;
|
|
}
|
|
break;
|
|
case TEXT('m'):
|
|
case TEXT('M'):
|
|
if (cArgs >= 4)
|
|
{
|
|
DoModify(tszArgs[1], tszArgs[2], tszArgs[3]);
|
|
cArgs -= 4;
|
|
tszArgs += 4;
|
|
fError = FALSE;
|
|
}
|
|
break;
|
|
case TEXT('q'):
|
|
case TEXT('Q'):
|
|
if (cArgs >= 2)
|
|
{
|
|
DoQuery(tszArgs[1]);
|
|
cArgs -= 2;
|
|
tszArgs += 2;
|
|
fError = FALSE;
|
|
}
|
|
break;
|
|
case TEXT('t'):
|
|
case TEXT('T'):
|
|
if (cArgs >= 2)
|
|
{
|
|
DoTouch(tszArgs[1]);
|
|
cArgs -= 2;
|
|
tszArgs += 2;
|
|
fError = FALSE;
|
|
}
|
|
break;
|
|
|
|
case TEXT('f'):
|
|
case TEXT('F'):
|
|
if (cArgs >= 2)
|
|
{
|
|
DoFill(tszArgs[1]);
|
|
cArgs -= 2;
|
|
tszArgs += 2;
|
|
fError = FALSE;
|
|
}
|
|
break;
|
|
|
|
case TEXT('p'):
|
|
case TEXT('P'):
|
|
if (cArgs >= 1)
|
|
{
|
|
DoPurge();
|
|
cArgs -= 1;
|
|
tszArgs += 1;
|
|
fError = FALSE;
|
|
}
|
|
break;
|
|
case TEXT('c'):
|
|
case TEXT('C'):
|
|
DoCachePurge();
|
|
cArgs -= 1;
|
|
tszArgs += 1;
|
|
fError = FALSE;
|
|
break;
|
|
|
|
case TEXT('r'):
|
|
case TEXT('R'):
|
|
DoRunTests();
|
|
cArgs -= 1;
|
|
tszArgs += 1;
|
|
fError = FALSE;
|
|
break;
|
|
|
|
case TEXT('i'):
|
|
case TEXT('I'):
|
|
printf("Type a command line switch at the prompt (control-c to exit.)\n");
|
|
do
|
|
{
|
|
|
|
TCHAR buf[256];
|
|
TCHAR * tszArgs2[16];
|
|
TCHAR ** tszArgsI = tszArgs2;
|
|
int cArgsI=0;
|
|
BOOL fError2;
|
|
|
|
printf("> ");
|
|
|
|
_getts(buf);
|
|
|
|
TCHAR * p = buf;
|
|
|
|
while (*p)
|
|
{
|
|
tszArgs2[cArgsI++] = p++;
|
|
while (*p && *p != TEXT(' ')) p++;
|
|
if (*p == ' ')
|
|
{
|
|
*p = 0;
|
|
p++;
|
|
}
|
|
}
|
|
|
|
DoSwitch(tszArgsI, cArgsI, fError2);
|
|
}
|
|
while (TRUE);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
EXTERN_C int __cdecl _tmain(int cArgs, TCHAR **tszArgs )
|
|
{
|
|
BOOL fError = FALSE;
|
|
HRESULT hr;
|
|
LARGE_INTEGER liFreq;
|
|
CTestSvrSvc test;
|
|
|
|
__try
|
|
{
|
|
|
|
TrkDebugCreate( TRK_DBG_FLAGS_WRITE_TO_DBG | TRK_DBG_FLAGS_WRITE_TO_STDOUT, "TLDAP" );
|
|
g_Debug = 0xffffffff & ~TRKDBG_WORKMAN;
|
|
test.Initialize();
|
|
|
|
cArgs--;
|
|
tszArgs++;
|
|
redo:
|
|
if (cArgs == 0)
|
|
{
|
|
fError = TRUE;
|
|
}
|
|
|
|
|
|
while (!fError && cArgs > 0)
|
|
{
|
|
fError = TRUE;
|
|
if (tszArgs[0][0] == '-' || tszArgs[0][0] == '/')
|
|
{
|
|
test.DoSwitch(tszArgs, cArgs, fError);
|
|
}
|
|
}
|
|
|
|
if (fError)
|
|
{
|
|
printf("Usage: \n");
|
|
printf(" Operation Params\n");
|
|
printf(" --------- ------\n");
|
|
printf(" Add -a <key> <cur> <birthid>\n");
|
|
printf(" Delete -d <key>\n");
|
|
printf(" Modify -m <key> <cur> <birthid>\n");
|
|
printf(" Query -q <key>\n");
|
|
printf(" Touch -t <key>\n");
|
|
printf(" Fill -f <number of entries> // aaa,aab,aac ...\n");
|
|
printf(" Purge -p 'purge all server database state'\n");
|
|
printf(" Cache Purge -c\n");
|
|
printf(" Run tests -r\n");
|
|
printf(" Interactive -i\n");
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
__except (BreakOnDebuggableException())
|
|
{
|
|
printf("Exception number %08X caught\n", GetExceptionCode());
|
|
hr = GetExceptionCode();
|
|
}
|
|
|
|
test.UnInitialize(hr);
|
|
|
|
Exit:
|
|
|
|
return(0);
|
|
}
|
|
|
|
#else
|
|
EXTERN_C int __cdecl _tmain(int cArgs, TCHAR **tszArgs )
|
|
{
|
|
printf("Retail build of tldap.exe doesn't run\n");
|
|
return(0);
|
|
}
|
|
#endif
|
|
|