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 WriteLineConfig(IN LPTSTR szDeviceName, 163 IN LPTSTR szLineName, 164 IN PSNDVOL_REG_LINESTATE LineState, 165 IN DWORD cbSize) 166 { 167 HKEY hLineKey; 168 TCHAR szDevRegKey[MAX_PATH]; 169 BOOL Ret = FALSE; 170 171 _stprintf(szDevRegKey, 172 TEXT("%s\\%s"), 173 szDeviceName, 174 szLineName); 175 176 if (RegCreateKeyEx(hAppSettingsKey, 177 szDevRegKey, 178 0, 179 NULL, 180 REG_OPTION_NON_VOLATILE, 181 KEY_READ | KEY_WRITE, 182 NULL, 183 &hLineKey, 184 NULL) == ERROR_SUCCESS) 185 { 186 /* now update line states */ 187 RegSetValueEx(hLineKey, LineStatesValue, 0, REG_BINARY, (const BYTE*)LineState, cbSize); 188 Ret = TRUE; 189 190 RegCloseKey(hLineKey); 191 } 192 193 return Ret; 194 } 195 196 BOOL 197 ReadLineConfig(IN LPTSTR szDeviceName, 198 IN LPTSTR szLineName, 199 IN LPTSTR szControlName, 200 OUT DWORD *Flags) 201 { 202 HKEY hLineKey; 203 DWORD Type; 204 DWORD i, Size = 0; 205 PSNDVOL_REG_LINESTATE LineStates = NULL; 206 TCHAR szDevRegKey[MAX_PATH]; 207 BOOL Ret = FALSE; 208 209 _stprintf(szDevRegKey, 210 TEXT("%s\\%s"), 211 szDeviceName, 212 szLineName); 213 214 if (RegCreateKeyEx(hAppSettingsKey, 215 szDevRegKey, 216 0, 217 NULL, 218 REG_OPTION_NON_VOLATILE, 219 KEY_READ | KEY_WRITE, 220 NULL, 221 &hLineKey, 222 NULL) == ERROR_SUCCESS) 223 { 224 if (RegQueryValueEx(hLineKey, 225 LineStatesValue, 226 NULL, 227 &Type, 228 NULL, 229 &Size) != ERROR_SUCCESS || 230 Type != REG_BINARY || 231 Size == 0 || (Size % sizeof(SNDVOL_REG_LINESTATE) != 0)) 232 { 233 goto ExitClose; 234 } 235 236 LineStates = HeapAlloc(GetProcessHeap(), 237 HEAP_ZERO_MEMORY, 238 Size); 239 240 if (LineStates != NULL) 241 { 242 if (RegQueryValueEx(hLineKey, 243 LineStatesValue, 244 NULL, 245 &Type, 246 (LPBYTE)LineStates, 247 &Size) != ERROR_SUCCESS || 248 Type != REG_BINARY || 249 Size == 0 || (Size % sizeof(SNDVOL_REG_LINESTATE) != 0)) 250 { 251 goto ExitClose; 252 } 253 254 /* try to find the control */ 255 for (i = 0; i < Size / sizeof(SNDVOL_REG_LINESTATE); i++) 256 { 257 if (!_tcscmp(szControlName, 258 LineStates[i].LineName)) 259 { 260 *Flags = LineStates[i].Flags; 261 Ret = TRUE; 262 break; 263 } 264 } 265 } 266 267 ExitClose: 268 HeapFree(GetProcessHeap(), 269 0, 270 LineStates); 271 RegCloseKey(hLineKey); 272 } 273 274 return Ret; 275 } 276