// Written in the D programming language.

/**
 * Convert Win32 error code to string.
 *
 * Copyright: Copyright The D Language Foundation" 2006 - 2013.
 * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
 * Authors:   $(HTTP digitalmars.com, Walter Bright)
 * Credits:   Based on code written by Regan Heath
 */
/*          Copyright The D Language Foundation" 2006 - 2013.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
module std.windows.syserror;
import std.traits : isSomeString;

version (StdDdoc)
{
    private
    {
        alias DWORD = uint;
        enum LANG_NEUTRAL = 0, SUBLANG_DEFAULT = 1;
    }

    /** Query the text for a Windows error code, as returned by
        $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360.aspx,
        `GetLastError`), as a D string.
     */
    string sysErrorString(
        DWORD errCode,
        // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) is the user's default language
        int langId = LANG_NEUTRAL,
        int subLangId = SUBLANG_DEFAULT) @trusted;

    /*********************
       Thrown if errors that set
       $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360.aspx,
       `GetLastError`) occur.
     */
    class WindowsException : Exception
    {
        private alias DWORD = int;
        final @property DWORD code(); /// `GetLastError`'s return value.
        this(DWORD code, string str=null, string file = null, size_t line = 0) nothrow @trusted;
    }

    /++
        If `!!value` is true, `value` is returned. Otherwise,
        $(D new WindowsException(GetLastError(), msg)) is thrown.
        `WindowsException` assumes that the last operation set
        `GetLastError()` appropriately.

        Example:
        --------------------
        wenforce(DeleteFileA("junk.tmp"), "DeleteFile failed");
        --------------------
     +/
    T wenforce(T, S)(T value, lazy S msg = null,
        string file = __FILE__, size_t line = __LINE__) @safe
    if (isSomeString!S);
}
else:

version (Windows):

import core.sys.windows.winbase, core.sys.windows.winnt;
import std.array : appender, Appender;
import std.conv : to, toTextRange, text;
import std.exception;

string sysErrorString(
    DWORD errCode,
    // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) is the user's default language
    int langId = LANG_NEUTRAL,
    int subLangId = SUBLANG_DEFAULT) @trusted
{
    auto buf = appender!string();

    wenforce(
        // Ignore unlikely UTF decoding errors, always report the actual error (`errCode`)
        putSysError(errCode, buf, MAKELANGID(langId, subLangId)).ifThrown(false),
        text("Could not fetch error string for WinAPI code ", errCode)
    );

    return buf.data;
}

@safe unittest
{
    import std.algorithm.searching;

    assert(sysErrorString(ERROR_PATH_NOT_FOUND) !is null);

    const msg = collectExceptionMsg!WindowsException(sysErrorString(DWORD.max));
    assert(msg.startsWith(`Could not fetch error string for WinAPI code 4294967295: `));
}

bool putSysError(Writer)(DWORD code, Writer w, /*WORD*/int langId = 0)
{
    wchar *lpMsgBuf = null;
    auto res = FormatMessageW(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        null,
        code,
        langId,
        cast(LPWSTR)&lpMsgBuf,
        0,
        null);
    scope(exit) if (lpMsgBuf) LocalFree(lpMsgBuf);

    if (lpMsgBuf)
    {
        import std.string : strip;
        w.put(lpMsgBuf[0 .. res].strip());
        return true;
    }
    else
        return false;
}

class WindowsException : Exception
{
    import core.sys.windows.windef : DWORD;

    final @property DWORD code() { return _code; } /// `GetLastError`'s return value.
    private DWORD _code;

    this(DWORD code, string str=null, string file = null, size_t line = 0) nothrow @trusted
    {
        _code = code;

        auto buf = appender!(char[]);

        if (str != null)
        {
            buf.put(str);
            if (code)
                buf.put(": ");
        }

        if (code && writeErrorMessage(code, buf))
        {
            buf.put(" (error ");
            toTextRange(code, buf);
            buf.put(')');
        }

        super(cast(immutable) buf.data, file, line);
    }
}

/// Writes the error string associated to `code` into `buf`.
/// Writes `Error <code>` when the error message lookup fails
private bool writeErrorMessage(DWORD code, ref Appender!(char[]) buf) nothrow
{
    bool success;
    try
    {
        // Reset the buffer to undo partial changes
        const len = buf[].length;
        scope (failure) buf.shrinkTo(len);

        success = putSysError(code, buf);
    }
    catch (Exception) {}

    // Write the error code instead if we couldn't find the string
    if (!success)
    {
        buf.put("Error ");
        toTextRange(code, buf);
    }

    return success;
}

T wenforce(T, S = string)(T value, lazy S msg = null,
string file = __FILE__, size_t line = __LINE__)
if (isSomeString!S)
{
    if (!value)
        throw new WindowsException(GetLastError(), to!string(msg), file, line);
    return value;
}

T wenforce(T)(T condition, const(char)[] name, const(wchar)* namez, string file = __FILE__, size_t line = __LINE__)
{
    if (condition)
        return condition;
    string names;
    if (!name)
    {
        static string trustedToString(const(wchar)* stringz) @trusted
        {
            import core.stdc.wchar_ : wcslen;
            import std.conv : to;
            auto len = wcslen(stringz);
            return to!string(stringz[0 .. len]);
        }

        names = trustedToString(namez);
    }
    else
        names = to!string(name);
    throw new WindowsException(GetLastError(), names, file, line);
}

@system unittest
{
    import std.algorithm.searching : startsWith, endsWith;
    import std.string;

    auto e = collectException!WindowsException(
        DeleteFileA("unexisting.txt").wenforce("DeleteFile")
    );
    assert(e.code == ERROR_FILE_NOT_FOUND);
    assert(e.msg.startsWith("DeleteFile: "));
    // can't test the entire message, as it depends on Windows locale
    assert(e.msg.endsWith(" (error 2)"));

    // Test code zero
    e = new WindowsException(0);
    assert(e.msg == "");

    e = new WindowsException(0, "Test");
    assert(e.msg == "Test");
}

@safe nothrow unittest
{
    import std.algorithm.searching : endsWith;

    auto e = new WindowsException(ERROR_FILE_NOT_FOUND);
    assert(e.msg.endsWith("(error 2)"));

    e = new WindowsException(DWORD.max);
    assert(e.msg == "Error 4294967295");
}

/// Tries to translate an error code from the Windows API to the corresponding
/// error message. Returns `Error <code>` on failure
package (std) string generateSysErrorMsg(DWORD errCode = GetLastError()) nothrow @trusted
{
    auto buf = appender!(char[]);
    cast(void) writeErrorMessage(errCode, buf);
    return cast(immutable) buf[];
}

nothrow @safe unittest
{
    assert(generateSysErrorMsg(ERROR_PATH_NOT_FOUND) !is null);
    assert(generateSysErrorMsg(DWORD.max) == "Error 4294967295");
}
