• The Old New Thing

    When can a thread receive window messages?

    • 16 Comments

    Everybody who has messed with window messaging knows that GetMessage and PeekMessage retrieve queued messages, which are dispatched to windows via DispatchMessage.

    Most people also know that GetMessage and PeekMessage will also dispatch nonqueued messages. (All pending nonqueued messages are dispatched, then the first queued message is returned.)

    But apparently not many people realize that SendMessage will also dispatch messages!

    If one thread T1 send a message to a window that belongs to another thread T2, the sending thread T1 is put to sleep until the receiving thread replies to the message. But if somebody else sends a message to thread T1, thread T1 is woken to process the message, then is returned to sleep.

    Why is that?

    Well, when two threads T1 and T2 are working together, it's common that thread T1 may send a message to thread T2, and while handling the message, thread T2 will send messages back to thread T1 before it returns to T1. Therefore, thread T1 must be ready to accept incoming sent messages.

    For example, thread T1 may send a message saying, "Tell me about all the X's that you know." Thread T2 will then send one message back to thread T1 saying, "Here's an X", and then another message to say "Here's another X", and so on, until it has finished telling thread T1 about all the X's, at which point it returns.

    Thread T1 now knows, when the original message returns, that it has received the entire list of X's from thread 2.

    This back-and-forth is how DDE service discovery works.

    Another case is that thread T1 sends a message to thread T2, and thread T2 needs to ask thread T1 for help before it can finish the operation. This isn't as strange as it sounds. You do something similar all the time without realizing it when you respond to a WM_NOTIFY message by sending messages back to the control that sent the notification. (For example, you may respond to a LVN_ITEMACTIVATE by sending back a LVM_GETITEM to get information about the item that was activated.)

    So remember: Any time you send a message, there is a potential for re-entrancy.

  • The Old New Thing

    Deleted but not yet forgotten

    • 18 Comments

    Earlier, I discussed the interactions of the various FILE_SHARE_* flags, then Larry Osterman took this as inspiration to give a history of the file sharing flags.

    If a file is opened with delete-sharing enabled and you delete the file, the file doesn't actually go away until the open handles are closed. In the meantime, the file hangs around as a zombie. (Under Unix, a deleted file with open handles is removed from the directory and merely floats around in the happy sea of inodes with no name.)

    Why doesn't the file go away?

    Well, one reason is that device drivers can ask for the name of the file that corresponds to an open handle. If the directory entry were removed, then there would be no name to return! (What would you expect to be returned from GetModuleFileName if the module no longer exists? Should it be possible for GetModuleFileName to return ERROR_FILE_NOT_FOUND?)

    Another reason is that if power were to be lost while a "forgotten but not lost" handle was still open, you would now have lost clusters on the disk.

    And a final reason is that a "pending delete" file isn't actually gone for good. A driver can "undelete" the file by clearing the delete-on-close flag!

  • The Old New Thing

    The suburbs make you fat, more researchers conclude

    • 12 Comments

    Two legs good - four wheels bad. (With apologies to George Orwell.)

    Researchers link increase car use with obesity.

    Each hour spent in a car was associated with a 6 percent increase in the likelihood of obesity and each half-mile walked per day reduced those odds by nearly 5 percent, the researchers found.

    A study last year came to a similar conclusion. Good to know that quality research yields quality results.

  • The Old New Thing

    Do not underestimate the power of the game Deer Hunter

    • 35 Comments

    During the run-up to Windows XP Service Pack 2 Beta in December of last year, there was a list of five bugs that the release management team decided were so critical that they were going to slip the beta until those bugs got fixed.

    The third bug on the list: Deer Hunter 4 won't run.

    Deer Hunter has the power to stop a beta.

  • The Old New Thing

    An easy way to determine whether you have a particular file permission

    • 21 Comments

    Sometimes you might want to determine whether you can do something without actually doing it. For example, you might want to know whether you have a particular permission in a directory, say permission to delete files from it.

    One way is to retrieve the ACL and then check whether the current user has the desired permission. The AccessCheck function does most of the heavy lifting there.

    Or you can realize, "Hey, wait a second, there is an entire security infrastructure whose job it is to decide who can access which files. Why not use it?"

    For example, here's how you can check whether the user has permission to delete files from a directory:

    BOOL CanDeleteFilesFromDirectory(LPCTSTR pszPath)
    {
      HANDLE h = CreateFile(pszPath, FILE_DELETE_CHILD, FILE_SHARE_READ |
                            FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
                            OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
      if (h != INVALID_HANDLE_VALUE) {
        CloseHandle(h);
      }
      return h != INVALID_HANDLE_VALUE;
    }
    

    What we did was open the directory (which requires backup semantics) and ask for FILE_DELETE_CHILD access. If it succeeded, then we have permission to delete files from it. [Corrected 7:52am]

    Note, of course, that this information is purely advisory. You shouldn't be making security decisions based on this, because the permissions might change between the time you check and the time you try.

  • The Old New Thing

    My first death threat

    • 32 Comments

    Actual feedback submitted to the microsoft.com web site many years ago.

    id: 13726
    Date: 1996-07-29 17:27:41.997
    Name: ***********
    Email: *************
    Area: Windows 95
    Comments:
    PLEASE read this entire email as it is quite serious. I just discovered today that in the Windows 95 operating system, there are no switches, command line options, or any way whatsoever to have the XCOPY command include hidden/system files in it's operations. It is clear that at some point in the development of the Windows 95 product, that somebody made a conscious decision to implement the xcopy command in this manner. It is also clear from looking at the Windows NT XCOPY command that it can be implemented in the manner I describe. Therefore, let me give fair warning. This may not be easy, and I will expect no help from Microsoft in finding out who this person (or persons) was that made this decision, but....eventually I will find out who made this decision, and I will kill them. This is not an idle threat - I will pursue this matter until it is resolved...whoever is responsible for this incredibly ridiculous implementation of what would be an otherwise useful tool will die at my hands, hopefully in a bloody, painful fashion. You will not get away. -J*hn ******

    J*hn, if you're still out there... the switch for copying hidden files on Windows 95 is /H. Same as Windows NT.

    Please don't kill me.

  • The Old New Thing

    Need to add 1.5kg and 350g?

    • 36 Comments

    Need to add 1.5kg and 350g? Don't take any chances. Go to a Certified Metrication Specialist.

  • The Old New Thing

    The dreaded "main" threading model

    • 7 Comments

    In the absence of an explicit threading model for your COM object, you get the "main" threading model. The "main" threading model is little-known, and that's a good thing. It's a relic from the days before multi-threading.

    The first thread in a process to initialize COM becomes declared the "main" thread. (It might be the first thread to initialize COM in apartment model; I forget.) When a "main" threaded object is created, COM marshals the creation call to the main thread, creates the object, then marshals the result back to the creator's thread. Similarly, when you invoke any method on the object, the call is marshalled to the main thread, invoked, then the result is marshalled back.

    In other words, a "main" threaded object is like an apartment threaded object, with the additional constraint that the only apartment that can use it is the one that the "main" thread belongs to.

    As you can imagine, this is a horrific performance penalty in any multithreaded application, since there is so much marshalling going on. Even worse, it completely bottlenecks the main thread because there are now all these objects that must be serviced on that thread and no other thread.

    Even worse than worse, all this marshalling creates new opportunities for re-entrancy. While waiting for the main thread to do its thing, the calling thread will likely process messages, which means that you can receive a window message at a time when you didn't expect it.

    So why does this awful threading model exist at all?

    For backwards compatibility with COM objects written before multithreaded support was added to COM. Back in those days, there was only one thread, so COM objects could be extremely lazy with their synchronization. In fact, they didn't need any! If you have only one thread, then you certainly don't need to coordinate your actions with other threads because there are none.

    That's also why "main" threading model is the default. Threading models were invented when multithreading support was added to COM. Before then, there were no threads, so no threading models. All old objects therefore didn't specify a threading model in their registration.

    The only reason you should even be aware of this ancient threading model in the first place is that if you forget to specify a threading model in your object registration, you will get the dreaded "main" threading model by default.

    And then you will wonder why your application's performance is horrible, and why you have all these strange re-entrancy problems.

  • The Old New Thing

    Letter carriers rebel

    • 19 Comments

    Letter carriers in both Sweden and Scotland have taken to refusing to deliver political advertisements from parties they personally find offensive.

    This isn't quite the stunning synchronicity as it may appear at first glance: Europe is gearing up for a continent-wide election.

  • The Old New Thing

    What does SHGFI_USEFILEATTRIBUTES mean?

    • 12 Comments

    One of the flags you can pass to the SHGetFileInfo function is SHGFI_USEFILEATTRIBUTES. What does this flag mean?

    It means, "Do not access the disk. Pretend that the file/directory exists, and that its file attributes are what I passed as the dwFileAttributes parameter. Do this regardless of whether it actually exists or not."

    You can use this flag to get the icon for a file type. For example, to get the icon for text files, pass a filename of "x.txt", pass SHGFI_USEFILEATTRIBUTES in the uFlags, and specify FILE_ATTRIBUTE_NORMAL as the file attributes.

    Why is the filename "x.txt"? Because you want it to have the extension ".txt", and you want it to be a valid filename. (Don't pass illegal filenames like "???.txt".)

    Why are the file attributes FILE_ATTRIBUTE_NORMAL? Because you want SHGetFileInfo to pretend that it is a normal file. (If you passed, say, FILE_ATTRIBUTE_DIRECTORY, then you would have gotten the folder icon back, since you told the function to pretend that "x.txt" was a directory.)

    Note that since you are telling SHGetFileInfo to "pretend", there are some things you lose by the nature of make-believe.

    For example, if the extension is a filetype whose icon changes depending on the contents of the file, then the dynamic icon will not be returned since there is no file. You told the function to "pretend", after all, and a pretend file has no contents.

Page 391 of 431 (4,308 items) «389390391392393»