ZwReadFile выдаёт STATUS_INVALID_PARAMETER

Тема в разделе "WASM.BEGINNERS", создана пользователем T800, 4 май 2010.

  1. T800

    T800 Member

    Публикаций:
    0
    Регистрация:
    7 дек 2006
    Сообщения:
    293
    Адрес:
    Moscow
    Имеется тестовая прожка, которая просто читает файлики с использованием "нативных" ф-ий (Zw*).
    Думал ранее что она работает нормально, но тут случайно обнаружил, что на некоторых файликах ZwReadFile спотыкается.
    Покурил немного wasm, но так и не понял причину этой ошибки.

    Вот сам кодес:
    Код (Text):
    1. function NtFileCreateEx(FileName: PWideChar): THandle;
    2. var
    3.   usName: TUnicodeString;
    4.   oa: TOBJECTATTRIBUTES;
    5.   Status: NTSTATUS;
    6.   IoStatusBlock: IO_STATUS_BLOCK;
    7. begin
    8.   Result := INVALID_HANDLE_VALUE;
    9.   RtlInitUnicodeString(@usName, FileName);
    10.   InitializeObjectAttributes(@oa, @usName, OBJ_CASE_INSENSITIVE, 0, nil);
    11.   Status := ZwCreateFile(@Result,
    12.       GENERIC_READ or SYNCHRONIZE,
    13.       @oa,
    14.       @IoStatusBlock,
    15.       nil,
    16.       FILE_ATTRIBUTE_NORMAL,
    17.       FILE_SHARE_READ,
    18.       FILE_OPEN,
    19.       FILE_NON_DIRECTORY_FILE or FILE_NO_INTERMEDIATE_BUFFERING or FILE_SYNCHRONOUS_IO_NONALERT,
    20.       nil,
    21.       0
    22.   );
    23.   if Status <> STATUS_SUCCESS then begin
    24.     SetLastError(RtlNtStatusToDosError(Status));
    25.     Result := INVALID_HANDLE_VALUE;
    26.   end;
    27. end;
    28.  
    29. function NtGetFileSize(hFile: THandle): Int64;
    30. var
    31.   errCode: NTSTATUS;
    32.   FileStandard: PFILE_STANDARD_INFORMATION;
    33.   IoStatusBlock: IO_STATUS_BLOCK;
    34. begin
    35.   GetMem(FileStandard, SizeOf(FileStandard^)+4);
    36.   errCode := ZwQueryInformationFile(hFile, @IoStatusBlock, FileStandard, SizeOf(FileStandard^)+4, FileStandardInformation);
    37.   if errCode <> STATUS_SUCCESS then begin
    38.     SetLastError(RtlNtStatusToDosError(errCode));
    39.     Result := -1;
    40.   end else begin
    41.     Result := FileStandard^.EndOfFile.QuadPart;
    42.   end;
    43.   FreeMem(FileStandard);
    44. end;
    45.  
    46. function MD5FileNative(FileName: PWideChar; Hash: PMD5Digest): Integer;
    47. const
    48.   FileBufSize = $20000;
    49. var
    50.   hFile: THandle;
    51.   fsz: LARGE_INTEGER;
    52.   md5c: TMD5Context;
    53.   ByteOffset: LARGE_INTEGER;
    54.   rdlen, h: DWORD;
    55.   ns: NTSTATUS;
    56.   StatusBlock: IO_STATUS_BLOCK;
    57.   tbuf: PChar;
    58. begin
    59.   Result := -1;
    60.   hFile := NtFileCreateEx(FileName);
    61.   if (hFile = 0) or (hFile = INVALID_HANDLE_VALUE) then Exit;
    62.   tbuf := nil;
    63.   try
    64.     fsz.QuadPart := NtGetFileSize(hFile);
    65.     if fsz.QuadPart <= 0 then Exit;
    66.     Result := -2;
    67.     if (fsz.QuadPart > 20*1024*1024) then Exit;
    68.     Form1.Memo1.Lines.Add('FileSize = '+IntToHex(fsz.LowPart, 8));
    69.     GetMem(tbuf, FileBufSize);
    70.     MD5Init(md5c);
    71.     ByteOffset.HighPart := 0;
    72.     ByteOffset.LowPart := 0;
    73.     rdlen := FileBufSize;
    74.     repeat
    75.       if (ByteOffset.LowPart + FileBufSize) > fsz.LowPart then
    76.         rdlen := fsz.LowPart - ByteOffset.LowPart;
    77.       Form1.Memo1.Lines.Add('L = '+IntToHex(ByteOffset.LowPart, 8)+'  rdlen = '+IntToHex(rdlen, 8));
    78.       ns := ZwReadFile(hFile, 0, nil, nil, @StatusBlock, tbuf, rdlen, @ByteOffset, 0);
    79.       if Integer(ns) < 0 then begin
    80.         Result := -3;
    81.         Form1.Memo1.Lines.Add('ERROR = '+IntToHex(ns, 8)+'  rdlen = '+IntToHex(rdlen, 8)+'  H = '+IntToStr(ByteOffset.HighPart)+'  L = '+IntToHex(ByteOffset.LowPart, 8));
    82.         Exit;
    83.       end;
    84.       if (StatusBlock.Information <> rdlen) then begin
    85.         Result := -4;
    86.         Exit;
    87.       end;
    88.       MD5Update(md5c, tbuf^, rdlen);
    89.       Inc(ByteOffset.LowPart, rdlen);
    90.     until ((ByteOffset.LowPart >= fsz.LowPart) or (rdlen <> FileBufSize));
    91.     MD5Final(md5c);
    92.     Hash^ := md5c.Digest;
    93.     Result :=  fsz.LowPart;
    94.   finally
    95.     CloseHandle(hFile);  // ZwClose(hFile);
    96.     if tbuf <> nil then FreeMem(tbuf);
    97.   end;
    98. end;      
    99.  
    100. .....
    101.   Memo1.Lines.Add(String(ws));
    102.   sz := MD5FileNative(@ws[1], @md5);
    103.   Memo1.Lines.Add('NT  sz = '+IntToStr(sz)+'  md5 = '+MD5DigestToStr(md5));
    104. .....
    Вот примеры чтения некоторых проблемных файлов:
    Код (Text):
    1. \Device\HarddiskVolume1\Program Files\Common Files\Microsoft Shared\VS7DEBUG\MDM.EXE
    2. FileSize = 0004EA48
    3. L = 00000000  rdlen = 00020000
    4. L = 00020000  rdlen = 00020000
    5. L = 00040000  rdlen = 0000EA48
    6. ERROR = C000000D  rdlen = 0000EA48  H = 0  L = 00040000
    7. NT  sz = -3  md5 = 00000000000000000000000000000000
    8.  
    9. \Device\HarddiskVolume1\ntldr
    10. FileSize = 0003D0B0
    11. L = 00000000  rdlen = 00020000
    12. L = 00020000  rdlen = 0001D0B0
    13. ERROR = C000000D  rdlen = 0001D0B0  H = 0  L = 00020000
    14. NT  sz = -3  md5 = 00000000000000000000000000000000
    При этом, если зачитывать байтики через стандартные ф-ии для работы с файлами (те что из kernel32), то все читается на ура.
    Привилегии и права все выставляются.
    Уже и не знаю куда копать.
     
  2. T800

    T800 Member

    Публикаций:
    0
    Регистрация:
    7 дек 2006
    Сообщения:
    293
    Адрес:
    Moscow
    Редко я обращаюсь к MSDN. Надо приучать себя.
    Написано там следующее:
    После того, как rdlen "выровнил" на 512, всё заработало.
    Надо бы более основательно о ZwReadFile почитать на досуге. Что то много там нюансов.
    Всем спасибо.