AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Seriennummer der Systemplatte...
Thema durchsuchen
Ansicht
Themen-Optionen

Seriennummer der Systemplatte...

Ein Thema von Z4ppy · begonnen am 9. Okt 2010 · letzter Beitrag vom 29. Apr 2012
Antwort Antwort
Seite 3 von 3     123   
hathor
(Gast)

n/a Beiträge
 
#21

AW: Seriennummer der Systemplatte...

  Alt 28. Apr 2012, 02:48
Aber doch nicht, um die Seriennummer auszulesen.
GetPhysicalDriveHandle ist das Problem. Es braucht Administrator-Rechte bei WIN 7.

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.
Miniaturansicht angehängter Grafiken
test.jpg   test-2.jpg  
Angehängte Dateien
Dateityp: zip TEST.zip (635,0 KB, 45x aufgerufen)

Geändert von hathor (28. Apr 2012 um 17:17 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.051 Beiträge
 
Delphi 12 Athens
 
#22

AW: Seriennummer der Systemplatte...

  Alt 28. Apr 2012, 10:15
Zitat:
GetPhysicalDriveHandle > GENERIC_READ or GENERIC_WRITE
Wozu werden eigentlich die Schreibrechte benötigt?

Ich dachte es soll nur was ausgelesen werden.

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?
Mit etwas Glück gibt es für Laufwerke auch sowas, wie bei dem Dateisystem? (z.B. ala FILE_READ_EA oder READ_CONTROL)
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".
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (28. Apr 2012 um 10:37 Uhr)
  Mit Zitat antworten Zitat
hathor
(Gast)

n/a Beiträge
 
#23

AW: Seriennummer der Systemplatte...

  Alt 28. Apr 2012, 17:11
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.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.051 Beiträge
 
Delphi 12 Athens
 
#24

AW: Seriennummer der Systemplatte...

  Alt 28. Apr 2012, 17:24
FILE_SHARE_WRITE entfernt - ändert nichts am Verhalten der EXE.
GENERIC_WRITE

Andere müssen natürlich Schreibzugriff bekommen können, aber dieser Auslesecode braucht sowas doch wohl nicht?


Zitat:
Vielleicht findet jemand einen Weg, den "Rechtsklick" zu umgehen.
Welchen Rechtsklick?
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (28. Apr 2012 um 17:28 Uhr)
  Mit Zitat antworten Zitat
hathor
(Gast)

n/a Beiträge
 
#25

AW: Seriennummer der Systemplatte...

  Alt 28. Apr 2012, 17:46
hDevice := GetPhysicalDriveHandle( 0, GENERIC_READ or GENERIC_WRITE ); <-- geht
// hDevice := GetPhysicalDriveHandle( 0, GENERIC_READ ); <--- geht nicht

Rechtsklick bedeutet: Als Administrator starten
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.051 Beiträge
 
Delphi 12 Athens
 
#26

AW: Seriennummer der Systemplatte...

  Alt 28. Apr 2012, 17:55
hDevice := GetPhysicalDriveHandle( 0, GENERIC_READ or GENERIC_WRITE ); <-- geht
// hDevice := GetPhysicalDriveHandle( 0, GENERIC_READ ); <--- geht nicht
hmmm

Zitat:
Rechtsklick bedeutet: Als Administrator starten
Ein Admin-Manifest einbinden?
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
hathor
(Gast)

n/a Beiträge
 
#27

AW: Seriennummer der Systemplatte...

  Alt 29. Apr 2012, 00:00
Mit Manifest geht's.
Angehängte Dateien
Dateityp: zip TEST.zip (634,8 KB, 27x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.051 Beiträge
 
Delphi 12 Athens
 
#28

AW: Seriennummer der Systemplatte...

  Alt 29. Apr 2012, 00:21
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.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz