1 /* 2 * ReactOS Sound Volume Control 3 * Copyright (C) 2004-2005 Thomas Weidenmueller 4 * 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. 9 * 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. 14 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 /* 20 * COPYRIGHT: See COPYING in the top level directory 21 * PROJECT: ReactOS Sound Volume Control 22 * FILE: base/applications/sndvol32/misc.c 23 * PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com> 24 */ 25 26 #include "sndvol32.h" 27 28 #include <winreg.h> 29 30 static INT 31 LengthOfStrResource(IN HINSTANCE hInst, 32 IN UINT uID) 33 { 34 HRSRC hrSrc; 35 HGLOBAL hRes; 36 LPWSTR lpName, lpStr; 37 38 if (hInst == NULL) 39 { 40 return -1; 41 } 42 43 /* There are always blocks of 16 strings */ 44 lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1); 45 46 /* Find the string table block */ 47 if ((hrSrc = FindResourceW(hInst, 48 lpName, 49 (LPWSTR)RT_STRING)) && 50 (hRes = LoadResource(hInst, 51 hrSrc)) && 52 (lpStr = LockResource(hRes))) 53 { 54 UINT x; 55 56 /* Find the string we're looking for */ 57 uID &= 0xF; /* position in the block, same as % 16 */ 58 for (x = 0; x < uID; x++) 59 { 60 lpStr += (*lpStr) + 1; 61 } 62 63 /* Found the string */ 64 return (int)(*lpStr); 65 } 66 return -1; 67 } 68 69 INT 70 AllocAndLoadString(OUT LPWSTR *lpTarget, 71 IN HINSTANCE hInst, 72 IN UINT uID) 73 { 74 INT ln; 75 76 ln = LengthOfStrResource(hInst, 77 uID); 78 if (ln++ > 0) 79 { 80 (*lpTarget) = (LPWSTR)LocalAlloc(LMEM_FIXED, 81 ln * sizeof(WCHAR)); 82 if ((*lpTarget) != NULL) 83 { 84 INT Ret = LoadStringW(hInst, 85 uID, 86 *lpTarget, 87 ln); 88 if (!Ret) 89 { 90 LocalFree((HLOCAL)(*lpTarget)); 91 } 92 return Ret; 93 } 94 } 95 return 0; 96 } 97 98 DWORD 99 LoadAndFormatString(IN HINSTANCE hInstance, 100 IN UINT uID, 101 OUT LPWSTR *lpTarget, 102 ...) 103 { 104 DWORD Ret = 0; 105 LPWSTR lpFormat; 106 va_list lArgs; 107 108 if (AllocAndLoadString(&lpFormat, 109 hInstance, 110 uID) > 0) 111 { 112 va_start(lArgs, lpTarget); 113 /* let's use FormatMessage to format it because it has the ability to 114 allocate memory automatically */ 115 Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, 116 lpFormat, 117 0, 118 0, 119 (LPWSTR)lpTarget, 120 0, 121 &lArgs); 122 va_end(lArgs); 123 124 LocalFree((HLOCAL)lpFormat); 125 } 126 127 return Ret; 128 } 129 130 static const TCHAR AppRegSettings[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Volume Control"); 131 static const TCHAR AppOptionsKey[] = TEXT("Options"); 132 static const TCHAR LineStatesValue[] = TEXT("LineStates"); 133 static const TCHAR StyleValue[] = TEXT("Style"); 134 135 HKEY hAppSettingsKey = NULL; 136 137 BOOL 138 InitAppConfig(VOID) 139 { 140 return RegCreateKeyEx(HKEY_CURRENT_USER, 141 AppRegSettings, 142 0, 143 NULL, 144 REG_OPTION_NON_VOLATILE, 145 KEY_READ | KEY_WRITE, 146 NULL, 147 &hAppSettingsKey, 148 NULL) == ERROR_SUCCESS; 149 } 150 151 VOID 152 CloseAppConfig(VOID) 153 { 154 if (hAppSettingsKey != NULL) 155 { 156 RegCloseKey(hAppSettingsKey); 157 hAppSettingsKey = NULL; 158 } 159 } 160 161 BOOL 162 LoadXYCoordWnd(IN PPREFERENCES_CONTEXT PrefContext) 163 { 164 HKEY hKey; 165 LONG lResult; 166 TCHAR DeviceMixerSettings[256]; 167 DWORD dwData; 168 DWORD cbData = sizeof(dwData); 169 170 /* Append the registry key path and device name key into one single string */ 171 StringCchPrintf(DeviceMixerSettings, _countof(DeviceMixerSettings), TEXT("%s\\%s"), AppRegSettings, PrefContext->DeviceName); 172 173 lResult = RegOpenKeyEx(HKEY_CURRENT_USER, 174 DeviceMixerSettings, 175 0, 176 KEY_READ, 177 &hKey); 178 if (lResult != ERROR_SUCCESS) 179 { 180 return FALSE; 181 } 182 183 lResult = RegQueryValueEx(hKey, 184 TEXT("X"), 185 0, 186 0, 187 (LPBYTE)&dwData, 188 &cbData); 189 if (lResult != ERROR_SUCCESS) 190 { 191 RegCloseKey(hKey); 192 return FALSE; 193 } 194 195 /* Cache the X coordinate point */ 196 PrefContext->MixerWindow->WndPosX = dwData; 197 198 lResult = RegQueryValueEx(hKey, 199 TEXT("Y"), 200 0, 201 0, 202 (LPBYTE)&dwData, 203 &cbData); 204 if (lResult != ERROR_SUCCESS) 205 { 206 RegCloseKey(hKey); 207 return FALSE; 208 } 209 210 /* Cache the Y coordinate point */ 211 PrefContext->MixerWindow->WndPosY = dwData; 212 213 RegCloseKey(hKey); 214 return TRUE; 215 } 216 217 BOOL 218 SaveXYCoordWnd(IN HWND hWnd, 219 IN PPREFERENCES_CONTEXT PrefContext) 220 { 221 HKEY hKey; 222 LONG lResult; 223 TCHAR DeviceMixerSettings[256]; 224 WINDOWPLACEMENT wp; 225 226 /* Get the placement coordinate data from the window */ 227 wp.length = sizeof(WINDOWPLACEMENT); 228 GetWindowPlacement(hWnd, &wp); 229 230 /* Append the registry key path and device name key into one single string */ 231 StringCchPrintf(DeviceMixerSettings, _countof(DeviceMixerSettings), TEXT("%s\\%s"), AppRegSettings, PrefContext->DeviceName); 232 233 lResult = RegOpenKeyEx(HKEY_CURRENT_USER, 234 DeviceMixerSettings, 235 0, 236 KEY_SET_VALUE, 237 &hKey); 238 if (lResult != ERROR_SUCCESS) 239 { 240 return FALSE; 241 } 242 243 lResult = RegSetValueEx(hKey, 244 TEXT("X"), 245 0, 246 REG_DWORD, 247 (LPBYTE)&wp.rcNormalPosition.left, 248 sizeof(wp.rcNormalPosition.left)); 249 if (lResult != ERROR_SUCCESS) 250 { 251 RegCloseKey(hKey); 252 return FALSE; 253 } 254 255 lResult = RegSetValueEx(hKey, 256 TEXT("Y"), 257 0, 258 REG_DWORD, 259 (LPBYTE)&wp.rcNormalPosition.top, 260 sizeof(wp.rcNormalPosition.top)); 261 if (lResult != ERROR_SUCCESS) 262 { 263 RegCloseKey(hKey); 264 return FALSE; 265 } 266 267 RegCloseKey(hKey); 268 return TRUE; 269 } 270 271 BOOL 272 WriteLineConfig(IN LPTSTR szDeviceName, 273 IN LPTSTR szLineName, 274 IN PSNDVOL_REG_LINESTATE LineState, 275 IN DWORD cbSize) 276 { 277 HKEY hLineKey; 278 TCHAR szDevRegKey[MAX_PATH]; 279 BOOL Ret = FALSE; 280 281 _stprintf(szDevRegKey, 282 TEXT("%s\\%s"), 283 szDeviceName, 284 szLineName); 285 286 if (RegCreateKeyEx(hAppSettingsKey, 287 szDevRegKey, 288 0, 289 NULL, 290 REG_OPTION_NON_VOLATILE, 291 KEY_READ | KEY_WRITE, 292 NULL, 293 &hLineKey, 294 NULL) == ERROR_SUCCESS) 295 { 296 /* now update line states */ 297 RegSetValueEx(hLineKey, LineStatesValue, 0, REG_BINARY, (const BYTE*)LineState, cbSize); 298 Ret = TRUE; 299 300 RegCloseKey(hLineKey); 301 } 302 303 return Ret; 304 } 305 306 BOOL 307 ReadLineConfig(IN LPTSTR szDeviceName, 308 IN LPTSTR szLineName, 309 IN LPTSTR szControlName, 310 OUT DWORD *Flags) 311 { 312 HKEY hLineKey; 313 DWORD Type; 314 DWORD i, Size = 0; 315 PSNDVOL_REG_LINESTATE LineStates = NULL; 316 TCHAR szDevRegKey[MAX_PATH]; 317 BOOL Ret = FALSE; 318 319 _stprintf(szDevRegKey, 320 TEXT("%s\\%s"), 321 szDeviceName, 322 szLineName); 323 324 if (RegCreateKeyEx(hAppSettingsKey, 325 szDevRegKey, 326 0, 327 NULL, 328 REG_OPTION_NON_VOLATILE, 329 KEY_READ | KEY_WRITE, 330 NULL, 331 &hLineKey, 332 NULL) == ERROR_SUCCESS) 333 { 334 if (RegQueryValueEx(hLineKey, 335 LineStatesValue, 336 NULL, 337 &Type, 338 NULL, 339 &Size) != ERROR_SUCCESS || 340 Type != REG_BINARY || 341 Size == 0 || (Size % sizeof(SNDVOL_REG_LINESTATE) != 0)) 342 { 343 goto ExitClose; 344 } 345 346 LineStates = HeapAlloc(GetProcessHeap(), 347 HEAP_ZERO_MEMORY, 348 Size); 349 350 if (LineStates != NULL) 351 { 352 if (RegQueryValueEx(hLineKey, 353 LineStatesValue, 354 NULL, 355 &Type, 356 (LPBYTE)LineStates, 357 &Size) != ERROR_SUCCESS || 358 Type != REG_BINARY || 359 Size == 0 || (Size % sizeof(SNDVOL_REG_LINESTATE) != 0)) 360 { 361 goto ExitClose; 362 } 363 364 /* try to find the control */ 365 for (i = 0; i < Size / sizeof(SNDVOL_REG_LINESTATE); i++) 366 { 367 if (!_tcscmp(szControlName, 368 LineStates[i].LineName)) 369 { 370 *Flags = LineStates[i].Flags; 371 Ret = TRUE; 372 break; 373 } 374 } 375 } 376 377 ExitClose: 378 HeapFree(GetProcessHeap(), 379 0, 380 LineStates); 381 RegCloseKey(hLineKey); 382 } 383 384 return Ret; 385 } 386 387 DWORD 388 GetStyleValue(VOID) 389 { 390 HKEY hOptionsKey; 391 DWORD dwStyle = 0, dwSize; 392 393 if (RegOpenKeyEx(hAppSettingsKey, 394 AppOptionsKey, 395 0, 396 KEY_READ, 397 &hOptionsKey) == ERROR_SUCCESS) 398 { 399 dwSize = sizeof(DWORD); 400 RegQueryValueEx(hOptionsKey, 401 StyleValue, 402 NULL, 403 NULL, 404 (LPBYTE)&dwStyle, 405 &dwSize); 406 407 RegCloseKey(hOptionsKey); 408 } 409 410 return dwStyle; 411 } 412