Win32 font resource leak - winapi

I have a small matter of GDI leak and i wanted to know someone's opinion on how to solve this.Say i have a class that enfolds data specific to creating and handling a window ex:
class Wnd {
HWND hWnd;
HFONT hFont;
LOGFONT LogFont;
//etc
public:
//constructors and member functions
//The following function atempts to change the font of the window
//pointed to by the hWnd parameter
void ChangeFont (const LOGFONT& lf) {
std::memcpy (&LogFont,&lf,sizeof(LOGFONT));
hFont=CreateFontIndirect (&LogFont);
SendMessage (hWnd,WM_SETFONT,(WPARAM) hFont,(LPARAM) 1);
}
~Wnd () {
//i don't think this would work since i haven't used the SelectObject function
DeleteObject ((HGDIOBJ) hFont);
}
};
So the main question is , at destruction time how do i release the memory allocated to the
hFont parameter?Should i get a device context of the window and use the SelectObject () function so that after that i could release it calling the function for the old font and use DeleteObject () to free the memory?Thanks a lot.

So the main question is , at destruction time how do i release the
memory allocated to the hFont parameter?
You use DeleteObject() per documentation for CreateFontIndirect() and the WM_SETFONT message.
Should i get a device context of the window and use the SelectObject
() function so that after that i could release it calling the function
for the old font and use DeleteObject () to free the memory?
This should not be necessary, as long as your painting routine correctly restores the old font somehow after the routine is done with the font.

Related

How to show a QDialog on a custom Windows Desktop (HDESK)

Solution
After several tests and good leads from the community, I can now confirm that it is mandatory to apply SetThreadDesktop before creating the QApplication. This is the only way to allow Qt to display QWidgets in the new desktop.
However, SwitchDesktop can be called before or after the QApplication, it doesn't matter as long as SetThreadDesktop has been called before the creation of the QApplication.
Thanks to all of you! I hope this topic will be useful for other people.
Problem
I'm working on a Qt project on Windows where i need to create a custom desktop (HDESK) using API such as CreateDesktop, OpenDesktop and SwitchDesktop. On this new Desktop, i need to show a QDialog (using exec or show depending on my needs) but the QDialog is not displayed on the new desktop but on the "default" one.
My code looks something like this :
/* Starting the QApplication from the main function */
QApplication qApp;
qApp.exec();
/* [...] An HEVENT is fired or a Win32 COM call is made telling me than i need to display the QDialog */
/* Creating the new desktop and switching to it */
HDESK hNewDesktop=NULL;
hNewDesktop=CreateDesktop(L"_MyNewDesktopName", NULL, NULL, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, NULL);
SwitchDesktop(hNewDesktop);
/* Creating the QDialog and showing it */
QDialog *pqdlgMyDialog=NULL;
pqdlgMyDialog=new QDialog(NULL);
pqdlgMyDialog.show(); // or .exec() depending on the my needs
Doing this, create and display a new desktop with a black background but the QDialog is displayed on the default desktop (the one we see when we start Windows).
I have to tried to set a parent to my QDialog doing something like this but it does not work either :
QWindow *pqwParentWindow=NULL;
QWidget *pwqParentWidget=NULL;
HWND hwndParentWindow=NULL;
hwndParentWindow=GetTopWindow(NULL); // I have also tried GetDesktopWindow, FindWindowEx etc.
pqwParentWindow=QWindow::fromWinId((WId)hwndParentWindow);
pwqParentWidget=QWidget::createWindowContainer(pqwParentWindow);
[...]
QDialog *pqdlgMyDialog=NULL;
pqdlgMyDialog=new QDialog(pwqParentWidget);
pqdlgMyDialog.show(); // or .exec() depending on the my needs
If someone has an idea, i'm willing to try everything !
I have done a lot of reading of Qt Documentation and MSDN, looking for stuff such as "Is a QApplication linked to a desktop" but without success...
HWNDs are tied to threads and threads with HWNDs are tied to desktops.
The SetThreadDesktop function will fail if the calling thread has any windows or hooks on its current desktop (unless the hDesktop parameter is a handle to the current desktop).
I don't know if QApplication creates a hidden window or if you have another HWND there but it is easy to demonstrate that SetThreadDesktop will fail if there is already a window on the thread:
HDESK g_hNew;
DWORD CALLBACK TrySwitch(LPVOID Param)
{
if (Param)
{
CreateWindow(L"EDIT", L"Existing window", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, 0, 0, 0, 0);
}
if (SetThreadDesktop(g_hNew))
{
SwitchDesktop(g_hNew);
CreateWindow(L"EDIT", L"New window", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, 0, 0, 0, 0);
}
Sleep(3333);
return 0;
}
void Example()
{
HDESK hIn = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, false, DESKTOP_SWITCHDESKTOP);
g_hNew = CreateDesktop(L"_MyNewDesktopName", NULL, NULL, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, NULL);
WaitForSingleObject(CreateThread(NULL, 0, TrySwitch, (void*) TRUE, 0, NULL), 3333); // Leaks thread handle and I don't care
WaitForSingleObject(CreateThread(NULL, 0, TrySwitch, (void*) FALSE, 0, NULL), 3333); // Leaks thread handle and I don't care
SwitchDesktop(hIn);
CloseDesktop(hIn);
CloseDesktop(g_hNew);
}

Is it safe to register an existing windows class with a new name?

I am writing a framework using VC2010, and mixed MFC/Win32. I have a number of control types, which all register their own window classes, and some of them use the WindowProc of one of the standard window class - similar to the following example.
void Button::OnInitClass(WNDCLASS &wndClass)
{
Object::OnInitClass(wndClass);
if(!GetClassInfo(NULL, WC_BUTTON, &wndClass)) {
throw std::exception("Failed getting window class info.");
}
wndClass.lpszClassName = ButtonBase::GetWndClassName();
}
bool Button::Create(CWnd* parent)
{
if(!WndClassInitialized) {
static VSCriticalSection cs;
cs.Enter();
if(!WndClassInitialized) {
WNDCLASS wndClass;
memset(&wndClass, 0, sizeof(WNDCLASS));
OnInitClass(wndClass);
assert(wndClass.lpszClassName);
if(!RegisterClass(&wndClass)) {
throw std::exception("Error registering window class");
}
WndClassInitialized = true;
}
cs.Leave();
}
DWORD style = WS_CHILD | WS_CLIPSIBLINGS | BS_PUSHBUTTON | BS_MULTILINE;
DWORD exStyle = WS_EX_LEFT | WS_EX_LTRREADING;
Created = CWnd::CreateEx(exStyle, ButtonBase::GetWndClassName(), "", style , _attribAnchor.Rect, parent, 0) != FALSE;
SetFont(_font);
return Created;
}
It all worked for a long time, but now I am getting a heap corruption now. However, if I use the WC_BUTTON class directly in the CreateEx call I don’t get the heap corruption.
I am in doubt of whether this way of registering a window class where I use the WindowProc from WC_BUTTON is safe. Is it?
If it is safe, then I of cause need to look for the course for the heap corruption elsewhere. But if not, is there a safe way to do what I try to do? (Namely registering an existing class with a new name - which I do in order to be able to recognize the controls from their window class name, given an arbitrary window handle)
I should mention that the heap corruption occurs in a string allocation, and all parameters seem right – so the problem must be somewhere prior to that.
Thanks in advance,
Martin
I'm afraid mixing MFC/Win32 make it worse. If your main framework/SDK is MFC then why not following MFC's rules and style? Why use ::RegisterClass instead of AfxRegisterClass (a lot simpler). Why register all different classes for mere UI controls?
Usual MFC programs only register new window class for popup or top-level windows (by AfxRegisterClass). MFC CWnd provides basic WndProc for that purpose. If you want a custom design button control you could use window subclassing mechanism.

Calling a managed delegate from an x64 callback? (parameter in rdx is getting trashed)

I have a library which exposes callback functions, and needs to be called from both managed and native code. I implemented this by doing:
typedef struct { DWORD blah; } MY_STRUCT;
class ICallbackInterface
{
public:
virtual HRESULT CallbackFunc1(const MY_STRUCT* pStruct) { return S_OK; }
// helper for overriding the vtable (used later on by the managed code)
class VTable
{
public:
void* pfnCallbackFunc1;
};
};
The native code receives a pointer to an ICallbackInterface, and calls CallbackFunc1.
In C++/CLI code, I'm allocating an ICallbackInterface, and overriding its vtable to point to delegates of the managed functions I want to call. (The following snippet is from the constructor):
public ref class MyManagedClass
{
...
m_pCallbackClass = new ICallbackInterface;
if (!m_pCallbackClass)
return E_OUTOFMEMORY;
m_pNewCallbackVtable = new ICallbackInterface::VTable;
if (!m_pNewCallbackVtable)
{
delete m_pCallbackClass;
m_pCallbackClass = nullptr;
return E_OUTOFMEMORY;
}
// Get the (hidden) pointer to the vtable
ICallbackInterface::VTable** ppAddressOfInternalVtablePointer =
(ICallbackInterface::VTable**)m_pCallbackClass;
ICallbackInterface::VTable* pOldVtable = *ppAddressOfInternalVtablePointer;
// Copy all the functions from the old vtable that we don't want to override
*m_pNewCallbackVtable = *pOldVtable;
// Manually override the vtable entries with our delegate functions
m_pNewCallbackVtable->pfnCallbackFunc1 = Marshal::GetFunctionPointerForDelegate(gcnew delCallbackFunc1(this, &MyManagedClass::CallbackFunc1)).ToPointer();
...
And here's the callback function & its delegate
[UnmanagedFunctionPointer(CallingConvention::StdCall)]
delegate HRESULT delCallbackFunc1(const MY_STRUCT* pMyStruct);
HRESULT CallbackFunc1(const MY_STRUCT* pMyStruct)
{
// do something with pMyStruct.
}
}
When I compile the native library for x86, all works well.
(I don't know why CallingConvention::StdCall is used there, but the alternatives seem to cause problems with esp.)
When I compile it for x64, the callback function gets called, and rsp is fine when I return, but pMyStruct is trashed. It appears the native code likes to pass things in to rdx, but somewhere in the native->managed transition (which the debugger won't let me step into), rdx is being filled with garbage.
Is there some attribute I can use to on my delegate to fix this on x64? Or do I need to do something less pleasant like wrap my entire managed class in a native class to do the callbacks? Or did I just find a managed codegen bug?
you're invoking undefined bwhavior left and right, and relying on implementation details such as vtable layout and virtual member function calling convention. it's no wonder that things broke when you changed platforms.
you need to write derived vl lass if the native interface. the implementation can call function pointers or managed delegates directly. and stop messing with the vtsble pointer.
Found the problem.
The managed code has its "this" pointer that comes when initializing the delegate.
But the native function has its own "this" pointer which is being passed along too. Changing the managed signatures to the following totally fixes the bug, and now the function gets access to both "this" pointers.
[UnmanagedFunctionPointer(CallingConvention::ThisCall)]
delegate HRESULT delCallbackFunc1(ICallbackInterface* NativeThis, const MY_STRUCT* pMyStruct);
HRESULT CallbackFunc1(ICallbackInterface* NativeThis, const MY_STRUCT* pMyStruct)
{
// do something with pMyStruct.
}
This works on x86 and x64.

timed MessageBox in console application

I use MessageBox function in Win32 console application.
Application does not not use MFC, not even event loop.
I need to make a wrapper, MessageBoxTimed(), that exits
(and dialog box disappears) after N seconds, if user did not press any button.
Is there more or less simple way to do this ?
This will not be trivial. Since the MessageBox() function itself is modal, you will likely need to start another thread that waits for the predefined number of seconds, and is interrupt-able if the message box is dismissed manually.
If the timer expires, use the FindWindow() API to find the handle of the message box and then simulate a click of the OK button, or perhaps more appropriately a keypress of the ESC button.
EDIT: Actually, not too bad. This isn't fully tested, may need some additional cleanup, but is enough to get you started.
#include <Windows.h>
class TimedMB
{
public:
TimedMB() : timeout_(0), caption_(0)
{
interrupt_ = CreateEvent(NULL, FALSE, FALSE, NULL);
}
~TimedMB()
{
CloseHandle(interrupt_);
}
static DWORD WINAPI timer(LPVOID param)
{
TimedMB* mb = reinterpret_cast<TimedMB*>(param);
if(WAIT_TIMEOUT == WaitForSingleObject(mb->interrupt_, mb->timeout_))
{
HWND message_box = FindWindow(NULL, mb->caption_);
if(::IsWindow(message_box))
{
PostMessage(message_box, WM_COMMAND, IDCANCEL, 0);
}
}
return 0;
}
void DisplayMessageBox(const char* msg, const char* caption, DWORD timeout)
{
timeout_ = timeout;
caption_ = caption;
CreateThread(NULL, 0, &TimedMB::timer, this, 0, NULL);
::MessageBox(NULL, msg, caption, MB_OKCANCEL);
::SetEvent(interrupt_);
}
private:
HANDLE interrupt_;
DWORD timeout_;
const char* caption_;
};
int main()
{
TimedMB mb;
mb.DisplayMessageBox("Hello There!", "My Message Box", 5000);
}
If you need to dismiss it automatically, I'd avoid using MessageBox at all. Instead, I'd just put together a dialog that closes itself after the specified period of time. If memory serves, you can do this pretty easily by setting a time when you display the pseudo-message box dialog. When the time goes off or the user clicks "ok" (or "close", etc.) you close the window and cancel the timer.
Don't do this. Modal dialogs should be closed by user intervention. Deviating from this pattern is just confusing and non-standard. If you want a message windows that closes itself, then use a balloon window.

Make IWebBrowser2 Control safe for scripting

I'm using IWebBrowser2 control in my application to display external web pages.
The problem is that the object is not safe for scripting and calls to get_Document fails (with S_FALSE as return value).
I've implemented a new class, IScriptableWebBrowser2 that inherits both from IWebBrowser2 & IObjectSafety, and tried to use it instead of IWebBrowser2 but that didn't do the trick.
How do I make my IWebBrowser2 control safe for scripting ?
class IScriptableWebBrowser2 :
public CComObjectRootEx<CComSingleThreadModel>,
public IWebBrowser2,
public IObjectSafety
{
BEGIN_COM_MAP(IScriptableWebBrowser2)
COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()
// IObjectSafety implementation
STDMETHODIMP GetInterfaceSafetyOptions(REFIID riid,
DWORD *pdwSupportedOptions,
DWORD *pdwEnabledOptions )
{
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER |
INTERFACESAFE_FOR_UNTRUSTED_DATA;
*pdwEnabledOptions = *pdwSupportedOptions;
return S_OK;
}
STDMETHODIMP SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
{
return S_OK;
}
};
I guess you created the browser in a thread and passed it on to another thread.
If that's the case, here's what you should do:
Before passing the IWebBrowser2 instance to another thread, in the creating thread, call CoMarshalInterThreadInterfaceInStream, that will marshal (convert) it to a thread-safe IStream object, and only then pass it to the tagert thread.
Later, in the target thread, you should call CoGetInterfaceAndReleaseStream with the previously marshaled IStream instance, which will unmarshal it back to your original object in the target thread (and release the IStream object along the way).
CoMarshalInterThreadInterfaceInStream in MSDN
CoGetInterfaceAndReleaseStream in MSDN
Hope that helps.
Well, I finally had some time to come back to this one..
It turns out that get_Document fails if you call it BEFORE the page completely loaded but the return value (S_FALSE) indicates a completely different error ("not safe for scripting")
btw, Loading local pages will give you the desirable behavior.
Therefore, calling get_Document after the page was loaded (DISPID_NAVIGATECOMPLETE2, DISPID_DOWNLOADCOMPLETE, DISPID_DOCUMENTCOMPLETE) will do the trick.
Hope this helps.

Resources