source: trunk/src/ole32/ole2.cpp@ 1036

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

Added CVS ID lines to all source files

File size: 12.9 KB
Line 
1/* $Id: ole2.cpp,v 1.2 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 * OLE functions.
9 *
10 * 2/9/99
11 *
12 * Copyright 1999 David J. Raison
13 *
14 * Some portions from Wine Implementation (2/9/99)
15 * Copyright 1995 Martin von Loewis
16 * Copyright 1999 Francis Beaudet
17 * Copyright 1999 Noel Borthwick
18 */
19
20#include "ole32.h"
21#include "commctrl.h"
22#include "oString.h"
23#include <assert.h>
24
25// ======================================================================
26// Local Data
27// ======================================================================
28
29/*
30 * This is the lock count on the OLE library. It is controlled by the
31 * OLEInitialize/OLEUninitialize methods.
32 */
33static ULONG OLE_moduleLockCount = 0;
34
35
36// ======================================================================
37// Prototypes.
38// ======================================================================
39static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue);
40
41// These are the prototypes of the utility methods used to manage a shared menu
42extern void OLEMenu_Initialize();
43extern void OLEMenu_UnInitialize();
44
45// These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
46extern void OLEClipbrd_UnInitialize();
47extern void OLEClipbrd_Initialize();
48
49// These are the prototypes of the utility methods used for OLE Drag n Drop
50extern void OLEDD_Initialize();
51extern void OLEDD_UnInitialize();
52
53// ======================================================================
54// Public API's
55// ======================================================================
56
57// ----------------------------------------------------------------------
58// OleBuildVersion()
59// ----------------------------------------------------------------------
60DWORD WIN32API OleBuildVersion(void)
61{
62 dprintf(("OLE32.OleBuildVersion"));
63 return (rmm<<16)+rup;
64}
65
66// ----------------------------------------------------------------------
67// OleInitialize()
68// ----------------------------------------------------------------------
69HRESULT WIN32API OleInitialize(LPVOID reserved)
70{
71 HRESULT hr;
72
73 dprintf(("OLE32: OleInitialize"));
74
75 // The first duty of the OleInitialize is to initialize the COM libraries.
76 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
77 if (FAILED(hr))
78 return hr;
79
80 // Then, it has to initialize the OLE specific modules.
81 // This includes:
82 // Clipboard
83 // Drag and Drop
84 // Object linking and Embedding
85 // In-place activation
86 if (++OLE_moduleLockCount == 1)
87 {
88 dprintf((" First time through - Initializing"));
89
90 // OLE Clipboard
91 OLEClipbrd_Initialize();
92
93 // Drag and Drop
94 OLEDD_Initialize();
95
96 // OLE shared menu
97 OLEMenu_Initialize();
98 }
99
100 return hr;
101}
102
103// ----------------------------------------------------------------------
104// CoGetCurrentProcess()
105// ----------------------------------------------------------------------
106DWORD WIN32API CoGetCurrentProcess()
107{
108 dprintf(("OLE32: CoGetCurrentProcess"));
109 return GetCurrentProcessId();
110}
111
112// ----------------------------------------------------------------------
113// OleUninitialize()
114// ----------------------------------------------------------------------
115void WIN32API OleUninitialize(void)
116{
117 dprintf(("OLE32: OleUninitialize"));
118
119 // If we hit the bottom of the lock stack, free the libraries.
120 if (--OLE_moduleLockCount == 0)
121 {
122 dprintf((" no more references - Terminating"));
123
124 // OLE Clipboard
125 OLEClipbrd_UnInitialize();
126
127 // Drag and Drop
128 OLEDD_UnInitialize();
129
130 // OLE shared menu
131 OLEMenu_UnInitialize();
132 }
133
134 // Then, uninitialize the COM libraries.
135 CoUninitialize();
136}
137
138// ----------------------------------------------------------------------
139// OleRegGetUserType()
140// ----------------------------------------------------------------------
141// This implementation of OleRegGetUserType ignores the dwFormOfType
142// parameter and always returns the full name of the object. This is
143// not too bad since this is the case for many objects because of the
144// way they are registered.
145// ----------------------------------------------------------------------
146HRESULT WIN32API OleRegGetUserType
147 (REFCLSID clsid,
148 DWORD dwFormOfType,
149 LPOLESTR * pszUserType)
150
151{
152 oStringA tCLSID;
153 DWORD dwKeyType;
154 DWORD cbData;
155 HKEY clsidKey;
156 LONG hres;
157
158 dprintf(("OLE32: OleRegGetUserType"));
159
160 *pszUserType = NULL;
161
162 // Build the key name we're looking for
163 tCLSID = "CLSID\\";
164 tCLSID += clsid;
165 tCLSID += "\\";
166
167 // Open the class id Key
168 hres = RegOpenKeyA(HKEY_CLASSES_ROOT, tCLSID, &clsidKey);
169 if (hres != ERROR_SUCCESS)
170 return REGDB_E_CLASSNOTREG;
171
172 // Retrieve the size of the name string.
173 cbData = 0;
174 hres = RegQueryValueExA(clsidKey, "", NULL, &dwKeyType, NULL, &cbData);
175 if (hres != ERROR_SUCCESS)
176 {
177 RegCloseKey(clsidKey);
178 return REGDB_E_READREGDB;
179 }
180
181 // Allocate a buffer for the registry value.
182 *pszUserType = (LPOLESTR)CoTaskMemAlloc(cbData);
183
184 if (*pszUserType == NULL)
185 {
186 RegCloseKey(clsidKey);
187 return E_OUTOFMEMORY;
188 }
189
190 hres = RegQueryValueExA(HKEY_CLASSES_ROOT, "", NULL, &dwKeyType, (LPBYTE)*pszUserType, &cbData);
191 RegCloseKey(clsidKey);
192 if (hres != ERROR_SUCCESS)
193 {
194 CoTaskMemFree(*pszUserType);
195 *pszUserType = NULL;
196 return REGDB_E_READREGDB;
197 }
198
199 return S_OK;
200}
201
202// ----------------------------------------------------------------------
203// OleRegGetMiscStatus()
204// ----------------------------------------------------------------------
205HRESULT WIN32API OleRegGetMiscStatus
206 (REFCLSID clsid,
207 DWORD dwAspect,
208 DWORD * pdwStatus)
209{
210 oStringA tStr;
211 HKEY clsidKey;
212 HKEY miscStatusKey;
213 HKEY aspectKey;
214 LONG result;
215
216 dprintf(("OLE32: OleRegGetMiscStatus"));
217
218 // Initialize the out parameter.
219 *pdwStatus = 0;
220
221 // Build the key name we're looking for
222 tStr = "CLSID\\";
223 tStr += clsid;
224 tStr += "\\";
225 dprintf((" Key : %s", (char *)tStr));
226
227 // Open the class id Key
228 result = RegOpenKeyA(HKEY_CLASSES_ROOT, tStr, &clsidKey);
229
230 if (result != ERROR_SUCCESS)
231 return REGDB_E_CLASSNOTREG;
232
233 // Get the MiscStatus
234 result = RegOpenKeyA(clsidKey, "MiscStatus", &miscStatusKey);
235
236 if (result != ERROR_SUCCESS)
237 {
238 RegCloseKey(clsidKey);
239 return REGDB_E_READREGDB;
240 }
241
242 // Read the default value
243 OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus);
244
245 // Open the key specific to the requested aspect.
246 oStringA tKey(dwAspect);
247 dprintf((" Aspect: %s", (char *)tKey));
248
249 result = RegOpenKeyA(miscStatusKey, tKey, &aspectKey);
250
251 if (result == ERROR_SUCCESS)
252 {
253 OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus);
254 RegCloseKey(aspectKey);
255 }
256
257 // Cleanup
258 RegCloseKey(miscStatusKey);
259 RegCloseKey(clsidKey);
260
261 return S_OK;
262}
263
264// ----------------------------------------------------------------------
265// OleSetContainedObject()
266// ----------------------------------------------------------------------
267HRESULT WIN32API OleSetContainedObject
268 (LPUNKNOWN pUnknown,
269 BOOL fContained)
270{
271 IRunnableObject * runnable = NULL;
272 HRESULT hres;
273
274 dprintf(("OLE32: OleSetContainedObject"));
275
276 hres = IUnknown_QueryInterface(pUnknown, &IID_IRunnableObject, (void**)&runnable);
277
278 if (SUCCEEDED(hres))
279 {
280 hres = IRunnableObject_SetContainedObject(runnable, fContained);
281
282 IRunnableObject_Release(runnable);
283
284 return hres;
285 }
286
287 return S_OK;
288}
289
290// ----------------------------------------------------------------------
291// OleLoad()
292// ----------------------------------------------------------------------
293HRESULT WIN32API OleLoad
294 (LPSTORAGE pStg,
295 REFIID riid,
296 LPOLECLIENTSITE pClientSite,
297 LPVOID * ppvObj)
298{
299 IPersistStorage * persistStorage = NULL;
300 IOleObject * oleObject = NULL;
301 STATSTG storageInfo;
302 HRESULT hres;
303
304 dprintf(("OLE32: OleLoad"));
305
306 // TODO, Conversion ... OleDoAutoConvert
307
308 // Get the class ID for the object.
309 hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME);
310
311 // Now, try and create the handler for the object
312 hres = CoCreateInstance(&storageInfo.clsid,
313 NULL,
314 CLSCTX_INPROC_HANDLER,
315 &IID_IOleObject,
316 (void**)&oleObject);
317
318 // If that fails, as it will most times, load the default OLE handler.
319 if (FAILED(hres))
320 {
321 hres = OleCreateDefaultHandler(&storageInfo.clsid,
322 NULL,
323 &IID_IOleObject,
324 (void**)&oleObject);
325 }
326
327 // If we couldn't find a handler... this is bad. Abort the whole thing.
328 if (FAILED(hres))
329 return hres;
330
331 // Inform the new object of it's client site.
332 hres = IOleObject_SetClientSite(oleObject, pClientSite);
333
334 // Initialize the object with it's IPersistStorage interface.
335 hres = IOleObject_QueryInterface(oleObject, &IID_IPersistStorage, (void**)&persistStorage);
336
337 if (SUCCEEDED(hres))
338 {
339 IPersistStorage_Load(persistStorage, pStg);
340
341 IPersistStorage_Release(persistStorage);
342 persistStorage = NULL;
343 }
344
345 // Return the requested interface to the caller.
346 hres = IOleObject_QueryInterface(oleObject, riid, ppvObj);
347
348 // Cleanup interfaces used internally
349 IOleObject_Release(oleObject);
350
351 return hres;
352}
353
354// ----------------------------------------------------------------------
355// OleSave()
356// ----------------------------------------------------------------------
357HRESULT WIN32API OleSave
358 (LPPERSISTSTORAGE pPS,
359 LPSTORAGE pStg,
360 BOOL fSameAsLoad)
361{
362 HRESULT hres;
363 CLSID objectClass;
364
365 dprintf(("OLE32: OleSave"));
366
367 // First, we transfer the class ID (if available)
368 hres = IPersistStorage_GetClassID(pPS, &objectClass);
369
370 if (SUCCEEDED(hres))
371 WriteClassStg(pStg, &objectClass);
372
373 // Then, we ask the object to save itself to the
374 // storage. If it is successful, we commit the storage.
375 hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad);
376
377 if (SUCCEEDED(hres))
378 IStorage_Commit(pStg, STGC_DEFAULT);
379
380 return hres;
381}
382
383// ----------------------------------------------------------------------
384// ReleaseStgMedium()
385// ----------------------------------------------------------------------
386void WIN32API ReleaseStgMedium(STGMEDIUM * pmedium)
387{
388 switch (pmedium->tymed)
389 {
390 case TYMED_HGLOBAL:
391 {
392 if ( (pmedium->pUnkForRelease == 0) && (pmedium->u.hGlobal != 0) )
393 GlobalFree(pmedium->u.hGlobal);
394
395 pmedium->u.hGlobal = 0;
396 break;
397 }
398 case TYMED_FILE:
399 {
400 if (pmedium->u.lpszFileName != 0)
401 {
402 if (pmedium->pUnkForRelease == 0)
403 DeleteFileW(pmedium->u.lpszFileName);
404
405 CoTaskMemFree(pmedium->u.lpszFileName);
406 }
407
408 pmedium->u.lpszFileName = 0;
409 break;
410 }
411 case TYMED_ISTREAM:
412 {
413 if (pmedium->u.pstm != 0)
414 IStream_Release(pmedium->u.pstm);
415
416 pmedium->u.pstm = 0;
417 break;
418 }
419 case TYMED_ISTORAGE:
420 {
421 if (pmedium->u.pstg != 0)
422 IStorage_Release(pmedium->u.pstg);
423
424 pmedium->u.pstg = 0;
425 break;
426 }
427 case TYMED_GDI:
428 {
429 if ( (pmedium->pUnkForRelease == 0) && (pmedium->u.hGlobal != 0) )
430 DeleteObject(pmedium->u.hGlobal);
431
432 pmedium->u.hGlobal = 0;
433 break;
434 }
435 case TYMED_MFPICT:
436 {
437 if ( (pmedium->pUnkForRelease == 0) && (pmedium->u.hMetaFilePict != 0) )
438 {
439 DeleteMetaFile(pmedium->u.hMetaFilePict);
440 GlobalFree(pmedium->u.hMetaFilePict);
441 }
442
443 pmedium->u.hMetaFilePict = 0;
444 break;
445 }
446 case TYMED_ENHMF:
447 {
448 if ( (pmedium->pUnkForRelease == 0) && (pmedium->u.hEnhMetaFile != 0) )
449 DeleteEnhMetaFile(pmedium->u.hEnhMetaFile);
450
451 pmedium->u.hEnhMetaFile = 0;
452 break;
453 }
454 case TYMED_NULL:
455 // Do nothing
456 break;
457
458 default:
459 break;
460 }
461
462 // After cleaning up, the unknown is released
463 if (pmedium->pUnkForRelease != 0)
464 {
465 IUnknown_Release(pmedium->pUnkForRelease);
466 pmedium->pUnkForRelease = 0;
467 }
468}
469
470// ======================================================================
471// Private functions.
472// ======================================================================
473
474/***
475 * OLEUTL_ReadRegistryDWORDValue
476 *
477 * This method will read the default value of the registry key in
478 * parameter and extract a DWORD value from it. The registry key value
479 * can be in a string key or a DWORD key.
480 *
481 * params:
482 * regKey - Key to read the default value from
483 * pdwValue - Pointer to the location where the DWORD
484 * value is returned. This value is not modified
485 * if the value is not found.
486 */
487
488static void OLEUTL_ReadRegistryDWORDValue(
489 HKEY regKey,
490 DWORD* pdwValue)
491{
492 char buffer[20];
493 DWORD dwKeyType;
494 DWORD cbData = 20;
495 LONG lres;
496
497 lres = RegQueryValueExA(regKey,
498 "",
499 NULL,
500 &dwKeyType,
501 (LPBYTE)buffer,
502 &cbData);
503
504 if (lres == ERROR_SUCCESS)
505 {
506 switch (dwKeyType)
507 {
508 case REG_DWORD:
509 *pdwValue = *(DWORD*)buffer;
510 break;
511 case REG_EXPAND_SZ:
512 case REG_MULTI_SZ:
513 case REG_SZ:
514 *pdwValue = (DWORD)strtoul(buffer, NULL, 10);
515 break;
516 }
517 }
518}
519
Note: See TracBrowser for help on using the repository browser.