ntdll.dll의 비문서화 함수인 ZwQuerySystemInformation 함수를 이용해서 각종 시스템 핸들을 구해보려고 합니다.
그런데 리턴으로 오는 포인터 값의 형태가 '리턴되는 갯수 + 구조체 + 구조체 + 구조체 + ..... ' 이런 형태네요.
단순히 '구조체 + 구조체 + 구조체 + ....' 형태는 배열처럼 사용하면 된다고 알고 있습니다만,
이런 형태의 경우 어떻게 읽어야 하는지 모르겠습니다.
사실 리턴되는갯수도 정확히 읽는건지도 모르겠구요.. ^^;
<!--CodeS-->
const
CONST_BASIC_QUERY_SIZE = 26000;
CONST_ADD_QUERY_SIZE = 100;
procedure TForm1.Button1Click(Sender: TObject);
var
nCount : integer;
pInfo : PULONG;
nHandles : ULONG;
aHandles : PSYSTEM_HANDLE_INFORMATION;
begin
nCount := CONST_BASIC_QUERY_SIZE;
GetMem( pInfo, nCount * sizeof(SYSTEM_HANDLE_INFORMATION) + sizeof(ULONG));
while ( ZwQuerySystemInformation(SystemHandleInformation, pInfo, nCount * sizeof(SYSTEM_HANDLE_INFORMATION) +
sizeof(ULONG), 0) = STATUS_INFO_LENGTH_MISMATCH) do
begin
freeMem(pInfo);
nCount := nCount + CONST_ADD_QUERY_SIZE;
GetMem( pInfo, nCount * sizeof(SYSTEM_HANDLE_INFORMATION) + sizeof(ULONG));
end;
nHandles := nHandles := pInfo^; // <--- 리턴된 수는 이게 맞나요?
aHandles := (PSYSTEM_HANDLE_INFORMATION) pInfo+1; // <- VC에서는 이렇게 읽던데 델파이에선 안 통하네요 ^^;;
<!--CodeE-->
저게 씨코드 그대로 변환한것이라면... 아래 둘중하나의 코드를 쓰세요.
aHandles := PULONG(LongWord(pInfo) + SizeOf(ULONG));
혹은
aHandles := pInfo;
Inc(PULONG(aHandle));
위처럼 포인터를 쓰셔도 되지만... 배열을 이용하면 더 편리합니다.
type
T구조체 = packed record
필드1: 데이터형1;
필드n: 데이터형n;
end;
PSYSTEM_HANDLE_INFORMATION = ^TSYSTEM_HANDLE_INFORMATION;
TSYSTEM_HANDLE_INFORMATION = packed record
리턴되는갯수: 정수;
구조체배열: array[0..0] of T구조체;
end;
var
P: PSYSTEM_HANDLE_INFORMATION;
begin
for I := 0 to P.리턴되는갯수-1 do
begin
데이터1 := P.구조체배열[I].필드1;
데이터n := p.구조체배열[I].필드n;
DoSomething;
end;
end;