PRB: Oleaut32 Hidden Window Blocks Apps Broadcasting Messages

Article translations Article translations
Article ID: 189427 - View products that this article applies to.
This article was previously published under Q189427
Expand all | Collapse all

On This Page

SYMPTOMS

An application that calls certain OLE Automation functions can block the global broadcast of Windows messages. For example, when a user double- clicks a desktop icon, the program associated with the icon might be blocked from starting and Windows Explorer might hang.

CAUSE

Certain Automation APIs (example:VariantChangeType) cause OLEAut32.dll to create a hidden top-level window that processes the WM_WININICHANGE message (for example, to get notifications like time zone changes, and so forth). This is used to invalidate OLE Automation's national language setting (NLS) cache. If the thread that called this function does not service the message queue, the hidden top-level window is starved of messages. Any global broadcast of messages using the SendMessage API will cause the broadcasting application to block indefinitely. Under the MTA programming model, a thread is not obligated to service the message queue. Hence an MTA thread that calls these Automation APIs can cause this problem.

RESOLUTION

There is no fixed set of OLE Automation APIs that create the hidden top-level window. However, the hidden top-level window is created the first time Ole Automation runtime needs to look at the NLS information. To work around this, spin a secondary thread and call an OLE Automation API first on the secondary thread (for example, VariantChangeType, changing from BSTR). This creates the hidden top-level window the secondary thread, and then pumps messages on the secondary thread. As a result, the hidden top- level window does not block broadcast messages. You can continue to use your automation methods in other threads. Send a WM_ QUIT message or use another form of inter-thread communication from the primary thread to end the secondary thread.


A supported hotfix is now available from Microsoft, but it is only intended to correct the problem that this article describes. Apply it only to systems that are experiencing this specific problem.

To resolve this problem, contact Microsoft Product Support Services to obtain the hotfix. For a complete list of Microsoft Product Support Services telephone numbers and information about support costs, visit the following Microsoft Web site:
http://support.microsoft.com/contactus/?ws=support
Note In special cases, charges that are ordinarily incurred for support calls may be canceled if a Microsoft Support Professional determines that a specific update will resolve your problem. The usual support costs will apply to additional support questions and issues that do not qualify for the specific update in question.

The English version of this fix should have the following file attributes or later:
   Date        Time    Version      Size      File name     
   -------------------------------------------------------
   05/29/2001  06:23p  2.40.4518.0  143,632   Asycfilt.dll
   05/29/2001  06:23p  2.40.4518.0  626,960   Oleaut32.dll
   05/29/2001  06:23p  5.0.4518.0   164,112   Olepro32.dll

				

NOTE: The problem will not occur in Windows 2000 because OLE Automation in Windows 2000 does not create the hidden window to get notifications regarding control panel changes.

STATUS

Microsoft has confirmed that this is a problem in the Microsoft products that are listed at the beginning of this article.

MORE INFORMATION

Steps to Reproduce Behavior

Use the following code to develop a console application:

Sample Code

    #define _WIN32_DCOM
    #include <windows.h>

    void main()
    {
   CoInitializeEx(NULL, COINIT_MULTITHREADED);
   VARIANT var,var1;
   VariantInit(&var);
   VariantInit(&var1);
   BSTR str = SysAllocString(L"Test");
   var.vt = VT_BSTR;
   var.bstrVal = str;
   VariantChangeType(&var, &var, 0, VT_I2);
   VariantClear(&var);
   VariantClear(&var1);
   while (1)
   {
      ;
   }
   CoUninitialize();

    }
				
Run this application. Run another application that broadcasts a message (for example, double click a .doc icon on the desktop). A message is broadcast to all the top-level windows that are using either SendMessage or a non-blocking variation of the SendMessage API (such as SendMessageTimeout). The broadcasting application is either blocked (hung) indefinitely or hung for the period of time it takes the call to timeout.

One work around for the problem is to create a secondary thread from the primary thread. After you have done this, call an automation method on the secondary thread's procedure (the secondary thread will create the hidden top-level window). Create a message loop to process the messages in the secondary thread. After everything is finished, close the secondary thread from the primary thread. Since there is a message pump in the secondary thread, any broadcasted message will be processed.

Sample Code

   #define _WIN32_DCOM
   #include <windows.h>

   HANDLE g_EventHandle;

   DWORD WINAPI SecondaryThread(LPVOID pInputParam)
   {

      HRESULT hr = S_OK;
      // Initialize COM with Mutithreaded.
      hr = CoInitializeEx(NULL,COINIT_MULTITHREADED);

      VARIANT var, var1;

      VariantInit(&var);
      VariantInit(&;var1);
      BSTR str = SysAllocString(L"Test");
      var.vt = VT_BSTR;
      var.bstrVal = str;

      // This will create a hidden window in this thread.
      hr = VariantChangeType(&var, &var, 0, VT_I2);

      // Set the global event.
      SetEvent(g_EventHandle);

      VariantClear(&var);
      VariantClear(&var1);

      MSG msg;

       // msg-pump.
       while (GetMessage(&msg, NULL, 0, 0))
       {
            // This was the message -- time to work.
            if ( msg.message == WM_USER+1)
            {
                // When done:
      break;
        }
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        CoUninitialize();
        return 0;
   }

   void main()
   {

      DWORD dwThreadID;
      HANDLE hThread;

      // Create a global Event.
      g_EventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
      // Spin the secondary thread.
      hThread = CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)
                             SecondaryThread,0,0,&dwThreadID);
      DWORD ret;
      // Wait until the event is set in the secondary thread.
      ret = WaitForSingleObject(g_EventHandle, INFINITE);

      CoInitializeEx(NULL, COINIT_MULTITHREADED);
       // Any other code.
       while (1)
      {
         ;
      }
      CoUninitialize();

      // Clean up the secondary thread.
      PostThreadMessage(dwThreadID,WM_USER+1,0,0);
      WaitForSingleObject(hThread, INFINITE);
      CloseHandle(hThread);
   }
				

Properties

Article ID: 189427 - Last Review: October 19, 2005 - Revision: 1.4
APPLIES TO
  • Microsoft Platform Software Development Kit-January 2000 Edition
Keywords: 
kboleapp kbqfe kbolearc kbprb kbhotfixserver KB189427

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com