Bug SetWindowLongPtr_() and SetClassLongPtr_()

Just starting out? Need help? Post your questions and find answers here.
User_Russian
Addict
Addict
Posts: 1443
Joined: Wed Nov 12, 2008 5:01 pm
Location: Russia

Bug SetWindowLongPtr_() and SetClassLongPtr_()

Post by User_Russian »

The original topic. http://www.cyberforum.ru/pure-basic/thread1261571.html

Probably in a function SetWindowLongPtr_() declaration bug, because it does not work on Windows 8 x64.
Function GetLastError_(), returns an error code 1413. The same error when using the SetClassLongPtr_().

Code: Select all

Global *OldCallback
Procedure CallW(hWnd, Msg, wParam, lParam)
  Debug msg
  If msg = #WM_RBUTTONDOWN
    msg = 0
  EndIf
  ProcedureReturn CallWindowProc_(*OldCallback, hWnd, msg, wParam, lParam)
EndProcedure
If OpenWindow(0, 0, 0, 400, 100, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  StringGadget(0, 10, 10, 380, 20, "")
  
  *OldCallback = SetWindowLongPtr_(GadgetID(0), #GWLP_WNDPROC, @CallW())
  Debug GetLastError_()
  Repeat
    Event = WaitWindowEvent()
    
  Until Event = #PB_Event_CloseWindow
EndIf
When the function declaration as to the msdn, there is no error.

Code: Select all

Import "User32.lib"
  SetWindowLongPtrW(hWnd, Index, NewLong.l)
EndImport
 
Global *OldCallback
Procedure CallW(hWnd, Msg, wParam, lParam)
  Debug msg
  If msg = #WM_RBUTTONDOWN
    msg = 0
  EndIf
  ProcedureReturn CallWindowProc_(*OldCallback, hWnd, msg, wParam, lParam)
EndProcedure
If OpenWindow(0, 0, 0, 400, 100, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  StringGadget(0, 10, 10, 380, 20, "")
  
  *OldCallback = SetWindowLongPtrW(GadgetID(0), #GWLP_WNDPROC, @CallW())
  
  Debug GetLastError_()
  Repeat
    Event = WaitWindowEvent()
    
  Until Event = #PB_Event_CloseWindow
EndIf
User avatar
Danilo
Addict
Addict
Posts: 3037
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Bug SetWindowLongPtr_() and SetClassLongPtr_()

Post by Danilo »

User_Russian wrote:Probably in a function SetWindowLongPtr_() declaration bug, because it does not work on Windows 8 x64.
Function GetLastError_(), returns an error code 1413. The same error when using the SetClassLongPtr_().

Code: Select all

Global *OldCallback
Procedure CallW(hWnd, Msg, wParam, lParam)
  Debug msg
  If msg = #WM_RBUTTONDOWN
    msg = 0
  EndIf
  ProcedureReturn CallWindowProc_(*OldCallback, hWnd, msg, wParam, lParam)
EndProcedure
If OpenWindow(0, 0, 0, 400, 100, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  StringGadget(0, 10, 10, 380, 20, "")
  
  *OldCallback = SetWindowLongPtr_(GadgetID(0), #GWLP_WNDPROC, @CallW())
  Debug GetLastError_()
  Repeat
    Event = WaitWindowEvent()
    
  Until Event = #PB_Event_CloseWindow
EndIf
Works fine here (PB 5.2x LTS x64), returning 0 for GetLastError_(). Did you try SetLastError_(0) before the call to SetWindowLongPtr_()?
User_Russian wrote:When the function declaration as to the msdn, there is no error.

Code: Select all

Import "User32.lib"
  SetWindowLongPtrW(hWnd, Index, NewLong.l)
EndImport
The second parameter is 'int' (32bit .l). The 3rd parameter is a pointer (LONG_PTR), so your Import is wrong.
It works anyway, because all arguments get widened to 64bit. The following just crashes with x64:

Code: Select all

  callback.l = @CallW()
  *OldCallback = SetWindowLongPtrW(GadgetID(0), #GWLP_WNDPROC, callback)
Fred
Administrator
Administrator
Posts: 16619
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Bug SetWindowLongPtr_() and SetClassLongPtr_()

Post by Fred »

Seems to work as well here, can anybody else confirm ?
freak
PureBasic Team
PureBasic Team
Posts: 5929
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Bug SetWindowLongPtr_() and SetClassLongPtr_()

Post by freak »

Just checking GetLastError_() is not enough according to the documentation:
If the previous value is zero and the function succeeds, the return value is zero, but the function does not clear the last error information. To determine success or failure, clear the last error information by calling SetLastError with 0, then call SetWindowLongPtr. Function failure will be indicated by a return value of zero and a GetLastError result that is nonzero.
So you need to:
  • Call SetLastError_(0)
  • Check that the function returns 0
  • Check that GetLastError_() is not 0
quidquid Latine dictum sit altum videtur
User_Russian
Addict
Addict
Posts: 1443
Joined: Wed Nov 12, 2008 5:01 pm
Location: Russia

Re: Bug SetWindowLongPtr_() and SetClassLongPtr_()

Post by User_Russian »

Fred wrote:Seems to work as well here
In Windows 8 x64 and PB x64?
Fred
Administrator
Administrator
Posts: 16619
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Bug SetWindowLongPtr_() and SetClassLongPtr_()

Post by Fred »

Yes, that's my dev config
Fred
Administrator
Administrator
Posts: 16619
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Bug SetWindowLongPtr_() and SetClassLongPtr_()

Post by Fred »

Does it still happen ?
Olli
Addict
Addict
Posts: 1071
Joined: Wed May 27, 2020 12:26 pm

Re: Bug SetWindowLongPtr_() and SetClassLongPtr_()

Post by Olli »

@Fred

I am on demo version X64 and the prototype I must create contains any longs as window handle, not a long long (quad). I checked the window handle : even on X64, it stays any longs somewhere...

Code: Select all

Prototype.L GetWindowLongPtrW(hWnd.L, index.i)
hWnd : 32 bits
index : 64 bits
result : 32 bits

Code: Select all

Global u32=OpenLibrary(#PB_Any,"user32")
Prototype.L GetWindowLongPtrW(handle.L,i.i)
Global GetWindowLongPtrW.GetWindowLongPtrW = GetFunction(u32,"GetWindowLongPtrW")
Prototype.L SetWindowLongPtrW(handle.L,i.i,value.L)
Global SetWindowLongPtrW.SetWindowLongPtrW = GetFunction(u32,"SetWindowLongPtrW")
Prototype.L SetLayeredWindowAttributes(handle.L,cKey.L,alpha.a,opt.L)
Global SetLayeredWindowAttributes.SetLayeredWindowAttributes = GetFunction(u32,"SetLayeredWindowAttributes")

OpenWindow(1,100,100,200,200,"Resizable",#PB_Window_SizeGadget|#PB_Window_SystemMenu)
SetWindowColor(1,$efface)
wId = WindowID(1)
SetWindowLongPtrW(wId,-20,GetWindowLongPtrW(wId,-20)|$80000)
SetLayeredWindowAttributes(wId,$efface,0,1)
Repeat
 ev=WaitWindowEvent()
 If ev=#PB_Event_Repaint Or ev=#PB_Event_SizeWindow
  StartDrawing(WindowOutput(1))
  w=OutputWidth()
  h=OutputHeight()
  Box(0,0,w,h,#White)
  Ellipse(w/2,h/2,w/2,h/2,$efface)
  StopDrawing()
 EndIf
Until ev=#PB_Event_CloseWindow
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Bug SetWindowLongPtr_() and SetClassLongPtr_()

Post by mk-soft »

With x64, handles and pointers are always 64-bit wide, even if it seems to work with long. At some point you will get a handle or pointer over 32bit and hang up your program.
So always take integer for handles and pointer always *Pointer
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Olli
Addict
Addict
Posts: 1071
Joined: Wed May 27, 2020 12:26 pm

Re: Bug SetWindowLongPtr_() and SetClassLongPtr_()

Post by Olli »

Thank you for this recall mk-soft.
Post Reply