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.

569 lines
16 KiB

  1. /*++
  2. Filename : Machines.c
  3. Description: This contains the functions that will interrogate the
  4. machine for details.
  5. The GetNTSoundINfo function is directly copied from David Shiftlet's code.
  6. Since we didn't use it, I'm not going to waste debug time figuring out
  7. if the random code he put in actually works.
  8. Created by: Wally Ho
  9. History: Created on 02/01/99.
  10. Contains these functions:
  11. 1. DWORD GetCurrentMachinesBuildNumber( VOID );
  12. 2. DWORD RandomMachineID(VOID)
  13. 3. VOID GetNTSoundInfo(OUT LPMACHINE_DETAILS pMd)
  14. 4. VOID GetVidInfo (OUT LPMACHINE_DETAILS pMd)
  15. 5. VOID GetPNPDevices (OUT LPMACHINE_DETAILS pMd)
  16. 6. BOOL IsHydra ( VOID )
  17. 7. BOOL GetPnPDisplayInfo(LPTSTR pOutputData)
  18. --*/
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <windows.h>
  22. #include <time.h>
  23. #include <sys/timeb.h>
  24. #include <tchar.h>
  25. #include <winuser.h>
  26. #include "network.h"
  27. #include "machines.h"
  28. #include "idw_dbg.h"
  29. // For PnP Stuff
  30. #include <devguid.h>
  31. #include <initguid.h>
  32. #include <setupapi.h>
  33. #include <syssetup.h>
  34. #include <regstr.h>
  35. #include <setupbat.h>
  36. #include <cfgmgr32.h>
  37. #include "netinfo.h"
  38. // These aren't used but I think I can use them
  39. // somewhere so I'll leave them here. Wallyho
  40. LPTSTR Days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  41. LPTSTR Months[] = { "", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  42. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  43. DWORD
  44. GetCurrentMachinesBuildNumber( VOID )
  45. /*++
  46. Author: Wallyho.
  47. Routine Description:
  48. Purpose this should get the current build number of the
  49. running OS.
  50. Arguments:
  51. NONE
  52. Return Value:
  53. The DWORD of the build.
  54. --*/
  55. {
  56. OSVERSIONINFO osVer;
  57. osVer.dwOSVersionInfoSize= sizeof( osVer );
  58. if (GetVersionEx( &osVer )&&osVer.dwMajorVersion >= 5)
  59. return osVer.dwBuildNumber;
  60. else
  61. return FALSE;
  62. }
  63. DWORD
  64. RandomMachineID(VOID)
  65. /*++
  66. Copyright (c) 2000, Microsoft.
  67. Author: Wally W. Ho (wallyho)
  68. Date: 8/18/2000
  69. Routine Description:
  70. Generates DWORD random MachineID for each machine.
  71. There is a very slim chance that duplicates could occur.
  72. Arguments:
  73. NONE
  74. Return Value:
  75. The DWORD random ID.
  76. --*/
  77. {
  78. INT i;
  79. INT iLenCName;
  80. INT iNameTotal = 0;
  81. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1];
  82. DWORD dwSize;
  83. DWORD dwMachineID;
  84. CHAR szRandomID[ 4 ]; // need 4 bytes to contain the DWORD.
  85. struct _timeb tm;
  86. //
  87. // This will get us the milliseconds
  88. _ftime(&tm);
  89. //
  90. // Seed the random number generator.
  91. // We will seed with the seconds + milliseconds at
  92. // at that time. I was getting the same number
  93. // if I pressed the keyboard too fast in testing this.
  94. // The milli seconds should decrease the expectancy of
  95. // duplication.
  96. //
  97. srand( ((UINT)time(NULL)) + tm.millitm);
  98. //
  99. // This will guarantee a mostly random identifier.
  100. // Even with no computer name. We will tally the
  101. // ascii decimal value of the computer name and
  102. // add that to the randomly generated number.
  103. // The possibility of a dup is greatly decreased
  104. // since we switched to a dword system.
  105. // This computername tweak should be unnecessary.
  106. //
  107. dwSize = sizeof(szComputerName);
  108. if (0 == GetComputerName(szComputerName,&dwSize) ){
  109. //
  110. // This algorithm will limit the random number to
  111. // uppercase ascii alphabet.
  112. //
  113. szComputerName[0] = 65 + (rand() % 25);
  114. szComputerName[1] = 65 + (rand() % 25);
  115. szComputerName[2] = 65 + (rand() % 25);
  116. szComputerName[3] = 65 + (rand() % 25);
  117. szComputerName[4] = 65 + (rand() % 25);
  118. szComputerName[5] = 65 + (rand() % 25);
  119. szComputerName[6] = 65 + (rand() % 25);
  120. szComputerName[7] = TEXT('\0');
  121. }
  122. iLenCName = _tcslen (szComputerName);
  123. //
  124. // Tally up the individual elements in the file
  125. //
  126. for (i = 0; i < iLenCName; i++)
  127. iNameTotal += szComputerName[i];
  128. //
  129. // Generate four 8 bit numbers.
  130. // Add the some random number based on the
  131. // computername mod'ed to 0-100.
  132. // Limit the 8 bit number to 0-155 to make room
  133. // for the 100 from the computer name tweak.
  134. // Total per 8 bit is 256.
  135. // Do this tweak to only 2.
  136. // We will then cast and shift to combine it
  137. // into a DWORD.
  138. //
  139. szRandomID[0] = (rand() % 155) + (iNameTotal % 100);
  140. szRandomID[1] = rand() % 255;
  141. szRandomID[2] = (rand() % 155) + (iNameTotal % 100);
  142. szRandomID[3] = rand() % 255;
  143. // This should limit the last digit to 0011 only two binaries so we will
  144. // only get 9 chars in the random id. 10 chars may cause an overflow
  145. // of the dword we are using.
  146. //
  147. // This will combine the 4 8bit CHAR into one DWORD
  148. //
  149. dwMachineID = (DWORD)szRandomID[0] * 0x00000001 +
  150. (DWORD)szRandomID[1] * 0x00000100 +
  151. (DWORD)szRandomID[2] * 0x00010000 +
  152. (DWORD)szRandomID[3] * 0x01000000;
  153. return dwMachineID;
  154. }
  155. VOID
  156. GetNTSoundInfo(OUT LPMACHINE_DETAILS pMd)
  157. {
  158. HKEY hKey;
  159. DWORD dwCbData;
  160. ULONG ulType;
  161. LPTSTR sSubKey=TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32");
  162. INT i;
  163. TCHAR szSubKeyName[ MAX_PATH ];
  164. TCHAR szTempString[ MAX_PATH ];
  165. // Get Sound Card Info
  166. pMd->iNumWaveOutDevices = 0;
  167. hKey = 0;
  168. if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, sSubKey, 0, KEY_READ, &hKey)){
  169. // Loop through the key to see how many wave devices we have, but skip mmdrv.dll.
  170. for (i = 0; i <= 1; i++){
  171. if (i != 0)
  172. _stprintf(szSubKeyName, TEXT("wave%d"),i);
  173. else
  174. _tcscpy(szSubKeyName, TEXT("wave"));
  175. dwCbData = sizeof (szTempString);
  176. if (RegQueryValueEx(hKey, szSubKeyName, 0, &ulType, (LPBYTE)szTempString, &dwCbData))
  177. break;
  178. else{
  179. // We want to skip mmdrv.dll - not relevant.
  180. if (szTempString[0] &&
  181. _tcscmp(szTempString, TEXT("mmdrv.dll"))) {
  182. _tcscpy(&pMd->szWaveDriverName[pMd->iNumWaveOutDevices][0],
  183. szTempString);
  184. pMd->iNumWaveOutDevices++;
  185. }
  186. }
  187. }
  188. }
  189. if (hKey){
  190. RegCloseKey(hKey);
  191. hKey = 0;
  192. }
  193. sSubKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\drivers.desc");
  194. hKey = 0;
  195. if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, sSubKey, 0, KEY_READ, &hKey)){
  196. // Now grab the sound device string for each wave device
  197. for (i = 0; i < pMd->iNumWaveOutDevices; i++){
  198. dwCbData = sizeof szTempString;
  199. if (RegQueryValueEx(hKey, pMd->szWaveDriverName[i], 0, &ulType, (LPBYTE)szTempString, &dwCbData))
  200. _tcscpy(pMd->szWaveOutDesc[i], TEXT("Unknown"));
  201. else
  202. _tcscpy(pMd->szWaveOutDesc[i], szTempString);
  203. }
  204. }
  205. if (hKey){
  206. RegCloseKey(hKey);
  207. hKey = 0;
  208. }
  209. return;
  210. }
  211. VOID
  212. GetVidInfo (OUT LPMACHINE_DETAILS pMd)
  213. /*++
  214. GetVidInfo reads registry information about the installed
  215. video cards and produces one string
  216. --*/
  217. {
  218. TCHAR szDeviceKey[256];
  219. WCHAR szWideBuf[128];
  220. HKEY hkHardware;
  221. HKEY hkCard;
  222. DWORD dwSize;
  223. TCHAR szSubKey[128];
  224. DWORD dwIndex=0;
  225. DWORD dwMem;
  226. DWORD iLoop;
  227. LPTSTR pch;
  228. DISPLAY_DEVICE displayDevice;
  229. DEVMODE dmCurrent;
  230. // make sure its zeroed even though it should be from ZeroMemory.
  231. pMd->szVideoInfo[0] = TEXT('\0');
  232. szWideBuf[0] = TEXT('\0');
  233. // Look in HWKEY to find out what services are used.
  234. if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_LOCAL_MACHINE, VIDEOKEY, 0, KEY_READ, &hkHardware)){
  235. Idwlog(TEXT("Failed to open the Video hardware Key. Video is NULL."));
  236. return;
  237. }
  238. dwSize=128;
  239. while (ERROR_SUCCESS == RegEnumKeyEx (hkHardware, dwIndex++,szSubKey, &dwSize,NULL,NULL,NULL,NULL)){
  240. // Append the subkey name to SERVICEKEY.
  241. // Look up only Device0 for this card
  242. _stprintf (szDeviceKey, ("%s\\%s\\Device0"), SERVICEKEY, szSubKey);
  243. RegOpenKeyEx (HKEY_LOCAL_MACHINE, szDeviceKey, 0, KEY_READ, &hkCard);
  244. // First get the description
  245. dwSize=256;
  246. if (ERROR_SUCCESS == RegQueryValueEx( hkCard, DEVICE_DESCR, NULL, NULL, (_TUCHAR *)szDeviceKey, &dwSize)){
  247. if (_tcsclen(pMd->szVideoInfo ) + dwSize < 254){
  248. _tcscpy(pMd->szVideoInfo , szDeviceKey);
  249. _tcscat (pMd->szVideoInfo , TEXT(" "));
  250. }
  251. }
  252. // Read the chip type. This is a UNICODE string stored in REG_BINARY format
  253. dwSize=256;
  254. lstrcpyW (szWideBuf, L"ChipType:");
  255. if (ERROR_SUCCESS == RegQueryValueEx (hkCard, CHIP_TYPE,NULL, NULL, (LPBYTE)(szWideBuf+9), &dwSize)){
  256. if ((dwSize=lstrlen(pMd->szVideoInfo))+lstrlenW(szWideBuf)<254) {
  257. WideCharToMultiByte (CP_ACP,
  258. 0,
  259. szWideBuf,
  260. -1,
  261. pMd->szVideoInfo + dwSize,
  262. 256-dwSize,
  263. NULL,
  264. NULL);
  265. _tcscat (pMd->szVideoInfo, TEXT(" "));
  266. }
  267. }
  268. // Read the DAC. Another UNICODE string
  269. dwSize=256;
  270. lstrcpyW (szWideBuf, L"DACType:");
  271. if (ERROR_SUCCESS == RegQueryValueEx (hkCard, DAC_TYPE, NULL, NULL, (LPBYTE)(szWideBuf+8), &dwSize)){
  272. if ((dwSize=lstrlen(pMd->szVideoInfo))+lstrlenW(szWideBuf)<254){
  273. WideCharToMultiByte (CP_ACP,
  274. 0,
  275. szWideBuf,
  276. -1,
  277. pMd->szVideoInfo + dwSize,
  278. 256 - dwSize,
  279. NULL,
  280. NULL);
  281. _tcscat (pMd->szVideoInfo, TEXT(" "));
  282. }
  283. }
  284. // Read the memory size. This is a binary value.
  285. dwSize=sizeof(DWORD);
  286. if (ERROR_SUCCESS == RegQueryValueEx (hkCard, MEM_TYPE, NULL,NULL,(LPBYTE)&dwMem, &dwSize)){
  287. _stprintf (szDeviceKey, TEXT("Memory:0x%x ;"), dwMem);
  288. if (_tcsclen(pMd->szVideoInfo)+lstrlen(szDeviceKey)<255)
  289. _tcscat (pMd->szVideoInfo, szDeviceKey);
  290. }
  291. RegCloseKey (hkCard);
  292. dwSize=128;
  293. }
  294. RegCloseKey (hkHardware);
  295. //__________________________________________________________________
  296. // Video Information for ChrisW
  297. // Video display name.
  298. _tcscpy(pMd->szVideoDisplayName,TEXT("Unknown"));
  299. displayDevice.cb = sizeof(DISPLAY_DEVICE);
  300. iLoop = 0;
  301. while(EnumDisplayDevices(NULL, iLoop, &displayDevice, 0)) {
  302. ZeroMemory( &dmCurrent, sizeof(dmCurrent) );
  303. dmCurrent.dmSize= sizeof(dmCurrent);
  304. if( EnumDisplaySettings( displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &dmCurrent ) ) {
  305. if(iLoop == 0)
  306. pMd->szVideoDisplayName[0] = 0;
  307. else
  308. _tcscat( pMd->szVideoDisplayName, TEXT(",") );
  309. _tcscat( pMd->szVideoDisplayName, (LPCTSTR)dmCurrent.dmDeviceName );
  310. }
  311. iLoop++;
  312. }
  313. // replace spaces so we don't break the perl script the build lab is using
  314. pch = pMd->szVideoDisplayName;
  315. while(*pch) {
  316. if(*pch == TEXT(' '))
  317. *pch = TEXT('.');
  318. pch++;
  319. }
  320. }
  321. extern DEV_INFO *g_pdiDevList;
  322. // in netinfo.c
  323. VOID
  324. GetPNPDevices (OUT LPMACHINE_DETAILS pMd)
  325. /*++
  326. GetPNP Devices like net, scsi, pcmcia etc.
  327. This is a wally created function incorporting the random
  328. placement of this from before.
  329. --*/
  330. {
  331. DEV_INFO *pdi;
  332. // Get PNP net card info
  333. _tcscpy(pMd->szNetcards, TEXT("Unknown"));
  334. _tcscpy(pMd->szScsi, TEXT("Unknown"));
  335. _tcscpy(pMd->szModem , TEXT("Unknown"));
  336. CollectDevData ();
  337. pdi=g_pdiDevList;
  338. while (pdi){
  339. if (0 == _tcscmp(pdi->szClass, TEXT("Net"))){
  340. if (_tcsclen(pMd->szNetcards) + _tcsclen(pdi->szDescription) + _tcsclen(pdi->szService) < 250){
  341. _tcscpy (pMd->szNetcards, pdi->szDescription);
  342. _tcscat (pMd->szNetcards, "(");
  343. _tcscat (pMd->szNetcards, pdi->szService);
  344. _tcscat (pMd->szNetcards, TEXT(")"));
  345. }
  346. }
  347. else if (0 == _tcscmp(pdi->szClass, TEXT("SCSIAdapter"))){
  348. if (_tcsclen(pMd->szScsi) + _tcsclen(pdi->szService) < 250){
  349. _tcscpy (pMd->szScsi, pdi->szService);
  350. _tcscat (pMd->szScsi, TEXT(","));
  351. }
  352. }
  353. else if (0 == _tcscmp(pdi->szClass, TEXT("Modem"))){
  354. if (_tcsclen( pMd->szModem) + _tcsclen(pdi->szDescription) < 250){
  355. _tcscpy ( pMd->szModem, pdi->szDescription);
  356. _tcscat ( pMd->szModem, TEXT(","));
  357. }
  358. }
  359. else if (0 == _tcscmp(pdi->szClass, TEXT("USB")))
  360. pMd->bUSB = TRUE;
  361. else if (0 == _tcscmp(pdi->szClass, TEXT("Infrared")))
  362. pMd->bIR = TRUE;
  363. else if (0 == _tcscmp(pdi->szClass, TEXT("PCMCIA") ) ||
  364. 0 == _tcscmp(pdi->szService, TEXT("PCMCIA") ))
  365. pMd->bPCCard = TRUE;
  366. else if (_tcsstr(pdi->szClass, TEXT("ACPI")) ||
  367. _tcsstr(pdi->szService, TEXT("ACPI")))
  368. pMd->bACPI = TRUE;
  369. pdi=pdi->Next;
  370. }
  371. Cleanup(); //free all the pnp data and restore configuration
  372. if (pMd->szNetcards[0] == 0)
  373. _tcscpy (pMd->szNetcards, TEXT("Unknown"));
  374. }
  375. BOOL
  376. IsHydra ( VOID )
  377. // Hydra is denoted by "Terminal Server" in the ProductOptions key
  378. {
  379. BOOL rVal = FALSE;
  380. LONG Rslt;
  381. HKEY hKey = NULL;
  382. DWORD Type = 0;
  383. DWORD Size = 0;
  384. LPTSTR ProductSuite = NULL;
  385. LPTSTR p;
  386. __try{
  387. Rslt = RegOpenKey(
  388. HKEY_LOCAL_MACHINE,
  389. TEXT("System\\CurrentControlSet\\Control\\ProductOptions"),
  390. &hKey
  391. );
  392. if (Rslt != ERROR_SUCCESS)
  393. goto exit;
  394. Rslt = RegQueryValueEx( hKey, TEXT("ProductSuite"), NULL, &Type, NULL, &Size );
  395. if (Rslt != ERROR_SUCCESS || !Size)
  396. goto exit;
  397. ProductSuite = (LPTSTR) LocalAlloc( LPTR, Size );
  398. if (!ProductSuite)
  399. goto exit;
  400. Rslt = RegQueryValueEx( hKey, TEXT("ProductSuite"), NULL, &Type,
  401. (LPBYTE) ProductSuite, &Size );
  402. if (Rslt != ERROR_SUCCESS || Type != REG_MULTI_SZ)
  403. goto exit;
  404. p = ProductSuite;
  405. while (*p) {
  406. if (_tcscmp( p, TEXT("Terminal Server") ) == 0) {
  407. rVal = TRUE;
  408. break;
  409. }
  410. p += (_tcslen( p ) + 1);
  411. }
  412. exit:
  413. if (ProductSuite)
  414. LocalFree( ProductSuite );
  415. if (hKey)
  416. RegCloseKey( hKey );
  417. }__except (EXCEPTION_EXECUTE_HANDLER) {
  418. // This is here as for some reason this faults in NT 4.0.
  419. }
  420. return rVal;
  421. }
  422. /*
  423. BOOL
  424. GetPnPDisplayInfo(
  425. LPTSTR pOutputData
  426. )
  427. {
  428. BOOL bRet = FALSE;
  429. HDEVINFO hDevInfo;
  430. SP_DEVINFO_DATA DeviceInfoData;
  431. DWORD index = 0;
  432. TCHAR RegistryProperty[256];
  433. ULONG BufferSize;
  434. //
  435. // Let's find all the video drivers that are installed in the system
  436. //
  437. hDevInfo = SetupDiGetClassDevs((LPGUID) &GUID_DEVCLASS_DISPLAY,
  438. NULL,
  439. NULL,
  440. 0);
  441. while (hDevInfo != INVALID_HANDLE_VALUE){
  442. if (bRet)
  443. strcat(pOutputData, TEXT(",") );
  444. ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
  445. DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  446. if (!SetupDiEnumDeviceInfo(hDevInfo,
  447. index++,
  448. &DeviceInfoData))
  449. break;
  450. BufferSize = sizeof(RegistryProperty);
  451. if (CR_SUCCESS ==
  452. CM_Get_Device_ID(DeviceInfoData.DevInst,
  453. RegistryProperty,
  454. sizeof(RegistryProperty),
  455. 0)){
  456. bRet = TRUE;
  457. strcat(pOutputData, RegistryProperty);
  458. }
  459. }
  460. return (bRet);
  461. }
  462. */