A WinAPI C++ program for printing the master boot record of the hard drive I have rolled this program for reading the MBR:

#define WIN32_LEAN_AND_MEAN

#include &lt;Windows.h&gt;
#include &lt;cctype&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;utility&gt;

using std::isprint;
using std::cout;
using std::cin;
using std::move;
using std::size_t;
using std::string;

constexpr size_t MBR_SIZE = 512;
constexpr size_t BYTES_PER_LINE = 4;
constexpr size_t NUMBER_OF_LINES = MBR_SIZE / BYTES_PER_LINE;

// Converts 4 least significant bits of 'c' to corresponding 
// hexadecimal string.
static string fourBitsToString(char c)
{
    string s = " ";

    if (c &gt;= 0 &amp;&amp; c &lt;= 9) {
        s[0] = '0' + c;
    } else {
        c -= 10;
        s[0] = 'A' + c;
    }

    return move(s);
}

// Converts a character to its hexadecimal representation.
static string charToHex(char c)
{
    char lo = c &amp; 0xf;
    char hi = (c &gt;&gt; 4) &amp; 0xf;
    string s;
    char chars[] = {hi, lo};

    for (char ch : chars) {
        s += fourBitsToString(ch);
    }

    return std::move(s);
}

// Prints the MBR to console.
static void PrintMBR(char buffer[MBR_SIZE])
{
    size_t byteIndex = 0;
    string lineSeparator;
    string columnSeparator;

    for (size_t i = 0; i &lt; NUMBER_OF_LINES; i++) {
        cout &lt;&lt; lineSeparator;
        lineSeparator = '\n';
        columnSeparator = "";

        for (size_t j = 0; j &lt; BYTES_PER_LINE; j++) {
            string ch = charToHex(buffer[byteIndex++]);
            cout &lt;&lt; columnSeparator &lt;&lt; ch;
            columnSeparator = " ";
        }

        cout &lt;&lt; ' ';

        for (size_t j = 0; j &lt; BYTES_PER_LINE; j++) {
            char c = buffer[byteIndex - BYTES_PER_LINE + j];
            cout &lt;&lt; (isprint((unsigned int) c) ? c : '.');
        }
    }
}

// Reads the entire master boot record (MBR) into lpBuffer. 
// Expects lpBuffer to point to a memory point that may     
// hold at leasst 512 bytes.                                
static DWORD ReadMBR(PCHAR lpBuffer)
{

    HANDLE diskHandle = CreateFile(
        TEXT("\\\\.\\PhysicalDrive0"),
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

    char* buffer = new char[MBR_SIZE];

    ReadFile(
        diskHandle,
        lpBuffer,
        MBR_SIZE,
        NULL,
        NULL);

    return GetLastError();
}

int main() {
    char buffer[MBR_SIZE];
    ReadMBR(buffer);
    PrintMBR(buffer);
    cin.get();
    return 3;
}


(Compile as Release instead of Debug if it throws a nasty runtime breakpoint.)

I would love to hear any comments possible, but my main question is whether it is  idiomatic C/C++/WinAPI.

Note: To see the actual MBR, run this as administrator.
Idiomatic is relative. I guess it's a coding style you could find in older code-bases (and many winapi based applications are rather old), but you wouldn't write C++ like this today. Consider for instance:

#include &lt;iostream&gt;
#include &lt;iomanip&gt;
#include &lt;iterator&gt;
#include &lt;algorithm&gt;
#include &lt;numeric&gt;
#include &lt;array&gt;

constexpr std::size_t MBR_SIZE = 255;
constexpr std::size_t BYTES_PER_COLUMN = 4;
constexpr char LINE_DELIMITER = '\n';
constexpr const char* COL_DELIMITER = " ";

int main() {
    std::array&lt;unsigned char, MBR_SIZE&gt; mbr;
    std::iota(std::begin(mbr), std::end(mbr), 0); // filling it for testing purposes

    std::cout &lt;&lt; std::hex &lt;&lt; std::setfill('0');
    std::size_t index = 0;
    std::transform(std::begin(mbr), std::end(mbr), std::ostream_iterator&lt;int&gt;(std::cout, COL_DELIMITER), [index](auto c) mutable {
        if (index++ % BYTES_PER_COLUMN == 0) std::cout &lt;&lt; LINE_DELIMITER;
        std::cout &lt;&lt; std::setw(2); // setw must be applied for each output
        return c;
    });
    std::cout &lt;&lt; std::endl;
}


In a dozen of lines you get the same result as printMBR and its two auxiliary functions (at least I believe so, I haven't had the chance to run your code), which are longer and more complicated.

To be more specific about your code:


don't declare a variable before you're ready to define it, and don't define it before you're ready to use it.
don't std::move your return value, it prevents copy elision
don't declare free functions static, it's a java thing
inside ReadMBR there's a char* buffer = new char[MBR_SIZE]; you don't use afterwards
I'm not a fan of that many using directives; prefix the names with std:: and be done with it, unless you prefer to set up aliases: then using string = std::string is clearer
use standard algorithms, such as std::copy, std::accumulate, etc (in headers &lt;algorithm&gt; and &lt;numeric&gt;) or range-base for loops (for auto item : sequence) instead of "raw" loops. For instance, charToHex could be written


like this:

std::string s;
for (auto nibble : { (c &gt;&gt; 4) &amp; 0xf, c &amp; 0xf }) 
    s += fourBitsToString(nibble);
return s;


or:

char lo = c &amp; 0xf;
char hi = (c &gt;&gt; 4) &amp; 0xf;
char chars[] = {hi, lo};

return std::accumulate(std::begin(chars), std::end(chars), std::string(), [](auto init, auto elem) {
    return init += (fourBitsToString(elem));
});


And, on a more aesthetic note, a four-bits aggregate can be called a half-byte or a nibble.