1 /*******************************************************************************
2 
3         copyright:      Copyright (c) 2004 Kris Bell. All rights reserved
4 
5         license:        BSD style: $(LICENSE)
6 
7         version:        Initial release: November 2005
8 
9         author:         Kris
10 
11 *******************************************************************************/
12 
13 module tango.sys.Common;
14 
15 version (Win32)
16         {
17         public import tango.sys.win32.UserGdi;
18         }
19 
20 version (linux)
21         {
22         public import tango.sys.linux.linux;
23         alias tango.sys.linux.linux posix;
24         }
25 
26 version (darwin)
27         {
28         public import tango.sys.darwin.darwin;
29         alias tango.sys.darwin.darwin posix;
30         }
31 version (FreeBSD)
32         {
33         public import tango.sys.freebsd.freebsd;
34         alias tango.sys.freebsd.freebsd posix;
35         }
36 version (solaris)
37         {
38         public import tango.sys.solaris.solaris;
39         alias tango.sys.solaris.solaris posix;
40         }
41 
42 /*******************************************************************************
43 
44         Stuff for sysErrorMsg(), kindly provided by Regan Heath.
45 
46 *******************************************************************************/
47 
48 version (Win32)
49         {
50         private enum FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
51         private enum FORMAT_MESSAGE_IGNORE_INSERTS  = 0x00000200;
52         private enum FORMAT_MESSAGE_FROM_STRING     = 0x00000400;
53         private enum FORMAT_MESSAGE_FROM_HMODULE    = 0x00000800;
54         private enum FORMAT_MESSAGE_FROM_SYSTEM     = 0x00001000;
55         private enum FORMAT_MESSAGE_ARGUMENT_ARRAY  = 0x00002000;
56         private enum FORMAT_MESSAGE_MAX_WIDTH_MASK  = 0x000000FF;
57 
58         private DWORD MAKELANGID(WORD p, WORD s)  { return (((cast(WORD)s) << 10) | cast(WORD)p); }
59 
60         private alias HGLOBAL HLOCAL;
61 
62         private enum LANG_NEUTRAL = 0x00;
63         private enum SUBLANG_DEFAULT = 0x01;
64 
65         private extern (Windows)
66                        {
67                        DWORD FormatMessageW (DWORD dwFlags,
68                                              LPCVOID lpSource,
69                                              DWORD dwMessageId,
70                                              DWORD dwLanguageId,
71                                              LPWSTR lpBuffer,
72                                              DWORD nSize,
73                                              LPCVOID args
74                                              );
75 
76                        HLOCAL LocalFree(HLOCAL hMem);
77                        }
78         }
79 else
80 version (Posix)
81         {
82         private import tango.stdc.errno;
83         private import tango.stdc.string;
84         }
85 else
86    {
87    pragma (msg, "Unsupported environment; neither Win32 or Posix is declared");
88    static assert(0);
89    }
90 
91    
92 /*******************************************************************************
93 
94 *******************************************************************************/
95 
96 struct SysError
97 {   
98         /***********************************************************************
99 
100         ***********************************************************************/
101 
102         @property static uint lastCode ()
103         {
104                 version (Win32)
105                          return GetLastError();
106                      else
107                          return errno;
108         }
109 
110         /***********************************************************************
111 
112         ***********************************************************************/
113 
114         @property static char[] lastMsg ()
115         {
116                 return lookup (lastCode);
117         }
118 
119         /***********************************************************************
120 
121         ***********************************************************************/
122 
123         @property static char[] lookup (uint errcode)
124         {
125                 char[] text;
126 
127                 version (Win32)
128                         {
129                         DWORD  i;
130                         LPWSTR lpMsgBuf;
131 
132                         i = FormatMessageW (
133                                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
134                                 FORMAT_MESSAGE_FROM_SYSTEM |
135                                 FORMAT_MESSAGE_IGNORE_INSERTS,
136                                 null,
137                                 errcode,
138                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
139                                 cast(LPWSTR)&lpMsgBuf,
140                                 0,
141                                 null);
142 
143                         /* Remove \r\n from error string */
144                         if (i >= 2) i -= 2;
145                         text = new char[i * 3];
146                         i = WideCharToMultiByte (CP_UTF8, 0, lpMsgBuf, i, 
147                                                  cast(PCHAR)text.ptr, text.length, null, null);
148                         text = text [0 .. i];
149                         LocalFree (cast(HLOCAL) lpMsgBuf);
150                         }
151                      else
152                         {
153                         size_t  r;
154                         char* pemsg;
155 
156                         pemsg = strerror(errcode);
157                         r = strlen(pemsg);
158 
159                         /* Remove \r\n from error string */
160                         if (pemsg[r-1] == '\n') r--;
161                         if (pemsg[r-1] == '\r') r--;
162                         text = pemsg[0..r].dup;
163                         }
164 
165                 return text;
166         }
167 }