Link to home
Start Free TrialLog in
Avatar of klemperer
klemperer

asked on

Question about GetOpenFileNameA API

In my application I hooked GetOpenFileNameA API expecting that the OpengFile dialog won't appear but returns with a desired filename. The application raises an error when calling this API, can anyone help me? Thank you.

uses madCodeHook
var
GetOpenFilenameANextHook: function (var OpenFile: TOpenFilenameA): Bool; stdcall;

HookAPI('Comdlg32.dll', 'GetOpenFileNameA',@myGetOpenFileNameA, @GetOpenFilenameANextHook);

function myGetOpenFileNameA(var OpenFile: TOpenFilenameA): Bool; stdcall;
var
szFile:PCHAR;
begin
  showmsg('HOoked');
  GetMem(szFile,260);
  ZeroMemory(szFile,260);
  szFile:='c:\1.txt';

  ZeroMemory(@OpenFile, sizeof(TOpenFilenameA));
  OpenFile.lStructSize := sizeof(TOpenFilenameA);
  OpenFile.hwndOwner := Hinstance;
  OpenFile.lpstrFile := szFile;
  OpenFile.nMaxFile := 260;
  OpenFile.lpstrFilter := pchar('All'#0'*.*'#0'Text'#0'*.TXT'#0);
  OpenFile.nFilterIndex := 1;
  OpenFile.lpstrFileTitle := nil;
  OpenFile.nMaxFileTitle := 0;
  OpenFile.lpstrInitialDir := nil;
  OpenFile.Flags := OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST;
  result:=true;
end;
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

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
what is it you are trying to do?
Avatar of klemperer
klemperer

ASKER

Thank you for your answer.
Consider an application with the following procedure: Click "Open File" button-->Open File Dialog appears-->Select a File and Click "OK"-->The application reads the file and adds its content to a listview

Now I would like to change its procedure as follows: Click "Open File" button-->The application reads the desired file "c:\1.txt" and adds its content to a listview.

So I wrote a dll and injected it into the application and HOOK GetOpenFilenameA API (The application calls GetOpenFilenameA to show an open file dialog).

The code is:

var
 GetOpenFilenameANextHook: function (var OpenFile: TOpenFilenameA): Bool; stdcall;

function myGetOpenFileNameA(var OpenFile: TOpenFilenameA): Bool; stdcall;
begin
  showmsg('HOoked');
  lstrcpy(OpenFile.lpstrFile,'c:\1.txt');
  result:=true;
end;

.......
HookAPI('Comdlg32.dll', 'GetOpenFileNameA',@myGetOpenFileNameA, @GetOpenFilenameANextHook);
......

Now the problem is, when I click on "open file" button, the "HOoked" dialog appears, but the content of desired file doesn't show in a listview.
I am quite puzzled now~
The hooking is process wide and won't intercept the system call for GetOpenFilenameA
the system API  GetOpenFilenameA( ) is not so simple, it takes a complex record TOpenFilenameA with 20 members . . . and the Flags member can have more than 22 flag bits (even more for win 200 and XP), I would guess that the calling program requires more than just the OpenFile.lpstrFile  to be filled with the file name, you may need to set the  OpenFile.nFileOffset  or the  OpenFile.nFileExtension or maybe the  OpenFile.lpstrFileTitle                                                          ? ?. . .
 or maybe if it has a  OpenFile.lpfnHook it will need some dialog box input to confirm the acceptance of the file?,
you do not test for any of the flag bits, if I tested for them , I am not sure what to do for some of them like the  OFN_ENABLEHOOK

I am guessing that the file - 'c:\1.txt'  does exist, the program may check for it's existance, or may check for the folder location, or may check for many other things for a file path sent to it. . .
Sounds difficult. Now there are still two questions.
1. Can I spy the members of TOpenFilename while its open file dialog appears?

2. What if I let the open file dialog shows, then I PostMessage(Hinstance,WM_KEYDOWN,VK_RETURN,0) to return?

function myGetOpenFileNameA(var OpenFile: TOpenFilenameA): Bool; stdcall;
var
flag:boolean;
begin
   result:=GetOpenFilenameANextHook(OpenFile);
end;
The two functions below lead to different results?

function myGetOpenFileNameA(var OpenFile: TOpenFilenameA): Bool; stdcall;
var
flag:boolean;
begin
   flag:=GetOpenFilenameANextHook(OpenFile);
   result:=flag;
end;

function myGetOpenFileNameA(var OpenFile: TOpenFilenameA): Bool; stdcall;
begin
   result:=GetOpenFilenameANextHook(OpenFile);
end;
sorry, I have made a mistake--the difference between bool and boolean :)
What I would do is to call the -
  GetOpenFilenameANextHook( )
in your  myGetOpenFileNameA( ), and then analize the returned   OpenFile  for the members and use this data to set your returned   OpenFile  members to reflect the data returned of  members in the  OpenFile   from the GetOpenFilenameANextHook, , , ,

is the  OFN_ENABLEHOOK  flag bit in the Flags of the sent  OpenFile  record ? if it does not have this it may be eaysier


function myGetOpenFileNameA(var OpenFile: TOpenFilenameA): Bool; stdcall;
begin
result:=GetOpenFilenameANextHook(OpenFile);
showmsg(IntToStr(OpenFile.Flags));
showmsg(IntToStr(Integer(OpenFile.lpstrFileTitle)));
//more OpenFile member data analysis
end;
I got the members.
The flags include:

OFN_HIDEREADONLY
OFN_ENABLEHOOK
OFN_PATHMUSTEXIST
OFN_FILEMUSTEXIST
OFN_EXPLORBER
OFN_SHATEWARN

including OFN_ENABLEHOOK. Sounds more difficulty now.

By the way, the result of  GetOpenFilenameANextHook(OpenFile) is a longbool variable with value "01 00 00 00".
If I didn't call GetOpenFilenameANextHook, How can I set a longbool variable with the value I just said?
a BOOL value is just a 32 bit memory block used as a Boolean value, in Delphi you can just set a BOOL value to True or False, the compilier will know to set the value to cardinal 1 . . . which I beleive is   "01 00 00 00"  for true, if for some reason you need to use all four bytes, I believe you can typecate it to a Cardinal

Cardinal(Result) := 1; // true

you could test it with
if Cardinal(Result) = 1 then



since it has the OFN_ENABLEHOOK, there may be complications, it may read the user's seletions with the CDN_SELCHANGE notifycation message and do some internal data changes? or Not

//The following code got the desired result
var
flag:bool;
....
flag:=GetOpenFilenameANextHook(OpenFile);
if Cardinal(flag) = 1 then   //true
showmsg('True');
result:=flag;

//but the following code can't get the desired result
var
flag:bool;
....
flag:=GetOpenFilenameANextHook(OpenFile);
flag:=true;
if Cardinal(flag) = 1 then   //false
showmsg('True');
result:=flag;

I do not know, I have used this code many many many times -

if GetOpenFileName(OFName) then
    Str1 := FileName;

and the GetOpenFileName( )  ( which calles the GetOpenFileNameA( ) ) will give a True result if the open dialog is not canceled, as far as I know
one is true and 0 is false, even in a normal Boolean (which just uses one Byte), the 32 bit Bool is more efficient 32 bit code and works faster, I have changed many of my Boolean to BOOL variables in my code
Well, while you use "if GetOpenFileName(OFName) then", the result will be auto type casted to boolean, and some bits will be lost.
I got it:)

integer(flag):=1;  //it works

Thank you for your help all the time:)