diff --git a/.travis.yml b/.travis.yml index 55502d412477..dc0903ef44c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,7 @@ branches: only: - master - /\Arelease\/.+\z/ + - /^win\W/ notifications: irc: channels: diff --git a/src/callstack.cr b/src/callstack.cr index 28dd04cd7783..0a516e33717a 100644 --- a/src/callstack.cr +++ b/src/callstack.cr @@ -1,4 +1,6 @@ -require "c/dlfcn" +{% if !flag?(:windows) %} + require "c/dlfcn" +{% end %} require "c/stdio" require "c/string" require "callstack/lib_unwind" @@ -389,16 +391,19 @@ struct CallStack {% end %} protected def self.decode_frame(ip, original_ip = ip) - if LibC.dladdr(ip, out info) != 0 - offset = original_ip - info.dli_saddr + {% if flag?(:windows) %} + {% else %} + if LibC.dladdr(ip, out info) != 0 + offset = original_ip - info.dli_saddr - if offset == 0 - return decode_frame(ip - 1, original_ip) - end + if offset == 0 + return decode_frame(ip - 1, original_ip) + end - unless info.dli_sname.null? - {offset, info.dli_sname} + unless info.dli_sname.null? + {offset, info.dli_sname} + end end - end + {% end %} end end diff --git a/src/concurrent.cr b/src/concurrent.cr index fb52a3a46335..5cf400f045be 100644 --- a/src/concurrent.cr +++ b/src/concurrent.cr @@ -1,5 +1,8 @@ require "fiber" -require "./concurrent/*" +require "./concurrent/channel" +require "./concurrent/error" +require "./concurrent/future" +require "./concurrent/scheduler" # Blocks the current fiber for the specified number of seconds. # diff --git a/src/concurrent/scheduler.cr b/src/concurrent/scheduler.cr index 51228be6a555..ff25d4a79332 100644 --- a/src/concurrent/scheduler.cr +++ b/src/concurrent/scheduler.cr @@ -1,89 +1,5 @@ -require "event" - -# :nodoc: -class Scheduler - @@runnables = Deque(Fiber).new - @@eb = Event::Base.new - - def self.reschedule - if runnable = @@runnables.shift? - runnable.resume - else - loop_fiber.resume - end - nil - end - - def self.loop_fiber - @@loop_fiber ||= Fiber.new { @@eb.run_loop } - end - - def self.after_fork - @@eb.reinit - end - - def self.create_resume_event(fiber) - @@eb.new_event(-1, LibEvent2::EventFlags::None, fiber) do |s, flags, data| - data.as(Fiber).resume - end - end - - def self.create_fd_write_event(io : IO::FileDescriptor, edge_triggered : Bool = false) - flags = LibEvent2::EventFlags::Write - flags |= LibEvent2::EventFlags::Persist | LibEvent2::EventFlags::ET if edge_triggered - event = @@eb.new_event(io.fd, flags, io) do |s, flags, data| - fd_io = data.as(IO::FileDescriptor) - if flags.includes?(LibEvent2::EventFlags::Write) - fd_io.resume_write - elsif flags.includes?(LibEvent2::EventFlags::Timeout) - fd_io.write_timed_out = true - fd_io.resume_write - end - end - event - end - - def self.create_fd_read_event(io : IO::FileDescriptor, edge_triggered : Bool = false) - flags = LibEvent2::EventFlags::Read - flags |= LibEvent2::EventFlags::Persist | LibEvent2::EventFlags::ET if edge_triggered - event = @@eb.new_event(io.fd, flags, io) do |s, flags, data| - fd_io = data.as(IO::FileDescriptor) - if flags.includes?(LibEvent2::EventFlags::Read) - fd_io.resume_read - elsif flags.includes?(LibEvent2::EventFlags::Timeout) - fd_io.read_timed_out = true - fd_io.resume_read - end - end - event - end - - def self.create_signal_event(signal : Signal, chan) - flags = LibEvent2::EventFlags::Signal | LibEvent2::EventFlags::Persist - event = @@eb.new_event(Int32.new(signal.to_i), flags, chan) do |s, flags, data| - ch = data.as(Channel::Buffered(Signal)) - sig = Signal.new(s) - ch.send sig - end - event.add - event - end - - @@dns_base : Event::DnsBase? - - private def self.dns_base - @@dns_base ||= @@eb.new_dns_base - end - - def self.create_dns_request(nodename, servname, hints, data, &callback : LibEvent2::DnsGetAddrinfoCallback) - dns_base.getaddrinfo(nodename, servname, hints, data, &callback) - end - - def self.enqueue(fiber : Fiber) - @@runnables << fiber - end - - def self.enqueue(fibers : Enumerable(Fiber)) - @@runnables.concat fibers - end -end +{% if flag?(:windows) %} + require "./scheduler.windows.cr" +{% else %} + require "./scheduler.posix.cr" +{% end %} diff --git a/src/concurrent/scheduler.posix.cr b/src/concurrent/scheduler.posix.cr new file mode 100644 index 000000000000..51228be6a555 --- /dev/null +++ b/src/concurrent/scheduler.posix.cr @@ -0,0 +1,89 @@ +require "event" + +# :nodoc: +class Scheduler + @@runnables = Deque(Fiber).new + @@eb = Event::Base.new + + def self.reschedule + if runnable = @@runnables.shift? + runnable.resume + else + loop_fiber.resume + end + nil + end + + def self.loop_fiber + @@loop_fiber ||= Fiber.new { @@eb.run_loop } + end + + def self.after_fork + @@eb.reinit + end + + def self.create_resume_event(fiber) + @@eb.new_event(-1, LibEvent2::EventFlags::None, fiber) do |s, flags, data| + data.as(Fiber).resume + end + end + + def self.create_fd_write_event(io : IO::FileDescriptor, edge_triggered : Bool = false) + flags = LibEvent2::EventFlags::Write + flags |= LibEvent2::EventFlags::Persist | LibEvent2::EventFlags::ET if edge_triggered + event = @@eb.new_event(io.fd, flags, io) do |s, flags, data| + fd_io = data.as(IO::FileDescriptor) + if flags.includes?(LibEvent2::EventFlags::Write) + fd_io.resume_write + elsif flags.includes?(LibEvent2::EventFlags::Timeout) + fd_io.write_timed_out = true + fd_io.resume_write + end + end + event + end + + def self.create_fd_read_event(io : IO::FileDescriptor, edge_triggered : Bool = false) + flags = LibEvent2::EventFlags::Read + flags |= LibEvent2::EventFlags::Persist | LibEvent2::EventFlags::ET if edge_triggered + event = @@eb.new_event(io.fd, flags, io) do |s, flags, data| + fd_io = data.as(IO::FileDescriptor) + if flags.includes?(LibEvent2::EventFlags::Read) + fd_io.resume_read + elsif flags.includes?(LibEvent2::EventFlags::Timeout) + fd_io.read_timed_out = true + fd_io.resume_read + end + end + event + end + + def self.create_signal_event(signal : Signal, chan) + flags = LibEvent2::EventFlags::Signal | LibEvent2::EventFlags::Persist + event = @@eb.new_event(Int32.new(signal.to_i), flags, chan) do |s, flags, data| + ch = data.as(Channel::Buffered(Signal)) + sig = Signal.new(s) + ch.send sig + end + event.add + event + end + + @@dns_base : Event::DnsBase? + + private def self.dns_base + @@dns_base ||= @@eb.new_dns_base + end + + def self.create_dns_request(nodename, servname, hints, data, &callback : LibEvent2::DnsGetAddrinfoCallback) + dns_base.getaddrinfo(nodename, servname, hints, data, &callback) + end + + def self.enqueue(fiber : Fiber) + @@runnables << fiber + end + + def self.enqueue(fibers : Enumerable(Fiber)) + @@runnables.concat fibers + end +end diff --git a/src/concurrent/scheduler.windows.cr b/src/concurrent/scheduler.windows.cr new file mode 100644 index 000000000000..a18a04b8e9d7 --- /dev/null +++ b/src/concurrent/scheduler.windows.cr @@ -0,0 +1,138 @@ +require "event" + +# :nodoc: +class Scheduler + @@runnables = Deque(Fiber).new + @@timers = Hash(Fiber, LibWindows::Handle).new + + def self.reschedule + if runnable = @@runnables.shift? + runnable.resume + else + loop_fiber.resume + end + nil + end + + def self.completion_port + completion_port = @@completion_port ||= LibWindows.create_io_completion_port(LibWindows::INVALID_HANDLE_VALUE, nil, nil, 0) + if completion_port.null? + raise WinError.new("CreateIoCompletionPort") + end + completion_port + end + + def self.attach_to_completion_port(handle, fd) : Bool + if LibWindows.create_io_completion_port(handle, Scheduler.completion_port, fd.as(Void*), 0).null? + if LibWindows.get_last_error == WinError::ERROR_INVALID_PARAMETER + # It is allowed to fail if the handle doesn't have FILE_FLAG_OVERLAPPED. + # But better check before calling. How to check for if the flag is set on the handle? + return false + end + + raise WinError.new("CreateIoCompletionPort") + end + true + end + + def self.loop_fiber + @@loop_fiber ||= Fiber.new do + loop do + bytes_transfered = 0u32 + data = Pointer(Void).null + entry = uninitialized LibWindows::Overlapped* + if LibWindows.get_queued_completion_status(Scheduler.completion_port, pointerof(bytes_transfered), pointerof(data), pointerof(entry), LibWindows::INFINITY) + if entry.null? + # It is just a fiber wanting to be resumed + fiber = data.as(Fiber) + if timer_handle = @@timers[fiber]? + unless LibWindows.delete_timer_queue_timer(nil, timer_handle, nil) + error = WinError.new "DeleteTimerQueueTimer" + raise error if error.code != WinError::ERROR_IO_PENDING && error.code != WinError::ERROR_SUCCESS + end + @@timers.delete(fiber) + end + fiber.resume + else + fd = data.as(IO::FileDescriptor) + fd.resume_overlapped entry + end + end + end + end + end + + def self.create_resume_event(fiber) + unless LibWindows.post_queued_completion_status(Scheduler.completion_port, 0, fiber.as(Void*), nil) + raise WinError.new "PostQueueCompletionStatus" + end + end + + def self.create_sleep_event(fiber, seconds) + LibWindows.create_timer_queue_timer(out handle, nil, ->(data, fired) { + # this is run inside a thread from a pool managed by the system + Scheduler.create_resume_event(data.as(Fiber)) + }, fiber.as(Void*), (seconds*1000).to_u32, 0, 0) + + @@timers[fiber] = handle + end + + # def self.create_fd_write_event(io : IO::FileDescriptor, edge_triggered : Bool = false) + # flags = LibEvent2::EventFlags::Write + # flags |= LibEvent2::EventFlags::Persist | LibEvent2::EventFlags::ET if edge_triggered + # event = @@eb.new_event(io.fd, flags, io) do |s, flags, data| + # fd_io = data.as(IO::FileDescriptor) + # if flags.includes?(LibEvent2::EventFlags::Write) + # fd_io.resume_write + # elsif flags.includes?(LibEvent2::EventFlags::Timeout) + # fd_io.write_timed_out = true + # fd_io.resume_write + # end + # end + # event + # end + + # def self.create_fd_read_event(io : IO::FileDescriptor, edge_triggered : Bool = false) + # flags = LibEvent2::EventFlags::Read + # flags |= LibEvent2::EventFlags::Persist | LibEvent2::EventFlags::ET if edge_triggered + # event = @@eb.new_event(io.fd, flags, io) do |s, flags, data| + # fd_io = data.as(IO::FileDescriptor) + # if flags.includes?(LibEvent2::EventFlags::Read) + # fd_io.resume_read + # elsif flags.includes?(LibEvent2::EventFlags::Timeout) + # fd_io.read_timed_out = true + # fd_io.resume_read + # end + # end + # event + # end + + # def self.create_signal_event(signal : Signal, chan) + # flags = LibEvent2::EventFlags::Signal | LibEvent2::EventFlags::Persist + # event = @@eb.new_event(Int32.new(signal.to_i), flags, chan) do |s, flags, data| + # ch = data.as(Channel::Buffered(Signal)) + # sig = Signal.new(s) + # ch.send sig + # end + # event.add + # event + # end + + # @@dns_base : Event::DnsBase? + + # private def self.dns_base + # @@dns_base ||= @@eb.new_dns_base + # end + + # def self.create_dns_request(nodename, servname, hints, data, &callback : LibEvent2::DnsGetAddrinfoCallback) + # dns_base.getaddrinfo(nodename, servname, hints, data, &callback) + # end + + def self.enqueue(fiber : Fiber) + @@runnables << fiber + end + + def self.enqueue(fibers : Enumerable(Fiber)) + @@runnables.concat fibers + end +end diff --git a/src/docs_main.cr b/src/docs_main.cr index 05959374614d..e91683ee7714 100644 --- a/src/docs_main.cr +++ b/src/docs_main.cr @@ -13,7 +13,7 @@ require "./fiber" require "./gc/**" require "./html" require "./http/**" -require "./io/**" +require "./io" require "./json" require "./llvm" require "./logger" diff --git a/src/event/lib_event2.cr b/src/event/lib_event2.cr index cccc01b48638..0c09be850474 100644 --- a/src/event/lib_event2.cr +++ b/src/event/lib_event2.cr @@ -1,4 +1,9 @@ -require "c/netdb" +require "c/time" +{% if flag?(:windows) %} + require "lib_windows" +{% else %} + require "c/netdb" +{% end %} {% if flag?(:linux) %} @[Link("rt")] @@ -14,7 +19,7 @@ lib LibEvent2 alias Int = LibC::Int {% if flag?(:windows) %} - # TODO + alias EvutilSocketT = LibWindows::DWord {% else %} alias EvutilSocketT = Int {% end %} @@ -58,11 +63,11 @@ lib LibEvent2 EVUTIL_EAI_CANCEL = -90001 - alias DnsGetAddrinfoCallback = (Int32, LibC::Addrinfo*, Void*) -> + # alias DnsGetAddrinfoCallback = (Int32, LibC::Addrinfo*, Void*) -> - fun evdns_base_new(base : EventBase, init : Int32) : DnsBase - fun evdns_base_free(base : DnsBase, fail_requests : Int32) - fun evdns_getaddrinfo(base : DnsBase, nodename : UInt8*, servname : UInt8*, hints : LibC::Addrinfo*, cb : DnsGetAddrinfoCallback, arg : Void*) : DnsGetAddrinfoRequest - fun evdns_getaddrinfo_cancel(DnsGetAddrinfoRequest) - fun evutil_freeaddrinfo(ai : LibC::Addrinfo*) + # fun evdns_base_new(base : EventBase, init : Int32) : DnsBase + # fun evdns_base_free(base : DnsBase, fail_requests : Int32) + # fun evdns_getaddrinfo(base : DnsBase, nodename : UInt8*, servname : UInt8*, hints : LibC::Addrinfo*, cb : DnsGetAddrinfoCallback, arg : Void*) : DnsGetAddrinfoRequest + # fun evdns_getaddrinfo_cancel(DnsGetAddrinfoRequest) + # fun evutil_freeaddrinfo(ai : LibC::Addrinfo*) end diff --git a/src/event/signal_child_handler.cr b/src/event/signal_child_handler.cr index 694a03386879..085cb8e53662 100644 --- a/src/event/signal_child_handler.cr +++ b/src/event/signal_child_handler.cr @@ -1,4 +1,6 @@ -require "c/sys/wait" +{% if !flag?(:windows) %} + require "c/sys/wait" +{% end %} # :nodoc: # Singleton that handles `SIG_CHLD` and queues events for `Process#waitpid`. diff --git a/src/event/signal_handler.cr b/src/event/signal_handler.cr index 857a2bea9701..cd483c7e53d9 100644 --- a/src/event/signal_handler.cr +++ b/src/event/signal_handler.cr @@ -1,5 +1,7 @@ -require "c/signal" -require "c/unistd" +{% if !flag?(:windows) %} + require "c/signal" + require "c/unistd" +{% end %} # :nodoc: # Singleton that runs Signal events (libevent2) in it's own Fiber. diff --git a/src/fiber.cr b/src/fiber.cr index f34140256f7e..77d46c824473 100644 --- a/src/fiber.cr +++ b/src/fiber.cr @@ -1,4 +1,6 @@ -require "c/sys/mman" +{% if !flag?(:windows) %} + require "c/sys/mman" +{% end %} # :nodoc: @[NoInline] @@ -15,7 +17,6 @@ class Fiber @@stack_pool = [] of Void* @stack : Void* - @resume_event : Event::Event? @stack_top = uninitialized Void* protected property stack_top : Void* protected property stack_bottom : Void* @@ -23,18 +24,35 @@ class Fiber protected property prev_fiber : Fiber? property name : String? + {% if !flag?(:windows) %} + @resume_event : Event::Event? + {% end %} + def initialize(@name : String? = nil, &@proc : ->) @stack = Fiber.allocate_stack @stack_bottom = @stack + STACK_SIZE fiber_main = ->(f : Fiber) { f.run } + stack_ptr = nil + {% if flag?(:windows) %} + # It's the caller's responsibility to allocate 32 bytes of "shadow space" on the stack right + # before calling the function (regardless of the actual number of parameters used) + stack_ptr = @stack + STACK_SIZE - sizeof(Void*) * 4 + {% else %} stack_ptr = @stack + STACK_SIZE - sizeof(Void*) + {% end %} # Align the stack pointer to 16 bytes stack_ptr = Pointer(Void*).new(stack_ptr.address & ~0x0f_u64) # @stack_top will be the stack pointer on the initial call to `resume` - {% if flag?(:x86_64) %} + {% if flag?(:x86_64) && flag?(:windows) %} + # In x86-64, the context switch push/pop 9 registers + @stack_top = (stack_ptr - 9).as(Void*) + + stack_ptr[0] = fiber_main.pointer # Initial `resume` will `ret` to this address + stack_ptr[-1] = self.as(Void*) # This will be `pop` into %rcx (first argument) + {% elsif flag?(:x86_64) %} # In x86-64, the context switch push/pop 7 registers @stack_top = (stack_ptr - 7).as(Void*) @@ -90,16 +108,20 @@ class Fiber end protected def self.allocate_stack - @@stack_pool.pop? || LibC.mmap(nil, Fiber::STACK_SIZE, + {% if flag?(:windows) %} + @@stack_pool.pop? || LibC.malloc(Fiber::STACK_SIZE) + {% else %} + @@stack_pool.pop? || LibC.mmap(nil, Fiber::STACK_SIZE, LibC::PROT_READ | LibC::PROT_WRITE, LibC::MAP_PRIVATE | LibC::MAP_ANON, -1, 0).tap do |pointer| - raise Errno.new("Cannot allocate new fiber stack") if pointer == LibC::MAP_FAILED - {% if flag?(:linux) %} - LibC.madvise(pointer, Fiber::STACK_SIZE, LibC::MADV_NOHUGEPAGE) - {% end %} - LibC.mprotect(pointer, 4096, LibC::PROT_NONE) - end + raise Errno.new("Cannot allocate new fiber stack") if pointer == LibC::MAP_FAILED + {% if flag?(:linux) %} + LibC.madvise(pointer, Fiber::STACK_SIZE, LibC::MADV_NOHUGEPAGE) + {% end %} + LibC.mprotect(pointer, 4096, LibC::PROT_NONE) + end + {% end %} end def self.stack_pool_collect @@ -107,7 +129,11 @@ class Fiber free_count = @@stack_pool.size > 1 ? @@stack_pool.size / 2 : 1 free_count.times do stack = @@stack_pool.pop - LibC.munmap(stack, Fiber::STACK_SIZE) + {% if flag?(:windows) %} + + {% else %} + LibC.munmap(stack, Fiber::STACK_SIZE) + {% end %} end end @@ -115,12 +141,12 @@ class Fiber @proc.call rescue ex if name = @name - STDERR.puts "Unhandled exception in spawn(name: #{name}):" + # STDERR.puts "Unhandled exception in spawn(name: #{name}):" else - STDERR.puts "Unhandled exception in spawn:" + # STDERR.puts "Unhandled exception in spawn:" end - ex.inspect_with_backtrace STDERR - STDERR.flush + # ex.inspect_with_backtrace STDERR + # STDERR.flush ensure @@stack_pool << @stack @@ -137,8 +163,10 @@ class Fiber @@last_fiber = @prev_fiber end - # Delete the resume event if it was used by `yield` or `sleep` - @resume_event.try &.free + {% if !flag?(:windows) %} + # Delete the resume event if it was used by `yield` or `sleep` + @resume_event.try &.free + {% end %} Scheduler.reschedule end @@ -146,7 +174,30 @@ class Fiber @[NoInline] @[Naked] protected def self.switch_stacks(current, to) : Nil - {% if flag?(:x86_64) %} + {% if flag?(:x86_64) && flag?(:windows) %} + asm(" + pushq %rcx + pushq %rdi + pushq %rbx + pushq %rbp + pushq %rsi + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + movq %rsp, ($0) + movq ($1), %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rsi + popq %rbp + popq %rbx + popq %rdi + popq %rcx" + :: "r"(current), "r"(to)) + {% elsif flag?(:x86_64) %} asm(" pushq %rdi pushq %rbx @@ -265,13 +316,22 @@ class Fiber end def sleep(time) - event = @resume_event ||= Scheduler.create_resume_event(self) - event.add(time) + {% if flag?(:windows) %} + Scheduler.create_sleep_event(self, time) + {% else %} + event = @resume_event ||= Scheduler.create_resume_event(self) + event.add(time) + {% end %} Scheduler.reschedule end def yield - sleep(0) + {% if flag?(:windows) %} + Scheduler.create_resume_event(self) + Scheduler.reschedule + {% else %} + sleep(0) + {% end %} end def self.sleep(time) diff --git a/src/file.cr b/src/file.cr index b67b0c7c98fe..ba00177e190c 100644 --- a/src/file.cr +++ b/src/file.cr @@ -1,659 +1,9 @@ -require "c/fcntl" -require "c/stdio" -require "c/stdlib" -require "c/sys/stat" -require "c/unistd" - -class File < IO::FileDescriptor - # The file/directory separator character. `'/'` in Unix, `'\\'` in Windows. - SEPARATOR = {% if flag?(:windows) %} - '\\' - {% else %} - '/' - {% end %} - - # The file/directory separator string. `"/"` in Unix, `"\\"` in Windows. - SEPARATOR_STRING = {% if flag?(:windows) %} - "\\" - {% else %} - "/" - {% end %} - - # :nodoc: - DEFAULT_CREATE_MODE = LibC::S_IRUSR | LibC::S_IWUSR | LibC::S_IRGRP | LibC::S_IROTH - - def initialize(filename : String, mode = "r", perm = DEFAULT_CREATE_MODE, encoding = nil, invalid = nil) - oflag = open_flag(mode) | LibC::O_CLOEXEC - - fd = LibC.open(filename.check_no_null_byte, oflag, perm) - if fd < 0 - raise Errno.new("Error opening file '#{filename}' with mode '#{mode}'") - end - - @path = filename - self.set_encoding(encoding, invalid: invalid) if encoding - super(fd, blocking: true) - end - - protected def open_flag(mode) - if mode.size == 0 - raise "Invalid access mode #{mode}" - end - - m = 0 - o = 0 - case mode[0] - when 'r' - m = LibC::O_RDONLY - when 'w' - m = LibC::O_WRONLY - o = LibC::O_CREAT | LibC::O_TRUNC - when 'a' - m = LibC::O_WRONLY - o = LibC::O_CREAT | LibC::O_APPEND - else - raise "Invalid access mode #{mode}" - end - - case mode.size - when 1 - # Nothing - when 2 - case mode[1] - when '+' - m = LibC::O_RDWR - when 'b' - # Nothing - else - raise "Invalid access mode #{mode}" - end - else - raise "Invalid access mode #{mode}" - end - - oflag = m | o - end - - getter path : String - - # Returns a `File::Stat` object for the file given by *path* or raises - # `Errno` in case of an error. In case of a symbolic link - # it is followed and information about the target is returned. - # - # ``` - # File.write("foo", "foo") - # File.stat("foo").size # => 3 - # File.stat("foo").mtime # => 2015-09-23 06:24:19 UTC - # ``` - def self.stat(path) : Stat - if LibC.stat(path.check_no_null_byte, out stat) != 0 - raise Errno.new("Unable to get stat for '#{path}'") - end - Stat.new(stat) - end - - # Returns a `File::Stat` object for the file given by *path* or raises - # `Errno` in case of an error. In case of a symbolic link - # information about it is returned. - # - # ``` - # File.write("foo", "foo") - # File.lstat("foo").size # => 3 - # File.lstat("foo").mtime # => 2015-09-23 06:24:19 UTC - # ``` - def self.lstat(path) : Stat - if LibC.lstat(path.check_no_null_byte, out stat) != 0 - raise Errno.new("Unable to get lstat for '#{path}'") - end - Stat.new(stat) - end - - # Returns `true` if *path* exists else returns `false` - # - # ``` - # File.delete("foo") if File.exists?("foo") - # File.exists?("foo") # => false - # File.write("foo", "foo") - # File.exists?("foo") # => true - # ``` - def self.exists?(path) : Bool - accessible?(path, LibC::F_OK) - end - - # Returns `true` if the file at *path* is empty, otherwise returns `false`. - # Raises `Errno` if the file at *path* does not exist. - # - # ``` - # File.write("foo", "") - # File.empty?("foo") # => true - # File.write("foo", "foo") - # File.empty?("foo") # => false - # ``` - def self.empty?(path) : Bool - begin - stat(path).size == 0 - rescue Errno - raise Errno.new("Error determining size of '#{path}'") - end - end - - # Returns `true` if *path* is readable by the real user id of this process else returns `false`. - # - # ``` - # File.write("foo", "foo") - # File.readable?("foo") # => true - # ``` - def self.readable?(path) : Bool - accessible?(path, LibC::R_OK) - end - - # Returns `true` if *path* is writable by the real user id of this process else returns `false`. - # - # ``` - # File.write("foo", "foo") - # File.writable?("foo") # => true - # ``` - def self.writable?(path) : Bool - accessible?(path, LibC::W_OK) - end - - # Returns `true` if *path* is executable by the real user id of this process else returns `false`. - # - # ``` - # File.write("foo", "foo") - # File.executable?("foo") # => false - # ``` - def self.executable?(path) : Bool - accessible?(path, LibC::X_OK) - end - - # Convenience method to avoid code on LibC.access calls. Not meant to be called by users of this class. - private def self.accessible?(path, flag) - LibC.access(path.check_no_null_byte, flag) == 0 - end - - # Returns `true` if given *path* exists and is a file. - # - # ``` - # File.write("foo", "") - # Dir.mkdir("dir1") - # File.file?("foo") # => true - # File.file?("dir1") # => false - # File.file?("foobar") # => false - # ``` - def self.file?(path) : Bool - if LibC.stat(path.check_no_null_byte, out stat) != 0 - if Errno.value == Errno::ENOENT - return false - else - raise Errno.new("stat") - end - end - File::Stat.new(stat).file? - end - - # Returns `true` if the given *path* exists and is a directory. - # - # ``` - # File.write("foo", "") - # Dir.mkdir("dir2") - # File.directory?("foo") # => false - # File.directory?("dir2") # => true - # File.directory?("foobar") # => false - # ``` - def self.directory?(path) : Bool - Dir.exists?(path) - end - - # Returns all components of the given *path* except the last one. - # - # ``` - # File.dirname("/foo/bar/file.cr") # => "/foo/bar" - # ``` - def self.dirname(path) : String - path.check_no_null_byte - index = path.rindex SEPARATOR - if index - if index == 0 - SEPARATOR_STRING - else - path[0, index] - end - else - "." - end - end - - # Returns the last component of the given *path*. - # - # ``` - # File.basename("/foo/bar/file.cr") # => "file.cr" - # ``` - def self.basename(path) : String - return "" if path.bytesize == 0 - return SEPARATOR_STRING if path == SEPARATOR_STRING - - path.check_no_null_byte - - last = path.size - 1 - last -= 1 if path[last] == SEPARATOR - - index = path.rindex SEPARATOR, last - if index - path[index + 1, last - index] - else - path - end - end - - # Returns the last component of the given *path*. - # - # If *suffix* is present at the end of *path*, it is removed. - # - # ``` - # File.basename("/foo/bar/file.cr", ".cr") # => "file" - # ``` - def self.basename(path, suffix) : String - suffix.check_no_null_byte - basename(path).chomp(suffix) - end - - # Changes the owner of the specified file. - # - # ``` - # File.chown("/foo/bar/baz.cr", 1001, 100) - # File.chown("/foo/bar", gid: 100) - # ``` - # - # Unless *follow_symlinks* is set to `true`, then the owner symlink itself will - # be changed, otherwise the owner of the symlink destination file will be - # changed. For example, assuming symlinks as `foo -> bar -> baz`: - # - # ``` - # File.chown("foo", gid: 100) # changes foo's gid - # File.chown("foo", gid: 100, follow_symlinks: true) # changes baz's gid - # ``` - def self.chown(path, uid : Int? = -1, gid : Int = -1, follow_symlinks = false) - ret = if !follow_symlinks && symlink?(path) - LibC.lchown(path, uid, gid) - else - LibC.chown(path, uid, gid) - end - raise Errno.new("Error changing owner of '#{path}'") if ret == -1 - end - - # Changes the permissions of the specified file. - # - # Symlinks are dereferenced, so that only the permissions of the symlink - # destination are changed, never the permissions of the symlink itself. - # - # ``` - # File.chmod("foo", 0o755) - # File.stat("foo").perm # => 0o755 - # - # File.chmod("foo", 0o700) - # File.stat("foo").perm # => 0o700 - # ``` - def self.chmod(path, mode : Int) - if LibC.chmod(path, mode) == -1 - raise Errno.new("Error changing permissions of '#{path}'") - end - end - - # Delete the file at *path*. Deleting non-existent file will raise an exception. - # - # ``` - # File.write("foo", "") - # File.delete("./foo") - # File.delete("./bar") # raises Errno (No such file or directory) - # ``` - def self.delete(path) - err = LibC.unlink(path.check_no_null_byte) - if err == -1 - raise Errno.new("Error deleting file '#{path}'") - end - end - - # Returns *filename*'s extension, or an empty string if it has no extension. - # - # ``` - # File.extname("foo.cr") # => ".cr" - # ``` - def self.extname(filename) : String - filename.check_no_null_byte - - dot_index = filename.rindex('.') - - if dot_index && dot_index != filename.size - 1 && filename[dot_index - 1] != SEPARATOR - filename[dot_index, filename.size - dot_index] - else - "" - end - end - - # Converts *path* to an absolute path. Relative paths are - # referenced from the current working directory of the process unless - # *dir* is given, in which case it will be used as the starting point. - # - # ``` - # File.expand_path("foo") # => "/home/.../foo" - # File.expand_path("~/crystal/foo") # => "/home/crystal/foo" - # File.expand_path("baz", "/foo/bar") # => "/foo/bar/baz" - # ``` - def self.expand_path(path, dir = nil) : String - path.check_no_null_byte - - if path.starts_with?('~') - home = ENV["HOME"] - home = home.chomp('/') unless home == "/" - - if path.size >= 2 && path[1] == SEPARATOR - path = home + path[1..-1] - elsif path.size < 2 - return home - end - end - - unless path.starts_with?(SEPARATOR) - dir = dir ? expand_path(dir) : Dir.current - path = "#{dir}#{SEPARATOR}#{path}" - end - - parts = path.split(SEPARATOR) - items = [] of String - parts.each do |part| - case part - when "", "." - # Nothing - when ".." - items.pop? - else - items << part - end - end - - String.build do |str| - {% if !flag?(:windows) %} - str << SEPARATOR_STRING - {% end %} - items.join SEPARATOR_STRING, str - end - end - - # Resolves the real path of *path* by following symbolic links. - def self.real_path(path) : String - real_path_ptr = LibC.realpath(path, nil) - raise Errno.new("Error resolving real path of #{path}") unless real_path_ptr - String.new(real_path_ptr).tap { LibC.free(real_path_ptr.as(Void*)) } - end - - # Creates a new link (also known as a hard link) at *new_path* to an existing file - # given by *old_path*. - def self.link(old_path, new_path) - ret = LibC.link(old_path.check_no_null_byte, new_path.check_no_null_byte) - raise Errno.new("Error creating link from #{old_path} to #{new_path}") if ret != 0 - ret - end - - # Creates a symbolic link at *new_path* to an existing file given by *old_path. - def self.symlink(old_path, new_path) - ret = LibC.symlink(old_path.check_no_null_byte, new_path.check_no_null_byte) - raise Errno.new("Error creating symlink from #{old_path} to #{new_path}") if ret != 0 - ret - end - - # Returns `true` if the *path* is a symbolic link. - def self.symlink?(path) : Bool - if LibC.lstat(path.check_no_null_byte, out stat) != 0 - if Errno.value == Errno::ENOENT - return false - else - raise Errno.new("stat") - end - end - (stat.st_mode & LibC::S_IFMT) == LibC::S_IFLNK - end - - # Opens the file named by *filename*. If a file is being created, its initial - # permissions may be set using the *perm* parameter. - def self.open(filename, mode = "r", perm = DEFAULT_CREATE_MODE, encoding = nil, invalid = nil) : self - new filename, mode, perm, encoding, invalid - end - - # Opens the file named by *filename*. If a file is being created, its initial - # permissions may be set using the *perm* parameter. Then given block will be passed the opened - # file as an argument, the file will be automatically closed when the block returns. - def self.open(filename, mode = "r", perm = DEFAULT_CREATE_MODE, encoding = nil, invalid = nil) - file = File.new filename, mode, perm, encoding, invalid - begin - yield file - ensure - file.close - end - end - - # Returns the content of *filename* as a string. - # - # ``` - # File.write("bar", "foo") - # File.read("bar") # => "foo" - # ``` - def self.read(filename, encoding = nil, invalid = nil) : String - File.open(filename, "r") do |file| - if encoding - file.set_encoding(encoding, invalid: invalid) - file.gets_to_end - else - # We try to read a string with an initialize capacity - # equal to the file's size, but the size might not be - # correct or even be zero (for example for /proc files) - size = file.size.to_i - size = 256 if size == 0 - String.build(size) do |io| - IO.copy(file, io) - end - end - end - end - - # Yields each line in *filename* to the given block. - # - # ``` - # File.write("foobar", "foo\nbar") - # - # array = [] of String - # File.each_line("foobar") do |line| - # array << line - # end - # array # => ["foo", "bar"] - # ``` - def self.each_line(filename, encoding = nil, invalid = nil, chomp = true) - File.open(filename, "r", encoding: encoding, invalid: invalid) do |file| - file.each_line(chomp: chomp) do |line| - yield line - end - end - end - - # Returns an `Iterator` for each line in *filename*. - def self.each_line(filename, encoding = nil, invalid = nil, chomp = true) - File.open(filename, "r", encoding: encoding, invalid: invalid).each_line(chomp: chomp) - end - - # Returns all lines in *filename* as an array of strings. - # - # ``` - # File.write("foobar", "foo\nbar") - # File.read_lines("foobar") # => ["foo", "bar"] - # ``` - def self.read_lines(filename, encoding = nil, invalid = nil, chomp = true) : Array(String) - lines = [] of String - each_line(filename, encoding: encoding, invalid: invalid, chomp: chomp) do |line| - lines << line - end - lines - end - - # Write the given *content* to *filename*. - # - # An existing file will be overwritten, else a file will be created. - # - # ``` - # File.write("foo", "bar") - # ``` - # - # NOTE: If the content is a `Slice(UInt8)`, those bytes will be written. - # If it's an `IO`, all bytes from the `IO` will be written. - # Otherwise, the string representation of *content* will be written - # (the result of invoking `to_s` on *content*). - def self.write(filename, content, perm = DEFAULT_CREATE_MODE, encoding = nil, invalid = nil) - File.open(filename, "w", perm, encoding: encoding, invalid: invalid) do |file| - case content - when Bytes - file.write(content) - when IO - IO.copy(content, file) - else - file.print(content) - end - end - end - - # Returns a new string formed by joining the strings using `File::SEPARATOR`. - # - # ``` - # File.join("foo", "bar", "baz") # => "foo/bar/baz" - # File.join("foo/", "/bar/", "/baz") # => "foo/bar/baz" - # File.join("/foo/", "/bar/", "/baz/") # => "/foo/bar/baz/" - # ``` - def self.join(*parts) : String - join parts - end - - # Returns a new string formed by joining the strings using `File::SEPARATOR`. - # - # ``` - # File.join({"foo", "bar", "baz"}) # => "foo/bar/baz" - # File.join({"foo/", "/bar/", "/baz"}) # => "foo/bar/baz" - # File.join(["/foo/", "/bar/", "/baz/"]) # => "/foo/bar/baz/" - # ``` - def self.join(parts : Array | Tuple) : String - String.build do |str| - parts.each_with_index do |part, index| - part.check_no_null_byte - - str << SEPARATOR if index > 0 - - byte_start = 0 - byte_count = part.bytesize - - if index > 0 && part.starts_with?(SEPARATOR) - byte_start += 1 - byte_count -= 1 - end - - if index != parts.size - 1 && part.ends_with?(SEPARATOR) - byte_count -= 1 - end - - str.write part.unsafe_byte_slice(byte_start, byte_count) - end - end - end - - # Returns the size of *filename* bytes. - def self.size(filename) : UInt64 - stat(filename.check_no_null_byte).size - end - - # Moves *old_filename* to *new_filename*. - # - # ``` - # File.write("afile", "foo") - # File.exists?("afile") # => true - # - # File.rename("afile", "afile.cr") - # File.exists?("afile") # => false - # File.exists?("afile.cr") # => true - # ``` - def self.rename(old_filename, new_filename) - code = LibC.rename(old_filename.check_no_null_byte, new_filename.check_no_null_byte) - if code != 0 - raise Errno.new("Error renaming file '#{old_filename}' to '#{new_filename}'") - end - code - end - - # Sets the access and modification times of *filename*. - def self.utime(atime : Time, mtime : Time, filename : String) : Nil - timevals = uninitialized LibC::Timeval[2] - timevals[0] = to_timeval(atime) - timevals[1] = to_timeval(mtime) - ret = LibC.utimes(filename, timevals) - if ret != 0 - raise Errno.new("Error setting time to file '#{filename}'") - end - end - - # Attempts to set the access and modification times of the file named - # in the *filename* parameter to the value given in *time*. - # - # If the file does not exist, it will be created. - def self.touch(filename : String, time : Time = Time.now) - open(filename, "a") { } unless exists?(filename) - utime time, time, filename - end - - private def self.to_timeval(time : Time) - t = uninitialized LibC::Timeval - t.tv_sec = typeof(t.tv_sec).new(time.to_local.epoch) - t.tv_usec = typeof(t.tv_usec).new(0) - t - end - - # Return the size in bytes of the currently opened file. - def size - stat.size - end - - # Truncates the file to the specified *size*. Requires that the current file is opened - # for writing. - def truncate(size = 0) - flush - code = LibC.ftruncate(fd, size) - if code != 0 - raise Errno.new("Error truncating file '#{path}'") - end - code - end - - # Yields an `IO` to read a section inside this file. - # Mutliple sections can be read concurrently. - def read_at(offset, bytesize, &block) - self_bytesize = self.size - - unless 0 <= offset <= self_bytesize - raise ArgumentError.new("Offset out of bounds") - end - - if bytesize < 0 - raise ArgumentError.new("Negative bytesize") - end - - unless 0 <= offset + bytesize <= self_bytesize - raise ArgumentError.new("Bytesize out of bounds") - end - - io = PReader.new(fd, offset, bytesize) - yield io ensure io.close - end - - def inspect(io) - io << "#" - io - end -end - -require "./file/*" +{% if flag?(:windows) %} + require "./file.windows.cr" +{% else %} + require "./file.posix.cr" + require "file/flock.posix.cr" +{% end %} + +require "file/stat" +require "file/preader" diff --git a/src/file.posix.cr b/src/file.posix.cr new file mode 100644 index 000000000000..31eace310956 --- /dev/null +++ b/src/file.posix.cr @@ -0,0 +1,649 @@ +require "c/fcntl" +require "c/stdio" +require "c/stdlib" +require "c/sys/stat" +require "c/unistd" + +class File < IO::FileDescriptor + # The file/directory separator character. `'/'` in Unix, `'\\'` in Windows. + SEPARATOR = '/' + + # The file/directory separator string. `"/"` in Unix, `"\\"` in Windows. + SEPARATOR_STRING = "/" + + # :nodoc: + DEFAULT_CREATE_MODE = LibC::S_IRUSR | LibC::S_IWUSR | LibC::S_IRGRP | LibC::S_IROTH + + def initialize(filename : String, mode = "r", perm = DEFAULT_CREATE_MODE, encoding = nil, invalid = nil) + oflag = open_flag(mode) | LibC::O_CLOEXEC + + fd = LibC.open(filename.check_no_null_byte, oflag, perm) + if fd < 0 + raise Errno.new("Error opening file '#{filename}' with mode '#{mode}'") + end + + @path = filename + self.set_encoding(encoding, invalid: invalid) if encoding + super(fd, blocking: true) + end + + protected def open_flag(mode) + if mode.size == 0 + raise "Invalid access mode #{mode}" + end + + m = 0 + o = 0 + case mode[0] + when 'r' + m = LibC::O_RDONLY + when 'w' + m = LibC::O_WRONLY + o = LibC::O_CREAT | LibC::O_TRUNC + when 'a' + m = LibC::O_WRONLY + o = LibC::O_CREAT | LibC::O_APPEND + else + raise "Invalid access mode #{mode}" + end + + case mode.size + when 1 + # Nothing + when 2 + case mode[1] + when '+' + m = LibC::O_RDWR + when 'b' + # Nothing + else + raise "Invalid access mode #{mode}" + end + else + raise "Invalid access mode #{mode}" + end + + oflag = m | o + end + + getter path : String + + # Returns a `File::Stat` object for the file given by *path* or raises + # `Errno` in case of an error. In case of a symbolic link + # it is followed and information about the target is returned. + # + # ``` + # File.write("foo", "foo") + # File.stat("foo").size # => 3 + # File.stat("foo").mtime # => 2015-09-23 06:24:19 UTC + # ``` + def self.stat(path) : Stat + if LibC.stat(path.check_no_null_byte, out stat) != 0 + raise Errno.new("Unable to get stat for '#{path}'") + end + Stat.new(stat) + end + + # Returns a `File::Stat` object for the file given by *path* or raises + # `Errno` in case of an error. In case of a symbolic link + # information about it is returned. + # + # ``` + # File.write("foo", "foo") + # File.lstat("foo").size # => 3 + # File.lstat("foo").mtime # => 2015-09-23 06:24:19 UTC + # ``` + def self.lstat(path) : Stat + if LibC.lstat(path.check_no_null_byte, out stat) != 0 + raise Errno.new("Unable to get lstat for '#{path}'") + end + Stat.new(stat) + end + + # Returns `true` if *path* exists else returns `false` + # + # ``` + # File.delete("foo") if File.exists?("foo") + # File.exists?("foo") # => false + # File.write("foo", "foo") + # File.exists?("foo") # => true + # ``` + def self.exists?(path) : Bool + accessible?(path, LibC::F_OK) + end + + # Returns `true` if the file at *path* is empty, otherwise returns `false`. + # Raises `Errno` if the file at *path* does not exist. + # + # ``` + # File.write("foo", "") + # File.empty?("foo") # => true + # File.write("foo", "foo") + # File.empty?("foo") # => false + # ``` + def self.empty?(path) : Bool + begin + stat(path).size == 0 + rescue Errno + raise Errno.new("Error determining size of '#{path}'") + end + end + + # Returns `true` if *path* is readable by the real user id of this process else returns `false`. + # + # ``` + # File.write("foo", "foo") + # File.readable?("foo") # => true + # ``` + def self.readable?(path) : Bool + accessible?(path, LibC::R_OK) + end + + # Returns `true` if *path* is writable by the real user id of this process else returns `false`. + # + # ``` + # File.write("foo", "foo") + # File.writable?("foo") # => true + # ``` + def self.writable?(path) : Bool + accessible?(path, LibC::W_OK) + end + + # Returns `true` if *path* is executable by the real user id of this process else returns `false`. + # + # ``` + # File.write("foo", "foo") + # File.executable?("foo") # => false + # ``` + def self.executable?(path) : Bool + accessible?(path, LibC::X_OK) + end + + # Convenience method to avoid code on LibC.access calls. Not meant to be called by users of this class. + private def self.accessible?(path, flag) + LibC.access(path.check_no_null_byte, flag) == 0 + end + + # Returns `true` if given *path* exists and is a file. + # + # ``` + # File.write("foo", "") + # Dir.mkdir("dir1") + # File.file?("foo") # => true + # File.file?("dir1") # => false + # File.file?("foobar") # => false + # ``` + def self.file?(path) : Bool + if LibC.stat(path.check_no_null_byte, out stat) != 0 + if Errno.value == Errno::ENOENT + return false + else + raise Errno.new("stat") + end + end + File::Stat.new(stat).file? + end + + # Returns `true` if the given *path* exists and is a directory. + # + # ``` + # File.write("foo", "") + # Dir.mkdir("dir2") + # File.directory?("foo") # => false + # File.directory?("dir2") # => true + # File.directory?("foobar") # => false + # ``` + def self.directory?(path) : Bool + Dir.exists?(path) + end + + # Returns all components of the given *path* except the last one. + # + # ``` + # File.dirname("/foo/bar/file.cr") # => "/foo/bar" + # ``` + def self.dirname(path) : String + path.check_no_null_byte + index = path.rindex SEPARATOR + if index + if index == 0 + SEPARATOR_STRING + else + path[0, index] + end + else + "." + end + end + + # Returns the last component of the given *path*. + # + # ``` + # File.basename("/foo/bar/file.cr") # => "file.cr" + # ``` + def self.basename(path) : String + return "" if path.bytesize == 0 + return SEPARATOR_STRING if path == SEPARATOR_STRING + + path.check_no_null_byte + + last = path.size - 1 + last -= 1 if path[last] == SEPARATOR + + index = path.rindex SEPARATOR, last + if index + path[index + 1, last - index] + else + path + end + end + + # Returns the last component of the given *path*. + # + # If *suffix* is present at the end of *path*, it is removed. + # + # ``` + # File.basename("/foo/bar/file.cr", ".cr") # => "file" + # ``` + def self.basename(path, suffix) : String + suffix.check_no_null_byte + basename(path).chomp(suffix) + end + + # Changes the owner of the specified file. + # + # ``` + # File.chown("/foo/bar/baz.cr", 1001, 100) + # File.chown("/foo/bar", gid: 100) + # ``` + # + # Unless *follow_symlinks* is set to `true`, then the owner symlink itself will + # be changed, otherwise the owner of the symlink destination file will be + # changed. For example, assuming symlinks as `foo -> bar -> baz`: + # + # ``` + # File.chown("foo", gid: 100) # changes foo's gid + # File.chown("foo", gid: 100, follow_symlinks: true) # changes baz's gid + # ``` + def self.chown(path, uid : Int? = -1, gid : Int = -1, follow_symlinks = false) + ret = if !follow_symlinks && symlink?(path) + LibC.lchown(path, uid, gid) + else + LibC.chown(path, uid, gid) + end + raise Errno.new("Error changing owner of '#{path}'") if ret == -1 + end + + # Changes the permissions of the specified file. + # + # Symlinks are dereferenced, so that only the permissions of the symlink + # destination are changed, never the permissions of the symlink itself. + # + # ``` + # File.chmod("foo", 0o755) + # File.stat("foo").perm # => 0o755 + # + # File.chmod("foo", 0o700) + # File.stat("foo").perm # => 0o700 + # ``` + def self.chmod(path, mode : Int) + if LibC.chmod(path, mode) == -1 + raise Errno.new("Error changing permissions of '#{path}'") + end + end + + # Delete the file at *path*. Deleting non-existent file will raise an exception. + # + # ``` + # File.write("foo", "") + # File.delete("./foo") + # File.delete("./bar") # raises Errno (No such file or directory) + # ``` + def self.delete(path) + err = LibC.unlink(path.check_no_null_byte) + if err == -1 + raise Errno.new("Error deleting file '#{path}'") + end + end + + # Returns *filename*'s extension, or an empty string if it has no extension. + # + # ``` + # File.extname("foo.cr") # => ".cr" + # ``` + def self.extname(filename) : String + filename.check_no_null_byte + + dot_index = filename.rindex('.') + + if dot_index && dot_index != filename.size - 1 && filename[dot_index - 1] != SEPARATOR + filename[dot_index, filename.size - dot_index] + else + "" + end + end + + # Converts *path* to an absolute path. Relative paths are + # referenced from the current working directory of the process unless + # *dir* is given, in which case it will be used as the starting point. + # + # ``` + # File.expand_path("foo") # => "/home/.../foo" + # File.expand_path("~/crystal/foo") # => "/home/crystal/foo" + # File.expand_path("baz", "/foo/bar") # => "/foo/bar/baz" + # ``` + def self.expand_path(path, dir = nil) : String + path.check_no_null_byte + + if path.starts_with?('~') + home = ENV["HOME"] + home = home.chomp('/') unless home == "/" + + if path.size >= 2 && path[1] == SEPARATOR + path = home + path[1..-1] + elsif path.size < 2 + return home + end + end + + unless path.starts_with?(SEPARATOR) + dir = dir ? expand_path(dir) : Dir.current + path = "#{dir}#{SEPARATOR}#{path}" + end + + parts = path.split(SEPARATOR) + items = [] of String + parts.each do |part| + case part + when "", "." + # Nothing + when ".." + items.pop? + else + items << part + end + end + + String.build do |str| + {% if !flag?(:windows) %} + str << SEPARATOR_STRING + {% end %} + items.join SEPARATOR_STRING, str + end + end + + # Resolves the real path of *path* by following symbolic links. + def self.real_path(path) : String + real_path_ptr = LibC.realpath(path, nil) + raise Errno.new("Error resolving real path of #{path}") unless real_path_ptr + String.new(real_path_ptr).tap { LibC.free(real_path_ptr.as(Void*)) } + end + + # Creates a new link (also known as a hard link) at *new_path* to an existing file + # given by *old_path*. + def self.link(old_path, new_path) + ret = LibC.link(old_path.check_no_null_byte, new_path.check_no_null_byte) + raise Errno.new("Error creating link from #{old_path} to #{new_path}") if ret != 0 + ret + end + + # Creates a symbolic link at *new_path* to an existing file given by *old_path. + def self.symlink(old_path, new_path) + ret = LibC.symlink(old_path.check_no_null_byte, new_path.check_no_null_byte) + raise Errno.new("Error creating symlink from #{old_path} to #{new_path}") if ret != 0 + ret + end + + # Returns `true` if the *path* is a symbolic link. + def self.symlink?(path) : Bool + if LibC.lstat(path.check_no_null_byte, out stat) != 0 + if Errno.value == Errno::ENOENT + return false + else + raise Errno.new("stat") + end + end + (stat.st_mode & LibC::S_IFMT) == LibC::S_IFLNK + end + + # Opens the file named by *filename*. If a file is being created, its initial + # permissions may be set using the *perm* parameter. + def self.open(filename, mode = "r", perm = DEFAULT_CREATE_MODE, encoding = nil, invalid = nil) : self + new filename, mode, perm, encoding, invalid + end + + # Opens the file named by *filename*. If a file is being created, its initial + # permissions may be set using the *perm* parameter. Then given block will be passed the opened + # file as an argument, the file will be automatically closed when the block returns. + def self.open(filename, mode = "r", perm = DEFAULT_CREATE_MODE, encoding = nil, invalid = nil) + file = File.new filename, mode, perm, encoding, invalid + begin + yield file + ensure + file.close + end + end + + # Returns the content of *filename* as a string. + # + # ``` + # File.write("bar", "foo") + # File.read("bar") # => "foo" + # ``` + def self.read(filename, encoding = nil, invalid = nil) : String + File.open(filename, "r") do |file| + if encoding + file.set_encoding(encoding, invalid: invalid) + file.gets_to_end + else + # We try to read a string with an initialize capacity + # equal to the file's size, but the size might not be + # correct or even be zero (for example for /proc files) + size = file.size.to_i + size = 256 if size == 0 + String.build(size) do |io| + IO.copy(file, io) + end + end + end + end + + # Yields each line in *filename* to the given block. + # + # ``` + # File.write("foobar", "foo\nbar") + # + # array = [] of String + # File.each_line("foobar") do |line| + # array << line + # end + # array # => ["foo", "bar"] + # ``` + def self.each_line(filename, encoding = nil, invalid = nil, chomp = true) + File.open(filename, "r", encoding: encoding, invalid: invalid) do |file| + file.each_line(chomp: chomp) do |line| + yield line + end + end + end + + # Returns an `Iterator` for each line in *filename*. + def self.each_line(filename, encoding = nil, invalid = nil, chomp = true) + File.open(filename, "r", encoding: encoding, invalid: invalid).each_line(chomp: chomp) + end + + # Returns all lines in *filename* as an array of strings. + # + # ``` + # File.write("foobar", "foo\nbar") + # File.read_lines("foobar") # => ["foo", "bar"] + # ``` + def self.read_lines(filename, encoding = nil, invalid = nil, chomp = true) : Array(String) + lines = [] of String + each_line(filename, encoding: encoding, invalid: invalid, chomp: chomp) do |line| + lines << line + end + lines + end + + # Write the given *content* to *filename*. + # + # An existing file will be overwritten, else a file will be created. + # + # ``` + # File.write("foo", "bar") + # ``` + # + # NOTE: If the content is a `Slice(UInt8)`, those bytes will be written. + # If it's an `IO`, all bytes from the `IO` will be written. + # Otherwise, the string representation of *content* will be written + # (the result of invoking `to_s` on *content*). + def self.write(filename, content, perm = DEFAULT_CREATE_MODE, encoding = nil, invalid = nil) + File.open(filename, "w", perm, encoding: encoding, invalid: invalid) do |file| + case content + when Bytes + file.write(content) + when IO + IO.copy(content, file) + else + file.print(content) + end + end + end + + # Returns a new string formed by joining the strings using `File::SEPARATOR`. + # + # ``` + # File.join("foo", "bar", "baz") # => "foo/bar/baz" + # File.join("foo/", "/bar/", "/baz") # => "foo/bar/baz" + # File.join("/foo/", "/bar/", "/baz/") # => "/foo/bar/baz/" + # ``` + def self.join(*parts) : String + join parts + end + + # Returns a new string formed by joining the strings using `File::SEPARATOR`. + # + # ``` + # File.join({"foo", "bar", "baz"}) # => "foo/bar/baz" + # File.join({"foo/", "/bar/", "/baz"}) # => "foo/bar/baz" + # File.join(["/foo/", "/bar/", "/baz/"]) # => "/foo/bar/baz/" + # ``` + def self.join(parts : Array | Tuple) : String + String.build do |str| + parts.each_with_index do |part, index| + part.check_no_null_byte + + str << SEPARATOR if index > 0 + + byte_start = 0 + byte_count = part.bytesize + + if index > 0 && part.starts_with?(SEPARATOR) + byte_start += 1 + byte_count -= 1 + end + + if index != parts.size - 1 && part.ends_with?(SEPARATOR) + byte_count -= 1 + end + + str.write part.unsafe_byte_slice(byte_start, byte_count) + end + end + end + + # Returns the size of *filename* bytes. + def self.size(filename) : UInt64 + stat(filename.check_no_null_byte).size + end + + # Moves *old_filename* to *new_filename*. + # + # ``` + # File.write("afile", "foo") + # File.exists?("afile") # => true + # + # File.rename("afile", "afile.cr") + # File.exists?("afile") # => false + # File.exists?("afile.cr") # => true + # ``` + def self.rename(old_filename, new_filename) + code = LibC.rename(old_filename.check_no_null_byte, new_filename.check_no_null_byte) + if code != 0 + raise Errno.new("Error renaming file '#{old_filename}' to '#{new_filename}'") + end + code + end + + # Sets the access and modification times of *filename*. + def self.utime(atime : Time, mtime : Time, filename : String) : Nil + timevals = uninitialized LibC::Timeval[2] + timevals[0] = to_timeval(atime) + timevals[1] = to_timeval(mtime) + ret = LibC.utimes(filename, timevals) + if ret != 0 + raise Errno.new("Error setting time to file '#{filename}'") + end + end + + # Attempts to set the access and modification times of the file named + # in the *filename* parameter to the value given in *time*. + # + # If the file does not exist, it will be created. + def self.touch(filename : String, time : Time = Time.now) + open(filename, "a") { } unless exists?(filename) + utime time, time, filename + end + + private def self.to_timeval(time : Time) + t = uninitialized LibC::Timeval + t.tv_sec = typeof(t.tv_sec).new(time.to_local.epoch) + t.tv_usec = typeof(t.tv_usec).new(0) + t + end + + # Return the size in bytes of the currently opened file. + def size + stat.size + end + + # Truncates the file to the specified *size*. Requires that the current file is opened + # for writing. + def truncate(size = 0) + flush + code = LibC.ftruncate(fd, size) + if code != 0 + raise Errno.new("Error truncating file '#{path}'") + end + code + end + + # Yields an `IO` to read a section inside this file. + # Mutliple sections can be read concurrently. + def read_at(offset, bytesize, &block) + self_bytesize = self.size + + unless 0 <= offset <= self_bytesize + raise ArgumentError.new("Offset out of bounds") + end + + if bytesize < 0 + raise ArgumentError.new("Negative bytesize") + end + + unless 0 <= offset + bytesize <= self_bytesize + raise ArgumentError.new("Bytesize out of bounds") + end + + io = PReader.new(fd, offset, bytesize) + yield io ensure io.close + end + + def inspect(io) + io << "#" + io + end +end diff --git a/src/file.windows.cr b/src/file.windows.cr new file mode 100644 index 000000000000..24ba38fea4b3 --- /dev/null +++ b/src/file.windows.cr @@ -0,0 +1,647 @@ +require "c/stdio" +require "c/stdlib" + +class File < IO::FileDescriptor + # The file/directory separator character. '/' in Unix, '\\' in Windows. + SEPARATOR = '\\' + + # The file/directory separator string. "/" in Unix, "\\" in Windows. + SEPARATOR_STRING = "\\" + + def initialize(filename : String, mode = "r", encoding = nil, invalid = nil) + access, creation, seek = open_flag(mode) + flags = LibWindows::FILE_FLAG_OVERLAPPED + handle = LibWindows.create_file(filename, access, 0, nil, creation, flags, nil) + + if handle.null? + raise WinError.new("Error opening file '#{filename}' with mode '#{mode}'") + end + + if seek + # SEEK_END + end + + @path = filename + self.set_encoding(encoding, invalid: invalid) if encoding + super(handle) + end + + protected def open_flag(mode) + if mode.size == 0 + raise "Invalid access mode #{mode}" + end + + seek = false + case mode[0] + when 'r' + access = LibWindows::GENERIC_READ + creation = LibWindows::OPEN_EXISTING + when 'w' + access = LibWindows::GENERIC_WRITE + creation = LibWindows::CREATE_ALWAYS + when 'a' + access = LibWindows::GENERIC_WRITE + creation = LibWindows::OPEN_ALWAYS + seek = true + else + raise "Invalid access mode #{mode}" + end + + case mode.size + when 1 + # Nothing + when 2 + case mode[1] + when '+' + access = LibWindows::GENERIC_READ | LibWindows::GENERIC_WRITE + when 'b' + # Nothing + else + raise "Invalid access mode #{mode}" + end + else + raise "Invalid access mode #{mode}" + end + + return {access, creation, seek} + end + + getter path : String + + # Returns a `File::Stat` object for the file given by *path* or raises + # `Errno` in case of an error. In case of a symbolic link + # it is followed and information about the target is returned. + # + # ``` + # File.write("foo", "foo") + # File.stat("foo").size # => 3 + # File.stat("foo").mtime # => 2015-09-23 06:24:19 UTC + # ``` + def self.stat(path) : Stat + if LibC.stat(path.check_no_null_byte, out stat) != 0 + raise Errno.new("Unable to get stat for '#{path}'") + end + Stat.new(stat) + end + + # Returns a `File::Stat` object for the file given by *path* or raises + # `Errno` in case of an error. In case of a symbolic link + # information about it is returned. + # + # ``` + # File.write("foo", "foo") + # File.lstat("foo").size # => 3 + # File.lstat("foo").mtime # => 2015-09-23 06:24:19 UTC + # ``` + def self.lstat(path) : Stat + if LibC.lstat(path.check_no_null_byte, out stat) != 0 + raise Errno.new("Unable to get lstat for '#{path}'") + end + Stat.new(stat) + end + + # Returns `true` if *path* exists else returns `false` + # + # ``` + # File.delete("foo") if File.exists?("foo") + # File.exists?("foo") # => false + # File.write("foo", "foo") + # File.exists?("foo") # => true + # ``` + def self.exists?(path) : Bool + accessible?(path, LibC::F_OK) + end + + # Returns `true` if the file at *path* is empty, otherwise returns `false`. + # Raises `Errno` if the file at *path* does not exist. + # + # ``` + # File.write("foo", "") + # File.empty?("foo") # => true + # File.write("foo", "foo") + # File.empty?("foo") # => false + # ``` + def self.empty?(path) : Bool + begin + stat(path).size == 0 + rescue Errno + raise Errno.new("Error determining size of '#{path}'") + end + end + + # Returns `true` if *path* is readable by the real user id of this process else returns `false`. + # + # ``` + # File.write("foo", "foo") + # File.readable?("foo") # => true + # ``` + def self.readable?(path) : Bool + accessible?(path, LibC::R_OK) + end + + # Returns `true` if *path* is writable by the real user id of this process else returns `false`. + # + # ``` + # File.write("foo", "foo") + # File.writable?("foo") # => true + # ``` + def self.writable?(path) : Bool + accessible?(path, LibC::W_OK) + end + + # Returns `true` if *path* is executable by the real user id of this process else returns `false`. + # + # ``` + # File.write("foo", "foo") + # File.executable?("foo") # => false + # ``` + def self.executable?(path) : Bool + accessible?(path, LibC::X_OK) + end + + # Convenience method to avoid code on LibC.access calls. Not meant to be called by users of this class. + private def self.accessible?(path, flag) + LibC.access(path.check_no_null_byte, flag) == 0 + end + + # Returns `true` if given *path* exists and is a file. + # + # ``` + # File.write("foo", "") + # Dir.mkdir("dir1") + # File.file?("foo") # => true + # File.file?("dir1") # => false + # File.file?("foobar") # => false + # ``` + def self.file?(path) : Bool + if LibC.stat(path.check_no_null_byte, out stat) != 0 + if Errno.value == Errno::ENOENT + return false + else + raise Errno.new("stat") + end + end + File::Stat.new(stat).file? + end + + # Returns `true` if the given *path* exists and is a directory. + # + # ``` + # File.write("foo", "") + # Dir.mkdir("dir2") + # File.directory?("foo") # => false + # File.directory?("dir2") # => true + # File.directory?("foobar") # => false + # ``` + def self.directory?(path) : Bool + Dir.exists?(path) + end + + # Returns all components of the given *path* except the last one. + # + # ``` + # File.dirname("/foo/bar/file.cr") # => "/foo/bar" + # ``` + def self.dirname(path) : String + path.check_no_null_byte + index = path.rindex SEPARATOR + if index + if index == 0 + SEPARATOR_STRING + else + path[0, index] + end + else + "." + end + end + + # Returns the last component of the given *path*. + # + # ``` + # File.basename("/foo/bar/file.cr") # => "file.cr" + # ``` + def self.basename(path) : String + return "" if path.bytesize == 0 + return SEPARATOR_STRING if path == SEPARATOR_STRING + + path.check_no_null_byte + + last = path.size - 1 + last -= 1 if path[last] == SEPARATOR + + index = path.rindex SEPARATOR, last + if index + path[index + 1, last - index] + else + path + end + end + + # Returns the last component of the given *path*. + # + # If *suffix* is present at the end of *path*, it is removed. + # + # ``` + # File.basename("/foo/bar/file.cr", ".cr") # => "file" + # ``` + def self.basename(path, suffix) : String + suffix.check_no_null_byte + basename(path).chomp(suffix) + end + + # Changes the owner of the specified file. + # + # ``` + # File.chown("/foo/bar/baz.cr", 1001, 100) + # File.chown("/foo/bar", gid: 100) + # ``` + # + # Unless *follow_symlinks* is set to `true`, then the owner symlink itself will + # be changed, otherwise the owner of the symlink destination file will be + # changed. For example, assuming symlinks as `foo -> bar -> baz`: + # + # ``` + # File.chown("foo", gid: 100) # changes foo's gid + # File.chown("foo", gid: 100, follow_symlinks: true) # changes baz's gid + # ``` + def self.chown(path, uid : Int? = -1, gid : Int = -1, follow_symlinks = false) + ret = if !follow_symlinks && symlink?(path) + LibC.lchown(path, uid, gid) + else + LibC.chown(path, uid, gid) + end + raise Errno.new("Error changing owner of '#{path}'") if ret == -1 + end + + # Changes the permissions of the specified file. + # + # Symlinks are dereferenced, so that only the permissions of the symlink + # destination are changed, never the permissions of the symlink itself. + # + # ``` + # File.chmod("foo", 0o755) + # File.stat("foo").perm # => 0o755 + # + # File.chmod("foo", 0o700) + # File.stat("foo").perm # => 0o700 + # ``` + def self.chmod(path, mode : Int) + if LibC.chmod(path, mode) == -1 + raise Errno.new("Error changing permissions of '#{path}'") + end + end + + # Delete the file at *path*. Deleting non-existent file will raise an exception. + # + # ``` + # File.write("foo", "") + # File.delete("./foo") + # File.delete("./bar") # raises Errno (No such file or directory) + # ``` + def self.delete(path) + err = LibC.unlink(path.check_no_null_byte) + if err == -1 + raise Errno.new("Error deleting file '#{path}'") + end + end + + # Returns *filename*'s extension, or an empty string if it has no extension. + # + # ``` + # File.extname("foo.cr") # => ".cr" + # ``` + def self.extname(filename) : String + filename.check_no_null_byte + + dot_index = filename.rindex('.') + + if dot_index && dot_index != filename.size - 1 && filename[dot_index - 1] != SEPARATOR + filename[dot_index, filename.size - dot_index] + else + "" + end + end + + # Converts *path* to an absolute path. Relative paths are + # referenced from the current working directory of the process unless + # *dir* is given, in which case it will be used as the starting point. + # + # ``` + # File.expand_path("foo") # => "/home/.../foo" + # File.expand_path("~/crystal/foo") # => "/home/crystal/foo" + # File.expand_path("baz", "/foo/bar") # => "/foo/bar/baz" + # ``` + def self.expand_path(path, dir = nil) : String + path.check_no_null_byte + + if path.starts_with?('~') + home = ENV["HOME"] + home = home.chomp('/') unless home == "/" + + if path.size >= 2 && path[1] == SEPARATOR + path = home + path[1..-1] + elsif path.size < 2 + return home + end + end + + unless path.starts_with?(SEPARATOR) + dir = dir ? expand_path(dir) : Dir.current + path = "#{dir}#{SEPARATOR}#{path}" + end + + parts = path.split(SEPARATOR) + items = [] of String + parts.each do |part| + case part + when "", "." + # Nothing + when ".." + items.pop? + else + items << part + end + end + + String.build do |str| + {% if !flag?(:windows) %} + str << SEPARATOR_STRING + {% end %} + items.join SEPARATOR_STRING, str + end + end + + # Resolves the real path of *path* by following symbolic links. + def self.real_path(path) : String + real_path_ptr = LibC.realpath(path, nil) + raise Errno.new("Error resolving real path of #{path}") unless real_path_ptr + String.new(real_path_ptr).tap { LibC.free(real_path_ptr.as(Void*)) } + end + + # Creates a new link (also known as a hard link) at *new_path* to an existing file + # given by *old_path*. + def self.link(old_path, new_path) + ret = LibC.link(old_path.check_no_null_byte, new_path.check_no_null_byte) + raise Errno.new("Error creating link from #{old_path} to #{new_path}") if ret != 0 + ret + end + + # Creates a symbolic link at *new_path* to an existing file given by *old_path. + def self.symlink(old_path, new_path) + ret = LibC.symlink(old_path.check_no_null_byte, new_path.check_no_null_byte) + raise Errno.new("Error creating symlink from #{old_path} to #{new_path}") if ret != 0 + ret + end + + # Returns `true` if the *path* is a symbolic link. + def self.symlink?(path) : Bool + if LibC.lstat(path.check_no_null_byte, out stat) != 0 + if Errno.value == Errno::ENOENT + return false + else + raise Errno.new("stat") + end + end + (stat.st_mode & LibC::S_IFMT) == LibC::S_IFLNK + end + + # Opens the file named by *filename*. + def self.open(filename, mode = "r", encoding = nil, invalid = nil) : self + new filename, mode, encoding, invalid + end + + # Opens the file named by *filename*. Then given block will be passed the opened + # file as an argument, the file will be automatically closed when the block returns. + def self.open(filename, mode = "r", encoding = nil, invalid = nil) + file = File.new filename, mode, encoding, invalid + begin + yield file + ensure + file.close + end + end + + # Returns the content of *filename* as a string. + # + # ``` + # File.write("bar", "foo") + # File.read("bar") # => "foo" + # ``` + def self.read(filename, encoding = nil, invalid = nil) : String + File.open(filename, "r") do |file| + if encoding + file.set_encoding(encoding, invalid: invalid) + file.gets_to_end + else + # We try to read a string with an initialize capacity + # equal to the file's size, but the size might not be + # correct or even be zero (for example for /proc files) + size = file.size.to_i + size = 256 if size == 0 + String.build(size) do |io| + IO.copy(file, io) + end + end + end + end + + # Yields each line in *filename* to the given block. + # + # ``` + # File.write("foobar", "foo\nbar") + # + # array = [] of String + # File.each_line("foobar") do |line| + # array << line + # end + # array # => ["foo", "bar"] + # ``` + def self.each_line(filename, encoding = nil, invalid = nil, chomp = true) + File.open(filename, "r", encoding: encoding, invalid: invalid) do |file| + file.each_line(chomp: chomp) do |line| + yield line + end + end + end + + # Returns an `Iterator` for each line in *filename*. + def self.each_line(filename, encoding = nil, invalid = nil, chomp = true) + File.open(filename, "r", encoding: encoding, invalid: invalid).each_line(chomp: chomp) + end + + # Returns all lines in *filename* as an array of strings. + # + # ``` + # File.write("foobar", "foo\nbar") + # File.read_lines("foobar") # => ["foo", "bar"] + # ``` + def self.read_lines(filename, encoding = nil, invalid = nil, chomp = true) : Array(String) + lines = [] of String + each_line(filename, encoding: encoding, invalid: invalid, chomp: chomp) do |line| + lines << line + end + lines + end + + # Write the given *content* to *filename*. + # + # An existing file will be overwritten, else a file will be created. + # + # ``` + # File.write("foo", "bar") + # ``` + # + # NOTE: If the content is a `Slice(UInt8)`, those bytes will be written. + # If it's an `IO`, all bytes from the `IO` will be written. + # Otherwise, the string representation of *content* will be written + # (the result of invoking `to_s` on *content*). + def self.write(filename, content, perm = DEFAULT_CREATE_MODE, encoding = nil, invalid = nil) + File.open(filename, "w", perm, encoding: encoding, invalid: invalid) do |file| + case content + when Bytes + file.write(content) + when IO + IO.copy(content, file) + else + file.print(content) + end + end + end + + # Returns a new string formed by joining the strings using `File::SEPARATOR`. + # + # ``` + # File.join("foo", "bar", "baz") # => "foo/bar/baz" + # File.join("foo/", "/bar/", "/baz") # => "foo/bar/baz" + # File.join("/foo/", "/bar/", "/baz/") # => "/foo/bar/baz/" + # ``` + def self.join(*parts) : String + join parts + end + + # Returns a new string formed by joining the strings using `File::SEPARATOR`. + # + # ``` + # File.join({"foo", "bar", "baz"}) # => "foo/bar/baz" + # File.join({"foo/", "/bar/", "/baz"}) # => "foo/bar/baz" + # File.join(["/foo/", "/bar/", "/baz/"]) # => "/foo/bar/baz/" + # ``` + def self.join(parts : Array | Tuple) : String + String.build do |str| + parts.each_with_index do |part, index| + part.check_no_null_byte + + str << SEPARATOR if index > 0 + + byte_start = 0 + byte_count = part.bytesize + + if index > 0 && part.starts_with?(SEPARATOR) + byte_start += 1 + byte_count -= 1 + end + + if index != parts.size - 1 && part.ends_with?(SEPARATOR) + byte_count -= 1 + end + + str.write part.unsafe_byte_slice(byte_start, byte_count) + end + end + end + + # Returns the size of *filename* bytes. + def self.size(filename) : UInt64 + stat(filename.check_no_null_byte).size + end + + # Moves *old_filename* to *new_filename*. + # + # ``` + # File.write("afile", "foo") + # File.exists?("afile") # => true + # + # File.rename("afile", "afile.cr") + # File.exists?("afile") # => false + # File.exists?("afile.cr") # => true + # ``` + def self.rename(old_filename, new_filename) + code = LibC.rename(old_filename.check_no_null_byte, new_filename.check_no_null_byte) + if code != 0 + raise Errno.new("Error renaming file '#{old_filename}' to '#{new_filename}'") + end + code + end + + # Sets the access and modification times of *filename*. + def self.utime(atime : Time, mtime : Time, filename : String) : Nil + timevals = uninitialized LibC::Timeval[2] + timevals[0] = to_timeval(atime) + timevals[1] = to_timeval(mtime) + ret = LibC.utimes(filename, timevals) + if ret != 0 + raise Errno.new("Error setting time to file '#{filename}'") + end + end + + # Attempts to set the access and modification times of the file named + # in the *filename* parameter to the value given in *time*. + # + # If the file does not exist, it will be created. + def self.touch(filename : String, time : Time = Time.now) + open(filename, "a") { } unless exists?(filename) + utime time, time, filename + end + + private def self.to_timeval(time : Time) + t = uninitialized LibC::Timeval + t.tv_sec = typeof(t.tv_sec).new(time.to_local.epoch) + t.tv_usec = typeof(t.tv_usec).new(0) + t + end + + # Return the size in bytes of the currently opened file. + def size + stat.size + end + + # Truncates the file to the specified *size*. Requires that the current file is opened + # for writing. + def truncate(size = 0) + flush + code = LibC.ftruncate(fd, size) + if code != 0 + raise Errno.new("Error truncating file '#{path}'") + end + code + end + + # Yields an `IO` to read a section inside this file. + # Mutliple sections can be read concurrently. + def read_at(offset, bytesize, &block) + self_bytesize = self.size + + unless 0 <= offset <= self_bytesize + raise ArgumentError.new("Offset out of bounds") + end + + if bytesize < 0 + raise ArgumentError.new("Negative bytesize") + end + + unless 0 <= offset + bytesize <= self_bytesize + raise ArgumentError.new("Bytesize out of bounds") + end + + io = PReader.new(fd, offset, bytesize) + yield io ensure io.close + end + + def inspect(io) + io << "#" + io + end +end diff --git a/src/file/flock.cr b/src/file/flock.posix.cr similarity index 100% rename from src/file/flock.cr rename to src/file/flock.posix.cr diff --git a/src/file/stat.cr b/src/file/stat.cr index 12f883aff478..b7543ee91a70 100644 --- a/src/file/stat.cr +++ b/src/file/stat.cr @@ -1,178 +1,5 @@ -require "c/sys/stat" - -class File - struct Stat - def initialize(filename : String) - if LibC.stat(filename, out @stat) != 0 - raise Errno.new("Unable to get stat for '#{filename}'") - end - end - - def initialize(@stat : LibC::Stat) - end - - def atime - {% if flag?(:darwin) %} - time @stat.st_atimespec - {% else %} - time @stat.st_atim - {% end %} - end - - def blksize - @stat.st_blksize - end - - def blocks - @stat.st_blocks - end - - def ctime - {% if flag?(:darwin) %} - time @stat.st_ctimespec - {% else %} - time @stat.st_ctim - {% end %} - end - - def dev - @stat.st_dev - end - - def gid - @stat.st_gid - end - - def ino - @stat.st_ino - end - - def mode - @stat.st_mode - end - - # permission bits of mode - def perm - mode & 0o7777 - end - - def mtime - {% if flag?(:darwin) %} - time @stat.st_mtimespec - {% else %} - time @stat.st_mtim - {% end %} - end - - def nlink - @stat.st_nlink - end - - def rdev - @stat.st_rdev - end - - def size - @stat.st_size.to_u64 - end - - def uid - @stat.st_uid - end - - def inspect(io) - io << "#" - end - - def pretty_print(pp) - pp.surround("#", left_break: " ", right_break: nil) do - pp.text "dev=0x#{dev.to_s(16)}" - pp.comma - pp.text "ino=#{ino}" - pp.comma - pp.text "mode=0o#{mode.to_s(8)}" - pp.comma - pp.text "nlink=#{nlink}" - pp.comma - pp.text "uid=#{uid}" - pp.comma - pp.text "gid=#{gid}" - pp.comma - pp.text "rdev=0x#{rdev.to_s(16)}" - pp.comma - pp.text "size=#{size}" - pp.comma - pp.text "blksize=#{blksize}" - pp.comma - pp.text "blocks=#{blocks}" - pp.comma - pp.text "atime=#{atime}" - pp.comma - pp.text "mtime=#{mtime}" - pp.comma - pp.text "ctime=#{ctime}" - end - end - - def blockdev? - (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFBLK - end - - def chardev? - (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFCHR - end - - def directory? - (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFDIR - end - - def file? - (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFREG - end - - def pipe? - (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFIFO - end - - def setuid? - (@stat.st_mode & LibC::S_IFMT) == LibC::S_ISUID - end - - def setgid? - (@stat.st_mode & LibC::S_IFMT) == LibC::S_ISGID - end - - def symlink? - (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFLNK - end - - def socket? - (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFSOCK - end - - def sticky? - (@stat.st_mode & LibC::S_IFMT) == LibC::S_ISVTX - end - - private def time(value) - Time.new value, Time::Kind::Utc - end - end -end +{% if flag?(:windows) %} + require "./stat.windows.cr" +{% else %} + require "./stat.posix.cr" +{% end %} diff --git a/src/file/stat.posix.cr b/src/file/stat.posix.cr new file mode 100644 index 000000000000..12f883aff478 --- /dev/null +++ b/src/file/stat.posix.cr @@ -0,0 +1,178 @@ +require "c/sys/stat" + +class File + struct Stat + def initialize(filename : String) + if LibC.stat(filename, out @stat) != 0 + raise Errno.new("Unable to get stat for '#{filename}'") + end + end + + def initialize(@stat : LibC::Stat) + end + + def atime + {% if flag?(:darwin) %} + time @stat.st_atimespec + {% else %} + time @stat.st_atim + {% end %} + end + + def blksize + @stat.st_blksize + end + + def blocks + @stat.st_blocks + end + + def ctime + {% if flag?(:darwin) %} + time @stat.st_ctimespec + {% else %} + time @stat.st_ctim + {% end %} + end + + def dev + @stat.st_dev + end + + def gid + @stat.st_gid + end + + def ino + @stat.st_ino + end + + def mode + @stat.st_mode + end + + # permission bits of mode + def perm + mode & 0o7777 + end + + def mtime + {% if flag?(:darwin) %} + time @stat.st_mtimespec + {% else %} + time @stat.st_mtim + {% end %} + end + + def nlink + @stat.st_nlink + end + + def rdev + @stat.st_rdev + end + + def size + @stat.st_size.to_u64 + end + + def uid + @stat.st_uid + end + + def inspect(io) + io << "#" + end + + def pretty_print(pp) + pp.surround("#", left_break: " ", right_break: nil) do + pp.text "dev=0x#{dev.to_s(16)}" + pp.comma + pp.text "ino=#{ino}" + pp.comma + pp.text "mode=0o#{mode.to_s(8)}" + pp.comma + pp.text "nlink=#{nlink}" + pp.comma + pp.text "uid=#{uid}" + pp.comma + pp.text "gid=#{gid}" + pp.comma + pp.text "rdev=0x#{rdev.to_s(16)}" + pp.comma + pp.text "size=#{size}" + pp.comma + pp.text "blksize=#{blksize}" + pp.comma + pp.text "blocks=#{blocks}" + pp.comma + pp.text "atime=#{atime}" + pp.comma + pp.text "mtime=#{mtime}" + pp.comma + pp.text "ctime=#{ctime}" + end + end + + def blockdev? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFBLK + end + + def chardev? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFCHR + end + + def directory? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFDIR + end + + def file? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFREG + end + + def pipe? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFIFO + end + + def setuid? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_ISUID + end + + def setgid? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_ISGID + end + + def symlink? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFLNK + end + + def socket? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFSOCK + end + + def sticky? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_ISVTX + end + + private def time(value) + Time.new value, Time::Kind::Utc + end + end +end diff --git a/src/file/stat.windows.cr b/src/file/stat.windows.cr new file mode 100644 index 000000000000..160274158be3 --- /dev/null +++ b/src/file/stat.windows.cr @@ -0,0 +1,176 @@ +class File + struct Stat + def initialize(filename : String) + if LibC.stat(filename, out @stat) != 0 + raise Errno.new("Unable to get stat for '#{filename}'") + end + end + + def initialize(@stat : LibC::Stat) + end + + def atime + {% if flag?(:darwin) %} + time @stat.st_atimespec + {% else %} + time @stat.st_atim + {% end %} + end + + def blksize + @stat.st_blksize + end + + def blocks + @stat.st_blocks + end + + def ctime + {% if flag?(:darwin) %} + time @stat.st_ctimespec + {% else %} + time @stat.st_ctim + {% end %} + end + + def dev + @stat.st_dev + end + + def gid + @stat.st_gid + end + + def ino + @stat.st_ino + end + + def mode + @stat.st_mode + end + + # permission bits of mode + def perm + mode & 0o7777 + end + + def mtime + {% if flag?(:darwin) %} + time @stat.st_mtimespec + {% else %} + time @stat.st_mtim + {% end %} + end + + def nlink + @stat.st_nlink + end + + def rdev + @stat.st_rdev + end + + def size + @stat.st_size.to_u64 + end + + def uid + @stat.st_uid + end + + def inspect(io) + io << "#" + end + + def pretty_print(pp) + pp.surround("#", left_break: " ", right_break: nil) do + pp.text "dev=0x#{dev.to_s(16)}" + pp.comma + pp.text "ino=#{ino}" + pp.comma + pp.text "mode=0o#{mode.to_s(8)}" + pp.comma + pp.text "nlink=#{nlink}" + pp.comma + pp.text "uid=#{uid}" + pp.comma + pp.text "gid=#{gid}" + pp.comma + pp.text "rdev=0x#{rdev.to_s(16)}" + pp.comma + pp.text "size=#{size}" + pp.comma + pp.text "blksize=#{blksize}" + pp.comma + pp.text "blocks=#{blocks}" + pp.comma + pp.text "atime=#{atime}" + pp.comma + pp.text "mtime=#{mtime}" + pp.comma + pp.text "ctime=#{ctime}" + end + end + + def blockdev? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFBLK + end + + def chardev? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFCHR + end + + def directory? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFDIR + end + + def file? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFREG + end + + def pipe? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFIFO + end + + def setuid? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_ISUID + end + + def setgid? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_ISGID + end + + def symlink? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFLNK + end + + def socket? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_IFSOCK + end + + def sticky? + (@stat.st_mode & LibC::S_IFMT) == LibC::S_ISVTX + end + + private def time(value) + Time.new value, Time::Kind::Utc + end + end +end diff --git a/src/gc/boehm.cr b/src/gc/boehm.cr index 5016600dcd2e..005a434bc49f 100644 --- a/src/gc/boehm.cr +++ b/src/gc/boehm.cr @@ -53,10 +53,16 @@ lib LibGC fun size = GC_size(addr : Void*) : LibC::SizeT - # Boehm GC requires to use GC_pthread_create and GC_pthread_join instead of pthread_create and pthread_join - fun pthread_create = GC_pthread_create(thread : LibC::PthreadT*, attr : Void*, start : Void* ->, arg : Void*) : LibC::Int - fun pthread_join = GC_pthread_join(thread : LibC::PthreadT, value : Void**) : LibC::Int - fun pthread_detach = GC_pthread_detach(thread : LibC::PthreadT) : LibC::Int + {% if flag?(:windows) %} + # Boehm GC requires to use GC_CreateThread and GC_ExitThread instead of CreateThread and ExitThread + fun create_thread = GC_CreateThread(attr : LibWindows::SecurityAttributes*, stack_size : LibWindows::DWord, start : Void* -> LibWindows::DWord, arg : Void*, flags : LibWindows::DWord, id : LibWindows::DWord*) : LibWindows::Handle + fun exit_thread = GC_ExitThread(code : LibWindows::DWord) : NoReturn + {% else %} + # Boehm GC requires to use GC_pthread_create and GC_pthread_join instead of pthread_create and pthread_join + fun pthread_create = GC_pthread_create(thread : LibC::PthreadT*, attr : Void*, start : Void* ->, arg : Void*) : LibC::Int + fun pthread_join = GC_pthread_join(thread : LibC::PthreadT, value : Void**) : LibC::Int + fun pthread_detach = GC_pthread_detach(thread : LibC::PthreadT) : LibC::Int + {% end %} end # :nodoc: @@ -76,7 +82,9 @@ end module GC def self.init - LibGC.set_handle_fork(1) + {% if !flag? :windows %} + LibGC.set_handle_fork(1) + {% end %} LibGC.init end diff --git a/src/iconv.cr b/src/iconv.cr index 3d41f1c05603..154de6878bfc 100644 --- a/src/iconv.cr +++ b/src/iconv.cr @@ -9,27 +9,31 @@ struct Iconv @skip_invalid = invalid == :skip {% unless flag?(:freebsd) || flag?(:musl) %} - if @skip_invalid - from = "#{from}//IGNORE" - to = "#{to}//IGNORE" - end + if @skip_invalid + from = "#{from}//IGNORE" + to = "#{to}//IGNORE" + end {% end %} - @iconv = LibC.iconv_open(to, from) + @iconv = uninitialized LibC::IconvT + + {% if !flag?(:windows) %} + @iconv = LibC.iconv_open(to, from) - if @iconv.address == LibC::SizeT.new(-1) - if Errno.value == Errno::EINVAL - if original_from == "UTF-8" - raise ArgumentError.new("Invalid encoding: #{original_to}") - elsif original_to == "UTF-8" - raise ArgumentError.new("Invalid encoding: #{original_from}") + if @iconv.address == LibC::SizeT.new(-1) + if Errno.value == Errno::EINVAL + if original_from == "UTF-8" + raise ArgumentError.new("Invalid encoding: #{original_to}") + elsif original_to == "UTF-8" + raise ArgumentError.new("Invalid encoding: #{original_from}") + else + raise ArgumentError.new("Invalid encoding: #{original_from} -> #{original_to}") + end else - raise ArgumentError.new("Invalid encoding: #{original_from} -> #{original_to}") + raise Errno.new("iconv_open") end - else - raise Errno.new("iconv_open") end - end + {% end %} end def self.new(from : String, to : String, invalid : Symbol? = nil) @@ -43,11 +47,13 @@ struct Iconv def convert(inbuf : UInt8**, inbytesleft : LibC::SizeT*, outbuf : UInt8**, outbytesleft : LibC::SizeT*) {% if flag?(:freebsd) %} - if @skip_invalid - return LibC.__iconv(@iconv, inbuf, inbytesleft, outbuf, outbytesleft, LibC::ICONV_F_HIDE_INVALID, out invalids) - end + if @skip_invalid + return LibC.__iconv(@iconv, inbuf, inbytesleft, outbuf, outbytesleft, LibC::ICONV_F_HIDE_INVALID, out invalids) + end + {% end %} + {% if !flag?(:windows) %} + LibC.iconv(@iconv, inbuf, inbytesleft, outbuf, outbytesleft) {% end %} - LibC.iconv(@iconv, inbuf, inbytesleft, outbuf, outbytesleft) end def handle_invalid(inbuf, inbytesleft) @@ -59,18 +65,22 @@ struct Iconv inbytesleft.value -= 1 end else - case Errno.value - when Errno::EINVAL - raise ArgumentError.new "Incomplete multibyte sequence" - when Errno::EILSEQ - raise ArgumentError.new "Invalid multibyte sequence" - end + {% if !flag?(:windows) %} + case Errno.value + when Errno::EINVAL + raise ArgumentError.new "Incomplete multibyte sequence" + when Errno::EILSEQ + raise ArgumentError.new "Invalid multibyte sequence" + end + {% end %} end end def close - if LibC.iconv_close(@iconv) == -1 - raise Errno.new("iconv_close") - end + {% if !flag?(:windows) %} + if LibC.iconv_close(@iconv) == -1 + raise Errno.new("iconv_close") + end + {% end %} end end diff --git a/src/io.cr b/src/io.cr index 4e9d52f1bb80..32e8a4da76b0 100644 --- a/src/io.cr +++ b/src/io.cr @@ -1,9 +1,11 @@ -require "c/fcntl" require "c/stdio" -require "c/sys/select" -require "c/sys/wait" -require "c/errno" -require "c/unistd" +{% if !flag?(:windows) %} + require "c/fcntl" + require "c/sys/select" + require "c/sys/wait" + require "c/errno" + require "c/unistd" +{% end %} # The `IO` module is the basis for all input and output in Crystal. # @@ -1137,4 +1139,16 @@ module IO end end -require "./io/*" +# require "./io/*" +require "./io/argf.cr" +require "./io/buffered.cr" +require "./io/byte_format.cr" +require "./io/console.cr" +require "./io/delimited.cr" +require "./io/encoding.cr" +require "./io/error.cr" +require "./io/file_descriptor.cr" +require "./io/hexdump.cr" +require "./io/memory.cr" +require "./io/multi_writer.cr" +require "./io/sized.cr" diff --git a/src/io/console.cr b/src/io/console.cr index e138c61bb999..48eb1dea0c38 100644 --- a/src/io/console.cr +++ b/src/io/console.cr @@ -1,114 +1,116 @@ -require "termios" +{% unless flag?(:windows) %} + require "termios" -class IO::FileDescriptor - # Turn off character echoing for the duration of the given block. - # This will prevent displaying back to the user what they enter on the terminal. - # Only call this when this IO is a TTY, such as a not redirected stdin. - # - # ``` - # print "Enter password: " - # password = STDIN.noecho &.gets.try &.chomp - # puts - # ``` - def noecho - preserving_tc_mode("can't set IO#noecho") do |mode| + class IO::FileDescriptor + # Turn off character echoing for the duration of the given block. + # This will prevent displaying back to the user what they enter on the terminal. + # Only call this when this IO is a TTY, such as a not redirected stdin. + # + # ``` + # print "Enter password: " + # password = STDIN.noecho &.gets.try &.chomp + # puts + # ``` + def noecho + preserving_tc_mode("can't set IO#noecho") do |mode| + noecho_from_tc_mode! + yield self + end + end + + # Turn off character echoing for this IO. + # This will prevent displaying back to the user what they enter on the terminal. + # Only call this when this IO is a TTY, such as a not redirected stdin. + def noecho! + if LibC.tcgetattr(fd, out mode) != 0 + raise Errno.new "can't set IO#noecho!" + end noecho_from_tc_mode! - yield self end - end - # Turn off character echoing for this IO. - # This will prevent displaying back to the user what they enter on the terminal. - # Only call this when this IO is a TTY, such as a not redirected stdin. - def noecho! - if LibC.tcgetattr(fd, out mode) != 0 - raise Errno.new "can't set IO#noecho!" + macro noecho_from_tc_mode! + mode.c_lflag &= ~(Termios::LocalMode.flags(ECHO, ECHOE, ECHOK, ECHONL).value) + LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(mode)) end - noecho_from_tc_mode! - end - macro noecho_from_tc_mode! - mode.c_lflag &= ~(Termios::LocalMode.flags(ECHO, ECHOE, ECHOK, ECHONL).value) - LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(mode)) - end + # Enable character processing for the duration of the given block. + # The so called cooked mode is the standard behavior of a terminal, + # doing line wise editing by the terminal and only sending the input to + # the program on a newline. + # Only call this when this IO is a TTY, such as a not redirected stdin. + def cooked + preserving_tc_mode("can't set IO#cooked") do |mode| + cooked_from_tc_mode! + yield self + end + end - # Enable character processing for the duration of the given block. - # The so called cooked mode is the standard behavior of a terminal, - # doing line wise editing by the terminal and only sending the input to - # the program on a newline. - # Only call this when this IO is a TTY, such as a not redirected stdin. - def cooked - preserving_tc_mode("can't set IO#cooked") do |mode| + # Enable character processing for this IO. + # The so called cooked mode is the standard behavior of a terminal, + # doing line wise editing by the terminal and only sending the input to + # the program on a newline. + # Only call this when this IO is a TTY, such as a not redirected stdin. + def cooked! + if LibC.tcgetattr(fd, out mode) != 0 + raise Errno.new "can't set IO#cooked!" + end cooked_from_tc_mode! - yield self end - end - # Enable character processing for this IO. - # The so called cooked mode is the standard behavior of a terminal, - # doing line wise editing by the terminal and only sending the input to - # the program on a newline. - # Only call this when this IO is a TTY, such as a not redirected stdin. - def cooked! - if LibC.tcgetattr(fd, out mode) != 0 - raise Errno.new "can't set IO#cooked!" + macro cooked_from_tc_mode! + mode.c_iflag |= (Termios::InputMode::BRKINT | + Termios::InputMode::ISTRIP | + Termios::InputMode::ICRNL | + Termios::InputMode::IXON).value + mode.c_oflag |= Termios::OutputMode::OPOST.value + mode.c_lflag |= (Termios::LocalMode::ECHO | + Termios::LocalMode::ECHOE | + Termios::LocalMode::ECHOK | + Termios::LocalMode::ECHONL | + Termios::LocalMode::ICANON | + Termios::LocalMode::ISIG | + Termios::LocalMode::IEXTEN).value + LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(mode)) end - cooked_from_tc_mode! - end - macro cooked_from_tc_mode! - mode.c_iflag |= (Termios::InputMode::BRKINT | - Termios::InputMode::ISTRIP | - Termios::InputMode::ICRNL | - Termios::InputMode::IXON).value - mode.c_oflag |= Termios::OutputMode::OPOST.value - mode.c_lflag |= (Termios::LocalMode::ECHO | - Termios::LocalMode::ECHOE | - Termios::LocalMode::ECHOK | - Termios::LocalMode::ECHONL | - Termios::LocalMode::ICANON | - Termios::LocalMode::ISIG | - Termios::LocalMode::IEXTEN).value - LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(mode)) - end + # Enable raw mode for the duration of the given block. + # In raw mode every keypress is directly sent to the program, no interpretation + # is done by the terminal. + # Only call this when this IO is a TTY, such as a not redirected stdin. + def raw + preserving_tc_mode("can't set IO#raw") do |mode| + raw_from_tc_mode! + yield self + end + end + + # Enable raw mode for this IO. + # In raw mode every keypress is directly sent to the program, no interpretation + # is done by the terminal. + # Only call this when this IO is a TTY, such as a not redirected stdin. + def raw! + if LibC.tcgetattr(fd, out mode) != 0 + raise Errno.new "can't set IO#raw!" + end - # Enable raw mode for the duration of the given block. - # In raw mode every keypress is directly sent to the program, no interpretation - # is done by the terminal. - # Only call this when this IO is a TTY, such as a not redirected stdin. - def raw - preserving_tc_mode("can't set IO#raw") do |mode| raw_from_tc_mode! - yield self end - end - # Enable raw mode for this IO. - # In raw mode every keypress is directly sent to the program, no interpretation - # is done by the terminal. - # Only call this when this IO is a TTY, such as a not redirected stdin. - def raw! - if LibC.tcgetattr(fd, out mode) != 0 - raise Errno.new "can't set IO#raw!" + macro raw_from_tc_mode! + LibC.cfmakeraw(pointerof(mode)) + LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(mode)) end - raw_from_tc_mode! - end - - macro raw_from_tc_mode! - LibC.cfmakeraw(pointerof(mode)) - LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(mode)) - end - - private def preserving_tc_mode(msg) - if LibC.tcgetattr(fd, out mode) != 0 - raise Errno.new msg - end - before = mode - begin - yield mode - ensure - LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(before)) + private def preserving_tc_mode(msg) + if LibC.tcgetattr(fd, out mode) != 0 + raise Errno.new msg + end + before = mode + begin + yield mode + ensure + LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(before)) + end end end -end +{% end %} diff --git a/src/io/file_descriptor.cr b/src/io/file_descriptor.cr index 7122f216a936..d6b6f02c7cd9 100644 --- a/src/io/file_descriptor.cr +++ b/src/io/file_descriptor.cr @@ -1,375 +1,5 @@ -require "c/fcntl" - -# An `IO` over a file descriptor. -class IO::FileDescriptor - include Buffered - - @read_timeout : Float64? - @write_timeout : Float64? - @read_event : Event::Event? - @write_event : Event::Event? - - # :nodoc: - property read_timed_out : Bool - property write_timed_out : Bool - - def initialize(@fd : Int32, blocking = false, edge_triggerable = false) - @edge_triggerable = !!edge_triggerable - @closed = false - @read_timed_out = false - @write_timed_out = false - @fd = fd - - unless blocking - self.blocking = false - if @edge_triggerable - @read_event = Scheduler.create_fd_read_event(self, @edge_triggerable) - @write_event = Scheduler.create_fd_write_event(self, @edge_triggerable) - end - end - end - - # Set the number of seconds to wait when reading before raising an `IO::Timeout`. - def read_timeout=(read_timeout : Number) - @read_timeout = read_timeout.to_f - end - - # ditto - def read_timeout=(read_timeout : Time::Span) - self.read_timeout = read_timeout.total_seconds - end - - # Sets no timeout on read operations, so an `IO::Timeout` will never be raised. - def read_timeout=(read_timeout : Nil) - @read_timeout = nil - end - - # Set the number of seconds to wait when writing before raising an `IO::Timeout`. - def write_timeout=(write_timeout : Number) - @write_timeout = write_timeout.to_f - end - - # ditto - def write_timeout=(write_timeout : Time::Span) - self.write_timeout = write_timeout.total_seconds - end - - # Sets no timeout on write operations, so an `IO::Timeout` will never be raised. - def write_timeout=(write_timeout : Nil) - @write_timeout = nil - end - - def blocking - fcntl(LibC::F_GETFL) & LibC::O_NONBLOCK == 0 - end - - def blocking=(value) - flags = fcntl(LibC::F_GETFL) - if value - flags &= ~LibC::O_NONBLOCK - else - flags |= LibC::O_NONBLOCK - end - fcntl(LibC::F_SETFL, flags) - end - - def close_on_exec? - flags = fcntl(LibC::F_GETFD) - (flags & LibC::FD_CLOEXEC) == LibC::FD_CLOEXEC - end - - def close_on_exec=(arg : Bool) - fcntl(LibC::F_SETFD, arg ? LibC::FD_CLOEXEC : 0) - arg - end - - def self.fcntl(fd, cmd, arg = 0) - r = LibC.fcntl fd, cmd, arg - raise Errno.new("fcntl() failed") if r == -1 - r - end - - def fcntl(cmd, arg = 0) - self.class.fcntl @fd, cmd, arg - end - - # :nodoc: - def resume_read - if reader = @readers.try &.shift? - reader.resume - end - end - - # :nodoc: - def resume_write - if writer = @writers.try &.shift? - writer.resume - end - end - - def stat - if LibC.fstat(@fd, out stat) != 0 - raise Errno.new("Unable to get stat") - end - File::Stat.new(stat) - end - - # Seeks to a given *offset* (in bytes) according to the *whence* argument. - # Returns `self`. - # - # ``` - # File.write("testfile", "abc") - # - # file = File.new("testfile") - # file.gets(3) # => "abc" - # file.seek(1, IO::Seek::Set) - # file.gets(2) # => "bc" - # file.seek(-1, IO::Seek::Current) - # file.gets(1) # => "c" - # ``` - def seek(offset, whence : Seek = Seek::Set) - check_open - - flush - seek_value = LibC.lseek(@fd, offset, whence) - if seek_value == -1 - raise Errno.new "Unable to seek" - end - - @in_buffer_rem = Bytes.empty - - self - end - - # Same as `seek` but yields to the block after seeking and eventually seeks - # back to the original position when the block returns. - def seek(offset, whence : Seek = Seek::Set) - original_pos = tell - begin - seek(offset, whence) - yield - ensure - seek(original_pos) - end - end - - # Same as `pos`. - def tell - pos - end - - # Returns the current position (in bytes) in this `IO`. - # - # ``` - # File.write("testfile", "hello") - # - # file = File.new("testfile") - # file.pos # => 0 - # file.gets(2) # => "he" - # file.pos # => 2 - # ``` - def pos - check_open - - seek_value = LibC.lseek(@fd, 0, Seek::Current) - raise Errno.new "Unable to tell" if seek_value == -1 - - seek_value - @in_buffer_rem.size - end - - # Sets the current position (in bytes) in this `IO`. - # - # ``` - # File.write("testfile", "hello") - # - # file = File.new("testfile") - # file.pos = 3 - # file.gets_to_end # => "lo" - # ``` - def pos=(value) - seek value - value - end - - def fd - @fd - end - - def finalize - return if closed? - - close rescue nil - end - - def closed? - @closed - end - - def tty? - LibC.isatty(fd) == 1 - end - - def reopen(other : IO::FileDescriptor) - if LibC.dup2(other.fd, self.fd) == -1 - raise Errno.new("Could not reopen file descriptor") - end - - # flag is lost after dup - self.close_on_exec = true - - other - end - - def inspect(io) - io << "#" - io - end - - def pretty_print(pp) - pp.text inspect - end - - private def unbuffered_read(slice : Bytes) - count = slice.size - loop do - bytes_read = LibC.read(@fd, slice.pointer(count).as(Void*), count) - if bytes_read != -1 - return bytes_read - end - - if Errno.value == Errno::EAGAIN - wait_readable - else - raise Errno.new "Error reading file" - end - end - ensure - if (readers = @readers) && !readers.empty? - add_read_event - end - end - - private def unbuffered_write(slice : Bytes) - count = slice.size - total = count - loop do - bytes_written = LibC.write(@fd, slice.pointer(count).as(Void*), count) - if bytes_written != -1 - count -= bytes_written - return total if count == 0 - slice += bytes_written - else - if Errno.value == Errno::EAGAIN - wait_writable - next - elsif Errno.value == Errno::EBADF - raise IO::Error.new "File not open for writing" - else - raise Errno.new "Error writing file" - end - end - end - ensure - if (writers = @writers) && !writers.empty? - add_write_event - end - end - - private def wait_readable - wait_readable { |err| raise err } - end - - private def wait_readable - readers = (@readers ||= Deque(Fiber).new) - readers << Fiber.current - add_read_event - Scheduler.reschedule - - if @read_timed_out - @read_timed_out = false - yield Timeout.new("Read timed out") - end - - nil - end - - private def add_read_event - return if @edge_triggerable - event = @read_event ||= Scheduler.create_fd_read_event(self) - event.add @read_timeout - nil - end - - private def wait_writable(timeout = @write_timeout) - wait_writable(timeout: timeout) { |err| raise err } - end - - # msg/timeout are overridden in nonblock_connect - private def wait_writable(msg = "Write timed out", timeout = @write_timeout) - writers = (@writers ||= Deque(Fiber).new) - writers << Fiber.current - add_write_event timeout - Scheduler.reschedule - - if @write_timed_out - @write_timed_out = false - yield Timeout.new(msg) - end - - nil - end - - private def add_write_event(timeout = @write_timeout) - return if @edge_triggerable - event = @write_event ||= Scheduler.create_fd_write_event(self) - event.add timeout - nil - end - - private def unbuffered_rewind - seek(0, IO::Seek::Set) - self - end - - private def unbuffered_close - return if @closed - - err = nil - if LibC.close(@fd) != 0 - case Errno.value - when Errno::EINTR, Errno::EINPROGRESS - # ignore - else - err = Errno.new("Error closing file") - end - end - - @closed = true - - @read_event.try &.free - @read_event = nil - @write_event.try &.free - @write_event = nil - if readers = @readers - Scheduler.enqueue readers - readers.clear - end - - if writers = @writers - Scheduler.enqueue writers - writers.clear - end - - raise err if err - end - - private def unbuffered_flush - # Nothing - end -end +{% if flag?(:windows) %} + require "./file_descriptor.windows.cr" +{% else %} + require "./file_descriptor.posix.cr" +{% end %} diff --git a/src/io/file_descriptor.posix.cr b/src/io/file_descriptor.posix.cr new file mode 100644 index 000000000000..7122f216a936 --- /dev/null +++ b/src/io/file_descriptor.posix.cr @@ -0,0 +1,375 @@ +require "c/fcntl" + +# An `IO` over a file descriptor. +class IO::FileDescriptor + include Buffered + + @read_timeout : Float64? + @write_timeout : Float64? + @read_event : Event::Event? + @write_event : Event::Event? + + # :nodoc: + property read_timed_out : Bool + property write_timed_out : Bool + + def initialize(@fd : Int32, blocking = false, edge_triggerable = false) + @edge_triggerable = !!edge_triggerable + @closed = false + @read_timed_out = false + @write_timed_out = false + @fd = fd + + unless blocking + self.blocking = false + if @edge_triggerable + @read_event = Scheduler.create_fd_read_event(self, @edge_triggerable) + @write_event = Scheduler.create_fd_write_event(self, @edge_triggerable) + end + end + end + + # Set the number of seconds to wait when reading before raising an `IO::Timeout`. + def read_timeout=(read_timeout : Number) + @read_timeout = read_timeout.to_f + end + + # ditto + def read_timeout=(read_timeout : Time::Span) + self.read_timeout = read_timeout.total_seconds + end + + # Sets no timeout on read operations, so an `IO::Timeout` will never be raised. + def read_timeout=(read_timeout : Nil) + @read_timeout = nil + end + + # Set the number of seconds to wait when writing before raising an `IO::Timeout`. + def write_timeout=(write_timeout : Number) + @write_timeout = write_timeout.to_f + end + + # ditto + def write_timeout=(write_timeout : Time::Span) + self.write_timeout = write_timeout.total_seconds + end + + # Sets no timeout on write operations, so an `IO::Timeout` will never be raised. + def write_timeout=(write_timeout : Nil) + @write_timeout = nil + end + + def blocking + fcntl(LibC::F_GETFL) & LibC::O_NONBLOCK == 0 + end + + def blocking=(value) + flags = fcntl(LibC::F_GETFL) + if value + flags &= ~LibC::O_NONBLOCK + else + flags |= LibC::O_NONBLOCK + end + fcntl(LibC::F_SETFL, flags) + end + + def close_on_exec? + flags = fcntl(LibC::F_GETFD) + (flags & LibC::FD_CLOEXEC) == LibC::FD_CLOEXEC + end + + def close_on_exec=(arg : Bool) + fcntl(LibC::F_SETFD, arg ? LibC::FD_CLOEXEC : 0) + arg + end + + def self.fcntl(fd, cmd, arg = 0) + r = LibC.fcntl fd, cmd, arg + raise Errno.new("fcntl() failed") if r == -1 + r + end + + def fcntl(cmd, arg = 0) + self.class.fcntl @fd, cmd, arg + end + + # :nodoc: + def resume_read + if reader = @readers.try &.shift? + reader.resume + end + end + + # :nodoc: + def resume_write + if writer = @writers.try &.shift? + writer.resume + end + end + + def stat + if LibC.fstat(@fd, out stat) != 0 + raise Errno.new("Unable to get stat") + end + File::Stat.new(stat) + end + + # Seeks to a given *offset* (in bytes) according to the *whence* argument. + # Returns `self`. + # + # ``` + # File.write("testfile", "abc") + # + # file = File.new("testfile") + # file.gets(3) # => "abc" + # file.seek(1, IO::Seek::Set) + # file.gets(2) # => "bc" + # file.seek(-1, IO::Seek::Current) + # file.gets(1) # => "c" + # ``` + def seek(offset, whence : Seek = Seek::Set) + check_open + + flush + seek_value = LibC.lseek(@fd, offset, whence) + if seek_value == -1 + raise Errno.new "Unable to seek" + end + + @in_buffer_rem = Bytes.empty + + self + end + + # Same as `seek` but yields to the block after seeking and eventually seeks + # back to the original position when the block returns. + def seek(offset, whence : Seek = Seek::Set) + original_pos = tell + begin + seek(offset, whence) + yield + ensure + seek(original_pos) + end + end + + # Same as `pos`. + def tell + pos + end + + # Returns the current position (in bytes) in this `IO`. + # + # ``` + # File.write("testfile", "hello") + # + # file = File.new("testfile") + # file.pos # => 0 + # file.gets(2) # => "he" + # file.pos # => 2 + # ``` + def pos + check_open + + seek_value = LibC.lseek(@fd, 0, Seek::Current) + raise Errno.new "Unable to tell" if seek_value == -1 + + seek_value - @in_buffer_rem.size + end + + # Sets the current position (in bytes) in this `IO`. + # + # ``` + # File.write("testfile", "hello") + # + # file = File.new("testfile") + # file.pos = 3 + # file.gets_to_end # => "lo" + # ``` + def pos=(value) + seek value + value + end + + def fd + @fd + end + + def finalize + return if closed? + + close rescue nil + end + + def closed? + @closed + end + + def tty? + LibC.isatty(fd) == 1 + end + + def reopen(other : IO::FileDescriptor) + if LibC.dup2(other.fd, self.fd) == -1 + raise Errno.new("Could not reopen file descriptor") + end + + # flag is lost after dup + self.close_on_exec = true + + other + end + + def inspect(io) + io << "#" + io + end + + def pretty_print(pp) + pp.text inspect + end + + private def unbuffered_read(slice : Bytes) + count = slice.size + loop do + bytes_read = LibC.read(@fd, slice.pointer(count).as(Void*), count) + if bytes_read != -1 + return bytes_read + end + + if Errno.value == Errno::EAGAIN + wait_readable + else + raise Errno.new "Error reading file" + end + end + ensure + if (readers = @readers) && !readers.empty? + add_read_event + end + end + + private def unbuffered_write(slice : Bytes) + count = slice.size + total = count + loop do + bytes_written = LibC.write(@fd, slice.pointer(count).as(Void*), count) + if bytes_written != -1 + count -= bytes_written + return total if count == 0 + slice += bytes_written + else + if Errno.value == Errno::EAGAIN + wait_writable + next + elsif Errno.value == Errno::EBADF + raise IO::Error.new "File not open for writing" + else + raise Errno.new "Error writing file" + end + end + end + ensure + if (writers = @writers) && !writers.empty? + add_write_event + end + end + + private def wait_readable + wait_readable { |err| raise err } + end + + private def wait_readable + readers = (@readers ||= Deque(Fiber).new) + readers << Fiber.current + add_read_event + Scheduler.reschedule + + if @read_timed_out + @read_timed_out = false + yield Timeout.new("Read timed out") + end + + nil + end + + private def add_read_event + return if @edge_triggerable + event = @read_event ||= Scheduler.create_fd_read_event(self) + event.add @read_timeout + nil + end + + private def wait_writable(timeout = @write_timeout) + wait_writable(timeout: timeout) { |err| raise err } + end + + # msg/timeout are overridden in nonblock_connect + private def wait_writable(msg = "Write timed out", timeout = @write_timeout) + writers = (@writers ||= Deque(Fiber).new) + writers << Fiber.current + add_write_event timeout + Scheduler.reschedule + + if @write_timed_out + @write_timed_out = false + yield Timeout.new(msg) + end + + nil + end + + private def add_write_event(timeout = @write_timeout) + return if @edge_triggerable + event = @write_event ||= Scheduler.create_fd_write_event(self) + event.add timeout + nil + end + + private def unbuffered_rewind + seek(0, IO::Seek::Set) + self + end + + private def unbuffered_close + return if @closed + + err = nil + if LibC.close(@fd) != 0 + case Errno.value + when Errno::EINTR, Errno::EINPROGRESS + # ignore + else + err = Errno.new("Error closing file") + end + end + + @closed = true + + @read_event.try &.free + @read_event = nil + @write_event.try &.free + @write_event = nil + if readers = @readers + Scheduler.enqueue readers + readers.clear + end + + if writers = @writers + Scheduler.enqueue writers + writers.clear + end + + raise err if err + end + + private def unbuffered_flush + # Nothing + end +end diff --git a/src/io/file_descriptor.windows.cr b/src/io/file_descriptor.windows.cr new file mode 100644 index 000000000000..c2ff71f53998 --- /dev/null +++ b/src/io/file_descriptor.windows.cr @@ -0,0 +1,239 @@ +# An `IO` over a file descriptor. +class IO::FileDescriptor + include Buffered + + # :nodoc: + property overlappeds = Hash(LibWindows::Overlapped*, Fiber?).new + + def initialize(@handle : LibWindows::Handle) + @edge_triggerable = false # HACK to make docs build in ci. + @closed = false + @pos = 0_u64 + @async = Scheduler.attach_to_completion_port(@handle, self) + end + + # def self.fcntl(handle, cmd, arg = 0) + # r = LibC.fcntl handle, cmd, arg + # raise Errno.new("fcntl() failed") if r == -1 + # r + # end + + # def fcntl(cmd, arg = 0) + # self.class.fcntl @handle, cmd, arg + # end + + def stat + if LibC.fstat(@handle, out stat) != 0 + raise Errno.new("Unable to get stat") + end + File::Stat.new(stat) + end + + # Seeks to a given *offset* (in bytes) according to the *whence* argument. + # Returns `self`. + # + # ``` + # File.write("testfile", "abc") + # + # file = File.new("testfile") + # file.gets(3) # => "abc" + # file.seek(1, IO::Seek::Set) + # file.gets(2) # => "bc" + # file.seek(-1, IO::Seek::Current) + # file.gets(1) # => "c" + # ``` + def seek(offset, whence : Seek = Seek::Set) + check_open + + flush + seek_value = LibC.lseek(@handle, offset, whence) + if seek_value == -1 + raise Errno.new "Unable to seek" + end + + @in_buffer_rem = Bytes.empty + + self + end + + # Same as `seek` but yields to the block after seeking and eventually seeks + # back to the original position when the block returns. + def seek(offset, whence : Seek = Seek::Set) + original_pos = tell + begin + seek(offset, whence) + yield + ensure + seek(original_pos) + end + end + + # Same as `pos`. + def tell + pos + end + + # Returns the current position (in bytes) in this `IO`. + # + # ``` + # File.write("testfile", "hello") + # + # file = File.new("testfile") + # file.pos # => 0 + # file.gets(2) # => "he" + # file.pos # => 2 + # ``` + def pos + check_open + + seek_value = LibC.lseek(@handle, 0, Seek::Current) + raise Errno.new "Unable to tell" if seek_value == -1 + + seek_value - @in_buffer_rem.size + end + + # Sets the current position (in bytes) in this `IO`. + # + # ``` + # File.write("testfile", "hello") + # + # file = File.new("testfile") + # file.pos = 3 + # file.gets_to_end # => "lo" + # ``` + def pos=(value) + seek value + value + end + + def handle + @handle + end + + def finalize + return if closed? + + close rescue nil + end + + def closed? + @closed + end + + def tty? + LibWindows.get_file_type(@handle) == LibWindows::FILE_TYPE_CHAR + end + + def reopen(other : IO::FileDescriptor) + if LibC.dup2(other.handle, self.handle) == -1 + raise Errno.new("Could not reopen file descriptor") + end + + # flag is lost after dup + self.close_on_exec = true + + other + end + + def inspect(io) + io << "#" + io + end + + def pretty_print(pp) + pp.text inspect + end + + private def unbuffered_read(slice : Bytes) + overlapped = Pointer(LibWindows::Overlapped).malloc + overlapped.value = LibWindows::Overlapped.new + overlapped.value.offset = @pos + LibWindows.read_file(@handle, slice.pointer(slice.size), slice.size, out bytes_read, overlapped) + status = LibWindows.get_last_error + if status == WinError::ERROR_IO_PENDING + @overlappeds[overlapped] = Fiber.current + Scheduler.reschedule + status = overlapped.value.status.to_u32 + bytes_read = overlapped.value.bytes_transfered + elsif @async + # See unbuffered_write + @overlappeds[overlapped] = nil + end + + if status == WinError::ERROR_SUCCESS + @pos += bytes_read + return bytes_read + elsif status == WinError::ERROR_HANDLE_EOF + return 0 + else + raise WinError.new "ReadFile", status + end + end + + private def unbuffered_write(slice : Bytes) + count = slice.size + total = count + loop do + overlapped = Pointer(LibWindows::Overlapped).malloc + overlapped.value = LibWindows::Overlapped.new + overlapped.value.offset = @pos + LibWindows.write_file(@handle, slice.pointer(count), count, out bytes_written, overlapped) + status = LibWindows.get_last_error + if status == WinError::ERROR_IO_PENDING + @overlappeds[overlapped] = Fiber.current + Scheduler.reschedule + status = overlapped.value.status.to_u32 + bytes_written = overlapped.value.bytes_transfered + elsif @async + # Even though the operation already completed, this IO is asynchronous and a completion notification + # will be triggered ai the IOCP (Scheduler). This means the overlapped pointer still remain valid. + # It is saved in the @overlappeds Hash to prevent GC collection. We can return the results now and + # simply ignore the event later. + @overlappeds[overlapped] = nil + end + + if status == WinError::ERROR_SUCCESS + @pos += bytes_written + count -= bytes_written + return total if count == 0 + slice += bytes_written + else + raise WinError.new "WriteFile", status + end + end + end + + # :nodoc: + def resume_overlapped(overlapped_ptr) + # @overlappeds will not contain this overlapped if the call returned success earlier + @overlappeds.delete(overlapped_ptr).try &.resume + end + + private def unbuffered_rewind + seek(0, IO::Seek::Set) + self + end + + private def unbuffered_close + return if @closed + + err = nil + unless LibWindows.close_handle(@handle) + err = "Error closing file" + end + + @closed = true + + raise err if err + end + + private def unbuffered_flush + # Nothing + end +end diff --git a/src/kernel.cr b/src/kernel.cr index 3ac84528b2aa..0f24da185ca5 100644 --- a/src/kernel.cr +++ b/src/kernel.cr @@ -1,8 +1,14 @@ -require "c/unistd" - -STDIN = IO::FileDescriptor.new(0, blocking: LibC.isatty(0) == 0) -STDOUT = (IO::FileDescriptor.new(1, blocking: LibC.isatty(1) == 0)).tap { |f| f.flush_on_newline = true } -STDERR = (IO::FileDescriptor.new(2, blocking: LibC.isatty(2) == 0)).tap { |f| f.flush_on_newline = true } +{% if flag?(:windows) %} + STDIN = IO::FileDescriptor.new(LibWindows.get_std_handle(LibWindows::STD_INPUT_HANDLE)) + STDOUT = IO::FileDescriptor.new(LibWindows.get_std_handle(LibWindows::STD_OUTPUT_HANDLE)).tap { |f| f.flush_on_newline = true } + STDERR = IO::FileDescriptor.new(LibWindows.get_std_handle(LibWindows::STD_ERROR_HANDLE)).tap { |f| f.flush_on_newline = true } +{% else %} + require "c/unistd" + + STDIN = IO::FileDescriptor.new(0, blocking: LibC.isatty(0) == 0) + STDOUT = (IO::FileDescriptor.new(1, blocking: LibC.isatty(1) == 0)).tap { |f| f.flush_on_newline = true } + STDERR = (IO::FileDescriptor.new(2, blocking: LibC.isatty(2) == 0)).tap { |f| f.flush_on_newline = true } +{% end %} PROGRAM_NAME = String.new(ARGV_UNSAFE.value) ARGV = (ARGV_UNSAFE + 1).to_slice(ARGC_UNSAFE - 1).map { |c_str| String.new(c_str) } @@ -190,9 +196,10 @@ class Process end end -Signal.setup_default_handlers - -at_exit { Event::SignalHandler.close } +{% if !flag?(:windows) %} + Signal.setup_default_handlers + at_exit { Event::SignalHandler.close } +{% end %} # Background loop to cleanup unused fiber stacks. spawn do diff --git a/src/lib_c/x86_64-windows-gnu/c/fcntl.cr b/src/lib_c/x86_64-windows-gnu/c/fcntl.cr new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/lib_c/x86_64-windows-gnu/c/iconv.cr b/src/lib_c/x86_64-windows-gnu/c/iconv.cr new file mode 100644 index 000000000000..230d65f69cda --- /dev/null +++ b/src/lib_c/x86_64-windows-gnu/c/iconv.cr @@ -0,0 +1,3 @@ +lib LibC + type IconvT = Void* +end diff --git a/src/lib_c/x86_64-windows-gnu/c/stddef.cr b/src/lib_c/x86_64-windows-gnu/c/stddef.cr new file mode 100644 index 000000000000..4afcdf34d723 --- /dev/null +++ b/src/lib_c/x86_64-windows-gnu/c/stddef.cr @@ -0,0 +1,3 @@ +lib LibC + alias SizeT = ULong +end diff --git a/src/lib_c/x86_64-windows-gnu/c/stdint.cr b/src/lib_c/x86_64-windows-gnu/c/stdint.cr new file mode 100644 index 000000000000..f1aae04d919e --- /dev/null +++ b/src/lib_c/x86_64-windows-gnu/c/stdint.cr @@ -0,0 +1,10 @@ +lib LibC + alias Int8T = SChar + alias Int16T = Short + alias Int32T = Int + alias Int64T = Long + alias UInt8T = Char + alias UInt16T = UShort + alias UInt32T = UInt + alias UInt64T = ULong +end diff --git a/src/lib_c/x86_64-windows-gnu/c/stdio.cr b/src/lib_c/x86_64-windows-gnu/c/stdio.cr new file mode 100644 index 000000000000..3164236ccc45 --- /dev/null +++ b/src/lib_c/x86_64-windows-gnu/c/stdio.cr @@ -0,0 +1,8 @@ +# require "./sys/types" +require "./stddef" + +lib LibC + fun printf(format : Char*, ...) : Int + fun rename(old : Char*, new : Char*) : Int + fun snprintf(s : Char*, maxlen : SizeT, format : Char*, ...) : Int +end diff --git a/src/lib_c/x86_64-windows-gnu/c/stdlib.cr b/src/lib_c/x86_64-windows-gnu/c/stdlib.cr new file mode 100644 index 000000000000..2408cdba1ed2 --- /dev/null +++ b/src/lib_c/x86_64-windows-gnu/c/stdlib.cr @@ -0,0 +1,25 @@ +require "./stddef" + +# require "./sys/wait" + +lib LibC + struct DivT + quot : Int + rem : Int + end + + fun atof(nptr : Char*) : Double + fun div(numer : Int, denom : Int) : DivT + fun exit(status : Int) : NoReturn + fun free(ptr : Void*) : Void + fun getenv(name : Char*) : Char* + fun malloc(size : SizeT) : Void* + fun mkstemp(template : Char*) : Int + fun putenv(string : Char*) : Int + fun realloc(ptr : Void*, size : SizeT) : Void* + fun realpath(name : Char*, resolved : Char*) : Char* + fun setenv(name : Char*, value : Char*, replace : Int) : Int + fun strtof(nptr : Char*, endptr : Char**) : Float + fun strtod(nptr : Char*, endptr : Char**) : Double + fun unsetenv(name : Char*) : Int +end diff --git a/src/lib_c/x86_64-windows-gnu/c/string.cr b/src/lib_c/x86_64-windows-gnu/c/string.cr new file mode 100644 index 000000000000..8c156408e6ae --- /dev/null +++ b/src/lib_c/x86_64-windows-gnu/c/string.cr @@ -0,0 +1,8 @@ +require "./stddef" + +lib LibC + fun memchr(x0 : Void*, c : Int, n : SizeT) : Void* + fun memcmp(s1 : Void*, s2 : Void*, n : SizeT) : Int + fun strcmp(s1 : Char*, s2 : Char*) : Int + fun strlen(s : Char*) : SizeT +end diff --git a/src/lib_c/x86_64-windows-gnu/c/sys/stat.cr b/src/lib_c/x86_64-windows-gnu/c/sys/stat.cr new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/lib_c/x86_64-windows-gnu/c/time.cr b/src/lib_c/x86_64-windows-gnu/c/time.cr new file mode 100644 index 000000000000..048deabad160 --- /dev/null +++ b/src/lib_c/x86_64-windows-gnu/c/time.cr @@ -0,0 +1,41 @@ +lib LibC + CLOCK_MONOTONIC = 1 + CLOCK_REALTIME = 0 + + alias SusecondsT = Long + alias TimeT = Long + + struct Timeval + tv_sec : TimeT + tv_usec : SusecondsT + end + + struct Tm + tm_sec : Int + tm_min : Int + tm_hour : Int + tm_mday : Int + tm_mon : Int + tm_year : Int + tm_wday : Int + tm_yday : Int + tm_isdst : Int + tm_gmtoff : Long + tm_zone : Char* + end + + struct Timespec + tv_sec : TimeT + tv_nsec : Long + end + + fun gmtime_r(timer : TimeT*, tp : Tm*) : Tm* + fun localtime_r(timer : TimeT*, tp : Tm*) : Tm* + fun mktime(tp : Tm*) : TimeT + fun tzset : Void + fun timegm(tp : Tm*) : TimeT + + $daylight : Int + $timezone : Long + $tzname : StaticArray(Char*, 2) +end diff --git a/src/lib_c/x86_64-windows-gnu/c/unistd.cr b/src/lib_c/x86_64-windows-gnu/c/unistd.cr new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/lib_windows.cr b/src/lib_windows.cr new file mode 100644 index 000000000000..dd32b9d39da9 --- /dev/null +++ b/src/lib_windows.cr @@ -0,0 +1,139 @@ +@[CallConvention("X86_StdCall")] +lib LibWindows + STD_INPUT_HANDLE = 0xFFFFFFF6_u32 + STD_OUTPUT_HANDLE = 0xFFFFFFF5_u32 + STD_ERROR_HANDLE = 0xFFFFFFF4_u32 + + FILE_TYPE_UNKNOWN = 0x0000 + FILE_TYPE_DISK = 0x0001 + FILE_TYPE_CHAR = 0x0002 + FILE_TYPE_PIPE = 0x0003 + FILE_TYPE_REMOTE = 0x8000 + + GENERIC_EXECUTE = 0x20000000 + GENERIC_WRITE = 0x40000000 + GENERIC_READ = 0x80000000 + + CREATE_NEW = 1 + CREATE_ALWAYS = 2 + OPEN_EXISTING = 3 + OPEN_ALWAYS = 4 + TRUNCATE_EXISTING = 5 + + FILE_FLAG_OVERLAPPED = 0x40000000 + + # source https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx + alias Long = Int32 + alias Word = UInt16 + alias WChar = UInt16 + alias DWord = UInt32 + alias Handle = Void* + alias SizeT = UInt64 # FIXME + + INVALID_HANDLE_VALUE = Pointer(Void).new((-1).to_u64) + INFINITY = 0xFFFFFFFF_u32 + + fun duplicate_handle = DuplicateHandle(source_process : Handle, source : Handle, target_process : Handle, target : Handle*, desired_access : DWord, inherit_handle : Bool, options : DWord) : Bool + + struct Overlapped + status : SizeT + bytes_transfered : SizeT + offset : UInt64 + event : Handle + end + + struct SecurityAttributes + length : DWord + security_descriptors : Void* + inherit_handle : Bool + end + + fun get_std_handle = GetStdHandle(std_handle : DWord) : Handle + fun get_file_type = GetFileType(file : Handle) : DWord + fun create_file = CreateFileA(filename : UInt8*, access : DWord, sharemode : DWord, security_attributes : SecurityAttributes*, creation : DWord, flags : DWord, template : Handle) : Handle + fun read_file = ReadFile(file : Handle, buffer : UInt8*, size : DWord, read : DWord*, overlapped : Overlapped*) : Bool + fun write_file = WriteFile(file : Handle, buffer : UInt8*, size : DWord, written : DWord*, overlapped : Overlapped*) : Bool + fun close_handle = CloseHandle(file : Handle) : Bool + + fun create_io_completion_port = CreateIoCompletionPort(file : Handle, port : Handle, data : Void*, threads : DWord) : Handle + fun get_queued_completion_status = GetQueuedCompletionStatus(port : Handle, bytes_transfered : DWord*, data : Void**, entry : Overlapped**, timeout_millis : DWord) : Bool + fun post_queued_completion_status = PostQueuedCompletionStatus(port : Handle, bytes_transfered : DWord, data : Void*, entry : Overlapped*) : Bool + fun get_current_process = GetCurrentProcess : Handle + fun get_current_thread = GetCurrentThread : Handle + + WAIT_ABANDONED = 0x00000080_u32 + WAIT_OBJECT_0 = 0x00000000_u32 + WAIT_TIMEOUT = 0x00000102_u32 + WAIT_FAILED = 0xFFFFFFFF_u32 + + fun wait_for_single_object = WaitForSingleObject(handle : Handle, timeout_millis : DWord) : DWord + fun create_timer_queue_timer = CreateTimerQueueTimer(timer_handle : Handle*, queue_handle : Handle, callback : (Void*, Bool) ->, data : Void*, due : DWord, period : DWord, flags : SizeT) : Bool + fun delete_timer_queue_timer = DeleteTimerQueueTimer(queue_handle : Handle, timer_handle : Handle, completion_event : Handle) : Bool + fun get_last_error = GetLastError : DWord + + FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100_u32 + FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200_u32 + FORMAT_MESSAGE_FROM_STRING = 0x00000400_u32 + FORMAT_MESSAGE_FROM_HMODULE = 0x00000800_u32 + FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000_u32 + FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000_u32 + + fun format_message = FormatMessageA(flags : DWord, source : Void*, msg : DWord, lang : DWord, buffer : UInt8*, size : DWord, args : Void*) : DWord + + WSASYSNOTREADY = 10091 + WSAVERNOTSUPPORTED = 10092 + WSAEINPROGRESS = 10036 + WSAEPROCLIM = 10067 + WSAEFAULT = 10014 + WSAEINVAL = 10022 + + struct WSAData + version : UInt16 + high_version : UInt16 + description : UInt8[257] + system_status : UInt8[129] + max_sockets : UInt16 + max_udp_datagram : UInt16 + vendor_info : UInt8* + end + + fun wsa_startup = WSAStartup(version : Int16, data : WSAData*) : Int32 + + # source https://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx + struct SystemTime + year : Word + month : Word + day_of_week : Word + day : Word + hour : Word + minute : Word + second : Word + milliseconds : Word + end + + # source https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx + struct TimeZoneInformation + bias : Long + standard_name : StaticArray(WChar, 32) + standard_date : SystemTime + standard_bias : Long + daylight_name : StaticArray(WChar, 32) + daylight_date : SystemTime + daylight_bias : Long + end + + struct FileTime + low_date_time : DWord + high_date_time : DWord + end + + fun get_time_zone_information = GetTimeZoneInformation(tz_info : TimeZoneInformation*) : DWord + fun get_system_time_as_file_time = GetSystemTimeAsFileTime(time : FileTime*) +end + +require "winerror.cr" + +data = uninitialized LibWindows::WSAData +if LibWindows.wsa_startup(0x0202, pointerof(data)) != 0 + raise WinError.new "WSAStartup" +end diff --git a/src/process.cr b/src/process.cr index ebe70c5536c6..f8d2deca89f9 100644 --- a/src/process.cr +++ b/src/process.cr @@ -1,8 +1,10 @@ -require "c/signal" require "c/stdlib" -require "c/sys/times" -require "c/sys/wait" -require "c/unistd" +{% if !flag?(:windows) %} + require "c/signal" + require "c/sys/times" + require "c/sys/wait" + require "c/unistd" +{% end %} class Process # Terminate the current process immediately. All open files, pipes and sockets diff --git a/src/raise.cr b/src/raise.cr index 68e606ce66f0..8a5609104da2 100644 --- a/src/raise.cr +++ b/src/raise.cr @@ -176,13 +176,21 @@ fun __crystal_get_exception(unwind_ex : LibUnwind::Exception*) : UInt64 end def raise(ex : Exception) : NoReturn - ex.callstack = CallStack.new - unwind_ex = Pointer(LibUnwind::Exception).malloc - unwind_ex.value.exception_class = LibC::SizeT.zero - unwind_ex.value.exception_cleanup = LibC::SizeT.zero - unwind_ex.value.exception_object = ex.object_id - unwind_ex.value.exception_type_id = ex.crystal_type_id - __crystal_raise(unwind_ex) + {% if flag?(:windows) %} + data = ex.inspect_with_backtrace.to_slice + count = data.size + stderr = LibWindows.get_std_handle(LibWindows::STD_ERROR_HANDLE) + LibWindows.write_file(stderr, data.pointer(count), count, nil, nil) + LibC.exit 1 + {% else %} + ex.callstack = CallStack.new + unwind_ex = Pointer(LibUnwind::Exception).malloc + unwind_ex.value.exception_class = LibC::SizeT.zero + unwind_ex.value.exception_cleanup = LibC::SizeT.zero + unwind_ex.value.exception_object = ex.object_id + unwind_ex.value.exception_type_id = ex.crystal_type_id + __crystal_raise(unwind_ex) + {% end %} end def raise(message : String) : NoReturn diff --git a/src/regex.cr b/src/regex.cr index c87d1ba24e59..13a8cadd83e5 100644 --- a/src/regex.cr +++ b/src/regex.cr @@ -1,4 +1,6 @@ -require "./regex/*" +{% if !flag?(:windows) %} + require "./regex/*" +{% end %} # A `Regex` represents a regular expression, a pattern that describes the # contents of strings. A `Regex` can determine whether or not a string matches diff --git a/src/thread.cr b/src/thread.cr index 8102a033dbe0..941ca8343667 100644 --- a/src/thread.cr +++ b/src/thread.cr @@ -1,98 +1,7 @@ -require "c/pthread" require "./thread/*" -# :nodoc: -class Thread - # Don't use this class, it is used internally by the event scheduler. - # Use spawn and channels instead. - - @th : LibC::PthreadT? - @exception : Exception? - @detached = false - - property current_fiber - - def initialize(&@func : ->) - @current_fiber = uninitialized Fiber - @@threads << self - - ret = LibGC.pthread_create(out th, nil, ->(data) { - (data.as(Thread)).start - }, self.as(Void*)) - @th = th - - if ret != 0 - raise Errno.new("pthread_create") - end - end - - def initialize - @current_fiber = uninitialized Fiber - @func = ->{} - @@threads << self - @th = LibC.pthread_self - end - - def finalize - LibGC.pthread_detach(@th.not_nil!) unless @detached - end - - def join - if LibGC.pthread_join(@th.not_nil!, out _ret) != 0 - raise Errno.new("pthread_join") - end - @detached = true - - if exception = @exception - raise exception - end - end - - # All threads, so the GC can see them (GC doesn't scan thread locals) - # and we can find the current thread on platforms that don't support - # thread local storage (eg: OpenBSD) - @@threads = Set(Thread).new - - {% if flag?(:openbsd) %} - @@main = new - - def self.current : Thread - if LibC.pthread_main_np == 1 - return @@main - end - - current_thread_id = LibC.pthread_self - - current_thread = @@threads.find do |thread| - LibC.pthread_equal(thread.id, current_thread_id) != 0 - end - - raise "Error: failed to find current thread" unless current_thread - current_thread - end - - protected def id - @th.not_nil! - end - {% else %} - @[ThreadLocal] - @@current = new - - def self.current - @@current - end - {% end %} - - protected def start - {% unless flag?(:openbsd) %} - @@current = self - {% end %} - begin - @func.call - rescue ex - @exception = ex - ensure - @@threads.delete(self) - end - end -end +{% if flag?(:windows) %} + require "./thread.windows.cr" +{% else %} + require "./thread.posix.cr" +{% end %} diff --git a/src/thread.posix.cr b/src/thread.posix.cr new file mode 100644 index 000000000000..729d4d12b213 --- /dev/null +++ b/src/thread.posix.cr @@ -0,0 +1,97 @@ +require "c/pthread" + +# :nodoc: +class Thread + # Don't use this class, it is used internally by the event scheduler. + # Use spawn and channels instead. + + @th : LibC::PthreadT? + @exception : Exception? + @detached = false + + property current_fiber + + def initialize(&@func : ->) + @current_fiber = uninitialized Fiber + @@threads << self + + ret = LibGC.pthread_create(out th, nil, ->(data) { + (data.as(Thread)).start + }, self.as(Void*)) + @th = th + + if ret != 0 + raise Errno.new("pthread_create") + end + end + + def initialize + @current_fiber = uninitialized Fiber + @func = ->{} + @@threads << self + @th = LibC.pthread_self + end + + def finalize + LibGC.pthread_detach(@th.not_nil!) unless @detached + end + + def join + if LibGC.pthread_join(@th.not_nil!, out _ret) != 0 + raise Errno.new("pthread_join") + end + @detached = true + + if exception = @exception + raise exception + end + end + + # All threads, so the GC can see them (GC doesn't scan thread locals) + # and we can find the current thread on platforms that don't support + # thread local storage (eg: OpenBSD) + @@threads = Set(Thread).new + + {% if flag?(:openbsd) %} + @@main = new + + def self.current : Thread + if LibC.pthread_main_np == 1 + return @@main + end + + current_thread_id = LibC.pthread_self + + current_thread = @@threads.find do |thread| + LibC.pthread_equal(thread.id, current_thread_id) != 0 + end + + raise "Error: failed to find current thread" unless current_thread + current_thread + end + + protected def id + @th.not_nil! + end + {% else %} + @[ThreadLocal] + @@current = new + + def self.current + @@current + end + {% end %} + + protected def start + {% unless flag?(:openbsd) %} + @@current = self + {% end %} + begin + @func.call + rescue ex + @exception = ex + ensure + @@threads.delete(self) + end + end +end diff --git a/src/thread.windows.cr b/src/thread.windows.cr new file mode 100644 index 000000000000..5118ba356573 --- /dev/null +++ b/src/thread.windows.cr @@ -0,0 +1,70 @@ +# :nodoc: +class Thread + # Don't use this class, it is used internally by the event scheduler. + # Use spawn and channels instead. + + @th : LibWindows::Handle? + @exception : Exception? + + property current_fiber + + def initialize(&@func : ->) + @current_fiber = uninitialized Fiber + @@threads << self + @th = LibGC.create_thread(nil, 0, ->(data) { + (data.as(Thread)).start + return 0u32 + }, self.as(Void*), 0, nil) + + if @th.not_nil!.null? + raise WinError.new "CreateThread" + end + end + + def initialize + @current_fiber = uninitialized Fiber + @func = ->{} + @@threads << self + proc = LibWindows.get_current_process + th = LibWindows.get_current_thread + LibWindows.duplicate_handle(proc, th, proc, pointerof(th), 0, false, 0) + @th = th + end + + def finalize + LibWindows.close_handle(@th.not_nil!) + end + + def join + if LibWindows.wait_for_single_object(@th.not_nil!, LibWindows::INFINITY) != LibWindows::WAIT_OBJECT_0 + raise WinError.new "WaitForSingleObject" + end + + if exception = @exception + raise exception + end + end + + # All threads, so the GC can see them (GC doesn't scan thread locals) + # and we can find the current thread on platforms that don't support + # thread local storage (eg: OpenBSD) + @@threads = Set(Thread).new + + @[ThreadLocal] + @@current = new + + def self.current + @@current + end + + protected def start + @@current = self + begin + @func.call + rescue ex + @exception = ex + ensure + @@threads.delete(self) + end + end +end diff --git a/src/thread/condition_variable.cr b/src/thread/condition_variable.cr index 2eb8c26d72d4..8a3341f141b4 100644 --- a/src/thread/condition_variable.cr +++ b/src/thread/condition_variable.cr @@ -1,4 +1,6 @@ -require "c/pthread" +{% if !flag?(:windows) %} + require "c/pthread" +{% end %} # :nodoc: class Thread diff --git a/src/thread/mutex.cr b/src/thread/mutex.cr index f1241a0c6549..92fdbb3a61b2 100644 --- a/src/thread/mutex.cr +++ b/src/thread/mutex.cr @@ -1,4 +1,6 @@ -require "c/pthread" +{% if !flag?(:windows) %} + require "c/pthread" +{% end %} # :nodoc: class Thread diff --git a/src/time.cr b/src/time.cr index 8b62b3d846f8..20edd3632052 100644 --- a/src/time.cr +++ b/src/time.cr @@ -1,4 +1,6 @@ -require "c/sys/time" +{% if !flag?(:windows) %} + require "c/sys/time" +{% end %} require "c/time" # `Time` represents an instance in time. Here are some examples: @@ -613,10 +615,19 @@ struct Time {% end %} unless offset - # current TZ may have DST, either in past, present or future - ret = LibC.localtime_r(pointerof(second), out tm) - raise Errno.new("localtime_r") if ret.null? - offset = tm.tm_gmtoff.to_i64 + {% if !flag?(:windows) %} + # current TZ may have DST, either in past, present or future + ret = LibC.localtime_r(pointerof(second), out tm) + raise Errno.new("localtime_r") if ret.null? + offset = tm.tm_gmtoff.to_i64 + {% else %} + # TODO handle daylight? + # https://msdn.microsoft.com/en-us/library/windows/desktop/ms724421(v=vs.85).aspx + ret = LibWindows.get_time_zone_information(out tz) + raise WinError.new("GetTimeZoneInformation") if ret == -1 + # UTC = local time + bias + return tz.bias.to_i64 * - Span::TicksPerMinute + {% end %} end offset / 60 * Span::TicksPerMinute @@ -627,6 +638,11 @@ struct Time ret = LibC.gettimeofday(out timeval, nil) raise Errno.new("gettimeofday") unless ret == 0 {timeval.tv_sec, timeval.tv_usec.to_i64 * 10} + {% elsif flag?(:windows) %} + LibWindows.get_system_time_as_file_time(out filetime) + winticks = (filetime.high_date_time.to_u64 << 32) | filetime.low_date_time.to_u64 + # winticks start in 1601. unix in 1970. + { (winticks / 10_000_000i64) - 11644473600i64, (winticks % 10_000_000) * 10 } {% else %} ret = LibC.clock_gettime(LibC::CLOCK_REALTIME, out timespec) raise Errno.new("clock_gettime") unless ret == 0 diff --git a/src/windows-prelude.cr b/src/windows-prelude.cr new file mode 100644 index 000000000000..61db1577a9b8 --- /dev/null +++ b/src/windows-prelude.cr @@ -0,0 +1,66 @@ +require "lib_c" +require "macros" +require "object" +require "comparable" +require "exception" +require "iterable" +require "iterator" +require "indexable" +require "string" + +require "array" +require "atomic" +require "bool" +require "box" +require "char" +require "char/reader" +require "class" +require "concurrent" +require "deque" +# require "dir" +require "enum" +require "enumerable" +require "env" +# require "errno" +require "ext" +require "file" +require "float" +require "gc" +# # require "gc/null" +require "gc/boehm" +require "hash" +require "iconv" +require "int" +require "intrinsics" +require "io" +require "kernel" +require "main" +require "math/math" +# require "mutex" +require "named_tuple" +require "nil" +require "number" +require "pointer" +require "pretty_print" +require "primitives" +require "proc" +require "process" +require "raise" +require "random" +require "range" +require "reference" +require "reflect" +# require "regex" +require "set" +# require "signal" +require "slice" +require "static_array" +require "struct" +require "symbol" +# require "system" +require "thread" +require "time" +require "tuple" +require "unicode" +require "union" +require "value" diff --git a/src/winerror.cr b/src/winerror.cr new file mode 100644 index 000000000000..d70cab0c26b6 --- /dev/null +++ b/src/winerror.cr @@ -0,0 +1,2104 @@ +class WinError < Exception + property code : UInt32 + + # NOTE: `get_last_error` must be called BEFORE an instance of this class + # is malloced as it would change the "last error" to SUCCESS + def self.new(message) + new(message, LibWindows.get_last_error) + end + + def initialize(message, @code) + buffer = uninitialized UInt8[256] + size = LibWindows.format_message(LibWindows::FORMAT_MESSAGE_FROM_SYSTEM, nil, @code, 0, buffer, buffer.size, nil) + details = String.new(buffer.to_unsafe, size).strip + super "#{message}: #{details}" + end + + ERROR_SUCCESS = 0_u32 + ERROR_INVALID_FUNCTION = 1_u32 + ERROR_FILE_NOT_FOUND = 2_u32 + ERROR_PATH_NOT_FOUND = 3_u32 + ERROR_TOO_MANY_OPEN_FILES = 4_u32 + ERROR_ACCESS_DENIED = 5_u32 + ERROR_INVALID_HANDLE = 6_u32 + ERROR_ARENA_TRASHED = 7_u32 + ERROR_NOT_ENOUGH_MEMORY = 8_u32 + ERROR_INVALID_BLOCK = 9_u32 + ERROR_BAD_ENVIRONMENT = 10_u32 + ERROR_BAD_FORMAT = 11_u32 + ERROR_INVALID_ACCESS = 12_u32 + ERROR_INVALID_DATA = 13_u32 + ERROR_OUTOFMEMORY = 14_u32 + ERROR_INVALID_DRIVE = 15_u32 + ERROR_CURRENT_DIRECTORY = 16_u32 + ERROR_NOT_SAME_DEVICE = 17_u32 + ERROR_NO_MORE_FILES = 18_u32 + ERROR_WRITE_PROTECT = 19_u32 + ERROR_BAD_UNIT = 20_u32 + ERROR_NOT_READY = 21_u32 + ERROR_BAD_COMMAND = 22_u32 + ERROR_CRC = 23_u32 + ERROR_BAD_LENGTH = 24_u32 + ERROR_SEEK = 25_u32 + ERROR_NOT_DOS_DISK = 26_u32 + ERROR_SECTOR_NOT_FOUND = 27_u32 + ERROR_OUT_OF_PAPER = 28_u32 + ERROR_WRITE_FAULT = 29_u32 + ERROR_READ_FAULT = 30_u32 + ERROR_GEN_FAILURE = 31_u32 + ERROR_SHARING_VIOLATION = 32_u32 + ERROR_LOCK_VIOLATION = 33_u32 + ERROR_WRONG_DISK = 34_u32 + ERROR_SHARING_BUFFER_EXCEEDED = 36_u32 + ERROR_HANDLE_EOF = 38_u32 + ERROR_HANDLE_DISK_FULL = 39_u32 + ERROR_NOT_SUPPORTED = 50_u32 + ERROR_REM_NOT_LIST = 51_u32 + ERROR_DUP_NAME = 52_u32 + ERROR_BAD_NETPATH = 53_u32 + ERROR_NETWORK_BUSY = 54_u32 + ERROR_DEV_NOT_EXIST = 55_u32 + ERROR_TOO_MANY_CMDS = 56_u32 + ERROR_ADAP_HDW_ERR = 57_u32 + ERROR_BAD_NET_RESP = 58_u32 + ERROR_UNEXP_NET_ERR = 59_u32 + ERROR_BAD_REM_ADAP = 60_u32 + ERROR_PRINTQ_FULL = 61_u32 + ERROR_NO_SPOOL_SPACE = 62_u32 + ERROR_PRINT_CANCELLED = 63_u32 + ERROR_NETNAME_DELETED = 64_u32 + ERROR_NETWORK_ACCESS_DENIED = 65_u32 + ERROR_BAD_DEV_TYPE = 66_u32 + ERROR_BAD_NET_NAME = 67_u32 + ERROR_TOO_MANY_NAMES = 68_u32 + ERROR_TOO_MANY_SESS = 69_u32 + ERROR_SHARING_PAUSED = 70_u32 + ERROR_REQ_NOT_ACCEP = 71_u32 + ERROR_REDIR_PAUSED = 72_u32 + ERROR_FILE_EXISTS = 80_u32 + ERROR_CANNOT_MAKE = 82_u32 + ERROR_FAIL_I24 = 83_u32 + ERROR_OUT_OF_STRUCTURES = 84_u32 + ERROR_ALREADY_ASSIGNED = 85_u32 + ERROR_INVALID_PASSWORD = 86_u32 + ERROR_INVALID_PARAMETER = 87_u32 + ERROR_NET_WRITE_FAULT = 88_u32 + ERROR_NO_PROC_SLOTS = 89_u32 + ERROR_TOO_MANY_SEMAPHORES = 100_u32 + ERROR_EXCL_SEM_ALREADY_OWNED = 101_u32 + ERROR_SEM_IS_SET = 102_u32 + ERROR_TOO_MANY_SEM_REQUESTS = 103_u32 + ERROR_INVALID_AT_INTERRUPT_TIME = 104_u32 + ERROR_SEM_OWNER_DIED = 105_u32 + ERROR_SEM_USER_LIMIT = 106_u32 + ERROR_DISK_CHANGE = 107_u32 + ERROR_DRIVE_LOCKED = 108_u32 + ERROR_BROKEN_PIPE = 109_u32 + ERROR_OPEN_FAILED = 110_u32 + ERROR_BUFFER_OVERFLOW = 111_u32 + ERROR_DISK_FULL = 112_u32 + ERROR_NO_MORE_SEARCH_HANDLES = 113_u32 + ERROR_INVALID_TARGET_HANDLE = 114_u32 + ERROR_INVALID_CATEGORY = 117_u32 + ERROR_INVALID_VERIFY_SWITCH = 118_u32 + ERROR_BAD_DRIVER_LEVEL = 119_u32 + ERROR_CALL_NOT_IMPLEMENTED = 120_u32 + ERROR_SEM_TIMEOUT = 121_u32 + ERROR_INSUFFICIENT_BUFFER = 122_u32 + ERROR_INVALID_NAME = 123_u32 + ERROR_INVALID_LEVEL = 124_u32 + ERROR_NO_VOLUME_LABEL = 125_u32 + ERROR_MOD_NOT_FOUND = 126_u32 + ERROR_PROC_NOT_FOUND = 127_u32 + ERROR_WAIT_NO_CHILDREN = 128_u32 + ERROR_CHILD_NOT_COMPLETE = 129_u32 + ERROR_DIRECT_ACCESS_HANDLE = 130_u32 + ERROR_NEGATIVE_SEEK = 131_u32 + ERROR_SEEK_ON_DEVICE = 132_u32 + ERROR_IS_JOIN_TARGET = 133_u32 + ERROR_IS_JOINED = 134_u32 + ERROR_IS_SUBSTED = 135_u32 + ERROR_NOT_JOINED = 136_u32 + ERROR_NOT_SUBSTED = 137_u32 + ERROR_JOIN_TO_JOIN = 138_u32 + ERROR_SUBST_TO_SUBST = 139_u32 + ERROR_JOIN_TO_SUBST = 140_u32 + ERROR_SUBST_TO_JOIN = 141_u32 + ERROR_BUSY_DRIVE = 142_u32 + ERROR_SAME_DRIVE = 143_u32 + ERROR_DIR_NOT_ROOT = 144_u32 + ERROR_DIR_NOT_EMPTY = 145_u32 + ERROR_IS_SUBST_PATH = 146_u32 + ERROR_IS_JOIN_PATH = 147_u32 + ERROR_PATH_BUSY = 148_u32 + ERROR_IS_SUBST_TARGET = 149_u32 + ERROR_SYSTEM_TRACE = 150_u32 + ERROR_INVALID_EVENT_COUNT = 151_u32 + ERROR_TOO_MANY_MUXWAITERS = 152_u32 + ERROR_INVALID_LIST_FORMAT = 153_u32 + ERROR_LABEL_TOO_LONG = 154_u32 + ERROR_TOO_MANY_TCBS = 155_u32 + ERROR_SIGNAL_REFUSED = 156_u32 + ERROR_DISCARDED = 157_u32 + ERROR_NOT_LOCKED = 158_u32 + ERROR_BAD_THREADID_ADDR = 159_u32 + ERROR_BAD_ARGUMENTS = 160_u32 + ERROR_BAD_PATHNAME = 161_u32 + ERROR_SIGNAL_PENDING = 162_u32 + ERROR_MAX_THRDS_REACHED = 164_u32 + ERROR_LOCK_FAILED = 167_u32 + ERROR_BUSY = 170_u32 + ERROR_CANCEL_VIOLATION = 173_u32 + ERROR_ATOMIC_LOCKS_NOT_SUPPORTED = 174_u32 + ERROR_INVALID_SEGMENT_NUMBER = 180_u32 + ERROR_INVALID_ORDINAL = 182_u32 + ERROR_ALREADY_EXISTS = 183_u32 + ERROR_INVALID_FLAG_NUMBER = 186_u32 + ERROR_SEM_NOT_FOUND = 187_u32 + ERROR_INVALID_STARTING_CODESEG = 188_u32 + ERROR_INVALID_STACKSEG = 189_u32 + ERROR_INVALID_MODULETYPE = 190_u32 + ERROR_INVALID_EXE_SIGNATURE = 191_u32 + ERROR_EXE_MARKED_INVALID = 192_u32 + ERROR_BAD_EXE_FORMAT = 193_u32 + ERROR_ITERATED_DATA_EXCEEDS_64k = 194_u32 + ERROR_INVALID_MINALLOCSIZE = 195_u32 + ERROR_DYNLINK_FROM_INVALID_RING = 196_u32 + ERROR_IOPL_NOT_ENABLED = 197_u32 + ERROR_INVALID_SEGDPL = 198_u32 + ERROR_AUTODATASEG_EXCEEDS_64k = 199_u32 + ERROR_RING2SEG_MUST_BE_MOVABLE = 200_u32 + ERROR_RELOC_CHAIN_XEEDS_SEGLIM = 201_u32 + ERROR_INFLOOP_IN_RELOC_CHAIN = 202_u32 + ERROR_ENVVAR_NOT_FOUND = 203_u32 + ERROR_NO_SIGNAL_SENT = 205_u32 + ERROR_FILENAME_EXCED_RANGE = 206_u32 + ERROR_RING2_STACK_IN_USE = 207_u32 + ERROR_META_EXPANSION_TOO_LONG = 208_u32 + ERROR_INVALID_SIGNAL_NUMBER = 209_u32 + ERROR_THREAD_1_INACTIVE = 210_u32 + ERROR_LOCKED = 212_u32 + ERROR_TOO_MANY_MODULES = 214_u32 + ERROR_NESTING_NOT_ALLOWED = 215_u32 + ERROR_EXE_MACHINE_TYPE_MISMATCH = 216_u32 + ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY = 217_u32 + ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY = 218_u32 + ERROR_FILE_CHECKED_OUT = 220_u32 + ERROR_CHECKOUT_REQUIRED = 221_u32 + ERROR_BAD_FILE_TYPE = 222_u32 + ERROR_FILE_TOO_LARGE = 223_u32 + ERROR_FORMS_AUTH_REQUIRED = 224_u32 + ERROR_PIPE_LOCAL = 229_u32 + ERROR_BAD_PIPE = 230_u32 + ERROR_PIPE_BUSY = 231_u32 + ERROR_NO_DATA = 232_u32 + ERROR_PIPE_NOT_CONNECTED = 233_u32 + ERROR_MORE_DATA = 234_u32 + ERROR_VC_DISCONNECTED = 240_u32 + ERROR_INVALID_EA_NAME = 254_u32 + ERROR_EA_LIST_INCONSISTENT = 255_u32 + WAIT_TIMEOUT = 258_u32 + ERROR_NO_MORE_ITEMS = 259_u32 + ERROR_CANNOT_COPY = 266_u32 + ERROR_DIRECTORY = 267_u32 + ERROR_EAS_DIDNT_FIT = 275_u32 + ERROR_EA_FILE_CORRUPT = 276_u32 + ERROR_EA_TABLE_FULL = 277_u32 + ERROR_INVALID_EA_HANDLE = 278_u32 + ERROR_EAS_NOT_SUPPORTED = 282_u32 + ERROR_NOT_OWNER = 288_u32 + ERROR_TOO_MANY_POSTS = 298_u32 + ERROR_PARTIAL_COPY = 299_u32 + ERROR_OPLOCK_NOT_GRANTED = 300_u32 + ERROR_INVALID_OPLOCK_PROTOCOL = 301_u32 + ERROR_DISK_TOO_FRAGMENTED = 302_u32 + ERROR_DELETE_PENDING = 303_u32 + ERROR_MR_MID_NOT_FOUND = 317_u32 + ERROR_SCOPE_NOT_FOUND = 318_u32 + ERROR_INVALID_ADDRESS = 487_u32 + ERROR_ARITHMETIC_OVERFLOW = 534_u32 + ERROR_PIPE_CONNECTED = 535_u32 + ERROR_PIPE_LISTENING = 536_u32 + ERROR_WAKE_SYSTEM = 730_u32 + ERROR_WAIT_1 = 731_u32 + ERROR_WAIT_2 = 732_u32 + ERROR_WAIT_3 = 733_u32 + ERROR_WAIT_63 = 734_u32 + ERROR_ABANDONED_WAIT_0 = 735_u32 + ERROR_ABANDONED_WAIT_63 = 736_u32 + ERROR_USER_APC = 737_u32 + ERROR_KERNEL_APC = 738_u32 + ERROR_ALERTED = 739_u32 + ERROR_EA_ACCESS_DENIED = 994_u32 + ERROR_OPERATION_ABORTED = 995_u32 + ERROR_IO_INCOMPLETE = 996_u32 + ERROR_IO_PENDING = 997_u32 + ERROR_NOACCESS = 998_u32 + ERROR_SWAPERROR = 999_u32 + ERROR_STACK_OVERFLOW = 1001_u32 + ERROR_INVALID_MESSAGE = 1002_u32 + ERROR_CAN_NOT_COMPLETE = 1003_u32 + ERROR_INVALID_FLAGS = 1004_u32 + ERROR_UNRECOGNIZED_VOLUME = 1005_u32 + ERROR_FILE_INVALID = 1006_u32 + ERROR_FULLSCREEN_MODE = 1007_u32 + ERROR_NO_TOKEN = 1008_u32 + ERROR_BADDB = 1009_u32 + ERROR_BADKEY = 1010_u32 + ERROR_CANTOPEN = 1011_u32 + ERROR_CANTREAD = 1012_u32 + ERROR_CANTWRITE = 1013_u32 + ERROR_REGISTRY_RECOVERED = 1014_u32 + ERROR_REGISTRY_CORRUPT = 1015_u32 + ERROR_REGISTRY_IO_FAILED = 1016_u32 + ERROR_NOT_REGISTRY_FILE = 1017_u32 + ERROR_KEY_DELETED = 1018_u32 + ERROR_NO_LOG_SPACE = 1019_u32 + ERROR_KEY_HAS_CHILDREN = 1020_u32 + ERROR_CHILD_MUST_BE_VOLATILE = 1021_u32 + ERROR_NOTIFY_ENUM_DIR = 1022_u32 + ERROR_DEPENDENT_SERVICES_RUNNING = 1051_u32 + ERROR_INVALID_SERVICE_CONTROL = 1052_u32 + ERROR_SERVICE_REQUEST_TIMEOUT = 1053_u32 + ERROR_SERVICE_NO_THREAD = 1054_u32 + ERROR_SERVICE_DATABASE_LOCKED = 1055_u32 + ERROR_SERVICE_ALREADY_RUNNING = 1056_u32 + ERROR_INVALID_SERVICE_ACCOUNT = 1057_u32 + ERROR_SERVICE_DISABLED = 1058_u32 + ERROR_CIRCULAR_DEPENDENCY = 1059_u32 + ERROR_SERVICE_DOES_NOT_EXIST = 1060_u32 + ERROR_SERVICE_CANNOT_ACCEPT_CTRL = 1061_u32 + ERROR_SERVICE_NOT_ACTIVE = 1062_u32 + ERROR_FAILED_SERVICE_CONTROLLER_CONNECT = 1063_u32 + ERROR_EXCEPTION_IN_SERVICE = 1064_u32 + ERROR_DATABASE_DOES_NOT_EXIST = 1065_u32 + ERROR_SERVICE_SPECIFIC_ERROR = 1066_u32 + ERROR_PROCESS_ABORTED = 1067_u32 + ERROR_SERVICE_DEPENDENCY_FAIL = 1068_u32 + ERROR_SERVICE_LOGON_FAILED = 1069_u32 + ERROR_SERVICE_START_HANG = 1070_u32 + ERROR_INVALID_SERVICE_LOCK = 1071_u32 + ERROR_SERVICE_MARKED_FOR_DELETE = 1072_u32 + ERROR_SERVICE_EXISTS = 1073_u32 + ERROR_ALREADY_RUNNING_LKG = 1074_u32 + ERROR_SERVICE_DEPENDENCY_DELETED = 1075_u32 + ERROR_BOOT_ALREADY_ACCEPTED = 1076_u32 + ERROR_SERVICE_NEVER_STARTED = 1077_u32 + ERROR_DUPLICATE_SERVICE_NAME = 1078_u32 + ERROR_DIFFERENT_SERVICE_ACCOUNT = 1079_u32 + ERROR_CANNOT_DETECT_DRIVER_FAILURE = 1080_u32 + ERROR_CANNOT_DETECT_PROCESS_ABORT = 1081_u32 + ERROR_NO_RECOVERY_PROGRAM = 1082_u32 + ERROR_SERVICE_NOT_IN_EXE = 1083_u32 + ERROR_NOT_SAFEBOOT_SERVICE = 1084_u32 + ERROR_END_OF_MEDIA = 1100_u32 + ERROR_FILEMARK_DETECTED = 1101_u32 + ERROR_BEGINNING_OF_MEDIA = 1102_u32 + ERROR_SETMARK_DETECTED = 1103_u32 + ERROR_NO_DATA_DETECTED = 1104_u32 + ERROR_PARTITION_FAILURE = 1105_u32 + ERROR_INVALID_BLOCK_LENGTH = 1106_u32 + ERROR_DEVICE_NOT_PARTITIONED = 1107_u32 + ERROR_UNABLE_TO_LOCK_MEDIA = 1108_u32 + ERROR_UNABLE_TO_UNLOAD_MEDIA = 1109_u32 + ERROR_MEDIA_CHANGED = 1110_u32 + ERROR_BUS_RESET = 1111_u32 + ERROR_NO_MEDIA_IN_DRIVE = 1112_u32 + ERROR_NO_UNICODE_TRANSLATION = 1113_u32 + ERROR_DLL_INIT_FAILED = 1114_u32 + ERROR_SHUTDOWN_IN_PROGRESS = 1115_u32 + ERROR_NO_SHUTDOWN_IN_PROGRESS = 1116_u32 + ERROR_IO_DEVICE = 1117_u32 + ERROR_SERIAL_NO_DEVICE = 1118_u32 + ERROR_IRQ_BUSY = 1119_u32 + ERROR_MORE_WRITES = 1120_u32 + ERROR_COUNTER_TIMEOUT = 1121_u32 + ERROR_FLOPPY_ID_MARK_NOT_FOUND = 1122_u32 + ERROR_FLOPPY_WRONG_CYLINDER = 1123_u32 + ERROR_FLOPPY_UNKNOWN_ERROR = 1124_u32 + ERROR_FLOPPY_BAD_REGISTERS = 1125_u32 + ERROR_DISK_RECALIBRATE_FAILED = 1126_u32 + ERROR_DISK_OPERATION_FAILED = 1127_u32 + ERROR_DISK_RESET_FAILED = 1128_u32 + ERROR_EOM_OVERFLOW = 1129_u32 + ERROR_NOT_ENOUGH_SERVER_MEMORY = 1130_u32 + ERROR_POSSIBLE_DEADLOCK = 1131_u32 + ERROR_MAPPED_ALIGNMENT = 1132_u32 + ERROR_SET_POWER_STATE_VETOED = 1140_u32 + ERROR_SET_POWER_STATE_FAILED = 1141_u32 + ERROR_TOO_MANY_LINKS = 1142_u32 + ERROR_OLD_WIN_VERSION = 1150_u32 + ERROR_APP_WRONG_OS = 1151_u32 + ERROR_SINGLE_INSTANCE_APP = 1152_u32 + ERROR_RMODE_APP = 1153_u32 + ERROR_INVALID_DLL = 1154_u32 + ERROR_NO_ASSOCIATION = 1155_u32 + ERROR_DDE_FAIL = 1156_u32 + ERROR_DLL_NOT_FOUND = 1157_u32 + ERROR_NO_MORE_USER_HANDLES = 1158_u32 + ERROR_MESSAGE_SYNC_ONLY = 1159_u32 + ERROR_SOURCE_ELEMENT_EMPTY = 1160_u32 + ERROR_DESTINATION_ELEMENT_FULL = 1161_u32 + ERROR_ILLEGAL_ELEMENT_ADDRESS = 1162_u32 + ERROR_MAGAZINE_NOT_PRESENT = 1163_u32 + ERROR_DEVICE_REINITIALIZATION_NEEDED = 1164_u32 + ERROR_DEVICE_REQUIRES_CLEANING = 1165_u32 + ERROR_DEVICE_DOOR_OPEN = 1166_u32 + ERROR_DEVICE_NOT_CONNECTED = 1167_u32 + ERROR_NOT_FOUND = 1168_u32 + ERROR_NO_MATCH = 1169_u32 + ERROR_SET_NOT_FOUND = 1170_u32 + ERROR_POINT_NOT_FOUND = 1171_u32 + ERROR_NO_TRACKING_SERVICE = 1172_u32 + ERROR_NO_VOLUME_ID = 1173_u32 + ERROR_UNABLE_TO_REMOVE_REPLACED = 1175_u32 + ERROR_UNABLE_TO_MOVE_REPLACEMENT = 1176_u32 + ERROR_UNABLE_TO_MOVE_REPLACEMENT_2 = 1177_u32 + ERROR_JOURNAL_DELETE_IN_PROGRESS = 1178_u32 + ERROR_JOURNAL_NOT_ACTIVE = 1179_u32 + ERROR_POTENTIAL_FILE_FOUND = 1180_u32 + ERROR_JOURNAL_ENTRY_DELETED = 1181_u32 + ERROR_BAD_DEVICE = 1200_u32 + ERROR_CONNECTION_UNAVAIL = 1201_u32 + ERROR_DEVICE_ALREADY_REMEMBERED = 1202_u32 + ERROR_NO_NET_OR_BAD_PATH = 1203_u32 + ERROR_BAD_PROVIDER = 1204_u32 + ERROR_CANNOT_OPEN_PROFILE = 1205_u32 + ERROR_BAD_PROFILE = 1206_u32 + ERROR_NOT_CONTAINER = 1207_u32 + ERROR_EXTENDED_ERROR = 1208_u32 + ERROR_INVALID_GROUPNAME = 1209_u32 + ERROR_INVALID_COMPUTERNAME = 1210_u32 + ERROR_INVALID_EVENTNAME = 1211_u32 + ERROR_INVALID_DOMAINNAME = 1212_u32 + ERROR_INVALID_SERVICENAME = 1213_u32 + ERROR_INVALID_NETNAME = 1214_u32 + ERROR_INVALID_SHARENAME = 1215_u32 + ERROR_INVALID_PASSWORDNAME = 1216_u32 + ERROR_INVALID_MESSAGENAME = 1217_u32 + ERROR_INVALID_MESSAGEDEST = 1218_u32 + ERROR_SESSION_CREDENTIAL_CONFLICT = 1219_u32 + ERROR_REMOTE_SESSION_LIMIT_EXCEEDED = 1220_u32 + ERROR_DUP_DOMAINNAME = 1221_u32 + ERROR_NO_NETWORK = 1222_u32 + ERROR_CANCELLED = 1223_u32 + ERROR_USER_MAPPED_FILE = 1224_u32 + ERROR_CONNECTION_REFUSED = 1225_u32 + ERROR_GRACEFUL_DISCONNECT = 1226_u32 + ERROR_ADDRESS_ALREADY_ASSOCIATED = 1227_u32 + ERROR_ADDRESS_NOT_ASSOCIATED = 1228_u32 + ERROR_CONNECTION_INVALID = 1229_u32 + ERROR_CONNECTION_ACTIVE = 1230_u32 + ERROR_NETWORK_UNREACHABLE = 1231_u32 + ERROR_HOST_UNREACHABLE = 1232_u32 + ERROR_PROTOCOL_UNREACHABLE = 1233_u32 + ERROR_PORT_UNREACHABLE = 1234_u32 + ERROR_REQUEST_ABORTED = 1235_u32 + ERROR_CONNECTION_ABORTED = 1236_u32 + ERROR_RETRY = 1237_u32 + ERROR_CONNECTION_COUNT_LIMIT = 1238_u32 + ERROR_LOGIN_TIME_RESTRICTION = 1239_u32 + ERROR_LOGIN_WKSTA_RESTRICTION = 1240_u32 + ERROR_INCORRECT_ADDRESS = 1241_u32 + ERROR_ALREADY_REGISTERED = 1242_u32 + ERROR_SERVICE_NOT_FOUND = 1243_u32 + ERROR_NOT_AUTHENTICATED = 1244_u32 + ERROR_NOT_LOGGED_ON = 1245_u32 + ERROR_CONTINUE = 1246_u32 + ERROR_ALREADY_INITIALIZED = 1247_u32 + ERROR_NO_MORE_DEVICES = 1248_u32 + ERROR_NO_SUCH_SITE = 1249_u32 + ERROR_DOMAIN_CONTROLLER_EXISTS = 1250_u32 + ERROR_ONLY_IF_CONNECTED = 1251_u32 + ERROR_OVERRIDE_NOCHANGES = 1252_u32 + ERROR_BAD_USER_PROFILE = 1253_u32 + ERROR_NOT_SUPPORTED_ON_SBS = 1254_u32 + ERROR_SERVER_SHUTDOWN_IN_PROGRESS = 1255_u32 + ERROR_HOST_DOWN = 1256_u32 + ERROR_NON_ACCOUNT_SID = 1257_u32 + ERROR_NON_DOMAIN_SID = 1258_u32 + ERROR_APPHELP_BLOCK = 1259_u32 + ERROR_ACCESS_DISABLED_BY_POLICY = 1260_u32 + ERROR_REG_NAT_CONSUMPTION = 1261_u32 + ERROR_CSCSHARE_OFFLINE = 1262_u32 + ERROR_PKINIT_FAILURE = 1263_u32 + ERROR_SMARTCARD_SUBSYSTEM_FAILURE = 1264_u32 + ERROR_DOWNGRADE_DETECTED = 1265_u32 + ERROR_MACHINE_LOCKED = 1271_u32 + ERROR_CALLBACK_SUPPLIED_INVALID_DATA = 1273_u32 + ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED = 1274_u32 + ERROR_DRIVER_BLOCKED = 1275_u32 + ERROR_INVALID_IMPORT_OF_NON_DLL = 1276_u32 + ERROR_ACCESS_DISABLED_WEBBLADE = 1277_u32 + ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER = 1278_u32 + ERROR_RECOVERY_FAILURE = 1279_u32 + ERROR_ALREADY_FIBER = 1280_u32 + ERROR_ALREADY_THREAD = 1281_u32 + ERROR_STACK_BUFFER_OVERRUN = 1282_u32 + ERROR_PARAMETER_QUOTA_EXCEEDED = 1283_u32 + ERROR_DEBUGGER_INACTIVE = 1284_u32 + ERROR_DELAY_LOAD_FAILED = 1285_u32 + ERROR_VDM_DISALLOWED = 1286_u32 + ERROR_UNIDENTIFIED_ERROR = 1287_u32 + ERROR_NOT_ALL_ASSIGNED = 1300_u32 + ERROR_SOME_NOT_MAPPED = 1301_u32 + ERROR_NO_QUOTAS_FOR_ACCOUNT = 1302_u32 + ERROR_LOCAL_USER_SESSION_KEY = 1303_u32 + ERROR_NULL_LM_PASSWORD = 1304_u32 + ERROR_UNKNOWN_REVISION = 1305_u32 + ERROR_REVISION_MISMATCH = 1306_u32 + ERROR_INVALID_OWNER = 1307_u32 + ERROR_INVALID_PRIMARY_GROUP = 1308_u32 + ERROR_NO_IMPERSONATION_TOKEN = 1309_u32 + ERROR_CANT_DISABLE_MANDATORY = 1310_u32 + ERROR_NO_LOGON_SERVERS = 1311_u32 + ERROR_NO_SUCH_LOGON_SESSION = 1312_u32 + ERROR_NO_SUCH_PRIVILEGE = 1313_u32 + ERROR_PRIVILEGE_NOT_HELD = 1314_u32 + ERROR_INVALID_ACCOUNT_NAME = 1315_u32 + ERROR_USER_EXISTS = 1316_u32 + ERROR_NO_SUCH_USER = 1317_u32 + ERROR_GROUP_EXISTS = 1318_u32 + ERROR_NO_SUCH_GROUP = 1319_u32 + ERROR_MEMBER_IN_GROUP = 1320_u32 + ERROR_MEMBER_NOT_IN_GROUP = 1321_u32 + ERROR_LAST_ADMIN = 1322_u32 + ERROR_WRONG_PASSWORD = 1323_u32 + ERROR_ILL_FORMED_PASSWORD = 1324_u32 + ERROR_PASSWORD_RESTRICTION = 1325_u32 + ERROR_LOGON_FAILURE = 1326_u32 + ERROR_ACCOUNT_RESTRICTION = 1327_u32 + ERROR_INVALID_LOGON_HOURS = 1328_u32 + ERROR_INVALID_WORKSTATION = 1329_u32 + ERROR_PASSWORD_EXPIRED = 1330_u32 + ERROR_ACCOUNT_DISABLED = 1331_u32 + ERROR_NONE_MAPPED = 1332_u32 + ERROR_TOO_MANY_LUIDS_REQUESTED = 1333_u32 + ERROR_LUIDS_EXHAUSTED = 1334_u32 + ERROR_INVALID_SUB_AUTHORITY = 1335_u32 + ERROR_INVALID_ACL = 1336_u32 + ERROR_INVALID_SID = 1337_u32 + ERROR_INVALID_SECURITY_DESCR = 1338_u32 + ERROR_BAD_INHERITANCE_ACL = 1340_u32 + ERROR_SERVER_DISABLED = 1341_u32 + ERROR_SERVER_NOT_DISABLED = 1342_u32 + ERROR_INVALID_ID_AUTHORITY = 1343_u32 + ERROR_ALLOTTED_SPACE_EXCEEDED = 1344_u32 + ERROR_INVALID_GROUP_ATTRIBUTES = 1345_u32 + ERROR_BAD_IMPERSONATION_LEVEL = 1346_u32 + ERROR_CANT_OPEN_ANONYMOUS = 1347_u32 + ERROR_BAD_VALIDATION_CLASS = 1348_u32 + ERROR_BAD_TOKEN_TYPE = 1349_u32 + ERROR_NO_SECURITY_ON_OBJECT = 1350_u32 + ERROR_CANT_ACCESS_DOMAIN_INFO = 1351_u32 + ERROR_INVALID_SERVER_STATE = 1352_u32 + ERROR_INVALID_DOMAIN_STATE = 1353_u32 + ERROR_INVALID_DOMAIN_ROLE = 1354_u32 + ERROR_NO_SUCH_DOMAIN = 1355_u32 + ERROR_DOMAIN_EXISTS = 1356_u32 + ERROR_DOMAIN_LIMIT_EXCEEDED = 1357_u32 + ERROR_INTERNAL_DB_CORRUPTION = 1358_u32 + ERROR_INTERNAL_ERROR = 1359_u32 + ERROR_GENERIC_NOT_MAPPED = 1360_u32 + ERROR_BAD_DESCRIPTOR_FORMAT = 1361_u32 + ERROR_NOT_LOGON_PROCESS = 1362_u32 + ERROR_LOGON_SESSION_EXISTS = 1363_u32 + ERROR_NO_SUCH_PACKAGE = 1364_u32 + ERROR_BAD_LOGON_SESSION_STATE = 1365_u32 + ERROR_LOGON_SESSION_COLLISION = 1366_u32 + ERROR_INVALID_LOGON_TYPE = 1367_u32 + ERROR_CANNOT_IMPERSONATE = 1368_u32 + ERROR_RXACT_INVALID_STATE = 1369_u32 + ERROR_RXACT_COMMIT_FAILURE = 1370_u32 + ERROR_SPECIAL_ACCOUNT = 1371_u32 + ERROR_SPECIAL_GROUP = 1372_u32 + ERROR_SPECIAL_USER = 1373_u32 + ERROR_MEMBERS_PRIMARY_GROUP = 1374_u32 + ERROR_TOKEN_ALREADY_IN_USE = 1375_u32 + ERROR_NO_SUCH_ALIAS = 1376_u32 + ERROR_MEMBER_NOT_IN_ALIAS = 1377_u32 + ERROR_MEMBER_IN_ALIAS = 1378_u32 + ERROR_ALIAS_EXISTS = 1379_u32 + ERROR_LOGON_NOT_GRANTED = 1380_u32 + ERROR_TOO_MANY_SECRETS = 1381_u32 + ERROR_SECRET_TOO_LONG = 1382_u32 + ERROR_INTERNAL_DB_ERROR = 1383_u32 + ERROR_TOO_MANY_CONTEXT_IDS = 1384_u32 + ERROR_LOGON_TYPE_NOT_GRANTED = 1385_u32 + ERROR_NT_CROSS_ENCRYPTION_REQUIRED = 1386_u32 + ERROR_NO_SUCH_MEMBER = 1387_u32 + ERROR_INVALID_MEMBER = 1388_u32 + ERROR_TOO_MANY_SIDS = 1389_u32 + ERROR_LM_CROSS_ENCRYPTION_REQUIRED = 1390_u32 + ERROR_NO_INHERITANCE = 1391_u32 + ERROR_FILE_CORRUPT = 1392_u32 + ERROR_DISK_CORRUPT = 1393_u32 + ERROR_NO_USER_SESSION_KEY = 1394_u32 + ERROR_LICENSE_QUOTA_EXCEEDED = 1395_u32 + ERROR_WRONG_TARGET_NAME = 1396_u32 + ERROR_MUTUAL_AUTH_FAILED = 1397_u32 + ERROR_TIME_SKEW = 1398_u32 + ERROR_CURRENT_DOMAIN_NOT_ALLOWED = 1399_u32 + ERROR_INVALID_WINDOW_HANDLE = 1400_u32 + ERROR_INVALID_MENU_HANDLE = 1401_u32 + ERROR_INVALID_CURSOR_HANDLE = 1402_u32 + ERROR_INVALID_ACCEL_HANDLE = 1403_u32 + ERROR_INVALID_HOOK_HANDLE = 1404_u32 + ERROR_INVALID_DWP_HANDLE = 1405_u32 + ERROR_TLW_WITH_WSCHILD = 1406_u32 + ERROR_CANNOT_FIND_WND_CLASS = 1407_u32 + ERROR_WINDOW_OF_OTHER_THREAD = 1408_u32 + ERROR_HOTKEY_ALREADY_REGISTERED = 1409_u32 + ERROR_CLASS_ALREADY_EXISTS = 1410_u32 + ERROR_CLASS_DOES_NOT_EXIST = 1411_u32 + ERROR_CLASS_HAS_WINDOWS = 1412_u32 + ERROR_INVALID_INDEX = 1413_u32 + ERROR_INVALID_ICON_HANDLE = 1414_u32 + ERROR_PRIVATE_DIALOG_INDEX = 1415_u32 + ERROR_LISTBOX_ID_NOT_FOUND = 1416_u32 + ERROR_NO_WILDCARD_CHARACTERS = 1417_u32 + ERROR_CLIPBOARD_NOT_OPEN = 1418_u32 + ERROR_HOTKEY_NOT_REGISTERED = 1419_u32 + ERROR_WINDOW_NOT_DIALOG = 1420_u32 + ERROR_CONTROL_ID_NOT_FOUND = 1421_u32 + ERROR_INVALID_COMBOBOX_MESSAGE = 1422_u32 + ERROR_WINDOW_NOT_COMBOBOX = 1423_u32 + ERROR_INVALID_EDIT_HEIGHT = 1424_u32 + ERROR_DC_NOT_FOUND = 1425_u32 + ERROR_INVALID_HOOK_FILTER = 1426_u32 + ERROR_INVALID_FILTER_PROC = 1427_u32 + ERROR_HOOK_NEEDS_HMOD = 1428_u32 + ERROR_GLOBAL_ONLY_HOOK = 1429_u32 + ERROR_JOURNAL_HOOK_SET = 1430_u32 + ERROR_HOOK_NOT_INSTALLED = 1431_u32 + ERROR_INVALID_LB_MESSAGE = 1432_u32 + ERROR_SETCOUNT_ON_BAD_LB = 1433_u32 + ERROR_LB_WITHOUT_TABSTOPS = 1434_u32 + ERROR_DESTROY_OBJECT_OF_OTHER_THREAD = 1435_u32 + ERROR_CHILD_WINDOW_MENU = 1436_u32 + ERROR_NO_SYSTEM_MENU = 1437_u32 + ERROR_INVALID_MSGBOX_STYLE = 1438_u32 + ERROR_INVALID_SPI_VALUE = 1439_u32 + ERROR_SCREEN_ALREADY_LOCKED = 1440_u32 + ERROR_HWNDS_HAVE_DIFF_PARENT = 1441_u32 + ERROR_NOT_CHILD_WINDOW = 1442_u32 + ERROR_INVALID_GW_COMMAND = 1443_u32 + ERROR_INVALID_THREAD_ID = 1444_u32 + ERROR_NON_MDICHILD_WINDOW = 1445_u32 + ERROR_POPUP_ALREADY_ACTIVE = 1446_u32 + ERROR_NO_SCROLLBARS = 1447_u32 + ERROR_INVALID_SCROLLBAR_RANGE = 1448_u32 + ERROR_INVALID_SHOWWIN_COMMAND = 1449_u32 + ERROR_NO_SYSTEM_RESOURCES = 1450_u32 + ERROR_NONPAGED_SYSTEM_RESOURCES = 1451_u32 + ERROR_PAGED_SYSTEM_RESOURCES = 1452_u32 + ERROR_WORKING_SET_QUOTA = 1453_u32 + ERROR_PAGEFILE_QUOTA = 1454_u32 + ERROR_COMMITMENT_LIMIT = 1455_u32 + ERROR_MENU_ITEM_NOT_FOUND = 1456_u32 + ERROR_INVALID_KEYBOARD_HANDLE = 1457_u32 + ERROR_HOOK_TYPE_NOT_ALLOWED = 1458_u32 + ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION = 1459_u32 + ERROR_TIMEOUT = 1460_u32 + ERROR_INVALID_MONITOR_HANDLE = 1461_u32 + ERROR_INCORRECT_SIZE = 1462_u32 + ERROR_EVENTLOG_FILE_CORRUPT = 1500_u32 + ERROR_EVENTLOG_CANT_START = 1501_u32 + ERROR_LOG_FILE_FULL = 1502_u32 + ERROR_EVENTLOG_FILE_CHANGED = 1503_u32 + ERROR_INSTALL_SERVICE_FAILURE = 1601_u32 + ERROR_INSTALL_USEREXIT = 1602_u32 + ERROR_INSTALL_FAILURE = 1603_u32 + ERROR_INSTALL_SUSPEND = 1604_u32 + ERROR_UNKNOWN_PRODUCT = 1605_u32 + ERROR_UNKNOWN_FEATURE = 1606_u32 + ERROR_UNKNOWN_COMPONENT = 1607_u32 + ERROR_UNKNOWN_PROPERTY = 1608_u32 + ERROR_INVALID_HANDLE_STATE = 1609_u32 + ERROR_BAD_CONFIGURATION = 1610_u32 + ERROR_INDEX_ABSENT = 1611_u32 + ERROR_INSTALL_SOURCE_ABSENT = 1612_u32 + ERROR_INSTALL_PACKAGE_VERSION = 1613_u32 + ERROR_PRODUCT_UNINSTALLED = 1614_u32 + ERROR_BAD_QUERY_SYNTAX = 1615_u32 + ERROR_INVALID_FIELD = 1616_u32 + ERROR_DEVICE_REMOVED = 1617_u32 + ERROR_INSTALL_ALREADY_RUNNING = 1618_u32 + ERROR_INSTALL_PACKAGE_OPEN_FAILED = 1619_u32 + ERROR_INSTALL_PACKAGE_INVALID = 1620_u32 + ERROR_INSTALL_UI_FAILURE = 1621_u32 + ERROR_INSTALL_LOG_FAILURE = 1622_u32 + ERROR_INSTALL_LANGUAGE_UNSUPPORTED = 1623_u32 + ERROR_INSTALL_TRANSFORM_FAILURE = 1624_u32 + ERROR_INSTALL_PACKAGE_REJECTED = 1625_u32 + ERROR_FUNCTION_NOT_CALLED = 1626_u32 + ERROR_FUNCTION_FAILED = 1627_u32 + ERROR_INVALID_TABLE = 1628_u32 + ERROR_DATATYPE_MISMATCH = 1629_u32 + ERROR_UNSUPPORTED_TYPE = 1630_u32 + ERROR_CREATE_FAILED = 1631_u32 + ERROR_INSTALL_TEMP_UNWRITABLE = 1632_u32 + ERROR_INSTALL_PLATFORM_UNSUPPORTED = 1633_u32 + ERROR_INSTALL_NOTUSED = 1634_u32 + ERROR_PATCH_PACKAGE_OPEN_FAILED = 1635_u32 + ERROR_PATCH_PACKAGE_INVALID = 1636_u32 + ERROR_PATCH_PACKAGE_UNSUPPORTED = 1637_u32 + ERROR_PRODUCT_VERSION = 1638_u32 + ERROR_INVALID_COMMAND_LINE = 1639_u32 + ERROR_INSTALL_REMOTE_DISALLOWED = 1640_u32 + ERROR_SUCCESS_REBOOT_INITIATED = 1641_u32 + ERROR_PATCH_TARGET_NOT_FOUND = 1642_u32 + ERROR_PATCH_PACKAGE_REJECTED = 1643_u32 + ERROR_INSTALL_TRANSFORM_REJECTED = 1644_u32 + ERROR_INSTALL_REMOTE_PROHIBITED = 1645_u32 + RPC_S_INVALID_STRING_BINDING = 1700_u32 + RPC_S_WRONG_KIND_OF_BINDING = 1701_u32 + RPC_S_INVALID_BINDING = 1702_u32 + RPC_S_PROTSEQ_NOT_SUPPORTED = 1703_u32 + RPC_S_INVALID_RPC_PROTSEQ = 1704_u32 + RPC_S_INVALID_STRING_UUID = 1705_u32 + RPC_S_INVALID_ENDPOINT_FORMAT = 1706_u32 + RPC_S_INVALID_NET_ADDR = 1707_u32 + RPC_S_NO_ENDPOINT_FOUND = 1708_u32 + RPC_S_INVALID_TIMEOUT = 1709_u32 + RPC_S_OBJECT_NOT_FOUND = 1710_u32 + RPC_S_ALREADY_REGISTERED = 1711_u32 + RPC_S_TYPE_ALREADY_REGISTERED = 1712_u32 + RPC_S_ALREADY_LISTENING = 1713_u32 + RPC_S_NO_PROTSEQS_REGISTERED = 1714_u32 + RPC_S_NOT_LISTENING = 1715_u32 + RPC_S_UNKNOWN_MGR_TYPE = 1716_u32 + RPC_S_UNKNOWN_IF = 1717_u32 + RPC_S_NO_BINDINGS = 1718_u32 + RPC_S_NO_PROTSEQS = 1719_u32 + RPC_S_CANT_CREATE_ENDPOINT = 1720_u32 + RPC_S_OUT_OF_RESOURCES = 1721_u32 + RPC_S_SERVER_UNAVAILABLE = 1722_u32 + RPC_S_SERVER_TOO_BUSY = 1723_u32 + RPC_S_INVALID_NETWORK_OPTIONS = 1724_u32 + RPC_S_NO_CALL_ACTIVE = 1725_u32 + RPC_S_CALL_FAILED = 1726_u32 + RPC_S_CALL_FAILED_DNE = 1727_u32 + RPC_S_PROTOCOL_ERROR = 1728_u32 + RPC_S_UNSUPPORTED_TRANS_SYN = 1730_u32 + RPC_S_UNSUPPORTED_TYPE = 1732_u32 + RPC_S_INVALID_TAG = 1733_u32 + RPC_S_INVALID_BOUND = 1734_u32 + RPC_S_NO_ENTRY_NAME = 1735_u32 + RPC_S_INVALID_NAME_SYNTAX = 1736_u32 + RPC_S_UNSUPPORTED_NAME_SYNTAX = 1737_u32 + RPC_S_UUID_NO_ADDRESS = 1739_u32 + RPC_S_DUPLICATE_ENDPOINT = 1740_u32 + RPC_S_UNKNOWN_AUTHN_TYPE = 1741_u32 + RPC_S_MAX_CALLS_TOO_SMALL = 1742_u32 + RPC_S_STRING_TOO_LONG = 1743_u32 + RPC_S_PROTSEQ_NOT_FOUND = 1744_u32 + RPC_S_PROCNUM_OUT_OF_RANGE = 1745_u32 + RPC_S_BINDING_HAS_NO_AUTH = 1746_u32 + RPC_S_UNKNOWN_AUTHN_SERVICE = 1747_u32 + RPC_S_UNKNOWN_AUTHN_LEVEL = 1748_u32 + RPC_S_INVALID_AUTH_IDENTITY = 1749_u32 + RPC_S_UNKNOWN_AUTHZ_SERVICE = 1750_u32 + EPT_S_INVALID_ENTRY = 1751_u32 + EPT_S_CANT_PERFORM_OP = 1752_u32 + EPT_S_NOT_REGISTERED = 1753_u32 + RPC_S_NOTHING_TO_EXPORT = 1754_u32 + RPC_S_INCOMPLETE_NAME = 1755_u32 + RPC_S_INVALID_VERS_OPTION = 1756_u32 + RPC_S_NO_MORE_MEMBERS = 1757_u32 + RPC_S_NOT_ALL_OBJS_UNEXPORTED = 1758_u32 + RPC_S_INTERFACE_NOT_FOUND = 1759_u32 + RPC_S_ENTRY_ALREADY_EXISTS = 1760_u32 + RPC_S_ENTRY_NOT_FOUND = 1761_u32 + RPC_S_NAME_SERVICE_UNAVAILABLE = 1762_u32 + RPC_S_INVALID_NAF_ID = 1763_u32 + RPC_S_CANNOT_SUPPORT = 1764_u32 + RPC_S_NO_CONTEXT_AVAILABLE = 1765_u32 + RPC_S_INTERNAL_ERROR = 1766_u32 + RPC_S_ZERO_DIVIDE = 1767_u32 + RPC_S_ADDRESS_ERROR = 1768_u32 + RPC_S_FP_DIV_ZERO = 1769_u32 + RPC_S_FP_UNDERFLOW = 1770_u32 + RPC_S_FP_OVERFLOW = 1771_u32 + RPC_X_NO_MORE_ENTRIES = 1772_u32 + RPC_X_SS_CHAR_TRANS_OPEN_FAIL = 1773_u32 + RPC_X_SS_CHAR_TRANS_SHORT_FILE = 1774_u32 + RPC_X_SS_IN_NULL_CONTEXT = 1775_u32 + RPC_X_SS_CONTEXT_DAMAGED = 1777_u32 + RPC_X_SS_HANDLES_MISMATCH = 1778_u32 + RPC_X_SS_CANNOT_GET_CALL_HANDLE = 1779_u32 + RPC_X_NULL_REF_POINTER = 1780_u32 + RPC_X_ENUM_VALUE_OUT_OF_RANGE = 1781_u32 + RPC_X_BYTE_COUNT_TOO_SMALL = 1782_u32 + RPC_X_BAD_STUB_DATA = 1783_u32 + ERROR_INVALID_USER_BUFFER = 1784_u32 + ERROR_UNRECOGNIZED_MEDIA = 1785_u32 + ERROR_NO_TRUST_LSA_SECRET = 1786_u32 + ERROR_NO_TRUST_SAM_ACCOUNT = 1787_u32 + ERROR_TRUSTED_DOMAIN_FAILURE = 1788_u32 + ERROR_TRUSTED_RELATIONSHIP_FAILURE = 1789_u32 + ERROR_TRUST_FAILURE = 1790_u32 + RPC_S_CALL_IN_PROGRESS = 1791_u32 + ERROR_NETLOGON_NOT_STARTED = 1792_u32 + ERROR_ACCOUNT_EXPIRED = 1793_u32 + ERROR_REDIRECTOR_HAS_OPEN_HANDLES = 1794_u32 + ERROR_PRINTER_DRIVER_ALREADY_INSTALLED = 1795_u32 + ERROR_UNKNOWN_PORT = 1796_u32 + ERROR_UNKNOWN_PRINTER_DRIVER = 1797_u32 + ERROR_UNKNOWN_PRINTPROCESSOR = 1798_u32 + ERROR_INVALID_SEPARATOR_FILE = 1799_u32 + ERROR_INVALID_PRIORITY = 1800_u32 + ERROR_INVALID_PRINTER_NAME = 1801_u32 + ERROR_PRINTER_ALREADY_EXISTS = 1802_u32 + ERROR_INVALID_PRINTER_COMMAND = 1803_u32 + ERROR_INVALID_DATATYPE = 1804_u32 + ERROR_INVALID_ENVIRONMENT = 1805_u32 + RPC_S_NO_MORE_BINDINGS = 1806_u32 + ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 1807_u32 + ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT = 1808_u32 + ERROR_NOLOGON_SERVER_TRUST_ACCOUNT = 1809_u32 + ERROR_DOMAIN_TRUST_INCONSISTENT = 1810_u32 + ERROR_SERVER_HAS_OPEN_HANDLES = 1811_u32 + ERROR_RESOURCE_DATA_NOT_FOUND = 1812_u32 + ERROR_RESOURCE_TYPE_NOT_FOUND = 1813_u32 + ERROR_RESOURCE_NAME_NOT_FOUND = 1814_u32 + ERROR_RESOURCE_LANG_NOT_FOUND = 1815_u32 + ERROR_NOT_ENOUGH_QUOTA = 1816_u32 + RPC_S_NO_INTERFACES = 1817_u32 + RPC_S_CALL_CANCELLED = 1818_u32 + RPC_S_BINDING_INCOMPLETE = 1819_u32 + RPC_S_COMM_FAILURE = 1820_u32 + RPC_S_UNSUPPORTED_AUTHN_LEVEL = 1821_u32 + RPC_S_NO_PRINC_NAME = 1822_u32 + RPC_S_NOT_RPC_ERROR = 1823_u32 + RPC_S_UUID_LOCAL_ONLY = 1824_u32 + RPC_S_SEC_PKG_ERROR = 1825_u32 + RPC_S_NOT_CANCELLED = 1826_u32 + RPC_X_INVALID_ES_ACTION = 1827_u32 + RPC_X_WRONG_ES_VERSION = 1828_u32 + RPC_X_WRONG_STUB_VERSION = 1829_u32 + RPC_X_INVALID_PIPE_OBJECT = 1830_u32 + RPC_X_WRONG_PIPE_ORDER = 1831_u32 + RPC_X_WRONG_PIPE_VERSION = 1832_u32 + RPC_S_GROUP_MEMBER_NOT_FOUND = 1898_u32 + EPT_S_CANT_CREATE = 1899_u32 + RPC_S_INVALID_OBJECT = 1900_u32 + ERROR_INVALID_TIME = 1901_u32 + ERROR_INVALID_FORM_NAME = 1902_u32 + ERROR_INVALID_FORM_SIZE = 1903_u32 + ERROR_ALREADY_WAITING = 1904_u32 + ERROR_PRINTER_DELETED = 1905_u32 + ERROR_INVALID_PRINTER_STATE = 1906_u32 + ERROR_PASSWORD_MUST_CHANGE = 1907_u32 + ERROR_DOMAIN_CONTROLLER_NOT_FOUND = 1908_u32 + ERROR_ACCOUNT_LOCKED_OUT = 1909_u32 + OR_INVALID_OXID = 1910_u32 + OR_INVALID_OID = 1911_u32 + OR_INVALID_SET = 1912_u32 + RPC_S_SEND_INCOMPLETE = 1913_u32 + RPC_S_INVALID_ASYNC_HANDLE = 1914_u32 + RPC_S_INVALID_ASYNC_CALL = 1915_u32 + RPC_X_PIPE_CLOSED = 1916_u32 + RPC_X_PIPE_DISCIPLINE_ERROR = 1917_u32 + RPC_X_PIPE_EMPTY = 1918_u32 + ERROR_NO_SITENAME = 1919_u32 + ERROR_CANT_ACCESS_FILE = 1920_u32 + ERROR_CANT_RESOLVE_FILENAME = 1921_u32 + RPC_S_ENTRY_TYPE_MISMATCH = 1922_u32 + RPC_S_NOT_ALL_OBJS_EXPORTED = 1923_u32 + RPC_S_INTERFACE_NOT_EXPORTED = 1924_u32 + RPC_S_PROFILE_NOT_ADDED = 1925_u32 + RPC_S_PRF_ELT_NOT_ADDED = 1926_u32 + RPC_S_PRF_ELT_NOT_REMOVED = 1927_u32 + RPC_S_GRP_ELT_NOT_ADDED = 1928_u32 + RPC_S_GRP_ELT_NOT_REMOVED = 1929_u32 + ERROR_KM_DRIVER_BLOCKED = 1930_u32 + ERROR_CONTEXT_EXPIRED = 1931_u32 + ERROR_PER_USER_TRUST_QUOTA_EXCEEDED = 1932_u32 + ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED = 1933_u32 + ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED = 1934_u32 + ERROR_AUTHENTICATION_FIREWALL_FAILED = 1935_u32 + ERROR_REMOTE_PRINT_CONNECTIONS_BLOCKED = 1936_u32 + ERROR_INVALID_PIXEL_FORMAT = 2000_u32 + ERROR_BAD_DRIVER = 2001_u32 + ERROR_INVALID_WINDOW_STYLE = 2002_u32 + ERROR_METAFILE_NOT_SUPPORTED = 2003_u32 + ERROR_TRANSFORM_NOT_SUPPORTED = 2004_u32 + ERROR_CLIPPING_NOT_SUPPORTED = 2005_u32 + ERROR_INVALID_CMM = 2010_u32 + ERROR_INVALID_PROFILE = 2011_u32 + ERROR_TAG_NOT_FOUND = 2012_u32 + ERROR_TAG_NOT_PRESENT = 2013_u32 + ERROR_DUPLICATE_TAG = 2014_u32 + ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE = 2015_u32 + ERROR_PROFILE_NOT_FOUND = 2016_u32 + ERROR_INVALID_COLORSPACE = 2017_u32 + ERROR_ICM_NOT_ENABLED = 2018_u32 + ERROR_DELETING_ICM_XFORM = 2019_u32 + ERROR_INVALID_TRANSFORM = 2020_u32 + ERROR_COLORSPACE_MISMATCH = 2021_u32 + ERROR_INVALID_COLORINDEX = 2022_u32 + ERROR_CONNECTED_OTHER_PASSWORD = 2108_u32 + ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT = 2109_u32 + ERROR_BAD_USERNAME = 2202_u32 + ERROR_NOT_CONNECTED = 2250_u32 + ERROR_OPEN_FILES = 2401_u32 + ERROR_ACTIVE_CONNECTIONS = 2402_u32 + ERROR_DEVICE_IN_USE = 2404_u32 + ERROR_UNKNOWN_PRINT_MONITOR = 3000_u32 + ERROR_PRINTER_DRIVER_IN_USE = 3001_u32 + ERROR_SPOOL_FILE_NOT_FOUND = 3002_u32 + ERROR_SPL_NO_STARTDOC = 3003_u32 + ERROR_SPL_NO_ADDJOB = 3004_u32 + ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED = 3005_u32 + ERROR_PRINT_MONITOR_ALREADY_INSTALLED = 3006_u32 + ERROR_INVALID_PRINT_MONITOR = 3007_u32 + ERROR_PRINT_MONITOR_IN_USE = 3008_u32 + ERROR_PRINTER_HAS_JOBS_QUEUED = 3009_u32 + ERROR_SUCCESS_REBOOT_REQUIRED = 3010_u32 + ERROR_SUCCESS_RESTART_REQUIRED = 3011_u32 + ERROR_PRINTER_NOT_FOUND = 3012_u32 + ERROR_PRINTER_DRIVER_WARNED = 3013_u32 + ERROR_PRINTER_DRIVER_BLOCKED = 3014_u32 + ERROR_WINS_INTERNAL = 4000_u32 + ERROR_CAN_NOT_DEL_LOCAL_WINS = 4001_u32 + ERROR_STATIC_INIT = 4002_u32 + ERROR_INC_BACKUP = 4003_u32 + ERROR_FULL_BACKUP = 4004_u32 + ERROR_REC_NON_EXISTENT = 4005_u32 + ERROR_RPL_NOT_ALLOWED = 4006_u32 + ERROR_DHCP_ADDRESS_CONFLICT = 4100_u32 + ERROR_WMI_GUID_NOT_FOUND = 4200_u32 + ERROR_WMI_INSTANCE_NOT_FOUND = 4201_u32 + ERROR_WMI_ITEMID_NOT_FOUND = 4202_u32 + ERROR_WMI_TRY_AGAIN = 4203_u32 + ERROR_WMI_DP_NOT_FOUND = 4204_u32 + ERROR_WMI_UNRESOLVED_INSTANCE_REF = 4205_u32 + ERROR_WMI_ALREADY_ENABLED = 4206_u32 + ERROR_WMI_GUID_DISCONNECTED = 4207_u32 + ERROR_WMI_SERVER_UNAVAILABLE = 4208_u32 + ERROR_WMI_DP_FAILED = 4209_u32 + ERROR_WMI_INVALID_MOF = 4210_u32 + ERROR_WMI_INVALID_REGINFO = 4211_u32 + ERROR_WMI_ALREADY_DISABLED = 4212_u32 + ERROR_WMI_READ_ONLY = 4213_u32 + ERROR_WMI_SET_FAILURE = 4214_u32 + ERROR_INVALID_MEDIA = 4300_u32 + ERROR_INVALID_LIBRARY = 4301_u32 + ERROR_INVALID_MEDIA_POOL = 4302_u32 + ERROR_DRIVE_MEDIA_MISMATCH = 4303_u32 + ERROR_MEDIA_OFFLINE = 4304_u32 + ERROR_LIBRARY_OFFLINE = 4305_u32 + ERROR_EMPTY = 4306_u32 + ERROR_NOT_EMPTY = 4307_u32 + ERROR_MEDIA_UNAVAILABLE = 4308_u32 + ERROR_RESOURCE_DISABLED = 4309_u32 + ERROR_INVALID_CLEANER = 4310_u32 + ERROR_UNABLE_TO_CLEAN = 4311_u32 + ERROR_OBJECT_NOT_FOUND = 4312_u32 + ERROR_DATABASE_FAILURE = 4313_u32 + ERROR_DATABASE_FULL = 4314_u32 + ERROR_MEDIA_INCOMPATIBLE = 4315_u32 + ERROR_RESOURCE_NOT_PRESENT = 4316_u32 + ERROR_INVALID_OPERATION = 4317_u32 + ERROR_MEDIA_NOT_AVAILABLE = 4318_u32 + ERROR_DEVICE_NOT_AVAILABLE = 4319_u32 + ERROR_REQUEST_REFUSED = 4320_u32 + ERROR_INVALID_DRIVE_OBJECT = 4321_u32 + ERROR_LIBRARY_FULL = 4322_u32 + ERROR_MEDIUM_NOT_ACCESSIBLE = 4323_u32 + ERROR_UNABLE_TO_LOAD_MEDIUM = 4324_u32 + ERROR_UNABLE_TO_INVENTORY_DRIVE = 4325_u32 + ERROR_UNABLE_TO_INVENTORY_SLOT = 4326_u32 + ERROR_UNABLE_TO_INVENTORY_TRANSPORT = 4327_u32 + ERROR_TRANSPORT_FULL = 4328_u32 + ERROR_CONTROLLING_IEPORT = 4329_u32 + ERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA = 4330_u32 + ERROR_CLEANER_SLOT_SET = 4331_u32 + ERROR_CLEANER_SLOT_NOT_SET = 4332_u32 + ERROR_CLEANER_CARTRIDGE_SPENT = 4333_u32 + ERROR_UNEXPECTED_OMID = 4334_u32 + ERROR_CANT_DELETE_LAST_ITEM = 4335_u32 + ERROR_MESSAGE_EXCEEDS_MAX_SIZE = 4336_u32 + ERROR_VOLUME_CONTAINS_SYS_FILES = 4337_u32 + ERROR_INDIGENOUS_TYPE = 4338_u32 + ERROR_NO_SUPPORTING_DRIVES = 4339_u32 + ERROR_CLEANER_CARTRIDGE_INSTALLED = 4340_u32 + ERROR_IEPORT_FULL = 4341_u32 + ERROR_FILE_OFFLINE = 4350_u32 + ERROR_REMOTE_STORAGE_NOT_ACTIVE = 4351_u32 + ERROR_REMOTE_STORAGE_MEDIA_ERROR = 4352_u32 + ERROR_NOT_A_REPARSE_POINT = 4390_u32 + ERROR_REPARSE_ATTRIBUTE_CONFLICT = 4391_u32 + ERROR_INVALID_REPARSE_DATA = 4392_u32 + ERROR_REPARSE_TAG_INVALID = 4393_u32 + ERROR_REPARSE_TAG_MISMATCH = 4394_u32 + ERROR_VOLUME_NOT_SIS_ENABLED = 4500_u32 + ERROR_DEPENDENT_RESOURCE_EXISTS = 5001_u32 + ERROR_DEPENDENCY_NOT_FOUND = 5002_u32 + ERROR_DEPENDENCY_ALREADY_EXISTS = 5003_u32 + ERROR_RESOURCE_NOT_ONLINE = 5004_u32 + ERROR_HOST_NODE_NOT_AVAILABLE = 5005_u32 + ERROR_RESOURCE_NOT_AVAILABLE = 5006_u32 + ERROR_RESOURCE_NOT_FOUND = 5007_u32 + ERROR_SHUTDOWN_CLUSTER = 5008_u32 + ERROR_CANT_EVICT_ACTIVE_NODE = 5009_u32 + ERROR_OBJECT_ALREADY_EXISTS = 5010_u32 + ERROR_OBJECT_IN_LIST = 5011_u32 + ERROR_GROUP_NOT_AVAILABLE = 5012_u32 + ERROR_GROUP_NOT_FOUND = 5013_u32 + ERROR_GROUP_NOT_ONLINE = 5014_u32 + ERROR_HOST_NODE_NOT_RESOURCE_OWNER = 5015_u32 + ERROR_HOST_NODE_NOT_GROUP_OWNER = 5016_u32 + ERROR_RESMON_CREATE_FAILED = 5017_u32 + ERROR_RESMON_ONLINE_FAILED = 5018_u32 + ERROR_RESOURCE_ONLINE = 5019_u32 + ERROR_QUORUM_RESOURCE = 5020_u32 + ERROR_NOT_QUORUM_CAPABLE = 5021_u32 + ERROR_CLUSTER_SHUTTING_DOWN = 5022_u32 + ERROR_INVALID_STATE = 5023_u32 + ERROR_RESOURCE_PROPERTIES_STORED = 5024_u32 + ERROR_NOT_QUORUM_CLASS = 5025_u32 + ERROR_CORE_RESOURCE = 5026_u32 + ERROR_QUORUM_RESOURCE_ONLINE_FAILED = 5027_u32 + ERROR_QUORUMLOG_OPEN_FAILED = 5028_u32 + ERROR_CLUSTERLOG_CORRUPT = 5029_u32 + ERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE = 5030_u32 + ERROR_CLUSTERLOG_EXCEEDS_MAXSIZE = 5031_u32 + ERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND = 5032_u32 + ERROR_CLUSTERLOG_NOT_ENOUGH_SPACE = 5033_u32 + ERROR_QUORUM_OWNER_ALIVE = 5034_u32 + ERROR_NETWORK_NOT_AVAILABLE = 5035_u32 + ERROR_NODE_NOT_AVAILABLE = 5036_u32 + ERROR_ALL_NODES_NOT_AVAILABLE = 5037_u32 + ERROR_RESOURCE_FAILED = 5038_u32 + ERROR_CLUSTER_INVALID_NODE = 5039_u32 + ERROR_CLUSTER_NODE_EXISTS = 5040_u32 + ERROR_CLUSTER_JOIN_IN_PROGRESS = 5041_u32 + ERROR_CLUSTER_NODE_NOT_FOUND = 5042_u32 + ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND = 5043_u32 + ERROR_CLUSTER_NETWORK_EXISTS = 5044_u32 + ERROR_CLUSTER_NETWORK_NOT_FOUND = 5045_u32 + ERROR_CLUSTER_NETINTERFACE_EXISTS = 5046_u32 + ERROR_CLUSTER_NETINTERFACE_NOT_FOUND = 5047_u32 + ERROR_CLUSTER_INVALID_REQUEST = 5048_u32 + ERROR_CLUSTER_INVALID_NETWORK_PROVIDER = 5049_u32 + ERROR_CLUSTER_NODE_DOWN = 5050_u32 + ERROR_CLUSTER_NODE_UNREACHABLE = 5051_u32 + ERROR_CLUSTER_NODE_NOT_MEMBER = 5052_u32 + ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS = 5053_u32 + ERROR_CLUSTER_INVALID_NETWORK = 5054_u32 + ERROR_CLUSTER_NODE_UP = 5056_u32 + ERROR_CLUSTER_IPADDR_IN_USE = 5057_u32 + ERROR_CLUSTER_NODE_NOT_PAUSED = 5058_u32 + ERROR_CLUSTER_NO_SECURITY_CONTEXT = 5059_u32 + ERROR_CLUSTER_NETWORK_NOT_INTERNAL = 5060_u32 + ERROR_CLUSTER_NODE_ALREADY_UP = 5061_u32 + ERROR_CLUSTER_NODE_ALREADY_DOWN = 5062_u32 + ERROR_CLUSTER_NETWORK_ALREADY_ONLINE = 5063_u32 + ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE = 5064_u32 + ERROR_CLUSTER_NODE_ALREADY_MEMBER = 5065_u32 + ERROR_CLUSTER_LAST_INTERNAL_NETWORK = 5066_u32 + ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS = 5067_u32 + ERROR_INVALID_OPERATION_ON_QUORUM = 5068_u32 + ERROR_DEPENDENCY_NOT_ALLOWED = 5069_u32 + ERROR_CLUSTER_NODE_PAUSED = 5070_u32 + ERROR_NODE_CANT_HOST_RESOURCE = 5071_u32 + ERROR_CLUSTER_NODE_NOT_READY = 5072_u32 + ERROR_CLUSTER_NODE_SHUTTING_DOWN = 5073_u32 + ERROR_CLUSTER_JOIN_ABORTED = 5074_u32 + ERROR_CLUSTER_INCOMPATIBLE_VERSIONS = 5075_u32 + ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED = 5076_u32 + ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED = 5077_u32 + ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND = 5078_u32 + ERROR_CLUSTER_RESTYPE_NOT_SUPPORTED = 5079_u32 + ERROR_CLUSTER_RESNAME_NOT_FOUND = 5080_u32 + ERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED = 5081_u32 + ERROR_CLUSTER_OWNER_NOT_IN_PREFLIST = 5082_u32 + ERROR_CLUSTER_DATABASE_SEQMISMATCH = 5083_u32 + ERROR_RESMON_INVALID_STATE = 5084_u32 + ERROR_CLUSTER_GUM_NOT_LOCKER = 5085_u32 + ERROR_QUORUM_DISK_NOT_FOUND = 5086_u32 + ERROR_DATABASE_BACKUP_CORRUPT = 5087_u32 + ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT = 5088_u32 + ERROR_RESOURCE_PROPERTY_UNCHANGEABLE = 5089_u32 + ERROR_CLUSTER_MEMBERSHIP_INVALID_STATE = 5890_u32 + ERROR_CLUSTER_QUORUMLOG_NOT_FOUND = 5891_u32 + ERROR_CLUSTER_MEMBERSHIP_HALT = 5892_u32 + ERROR_CLUSTER_INSTANCE_ID_MISMATCH = 5893_u32 + ERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP = 5894_u32 + ERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH = 5895_u32 + ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP = 5896_u32 + ERROR_CLUSTER_PARAMETER_MISMATCH = 5897_u32 + ERROR_NODE_CANNOT_BE_CLUSTERED = 5898_u32 + ERROR_CLUSTER_WRONG_OS_VERSION = 5899_u32 + ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME = 5900_u32 + ERROR_CLUSCFG_ALREADY_COMMITTED = 5901_u32 + ERROR_CLUSCFG_ROLLBACK_FAILED = 5902_u32 + ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT = 5903_u32 + ERROR_CLUSTER_OLD_VERSION = 5904_u32 + ERROR_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME = 5905_u32 + ERROR_ENCRYPTION_FAILED = 6000_u32 + ERROR_DECRYPTION_FAILED = 6001_u32 + ERROR_FILE_ENCRYPTED = 6002_u32 + ERROR_NO_RECOVERY_POLICY = 6003_u32 + ERROR_NO_EFS = 6004_u32 + ERROR_WRONG_EFS = 6005_u32 + ERROR_NO_USER_KEYS = 6006_u32 + ERROR_FILE_NOT_ENCRYPTED = 6007_u32 + ERROR_NOT_EXPORT_FORMAT = 6008_u32 + ERROR_FILE_READ_ONLY = 6009_u32 + ERROR_DIR_EFS_DISALLOWED = 6010_u32 + ERROR_EFS_SERVER_NOT_TRUSTED = 6011_u32 + ERROR_BAD_RECOVERY_POLICY = 6012_u32 + ERROR_EFS_ALG_BLOB_TOO_BIG = 6013_u32 + ERROR_VOLUME_NOT_SUPPORT_EFS = 6014_u32 + ERROR_EFS_DISABLED = 6015_u32 + ERROR_EFS_VERSION_NOT_SUPPORT = 6016_u32 + ERROR_NO_BROWSER_SERVERS_FOUND = 6118_u32 + SCHED_E_SERVICE_NOT_LOCALSYSTEM = 6200_u32 + ERROR_CTX_WINSTATION_NAME_INVALID = 7001_u32 + ERROR_CTX_INVALID_PD = 7002_u32 + ERROR_CTX_PD_NOT_FOUND = 7003_u32 + ERROR_CTX_WD_NOT_FOUND = 7004_u32 + ERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY = 7005_u32 + ERROR_CTX_SERVICE_NAME_COLLISION = 7006_u32 + ERROR_CTX_CLOSE_PENDING = 7007_u32 + ERROR_CTX_NO_OUTBUF = 7008_u32 + ERROR_CTX_MODEM_INF_NOT_FOUND = 7009_u32 + ERROR_CTX_INVALID_MODEMNAME = 7010_u32 + ERROR_CTX_MODEM_RESPONSE_ERROR = 7011_u32 + ERROR_CTX_MODEM_RESPONSE_TIMEOUT = 7012_u32 + ERROR_CTX_MODEM_RESPONSE_NO_CARRIER = 7013_u32 + ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE = 7014_u32 + ERROR_CTX_MODEM_RESPONSE_BUSY = 7015_u32 + ERROR_CTX_MODEM_RESPONSE_VOICE = 7016_u32 + ERROR_CTX_TD_ERROR = 7017_u32 + ERROR_CTX_WINSTATION_NOT_FOUND = 7022_u32 + ERROR_CTX_WINSTATION_ALREADY_EXISTS = 7023_u32 + ERROR_CTX_WINSTATION_BUSY = 7024_u32 + ERROR_CTX_BAD_VIDEO_MODE = 7025_u32 + ERROR_CTX_GRAPHICS_INVALID = 7035_u32 + ERROR_CTX_LOGON_DISABLED = 7037_u32 + ERROR_CTX_NOT_CONSOLE = 7038_u32 + ERROR_CTX_CLIENT_QUERY_TIMEOUT = 7040_u32 + ERROR_CTX_CONSOLE_DISCONNECT = 7041_u32 + ERROR_CTX_CONSOLE_CONNECT = 7042_u32 + ERROR_CTX_SHADOW_DENIED = 7044_u32 + ERROR_CTX_WINSTATION_ACCESS_DENIED = 7045_u32 + ERROR_CTX_INVALID_WD = 7049_u32 + ERROR_CTX_SHADOW_INVALID = 7050_u32 + ERROR_CTX_SHADOW_DISABLED = 7051_u32 + ERROR_CTX_CLIENT_LICENSE_IN_USE = 7052_u32 + ERROR_CTX_CLIENT_LICENSE_NOT_SET = 7053_u32 + ERROR_CTX_LICENSE_NOT_AVAILABLE = 7054_u32 + ERROR_CTX_LICENSE_CLIENT_INVALID = 7055_u32 + ERROR_CTX_LICENSE_EXPIRED = 7056_u32 + ERROR_CTX_SHADOW_NOT_RUNNING = 7057_u32 + ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE = 7058_u32 + ERROR_ACTIVATION_COUNT_EXCEEDED = 7059_u32 + FRS_ERR_INVALID_API_SEQUENCE = 8001_u32 + FRS_ERR_STARTING_SERVICE = 8002_u32 + FRS_ERR_STOPPING_SERVICE = 8003_u32 + FRS_ERR_INTERNAL_API = 8004_u32 + FRS_ERR_INTERNAL = 8005_u32 + FRS_ERR_SERVICE_COMM = 8006_u32 + FRS_ERR_INSUFFICIENT_PRIV = 8007_u32 + FRS_ERR_AUTHENTICATION = 8008_u32 + FRS_ERR_PARENT_INSUFFICIENT_PRIV = 8009_u32 + FRS_ERR_PARENT_AUTHENTICATION = 8010_u32 + FRS_ERR_CHILD_TO_PARENT_COMM = 8011_u32 + FRS_ERR_PARENT_TO_CHILD_COMM = 8012_u32 + FRS_ERR_SYSVOL_POPULATE = 8013_u32 + FRS_ERR_SYSVOL_POPULATE_TIMEOUT = 8014_u32 + FRS_ERR_SYSVOL_IS_BUSY = 8015_u32 + FRS_ERR_SYSVOL_DEMOTE = 8016_u32 + FRS_ERR_INVALID_SERVICE_PARAMETER = 8017_u32 + ERROR_DS_NOT_INSTALLED = 8200_u32 + ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY = 8201_u32 + ERROR_DS_NO_ATTRIBUTE_OR_VALUE = 8202_u32 + ERROR_DS_INVALID_ATTRIBUTE_SYNTAX = 8203_u32 + ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED = 8204_u32 + ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS = 8205_u32 + ERROR_DS_BUSY = 8206_u32 + ERROR_DS_UNAVAILABLE = 8207_u32 + ERROR_DS_NO_RIDS_ALLOCATED = 8208_u32 + ERROR_DS_NO_MORE_RIDS = 8209_u32 + ERROR_DS_INCORRECT_ROLE_OWNER = 8210_u32 + ERROR_DS_RIDMGR_INIT_ERROR = 8211_u32 + ERROR_DS_OBJ_CLASS_VIOLATION = 8212_u32 + ERROR_DS_CANT_ON_NON_LEAF = 8213_u32 + ERROR_DS_CANT_ON_RDN = 8214_u32 + ERROR_DS_CANT_MOD_OBJ_CLASS = 8215_u32 + ERROR_DS_CROSS_DOM_MOVE_ERROR = 8216_u32 + ERROR_DS_GC_NOT_AVAILABLE = 8217_u32 + ERROR_SHARED_POLICY = 8218_u32 + ERROR_POLICY_OBJECT_NOT_FOUND = 8219_u32 + ERROR_POLICY_ONLY_IN_DS = 8220_u32 + ERROR_PROMOTION_ACTIVE = 8221_u32 + ERROR_NO_PROMOTION_ACTIVE = 8222_u32 + ERROR_DS_OPERATIONS_ERROR = 8224_u32 + ERROR_DS_PROTOCOL_ERROR = 8225_u32 + ERROR_DS_TIMELIMIT_EXCEEDED = 8226_u32 + ERROR_DS_SIZELIMIT_EXCEEDED = 8227_u32 + ERROR_DS_ADMIN_LIMIT_EXCEEDED = 8228_u32 + ERROR_DS_COMPARE_FALSE = 8229_u32 + ERROR_DS_COMPARE_TRUE = 8230_u32 + ERROR_DS_AUTH_METHOD_NOT_SUPPORTED = 8231_u32 + ERROR_DS_STRONG_AUTH_REQUIRED = 8232_u32 + ERROR_DS_INAPPROPRIATE_AUTH = 8233_u32 + ERROR_DS_AUTH_UNKNOWN = 8234_u32 + ERROR_DS_REFERRAL = 8235_u32 + ERROR_DS_UNAVAILABLE_CRIT_EXTENSION = 8236_u32 + ERROR_DS_CONFIDENTIALITY_REQUIRED = 8237_u32 + ERROR_DS_INAPPROPRIATE_MATCHING = 8238_u32 + ERROR_DS_CONSTRAINT_VIOLATION = 8239_u32 + ERROR_DS_NO_SUCH_OBJECT = 8240_u32 + ERROR_DS_ALIAS_PROBLEM = 8241_u32 + ERROR_DS_INVALID_DN_SYNTAX = 8242_u32 + ERROR_DS_IS_LEAF = 8243_u32 + ERROR_DS_ALIAS_DEREF_PROBLEM = 8244_u32 + ERROR_DS_UNWILLING_TO_PERFORM = 8245_u32 + ERROR_DS_LOOP_DETECT = 8246_u32 + ERROR_DS_NAMING_VIOLATION = 8247_u32 + ERROR_DS_OBJECT_RESULTS_TOO_LARGE = 8248_u32 + ERROR_DS_AFFECTS_MULTIPLE_DSAS = 8249_u32 + ERROR_DS_SERVER_DOWN = 8250_u32 + ERROR_DS_LOCAL_ERROR = 8251_u32 + ERROR_DS_ENCODING_ERROR = 8252_u32 + ERROR_DS_DECODING_ERROR = 8253_u32 + ERROR_DS_FILTER_UNKNOWN = 8254_u32 + ERROR_DS_PARAM_ERROR = 8255_u32 + ERROR_DS_NOT_SUPPORTED = 8256_u32 + ERROR_DS_NO_RESULTS_RETURNED = 8257_u32 + ERROR_DS_CONTROL_NOT_FOUND = 8258_u32 + ERROR_DS_CLIENT_LOOP = 8259_u32 + ERROR_DS_REFERRAL_LIMIT_EXCEEDED = 8260_u32 + ERROR_DS_SORT_CONTROL_MISSING = 8261_u32 + ERROR_DS_OFFSET_RANGE_ERROR = 8262_u32 + ERROR_DS_ROOT_MUST_BE_NC = 8301_u32 + ERROR_DS_ADD_REPLICA_INHIBITED = 8302_u32 + ERROR_DS_ATT_NOT_DEF_IN_SCHEMA = 8303_u32 + ERROR_DS_MAX_OBJ_SIZE_EXCEEDED = 8304_u32 + ERROR_DS_OBJ_STRING_NAME_EXISTS = 8305_u32 + ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA = 8306_u32 + ERROR_DS_RDN_DOESNT_MATCH_SCHEMA = 8307_u32 + ERROR_DS_NO_REQUESTED_ATTS_FOUND = 8308_u32 + ERROR_DS_USER_BUFFER_TO_SMALL = 8309_u32 + ERROR_DS_ATT_IS_NOT_ON_OBJ = 8310_u32 + ERROR_DS_ILLEGAL_MOD_OPERATION = 8311_u32 + ERROR_DS_OBJ_TOO_LARGE = 8312_u32 + ERROR_DS_BAD_INSTANCE_TYPE = 8313_u32 + ERROR_DS_MASTERDSA_REQUIRED = 8314_u32 + ERROR_DS_OBJECT_CLASS_REQUIRED = 8315_u32 + ERROR_DS_MISSING_REQUIRED_ATT = 8316_u32 + ERROR_DS_ATT_NOT_DEF_FOR_CLASS = 8317_u32 + ERROR_DS_ATT_ALREADY_EXISTS = 8318_u32 + ERROR_DS_CANT_ADD_ATT_VALUES = 8320_u32 + ERROR_DS_SINGLE_VALUE_CONSTRAINT = 8321_u32 + ERROR_DS_RANGE_CONSTRAINT = 8322_u32 + ERROR_DS_ATT_VAL_ALREADY_EXISTS = 8323_u32 + ERROR_DS_CANT_REM_MISSING_ATT = 8324_u32 + ERROR_DS_CANT_REM_MISSING_ATT_VAL = 8325_u32 + ERROR_DS_ROOT_CANT_BE_SUBREF = 8326_u32 + ERROR_DS_NO_CHAINING = 8327_u32 + ERROR_DS_NO_CHAINED_EVAL = 8328_u32 + ERROR_DS_NO_PARENT_OBJECT = 8329_u32 + ERROR_DS_PARENT_IS_AN_ALIAS = 8330_u32 + ERROR_DS_CANT_MIX_MASTER_AND_REPS = 8331_u32 + ERROR_DS_CHILDREN_EXIST = 8332_u32 + ERROR_DS_OBJ_NOT_FOUND = 8333_u32 + ERROR_DS_ALIASED_OBJ_MISSING = 8334_u32 + ERROR_DS_BAD_NAME_SYNTAX = 8335_u32 + ERROR_DS_ALIAS_POINTS_TO_ALIAS = 8336_u32 + ERROR_DS_CANT_DEREF_ALIAS = 8337_u32 + ERROR_DS_OUT_OF_SCOPE = 8338_u32 + ERROR_DS_OBJECT_BEING_REMOVED = 8339_u32 + ERROR_DS_CANT_DELETE_DSA_OBJ = 8340_u32 + ERROR_DS_GENERIC_ERROR = 8341_u32 + ERROR_DS_DSA_MUST_BE_INT_MASTER = 8342_u32 + ERROR_DS_CLASS_NOT_DSA = 8343_u32 + ERROR_DS_INSUFF_ACCESS_RIGHTS = 8344_u32 + ERROR_DS_ILLEGAL_SUPERIOR = 8345_u32 + ERROR_DS_ATTRIBUTE_OWNED_BY_SAM = 8346_u32 + ERROR_DS_NAME_TOO_MANY_PARTS = 8347_u32 + ERROR_DS_NAME_TOO_LONG = 8348_u32 + ERROR_DS_NAME_VALUE_TOO_LONG = 8349_u32 + ERROR_DS_NAME_UNPARSEABLE = 8350_u32 + ERROR_DS_NAME_TYPE_UNKNOWN = 8351_u32 + ERROR_DS_NOT_AN_OBJECT = 8352_u32 + ERROR_DS_SEC_DESC_TOO_SHORT = 8353_u32 + ERROR_DS_SEC_DESC_INVALID = 8354_u32 + ERROR_DS_NO_DELETED_NAME = 8355_u32 + ERROR_DS_SUBREF_MUST_HAVE_PARENT = 8356_u32 + ERROR_DS_NCNAME_MUST_BE_NC = 8357_u32 + ERROR_DS_CANT_ADD_SYSTEM_ONLY = 8358_u32 + ERROR_DS_CLASS_MUST_BE_CONCRETE = 8359_u32 + ERROR_DS_INVALID_DMD = 8360_u32 + ERROR_DS_OBJ_GUID_EXISTS = 8361_u32 + ERROR_DS_NOT_ON_BACKLINK = 8362_u32 + ERROR_DS_NO_CROSSREF_FOR_NC = 8363_u32 + ERROR_DS_SHUTTING_DOWN = 8364_u32 + ERROR_DS_UNKNOWN_OPERATION = 8365_u32 + ERROR_DS_INVALID_ROLE_OWNER = 8366_u32 + ERROR_DS_COULDNT_CONTACT_FSMO = 8367_u32 + ERROR_DS_CROSS_NC_DN_RENAME = 8368_u32 + ERROR_DS_CANT_MOD_SYSTEM_ONLY = 8369_u32 + ERROR_DS_REPLICATOR_ONLY = 8370_u32 + ERROR_DS_OBJ_CLASS_NOT_DEFINED = 8371_u32 + ERROR_DS_OBJ_CLASS_NOT_SUBCLASS = 8372_u32 + ERROR_DS_NAME_REFERENCE_INVALID = 8373_u32 + ERROR_DS_CROSS_REF_EXISTS = 8374_u32 + ERROR_DS_CANT_DEL_MASTER_CROSSREF = 8375_u32 + ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD = 8376_u32 + ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX = 8377_u32 + ERROR_DS_DUP_RDN = 8378_u32 + ERROR_DS_DUP_OID = 8379_u32 + ERROR_DS_DUP_MAPI_ID = 8380_u32 + ERROR_DS_DUP_SCHEMA_ID_GUID = 8381_u32 + ERROR_DS_DUP_LDAP_DISPLAY_NAME = 8382_u32 + ERROR_DS_SEMANTIC_ATT_TEST = 8383_u32 + ERROR_DS_SYNTAX_MISMATCH = 8384_u32 + ERROR_DS_EXISTS_IN_MUST_HAVE = 8385_u32 + ERROR_DS_EXISTS_IN_MAY_HAVE = 8386_u32 + ERROR_DS_NONEXISTENT_MAY_HAVE = 8387_u32 + ERROR_DS_NONEXISTENT_MUST_HAVE = 8388_u32 + ERROR_DS_AUX_CLS_TEST_FAIL = 8389_u32 + ERROR_DS_NONEXISTENT_POSS_SUP = 8390_u32 + ERROR_DS_SUB_CLS_TEST_FAIL = 8391_u32 + ERROR_DS_BAD_RDN_ATT_ID_SYNTAX = 8392_u32 + ERROR_DS_EXISTS_IN_AUX_CLS = 8393_u32 + ERROR_DS_EXISTS_IN_SUB_CLS = 8394_u32 + ERROR_DS_EXISTS_IN_POSS_SUP = 8395_u32 + ERROR_DS_RECALCSCHEMA_FAILED = 8396_u32 + ERROR_DS_TREE_DELETE_NOT_FINISHED = 8397_u32 + ERROR_DS_CANT_DELETE = 8398_u32 + ERROR_DS_ATT_SCHEMA_REQ_ID = 8399_u32 + ERROR_DS_BAD_ATT_SCHEMA_SYNTAX = 8400_u32 + ERROR_DS_CANT_CACHE_ATT = 8401_u32 + ERROR_DS_CANT_CACHE_CLASS = 8402_u32 + ERROR_DS_CANT_REMOVE_ATT_CACHE = 8403_u32 + ERROR_DS_CANT_REMOVE_CLASS_CACHE = 8404_u32 + ERROR_DS_CANT_RETRIEVE_DN = 8405_u32 + ERROR_DS_MISSING_SUPREF = 8406_u32 + ERROR_DS_CANT_RETRIEVE_INSTANCE = 8407_u32 + ERROR_DS_CODE_INCONSISTENCY = 8408_u32 + ERROR_DS_DATABASE_ERROR = 8409_u32 + ERROR_DS_GOVERNSID_MISSING = 8410_u32 + ERROR_DS_MISSING_EXPECTED_ATT = 8411_u32 + ERROR_DS_NCNAME_MISSING_CR_REF = 8412_u32 + ERROR_DS_SECURITY_CHECKING_ERROR = 8413_u32 + ERROR_DS_SCHEMA_NOT_LOADED = 8414_u32 + ERROR_DS_SCHEMA_ALLOC_FAILED = 8415_u32 + ERROR_DS_ATT_SCHEMA_REQ_SYNTAX = 8416_u32 + ERROR_DS_GCVERIFY_ERROR = 8417_u32 + ERROR_DS_DRA_SCHEMA_MISMATCH = 8418_u32 + ERROR_DS_CANT_FIND_DSA_OBJ = 8419_u32 + ERROR_DS_CANT_FIND_EXPECTED_NC = 8420_u32 + ERROR_DS_CANT_FIND_NC_IN_CACHE = 8421_u32 + ERROR_DS_CANT_RETRIEVE_CHILD = 8422_u32 + ERROR_DS_SECURITY_ILLEGAL_MODIFY = 8423_u32 + ERROR_DS_CANT_REPLACE_HIDDEN_REC = 8424_u32 + ERROR_DS_BAD_HIERARCHY_FILE = 8425_u32 + ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED = 8426_u32 + ERROR_DS_CONFIG_PARAM_MISSING = 8427_u32 + ERROR_DS_COUNTING_AB_INDICES_FAILED = 8428_u32 + ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED = 8429_u32 + ERROR_DS_INTERNAL_FAILURE = 8430_u32 + ERROR_DS_UNKNOWN_ERROR = 8431_u32 + ERROR_DS_ROOT_REQUIRES_CLASS_TOP = 8432_u32 + ERROR_DS_REFUSING_FSMO_ROLES = 8433_u32 + ERROR_DS_MISSING_FSMO_SETTINGS = 8434_u32 + ERROR_DS_UNABLE_TO_SURRENDER_ROLES = 8435_u32 + ERROR_DS_DRA_GENERIC = 8436_u32 + ERROR_DS_DRA_INVALID_PARAMETER = 8437_u32 + ERROR_DS_DRA_BUSY = 8438_u32 + ERROR_DS_DRA_BAD_DN = 8439_u32 + ERROR_DS_DRA_BAD_NC = 8440_u32 + ERROR_DS_DRA_DN_EXISTS = 8441_u32 + ERROR_DS_DRA_INTERNAL_ERROR = 8442_u32 + ERROR_DS_DRA_INCONSISTENT_DIT = 8443_u32 + ERROR_DS_DRA_CONNECTION_FAILED = 8444_u32 + ERROR_DS_DRA_BAD_INSTANCE_TYPE = 8445_u32 + ERROR_DS_DRA_OUT_OF_MEM = 8446_u32 + ERROR_DS_DRA_MAIL_PROBLEM = 8447_u32 + ERROR_DS_DRA_REF_ALREADY_EXISTS = 8448_u32 + ERROR_DS_DRA_REF_NOT_FOUND = 8449_u32 + ERROR_DS_DRA_OBJ_IS_REP_SOURCE = 8450_u32 + ERROR_DS_DRA_DB_ERROR = 8451_u32 + ERROR_DS_DRA_NO_REPLICA = 8452_u32 + ERROR_DS_DRA_ACCESS_DENIED = 8453_u32 + ERROR_DS_DRA_NOT_SUPPORTED = 8454_u32 + ERROR_DS_DRA_RPC_CANCELLED = 8455_u32 + ERROR_DS_DRA_SOURCE_DISABLED = 8456_u32 + ERROR_DS_DRA_SINK_DISABLED = 8457_u32 + ERROR_DS_DRA_NAME_COLLISION = 8458_u32 + ERROR_DS_DRA_SOURCE_REINSTALLED = 8459_u32 + ERROR_DS_DRA_MISSING_PARENT = 8460_u32 + ERROR_DS_DRA_PREEMPTED = 8461_u32 + ERROR_DS_DRA_ABANDON_SYNC = 8462_u32 + ERROR_DS_DRA_SHUTDOWN = 8463_u32 + ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET = 8464_u32 + ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA = 8465_u32 + ERROR_DS_DRA_EXTN_CONNECTION_FAILED = 8466_u32 + ERROR_DS_INSTALL_SCHEMA_MISMATCH = 8467_u32 + ERROR_DS_DUP_LINK_ID = 8468_u32 + ERROR_DS_NAME_ERROR_RESOLVING = 8469_u32 + ERROR_DS_NAME_ERROR_NOT_FOUND = 8470_u32 + ERROR_DS_NAME_ERROR_NOT_UNIQUE = 8471_u32 + ERROR_DS_NAME_ERROR_NO_MAPPING = 8472_u32 + ERROR_DS_NAME_ERROR_DOMAIN_ONLY = 8473_u32 + ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 8474_u32 + ERROR_DS_CONSTRUCTED_ATT_MOD = 8475_u32 + ERROR_DS_WRONG_OM_OBJ_CLASS = 8476_u32 + ERROR_DS_DRA_REPL_PENDING = 8477_u32 + ERROR_DS_DS_REQUIRED = 8478_u32 + ERROR_DS_INVALID_LDAP_DISPLAY_NAME = 8479_u32 + ERROR_DS_NON_BASE_SEARCH = 8480_u32 + ERROR_DS_CANT_RETRIEVE_ATTS = 8481_u32 + ERROR_DS_BACKLINK_WITHOUT_LINK = 8482_u32 + ERROR_DS_EPOCH_MISMATCH = 8483_u32 + ERROR_DS_SRC_NAME_MISMATCH = 8484_u32 + ERROR_DS_SRC_AND_DST_NC_IDENTICAL = 8485_u32 + ERROR_DS_DST_NC_MISMATCH = 8486_u32 + ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC = 8487_u32 + ERROR_DS_SRC_GUID_MISMATCH = 8488_u32 + ERROR_DS_CANT_MOVE_DELETED_OBJECT = 8489_u32 + ERROR_DS_PDC_OPERATION_IN_PROGRESS = 8490_u32 + ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD = 8491_u32 + ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION = 8492_u32 + ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS = 8493_u32 + ERROR_DS_NC_MUST_HAVE_NC_PARENT = 8494_u32 + ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE = 8495_u32 + ERROR_DS_DST_DOMAIN_NOT_NATIVE = 8496_u32 + ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER = 8497_u32 + ERROR_DS_CANT_MOVE_ACCOUNT_GROUP = 8498_u32 + ERROR_DS_CANT_MOVE_RESOURCE_GROUP = 8499_u32 + ERROR_DS_INVALID_SEARCH_FLAG = 8500_u32 + ERROR_DS_NO_TREE_DELETE_ABOVE_NC = 8501_u32 + ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE = 8502_u32 + ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE = 8503_u32 + ERROR_DS_SAM_INIT_FAILURE = 8504_u32 + ERROR_DS_SENSITIVE_GROUP_VIOLATION = 8505_u32 + ERROR_DS_CANT_MOD_PRIMARYGROUPID = 8506_u32 + ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD = 8507_u32 + ERROR_DS_NONSAFE_SCHEMA_CHANGE = 8508_u32 + ERROR_DS_SCHEMA_UPDATE_DISALLOWED = 8509_u32 + ERROR_DS_CANT_CREATE_UNDER_SCHEMA = 8510_u32 + ERROR_DS_INSTALL_NO_SRC_SCH_VERSION = 8511_u32 + ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE = 8512_u32 + ERROR_DS_INVALID_GROUP_TYPE = 8513_u32 + ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = 8514_u32 + ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = 8515_u32 + ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = 8516_u32 + ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = 8517_u32 + ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = 8518_u32 + ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = 8519_u32 + ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = 8520_u32 + ERROR_DS_HAVE_PRIMARY_MEMBERS = 8521_u32 + ERROR_DS_STRING_SD_CONVERSION_FAILED = 8522_u32 + ERROR_DS_NAMING_MASTER_GC = 8523_u32 + ERROR_DS_DNS_LOOKUP_FAILURE = 8524_u32 + ERROR_DS_COULDNT_UPDATE_SPNS = 8525_u32 + ERROR_DS_CANT_RETRIEVE_SD = 8526_u32 + ERROR_DS_KEY_NOT_UNIQUE = 8527_u32 + ERROR_DS_WRONG_LINKED_ATT_SYNTAX = 8528_u32 + ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD = 8529_u32 + ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY = 8530_u32 + ERROR_DS_CANT_START = 8531_u32 + ERROR_DS_INIT_FAILURE = 8532_u32 + ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION = 8533_u32 + ERROR_DS_SOURCE_DOMAIN_IN_FOREST = 8534_u32 + ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST = 8535_u32 + ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED = 8536_u32 + ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN = 8537_u32 + ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER = 8538_u32 + ERROR_DS_SRC_SID_EXISTS_IN_FOREST = 8539_u32 + ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH = 8540_u32 + ERROR_SAM_INIT_FAILURE = 8541_u32 + ERROR_DS_DRA_SCHEMA_INFO_SHIP = 8542_u32 + ERROR_DS_DRA_SCHEMA_CONFLICT = 8543_u32 + ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT = 8544_u32 + ERROR_DS_DRA_OBJ_NC_MISMATCH = 8545_u32 + ERROR_DS_NC_STILL_HAS_DSAS = 8546_u32 + ERROR_DS_GC_REQUIRED = 8547_u32 + ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY = 8548_u32 + ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS = 8549_u32 + ERROR_DS_CANT_ADD_TO_GC = 8550_u32 + ERROR_DS_NO_CHECKPOINT_WITH_PDC = 8551_u32 + ERROR_DS_SOURCE_AUDITING_NOT_ENABLED = 8552_u32 + ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC = 8553_u32 + ERROR_DS_INVALID_NAME_FOR_SPN = 8554_u32 + ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS = 8555_u32 + ERROR_DS_UNICODEPWD_NOT_IN_QUOTES = 8556_u32 + ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = 8557_u32 + ERROR_DS_MUST_BE_RUN_ON_DST_DC = 8558_u32 + ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER = 8559_u32 + ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ = 8560_u32 + ERROR_DS_INIT_FAILURE_CONSOLE = 8561_u32 + ERROR_DS_SAM_INIT_FAILURE_CONSOLE = 8562_u32 + ERROR_DS_FOREST_VERSION_TOO_HIGH = 8563_u32 + ERROR_DS_DOMAIN_VERSION_TOO_HIGH = 8564_u32 + ERROR_DS_FOREST_VERSION_TOO_LOW = 8565_u32 + ERROR_DS_DOMAIN_VERSION_TOO_LOW = 8566_u32 + ERROR_DS_INCOMPATIBLE_VERSION = 8567_u32 + ERROR_DS_LOW_DSA_VERSION = 8568_u32 + ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN = 8569_u32 + ERROR_DS_NOT_SUPPORTED_SORT_ORDER = 8570_u32 + ERROR_DS_NAME_NOT_UNIQUE = 8571_u32 + ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4 = 8572_u32 + ERROR_DS_OUT_OF_VERSION_STORE = 8573_u32 + ERROR_DS_INCOMPATIBLE_CONTROLS_USED = 8574_u32 + ERROR_DS_NO_REF_DOMAIN = 8575_u32 + ERROR_DS_RESERVED_LINK_ID = 8576_u32 + ERROR_DS_LINK_ID_NOT_AVAILABLE = 8577_u32 + ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = 8578_u32 + ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE = 8579_u32 + ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC = 8580_u32 + ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG = 8581_u32 + ERROR_DS_MODIFYDN_WRONG_GRANDPARENT = 8582_u32 + ERROR_DS_NAME_ERROR_TRUST_REFERRAL = 8583_u32 + ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER = 8584_u32 + ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD = 8585_u32 + ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2 = 8586_u32 + ERROR_DS_THREAD_LIMIT_EXCEEDED = 8587_u32 + ERROR_DS_NOT_CLOSEST = 8588_u32 + ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF = 8589_u32 + ERROR_DS_SINGLE_USER_MODE_FAILED = 8590_u32 + ERROR_DS_NTDSCRIPT_SYNTAX_ERROR = 8591_u32 + ERROR_DS_NTDSCRIPT_PROCESS_ERROR = 8592_u32 + ERROR_DS_DIFFERENT_REPL_EPOCHS = 8593_u32 + ERROR_DS_DRS_EXTENSIONS_CHANGED = 8594_u32 + ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR = 8595_u32 + ERROR_DS_NO_MSDS_INTID = 8596_u32 + ERROR_DS_DUP_MSDS_INTID = 8597_u32 + ERROR_DS_EXISTS_IN_RDNATTID = 8598_u32 + ERROR_DS_AUTHORIZATION_FAILED = 8599_u32 + ERROR_DS_INVALID_SCRIPT = 8600_u32 + ERROR_DS_REMOTE_CROSSREF_OP_FAILED = 8601_u32 + ERROR_DS_CROSS_REF_BUSY = 8602_u32 + ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN = 8603_u32 + ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC = 8604_u32 + ERROR_DS_DUPLICATE_ID_FOUND = 8605_u32 + ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT = 8606_u32 + ERROR_DS_GROUP_CONVERSION_ERROR = 8607_u32 + ERROR_DS_CANT_MOVE_APP_BASIC_GROUP = 8608_u32 + ERROR_DS_CANT_MOVE_APP_QUERY_GROUP = 8609_u32 + ERROR_DS_ROLE_NOT_VERIFIED = 8610_u32 + ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL = 8611_u32 + ERROR_DS_DOMAIN_RENAME_IN_PROGRESS = 8612_u32 + ERROR_DS_EXISTING_AD_CHILD_NC = 8613_u32 + ERROR_DS_REPL_LIFETIME_EXCEEDED = 8614_u32 + ERROR_DS_DISALLOWED_IN_SYSTEM_CONTAINER = 8615_u32 + ERROR_DS_LDAP_SEND_QUEUE_FULL = 8616_u32 + ERROR_DS_DRA_OUT_SCHEDULE_WINDOW = 8617_u32 + DNS_ERROR_RESPONSE_CODES_BASE = 9000_u32 + DNS_ERROR_MASK = 0x00002328_u32 + DNS_ERROR_RCODE_FORMAT_ERROR = 9001_u32 + DNS_ERROR_RCODE_SERVER_FAILURE = 9002_u32 + DNS_ERROR_RCODE_NAME_ERROR = 9003_u32 + DNS_ERROR_RCODE_NOT_IMPLEMENTED = 9004_u32 + DNS_ERROR_RCODE_REFUSED = 9005_u32 + DNS_ERROR_RCODE_YXDOMAIN = 9006_u32 + DNS_ERROR_RCODE_YXRRSET = 9007_u32 + DNS_ERROR_RCODE_NXRRSET = 9008_u32 + DNS_ERROR_RCODE_NOTAUTH = 9009_u32 + DNS_ERROR_RCODE_NOTZONE = 9010_u32 + DNS_ERROR_RCODE_BADSIG = 9016_u32 + DNS_ERROR_RCODE_BADKEY = 9017_u32 + DNS_ERROR_RCODE_BADTIME = 9018_u32 + DNS_ERROR_RCODE_LAST = DNS_ERROR_RCODE_BADTIME + DNS_ERROR_PACKET_FMT_BASE = 9500_u32 + DNS_INFO_NO_RECORDS = 9501_u32 + DNS_ERROR_BAD_PACKET = 9502_u32 + DNS_ERROR_NO_PACKET = 9503_u32 + DNS_ERROR_RCODE = 9504_u32 + DNS_ERROR_UNSECURE_PACKET = 9505_u32 + DNS_STATUS_PACKET_UNSECURE = DNS_ERROR_UNSECURE_PACKET + DNS_ERROR_NO_MEMORY = ERROR_OUTOFMEMORY + DNS_ERROR_INVALID_NAME = ERROR_INVALID_NAME + DNS_ERROR_INVALID_DATA = ERROR_INVALID_DATA + DNS_ERROR_GENERAL_API_BASE = 9550_u32 + DNS_ERROR_INVALID_TYPE = 9551_u32 + DNS_ERROR_INVALID_IP_ADDRESS = 9552_u32 + DNS_ERROR_INVALID_PROPERTY = 9553_u32 + DNS_ERROR_TRY_AGAIN_LATER = 9554_u32 + DNS_ERROR_NOT_UNIQUE = 9555_u32 + DNS_ERROR_NON_RFC_NAME = 9556_u32 + DNS_STATUS_FQDN = 9557_u32 + DNS_STATUS_DOTTED_NAME = 9558_u32 + DNS_STATUS_SINGLE_PART_NAME = 9559_u32 + DNS_ERROR_INVALID_NAME_CHAR = 9560_u32 + DNS_ERROR_NUMERIC_NAME = 9561_u32 + DNS_ERROR_NOT_ALLOWED_ON_ROOT_SERVER = 9562_u32 + DNS_ERROR_NOT_ALLOWED_UNDER_DELEGATION = 9563_u32 + DNS_ERROR_CANNOT_FIND_ROOT_HINTS = 9564_u32 + DNS_ERROR_INCONSISTENT_ROOT_HINTS = 9565_u32 + DNS_ERROR_ZONE_BASE = 9600_u32 + DNS_ERROR_ZONE_DOES_NOT_EXIST = 9601_u32 + DNS_ERROR_NO_ZONE_INFO = 9602_u32 + DNS_ERROR_INVALID_ZONE_OPERATION = 9603_u32 + DNS_ERROR_ZONE_CONFIGURATION_ERROR = 9604_u32 + DNS_ERROR_ZONE_HAS_NO_SOA_RECORD = 9605_u32 + DNS_ERROR_ZONE_HAS_NO_NS_RECORDS = 9606_u32 + DNS_ERROR_ZONE_LOCKED = 9607_u32 + DNS_ERROR_ZONE_CREATION_FAILED = 9608_u32 + DNS_ERROR_ZONE_ALREADY_EXISTS = 9609_u32 + DNS_ERROR_AUTOZONE_ALREADY_EXISTS = 9610_u32 + DNS_ERROR_INVALID_ZONE_TYPE = 9611_u32 + DNS_ERROR_SECONDARY_REQUIRES_MASTER_IP = 9612_u32 + DNS_ERROR_ZONE_NOT_SECONDARY = 9613_u32 + DNS_ERROR_NEED_SECONDARY_ADDRESSES = 9614_u32 + DNS_ERROR_WINS_INIT_FAILED = 9615_u32 + DNS_ERROR_NEED_WINS_SERVERS = 9616_u32 + DNS_ERROR_NBSTAT_INIT_FAILED = 9617_u32 + DNS_ERROR_SOA_DELETE_INVALID = 9618_u32 + DNS_ERROR_FORWARDER_ALREADY_EXISTS = 9619_u32 + DNS_ERROR_ZONE_REQUIRES_MASTER_IP = 9620_u32 + DNS_ERROR_ZONE_IS_SHUTDOWN = 9621_u32 + DNS_ERROR_DATAFILE_BASE = 9650_u32 + DNS_ERROR_PRIMARY_REQUIRES_DATAFILE = 9651_u32 + DNS_ERROR_INVALID_DATAFILE_NAME = 9652_u32 + DNS_ERROR_DATAFILE_OPEN_FAILURE = 9653_u32 + DNS_ERROR_FILE_WRITEBACK_FAILED = 9654_u32 + DNS_ERROR_DATAFILE_PARSING = 9655_u32 + DNS_ERROR_DATABASE_BASE = 9700_u32 + DNS_ERROR_RECORD_DOES_NOT_EXIST = 9701_u32 + DNS_ERROR_RECORD_FORMAT = 9702_u32 + DNS_ERROR_NODE_CREATION_FAILED = 9703_u32 + DNS_ERROR_UNKNOWN_RECORD_TYPE = 9704_u32 + DNS_ERROR_RECORD_TIMED_OUT = 9705_u32 + DNS_ERROR_NAME_NOT_IN_ZONE = 9706_u32 + DNS_ERROR_CNAME_LOOP = 9707_u32 + DNS_ERROR_NODE_IS_CNAME = 9708_u32 + DNS_ERROR_CNAME_COLLISION = 9709_u32 + DNS_ERROR_RECORD_ONLY_AT_ZONE_ROOT = 9710_u32 + DNS_ERROR_RECORD_ALREADY_EXISTS = 9711_u32 + DNS_ERROR_SECONDARY_DATA = 9712_u32 + DNS_ERROR_NO_CREATE_CACHE_DATA = 9713_u32 + DNS_ERROR_NAME_DOES_NOT_EXIST = 9714_u32 + DNS_WARNING_PTR_CREATE_FAILED = 9715_u32 + DNS_WARNING_DOMAIN_UNDELETED = 9716_u32 + DNS_ERROR_DS_UNAVAILABLE = 9717_u32 + DNS_ERROR_DS_ZONE_ALREADY_EXISTS = 9718_u32 + DNS_ERROR_NO_BOOTFILE_IF_DS_ZONE = 9719_u32 + DNS_ERROR_OPERATION_BASE = 9750_u32 + DNS_INFO_AXFR_COMPLETE = 9751_u32 + DNS_ERROR_AXFR = 9752_u32 + DNS_INFO_ADDED_LOCAL_WINS = 9753_u32 + DNS_ERROR_SECURE_BASE = 9800_u32 + DNS_STATUS_CONTINUE_NEEDED = 9801_u32 + DNS_ERROR_SETUP_BASE = 9850_u32 + DNS_ERROR_NO_TCPIP = 9851_u32 + DNS_ERROR_NO_DNS_SERVERS = 9852_u32 + DNS_ERROR_DP_BASE = 9900_u32 + DNS_ERROR_DP_DOES_NOT_EXIST = 9901_u32 + DNS_ERROR_DP_ALREADY_EXISTS = 9902_u32 + DNS_ERROR_DP_NOT_ENLISTED = 9903_u32 + DNS_ERROR_DP_ALREADY_ENLISTED = 9904_u32 + DNS_ERROR_DP_NOT_AVAILABLE = 9905_u32 + DNS_ERROR_DP_FSMO_ERROR = 9906_u32 + WSABASEERR = 10000_u32 + WSAEINTR = (WSABASEERR + 4) + WSAEBADF = (WSABASEERR + 9) + WSAEACCES = (WSABASEERR + 13) + WSAEFAULT = (WSABASEERR + 14) + WSAEINVAL = (WSABASEERR + 22) + WSAEMFILE = (WSABASEERR + 24) + WSAEWOULDBLOCK = (WSABASEERR + 35) + WSAEINPROGRESS = (WSABASEERR + 36) + WSAEALREADY = (WSABASEERR + 37) + WSAENOTSOCK = (WSABASEERR + 38) + WSAEDESTADDRREQ = (WSABASEERR + 39) + WSAEMSGSIZE = (WSABASEERR + 40) + WSAEPROTOTYPE = (WSABASEERR + 41) + WSAENOPROTOOPT = (WSABASEERR + 42) + WSAEPROTONOSUPPORT = (WSABASEERR + 43) + WSAESOCKTNOSUPPORT = (WSABASEERR + 44) + WSAEOPNOTSUPP = (WSABASEERR + 45) + WSAEPFNOSUPPORT = (WSABASEERR + 46) + WSAEAFNOSUPPORT = (WSABASEERR + 47) + WSAEADDRINUSE = (WSABASEERR + 48) + WSAEADDRNOTAVAIL = (WSABASEERR + 49) + WSAENETDOWN = (WSABASEERR + 50) + WSAENETUNREACH = (WSABASEERR + 51) + WSAENETRESET = (WSABASEERR + 52) + WSAECONNABORTED = (WSABASEERR + 53) + WSAECONNRESET = (WSABASEERR + 54) + WSAENOBUFS = (WSABASEERR + 55) + WSAEISCONN = (WSABASEERR + 56) + WSAENOTCONN = (WSABASEERR + 57) + WSAESHUTDOWN = (WSABASEERR + 58) + WSAETOOMANYREFS = (WSABASEERR + 59) + WSAETIMEDOUT = (WSABASEERR + 60) + WSAECONNREFUSED = (WSABASEERR + 61) + WSAELOOP = (WSABASEERR + 62) + WSAENAMETOOLONG = (WSABASEERR + 63) + WSAEHOSTDOWN = (WSABASEERR + 64) + WSAEHOSTUNREACH = (WSABASEERR + 65) + WSAENOTEMPTY = (WSABASEERR + 66) + WSAEPROCLIM = (WSABASEERR + 67) + WSAEUSERS = (WSABASEERR + 68) + WSAEDQUOT = (WSABASEERR + 69) + WSAESTALE = (WSABASEERR + 70) + WSAEREMOTE = (WSABASEERR + 71) + WSASYSNOTREADY = (WSABASEERR + 91) + WSAVERNOTSUPPORTED = (WSABASEERR + 92) + WSANOTINITIALISED = (WSABASEERR + 93) + WSAEDISCON = (WSABASEERR + 101) + WSAENOMORE = (WSABASEERR + 102) + WSAECANCELLED = (WSABASEERR + 103) + WSAEINVALIDPROCTABLE = (WSABASEERR + 104) + WSAEINVALIDPROVIDER = (WSABASEERR + 105) + WSAEPROVIDERFAILEDINIT = (WSABASEERR + 106) + WSASYSCALLFAILURE = (WSABASEERR + 107) + WSASERVICE_NOT_FOUND = (WSABASEERR + 108) + WSATYPE_NOT_FOUND = (WSABASEERR + 109) + WSA_E_NO_MORE = (WSABASEERR + 110) + WSA_E_CANCELLED = (WSABASEERR + 111) + WSAEREFUSED = (WSABASEERR + 112) + WSAHOST_NOT_FOUND = (WSABASEERR + 1001) + WSATRY_AGAIN = (WSABASEERR + 1002) + WSANO_RECOVERY = (WSABASEERR + 1003) + WSANO_DATA = (WSABASEERR + 1004) + WSA_QOS_RECEIVERS = (WSABASEERR + 1005) + WSA_QOS_SENDERS = (WSABASEERR + 1006) + WSA_QOS_NO_SENDERS = (WSABASEERR + 1007) + WSA_QOS_NO_RECEIVERS = (WSABASEERR + 1008) + WSA_QOS_REQUEST_CONFIRMED = (WSABASEERR + 1009) + WSA_QOS_ADMISSION_FAILURE = (WSABASEERR + 1010) + WSA_QOS_POLICY_FAILURE = (WSABASEERR + 1011) + WSA_QOS_BAD_STYLE = (WSABASEERR + 1012) + WSA_QOS_BAD_OBJECT = (WSABASEERR + 1013) + WSA_QOS_TRAFFIC_CTRL_ERROR = (WSABASEERR + 1014) + WSA_QOS_GENERIC_ERROR = (WSABASEERR + 1015) + WSA_QOS_ESERVICETYPE = (WSABASEERR + 1016) + WSA_QOS_EFLOWSPEC = (WSABASEERR + 1017) + WSA_QOS_EPROVSPECBUF = (WSABASEERR + 1018) + WSA_QOS_EFILTERSTYLE = (WSABASEERR + 1019) + WSA_QOS_EFILTERTYPE = (WSABASEERR + 1020) + WSA_QOS_EFILTERCOUNT = (WSABASEERR + 1021) + WSA_QOS_EOBJLENGTH = (WSABASEERR + 1022) + WSA_QOS_EFLOWCOUNT = (WSABASEERR + 1023) + WSA_QOS_EUNKNOWNPSOBJ = (WSABASEERR + 1024) + WSA_QOS_EUNKOWNPSOBJ = WSA_QOS_EUNKNOWNPSOBJ + WSA_QOS_EPOLICYOBJ = (WSABASEERR + 1025) + WSA_QOS_EFLOWDESC = (WSABASEERR + 1026) + WSA_QOS_EPSFLOWSPEC = (WSABASEERR + 1027) + WSA_QOS_EPSFILTERSPEC = (WSABASEERR + 1028) + WSA_QOS_ESDMODEOBJ = (WSABASEERR + 1029) + WSA_QOS_ESHAPERATEOBJ = (WSABASEERR + 1030) + WSA_QOS_RESERVED_PETYPE = (WSABASEERR + 1031) + ERROR_SXS_SECTION_NOT_FOUND = 14000_u32 + ERROR_SXS_CANT_GEN_ACTCTX = 14001_u32 + ERROR_SXS_INVALID_ACTCTXDATA_FORMAT = 14002_u32 + ERROR_SXS_ASSEMBLY_NOT_FOUND = 14003_u32 + ERROR_SXS_MANIFEST_FORMAT_ERROR = 14004_u32 + ERROR_SXS_MANIFEST_PARSE_ERROR = 14005_u32 + ERROR_SXS_ACTIVATION_CONTEXT_DISABLED = 14006_u32 + ERROR_SXS_KEY_NOT_FOUND = 14007_u32 + ERROR_SXS_VERSION_CONFLICT = 14008_u32 + ERROR_SXS_WRONG_SECTION_TYPE = 14009_u32 + ERROR_SXS_THREAD_QUERIES_DISABLED = 14010_u32 + ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET = 14011_u32 + ERROR_SXS_UNKNOWN_ENCODING_GROUP = 14012_u32 + ERROR_SXS_UNKNOWN_ENCODING = 14013_u32 + ERROR_SXS_INVALID_XML_NAMESPACE_URI = 14014_u32 + ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED = 14015_u32 + ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED = 14016_u32 + ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE = 14017_u32 + ERROR_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE = 14018_u32 + ERROR_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE = 14019_u32 + ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT = 14020_u32 + ERROR_SXS_DUPLICATE_DLL_NAME = 14021_u32 + ERROR_SXS_DUPLICATE_WINDOWCLASS_NAME = 14022_u32 + ERROR_SXS_DUPLICATE_CLSID = 14023_u32 + ERROR_SXS_DUPLICATE_IID = 14024_u32 + ERROR_SXS_DUPLICATE_TLBID = 14025_u32 + ERROR_SXS_DUPLICATE_PROGID = 14026_u32 + ERROR_SXS_DUPLICATE_ASSEMBLY_NAME = 14027_u32 + ERROR_SXS_FILE_HASH_MISMATCH = 14028_u32 + ERROR_SXS_POLICY_PARSE_ERROR = 14029_u32 + ERROR_SXS_XML_E_MISSINGQUOTE = 14030_u32 + ERROR_SXS_XML_E_COMMENTSYNTAX = 14031_u32 + ERROR_SXS_XML_E_BADSTARTNAMECHAR = 14032_u32 + ERROR_SXS_XML_E_BADNAMECHAR = 14033_u32 + ERROR_SXS_XML_E_BADCHARINSTRING = 14034_u32 + ERROR_SXS_XML_E_XMLDECLSYNTAX = 14035_u32 + ERROR_SXS_XML_E_BADCHARDATA = 14036_u32 + ERROR_SXS_XML_E_MISSINGWHITESPACE = 14037_u32 + ERROR_SXS_XML_E_EXPECTINGTAGEND = 14038_u32 + ERROR_SXS_XML_E_MISSINGSEMICOLON = 14039_u32 + ERROR_SXS_XML_E_UNBALANCEDPAREN = 14040_u32 + ERROR_SXS_XML_E_INTERNALERROR = 14041_u32 + ERROR_SXS_XML_E_UNEXPECTED_WHITESPACE = 14042_u32 + ERROR_SXS_XML_E_INCOMPLETE_ENCODING = 14043_u32 + ERROR_SXS_XML_E_MISSING_PAREN = 14044_u32 + ERROR_SXS_XML_E_EXPECTINGCLOSEQUOTE = 14045_u32 + ERROR_SXS_XML_E_MULTIPLE_COLONS = 14046_u32 + ERROR_SXS_XML_E_INVALID_DECIMAL = 14047_u32 + ERROR_SXS_XML_E_INVALID_HEXIDECIMAL = 14048_u32 + ERROR_SXS_XML_E_INVALID_UNICODE = 14049_u32 + ERROR_SXS_XML_E_WHITESPACEORQUESTIONMARK = 14050_u32 + ERROR_SXS_XML_E_UNEXPECTEDENDTAG = 14051_u32 + ERROR_SXS_XML_E_UNCLOSEDTAG = 14052_u32 + ERROR_SXS_XML_E_DUPLICATEATTRIBUTE = 14053_u32 + ERROR_SXS_XML_E_MULTIPLEROOTS = 14054_u32 + ERROR_SXS_XML_E_INVALIDATROOTLEVEL = 14055_u32 + ERROR_SXS_XML_E_BADXMLDECL = 14056_u32 + ERROR_SXS_XML_E_MISSINGROOT = 14057_u32 + ERROR_SXS_XML_E_UNEXPECTEDEOF = 14058_u32 + ERROR_SXS_XML_E_BADPEREFINSUBSET = 14059_u32 + ERROR_SXS_XML_E_UNCLOSEDSTARTTAG = 14060_u32 + ERROR_SXS_XML_E_UNCLOSEDENDTAG = 14061_u32 + ERROR_SXS_XML_E_UNCLOSEDSTRING = 14062_u32 + ERROR_SXS_XML_E_UNCLOSEDCOMMENT = 14063_u32 + ERROR_SXS_XML_E_UNCLOSEDDECL = 14064_u32 + ERROR_SXS_XML_E_UNCLOSEDCDATA = 14065_u32 + ERROR_SXS_XML_E_RESERVEDNAMESPACE = 14066_u32 + ERROR_SXS_XML_E_INVALIDENCODING = 14067_u32 + ERROR_SXS_XML_E_INVALIDSWITCH = 14068_u32 + ERROR_SXS_XML_E_BADXMLCASE = 14069_u32 + ERROR_SXS_XML_E_INVALID_STANDALONE = 14070_u32 + ERROR_SXS_XML_E_UNEXPECTED_STANDALONE = 14071_u32 + ERROR_SXS_XML_E_INVALID_VERSION = 14072_u32 + ERROR_SXS_XML_E_MISSINGEQUALS = 14073_u32 + ERROR_SXS_PROTECTION_RECOVERY_FAILED = 14074_u32 + ERROR_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT = 14075_u32 + ERROR_SXS_PROTECTION_CATALOG_NOT_VALID = 14076_u32 + ERROR_SXS_UNTRANSLATABLE_HRESULT = 14077_u32 + ERROR_SXS_PROTECTION_CATALOG_FILE_MISSING = 14078_u32 + ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE = 14079_u32 + ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME = 14080_u32 + ERROR_SXS_ASSEMBLY_MISSING = 14081_u32 + ERROR_SXS_CORRUPT_ACTIVATION_STACK = 14082_u32 + ERROR_SXS_CORRUPTION = 14083_u32 + ERROR_SXS_EARLY_DEACTIVATION = 14084_u32 + ERROR_SXS_INVALID_DEACTIVATION = 14085_u32 + ERROR_SXS_MULTIPLE_DEACTIVATION = 14086_u32 + ERROR_SXS_PROCESS_TERMINATION_REQUESTED = 14087_u32 + ERROR_SXS_RELEASE_ACTIVATION_CONTEXT = 14088_u32 + ERROR_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY = 14089_u32 + ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE = 14090_u32 + ERROR_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME = 14091_u32 + ERROR_SXS_IDENTITY_DUPLICATE_ATTRIBUTE = 14092_u32 + ERROR_SXS_IDENTITY_PARSE_ERROR = 14093_u32 + ERROR_MALFORMED_SUBSTITUTION_STRING = 14094_u32 + ERROR_SXS_INCORRECT_PUBLIC_KEY_TOKEN = 14095_u32 + ERROR_UNMAPPED_SUBSTITUTION_STRING = 14096_u32 + ERROR_SXS_ASSEMBLY_NOT_LOCKED = 14097_u32 + ERROR_SXS_COMPONENT_STORE_CORRUPT = 14098_u32 + ERROR_ADVANCED_INSTALLER_FAILED = 14099_u32 + ERROR_XML_ENCODING_MISMATCH = 14100_u32 + ERROR_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT = 14101_u32 + ERROR_SXS_IDENTITIES_DIFFERENT = 14102_u32 + ERROR_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT = 14103_u32 + ERROR_SXS_FILE_NOT_PART_OF_ASSEMBLY = 14104_u32 + ERROR_SXS_MANIFEST_TOO_BIG = 14105_u32 + ERROR_SXS_SETTING_NOT_REGISTERED = 14106_u32 + ERROR_SXS_TRANSACTION_CLOSURE_INCOMPLETE = 14107_u32 + ERROR_SMI_PRIMITIVE_INSTALLER_FAILED = 14108_u32 + ERROR_GENERIC_COMMAND_FAILED = 14109_u32 + ERROR_SXS_FILE_HASH_MISSING = 14110_u32 + ERROR_IPSEC_QM_POLICY_EXISTS = 13000_u32 + ERROR_IPSEC_QM_POLICY_NOT_FOUND = 13001_u32 + ERROR_IPSEC_QM_POLICY_IN_USE = 13002_u32 + ERROR_IPSEC_MM_POLICY_EXISTS = 13003_u32 + ERROR_IPSEC_MM_POLICY_NOT_FOUND = 13004_u32 + ERROR_IPSEC_MM_POLICY_IN_USE = 13005_u32 + ERROR_IPSEC_MM_FILTER_EXISTS = 13006_u32 + ERROR_IPSEC_MM_FILTER_NOT_FOUND = 13007_u32 + ERROR_IPSEC_TRANSPORT_FILTER_EXISTS = 13008_u32 + ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND = 13009_u32 + ERROR_IPSEC_MM_AUTH_EXISTS = 13010_u32 + ERROR_IPSEC_MM_AUTH_NOT_FOUND = 13011_u32 + ERROR_IPSEC_MM_AUTH_IN_USE = 13012_u32 + ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND = 13013_u32 + ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND = 13014_u32 + ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND = 13015_u32 + ERROR_IPSEC_TUNNEL_FILTER_EXISTS = 13016_u32 + ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND = 13017_u32 + ERROR_IPSEC_MM_FILTER_PENDING_DELETION = 13018_u32 + ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION = 13019_u32 + ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION = 13020_u32 + ERROR_IPSEC_MM_POLICY_PENDING_DELETION = 13021_u32 + ERROR_IPSEC_MM_AUTH_PENDING_DELETION = 13022_u32 + ERROR_IPSEC_QM_POLICY_PENDING_DELETION = 13023_u32 + WARNING_IPSEC_MM_POLICY_PRUNED = 13024_u32 + WARNING_IPSEC_QM_POLICY_PRUNED = 13025_u32 + ERROR_IPSEC_IKE_NEG_STATUS_BEGIN = 13800_u32 + ERROR_IPSEC_IKE_AUTH_FAIL = 13801_u32 + ERROR_IPSEC_IKE_ATTRIB_FAIL = 13802_u32 + ERROR_IPSEC_IKE_NEGOTIATION_PENDING = 13803_u32 + ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR = 13804_u32 + ERROR_IPSEC_IKE_TIMED_OUT = 13805_u32 + ERROR_IPSEC_IKE_NO_CERT = 13806_u32 + ERROR_IPSEC_IKE_SA_DELETED = 13807_u32 + ERROR_IPSEC_IKE_SA_REAPED = 13808_u32 + ERROR_IPSEC_IKE_MM_ACQUIRE_DROP = 13809_u32 + ERROR_IPSEC_IKE_QM_ACQUIRE_DROP = 13810_u32 + ERROR_IPSEC_IKE_QUEUE_DROP_MM = 13811_u32 + ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM = 13812_u32 + ERROR_IPSEC_IKE_DROP_NO_RESPONSE = 13813_u32 + ERROR_IPSEC_IKE_MM_DELAY_DROP = 13814_u32 + ERROR_IPSEC_IKE_QM_DELAY_DROP = 13815_u32 + ERROR_IPSEC_IKE_ERROR = 13816_u32 + ERROR_IPSEC_IKE_CRL_FAILED = 13817_u32 + ERROR_IPSEC_IKE_INVALID_KEY_USAGE = 13818_u32 + ERROR_IPSEC_IKE_INVALID_CERT_TYPE = 13819_u32 + ERROR_IPSEC_IKE_NO_PRIVATE_KEY = 13820_u32 + ERROR_IPSEC_IKE_DH_FAIL = 13822_u32 + ERROR_IPSEC_IKE_INVALID_HEADER = 13824_u32 + ERROR_IPSEC_IKE_NO_POLICY = 13825_u32 + ERROR_IPSEC_IKE_INVALID_SIGNATURE = 13826_u32 + ERROR_IPSEC_IKE_KERBEROS_ERROR = 13827_u32 + ERROR_IPSEC_IKE_NO_PUBLIC_KEY = 13828_u32 + ERROR_IPSEC_IKE_PROCESS_ERR = 13829_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_SA = 13830_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_PROP = 13831_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_TRANS = 13832_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_KE = 13833_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_ID = 13834_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_CERT = 13835_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ = 13836_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_HASH = 13837_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_SIG = 13838_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_NONCE = 13839_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY = 13840_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_DELETE = 13841_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR = 13842_u32 + ERROR_IPSEC_IKE_INVALID_PAYLOAD = 13843_u32 + ERROR_IPSEC_IKE_LOAD_SOFT_SA = 13844_u32 + ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN = 13845_u32 + ERROR_IPSEC_IKE_INVALID_COOKIE = 13846_u32 + ERROR_IPSEC_IKE_NO_PEER_CERT = 13847_u32 + ERROR_IPSEC_IKE_PEER_CRL_FAILED = 13848_u32 + ERROR_IPSEC_IKE_POLICY_CHANGE = 13849_u32 + ERROR_IPSEC_IKE_NO_MM_POLICY = 13850_u32 + ERROR_IPSEC_IKE_NOTCBPRIV = 13851_u32 + ERROR_IPSEC_IKE_SECLOADFAIL = 13852_u32 + ERROR_IPSEC_IKE_FAILSSPINIT = 13853_u32 + ERROR_IPSEC_IKE_FAILQUERYSSP = 13854_u32 + ERROR_IPSEC_IKE_SRVACQFAIL = 13855_u32 + ERROR_IPSEC_IKE_SRVQUERYCRED = 13856_u32 + ERROR_IPSEC_IKE_GETSPIFAIL = 13857_u32 + ERROR_IPSEC_IKE_INVALID_FILTER = 13858_u32 + ERROR_IPSEC_IKE_OUT_OF_MEMORY = 13859_u32 + ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED = 13860_u32 + ERROR_IPSEC_IKE_INVALID_POLICY = 13861_u32 + ERROR_IPSEC_IKE_UNKNOWN_DOI = 13862_u32 + ERROR_IPSEC_IKE_INVALID_SITUATION = 13863_u32 + ERROR_IPSEC_IKE_DH_FAILURE = 13864_u32 + ERROR_IPSEC_IKE_INVALID_GROUP = 13865_u32 + ERROR_IPSEC_IKE_ENCRYPT = 13866_u32 + ERROR_IPSEC_IKE_DECRYPT = 13867_u32 + ERROR_IPSEC_IKE_POLICY_MATCH = 13868_u32 + ERROR_IPSEC_IKE_UNSUPPORTED_ID = 13869_u32 + ERROR_IPSEC_IKE_INVALID_HASH = 13870_u32 + ERROR_IPSEC_IKE_INVALID_HASH_ALG = 13871_u32 + ERROR_IPSEC_IKE_INVALID_HASH_SIZE = 13872_u32 + ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG = 13873_u32 + ERROR_IPSEC_IKE_INVALID_AUTH_ALG = 13874_u32 + ERROR_IPSEC_IKE_INVALID_SIG = 13875_u32 + ERROR_IPSEC_IKE_LOAD_FAILED = 13876_u32 + ERROR_IPSEC_IKE_RPC_DELETE = 13877_u32 + ERROR_IPSEC_IKE_BENIGN_REINIT = 13878_u32 + ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY = 13879_u32 + ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN = 13881_u32 + ERROR_IPSEC_IKE_MM_LIMIT = 13882_u32 + ERROR_IPSEC_IKE_NEGOTIATION_DISABLED = 13883_u32 + ERROR_IPSEC_IKE_QM_LIMIT = 13884_u32 + ERROR_IPSEC_IKE_MM_EXPIRED = 13885_u32 + ERROR_IPSEC_IKE_PEER_MM_ASSUMED_INVALID = 13886_u32 + ERROR_IPSEC_IKE_CERT_CHAIN_POLICY_MISMATCH = 13887_u32 + ERROR_IPSEC_IKE_UNEXPECTED_MESSAGE_ID = 13888_u32 + ERROR_IPSEC_IKE_INVALID_AUTH_PAYLOAD = 13889_u32 + ERROR_IPSEC_IKE_DOS_COOKIE_SENT = 13890_u32 + ERROR_IPSEC_IKE_SHUTTING_DOWN = 13891_u32 + ERROR_IPSEC_IKE_CGA_AUTH_FAILED = 13892_u32 + ERROR_IPSEC_IKE_PROCESS_ERR_NATOA = 13893_u32 + ERROR_IPSEC_IKE_INVALID_MM_FOR_QM = 13894_u32 + ERROR_IPSEC_IKE_QM_EXPIRED = 13895_u32 + ERROR_IPSEC_IKE_TOO_MANY_FILTERS = 13896_u32 + ERROR_IPSEC_IKE_NEG_STATUS_END = 13897_u32 + ERROR_IPSEC_IKE_KILL_DUMMY_NAP_TUNNEL = 13898_u32 + ERROR_IPSEC_IKE_INNER_IP_ASSIGNMENT_FAILURE = 13899_u32 + ERROR_IPSEC_IKE_REQUIRE_CP_PAYLOAD_MISSING = 13900_u32 + ERROR_IPSEC_KEY_MODULE_IMPERSONATION_NEGOTIATION_PENDING = 13901_u32 + ERROR_IPSEC_IKE_COEXISTENCE_SUPPRESS = 13902_u32 + ERROR_IPSEC_IKE_RATELIMIT_DROP = 13903_u32 + ERROR_IPSEC_IKE_PEER_DOESNT_SUPPORT_MOBIKE = 13904_u32 + ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE = 13905_u32 + ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_FAILURE = 13906_u32 + ERROR_IPSEC_IKE_AUTHORIZATION_FAILURE_WITH_OPTIONAL_RETRY = 13907_u32 + ERROR_IPSEC_IKE_STRONG_CRED_AUTHORIZATION_AND_CERTMAP_FAILURE = 13908_u32 + ERROR_IPSEC_IKE_NEG_STATUS_EXTENDED_END = 13909_u32 + ERROR_IPSEC_BAD_SPI = 13910_u32 + ERROR_IPSEC_SA_LIFETIME_EXPIRED = 13911_u32 + ERROR_IPSEC_WRONG_SA = 13912_u32 + ERROR_IPSEC_REPLAY_CHECK_FAILED = 13913_u32 + ERROR_IPSEC_INVALID_PACKET = 13914_u32 + ERROR_IPSEC_INTEGRITY_CHECK_FAILED = 13915_u32 + ERROR_IPSEC_CLEAR_TEXT_DROP = 13916_u32 + ERROR_IPSEC_AUTH_FIREWALL_DROP = 13917_u32 + ERROR_IPSEC_THROTTLE_DROP = 13918_u32 + ERROR_IPSEC_DOSP_BLOCK = 13925_u32 + ERROR_IPSEC_DOSP_RECEIVED_MULTICAST = 13926_u32 + ERROR_IPSEC_DOSP_INVALID_PACKET = 13927_u32 + ERROR_IPSEC_DOSP_STATE_LOOKUP_FAILED = 13928_u32 + ERROR_IPSEC_DOSP_MAX_ENTRIES = 13929_u32 + ERROR_IPSEC_DOSP_KEYMOD_NOT_ALLOWED = 13930_u32 + ERROR_IPSEC_DOSP_NOT_INSTALLED = 13931_u32 + ERROR_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES = 13932_u32 + ERROR_EVT_INVALID_CHANNEL_PATH = 15000_u32 + ERROR_EVT_INVALID_QUERY = 15001_u32 + ERROR_EVT_PUBLISHER_METADATA_NOT_FOUND = 15002_u32 + ERROR_EVT_EVENT_TEMPLATE_NOT_FOUND = 15003_u32 + ERROR_EVT_INVALID_PUBLISHER_NAME = 15004_u32 + ERROR_EVT_INVALID_EVENT_DATA = 15005_u32 + ERROR_EVT_CHANNEL_NOT_FOUND = 15007_u32 + ERROR_EVT_MALFORMED_XML_TEXT = 15008_u32 + ERROR_EVT_SUBSCRIPTION_TO_DIRECT_CHANNEL = 15009_u32 + ERROR_EVT_CONFIGURATION_ERROR = 15010_u32 + ERROR_EVT_QUERY_RESULT_STALE = 15011_u32 + ERROR_EVT_QUERY_RESULT_INVALID_POSITION = 15012_u32 + ERROR_EVT_NON_VALIDATING_MSXML = 15013_u32 + ERROR_EVT_FILTER_ALREADYSCOPED = 15014_u32 + ERROR_EVT_FILTER_NOTELTSET = 15015_u32 + ERROR_EVT_FILTER_INVARG = 15016_u32 + ERROR_EVT_FILTER_INVTEST = 15017_u32 + ERROR_EVT_FILTER_INVTYPE = 15018_u32 + ERROR_EVT_FILTER_PARSEERR = 15019_u32 + ERROR_EVT_FILTER_UNSUPPORTEDOP = 15020_u32 + ERROR_EVT_FILTER_UNEXPECTEDTOKEN = 15021_u32 + ERROR_EVT_INVALID_OPERATION_OVER_ENABLED_DIRECT_CHANNEL = 15022_u32 + ERROR_EVT_INVALID_CHANNEL_PROPERTY_VALUE = 15023_u32 + ERROR_EVT_INVALID_PUBLISHER_PROPERTY_VALUE = 15024_u32 + ERROR_EVT_CHANNEL_CANNOT_ACTIVATE = 15025_u32 + ERROR_EVT_FILTER_TOO_COMPLEX = 15026_u32 + ERROR_EVT_MESSAGE_NOT_FOUND = 15027_u32 + ERROR_EVT_MESSAGE_ID_NOT_FOUND = 15028_u32 + ERROR_EVT_UNRESOLVED_VALUE_INSERT = 15029_u32 + ERROR_EVT_UNRESOLVED_PARAMETER_INSERT = 15030_u32 + ERROR_EVT_MAX_INSERTS_REACHED = 15031_u32 + ERROR_EVT_EVENT_DEFINITION_NOT_FOUND = 15032_u32 + ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND = 15033_u32 + ERROR_EVT_VERSION_TOO_OLD = 15034_u32 + ERROR_EVT_VERSION_TOO_NEW = 15035_u32 + ERROR_EVT_CANNOT_OPEN_CHANNEL_OF_QUERY = 15036_u32 + ERROR_EVT_PUBLISHER_DISABLED = 15037_u32 + ERROR_EVT_FILTER_OUT_OF_RANGE = 15038_u32 + ERROR_EC_SUBSCRIPTION_CANNOT_ACTIVATE = 15080_u32 + ERROR_EC_LOG_DISABLED = 15081_u32 + ERROR_EC_CIRCULAR_FORWARDING = 15082_u32 + ERROR_EC_CREDSTORE_FULL = 15083_u32 + ERROR_EC_CRED_NOT_FOUND = 15084_u32 + ERROR_EC_NO_ACTIVE_CHANNEL = 15085_u32 + ERROR_MUI_FILE_NOT_FOUND = 15100_u32 + ERROR_MUI_INVALID_FILE = 15101_u32 + ERROR_MUI_INVALID_RC_CONFIG = 15102_u32 + ERROR_MUI_INVALID_LOCALE_NAME = 15103_u32 + ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME = 15104_u32 + ERROR_MUI_FILE_NOT_LOADED = 15105_u32 + ERROR_RESOURCE_ENUM_USER_STOP = 15106_u32 + ERROR_MUI_INTLSETTINGS_UILANG_NOT_INSTALLED = 15107_u32 + ERROR_MUI_INTLSETTINGS_INVALID_LOCALE_NAME = 15108_u32 + ERROR_MRM_RUNTIME_NO_DEFAULT_OR_NEUTRAL_RESOURCE = 15110_u32 + ERROR_MRM_INVALID_PRICONFIG = 15111_u32 + ERROR_MRM_INVALID_FILE_TYPE = 15112_u32 + ERROR_MRM_UNKNOWN_QUALIFIER = 15113_u32 + ERROR_MRM_INVALID_QUALIFIER_VALUE = 15114_u32 + ERROR_MRM_NO_CANDIDATE = 15115_u32 + ERROR_MRM_NO_MATCH_OR_DEFAULT_CANDIDATE = 15116_u32 + ERROR_MRM_RESOURCE_TYPE_MISMATCH = 15117_u32 + ERROR_MRM_DUPLICATE_MAP_NAME = 15118_u32 + ERROR_MRM_DUPLICATE_ENTRY = 15119_u32 + ERROR_MRM_INVALID_RESOURCE_IDENTIFIER = 15120_u32 + ERROR_MRM_FILEPATH_TOO_LONG = 15121_u32 + ERROR_MRM_UNSUPPORTED_DIRECTORY_TYPE = 15122_u32 + ERROR_MRM_INVALID_PRI_FILE = 15126_u32 + ERROR_MRM_NAMED_RESOURCE_NOT_FOUND = 15127_u32 + ERROR_MRM_MAP_NOT_FOUND = 15135_u32 + ERROR_MRM_UNSUPPORTED_PROFILE_TYPE = 15136_u32 + ERROR_MRM_INVALID_QUALIFIER_OPERATOR = 15137_u32 + ERROR_MRM_INDETERMINATE_QUALIFIER_VALUE = 15138_u32 + ERROR_MRM_AUTOMERGE_ENABLED = 15139_u32 + ERROR_MRM_TOO_MANY_RESOURCES = 15140_u32 + ERROR_MCA_INVALID_CAPABILITIES_STRING = 15200_u32 + ERROR_MCA_INVALID_VCP_VERSION = 15201_u32 + ERROR_MCA_MONITOR_VIOLATES_MCCS_SPECIFICATION = 15202_u32 + ERROR_MCA_MCCS_VERSION_MISMATCH = 15203_u32 + ERROR_MCA_UNSUPPORTED_MCCS_VERSION = 15204_u32 + ERROR_MCA_INTERNAL_ERROR = 15205_u32 + ERROR_MCA_INVALID_TECHNOLOGY_TYPE_RETURNED = 15206_u32 + ERROR_MCA_UNSUPPORTED_COLOR_TEMPERATURE = 15207_u32 + ERROR_AMBIGUOUS_SYSTEM_DEVICE = 15250_u32 + ERROR_SYSTEM_DEVICE_NOT_FOUND = 15299_u32 + ERROR_HASH_NOT_SUPPORTED = 15300_u32 + ERROR_HASH_NOT_PRESENT = 15301_u32 + ERROR_SECONDARY_IC_PROVIDER_NOT_REGISTERED = 15321_u32 + ERROR_GPIO_CLIENT_INFORMATION_INVALID = 15322_u32 + ERROR_GPIO_VERSION_NOT_SUPPORTED = 15323_u32 + ERROR_GPIO_INVALID_REGISTRATION_PACKET = 15324_u32 + ERROR_GPIO_OPERATION_DENIED = 15325_u32 + ERROR_GPIO_INCOMPATIBLE_CONNECT_MODE = 15326_u32 + ERROR_GPIO_INTERRUPT_ALREADY_UNMASKED = 15327_u32 + ERROR_CANNOT_SWITCH_RUNLEVEL = 15400_u32 + ERROR_INVALID_RUNLEVEL_SETTING = 15401_u32 + ERROR_RUNLEVEL_SWITCH_TIMEOUT = 15402_u32 + ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT = 15403_u32 + ERROR_RUNLEVEL_SWITCH_IN_PROGRESS = 15404_u32 + ERROR_SERVICES_FAILED_AUTOSTART = 15405_u32 + ERROR_COM_TASK_STOP_PENDING = 15501_u32 + ERROR_INSTALL_OPEN_PACKAGE_FAILED = 15600_u32 + ERROR_INSTALL_PACKAGE_NOT_FOUND = 15601_u32 + ERROR_INSTALL_INVALID_PACKAGE = 15602_u32 + ERROR_INSTALL_RESOLVE_DEPENDENCY_FAILED = 15603_u32 + ERROR_INSTALL_OUT_OF_DISK_SPACE = 15604_u32 + ERROR_INSTALL_NETWORK_FAILURE = 15605_u32 + ERROR_INSTALL_REGISTRATION_FAILURE = 15606_u32 + ERROR_INSTALL_DEREGISTRATION_FAILURE = 15607_u32 + ERROR_INSTALL_CANCEL = 15608_u32 + ERROR_INSTALL_FAILED = 15609_u32 + ERROR_REMOVE_FAILED = 15610_u32 + ERROR_PACKAGE_ALREADY_EXISTS = 15611_u32 + ERROR_NEEDS_REMEDIATION = 15612_u32 + ERROR_INSTALL_PREREQUISITE_FAILED = 15613_u32 + ERROR_PACKAGE_REPOSITORY_CORRUPTED = 15614_u32 + ERROR_INSTALL_POLICY_FAILURE = 15615_u32 + ERROR_PACKAGE_UPDATING = 15616_u32 + ERROR_DEPLOYMENT_BLOCKED_BY_POLICY = 15617_u32 + ERROR_PACKAGES_IN_USE = 15618_u32 + ERROR_RECOVERY_FILE_CORRUPT = 15619_u32 + ERROR_INVALID_STAGED_SIGNATURE = 15620_u32 + ERROR_DELETING_EXISTING_APPLICATIONDATA_STORE_FAILED = 15621_u32 + ERROR_INSTALL_PACKAGE_DOWNGRADE = 15622_u32 + ERROR_SYSTEM_NEEDS_REMEDIATION = 15623_u32 + ERROR_APPX_INTEGRITY_FAILURE_CLR_NGEN = 15624_u32 + ERROR_RESILIENCY_FILE_CORRUPT = 15625_u32 + ERROR_INSTALL_FIREWALL_SERVICE_NOT_RUNNING = 15626_u32 + APPMODEL_ERROR_NO_PACKAGE = 15700_u32 + APPMODEL_ERROR_PACKAGE_RUNTIME_CORRUPT = 15701_u32 + APPMODEL_ERROR_PACKAGE_IDENTITY_CORRUPT = 15702_u32 + APPMODEL_ERROR_NO_APPLICATION = 15703_u32 + ERROR_STATE_LOAD_STORE_FAILED = 15800_u32 + ERROR_STATE_GET_VERSION_FAILED = 15801_u32 + ERROR_STATE_SET_VERSION_FAILED = 15802_u32 + ERROR_STATE_STRUCTURED_RESET_FAILED = 15803_u32 + ERROR_STATE_OPEN_CONTAINER_FAILED = 15804_u32 + ERROR_STATE_CREATE_CONTAINER_FAILED = 15805_u32 + ERROR_STATE_DELETE_CONTAINER_FAILED = 15806_u32 + ERROR_STATE_READ_SETTING_FAILED = 15807_u32 + ERROR_STATE_WRITE_SETTING_FAILED = 15808_u32 + ERROR_STATE_DELETE_SETTING_FAILED = 15809_u32 + ERROR_STATE_QUERY_SETTING_FAILED = 15810_u32 + ERROR_STATE_READ_COMPOSITE_SETTING_FAILED = 15811_u32 + ERROR_STATE_WRITE_COMPOSITE_SETTING_FAILED = 15812_u32 + ERROR_STATE_ENUMERATE_CONTAINER_FAILED = 15813_u32 + ERROR_STATE_ENUMERATE_SETTINGS_FAILED = 15814_u32 + ERROR_STATE_COMPOSITE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED = 15815_u32 + ERROR_STATE_SETTING_VALUE_SIZE_LIMIT_EXCEEDED = 15816_u32 + ERROR_STATE_SETTING_NAME_SIZE_LIMIT_EXCEEDED = 15817_u32 + ERROR_STATE_CONTAINER_NAME_SIZE_LIMIT_EXCEEDED = 15818_u32 + ERROR_API_UNAVAILABLE = 15841_u32 +end