mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
253 lines
7 KiB
C
253 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;
|
|
}
|