257 lines
5.5 KiB
C
257 lines
5.5 KiB
C
/*++
|
||
|
||
|
||
|
||
|
||
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 );
|
||
}
|
||
|