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
getMacAddress(UCHAR * MacAddress)29 getMacAddress(UCHAR * MacAddress)
30 {
31 /* FIXME: query NDIS for all the interfaces */
32 UNIMPLEMENTED;
33 return FALSE;
34 }
35
36 static VOID
CookupNodeId(UCHAR * NodeId)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
DealWithDeviceEvent(VOID)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