source: trunk/src/ole32/ole32.cpp@ 2362

Last change on this file since 2362 was 2362, checked in by davidr, 26 years ago

Fixed log file typo's

File size: 26.2 KB
Line 
1/* $Id: ole32.cpp,v 1.12 2000-01-08 09:27:56 davidr Exp $ */
2/*
3 *
4 * Project Odin Software License can be found in LICENSE.TXT
5 *
6 */
7/*
8 * COM/OLE misc. functions.
9 *
10 * 1/7/99
11 *
12 * Copyright 1999 David J. Raison
13 *
14 * Some portions from Wine Implementation
15 * Copyright 1995 Martin von Loewis
16 * Copyright 1998 Justin Bradford
17 * Copyright 1999 Francis Beaudet
18 * Copyright 1999 Sylvain St-Germain
19 */
20
21#include "ole32.h"
22
23#include "oString.h"
24#include "moniker.h" // RunningObjectTableImpl_***
25#include "filemoniker.h" // FileMonikerImpl_***
26
27// ======================================================================
28// Local Data
29// ======================================================================
30typedef 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 */
37typedef 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
47static 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 */
64typedef struct COM_ExternalLock COM_ExternalLock;
65typedef struct COM_ExternalLockList COM_ExternalLockList;
66
67struct 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
74struct 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 */
83static 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 */
91static LONG COM_ref = 0;
92
93// ======================================================================
94// Prototypes.
95// ======================================================================
96static HRESULT COM_GetRegisteredClassObject(
97 REFCLSID rclsid,
98 DWORD dwClsContext,
99 LPUNKNOWN * ppUnk);
100
101static void COM_RevokeAllClasses();
102
103static void COM_ExternalLockFreeList();
104
105static void COM_ExternalLockAddRef(
106 IUnknown * pUnk);
107
108static void COM_ExternalLockRelease(
109 IUnknown * pUnk,
110 BOOL bRelAll);
111
112static BOOL COM_ExternalLockInsert(
113 IUnknown * pUnk);
114
115static void COM_ExternalLockDelete(
116 COM_ExternalLock * element);
117
118static COM_ExternalLock * COM_ExternalLockFind(
119 IUnknown * pUnk);
120
121static COM_ExternalLock * COM_ExternalLockLocate(
122 COM_ExternalLock * element,
123 IUnknown * pUnk);
124
125// ======================================================================
126// Public API's
127// ======================================================================
128
129// ----------------------------------------------------------------------
130// CoBuildVersion()
131// ----------------------------------------------------------------------
132DWORD WIN32API CoBuildVersion()
133{
134 dprintf(("OLE32.CoBuildVersion"));
135 return (rmm << 16) + rup;
136}
137
138// ----------------------------------------------------------------------
139// CoDosDateTimeToFileTime
140// ----------------------------------------------------------------------
141BOOL WIN32API CoDosDateTimeToFileTime(WORD nDosDate, WORD nDosTime,
142 FILETIME *lpFileTime)
143{
144 dprintf(("OLE32: CoDosDateTimeToFileTime"));
145
146 return DosDateTimeToFileTime(nDosDate, nDosTime, lpFileTime);
147}
148
149// ----------------------------------------------------------------------
150// CoDosDateTimeToFileTime
151// ----------------------------------------------------------------------
152HRESULT 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// ----------------------------------------------------------------------
165BOOL WIN32API CoFileTimeToDosDateTime(FILETIME *lpFileTime, LPWORD lpDosDate,
166 LPWORD lpDosTime)
167{
168 dprintf(("OLE32: CoFileTimeToDosDateTime"));
169
170 return FileTimeToDosDateTime(lpFileTime, lpDosDate, lpDosTime);
171}
172
173// ----------------------------------------------------------------------
174// CoInitialize()
175// ----------------------------------------------------------------------
176HRESULT WIN32API CoInitialize(LPVOID lpReserved)
177{
178 dprintf(("OLE32: CoInitialize\n"));
179
180 return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
181}
182
183// ----------------------------------------------------------------------
184// CoInitializeEx()
185// ----------------------------------------------------------------------
186HRESULT 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// ----------------------------------------------------------------------
225void 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// ----------------------------------------------------------------------
246HRESULT 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// ----------------------------------------------------------------------
285HRESULT 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// ----------------------------------------------------------------------
353HRESULT 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 }
398
399 if (dwClsContext & CLSCTX_REMOTE_SERVER)
400 {
401 dprintf(("OLE32: CoGetClassObject - CLSCTX_REMOTE_SERVER not supported!\n"));
402 return E_ACCESSDENIED;
403 }
404
405 // Get down to the biz..
406 if (dwClsContext & (CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER))
407 {
408 HKEY CLSIDkey;
409 HKEY key;
410
411 /* lookup CLSID in registry key HKCR/CLSID */
412 hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &CLSIDkey);
413 if (hres != ERROR_SUCCESS)
414 return REGDB_E_READREGDB;
415
416 hres = RegOpenKeyExA(CLSIDkey, tCLSID, 0, KEY_QUERY_VALUE, &key);
417 if (hres != ERROR_SUCCESS)
418 {
419 RegCloseKey(CLSIDkey);
420 return REGDB_E_CLASSNOTREG;
421 }
422
423 hres = RegQueryValueA(key, "InprocServer32", dllName, &dllNameLen);
424 RegCloseKey(key);
425 RegCloseKey(CLSIDkey);
426 if (hres != ERROR_SUCCESS)
427 {
428 dprintf(("OLE32: CoGetClassObject - InprocServer32 not found in registry"));
429 return REGDB_E_READREGDB;
430 }
431
432 dprintf(("OLE32: CoGetClassObject - Registry reports InprocServer32 dll as %s\n", dllName));
433
434 /* open dll, call DllGetClassFactory */
435 hLibrary = CoLoadLibrary(dllName, TRUE);
436 if (hLibrary == 0)
437 {
438 dprintf(("OLE32: CoGetClassObject - couldn't load %s\n", dllName));
439 return E_ACCESSDENIED; /* or should this be CO_E_DLLNOTFOUND? */
440 }
441
442 DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject");
443 if (!DllGetClassObject)
444 {
445 dprintf(("OLE32: CoGetClassObject - couldn't function DllGetClassObject in %s\n", dllName));
446 /* not sure if this should be called here CoFreeLibrary(hLibrary);*/
447 return E_ACCESSDENIED;
448 }
449
450 // Ask the DLL for it's class object. (there was a note here about class
451 // factories but this is good.
452 return DllGetClassObject(rclsid, iid, ppv);
453 }
454 return hres;
455}
456
457// ----------------------------------------------------------------------
458// CoLockObjectExternal
459// ----------------------------------------------------------------------
460HRESULT WIN32API CoLockObjectExternal(IUnknown *pUnk, BOOL fLock, BOOL fLastUnlockReleases)
461{
462 dprintf(("OLE32: CoLockObjectExternal"));
463
464 if (fLock)
465 {
466 /*
467 * Increment the external lock coutner, COM_ExternalLockAddRef also
468 * increment the object's internal lock counter.
469 */
470 COM_ExternalLockAddRef( pUnk);
471 }
472 else
473 {
474 /*
475 * Decrement the external lock coutner, COM_ExternalLockRelease also
476 * decrement the object's internal lock counter.
477 */
478 COM_ExternalLockRelease( pUnk, fLastUnlockReleases);
479 }
480
481 return S_OK;
482}
483
484// ----------------------------------------------------------------------
485// CoRegisterClassObject
486// ----------------------------------------------------------------------
487HRESULT WIN32API CoRegisterClassObject(
488 REFCLSID rclsid,
489 LPUNKNOWN pUnk,
490 DWORD dwClsContext, // Context in which to run the executable
491 DWORD flags, // how connections are made
492 LPDWORD lpdwRegister)
493{
494 RegisteredClass * newClass;
495 LPUNKNOWN foundObject;
496 HRESULT hr;
497 oStringA tClsid(rclsid);
498
499 dprintf(("OLE32: CoRegisterClassObject(%s)", (char *)tClsid));
500
501 // Perform a sanity check on the parameters
502 if ((lpdwRegister == 0) || (pUnk == 0))
503 return E_INVALIDARG;
504
505 // Initialize the cookie (out parameter)
506 *lpdwRegister = 0;
507
508 // First, check if the class is already registered.
509 // If it is, this should cause an error.
510 hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject);
511 if (hr == S_OK)
512 {
513 // The COM_GetRegisteredClassObject increased the reference count on the
514 // object so it has to be released.
515 IUnknown_Release(foundObject);
516
517 return CO_E_OBJISREG;
518 }
519
520 // If it is not registered, we must create a new entry for this class and
521 // append it to the registered class list.
522 // We use the address of the chain node as the cookie since we are sure it's
523 // unique.
524 newClass = (RegisteredClass *)HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass));
525
526 // Initialize the node.
527 newClass->classIdentifier = *rclsid;
528 newClass->runContext = dwClsContext;
529 newClass->connectFlags = flags;
530 newClass->dwCookie = (DWORD)newClass;
531 newClass->nextClass = firstRegisteredClass;
532
533 // Since we're making a copy of the object pointer, we have to increase it's
534 // reference count.
535 newClass->classObject = pUnk;
536 IUnknown_AddRef(newClass->classObject);
537
538 firstRegisteredClass = newClass;
539
540 // Assign the out parameter (cookie)
541 *lpdwRegister = newClass->dwCookie;
542
543 return S_OK;
544}
545
546// ----------------------------------------------------------------------
547// CoRevokeClassObject
548//
549// This method will remove a class object from the class registry
550// ----------------------------------------------------------------------
551HRESULT WIN32API CoRevokeClassObject(DWORD dwRegister)
552{
553 RegisteredClass * * prevClassLink;
554 RegisteredClass * curClass;
555
556 dprintf(("OLE32: CoRevokeClassObject"));
557
558 // Iterate through the whole list and try to match the cookie.
559 curClass = firstRegisteredClass;
560 prevClassLink = &firstRegisteredClass;
561
562 while (curClass != 0)
563 {
564 // Check if we have a match on the cookie.
565 if (curClass->dwCookie == dwRegister)
566 {
567 // Remove the class from the chain.
568 *prevClassLink = curClass->nextClass;
569
570 // Release the reference to the class object.
571 IUnknown_Release(curClass->classObject);
572
573 // Free the memory used by the chain node.
574 HeapFree(GetProcessHeap(), 0, curClass);
575
576 return S_OK;
577 }
578
579 // Step to the next class in the list.
580 prevClassLink = &(curClass->nextClass);
581 curClass = curClass->nextClass;
582 }
583
584 return E_INVALIDARG;
585}
586
587// ----------------------------------------------------------------------
588// GetClassFile
589//
590// This function supplies the CLSID associated with the given filename.
591// ----------------------------------------------------------------------
592HRESULT WIN32API GetClassFile(LPOLESTR filePathName, CLSID *pclsid)
593{
594 IStorage * pstg = 0;
595 HRESULT res;
596 int nbElm = 0;
597 int length = 0;
598 int i = 0;
599 LONG sizeProgId = 20;
600 LPOLESTR * pathDec = 0;
601 LPOLESTR absFile = 0;
602 LPOLESTR progId = 0;
603 WCHAR extention[100] = {0};
604
605 dprintf(("OLE32: GetClassFile"));
606
607 // if the file contain a storage object the return the CLSID
608 // writen by IStorage_SetClass method
609
610 if((StgIsStorageFile(filePathName)) == S_OK)
611 {
612 res = StgOpenStorage(filePathName, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &pstg);
613
614 if (SUCCEEDED(res))
615 res = ReadClassStg(pstg, pclsid);
616
617 IStorage_Release(pstg);
618
619 return res;
620 }
621
622 /* if the obove strategies fail then search for the extension key in the registry */
623
624 /* get the last element (absolute file) in the path name */
625 nbElm = FileMonikerImpl_DecomposePath(filePathName, &pathDec);
626 absFile = pathDec[nbElm-1];
627
628 /* failed if the path represente a directory and not an absolute file name*/
629 if (lstrcmpW(absFile, (LPOLESTR)"\\"))
630 return MK_E_INVALIDEXTENSION;
631
632 /* get the extension of the file */
633 length = lstrlenW(absFile);
634 for(i = length-1; ( (i >= 0) && (extention[i] = absFile[i]) ); i--);
635
636 /* get the progId associated to the extension */
637 progId = (WCHAR *)CoTaskMemAlloc(sizeProgId);
638
639 res = RegQueryValueW(HKEY_CLASSES_ROOT, extention, progId, &sizeProgId);
640
641 if (res == ERROR_MORE_DATA)
642 {
643 CoTaskMemRealloc(progId,sizeProgId);
644
645 res = RegQueryValueW(HKEY_CLASSES_ROOT, extention, progId, &sizeProgId);
646 }
647 if (res == ERROR_SUCCESS)
648 /* return the clsid associated to the progId */
649 res = CLSIDFromProgID(progId, pclsid);
650
651 for(i = 0; pathDec[i] != NULL; i++)
652 CoTaskMemFree(pathDec[i]);
653
654 CoTaskMemFree(pathDec);
655
656 CoTaskMemFree(progId);
657
658 if (res == ERROR_SUCCESS)
659 return res;
660
661 return MK_E_INVALIDEXTENSION;
662}
663// ======================================================================
664// Private functions.
665// ======================================================================
666
667// ----------------------------------------------------------------------
668// COM_GetRegisteredClassObject
669// ----------------------------------------------------------------------
670// This internal method is used to scan the registered class list to
671// find a class object.
672//
673// Params:
674// rclsid Class ID of the class to find.
675// dwClsContext Class context to match.
676// ppv [out] returns a pointer to the class object. Complying
677// to normal COM usage, this method will increase the
678// reference count on this object.
679static HRESULT COM_GetRegisteredClassObject
680 (REFCLSID rclsid,
681 DWORD dwClsContext,
682 LPUNKNOWN * ppUnk)
683{
684 RegisteredClass* curClass;
685
686 oStringA tCLSID(rclsid);
687
688 dprintf(("OLE32: COM_GetRegisteredClassObject"));
689 dprintf((" CLSID:%s", (char *)tCLSID));
690
691 // Sanity check
692 if (ppUnk == 0)
693 return E_POINTER;
694
695 // Iterate through the whole list and try to match the class ID.
696 curClass = firstRegisteredClass;
697
698 while (curClass != 0)
699 {
700 // Check if we have a match on the class ID.
701 if (IsEqualGUID(&curClass->classIdentifier, &rclsid))
702 {
703 // Since we don't do out-of process or DCOM just right away,
704 // let's ignore the class context.
705
706 // We have a match, return the pointer to the class object.
707 *ppUnk = curClass->classObject;
708
709 IUnknown_AddRef(curClass->classObject);
710
711 return S_OK;
712 }
713
714 // Step to the next class in the list.
715 curClass = curClass->nextClass;
716 }
717
718 // If we get to here, we haven't found our class.
719 return S_FALSE;
720}
721
722// ----------------------------------------------------------------------
723// COM_RevokeAllClasses
724// ----------------------------------------------------------------------
725// This method is called when the COM libraries are uninitialized to
726// release all the references to the class objects registered with
727// the library
728static void COM_RevokeAllClasses()
729{
730 dprintf(("OLE32: COM_RevokeAllClasses"));
731
732 while (firstRegisteredClass != 0)
733 {
734 CoRevokeClassObject(firstRegisteredClass->dwCookie);
735 }
736}
737
738// ----------------------------------------------------------------------
739// COM_ExternalLockAddRef
740// ----------------------------------------------------------------------
741// Method that increments the count for a IUnknown* in the linked
742// list. The item is inserted if not already in the list.
743static void COM_ExternalLockAddRef(IUnknown * pUnk)
744{
745 dprintf(("OLE32: COM_ExternalLockAddRef"));
746
747 COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk);
748
749 /*
750 * Add an external lock to the object. If it was already externally
751 * locked, just increase the reference count. If it was not.
752 * add the item to the list.
753 */
754 if ( externalLock == EL_NOT_FOUND )
755 COM_ExternalLockInsert(pUnk);
756 else
757 externalLock->uRefCount++;
758
759 /*
760 * Add an internal lock to the object
761 */
762 IUnknown_AddRef(pUnk);
763}
764
765// ----------------------------------------------------------------------
766// COM_ExternalLockRelease
767// ----------------------------------------------------------------------
768// Method that decrements the count for a IUnknown* in the linked
769// list. The item is removed from the list if its count end up at zero or if
770// bRelAll is TRUE.
771static void COM_ExternalLockRelease(IUnknown * pUnk, BOOL bRelAll)
772{
773 dprintf(("OLE32: COM_ExternalLockRelease"));
774
775 COM_ExternalLock * externalLock = COM_ExternalLockFind(pUnk);
776
777 if ( externalLock != EL_NOT_FOUND )
778 {
779 do
780 {
781 externalLock->uRefCount--; /* release external locks */
782 IUnknown_Release(pUnk); /* release local locks as well */
783
784 if ( bRelAll == FALSE )
785 break; /* perform single release */
786
787 } while ( externalLock->uRefCount > 0 );
788
789 if ( externalLock->uRefCount == 0 ) /* get rid of the list entry */
790 COM_ExternalLockDelete(externalLock);
791 }
792}
793
794// ----------------------------------------------------------------------
795// COM_ExternalLockFreeList
796// ----------------------------------------------------------------------
797// Method that frees the content of the list.
798static void COM_ExternalLockFreeList()
799{
800 dprintf(("OLE32: COM_ExternalLockFreeList"));
801
802 COM_ExternalLock *head;
803
804 head = elList.head; /* grab it by the head */
805 while (head != EL_END_OF_LIST)
806 {
807 COM_ExternalLockDelete(head); /* get rid of the head stuff */
808
809 head = elList.head; /* get the new head... */
810 }
811}
812
813// ----------------------------------------------------------------------
814// COM_ExternalLockDump
815// ----------------------------------------------------------------------
816// Method that dump the content of the list.
817void COM_ExternalLockDump()
818{
819 dprintf(("OLE32: COM_ExternalLockDump"));
820
821 COM_ExternalLock *current = elList.head;
822
823 printf("External lock list:");
824
825 while ( current != EL_END_OF_LIST )
826 {
827 dprintf((" %p with %lu references count.\n", current->pUnk, current->uRefCount));
828
829 /* Skip to the next item */
830 current = current->next;
831 }
832}
833
834// ----------------------------------------------------------------------
835// COM_ExternalLockFind
836// ----------------------------------------------------------------------
837// Find a IUnknown* in the linked list
838static COM_ExternalLock * COM_ExternalLockFind(IUnknown *pUnk)
839{
840 dprintf(("OLE32: COM_ExternalLockFind"));
841
842 return COM_ExternalLockLocate(elList.head, pUnk);
843}
844
845// ----------------------------------------------------------------------
846// COM_ExternalLockLocate
847// ----------------------------------------------------------------------
848// Recursivity agent for IUnknownExternalLockList_Find
849static COM_ExternalLock * COM_ExternalLockLocate( COM_ExternalLock * element, IUnknown * pUnk)
850{
851 if ( element == EL_END_OF_LIST )
852 return EL_NOT_FOUND;
853
854 else if ( element->pUnk == pUnk ) /* We found it */
855 return element;
856
857 else /* Not the right guy, keep on looking */
858 return COM_ExternalLockLocate( element->next, pUnk);
859}
860
861// ----------------------------------------------------------------------
862// COM_ExternalLockInsert
863// ----------------------------------------------------------------------
864// Insert a new IUnknown* to the linked list
865static BOOL COM_ExternalLockInsert(IUnknown * pUnk)
866{
867 dprintf(("OLE32: COM_ExternalLockInsert"));
868
869 COM_ExternalLock * newLock = NULL;
870 COM_ExternalLock * previousHead = NULL;
871
872 // Allocate space for the new storage object
873 newLock = (COM_ExternalLock *)HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock));
874
875 if (newLock != NULL)
876 {
877 if ( elList.head == EL_END_OF_LIST )
878 elList.head = newLock; /* The list is empty */
879 else
880 {
881 // insert does it at the head
882 previousHead = elList.head;
883 elList.head = newLock;
884 }
885
886 /*
887 * Set new list item data member
888 */
889 newLock->pUnk = pUnk;
890 newLock->uRefCount = 1;
891 newLock->next = previousHead;
892
893 return TRUE;
894 }
895
896 return FALSE;
897}
898
899// ----------------------------------------------------------------------
900// ExternalLockDelete
901// ----------------------------------------------------------------------
902// Method that removes an item from the linked list.
903static void COM_ExternalLockDelete(COM_ExternalLock * itemList)
904{
905 dprintf(("OLE32: ExternalLockDelete"));
906
907 COM_ExternalLock *current = elList.head;
908
909 if ( current == itemList )
910 {
911 // this section handles the deletion of the first node
912 elList.head = itemList->next;
913 HeapFree( GetProcessHeap(), 0, itemList);
914 }
915 else
916 {
917 do
918 {
919 if ( current->next == itemList ) /* We found the item to free */
920 {
921 current->next = itemList->next; /* readjust the list pointers */
922
923 HeapFree( GetProcessHeap(), 0, itemList);
924 break;
925 }
926
927 /* Skip to the next item */
928 current = current->next;
929
930 } while ( current != EL_END_OF_LIST );
931 }
932}
Note: See TracBrowser for help on using the repository browser.