1 // Written in the D programming language.
4 * Convert Win32 error code to string.
6 * Copyright: Copyright Digital Mars 2006 - 2013.
7 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
8 * Authors: $(HTTP digitalmars.com, Walter Bright)
9 * Credits: Based on code written by Regan Heath
11 /* Copyright Digital Mars 2006 - 2013.
12 * Distributed under the Boost Software License, Version 1.0.
13 * (See accompanying file LICENSE_1_0.txt or copy at
14 * http://www.boost.org/LICENSE_1_0.txt)
16 module std
.windows
.syserror
;
17 import std
.traits
: isSomeString
;
24 enum LANG_NEUTRAL
= 0, SUBLANG_DEFAULT
= 1;
27 /** Query the text for a Windows error code, as returned by
28 $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360.aspx,
29 $(D GetLastError)), as a D string.
31 string
sysErrorString(
33 // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) is the user's default language
34 int langId
= LANG_NEUTRAL
,
35 int subLangId
= SUBLANG_DEFAULT
) @trusted;
37 /*********************
38 Thrown if errors that set
39 $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360.aspx,
40 $(D GetLastError)) occur.
42 class WindowsException
: Exception
44 private alias DWORD
= int;
45 final @property DWORD
code(); /// $(D GetLastError)'s return value.
46 this(DWORD code
, string
str=null, string file
= null, size_t line
= 0) @trusted;
50 If $(D !!value) is true, $(D value) is returned. Otherwise,
51 $(D new WindowsException(GetLastError(), msg)) is thrown.
52 $(D WindowsException) assumes that the last operation set
53 $(D GetLastError()) appropriately.
57 wenforce(DeleteFileA("junk.tmp"), "DeleteFile failed");
60 T
wenforce(T
, S
)(T value
, lazy S msg
= null,
61 string file
= __FILE__
, size_t line
= __LINE__
) @safe
68 import core
.sys
.windows
.windows
;
69 import std
.array
: appender
;
71 import std
.format
: formattedWrite
;
72 import std
.windows
.charset
;
74 string
sysErrorString(
76 // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) is the user's default language
77 int langId
= LANG_NEUTRAL
,
78 int subLangId
= SUBLANG_DEFAULT
) @trusted
80 auto buf
= appender
!string();
82 if (!putSysError(errCode
, buf
, MAKELANGID(langId
, subLangId
)))
85 "failed getting error string for WinAPI error code: " ~
86 sysErrorString(GetLastError()));
92 bool putSysError(Writer
)(DWORD code
, Writer w
, /*WORD*/int langId
= 0)
94 wchar *lpMsgBuf
= null;
95 auto res
= FormatMessageW(
96 FORMAT_MESSAGE_ALLOCATE_BUFFER |
97 FORMAT_MESSAGE_FROM_SYSTEM |
98 FORMAT_MESSAGE_IGNORE_INSERTS
,
102 cast(LPWSTR
)&lpMsgBuf
,
105 scope(exit
) if (lpMsgBuf
) LocalFree(lpMsgBuf
);
109 import std
.string
: strip
;
110 w
.put(lpMsgBuf
[0 .. res
].strip());
118 class WindowsException
: Exception
120 import core
.sys
.windows
.windows
: DWORD
;
122 final @property DWORD
code() { return _code
; } /// $(D GetLastError)'s return value.
125 this(DWORD code
, string
str=null, string file
= null, size_t line
= 0) @trusted
129 auto buf
= appender
!string();
140 auto success
= putSysError(code
, buf
);
141 formattedWrite(buf
, success ?
" (error %d)" : "Error %d", code
);
144 super(buf
.data
, file
, line
);
149 T
wenforce(T
, S
)(T value
, lazy S msg
= null,
150 string file
= __FILE__
, size_t line
= __LINE__
)
154 throw new WindowsException(GetLastError(), to
!string(msg
), file
, line
);
158 T
wenforce(T
)(T condition
, const(char)[] name
, const(wchar)* namez
, string file
= __FILE__
, size_t line
= __LINE__
)
165 static string
trustedToString(const(wchar)* stringz
) @trusted
167 import core
.stdc
.wchar_
: wcslen
;
168 import std
.conv
: to
;
169 auto len
= wcslen(stringz
);
170 return to
!string(stringz
[0 .. len
]);
173 names
= trustedToString(namez
);
176 names
= to
!string(name
);
177 throw new WindowsException(GetLastError(), names
, file
, line
);
183 import std
.algorithm
.searching
: startsWith
, endsWith
;
184 import std
.exception
;
187 auto e
= collectException
!WindowsException(
188 DeleteFileA("unexisting.txt").wenforce("DeleteFile")
190 assert(e
.code
== ERROR_FILE_NOT_FOUND
);
191 assert(e
.msg
.startsWith("DeleteFile: "));
192 // can't test the entire message, as it depends on Windows locale
193 assert(e
.msg
.endsWith(" (error 2)"));
196 e
= new WindowsException(0);
199 e
= new WindowsException(0, "Test");
200 assert(e
.msg
== "Test");