400 lines
8.5 KiB
C
400 lines
8.5 KiB
C
/*++
|
|
|
|
Copyright (c) 1997-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
perfhit.c
|
|
|
|
Abstract:
|
|
|
|
test app
|
|
|
|
Author:
|
|
|
|
16-Jan-1997 AlanWar
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#define INITGUID
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <ole2.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <ntdddisk.h>
|
|
#include <ntddstor.h>
|
|
|
|
#include "wmium.h"
|
|
|
|
#define OffsetToPtr(Base, Offset) ((PBYTE)((PBYTE)Base + Offset))
|
|
|
|
|
|
ULONG InstanceCount;
|
|
PCHAR *InstanceNames;
|
|
|
|
ULONG SmartDisabled;
|
|
|
|
GUID SmartStatusGuid = WMI_DISK_FAILURE_PREDICT_STATUS_GUID;
|
|
GUID SmartDataGuid = WMI_DISK_FAILURE_PREDICT_DATA_GUID;
|
|
GUID SmartPerformFunction = WMI_DISK_FAILURE_PREDICT_FUNCTION_GUID;
|
|
|
|
// void AllowPerformanceHit([in] boolean Allow)
|
|
#define AllowDisallowPerformanceHit 1
|
|
|
|
// void EnableDisableHardwareFailurePrediction([in] boolean Enable)
|
|
#define EnableDisableHardwareFailurePrediction 2
|
|
|
|
// void EnableDisableFailurePredictionPolling(
|
|
// [in] uint32 Period,
|
|
// [in] boolean Enable)
|
|
#define EnableDisableFailurePredictionPolling 3
|
|
|
|
// void GetFailurePredictionCapability([out] uint32 Capability)
|
|
#define GetFailurePredictionCapability 4
|
|
|
|
// void EnableOfflineDiags([out] boolean Success);
|
|
#define EnableOfflineDiags 5
|
|
|
|
GUID SmartEventGuid = STORAGE_PREDICT_FAILURE_EVENT_GUID;
|
|
|
|
DEFINE_GUID(WmiScsiAddressGuid,
|
|
0x53f5630f,
|
|
0xb6bf,
|
|
0x11d0,
|
|
0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
|
|
|
typedef ULONG (*THREADFUNC)(
|
|
PVOID FirstTestNumber,
|
|
PVOID LastTestNumber
|
|
);
|
|
|
|
|
|
typedef struct
|
|
{
|
|
THREADFUNC ThreadFunc;
|
|
PVOID FirstTestNumber;
|
|
PVOID LastTestNumber;
|
|
} LAUNCHCTX, *PLAUNCHCTX;
|
|
|
|
ULONG LaunchThreadProc(PVOID Context)
|
|
{
|
|
PLAUNCHCTX LaunchCtx = (PLAUNCHCTX)Context;
|
|
|
|
(*LaunchCtx->ThreadFunc)(LaunchCtx->FirstTestNumber,
|
|
LaunchCtx->LastTestNumber);
|
|
|
|
return(0);
|
|
}
|
|
|
|
void LaunchThread(
|
|
THREADFUNC ThreadFunc,
|
|
PVOID FirstTestNumber,
|
|
PVOID LastTestNumber
|
|
)
|
|
{
|
|
PLAUNCHCTX LaunchCtx;
|
|
HANDLE ThreadHandle;
|
|
|
|
LaunchCtx = (PLAUNCHCTX)malloc(sizeof(LAUNCHCTX));
|
|
|
|
if (LaunchCtx != NULL)
|
|
{
|
|
LaunchCtx->ThreadFunc = ThreadFunc;
|
|
LaunchCtx->FirstTestNumber = FirstTestNumber;
|
|
LaunchCtx->LastTestNumber = LastTestNumber;
|
|
|
|
ThreadHandle = CreateThread(NULL,
|
|
0,
|
|
LaunchThreadProc,
|
|
LaunchCtx,
|
|
0,
|
|
NULL);
|
|
if (ThreadHandle != NULL)
|
|
{
|
|
CloseHandle(ThreadHandle);
|
|
}
|
|
}
|
|
}
|
|
|
|
ULONG DetermineInstanceNames(
|
|
LPGUID Guid,
|
|
PULONG InstanceCount,
|
|
PCHAR **InstanceNamePtrArray
|
|
)
|
|
{
|
|
WMIHANDLE Handle;
|
|
ULONG status;
|
|
ULONG bufferSize;
|
|
PUCHAR buffer;
|
|
ULONG i, iCount, linkage;
|
|
PWNODE_ALL_DATA WAD;
|
|
PCHAR *iNames;
|
|
PULONG pInstanceNameOffsets;
|
|
PCHAR pName;
|
|
PUSHORT pNameSize;
|
|
|
|
status = WmiOpenBlock(Guid,
|
|
GENERIC_READ,
|
|
&Handle);
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
printf("WmiOpenBlock(Statyus) => %d\n", status);
|
|
return(status);
|
|
}
|
|
|
|
bufferSize = 0x1000;
|
|
buffer = NULL;
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
while (status == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
if (buffer != NULL)
|
|
{
|
|
free(buffer);
|
|
}
|
|
|
|
buffer = malloc(bufferSize);
|
|
if (buffer == NULL)
|
|
{
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
status = WmiQueryAllData(Handle,
|
|
&bufferSize,
|
|
buffer);
|
|
}
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
WAD = (PWNODE_ALL_DATA)buffer;
|
|
linkage = 0;
|
|
iCount = 0;
|
|
do
|
|
{
|
|
WAD = (PWNODE_ALL_DATA)OffsetToPtr(WAD, linkage);
|
|
linkage = WAD->WnodeHeader.Linkage;
|
|
iCount++;
|
|
|
|
} while (linkage != 0);
|
|
|
|
|
|
iNames = malloc(iCount * sizeof(PCHAR));
|
|
if (iNames == NULL)
|
|
{
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
return(status);
|
|
}
|
|
|
|
WAD = (PWNODE_ALL_DATA)buffer;
|
|
linkage = 0;
|
|
i = 0;
|
|
do
|
|
{
|
|
WAD = (PWNODE_ALL_DATA)OffsetToPtr(WAD, linkage);
|
|
|
|
pInstanceNameOffsets = (PULONG)OffsetToPtr(WAD, WAD->OffsetInstanceNameOffsets);
|
|
pNameSize = (PUSHORT)OffsetToPtr(WAD, *pInstanceNameOffsets);
|
|
pName = (PCHAR)OffsetToPtr(pNameSize, sizeof(USHORT));
|
|
|
|
iNames[i] = malloc(*pNameSize + 1);
|
|
if (iNames[i] == NULL)
|
|
{
|
|
status = ERROR_NOT_ENOUGH_MEMORY;
|
|
return(status);
|
|
}
|
|
memset(iNames[i], 0, *pNameSize + 1);
|
|
memcpy(iNames[i], pName, *pNameSize);
|
|
|
|
linkage = WAD->WnodeHeader.Linkage;
|
|
i++;
|
|
|
|
} while (linkage != 0);
|
|
|
|
} else {
|
|
printf("QAD(status) -> %d\n", status);
|
|
}
|
|
|
|
free(buffer);
|
|
|
|
*InstanceCount = iCount;
|
|
*InstanceNamePtrArray = iNames;
|
|
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
void Usage(void)
|
|
{
|
|
printf("perfhit [perf | poll | hardware | offdiag] <enable> <period>\n");
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
ULONG Period;
|
|
BOOLEAN Enable;
|
|
} POLLONOFF, *PPOLLONOFF;
|
|
|
|
|
|
CHAR *FPMethod[] =
|
|
{
|
|
"FailurePredictionNone",
|
|
"FailurePredictionIoctl",
|
|
"FailurePredictionSmart",
|
|
"FailurePredictionSense",
|
|
"FailurePredictionUnknown"
|
|
};
|
|
|
|
int _cdecl main(int argc, char *argv[])
|
|
{
|
|
ULONG status;
|
|
ULONG i;
|
|
WMIHANDLE Handle;
|
|
ULONG len, j;
|
|
BOOLEAN enable;
|
|
ULONG inSize;
|
|
PVOID inPtr;
|
|
ULONG outSize;
|
|
PVOID outPtr;
|
|
POLLONOFF PollOnOff;
|
|
ULONG operation;
|
|
ULONG period;
|
|
int argNeed;
|
|
|
|
status = DetermineInstanceNames(&SmartStatusGuid,
|
|
&InstanceCount,
|
|
&InstanceNames);
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
printf("DetermineInstanceNames failed %d\n", status);
|
|
return(status);
|
|
}
|
|
|
|
|
|
operation = 0;
|
|
if (argc >= 2)
|
|
{
|
|
|
|
argNeed = 3;
|
|
if (_stricmp(argv[1], "perf") == 0)
|
|
{
|
|
operation = AllowDisallowPerformanceHit;
|
|
}
|
|
|
|
if (_stricmp(argv[1], "poll") == 0)
|
|
{
|
|
argNeed = 4;
|
|
operation = EnableDisableFailurePredictionPolling;
|
|
}
|
|
|
|
if (_stricmp(argv[1], "hardware") == 0)
|
|
{
|
|
operation = EnableDisableHardwareFailurePrediction;
|
|
}
|
|
|
|
if (_stricmp(argv[1], "offdiag") == 0)
|
|
{
|
|
operation = EnableOfflineDiags;
|
|
argNeed = 2;
|
|
}
|
|
}
|
|
|
|
if ((operation == 0) ||
|
|
(argNeed != argc))
|
|
{
|
|
Usage();
|
|
return(0);
|
|
}
|
|
|
|
period = 0;
|
|
enable = FALSE;
|
|
|
|
if (argNeed >= 3)
|
|
{
|
|
enable = atoi(argv[2]);
|
|
}
|
|
|
|
if (argNeed == 4)
|
|
{
|
|
period = atoi(argv[3]);
|
|
}
|
|
|
|
printf("Operation %d(%d, %d)\n", operation, enable, period);
|
|
|
|
outPtr = NULL;
|
|
outSize = 0;
|
|
if (operation == EnableDisableFailurePredictionPolling)
|
|
{
|
|
inSize = sizeof(POLLONOFF);
|
|
inPtr = &PollOnOff;
|
|
PollOnOff.Enable = enable;
|
|
PollOnOff.Period = period;
|
|
} else {
|
|
inSize = sizeof(BOOLEAN);
|
|
inPtr = &enable;
|
|
}
|
|
|
|
if (operation == EnableOfflineDiags)
|
|
{
|
|
inSize = 0;
|
|
inPtr = &enable;
|
|
outSize = sizeof(BOOLEAN);
|
|
outPtr = &enable;
|
|
}
|
|
|
|
status = WmiOpenBlock((LPGUID)&SmartPerformFunction,
|
|
GENERIC_EXECUTE,
|
|
&Handle);
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
printf("Open(function guid) -> %d\n", status);
|
|
return(status);
|
|
}
|
|
|
|
|
|
for (i = 0; i < InstanceCount; i++)
|
|
{
|
|
len = sizeof(ULONG);
|
|
status = WmiExecuteMethod(Handle,
|
|
InstanceNames[i],
|
|
GetFailurePredictionCapability,
|
|
0,
|
|
NULL,
|
|
&len,
|
|
&j);
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
j = 4;
|
|
}
|
|
|
|
printf("Instance %d -> %s supports %s \n", i, InstanceNames[i], FPMethod[j]);
|
|
|
|
status = WmiExecuteMethod(Handle,
|
|
InstanceNames[i],
|
|
operation,
|
|
inSize,
|
|
inPtr,
|
|
&outSize,
|
|
outPtr);
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
printf("perfhit %d failed\n", enable);
|
|
}
|
|
|
|
}
|
|
|
|
WmiCloseBlock(Handle);
|
|
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
|