2012-10-18 25 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を作成しました。機能はこれです:

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#プロジェクトにインポート:

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

は、それから私は、関数を呼び出す:

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

は常に値に関係なく、最初のセクタに書き込むことはありません"posicion_inicio"(開始オフセット、スペイン語のタグについてはごめんなさい)だから、書き込まれたバイトの代わりにdwPtr(ResultのSetFilePointer)を返すようにAPIの書き込み関数を変更したのはこのためです。これは常にゼロと思われますが、明らかに私が望むものではありません。しかし、なぜ最初の関数が動作し、dll呼び出しはしません見つけることができません。

たぶん、最初の一目で見られるべきものですが、私が言ったように、私はプログラミングのこの種に使用されていない電子機器の男、午前...仕事(DISK_GEOMETRYまたはVOLUME_DISK_EXTENTSの読み取りなど)

その他の機能、どの物理ドライブが特定の論理ユニットであるかを判断するために使用します。私が言うように、書くことと読むこともうまくいきます。私はいつもセクターゼロを指しています...

ありがとうございます。また、私がここに投稿するのは初めてです。何度も読んだので(私はここで尋ねることにした)、質問を投稿するときに間違いがあった場合は、それを指摘してください。

答えて

3

longは32ビットです。これにより、C#のになります。 pinvoke宣言でlongをintに置き換えます。

あなたはそれについてのPInvokeStackImbalance警告を得ているはずです。警告をオフにした場合は、再度有効にしてください。 * posicion_inicio *の値がデバッガで間違っていることを確認するのは簡単でした。アンマネージドデバッグ、Project + Properties、Debugタブを必ず有効にしてください。これで、C++コードにブレークポイントを設定できます。

+0

ありがとうございます。それはC++のint型として宣言されています。また、管理されていないコードのデバッグのヒントについてもありがとう、そのオプションについては知らなかった。今は意図したとおりに動作します。これは、言語を切り替えるときに、データ型に注意を払う必要があると私は考えています。再度、感謝します!私の英語を許してください:)編集:私はそうする評判15する必要があるように答えを投票することはできません。 – JeToMad

+0

技術的には、** Microsoft Visual C++ **の 'long'は32ビットです。 IIRC、Linux/G ++ではC#と同じように64ビットになることがよくあります。 – MSalters

関連する問題