Announcement

Collapse
No announcement yet.

C++ 2 Delphi

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • C++ 2 Delphi

    Hallo,

    ich habe mal wieder ein kleines Problem mit C++ Code, den ich in Delphi einfügen will:

    <pre>
    #define VAR_2 0x00008300
    #define VARIABLE (ULONG) CTL_CODE (VAR_2, 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
    </pre>

    Ich habe es mit
    <code>
    const
    variable = $01
    </code>
    versucht, aber scheinbar funktioniert das nicht...

    Tschüss Tim

  • #2
    const<br>
    VAR_2 = $00008300;<br>
    VARIABLE = DWORD($xxxxxxxx);

    CTL_CODE ist nur ein Bitschiebemakro. Es loest sich zu einer schlichten Zahl auf. Schau dir mal die C-Deklaration des Makros an. Im Augenblick habe ich es nicht zur Hand. METHOD_BUFFERED und FILE_ANY_ACCESS sind auch nur Zahlenkonstanten.<br>
    Insgesamt setzt CTL_CODE die vier Parameterzahlen als Bitfelder in einer 32-Biz-Zahl ein.<br>
    Die DWORD-Umtypung verhindert das VARIABLE vom Typ Int64 werden kann

    Comment


    • #3
      Hallo,

      ich habe folgenden funktionsfähigen Source in C:

      <pre>
      #define LOGBUFSIZE ((ULONG)(64*0x400-(3*sizeof(ULONG)+1)))

      #pragma pack(1)
      typedef struct {
      ULONG seq;
      LARGE_INTEGER perftime;
      LARGE_INTEGER datetime;
      char text[0];
      } ENTRY, *PENTRY;
      #pragma pack()

      char Stats[ LOGBUFSIZE ];
      DWORD StatsLen;

      if (! DeviceIoControl (SysHandle, 2,
      NULL, 0, &Stats, sizeof Stats,
      &StatsLen, NULL ))
      {
      Abort( hWnd, _T("Couldn't access device driver (GetStats 2900)"),
      GetLastError() );
      return TRUE;
      }

      if ( StatsLen == 0 )
      break;

      UpdateStatistics( hWnd, hWndList, FALSE );

      void UpdateStatistics( HWND hWnd, HWND hList, BOOL Clear )
      {
      PENTRY ptr;

      // Add all List items from Stats[] data
      for ( ptr = (void *)Stats; (char *)ptr < min(Stats+StatsLen,Stats + sizeof (Stats)); )
      {
      // Add to list
      ULONG len = strlen(ptr->text);

      itemsAdded |= ListAppend( hList, ptr->seq, ptr->perftime.QuadPart,
      ptr->datetime.QuadPart, ptr->text );

      ptr = (void *)(ptr->text + len + 1);
      }

      // Empty the buffer
      StatsLen = 0;
      }
      </pre>

      Nun habe ich versucht diesen in Delphi zu übersetzen, erhalte aber
      immer "Keine Daten empfangen: 87" od. 0

      Comment


      • #4
        <pre>
        const
        LOGBUFSIZE = ULONG (64*$400 -(3* sizeOf(ULONG)+1));

        type
        Eingang = packed Record // jeder Record ist 4 Byte??
        seq : uLong; // Cardinal 32-bit
        perftime : Int64; // represent a 64-bit signed integer value
        datetime : Int64;
        text : array[0..0] of Char; // PChar;
        end; // = 160-bit = 20 Byte ?
        var
        Stats : array[0..LOGBUFSIZE-1] of Char;
        StatsLen : DWORD;
        procedure UpdateStatistics;
        var
        ptr : Eingang;
        begin
        with Form1.ListView1.items do
        // for ( ptr = (void *)Stats; (char *)ptr <
        // min(Stats+StatsLen,Stats + sizeof (Stats)); )
        begin
        // Add to list
        Add.caption:= IntToStr (ptr.seq);
        Add.SubItems.Add (IntToStr (ptr.perftime));
        Add.SubItems.Add (IntToStr (ptr.datetime));
        Add.SubItems.Add (ptr.text);
        end;

        StatsLen:= 0;
        end;

        if not DeviceIoControl (hVxDHandle, 2, nil, 0,
        @Stats,
        sizeOf (Stats),
        StatsLen, nil) then
        Application.MessageBox ('Fehler DIOC!','DIOC2',
        mb_ok + mb_iconError);

        if StatsLen <> 0 then
        UpdateStatistics
        else
        Application.MessageBox (PChar ('Keine Daten empfangen: '+
        IntToStr (GetLastError)),
        'BytesReturned = 0',
        mb_ok + mb_iconError);
        </pre>

        Woran könnte das liegen?

        Tschüss Ti

        Comment


        • #5
          Hallo,<br>
          <br>
          wenn ich mal kurz mit dem Makro und dessen 'Übersetzung' nach Delphi dienen dürfte ;-)<br>
          <br>
          <pre>
          #define IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER CTL_CODE(IOCTL_STORAGE_BASE, 0x0304, METHOD_BUFFERED, FILE_ANY_ACCESS)
          <br>
          wird zu
          <br>
          IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER =
          ((IOCTL_STORAGE_BASE) shl 16)
          or
          (($304) shl 2)
          or
          ((METHOD_BUFFERED))
          or
          ((FILE_ANY_ACCESS shl 14));
          <br>
          Das eigentliche Makro sieht so aus:
          <br>
          #define CTL_CODE( DeviceType, Function, Method, Access ) ( \
          ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
          )
          <br>
          wobei die \ nur als Kennung für die Fortsetzung in der nächsten Zeile dienen (siehe auch .REG Dateien)
          </pre>
          <br>
          Ciao<br>
          Chri

          Comment


          • #6
            Hi Tim,<br>
            <br>
            Fehler 87 heisst ja ERROR_INVALID_PARAMETER, als stimmt einer der Paramter beim Aufruf nicht.<br>
            Hast Du die beim Aufruf von DeviceIoControl schon alle überprüft. Ich hab' da so ganz besonders das hVxDHandle im Verdacht.<br>
            Was bedeutet eingentlich der Kommentar:<br>
            packed Record // jeder Record ist 4 Byte?? <br>
            <br>
            Ciao<br>
            Chri

            Comment


            • #7
              Hallo Christian,

              ich denke es muss irgendwei an den Puffern liegen, denn alle anderen DIOC-Aufrufe funktionieren eigentlich tadellos, d.h. diese mit DIOC (hVxDHandle, nil, 0, 0, 0, StatsLen, nil);

              Der VxD source sieht so aus:
              <pre>
              DWORD
              OnW32Deviceiocontrol(
              PIOCTLPARAMS pEingang
              )
              {
              PLOG_BUF old;

              switch( pEingang->dioc_IOCtlCode )
              {
              case 0:
              return ERROR_SUCCESS;

              case 1:
              // setzt alles auf "0" zurück
              Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );
              while ( Log->Next )
              {
              // Release the next entry.
              old = Log->Next;
              Log->Next = old->Next;
              Signal_Semaphore( LogMutex );
              PageFree( old->Handle, 0 );
              Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );
              NumLog--;
              }
              Log->Len = 0;
              Signal_Semaphore( LogMutex );
              Sequence = 0;
              return ERROR_SUCCESS;

              case 2:
              // Copy buffer into user space.
              Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );

              // wenn der VxD Puffer größer als der zur Verfügungstehende
              // ist
              if ( LOGBUFSIZE > pEingang->dioc_cbOutBuf )
              {
              // wenn der Puffer zu klein ist, senden wir folgenden
              // Fehler zurück:
              Signal_Semaphore( LogMutex );
              return ERROR_INSUFFICIENT_BUFFER;
              }
              else // Log->Len sollte 0 sein, durch ZeroStats // Log->Next ist beim Starten auch 0 !!
              if ( Log->Len || Log->Next )
              {
              // ansonsten wird zu einem neuen Puffer gewechselt:
              FilemonNewLog();

              // Fetch the oldest buffer to give to caller.
              old = FilemonOldestLog();
              Signal_Semaphore( LogMutex );

              // Copy it into the caller's buffer. (OutBuffer)
              memcpy( pEingang->dioc_OutBuf, old->Data, old->Len );

              // Return length of copied info. (BytesReturned)
              *pEingang->dioc_bytesret = old->Len;

              // Deallocate the buffer.
              PageFree( old->Handle, 0 );
              }
              else
              {
              // There is no #unread# data. (BytesReturned, StatsLen = 0)
              Signal_Semaphore( LogMutex );
              *pEingang->dioc_bytesret = 0;
              }
              return ERROR_SUCCESS;
              </pre&gt

              Comment


              • #8
                Bei "There is no #unread# data", also Log->Len = Log->Next, wird 0 als StatsLen zurückgegeben, aber weshalb?

                Irgendwo hatte ich gelesen, dass jeder Record 4 Byte hat, ich suche nochmal nach...

                Tschüss Ti

                Comment


                • #9
                  Hallo Tim,<br>
                  <br>
                  erst einmal noch zum Record.<br>
                  Record leitet in diesem Falle ja nur die Deklaration einer selbstdefinierten Datenstruktur (Record) ein. Die Grösse hängt also unmittelbar mit den darin verwendeten Feldern zusammen.<br>
                  Mir ist allerdings noch aufgefallen, dass Du an der Stelle, wo ein Pointer auf die ENTRY gefordert ist, die Struktur selbst angibst. PENTRY hast Du auch gar nicht definiert.<br>
                  Aber ansonsten...<br>
                  Was verbirgt sich denn hinter der DIOC Funktion 2 die Du da aufrufst?<br>
                  Mit der Info könnte man der Sache vielleicht näher kommen.<br>
                  <br>
                  Ciao<br>
                  Chri

                  Comment


                  • #10
                    Hallo,

                    ich habe es inzwischen soweit geschafft, dass ich folgendes Ergebnis
                    erhalte:
                    Eingang.seq -> 512<br>
                    Eingang.perftime -> 0<br>
                    Eingang.datetime -> 7204330155230032
                    Eingang.text -> <br>

                    Irgendwas haut mit der Umwandlung (Puffer-/Record-Deklaration)
                    nicht richtig hin...

                    Ich dachte PENTRY sei überflüssig, wie müsste dass ganze in Delphi aussehen, ich hatte folgende Grundlage:<br>
                    C:<pre>
                    #pragma pack(1)
                    struct WohntIn
                    {
                    int PLZ; // 4 Byte
                    char Landkennung; // 1 Byte
                    };
                    #pragma pack(8)
                    </pre>Delphi:
                    <pre>
                    type
                    WohntIn = packed record
                    PLZ: Integer; // 4 Byte
                    Landkennung: Char; // 1 Byte
                    end;
                    </pre>

                    Eigentlich geht es bei diesem VxD, um das Aufzeichnen von Datei-Aktivitäten, d.h. ich versuche in Delphi ein Programm zu schreiben, dass alle Kopier- und Löschvorgänge aufzeichnet und u.U. stoppt.<br>
                    Nun bin ich mir aber nicht ganz im klaren, wie die Daten vom VxD zur Delphi-Applikation gelangen und konvertiert werden müssen.

                    Im wesentlichen geht es bei DIOC 2, um "FilemonNewLog", dass aufgerufen wird, wenn der momentanige Puffer voll ist:
                    <pre>
                    // Called when the current buffer has filled up. This moves us to the
                    // pre-allocated buffer and then allocates another buffer.
                    // Returns FALSE if another thread is already allocating a buffer.
                    </pre>

                    und falls der Puffer nicht voll ist, die Daten in OutBuffer zu kopieren:<br>
                    // Copy it into the caller's buffer. (OutBuffer)<br>
                    memcpy( pEingang->dioc_OutBuf, old->Data, old->Len );<br><br>

                    // Return length of copied info. (BytesReturned)<br>
                    *pEingang->dioc_bytesret = old->Len; <br>

                    Tschüss Ti

                    Comment


                    • #11
                      Hallo,

                      PENTRY sieht jetzt folgendermaßen aus, dies scheint trotzdem nicht zu funktionieren...
                      <pre>
                      const
                      LOGBUFSIZE = ULONG (64*$400 -(3* sizeOf(ULONG)+1));

                      type
                      Eingang = packed Record
                      seq : uLong; // Cardinal 32-bit
                      perftime : Int64; // represent a 64-bit signed integer value
                      datetime : Int64;
                      text : array[0..0] of Char; // PChar;
                      end; // = 160-bit = 20 Byte
                      PENTRY = ^Eingang;
                      </pre>

                      Langsam gehen mir die Ideen aus.

                      Tschüss Ti

                      Comment


                      • #12
                        Hallo Tim,<br>
                        <br>
                        wenn Du magst, kannst Du mir ja mal beide Sourcen (C++ und Delphi) schicken ([email protected]), dann kann ich sie mir auch noch mal gezielt anschauen. So sind mir nämlich sonst auch die Ideen ausgegangen.<br>
                        <br>
                        Ciao<br>
                        Chri

                        Comment


                        • #13
                          Hallo,

                          Wie müsste man folgenden Teil in Delphi "übersetzen"?

                          <pre>
                          #pragma pack(1)
                          typedef struct {
                          ULONG seq;
                          LARGE_INTEGER perftime;
                          LARGE_INTEGER datetime;
                          char text[0];
                          } ENTRY, *PENTRY;
                          // typedef ENTRY * PENTRY;
                          #pragma pack()<br><br>

                          #define LOGBUFSIZE ((ULONG)(64*0x400-(3*sizeof(ULONG)+1)))<br><br>

                          PENTRY ptr;
                          char Stats[ LOGBUFSIZE ];
                          DWORD StatsLen;

                          for ( ptr = (void *)Stats; (char *)ptr < min(Stats+StatsLen,Stats + sizeof (Stats)); )
                          { ...
                          </pre>

                          <i><b><u>Delphi:</i></u></b>
                          <pre>
                          LOGBUFSIZE = ULONG (64*$400 -(3* sizeOf(ULONG)+1)); // ??? <br><br>

                          type
                          Eingang = packed Record
                          seq : uLong; // Cardinal 32-bit
                          perftime : Int64; // represent a 64-bit signed integer value
                          datetime : Int64;
                          text : array[0..0] of Char; // PChar;
                          end; // = 160-bit = 20 Byte
                          PENTRY = ^Eingang; // oder: Eingang^ ????
                          var
                          Stats : array[0..LOGBUFSIZE-1] of Char;
                          StatsLen : DWORD;


                          for ptr:= ??? < ??? do
                          </pre>

                          Tschüss Ti

                          Comment


                          • #14
                            Anmerkung: "char text[0]" belegt in C keinen Platz im struct. Es ist ein Trick dem Speicher hinter dem struct einen Namen zu geben.<br>
                            Das Ganze ist also eine Datenstruktur mit variabler Laenge. Ein fester Header gefolgt von einem C string.<br>
                            Du musst also eine Variable vom Typ PENTRY anlegen und genuegend Speicher dafuer alloziieren

                            Comment


                            • #15
                              Hallo Robert,

                              Danke für den Hinweis.

                              Wie kann man nun Speicher für PENTRY reservieren (mit VirtualAlloc)? Deshalb funktioniert wohl <i>"text : array[0..0] of Char bzw. PChar;"</i> nicht...

                              Tschüss Ti

                              Comment

                              Working...
                              X