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

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

Initial port of OLE2.
Added regsvr32

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