#include "stdafx.h"
#include "SystemError.h"
#include "Convert.h"

#ifdef WINDOWS
#undef null
#include <comdef.h>
#define null NULL
#endif

namespace storm {

#if defined(WINDOWS)

	Str *systemErrorMessage(Engine &e, DWORD lastError) {
		wchar *buffer = null;
		size_t size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
									FORMAT_MESSAGE_FROM_SYSTEM |
									FORMAT_MESSAGE_IGNORE_INSERTS,
									NULL,
									lastError,
									// MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
									MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
									(wchar *)&buffer,
									0,
									NULL);
		try {
			Str *msg = new (e) Str(buffer);
			LocalFree(buffer);
			return msg;
		} catch (...) {
			LocalFree(buffer);
			throw;
		}
	}

	Str *hresultErrorMessage(Engine &e, HRESULT result) {
		return new (e) Str(_com_error(result).ErrorMessage());
	}

#endif

#if defined(POSIX)

	// There are two variants of strerror_r with different return values. Detect which one is used
	// and extract the error as appropriate.
	static const char *extract(char *buffer, int result) {
		if (result != 0)
			strcat(buffer, "unknown error");
		return buffer;
	}
	static const char *extract(char *buffer, const char *result) {
		(void)buffer;
		return result;
	}

	Str *systemErrorMessage(Engine &e, int error) {
		const size_t bufsize = 512;
		char buffer[bufsize] = { 0 };

		const char *msg = extract(buffer, strerror_r(error, buffer, bufsize));
		return new (e) Str(toWChar(e, msg));
	}

#endif

}
