[FREELDR]
[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 #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 /* NOTE: do NOT modify SNDVOL_REG_LINESTATE for binary compatibility with XP! */
129 typedef struct _SNDVOL_REG_LINESTATE
130 {
131 DWORD Flags;
132 WCHAR LineName[MIXER_LONG_NAME_CHARS];
133 } SNDVOL_REG_LINESTATE, *PSNDVOL_REG_LINESTATE;
134
135 static const TCHAR AppRegSettings[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Volume Control");
136 static const TCHAR AppOptionsKey[] = TEXT("Options");
137 static const TCHAR LineStatesValue[] = TEXT("LineStates");
138 static const TCHAR StyleValue[] = TEXT("Style");
139
140 HKEY hAppSettingsKey = NULL;
141
142 BOOL
143 InitAppConfig(VOID)
144 {
145 return RegCreateKeyEx(HKEY_CURRENT_USER,
146 AppRegSettings,
147 0,
148 NULL,
149 REG_OPTION_NON_VOLATILE,
150 KEY_READ | KEY_WRITE,
151 NULL,
152 &hAppSettingsKey,
153 NULL) == ERROR_SUCCESS;
154 }
155
156 VOID
157 CloseAppConfig(VOID)
158 {
159 if (hAppSettingsKey != NULL)
160 {
161 RegCloseKey(hAppSettingsKey);
162 hAppSettingsKey = NULL;
163 }
164 }
165
166 BOOL
167 ReadLineConfig(IN LPTSTR szDeviceName,
168 IN LPTSTR szLineName,
169 IN LPTSTR szControlName,
170 OUT DWORD *Flags)
171 {
172 HKEY hLineKey;
173 DWORD Type;
174 DWORD i, Size = 0;
175 PSNDVOL_REG_LINESTATE LineStates = NULL;
176 TCHAR szDevRegKey[MAX_PATH];
177 BOOL Ret = FALSE;
178
179 _stprintf(szDevRegKey,
180 TEXT("%s\\%s"),
181 szDeviceName,
182 szLineName);
183
184 if (RegCreateKeyEx(hAppSettingsKey,
185 szDevRegKey,
186 0,
187 NULL,
188 REG_OPTION_NON_VOLATILE,
189 KEY_READ | KEY_WRITE,
190 NULL,
191 &hLineKey,
192 NULL) == ERROR_SUCCESS)
193 {
194 if (RegQueryValueEx(hLineKey,
195 LineStatesValue,
196 NULL,
197 &Type,
198 NULL,
199 &Size) != ERROR_SUCCESS ||
200 Type != REG_BINARY ||
201 Size == 0 || (Size % sizeof(SNDVOL_REG_LINESTATE) != 0))
202 {
203 goto ExitClose;
204 }
205
206 LineStates = HeapAlloc(GetProcessHeap(),
207 0,
208 Size);
209
210 if (LineStates != NULL)
211 {
212 if (RegQueryValueEx(hLineKey,
213 LineStatesValue,
214 NULL,
215 &Type,
216 (LPBYTE)LineStates,
217 &Size) != ERROR_SUCCESS ||
218 Type != REG_BINARY ||
219 Size == 0 || (Size % sizeof(SNDVOL_REG_LINESTATE) != 0))
220 {
221 goto ExitClose;
222 }
223
224 /* try to find the control */
225 for (i = 0; i < Size / sizeof(SNDVOL_REG_LINESTATE); i++)
226 {
227 if (!_tcscmp(szControlName,
228 LineStates[i].LineName))
229 {
230 *Flags = LineStates[i].Flags;
231 Ret = TRUE;
232 break;
233 }
234 }
235 }
236
237 ExitClose:
238 HeapFree(GetProcessHeap(),
239 0,
240 LineStates);
241 RegCloseKey(hLineKey);
242 }
243
244 return Ret;
245 }