2016-05-11 7 views
0

下記の例を見てください。デルファイは440バイトのCreateFileまたはWriteFileを使用します

WriteFile(hDevice、bfile、512、size、nil)then ShowMessage( 'Ok');

上記のように、私は512を使用しましたが、それは440で、以下のように、いいえ。

WriteFile(hDevice、bfile、440、size、nil)then ShowMessage( 'Ok');

私の質問は、どのように440バイト以下の512バイトを書くことができますか?

hDevice := CreateFile('\\.\PHYSICALDRIVE1', GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 
    if hDevice <> INVALID_HANDLE_VALUE then 
    begin 
     bfile := CreateFile('C:\Users\Administrator\Downloads\bfile', GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 
     if bfile <> INVALID_HANDLE_VALUE then 
     begin 
      ShowMessage(IntToStr(getlasterror)); 
      //SetFilePointer(hDevice,0,nil,FILE_BEGIN); // replace 0 with sector that you wish to read 
      if WriteFile(hDevice, bfile, 440, size, nil) then ShowMessage('b'); 
      ShowMessage(IntToStr(getlasterror)); 
      CloseHandle(hDevice); 
     end; 
    end; 
+0

関数が失敗したときに 'GetLastError'は何を返しますか? –

+0

@トム・ブルンベルク:それは2を返します! – nguyentu

+0

OK、ドキュメントについて2とは何ですか? –

答えて

0

WriteFile()は、第2引数としてメモリバッファへのポインタを受け取ります。

代わりにファイルハンドルを渡しています。

また、宛先は通常のファイルではなく、ハードディスクブロックデバイス(特別な制限があります)です。

ファイルからブロックデバイス上の元の場所にデータをコピーするとします。解決方法:bfileのデータをReadFile()のメモリバッファに読み込み、メモリバッファをWriteFile()に渡してhDeviceに書き込みます。

がまだ512書き込みを受け入れない場合は、hDeviceからセクタを読み取り、440バイトを最初のバイトにコピーするか、440バイトをたとえば128バイトで埋めます。ゼロ。

もちろん、間違って使用すると、このコードはハードディスクのブートセクタを壊してしまいます(WindowsとBIOSによって可能になる場合)、あなたが何をしているのかわからないので、私はあなたのために願っていますスクラッチシステムでのみこれをテストしていることを確認してください。

+0

ありがとう、私は仮想マシンと仮想ディスクを試して、それはより安全です – nguyentu

+0

ありがとう!最初の方法は私のためには機能しませんが、2番目の方法はうまくいきました。 512バイトのハードドライブを 'backup512'ファイルにバックアップした後、' bfile'ファイルの440バイトを 'backup512'に上書きしてから、もう一度' backup512'ファイルを私のハードドライブに書き込みます – nguyentu

+0

@ng一時バッファとしてのファイルは弱いです。メモリを使用します。 –

2

CreateFileのドキュメントこれは言う:

ボリュームは、1つまたは複数のマウントされたファイル・システムが含まれています。ボリュームハンドルは、特定のファイル システムの裁量で、非キャッシュオプションがCreateFileで指定されていない場合でも、 を非キャッシュとして開くことができます。 すべてのMicrosoftファイルシステムでボリュームハンドルが で、キャッシュされていないと想定する必要があります。ファイルの非キャッシュI/Oの制限は、ボリュームに を適用します。

のデータがキャッシュされていなくても、ファイルシステムにバッファのアライメントが必要な場合とない場合があります。ただし、 がボリュームを開いているときにキャッシュされていないオプションが指定されている場合は、ボリューム上のファイル に関係なく、バッファの位置合わせが強制されます。すべてのファイルシステムで、 オープンボリュ​​ームハンドルを非キャッシュとしてお勧めし、キャッシュされていないI/O の制限に従ってください。

この結果の1つは、セクタサイズの倍数で読み書きする必要があることです。そして、すべてのアクセスはセクターの境界になければなりません。コードがひどくこの時点で破壊されその上に

WriteFile(hDevice, bfile, 440, size, nil); 

2番目の引数はhDeviceに書き込まれるメモリのブロックへのポインタであるべきです。代わりに、ファイルハンドル値を指定します。おそらく、ファイルからバッファに読み込んだ後にデバイスに書き込む必要があります。

ストリームを使用すると、このコードは非常に簡単になります。ファイルにはTFileStreamを、デバイスへの書き込みにはTHandleStreamを使用できます。

+0

ありがとうございます。私はちょうど最近の日にデルファイについて学びます、私はあなたからフルコードを手に入れるのを手伝っていますか? – nguyentu

+0

これは実際にスタックオーバーフローの仕組みではありません。私たちは人々のためのコードを書くのではなく、ここで具体的な質問に答えます。さらに、これは実際にはWindowsの問題であり、Delphiの問題ではありません。 Delphiはプラットフォームを反映しています。あなたが知る必要があるのは、直接ディスクまたはボリュームへのアクセスには、バッファの位置合わせが必要であるということです。 –

+0

私は初心者ですが、例がなくてもそのドキュメントを理解することはできません。 – nguyentu

関連する問題