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

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

Added IUnknown & library handling.
Removed stubs accordingly.

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