String Table Resourcen hinzufügen

Rettig

Grünschnabel
Hallo,
ich möchte gerne in einer fertigen DLL neue Strings zur String Table Resource hinzufügen. Keine bestehenden Strings ändern, sondern neue hinzufügen.
 
"Fertige DLL" bedeutet, keine Source-Änderung? Von einem anderen Programm aus die Resourcen in der DLL ändern?

Wenn du es selber programmieren willst, musst du in Richtung BeginUpdateResource/UpdateResource/EndUpdateResource schielen. Und das Format von String-Tables kennen (Unicode-Strings, 16 Strings sind in einem Block gebündelt, vorne an ist ein Längen-WORD a 16bit).
Dann liest du den String-Table der DLL aus (bekommst einen Speicherblock), parst ihn, setzt deine neuen Strings ein und schreibst den String-Table mit den Update-Funktionen wieder zurück.

Mit einem Wort: Heftig. Aber. Machbar.

Wenn es nur um ein zwei Strings einmal geht, such den ResourceHacker. Damit kannst du das auch machen. Und ist schon fertig.
 
Hi

Ich sitze gerade am gleichen Problem.
Allerdings möchte ich nicht Strings in die Stringtable, sondern von mir selbst erstellte Resourcen in der compilierten DLL hinzufügen.
Habe jetzt schon alles rund um UpdateResource() probiert, aber irgendwie klappt es immer noch nicht so richtig. Die neuen Resourcen (binary data) werden zwar hinzugefügt, aber ich kann sie dann in der DLL nicht korrekt ansprechen.

Statt:
  1. erster string
  2. zweiter string
  3. ....
  4. n-ter string

Erhalte ich immer:
erster string PAD zweiter string PAD ... PAD n-ter string

:confused:

So langsam bin ich mit meinem Latein am Ende!
Vielleicht kann mir ja einer helfen?!
 
Wie gesagt, das Speicherlayout der Resourcen ist etwas eigen. Besonders bei den Strings:

Also, in den Resourcen sind immer 16 Strings zu einem Block zusammengefasst:


int nBlock = dwResourceId / 16 + 1;
int nNum = dwResourceId & 0x0f;

Wenn du also einen einzelnen String eintragen willst, ist nBlock die Resource-ID, die anzulegen ist!
In einem Block sind 16 Strings so gespeichert:
Ein WORD (16bit) als Länge des Strings, danach der String als Unicode. Ist ein String nicht vorhanden, ist da nur ein WORD mit Wert 0. Die Strings sind NICHT null-terminiert.

ES GIBT KEINE MÖGLICHKEIT, EINEN LEEREN STRING VON EINEM NICHT VORHANDENEN ZU UNTERSCHEIDEN!

D.h., wenn du einen einzelnen String eintragen willst, musst du 15 leere drumrum setzen.


Hier mal spasshalber ein Schnipsel, wie man einen String per Hand aus den Resourcen lädt:

Code:
std::string CWinUtils::LoadStringEx( DWORD dwResourceId, WORD wLanguage )
{

  std::string   strTemp( "" );

  int nBlock = dwResourceId / 16 + 1;
  int nNum = dwResourceId & 0x0f;

  HRSRC hRes = FindResourceEx( GetModuleHandle( NULL ), RT_STRING, MAKEINTRESOURCE( nBlock ), wLanguage );

  if ( hRes == NULL )
  {
    return "";
  }

  HGLOBAL hGlobal = LoadResource( GetModuleHandle( NULL ), hRes );
  if ( hGlobal == NULL )
  {
    return "";
  }

  WCHAR*   pData = (WCHAR*)LockResource( hGlobal );

  WORD    wStringLength = 0;
  if ( pData )
  {
    
    for ( int i = 0; i < nNum; ++i )
    {
      wStringLength = (WORD)*pData;

      pData += 1 + wStringLength;
    }
    wStringLength = (WORD)*pData;
    ++pData;

    char*      pTemp = new char[wStringLength + 1];

    WideCharToMultiByte( CP_ACP, 0, (WCHAR*)pData, wStringLength, pTemp, wStringLength, 0, 0 );

    pTemp[wStringLength] = 0;

    strTemp = pTemp;

    delete[] pTemp;
  }

  UnlockResource( hGlobal );
  FreeResource( hGlobal );

  return strTemp;

}
 
@Endurion: Danke für die Tips!

die probleme beim speichern der resourcen gab's, weil die strings nicht null-terminiert sind! ;-]
also hab ich sie mir selber terminiert!
jetzt klappt's! :)
 
Zurück