Synchronize with trunk r58457.
[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 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS Sound Volume Control
23 * FILE: subsys/system/sndvol32/misc.c
24 * PROGRAMMERS: Thomas Weidenmueller <w3seek@reactos.com>
25 */
26
27 #include "sndvol32.h"
28
29 static INT
30 LengthOfStrResource(IN HINSTANCE hInst,
31 IN UINT uID)
32 {
33 HRSRC hrSrc;
34 HGLOBAL hRes;
35 LPWSTR lpName, lpStr;
36
37 if (hInst == NULL)
38 {
39 return -1;
40 }
41
42 /* There are always blocks of 16 strings */
43 lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1);
44
45 /* Find the string table block */
46 if ((hrSrc = FindResourceW(hInst,
47 lpName,
48 (LPWSTR)RT_STRING)) &&
49 (hRes = LoadResource(hInst,
50 hrSrc)) &&
51 (lpStr = LockResource(hRes)))
52 {
53 UINT x;
54
55 /* Find the string we're looking for */
56 uID &= 0xF; /* position in the block, same as % 16 */
57 for (x = 0; x < uID; x++)
58 {
59 lpStr += (*lpStr) + 1;
60 }
61
62 /* Found the string */
63 return (int)(*lpStr);
64 }
65 return -1;
66 }
67
68 INT
69 AllocAndLoadString(OUT LPWSTR *lpTarget,
70 IN HINSTANCE hInst,
71 IN UINT uID)
72 {
73 INT ln;
74
75 ln = LengthOfStrResource(hInst,
76 uID);
77 if (ln++ > 0)
78 {
79 (*lpTarget) = (LPWSTR)LocalAlloc(LMEM_FIXED,
80 ln * sizeof(WCHAR));
81 if ((*lpTarget) != NULL)
82 {
83 INT Ret = LoadStringW(hInst,
84 uID,
85 *lpTarget,
86 ln);
87 if (!Ret)
88 {
89 LocalFree((HLOCAL)(*lpTarget));
90 }
91 return Ret;
92 }
93 }
94 return 0;
95 }
96
97 DWORD
98 LoadAndFormatString(IN HINSTANCE hInstance,
99 IN UINT uID,
100 OUT LPWSTR *lpTarget,
101 ...)
102 {
103 DWORD Ret = 0;
104 LPWSTR lpFormat;
105 va_list lArgs;
106
107 if (AllocAndLoadString(&lpFormat,
108 hInstance,
109 uID) > 0)
110 {
111 va_start(lArgs, lpTarget);
112 /* let's use FormatMessage to format it because it has the ability to
113 allocate memory automatically */
114 Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
115 lpFormat,
116 0,
117 0,
118 (LPWSTR)lpTarget,
119 0,
120 &lArgs);
121 va_end(lArgs);
122
123 LocalFree((HLOCAL)lpFormat);
124 }
125
126 return Ret;
127 }
128
129 static const TCHAR AppRegSettings[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Volume Control");
130 static const TCHAR AppOptionsKey[] = TEXT("Options");
131 static const TCHAR LineStatesValue[] = TEXT("LineStates");
132 static const TCHAR StyleValue[] = TEXT("Style");
133
134 HKEY hAppSettingsKey = NULL;
135
136 BOOL
137 InitAppConfig(VOID)
138 {
139 return RegCreateKeyEx(HKEY_CURRENT_USER,
140 AppRegSettings,
141 0,
142 NULL,
143 REG_OPTION_NON_VOLATILE,
144 KEY_READ | KEY_WRITE,
145 NULL,
146 &hAppSettingsKey,
147 NULL) == ERROR_SUCCESS;
148 }
149
150 VOID
151 CloseAppConfig(VOID)
152 {
153 if (hAppSettingsKey != NULL)
154 {
155 RegCloseKey(hAppSettingsKey);
156 hAppSettingsKey = NULL;
157 }
158 }
159
160 BOOL
161 WriteLineConfig(IN LPTSTR szDeviceName,
162 IN LPTSTR szLineName,
163 IN PSNDVOL_REG_LINESTATE LineState,
164 IN DWORD cbSize)
165 {
166 HKEY hLineKey;
167 TCHAR szDevRegKey[MAX_PATH];
168 BOOL Ret = FALSE;
169
170 _stprintf(szDevRegKey,
171 TEXT("%s\\%s"),
172 szDeviceName,
173 szLineName);
174
175 if (RegCreateKeyEx(hAppSettingsKey,
176 szDevRegKey,
177 0,
178 NULL,
179 REG_OPTION_NON_VOLATILE,
180 KEY_READ | KEY_WRITE,
181 NULL,
182 &hLineKey,
183 NULL) == ERROR_SUCCESS)
184 {
185 /* now update line states */
186 RegSetValueEx(hLineKey, LineStatesValue, 0, REG_BINARY, (const BYTE*)LineState, cbSize);
187 Ret = TRUE;
188
189 RegCloseKey(hLineKey);
190 }
191
192 return Ret;
193 }
194
195 BOOL
196 ReadLineConfig(IN LPTSTR szDeviceName,
197 IN LPTSTR szLineName,
198 IN LPTSTR szControlName,
199 OUT DWORD *Flags)
200 {
201 HKEY hLineKey;
202 DWORD Type;
203 DWORD i, Size = 0;
204 PSNDVOL_REG_LINESTATE LineStates = NULL;
205 TCHAR szDevRegKey[MAX_PATH];
206 BOOL Ret = FALSE;
207
208 _stprintf(szDevRegKey,
209 TEXT("%s\\%s"),
210 szDeviceName,
211 szLineName);
212
213 if (RegCreateKeyEx(hAppSettingsKey,
214 szDevRegKey,
215 0,
216 NULL,
217 REG_OPTION_NON_VOLATILE,
218 KEY_READ | KEY_WRITE,
219 NULL,
220 &hLineKey,
221 NULL) == ERROR_SUCCESS)
222 {
223 if (RegQueryValueEx(hLineKey,
224 LineStatesValue,
225 NULL,
226 &Type,
227 NULL,
228 &Size) != ERROR_SUCCESS ||
229 Type != REG_BINARY ||
230 Size == 0 || (Size % sizeof(SNDVOL_REG_LINESTATE) != 0))
231 {
232 goto ExitClose;
233 }
234
235 LineStates = HeapAlloc(GetProcessHeap(),
236 HEAP_ZERO_MEMORY,
237 Size);
238
239 if (LineStates != NULL)
240 {
241 if (RegQueryValueEx(hLineKey,
242 LineStatesValue,
243 NULL,
244 &Type,
245 (LPBYTE)LineStates,
246 &Size) != ERROR_SUCCESS ||
247 Type != REG_BINARY ||
248 Size == 0 || (Size % sizeof(SNDVOL_REG_LINESTATE) != 0))
249 {
250 goto ExitClose;
251 }
252
253 /* try to find the control */
254 for (i = 0; i < Size / sizeof(SNDVOL_REG_LINESTATE); i++)
255 {
256 if (!_tcscmp(szControlName,
257 LineStates[i].LineName))
258 {
259 *Flags = LineStates[i].Flags;
260 Ret = TRUE;
261 break;
262 }
263 }
264 }
265
266 ExitClose:
267 HeapFree(GetProcessHeap(),
268 0,
269 LineStates);
270 RegCloseKey(hLineKey);
271 }
272
273 return Ret;
274 }