2015-01-09 5 views
2

ReadFile에서 간단한 텍스트 파일을 읽을 수는 있지만 실제 드라이브에서는 제대로 작동하지 않습니다. GetLastError에서 "The parameter is incorrect"오류가 발생합니다. 일부 블록 크기로 정렬되어야합니다 - 나는 5 원시 장치에서 읽을 때 읽을 수있는 잘못된 크기입니다 생각ReadFile을 실제 드라이브와 함께 사용할 수 없습니다.

using System; 
using System.Runtime.InteropServices; 

namespace ReadFileTest 
{ 
class Program 
{ 
    [DllImport("kernel32.dll")] 
    static extern unsafe uint GetLastError(); 

    [DllImport("kernel32", SetLastError = true)] 
    static extern unsafe System.IntPtr CreateFile 
    (
     string FileName,   // file name 
     uint DesiredAccess,  // access mode 
     uint ShareMode,   // share mode 
     uint SecurityAttributes, // Security Attributes 
     uint CreationDisposition, // how to create 
     uint FlagsAndAttributes, // file attributes 
     int hTemplateFile   // handle to template file 
    ); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern unsafe bool ReadFile 
    (
     IntPtr hFile, 
     [Out] byte[] lpBuffer, 
     uint nNumberOfBytesToRead, 
     out uint lpNumberOfBytesRead, 
     IntPtr lpOverlapped 
    ); 

    const uint GENERIC_READ = 0x80000000; 
    const uint GENERIC_WRITE = 0x050000000; 
    const uint GENERIC_ALL = 0x10000000; 
    const uint FILE_SHARE_READ = 1; 
    const uint FILE_SHARE_WRITE = 2; 

    const uint OPEN_EXISTING = 3; 
    const int INVALID_HANDLE_VALUE = -1; 

    static void Main(string[] args) 
    { 
     unsafe 
     { 
      // Reading a simple text file works perfectly: 
      //IntPtr handle = CreateFile("D:\\Test.txt", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); 

      // CreateFile of a physical drive gives me a valid handle. 
      // But when attempting to read the drive, (all of my drives give the same result), I get the error "The parameter is incorrect." 
      IntPtr handle = CreateFile(@"\\.\PHYSICALDRIVE2", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); 

      // GetLastError returns this: 
      // ERROR_INVALID_PARAMETER87 (0x57) 
      // The parameter is incorrect. 

      byte[] b = { 1, 2, 3, 4, 5 }; 
      uint n = 1; 

      while (n != 0) 
      { 
       bool ret = ReadFile(handle, b, (uint)5, out n, (IntPtr)0); 
       uint e = GetLastError(); 
      } 

     } 
    } 
} 
} 

// I have unmounted the physical drive and run the test with the same results. 
// I tried using pointers for the parameters, same result. 
// I tried different variations of options for CreateFile. 
// Don't know which parameter is giving the error. 
+0

상승 중입니까? (ISTR 일반 사용자는 장치를 직접 읽을 수 없습니다.) – Richard

+0

사이드 노트 : [GetLastWin32Error]를 사용해야 함을 알고 있습니다 (http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal .getlastwin32error.aspx) 대신 PInvoke'GetLastError'를 직접 사용할 수 있습니까? (GetLastError 호출을 표시하는 이유가 샘플을 길게 만드는 이유는 확실치 않습니다). –

+1

또한'ReadFile' 결과를 확인하지 않고 있습니다. 성공적인 API 호출이 항상 오류 값을 지우는 것은 아닙니다. – Richard

답변

2

다음 더 많은 정보를 제공하기 때문에 내 코드입니다. 0x1000과 같은 무언가가 성공할 확률이 더 큽니다.

ReadFile 설명서를주의 깊게 읽으십시오. 로우 레벨 API를 실제로 탐색하려는 경우 "Windows Internals"서적 중 하나를 읽는 것을 고려하십시오.

관련 문제