131 lines
3.1 KiB
C
131 lines
3.1 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
cmquery.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the object name query method for the registry.
|
||
|
||
Author:
|
||
|
||
Bryan M. Willman (bryanwi) 8-Apr-1992
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "cmp.h"
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE,CmpQueryKeyName)
|
||
#endif
|
||
|
||
NTSTATUS
|
||
CmpQueryKeyName(
|
||
IN PVOID Object,
|
||
IN BOOLEAN HasObjectName,
|
||
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||
IN ULONG Length,
|
||
OUT PULONG ReturnLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine interfaces to the NT Object Manager. It is invoked when
|
||
the object system wishes to discover the name of an object that
|
||
belongs to the registry.
|
||
|
||
Arguments:
|
||
|
||
Object - pointer to a Key, thus -> KEY_BODY.
|
||
|
||
HasObjectName - indicates whether the object manager knows about a name
|
||
for this object
|
||
|
||
ObjectNameInfo - place where we report the name
|
||
|
||
Length - maximum length they can deal with
|
||
|
||
ReturnLength - supplies variable to receive actual length
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS
|
||
|
||
STATUS_INFO_LENGTH_MISMATCH
|
||
|
||
--*/
|
||
|
||
{
|
||
PUNICODE_STRING Name;
|
||
PWCHAR t;
|
||
PWCHAR s;
|
||
ULONG l;
|
||
NTSTATUS status;
|
||
|
||
UNREFERENCED_PARAMETER(HasObjectName);
|
||
|
||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_PARSE,"CmpQueryKeyName:\n"));
|
||
|
||
CmpLockRegistry();
|
||
|
||
if ( ((PCM_KEY_BODY)Object)->KeyControlBlock->Delete) {
|
||
CmpUnlockRegistry();
|
||
return STATUS_KEY_DELETED;
|
||
}
|
||
Name = CmpConstructName(((PCM_KEY_BODY)Object)->KeyControlBlock);
|
||
if (Name == NULL) {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
CmpUnlockRegistry();
|
||
return status;
|
||
}
|
||
|
||
if (Length <= sizeof(OBJECT_NAME_INFORMATION)) {
|
||
*ReturnLength = Name->Length + sizeof(WCHAR) + sizeof(OBJECT_NAME_INFORMATION);
|
||
ExFreePoolWithTag(Name, CM_NAME_TAG | PROTECTED_POOL);
|
||
CmpUnlockRegistry();
|
||
return STATUS_INFO_LENGTH_MISMATCH; // they can't even handle null
|
||
}
|
||
|
||
t = (PWCHAR)(ObjectNameInfo + 1);
|
||
s = Name->Buffer;
|
||
l = Name->Length;
|
||
l += sizeof(WCHAR); // account for null
|
||
|
||
|
||
*ReturnLength = l + sizeof(OBJECT_NAME_INFORMATION);
|
||
if (l > Length - sizeof(OBJECT_NAME_INFORMATION)) {
|
||
l = Length - sizeof(OBJECT_NAME_INFORMATION);
|
||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||
} else {
|
||
status = STATUS_SUCCESS;
|
||
}
|
||
l -= sizeof(WCHAR);
|
||
|
||
//
|
||
// The ObjectNameInfo buffer is a usermode buffer, so make sure we have an
|
||
// exception handler in case a malicious app changes the protection out from
|
||
// under us.
|
||
//
|
||
// Note the object manager is responsible for probing the buffer and ensuring
|
||
// that a top-level exception handler returns the correct error code. We just
|
||
// need to make sure we drop our lock.
|
||
//
|
||
try {
|
||
RtlCopyMemory(t, s, l);
|
||
t[l/sizeof(WCHAR)] = UNICODE_NULL;
|
||
ObjectNameInfo->Name.Length = (USHORT)l;
|
||
ObjectNameInfo->Name.MaximumLength = ObjectNameInfo->Name.Length;
|
||
ObjectNameInfo->Name.Buffer = t;
|
||
} finally {
|
||
ExFreePoolWithTag(Name, CM_NAME_TAG | PROTECTED_POOL);
|
||
CmpUnlockRegistry();
|
||
}
|
||
return status;
|
||
}
|