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