It looks like fopen sets the errno, then clears the error code accessed by GetLastError. In the end, you need to call FormatMessage to get the system error message. Pass errno set by fopen directly to FormatMessage, don't use GetLastError.
// get the error message from the errno set by fopen
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errno,
LANG_NEUTRAL,
errorMsg,
256,
NULL);
See the attached files for a working example which tries to open a non-existent file to force an error.