2025-04-27 07:49:33 -04:00

630 lines
17 KiB
C++

#include <windows.h>
#include <stdio.h>
#include <dbgtrace.h>
#include <tigtypes.h>
#include <ihash.h>
#include <crchash.h>
#include <fsconst.h>
typedef char *LPMULTISZ ;
#include <nntpmeta.h>
#include <nwstree.h>
#include <ctype.h>
#define _ATL_NO_DEBUG_CRT
#define _ASSERTE _ASSERT
#include <atlbase.h>
CComModule _Module;
#include <atlcom.h>
#include <atlimpl.cpp>
CNNTPVRootTable *g_pVRTable = NULL;
CNewsTreeCore *g_pNewsTree = NULL;
CXoverMap *g_pXOver = NULL;
CMsgArtMap *g_pArt = NULL;
#define WMDPATH L"/LM/modhash"
#define MDPATH "/LM/modhash"
#define PROGID_NO_DRIVER L"TestNT.NoDriver"
#define VRPATH L""
#define INI_KEY_GROUPNAME "Group%i"
#define INI_KEY_ARTIDMAX "ArtIdMax%i"
#define TESTIFS_SECTION "TestIFS"
class CExtractor : public IExtractObject {
public:
BOOL DoExtract(GROUPID groupid,
ARTICLEID articleid,
PGROUP_ENTRY pGroups,
DWORD cGroups)
{
if(groupid & 0x1) return TRUE; else return FALSE;
}
};
void Post(char *pszGroup, DWORD iArticleId, char *pszMessageId) {
CGRPCOREPTR pGroup;
HRESULT hr;
hr = g_pNewsTree->FindOrCreateGroup(pszGroup, FALSE, FALSE, FALSE, &pGroup);
if (FAILED(hr)) {
printf("group %s doesn't seem to exist. hr = 0x%x\n", pszGroup, hr);
return;
}
DWORD iGroupId = pGroup->GetGroupId();
printf("-- post %s:%i %s\n", pszGroup, iArticleId, pszMessageId);
printf("%s -> %i\n", pszGroup, iGroupId);
CStoreId storeid;
storeid.cLen = 10;
strcpy((char *) storeid.pbStoreId, "thisistst");
if (g_pArt->InsertMapEntry(pszMessageId,
0,
0,
iGroupId,
iArticleId,
storeid))
{
SYSTEMTIME systime;
FILETIME filetime;
GetLocalTime(&systime);
SystemTimeToFileTime(&systime, &filetime);
DWORD cStoreId = 1;
BYTE cCrossposts = 1;
if (g_pXOver->CreatePrimaryNovEntry(iGroupId,
iArticleId,
0,
0,
&filetime,
pszMessageId,
strlen(pszMessageId),
0,
NULL,
cStoreId,
&storeid,
&cCrossposts
))
{
printf("post successful\n");
} else {
printf("CreatePrimaryNovEntry failed with %lu\n", GetLastError());
g_pArt->DeleteMapEntry(pszMessageId);
}
} else {
printf("InsertMapEntry failed with %lu\n", GetLastError());
}
}
void DumpStoreId(CStoreId storeid) {
if (storeid.cLen == 0) return;
DWORD i = 0;
while (i < storeid.cLen) {
DWORD j, c;
c = (j + 16 > storeid.cLen) ? storeid.cLen : j + 16;
printf("StoreId: %02x-%02x: ", i, c);
for (j = i; j < c; j++)
printf("%02x ", storeid.pbStoreId[j]);
printf(" | ");
for (j = i; j < c; j++)
printf("%c", (isprint(storeid.pbStoreId[j])) ? storeid.pbStoreId[j] : '.');
printf("\n");
i = j;
}
}
void FindMessageId(char *pszMessageId) {
printf("-- findmsgid %s\n", pszMessageId);
WORD iHeaderOffset, cHeaderLength;
DWORD iArticleId, iGroupId;
CStoreId storeid;
if (g_pArt->GetEntryArticleId(pszMessageId,
iHeaderOffset,
cHeaderLength,
iArticleId,
iGroupId,
storeid))
{
CGRPCOREPTR pGroup = g_pNewsTree->GetGroup(iGroupId);
if (pGroup) {
printf("%i -> %s\n", iGroupId, pGroup->GetNativeName());
printf("%s is %s:%i\n", pszMessageId, pGroup->GetNativeName(), iArticleId);
} else {
printf("couldn't find group for groupid %i\n", iGroupId);
printf("%s is %i:%i\n", pszMessageId, iGroupId, iArticleId);
}
DumpStoreId(storeid);
} else {
printf("GetEntryArticleId failed with %lu\n", GetLastError());
}
}
void FindArtId(char *pszGroup, DWORD iArticleId) {
printf("-- findartid %s:%i\n", pszGroup, iArticleId);
CGRPCOREPTR pGroup;
HRESULT hr;
hr = g_pNewsTree->FindOrCreateGroup(pszGroup, FALSE, FALSE, FALSE, &pGroup);
if (FAILED(hr)) {
printf("group %s doesn't seem to exist. hr = 0x%x\n", pszGroup, hr);
return;
}
DWORD iGroupId = pGroup->GetGroupId();
printf("%s -> %i\n", pszGroup, iGroupId);
WORD iHeaderOffset, cHeaderLength;
DWORD iPriArticleId, iPriGroupId;
char pszMessageId[256];
CStoreId storeid;
DWORD cDataLen;
if (g_pXOver->GetPrimaryArticle(iGroupId,
iArticleId,
iPriGroupId,
iPriArticleId,
256,
pszMessageId,
cDataLen,
iHeaderOffset,
cHeaderLength,
storeid))
{
CGRPCOREPTR pGroup = g_pNewsTree->GetGroup(iPriGroupId);
if (pGroup) {
printf("%i -> %s\n", iPriGroupId, pGroup->GetNativeName());
printf("%s:%i is %s, %s:%i\n",
pszGroup, iArticleId,
pszMessageId, pGroup->GetNativeName(), iPriArticleId);
} else {
printf("couldn't find group for groupid %i\n", iGroupId);
printf("%s:%i is %s, %i:%i\n",
pszGroup, iArticleId,
pszMessageId, iPriGroupId, iPriArticleId);
}
DumpStoreId(storeid);
} else {
printf("GetEntryArticleId failed with %lu\n", GetLastError());
}
}
void DeleteMessageId(char *pszMessageId) {
printf("-- deletemsgid %s\n", pszMessageId);
WORD iHeaderOffset, cHeaderLength;
DWORD iArticleId, iGroupId;
CStoreId storeid;
if (g_pArt->GetEntryArticleId(pszMessageId,
iHeaderOffset,
cHeaderLength,
iArticleId,
iGroupId,
storeid))
{
printf("%s is %i:%i\n", pszMessageId, iGroupId, iArticleId);
if (g_pArt->DeleteMapEntry(pszMessageId)) {
if (g_pXOver->DeleteNovEntry(iGroupId, iArticleId)) {
printf("delete successful\n");
} else {
printf("DeleteNovEntry failed with %lu\n", GetLastError());
}
} else {
printf("DeleteMapEntry failed with %lu\n", GetLastError());
}
}
}
void PostIFS(char *pszGroup, DWORD iArticleId, char *pszMessageId, BYTE* pbStoreId, BYTE cbStoreId) {
CGRPCOREPTR pGroup;
HRESULT hr;
hr = g_pNewsTree->FindOrCreateGroup(pszGroup, FALSE, FALSE, FALSE, &pGroup);
if (FAILED(hr)) {
printf("group %s doesn't seem to exist. hr = 0x%x\n", pszGroup, hr);
return;
}
CStoreId storeid;
storeid.cLen = cbStoreId;
memcpy(storeid.pbStoreId, pbStoreId, cbStoreId);
DWORD iGroupId = pGroup->GetGroupId();
printf("-- postIFS %s:%i %s\n", pszGroup, iArticleId, pszMessageId);
DumpStoreId(storeid);
printf("%s -> %i\n", pszGroup, iGroupId);
if (g_pArt->InsertMapEntry(pszMessageId,
0,
0,
iGroupId,
iArticleId,
storeid))
{
SYSTEMTIME systime;
FILETIME filetime;
GetLocalTime(&systime);
SystemTimeToFileTime(&systime, &filetime);
if (g_pXOver->CreatePrimaryNovEntry(iGroupId,
iArticleId,
0,
0,
&filetime,
pszMessageId,
strlen(pszMessageId),
0,
NULL))
{
printf("post successful\n");
} else {
printf("CreatePrimaryNovEntry failed with %lu\n", GetLastError());
g_pArt->DeleteMapEntry(pszMessageId);
}
} else {
printf("InsertMapEntry failed with %lu\n", GetLastError());
}
}
void TestIFS(char* pszIniFile) {
int cGroups = 0;
char szKey[20];
char szArtIdMax[20];
int iArtIdMax;
char szFIDMID[MAX_PATH];
char szGroupName[1024];
char szMessageId[MAX_PATH];
while (1)
{
// Get the newsgroup name
sprintf(szKey, INI_KEY_GROUPNAME, cGroups);
GetPrivateProfileString(TESTIFS_SECTION,
szKey,
"",
szGroupName,
1024,
pszIniFile);
if (szGroupName[0] == 0)
{
break;
}
printf("Post to %s ...\n", szGroupName);
// Now get the ArtIdMax
sprintf(szKey, INI_KEY_ARTIDMAX, cGroups);
GetPrivateProfileString(TESTIFS_SECTION,
szKey,
"",
szArtIdMax,
20,
pszIniFile);
if (szArtIdMax[0] == 0)
{
break;
}
iArtIdMax = atoi(szArtIdMax);
if (iArtIdMax < 0) iArtIdMax = 1;
printf("...with %d articles...\n", iArtIdMax);
// Loop through dwArtIdMax times and do PostIFS
// randomlly generate message-id's, use first 8 byte of
// the group name as FID, and first 8 byte of ArtId as MID
while (iArtIdMax-- > 0)
{
// Generate the Message-id
sprintf(szMessageId, "<mid%d@testifs.com>", iArtIdMax);
ZeroMemory(szFIDMID, sizeof(szFIDMID));
sprintf(szFIDMID, "%.8hs%d", szGroupName, iArtIdMax);
// Call PostIFS to post this article, FID/MID is always 16 bytes long
PostIFS(szGroupName, iArtIdMax, szMessageId, (BYTE *)szFIDMID, 16);
}
cGroups++;
}
}
void CreateGroup(char *pszGroupName) {
printf("-- create group %s\n", pszGroupName);
if (!g_pNewsTree->CreateGroup(pszGroupName, FALSE)) {
printf("CreateGroup failed with %lu\n", GetLastError());
}
}
void SetHighwater(char *pszGroup, DWORD iHigh) {
printf("-- sethigh %s %i\n", pszGroup, iHigh);
HRESULT hr;
CGRPCOREPTR pGroup;
hr = g_pNewsTree->FindOrCreateGroup(pszGroup, FALSE, FALSE, FALSE, &pGroup);
if (FAILED(hr)) {
printf("group %s doesn't seem to exist. hr = 0x%x\n", pszGroup, hr);
return;
}
pGroup->SetMessageCount(iHigh - 1);
pGroup->SetHighWatermark(iHigh);
pGroup->SaveFixedProperties();
}
void ProcessCommands(int argc, char **argv) {
while (argc) {
if (strcmp(*argv, "post") == 0) {
if (argc < 3) {
printf("not enough arguments to post");
return;
}
argc -= 3;
char *pszGroupName = *(++argv);
DWORD iArticleId = atoi(*(++argv));
char szMessageId[MAX_PATH];
sprintf(szMessageId, "<%s>", *(++argv));
Post(pszGroupName, iArticleId, szMessageId);
} else if (strcmp(*argv, "findmsgid") == 0) {
if (argc < 1) {
printf("not enough arguments to findmsgid");
return;
}
argc -= 1;
char szMessageId[MAX_PATH];
sprintf(szMessageId, "<%s>", *(++argv));
FindMessageId(szMessageId);
} else if (strcmp(*argv, "findartid") == 0) {
if (argc < 2) {
printf("not enough arguments to findartid");
return;
}
argc -= 2;
char *pszGroupName = *(++argv);
DWORD iArticleId = atoi(*(++argv));
FindArtId(pszGroupName, iArticleId);
} else if (strcmp(*argv, "deletemsgid") == 0) {
if (argc < 1) {
printf("not enough arguments to deletemsgid");
return;
}
argc -= 1;
char szMessageId[MAX_PATH];
sprintf(szMessageId, "<%s>", *(++argv));
DeleteMessageId(szMessageId);
} else if (strcmp(*argv, "creategroup") == 0) {
if (argc < 1) {
printf("not enough arguments to creategroup");
return;
}
argc -= 1;
char *pszGroupName = *(++argv);
CreateGroup(pszGroupName);
} else if (strcmp(*argv, "sethigh") == 0) {
if (argc < 2) {
printf("not enough arguments to sethigh");
return;
}
argc -= 2;
char *pszGroupName = *(++argv);
DWORD iHigh = atoi(*(++argv));
SetHighwater(pszGroupName, iHigh);
} else if (strcmp(*argv, "testifs") == 0) {
if (argc < 1) {
printf("not enough arguments to TestIFS");
return;
}
argc -= 1;
char *pszIniFile = *(++argv);
TestIFS(pszIniFile);
} else {
printf("skipping unknown command %s\n", *argv);
}
argc--;
argv++;
}
}
void InitializeNewstree(char *szGroupList, char *szGroupVarList) {
HRESULT hr;
BOOL fFatal;
IMSAdminBaseW *pMB;
METADATA_HANDLE hmRoot;
// initialize COM and the metabase
printf("initializing metabase\n");
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr)) {
printf("CoInitializeEx failed with 0x%x\n", hr);
exit(0);
}
hr = CoCreateInstance(CLSID_MSAdminBase_W, NULL, CLSCTX_ALL,
IID_IMSAdminBase_W, (LPVOID *) &pMB);
if (FAILED(hr)) {
printf("CoCreateInstance failed with 0x%x\n", hr);
exit(0);
}
// create a vroot entry for the root. we don't have any other
// vroot entries
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);
if (FAILED(hr)) {
printf("creating virtual root hierarchy\n");
printf("OpenKey failed with 0x%x\n", hr);
exit(0);
}
// first we delete whatever exists in the metabase under this path,
// then we create a new area to play in
pMB->DeleteKey(hmRoot, WMDPATH);
hr = pMB->AddKey(hmRoot, WMDPATH);
if (FAILED(hr)) {
printf("creating key %s\n", MDPATH);
printf("AddKey failed with 0x%x\n", hr);
exit(0);
}
// 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
};
hr = pMB->SetData(hmRoot, WMDPATH, &mdrProgID);
if (FAILED(hr)) {
printf("setting MD_VR_DRIVER_PROGID = \"%S\"\n", PROGID_NO_DRIVER);
printf("SetData failed with 0x%x\n", hr);
exit(0);
}
METADATA_RECORD mdrVRPath = {
MD_VR_PATH,
METADATA_INHERIT,
ALL_METADATA,
STRING_METADATA,
(lstrlenW(VRPATH)+1) * sizeof(WCHAR),
(BYTE *) VRPATH,
0
};
hr = pMB->SetData(hmRoot, WMDPATH, &mdrVRPath);
if (FAILED(hr)) {
printf("setting MD_VR_PATH = \"%S\"\n", VRPATH);
printf("SetData failed with 0x%x\n", hr);
exit(0);
}
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(MDPATH);
if (FAILED(hr)) {
printf("g_pVRTable->Initialize(\"%s\") returned %x\n", MDPATH, hr);
exit(0);
}
// load the newstree from disk
g_pNewsTree->LoadTree(szGroupList, szGroupVarList);
}
void ShutdownNewstree() {
g_pNewsTree->StopTree();
g_pNewsTree->TermTree();
delete g_pVRTable;
delete g_pNewsTree;
}
int __cdecl main(int argc, char **argv) {
CExtractor extractor;
char szXOverFile[MAX_PATH];
char szArticleFile[MAX_PATH];
char szGroupList[MAX_PATH];
char szGroupVarList[MAX_PATH];
if (argc < 2) {
printf("usage: modhash <nntpfile dir> [commands...]\n");
printf(" commands:\n");
printf(" post <groupname> <artid> <msgid>\n");
printf(" findmsgid <msgid>\n");
printf(" findartid <groupname> <artid>\n");
printf(" deletemsgid <msgid>\n");
printf(" creategroup <groupname>\n");
printf(" sethigh <groupname> <highwatermark>\n");
return 0;
}
sprintf(szXOverFile, "%s\\xover.hsh", argv[1]);
sprintf(szArticleFile, "%s\\article.hsh", argv[1]);
sprintf(szGroupList, "%s\\group.lst", argv[1]);
sprintf(szGroupVarList, "%s\\groupvar.lst", argv[1]);
printf("-- initializing\n");
printf("xover.hsh path: %s\n", szXOverFile);
printf("article.hsh path: %s\n", szArticleFile);
printf("group.lst path: %s\n", szGroupList);
printf("groupvar.lst path: %s\n", szGroupVarList);
crcinit();
CVRootTable::GlobalInitialize();
_Module.Init(NULL, (HINSTANCE) INVALID_HANDLE_VALUE);
InitializeNewstree(szGroupList, szGroupVarList);
printf("initializing hash tables\n");
InitializeNNTPHashLibrary();
printf("initializing CXoverMap\n");
g_pXOver = CXoverMap::CreateXoverMap();
g_pArt = CMsgArtMap::CreateMsgArtMap();
if (g_pXOver && g_pArt && !g_pXOver->Initialize(szXOverFile, 0)) {
printf("CXoverMap::Initialize failed with %lu", GetLastError());
delete g_pXOver;
g_pXOver = NULL;
}
printf("initializing CMsgArtMap\n");
if (g_pXOver && g_pArt && !g_pArt->Initialize(szArticleFile, 0)) {
printf("CMsgArtMap::Initialize failed with %lu", GetLastError());
delete g_pArt;
g_pArt = NULL;
}
ProcessCommands(argc - 2, argv + 2);
printf("-- shutting down\n");
if (g_pXOver) {
g_pXOver->Shutdown();
delete g_pXOver;
g_pXOver = NULL;
}
if (g_pArt) {
g_pArt->Shutdown();
delete g_pArt;
g_pArt = NULL;
}
TermNNTPHashLibrary();
ShutdownNewstree();
_Module.Term();
CVRootTable::GlobalShutdown();
return 0;
}