Fix a possible memory leak when extracting from an ICO file.
[wine] / dlls / ole32 / compobj.c
index e58b00a..8ded0bc 100644 (file)
 #include "winerror.h"
 #include "winreg.h"
 #include "wownt32.h"
-#include "wtypes.h"
 #include "wine/unicode.h"
-#include "wine/obj_base.h"
-#include "wine/obj_clientserver.h"
-#include "wine/obj_misc.h"
-#include "wine/obj_marshal.h"
-#include "wine/obj_storage.h"
-#include "wine/obj_channel.h"
-#include "wine/winbase16.h"
+#include "objbase.h"
 #include "compobj_private.h"
-#include "ifs.h"
 
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
 /****************************************************************************
- *  COM External Lock structures and methods declaration
- *
- *  This api provides a linked list to managed external references to
- *  COM objects.
+ * This section defines variables internal to the COM module.
  *
- *  The public interface consists of three calls:
- *      COM_ExternalLockAddRef
- *      COM_ExternalLockRelease
- *      COM_ExternalLockFreeList
+ * TODO: Most of these things will have to be made thread-safe.
  */
+HINSTANCE       COMPOBJ_hInstance32 = 0;
 
-#define EL_END_OF_LIST 0
-#define EL_NOT_FOUND   0
+static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid, DWORD dwClsContext, LPUNKNOWN*  ppUnk);
+static void COM_RevokeAllClasses();
+static void COM_ExternalLockFreeList();
 
-/*
- * Declaration of the static structure that manage the
- * external lock to COM  objects.
+/*****************************************************************************
+ * Appartment management stuff
+ *
+ * NOTE:
+ *  per Thread values are stored in the TEB on offset 0xF80
+ *
+ *  see www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm
+ *
  */
-typedef struct COM_ExternalLock     COM_ExternalLock;
-typedef struct COM_ExternalLockList COM_ExternalLockList;
 
-struct COM_ExternalLock
-{
-  IUnknown         *pUnk;     /* IUnknown referenced */
-  ULONG            uRefCount; /* external lock counter to IUnknown object*/
-  COM_ExternalLock *next;     /* Pointer to next element in list */
-};
+typedef struct {
+        unsigned char          threadingModell;        /* we use the COINIT flags */
+        unsigned long          threadID;
+       long                    AppartmentLockCount;
+} OleAppartmentData;
 
-struct COM_ExternalLockList
-{
-  COM_ExternalLock *head;     /* head of list */
-};
+typedef struct {
+       OleAppartmentData       *AppartmentData;
+} OleThreadData;
 
+/* not jet used
+static CRITICAL_SECTION csAppartmentData = CRITICAL_SECTION_INIT("csAppartmentData");
+*/
 /*
- * Declaration and initialization of the static structure that manages
- * the external lock to COM objects.
+ * the first STA created in a process is the main STA
  */
-static COM_ExternalLockList elList = { EL_END_OF_LIST };
 
-/*
- * Public Interface to the external lock list
- */
-static void COM_ExternalLockFreeList();
-static void COM_ExternalLockAddRef(IUnknown *pUnk);
-static void COM_ExternalLockRelease(IUnknown *pUnk, BOOL bRelAll);
-void COM_ExternalLockDump(); /* testing purposes, not static to avoid warning */
+/* not jet used
+static OleAppartmentData * mainSTA;
+*/
 
 /*
- * Private methods used to managed the linked list
- */
-static BOOL COM_ExternalLockInsert(
-  IUnknown *pUnk);
-
-static void COM_ExternalLockDelete(
-  COM_ExternalLock *element);
-
-static COM_ExternalLock* COM_ExternalLockFind(
-  IUnknown *pUnk);
-
-static COM_ExternalLock* COM_ExternalLockLocate(
-  COM_ExternalLock *element,
-  IUnknown         *pUnk);
-
-/****************************************************************************
- * This section defines variables internal to the COM module.
- *
- * TODO: Most of these things will have to be made thread-safe.
+ * a Process can only have one MTA
  */
-HINSTANCE16     COMPOBJ_hInstance = 0;
-HINSTANCE       COMPOBJ_hInstance32 = 0;
-static int      COMPOBJ_Attach = 0;
 
-LPMALLOC16 currentMalloc16=NULL;
-LPMALLOC currentMalloc32=NULL;
+/* not jet used
+static OleAppartmentData * processMTA;
+*/
 
-HTASK16 hETask = 0;
-WORD Table_ETask[62];
 
 /*
  * This lock count counts the number of times CoInitialize is called. It is
@@ -158,30 +122,30 @@ typedef struct tagRegisteredClass
   struct tagRegisteredClass* nextClass;
 } RegisteredClass;
 
-static CRITICAL_SECTION csRegisteredClassList;
+static CRITICAL_SECTION csRegisteredClassList = CRITICAL_SECTION_INIT("csRegisteredClassList");
 static RegisteredClass* firstRegisteredClass = NULL;
 
-/* this open DLL table belongs in a per process table, but my guess is that
- * it shouldn't live in the kernel, so I'll put them out here in DLL
- * space assuming that there is one OLE32 per process.
+/*****************************************************************************
+ * This section contains OpenDllList definitions
+ *
+ * The OpenDllList contains only handles of dll loaded by CoGetClassObject or
+ * other functions what do LoadLibrary _without_ giving back a HMODULE.
+ * Without this list these handles would be freed never.
+ *
+ * FIXME: a DLL what says OK whenn asked for unloading is unloaded in the
+ * next unload-call but not before 600 sec.
  */
+
 typedef struct tagOpenDll {
   HINSTANCE hLibrary;
   struct tagOpenDll *next;
 } OpenDll;
 
-static CRITICAL_SECTION csOpenDllList;
+static CRITICAL_SECTION csOpenDllList = CRITICAL_SECTION_INIT("csOpenDllList");
 static OpenDll *openDllList = NULL; /* linked list of open dlls */
 
-/*****************************************************************************
- * This section contains prototypes to internal methods for this
- * module
- */
-static HRESULT COM_GetRegisteredClassObject(REFCLSID    rclsid,
-                                           DWORD       dwClsContext,
-                                           LPUNKNOWN*  ppUnk);
-
-static void COM_RevokeAllClasses();
+static void COMPOBJ_DLLList_Add(HANDLE hLibrary);
+static void COMPOBJ_DllList_FreeUnused(int Timeout);
 
 
 /******************************************************************************
@@ -189,14 +153,85 @@ static void COM_RevokeAllClasses();
  */
 void COMPOBJ_InitProcess( void )
 {
-    InitializeCriticalSection( &csRegisteredClassList );
-    InitializeCriticalSection( &csOpenDllList );
 }
 
 void COMPOBJ_UninitProcess( void )
 {
-    DeleteCriticalSection( &csRegisteredClassList );
-    DeleteCriticalSection( &csOpenDllList );
+}
+
+/*****************************************************************************
+ * This section contains OpenDllList implemantation
+ */
+
+static void COMPOBJ_DLLList_Add(HANDLE hLibrary)
+{
+    OpenDll *ptr;
+    OpenDll *tmp;
+
+    TRACE("\n");
+
+    EnterCriticalSection( &csOpenDllList );
+
+    if (openDllList == NULL) {
+        /* empty list -- add first node */
+        openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
+       openDllList->hLibrary=hLibrary;
+       openDllList->next = NULL;
+    } else {
+        /* search for this dll */
+        int found = FALSE;
+        for (ptr = openDllList; ptr->next != NULL; ptr=ptr->next) {
+           if (ptr->hLibrary == hLibrary) {
+               found = TRUE;
+               break;
+           }
+        }
+       if (!found) {
+           /* dll not found, add it */
+           tmp = openDllList;
+           openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
+           openDllList->hLibrary = hLibrary;
+           openDllList->next = tmp;
+       }
+    }
+
+    LeaveCriticalSection( &csOpenDllList );
+}
+
+static void COMPOBJ_DllList_FreeUnused(int Timeout)
+{
+    OpenDll *curr, *next, *prev = NULL;
+    typedef HRESULT(*DllCanUnloadNowFunc)(void);
+    DllCanUnloadNowFunc DllCanUnloadNow;
+
+    TRACE("\n");
+
+    EnterCriticalSection( &csOpenDllList );
+
+    for (curr = openDllList; curr != NULL; ) {
+       DllCanUnloadNow = (DllCanUnloadNowFunc) GetProcAddress(curr->hLibrary, "DllCanUnloadNow");
+
+       if ( (DllCanUnloadNow != NULL) && (DllCanUnloadNow() == S_OK) ) {
+           next = curr->next;
+
+           TRACE("freeing %p\n", curr->hLibrary);
+           FreeLibrary(curr->hLibrary);
+
+           HeapFree(GetProcessHeap(), 0, curr);
+           if (curr == openDllList) {
+               openDllList = next;
+           } else {
+             prev->next = next;
+           }
+
+           curr = next;
+       } else {
+           prev = curr;
+           curr = curr->next;
+       }
+    }
+
+    LeaveCriticalSection( &csOpenDllList );
 }
 
 /******************************************************************************
@@ -212,17 +247,6 @@ DWORD WINAPI CoBuildVersion(void)
     return (rmm<<16)+rup;
 }
 
-/******************************************************************************
- *             CoInitialize    [COMPOBJ.2]
- * Set the win16 IMalloc used for memory management
- */
-HRESULT WINAPI CoInitialize16(
-       LPVOID lpReserved       /* [in] pointer to win16 malloc interface */
-) {
-    currentMalloc16 = (LPMALLOC16)lpReserved;
-    return S_OK;
-}
-
 /******************************************************************************
  *             CoInitialize    [OLE32.26]
  *
@@ -307,18 +331,6 @@ HRESULT WINAPI CoInitializeEx(
   return hr;
 }
 
-/***********************************************************************
- *           CoUninitialize   [COMPOBJ.3]
- * Don't know what it does.
- * 3-Nov-98 -- this was originally misspelled, I changed it to what I
- *   believe is the correct spelling
- */
-void WINAPI CoUninitialize16(void)
-{
-  TRACE("()\n");
-  CoFreeAllLibraries();
-}
-
 /***********************************************************************
  *           CoUninitialize   [OLE32.47]
  *
@@ -367,49 +379,6 @@ void WINAPI CoUninitialize(void)
   }
 }
 
-/***********************************************************************
- *           CoGetMalloc    [COMPOBJ.4]
- * RETURNS
- *     The current win16 IMalloc
- */
-HRESULT WINAPI CoGetMalloc16(
-       DWORD dwMemContext,     /* [in] unknown */
-       LPMALLOC16 * lpMalloc   /* [out] current win16 malloc interface */
-) {
-    if(!currentMalloc16)
-       currentMalloc16 = IMalloc16_Constructor();
-    *lpMalloc = currentMalloc16;
-    return S_OK;
-}
-
-/******************************************************************************
- *             CoGetMalloc     [OLE32.20]
- *
- * RETURNS
- *     The current win32 IMalloc
- */
-HRESULT WINAPI CoGetMalloc(
-       DWORD dwMemContext,     /* [in] unknown */
-       LPMALLOC *lpMalloc      /* [out] current win32 malloc interface */
-) {
-    if(!currentMalloc32)
-       currentMalloc32 = IMalloc_Constructor();
-    *lpMalloc = currentMalloc32;
-    return S_OK;
-}
-
-/***********************************************************************
- *           CoCreateStandardMalloc [COMPOBJ.71]
- */
-HRESULT WINAPI CoCreateStandardMalloc16(DWORD dwMemContext,
-                                         LPMALLOC16 *lpMalloc)
-{
-    /* FIXME: docu says we shouldn't return the same allocator as in
-     * CoGetMalloc16 */
-    *lpMalloc = IMalloc16_Constructor();
-    return S_OK;
-}
-
 /******************************************************************************
  *             CoDisconnectObject      [COMPOBJ.15]
  *             CoDisconnectObject      [OLE32.8]
@@ -420,37 +389,33 @@ HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
     return S_OK;
 }
 
-/***********************************************************************
- *           IsEqualGUID [COMPOBJ.18]
- *
- * Compares two Unique Identifiers.
+/******************************************************************************
+ *             CoCreateGuid[OLE32.6]
  *
- * RETURNS
- *     TRUE if equal
  */
-BOOL16 WINAPI IsEqualGUID16(
-       GUID* g1,       /* [in] unique id 1 */
-       GUID* g2        /* [in] unique id 2 */
+HRESULT WINAPI CoCreateGuid(
+       GUID *pguid /* [out] points to the GUID to initialize */
 ) {
-    return !memcmp( g1, g2, sizeof(GUID) );
+    return UuidCreate(pguid);
 }
 
 /******************************************************************************
- *             CLSIDFromString [COMPOBJ.20]
+ *             CLSIDFromString [OLE32.3]
+ *             IIDFromString   [OLE32.74]
  * Converts a unique identifier from its string representation into
  * the GUID struct.
  *
- * Class id: DWORD-WORD-WORD-BYTES[2]-BYTES[6]
+ * UNDOCUMENTED
+ *      If idstr is not a valid CLSID string then it gets treated as a ProgID
  *
  * RETURNS
  *     the converted GUID
  */
-HRESULT WINAPI CLSIDFromString16(
-       LPCOLESTR16 idstr,      /* [in] string representation of guid */
-       CLSID *id               /* [out] GUID converted from string */
-{
+HRESULT WINAPI __CLSIDFromStringA(
+       LPCSTR idstr,           /* [in] string representation of guid */
+       CLSID *id)              /* [out] GUID converted from string */
+{
   BYTE *s = (BYTE *) idstr;
-  BYTE *p;
   int  i;
   BYTE table[256];
 
@@ -464,13 +429,11 @@ HRESULT WINAPI CLSIDFromString16(
       if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') || (s[24]!='-') || (s[37]!='}'))
           return CO_E_CLASSSTRING;
 
-      for (i=1; i<37; i++)
-      {
+      for (i=1; i<37; i++) {
           if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
           if (!(((s[i] >= '0') && (s[i] <= '9'))  ||
                 ((s[i] >= 'a') && (s[i] <= 'f'))  ||
-                ((s[i] >= 'A') && (s[i] <= 'F')))
-             )
+                ((s[i] >= 'A') && (s[i] <= 'F'))))
               return CO_E_CLASSSTRING;
       }
   }
@@ -490,67 +453,26 @@ HRESULT WINAPI CLSIDFromString16(
 
   /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
 
-  p = (BYTE *) id;
-
-  s++; /* skip leading brace  */
-  for (i = 0; i < 4; i++) {
-    p[3 - i] = table[*s]<<4 | table[*(s+1)];
-    s += 2;
-  }
-  p += 4;
-  s++; /* skip - */
-
-  for (i = 0; i < 2; i++) {
-    p[1-i] = table[*s]<<4 | table[*(s+1)];
-    s += 2;
-  }
-  p += 2;
-  s++; /* skip - */
-
-  for (i = 0; i < 2; i++) {
-    p[1-i] = table[*s]<<4 | table[*(s+1)];
-    s += 2;
-  }
-  p += 2;
-  s++; /* skip - */
+  id->Data1 = (table[s[1]] << 28 | table[s[2]] << 24 | table[s[3]] << 20 | table[s[4]] << 16 |
+               table[s[5]] << 12 | table[s[6]] << 8  | table[s[7]] << 4  | table[s[8]]);
+  id->Data2 = table[s[10]] << 12 | table[s[11]] << 8 | table[s[12]] << 4 | table[s[13]];
+  id->Data3 = table[s[15]] << 12 | table[s[16]] << 8 | table[s[17]] << 4 | table[s[18]];
 
   /* these are just sequential bytes */
-  for (i = 0; i < 2; i++) {
-    *p++ = table[*s]<<4 | table[*(s+1)];
-    s += 2;
-  }
-  s++; /* skip - */
-
-  for (i = 0; i < 6; i++) {
-    *p++ = table[*s]<<4 | table[*(s+1)];
-    s += 2;
-  }
+  id->Data4[0] = table[s[20]] << 4 | table[s[21]];
+  id->Data4[1] = table[s[22]] << 4 | table[s[23]];
+  id->Data4[2] = table[s[25]] << 4 | table[s[26]];
+  id->Data4[3] = table[s[27]] << 4 | table[s[28]];
+  id->Data4[4] = table[s[29]] << 4 | table[s[30]];
+  id->Data4[5] = table[s[31]] << 4 | table[s[32]];
+  id->Data4[6] = table[s[33]] << 4 | table[s[34]];
+  id->Data4[7] = table[s[35]] << 4 | table[s[36]];
 
   return S_OK;
 }
 
-/******************************************************************************
- *             CoCreateGuid[OLE32.6]
- *
- */
-HRESULT WINAPI CoCreateGuid(
-       GUID *pguid /* [out] points to the GUID to initialize */
-) {
-    return UuidCreate(pguid);
-}
+/*****************************************************************************/
 
-/******************************************************************************
- *             CLSIDFromString [OLE32.3]
- *             IIDFromString   [OLE32.74]
- * Converts a unique identifier from its string representation into
- * the GUID struct.
- *
- * UNDOCUMENTED
- *      If idstr is not a valid CLSID string then it gets treated as a ProgID
- *
- * RETURNS
- *     the converted GUID
- */
 HRESULT WINAPI CLSIDFromString(
        LPCOLESTR idstr,        /* [in] string representation of GUID */
        CLSID *id )             /* [out] GUID represented by above string */
@@ -560,7 +482,9 @@ HRESULT WINAPI CLSIDFromString(
 
     if (!WideCharToMultiByte( CP_ACP, 0, idstr, -1, xid, sizeof(xid), NULL, NULL ))
         return CO_E_CLASSSTRING;
-    ret = CLSIDFromString16(xid,id);
+
+
+    ret = __CLSIDFromStringA(xid,id);
     if(ret != S_OK) { /* It appears a ProgID is also valid */
         ret = CLSIDFromProgID(idstr, id);
     }
@@ -609,47 +533,6 @@ HRESULT WINE_StringFromCLSID(
   return S_OK;
 }
 
-/******************************************************************************
- *             StringFromCLSID [COMPOBJ.19]
- * Converts a GUID into the respective string representation.
- * The target string is allocated using the OLE IMalloc.
- * RETURNS
- *     the string representation and HRESULT
- */
-HRESULT WINAPI StringFromCLSID16(
-        REFCLSID id,            /* [in] the GUID to be converted */
-       LPOLESTR16 *idstr       /* [out] a pointer to a to-be-allocated segmented pointer pointing to the resulting string */
-
-) {
-    extern BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags,
-                                           DWORD cbArgs, LPVOID pArgs, LPDWORD pdwRetCode );
-    LPMALLOC16 mllc;
-    HRESULT    ret;
-    DWORD      args[2];
-
-    ret = CoGetMalloc16(0,&mllc);
-    if (ret) return ret;
-
-    args[0] = (DWORD)mllc;
-    args[1] = 40;
-
-    /* No need for a Callback entry, we have WOWCallback16Ex which does
-     * everything we need.
-     */
-    if (!K32WOWCallback16Ex(
-       (DWORD)((ICOM_VTABLE(IMalloc16)*)MapSL(
-            (SEGPTR)ICOM_VTBL(((LPMALLOC16)MapSL((SEGPTR)mllc))))
-       )->Alloc,
-       WCB16_CDECL,
-       2*sizeof(DWORD),
-       (LPVOID)args,
-       (LPDWORD)idstr
-    )) {
-       WARN("CallTo16 IMalloc16 failed\n");
-       return E_FAIL;
-    }
-    return WINE_StringFromCLSID(id,MapSL((SEGPTR)*idstr));
-}
 
 /******************************************************************************
  *             StringFromCLSID [OLE32.151]
@@ -752,37 +635,6 @@ HRESULT WINAPI ProgIDFromCLSID(
   return ret;
 }
 
-/******************************************************************************
- *             CLSIDFromProgID [COMPOBJ.61]
- * Converts a program id into the respective GUID. (By using a registry lookup)
- * RETURNS
- *     riid associated with the progid
- */
-HRESULT WINAPI CLSIDFromProgID16(
-       LPCOLESTR16 progid,     /* [in] program id as found in registry */
-       LPCLSID riid            /* [out] associated CLSID */
-) {
-       char    *buf,buf2[80];
-       DWORD   buf2len;
-       HRESULT err;
-       HKEY    xhkey;
-
-       buf = HeapAlloc(GetProcessHeap(),0,strlen(progid)+8);
-       sprintf(buf,"%s\\CLSID",progid);
-       if ((err=RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&xhkey))) {
-               HeapFree(GetProcessHeap(),0,buf);
-                return CO_E_CLASSSTRING;
-       }
-       HeapFree(GetProcessHeap(),0,buf);
-       buf2len = sizeof(buf2);
-       if ((err=RegQueryValueA(xhkey,NULL,buf2,&buf2len))) {
-               RegCloseKey(xhkey);
-                return CO_E_CLASSSTRING;
-       }
-       RegCloseKey(xhkey);
-       return CLSIDFromString16(buf2,riid);
-}
-
 /******************************************************************************
  *             CLSIDFromProgID [OLE32.2]
  * Converts a program id into the respective GUID. (By using a registry lookup)
@@ -814,7 +666,7 @@ HRESULT WINAPI CLSIDFromProgID(
         return CO_E_CLASSSTRING;
     }
     RegCloseKey(xhkey);
-    return CLSIDFromString16(buf2,riid);
+    return __CLSIDFromStringA(buf2,riid);
 }
 
 
@@ -875,8 +727,7 @@ HRESULT WINAPI CoGetPSClsid(
 
     /* We have the CLSid we want back from the registry as a string, so
        lets convert it into a CLSID structure */
-    if ( (CLSIDFromString16(buf2,pclsid)) != NOERROR)
-    {
+    if ( (__CLSIDFromStringA(buf2,pclsid)) != NOERROR) {
        return E_INVALIDARG;
     }
 
@@ -927,98 +778,19 @@ HRESULT WINAPI ReadClassStm(IStream *pStm,CLSID *pclsid)
         return S_OK;
 }
 
-/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
-/***********************************************************************
- *           LookupETask (COMPOBJ.94)
- */
-HRESULT WINAPI LookupETask16(HTASK16 *hTask,LPVOID p) {
-       FIXME("(%p,%p),stub!\n",hTask,p);
-       if ((*hTask = GetCurrentTask()) == hETask) {
-               memcpy(p, Table_ETask, sizeof(Table_ETask));
-       }
-       return 0;
-}
-
-/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
-/***********************************************************************
- *           SetETask (COMPOBJ.95)
- */
-HRESULT WINAPI SetETask16(HTASK16 hTask, LPVOID p) {
-        FIXME("(%04x,%p),stub!\n",hTask,p);
-       hETask = hTask;
-       return 0;
-}
-
-/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
-/***********************************************************************
- *           CALLOBJECTINWOW (COMPOBJ.201)
- */
-HRESULT WINAPI CallObjectInWOW(LPVOID p1,LPVOID p2) {
-       FIXME("(%p,%p),stub!\n",p1,p2);
-       return 0;
-}
 
-/******************************************************************************
- *             CoRegisterClassObject   [COMPOBJ.5]
+/***
+ * COM_GetRegisteredClassObject
+ *
+ * This internal method is used to scan the registered class list to
+ * find a class object.
  *
- * Don't know where it registers it ...
- */
-HRESULT WINAPI CoRegisterClassObject16(
-       REFCLSID rclsid,
-       LPUNKNOWN pUnk,
-       DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */
-       DWORD flags,        /* [in] REGCLS flags indicating how connections are made */
-       LPDWORD lpdwRegister
-) {
-       char    buf[80];
-
-       WINE_StringFromCLSID(rclsid,buf);
-
-       FIXME("(%s,%p,0x%08lx,0x%08lx,%p),stub\n",
-               buf,pUnk,dwClsContext,flags,lpdwRegister
-       );
-       return 0;
-}
-
-
-/******************************************************************************
- *      CoRevokeClassObject [COMPOBJ.6]
- *
- */
-HRESULT WINAPI CoRevokeClassObject16(DWORD dwRegister) /* [in] token on class obj */
-{
-    FIXME("(0x%08lx),stub!\n", dwRegister);
-    return 0;
-}
-
-/******************************************************************************
- *      CoFileTimeToDosDateTime [COMPOBJ.30]
- */
-BOOL16 WINAPI CoFileTimeToDosDateTime16(const FILETIME *ft, LPWORD lpDosDate, LPWORD lpDosTime)
-{
-    return FileTimeToDosDateTime(ft, lpDosDate, lpDosTime);
-}
-
-/******************************************************************************
- *      CoDosDateTimeToFileTime [COMPOBJ.31]
- */
-BOOL16 WINAPI CoDosDateTimeToFileTime16(WORD wDosDate, WORD wDosTime, FILETIME *ft)
-{
-    return DosDateTimeToFileTime(wDosDate, wDosTime, ft);
-}
-
-/***
- * COM_GetRegisteredClassObject
- *
- * This internal method is used to scan the registered class list to
- * find a class object.
- *
- * Params:
- *   rclsid        Class ID of the class to find.
- *   dwClsContext  Class context to match.
- *   ppv           [out] returns a pointer to the class object. Complying
- *                 to normal COM usage, this method will increase the
- *                 reference count on this object.
+ * Params:
+ *   rclsid        Class ID of the class to find.
+ *   dwClsContext  Class context to match.
+ *   ppv           [out] returns a pointer to the class object. Complying
+ *                 to normal COM usage, this method will increase the
+ *                 reference count on this object.
  */
 static HRESULT COM_GetRegisteredClassObject(
        REFCLSID    rclsid,
@@ -1293,47 +1065,37 @@ end:
   return hr;
 }
 
-static HRESULT WINAPI Remote_CoGetClassObject(
-    REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo,
-    REFIID iid, LPVOID *ppv
-) {
-  HKEY         key;
-  char                 buf[200];
-  HRESULT      hres = E_UNEXPECTED;
-  char         xclsid[80];
-  WCHAR        dllName[MAX_PATH+1];
-  DWORD        dllNameLen = sizeof(dllName);
-  STARTUPINFOW sinfo;
-  PROCESS_INFORMATION  pinfo;
-
-  WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
-
-  sprintf(buf,"CLSID\\%s\\LocalServer32",xclsid);
-  hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key);
-
-  if (hres != ERROR_SUCCESS)
-      return REGDB_E_CLASSNOTREG;
-
-  memset(dllName,0,sizeof(dllName));
-  hres= RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)dllName,&dllNameLen);
-  if (hres)
-         return REGDB_E_CLASSNOTREG; /* FIXME: check retval */
-  RegCloseKey(key);
-
-  TRACE("found LocalServer32 exe %s\n", debugstr_w(dllName));
-
-  memset(&sinfo,0,sizeof(sinfo));
-  sinfo.cb = sizeof(sinfo);
-  if (!CreateProcessW(NULL,dllName,NULL,NULL,FALSE,0,NULL,NULL,&sinfo,&pinfo))
-      return E_FAIL;
-  return create_marshalled_proxy(rclsid,iid,ppv);
+/***********************************************************************
+ *     compobj_RegReadPath     [internal]
+ *
+ *     Reads a registry value and expands it when nessesary
+ */
+HRESULT compobj_RegReadPath(char * keyname, char * valuename, char * dst, int dstlen)
+{
+       HRESULT hres;
+       HKEY key;
+       DWORD keytype;
+       char src[MAX_PATH];
+       DWORD dwLength = dstlen;
+
+       if((hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &key)) == ERROR_SUCCESS) {
+          if( (hres = RegQueryValueExA(key, NULL, NULL, &keytype, (LPBYTE)src, &dwLength)) == ERROR_SUCCESS ) {
+            if (keytype == REG_EXPAND_SZ) {
+              if (dstlen <= ExpandEnvironmentStringsA(src, dst, dstlen)) hres = ERROR_MORE_DATA;
+            } else {
+              strncpy(dst, src, dstlen);
+            }
+         }
+          RegCloseKey (key);
+       }
+       return hres;
 }
 
 /***********************************************************************
  *           CoGetClassObject [COMPOBJ.7]
  *           CoGetClassObject [OLE32.16]
  *
- * FIXME.  If request allows of several options and there is a failure 
+ * FIXME.  If request allows of several options and there is a failure
  *         with one (other than not being registered) do we try the
  *         others or return failure?  (E.g. inprocess is registered but
  *         the DLL is not found but the server version works)
@@ -1345,21 +1107,13 @@ HRESULT WINAPI CoGetClassObject(
     LPUNKNOWN  regClassObject;
     HRESULT    hres = E_UNEXPECTED;
     char       xclsid[80];
-    WCHAR ProviderName[MAX_PATH+1];
-    DWORD ProviderNameLen = sizeof(ProviderName);
     HINSTANCE hLibrary;
-    typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid,
-                            REFIID iid, LPVOID *ppv);
+    typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
     DllGetClassObjectFunc DllGetClassObject;
-    HKEY key;
-    char buf[200];
 
     WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
 
-    TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",
-       debugstr_guid(rclsid),
-       debugstr_guid(iid)
-    );
+    TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid), debugstr_guid(iid));
 
     if (pServerInfo) {
        FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo->pwszName));
@@ -1387,78 +1141,46 @@ HRESULT WINAPI CoGetClassObject(
       return hres;
     }
 
-    if (((CLSCTX_LOCAL_SERVER) & dwClsContext)
-        && !((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext))
-       return Remote_CoGetClassObject(rclsid,dwClsContext,pServerInfo,iid,ppv);
+    /* first try: in-process */
+    if ((CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER) & dwClsContext) {
+       char keyname[MAX_PATH];
+       char dllpath[MAX_PATH+1];
 
-    /* remote servers not supported yet */
-    if (     ((CLSCTX_REMOTE_SERVER) & dwClsContext)
-        && !((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext)
-    ){
-        FIXME("CLSCTX_REMOTE_SERVER not supported!\n");
-       return E_NOINTERFACE;
-    }
+       sprintf(keyname,"CLSID\\%s\\InprocServer32",xclsid);
 
-    if ((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext) {
-        HKEY key;
-       char buf[200];
-
-       memset(ProviderName,0,sizeof(ProviderName));
-       sprintf(buf,"CLSID\\%s\\InprocServer32",xclsid);
-        if (((hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key)) != ERROR_SUCCESS) ||
-            ((hres = RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)ProviderName,&ProviderNameLen)),
-             RegCloseKey (key),
-             hres != ERROR_SUCCESS))
-        {
+       if ( compobj_RegReadPath(keyname, NULL, dllpath, sizeof(dllpath)) != ERROR_SUCCESS) {
+           /* failure: CLSID is not found in registry */
+           WARN("class %s not registred\n", xclsid);
             hres = REGDB_E_CLASSNOTREG;
-        }
-        /* Don't ask me.  MSDN says that CoGetClassObject does NOT call CoLoadLibrary */
-        else if ((hLibrary = CoLoadLibrary(ProviderName, TRUE)) == 0)
-        {
-           FIXME("couldn't load InprocServer32 dll %s\n", debugstr_w(ProviderName));
-           hres = E_ACCESSDENIED; /* or should this be CO_E_DLLNOTFOUND? */
-       }
-       else if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject")))
-        {
-           /* not sure if this should be called here CoFreeLibrary(hLibrary);*/
-           FIXME("couldn't find function DllGetClassObject in %s\n", debugstr_w(ProviderName));
-           hres = E_ACCESSDENIED;
-       }
-        else
-        {
-           /* Ask the DLL for its class object. (there was a note here about
-            * class factories but this is good.
-            */
+       } else {
+         if ((hLibrary = LoadLibraryExA(dllpath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0) {
+           /* failure: DLL could not be loaded */
+           ERR("couldn't load InprocServer32 dll %s\n", dllpath);
+           hres = E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
+         } else if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject"))) {
+           /* failure: the dll did not export DllGetClassObject */
+           ERR("couldn't find function DllGetClassObject in %s\n", dllpath);
+           FreeLibrary( hLibrary );
+           hres = CO_E_DLLNOTFOUND;
+         } else {
+           /* OK: get the ClassObject */
+           COMPOBJ_DLLList_Add( hLibrary );
            return DllGetClassObject(rclsid, iid, ppv);
-        }
+         }
+       }
     }
-    
 
-    /* Finally try out of process */
-    /* out of process and remote servers not supported yet */
+    /* Next try out of process */
     if (CLSCTX_LOCAL_SERVER & dwClsContext)
     {
-       memset(ProviderName,0,sizeof(ProviderName));
-       sprintf(buf,"CLSID\\%s\\LocalServer32",xclsid);
-        if (((hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key)) != ERROR_SUCCESS) ||
-            ((hres = RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)ProviderName,&ProviderNameLen)),
-             RegCloseKey (key),
-             hres != ERROR_SUCCESS))
-        {
-            hres = REGDB_E_CLASSNOTREG;
-        }
-        else
-        {
-            /* CO_E_APPNOTFOUND if no exe */
-            FIXME("CLSCTX_LOCAL_SERVER %s registered but not yet supported!\n",debugstr_w(ProviderName));
-            hres = E_ACCESSDENIED;
-       }
+        return create_marshalled_proxy(rclsid,iid,ppv);
     }
 
+    /* Finally try remote */
     if (CLSCTX_REMOTE_SERVER & dwClsContext)
     {
         FIXME ("CLSCTX_REMOTE_SERVER not supported\n");
-        hres = E_ACCESSDENIED;
+        hres = E_NOINTERFACE;
     }
 
     return hres;
@@ -1483,12 +1205,14 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
 {
     IStorage *pstg=0;
     HRESULT res;
-    int nbElm=0,length=0,i=0;
-    LONG sizeProgId=20;
+    int nbElm, length, i;
+    LONG sizeProgId;
     LPOLESTR *pathDec=0,absFile=0,progId=0;
-    WCHAR extention[100]={0};
+    LPWSTR extension;
+    static const WCHAR bkslashW[] = {'\\',0};
+    static const WCHAR dotW[] = {'.',0};
 
-    TRACE("()\n");
+    TRACE("%s, %p\n", debugstr_w(filePathName), pclsid);
 
     /* if the file contain a storage object the return the CLSID writen by IStorage_SetClass method*/
     if((StgIsStorageFile(filePathName))==S_OK){
@@ -1532,23 +1256,24 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
     absFile=pathDec[nbElm-1];
 
     /* failed if the path represente a directory and not an absolute file name*/
-    if (lstrcmpW(absFile,(LPOLESTR)"\\"))
+    if (!lstrcmpW(absFile, bkslashW))
         return MK_E_INVALIDEXTENSION;
 
     /* get the extension of the file */
+    extension = NULL;
     length=lstrlenW(absFile);
-    for(i=length-1; ( (i>=0) && (extention[i]=absFile[i]) );i--);
+    for(i = length-1; (i >= 0) && *(extension = &absFile[i]) != '.'; i--)
+        /* nothing */;
 
-    /* get the progId associated to the extension */
-    progId=CoTaskMemAlloc(sizeProgId);
+    if (!extension || !lstrcmpW(extension, dotW))
+        return MK_E_INVALIDEXTENSION;
 
-    res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId);
+    res=RegQueryValueW(HKEY_CLASSES_ROOT, extension, NULL, &sizeProgId);
 
-    if (res==ERROR_MORE_DATA){
+    /* get the progId associated to the extension */
+    progId = CoTaskMemAlloc(sizeProgId);
+    res = RegQueryValueW(HKEY_CLASSES_ROOT, extension, progId, &sizeProgId);
 
-        progId = CoTaskMemRealloc(progId,sizeProgId);
-        res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId);
-    }
     if (res==ERROR_SUCCESS)
         /* return the clsid associated to the progId */
         res= CLSIDFromProgID(progId,pclsid);
@@ -1564,17 +1289,6 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
 
     return MK_E_INVALIDEXTENSION;
 }
-/******************************************************************************
- *             CoRegisterMessageFilter [COMPOBJ.27]
- */
-HRESULT WINAPI CoRegisterMessageFilter16(
-       LPMESSAGEFILTER lpMessageFilter,
-       LPMESSAGEFILTER *lplpMessageFilter
-) {
-       FIXME("(%p,%p),stub!\n",lpMessageFilter,lplpMessageFilter);
-       return 0;
-}
-
 /***********************************************************************
  *           CoCreateInstance [COMPOBJ.13]
  *           CoCreateInstance [OLE32.7]
@@ -1701,93 +1415,47 @@ HRESULT WINAPI CoCreateInstanceEx(
 }
 
 /***********************************************************************
- *           CoFreeLibrary [OLE32.13]
+ *           CoLoadLibrary (OLE32.30)
  */
-void WINAPI CoFreeLibrary(HINSTANCE hLibrary)
+HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree)
 {
-    OpenDll *ptr, *prev;
-    OpenDll *tmp;
-
-    EnterCriticalSection( &csOpenDllList );
+    TRACE("(%s, %d)\n", debugstr_w(lpszLibName), bAutoFree);
 
-    /* lookup library in linked list */
-    prev = NULL;
-    for (ptr = openDllList; ptr != NULL; ptr=ptr->next) {
-       if (ptr->hLibrary == hLibrary) {
-           break;
-       }
-       prev = ptr;
-    }
+    return LoadLibraryExW(lpszLibName, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
+}
 
-    if (ptr == NULL) {
-       /* shouldn't happen if user passed in a valid hLibrary */
-       goto end;
-    }
-    /* assert: ptr points to the library entry to free */
-
-    /* free library and remove node from list */
-    FreeLibrary(hLibrary);
-    if (ptr == openDllList) {
-       tmp = openDllList->next;
-       HeapFree(GetProcessHeap(), 0, openDllList);
-       openDllList = tmp;
-    } else {
-       tmp = ptr->next;
-       HeapFree(GetProcessHeap(), 0, ptr);
-       prev->next = tmp;
-    }
-end:
-    LeaveCriticalSection( &csOpenDllList );
+/***********************************************************************
+ *           CoFreeLibrary [OLE32.13]
+ *
+ * NOTES: don't belive the docu
+ */
+void WINAPI CoFreeLibrary(HINSTANCE hLibrary)
+{
+       FreeLibrary(hLibrary);
 }
 
 
 /***********************************************************************
  *           CoFreeAllLibraries [OLE32.12]
+ *
+ * NOTES: don't belive the docu
  */
 void WINAPI CoFreeAllLibraries(void)
 {
-    OpenDll *ptr, *tmp;
-
-    EnterCriticalSection( &csOpenDllList );
-
-    for (ptr = openDllList; ptr != NULL; ) {
-       tmp=ptr->next;
-       CoFreeLibrary(ptr->hLibrary);
-       ptr = tmp;
-    }
-
-    LeaveCriticalSection( &csOpenDllList );
+        /* NOP */
 }
 
 
-
 /***********************************************************************
  *           CoFreeUnusedLibraries [COMPOBJ.17]
  *           CoFreeUnusedLibraries [OLE32.14]
+ *
+ * FIXME: Calls to CoFreeUnusedLibraries from any thread always route
+ * through the main apartment's thread to call DllCanUnloadNow
  */
 void WINAPI CoFreeUnusedLibraries(void)
 {
-    OpenDll *ptr, *tmp;
-    typedef HRESULT(*DllCanUnloadNowFunc)(void);
-    DllCanUnloadNowFunc DllCanUnloadNow;
-
-    EnterCriticalSection( &csOpenDllList );
-
-    for (ptr = openDllList; ptr != NULL; ) {
-       DllCanUnloadNow = (DllCanUnloadNowFunc)
-           GetProcAddress(ptr->hLibrary, "DllCanUnloadNow");
-
-       if ( (DllCanUnloadNow != NULL) &&
-            (DllCanUnloadNow() == S_OK) ) {
-           tmp=ptr->next;
-           CoFreeLibrary(ptr->hLibrary);
-           ptr = tmp;
-       } else {
-           ptr=ptr->next;
-       }
-    }
-
-    LeaveCriticalSection( &csOpenDllList );
+    COMPOBJ_DllList_FreeUnused(0);
 }
 
 /***********************************************************************
@@ -1804,208 +1472,151 @@ HRESULT WINAPI CoFileTimeNow( FILETIME *lpFileTime ) /* [out] the current time *
 }
 
 /***********************************************************************
- *           CoTaskMemAlloc (OLE32.43)
- * RETURNS
- *     pointer to newly allocated block
+ *           CoLoadLibrary (OLE32.30)
  */
-LPVOID WINAPI CoTaskMemAlloc(
-       ULONG size      /* [in] size of memoryblock to be allocated */
-) {
-    LPMALLOC   lpmalloc;
-    HRESULT    ret = CoGetMalloc(0,&lpmalloc);
+static void COM_RevokeAllClasses()
+{
+  EnterCriticalSection( &csRegisteredClassList );
 
-    if (FAILED(ret))
-       return NULL;
+  while (firstRegisteredClass!=0)
+  {
+    CoRevokeClassObject(firstRegisteredClass->dwCookie);
+  }
 
-    return IMalloc_Alloc(lpmalloc,size);
+  LeaveCriticalSection( &csRegisteredClassList );
 }
-/***********************************************************************
- *           CoTaskMemFree (OLE32.44)
- */
-VOID WINAPI CoTaskMemFree(
-       LPVOID ptr      /* [in] pointer to be freed */
-) {
-    LPMALLOC   lpmalloc;
-    HRESULT    ret = CoGetMalloc(0,&lpmalloc);
 
-    if (FAILED(ret))
-      return;
+/****************************************************************************
+ *  COM External Lock methods implementation
+ *
+ *  This api provides a linked list to managed external references to
+ *  COM objects.
+ *
+ *  The public interface consists of three calls:
+ *      COM_ExternalLockAddRef
+ *      COM_ExternalLockRelease
+ *      COM_ExternalLockFreeList
+ */
 
-    IMalloc_Free(lpmalloc, ptr);
-}
+#define EL_END_OF_LIST 0
+#define EL_NOT_FOUND   0
 
-/***********************************************************************
- *           CoTaskMemRealloc (OLE32.45)
- * RETURNS
- *     pointer to newly allocated block
+/*
+ * Declaration of the static structure that manage the
+ * external lock to COM  objects.
  */
-LPVOID WINAPI CoTaskMemRealloc(
-  LPVOID pvOld,
-  ULONG  size) /* [in] size of memoryblock to be allocated */
+typedef struct COM_ExternalLock     COM_ExternalLock;
+typedef struct COM_ExternalLockList COM_ExternalLockList;
+
+struct COM_ExternalLock
 {
-  LPMALLOC lpmalloc;
-  HRESULT  ret = CoGetMalloc(0,&lpmalloc);
+  IUnknown         *pUnk;     /* IUnknown referenced */
+  ULONG            uRefCount; /* external lock counter to IUnknown object*/
+  COM_ExternalLock *next;     /* Pointer to next element in list */
+};
 
-  if (FAILED(ret))
-    return NULL;
+struct COM_ExternalLockList
+{
+  COM_ExternalLock *head;     /* head of list */
+};
 
-  return IMalloc_Realloc(lpmalloc, pvOld, size);
-}
+/*
+ * Declaration and initialization of the static structure that manages
+ * the external lock to COM objects.
+ */
+static COM_ExternalLockList elList = { EL_END_OF_LIST };
 
-/***********************************************************************
- *           CoLoadLibrary (OLE32.30)
+/*
+ * Private methods used to managed the linked list
  */
-HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree)
-{
-    HINSTANCE hLibrary;
-    OpenDll *ptr;
-    OpenDll *tmp;
 
-    TRACE("(%s, %d)\n", debugstr_w(lpszLibName), bAutoFree);
 
-    hLibrary = LoadLibraryExW(lpszLibName, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
+static COM_ExternalLock* COM_ExternalLockLocate(
+  COM_ExternalLock *element,
+  IUnknown         *pUnk);
 
-    if (!bAutoFree)
-       return hLibrary;
+/****************************************************************************
+ * Internal - Insert a new IUnknown* to the linked list
+ */
+static BOOL COM_ExternalLockInsert(
+  IUnknown *pUnk)
+{
+  COM_ExternalLock *newLock      = NULL;
+  COM_ExternalLock *previousHead = NULL;
 
-    EnterCriticalSection( &csOpenDllList );
+  /*
+   * Allocate space for the new storage object
+   */
+  newLock = HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock));
 
-    if (openDllList == NULL) {
-        /* empty list -- add first node */
-        openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
-       openDllList->hLibrary=hLibrary;
-       openDllList->next = NULL;
+  if (newLock!=NULL) {
+    if ( elList.head == EL_END_OF_LIST ) {
+      elList.head = newLock;    /* The list is empty */
     } else {
-        /* search for this dll */
-        int found = FALSE;
-        for (ptr = openDllList; ptr->next != NULL; ptr=ptr->next) {
-           if (ptr->hLibrary == hLibrary) {
-               found = TRUE;
-               break;
-           }
-        }
-       if (!found) {
-           /* dll not found, add it */
-           tmp = openDllList;
-           openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
-           openDllList->hLibrary = hLibrary;
-           openDllList->next = tmp;
-       }
+      /* insert does it at the head */
+      previousHead  = elList.head;
+      elList.head = newLock;
     }
 
-    LeaveCriticalSection( &csOpenDllList );
-
-    return hLibrary;
-}
-
-/***********************************************************************
- *           CoInitializeWOW (OLE32.27)
- */
-HRESULT WINAPI CoInitializeWOW(DWORD x,DWORD y) {
-    FIXME("(0x%08lx,0x%08lx),stub!\n",x,y);
-    return 0;
-}
-
-/******************************************************************************
- *             CoLockObjectExternal    [COMPOBJ.63]
- */
-HRESULT WINAPI CoLockObjectExternal16(
-    LPUNKNOWN pUnk,            /* [in] object to be locked */
-    BOOL16 fLock,              /* [in] do lock */
-    BOOL16 fLastUnlockReleases /* [in] ? */
-) {
-    FIXME("(%p,%d,%d),stub!\n",pUnk,fLock,fLastUnlockReleases);
-    return S_OK;
-}
-
-/******************************************************************************
- *             CoLockObjectExternal    [OLE32.31]
- */
-HRESULT WINAPI CoLockObjectExternal(
-    LPUNKNOWN pUnk,            /* [in] object to be locked */
-    BOOL fLock,                /* [in] do lock */
-    BOOL fLastUnlockReleases) /* [in] unlock all */
-{
+    /* Set new list item data member */
+    newLock->pUnk      = pUnk;
+    newLock->uRefCount = 1;
+    newLock->next      = previousHead;
 
-  if (fLock)
-  {
-    /*
-     * Increment the external lock coutner, COM_ExternalLockAddRef also
-     * increment the object's internal lock counter.
-     */
-    COM_ExternalLockAddRef( pUnk);
-  }
-  else
-  {
-    /*
-     * Decrement the external lock coutner, COM_ExternalLockRelease also
-     * decrement the object's internal lock counter.
-     */
-    COM_ExternalLockRelease( pUnk, fLastUnlockReleases);
+    return TRUE;
   }
-
-    return S_OK;
+  return FALSE;
 }
 
-/***********************************************************************
- *           CoGetState [COMPOBJ.115]
- */
-HRESULT WINAPI CoGetState16(LPDWORD state)
-{
-    FIXME("(%p),stub!\n", state);
-    *state = 0;
-    return S_OK;
-}
-/***********************************************************************
- *           CoSetState [OLE32.42]
- */
-HRESULT WINAPI CoSetState(LPDWORD state)
-{
-    FIXME("(%p),stub!\n", state);
-    if (state) *state = 0;
-    return S_OK;
-}
-/***********************************************************************
- *          CoCreateFreeThreadedMarshaler [OLE32.5]
+/****************************************************************************
+ * Internal - Method that removes an item from the linked list.
  */
-HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN* ppunkMarshal)
+static void COM_ExternalLockDelete(
+  COM_ExternalLock *itemList)
 {
-   FIXME ("(%p %p): stub\n", punkOuter, ppunkMarshal);
+  COM_ExternalLock *current = elList.head;
 
-   return S_OK;
-}
+  if ( current == itemList ) {
+    /* this section handles the deletion of the first node */
+    elList.head = itemList->next;
+    HeapFree( GetProcessHeap(), 0, itemList);
+  } else {
+    do {
+      if ( current->next == itemList ){   /* We found the item to free  */
+        current->next = itemList->next;  /* readjust the list pointers */
+        HeapFree( GetProcessHeap(), 0, itemList);
+        break;
+      }
 
-/***
- * COM_RevokeAllClasses
- *
- * This method is called when the COM libraries are uninitialized to
- * release all the references to the class objects registered with
- * the library
- */
-static void COM_RevokeAllClasses()
-{
-  EnterCriticalSection( &csRegisteredClassList );
+      /* Skip to the next item */
+      current = current->next;
 
-  while (firstRegisteredClass!=0)
-  {
-    CoRevokeClassObject(firstRegisteredClass->dwCookie);
+    } while ( current != EL_END_OF_LIST );
   }
-
-  LeaveCriticalSection( &csRegisteredClassList );
 }
 
 /****************************************************************************
- *  COM External Lock methods implementation
+ * Internal - Recursivity agent for IUnknownExternalLockList_Find
+ *
+ * NOTES: how long can the list be ?? (recursive!!!)
  */
+static COM_ExternalLock* COM_ExternalLockLocate( COM_ExternalLock *element, IUnknown *pUnk)
+{
+  if ( element == EL_END_OF_LIST )
+    return EL_NOT_FOUND;
+  else if ( element->pUnk == pUnk )    /* We found it */
+    return element;
+  else                                 /* Not the right guy, keep on looking */
+    return COM_ExternalLockLocate( element->next, pUnk);
+}
 
 /****************************************************************************
  * Public - Method that increments the count for a IUnknown* in the linked
  * list.  The item is inserted if not already in the list.
  */
-static void COM_ExternalLockAddRef(
-  IUnknown *pUnk)
+static void COM_ExternalLockAddRef(IUnknown *pUnk)
 {
-  COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk);
+  COM_ExternalLock *externalLock = COM_ExternalLockLocate(elList.head, pUnk);
 
   /*
    * Add an external lock to the object. If it was already externally
@@ -2032,17 +1643,14 @@ static void COM_ExternalLockRelease(
   IUnknown *pUnk,
   BOOL   bRelAll)
 {
-  COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk);
+  COM_ExternalLock *externalLock = COM_ExternalLockLocate(elList.head, pUnk);
 
-  if ( externalLock != EL_NOT_FOUND )
-  {
-    do
-    {
+  if ( externalLock != EL_NOT_FOUND ) {
+    do {
       externalLock->uRefCount--;  /* release external locks      */
       IUnknown_Release(pUnk);     /* release local locks as well */
 
-      if ( bRelAll == FALSE )
-        break;  /* perform single release */
+      if ( bRelAll == FALSE ) break;  /* perform single release */
 
     } while ( externalLock->uRefCount > 0 );
 
@@ -2058,10 +1666,8 @@ static void COM_ExternalLockFreeList()
   COM_ExternalLock *head;
 
   head = elList.head;                 /* grab it by the head             */
-  while ( head != EL_END_OF_LIST )
-  {
+  while ( head != EL_END_OF_LIST ) {
     COM_ExternalLockDelete(head);     /* get rid of the head stuff       */
-
     head = elList.head;               /* get the new head...             */
   }
 }
@@ -2075,144 +1681,98 @@ void COM_ExternalLockDump()
 
   DPRINTF("\nExternal lock list contains:\n");
 
-  while ( current != EL_END_OF_LIST )
-  {
-      DPRINTF( "\t%p with %lu references count.\n", current->pUnk, current->uRefCount);
+  while ( current != EL_END_OF_LIST ) {
+    DPRINTF( "\t%p with %lu references count.\n", current->pUnk, current->uRefCount);
 
     /* Skip to the next item */
     current = current->next;
   }
-
 }
 
-/****************************************************************************
- * Internal - Find a IUnknown* in the linked list
- */
-static COM_ExternalLock* COM_ExternalLockFind(
-  IUnknown *pUnk)
-{
-  return COM_ExternalLockLocate(elList.head, pUnk);
-}
-
-/****************************************************************************
- * Internal - Recursivity agent for IUnknownExternalLockList_Find
+/******************************************************************************
+ *             CoLockObjectExternal    [OLE32.31]
  */
-static COM_ExternalLock* COM_ExternalLockLocate(
-  COM_ExternalLock *element,
-  IUnknown         *pUnk)
+HRESULT WINAPI CoLockObjectExternal(
+    LPUNKNOWN pUnk,            /* [in] object to be locked */
+    BOOL fLock,                /* [in] do lock */
+    BOOL fLastUnlockReleases) /* [in] unlock all */
 {
-  if ( element == EL_END_OF_LIST )
-    return EL_NOT_FOUND;
 
-  else if ( element->pUnk == pUnk )    /* We found it */
-    return element;
+       if (fLock) {
+            /*
+             * Increment the external lock coutner, COM_ExternalLockAddRef also
+             * increment the object's internal lock counter.
+             */
+           COM_ExternalLockAddRef( pUnk);
+        } else {
+            /*
+             * Decrement the external lock coutner, COM_ExternalLockRelease also
+             * decrement the object's internal lock counter.
+             */
+            COM_ExternalLockRelease( pUnk, fLastUnlockReleases);
+        }
 
-  else                                 /* Not the right guy, keep on looking */
-    return COM_ExternalLockLocate( element->next, pUnk);
+        return S_OK;
 }
 
-/****************************************************************************
- * Internal - Insert a new IUnknown* to the linked list
+/***********************************************************************
+ *           CoInitializeWOW (OLE32.27)
  */
-static BOOL COM_ExternalLockInsert(
-  IUnknown *pUnk)
-{
-  COM_ExternalLock *newLock      = NULL;
-  COM_ExternalLock *previousHead = NULL;
-
-  /*
-   * Allocate space for the new storage object
-   */
-  newLock = HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock));
-
-  if (newLock!=NULL)
-  {
-    if ( elList.head == EL_END_OF_LIST )
-    {
-      elList.head = newLock;    /* The list is empty */
-    }
-    else
-    {
-      /*
-       * insert does it at the head
-       */
-      previousHead  = elList.head;
-      elList.head = newLock;
-    }
-
-    /*
-     * Set new list item data member
-     */
-    newLock->pUnk      = pUnk;
-    newLock->uRefCount = 1;
-    newLock->next      = previousHead;
-
-    return TRUE;
-  }
-  else
-    return FALSE;
+HRESULT WINAPI CoInitializeWOW(DWORD x,DWORD y) {
+    FIXME("(0x%08lx,0x%08lx),stub!\n",x,y);
+    return 0;
 }
 
-/****************************************************************************
- * Internal - Method that removes an item from the linked list.
+static IUnknown * pUnkState = 0; /* FIXME: thread local */
+static int nStatCounter = 0;    /* global */
+static HMODULE hOleAut32 = 0;   /* global */
+
+/***********************************************************************
+ *           CoGetState [OLE32.24]
+ *
+ * NOTES: might be incomplete
  */
-static void COM_ExternalLockDelete(
-  COM_ExternalLock *itemList)
+HRESULT WINAPI CoGetState(IUnknown ** ppv)
 {
-  COM_ExternalLock *current = elList.head;
-
-  if ( current == itemList )
-  {
-    /*
-     * this section handles the deletion of the first node
-     */
-    elList.head = itemList->next;
-    HeapFree( GetProcessHeap(), 0, itemList);
-  }
-  else
-  {
-    do
-    {
-      if ( current->next == itemList )   /* We found the item to free  */
-      {
-        current->next = itemList->next;  /* readjust the list pointers */
-
-        HeapFree( GetProcessHeap(), 0, itemList);
-        break;
-      }
+       FIXME("\n");
 
-      /* Skip to the next item */
-      current = current->next;
+       if(pUnkState) {
+           IUnknown_AddRef(pUnkState);
+           *ppv = pUnkState;
+           FIXME("-- %p\n", *ppv);
+           return S_OK;
+       }
+       *ppv = NULL;
+       return E_FAIL;
 
-    } while ( current != EL_END_OF_LIST );
-  }
 }
 
 /***********************************************************************
- *      DllEntryPoint                   [COMPOBJ.116]
- *
- *    Initialization code for the COMPOBJ DLL
+ *           CoSetState [OLE32.42]
  *
- * RETURNS:
+ * NOTES: FIXME: protect this with a crst
  */
-BOOL WINAPI COMPOBJ_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, WORD ds, WORD HeapSize, DWORD res1, WORD res2)
+HRESULT WINAPI CoSetState(IUnknown * pv)
 {
-        TRACE("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", Reason, hInst, ds, HeapSize,
- res1, res2);
-        switch(Reason)
-        {
-        case DLL_PROCESS_ATTACH:
-                if (!COMPOBJ_Attach++) COMPOBJ_hInstance = hInst;
-                break;
-
-        case DLL_PROCESS_DETACH:
-                if(!--COMPOBJ_Attach)
-                        COMPOBJ_hInstance = 0;
-                break;
-        }
-        return TRUE;
+       FIXME("(%p),stub!\n", pv);
+
+       if (pv) {
+           IUnknown_AddRef(pv);
+           nStatCounter++;
+           if (nStatCounter == 1) LoadLibraryA("OLEAUT32.DLL");
+       }
+
+       if (pUnkState) {
+           TRACE("-- release %p now\n", pUnkState);
+           IUnknown_Release(pUnkState);
+           nStatCounter--;
+           if (!nStatCounter) FreeLibrary(hOleAut32);
+       }
+       pUnkState = pv;
+       return S_OK;
 }
 
+
 /******************************************************************************
  *              OleGetAutoConvert        [OLE32.104]
  */
@@ -2241,9 +1801,8 @@ HRESULT WINAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew)
     MultiByteToWideChar( CP_ACP, 0, buf, -1, wbuf, sizeof(wbuf)/sizeof(WCHAR) );
     CLSIDFromString(wbuf,pClsidNew);
 done:
-  if (hkey) RegCloseKey(hkey);
-
-  return res;
+    if (hkey) RegCloseKey(hkey);
+    return res;
 }
 
 /******************************************************************************
@@ -2319,3 +1878,18 @@ BOOL WINAPI IsEqualGUID(
 {
     return !memcmp(rguid1,rguid2,sizeof(GUID));
 }
+
+/***********************************************************************
+ *           CoInitializeSecurity [OLE32.164]
+ */
+HRESULT WINAPI CoInitializeSecurity(PSECURITY_DESCRIPTOR pSecDesc, LONG cAuthSvc,
+                                    SOLE_AUTHENTICATION_SERVICE* asAuthSvc,
+                                    void* pReserved1, DWORD dwAuthnLevel,
+                                    DWORD dwImpLevel, void* pReserved2,
+                                    DWORD dwCapabilities, void* pReserved3)
+{
+  FIXME("(%p,%ld,%p,%p,%ld,%ld,%p,%ld,%p) - stub!\n", pSecDesc, cAuthSvc,
+        asAuthSvc, pReserved1, dwAuthnLevel, dwImpLevel, pReserved2,
+        dwCapabilities, pReserved3);
+  return S_OK;
+}