Holy cow, I wrote a book!
Strange what sorts of things need to be spelled out explicitly nowadays. You know you're in trouble when your employee training includes a discussion of company policy regarding employees making inappropriate comments or questions about underwear.
New in Visual C++ 2005 is the ability to specify a manifest dependency via a #pragma directive. This greatly simplifies using version 6 of the shell common controls. You just have to drop the line
#pragma
// do not use - see discussion below #pragma comment(linker, \ "\"/manifestdependency:type='Win32' "\ "name='Microsoft.Windows.Common-Controls' "\ "version='6.0.0.0' "\ "processorArchitecture='X86' "\ "publicKeyToken='6595b64144ccf1df' "\ "language='*'\"")
into your program and the linker will do the rest.
Note that the processor architecture is hard-coded into the above directive, which means that if you are targetting x64, you'll get the wrong manifest. To fix that, we need to do some preprocessor munging.
#if defined(_M_IX86) #define MANIFEST_PROCESSORARCHITECTURE "x86" #elif defined(_M_AMD64) #define MANIFEST_PROCESSORARCHITECTURE "amd64" #elif defined(_M_IA64) #define MANIFEST_PROCESSORARCHITECTURE "ia64" #else #error Unknown processor architecture. #endif #pragma comment(linker, \ "\"/manifestdependency:type='Win32' "\ "name='Microsoft.Windows.Common-Controls' "\ "version='6.0.0.0' "\ "processorArchitecture='" MANIFEST_PROCESSORARCHITECTURE "' "\ "publicKeyToken='6595b64144ccf1df' "\ "language='*'\"")
Update: I didn't know that * is allowed here to indicate "all architectures". That simplifies matters greatly.
#pragma comment(linker, \ "\"/manifestdependency:type='Win32' "\ "name='Microsoft.Windows.Common-Controls' "\ "version='6.0.0.0' "\ "processorArchitecture='*' "\ "publicKeyToken='6595b64144ccf1df' "\ "language='*'\"")
Nitpicker's corner
One of my friends is involved with Science on Tap, a free, informal monthly get-together in the Seattle area covering science topics for the general public. (Recent coverage in the Seattle-PI.) The topic for July 30th is "The three things you need to know about tsunamis", and a title like that pretty much sells itself.
I just made up that term now because I needed a word to describe the situation where some manager is put in charge of a feature but is not given a staff to implement that feature. This happens more often than you might think, since there are many features that are "horizontal", i.e., features which affect all teams throughout the project. So-called taxes often fall into this category, such as power management, accessibility, and multiple monitors. (Larry Osterman calls them *bilities. I call them taxes.)
The unempowered manager is in a predicament, having been assigned a task without a staff to accomplish it. All the unempowered manager can do is nag other people, usually about bugs that fall into the manager's area.
Now, most of these unempowered managers understand that they are just one of many demands on the development teams, providing advice as necessary (since they have valuable specialized knowledge about the problem area) but basically trying to stay out of the way.
Others, on the other hand, take upon themselves a much more active role in "driving" their pet issues. This means that I will get mail like this:
You have an elephant† bug The following elephant bug is assigned to you: 16384 Elephants not available in animal dropdown box (opened 2006/05/12) What is the ETA for fixing this bug? (signed) Somebody you've never heard of
You have an elephant† bug
The following elephant bug is assigned to you:
16384 Elephants not available in animal dropdown box (opened 2006/05/12)
What is the ETA for fixing this bug?
(signed) Somebody you've never heard of
This is another case of "You're not my manager". My manager decides what tasks I should be working on and in what order. If you think this bug should be higher on my priority list, feel free to set up a little meeting with my manager to work this out. Until then, don't bug me. I have work to do.
"But elephant-compatibility is important."
Are you saying that all my other tasks are unimportant? What makes elephant-compatibility more important than my other tasks? Do you even know what my other tasks are?
At one point, this got so bad, with many managers nagging me about their favorite bugs on a nearly daily basis, that I created a SharePoint site‡ called "Raymond's task list for <date>". Whenever somebody sent me nag mail, I replied, "I have added your request to my SharePoint site and assigned it a default priority." And then I never heard from them again.
For those new to this web site (and a reminder to those with poor memory):
†I disguise the name because (1) it's not important to the story, and because (2) the goal is not to ridicule but rather to illustrate a point. Attempts to guess what "elephant" is will be deleted. Don't make me delete further stories in this series like I did with "Stories about Bob."
‡Or, if you're a trademark lawyer, "A Web site powered by Microsoft® SharePoint® services."
*Here's your stupid asterisk.
On Mark Rosenfelder's Zompist web site I found a series of cultural guides named How to tell if you're ‹nationality›. All of the entries are simultaneously funny and insightful, such as this one from Turkey:
A company can fire just about anybody it wants. But it will also hire anybody.
For some reason, my favorite is this one from the Polish entry:
When you negotiate, you are polite, of course, but it's only good business to 'play hardball'. You don't say what you mean, you pretend not to know many things, but you surely never lie. You know the other side does the same thing, and they know you know. Many people are tired of it, so they start talking normally. You say "let's talk like people" then.
I like how the Poles understand that it's all an act, and they have a code for saying, "This is stupid."
While you're there, you should also check out The Zompist Phrasebook, the absolutely worst phrasebook you'll ever find that's still hilarious.
Solving this next problem should be a snap with your nascent psychic powers:
I'm trying use FormatMessage to load a resource string with one insertion in it, and this doesn't work for some reason. The string is "Blah blah blah %1. Blah blah blah." The call to FormatMessage fails, and GetLastError() returns ERROR_RESOURCE_TYPE_NOT_FOUND. What am I doing wrong? LPTSTR pszInsertion = TEXT("Sample"); LPTSTR pszResult; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, //I also tried an instance handle and NULL. GetModuleHandle(NULL), IDS_MY_CUSTOM_MESSAGE, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language (LPTSTR) &pszResult, 0, (va_list*) &pszInsertion);
FormatMessage
GetLastError()
ERROR_RESOURCE_TYPE_NOT_FOUND
LPTSTR pszInsertion = TEXT("Sample"); LPTSTR pszResult; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, //I also tried an instance handle and NULL. GetModuleHandle(NULL), IDS_MY_CUSTOM_MESSAGE, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language (LPTSTR) &pszResult, 0, (va_list*) &pszInsertion);
Hint: Take a closer look at the parameter IDS_MY_CUSTOM_MESSAGE.
IDS_MY_CUSTOM_MESSAGE
Hint 2: What does "IDS_" tell you?
IDS_
Resource identifiers that begin with "IDS_" are typically string resource identifiers, not message resource identifiers. There is no strong consensus on the naming convention for message resource identifiers, although I've seen "MSG_". Part of the reason why there is no strong consensus on the naming convention for message resource identifiers is that almost nobody uses message resources! I don't understand why they were added to Win32, since there was already a way of embedding strings in resources, namely, string resources.
MSG_
That's why you're getting ERROR_RESOURCE_TYPE_NOT_FOUND. There is no message resource in your module. If you're not going to use a message resource, you'll have to use the FORMAT_MESSAGE_FROM_STRING flag and pass the format string explicitly.
FORMAT_MESSAGE_FROM_STRING
DWORD_PTR rgdwInsertions[1] = { (DWORD_PTR)TEXT("Sample") }; TCHAR szFormat[256]; LoadString(hInstance, IDS_MY_CUSTOM_MESSAGE, szFormat, 256); LPTSTR pszResult; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, szFormat, 0, 0, (LPTSTR) &pszResult, 0, (va_list*) &rgdwInsertions);
I also made a slight change to the final parameter. When you use FORMAT_MESSAGE_ARGUMENT_ARRAY, the last parameter must be an array of DWORD_PTRs. (The parameter must be cast to va_list* to keep the compiler happy.) It so happens that the original code got away with this mistake since sizeof(DWORD_PTR) == sizeof(LPTSTR) and they both have the same alignment requirements. On the other hand, if the insertion were a DWORD, passing (va_list*)&dwValue is definitely wrong and can crash if you're sufficiently unlucky. (Determining the conditions under which your luck runs out is left as an exercise.)
FORMAT_MESSAGE_ARGUMENT_ARRAY
DWORD_PTR
va_list*
sizeof(DWORD_PTR) == sizeof(LPTSTR)
DWORD
(va_list*)&dwValue
The IT department here will periodically send out notifications regarding changes to the network infrastructure or updates that are being deployed across the company. One of my colleagues sent me email saying, "Cool, they're using Roman numerals!" It was in response to one particular IT notification that included the following sentence:
This update will require approximately X minutes.
Nobody asked, but I'm going to post it anyway. These are the movies I'm planning on seeing, along with my twisted take on the plot, based solely on the movie description.
¹These movies were chosen in large part to serve as German lessons.
²I have a weak spot for slightly off-kilter Japanese movies set in the modern day.
³Swedish class group movie. Even though it's in Danish.
Since Outsourced is sold out, I'll have to find another movie to replace it. Possibilities include French for Beginners, Mushihi, The Three Musketeers (animated), and Eagle vs. Shark.
Larry Osterman mentioned this almost in passing quite a while ago, that the parameters to PostQueuedCompletionStatus are not interpreted by the operating system. Well, obviously the first parameter, the handle to the completion port, is interpreted as the handle to the completion port. But the other parameters, dwNumberOfBytesTransferred, dwCompletionKey, and lpOverlapped are not interpreted at all. Even though they have names, the names don't mean anything. Whatever values you pass for those three parameters merely pop out of GetQueuedCompletionStatus when the notification packet makes it to the head of the queue.
PostQueuedCompletionStatus
dwNumberOfBytesTransferred
dwCompletionKey
lpOverlapped
GetQueuedCompletionStatus
Why do the parameters have names if the names don't mean anything?
Because the operating system itself will post notifications to the completion port if you ask it to, and in that case, the values returned by the GetQueuedCompletionStatus function really mean something related to their names. For example, if you issued an asynchronous read to a file that is associated with a completion port, then the dwNumberOfBytesTransferred really is the number of bytes transferred, the dwCompletionKey really is the completion key that you associated with the file handle when you called CreateIoCompletionPort, and the lpOverlapped really is the pointer to the OVERLAPPED structure that you originally issued the read request against.
CreateIoCompletionPort
OVERLAPPED
But if you call PostQueuedCompletionStatus manually, then you can choose any values you want. Of course, if you're going to mix operating system-generated completion port activity with manually-generated completion port activity, it would be in your best interest to use the dwCompletionKey (or if you're really clever, the lpOverlapped) in a consistent manner so that you can tell whether a notification came from the I/O subsystem or was one you generated manually.
But it's up to you.
Occasionally, somebody will use the fact that they were nominated for the Nobel Prize as some sort of proof that they are a qualified or well-respected person. Except that it proves no such thing.
This isn't like the Academy Awards or the Pulizter Prize for which receiving a nomination means that you are one of a handful of finalists. For the Nobel Prize committee, nomination is just the first step, and there is no restriction on how many people can be nominated. In particular, the list of people authorized to submit nominations for the Nobel Peace Prize includes "members of national assemblies and governments of states." For the United States, this means that any member of the Executive Branch and any member of Congress can submit a nomination. Deputy Under-Secretary of Transportation? Sure.
The easiest way in is to convince a House Representative to submit a nomination for you, since there are over 400 of those positions, and each one represents fewer than a million people. Representatives are known for being quirky, so shop around. I'm sure you'll find somebody who would be willing to submit your name. It costs them nothing, after all.
According to the rules of the Nobel Committee, the list of nominees (and nominators) is kept secret for fifty years. You can search the database of Peace Prize nominees from 1901 to 1951 to see whether your favorite figure or organization is in it.
With a nod to Godwin's Law,† I point out that even Adolf Hitler was nominated for a Nobel Peace Prize.
†Notice that I am not invoking Godwin's Law, since this is not an instance of it. I'm merely acknowledging its existence.