+#elif defined(PERF_METHOD2)
+
+/*************************************************************
+ METHOD 2
+
+ Uses NtQuerySystemInformation.
+ This requires definitions that are not part of
+ standard include files.
+*************************************************************/
+#include <ntdef.h>
+
+typedef enum _SYSTEM_INFORMATION_CLASS
+{
+ SystemBasicInformation = 0,
+ SystemPerformanceInformation = 2,
+ SystemTimeOfDayInformation = 3,
+ SystemProcessesAndThreadsInformation = 5,
+ SystemProcessorTimes = 8,
+ SystemPagefileInformation = 18,
+ /* There are a lot more of these... */
+} SYSTEM_INFORMATION_CLASS;
+
+typedef struct _SYSTEM_BASIC_INFORMATION
+{
+ ULONG Unknown;
+ ULONG MaximumIncrement;
+ ULONG PhysicalPageSize;
+ ULONG NumberOfPhysicalPages;
+ ULONG LowestPhysicalPage;
+ ULONG HighestPhysicalPage;
+ ULONG AllocationGranularity;
+ ULONG LowestUserAddress;
+ ULONG HighestUserAddress;
+ ULONG ActiveProcessors;
+ UCHAR NumberProcessors;
+} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
+
+typedef struct __attribute__ ((aligned (8))) _SYSTEM_PROCESSOR_TIMES
+{
+ LARGE_INTEGER IdleTime;
+ LARGE_INTEGER KernelTime;
+ LARGE_INTEGER UserTime;
+ LARGE_INTEGER DpcTime;
+ LARGE_INTEGER InterruptTime;
+ ULONG InterruptCount;
+} SYSTEM_PROCESSOR_TIMES, *PSYSTEM_PROCESSOR_TIMES;
+
+typedef NTSTATUS NTAPI (*NtQuerySystemInformation_t) (SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+typedef ULONG NTAPI (*RtlNtStatusToDosError_t) (NTSTATUS);
+
+static NtQuerySystemInformation_t NtQuerySystemInformation;
+static RtlNtStatusToDosError_t RtlNtStatusToDosError;
+
+/*****************************************************************
+ *
+ LoadNtdll()
+ Load special functions from the NTDLL
+ Return TRUE if success.
+
+ *****************************************************************/
+
+static BOOL LoadNtdll()
+{
+ HINSTANCE hinstLib;
+
+ if ((hinstLib = LoadLibrary("NTDLL.DLL"))
+ && (NtQuerySystemInformation =
+ (NtQuerySystemInformation_t) GetProcAddress(hinstLib,
+ "NtQuerySystemInformation"))
+ && (RtlNtStatusToDosError =
+ (RtlNtStatusToDosError_t) GetProcAddress(hinstLib,
+ "RtlNtStatusToDosError")))
+ return TRUE;
+
+ DEBUG(D_load)
+ debug_printf("perf: load: %ld (Windows)\n", GetLastError());
+ return FALSE;
+}
+
+/*****************************************************************
+ *
+ ReadStat()
+ Measures current Time100ns and IdleCount
+ Return TRUE if success.
+
+ *****************************************************************/
+
+static BOOL ReadStat(unsigned long long int *Time100nsPtr,
+ unsigned long long int *IdleCountPtr)
+{
+ NTSTATUS ret;
+ SYSTEM_BASIC_INFORMATION sbi;
+ PSYSTEM_PROCESSOR_TIMES spt;
+
+ *Time100nsPtr = *IdleCountPtr = 0;
+
+ if ((ret = NtQuerySystemInformation(SystemBasicInformation,
+ (PVOID) &sbi, sizeof sbi, NULL))
+ != STATUS_SUCCESS) {
+ DEBUG(D_load)
+ debug_printf("Perf: NtQuerySystemInformation: %lu (Windows)\n",
+ RtlNtStatusToDosError(ret));
+ }
+ else if (!(spt = (PSYSTEM_PROCESSOR_TIMES) alloca(sizeof(spt[0]) * sbi.NumberProcessors))) {
+ DEBUG(D_load)
+ debug_printf("Perf: alloca: errno %d (%s)\n", errno, strerror(errno));
+ }
+ else if ((ret = NtQuerySystemInformation(SystemProcessorTimes, (PVOID) spt,
+ sizeof spt[0] * sbi.NumberProcessors, NULL))
+ != STATUS_SUCCESS) {
+ DEBUG(D_load)
+ debug_printf("Perf: NtQuerySystemInformation: %lu (Windows)\n",
+ RtlNtStatusToDosError(ret));
+ }
+ else {
+ int i;
+ for (i = 0; i < sbi.NumberProcessors; i++) {
+ *Time100nsPtr += spt[i].KernelTime.QuadPart;;
+ *Time100nsPtr += spt[i].UserTime.QuadPart;
+ *IdleCountPtr += spt[i].IdleTime.QuadPart;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif /* PERF_METHODX */
+