FS2_Open
Open source remastering of the Freespace 2 engine
osregistry.cpp
Go to the documentation of this file.
1 /*
2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
3 *
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on the
6 * source.
7 *
8 */
9 
10 #include <string.h>
11 #include <windows.h>
12 
13 #include <Shlobj.h>
14 #include <Sddl.h>
15 
16 #include "globalincs/pstypes.h"
17 #include "osapi/osregistry.h"
18 #include "cmdline/cmdline.h"
19 
20 // ------------------------------------------------------------------------------------------------------------
21 // REGISTRY DEFINES/VARS
22 //
23 
24 static char szCompanyName[128];
25 static char szAppName[128];
26 static char szAppVersion[128];
27 
28 const char *Osreg_company_name = "Volition";
29 const char *Osreg_class_name = "FreeSpace2Class";
30 
31 // RT Lets make all versions use the same registry location
32 // If we don't the launcher either needs to handle somehow telling what release type a
33 // FS2 exe is or it won't work. Its far similar to just use one default location.
34 // The Launcher will set up everything needed
35 const char *Osreg_app_name = "FreeSpace2";
36 const char *Osreg_title = "FreeSpace 2";
37 
38 const char *Osreg_pref_dir = NULL;
39 
40 int Os_reg_inited = 0;
41 
42 // For string config functions
43 static char tmp_string_data[1024];
44 
45 // This code is needed for compatibility with the old windows registry
46 
47 static bool userSIDValid = false;
48 static SCP_string userSID;
49 
50 bool get_user_sid(SCP_string& outStr)
51 {
52  HANDLE hToken = NULL;
53  if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) == FALSE)
54  {
55  mprintf(("Failed to get process token! Error Code: %d", GetLastError()));
56 
57  return false;
58  }
59 
60  DWORD dwBufferSize;
61  GetTokenInformation(hToken, TokenUser, NULL, 0, &dwBufferSize);
62 
63  PTOKEN_USER ptkUser = (PTOKEN_USER) new byte[dwBufferSize];
64 
65  if (GetTokenInformation(hToken, TokenUser, ptkUser, dwBufferSize, &dwBufferSize))
66  {
67  CloseHandle(hToken);
68  }
69 
70  if (IsValidSid(ptkUser->User.Sid) == FALSE)
71  {
72  mprintf(("Invalid SID structure detected!"));
73 
74  delete[] ptkUser;
75  return false;
76  }
77 
78  LPTSTR sidName = NULL;
79  if (ConvertSidToStringSid(ptkUser->User.Sid, &sidName) == 0)
80  {
81  mprintf(("Failed to convert SID structure to string! Error Code: %d", GetLastError()));
82 
83  delete[] ptkUser;
84  return false;
85  }
86 
87  outStr.assign(sidName);
88 
89  LocalFree(sidName);
90  delete[](byte*) ptkUser;
91 
92  return true;
93 }
94 
95 bool needsWOW64()
96 {
97 #ifdef _WIN64
98  // 64-bit application always use the Wow6432Node
99  return true;
100 #else
101  BOOL bIsWow64 = FALSE;
102  if (!IsWow64Process(GetCurrentProcess(), &bIsWow64))
103  {
104  mprintf(("Failed to determine if we run under Wow64, registry configuration may fail!"));
105  return false;
106  }
107 
108  return bIsWow64 == TRUE;
109 #endif
110 }
111 
112 HKEY get_registry_keyname(char* out_keyname, const char* section)
113 {
114  if (!Cmdline_alternate_registry_path) {
115  // Use the original registry path, sometimes breaks for no reason which can be fixed by the code below
116  if (section) {
117  sprintf(out_keyname, "Software\\%s\\%s\\%s", szCompanyName, szAppName, section);
118  }
119  else {
120  sprintf(out_keyname, "Software\\%s\\%s", szCompanyName, szAppName);
121  }
122  return HKEY_LOCAL_MACHINE;
123  }
124 
125  // Every compiler from Visual Studio 2008 onward should have support for UAC
126 #if _MSC_VER >= 1400
127  if (userSIDValid)
128  {
129  if (needsWOW64())
130  {
131  if (section) {
132  sprintf(out_keyname, "%s_Classes\\VirtualStore\\Machine\\Software\\Wow6432Node\\%s\\%s\\%s", userSID.c_str(), szCompanyName, szAppName, section);
133  }
134  else {
135  sprintf(out_keyname, "%s_Classes\\VirtualStore\\Machine\\Software\\Wow6432Node\\%s\\%s", userSID.c_str(), szCompanyName, szAppName);
136  }
137  }
138  else
139  {
140  if (section) {
141  sprintf(out_keyname, "%s_Classes\\VirtualStore\\Machine\\Software\\%s\\%s\\%s", userSID.c_str(), szCompanyName, szAppName, section);
142  }
143  else {
144  sprintf(out_keyname, "%s_Classes\\VirtualStore\\Machine\\Software\\%s\\%s", userSID.c_str(), szCompanyName, szAppName);
145  }
146  }
147 
148  return HKEY_USERS;
149  }
150  else
151  {
152  // This will probably fail
153  if (section) {
154  sprintf(out_keyname, "Software\\%s\\%s\\%s", szCompanyName, szAppName, section);
155  }
156  else {
157  sprintf(out_keyname, "Software\\%s\\%s", szCompanyName, szAppName);
158  }
159 
160  return HKEY_LOCAL_MACHINE;
161  }
162 #else
163  if (section) {
164  sprintf(out_keyname, "Software\\%s\\%s\\%s", szCompanyName, szAppName, section);
165  }
166  else {
167  sprintf(out_keyname, "Software\\%s\\%s", szCompanyName, szAppName);
168  }
169 
170  return HKEY_LOCAL_MACHINE;
171 #endif
172 }
173 
174 bool registry_has_value(const char *section, const char *name)
175 {
176  HKEY hKey = NULL;
177  char keyname[1024];
178  LONG lResult;
179  bool retVal = false;
180 
181  if (!Os_reg_inited) {
182  return NULL;
183  }
184 
185  HKEY useHKey = get_registry_keyname(keyname, section);
186 
187  lResult = RegOpenKeyEx(useHKey, // Where it is
188  keyname, // name of key
189  NULL, // DWORD reserved
190  KEY_QUERY_VALUE, // Allows all changes
191  &hKey); // Location to store key
192 
193  if (lResult != ERROR_SUCCESS) {
194  goto Cleanup;
195  }
196 
197  if (!name) {
198  goto Cleanup;
199  }
200 
201  lResult = RegQueryValueEx(hKey, // Handle to key
202  name, // The values name
203  NULL, // DWORD reserved
204  NULL, // What kind it is
205  NULL, // value to set
206  NULL); // How many bytes to set
207 
208  if (lResult != ERROR_SUCCESS) {
209  goto Cleanup;
210  }
211 
212  retVal = true;
213 
214 Cleanup:
215  if (hKey)
216  RegCloseKey(hKey);
217 
218  return retVal;
219 }
220 
221 void os_config_write_string(const char *section, const char *name, const char *value)
222 {
223  HKEY hKey = NULL;
224  DWORD dwDisposition;
225  char keyname[1024];
226  LONG lResult;
227 
228  if (!Os_reg_inited) {
229  return;
230  }
231 
232  HKEY useHKey = get_registry_keyname(keyname, section);
233 
234  lResult = RegCreateKeyEx(useHKey, // Where to add it
235  keyname, // name of key
236  NULL, // DWORD reserved
237  "", // Object class
238  REG_OPTION_NON_VOLATILE, // Save to disk
239  KEY_ALL_ACCESS, // Allows all changes
240  NULL, // Default security attributes
241  &hKey, // Location to store key
242  &dwDisposition); // Location to store status of key
243 
244  if (lResult != ERROR_SUCCESS) {
245  goto Cleanup;
246  }
247 
248  if (!name) {
249  goto Cleanup;
250  }
251 
252  lResult = RegSetValueEx(hKey, // Handle to key
253  name, // The values name
254  NULL, // DWORD reserved
255  REG_SZ, // null terminated string
256  (CONST BYTE *)value, // value to set
257  strlen(value) + 1); // How many bytes to set
258 
259  if (lResult != ERROR_SUCCESS) {
260  goto Cleanup;
261  }
262 
263 
264 Cleanup:
265  if (hKey)
266  RegCloseKey(hKey);
267 }
268 
269 void os_config_write_uint(const char *section, const char *name, uint value)
270 {
271  HKEY hKey = NULL;
272  DWORD dwDisposition;
273  char keyname[1024];
274  LONG lResult;
275 
276  if (!Os_reg_inited) {
277  return;
278  }
279 
280  HKEY useHKey = get_registry_keyname(keyname, section);
281 
282  lResult = RegCreateKeyEx(useHKey, // Where to add it
283  keyname, // name of key
284  NULL, // DWORD reserved
285  "", // Object class
286  REG_OPTION_NON_VOLATILE, // Save to disk
287  KEY_ALL_ACCESS, // Allows all changes
288  NULL, // Default security attributes
289  &hKey, // Location to store key
290  &dwDisposition); // Location to store status of key
291 
292  if (lResult != ERROR_SUCCESS) {
293  goto Cleanup;
294  }
295 
296  if (!name) {
297  goto Cleanup;
298  }
299 
300  lResult = RegSetValueEx(hKey, // Handle to key
301  name, // The values name
302  NULL, // DWORD reserved
303  REG_DWORD, // null terminated string
304  (CONST BYTE *)&value, // value to set
305  4); // How many bytes to set
306 
307  if (lResult != ERROR_SUCCESS) {
308  goto Cleanup;
309  }
310 
311 Cleanup:
312  if (hKey)
313  RegCloseKey(hKey);
314 
315 }
316 
317 // Reads a string from the INI file. If default is passed,
318 // and the string isn't found, returns ptr to default otherwise
319 // returns NULL; Copy the return value somewhere before
320 // calling os_read_string again, because it might reuse the
321 // same buffer.
322 const char * os_config_read_string(const char *section, const char *name, const char *default_value)
323 {
324  HKEY hKey = NULL;
325  DWORD dwType, dwLen;
326  char keyname[1024];
327  LONG lResult;
328 
329  if (!Os_reg_inited) {
330  return NULL;
331  }
332 
333  HKEY useHKey = get_registry_keyname(keyname, section);
334 
335  lResult = RegOpenKeyEx(useHKey, // Where it is
336  keyname, // name of key
337  NULL, // DWORD reserved
338  KEY_QUERY_VALUE, // Allows all changes
339  &hKey); // Location to store key
340 
341  if (lResult != ERROR_SUCCESS) {
342  goto Cleanup;
343  }
344 
345  if (!name) {
346  goto Cleanup;
347  }
348 
349  dwLen = 1024;
350  lResult = RegQueryValueEx(hKey, // Handle to key
351  name, // The values name
352  NULL, // DWORD reserved
353  &dwType, // What kind it is
354  (ubyte *)&tmp_string_data, // value to set
355  &dwLen); // How many bytes to set
356 
357  if (lResult != ERROR_SUCCESS) {
358  goto Cleanup;
359  }
360 
361  default_value = tmp_string_data;
362 
363 Cleanup:
364  if (hKey)
365  RegCloseKey(hKey);
366 
367  return default_value;
368 }
369 
370 // Reads a string from the INI file. Default_value must
371 // be passed, and if 'name' isn't found, then returns default_value
372 uint os_config_read_uint(const char *section, const char *name, uint default_value)
373 {
374  HKEY hKey = NULL;
375  DWORD dwType, dwLen;
376  char keyname[1024];
377  LONG lResult;
378  uint tmp_val;
379 
380  if (!Os_reg_inited) {
381  return default_value;
382  }
383 
384  HKEY useHKey = get_registry_keyname(keyname, section);
385 
386  lResult = RegOpenKeyEx(useHKey, // Where it is
387  keyname, // name of key
388  NULL, // DWORD reserved
389  KEY_QUERY_VALUE, // Allows all changes
390  &hKey); // Location to store key
391 
392  if (lResult != ERROR_SUCCESS) {
393  goto Cleanup;
394  }
395 
396  if (!name) {
397  goto Cleanup;
398  }
399 
400  dwLen = 4;
401  lResult = RegQueryValueEx(hKey, // Handle to key
402  name, // The values name
403  NULL, // DWORD reserved
404  &dwType, // What kind it is
405  (ubyte *)&tmp_val, // value to set
406  &dwLen); // How many bytes to set
407 
408  if (lResult != ERROR_SUCCESS) {
409  goto Cleanup;
410  }
411 
412  default_value = tmp_val;
413 
414 Cleanup:
415  if (hKey)
416  RegCloseKey(hKey);
417 
418  return default_value;
419 }
420 
421 
422 // initialize the registry. setup default keys to use
423 void os_init_registry_stuff(const char *company, const char *app, const char *version)
424 {
425  if (company) {
426  strcpy_s(szCompanyName, company);
427  }
428  else {
429  strcpy_s(szCompanyName, Osreg_company_name);
430  }
431 
432  if (app) {
433  strcpy_s(szAppName, app);
434  }
435  else {
436  strcpy_s(szAppName, Osreg_app_name);
437  }
438 
439  if (version) {
440  strcpy_s(szAppVersion, version);
441  }
442  else {
443  strcpy_s(szAppVersion, "1.0");
444  }
445 
446  OSVERSIONINFO versionInfo;
447  versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
448  GetVersionEx(&versionInfo);
449 
450  // Windows Vista is 6.0 which is the first version requiring this
451  if (versionInfo.dwMajorVersion >= 6)
452  {
453  userSIDValid = get_user_sid(userSID);
454  }
455 
456  Os_reg_inited = 1;
457 }
uint os_config_read_uint(const char *section, const char *name, uint default_value)
Definition: osregistry.cpp:372
int Os_reg_inited
Definition: osregistry.cpp:40
GLsizei const GLfloat * value
Definition: Glext.h:5646
#define mprintf(args)
Definition: pstypes.h:238
void os_init_registry_stuff(const char *company, const char *app, const char *version)
Definition: osregistry.cpp:423
#define TRUE
Definition: pstypes.h:399
const char * os_config_read_string(const char *section, const char *name, const char *default_value)
Definition: osregistry.cpp:322
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
void os_config_write_uint(const char *section, const char *name, uint value)
Definition: osregistry.cpp:269
bool get_user_sid(SCP_string &outStr)
Definition: osregistry.cpp:50
const char * Osreg_app_name
Definition: osregistry.cpp:35
void os_config_write_string(const char *section, const char *name, const char *value)
Definition: osregistry.cpp:221
bool needsWOW64()
Definition: osregistry.cpp:95
unsigned int uint
Definition: pstypes.h:64
bool registry_has_value(const char *section, const char *name)
Definition: osregistry.cpp:174
const char * Osreg_title
Definition: osregistry.cpp:36
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
unsigned long DWORD
Definition: config.h:90
unsigned char ubyte
Definition: pstypes.h:62
long LONG
Definition: config.h:95
HKEY get_registry_keyname(char *out_keyname, const char *section)
Definition: osregistry.cpp:112
GLuint const GLchar * name
Definition: Glext.h:5608
int BOOL
Definition: config.h:80
const char * Osreg_company_name
Definition: osregistry.cpp:28
const char * Osreg_class_name
Definition: osregistry.cpp:29
const char * Osreg_pref_dir
Definition: osregistry.cpp:38
void * HANDLE
Definition: config.h:106
#define FALSE
Definition: pstypes.h:400
#define strcpy_s(...)
Definition: safe_strings.h:67