Ignore:
Timestamp:
Apr 26, 2001, 9:33:15 PM (24 years ago)
Author:
sandervl
Message:

resync with Wine 20010418

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/ole32/ole32.cpp

    r3177 r5602  
    1 /* $Id: ole32.cpp,v 1.14 2000-03-21 00:37:46 davidr Exp $ */
     1/* $Id: ole32.cpp,v 1.15 2001-04-26 19:32:49 sandervl Exp $ */
    22/*
    33 *
     
    2121#include "ole32.h"
    2222
    23 #include "oString.h"
    24 #include "moniker.h"            // RunningObjectTableImpl_***
    25 #include "filemoniker.h"        // FileMonikerImpl_***
    26 
    27 // ======================================================================
    28 // Local Data
    29 // ======================================================================
    30 typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
    31 
    32 /*
    33  * This linked list contains the list of registered class objects. These
    34  * are mostly used to register the factories for out-of-proc servers of OLE
    35  * objects.
    36  */
    37 typedef struct tagRegisteredClass
    38 {
    39   CLSID     classIdentifier;
    40   LPUNKNOWN classObject;
    41   DWORD     runContext;
    42   DWORD     connectFlags;
    43   DWORD     dwCookie;
    44   struct tagRegisteredClass* nextClass;
    45 } RegisteredClass;
    46 
    47 static RegisteredClass* firstRegisteredClass = NULL;
    48 
    49 /*
    50  * COM External Lock structures and methods declaration
    51  *
    52  * This api provides a linked list to managed external references to
    53  * COM objects.
    54  *
    55  */
    56 
    57 #define EL_END_OF_LIST 0
    58 #define EL_NOT_FOUND   0
    59 
    60 /*
    61  * Declaration of the static structure that manage the
    62  * external lock to COM  objects.
    63  */
    64 typedef struct COM_ExternalLock     COM_ExternalLock;
    65 typedef struct COM_ExternalLockList COM_ExternalLockList;
    66 
    67 struct COM_ExternalLock
    68 {
    69     IUnknown         *pUnk;     /* IUnknown referenced */
    70     ULONG            uRefCount; /* external lock counter to IUnknown object*/
    71     COM_ExternalLock *next;     /* Pointer to next element in list */
    72 };
    73 
    74 struct COM_ExternalLockList
    75 {
    76     COM_ExternalLock *head;     /* head of list */
    77 };
    78 
    79 /*
    80  * Declaration and initialization of the static structure that manages
    81  * the external lock to COM objects.
    82  */
    83 static COM_ExternalLockList elList = { EL_END_OF_LIST };
    84 
    85 /*
    86  * Com Library reference count...
    87  *
    88  * Used to control loading / unloading of Library resources,
    89  * Runnng object table, DLL's etc...
    90  */
    91 static LONG     COM_ref = 0;
    92 
    93 // ======================================================================
    94 // Prototypes.
    95 // ======================================================================
    96 static HRESULT COM_GetRegisteredClassObject(
    97         REFCLSID        rclsid,
    98         DWORD           dwClsContext,
    99         LPUNKNOWN *     ppUnk);
    100 
    101 static void COM_RevokeAllClasses();
    102 
    103 static void COM_ExternalLockFreeList();
    104 
    105 static void COM_ExternalLockAddRef(
    106         IUnknown * pUnk);
    107 
    108 static void COM_ExternalLockRelease(
    109         IUnknown *      pUnk,
    110         BOOL            bRelAll);
    111 
    112 static BOOL COM_ExternalLockInsert(
    113         IUnknown * pUnk);
    114 
    115 static void COM_ExternalLockDelete(
    116         COM_ExternalLock * element);
    117 
    118 static COM_ExternalLock * COM_ExternalLockFind(
    119         IUnknown *      pUnk);
    120 
    121 static COM_ExternalLock * COM_ExternalLockLocate(
    122         COM_ExternalLock * element,
    123         IUnknown *      pUnk);
    124 
    125 // ======================================================================
    126 // Public API's
    127 // ======================================================================
    128 
    129 // ----------------------------------------------------------------------
    130 // CoBuildVersion()
    131 // ----------------------------------------------------------------------
    132 DWORD WIN32API CoBuildVersion()
    133 {
    134     dprintf(("OLE32.CoBuildVersion"));
    135     return (rmm << 16) + rup;
    136 }
    137 
    13823// ----------------------------------------------------------------------
    13924// CoDosDateTimeToFileTime
     
    15035// CoDosDateTimeToFileTime
    15136// ----------------------------------------------------------------------
    152 HRESULT WIN32API CoFileTimeNow(FILETIME *lpFileTime)
    153 {
    154     SYSTEMTIME systime;
    155 
    156     dprintf(("OLE32: CoFileTimeNow"));
    157 
    158     GetSystemTime(&systime);
    159     return SystemTimeToFileTime(&systime, lpFileTime);
    160 }
    161 
    162 // ----------------------------------------------------------------------
    163 // CoDosDateTimeToFileTime
    164 // ----------------------------------------------------------------------
    16537BOOL WIN32API CoFileTimeToDosDateTime(FILETIME *lpFileTime, LPWORD lpDosDate,
    16638                                         LPWORD lpDosTime)
     
    17042    return FileTimeToDosDateTime(lpFileTime, lpDosDate, lpDosTime);
    17143}
    172 
    173 // ----------------------------------------------------------------------
    174 // CoInitialize()
    175 // ----------------------------------------------------------------------
    176 HRESULT WIN32API CoInitialize(LPVOID lpReserved)
    177 {
    178     dprintf(("OLE32: CoInitialize\n"));
    179 
    180     return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
    181 }
    182 
    183 // ----------------------------------------------------------------------
    184 // CoInitializeEx()
    185 // ----------------------------------------------------------------------
    186 HRESULT WIN32API CoInitializeEx(
    187         LPVOID  lpReserved,     // [in] pointer to win32 malloc interface
    188         DWORD   dwCoInit)       // [in] A value from COINIT specifies the thread
    189 {
    190     HRESULT             hr;
    191 
    192     dprintf(("OLE32: CoInitializeEx(%p, %lx)\n", lpReserved, dwCoInit));
    193 
    194     if (lpReserved != NULL)
    195     {
    196         dprintf(("Warning: Bad parameter %p, must be an old Windows Application", lpReserved));
    197     }
    198 
    199     /*
    200      * Check for unsupported features.
    201      */
    202     if (dwCoInit != COINIT_APARTMENTTHREADED)
    203     {
    204         dprintf(("Warning: Unsupported flag %lx", dwCoInit));
    205         /* Hope for the best and continue anyway */
    206     }
    207 
    208     /*
    209      * Initialise the Running Object Table
    210      */
    211     hr = S_FALSE;
    212     if (++COM_ref == 1)
    213     {
    214         hr = RunningObjectTableImpl_Initialize();
    215         if (hr != S_OK)
    216             --COM_ref;
    217     }
    218 
    219     return hr;
    220 }
    221 
    222 // ----------------------------------------------------------------------
    223 // CoUninitialize()
    224 // ----------------------------------------------------------------------
    225 void WIN32API CoUninitialize(void)
    226 {
    227     dprintf(("OLE32: CoUninitialize"));
    228 
    229     if (--COM_ref == 0)
    230     {
    231         dprintf(("OLE32: Releasing COM libraries"));
    232 
    233         RunningObjectTableImpl_UnInitialize();
    234 
    235         COM_RevokeAllClasses();
    236 
    237         CoFreeAllLibraries();
    238        
    239         COM_ExternalLockFreeList();
    240     }
    241 }
    242 
    243 // ----------------------------------------------------------------------
    244 // CoCreateInstance
    245 // ----------------------------------------------------------------------
    246 HRESULT WIN32API CoCreateInstance
    247    (REFCLSID            rclsid,
    248     LPUNKNOWN           pUnkOuter,
    249     DWORD               dwClsContext,
    250     REFIID              iid,
    251     LPVOID *            ppv)
    252 {
    253     HRESULT hres;
    254     LPCLASSFACTORY lpclf = 0;
    255 
    256     oStringA            tCLSID(rclsid);
    257     oStringA            tIId(iid);
    258 
    259     dprintf(("OLE32: CoCreateInstance"));
    260     dprintf(("       CLSID:%s", (char *)tCLSID));
    261     dprintf(("       IID  :%s", (char *)tIId));
    262 
    263     // Sanity check
    264     if (ppv == 0)
    265         return E_POINTER;
    266 
    267     *ppv = 0;
    268 
    269     // Get a class factory to construct the object we want.
    270     hres = CoGetClassObject(rclsid, dwClsContext, NULL, &IID_IClassFactory, (LPVOID *)&lpclf);
    271 
    272     if (FAILED(hres))
    273         return hres;
    274 
    275     // Create the object and don't forget to release the factory
    276     hres = IClassFactory_CreateInstance(lpclf, pUnkOuter, iid, ppv);
    277     IClassFactory_Release(lpclf);
    278 
    279     return hres;
    280 }
    281 
    282 // ----------------------------------------------------------------------
    283 // CoCreateInstanceEx
    284 // ----------------------------------------------------------------------
    285 HRESULT WIN32API CoCreateInstanceEx
    286    (REFCLSID            rclsid,
    287     LPUNKNOWN           pUnkOuter,
    288     DWORD               dwClsContext,
    289     COSERVERINFO *      pServerInfo,
    290     ULONG               cmq,
    291     MULTI_QI *          pResults)
    292 {
    293     IUnknown *          pUnk = NULL;
    294     HRESULT             hr;
    295     ULONG               index;
    296     int                 successCount = 0;
    297 
    298     oStringA            tCLSID(rclsid);
    299 
    300     dprintf(("OLE32: CoCreateInstanceEx"));
    301     dprintf(("       CLSID:%s", (char *)tCLSID));
    302 
    303     // Sanity check
    304     if ( (cmq == 0) || (pResults == NULL))
    305         return E_INVALIDARG;
    306 
    307     if (pServerInfo != NULL)
    308         dprintf(("OLE32: CoCreateInstanceEx - pServerInfo not supported!"));
    309 
    310     // Initialize all the "out" parameters.
    311     for (index = 0; index < cmq; index++)
    312     {
    313         pResults[index].pItf = NULL;
    314         pResults[index].hr   = E_NOINTERFACE;
    315     }
    316 
    317     /*
    318     * Get the object and get it's IUnknown pointer.
    319     */
    320     hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, &IID_IUnknown, (VOID**)&pUnk);
    321 
    322     if (hr)
    323         return hr;
    324 
    325     /*
    326     * Then, query for all the interfaces requested.
    327     */
    328     for (index = 0; index < cmq; index++)
    329     {
    330         pResults[index].hr = IUnknown_QueryInterface(pUnk, pResults[index].pIID, (VOID**)&(pResults[index].pItf));
    331 
    332         if (pResults[index].hr == S_OK)
    333             successCount++;
    334     }
    335 
    336     /*
    337     * Release our temporary unknown pointer.
    338     */
    339     IUnknown_Release(pUnk);
    340 
    341     if (successCount == 0)
    342         return E_NOINTERFACE;
    343 
    344     if (successCount != cmq)
    345         return CO_S_NOTALLINTERFACES;
    346 
    347     return S_OK;
    348 }
    349 
    350 // ----------------------------------------------------------------------
    351 // CoGetClassObject
    352 // ----------------------------------------------------------------------
    353 HRESULT WIN32API CoGetClassObject
    354    (REFCLSID            rclsid,
    355     DWORD               dwClsContext,
    356     LPVOID              pvReserved,
    357     REFIID              iid,
    358     LPVOID *            ppv)
    359 {
    360     LPUNKNOWN           regClassObject;
    361     HRESULT             hres = E_UNEXPECTED;
    362 
    363     char                dllName[MAX_PATH+1];
    364     LONG                dllNameLen = sizeof(dllName);
    365     HINSTANCE           hLibrary;
    366 
    367     DllGetClassObjectFunc DllGetClassObject;
    368     oStringA            tCLSID(rclsid);
    369 
    370 #ifdef DEBUG
    371     oStringA            tIId(iid);
    372     dprintf(("OLE32: CoGetClassObject"));
    373     dprintf(("       CLSID:%s", (char *)tCLSID));
    374     dprintf(("       IID  :%s", (char *)tIId));
    375 #endif
    376 
    377     // First, try and see if we can't match the class ID with one of the
    378     // registered classes.
    379     if (S_OK == COM_GetRegisteredClassObject(rclsid, dwClsContext, &regClassObject))
    380     {
    381         // Get the required interface from the retrieved pointer.
    382         hres = IUnknown_QueryInterface(regClassObject, iid, ppv);
    383 
    384         // Since QI got another reference on the pointer, we want to release the
    385         // one we already have. If QI was unsuccessful, this will release the object. This
    386         // is good since we are not returning it in the "out" parameter.
    387         IUnknown_Release(regClassObject);
    388 
    389         return hres;
    390     }
    391 
    392     // out of process and remote servers not supported yet...
    393     if (dwClsContext & CLSCTX_LOCAL_SERVER)
    394     {
    395         dprintf(("OLE32: CoGetClassObject - CLSCTX_LOCAL_SERVER not supported!\n"));
    396 //      return E_ACCESSDENIED;
    397         dwClsContext |= CLSCTX_INPROC_SERVER;   // Kludge as VB uses CLSCTX_LOCAL_SERVER
    398     }
    399 
    400     if (dwClsContext & CLSCTX_REMOTE_SERVER)
    401     {
    402         dprintf(("OLE32: CoGetClassObject - CLSCTX_REMOTE_SERVER not supported!\n"));
    403         return E_ACCESSDENIED;
    404     }
    405 
    406     // Get down to the biz..
    407     if (dwClsContext & (CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER))
    408     {
    409         HKEY    CLSIDkey;
    410         HKEY    key;
    411 
    412         /* lookup CLSID in registry key HKCR/CLSID */
    413         hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &CLSIDkey);
    414         if (hres != ERROR_SUCCESS)
    415             return REGDB_E_READREGDB;
    416 
    417         hres = RegOpenKeyExA(CLSIDkey, tCLSID, 0, KEY_QUERY_VALUE, &key);
    418         if (hres != ERROR_SUCCESS)
    419         {
    420             RegCloseKey(CLSIDkey);
    421             return REGDB_E_CLASSNOTREG;
    422         }
    423 
    424         hres = RegQueryValueA(key, "InprocServer32", dllName, &dllNameLen);
    425         RegCloseKey(key);
    426         RegCloseKey(CLSIDkey);
    427         if (hres != ERROR_SUCCESS)
    428         {
    429             dprintf(("OLE32: CoGetClassObject - InprocServer32 not found in registry"));
    430             return REGDB_E_READREGDB;
    431         }
    432 
    433         dprintf(("OLE32: CoGetClassObject - Registry reports InprocServer32 dll as %s\n", dllName));
    434 
    435         /* open dll, call DllGetClassFactory */
    436         hLibrary = CoLoadLibrary(dllName, TRUE);
    437         if (hLibrary == 0)
    438         {
    439             dprintf(("OLE32: CoGetClassObject - couldn't load %s\n", dllName));
    440             return E_ACCESSDENIED; /* or should this be CO_E_DLLNOTFOUND? */
    441         }
    442 
    443         DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject");
    444         if (!DllGetClassObject)
    445         {
    446             dprintf(("OLE32: CoGetClassObject - couldn't function DllGetClassObject in %s\n", dllName));
    447             /* not sure if this should be called here CoFreeLibrary(hLibrary);*/
    448             return E_ACCESSDENIED;
    449         }
    450 
    451         // Ask the DLL for it's class object. (there was a note here about class
    452         // factories but this is good.
    453         return DllGetClassObject(rclsid, iid, ppv);
    454     }
    455     return hres;
    456 }
    457 
    458 // ----------------------------------------------------------------------
    459 // CoLockObjectExternal
    460 // ----------------------------------------------------------------------
    461 HRESULT WIN32API CoLockObjectExternal(IUnknown *pUnk, BOOL fLock, BOOL fLastUnlockReleases)
    462 {
    463     dprintf(("OLE32: CoLockObjectExternal"));
    464 
    465     if (fLock)
    466     {
    467         /*
    468          * Increment the external lock coutner, COM_ExternalLockAddRef also
    469          * increment the object's internal lock counter.
    470          */
    471         COM_ExternalLockAddRef( pUnk);
    472     }
    473     else
    474     {
    475         /*
    476          * Decrement the external lock coutner, COM_ExternalLockRelease also
    477          * decrement the object's internal lock counter.
    478          */
    479         COM_ExternalLockRelease( pUnk, fLastUnlockReleases);
    480     }
    481 
    482     return S_OK;
    483 }
    484 
    485 // ----------------------------------------------------------------------
    486 // CoRegisterClassObject
    487 // ----------------------------------------------------------------------
    488 HRESULT WIN32API CoRegisterClassObject(
    489     REFCLSID            rclsid,
    490     LPUNKNOWN           pUnk,
    491     DWORD               dwClsContext,   // Context in which to run the executable
    492     DWORD               flags,          // how connections are made
    493     LPDWORD             lpdwRegister)
    494 {
    495     RegisteredClass *   newClass;
    496     LPUNKNOWN           foundObject;
    497     HRESULT             hr;
    498     oStringA            tClsid(rclsid);
    499 
    500     dprintf(("OLE32: CoRegisterClassObject(%s)", (char *)tClsid));
    501 
    502     // Perform a sanity check on the parameters
    503     if ((lpdwRegister == 0) || (pUnk == 0))
    504         return E_INVALIDARG;
    505 
    506     // Initialize the cookie (out parameter)
    507     *lpdwRegister = 0;
    508 
    509     // First, check if the class is already registered.
    510     // If it is, this should cause an error.
    511     hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject);
    512     if (hr == S_OK)
    513     {
    514         // The COM_GetRegisteredClassObject increased the reference count on the
    515         // object so it has to be released.
    516         IUnknown_Release(foundObject);
    517 
    518         return CO_E_OBJISREG;
    519     }
    520 
    521     // If it is not registered, we must create a new entry for this class and
    522     // append it to the registered class list.
    523     // We use the address of the chain node as the cookie since we are sure it's
    524     // unique.
    525     newClass = (RegisteredClass *)HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass));
    526 
    527     // Initialize the node.
    528     newClass->classIdentifier = *rclsid;
    529     newClass->runContext      = dwClsContext;
    530     newClass->connectFlags    = flags;
    531     newClass->dwCookie        = (DWORD)newClass;
    532     newClass->nextClass       = firstRegisteredClass;
    533 
    534     // Since we're making a copy of the object pointer, we have to increase it's
    535     // reference count.
    536     newClass->classObject     = pUnk;
    537     IUnknown_AddRef(newClass->classObject);
    538 
    539     firstRegisteredClass = newClass;
    540 
    541     // Assign the out parameter (cookie)
    542     *lpdwRegister = newClass->dwCookie;
    543 
    544     return S_OK;
    545 }
    546 
    547 // ----------------------------------------------------------------------
    548 // CoRevokeClassObject
    549 //
    550 // This method will remove a class object from the class registry
    551 // ----------------------------------------------------------------------
    552 HRESULT WIN32API CoRevokeClassObject(DWORD dwRegister)
    553 {
    554     RegisteredClass * * prevClassLink;
    555     RegisteredClass *   curClass;
    556 
    557     dprintf(("OLE32: CoRevokeClassObject"));
    558 
    559     // Iterate through the whole list and try to match the cookie.
    560     curClass      = firstRegisteredClass;
    561     prevClassLink = &firstRegisteredClass;
    562 
    563     while (curClass != 0)
    564     {
    565         // Check if we have a match on the cookie.
    566         if (curClass->dwCookie == dwRegister)
    567         {
    568             // Remove the class from the chain.
    569             *prevClassLink = curClass->nextClass;
    570 
    571             // Release the reference to the class object.
    572             IUnknown_Release(curClass->classObject);
    573 
    574             // Free the memory used by the chain node.
    575             HeapFree(GetProcessHeap(), 0, curClass);
    576 
    577             return S_OK;
    578         }
    579 
    580         // Step to the next class in the list.
    581         prevClassLink = &(curClass->nextClass);
    582         curClass      = curClass->nextClass;
    583     }
    584 
    585     return E_INVALIDARG;
    586 }
    587 
    588 // ----------------------------------------------------------------------
    589 // GetClassFile
    590 //
    591 // This function supplies the CLSID associated with the given filename.
    592 // ----------------------------------------------------------------------
    593 HRESULT WIN32API GetClassFile(LPOLESTR filePathName, CLSID *pclsid)
    594 {
    595     IStorage *  pstg = 0;
    596     HRESULT     res;
    597     int         nbElm = 0;
    598     int         length = 0;
    599     int         i = 0;
    600     LONG        sizeProgId = 20;
    601     LPOLESTR *  pathDec = 0;
    602     LPOLESTR    absFile = 0;
    603     LPOLESTR    progId = 0;
    604     WCHAR       extention[100] = {0};
    605 
    606     dprintf(("OLE32: GetClassFile"));
    607 
    608     // if the file contain a storage object the return the CLSID
    609     // writen by IStorage_SetClass method
    610 
    611     if((StgIsStorageFile(filePathName)) == S_OK)
    612     {
    613         res = StgOpenStorage(filePathName, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &pstg);
    614 
    615         if (SUCCEEDED(res))
    616             res = ReadClassStg(pstg, pclsid);
    617 
    618         IStorage_Release(pstg);
    619 
    620         return res;
    621     }
    622 
    623     /* if the obove strategies fail then search for the extension key in the registry */
    624 
    625     /* get the last element (absolute file) in the path name */
    626     nbElm = FileMonikerImpl_DecomposePath(filePathName, &pathDec);
    627     absFile = pathDec[nbElm-1];
    628 
    629     /* failed if the path represente a directory and not an absolute file name*/
    630     if (lstrcmpW(absFile, (LPOLESTR)"\\"))
    631         return MK_E_INVALIDEXTENSION;
    632 
    633     /* get the extension of the file */
    634     length = lstrlenW(absFile);
    635     for(i = length-1; ( (i >= 0) && (extention[i] = absFile[i]) ); i--);
    636        
    637     /* get the progId associated to the extension */
    638     progId = (WCHAR *)CoTaskMemAlloc(sizeProgId);
    639 
    640     res = RegQueryValueW(HKEY_CLASSES_ROOT, extention, progId, &sizeProgId);
    641 
    642     if (res == ERROR_MORE_DATA)
    643     {
    644         CoTaskMemRealloc(progId,sizeProgId);
    645 
    646         res = RegQueryValueW(HKEY_CLASSES_ROOT, extention, progId, &sizeProgId);
    647     }
    648     if (res == ERROR_SUCCESS)
    649         /* return the clsid associated to the progId */
    650         res =  CLSIDFromProgID(progId, pclsid);
    651 
    652     for(i = 0; pathDec[i] != NULL; i++)
    653         CoTaskMemFree(pathDec[i]);
    654 
    655     CoTaskMemFree(pathDec);
    656 
    657     CoTaskMemFree(progId);
    658 
    659     if (res == ERROR_SUCCESS)
    660         return res;
    661 
    662     return MK_E_INVALIDEXTENSION;
    663 }
    664 // ======================================================================
    665 // Private functions.
    666 // ======================================================================
    667 
    668 // ----------------------------------------------------------------------
    669 // COM_GetRegisteredClassObject
    670 // ----------------------------------------------------------------------
    671 // This internal method is used to scan the registered class list to
    672 // find a class object.
    673 //
    674 // Params:
    675 //   rclsid        Class ID of the class to find.
    676 //   dwClsContext  Class context to match.
    677 //   ppv           [out] returns a pointer to the class object. Complying
    678 //                 to normal COM usage, this method will increase the
    679 //                 reference count on this object.
    680 static HRESULT COM_GetRegisteredClassObject
    681    (REFCLSID            rclsid,
    682     DWORD               dwClsContext,
    683     LPUNKNOWN *         ppUnk)
    684 {
    685     RegisteredClass* curClass;
    686 
    687     oStringA            tCLSID(rclsid);
    688 
    689     dprintf(("OLE32: COM_GetRegisteredClassObject"));
    690     dprintf(("       CLSID:%s", (char *)tCLSID));
    691 
    692     // Sanity check
    693     if (ppUnk == 0)
    694         return E_POINTER;
    695 
    696     // Iterate through the whole list and try to match the class ID.
    697     curClass = firstRegisteredClass;
    698 
    699     while (curClass != 0)
    700     {
    701         // Check if we have a match on the class ID.
    702         if (IsEqualGUID(&curClass->classIdentifier, rclsid))
    703         {
    704             // Since we don't do out-of process or DCOM just right away,
    705             // let's ignore the class context.
    706 
    707             // We have a match, return the pointer to the class object.
    708             *ppUnk = curClass->classObject;
    709 
    710             IUnknown_AddRef(curClass->classObject);
    711 
    712             return S_OK;
    713         }
    714 
    715     // Step to the next class in the list.
    716     curClass = curClass->nextClass;
    717     }
    718 
    719     // If we get to here, we haven't found our class.
    720     return S_FALSE;
    721 }
    722 
    723 // ----------------------------------------------------------------------
    724 // COM_RevokeAllClasses
    725 // ----------------------------------------------------------------------
    726 // This method is called when the COM libraries are uninitialized to
    727 // release all the references to the class objects registered with
    728 // the library
    729 static void COM_RevokeAllClasses()
    730 {
    731     dprintf(("OLE32: COM_RevokeAllClasses"));
    732 
    733     while (firstRegisteredClass != 0)
    734     {
    735         CoRevokeClassObject(firstRegisteredClass->dwCookie);
    736     }
    737 }
    738 
    739 // ----------------------------------------------------------------------
    740 // COM_ExternalLockAddRef
    741 // ----------------------------------------------------------------------
    742 // Method that increments the count for a IUnknown* in the linked
    743 // list.  The item is inserted if not already in the list.
    744 static void COM_ExternalLockAddRef(IUnknown * pUnk)
    745 {
    746     dprintf(("OLE32: COM_ExternalLockAddRef"));
    747 
    748     COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk);
    749 
    750     /*
    751      * Add an external lock to the object. If it was already externally
    752      * locked, just increase the reference count. If it was not.
    753      * add the item to the list.
    754      */
    755     if ( externalLock == EL_NOT_FOUND )
    756         COM_ExternalLockInsert(pUnk);
    757     else
    758         externalLock->uRefCount++;
    759 
    760     /*
    761      * Add an internal lock to the object
    762      */
    763     IUnknown_AddRef(pUnk);
    764 }
    765 
    766 // ----------------------------------------------------------------------
    767 // COM_ExternalLockRelease
    768 // ----------------------------------------------------------------------
    769 // Method that decrements the count for a IUnknown* in the linked
    770 // list.  The item is removed from the list if its count end up at zero or if
    771 // bRelAll is TRUE.
    772 static void COM_ExternalLockRelease(IUnknown * pUnk, BOOL bRelAll)
    773 {
    774     dprintf(("OLE32: COM_ExternalLockRelease"));
    775 
    776     COM_ExternalLock * externalLock = COM_ExternalLockFind(pUnk);
    777 
    778     if ( externalLock != EL_NOT_FOUND )
    779     {
    780         do
    781         {
    782             externalLock->uRefCount--;  /* release external locks      */
    783             IUnknown_Release(pUnk);     /* release local locks as well */
    784 
    785             if ( bRelAll == FALSE )
    786                 break;  /* perform single release */
    787 
    788         } while ( externalLock->uRefCount > 0 ); 
    789 
    790         if ( externalLock->uRefCount == 0 )  /* get rid of the list entry */
    791             COM_ExternalLockDelete(externalLock);
    792     }
    793 }
    794 
    795 // ----------------------------------------------------------------------
    796 // COM_ExternalLockFreeList
    797 // ----------------------------------------------------------------------
    798 // Method that frees the content of the list.
    799 static void COM_ExternalLockFreeList()
    800 {
    801     dprintf(("OLE32: COM_ExternalLockFreeList"));
    802 
    803     COM_ExternalLock *head;
    804 
    805     head = elList.head;                 /* grab it by the head             */
    806     while (head != EL_END_OF_LIST)
    807     {
    808         COM_ExternalLockDelete(head);     /* get rid of the head stuff       */
    809 
    810         head = elList.head;               /* get the new head...             */
    811     }
    812 }
    813 
    814 // ----------------------------------------------------------------------
    815 // COM_ExternalLockDump
    816 // ----------------------------------------------------------------------
    817 // Method that dump the content of the list.
    818 void COM_ExternalLockDump()
    819 {
    820     dprintf(("OLE32: COM_ExternalLockDump"));
    821 
    822     COM_ExternalLock *current = elList.head;
    823 
    824     printf("External lock list:");
    825 
    826     while ( current != EL_END_OF_LIST )
    827     {
    828         dprintf(("    %p with %lu references count.\n", current->pUnk, current->uRefCount));
    829 
    830         /* Skip to the next item */
    831         current = current->next;
    832     }
    833 }
    834 
    835 // ----------------------------------------------------------------------
    836 // COM_ExternalLockFind
    837 // ----------------------------------------------------------------------
    838 // Find a IUnknown* in the linked list
    839 static COM_ExternalLock * COM_ExternalLockFind(IUnknown *pUnk)
    840 {
    841     dprintf(("OLE32: COM_ExternalLockFind"));
    842 
    843     return COM_ExternalLockLocate(elList.head, pUnk);
    844 }
    845 
    846 // ----------------------------------------------------------------------
    847 // COM_ExternalLockLocate
    848 // ----------------------------------------------------------------------
    849 // Recursivity agent for IUnknownExternalLockList_Find
    850 static COM_ExternalLock * COM_ExternalLockLocate( COM_ExternalLock * element, IUnknown * pUnk)
    851 {
    852   if ( element == EL_END_OF_LIST ) 
    853     return EL_NOT_FOUND;
    854 
    855   else if ( element->pUnk == pUnk )    /* We found it */
    856     return element;
    857 
    858   else                                 /* Not the right guy, keep on looking */
    859     return COM_ExternalLockLocate( element->next, pUnk);
    860 }
    861 
    862 // ----------------------------------------------------------------------
    863 // COM_ExternalLockInsert
    864 // ----------------------------------------------------------------------
    865 // Insert a new IUnknown* to the linked list
    866 static BOOL COM_ExternalLockInsert(IUnknown * pUnk)
    867 {
    868     dprintf(("OLE32: COM_ExternalLockInsert"));
    869 
    870     COM_ExternalLock *  newLock      = NULL;
    871     COM_ExternalLock *  previousHead = NULL;
    872 
    873     // Allocate space for the new storage object
    874     newLock = (COM_ExternalLock *)HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock));
    875 
    876     if (newLock != NULL)
    877     {
    878         if ( elList.head == EL_END_OF_LIST )
    879             elList.head = newLock;    /* The list is empty */
    880         else
    881         {
    882             // insert does it at the head
    883             previousHead  = elList.head;
    884             elList.head = newLock;
    885         }
    886 
    887         /*
    888          * Set new list item data member
    889          */
    890         newLock->pUnk      = pUnk;
    891         newLock->uRefCount = 1;
    892         newLock->next      = previousHead;
    893 
    894         return TRUE;
    895     }
    896 
    897     return FALSE;
    898 }
    899 
    900 // ----------------------------------------------------------------------
    901 // ExternalLockDelete
    902 // ----------------------------------------------------------------------
    903 // Method that removes an item from the linked list.
    904 static void COM_ExternalLockDelete(COM_ExternalLock * itemList)
    905 {
    906     dprintf(("OLE32: ExternalLockDelete"));
    907 
    908     COM_ExternalLock *current = elList.head;
    909 
    910     if ( current == itemList )
    911     {
    912         // this section handles the deletion of the first node
    913         elList.head = itemList->next;
    914         HeapFree( GetProcessHeap(), 0, itemList); 
    915     }
    916     else
    917     {
    918         do
    919         {
    920             if ( current->next == itemList )   /* We found the item to free  */
    921             {
    922                 current->next = itemList->next;  /* readjust the list pointers */
    923 
    924                 HeapFree( GetProcessHeap(), 0, itemList); 
    925                 break;
    926             }
    927 
    928             /* Skip to the next item */
    929             current = current->next;
    930 
    931         } while ( current != EL_END_OF_LIST );
    932     }
    933 }
Note: See TracChangeset for help on using the changeset viewer.