gdi32: Move the handling of font family fallbacks out of freetype.c.
[wine/zf.git] / dlls / packager / packager_main.c
blobde07e5ca2655712db4137f09edaa662e42598453
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 <stdarg.h>
21 #define COBJMACROS
22 #include "initguid.h"
23 #include "windef.h"
24 #include "winbase.h"
25 #include "ole2.h"
26 #include "rpcproxy.h"
27 #include "shellapi.h"
28 #include "shlwapi.h"
30 #include "wine/debug.h"
32 #include "packager_classes.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(packager);
36 static HINSTANCE g_instance;
38 struct Package {
39 IOleObject IOleObject_iface;
40 IPersistStorage IPersistStorage_iface;
42 LONG ref;
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;
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->clientsite)
99 IOleClientSite_Release(This->clientsite);
101 if(*This->filename)
102 DeleteFileW(This->filename);
104 HeapFree(GetProcessHeap(), 0, This);
107 return ref;
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);
116 if(This->clientsite)
117 IOleClientSite_Release(This->clientsite);
119 This->clientsite = pClientSite;
120 if(pClientSite)
121 IOleClientSite_AddRef(pClientSite);
123 return S_OK;
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);
130 return E_NOTIMPL;
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));
137 return E_NOTIMPL;
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");
150 return S_OK;
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);
157 return E_NOTIMPL;
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);
164 return E_NOTIMPL;
167 static HRESULT WINAPI OleObject_InitFromData(IOleObject *iface, IDataObject *pDataObject, BOOL fCreation,
168 DWORD dwReserved)
170 struct Package *This = impl_from_IOleObject(iface);
171 FIXME("(%p)->(%p, 0x%x, %d)\n", This, pDataObject, fCreation, dwReserved);
172 return E_NOTIMPL;
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);
179 return E_NOTIMPL;
182 static HRESULT do_activate_object(struct Package *This, HWND parent)
184 ShellExecuteW(parent, L"open", This->filename, NULL, NULL, SW_SHOW);
185 return S_OK;
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);
195 switch(iVerb){
196 case 0:
197 return do_activate_object(This, hwndParent);
200 return E_INVALIDARG;
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);
207 return E_NOTIMPL;
210 static HRESULT WINAPI OleObject_Update(IOleObject *iface)
212 struct Package *This = impl_from_IOleObject(iface);
213 FIXME("(%p)\n", This);
214 return E_NOTIMPL;
217 static HRESULT WINAPI OleObject_IsUpToDate(IOleObject *iface)
219 struct Package *This = impl_from_IOleObject(iface);
220 FIXME("(%p)\n", This);
221 return E_NOTIMPL;
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);
228 return E_NOTIMPL;
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);
235 return E_NOTIMPL;
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);
242 return E_NOTIMPL;
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);
249 return E_NOTIMPL;
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);
256 return E_NOTIMPL;
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);
263 return E_NOTIMPL;
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);
270 return E_NOTIMPL;
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);
279 if(!pdwStatus)
280 return E_INVALIDARG;
282 *pdwStatus = OLEMISC_ONLYICONIC;
284 return S_OK;
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);
291 return E_NOTIMPL;
294 static const IOleObjectVtbl OleObject_Vtbl = {
295 OleObject_QueryInterface,
296 OleObject_AddRef,
297 OleObject_Release,
298 OleObject_SetClientSite,
299 OleObject_GetClientSite,
300 OleObject_SetHostNames,
301 OleObject_Close,
302 OleObject_SetMoniker,
303 OleObject_GetMoniker,
304 OleObject_InitFromData,
305 OleObject_GetClipboardData,
306 OleObject_DoVerb,
307 OleObject_EnumVerbs,
308 OleObject_Update,
309 OleObject_IsUpToDate,
310 OleObject_GetUserClassID,
311 OleObject_GetUserType,
312 OleObject_SetExtent,
313 OleObject_GetExtent,
314 OleObject_Advise,
315 OleObject_Unadvise,
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,
344 CLSID *pClassID)
346 struct Package *This = impl_from_IPersistStorage(iface);
347 FIXME("(%p)->(%p)\n", This, pClassID);
348 return E_NOTIMPL;
351 static HRESULT WINAPI PersistStorage_IsDirty(IPersistStorage* iface)
353 struct Package *This = impl_from_IPersistStorage(iface);
354 FIXME("(%p)\n", This);
355 return E_NOTIMPL;
358 static HRESULT WINAPI PersistStorage_InitNew(IPersistStorage* iface,
359 IStorage *pStg)
361 struct Package *This = impl_from_IPersistStorage(iface);
362 FIXME("(%p)->(%p)\n", This, pStg);
363 return E_NOTIMPL;
366 static HRESULT discard_string(struct Package *This, IStream *stream)
368 ULONG nbytes;
369 HRESULT hr;
370 char chr = 0;
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;
378 }while(chr);
380 return S_OK;
383 static HRESULT WINAPI PersistStorage_Load(IPersistStorage* iface,
384 IStorage *pStg)
386 struct Package *This = impl_from_IPersistStorage(iface);
387 IStream *stream;
388 DWORD payload_size, len, stream_filename_len, filenameA_len, i, bytes_read;
389 ULARGE_INTEGER payload_pos;
390 LARGE_INTEGER seek;
391 HRESULT hr;
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);
402 if(FAILED(hr)){
403 TRACE("OpenStream gave: %08x\n", hr);
404 return hr;
407 /* skip stream size & two unknown bytes */
408 seek.QuadPart = 6;
409 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
410 if(FAILED(hr))
411 goto exit;
413 /* read and discard label */
414 hr = discard_string(This, stream);
415 if(FAILED(hr))
416 goto exit;
418 /* read and discard filename */
419 hr = discard_string(This, stream);
420 if(FAILED(hr))
421 goto exit;
423 /* skip more unknown data */
424 seek.QuadPart = 4;
425 hr = IStream_Seek(stream, seek, STREAM_SEEK_CUR, NULL);
426 if(FAILED(hr))
427 goto exit;
429 /* ASCIIZ filename */
430 hr = IStream_Read(stream, &filenameA_len, 4, NULL);
431 if(FAILED(hr))
432 goto exit;
434 hr = IStream_Read(stream, filenameA, filenameA_len, NULL);
435 if(FAILED(hr))
436 goto exit;
438 /* skip payload for now */
439 hr = IStream_Read(stream, &payload_size, 4, NULL);
440 if(FAILED(hr))
441 goto exit;
443 seek.QuadPart = 0;
444 hr = IStream_Seek(stream, seek, STREAM_SEEK_CUR, &payload_pos);
445 if(FAILED(hr))
446 goto exit;
448 seek.QuadPart = payload_size;
449 hr = IStream_Seek(stream, seek, STREAM_SEEK_CUR, NULL);
450 if(FAILED(hr))
451 goto exit;
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);
457 if(FAILED(hr))
458 goto exit;
459 }else{
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 != '\\')
467 --stream_filename;
468 if(*stream_filename == '\\')
469 ++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);
479 if(FAILED(hr))
480 goto exit;
482 base_end = PathFindExtensionW(This->filename);
483 lstrcpyW(extension, base_end);
484 i = 1;
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());
491 hr = E_FAIL;
492 goto exit;
495 /* file exists, so increment file name and try again */
496 ++i;
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));
505 while(payload_size){
506 ULONG nbytes;
507 BYTE data[4096];
508 DWORD written;
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)
514 hr = E_FAIL;
515 goto exit;
518 payload_size -= nbytes;
520 WriteFile(file, data, nbytes, &written, NULL);
523 hr = S_OK;
525 exit:
526 if(file != INVALID_HANDLE_VALUE){
527 CloseHandle(file);
528 if(FAILED(hr))
529 DeleteFileW(This->filename);
531 IStream_Release(stream);
533 TRACE("Returning: %08x\n", hr);
534 return 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);
542 return E_NOTIMPL;
545 static HRESULT WINAPI PersistStorage_SaveCompleted(IPersistStorage* iface,
546 IStorage *pStgNew)
548 struct Package *This = impl_from_IPersistStorage(iface);
549 FIXME("(%p)->(%p)\n", This, pStgNew);
550 return E_NOTIMPL;
553 static HRESULT WINAPI PersistStorage_HandsOffStorage(IPersistStorage* iface)
555 struct Package *This = impl_from_IPersistStorage(iface);
556 FIXME("(%p)\n", This);
557 return E_NOTIMPL;
560 static IPersistStorageVtbl PersistStorage_Vtbl = {
561 PersistStorage_QueryInterface,
562 PersistStorage_AddRef,
563 PersistStorage_Release,
564 PersistStorage_GetClassID,
565 PersistStorage_IsDirty,
566 PersistStorage_InitNew,
567 PersistStorage_Load,
568 PersistStorage_Save,
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))
579 *obj = iface;
580 else
581 *obj = NULL;
583 if(*obj){
584 IUnknown_AddRef((IUnknown*)*obj);
585 return S_OK;
588 FIXME("Unknown interface: %s\n", debugstr_guid(riid));
589 return E_NOINTERFACE;
592 static ULONG WINAPI PackageCF_AddRef(IClassFactory *iface)
594 TRACE("(static)\n");
595 return 2;
598 static ULONG WINAPI PackageCF_Release(IClassFactory *iface)
600 TRACE("(static)\n");
601 return 1;
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));
612 if(!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);
624 return S_OK;
627 static const IClassFactoryVtbl PackageCF_Vtbl = {
628 PackageCF_QueryInterface,
629 PackageCF_AddRef,
630 PackageCF_Release,
631 PackageCF_CreateInstance,
632 PackageCF_LockServer
635 static IClassFactory PackageCF = {
636 &PackageCF_Vtbl
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)
653 return S_OK;
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);
670 switch(reason){
671 case DLL_PROCESS_ATTACH:
672 g_instance = instance;
673 DisableThreadLibraryCalls(instance);
674 break;
677 return TRUE;