Erstmal vorab vielen Dank für alle Antworten
@p80286: klar habe ich eine Übungspartition - ich teste das alles mit VMWare 8 (XP) in einer virtuellen Maschine. Gute Idee, das mit dem Kopierschutz, habe leider im VMWare-Bios keinen gefunden.
@Luckie: großartig, danke! Auch wenn Du da mit Volumes arbeitest, weswegen es mir hier konkret nicht hilft - das kann ich später sicher nochmal als Referenz gebrauchen (Bootsektoren und Teile des NTFS-Dateisystems kann der Code auch schon lesen, aber da hab ich mich ums Schreiben noch gar nicht kümmern können bisher, und in der
GUI isses noch lange nicht).
@himitsu, sx2008: In Sachen Rechte hatte ich das hier im
MSDN gefunden:
Zitat:
A write on a volume
handle will succeed if the volume does not have a mounted file system, or if one of the following conditions is true:
- The sectors to be written to are boot sectors.
- The sectors to be written to reside outside of file system space.
- You have explicitly locked or dismounted the volume by using FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME.
- The volume has no actual file system. (In other words, it has a RAW file system mounted.)
A write on a disk
handle will succeed if one of the following conditions is true:
- The sectors to be written to do not fall within a volume's extents.
- The sectors to be written to fall within a mounted volume, but you have explicitly locked or dismounted the volume by using FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME.
- The sectors to be written to fall within a volume that has no mounted file system other than RAW.
Um ein Volume-
Handle handelt es sich nicht, aber der Bootsektor bei Volumes wird lockerer gehandhabt, und ich habe auch zu Disk-Handles (ich glaube sogar hier im Forum) gelesen, daß man ausgerechnet da einfacher drauf schreiben darf. Siehe auch da oben: fällt nicht in den Bereich eines Volumes.
Unter XP ein Admin, unter Win7 ein Admin mit dem Programm elevated ist natürlich selbstverständlich, das Manifest passt entsprechend. Unter Win7 bekomme ich auch noch ein
Access Denied, aber solange es unter XP nicht läuft, muss ich da erstmal nicht ran (denke ich?).
@himitsu: stimmt, ich werte den Rückgabewert von CreateFile nicht aus. War aber auch nur der alternative Ansatz, im TFileStream-Mopped gäbe es ja False als Rückgabewert, und die
Handle-Variante hätte spätestens beim ReadFile einen Error, wenn das CreateFile scheitern würde. Egal, habe das mal nachgeholt.
@sx2008: THandleStream?
Oh, der ist mir neu, was für ne praktische Sache!
Habe das ganze als dritte Alternative nun auch noch mit THandleStream geschrieben:
Delphi-Quellcode:
function TMasterBootRecordStream.WriteToDriveFileHandleStream(
const ADiskDeviceName:
string;
var AErrorCode: cardinal): boolean;
var
h: THandle;
hs: THandleStream;
ms: TMemoryStream;
iBytesCopied: Int64;
begin
AErrorCode := 0;
try
Seek(0, soFromBeginning);
h := CreateFile(PChar('
\\.\' + ADiskDeviceName), GENERIC_READ
or GENERIC_WRITE, FILE_SHARE_READ
or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
Result := (h <> INVALID_HANDLE_VALUE);
if Result
then begin
hs := THandleStream.Create(h);
ms := TMemoryStream.Create;
try
{$IFDEF MBRWriteOnlyAffectedBytes}
iBytesCopied := hs.CopyFrom(Self, MasterBootRecordCodeSize);
Result := (iBytesCopied = MasterBootRecordCodeSize);
if not Result
then begin
AErrorCode := ERROR_BAD_LENGTH;
end;
{$ELSE MBRWriteOnlyAffectedBytes}
hs.Seek(0, soFromBeginning);
iBytesCopied := ms.CopyFrom(hs, SectorSize);
Result := (iBytesCopied = SectorSize);
if Result
then begin
ms.Seek(0, soFromBeginning);
iBytesCopied := ms.CopyFrom(Self, MasterBootRecordCodeSize);
Result := (iBytesCopied = MasterBootRecordCodeSize);
if Result
then begin
ms.Seek(0, soFromBeginning);
hs.Seek(0, soFromBeginning);
iBytesCopied := hs.CopyFrom(ms, SectorSize);
Result := (iBytesCopied = SectorSize);
if not Result
then begin
AErrorCode := ERROR_BAD_LENGTH;
end;
end else begin
AErrorCode := ERROR_BAD_LENGTH;
end;
end else begin
AErrorCode := ERROR_BAD_LENGTH;
end;
{$ENDIF MBRWriteOnlyAffectedBytes}
finally
ms.Free;
hs.Free;
end;
end else begin
AErrorCode := GetLastError;
end;
except
on E:
Exception do begin
Result := false;
ShowMessage(E.
Message);
end;
end;
end;