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
32 #include "wine/debug.h"
34 #include "packager_classes.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(packager
);
38 static HINSTANCE g_instance
;
41 IOleObject IOleObject_iface
;
42 IPersistStorage IPersistStorage_iface
;
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
;
73 FIXME("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
78 IUnknown_AddRef((IUnknown
*)*obj
);
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
);
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
);
101 IOleClientSite_Release(This
->clientsite
);
104 DeleteFileW(This
->filename
);
106 HeapFree(GetProcessHeap(), 0, This
);
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
);
119 IOleClientSite_Release(This
->clientsite
);
121 This
->clientsite
= pClientSite
;
123 IOleClientSite_AddRef(pClientSite
);
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
);
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
));
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");
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
);
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
);
169 static HRESULT WINAPI
OleObject_InitFromData(IOleObject
*iface
, IDataObject
*pDataObject
, BOOL fCreation
,
172 struct Package
*This
= impl_from_IOleObject(iface
);
173 FIXME("(%p)->(%p, 0x%x, %d)\n", This
, pDataObject
, fCreation
, dwReserved
);
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
);
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
);
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
);
200 return do_activate_object(This
, hwndParent
);
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
);
213 static HRESULT WINAPI
OleObject_Update(IOleObject
*iface
)
215 struct Package
*This
= impl_from_IOleObject(iface
);
216 FIXME("(%p)\n", This
);
220 static HRESULT WINAPI
OleObject_IsUpToDate(IOleObject
*iface
)
222 struct Package
*This
= impl_from_IOleObject(iface
);
223 FIXME("(%p)\n", This
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
285 *pdwStatus
= OLEMISC_ONLYICONIC
;
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
);
297 static const IOleObjectVtbl OleObject_Vtbl
= {
298 OleObject_QueryInterface
,
301 OleObject_SetClientSite
,
302 OleObject_GetClientSite
,
303 OleObject_SetHostNames
,
305 OleObject_SetMoniker
,
306 OleObject_GetMoniker
,
307 OleObject_InitFromData
,
308 OleObject_GetClipboardData
,
312 OleObject_IsUpToDate
,
313 OleObject_GetUserClassID
,
314 OleObject_GetUserType
,
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
,
349 struct Package
*This
= impl_from_IPersistStorage(iface
);
350 FIXME("(%p)->(%p)\n", This
, pClassID
);
354 static HRESULT WINAPI
PersistStorage_IsDirty(IPersistStorage
* iface
)
356 struct Package
*This
= impl_from_IPersistStorage(iface
);
357 FIXME("(%p)\n", This
);
361 static HRESULT WINAPI
PersistStorage_InitNew(IPersistStorage
* iface
,
364 struct Package
*This
= impl_from_IPersistStorage(iface
);
365 FIXME("(%p)->(%p)\n", This
, pStg
);
369 static HRESULT
discard_string(struct Package
*This
, IStream
*stream
)
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
;
386 static HRESULT WINAPI
PersistStorage_Load(IPersistStorage
* iface
,
389 struct Package
*This
= impl_from_IPersistStorage(iface
);
391 DWORD payload_size
, len
, stream_filename_len
, filenameA_len
, i
, bytes_read
;
392 ULARGE_INTEGER payload_pos
;
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
);
408 TRACE("OpenStream gave: %08x\n", hr
);
412 /* skip stream size & two unknown bytes */
414 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_SET
, NULL
);
418 /* read and discard label */
419 hr
= discard_string(This
, stream
);
423 /* read and discard filename */
424 hr
= discard_string(This
, stream
);
428 /* skip more unknown data */
430 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, NULL
);
434 /* ASCIIZ filename */
435 hr
= IStream_Read(stream
, &filenameA_len
, 4, NULL
);
439 hr
= IStream_Read(stream
, filenameA
, filenameA_len
, NULL
);
443 /* skip payload for now */
444 hr
= IStream_Read(stream
, &payload_size
, 4, NULL
);
449 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, &payload_pos
);
453 seek
.QuadPart
= payload_size
;
454 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, NULL
);
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
);
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
!= '\\')
473 if(*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
);
487 base_end
= PathFindExtensionW(This
->filename
);
488 lstrcpyW(extension
, base_end
);
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());
502 /* file exists, so increment file name and try again */
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
));
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
)
525 payload_size
-= nbytes
;
527 WriteFile(file
, data
, nbytes
, &written
, NULL
);
533 if(file
!= INVALID_HANDLE_VALUE
){
536 DeleteFileW(This
->filename
);
538 IStream_Release(stream
);
540 TRACE("Returning: %08x\n", 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
);
552 static HRESULT WINAPI
PersistStorage_SaveCompleted(IPersistStorage
* iface
,
555 struct Package
*This
= impl_from_IPersistStorage(iface
);
556 FIXME("(%p)->(%p)\n", This
, pStgNew
);
560 static HRESULT WINAPI
PersistStorage_HandsOffStorage(IPersistStorage
* iface
)
562 struct Package
*This
= impl_from_IPersistStorage(iface
);
563 FIXME("(%p)\n", This
);
567 static IPersistStorageVtbl PersistStorage_Vtbl
= {
568 PersistStorage_QueryInterface
,
569 PersistStorage_AddRef
,
570 PersistStorage_Release
,
571 PersistStorage_GetClassID
,
572 PersistStorage_IsDirty
,
573 PersistStorage_InitNew
,
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
))
591 IUnknown_AddRef((IUnknown
*)*obj
);
595 FIXME("Unknown interface: %s\n", debugstr_guid(riid
));
596 return E_NOINTERFACE
;
599 static ULONG WINAPI
PackageCF_AddRef(IClassFactory
*iface
)
605 static ULONG WINAPI
PackageCF_Release(IClassFactory
*iface
)
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
));
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
);
634 static const IClassFactoryVtbl PackageCF_Vtbl
= {
635 PackageCF_QueryInterface
,
638 PackageCF_CreateInstance
,
642 static IClassFactory PackageCF
= {
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)
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
);
678 case DLL_PROCESS_ATTACH
:
679 g_instance
= instance
;
680 DisableThreadLibraryCalls(instance
);