xref: /reactos/base/applications/sndvol32/misc.c (revision ede7a20a)
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