packager: Add loading support for Ole10Native storage objects.
[wine/wine-gecko.git] / dlls / packager / packager_main.c
blob47353834c6bd605eca301d2acf19483bb0fa07d8
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];
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;
70 }else {
71 FIXME("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
72 *obj = NULL;
73 return E_NOINTERFACE;
76 IUnknown_AddRef((IUnknown*)*obj);
77 return S_OK;
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);
87 return 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);
97 if(!ref){
98 if(*This->filename)
99 DeleteFileW(This->filename);
101 HeapFree(GetProcessHeap(), 0, This);
104 return ref;
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);
111 return E_NOTIMPL;
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);
118 return E_NOTIMPL;
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));
125 return E_NOTIMPL;
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);
132 return E_NOTIMPL;
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);
139 return E_NOTIMPL;
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);
146 return E_NOTIMPL;
149 static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, IDataObject *pDataObject, BOOL fCreation,
150 DWORD dwReserved)
152 struct Package *This = impl_from_IOleObject(iface);
153 FIXME("(%p)->(%p, 0x%x, %d)\n", This, pDataObject, fCreation, dwReserved);
154 return E_NOTIMPL;
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);
161 return E_NOTIMPL;
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);
169 return E_NOTIMPL;
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);
176 return E_NOTIMPL;
179 static HRESULT WINAPI OleObject_Update(IOleObject *iface)
181 struct Package *This = impl_from_IOleObject(iface);
182 FIXME("(%p)\n", This);
183 return E_NOTIMPL;
186 static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface)
188 struct Package *This = impl_from_IOleObject(iface);
189 FIXME("(%p)\n", This);
190 return E_NOTIMPL;
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);
197 return E_NOTIMPL;
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);
204 return E_NOTIMPL;
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);
211 return E_NOTIMPL;
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);
218 return E_NOTIMPL;
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);
225 return E_NOTIMPL;
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);
232 return E_NOTIMPL;
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);
239 return E_NOTIMPL;
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);
246 return E_NOTIMPL;
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);
253 return E_NOTIMPL;
256 static const IOleObjectVtbl OleObject_Vtbl = {
257 OleObject_QueryInterface,
258 OleObject_AddRef,
259 OleObject_Release,
260 OleObject_SetClientSite,
261 OleObject_GetClientSite,
262 OleObject_SetHostNames,
263 OleObject_Close,
264 OleObject_SetMoniker,
265 OleObject_GetMoniker,
266 OleObject_InitFromData,
267 OleObject_GetClipboardData,
268 OleObject_DoVerb,
269 OleObject_EnumVerbs,
270 OleObject_Update,
271 OleObject_IsUpToDate,
272 OleObject_GetUserClassID,
273 OleObject_GetUserType,
274 OleObject_SetExtent,
275 OleObject_GetExtent,
276 OleObject_Advise,
277 OleObject_Unadvise,
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,
306 CLSID *pClassID)
308 struct Package *This = impl_from_IPersistStorage(iface);
309 FIXME("(%p)->(%p)\n", This, pClassID);
310 return E_NOTIMPL;
313 static HRESULT WINAPI PersistStorage_IsDirty(IPersistStorage* iface)
315 struct Package *This = impl_from_IPersistStorage(iface);
316 FIXME("(%p)\n", This);
317 return E_NOTIMPL;
320 static HRESULT WINAPI PersistStorage_InitNew(IPersistStorage* iface,
321 IStorage *pStg)
323 struct Package *This = impl_from_IPersistStorage(iface);
324 FIXME("(%p)->(%p)\n", This, pStg);
325 return E_NOTIMPL;
328 static HRESULT discard_string(struct Package *This, IStream *stream)
330 ULONG nbytes;
331 HRESULT hr;
332 char chr = 0;
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;
340 }while(chr);
342 return S_OK;
345 static HRESULT WINAPI PersistStorage_Load(IPersistStorage* iface,
346 IStorage *pStg)
348 struct Package *This = impl_from_IPersistStorage(iface);
349 IStream *stream;
350 DWORD payload_size, len, stream_filename_len, filenameA_len, i, bytes_read;
351 ULARGE_INTEGER payload_pos;
352 LARGE_INTEGER seek;
353 HRESULT hr;
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);
366 if(FAILED(hr)){
367 TRACE("OpenStream gave: %08x\n", hr);
368 return hr;
371 /* skip stream size & two unknown bytes */
372 seek.QuadPart = 6;
373 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
374 if(FAILED(hr))
375 goto exit;
377 /* read and discard label */
378 hr = discard_string(This, stream);
379 if(FAILED(hr))
380 goto exit;
382 /* read and discard filename */
383 hr = discard_string(This, stream);
384 if(FAILED(hr))
385 goto exit;
387 /* skip more unknown data */
388 seek.QuadPart = 4;
389 hr = IStream_Seek(stream, seek, STREAM_SEEK_CUR, NULL);
390 if(FAILED(hr))
391 goto exit;
393 /* ASCIIZ filename */
394 hr = IStream_Read(stream, &filenameA_len, 4, NULL);
395 if(FAILED(hr))
396 goto exit;
398 hr = IStream_Read(stream, filenameA, filenameA_len, NULL);
399 if(FAILED(hr))
400 goto exit;
402 /* skip payload for now */
403 hr = IStream_Read(stream, &payload_size, 4, NULL);
404 if(FAILED(hr))
405 goto exit;
407 seek.QuadPart = 0;
408 hr = IStream_Seek(stream, seek, STREAM_SEEK_CUR, &payload_pos);
409 if(FAILED(hr))
410 goto exit;
412 seek.QuadPart = payload_size;
413 hr = IStream_Seek(stream, seek, STREAM_SEEK_CUR, NULL);
414 if(FAILED(hr))
415 goto exit;
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);
421 if(FAILED(hr))
422 goto exit;
423 }else{
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 != '\\')
431 --stream_filename;
432 if(*stream_filename == '\\')
433 ++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);
443 if(FAILED(hr))
444 goto exit;
446 base_end = PathFindExtensionW(This->filename);
447 lstrcpyW(extension, base_end);
448 i = 1;
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());
457 hr = E_FAIL;
458 goto exit;
461 /* file exists, so increment file name and try again */
462 ++i;
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));
471 while(payload_size){
472 ULONG nbytes;
473 BYTE data[4096];
474 DWORD written;
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)
480 hr = E_FAIL;
481 goto exit;
484 payload_size -= nbytes;
486 WriteFile(file, data, nbytes, &written, NULL);
489 hr = S_OK;
491 exit:
492 if(file != INVALID_HANDLE_VALUE){
493 CloseHandle(file);
494 if(FAILED(hr))
495 DeleteFileW(This->filename);
497 IStream_Release(stream);
499 TRACE("Returning: %08x\n", hr);
500 return 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);
508 return E_NOTIMPL;
511 static HRESULT WINAPI PersistStorage_SaveCompleted(IPersistStorage* iface,
512 IStorage *pStgNew)
514 struct Package *This = impl_from_IPersistStorage(iface);
515 FIXME("(%p)->(%p)\n", This, pStgNew);
516 return E_NOTIMPL;
519 static HRESULT WINAPI PersistStorage_HandsOffStorage(IPersistStorage* iface)
521 struct Package *This = impl_from_IPersistStorage(iface);
522 FIXME("(%p)\n", This);
523 return E_NOTIMPL;
526 static IPersistStorageVtbl PersistStorage_Vtbl = {
527 PersistStorage_QueryInterface,
528 PersistStorage_AddRef,
529 PersistStorage_Release,
530 PersistStorage_GetClassID,
531 PersistStorage_IsDirty,
532 PersistStorage_InitNew,
533 PersistStorage_Load,
534 PersistStorage_Save,
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))
545 *obj = iface;
546 else
547 *obj = NULL;
549 if(*obj){
550 IUnknown_AddRef((IUnknown*)*obj);
551 return S_OK;
554 FIXME("Unknown interface: %s\n", debugstr_guid(riid));
555 return E_NOINTERFACE;
558 static ULONG WINAPI PackageCF_AddRef(IClassFactory *iface)
560 TRACE("(static)\n");
561 return 2;
564 static ULONG WINAPI PackageCF_Release(IClassFactory *iface)
566 TRACE("(static)\n");
567 return 1;
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));
578 if(!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);
590 return S_OK;
593 static const IClassFactoryVtbl PackageCF_Vtbl = {
594 PackageCF_QueryInterface,
595 PackageCF_AddRef,
596 PackageCF_Release,
597 PackageCF_CreateInstance,
598 PackageCF_LockServer
601 static IClassFactory PackageCF = {
602 &PackageCF_Vtbl
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)
619 return S_OK;
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);
636 switch(reason){
637 case DLL_PROCESS_ATTACH:
638 g_instance = instance;
639 DisableThreadLibraryCalls(instance);
640 break;
643 return TRUE;