Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

243 lines
10 KiB

  1. #ifdef OS_WINCE
  2. // BUGBUG -- cleanup sources file in this dir a little (include wincecom.inc)
  3. #include "windows.h"
  4. #include <winsock.h>
  5. // extern "C" {
  6. // The following four files are from the OS, but are needed here
  7. // by the GUID-generation code, so they were copied over.
  8. // Ick...
  9. #include "tdiinfo.h"
  10. #include "tdistat.h"
  11. #include "llinfo.h"
  12. #include "wscntl.h"
  13. #define REGISTRY_ROOT TEXT("Software\\Microsoft\\Terminal Server Client")
  14. #define REGISTRY_VALUE_UUID TEXT("UUID")
  15. #define ETHER_ADDRESS_LENGTH 6
  16. #define DEFAULT_MINIMUM_ENTITIES 32
  17. #define MAX_ADAPTER_DESCRIPTION_LENGTH 128
  18. #define RPC_UUID_TIME_HIGH_MASK 0x0FFF
  19. #define RPC_UUID_VERSION 0x1000
  20. #define RPC_UUID_RESERVED 0x80
  21. #define RPC_UUID_CLOCK_SEQ_HI_MASK 0x3F
  22. typedef struct {
  23. unsigned long ulTimeLow;
  24. unsigned short usTimeMid;
  25. unsigned short usTimeHiAndVersion;
  26. unsigned char ucClockSeqHiAndReserved;
  27. unsigned char ucClockSeqLow;
  28. unsigned char ucNodeId[6];
  29. } _UUID;
  30. static unsigned int gs_seq = 0;
  31. static LARGE_INTEGER gs_tm = {0};
  32. static unsigned char gs_ucEtherAddr[ETHER_ADDRESS_LENGTH];
  33. static int gs_fIsAddressInitialized = FALSE;
  34. static void GetAdapterAddress()
  35. {
  36. if(!gs_fIsAddressInitialized) {
  37. memset (gs_ucEtherAddr, 0, sizeof(gs_ucEtherAddr));
  38. // Load WinSock.DLL so we can call into WsControl(...)
  39. HINSTANCE hInstWinSock = LoadLibrary(TEXT("winsock.dll"));
  40. if(0 != hInstWinSock) {
  41. DWORD(*fpfWsControl)(DWORD Protocol, DWORD Action, LPVOID InputBuffer, LPDWORD InputBufferLength, LPVOID OutputBuffer, LPDWORD OutputBufferLength);
  42. fpfWsControl = (DWORD(*)(DWORD Protocol, DWORD Action, LPVOID InputBuffer, LPDWORD InputBufferLength, LPVOID OutputBuffer, LPDWORD OutputBufferLength))GetProcAddress(hInstWinSock, TEXT("WsControl"));
  43. if(0 != fpfWsControl) {
  44. // First, obtain list of TCP entities...
  45. TCP_REQUEST_QUERY_INFORMATION_EX req;
  46. memset(&req, 0, sizeof(req));
  47. req.ID.toi_entity.tei_entity = GENERIC_ENTITY;
  48. req.ID.toi_entity.tei_instance = 0;
  49. req.ID.toi_class = INFO_CLASS_GENERIC;
  50. req.ID.toi_type = INFO_TYPE_PROVIDER;
  51. req.ID.toi_id = ENTITY_LIST_ID;
  52. int iInputLen = sizeof(req);
  53. int iOutputLen = sizeof(TDIEntityID) * DEFAULT_MINIMUM_ENTITIES;
  54. TDIEntityID *pEntity = NULL;
  55. for ( ; ; ) {
  56. int iPrevOutputLen = iOutputLen;
  57. pEntity = (TDIEntityID*)LocalAlloc(LPTR, (size_t)iOutputLen);
  58. if (!pEntity)
  59. break;
  60. DWORD status = fpfWsControl(IPPROTO_TCP,
  61. WSCNTL_TCPIP_QUERY_INFO,
  62. (LPVOID)&req,
  63. (ULONG *)&iInputLen,
  64. (LPVOID)pEntity,
  65. (ULONG *)&iOutputLen
  66. );
  67. if (status != TDI_SUCCESS) {
  68. LocalFree(pEntity);
  69. pEntity = NULL;
  70. break;
  71. }
  72. if (iOutputLen <= iPrevOutputLen)
  73. break;
  74. LocalFree(pEntity);
  75. }
  76. if (0 != pEntity) {
  77. int iCount = (UINT)(iOutputLen / sizeof(TDIEntityID));
  78. // Second, walk through these in search of adapters
  79. TDIEntityID *pRunner = pEntity;
  80. for (int i = 0; i < iCount; ++i, ++pRunner) {
  81. // IF_ENTITY: this entity/instance describes an adapter
  82. if (pRunner->tei_entity == IF_ENTITY) {
  83. // find out if this entity supports MIB requests
  84. memset(&req, 0, sizeof(req));
  85. TDIObjectID id;
  86. memset (&id, 0, sizeof(id));
  87. id.toi_entity = *pRunner;
  88. id.toi_class = INFO_CLASS_GENERIC;
  89. id.toi_type = INFO_TYPE_PROVIDER;
  90. id.toi_id = ENTITY_TYPE_ID;
  91. req.ID = id;
  92. DWORD fIsMib = FALSE;
  93. iInputLen = sizeof(req);
  94. iOutputLen = sizeof(fIsMib);
  95. DWORD status = fpfWsControl(IPPROTO_TCP,
  96. WSCNTL_TCPIP_QUERY_INFO,
  97. (LPVOID)&req,
  98. (ULONG *)&iInputLen,
  99. (LPVOID)&fIsMib,
  100. (ULONG *)&iOutputLen
  101. );
  102. if (status != TDI_SUCCESS)
  103. break;
  104. if (fIsMib != IF_MIB)
  105. continue;
  106. // MIB requests supported - query the adapter info
  107. id.toi_class = INFO_CLASS_PROTOCOL;
  108. id.toi_id = IF_MIB_STATS_ID;
  109. memset(&req, 0, sizeof(req));
  110. req.ID = id;
  111. BYTE info[sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1];
  112. iInputLen = sizeof(req);
  113. iOutputLen = sizeof(info);
  114. status = fpfWsControl(IPPROTO_TCP,
  115. WSCNTL_TCPIP_QUERY_INFO,
  116. (LPVOID)&req,
  117. (ULONG *)&iInputLen,
  118. (LPVOID)&info,
  119. (ULONG *)&iOutputLen
  120. );
  121. if (status != TDI_SUCCESS)
  122. break;
  123. if (iOutputLen > sizeof(info))
  124. continue;
  125. IFEntry* pIfEntry = (IFEntry*)info;
  126. memcpy (gs_ucEtherAddr, pIfEntry->if_physaddr, sizeof (gs_ucEtherAddr));
  127. gs_fIsAddressInitialized = TRUE;
  128. break;
  129. }
  130. }
  131. LocalFree (pEntity);
  132. }
  133. }
  134. FreeLibrary(hInstWinSock);
  135. }
  136. }
  137. }
  138. BOOL generate_guid (GUID *guid) {
  139. GetAdapterAddress(); // It may fail, but gs_ucEtherAddr will still be all 0
  140. _UUID *p_uuid = (_UUID *)guid;
  141. SYSTEMTIME st;
  142. GetLocalTime(&st);
  143. LARGE_INTEGER tm2;
  144. SystemTimeToFileTime (&st, (FILETIME *)&tm2);
  145. if (gs_tm.QuadPart < tm2.QuadPart)
  146. gs_tm = tm2;
  147. else
  148. ++gs_tm.QuadPart;
  149. if (gs_tm.QuadPart > tm2.QuadPart + 1000) { // Clock reset or super heavy usage
  150. gs_tm = tm2;
  151. ++gs_seq;
  152. }
  153. unsigned int uiLowPart = gs_tm.LowPart;
  154. unsigned int uiHighPart = gs_tm.HighPart;
  155. unsigned int uiSeq = gs_seq;
  156. p_uuid->ulTimeLow = (unsigned long)uiLowPart;
  157. p_uuid->usTimeMid = (unsigned short)(uiHighPart & 0x0000FFFF);
  158. p_uuid->usTimeHiAndVersion = (unsigned short)(( (unsigned short)(uiHighPart >> 16) & RPC_UUID_TIME_HIGH_MASK) | RPC_UUID_VERSION);
  159. p_uuid->ucClockSeqHiAndReserved = RPC_UUID_RESERVED | (((unsigned char) (uiSeq >> 8)) & (unsigned char) RPC_UUID_CLOCK_SEQ_HI_MASK);
  160. p_uuid->ucClockSeqLow = (unsigned char) (uiSeq & 0x00FF);
  161. p_uuid->ucNodeId[0] = gs_ucEtherAddr[0];
  162. p_uuid->ucNodeId[1] = gs_ucEtherAddr[1];
  163. p_uuid->ucNodeId[2] = gs_ucEtherAddr[2];
  164. p_uuid->ucNodeId[3] = gs_ucEtherAddr[3];
  165. p_uuid->ucNodeId[4] = gs_ucEtherAddr[4];
  166. p_uuid->ucNodeId[5] = gs_ucEtherAddr[5];
  167. return TRUE;
  168. }
  169. BOOL OEMGetUUID(GUID* pGuid)
  170. {
  171. DWORD len;
  172. HKEY hKey;
  173. BOOL fRetVal = FALSE;
  174. len = sizeof(UUID);
  175. // Try to read the UUID from the registry - if we find one, use it
  176. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_ROOT, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  177. {
  178. DWORD dwType;
  179. if ( ( RegQueryValueEx(hKey, REGISTRY_VALUE_UUID, 0, &dwType,
  180. (BYTE*)pGuid, &len) == ERROR_SUCCESS) && (sizeof(UUID) == len) )
  181. {
  182. fRetVal = TRUE;
  183. }
  184. RegCloseKey(hKey);
  185. }
  186. if (!fRetVal)
  187. {
  188. // We didn't find a UUID in the registry, so we need to generate one now
  189. // First, try asking the hardware for a UUID...
  190. fRetVal = KernelIoControl(IOCTL_HAL_GET_UUID, NULL, 0, pGuid, len, &len);
  191. // If the hardware was unable to provide a UUID, generate one now.
  192. if (!fRetVal)
  193. {
  194. fRetVal = generate_guid(pGuid);
  195. }
  196. // Save the UUID (however we got it) in the registry so that we will always use this UUID
  197. if(fRetVal) {
  198. DWORD dwDisposition;
  199. BOOL fSavedKey = FALSE;
  200. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_ROOT, 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, &dwDisposition) == ERROR_SUCCESS)
  201. {
  202. if (RegSetValueEx(hKey, REGISTRY_VALUE_UUID, 0, REG_BINARY, (BYTE*)pGuid, len) == ERROR_SUCCESS)
  203. {
  204. fSavedKey = TRUE;
  205. }
  206. RegCloseKey(hKey);
  207. }
  208. // If we can't save the registry key, we have to return failure because we don't want to leak licenses
  209. fRetVal = fSavedKey;
  210. }
  211. }
  212. if (!fRetVal)
  213. {
  214. // We failed to generate a UUID.
  215. MessageBox(NULL,
  216. TEXT("Can't read or generate licensing information. (Unable to generate a UUID or read one from the registry.)"),
  217. TEXT("Error"), MB_OK);
  218. }
  219. return fRetVal;
  220. }
  221. // }; // extern "C"
  222. #endif // OS_WINCE