source: trunk/src/ole32/new/ole32.cpp@ 3456

Last change on this file since 3456 was 3456, checked in by davidr, 25 years ago

OLE32/NEW: Work-in-progress on adding apartment handling

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