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