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