reactos/sdk/lib/cmlib/cmname.c

254 lines
7 KiB
C

/*
* PROJECT: ReactOS Registry Library
* LICENSE: GPL - See COPYING in the top level directory
* FILE: lib/cmlib/cmname.c
* PURPOSE: Configuration Manager - Name Management
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "cmlib.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
USHORT
NTAPI
CmpCopyName(IN PHHIVE Hive,
OUT PWCHAR Destination,
IN PCUNICODE_STRING Source)
{
ULONG i;
/* Check for old hives */
if (Hive->Version == 1)
{
/* Just copy the source directly */
RtlCopyMemory(Destination, Source->Buffer, Source->Length);
return Source->Length;
}
/* For new versions, check for compressed name */
for (i = 0; i < (Source->Length / sizeof(WCHAR)); i++)
{
/* Check if the name is non compressed */
if (Source->Buffer[i] > (UCHAR)-1)
{
/* Do the copy */
RtlCopyMemory(Destination, Source->Buffer, Source->Length);
return Source->Length;
}
/* Copy this character */
((PCHAR)Destination)[i] = (CHAR)(Source->Buffer[i]);
}
/* Compressed name, return length */
return Source->Length / sizeof(WCHAR);
}
VOID
NTAPI
CmpCopyCompressedName(OUT PWCHAR Destination,
IN ULONG DestinationLength,
IN PWCHAR Source,
IN ULONG SourceLength)
{
ULONG i, Length;
/* Get the actual length to copy */
Length = min(DestinationLength / sizeof(WCHAR), SourceLength);
for (i = 0; i < Length; i++)
{
/* Copy each character */
Destination[i] = (WCHAR)((PUCHAR)Source)[i];
}
}
USHORT
NTAPI
CmpNameSize(IN PHHIVE Hive,
IN PCUNICODE_STRING Name)
{
ULONG i;
/* For old hives, just return the length */
if (Hive->Version == 1) return Name->Length;
/* For new versions, check for compressed name */
for (i = 0; i < (Name->Length / sizeof(WCHAR)); i++)
{
/* Check if the name is non compressed */
if (Name->Buffer[i] > (UCHAR)-1) return Name->Length;
}
/* Compressed name, return length */
return Name->Length / sizeof(WCHAR);
}
USHORT
NTAPI
CmpCompressedNameSize(IN PWCHAR Name,
IN ULONG Length)
{
/*
* Don't remove this: compressed names are "opaque" and just because
* the current implementation turns them into ansi-names doesn't mean
* that it will remain that way forever, so -never- assume this code
* below internally!
*/
return (USHORT)Length * sizeof(WCHAR);
}
LONG
NTAPI
CmpCompareCompressedName(IN PCUNICODE_STRING SearchName,
IN PWCHAR CompressedName,
IN ULONG NameLength)
{
WCHAR* p;
UCHAR* pp;
WCHAR chr1, chr2;
USHORT SearchLength;
LONG Result;
/* Set the pointers and length and then loop */
p = SearchName->Buffer;
pp = (PUCHAR)CompressedName;
SearchLength = (SearchName->Length / sizeof(WCHAR));
while (SearchLength > 0 && NameLength > 0)
{
/* Get the characters */
chr1 = *p++;
chr2 = (WCHAR)(*pp++);
/* Check if we have a direct match */
if (chr1 != chr2)
{
/* See if they match and return result if they don't */
Result = (LONG)RtlUpcaseUnicodeChar(chr1) -
(LONG)RtlUpcaseUnicodeChar(chr2);
if (Result) return Result;
}
/* Next chars */
SearchLength--;
NameLength--;
}
/* Return the difference directly */
return SearchLength - NameLength;
}
BOOLEAN
NTAPI
CmpFindNameInList(IN PHHIVE Hive,
IN PCHILD_LIST ChildList,
IN PCUNICODE_STRING Name,
OUT PULONG ChildIndex OPTIONAL,
OUT PHCELL_INDEX CellIndex)
{
PCELL_DATA CellData;
HCELL_INDEX CellToRelease = HCELL_NIL;
ULONG i;
PCM_KEY_VALUE KeyValue;
LONG Result;
UNICODE_STRING SearchName;
BOOLEAN Success;
/* Make sure there's actually something on the list */
if (ChildList->Count != 0)
{
/* Get the cell data */
CellData = (PCELL_DATA)HvGetCell(Hive, ChildList->List);
if (!CellData)
{
/* Couldn't get the cell... tell the caller */
*CellIndex = HCELL_NIL;
return FALSE;
}
/* Now loop every entry */
for (i = 0; i < ChildList->Count; i++)
{
/* Check if we have a cell to release */
if (CellToRelease != HCELL_NIL)
{
/* Release it */
HvReleaseCell(Hive, CellToRelease);
CellToRelease = HCELL_NIL;
}
/* Get this value */
KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellData->u.KeyList[i]);
if (!KeyValue)
{
/* Return with no data found */
*CellIndex = HCELL_NIL;
Success = FALSE;
goto Return;
}
/* Save the cell to release */
CellToRelease = CellData->u.KeyList[i];
/* Check if it's a compressed value name */
if (KeyValue->Flags & VALUE_COMP_NAME)
{
/* Compare compressed names */
Result = CmpCompareCompressedName(Name,
KeyValue->Name,
KeyValue->NameLength);
}
else
{
/* Compare the Unicode name directly */
SearchName.Length = KeyValue->NameLength;
SearchName.MaximumLength = SearchName.Length;
SearchName.Buffer = KeyValue->Name;
Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
}
/* Check if we found it */
if (!Result)
{
/* We did... return info to caller */
if (ChildIndex) *ChildIndex = i;
*CellIndex = CellData->u.KeyList[i];
/* Set success state */
Success = TRUE;
goto Return;
}
}
/* Got to the end of the list */
if (ChildIndex) *ChildIndex = i;
*CellIndex = HCELL_NIL;
/* Nothing found if we got here */
Success = TRUE;
goto Return;
}
/* Nothing found... check if the caller wanted more info */
ASSERT(ChildList->Count == 0);
if (ChildIndex) *ChildIndex = 0;
*CellIndex = HCELL_NIL;
/* Nothing found if we got here */
return TRUE;
Return:
/* Release the first cell we got */
if (CellData) HvReleaseCell(Hive, ChildList->List);
/* Release the secondary one, if we have one */
if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
return Success;
}