Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

515 lines
11 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
regutil.c
Abstract:
Utilities for accessing the system registry.
Author:
Mike Massa (mikemas) May 19, 1997
Revision History:
Who When What
-------- -------- ----------------------------------------------
mikemas 05-19-97 created
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
LPCWSTR
ClRtlMultiSzEnum(
IN LPCWSTR MszString,
IN DWORD MszStringLength,
IN DWORD StringIndex
)
/*++
Routine Description:
Parses a REG_MULTI_SZ string and returns the specified substring.
Arguments:
MszString - A pointer to the REG_MULTI_SZ string.
MszStringLength - The length of the REG_MULTI_SZ string in characters,
including the terminating null character.
StringIndex - Index number of the substring to return. Specifiying
index 0 retrieves the first substring.
Return Value:
A pointer to the specified substring.
--*/
{
LPCWSTR string = MszString;
if ( MszStringLength < 2 ) {
return(NULL);
}
//
// Find the start of the desired string.
//
while (StringIndex) {
while (MszStringLength >= 1) {
MszStringLength -= 1;
if (*string++ == UNICODE_NULL) {
break;
}
}
//
// Check for index out of range.
//
if ( MszStringLength < 2 ) {
return(NULL);
}
StringIndex--;
}
if ( MszStringLength < 2 ) {
return(NULL);
}
return(string);
}
DWORD
ClRtlMultiSzRemove(
IN LPWSTR lpszMultiSz,
IN OUT LPDWORD StringLength,
IN LPCWSTR lpString
)
/*++
Routine Description:
Removes the specified string from the supplied REG_MULTI_SZ.
The MULTI_SZ is edited in place.
Arguments:
lpszMultiSz - Supplies the REG_MULTI_SZ string that lpString should
be removed from.
StringLength - Supplies the length (in characters) of lpszMultiSz
Returns the new length (in characters) of lpszMultiSz
lpString - Supplies the string to be removed from lpszMultiSz
Return Value:
ERROR_SUCCESS if successful
ERROR_FILE_NOT_FOUND if the string was not found in the MULTI_SZ
Win32 error code otherwise
--*/
{
PCHAR Dest, Src;
DWORD CurrentLength;
DWORD i;
LPCWSTR Next;
DWORD NextLength;
//
// Scan through the strings in the returned MULTI_SZ looking
// for a match.
//
CurrentLength = *StringLength;
for (i=0; ;i++) {
Next = ClRtlMultiSzEnum(lpszMultiSz, *StringLength, i);
if (Next == NULL) {
//
// The value was not in the specified multi-sz
//
break;
}
NextLength = lstrlenW(Next)+1;
CurrentLength -= NextLength;
if (lstrcmpiW(Next, lpString)==0) {
//
// Found the string, delete it and return
//
Dest = (PCHAR)Next;
Src = (PCHAR)Next + (NextLength*sizeof(WCHAR));
CopyMemory(Dest, Src, CurrentLength*sizeof(WCHAR));
*StringLength -= NextLength;
return(ERROR_SUCCESS);
}
}
return(ERROR_FILE_NOT_FOUND);
}
DWORD
ClRtlMultiSzAppend(
IN OUT LPWSTR *MultiSz,
IN OUT LPDWORD StringLength,
IN LPCWSTR lpString
)
/*++
Routine Description:
Appends the specified string to the supplied REG_MULTI_SZ.
The passed in MultiSz will be freed with LocalFree. A new
MultiSz large enough to hold the new value will be allocated
with LocalAlloc and returned in *MultiSz
Arguments:
lpszMultiSz - Supplies the REG_MULTI_SZ string that lpString should
be appended to.
Returns the new REG_MULTI_SZ string with lpString appended
StringLength - Supplies the length (in characters) of lpszMultiSz
Returns the new length (in characters) of lpszMultiSz
lpString - Supplies the string to be appended to lpszMultiSz
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
LPWSTR NewMultiSz;
DWORD Length;
DWORD NewLength;
if (*MultiSz == NULL) {
//
// There is no multi-sz, create a new multi-sz with lpString as the
// only entry.
//
NewLength = lstrlenW(lpString)+2;
NewMultiSz = LocalAlloc(LMEM_FIXED, NewLength*sizeof(WCHAR));
if (NewMultiSz == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
CopyMemory(NewMultiSz, lpString, (NewLength-1)*sizeof(WCHAR));
} else {
//
// Append this string to the existing MULTI_SZ
//
Length = lstrlenW(lpString) + 1;
NewLength = *StringLength + Length;
NewMultiSz = LocalAlloc(LMEM_FIXED, NewLength * sizeof(WCHAR));
if (NewMultiSz == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
CopyMemory(NewMultiSz, *MultiSz, *StringLength * sizeof(WCHAR));
CopyMemory(NewMultiSz + *StringLength - 1, lpString, Length * sizeof(WCHAR));
NewMultiSz[NewLength-1] = L'\0';
//Free the passed in MultiSz
LocalFree(*MultiSz);
}
NewMultiSz[NewLength-1] = L'\0';
*MultiSz = NewMultiSz;
*StringLength = NewLength;
return(ERROR_SUCCESS);
}
DWORD
ClRtlMultiSzLength(
IN LPCWSTR lpszMultiSz
)
/*++
Routine Description:
Determines the length (in characters) of a multi-sz. The calculated
length includes all trailing NULLs.
Arguments:
lpszMultiSz - Supplies the multi-sz
Return Value:
The length (in characters) of the supplied multi-sz
--*/
{
LPCWSTR p;
DWORD Length=0;
if(!lpszMultiSz)
return 0;
if (*lpszMultiSz == UNICODE_NULL)
return 1;
p=lpszMultiSz;
do {
while (p[Length++] != L'\0') {
}
} while ( p[Length++] != L'\0' );
return(Length);
}
LPCWSTR
ClRtlMultiSzScan(
IN LPCWSTR lpszMultiSz,
IN LPCWSTR lpszString
)
/*++
Routine Description:
Scans a multi-sz looking for an entry that matches the specified string.
The match is done case-insensitive.
Arguments:
lpszMultiSz - Supplies the multi-sz to scan.
lpszString - Supplies the string to look for
Return Value:
A pointer to the string in the supplied multi-sz if found.
NULL if not found.
--*/
{
DWORD dwLength;
DWORD i;
LPCWSTR sz;
dwLength = ClRtlMultiSzLength(lpszMultiSz);
for (i=0; ; i++) {
sz = ClRtlMultiSzEnum(lpszMultiSz,
dwLength,
i);
if (sz == NULL) {
break;
}
if (lstrcmpiW(sz, lpszString) == 0) {
break;
}
}
return(sz);
}
DWORD
ClRtlRegQueryDword(
IN HKEY hKey,
IN LPWSTR lpValueName,
OUT LPDWORD lpValue,
IN LPDWORD lpDefaultValue OPTIONAL
)
/*++
Routine Description:
Reads a REG_DWORD registry value. If the value is not present, then
default to the value supplied in lpDefaultValue (if present).
Arguments:
hKey - Open key for the value to be read.
lpValueName - Unicode name of the value to be read.
lpValue - Pointer to the DWORD into which to read the value.
lpDefaultValue - Optional pointer to a DWORD to use as a default value.
Return Value:
ERROR_SUCCESS if successful
Win32 error code otherwise
--*/
{
HKEY Key;
DWORD Status;
DWORD ValueType;
DWORD ValueSize = sizeof(DWORD);
Status = RegQueryValueExW(
hKey,
lpValueName,
NULL,
&ValueType,
(LPBYTE)lpValue,
&ValueSize
);
if ( Status == ERROR_SUCCESS ) {
if ( ValueType != REG_DWORD ) {
Status = ERROR_INVALID_PARAMETER;
}
} else {
if ( ARGUMENT_PRESENT( lpDefaultValue ) ) {
*lpValue = *lpDefaultValue;
Status = ERROR_SUCCESS;
}
}
return(Status);
} // ClRtlRegQueryDword
DWORD
ClRtlRegQueryString(
IN HKEY Key,
IN LPWSTR ValueName,
IN DWORD ValueType,
IN LPWSTR *StringBuffer,
IN OUT LPDWORD StringBufferSize,
OUT LPDWORD StringSize
)
/*++
Routine Description:
Reads a REG_SZ or REG_MULTI_SZ registry value. If the StringBuffer is
not large enough to hold the data, it is reallocated.
Arguments:
Key - Open key for the value to be read.
ValueName - Unicode name of the value to be read.
ValueType - REG_SZ or REG_MULTI_SZ.
StringBuffer - Buffer into which to place the value data.
StringBufferSize - Pointer to the size of the StringBuffer. This parameter
is updated if StringBuffer is reallocated.
StringSize - The size of the data returned in StringBuffer, including
the terminating null character.
Return Value:
The status of the registry query.
--*/
{
DWORD status;
DWORD valueType;
WCHAR *temp;
DWORD oldBufferSize = *StringBufferSize;
BOOL noBuffer = FALSE;
if (*StringBufferSize == 0) {
noBuffer = TRUE;
}
*StringSize = *StringBufferSize;
status = RegQueryValueExW(
Key,
ValueName,
NULL,
&valueType,
(LPBYTE) *StringBuffer,
StringSize
);
if (status == NO_ERROR) {
if (!noBuffer ) {
if (valueType == ValueType) {
return(NO_ERROR);
}
else {
return(ERROR_INVALID_PARAMETER);
}
}
status = ERROR_MORE_DATA;
}
if (status == ERROR_MORE_DATA) {
temp = LocalAlloc(LMEM_FIXED, *StringSize);
if (temp == NULL) {
*StringSize = 0;
return(ERROR_NOT_ENOUGH_MEMORY);
}
if (!noBuffer) {
LocalFree(*StringBuffer);
}
*StringBuffer = temp;
*StringBufferSize = *StringSize;
status = RegQueryValueExW(
Key,
ValueName,
NULL,
&valueType,
(LPBYTE) *StringBuffer,
StringSize
);
if (status == NO_ERROR) {
if (valueType == ValueType) {
return(NO_ERROR);
}
else {
*StringSize = 0;
return(ERROR_INVALID_PARAMETER);
}
}
}
return(status);
} // ClRtlRegQueryString