windows-nt/Source/XPSP1/NT/public/sdk/inc/collect.h
2020-09-26 16:20:57 +08:00

481 lines
15 KiB
C++

//*********************************************************************************************************************************************
//
// File: collect.h
// Author: Donald Drake
// Purpose: Defines classes to support titles, collections, locations and folders
#ifndef _COLLECT_H
#define _COLLECT_H
#undef CLASS_IMPORT_EXPORT
#ifdef HHCTRL // define this only when building the HHCtrl DLL
#define CLASS_IMPORT_EXPORT /**/
#else
#ifdef HHSETUP // define this only when building the HHSetup DLL
#define CLASS_IMPORT_EXPORT __declspec( dllexport )
#else
#define CLASS_IMPORT_EXPORT __declspec( dllimport )
#endif
#endif
#ifndef HHCTRL
#undef COUNT
#define COUNT(x)
#undef MI_COUNT
#define MI_COUNT(x)
#undef SI_COUNT
#define SI_COUNT(x)
#undef MI2_COUNT
#define MI2_COUNT(x)
#undef AUTO_CLASS_COUNT_CHECK
#define AUTO_CLASS_COUNT_CHECK(x)
#undef CHECK_CLASS_COUNT
#define CHECK_CLASS_COUNT(x)
#undef DUMP_CLASS_COUNT
#define DUMP_CLASS_COUNT(x)
#endif
#ifdef HHCTRL
#include "parserhh.h"
#else
#include "parser.h"
#endif
#define F_MSDN 0x0001
#define F_TITLELOCAL 0x0002
#define F_INDEXLOCAL 0x0004
#define STARTINGCOLNO 10000
#define ENGLANGID 1033
#define MAX_LEVELS 100
typedef struct LocationHistory {
CHAR * SampleLocation;
CHAR * FileName;
CHAR * IndexFileName;
CHAR * QueryFileName;
CHAR * LocationId;
DWORD CollectionNumber;
DWORD Version;
DWORD LastPromptedVersion;
BOOL bSupportsMerge;
LocationHistory *pNext;
CHAR * QueryLocation;
} LOCATIONHISTORY;
DWORD CLASS_IMPORT_EXPORT AllocSetValue(const CHAR *value, CHAR **dest);
// forward declarations
class CLocation;
class CTitle;
class CCollection;
class CFolder;
class CSlotLookupTable;
class CExTitle;
class CColList;
typedef struct ListItem {
void *pItem;
ListItem *Next;
} LISTITEM;
class CLASS_IMPORT_EXPORT CPointerList {
private:
LISTITEM *m_pHead;
public:
CPointerList()
{
m_pHead = NULL;
}
~CPointerList();
void RemoveAll();
LISTITEM *Add(void *);
LISTITEM *First();
LISTITEM *Next(LISTITEM *p) { return p->Next; }
};
#ifdef HHCTRL // define this only when building the HHCtrl DLL
//
// <mc>
// This lookup table will facilitate a quick translation of a "slot" number into a CFolder* as well as a
// HASH value into a CFolder*. This will be done using two DWORDS per CFolder object, one for the HASH value
// and one for the CFolder*. After ALL the CFolders for a given collection have been created and this lookup
// table is fully populated the SortAndAssignSlots() member will be called. This will sort the table by HASH
// value and will assign the slot values back to the CFolders according to the sorted order. This will make
// slot --> CFolder* lookup a simple array index and will also allow us to use a bsearch for the
// HASH --> CFolder* lookup. Note that only leaf level CFolders have useful hash values, for the non leaf
// CFolders we will assign a hash of -1, these items in the table will then appear at the end of the table
// and will not interfear with a bsearch operation when translating a hash into a pSLT.
// </mc>
//
class CSlotLookupTable
{
public:
CSlotLookupTable();
~CSlotLookupTable();
static int FASTCALL ltqs_callback(const void *elem1, const void *elem2);
void AddValue(CFolder* pFolder);
void SortAndAssignSlots(void);
CFolder* HashToCFolder(HASH hash);
CFolder* SlotToCFolder(DWORD dwSlot)
{
if ( dwSlot > 0 && dwSlot <= m_uiTotalCnt ) // Slot 0 reserved for error case.
return m_pSLT[dwSlot].pCFolder;
else
return NULL;
}
private:
struct _slt
{
HASH hash;
CFolder* pCFolder;
};
struct _slt* m_pSLT;
unsigned m_uiTotalAllocated;
unsigned m_uiTotalCnt;
unsigned m_uiHashCnt;
};
#endif
class CLASS_IMPORT_EXPORT CFolder SI_COUNT(CFolder)
{
private:
CHAR *Title; // name of the folder
WCHAR *pwcTitle;
DWORD Order;
LANGID LangId;
DWORD dwSlot;
CExTitle* pExTitle;
CFolder *pNext, *pKid, *pParent;
//
// This DWORD value is being added to support .CHM level subsetting.
//
WORD iLevel;
WORD f_Filter: 1; // render into filter LB.
WORD f_Available: 1; // render into Available LB.
WORD f_F_Open: 1; // Expanded or closed ?
WORD f_A_Open: 1; // Expanded or closed ?
WORD f_HasHash: 1; // Does Node have a prefix hash ?
WORD f_IsOrphan: 1; // Is this node an orphane ?
WORD f_IsVisable: 1; // Indicates membership in the currently selected TOC subset.
public:
CFolder();
~CFolder();
BOOL bIsVisable() { return (BOOL)f_IsVisable; }
void SetTitle(const CHAR *);
void SetTitle(const WCHAR *);
void SetExTitlePtr(CExTitle* pTitle);
CHAR *GetTitle() { return Title; }
const WCHAR *GetTitleW();
void SetLanguage(LANGID Id) { LangId = Id; }
LANGID GetLanguage() { return LangId; }
void SetOrder(DWORD);
DWORD GetOrder();
// Returns the next sibling folder given a folder entry
CFolder * GetNextFolder();
void SetNextFolder(CFolder *p) { pNext = p; }
// Returns the first child of a given folder if it exists
CFolder * GetFirstChildFolder();
void SetFirstChildFolder(CFolder *p) { pKid = p; }
// Add a new folder as child of a given folder
CFolder * AddChildFolder(const CHAR *szName, DWORD Order, DWORD *pError, LANGID LangId = ENGLANGID);
CFolder * AddChildFolder(const WCHAR *szName, DWORD Order, DWORD *pError, LANGID LangId = ENGLANGID);
DWORD AddChildFolder(CFolder *newFolder);
void SetParent(CFolder *p) { pParent = p; }
CFolder * GetParent() { return pParent; }
friend class CSlotLookupTable;
friend class CDefineSS;
friend class CStructuralSubset;
};
class CLASS_IMPORT_EXPORT CCollection SI_COUNT(CCollection)
{
public:
CCollection();
~CCollection();
void ConfirmTitles() { m_bConfirmTitles = TRUE; }
void SetSampleLocation(const CHAR *);
CHAR *GetSampleLocation();
void SetMasterCHM(const CHAR *szName, LANGID Lang);
BOOL GetMasterCHM(CHAR ** szName, LANGID *Lang);
// Opens and loads the contents of the file into data structures
DWORD Open(const CHAR * FileName);
void SetSampleLocation(const WCHAR *);
void SetFindMergedCHMS(BOOL bFind) { m_bFindMergedChms = bFind; }
BOOL GetFindMergedCHMS() { return m_bFindMergedChms; }
const WCHAR *GetSampleLocationW();
void SetMasterCHM(const WCHAR *szName, LANGID Lang);
BOOL GetMasterCHM(WCHAR ** szName, LANGID *Lang);
// Opens and loads the contents of the file into data structures
DWORD Open(const WCHAR * FileName);
// Saves any changes made to the internal data structures to the file.
DWORD Save();
DWORD Close();
void AddRef() { m_dwRef++; }
DWORD GetVersion() { return m_dwVersion; }
void SetVersion(DWORD dw) { m_dwVersion = dw; }
// navigating the collection
// Returns the first folder in the collection
CFolder * GetRootFolder() { return m_pRootFolder; }
CFolder * GetVisableRootFolder() { return m_pRootFolder->GetFirstChildFolder(); } // Returns the visable root.
// Returns the first title
CTitle * GetFirstTitle();
// Locates a title based on id
CTitle * FindTitle(const CHAR * Id, LANGID LangId = ENGLANGID);
CTitle * FindTitle(const WCHAR * Id, LANGID LangId = ENGLANGID);
// Try multiple LangIds, before failing.
#ifdef HHCTRL
CTitle * FindTitleNonExact(const CHAR * Id, LANGID LangId) ;
#endif // #ifdef HHCTRL
// Returns the first location
CLocation* FirstLocation();
// Finds a location based on a name
CLocation * FindLocation(const CHAR * Name, UINT* puiVolumeOrder = NULL );
// collection entry management
CColList * FindCollection(CHAR *szFileName);
CColList * AddCollection();
void RemoveCollectionEntry(CHAR *szFileName);
//Adds a new folder to the top level of the table of contents, with the given name and order and returns a pointer to that folder object. A return of NULL indicates a failure and pDWORD will be populated with one of above DWORD codes.
CFolder * AddFolder(const CHAR * szName, DWORD Order, DWORD *pDWORD, LANGID LangId = ENGLANGID);
DWORD DeleteFolder(CFolder *);
//Adds a title based on the provided information.
//A return of NULL indicates a failure and pDWORD will be
//populated with one of above DWORD codes. Note: you must add or
//find a CLocation object or pass null to indication no location is in
// use (local file).
CTitle * AddTitle(const CHAR * Id, const CHAR * FileName, const CHAR * IndexFile,
const CHAR * Query, const CHAR *SampleLocation, LANGID Lang,
UINT uiFlags, CLocation *pLocation, DWORD *pDWORD,
BOOL bSupportsMerge = FALSE, const CHAR *QueryLocation = NULL);
// Adds location based on the given information. A return of NULL indicates a failure and pDWORD will be populated with one of above DWORD codes.
CLocation * AddLocation(const CHAR * Title, const CHAR * Path, const CHAR * Id, const CHAR * Volume, DWORD *pDWORD);
CLocation * FindLocation(const WCHAR * Name, UINT* puiVolumeOrder = NULL );
CFolder * AddFolder(const WCHAR * szName, DWORD Order, DWORD *pDWORD, LANGID LangId = ENGLANGID);
CTitle * AddTitle(const WCHAR * Id, const WCHAR * FileName,
const WCHAR * IndexFile, const WCHAR * Query,
const WCHAR *SampleLocation, LANGID Lang, UINT uiFlags,
CLocation *pLocation, DWORD *pDWORD,
BOOL bSupportsMerge = FALSE, const WCHAR *QueryLocation = NULL);
CLocation * AddLocation(const WCHAR * Title, const WCHAR * Path, const WCHAR * Id, const WCHAR * Volume, DWORD *pDWORD);
DWORD RemoveCollection(BOOL bRemoveLocalFiles = FALSE);
DWORD GetRefTitleCount() { return m_dwTitleRefCount; }
// Merges the currently installed titles for the collection into the specified filename (path determined internally)
BOOL MergeKeywords(CHAR * pwzFilename );
BOOL MergeKeywords(WCHAR * pwzFilename );
DWORD GetColNo() { return m_dwColNo; }
PCSTR GetCollectionFileName(void) { return m_szFileName; }
const WCHAR *GetCollectionFileNameW(void);
BOOL IsDirty() { return m_bDirty;}
void IncrementRefTitleCount() { m_dwTitleRefCount++; }
void DecrementRefTitleCount() { m_dwTitleRefCount--; }
void Dirty() { m_bDirty = TRUE; }
LANGID GetLangId(const CHAR *FileName);
LANGID GetLangId(const WCHAR *FileName);
private: // functions
DWORD AddRefedTitle(CFolder *pFolder);
// removing objects
DWORD DeleteTitle(CTitle *);
void DeleteLocalFiles(LOCATIONHISTORY *pHist, CTitle *pTitle);
DWORD DeleteLocation(CLocation *);
DWORD CheckTitleRef(const CHAR *pId, const LANGID Lang);
DWORD CheckTitleRef(const WCHAR *pId, const LANGID Lang);
DWORD ParseFile(const CHAR *FileName);
DWORD HandleCollection(CParseXML *parser, CHAR *sz);
DWORD HandleCollectionEntry(CParseXML *parser, CHAR *sz);
DWORD HandleFolder(CParseXML *parser, CHAR *token);
DWORD HandleLocation(CParseXML *parser, CHAR *token);
DWORD HandleTitle(CParseXML *parser, CHAR *token);
void DeleteChildren(CFolder **p);
void DeleteFolders(CFolder **p);
BOOL WriteFolders(CFolder **p);
BOOL WriteFolder(CFolder **p);
DWORD AllocCopyValue(CParseXML *parser, CHAR *token, CHAR **dest);
CTitle *NewTitle();
CLocation *NewLocation();
private:
BOOL m_bRemoveLocalFiles;
BOOL m_bRemoved;
DWORD Release();
CHAR * m_szFileName;
WCHAR * m_pwcFileName;
CHAR * m_szMasterCHM;
WCHAR * m_pwcMasterCHM;
CHAR * m_szSampleLocation;
WCHAR * m_pwcSampleLocation;
LANGID m_MasterLangId;
CTitle * m_pFirstTitle;
CTitle * m_pTitleTail;
CLocation * m_pFirstLocation;
CLocation * m_pLocationTail;
CFolder *m_pRootFolder;
DWORD m_locationnum;
CFIFOString m_Strings;
CFolder *m_pParents[MAX_LEVELS];
DWORD m_dwCurLevel;
DWORD m_dwLastLevel;
DWORD m_dwNextColNo;
DWORD m_dwColNo;
DWORD m_dwTitleRefCount;
BOOL m_bConfirmTitles;
BOOL m_bFindMergedChms;
DWORD m_dwRef;
DWORD m_dwVersion;
HANDLE m_fh;
BOOL m_bDirty;
CColList *m_pColListHead;
CColList *m_pColListTail;
public:
CPointerList m_RefTitles;
BOOL m_bFailNoFile;
BOOL m_bAllFilesDeleted;
};
class CColList
{
private:
DWORD m_dwColNo;
CHAR * m_szFileName;
CColList *m_pNext;
public:
CColList();
~CColList();
void SetColNo(DWORD dw) { m_dwColNo = dw; }
void SetFileName(CHAR *szFileName);
DWORD GetColNo() { return m_dwColNo; }
CHAR *GetFileName() { return m_szFileName; }
CColList *GetNext() { return m_pNext; }
void SetNext(CColList *p) { m_pNext = p; }
};
class CLASS_IMPORT_EXPORT CTitle SI_COUNT(CTitle)
{
private:
CHAR * Id; // Title identifier
WCHAR *pwcId;
LANGID Language; // language identifier
CTitle *NextTitle; // pointer to the next title
public:
LOCATIONHISTORY *m_pHead, *m_pTail;
void SetId(const CHAR *);
void SetId(const WCHAR *);
void SetLanguage(LANGID);
CHAR * GetId();
const WCHAR * GetIdW();
LANGID GetLanguage();
LOCATIONHISTORY *GetLocation(DWORD Index);
CTitle* GetNextTitle();
~CTitle();
CTitle();
LOCATIONHISTORY *NewLocationHistory();
DWORD AddLocationHistory(DWORD ColNo, const CHAR *FileName, const CHAR *IndexFile, const CHAR *Query, const CLocation *pLocation, const CHAR *Sample, const CHAR *QueryLocation, BOOL bSupportsMerge);
DWORD AddLocationHistory(DWORD ColNo, const WCHAR *FileName, const WCHAR *IndexFile, const WCHAR *Query, const CLocation *pLocation, const WCHAR *Sample, const WCHAR *QueryLocation, BOOL bSupportsMerge);
void SetNextTitle(CTitle *p) { NextTitle = p; }
};
class CLASS_IMPORT_EXPORT CLocation SI_COUNT(CLocation)
{
private:
CHAR * Id;
CHAR * Title; // Friendly name for the title
CHAR * Path; // location of the device
CHAR * Volume;
WCHAR * pwcId;
WCHAR * pwcTitle; // Friendly name for the title
WCHAR * pwcPath; // location of the device
WCHAR * pwcVolume;
CLocation *NextLocation; // pointer to the next location if it exists
public:
DWORD m_ColNum;
CLocation()
{
Id = NULL;
Title = NULL;
Path = NULL;
Volume = NULL;
NextLocation = NULL;
pwcId = NULL;
pwcTitle = NULL;
pwcPath = NULL;
pwcVolume = NULL;
}
~CLocation()
{
if (Id)
delete Id;
if (Title)
delete Title;
if (Path)
delete Path;
if (Volume)
delete Volume;
if (pwcId)
delete pwcId;
if (pwcTitle)
delete pwcTitle;
if (pwcPath)
delete pwcPath;
if (pwcVolume)
delete pwcVolume;
}
void SetNextLocation(CLocation *p) { NextLocation = p; }
void SetId(const CHAR *);
void SetTitle(const CHAR *);
void SetPath(const CHAR *);
void SetVolume(const CHAR *);
CHAR * GetId() const;
CHAR * GetTitle();
CHAR * GetPath();
CHAR * GetVolume();
void SetId(const WCHAR *);
void SetTitle(const WCHAR *);
void SetPath(const WCHAR *);
void SetVolume(const WCHAR *);
const WCHAR * GetIdW();
const WCHAR * GetTitleW();
const WCHAR * GetPathW();
const WCHAR * GetVolumeW();
// Returns the next location
CLocation *GetNextLocation();
};
#endif