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 Hilfe bei Übersetzung von C nach Delphi (https://www.delphipraxis.net/117245-hilfe-bei-uebersetzung-von-c-nach-delphi.html)

c.wuensch 14. Jul 2008 21:11


Hilfe bei Übersetzung von C nach Delphi
 
Hi an alle,

Ich hab die Frage hier schonmal gestellt, aber mach jetzt nochmal einen neuen Thread damit der Titel besser passt.

Ich möchte den Power-Status (aktiv / Standby) einer Festplatte auslesen.

Folgender Delphi-Code bewirkt, dass die Platte in Standby versetzt wird (Dank an hathor):
Delphi-Quellcode:
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;  
 
const  
  BufferSize = SizeOf(TIDERegs)+4;  
  IOCTL_IDE_PASS_THROUGH       = $0004d028;

 
implementation

 
{$R *.dfm} 

 
Function IdeRegPassThrough(Device: String; var ideregs: TIDERegs ): Boolean;  
var  
  ret:BOOL;  
  hDevice : THandle;  
  cbBytesReturned : DWORD;  
  pInData : PIDERegs;  
  pOutData : Pointer;  
  Buffer : Array[0..BufferSize-1] of Byte;  
begin  
  Result := False;  
  FillChar(Buffer,BufferSize,#0);  

 
  hDevice := CreateFile( PChar(Device), GENERIC_READ or GENERIC_WRITE,  
    FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );  
  if hDevice=INVALID_HANDLE_VALUE then Exit;  
  try  
    pInData := @Buffer;  
     pOutData := pInData;  
    pInData^ := ideregs;  
    ret := DeviceIoControl( hDevice, IOCTL_IDE_PASS_THROUGH, @Buffer, BufferSize, @Buffer, BufferSize, cbBytesReturned, nil );  
    if not ret then begin  
      Exit;  
    end;  
    ideregs := PIDERegs(pOutData)^;  
  finally  
    CloseHandle(hDevice);  
  end;  
  Result := True;  
end;  

function SendToSleep(Device: String): Boolean;
var  
  ideregs : TIDERegs;  
begin  
  Result := False;  
  with ideregs do  
  begin  
    bFeaturesReg    := 0;  
    bSectorCountReg := 0;  
    bSectorNumberReg := 0;  
    bCylLowReg      := 0;  
    bCylHighReg     := 0;  
    bDriveHeadReg   := $A0;  
    bCommandReg     := $E6;  
    bReserved       := 0;  
  end;  
  if not IdeRegPassThrough(Device, ideregs ) then Exit else Result := True;  
end;
 
//Label1.caption:= BoolToStr(SendToSleep('\\.\PhysicalDrive0'));

Folgender C-Code stammt aus dem Linux-Tool hdparm und bewirkt das Auslesen des Status:
Code:
  __u8 args[4] = {ATA_OP_CHECKPOWERMODE1,0,0,0};
  const char *state;
  if (do_drive_cmd(fd, args)
    && (args[0] = ATA_OP_CHECKPOWERMODE2) /* (single =) try again with 0x98 */ 
    && do_drive_cmd(fd, args)) { 
      err = errno;
      state = "unknown";
    } else { 
      state = (args[2] == 255) ? "active/idle" : "standby";
    } 
  printf(" drive state is: %s\n", state);
Hier sind die Flags dazu:
Code:
ATA_OP_CHECKPOWERMODE1   = 0xe5,
ATA_OP_CHECKPOWERMODE2   = 0x98,
ATA_OP_STANDBYNOW1      = 0xe0,
ATA_OP_SLEEPNOW1      = 0xe6, // das hier wird im Delphi-Code schonmal benutzt
ATA_OP_SLEEPNOW2      = 0x99,
ATA_OP_SETIDLE1      = 0xe3,
Und hier ist die Funktion do_drive_cmd, die dadurch aufgerufen wird:
Code:
int do_drive_cmd (int fd, unsigned char *args)
{
#ifdef SG_IO

   struct ata_tf tf;
   void *data = NULL;
   unsigned int data_bytes = 0;
   int rc;

   if (args == NULL)
      goto use_legacy_ioctl;
   /*
    * Reformat and try to issue via SG_IO:
    */
   if (args[3]) {
      data_bytes = args[3] * 512;
      data      = args + 4;
   }
   tf_init(&tf, args[0], 0, args[1]);
   tf.lob.feat = args[2];
   if (tf.command == ATA_OP_SMART) {
      tf.lob.nsect = args[3];
      tf.lob.lbal = args[1];
      tf.lob.lbam = 0x4f;
      tf.lob.lbah = 0xc2;
   }

   rc = sg16(fd, SG_READ, &tf, data, data_bytes, 0);
   if (rc) {
      if (rc == -1)
         goto use_legacy_ioctl;
      errno = rc;
      rc = -1;
   } else if (tf.status & (ATA_STAT_ERR | ATA_STAT_DRQ)) {
      if (verbose)
         fprintf(stderr, "I/O error, ata_op=0x%02x ata_status=0x%02x ata_error=0x%02x\n",
            tf.command, tf.status, tf.error);
      errno = EIO;
      rc = -1;
   }

   args[0] = tf.status;
   args[1] = tf.error;
   args[2] = tf.lob.nsect;
   return rc;

use_legacy_ioctl:
#endif /* SG_IO */
   if (verbose)
      fprintf(stderr, "Trying legacy HDIO_DRIVE_CMD\n");
   return ioctl(fd, HDIO_DRIVE_CMD, args); // das ist wohl die entscheidende Zeile!
}
So, und jetzt die Frage:
Wie kann man obigen Delphi-Code entsprechend abwandeln, so dass er den Status abfragt?

Freue mich über jede Antwort!
Cu, Chris

c.wuensch 16. Jul 2008 14:25

Re: Hilfe bei Übersetzung von C nach Delphi
 
Hmm, das war vielleicht etwas zu viel...
Kann mir denn vielleicht wenigstens jemand einen Tipp geben, wie ich bei diesem Aufruf den Rückgabewert verarbeiten kann?
Delphi-Quellcode:
    ret := DeviceIoControl( hDevice, IOCTL_IDE_PASS_THROUGH, @Buffer, BufferSize, @Buffer, BufferSize, cbBytesReturned, nil );
ret ist ja nur eine Boolean-Variable, also wird der Wert wohl in einem der Puffer zu finden sein. Aber mit diesen Pointern usw. kenn ich mich nicht aus. Wie kriege ich diesen Wert denn in einen normalen Datentyp, wie bsp. Integer oder String konvertiert?

Cu, Chris


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:25 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