Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

Подписываем
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Предоплата всего
Подписываем
Федеральное агентство по образованию
Государственное образовательное учреждение
высшего профессионального образования
«Омский государственный технический университет»
Курсовая работа
по дисциплине «Организация и функционирование ОС»
на тему «Разработка программы выдачи дерева системных объектов ОС Windows»
Проверил:
Флоренсов А.Н.
_________________
(дата, подпись)
Выполнил:
студент гр. ИВМ-518
Полтавец А.В.
_________________
(дата, подпись)
Омск 2009
Оглавление[1] 1. Задание [2] 2. Дерево системных объектов Windows NT [2.1] 2.1 Символические связи [2.2] 2.2 Объекты "события", "мутанты" и "семафоры" [3] 3. Интерфейс программы [4] 4. Листинг программы [5] Список литературы |
Разработать программу, позволяющую выдавать информацию о дереве системных объектов ОС Windows. Требуется использовать Native API. (Функции библиотеки NTDLL.DLL). Минимальная информация заключается в именах объектов. Детальная информация об отдельных объектах этого дерева выдается только для тех, которые имеют состояния signaled и числовые значения внутреннего счетчика. (Это объекты типа Event, Semaphore, Mutex и т.п.).
Как известно, в Windows NT каждый разделяемый ресурс процесс, файл, память, представлен как объект. Объект является экземпляром некоторого типа данных, определенного в системе. Этот тип объекта (object type) описывает атрибуты объекта и операции, которые возможны над экземплярами этого типа. Для каждого типа объекта определены операции создания нового экземпляра (Create), получения доступа к существующему экземпляру (Open) и запроса информации об экземпляре (Query).
Созданием, удалением, защитой и отслеживанием состояния объектов занимается диспетчер объектов, который организует все объекты в иерархию в виде дерева. Доступ к каждому объекту может быть получен через задание его имени в иерархии. Например, накопитель на гибких дисках имеет полное имя объекта \Device\Floppy0, которое говорит о том, что объект Floppy0 находится в подкаталоге Device корневого каталога иерархии объектов. Обратная косая черта (\) является одновременно и обозначением корня дерева, и разделителем имен в полном пути.
Каждый каталог объектов представляет собой тоже объект типа DirectoryObject. Единственное, на что способен этот объект, это хранение имен и типов других объектов.
Функция NtOpenDirectoryObject. как нетрудно догадаться из названия, служит для открытия существующего каталога дерева объектов. Как и все другие функции Open, она имеет первым параметром адрес, по которому будет записан возвращенный системой описатель объекта: два других параметра это запрашиваемый доступ и адрес структуры OBJECT_ATTRIBUTES, описывающей объект. Функция аналогична по типам и количеству параметров функции создания дерева объектов ZwCreateDirectoryObject, описанной в DDK. Возвращаемое значение имеет тип NTSTATUS и представляет собой системный код ошибки, произошедшей при выполнении функции.
Структура OBJECT_ATTRIBUTES описывает создаваемый или открываемый объект и включает в себя следующие поля:
Функция NtQueryDirectoryObject предназначена для получения, информации об объекте типа Directory. Единственный класс информации, который можно получить из этого объекта это тип и имя каждого объекта, входящего в каталог. Первый параметр описатель соответствующего объекта (также, как и во всех других функциях Query), второй адрес буфера для результата, третий длина буфера, пятый признак первого запроса, шестой возвращаемый индекс объекта, седьмой возвращаемая длина информации, записанной в буфер. Анализируя содержимое буфера, можно определить, что там находятся две структуры UNICODE_STRING, первая из которых описывает имя объекта, а вторая его тип (например, SymbolicLink). Эти две строки я объединил в одну структуру:
typedef struct _OBJECT_NAMETYPE_INFO {
UNICODE_STRING ObjectName;
UNICODE_STRING ObjectType;
} OBJECT_NAMETYPE_INFO, “POBJECT_NAMEЕYPE_INFO;
Символическая связь (SymbolicLink), единственная задача этого объекта хранение строки, как правило с полным именем какого-либо объекта. Хранимое в объекте полное имя может само оказаться символической связью.
NTSTATUS NtOpenSymbolicLinkObject {
OUT PHANDLE ObjectHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT ATTRIBUTES ObjectAttributes
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
NTSTATUS NtQuerySymbolicLinkObject {
IN HANDLE Obj ectHandle,
OUT POBJECT_NAME_INFORMATION SubstituteString,
OUT PULONG SubstituteStringLength;
}
События, мутанты(мутексы) и семафоры используются для синхронизации процессов и потоков.
Работа с событиями:
NTSTATUS NtOpenEvent {
OUT PHANDLE EventHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
}
NTSTATUS NtQueryEvent {
IN HANDLE EventHandle,
IN EVENT_INFORMATION_CLASS EventlnformationCiass,
OUT PVOID Eventlnformation,
IN ULONG EventlnformationLength,
OUT PULONG LengthReturned
}
typedef enum _EVENT_TYPE {
NotificationEvent,
SynchronizationEvent
} EVENT_TYPE;
typedef struct _EVENT_BASIC_INFORMATION {
EVENT_TYPE EventType;
BOOLEAN Signaled;
} EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION;
typedef enum _EVENT_INFORMATION_CLASS {
EventBasicInformation
} EVENT_INFORMATION_CLASS;
Работа с мутантами:
NTSTATUS NtOpenMutant {
OUT PHANDLE MutantHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
}
NTSTATUS NtQueryMutant {
IN HANDLE MutantHandle,
IN MUTANT_INFORMATION_CLASS MutantlnformationClass ,
OUT PVOID Mutantlnformation,
IN ULONG MutantInformationLength,
PULONG LengthReturned
}
typedef enum _MUTANT_INFORMATION_CLASS {
MutantBasicInformation
} MUTANT_INFORMATION_CLASS, *PMUTANT_INFORMATION_CLASS;
typedef struct _MUTANT_BASIC_INFORMATION {
LONG CurrentCount;
BOOLEAN OwnedByCaller;
BOOLEAN AbandonedState;
} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;
Работа с семафорами:
NTSTATUS NtOpenSemaphore {
OUT PHANDLE SemaphoreHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
}
NTSTATUS NtQuerySemaphore {
IN HANDLE SemaphoreHandle,
IN SEMAPHORE_BASIC_INFORMATION SemaphorelnformationClass ,
OUT PVOID Semaphorelnformation,
IN ULONG SemaphorelnformationLength,
OUT POLONG LengthReturned
}
typedef struct _SEMAPHORE_BASIC_INFORMATION {
ULONG CurrentCount;
ULONG MaximumCount;
} SEMAPHORE_BASIC_INFORMATION, *PSEMAPHORE_BASIC_INFORMATION;
typedef enum _SEMAPHORE_INFORMATION_CLASS {
SemaphoreBasicInformation
} SEMAPHORE_INFORMATION_CLASS, *PSEMAPHORE_INFORMATION_CLASS;
На рисунке 1 изображено главное окно разработанной программы.
Рис. 1 Главное окно разработанной программы
Верхняя панель состоит из адресной строки, кнопки «Перейти» и кнопки «Домой». В адресной строке можно ввести адрес директории системных объектов. При нажатии на кнопку «Перейти» происходит переход по введённому адресу. При нажатии на кнопку «Домой» происходит переход в корневую директорию «\».
В центре основного окна программы расположен ListBox, который отображает список объектов текущей директории. В квадратных скобках отображается тип объекта.
В нижней части главного окна расположена строка состояния. В левой части строки выводится название текущей директории. Посередине выводятся свойства выбранного объекта. Справа выводится количество объектов в директории.
Класс NTDLLConnector импортирует функции из библиотеки NTDLL.DLL и предоставляет удобный интерфейс для их использования.
NTDLLConnector.h
#pragma once
#include "Stdafx.h"
using namespace System;
using namespace System::Runtime::InteropServices;
ref class NTDLLConnector
{
private:
HINSTANCE hinstLib;
System::String ^strPath;
UNICODE_STRING ObjectStringToUNICODE_STRING(System::String ^strNewPath);
protected:
~NTDLLConnector();
public:
NTDLLConnector(void);
System::Collections::Generic::List<SystemObject^> ^GetObjectList(System::String ^strNewPath);
System::String ^GetSymbolicLinkInfo(System::String ^objectFullName);
System::String ^GetEventInfo(System::String ^objectFullName);
System::String ^GetSemaphoreInfo(System::String ^objectFullName);
System::String ^GetMutantInfo(System::String ^objectFullName);
property System::String ^StrPath
{
System::String^ get()
{
return strPath;
}
}
};
NTDLLConnector.cpp
#include "NTDLLConnector.h"
#include "Stdafx.h"
NTDLLConnector::NTDLLConnector(void)
{
// Загружаем библиотеку NTDLL.DLL
hinstLib = LoadLibrary(TEXT("NTDLL.DLL"));
}
NTDLLConnector::~NTDLLConnector()
{
// Вынружаем библиотеку NTDLL.DLL
BOOL fFreeResult = FreeLibrary(hinstLib);
}
// Преобразуем объект строку из .Net Framework в UNICODE_STRING
UNICODE_STRING NTDLLConnector::ObjectStringToUNICODE_STRING(System::String ^strNewPath)
{
UNICODE_STRING unicodString;
System::IntPtr ^piName = Marshal::StringToHGlobalUni(strNewPath);
PWSTR pName = (PWSTR)piName->ToPointer();
unicodString.Buffer = pName;;
Marshal::FreeBSTR(*piName);
unicodString.Length = strNewPath->Length * 2;
unicodString.MaximumLength = strNewPath->Length * 2 + 2;
return unicodString;
}
// Метод, возвращающий список объектов, расположенных по заданному адресу
System::Collections::Generic::List<SystemObject^> ^NTDLLConnector::GetObjectList(System::String ^strNewPath)
{
strPath = strNewPath;
// Импортируем функции из библиотеки NTDLL.DLL
myNtOpenSomethingObject NtOpenDirectoryObject = (myNtOpenSomethingObject)GetProcAddress(hinstLib, "NtOpenDirectoryObject");
myNtQueryDirectoryObject NtQueryDirectoryObject = (myNtQueryDirectoryObject)GetProcAddress(hinstLib, "NtQueryDirectoryObject");
HANDLE handle;
UNICODE_STRING unicodString;
unicodString = ObjectStringToUNICODE_STRING(strNewPath);
OBJECT_ATTRIBUTES objectAttributes;
memset(&objectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
objectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
objectAttributes.ObjectName = &unicodString;
objectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
System::Collections::Generic::List<SystemObject^>^ systemObjects = gcnew System::Collections::Generic::List<SystemObject^>();
// Открываем директорию
if (NtOpenDirectoryObject(&handle, DIRECTORY_QUERY, &objectAttributes) == 0)
{
UNICODE_STRING* pinf;
BOOLEAN first = TRUE;
wchar_t buffer[512];
ULONG index;
ULONG actlen;
index = 0;
// Запрашиваем все элементы из директории
while(NtQueryDirectoryObject(handle, buffer, 512, 1, first, &index, &actlen) == 0)
{
pinf = (UNICODE_STRING*)buffer;
first = FALSE;
System::String ^strName = gcnew System::String(pinf[0].Buffer);
System::String ^strType = gcnew System::String(pinf[1].Buffer);
systemObjects->Add(gcnew SystemObject(strName, strType));
}
}
return systemObjects;
}
// Метод, возвращающий информацию об объекте SymbolicLink
System::String ^NTDLLConnector::GetSymbolicLinkInfo(System::String ^objectFullName)
{
// Импортируем функции из библиотеки NTDLL.DLL
myNtOpenSomethingObject NtOpenSymbolicLinkObject = (myNtOpenSomethingObject)GetProcAddress(hinstLib, "NtOpenSymbolicLinkObject");
myNtQuerySymbolicLinkObject NtQuerySymbolicLinkObject = (myNtQuerySymbolicLinkObject)GetProcAddress(hinstLib, "NtQuerySymbolicLinkObject");
HANDLE symbolicLinkHandle;
NTSTATUS ntStatus;
char queryDirectoryBuf[QUERY_DIRECTORY_BUF_SIZE];
UNICODE_STRING unicodString;
unicodString = ObjectStringToUNICODE_STRING(objectFullName);
OBJECT_ATTRIBUTES objectAttributes;
memset(&objectAttributes, 0, sizeof(objectAttributes));
objectAttributes.Length = sizeof(objectAttributes);
objectAttributes.ObjectName = &unicodString;
objectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
// Открываем объект SymbolicLink
ntStatus = NtOpenSymbolicLinkObject(&symbolicLinkHandle, SYMBOLIC_LINK_QUERY, &objectAttributes);
if(ntStatus != 0)
{
return "NtOpenSymbolicLinkObject error " + ntStatus.ToString();
}
UNICODE_STRING objectNameInformation;
memset(&objectNameInformation, 0, sizeof(objectNameInformation));
objectNameInformation.Buffer = (PWSTR)queryDirectoryBuf;
objectNameInformation.Length = 0;
objectNameInformation.MaximumLength = sizeof(queryDirectoryBuf);
ULONG length = 0;
memset(queryDirectoryBuf, 0, QUERY_DIRECTORY_BUF_SIZE);
// Получаем информацию об объекте SymbolicLink
ntStatus = NtQuerySymbolicLinkObject(symbolicLinkHandle, &objectNameInformation, &length);
if(ntStatus != 0)
{
return "NtQuerySymbolicLinkObject error " + ntStatus.ToString();
}
System::String ^result = gcnew System::String(objectNameInformation.Buffer);
return result;
}
// Метод, возвращающий информацию об объекте Event
System::String ^NTDLLConnector::GetEventInfo(System::String ^objectFullName)
{
// Импортируем функции из библиотеки NTDLL.DLL
myNtOpenSomethingObject NtOpenEvent = (myNtOpenSomethingObject)GetProcAddress(hinstLib, "NtOpenEvent");
myNtQueryEvent NtQueryEvent = (myNtQueryEvent)GetProcAddress(hinstLib, "NtQueryEvent");
HANDLE eventHandle;
UNICODE_STRING unicodString;
unicodString = ObjectStringToUNICODE_STRING(objectFullName);
OBJECT_ATTRIBUTES objectAttributes;
memset(&objectAttributes, 0, sizeof(objectAttributes));
objectAttributes.Length = sizeof(objectAttributes);
objectAttributes.ObjectName = &unicodString;
objectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
// Открываем объект Event
NTSTATUS ntStatus = NtOpenEvent(&eventHandle, EVENT_QUERY, &objectAttributes);
if(ntStatus != 0)
{
return "NtOpenEvent error " + ntStatus.ToString();
}
EVENT_BASIC_INFORMATION eventBasicInformation;
memset(&eventBasicInformation, 0, sizeof(eventBasicInformation));
ULONG returnLength = 0;
// Получаем информацию об объекте Event
ntStatus = NtQueryEvent(eventHandle, EventBasicInformation, &eventBasicInformation, sizeof(eventBasicInformation), &returnLength);
if(ntStatus != 0)
{
return "NtQueryEvent error " + ntStatus.ToString();
}
return gcnew System::String(eventBasicInformation.EventType == SynchronizationEvent ? "autoreset" : "manualreset") + " " + gcnew System::String(eventBasicInformation.Signaled ? "signaled" : "non-signaled");
}
// Метод, возвращающий информацию об объекте Semaphore
System::String ^NTDLLConnector::GetSemaphoreInfo(System::String ^objectFullName)
{
// Импортируем функции из библиотеки NTDLL.DLL
myNtOpenSomethingObject NtOpenSemaphore = (myNtOpenSomethingObject)GetProcAddress(hinstLib, "NtOpenSemaphore");
myNtQuerySemaphore NtQuerySemaphore = (myNtQuerySemaphore)GetProcAddress(hinstLib, "NtQuerySemaphore");
HANDLE semaphoreHandle;
NTSTATUS ntStatus;
UNICODE_STRING unicodString;
unicodString = ObjectStringToUNICODE_STRING(objectFullName);
OBJECT_ATTRIBUTES objectAttributes;
memset(&objectAttributes, 0, sizeof(objectAttributes));
objectAttributes.Length = sizeof(objectAttributes);
objectAttributes.ObjectName = &unicodString;
objectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
// Открываем объект Semaphore
ntStatus = NtOpenSemaphore(&semaphoreHandle, SEMAPHORE_QUERY, &objectAttributes);
if(ntStatus != 0)
{
return "NtOpenSemaphore error " + ntStatus.ToString();
}
ULONG returnLength = 0;
SEMAPHORE_BASIC_INFORMATION sbi;
memset(&sbi, 0, sizeof(sbi));
// Получаем информацию об объекте Semaphore
ntStatus = NtQuerySemaphore(semaphoreHandle, SemaphoreBasicInformation, &sbi, sizeof(sbi), &returnLength);
if(ntStatus != 0)
{
return "NtQuerySemaphore error " + ntStatus.ToString();
}
System::String ^result = sbi.CurrentCount.ToString() + "/" + sbi.MaximumCount.ToString();
return result;
}
// Метод, возвращающий информацию об объекте Mutant
System::String ^NTDLLConnector::GetMutantInfo(System::String ^objectFullName)
{
// Импортируем функции из библиотеки NTDLL.DLL
myNtOpenSomethingObject NtOpenMutant = (myNtOpenSomethingObject)GetProcAddress(hinstLib, "NtOpenMutant");
myNtQueryMutant NtQueryMutant = (myNtQueryMutant)GetProcAddress(hinstLib, "NtQueryMutant");
HANDLE mutantHandle;
NTSTATUS ntStatus;
UNICODE_STRING unicodString;
unicodString = ObjectStringToUNICODE_STRING(objectFullName);
OBJECT_ATTRIBUTES objectAttributes;
memset(&objectAttributes, 0, sizeof(objectAttributes));
objectAttributes.Length = sizeof(objectAttributes);
objectAttributes.ObjectName = &unicodString;
objectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
// Открываем объект Mutant
ntStatus = NtOpenMutant(&mutantHandle, MUTANT_QUERY, &objectAttributes);
if(ntStatus != 0)
{
return "NtOpenMutant error " + ntStatus.ToString();
}
ULONG returnLength = 0;
MUTANT_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof(mbi));
// Получаем информацию об объекте Mutant
ntStatus = NtQueryMutant(mutantHandle, MutantBasicInformation, &mbi, sizeof(mbi), &returnLength);
if(ntStatus != 0)
{
return "NtQueryMutant error " + ntStatus.ToString();
}
System::String ^result = gcnew System::String(mbi.AbandonedState ? "[Abandoned: true" : "[Abandoned: false") + " " +
gcnew System::String(mbi.OwnedByCaller ? "Owned: true" : "Owned: false") + " " +
"Count: " + (1 - mbi.CurrentCount).ToString() + "]";
return result;
}