Add -d/--debug option for windows plugins

#fixes 8119
This commit is contained in:
Jean Flach 2015-01-12 15:53:25 +01:00
parent 98989719ee
commit c11f2d5ca2
10 changed files with 431 additions and 103 deletions

View File

@ -34,6 +34,8 @@ namespace po = boost::program_options;
using std::cout; using std::endl; using std::set; using std::cout; using std::endl; using std::set;
using std::vector; using std::wstring; using std::wcout; using std::vector; using std::wstring; using std::wcout;
static BOOL debug = FALSE;
struct drive struct drive
{ {
wstring name; wstring name;
@ -100,6 +102,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
desc.add_options() desc.add_options()
("help,h", "print usage message and exit") ("help,h", "print usage message and exit")
("version,V", "print version and exit") ("version,V", "print version and exit")
("debug,d", "Verbose/Debug output")
("warning,w", po::wvalue<wstring>(), "warning threshold") ("warning,w", po::wvalue<wstring>(), "warning threshold")
("critical,c", po::wvalue<wstring>(), "critical threshold") ("critical,c", po::wvalue<wstring>(), "critical threshold")
("path,p", po::wvalue<vector<std::wstring>>()->multitoken(), "declare explicitly which drives to check (default checks all)") ("path,p", po::wvalue<vector<std::wstring>>()->multitoken(), "declare explicitly which drives to check (default checks all)")
@ -196,11 +199,16 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
} else } else
printInfo.unit = BunitB; printInfo.unit = BunitB;
if (vm.count("debug"))
debug = TRUE;
return -1; return -1;
} }
int printOutput(printInfoStruct& printInfo, vector<drive>& vDrives) int printOutput(printInfoStruct& printInfo, vector<drive>& vDrives)
{ {
if (debug)
wcout << L"Constructing output string" << endl;
state state = OK; state state = OK;
double tCap = 0, tFree = 0; double tCap = 0, tFree = 0;
std::wstringstream perf, prePerf; std::wstringstream perf, prePerf;
@ -233,13 +241,13 @@ int printOutput(printInfoStruct& printInfo, vector<drive>& vDrives)
switch (state) { switch (state) {
case OK: case OK:
wcout << L"DISK OK " << tFree << unit << prePerf.str() << perf.str() << endl; wcout << L"DISK OK " << std::fixed << removeZero(tFree) << unit << prePerf.str() << perf.str() << endl;
break; break;
case WARNING: case WARNING:
wcout << L"DISK WARNING " << tFree << unit << prePerf.str() << perf.str() << endl; wcout << L"DISK WARNING " << std::fixed << removeZero(tFree) << unit << prePerf.str() << perf.str() << endl;
break; break;
case CRITICAL: case CRITICAL:
wcout << L"DISK CRITICAL " << tFree << unit << prePerf.str() << perf.str() << endl; wcout << L"DISK CRITICAL " << std::fixed << removeZero(tFree) << unit << prePerf.str() << perf.str() << endl;
break; break;
} }
@ -249,29 +257,45 @@ int printOutput(printInfoStruct& printInfo, vector<drive>& vDrives)
int check_drives(vector<drive>& vDrives) int check_drives(vector<drive>& vDrives)
{ {
DWORD dwResult, dwSize = 0, dwVolumePathNamesLen = MAX_PATH + 1; DWORD dwResult, dwSize = 0, dwVolumePathNamesLen = MAX_PATH + 1;
wchar_t szLogicalDrives[MAX_PATH], szVolumeName[MAX_PATH], *szVolumePathNames; wchar_t szLogicalDrives[1024], szVolumeName[MAX_PATH], *szVolumePathNames;
HANDLE hVolume; HANDLE hVolume;
wstring wsLogicalDrives; wstring wsLogicalDrives;
size_t volumeNameEnd = 0; size_t volumeNameEnd = 0;
set<wstring> sDrives; set<wstring> sDrives;
if (debug)
wcout << L"Getting logic drive string (includes network drives)" << endl;
dwResult = GetLogicalDriveStrings(MAX_PATH, szLogicalDrives); dwResult = GetLogicalDriveStrings(MAX_PATH, szLogicalDrives);
if (dwResult < 0 || dwResult > MAX_PATH) if (dwResult < 0 || dwResult > MAX_PATH)
goto die; goto die;
if (debug)
wcout << L"Splitting string into single drive names" << endl;
LPTSTR szSingleDrive = szLogicalDrives; LPTSTR szSingleDrive = szLogicalDrives;
while (*szSingleDrive) { while (*szSingleDrive) {
wstring drname = szSingleDrive; wstring drname = szSingleDrive;
sDrives.insert(drname); sDrives.insert(drname);
szSingleDrive += wcslen(szSingleDrive) + 1; szSingleDrive += wcslen(szSingleDrive) + 1;
if (debug)
wcout << "Got: " << drname << endl;
} }
if (debug)
wcout << L"Getting volume mountpoints (includes NTFS folders)" << endl
<< L"Getting first volume" << endl;
hVolume = FindFirstVolume(szVolumeName, MAX_PATH); hVolume = FindFirstVolume(szVolumeName, MAX_PATH);
if (hVolume == INVALID_HANDLE_VALUE) if (hVolume == INVALID_HANDLE_VALUE)
goto die; goto die;
if (debug)
wcout << L"Traversing through list of drives" << endl;
while (GetLastError() != ERROR_NO_MORE_FILES) { while (GetLastError() != ERROR_NO_MORE_FILES) {
if (debug)
wcout << L"Path name for " << szVolumeName << L"= \"";
volumeNameEnd = wcslen(szVolumeName) - 1; volumeNameEnd = wcslen(szVolumeName) - 1;
szVolumePathNames = reinterpret_cast<wchar_t*>(new WCHAR[dwVolumePathNamesLen]); szVolumePathNames = reinterpret_cast<wchar_t*>(new WCHAR[dwVolumePathNamesLen]);
@ -282,17 +306,25 @@ int check_drives(vector<drive>& vDrives)
szVolumePathNames = reinterpret_cast<wchar_t*>(new WCHAR[dwVolumePathNamesLen]); szVolumePathNames = reinterpret_cast<wchar_t*>(new WCHAR[dwVolumePathNamesLen]);
} }
wcout << szVolumePathNames << L"\"" << endl;
//.insert() does the dublicate checking
sDrives.insert(wstring(szVolumePathNames)); sDrives.insert(wstring(szVolumePathNames));
FindNextVolume(hVolume, szVolumeName, MAX_PATH); FindNextVolume(hVolume, szVolumeName, MAX_PATH);
} }
wcout << L"Creating vector from found volumes, removing cd drives etc.:" << endl;
for (set<wstring>::iterator it = sDrives.begin(); it != sDrives.end(); ++it) { for (set<wstring>::iterator it = sDrives.begin(); it != sDrives.end(); ++it) {
UINT type = GetDriveType(it->c_str()); UINT type = GetDriveType(it->c_str());
if (type == DRIVE_FIXED || type == DRIVE_REMOTE) { if (type == DRIVE_FIXED || type == DRIVE_REMOTE) {
if (debug)
wcout << L"\t" << *it << endl;
vDrives.push_back(drive(*it)); vDrives.push_back(drive(*it));
} }
} }
FindVolumeClose(hVolume);
delete[] reinterpret_cast<wchar_t*>(szVolumePathNames);
return -1; return -1;
die: die:
@ -306,15 +338,19 @@ int check_drives(vector<drive>& vDrives, printInfoStruct& printInfo)
{ {
wchar_t *slash = L"\\"; wchar_t *slash = L"\\";
if (debug)
wcout << L"Parsing user input drive names" << endl;
for (vector<wstring>::iterator it = printInfo.drives.begin(); for (vector<wstring>::iterator it = printInfo.drives.begin();
it != printInfo.drives.end(); ++it) { it != printInfo.drives.end(); ++it) {
if (it->at(it->length() - 1) != *slash) if (it->at(it->length() - 1) != *slash)
it->append(slash); it->append(slash);
if (std::wstring::npos == it->find(L":\\")) { if (std::wstring::npos == it->find(L":\\")) {
wcout << "A \":\" is required after the drive name of " << *it << endl; wcout << "A \":\" is required after the drive name of " << *it << endl;
return 3; return 3;
} }
if (debug)
wcout << L"Added " << *it << endl;
vDrives.push_back(drive(*it)); vDrives.push_back(drive(*it));
} }
return -1; return -1;
@ -322,13 +358,21 @@ int check_drives(vector<drive>& vDrives, printInfoStruct& printInfo)
bool getFreeAndCap(drive& drive, const Bunit& unit) bool getFreeAndCap(drive& drive, const Bunit& unit)
{ {
if (debug)
wcout << L"Getting free disk space for drive " << drive.name << endl;
ULARGE_INTEGER tempFree, tempTotal; ULARGE_INTEGER tempFree, tempTotal;
if (!GetDiskFreeSpaceEx(drive.name.c_str(), NULL, &tempTotal, &tempFree)) { if (!GetDiskFreeSpaceEx(drive.name.c_str(), NULL, &tempTotal, &tempFree)) {
return FALSE; return FALSE;
} }
if (debug)
wcout << L"\tcap: " << tempFree.QuadPart << endl;
drive.cap = round((tempTotal.QuadPart / pow(1024.0, unit))); drive.cap = round((tempTotal.QuadPart / pow(1024.0, unit)));
if (debug)
wcout << L"\tAfter converion: " << drive.cap << endl
<< L"\tfree: " << tempFree.QuadPart << endl;
drive.free = round((tempFree.QuadPart / pow(1024.0, unit))); drive.free = round((tempFree.QuadPart / pow(1024.0, unit)));
if (debug)
wcout << L"\tAfter converion: " << drive.free << endl << endl;
return TRUE; return TRUE;
} }

View File

@ -33,6 +33,8 @@ namespace po = boost::program_options;
using std::endl; using std::cout; using std::wstring; using std::endl; using std::cout; using std::wstring;
using std::wcout; using std::wcout;
static BOOL debug = FALSE;
struct printInfoStruct struct printInfoStruct
{ {
threshold warn, crit; threshold warn, crit;
@ -69,6 +71,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
desc.add_options() desc.add_options()
("help,h", "print usage message and exit") ("help,h", "print usage message and exit")
("version,V", "print version and exit") ("version,V", "print version and exit")
("debug,d", "Verbose/Debug output")
("warning,w", po::wvalue<wstring>(), "warning value (in percent)") ("warning,w", po::wvalue<wstring>(), "warning value (in percent)")
("critical,c", po::wvalue<wstring>(), "critical value (in percent)") ("critical,c", po::wvalue<wstring>(), "critical value (in percent)")
; ;
@ -156,11 +159,17 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
} }
} }
if (vm.count("debug"))
debug = TRUE;
return -1; return -1;
} }
int printOutput(printInfoStruct& printInfo) int printOutput(printInfoStruct& printInfo)
{ {
if (debug)
wcout << L"Constructing output string" << endl;
state state = OK; state state = OK;
if (printInfo.warn.rend(printInfo.load)) if (printInfo.warn.rend(printInfo.load))
@ -199,6 +208,9 @@ int check_load(printInfoStruct& printInfo)
LPCWSTR path = L"\\Processor(_Total)\\% Idle Time"; LPCWSTR path = L"\\Processor(_Total)\\% Idle Time";
if (debug)
wcout << L"Creating query and adding counter" << endl;
err = PdhOpenQuery(NULL, NULL, &phQuery); err = PdhOpenQuery(NULL, NULL, &phQuery);
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
@ -207,20 +219,39 @@ int check_load(printInfoStruct& printInfo)
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
if (debug)
wcout << L"Collecting first batch of query data" << endl;
err = PdhCollectQueryData(phQuery); err = PdhCollectQueryData(phQuery);
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
if (debug)
wcout << L"Sleep for one second" << endl;
Sleep(1000); Sleep(1000);
if (debug)
wcout << L"Collecting second batch of query data" << endl;
err = PdhCollectQueryData(phQuery); err = PdhCollectQueryData(phQuery);
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
if (debug)
wcout << L"Creating formatted counter array" << endl;
err = PdhGetFormattedCounterValue(phCounter, PDH_FMT_DOUBLE, &CounterType, &DisplayValue); err = PdhGetFormattedCounterValue(phCounter, PDH_FMT_DOUBLE, &CounterType, &DisplayValue);
if (SUCCEEDED(err)) { if (SUCCEEDED(err)) {
if (DisplayValue.CStatus == PDH_CSTATUS_VALID_DATA) if (DisplayValue.CStatus == PDH_CSTATUS_VALID_DATA) {
if (debug)
wcout << L"Recieved Value of " << DisplayValue.doubleValue << L" (idle)" << endl;
printInfo.load = 100.0 - DisplayValue.doubleValue; printInfo.load = 100.0 - DisplayValue.doubleValue;
}
if (debug)
wcout << L"Finished collection. Cleaning up and returning" << endl;
PdhCloseQuery(phQuery); PdhCloseQuery(phQuery);
return -1; return -1;
} }

View File

@ -31,6 +31,9 @@ namespace po = boost::program_options;
using std::endl; using std::vector; using std::wstring; using std::endl; using std::vector; using std::wstring;
using std::wcout; using std::cout; using std::wcout; using std::cout;
static BOOL debug = FALSE;
struct nInterface struct nInterface
{ {
wstring name; wstring name;
@ -77,6 +80,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
desc.add_options() desc.add_options()
("help,h", "print usage and exit") ("help,h", "print usage and exit")
("version,V", "print version and exit") ("version,V", "print version and exit")
("debug,d", "Verbose/Debug output")
("warning,w", po::wvalue<wstring>(), "warning value") ("warning,w", po::wvalue<wstring>(), "warning value")
("critical,c", po::wvalue<wstring>(), "critical value") ("critical,c", po::wvalue<wstring>(), "critical value")
; ;
@ -161,11 +165,17 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
} }
} }
if (vm.count("debug"))
debug = TRUE;
return -1; return -1;
} }
int printOutput(printInfoStruct& printInfo, const vector<nInterface>& vInterfaces) int printOutput(printInfoStruct& printInfo, const vector<nInterface>& vInterfaces)
{ {
if (debug)
wcout << L"Constructing output string" << endl;
long tIn = 0, tOut = 0; long tIn = 0, tOut = 0;
std::wstringstream tss, perfDataFirst; std::wstringstream tss, perfDataFirst;
state state = OK; state state = OK;
@ -209,6 +219,9 @@ int check_network(vector <nInterface>& vInterfaces)
PDH_FMT_COUNTERVALUE_ITEM *pDisplayValuesIn = NULL, *pDisplayValuesOut = NULL; PDH_FMT_COUNTERVALUE_ITEM *pDisplayValuesIn = NULL, *pDisplayValuesOut = NULL;
PDH_STATUS err; PDH_STATUS err;
if (debug)
wcout << L"Creating Query and adding counters" << endl;
err = PdhOpenQuery(NULL, NULL, &phQuery); err = PdhOpenQuery(NULL, NULL, &phQuery);
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
@ -221,16 +234,28 @@ int check_network(vector <nInterface>& vInterfaces)
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
if (debug)
wcout << L"Collecting first batch of query data" << endl;
err = PdhCollectQueryData(phQuery); err = PdhCollectQueryData(phQuery);
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
if (debug)
wcout << L"Sleep for one second" << endl;
Sleep(1000); Sleep(1000);
if (debug)
wcout << L"Collecting second batch of query data" << endl;
err = PdhCollectQueryData(phQuery); err = PdhCollectQueryData(phQuery);
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
if (debug)
wcout << L"Creating formatted counter arrays" << endl;
err = PdhGetFormattedCounterArray(phCounterIn, PDH_FMT_LONG, &dwBufferSizeIn, &dwItemCount, pDisplayValuesIn); err = PdhGetFormattedCounterArray(phCounterIn, PDH_FMT_LONG, &dwBufferSizeIn, &dwItemCount, pDisplayValuesIn);
if (err == PDH_MORE_DATA || SUCCEEDED(err)) if (err == PDH_MORE_DATA || SUCCEEDED(err))
pDisplayValuesIn = reinterpret_cast<PDH_FMT_COUNTERVALUE_ITEM*>(new BYTE[dwItemCount*dwBufferSizeIn]); pDisplayValuesIn = reinterpret_cast<PDH_FMT_COUNTERVALUE_ITEM*>(new BYTE[dwItemCount*dwBufferSizeIn]);
@ -251,16 +276,24 @@ int check_network(vector <nInterface>& vInterfaces)
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
if (debug)
wcout << L"Going over counter array" << endl;
for (DWORD i = 0; i < dwItemCount; i++) { for (DWORD i = 0; i < dwItemCount; i++) {
nInterface *iface = new nInterface(wstring(pDisplayValuesIn[i].szName)); nInterface *iface = new nInterface(wstring(pDisplayValuesIn[i].szName));
iface->BytesInSec = pDisplayValuesIn[i].FmtValue.longValue; iface->BytesInSec = pDisplayValuesIn[i].FmtValue.longValue;
iface->BytesOutSec = pDisplayValuesOut[i].FmtValue.longValue; iface->BytesOutSec = pDisplayValuesOut[i].FmtValue.longValue;
vInterfaces.push_back(*iface); vInterfaces.push_back(*iface);
if (debug)
wcout << L"Collected interface " << pDisplayValuesIn[i].szName << endl;
} }
PdhCloseQuery(phQuery); if (debug)
delete pDisplayValuesIn; wcout << L"Finished collection. Cleaning up and returning" << endl;
delete pDisplayValuesOut;
return -1; PdhCloseQuery(phQuery);
delete reinterpret_cast<PDH_FMT_COUNTERVALUE_ITEM*>(pDisplayValuesIn);
delete reinterpret_cast<PDH_FMT_COUNTERVALUE_ITEM*>(pDisplayValuesOut);
return -1;
die: die:
die(err); die(err);
if (phQuery) if (phQuery)

View File

@ -40,6 +40,8 @@ namespace po = boost::program_options;
using std::cout; using std::endl; using std::wcout; using std::cout; using std::endl; using std::wcout;
using std::wstring; using std::string; using std::wstring; using std::string;
static BOOL debug = FALSE;
struct response struct response
{ {
double avg; double avg;
@ -97,6 +99,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
desc.add_options() desc.add_options()
("help,h", "print usage message and exit") ("help,h", "print usage message and exit")
("version,V", "print version and exit") ("version,V", "print version and exit")
("debug,d", "Verbose/Debug output")
("host,H", po::wvalue<wstring>()->required(), "host ip to ping") ("host,H", po::wvalue<wstring>()->required(), "host ip to ping")
(",4", "--host is an ipv4 address (default)") (",4", "--host is an ipv4 address (default)")
(",6", "--host is an ipv6 address") (",6", "--host is an ipv6 address")
@ -222,11 +225,17 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
printInfo.host = vm["host"].as<wstring>(); printInfo.host = vm["host"].as<wstring>();
if (vm.count("debug"))
debug = TRUE;
return -1; return -1;
} }
int printOutput(printInfoStruct& printInfo, response& response) int printOutput(printInfoStruct& printInfo, response& response)
{ {
if (debug)
wcout << L"Constructing output string" << endl;
state state = OK; state state = OK;
double plp = ((double)response.dropped / printInfo.num) * 100.0; double plp = ((double)response.dropped / printInfo.num) * 100.0;
@ -273,6 +282,9 @@ int check_ping4(const printInfoStruct& pi, response& response)
LARGE_INTEGER frequency, timer1, timer2; LARGE_INTEGER frequency, timer1, timer2;
LPCWSTR term; LPCWSTR term;
if (debug)
wcout << L"Parsing ip address" << endl;
if (RtlIpv4StringToAddress(pi.host.c_str(), TRUE, &term, &ipDest4) == STATUS_INVALID_PARAMETER) { if (RtlIpv4StringToAddress(pi.host.c_str(), TRUE, &term, &ipDest4) == STATUS_INVALID_PARAMETER) {
std::wcout << pi.host << " is not a valid ip address" << std::endl; std::wcout << pi.host << " is not a valid ip address" << std::endl;
return 3; return 3;
@ -283,6 +295,9 @@ int check_ping4(const printInfoStruct& pi, response& response)
return 3; return 3;
} }
if (debug)
wcout << L"Creating Icmp File" << endl;
if ((hIcmp = IcmpCreateFile()) == INVALID_HANDLE_VALUE) if ((hIcmp = IcmpCreateFile()) == INVALID_HANDLE_VALUE)
goto die; goto die;
@ -295,20 +310,33 @@ int check_ping4(const printInfoStruct& pi, response& response)
QueryPerformanceFrequency(&frequency); QueryPerformanceFrequency(&frequency);
do { do {
QueryPerformanceCounter(&timer1); QueryPerformanceCounter(&timer1);
dwRet = IcmpSendEcho2(hIcmp, NULL, NULL, NULL, ipDest4.S_un.S_addr,
NULL, 0, NULL, repBuf, dwRepSize, pi.timeout); if (debug)
if (!dwRet) { wcout << L"Sending Icmp echo" << endl;
if (!IcmpSendEcho2(hIcmp, NULL, NULL, NULL, ipDest4.S_un.S_addr,
NULL, 0, NULL, repBuf, dwRepSize, pi.timeout)) {
response.dropped++; response.dropped++;
if (debug)
wcout << L"Dropped: Response was 0" << endl;
continue; continue;
} }
if (debug)
wcout << "Ping recieved" << endl;
PICMP_ECHO_REPLY pEchoReply = static_cast<PICMP_ECHO_REPLY>(repBuf); PICMP_ECHO_REPLY pEchoReply = static_cast<PICMP_ECHO_REPLY>(repBuf);
if (pEchoReply->Status != IP_SUCCESS) { if (pEchoReply->Status != IP_SUCCESS) {
response.dropped++; response.dropped++;
if (debug)
wcout << L"Dropped: echo reply status " << pEchoReply->Status << endl;
continue; continue;
} }
if (debug)
wcout << L"Recorded rtt of " << pEchoReply->RoundTripTime << endl;
rtt += pEchoReply->RoundTripTime; rtt += pEchoReply->RoundTripTime;
if (response.pMin == 0 || pEchoReply->RoundTripTime < response.pMin) if (response.pMin == 0 || pEchoReply->RoundTripTime < response.pMin)
response.pMin = pEchoReply->RoundTripTime; response.pMin = pEchoReply->RoundTripTime;
@ -320,6 +348,8 @@ int check_ping4(const printInfoStruct& pi, response& response)
Sleep(pi.timeout - ((timer2.QuadPart - timer1.QuadPart) * 1000 / frequency.QuadPart)); Sleep(pi.timeout - ((timer2.QuadPart - timer1.QuadPart) * 1000 / frequency.QuadPart));
} while (--num); } while (--num);
if (debug)
wcout << L"All pings sent. Cleaning up and returning" << endl;
IcmpCloseHandle(hIcmp); IcmpCloseHandle(hIcmp);
delete reinterpret_cast<VOID *>(repBuf); delete reinterpret_cast<VOID *>(repBuf);
@ -350,6 +380,9 @@ int check_ping6(const printInfoStruct& pi, response& response)
int num = pi.num; int num = pi.num;
UINT rtt = 0; UINT rtt = 0;
if (debug)
wcout << L"Parsing ip address" << endl;
if (RtlIpv6StringToAddressEx(pi.host.c_str(), &ipDest6.sin6_addr, &ipDest6.sin6_scope_id, &ipDest6.sin6_port)) { if (RtlIpv6StringToAddressEx(pi.host.c_str(), &ipDest6.sin6_addr, &ipDest6.sin6_scope_id, &ipDest6.sin6_port)) {
std::wcout << pi.host << " is not a valid ipv6 address" << std::endl; std::wcout << pi.host << " is not a valid ipv6 address" << std::endl;
return 3; return 3;
@ -362,6 +395,9 @@ int check_ping6(const printInfoStruct& pi, response& response)
ipSource6.sin6_flowinfo = 0; ipSource6.sin6_flowinfo = 0;
ipSource6.sin6_port = 0; ipSource6.sin6_port = 0;
if (debug)
wcout << L"Creating Icmp File" << endl;
HANDLE hIcmp = Icmp6CreateFile(); HANDLE hIcmp = Icmp6CreateFile();
if (hIcmp == INVALID_HANDLE_VALUE) { if (hIcmp == INVALID_HANDLE_VALUE) {
goto die; goto die;
@ -370,32 +406,50 @@ int check_ping6(const printInfoStruct& pi, response& response)
QueryPerformanceFrequency(&frequency); QueryPerformanceFrequency(&frequency);
do { do {
QueryPerformanceCounter(&timer1); QueryPerformanceCounter(&timer1);
if (debug)
wcout << L"Sending Icmp echo" << endl;
if (!Icmp6SendEcho2(hIcmp, NULL, NULL, NULL, &ipSource6, &ipDest6, if (!Icmp6SendEcho2(hIcmp, NULL, NULL, NULL, &ipSource6, &ipDest6,
NULL, 0, &ipInfo, repBuf, dwRepSize, pi.timeout)) { NULL, 0, &ipInfo, repBuf, dwRepSize, pi.timeout)) {
response.dropped++; response.dropped++;
if (debug)
wcout << L"Dropped: Response was 0" << endl;
continue; continue;
} }
if (debug)
wcout << "Ping recieved" << endl;
Icmp6ParseReplies(repBuf, dwRepSize); Icmp6ParseReplies(repBuf, dwRepSize);
ICMPV6_ECHO_REPLY *echoReply = static_cast<ICMPV6_ECHO_REPLY *>(repBuf); ICMPV6_ECHO_REPLY *pEchoReply = static_cast<ICMPV6_ECHO_REPLY *>(repBuf);
if (echoReply->Status != IP_SUCCESS) { if (pEchoReply->Status != IP_SUCCESS) {
response.dropped++; response.dropped++;
if (debug)
wcout << L"Dropped: echo reply status " << pEchoReply->Status << endl;
continue; continue;
} }
rtt += echoReply->RoundTripTime; rtt += pEchoReply->RoundTripTime;
if (response.pMin == 0 || echoReply->RoundTripTime < response.pMin)
response.pMin = echoReply->RoundTripTime; if (debug)
else if (echoReply->RoundTripTime > response.pMax) wcout << L"Recorded rtt of " << pEchoReply->RoundTripTime << endl;
response.pMax = echoReply->RoundTripTime;
if (response.pMin == 0 || pEchoReply->RoundTripTime < response.pMin)
response.pMin = pEchoReply->RoundTripTime;
else if (pEchoReply->RoundTripTime > response.pMax)
response.pMax = pEchoReply->RoundTripTime;
QueryPerformanceCounter(&timer2); QueryPerformanceCounter(&timer2);
if (((timer2.QuadPart - timer1.QuadPart) * 1000 / frequency.QuadPart) < pi.timeout) if (((timer2.QuadPart - timer1.QuadPart) * 1000 / frequency.QuadPart) < pi.timeout)
Sleep(pi.timeout - ((timer2.QuadPart - timer1.QuadPart) * 1000 / frequency.QuadPart)); Sleep(pi.timeout - ((timer2.QuadPart - timer1.QuadPart) * 1000 / frequency.QuadPart));
} while (--num); } while (--num);
if (debug)
wcout << L"All pings sent. Cleaning up and returning" << endl;
IcmpCloseHandle(hIcmp); IcmpCloseHandle(hIcmp);
delete reinterpret_cast<VOID *>(repBuf); delete reinterpret_cast<VOID *>(repBuf);
response.avg = ((double)rtt / pi.num); response.avg = ((double)rtt / pi.num);

View File

@ -32,6 +32,8 @@ namespace po = boost::program_options;
using std::endl; using std::wstring; using std::wcout; using std::endl; using std::wstring; using std::wcout;
using std::cout; using std::cout;
static BOOL debug = FALSE;
struct printInfoStruct struct printInfoStruct
{ {
threshold warn, crit; threshold warn, crit;
@ -59,38 +61,6 @@ int wmain(int argc, wchar_t **argv)
return printOutput(countProcs(), printInfo); return printOutput(countProcs(), printInfo);
} }
int printOutput(const int numProcs, printInfoStruct& printInfo)
{
state state = OK;
if (printInfo.warn.rend(numProcs))
state = WARNING;
if (printInfo.crit.rend(numProcs))
state = CRITICAL;
wstring user = L"";
if (!printInfo.user.empty())
user.append(L" processes of user ").append(printInfo.user);
switch (state) {
case OK:
wcout << L"PROCS OK " << numProcs << user << L" | procs=" << numProcs << L";"
<< printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << endl;
break;
case WARNING:
wcout << L"PROCS WARNING " << numProcs << user << L" | procs=" << numProcs << L";"
<< printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << endl;
break;
case CRITICAL:
wcout << L"PROCS CRITICAL " << numProcs << user << L" | procs=" << numProcs << L";"
<< printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << endl;
break;
}
return state;
}
int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct& printInfo) int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct& printInfo)
{ {
wchar_t namePath[MAX_PATH]; wchar_t namePath[MAX_PATH];
@ -102,9 +72,10 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
desc.add_options() desc.add_options()
("help,h", "print help message and exit") ("help,h", "print help message and exit")
("version,V", "print version and exit") ("version,V", "print version and exit")
("debug,d", "Verbose/Debug output")
("user,u", po::wvalue<wstring>(), "count only processes by user [arg]")
("warning,w", po::wvalue<wstring>(), "warning threshold") ("warning,w", po::wvalue<wstring>(), "warning threshold")
("critical,c", po::wvalue<wstring>(), "critical threshold") ("critical,c", po::wvalue<wstring>(), "critical threshold")
("user,u", po::wvalue<wstring>(), "count only processes by user [arg]")
; ;
po::basic_command_line_parser<wchar_t> parser(ac, av); po::basic_command_line_parser<wchar_t> parser(ac, av);
@ -132,7 +103,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
cout << desc; cout << desc;
wprintf( wprintf(
L"\nIt will then output a string looking something like this:\n\n" L"\nIt will then output a string looking something like this:\n\n"
L"\tPROCS WARNING 67|load=67;50;90;0\n\n" L"\tPROCS WARNING 67 | load=67;50;90;0\n\n"
L"\"PROCS\" being the type of the check, \"WARNING\" the returned status\n" L"\"PROCS\" being the type of the check, \"WARNING\" the returned status\n"
L"and \"67\" is the returned value.\n" L"and \"67\" is the returned value.\n"
L"The performance data is found behind the \"|\", in order:\n" L"The performance data is found behind the \"|\", in order:\n"
@ -191,20 +162,67 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
if (vm.count("user")) if (vm.count("user"))
printInfo.user = vm["user"].as<wstring>(); printInfo.user = vm["user"].as<wstring>();
if (vm.count("debug"))
debug = TRUE;
return -1; return -1;
} }
int printOutput(const int numProcs, printInfoStruct& printInfo)
{
if (debug)
wcout << L"Constructing output string" << endl;
state state = OK;
if (printInfo.warn.rend(numProcs))
state = WARNING;
if (printInfo.crit.rend(numProcs))
state = CRITICAL;
wstring user = L"";
if (!printInfo.user.empty())
user.append(L" processes of user ").append(printInfo.user);
switch (state) {
case OK:
wcout << L"PROCS OK " << numProcs << user << L" | procs=" << numProcs << L";"
<< printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << endl;
break;
case WARNING:
wcout << L"PROCS WARNING " << numProcs << user << L" | procs=" << numProcs << L";"
<< printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << endl;
break;
case CRITICAL:
wcout << L"PROCS CRITICAL " << numProcs << user << L" | procs=" << numProcs << L";"
<< printInfo.warn.pString() << L";" << printInfo.crit.pString() << L";0;" << endl;
break;
}
return state;
}
int countProcs() int countProcs()
{ {
if (debug)
wcout << L"Counting all processes" << endl;
HANDLE hProcessSnap; HANDLE hProcessSnap;
PROCESSENTRY32 pe32; PROCESSENTRY32 pe32;
if (debug)
wcout << L"Creating snapshot" << endl;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) if (hProcessSnap == INVALID_HANDLE_VALUE)
return -1; return -1;
pe32.dwSize = sizeof(PROCESSENTRY32); pe32.dwSize = sizeof(PROCESSENTRY32);
if (debug)
wcout << L"Grabbing first proccess" << endl;
if (!Process32First(hProcessSnap, &pe32)) { if (!Process32First(hProcessSnap, &pe32)) {
CloseHandle(hProcessSnap); CloseHandle(hProcessSnap);
return -1; return -1;
@ -212,16 +230,25 @@ int countProcs()
int numProcs = 0; int numProcs = 0;
if (debug)
wcout << L"Counting processes..." << endl;
do { do {
++numProcs; ++numProcs;
} while (Process32Next(hProcessSnap, &pe32)); } while (Process32Next(hProcessSnap, &pe32));
if (debug)
wcout << L"Found " << numProcs << L" processes. Cleaning up udn returning" << endl;
CloseHandle(hProcessSnap); CloseHandle(hProcessSnap);
return numProcs; return numProcs;
} }
int countProcs(const wstring user) int countProcs(const wstring user)
{ {
if (debug)
wcout << L"Counting all processes of user" << user << endl;
const wchar_t *wuser = user.c_str(); const wchar_t *wuser = user.c_str();
int numProcs = 0; int numProcs = 0;
@ -232,16 +259,28 @@ int countProcs(const wstring user)
SID_NAME_USE sidNameUse; SID_NAME_USE sidNameUse;
LPWSTR AcctName, DomainName; LPWSTR AcctName, DomainName;
if (debug)
wcout << L"Creating snapshot" << endl;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) if (hProcessSnap == INVALID_HANDLE_VALUE)
goto die; goto die;
pe32.dwSize = sizeof(PROCESSENTRY32); pe32.dwSize = sizeof(PROCESSENTRY32);
if (debug)
wcout << L"Grabbing first proccess" << endl;
if (!Process32First(hProcessSnap, &pe32)) if (!Process32First(hProcessSnap, &pe32))
goto die; goto die;
if (debug)
wcout << L"Counting processes..." << endl;
do { do {
if (debug)
wcout << L"Getting process token" << endl;
//get ProcessToken //get ProcessToken
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID); hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
@ -257,8 +296,14 @@ int countProcs(const wstring user)
pSIDTokenUser = reinterpret_cast<PTOKEN_USER>(new BYTE[dwReturnLength]); pSIDTokenUser = reinterpret_cast<PTOKEN_USER>(new BYTE[dwReturnLength]);
memset(pSIDTokenUser, 0, dwReturnLength); memset(pSIDTokenUser, 0, dwReturnLength);
if (!pSIDTokenUser) if (!pSIDTokenUser) {
if (debug)
wcout << L"Could not recieve token, skiping" << endl;
continue; continue;
}
if (debug)
wcout << L"Recieved token, saving information" << endl;
//write Info in pSIDTokenUser //write Info in pSIDTokenUser
if (!GetTokenInformation(hToken, TokenUser, pSIDTokenUser, dwReturnLength, NULL)) if (!GetTokenInformation(hToken, TokenUser, pSIDTokenUser, dwReturnLength, NULL))
@ -268,6 +313,10 @@ int countProcs(const wstring user)
DomainName = NULL; DomainName = NULL;
dwAcctName = 1; dwAcctName = 1;
dwDomainName = 1; dwDomainName = 1;
if (debug)
wcout << L"Looking up SID" << endl;
//get dwAcctName and dwDomainName size //get dwAcctName and dwDomainName size
if (!LookupAccountSid(NULL, pSIDTokenUser->User.Sid, AcctName, if (!LookupAccountSid(NULL, pSIDTokenUser->User.Sid, AcctName,
(LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &sidNameUse) (LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &sidNameUse)
@ -284,8 +333,13 @@ int countProcs(const wstring user)
(LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &sidNameUse)) (LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &sidNameUse))
continue; continue;
if (!wcscmp(AcctName, wuser)) if (debug)
wcout << L"Comparing " << AcctName << L" to " << wuser << endl;
if (!wcscmp(AcctName, wuser)) {
++numProcs; ++numProcs;
if (debug)
wcout << L"Is process of " << wuser << L" (" << numProcs << L")" << endl;
}
delete[] reinterpret_cast<LPWSTR>(AcctName); delete[] reinterpret_cast<LPWSTR>(AcctName);
delete[] reinterpret_cast<LPWSTR>(DomainName); delete[] reinterpret_cast<LPWSTR>(DomainName);

View File

@ -31,6 +31,8 @@ namespace po = boost::program_options;
using std::wcout; using std::endl; using std::wcout; using std::endl;
using std::cout; using std::wstring; using std::cout; using std::wstring;
static BOOL debug;
struct printInfoStruct struct printInfoStruct
{ {
bool warn; bool warn;
@ -69,6 +71,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
desc.add_options() desc.add_options()
("help,h", "print help message and exit") ("help,h", "print help message and exit")
("version,V", "print version and exit") ("version,V", "print version and exit")
("debug,d", "Verbose/Debug output")
("service,s", po::wvalue<wstring>(), "service to check (required)") ("service,s", po::wvalue<wstring>(), "service to check (required)")
("warn,w", "return warning (1) instead of critical (2),\n when service is not running") ("warn,w", "return warning (1) instead of critical (2),\n when service is not running")
; ;
@ -132,12 +135,18 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
printInfo.warn = true; printInfo.warn = true;
printInfo.service = vm["service"].as<wstring>(); printInfo.service = vm["service"].as<wstring>();
if (vm.count("debug"))
debug = TRUE;
return -1; return -1;
} }
int printOutput(const printInfoStruct& printInfo) int printOutput(const printInfoStruct& printInfo)
{ {
if (debug)
wcout << L"Constructing output string" << endl;
wstring perf; wstring perf;
state state = OK; state state = OK;
@ -166,6 +175,9 @@ int printOutput(const printInfoStruct& printInfo)
int ServiceStatus(const printInfoStruct& printInfo) int ServiceStatus(const printInfoStruct& printInfo)
{ {
if (debug)
wcout << L"Opening SC Manager" << endl;
SC_HANDLE service_api = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); SC_HANDLE service_api = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
if (service_api == NULL) if (service_api == NULL)
goto die; goto die;
@ -174,6 +186,9 @@ int ServiceStatus(const printInfoStruct& printInfo)
DWORD cbBufSize = 0; DWORD cbBufSize = 0;
DWORD pcbBytesNeeded = NULL, ServicesReturned = NULL, ResumeHandle = NULL; DWORD pcbBytesNeeded = NULL, ServicesReturned = NULL, ResumeHandle = NULL;
if (debug)
wcout << L"Creating service info structure" << endl;
if (!EnumServicesStatusEx(service_api, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, if (!EnumServicesStatusEx(service_api, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL,
lpServices, cbBufSize, &pcbBytesNeeded, &ServicesReturned, &ResumeHandle, NULL) lpServices, cbBufSize, &pcbBytesNeeded, &ServicesReturned, &ResumeHandle, NULL)
&& GetLastError() != ERROR_MORE_DATA) && GetLastError() != ERROR_MORE_DATA)
@ -188,16 +203,24 @@ int ServiceStatus(const printInfoStruct& printInfo)
LPENUM_SERVICE_STATUS_PROCESS pInfo = (LPENUM_SERVICE_STATUS_PROCESS)lpServices; LPENUM_SERVICE_STATUS_PROCESS pInfo = (LPENUM_SERVICE_STATUS_PROCESS)lpServices;
if (debug)
wcout << L"Traversing services" << endl;
for (DWORD i = 0; i < ServicesReturned; i++) { for (DWORD i = 0; i < ServicesReturned; i++) {
if (debug)
wcout << L"Comparing " << pInfo[i].lpServiceName << L" to " << printInfo.service << endl;
if (!wcscmp(printInfo.service.c_str(), pInfo[i].lpServiceName)) { if (!wcscmp(printInfo.service.c_str(), pInfo[i].lpServiceName)) {
if (debug)
wcout << L"Service " << pInfo[i].lpServiceName << L" = " << printInfo.service << ". Returning" << endl;
int state = pInfo[i].ServiceStatusProcess.dwCurrentState; int state = pInfo[i].ServiceStatusProcess.dwCurrentState;
delete lpServices; delete lpServices;
return state; return state;
} }
} }
return 0;
delete[] reinterpret_cast<LPBYTE>(lpServices); delete[] reinterpret_cast<LPBYTE>(lpServices);
return -1; return 0;
die: die:
die(); die();

View File

@ -31,6 +31,8 @@ namespace po = boost::program_options;
using std::endl; using std::wcout; using std::wstring; using std::endl; using std::wcout; using std::wstring;
using std::cout; using std::cout;
static BOOL debug = FALSE;
struct printInfoStruct struct printInfoStruct
{ {
threshold warn, crit; threshold warn, crit;
@ -68,6 +70,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
desc.add_options() desc.add_options()
("help,h", "print help message and exit") ("help,h", "print help message and exit")
("version,V", "print version and exit") ("version,V", "print version and exit")
("debug,d", "Verbose/Debug output")
("warning,w", po::wvalue<wstring>(), "warning threshold") ("warning,w", po::wvalue<wstring>(), "warning threshold")
("critical,c", po::wvalue<wstring>(), "critical threshold") ("critical,c", po::wvalue<wstring>(), "critical threshold")
; ;
@ -141,6 +144,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
return 3; return 3;
} }
} }
if (vm.count("critical")) { if (vm.count("critical")) {
try { try {
printInfo.crit = threshold(vm["critical"].as<wstring>()); printInfo.crit = threshold(vm["critical"].as<wstring>());
@ -150,11 +154,17 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
} }
} }
if (vm.count("debug"))
debug = TRUE;
return -1; return -1;
} }
int printOutput(printInfoStruct& printInfo) int printOutput(printInfoStruct& printInfo)
{ {
if (debug)
wcout << L"Constructing output string" << endl;
state state = OK; state state = OK;
if (printInfo.warn.rend(printInfo.swap)) if (printInfo.warn.rend(printInfo.swap))
@ -192,18 +202,30 @@ int check_swap(printInfoStruct& printInfo)
LPCWSTR path = L"\\Paging File(*)\\% Usage"; LPCWSTR path = L"\\Paging File(*)\\% Usage";
if (debug)
wcout << L"Opening querry handle" << endl;
err = PdhOpenQuery(NULL, NULL, &phQuery); err = PdhOpenQuery(NULL, NULL, &phQuery);
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
if (debug)
wcout << L"Adding counter" << endl;
err = PdhAddEnglishCounter(phQuery, path, NULL, &phCounter); err = PdhAddEnglishCounter(phQuery, path, NULL, &phCounter);
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
if (debug)
wcout << L"Collecting querry data" << endl;
err = PdhCollectQueryData(phQuery); err = PdhCollectQueryData(phQuery);
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
if (debug)
wcout << L"Formatting counter data" << endl;
err = PdhGetFormattedCounterValue(phCounter, PDH_FMT_DOUBLE, &CounterType, &DisplayValue); err = PdhGetFormattedCounterValue(phCounter, PDH_FMT_DOUBLE, &CounterType, &DisplayValue);
if (SUCCEEDED(err)) { if (SUCCEEDED(err)) {
printInfo.swap = DisplayValue.doubleValue; printInfo.swap = DisplayValue.doubleValue;

View File

@ -35,6 +35,8 @@ namespace po = boost::program_options;
using std::wcout; using std::endl; using std::wcout; using std::endl;
using std::wstring; using std::cout; using std::wstring; using std::cout;
static BOOL debug = FALSE;
struct printInfoStruct struct printInfoStruct
{ {
BOOL warn, crit; BOOL warn, crit;
@ -46,10 +48,10 @@ static int parseArguments(int, wchar_t **, po::variables_map&, printInfoStruct&)
static int printOutput(const printInfoStruct&); static int printOutput(const printInfoStruct&);
static int check_update(printInfoStruct&); static int check_update(printInfoStruct&);
int main(int argc, wchar_t **argv) int wmain(int argc, wchar_t **argv)
{ {
po::variables_map vm;
printInfoStruct printInfo = { FALSE, FALSE, 0, FALSE, FALSE, FALSE }; printInfoStruct printInfo = { FALSE, FALSE, 0, FALSE, FALSE, FALSE };
po::variables_map vm;
int ret = parseArguments(argc, argv, vm, printInfo); int ret = parseArguments(argc, argv, vm, printInfo);
if (ret != -1) if (ret != -1)
@ -62,35 +64,6 @@ int main(int argc, wchar_t **argv)
return printOutput(printInfo); return printOutput(printInfo);
} }
int printOutput(const printInfoStruct& printInfo)
{
state state = OK;
wstring output = L"UPDATE ";
if (printInfo.important)
state = WARNING;
if (printInfo.reboot)
state = CRITICAL;
switch (state) {
case OK:
output.append(L"OK ");
break;
case WARNING:
output.append(L"WARNING ");
break;
case CRITICAL:
output.append(L"CRITICAL ");
break;
}
wcout << output << printInfo.numUpdates << L" | update=" << printInfo.numUpdates << L";"
<< printInfo.warn << L";" << printInfo.crit << L";0;" << endl;
return state;
}
int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct& printInfo) int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct& printInfo)
{ {
wchar_t namePath[MAX_PATH]; wchar_t namePath[MAX_PATH];
@ -102,9 +75,10 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
desc.add_options() desc.add_options()
("help,h", "print help message and exit") ("help,h", "print help message and exit")
("version,V", "print version and exit") ("version,V", "print version and exit")
("debug,d", "Verbose/Debug output")
("warning,w", "warn if there are important updates available") ("warning,w", "warn if there are important updates available")
("critical,c", "critical if there are important updates that require a reboot") ("critical,c", "critical if there are important updates that require a reboot")
("possible-reboot", "treat \"update may need to reboot\" as \"update needs to reboot\"") ("possible-reboot", "treat \"update may need reboot\" as \"update needs reboot\"")
; ;
po::basic_command_line_parser<wchar_t> parser(ac, av); po::basic_command_line_parser<wchar_t> parser(ac, av);
@ -132,7 +106,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
cout << desc; cout << desc;
wprintf( wprintf(
L"\nAfter some time, it will then output a string like this one:\n\n" L"\nAfter some time, it will then output a string like this one:\n\n"
L"\tUPDATE WARNING 8|updates=8;1;1;0\n\n" L"\tUPDATE WARNING 8 | updates=8;1;1;0\n\n"
L"\"UPDATE\" being the type of the check, \"WARNING\" the returned status\n" L"\"UPDATE\" being the type of the check, \"WARNING\" the returned status\n"
L"and \"8\" is the number of important updates updates.\n" L"and \"8\" is the number of important updates updates.\n"
L"The performance data is found behind the \"|\", in order:\n" L"The performance data is found behind the \"|\", in order:\n"
@ -170,18 +144,56 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
if (vm.count("possible-reboot")) if (vm.count("possible-reboot"))
printInfo.careForCanRequest = TRUE; printInfo.careForCanRequest = TRUE;
if (vm.count("debug"))
debug = TRUE;
return -1; return -1;
} }
int printOutput(const printInfoStruct& printInfo)
{
if (debug)
wcout << L"Constructing output string" << endl;
state state = OK;
wstring output = L"UPDATE ";
if (printInfo.important)
state = WARNING;
if (printInfo.reboot)
state = CRITICAL;
switch (state) {
case OK:
output.append(L"OK ");
break;
case WARNING:
output.append(L"WARNING ");
break;
case CRITICAL:
output.append(L"CRITICAL ");
break;
}
wcout << output << printInfo.numUpdates << L" | update=" << printInfo.numUpdates << L";"
<< printInfo.warn << L";" << printInfo.crit << L";0;" << endl;
return state;
}
int check_update(printInfoStruct& printInfo) int check_update(printInfoStruct& printInfo)
{ {
if (debug)
wcout << "Initializing COM library" << endl;
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
ISearchResult *pResult; ISearchResult *pResult;
IUpdateSession *pSession; IUpdateSession *pSession;
IUpdateSearcher *pSearcher; IUpdateSearcher *pSearcher;
HRESULT err; HRESULT err;
if (debug)
wcout << "Creating UpdateSession and UpdateSearcher" << endl;
CoCreateInstance(CLSID_UpdateSession, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&pSession); CoCreateInstance(CLSID_UpdateSession, NULL, CLSCTX_INPROC_SERVER, IID_IUpdateSession, (LPVOID*)&pSession);
pSession->CreateUpdateSearcher(&pSearcher); pSession->CreateUpdateSearcher(&pSearcher);
@ -196,6 +208,9 @@ int check_update(printInfoStruct& printInfo)
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa386526%28v=vs.85%29.aspx // http://msdn.microsoft.com/en-us/library/windows/desktop/aa386526%28v=vs.85%29.aspx
// http://msdn.microsoft.com/en-us/library/ff357803%28v=vs.85%29.aspx // http://msdn.microsoft.com/en-us/library/ff357803%28v=vs.85%29.aspx
if (debug)
wcout << L"Querrying updates from server" << endl;
err = pSearcher->Search(criteria, &pResult); err = pSearcher->Search(criteria, &pResult);
if (!SUCCEEDED(err)) if (!SUCCEEDED(err))
goto die; goto die;
@ -212,30 +227,40 @@ int check_update(printInfoStruct& printInfo)
return -1; return -1;
printInfo.numUpdates = updateSize; printInfo.numUpdates = updateSize;
printInfo.important = printInfo.warn; // printInfo.important = printInfo.warn;
if (!printInfo.crit)
return -1;
IInstallationBehavior *pIbehav; IInstallationBehavior *pIbehav;
InstallationRebootBehavior updateReboot; InstallationRebootBehavior updateReboot;
for (LONG i = 0; i < updateSize; i++) { for (LONG i = 0; i < updateSize; i++) {
pCollection->get_Item(i, &pUpdate); pCollection->get_Item(i, &pUpdate);
if (debug) {
wcout << L"Checking reboot behaviour of update number " << i << endl;
}
pUpdate->get_InstallationBehavior(&pIbehav); pUpdate->get_InstallationBehavior(&pIbehav);
pIbehav->get_RebootBehavior(&updateReboot); pIbehav->get_RebootBehavior(&updateReboot);
if (updateReboot == irbAlwaysRequiresReboot) { if (updateReboot == irbAlwaysRequiresReboot) {
printInfo.reboot = TRUE; printInfo.reboot = TRUE;
if (debug)
wcout << L"It requires reboot" << endl;
continue; continue;
} }
if (printInfo.careForCanRequest && updateReboot == irbCanRequestReboot) if (printInfo.careForCanRequest && updateReboot == irbCanRequestReboot)
if (debug)
wcout << L"It requires reboot" << endl;
printInfo.reboot = TRUE; printInfo.reboot = TRUE;
} }
if (debug)
wcout << L"Cleaning up and returning" << endl;
SysFreeString(criteria);
CoUninitialize();
return 0; return 0;
die: die:
die(err); die(err);
CoUninitialize();
if (criteria) if (criteria)
SysFreeString(criteria); SysFreeString(criteria);
return 3; return 3;

View File

@ -32,6 +32,8 @@ namespace po = boost::program_options;
using std::cout; using std::endl; using std::cout; using std::endl;
using std::wcout; using std::wstring; using std::wcout; using std::wstring;
static BOOL debug;
struct printInfoStruct struct printInfoStruct
{ {
threshold warn, crit; threshold warn, crit;
@ -70,6 +72,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
("help,h", "print help message and exit") ("help,h", "print help message and exit")
("version,V", "print version and exit") ("version,V", "print version and exit")
("warning,w", po::wvalue<wstring>(), "warning threshold (Uses -unit)") ("warning,w", po::wvalue<wstring>(), "warning threshold (Uses -unit)")
("debug,d", "Verbose/Debug output")
("critical,c", po::wvalue<wstring>(), "critical threshold (Uses -unit)") ("critical,c", po::wvalue<wstring>(), "critical threshold (Uses -unit)")
("unit,u", po::wvalue<wstring>(), "desired unit of output\nh\t- hours\nm\t- minutes\ns\t- seconds (default)\nms\t- milliseconds") ("unit,u", po::wvalue<wstring>(), "desired unit of output\nh\t- hours\nm\t- minutes\ns\t- seconds (default)\nms\t- milliseconds")
; ;
@ -164,12 +167,18 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
} wcout << L"Unknown unit type " << vm["unit"].as<wstring>() << endl; } wcout << L"Unknown unit type " << vm["unit"].as<wstring>() << endl;
} else } else
printInfo.unit = TunitS; printInfo.unit = TunitS;
if (vm.count("debug"))
debug = TRUE;
return -1; return -1;
} }
static int printOutput(printInfoStruct& printInfo) static int printOutput(printInfoStruct& printInfo)
{ {
if (debug)
wcout << L"Constructing output string" << endl;
state state = OK; state state = OK;
if (printInfo.warn.rend(printInfo.time)) if (printInfo.warn.rend(printInfo.time))
@ -200,8 +209,14 @@ static int printOutput(printInfoStruct& printInfo)
void getUptime(printInfoStruct& printInfo) void getUptime(printInfoStruct& printInfo)
{ {
if (debug)
wcout << L"Getting uptime in milliseconds" << endl;
boost::chrono::milliseconds uptime = boost::chrono::milliseconds(GetTickCount64()); boost::chrono::milliseconds uptime = boost::chrono::milliseconds(GetTickCount64());
if (debug)
wcout << L"Converting requested unit (default: seconds)" << endl;
switch (printInfo.unit) { switch (printInfo.unit) {
case TunitH: case TunitH:
printInfo.time = boost::chrono::duration_cast<boost::chrono::hours>(uptime).count(); printInfo.time = boost::chrono::duration_cast<boost::chrono::hours>(uptime).count();
@ -216,5 +231,4 @@ void getUptime(printInfoStruct& printInfo)
printInfo.time = uptime.count(); printInfo.time = uptime.count();
break; break;
} }
} }

View File

@ -32,6 +32,8 @@ namespace po = boost::program_options;
using std::endl; using std::wcout; using std::endl; using std::wcout;
using std::cout; using std::wstring; using std::cout; using std::wstring;
static BOOL debug = FALSE;
struct printInfoStruct struct printInfoStruct
{ {
threshold warn, crit; threshold warn, crit;
@ -69,6 +71,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
desc.add_options() desc.add_options()
("help,h", "print help message and exit") ("help,h", "print help message and exit")
("version,V", "print version and exit") ("version,V", "print version and exit")
("debug,d", "Verbose/Debug output")
("warning,w", po::wvalue<wstring>(), "warning threshold") ("warning,w", po::wvalue<wstring>(), "warning threshold")
("critical,c", po::wvalue<wstring>(), "critical threshold") ("critical,c", po::wvalue<wstring>(), "critical threshold")
; ;
@ -98,7 +101,7 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
cout << desc; cout << desc;
wprintf( wprintf(
L"\nIt will then output a string looking something like this:\n\n" L"\nIt will then output a string looking something like this:\n\n"
L"\tUSERS WARNING 48|users=48;10;50;0\n\n" L"\tUSERS WARNING 48 | users=48;10;50;0\n\n"
L"\"USERS\" being the type of the check, \"WARNING\" the returned status\n" L"\"USERS\" being the type of the check, \"WARNING\" the returned status\n"
L"and \"48\" is the returned value.\n" L"and \"48\" is the returned value.\n"
L"The performance data is found behind the \"|\", in order:\n" L"The performance data is found behind the \"|\", in order:\n"
@ -151,11 +154,17 @@ int parseArguments(int ac, wchar_t **av, po::variables_map& vm, printInfoStruct&
} }
} }
if (vm.count("debug"))
debug = TRUE;
return -1; return -1;
} }
int printOutput(printInfoStruct& printInfo) int printOutput(printInfoStruct& printInfo)
{ {
if (debug)
wcout << L"Constructing output string" << endl;
state state = OK; state state = OK;
if (printInfo.warn.rend(printInfo.users)) if (printInfo.warn.rend(printInfo.users))
@ -189,33 +198,52 @@ int check_users(printInfoStruct& printInfo)
DWORD count; DWORD count;
DWORD index; DWORD index;
if (debug)
wcout << L"Trying to enumerate terminal sessions" << endl;
if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &count)) { if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &count)) {
wcout << L"Failed to enumerate terminal sessions" << endl; wcout << L"Failed to enumerate terminal sessions" << endl;
die();
if (pSessionInfo) if (pSessionInfo)
WTSFreeMemory(pSessionInfo); WTSFreeMemory(pSessionInfo);
return 3; return 3;
} }
if (debug)
wcout << L"Got all sessions (" << count << L"), traversing and counting active ones" << endl;
for (index = 0; index < count; index++) { for (index = 0; index < count; index++) {
LPWSTR name; LPWSTR name;
DWORD size; DWORD size;
int len; int len;
if (debug)
wcout << L"Querrying session number " << index << endl;
if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, pSessionInfo[index].SessionId, if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, pSessionInfo[index].SessionId,
WTSUserName, &name, &size)) WTSUserName, &name, &size))
continue; continue;
if (debug)
wcout << L"Found \"" << name << L"\". Checking whether it's a real session" << endl;
len = lstrlenW(name); len = lstrlenW(name);
WTSFreeMemory(name); WTSFreeMemory(name);
if (!len) if (!len)
continue; continue;
if (pSessionInfo[index].State == WTSActive || pSessionInfo[index].State == WTSDisconnected) if (pSessionInfo[index].State == WTSActive || pSessionInfo[index].State == WTSDisconnected) {
users++; users++;
if (debug)
wcout << L"\"" << name << L"\" is a real session, counting it. Now " << users << endl;
}
} }
if (debug)
wcout << "Finished coutning user sessions (" << users << "). Freeing memory and returning" << endl;
WTSFreeMemory(pSessionInfo); WTSFreeMemory(pSessionInfo);
printInfo.users = users; printInfo.users = users;
return -1; return -1;