2017-04-21 19 views
1

내 프로그램 "Kernel32.dll"기능을 사용하여 WinXP SP3 OS (외장 HDD)의 원시 디스크 섹터에 액세스하고 있습니다.외부 HDD에서 높은 오프셋 (4G 이상)의 원시 섹터 액세스

프로그램이 섹터 번호 8388607에 도달 할 때까지 모든 것이 잘 작동합니다. 즉, SetFilePointer에서 바이트 오프셋이 32 비트 (단위! 그러나 아래 코드는 모든 변수를 "long"으로 사용합니다. 내가 뭘 잘못하고 있니? (버튼 클릭 "덤프"에 대한)

코드 :

int drive = DRV.SelectedIndex; // DRV is the drive combo box 
long bps = BytesPerSector(drive), spt = GetTotalSectors(drive); 
string dr = DRV.SelectedItem.ToString(); 
int moveToHigh, read = 0; 

uint GENERIC_READ = 0x80000000; 
uint OPEN_EXISTING = 3; 
SafeFileHandle handleValue = CreateFile(dr, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); 
if (handleValue.IsInvalid) 
    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 

// idx = Loop starting index 
// FS = The starting sector index 
// TS = The final sector index 
long idx = (FS == -1) ? 0 : FS, tot = (TS == -1) ? spt : TS; 

for (; idx < tot; idx++) 
{ 
     byte[] b = new byte[bps]; 

     // HERE IS THE ISSUE!!! 
     SetFilePointer(handleValue, idx*bps), out moveToHigh, EMoveMethod.Current); 

     if (ReadFile(handleValue, b, bps, out read, IntPtr.Zero) == 0) 
      Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 



     if (this.IsDisposed == true) { handleValue.Close(); break; } 
      Application.DoEvents(); 
    } 
    handleValue.Close(); 

kernel32.dll에서 외부 함수 :

[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
static extern uint SetFilePointer(
     [In] SafeFileHandle hFile, 
     [In] long lDistanceToMove, 
     [Out] out int lpDistanceToMoveHigh, 
     [In] EMoveMethod dwMoveMethod); 

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, 
     uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, 
     uint dwFlagsAndAttributes, IntPtr hTemplateFile); 

[DllImport("kernel32", SetLastError = true)] 
internal extern static int ReadFile(SafeFileHandle handle, byte[] bytes, 
     int numBytesToRead, out int numBytesRead, IntPtr overlapped_MustBeZero); 

내가 많은 것을 시도했다, 그러나 아무 생각이 무슨 없으며, 응용 프로그램 그냥 치명적인 예외로 끝날 버그보고를 보내달라고

고마워요

+0

그러면 어떻게됩니까? 오류? 그리고 왜 정수에 double을 사용합니까? 또한 .NET에서 길다는 것은 Win32API에서 길다는 것과 다릅니다. –

답변

1

P/Invoke 정의가 잘못되었습니다. 이 함수는 32 비트 값을 사용하지만 64 비트 값으로 정의했습니다. 제대로 작동하지 않으며 32 비트 변수의 값 범위를 지나치지 않습니다.

pinvoke.net에서 사용하는 방법에 대한 정의와 예를 참조하십시오

[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
private static extern int SetFilePointer(IntPtr handle, int lDistanceToMove, out int lpDistanceToMoveHigh, uint dwMoveMethod); 


int lo = (int)(offset & 0xffffffff); 
int hi = (int)(offset >> 32); 

lo = SetFilePointer(handle, lo, out hi, moveMethod); 

그래서 당신이 두 64 비트 값을 분할 함수에 대한 두 부분을 제공해야합니다.

또한 정수에는 double을 사용하지 마십시오. 정확성이 끝나고 그것을 사용할 이유가 없으면 문제가 발생할 것입니다.

+0

나는 그것을 바로 잡았지만 섹터 # 8388636에서 나는 정확히 무슨 일이 일어 났는지에 대한 명확한 설명없이 "HRESULT : 0x80070017"예외를 얻는다. 이것은 무엇을 의미합니까? – Xerix

+0

나는 그것을 발견했다. 나는 현재부터 찾고 있었고, 시작으로 바뀌었다. – Xerix