!package.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    Copyright © 2021, 2024, 2026 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package platform.dependent.mswindows.services;

import avt.io.*;
import avt.io.extension.*;
import avt.lang.array.*;
import platform.dependent.*;
import platform.dependent.mswindows.kernel.*;
import platform.independent.filesystem.*;
import platform.independent.osservices.*;
import platform.independent.util.*;

package class CriticalSection(Object, Mutex)
{
    private final long fldPointer;
    private final platform.dependent.mswindows.kernel.CriticalSection fldInstance;

    public () {
        platform.dependent.mswindows.kernel.CriticalSection instance = new platform.dependent.mswindows.kernel.CriticalSection();
        fldPointer = instance.getPointer();
        fldInstance = instance;
    }

    public void lock() { Kernel.enterCriticalSection(fldPointer); }

    public void unlock() { Kernel.leaveCriticalSection(fldPointer); }

    public boolean isHold() { return fldInstance.owningThread != 0; }

    protected void afterConstruction() { Kernel.initializeCriticalSection(fldPointer); }

    protected void beforeDestruction() { Kernel.deleteCriticalSection(fldPointer); }
}

package class Monitor(CriticalSection, Mutex, Waitable, platform.dependent.Monitor)
{
    private static final long ENTRY_STATE_OWNEDBY = 0x00794264656e774fL;
    private static final long ENTRY_STATE_BLOCKED = 0x0064656b636f6c42L;
    private static final long ENTRY_STATE_WAITING = 0x00676e6974696157L;

    private long fldNotifies;
    private long4 fldOwnedBy;
    private long4[] fldEntries;

    /* схема хранения данных: new long4 { state, threadId, lockCount, interrupted } */

    public () {  }

    public void lock() {
        boolean isBlocked = false;
        long currentId = Kernel.getCurrentThreadId();
        super.lock();
        try
        {
            long4 entry = fldOwnedBy;
            if(entry == 0)
            {
                fldOwnedBy = new long4 { ENTRY_STATE_OWNEDBY, currentId, 1, 0 };
            } else if(entry[1] == currentId)
            {
                fldOwnedBy = entry + new byte4 { 0, 0, 1, 0 };
            } else
            {
                appendEntry(new long4 { ENTRY_STATE_BLOCKED, currentId, 1, 0 });
                isBlocked = true;
            }
        } finally
        {
            super.unlock();
        }
        if(isBlocked) ThreadEvent.get(currentId).waitSignalled(0, 0);
    }

    public void unlock() {
        boolean isNotOwnedBy = false;
        long currentId = Kernel.getCurrentThreadId();
        super.lock();
        try
        {
            long4 entry = fldOwnedBy;
            if(entry == 0 || entry[1] != currentId)
            {
                isNotOwnedBy = true;
            } else if((fldOwnedBy = entry - new byte4 { 0, 0, 1, 0 })[2] == 0)
            {
                extractEntry();
            }
        } finally
        {
            super.unlock();
        }
        if(isNotOwnedBy)
        {
            throw new IllegalMonitorStateException(avt.lang.package.getResourceString("illegal-state.monitor"));
        }
    }

    public boolean isHold() { return fldOwnedBy != 0; }

    public void interruptio(long threadId) {
        super.lock();
        try
        {
            int index = getEntryIndexByThreadId(threadId);
            if(index >= 0)
            {
                long4[] entries = fldEntries;
                long4 entry = entries[index];
                if(entry[0] == ENTRY_STATE_WAITING)
                {
                    entries[index] = entry | -new byte4 { 0, 0, 0, 1 };
                    if(fldOwnedBy == 0) extractEntry();
                }
            }
        } finally
        {
            super.unlock();
        }
    }

    public void notify(boolean isAll, long threadId) {
        boolean isNotOwnedBy = false;
        long currentId = Kernel.getCurrentThreadId();
        super.lock();
        try
        {
            long4 entry = fldOwnedBy;
            if(entry == 0 || entry[1] != currentId)
            {
                isNotOwnedBy = true;
            } else if(isAll)
            {
                for(long4[] entries = fldEntries, int index = entries == null ? 0 : entries.length; index-- > 0; )
                {
                    entries[index] = Long4.setElement(entries[index], 0, ENTRY_STATE_BLOCKED);
                }
            } else
            {
                int index = -1;
                if(threadId == 0 || (index = getEntryIndexByThreadId(threadId)) < 0) index = getEntryIndexByState(ENTRY_STATE_WAITING);
                long4[] entries = fldEntries;
                if(index < 0 || (entry = entries[index])[0] != ENTRY_STATE_WAITING)
                {
                    fldNotifies++;
                } else
                {
                    entries[index] = Long4.setElement(entry, 0, ENTRY_STATE_BLOCKED);
                }
            }
        } finally
        {
            super.unlock();
        }
        if(isNotOwnedBy)
        {
            throw new IllegalMonitorStateException(avt.lang.package.getResourceString("illegal-state.monitor"));
        }
    }

    public void wait(int timeInMillis, InterruptioHandler handler) throws InterruptedException { wait((long) timeInMillis, handler); }

    public void wait(long timeInMillis, InterruptioHandler handler) throws InterruptedException {
        boolean isWaiting = false;
        boolean isNotOwnedBy = false;
        boolean isInterrupted = false;
        long currentId = Kernel.getCurrentThreadId();
        super.lock();
        try
        {
            long4 entry = fldOwnedBy;
            if(entry == 0 || entry[1] != currentId)
            {
                isNotOwnedBy = true;
            } else
            {
                long notifies = fldNotifies;
                if(notifies == 0)
                {
                    extractEntry();
                    appendEntry(Long4.setElement(entry, 0, ENTRY_STATE_WAITING));
                    isWaiting = true;
                } else if(handler != null && handler.isInterrupted())
                {
                    isInterrupted = true;
                } else
                {
                    fldNotifies = notifies - 1;
                }
            }
        } finally
        {
            super.unlock();
        }
        if(isNotOwnedBy)
        {
            throw new IllegalMonitorStateException(avt.lang.package.getResourceString("illegal-state.monitor"));
        }
        if(isWaiting)
        {
            ThreadEvent event = ThreadEvent.get(currentId);
            if(handler != null) handler.setWaitable(this);
            event.waitSignalled(timeInMillis, 0);
            do
            {
                super.lock();
                try
                {
                    long4 entry = fldOwnedBy;
                    if((isNotOwnedBy = entry == 0) || entry[1] == currentId)
                    {
                        if(isNotOwnedBy)
                        {
                            extractEntry(currentId);
                            entry = fldOwnedBy;
                        }
                        fldOwnedBy = entry & -new byte4 { 1, 1, 1, 0 };
                        isInterrupted = entry[3] != 0;
                        isWaiting = false;
                    } else
                    {
                        int index = getEntryIndexByThreadId(currentId);
                        long4[] entries = fldEntries;
                        entries[index] = Long4.setElement(entries[index], 0, ENTRY_STATE_BLOCKED);
                    }
                } finally
                {
                    super.unlock();
                }
                if(!isWaiting) break;
                event.waitSignalled(0, 0);
            } while(true);
            if(handler != null) handler.setWaitable(null);
        }
        if(isInterrupted)
        {
            throw new InterruptedException(avt.lang.package.getResourceString("interrupted.wait"));
        }
    }

    private void resume(long4 entry, boolean needSignal) {
        fldOwnedBy = Long4.setElement(entry, 0, ENTRY_STATE_OWNEDBY);
        if(needSignal) ThreadEvent.get(entry[1]).setSignalled();
    }

    private void extractEntry() {
        long4[] entries = fldEntries;
        if(entries == null)
        {
            fldOwnedBy = 0;
            return;
        }
        int length = entries.length;
        long4 entry;
        int index;
        label0:
        {
            for(index = 0; index < length; index++) if((entry = entries[index])[3] != 0) break label0;
            for(index = 0; index < length; index++) if((entry = entries[index])[0] == ENTRY_STATE_BLOCKED) break label0;
            fldOwnedBy = 0;
            return;
        }
        Array.copy(entries, index + 1, entries, index, --length - index);
        entries[length] = 0;
        entries.length = length;
        resume(entry, true);
    }

    private void extractEntry(long threadId) {
        long4[] entries = fldEntries;
        if(entries == null)
        {
            fldOwnedBy = 0;
            return;
        }
        int length = entries.length;
        long4 entry;
        int index;
        label0:
        {
            for(index = 0; index < length; index++) if((entry = entries[index])[1] == threadId) break label0;
            fldOwnedBy = 0;
            return;
        }
        Array.copy(entries, index + 1, entries, index, --length - index);
        entries[length] = 0;
        entries.length = length;
        resume(entry, false);
    }

    private void appendEntry(long4 entry) {
        long4[] entries = fldEntries;
        if(entries == null)
        {
            (fldEntries = entries = new long4[0x0f]).length = 1;
            entries[0] = entry;
            return;
        }
        int length = entries.length;
        if(length == entries.capacity) Array.copy(entries, 0, fldEntries = entries = new long4[length << 1 | 1], 0, length);
        entries.length = length + 1;
        entries[length] = entry;
    }

    private int getEntryIndexByState(long state) {
        long4[] entries = fldEntries;
        if(entries == null) return -1;
        int length = entries.length;
        int index;
        label0:
        {
            long4 entry;
            for(index = 0; index < length; index++) if((entry = entries[index])[0] == state && entry[3] != 0) break label0;
            for(index = 0; index < length; index++) if(entries[index][0] == state) break label0;
            return -1;
        }
        return index;
    }

    private int getEntryIndexByThreadId(long threadId) {
        long4[] entries = fldEntries;
        if(entries == null) return -1;
        int length = entries.length;
        int index;
        label0:
        {
            for(index = 0; index < length; index++) if(entries[index][1] == threadId) break label0;
            return -1;
        }
        return index;
    }
}

package class FileSystemDescriptor(FileSystemRoot)
{
    private char[] fldCanonicalPath;
    private FileSystem fldFileSystem;

    public (String rootPath, String currentDirectory): super(rootPath) {
        int length = rootPath.length;
        char[] canonical = new char[length + 1];
        rootPath.getChars(1, length, canonical, 0);
        canonical[length - 1] = '\\';
        fldCanonicalPath = canonical;
        fldFileSystem = new VolumeFileSystem(PlatformServices.getInstance().toInternalPath(rootPath), currentDirectory.replaceAll('/', '\\'));
    }

    public FileSystem fileSystem { read = fldFileSystem }

    public String name { read = getName }

    private String getName() {
        char[] result = new char[Kernel.MAX_PATH + 1];
        int length = Kernel.getVolumeName(fldCanonicalPath.getPointer(), result.getPointer(), Kernel.MAX_PATH + 1);
        return length < 0 ? null : new String(result, 0, length);
    }
}

package class Extensions(Object, Extendable)
{
    protected Extension[] fldExtensions;

    protected () {  }

    public Extension[] getExtensions() {
        Extension[] exts = fldExtensions;
        int length = exts == null ? 0 : exts.length;
        Extension[] result = new Extension[length];
        Array.copy(exts, 0, result, 0, length);
        return result;
    }

    public Extension getExtension(Class type) {
        Extension[] exts = fldExtensions;
        if(exts != null) for(int length = exts.length, int index = 0; index < length; index++)
        {
            Extension ext = exts[index];
            if(ext != null && (type == null || type.isAssignableFrom(ext.getClass()))) return ext;
        }
        return null;
    }
}

package class HandleInputStream(Extensions, Closeable, ByteReader)
{
    protected long fldHandle;

    public (long handle) { fldHandle = handle; }

    public void close() throws IOException {  }

    public int read() throws IOException {
        long handle = handleNeeded();
        int2 result = Kernel.readFile(handle, 0);
        if(result[0] == 0)
        {
            throw new IOException(avt.io.package.getResourceString("io.read"));
        }
        return result[1];
    }

    public int read(byte[] dst, int offset, int length) throws IOException {
        long handle = handleNeeded();
        if(dst == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "dst" }));
        }
        Array.checkBounds(dst, offset, length);
        if(length <= 0) return 0;
        int2 result = Kernel.readFile(handle, dst.getPointer() + offset, length, 0);
        if(result[0] == 0)
        {
            throw new IOException(avt.io.package.getResourceString("io.read"));
        }
        int readed = result[1];
        return readed <= 0 ? -1 : readed;
    }

    public long skip(long bytesQuantity) throws IOException {
        long handle = handleNeeded();
        if(bytesQuantity <= 0) return 0;
        long skiped = 0;
        do
        {
            if(Kernel.readFile(handle, 0)[0] == 0)
            {
                if(skiped > 0) break;
                throw new IOException(avt.io.package.getResourceString("io"));
            }
            skiped++;
        } while(--bytesQuantity > 0);
        return skiped;
    }

    protected final long handleNeeded() throws ClosedFileException {
        long handle = fldHandle;
        if(handle == 0)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        return handle;
    }

    package final long handle { read = fldHandle }
}

package class HandleOutputStream(Extensions, Closeable, ByteWriter)
{
    protected long fldHandle;
    protected char[] fldRootPath;

    public (long handle, char[] rootPath) {
        fldHandle = handle;
        fldRootPath = rootPath;
    }

    public void close() throws IOException {  }

    public void write(int byteData) throws IOException {
        long handle = handleNeeded();
        int2 result = Kernel.writeFile(handle, byteData, 0);
        if(result[0] == 0)
        {
            if(Kernel.getLastError() == Kernel.ERROR_DISK_FULL)
            {
                throw new FileSystemFullException(String.format(platform.independent.osservices.package.getResourceString("file-system.full"), new Object[] { fldRootPath }));
            }
            throw new IOException(avt.io.package.getResourceString("io.write"));
        }
        if(result[1] < 1)
        {
            throw new FileSystemFullException(String.format(platform.independent.osservices.package.getResourceString("file-system.full"), new Object[] { fldRootPath }));
        }
    }

    public void write(byte[] src, int offset, int length) throws IOException {
        long handle = handleNeeded();
        if(src == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
        }
        Array.checkBounds(src, offset, length);
        if(length <= 0) return;
        int2 result = Kernel.writeFile(handle, src.getPointer() + offset, length, 0);
        if(result[0] == 0)
        {
            if(Kernel.getLastError() == Kernel.ERROR_DISK_FULL)
            {
                throw new FileSystemFullException(String.format(platform.independent.osservices.package.getResourceString("file-system.full"), new Object[] { fldRootPath }));
            }
            throw new IOException(avt.io.package.getResourceString("io.write"));
        }
        if(result[1] < length)
        {
            throw new FileSystemFullException(String.format(platform.independent.osservices.package.getResourceString("file-system.full"), new Object[] { fldRootPath }));
        }
    }

    public void flush() throws IOException {  }

    protected final long handleNeeded() throws ClosedFileException {
        long handle = fldHandle;
        if(handle == 0)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        return handle;
    }

    package final long handle { read = fldHandle }
}

package abstract class HandleBidirectStream(Extensions, Closeable, ByteStream)
{
    protected long fldHandleForRead;
    protected long fldHandleForWrite;
    protected HandleInputStream fldReader;
    protected HandleOutputStream fldWriter;

    public (long handleForRead, long handleForWrite) {
        fldHandleForRead = handleForRead;
        fldHandleForWrite = handleForWrite;
    }

    public void close() throws IOException {
        long handleForRead = fldHandleForRead;
        long handleForWrite = fldHandleForWrite;
        {
            fldHandleForRead = 0;
            fldHandleForWrite = 0;
            fldReader.fldHandle = 0;
            fldWriter.fldHandle = 0;
        }
        if((handleForRead | handleForWrite) != 0 && (!Kernel.closeHandle(handleForRead) || handleForRead != handleForWrite && !Kernel.closeHandle(handleForWrite)))
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
    }

    public ByteReader reader { read = fldReader }

    public ByteWriter writer { read = fldWriter }

    protected void beforeDestruction() {
        long handleForRead = fldHandleForRead;
        long handleForWrite = fldHandleForWrite;
        if((handleForRead | handleForWrite) != 0)
        {
            Kernel.closeHandle(handleForRead);
            if(handleForRead != handleForWrite) Kernel.closeHandle(handleForWrite);
        }
    }
}

package final class PipeStream(HandleBidirectStream)
{
    public (long handleForRead, long handleForWrite): super(handleForRead, handleForWrite) {
        fldReader = new HandleInputStream(handleForRead);
        fldWriter = new HandleOutputStream(handleForWrite, null);
    }
}

package final class EnvironmentTable(Object, platform.dependent.EnvironmentTable, Measureable, ObjectArray)
{
    private final OrderedTable fldVariables;

    public () { fldVariables = new OrderedTable(); }

    public boolean equals(Object anot) {
        OrderedTable tvars = fldVariables;
        OrderedTable avars = ((EnvironmentTable) anot).fldVariables;
        int length = tvars.length;
        if(length != avars.length) return false;
        for(int tindex = length; tindex-- > 0; )
        {
            String aname;
            String tname = (String) tvars[tindex];
            String avalue = (String) avars[tname];
            String tvalue = (String) tvars[tname];
            if(avalue != null)
            {
                if(avalue.equalsIgnoreCase(tvalue)) continue;
                return false;
            }
            label0:
            {
                for(int aindex = length; aindex-- > 0; ) if((aname = (String) avars[aindex]).equalsIgnoreCase(tname)) break label0;
                return false;
            }
            if(!((String) avars[aname]).equalsIgnoreCase(tvalue)) return false;
        }
        return true;
    }

    public void clear() { fldVariables.clear(); }

    public boolean isCaseSensitive() { return false; }

    public boolean contains(String envName) {
        OrderedTable vars = fldVariables;
        if(vars.contains(envName)) return true;
        for(int index = vars.length; index-- > 0; ) if(((String) vars[index]).equalsIgnoreCase(envName)) return true;
        return false;
    }

    public int length { read = fldVariables.length }

    public void operator []=(String envName, String newValue) {
        OrderedTable vars = fldVariables;
        if(!vars.contains(envName)) for(int index = vars.length; index-- > 0; )
        {
            String name = (String) vars[index];
            if(name.equalsIgnoreCase(envName))
            {
                vars[name] = newValue;
                return;
            }
        }
        vars[envName] = newValue;
    }

    public String operator [](String envName) {
        OrderedTable vars = fldVariables;
        String value = (String) vars[envName];
        if(value != null) return value;
        for(int index = vars.length; index-- > 0; )
        {
            String name = (String) vars[index];
            if(name.equalsIgnoreCase(envName)) return (String) vars[name];
        }
        return null;
    }

    public String operator [](int index) { return (String) fldVariables[index]; }
}

package final class CurrentProcess(Process)
{
    private static String[] parseCommandLine() {
        try
        {
            final char SPACE = '\u0020';
            final char QUOTE = '\u0022';
            long2 cmdDs = Kernel.getCommandLine();
            long cmdPtr = cmdDs[0];
            int cmdLen = (int) cmdDs[1];
            char[] cmdChars = (char[]) char[].class.newArrayAt(cmdPtr, cmdLen);
            int length = 0;
            boolean quoted = false;
            char prev = SPACE;
            for(int index = 0; index < cmdLen; index++)
            {
                char curr = cmdChars[index];
                if(curr == QUOTE)
                {
                    quoted = !quoted;
                } else
                {
                    if(!quoted && prev != SPACE && curr == SPACE) length++;
                }
                if(cmdLen - index == 1 && curr != SPACE) length++;
                prev = curr;
            }
            String[] arguments = new String[length];
            char[] argChars = new char[cmdLen];
            int argLength = 0;
            length = 0;
            quoted = false;
            prev = SPACE;
            for(int index = 0; index < cmdLen; index++)
            {
                char curr = cmdChars[index];
                if(curr == QUOTE)
                {
                    quoted = !quoted;
                } else if(quoted || curr != SPACE)
                {
                    argChars[argLength++] = curr;
                } else if(prev != SPACE)
                {
                    arguments[length++] = new String(argChars, 0, argLength);
                    argLength = 0;
                }
                if(cmdLen - index == 1 && curr != SPACE)
                {
                    arguments[length++] = new String(argChars, 0, argLength);
                }
                prev = curr;
            }
            argChars = new char[Kernel.MAX_PATH + 1];
            argLength = Kernel.getModuleFileName(0, argChars.getPointer(), Kernel.MAX_PATH + 1);
            if(length <= 0) return new String[] { new String(argChars, 0, argLength) };
            arguments[0] = new String(argChars, 0, argLength);
            return arguments;
        } catch(Exception exception)
        {
            return null;
        }
    }

    private final CriticalSection fldWorkingDirectoryOperation;

    public () {
        long stdIn = Kernel.getStdHandle(Kernel.STD_INPUT);
        long stdOut = Kernel.getStdHandle(Kernel.STD_OUTPUT);
        long stdErr = Kernel.getStdHandle(Kernel.STD_ERROR);
        String[] commandLine = parseCommandLine();
        if(stdIn != Kernel.INVALID_HANDLE_VALUE) super.setStandardInput(new HandleInputStream(stdIn));
        if(stdOut != Kernel.INVALID_HANDLE_VALUE) super.setStandardOutput(new HandleOutputStream(stdOut, null));
        if(stdErr != Kernel.INVALID_HANDLE_VALUE) super.setStandardError(new HandleOutputStream(stdErr, null));
        if(commandLine != null) commandLine.finalize();
        fldCommandLine = commandLine;
        fldWorkingDirectoryOperation = new CriticalSection();
    }

    public void start() {
        throw new IllegalProcessStateException(platform.independent.osservices.package.getResourceString("illegal-state.process.already-started"));
    }

    public boolean isTerminated() { return false; }

    public int getExitCode() { return STILL_ACTIVE; }

    protected void setPriority(int newPriority) {
        if(newPriority < MIN_PRIORITY) newPriority = MIN_PRIORITY;
        if(newPriority > MAX_PRIORITY) newPriority = MAX_PRIORITY;
        switch(newPriority)
        {
            case MIN_PRIORITY:
            {
                newPriority = Kernel.IDLE_PRIORITY_CLASS;
                break;
            }
            case LOW_PRIORITY - 1:
            case LOW_PRIORITY:
            {
                newPriority = Kernel.BELOW_NORMAL_PRIORITY_CLASS;
                break;
            }
            case NORM_PRIORITY - 1:
            case NORM_PRIORITY:
            case NORM_PRIORITY + 1:
            {
                newPriority = Kernel.NORMAL_PRIORITY_CLASS;
                break;
            }
            case HIGH_PRIORITY:
            case HIGH_PRIORITY + 1:
            {
                newPriority = Kernel.ABOVE_NORMAL_PRIORITY_CLASS;
                break;
            }
            case MAX_PRIORITY:
            {
                newPriority = Kernel.HIGH_PRIORITY_CLASS;
                break;
            }
        }
        Kernel.setPriorityClass(Kernel.getCurrentProcess(), newPriority);
    }

    protected void setCommandLine(String[] newCommandLine) {
        throw new ReadOnlyPropertyException(String.format(avt.lang.package.getResourceString("unsupported-operation.property.read-only"), new Object[] { "commandLine", class.canonicalName }));
    }

    protected void setWorkingDirectory(String newWorkingDirectory) {
        if(newWorkingDirectory == null)
        {
            throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "workingDirectory" }));
        }
        int length = (newWorkingDirectory = PlatformServices.getInstance().toInternalPath(newWorkingDirectory)).length;
        char[] internalFullPath = new char[length + 1];
        newWorkingDirectory.getChars(0, length, internalFullPath, 0);
        CriticalSection operation = fldWorkingDirectoryOperation;
        operation.lock();
        try
        {
            if(!Kernel.setCurrentDirectory(internalFullPath.getPointer()))
            {
                throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "workingDirectory" }));
            }
        } finally
        {
            operation.unlock();
        }
    }

    protected void setStandardInput(ByteReader newStandardInput) {
        throw new ReadOnlyPropertyException(String.format(avt.lang.package.getResourceString("unsupported-operation.property.read-only"), new Object[] { "standardInput", class.canonicalName }));
    }

    protected void setStandardOutput(ByteWriter newStandardOutput) {
        throw new ReadOnlyPropertyException(String.format(avt.lang.package.getResourceString("unsupported-operation.property.read-only"), new Object[] { "standardOutput", class.canonicalName }));
    }

    protected void setStandardError(ByteWriter newStandardError) {
        throw new ReadOnlyPropertyException(String.format(avt.lang.package.getResourceString("unsupported-operation.property.read-only"), new Object[] { "standardError", class.canonicalName }));
    }

    protected int getPriority() {
        switch(Kernel.getPriorityClass(Kernel.getCurrentProcess()))
        {
            case Kernel.IDLE_PRIORITY_CLASS        : return MIN_PRIORITY;
            case Kernel.BELOW_NORMAL_PRIORITY_CLASS: return LOW_PRIORITY;
            case Kernel.NORMAL_PRIORITY_CLASS      : return NORM_PRIORITY;
            case Kernel.ABOVE_NORMAL_PRIORITY_CLASS: return HIGH_PRIORITY;
            case Kernel.HIGH_PRIORITY_CLASS        : return MAX_PRIORITY;
            default                                : return 0;
        }
    }

    protected String getWorkingDirectory() {
        int length;
        char[] internalFullPath;
        CriticalSection operation = fldWorkingDirectoryOperation;
        operation.lock();
        try
        {
            length = Kernel.getCurrentDirectory(0, 0);
            internalFullPath = new char[length];
            Kernel.getCurrentDirectory(length--, internalFullPath.getPointer());
        } finally
        {
            operation.unlock();
        }
        if(length > 0 && internalFullPath[length - 1] != '\\') internalFullPath[length++] = '\\';
        return PlatformServices.getInstance().toObjectPath(new String(internalFullPath, 0, length));
    }

    protected Environment createEnvironment() { return new CurrentEnvironment(); }
}

final class VolumeFileSystem(Object, FileSystem, RequiredAttributes, VolumeRequiredAttributes)
{
    private static final int AT_OBJECT    = 0;
    private static final int AT_FILE      = 1;
    private static final int AT_DIRECTORY = 2;

    private static final int OBJECT_NAME_MAXIMUM_LENGTH = 255;

    private static final String[] reserved = new String[] {
        "con", "prn", "aux", "nul",
        "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9", "com\u00b9", "com\u00b2", "com\u00b3",
        "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "lpt\u00b9", "lpt\u00b2", "lpt\u00b3"
    };

    private static boolean isComponentReserved(String component) {
        int length = component.length;
        if(length > 0) switch(component[length - 1])
        {
            case ' ': return true;
            case '.': return length > 1 && (length > 2 || component[0] != '.');
        }
        int index = component.indexOf('.');
        String name = index < 0 ? component : component.substring(0, index);
        if((length = name.length) >= 3 && length <= 4) for(length = reserved.length, index = 0; index < length; index++) if(reserved[index].equalsIgnoreCase(name)) return true;
        return false;
    }

    private static char[] toZeroTerminatedArray(String str) {
        int length = str.length;
        char[] result = new char[length + 1];
        str.getChars(0, length, result, 0);
        return result;
    }

    private boolean fldCurrentUnreliableBlock;
    private long fldCurrentHandle;
    private char[] fldCanonicalRootPath; /* C:\ */
    private String fldInternalRootPath; /* C: */
    private String fldCurrentDirectory; /* \Windows\ */
    private CriticalSection fldCurrentOperation;

    public (String rootPath, String currentDirectory) {
        int length = rootPath.length;
        char[] canonical = new char[length + 2];
        rootPath.getChars(0, length, canonical, 0);
        canonical[length++] = '\\';
        canonical.length = length;
        fldCurrentUnreliableBlock = true;
        fldCurrentHandle = Kernel.INVALID_HANDLE_VALUE;
        fldCanonicalRootPath = canonical;
        fldInternalRootPath = rootPath;
        fldCurrentDirectory = currentDirectory;
        fldCurrentOperation = new CriticalSection();
        tryMakeCurrentReliableBlock();
    }

    public void changeCurrentDirectory(String directoryPath) throws DirectoryNotFoundException, IOException {
        String internalFullPath;
        if(directoryPath == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "directoryPath" }));
        }
        if(directoryPath.length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "directoryPath" }));
        }
        if(!isObjectNameValid(directoryPath))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "directoryPath" }));
        }
        if((internalFullPath = toVolumeFullPath(directoryPath)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "directoryPath" }));
        }
        internalFullPath = makeInternalFullPathAndCheckExist(internalFullPath, AT_DIRECTORY);
        if(internalFullPath.endsWith("\\")) internalFullPath = internalFullPath.substring(0, internalFullPath.length - 1);
        int rootPathLength = fldInternalRootPath.length;
        String newCurrentDirectory = internalFullPath.substring(rootPathLength) + '\\';
        CriticalSection operation = fldCurrentOperation;
        operation.lock();
        try
        {
            if(!fldCurrentDirectory.equalsIgnoreCase(newCurrentDirectory))
            {
                boolean unreliableBlock = false;
                long newHandle = Kernel.INVALID_HANDLE_VALUE;
                if(internalFullPath.length > rootPathLength)
                {
                    unreliableBlock = true;
                    char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
                    long zerotermFullPathPtr = zerotermFullPath.getPointer();
                    newHandle = Kernel.createFile(
                        zerotermFullPathPtr,
                        /* Kernel.DELETE */ 0x00010000,
                        Kernel.FILE_SHARE_READ | Kernel.FILE_SHARE_WRITE,
                        0,
                        Kernel.OPEN_EXISTING,
                        Kernel.FILE_ATTRIBUTE_NORMAL | Kernel.FILE_FLAG_BACKUP_SEMANTICS,
                        0
                    );
                    if(newHandle != Kernel.INVALID_HANDLE_VALUE)
                    {
                        unreliableBlock = false;
                    } else
                    {
                        newHandle = Kernel.createFile(
                            zerotermFullPathPtr,
                            0,
                            0,
                            0,
                            Kernel.OPEN_EXISTING,
                            Kernel.FILE_ATTRIBUTE_NORMAL | Kernel.FILE_FLAG_BACKUP_SEMANTICS,
                            0
                        );
                    }
                    label0:
                    {
                        if(newHandle != Kernel.INVALID_HANDLE_VALUE)
                        {
                            if((Kernel.getFileAttributes(zerotermFullPathPtr) & Kernel.FILE_ATTRIBUTE_DIRECTORY) != 0) break label0;
                            Kernel.closeHandle(newHandle);
                        } else switch(Kernel.getLastError())
                        {
                            case Kernel.ERROR_FILE_NOT_FOUND:
                            case Kernel.ERROR_PATH_NOT_FOUND: break;
                            case Kernel.ERROR_NOT_READY:
                            {
                                throw new FileSystemNotAttachedException(
                                    String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath })
                                );
                            }
                            default:
                            {
                                throw new IOException(avt.io.package.getResourceString("io"));
                            }
                        }
                        throw new DirectoryNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.directory")) { directoryName = internalFullPath };
                    }
                }
                long oldHandle = fldCurrentHandle;
                if(oldHandle != Kernel.INVALID_HANDLE_VALUE) Kernel.closeHandle(oldHandle);
                fldCurrentUnreliableBlock = unreliableBlock;
                fldCurrentDirectory = newCurrentDirectory;
                fldCurrentHandle = newHandle;
            }
        } finally
        {
            operation.unlock();
        }
    }

    public void readAttributes(String objectName, ObjectAttributes objectAttr) throws ObjectNotFoundException, ObjectReadAttributesException, IOException {
        int standardNameLength;
        String internalFullPath;
        if(objectName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectName" }));
        }
        if((standardNameLength = objectName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectName" }));
        }
        if(standardNameLength <= 0 || objectName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "objectName" }));
        }
        if(!isObjectNameValid(objectName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "objectName" }));
        }
        if((internalFullPath = toVolumeFullPath(objectName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectName" }));
        }
        internalFullPath = makeInternalFullPathAndCheckExist(internalFullPath, AT_OBJECT);
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        long zerotermFullPathPtr = zerotermFullPath.getPointer();
        long objHandle = Kernel.createFile(
            zerotermFullPathPtr,
            Kernel.GENERIC_READ,
            Kernel.FILE_SHARE_READ | Kernel.FILE_SHARE_WRITE | Kernel.FILE_SHARE_DELETE,
            0,
            Kernel.OPEN_EXISTING,
            Kernel.FILE_ATTRIBUTE_NORMAL | Kernel.FILE_FLAG_BACKUP_SEMANTICS,
            0
        );
        if(objHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
            {
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) { objectName = internalFullPath };
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        FileTime internalCreationTime = new FileTime();
        FileTime internalLastWriteTime = new FileTime();
        FileTime internalLastAccessTime = new FileTime();
        int internalAttributes = Kernel.getFileAttributes(zerotermFullPathPtr);
        boolean objReadTime = Kernel.getFileTime(objHandle, internalCreationTime.getPointer(), internalLastAccessTime.getPointer(), internalLastWriteTime.getPointer());
        if(!Kernel.closeHandle(objHandle))
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        if(internalAttributes == Kernel.INVALID_FILE_ATTRIBUTES || !objReadTime)
        {
            throw new ObjectReadAttributesException(platform.independent.filesystem.package.getResourceString("object.read-attributes")) { objectName = internalFullPath };
        }
        if(objectAttr == null) return;
        if(objectAttr.isSupportedAttributeId(B_DIRECTORY)) objectAttr.setBooleanAttribute(B_DIRECTORY, (internalAttributes & Kernel.FILE_ATTRIBUTE_DIRECTORY) != 0);
        if(objectAttr.isSupportedAttributeId(B_READ_ONLY)) objectAttr.setBooleanAttribute(B_READ_ONLY, (internalAttributes & Kernel.FILE_ATTRIBUTE_READONLY) != 0);
        if(objectAttr.isSupportedAttributeId(B_ARCHIVE)) objectAttr.setBooleanAttribute(B_ARCHIVE, (internalAttributes & Kernel.FILE_ATTRIBUTE_ARCHIVE) != 0);
        if(objectAttr.isSupportedAttributeId(B_HIDDEN)) objectAttr.setBooleanAttribute(B_HIDDEN, (internalAttributes & Kernel.FILE_ATTRIBUTE_HIDDEN) != 0);
        if(objectAttr.isSupportedAttributeId(B_SYSTEM)) objectAttr.setBooleanAttribute(B_SYSTEM, (internalAttributes & Kernel.FILE_ATTRIBUTE_SYSTEM) != 0);
        if(objectAttr.isSupportedAttributeId(L_CREATION_TIME)) objectAttr.setLongAttribute(L_CREATION_TIME, toObjectTime(internalCreationTime.ftFileTime));
        if(objectAttr.isSupportedAttributeId(L_LAST_WRITE_TIME)) objectAttr.setLongAttribute(L_LAST_WRITE_TIME, toObjectTime(internalLastWriteTime.ftFileTime));
        if(objectAttr.isSupportedAttributeId(L_LAST_ACCESS_TIME)) objectAttr.setLongAttribute(L_LAST_ACCESS_TIME, toObjectTime(internalLastAccessTime.ftFileTime));
    }

    public void writeAttributes(String objectName, ObjectAttributes objectAttr) throws ReadOnlyFileSystemException, ObjectNotFoundException, ObjectWriteAttributesException, IOException {
        int standardNameLength;
        String internalFullPath;
        if(objectName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectName" }));
        }
        if((standardNameLength = objectName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectName" }));
        }
        if(standardNameLength <= 0 || objectName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "objectName" }));
        }
        if(!isObjectNameValid(objectName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "objectName" }));
        }
        if((internalFullPath = toVolumeFullPath(objectName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectName" }));
        }
        if(objectAttr == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectAttr" }));
        }
        int internalAttributes = 0;
        FileTime internalCreationTime = new FileTime();
        FileTime internalLastWriteTime = new FileTime();
        FileTime internalLastAccessTime = new FileTime();
        if(objectAttr.isSupportedAttributeId(B_DIRECTORY) && objectAttr.getBooleanAttribute(B_DIRECTORY)) internalAttributes |= Kernel.FILE_ATTRIBUTE_DIRECTORY;
        if(objectAttr.isSupportedAttributeId(B_READ_ONLY) && objectAttr.getBooleanAttribute(B_READ_ONLY)) internalAttributes |= Kernel.FILE_ATTRIBUTE_READONLY;
        if(objectAttr.isSupportedAttributeId(B_ARCHIVE) && objectAttr.getBooleanAttribute(B_ARCHIVE)) internalAttributes |= Kernel.FILE_ATTRIBUTE_ARCHIVE;
        if(objectAttr.isSupportedAttributeId(B_HIDDEN) && objectAttr.getBooleanAttribute(B_HIDDEN)) internalAttributes |= Kernel.FILE_ATTRIBUTE_HIDDEN;
        if(objectAttr.isSupportedAttributeId(B_SYSTEM) && objectAttr.getBooleanAttribute(B_SYSTEM)) internalAttributes |= Kernel.FILE_ATTRIBUTE_SYSTEM;
        if(objectAttr.isSupportedAttributeId(L_CREATION_TIME))
        {
            long time = toInternalTime(objectAttr.getLongAttribute(L_CREATION_TIME));
            internalCreationTime.ftFileTime = time < 0 ? 0 : time;
        }
        if(objectAttr.isSupportedAttributeId(L_LAST_WRITE_TIME))
        {
            long time = toInternalTime(objectAttr.getLongAttribute(L_LAST_WRITE_TIME));
            internalLastWriteTime.ftFileTime = time < 0 ? 0 : time;
        }
        if(objectAttr.isSupportedAttributeId(L_LAST_ACCESS_TIME))
        {
            long time = toInternalTime(objectAttr.getLongAttribute(L_LAST_ACCESS_TIME));
            internalLastAccessTime.ftFileTime = time < 0 ? 0 : time;
        }
        internalFullPath = makeInternalFullPathAndCheckExist(internalFullPath, AT_OBJECT);
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        long zerotermFullPathPtr = zerotermFullPath.getPointer();
        boolean objWriteAttr = Kernel.setFileAttributes(zerotermFullPathPtr, Kernel.FILE_ATTRIBUTE_NORMAL);
        long objHandle = Kernel.createFile(
            zerotermFullPathPtr,
            Kernel.GENERIC_WRITE,
            Kernel.FILE_SHARE_READ | Kernel.FILE_SHARE_WRITE | Kernel.FILE_SHARE_DELETE,
            0,
            Kernel.OPEN_EXISTING,
            Kernel.FILE_ATTRIBUTE_NORMAL | Kernel.FILE_FLAG_BACKUP_SEMANTICS,
            0
        );
        if(objHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
            {
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) { objectName = internalFullPath };
            }
            case Kernel.ERROR_WRITE_PROTECT:
            {
                throw new ReadOnlyFileSystemException(String.format(platform.independent.osservices.package.getResourceString("file-system.read-only"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        boolean objWriteTime = Kernel.setFileTime(objHandle, internalCreationTime.getPointer(), internalLastAccessTime.getPointer(), internalLastWriteTime.getPointer());
        objWriteAttr = Kernel.setFileAttributes(zerotermFullPathPtr, internalAttributes) && objWriteAttr;
        if(!Kernel.closeHandle(objHandle))
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        if(!objWriteAttr || !objWriteTime)
        {
            throw new ObjectWriteAttributesException(platform.independent.filesystem.package.getResourceString("object.write-attributes")) { objectName = internalFullPath };
        }
    }

    public void move(String objectOldName, String objectNewName) throws ReadOnlyFileSystemException, ObjectNotFoundException, MoveOperationException, IOException {
        int standardNameLength;
        String internalOldFullPath;
        String internalNewFullPath;
        if(objectOldName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectOldName" }));
        }
        if((standardNameLength = objectOldName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectOldName" }));
        }
        if(standardNameLength <= 0 || objectOldName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "objectOldName" }));
        }
        if(!isObjectNameValid(objectOldName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "objectOldName" }));
        }
        if((internalOldFullPath = toVolumeFullPath(objectOldName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectOldName" }));
        }
        if(objectNewName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectNewName" }));
        }
        if((standardNameLength = objectNewName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectNewName" }));
        }
        if(standardNameLength <= 0 || objectNewName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "objectNewName" }));
        }
        if(!isObjectNameValid(objectNewName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "objectNewName" }));
        }
        if((internalNewFullPath = toVolumeFullPath(objectNewName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectNewName" }));
        }
        tryMakeCurrentReliableBlock();
        internalOldFullPath = makeInternalFullPathAndCheckExist(internalOldFullPath, AT_OBJECT);
        internalNewFullPath = makeInternalFullPathAndCheckCreat(internalNewFullPath);
        char[] zerotermOldFullPath = toZeroTerminatedArray(internalOldFullPath);
        char[] zerotermNewFullPath = toZeroTerminatedArray(internalNewFullPath);
        if(Kernel.moveFile(zerotermOldFullPath.getPointer(), zerotermNewFullPath.getPointer())) return;
        switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_EXISTS:
            case Kernel.ERROR_ALREADY_EXISTS:
            {
                throw new MoveOperationException(platform.independent.filesystem.package.getResourceString("move-operation")) {
                    objectOldName = internalOldFullPath,
                    objectNewName = internalNewFullPath
                };
            }
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
            {
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) { objectName = internalOldFullPath };
            }
            case Kernel.ERROR_DISK_FULL:
            {
                throw new FileSystemFullException(String.format(platform.independent.osservices.package.getResourceString("file-system.full"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_WRITE_PROTECT:
            {
                throw new ReadOnlyFileSystemException(String.format(platform.independent.osservices.package.getResourceString("file-system.read-only"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
    }

    public void deleteFile(String fileName) throws ReadOnlyFileSystemException, FileNotFoundException, FileDeletionException, IOException {
        int standardNameLength;
        String internalFullPath;
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        if((standardNameLength = fileName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        if(standardNameLength <= 0 || fileName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "fileName" }));
        }
        if(!isObjectNameValid(fileName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "fileName" }));
        }
        if((internalFullPath = toVolumeFullPath(fileName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        internalFullPath = makeInternalFullPathAndCheckExist(internalFullPath, AT_FILE);
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        if(Kernel.deleteFile(zerotermFullPath.getPointer())) return;
        switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
            {
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) { fileName = internalFullPath };
            }
            case Kernel.ERROR_WRITE_PROTECT:
            {
                throw new ReadOnlyFileSystemException(String.format(platform.independent.osservices.package.getResourceString("file-system.read-only"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                if(Kernel.getLastStatus() != Kernel.STATUS_FILE_IS_A_DIRECTORY)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
            }
        }
        throw new FileDeletionException(platform.independent.filesystem.package.getResourceString("file.deletion")) { fileName = internalFullPath };
    }

    public void deleteDirectory(String directoryName) throws ReadOnlyFileSystemException, DirectoryNotFoundException, DirectoryDeletionException, IOException {
        int standardNameLength;
        String internalFullPath;
        if(directoryName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "directoryName" }));
        }
        if((standardNameLength = directoryName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "directoryName" }));
        }
        if(standardNameLength <= 0 || directoryName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "directoryName" }));
        }
        if(!isObjectNameValid(directoryName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "directoryName" }));
        }
        if((internalFullPath = toVolumeFullPath(directoryName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "directoryName" }));
        }
        tryMakeCurrentReliableBlock();
        internalFullPath = makeInternalFullPathAndCheckExist(internalFullPath, AT_DIRECTORY);
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        if(Kernel.removeDirectory(zerotermFullPath.getPointer())) return;
        switch(Kernel.getLastError())
        {
            case Kernel.ERROR_DIR_NOT_EMPTY: break;
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
            {
                throw new DirectoryNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.directory")) { directoryName = internalFullPath };
            }
            case Kernel.ERROR_WRITE_PROTECT:
            {
                throw new ReadOnlyFileSystemException(String.format(platform.independent.osservices.package.getResourceString("file-system.read-only"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                if(Kernel.getLastStatus() != Kernel.STATUS_NOT_A_DIRECTORY)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
            }
        }
        throw new DirectoryDeletionException(platform.independent.filesystem.package.getResourceString("directory.deletion")) { directoryName = internalFullPath };
    }

    public void createDirectory(String directoryName) throws ReadOnlyFileSystemException, DirectoryCreationException, IOException {
        int standardNameLength;
        String internalFullPath;
        if(directoryName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "directoryName" }));
        }
        if((standardNameLength = directoryName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "directoryName" }));
        }
        if(standardNameLength <= 0 || directoryName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "directoryName" }));
        }
        if(!isObjectNameValid(directoryName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "directoryName" }));
        }
        if((internalFullPath = toVolumeFullPath(directoryName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "directoryName" }));
        }
        internalFullPath = makeInternalFullPathAndCheckCreat(internalFullPath);
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        if(Kernel.createDirectory(zerotermFullPath.getPointer(), 0)) return;
        switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_EXISTS:
            case Kernel.ERROR_ALREADY_EXISTS:
            {
                throw new DirectoryCreationException(platform.independent.filesystem.package.getResourceString("directory.creation")) { directoryName = internalFullPath };
            }
            case Kernel.ERROR_DISK_FULL:
            {
                throw new FileSystemFullException(String.format(platform.independent.osservices.package.getResourceString("file-system.full"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_WRITE_PROTECT:
            {
                throw new ReadOnlyFileSystemException(String.format(platform.independent.osservices.package.getResourceString("file-system.read-only"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
    }

    public boolean isAttached() throws IOException {
        Kernel.setErrorMode(Kernel.SEM_FAILCRITICALERRORS);
        if(Kernel.getVolumeFlags(fldCanonicalRootPath.getPointer()) == Kernel.INVALID_VOLUME_FLAGS)
        {
            if(Kernel.getLastError() == Kernel.ERROR_NOT_READY) return false;
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        return true;
    }

    public boolean isReadOnly() throws IOException {
        char[] canonicalRootPath = fldCanonicalRootPath;
        Kernel.setErrorMode(Kernel.SEM_FAILCRITICALERRORS);
        int flags = Kernel.getVolumeFlags(canonicalRootPath.getPointer());
        if(flags == Kernel.INVALID_VOLUME_FLAGS) switch(Kernel.getLastError())
        {
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { canonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        return (flags & Kernel.FILE_READ_ONLY_VOLUME) != 0;
    }

    public boolean isObjectNameCaseSensitive() throws IOException {
        char[] canonicalRootPath = fldCanonicalRootPath;
        Kernel.setErrorMode(Kernel.SEM_FAILCRITICALERRORS);
        if(Kernel.getVolumeFlags(canonicalRootPath.getPointer()) == Kernel.INVALID_VOLUME_FLAGS) switch(Kernel.getLastError())
        {
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { canonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        return false;
    }

    public boolean isObjectExists(String objectName) throws IOException {
        int standardNameLength;
        String internalFullPath;
        if(objectName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectName" }));
        }
        if((standardNameLength = objectName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectName" }));
        }
        if(standardNameLength <= 0 || objectName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "objectName" }));
        }
        if(!isObjectNameValid(objectName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "objectName" }));
        }
        if((internalFullPath = toVolumeFullPath(objectName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectName" }));
        }
        if((internalFullPath = makeInternalFullPathAndIsExist(internalFullPath)) == null) return false;
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        if(Kernel.getFileAttributes(zerotermFullPath.getPointer()) == Kernel.INVALID_FILE_ATTRIBUTES) switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND: return false;
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        return true;
    }

    public boolean isObjectNameValid(String objectName) {
        if(objectName == null) return false;
        int length = objectName.length;
        if(length > OBJECT_NAME_MAXIMUM_LENGTH || objectName.indexOf("//") >= 0) return false;
        for(int index = 0; index < length; index++)
        {
            char chr = objectName[index];
            if(chr >= '\0' && chr < '\u0020' || chr == '<' || chr == '>' || chr == ':' || chr == '\"' || chr == '\\' || chr == '|' || chr == '?' || chr == '*') return false;
        }
        if(length > 0)
        {
            int beginIndex = 0;
            if(objectName[0] == '/') beginIndex++;
            while(beginIndex >= 0 && beginIndex < length)
            {
                int endIndex = objectName.indexOf('/', beginIndex);
                if(endIndex < 0) endIndex = length;
                if(isComponentReserved(objectName.substring(beginIndex, endIndex))) return false;
                beginIndex = endIndex + 1;
            }
        }
        return true;
    }

    public boolean isInternalNameFull(String internalName) { return internalName != null && internalName.startsWith("\\"); }

    public boolean isInternalNameValid(String internalName) {
        if(internalName == null) return false;
        int length = internalName.length;
        if(length > OBJECT_NAME_MAXIMUM_LENGTH || internalName.indexOf("\\\\") >= 0) return false;
        for(int index = 0; index < length; index++)
        {
            char chr = internalName[index];
            if(chr >= '\0' && chr < '\u0020' || chr == '<' || chr == '>' || chr == ':' || chr == '\"' || chr == '/' || chr == '|' || chr == '?' || chr == '*') return false;
        }
        if(length > 0)
        {
            int beginIndex = 0;
            if(internalName[0] == '\\') beginIndex++;
            while(beginIndex >= 0 && beginIndex < length)
            {
                int endIndex = internalName.indexOf('\\', beginIndex);
                if(endIndex < 0) endIndex = length;
                if(isComponentReserved(internalName.substring(beginIndex, endIndex))) return false;
                beginIndex = endIndex + 1;
            }
        }
        return true;
    }

    public int getObjectNameMaximumLength() { return OBJECT_NAME_MAXIMUM_LENGTH; }

    public long totalSize() throws IOException {
        char[] canonicalRootPath = fldCanonicalRootPath;
        long4 freeSpace = Kernel.getDiskFreeSpaceEx(canonicalRootPath.getPointer());
        if(freeSpace[0] == 0) switch(Kernel.getLastError())
        {
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { canonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        return freeSpace[2];
    }

    public long usedSize() throws IOException {
        char[] canonicalRootPath = fldCanonicalRootPath;
        long4 freeSpace = Kernel.getDiskFreeSpaceEx(canonicalRootPath.getPointer());
        if(freeSpace[0] == 0) switch(Kernel.getLastError())
        {
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { canonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        return freeSpace[2] - freeSpace[3];
    }

    public long availableSize() throws IOException {
        char[] canonicalRootPath = fldCanonicalRootPath;
        long4 freeSpace = Kernel.getDiskFreeSpaceEx(canonicalRootPath.getPointer());
        if(freeSpace[0] == 0) switch(Kernel.getLastError())
        {
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { canonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        return freeSpace[3];
    }

    public String toInternalName(String objectName) {
        if(objectName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectName" }));
        }
        return objectName.replaceAll('/', '\\');
    }

    public String toObjectName(String internalName) {
        if(internalName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "internalName" }));
        }
        return internalName.replaceAll('\\', '/');
    }

    public ObjectEnumeration findFirst(String objectPath) throws ObjectNotFoundException, IOException {
        String internalFullPath;
        if(objectPath == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectPath" }));
        }
        if(objectPath.length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectPath" }));
        }
        if(!isObjectNameValid(objectPath))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "objectPath" }));
        }
        if((internalFullPath = toVolumeFullPath(objectPath)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "objectPath" }));
        }
        internalFullPath = makeInternalFullPathAndCheckExist(internalFullPath, AT_OBJECT);
        if(internalFullPath.endsWith("\\")) internalFullPath = internalFullPath + '*';
        Win32FindData info = new Win32FindData();
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        long handle = Kernel.findFirstFile(zerotermFullPath.getPointer(), info.getPointer());
        if(handle != Kernel.INVALID_HANDLE_VALUE)
        {
            return new VolumeObjectEnumeration(handle, info);
        }
        switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
            {
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) { objectName = internalFullPath };
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
    }

    public ByteWriter createFile(String fileName) throws ReadOnlyFileSystemException, FileCreationException, IOException {
        int standardNameLength;
        String internalFullPath;
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        if((standardNameLength = fileName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        if(standardNameLength <= 0 || fileName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "fileName" }));
        }
        if(!isObjectNameValid(fileName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "fileName" }));
        }
        if((internalFullPath = toVolumeFullPath(fileName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        internalFullPath = makeInternalFullPathAndCheckCreat(internalFullPath);
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        long handle = Kernel.createFile(
            zerotermFullPath.getPointer(),
            Kernel.GENERIC_WRITE,
            0,
            0,
            Kernel.CREATE_NEW,
            Kernel.FILE_ATTRIBUTE_NORMAL,
            0
        );
        if(handle != Kernel.INVALID_HANDLE_VALUE)
        {
            return new FileOutputStream(handle, fldCanonicalRootPath, null, null);
        }
        switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_EXISTS:
            case Kernel.ERROR_ALREADY_EXISTS: break;
            case Kernel.ERROR_DISK_FULL:
            {
                throw new FileSystemFullException(String.format(platform.independent.osservices.package.getResourceString("file-system.full"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_WRITE_PROTECT:
            {
                throw new ReadOnlyFileSystemException(String.format(platform.independent.osservices.package.getResourceString("file-system.read-only"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                if(Kernel.getLastStatus() != Kernel.STATUS_FILE_IS_A_DIRECTORY)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
            }
        }
        throw new FileCreationException(platform.independent.filesystem.package.getResourceString("file.creation")) { fileName = internalFullPath };
    }

    public ByteWriter rewriteFile(String fileName) throws ReadOnlyFileSystemException, FileCreationException, IOException {
        int standardNameLength;
        String internalFullPath;
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        if((standardNameLength = fileName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        if(standardNameLength <= 0 || fileName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "fileName" }));
        }
        if(!isObjectNameValid(fileName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "fileName" }));
        }
        if((internalFullPath = toVolumeFullPath(fileName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        internalFullPath = makeInternalFullPathAndCheckCreat(internalFullPath);
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        long handle = Kernel.createFile(
            zerotermFullPath.getPointer(),
            Kernel.GENERIC_WRITE,
            0,
            0,
            Kernel.CREATE_ALWAYS,
            Kernel.FILE_ATTRIBUTE_NORMAL,
            0
        );
        if(handle != Kernel.INVALID_HANDLE_VALUE)
        {
            return new FileOutputStream(handle, fldCanonicalRootPath, null, null);
        }
        switch(Kernel.getLastError())
        {
            case Kernel.ERROR_DISK_FULL:
            {
                throw new FileSystemFullException(String.format(platform.independent.osservices.package.getResourceString("file-system.full"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_WRITE_PROTECT:
            {
                throw new ReadOnlyFileSystemException(String.format(platform.independent.osservices.package.getResourceString("file-system.read-only"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                if(Kernel.getLastStatus() != Kernel.STATUS_FILE_IS_A_DIRECTORY)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
            }
        }
        throw new FileCreationException(platform.independent.filesystem.package.getResourceString("file.creation")) { fileName = internalFullPath };
    }

    public ByteWriter openFileForAppend(String fileName) throws ReadOnlyFileSystemException, FileNotFoundException, FileOpeningException, IOException {
        int standardNameLength;
        String internalFullPath;
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        if((standardNameLength = fileName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        if(standardNameLength <= 0 || fileName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "fileName" }));
        }
        if(!isObjectNameValid(fileName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "fileName" }));
        }
        if((internalFullPath = toVolumeFullPath(fileName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        internalFullPath = makeInternalFullPathAndCheckExist(internalFullPath, AT_FILE);
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        long handle = Kernel.createFile(
            zerotermFullPath.getPointer(),
            Kernel.GENERIC_WRITE,
            0,
            0,
            Kernel.OPEN_EXISTING,
            Kernel.FILE_ATTRIBUTE_NORMAL,
            0
        );
        if(handle != Kernel.INVALID_HANDLE_VALUE)
        {
            Kernel.setFilePointer(handle, 0, Kernel.FILE_END);
            return new FileOutputStream(handle, fldCanonicalRootPath, null, null);
        }
        switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
            {
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) { fileName = internalFullPath };
            }
            case Kernel.ERROR_WRITE_PROTECT:
            {
                throw new ReadOnlyFileSystemException(String.format(platform.independent.osservices.package.getResourceString("file-system.read-only"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                if(Kernel.getLastStatus() != Kernel.STATUS_FILE_IS_A_DIRECTORY)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
            }
        }
        throw new FileOpeningException(platform.independent.filesystem.package.getResourceString("file.opening.append")) { fileName = internalFullPath };
    }

    public ByteReader openFileForRead(String fileName) throws FileNotFoundException, FileOpeningException, IOException {
        int standardNameLength;
        String internalFullPath;
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        if((standardNameLength = fileName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        if(standardNameLength <= 0 || fileName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "fileName" }));
        }
        if(!isObjectNameValid(fileName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "fileName" }));
        }
        if((internalFullPath = toVolumeFullPath(fileName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        internalFullPath = makeInternalFullPathAndCheckExist(internalFullPath, AT_FILE);
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        long handle = Kernel.createFile(
            zerotermFullPath.getPointer(),
            Kernel.GENERIC_READ,
            Kernel.FILE_SHARE_READ,
            0,
            Kernel.OPEN_EXISTING,
            Kernel.FILE_ATTRIBUTE_NORMAL,
            0
        );
        if(handle != Kernel.INVALID_HANDLE_VALUE)
        {
            return new FileInputStream(handle, null);
        }
        switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
            {
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) { fileName = internalFullPath };
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                if(Kernel.getLastStatus() != Kernel.STATUS_FILE_IS_A_DIRECTORY)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
            }
        }
        throw new FileOpeningException(platform.independent.filesystem.package.getResourceString("file.opening.read")) { fileName = internalFullPath };
    }

    public ByteStream openFile(String fileName) throws ReadOnlyFileSystemException, FileNotFoundException, FileOpeningException, IOException {
        int standardNameLength;
        String internalFullPath;
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        if((standardNameLength = fileName.length) > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        if(standardNameLength <= 0 || fileName.endsWith("/"))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.path"), new Object[] { "fileName" }));
        }
        if(!isObjectNameValid(fileName))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name"), new Object[] { "fileName" }));
        }
        if((internalFullPath = toVolumeFullPath(fileName)).length > OBJECT_NAME_MAXIMUM_LENGTH)
        {
            throw new ObjectNameTooLongException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"), new Object[] { "fileName" }));
        }
        internalFullPath = makeInternalFullPathAndCheckExist(internalFullPath, AT_FILE);
        char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
        long handle = Kernel.createFile(
            zerotermFullPath.getPointer(),
            Kernel.GENERIC_READ | Kernel.GENERIC_WRITE,
            0,
            0,
            Kernel.OPEN_EXISTING,
            Kernel.FILE_ATTRIBUTE_NORMAL,
            0
        );
        if(handle != Kernel.INVALID_HANDLE_VALUE)
        {
            return new FileBidirectStream(handle, fldCanonicalRootPath);
        }
        switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
            {
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) { fileName = internalFullPath };
            }
            case Kernel.ERROR_WRITE_PROTECT:
            {
                throw new ReadOnlyFileSystemException(String.format(platform.independent.osservices.package.getResourceString("file-system.read-only"), new Object[] { fldCanonicalRootPath }));
            }
            case Kernel.ERROR_NOT_READY:
            {
                throw new FileSystemNotAttachedException(String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath }));
            }
            default:
            {
                if(Kernel.getLastStatus() != Kernel.STATUS_FILE_IS_A_DIRECTORY)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
            }
        }
        throw new FileOpeningException(platform.independent.filesystem.package.getResourceString("file.opening")) { fileName = internalFullPath };
    }

    public Attributes newAttributes() { return new VolumeObjectAttributes(); }

    public String currentDirectory { read = fldCurrentDirectory.replaceAll('\\', '/') }

    private void tryMakeCurrentReliableBlock() {
        CriticalSection operation = fldCurrentOperation;
        operation.lock();
        try
        {
            label0:
            if(fldCurrentUnreliableBlock)
            {
                String internalFullPath = fldCurrentDirectory;
                int length = internalFullPath.length;
                if(length <= 1)
                {
                    fldCurrentUnreliableBlock = false;
                    break label0;
                }
                internalFullPath = fldInternalRootPath + internalFullPath.substring(0, length - 1);
                char[] zerotermFullPath = toZeroTerminatedArray(internalFullPath);
                long zerotermFullPathPtr = zerotermFullPath.getPointer();
                long newHandle = Kernel.createFile(
                    zerotermFullPathPtr,
                    /* Kernel.DELETE */ 0x00010000,
                    Kernel.FILE_SHARE_READ | Kernel.FILE_SHARE_WRITE,
                    0,
                    Kernel.OPEN_EXISTING,
                    Kernel.FILE_ATTRIBUTE_NORMAL | Kernel.FILE_FLAG_BACKUP_SEMANTICS,
                    0
                );
                if(newHandle != Kernel.INVALID_HANDLE_VALUE)
                {
                    fldCurrentUnreliableBlock = false;
                } else
                {
                    newHandle = Kernel.createFile(
                        zerotermFullPathPtr,
                        0,
                        0,
                        0,
                        Kernel.OPEN_EXISTING,
                        Kernel.FILE_ATTRIBUTE_NORMAL | Kernel.FILE_FLAG_BACKUP_SEMANTICS,
                        0
                    );
                }
                long oldHandle = fldCurrentHandle;
                if(oldHandle != Kernel.INVALID_HANDLE_VALUE) Kernel.closeHandle(oldHandle);
                fldCurrentHandle = newHandle;
            }
        } finally
        {
            operation.unlock();
        }
    }

    private String toVolumeFullPath(String objectName) {
        String internalName = objectName.replaceAll('/', '\\');
        return isInternalNameFull(internalName) ? internalName : fldCurrentDirectory + internalName;
    }

    private String makeInternalFullPathAndIsExist(String volumeFullPath) throws IOException {
        String internalRootPath = fldInternalRootPath;
        String internalFullPath = volumeFullPath;
        int dotPosition = 0;
        do
        {
            if((dotPosition = internalFullPath.indexOf("\\.\\", dotPosition)) < 0)
            {
                if(!internalFullPath.endsWith("\\.")) break;
                dotPosition = internalFullPath.length - 2;
            }
            internalFullPath = internalFullPath.substring(0, dotPosition) + internalFullPath.substring(dotPosition + 2);
        } while(true);
        dotPosition = 0;
        do
        {
            if((dotPosition = internalFullPath.indexOf("\\..\\", dotPosition)) < 0)
            {
                if(!internalFullPath.endsWith("\\..")) break;
                dotPosition = internalFullPath.length - 3;
            }
            label0:
            {
                if(dotPosition > 0)
                {
                    char[] zerotermFullPath = toZeroTerminatedArray(internalRootPath + internalFullPath.substring(0, dotPosition));
                    int attributes = Kernel.getFileAttributes(zerotermFullPath.getPointer());
                    if(attributes != Kernel.INVALID_FILE_ATTRIBUTES && (attributes & Kernel.FILE_ATTRIBUTE_DIRECTORY) != 0) break label0;
                    switch(Kernel.getLastError())
                    {
                        case Kernel.ERROR_FILE_NOT_FOUND:
                        case Kernel.ERROR_PATH_NOT_FOUND: break;
                        case Kernel.ERROR_NOT_READY:
                        {
                            throw new FileSystemNotAttachedException(
                                String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath })
                            );
                        }
                        default:
                        {
                            throw new IOException(avt.io.package.getResourceString("io"));
                        }
                    }
                }
                return null;
            }
            int reductionPosition = internalFullPath.lastIndexOf('\\', dotPosition - 1);
            internalFullPath = internalFullPath.substring(0, reductionPosition) + internalFullPath.substring(dotPosition + 3);
            dotPosition = reductionPosition;
        } while(true);
        return internalRootPath + internalFullPath;
    }

    private String makeInternalFullPathAndCheckCreat(String volumeFullPath) throws IOException {
        int position = volumeFullPath.lastIndexOf('\\') + 1;
        String dirFullPath = makeInternalFullPathAndCheckExist(volumeFullPath.substring(0, position), AT_DIRECTORY);
        String checkFullPath = dirFullPath + '.';
        char[] zerotermFullPath = toZeroTerminatedArray(checkFullPath);
        if(Kernel.getFileAttributes(zerotermFullPath.getPointer()) == Kernel.INVALID_FILE_ATTRIBUTES) switch(Kernel.getLastError())
        {
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
            {
                throw new DirectoryNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.directory")) { directoryName = checkFullPath };
            }
            default:
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        return dirFullPath + volumeFullPath.substring(position);
    }

    private String makeInternalFullPathAndCheckExist(String volumeFullPath, int argumentType) throws IOException {
        String internalRootPath = fldInternalRootPath;
        String internalFullPath = volumeFullPath;
        int dotPosition = 0;
        do
        {
            if((dotPosition = internalFullPath.indexOf("\\.\\", dotPosition)) < 0)
            {
                if(!internalFullPath.endsWith("\\.")) break;
                dotPosition = internalFullPath.length - 2;
            }
            internalFullPath = internalFullPath.substring(0, dotPosition) + internalFullPath.substring(dotPosition + 2);
        } while(true);
        dotPosition = 0;
        do
        {
            if((dotPosition = internalFullPath.indexOf("\\..\\", dotPosition)) < 0)
            {
                if(!internalFullPath.endsWith("\\..")) break;
                dotPosition = internalFullPath.length - 3;
            }
            label0:
            {
                if(dotPosition > 0)
                {
                    char[] zerotermFullPath = toZeroTerminatedArray(internalRootPath + internalFullPath.substring(0, dotPosition));
                    int attributes = Kernel.getFileAttributes(zerotermFullPath.getPointer());
                    if(attributes != Kernel.INVALID_FILE_ATTRIBUTES && (attributes & Kernel.FILE_ATTRIBUTE_DIRECTORY) != 0) break label0;
                    switch(Kernel.getLastError())
                    {
                        case Kernel.ERROR_FILE_NOT_FOUND:
                        case Kernel.ERROR_PATH_NOT_FOUND: break;
                        case Kernel.ERROR_NOT_READY:
                        {
                            throw new FileSystemNotAttachedException(
                                String.format(platform.independent.osservices.package.getResourceString("file-system.not-attached"), new Object[] { fldCanonicalRootPath })
                            );
                        }
                        default:
                        {
                            throw new IOException(avt.io.package.getResourceString("io"));
                        }
                    }
                }
                switch(argumentType)
                {
                    case AT_FILE:
                    {
                        throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) { fileName = internalRootPath + internalFullPath };
                    }
                    case AT_DIRECTORY:
                    {
                        throw new DirectoryNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.directory")) { directoryName = internalRootPath + internalFullPath };
                    }
                    default:
                    {
                        throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) { objectName = internalRootPath + internalFullPath };
                    }
                }
            }
            int reductionPosition = internalFullPath.lastIndexOf('\\', dotPosition - 1);
            internalFullPath = internalFullPath.substring(0, reductionPosition) + internalFullPath.substring(dotPosition + 3);
            dotPosition = reductionPosition;
        } while(true);
        return internalRootPath + internalFullPath;
    }
}

service VolumeRequiredAttributes(Object, RequiredAttributes)
{
    public static final String B_HIDDEN        =       "bHidden";
    public static final String B_SYSTEM        =       "bSystem";
    public static final String B_ARCHIVE       =      "bArchive";
    public static final String L_CREATION_TIME = "lCreationTime";

    public static long toObjectTime(long internalTime) { return internalTime < 0 ? Long.MIN_VALUE : internalTime / 10000 + 0x2debe1767000L; }

    public static long toInternalTime(long objectTime) { return objectTime < 0x2debe1767000L || objectTime > 0x000374c83ed9f865L ? Long.MIN_VALUE : (objectTime - 0x2debe1767000L) * 10000; }
}

final class VolumeObjectAttributes(Object, Attributes, RequiredAttributes, VolumeRequiredAttributes)
{
    private static final long[] attrHashes;
    private static final String[] attrIds;

    private static {
        attrIds = new String[] { B_READ_ONLY, B_HIDDEN, B_SYSTEM, null, B_DIRECTORY, B_ARCHIVE, null, null, L_CREATION_TIME, L_LAST_ACCESS_TIME, L_LAST_WRITE_TIME };
        int index = attrIds.length;
        attrHashes = new long[index];
        while(index-- > 0) {
            String attrId = attrIds[index];
            if(attrId != null) attrHashes[index] = attrId.hashCodeAsLong();
        }
    }

    private static void stringAttributeIdIsInvalid(String attrId) {
        if(attrId == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "attrId" }));
        }
        if(attrId.isEmpty())
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "attrId" }));
        }
        if(attrId[0] == 's')
        {
            throw new IllegalArgumentException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.attribute-id"), new Object[] { attrId }));
        }
        throw new IllegalArgumentException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.attribute-type"), new Object[] { attrId }));
    }

    private static int booleanAttributeIdToIndex(String attrId) {
        if(attrId == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "attrId" }));
        }
        if(attrId.isEmpty())
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "attrId" }));
        }
        int index = Array.indexOf(attrId.hashCodeAsLong(), attrHashes, 0, 8);
        if(index >= 0 && attrId.equals(attrIds[index])) return index - 0;
        if(attrId[0] == 'b')
        {
            throw new IllegalArgumentException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.attribute-id"), new Object[] { attrId }));
        }
        throw new IllegalArgumentException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.attribute-type"), new Object[] { attrId }));
    }

    private static int longAttributeIdToIndex(String attrId) {
        if(attrId == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "attrId" }));
        }
        if(attrId.isEmpty())
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "attrId" }));
        }
        int index = Array.indexOf(attrId.hashCodeAsLong(), attrHashes, 8, 8);
        if(index >= 0 && attrId.equals(attrIds[index])) return index - 8;
        if(attrId[0] == 'l')
        {
            throw new IllegalArgumentException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.attribute-id"), new Object[] { attrId }));
        }
        throw new IllegalArgumentException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.attribute-type"), new Object[] { attrId }));
    }

    private int fldAttributes;
    private final long[] fldTimes;

    public () { fldTimes = new long[3]; }

    public void setBooleanAttribute(String attrId, boolean newValue) {
        int mask = 1 << booleanAttributeIdToIndex(attrId);
        if(newValue)
        {
            fldAttributes |= mask;
            return;
        }
        fldAttributes &= ~mask;
    }

    public void setLongAttribute(String attrId, long newValue) {
        int index = longAttributeIdToIndex(attrId);
        fldTimes[index] = newValue;
    }

    public void setStringAttribute(String attrId, String newValue) { stringAttributeIdIsInvalid(attrId); }

    public boolean isSupportedAttributeId(String attrId) {
        if(attrId == null || attrId.isEmpty()) return false;
        int index = Array.indexOf(attrId.hashCodeAsLong(), attrHashes, 0, 0);
        return index >= 0 && attrId.equals(attrIds[index]);
    }

    public boolean getBooleanAttribute(String attrId) {
        int mask = 1 << booleanAttributeIdToIndex(attrId);
        return (fldAttributes & mask) != 0;
    }

    public long getLongAttribute(String attrId) {
        int index = longAttributeIdToIndex(attrId);
        return fldTimes[index];
    }

    public String getStringAttribute(String attrId) {
        stringAttributeIdIsInvalid(attrId);
        return null; /* недостижимый код */
    }

    public String displayName(String attrId) {
        if(attrId == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "attrId" }));
        }
        if(attrId.isEmpty())
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "attrId" }));
        }
        int index = Array.indexOf(attrId.hashCodeAsLong(), attrHashes, 0, 0);
        if(index >= 0 && attrId.equals(attrIds[index])) switch(index)
        {
            case  0: return platform.independent.filesystem.package.getResourceString("display-name.object-attributes.read-only");
            case  1: return package.getResourceString("display-name.object-attributes.hidden");
            case  2: return package.getResourceString("display-name.object-attributes.system");
            case  4: return platform.independent.filesystem.package.getResourceString("display-name.object-attributes.directory");
            case  5: return package.getResourceString("display-name.object-attributes.archive");
            case  8: return package.getResourceString("display-name.object-attributes.creation-time");
            case  9: return platform.independent.filesystem.package.getResourceString("display-name.object-attributes.last-access-time");
            case 10: return platform.independent.filesystem.package.getResourceString("display-name.object-attributes.last-write-time");
        }
        throw new IllegalArgumentException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.attribute-id"), new Object[] { attrId }));
    }

    public String[] getSupportedAttributeIds() { return new String[] { B_READ_ONLY, B_HIDDEN, B_SYSTEM, B_DIRECTORY, B_ARCHIVE, L_CREATION_TIME, L_LAST_ACCESS_TIME, L_LAST_WRITE_TIME }; }
}

final class VolumeObjectEnumeration(ObjectEnumeration, Closeable, Attributes, RequiredAttributes, VolumeRequiredAttributes)
{
    private long fldHandle;
    private final long fldPointer;
    private final Win32FindData fldInfo;

    private void setAttributes() {
        Win32FindData info = fldInfo;
        int oattr = info.dwFileAttributes;
        char[] oname = info.cFileName;
        int length = Array.indexOf(0, oname, 0, 0);
        if(length < 0) length = oname.length;
        name = new String(oname, 0, length);
        size = (oattr & Kernel.FILE_ATTRIBUTE_DIRECTORY) != 0 ? 0 : ^^^^info.nFileSizeHigh | ####info.nFileSizeLow;
        setBooleanAttribute(B_DIRECTORY, (oattr & Kernel.FILE_ATTRIBUTE_DIRECTORY) != 0);
        setBooleanAttribute(B_READ_ONLY, (oattr & Kernel.FILE_ATTRIBUTE_READONLY) != 0);
        setBooleanAttribute(B_ARCHIVE, (oattr & Kernel.FILE_ATTRIBUTE_ARCHIVE) != 0);
        setBooleanAttribute(B_HIDDEN, (oattr & Kernel.FILE_ATTRIBUTE_HIDDEN) != 0);
        setBooleanAttribute(B_SYSTEM, (oattr & Kernel.FILE_ATTRIBUTE_SYSTEM) != 0);
        setLongAttribute(L_CREATION_TIME, toObjectTime(info.ftCreationTime));
        setLongAttribute(L_LAST_WRITE_TIME, toObjectTime(info.ftLastWriteTime));
        setLongAttribute(L_LAST_ACCESS_TIME, toObjectTime(info.ftLastAccessTime));
    }

    public (long handle, Win32FindData info): super(new VolumeObjectAttributes()) {
        fldHandle = handle;
        fldPointer = info.getPointer();
        fldInfo = info;
        setAttributes();
    }

    public void close() throws IOException {
        long handle = fldHandle;
        {
            fldHandle = 0;
        }
        if(handle != 0 && !Kernel.findClose(handle))
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
    }

    public boolean findNext() throws ObjectEnumerationException, IOException {
        if(Kernel.findNextFile(fldHandle, fldPointer))
        {
            setAttributes();
            return true;
        }
        if(Kernel.getLastError() != Kernel.ERROR_NO_MORE_FILES)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        return false;
    }

    protected void beforeDestruction() {
        long handle = fldHandle;
        if(handle != 0) Kernel.findClose(handle);
    }
}

class FileSeekExtension(Object, Extension, LimitedSizeExtension, SeekExtension)
{
    long fldHandle;

    public (long handle) { fldHandle = handle; }

    public long available() throws IOException {
        long handle = handleNeeded();
        long size = Kernel.getFileSize(handle);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        long pos = Kernel.setFilePointer(handle, 0, Kernel.FILE_CURRENT);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        return size - pos;
    }

    public long seek(long offset, int from) throws IOException {
        long handle = handleNeeded();
        if(from < BEGIN || from > END)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "from" }));
        }
        long size = Kernel.getFileSize(handle);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        long pos;
        switch(from)
        {
            case BEGIN:
            {
                pos = offset;
                break;
            }
            case END:
            {
                pos = offset + size;
                break;
            }
            default:
            {
                long curr = Kernel.setFilePointer(handle, 0, Kernel.FILE_CURRENT);
                if(Kernel.getLastError() != Kernel.NO_ERROR)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
                pos = offset + curr;
            }
        }
        if(pos < 0) pos = 0;
        if(pos > size) pos = size;
        pos = Kernel.setFilePointer(handle, pos, Kernel.FILE_BEGIN);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        return pos;
    }

    public long position() throws IOException {
        long handle = handleNeeded();
        long result = Kernel.setFilePointer(handle, 0, Kernel.FILE_CURRENT);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        return result;
    }

    public long size() throws IOException {
        long handle = handleNeeded();
        long result = Kernel.getFileSize(handle);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        return result;
    }

    protected final long handleNeeded() throws ClosedFileException {
        long handle = fldHandle;
        if(handle == 0)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        return handle;
    }
}

class FileInputStream(HandleInputStream, Closeable, Extension, MarkExtension)
{
    long fldMarked;
    private boolean fldOwned;
    private FileSeekExtension fldSeekable;

    public (long handle, FileSeekExtension seekable): super(handle) {
        if(seekable == null)
        {
            seekable = new FileSeekExtension(handle);
            fldOwned = true;
        }
        fldSeekable = seekable;
        fldExtensions = new Extension[] { this, seekable };
    }

    public void close() throws IOException {
        long handle = fldHandle;
        {
            fldHandle = 0;
            if(fldOwned) fldSeekable.fldHandle = 0;
        }
        if(handle != 0 && !Kernel.closeHandle(handle))
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
    }

    public long skip(long bytesQuantity) throws IOException {
        long handle = handleNeeded();
        if(bytesQuantity <= 0) return 0;
        long size = Kernel.getFileSize(handle);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        long opos = Kernel.setFilePointer(handle, 0, Kernel.FILE_CURRENT);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        long npos = size - opos;
        if(bytesQuantity > npos) bytesQuantity = npos;
        npos = Kernel.setFilePointer(handle, opos + bytesQuantity, Kernel.FILE_BEGIN);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        return npos - opos;
    }

    public void mark() throws IOException {
        long handle = handleNeeded();
        long pos = Kernel.setFilePointer(handle, 0, Kernel.FILE_CURRENT);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        fldMarked = pos;
    }

    public void reset() throws IOException {
        long handle = handleNeeded();
        Kernel.setFilePointer(handle, fldMarked, Kernel.FILE_BEGIN);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
    }

    protected void beforeDestruction() {
        long handle = fldHandle;
        if(handle != 0) Kernel.closeHandle(handle);
    }
}

class FileOutputStream(HandleOutputStream, Closeable, Extension, MarkExtension, TruncateExtension)
{
    private boolean fldOwned;
    private long fldMarked;
    private FileInputStream fldReader;
    private FileSeekExtension fldSeekable;

    public (long handle, char[] rootPath, FileSeekExtension seekable, FileInputStream reader): super(handle, rootPath) {
        if(seekable == null)
        {
            seekable = new FileSeekExtension(handle);
            fldOwned = true;
        }
        fldReader = reader;
        fldSeekable = seekable;
        fldExtensions = new Extension[] { this, seekable };
    }

    public void close() throws IOException {
        long handle = fldHandle;
        {
            fldHandle = 0;
            if(fldOwned) fldSeekable.fldHandle = 0;
        }
        if(handle != 0 && !Kernel.closeHandle(handle))
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
    }

    public void flush() throws IOException {
        long handle = handleNeeded();
        if(!Kernel.flushFileBuffers(handle))
        {
            if(Kernel.getLastError() == Kernel.ERROR_DISK_FULL)
            {
                throw new FileSystemFullException(String.format(platform.independent.osservices.package.getResourceString("file-system.full"), new Object[] { fldRootPath }));
            }
            throw new IOException(avt.io.package.getResourceString("io"));
        }
    }

    public void mark() throws IOException {
        long handle = handleNeeded();
        long pos = Kernel.setFilePointer(handle, 0, Kernel.FILE_CURRENT);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        fldMarked = pos;
    }

    public void reset() throws IOException {
        long handle = handleNeeded();
        Kernel.setFilePointer(handle, fldMarked, Kernel.FILE_BEGIN);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
    }

    public void truncate() throws IOException {
        long handle = handleNeeded();
        if(!Kernel.setEndOfFile(handle))
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        long size = Kernel.setFilePointer(handle, 0, Kernel.FILE_CURRENT);
        if(Kernel.getLastError() != Kernel.NO_ERROR)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        FileInputStream reader = fldReader;
        if(fldMarked > size) fldMarked = size;
        if(reader != null && reader.fldMarked > size) reader.fldMarked = size;
    }

    protected void beforeDestruction() {
        long handle = fldHandle;
        if(handle != 0) Kernel.closeHandle(handle);
    }
}

class FileBidirectStream(HandleBidirectStream)
{
    public (long handle, char[] rootPath): super(handle, handle) {
        FileSeekExtension seekable = new FileSeekExtension(handle);
        FileInputStream reader = new FileBidirectStreamReader(handle, seekable);
        FileOutputStream writer = new FileBidirectStreamWriter(handle, rootPath, seekable, reader);
        fldExtensions = new Extension[] { seekable };
        fldReader = reader;
        fldWriter = writer;
    }
}

service FileBidirectStreamReader(FileInputStream)
{
    public void close() {  }

    protected void beforeDestruction() {  }
}

service FileBidirectStreamWriter(FileOutputStream)
{
    public void close() {  }

    protected void beforeDestruction() {  }
}

final class CurrentEnvironment(Environment)
{
    private static native Mutex getOperation(Environment env);

    private static native platform.dependent.EnvironmentTable getVariables(Environment env);

    public () { update(); }

    public void assign(Environment anot) {
        if(anot == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "anot" }));
        }
        if(anot == this) return;
        StringBuilder block = new StringBuilder();
        platform.dependent.EnvironmentTable vars = getVariables(anot);
        Mutex operation = getOperation(anot);
        operation.lock();
        try
        {
            for(int length = vars.length, int index = 0; index < length; index++)
            {
                String name = vars[index];
                block.append(name).append('=').append(vars[name]).append('\0');
            }
        } finally
        {
            operation.unlock();
        }
        int length = block.append('\0').length;
        char[] envChars = new char[length];
        block.getChars(0, length, envChars, 0);
        if(Kernel.setEnvironmentStrings(envChars.getPointer())) update();
    }

    public void operator []=(String envName, String newValue) {
        if(envName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "envName" }));
        }
        if(envName.indexOf(0) >= 0 || envName.indexOf('=') >= 0)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "envName" }));
        }
        if(newValue == null)
        {
            int length = envName.length;
            char[] envChars = new char[length + 1];
            envName.getChars(0, length, envChars, 0);
            if(Kernel.setEnvironmentVariable(envChars.getPointer(), 0)) update();
            return;
        }
        if(newValue.indexOf(0) >= 0)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "newValue" }));
        }
        int nlength = envName.length + 1;
        int vlength = newValue.length + 1;
        char[] envChars = new char[nlength + vlength];
        long envPtr = envChars.getPointer();
        envName.getChars(0, nlength - 1, envChars, 0);
        newValue.getChars(0, vlength - 1, envChars, nlength);
        if(Kernel.setEnvironmentVariable(envPtr, envPtr + (nlength << 1))) update();
    }

    private void update() {
        try
        {
            long2 envDs = Kernel.getEnvironmentStrings();
            long envPtr = envDs[0];
            try
            {
                int envLen = (int) envDs[1];
                char[] envChars = (char[]) char[].class.newArrayAt(envPtr, envLen);
                platform.dependent.EnvironmentTable vars = getVariables(this);
                Mutex operation = getOperation(this);
                operation.lock();
                try
                {
                    for(vars.clear(), int beginIndex = 0; beginIndex >= 0 && beginIndex < envLen; )
                    {
                        int endIndex = Array.indexOf(0, envChars, beginIndex, 0);
                        int eqIndex = Array.indexOf('=', envChars, beginIndex, endIndex - beginIndex);
                        String name = new String(envChars, beginIndex, eqIndex - beginIndex);
                        String value = new String(envChars, eqIndex + 1, endIndex - eqIndex - 1);
                        vars[name] = value;
                        beginIndex = endIndex + 1;
                    }
                } finally
                {
                    operation.unlock();
                }
            } finally
            {
                Kernel.freeEnvironmentStrings(envPtr);
            }
        } catch(Exception exception) {  }
    }
}