Author Topic: Problems with GetOpenFileNameW  (Read 7326 times)

x64Core

  • Member
  • **
  • Posts: 80
Problems with GetOpenFileNameW
« on: March 17, 2013, 08:32:39 AM »
Hi guys, I have a problem with GetOpenFileNameW so want to know if anyone can given me any idea.
In a VC project with two winproc procedures , mainProc and Controlproc

This ControlProc is subclassing a control and calls to GetOpenFileNameW >

{
    switch(msg)
    {
    WM_COMMAND:
        // CHECK CONTROL HANDLE
        {
            OPENFILENAMEW    MYFILE;

            ZeroMemory(&MYFILE,sizeof(MYFILE));
            MYFILE.lStructSize = sizeof(MYFILE);
           
            //MYFILE.hwndOwner = NULL;
            MYFILE.lpstrFile = Buffer;
            MYFILE.lpstrFile[0] = L'\0';
            MYFILE.nMaxFile = MAX_PATH;
            MYFILE.lpstrFilter = StrFilterType;
            MYFILE.nFilterIndex = 1;
            MYFILE.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

            GetOpenFileNameW(&MYFILE);
        }
        break;
    }
    return CallWindowProcW((WNDPROC)ControlSC, hWnd, msg,wParam, lParam);   
}
   
all is ok, but when I press the Close button (title bar) the app is not closed because it has some still some thread running in the process
( threads which are created by such api ). I have tried several things ( creating aditional thread to call to the API function, assignment of owner, instance ) but without successful.
I know that GetOpenFileNameW is the problem because I have run the app withput any call to the function and the application is finishing correctly. also, I have checked with a thread viewer all thread which are created, and GetOpenFileName creates several threads.

well, it's c++ but i'm asking here because you guys have a lot of experience. any ideas? thanks.

EDIT>
I dont want to finish my app with ExitProcess obviously, nasty habit.

jj2007

  • Member
  • *****
  • Posts: 11583
  • Assembler is fun ;-)
    • MasmBasic
Re: Problems with GetOpenFileNameW
« Reply #1 on: March 17, 2013, 08:54:33 AM »
You are up for some bug chasing...
- which OS? Win7-64?
- any strange things when looking at it with a debugger?
- Buffer is a wchar with MAX_PATH chars, i.e. 2*MAX_PATH bytes?
- tried to call HeapValidate before and after?
- same with OPENFILENAMEA?
- StrFilterType has a double zero delimiter? Tried with a nullstring?
- Can you create a small test app that shows this behaviour, and post the exe here?

x64Core

  • Member
  • **
  • Posts: 80
Re: Problems with GetOpenFileNameW
« Reply #2 on: March 17, 2013, 09:42:28 AM »
You are up for some bug chasing...
- which OS? Win7-64?
- any strange things when looking at it with a debugger?
- Buffer is a wchar with MAX_PATH chars, i.e. 2*MAX_PATH bytes?
- tried to call HeapValidate before and after?
- same with OPENFILENAMEA?
- StrFilterType has a double zero delimiter? Tried with a nullstring?
- Can you create a small test app that shows this behaviour, and post the exe here?

Hi jochen

- Yes Win7 64bit but also, I have tested my app ( debug mode and rel mode ) on WinXP 32bit, win7 32bit, Win8 32bit and same problem
- well, normally I'm debugging in debug mode.I think that any difference with another debugger  :P
- is WCHAR buffer[MAX_PATH+1]; I think that it's ok
-
- yes
- I made this program and same problem  :

Code: [Select]
HMODULE GlobalInstance;
HWND hwMainWindow;
HWND hMainTab;
LONG TabControlSubClass;
HWND hUniqueButton;
WCHAR Buffer[MAX_PATH+1];

INT OpenFileDlg(PWCHAR StrFilterType, PWCHAR Buffer)
{
    OPENFILENAMEW    MYFILE;

    ZeroMemory(&MYFILE,sizeof(MYFILE));
    MYFILE.lStructSize = sizeof(MYFILE);

    MYFILE.hInstance = GetModuleHandleW(NULL);
    MYFILE.hwndOwner = NULL;
    MYFILE.lpstrFile = Buffer;
    MYFILE.lpstrFile[0] = L'\0';
    MYFILE.nMaxFile = MAX_PATH;
    MYFILE.lpstrFilter = StrFilterType;
    MYFILE.lpstrFileTitle = NULL;
    MYFILE.nMaxFileTitle = 0;
    MYFILE.nFilterIndex = 1;
    MYFILE.lpstrInitialDir = NULL;
    MYFILE.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    return GetOpenFileNameW(&MYFILE);
}



LRESULT CALLBACK TabProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_COMMAND:
        if((HWND)lParam == hUniqueButton)
        {
            OpenFileDlg(L"jpg files \0*.jpg\0",Buffer);
        }
        break;

    }

    return CallWindowProcW((WNDPROC)TabControlSubClass, hWnd, message,wParam, lParam);
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
{
    case WM_DESTROY:
        SetWindowLongW(hMainTab, GWL_WNDPROC,(LONG) TabControlSubClass);
        PostQuitMessage(0);
        break;
    default:
            return DefWindowProc(hWnd, message, wParam, lParam);
}

return 0;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW    wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style         = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra     = 0;
wcex.cbWndExtra     = 0;
wcex.hInstance = hInstance;
wcex.hIcon         = NULL;
wcex.hCursor = 0;
wcex.hbrBackground =  (HBRUSH)COLOR_BTNSHADOW;
wcex.lpszMenuName = 0;
wcex.lpszClassName = L"TEST";
wcex.hIconSm = NULL;

return RegisterClassExW(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance)
{
    TCITEM    mTC = {0};


    hwMainWindow = CreateWindowW(L"TEST",L"WINDOW 1", DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU,
               CW_USEDEFAULT, CW_USEDEFAULT,300,300, NULL, NULL, hInstance, NULL);
     
    if (!hwMainWindow)
        return FALSE;

    hMainTab = CreateWindowW(L"SysTabControl32",0,WS_CHILDWINDOW | WS_VISIBLE,10,40,200,200,hwMainWindow,0,GlobalInstance,0);
    if(hMainTab)
    {
            hUniqueButton = CreateWindowW(L"button",L"OPEN",WS_CHILDWINDOW | WS_VISIBLE,20,40,120,40,hMainTab,0,0,0);

            TabControlSubClass = SetWindowLongW(hMainTab ,GWL_WNDPROC,(LONG) TabProc);

            /* All OK */
            ShowWindow(hMainTab, nCmdShow);
            UpdateWindow(hMainTab);
            return TRUE;

    }

    return FALSE;
}

int main()
{
    MSG            msg;
    GlobalInstance = GetModuleHandleW(0);
    MyRegisterClass(GlobalInstance);
    if (InitInstance (GlobalInstance, SW_SHOW))
    {
        while(GetMessageW(&msg, NULL, 0, 0) > 0)
        {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }       
    }
    return FALSE;
}


EDIT>

Exe in attahced

qWord

  • Member
  • *****
  • Posts: 1476
  • The base type of a type is the type itself
    • SmplMath macros
Re: Problems with GetOpenFileNameW
« Reply #3 on: March 17, 2013, 10:39:16 AM »
One problem that I see is that the main function is specified as entry point thus returning yields in only exiting that thread. Using ExitProcess at this point is correct. BTW, if compile your code as console application (because of main()), it works perfectly.
For all that thread (which are in an wait state), it seems to be common that they are not removed - maybe to speed up future usage (as a thread pool?).
MREAL macros - when you need floating point arithmetic while assembling!

x64Core

  • Member
  • **
  • Posts: 80
Re: Problems with GetOpenFileNameW
« Reply #4 on: March 17, 2013, 11:01:49 AM »
One problem that I see is that the main function is specified as entry point thus returning yields in only exiting that thread. Using ExitProcess at this point is correct. BTW, if compile your code as console application (because of main()), it works perfectly.
For all that thread (which are in an wait state), it seems to be common that they are not removed - maybe to speed up future usage (as a thread pool?).
hello,
if the entrypoint is the problem then MASM code would fail too.
main() is the ep by default for console mode programs, but the compiler will add its library ( i'm trying to avoid this library too ).
I'm really not convinced by using ExitProcess  :P

qWord

  • Member
  • *****
  • Posts: 1476
  • The base type of a type is the type itself
    • SmplMath macros
Re: Problems with GetOpenFileNameW
« Reply #5 on: March 17, 2013, 11:12:05 AM »
if the entrypoint is the problem then MASM code would fail too
they do not fail because we use ExitProcess() - you will find that these threads are also present for ASM programs.
i'm trying to avoid this library too
it that case there is no way around using ExitProcess.
MREAL macros - when you need floating point arithmetic while assembling!

jj2007

  • Member
  • *****
  • Posts: 11583
  • Assembler is fun ;-)
    • MasmBasic
Re: Problems with GetOpenFileNameW
« Reply #6 on: March 17, 2013, 12:24:27 PM »
Exe in attahced


I see. Inside OpenFile it throws an exception 6BA, but apparently you can ignore that (First-chance exception 0x000006BA: The RPC server is unavailable). I've debugged it with Olly until the ret, it then calls ExitThread.

If you let it go, the program terminates but one thread remains active.

If instead of continuing in ExitThread you set the origin some lines below to a push whatever, call ExitProcess, it exits without leaving threads open. Which confirms what qWord suggests.

So what's wrong with ExitProcess? Why do you want to avoid it?

x64Core

  • Member
  • **
  • Posts: 80
Re: Problems with GetOpenFileNameW
« Reply #7 on: March 19, 2013, 03:44:10 AM »
alright thank you guys I really appreciate your help
« Last Edit: March 19, 2013, 06:12:29 AM by x64Core »