]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/windows/c.rs
Auto merge of #22517 - brson:relnotes, r=Gankro
[rust.git] / src / libstd / sys / windows / c.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! C definitions used by libnative that don't belong in liblibc
12
13 #![allow(bad_style, dead_code, overflowing_literals)]
14
15 use libc;
16
17 pub use self::GET_FILEEX_INFO_LEVELS::*;
18 pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
19 pub use libc::consts::os::extra::{
20     FILE_ATTRIBUTE_READONLY,
21     FILE_ATTRIBUTE_DIRECTORY,
22     WSAPROTOCOL_LEN,
23 };
24 pub use libc::types::os::arch::extra::{GROUP, GUID, WSAPROTOCOLCHAIN};
25
26 pub const WSADESCRIPTION_LEN: usize = 256;
27 pub const WSASYS_STATUS_LEN: usize = 128;
28 pub const FIONBIO: libc::c_long = 0x8004667e;
29 pub const FD_SETSIZE: usize = 64;
30 pub const MSG_DONTWAIT: libc::c_int = 0;
31 pub const ERROR_ILLEGAL_CHARACTER: libc::c_int = 582;
32 pub const ENABLE_ECHO_INPUT: libc::DWORD = 0x4;
33 pub const ENABLE_EXTENDED_FLAGS: libc::DWORD = 0x80;
34 pub const ENABLE_INSERT_MODE: libc::DWORD = 0x20;
35 pub const ENABLE_LINE_INPUT: libc::DWORD = 0x2;
36 pub const ENABLE_PROCESSED_INPUT: libc::DWORD = 0x1;
37 pub const ENABLE_QUICK_EDIT_MODE: libc::DWORD = 0x40;
38 pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT;
39
40 pub const FD_ACCEPT: libc::c_long = 0x08;
41 pub const FD_MAX_EVENTS: usize = 10;
42 pub const WSA_INFINITE: libc::DWORD = libc::INFINITE;
43 pub const WSA_WAIT_TIMEOUT: libc::DWORD = libc::consts::os::extra::WAIT_TIMEOUT;
44 pub const WSA_WAIT_EVENT_0: libc::DWORD = libc::consts::os::extra::WAIT_OBJECT_0;
45 pub const WSA_WAIT_FAILED: libc::DWORD = libc::consts::os::extra::WAIT_FAILED;
46 pub const WSAESHUTDOWN: libc::c_int = 10058;
47
48 pub const ERROR_NO_MORE_FILES: libc::DWORD = 18;
49 pub const TOKEN_READ: libc::DWORD = 0x20008;
50
51 #[repr(C)]
52 #[cfg(target_arch = "x86")]
53 pub struct WSADATA {
54     pub wVersion: libc::WORD,
55     pub wHighVersion: libc::WORD,
56     pub szDescription: [u8; WSADESCRIPTION_LEN + 1],
57     pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
58     pub iMaxSockets: u16,
59     pub iMaxUdpDg: u16,
60     pub lpVendorInfo: *mut u8,
61 }
62 #[repr(C)]
63 #[cfg(target_arch = "x86_64")]
64 pub struct WSADATA {
65     pub wVersion: libc::WORD,
66     pub wHighVersion: libc::WORD,
67     pub iMaxSockets: u16,
68     pub iMaxUdpDg: u16,
69     pub lpVendorInfo: *mut u8,
70     pub szDescription: [u8; WSADESCRIPTION_LEN + 1],
71     pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
72 }
73
74 pub type LPWSADATA = *mut WSADATA;
75
76 #[repr(C)]
77 pub struct WSANETWORKEVENTS {
78     pub lNetworkEvents: libc::c_long,
79     pub iErrorCode: [libc::c_int; FD_MAX_EVENTS],
80 }
81
82 pub type LPWSANETWORKEVENTS = *mut WSANETWORKEVENTS;
83
84 pub type WSAEVENT = libc::HANDLE;
85
86 #[repr(C)]
87 #[derive(Copy)]
88 pub struct WSAPROTOCOL_INFO {
89     pub dwServiceFlags1: libc::DWORD,
90     pub dwServiceFlags2: libc::DWORD,
91     pub dwServiceFlags3: libc::DWORD,
92     pub dwServiceFlags4: libc::DWORD,
93     pub dwProviderFlags: libc::DWORD,
94     pub ProviderId: GUID,
95     pub dwCatalogEntryId: libc::DWORD,
96     pub ProtocolChain: WSAPROTOCOLCHAIN,
97     pub iVersion: libc::c_int,
98     pub iAddressFamily: libc::c_int,
99     pub iMaxSockAddr: libc::c_int,
100     pub iMinSockAddr: libc::c_int,
101     pub iSocketType: libc::c_int,
102     pub iProtocol: libc::c_int,
103     pub iProtocolMaxOffset: libc::c_int,
104     pub iNetworkByteOrder: libc::c_int,
105     pub iSecurityScheme: libc::c_int,
106     pub dwMessageSize: libc::DWORD,
107     pub dwProviderReserved: libc::DWORD,
108     pub szProtocol: [u16; (WSAPROTOCOL_LEN as usize) + 1],
109 }
110
111 pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
112
113 #[repr(C)]
114 pub struct fd_set {
115     fd_count: libc::c_uint,
116     fd_array: [libc::SOCKET; FD_SETSIZE],
117 }
118
119 pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) {
120     set.fd_array[set.fd_count as usize] = s;
121     set.fd_count += 1;
122 }
123
124 pub type SHORT = libc::c_short;
125
126 #[repr(C)]
127 pub struct COORD {
128     pub X: SHORT,
129     pub Y: SHORT,
130 }
131
132 #[repr(C)]
133 pub struct SMALL_RECT {
134     pub Left: SHORT,
135     pub Top: SHORT,
136     pub Right: SHORT,
137     pub Bottom: SHORT,
138 }
139
140 #[repr(C)]
141 pub struct CONSOLE_SCREEN_BUFFER_INFO {
142     pub dwSize: COORD,
143     pub dwCursorPosition: COORD,
144     pub wAttributes: libc::WORD,
145     pub srWindow: SMALL_RECT,
146     pub dwMaximumWindowSize: COORD,
147 }
148 pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO;
149
150 #[repr(C)]
151 pub struct WIN32_FILE_ATTRIBUTE_DATA {
152     pub dwFileAttributes: libc::DWORD,
153     pub ftCreationTime: libc::FILETIME,
154     pub ftLastAccessTime: libc::FILETIME,
155     pub ftLastWriteTime: libc::FILETIME,
156     pub nFileSizeHigh: libc::DWORD,
157     pub nFileSizeLow: libc::DWORD,
158 }
159
160 #[repr(C)]
161 pub struct BY_HANDLE_FILE_INFORMATION {
162     pub dwFileAttributes: libc::DWORD,
163     pub ftCreationTime: libc::FILETIME,
164     pub ftLastAccessTime: libc::FILETIME,
165     pub ftLastWriteTime: libc::FILETIME,
166     pub dwVolumeSerialNumber: libc::DWORD,
167     pub nFileSizeHigh: libc::DWORD,
168     pub nFileSizeLow: libc::DWORD,
169     pub nNumberOfLinks: libc::DWORD,
170     pub nFileIndexHigh: libc::DWORD,
171     pub nFileIndexLow: libc::DWORD,
172 }
173
174 pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION;
175
176 #[repr(C)]
177 pub enum GET_FILEEX_INFO_LEVELS {
178     GetFileExInfoStandard,
179     GetFileExMaxInfoLevel
180 }
181
182 #[repr(C)]
183 pub enum FILE_INFO_BY_HANDLE_CLASS {
184     FileBasicInfo                   = 0,
185     FileStandardInfo                = 1,
186     FileNameInfo                    = 2,
187     FileRenameInfo                  = 3,
188     FileDispositionInfo             = 4,
189     FileAllocationInfo              = 5,
190     FileEndOfFileInfo               = 6,
191     FileStreamInfo                  = 7,
192     FileCompressionInfo             = 8,
193     FileAttributeTagInfo            = 9,
194     FileIdBothDirectoryInfo         = 10, // 0xA
195     FileIdBothDirectoryRestartInfo  = 11, // 0xB
196     FileIoPriorityHintInfo          = 12, // 0xC
197     FileRemoteProtocolInfo          = 13, // 0xD
198     FileFullDirectoryInfo           = 14, // 0xE
199     FileFullDirectoryRestartInfo    = 15, // 0xF
200     FileStorageInfo                 = 16, // 0x10
201     FileAlignmentInfo               = 17, // 0x11
202     FileIdInfo                      = 18, // 0x12
203     FileIdExtdDirectoryInfo         = 19, // 0x13
204     FileIdExtdDirectoryRestartInfo  = 20, // 0x14
205     MaximumFileInfoByHandlesClass
206 }
207
208 #[repr(C)]
209 pub struct FILE_END_OF_FILE_INFO {
210     pub EndOfFile: libc::LARGE_INTEGER,
211 }
212
213 #[link(name = "ws2_32")]
214 extern "system" {
215     pub fn WSAStartup(wVersionRequested: libc::WORD,
216                       lpWSAData: LPWSADATA) -> libc::c_int;
217     pub fn WSACleanup() -> libc::c_int;
218     pub fn WSAGetLastError() -> libc::c_int;
219     pub fn WSACloseEvent(hEvent: WSAEVENT) -> libc::BOOL;
220     pub fn WSACreateEvent() -> WSAEVENT;
221     pub fn WSAEventSelect(s: libc::SOCKET,
222                           hEventObject: WSAEVENT,
223                           lNetworkEvents: libc::c_long) -> libc::c_int;
224     pub fn WSASetEvent(hEvent: WSAEVENT) -> libc::BOOL;
225     pub fn WSAWaitForMultipleEvents(cEvents: libc::DWORD,
226                                     lphEvents: *const WSAEVENT,
227                                     fWaitAll: libc::BOOL,
228                                     dwTimeout: libc::DWORD,
229                                     fAltertable: libc::BOOL) -> libc::DWORD;
230     pub fn WSAEnumNetworkEvents(s: libc::SOCKET,
231                                 hEventObject: WSAEVENT,
232                                 lpNetworkEvents: LPWSANETWORKEVENTS)
233                                 -> libc::c_int;
234     pub fn WSADuplicateSocketW(s: libc::SOCKET,
235                                dwProcessId: libc::DWORD,
236                                lpProtocolInfo: LPWSAPROTOCOL_INFO)
237                                -> libc::c_int;
238     pub fn GetCurrentProcessId() -> libc::DWORD;
239     pub fn WSASocketW(af: libc::c_int,
240                       kind: libc::c_int,
241                       protocol: libc::c_int,
242                       lpProtocolInfo: LPWSAPROTOCOL_INFO,
243                       g: GROUP,
244                       dwFlags: libc::DWORD) -> libc::SOCKET;
245
246     pub fn ioctlsocket(s: libc::SOCKET, cmd: libc::c_long,
247                        argp: *mut libc::c_ulong) -> libc::c_int;
248     pub fn select(nfds: libc::c_int,
249                   readfds: *mut fd_set,
250                   writefds: *mut fd_set,
251                   exceptfds: *mut fd_set,
252                   timeout: *mut libc::timeval) -> libc::c_int;
253     pub fn getsockopt(sockfd: libc::SOCKET,
254                       level: libc::c_int,
255                       optname: libc::c_int,
256                       optval: *mut libc::c_char,
257                       optlen: *mut libc::c_int) -> libc::c_int;
258
259     pub fn SetEvent(hEvent: libc::HANDLE) -> libc::BOOL;
260     pub fn WaitForMultipleObjects(nCount: libc::DWORD,
261                                   lpHandles: *const libc::HANDLE,
262                                   bWaitAll: libc::BOOL,
263                                   dwMilliseconds: libc::DWORD) -> libc::DWORD;
264
265     pub fn CancelIo(hFile: libc::HANDLE) -> libc::BOOL;
266     pub fn CancelIoEx(hFile: libc::HANDLE,
267                       lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL;
268 }
269
270 pub mod compat {
271     use prelude::v1::*;
272
273     use ffi::CString;
274     use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
275     use sync::atomic::{AtomicUsize, Ordering};
276
277     extern "system" {
278         fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
279         fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> LPVOID;
280     }
281
282     fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str,
283                   fallback: usize) -> usize {
284         let mut module: Vec<u16> = module.utf16_units().collect();
285         module.push(0);
286         let symbol = CString::from_slice(symbol.as_bytes());
287         let func = unsafe {
288             let handle = GetModuleHandleW(module.as_ptr());
289             GetProcAddress(handle, symbol.as_ptr()) as usize
290         };
291         let value = if func == 0 {fallback} else {func};
292         ptr.store(value, Ordering::SeqCst);
293         value
294     }
295
296     /// Macro for creating a compatibility fallback for a Windows function
297     ///
298     /// # Example
299     /// ```
300     /// compat_fn!(adll32::SomeFunctionW(_arg: LPCWSTR) {
301     ///     // Fallback implementation
302     /// })
303     /// ```
304     ///
305     /// Note that arguments unused by the fallback implementation should not be
306     /// called `_` as they are used to be passed to the real function if
307     /// available.
308     macro_rules! compat_fn {
309         ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*)
310                                       -> $rettype:ty { $fallback:expr }) => (
311             #[inline(always)]
312             pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype {
313                 use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
314                 use mem;
315
316                 static PTR: AtomicUsize = ATOMIC_USIZE_INIT;
317
318                 fn load() -> usize {
319                     ::sys::c::compat::store_func(&PTR,
320                                                  stringify!($module),
321                                                  stringify!($symbol),
322                                                  fallback as usize)
323                 }
324
325                 extern "system" fn fallback($($argname: $argtype),*)
326                                             -> $rettype { $fallback }
327
328                 let addr = match PTR.load(Ordering::SeqCst) {
329                     0 => load(),
330                     n => n,
331                 };
332                 let f: extern "system" fn($($argtype),*) -> $rettype =
333                     mem::transmute(addr);
334                 f($($argname),*)
335             }
336         )
337     }
338
339     /// Compatibility layer for functions in `kernel32.dll`
340     ///
341     /// Latest versions of Windows this is needed for:
342     ///
343     /// * `CreateSymbolicLinkW`: Windows XP, Windows Server 2003
344     /// * `GetFinalPathNameByHandleW`: Windows XP, Windows Server 2003
345     pub mod kernel32 {
346         use libc::c_uint;
347         use libc::types::os::arch::extra::{DWORD, LPCWSTR, BOOLEAN, HANDLE};
348         use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
349         use sys::c::SetLastError;
350
351         compat_fn! {
352             kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
353                                           _lpTargetFileName: LPCWSTR,
354                                           _dwFlags: DWORD) -> BOOLEAN {
355                 unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 }
356             }
357         }
358
359         compat_fn! {
360             kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE,
361                                                 _lpszFilePath: LPCWSTR,
362                                                 _cchFilePath: DWORD,
363                                                 _dwFlags: DWORD) -> DWORD {
364                 unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 }
365             }
366         }
367
368         compat_fn! {
369             kernel32::SetThreadErrorMode(_dwNewMode: DWORD, _lpOldMode: *mut DWORD) -> c_uint {
370                 unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 }
371             }
372         }
373     }
374 }
375
376 extern "system" {
377     // FIXME - pInputControl should be PCONSOLE_READCONSOLE_CONTROL
378     pub fn ReadConsoleW(hConsoleInput: libc::HANDLE,
379                         lpBuffer: libc::LPVOID,
380                         nNumberOfCharsToRead: libc::DWORD,
381                         lpNumberOfCharsRead: libc::LPDWORD,
382                         pInputControl: libc::LPVOID) -> libc::BOOL;
383
384     pub fn WriteConsoleW(hConsoleOutput: libc::HANDLE,
385                          lpBuffer: libc::types::os::arch::extra::LPCVOID,
386                          nNumberOfCharsToWrite: libc::DWORD,
387                          lpNumberOfCharsWritten: libc::LPDWORD,
388                          lpReserved: libc::LPVOID) -> libc::BOOL;
389
390     pub fn GetConsoleMode(hConsoleHandle: libc::HANDLE,
391                           lpMode: libc::LPDWORD) -> libc::BOOL;
392
393     pub fn SetConsoleMode(hConsoleHandle: libc::HANDLE,
394                           lpMode: libc::DWORD) -> libc::BOOL;
395     pub fn GetConsoleScreenBufferInfo(
396         hConsoleOutput: libc::HANDLE,
397         lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO,
398     ) -> libc::BOOL;
399
400     pub fn GetFileAttributesExW(lpFileName: libc::LPCWSTR,
401                                 fInfoLevelId: GET_FILEEX_INFO_LEVELS,
402                                 lpFileInformation: libc::LPVOID) -> libc::BOOL;
403     pub fn RemoveDirectoryW(lpPathName: libc::LPCWSTR) -> libc::BOOL;
404     pub fn SetFileAttributesW(lpFileName: libc::LPCWSTR,
405                               dwFileAttributes: libc::DWORD) -> libc::BOOL;
406     pub fn GetFileAttributesW(lpFileName: libc::LPCWSTR) -> libc::DWORD;
407     pub fn GetFileInformationByHandle(hFile: libc::HANDLE,
408                             lpFileInformation: LPBY_HANDLE_FILE_INFORMATION)
409                             -> libc::BOOL;
410
411     pub fn SetLastError(dwErrCode: libc::DWORD);
412     pub fn GetCommandLineW() -> *mut libc::LPCWSTR;
413     pub fn LocalFree(ptr: *mut libc::c_void);
414     pub fn CommandLineToArgvW(lpCmdLine: *mut libc::LPCWSTR,
415                               pNumArgs: *mut libc::c_int) -> *mut *mut u16;
416     pub fn SetFileTime(hFile: libc::HANDLE,
417                        lpCreationTime: *const libc::FILETIME,
418                        lpLastAccessTime: *const libc::FILETIME,
419                        lpLastWriteTime: *const libc::FILETIME) -> libc::BOOL;
420     pub fn SetFileInformationByHandle(hFile: libc::HANDLE,
421                     FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
422                     lpFileInformation: libc::LPVOID,
423                     dwBufferSize: libc::DWORD) -> libc::BOOL;
424     pub fn GetTempPathW(nBufferLength: libc::DWORD,
425                         lpBuffer: libc::LPCWSTR) -> libc::DWORD;
426     pub fn OpenProcessToken(ProcessHandle: libc::HANDLE,
427                             DesiredAccess: libc::DWORD,
428                             TokenHandle: *mut libc::HANDLE) -> libc::BOOL;
429     pub fn GetCurrentProcess() -> libc::HANDLE;
430 }
431
432 #[link(name = "userenv")]
433 extern "system" {
434     pub fn GetUserProfileDirectoryW(hToken: libc::HANDLE,
435                                     lpProfileDir: libc::LPCWSTR,
436                                     lpcchSize: *mut libc::DWORD) -> libc::BOOL;
437 }