654 lines
20 KiB
C++
654 lines
20 KiB
C++
#ifndef _WIN32_WINNT
|
|
#define _WIN32_WINNT 0x0400
|
|
#endif
|
|
|
|
#include <stdinc.h>
|
|
#define _ATL_NO_DEBUG_CRT
|
|
#define _ASSERTE _ASSERT
|
|
#include <atlbase.h>
|
|
CComModule _Module;
|
|
#include <atlcom.h>
|
|
#include <atlimpl.cpp>
|
|
|
|
#include "nntpdrv.h"
|
|
|
|
GET_DEFAULT_DOMAIN_NAME_FN pfnGetDefaultDomainName = NULL;
|
|
HANDLE g_hProcessImpersonationToken = NULL;
|
|
|
|
// INI file keys, etc
|
|
static const char g_pszDefaultSectionName[] = "testnt";
|
|
#define INI_KEY_MBPATH "MetabasePath"
|
|
#define DEF_KEY_MBPATH "/LM/testnt"
|
|
#define INI_KEY_GROUPNAME "Group%i"
|
|
#define INI_KEY_INSERTORDER "InsertOrder"
|
|
#define INI_KEY_REMOVEORDER "RemoveOrder"
|
|
#define INI_KEY_LISTORDER "ListOrder"
|
|
#define INI_KEY_WILDMAT "Wildmat"
|
|
#define INI_KEY_WILDMATLISTORDER "WildmatListOrder"
|
|
|
|
// keys expected in the vroot
|
|
#define PROGID_NO_DRIVER L"TestNT.NoDriver"
|
|
#define VRPATH L""
|
|
|
|
// an array of groups that we'll play with
|
|
DWORD g_cGroups;
|
|
char **g_rgszGroupList;
|
|
char **g_rgszInsertOrder;
|
|
char **g_rgszRemoveOrder;
|
|
char **g_rgszListOrder;
|
|
DWORD g_cWildmatGroups;
|
|
char **g_rgszWildmatListOrder;
|
|
char g_szWildmat[1024];
|
|
|
|
// path to our corner of the metabase
|
|
char g_szMBPath[1024];
|
|
WCHAR g_wszMBPath[1024];
|
|
|
|
// our newstree file
|
|
char g_szGroupList[1024];
|
|
char g_szVarGroupList[1024];
|
|
|
|
// our vroot table
|
|
CNNTPVRootTable *g_pVRTable;
|
|
CNewsTreeCore *g_pNewsTree;
|
|
|
|
// global count of errors
|
|
LONG g_cErrors;
|
|
|
|
void Verify(BOOL fTest, const char *szError, const char *szContext, DWORD dwLine) {
|
|
if (fTest) return;
|
|
InterlockedIncrement(&g_cErrors);
|
|
printf("ERROR: line %i -- %s (%s)\n", dwLine, szError, szContext);
|
|
_ASSERT(FALSE);
|
|
}
|
|
|
|
#define V(__f__, __szError__, __szContext__) Verify(__f__, __szError__, __szContext__, __LINE__)
|
|
|
|
void StartHintFunction( void )
|
|
{}
|
|
|
|
DWORD INNHash( PBYTE pb, DWORD )
|
|
{ return 0; }
|
|
|
|
BOOL fTestComponents( LPCSTR what )
|
|
{ return TRUE; }
|
|
|
|
|
|
// get a DWORD from an INI file
|
|
int GetINIDWord(const char *szINIFile, const char *pszSectionName, const char *szKey, int dwDefault) {
|
|
char szBuf[MAX_PATH];
|
|
|
|
GetPrivateProfileString(pszSectionName,
|
|
szKey,
|
|
"default",
|
|
szBuf,
|
|
MAX_PATH,
|
|
szINIFile);
|
|
|
|
if (strcmp(szBuf, "default") == 0) {
|
|
return dwDefault;
|
|
} else {
|
|
return atoi(szBuf);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CopyUnicodeStringIntoAscii(
|
|
IN LPSTR AsciiString,
|
|
IN LPWSTR UnicodeString
|
|
)
|
|
{
|
|
while ( (*AsciiString++ = (CHAR)*UnicodeString++) != '\0');
|
|
|
|
} // CopyUnicodeStringIntoAscii
|
|
|
|
//
|
|
// parse a string from the INI file into one of our arrays of groups.
|
|
// the string should be a comma delimited list of number which contains no
|
|
// duplicates. the numbers are indexs into the g_rgszGroupList. this
|
|
// builds up rgszArray to be in the order specified by the indexes.
|
|
//
|
|
// parameters:
|
|
// szINIFile - the INI file to read from
|
|
// pszSectionName - the section in the INI file to read from
|
|
// pszKeyName - the key to read
|
|
// rgszArray - the array of string pointers to populate
|
|
// pdwCount - if this is NULL then this function requires that
|
|
// rgszArray is populated to be the same length as g_cGroups.
|
|
// otherwise this returns the number of groups in the array.
|
|
//
|
|
void ParseIntoArray(const char *szINIFile,
|
|
const char *pszSectionName,
|
|
const char *pszKeyName,
|
|
char **rgszArray,
|
|
DWORD *pdwCount)
|
|
{
|
|
char szBuf[1024];
|
|
GetPrivateProfileString(pszSectionName,
|
|
pszKeyName,
|
|
"",
|
|
szBuf,
|
|
1024,
|
|
szINIFile);
|
|
|
|
V(*szBuf != 0, "Missing required key", pszKeyName);
|
|
|
|
// used to find duplicates
|
|
BOOL *rgfUsed = new BOOL[g_cGroups];
|
|
V(rgfUsed != NULL, "memory allocation for failed", "rgfUsed");
|
|
ZeroMemory(rgfUsed, sizeof(BOOL) * g_cGroups);
|
|
|
|
char *p = szBuf;
|
|
char *pComma = NULL;
|
|
DWORD i = 0;
|
|
do {
|
|
// find the next comma
|
|
pComma = strchr(p, ',');
|
|
// set it to 0 if it exists
|
|
if (pComma != NULL) *pComma = 0;
|
|
|
|
// convert the current text string (which should be anumber) into a #
|
|
DWORD iGroupList = atoi(p);
|
|
// make sure that it is valid
|
|
V(i < g_cGroups, "array contains too many items", pszKeyName);
|
|
V(!(rgfUsed[i]), "array contains duplicate indexes", pszKeyName);
|
|
rgfUsed[i] = TRUE;
|
|
|
|
if (i < g_cGroups) {
|
|
V(iGroupList >= 0 && iGroupList < g_cGroups, "array index out of bounds", pszKeyName);
|
|
rgszArray[i] = g_rgszGroupList[iGroupList];
|
|
}
|
|
|
|
// move our pointer to the next item in the list
|
|
if (pComma != NULL) p = pComma + 1;
|
|
i++;
|
|
} while (pComma != NULL);
|
|
|
|
if (pdwCount == NULL) {
|
|
V(i == g_cGroups, "array doesn't contain enough items", pszKeyName);
|
|
} else {
|
|
*pdwCount = i;
|
|
}
|
|
|
|
delete[] rgfUsed;
|
|
}
|
|
|
|
// read our parameters from the INI file.
|
|
void ReadINIFile(const char *szINIFile, const char *pszSectionName) {
|
|
char szBuf[1024];
|
|
DWORD i;
|
|
|
|
// get the base metabase path
|
|
GetPrivateProfileString(pszSectionName,
|
|
INI_KEY_MBPATH,
|
|
DEF_KEY_MBPATH,
|
|
szBuf,
|
|
1024,
|
|
szINIFile);
|
|
mbstowcs(g_wszMBPath, szBuf, 1024);
|
|
strcpy(g_szMBPath, szBuf);
|
|
printf("metabase path = %s\n", g_szMBPath);
|
|
|
|
// get the wildmat used for the wildmat list test
|
|
GetPrivateProfileString(pszSectionName,
|
|
INI_KEY_WILDMAT,
|
|
"",
|
|
szBuf,
|
|
1024,
|
|
szINIFile);
|
|
V(*szBuf != 0, "Required key not found in INI file", INI_KEY_WILDMAT);
|
|
strcpy(g_szWildmat, szBuf);
|
|
|
|
printf("reading groups from INI file\n");
|
|
// get the number of vroots listed in the INI file
|
|
for (g_cGroups = 0; *szBuf != 0; g_cGroups++) {
|
|
char szKey[20];
|
|
sprintf(szKey, INI_KEY_GROUPNAME, g_cGroups);
|
|
GetPrivateProfileString(pszSectionName,
|
|
szKey,
|
|
"",
|
|
szBuf,
|
|
1024,
|
|
szINIFile);
|
|
}
|
|
// fix off by one error
|
|
g_cGroups--;
|
|
V(g_cGroups != 0, "at least one group must be specified", NULL);
|
|
|
|
// allocate an array of groups
|
|
g_rgszGroupList = new PCHAR[g_cGroups];
|
|
g_rgszInsertOrder = new PCHAR[g_cGroups];
|
|
g_rgszRemoveOrder = new PCHAR[g_cGroups];
|
|
g_rgszListOrder = new PCHAR[g_cGroups];
|
|
g_rgszWildmatListOrder = new PCHAR[g_cGroups];
|
|
|
|
for (i = 0; i < g_cGroups; i++) {
|
|
char szKey[20];
|
|
sprintf(szKey, INI_KEY_GROUPNAME, i);
|
|
GetPrivateProfileString(pszSectionName,
|
|
szKey,
|
|
"",
|
|
szBuf,
|
|
1024,
|
|
szINIFile);
|
|
g_rgszGroupList[i] = new char[lstrlen(szBuf) + 1];
|
|
lstrcpy(g_rgszGroupList[i], szBuf);
|
|
}
|
|
|
|
ParseIntoArray(szINIFile, pszSectionName,
|
|
INI_KEY_INSERTORDER, g_rgszInsertOrder, NULL);
|
|
ParseIntoArray(szINIFile, pszSectionName,
|
|
INI_KEY_REMOVEORDER, g_rgszRemoveOrder, NULL);
|
|
ParseIntoArray(szINIFile, pszSectionName,
|
|
INI_KEY_LISTORDER, g_rgszListOrder, NULL);
|
|
ParseIntoArray(szINIFile, pszSectionName,
|
|
INI_KEY_WILDMATLISTORDER, g_rgszWildmatListOrder,
|
|
&g_cWildmatGroups);
|
|
|
|
if (g_cErrors > 0) {
|
|
printf("errors parsing INI file\n");
|
|
exit(g_cErrors);
|
|
}
|
|
printf("read %i groups from INI file\n", g_cGroups);
|
|
}
|
|
|
|
void Initialize(BOOL fDeleteGroupList) {
|
|
HRESULT hr;
|
|
BOOL fFatal;
|
|
static IMSAdminBaseW *pMB;
|
|
METADATA_HANDLE hmRoot;
|
|
|
|
// initialize COM and the metabase
|
|
printf("initializing metabase\n");
|
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
V(SUCCEEDED(hr), "CoInitializeEx", NULL);
|
|
|
|
hr = CoCreateInstance(CLSID_MSAdminBase_W, NULL, CLSCTX_ALL,
|
|
IID_IMSAdminBase_W, (LPVOID *) &pMB);
|
|
V(hr == S_OK, "CoCreateInstance", NULL);
|
|
|
|
// create a vroot entry for the root. we don't have any other
|
|
// vroot entries
|
|
printf("creating virtual root hierarchy\n");
|
|
DWORD i = 0;
|
|
do {
|
|
hr = pMB->OpenKey(METADATA_MASTER_ROOT_HANDLE,
|
|
L"",
|
|
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
|
|
100,
|
|
&hmRoot);
|
|
if (FAILED(hr) && i++ < 5) Sleep(50);
|
|
} while (FAILED(hr) && i < 5);
|
|
V(hr == S_OK, "metabase OpenKey(root)", NULL);
|
|
|
|
// first we delete whatever exists in the metabase under this path,
|
|
// then we create a new area to play in
|
|
pMB->DeleteKey(hmRoot, g_wszMBPath);
|
|
printf("creating key %s\n", g_wszMBPath);
|
|
hr = pMB->AddKey(hmRoot, g_wszMBPath);
|
|
V(hr == S_OK, "AddKey failed", g_szMBPath);
|
|
// we configure one root vroot with parameters set to create no driver
|
|
METADATA_RECORD mdrProgID = {
|
|
MD_VR_DRIVER_PROGID,
|
|
METADATA_INHERIT,
|
|
ALL_METADATA,
|
|
STRING_METADATA,
|
|
(lstrlenW(PROGID_NO_DRIVER)+1) * sizeof(WCHAR),
|
|
(BYTE *) PROGID_NO_DRIVER,
|
|
0
|
|
};
|
|
printf("setting MD_VR_DRIVER_PROGID = \"%S\"\n", PROGID_NO_DRIVER);
|
|
hr = pMB->SetData(hmRoot, g_wszMBPath, &mdrProgID);
|
|
V(hr == S_OK, "SetData(MD_VR_DRIVER_PROGID) failed", g_szMBPath);
|
|
|
|
METADATA_RECORD mdrVRPath = {
|
|
MD_VR_PATH,
|
|
METADATA_INHERIT,
|
|
ALL_METADATA,
|
|
STRING_METADATA,
|
|
(lstrlenW(VRPATH)+1) * sizeof(WCHAR),
|
|
(BYTE *) VRPATH,
|
|
0
|
|
};
|
|
printf("setting MD_VR_PATH = \"%S\"\n", VRPATH);
|
|
hr = pMB->SetData(hmRoot, g_wszMBPath, &mdrVRPath);
|
|
V(hr == S_OK, "SetData(MD_VR_PATH) failed", g_szMBPath);
|
|
|
|
pMB->CloseKey(hmRoot);
|
|
pMB->Release();
|
|
|
|
// initialize our news tree
|
|
printf("initializing newstree object\n");
|
|
g_pNewsTree = new CNewsTreeCore();
|
|
g_pVRTable = new CNNTPVRootTable(g_pNewsTree->GetINewsTree(),
|
|
CNewsTreeCore::VRootRescanCallback);
|
|
g_pNewsTree->Init(g_pVRTable, fFatal, 100, TRUE);
|
|
|
|
// initialize the vroot table
|
|
printf("initializing vroot table\n");
|
|
hr = g_pVRTable->Initialize(g_szMBPath);
|
|
printf("g_pVRTable->Initialize(\"%s\") returned %x\n", g_szMBPath, hr);
|
|
V(hr == S_OK, "g_pVRTable->Initialize() failed", g_szMBPath);
|
|
|
|
// load the newstree from disk
|
|
// figure out a group.lst filename
|
|
GetEnvironmentVariable("temp", g_szGroupList, 1024);
|
|
lstrcat(g_szGroupList, "\\group.lst");
|
|
printf("using group.lst path %s\n", g_szGroupList);
|
|
if (fDeleteGroupList) DeleteFile(g_szGroupList);
|
|
GetEnvironmentVariable("temp", g_szVarGroupList, 1024);
|
|
lstrcat(g_szVarGroupList, "\\groupvar.lst");
|
|
printf("using groupvar.lst path %s\n", g_szVarGroupList);
|
|
if (fDeleteGroupList) DeleteFile(g_szVarGroupList);
|
|
g_pNewsTree->LoadTree(g_szGroupList, g_szVarGroupList);
|
|
}
|
|
|
|
void Shutdown() {
|
|
g_pNewsTree->StopTree();
|
|
g_pNewsTree->TermTree();
|
|
delete g_pVRTable;
|
|
delete g_pNewsTree;
|
|
}
|
|
|
|
void List(BOOL fFull = FALSE, CNewsTreeCore *pNT = g_pNewsTree) {
|
|
CGroupIteratorCore *pi = pNT->ActiveGroups();
|
|
DWORD i = 0;
|
|
|
|
printf("-- group list\n");
|
|
while (!pi->IsEnd()) {
|
|
char szBuf[1024];
|
|
CGRPCOREPTR pGroup = pi->Current(), pGroup2 = NULL, pGroup3 = NULL;
|
|
INNTPPropertyBag *pGroupBag;
|
|
|
|
V(pi != NULL, "pi->Current() returned NULL, shouldn't have", NULL);
|
|
|
|
if (fFull) {
|
|
printf("%s %s\n", pGroup->GetNativeName(), pGroup->GetPrettyName());
|
|
} else {
|
|
printf("%s\n", pGroup->GetNativeName());
|
|
}
|
|
|
|
// verifying that the native name and group name are the same
|
|
V(_strcmpi(pGroup->GetNativeName(), pGroup->GetName()) == 0, "verify group name and native name are the same", pGroup->GetNativeName());
|
|
|
|
// get the native name through the property bag and verify that
|
|
// it is the same as the native name found through the group.
|
|
pGroupBag = pGroup->GetPropertyBag();
|
|
DWORD dwSize = 1024;
|
|
HRESULT hr = pGroupBag->GetBLOB(NEWSGRP_PROP_NATIVENAME,
|
|
(BYTE*)szBuf,
|
|
&dwSize);
|
|
V(hr == S_OK, "use IPropertyBag to get native name (should pass)", pGroup->GetNativeName());
|
|
V(lstrcmp(pGroup->GetNativeName(), szBuf) == 0, "make sure property bag points to correct group", pGroup->GetNativeName());
|
|
pGroupBag->Release();
|
|
|
|
// get the group object for this group through the newstree
|
|
// and verify that it is the same
|
|
strcpy(szBuf, pGroup->GetGroupName());
|
|
pGroup2 = pNT->GetGroup(szBuf, pGroup->GetGroupNameLen());
|
|
V(pGroup2 == pGroup, "verify GetGroup found same group (by name)", pGroup->GetNativeName());
|
|
|
|
// set the moderator prettyname to be the same as the group name plus "pretty"
|
|
char szPrettyName[1024] = "prettyname for ";
|
|
lstrcat(szPrettyName, pGroup->GetNativeName());
|
|
pGroup->SetPrettyName(szPrettyName);
|
|
|
|
// get the group by its groupid and verify that it is the same
|
|
pGroup3 = pNT->GetGroup(pGroup->GetGroupId());
|
|
V(pGroup == pGroup3, "verify GetGroup found same group (by id)", pGroup->GetNativeName());
|
|
|
|
// go to the next group
|
|
pi->Next();
|
|
i++;
|
|
}
|
|
|
|
printf("%i groups in list\n", i);
|
|
}
|
|
|
|
void List2(CNewsTreeCore *pNT = g_pNewsTree) {
|
|
INewsTreeIterator *pi;
|
|
HRESULT hr = pNT->GetINewsTree()->GetIterator(&pi);
|
|
DWORD i = 0;
|
|
|
|
V(hr == S_OK, "GetIterator should return OK", NULL);
|
|
V(pi != NULL, "iterator pointer shouldn't be NULL", NULL);
|
|
|
|
printf("-- group list (via COM)\n");
|
|
while (!pi->IsEnd()) {
|
|
char szBuf[1024];
|
|
INNTPPropertyBag *pGroupBag;
|
|
hr = pi->Current(&pGroupBag, NULL );
|
|
V(hr == S_OK, "Current() should return OK", NULL);
|
|
V(pGroupBag != NULL, "Current() shouldn't return NULL", NULL);
|
|
|
|
// get the native name through the property bag and verify that
|
|
// it is the same as the native name found through the group.
|
|
DWORD dwSize = 1024;
|
|
HRESULT hr = pGroupBag->GetBLOB(NEWSGRP_PROP_NATIVENAME,
|
|
(BYTE*)szBuf,
|
|
&dwSize);
|
|
V(hr == S_OK, "use IPropertyBag to get native name (should pass)", NULL);
|
|
printf("%s\n", szBuf);
|
|
pGroupBag->Release();
|
|
|
|
// go to the next group
|
|
pi->Next();
|
|
i++;
|
|
}
|
|
|
|
printf("%i groups in list\n", i);
|
|
}
|
|
|
|
//
|
|
// this should try to hit all of the common uses and error cases of the
|
|
// newstree and newsgroup objects
|
|
//
|
|
void TestFunctionality() {
|
|
DWORD i;
|
|
HRESULT hr;
|
|
|
|
printf("-- start TestFunctionality\n");
|
|
printf("-- adding some groups via CNewsTreeCore\n");
|
|
// in a loop create each of the groups
|
|
for (i = 0; i < g_cGroups; i++) {
|
|
char *szGroup = g_rgszInsertOrder[i];
|
|
|
|
printf("%s\n", szGroup);
|
|
V(g_pNewsTree->CreateGroup(szGroup, FALSE), "CreateGroup failed (should pass)", szGroup);
|
|
// try to add it again and verify that it fails
|
|
V(!(g_pNewsTree->CreateGroup(szGroup, FALSE)), "CreateGroup passed (should fail)", szGroup);
|
|
}
|
|
List();
|
|
|
|
List2();
|
|
|
|
printf("-- verifying list\n");
|
|
// list them and make sure that the list matches what we expect
|
|
CGroupIteratorCore *pi = g_pNewsTree->ActiveGroups();
|
|
i = 0;
|
|
while (!pi->IsEnd()) {
|
|
V(i < g_cGroups, "iterator found more groups then exist", NULL);
|
|
|
|
if (i < g_cGroups) {
|
|
char *szGroup = g_rgszListOrder[i];
|
|
CGRPCOREPTR pGroup = pi->Current();
|
|
|
|
printf("%s (expect %s)\n", pGroup->GetNativeName(), szGroup);
|
|
V(strcmp(pGroup->GetNativeName(), szGroup) == 0, "group order incorrect", szGroup);
|
|
}
|
|
|
|
// go to the next group
|
|
pi->Next();
|
|
i++;
|
|
}
|
|
|
|
printf("-- verifying list (wildmat = %s)\n", g_szWildmat);
|
|
// list them and make sure that the list matches what we expect
|
|
pi = g_pNewsTree->GetIterator(g_szWildmat, FALSE);
|
|
i = 0;
|
|
while (!pi->IsEnd()) {
|
|
V(i < g_cWildmatGroups, "iterator found more groups then exist", NULL);
|
|
|
|
if (i < g_cWildmatGroups) {
|
|
char *szGroup = g_rgszWildmatListOrder[i];
|
|
CGRPCOREPTR pGroup = pi->Current();
|
|
|
|
printf("%s (expect %s)\n", pGroup->GetNativeName(), szGroup);
|
|
V(strcmp(pGroup->GetNativeName(), szGroup) == 0, "group order incorrect", szGroup);
|
|
}
|
|
|
|
// go to the next group
|
|
pi->Next();
|
|
i++;
|
|
}
|
|
|
|
//
|
|
// walk the group list and add and remove groups
|
|
//
|
|
for (i = 0; i < g_cGroups; i++) {
|
|
char *szGroup = g_rgszGroupList[i];
|
|
CGRPCOREPTR pGroup;
|
|
|
|
// look up a newsgroup
|
|
printf("-- looking for %s\n", szGroup);
|
|
hr = g_pNewsTree->FindOrCreateGroup(szGroup, FALSE, FALSE, FALSE, &pGroup);
|
|
V(hr == S_FALSE, "FindOrCreateGroup, should find it", szGroup);
|
|
|
|
// remove it
|
|
printf("-- removing %s\n", pGroup->GetGroupName());
|
|
V(g_pNewsTree->RemoveGroup(pGroup), "remove group, should pass", szGroup);
|
|
V(!(g_pNewsTree->RemoveGroup(pGroup)), "remove group, should fail", szGroup);
|
|
pGroup = NULL;
|
|
List();
|
|
|
|
// add it again
|
|
printf("-- adding %s\n", szGroup);
|
|
V(g_pNewsTree->CreateGroup(szGroup, FALSE), "CreateGroup failed (should pass)", szGroup);
|
|
V(!(g_pNewsTree->CreateGroup(szGroup, FALSE)), "CreateGroup passed (should fail)", szGroup);
|
|
List();
|
|
}
|
|
|
|
// remove all of the groups, using an iterator
|
|
printf("-- remove all groups (iterator)\n");
|
|
pi = g_pNewsTree->ActiveGroups();
|
|
i = 0;
|
|
while (!pi->IsEnd()) {
|
|
V(i < g_cGroups, "iterator found more groups then exist", NULL);
|
|
|
|
if (i < g_cGroups) {
|
|
CGRPCOREPTR pGroup = pi->Current();
|
|
char *szGroup = g_rgszListOrder[i];
|
|
|
|
printf("%s\n", pGroup->GetNativeName());
|
|
V(strcmp(pGroup->GetNativeName(), szGroup) == 0, "group order incorrect", szGroup);
|
|
V(g_pNewsTree->RemoveGroup(pGroup), "RemoveGroup failed (should pass)", szGroup);
|
|
V(!(g_pNewsTree->RemoveGroup(pGroup)), "RemoveGroup passed (should fail)", szGroup);
|
|
}
|
|
|
|
// go to the next group
|
|
pi->Next();
|
|
i++;
|
|
}
|
|
List();
|
|
|
|
// add the groups back again
|
|
printf("-- adding the groups back again\n");
|
|
// in a loop create each of the groups
|
|
for (i = 0; i < g_cGroups; i++) {
|
|
char *szGroup = g_rgszInsertOrder[i];
|
|
|
|
printf("%s\n", szGroup);
|
|
V(g_pNewsTree->CreateGroup(szGroup, FALSE), "CreateGroup failed (should pass)", szGroup);
|
|
// try to add it again and verify that it fails
|
|
V(!(g_pNewsTree->CreateGroup(szGroup, FALSE)), "CreateGroup passed (should fail)", szGroup);
|
|
}
|
|
List();
|
|
|
|
#if 0
|
|
// remove them all using their names and lookups
|
|
printf("-- remove all groups (by name)\n");
|
|
for (i = 0; i < g_cGroups; i++) {
|
|
char *szGroup = g_rgszRemoveOrder[i];
|
|
CGRPCOREPTR pGroup;
|
|
|
|
printf("%s\n", szGroup);
|
|
hr = g_pNewsTree->FindOrCreateGroup(szGroup, FALSE, FALSE, &pGroup);
|
|
V(hr == S_OK, "FindOrCreateGroup, should find it", szGroup);
|
|
|
|
V(g_pNewsTree->RemoveGroup(pGroup), "RemoveGroup failed (should pass)", szGroup);
|
|
V(!(g_pNewsTree->RemoveGroup(pGroup)), "RemoveGroup passed (should fail)", szGroup);
|
|
}
|
|
List();
|
|
#endif
|
|
|
|
printf("-- done in TestFunctionality\n");
|
|
}
|
|
|
|
//
|
|
// this should try to hit all of the common uses and error cases of the
|
|
// newstree and newsgroup objects
|
|
//
|
|
void DumpGroups() {
|
|
printf("-- start DumpGroups\n");
|
|
|
|
List(TRUE);
|
|
|
|
printf("-- done in DumpGroups\n");
|
|
}
|
|
|
|
int _cdecl main(int argc, const char **argv) {
|
|
CVRootTable::GlobalInitialize();
|
|
|
|
_Module.Init(NULL, (HINSTANCE) INVALID_HANDLE_VALUE);
|
|
|
|
int rc;
|
|
g_cErrors = 0;
|
|
|
|
if (argc < 2 || argc > 3 || (strcmp(argv[1], "/help") == 0)) {
|
|
printf("usage: testnt inifile [ini section name]\n");
|
|
printf(" default section name is \"testnt\"\n");
|
|
printf(" The following keys are required:\n");
|
|
printf(" * Group%%i - up to N keys consecutively named are expected,\n");
|
|
printf(" with each one consisting of the name of a newsgroup. The group\n");
|
|
printf(" numbers are zero based and must be consecutive.\n");
|
|
printf(" * InsertOrder - the order that these groups should be inserted\n");
|
|
printf(" in. The list is a comma delimited set of numbers, where each\n");
|
|
printf(" number corresponds to a group specified with a group key\n");
|
|
printf(" * RemoveOrder - the order that these groups should be removed in.\n");
|
|
printf(" * ListOrder - the order that these groups should be found in\n");
|
|
printf(" when executing a list command.\n");
|
|
printf(" * Wildmat - a wildmat to use for testing the iterator.\n");
|
|
printf(" * WildmatListOrder - the order that these groups should be found in\n");
|
|
printf(" when executing a list command with the specified wildmat.\n");
|
|
printf(" Optional keys:\n");
|
|
printf(" * MetabasePath - where we make our vroot table. Default is %s\n", DEF_KEY_MBPATH);
|
|
printf(" Example section:\n");
|
|
printf(" [testnt]\n");
|
|
printf(" Group0=alt.test\n");
|
|
printf(" Group1=rec.test\n");
|
|
printf(" InsertOrder=0,1\n");
|
|
printf(" RemoveOrder=1,0\n");
|
|
printf(" ListOrder=0,1\n");
|
|
printf(" Wildmat=r*\n");
|
|
printf(" WildmatListOrder=1\n");
|
|
rc = 1;
|
|
} else {
|
|
const char *pszSectionName = (argc == 2) ? g_pszDefaultSectionName : argv[2];
|
|
printf("reading from INI section %s\n", pszSectionName);
|
|
ReadINIFile(argv[1], pszSectionName);
|
|
Initialize(TRUE);
|
|
TestFunctionality();
|
|
Shutdown();
|
|
Initialize(FALSE);
|
|
DumpGroups();
|
|
Shutdown();
|
|
rc = g_cErrors;
|
|
}
|
|
|
|
_Module.Term();
|
|
|
|
CVRootTable::GlobalShutdown();
|
|
|
|
return rc;
|
|
}
|