2012-01-12 6 views
5

L'esecuzione del codice seguente nella piattaforma XE2 Win32 di Delphi funziona. Tuttavia, lo stesso codice compilato in piattaforma Win64 causerà violazione di accesso in "EnumRCDataProc" se l'esecuzione in modalità di debug:Delphi XE2: richiama WinAPI EnumResourceNames causa violazione di accesso nella piattaforma Win64

procedure TForm2.Button1Click(Sender: TObject); 
    function EnumRCDataProc(hModule: THandle; lpszType, lpszName: PChar; lParam: 
     NativeInt): Boolean; stdcall; 
    begin 
    TStrings(lParam).Add(lpszName); 
    Result := True; 
    end; 

var k: NativeInt; 
    L: TStringList; 
    H: THandle; 
begin 
    H := LoadPackage('resource.bpl'); 
    L := TStringList.Create; 
    try 
    EnumResourceNames(H, RT_RCDATA, @EnumRCDataProc, NativeInt(L)); 
    ShowMessage(L.Text); 
    finally 
    L.Free; 
    UnloadPackage(H); 
    end; 
end; 

Quando eseguire il debug del codice Delphi XE2 IDE su piattaforma Win64, ho trovato il valore di hModule in EnumRCDataProc non corrisponde alla variabile H. Sospetto che possa essere qualcosa di sbagliato nei parametri che ho costruito per EnumRCDataProc. Tuttavia, non riesco a capire come. Qualche idea?

risposta

5

Il problema è che è stata eseguita la procedura locale EnumRCDataProc. Hai bisogno di spostarlo al di fuori del metodo.

function EnumRCDataProc(hModule: HMODULE; lpszType, lpszName: PChar; lParam: 
    NativeInt): BOOL; stdcall; 
begin 
    TStrings(lParam).Add(lpszName); 
    Result := True; 
end; 

procedure TForm2.Button1Click(Sender: TObject); 
var k: NativeInt; 
    L: TStringList; 
    H: HMODULE; 
begin 
    H := LoadPackage('resource.bpl'); 
    L := TStringList.Create; 
    try 
    EnumResourceNames(H, RT_RCDATA, @EnumRCDataProc, NativeInt(L)); 
    ShowMessage(L.Text); 
    finally 
    L.Free; 
    UnloadPackage(H); 
    end; 
end; 

A prima vista mi aspettavo che il compilatore emetterebbe un errore con il codice:

E2094 procedura/funzione Local 'Callback' assegnato alla variabile procedura

ma lo fa non farlo Ho scavato un po 'più a fondo e ho scoperto che il parametro di callback per EnumResourceNames è dichiarato come tipo Pointer. Se la traduzione dell'intestazione avesse dichiarato questo come parametro di callback digitato, il messaggio di errore sopra riportato sarebbe stato effettivamente emesso. A mio avviso la traduzione dell'intestazione è scarsa a questo riguardo. Sembra che ci sia molto poco da guadagnare dall'abbandono della sicurezza del sistema dei tipi.

Il fatto che il codice funzioni con codice a 32 bit è solo una felice coincidenza che si basa sui dettagli di implementazione. La tua fortuna si esaurisce a 64 bit. Di nuovo, se il sistema di controllo dei tipi fosse stato abilitato, il compilatore avrebbe potuto dirti cosa c'era che non andava immediatamente.

Alcuni altri commenti:

  1. Il EnumRCDataProc ha un paio di tipi errati nella sua dichiarazione: hModule dovrebbero essere di tipo HMODULE e il risultato della funzione dovrebbe essere BOOL.
  2. LoadPackage è un approccio piuttosto pesante per ottenere un handle di modulo. Preferirei vedere LoadLibraryEx con le opzioni LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE e LOAD_LIBRARY_AS_IMAGE_RESOURCE.
+0

Il compilatore non dovrebbe lamentarsi di ciò. La funzione enum locale non è affatto un problema. – OnTheFly

+0

Indovina perché emette il messaggio: p – OnTheFly

+1

Finché la richiamata non accede a nessuna forma che non dovrebbe costituire un problema. Poi di nuovo, solo a tale scopo, prendere la callback è la cosa giusta. Cosa significa over-strike? Ciò annulla la parte della risposta sopra? –

Problemi correlati