xref: /reactos/base/services/dcomlaunch/network.c (revision 94a413ae)
1 /*
2  * PROJECT:     ReactOS RPC Subsystem Service
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     UUID initialization.
5  * COPYRIGHT:   Copyright 2019 Pierre Schweitzer
6  */
7 
8 /* INCLUDES *****************************************************************/
9 
10 /* PSDK/NDK Headers */
11 #define WIN32_NO_STATUS
12 #include <windef.h>
13 #include <winbase.h>
14 #include <winreg.h>
15 #include <winsvc.h>
16 #include <ntddndis.h>
17 
18 #include <ndk/exfuncs.h>
19 #include <ntsecapi.h>
20 
21 #define NDEBUG
22 #include <debug.h>
23 
24 #define SEED_BUFFER_SIZE 6
25 
26 /* FUNCTIONS ****************************************************************/
27 
28 static BOOLEAN
29 getMacAddress(UCHAR * MacAddress)
30 {
31     /* FIXME: query NDIS for all the interfaces */
32     UNIMPLEMENTED;
33     return FALSE;
34 }
35 
36 static VOID
37 CookupNodeId(UCHAR * NodeId)
38 {
39     CHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
40     CHAR * CurrentChar;
41     DWORD Size;
42     LARGE_INTEGER PerformanceCount;
43     PDWORD NodeBegin, NodeMiddle;
44     DWORD dwValue;
45     MEMORYSTATUS MemoryStatus;
46     LUID Luid;
47     WCHAR szSystem[MAX_PATH];
48     ULARGE_INTEGER FreeBytesToCaller, TotalBytes, TotalFreeBytes;
49 
50     /* Initialize node id */
51     memset(NodeId, 0x11, SEED_BUFFER_SIZE * sizeof(UCHAR));
52 
53     /* Randomize it with computer name */
54     Size = MAX_COMPUTERNAME_LENGTH + 1;
55     if (GetComputerNameA(ComputerName, &Size))
56     {
57         Size = 0;
58         CurrentChar = &ComputerName[0];
59         while (*CurrentChar != ANSI_NULL)
60         {
61             NodeId[Size] ^= *CurrentChar;
62             ++CurrentChar;
63 
64             /* Don't overflow our NodeId */
65             if (++Size >= SEED_BUFFER_SIZE)
66             {
67                 Size = 0;
68             }
69         }
70     }
71 
72     /* Now, we'll work directly on DWORD values */
73     NodeBegin = (DWORD *)&NodeId[0];
74     NodeMiddle = (DWORD *)&NodeId[2];
75 
76     /* Randomize with performance counter */
77     if (QueryPerformanceCounter(&PerformanceCount))
78     {
79         *NodeMiddle = *NodeMiddle ^ PerformanceCount.u.HighPart ^ PerformanceCount.u.LowPart;
80 
81         dwValue = PerformanceCount.u.HighPart ^ PerformanceCount.u.LowPart ^ *NodeBegin;
82     }
83     else
84     {
85         dwValue = *NodeBegin;
86     }
87 
88     *NodeBegin = *NodeBegin ^ dwValue;
89     *NodeMiddle = *NodeMiddle ^ *NodeBegin;
90 
91     /* Then, with memory status */
92     MemoryStatus.dwLength = sizeof(MemoryStatus);
93     GlobalMemoryStatus(&MemoryStatus);
94 
95     *NodeBegin = *NodeBegin ^ MemoryStatus.dwMemoryLoad;
96     *NodeMiddle = *NodeMiddle ^ MemoryStatus.dwTotalPhys;
97     *NodeBegin = *NodeBegin ^ MemoryStatus.dwTotalPageFile ^ MemoryStatus.dwAvailPhys;
98     *NodeMiddle = *NodeMiddle ^ MemoryStatus.dwTotalVirtual ^ MemoryStatus.dwAvailPageFile;
99     *NodeBegin = *NodeBegin ^ MemoryStatus.dwAvailVirtual;
100 
101     /* With a LUID */
102     if (AllocateLocallyUniqueId(&Luid))
103     {
104         *NodeBegin = *NodeBegin ^ Luid.LowPart;
105         *NodeMiddle = *NodeMiddle ^ Luid.HighPart;
106     }
107 
108     /* Get system directory */
109     GetSystemDirectoryW(szSystem, ARRAYSIZE(szSystem));
110 
111     /* And finally with free disk space */
112     if (GetDiskFreeSpaceExW(szSystem, &FreeBytesToCaller, &TotalBytes, &TotalFreeBytes))
113     {
114         *NodeMiddle ^= FreeBytesToCaller.LowPart ^ TotalFreeBytes.HighPart;
115         *NodeMiddle ^= FreeBytesToCaller.HighPart ^ TotalFreeBytes.LowPart;
116         *NodeBegin ^= TotalBytes.LowPart ^ TotalFreeBytes.LowPart;
117         *NodeBegin ^= TotalBytes.HighPart ^ TotalFreeBytes.HighPart;
118     }
119 
120     /*
121      * Because it was locally generated, force the seed to be local
122      * setting this, will trigger the check for validness in the kernel
123      * and make the seed local
124      */
125     NodeId[0] |= 0x80u;
126 }
127 
128 VOID DealWithDeviceEvent(VOID)
129 {
130     NTSTATUS Status;
131     UCHAR UuidSeed[SEED_BUFFER_SIZE];
132 
133     /* First, try to get a multicast MAC address */
134     if (!getMacAddress(UuidSeed))
135     {
136         DPRINT1("Failed finding a proper MAC address, will generate seed\n");
137         CookupNodeId(UuidSeed);
138     }
139 
140     /* Seed our UUID generator */
141     Status = NtSetUuidSeed(UuidSeed);
142     if (!NT_SUCCESS(Status))
143     {
144         DPRINT1("NtSetUuidSeed failed with status: %lx\n", Status);
145     }
146 }
147