naja ... das problem sind die Speicher Leaks die dabei übrig bleiben
Ok ... schaun wir uns das im Original noch mal an.
Code:
typedef struct _WINTRUST_DATA {
DWORD cbStruct;
LPVOID pPolicyCallbackData;
LPVOID pSIPClientData;
DWORD dwUIChoice;
DWORD fdwRevocationChecks;
DWORD dwUnionChoice;
union {
struct WINTRUST_FILE_INFO_* pFile;
struct WINTRUST_CATALOG_INFO_* pCatalog;
struct WINTRUST_BLOB_INFO_* pBlob;
struct WINTRUST_SGNR_INFO_* pSgnr;
struct WINTRUST_CERT_INFO_* pCert;
};
DWORD dwStateAction;
HANDLE hWVTStateData;
WCHAR* pwszURLReference;
DWORD dwProvFlags;
DWORD dwUIContext;
} WINTRUST_DATA,
*PWINTRUST_DATA;
was man jetzt wissen muss (oder in einem Debugger anschaut
) ist ...
im c++ wird der Pointer, der über dwUnionChoice gewählt wurde,
an die erste Stelle im Speicher verschoben und die anderen kommen hinten dran
z.B.
dwUnionChoice = 3 (WINTRUST_SGNR_INFO)
dann sieht es im Speicher so aus
Code:
PWINTRUST_SGNR_INFO = $12F310
PWINTRUST_FILE_INFO = $12F318
PWINTRUST_CATALOG_INFO = $12F326
PWINTRUST_BLOB_INFO = $12F334
PWINTRUST_CERT_INFO = $12F342
mit deiner deklaration in Delphi sind aber alle 5 Pointer gleich, sprich alle
sind auf $12F310 (siehe Angefügtes Bild)
Die Funktion WinVerifyTrust() legt im Hintergrund 5 der Strukturen an und weist ihnen Speicher zu.
Jetzt schiebst du die WINTRUST_DATA mit 5 Pointern rein die alle auf den gleichen Platz im Speicher
verweisen !
Wenn dann der Aufruf durch ist versucht die Funktion den Speicher Freizugeben .. doch nanu ... an stelle der
5 Speicheradressen ist nur noch eine da ... naja dann gibt sie halt nur eine von den 5 frei !!!
Und schon iss es passiert ein richtig fettes Leak (rund 2-4MB weil intern noch etliche unterstrukturen da waren)
Wenn ich das mit meiner Hand ausdrücken soll .. würde ich es so erklären:
WinVerifyTrust() hat 5 Löcher wo jeweils nur 1 Finger reinpasst und keines freibleiben darf ...
also musst man 5 Finger reinstecken und wieder rausziehen und nicht einen in 5 Löcher
Der Spass hat mich ne ganze weile beschäftigt ....
Der Trick ist nun ... wie du dir sicherlich schon denken kannst... es folgender maßen zu deklarieren
Delphi-Quellcode:
dwUnionChoice: DWORD; // benötigt, welche Datenstruktur soll verwendet werden
pWTDINFO: pointer; // Pointer zu einer der Wintrust_X_Info Strukturen
pFake: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird
pFake1: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird
pFake2: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird
pFake3: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird
Um das zu erkennen war wirklich harte Arbeit Debugger notwendig.