Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29070 Discussions

Running the out-of-box MDI example project fails with error Failed in LocalLock

brianreinhold
Novice
268 Views

I have downloaded and installed the latest version of the Intel Fortran compiler 2025.1.1
I have created the Visual Studio project MDI (Multiple Document Interface)
It builds and  runs.

When I click on File->new to generate a child window as shown in their documentation
https://community.intel.com/legacyfs/online/drupal_files/Creating_Fortran_Win_Apps_0.pdf
I get a message box with error
"Failed in LocalLock"

Running in the debugger I see

Unhandled exception at 0x00007FFC680A1792 (ntdll.dll) in Win32TransformModel.exe: 0xC000041D: An unhandled exception was encountered during a user callback.

and

Exception thrown at 0x00007FFC680A1792 (ntdll.dll) in Win32TransformModel.exe: 0xC0000005: Access violation reading location 0x0000000000000000.

I am running Visual Studio 2022 as administrator. (It did not help.)

I expected the code just to work - debugging is difficult right now for me  as I have to learn how to deal with win32 API from FORTRAN (Have only experience with C++). I don't know if it is a FORTRAN interfacing problem or a real coding error using win32 APIs.

A few other things to note. The documentation has a nice blue toolbar on the windows. The single window I have has a light gray toolbar and a darker gray main window. Kind of ugly and not at all that shown by the documentation.

0 Kudos
4 Replies
andrew_4619
Honored Contributor III
215 Views

I had a quick play with this: 

        ! First, get the text window's handle from the per MDI child
        ! INFO data structure
          ! hInfo1 = GetWindowLong(hwnd, 0)   !cant use for 64 bit windows  use GetWindowLongPtr
            hInfo1 = GetWindowLongPtr(hwnd, GWLP_HINSTANCE)
            if (hInfo1 .NE. 0)  then

I changed the line 3  for line 4. GetWindowLong only works with 32 bit, GetWindowLongPtr works with 32 or 64bit under the hood for 32 bit the latter calls the former.

 

With that change is does not crash but there are other problems of a similar nature. The program has not been updates for the 64bit world. Intel need to fix the template  or remove it.

brianreinhold
Novice
165 Views

I found the bug. The wizard generated code that passed the wrong handle to the SetWindowLong() method in WM_CREATE in the MDIWinProc callback. It was setting the handle to the handle of the MDI window and not the text window

This code:

        case (WM_CREATE)

            hTextWnd2 = CreateWindowEx(0,                             &
                            "Win32TransformModelText"C, ""C,                     &
                            IOR (WS_BORDER, IOR(SS_LEFT,              &
                            IOR(WS_CHILD, WS_VISIBLE))),              &
                            0, 0, 0, 0,                               &
                            hwnd,                                     &
                            2_HANDLE,                                 &
                            ghModule,                                 &
                            NULL)
        
            ret = SetWindowText(hTextWnd2,"Select 'Option' menu items"C)


            ! INFO was allocated in the MDIWndProc at IDM_NEW time and is
            ! passed to us at WM_CREATE time...
            hInfo2 = SetHandle (lParam)
            if (hInfo2 .NE. 0 )  then
                pInfo2 = LocalLock(hInfo2)
                if (pInfo2 == NULL) then
                    ret = MessageBox(ghwndMain,                       &
                                    "Failed in LocalLock WM_CREATE"C,           &
                                    "Error"C, MB_OK)
                end if
                call CopyMemory(LOC(Info2), pInfo2, 44) ! SIZEOFINFO = 44
                Info2%hTextWnd = hTextWnd2
            
                if (GetClientRect(hwnd, Info2%rcClient) .EQV. FALSE) &
                                                        then
                    ret = MessageBox(ghwndMain,                       &
                                    "Failed in GetClientRect!"C,      &
                                    "Error"C, MB_OK)
                end if
                call Copymemory(pInfo2, LOC(Info2), 44) ! SIZEOFINFO = 44
                ! Save the handle to INFO in our window structure
                lData = hInfo2
                ret = SetWindowLong(hwnd, 0, lData)
                ret = LocalUnlock(hInfo2)
            else
                ret = MessageBox(ghwndMain,"Can't allocate hInfo!"C,"Error"C, MB_OK)
            end if

has the error. Error is line 38l Fix is to set

SetWindowLong(hTextWnd2, 0, lData) 

There might be more errors related to the same thing, but now at least it creates the MDI Window

andrew_4619
Honored Contributor III
129 Views

There are quite a few things wrong. As I said before  use of GetWindowLong is invalid in 64bit but I also note the value 44 is passed into copymemory in many places, that is also wrong as that was hard code for 32 bit, for 64 it would be int( sizeof(info), SIZE_T ), the SIZOFINFO variable is also wrong, I suspect there are many more things.

0 Kudos
brianreinhold
Novice
78 Views

Yes you are right. This template is full of errors. The original error and solution I had is not valid but arose because of other 64 bit errors. I have made several modifications but I still cannot get by the SetWindowLongPtr

        case (WM_CREATE)

            hTextWnd2 = CreateWindowEx(0,                             &
                            "Win32ModelText"C, ""C,                   &
                            IOR (WS_BORDER, IOR(SS_LEFT,              &
                            IOR(WS_CHILD, WS_VISIBLE))),              &
                            0, 0, 0, 0,                               &
                            hwnd,                                     &
                            2_HANDLE,                                 &
                            ghModule,                                 &
                            NULL)
        
            ret = SetWindowText(hTextWnd2,"Select 'Option' menu items"C)

            ! INFO was allocated in the MDIWndProc at IDM_NEW time and is
            ! passed to us at WM_CREATE time...
            hInfo2 = SetHandle (lParam)
            if (hInfo2 .NE. 0 )  then
                pInfo2 = LocalLock(hInfo2)
                if (pInfo2 == NULL) then
                    ret = MessageBox(ghwndMain, "Failed in LocalLock WM_CREATE"C, "Error"C, MB_OK)
                end if
                call CopyMemory(LOC(Info2), pInfo2, SIZEOFINFO) 
                Info2%hTextWnd = hTextWnd2
            
                if (GetClientRect(hwnd, Info2%rcClient) .EQV. FALSE) then
                    ret = MessageBox(ghwndMain,                       &
                                    "Failed in GetClientRect WM_CREATE!"C,      &
                                    "Error"C, MB_OK)
                end if
                call Copymemory(pInfo2, LOC(Info2), SIZEOFINFO)
                ! Save the handle to INFO in our window structure
                lData = hInfo2
                ! Check window handle is valid
                if (IsWindow(hwnd) == 0) then
                    ret = MessageBox(ghwndMain,"Window handle hwnd in WM_CREATE MDI Proc is invalid", "Error"C, MB_OK)
                endif
                ret = SetWindowLongPtr(hwnd, 0, lData)
                if (ret == 0) then
                    err = GetLastError()
                    msg = "SetWindowLongPtr in WM_CREATE MDI Proc failed with error "
                    header = "Error"
                    ret = WriteMessageBox(ghwndMain, err, msg, header)

                end if
                
                ret = LocalUnlock(hInfo2)

 I have added a function WriteMessageBox to print out a number in MessageBox which was MUCH harder to do than I ever expected it to be. I have tried all kinds of things, I have followed the data placed into lParam and 'extracted' here and I see it is what is should be. It gets modified for the GetClientRectangle() call and the modification is copied back and now hData2 will point to the modified data which you can validate by relocking it.

All my attempts keep getting error 6 which is invalid handle. hwnd is fine, so I can only think it must have something to do with lData. (I have tried GWLP_USERDATA as a storage location to no effect, I have fixed the size to handle 64-bits (was hardcoded to 44 and I now obtain that value dynamically which is 56), I fixed the cbWinExtra parameter from 4 to 8 and it still gives the error. 

Been working on this for days would really appreciate it if someone could fix this template code so it actually worked! I attach my Visual Studio project code if anyone (are you listening Intel) could help fixing this template code so that it does what it is advertised to do! Thanks.

0 Kudos
Reply
OSZAR »