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