Link to home
Start Free TrialLog in
Avatar of m_adil
m_adil

asked on

Dll Problem

Hi,
I've develpoed a dll that contains a form and some edit boxes. It reads and writes some values from registry. The dll is working fine with an Delphi application, but when I try this with rundll32, it gives me an error **Invalid page fault error**
Infact Rundll32 correctly executes the dll (Correctly reads & writes values to the registry). The error comes when I close the form in the dll.

what could be the possible error.
Avatar of Motaz
Motaz

Did you free any objects in form OnClose event or OnCloseQuery ?

Motaz
Delphi had in earlier versions some problems with thread-saftey. This could be PERHAPS a reason for you problem:

1. Don't use sharemem.pas
2. Don't pass 'string'-vars in DLL-calls, use PChars instead

Try this. If it don't helps give us further information on your configuration (Delphi-Version, Windows etc...)
Are you starting a specific function with RunDll? Or only the initialization of the DLL? If you start a specific function, please show us the code of the function.
Then you can try it with removing the code in the function (or in the initialization). Does it work then? If yes: Add the code again, but only half of the code. This way you should find the line which is responsible for the problem.

Regards, Madshi.
Avatar of m_adil

ASKER

I'm using Delphi-3, win-95/NT-4.
>> Delphi had in earlier ...
I'm not passing any var. to dll.

Yes Madshi I'm calling a specific function with RunDll. First I wrote a starting function that returns True if user clicks ok and False if cancel but afterwards I changed the function to procedure but the problemd persists in both cases.

Here is the DLL code
=================================
unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Registry, StdCtrls, ExtCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    Panel1: TPanel;
    Button1: TButton;
    Button2: TButton;
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Label5: TLabel;
    fName: TEdit;
    Pwd: TEdit;
    GroupBox2: TGroupBox;
    CheckBox1: TCheckBox;
    Label6: TLabel;
    proxy: TEdit;
    Label7: TLabel;
    port: TEdit;
    procedure ReadRegistry;
    procedure CheckBox1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure WriteRegistry;
  private
    { Private declarations }

  public
    { Public declarations }
  end;

// extern DLL function declaration
procedure loadSettings; stdcall;
//function loadSettings:Boolean; stdcall;


var
  Form1: TForm1;
implementation

{$R *.DFM}

procedure TForm1.ReadRegistry;
var
   Reg:TRegistry;
begin
Reg:= TRegistry.Create;
Reg.RootKey:= HKEY_CLASSES_ROOT;
if Reg.OpenKey('CLSID\{BDE17913-32E5-11d2-8D84-00400557ABF6}\Settings', FALSE) then
begin
   fName.Text:= Reg.ReadString('userName');
   proxy.Text:= Reg.ReadString('proxy');
   port.Text := Reg.ReadString('port');
   CheckBox1.Checked:= Reg.ReadBool('Firewall');
end;

Reg.CloseKey;
Reg.Destroy;

end;

//function loadSettings:Boolean;
procedure loadSettings;
begin
Try
  try
     Form1:= TForm1.Create(Application);
     Form1.ReadRegistry;
     if Form1.ShowModal = mrOK then
        Form1.WriteRegistry;

  finally
     Form1.Free;
  end;

Except
   on E: Exception do
      MessageDlg('An error occured '+ E.Message, mtError, [mbok], 0);
end; //except

end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
proxy.Enabled:= CheckBox1.Checked;
port.Enabled := CheckBox1.Checked;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
//Form1.WriteRegistry;
end;

procedure TForm1.WriteRegistry;
var
   Reg:TRegistry;
begin
Reg:= TRegistry.Create;
Reg.RootKey:= HKEY_CLASSES_ROOT;
if Reg.OpenKey('CLSID\{BDE17913-32E5-11d2-8D84-00400557ABF6}\Settings', FALSE) then
begin
   Reg.WriteString('userName',fName.Text);
   Reg.WriteString('proxy', proxy.Text);
   Reg.WriteString('port', port.Text);
   Reg.WriteBool('Firewall', CheckBox1.Checked);
end;

Reg.CloseKey;
Reg.Destroy;


end;

end.

==============================
and here is the DPR file

library Config;

uses
  Main in 'Main.pas' {Form1};

exports
  loadSettings;

end.

=================================
Avatar of m_adil

ASKER

I've found another thing in MSDN

To call 32-bit DLL with RunDll32:

  void CALLBACK
  EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);

whats this!!
Yes, you've found the right idea on MSDN. Functions that you call via RunDll32 must look like this:

  procedure loadSettings(window, hInstance: dword; cmdLine: pchar; showCmd: integer); stdcall;

Regards, Madshi.
Avatar of m_adil

ASKER

so what are the parameters that I've to pass to rundll32.
Currently I'm using the cmdLine
rundll32 mydll,loadSettings
You could start it as this:

RUNDLL32.EXE mydll.dll,loadSettings 777 Teststring

But I'm quite sure that you can start it as you've done (without any additional parameters). Just change the parameters of the loadSettings function. I think it will work then.
Avatar of m_adil

ASKER

Yup this works fine. but there is a little problem. How can i pass an argument to loadSettings procedure.
I've tried
procedure loadSettings(n, window, hInstance: dword; cmdLine: pchar; showCmd: integer); stdcall;

where n is the parameter of int type I've to send.
I used cmdLine
rundll32 mydll,loadSettings(1)
but it give me the error Entry point not found

Except this it is working fine!!
ASKER CERTIFIED SOLUTION
Avatar of Madshi
Madshi

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of m_adil

ASKER

Thanks alot!!!