9cd64b1d0ab4579ad211a203d9aaf94c1f649ed9
[people/sha0/winvblock.git] / src / aoe / registry.c
1 /**
2  * Copyright (C) 2009-2010, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
3  * Copyright 2006-2008, V.
4  * For WinAoE contact information, see http://winaoe.org/
5  *
6  * This file is part of WinVBlock, derived from WinAoE.
7  *
8  * WinVBlock is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * WinVBlock is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with WinVBlock.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /**
23  * @file
24  *
25  * AoE registry specifics.
26  */
27
28 #include <ntddk.h>
29
30 #include "winvblock.h"
31 #include "wv_stdlib.h"
32 #include "wv_string.h"
33 #include "portable.h"
34 #include "registry.h"
35 #include "debug.h"
36
37 winvblock__bool STDCALL AoeRegSetup(OUT PNTSTATUS status_out) {
38     NTSTATUS status;
39     winvblock__bool Updated = FALSE;
40     WCHAR InterfacesPath[] = L"\\Ndi\\Interfaces\\";
41     WCHAR LinkagePath[] = L"\\Linkage\\";
42     WCHAR NdiPath[] = L"\\Ndi\\";
43     WCHAR DriverServiceNamePath[] =
44       L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
45     OBJECT_ATTRIBUTES SubKeyObject;
46     HANDLE
47       ControlKeyHandle, NetworkClassKeyHandle, SubKeyHandle;
48     winvblock__uint32
49       i, SubkeyIndex, ResultLength, InterfacesKeyStringLength,
50       LinkageKeyStringLength, NdiKeyStringLength, NewValueLength;
51     PWCHAR
52       InterfacesKeyString, LinkageKeyString, NdiKeyString,
53       DriverServiceNameString, NewValue;
54     UNICODE_STRING
55       InterfacesKey, LinkageKey, NdiKey, LowerRange, UpperBind, Service,
56       DriverServiceName;
57     PKEY_BASIC_INFORMATION KeyInformation;
58     PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
59     winvblock__bool Update, Found;
60
61     DBG("Entry\n");
62
63     RtlInitUnicodeString(&LowerRange, L"LowerRange");
64     RtlInitUnicodeString(&UpperBind, L"UpperBind");
65     RtlInitUnicodeString(&Service, L"Service");
66
67     /* Open the network adapter class key. */
68     status = WvlRegOpenKey(
69         (L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Class\\"
70           L"{4D36E972-E325-11CE-BFC1-08002BE10318}\\"),
71         &NetworkClassKeyHandle
72       );
73     if (!NT_SUCCESS(status))
74       goto err_keyopennetworkclass;
75
76     /* Enumerate through subkeys. */
77     SubkeyIndex = 0;
78     while ((status = ZwEnumerateKey(
79         NetworkClassKeyHandle,
80         SubkeyIndex,
81         KeyBasicInformation,
82         NULL,
83         0,
84         &ResultLength
85       )) != STATUS_NO_MORE_ENTRIES)
86       {
87         if ((status != STATUS_SUCCESS) &&
88             (status != STATUS_BUFFER_OVERFLOW) &&
89             (status != STATUS_BUFFER_TOO_SMALL)
90           )
91           {
92             DBG("ZwEnumerateKey 1 failed (%lx)\n", status);
93             goto e0_1;
94           }
95         if ((KeyInformation = wv_malloc(ResultLength)) == NULL)
96           {
97             DBG("wv_malloc KeyData failed\n");
98             goto e0_1;
99             WvlRegCloseKey(NetworkClassKeyHandle);
100           }
101         if (!(NT_SUCCESS(
102             ZwEnumerateKey(
103                 NetworkClassKeyHandle,
104                 SubkeyIndex,
105                 KeyBasicInformation,
106                 KeyInformation,
107                 ResultLength,
108                 &ResultLength
109           ))))
110           {
111             DBG ("ZwEnumerateKey 2 failed\n");
112             goto e0_2;
113           }
114
115         InterfacesKeyStringLength =
116           KeyInformation->NameLength + sizeof InterfacesPath;
117         InterfacesKeyString = wv_malloc(InterfacesKeyStringLength);
118         if (InterfacesKeyString == NULL)
119           {
120             DBG("wv_malloc InterfacesKeyString failed\n");
121             goto e0_2;
122           }
123
124         RtlCopyMemory(
125             InterfacesKeyString,
126             KeyInformation->Name,
127             KeyInformation->NameLength
128           );
129         RtlCopyMemory(
130             InterfacesKeyString +
131               (KeyInformation->NameLength / sizeof (WCHAR)),
132             InterfacesPath,
133             sizeof InterfacesPath
134           );
135         RtlInitUnicodeString(&InterfacesKey, InterfacesKeyString);
136
137         Update = FALSE;
138         InitializeObjectAttributes(
139             &SubKeyObject,
140             &InterfacesKey,
141             OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
142             NetworkClassKeyHandle,
143             NULL
144           );
145         if (NT_SUCCESS(ZwOpenKey(&SubKeyHandle, KEY_ALL_ACCESS, &SubKeyObject)))
146           {
147             if ((status = ZwQueryValueKey(
148                 SubKeyHandle,
149                 &LowerRange,
150                 KeyValuePartialInformation,
151                 NULL,
152                 0,
153                 &ResultLength
154               )) != STATUS_OBJECT_NAME_NOT_FOUND )
155               {
156                 if ((status != STATUS_SUCCESS) &&
157                     (status != STATUS_BUFFER_OVERFLOW) &&
158                     (status != STATUS_BUFFER_TOO_SMALL))
159                   {
160                     DBG(
161                         "ZwQueryValueKey InterfacesKey 1 failed (%lx)\n",
162                         status
163                       );
164                     goto e1_1;
165                   }
166                 if ((KeyValueInformation = wv_malloc(ResultLength)) == NULL)
167                   {
168                     DBG("wv_malloc InterfacesKey KeyValueData failed\n");
169                     goto e1_1;
170                   }
171                 if (!(NT_SUCCESS(ZwQueryValueKey(
172                     SubKeyHandle,
173                     &LowerRange,
174                     KeyValuePartialInformation,
175                     KeyValueInformation,
176                     ResultLength,
177                     &ResultLength
178                   ))))
179                   {
180                     DBG("ZwQueryValueKey InterfacesKey 2 failed\n");
181                     goto e1_2;
182                   }
183                 if (wv_memcmpeq(
184                     L"ethernet",
185                     KeyValueInformation->Data,
186                     sizeof L"ethernet"
187                   ))
188                   Update = TRUE;
189                 wv_free(KeyValueInformation);
190                 if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
191                   {
192                     DBG("ZwClose InterfacesKey SubKeyHandle failed\n");
193                     goto e1_0;
194                   }
195                }
196           }
197         wv_free(InterfacesKeyString);
198
199         if (Update)
200           {
201             LinkageKeyStringLength =
202               KeyInformation->NameLength + sizeof LinkagePath;
203             if ((LinkageKeyString = wv_malloc(LinkageKeyStringLength)) == NULL)
204               {
205                 DBG("wv_malloc LinkageKeyString failed\n");
206                 goto e0_2;
207               }
208             RtlCopyMemory(
209                 LinkageKeyString,
210                 KeyInformation->Name,
211                 KeyInformation->NameLength
212               );
213             RtlCopyMemory(
214                 LinkageKeyString +
215                 (KeyInformation->NameLength / sizeof (WCHAR)),
216                 LinkagePath,
217                 sizeof LinkagePath
218               );
219             RtlInitUnicodeString(&LinkageKey, LinkageKeyString);
220
221             InitializeObjectAttributes(
222                 &SubKeyObject,
223                 &LinkageKey,
224                 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
225                 NetworkClassKeyHandle,
226                 NULL
227               );
228             if (!NT_SUCCESS(ZwCreateKey(
229                 &SubKeyHandle,
230                 KEY_ALL_ACCESS,
231                 &SubKeyObject,
232                 0,
233                 NULL,
234                  REG_OPTION_NON_VOLATILE,
235                 NULL
236               )))
237               {
238                 DBG("ZwCreateKey failed (%lx)\n");
239                 goto e2_0;
240               }
241             if ((status = ZwQueryValueKey(
242                 SubKeyHandle,
243                 &UpperBind,
244                 KeyValuePartialInformation,
245                 NULL,
246                 0,
247                 &ResultLength
248               )) != STATUS_OBJECT_NAME_NOT_FOUND)
249               {
250                 if ((status != STATUS_SUCCESS) &&
251                     (status != STATUS_BUFFER_OVERFLOW) &&
252                     (status != STATUS_BUFFER_TOO_SMALL))
253                   {
254                     DBG("ZwQueryValueKey LinkageKey 1 failed (%lx)\n", status);
255                     goto e2_1;
256                   }
257                 if ((KeyValueInformation = wv_malloc(ResultLength)) == NULL)
258                   {
259                     DBG("wv_malloc LinkageKey KeyValueData failed\n");
260                     goto e2_1;
261                   }
262                 if (!(NT_SUCCESS(ZwQueryValueKey(
263                     SubKeyHandle,
264                     &UpperBind,
265                     KeyValuePartialInformation,
266                     KeyValueInformation,
267                     ResultLength,
268                     &ResultLength
269                   ))))
270                    {
271                     DBG("ZwQueryValueKey LinkageKey 2 failed\n");
272                     goto e2_2;
273                   }
274
275                 Found = FALSE;
276                 for (i = 0;
277                     i < (KeyValueInformation->DataLength -
278                       sizeof winvblock__literal_w / sizeof (WCHAR));
279                     i++)
280                   {
281                     if (wv_memcmpeq(
282                         winvblock__literal_w,
283                         ((PWCHAR)KeyValueInformation->Data) + i,
284                         sizeof winvblock__literal_w
285                       ))
286                       {
287                         Found = TRUE;
288                         break;
289                       } /* if wv_memcmpeq */
290                   } /* for */
291
292                 if (Found)
293                   {
294                     NewValueLength = KeyValueInformation->DataLength;
295                     if ((NewValue = wv_malloc(NewValueLength)) == NULL)
296                       {
297                         DBG("wv_malloc NewValue 1 failed\n");
298                         goto e2_2;
299                       }
300                     RtlCopyMemory(
301                         NewValue,
302                         KeyValueInformation->Data,
303                         KeyValueInformation->DataLength
304                       );
305                   } /* if Found */
306                   else
307                   {
308                     Updated = TRUE;
309                     NewValueLength = KeyValueInformation->DataLength +
310                       sizeof winvblock__literal_w;
311                     if ((NewValue = wv_malloc(NewValueLength)) == NULL)
312                       {
313                         DBG("wv_malloc NewValue 2 failed\n");
314                         goto e2_2;
315                       }
316                     RtlCopyMemory(
317                         NewValue,
318                         winvblock__literal_w,
319                         sizeof winvblock__literal_w
320                       );
321                     RtlCopyMemory(
322                         NewValue +
323                           (sizeof winvblock__literal_w / sizeof (WCHAR)),
324                         KeyValueInformation->Data,
325                         KeyValueInformation->DataLength
326                       );
327                      } /* else !Found */
328                 wv_free(KeyValueInformation);
329               }
330               else
331               {
332                 Updated = TRUE;
333                 NewValueLength = sizeof winvblock__literal_w + sizeof (WCHAR);
334                 if ((NewValue = wv_mallocz(NewValueLength)) == NULL)
335                   {
336                     DBG("wv_mallocz NewValue 3 failed\n");
337                     goto e2_1;
338                   }
339                 RtlCopyMemory(
340                     NewValue,
341                     winvblock__literal_w,
342                     sizeof winvblock__literal_w
343                   );
344               }
345             if (!NT_SUCCESS(ZwSetValueKey(
346                 SubKeyHandle,
347                 &UpperBind,
348                 0,
349                 REG_MULTI_SZ,
350                 NewValue,
351                 NewValueLength
352               )))
353               {
354                 DBG("ZwSetValueKey failed\n");
355                 wv_free(NewValue);
356                 goto e2_1;
357               }
358             wv_free(NewValue);
359             if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
360               {
361                 DBG("ZwClose LinkageKey SubKeyHandle failed\n");
362                 goto e2_0;
363               }
364             wv_free(LinkageKeyString);
365
366             /* Not sure where this comes from. */
367             #if 0
368             start nic (
369             #endif
370             NdiKeyStringLength = KeyInformation->NameLength + sizeof NdiPath;
371             if ((NdiKeyString = wv_malloc(NdiKeyStringLength)) == NULL)
372               {
373                 DBG("wv_malloc NdiKeyString failed\n");
374                 goto e0_2;
375               }
376             RtlCopyMemory(
377                 NdiKeyString,
378                 KeyInformation->Name,
379                 KeyInformation->NameLength
380               );
381             RtlCopyMemory(
382                 NdiKeyString + (KeyInformation->NameLength / sizeof (WCHAR)),
383                 NdiPath,
384                 sizeof NdiPath
385               );
386             RtlInitUnicodeString(&NdiKey, NdiKeyString);
387
388             InitializeObjectAttributes(
389                 &SubKeyObject,
390                 &NdiKey,
391                 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
392                 NetworkClassKeyHandle,
393                 NULL
394               );
395             if (NT_SUCCESS(ZwOpenKey(
396                 &SubKeyHandle,
397                 KEY_ALL_ACCESS,
398                 &SubKeyObject
399               )))
400               {
401                 if ((status = ZwQueryValueKey(
402                     SubKeyHandle,
403                     &Service,
404                     KeyValuePartialInformation,
405                     NULL,
406                     0,
407                     &ResultLength
408                   )) != STATUS_OBJECT_NAME_NOT_FOUND)
409                   {
410                   if ((status != STATUS_SUCCESS) &&
411                       (status != STATUS_BUFFER_OVERFLOW) &&
412                       (status != STATUS_BUFFER_TOO_SMALL))
413                     {
414                       DBG("ZwQueryValueKey NdiKey 1 failed (%lx)\n", status);
415                       goto e3_1;
416                     }
417                   if ((KeyValueInformation = wv_malloc(ResultLength)) == NULL)
418                     {
419                       DBG("wv_malloc NdiKey KeyValueData failed\n");
420                       goto e3_1;
421                     }
422                   if (!(NT_SUCCESS(ZwQueryValueKey(
423                       SubKeyHandle,
424                       &Service,
425                       KeyValuePartialInformation,
426                       KeyValueInformation,
427                       ResultLength,
428                       &ResultLength
429                     ))))
430                     {
431                       DBG("ZwQueryValueKey NdiKey 2 failed\n");
432                       wv_free(KeyValueInformation);
433                       goto e3_1;
434                     }
435                   if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
436                     {
437                       DBG("ZwClose NdiKey SubKeyHandle failed\n");
438                       goto e3_0;
439                     }
440                   DriverServiceNameString = wv_malloc(
441                       sizeof DriverServiceNamePath +
442                         KeyValueInformation->DataLength -
443                         sizeof *DriverServiceNamePath
444                     );
445                   if (DriverServiceNameString == NULL)
446                     {
447                       DBG("wv_malloc DriverServiceNameString failed\n");
448                       goto e3_0;
449                     }
450
451                   RtlCopyMemory(
452                       DriverServiceNameString,
453                       DriverServiceNamePath,
454                       sizeof DriverServiceNamePath
455                     );
456                   RtlCopyMemory(
457                       DriverServiceNameString +
458                         (sizeof DriverServiceNamePath / sizeof (WCHAR)) - 1,
459                       KeyValueInformation->Data,
460                       KeyValueInformation->DataLength
461                     );
462                   RtlInitUnicodeString(
463                       &DriverServiceName,
464                       DriverServiceNameString
465                     );
466                   #if 0
467                   DBG(
468                       "Starting driver %S -> %08x\n",
469                       KeyValueInformation->Data,
470                       ZwLoadDriver(&DriverServiceName)
471                     );
472                   #endif
473                     wv_free(DriverServiceNameString);
474                     wv_free(KeyValueInformation);
475                   }
476               }
477             wv_free(NdiKeyString);
478           }
479         wv_free(KeyInformation);
480         SubkeyIndex++;
481       } /* while */
482     WvlRegCloseKey(NetworkClassKeyHandle);
483     *status_out = STATUS_SUCCESS;
484     return Updated;
485
486     e3_1:
487
488     if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
489       DBG("ZwClose SubKeyHandle failed\n");
490     e3_0:
491
492     wv_free(NdiKeyString);
493     goto e0_2;
494     e2_2:
495
496     wv_free(KeyValueInformation);
497     e2_1:
498
499     if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
500       DBG("ZwClose SubKeyHandle failed\n");
501     e2_0:
502
503     wv_free(LinkageKeyString);
504     goto e0_2;
505     e1_2:
506
507     wv_free(KeyValueInformation);
508     e1_1:
509
510     if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
511       DBG("ZwClose SubKeyHandle failed\n");
512     e1_0:
513
514     wv_free(InterfacesKeyString);
515     goto e0_2;
516     e0_2:
517
518     wv_free(KeyInformation);
519     e0_1:
520
521     WvlRegCloseKey(NetworkClassKeyHandle);
522     err_keyopennetworkclass:
523
524     *status_out = STATUS_UNSUCCESSFUL;
525     return FALSE;
526   }