Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Перечисление системных объектных типов [Win2k]


Страницы:   1 2 3

BiN ©   (2006-10-18 16:20:00) 

Как по вашему, возможна ли ситуация, когда NtQueryObject(0, ObjectAllTypesInformation... возвращает не полный список типов

Собственно, кусок действующего кода

procedure TSystemTypeList.Refresh;
var
 Data: POBJECT_ALL_TYPES_INFO;
 TypeInfo: POBJECT_TYPE_INFO;
 dwToRead: DWORD;
 dwRead: DWORD;
 ntRes: NTSTATUS;
 i: Integer;
begin
 Clear;
 Data:=nil;
 try
   dwToRead:=0;
   ntRes:=NtQueryObject(0, ObjectAllTypesInformation, Data, dwToRead, @dwRead);

   while ntRes=STATUS_INFO_LENGTH_MISMATCH do
   begin
     dwToRead:=dwRead;
     ReallocMem(Data, dwToRead);
     ntRes:=NtQueryObject(0, ObjectAllTypesInformation, Data, dwToRead, @dwRead);
   end;
   if not NT_SUCCESS(ntRes) then
     RaiseNtStatusError(ntRes);
   ReallocMem(Data, dwRead);
   TypeInfo:=@(Data^.ObjectsTypeInfo);
   for i:=0 to Data^.NumberOfObjectTypes-1 do
   begin
     Add(TypeInfo);
     TypeInfo:=POBJECT_TYPE_INFO((DWORD(TypeInfo.Name.Buffer)+TypeInfo.Name.Length) and not 3+4);
   end;
 finally
   ReallocMem(Data, 0);
 end;
end;


В результате, в список по пока невыясненным причинам не попадает, например, тип "File". Но при этом вызов NtQueryObject(hTempHandle, ObjectTypeInformation... с хэндлом файла в качестве параметра отрабатывает вполне корректно.


Rouse_   (2006-11-07 14:39:00) [1]

Вполне возможно - пример писался давно и всех тонкостей уже не помню...


BiN   (2006-11-07 13:41:00) [2]


> BiN ©   (07.11.06 13:39) [39]
>
>
> Из-за того, что GetFileType вызывает NtQueryVolumeInformation

пардон, NtQueryVolumeInformation File


BiN   (2006-11-07 13:39:00) [3]


> Riply ©   (07.11.06 13:19) [38]
>
> GetFileType - тоже виснем, но быстрее, проще и безболезненние
> :)

Из-за того, что GetFileType вызывает NtQueryVolumeInformation


Riply   (2006-11-07 13:19:00) [4]

>[34] Rouse_ ©   (06.11.06 19:37)
Мои эксперементы показали, что на NtQueryInformationFile мы виснем также
успешно, как и на NtQueryObject(... ObjectNameInformation, с той только
разницей, что после NtQueryInformationFile убить поток можно, а после
NtQueryObject - не получается. Поэтому перед NtQueryObject я вызываю
GetFileType - тоже виснем, но быстрее, проще и безболезненние :)


BiN   (2006-11-06 20:25:00) [5]

вдогонку к [36]

function NT_SUCCESS(Status: NTSTATUS): BOOL;
begin
 Result := Status >= 0;
end;

procedure RaiseNtStatusError(Status: Integer);
var
 ErrorCode: Integer;
 Error: EOSError;
begin
 ErrorCode := LsaNtStatusToWinError(Status);
 if ErrorCode <> 0 then
   Error := EOSError.CreateResFmt(@SOSError, [ErrorCode,
     SysErrorMessage(ErrorCode)])
 else
   Error := EOSError.CreateRes(@SUnkOSError);
 Error.ErrorCode := ErrorCode;
 raise Error;
end;

procedure NtCheckStatus(Status: NTSTATUS);
begin
 if not NT_SUCCESS(Status) then
   RaiseNtStatusError(Status);
end;


BiN   (2006-11-06 20:22:00) [6]


> вот тут на пайпе будет не STATUS_SUCCESS
>
>    Result := NtQueryInformationFile(pThreadParam.hFile,
> @IoStatusBlock,
>      @FileNameInfo, MAX_PATH * 2, FileNameInformation);
>    if Result = STATUS_SUCCESS then

Ты уверен? Пример ниже демонстрирует, что NtQueryInformationFile вполне дружит с каналами. Или ты имел ввиду только "проблемные" каналы?


procedure TForm1.Button1Click(Sender: TObject);
var
 hPipe: THandle;
 ObjectNameInfo: PFILE_NAME_INFORMATION;
 IoStatusBlock: IO_STATUS_BLOCK;
 dwSize: DWORD;
 S: WideString;
begin
 hPipe:=CreateNamedPipe('\\.\pipe\myextrapipe', PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE,
   1, 0, 0, INFINITE, nil);
 Win32Check(hPipe<>INVALID_HANDLE_VALUE);
 try
   dwSize:=MAX_PATH*SizeOf(WCHAR)+SizeOf(DWORD);

   ObjectNameInfo:=AllocMem(dwSize);
   try
     NtCheckStatus(NtQueryInformationFile(hPipe, @IOStatusBlock, ObjectNameInfo, dwSize, FileNameInformation));
     SetLength(S, ObjectNameInfo^.FileNameLength div SizeOf(WideChar));
     if ObjectNameInfo^.FileNameLength>0 then
       Move(ObjectNameInfo^.FileName[0], S[1], ObjectNameInfo^.FileNameLength);
     Caption:=S;
   finally
     ReallocMem(ObjectNameInfo, 0);
   end;
 finally
   CloseHandle(hPipe);
 end;

end;


Rouse_   (2006-11-06 19:38:00) [7]

а код целиком можешь тут посмотреть: http://forum.sources.ru/index.php?showtopic=152912


Rouse_   (2006-11-06 19:37:00) [8]

:))

NtQueryInformationFile конечно :)
Вот смотри:

function GetFileNameThread(lpParameters: Pointer): DWORD; stdcall;
 var
   FileNameInfo: FILE_NAME_INFORMATION;
   ObjectNameInfo: TOBJECT_NAME_INFORMATION;
   IoStatusBlock: IO_STATUS_BLOCK;
   pThreadParam: TGetFileNameThreadParam;
   dwReturn: DWORD;
 begin
   ZeroMemory(@FileNameInfo, SizeOf(FILE_NAME_INFORMATION));
   pThreadParam := PGetFileNameThreadParam(lpParameters)^;
   Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock,
     @FileNameInfo, MAX_PATH * 2, FileNameInformation);
   if Result = STATUS_SUCCESS then
   begin
     Result := NtQueryObject(pThreadParam.hFile, ObjectNameInformation,
       @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
     if Result = STATUS_SUCCESS then
     begin
       pThreadParam.Status := Result;
       WideCharToMultiByte(CP_ACP, 0,
         @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength -
         ObjectNameInfo.Name.Length],
         ObjectNameInfo.Name.Length, @pThreadParam.Data[0],
         MAX_PATH, nil, nil);
     end
     else
     begin
       pThreadParam.Status := STATUS_SUCCESS;
       Result := STATUS_SUCCESS;
       WideCharToMultiByte(CP_ACP, 0,
         @FileNameInfo.FileName[0], IoStatusBlock.Information,
         @pThreadParam.Data[0],
         MAX_PATH, nil, nil);
     end;
   end;
   PGetFileNameThreadParam(lpParameters)^ := pThreadParam;
   ExitThread(Result);
 end;


вот тут на пайпе будет не STATUS_SUCCESS

   Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock,
     @FileNameInfo, MAX_PATH * 2, FileNameInformation);
   if Result = STATUS_SUCCESS then


соответственно дальнейшая проверка не нужна...


BiN   (2006-11-06 19:32:00) [9]


> Rouse_ ©   (06.11.06 17:42) [31]
>
>
> > Просто, как Розыч: вызывать DuplicateHandle и NtQueryObject
>
> > в отдельном потоке - при таймауте, убивать поток.
>
> Дим ну сколько раз я тебе повторял - что деструктор потока
> у меня не срабатывает, т.к. синхронный пайп я таки отлавливаю
> на NtQueryFile а не NtQueryObject - где и будет зависон
> :)


Пардон, а NtQueryFile это что?
Сань, я по своей дырявой памяти вкратце воспроизводил твой метод, так как приснопямятная ветка утекла в Лету.


Rouse_   (2006-11-06 17:46:00) [10]

Точнее, парнондю - не отлавливаю а отсекаю :)
У меня задача была заточена именно на Файл


Rouse_   (2006-11-06 17:42:00) [11]


> Просто, как Розыч: вызывать DuplicateHandle и NtQueryObject
> в отдельном потоке - при таймауте, убивать поток.

Дим ну сколько раз я тебе повторял - что деструктор потока у меня не срабатывает, т.к. синхронный пайп я таки отлавливаю на NtQueryFile а не NtQueryObject - где и будет зависон :)


Ketmar   (2006-11-06 17:21:00) [12]

>[28] Riply(c) 6-Nov-2006, 13:32
>Что делать, если больше негде :)) Да и интересного там
>много :)
мне б твой молодой энтузиазм...


BiN   (2006-11-06 14:28:00) [13]


> Riply ©   (06.11.06 13:26) [27]
>
> А с помощью чего исследуешь ?

С помощью \Device\PhysicalMemory.


Riply   (2006-11-06 13:32:00) [14]

>[25] Ketmar ©   (05.11.06 23:07)
>фигасе люди лазят по системе...
Что делать, если больше негде :)) Да и интересного там много :)


Riply   (2006-11-06 13:26:00) [15]

>[26] BiN ©   (06.11.06 01:21)
:)
>исследую FILE_OBJECT, а именно .DeviceObject.DeviceType
>на предмет равенства FILE_DEVICE_NAMED_PIPE, и FileName соответсвенно
А с помощью чего исследуешь ?
NtQueryObject(...ObjectTypeInformation... ?
Я не нашла ничего похожего на ".DeviceObject.DeviceType".
Во всяком случае в OBJECT_TYPE_INFORMATION у меня этого нет.
Правда в OBJECT_BASIC_INFORMATION три параметра - "Unknown".


BiN   (2006-11-06 01:21:00) [16]


> Riply ©   (05.11.06 22:45) [24]
>
> Порядковый номер соответствует типу.

О, ангидрид в мою перекись! У меня в программе был баг... Кто ж думал, что типы индексируются с единицы, а не с нуля!!!!


> Перед вызовом NtQueryObject, все таки хотелось бы
> по таблице посмотреть, что за тип у хендла.  А то и зависнуть можно :)

С зависанием можно бороться следующим образом:
1) Просто, как Розыч: вызывать DuplicateHandle и NtQueryObject в отдельном потоке - при таймауте, убивать поток.
2) Сложно (ну не люблю я убивать потоки -)): определять заранее индекс "рискованного" типа File, создав объект данного типа (предпочитаю CreateNamedPipe, т.к. на создание дискового файла может и прав не хватить). У описателей с таким индексом (в W2k он равен 26) исследую FILE_OBJECT, а именно .DeviceObject.DeviceType на предмет равенства FILE_DEVICE_NAMED_PIPE, и FileName соответсвенно. Завис, как известно, случается с запросом имени именованных каналов, находящихся в ожидании завершения IO.

> Можно ли временно менять состояние флага и как ? И безопасно
> ли это ( смена флага ) ?

Менять вроде можно с помощью NtSetSystemInformation(SystemGlobalFlag,.. при установленной debug-привилегии.
Безопасно ли, см. http://www.osronline.com/ddkx/ddtools/gflags_7u5v.htm


Ketmar   (2006-11-05 23:07:00) [17]

фигасе люди лазят по системе...


Riply   (2006-11-05 22:45:00) [18]

>[23] BiN ©   (05.11.06 14:25)
>таблица соответсвия сама по себе мало где применима
>Если хотим определить имя типа объекта,
>то NtQueryObject(Handle, ObjectTypeInformation
Перед вызовом NtQueryObject, все таки хотелось бы
по таблице посмотреть, что за тип у хендла. А то и зависнуть можно :)
Да и при поиске чего то конкретного удобно сразу отбасывать хэндлы не тех типов.
У меня дела обстоят таким образом:
NtQueryObject(0, ObjectAllTypesInformation..  выдает следующий список:
Type
Directory
SymbolicLink
Token
Process
Thread
Job
DebugObject
Event
EventPair
Mutant
Callback
Semaphore
Timer
Profile
KeyedEvent
WindowStation
Desktop
Section
Key
Port
WaitablePort
Adapter
Controller
Device
Driver
IoCompletion
File
WmiGuid
FilterConnectionPort
FilterCommunicationPort

Порядковый номер соответствует типу.
Проверяла на NtQueryObject.
Флаг FLG_MAINTAIN_OBJECT_TYPELIST не установлен.
(если я все правильно делаю) RtlGetNtGlobalFlags возвращает 112,
как и PPEB^.NtGlobalFlag.
Можно ли временно менять состояние флага и как ? И безопасно ли это ( смена флага ) ?


BiN   (2006-11-05 14:25:00) [19]


> Riply ©   (05.11.06 10:00) [22]
>
> Т.е. при сброшеном флаге, для определения таблицы соответствия,
>
> надо создать объекты всех типов и посмотреть их индексы
> ?
> Как-то некузяво :))

Подобная таблица соответсвия сама по себе мало где применима без объектов, точнее без их описателей.
Если нужно получить список типов, используем NtQueryDirectoryObject.
Если хотим определить имя типа объекта, хэндл которого получили с помощью QSI, то NtQueryObject(Handle, ObjectTypeInformation


Riply   (2006-11-05 10:00:00) [20]

Т.е. при сброшеном флаге, для определения таблицы соответствия,
надо создать объекты всех типов и посмотреть их индексы ?
Как-то некузяво :))


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо