none
Native C++ return "HRESULT - 0x80010106 - Cannot change thread mode after it is set. " in .NET web service

    Question

  • I have a .NET web service which uses PythonNET 2.0 to load a native Python DLL.  In this Python DLL, it does following call:

     

    DWORD ret=CoInitialize(NULL);

     

    and it returns "HRESULT - 0x80010106 - Cannot change thread mode after it is set. ".  I found KB824480, http://support.microsoft.com/kb/824480, but it doesn't solve my problem because I have a different context.  Can anybody help me this out?  It works on Windows XP, and Windows Server 2003 SP1.  It is reproducible on Window Server 2003 SP2.

    Monday, September 17, 2007 5:26 PM

Answers

  • This is quite common when you DLL is not the first DLL that may initializes COM. We have the same problem in the C++ compiler and we stuff like the following:

     

    Code Snippet

    HRESULT hr = CoInitialize(NULL);

     

    // Only record that we initialized COM if that is what we really

    // did. An error code of RPC_E_CHANGED_MODE means that the call

    // to CoInitialize failed because COM had already been initialized

    // on another mode - which isn't a fatal condition and so in this

    // case we don't want to call CoUninitialize

    if (FAILED(hr))

    {

       if (hr != RPC_E_CHANGED_MODE)

       {

           fatal_error(...);

       }

    }

    else

    {

       COMIsLoaded = true;

    }

     

    As you can see we treat RCP_E_CHANGED_MODE as an ignorable failure (which it is in most cases). One important thing to note is that as this call to CoInitialize "failed" we don't want to call the "matching" CoUninitialize: we leave that up to the CoUninitialize that "matches" the original call to CoInitialize.

    Monday, September 17, 2007 10:56 PM
  • What does the "IMyCOM" pointer you're calling through have to do with the "iValidator" into which you placed the CoCreated interface pointer?

    Wednesday, September 19, 2007 12:15 AM
  • I solve it myself:

     

    create a new thread and put all those COM related code in that thread.

    Friday, September 21, 2007 7:02 PM

All replies

  • This is quite common when you DLL is not the first DLL that may initializes COM. We have the same problem in the C++ compiler and we stuff like the following:

     

    Code Snippet

    HRESULT hr = CoInitialize(NULL);

     

    // Only record that we initialized COM if that is what we really

    // did. An error code of RPC_E_CHANGED_MODE means that the call

    // to CoInitialize failed because COM had already been initialized

    // on another mode - which isn't a fatal condition and so in this

    // case we don't want to call CoUninitialize

    if (FAILED(hr))

    {

       if (hr != RPC_E_CHANGED_MODE)

       {

           fatal_error(...);

       }

    }

    else

    {

       COMIsLoaded = true;

    }

     

    As you can see we treat RCP_E_CHANGED_MODE as an ignorable failure (which it is in most cases). One important thing to note is that as this call to CoInitialize "failed" we don't want to call the "matching" CoUninitialize: we leave that up to the CoUninitialize that "matches" the original call to CoInitialize.

    Monday, September 17, 2007 10:56 PM
  • Jonathan - Thanks for your reply.

     

    OK, I ignore this error and make sure it won't call CoUninitialize() in the end.  But other problems come up:

     

    Code Snippet

    IMyCOM *=NULL;

     

    DWORD theErrorCode = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&iValidator);

    // this line works OK - at least the return value is S_OK.

     

    IMyCOM->SomeMethod();

    // The program is died here

     

     

    Now the Call Stack is:

     

    ntdll.dll!7c8285ec()

    [Frames below may be incorrect and/or ...

    ntdll.dll!7c826f4b()

    kernel32.dll!

    mscorwks.dll

    ...

     

    Tuesday, September 18, 2007 9:51 PM
  • What does the "IMyCOM" pointer you're calling through have to do with the "iValidator" into which you placed the CoCreated interface pointer?

    Wednesday, September 19, 2007 12:15 AM
  • Sorry!  I missed *iValidator* here.  So the correct code should be:

     

    Code Snippet

    IMyCOM *iValidator = NULL;

     

    DWORD theErrorCode = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&iValidator);

    // this line works OK - at least the return value is S_OK.

     

    iValidator->SomeMethod();

    // The program is died here

     

     

    IMyCOM is the interface type in a COM I'm try to load  in my native DLL.
    Wednesday, September 19, 2007 12:37 AM
  • I solve it myself:

     

    create a new thread and put all those COM related code in that thread.

    Friday, September 21, 2007 7:02 PM