#ifdef OS_WINCE #include "windows.h" #include #include "ceconfig.h" // extern "C" { // The following four files are from the OS, but are needed here // by the GUID-generation code, so they were copied over. // Ick... #include "tdiinfo.h" #include "tdistat.h" #include "llinfo.h" #include "wscntl.h" #define REGISTRY_ROOT TEXT("Software\\Microsoft\\Terminal Server Client") #define REGISTRY_VALUE_UUID TEXT("UUID") #define ETHER_ADDRESS_LENGTH 6 #define DEFAULT_MINIMUM_ENTITIES 32 #define MAX_ADAPTER_DESCRIPTION_LENGTH 128 #define RPC_UUID_TIME_HIGH_MASK 0x0FFF #define RPC_UUID_VERSION 0x1000 #define RPC_UUID_RESERVED 0x80 #define RPC_UUID_CLOCK_SEQ_HI_MASK 0x3F typedef struct { unsigned long ulTimeLow; unsigned short usTimeMid; unsigned short usTimeHiAndVersion; unsigned char ucClockSeqHiAndReserved; unsigned char ucClockSeqLow; unsigned char ucNodeId[6]; } _UUID; static unsigned int gs_seq = 0; static LARGE_INTEGER gs_tm = {0}; static unsigned char gs_ucEtherAddr[ETHER_ADDRESS_LENGTH]; static int gs_fIsAddressInitialized = FALSE; static void GetAdapterAddress() { if(!gs_fIsAddressInitialized) { memset (gs_ucEtherAddr, 0, sizeof(gs_ucEtherAddr)); // Load WinSock.DLL so we can call into WsControl(...) HINSTANCE hInstWinSock = LoadLibrary(TEXT("winsock.dll")); if(0 != hInstWinSock) { DWORD(*fpfWsControl)(DWORD Protocol, DWORD Action, LPVOID InputBuffer, LPDWORD InputBufferLength, LPVOID OutputBuffer, LPDWORD OutputBufferLength); fpfWsControl = (DWORD(*)(DWORD Protocol, DWORD Action, LPVOID InputBuffer, LPDWORD InputBufferLength, LPVOID OutputBuffer, LPDWORD OutputBufferLength))GetProcAddress(hInstWinSock, TEXT("WsControl")); if(0 != fpfWsControl) { // First, obtain list of TCP entities... TCP_REQUEST_QUERY_INFORMATION_EX req; memset(&req, 0, sizeof(req)); req.ID.toi_entity.tei_entity = GENERIC_ENTITY; req.ID.toi_entity.tei_instance = 0; req.ID.toi_class = INFO_CLASS_GENERIC; req.ID.toi_type = INFO_TYPE_PROVIDER; req.ID.toi_id = ENTITY_LIST_ID; int iInputLen = sizeof(req); int iOutputLen = sizeof(TDIEntityID) * DEFAULT_MINIMUM_ENTITIES; TDIEntityID *pEntity = NULL; for ( ; ; ) { int iPrevOutputLen = iOutputLen; pEntity = (TDIEntityID*)LocalAlloc(LPTR, (size_t)iOutputLen); if (!pEntity) break; DWORD status = fpfWsControl(IPPROTO_TCP, WSCNTL_TCPIP_QUERY_INFO, (LPVOID)&req, (ULONG *)&iInputLen, (LPVOID)pEntity, (ULONG *)&iOutputLen ); if (status != TDI_SUCCESS) { LocalFree(pEntity); pEntity = NULL; break; } if (iOutputLen <= iPrevOutputLen) break; LocalFree(pEntity); } if (0 != pEntity) { int iCount = (UINT)(iOutputLen / sizeof(TDIEntityID)); // Second, walk through these in search of adapters TDIEntityID *pRunner = pEntity; for (int i = 0; i < iCount; ++i, ++pRunner) { // IF_ENTITY: this entity/instance describes an adapter if (pRunner->tei_entity == IF_ENTITY) { // find out if this entity supports MIB requests memset(&req, 0, sizeof(req)); TDIObjectID id; memset (&id, 0, sizeof(id)); id.toi_entity = *pRunner; id.toi_class = INFO_CLASS_GENERIC; id.toi_type = INFO_TYPE_PROVIDER; id.toi_id = ENTITY_TYPE_ID; req.ID = id; DWORD fIsMib = FALSE; iInputLen = sizeof(req); iOutputLen = sizeof(fIsMib); DWORD status = fpfWsControl(IPPROTO_TCP, WSCNTL_TCPIP_QUERY_INFO, (LPVOID)&req, (ULONG *)&iInputLen, (LPVOID)&fIsMib, (ULONG *)&iOutputLen ); if (status != TDI_SUCCESS) break; if (fIsMib != IF_MIB) continue; // MIB requests supported - query the adapter info id.toi_class = INFO_CLASS_PROTOCOL; id.toi_id = IF_MIB_STATS_ID; memset(&req, 0, sizeof(req)); req.ID = id; BYTE info[sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1]; iInputLen = sizeof(req); iOutputLen = sizeof(info); status = fpfWsControl(IPPROTO_TCP, WSCNTL_TCPIP_QUERY_INFO, (LPVOID)&req, (ULONG *)&iInputLen, (LPVOID)&info, (ULONG *)&iOutputLen ); if (status != TDI_SUCCESS) break; if (iOutputLen > sizeof(info)) continue; IFEntry* pIfEntry = (IFEntry*)info; memcpy (gs_ucEtherAddr, pIfEntry->if_physaddr, sizeof (gs_ucEtherAddr)); gs_fIsAddressInitialized = TRUE; break; } } LocalFree (pEntity); } } FreeLibrary(hInstWinSock); } } } BOOL generate_guid (GUID *guid) { GetAdapterAddress(); // It may fail, but gs_ucEtherAddr will still be all 0 _UUID *p_uuid = (_UUID *)guid; SYSTEMTIME st; GetLocalTime(&st); LARGE_INTEGER tm2; SystemTimeToFileTime (&st, (FILETIME *)&tm2); if (gs_tm.QuadPart < tm2.QuadPart) gs_tm = tm2; else ++gs_tm.QuadPart; if (gs_tm.QuadPart > tm2.QuadPart + 1000) { // Clock reset or super heavy usage gs_tm = tm2; ++gs_seq; } unsigned int uiLowPart = gs_tm.LowPart; unsigned int uiHighPart = gs_tm.HighPart; unsigned int uiSeq = gs_seq; p_uuid->ulTimeLow = (unsigned long)uiLowPart; p_uuid->usTimeMid = (unsigned short)(uiHighPart & 0x0000FFFF); p_uuid->usTimeHiAndVersion = (unsigned short)(( (unsigned short)(uiHighPart >> 16) & RPC_UUID_TIME_HIGH_MASK) | RPC_UUID_VERSION); p_uuid->ucClockSeqHiAndReserved = RPC_UUID_RESERVED | (((unsigned char) (uiSeq >> 8)) & (unsigned char) RPC_UUID_CLOCK_SEQ_HI_MASK); p_uuid->ucClockSeqLow = (unsigned char) (uiSeq & 0x00FF); p_uuid->ucNodeId[0] = gs_ucEtherAddr[0]; p_uuid->ucNodeId[1] = gs_ucEtherAddr[1]; p_uuid->ucNodeId[2] = gs_ucEtherAddr[2]; p_uuid->ucNodeId[3] = gs_ucEtherAddr[3]; p_uuid->ucNodeId[4] = gs_ucEtherAddr[4]; p_uuid->ucNodeId[5] = gs_ucEtherAddr[5]; return TRUE; } BOOL OEMGetUUID(GUID* pGuid) { DWORD len; HKEY hKey; BOOL fRetVal = FALSE; len = sizeof(UUID); // Try to read the UUID from the registry - if we find one, use it if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_ROOT, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { DWORD dwType; if ( ( RegQueryValueEx(hKey, REGISTRY_VALUE_UUID, 0, &dwType, (BYTE*)pGuid, &len) == ERROR_SUCCESS) && (sizeof(UUID) == len) ) { fRetVal = TRUE; } RegCloseKey(hKey); } if (!fRetVal) { // We didn't find a UUID in the registry, so we need to generate one now // First, try asking the hardware for a UUID... fRetVal = KernelIoControl(IOCTL_HAL_GET_UUID, NULL, 0, pGuid, len, &len); // If the hardware was unable to provide a UUID, generate one now. if (!fRetVal) { fRetVal = generate_guid(pGuid); } // Save the UUID (however we got it) in the registry so that we will always use this UUID if(fRetVal) { DWORD dwDisposition; BOOL fSavedKey = FALSE; if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_ROOT, 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, &dwDisposition) == ERROR_SUCCESS) { if (RegSetValueEx(hKey, REGISTRY_VALUE_UUID, 0, REG_BINARY, (BYTE*)pGuid, len) == ERROR_SUCCESS) { fSavedKey = TRUE; } RegCloseKey(hKey); } // If we can't save the registry key, we have to return failure because we don't want to leak licenses fRetVal = fSavedKey; } } if (!fRetVal) { // We failed to generate a UUID. MessageBox(NULL, TEXT("Can't read or generate licensing information. (Unable to generate a UUID or read one from the registry.)"), TEXT("Error"), MB_OK); } return fRetVal; } // }; // extern "C" #endif // OS_WINCE