![]() |
AW: Seriennummer der Systemplatte...
Liste der Anhänge anzeigen (Anzahl: 3)
Zitat:
Test-Programm im Anhang.
Delphi-Quellcode:
unit Unit1;
{$mode objfpc}{$H+} interface uses Windows, Forms, StdCtrls; type { TForm1 } TForm1 = class(TForm) Label1: TLabel; Label2: TLabel; Label3: TLabel; procedure FormShow(Sender: TObject); private { private declarations } public { public declarations } end; var Form1: TForm1; OSVersionInfo: TOSVersionInfo; const IDENTIFY_BUFFER_SIZE = 512; // SMART IOCTL commands DFP_GET_VERSION = $00074080; DFP_SEND_DRIVE_COMMAND = $0007c084; DFP_RECEIVE_DRIVE_DATA = $0007c088; IDE_ATAPI_ID = $A1; // Returns ID sector for ATAPI. IDE_ID_FUNCTION = $EC; // Returns ID sector for ATA. IDE_EXECUTE_SMART_FUNCTION = $B0; // Performs SMART cmd. Requires valid bFeaturesReg, bCylLowReg, and bCylHighReg type TIDERegs = packed record bFeaturesReg : BYTE; // Used for specifying SMART "commands". bSectorCountReg : BYTE; // IDE sector count register bSectorNumberReg : BYTE; // IDE sector number register bCylLowReg : BYTE; // IDE low order cylinder value bCylHighReg : BYTE; // IDE high order cylinder value bDriveHeadReg : BYTE; // IDE drive/head register bCommandReg : BYTE; // Actual IDE command. bReserved : BYTE; // reserved for future use. Must be zero. end; IDEREGS = TIDERegs; PIDERegs = ^TIDERegs; LPIDERegs = PIDERegs; _IDEREGS = TIDERegs; type TIdSector = packed record wGenConfig : Word; wNumCyls : Word; wReserved : Word; wNumHeads : Word; wBytesPerTrack : Word; wBytesPerSector : Word; wSectorsPerTrack : Word; wVendorUnique : Array[0..2] of Word; sSerialNumber : Array[0..19] of CHAR; wBufferType : Word; wBufferSize : Word; wECCSize : Word; sFirmwareRev : Array[0..7] of Char; sModelNumber : Array[0..39] of Char; wMoreVendorUnique : Word; wDoubleWordIO : Word; wCapabilities : Word; wReserved1 : Word; wPIOTiming : Word; wDMATiming : Word; wBS : Word; wNumCurrentCyls : Word; wNumCurrentHeads : Word; wNumCurrentSectorsPerTrack : Word; ulCurrentSectorCapacity : DWORD; wMultSectorStuff : Word; ulTotalAddressableSectors : DWORD; wSingleWordDMA : Word; wMultiWordDMA : Word; bReserved : Array[0..127] of BYTE; end; PIdSector = ^TIdSector; type TDriverStatus = packed record bDriverError : Byte; // Error code from driver, or 0 if no error. bIDEStatus : Byte; // Contents of IDE Error register. Only valid when bDriverError is SMART_IDE_ERROR. bReserved : Array[0..1] of Byte; // Reserved for future expansion. dwReserved : Array[0..1] of DWORD; // Reserved for future expansion. end; DRIVERSTATUS = TDriverStatus; PDriverStatus = ^TDriverStatus; LPDriverStatus = TDriverStatus; _DRIVERSTATUS = TDriverStatus; type TSendCmdOutParams = packed record cBufferSize : DWORD; // Size of bBuffer in bytes DriverStatus : TDriverStatus; // Driver status structure. bBuffer : Array[0..0] of BYTE; // Buffer of arbitrary length in which to store the data read from the drive. end; SENDCMDOUTPARAMS = TSendCmdOutParams; PSendCmdOutParams = ^TSendCmdOutParams; LPSendCmdOutParams = PSendCmdOutParams; _SENDCMDOUTPARAMS = TSendCmdOutParams; type TSendCmdInParams = packed record cBufferSize : DWORD; // Buffer size in bytes irDriveRegs : TIDERegs; // Structure with drive register values. bDriveNumber : BYTE; // Physical drive number to send command to (0,1,2,3). bReserved : Array[0..2] of Byte; // Reserved for future expansion. dwReserved : Array[0..3] of DWORD; // For future use. bBuffer : Array[0..0] of Byte; // Input buffer. end; SENDCMDINPARAMS = TSendCmdInParams; PSendCmdInParams = ^TSendCmdInParams; LPSendCmdInParams = PSendCmdInParams; _SENDCMDINPARAMS = TSendCmdInParams; implementation {$R *.lfm} //-------------------------------------------------------------------------------------------------------------------------- (* asm kennt LAZARUS nicht function StrLCopy(Dest: PAnsiChar; const Source: PAnsiChar; MaxLen: Cardinal): PAnsiChar; assembler; asm PUSH EDI PUSH ESI PUSH EBX MOV ESI,EAX MOV EDI,EDX MOV EBX,ECX XOR AL,AL TEST ECX,ECX JZ @@1 REPNE SCASB JNE @@1 INC ECX @@1: SUB EBX,ECX MOV EDI,ESI MOV ESI,EDX MOV EDX,EDI MOV ECX,EBX SHR ECX,2 REP MOVSD MOV ECX,EBX AND ECX,3 REP MOVSB STOSB MOV EAX,EDX POP EBX POP ESI POP EDI end; *) function StrLCopy(Dest, Source: PChar; MaxLen: Cardinal): PChar; var Count: Cardinal; begin // copies a specified maximum number of characters from Source to Dest Result := Dest; Count := 0; While (Count < MaxLen) and (Source^ <> #0) do begin Dest^ := Source^; Inc(Source); Inc(Dest); Inc(Count); end; Dest^ := #0; end; /// <description> copies a specified maximum number of characters from Source to Dest </description> function StrLCopy3(Dest, Source: PChar; MaxLen: UInt64): PChar; begin Dec(MaxLen); // für die abschließende #0 if Int64(MaxLen) < 0 then Exit(nil); Result := Dest; while (MaxLen > 0) and (Source^ <> #0) do begin Dest^ := Source^; Inc(Source); Inc(Dest); Dec(MaxLen); end; Dest^ := #0; end; procedure ChangeByteOrder( var Data; Size : Integer ); var ptr : PChar; i : Integer; c : Char; begin ptr := @Data; for i := 0 to (Size shr 1)-1 do begin c := ptr^; ptr^ := (ptr+1)^; (ptr+1)^ := c; Inc(ptr,2); end; end; function GetPhysicalDriveHandle(DriveNum: Byte; DesireAccess: ACCESS_MASK): THandle; var S: string; begin OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo); GetVersionEx(OSVersionInfo); if OSVersionInfo.dwPlatformId=VER_PLATFORM_WIN32_NT then // Windows NT, Windows 2000 begin Str(DriveNum,s); // avoid SysUtils // Result := CreateFile( PChar('\\.\PhysicalDrive'+S), DesireAccess, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ); Result := CreateFile( PChar('\\.\PhysicalDrive'+S), DesireAccess, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0 ); end else // Windows 95 OSR2, Windows 98 Result := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 ); end; procedure PrintIdSectorInfo( IdSector : TIdSector ); var szOutBuffer : Array [0..40] of Char; begin with IdSector do begin ChangeByteOrder( sModelNumber, SizeOf(sModelNumber) ); // Change the WORD array to a BYTE array szOutBuffer[SizeOf(sModelNumber)] := #0; StrLCopy( szOutBuffer, sModelNumber, SizeOf(sModelNumber) ); Form1.label1.caption :='Model : ' + szOutBuffer ; ChangeByteOrder( sFirmwareRev, SizeOf(sFirmwareRev) ); szOutBuffer[SizeOf(sFirmwareRev)] := #0; StrLCopy( szOutBuffer, sFirmwareRev, SizeOf(sFirmwareRev) ); Form1.label2.caption := 'Firmware Rev : ' + szOutBuffer ; ChangeByteOrder( sSerialNumber, SizeOf(sSerialNumber) ); szOutBuffer[SizeOf(sSerialNumber)] := #0; StrLCopy( szOutBuffer, sSerialNumber, SizeOf(sSerialNumber) ); Form1.label3.caption := 'Serial Number : '+ szOutBuffer ; end; end; function SmartIdentifyDirect( hDevice : THandle; bDriveNum : Byte; bIDCmd : Byte; var IdSector : TIdSector; var IdSectorSize : LongInt ) : BOOL; const BufferSize = SizeOf(TSendCmdOutParams)+IDENTIFY_BUFFER_SIZE-1; var SCIP : TSendCmdInParams; Buffer : Array [0..BufferSize-1] of Byte; SCOP : TSendCmdOutParams absolute Buffer; dwBytesReturned : DWORD; begin FillChar(SCIP,SizeOf(TSendCmdInParams)-1,#0); FillChar(Buffer,BufferSize,#0); dwBytesReturned := 0; IdSectorSize := 0; // Set up data structures for IDENTIFY command. with SCIP do begin cBufferSize := IDENTIFY_BUFFER_SIZE; bDriveNumber := bDriveNum; with irDriveRegs do begin bFeaturesReg := 0; bSectorCountReg := 1; bSectorNumberReg := 1; bCylLowReg := 0; bCylHighReg := 0; bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4); bCommandReg := bIDCmd; // The command can either be IDE identify or ATAPI identify. end; end; Result := DeviceIoControl( hDevice, DFP_RECEIVE_DRIVE_DATA, @SCIP, SizeOf(TSendCmdInParams)-1, @SCOP, BufferSize, dwBytesReturned, nil ); if Result then begin IdSectorSize := dwBytesReturned-SizeOf(TSendCmdOutParams)+1; if IdSectorSize<=0 then IdSectorSize := 0 else System.Move(SCOP.bBuffer,IdSector,IdSectorSize); end; end; procedure DirectIdentify; var hDevice : THandle; //rc : DWORD; nIdSectorSize : LongInt; aIdBuffer : Array [0..IDENTIFY_BUFFER_SIZE-1] of Byte; IdSector : TIdSector absolute aIdBuffer; begin FillChar(aIdBuffer,SizeOf(aIdBuffer),#0); hDevice := GetPhysicalDriveHandle( 0, GENERIC_READ or GENERIC_WRITE ); // hDevice := GetPhysicalDriveHandle( 0, GENERIC_READ ); <-- geht NICHT if hDevice=INVALID_HANDLE_VALUE then begin //rc := GetLastError; end else try if not SmartIdentifyDirect( hDevice, 0, IDE_ID_FUNCTION, IdSector, nIdSectorSize ) then begin //rc := GetLastError; end else begin //ShowMessage('SMART IDENTIFY command is completed successfully.'); PrintIdSectorInfo(IdSector); end; finally CloseHandle(hDevice); end; end; { TForm1 } procedure TForm1.FormShow(Sender: TObject); begin DirectIdentify; end; end. |
AW: Seriennummer der Systemplatte...
Zitat:
Ich dachte es soll nur was ausgelesen werden. :stupid: Und besonders das Laufwerk C: und de zugehörige PhysicalDrive0 stehn seit mindestens Windows 7 unter besonderem Schutz. Währe doch zu schlimmen, wenn jedes Programm einfach so auf der Platte rumschreiben könnte. PS: Auch das Lesen ist ein Problem, denn damit könnte man schließlich die Schutzmaßnahmen umgehen, also die Zugriffsrechte auf Verzeichnisse und Dateien. (was, ich hab keinen Zugriff? egal, denn geh ich eben direkt über das Laufwerk) Eventuell könnte man sogar noch auf das GENERIC_READ verzichten, denn eigentlich soll ja garnicht via ReadFile auf die Daten der Platte zugegriffen werden? :gruebel: Mit etwas Glück gibt es für Laufwerke auch sowas, wie bei dem Dateisystem? (z.B. ala ![]() ![]() Volle AdminRechte sind doch auch nicht nötig. Hab aber zu DeviceIoControl und DFP_RECEIVE_DRIVE_DATA noch nichts finden können, welchen DesiredAccess und was für Privilges benötigt werden. PS: In einem Windows 7 mit erhöhten Rechten (also auf 'nem Server2008/2001) funktioniert keiner der Codes. Auch dein fertiges Programm zeigt immer nur "Rechtsklick und so". |
AW: Seriennummer der Systemplatte...
FILE_SHARE_WRITE entfernt - ändert nichts am Verhalten der EXE.
Ich habe oben den gesamten Code (für LAZARUS) eingefügt. Vielleicht findet jemand einen Weg, den "Rechtsklick" zu umgehen. |
AW: Seriennummer der Systemplatte...
Zitat:
Andere müssen natürlich Schreibzugriff bekommen können, aber dieser Auslesecode braucht sowas doch wohl nicht? :angle: Zitat:
|
AW: Seriennummer der Systemplatte...
hDevice := GetPhysicalDriveHandle( 0, GENERIC_READ or GENERIC_WRITE ); <-- geht
// hDevice := GetPhysicalDriveHandle( 0, GENERIC_READ ); <--- geht nicht Rechtsklick bedeutet: Als Administrator starten |
AW: Seriennummer der Systemplatte...
Zitat:
Zitat:
|
AW: Seriennummer der Systemplatte...
Liste der Anhänge anzeigen (Anzahl: 1)
Mit Manifest geht's.
|
AW: Seriennummer der Systemplatte...
Nja, solange man unbedingt ein Handle benötigt, welches Schreib- und/oder Leserechte benötigt (GENERIC_READ und/oder GENERIC_WRITE), mit denen man z.B. via ReadFile auch auf die Daten der Platte zugreifen könnte ... solange kommt man um erhöhte Rechte, bzw. die nötigen Privilegien (am Einfachsten als Administrator) nicht drumrum.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:41 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz