mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-13 07:56:17 +01:00
Merge branch 'appinfo-shellany-uwplaunch' into 'master'
GWin32AppInfo: support getting info about UWP apps and launching them Closes #1991 See merge request GNOME/glib!1772
This commit is contained in:
commit
0c85348efc
@ -85,8 +85,15 @@ if get_option('gtk_doc')
|
||||
'gunixvolume.h',
|
||||
'gunixvolumemonitor.h',
|
||||
'gwin32networkmonitor.h',
|
||||
'gwin32api-application-activation-manager.h',
|
||||
'gwin32api-iterator.h',
|
||||
'gwin32api-misc.h',
|
||||
'gwin32api-package.h',
|
||||
'gwin32api-storage.h',
|
||||
'gwin32appinfo.h',
|
||||
'gwin32file-sync-stream.h',
|
||||
'gwin32mount.h',
|
||||
'gwin32packageparser.h',
|
||||
'gwin32resolver.h',
|
||||
'gwin32volumemonitor.h',
|
||||
'thumbnail-verify.h',
|
||||
|
126
gio/gwin32api-application-activation-manager.h
Executable file
126
gio/gwin32api-application-activation-manager.h
Executable file
@ -0,0 +1,126 @@
|
||||
#if NTDDI_VERSION < NTDDI_WIN8
|
||||
/* The following code is copied verbatim from MinGW-w64 shobjidl.h */
|
||||
/*
|
||||
* IApplicationActivationManager interface
|
||||
*/
|
||||
typedef enum ACTIVATEOPTIONS {
|
||||
AO_NONE = 0x0,
|
||||
AO_DESIGNMODE = 0x1,
|
||||
AO_NOERRORUI = 0x2,
|
||||
AO_NOSPLASHSCREEN = 0x4
|
||||
} ACTIVATEOPTIONS;
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS(ACTIVATEOPTIONS)
|
||||
|
||||
#ifndef __IApplicationActivationManager_INTERFACE_DEFINED__
|
||||
#define __IApplicationActivationManager_INTERFACE_DEFINED__
|
||||
|
||||
DEFINE_GUID(IID_IApplicationActivationManager, 0x2e941141, 0x7f97, 0x4756, 0xba,0x1d, 0x9d,0xec,0xde,0x89,0x4a,0x3d);
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
MIDL_INTERFACE("2e941141-7f97-4756-ba1d-9decde894a3d")
|
||||
IApplicationActivationManager : public IUnknown
|
||||
{
|
||||
virtual HRESULT STDMETHODCALLTYPE ActivateApplication(
|
||||
LPCWSTR appUserModelId,
|
||||
LPCWSTR arguments,
|
||||
ACTIVATEOPTIONS options,
|
||||
DWORD *processId) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE ActivateForFile(
|
||||
LPCWSTR appUserModelId,
|
||||
IShellItemArray *itemArray,
|
||||
LPCWSTR verb,
|
||||
DWORD *processId) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE ActivateForProtocol(
|
||||
LPCWSTR appUserModelId,
|
||||
IShellItemArray *itemArray,
|
||||
DWORD *processId) = 0;
|
||||
|
||||
};
|
||||
#ifdef __CRT_UUID_DECL
|
||||
__CRT_UUID_DECL(IApplicationActivationManager, 0x2e941141, 0x7f97, 0x4756, 0xba,0x1d, 0x9d,0xec,0xde,0x89,0x4a,0x3d)
|
||||
#endif
|
||||
#else
|
||||
typedef struct IApplicationActivationManagerVtbl {
|
||||
BEGIN_INTERFACE
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
|
||||
IApplicationActivationManager *This,
|
||||
REFIID riid,
|
||||
void **ppvObject);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *AddRef)(
|
||||
IApplicationActivationManager *This);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *Release)(
|
||||
IApplicationActivationManager *This);
|
||||
|
||||
/*** IApplicationActivationManager methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *ActivateApplication)(
|
||||
IApplicationActivationManager *This,
|
||||
LPCWSTR appUserModelId,
|
||||
LPCWSTR arguments,
|
||||
ACTIVATEOPTIONS options,
|
||||
DWORD *processId);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *ActivateForFile)(
|
||||
IApplicationActivationManager *This,
|
||||
LPCWSTR appUserModelId,
|
||||
IShellItemArray *itemArray,
|
||||
LPCWSTR verb,
|
||||
DWORD *processId);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *ActivateForProtocol)(
|
||||
IApplicationActivationManager *This,
|
||||
LPCWSTR appUserModelId,
|
||||
IShellItemArray *itemArray,
|
||||
DWORD *processId);
|
||||
|
||||
END_INTERFACE
|
||||
} IApplicationActivationManagerVtbl;
|
||||
|
||||
interface IApplicationActivationManager {
|
||||
CONST_VTBL IApplicationActivationManagerVtbl* lpVtbl;
|
||||
};
|
||||
|
||||
#ifdef COBJMACROS
|
||||
#ifndef WIDL_C_INLINE_WRAPPERS
|
||||
/*** IUnknown methods ***/
|
||||
#define IApplicationActivationManager_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
|
||||
#define IApplicationActivationManager_AddRef(This) (This)->lpVtbl->AddRef(This)
|
||||
#define IApplicationActivationManager_Release(This) (This)->lpVtbl->Release(This)
|
||||
/*** IApplicationActivationManager methods ***/
|
||||
#define IApplicationActivationManager_ActivateApplication(This,appUserModelId,arguments,options,processId) (This)->lpVtbl->ActivateApplication(This,appUserModelId,arguments,options,processId)
|
||||
#define IApplicationActivationManager_ActivateForFile(This,appUserModelId,itemArray,verb,processId) (This)->lpVtbl->ActivateForFile(This,appUserModelId,itemArray,verb,processId)
|
||||
#define IApplicationActivationManager_ActivateForProtocol(This,appUserModelId,itemArray,processId) (This)->lpVtbl->ActivateForProtocol(This,appUserModelId,itemArray,processId)
|
||||
#else
|
||||
/*** IUnknown methods ***/
|
||||
static FORCEINLINE HRESULT IApplicationActivationManager_QueryInterface(IApplicationActivationManager* This,REFIID riid,void **ppvObject) {
|
||||
return This->lpVtbl->QueryInterface(This,riid,ppvObject);
|
||||
}
|
||||
static FORCEINLINE ULONG IApplicationActivationManager_AddRef(IApplicationActivationManager* This) {
|
||||
return This->lpVtbl->AddRef(This);
|
||||
}
|
||||
static FORCEINLINE ULONG IApplicationActivationManager_Release(IApplicationActivationManager* This) {
|
||||
return This->lpVtbl->Release(This);
|
||||
}
|
||||
/*** IApplicationActivationManager methods ***/
|
||||
static FORCEINLINE HRESULT IApplicationActivationManager_ActivateApplication(IApplicationActivationManager* This,LPCWSTR appUserModelId,LPCWSTR arguments,ACTIVATEOPTIONS options,DWORD *processId) {
|
||||
return This->lpVtbl->ActivateApplication(This,appUserModelId,arguments,options,processId);
|
||||
}
|
||||
static FORCEINLINE HRESULT IApplicationActivationManager_ActivateForFile(IApplicationActivationManager* This,LPCWSTR appUserModelId,IShellItemArray *itemArray,LPCWSTR verb,DWORD *processId) {
|
||||
return This->lpVtbl->ActivateForFile(This,appUserModelId,itemArray,verb,processId);
|
||||
}
|
||||
static FORCEINLINE HRESULT IApplicationActivationManager_ActivateForProtocol(IApplicationActivationManager* This,LPCWSTR appUserModelId,IShellItemArray *itemArray,DWORD *processId) {
|
||||
return This->lpVtbl->ActivateForProtocol(This,appUserModelId,itemArray,processId);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __IApplicationActivationManager_INTERFACE_DEFINED__ */
|
||||
#endif /* NTDDI_VERSION < NTDDI_WIN8 */
|
125
gio/gwin32api-iterator.h
Executable file
125
gio/gwin32api-iterator.h
Executable file
@ -0,0 +1,125 @@
|
||||
typedef interface IIterator IIterator;
|
||||
typedef interface IIterable IIterable;
|
||||
|
||||
/* IIterator */
|
||||
typedef struct IIteratorVtbl {
|
||||
BEGIN_INTERFACE
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
|
||||
IIterator *This,
|
||||
REFIID riid,
|
||||
void **ppvObject);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *AddRef)(
|
||||
IIterator *This);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *Release)(
|
||||
IIterator *This);
|
||||
|
||||
/*** IInspectable methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *GetIids)(
|
||||
IIterator *This,
|
||||
UINT32 *count,
|
||||
IID **ids);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)(
|
||||
IIterator *This,
|
||||
HSTRING *className);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetTrustLevel)(
|
||||
IIterator *This,
|
||||
TrustLevel *trustLevel);
|
||||
|
||||
/*** IIterator methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *get_Current)(
|
||||
IIterator *This,
|
||||
IUnknown **current);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_HasCurrent)(
|
||||
IIterator *This,
|
||||
CHAR *hasCurrent);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *MoveNext)(
|
||||
IIterator *This,
|
||||
CHAR *hasCurrent);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetMany)(
|
||||
IIterator *This,
|
||||
UINT capacity,
|
||||
void *value,
|
||||
UINT *actual);
|
||||
|
||||
END_INTERFACE
|
||||
} IIteratorVtbl;
|
||||
|
||||
interface IIterator {
|
||||
CONST_VTBL IIteratorVtbl* lpVtbl;
|
||||
};
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
#define IIterator_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
|
||||
#define IIterator_AddRef(This) (This)->lpVtbl->AddRef(This)
|
||||
#define IIterator_Release(This) (This)->lpVtbl->Release(This)
|
||||
/*** IInspectable methods ***/
|
||||
#define IIterator_GetIids(This,count,ids) (This)->lpVtbl->GetIids(This,count,ids)
|
||||
#define IIterator_GetRuntimeClassName(This,name) (This)->lpVtbl->GetRuntimeClassName(This,name)
|
||||
#define IIterator_GetTrustLevel(This,level) (This)->lpVtbl->GetTrustLevel(This,level)
|
||||
/*** IIterator methods ***/
|
||||
#define IIterator_get_Current(This,current) (This)->lpVtbl->get_Current(This,current)
|
||||
#define IIterator_get_HasCurrent(This,hasCurrent) (This)->lpVtbl->get_HasCurrent(This,hasCurrent)
|
||||
#define IIterator_MoveNext(This,hasCurrent) (This)->lpVtbl->MoveNext(This,hasCurrent)
|
||||
#define IIterator_GetMany(This,capacity,value,actual) (This)->lpVtbl->GetMany(This,capacity,value,actual)
|
||||
|
||||
/* IIterable */
|
||||
typedef struct IIterableVtbl {
|
||||
BEGIN_INTERFACE
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
|
||||
IIterable *This,
|
||||
REFIID riid,
|
||||
void **ppvObject);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *AddRef)(
|
||||
IIterable *This);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *Release)(
|
||||
IIterable *This);
|
||||
|
||||
/*** IInspectable methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *GetIids)(
|
||||
IIterable *This,
|
||||
UINT32 *count,
|
||||
IID **ids);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)(
|
||||
IIterable *This,
|
||||
HSTRING *className);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetTrustLevel)(
|
||||
IIterable *This,
|
||||
TrustLevel *trustLevel);
|
||||
|
||||
/*** IIterable methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *First)(
|
||||
IIterable *This,
|
||||
IIterator **first);
|
||||
|
||||
END_INTERFACE
|
||||
} IIterableVtbl;
|
||||
|
||||
interface IIterable {
|
||||
CONST_VTBL IIterableVtbl* lpVtbl;
|
||||
};
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
#define IIterable_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
|
||||
#define IIterable_AddRef(This) (This)->lpVtbl->AddRef(This)
|
||||
#define IIterable_Release(This) (This)->lpVtbl->Release(This)
|
||||
/*** IInspectable methods ***/
|
||||
#define IIterable_GetIids(This,count,ids) (This)->lpVtbl->GetIids(This,count,ids)
|
||||
#define IIterable_GetRuntimeClassName(This,name) (This)->lpVtbl->GetRuntimeClassName(This,name)
|
||||
#define IIterable_GetTrustLevel(This,level) (This)->lpVtbl->GetTrustLevel(This,level)
|
||||
/*** IIterable methods ***/
|
||||
#define IIterable_First(This,retval) (This)->lpVtbl->First(This,retval)
|
1
gio/gwin32api-misc.h
Executable file
1
gio/gwin32api-misc.h
Executable file
@ -0,0 +1 @@
|
||||
typedef interface IProcessorArchitecture IProcessorArchitecture;
|
264
gio/gwin32api-package.h
Executable file
264
gio/gwin32api-package.h
Executable file
@ -0,0 +1,264 @@
|
||||
typedef interface IPackageManager IPackageManager;
|
||||
typedef interface IPackage IPackage;
|
||||
typedef interface IPackageId IPackageId;
|
||||
typedef interface IPackageVersion IPackageVersion;
|
||||
|
||||
DEFINE_GUID(IID_IPackageManager, 0x9A7D4B65, 0x5E8F, 0x4FC7, 0xA2, 0xE5, 0x7F, 0x69, 0x25, 0xCB, 0x8B, 0x53);
|
||||
DEFINE_GUID(IID_IPackage, 0x163C792F, 0xBD75, 0x413C, 0xBF, 0x23, 0xB1, 0xFE, 0x7B, 0x95, 0xD8, 0x25);
|
||||
|
||||
/* IPackageManager */
|
||||
typedef struct IPackageManagerVtbl {
|
||||
BEGIN_INTERFACE
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
|
||||
IPackageManager *This,
|
||||
REFIID riid,
|
||||
void **ppvObject);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *AddRef)(
|
||||
IPackageManager *This);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *Release)(
|
||||
IPackageManager *This);
|
||||
|
||||
/*** IInspectable methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *GetIids)(
|
||||
IPackageManager *This,
|
||||
UINT32 *count,
|
||||
IID **ids);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)(
|
||||
IPackageManager *This,
|
||||
HSTRING *className);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetTrustLevel)(
|
||||
IPackageManager *This,
|
||||
TrustLevel *trustLevel);
|
||||
|
||||
/*** IPackageManager methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *stub_AddPackageAsync)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_UpdatePackageAsync)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_RemovePackageAsync)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_StagePackageAsync)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_RegisterPackageAsync)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *FindPackages)(
|
||||
IPackageManager *This,
|
||||
IIterable **retval);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *FindPackagesByUserSecurityId)(
|
||||
IPackageManager *This,
|
||||
HSTRING userSecurityId,
|
||||
IIterable **retval);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_FindPackagesByNamePublisher)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_FindPackagesByUserSecurityIdNamePublisher)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_FindUsers)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_SetPackageState)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_FindPackageByPackageFullName)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_CleanupPackageForUserAsync)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_FindPackagesByPackageFamilyName)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_FindPackagesByUserSecurityIdPackageFamilyName)(
|
||||
IPackageManager *This);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *stub_FindPackageByUserSecurityIdPackageFullName)(
|
||||
IPackageManager *This);
|
||||
|
||||
END_INTERFACE
|
||||
} IPackageManagerVtbl;
|
||||
|
||||
interface IPackageManager {
|
||||
CONST_VTBL IPackageManagerVtbl* lpVtbl;
|
||||
};
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
#define IPackageManager_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
|
||||
#define IPackageManager_AddRef(This) (This)->lpVtbl->AddRef(This)
|
||||
#define IPackageManager_Release(This) (This)->lpVtbl->Release(This)
|
||||
/*** IInspectable methods ***/
|
||||
#define IPackageManager_GetIids(This,count,ids) (This)->lpVtbl->GetIids(This,count,ids)
|
||||
#define IPackageManager_GetRuntimeClassName(This,name) (This)->lpVtbl->GetRuntimeClassName(This,name)
|
||||
#define IPackageManager_GetTrustLevel(This,level) (This)->lpVtbl->GetTrustLevel(This,level)
|
||||
/*** IPackageManager methods ***/
|
||||
#define IPackageManager_FindPackages(This,retval) (This)->lpVtbl->FindPackages(This,retval)
|
||||
#define IPackageManager_FindPackagesByUserSecurityId(This,userSecurityId,retval) (This)->lpVtbl->FindPackagesByUserSecurityId(This,userSecurityId,retval)
|
||||
|
||||
/* IPackageId */
|
||||
typedef struct IPackageIdVtbl {
|
||||
BEGIN_INTERFACE
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
|
||||
IPackageId *This,
|
||||
REFIID riid,
|
||||
void **ppvObject);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *AddRef)(
|
||||
IPackageId *This);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *Release)(
|
||||
IPackageId *This);
|
||||
|
||||
/*** IInspectable methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *GetIids)(
|
||||
IPackageId *This,
|
||||
UINT32 *count,
|
||||
IID **ids);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)(
|
||||
IPackageId *This,
|
||||
HSTRING *className);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetTrustLevel)(
|
||||
IPackageId *This,
|
||||
TrustLevel *trustLevel);
|
||||
|
||||
/*** IPackageId methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *get_Name)(
|
||||
IPackageId *This,
|
||||
HSTRING *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_Version)(
|
||||
IPackageId *This,
|
||||
IPackageVersion *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_Architecture)(
|
||||
IPackageId *This,
|
||||
IProcessorArchitecture *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_ResourceId)(
|
||||
IPackageId *This,
|
||||
HSTRING *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_Publisher)(
|
||||
IPackageId *This,
|
||||
HSTRING *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_PublisherId)(
|
||||
IPackageId *This,
|
||||
HSTRING *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_FullName)(
|
||||
IPackageId *This,
|
||||
HSTRING *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_FamilyName)(
|
||||
IPackageId *This,
|
||||
HSTRING *value);
|
||||
|
||||
END_INTERFACE
|
||||
} IPackageIdVtbl;
|
||||
|
||||
interface IPackageId {
|
||||
CONST_VTBL IPackageIdVtbl* lpVtbl;
|
||||
};
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
#define IPackageId_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
|
||||
#define IPackageId_AddRef(This) (This)->lpVtbl->AddRef(This)
|
||||
#define IPackageId_Release(This) (This)->lpVtbl->Release(This)
|
||||
/*** IInspectable methods ***/
|
||||
#define IPackageId_GetIids(This,count,ids) (This)->lpVtbl->GetIids(This,count,ids)
|
||||
#define IPackageId_GetRuntimeClassName(This,name) (This)->lpVtbl->GetRuntimeClassName(This,name)
|
||||
#define IPackageId_GetTrustLevel(This,level) (This)->lpVtbl->GetTrustLevel(This,level)
|
||||
/*** IPackageId methods ***/
|
||||
#define IPackageId_get_Name(This,value) (This)->lpVtbl->get_Name(This,value)
|
||||
#define IPackageId_get_Version(This,value) (This)->lpVtbl->get_Version(This,value)
|
||||
#define IPackageId_get_Architecture(This,value) (This)->lpVtbl->get_Architecture(This,value)
|
||||
#define IPackageId_get_ResourceId(This,value) (This)->lpVtbl->get_ResourceId(This,value)
|
||||
#define IPackageId_get_Publisher(This,value) (This)->lpVtbl->get_Publisher(This,value)
|
||||
#define IPackageId_get_PublisherId(This,value) (This)->lpVtbl->get_PublisherId(This,value)
|
||||
#define IPackageId_get_FullName(This,value) (This)->lpVtbl->get_FullName(This,value)
|
||||
#define IPackageId_get_FamilyName(This,value) (This)->lpVtbl->get_FamilyName(This,value)
|
||||
|
||||
/* IPackage */
|
||||
typedef struct IPackageVtbl {
|
||||
BEGIN_INTERFACE
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
|
||||
IPackage *This,
|
||||
REFIID riid,
|
||||
void **ppvObject);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *AddRef)(
|
||||
IPackage *This);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *Release)(
|
||||
IPackage *This);
|
||||
|
||||
/*** IInspectable methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *GetIids)(
|
||||
IPackage *This,
|
||||
UINT32 *count,
|
||||
IID **ids);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)(
|
||||
IPackage *This,
|
||||
HSTRING *className);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetTrustLevel)(
|
||||
IPackage *This,
|
||||
TrustLevel *trustLevel);
|
||||
|
||||
/*** IPackage methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *get_Id)(
|
||||
IPackage *This,
|
||||
IPackageId **value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_InstalledLocation)(
|
||||
IPackage *This,
|
||||
IUnknown **value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_IsFramework)(
|
||||
IPackage *This,
|
||||
CHAR *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_Dependencies)(
|
||||
IPackage *This,
|
||||
void **value);
|
||||
|
||||
END_INTERFACE
|
||||
} IPackageVtbl;
|
||||
|
||||
interface IPackage {
|
||||
CONST_VTBL IPackageVtbl* lpVtbl;
|
||||
};
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
#define IPackage_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
|
||||
#define IPackage_AddRef(This) (This)->lpVtbl->AddRef(This)
|
||||
#define IPackage_Release(This) (This)->lpVtbl->Release(This)
|
||||
/*** IInspectable methods ***/
|
||||
#define IPackage_GetIids(This,count,ids) (This)->lpVtbl->GetIids(This,count,ids)
|
||||
#define IPackage_GetRuntimeClassName(This,name) (This)->lpVtbl->GetRuntimeClassName(This,name)
|
||||
#define IPackage_GetTrustLevel(This,level) (This)->lpVtbl->GetTrustLevel(This,level)
|
||||
/*** IPackage methods ***/
|
||||
#define IPackage_get_Id(This,value) (This)->lpVtbl->get_Id(This,value)
|
||||
#define IPackage_get_InstalledLocation(This,value) (This)->lpVtbl->get_InstalledLocation(This,value)
|
||||
#define IPackage_get_IsFramework(This,value) (This)->lpVtbl->get_IsFramework(This,value)
|
||||
#define IPackage_get_Dependencies(This,value) (This)->lpVtbl->get_Dependencies(This,value)
|
339
gio/gwin32api-storage.h
Executable file
339
gio/gwin32api-storage.h
Executable file
@ -0,0 +1,339 @@
|
||||
struct DateTime;
|
||||
|
||||
typedef struct DateTime {
|
||||
UINT64 UniversalTime;
|
||||
} DateTime;
|
||||
|
||||
/* The following is copied verbatim from MinGW-w64 windows.storage.h */
|
||||
enum StorageItemTypes;
|
||||
enum FileAttributes;
|
||||
enum NameCollisionOption;
|
||||
enum StorageDeleteOption;
|
||||
|
||||
typedef enum NameCollisionoption {
|
||||
NameCollisionoption_GenerateUniqueName = 0,
|
||||
NameCollisionoption_ReplaceExisting = 1,
|
||||
NameCollisionoption_FailIfExists = 2
|
||||
} NameCollisionOption;
|
||||
|
||||
typedef enum FileAttributes {
|
||||
FileAttributes_Normal = 0,
|
||||
FileAttributes_ReadOnly = 1,
|
||||
FileAttributes_Directory = 2,
|
||||
FileAttributes_Archive = 3,
|
||||
FileAttributes_Temporary = 4
|
||||
} FileAttributes;
|
||||
|
||||
typedef enum StorageItemTypes {
|
||||
StorageItemTypes_None = 0,
|
||||
StorageItemTypes_File = 1,
|
||||
StorageItemTypes_Folder = 2
|
||||
} StorageItemTypes;
|
||||
|
||||
typedef enum StorageDeleteOption {
|
||||
StorageDeleteOption_Default = 0,
|
||||
StorageDeleteOption_PermanentDelete = 1
|
||||
} StorageDeleteOption;
|
||||
|
||||
#ifndef __IStorageItem_FWD_DEFINED__
|
||||
#define __IStorageItem_FWD_DEFINED__
|
||||
typedef interface IStorageItem IStorageItem;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* IStorageItem interface
|
||||
*/
|
||||
#ifndef __IStorageItem_INTERFACE_DEFINED__
|
||||
#define __IStorageItem_INTERFACE_DEFINED__
|
||||
|
||||
DEFINE_GUID(IID_IStorageItem, 0x4207a996, 0xca2f, 0x42f7, 0xbd,0xe8, 0x8b,0x10,0x45,0x7a,0x7f,0x30);
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
MIDL_INTERFACE("4207a996-ca2f-42f7-bde8-8b10457a7f30")
|
||||
IStorageItem : public IInspectable
|
||||
{
|
||||
virtual HRESULT STDMETHODCALLTYPE RenameAsyncOverloadDefaultOptions(
|
||||
HSTRING desiredName,
|
||||
IInspectable **action) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE RenameAsync(
|
||||
HSTRING desiredName,
|
||||
NameCollisionOption option,
|
||||
IInspectable **action) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE DeleteAsyncOverloadDefaultOptions(
|
||||
IInspectable **action) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE DeleteAsync(
|
||||
StorageDeleteOption option,
|
||||
IInspectable **action) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetBasicPropertiesAsync(
|
||||
IInspectable **action) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE get_Name(
|
||||
HSTRING *value) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE get_Path(
|
||||
HSTRING *value) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE get_Attributes(
|
||||
FileAttributes *value) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE get_DateCreated(
|
||||
DateTime *value) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE IsOfType(
|
||||
StorageItemTypes itemType,
|
||||
boolean *value) = 0;
|
||||
|
||||
};
|
||||
#ifdef __CRT_UUID_DECL
|
||||
__CRT_UUID_DECL(IStorageItem, 0x4207a996, 0xca2f, 0x42f7, 0xbd,0xe8, 0x8b,0x10,0x45,0x7a,0x7f,0x30)
|
||||
#endif
|
||||
#else
|
||||
typedef struct IStorageItemVtbl {
|
||||
BEGIN_INTERFACE
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
|
||||
IStorageItem* This,
|
||||
REFIID riid,
|
||||
void **ppvObject);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *AddRef)(
|
||||
IStorageItem* This);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *Release)(
|
||||
IStorageItem* This);
|
||||
|
||||
/*** IInspectable methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *GetIids)(
|
||||
IStorageItem* This,
|
||||
ULONG *iidCount,
|
||||
IID **iids);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)(
|
||||
IStorageItem* This,
|
||||
HSTRING *className);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetTrustLevel)(
|
||||
IStorageItem* This,
|
||||
TrustLevel *trustLevel);
|
||||
|
||||
/*** IStorageItem methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *RenameAsyncOverloadDefaultOptions)(
|
||||
IStorageItem* This,
|
||||
HSTRING desiredName,
|
||||
IInspectable **action);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *RenameAsync)(
|
||||
IStorageItem* This,
|
||||
HSTRING desiredName,
|
||||
NameCollisionOption option,
|
||||
IInspectable **action);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *DeleteAsyncOverloadDefaultOptions)(
|
||||
IStorageItem* This,
|
||||
IInspectable **action);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *DeleteAsync)(
|
||||
IStorageItem* This,
|
||||
StorageDeleteOption option,
|
||||
IInspectable **action);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *GetBasicPropertiesAsync)(
|
||||
IStorageItem* This,
|
||||
IInspectable **action);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_Name)(
|
||||
IStorageItem* This,
|
||||
HSTRING *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_Path)(
|
||||
IStorageItem* This,
|
||||
HSTRING *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_Attributes)(
|
||||
IStorageItem* This,
|
||||
FileAttributes *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *get_DateCreated)(
|
||||
IStorageItem* This,
|
||||
DateTime *value);
|
||||
|
||||
HRESULT (STDMETHODCALLTYPE *IsOfType)(
|
||||
IStorageItem* This,
|
||||
StorageItemTypes itemType,
|
||||
boolean *value);
|
||||
|
||||
END_INTERFACE
|
||||
} IStorageItemVtbl;
|
||||
interface IStorageItem {
|
||||
CONST_VTBL IStorageItemVtbl* lpVtbl;
|
||||
};
|
||||
|
||||
#ifdef COBJMACROS
|
||||
#ifndef WIDL_C_INLINE_WRAPPERS
|
||||
/*** IUnknown methods ***/
|
||||
#define IStorageItem_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject)
|
||||
#define IStorageItem_AddRef(This) (This)->lpVtbl->AddRef(This)
|
||||
#define IStorageItem_Release(This) (This)->lpVtbl->Release(This)
|
||||
/*** IInspectable methods ***/
|
||||
#define IStorageItem_GetIids(This,iidCount,iids) (This)->lpVtbl->GetIids(This,iidCount,iids)
|
||||
#define IStorageItem_GetRuntimeClassName(This,className) (This)->lpVtbl->GetRuntimeClassName(This,className)
|
||||
#define IStorageItem_GetTrustLevel(This,trustLevel) (This)->lpVtbl->GetTrustLevel(This,trustLevel)
|
||||
/*** IStorageItem methods ***/
|
||||
#define IStorageItem_RenameAsyncOverloadDefaultOptions(This,desiredName,action) (This)->lpVtbl->RenameAsyncOverloadDefaultOptions(This,desiredName,action)
|
||||
#define IStorageItem_RenameAsync(This,desiredName,option,action) (This)->lpVtbl->RenameAsync(This,desiredName,option,action)
|
||||
#define IStorageItem_DeleteAsyncOverloadDefaultOptions(This,action) (This)->lpVtbl->DeleteAsyncOverloadDefaultOptions(This,action)
|
||||
#define IStorageItem_DeleteAsync(This,option,action) (This)->lpVtbl->DeleteAsync(This,option,action)
|
||||
#define IStorageItem_GetBasicPropertiesAsync(This,action) (This)->lpVtbl->GetBasicPropertiesAsync(This,action)
|
||||
#define IStorageItem_get_Name(This,value) (This)->lpVtbl->get_Name(This,value)
|
||||
#define IStorageItem_get_Path(This,value) (This)->lpVtbl->get_Path(This,value)
|
||||
#define IStorageItem_get_Attributes(This,value) (This)->lpVtbl->get_Attributes(This,value)
|
||||
#define IStorageItem_get_DateCreated(This,value) (This)->lpVtbl->get_DateCreated(This,value)
|
||||
#define IStorageItem_IsOfType(This,itemType,value) (This)->lpVtbl->IsOfType(This,itemType,value)
|
||||
#else
|
||||
/*** IUnknown methods ***/
|
||||
static FORCEINLINE HRESULT IStorageItem_QueryInterface(IStorageItem* This,REFIID riid,void **ppvObject) {
|
||||
return This->lpVtbl->QueryInterface(This,riid,ppvObject);
|
||||
}
|
||||
static FORCEINLINE ULONG IStorageItem_AddRef(IStorageItem* This) {
|
||||
return This->lpVtbl->AddRef(This);
|
||||
}
|
||||
static FORCEINLINE ULONG IStorageItem_Release(IStorageItem* This) {
|
||||
return This->lpVtbl->Release(This);
|
||||
}
|
||||
/*** IInspectable methods ***/
|
||||
static FORCEINLINE HRESULT IStorageItem_GetIids(IStorageItem* This,ULONG *iidCount,IID **iids) {
|
||||
return This->lpVtbl->GetIids(This,iidCount,iids);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_GetRuntimeClassName(IStorageItem* This,HSTRING *className) {
|
||||
return This->lpVtbl->GetRuntimeClassName(This,className);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_GetTrustLevel(IStorageItem* This,TrustLevel *trustLevel) {
|
||||
return This->lpVtbl->GetTrustLevel(This,trustLevel);
|
||||
}
|
||||
/*** IStorageItem methods ***/
|
||||
static FORCEINLINE HRESULT IStorageItem_RenameAsyncOverloadDefaultOptions(IStorageItem* This,HSTRING desiredName,IInspectable **action) {
|
||||
return This->lpVtbl->RenameAsyncOverloadDefaultOptions(This,desiredName,action);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_RenameAsync(IStorageItem* This,HSTRING desiredName,NameCollisionOption option,IInspectable **action) {
|
||||
return This->lpVtbl->RenameAsync(This,desiredName,option,action);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_DeleteAsyncOverloadDefaultOptions(IStorageItem* This,IInspectable **action) {
|
||||
return This->lpVtbl->DeleteAsyncOverloadDefaultOptions(This,action);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_DeleteAsync(IStorageItem* This,StorageDeleteOption option,IInspectable **action) {
|
||||
return This->lpVtbl->DeleteAsync(This,option,action);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_GetBasicPropertiesAsync(IStorageItem* This,IInspectable **action) {
|
||||
return This->lpVtbl->GetBasicPropertiesAsync(This,action);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_get_Name(IStorageItem* This,HSTRING *value) {
|
||||
return This->lpVtbl->get_Name(This,value);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_get_Path(IStorageItem* This,HSTRING *value) {
|
||||
return This->lpVtbl->get_Path(This,value);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_get_Attributes(IStorageItem* This,FileAttributes *value) {
|
||||
return This->lpVtbl->get_Attributes(This,value);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_get_DateCreated(IStorageItem* This,DateTime *value) {
|
||||
return This->lpVtbl->get_DateCreated(This,value);
|
||||
}
|
||||
static FORCEINLINE HRESULT IStorageItem_IsOfType(IStorageItem* This,StorageItemTypes itemType,boolean *value) {
|
||||
return This->lpVtbl->IsOfType(This,itemType,value);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
HRESULT STDMETHODCALLTYPE IStorageItem_RenameAsyncOverloadDefaultOptions_Proxy(
|
||||
IStorageItem* This,
|
||||
HSTRING desiredName,
|
||||
IInspectable **action);
|
||||
void __RPC_STUB IStorageItem_RenameAsyncOverloadDefaultOptions_Stub(
|
||||
IRpcStubBuffer* This,
|
||||
IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
HRESULT STDMETHODCALLTYPE IStorageItem_RenameAsync_Proxy(
|
||||
IStorageItem* This,
|
||||
HSTRING desiredName,
|
||||
NameCollisionOption option,
|
||||
IInspectable **action);
|
||||
void __RPC_STUB IStorageItem_RenameAsync_Stub(
|
||||
IRpcStubBuffer* This,
|
||||
IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
HRESULT STDMETHODCALLTYPE IStorageItem_DeleteAsyncOverloadDefaultOptions_Proxy(
|
||||
IStorageItem* This,
|
||||
IInspectable **action);
|
||||
void __RPC_STUB IStorageItem_DeleteAsyncOverloadDefaultOptions_Stub(
|
||||
IRpcStubBuffer* This,
|
||||
IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
HRESULT STDMETHODCALLTYPE IStorageItem_DeleteAsync_Proxy(
|
||||
IStorageItem* This,
|
||||
StorageDeleteOption option,
|
||||
IInspectable **action);
|
||||
void __RPC_STUB IStorageItem_DeleteAsync_Stub(
|
||||
IRpcStubBuffer* This,
|
||||
IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
HRESULT STDMETHODCALLTYPE IStorageItem_GetBasicPropertiesAsync_Proxy(
|
||||
IStorageItem* This,
|
||||
IInspectable **action);
|
||||
void __RPC_STUB IStorageItem_GetBasicPropertiesAsync_Stub(
|
||||
IRpcStubBuffer* This,
|
||||
IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
HRESULT STDMETHODCALLTYPE IStorageItem_get_Name_Proxy(
|
||||
IStorageItem* This,
|
||||
HSTRING *value);
|
||||
void __RPC_STUB IStorageItem_get_Name_Stub(
|
||||
IRpcStubBuffer* This,
|
||||
IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
HRESULT STDMETHODCALLTYPE IStorageItem_get_Path_Proxy(
|
||||
IStorageItem* This,
|
||||
HSTRING *value);
|
||||
void __RPC_STUB IStorageItem_get_Path_Stub(
|
||||
IRpcStubBuffer* This,
|
||||
IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
HRESULT STDMETHODCALLTYPE IStorageItem_get_Attributes_Proxy(
|
||||
IStorageItem* This,
|
||||
FileAttributes *value);
|
||||
void __RPC_STUB IStorageItem_get_Attributes_Stub(
|
||||
IRpcStubBuffer* This,
|
||||
IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
HRESULT STDMETHODCALLTYPE IStorageItem_get_DateCreated_Proxy(
|
||||
IStorageItem* This,
|
||||
DateTime *value);
|
||||
void __RPC_STUB IStorageItem_get_DateCreated_Stub(
|
||||
IRpcStubBuffer* This,
|
||||
IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
HRESULT STDMETHODCALLTYPE IStorageItem_IsOfType_Proxy(
|
||||
IStorageItem* This,
|
||||
StorageItemTypes itemType,
|
||||
boolean *value);
|
||||
void __RPC_STUB IStorageItem_IsOfType_Stub(
|
||||
IRpcStubBuffer* This,
|
||||
IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
|
||||
#endif /* __IStorageItem_INTERFACE_DEFINED__ */
|
1117
gio/gwin32appinfo.c
1117
gio/gwin32appinfo.c
File diff suppressed because it is too large
Load Diff
508
gio/gwin32file-sync-stream.c
Executable file
508
gio/gwin32file-sync-stream.c
Executable file
@ -0,0 +1,508 @@
|
||||
/* gwin32file-sync-stream.c - a simple IStream implementation
|
||||
*
|
||||
* Copyright 2020 Руслан Ижбулатов
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* A COM object that implements an IStream backed by a file HANDLE.
|
||||
* Works just like `SHCreateStreamOnFileEx()`, but does not
|
||||
* support locking, and doesn't force us to link to libshlwapi.
|
||||
* Only supports synchronous access.
|
||||
*/
|
||||
#include "config.h"
|
||||
#define COBJMACROS
|
||||
#define INITGUID
|
||||
#include <windows.h>
|
||||
|
||||
#include "gwin32file-sync-stream.h"
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_query_interface (IStream *self_ptr,
|
||||
REFIID ref_interface_guid,
|
||||
LPVOID *output_object_ptr);
|
||||
static ULONG STDMETHODCALLTYPE _file_sync_stream_release (IStream *self_ptr);
|
||||
static ULONG STDMETHODCALLTYPE _file_sync_stream_add_ref (IStream *self_ptr);
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_read (IStream *self_ptr,
|
||||
void *output_data,
|
||||
ULONG bytes_to_read,
|
||||
ULONG *output_bytes_read);
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_write (IStream *self_ptr,
|
||||
const void *data,
|
||||
ULONG bytes_to_write,
|
||||
ULONG *output_bytes_written);
|
||||
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_clone (IStream *self_ptr,
|
||||
IStream **output_clone_ptr);
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_commit (IStream *self_ptr,
|
||||
DWORD commit_flags);
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_copy_to (IStream *self_ptr,
|
||||
IStream *output_stream,
|
||||
ULARGE_INTEGER bytes_to_copy,
|
||||
ULARGE_INTEGER *output_bytes_read,
|
||||
ULARGE_INTEGER *output_bytes_written);
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_lock_region (IStream *self_ptr,
|
||||
ULARGE_INTEGER lock_offset,
|
||||
ULARGE_INTEGER lock_bytes,
|
||||
DWORD lock_type);
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_revert (IStream *self_ptr);
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_seek (IStream *self_ptr,
|
||||
LARGE_INTEGER move_distance,
|
||||
DWORD origin,
|
||||
ULARGE_INTEGER *output_new_position);
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_set_size (IStream *self_ptr,
|
||||
ULARGE_INTEGER new_size);
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_stat (IStream *self_ptr,
|
||||
STATSTG *output_stat,
|
||||
DWORD flags);
|
||||
static HRESULT STDMETHODCALLTYPE _file_sync_stream_unlock_region (IStream *self_ptr,
|
||||
ULARGE_INTEGER lock_offset,
|
||||
ULARGE_INTEGER lock_bytes,
|
||||
DWORD lock_type);
|
||||
|
||||
static void _file_sync_stream_free (GWin32FileSyncStream *self);
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_query_interface (IStream *self_ptr,
|
||||
REFIID ref_interface_guid,
|
||||
LPVOID *output_object_ptr)
|
||||
{
|
||||
*output_object_ptr = NULL;
|
||||
|
||||
if (IsEqualGUID (ref_interface_guid, &IID_IUnknown))
|
||||
{
|
||||
IUnknown_AddRef ((IUnknown *) self_ptr);
|
||||
*output_object_ptr = self_ptr;
|
||||
return S_OK;
|
||||
}
|
||||
else if (IsEqualGUID (ref_interface_guid, &IID_IStream))
|
||||
{
|
||||
IStream_AddRef (self_ptr);
|
||||
*output_object_ptr = self_ptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE
|
||||
_file_sync_stream_add_ref (IStream *self_ptr)
|
||||
{
|
||||
GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr;
|
||||
|
||||
return ++self->ref_count;
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE
|
||||
_file_sync_stream_release (IStream *self_ptr)
|
||||
{
|
||||
GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr;
|
||||
|
||||
int ref_count = --self->ref_count;
|
||||
|
||||
if (ref_count == 0)
|
||||
_file_sync_stream_free (self);
|
||||
|
||||
return ref_count;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_read (IStream *self_ptr,
|
||||
void *output_data,
|
||||
ULONG bytes_to_read,
|
||||
ULONG *output_bytes_read)
|
||||
{
|
||||
GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr;
|
||||
DWORD bytes_read;
|
||||
|
||||
if (!ReadFile (self->file_handle, output_data, bytes_to_read, &bytes_read, NULL))
|
||||
{
|
||||
DWORD error = GetLastError ();
|
||||
return __HRESULT_FROM_WIN32 (error);
|
||||
}
|
||||
|
||||
if (output_bytes_read)
|
||||
*output_bytes_read = bytes_read;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_write (IStream *self_ptr,
|
||||
const void *data,
|
||||
ULONG bytes_to_write,
|
||||
ULONG *output_bytes_written)
|
||||
{
|
||||
GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr;
|
||||
DWORD bytes_written;
|
||||
|
||||
if (!WriteFile (self->file_handle, data, bytes_to_write, &bytes_written, NULL))
|
||||
{
|
||||
DWORD error = GetLastError ();
|
||||
return __HRESULT_FROM_WIN32 (error);
|
||||
}
|
||||
|
||||
if (output_bytes_written)
|
||||
*output_bytes_written = bytes_written;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_seek (IStream *self_ptr,
|
||||
LARGE_INTEGER move_distance,
|
||||
DWORD origin,
|
||||
ULARGE_INTEGER *output_new_position)
|
||||
{
|
||||
GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr;
|
||||
LARGE_INTEGER new_position;
|
||||
DWORD move_method;
|
||||
|
||||
switch (origin)
|
||||
{
|
||||
case STREAM_SEEK_SET:
|
||||
move_method = FILE_BEGIN;
|
||||
break;
|
||||
case STREAM_SEEK_CUR:
|
||||
move_method = FILE_CURRENT;
|
||||
break;
|
||||
case STREAM_SEEK_END:
|
||||
move_method = FILE_END;
|
||||
break;
|
||||
default:
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (!SetFilePointerEx (self->file_handle, move_distance, &new_position, move_method))
|
||||
{
|
||||
DWORD error = GetLastError ();
|
||||
return __HRESULT_FROM_WIN32 (error);
|
||||
}
|
||||
|
||||
(*output_new_position).QuadPart = new_position.QuadPart;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_set_size (IStream *self_ptr,
|
||||
ULARGE_INTEGER new_size)
|
||||
{
|
||||
GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr;
|
||||
FILE_END_OF_FILE_INFO info;
|
||||
|
||||
info.EndOfFile.QuadPart = new_size.QuadPart;
|
||||
|
||||
if (SetFileInformationByHandle (self->file_handle, FileEndOfFileInfo, &info, sizeof (info)))
|
||||
{
|
||||
DWORD error = GetLastError ();
|
||||
return __HRESULT_FROM_WIN32 (error);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_copy_to (IStream *self_ptr,
|
||||
IStream *output_stream,
|
||||
ULARGE_INTEGER bytes_to_copy,
|
||||
ULARGE_INTEGER *output_bytes_read,
|
||||
ULARGE_INTEGER *output_bytes_written)
|
||||
{
|
||||
ULARGE_INTEGER counter;
|
||||
ULARGE_INTEGER written_counter;
|
||||
ULARGE_INTEGER read_counter;
|
||||
|
||||
counter.QuadPart = bytes_to_copy.QuadPart;
|
||||
written_counter.QuadPart = 0;
|
||||
read_counter.QuadPart = 0;
|
||||
|
||||
while (counter.QuadPart > 0)
|
||||
{
|
||||
HRESULT hr;
|
||||
ULONG bytes_read;
|
||||
ULONG bytes_written;
|
||||
ULONG bytes_index;
|
||||
#define _INTERNAL_BUFSIZE 1024
|
||||
BYTE buffer[_INTERNAL_BUFSIZE];
|
||||
#undef _INTERNAL_BUFSIZE
|
||||
ULONG buffer_size = sizeof (buffer);
|
||||
ULONG to_read = buffer_size;
|
||||
|
||||
if (counter.QuadPart < buffer_size)
|
||||
to_read = (ULONG) counter.QuadPart;
|
||||
|
||||
/* Because MS SDK has a function IStream_Read() with 3 arguments */
|
||||
hr = self_ptr->lpVtbl->Read (self_ptr, buffer, to_read, &bytes_read);
|
||||
if (!SUCCEEDED (hr))
|
||||
return hr;
|
||||
|
||||
read_counter.QuadPart += bytes_read;
|
||||
|
||||
if (bytes_read == 0)
|
||||
break;
|
||||
|
||||
bytes_index = 0;
|
||||
|
||||
while (bytes_index < bytes_read)
|
||||
{
|
||||
/* Because MS SDK has a function IStream_Write() with 3 arguments */
|
||||
hr = output_stream->lpVtbl->Write (output_stream, &buffer[bytes_index], bytes_read - bytes_index, &bytes_written);
|
||||
if (!SUCCEEDED (hr))
|
||||
return hr;
|
||||
|
||||
if (bytes_written == 0)
|
||||
return __HRESULT_FROM_WIN32 (ERROR_WRITE_FAULT);
|
||||
|
||||
bytes_index += bytes_written;
|
||||
written_counter.QuadPart += bytes_written;
|
||||
}
|
||||
}
|
||||
|
||||
if (output_bytes_read)
|
||||
output_bytes_read->QuadPart = read_counter.QuadPart;
|
||||
if (output_bytes_written)
|
||||
output_bytes_written->QuadPart = written_counter.QuadPart;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_commit (IStream *self_ptr,
|
||||
DWORD commit_flags)
|
||||
{
|
||||
GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr;
|
||||
|
||||
if (!FlushFileBuffers (self->file_handle))
|
||||
{
|
||||
DWORD error = GetLastError ();
|
||||
return __HRESULT_FROM_WIN32 (error);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_revert (IStream *self_ptr)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_lock_region (IStream *self_ptr,
|
||||
ULARGE_INTEGER lock_offset,
|
||||
ULARGE_INTEGER lock_bytes,
|
||||
DWORD lock_type)
|
||||
{
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_unlock_region (IStream *self_ptr,
|
||||
ULARGE_INTEGER lock_offset,
|
||||
ULARGE_INTEGER lock_bytes,
|
||||
DWORD lock_type)
|
||||
{
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_stat (IStream *self_ptr,
|
||||
STATSTG *output_stat,
|
||||
DWORD flags)
|
||||
{
|
||||
GWin32FileSyncStream *self = (GWin32FileSyncStream *) self_ptr;
|
||||
BOOL get_name = FALSE;
|
||||
FILE_BASIC_INFO bi;
|
||||
FILE_STANDARD_INFO si;
|
||||
|
||||
if (output_stat == NULL)
|
||||
return STG_E_INVALIDPOINTER;
|
||||
|
||||
switch (flags)
|
||||
{
|
||||
case STATFLAG_DEFAULT:
|
||||
get_name = TRUE;
|
||||
break;
|
||||
case STATFLAG_NONAME:
|
||||
get_name = FALSE;
|
||||
break;
|
||||
default:
|
||||
return STG_E_INVALIDFLAG;
|
||||
}
|
||||
|
||||
if (!GetFileInformationByHandleEx (self->file_handle, FileBasicInfo, &bi, sizeof (bi)) ||
|
||||
!GetFileInformationByHandleEx (self->file_handle, FileStandardInfo, &si, sizeof (si)))
|
||||
{
|
||||
DWORD error = GetLastError ();
|
||||
return __HRESULT_FROM_WIN32 (error);
|
||||
}
|
||||
|
||||
output_stat->type = STGTY_STREAM;
|
||||
output_stat->mtime.dwLowDateTime = bi.LastWriteTime.LowPart;
|
||||
output_stat->mtime.dwHighDateTime = bi.LastWriteTime.HighPart;
|
||||
output_stat->ctime.dwLowDateTime = bi.CreationTime.LowPart;
|
||||
output_stat->ctime.dwHighDateTime = bi.CreationTime.HighPart;
|
||||
output_stat->atime.dwLowDateTime = bi.LastAccessTime.LowPart;
|
||||
output_stat->atime.dwHighDateTime = bi.LastAccessTime.HighPart;
|
||||
output_stat->grfLocksSupported = 0;
|
||||
memset (&output_stat->clsid, 0, sizeof (CLSID));
|
||||
output_stat->grfStateBits = 0;
|
||||
output_stat->reserved = 0;
|
||||
output_stat->cbSize.QuadPart = si.EndOfFile.QuadPart;
|
||||
output_stat->grfMode = self->stgm_mode;
|
||||
|
||||
if (get_name)
|
||||
{
|
||||
DWORD tries;
|
||||
wchar_t *buffer;
|
||||
|
||||
/* Nothing in the documentation guarantees that the name
|
||||
* won't change between two invocations (one - to get the
|
||||
* buffer size, the other - to fill the buffer).
|
||||
* Re-try up to 5 times in case the required buffer size
|
||||
* doesn't match.
|
||||
*/
|
||||
for (tries = 5; tries > 0; tries--)
|
||||
{
|
||||
DWORD buffer_size;
|
||||
DWORD buffer_size2;
|
||||
DWORD error;
|
||||
|
||||
buffer_size = GetFinalPathNameByHandleW (self->file_handle, NULL, 0, 0);
|
||||
|
||||
if (buffer_size == 0)
|
||||
{
|
||||
DWORD error = GetLastError ();
|
||||
return __HRESULT_FROM_WIN32 (error);
|
||||
}
|
||||
|
||||
buffer = CoTaskMemAlloc (buffer_size);
|
||||
buffer[buffer_size - 1] = 0;
|
||||
buffer_size2 = GetFinalPathNameByHandleW (self->file_handle, buffer, buffer_size, 0);
|
||||
|
||||
if (buffer_size2 < buffer_size)
|
||||
break;
|
||||
|
||||
error = GetLastError ();
|
||||
CoTaskMemFree (buffer);
|
||||
if (buffer_size2 == 0)
|
||||
return __HRESULT_FROM_WIN32 (error);
|
||||
}
|
||||
|
||||
if (tries == 0)
|
||||
return __HRESULT_FROM_WIN32 (ERROR_BAD_LENGTH);
|
||||
|
||||
output_stat->pwcsName = buffer;
|
||||
}
|
||||
else
|
||||
output_stat->pwcsName = NULL;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
_file_sync_stream_clone (IStream *self_ptr,
|
||||
IStream **output_clone_ptr)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static IStreamVtbl _file_sync_stream_vtbl = {
|
||||
_file_sync_stream_query_interface,
|
||||
_file_sync_stream_add_ref,
|
||||
_file_sync_stream_release,
|
||||
_file_sync_stream_read,
|
||||
_file_sync_stream_write,
|
||||
_file_sync_stream_seek,
|
||||
_file_sync_stream_set_size,
|
||||
_file_sync_stream_copy_to,
|
||||
_file_sync_stream_commit,
|
||||
_file_sync_stream_revert,
|
||||
_file_sync_stream_lock_region,
|
||||
_file_sync_stream_unlock_region,
|
||||
_file_sync_stream_stat,
|
||||
_file_sync_stream_clone,
|
||||
};
|
||||
|
||||
static void
|
||||
_file_sync_stream_free (GWin32FileSyncStream *self)
|
||||
{
|
||||
if (self->owns_handle)
|
||||
CloseHandle (self->file_handle);
|
||||
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_win32_file_sync_stream_new:
|
||||
* @handle: a Win32 HANDLE for a file.
|
||||
* @owns_handle: %TRUE if newly-created stream owns the handle
|
||||
* (and closes it when destroyed)
|
||||
* @stgm_mode: a combination of [STGM constants](https://docs.microsoft.com/en-us/windows/win32/stg/stgm-constants)
|
||||
* that specify the mode with which the stream
|
||||
* is opened.
|
||||
* @output_hresult: (out) (optional): a HRESULT from the internal COM calls.
|
||||
* Will be `S_OK` on success.
|
||||
*
|
||||
* Creates an IStream object backed by a HANDLE.
|
||||
*
|
||||
* @stgm_mode should match the mode of the @handle, otherwise the stream might
|
||||
* attempt to perform operations that the @handle does not allow. The implementation
|
||||
* itself ignores these flags completely, they are only used to report
|
||||
* the mode of the stream to third parties.
|
||||
*
|
||||
* The stream only does synchronous access and will never return `E_PENDING` on I/O.
|
||||
*
|
||||
* The returned stream object should be treated just like any other
|
||||
* COM object, and released via `IUnknown_Release()`.
|
||||
* its elements have been unreffed with g_object_unref().
|
||||
*
|
||||
* Returns: (nullable) (transfer full): a new IStream object on success, %NULL on failure.
|
||||
**/
|
||||
IStream *
|
||||
g_win32_file_sync_stream_new (HANDLE file_handle,
|
||||
gboolean owns_handle,
|
||||
DWORD stgm_mode,
|
||||
HRESULT *output_hresult)
|
||||
{
|
||||
GWin32FileSyncStream *new_stream;
|
||||
IStream *result;
|
||||
HRESULT hr;
|
||||
|
||||
new_stream = g_new0 (GWin32FileSyncStream, 1);
|
||||
new_stream->self.lpVtbl = &_file_sync_stream_vtbl;
|
||||
|
||||
hr = IUnknown_QueryInterface ((IUnknown *) new_stream, &IID_IStream, (void **) &result);
|
||||
if (!SUCCEEDED (hr))
|
||||
{
|
||||
g_free (new_stream);
|
||||
|
||||
if (output_hresult)
|
||||
*output_hresult = hr;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_stream->stgm_mode = stgm_mode;
|
||||
new_stream->file_handle = file_handle;
|
||||
new_stream->owns_handle = owns_handle;
|
||||
|
||||
if (output_hresult)
|
||||
*output_hresult = S_OK;
|
||||
|
||||
return result;
|
||||
}
|
44
gio/gwin32file-sync-stream.h
Executable file
44
gio/gwin32file-sync-stream.h
Executable file
@ -0,0 +1,44 @@
|
||||
/* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright (C) 2020 Руслан Ижбулатов <lrn1986@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef __G_WIN32_FILE_SYNC_STREAM_H__
|
||||
#define __G_WIN32_FILE_SYNC_STREAM_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
|
||||
typedef struct _GWin32FileSyncStream GWin32FileSyncStream;
|
||||
|
||||
struct _GWin32FileSyncStream
|
||||
{
|
||||
IStream self;
|
||||
ULONG ref_count;
|
||||
HANDLE file_handle;
|
||||
gboolean owns_handle;
|
||||
DWORD stgm_mode;
|
||||
};
|
||||
|
||||
IStream *g_win32_file_sync_stream_new (HANDLE file_handle,
|
||||
gboolean owns_handle,
|
||||
DWORD stgm_mode,
|
||||
HRESULT *output_hresult);
|
||||
|
||||
#endif /* G_PLATFORM_WIN32 */
|
||||
|
||||
#endif /* __G_WIN32_FILE_SYNC_STREAM_H__ */
|
815
gio/gwin32packageparser.c
Executable file
815
gio/gwin32packageparser.c
Executable file
@ -0,0 +1,815 @@
|
||||
/* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright (C) 2020 Руслан Ижбулатов <lrn1986@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Queries the system (Windows 8 or newer) for the list
|
||||
* of UWP packages, parses their manifests and invokes
|
||||
* a user-provided callback with the needed application
|
||||
* info.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define COBJMACROS
|
||||
#define INITGUID
|
||||
#include <windows.h>
|
||||
#include <winstring.h>
|
||||
#include <roapi.h>
|
||||
#include <stdio.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
#include "gwin32api-storage.h"
|
||||
#include "gwin32api-misc.h"
|
||||
#include "gwin32api-iterator.h"
|
||||
#include "gwin32api-package.h"
|
||||
|
||||
#include <xmllite.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "gwin32file-sync-stream.h"
|
||||
#include "gwin32packageparser.h"
|
||||
|
||||
#ifdef G_WINAPI_ONLY_APP
|
||||
#define LoadedRoActivateInstance RoActivateInstance
|
||||
#define LoadedWindowsCreateStringReference WindowsCreateStringReference
|
||||
#define LoadedWindowsDeleteString WindowsDeleteString
|
||||
#define sax_WindowsGetStringRawBuffer WindowsGetStringRawBuffer
|
||||
#define LoadedWindowsGetStringRawBuffer WindowsGetStringRawBuffer
|
||||
#define sax_CreateXmlReader CreateXmlReader
|
||||
#else
|
||||
typedef HRESULT (WINAPI *RoActivateInstance_func)(HSTRING activatableClassId, IInspectable **instance);
|
||||
typedef HRESULT (WINAPI *WindowsCreateStringReference_func)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING *string);
|
||||
typedef HRESULT (WINAPI *WindowsDeleteString_func)(HSTRING string);
|
||||
typedef PCWSTR (WINAPI *WindowsGetStringRawBuffer_func)(HSTRING string, UINT32 *length);
|
||||
typedef HRESULT (STDAPICALLTYPE *CreateXmlReader_func)(REFIID riid, void **ppvObject, IMalloc *pMalloc);
|
||||
#define sax_WindowsGetStringRawBuffer sax->WindowsGetStringRawBuffer
|
||||
#define sax_CreateXmlReader sax->CreateXmlReader
|
||||
#endif
|
||||
|
||||
static gssize
|
||||
g_utf16_len (const gunichar2 *str)
|
||||
{
|
||||
gssize result;
|
||||
|
||||
for (result = 0; str[0] != 0; str++, result++)
|
||||
;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gunichar2 *
|
||||
g_wcsdup (const gunichar2 *str, gssize str_len)
|
||||
{
|
||||
gssize str_size;
|
||||
|
||||
g_return_val_if_fail (str != NULL, NULL);
|
||||
|
||||
if (str_len == -1)
|
||||
str_len = g_utf16_len (str);
|
||||
|
||||
g_assert (str_len <= G_MAXSIZE / sizeof (gunichar2) - 1);
|
||||
str_size = (str_len + 1) * sizeof (gunichar2);
|
||||
|
||||
return g_memdup (str, str_size);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
WIN32_FROM_HRESULT (HRESULT hresult,
|
||||
DWORD *win32_error_code)
|
||||
{
|
||||
if ((hresult & 0xFFFF0000) == MAKE_HRESULT (SEVERITY_ERROR, FACILITY_WIN32, 0) ||
|
||||
hresult == S_OK)
|
||||
{
|
||||
*win32_error_code = HRESULT_CODE (hresult);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GIOErrorEnum
|
||||
gio_error_from_hresult (HRESULT hresult)
|
||||
{
|
||||
DWORD error;
|
||||
|
||||
if (WIN32_FROM_HRESULT (hresult, &error))
|
||||
return g_io_error_from_errno (error);
|
||||
|
||||
return G_IO_ERROR_FAILED;
|
||||
}
|
||||
|
||||
static void
|
||||
free_extgroup (GWin32PackageExtGroup *g)
|
||||
{
|
||||
g_ptr_array_unref (g->verbs);
|
||||
g_ptr_array_unref (g->extensions);
|
||||
g_free (g);
|
||||
}
|
||||
|
||||
struct _xml_sax_state
|
||||
{
|
||||
#ifndef G_WINAPI_ONLY_APP
|
||||
WindowsGetStringRawBuffer_func WindowsGetStringRawBuffer;
|
||||
CreateXmlReader_func CreateXmlReader;
|
||||
#endif
|
||||
|
||||
GWin32PackageParserCallback callback;
|
||||
gpointer user_data;
|
||||
|
||||
const wchar_t *manifest_filename;
|
||||
gsize package_index;
|
||||
const wchar_t *wcs_full_name;
|
||||
const wchar_t *wcs_name;
|
||||
HSTRING package_family;
|
||||
|
||||
gboolean applist;
|
||||
gboolean exit_early;
|
||||
|
||||
UINT64 in_package;
|
||||
UINT64 in_applications;
|
||||
UINT64 in_application;
|
||||
UINT64 in_extensions;
|
||||
UINT64 in_extension_protocol;
|
||||
UINT64 in_extension_fta;
|
||||
UINT64 in_fta_group;
|
||||
UINT64 in_sfp;
|
||||
UINT64 in_filetype;
|
||||
UINT64 in_sv;
|
||||
GPtrArray *supported_extensions;
|
||||
GPtrArray *supported_protocols;
|
||||
GPtrArray *supported_verbs;
|
||||
GPtrArray *supported_extgroups;
|
||||
wchar_t *application_usermodelid;
|
||||
};
|
||||
|
||||
static gboolean parse_manifest_file (struct _xml_sax_state *sax);
|
||||
static gboolean xml_parser_iteration (struct _xml_sax_state *sax,
|
||||
IXmlReader *xml_reader);
|
||||
static gboolean xml_parser_get_current_state (struct _xml_sax_state *sax,
|
||||
IXmlReader *xml_reader,
|
||||
const wchar_t **local_name,
|
||||
const wchar_t **prefix,
|
||||
const wchar_t **value);
|
||||
|
||||
gboolean
|
||||
g_win32_package_parser_enum_packages (GWin32PackageParserCallback callback,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
gboolean result = TRUE;
|
||||
HRESULT hr;
|
||||
HSTRING packagemanager_name = NULL;
|
||||
HSTRING_HEADER packageanager_name_header;
|
||||
const wchar_t *packman_id = L"Windows.Management.Deployment.PackageManager";
|
||||
IInspectable *ii_pm = NULL;
|
||||
IPackageManager *pm = NULL;
|
||||
IIterable *packages_iterable = NULL;
|
||||
IIterator *packages_iterator = NULL;
|
||||
CHAR has_current;
|
||||
gsize package_index;
|
||||
const wchar_t *bslash_appmanifest = L"\\AppxManifest.xml";
|
||||
struct _xml_sax_state sax_stack;
|
||||
struct _xml_sax_state *sax = &sax_stack;
|
||||
|
||||
#ifndef G_WINAPI_ONLY_APP
|
||||
HMODULE xmllite = NULL;
|
||||
HMODULE combase = NULL;
|
||||
HMODULE winrt = NULL;
|
||||
RoActivateInstance_func LoadedRoActivateInstance;
|
||||
WindowsCreateStringReference_func LoadedWindowsCreateStringReference;
|
||||
WindowsDeleteString_func LoadedWindowsDeleteString;
|
||||
WindowsGetStringRawBuffer_func LoadedWindowsGetStringRawBuffer;
|
||||
CreateXmlReader_func LoadedCreateXmlReader;
|
||||
|
||||
winrt = LoadLibraryW (L"api-ms-win-core-winrt-l1-1-0.dll");
|
||||
if (winrt == NULL)
|
||||
{
|
||||
result = FALSE;
|
||||
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
|
||||
"Failed to load api-ms-win-core-winrt-l1-1-0.dll");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
combase = LoadLibraryW (L"combase.dll");
|
||||
if (combase == NULL)
|
||||
{
|
||||
result = FALSE;
|
||||
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
|
||||
"Failed to load combase.dll");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
xmllite = LoadLibraryW (L"xmllite.dll");
|
||||
if (xmllite == NULL)
|
||||
{
|
||||
result = FALSE;
|
||||
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
|
||||
"Failed to load xmllite.dll");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
LoadedCreateXmlReader = (CreateXmlReader_func) GetProcAddress (xmllite, "CreateXmlReader");
|
||||
if (LoadedCreateXmlReader == NULL)
|
||||
{
|
||||
result = FALSE;
|
||||
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
|
||||
"CreateXmlReader entry point is not found in xmllite.dll");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
LoadedRoActivateInstance = (RoActivateInstance_func) GetProcAddress (winrt, "RoActivateInstance");
|
||||
if (LoadedRoActivateInstance == NULL)
|
||||
{
|
||||
result = FALSE;
|
||||
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
|
||||
"RoActivateInstance entry point is not found in api-ms-win-core-winrt-l1-1-0.dll");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
LoadedWindowsCreateStringReference = (WindowsCreateStringReference_func) GetProcAddress (combase, "WindowsCreateStringReference");
|
||||
if (LoadedWindowsCreateStringReference == NULL)
|
||||
{
|
||||
result = FALSE;
|
||||
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
|
||||
"WindowsCreateStringReference entry point is not found in combase.dll");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
LoadedWindowsDeleteString = (WindowsDeleteString_func) GetProcAddress (combase, "WindowsDeleteString");
|
||||
if (LoadedWindowsDeleteString == NULL)
|
||||
{
|
||||
result = FALSE;
|
||||
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
|
||||
"WindowsDeleteString entry point is not found in combase.dll");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
LoadedWindowsGetStringRawBuffer = (WindowsGetStringRawBuffer_func) GetProcAddress (combase, "WindowsGetStringRawBuffer");
|
||||
if (LoadedWindowsGetStringRawBuffer == NULL)
|
||||
{
|
||||
result = FALSE;
|
||||
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
|
||||
"WindowsGetStringRawBuffer entry point is not found in combase.dll");
|
||||
goto cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This essentially locks current GLib thread into apartment COM model. */
|
||||
hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
|
||||
/* Can return S_FALSE if COM is already initialized,
|
||||
* which is not an error, and we still need to uninitialize after that.
|
||||
*/
|
||||
if (hr != S_OK && hr != S_FALSE)
|
||||
{
|
||||
result = FALSE;
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
|
||||
"CoInitializeEx(COINIT_APARTMENTTHREADED) failed with code 0x%lx", hr);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#define canned_com_error_handler(function_name_literal, where_to_go) \
|
||||
do \
|
||||
{ \
|
||||
if (FAILED (hr)) \
|
||||
{ \
|
||||
result = FALSE; \
|
||||
g_set_error (error, G_IO_ERROR, gio_error_from_hresult (hr), \
|
||||
function_name_literal " failed with code 0x%lx", hr); \
|
||||
goto where_to_go; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
hr = LoadedWindowsCreateStringReference (packman_id, wcslen (packman_id), &packageanager_name_header, &packagemanager_name);
|
||||
canned_com_error_handler ("WindowsCreateStringReference()", cleanup);
|
||||
|
||||
hr = LoadedRoActivateInstance (packagemanager_name, &ii_pm);
|
||||
canned_com_error_handler ("RoActivateInstance()", cleanup);
|
||||
|
||||
hr = IInspectable_QueryInterface (ii_pm, &IID_IPackageManager, (void**) &pm);
|
||||
canned_com_error_handler ("IInspectable_QueryInterface()", cleanup);
|
||||
|
||||
hr = IPackageManager_FindPackagesByUserSecurityId (pm, 0, &packages_iterable);
|
||||
canned_com_error_handler ("IPackageManager_FindPackagesByUserSecurityId()", cleanup);
|
||||
|
||||
hr = IIterable_First (packages_iterable, &packages_iterator);
|
||||
canned_com_error_handler ("IIterable_First()", cleanup);
|
||||
|
||||
hr = IIterator_get_HasCurrent (packages_iterator, &has_current);
|
||||
canned_com_error_handler ("IIterator_get_HasCurrent()", cleanup);
|
||||
|
||||
for (package_index = 0; SUCCEEDED (hr) && has_current; package_index++)
|
||||
{
|
||||
IUnknown *item = NULL;
|
||||
IPackage *ipackage = NULL;
|
||||
IPackageId *ipackageid = NULL;
|
||||
IUnknown *package_install_location = NULL;
|
||||
IStorageItem *storage_item = NULL;
|
||||
HSTRING path = NULL;
|
||||
HSTRING name = NULL;
|
||||
HSTRING full_name = NULL;
|
||||
HSTRING package_family = NULL;
|
||||
size_t manifest_filename_size;
|
||||
const wchar_t *wcs_path;
|
||||
const wchar_t *wcs_full_name;
|
||||
const wchar_t *wcs_name;
|
||||
wchar_t *manifest_filename = NULL;
|
||||
|
||||
#define canned_com_error_handler_pkg(function_name_literal, where_to_go) \
|
||||
do \
|
||||
{ \
|
||||
if (FAILED (hr)) \
|
||||
{ \
|
||||
result = FALSE; \
|
||||
g_set_error (error, G_IO_ERROR, gio_error_from_hresult (hr), \
|
||||
function_name_literal " for package #%zu failed with code 0x%lx", package_index, hr); \
|
||||
goto where_to_go; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
hr = IIterator_get_Current (packages_iterator, &item);
|
||||
canned_com_error_handler_pkg ("IIterator_get_Current()", package_cleanup);
|
||||
|
||||
hr = IUnknown_QueryInterface (item, &IID_IPackage, (void **) &ipackage);
|
||||
canned_com_error_handler_pkg ("IUnknown_QueryInterface(IID_IPackage)", package_cleanup);
|
||||
|
||||
hr = IPackage_get_Id (ipackage, &ipackageid);
|
||||
canned_com_error_handler_pkg ("IPackage_get_Id()", package_cleanup);
|
||||
|
||||
hr = IPackageId_get_FullName (ipackageid, &full_name);
|
||||
canned_com_error_handler_pkg ("IPackageId_get_FullName()", package_cleanup);
|
||||
|
||||
hr = IPackageId_get_Name (ipackageid, &name);
|
||||
canned_com_error_handler_pkg ("IPackageId_get_Name()", package_cleanup);
|
||||
|
||||
wcs_full_name = LoadedWindowsGetStringRawBuffer (full_name, NULL);
|
||||
wcs_name = LoadedWindowsGetStringRawBuffer (name, NULL);
|
||||
|
||||
#define canned_com_error_handler_pkg_named(function_name_literal, where_to_go) \
|
||||
do \
|
||||
{ \
|
||||
if (FAILED (hr)) \
|
||||
{ \
|
||||
result = FALSE; \
|
||||
g_set_error (error, G_IO_ERROR, gio_error_from_hresult (hr), \
|
||||
function_name_literal " for package #%zu (`%S') failed with code 0x%lx", package_index, wcs_full_name, hr); \
|
||||
goto where_to_go; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
hr = IPackage_get_InstalledLocation (ipackage, &package_install_location);
|
||||
canned_com_error_handler_pkg_named ("IPackage_get_InstalledLocation()", package_cleanup);
|
||||
|
||||
hr = IUnknown_QueryInterface (package_install_location, &IID_IStorageItem, (void **) &storage_item);
|
||||
canned_com_error_handler_pkg_named ("IUnknown_QueryInterface(IID_IStorageItem)", package_cleanup);
|
||||
|
||||
hr = IPackageId_get_FamilyName (ipackageid, &package_family);
|
||||
canned_com_error_handler_pkg_named ("IPackageId_get_FamilyName()", package_cleanup);
|
||||
|
||||
hr = IStorageItem_get_Path (storage_item, &path);
|
||||
canned_com_error_handler_pkg_named ("IStorageItem_get_Path()", package_cleanup);
|
||||
|
||||
wcs_path = LoadedWindowsGetStringRawBuffer (path, NULL);
|
||||
manifest_filename_size = wcslen (wcs_path) + wcslen (bslash_appmanifest);
|
||||
manifest_filename = g_new (wchar_t, manifest_filename_size + 1);
|
||||
memcpy (manifest_filename, wcs_path, manifest_filename_size * sizeof (wchar_t));
|
||||
memcpy (&manifest_filename[wcslen (wcs_path)], bslash_appmanifest, (wcslen (bslash_appmanifest) + 1) * sizeof (wchar_t));
|
||||
|
||||
memset (sax, 0, sizeof (*sax));
|
||||
sax->callback = callback;
|
||||
sax->user_data = user_data;
|
||||
sax->manifest_filename = manifest_filename;
|
||||
sax->package_index = package_index;
|
||||
sax->wcs_full_name = wcs_full_name;
|
||||
sax->wcs_name = wcs_name;
|
||||
sax->package_family = package_family;
|
||||
sax->applist = TRUE;
|
||||
sax->exit_early = FALSE;
|
||||
#ifndef G_WINAPI_ONLY_APP
|
||||
sax->CreateXmlReader = LoadedCreateXmlReader;
|
||||
sax->WindowsGetStringRawBuffer = LoadedWindowsGetStringRawBuffer;
|
||||
#endif
|
||||
/* Result isn't checked. If we fail to parse the manifest,
|
||||
* just try the next package, no need to bail out.
|
||||
*/
|
||||
parse_manifest_file (sax);
|
||||
|
||||
hr = IIterator_MoveNext (packages_iterator, &has_current);
|
||||
canned_com_error_handler_pkg_named ("IIterator_MoveNext()", package_cleanup);
|
||||
|
||||
#undef canned_com_error_handler_pkg_named
|
||||
#undef canned_com_error_handler_pkg
|
||||
#undef canned_com_error_handler
|
||||
|
||||
package_cleanup:
|
||||
g_clear_pointer (&manifest_filename, g_free);
|
||||
|
||||
if (path)
|
||||
LoadedWindowsDeleteString (path);
|
||||
if (storage_item)
|
||||
(void) IStorageItem_Release (storage_item);
|
||||
if (package_install_location)
|
||||
(void) IUnknown_Release (package_install_location);
|
||||
if (ipackage)
|
||||
(void) IPackage_Release (ipackage);
|
||||
if (item)
|
||||
(void) IUnknown_Release (item);
|
||||
|
||||
if (package_family)
|
||||
LoadedWindowsDeleteString (package_family);
|
||||
if (name)
|
||||
LoadedWindowsDeleteString (name);
|
||||
if (full_name)
|
||||
LoadedWindowsDeleteString (full_name);
|
||||
|
||||
if (ipackageid)
|
||||
(void) IPackageId_Release (ipackageid);
|
||||
if (sax->exit_early)
|
||||
break;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (packages_iterator)
|
||||
(void) IIterator_Release (packages_iterator);
|
||||
if (packages_iterable)
|
||||
(void) IIterable_Release (packages_iterable);
|
||||
if (pm)
|
||||
(void) IPackageManager_Release (pm);
|
||||
if (ii_pm)
|
||||
(void) IInspectable_Release (ii_pm);
|
||||
|
||||
CoUninitialize ();
|
||||
|
||||
#ifndef G_WINAPI_ONLY_APP
|
||||
if (xmllite)
|
||||
(void) FreeLibrary (xmllite);
|
||||
if (combase)
|
||||
(void) FreeLibrary (combase);
|
||||
if (winrt)
|
||||
(void) FreeLibrary (winrt);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_manifest_file (struct _xml_sax_state *sax)
|
||||
{
|
||||
HRESULT hr;
|
||||
HANDLE file_handle = INVALID_HANDLE_VALUE;
|
||||
IStream *file_stream = NULL;
|
||||
gboolean result;
|
||||
IXmlReader *xml_reader;
|
||||
|
||||
file_handle = CreateFileW (sax->manifest_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
g_warning ("Failed to open application manifest `%S' for package #%zu (`%S'): error code 0x%lx",
|
||||
sax->manifest_filename, sax->package_index, sax->wcs_full_name, GetLastError ());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
file_stream = g_win32_file_sync_stream_new (file_handle, TRUE, STGM_READ | STGM_SHARE_DENY_WRITE, &hr);
|
||||
if (file_stream == NULL)
|
||||
{
|
||||
g_warning ("Failed to create an IStream for application manifest `%S' for package #%zu (`%S'): HRESULT 0x%lx",
|
||||
sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr);
|
||||
CloseHandle (file_handle);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* file_stream owns it now */
|
||||
file_handle = NULL;
|
||||
|
||||
hr = sax_CreateXmlReader (&IID_IXmlReader, (void **) &xml_reader, NULL);
|
||||
/* Slightly incorrect - xml reader is not created for any particular file,
|
||||
* in theory we could re-use the same xml reader instance for all files.
|
||||
*/
|
||||
if (FAILED (hr))
|
||||
{
|
||||
g_warning ("CreateXmlReader() for application manifest `%S' for package #%zu (`%S') failed with HRESULT 0x%lx",
|
||||
sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr);
|
||||
(void) IStream_Release (file_stream);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IXmlReader_SetInput (xml_reader, (IUnknown *) file_stream);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
g_warning ("IXmlReader_SetInput() for application manifest `%S' for package #%zu (`%S') failed with HRESULT 0x%lx",
|
||||
sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr);
|
||||
(void) IXmlReader_Release (xml_reader);
|
||||
(void) IStream_Release (file_stream);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sax->supported_extensions = g_ptr_array_new_full (0, (GDestroyNotify) g_free);
|
||||
sax->supported_protocols = g_ptr_array_new_full (0, (GDestroyNotify) g_free);
|
||||
sax->supported_verbs = g_ptr_array_new_full (0, (GDestroyNotify) g_free);
|
||||
sax->supported_extgroups = g_ptr_array_new_full (0, (GDestroyNotify) free_extgroup);
|
||||
|
||||
result = TRUE;
|
||||
|
||||
while (!sax->exit_early && result && !IXmlReader_IsEOF (xml_reader))
|
||||
result = xml_parser_iteration (sax, xml_reader);
|
||||
|
||||
g_clear_pointer (&sax->application_usermodelid, g_free);
|
||||
g_clear_pointer (&sax->supported_extensions, g_ptr_array_unref);
|
||||
g_clear_pointer (&sax->supported_verbs, g_ptr_array_unref);
|
||||
g_clear_pointer (&sax->supported_extgroups, g_ptr_array_unref);
|
||||
g_clear_pointer (&sax->supported_protocols, g_ptr_array_unref);
|
||||
|
||||
(void) IXmlReader_Release (xml_reader);
|
||||
(void) IStream_Release (file_stream);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
xml_parser_get_current_state (struct _xml_sax_state *sax,
|
||||
IXmlReader *xml_reader,
|
||||
const wchar_t **local_name,
|
||||
const wchar_t **prefix,
|
||||
const wchar_t **value)
|
||||
{
|
||||
HRESULT hr;
|
||||
UINT xml_line_number;
|
||||
UINT xml_line_position;
|
||||
|
||||
hr = IXmlReader_GetLineNumber (xml_reader, &xml_line_number);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
g_warning ("IXmlReader_GetLineNumber() for application manifest `%S' for package #%zu (`%S') failed with HRESULT 0x%lx",
|
||||
sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IXmlReader_GetLinePosition (xml_reader, &xml_line_position);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
g_warning ("IXmlReader_GetLinePosition() for application manifest `%S' for package #%zu (`%S') failed with HRESULT 0x%lx",
|
||||
sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IXmlReader_GetLocalName (xml_reader, local_name, NULL);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
g_warning ("IXmlReader_GetLocalName() for application manifest `%S':%u (column %u) for package #%zu (`%S') failed with HRESULT 0x%lx",
|
||||
sax->manifest_filename, xml_line_number, xml_line_position, sax->package_index, sax->wcs_full_name, hr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IXmlReader_GetPrefix (xml_reader, prefix, NULL);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
g_warning ("IXmlReader_GetPrefix() for application manifest `%S':%u (column %u) for package #%zu (`%S') failed with HRESULT 0x%lx",
|
||||
sax->manifest_filename, xml_line_number, xml_line_position, sax->package_index, sax->wcs_full_name, hr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hr = IXmlReader_GetValue (xml_reader, value, NULL);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
g_warning ("IXmlReader_GetValue() for application manifest `%S':%u (column %u) for package #%zu (`%S') failed with HRESULT 0x%lx",
|
||||
sax->manifest_filename, xml_line_number, xml_line_position, sax->package_index, sax->wcs_full_name, hr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
xml_parser_iteration (struct _xml_sax_state *sax,
|
||||
IXmlReader *xml_reader)
|
||||
{
|
||||
HRESULT hr;
|
||||
XmlNodeType xml_node_type;
|
||||
const wchar_t *local_name;
|
||||
const wchar_t *prefix;
|
||||
const wchar_t *value;
|
||||
BOOL is_visual_elements = FALSE;
|
||||
BOOL is_extension = FALSE;
|
||||
BOOL is_protocol = FALSE;
|
||||
BOOL is_empty;
|
||||
BOOL is_application = FALSE;
|
||||
BOOL is_verb = FALSE;
|
||||
|
||||
hr = IXmlReader_Read (xml_reader, &xml_node_type);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
g_warning ("IXmlReader_Read() for application manifest `%S' for package #%zu (`%S') failed with HRESULT 0x%lx",
|
||||
sax->manifest_filename, sax->package_index, sax->wcs_full_name, hr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!xml_parser_get_current_state (sax, xml_reader, &local_name, &prefix, &value))
|
||||
return FALSE;
|
||||
|
||||
switch (xml_node_type)
|
||||
{
|
||||
case XmlNodeType_Element:
|
||||
is_empty = IXmlReader_IsEmptyElement (xml_reader);
|
||||
g_assert (local_name != NULL);
|
||||
|
||||
if (!is_empty &&
|
||||
_wcsicmp (local_name, L"Package") == 0 &&
|
||||
prefix[0] == 0)
|
||||
sax->in_package += 1;
|
||||
else if (!is_empty &&
|
||||
sax->in_package == 1 &&
|
||||
_wcsicmp (local_name, L"Applications") == 0 &&
|
||||
prefix[0] == 0)
|
||||
sax->in_applications += 1;
|
||||
else if (!is_empty &&
|
||||
sax->in_applications == 1 &&
|
||||
_wcsicmp (local_name, L"Application") == 0 &&
|
||||
prefix[0] == 0)
|
||||
{
|
||||
sax->in_application += 1;
|
||||
is_application = TRUE;
|
||||
sax->applist = TRUE;
|
||||
g_clear_pointer (&sax->application_usermodelid, g_free);
|
||||
}
|
||||
else if (sax->in_application == 1 &&
|
||||
_wcsicmp (local_name, L"VisualElements") == 0 &&
|
||||
(_wcsicmp (prefix, L"uap") == 0 || _wcsicmp (prefix, L"uap3") == 0))
|
||||
is_visual_elements = TRUE;
|
||||
else if (!is_empty &&
|
||||
sax->in_application == 1 &&
|
||||
_wcsicmp (local_name, L"Extensions") == 0 &&
|
||||
prefix[0] == 0)
|
||||
sax->in_extensions += 1;
|
||||
else if (!is_empty &&
|
||||
sax->in_application == 1 &&
|
||||
_wcsicmp (local_name, L"Extension") == 0 &&
|
||||
_wcsicmp (prefix, L"uap") == 0)
|
||||
is_extension = TRUE;
|
||||
else if (sax->in_extension_protocol == 1 &&
|
||||
_wcsicmp (local_name, L"Protocol") == 0 &&
|
||||
_wcsicmp (prefix, L"uap") == 0)
|
||||
is_protocol = TRUE;
|
||||
else if (!is_empty &&
|
||||
sax->in_extension_fta == 1 &&
|
||||
_wcsicmp (local_name, L"FileTypeAssociation") == 0 &&
|
||||
_wcsicmp (prefix, L"uap") == 0)
|
||||
sax->in_fta_group += 1;
|
||||
else if (!is_empty &&
|
||||
sax->in_fta_group == 1 &&
|
||||
_wcsicmp (local_name, L"SupportedFileTypes") == 0 &&
|
||||
_wcsicmp (prefix, L"uap") == 0)
|
||||
sax->in_sfp += 1;
|
||||
else if (!is_empty &&
|
||||
sax->in_fta_group == 1 &&
|
||||
_wcsicmp (local_name, L"SupportedVerbs") == 0 &&
|
||||
_wcsicmp (prefix, L"uap2") == 0)
|
||||
sax->in_sv += 1;
|
||||
else if (!is_empty &&
|
||||
sax->in_sfp == 1 &&
|
||||
_wcsicmp (local_name, L"FileType") == 0 &&
|
||||
_wcsicmp (prefix, L"uap") == 0)
|
||||
sax->in_filetype += 1;
|
||||
else if (!is_empty &&
|
||||
sax->in_sv == 1 &&
|
||||
_wcsicmp (local_name, L"Verb") == 0 &&
|
||||
_wcsicmp (prefix, L"uap3") == 0)
|
||||
is_verb = TRUE;
|
||||
|
||||
hr = IXmlReader_MoveToFirstAttribute (xml_reader);
|
||||
while (hr == S_OK)
|
||||
{
|
||||
if (!xml_parser_get_current_state (sax, xml_reader, &local_name, &prefix, &value))
|
||||
return FALSE;
|
||||
|
||||
g_assert (local_name != NULL);
|
||||
g_assert (value != NULL);
|
||||
g_assert (prefix != NULL);
|
||||
|
||||
if (is_application &&
|
||||
sax->application_usermodelid == NULL &&
|
||||
_wcsicmp (local_name, L"Id") == 0)
|
||||
{
|
||||
size_t id_len = 0;
|
||||
size_t value_len = wcslen (value);
|
||||
const wchar_t *wcs_package_family;
|
||||
size_t wcs_package_family_len;
|
||||
|
||||
wcs_package_family = sax_WindowsGetStringRawBuffer (sax->package_family, NULL);
|
||||
wcs_package_family_len = wcslen (wcs_package_family);
|
||||
id_len += wcs_package_family_len + 1 + value_len;
|
||||
sax->application_usermodelid = g_new (wchar_t, id_len + 1);
|
||||
/* AppUserModelId = <family>!<id> */
|
||||
memcpy (&sax->application_usermodelid[0], wcs_package_family, wcs_package_family_len * sizeof (wchar_t));
|
||||
memcpy (&sax->application_usermodelid[wcs_package_family_len], L"!", sizeof (wchar_t));
|
||||
memcpy (&sax->application_usermodelid[wcs_package_family_len + 1], value, (value_len + 1) * sizeof (wchar_t));
|
||||
}
|
||||
else if (is_visual_elements &&
|
||||
_wcsicmp (local_name, L"AppListEntry") == 0 &&
|
||||
_wcsicmp (value, L"none") == 0)
|
||||
sax->applist = FALSE;
|
||||
else if (is_extension &&
|
||||
_wcsicmp (local_name, L"Category") == 0 &&
|
||||
_wcsicmp (value, L"windows.protocol") == 0)
|
||||
sax->in_extension_protocol += 1;
|
||||
else if (is_extension &&
|
||||
_wcsicmp (local_name, L"Category") == 0 &&
|
||||
_wcsicmp (value, L"windows.fileTypeAssociation") == 0)
|
||||
sax->in_extension_fta += 1;
|
||||
else if (is_protocol &&
|
||||
_wcsicmp (local_name, L"Name") == 0)
|
||||
g_ptr_array_add (sax->supported_protocols, g_wcsdup (value, -1));
|
||||
else if (is_verb &&
|
||||
_wcsicmp (local_name, L"Id") == 0)
|
||||
g_ptr_array_add (sax->supported_verbs, g_wcsdup (value, -1));
|
||||
|
||||
hr = IXmlReader_MoveToNextAttribute (xml_reader);
|
||||
}
|
||||
break;
|
||||
case XmlNodeType_Text:
|
||||
g_assert (value != NULL);
|
||||
|
||||
if (sax->in_filetype && value[0] != 0)
|
||||
g_ptr_array_add (sax->supported_extensions, g_wcsdup (value, -1));
|
||||
break;
|
||||
case XmlNodeType_EndElement:
|
||||
g_assert (local_name != NULL);
|
||||
|
||||
if (_wcsicmp (local_name, L"Package") == 0 &&
|
||||
prefix[0] == 0)
|
||||
sax->in_package -= 1;
|
||||
else if (sax->in_package == 1 &&
|
||||
_wcsicmp (local_name, L"Applications") == 0 &&
|
||||
prefix[0] == 0)
|
||||
sax->in_applications -= 1;
|
||||
else if (sax->in_application == 1 &&
|
||||
_wcsicmp (local_name, L"Extensions") == 0 &&
|
||||
prefix[0] == 0)
|
||||
sax->in_extensions -= 1;
|
||||
else if (sax->in_extension_protocol == 1 &&
|
||||
_wcsicmp (local_name, L"Extension") == 0 &&
|
||||
_wcsicmp (prefix, L"uap") == 0)
|
||||
sax->in_extension_protocol -= 1;
|
||||
else if (sax->in_extension_fta == 1 &&
|
||||
_wcsicmp (local_name, L"Extension") == 0 &&
|
||||
_wcsicmp (prefix, L"uap") == 0)
|
||||
sax->in_extension_fta -= 1;
|
||||
else if (sax->in_fta_group == 1 &&
|
||||
_wcsicmp (local_name, L"SupportedFileTypes") == 0 &&
|
||||
_wcsicmp (prefix, L"uap") == 0)
|
||||
sax->in_sfp -= 1;
|
||||
else if (sax->in_sfp == 1 &&
|
||||
_wcsicmp (local_name, L"FileType") == 0 &&
|
||||
_wcsicmp (prefix, L"uap") == 0)
|
||||
sax->in_filetype -= 1;
|
||||
else if (sax->in_fta_group == 1 &&
|
||||
_wcsicmp (local_name, L"SupportedVerbs") == 0 &&
|
||||
_wcsicmp (prefix, L"uap2") == 0)
|
||||
sax->in_sv -= 1;
|
||||
else if (sax->in_applications == 1 &&
|
||||
_wcsicmp (local_name, L"Application") == 0 &&
|
||||
prefix[0] == 0)
|
||||
{
|
||||
if (sax->application_usermodelid != NULL)
|
||||
sax->exit_early = !sax->callback (sax->user_data, sax->wcs_full_name, sax->wcs_name,
|
||||
sax->application_usermodelid, sax->applist,
|
||||
sax->supported_extgroups, sax->supported_protocols);
|
||||
g_clear_pointer (&sax->supported_extgroups, g_ptr_array_unref);
|
||||
g_clear_pointer (&sax->supported_protocols, g_ptr_array_unref);
|
||||
sax->supported_protocols = g_ptr_array_new_full (0, (GDestroyNotify) g_free);
|
||||
sax->supported_extgroups = g_ptr_array_new_full (0, (GDestroyNotify) free_extgroup);
|
||||
sax->in_application -= 1;
|
||||
}
|
||||
else if (sax->in_extension_fta == 1 &&
|
||||
_wcsicmp (local_name, L"FileTypeAssociation") == 0 &&
|
||||
_wcsicmp (prefix, L"uap") == 0)
|
||||
{
|
||||
GWin32PackageExtGroup *new_group = g_new0 (GWin32PackageExtGroup, 1);
|
||||
new_group->extensions = g_steal_pointer (&sax->supported_extensions);
|
||||
sax->supported_extensions = g_ptr_array_new_full (0, (GDestroyNotify) g_free);
|
||||
new_group->verbs = g_steal_pointer (&sax->supported_verbs);
|
||||
sax->supported_verbs = g_ptr_array_new_full (0, (GDestroyNotify) g_free);
|
||||
g_ptr_array_add (sax->supported_extgroups, new_group);
|
||||
sax->in_fta_group -= 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
48
gio/gwin32packageparser.h
Executable file
48
gio/gwin32packageparser.h
Executable file
@ -0,0 +1,48 @@
|
||||
/* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright (C) 2020 Руслан Ижбулатов <lrn1986@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef __G_WIN32_PACKAGE_PARSER_H__
|
||||
#define __G_WIN32_PACKAGE_PARSER_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
|
||||
typedef struct _GWin32PackageExtGroup GWin32PackageExtGroup;
|
||||
|
||||
struct _GWin32PackageExtGroup
|
||||
{
|
||||
GPtrArray *verbs;
|
||||
GPtrArray *extensions;
|
||||
};
|
||||
|
||||
typedef gboolean (*GWin32PackageParserCallback)(gpointer user_data,
|
||||
const gunichar2 *full_package_name,
|
||||
const gunichar2 *package_name,
|
||||
const gunichar2 *app_user_model_id,
|
||||
gboolean show_in_applist,
|
||||
GPtrArray *supported_extgroups,
|
||||
GPtrArray *supported_protocols);
|
||||
|
||||
gboolean g_win32_package_parser_enum_packages (GWin32PackageParserCallback callback,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
|
||||
#endif /* G_PLATFORM_WIN32 */
|
||||
|
||||
#endif /* __G_WIN32_PACKAGE_PARSER_H__ */
|
@ -430,12 +430,16 @@ else
|
||||
cc.find_library('dnsapi'),
|
||||
iphlpapi_dep,
|
||||
winsock2]
|
||||
platform_deps += uwp_gio_deps
|
||||
|
||||
win32_sources += files(
|
||||
'gwin32registrykey.c',
|
||||
'gwin32mount.c',
|
||||
'gwin32volumemonitor.c',
|
||||
'gwin32inputstream.c',
|
||||
'gwin32outputstream.c',
|
||||
'gwin32file-sync-stream.c',
|
||||
'gwin32packageparser.c',
|
||||
'gwin32networkmonitor.c',
|
||||
'gwin32networkmonitor.h',
|
||||
'gwin32notificationbackend.c',
|
||||
|
@ -466,9 +466,12 @@ if host_system == 'windows'
|
||||
glib_conf.set('G_WINAPI_ONLY_APP', true)
|
||||
# We require Windows 10+ on WinRT
|
||||
glib_conf.set('_WIN32_WINNT', '0x0A00')
|
||||
uwp_gio_deps = [cc.find_library('shcore'),
|
||||
cc.find_library('runtimeobject')]
|
||||
else
|
||||
# We require Windows 7+ on Win32
|
||||
glib_conf.set('_WIN32_WINNT', '0x0601')
|
||||
uwp_gio_deps = []
|
||||
endif
|
||||
endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user