AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein [AV] Ende einer Prozedur verursacht eine AV...
Thema durchsuchen
Ansicht
Themen-Optionen

[AV] Ende einer Prozedur verursacht eine AV...

Ein Thema von Daniel G · begonnen am 11. Jul 2006 · letzter Beitrag vom 12. Jul 2006
 
Daniel G
(Gast)

n/a Beiträge
 
#1

[AV] Ende einer Prozedur verursacht eine AV...

  Alt 11. Jul 2006, 23:53
N'Abend,

Ich hab' mal wieder ein kleines Problem mit einem C - Code, den ich nach Delphi portiert habe. (Ja, ich weiß, ich sollte diese verdammte Sprache endlich lernen ). Da in dem Original die AV nicht auftritt, denke ich, dass das mit meiner Portierung zu tun hat...

Nevertheless, mein Problem liegt hier:

Delphi-Quellcode:
//----------------------------------------------------------------------------
// ATA-Befehle unter Windows 2000 oder XP versenden
Function TAAMClass.SendCommand_Win2000(pATARegs: PATARegs; var pBuf;
BufSize: Cardinal; pResultSize: Cardinal): Boolean;
var
  Size: Cardinal;
  VirtualAddress: Pointer;
  pAPT: ATA_PASS_THROUGH;
  BytesReturned: LongWord;
  Status: Boolean;
  ReturnedSize: Cardinal;
begin
  Result := FALSE;
  BytesReturned := 0;

  Size := sizeof(ATA_PASS_THROUGH) + BufSize;
  // Datenpuffer mit VirtualAlloc anfordern, damit der Gerätetreiber den Speicher ansprechen kann
  VirtualAddress := VirtualAlloc(NIL, Size, MEM_COMMIT, PAGE_READWRITE);
  pAPT := ATA_PASS_THROUGH(VirtualAddress^);

  if Assigned(@pAPT) then
  begin
      //ZeroMemory(@pAPT, Size);
      // Größe des Datenpuffers setzen
      pAPT.DataBufferSize := BufSize;
      // ATA-Register setzen
      pAPT.IdeReg.bFeaturesReg := pATARegs^.Reg[0];
      pAPT.IdeReg.bSectorCountReg := pATARegs^.Reg[1];
      pAPT.IdeReg.bSectorNumberReg := pATARegs^.Reg[2];
      pAPT.IdeReg.bCylLowReg := pATARegs^.Reg[3];
      pAPT.IdeReg.bCylHighReg := pATARegs^.Reg[4];
      pAPT.IdeReg.bDriveHeadReg := pATARegs^.Reg[5];
      pAPT.IdeReg.bCommandReg := pATARegs^.Reg[6];

      if (pAPT.IdeReg.bCommandReg = $EC) then // ist es ATA IDENTIFY?
      begin
           // Windows XP merkt sich den IDE-Konfigurationssektor
          // daher vorher mit IOCTL_SCSI_RESCAN_BUS für ungültig erklären

          DeviceIoControl(fDriveHandle, IOCTL_SCSI_RESCAN_BUS, NIL, 0, NIL, 0, BytesReturned, 0);
          // eine halbe Sekunde warten
          Sleep(500);
      end;

      BytesReturned := 0;
      
      Status := DeviceIoControl(fDriveHandle, IOCTL_IDE_PASS_THROUGH,
                                    @pAPT, Size, @pAPT, Size, BytesReturned, 0);
      if not Status then
        fError := aec_CommandFailed
      else
      begin
          if Assigned(@pBuf) then
          begin
              if (BufSize <> 0) then
                ZeroMemory(@pBuf, BufSize);
              if (BytesReturned > sizeof(ATA_PASS_THROUGH)) then
              begin
                  ReturnedSize := BytesReturned - sizeof(ATA_PASS_THROUGH);
                  if (pResultSize <> 0) then
                    pResultSize := ReturnedSize;
                  if (ReturnedSize > BufSize) then
                    ReturnedSize := BufSize;
                  Move(pAPT.DataBuffer, pBuf, ReturnedSize);
              end;
          end;
          Result := TRUE;
      end;
      VirtualFree(@pAPT, Size, MEM_RELEASE);
  end
  else
    fError := aec_OutOfMemory;
end;
Nachdem die Funktion durchlaufen wurde, werde ich mit einer AV bombadiert:

Zitat:
---------------------------
Anwendungsfehler
---------------------------
Exception EAccessViolation in Modul bquiet.exe bei 57201020.

Zugriffsverletzung bei Adresse 57202020. Lesen von Adresse 57202020.


---------------------------
OK
---------------------------
Ich tippe mal, ich mache dort irgendwie Mist mit den Pointern. Leider kann ich mit dieser Meldung absolut nichts anfangen, da im Vergleich zu sonst dort ausnahmsweise ne Adress steht und nicht, wie gewohnt, 00000000 ()

Der äquivalente C - Code wäre:

Code:
//----------------------------------------------------------------------------
// ATA-Befehle unter Windows 2000 oder XP versenden

BOOL CWinAta::SendCommand_Win2000(PATARegs pATARegs, void *pBuf, unsigned int BufSize, unsigned int *pResultSize)
{
 
  //---------------------------------------------------
  // Definitionen und Datenstruktur für Windows 2000 und XP
  // aus dem DDK-Headerfile ntddscsi.h übernommen
 
  #define IOCTL_IDE_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x040A, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
  #define FILE_ANY_ACCESS        0
  #define IOCTL_SCSI_RESCAN_BUS  CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS)

  typedef struct
  {
      IDEREGS IdeReg;
      ULONG  DataBufferSize;
      UCHAR  DataBuffer[1];
  } ATA_PASS_THROUGH;
  //---------------------------------------------------
 
 
  BOOL Result = FALSE;
 
  unsigned int Size = sizeof(ATA_PASS_THROUGH) + BufSize;
  // Datenpuffer mit VirtualAlloc anfordern, damit der Gerätetreiber den Speicher ansprechen kann
  ATA_PASS_THROUGH *pAPT = (ATA_PASS_THROUGH *)VirtualAlloc(NULL, Size, MEM_COMMIT, PAGE_READWRITE);
 
  if (pAPT)
  {
      memset(pAPT, 0, Size);
      // Größe des Datenpuffers setzen
      pAPT->DataBufferSize         = BufSize;
      // ATA-Register setzen
      pAPT->IdeReg.bFeaturesReg    = pATARegs->Reg[0];
      pAPT->IdeReg.bSectorCountReg = pATARegs->Reg[1];
      pAPT->IdeReg.bSectorNumberReg = pATARegs->Reg[2];
      pAPT->IdeReg.bCylLowReg      = pATARegs->Reg[3];
      pAPT->IdeReg.bCylHighReg     = pATARegs->Reg[4];
      pAPT->IdeReg.bDriveHeadReg   = pATARegs->Reg[5];
      pAPT->IdeReg.bCommandReg     = pATARegs->Reg[6];

      if (pAPT->IdeReg.bCommandReg == 0xEC) // ist es ATA IDENTIFY?
      {
     // Windows XP merkt sich den IDE-Konfigurationssektor
          // daher vorher mit IOCTL_SCSI_RESCAN_BUS für ungültig erklären
          DWORD BytesReturned = 0;
          (void)DeviceIoControl(Device, IOCTL_SCSI_RESCAN_BUS, NULL, 0, NULL, 0, &BytesReturned, FALSE);
          // eine halbe Sekunde warten
          Sleep(500);  
      }

      DWORD BytesReturned = 0;
     
      BOOL Status = DeviceIoControl(Device, IOCTL_IDE_PASS_THROUGH,
                                    pAPT, Size, pAPT, Size, &BytesReturned, FALSE);
      if (!Status)
        WinAtaErrorCode = aec_CommandFailed;
      else
      {
          if (pBuf)
          {
              if (BufSize)
                memset(pBuf, 0, BufSize);
              if (BytesReturned > sizeof(ATA_PASS_THROUGH))
              {
                  unsigned int ReturnedSize = BytesReturned - sizeof(ATA_PASS_THROUGH);
                  if (pResultSize)
                    *pResultSize = ReturnedSize;
                  if (ReturnedSize > BufSize)
                    ReturnedSize = BufSize;
                   
                  memcpy(pBuf, pAPT->DataBuffer, ReturnedSize);
              }
          }
          Result = TRUE;
      }
      VirtualFree(pAPT, Size, MEM_RELEASE);
  }
  else
    WinAtaErrorCode = aec_OutOfMemory;
 
  return Result;
}
Hat irgendwer eine Idee? Im Anhang ist mal das komplette Delphi - Projekt. Auf das C - Original verlinke ich lieber. Ist von der c't... es handelt sich um die "WinATA.cpp".

Download vpn Heise *klick*

Danke schonmal für's lesen.
Angehängte Dateien
Dateityp: zip bequiet_177.zip (8,4 KB, 1x aufgerufen)
  Mit Zitat antworten Zitat
 


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:36 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 by Thomas Breitkreuz