• The Old New Thing

    The difference between thread-safety and re-entrancy

    • 19 Comments

    An operation is "thread-safe" if it can be performed from multiple threads safely, even if the calls happen simultaneously on multiple threads.

    An operation is re-entrant if it can be performed while the operation is already in progress (perhaps in another context). This is a stronger concept than thread-safety, because the second attempt to perform the operation can even come from within the same thread.

    Consider the following function:

    int length = 0;
    char *s = NULL;
    
    // Note: Since strings end with a 0, if we want to
    // add a 0, we encode it as "\0", and encode a
    // backslash as "\\".
    
    // WARNING! This code is buggy - do not use!
    
    void AddToString(int ch)
    {
      EnterCriticalSection(&someCriticalSection);
      // +1 for the character we're about to add
      // +1 for the null terminator
      char *newString = realloc(s, (length+1) * sizeof(char));
      if (newString) {
        if (ch == '\0' || ch == '\\') {
          AddToString('\\'); // escape prefix
        }
        newString[length++] = ch;
        newString[length] = '\0';
        s = newString;
      }
      LeaveCriticalSection(&someCriticalSection);
    }
    

    This function is thread-safe because the critical section prevents two threads from attempting to add to the string simultaneously. However, it is not re-entrant.

    The internal call to AddToString occurs while the data structures are unstable. At the point of the call, execution re-enters the start of the function AddToString, but this time the attempt to realloc the memory will use a pointer (s) that is no longer valid. (It was invalidated by the call to realloc performed by the caller.)

  • The Old New Thing

    You can already see the bug report that led to this dialog box

    • 24 Comments

    It's like stupid warning labels on consumer products: Once you read the warning label, you can already imagine the lawsuit that required the warning label to be written in the first place.

    Use that same imagination to interpret this Windows XP SP2 setup error message.

    [Dumb typo in title fixed 7:43am.]

  • The Old New Thing

    When does SHLoadInProc unload a DLL?

    • 13 Comments

    The SHLoadInProc function instructs Explorer to create an instance of a particular CLSID. This causes the DLL responsible for that CLSID to be loaded.

    But when is it unloaded?

    This is one of those puzzles you should be able to figure out by thinking about it.

    Consider: The object is created by calling CoCreateInstance and then immediately releasing the returned object. That's all. Explorer pays no attention to your DLL from then on.

    With this hint, maybe now you can answer the question: When is it unloaded?

    Still don't know? Here's another hint: The issue is no longer a shell issue. Now it's a COM issue.

    When is any DLL loaded via CoCreateInstance unloaded?

    Answer: The DLL is periodically asked whether it is safe to unload. Once the DLL response in the affirmative (via S_OK), COM will unload it.

  • The Old New Thing

    Ringside seats at Fruit Fly Fight Club

    • 7 Comments

    The first rule of Fruit Fly Fight Club: Flies can't talk about Fruit Fly Fight Club. Because they can't talk at all. At least not to humans.

    Researchers at Harvard Medical School took a break from studying lobster fighting and shifted their focus to fruit fly fights, and even mutant fruit fly fights.

    (Via The Annals of Improbable Research.)

    Fruit flies are strange creatures. Or perhaps it's that fruit fly researchers are strange creatures.

    One of my cousins was a fruit fly researcher. She took fruit fly testicles and squashed them and then studied them under a microscope, looking for... something... I forget. I think just finding the fruit fly testicles in the first place was accomplishment enough.

    Fruit fly researchers like to give their discoveries strange names. Typically, a gene is named after what results when you disable it. For example, a gene without which fruit flies die in two days is named Kenny, after the South Park character.

    My favorite: The gene without which fruit flies get drunk really easily is called cheap date. (That last page has several more funny gene names.)

    Yes, that's right. Fruit flies get drunk. There's a fruit fly drunk-o-meter, though I forget how it works. But one amusing aspect of fruit fly drunkenness is that just before they finally pass out, there's a big burst of activity.

    Strange gene naming has spread beyond the fruit fly world. There is a human gene named sonic hedgehog after the Sega video game character. (It's related to the fruit fly gene "hedgehog", so named because disabling it causes the fly to develop into a ball with spikes.)

  • The Old New Thing

    Suggestion box

    • 142 Comments

    Post suggestions for future topics here instead of posting off-topic comments. Note that the suggestion box is emptied and read periodically so don't be surprised if your suggestion vanishes. (Note also that I am under no obligation to accept any suggestion.)

    Topics I are more inclined to cover:

    • Windows history (particularly the Windows 95 era).
    • Windows user interface programming in Win32, and shell programming in particular.
    • General programming topics (selectively).
    • Issues of general interest.
    • My personal hobbies.

    Topics I am not inclined to cover:

    • The blog software itself.  You can send feedback about .Text to its author, Scott Watermasysk.
    • Internet Explorer. You can try IE folks like Tony Schreiner, jeffdav, and Dave Massy.
    • Visual Studio.  You can try one of the Visual Studio blogs.
    • Non-software Microsoft topics, such as product support policies, marketing tactics, and hiring policy.
    • Microsoft software that isn't Windows. (Exchange, Office, ...)
    • Windows topics outside user interface programming. (Plug and Play, Terminal Services, Windows Messenger, Outlook Express, SQL, IIS, remoting, SOA...)
    • User interface programming in anything other than Win32. (Because I know nothing about it.)
    • Debugging a specific problem. (Not of general interest.)
    • Legal issues.
    • Predictions for the future. (What's the title of this blog again?)
  • The Old New Thing

    Hong Kong crocodile caught at last.

    • 6 Comments

    After over half a year of eluding experts, the Hong Kong crocodile was caught at last. What amused me was that the article said that the creature had eluded an expert crocodile hunter from Australia named... John Lever? (Curiously, in this article, he is given credit for capturing the croc.)

    Not the self-proclaimed Crocodile Hunter Steve Irwin? Where's his PR department when he needs them?

  • The Old New Thing

    Monitor giving you a headache? Check the refresh rate.

    • 46 Comments

    Some people are more sensitive to lower monitor refresh rates than others. Go to the display control panel and click to the Settings tab. From there, click the Advanced button and go to the Monitor tab. From there, you can adjust your screen refresh rate.

    As a rule of thumb, higher refresh rates are less likely to cause eyestrain.

    If you pick a refresh rate and your monitor goes all blooey, don't panic. Just wait fifteen seconds and the system will switch back to the original settings. (If you have a Plug and Play monitor, it's supposed to report the refresh rates it supports, but sometimes that doesn't work.)

    Note that not all refresh rates are available at all screen resolutions, so if you want to crank the rate higher, you may have to sacrifice resolution.

  • The Old New Thing

    At least it's easier than learning Finnish

    • 38 Comments

    Finnish Radio station YLE offers weekly news summaries in classical Latin. Because practically nobody outside Finland would understand the news in Finnish...

    In my random travels around the Internet, I stumbled across this article on the subject of teaching Finnish to foreigners: Finnish's status as an official EU language has created demand for interpreters. Finns have long accepted that they will have to learn the languages of others, considering the language's comparatively minor exposure on the world stage. But now, others will have to learn Finnish!

    I occasionally toy with the idea of learning Finnish myself but each time conclude that it would be too much work. Though I do have as a long-term goal to learn the major modern Germanic languages. In probable order of study: English, German, Swedish, Norwegian, Dutch, Afrikaans, and Icelandic.

    (Hey, I left out Danish.)

  • The Old New Thing

    The evolution of dialog templates - Summary

    • 4 Comments

    As promised, here's the tabular version of the evolution of dialog templates. It doesn't contain any new information, but it may give you a little glimpse into how things evolved to see the small changes highlighted against each other.

    16-bit classic 32-bit classic
    16-bit extended 32-bit extended
    Header style
    8-bit item count
    coordinates
    extended style, style
    16-bit item count
    coordinates
    help ID, extended style, style
    8-bit item count
    coordinates
    help ID, extended style, style
    16-bit item count
    coordinates
    Menu ASCIIZ or ordinal UNICODEZ or ordinal
    ASCIIZ or ordinal UNICODEZ or ordinal
    Class ASCIIZ or ordinal UNICODEZ or ordinal
    ASCIIZ or ordinal UNICODEZ or ordinal
    Caption ASCIIZ UNICODEZ
    ASCIIZ UNICODEZ
    Font
    (if DS_SETFONT)
    size
    ASCIIZ font name
    size
    UNICODEZ font name
    size, weight, italic, charset
    ASCIIZ font name
    size, weight, italic, charset
    UNICODEZ font name
    Item template alignment BYTE DWORD
    BYTE DWORD
    Item templates size, position
    16-bit ID
    style
    class, ASCIIZ text/ordinal
    8-bit extra data
    size, position
    16-bit ID
    extended style, style
    class, UNICODEZ text/ordinal
    16-bit extra data
    size, position
    32-bit ID
    help ID, extended style, style
    class, ASCIIZ text/ordinal
    16-bit extra data
    size, position
    32-bit ID
    help ID, extended style, style
    class, UNICODEZ text/ordinal
    16-bit extra data
  • The Old New Thing

    The evolution of dialog templates - 32-bit Extended Templates

    • 10 Comments

    At last we reach our goal, the 32-bit extended dialog template, known in resource files as DIALOGEX. I will celebrate this with a gratuitous commutative diagram:

    16-bit DIALOG
    32
    32-bit DIALOG
    EX EX
    16-bit DIALOGEX
    32
    32-bit DIALOGEX

    Isn't that special.

    Okay, so let's get going. The 32-bit extended dialog template is the 32-bit version of the 16-bit extended dialog template, so you won't see any real surprises if you've been following along.

    Once again, we start with a header, this time the 32-bit extended header.

    WORD  wDlgVer;      // version number - always 1
    WORD  wSignature;   // always 0xFFFF
    DWORD dwHelpID;     // help ID
    DWORD dwExStyle;    // window extended style
    DWORD dwStyle;      // dialog style
    WORD  cItems;       // number of controls in this dialog
    WORD  x;            // x-coordinate
    WORD  y;            // y-coordinate
    WORD  cx;           // width
    WORD  cy;           // height
    

    The first two fields serve exactly the same purpose as the 16-bit extended template: They identify this header as an extended dialog template.

    As before, the next two fields are new. The help identifier is attached to the dialog via the SetWindowContextHelpId function, and the extended dialog style shouldn't be a surprise.

    You know the drill: Next come the three strings for the menu, class, and dialog title. Since this is the 32-bit template, the strings are Unicode.

    As with the 16-bit extended template, the optional custom font consists of a little more information than the non-extended template:

    WORD wPoint;        // point size
    WORD wWeight;       // font weight
    BYTE bItalic;       // 1 if italic, 0 if not
    BYTE bCharSet;      // character set
    WCHAR szFontName[]; // variable-length
    

    As before, the point, weight, italic and character set are all passed to the CreateFont function.

    After the header come the dialog item templates, each of which must be aligned on a DWORD boundary.

    DWORD dwHelpID;     // help identifier
    DWORD dwExStyle;    // window extended style
    DWORD dwStyle;      // window style
    WORD  x;            // x-coordinate (DLUs)
    WORD  y;            // y-coordinate (DLUs)
    WORD  cx;           // width (DLUs)
    WORD  cy;           // height (DLUs)
    DWORD dwID;         // control ID
    WCHAR szClassName[];// variable-length (possibly ordinal)
    WCHAR szText[];     // variable-length (possibly ordinal)
    WORD  cbExtra;      // amount of extra data
    BYTE  rgbExtra[cbExtra]; // extra data follows (usually none)
    

    The changes here:

    • New dwHelpID and dwExStyle fields.
    • The dwStyle field has moved.
    • The control ID has grown to a 32-bit value.

    Not that expanding the control ID to a 32-bit value helps any, because WM_COMMAND and similar messages still use a 16-bit value to pass the control ID. So in practice, you can't use a value greater than 16 bits. (Well, you can always ignore the control ID field and retrieve the full 32-bit control ID via the GetDlgCtrlID function, assuming you have the window handle of the control available.)

    And that's all there is to it.

    Here's the customary annotated hex dump.

    0000  01 00 FF FF 00 00 00 00-00 00 00 00 C4 00 C8 80  ................
    0010  0B 00 24 00 2C 00 E6 00-5E 00 00 00 00 00 52 00  ..$.,...^.....R.
    0020  65 00 70 00 6C 00 61 00-63 00 65 00 00 00 08 00  e.p.l.a.c.e.....
    0030  00 00 00 01 4D 00 53 00-20 00 53 00 68 00 65 00  ....M.S. .S.h.e.
    0040  6C 00 6C 00 20 00 44 00-6C 00 67 00 00 00 00 00  l.l. .D.l.g.....
    0050  00 00 00 00 00 00 00 00-00 00 02 50 04 00 09 00  ...........P....
    0060  30 00 08 00 FF FF FF FF-FF FF 82 00 46 00 69 00  0...........F.i.
    0070  26 00 6E 00 64 00 20 00-57 00 68 00 61 00 74 00  &.n.d. .W.h.a.t.
    0080  3A 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  :...............
    0090  80 00 83 50 36 00 07 00-72 00 0C 00 80 04 00 00  ...P6...r.......
    00A0  FF FF 81 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
    00B0  00 00 02 50 04 00 1A 00-30 00 08 00 FF FF FF FF  ...P....0.......
    00C0  FF FF 82 00 52 00 65 00-26 00 70 00 6C 00 61 00  ....R.e.&.p.l.a.
    00D0  63 00 65 00 20 00 77 00-69 00 74 00 68 00 3A 00  c.e. .w.i.t.h.:.
    00E0  00 00 00 00 00 00 00 00-00 00 00 00 80 00 83 50  ...............P
    00F0  36 00 18 00 72 00 0C 00-81 04 00 00 FF FF 81 00  6...r...........
    0100  00 00 00 00 00 00 00 00-00 00 00 00 03 00 03 50  ...............P
    0110  05 00 2E 00 68 00 0C 00-10 04 00 00 FF FF 80 00  ....h...........
    0120  4D 00 61 00 74 00 63 00-68 00 20 00 26 00 77 00  M.a.t.c.h. .&.w.
    0130  68 00 6F 00 6C 00 65 00-20 00 77 00 6F 00 72 00  h.o.l.e. .w.o.r.
    0140  64 00 20 00 6F 00 6E 00-6C 00 79 00 00 00 00 00  d. .o.n.l.y.....
    0150  00 00 00 00 00 00 00 00-03 00 01 50 05 00 3E 00  ...........P..>.
    0160  3B 00 0C 00 11 04 00 00-FF FF 80 00 4D 00 61 00  ;...........M.a.
    0170  74 00 63 00 68 00 20 00-26 00 63 00 61 00 73 00  t.c.h. .&.c.a.s.
    0180  65 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  e...............
    0190  01 00 03 50 AE 00 04 00-32 00 0E 00 01 00 00 00  ...P....2.......
    01A0  FF FF 80 00 26 00 46 00-69 00 6E 00 64 00 20 00  ....&.F.i.n.d. .
    01B0  4E 00 65 00 78 00 74 00-00 00 00 00 00 00 00 00  N.e.x.t.........
    01C0  00 00 00 00 00 00 01 50-AE 00 15 00 32 00 0E 00  .......P....2...
    01D0  00 04 00 00 FF FF 80 00-26 00 52 00 65 00 70 00  ........&.R.e.p.
    01E0  6C 00 61 00 63 00 65 00-00 00 00 00 00 00 00 00  l.a.c.e.........
    01F0  00 00 00 00 00 00 01 50-AE 00 26 00 32 00 0E 00  .......P..&.2...
    0200  01 04 00 00 FF FF 80 00-52 00 65 00 70 00 6C 00  ........R.e.p.l.
    0210  61 00 63 00 65 00 20 00-26 00 41 00 6C 00 6C 00  a.c.e. .&.A.l.l.
    0220  00 00 00 00 00 00 00 00-00 00 00 00 00 00 01 50  ...............P
    0230  AE 00 37 00 32 00 0E 00-02 00 00 00 FF FF 80 00  ..7.2...........
    0240  43 00 61 00 6E 00 63 00-65 00 6C 00 00 00 00 00  C.a.n.c.e.l.....
    0250  00 00 00 00 00 00 00 00-00 00 01 50 AE 00 4B 00  ...........P..K.
    0260  32 00 0E 00 0E 04 00 00-FF FF 80 00 26 00 48 00  2...........&.H.
    0270  65 00 6C 00 70 00 00 00-00 00                    e.l.p.....
    

    As always, the header comes first.

    0000  01 00         // wVersion
    0002  FF FF         // wSignature
    0004  00 00 00 00   // dwHelpID
    0008  00 00 00 00   // dwExStyle
    000C  C4 00 C8 80   // dwStyle
    0010  0B 00         // cItems
    0012  24 00 2C 00   // x, y
    0016  E6 00 5E 00   // cx, cy
    

    Nothing surprising here; you've seen it before.

    wVersion = 0x0001 = 1
    wSignature = 0xFFFF
    dwHelpID = 0x00000000 = 0
    dwExStyle = 0x00000000 = 0
    dwStyle = 0x80C800C4 = WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_SETFONT | DS_MODALFRAME | DS_3DLOOK
    cItems = 0x000B = 11
    x = 0x0024 = 36
    y = 0x002C = 44
    cx = 0x00E6 = 230
    cy = 0x005E = 94

    After the header come the menu name, class name, and dialog title:

    001A  00 00         // no menu
    001C  00 00         // default dialog class
    001E  52 00 65 00 70 00 6C 00 61 00 63 00
          65 00 00 00   // "Replace"
    

    And since DS_SETFONT is set in the dialog style, font information comes next. Notice that the additional font characteristics are included in the extended template.

    002E  08 00         // wSize = 8
    0030  00 00         // wWeight = 0x0000 = FW_DONTCARE
    0032  00            // Italic
    0033  01            // Character set = 0x01 = DEFAULT_CHARSET
    0034  4D 00 53 00 20 00 53 00 68 00 65 00 6C 00
          6C 00 20 00 44 00 6C 00 67 00 00 00
                        // "MS Shell Dlg"
    

    You've seen this all before. Here come the extended dialog item templates. Remember, these must be DWORD-aligned.

    004E  00 00         // padding to achieve DWORD alignment
    
    // First control
    0050  00 00 00 00   // dwHelpID
    0054  00 00 00 00   // dwExStyle
    0058  00 00 02 50   // dwStyle
    005C  04 00 09 00   // x, y
    0060  30 00 08 00   // cx, cy
    0064  FF FF FF FF   // wID
    0068  FF FF 82 00   // szClass = ordinal 0x0082 = "static"
    006C  46 00 69 00
    0070  26 00 6E 00 64 00 20 00 77 00 68 00 61 00 74 00
    0080  3A 00 00 00   // "Fi&nd what:"
    0084  00 00         // no extra data
    0086  00 00         // padding to achieve DWORD alignment
    
    // Second control
    
    0088  00 00 00 00   // dwHelpID
    008C  00 00 00 00   // dwExStyle
    0090  80 00 83 50   // dwStyle
    0094  36 00 07 00   // x, y
    0098  72 00 0C 00   // cx, cy
    009C  80 04 00 00   // wID
    00A0  FF FF 81 00   // "edit"
    00A4  00 00         // ""
    00A6  00 00         // no extra data
    
    // Third control
    00A8  00 00 00 00   // dwHelpID
    00AC  00 00 00 00   // dwExStyle
    00B0  00 00 02 50   // dwStyle
    00B4  04 00 1A 00   // x, y
    00B8  30 00 08 00   // cx, cy
    00BC  FF FF FF FF   // wID
    00C0  FF FF 82 00   // "static"
    00C4  52 00 65 00 26 00 70 00 6C 00 61 00
    00D0  63 00 65 00 20 00 77 00 69 00 74 00 68 00 3A 00
    00E0  00 00         // "Re&place with:"
    00E2  00 00         // no extra data
    
    // Fourth control
    00E4  00 00 00 00   // dwHelpID
    00E8  00 00 00 00   // dwExStyle
    00EC  80 00 83 50   // dwStyle
    00F0  36 00 18 00   // x, y
    00F4  72 00 0C 00   // cx, cy
    00F8  81 04 00 00   // wID
    00FC  FF FF 81 00   // "edit"
    0100  00 00         // ""
    0102  00 00         // no extra data
    
    // Fifth control
    0104  00 00 00 00   // dwHelpID
    0108  00 00 00 00   // dwExStyle
    010C  03 00 03 50   // dwStyle
    0110  05 00 2E 00   // x, y
    0114  68 00 0C 00   // cx, cy
    0118  10 04 00 00   // wID
    011C  FF FF 80 00   // "button"
    0120  4D 00 61 00 74 00 63 00 68 00 20 00 26 00 77 00
    0130  68 00 6F 00 6C 00 65 00 20 00 77 00 6F 00 72 00
    0140  64 00 20 00 6F 00 6E 00 6C 00 79 00 00 00
                        // "Match &whole word only"
    014E  00 00         // no extra data
    
    // Sixth control
    0150  00 00 00 00   // dwHelpID
    0154  00 00 00 00   // dwExStyle
    0158  03 00 01 50   // dwStyle
    015C  05 00 3E 00   // x, y
    0160  3B 00 0C 00   // cx, cy
    0164  11 04 00 00   // wID
    0168  FF FF 80 00   // "button"
    016C  4D 00 61 00
    0170  74 00 63 00 68 00 20 00 26 00 63 00 61 00 73 00
    0180  65 00 00 00   // "Match &case"
    0184  00 00         // no extra data
    0186  00 00         // padding to achieve DWORD alignment
    
    // Seventh control
    0188  00 00 00 00   // dwHelpID
    018C  00 00 00 00   // dwExStyle
    0190  01 00 03 50   // dwStyle
    0194  AE 00 04 00   // x, y
    0198  32 00 0E 00   // cx, cy
    019C  01 00 00 00   // wID
    01A0  FF FF 80 00   // "button"
    01A4  26 00 46 00 69 00 6E 00 64 00 20 00
    01B0  4E 00 65 00 78 00 74 00 00 00
                        // "&Find Next"
    01BA  00 00         // no extra data
    
    // Eighth control
    01BC  00 00 00 00   // dwHelpID
    01C0  00 00 00 00   // dwExStyle
    01C4  00 00 03 50   // dwStyle
    01C8  AE 00 15 00   // x, y
    01CC  32 00 0E 00   // cx, cy
    01D0  00 04 00 00   // wID
    01D4  FF FF 80 00   // "button"
    01D8  26 00 52 00 65 00 70 00
                        // "&Replace"
    01E0  6C 00 61 00 63 00 65 00 00 00
    01EA  00 00         // no extra data
    
    // Ninth control
    01EC  00 00 00 00   // dwHelpID
    01F0  00 00 00 00   // dwExStyle
    01F4  00 00 03 50   // dwStyle
    01F8  AE 00 26 00   // x, y
    01FC  32 00 0E 00   // cx, cy
    0200  01 04 00 00   // wID
    0204  FF FF 80 00   // "button"
    0208  52 00 65 00 70 00 6C 00
    0210  61 00 63 00 65 00 20 00 26 00 41 00 6C 00 6C 00
    0220  00 00         // "Replace &All"
    0222  00 00         // no extra data
    
    // Tenth control
    0224  00 00 00 00   // dwHelpID
    0228  00 00 00 00   // dwExStyle
    022C  00 00 01 50   // dwStyle
    0230  AE 00 37 00   // x, y
    0234  32 00 0E 00   // cx, cy
    0238  02 00 00 00   // wID
    023C  FF FF 80 00   // "button"
    0240  43 00 61 00 6E 00 63 00 65 00 6C 00 00 00
                        // "Cancel"
    024E  00 00         // no extra data
    
    // Eleventh control
    0250  00 00 00 00   // dwHelpID
    0254  00 00 00 00   // dwExStyle
    0258  00 00 03 50   // dwStyle
    025C  AE 00 4B 00   // x, y
    0260  32 00 0E 00   // cx, cy
    0264  0E 04 00 00   // wID
    0268  FF FF 80 00   // "button"
    026C  26 00 48 00
    0270  65 00 6C 00 70 00 00 00
                        // "&Help"
    0278  00 00         // no extra data
    

    The original dialog template is, of course, the one you're probably sick of by now. The only change is that the DIALOG keyword has been changed to DIALOGEX.

    DIALOGEX 36, 44, 230, 94
    ...
    

    So that's the last of the dialog template formats. Tomrrow, a chart that tries to summarize everything at a glance.

Page 388 of 431 (4,310 items) «386387388389390»