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

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

Added CVS ID lines to all source files

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