oleaut32: Use WdtpInterfacePointer_* functions in VARIANT marshalling.
[wine.git] / dlls / packager / packager_main.c
blobc1d194e3684189a91e2570480e5d8859d50b973f
1 /*
2 * Copyright 2014 Andrew Eikum for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
21 #include <stdarg.h>
23 #define COBJMACROS
24 #include "initguid.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "ole2.h"
28 #include "rpcproxy.h"
29 #include "shellapi.h"
30 #include "shlwapi.h"
32 #include "wine/debug.h"
34 #include "packager_classes.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(packager);
38 static HINSTANCE g_instance;
40 struct Package {
41 IOleObject IOleObject_iface;
42 IPersistStorage IPersistStorage_iface;
44 LONG ref;
46 WCHAR filename[MAX_PATH];
48 IOleClientSite *clientsite;
51 static inline struct Package *impl_from_IOleObject(IOleObject *iface)
53 return CONTAINING_RECORD(iface, struct Package, IOleObject_iface);
56 static inline struct Package *impl_from_IPersistStorage(IPersistStorage *iface)
58 return CONTAINING_RECORD(iface, struct Package, IPersistStorage_iface);
61 static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, void **obj)
63 struct Package *This = impl_from_IOleObject(iface);
65 if(IsEqualGUID(riid, &IID_IUnknown) ||
66 IsEqualGUID(riid, &IID_IOleObject)) {
67 TRACE("(%p)->(IID_IOleObject, %p)\n", This, obj);
68 *obj = &This->IOleObject_iface;
69 }else if(IsEqualGUID(riid, &IID_IPersistStorage)){
70 TRACE("(%p)->(IID_IPersistStorage, %p)\n", This, obj);
71 *obj = &This->IPersistStorage_iface;
72 }else {
73 FIXME("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
74 *obj = NULL;
75 return E_NOINTERFACE;
78 IUnknown_AddRef((IUnknown*)*obj);
79 return S_OK;
82 static ULONG WINAPI OleObject_AddRef(IOleObject *iface)
84 struct Package *This = impl_from_IOleObject(iface);
85 LONG ref = InterlockedIncrement(&This->ref);
87 TRACE("(%p) ref=%d\n", This, ref);
89 return ref;
92 static ULONG WINAPI OleObject_Release(IOleObject *iface)
94 struct Package *This = impl_from_IOleObject(iface);
95 LONG ref = InterlockedDecrement(&This->ref);
97 TRACE("(%p) ref=%d\n", This, ref);
99 if(!ref){
100 if(This->clientsite)
101 IOleClientSite_Release(This->clientsite);
103 if(*This->filename)
104 DeleteFileW(This->filename);
106 HeapFree(GetProcessHeap(), 0, This);
109 return ref;
112 static HRESULT WINAPI OleObject_SetClientSite(IOleObject *iface, IOleClientSite *pClientSite)
114 struct Package *This = impl_from_IOleObject(iface);
116 TRACE("(%p)->(%p)\n", This, pClientSite);
118 if(This->clientsite)
119 IOleClientSite_Release(This->clientsite);
121 This->clientsite = pClientSite;
122 if(pClientSite)
123 IOleClientSite_AddRef(pClientSite);
125 return S_OK;
128 static HRESULT WINAPI OleObject_GetClientSite(IOleObject *iface, IOleClientSite **ppClientSite)
130 struct Package *This = impl_from_IOleObject(iface);
131 FIXME("(%p)->(%p)\n", This, ppClientSite);
132 return E_NOTIMPL;
135 static HRESULT WINAPI OleObject_SetHostNames(IOleObject *iface, LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
137 struct Package *This = impl_from_IOleObject(iface);
138 FIXME("(%p)->(%s, %s)\n", This, debugstr_w(szContainerApp), debugstr_w(szContainerObj));
139 return E_NOTIMPL;
142 static HRESULT WINAPI OleObject_Close(IOleObject *iface, DWORD dwSaveOption)
144 struct Package *This = impl_from_IOleObject(iface);
146 TRACE("(%p)->(0x%x)\n", This, dwSaveOption);
148 if(dwSaveOption == OLECLOSE_SAVEIFDIRTY ||
149 dwSaveOption == OLECLOSE_PROMPTSAVE)
150 WARN("Saving unsupported\n");
152 return S_OK;
155 static HRESULT WINAPI OleObject_SetMoniker(IOleObject *iface, DWORD dwWhichMoniker, IMoniker *pmk)
157 struct Package *This = impl_from_IOleObject(iface);
158 FIXME("(%p)->(%d, %p)\n", This, dwWhichMoniker, pmk);
159 return E_NOTIMPL;
162 static HRESULT WINAPI OleObject_GetMoniker(IOleObject *iface, DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk)
164 struct Package *This = impl_from_IOleObject(iface);
165 FIXME("(%p)->(%d, %d, %p)\n", This, dwAssign, dwWhichMoniker, ppmk);
166 return E_NOTIMPL;
169 static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, IDataObject *pDataObject, BOOL fCreation,
170 DWORD dwReserved)
172 struct Package *This = impl_from_IOleObject(iface);
173 FIXME("(%p)->(%p, 0x%x, %d)\n", This, pDataObject, fCreation, dwReserved);
174 return E_NOTIMPL;
177 static HRESULT WINAPI OleObject_GetClipboardData(IOleObject *iface, DWORD dwReserved, IDataObject **ppDataObject)
179 struct Package *This = impl_from_IOleObject(iface);
180 FIXME("(%p)->(%d, %p)\n", This, dwReserved, ppDataObject);
181 return E_NOTIMPL;
184 static HRESULT do_activate_object(struct Package *This, HWND parent)
186 static const WCHAR openW[] = {'o','p','e','n',0};
187 ShellExecuteW(parent, openW, This->filename, NULL, NULL, SW_SHOW);
188 return S_OK;
191 static HRESULT WINAPI OleObject_DoVerb(IOleObject *iface, LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite,
192 LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
194 struct Package *This = impl_from_IOleObject(iface);
196 TRACE("(%p)->(%d)\n", This, iVerb);
198 switch(iVerb){
199 case 0:
200 return do_activate_object(This, hwndParent);
203 return E_INVALIDARG;
206 static HRESULT WINAPI OleObject_EnumVerbs(IOleObject *iface, IEnumOLEVERB **ppEnumOleVerb)
208 struct Package *This = impl_from_IOleObject(iface);
209 FIXME("(%p)->(%p)\n", This, ppEnumOleVerb);
210 return E_NOTIMPL;
213 static HRESULT WINAPI OleObject_Update(IOleObject *iface)
215 struct Package *This = impl_from_IOleObject(iface);
216 FIXME("(%p)\n", This);
217 return E_NOTIMPL;
220 static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface)
222 struct Package *This = impl_from_IOleObject(iface);
223 FIXME("(%p)\n", This);
224 return E_NOTIMPL;
227 static HRESULT WINAPI OleObject_GetUserClassID(IOleObject *iface, CLSID *pClsid)
229 struct Package *This = impl_from_IOleObject(iface);
230 FIXME("(%p)->(%p)\n", This, pClsid);
231 return E_NOTIMPL;
234 static HRESULT WINAPI OleObject_GetUserType(IOleObject *iface, DWORD dwFormOfType, LPOLESTR *pszUserType)
236 struct Package *This = impl_from_IOleObject(iface);
237 FIXME("(%p)->(%d, %p)\n", This, dwFormOfType, pszUserType);
238 return E_NOTIMPL;
241 static HRESULT WINAPI OleObject_SetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
243 struct Package *This = impl_from_IOleObject(iface);
244 FIXME("(%p)->(%d, %p)\n", This, dwDrawAspect, psizel);
245 return E_NOTIMPL;
248 static HRESULT WINAPI OleObject_GetExtent(IOleObject *iface, DWORD dwDrawAspect, SIZEL *psizel)
250 struct Package *This = impl_from_IOleObject(iface);
251 FIXME("(%p)->(%d, %p)\n", This, dwDrawAspect, psizel);
252 return E_NOTIMPL;
255 static HRESULT WINAPI OleObject_Advise(IOleObject *iface, IAdviseSink *pAdvSink, DWORD *pdwConnection)
257 struct Package *This = impl_from_IOleObject(iface);
258 FIXME("(%p)->(%p, %p)\n", This, pAdvSink, pdwConnection);
259 return E_NOTIMPL;
262 static HRESULT WINAPI OleObject_Unadvise(IOleObject *iface, DWORD dwConnection)
264 struct Package *This = impl_from_IOleObject(iface);
265 FIXME("(%p)->(%d)\n", This, dwConnection);
266 return E_NOTIMPL;
269 static HRESULT WINAPI OleObject_EnumAdvise(IOleObject *iface, IEnumSTATDATA **ppenumAdvise)
271 struct Package *This = impl_from_IOleObject(iface);
272 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
273 return E_NOTIMPL;
276 static HRESULT WINAPI OleObject_GetMiscStatus(IOleObject *iface, DWORD dwAspect, DWORD *pdwStatus)
278 struct Package *This = impl_from_IOleObject(iface);
280 TRACE("(%p)->(%d, %p)\n", This, dwAspect, pdwStatus);
282 if(!pdwStatus)
283 return E_INVALIDARG;
285 *pdwStatus = OLEMISC_ONLYICONIC;
287 return S_OK;
290 static HRESULT WINAPI OleObject_SetColorScheme(IOleObject *iface, LOGPALETTE *pLogpal)
292 struct Package *This = impl_from_IOleObject(iface);
293 FIXME("(%p)->(%p)\n", This, pLogpal);
294 return E_NOTIMPL;
297 static const IOleObjectVtbl OleObject_Vtbl = {
298 OleObject_QueryInterface,
299 OleObject_AddRef,
300 OleObject_Release,
301 OleObject_SetClientSite,
302 OleObject_GetClientSite,
303 OleObject_SetHostNames,
304 OleObject_Close,
305 OleObject_SetMoniker,
306 OleObject_GetMoniker,
307 OleObject_InitFromData,
308 OleObject_GetClipboardData,
309 OleObject_DoVerb,
310 OleObject_EnumVerbs,
311 OleObject_Update,
312 OleObject_IsUpToDate,
313 OleObject_GetUserClassID,
314 OleObject_GetUserType,
315 OleObject_SetExtent,
316 OleObject_GetExtent,
317 OleObject_Advise,
318 OleObject_Unadvise,
319 OleObject_EnumAdvise,
320 OleObject_GetMiscStatus,
321 OleObject_SetColorScheme
324 static HRESULT WINAPI PersistStorage_QueryInterface(IPersistStorage* iface,
325 REFIID riid, void **ppvObject)
327 struct Package *This = impl_from_IPersistStorage(iface);
329 return OleObject_QueryInterface(&This->IOleObject_iface, riid, ppvObject);
332 static ULONG WINAPI PersistStorage_AddRef(IPersistStorage* iface)
334 struct Package *This = impl_from_IPersistStorage(iface);
336 return OleObject_AddRef(&This->IOleObject_iface);
339 static ULONG WINAPI PersistStorage_Release(IPersistStorage* iface)
341 struct Package *This = impl_from_IPersistStorage(iface);
343 return OleObject_Release(&This->IOleObject_iface);
346 static HRESULT WINAPI PersistStorage_GetClassID(IPersistStorage* iface,
347 CLSID *pClassID)
349 struct Package *This = impl_from_IPersistStorage(iface);
350 FIXME("(%p)->(%p)\n", This, pClassID);
351 return E_NOTIMPL;
354 static HRESULT WINAPI PersistStorage_IsDirty(IPersistStorage* iface)
356 struct Package *This = impl_from_IPersistStorage(iface);
357 FIXME("(%p)\n", This);
358 return E_NOTIMPL;
361 static HRESULT WINAPI PersistStorage_InitNew(IPersistStorage* iface,
362 IStorage *pStg)
364 struct Package *This = impl_from_IPersistStorage(iface);
365 FIXME("(%p)->(%p)\n", This, pStg);
366 return E_NOTIMPL;
369 static HRESULT discard_string(struct Package *This, IStream *stream)
371 ULONG nbytes;
372 HRESULT hr;
373 char chr = 0;
376 hr = IStream_Read(stream, &chr, 1, &nbytes);
377 if(FAILED(hr) || !nbytes){
378 TRACE("Unexpected end of stream or Read failed with %08x\n", hr);
379 return (hr == S_OK || hr == S_FALSE) ? E_FAIL : hr;
381 }while(chr);
383 return S_OK;
386 static HRESULT WINAPI PersistStorage_Load(IPersistStorage* iface,
387 IStorage *pStg)
389 struct Package *This = impl_from_IPersistStorage(iface);
390 IStream *stream;
391 DWORD payload_size, len, stream_filename_len, filenameA_len, i, bytes_read;
392 ULARGE_INTEGER payload_pos;
393 LARGE_INTEGER seek;
394 HRESULT hr;
395 HANDLE file = INVALID_HANDLE_VALUE;
396 WCHAR filenameW[MAX_PATH];
397 char filenameA[MAX_PATH];
398 WCHAR *stream_filename;
399 WCHAR *base_end, extension[MAX_PATH];
401 static const WCHAR ole10nativeW[] = {0x0001,'O','l','e','1','0','N','a','t','i','v','e',0};
403 TRACE("(%p)->(%p)\n", This, pStg);
405 hr = IStorage_OpenStream(pStg, ole10nativeW, NULL,
406 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream);
407 if(FAILED(hr)){
408 TRACE("OpenStream gave: %08x\n", hr);
409 return hr;
412 /* skip stream size & two unknown bytes */
413 seek.QuadPart = 6;
414 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
415 if(FAILED(hr))
416 goto exit;
418 /* read and discard label */
419 hr = discard_string(This, stream);
420 if(FAILED(hr))
421 goto exit;
423 /* read and discard filename */
424 hr = discard_string(This, stream);
425 if(FAILED(hr))
426 goto exit;
428 /* skip more unknown data */
429 seek.QuadPart = 4;
430 hr = IStream_Seek(stream, seek, STREAM_SEEK_CUR, NULL);
431 if(FAILED(hr))
432 goto exit;
434 /* ASCIIZ filename */
435 hr = IStream_Read(stream, &filenameA_len, 4, NULL);
436 if(FAILED(hr))
437 goto exit;
439 hr = IStream_Read(stream, filenameA, filenameA_len, NULL);
440 if(FAILED(hr))
441 goto exit;
443 /* skip payload for now */
444 hr = IStream_Read(stream, &payload_size, 4, NULL);
445 if(FAILED(hr))
446 goto exit;
448 seek.QuadPart = 0;
449 hr = IStream_Seek(stream, seek, STREAM_SEEK_CUR, &payload_pos);
450 if(FAILED(hr))
451 goto exit;
453 seek.QuadPart = payload_size;
454 hr = IStream_Seek(stream, seek, STREAM_SEEK_CUR, NULL);
455 if(FAILED(hr))
456 goto exit;
458 /* read WCHAR filename, if present */
459 hr = IStream_Read(stream, &len, 4, &bytes_read);
460 if(SUCCEEDED(hr) && bytes_read == 4 && len > 0){
461 hr = IStream_Read(stream, filenameW, len * sizeof(WCHAR), NULL);
462 if(FAILED(hr))
463 goto exit;
464 }else{
465 len = MultiByteToWideChar(CP_ACP, 0, filenameA, filenameA_len,
466 filenameW, sizeof(filenameW) / sizeof(*filenameW));
469 stream_filename = filenameW + len - 1;
470 while(stream_filename != filenameW &&
471 *stream_filename != '\\')
472 --stream_filename;
473 if(*stream_filename == '\\')
474 ++stream_filename;
475 stream_filename_len = len - (stream_filename - filenameW);
477 len = GetTempPathW(sizeof(This->filename)/sizeof(WCHAR), This->filename);
478 memcpy(This->filename + len, stream_filename, stream_filename_len * sizeof(WCHAR));
479 This->filename[len + stream_filename_len] = 0;
481 /* read & write payload */
482 memcpy(&seek, &payload_pos, sizeof(seek)); /* STREAM_SEEK_SET treats as ULARGE_INTEGER */
483 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
484 if(FAILED(hr))
485 goto exit;
487 base_end = PathFindExtensionW(This->filename);
488 lstrcpyW(extension, base_end);
489 i = 1;
491 file = CreateFileW(This->filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
492 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
493 while(file == INVALID_HANDLE_VALUE){
494 static const WCHAR fmtW[] = {' ','(','%','u',')',0};
496 if(GetLastError() != ERROR_FILE_EXISTS){
497 WARN("CreateFile failed: %u\n", GetLastError());
498 hr = E_FAIL;
499 goto exit;
502 /* file exists, so increment file name and try again */
503 ++i;
504 wsprintfW(base_end, fmtW, i);
505 lstrcatW(base_end, extension);
507 file = CreateFileW(This->filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
508 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
510 TRACE("Final filename: %s\n", wine_dbgstr_w(This->filename));
512 while(payload_size){
513 ULONG nbytes;
514 BYTE data[4096];
515 DWORD written;
517 hr = IStream_Read(stream, data, min(sizeof(data), payload_size), &nbytes);
518 if(FAILED(hr) || nbytes == 0){
519 TRACE("Unexpected end of file, or Read failed with %08x\n", hr);
520 if(hr == S_OK || hr == S_FALSE)
521 hr = E_FAIL;
522 goto exit;
525 payload_size -= nbytes;
527 WriteFile(file, data, nbytes, &written, NULL);
530 hr = S_OK;
532 exit:
533 if(file != INVALID_HANDLE_VALUE){
534 CloseHandle(file);
535 if(FAILED(hr))
536 DeleteFileW(This->filename);
538 IStream_Release(stream);
540 TRACE("Returning: %08x\n", hr);
541 return hr;
544 static HRESULT WINAPI PersistStorage_Save(IPersistStorage* iface,
545 IStorage *pStgSave, BOOL fSameAsLoad)
547 struct Package *This = impl_from_IPersistStorage(iface);
548 FIXME("(%p)->(%p, %u)\n", This, pStgSave, fSameAsLoad);
549 return E_NOTIMPL;
552 static HRESULT WINAPI PersistStorage_SaveCompleted(IPersistStorage* iface,
553 IStorage *pStgNew)
555 struct Package *This = impl_from_IPersistStorage(iface);
556 FIXME("(%p)->(%p)\n", This, pStgNew);
557 return E_NOTIMPL;
560 static HRESULT WINAPI PersistStorage_HandsOffStorage(IPersistStorage* iface)
562 struct Package *This = impl_from_IPersistStorage(iface);
563 FIXME("(%p)\n", This);
564 return E_NOTIMPL;
567 static IPersistStorageVtbl PersistStorage_Vtbl = {
568 PersistStorage_QueryInterface,
569 PersistStorage_AddRef,
570 PersistStorage_Release,
571 PersistStorage_GetClassID,
572 PersistStorage_IsDirty,
573 PersistStorage_InitNew,
574 PersistStorage_Load,
575 PersistStorage_Save,
576 PersistStorage_SaveCompleted,
577 PersistStorage_HandsOffStorage
580 static HRESULT WINAPI PackageCF_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
582 TRACE("(static)->(%s, %p)\n", debugstr_guid(riid), obj);
584 if(IsEqualGUID(&IID_IUnknown, riid) ||
585 IsEqualGUID(&IID_IClassFactory, riid))
586 *obj = iface;
587 else
588 *obj = NULL;
590 if(*obj){
591 IUnknown_AddRef((IUnknown*)*obj);
592 return S_OK;
595 FIXME("Unknown interface: %s\n", debugstr_guid(riid));
596 return E_NOINTERFACE;
599 static ULONG WINAPI PackageCF_AddRef(IClassFactory *iface)
601 TRACE("(static)\n");
602 return 2;
605 static ULONG WINAPI PackageCF_Release(IClassFactory *iface)
607 TRACE("(static)\n");
608 return 1;
611 static HRESULT WINAPI PackageCF_CreateInstance(IClassFactory *iface, IUnknown *outer,
612 REFIID iid, void **obj)
614 struct Package *package;
616 TRACE("(static)->(%p, %s, %p)\n", outer, wine_dbgstr_guid(iid), obj);
618 package = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*package));
619 if(!package)
620 return E_OUTOFMEMORY;
622 package->IOleObject_iface.lpVtbl = &OleObject_Vtbl;
623 package->IPersistStorage_iface.lpVtbl = &PersistStorage_Vtbl;
625 return IOleObject_QueryInterface(&package->IOleObject_iface, iid, obj);
628 static HRESULT WINAPI PackageCF_LockServer(IClassFactory *iface, BOOL fLock)
630 TRACE("(%p)->(%x)\n", iface, fLock);
631 return S_OK;
634 static const IClassFactoryVtbl PackageCF_Vtbl = {
635 PackageCF_QueryInterface,
636 PackageCF_AddRef,
637 PackageCF_Release,
638 PackageCF_CreateInstance,
639 PackageCF_LockServer
642 static IClassFactory PackageCF = {
643 &PackageCF_Vtbl
646 HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **obj)
648 TRACE("(%s, %s, %p)\n", wine_dbgstr_guid(clsid), wine_dbgstr_guid(iid), obj);
650 if(IsEqualGUID(clsid, &CLSID_Package))
651 return IClassFactory_QueryInterface(&PackageCF, iid, obj);
653 FIXME("Unknown CLSID: %s\n", wine_dbgstr_guid(clsid));
655 return CLASS_E_CLASSNOTAVAILABLE;
658 HRESULT WINAPI DllCanUnloadNow(void)
660 return S_OK;
663 HRESULT WINAPI DllRegisterServer(void)
665 return __wine_register_resources(g_instance);
668 HRESULT WINAPI DllUnregisterServer(void)
670 return __wine_unregister_resources(g_instance);
673 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
675 TRACE("(%p, %u, %p)\n", instance, reason, reserved);
677 switch(reason){
678 case DLL_PROCESS_ATTACH:
679 g_instance = instance;
680 DisableThreadLibraryCalls(instance);
681 break;
684 return TRUE;