swift
simconnectsymbols.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2018 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "simconnectsymbols.h"
5 
6 // clang-format off
7 #include <Windows.h>
8 #include <SimConnect.h>
9 // clang-format on
10 
11 #include <array>
12 
13 #include <QLibrary>
14 
15 #include "misc/logcategories.h"
16 #include "misc/logmessage.h"
17 #include "misc/stringutils.h"
18 
19 // clazy:excludeall=function-args-by-ref
20 
21 using namespace swift::misc;
22 
23 bool loadAndResolveSimConnect(bool manifestProbing)
24 {
25  Q_UNUSED(manifestProbing);
26  return true;
27 }
28 
29 // old FSX API: https://docs.microsoft.com/en-us/previous-versions/microsoft-esp/cc526983(v=msdn.10)
30 using PfnSimConnect_Open = HRESULT(__stdcall *)(HANDLE *, LPCSTR, HWND, DWORD, HANDLE, DWORD);
31 using PfnSimConnect_Close = HRESULT(__stdcall *)(HANDLE);
32 using PfnSimConnect_AddToDataDefinition = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_DATA_DEFINITION_ID, const char *,
33  const char *, SIMCONNECT_DATATYPE, float, DWORD);
34 using PfnSimConnect_Text = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_TEXT_TYPE, float, SIMCONNECT_CLIENT_EVENT_ID, DWORD,
35  void *);
36 using PfnSimConnect_CallDispatch = HRESULT(__stdcall *)(HANDLE, DispatchProc, void *);
37 using PfnSimConnect_WeatherSetModeCustom = HRESULT(__stdcall *)(HANDLE);
38 using PfnSimConnect_WeatherSetModeGlobal = HRESULT(__stdcall *)(HANDLE);
39 using PfnSimConnect_WeatherSetObservation = HRESULT(__stdcall *)(HANDLE, DWORD, const char *);
40 using PfnSimConnect_TransmitClientEvent = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_OBJECT_ID, SIMCONNECT_CLIENT_EVENT_ID,
41  DWORD, SIMCONNECT_NOTIFICATION_GROUP_ID,
42  SIMCONNECT_EVENT_FLAG);
43 using PfnSimConnect_SetClientData = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_CLIENT_DATA_ID,
44  SIMCONNECT_CLIENT_DATA_DEFINITION_ID,
45  SIMCONNECT_CLIENT_DATA_SET_FLAG, DWORD, DWORD, void *);
46 using PfnSimConnect_RequestDataOnSimObject = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_DATA_REQUEST_ID,
47  SIMCONNECT_DATA_DEFINITION_ID, SIMCONNECT_OBJECT_ID,
48  SIMCONNECT_PERIOD, SIMCONNECT_DATA_REQUEST_FLAG,
49  DWORD, DWORD, DWORD);
50 using PfnSimConnect_RequestClientData = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_CLIENT_DATA_ID,
51  SIMCONNECT_DATA_REQUEST_ID,
52  SIMCONNECT_CLIENT_DATA_DEFINITION_ID,
53  SIMCONNECT_CLIENT_DATA_PERIOD,
54  SIMCONNECT_CLIENT_DATA_REQUEST_FLAG, DWORD, DWORD, DWORD);
55 using PfnSimConnect_SubscribeToSystemEvent = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_CLIENT_EVENT_ID, const char *);
56 using PfnSimConnect_MapClientEventToSimEvent = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_CLIENT_EVENT_ID, const char *);
57 using PfnSimConnect_SubscribeToFacilities = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_FACILITY_LIST_TYPE,
58  SIMCONNECT_DATA_REQUEST_ID);
59 using PfnSimConnect_GetLastSentPacketID = HRESULT(__stdcall *)(HANDLE, DWORD *);
60 using PfnSimConnect_AIRemoveObject = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_OBJECT_ID, SIMCONNECT_DATA_REQUEST_ID);
61 using PfnSimConnect_SetDataOnSimObject = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_DATA_DEFINITION_ID,
62  SIMCONNECT_OBJECT_ID, SIMCONNECT_DATA_SET_FLAG, DWORD,
63  DWORD, void *);
64 using PfnSimConnect_AIReleaseControl = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_OBJECT_ID, SIMCONNECT_DATA_REQUEST_ID);
65 using PfnSimConnect_AICreateNonATCAircraft = HRESULT(__stdcall *)(HANDLE, const char *, const char *,
66  SIMCONNECT_DATA_INITPOSITION,
67  SIMCONNECT_DATA_REQUEST_ID);
68 using PfnSimConnect_AICreateEnrouteATCAircraft = HRESULT(__stdcall *)(HANDLE, const char *, const char *, int,
69  const char *, double, BOOL,
70  SIMCONNECT_DATA_REQUEST_ID);
71 using PfnSimConnect_AICreateParkedATCAircraft = HRESULT(__stdcall *)(HANDLE, const char *, const char *, const char *,
72  SIMCONNECT_DATA_REQUEST_ID);
73 using PfnSimConnect_AICreateSimulatedObject = HRESULT(__stdcall *)(HANDLE, const char *, SIMCONNECT_DATA_INITPOSITION,
74  SIMCONNECT_DATA_REQUEST_ID);
75 using PfnSimConnect_MapClientDataNameToID = HRESULT(__stdcall *)(HANDLE, const char *, SIMCONNECT_CLIENT_DATA_ID);
76 using PfnSimConnect_CreateClientData = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_CLIENT_DATA_ID, DWORD,
77  SIMCONNECT_CREATE_CLIENT_DATA_FLAG);
78 using PfnSimConnect_AddToClientDataDefinition = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_CLIENT_DATA_DEFINITION_ID,
79  DWORD, DWORD, float, DWORD);
80 
81 #ifdef Q_OS_WIN64
82 using PfnSimConnect_RequestGroundInfo = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_DATA_REQUEST_ID, double, double, double,
83  double, double, double, DWORD, DWORD,
84  SIMCONNECT_GROUND_INFO_LATLON_FORMAT,
85  SIMCONNECT_GROUND_INFO_ALT_FORMAT,
86  SIMCONNECT_GROUND_INFO_SOURCE_FLAG);
87 using PfnSimConnect_ChangeView = HRESULT(__stdcall *)(HANDLE, const char *);
88 using PfnSimConnect_AIReleaseControlEx = HRESULT(__stdcall *)(HANDLE, SIMCONNECT_OBJECT_ID, SIMCONNECT_DATA_REQUEST_ID,
89  BOOL);
90 using PfnSimConnect_CloseView = HRESULT(__stdcall *)(HANDLE, const char *);
91 using PfnSimConnect_OpenView = HRESULT(__stdcall *)(HANDLE, const char *, const char *);
92 using PfnSimConnect_ChangeView = HRESULT(__stdcall *)(HANDLE, const char *);
93 using PfnSimConnect_CreateCameraInstance = HRESULT(__stdcall *)(HANDLE, const GUID, const char *, SIMCONNECT_OBJECT_ID,
94  SIMCONNECT_DATA_REQUEST_ID);
95 using PfnSimConnect_DeleteCameraInstance = HRESULT(__stdcall *)(HANDLE, const GUID, UINT32);
96 using PfnSimConnect_CreateCameraDefinition = HRESULT(__stdcall *)(HANDLE, const GUID, SIMCONNECT_CAMERA_TYPE,
97  const char *, SIMCONNECT_DATA_XYZ,
99 using PfnSimConnect_ObserverAttachToEntityOn = HRESULT(__stdcall *)(HANDLE, const char *, DWORD, SIMCONNECT_DATA_XYZ);
100 using PfnSimConnect_CreateObserver = HRESULT(__stdcall *)(HANDLE, const char *, SIMCONNECT_DATA_OBSERVER);
101 using PfnSimConnect_SetObserverLookAt = HRESULT(__stdcall *)(HANDLE, const char *, SIMCONNECT_DATA_LATLONALT);
102 #endif
103 
106 struct SimConnectSymbols
107 {
108  PfnSimConnect_Open SimConnect_Open = nullptr;
109  PfnSimConnect_Close SimConnect_Close = nullptr;
110  PfnSimConnect_AddToDataDefinition SimConnect_AddToDataDefinition = nullptr;
111  PfnSimConnect_Text SimConnect_Text = nullptr;
112  PfnSimConnect_CallDispatch SimConnect_CallDispatch = nullptr;
113  PfnSimConnect_WeatherSetModeCustom SimConnect_WeatherSetModeCustom = nullptr;
114  PfnSimConnect_WeatherSetModeGlobal SimConnect_WeatherSetModeGlobal = nullptr;
115  PfnSimConnect_WeatherSetObservation SimConnect_WeatherSetObservation = nullptr;
116  PfnSimConnect_TransmitClientEvent SimConnect_TransmitClientEvent = nullptr;
117  PfnSimConnect_SetClientData SimConnect_SetClientData = nullptr;
118  PfnSimConnect_RequestDataOnSimObject SimConnect_RequestDataOnSimObject = nullptr;
119  PfnSimConnect_RequestClientData SimConnect_RequestClientData = nullptr;
120  PfnSimConnect_SubscribeToSystemEvent SimConnect_SubscribeToSystemEvent = nullptr;
121  PfnSimConnect_MapClientEventToSimEvent SimConnect_MapClientEventToSimEvent = nullptr;
122  PfnSimConnect_SubscribeToFacilities SimConnect_SubscribeToFacilities = nullptr;
123  PfnSimConnect_GetLastSentPacketID SimConnect_GetLastSentPacketID = nullptr;
124  PfnSimConnect_AIRemoveObject SimConnect_AIRemoveObject = nullptr;
125  PfnSimConnect_SetDataOnSimObject SimConnect_SetDataOnSimObject = nullptr;
126  PfnSimConnect_AIReleaseControl SimConnect_AIReleaseControl = nullptr;
127  PfnSimConnect_AICreateNonATCAircraft SimConnect_AICreateNonATCAircraft = nullptr;
128  PfnSimConnect_AICreateParkedATCAircraft SimConnect_AICreateParkedATCAircraft = nullptr;
129  PfnSimConnect_AICreateEnrouteATCAircraft SimConnect_AICreateEnrouteATCAircraft = nullptr;
130  PfnSimConnect_AICreateSimulatedObject SimConnect_AICreateSimulatedObject = nullptr;
131  PfnSimConnect_MapClientDataNameToID SimConnect_MapClientDataNameToID = nullptr;
132  PfnSimConnect_CreateClientData SimConnect_CreateClientData = nullptr;
133  PfnSimConnect_AddToClientDataDefinition SimConnect_AddToClientDataDefinition = nullptr;
134 #ifdef Q_OS_WIN64
135  PfnSimConnect_RequestGroundInfo SimConnect_RequestGroundInfo = nullptr;
136  PfnSimConnect_ChangeView SimConnect_ChangeView = nullptr;
137  PfnSimConnect_AIReleaseControlEx SimConnect_AIReleaseControlEx = nullptr;
138  PfnSimConnect_CreateCameraDefinition SimConnect_CreateCameraDefinition = nullptr;
139  PfnSimConnect_ObserverAttachToEntityOn SimConnect_ObserverAttachToEntityOn = nullptr;
140  PfnSimConnect_CreateObserver SimConnect_CreateObserver = nullptr;
141  PfnSimConnect_CreateCameraInstance SimConnect_CreateCameraInstance = nullptr;
142  PfnSimConnect_DeleteCameraInstance SimConnect_DeleteCameraInstance = nullptr;
143  PfnSimConnect_SetObserverLookAt SimConnect_SetObserverLookAt = nullptr;
144  PfnSimConnect_OpenView SimConnect_OpenView = nullptr;
145  PfnSimConnect_CloseView SimConnect_CloseView = nullptr;
146 #endif
147 };
148 
149 static SimConnectSymbols gSymbols;
150 
151 template <typename FuncPtr>
152 bool resolveSimConnectSymbol(QLibrary &library, FuncPtr &funcPtr, const char *funcName)
153 {
154  funcPtr = reinterpret_cast<FuncPtr>(library.resolve(funcName));
155  if (!funcPtr)
156  {
157  CLogMessage(CLogCategories::driver()).error(u"Failed to resolve %1: %2") << funcName << library.errorString();
158  return false;
159  }
160  return true;
161 }
162 
163 bool resolveCommonSimConnectSymbols(QLibrary &simConnectDll)
164 {
165  bool resolveSuccess = true;
166  resolveSuccess =
167  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_Open, "SimConnect_Open");
168  resolveSuccess =
169  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_Close, "SimConnect_Close");
170  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_AddToDataDefinition,
171  "SimConnect_AddToDataDefinition");
172  resolveSuccess =
173  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_Text, "SimConnect_Text");
174  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_CallDispatch,
175  "SimConnect_CallDispatch");
176  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_WeatherSetModeCustom,
177  "SimConnect_WeatherSetModeCustom");
178  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_WeatherSetModeGlobal,
179  "SimConnect_WeatherSetModeGlobal");
180  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_WeatherSetObservation,
181  "SimConnect_WeatherSetObservation");
182  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_TransmitClientEvent,
183  "SimConnect_TransmitClientEvent");
184  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_SetClientData,
185  "SimConnect_SetClientData");
186  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_RequestDataOnSimObject,
187  "SimConnect_RequestDataOnSimObject");
188  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_RequestClientData,
189  "SimConnect_RequestClientData");
190  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_SubscribeToSystemEvent,
191  "SimConnect_SubscribeToSystemEvent");
192  resolveSuccess =
193  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_MapClientEventToSimEvent,
194  "SimConnect_MapClientEventToSimEvent");
195  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_SubscribeToFacilities,
196  "SimConnect_SubscribeToFacilities");
197  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_GetLastSentPacketID,
198  "SimConnect_GetLastSentPacketID");
199  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_AIRemoveObject,
200  "SimConnect_AIRemoveObject");
201  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_SetDataOnSimObject,
202  "SimConnect_SetDataOnSimObject");
203  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_AIReleaseControl,
204  "SimConnect_AIReleaseControl");
205  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_AICreateNonATCAircraft,
206  "SimConnect_AICreateNonATCAircraft");
207  resolveSuccess =
208  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_AICreateEnrouteATCAircraft,
209  "SimConnect_AICreateEnrouteATCAircraft");
210  resolveSuccess =
211  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_AICreateParkedATCAircraft,
212  "SimConnect_AICreateParkedATCAircraft");
213  resolveSuccess =
214  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_AICreateSimulatedObject,
215  "SimConnect_AICreateSimulatedObject");
216  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_MapClientDataNameToID,
217  "SimConnect_MapClientDataNameToID");
218  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_CreateClientData,
219  "SimConnect_CreateClientData");
220  resolveSuccess =
221  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_AddToClientDataDefinition,
222  "SimConnect_AddToClientDataDefinition");
223  return resolveSuccess;
224 }
225 
226 #ifdef Q_OS_WIN64
227 bool resolveP3DSimConnectSymbols(QLibrary &simConnectDll)
228 {
229  bool resolveSuccess = true;
230  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_RequestGroundInfo,
231  "SimConnect_RequestGroundInfo");
232  resolveSuccess = resolveSuccess &
233  resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_ChangeView, "SimConnect_ChangeView");
234  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_AIReleaseControlEx,
235  "SimConnect_AIReleaseControlEx");
236  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_CreateCameraDefinition,
237  "SimConnect_CreateCameraDefinition");
238  resolveSuccess =
239  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_ObserverAttachToEntityOn,
240  "SimConnect_ObserverAttachToEntityOn");
241  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_CreateObserver,
242  "SimConnect_CreateObserver");
243  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_CreateCameraInstance,
244  "SimConnect_CreateCameraInstance");
245  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_DeleteCameraInstance,
246  "SimConnect_DeleteCameraInstance");
247  resolveSuccess = resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_SetObserverLookAt,
248  "SimConnect_SetObserverLookAt");
249  resolveSuccess =
250  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_OpenView, "SimConnect_OpenView");
251  resolveSuccess =
252  resolveSuccess & resolveSimConnectSymbol(simConnectDll, gSymbols.SimConnect_CloseView, "SimConnect_CloseView");
253  return resolveSuccess;
254 }
255 
256 P3DSimConnectVersion stringToP3DVersion(const QString &p3d)
257 {
258  if (p3d.length() >= 2)
259  {
260  const QString p = digitOnlyString(p3d);
261  if (p.contains("40")) { return P3DSimConnectv40; }
262  if (p.contains("41")) { return P3DSimConnectv41; }
263  if (p.contains("42")) { return P3DSimConnectv42; }
264  if (p.contains("43")) { return P3DSimConnectv43; }
265  if (p.contains("44")) { return P3DSimConnectv44; }
266  if (p.contains("45")) { return P3DSimConnectv45; }
267 
268  if (p.contains("50")) { return P3DSimConnectv45; }
269  if (p.contains("51")) { return P3DSimConnectv45; }
270  if (p.contains("52")) { return P3DSimConnectv45; }
271  }
272  return P3DSimConnectv44; // default
273 }
274 
275 bool loadAndResolveP3DSimConnect(P3DSimConnectVersion version)
276 {
277  // Check if already loaded
278  if (gSymbols.SimConnect_Open) { return true; }
279 
280  QString simConnectFileName(QStringLiteral("SimConnect.P3D-"));
281 
282  switch (version)
283  {
284  case P3DSimConnectv40: simConnectFileName += "v4.0"; break;
285  case P3DSimConnectv41: simConnectFileName += "v4.1"; break;
286  case P3DSimConnectv42: simConnectFileName += "v4.2"; break;
287  case P3DSimConnectv43: simConnectFileName += "v4.3"; break;
288  case P3DSimConnectv44: simConnectFileName += "v4.4"; break;
289  case P3DSimConnectv45: simConnectFileName += "v4.5"; break;
290  }
291 
292  QLibrary simConnectDll(simConnectFileName);
293  simConnectDll.setLoadHints(QLibrary::PreventUnloadHint);
294  if (simConnectDll.load())
295  {
296  const bool resolvedCommon = resolveCommonSimConnectSymbols(simConnectDll);
297  const bool resolvedP3DSimConnectSymbols = resolveP3DSimConnectSymbols(simConnectDll);
298  if (!resolvedCommon)
299  {
300  CLogMessage(CLogCategories::driver()).error(u"Failed to resolve common symbols from SimConnect.dll: '%1'")
301  << simConnectFileName;
302  return false;
303  }
304  if (!resolvedP3DSimConnectSymbols)
305  {
306  CLogMessage(CLogCategories::driver()).error(u"Failed to resolve P3D symbols from SimConnect.dll: '%1'")
307  << simConnectFileName;
308  return false;
309  }
310 
311  CLogMessage(CLogCategories::driver()).info(u"Loaded and resolved P3D symbols from SimConnect.dll: '%1'")
312  << simConnectFileName;
313  return resolvedCommon && resolvedP3DSimConnectSymbols;
314  }
315  else
316  {
317  CLogMessage(CLogCategories::driver()).error(u"Failed to load SimConnect.dll: '%1' '%2'")
318  << simConnectFileName << simConnectDll.errorString();
319  return false;
320  }
321 }
322 
323 bool loadAndResolveMSFSimConnect()
324 {
325  // Check if already loaded
326  if (gSymbols.SimConnect_Open) { return true; }
327 
328  QString simConnectFileName(QStringLiteral("SimConnect.MSFS"));
329 
330  QLibrary simConnectDll(simConnectFileName);
331  simConnectDll.setLoadHints(QLibrary::PreventUnloadHint);
332  if (simConnectDll.load())
333  {
334  const bool resolvedCommon = resolveCommonSimConnectSymbols(simConnectDll);
335  if (!resolvedCommon)
336  {
337  CLogMessage(CLogCategories::driver()).error(u"Failed to resolve common symbols from SimConnect.dll: '%1'")
338  << simConnectFileName;
339  return false;
340  }
341 
342  CLogMessage(CLogCategories::driver()).info(u"Loaded and resolved MSFS symbols from SimConnect.dll: '%1'")
343  << simConnectFileName;
344  return resolvedCommon;
345  }
346  else
347  {
348  CLogMessage(CLogCategories::driver()).error(u"Failed to load SimConnect.dll: '%1' '%2'")
349  << simConnectFileName << simConnectDll.errorString();
350  return false;
351  }
352 }
353 
354 bool loadAndResolveMSFS2024SimConnect()
355 {
356  // Check if already loaded
357  if (gSymbols.SimConnect_Open) { return true; }
358 
359  QString simConnectFileName(QStringLiteral("SimConnect.MSFS2024"));
360 
361  QLibrary simConnectDll(simConnectFileName);
362  simConnectDll.setLoadHints(QLibrary::PreventUnloadHint);
363  if (simConnectDll.load())
364  {
365  const bool resolvedCommon = resolveCommonSimConnectSymbols(simConnectDll);
366  if (!resolvedCommon)
367  {
368  CLogMessage(CLogCategories::driver()).error(u"Failed to resolve common symbols from SimConnect.dll: '%1'")
369  << simConnectFileName;
370  return false;
371  }
372 
373  CLogMessage(CLogCategories::driver()).info(u"Loaded and resolved MSFS2024 symbols from SimConnect.dll: '%1'")
374  << simConnectFileName;
375  return resolvedCommon;
376  }
377  else
378  {
379  CLogMessage(CLogCategories::driver()).error(u"Failed to load SimConnect.dll: '%1' '%2'")
380  << simConnectFileName << simConnectDll.errorString();
381  return false;
382  }
383 }
384 
385 #else
386 bool loadAndResolveFsxSimConnect(bool manifestProbing)
387 {
388  // Check if already loaded
389  if (gSymbols.SimConnect_Open) { return true; }
390 
391  QLibrary simConnectDll(QStringLiteral("SimConnect"));
392  simConnectDll.setLoadHints(QLibrary::PreventUnloadHint);
393  if (manifestProbing)
394  {
395  HMODULE hInst = nullptr;
396  GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)loadAndResolveSimConnect, &hInst);
397  wchar_t szModuleName[MAX_PATH];
398  GetModuleFileName(hInst, szModuleName, MAX_PATH);
399 
400  // 101 => "SimConnect_RTM.manifest"
401  // 102 => "SimConnect_SP1.manifest"
402  // 103 => "SimConnect_XPack.manifest"
403  // Use only SP1 and XPack, since RTM is missing two important symbols.
404  // Try the latest one first.
405  std::array<WORD, 2> resourceNumbers = { { 103U, 102U } };
406 
407  for (const auto resourceNumber : resourceNumbers)
408  {
409  ACTCTX actCtx;
410  memset(&actCtx, 0, sizeof(ACTCTX));
411  actCtx.cbSize = sizeof(actCtx);
412  actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
413  actCtx.lpSource = szModuleName;
414  actCtx.lpResourceName = MAKEINTRESOURCE(resourceNumber);
415 
416  HANDLE hActCtx;
417  hActCtx = CreateActCtx(&actCtx);
418  if (hActCtx != INVALID_HANDLE_VALUE)
419  {
420  ULONG_PTR lpCookie = 0;
421  if (ActivateActCtx(hActCtx, &lpCookie))
422  {
423  simConnectDll.load();
424  DeactivateActCtx(0, lpCookie);
425  if (simConnectDll.isLoaded()) { break; }
426  }
427  }
428  ReleaseActCtx(hActCtx);
429  }
430  }
431 
432  // If at that stage, no SimConnect library was found in the WinSxS folder, try once without activation context to
433  // link to the one we ship ourselves.
434  if (!simConnectDll.isLoaded()) { simConnectDll.load(); }
435 
436  if (simConnectDll.isLoaded()) { return resolveCommonSimConnectSymbols(simConnectDll); }
437  else
438  {
439  CLogMessage(CLogCategories::driver()).error(u"Failed to load SimConnect.dll: %1")
440  << simConnectDll.errorString();
441  return false;
442  }
443 }
444 
445 #endif
446 
447 SIMCONNECTAPI SimConnect_Open(HANDLE *phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle,
448  DWORD ConfigIndex)
449 {
450  return gSymbols.SimConnect_Open(phSimConnect, szName, hWnd, UserEventWin32, hEventHandle, ConfigIndex);
451 }
452 
453 SIMCONNECTAPI SimConnect_Close(HANDLE hSimConnect) { return gSymbols.SimConnect_Close(hSimConnect); }
454 
455 SIMCONNECTAPI SimConnect_AddToDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID,
456  const char *DatumName, const char *UnitsName,
457  SIMCONNECT_DATATYPE DatumType, float fEpsilon, DWORD DatumID)
458 {
459  return gSymbols.SimConnect_AddToDataDefinition(hSimConnect, DefineID, DatumName, UnitsName, DatumType, fEpsilon,
460  DatumID);
461 }
462 
463 SIMCONNECTAPI SimConnect_Text(HANDLE hSimConnect, SIMCONNECT_TEXT_TYPE type, float fTimeSeconds,
464  SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD cbUnitSize, void *pDataSet)
465 {
466  return gSymbols.SimConnect_Text(hSimConnect, type, fTimeSeconds, EventID, cbUnitSize, pDataSet);
467 }
468 
469 SIMCONNECTAPI SimConnect_CallDispatch(HANDLE hSimConnect, DispatchProc pfcnDispatch, void *pContext)
470 {
471  return gSymbols.SimConnect_CallDispatch(hSimConnect, pfcnDispatch, pContext);
472 }
473 
474 SIMCONNECTAPI SimConnect_WeatherSetModeCustom(HANDLE hSimConnect)
475 {
476  return gSymbols.SimConnect_WeatherSetModeCustom(hSimConnect);
477 }
478 
479 SIMCONNECTAPI SimConnect_WeatherSetModeGlobal(HANDLE hSimConnect)
480 {
481  return gSymbols.SimConnect_WeatherSetModeGlobal(hSimConnect);
482 }
483 
484 SIMCONNECTAPI SimConnect_WeatherSetObservation(HANDLE hSimConnect, DWORD Seconds, const char *szMETAR)
485 {
486  return gSymbols.SimConnect_WeatherSetObservation(hSimConnect, Seconds, szMETAR);
487 }
488 
489 SIMCONNECTAPI SimConnect_TransmitClientEvent(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID,
490  SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD dwData,
491  SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_EVENT_FLAG Flags)
492 {
493  return gSymbols.SimConnect_TransmitClientEvent(hSimConnect, ObjectID, EventID, dwData, GroupID, Flags);
494 }
495 
496 SIMCONNECTAPI SimConnect_SetClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID,
497  SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID,
498  SIMCONNECT_CLIENT_DATA_SET_FLAG Flags, DWORD dwReserved, DWORD cbUnitSize,
499  void *pDataSet)
500 {
501  return gSymbols.SimConnect_SetClientData(hSimConnect, ClientDataID, DefineID, Flags, dwReserved, cbUnitSize,
502  pDataSet);
503 }
504 
505 SIMCONNECTAPI SimConnect_RequestDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID,
506  SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID,
507  SIMCONNECT_PERIOD Period, SIMCONNECT_DATA_REQUEST_FLAG Flags,
508  DWORD origin, DWORD interval, DWORD limit)
509 {
510  return gSymbols.SimConnect_RequestDataOnSimObject(hSimConnect, RequestID, DefineID, ObjectID, Period, Flags, origin,
511  interval, limit);
512 }
513 
514 SIMCONNECTAPI SimConnect_RequestClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID,
515  SIMCONNECT_DATA_REQUEST_ID RequestID,
516  SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID,
517  SIMCONNECT_CLIENT_DATA_PERIOD Period,
518  SIMCONNECT_CLIENT_DATA_REQUEST_FLAG Flags, DWORD origin, DWORD interval,
519  DWORD limit)
520 {
521  return gSymbols.SimConnect_RequestClientData(hSimConnect, ClientDataID, RequestID, DefineID, Period, Flags, origin,
522  interval, limit);
523 }
524 
525 SIMCONNECTAPI SimConnect_SubscribeToSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID,
526  const char *SystemEventName)
527 {
528  return gSymbols.SimConnect_SubscribeToSystemEvent(hSimConnect, EventID, SystemEventName);
529 }
530 
531 SIMCONNECTAPI SimConnect_MapClientEventToSimEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID,
532  const char *EventName)
533 {
534  return gSymbols.SimConnect_MapClientEventToSimEvent(hSimConnect, EventID, EventName);
535 }
536 
537 SIMCONNECTAPI SimConnect_SubscribeToFacilities(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type,
538  SIMCONNECT_DATA_REQUEST_ID RequestID)
539 {
540  return gSymbols.SimConnect_SubscribeToFacilities(hSimConnect, type, RequestID);
541 }
542 
543 SIMCONNECTAPI SimConnect_GetLastSentPacketID(HANDLE hSimConnect, DWORD *pdwError)
544 {
545  return gSymbols.SimConnect_GetLastSentPacketID(hSimConnect, pdwError);
546 }
547 
548 SIMCONNECTAPI SimConnect_AIRemoveObject(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID,
549  SIMCONNECT_DATA_REQUEST_ID RequestID)
550 {
551  return gSymbols.SimConnect_AIRemoveObject(hSimConnect, ObjectID, RequestID);
552 }
553 
554 SIMCONNECTAPI SimConnect_SetDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID,
555  SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_SET_FLAG Flags,
556  DWORD ArrayCount, DWORD cbUnitSize, void *pDataSet)
557 {
558  return gSymbols.SimConnect_SetDataOnSimObject(hSimConnect, DefineID, ObjectID, Flags, ArrayCount, cbUnitSize,
559  pDataSet);
560 }
561 
562 SIMCONNECTAPI SimConnect_AIReleaseControl(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID,
563  SIMCONNECT_DATA_REQUEST_ID RequestID)
564 {
565  return gSymbols.SimConnect_AIReleaseControl(hSimConnect, ObjectID, RequestID);
566 }
567 
568 SIMCONNECTAPI SimConnect_AICreateNonATCAircraft(HANDLE hSimConnect, const char *szContainerTitle,
569  const char *szTailNumber, SIMCONNECT_DATA_INITPOSITION InitPos,
570  SIMCONNECT_DATA_REQUEST_ID RequestID)
571 {
572  return gSymbols.SimConnect_AICreateNonATCAircraft(hSimConnect, szContainerTitle, szTailNumber, InitPos, RequestID);
573 }
574 
575 SIMCONNECTAPI SimConnect_AICreateEnrouteATCAircraft(HANDLE hSimConnect, const char *szContainerTitle,
576  const char *szTailNumber, int iFlightNumber,
577  const char *szFlightPlanPath, double dFlightPlanPosition,
578  BOOL bTouchAndGo, SIMCONNECT_DATA_REQUEST_ID RequestID)
579 {
580  return gSymbols.SimConnect_AICreateEnrouteATCAircraft(hSimConnect, szContainerTitle, szTailNumber, iFlightNumber,
581  szFlightPlanPath, dFlightPlanPosition, bTouchAndGo,
582  RequestID);
583 }
584 
585 SIMCONNECTAPI SimConnect_AICreateParkedATCAircraft(HANDLE hSimConnect, const char *szContainerTitle,
586  const char *szTailNumber, const char *szAirportID,
587  SIMCONNECT_DATA_REQUEST_ID RequestID)
588 {
589  return gSymbols.SimConnect_AICreateParkedATCAircraft(hSimConnect, szContainerTitle, szTailNumber, szAirportID,
590  RequestID);
591 }
592 
593 SIMCONNECTAPI SimConnect_AICreateSimulatedObject(HANDLE hSimConnect, const char *szContainerTitle,
594  SIMCONNECT_DATA_INITPOSITION InitPos,
595  SIMCONNECT_DATA_REQUEST_ID RequestID)
596 {
597  return gSymbols.SimConnect_AICreateSimulatedObject(hSimConnect, szContainerTitle, InitPos, RequestID);
598 }
599 
600 SIMCONNECTAPI SimConnect_MapClientDataNameToID(HANDLE hSimConnect, const char *szClientDataName,
601  SIMCONNECT_CLIENT_DATA_ID ClientDataID)
602 {
603  return gSymbols.SimConnect_MapClientDataNameToID(hSimConnect, szClientDataName, ClientDataID);
604 }
605 
606 SIMCONNECTAPI SimConnect_CreateClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, DWORD dwSize,
607  SIMCONNECT_CREATE_CLIENT_DATA_FLAG Flags)
608 {
609  return gSymbols.SimConnect_CreateClientData(hSimConnect, ClientDataID, dwSize, Flags);
610 }
611 
612 SIMCONNECTAPI SimConnect_AddToClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID,
613  DWORD dwOffset, DWORD dwSizeOrType, float fEpsilon, DWORD DatumID)
614 {
615  return gSymbols.SimConnect_AddToClientDataDefinition(hSimConnect, DefineID, dwOffset, dwSizeOrType, fEpsilon,
616  DatumID);
617 }
618 
619 #ifdef Q_OS_WIN64
620 SIMCONNECTAPI SimConnect_RequestGroundInfo(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, double minLat,
621  double minLon, double minAlt, double maxLat, double maxLon, double maxAlt,
622  DWORD dwGridWidth, DWORD dwGridHeight,
623  SIMCONNECT_GROUND_INFO_LATLON_FORMAT eLatLonFormat,
624  SIMCONNECT_GROUND_INFO_ALT_FORMAT eAltFormat,
625  SIMCONNECT_GROUND_INFO_SOURCE_FLAG eSourceFlags)
626 {
627  return gSymbols.SimConnect_RequestGroundInfo(hSimConnect, RequestID, minLat, minLon, minAlt, maxLat, maxLon, maxAlt,
628  dwGridWidth, dwGridHeight, eLatLonFormat, eAltFormat, eSourceFlags);
629 }
630 
631 SIMCONNECTAPI SimConnect_ChangeView(HANDLE hSimConnect, const char *szName)
632 {
633  return gSymbols.SimConnect_ChangeView(hSimConnect, szName);
634 }
635 
636 SIMCONNECTAPI SimConnect_AIReleaseControlEx(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID,
637  SIMCONNECT_DATA_REQUEST_ID RequestID, BOOL destroyAI)
638 {
639  return gSymbols.SimConnect_AIReleaseControlEx(hSimConnect, ObjectID, RequestID, destroyAI);
640 }
641 
642 SIMCONNECTAPI SimConnect_ObserverAttachToEntityOn(HANDLE hSimConnect, const char *szName, DWORD dwObjectID,
643  SIMCONNECT_DATA_XYZ Offset)
644 {
645  return gSymbols.SimConnect_ObserverAttachToEntityOn(hSimConnect, szName, dwObjectID, Offset);
646 }
647 
648 SIMCONNECTAPI SimConnect_CreateObserver(HANDLE hSimConnect, const char *szName, SIMCONNECT_DATA_OBSERVER ObserverData)
649 {
650  return gSymbols.SimConnect_CreateObserver(hSimConnect, szName, ObserverData);
651 }
652 
653 SIMCONNECTAPI SimConnect_OpenView(HANDLE hSimConnect, const char *szName, const char *szTitle)
654 {
655  return gSymbols.SimConnect_OpenView(hSimConnect, szName, szTitle);
656 }
657 
658 SIMCONNECTAPI SimConnect_CloseView(HANDLE hSimConnect, const char *szName)
659 {
660  return gSymbols.SimConnect_CloseView(hSimConnect, szName);
661 }
662 
663 SIMCONNECTAPI SimConnect_SetObserverLookAt(HANDLE hSimConnect, const char *szName,
664  SIMCONNECT_DATA_LATLONALT TargetPosition)
665 {
666  return gSymbols.SimConnect_SetObserverLookAt(hSimConnect, szName, TargetPosition);
667 }
668 
669 #endif
static const QString & driver()
Driver.
Class for emitting a log message.
Definition: logmessage.h:27
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
Free functions in swift::misc.
QString digitOnlyString(const QString &string)
String only with digits.
Definition: stringutils.h:186
FSXCOMMON_EXPORT bool loadAndResolveFsxSimConnect(bool manifestProbing)
Load and resolve FSX SimConnect.
unsigned long DWORD
Fake Windows DWORD.
adding struct SIMCONNECT_DATA_PBH not existing in SimConnect FSX