![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Перечисление системных объектных типов [Win2k]
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]Т.е. при сброшеном флаге, для определения таблицы соответствия,
надо создать объекты всех типов и посмотреть их индексы ?
Как-то некузяво :))