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
);
36 static HINSTANCE g_instance
;
39 IOleObject IOleObject_iface
;
40 IPersistStorage IPersistStorage_iface
;
44 WCHAR filename
[MAX_PATH
];
46 IOleClientSite
*clientsite
;
49 static inline struct Package
*impl_from_IOleObject(IOleObject
*iface
)
51 return CONTAINING_RECORD(iface
, struct Package
, IOleObject_iface
);
54 static inline struct Package
*impl_from_IPersistStorage(IPersistStorage
*iface
)
56 return CONTAINING_RECORD(iface
, struct Package
, IPersistStorage_iface
);
59 static HRESULT WINAPI
OleObject_QueryInterface(IOleObject
*iface
, REFIID riid
, void **obj
)
61 struct Package
*This
= impl_from_IOleObject(iface
);
63 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
64 IsEqualGUID(riid
, &IID_IOleObject
)) {
65 TRACE("(%p)->(IID_IOleObject, %p)\n", This
, obj
);
66 *obj
= &This
->IOleObject_iface
;
67 }else if(IsEqualGUID(riid
, &IID_IPersistStorage
)){
68 TRACE("(%p)->(IID_IPersistStorage, %p)\n", This
, obj
);
69 *obj
= &This
->IPersistStorage_iface
;
71 FIXME("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
76 IUnknown_AddRef((IUnknown
*)*obj
);
80 static ULONG WINAPI
OleObject_AddRef(IOleObject
*iface
)
82 struct Package
*This
= impl_from_IOleObject(iface
);
83 LONG ref
= InterlockedIncrement(&This
->ref
);
85 TRACE("(%p) ref=%d\n", This
, ref
);
90 static ULONG WINAPI
OleObject_Release(IOleObject
*iface
)
92 struct Package
*This
= impl_from_IOleObject(iface
);
93 LONG ref
= InterlockedDecrement(&This
->ref
);
95 TRACE("(%p) ref=%d\n", This
, ref
);
99 IOleClientSite_Release(This
->clientsite
);
102 DeleteFileW(This
->filename
);
104 HeapFree(GetProcessHeap(), 0, This
);
110 static HRESULT WINAPI
OleObject_SetClientSite(IOleObject
*iface
, IOleClientSite
*pClientSite
)
112 struct Package
*This
= impl_from_IOleObject(iface
);
114 TRACE("(%p)->(%p)\n", This
, pClientSite
);
117 IOleClientSite_Release(This
->clientsite
);
119 This
->clientsite
= pClientSite
;
121 IOleClientSite_AddRef(pClientSite
);
126 static HRESULT WINAPI
OleObject_GetClientSite(IOleObject
*iface
, IOleClientSite
**ppClientSite
)
128 struct Package
*This
= impl_from_IOleObject(iface
);
129 FIXME("(%p)->(%p)\n", This
, ppClientSite
);
133 static HRESULT WINAPI
OleObject_SetHostNames(IOleObject
*iface
, LPCOLESTR szContainerApp
, LPCOLESTR szContainerObj
)
135 struct Package
*This
= impl_from_IOleObject(iface
);
136 FIXME("(%p)->(%s, %s)\n", This
, debugstr_w(szContainerApp
), debugstr_w(szContainerObj
));
140 static HRESULT WINAPI
OleObject_Close(IOleObject
*iface
, DWORD dwSaveOption
)
142 struct Package
*This
= impl_from_IOleObject(iface
);
144 TRACE("(%p)->(0x%x)\n", This
, dwSaveOption
);
146 if(dwSaveOption
== OLECLOSE_SAVEIFDIRTY
||
147 dwSaveOption
== OLECLOSE_PROMPTSAVE
)
148 WARN("Saving unsupported\n");
153 static HRESULT WINAPI
OleObject_SetMoniker(IOleObject
*iface
, DWORD dwWhichMoniker
, IMoniker
*pmk
)
155 struct Package
*This
= impl_from_IOleObject(iface
);
156 FIXME("(%p)->(%d, %p)\n", This
, dwWhichMoniker
, pmk
);
160 static HRESULT WINAPI
OleObject_GetMoniker(IOleObject
*iface
, DWORD dwAssign
, DWORD dwWhichMoniker
, IMoniker
**ppmk
)
162 struct Package
*This
= impl_from_IOleObject(iface
);
163 FIXME("(%p)->(%d, %d, %p)\n", This
, dwAssign
, dwWhichMoniker
, ppmk
);
167 static HRESULT WINAPI
OleObject_InitFromData(IOleObject
*iface
, IDataObject
*pDataObject
, BOOL fCreation
,
170 struct Package
*This
= impl_from_IOleObject(iface
);
171 FIXME("(%p)->(%p, 0x%x, %d)\n", This
, pDataObject
, fCreation
, dwReserved
);
175 static HRESULT WINAPI
OleObject_GetClipboardData(IOleObject
*iface
, DWORD dwReserved
, IDataObject
**ppDataObject
)
177 struct Package
*This
= impl_from_IOleObject(iface
);
178 FIXME("(%p)->(%d, %p)\n", This
, dwReserved
, ppDataObject
);
182 static HRESULT
do_activate_object(struct Package
*This
, HWND parent
)
184 ShellExecuteW(parent
, L
"open", This
->filename
, NULL
, NULL
, SW_SHOW
);
188 static HRESULT WINAPI
OleObject_DoVerb(IOleObject
*iface
, LONG iVerb
, LPMSG lpmsg
, IOleClientSite
*pActiveSite
,
189 LONG lindex
, HWND hwndParent
, LPCRECT lprcPosRect
)
191 struct Package
*This
= impl_from_IOleObject(iface
);
193 TRACE("(%p)->(%d)\n", This
, iVerb
);
197 return do_activate_object(This
, hwndParent
);
203 static HRESULT WINAPI
OleObject_EnumVerbs(IOleObject
*iface
, IEnumOLEVERB
**ppEnumOleVerb
)
205 struct Package
*This
= impl_from_IOleObject(iface
);
206 FIXME("(%p)->(%p)\n", This
, ppEnumOleVerb
);
210 static HRESULT WINAPI
OleObject_Update(IOleObject
*iface
)
212 struct Package
*This
= impl_from_IOleObject(iface
);
213 FIXME("(%p)\n", This
);
217 static HRESULT WINAPI
OleObject_IsUpToDate(IOleObject
*iface
)
219 struct Package
*This
= impl_from_IOleObject(iface
);
220 FIXME("(%p)\n", This
);
224 static HRESULT WINAPI
OleObject_GetUserClassID(IOleObject
*iface
, CLSID
*pClsid
)
226 struct Package
*This
= impl_from_IOleObject(iface
);
227 FIXME("(%p)->(%p)\n", This
, pClsid
);
231 static HRESULT WINAPI
OleObject_GetUserType(IOleObject
*iface
, DWORD dwFormOfType
, LPOLESTR
*pszUserType
)
233 struct Package
*This
= impl_from_IOleObject(iface
);
234 FIXME("(%p)->(%d, %p)\n", This
, dwFormOfType
, pszUserType
);
238 static HRESULT WINAPI
OleObject_SetExtent(IOleObject
*iface
, DWORD dwDrawAspect
, SIZEL
*psizel
)
240 struct Package
*This
= impl_from_IOleObject(iface
);
241 FIXME("(%p)->(%d, %p)\n", This
, dwDrawAspect
, psizel
);
245 static HRESULT WINAPI
OleObject_GetExtent(IOleObject
*iface
, DWORD dwDrawAspect
, SIZEL
*psizel
)
247 struct Package
*This
= impl_from_IOleObject(iface
);
248 FIXME("(%p)->(%d, %p)\n", This
, dwDrawAspect
, psizel
);
252 static HRESULT WINAPI
OleObject_Advise(IOleObject
*iface
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
254 struct Package
*This
= impl_from_IOleObject(iface
);
255 FIXME("(%p)->(%p, %p)\n", This
, pAdvSink
, pdwConnection
);
259 static HRESULT WINAPI
OleObject_Unadvise(IOleObject
*iface
, DWORD dwConnection
)
261 struct Package
*This
= impl_from_IOleObject(iface
);
262 FIXME("(%p)->(%d)\n", This
, dwConnection
);
266 static HRESULT WINAPI
OleObject_EnumAdvise(IOleObject
*iface
, IEnumSTATDATA
**ppenumAdvise
)
268 struct Package
*This
= impl_from_IOleObject(iface
);
269 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
273 static HRESULT WINAPI
OleObject_GetMiscStatus(IOleObject
*iface
, DWORD dwAspect
, DWORD
*pdwStatus
)
275 struct Package
*This
= impl_from_IOleObject(iface
);
277 TRACE("(%p)->(%d, %p)\n", This
, dwAspect
, pdwStatus
);
282 *pdwStatus
= OLEMISC_ONLYICONIC
;
287 static HRESULT WINAPI
OleObject_SetColorScheme(IOleObject
*iface
, LOGPALETTE
*pLogpal
)
289 struct Package
*This
= impl_from_IOleObject(iface
);
290 FIXME("(%p)->(%p)\n", This
, pLogpal
);
294 static const IOleObjectVtbl OleObject_Vtbl
= {
295 OleObject_QueryInterface
,
298 OleObject_SetClientSite
,
299 OleObject_GetClientSite
,
300 OleObject_SetHostNames
,
302 OleObject_SetMoniker
,
303 OleObject_GetMoniker
,
304 OleObject_InitFromData
,
305 OleObject_GetClipboardData
,
309 OleObject_IsUpToDate
,
310 OleObject_GetUserClassID
,
311 OleObject_GetUserType
,
316 OleObject_EnumAdvise
,
317 OleObject_GetMiscStatus
,
318 OleObject_SetColorScheme
321 static HRESULT WINAPI
PersistStorage_QueryInterface(IPersistStorage
* iface
,
322 REFIID riid
, void **ppvObject
)
324 struct Package
*This
= impl_from_IPersistStorage(iface
);
326 return OleObject_QueryInterface(&This
->IOleObject_iface
, riid
, ppvObject
);
329 static ULONG WINAPI
PersistStorage_AddRef(IPersistStorage
* iface
)
331 struct Package
*This
= impl_from_IPersistStorage(iface
);
333 return OleObject_AddRef(&This
->IOleObject_iface
);
336 static ULONG WINAPI
PersistStorage_Release(IPersistStorage
* iface
)
338 struct Package
*This
= impl_from_IPersistStorage(iface
);
340 return OleObject_Release(&This
->IOleObject_iface
);
343 static HRESULT WINAPI
PersistStorage_GetClassID(IPersistStorage
* iface
,
346 struct Package
*This
= impl_from_IPersistStorage(iface
);
347 FIXME("(%p)->(%p)\n", This
, pClassID
);
351 static HRESULT WINAPI
PersistStorage_IsDirty(IPersistStorage
* iface
)
353 struct Package
*This
= impl_from_IPersistStorage(iface
);
354 FIXME("(%p)\n", This
);
358 static HRESULT WINAPI
PersistStorage_InitNew(IPersistStorage
* iface
,
361 struct Package
*This
= impl_from_IPersistStorage(iface
);
362 FIXME("(%p)->(%p)\n", This
, pStg
);
366 static HRESULT
discard_string(struct Package
*This
, IStream
*stream
)
373 hr
= IStream_Read(stream
, &chr
, 1, &nbytes
);
374 if(FAILED(hr
) || !nbytes
){
375 TRACE("Unexpected end of stream or Read failed with %08x\n", hr
);
376 return (hr
== S_OK
|| hr
== S_FALSE
) ? E_FAIL
: hr
;
383 static HRESULT WINAPI
PersistStorage_Load(IPersistStorage
* iface
,
386 struct Package
*This
= impl_from_IPersistStorage(iface
);
388 DWORD payload_size
, len
, stream_filename_len
, filenameA_len
, i
, bytes_read
;
389 ULARGE_INTEGER payload_pos
;
392 HANDLE file
= INVALID_HANDLE_VALUE
;
393 WCHAR filenameW
[MAX_PATH
];
394 char filenameA
[MAX_PATH
];
395 WCHAR
*stream_filename
;
396 WCHAR
*base_end
, extension
[MAX_PATH
];
398 TRACE("(%p)->(%p)\n", This
, pStg
);
400 hr
= IStorage_OpenStream(pStg
, L
"\1Ole10Native", NULL
,
401 STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0, &stream
);
403 TRACE("OpenStream gave: %08x\n", hr
);
407 /* skip stream size & two unknown bytes */
409 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_SET
, NULL
);
413 /* read and discard label */
414 hr
= discard_string(This
, stream
);
418 /* read and discard filename */
419 hr
= discard_string(This
, stream
);
423 /* skip more unknown data */
425 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, NULL
);
429 /* ASCIIZ filename */
430 hr
= IStream_Read(stream
, &filenameA_len
, 4, NULL
);
434 hr
= IStream_Read(stream
, filenameA
, filenameA_len
, NULL
);
438 /* skip payload for now */
439 hr
= IStream_Read(stream
, &payload_size
, 4, NULL
);
444 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, &payload_pos
);
448 seek
.QuadPart
= payload_size
;
449 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, NULL
);
453 /* read WCHAR filename, if present */
454 hr
= IStream_Read(stream
, &len
, 4, &bytes_read
);
455 if(SUCCEEDED(hr
) && bytes_read
== 4 && len
> 0){
456 hr
= IStream_Read(stream
, filenameW
, len
* sizeof(WCHAR
), NULL
);
460 len
= MultiByteToWideChar(CP_ACP
, 0, filenameA
, filenameA_len
,
461 filenameW
, ARRAY_SIZE(filenameW
));
464 stream_filename
= filenameW
+ len
- 1;
465 while(stream_filename
!= filenameW
&&
466 *stream_filename
!= '\\')
468 if(*stream_filename
== '\\')
470 stream_filename_len
= len
- (stream_filename
- filenameW
);
472 len
= GetTempPathW(ARRAY_SIZE(This
->filename
), This
->filename
);
473 memcpy(This
->filename
+ len
, stream_filename
, stream_filename_len
* sizeof(WCHAR
));
474 This
->filename
[len
+ stream_filename_len
] = 0;
476 /* read & write payload */
477 memcpy(&seek
, &payload_pos
, sizeof(seek
)); /* STREAM_SEEK_SET treats as ULARGE_INTEGER */
478 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_SET
, NULL
);
482 base_end
= PathFindExtensionW(This
->filename
);
483 lstrcpyW(extension
, base_end
);
486 file
= CreateFileW(This
->filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
,
487 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
488 while(file
== INVALID_HANDLE_VALUE
){
489 if(GetLastError() != ERROR_FILE_EXISTS
){
490 WARN("CreateFile failed: %u\n", GetLastError());
495 /* file exists, so increment file name and try again */
497 wsprintfW(base_end
, L
" (%u)", i
);
498 lstrcatW(base_end
, extension
);
500 file
= CreateFileW(This
->filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
,
501 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
503 TRACE("Final filename: %s\n", wine_dbgstr_w(This
->filename
));
510 hr
= IStream_Read(stream
, data
, min(sizeof(data
), payload_size
), &nbytes
);
511 if(FAILED(hr
) || nbytes
== 0){
512 TRACE("Unexpected end of file, or Read failed with %08x\n", hr
);
513 if(hr
== S_OK
|| hr
== S_FALSE
)
518 payload_size
-= nbytes
;
520 WriteFile(file
, data
, nbytes
, &written
, NULL
);
526 if(file
!= INVALID_HANDLE_VALUE
){
529 DeleteFileW(This
->filename
);
531 IStream_Release(stream
);
533 TRACE("Returning: %08x\n", hr
);
537 static HRESULT WINAPI
PersistStorage_Save(IPersistStorage
* iface
,
538 IStorage
*pStgSave
, BOOL fSameAsLoad
)
540 struct Package
*This
= impl_from_IPersistStorage(iface
);
541 FIXME("(%p)->(%p, %u)\n", This
, pStgSave
, fSameAsLoad
);
545 static HRESULT WINAPI
PersistStorage_SaveCompleted(IPersistStorage
* iface
,
548 struct Package
*This
= impl_from_IPersistStorage(iface
);
549 FIXME("(%p)->(%p)\n", This
, pStgNew
);
553 static HRESULT WINAPI
PersistStorage_HandsOffStorage(IPersistStorage
* iface
)
555 struct Package
*This
= impl_from_IPersistStorage(iface
);
556 FIXME("(%p)\n", This
);
560 static IPersistStorageVtbl PersistStorage_Vtbl
= {
561 PersistStorage_QueryInterface
,
562 PersistStorage_AddRef
,
563 PersistStorage_Release
,
564 PersistStorage_GetClassID
,
565 PersistStorage_IsDirty
,
566 PersistStorage_InitNew
,
569 PersistStorage_SaveCompleted
,
570 PersistStorage_HandsOffStorage
573 static HRESULT WINAPI
PackageCF_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **obj
)
575 TRACE("(static)->(%s, %p)\n", debugstr_guid(riid
), obj
);
577 if(IsEqualGUID(&IID_IUnknown
, riid
) ||
578 IsEqualGUID(&IID_IClassFactory
, riid
))
584 IUnknown_AddRef((IUnknown
*)*obj
);
588 FIXME("Unknown interface: %s\n", debugstr_guid(riid
));
589 return E_NOINTERFACE
;
592 static ULONG WINAPI
PackageCF_AddRef(IClassFactory
*iface
)
598 static ULONG WINAPI
PackageCF_Release(IClassFactory
*iface
)
604 static HRESULT WINAPI
PackageCF_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
,
605 REFIID iid
, void **obj
)
607 struct Package
*package
;
609 TRACE("(static)->(%p, %s, %p)\n", outer
, wine_dbgstr_guid(iid
), obj
);
611 package
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*package
));
613 return E_OUTOFMEMORY
;
615 package
->IOleObject_iface
.lpVtbl
= &OleObject_Vtbl
;
616 package
->IPersistStorage_iface
.lpVtbl
= &PersistStorage_Vtbl
;
618 return IOleObject_QueryInterface(&package
->IOleObject_iface
, iid
, obj
);
621 static HRESULT WINAPI
PackageCF_LockServer(IClassFactory
*iface
, BOOL fLock
)
623 TRACE("(%p)->(%x)\n", iface
, fLock
);
627 static const IClassFactoryVtbl PackageCF_Vtbl
= {
628 PackageCF_QueryInterface
,
631 PackageCF_CreateInstance
,
635 static IClassFactory PackageCF
= {
639 HRESULT WINAPI
DllGetClassObject(REFCLSID clsid
, REFIID iid
, void **obj
)
641 TRACE("(%s, %s, %p)\n", wine_dbgstr_guid(clsid
), wine_dbgstr_guid(iid
), obj
);
643 if(IsEqualGUID(clsid
, &CLSID_Package
))
644 return IClassFactory_QueryInterface(&PackageCF
, iid
, obj
);
646 FIXME("Unknown CLSID: %s\n", wine_dbgstr_guid(clsid
));
648 return CLASS_E_CLASSNOTAVAILABLE
;
651 HRESULT WINAPI
DllCanUnloadNow(void)
656 HRESULT WINAPI
DllRegisterServer(void)
658 return __wine_register_resources(g_instance
);
661 HRESULT WINAPI
DllUnregisterServer(void)
663 return __wine_unregister_resources(g_instance
);
666 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, void *reserved
)
668 TRACE("(%p, %u, %p)\n", instance
, reason
, reserved
);
671 case DLL_PROCESS_ATTACH
:
672 g_instance
= instance
;
673 DisableThreadLibraryCalls(instance
);