WindowsXP-SP1/windows/appcompat/sdbapi/findtag.c
2020-09-30 16:53:49 +02:00

528 lines
15 KiB
C

/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
findtag.c
Abstract:
BUGBUG: This module implements ...
Author:
dmunsil created sometime in 1999
Revision History:
several people contributed (vadimb, clupu, ...)
--*/
#include "sdbp.h"
#if defined(KERNEL_MODE) && defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE, SdbFindFirstTag)
#pragma alloc_text(PAGE, SdbFindNextTag)
#pragma alloc_text(PAGE, SdbFindFirstNamedTag)
#pragma alloc_text(PAGE, SdbpFindNextNamedTag)
#pragma alloc_text(PAGE, SdbpFindMatchingName)
#pragma alloc_text(PAGE, SdbpFindMatchingDWORD)
#pragma alloc_text(PAGE, SdbpFindMatchingGUID)
#pragma alloc_text(PAGE, SdbFindFirstTagRef)
#pragma alloc_text(PAGE, SdbFindNextTagRef)
#endif // KERNEL_MODE && ALLOC_PRAGMA
TAGID
SdbFindFirstTag(
IN PDB pdb, // pdb to use
IN TAGID tiParent, // parent (must be LIST tag)
IN TAG tTag // tag to match
)
/*++
Return: The tag id found or TAGID_NULL on failure.
Desc: Finds the first child of tiParent that is a tag of type tTag.
--*/
{
TAGID tiTemp;
TAGID tiReturn = TAGID_NULL;
assert(pdb);
tiTemp = SdbGetFirstChild(pdb, tiParent);
while (tiTemp != TAGID_NULL) {
if (SdbGetTagFromTagID(pdb, tiTemp) == tTag) {
tiReturn = tiTemp;
break;
}
tiTemp = SdbGetNextChild(pdb, tiParent, tiTemp);
}
return tiReturn;
}
TAGID
SdbFindNextTag(
IN PDB pdb, // DB to use
IN TAGID tiParent, // parent tag to search (must be LIST)
IN TAGID tiPrev // previously found child of required type
)
/*++
Return: The next matching child of tiParent, or TAGID_NULL if no more.
Desc: Finds the next child of tiParent, starting with the one after tiPrev,
that is a tag of the same type as tiPrev.
--*/
{
TAGID tiTemp;
TAGID tiReturn = TAGID_NULL;
TAG tTag;
assert(pdb);
tTag = SdbGetTagFromTagID(pdb, tiPrev);
if (tTag == TAG_NULL) {
DBGPRINT((sdlError, "SdbFindNextTag", "Invalid tagid 0x%lx\n", tiPrev));
return TAGID_NULL;
}
tiTemp = SdbGetNextChild(pdb, tiParent, tiPrev);
while (tiTemp != TAGID_NULL) {
if (SdbGetTagFromTagID(pdb, tiTemp) == tTag) {
tiReturn = tiTemp;
break;
}
tiTemp = SdbGetNextChild(pdb, tiParent, tiTemp);
}
return tiReturn;
}
TAGID
SdbFindFirstNamedTag(
IN PDB pdb, // DB to use
IN TAGID tiParent, // parent to search in
IN TAG tToFind, // tag type to find
IN TAG tName, // child of found tag that will be some kind
// of STRING or STRINGREF
IN LPCTSTR pszName // string to search for
)
/*++
Return: The tag id found or TAGID_NULL if no tags match the criteria.
Desc: Scans sequentially through the children of tiParent, looking for
tags of type tToFind. When it finds one, it looks for a child of
that tag of type tName, and if found, compares that string to the
passed-in string. If they match, it returns the TAGID of the tag
of type tToFind.
--*/
{
TAGID tiTemp;
TAGID tiReturn = TAGID_NULL;
assert(pdb);
tiTemp = SdbGetFirstChild(pdb, tiParent);
while (tiTemp != TAGID_NULL) {
if (SdbGetTagFromTagID(pdb, tiTemp) == tToFind) {
TAGID tiName;
tiName = SdbFindFirstTag(pdb, tiTemp, tName);
if (tiName != TAGID_NULL) {
LPTSTR pszTemp;
pszTemp = SdbGetStringTagPtr(pdb, tiName);
if (pszTemp == NULL) {
DBGPRINT((sdlError,
"SdbFindFirstNamedTag",
"Can't get the name string.\n"));
break;
}
if (_tcsicmp(pszName, pszTemp) == 0) {
tiReturn = tiTemp;
break;
}
}
}
tiTemp = SdbGetNextChild(pdb, tiParent, tiTemp);
}
return tiReturn;
}
TAGID
SdbpFindNextNamedTag(
IN PDB pdb, // DB to use
IN TAGID tiParent, // parent to search in
IN TAGID tiPrev, // previously found record
IN TAG tName, // tag type that should be a STRING or STRINGREF
IN LPCTSTR pszName // string to search for
)
/*++
Return: The tag id found or TAGID_NULL if no tags match the criteria.
Desc: Scans sequentially through the children of tiParent, starting with tiPrev,
looking for tags of the same type as tiPrev.
When it finds one, it looks for a child of that tag of type tName,
and if found, compares that string to the passed-in string. If they
match, it returns the TAGID of the tag of the same type as tiPrev.
--*/
{
TAGID tiTemp;
TAGID tiReturn = TAGID_NULL;
TAG tToFind;
assert(pdb);
tToFind = SdbGetTagFromTagID(pdb, tiPrev);
if (tToFind == TAG_NULL) {
DBGPRINT((sdlError, "SdbpFindNextNamedTag", "Invalid tagid 0x%lx\n", tiPrev));
return TAGID_NULL;
}
tiTemp = SdbGetNextChild(pdb, tiParent, tiPrev);
while (tiTemp != TAGID_NULL) {
if (SdbGetTagFromTagID(pdb, tiTemp) == tToFind) {
TAGID tiName;
tiName = SdbFindFirstTag(pdb, tiTemp, tName);
if (tiName != TAGID_NULL) {
LPTSTR pszTemp;
pszTemp = SdbGetStringTagPtr(pdb, tiName);
if (pszTemp == NULL) {
DBGPRINT((sdlError,
"SdbpFindNextNamedTag",
"Can't get the name string tagid 0x%lx\n",
tiName));
break;
}
if (_tcsicmp(pszName, pszTemp) == 0) {
tiReturn = tiTemp;
break;
}
}
}
tiTemp = SdbGetNextChild(pdb, tiParent, tiTemp);
}
return tiReturn;
}
TAGID
SdbpFindMatchingName(
IN PDB pdb, // DB to use
IN TAGID tiStart, // the tag where to start from
IN FIND_INFO* pFindInfo // pointer to the search context structure
)
/*++
Return: The tag id found or TAGID_NULL if no tags match the criteria.
Desc: Given a database handle and a starting point in the database
the function scans the database to find the name matching the one
provided while calling one of the search functions.
--*/
{
TAGID tiName;
LPTSTR pszTemp;
TAGID tiReturn = tiStart;
while (tiReturn != TAGID_NULL) {
tiName = SdbFindFirstTag(pdb, tiReturn, pFindInfo->tName);
if (tiName == TAGID_NULL) {
DBGPRINT((sdlError,
"SdbpFindMatchingName",
"The tag 0x%x was not found under tag 0x%x.\n",
tiReturn,
pFindInfo->tName));
return TAGID_NULL;
}
//
// Get the pointer to the string.
//
pszTemp = SdbGetStringTagPtr(pdb, tiName);
if (pszTemp == NULL) {
DBGPRINT((sdlError,
"SdbpFindMatchingName",
"Can't get the name string for tagid 0x%x.\n",
tiName));
return TAGID_NULL; // corrupt database
}
//
// We have two different index styles. One index is a "unique" kind
// of index when each key in the index table occurs only once.
// The second kind stores all the occurences of keys. We check for the
// kind of index we're searching to determine what the proper
// comparison routine should be. Unique-style index has all the
// child items (having the same index value) sorted in ascending order
// by shimdbc. As a result we take advantage of that while performing
// matching on the name.
//
if (pFindInfo->dwFlags & SHIMDB_INDEX_UNIQUE_KEY) {
int iCmp;
iCmp = _tcsicmp(pFindInfo->szName, pszTemp);
//
// szName (string we search for) < szTemp (string from the db)
// we have not found our target, since all the strings in the database
// are sorted in ascending order
//
if (iCmp < 0) {
//
// No dpf here, what we were looking for was not found
//
return TAGID_NULL;
}
//
// Break if there is a match.
//
if (iCmp == 0) {
break;
}
} else {
//
// When using non-unique index the only kind of comparison
// that needs to be done is a direct comparison for equality.
//
if (_tcsicmp(pszTemp, pFindInfo->szName) == 0) {
//
// It's a match, so return it.
//
break;
}
}
tiReturn = SdbpGetNextIndexedRecord(pdb, pFindInfo->tiIndex, pFindInfo);
}
return tiReturn;
}
TAGID
SdbpFindMatchingDWORD(
IN PDB pdb, // DB to use
IN TAGID tiStart, // the tag where to start from
IN FIND_INFO* pFindInfo // pointer to the search context structure
)
/*++
Return: The tag id found or TAGID_NULL if no tags match the criteria.
Desc: BUGBUG: comments ?
--*/
{
TAGID tiName;
TAGID tiReturn = tiStart;
DWORD dwTemp;
while (tiReturn != TAGID_NULL) {
tiName = SdbFindFirstTag(pdb, tiReturn, pFindInfo->tName);
if (tiName == TAGID_NULL) {
DBGPRINT((sdlError,
"SdbpFindMatchingDWORD",
"The tag 0x%lx was not found under tag 0x%lx\n",
tiReturn,
pFindInfo->tName));
return TAGID_NULL;
}
dwTemp = SdbReadDWORDTag(pdb, tiName, (DWORD)-1);
if (dwTemp == (DWORD)-1) {
//
// This is not an error condition, merely an indication that the
// dword we were looking for was not found in the database.
//
return TAGID_NULL;
}
if (dwTemp == pFindInfo->dwName) {
break;
}
tiReturn = SdbpGetNextIndexedRecord(pdb, pFindInfo->tiIndex, pFindInfo);
}
return tiReturn;
}
TAGID
SdbpFindMatchingGUID(
IN PDB pdb, // DB to use
IN TAGID tiStart, // the tag where to start from
IN FIND_INFO* pFindInfo // pointer to the search context structure
)
/*++
Return: The tag id found or TAGID_NULL if no tags match the criteria.
Desc: BUGBUG: comments ?
--*/
{
GUID guidID = { 0 };
TAGID tiReturn = tiStart;
TAGID tiName;
DWORD dwTemp;
while (tiReturn != TAGID_NULL) {
tiName = SdbFindFirstTag(pdb, tiReturn, pFindInfo->tName);
if (tiName == TAGID_NULL) {
DBGPRINT((sdlError,
"SdbpFindMatchingGUID",
"The tag 0x%lx was not found under tag 0x%lx\n",
tiReturn,
pFindInfo->tName));
return TAGID_NULL;
}
if (!SdbReadBinaryTag(pdb, tiName, (PBYTE)&guidID, sizeof(guidID))) {
DBGPRINT((sdlError, "SdbpFindMatchingGUID",
"Cannot read binary tag 0x%lx\n", tiName));
return TAGID_NULL;
}
//
// verify whether the key for this entry is still the same as it is
// for original guid, if not -- that's it, guid key was not found
//
if (IS_MEMORY_EQUAL(&guidID, pFindInfo->pguidName, sizeof(guidID))) {
break;
}
tiReturn = SdbpGetNextIndexedRecord(pdb, pFindInfo->tiIndex, pFindInfo);
}
return tiReturn;
}
TAGREF
SdbFindFirstTagRef(
IN HSDB hSDB, // handle to the database channel
IN TAGREF trParent, // parent to search
IN TAG tTag // tag we're looking for
)
/*++
Return: The tagref of the first child that matches tTag.
Desc: Scans sequentially through all children of trParent, looking
for the first tag that matches tTag. Returns the first found,
or TAGREF_NULL if there are no children with that type.
trParent can be 0 (or TAGREF_ROOT) to look through the root tags,
which at this point are only DATABASE and possibly STRINGTABLE.
--*/
{
PDB pdb;
TAGID tiParent;
TAGID tiReturn;
TAGREF trReturn = TAGREF_NULL;
if (!SdbTagRefToTagID(hSDB, trParent, &pdb, &tiParent)) {
DBGPRINT((sdlError, "SdbFindFirstTagRef", "Can't convert tag ref.\n"));
goto err1;
}
tiReturn = SdbFindFirstTag(pdb, tiParent, tTag);
if (tiReturn == TAGID_NULL) {
//
// No error here. We just didn't find the tag.
//
goto err1;
}
if (!SdbTagIDToTagRef(hSDB, pdb, tiReturn, &trReturn)) {
DBGPRINT((sdlError, "SdbFindFirstTagRef", "Can't convert TAGID.\n"));
trReturn = TAGREF_NULL;
goto err1;
}
err1:
return trReturn;
}
TAGREF
SdbFindNextTagRef(
IN HSDB hSDB, // handle to the database channel
IN TAGREF trParent, // parent to search
IN TAGREF trPrev // previous child found
)
/*++
Return: The tagref of the next child of parent that matches trPrev.
Desc: Scans sequentially through all children of trParent, starting with
the first tag after trPrev, looking for the first tag that
matches tTag. Returns the next found, or TAGREF_NULL if there are
no more children with that type.
trParent can be 0 (or TAGREF_ROOT) to look through the root tags,
which at this point are only DATABASE and possibly STRINGTABLE.
--*/
{
PDB pdb;
TAGID tiParent;
TAGID tiPrev;
TAGID tiReturn;
TAGREF trReturn;
if (!SdbTagRefToTagID(hSDB, trParent, &pdb, &tiParent)) {
DBGPRINT((sdlError, "SdbFindNextTagRef", "Can't convert tag ref trParent.\n"));
return TAGREF_NULL;
}
if (!SdbTagRefToTagID(hSDB, trPrev, &pdb, &tiPrev)) {
DBGPRINT((sdlError, "SdbFindNextTagRef", "Can't convert tag ref trPrev.\n"));
return TAGREF_NULL;
}
tiReturn = SdbFindNextTag(pdb, tiParent, tiPrev);
if (tiReturn == TAGID_NULL) {
//
// No error here.
//
return TAGREF_NULL;
}
if (!SdbTagIDToTagRef(hSDB, pdb, tiReturn, &trReturn)) {
DBGPRINT((sdlError, "SdbFindNextTagRef", "Can't convert TAGID.\n"));
return TAGREF_NULL;
}
return trReturn;
}