* Sync up to trunk head (r64939).
[reactos.git] / base / applications / sndvol32 / misc.c
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: subsys/system/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 }