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
];
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 DeleteFileW(This
->filename
);
101 HeapFree(GetProcessHeap(), 0, This
);
107 static HRESULT WINAPI
OleObject_SetClientSite(IOleObject
*iface
, IOleClientSite
*pClientSite
)
109 struct Package
*This
= impl_from_IOleObject(iface
);
110 FIXME("(%p)->(%p)\n", This
, pClientSite
);
114 static HRESULT WINAPI
OleObject_GetClientSite(IOleObject
*iface
, IOleClientSite
**ppClientSite
)
116 struct Package
*This
= impl_from_IOleObject(iface
);
117 FIXME("(%p)->(%p)\n", This
, ppClientSite
);
121 static HRESULT WINAPI
OleObject_SetHostNames(IOleObject
*iface
, LPCOLESTR szContainerApp
, LPCOLESTR szContainerObj
)
123 struct Package
*This
= impl_from_IOleObject(iface
);
124 FIXME("(%p)->(%s, %s)\n", This
, debugstr_w(szContainerApp
), debugstr_w(szContainerObj
));
128 static HRESULT WINAPI
OleObject_Close(IOleObject
*iface
, DWORD dwSaveOption
)
130 struct Package
*This
= impl_from_IOleObject(iface
);
131 FIXME("(%p)->(0x%x)\n", This
, dwSaveOption
);
135 static HRESULT WINAPI
OleObject_SetMoniker(IOleObject
*iface
, DWORD dwWhichMoniker
, IMoniker
*pmk
)
137 struct Package
*This
= impl_from_IOleObject(iface
);
138 FIXME("(%p)->(%d, %p)\n", This
, dwWhichMoniker
, pmk
);
142 static HRESULT WINAPI
OleObject_GetMoniker(IOleObject
*iface
, DWORD dwAssign
, DWORD dwWhichMoniker
, IMoniker
**ppmk
)
144 struct Package
*This
= impl_from_IOleObject(iface
);
145 FIXME("(%p)->(%d, %d, %p)\n", This
, dwAssign
, dwWhichMoniker
, ppmk
);
149 static HRESULT WINAPI
OleObject_InitFromData(IOleObject
*iface
, IDataObject
*pDataObject
, BOOL fCreation
,
152 struct Package
*This
= impl_from_IOleObject(iface
);
153 FIXME("(%p)->(%p, 0x%x, %d)\n", This
, pDataObject
, fCreation
, dwReserved
);
157 static HRESULT WINAPI
OleObject_GetClipboardData(IOleObject
*iface
, DWORD dwReserved
, IDataObject
**ppDataObject
)
159 struct Package
*This
= impl_from_IOleObject(iface
);
160 FIXME("(%p)->(%d, %p)\n", This
, dwReserved
, ppDataObject
);
164 static HRESULT WINAPI
OleObject_DoVerb(IOleObject
*iface
, LONG iVerb
, LPMSG lpmsg
, IOleClientSite
*pActiveSite
,
165 LONG lindex
, HWND hwndParent
, LPCRECT lprcPosRect
)
167 struct Package
*This
= impl_from_IOleObject(iface
);
168 FIXME("(%p)->(%d)\n", This
, iVerb
);
172 static HRESULT WINAPI
OleObject_EnumVerbs(IOleObject
*iface
, IEnumOLEVERB
**ppEnumOleVerb
)
174 struct Package
*This
= impl_from_IOleObject(iface
);
175 FIXME("(%p)->(%p)\n", This
, ppEnumOleVerb
);
179 static HRESULT WINAPI
OleObject_Update(IOleObject
*iface
)
181 struct Package
*This
= impl_from_IOleObject(iface
);
182 FIXME("(%p)\n", This
);
186 static HRESULT WINAPI
OleObject_IsUpToDate(IOleObject
*iface
)
188 struct Package
*This
= impl_from_IOleObject(iface
);
189 FIXME("(%p)\n", This
);
193 static HRESULT WINAPI
OleObject_GetUserClassID(IOleObject
*iface
, CLSID
*pClsid
)
195 struct Package
*This
= impl_from_IOleObject(iface
);
196 FIXME("(%p)->(%p)\n", This
, pClsid
);
200 static HRESULT WINAPI
OleObject_GetUserType(IOleObject
*iface
, DWORD dwFormOfType
, LPOLESTR
*pszUserType
)
202 struct Package
*This
= impl_from_IOleObject(iface
);
203 FIXME("(%p)->(%d, %p)\n", This
, dwFormOfType
, pszUserType
);
207 static HRESULT WINAPI
OleObject_SetExtent(IOleObject
*iface
, DWORD dwDrawAspect
, SIZEL
*psizel
)
209 struct Package
*This
= impl_from_IOleObject(iface
);
210 FIXME("(%p)->(%d, %p)\n", This
, dwDrawAspect
, psizel
);
214 static HRESULT WINAPI
OleObject_GetExtent(IOleObject
*iface
, DWORD dwDrawAspect
, SIZEL
*psizel
)
216 struct Package
*This
= impl_from_IOleObject(iface
);
217 FIXME("(%p)->(%d, %p)\n", This
, dwDrawAspect
, psizel
);
221 static HRESULT WINAPI
OleObject_Advise(IOleObject
*iface
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
223 struct Package
*This
= impl_from_IOleObject(iface
);
224 FIXME("(%p)->(%p, %p)\n", This
, pAdvSink
, pdwConnection
);
228 static HRESULT WINAPI
OleObject_Unadvise(IOleObject
*iface
, DWORD dwConnection
)
230 struct Package
*This
= impl_from_IOleObject(iface
);
231 FIXME("(%p)->(%d)\n", This
, dwConnection
);
235 static HRESULT WINAPI
OleObject_EnumAdvise(IOleObject
*iface
, IEnumSTATDATA
**ppenumAdvise
)
237 struct Package
*This
= impl_from_IOleObject(iface
);
238 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
242 static HRESULT WINAPI
OleObject_GetMiscStatus(IOleObject
*iface
, DWORD dwAspect
, DWORD
*pdwStatus
)
244 struct Package
*This
= impl_from_IOleObject(iface
);
245 FIXME("(%p)->(%d, %p)\n", This
, dwAspect
, pdwStatus
);
249 static HRESULT WINAPI
OleObject_SetColorScheme(IOleObject
*iface
, LOGPALETTE
*pLogpal
)
251 struct Package
*This
= impl_from_IOleObject(iface
);
252 FIXME("(%p)->(%p)\n", This
, pLogpal
);
256 static const IOleObjectVtbl OleObject_Vtbl
= {
257 OleObject_QueryInterface
,
260 OleObject_SetClientSite
,
261 OleObject_GetClientSite
,
262 OleObject_SetHostNames
,
264 OleObject_SetMoniker
,
265 OleObject_GetMoniker
,
266 OleObject_InitFromData
,
267 OleObject_GetClipboardData
,
271 OleObject_IsUpToDate
,
272 OleObject_GetUserClassID
,
273 OleObject_GetUserType
,
278 OleObject_EnumAdvise
,
279 OleObject_GetMiscStatus
,
280 OleObject_SetColorScheme
283 static HRESULT WINAPI
PersistStorage_QueryInterface(IPersistStorage
* iface
,
284 REFIID riid
, void **ppvObject
)
286 struct Package
*This
= impl_from_IPersistStorage(iface
);
288 return OleObject_QueryInterface(&This
->IOleObject_iface
, riid
, ppvObject
);
291 static ULONG WINAPI
PersistStorage_AddRef(IPersistStorage
* iface
)
293 struct Package
*This
= impl_from_IPersistStorage(iface
);
295 return OleObject_AddRef(&This
->IOleObject_iface
);
298 static ULONG WINAPI
PersistStorage_Release(IPersistStorage
* iface
)
300 struct Package
*This
= impl_from_IPersistStorage(iface
);
302 return OleObject_Release(&This
->IOleObject_iface
);
305 static HRESULT WINAPI
PersistStorage_GetClassID(IPersistStorage
* iface
,
308 struct Package
*This
= impl_from_IPersistStorage(iface
);
309 FIXME("(%p)->(%p)\n", This
, pClassID
);
313 static HRESULT WINAPI
PersistStorage_IsDirty(IPersistStorage
* iface
)
315 struct Package
*This
= impl_from_IPersistStorage(iface
);
316 FIXME("(%p)\n", This
);
320 static HRESULT WINAPI
PersistStorage_InitNew(IPersistStorage
* iface
,
323 struct Package
*This
= impl_from_IPersistStorage(iface
);
324 FIXME("(%p)->(%p)\n", This
, pStg
);
328 static HRESULT
discard_string(struct Package
*This
, IStream
*stream
)
335 hr
= IStream_Read(stream
, &chr
, 1, &nbytes
);
336 if(FAILED(hr
) || !nbytes
){
337 TRACE("Unexpected end of stream or Read failed with %08x\n", hr
);
338 return (hr
== S_OK
|| hr
== S_FALSE
) ? E_FAIL
: hr
;
345 static HRESULT WINAPI
PersistStorage_Load(IPersistStorage
* iface
,
348 struct Package
*This
= impl_from_IPersistStorage(iface
);
350 DWORD payload_size
, len
, stream_filename_len
, filenameA_len
, i
, bytes_read
;
351 ULARGE_INTEGER payload_pos
;
354 HANDLE file
= INVALID_HANDLE_VALUE
;
355 WCHAR filenameW
[MAX_PATH
];
356 char filenameA
[MAX_PATH
];
357 WCHAR
*stream_filename
;
358 WCHAR
*base_end
, extension
[MAX_PATH
];
360 static const WCHAR ole10nativeW
[] = {0x0001,'O','l','e','1','0','N','a','t','i','v','e',0};
362 TRACE("(%p)->(%p)\n", This
, pStg
);
364 hr
= IStorage_OpenStream(pStg
, ole10nativeW
, NULL
,
365 STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0, &stream
);
367 TRACE("OpenStream gave: %08x\n", hr
);
371 /* skip stream size & two unknown bytes */
373 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_SET
, NULL
);
377 /* read and discard label */
378 hr
= discard_string(This
, stream
);
382 /* read and discard filename */
383 hr
= discard_string(This
, stream
);
387 /* skip more unknown data */
389 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, NULL
);
393 /* ASCIIZ filename */
394 hr
= IStream_Read(stream
, &filenameA_len
, 4, NULL
);
398 hr
= IStream_Read(stream
, filenameA
, filenameA_len
, NULL
);
402 /* skip payload for now */
403 hr
= IStream_Read(stream
, &payload_size
, 4, NULL
);
408 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, &payload_pos
);
412 seek
.QuadPart
= payload_size
;
413 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_CUR
, NULL
);
417 /* read WCHAR filename, if present */
418 hr
= IStream_Read(stream
, &len
, 4, &bytes_read
);
419 if(SUCCEEDED(hr
) && bytes_read
== 4 && len
> 0){
420 hr
= IStream_Read(stream
, filenameW
, len
* sizeof(WCHAR
), NULL
);
424 len
= MultiByteToWideChar(CP_ACP
, 0, filenameA
, filenameA_len
,
425 filenameW
, sizeof(filenameW
) / sizeof(*filenameW
));
428 stream_filename
= filenameW
+ len
- 1;
429 while(stream_filename
!= filenameW
&&
430 *stream_filename
!= '\\')
432 if(*stream_filename
== '\\')
434 stream_filename_len
= len
- (stream_filename
- filenameW
);
436 len
= GetTempPathW(sizeof(This
->filename
), This
->filename
);
437 memcpy(This
->filename
+ len
, stream_filename
, stream_filename_len
* sizeof(WCHAR
));
438 This
->filename
[len
+ stream_filename_len
] = 0;
440 /* read & write payload */
441 memcpy(&seek
, &payload_pos
, sizeof(seek
)); /* STREAM_SEEK_SET treats as ULARGE_INTEGER */
442 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_SET
, NULL
);
446 base_end
= PathFindExtensionW(This
->filename
);
447 lstrcpyW(extension
, base_end
);
450 file
= CreateFileW(This
->filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
,
451 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
452 while(file
== INVALID_HANDLE_VALUE
){
453 static const WCHAR fmtW
[] = {' ','(','%','u',')',0};
455 if(GetLastError() != ERROR_FILE_EXISTS
){
456 WARN("CreateFile failed: %u\n", GetLastError());
461 /* file exists, so increment file name and try again */
463 wsprintfW(base_end
, fmtW
, i
);
464 lstrcatW(base_end
, extension
);
466 file
= CreateFileW(This
->filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
,
467 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
469 TRACE("Final filename: %s\n", wine_dbgstr_w(This
->filename
));
476 hr
= IStream_Read(stream
, data
, min(sizeof(data
), payload_size
), &nbytes
);
477 if(FAILED(hr
) || nbytes
== 0){
478 TRACE("Unexpected end of file, or Read failed with %08x\n", hr
);
479 if(hr
== S_OK
|| hr
== S_FALSE
)
484 payload_size
-= nbytes
;
486 WriteFile(file
, data
, nbytes
, &written
, NULL
);
492 if(file
!= INVALID_HANDLE_VALUE
){
495 DeleteFileW(This
->filename
);
497 IStream_Release(stream
);
499 TRACE("Returning: %08x\n", hr
);
503 static HRESULT WINAPI
PersistStorage_Save(IPersistStorage
* iface
,
504 IStorage
*pStgSave
, BOOL fSameAsLoad
)
506 struct Package
*This
= impl_from_IPersistStorage(iface
);
507 FIXME("(%p)->(%p, %u)\n", This
, pStgSave
, fSameAsLoad
);
511 static HRESULT WINAPI
PersistStorage_SaveCompleted(IPersistStorage
* iface
,
514 struct Package
*This
= impl_from_IPersistStorage(iface
);
515 FIXME("(%p)->(%p)\n", This
, pStgNew
);
519 static HRESULT WINAPI
PersistStorage_HandsOffStorage(IPersistStorage
* iface
)
521 struct Package
*This
= impl_from_IPersistStorage(iface
);
522 FIXME("(%p)\n", This
);
526 static IPersistStorageVtbl PersistStorage_Vtbl
= {
527 PersistStorage_QueryInterface
,
528 PersistStorage_AddRef
,
529 PersistStorage_Release
,
530 PersistStorage_GetClassID
,
531 PersistStorage_IsDirty
,
532 PersistStorage_InitNew
,
535 PersistStorage_SaveCompleted
,
536 PersistStorage_HandsOffStorage
539 static HRESULT WINAPI
PackageCF_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **obj
)
541 TRACE("(static)->(%s, %p)\n", debugstr_guid(riid
), obj
);
543 if(IsEqualGUID(&IID_IUnknown
, riid
) ||
544 IsEqualGUID(&IID_IClassFactory
, riid
))
550 IUnknown_AddRef((IUnknown
*)*obj
);
554 FIXME("Unknown interface: %s\n", debugstr_guid(riid
));
555 return E_NOINTERFACE
;
558 static ULONG WINAPI
PackageCF_AddRef(IClassFactory
*iface
)
564 static ULONG WINAPI
PackageCF_Release(IClassFactory
*iface
)
570 static HRESULT WINAPI
PackageCF_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
,
571 REFIID iid
, void **obj
)
573 struct Package
*package
;
575 TRACE("(static)->(%p, %s, %p)\n", outer
, wine_dbgstr_guid(iid
), obj
);
577 package
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*package
));
579 return E_OUTOFMEMORY
;
581 package
->IOleObject_iface
.lpVtbl
= &OleObject_Vtbl
;
582 package
->IPersistStorage_iface
.lpVtbl
= &PersistStorage_Vtbl
;
584 return IOleObject_QueryInterface(&package
->IOleObject_iface
, iid
, obj
);
587 static HRESULT WINAPI
PackageCF_LockServer(IClassFactory
*iface
, BOOL fLock
)
589 TRACE("(%p)->(%x)\n", iface
, fLock
);
593 static const IClassFactoryVtbl PackageCF_Vtbl
= {
594 PackageCF_QueryInterface
,
597 PackageCF_CreateInstance
,
601 static IClassFactory PackageCF
= {
605 HRESULT WINAPI
DllGetClassObject(REFCLSID clsid
, REFIID iid
, void **obj
)
607 TRACE("(%s, %s, %p)\n", wine_dbgstr_guid(clsid
), wine_dbgstr_guid(iid
), obj
);
609 if(IsEqualGUID(clsid
, &CLSID_Package
))
610 return IClassFactory_QueryInterface(&PackageCF
, iid
, obj
);
612 FIXME("Unknown CLSID: %s\n", wine_dbgstr_guid(clsid
));
614 return CLASS_E_CLASSNOTAVAILABLE
;
617 HRESULT WINAPI
DllCanUnloadNow(void)
622 HRESULT WINAPI
DllRegisterServer(void)
624 return __wine_register_resources(g_instance
);
627 HRESULT WINAPI
DllUnregisterServer(void)
629 return __wine_unregister_resources(g_instance
);
632 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, void *reserved
)
634 TRACE("(%p, %u, %p)\n", instance
, reason
, reserved
);
637 case DLL_PROCESS_ATTACH
:
638 g_instance
= instance
;
639 DisableThreadLibraryCalls(instance
);