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
30 #include "wine/debug.h"
32 #include "packager_classes.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(packager
);
37 IOleObject IOleObject_iface
;
38 IPersistStorage IPersistStorage_iface
;
42 WCHAR filename
[MAX_PATH
];
44 IOleClientSite
*clientsite
;
47 static inline struct Package
*impl_from_IOleObject(IOleObject
*iface
)
49 return CONTAINING_RECORD(iface
, struct Package
, IOleObject_iface
);
52 static inline struct Package
*impl_from_IPersistStorage(IPersistStorage
*iface
)
54 return CONTAINING_RECORD(iface
, struct Package
, IPersistStorage_iface
);
57 static HRESULT WINAPI
OleObject_QueryInterface(IOleObject
*iface
, REFIID riid
, void **obj
)
59 struct Package
*This
= impl_from_IOleObject(iface
);
61 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
62 IsEqualGUID(riid
, &IID_IOleObject
)) {
63 TRACE("(%p)->(IID_IOleObject, %p)\n", This
, obj
);
64 *obj
= &This
->IOleObject_iface
;
65 }else if(IsEqualGUID(riid
, &IID_IPersistStorage
)){
66 TRACE("(%p)->(IID_IPersistStorage, %p)\n", This
, obj
);
67 *obj
= &This
->IPersistStorage_iface
;
69 FIXME("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
74 IUnknown_AddRef((IUnknown
*)*obj
);
78 static ULONG WINAPI
OleObject_AddRef(IOleObject
*iface
)
80 struct Package
*This
= impl_from_IOleObject(iface
);
81 LONG ref
= InterlockedIncrement(&This
->ref
);
83 TRACE("(%p) ref=%d\n", This
, ref
);
88 static ULONG WINAPI
OleObject_Release(IOleObject
*iface
)
90 struct Package
*This
= impl_from_IOleObject(iface
);
91 LONG ref
= InterlockedDecrement(&This
->ref
);
93 TRACE("(%p) ref=%d\n", This
, ref
);
97 IOleClientSite_Release(This
->clientsite
);
100 DeleteFileW(This
->filename
);
102 HeapFree(GetProcessHeap(), 0, This
);
108 static HRESULT WINAPI
OleObject_SetClientSite(IOleObject
*iface
, IOleClientSite
*pClientSite
)
110 struct Package
*This
= impl_from_IOleObject(iface
);
112 TRACE("(%p)->(%p)\n", This
, pClientSite
);
115 IOleClientSite_Release(This
->clientsite
);
117 This
->clientsite
= pClientSite
;
119 IOleClientSite_AddRef(pClientSite
);
124 static HRESULT WINAPI
OleObject_GetClientSite(IOleObject
*iface
, IOleClientSite
**ppClientSite
)
126 struct Package
*This
= impl_from_IOleObject(iface
);
127 FIXME("(%p)->(%p)\n", This
, ppClientSite
);
131 static HRESULT WINAPI
OleObject_SetHostNames(IOleObject
*iface
, LPCOLESTR szContainerApp
, LPCOLESTR szContainerObj
)
133 struct Package
*This
= impl_from_IOleObject(iface
);
134 FIXME("(%p)->(%s, %s)\n", This
, debugstr_w(szContainerApp
), debugstr_w(szContainerObj
));
138 static HRESULT WINAPI
OleObject_Close(IOleObject
*iface
, DWORD dwSaveOption
)
140 struct Package
*This
= impl_from_IOleObject(iface
);
142 TRACE("(%p)->(0x%x)\n", This
, dwSaveOption
);
144 if(dwSaveOption
== OLECLOSE_SAVEIFDIRTY
||
145 dwSaveOption
== OLECLOSE_PROMPTSAVE
)
146 WARN("Saving unsupported\n");
151 static HRESULT WINAPI
OleObject_SetMoniker(IOleObject
*iface
, DWORD dwWhichMoniker
, IMoniker
*pmk
)
153 struct Package
*This
= impl_from_IOleObject(iface
);
154 FIXME("(%p)->(%d, %p)\n", This
, dwWhichMoniker
, pmk
);
158 static HRESULT WINAPI
OleObject_GetMoniker(IOleObject
*iface
, DWORD dwAssign
, DWORD dwWhichMoniker
, IMoniker
**ppmk
)
160 struct Package
*This
= impl_from_IOleObject(iface
);
161 FIXME("(%p)->(%d, %d, %p)\n", This
, dwAssign
, dwWhichMoniker
, ppmk
);
165 static HRESULT WINAPI
OleObject_InitFromData(IOleObject
*iface
, IDataObject
*pDataObject
, BOOL fCreation
,
168 struct Package
*This
= impl_from_IOleObject(iface
);
169 FIXME("(%p)->(%p, 0x%x, %d)\n", This
, pDataObject
, fCreation
, dwReserved
);
173 static HRESULT WINAPI
OleObject_GetClipboardData(IOleObject
*iface
, DWORD dwReserved
, IDataObject
**ppDataObject
)
175 struct Package
*This
= impl_from_IOleObject(iface
);
176 FIXME("(%p)->(%d, %p)\n", This
, dwReserved
, ppDataObject
);
180 static HRESULT
do_activate_object(struct Package
*This
, HWND parent
)
182 ShellExecuteW(parent
, L
"open", This
->filename
, NULL
, NULL
, SW_SHOW
);
186 static HRESULT WINAPI
OleObject_DoVerb(IOleObject
*iface
, LONG iVerb
, LPMSG lpmsg
, IOleClientSite
*pActiveSite
,
187 LONG lindex
, HWND hwndParent
, LPCRECT lprcPosRect
)
189 struct Package
*This
= impl_from_IOleObject(iface
);
191 TRACE("(%p)->(%d)\n", This
, iVerb
);
195 return do_activate_object(This
, hwndParent
);
201 static HRESULT WINAPI
OleObject_EnumVerbs(IOleObject
*iface
, IEnumOLEVERB
**ppEnumOleVerb
)
203 struct Package
*This
= impl_from_IOleObject(iface
);
204 FIXME("(%p)->(%p)\n", This
, ppEnumOleVerb
);
208 static HRESULT WINAPI
OleObject_Update(IOleObject
*iface
)
210 struct Package
*This
= impl_from_IOleObject(iface
);
211 FIXME("(%p)\n", This
);
215 static HRESULT WINAPI
OleObject_IsUpToDate(IOleObject
*iface
)
217 struct Package
*This
= impl_from_IOleObject(iface
);
218 FIXME("(%p)\n", This
);
222 static HRESULT WINAPI
OleObject_GetUserClassID(IOleObject
*iface
, CLSID
*pClsid
)
224 struct Package
*This
= impl_from_IOleObject(iface
);
225 FIXME("(%p)->(%p)\n", This
, pClsid
);
229 static HRESULT WINAPI
OleObject_GetUserType(IOleObject
*iface
, DWORD dwFormOfType
, LPOLESTR
*pszUserType
)
231 struct Package
*This
= impl_from_IOleObject(iface
);
232 FIXME("(%p)->(%d, %p)\n", This
, dwFormOfType
, pszUserType
);
236 static HRESULT WINAPI
OleObject_SetExtent(IOleObject
*iface
, DWORD dwDrawAspect
, SIZEL
*psizel
)
238 struct Package
*This
= impl_from_IOleObject(iface
);
239 FIXME("(%p)->(%d, %p)\n", This
, dwDrawAspect
, psizel
);
243 static HRESULT WINAPI
OleObject_GetExtent(IOleObject
*iface
, DWORD dwDrawAspect
, SIZEL
*psizel
)
245 struct Package
*This
= impl_from_IOleObject(iface
);
246 FIXME("(%p)->(%d, %p)\n", This
, dwDrawAspect
, psizel
);
250 static HRESULT WINAPI
OleObject_Advise(IOleObject
*iface
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
252 struct Package
*This
= impl_from_IOleObject(iface
);
253 FIXME("(%p)->(%p, %p)\n", This
, pAdvSink
, pdwConnection
);
257 static HRESULT WINAPI
OleObject_Unadvise(IOleObject
*iface
, DWORD dwConnection
)
259 struct Package
*This
= impl_from_IOleObject(iface
);
260 FIXME("(%p)->(%d)\n", This
, dwConnection
);
264 static HRESULT WINAPI
OleObject_EnumAdvise(IOleObject
*iface
, IEnumSTATDATA
**ppenumAdvise
)
266 struct Package
*This
= impl_from_IOleObject(iface
);
267 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
271 static HRESULT WINAPI
OleObject_GetMiscStatus(IOleObject
*iface
, DWORD dwAspect
, DWORD
*pdwStatus
)
273 struct Package
*This
= impl_from_IOleObject(iface
);
275 TRACE("(%p)->(%d, %p)\n", This
, dwAspect
, pdwStatus
);
280 *pdwStatus
= OLEMISC_ONLYICONIC
;
285 static HRESULT WINAPI
OleObject_SetColorScheme(IOleObject
*iface
, LOGPALETTE
*pLogpal
)
287 struct Package
*This
= impl_from_IOleObject(iface
);
288 FIXME("(%p)->(%p)\n", This
, pLogpal
);
292 static const IOleObjectVtbl OleObject_Vtbl
= {
293 OleObject_QueryInterface
,
296 OleObject_SetClientSite
,
297 OleObject_GetClientSite
,
298 OleObject_SetHostNames
,
300 OleObject_SetMoniker
,
301 OleObject_GetMoniker
,
302 OleObject_InitFromData
,
303 OleObject_GetClipboardData
,
307 OleObject_IsUpToDate
,
308 OleObject_GetUserClassID
,
309 OleObject_GetUserType
,
314 OleObject_EnumAdvise
,
315 OleObject_GetMiscStatus
,
316 OleObject_SetColorScheme
319 static HRESULT WINAPI
PersistStorage_QueryInterface(IPersistStorage
* iface
,
320 REFIID riid
, void **ppvObject
)
322 struct Package
*This
= impl_from_IPersistStorage(iface
);
324 return OleObject_QueryInterface(&This
->IOleObject_iface
, riid
, ppvObject
);
327 static ULONG WINAPI
PersistStorage_AddRef(IPersistStorage
* iface
)
329 struct Package
*This
= impl_from_IPersistStorage(iface
);
331 return OleObject_AddRef(&This
->IOleObject_iface
);
334 static ULONG WINAPI
PersistStorage_Release(IPersistStorage
* iface
)
336 struct Package
*This
= impl_from_IPersistStorage(iface
);
338 return OleObject_Release(&This
->IOleObject_iface
);
341 static HRESULT WINAPI
PersistStorage_GetClassID(IPersistStorage
* iface
,
344 struct Package
*This
= impl_from_IPersistStorage(iface
);
345 FIXME("(%p)->(%p)\n", This
, pClassID
);
349 static HRESULT WINAPI
PersistStorage_IsDirty(IPersistStorage
* iface
)
351 struct Package
*This
= impl_from_IPersistStorage(iface
);
352 FIXME("(%p)\n", This
);
356 static HRESULT WINAPI
PersistStorage_InitNew(IPersistStorage
* iface
,
359 struct Package
*This
= impl_from_IPersistStorage(iface
);
360 FIXME("(%p)->(%p)\n", This
, pStg
);
364 static HRESULT
discard_string(struct Package
*This
, IStream
*stream
)
371 hr
= IStream_Read(stream
, &chr
, 1, &nbytes
);
372 if(FAILED(hr
) || !nbytes
){
373 TRACE("Unexpected end of stream or Read failed with %08x\n", hr
);
374 return (hr
== S_OK
|| hr
== S_FALSE
) ? E_FAIL
: hr
;
381 static HRESULT WINAPI
PersistStorage_Load(IPersistStorage
* iface
,
384 struct Package
*This
= impl_from_IPersistStorage(iface
);
386 DWORD payload_size
, len
, stream_filename_len
, filenameA_len
, i
, bytes_read
;
387 ULARGE_INTEGER payload_pos
;
390 HANDLE file
= INVALID_HANDLE_VALUE
;
391 WCHAR filenameW
[MAX_PATH
];
392 char filenameA
[MAX_PATH
];
393 WCHAR
*stream_filename
;
394 WCHAR
*base_end
, extension
[MAX_PATH
];
396 TRACE("(%p)->(%p)\n", This
, pStg
);
398 hr
= IStorage_OpenStream(pStg
, L
"\1Ole10Native", NULL
,
399 STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0, &stream
);
401 TRACE("OpenStream gave: %08x\n", hr
);
405 /* skip stream size & two unknown bytes */
407 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_SET
, NULL
);
411 /* read and discard label */
412 hr
= discard_string(This
, stream
);
416 /* read and discard filename */
417 hr
= discard_string(This
, stream
);
421 /* skip more unknown data */
423 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, NULL
);
427 /* ASCIIZ filename */
428 hr
= IStream_Read(stream
, &filenameA_len
, 4, NULL
);
432 hr
= IStream_Read(stream
, filenameA
, filenameA_len
, NULL
);
436 /* skip payload for now */
437 hr
= IStream_Read(stream
, &payload_size
, 4, NULL
);
442 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, &payload_pos
);
446 seek
.QuadPart
= payload_size
;
447 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, NULL
);
451 /* read WCHAR filename, if present */
452 hr
= IStream_Read(stream
, &len
, 4, &bytes_read
);
453 if(SUCCEEDED(hr
) && bytes_read
== 4 && len
> 0){
454 hr
= IStream_Read(stream
, filenameW
, len
* sizeof(WCHAR
), NULL
);
458 len
= MultiByteToWideChar(CP_ACP
, 0, filenameA
, filenameA_len
,
459 filenameW
, ARRAY_SIZE(filenameW
));
462 stream_filename
= filenameW
+ len
- 1;
463 while(stream_filename
!= filenameW
&&
464 *stream_filename
!= '\\')
466 if(*stream_filename
== '\\')
468 stream_filename_len
= len
- (stream_filename
- filenameW
);
470 len
= GetTempPathW(ARRAY_SIZE(This
->filename
), This
->filename
);
471 memcpy(This
->filename
+ len
, stream_filename
, stream_filename_len
* sizeof(WCHAR
));
472 This
->filename
[len
+ stream_filename_len
] = 0;
474 /* read & write payload */
475 memcpy(&seek
, &payload_pos
, sizeof(seek
)); /* STREAM_SEEK_SET treats as ULARGE_INTEGER */
476 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_SET
, NULL
);
480 base_end
= PathFindExtensionW(This
->filename
);
481 lstrcpyW(extension
, base_end
);
484 file
= CreateFileW(This
->filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
,
485 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
486 while(file
== INVALID_HANDLE_VALUE
){
487 if(GetLastError() != ERROR_FILE_EXISTS
){
488 WARN("CreateFile failed: %u\n", GetLastError());
493 /* file exists, so increment file name and try again */
495 wsprintfW(base_end
, L
" (%u)", i
);
496 lstrcatW(base_end
, extension
);
498 file
= CreateFileW(This
->filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
,
499 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
501 TRACE("Final filename: %s\n", wine_dbgstr_w(This
->filename
));
508 hr
= IStream_Read(stream
, data
, min(sizeof(data
), payload_size
), &nbytes
);
509 if(FAILED(hr
) || nbytes
== 0){
510 TRACE("Unexpected end of file, or Read failed with %08x\n", hr
);
511 if(hr
== S_OK
|| hr
== S_FALSE
)
516 payload_size
-= nbytes
;
518 WriteFile(file
, data
, nbytes
, &written
, NULL
);
524 if(file
!= INVALID_HANDLE_VALUE
){
527 DeleteFileW(This
->filename
);
529 IStream_Release(stream
);
531 TRACE("Returning: %08x\n", hr
);
535 static HRESULT WINAPI
PersistStorage_Save(IPersistStorage
* iface
,
536 IStorage
*pStgSave
, BOOL fSameAsLoad
)
538 struct Package
*This
= impl_from_IPersistStorage(iface
);
539 FIXME("(%p)->(%p, %u)\n", This
, pStgSave
, fSameAsLoad
);
543 static HRESULT WINAPI
PersistStorage_SaveCompleted(IPersistStorage
* iface
,
546 struct Package
*This
= impl_from_IPersistStorage(iface
);
547 FIXME("(%p)->(%p)\n", This
, pStgNew
);
551 static HRESULT WINAPI
PersistStorage_HandsOffStorage(IPersistStorage
* iface
)
553 struct Package
*This
= impl_from_IPersistStorage(iface
);
554 FIXME("(%p)\n", This
);
558 static IPersistStorageVtbl PersistStorage_Vtbl
= {
559 PersistStorage_QueryInterface
,
560 PersistStorage_AddRef
,
561 PersistStorage_Release
,
562 PersistStorage_GetClassID
,
563 PersistStorage_IsDirty
,
564 PersistStorage_InitNew
,
567 PersistStorage_SaveCompleted
,
568 PersistStorage_HandsOffStorage
571 static HRESULT WINAPI
PackageCF_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **obj
)
573 TRACE("(static)->(%s, %p)\n", debugstr_guid(riid
), obj
);
575 if(IsEqualGUID(&IID_IUnknown
, riid
) ||
576 IsEqualGUID(&IID_IClassFactory
, riid
))
582 IUnknown_AddRef((IUnknown
*)*obj
);
586 FIXME("Unknown interface: %s\n", debugstr_guid(riid
));
587 return E_NOINTERFACE
;
590 static ULONG WINAPI
PackageCF_AddRef(IClassFactory
*iface
)
596 static ULONG WINAPI
PackageCF_Release(IClassFactory
*iface
)
602 static HRESULT WINAPI
PackageCF_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
,
603 REFIID iid
, void **obj
)
605 struct Package
*package
;
607 TRACE("(static)->(%p, %s, %p)\n", outer
, wine_dbgstr_guid(iid
), obj
);
609 package
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*package
));
611 return E_OUTOFMEMORY
;
613 package
->IOleObject_iface
.lpVtbl
= &OleObject_Vtbl
;
614 package
->IPersistStorage_iface
.lpVtbl
= &PersistStorage_Vtbl
;
616 return IOleObject_QueryInterface(&package
->IOleObject_iface
, iid
, obj
);
619 static HRESULT WINAPI
PackageCF_LockServer(IClassFactory
*iface
, BOOL fLock
)
621 TRACE("(%p)->(%x)\n", iface
, fLock
);
625 static const IClassFactoryVtbl PackageCF_Vtbl
= {
626 PackageCF_QueryInterface
,
629 PackageCF_CreateInstance
,
633 static IClassFactory PackageCF
= {
637 HRESULT WINAPI
DllGetClassObject(REFCLSID clsid
, REFIID iid
, void **obj
)
639 TRACE("(%s, %s, %p)\n", wine_dbgstr_guid(clsid
), wine_dbgstr_guid(iid
), obj
);
641 if(IsEqualGUID(clsid
, &CLSID_Package
))
642 return IClassFactory_QueryInterface(&PackageCF
, iid
, obj
);
644 FIXME("Unknown CLSID: %s\n", wine_dbgstr_guid(clsid
));
646 return CLASS_E_CLASSNOTAVAILABLE
;