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
LengthOfStrResource(IN HINSTANCE hInst,IN UINT uID)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
AllocAndLoadString(OUT LPWSTR * lpTarget,IN HINSTANCE hInst,IN UINT uID)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
LoadAndFormatString(IN HINSTANCE hInstance,IN UINT uID,OUT LPWSTR * lpTarget,...)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
InitAppConfig(VOID)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
CloseAppConfig(VOID)152 CloseAppConfig(VOID)
153 {
154 if (hAppSettingsKey != NULL)
155 {
156 RegCloseKey(hAppSettingsKey);
157 hAppSettingsKey = NULL;
158 }
159 }
160
161 BOOL
LoadXYCoordWnd(IN PPREFERENCES_CONTEXT PrefContext)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
SaveXYCoordWnd(IN HWND hWnd,IN PPREFERENCES_CONTEXT PrefContext)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
WriteLineConfig(IN LPTSTR szDeviceName,IN LPTSTR szLineName,IN PSNDVOL_REG_LINESTATE LineState,IN DWORD cbSize)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
ReadLineConfig(IN LPTSTR szDeviceName,IN LPTSTR szLineName,IN LPTSTR szControlName,OUT DWORD * Flags)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
GetStyleValue(VOID)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