PB Windows crashing during interaction with C++ subclasing lib on windows

Windows specific forum
pamen
Enthusiast
Enthusiast
Posts: 193
Joined: Sat Dec 31, 2022 12:24 pm
Location: Cyprus
Contact:

PB Windows crashing during interaction with C++ subclasing lib on windows

Post by pamen »

Hi - question only for hard core PB people, who know how windows are created, managed and destroyed by PB under Windows.

I'm having trouble with hidden PureBasic code for opening and closing windows (possibly managing the list of Hwnds/ pointers to window structures?).
I'm trying to debug C++ VS2022 unicode lib (I have the source), which subclasses windows (all aspects, including NC_AREA).
My dll source is fine with C and C++ programs and any WinAPI windows (created by CreatedWindowEx())), but Purebasic Windows crash in strange places and do not unload cleanly for reasons not clear to me.

Sequence:
Purebasic: OpenWindowX() - Ok.
Call to DLL - to start intercepting various drawing related events, including NC_AREA - message pump for drawing screen elements installed, - Ok
Close Window (either from PB or via WM_CLOSE by the dll - it intercepts close button click) - Seems Ok at first but actually test for IsWindow() still shows valid Hwnd handle.
Check from the DLL running in the debuger - the hwnd is not used and gone correctly after the WM_CLOSE message.
VS Debugger is not running any code at this point so there is nothing to look at in the DLL code.

PureBasic: call the same OpenWindowX() again - heavy crash:
Exception thrown at 0x000000014003E0DD in abcd.exe: 0xC0000005: Access violation writing location 0x0000000000000008.

It is always the same ridiculous memory address. and it happens during second call to OpenWindow() with a parent window set. so nothing to debug in PB code as well.

pb code is simply a Window with a button, which opens a new window with new #PB_Any id every time when clicked, so more than basic.
The original developer of the lib cannot find anything (for 2 weeks), I cannot find anything (similar timeframe) - in C or pure WinAPI programs all windows close on WM_CLOSE or on call to DestroyWindow(), no crashes, as many windows can show as needed.

Unfortunately I cannot quote here this C++ source (not mine and not free) but all it is doing is using purely WinAPI to subclass and paint window and controls - it works actually with any windows program I tried (MS VC, simple plain ASM, Lazarus, old PowerBasic), just not PB.

So - what does PureBasic do special on Windows behind OpenWindow and after a window is closed???
S.T.V.B.E.E.V.
Olli
Addict
Addict
Posts: 1240
Joined: Wed May 27, 2020 12:26 pm

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by Olli »

pamen wrote: Sat Sep 16, 2023 4:51 pm Hi - question only for hard core PB people, who know how windows are created, managed and destroyed by PB under Windows.

[...]

So - what does PureBasic do special on Windows behind OpenWindow and after a window is closed???
Certainly a thing your C++ source code modifies.

Please isolate the problem (in the C++ code, you do not know, and that you cannot publish, by convention of copy right).

I think you will find the problem yourself. A "eight" (0x000000000000008h) it is absolutely not an address, but a bound value.

And all the diagnostic methodology has been recorded publicly.

------> Look after the stack


Good luck.
juergenkulow
Enthusiast
Enthusiast
Posts: 581
Joined: Wed Sep 25, 2019 10:18 am

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by juergenkulow »

Code: Select all

; CloseWindow in x64dbg
myWindow=OpenWindow(#PB_Any,0,0,100,100,"Test")
!Nop
CloseWindow(myWindow)
!Nop

; ASM Backend
; ; CloseWindow(myWindow)
;   PUSH   qword [v_myWindow]
;   POP    rcx
;   CALL   PB_CloseWindow

;x64dbg
; 00000001400010D4        | FF35 D2EE0000   | push qword ptr ds:[14000FFAC]          |
; 00000001400010DA        | 59              | pop rcx                                |
; 00000001400010DB        | E8 10100000     | call closewindow.1400020F0             |

; 00000001400020F0        | 48:895C24 08    | mov qword ptr ss:[rsp+8],rbx           |
; 00000001400020F5        | 57              | push rdi                               |
; 00000001400020F6        | 48:83EC 20      | sub rsp,20                             |
; 00000001400020FA        | 48:8BF9         | mov rdi,rcx                            |
; 00000001400020FD        | 48:83F9 FF      | cmp rcx,FFFFFFFFFFFFFFFF               |
; 0000000140002101        | 75 0E           | jne closewindow.140002111              |
; 0000000140002103        | 48:8B0D 16E1000 | mov rcx,qword ptr ds:[140010220]       | 0000000140010220:"àA³\x01"
; 000000014000210A        | E8 517F0000     | call closewindow.14000A060             |
; 000000014000210F        | EB 6F           | jmp closewindow.140002180              |
; 0000000140002111        | 48:8BD1         | mov rdx,rcx                            |
; 0000000140002114        | 48:8B0D 05E1000 | mov rcx,qword ptr ds:[140010220]       | 0000000140010220:"àA³\x01"
; 000000014000211B        | E8 B47F0000     | call closewindow.14000A0D4             |
; 0000000140002120        | 48:8BD8         | mov rbx,rax                            |
; 0000000140002123        | 48:85C0         | test rax,rax                           |
; 0000000140002126        | 74 58           | je closewindow.140002180               |
; 0000000140002128        | 48:8BCF         | mov rcx,rdi                            |
; 000000014000212B        | E8 DC170000     | call closewindow.14000390C             |
; 0000000140002130        | 48:8B0B         | mov rcx,qword ptr ds:[rbx]             |
; 0000000140002133        | BA 04000000     | mov edx,4                              |
; 0000000140002138        | FF15 5AD50000   | call qword ptr ds:[<&GetWindow>]       |
; 000000014000213E        | 48:85C0         | test rax,rax                           |
; 0000000140002141        | 74 10           | je closewindow.140002153               |
; 0000000140002143        | 48:837B 30 00   | cmp qword ptr ds:[rbx+30],0            |
; 0000000140002148        | 75 09           | jne closewindow.140002153              |
; 000000014000214A        | 48:8BC8         | mov rcx,rax                            |
; 000000014000214D        | FF15 4DD50000   | call qword ptr ds:[<&SetActiveWindow>] |
; 0000000140002153        | 48:8B4B 30      | mov rcx,qword ptr ds:[rbx+30]          |
; 0000000140002157        | 48:85C9         | test rcx,rcx                           |
; 000000014000215A        | 74 13           | je closewindow.14000216F               |
; 000000014000215C        | 4C:8B03         | mov r8,qword ptr ds:[rbx]              | r8:"œvhw"
; 000000014000215F        | 45:33C9         | XOr r9d,r9d                            |
; 0000000140002162        | BA 21020000     | mov edx,221                            |
; 0000000140002167        | FF15 3BD50000   | call qword ptr ds:[<&SendMessageW>]    |
; 000000014000216D        | EB 09           | jmp closewindow.140002178              |
; 000000014000216F        | 48:8B0B         | mov rcx,qword ptr ds:[rbx]             |
; 0000000140002172        | FF15 38D50000   | call qword ptr ds:[<&DestroyWindow>]   |
; 0000000140002178        | 48:8BCF         | mov rcx,rdi                            |
; 000000014000217B        | E8 F8170000     | call closewindow.140003978             |
; 0000000140002180        | 48:8B5C24 30    | mov rbx,qword ptr ss:[rsp+30]          |
; 0000000140002185        | 48:83C4 20      | add rsp,20                             |
; 0000000140002189        | 5F              | pop rdi                                |
; 000000014000218A        | C3              | ret                                    |
What is the command at address 014003E0DD, the registers and the stack?
Olli
Addict
Addict
Posts: 1240
Joined: Wed May 27, 2020 12:26 pm

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by Olli »

I ve less deep questions...

Code: Select all

disableASM
define rsp
! push rax ; save rax
! push rbx ; save rbx
! mov [v_rsp], rsp ; save the stack

! xor rsp, rsp ; SHUT DOWN THE STACK (Very bad trip trilogy)

! push rax ; memory exception ? Yes ! Now ? No !
! pop rbx ; maybe now ?

! mov rsp, [v_rsp] ; maybe now ?

! pop rbx ; maybe now ?
! pop rax : maybe now ?
; maybe now ?
; maybe now ?
; maybe now ?
; ....
The crash depends of the crush of the cache.
juergenkulow
Enthusiast
Enthusiast
Posts: 581
Joined: Wed Sep 25, 2019 10:18 am

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by juergenkulow »

@Olli

Code: Select all

! pop rax : maybe now 
          ^

0000000140001053        | 48:31E4         | xor rsp,rsp                            |          
0000000140001056        | 50              | push rax                               |
0000000140001056 C0000005 EXCEPTION_ACCESS_VIOLATION

RAX : 00000000002B6E54
RBX : 0000000000000000
RCX : 000007FEFEAD1570     msvcrt.000007FEFEAD1570
RDX : FFFFF801017E470C
RBP : 0000000000000000
RSP : 0000000000000000
RSI : 0000000000000000
RDI : 0000000000000000
R8  : 0000000000000000
R9  : 0000000000000000
R10 : 00000000002B026C
R11 : 00000000000004E4     L'Ӥ'
R12 : 0000000000000000
R13 : 0000000000000000
R14 : 0000000000000000
R15 : 0000000000000000
RIP : 0000000140001056     rsp.0000000140001056
RFLAGS : 0000000000010346

000000000012FF20   0000000000000000   
000000000012FF28   0000000000626E54   
000000000012FF30   0000000000000000   
000000000012FF38   0000000000000000   
000000000012FF40   0000000000621320   
000000000012FF48   0000000000000000   
000000000012FF50   0000000000000000   
000000000012FF58   0000000077945A4D   zurück zu kernel32.0000000077945A4D von ???
000000000012FF60   0000000000000000   
000000000012FF68   0000000000000000   
000000000012FF70   0000000000000000   
000000000012FF78   0000000000000000   
000000000012FF80   0000000000000000   
000000000012FF88   0000000077A7B831   zurück zu ntdll.0000000077A7B831 von ???
Please ask your questions, because switch on the cognition apparatus decides on the only known life in the universe.Wersten :DDüsseldorf NRW Germany Europe Earth Solar System Flake Bubble Orionarm
Milky Way Local_Group Virgo Supercluster Laniakea Universe
pamen
Enthusiast
Enthusiast
Posts: 193
Joined: Sat Dec 31, 2022 12:24 pm
Location: Cyprus
Contact:

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by pamen »

The originator of the code got tired of me finding more places where his framework crashes with brutal user32.dll errors in EventLog on a very simple PB application - so he gave up today.
He has a right to use his free time better, as his own C++ pure WindowAPI apps work with his framework :-)

[Edit] I deleted the code, as it is not mine, so no more searches for inappropriate games wit the stack.

So please consider my question as answered, sort of.
Not that my small brain understood all the ASM-ing above. Sounds very knowledgeable though. Huts off.
S.T.V.B.E.E.V.
Olli
Addict
Addict
Posts: 1240
Joined: Wed May 27, 2020 12:26 pm

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by Olli »

Code: Select all

0000000140001056        | 50              | push rax                               |
0000000140001056 C0000005 EXCEPTION_ACCESS_VIOLATION
Again some theory 8)

I thank juergenkulow for his work, and his respect of the question.

I am sorry for the colon character ':' instead of a semi-colon. I typed this code manually through my phone, and my eyes betray me sometimes...
pamen
Enthusiast
Enthusiast
Posts: 193
Joined: Sat Dec 31, 2022 12:24 pm
Location: Cyprus
Contact:

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by pamen »

Ok, The developer (a truly nice and very persistent person) found the issue with some minor help from me checking all the loaded modules of a normal PB Windows UI application, hurray for Process Explorer.

Here we go:
PureBasic loads system dlls as needed, some of them are loaded even if there seems no reason for it, like GDIPlus.
Certainly there is some magic reason (even without use UsePngDecoder() or any code relating to images and with no picture gadget).
GDIPlus is very picky and will not check itself via singleton if it is already loaded in current process and if "GDIplusStartup" was already called.

Trying to load GDIPlus second time unknowingly (which third party developer may or may not do) and then calling GDIPlusStartup will invariably cause a total havoc and memory access or stack errors in GDIPlus, but this hides from plain view - C++ debugger will blame PureBasic executable, PureBasic will Blame OpenWindow() and event viewer will show user.dll and application errors in PureBasic executable.

I'm no sure how to make it clear to other PB Devs - either via intercepting LoadLibrary() and instead returning the handle of the already loaded library, if it is system dll, or maybe just listing, what libraries are loaded in even simplest UI application.
My example had on purpose nothing in it apart from buttons, checkboxes and CommCtrl Gadgets with no images or image menus.
So there was no reason to suspect, that GDIPlus is loaded and initialized.

Cheers.

Ah - third party can, of course alleviate the problem simply, but not every third party will care, they wil lcare to balance load and free library, but not always checking the process.

Code: Select all

BOOL gdiplusExist = FALSE;
HMODULE gdiplib() {
    static HMODULE hGdip;
    if (hGdip == 0) {
        hGdip = GetModuleHandle(L"gdiplus.dll"); if (hGdip) gdiplusExist = TRUE; // PureBasic is already using it
        if (hGdip == 0) hGdip = LoadLibrary(L"GDIPLUS");
    }
    return hGdip;
S.T.V.B.E.E.V.
Olli
Addict
Addict
Posts: 1240
Joined: Wed May 27, 2020 12:26 pm

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by Olli »

Please change your truth to a simple question : << Does PureBasic load GDIPLUS library without reason ? >> and please ask this question in the Coding question.

PureBasic is crossplatform. gdiPlus, no.
User avatar
ChrisR
Addict
Addict
Posts: 1466
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by ChrisR »

Just for fun, a quick hack to remove GdiPlus dependency via a fake polink.exe
VectorDrawing.lib needs to be removed in addition to GdiPlus.lib
I checked on a basic window with Procmon (I prefer it to Process Explorer) and a filter on the exe process name and CreateFile operation, Gdiplus.dll is no longer loaded and the exe works.

Code: Select all

; -----------------------------------------------------------------------------
; polink.pb - Beta test: remove GdiPlus dependency (GdiPlus.LIB)
; Get Compilation via a fake polink.exe:
; -----------------------------------------------------------------------------
; Compile it as polink.exe
; Then In PureBasic_6.0_x64\Compilers, save, rename polink.exe to polink_real.exe and copy your Fake polink.exe in PureBasic_6.0_x64\Compilers 
; Do not forget to restore polink_real.exe to polink.exe when you no longer need this hack
; -----------------------------------------------------------------------------
EnableExplicit

Define ProgramParam$, polinkParam$, Line$, Output$, Error$
Define CountParam, I, Gcc, Polink
Define  gccParam$ = "-O0 -fsigned-char -Wno-discarded-qualifiers -Wno-incompatible-pointer-types -Wno-overflow -Wno-int-conversion -c -o PureBasic.obj purebasic.c"
;Define gccParam$ = "-O2 -fno-tree-vrp -freorder-blocks-algorithm=simple -fno-schedule-insns -fno-schedule-insns2 -fsigned-char -Wno-discarded-qualifiers -Wno-incompatible-pointer-types -Wno-overflow -Wno-int-conversion -c -o PureBasic.obj purebasic.c" 
Define CompilerPath$ = GetPathPart(ProgramFilename())

If FileSize(CompilerPath$ + "polink_real.exe") > 0
  CountParam = CountProgramParameters()
  For I=0 To CountParam-1
    ProgramParam$ = ProgramParameter(I)
    Select ProgramParam$
      Case "GdiPlus.LIB", "VectorDrawing.lib"
      Default
        polinkParam$ + ProgramParam$ + " "
    EndSelect   
  Next
  
  If Not RenameFile(GetCurrentDirectory() + "purebasic.c", GetCurrentDirectory() + "purebasic.org.c")
    MessageRequester("Error " +  GetCurrentDirectory(), "Renaming purebasic.c to purebasic.org.c failed!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
    End
  EndIf
  
  If ReadFile(0, GetCurrentDirectory() + "purebasic.org.c")
    If CreateFile(1, GetCurrentDirectory() + "purebasic.c")
      While Not Eof(0)
        Line$ = ReadString(0)
        Select Line$
          Case "integer PB_InitVectorDrawing();", "PB_InitVectorDrawing();", "integer PB_EndVectorDrawing();", "PB_EndVectorDrawing();"
            Line$ = "//" + Line$
        EndSelect
        WriteStringN(1, Line$)
      Wend
      CloseFile(1)
    Else
      MessageRequester("Error " +  GetCurrentDirectory(), "Couldn't create purebasic.c file!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
    EndIf
    CloseFile(0)
  Else
    MessageRequester("Error " +  GetCurrentDirectory(), "Couldn't open purebasic.org.c file!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
  EndIf
  
  ;Uncomment following lines to Compil via cmdlines
  ;SetClipboardText("Cd /D " + GetCurrentDirectory() +#CRLF$+ 
  ;                 "PATH=%PATH%;" + CompilerPath$ + ";" + CompilerPath$ + "gcc\" +#CRLF$+
  ;                 "gcc.exe " + gccParam$ +#CRLF$+
  ;                 "polink_real.exe " + polinkParam$ +#CRLF$+ "")
  ;   
  ;MessageRequester("Compilation Cmdlines", "Compilation cmdlines copied to the clipboard." +#CRLF$+#CRLF$+ "To be used in cmd.exe before closing this window", #PB_MessageRequester_Ok | #PB_MessageRequester_Info) 
  ;End
  
  Gcc = RunProgram(CompilerPath$ + "gcc\gcc.exe", gccParam$, GetCurrentDirectory(), #PB_Program_Open | #PB_Program_Read | #PB_Program_Error )
  If Gcc
    While ProgramRunning(Gcc)
      If AvailableProgramOutput(Gcc)
        Output$ + ReadProgramString(Gcc) + #CRLF$
        Error$ + ReadProgramError(Gcc) + #CRLF$
      EndIf
    Wend
    If ProgramExitCode(Gcc) <> 0 
      Error$ + ReadProgramError(Gcc) + #CRLF$
      MessageRequester("Error " +  GetCurrentDirectory(), "gcc.exe:" + Error$, #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
    EndIf
    CloseProgram(Gcc)
  EndIf
  
  Output$ = "" : Error$ = ""
  Polink = RunProgram(CompilerPath$ + "polink_real.exe", polinkParam$, GetCurrentDirectory(), #PB_Program_Open | #PB_Program_Read | #PB_Program_Error )
  If Polink
    While ProgramRunning(Polink)
      If AvailableProgramOutput(Polink)
        Output$ + ReadProgramString(Polink) + #CRLF$
        Error$ + ReadProgramError(Polink) + #CRLF$
      EndIf
    Wend
    If ProgramExitCode(Polink) <> 0 
      Error$ + ReadProgramError(Polink) + #CRLF$
      MessageRequester("Error " +  GetCurrentDirectory(), "polink_real.exe:" + Error$, #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
    EndIf
    CloseProgram(Polink)
  EndIf
  
Else
  MessageRequester("Compilation Error", "polink_real.exe not found!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
EndIf
pamen
Enthusiast
Enthusiast
Posts: 193
Joined: Sat Dec 31, 2022 12:24 pm
Location: Cyprus
Contact:

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by pamen »

Thanks Chris!
S.T.V.B.E.E.V.
pamen
Enthusiast
Enthusiast
Posts: 193
Joined: Sat Dec 31, 2022 12:24 pm
Location: Cyprus
Contact:

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by pamen »

Olli,
I hope this is simple enough, let me know if I should shorten it a bit
viewtopic.php?t=82496
Olli wrote: Fri Sep 22, 2023 1:53 am Please change your truth to a simple question : << Does PureBasic load GDIPLUS library without reason ? >> and please ask this question in the Coding question.

PureBasic is crossplatform. gdiPlus, no.
S.T.V.B.E.E.V.
Fred
Administrator
Administrator
Posts: 18199
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by Fred »

I mean there is nothing wrong to load GDIPlus, we use it for a various reason, the thirdparty tool needs to be fixed here, not PureBasic.
pamen
Enthusiast
Enthusiast
Posts: 193
Joined: Sat Dec 31, 2022 12:24 pm
Location: Cyprus
Contact:

Re: PB Windows crashing during interaction with C++ subclasing lib on windows

Post by pamen »

Dear Fred, I understand that and you are very correct!
Knowing which libs are loaded by default in plain PureBasic basic UI app is simply helpful for beginners like myself to troubleshoot anything out of PB scope (no headers - great, I hate header mess! but no headers = mystery what will be loaded).

What I did is to write C example in VS2022 with exactly the same gadgets and window creation behavior - it worked flawlessly (yeah - no GDIPlus loaded), in PB - crashed left and right, so my own lack of knowledge how PureBasic works was here the biggest hurdle. The fact that the component was buggy - was quite irrelevant until I (and the developer) could understand what is different in PureBasic compiled executable behavior from C or C++.
S.T.V.B.E.E.V.
Post Reply