Ładowanie funkcji z wininet.dll

0

Jak załadować dynamicznie funkcję InternetReadFile z wininet.dll? Próbowałem robić to przez LoadLibrary i GetProcAddress, ale program w momencie ładowania niespodziewanie kończy działanie. Zależy mi na takim załadowaniu funkcji, bez korzystania z wininet.pas.

0

Napisz jak wywołujesz funkcję oraz deklaracje typów dla funkcji.
Wywoływałem mase funkcji w WinApi z *.dll i błędy zdarzały się tylko na parametrach (typ w/w) i zwalnianiu funkcji z biblioteki.

0

A gdzie mogę znaleźć dokładny prototyp funkcji z wininet.dll?

na razie u mnie to wygląda tak:

type
  TSciagnij = function (hFile: HINTERNET; lpBuffer: Pointer;
  dwNumberOfBytesToRead: DWORD; var lpdwNumberOfBytesRead: DWORD): BOOL;

(...)

var
  biblioteka : THandle;
  Sciagnij : TSciagnij;

(...)

biblioteka := LoadLibrary('wininet.dll');

@Sciagnij := GetProcAddress(biblioteka, 'InternetReadFile');
if @Sciagnij = nil then ShowMessage('Nie udało się');
Sciagnij(hData, @Buffer, SizeOf(Buffer), BytesRead);

Czyli dokładnie tak jak to wygląda w Delphi, a czytam na msdn, że nazwy i parametry mogą się różnić.

0
v3ntus napisał(a)

A gdzie mogę znaleźć dokładny prototyp funkcji z wininet.dll?

na razie u mnie to wygląda tak:

type
  TSciagnij = function (hFile: HINTERNET; lpBuffer: Pointer;
  dwNumberOfBytesToRead: DWORD; var lpdwNumberOfBytesRead: DWORD): BOOL;

(...)

var
  biblioteka : THandle;
  Sciagnij : TSciagnij;

(...)

biblioteka := LoadLibrary('wininet.dll');

@Sciagnij := GetProcAddress(biblioteka, 'InternetReadFile');
if @Sciagnij = nil then ShowMessage('Nie udało się');
Sciagnij(hData, @Buffer, SizeOf(Buffer), BytesRead);

Czyli dokładnie tak jak to wygląda w Delphi, a czytam na msdn, że nazwy i parametry mogą się różnić.

Więc ja napisałbym to tak :


type
  TSciagnij = function (hFile: HINTERNET; lpBuffer: Pointer;
  dwNumberOfBytesToRead: DWORD; var lpdwNumberOfBytesRead: DWORD): BOOL;stdcall = nil; 

(...)

var
  biblioteka : THandle;
  Sciagnij : TSciagnij;
  status :LongInt;



biblioteka := LoadLibrary('wininet.dll');
  if biblioteka<>0 then
     begin
       @Sciagnij := GetProcAddress(biblioteka, 'InternetReadFile');

        if not Sciagnij(hData, @Buffer, SizeOf(Buffer), BytesRead) then ShowMessage('funkcja zwróciła FALSE');
lub
        status:=Sciagnij(hData, @Buffer, SizeOf(Buffer), BytesRead);
        if status <>0 then 
          begin
              ... 
          end
        else
          begin
              ...
          end;
      end
     else
      ShowMessage('Nie udało się');
...
{po wykonaniu funkcji zwalnianie uchwytu}}
if Sciagnij <>0 FreeLibrary(biblioteka);

No i niestety nie widzę tu deklaracji zmiennych lub typów dla funkcji :-)
Sciagnij(hData, @Buffer, SizeOf(Buffer), BytesRead);

Ładowanie dynamiczne funkcji z bibliotek wymaga perfekcyjnej precyzji.

doczytałem na necie :

conHandle = InternetOpen("Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);  
...  
hFile = InternetOpenUrl(conHandle, url.c_str(), NULL, 0, INTERNET_FLAG_RELOAD, 0);   
...  
 
if (!InternetReadFile(hFile, buffer, maxBufferSize, &size))  
{  
    // error  
} 

gdzie wynika jak byk , że jako pierwszy parametr musisz podać uchwyt z uruchomienia
hFile = InternetOpenUrl(conHandle, url.c_str(), NULL, 0, INTERNET_FLAG_RELOAD, 0);
a conHandle = InternetOpen("Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
Czyli aby poprawnie wywołać funkcję musisz wywołać jeszcze dwie. :-)

Lepiej kożystaj z gotowych rozwiązań zawartych w delphi albo będziesz musiał nieźle się namęczyć i nigdy nie będziesz pewien czy działa to poprawnie.
Najlepiej stwórz swoją własną bibliotekę i spróbuj załadować ją do swojego programu. A biblioteka niech ma w zasobie obrazki lub tekst.
np.

library Resmodfile;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  Windows,
  SysUtils,
  Classes;

{$R ABJ.RES}

var
 Res : TResourceStream;


procedure zgrajplik(resfile,fullfile,temp:string);stdcall;


begin
  Res := TResourceStream.Create(hInstance, resfile, RT_RCDATA);
  Res.SaveToFile(temp+fullfile);
  Res.Free;
end;
exports
   zgrajplik;

begin




end.

To jest kompletna biblioteka z zasobem ABJ.RES

0

No i niestety nie widzę tu deklaracji zmiennych lub typów dla funkcji :-)

Wkleiłem tutaj tylko fragmenty kodu, w orginale wszystko jest. Problemem jednak było to, że zapomniałem o "stdcall". Teraz wszystko śmiga. Dzięki wielkie za poświęcony czas.

1 użytkowników online, w tym zalogowanych: 0, gości: 1