1
Fork 0
rust/library/std/src/sys/pal/windows/c.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

516 lines
15 KiB
Rust
Raw Normal View History

//! C definitions used by libnative that don't belong in liblibc
#![allow(nonstandard_style)]
2016-02-20 08:18:02 +01:00
#![cfg_attr(test, allow(dead_code))]
#![unstable(issue = "none", feature = "windows_c")]
#![allow(clippy::style)]
use crate::ffi::CStr;
2022-01-06 02:47:36 +00:00
use crate::mem;
2023-04-05 02:05:37 +01:00
pub use crate::os::raw::c_int;
2024-07-14 06:43:43 +00:00
use crate::os::raw::{c_char, c_uint, c_ulong, c_ushort, c_void};
2023-04-05 02:05:37 +01:00
use crate::os::windows::io::{AsRawHandle, BorrowedHandle};
2019-02-11 04:23:21 +09:00
use crate::ptr;
2024-07-05 15:43:12 +00:00
pub(super) mod windows_targets;
2024-07-04 12:09:25 +00:00
2023-04-05 02:05:37 +01:00
mod windows_sys;
pub use windows_sys::*;
pub type DWORD = c_ulong;
pub type WCHAR = u16;
pub type USHORT = c_ushort;
pub type SIZE_T = usize;
pub type CHAR = c_char;
pub type ULONG = c_ulong;
2023-01-19 23:21:21 -08:00
pub type LPCVOID = *const c_void;
pub type LPOVERLAPPED = *mut OVERLAPPED;
pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES;
pub type LPVOID = *mut c_void;
pub type LPWCH = *mut WCHAR;
pub type LPWSTR = *mut WCHAR;
#[cfg(target_vendor = "win7")]
pub type PSRWLOCK = *mut SRWLOCK;
pub type socklen_t = c_int;
pub type ADDRESS_FAMILY = USHORT;
2023-04-05 02:05:37 +01:00
pub use FD_SET as fd_set;
pub use LINGER as linger;
pub use TIMEVAL as timeval;
pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::without_provenance_mut(-1i32 as _);
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure?view=msvc-170
pub const EXIT_SUCCESS: u32 = 0;
pub const EXIT_FAILURE: u32 = 1;
#[cfg(target_vendor = "win7")]
2023-04-05 02:05:37 +01:00
pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() };
#[cfg(target_vendor = "win7")]
2023-04-05 02:05:37 +01:00
pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() };
2024-06-15 17:47:35 +02:00
#[cfg(not(target_thread_local))]
2023-04-05 02:05:37 +01:00
pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() };
2022-01-06 02:47:36 +00:00
2023-04-05 02:05:37 +01:00
// Some windows_sys types have different signs than the types we use.
pub const OBJ_DONT_REPARSE: u32 = windows_sys::OBJ_DONT_REPARSE as u32;
pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: u32 =
windows_sys::FRS_ERR_SYSVOL_POPULATE_TIMEOUT as u32;
pub const AF_INET: c_int = windows_sys::AF_INET as c_int;
pub const AF_INET6: c_int = windows_sys::AF_INET6 as c_int;
#[repr(C)]
pub struct ip_mreq {
pub imr_multiaddr: in_addr,
pub imr_interface: in_addr,
}
#[repr(C)]
pub struct ipv6_mreq {
pub ipv6mr_multiaddr: in6_addr,
pub ipv6mr_interface: c_uint,
}
2022-01-06 02:47:36 +00:00
// Equivalent to the `NT_SUCCESS` C preprocessor macro.
// See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values
pub fn nt_success(status: NTSTATUS) -> bool {
status >= 0
}
2022-01-06 02:47:36 +00:00
impl UNICODE_STRING {
pub fn from_ref(slice: &[u16]) -> Self {
2023-11-21 23:17:29 +00:00
let len = mem::size_of_val(slice);
2022-01-06 02:47:36 +00:00
Self { Length: len as _, MaximumLength: len as _, Buffer: slice.as_ptr() as _ }
}
}
2023-04-05 02:05:37 +01:00
2022-01-06 02:47:36 +00:00
impl Default for OBJECT_ATTRIBUTES {
fn default() -> Self {
Self {
Length: mem::size_of::<Self>() as _,
RootDirectory: ptr::null_mut(),
ObjectName: ptr::null_mut(),
Attributes: 0,
SecurityDescriptor: ptr::null_mut(),
SecurityQualityOfService: ptr::null_mut(),
}
}
}
2023-04-05 02:05:37 +01:00
impl IO_STATUS_BLOCK {
2023-04-05 02:05:37 +01:00
pub const PENDING: Self =
IO_STATUS_BLOCK { Anonymous: IO_STATUS_BLOCK_0 { Status: STATUS_PENDING }, Information: 0 };
pub fn status(&self) -> NTSTATUS {
2023-04-05 02:05:37 +01:00
// SAFETY: If `self.Anonymous.Status` was set then this is obviously safe.
// If `self.Anonymous.Pointer` was set then this is the equivalent to converting
// the pointer to an integer, which is also safe.
// Currently the only safe way to construct `IO_STATUS_BLOCK` outside of
// this module is to call the `default` method, which sets the `Status`.
2023-04-05 02:05:37 +01:00
unsafe { self.Anonymous.Status }
}
}
2022-01-06 02:47:36 +00:00
/// NB: Use carefully! In general using this as a reference is likely to get the
/// provenance wrong for the `rest` field!
#[repr(C)]
pub struct REPARSE_DATA_BUFFER {
pub ReparseTag: c_uint,
pub ReparseDataLength: c_ushort,
pub Reserved: c_ushort,
pub rest: (),
}
/// NB: Use carefully! In general using this as a reference is likely to get the
/// provenance wrong for the `PathBuffer` field!
#[repr(C)]
pub struct SYMBOLIC_LINK_REPARSE_BUFFER {
pub SubstituteNameOffset: c_ushort,
pub SubstituteNameLength: c_ushort,
pub PrintNameOffset: c_ushort,
pub PrintNameLength: c_ushort,
pub Flags: c_ulong,
pub PathBuffer: WCHAR,
}
#[repr(C)]
pub struct MOUNT_POINT_REPARSE_BUFFER {
pub SubstituteNameOffset: c_ushort,
pub SubstituteNameLength: c_ushort,
pub PrintNameOffset: c_ushort,
pub PrintNameLength: c_ushort,
pub PathBuffer: WCHAR,
}
#[repr(C)]
pub struct SOCKADDR_STORAGE_LH {
pub ss_family: ADDRESS_FAMILY,
pub __ss_pad1: [CHAR; 6],
pub __ss_align: i64,
pub __ss_pad2: [CHAR; 112],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct sockaddr_in {
pub sin_family: ADDRESS_FAMILY,
pub sin_port: USHORT,
pub sin_addr: in_addr,
pub sin_zero: [CHAR; 8],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
pub sin6_family: ADDRESS_FAMILY,
pub sin6_port: USHORT,
pub sin6_flowinfo: c_ulong,
pub sin6_addr: in6_addr,
pub sin6_scope_id: c_ulong,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
2021-05-06 04:04:19 +01:00
// Desktop specific functions & types
cfg_if::cfg_if! {
if #[cfg(not(target_vendor = "uwp"))] {
2023-04-05 02:05:37 +01:00
pub const EXCEPTION_CONTINUE_SEARCH: i32 = 0;
}
}
2023-04-05 02:05:37 +01:00
pub unsafe extern "system" fn WriteFileEx(
hFile: BorrowedHandle<'_>,
lpBuffer: *mut ::core::ffi::c_void,
nNumberOfBytesToWrite: u32,
lpOverlapped: *mut OVERLAPPED,
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
) -> BOOL {
windows_sys::WriteFileEx(
hFile.as_raw_handle(),
lpBuffer.cast::<u8>(),
nNumberOfBytesToWrite,
lpOverlapped,
lpCompletionRoutine,
)
}
pub unsafe extern "system" fn ReadFileEx(
hFile: BorrowedHandle<'_>,
lpBuffer: *mut ::core::ffi::c_void,
nNumberOfBytesToRead: u32,
lpOverlapped: *mut OVERLAPPED,
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
) -> BOOL {
windows_sys::ReadFileEx(
hFile.as_raw_handle(),
2023-08-16 09:18:34 +01:00
lpBuffer.cast::<u8>(),
2023-04-05 02:05:37 +01:00
nNumberOfBytesToRead,
lpOverlapped,
lpCompletionRoutine,
)
}
// POSIX compatibility shims.
pub unsafe fn recv(socket: SOCKET, buf: *mut c_void, len: c_int, flags: c_int) -> c_int {
windows_sys::recv(socket, buf.cast::<u8>(), len, flags)
}
pub unsafe fn send(socket: SOCKET, buf: *const c_void, len: c_int, flags: c_int) -> c_int {
windows_sys::send(socket, buf.cast::<u8>(), len, flags)
}
pub unsafe fn recvfrom(
socket: SOCKET,
buf: *mut c_void,
len: c_int,
flags: c_int,
addr: *mut SOCKADDR,
addrlen: *mut c_int,
) -> c_int {
windows_sys::recvfrom(socket, buf.cast::<u8>(), len, flags, addr, addrlen)
}
pub unsafe fn sendto(
socket: SOCKET,
buf: *const c_void,
len: c_int,
flags: c_int,
addr: *const SOCKADDR,
addrlen: c_int,
) -> c_int {
windows_sys::sendto(socket, buf.cast::<u8>(), len, flags, addr, addrlen)
}
pub unsafe fn getaddrinfo(
node: *const c_char,
service: *const c_char,
hints: *const ADDRINFOA,
res: *mut *mut ADDRINFOA,
) -> c_int {
windows_sys::getaddrinfo(node.cast::<u8>(), service.cast::<u8>(), hints, res)
}
2023-06-10 16:30:26 +08:00
cfg_if::cfg_if! {
if #[cfg(not(target_vendor = "uwp"))] {
2023-04-05 02:05:37 +01:00
pub unsafe fn NtReadFile(
filehandle: BorrowedHandle<'_>,
event: HANDLE,
apcroutine: PIO_APC_ROUTINE,
apccontext: *mut c_void,
iostatusblock: &mut IO_STATUS_BLOCK,
buffer: *mut crate::mem::MaybeUninit<u8>,
length: ULONG,
2024-07-14 06:32:22 +00:00
byteoffset: Option<&i64>,
2023-04-05 02:05:37 +01:00
key: Option<&ULONG>,
) -> NTSTATUS {
windows_sys::NtReadFile(
filehandle.as_raw_handle(),
event,
apcroutine,
apccontext,
iostatusblock,
buffer.cast::<c_void>(),
length,
byteoffset.map(|o| o as *const i64).unwrap_or(ptr::null()),
key.map(|k| k as *const u32).unwrap_or(ptr::null()),
)
}
pub unsafe fn NtWriteFile(
filehandle: BorrowedHandle<'_>,
event: HANDLE,
apcroutine: PIO_APC_ROUTINE,
apccontext: *mut c_void,
iostatusblock: &mut IO_STATUS_BLOCK,
buffer: *const u8,
length: ULONG,
2024-07-14 06:32:22 +00:00
byteoffset: Option<&i64>,
2023-04-05 02:05:37 +01:00
key: Option<&ULONG>,
) -> NTSTATUS {
windows_sys::NtWriteFile(
filehandle.as_raw_handle(),
event,
apcroutine,
apccontext,
iostatusblock,
buffer.cast::<c_void>(),
length,
byteoffset.map(|o| o as *const i64).unwrap_or(ptr::null()),
key.map(|k| k as *const u32).unwrap_or(ptr::null()),
)
}
2023-06-10 16:30:26 +08:00
}
}
// Use raw-dylib to import ProcessPrng as we can't rely on there being an import library.
cfg_if::cfg_if! {
if #[cfg(not(target_vendor = "win7"))] {
#[cfg(target_arch = "x86")]
#[link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated")]
extern "system" {
pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL;
}
#[cfg(not(target_arch = "x86"))]
#[link(name = "bcryptprimitives", kind = "raw-dylib")]
extern "system" {
pub fn ProcessPrng(pbdata: *mut u8, cbdata: usize) -> BOOL;
}
}}
2017-09-06 20:40:34 +01:00
// Functions that aren't available on every version of Windows that we support,
// but we still use them and just provide some form of a fallback implementation.
compat_fn_with_fallback! {
2023-12-03 14:24:25 +03:00
pub static KERNEL32: &CStr = c"kernel32";
std: Fix Windows XP compatibility This commit enables executables linked against the standard library to run on Windows XP. There are two main components of this commit: * APIs not available on XP are shimmed to have a fallback implementation and use runtime detection to determine if they are available. * Mutexes on Windows were reimplemented to use critical sections on XP where rwlocks are not available. The APIs which are not available on XP are: * SetFileInformationByHandle - this is just used by `File::truncate` and that function just returns an error now. * SetThreadStackGuarantee - this is used by the stack overflow support on windows, but if this isn't available then it's just ignored (it seems non-critical). * All condition variable APIs are missing - the shims added for these apis simply always panic for now. We may eventually provide a fallback implementation, but for now the standard library does not rely on condition variables for normal use. * RWLocks, like condition variables, are missing entirely. The same story for condition variables is taken here. These APIs are all now panicking stubs as the standard library doesn't rely on RWLocks for normal use. Currently, as an optimization, we use SRWLOCKs for the standard `sync::Mutex` implementation on Windows, which is indeed required for normal operation of the standard library. To allow the standard library to run on XP, this commit reimplements mutexes on Windows to use SRWLOCK instances *if available* and otherwise a CriticalSection is used (with some checking for recursive locking). With all these changes put together, a 32-bit MSVC-built executable can run on Windows XP and print "hello world" Closes #12842 Closes #19992 Closes #24776
2015-06-26 09:30:35 -07:00
// >= Win10 1607
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
2023-04-05 02:05:37 +01:00
pub fn SetThreadDescription(hthread: HANDLE, lpthreaddescription: PCWSTR) -> HRESULT {
2017-09-06 20:40:34 +01:00
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
}
// >= Win10 1607
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreaddescription
pub fn GetThreadDescription(hthread: HANDLE, lpthreaddescription: *mut PWSTR) -> HRESULT {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
}
// >= Win8 / Server 2012
// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
#[cfg(target_vendor = "win7")]
2023-04-05 02:05:37 +01:00
pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> () {
GetSystemTimeAsFileTime(lpsystemtimeasfiletime)
}
// >= Win11 / Server 2022
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
2023-04-05 02:05:37 +01:00
pub fn GetTempPath2W(bufferlength: u32, buffer: PWSTR) -> u32 {
GetTempPathW(bufferlength, buffer)
}
std: Fix Windows XP compatibility This commit enables executables linked against the standard library to run on Windows XP. There are two main components of this commit: * APIs not available on XP are shimmed to have a fallback implementation and use runtime detection to determine if they are available. * Mutexes on Windows were reimplemented to use critical sections on XP where rwlocks are not available. The APIs which are not available on XP are: * SetFileInformationByHandle - this is just used by `File::truncate` and that function just returns an error now. * SetThreadStackGuarantee - this is used by the stack overflow support on windows, but if this isn't available then it's just ignored (it seems non-critical). * All condition variable APIs are missing - the shims added for these apis simply always panic for now. We may eventually provide a fallback implementation, but for now the standard library does not rely on condition variables for normal use. * RWLocks, like condition variables, are missing entirely. The same story for condition variables is taken here. These APIs are all now panicking stubs as the standard library doesn't rely on RWLocks for normal use. Currently, as an optimization, we use SRWLOCKs for the standard `sync::Mutex` implementation on Windows, which is indeed required for normal operation of the standard library. To allow the standard library to run on XP, this commit reimplements mutexes on Windows to use SRWLOCK instances *if available* and otherwise a CriticalSection is used (with some checking for recursive locking). With all these changes put together, a 32-bit MSVC-built executable can run on Windows XP and print "hello world" Closes #12842 Closes #19992 Closes #24776
2015-06-26 09:30:35 -07:00
}
2024-02-19 19:17:29 -03:00
#[cfg(not(target_vendor = "win7"))]
// Use raw-dylib to import synchronization functions to workaround issues with the older mingw import library.
#[cfg_attr(
target_arch = "x86",
link(
name = "api-ms-win-core-synch-l1-2-0",
kind = "raw-dylib",
import_name_type = "undecorated"
)
)]
#[cfg_attr(
not(target_arch = "x86"),
link(name = "api-ms-win-core-synch-l1-2-0", kind = "raw-dylib")
)]
2024-02-19 19:17:29 -03:00
extern "system" {
pub fn WaitOnAddress(
address: *const c_void,
compareaddress: *const c_void,
addresssize: usize,
dwmilliseconds: u32,
) -> BOOL;
pub fn WakeByAddressSingle(address: *const c_void);
pub fn WakeByAddressAll(address: *const c_void);
2024-02-19 19:17:29 -03:00
}
#[cfg(target_vendor = "win7")]
compat_fn_optional! {
crate::sys::compat::load_synch_functions();
pub fn WaitOnAddress(
2023-04-05 02:05:37 +01:00
address: *const ::core::ffi::c_void,
compareaddress: *const ::core::ffi::c_void,
addresssize: usize,
dwmilliseconds: u32
) -> BOOL;
pub fn WakeByAddressSingle(address: *const ::core::ffi::c_void);
}
2024-02-19 19:17:29 -03:00
#[cfg(any(target_vendor = "win7", target_vendor = "uwp"))]
compat_fn_with_fallback! {
2023-12-03 14:24:25 +03:00
pub static NTDLL: &CStr = c"ntdll";
2024-02-19 19:17:29 -03:00
#[cfg(target_vendor = "win7")]
pub fn NtCreateKeyedEvent(
2024-02-19 19:17:29 -03:00
KeyedEventHandle: *mut HANDLE,
DesiredAccess: DWORD,
ObjectAttributes: LPVOID,
Flags: ULONG
) -> NTSTATUS {
panic!("keyed events not available")
}
2024-02-19 19:17:29 -03:00
#[cfg(target_vendor = "win7")]
pub fn NtReleaseKeyedEvent(
EventHandle: HANDLE,
Key: LPVOID,
Alertable: BOOLEAN,
2024-02-19 19:17:29 -03:00
Timeout: *mut c_longlong
) -> NTSTATUS {
panic!("keyed events not available")
}
2024-02-19 19:17:29 -03:00
#[cfg(target_vendor = "win7")]
pub fn NtWaitForKeyedEvent(
EventHandle: HANDLE,
Key: LPVOID,
Alertable: BOOLEAN,
2024-02-19 19:17:29 -03:00
Timeout: *mut c_longlong
) -> NTSTATUS {
panic!("keyed events not available")
}
2023-06-10 16:30:26 +08:00
// These functions are available on UWP when lazily loaded. They will fail WACK if loaded statically.
#[cfg(target_vendor = "uwp")]
pub fn NtCreateFile(
filehandle: *mut HANDLE,
desiredaccess: FILE_ACCESS_RIGHTS,
objectattributes: *const OBJECT_ATTRIBUTES,
iostatusblock: *mut IO_STATUS_BLOCK,
allocationsize: *const i64,
fileattributes: FILE_FLAGS_AND_ATTRIBUTES,
shareaccess: FILE_SHARE_MODE,
createdisposition: NTCREATEFILE_CREATE_DISPOSITION,
createoptions: NTCREATEFILE_CREATE_OPTIONS,
eabuffer: *const ::core::ffi::c_void,
ealength: u32
) -> NTSTATUS {
STATUS_NOT_IMPLEMENTED
}
#[cfg(target_vendor = "uwp")]
pub fn NtReadFile(
filehandle: BorrowedHandle<'_>,
event: HANDLE,
apcroutine: PIO_APC_ROUTINE,
apccontext: *mut c_void,
iostatusblock: &mut IO_STATUS_BLOCK,
buffer: *mut crate::mem::MaybeUninit<u8>,
length: ULONG,
2024-07-14 06:32:22 +00:00
byteoffset: Option<&i64>,
2023-06-10 16:30:26 +08:00
key: Option<&ULONG>
) -> NTSTATUS {
STATUS_NOT_IMPLEMENTED
}
#[cfg(target_vendor = "uwp")]
pub fn NtWriteFile(
filehandle: BorrowedHandle<'_>,
event: HANDLE,
apcroutine: PIO_APC_ROUTINE,
apccontext: *mut c_void,
iostatusblock: &mut IO_STATUS_BLOCK,
buffer: *const u8,
length: ULONG,
2024-07-14 06:32:22 +00:00
byteoffset: Option<&i64>,
2023-06-10 16:30:26 +08:00
key: Option<&ULONG>
) -> NTSTATUS {
STATUS_NOT_IMPLEMENTED
}
#[cfg(target_vendor = "uwp")]
pub fn RtlNtStatusToDosError(Status: NTSTATUS) -> u32 {
Status as u32
2023-06-10 16:30:26 +08:00
}
}
2023-06-24 17:30:27 +01:00
// # Arm32 shim
//
// AddVectoredExceptionHandler and WSAStartup use platform-specific types.
// However, Microsoft no longer supports thumbv7a so definitions for those targets
// are not included in the win32 metadata. We work around that by defining them here.
//
// Where possible, these definitions should be kept in sync with https://docs.rs/windows-sys
cfg_if::cfg_if! {
if #[cfg(not(target_vendor = "uwp"))] {
#[link(name = "kernel32")]
extern "system" {
pub fn AddVectoredExceptionHandler(
first: u32,
handler: PVECTORED_EXCEPTION_HANDLER,
) -> *mut c_void;
}
pub type PVECTORED_EXCEPTION_HANDLER = Option<
unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32,
>;
#[repr(C)]
pub struct EXCEPTION_POINTERS {
pub ExceptionRecord: *mut EXCEPTION_RECORD,
pub ContextRecord: *mut CONTEXT,
}
#[cfg(target_arch = "arm")]
pub enum CONTEXT {}
}}
2024-07-04 12:09:25 +00:00
// WSAStartup is only redefined here so that we can override WSADATA for Arm32
windows_targets::link!("ws2_32.dll" "system" fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32);
2023-06-24 17:30:27 +01:00
#[cfg(target_arch = "arm")]
#[repr(C)]
pub struct WSADATA {
pub wVersion: u16,
pub wHighVersion: u16,
pub szDescription: [u8; 257],
pub szSystemStatus: [u8; 129],
pub iMaxSockets: u16,
pub iMaxUdpDg: u16,
pub lpVendorInfo: PSTR,
}