The Old New Thing
Practical development throughout the evolution of Windows.
Latest posts

How do I forward an exported function to an ordinal in another DLL?

The syntax for specifying that requests to import a function from your DLL should be forwarded to another DLL is This says that if somebody tries to call from , they are really calling in . This forwarding is done in the loader. Normally, when a client links to the function , the loader says, "Okay, let me get the address of the function in and store it into the variable." It's the logical equivalent of When you use a forwarder, the loader sees the forwarder entry and says, "Whoa, I'm not actually supposed to get the function from at all! I'm supposed to get the function from !" So it loads and g...

If you're going to write your own allocator, you need to respect the MEMORY_ALLOCATION_ALIGNMENT

This time, I'm not going to set up a story. I'm just going to go straight to the punch line. A customer overrode the operator in order to add additional instrumentation. Something like this: This worked out okay on 32-bit systems because in 32-bit Windows, is 8, and is also 8. If you start with a value that is a multiple of 8, then add 8 to it, the result is still a multiple of 8, so the pointer returned by the custom remains properly aligned. But on 64-bit systems, things went awry. On 64-bit systems, is 16, As a result, the custom handed out guaranteed-misaligned memory. The misalignment went u...

Break it up, you two!: The zero width non-joiner

Preventing characters from combining.

Microsoft Money crashes during import of account transactions or when changing a payee of a downloaded transaction

Update: An official fix for this issue has been released to Windows Update, although I must say that I think my patch has more style than the official one. You do not need to patch your binary. Just keep your copy of Windows 8 up to date and you'll be fine. For the five remaining Microsoft Money holdouts (meekly raises hand), here's a patch for a crashing bug during import of account transactions or when changing a payee of a downloaded transaction in Microsoft Money Sunset Deluxe. Patch the mnyob99.dll file as follows: File offset 003FACE8: Change 85 to 8D File offset 003FACED: Change 50 to 51 File of...

Frequentists vs Bayesians

But, I mean, c'mon. Frequentists vs Bayesians? Worst. Action. Movie. Ever.

Why are taskbar live previews lost when you use Fast User Switching?

Anonymous asks a metric buttload of questions, which means that I feel compelled to answer all or none. And given the choice, I decided to answer none. Okay, I will answer one and ignore the rest. Why are taskbar live previews lost when you use Fast User Switching? When you switch away from a user via Fast User Switching, the Desktop Window Manager for that session is turned off. After all, since that session no longer has access to the screen, there's no point running all this code and consuming all this memory for something nobody can see. When the Desktop Window Manager restarts upon reactivation of a ses...

Thread affinity of user interface objects: Addendum

Some time ago, I discussed the thread affinity of device contexts, noting that the and functions must be called from the same thread. The same restriction also applies to printer DCs. Printer DCs must be created and destroyed on the same thread. The printing team imposed this additional rule in order to make it easier for printer driver vendors to author their drivers. (Printer driver developers have a habit of calling in their implementation of and in their implementation of .) Given that printer drivers are a third-party extension point, it's probably in your best interest to treat printer DCs as havin...

What does the COINIT_SPEED_OVER_MEMORY flag to CoInitializeEx do?

One of the flags you can pass to is , which is documented as : Trade memory for speed. This documentation is already vague since it doesn't say which direction the trade is being made. Are you reducing memory to increase speed, or increasing memory by reducing speed? Actually it's neither: If you pass this flag, then you are instructing COM to consume more memory in an attempt to reduce CPU usage, under the assumption that you run faster by executing fewer cycles.¹ The request is a per-process one-way transition. Once anybody anywhere in the process puts COM into speed-over-memory mode, the flag stays ...

Instead of trying to create a filter that includes everything, try just omitting the filter

The question was sent to a peer-to-peer discussion group for an internal program, let's call it Program Q. I'll add additional context so you can follow along. Hi, I'm trying to build a query that finds all issues owned by a particular user, regardless of which product the issue belongs to. I know that I can query for specific products by saying Is there a better way to do this than just running the query for every product in the database? It would be great to find all the issues at one shot instead of having to issue dozens of commands and combine the results. The person who submitted this question go...