I hate skinned applications. Hate them, with a burning passion. The only thing I hate more are skinned applications that “try” to look native but spectacularly fail on anything else but the default theme.
Now, it ain’t so bad when applications restrict that to their client area. It is still useless and disrespectful of my settings, but at least it’s contained. But more and more apps take bolder steps at spitting in the face of my settings — hint: I set them that way for a reason, because I like it that way — and, sadly, Microsoft is no exception to this.
Windows Live Messenger is a big culprit in this case. Up until Wave 3, even though it defaulted to using custom window captions, a simple “Show the menu bar” would bring the regular ones back. But, as it seems to be the fashion these days, that possibility was removed. That, and they also now impose ClearType usage, even if you explicitly disabled it. Not that important now, since LCD screens are everywhere, but my old CRT monitor only broke 6 months ago.
But if you played a little with WLM9, you notice it reverts to regular window captions in certain cases, like if you maximize a window. A little poking around in WinDbg quickly shows that it’s just using window regions to do its bidding. That, along with a friend that showed me that under Aero Glass, it actually just lets the window manager do its job and uses regular captions, was more than enough to tip me off that something could be done very easily about this problem.
My first try was to try and block the SetWindowRgn call outright. I basically overwrite the code for that function in the process’ memory with the assembly equivalent of this:
int HookSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
{
if (hRgn)
DeleteObject(hRgn);
return 1;
}
There are multiple problems with this approach. First, since WLM hides the whole caption and window borders, it has to handle WM_NCHITTEST in order to allow window resizing from within its client area. Since it also still thinks the caption and borders are hidden, it does not handle these cases, and as such, returns HTBOTTOM when the cursor is on the window caption. Also, the theming system in UxTheme.dll also calls this function — why it does not call NtUserSetWindowRgn directly is beyond me — in order to have those round window corners, and this “fix” disables that too.
My second and final solution came upon noticing that when WLM itself decides to show these captions, they work properly, and also the pseudo-caption inside the client area disapprears, too. If there was a way to trick WLM into thinking one of the “show the caption” conditions is met, it would by itself comply and show it without additional work. I first tried to hook the IsZoomed function directly to make it always return TRUE, but again it caused problems with UxTheme.dll.
I started by looking for calls to SetWindowRgn in all of WLM’s binaries. One of these files is UxCore.dll. Now, the fun part with exporting C++ classes or functions directly with __declspec(dllexport) is that all the decorated names are kept intact, which is very handy for reverse engineering like this since they contain full parameters and return type information. It did not take much time to find the UXFramelessManager class, which is responsible for hiding or showing the window caption, and handling everything that is associated with it. That class has a method called UpdateFrame, which does the work of determining if a window region needs to be set, and setting or clearing it as needed.
The UpdateFrame method checks that at least one of these three conditions is met:
- The window is maximized
- Aero Glass is enabled
- High Contrast Mode is enabled
If that is the case, it will set a NULL region for the window and not do any custom handling of the WM_NCHITTEST message. So, I figured, let’s make it think the window is always maximized! The code that does this check is:
7033e028 push dword ptr [esi+8] 7033e02b shr eax,13h 7033e02e and al,1 7033e030 mov byte ptr [ebp-1],al 7033e033 call dword ptr [__imp__IsZoomed@4]
The instruction at 7033e028 pushes the HWND of the window on the stack. The next three instructions are interleaved code that does something else, probably due to agressive compiler optimization settings, then the call is done at 7033e033. So all we need to do is to change the code to just always assume IsZoomed returned TRUE, padding as appropriate with NOPs:
7033e028 nop 7033e029 nop 7033e02a nop 7033e02b shr eax,13h 7033e02e and al,1 7033e030 mov byte ptr [ebp-1],al 7033e033 mov eax,1 7033e038 nop
All that was needed was to patch that new stream of instructions at the right file offset in UxCore.dll:
0003D428 -> 90 90 90 C1 E8 13 24 01 88 45 FF B8 01 00 00 00 90
Upon starting WLM, I had my window captions indeed:
(Yes, I went back to Windows Classic, despite my claims to the contrary.)
There is still a bug with this though. It it not apparent under Windows Classic, but UxTheme.dll causes problems again, albeit a minor one this time. Basically, UpdateFrame will still call SetWindowRgn on window creation with a NULL region, clearing the one set by UxTheme.dll. This is the code that does it:
7033e141 push 1 7033e143 push ebx 7033e144 push dword ptr [esi+8] 7033e147 call dword ptr [__imp__SetWindowRgn@12]
Note that EBX is zeroed out at the beginning of the function, so this code is the equivalent of:
SetWindowRgn(m_hWnd,NULL,TRUE);
All we have to do is to replace that whole code sequence with NOPs again. I won’t present the code here, but directly the bytes to patch in the file:
0003D541 -> 90 90 90 90 90 90 90 90 90 90 90 90
Once this is patched, WLM will have regular window captions, with no glitch (that I found yet). It is sad though, that I had to resort to patching code for such a trivial matter, especially that older versions of WLM allowed this, so they actually had to remove code to make it not-work…
All code addresses and listings comes from UxCore.dll version 14.0.8050.1202 in the WLM installation directory. Make sure you have that exact same version before patching the file, of course.
Update: This also works with UxCore.dll version 14.0.8064.206, as none of the offsets have changed.

hi,
i stumbled on your blog after searching all over the internet for a way to bring the window border back with the latest version msn.
i’ve been trying to do what you have explained but am finding it difficult with my lack of expertise in modifying dll files.
i was wondering if it was possible to share a patched version of the dll you have modified?
I don’t think I can share a patched DLL publicly (aka put it on this website).
But I sure could email you one.
haha hey, i was just about to write another comment to let you know i figured it all out and got it working myself. thanks for the guide it really helped. =D
Great you figured it out!
I had just sent you the patched DLL by email, just ignore it then.
Hi
Do you know if it’s possible to Disable ClearType in this horroble version of Windows Live Messenger?
It’s killing my eyes :[
I do not know of a setting to do so, it seems hardcoded.
Although, I bet with a patch/loader program, it would be possible to force all HFONTs / GDI+ GpGraphics to have antialiasing disabled.
I’ll toy with it when I have more free time.
After a quick toying with the Messenger executable in WinDbg, I came to the conclusion that disabling ClearType is quite easy. All one has to do is to catch all calls to
CreateFontIndirectExWand patch theLOGFONTstruct. It works for GDI+ fonts too, apparently.This will make Messenger use the system setting for ClearType (change
0to3to disable all antialiasing):bp GDI32!CreateFontIndirectExW "eb poi(esp+4)+1a 0; g"The only downside is that you need to run a debugger along all the time. However this shows that it wouldn’t be that hard to code a generic loader+patcher that does that.
Is there any way to find out whether Messenger has a ‘hidden’ registry key for disabling ClearType, comparable to the Office 2007 “RespectSystemFontSmooth”?
You can try and look at what registry access it does on startup with a tool like Process Monitor.
Hi! Please could somebody send me the patched DLL? Thanks in advance.
hey there
i have actually opted on moving to the new version of WLM because of the ugly window borders, so thank you so much for this tutorial!
but i was wondering if you can email me the patched .dll file since i’m not really good at editing the file and i don’t have the proper tools.
thank you :)
Hi Koro,
I quite amazed that you could actually bring back the borders which I personally would want to. However, I’m not good at editing. So could you please kindly email me the patched .dll if possible?
Thanks.
Hi Koro,
Is there any way you can send me this DLL? I’m going crazy with this stupid cleartype!!!
Thank you so much!!!
Hi Koro
could you send me the dll with the border? i dont know how to edit those files =(
thank you soooo much :D
Hello Koro,
I have the same request as the others. If you could please email me the patched .dll file it would be greatly appreciated.
Keep up the good work and take care.
Hi Koro,
I have the same request as the others. Could you please email me the patched .DLL file?
It would be greatly appreciated.
Keep up the great work.
please, send me solution for this awful looking cleartype font…
What is the point of this post? Either offer the required patched file via one of a million free file storage sites (if its so impossible to offer it directly here) or tell people step by step how to do it. This is nothing but a “oh, look what I can do” post.
The point of this post is exactly that, to explain the edit, not just dumbly give a file to download without people reading the article.
In the end it’s just two trivial hex-edits to do to the DLL file, it does not even take 5 minutes to apply them.
Contrary to Craig, I see much point in this post. Thank you Koro, you saved me a lot of time…
Ah very nice! *patched* :D
Hello Koro, are you able to email me the patched dll please?
hi man.
First of all thank you for your guide.
i have downloaded an hex editor.
I go to offest 0003D428 and i insert what you have written (90 90 90 C1 E8 13 24 01 88 45 FF B8 01 00 00 00 90)
then i go to the other offset and change whit what you have posted.
My messenger crash at startup….hi have UxCore.dll version 14.0.8064.206.
i have tried again….it crash. someone can send me the patched uxcore.dll??
my mail is
havenita@hotmail.com