Atlas - SDL_windows.c
Home / ext / SDL2 / src / core / windows Lines: 1 | Size: 7213 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#if defined(__WIN32__) || defined(__WINRT__) 24 25#include "SDL_windows.h" 26#include "SDL_error.h" 27#include "SDL_assert.h" 28 29#include <objbase.h> /* for CoInitialize/CoUninitialize (Win32 only) */ 30 31#ifndef _WIN32_WINNT_VISTA 32#define _WIN32_WINNT_VISTA 0x0600 33#endif 34#ifndef _WIN32_WINNT_WIN7 35#define _WIN32_WINNT_WIN7 0x0601 36#endif 37 38 39/* Sets an error message based on an HRESULT */ 40int 41WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr) 42{ 43 TCHAR buffer[1024]; 44 char *message; 45 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, 46 buffer, SDL_arraysize(buffer), NULL); 47 message = WIN_StringToUTF8(buffer); 48 SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message); 49 SDL_free(message); 50 return -1; 51} 52 53/* Sets an error message based on GetLastError() */ 54int 55WIN_SetError(const char *prefix) 56{ 57 return WIN_SetErrorFromHRESULT(prefix, GetLastError()); 58} 59 60HRESULT 61WIN_CoInitialize(void) 62{ 63 /* SDL handles any threading model, so initialize with the default, which 64 is compatible with OLE and if that doesn't work, try multi-threaded mode. 65 66 If you need multi-threaded mode, call CoInitializeEx() before SDL_Init() 67 */ 68#ifdef __WINRT__ 69 /* DLudwig: On WinRT, it is assumed that COM was initialized in main(). 70 CoInitializeEx is available (not CoInitialize though), however 71 on WinRT, main() is typically declared with the [MTAThread] 72 attribute, which, AFAIK, should initialize COM. 73 */ 74 return S_OK; 75#else 76 HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 77 if (hr == RPC_E_CHANGED_MODE) { 78 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 79 } 80 81 /* S_FALSE means success, but someone else already initialized. */ 82 /* You still need to call CoUninitialize in this case! */ 83 if (hr == S_FALSE) { 84 return S_OK; 85 } 86 87 return hr; 88#endif 89} 90 91void 92WIN_CoUninitialize(void) 93{ 94#ifndef __WINRT__ 95 CoUninitialize(); 96#endif 97} 98 99#ifndef __WINRT__ 100static BOOL 101IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) 102{ 103 OSVERSIONINFOEXW osvi; 104 DWORDLONG const dwlConditionMask = VerSetConditionMask( 105 VerSetConditionMask( 106 VerSetConditionMask( 107 0, VER_MAJORVERSION, VER_GREATER_EQUAL ), 108 VER_MINORVERSION, VER_GREATER_EQUAL ), 109 VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL ); 110 111 SDL_zero(osvi); 112 osvi.dwOSVersionInfoSize = sizeof(osvi); 113 osvi.dwMajorVersion = wMajorVersion; 114 osvi.dwMinorVersion = wMinorVersion; 115 osvi.wServicePackMajor = wServicePackMajor; 116 117 return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; 118} 119#endif 120 121BOOL WIN_IsWindowsVistaOrGreater(void) 122{ 123#ifdef __WINRT__ 124 return TRUE; 125#else 126 return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0); 127#endif 128} 129 130BOOL WIN_IsWindows7OrGreater(void) 131{ 132#ifdef __WINRT__ 133 return TRUE; 134#else 135 return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0); 136#endif 137} 138 139/* 140WAVExxxCAPS gives you 31 bytes for the device name, and just truncates if it's 141longer. However, since WinXP, you can use the WAVExxxCAPS2 structure, which 142will give you a name GUID. The full name is in the Windows Registry under 143that GUID, located here: HKLM\System\CurrentControlSet\Control\MediaCategories 144 145Note that drivers can report GUID_NULL for the name GUID, in which case, 146Windows makes a best effort to fill in those 31 bytes in the usual place. 147This info summarized from MSDN: 148 149http://web.archive.org/web/20131027093034/http://msdn.microsoft.com/en-us/library/windows/hardware/ff536382(v=vs.85).aspx 150 151Always look this up in the registry if possible, because the strings are 152different! At least on Win10, I see "Yeti Stereo Microphone" in the 153Registry, and a unhelpful "Microphone(Yeti Stereo Microph" in winmm. Sigh. 154 155(Also, DirectSound shouldn't be limited to 32 chars, but its device enum 156has the same problem.) 157 158WASAPI doesn't need this. This is just for DirectSound/WinMM. 159*/ 160char * 161WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid) 162{ 163#if __WINRT__ 164 return WIN_StringToUTF8(name); /* No registry access on WinRT/UWP, go with what we've got. */ 165#else 166 static const GUID nullguid = { 0 }; 167 const unsigned char *ptr; 168 char keystr[128]; 169 WCHAR *strw = NULL; 170 SDL_bool rc; 171 HKEY hkey; 172 DWORD len = 0; 173 char *retval = NULL; 174 175 if (WIN_IsEqualGUID(guid, &nullguid)) { 176 return WIN_StringToUTF8(name); /* No GUID, go with what we've got. */ 177 } 178 179 ptr = (const unsigned char *) guid; 180 SDL_snprintf(keystr, sizeof (keystr), 181 "System\\CurrentControlSet\\Control\\MediaCategories\\{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 182 ptr[3], ptr[2], ptr[1], ptr[0], ptr[5], ptr[4], ptr[7], ptr[6], 183 ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]); 184 185 strw = WIN_UTF8ToString(keystr); 186 rc = (RegOpenKeyExW(HKEY_LOCAL_MACHINE, strw, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS); 187 SDL_free(strw); 188 if (!rc) { 189 return WIN_StringToUTF8(name); /* oh well. */ 190 } 191 192 rc = (RegQueryValueExW(hkey, L"Name", NULL, NULL, NULL, &len) == ERROR_SUCCESS); 193 if (!rc) { 194 RegCloseKey(hkey); 195 return WIN_StringToUTF8(name); /* oh well. */ 196 } 197 198 strw = (WCHAR *) SDL_malloc(len + sizeof (WCHAR)); 199 if (!strw) { 200 RegCloseKey(hkey); 201 return WIN_StringToUTF8(name); /* oh well. */ 202 } 203 204 rc = (RegQueryValueExW(hkey, L"Name", NULL, NULL, (LPBYTE) strw, &len) == ERROR_SUCCESS); 205 RegCloseKey(hkey); 206 if (!rc) { 207 SDL_free(strw); 208 return WIN_StringToUTF8(name); /* oh well. */ 209 } 210 211 strw[len / 2] = 0; /* make sure it's null-terminated. */ 212 213 retval = WIN_StringToUTF8(strw); 214 SDL_free(strw); 215 return retval ? retval : WIN_StringToUTF8(name); 216#endif /* if __WINRT__ / else */ 217} 218 219BOOL 220WIN_IsEqualGUID(const GUID * a, const GUID * b) 221{ 222 return (SDL_memcmp(a, b, sizeof (*a)) == 0); 223} 224 225BOOL 226WIN_IsEqualIID(REFIID a, REFIID b) 227{ 228 return (SDL_memcmp(a, b, sizeof (*a)) == 0); 229} 230 231#endif /* __WIN32__ || __WINRT__ */ 232 233/* vi: set ts=4 sw=4 expandtab: */ 234[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.