windows-nt/Source/XPSP1/NT/sdktools/winobj/object.c
2020-09-26 16:20:57 +08:00

673 lines
20 KiB
C

/* object.c -
*
* Handles display of object attributes
*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stdio.h>
#include "winfile.h"
#include "object.h"
INT_PTR APIENTRY ObjectAttributesDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL ObjectInformationDlgInit(HWND, LPSTR);
HANDLE OpenObject(HWND, LPSTR);
BOOL GetObjectInfo(HWND, HANDLE);
VOID CloseObject(HANDLE);
VOID StripObjectPath(LPSTR lpszPath);
VOID StripObjectSpec(LPSTR lpszPath);
// Define known object type names
#define DIRECTORYTYPE L"Directory"
#define SYMLINKTYPE L"SymbolicLink"
#define ADAPTERTYPE L"Adapter"
#define CONTROLLERTYPE L"Controller"
#define DEVICETYPE L"Device"
#define DRIVERTYPE L"Driver"
#define EVENTTYPE L"Event"
#define EVENTPAIRTYPE L"EventPair"
#define FILETYPE L"File"
#define MUTANTTYPE L"Mutant"
#define PORTTYPE L"Port"
#define PROFILETYPE L"Profile"
#define SECTIONTYPE L"Section"
#define SEMAPHORETYPE L"Semaphore"
#define TIMERTYPE L"Timer"
#define TYPETYPE L"Type"
#define PROCESSTYPE L"Process"
VOID
DisplayObjectInformation(
HWND hwndParent,
LPSTR lpstrObject
)
{
WNDPROC lpProc;
HANDLE hInst = hAppInstance;
DialogBoxParam(hInst,(LPSTR)IDD_OBJATTRS, hwndParent, ObjectAttributesDlgProc, (LPARAM)lpstrObject);
}
INT_PTR
APIENTRY
ObjectAttributesDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
switch (message) {
case WM_INITDIALOG:
if (!ObjectInformationDlgInit(hDlg, (HANDLE)lParam)) {
// Failed to initialize dialog, get out
EndDialog(hDlg, FALSE);
}
return (TRUE);
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
// we're done, drop through to quit dialog....
case IDCANCEL:
//MainDlgEnd(hDlg, LOWORD(wParam) == IDOK);
EndDialog(hDlg, TRUE);
return TRUE;
break;
default:
// We didn't process this message
return FALSE;
break;
}
break;
default:
// We didn't process this message
return FALSE;
}
// We processed the message
return TRUE;
}
BOOL
ObjectInformationDlgInit(
HWND hwnd,
LPSTR lpstrObject
)
{
HANDLE ObjectHandle;
BOOL Result;
ObjectHandle = OpenObject(hwnd, lpstrObject);
if (ObjectHandle == NULL) {
return(FALSE);
}
Result = GetObjectInfo(hwnd, ObjectHandle);
CloseObject(ObjectHandle);
return(Result);
}
/* Open the object given only its name.
* First find the object type by enumerating the directory entries.
* Then call the type-specific open routine to get a handle
*/
HANDLE
OpenObject(
HWND hwnd,
LPSTR lpstrObject
)
{
#define BUFFER_SIZE 1024
NTSTATUS Status;
HANDLE DirectoryHandle;
ULONG Context = 0;
ULONG ReturnedLength;
CHAR Buffer[BUFFER_SIZE];
ANSI_STRING AnsiString;
POBJECT_DIRECTORY_INFORMATION DirInfo;
WCHAR ObjectNameBuf[MAX_PATH];
UNICODE_STRING ObjectName;
WCHAR ObjectTypeBuf[MAX_PATH];
UNICODE_STRING ObjectType;
HANDLE ObjectHandle;
OBJECT_ATTRIBUTES Attributes;
UNICODE_STRING DirectoryName;
IO_STATUS_BLOCK IOStatusBlock;
//DbgPrint("Open object: raw full name = <%s>\n", lpstrObject);
// Remove drive letter
while ((*lpstrObject != 0) && (*lpstrObject != '\\')) {
lpstrObject ++;
}
//DbgPrint("Open object: full name = <%s>\n", lpstrObject);
// Initialize the object type buffer
ObjectType.Buffer = ObjectTypeBuf;
ObjectType.MaximumLength = sizeof(ObjectTypeBuf);
// Initialize the object name string
strcpy(Buffer, lpstrObject);
StripObjectPath(Buffer);
RtlInitAnsiString(&AnsiString, Buffer);
ObjectName.Buffer = ObjectNameBuf;
ObjectName.MaximumLength = sizeof(ObjectNameBuf);
Status = RtlAnsiStringToUnicodeString(&ObjectName, &AnsiString, FALSE);
ASSERT(NT_SUCCESS(Status));
//DbgPrint("Open object: name only = <%wZ>\n", &ObjectName);
//
// Open the directory for list directory access
//
strcpy(Buffer, lpstrObject);
StripObjectSpec(Buffer);
RtlInitAnsiString(&AnsiString, Buffer);
Status = RtlAnsiStringToUnicodeString( &DirectoryName, &AnsiString, TRUE);
ASSERT(NT_SUCCESS(Status));
InitializeObjectAttributes( &Attributes,
&DirectoryName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
//DbgPrint("Open object: dir only = <%wZ>\n", &DirectoryName);
if (!NT_SUCCESS( Status = NtOpenDirectoryObject( &DirectoryHandle,
STANDARD_RIGHTS_READ |
DIRECTORY_QUERY |
DIRECTORY_TRAVERSE,
&Attributes ) )) {
if (Status == STATUS_OBJECT_TYPE_MISMATCH) {
DbgPrint( "%wZ is not a valid Object Directory Object name\n",
&DirectoryName );
} else {
DbgPrint("OpenObject: failed to open directory, status = 0x%lx\n\r", Status);
}
RtlFreeUnicodeString(&DirectoryName);
MessageBox(hwnd, "Unable to open object", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
return NULL;
}
RtlFreeUnicodeString(&DirectoryName);
//
// Query the entire directory in one sweep
//
ObjectType.Length = 0;
for (Status = NtQueryDirectoryObject( DirectoryHandle,
Buffer,
sizeof(Buffer),
// LATER FALSE,
TRUE, // one entry at a time for now
TRUE,
&Context,
&ReturnedLength );
ObjectType.Length == 0;
Status = NtQueryDirectoryObject( DirectoryHandle,
Buffer,
sizeof(Buffer),
// LATER FALSE,
TRUE, // one entry at a time for now
FALSE,
&Context,
&ReturnedLength ) ) {
//
// Check the status of the operation.
//
if (!NT_SUCCESS( Status )) {
if (Status != STATUS_NO_MORE_ENTRIES) {
DbgPrint("OpenObject: failed to query directory object, status = 0x%lx\n\r", Status);
}
break;
}
//
// For every record in the buffer compare name with the one we're
// looking for
//
//
// Point to the first record in the buffer, we are guaranteed to have
// one otherwise Status would have been No More Files
//
DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
while (DirInfo->Name.Length != 0) {
//
// Compare with object we're searching for
//
//DbgPrint("Found object <%wZ>\n", &(DirInfo->Name));
if (RtlEqualString((PSTRING)&ObjectName, (PSTRING)&(DirInfo->Name), TRUE)) {
RtlCopyString((PSTRING)&ObjectType, (PSTRING)&DirInfo->TypeName);
break;
}
//
// Advance DirInfo to the next entry
//
DirInfo ++;
}
}
if (ObjectType.Length == 0) {
DbgPrint("Object not found in directory\n\r");
MessageBox(hwnd, "Unable to open object", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
return(NULL);
}
// We now have the type of the object in ObjectType
// We still have the full object name in lpstrObject
// Use the appropriate open routine to get a handle
ObjectHandle = NULL;
RtlInitString(&AnsiString, lpstrObject);
Status = RtlAnsiStringToUnicodeString(&ObjectName, &AnsiString, TRUE);
ASSERT(NT_SUCCESS(Status));
InitializeObjectAttributes(&Attributes,
&ObjectName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
switch (CalcAttributes(&ObjectType)) {
case ATTR_SYMLINK:
Status = NtOpenSymbolicLinkObject(&ObjectHandle,
READ_CONTROL | SYMBOLIC_LINK_QUERY,
&Attributes);
break;
case ATTR_EVENT:
Status = NtOpenEvent(&ObjectHandle,
READ_CONTROL,
&Attributes);
break;
case ATTR_EVENTPAIR:
Status = NtOpenEventPair(&ObjectHandle,
READ_CONTROL,
&Attributes);
break;
case ATTR_FILE:
Status = NtOpenFile(&ObjectHandle,
READ_CONTROL,
&Attributes,
&IOStatusBlock,
FILE_SHARE_VALID_FLAGS,
0);
break;
case ATTR_MUTANT:
Status = NtOpenMutant(&ObjectHandle,
READ_CONTROL,
&Attributes);
break;
case ATTR_SECTION:
Status = NtOpenSection(&ObjectHandle,
READ_CONTROL,
&Attributes);
break;
case ATTR_SEMAPHORE:
Status = NtOpenSemaphore(&ObjectHandle,
READ_CONTROL,
&Attributes);
break;
case ATTR_TIMER:
Status = NtOpenTimer(&ObjectHandle,
READ_CONTROL,
&Attributes);
break;
case ATTR_PROCESS:
Status = NtOpenProcess(&ObjectHandle,
READ_CONTROL,
&Attributes,
NULL);
break;
default:
DbgPrint("No open routine for this object type\n\r");
MessageBox(hwnd, "I don't know how to open an object of this type", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
Status = 0;
break;
}
if (!NT_SUCCESS(Status)) {
DbgPrint("Type specific open failed, status = 0x%lx\n\r", Status);
MessageBox(hwnd, "Object open failed", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
ObjectHandle = NULL;
}
RtlFreeUnicodeString(&ObjectName);
return(ObjectHandle);
}
VOID
CloseObject(
HANDLE ObjectHandle
)
{
NtClose(ObjectHandle);
}
BOOL
GetObjectInfo(
HWND hwnd,
HANDLE ObjectHandle
)
{
NTSTATUS Status;
OBJECT_BASIC_INFORMATION BasicInfo;
OBJECT_TYPE_INFORMATION TypeInfo;
WCHAR TypeName[ 64 ];
#define BUFFER_SIZE 1024
CHAR Buffer[BUFFER_SIZE];
STRING String;
TIME_FIELDS TimeFields;
WCHAR UnicodeBuffer[BUFFER_SIZE];
UNICODE_STRING UnicodeString;
//
// Name
//
Status = NtQueryObject(ObjectHandle, ObjectNameInformation,
(PVOID)Buffer, sizeof(Buffer), NULL);
if (!NT_SUCCESS(Status)) {
DbgPrint("GetObjectInfo: Failed to get name info, status = 0x%lx\n\r", Status);
return(FALSE);
}
Status = RtlUnicodeStringToAnsiString(&String, &(((POBJECT_NAME_INFORMATION)Buffer)->Name), TRUE);
ASSERT(NT_SUCCESS(Status));
SetDlgItemText(hwnd, IDS_NAME, String.Buffer);
RtlFreeAnsiString(&String);
//
// Type
//
Status = NtQueryObject(ObjectHandle, ObjectTypeInformation,
(PVOID)Buffer, sizeof(Buffer), NULL);
if (!NT_SUCCESS(Status)) {
DbgPrint("GetObjectInfo: Failed to get type info, status = 0x%lx\n\r", Status);
return(FALSE);
}
Status = RtlUnicodeStringToAnsiString(&String, &(((POBJECT_TYPE_INFORMATION)Buffer)->TypeName), TRUE);
ASSERT(NT_SUCCESS(Status));
SetDlgItemText(hwnd, IDS_TYPE, String.Buffer);
RtlFreeAnsiString(&String);
//
// Symbolic link target if this is a symlink
//
RtlInitUnicodeString(&UnicodeString, SYMLINKTYPE);
if (RtlEqualString((PSTRING)&UnicodeString,
(PSTRING)&(((POBJECT_TYPE_INFORMATION)Buffer)->TypeName), TRUE)) {
ShowWindow(GetDlgItem(hwnd, IDS_OTHERLABEL), SW_SHOWNOACTIVATE);
ShowWindow(GetDlgItem(hwnd, IDS_OTHERTEXT), SW_SHOWNOACTIVATE);
UnicodeString.Buffer = UnicodeBuffer;
UnicodeString.MaximumLength = sizeof(UnicodeBuffer);
Status = NtQuerySymbolicLinkObject(ObjectHandle, &UnicodeString, NULL);
if (!NT_SUCCESS(Status)) {
DbgPrint("GetObjectInfo: Failed to query symbolic link target, status = 0x%lx\n\r", Status);
return(FALSE);
}
RtlUnicodeStringToAnsiString(&String, &UnicodeString, TRUE);
SetDlgItemText(hwnd, IDS_OTHERTEXT, String.Buffer);
RtlFreeAnsiString(&String);
}
//
// Basic info
//
Status = NtQueryObject(ObjectHandle, ObjectBasicInformation,
(PVOID)&BasicInfo, sizeof(BasicInfo), NULL);
if (!NT_SUCCESS(Status)) {
DbgPrint("GetObjectInfo: Failed to get basic info, status = 0x%lx\n\r", Status);
return(FALSE);
}
TypeInfo.TypeName.Buffer = TypeName;
TypeInfo.TypeName.MaximumLength = sizeof( TypeName );
Status = NtQueryObject(ObjectHandle, ObjectTypeInformation,
(PVOID)&TypeInfo, sizeof(TypeInfo) + TypeInfo.TypeName.MaximumLength, NULL);
if (!NT_SUCCESS(Status)) {
DbgPrint("GetObjectInfo: Failed to get type info, status = 0x%lx\n\r", Status);
return(FALSE);
}
CheckDlgButton(hwnd, IDCB_INHERIT, (BasicInfo.Attributes & OBJ_INHERIT) != 0);
CheckDlgButton(hwnd, IDCB_PERMANENT, (BasicInfo.Attributes & OBJ_PERMANENT) != 0);
CheckDlgButton(hwnd, IDCB_EXCLUSIVE, (BasicInfo.Attributes & OBJ_EXCLUSIVE) != 0);
SetDlgItemInt(hwnd, IDS_PAGEDCHARGE, BasicInfo.PagedPoolCharge, FALSE);
SetDlgItemInt(hwnd, IDS_NONPAGEDCHARGE, BasicInfo.NonPagedPoolCharge, FALSE);
SetDlgItemInt(hwnd, IDS_HANDLES, BasicInfo.HandleCount, FALSE);
SetDlgItemInt(hwnd, IDS_TOTALHANDLES, TypeInfo.TotalNumberOfHandles, FALSE);
SetDlgItemInt(hwnd, IDS_POINTERS, BasicInfo.PointerCount, FALSE);
SetDlgItemInt(hwnd, IDS_TOTALPOINTERS, 0, FALSE);
SetDlgItemInt(hwnd, IDS_COUNT, TypeInfo.TotalNumberOfObjects, FALSE);
RtlTimeToTimeFields(&BasicInfo.CreationTime, &TimeFields);
sprintf(Buffer, "%hd/%hd/%hd @ %02hd:%02hd:%02hd",
TimeFields.Year, TimeFields.Month, TimeFields.Day,
TimeFields.Hour, TimeFields.Minute, TimeFields.Second);
SetDlgItemText(hwnd, IDS_CREATIONTIME, Buffer);
return(TRUE);
}
/* Converts the type-name into an attribute value */
LONG
CalcAttributes(
PUNICODE_STRING Type
)
{
UNICODE_STRING TypeName;
RtlInitUnicodeString(&TypeName, DIRECTORYTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_DIR;
}
RtlInitUnicodeString(&TypeName, SYMLINKTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_SYMLINK;
}
RtlInitUnicodeString(&TypeName, ADAPTERTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_ADAPTER;
}
RtlInitUnicodeString(&TypeName, CONTROLLERTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_CONTROLLER;
}
RtlInitUnicodeString(&TypeName, DEVICETYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_DEVICE;
}
RtlInitUnicodeString(&TypeName, DRIVERTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_DRIVER;
}
RtlInitUnicodeString(&TypeName, EVENTTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_EVENT;
}
RtlInitUnicodeString(&TypeName, EVENTPAIRTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_EVENTPAIR;
}
RtlInitUnicodeString(&TypeName, FILETYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_FILE;
}
RtlInitUnicodeString(&TypeName, MUTANTTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_MUTANT;
}
RtlInitUnicodeString(&TypeName, PORTTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_PORT;
}
RtlInitUnicodeString(&TypeName, PROFILETYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_PROFILE;
}
RtlInitUnicodeString(&TypeName, SECTIONTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_SECTION;
}
RtlInitUnicodeString(&TypeName, SEMAPHORETYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_SEMAPHORE;
}
RtlInitUnicodeString(&TypeName, TIMERTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_TIMER;
}
RtlInitUnicodeString(&TypeName, TYPETYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_TYPE;
}
RtlInitUnicodeString(&TypeName, PROCESSTYPE);
if (RtlEqualString((PSTRING)Type, (PSTRING)&TypeName, TRUE)) {
return ATTR_PROCESS;
}
return(0);
}
/*--------------------------------------------------------------------------*/
/* */
/* StripObjectSpec() - */
/* */
/*--------------------------------------------------------------------------*/
/* Remove the filespec portion from a path (including the backslash). */
VOID
StripObjectSpec(
LPSTR lpszPath
)
{
LPSTR p;
p = lpszPath + lstrlen(lpszPath);
while ((*p != '\\') && (p != lpszPath))
p = AnsiPrev(lpszPath, p);
/* Don't strip backslash from root directory entry. */
if ((p == lpszPath) && (*p == '\\')) {
p++;
}
*p = '\000';
}
/*--------------------------------------------------------------------------*/
/* */
/* StripObjectPath() - */
/* */
/*--------------------------------------------------------------------------*/
/* Extract only the filespec portion from a path. */
VOID
StripObjectPath(
LPSTR lpszPath
)
{
LPSTR p;
p = lpszPath + lstrlen(lpszPath);
while ((*p != '\\') && (p != lpszPath))
p = AnsiPrev(lpszPath, p);
if (*p == '\\')
p++;
if (p != lpszPath)
lstrcpy(lpszPath, p);
}