Skip to content

Instantly share code, notes, and snippets.

@asquigglytwist
Last active April 25, 2020 09:52
Show Gist options
  • Save asquigglytwist/545f6a87507154ebb030225d474647dc to your computer and use it in GitHub Desktop.
Save asquigglytwist/545f6a87507154ebb030225d474647dc to your computer and use it in GitHub Desktop.
Perform PreFlight Checks (like Min OS, Min RAM, Min FreeDiskSpace) on Windows - typically performed before any business logic.
#pragma once
#ifndef PREFLIGHTCHECK_HPP
#define PREFLIGHTCHECK_HPP
/* References for this implementation:
https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex
https://stackoverflow.com/questions/20119643/stringizing-operator-in-c-c
https://stackoverflow.com/questions/46794133/how-to-perform-arthemetic-with-ularge-integer
*/
#include "stdafx.h"
#include <Windows.h>
#include <VersionHelpers.h>
#define STRINGIFY(X) tstring(_T(#X))
#define HANDLE_RETURN_CODE(NameOfCheck, ReturnValue) { if (CheckReturnValue::UnableToPerformCheck == ReturnValue || CheckReturnValue::Fail == ReturnValue) { checkThatFailed = STRINGIFY(NameOfCheck); return ReturnValue; } }
#define ADD_CHECK(NameOfCheck) { HANDLE_RETURN_CODE(KnownPreFlightChecks::##NameOfCheck, EnvMeets##NameOfCheck()); }
#define WIDTH 7
#define BYTES_PER_KB 1024
#define BYTES_TO_KB(X) (X / BYTES_PER_KB)
#define BYTES_TO_MB(X) (BYTES_TO_KB(X) / BYTES_PER_KB)
#define BYTES_TO_GB(X) (BYTES_TO_MB(X) / BYTES_PER_KB)
#define MINIMUM_RAM_SIZE_IN_GB 2
#define MINIMUM_FREE_SPACE_IN_GB 1
namespace PreFlightCheck
{
enum class KnownPreFlightChecks
{
MinOSVersion,
MinRAMSize,
MinFreeDiskSpace
};
enum class CheckReturnValue/* : int*/
{
UnableToPerformCheck = -2,
Fail = -1,
Pass
};
auto EnvMeetsMinOSVersion()
{
auto retVal = CheckReturnValue::UnableToPerformCheck;
if (IsWindows7OrGreater())
{
dprintf(_T("OS is Windows 7 or higher."));
retVal = CheckReturnValue::Pass;
}
else
{
// Vista SP2 or lower.
dprintf(_T("OS is lower than Windows 7."));
retVal = CheckReturnValue::Fail;
}
return retVal;
}
auto EnvMeetsMinRAMSize()
{
auto retVal = CheckReturnValue::UnableToPerformCheck;
MEMORYSTATUSEX memStatEx;
memStatEx.dwLength = sizeof(memStatEx);
if (::GlobalMemoryStatusEx(&memStatEx) == FALSE)
{
dprintf(_T("Unable to check for RAM size; Error: [%ld]."), ::GetLastError());
}
else
{
auto ramSizeInKB = BYTES_TO_KB(memStatEx.ullTotalPhys);
auto ramSizeInGB = BYTES_TO_GB(memStatEx.ullTotalPhys);
dprintf(_T("Available Physical Memory: %*I64d in KB; %ld in GB."), WIDTH, ramSizeInKB, ramSizeInGB);
if (ramSizeInGB < MINIMUM_RAM_SIZE_IN_GB)
{
retVal = CheckReturnValue::Fail;
}
else
{
retVal = CheckReturnValue::Pass;
}
}
return retVal;
}
auto EnvMeetsMinFreeDiskSpace()
{
ULARGE_INTEGER uliFreeDiskSpaceForCaller;
auto retVal = CheckReturnValue::UnableToPerformCheck;
if (::GetDiskFreeSpaceEx(nullptr, &uliFreeDiskSpaceForCaller, nullptr, nullptr) == FALSE)
{
dprintf(_T("Unable to check for RAM size; Error: [%ld]."), ::GetLastError());
}
else
{
auto freeSpaceInGB = BYTES_TO_GB(uliFreeDiskSpaceForCaller.QuadPart);
dprintf(_T("freeSpaceInGB: %ud"), freeSpaceInGB);
if (freeSpaceInGB < MINIMUM_FREE_SPACE_IN_GB)
{
retVal = CheckReturnValue::Fail;
}
else
{
retVal = CheckReturnValue::Pass;
}
}
return retVal;
}
auto DoesEnvironmentMeetPreFlightCheckRequirements(tstring& checkThatFailed)
{
ADD_CHECK(MinOSVersion);
ADD_CHECK(MinRAMSize);
ADD_CHECK(MinFreeDiskSpace);
return CheckReturnValue::Pass;
}
}
#endif // !PREFLIGHTCHECK_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment