Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Seriennummer der Systemplatte... (https://www.delphipraxis.net/155119-seriennummer-der-systemplatte.html)

Z4ppy 9. Okt 2010 17:22

Seriennummer der Systemplatte...
 
Ich möchte gerne die Seriennummer derjenigen Festplatte auslesen, auf der das Windoof installiert ist.
Allerdings die echte (vom Hersteller vergebene) Seriennummer, da sich die beim Formatieren ja nicht ändert. Also bitte kein Hinweis auf Themen wie dieses ;)

Ich bin nun auf WMI gestossen und schaffe es auch, darüber (mit der Query 'SELECT Model,SerialNumber FROM Win32_DiskDrive') Modell und Seriennummer auszulesen.
Aber wie finde ich nun herraus, auf welchem der zurückgegebenen Geräte Windoof installiert ist?

MfG Z4ppy

RWarnecke 9. Okt 2010 17:29

AW: Seriennummer der Systemplatte...
 
Frage doch die Systemvariable "SystemRoot" ab.

Z4ppy 9. Okt 2010 17:36

AW: Seriennummer der Systemplatte...
 
Und weiter? Wie finde ich dann raus, auf welchem Gerät die Partition liegt?

MfG Z4ppy

€dit: OK, ich habe hier einen entsprechenden Weg gefunden. Nun hab ich versucht, das in Delphi umzusetzen, allerdings bekomme ich bei der zweiten Query ('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="'+strDeviceID+'"} WHERE AssocClass = Win32_DiskDriveToDiskPartition') den Fehler "Ungültiger Objektpfad" :S

€dit2: Ich habs hingekriegt...

Joerginger 7. Mär 2011 08:30

AW: Seriennummer der Systemplatte...
 
@Z4ppy: würdest Du uns an Deinem Erfolg teilhaben lassen? Ich täte nämlich so eine Routine suchen... Wenn ich mir das von Dir verlinkte VBScript auf dem TechNet Blog ansehe verzweifle ich jetzt schon...

GLG, Joerginger

hathor 7. Mär 2011 09:17

AW: Seriennummer der Systemplatte...
 
Frage:
Aber wie finde ich nun herraus, auf welchem der zurückgegebenen Geräte Windoof installiert ist?

Antwort:
Bei Win32_SystemOperatingSystem - PartComponent stehen die Infos.

Delphi-Quellcode:
uses OleServer, WbemScripting_TLB;
procedure TForm1.Button6Click(Sender: TObject);
resourcestring
  cWQL = 'SELECT PartComponent ' + 'FROM Win32_SystemOperatingSystem';
var
FLocator : ISWbemLocator;
  aSrv : ISWbemServices;
  aObjSet : ISWbemObjectSet;
  pEnum : IEnumVARIANT;
  vOut : OleVariant;
  dwRetrieved : LongWord;
  st : String;
const Computer : String = 'SUPER'; // dein computername
begin
FLocator := CoSWbemLocator.CreateRemote(Computer);
    if FLocator <> nil then
    begin
      aSrv := FLocator.ConnectServer('','','','','','',0,nil);
      aObjSet := aSrv.ExecQuery(cWQL, 'WQL', 0, nil);
      pEnum := aObjSet.Get__NewEnum as IEnumVARIANT;
      pEnum.Next(1, vOut, dwRetrieved);
  end;
 st:= VarToStr(vOut.PartComponent);
 Memo1.lines.add(' PartComponent : '+ st);
 Memo1.lines.add(' HardDisk : '+ Copy(st,Pos('Device\\',st)+8,9));
 Memo1.lines.add(' Partition : '+ Copy(st,Pos('Device\\',st)+19,10));
end;

DelphiSecurity 7. Mär 2011 09:25

AW: Seriennummer der Systemplatte...
 
Mich würde der Quellcode auch interessieren. :wink:

:glaskugel:

hathor 7. Mär 2011 10:37

AW: Seriennummer der Systemplatte...
 
Delphi-Quellcode:
function GetIdeHddSn: string;
const
    IDENTIFY_BUFFER_SIZE = 512;
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;
    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;
        dwReserved: array [0..3] of DWORD;
        bBuffer: array [0..0] of Byte; // Input buffer.
    end;
    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;
    TDriverStatus = packed record
        bDriverError: Byte;
        bIDEStatus: Byte;    // IDE SMART_IDE_ERROR
        bReserved: array [0..1] of Byte;
        dwReserved: array [0..1] of DWORD;
    end;
    TSendCmdOutParams = packed record
        cBufferSize: DWORD;          // bBuffer
        DriverStatus: TDriverStatus;                      
        bBuffer: array [0..0] of BYTE;
    end;

var
    hDevice             : THandle;
    cbBytesReturned     : DWORD;
    SCIP                : TSendCmdInParams;
    aIdOutCmd           : array [0..( SizeOf( TSendCmdOutParams ) +
        IDENTIFY_BUFFER_SIZE -
        1 ) - 1] of Byte;
    IdOutCmd            : TSendCmdOutParams absolute aIdOutCmd;

    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;

begin
    Result := '';                                          
    if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then // Windows NT, Windows 2000
    begin
        // '\\.\PhysicalDrive1\'
        hDevice := CreateFile( '\\.\PhysicalDrive0', GENERIC_READ or
            GENERIC_WRITE,
            FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );
    end
    else // Version Windows 95 OSR2, Windows 98
        hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 );
    if hDevice = INVALID_HANDLE_VALUE then
        Exit;
    try
        FillChar( SCIP, SizeOf( TSendCmdInParams ) - 1, #0 );
        FillChar( aIdOutCmd, SizeOf( aIdOutCmd ), #0 );
        cbBytesReturned := 0;
        // Set up data structures for IDENTIFY command.
        with SCIP do
        begin
            cBufferSize := IDENTIFY_BUFFER_SIZE; // bDriveNumber := 0;
            with irDriveRegs do
            begin
                bSectorCountReg := 1;
                bSectorNumberReg := 1;
                // if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0
                // else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4);
                bDriveHeadReg := $A0;
                bCommandReg := $EC;
            end;
        end;
        if not DeviceIoControl( hDevice, $0007C088, @SCIP, SizeOf(
            TSendCmdInParams ) - 1,
            @aIdOutCmd, SizeOf( aIdOutCmd ), cbBytesReturned, nil ) then
            Exit;
    finally
        CloseHandle( hDevice );
    end;
    with PIdSector( @IdOutCmd.bBuffer )^ do
    begin
        ChangeByteOrder( sSerialNumber, SizeOf( sSerialNumber ) );
        ( PChar( @sSerialNumber ) + SizeOf( sSerialNumber ) )^ := #0;
        Result := PChar( @sSerialNumber );
    end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Label1.Caption:= GetIdeHddSn;
end;

Joerginger 7. Mär 2011 12:00

AW: Seriennummer der Systemplatte...
 
Ich danke herzlich für die CodeSpende(n)!

GLG, Joerginger

user0815 7. Mär 2011 12:25

AW: Seriennummer der Systemplatte...
 
google code search findet auch genau diese function: http://www.google.com/codesearch?as_...ense=&as_case=

hathor 7. Mär 2011 16:42

AW: Seriennummer der Systemplatte...
 
Zitat:

Zitat von Z4ppy (Beitrag 1054704)
Ich bin nun auf WMI gestossen und schaffe es auch, darüber (mit der Query 'SELECT Model,SerialNumber FROM Win32_DiskDrive') Modell und Seriennummer auszulesen.
MfG Z4ppy

SerialNumber
Data type: string
Access type: Read-only
Number allocated by the manufacturer to identify the physical media.
Example: WD-WM3493798728
Windows Server 2003, Windows XP, Windows 2000, and Windows NT 4.0:
This property is not available.


Deshalb function GetIdeHddSn - Siehe oben.

himitsu 8. Mär 2011 06:55

AW: Seriennummer der Systemplatte...
 
Bei Google suchenIOCTL_IDE_PASS_THROUGH = $0004D028 und dort gibt es PassThrough.IDSector.SerialNumber
Bei Google suchenDFP_RECEIVE_DRIVE_DATA = $0007C088 in SendCmdOutParams.IDSector.SerialNumber
Bei Google suchenIOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER = $002D0C10
und über MSDN-Library durchsuchenGetVolumeInformation kommt man an die Seriennummer einer Partition.


Das $0007C088, in Hators Code wäre also ein DFP_RECEIVE_DRIVE_DATA.
(mit 'ner Konstante läßt sich so Einiges manchmal einfacher lesen)

PS: Ich selber versuche zuerst IOCTL_IDE_PASS_THROUGH und wenn das nicht geht, weiche ich in meinem Programm auf DFP_RECEIVE_DRIVE_DATA aus, aber ich glaub das hab ich damals nur so gemacht, da mir IOCTL_IDE_PASS_THROUGH mehr Infos liefert.

Chriscode 27. Apr 2012 11:14

AW: Seriennummer der Systemplatte...
 
Zitat:

Zitat von hathor (Beitrag 1086422)
Delphi-Quellcode:
function GetIdeHddSn: string;

Also es ist mir etwas unangenehm den Thread wieder auszugraben aber da ich die hier gepostete Funktion nicht zum Laufen bekomme ist es womöglich auch für andere interessant die auf dieses Thema stoßen.

Ich möchte genau wie der TE die Seriennummer der Systemplatte auslesen. Und das ganze zuverlässig und auch für Vista und Windows 7.

Problem: Wenn ich die Prozedur so wie geposted per c&p übernehme erhalte ich als Seriennummer nur Sonderzeichen. System windows xp.

Woran könnte das liegen? Und ist die Prozedur überhaupt geeignet auf jedem System zuverlässig zu arbeiten? Oder sollte man zur "Erkennung" des Systems besser die SID nehmen?

Ich habe etwas Angst das die Seriennummer z.B. nicht bei jeder Festplatte vorhanden ist oder nicht bei jedem System ausgelesen werden kann und es so zu Problemen kommt.

Besten Dank,

Gruß
Chris

mkinzler 27. Apr 2012 11:17

AW: Seriennummer der Systemplatte...
 
Unicodeproblem?

himitsu 27. Apr 2012 11:31

AW: Seriennummer der Systemplatte...
 
Definitiv ein Ja.

Mach aus allen Char/CHAR ein AnsiChar und aus PChar ein PAnsiChar

Ob du das String auch noch in ein AnsiString änderst, ist dir überlassen. (ist vermutlich aber nicht nötig)

mkinzler 27. Apr 2012 11:32

AW: Seriennummer der Systemplatte...
 
Zitat:

Ob du das String auch noch in ein AnsiString änderst, ist dir überlassen. (ist vermutlich aber nicht nötig)
Wenn schon, denn schon

Chriscode 27. Apr 2012 11:42

AW: Seriennummer der Systemplatte...
 
Ouch, dummer Fehler. Bitte um Verzeihung.

Vielen Dank für die blitzschnelle Hilfe. Man sollte bei c&p halt trotzdem sein Hirn einschalten :oops:

Gruß
Chris

hathor 27. Apr 2012 18:05

AW: Seriennummer der Systemplatte...
 
...und immer daran denken:
Unter VISTA und WIN 7 laufen manche Programme nur mit Administratorrechten -> Rechtsklick: Als Administrator ausführen.

Luckie 27. Apr 2012 20:13

AW: Seriennummer der Systemplatte...
 
Aber doch nicht, um die Seriennummer auszulesen. Und wenn dem so wäre, hätten die Programme schon unter XP nicht funktioniert, wenn man nur als Benutzer mit eingeschränkten Rechten arbeitet.

himitsu 27. Apr 2012 21:45

AW: Seriennummer der Systemplatte...
 
Zitat:

Zitat von Luckie (Beitrag 1163933)
hätten die Programme schon unter XP nicht funktioniert, wenn ...

Wenn nicht sogar früher. (WinNT + neues Rechtesystem, bzw. ab NTFS oder ab einer bestimmten NTFS-Version)

Luckie 27. Apr 2012 21:47

AW: Seriennummer der Systemplatte...
 
WinNT habe ich nicht erwähnt, weil er da wahrscheinlich noch nicht mal in Planung war. ;)

hathor 28. Apr 2012 01:48

AW: Seriennummer der Systemplatte...
 
Liste der Anhänge anzeigen (Anzahl: 3)
Zitat:

Zitat von Luckie (Beitrag 1163933)
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.

himitsu 28. Apr 2012 09:15

AW: Seriennummer der Systemplatte...
 
Zitat:

GetPhysicalDriveHandle > GENERIC_READ or GENERIC_WRITE
Wozu werden eigentlich die Schreibrechte benötigt?

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 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".

hathor 28. Apr 2012 16:11

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.

himitsu 28. Apr 2012 16:24

AW: Seriennummer der Systemplatte...
 
Zitat:

Zitat von hathor (Beitrag 1164042)
FILE_SHARE_WRITE entfernt - ändert nichts am Verhalten der EXE.

GENERIC_WRITE :zwinker:

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


Zitat:

Vielleicht findet jemand einen Weg, den "Rechtsklick" zu umgehen.
Welchen Rechtsklick?

hathor 28. Apr 2012 16:46

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

himitsu 28. Apr 2012 16:55

AW: Seriennummer der Systemplatte...
 
Zitat:

Zitat von hathor (Beitrag 1164052)
hDevice := GetPhysicalDriveHandle( 0, GENERIC_READ or GENERIC_WRITE ); <-- geht
// hDevice := GetPhysicalDriveHandle( 0, GENERIC_READ ); <--- geht nicht

hmmm :gruebel:

Zitat:

Rechtsklick bedeutet: Als Administrator starten
Ein Admin-Manifest einbinden?

hathor 28. Apr 2012 23:00

AW: Seriennummer der Systemplatte...
 
Liste der Anhänge anzeigen (Anzahl: 1)
Mit Manifest geht's.

himitsu 28. Apr 2012 23:21

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 13:35 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