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.

690 lines
17 KiB

  1. /*++
  2. Copyright (c) 1998-1999, Microsoft Corporation
  3. Module Name:
  4. Hardware.cpp
  5. Abstract:
  6. --*/
  7. #include "Hardware.h"
  8. #include <stdio.h> // only needed for testing
  9. #if defined(WIN32) || defined(_WIN32)
  10. static inline BOOL IsPlatformNT()
  11. {
  12. // always do it 'The NT Way'
  13. return TRUE;
  14. /*/////////////////////////////////////////////////////////////////////////////
  15. OSVERSIONINFO osvInfo;
  16. BOOL fNTPlatformFlag;
  17. osvInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  18. GetVersionEx( &osvInfo );
  19. switch( osvInfo.dwPlatformId )
  20. {
  21. case VER_PLATFORM_WIN32_NT:
  22. fNTPlatformFlag = TRUE;
  23. break;
  24. default:
  25. fNTPlatformFlag = FALSE;
  26. break;
  27. }
  28. return( fNTPlatformFlag );
  29. *//////////////////////////////////////////////////////////////////////////////
  30. }
  31. #else
  32. inline BOOL IsPlatformNT()
  33. {
  34. return FALSE;
  35. }
  36. extern "C" extern WORD _C000H;
  37. extern "C" extern WORD _F000H;
  38. #endif
  39. CHardware::CHardware()
  40. #ifdef HWID_DETAIL ////////////////////////////////////////////////////////////
  41. : m_dwBiosCrc32(0),
  42. m_dwVolSer(0),
  43. m_dwTotalRamMegs(0),
  44. m_dwVideoBiosCrc32(0)
  45. #endif
  46. {
  47. uClassID = CHARDWARE_CLASSID;
  48. ZeroMemory( (LPVOID)m_szHardwareID, HARDWARE_ID_SIZE );
  49. SetBIOSDigit();
  50. SetHDSerialDigit();
  51. SetTotalRAMDigit();
  52. SetFDConfigDigit();
  53. SetVideoBIOSDigit();
  54. #ifndef NO_HWID_GUID //////////////////////////////////////////////////////////
  55. CalculateHardwareGUID();
  56. #endif ////////////////////////////////////////////////////////////////////////
  57. }
  58. CHardware::~CHardware()
  59. {
  60. }
  61. DWORD CHardware::GetType()
  62. {
  63. return(IsPlatformNT() ? 1 : 0);
  64. }
  65. LPSTR CHardware::GetID()
  66. {
  67. return( m_szHardwareID );
  68. }
  69. #ifndef NO_HWID_GUID //////////////////////////////////////////////////////////
  70. LPSTR CHardware::GetGUID()
  71. {
  72. return( m_szHardwareGUID );
  73. }
  74. #endif ////////////////////////////////////////////////////////////////////////
  75. VOID CHardware::SetBIOSDigit()
  76. {
  77. DWORD dwBIOSChecksum;
  78. #if defined(WIN32) || defined(_WIN32)
  79. if ( IsPlatformNT() )
  80. {
  81. dwBIOSChecksum = CalculateRegKeyChecksum( "SystemBiosDate" );
  82. dwBIOSChecksum += CalculateRegKeyChecksum( "SystemBiosVersion" );
  83. m_dwBiosCrc32 = dwBIOSChecksum;
  84. } else
  85. #endif
  86. {
  87. LPBYTE pbMemoryByte;
  88. #if defined(WIN32) || defined(_WIN32)
  89. pbMemoryByte = (LPBYTE)0xF0000;
  90. #else
  91. pbMemoryByte = (LPBYTE)MAKELONG(0, &_F000H);
  92. #endif
  93. dwBIOSChecksum = CalculateMemoryRegionChecksum(pbMemoryByte, 2048);
  94. #ifdef HWID_DETAIL ////////////////////////////////////////////////////////////
  95. m_dwBiosCrc32 = CRC_32(pbMemoryByte, 2048);
  96. #endif
  97. }
  98. m_szHardwareID[ BIOS_DIGIT ] = (CHAR)( dwBIOSChecksum % 9 ) + '0';
  99. }
  100. #if defined(WIN32) || defined(_WIN32)
  101. UINT CHardware::CalculateRegKeyChecksum(LPSTR lpszKey)
  102. {
  103. LONG lStatus;
  104. HKEY hkSystem;
  105. UINT uChecksum;
  106. uChecksum = 0;
  107. lStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System", 0, KEY_QUERY_VALUE, &hkSystem );
  108. _ASSERT( lStatus == ERROR_SUCCESS );
  109. if ( lStatus == ERROR_SUCCESS )
  110. {
  111. DWORD dwValueType;
  112. DWORD dwBufferSize;
  113. BYTE Buffer[ MAX_BIOS_KEY_LENGTH ];
  114. dwBufferSize = MAX_BIOS_KEY_LENGTH;
  115. lStatus = RegQueryValueEx( hkSystem, lpszKey, NULL, &dwValueType, Buffer, &dwBufferSize );
  116. // ASSERT( lStatus == ERROR_SUCCESS ); // Not all values are guarenteed to exist
  117. if ( lStatus == ERROR_SUCCESS )
  118. {
  119. UINT nCurrentByte;
  120. for ( nCurrentByte = 0; nCurrentByte < dwBufferSize; nCurrentByte++ )
  121. {
  122. uChecksum += Buffer[ nCurrentByte ];
  123. }
  124. }
  125. RegCloseKey( hkSystem );
  126. }
  127. return( uChecksum );
  128. }
  129. #endif
  130. DWORD CHardware::CalculateMemoryRegionChecksum( LPBYTE pbChecksumArea, INT nNumberBytes )
  131. {
  132. DWORD dwRegionChecksum = 0;
  133. while (0 < nNumberBytes)
  134. {
  135. dwRegionChecksum += (UINT)( *pbChecksumArea );
  136. ++pbChecksumArea;
  137. --nNumberBytes;
  138. }
  139. return( dwRegionChecksum );
  140. }
  141. #if !defined(WIN32) && !defined(_WIN32)
  142. #pragma pack(1)
  143. // Media ID
  144. typedef struct {
  145. WORD wInfoLevel;
  146. DWORD dwSerialNum;
  147. char achVolLabel[11];
  148. BYTE abFileSysType[8];
  149. } MID, *PMID, FAR* LPMID;
  150. #pragma pack()
  151. #endif
  152. VOID CHardware::SetHDSerialDigit()
  153. {
  154. m_szHardwareID[ HD_SERIAL_DIGIT ] = '?';
  155. BOOL fInfoSuccess;
  156. DWORD dwVolumeSerialNumber;
  157. #if defined(WIN32) || defined(_WIN32)
  158. DWORD dwFileSystemFlags;
  159. DWORD dwMaximumComponentLength;
  160. CHAR szBootDrivePath[ MAX_PATH ];
  161. wsprintf( szBootDrivePath, "C:\\" );
  162. fInfoSuccess = GetVolumeInformation( szBootDrivePath, NULL, 0, &dwVolumeSerialNumber, &dwMaximumComponentLength, &dwFileSystemFlags, NULL, 0 );
  163. _ASSERT( fInfoSuccess );
  164. #else
  165. LPMID pmid;
  166. union _REGS regs;
  167. struct _SREGS segregs;
  168. DWORD dwMem;
  169. dwMem = GlobalDosAlloc(sizeof(MID));
  170. WORD wMidSelector = LOWORD(dwMem);
  171. WORD wMidSegment = HIWORD(dwMem);
  172. pmid = (LPMID)MAKELP(wMidSelector, 0);
  173. ZeroMemory(pmid, sizeof(MID));
  174. ZeroMemory(&regs, sizeof(regs));
  175. ZeroMemory(&segregs, sizeof(segregs));
  176. regs.x.ax = 0x440d; // DOS Function 440Dh - IOCTL for Block Device
  177. regs.h.cl = 0x66; // Minor Code 66h - Get Media ID
  178. regs.h.ch = 0x08; // Device category (must be 08h)
  179. regs.x.bx = 3; // Drive C:
  180. regs.x.dx = 0; // pmid offset
  181. segregs.ds = wMidSelector; // wMidSegment;
  182. segregs.es = wMidSelector; // wMidSegment;
  183. _intdosx(&regs, &regs, &segregs);
  184. fInfoSuccess = !regs.x.cflag;
  185. dwVolumeSerialNumber = pmid->dwSerialNum;
  186. GlobalDosFree(wMidSelector);
  187. #endif
  188. if ( fInfoSuccess )
  189. {
  190. m_szHardwareID[ HD_SERIAL_DIGIT ] = (CHAR)( dwVolumeSerialNumber % 9 ) + '0';
  191. #ifdef HWID_DETAIL ////////////////////////////////////////////////////////////
  192. m_dwVolSer = dwVolumeSerialNumber;
  193. #endif
  194. }
  195. }
  196. VOID CHardware::SetTotalRAMDigit()
  197. {
  198. DWORD dwTotalMegabytes;
  199. m_szHardwareID[ TOTAL_RAM_DIGIT ] = '?';
  200. #if defined(WIN32) || defined(_WIN32)
  201. MEMORYSTATUS mStatus;
  202. mStatus.dwLength = sizeof( MEMORYSTATUS );
  203. GlobalMemoryStatus( &mStatus );
  204. dwTotalMegabytes = (DWORD)( mStatus.dwTotalPhys / (1024 * 1024)); // convert to Megabytes
  205. dwTotalMegabytes += 1; // Add 1Mb to produce accurate result due to reserved space
  206. #else
  207. BYTE abDpmiMemInfo[0x30];
  208. memset(abDpmiMemInfo, -1, sizeof(abDpmiMemInfo));
  209. __asm {
  210. push di ;save regs
  211. push ss
  212. pop es ;make es point to stack
  213. lea di,abDpmiMemInfo ;Get offset of buffer
  214. mov ax,0500h ;DPMI -- Get Free Memory Info
  215. int 31h ;Call DPMI
  216. pop di ;restore regs
  217. }
  218. DWORD dwTotalPages = *(LPDWORD)&abDpmiMemInfo[0x18];
  219. // check to see if the field is -1 (error) and just use 0
  220. // we're adding 1 to account for the memory below 1M (I think)
  221. dwTotalMegabytes = (dwTotalPages == -1) ? 0 : (1 + dwTotalPages/(1024/4));
  222. #endif
  223. m_szHardwareID[ TOTAL_RAM_DIGIT ] = (CHAR)( dwTotalMegabytes % 9 ) + '0';
  224. #ifdef HWID_DETAIL ////////////////////////////////////////////////////////////
  225. m_dwTotalRamMegs = dwTotalMegabytes;
  226. #endif
  227. }
  228. VOID CHardware::SetFDConfigDigit()
  229. {
  230. DWORD dwFDConfig;
  231. #if defined(WIN32) || defined(_WIN32)
  232. if ( IsPlatformNT() )
  233. {
  234. dwFDConfig = CalculateDriveCapacityNT( 1 ) << 2;
  235. dwFDConfig += CalculateDriveCapacityNT( 2 );
  236. } else
  237. #endif
  238. {
  239. #ifndef _WIN64
  240. dwFDConfig = CalculateDriveCapacity95( 1 ) << 2;
  241. dwFDConfig += CalculateDriveCapacity95( 2 );
  242. #endif
  243. }
  244. m_szHardwareID[ FD_CONFIG_DIGIT ] = (CHAR)( dwFDConfig % 9 ) + '0';
  245. }
  246. #ifndef _WIN64
  247. DWORD CHardware::CalculateDriveCapacity95( INT nDrive )
  248. {
  249. DWORD dwDriveCapacity = 0;
  250. BOOL fOk;
  251. UINT uNumberHeads;
  252. UINT uNumberTracks;
  253. UINT uBytesPerSector;
  254. UINT uSectorsPerTrack;
  255. LPBYTE pbDiskParamTable;
  256. #if defined(WIN32) || defined(_WIN32)
  257. HANDLE hDevice;
  258. BOOL fResult;
  259. DIOC_REGISTERS DIOCRegs;
  260. DWORD dwBytesReturned;
  261. // Open VWIN32 Device For Access To DOS Int 13h Functions
  262. hDevice = CreateFile( "\\\\.\\vwin32", 0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL );
  263. fOk = (hDevice != INVALID_HANDLE_VALUE);
  264. if (fOk)
  265. {
  266. // Invoke Int 13h Function 08h - Get Drive Parameters
  267. DIOCRegs.reg_EAX = 0x0800; // Get Drive Parameters
  268. DIOCRegs.reg_EDX = nDrive - 1; // 0 = A:, 1 = B:
  269. fResult = DeviceIoControl( hDevice, VWIN32_DIOC_DOS_INT13, &DIOCRegs, sizeof( DIOC_REGISTERS ), &DIOCRegs, sizeof( DIOC_REGISTERS ), &dwBytesReturned, NULL );
  270. // Determine if Int 13h Call Succeeded
  271. fOk = (fResult == TRUE && 0 == (DIOCRegs.reg_Flags & FLAGS_CARRY));
  272. }
  273. if (fOk)
  274. {
  275. // Calculate Drive Capacity if Drive Number is Valid
  276. if ( ( DIOCRegs.reg_EDX & 0xFF ) >= (UINT)nDrive )
  277. {
  278. pbDiskParamTable = (UCHAR *)DIOCRegs.reg_EDI;
  279. uNumberHeads = ( ( DIOCRegs.reg_EDX >> 8 ) & 0xFF ) + 1;
  280. uNumberTracks = ( ( ( DIOCRegs.reg_ECX << 2 ) & 0x300 ) + ( ( DIOCRegs.reg_ECX >> 8 ) & 0xFF ) ) + 1;
  281. uSectorsPerTrack = ( DIOCRegs.reg_ECX & 0x3F );
  282. uBytesPerSector = ( 128 << ( *( pbDiskParamTable + 3 ) ) );
  283. dwDriveCapacity = uNumberHeads * uNumberTracks * uSectorsPerTrack * uBytesPerSector;
  284. }
  285. }
  286. if (hDevice != INVALID_HANDLE_VALUE)
  287. {
  288. CloseHandle( hDevice );
  289. }
  290. #else
  291. union _REGS regs;
  292. struct _SREGS segregs;
  293. ZeroMemory(&regs, sizeof(regs));
  294. ZeroMemory(&segregs, sizeof(segregs));
  295. regs.h.ah = 0x08; // BIOS Function 08h - Get drive parameters
  296. regs.x.dx = nDrive - 1; // 0 = A:, 1 = B:
  297. _int86x(
  298. 0x13, // BIOS Disk
  299. &regs,
  300. &regs,
  301. &segregs);
  302. fOk = (!regs.x.cflag);
  303. if (fOk)
  304. {
  305. uNumberHeads = regs.h.dh + 1;
  306. uNumberTracks = ((regs.h.cl & 0xC0) << 2) + regs.h.ch + 1;
  307. uSectorsPerTrack = regs.h.cl & 0x3F;
  308. pbDiskParamTable = (LPBYTE)MAKELP(segregs.es, regs.x.di);
  309. uBytesPerSector = (128 << pbDiskParamTable[3]);
  310. dwDriveCapacity = (DWORD)uNumberHeads * uNumberTracks * uSectorsPerTrack * uBytesPerSector;
  311. }
  312. #endif
  313. dwDriveCapacity /= ( 1024L * 100L );
  314. return( dwDriveCapacity );
  315. }
  316. #endif
  317. #if defined(WIN32) || defined(_WIN32)
  318. DWORD CHardware::CalculateDriveCapacityNT(INT nDrive)
  319. {
  320. BOOL fDriveExists;
  321. DWORD dwDriveCapacity;
  322. DWORD dwBytesReturned;
  323. CHAR szDrive[ MAX_PATH ];
  324. CHAR szDriveAssignment[ MAX_PATH ];
  325. dwDriveCapacity = 0;
  326. // Determine if Logical Drive Exists
  327. fDriveExists = FALSE;
  328. wsprintf( szDrive, "%c:", 'A' + ( nDrive - 1 ) ); // Create DOS Drive Identifier (A: or B:)
  329. dwBytesReturned = QueryDosDevice( szDrive, szDriveAssignment, MAX_PATH );
  330. if ( dwBytesReturned != 0 )
  331. {
  332. LPTSTR lpszWalkString;
  333. // DBCS-Enabled Terminate String At 2nd Backslash (1st Backslash always at Position 0)
  334. lpszWalkString = szDriveAssignment;
  335. do
  336. {
  337. lpszWalkString = CharNext( lpszWalkString );
  338. switch( *lpszWalkString )
  339. {
  340. case '\\':
  341. *lpszWalkString = 0;
  342. break;
  343. }
  344. }
  345. while( *lpszWalkString != 0 );
  346. // Determine if Logical Drive is Physically Present
  347. if ( lstrcmp( szDriveAssignment, "\\Device" ) == 0 )
  348. {
  349. fDriveExists = TRUE;
  350. }
  351. }
  352. if ( fDriveExists == TRUE )
  353. {
  354. // Get All Supported Media Types for Drive
  355. HANDLE hDevice;
  356. BOOL fResult;
  357. wsprintf( szDrive, "\\\\.\\%c:", 'A' + ( nDrive - 1 ) ); // Create NT Drive Identifier (\\.\A: or \\.\B:)
  358. hDevice = CreateFile( szDrive, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
  359. _ASSERT( hDevice != INVALID_HANDLE_VALUE );
  360. if ( hDevice != INVALID_HANDLE_VALUE )
  361. {
  362. DISK_GEOMETRY dGeometry[ 10 ];
  363. fResult = DeviceIoControl( hDevice, IOCTL_DISK_GET_MEDIA_TYPES, NULL, 0, (LPVOID)&dGeometry, sizeof( DISK_GEOMETRY ) * 10, &dwBytesReturned, NULL );
  364. _ASSERT( fResult );
  365. if ( fResult == TRUE )
  366. {
  367. // Calculate Maximum Media Size of Drive in Bytes if No Errors
  368. INT nMediaCount;
  369. INT nCurrentMedia;
  370. UINT uCurrentMediaCapacity;
  371. nMediaCount = dwBytesReturned / sizeof( DISK_GEOMETRY );
  372. for ( nCurrentMedia = 0; nCurrentMedia < nMediaCount; nCurrentMedia++ )
  373. {
  374. uCurrentMediaCapacity = (UINT)dGeometry[ nCurrentMedia ].Cylinders.LowPart;
  375. uCurrentMediaCapacity *= (UINT)dGeometry[ nCurrentMedia ].TracksPerCylinder;
  376. uCurrentMediaCapacity *= (UINT)dGeometry[ nCurrentMedia ].SectorsPerTrack;
  377. uCurrentMediaCapacity *= (UINT)dGeometry[ nCurrentMedia ].BytesPerSector;
  378. if ( uCurrentMediaCapacity > dwDriveCapacity )
  379. {
  380. dwDriveCapacity = uCurrentMediaCapacity;
  381. }
  382. }
  383. }
  384. CloseHandle( hDevice );
  385. }
  386. }
  387. dwDriveCapacity /= ( 1024 * 100 );
  388. return( dwDriveCapacity );
  389. }
  390. #endif
  391. VOID CHardware::SetVideoBIOSDigit()
  392. {
  393. DWORD dwVideoBIOSChecksum;
  394. #if defined(WIN32) || defined(_WIN32)
  395. if ( IsPlatformNT() )
  396. {
  397. dwVideoBIOSChecksum = CalculateRegKeyChecksum( "VideoBiosDate" );
  398. dwVideoBIOSChecksum += CalculateRegKeyChecksum( "VideoBiosVersion" );
  399. #ifdef HWID_DETAIL ////////////////////////////////////////////////////////////
  400. m_dwVideoBiosCrc32 = dwVideoBIOSChecksum;
  401. #endif
  402. } else
  403. #endif
  404. {
  405. LPBYTE pbMemoryByte;
  406. #if defined(WIN32) || defined(_WIN32)
  407. pbMemoryByte = (LPBYTE)0xC0000;
  408. #else
  409. pbMemoryByte = (LPBYTE)MAKELONG(0, &_C000H);
  410. #endif
  411. dwVideoBIOSChecksum = CalculateMemoryRegionChecksum(pbMemoryByte, 2048);
  412. #ifdef HWID_DETAIL ////////////////////////////////////////////////////////////
  413. m_dwVideoBiosCrc32 = CRC_32(pbMemoryByte, 2048);
  414. #endif
  415. }
  416. m_szHardwareID[ VIDEO_BIOS_DIGIT ] = (CHAR)( dwVideoBIOSChecksum % 9 ) + '0';
  417. }
  418. #ifndef NO_HWID_GUID //////////////////////////////////////////////////////////
  419. VOID CHardware::CalculateHardwareGUID()
  420. {
  421. ULONG uCRC;
  422. INT nIndex;
  423. CCrc32 *lpCCrc32;
  424. CHAR szCRCTemp[ 20 ];
  425. // Create Empty Template for GUID
  426. lstrcpy( m_szHardwareGUID, "{30303030-30DA-0000-0000-0020AFC36E79}" );
  427. // Add ASCII HWID to GUID
  428. for ( nIndex = 0; nIndex < lstrlen( m_szHardwareID ); nIndex++ )
  429. {
  430. switch( nIndex )
  431. {
  432. case 0:
  433. case 1:
  434. case 2:
  435. case 3:
  436. m_szHardwareGUID[ 2 + ( nIndex * 2 ) ] = m_szHardwareID[ nIndex ];
  437. break;
  438. case 4:
  439. m_szHardwareGUID[ 11 ] = m_szHardwareID[ nIndex ];
  440. break;
  441. default:
  442. _ASSERT( FALSE );
  443. break;
  444. }
  445. }
  446. // Calculate GUID CRC
  447. lpCCrc32 = new CCrc32();
  448. _ASSERT( lpCCrc32->uClassID == CCRC32_CLASSID );
  449. uCRC = lpCCrc32->CalculateBlockCRC( m_szHardwareGUID, lstrlen( m_szHardwareGUID ) );
  450. delete lpCCrc32;
  451. // Add CRC Result To GUID
  452. wsprintf( szCRCTemp, "%08X", uCRC );
  453. for ( nIndex = 0; nIndex < lstrlen( szCRCTemp ); nIndex++ )
  454. {
  455. switch( nIndex )
  456. {
  457. case 0:
  458. case 1:
  459. case 2:
  460. case 3:
  461. m_szHardwareGUID[ 15 + nIndex ] = szCRCTemp[ nIndex ];
  462. break;
  463. case 4:
  464. case 5:
  465. case 6:
  466. case 7:
  467. m_szHardwareGUID[ 16 + nIndex ] = szCRCTemp[ nIndex ];
  468. break;
  469. default:
  470. _ASSERT( FALSE );
  471. break;
  472. }
  473. }
  474. }
  475. #endif ////////////////////////////////////////////////////////////////////////
  476. #if 0 /////////////////////////////////////////////////////////////////////////
  477. // Test main() function
  478. int PASCAL WinMain(
  479. HINSTANCE, // hInstance, // handle to current instance
  480. HINSTANCE, // hPrevInstance, // handle to previous instance
  481. LPSTR, // lpCmdLine, // pointer to command line
  482. int // nCmdShow // show state of window)
  483. )
  484. {
  485. CHardware hwid;
  486. MessageBox(
  487. NULL,
  488. (char *)hwid.GetGUID(),
  489. (char *)hwid.GetID(),
  490. MB_OK);
  491. return 0;
  492. }
  493. #endif ////////////////////////////////////////////////////////////////////////