Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions dlls/xgameruntime/GDKComponent/System/XLauncher.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Xbox Game runtime Library
* GDK Component: System API -> XLauncher
*
* Copyright 2026 Olivia Ryan
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/

#include "../../private.h"
#include <shellapi.h>

struct x_launcher
{
IXLauncherImpl IXLauncherImpl_iface;
LONG ref;
};

WINE_DEFAULT_DEBUG_CHANNEL(gdkc);

static inline struct x_launcher *impl_from_IXLauncherImpl( IXLauncherImpl *iface )
{
return CONTAINING_RECORD( iface, struct x_launcher, IXLauncherImpl_iface );
}

static HRESULT WINAPI x_launcher_QueryInterface( IXLauncherImpl *iface, REFIID iid, void **out )
{
struct x_launcher *impl = impl_from_IXLauncherImpl( iface );

TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out );

if (IsEqualGUID( iid, &IID_IUnknown ) || IsEqualGUID( iid, &IID_IXLauncherImpl ))
{
IXLauncherImpl_AddRef( *out = &impl->IXLauncherImpl_iface );
return S_OK;
}

FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
*out = NULL;
return E_NOINTERFACE;
}

static ULONG WINAPI x_launcher_AddRef( IXLauncherImpl *iface )
{
struct x_launcher *impl = impl_from_IXLauncherImpl( iface );
ULONG ref = InterlockedIncrement( &impl->ref );
TRACE( "iface %p increasing refcount to %lu.\n", iface, ref );
return ref;
}

static ULONG WINAPI x_launcher_Release( IXLauncherImpl *iface )
{
struct x_launcher *impl = impl_from_IXLauncherImpl( iface );
ULONG ref = InterlockedDecrement( &impl->ref );
TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref );
return ref;
}

static HRESULT WINAPI x_launcher_XLaunchUri( IXLauncherImpl *iface, XUserHandle user, const char *uri )
{
TRACE( "iface %p, user %p uri %s.\n", iface, user, debugstr_a( uri ) );
return (SIZE_T)ShellExecuteA( NULL, "open", uri, NULL, NULL, SW_SHOW ) > 32 ? S_OK : E_GAMEPACKAGE_NO_PACKAGE_IDENTIFIER;
}

static HRESULT WINAPI x_launcher_XDisplayAcquireTimeoutDeferral( IXLauncherImpl *iface, XDisplayTimeoutDeferralHandle *handle )
{
FIXME( "iface %p, handle %p stub!\n", iface, handle );
return E_NOTIMPL;
}

static void WINAPI x_launcher_XDisplayCloseTimeoutDeferralHandle( IXLauncherImpl *iface, XDisplayTimeoutDeferralHandle handle )
{
FIXME( "iface %p stub!\n", iface, handle );
}

static const struct IXLauncherImplVtbl x_launcher_vtbl =
{
/* IUnknown methods */
x_launcher_QueryInterface,
x_launcher_AddRef,
x_launcher_Release,
/* IXLauncherImpl methods */
x_launcher_XLaunchUri,
x_launcher_XDisplayAcquireTimeoutDeferral,
x_launcher_XDisplayCloseTimeoutDeferralHandle,
};

static struct x_launcher x_launcher =
{
{&x_launcher_vtbl},
0,
};

IXLauncherImpl *x_launcher_impl = &x_launcher.IXLauncherImpl_iface;
3 changes: 2 additions & 1 deletion dlls/xgameruntime/Makefile.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
IMPORTS = user32 advapi32 crypt32 combase winhttp
IMPORTS = user32 advapi32 crypt32 combase shell32 winhttp
MODULE = xgameruntime.dll

SOURCES = \
Expand All @@ -16,6 +16,7 @@ SOURCES = \
GDKComponent/System/Threading/ThreadPool.c \
GDKComponent/System/XSystemAnalytics.c \
GDKComponent/System/XGameRuntimeFeature.c \
GDKComponent/System/XLauncher.c \
GDKComponent/System/Networking/HTTPClient.c \
GDKComponent/System/Networking/XNetworking.c

4 changes: 4 additions & 0 deletions dlls/xgameruntime/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ HRESULT WINAPI QueryApiImpl( const GUID *runtimeClassId, REFIID interfaceId, voi
{
return IXNetworkingImpl_QueryInterface( x_networking_impl, interfaceId, out );
}
else if ( IsEqualGUID( runtimeClassId, &CLSID_XLauncherImpl ) )
{
return IXLauncherImpl_QueryInterface( x_launcher_impl, interfaceId, out );
}

FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( runtimeClassId ) );
return E_NOTIMPL;
Expand Down
1 change: 1 addition & 0 deletions dlls/xgameruntime/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ extern IXSystemImpl *x_system_impl;
extern IXSystemAnalyticsImpl *x_system_analytics_impl;
extern IXThreadingImpl *x_threading_impl;
extern IXGameRuntimeFeatureImpl *x_game_runtime_feature_impl;
extern IXLauncherImpl *x_launcher_impl;
extern IXNetworkingImpl *x_networking_impl;

typedef struct _INITIALIZE_OPTIONS
Expand Down
23 changes: 23 additions & 0 deletions dlls/xgameruntime/provider.idl
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,26 @@ import "propidl.idl";

// --- xgameruntime --- //
typedef void* XSystemHandle;
typedef struct XUser* XUserHandle;

typedef enum XSystemHandleType XSystemHandleType;
typedef enum XSystemHandleCallbackReason XSystemHandleCallbackReason;
typedef enum XGameRuntimeFeature XGameRuntimeFeature;

typedef struct XVersion XVersion;
typedef struct XSystemAnalyticsInfo XSystemAnalyticsInfo;
typedef struct XDisplayTimeoutDeferral *XDisplayTimeoutDeferralHandle;

interface IWineAsyncWorkImpl;
interface IXSystemImpl;
interface IXSystemAnalyticsImpl;
interface IXGameRuntimeFeatureImpl;
interface IXLauncherImpl;

coclass XSystemImpl;
coclass XSystemAnalyticsImpl;
coclass XGameRuntimeFeatureImpl;
coclass XLauncherImpl;

enum XSystemHandleType
{
Expand Down Expand Up @@ -162,6 +166,18 @@ interface IXGameRuntimeFeatureImpl : IUnknown
BOOLEAN XGameRuntimeIsFeatureAvailable( [in] XGameRuntimeFeature feature );
}

[
local,
object,
uuid(1b339674-328d-4283-a200-3171f18d3639)
]
interface IXLauncherImpl : IUnknown
{
HRESULT XLaunchUri( [in, optional] XUserHandle user, [in, string] const char *uri );
HRESULT XDisplayAcquireTimeoutDeferral( [out] XDisplayTimeoutDeferralHandle *handle );
void XDisplayCloseTimeoutDeferralHandle( [in] XDisplayTimeoutDeferralHandle handle );
}

[
uuid(e349bd1a-fc20-4e40-b99c-4178cc6b409f)
]
Expand All @@ -186,3 +202,10 @@ coclass XGameRuntimeFeatureImpl
[default] interface IXGameRuntimeFeatureImpl;
}

[
uuid(1b339674-328d-4283-a200-3171f18d3639)
]
coclass XLauncherImpl
{
[default] interface IXLauncherImpl;
}
23 changes: 23 additions & 0 deletions dlls/xgameruntime/tests/provider.idl
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,28 @@ cpp_quote("#include <xasync.h>")

// --- xgameruntime --- //
typedef void* XSystemHandle;
typedef struct XUser* XUserHandle;

typedef enum XSystemHandleType XSystemHandleType;
typedef enum XSystemHandleCallbackReason XSystemHandleCallbackReason;
typedef enum XGameRuntimeFeature XGameRuntimeFeature;

typedef struct XVersion XVersion;
typedef struct XSystemAnalyticsInfo XSystemAnalyticsInfo;
typedef struct XDisplayTimeoutDeferral *XDisplayTimeoutDeferralHandle;

/* type-pruning version of XAsyncCompletionRoutine */

interface IWineAsyncWorkImpl;
interface IXSystemImpl;
interface IXSystemAnalyticsImpl;
interface IXGameRuntimeFeatureImpl;
interface IXLauncherImpl;

coclass XSystemImpl;
coclass XSystemAnalyticsImpl;
coclass XGameRuntimeFeatureImpl;
coclass XLauncherImpl;

enum XSystemHandleType
{
Expand Down Expand Up @@ -166,6 +170,18 @@ interface IXGameRuntimeFeatureImpl : IUnknown
BOOLEAN XGameRuntimeIsFeatureAvailable( [in] XGameRuntimeFeature feature );
}

[
local,
object,
uuid(1b339674-328d-4283-a200-3171f18d3639)
]
interface IXLauncherImpl : IUnknown
{
HRESULT XLaunchUri( [in, optional] XUserHandle user, [in, string] const char *uri );
HRESULT XDisplayAcquireTimeoutDeferral( [out] XDisplayTimeoutDeferralHandle *handle );
void XDisplayCloseTimeoutDeferralHandle( [in] XDisplayTimeoutDeferralHandle handle );
}

[
uuid(e349bd1a-fc20-4e40-b99c-4178cc6b409f)
]
Expand All @@ -190,3 +206,10 @@ coclass XGameRuntimeFeatureImpl
[default] interface IXGameRuntimeFeatureImpl;
}

[
uuid(1b339674-328d-4283-a200-3171f18d3639)
]
coclass XLauncherImpl
{
[default] interface IXLauncherImpl;
}
15 changes: 15 additions & 0 deletions dlls/xgameruntime/tests/xgameruntime.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,20 @@ static void test_XThreading(void)
}
}

void test_XLauncher(void)
{
IXLauncherImpl *xlauncher;
HRESULT hr;

hr = QueryApiImpl_fun( &CLSID_XLauncherImpl, &IID_IXLauncherImpl, (void **)&xlauncher );
ok( hr == S_OK, "got hr %#lx.\n", hr );

check_interface( xlauncher, &IID_IUnknown, TRUE );
check_interface( xlauncher, &IID_IXLauncherImpl, TRUE );

IXLauncherImpl_Release( xlauncher );
}

START_TEST(xgameruntime)
{
HRESULT hr;
Expand All @@ -371,6 +385,7 @@ START_TEST(xgameruntime)
test_XSystemAnalytics();
test_XGameRuntimeFeature();
test_XThreading();
test_XLauncher();

RoUninitialize();
}