windows-nt/Source/XPSP1/NT/base/screg/winreg/client/regclass.c

257 lines
5.5 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
Regclass.c
Abstract:
This module contains the client side wrappers for the Win32 Registry
APIs to open the classes root key for a specified user.
- RegOpenUserClassesRoot
Author:
Adam Edwards (adamed) 15-Apr-1998
Notes:
This API is local only.
See the notes in server\regkey.c.
--*/
#include <rpc.h>
#include "regrpc.h"
#include "client.h"
#include <malloc.h>
#define REG_USER_CLASSES_PREFIX L"\\Registry\\User\\"
#define REG_USER_CLASSES_SUFFIX L"_Classes"
BOOL InitializeClassesEnumTable();
BOOL InitializeClassesNameSpace();
BOOL CleanupClassesEnumTable(DWORD dwCriteria);
BOOL CleanupClassesNameSpace();
#if defined(LEAK_TRACK)
NTSTATUS TrackObject(HKEY hKey);
#endif // defined(LEAK_TRACK)
extern BOOL gbCombinedClasses;
LONG
APIENTRY
RegOpenUserClassesRoot(
HANDLE hToken,
DWORD dwOptions,
REGSAM samDesired,
PHKEY phkResult
)
/*++
Routine Description:
Win32 Unicode RPC wrapper for opening the classes root key
for the use specified by the hToken parameter.
Arguments:
hToken - token for user whose classes root is to be opened. If
this parameter is NULL, we return ERROR_INVALID_PARAMETER
phkResult - Returns an open handle to the newly opened key.
Return Value:
Returns ERROR_SUCCESS (0) for success; error-code for failure.
Notes:
--*/
{
NTSTATUS Status;
UNICODE_STRING UsersHive;
BYTE achBuffer[100];
PTOKEN_USER pTokenInfo = (PTOKEN_USER) &achBuffer;
DWORD dwBytesRequired;
LONG Error;
//
// Caller must pass pointer to the variable where the opened handle
// will be returned
//
if( phkResult == NULL ) {
return ERROR_INVALID_PARAMETER;
}
if (NULL == hToken) {
return ERROR_INVALID_PARAMETER;
}
if (dwOptions != REG_OPTION_RESERVED) {
return ERROR_INVALID_PARAMETER;
}
if (!gbCombinedClasses) {
return ERROR_FILE_NOT_FOUND;
}
//
// open up the token to get the sid
//
if (!GetTokenInformation(
hToken, // Handle
TokenUser, // TokenInformationClass
pTokenInfo, // TokenInformation
sizeof(achBuffer), // TokenInformationLength
&dwBytesRequired // ReturnLength
)) {
Error = GetLastError();
//
// Try again if the buffer was too small
//
if (ERROR_INSUFFICIENT_BUFFER != Error) {
return Error ;
}
//
// Allocate space for the user info
//
pTokenInfo = (PTOKEN_USER) alloca(dwBytesRequired);
if (!pTokenInfo) {
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Read in the UserInfo
//
if (!GetTokenInformation(
hToken, // Handle
TokenUser, // TokenInformationClass
pTokenInfo, // TokenInformation
dwBytesRequired, // TokenInformationLength
&dwBytesRequired // ReturnLength
)) {
return GetLastError();
}
}
//
// Change sid to a string
//
Status = RtlConvertSidToUnicodeString(
&UsersHive,
pTokenInfo->User.Sid,
TRUE); // allocate the string
if (NT_SUCCESS(Status)) {
UNICODE_STRING UserClassesString;
UserClassesString.MaximumLength = UsersHive.Length +
sizeof(REG_USER_CLASSES_PREFIX) +
sizeof(REG_USER_CLASSES_SUFFIX);
UserClassesString.Buffer = (WCHAR*) alloca(UserClassesString.MaximumLength);
if (UserClassesString.Buffer) {
UNICODE_STRING UserPrefix;
//
// construct the name
//
RtlInitUnicodeString(&UserPrefix, REG_USER_CLASSES_PREFIX);
RtlCopyUnicodeString(&UserClassesString, &UserPrefix);
Status = RtlAppendUnicodeStringToString(&UserClassesString, &UsersHive);
if (NT_SUCCESS(Status)) {
Status = RtlAppendUnicodeToString(&UserClassesString,
REG_USER_CLASSES_SUFFIX);
}
if (NT_SUCCESS(Status)) {
OBJECT_ATTRIBUTES Obja;
// open this key
InitializeObjectAttributes(
&Obja,
&UserClassesString,
OBJ_CASE_INSENSITIVE,
NULL, // using absolute path, no hkey
NULL);
Status = NtOpenKey(
phkResult,
samDesired,
&Obja);
}
} else {
Status = STATUS_NO_MEMORY;
}
RtlFreeUnicodeString(&UsersHive);
}
if (NT_SUCCESS(Status)) {
#if defined(LEAK_TRACK)
if (g_RegLeakTraceInfo.bEnableLeakTrack) {
(void) TrackObject(*phkResult);
}
#endif defined(LEAK_TRACK)
// mark this key as a class key
TagSpecialClassesHandle(phkResult);
}
return RtlNtStatusToDosError(Status);
}
BOOL InitializeClassesRoot()
{
if (!InitializeClassesEnumTable()) {
return FALSE;
}
return TRUE;
}
BOOL CleanupClassesRoot(BOOL fOnlyThisThread)
{
//
// Always remove enumeration states for this thread
//
return CleanupClassesEnumTable( fOnlyThisThread );
}