Leaked source code of windows server 2003
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.

699 lines
24 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation
  3. Module Name:
  4. sysinfo.cpp
  5. Abstract:
  6. This module implements CSystemInfo, the class that returns various
  7. system information
  8. Author:
  9. William Hsieh (williamh) created
  10. Revision History:
  11. --*/
  12. #include "devmgr.h"
  13. #include "sysinfo.h"
  14. // disk drive root template name. Used to retreive the disk's media
  15. // information or geometry
  16. const TCHAR* const DRIVE_ROOT = TEXT("\\\\.\\?:");
  17. const int DRIVE_LETTER_IN_DRIVE_ROOT = 4;
  18. // disk drive root directory template name. Used to retreive the disk's
  19. // total and free space
  20. const TCHAR* const DRIVE_ROOT_DIR = TEXT("?:\\");
  21. const int DRIVE_LETTER_IN_DRIVE_ROOT_DIR = 0;
  22. //
  23. // Registry various subkey and value names used to retreive
  24. // system information
  25. //
  26. const TCHAR* const REG_PATH_HARDWARE_SYSTEM = TEXT("HARDWARE\\DESCRIPTION\\System");
  27. const TCHAR* const REG_VALUE_SYSTEMBIOSDATE = TEXT("SystemBiosDate");
  28. const TCHAR* const REG_VALUE_SYSTEMBIOSVERSION = TEXT("SystemBiosVersion");
  29. const TCHAR* const REG_VALUE_MACHINETYPE = TEXT("Identifier");
  30. const TCHAR* const REG_PATH_WINDOWS_NT = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
  31. const TCHAR* const REG_VALUE_REGISTERED_OWNER = TEXT("RegisteredOwner");
  32. const TCHAR* const REG_VALUE_REGISTERED_ORGANIZATION = TEXT("RegisteredOrganization");
  33. const TCHAR* const REG_VALUE_CURRENTBUILDNUMBER = TEXT("CurrentBuildNumber");
  34. const TCHAR* const REG_VALUE_CURRENTVERSION = TEXT("CurrentVersion");
  35. const TCHAR* const REG_VALUE_CSDVERSION = TEXT("CSDVersion");
  36. const TCHAR* const REG_PATH_CPU = TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor");
  37. const TCHAR* const REG_VALUE_CPU_TYPE = TEXT("Identifier");
  38. const TCHAR* const REG_VALUE_CPU_VENDOR = TEXT("VendorIdentifier");
  39. CSystemInfo::CSystemInfo(
  40. CMachine* pMachine
  41. )
  42. {
  43. // assuming the machine is a local machine and initialize
  44. // the registry root key as well.
  45. m_hKeyMachine = HKEY_LOCAL_MACHINE;
  46. if (pMachine) {
  47. m_fLocalMachine = pMachine->IsLocal();
  48. m_strComputerName += pMachine->GetMachineDisplayName();
  49. } else {
  50. TCHAR LocalName[MAX_PATH + 1];
  51. DWORD dwSize = ARRAYLEN(LocalName);
  52. if (!GetComputerName(LocalName, &dwSize)) {
  53. LocalName[0] = _T('\0');
  54. }
  55. // local machine
  56. m_fLocalMachine = TRUE;
  57. m_strComputerName = LocalName;
  58. }
  59. if (!m_fLocalMachine) {
  60. // The machine is not local, connect to the registry
  61. String strFullComputerName;
  62. strFullComputerName = (LPCTSTR)TEXT("\\\\");
  63. strFullComputerName += m_strComputerName;
  64. m_hKeyMachine = NULL;
  65. RegConnectRegistry((LPCTSTR)strFullComputerName, HKEY_LOCAL_MACHINE, &m_hKeyMachine);
  66. }
  67. }
  68. CSystemInfo::~CSystemInfo()
  69. {
  70. if (!m_fLocalMachine && NULL != m_hKeyMachine) {
  71. RegCloseKey(m_hKeyMachine);
  72. // disconnect the machine
  73. WNetCancelConnection2(TEXT("\\server\\ipc$"), 0, TRUE);
  74. }
  75. }
  76. //
  77. // This function gets the disk information about the given disk drive
  78. // INPUT:
  79. // Drive -- the drive number. 0 for A, 1 for B and etc.
  80. // DiskInfo -- the DISK_INFO to be filled with the information about
  81. // the drive. DiskInfo.cbSize must be initialized before
  82. // the call.
  83. // OUTPUT:
  84. // TRUE -- if succeeded, DiskInfo is filled with information
  85. // FALSE -- if the drive information can not be retreived.
  86. // No appropriate error code is returned;
  87. BOOL
  88. CSystemInfo::GetDiskInfo(
  89. int Drive,
  90. DISK_INFO& DiskInfo
  91. )
  92. {
  93. // diskinfo only valid on local computer
  94. if (!m_fLocalMachine) {
  95. return FALSE;
  96. }
  97. TCHAR DriveLetter;
  98. TCHAR Root[MAX_PATH];
  99. DriveLetter = (TCHAR)(_T('A') + Drive);
  100. StringCchCopy(Root, ARRAYLEN(Root), DRIVE_ROOT_DIR);
  101. Root[DRIVE_LETTER_IN_DRIVE_ROOT_DIR] = DriveLetter;
  102. UINT DriveType;
  103. DriveType = GetDriveType(Root);
  104. //
  105. // only valid for local drives
  106. //
  107. if (DRIVE_UNKNOWN == DriveType || DRIVE_REMOTE == DriveType ||
  108. DRIVE_NO_ROOT_DIR == DriveType) {
  109. return FALSE;
  110. }
  111. if (DiskInfo.cbSize < sizeof(DISK_INFO)) {
  112. SetLastError(ERROR_INVALID_PARAMETER);
  113. return FALSE;
  114. }
  115. //
  116. // form the disk root name from template
  117. //
  118. StringCchCopy(Root, ARRAYLEN(Root), DRIVE_ROOT);
  119. Root[DRIVE_LETTER_IN_DRIVE_ROOT] = DriveLetter;
  120. HANDLE hDisk;
  121. // FILE_READ_ATTRIBUTES is used here so that we will not get nasty
  122. // error or prompt if the disk is a removable drive and there is no
  123. // media available.
  124. hDisk = CreateFile(Root,
  125. FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  126. FILE_SHARE_READ | FILE_SHARE_WRITE,
  127. NULL,
  128. OPEN_EXISTING,
  129. 0,
  130. NULL);
  131. if (INVALID_HANDLE_VALUE != hDisk) {
  132. // form the disk root directory name from template
  133. StringCchCopy(Root, ARRAYLEN(Root), DRIVE_ROOT_DIR);
  134. Root[DRIVE_LETTER_IN_DRIVE_ROOT_DIR] = DriveLetter;
  135. BYTE Buffer[512];
  136. DWORD BytesRequired = 0;
  137. if (DeviceIoControl(hDisk, IOCTL_STORAGE_GET_MEDIA_TYPES_EX, NULL, 0,
  138. Buffer, sizeof(Buffer), &BytesRequired, NULL)) {
  139. GET_MEDIA_TYPES* pMediaList;
  140. DEVICE_MEDIA_INFO* pMediaInfo;
  141. pMediaList = (GET_MEDIA_TYPES*)Buffer;
  142. pMediaInfo = pMediaList->MediaInfo;
  143. DWORD MediaCount = pMediaList->MediaInfoCount;
  144. ULARGE_INTEGER MaxSpace, NewSpace;
  145. DEVICE_MEDIA_INFO* pMaxMediaInfo;
  146. MaxSpace.QuadPart = 0;
  147. pMaxMediaInfo = NULL;
  148. for (DWORD i = 0; i < MediaCount; i++, pMediaInfo++) {
  149. //
  150. // find the mediainfo which has max space
  151. // A disk drive may support multiple media types and the
  152. // one with maximum capacity is what we want to report.
  153. //
  154. if (DRIVE_REMOVABLE == DriveType || DRIVE_CDROM == DriveType) {
  155. NewSpace.QuadPart =
  156. pMediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector *
  157. pMediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack *
  158. pMediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder *
  159. pMediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart;
  160. } else {
  161. NewSpace.QuadPart =
  162. pMediaInfo->DeviceSpecific.DiskInfo.BytesPerSector *
  163. pMediaInfo->DeviceSpecific.DiskInfo.SectorsPerTrack *
  164. pMediaInfo->DeviceSpecific.DiskInfo.TracksPerCylinder *
  165. pMediaInfo->DeviceSpecific.DiskInfo.Cylinders.QuadPart;
  166. }
  167. if (NewSpace.QuadPart > MaxSpace.QuadPart) {
  168. MaxSpace.QuadPart = NewSpace.QuadPart;
  169. pMaxMediaInfo = pMediaInfo;
  170. }
  171. }
  172. if (pMaxMediaInfo) {
  173. //
  174. // a valid media information is found, compose DISK_INFO
  175. // from the media information
  176. //
  177. DiskInfo.DriveType = DriveType;
  178. if (DRIVE_REMOVABLE == DriveType || DRIVE_CDROM == DriveType) {
  179. DiskInfo.MediaType = pMaxMediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType;
  180. DiskInfo.Cylinders = pMaxMediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders;
  181. DiskInfo.Heads = pMaxMediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder;
  182. DiskInfo.BytesPerSector = pMaxMediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector;
  183. DiskInfo.SectorsPerTrack = pMaxMediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack;
  184. //
  185. // Do not call GetDiskFreeSpaceEx on removable disk
  186. // or CD-ROM
  187. //
  188. DiskInfo.TotalSpace = MaxSpace;
  189. DiskInfo.FreeSpace.QuadPart = (ULONGLONG)-1;
  190. } else {
  191. DiskInfo.MediaType = pMaxMediaInfo->DeviceSpecific.DiskInfo.MediaType;
  192. DiskInfo.Cylinders = pMaxMediaInfo->DeviceSpecific.DiskInfo.Cylinders;
  193. DiskInfo.Heads = pMaxMediaInfo->DeviceSpecific.DiskInfo.TracksPerCylinder;
  194. DiskInfo.BytesPerSector = pMaxMediaInfo->DeviceSpecific.DiskInfo.BytesPerSector;
  195. DiskInfo.SectorsPerTrack = pMaxMediaInfo->DeviceSpecific.DiskInfo.SectorsPerTrack;
  196. StringCchCopy(Root, ARRAYLEN(Root), DRIVE_ROOT_DIR);
  197. Root[DRIVE_LETTER_IN_DRIVE_ROOT_DIR] = DriveLetter;
  198. ULARGE_INTEGER FreeSpaceForCaller;
  199. if (!GetDiskFreeSpaceEx(Root, &FreeSpaceForCaller, &DiskInfo.TotalSpace, &DiskInfo.FreeSpace)) {
  200. DiskInfo.TotalSpace = MaxSpace;
  201. // unknown
  202. DiskInfo.FreeSpace.QuadPart = (ULONGLONG)-1;
  203. }
  204. }
  205. CloseHandle(hDisk);
  206. return TRUE;
  207. }
  208. }
  209. //
  210. // we wouldn't go here if the drive is not removable.
  211. // Basically, this is for floppy drives only.
  212. //
  213. if (DRIVE_REMOVABLE == DriveType &&
  214. DeviceIoControl(hDisk, IOCTL_DISK_GET_MEDIA_TYPES, NULL, 0,
  215. Buffer, sizeof(Buffer), &BytesRequired, NULL)) {
  216. int TotalMediaTypes = BytesRequired / sizeof(DISK_GEOMETRY);
  217. DISK_GEOMETRY* pGeometry;
  218. pGeometry = (DISK_GEOMETRY*)Buffer;
  219. ULARGE_INTEGER MaxSpace;
  220. ULARGE_INTEGER NewSpace;
  221. MaxSpace.QuadPart = 0;
  222. DISK_GEOMETRY* pMaxGeometry = NULL;
  223. for (int i = 0; i < TotalMediaTypes; i++, pGeometry++) {
  224. //
  225. // find the geometry with maximum capacity
  226. //
  227. NewSpace.QuadPart = pGeometry->BytesPerSector *
  228. pGeometry->SectorsPerTrack *
  229. pGeometry->TracksPerCylinder *
  230. pGeometry->Cylinders.QuadPart;
  231. if (NewSpace.QuadPart > MaxSpace.QuadPart) {
  232. pMaxGeometry = pGeometry;
  233. MaxSpace = NewSpace;
  234. }
  235. }
  236. if (pMaxGeometry) {
  237. DiskInfo.DriveType = DriveType;
  238. DiskInfo.MediaType = (STORAGE_MEDIA_TYPE)pMaxGeometry->MediaType;
  239. DiskInfo.Cylinders = pMaxGeometry->Cylinders;
  240. DiskInfo.Heads = pMaxGeometry->TracksPerCylinder;
  241. DiskInfo.BytesPerSector = pMaxGeometry->BytesPerSector;
  242. DiskInfo.SectorsPerTrack = pMaxGeometry->SectorsPerTrack;
  243. DiskInfo.TotalSpace = MaxSpace;
  244. DiskInfo.FreeSpace.QuadPart = (ULONGLONG)-1;
  245. CloseHandle(hDisk);
  246. return TRUE;
  247. }
  248. }
  249. CloseHandle(hDisk);
  250. }
  251. return FALSE;
  252. }
  253. //
  254. // This functions retreive the Window version information in text string
  255. // INPUT:
  256. // Buffer -- buffer to receive the text string
  257. // BufferSize -- buffer size in char(in bytes on ANSI version)
  258. // OUTPUT:
  259. // The size of the text string, not including the terminated NULL char
  260. // If the returned value is 0, GetLastError will returns the error code.
  261. // If the returned value is larger than BufferSize, Buffer is too small
  262. //
  263. DWORD
  264. CSystemInfo::WindowsVersion(
  265. TCHAR* Buffer,
  266. DWORD BufferSize
  267. )
  268. {
  269. if (!Buffer && BufferSize) {
  270. SetLastError(ERROR_INVALID_PARAMETER);
  271. return 0;
  272. }
  273. String strFinalText;
  274. TCHAR Temp[LINE_LEN];
  275. strFinalText.Empty();
  276. strFinalText.LoadString(g_hInstance, IDS_WINDOWS_NT);
  277. CSafeRegistry regWindowsNT;
  278. if (regWindowsNT.Open(m_hKeyMachine, REG_PATH_WINDOWS_NT, KEY_READ)) {
  279. DWORD Type, Size;
  280. Size = sizeof(Temp);
  281. if (regWindowsNT.GetValue(REG_VALUE_CURRENTVERSION, &Type,
  282. (PBYTE)Temp, &Size)) {
  283. strFinalText += (LPCTSTR)Temp;
  284. }
  285. Size = sizeof(Temp);
  286. if (regWindowsNT.GetValue(REG_VALUE_CSDVERSION, &Type,
  287. (PBYTE)Temp, &Size) && Size) {
  288. strFinalText += (LPCTSTR)TEXT(" ");
  289. strFinalText += (LPCTSTR)Temp;
  290. }
  291. Size = sizeof(Temp);
  292. if (regWindowsNT.GetValue(REG_VALUE_CURRENTBUILDNUMBER, &Type,
  293. (PBYTE)Temp, &Size) && Size) {
  294. String strBuildFormat;
  295. strBuildFormat.LoadString(g_hInstance, IDS_BUILD_NUMBER);
  296. String strBuild;
  297. strBuild.Format((LPCTSTR)strBuildFormat, Temp);
  298. strFinalText += strBuild;
  299. }
  300. }
  301. if (BufferSize > (DWORD)strFinalText.GetLength()) {
  302. StringCchCopy(Buffer, BufferSize, (LPCTSTR)strFinalText);
  303. SetLastError(ERROR_SUCCESS);
  304. }
  305. else {
  306. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  307. }
  308. return strFinalText.GetLength();
  309. }
  310. //
  311. // This functions retreive a REG_SZ from the registry
  312. // INPUT:
  313. // SubkeyName -- registry subkey name.
  314. // ValueName -- registry value name;
  315. // Buffer -- buffer to receive the string
  316. // BufferSize -- buffer size in char(in bytes on ANSI version)
  317. // hKeyAncestory -- the key under which Subkeyname should be opened.
  318. //
  319. // OUTPUT:
  320. // The size of the text string, not including the terminated NULL char
  321. // If the returned value is 0, GetLastError will returns the error code.
  322. // If the returned value is larger than BufferSize, Buffer is too small
  323. //
  324. DWORD
  325. CSystemInfo::InfoFromRegistry(
  326. LPCTSTR SubkeyName,
  327. LPCTSTR ValueName,
  328. TCHAR* Buffer,
  329. DWORD BufferSize,
  330. HKEY hKeyAncestor
  331. )
  332. {
  333. // validate parameters
  334. if (!SubkeyName || !ValueName || _T('\0') == *SubkeyName ||
  335. _T('\0') == *SubkeyName || (!Buffer && BufferSize)) {
  336. SetLastError(ERROR_INVALID_PARAMETER);
  337. return 0;
  338. }
  339. if (!hKeyAncestor) {
  340. hKeyAncestor = m_hKeyMachine;
  341. }
  342. CSafeRegistry regSubkey;
  343. if (regSubkey.Open(hKeyAncestor, SubkeyName, KEY_READ)) {
  344. TCHAR Temp[MAX_PATH];
  345. DWORD Type;
  346. DWORD Size;
  347. Size = sizeof(Temp);
  348. if (regSubkey.GetValue(ValueName, &Type, (PBYTE)Temp, &Size) && Size) {
  349. Size /= sizeof(TCHAR);
  350. if (BufferSize > Size) {
  351. StringCchCopy(Buffer, BufferSize, Temp);
  352. }
  353. return Size;
  354. }
  355. }
  356. SetLastError(ERROR_SUCCESS);
  357. return 0;
  358. }
  359. //
  360. // This functions retreive the system BIOS date information in text string
  361. // INPUT:
  362. // Buffer -- buffer to receive the text string
  363. // BufferSize -- buffer size in char(in bytes on ANSI version)
  364. // OUTPUT:
  365. // The size of the text string, not including the terminated NULL char
  366. // If the returned value is 0, GetLastError will returns the error code.
  367. // If the returned value is larger than BufferSize, Buffer is too small
  368. //
  369. DWORD
  370. CSystemInfo::SystemBiosDate(
  371. TCHAR* Buffer,
  372. DWORD BufferSize
  373. )
  374. {
  375. return InfoFromRegistry(REG_PATH_HARDWARE_SYSTEM,
  376. REG_VALUE_SYSTEMBIOSDATE,
  377. Buffer, BufferSize);
  378. }
  379. //
  380. // This functions retreive the system BIOS version information in text string
  381. // INPUT:
  382. // Buffer -- buffer to receive the text string
  383. // BufferSize -- buffer size in char(in bytes on ANSI version)
  384. // OUTPUT:
  385. // The size of the text string, not including the terminated NULL char
  386. // If the returned value is 0, GetLastError will returns the error code.
  387. // If the returned value is larger than BufferSize, Buffer is too small
  388. //
  389. DWORD
  390. CSystemInfo::SystemBiosVersion(
  391. TCHAR* Buffer,
  392. DWORD BufferSize
  393. )
  394. {
  395. return InfoFromRegistry(REG_PATH_HARDWARE_SYSTEM,
  396. REG_VALUE_SYSTEMBIOSVERSION,
  397. Buffer, BufferSize);
  398. }
  399. //
  400. // This functions retreive the machine type in text string
  401. // INPUT:
  402. // Buffer -- buffer to receive the text string
  403. // BufferSize -- buffer size in char(in bytes on ANSI version)
  404. // OUTPUT:
  405. // The size of the text string, not including the terminated NULL char
  406. // If the returned value is 0, GetLastError will returns the error code.
  407. // If the returned value is larger than BufferSize, Buffer is too small
  408. //
  409. DWORD
  410. CSystemInfo::MachineType(
  411. TCHAR* Buffer,
  412. DWORD BufferSize
  413. )
  414. {
  415. return InfoFromRegistry(REG_PATH_HARDWARE_SYSTEM,
  416. REG_VALUE_MACHINETYPE,
  417. Buffer, BufferSize);
  418. }
  419. //
  420. // This functions retreive the registered owner name
  421. // INPUT:
  422. // Buffer -- buffer to receive the text string
  423. // BufferSize -- buffer size in char(in bytes on ANSI version)
  424. // OUTPUT:
  425. // The size of the text string, not including the terminated NULL char
  426. // If the returned value is 0, GetLastError will returns the error code.
  427. // If the returned value is larger than BufferSize, Buffer is too small
  428. //
  429. DWORD
  430. CSystemInfo::RegisteredOwner(
  431. TCHAR* Buffer,
  432. DWORD BufferSize
  433. )
  434. {
  435. return InfoFromRegistry(REG_PATH_WINDOWS_NT,
  436. REG_VALUE_REGISTERED_OWNER,
  437. Buffer,
  438. BufferSize
  439. );
  440. }
  441. //
  442. // This functions retreive the registered organization name
  443. // INPUT:
  444. // Buffer -- buffer to receive the text string
  445. // BufferSize -- buffer size in char(in bytes on ANSI version)
  446. // OUTPUT:
  447. // The size of the text string, not including the terminated NULL char
  448. // If the returned value is 0, GetLastError will returns the error code.
  449. // If the returned value is larger than BufferSize, Buffer is too small
  450. //
  451. DWORD
  452. CSystemInfo::RegisteredOrganization(
  453. TCHAR* Buffer,
  454. DWORD BufferSize
  455. )
  456. {
  457. return InfoFromRegistry(REG_PATH_WINDOWS_NT,
  458. REG_VALUE_REGISTERED_ORGANIZATION,
  459. Buffer,
  460. BufferSize
  461. );
  462. }
  463. // This function resturns the number of processors on the computer
  464. // INPUT:
  465. // NONE
  466. // OUTPUT:
  467. // Number of processor.
  468. //
  469. DWORD
  470. CSystemInfo::NumberOfProcessors()
  471. {
  472. CSafeRegistry regCPU;
  473. DWORD CPUs = 0;
  474. if (regCPU.Open(m_hKeyMachine, REG_PATH_CPU, KEY_READ)) {
  475. TCHAR SubkeyName[MAX_PATH + 1];
  476. DWORD SubkeySize = ARRAYLEN(SubkeyName);
  477. while (regCPU.EnumerateSubkey(CPUs, SubkeyName, &SubkeySize)) {
  478. SubkeySize = ARRAYLEN(SubkeyName);
  479. CPUs++;
  480. }
  481. }
  482. return CPUs;
  483. }
  484. // This function returns the processor vendor in text string
  485. // INPUT:
  486. // Buffer -- buffer to receive the string
  487. // BufferSize -- size of the buffer in char(bytes in ANSI)
  488. // OUTPUT:
  489. // The size of the text string, not including the terminated NULL char
  490. // If the returned value is 0, GetLastError will returns the error code.
  491. // If the returned value is larger than BufferSize, Buffer is too small
  492. //
  493. // The system assumes that all processor in the machine must
  494. // have the same type, therefore, this function does not take
  495. // processor number as a parameter.
  496. DWORD
  497. CSystemInfo::ProcessorVendor(
  498. TCHAR* Buffer,
  499. DWORD BufferSize
  500. )
  501. {
  502. return ProcessorInfo(REG_VALUE_CPU_VENDOR, Buffer, BufferSize);
  503. }
  504. // This function returns the processor type in text string
  505. // INPUT:
  506. // Buffer -- buffer to receive the string
  507. // BufferSize -- size of the buffer in char(bytes in ANSI)
  508. // OUTPUT:
  509. // The size of the text string, not including the terminated NULL char
  510. // If the returned value is 0, GetLastError will returns the error code.
  511. // If the returned value is larger than BufferSize, Buffer is too small
  512. //
  513. // The system assumes that all processor in the machine must
  514. // have the same type, therefore, this function does not take
  515. // processor number as a parameter.
  516. DWORD
  517. CSystemInfo::ProcessorType(
  518. TCHAR* Buffer,
  519. DWORD BufferSize
  520. )
  521. {
  522. return ProcessorInfo(REG_VALUE_CPU_TYPE, Buffer, BufferSize);
  523. }
  524. DWORD
  525. CSystemInfo::ProcessorInfo(
  526. LPCTSTR ValueName,
  527. TCHAR* Buffer,
  528. DWORD BufferSize
  529. )
  530. {
  531. if (!ValueName || (!Buffer && BufferSize)) {
  532. SetLastError(ERROR_INVALID_PARAMETER);
  533. return 0;
  534. }
  535. CSafeRegistry regCPU;
  536. DWORD CPUIndex = 0;
  537. TCHAR CPUInfo[MAX_PATH];
  538. DWORD CPUInfoSize = 0;
  539. DWORD Type;
  540. if (regCPU.Open(m_hKeyMachine, REG_PATH_CPU, KEY_READ)) {
  541. TCHAR CPUKey[MAX_PATH + 1];
  542. DWORD Size;
  543. Size = ARRAYLEN(CPUKey);
  544. // loop through all cpus until we find something interesting
  545. while (CPUInfoSize <= sizeof(TCHAR) &&
  546. regCPU.EnumerateSubkey(CPUIndex, CPUKey, &Size)) {
  547. CSafeRegistry regTheCPU;
  548. if (regTheCPU.Open(regCPU, CPUKey, KEY_READ)) {
  549. CPUInfoSize = sizeof(CPUInfo);
  550. regTheCPU.GetValue(ValueName, &Type, (PBYTE)CPUInfo, &CPUInfoSize);
  551. }
  552. CPUIndex++;
  553. }
  554. // CPUInfoSize != 0 means we find something
  555. if (CPUInfoSize > sizeof(TCHAR)) {
  556. CPUInfoSize = CPUInfoSize / sizeof(TCHAR) - 1;
  557. if (BufferSize > CPUInfoSize) {
  558. StringCchCopy(Buffer, BufferSize, CPUInfo);
  559. }
  560. return CPUInfoSize;
  561. }
  562. }
  563. return 0;
  564. }
  565. //
  566. // This function returns the total physical memeory in KB
  567. // INPUT:
  568. // NONE
  569. // OUTPUT:
  570. // Total Memory in KB
  571. //
  572. void
  573. CSystemInfo::TotalPhysicalMemory(
  574. ULARGE_INTEGER& Size
  575. )
  576. {
  577. if (m_fLocalMachine) {
  578. SYSTEM_BASIC_INFORMATION SysBasicInfo;
  579. NTSTATUS Status;
  580. Status = NtQuerySystemInformation(SystemBasicInformation,
  581. (PVOID)&SysBasicInfo,
  582. sizeof(SysBasicInfo),
  583. NULL);
  584. if (NT_SUCCESS(Status)) {
  585. Size.QuadPart = Int32x32To64(SysBasicInfo.PageSize,
  586. SysBasicInfo.NumberOfPhysicalPages
  587. );
  588. }
  589. else {
  590. MEMORYSTATUS MemoryStatus;
  591. GlobalMemoryStatus(&MemoryStatus);
  592. Size.LowPart = (ULONG)MemoryStatus.dwTotalPhys;
  593. Size.HighPart = 0;
  594. }
  595. }
  596. else {
  597. Size.QuadPart = 0;
  598. SetLastError(ERROR_SUCCESS);
  599. }
  600. }