include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / windows.gaming.input / main.c
blob39c0540aacedc4009ce826f16e0309047ae9054a
1 /* WinRT Windows.Gaming.Input implementation
3 * Copyright 2021 RĂ©mi Bernon for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdarg.h>
21 #include <stddef.h>
23 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winreg.h"
27 #include "winuser.h"
29 #include "dbt.h"
30 #include "ddk/hidclass.h"
31 #include "ddk/hidsdi.h"
32 #include "setupapi.h"
34 #include "initguid.h"
35 #include "private.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(input);
41 HINSTANCE windows_gaming_input;
43 DEFINE_GUID( GUID_DEVINTERFACE_WINEXINPUT,0x6c53d5fd,0x6480,0x440f,0xb6,0x18,0x47,0x67,0x50,0xc5,0xe1,0xa6 );
45 static LRESULT CALLBACK devnotify_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
47 DEV_BROADCAST_DEVICEINTERFACE_W *iface;
49 TRACE( "hwnd %p, msg %#x, wparam %#Ix, lparam %#Ix\n", hwnd, msg, wparam, lparam );
51 if (msg == WM_DEVICECHANGE)
53 switch (wparam)
55 case DBT_DEVICEARRIVAL:
56 iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)lparam;
57 provider_create( iface->dbcc_name );
58 break;
59 case DBT_DEVICEREMOVECOMPLETE:
60 iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)lparam;
61 provider_remove( iface->dbcc_name );
62 break;
63 default: break;
67 return DefWindowProcW( hwnd, msg, wparam, lparam );
70 static void initialize_providers( void )
72 char buffer[offsetof( SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath[MAX_PATH] )];
73 SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer;
74 SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
75 GUID guid = GUID_DEVINTERFACE_WINEXINPUT;
76 HDEVINFO set;
77 DWORD i = 0;
79 set = SetupDiGetClassDevsW( NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
81 while (SetupDiEnumDeviceInterfaces( set, NULL, &guid, i++, &iface ))
83 detail->cbSize = sizeof(*detail);
84 if (!SetupDiGetDeviceInterfaceDetailW( set, &iface, detail, sizeof(buffer), NULL, NULL )) continue;
85 provider_create( detail->DevicePath );
88 HidD_GetHidGuid( &guid );
90 while (SetupDiEnumDeviceInterfaces( set, NULL, &guid, i++, &iface ))
92 detail->cbSize = sizeof(*detail);
93 if (!SetupDiGetDeviceInterfaceDetailW( set, &iface, detail, sizeof(buffer), NULL, NULL )) continue;
94 provider_create( detail->DevicePath );
97 SetupDiDestroyDeviceInfoList( set );
100 static DWORD WINAPI monitor_thread_proc( void *param )
102 DEV_BROADCAST_DEVICEINTERFACE_W filter =
104 .dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE_W),
105 .dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE,
107 WNDCLASSEXW wndclass =
109 .cbSize = sizeof(WNDCLASSEXW),
110 .lpszClassName = L"__wine_gaming_input_devnotify",
111 .lpfnWndProc = devnotify_wndproc,
113 HANDLE start_event = param;
114 HDEVNOTIFY devnotify;
115 HMODULE module;
116 HWND hwnd;
117 MSG msg;
119 SetThreadDescription( GetCurrentThread(), L"wine_wginput_worker" );
121 GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (void *)windows_gaming_input, &module );
122 RegisterClassExW( &wndclass );
123 hwnd = CreateWindowExW( 0, wndclass.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL );
124 devnotify = RegisterDeviceNotificationW( hwnd, &filter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES );
125 initialize_providers();
126 SetEvent( start_event );
130 while (PeekMessageW( &msg, hwnd, 0, 0, PM_REMOVE ))
132 TranslateMessage( &msg );
133 DispatchMessageW( &msg );
135 } while (!MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE ));
137 UnregisterDeviceNotification( devnotify );
138 DestroyWindow( hwnd );
139 UnregisterClassW( wndclass.lpszClassName, NULL );
141 FreeLibraryAndExitThread( module, 0 );
142 return 0;
145 static BOOL WINAPI start_monitor_thread( INIT_ONCE *once, void *param, void **context )
147 HANDLE thread, start_event;
149 start_event = CreateEventA( NULL, FALSE, FALSE, NULL );
150 if (!start_event) ERR( "Failed to create start event, error %lu\n", GetLastError() );
152 thread = CreateThread( NULL, 0, monitor_thread_proc, start_event, 0, NULL );
153 if (!thread) ERR( "Failed to create monitor thread, error %lu\n", GetLastError() );
154 else
156 WaitForSingleObject( start_event, INFINITE );
157 CloseHandle( thread );
160 CloseHandle( start_event );
161 return !!thread;
164 HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out)
166 FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out);
167 return CLASS_E_CLASSNOTAVAILABLE;
170 HRESULT WINAPI DllGetActivationFactory( HSTRING class_str, IActivationFactory **factory )
172 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
173 const WCHAR *buffer = WindowsGetStringRawBuffer( class_str, NULL );
175 TRACE( "class %s, factory %p.\n", debugstr_w(buffer), factory );
177 InitOnceExecuteOnce( &init_once, start_monitor_thread, NULL, NULL );
179 *factory = NULL;
181 if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_Input_RawGameController ))
182 ICustomGameControllerFactory_QueryInterface( controller_factory, &IID_IActivationFactory, (void **)factory );
183 if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_Input_Gamepad ))
184 ICustomGameControllerFactory_QueryInterface( gamepad_factory, &IID_IActivationFactory, (void **)factory );
185 if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_Input_RacingWheel ))
186 ICustomGameControllerFactory_QueryInterface( racing_wheel_factory, &IID_IActivationFactory, (void **)factory );
187 if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_Input_Custom_GameControllerFactoryManager ))
188 IGameControllerFactoryManagerStatics2_QueryInterface( manager_factory, &IID_IActivationFactory, (void **)factory );
190 if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_Input_ForceFeedback_ConstantForceEffect ))
191 IInspectable_QueryInterface( constant_effect_factory, &IID_IActivationFactory, (void **)factory );
192 if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_Input_ForceFeedback_RampForceEffect ))
193 IInspectable_QueryInterface( ramp_effect_factory, &IID_IActivationFactory, (void **)factory );
194 if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_Input_ForceFeedback_PeriodicForceEffect ))
195 IInspectable_QueryInterface( periodic_effect_factory, &IID_IActivationFactory, (void **)factory );
196 if (!wcscmp( buffer, RuntimeClass_Windows_Gaming_Input_ForceFeedback_ConditionForceEffect ))
197 IInspectable_QueryInterface( condition_effect_factory, &IID_IActivationFactory, (void **)factory );
199 if (*factory) return S_OK;
200 return CLASS_E_CLASSNOTAVAILABLE;
203 BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved )
205 TRACE( "instance %p, reason %lu, reserved %p.\n", instance, reason, reserved );
207 switch (reason)
209 case DLL_PROCESS_ATTACH:
210 DisableThreadLibraryCalls( instance );
211 windows_gaming_input = instance;
212 break;
214 return TRUE;