2012-10-18 2 views
5

먼저 내가 바보라고 말하면 용서해주십시오. IT 엔지니어는 아니지만 전자 기술자입니다.하지만 더 많은 기술을 필요로하는 것에 할당되었습니다.SetFilePointer가 실패하지 않고 포인터도 이동하지 않습니다.

SD 카드에 물리적 섹터를 쓰고 읽어야합니다. C++로 완성했지만 주요 응용 프로그램은 C#으로 작성되었으므로 첫 번째 dll을 작성하는 것이 좋은 순간이라고 생각했습니다.

다음은 섹터 작성을 위해 C++에서 작동하는 코드입니다.

private: System::Void button4_Click(System::Object^ sender, System::EventArgs^ e) { 
HANDLE hFile = INVALID_HANDLE_VALUE; 
    BOOL fSuccess = FALSE; 


    DWORD dwBytesWritten = 0; 

    unsigned char chBuffer[SIZE]; 

    long SectorActual = 39; 
    long PosicionInicio = SectorActual * 512; 

     for (int i=0; i<SIZE; i++) // Garbage values to be written 
     { 
      chBuffer[i]= i % 16; 
      if((i/16)%2==0) 
      { 
       chBuffer[i]= 15 - chBuffer[i]; 
      } 
     } 
     hFile = CreateFileA("\\\\.\\PhysicalDrive5",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 

     if (hFile == INVALID_HANDLE_VALUE) 
     { 
      textBox1->Text += "Could not open file (error " + GetLastError() + ") \r\n"; 
      return; 
     } 

     DWORD dwPtr = SetFilePointer(hFile, 
           PosicionInicio, 
           NULL, 
           FILE_BEGIN); 

     if (dwPtr == INVALID_SET_FILE_POINTER) // Test for failure 
     { 
      textBox1->Text += "Error moving pointer (error " + GetLastError() + ") \r\n"; 
      return;  // Deal with failure 
     } // End of error handler 

     fSuccess = WriteFile(hFile, chBuffer, TAMANYO_SECTOR, &dwBytesWritten, NULL); 
     if (!fSuccess) 
     { 
      textBox1->Text += "WriteFile failed\r\n"; 
     } 
     else 
     { 
      textBox1->Text += "WriteFile wrote " + dwBytesWritten.ToString() + " bytes\r\n"; 
     } 

     CloseHandle(hFile); 
    } 

그럼 DLL을 만들었습니다.

[DllImport("AccesoBajoNivel.dll", CallingConvention = CallingConvention.Cdecl)] 
static extern int EscribeBloqueFisico(char numeroDisco, byte[] buffer, long BytesQueEscribir, long posicion_inicio); 

가 그럼이 함수를 호출 : :

int AccesoBajoNivel::EscribeBloqueFisico(char numeroDisco, unsigned char * buffer, long  BytesQueEscribir, long posicion_inicio) 
{ 
    HANDLE hFile = INVALID_HANDLE_VALUE; 
      BOOL fSuccess = FALSE; 
    DWORD dwBytesWritten = 0; 

    char ArrayDeChars[] = "\\\\.\\PhysicalDrive5"; 
      ArrayDeChars[17] = numeroDisco; 
    LPCSTR pathAlDisco = ArrayDeChars; 

    hFile = CreateFileA(pathAlDisco,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 

    if (hFile == INVALID_HANDLE_VALUE) 
    { 
     //printf("Could not open file (error %d)\n", GetLastError()); 
     CloseHandle(hFile); 
     return -1; 
    } 

    DWORD dwPtr = SetFilePointer(hFile, 
          posicion_inicio, 
          NULL, 
          FILE_BEGIN); 

    if (dwPtr == INVALID_SET_FILE_POINTER) // Test for failure 
    { 
     CloseHandle(hFile); 
     return -2;  // Deal with failure 
    } // End of error handler 

    fSuccess = WriteFile(hFile, buffer, BytesQueEscribir, &dwBytesWritten, NULL); 
    if (!fSuccess) 
    { 
     CloseHandle(hFile); 
     return -3; 
    } 
    else 
    { 
     CloseHandle(hFile); 
     //return dwBytesWritten; 
     return dwPtr; 
    } 

    CloseHandle(hFile); 
} 

그런 다음 나는 C# 프로젝트에 수입 : 기능이있다

int ResultEscribir = EscribeBloqueFisico(numeroDiscoFisico, BufferEscritura, 512, SectorEscribir * 512); 

항상 첫 번째 섹터에 기록을 상관없이 값 "posicion_inicio"(시작 오프셋, spanish 태그에 대해 미안합니다.) 그래서 api에서 쓰기 기능을 변경하여 dwPtr (Result of SetFilePointer)를 작성한 바이트 대신 반환했습니다. 이것은 항상 제로 인 것처럼 보이는데, 그것은 분명히 내가 원하는 것이 아닙니다. 그러나 첫 번째 함수가 작동하고 dll 호출이 왜 작동하지 않는지 알 수 없습니다.

어쩌면 처음 눈에 볼 수 있어야 뭔가이지만, 내가 말했듯이, 나는 작업 (읽기 DISK_GEOMETRY 또는 VOLUME_DISK_EXTENTS으로) ... 전자는 사람, 프로그램의 종류에 익숙하지

다른 기능을 오전, 어떤 물리적 드라이브가 주어진 논리 단위인지 결정하는 데 사용됩니다. 제가 말했듯이, 글쓰기와 읽기가 잘 작동한다는 것은 제가 항상 섹터 0을 가리키고 있다는 것입니다 ...

미리 감사드립니다. 또한, 내가 여기에 게시하는 것은 이번이 처음이다. 여러 번 읽음 (이 때문에 내가 여기서 물어보기로 했음)하지만 질문을 게시 할 때 실수를했다면 지적 해주십시오.

답변

3

길이가 인 C++가 32 비트입니다. 어느 것이 C#에서 이됩니다. pinvoke 선언에서 long을 int로 바꾸십시오.

그것에 대해 PInvokeStackImbalance 경고가 표시되어야합니다. 사용 중지 한 경우 경고를 다시 사용하도록 설정했는지 확인하십시오. 디버거에서는 * posicion_inicio *의 값이 잘못되었음을 쉽게 알 수 있습니다. 관리되지 않는 디버깅 인 Project + Properties, Debug 탭을 사용해야합니다. 이제 C++ 코드에 중단 점을 설정할 수 있습니다.

+0

대단히 감사합니다. (C++에서 int로 선언하면 C++에서 길었던 것이므로) 문제가 해결되었습니다. 또한 관리되지 않는 코드 디버깅에 대한 힌트를 주셔서 감사합니다. 이제 의도 한대로 작동합니다. 이 언어로 전환 할 때 데이터 유형에주의를 기울여야한다고 생각합니다. 다시 한 번 감사드립니다! 제발 내 영어를 용서해주세요 :) 편집 : 그렇게하기 위해 평판이 필요하다고 생각되는 것처럼 대답을 투표 할 수 없습니다. – JeToMad

+0

** Microsoft Visual C++ **의 'long'은 기술적으로 32 비트입니다. IIRC, Linux/G ++에서 C#처럼 자주 64 비트입니다. – MSalters

관련 문제