[project] Rename winvblock__uint32 back to UINT32
[people/sha0/winvblock.git] / src / aoe / registry.c
1 /**
2  * Copyright (C) 2009-2011, 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     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 WVL_M_WLIT / sizeof (WCHAR));
279                     i++)
280                   {
281                     if (wv_memcmpeq(
282                         WVL_M_WLIT,
283                         ((PWCHAR)KeyValueInformation->Data) + i,
284                         sizeof WVL_M_WLIT
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 WVL_M_WLIT;
311                     if ((NewValue = wv_malloc(NewValueLength)) == NULL)
312                       {
313                         DBG("wv_malloc NewValue 2 failed\n");
314                         goto e2_2;
315                       }
316                     RtlCopyMemory(NewValue, WVL_M_WLIT, sizeof WVL_M_WLIT);
317                     RtlCopyMemory(
318                         NewValue +
319                           (sizeof WVL_M_WLIT / sizeof (WCHAR)),
320                         KeyValueInformation->Data,
321                         KeyValueInformation->DataLength
322                       );
323                      } /* else !Found */
324                 wv_free(KeyValueInformation);
325               }
326               else
327               {
328                 Updated = TRUE;
329                 NewValueLength = sizeof WVL_M_WLIT + sizeof (WCHAR);
330                 if ((NewValue = wv_mallocz(NewValueLength)) == NULL)
331                   {
332                     DBG("wv_mallocz NewValue 3 failed\n");
333                     goto e2_1;
334                   }
335                 RtlCopyMemory(NewValue, WVL_M_WLIT, sizeof WVL_M_WLIT);
336               }
337             if (!NT_SUCCESS(ZwSetValueKey(
338                 SubKeyHandle,
339                 &UpperBind,
340                 0,
341                 REG_MULTI_SZ,
342                 NewValue,
343                 NewValueLength
344               )))
345               {
346                 DBG("ZwSetValueKey failed\n");
347                 wv_free(NewValue);
348                 goto e2_1;
349               }
350             wv_free(NewValue);
351             if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
352               {
353                 DBG("ZwClose LinkageKey SubKeyHandle failed\n");
354                 goto e2_0;
355               }
356             wv_free(LinkageKeyString);
357
358             /* Not sure where this comes from. */
359             #if 0
360             start nic (
361             #endif
362             NdiKeyStringLength = KeyInformation->NameLength + sizeof NdiPath;
363             if ((NdiKeyString = wv_malloc(NdiKeyStringLength)) == NULL)
364               {
365                 DBG("wv_malloc NdiKeyString failed\n");
366                 goto e0_2;
367               }
368             RtlCopyMemory(
369                 NdiKeyString,
370                 KeyInformation->Name,
371                 KeyInformation->NameLength
372               );
373             RtlCopyMemory(
374                 NdiKeyString + (KeyInformation->NameLength / sizeof (WCHAR)),
375                 NdiPath,
376                 sizeof NdiPath
377               );
378             RtlInitUnicodeString(&NdiKey, NdiKeyString);
379
380             InitializeObjectAttributes(
381                 &SubKeyObject,
382                 &NdiKey,
383                 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
384                 NetworkClassKeyHandle,
385                 NULL
386               );
387             if (NT_SUCCESS(ZwOpenKey(
388                 &SubKeyHandle,
389                 KEY_ALL_ACCESS,
390                 &SubKeyObject
391               )))
392               {
393                 if ((status = ZwQueryValueKey(
394                     SubKeyHandle,
395                     &Service,
396                     KeyValuePartialInformation,
397                     NULL,
398                     0,
399                     &ResultLength
400                   )) != STATUS_OBJECT_NAME_NOT_FOUND)
401                   {
402                   if ((status != STATUS_SUCCESS) &&
403                       (status != STATUS_BUFFER_OVERFLOW) &&
404                       (status != STATUS_BUFFER_TOO_SMALL))
405                     {
406                       DBG("ZwQueryValueKey NdiKey 1 failed (%lx)\n", status);
407                       goto e3_1;
408                     }
409                   if ((KeyValueInformation = wv_malloc(ResultLength)) == NULL)
410                     {
411                       DBG("wv_malloc NdiKey KeyValueData failed\n");
412                       goto e3_1;
413                     }
414                   if (!(NT_SUCCESS(ZwQueryValueKey(
415                       SubKeyHandle,
416                       &Service,
417                       KeyValuePartialInformation,
418                       KeyValueInformation,
419                       ResultLength,
420                       &ResultLength
421                     ))))
422                     {
423                       DBG("ZwQueryValueKey NdiKey 2 failed\n");
424                       wv_free(KeyValueInformation);
425                       goto e3_1;
426                     }
427                   if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
428                     {
429                       DBG("ZwClose NdiKey SubKeyHandle failed\n");
430                       goto e3_0;
431                     }
432                   DriverServiceNameString = wv_malloc(
433                       sizeof DriverServiceNamePath +
434                         KeyValueInformation->DataLength -
435                         sizeof *DriverServiceNamePath
436                     );
437                   if (DriverServiceNameString == NULL)
438                     {
439                       DBG("wv_malloc DriverServiceNameString failed\n");
440                       goto e3_0;
441                     }
442
443                   RtlCopyMemory(
444                       DriverServiceNameString,
445                       DriverServiceNamePath,
446                       sizeof DriverServiceNamePath
447                     );
448                   RtlCopyMemory(
449                       DriverServiceNameString +
450                         (sizeof DriverServiceNamePath / sizeof (WCHAR)) - 1,
451                       KeyValueInformation->Data,
452                       KeyValueInformation->DataLength
453                     );
454                   RtlInitUnicodeString(
455                       &DriverServiceName,
456                       DriverServiceNameString
457                     );
458                   #if 0
459                   DBG(
460                       "Starting driver %S -> %08x\n",
461                       KeyValueInformation->Data,
462                       ZwLoadDriver(&DriverServiceName)
463                     );
464                   #endif
465                     wv_free(DriverServiceNameString);
466                     wv_free(KeyValueInformation);
467                   }
468               }
469             wv_free(NdiKeyString);
470           }
471         wv_free(KeyInformation);
472         SubkeyIndex++;
473       } /* while */
474     WvlRegCloseKey(NetworkClassKeyHandle);
475     *status_out = STATUS_SUCCESS;
476     return Updated;
477
478     e3_1:
479
480     if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
481       DBG("ZwClose SubKeyHandle failed\n");
482     e3_0:
483
484     wv_free(NdiKeyString);
485     goto e0_2;
486     e2_2:
487
488     wv_free(KeyValueInformation);
489     e2_1:
490
491     if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
492       DBG("ZwClose SubKeyHandle failed\n");
493     e2_0:
494
495     wv_free(LinkageKeyString);
496     goto e0_2;
497     e1_2:
498
499     wv_free(KeyValueInformation);
500     e1_1:
501
502     if (!NT_SUCCESS(ZwClose(SubKeyHandle)))
503       DBG("ZwClose SubKeyHandle failed\n");
504     e1_0:
505
506     wv_free(InterfacesKeyString);
507     goto e0_2;
508     e0_2:
509
510     wv_free(KeyInformation);
511     e0_1:
512
513     WvlRegCloseKey(NetworkClassKeyHandle);
514     err_keyopennetworkclass:
515
516     *status_out = STATUS_UNSUCCESSFUL;
517     return FALSE;
518   }