/* object.c - * * Handles display of object attributes */ #include #include #include #include #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); }