1 /*
2  *
3  * COPYRIGHT:            See COPYING in the top level directory
4  * PROJECT:              ReactOS kernel
5  * FILE:                 drivers/dd/sndblst/settings.c
6  * PURPOSE:              MPU-401 MIDI device driver setting management
7  * PROGRAMMER:           Andrew Greenwood
8  * UPDATE HISTORY:
9  *                       Sept 28, 2003: Created
10  */
11 
12 #include <ntddk.h>
13 #include "sndblst.h"
14 #include "sbdebug.h"  // our own debug helper
15 
16 
17 #if 0
18 NTSTATUS
19 OpenDevicesKey(
20     IN PWSTR RegistryPath,
21     OUT PHANDLE Key)
22 /*
23     Description:
24         Create a volatile key under this driver's Services node to contain
25         the device name list.
26 
27     Parameters:
28         RegistryPath    The location of the registry entry
29         Key             The key in the registry
30 
31     Return Value:
32         NT status STATUS_SUCCESS if successful (duh...)
33 */
34 {
35     NTSTATUS s;
36     HANDLE hKey;
37     OBJECT_ATTRIBUTES oa;
38     UNICODE_STRING uStr;
39 
40     // Attempt to open the key
41 
42     RtlInitUnicodeString(&uStr, RegistryPath);
43 
44     InitializeObjectAttributes(&oa, &uStr, OBJ_CASE_INSENSITIVE, NULL,
45                                 (PSECURITY_DESCRIPTOR)NULL);
46 
47     s = ZwOpenKey(&hKey, KEY_CREATE_SUB_KEY, &oa);
48 
49     if (! NT_SUCCESS(s))
50         return s;   // Problem
51 
52 
53     // Now create sub key
54 
55     RtlInitUnicodeString(&uStr, (PWSTR) DEVICE_SUBKEY);
56 
57     InitializeObjectAttributes(&oa, &uStr, OBJ_CASE_INSENSITIVE, hKey,
58                                 (PSECURITY_DESCRIPTOR)NULL);
59 
60     s = ZwCreateKey(Key, KEY_ALL_ACCESS, &oa, 0, NULL, REG_OPTION_VOLATILE,
61                     NULL);
62 
63     ZwClose(hKey);
64 
65     return s;
66 }
67 #endif
68 
69 
70 NTSTATUS NTAPI EnumDeviceKeys(
71     IN PUNICODE_STRING RegistryPath,
72     IN PWSTR SubKey,
73     IN PREGISTRY_CALLBACK_ROUTINE Callback,
74     IN PVOID Context)
75 /*
76     Description:
77         Enumerate the device subkeys in the driver's registry entry, and
78         call the specified callback routine for each device.
79 
80     Parameters:
81         RegistryPath    The location of the registry entry
82         Subkey          The device's subkey
83         Callback        A routine called for each device
84         Context         ???
85 
86     Return Value:
87         NT status STATUS_SUCCESS if successful
88 */
89 {
90     NTSTATUS s;
91     OBJECT_ATTRIBUTES oa;
92     HANDLE hKey, hSubKey;
93     UNICODE_STRING SubkeyName;
94     ULONG i;
95 
96     // Attempt to open the key
97 
98     InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE,
99                                 NULL, (PSECURITY_DESCRIPTOR)NULL);
100 
101     s = ZwOpenKey(&hKey, KEY_READ, &oa);
102 
103         TEST_STATUS(s); // debugging
104 
105     if (! NT_SUCCESS(s))
106         return s;   // Problem
107 
108     RtlInitUnicodeString(&SubkeyName, SubKey);
109 
110     DPRINT("Subkey: %wZ\n", &SubkeyName);
111 
112     InitializeObjectAttributes(&oa, &SubkeyName, OBJ_CASE_INSENSITIVE,
113                                 hKey, (PSECURITY_DESCRIPTOR)NULL);
114 
115     s = ZwOpenKey(&hSubKey, KEY_ENUMERATE_SUB_KEYS, &oa);
116 
117     ZwClose(hKey);
118 
119         TEST_STATUS(s); // debugging
120 
121     if (! NT_SUCCESS(s))
122         return s;
123 
124 
125     // And now, the enumeration
126 
127     for (i = 0;; i ++)
128     {
129         KEY_BASIC_INFORMATION Info;
130         PKEY_BASIC_INFORMATION pInfo;
131         ULONG ResultLength = 0;
132         ULONG Size = 0;
133         PWSTR Pos;
134         PWSTR Name;
135 
136         // Find the length of the subkey data
137 
138 //        Info.NameLength = 0;    // TEMPORARY!
139 
140         s = ZwEnumerateKey(hSubKey, i, KeyBasicInformation, &Info,
141                             sizeof(Info), &ResultLength);
142 
143         if (s == STATUS_NO_MORE_ENTRIES)
144             break;
145 
146         DPRINT("Found an entry, allocating memory...\n");
147 
148 //        Size = Info.NameLength + FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
149         Size = ResultLength + FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
150 
151         DPRINT("Size is %d\n", Size);
152 
153         pInfo = (PKEY_BASIC_INFORMATION) ExAllocatePool(PagedPool, Size);
154 
155         if (pInfo == NULL)
156         {
157             DPRINT("INSUFFICIENT RESOURCES!\n");
158             s = STATUS_INSUFFICIENT_RESOURCES;
159             break;
160         }
161 
162         DPRINT("Re-enumerating...\n");
163 
164         s = ZwEnumerateKey(hSubKey, i, KeyBasicInformation, pInfo, Size,
165                             &ResultLength);
166 
167 //        TEST_STATUS(s); // debugging
168 
169         if (! NT_SUCCESS(s))
170         {
171             ExFreePool((PVOID) pInfo);
172             s = STATUS_INTERNAL_ERROR;
173             break;
174         }
175 
176         DPRINT("Allocating memory for name...\n");
177 
178         Name = ExAllocatePool(PagedPool,
179                           RegistryPath->Length + sizeof(WCHAR) +
180                           SubkeyName.Length + sizeof(WCHAR) +
181                           pInfo->NameLength + sizeof(UNICODE_NULL));
182 
183         if (Name == NULL)
184         {
185             DPRINT("INSUFFICIENT RESOURCES!");
186             ExFreePool((PVOID) pInfo);
187             return STATUS_INSUFFICIENT_RESOURCES;
188         }
189 
190         // Copy the key name
191         RtlCopyMemory((PVOID)Name, (PVOID)RegistryPath->Buffer, RegistryPath->Length);
192         Pos = Name + (RegistryPath->Length / sizeof(WCHAR));
193         Pos[0] = '\\';
194         Pos++;
195 
196         // Copy the parameters sub key name
197         RtlCopyMemory((PVOID)Pos, (PVOID)SubKey, SubkeyName.Length);    //SubkeyName?
198         Pos += SubkeyName.Length / sizeof(WCHAR);
199         Pos[0] = '\\';
200         Pos ++;
201 
202         // Copy the device sub key name
203         RtlCopyMemory((PVOID)Pos, (PVOID)pInfo->Name, pInfo->NameLength);
204         Pos += pInfo->NameLength / sizeof(WCHAR);
205         Pos[0] = UNICODE_NULL;
206 
207         ExFreePool((PVOID)pInfo);
208 
209         DPRINT("Calling callback...\n");
210 
211         s = (*Callback)(Name, Context);
212 
213         if (! NT_SUCCESS(s))
214         {   DPRINT("Callback FAILED\n");
215             break;}
216     }
217 
218     ZwClose(hSubKey);
219 
220     DPRINT("%d device registry keys found\n", i);
221 
222     if ((i == 0) && (s == STATUS_NO_MORE_ENTRIES))
223         return STATUS_DEVICE_CONFIGURATION_ERROR;
224 
225     return s == STATUS_NO_MORE_ENTRIES ? STATUS_SUCCESS : s;
226 }
227 
228 
229 
230 NTSTATUS NTAPI LoadSettings(
231     IN  PWSTR ValueName,
232     IN  ULONG ValueType,
233     IN  PVOID ValueData,
234     IN  ULONG ValueLength,
235     IN  PVOID Context,
236     IN  PVOID EntryContext)
237 /*
238     Description:
239         Read the settings for a particular device
240 
241     Parameters:
242         ValueName       The value to read from the registry
243         ValueType       ?
244         ValueData       ?
245         ValueLength     ?
246         Context         The configuration structure to write to
247         EntryContext    ?
248 
249     Return Value:
250         NT status STATUS_SUCCESS if successful
251 */
252 {
253     PDEVICE_EXTENSION DeviceInfo = Context;
254 
255     if (ValueType == REG_DWORD)
256     {
257         if (! _wcsicmp(ValueName, REGISTRY_PORT))
258         {
259             DeviceInfo->Port = *(PULONG) ValueData;
260             DPRINT("Registry port = 0x%x\n", DeviceInfo->Port);
261         }
262 
263         // More to come... (config.c)
264     }
265 
266     else
267     {
268         // ?
269     }
270 
271     return STATUS_SUCCESS;
272 }
273 
274 
275 #if 0
276 NTSTATUS SaveSettings(
277     IN  PWSTR RegistryPath,
278     IN  ULONG Port,
279     IN  ULONG IRQ,
280     IN  ULONG DMA)
281 /*
282     Description:
283         Saves the settings for a particular device
284 
285     Parameters:
286         RegistryPath    Where to save the settings to
287         Port            The device's port number
288         IRQ             The device's interrupt number
289         DMA             The device's DMA channel
290 
291     Return Value:
292         NT status STATUS_SUCCESS if successful
293 */
294 {
295     DPRINT("SaveSettings() unimplemented\n");
296 
297 //    UNIMPLEMENTED;
298 
299     return STATUS_SUCCESS;
300 }
301 #endif
302