Hey, nifty, fake rocks.


I assume it’s either related to this, or it’s “Movie Where Manhattan Explodes #957.” (They are getting less and less creative with the titles these days.)
Let me be the first to say that this is probably a really bad idea, unless you are very desperate.
On the other hand, this was really fun to write.
Today I wrote some code that patches the first few bytes of user32!MessageBoxExW
, in order to keep a pesky third-party library from showing a prompt when nobody was around to click on it. This overwrites the start of that function with a relative jump to one of my own, which then forwards to a managed function that logs what the message box was trying to tell us.
Actually, this was for a friend’s program. I would probably shy away from doing this if I weren’t only indirectly responsible.
void InstallHook()
{
HMODULE hUser32 = LoadLibrary(L"user32.dll");
PROC pMsgBox = GetProcAddress(hUser32, "MessageBoxExW");
FailIf(pMsgBox == NULL);
// Need to change the memory protection for the
// (read/execute) page in user32.dll before we
//write to it.
MEMORY_BASIC_INFORMATION mbi = {0};
VirtualQuery(pMsgBox, &mbi,
sizeof(MEMORY_BASIC_INFORMATION));
FailIf(!VirtualProtect(mbi.BaseAddress, mbi.RegionSize,
PAGE_READWRITE, &mbi.Protect));
// Copy in the jump instruction... you could of course
// opt to not write this in assembly, but if we've gone this
// far, what's the difference?
__asm
{
// edi <- user32!MessageBoxExW
mov edi, pMsgBox;
// write the opcode for JMP rel32
mov byte ptr [edi], 0xe9;
// eax <- _MessageBoxEx, then
// eax <- _MessageBoxEx - user32!MessageBoxExW
mov eax, offset _MessageBoxEx;
sub eax, edi;
// One byte for jmp, four for the address.
sub eax, 5;
inc edi;
stosd;
};
// Restore the old protection
DWORD oldProtect = 0;
FailIf(!VirtualProtect(mbi.BaseAddress,
mbi.RegionSize, mbi.Protect, &oldProtect));
}
With that in place it’s not hard to erect some managed scaffolding around it, and nobody needs to know your secret. Until they try to run it on an x64, I guess:
static void Main(string[] args)
{
HookMonkey.Install(delegate(MessageBoxInfo mbi)
{
Console.WriteLine(mbi.Text);
return DialogResult.OK;
});
MessageBox.Show("foo bar");
}
You can download some sample code here.
Don Box says:
As a WPF user, I spend at least as much time reading and writing XAML as I do reading/writing C# code that does WPF-isms. I do spend a lot of time in C#, but little of it is WPF specific, which arguably is one of the strengths of WPF’s data/content facilities.
In my opinion, the sooner folks get thrown into the XAML pool the sooner they learn to swim.
(Emphasis mine.)
I thought the whole point of selling our souls to the XML devils was that development tools would deal with that slop for us.
Forget swimming. I am having trouble seeing any non-masochistic reason for me to learn this at all. I am just not getting through the Microsoft marketing on this one. I say this as somebody with deep-to-extremely-deep knowledge of most of the Microsoft tools of the last 10 years—I’m not Don Box, but I’m also no slouch.
Give me one good reason why I should spend my spare time learning an API that looks like this. (And it would be my spare time. I am still living here in the real world, where it still seems to be occasionally more practical to write Windows platform code in C++, for god’s sake.)
Wikipedia reassures me—in a rather hilarious, pleonastic way—that this is “simply XML.”
[A] key aspect of the technology is the reduced complexity needed for tools to process XAML, because it is simply XML. As a result, a variety of products are emerging, particularly in the WPF space, which create XAML-based applications. As XAML is simply based on XML, developers and designers are able to share and edit content freely amongst themselves without requiring compilation.
(Emphasis mine.)
Show me one XML-based API that does not, in one way or another, prove this to be an oxymoron. (See also: “Java programmer writes application which reads 243 XML files on startup then wonders why it takes 30 seconds to start.” Thanks, Slava.)
Sometimes trite observations become trite because they are obviously correct. Who created the creator? Why re-invent the s-expressions that have been around since the 50’s, but poorly? Et cetera. In these cases the fact that the criticism is well-worn does nothing to detract from it.
Maybe I am just being a grizzled old fogey (at the incredibly advanced age of 27.) It wouldn’t be the first time that I have been described as a crotchety septugenarian in the body of a young adult. If I am way off the mark here, please enlighten me.
Update, May 20th: Jon Harrop avoids my bitching and gives solutions. See XAML or F#.