Hi, all,
I didn’t expect this thread to generate so much interest
Thanks for
everyone to help me out with the problem!
1.) Yes, R. Yang and Pavel are correct, at least for RegNtDeleteKey and
RegNtDeleteValueKey, the Object is a POINTER to a registry object, NOT
a pointer to a pointer to a registry object as shown in MSDN.
2.) I have tried to pass in both a pre-allocated buffer as well as a
NULL buffer, which I have shown in the code I posted. And for both
methods I get a PAGE_FAULT_IN_NONPAGED_AREA fault. The debug session
attached below show the code sample where I use a buffer of size 24 for
the first ObQueryNameString call.
3.) For the debug session attached below, this is a fault generated when
my code handles RegNtPostOpenKey:
case RegNtPostOpenKey:
{
PREG_POST_OPEN_KEY_INFORMATION pInfo =
(PREG_POST_OPEN_KEY_INFORMATION) arg2;
if (pInfo != NULL) {
// Find out which key the process is trying to open, and
// cache this information. Only cache it if it was successful
if (NT_SUCCESS(pInfo->Status)) {
//
// This call causes the BSOD, line 737 of registry.c
PUNICODE_STRING fullPath = QueryObjectFullPath( pInfo->Object
);
}
And here is the code for handling QueryObjectFullPath, notice that I
have changed it to follow Anton’s suggestion, and it gives the same
result.
PUNICODE_STRING
QueryObjectFullPath(PVOID object)
{
USHORT returnLength = 0;
OBJECT_NAME_INFORMATION info;
NTSTATUS status;
if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
PUNICODE_STRING path = NULL;
info.Name.Buffer = ExAllocatePoolWithTag(PagedPool, 1024,
‘PAGE’);
info.Name.Length = 1024;
info.Name.MaximumLength = 1024;
// This is line 1310 in util.c, where the fault occurred
status = ObQueryNameString(object, &info,
sizeof(OBJECT_NAME_INFORMATION) +
1024,
&returnLength );
…
}
kd> !analyze -v
************************************************************************
*******
*
*
* Bugcheck Analysis
*
*
*
************************************************************************
*******
PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by
try-except,
it must be protected by a Probe. Typically the address is just plain
bad or it
is pointing at freed memory.
Arguments:
Arg1: c2dec3d2, memory referenced.
Arg2: 00000000, value 0 = read operation, 1 = write operation.
Arg3: c2dec3d2, If non-zero, the instruction address which referenced
the bad memory
address.
Arg4: 00000000, (reserved)
Debugging Details:
READ_ADDRESS: c2dec3d2
FAULTING_IP:
+ffffffffc2dec3d2
c2dec3d2 ?? ???
MM_INTERNAL_CODE: 0
DEFAULT_BUCKET_ID: DRIVER_FAULT
BUGCHECK_STR: 0x50
PROCESS_NAME: explorer.exe
TRAP_FRAME: f7b5a248 – (.trap fffffffff7b5a248)
ErrCode = 00000000
eax=01000000 ebx=f7b5ac03 ecx=c2dec3d2 edx=56350101 esi=56350100
edi=f7b5ac0f
eip=c2dec3d2 esp=f7b5a2bc ebp=f7b5a3dc iopl=0 nv up ei pl zr na
pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000
efl=00010246
c2dec3d2 ?? ???
Resetting default scope
LAST_CONTROL_TRANSFER: from 80532487 to 804e3592
FAILED_INSTRUCTION_ADDRESS:
+ffffffffc2dec3d2
c2dec3d2 ?? ???
STACK_TEXT:
f7b59d98 80532487 00000004 00001000 00000000
nt!RtlpBreakWithStatusInstruction
f7b59de4 8053343b 00000004 806ee298 c030b7b0
nt!KiBugCheckDebugBreak+0x19
f7b5a1c4 8053354e 00000050 c2dec3d2 00000000 nt!KeBugCheck2+0xa51
f7b5a1e4 80523fa0 00000050 c2dec3d2 00000000 nt!KeBugCheckEx+0x1b
f7b5a230 804e1718 00000000 c2dec3d2 00000000 nt!MmAccessFault+0x6f5
f7b5a230 c2dec3d2 00000000 c2dec3d2 00000000 nt!KiTrap0E+0xcc
WARNING: Frame IP not in any known module. Following frames may be
wrong.
f7b5a2b8 80581d36 f7b5ac1c 01000000 f7b5a408 0xc2dec3d2
f7b5a3dc f77cc8ad f7b5ac1c f7b5a408 00000018 nt!ObQueryNameString+0xe0
f7b5a424 f77cd94d f7b5ac1c f742f115 e1bf7fb8
Argus!QueryObjectFullPath+0x4d [c:\starteam\research\argus\util\util.c @
1310]
f7b5a99c 80610417 81ae1be8 0000000d f7b5ab60
Argus!RegistryCallback+0xa3d
[c:\starteam\research\argus\registry_drv\registry.c @ 737]
f7b5a9d0 8060bee4 0000000d f7b5ab60 e1beead0 nt!CmpCallCallBacks+0x50
f7b5aba0 805676b5 0005d140 00000000 8195d270 nt!CmpParseKey+0x6fa
f7b5ac28 8056749a 00000058 f7b5ac68 00000040
nt!ObpLookupObjectName+0x119
f7b5ac7c 80567dfd 00000000 81bc5980 00000001 nt!ObOpenObjectByName+0xeb
f7b5ad50 804de7ec 00dffc54 00000001 00dff96c nt!NtOpenKey+0x1af
f7b5ad50 7c90eb94 00dffc54 00000001 00dff96c nt!KiFastCallEntry+0xf8
00dff948 7c90dd48 77dd6a13 00dffc54 00000001 ntdll!KiFastSystemCallRet
00dff94c 77dd6a13 00dffc54 00000001 00dff96c ntdll!ZwOpenKey+0xc
00dff9ac 77dd6b5e 00000058 00dff9d4 00000000
ADVAPI32!LocalBaseRegOpenKey+0xe4
00dff9e0 77f6412c 80000001 7c9c89b8 00000000
ADVAPI32!RegOpenKeyExW+0x10d
00dffc1c 77f64544 80000001 7c9c89b8 00000000
SHLWAPI!RegOpenKeyExWrapW+0x67
00dffd60 77f645a8 80000001 7c9c89b8 7c9c88c8 SHLWAPI!SHRegGetValueW+0xe5
00dffd84 7ca017b7 80000001 7c9c89b8 7c9c88c8 SHLWAPI!SHGetValueW+0x21
00dffdac 0102160e 000db970 00dffdd0 000eb070
SHELL32!CStartMenuPin::GetChangeCount+0x2d
00dffde0 01021647 000eaf28 010217b6 00000409
Explorer!ByUsage::_FillPinnedItemsCache+0x2b
00dffde8 010217b6 00000409 0001008e 00dffe0c
Explorer!ByUsage::PrePopulate+0xa
00dffdf8 01021897 00000000 00dffe74 01004a5c
Explorer!SFTBarHost::_EnumerateContents+0x7e
00dffe0c 7e418734 0001008e 00000409 00000000
Explorer!SFTBarHost::_WndProc+0x2ea
00dffe38 7e418816 01004a5c 0001008e 00000409
USER32!InternalCallWinProc+0x28
00dffea0 7e4189cd 0009fa60 01004a5c 0001008e
USER32!UserCallWinProcCheckWow+0x150
00dfff00 7e418a10 00dfff28 00000000 00dfff44
USER32!DispatchMessageWorker+0x306
00dfff10 01001a35 00dfff28 00000000 010460d8 USER32!DispatchMessageW+0xf
00dfff44 01011e8b 00000000 00dfffb4 77f7429a
Explorer!CTray::_MessageLoop+0xd9
00dfff50 77f7429a 010460d8 0000005c 0007fc04
Explorer!CTray::MainThreadProc+0x29
00dfffb4 7c80b683 00000000 0000005c 0007fc04
SHLWAPI!WrapperThreadProc+0x94
00dfffec 00000000 77f7422b 0007fdbc 00000000
kernel32!BaseThreadStart+0x37
STACK_COMMAND: kb
FOLLOWUP_IP:
Argus!QueryObjectFullPath+4d [c:\starteam\research\argus\util\util.c @
1310]
f77cc8ad 8945dc mov dword ptr [ebp-24h],eax
FAULTING_SOURCE_CODE:
1306: NTSTATUS status;
1307:
1308: if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
1309:
1310: status = ObQueryNameString(object,
(POBJECT_NAME_INFORMATION) buf, 24, &returnLength );
1311:
1312: if ( (status == STATUS_INFO_LENGTH_MISMATCH) &&
(returnLength > 0)) {
1313:
1314: buffer = (char *) ExAllocatePoolWithTag(PagedPool,
returnLength, ‘PAGE’);
1315:
SYMBOL_STACK_INDEX: 8
SYMBOL_NAME: Argus!QueryObjectFullPath+4d
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: Argus
IMAGE_NAME: Argus.sys
DEBUG_FLR_IMAGE_TIMESTAMP: 46321282
FAILURE_BUCKET_ID: 0x50_CODE_AV_BAD_IP_Argus!QueryObjectFullPath+4d
BUCKET_ID: 0x50_CODE_AV_BAD_IP_Argus!QueryObjectFullPath+4d
Followup: MachineOwner
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Thursday, April 26, 2007 9:26 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ObQueryNameString on registry object
// This is where the exception and PAGE_FAULT occurs
status = ObQueryNameString(object, (
POBJECT_NAME_INFORMATION) NULL, 0, &returnLength );
You pass NULL pointer as POBJECT_NAME_INFORMATION, i.e. pointer to a
structure that into which data is supposed to be copied. What else,
apart from the exception, would you expect here???
It does not matter that you request 0 bytes to be returned - a pointer
still has to be valid.
Here is one more “masterpiece”:
if ( (status == STATUS_INFO_LENGTH_MISMATCH) && (returnLength >
0)) {
buffer = (char *)
ExAllocatePoolWithTag(PagedPool,
returnLength * sizeof(WCHAR),
‘PAGE’);
info = (POBJECT_NAME_INFORMATION) buffer;
// This is where PAGE_FAULT occurs
if (ObQueryNameString(object,
info,
returnLength,
&returnLength) ==
STATUS_INFO_LENGTH_MISMATCH) {
return NULL;
}
Look at the declaration:
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
Therefore, you have to do something like
OBJECT_NAME_INFORMATION info;
info.Name. Buffer=ExAllocatePool(PagedPool, size);
info.Name. Length=info.Name. MaximumLength=size;
At this point you can pass ‘info’ to ObQueryNameString().
Instead of doing things this way, you just allocate a buffer, and pass
it to ObQueryNameString().
How is ObQueryNameString() supposed to interpretate it???
In other words, your code is just full of bugs. To be honest, I don’t
see the reason why someone should ask questions like that in the NG -
after all, more or less competent programmer should be able to detect so
obvious bugs without any assistance…
Anton Bassov
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer