!package.avt

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

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

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

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

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

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

package platform.dependent.mswindows.runtime;

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

package service Constants(Object, RequiredAttributes)
{
    public static final char INTERNAL_ANY_OBJECT          =  '*';
    public static final char INTERNAL_DRIVE_SEPARATOR     =  ':';
    public static final char INTERNAL_DIRECTORY_SEPARATOR = '\\';

    public static final int MAX_PATH =   260;
    public static final int MAX_ENV  = 32767;

    public static final int SEEKABLE    = 0x00000001;
    public static final int TRUNCATABLE = 0x00000002;
    public static final int CLOSEABLE   = 0x80000000;

    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; }
}

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

    public () { fldOperationPointer = (fldOperationObject = new platform.dependent.mswindows.kernel.CriticalSection()).getPointer(); }

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

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

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

    protected final void afterConstruction() { Kernel.initializeCriticalSection(fldOperationPointer); }

    protected final void beforeDestruction() { Kernel.deleteCriticalSection(fldOperationPointer); }
}

package class Heap64(Object, Measureable, Long2Array)
{
    public static final long BLOCK_SIZE     =    1L << 8;
    public static final long MIN_ALLOC_SIZE = 128L << 20;
    public static final long MAX_ALLOC_SIZE = 128L << 30;

    public static int getMemoryMapLength(long allocationSize) {
        return (int) (allocationSize >> 8);
    }

    public static long getAllocationSize(long instanceSize) {
        if(instanceSize < MIN_ALLOC_SIZE)
        {
            instanceSize = MIN_ALLOC_SIZE;
        }
        else if(instanceSize > MAX_ALLOC_SIZE)
        {
            instanceSize = MAX_ALLOC_SIZE;
        }
        return instanceSize + (-instanceSize & MIN_ALLOC_SIZE - 1);
    }

    private int fldAttributes;
    private int fldHeapLength;
    private int fldHeapCapacity;
    private int fldInsertIndex;
    private int4 fldInsertElement;
    private long fldAllocationPointer;
    private long fldAllocationSize;
    private int4[] fldMemoryMap;

    public () {  }

    public void initialize(long allocationPointer, int attributes, int4[] memoryMap) {
        int capacity = memoryMap.capacity;
        memoryMap.length = 0;
        fldAttributes = attributes;
        fldHeapLength = 0;
        fldHeapCapacity = capacity;
        fldAllocationPointer = allocationPointer;
        fldAllocationSize = (long) capacity << 8;
        fldMemoryMap = memoryMap;
    }

    public void allocateFinish() {
        int index = fldInsertIndex;
        int length = fldHeapLength;
        int4[] map = fldMemoryMap;
        if(index > 0)
        {
            map[--index] = (int2) map[index++];
        }
        map.length = ++length;
        insert(index);
        map[index] = fldInsertElement;
        fldHeapLength = length;
    }

    public long allocateStart(long instanceSize) {
        int blockLength = (int) (instanceSize + (-instanceSize & BLOCK_SIZE - 1) >> 8);
        if(blockLength <= 0)
        {
            return 0;
        }
        int index = findFreeSpace(blockLength);
        if(index < 0)
        {
            return 0;
        }
        int4[] map = fldMemoryMap;
        int4 previous = 0;
        if(index > 0)
        {
            previous = map[index - 1];
        }
        int blockOffset = previous[0] + previous[1];
        fldInsertIndex = index;
        fldInsertElement = new int4 { blockOffset, blockLength, (index >= fldHeapLength ? fldHeapCapacity : (int) map[index]) - blockOffset - blockLength, 0 };
        return fldAllocationPointer + ((long) blockOffset << 8);
    }

    public long allocate(long instanceSize) {
        int blockLength = (int) (instanceSize + (-instanceSize & BLOCK_SIZE - 1) >> 8);
        if(blockLength <= 0)
        {
            return 0;
        }
        int index = findFreeSpace(blockLength);
        if(index < 0)
        {
            return 0;
        }
        int4[] map = fldMemoryMap;
        int2 previous = 0;
        if(index > 0)
        {
            map[--index] = previous = (int2) map[index++];
        }
        int length = fldHeapLength;
        int blockOffset = previous[0] + previous[1];
        int4 element = new int4 { blockOffset, blockLength, (index >= length ? fldHeapCapacity : (int) map[index]) - blockOffset - blockLength, 0 };
        map.length = ++length;
        insert(index);
        map[index] = element;
        fldHeapLength = length;
        return fldAllocationPointer + ((long) blockOffset << 8);
    }

    public long free(long instancePointer) {
        if((instancePointer -= fldAllocationPointer) < 0 || instancePointer >= fldAllocationSize || (instancePointer & BLOCK_SIZE - 1) != 0)
        {
            return 0;
        }
        int index = indexOf((int) (instancePointer >> 8));
        if(index < 0)
        {
            return 0;
        }
        int4[] map = fldMemoryMap;
        int4 element = map[index];
        int length = fldHeapLength;
        int blockLength = element[1];
        fldHeapLength = --length;
        delete(index);
        map[length] = 0;
        map.length = length;
        if(index > 0)
        {
            map[index - 1] += new int4 { 0, 0, blockLength + element[2], 0 };
        }
        return (long) blockLength << 8;
    }

    public long freeMemory() {
        int index = fldHeapLength - 1;
        return index < 0 ? fldAllocationSize : (long) fldMemoryMap[index][2] << 8;
    }

    public int length { read = fldHeapLength }

    public int attributes { read = fldAttributes }

    public long allocationPointer { read = fldAllocationPointer }

    public long allocationSize { read = fldAllocationSize }

    public long2 operator [](int index) { return fldAllocationPointer + ((long2) fldMemoryMap[index] << 8); }

    private native void insert(int index);

    private native void delete(int index);

    private native int findFreeSpace(int length);

    private native int indexOf(int offset);
}

package class Monitor(CriticalSection, platform.dependent.Monitor, platform.dependent.Waitable)
{
    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 = (long) 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)
        {
            Event.getInstanceFor(currentId, Win32Runtime.getSecurityContext()).waitSignalled(0i);
        }
    }

    public void unlock() {
        boolean isNotOwnedBy = false;
        long currentId = (long) 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 = (long) 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 {
        boolean isWaiting = false;
        boolean isNotOwnedBy = false;
        boolean isInterrupted = false;
        long currentId = (long) 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)
        {
            Event event = Event.getInstanceFor(currentId, Win32Runtime.getSecurityContext());
            if(handler != null) handler.setWaitable(this);
            event.waitSignalled(timeInMillis);
            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(0i);
            } 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) Event.getInstanceFor(entry[1], Win32Runtime.getSecurityContext()).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;
        long4 entry;
        int index;
        label0:
        {
            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 Services(Object, ProcessEnvironment, FileSystem, TimeBase, ProcessEnvironmentVariables, Constants, RequiredAttributes)
{
    private static final char SPACE = '\u0020';
    private static final char QUOTE = '\u0022';

    private static boolean isDriveLetter(char character) {
        return character >= 'A' && character <= 'Z' || character >= 'a' && character <= 'z';
    }

    private static int getDaysCount(int year, int month) {
        switch(month + 1)
        {
        case  1:
        case  3:
        case  5:
        case  7:
        case  8:
        case 10:
        case 12:
            return 31;
        case  4:
        case  6:
        case  9:
        case 11:
            return 30;
        case  2:
            return ++year % (year % 100 == 0 ? 400 : 4) == 0 ? 29 : 28;
        }
        return 0;
    }

    private static int getReadOnlyPathLength(char[] internalNameChars) throws DirectoryNotFoundException, IOException {
        if(!isDriveLetter(internalNameChars[0]) || internalNameChars[1] != INTERNAL_DRIVE_SEPARATOR || internalNameChars[2] != INTERNAL_DIRECTORY_SEPARATOR)
        {
            throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-syntax"));
        }
        char character = internalNameChars[3];
        internalNameChars[3] = '\0';
        try
        {
            switch(Kernel.getDriveType(internalNameChars.getPointer()))
            {
            case Kernel.DRIVE_NO_ROOT_DIR:
                throw new DirectoryNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.directory")) {
                    directoryName = new String(internalNameChars, 0, 3)
                };
            case Kernel.DRIVE_UNKNOWN:
                throw new IOException(avt.io.package.getResourceString("io"));
            case Kernel.DRIVE_CDROM:
                return 3;
            default:
                return 0;
            }
        } finally
        {
            internalNameChars[3] = character;
        }
    }

    private static char[] toInternalNameChars(String objectName, String methodName) {
        /*  Преобразование полных стандартных имён объектов во внутренние по следующей схеме:
            /           =>  
            /d:         =>  D:\
            /d:/        =>  D:\*
            /d:/obj     =>  D:\obj
            /d:/dir/    =>  D:\dir\*
            /d:/dir/obj =>  D:\dir\obj
        */
        int nlength = objectName.length;
        if(nlength > MAX_PATH - 1)
        {
            throw new ObjectNameTooLongException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"));
        }
        if(!objectName.startsWith("" + DIRECTORY_SEPARATOR))
        {
            throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.not-begins-with-separator"));
        }
        if(methodName != null && objectName.endsWith("" + DIRECTORY_SEPARATOR))
        {
            throw new IllegalObjectNameException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.ends-with-separator"),
                new Object[] { methodName }
            ));
        }
        if((
            objectName.indexOf('\0') & objectName.indexOf('<') & objectName.indexOf('>') &
            objectName.indexOf('\"') & objectName.indexOf('?') & objectName.indexOf('|') &
            objectName.indexOf(INTERNAL_ANY_OBJECT) &
            objectName.indexOf(INTERNAL_DIRECTORY_SEPARATOR) &
            objectName.indexOf(INTERNAL_DRIVE_SEPARATOR, 3)
        ) >= 0)
        {
            throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-characters"));
        }
        if(
            nlength == 2 || objectName.indexOf("" + DIRECTORY_SEPARATOR + DIRECTORY_SEPARATOR) >= 0 ||
            nlength >= 3 && (!isDriveLetter(objectName[1]) || objectName[2] != INTERNAL_DRIVE_SEPARATOR) ||
            nlength >= 4 && (objectName[3] != DIRECTORY_SEPARATOR)
        )
        {
            throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-syntax"));
        }
        int rlength = 0;
        char[] result = new char[MAX_PATH];
        for(int beginIndex = 0, int cindex = 0; beginIndex < nlength; )
        {
            int endIndex = objectName.indexOf(DIRECTORY_SEPARATOR, ++beginIndex);
            if(endIndex < 0) endIndex = nlength;
            int clength = endIndex - beginIndex;
            String component = objectName.substring(beginIndex, endIndex);
            if(component.equals(".") || component.equals(".."))
            {
                throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-syntax"));
            }
            if(cindex > 0 && clength <= 0)
            {
                clength = (component = "" + INTERNAL_ANY_OBJECT).length;
            }
            if(cindex > 1)
            {
                result[rlength++] = INTERNAL_DIRECTORY_SEPARATOR;
            }
            component.getChars(0, clength, result, rlength);
            if(cindex < 1 && clength == 2)
            {
                result[rlength] = Char.toUpperCase(result[rlength]);
                rlength += clength;
                result[rlength++] = INTERNAL_DIRECTORY_SEPARATOR;
            } else
            {
                rlength += clength;
            }
            beginIndex = endIndex;
            cindex++;
        }
        return result;
    }

    private static String[] newArguments() {
        try
        {
            long2 descriptor = Kernel.getCommandLine();
            char[] commandLineChars = (char[]) char[].class.newArrayAt((long) descriptor, (int) descriptor[1]);
            int commandLineLength = commandLineChars.length;
            int length = 0;
            for(boolean quote = false, char prev = SPACE, int pos = 0; pos < commandLineLength; pos++)
            {
                char curr = commandLineChars[pos];
                if(curr == QUOTE)
                {
                    quote = !quote;
                }
                else if(!quote && prev != SPACE && curr == SPACE)
                {
                    length++;
                }
                if(commandLineLength - pos == 1 && curr != SPACE)
                {
                    length++;
                }
                prev = curr;
            }
            String[] result = new String[length];
            for(boolean quote = false, char prev = SPACE, StringBuilder argument = new StringBuilder(commandLineLength), int pos = length = 0; pos < commandLineLength; pos++)
            {
                char curr = commandLineChars[pos];
                if(curr == QUOTE)
                {
                    quote = !quote;
                }
                else if(quote || curr != SPACE)
                {
                    argument + curr;
                }
                else if(prev != SPACE)
                {
                    result[length++] = argument.toString();
                    argument.clear();
                }
                if(commandLineLength - pos == 1 && curr != SPACE)
                {
                    result[length++] = argument.toString();
                }
                prev = curr;
            }
            if(length > 0)
            {
                char[] moduleNameChars = new char[MAX_PATH];
                int moduleNameLength = Kernel.getModuleFileName(0, moduleNameChars.getPointer(), MAX_PATH);
                result[0] = new String(moduleNameChars, 0, moduleNameLength);
            }
            result.finalize();
            return result;
        }
        catch(Exception exception)
        {
            throw exception instanceof RuntimeException ? (RuntimeException) exception : new RuntimeException(exception.message, exception);
        }
    }

    private final String[] fldArguments;
    private final Win32FindData fldDummyFindData;
    private final ByteReader fldStandardInput;
    private final ByteWriter fldStandardError;
    private final ByteWriter fldStandardOutput;
    private final String fldConsoleInputCharsetName;
    private final String fldConsoleOutputCharsetName;

    public () {
        fldArguments = newArguments();
        fldDummyFindData = new Win32FindData();
        fldStandardInput = new FileInputStream(Kernel.getStdHandle(Kernel.STD_INPUT));
        fldStandardError = new FileOutputStream(Kernel.getStdHandle(Kernel.STD_ERROR));
        fldStandardOutput = new FileOutputStream(Kernel.getStdHandle(Kernel.STD_OUTPUT));
        fldConsoleInputCharsetName = ("CP" + Int.toString(Kernel.getConsoleInputCP())).intern();
        fldConsoleOutputCharsetName = ("CP" + Int.toString(Kernel.getConsoleOutputCP())).intern();
    }

    public void setCurrentDirectory(String directoryName) throws DirectoryNotFoundException, DirectoryOperationException, IOException {
        if(directoryName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "directoryName" }));
        }
        char[] internalNameChars = toInternalNameChars(directoryName, "setCurrentDirectory");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(!Kernel.setCurrentDirectory(internalNameChars.getPointer())) switch(Kernel.getLastError())
        {
        default:
            if(Kernel.getLastStatus() != Kernel.STATUS_NOT_A_DIRECTORY)
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
            throw new DirectoryOperationException(platform.dependent.package.getResourceString("current-directory.set")) {
                directoryName = new String(internalNameChars, 0, internalNameLength)
            };
        case Kernel.ERROR_FILE_NOT_FOUND:
        case Kernel.ERROR_PATH_NOT_FOUND:
            throw new DirectoryNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.directory")) {
                directoryName = new String(internalNameChars, 0, internalNameLength)
            };
        }
    }

    public void readAttributes(String objectName, ObjectAttributes objectAttr) throws ObjectNotFoundException, IOException {
        if(objectName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectName" }));
        }
        char[] internalNameChars = toInternalNameChars(objectName, "readAttributes");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) {
                    objectName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            if(objectAttr != null)
            {
                if(objectAttr.isSupportedAttributeId(B_DIRECTORY)) objectAttr.setBooleanAttribute(B_DIRECTORY, true);
                if(objectAttr.isSupportedAttributeId(B_READ_ONLY)) objectAttr.setBooleanAttribute(B_READ_ONLY, false);
                if(objectAttr.isSupportedAttributeId(B_ARCHIVE)) objectAttr.setBooleanAttribute(B_ARCHIVE, true);
                if(objectAttr.isSupportedAttributeId(B_HIDDEN)) objectAttr.setBooleanAttribute(B_HIDDEN, false);
                if(objectAttr.isSupportedAttributeId(B_SYSTEM)) objectAttr.setBooleanAttribute(B_SYSTEM, true);
                if(objectAttr.isSupportedAttributeId(L_LAST_ACCESS_TIME)) objectAttr.setLongAttribute(L_LAST_ACCESS_TIME, Long.MIN_VALUE);
                if(objectAttr.isSupportedAttributeId(L_LAST_WRITE_TIME)) objectAttr.setLongAttribute(L_LAST_WRITE_TIME, Long.MIN_VALUE);
                if(objectAttr.isSupportedAttributeId(L_CREATION_TIME)) objectAttr.setLongAttribute(L_CREATION_TIME, Long.MIN_VALUE);
            }
        } else
        {
            Win32FindData internalFindData = new Win32FindData();
            long findHandle = Kernel.findFirstFile(internalNameChars.getPointer(), internalFindData.getPointer());
            if(findHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
            {
            default:
                throw new IOException(avt.io.package.getResourceString("io"));
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) {
                    objectName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            if(!Kernel.findClose(findHandle))
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
            if(objectAttr != null)
            {
                int attributes = internalFindData.dwFileAttributes;
                if(objectAttr.isSupportedAttributeId(B_DIRECTORY)) objectAttr.setBooleanAttribute(B_DIRECTORY, (attributes & Kernel.FILE_ATTRIBUTE_DIRECTORY) != 0);
                if(objectAttr.isSupportedAttributeId(B_READ_ONLY)) objectAttr.setBooleanAttribute(B_READ_ONLY, (attributes & Kernel.FILE_ATTRIBUTE_READONLY) != 0);
                if(objectAttr.isSupportedAttributeId(B_ARCHIVE)) objectAttr.setBooleanAttribute(B_ARCHIVE, (attributes & Kernel.FILE_ATTRIBUTE_ARCHIVE) != 0);
                if(objectAttr.isSupportedAttributeId(B_HIDDEN)) objectAttr.setBooleanAttribute(B_HIDDEN, (attributes & Kernel.FILE_ATTRIBUTE_HIDDEN) != 0);
                if(objectAttr.isSupportedAttributeId(B_SYSTEM)) objectAttr.setBooleanAttribute(B_SYSTEM, (attributes & Kernel.FILE_ATTRIBUTE_SYSTEM) != 0);
                if(objectAttr.isSupportedAttributeId(L_LAST_ACCESS_TIME)) objectAttr.setLongAttribute(L_LAST_ACCESS_TIME, toObjectTime(internalFindData.ftLastAccessTime));
                if(objectAttr.isSupportedAttributeId(L_LAST_WRITE_TIME)) objectAttr.setLongAttribute(L_LAST_WRITE_TIME, toObjectTime(internalFindData.ftLastWriteTime));
                if(objectAttr.isSupportedAttributeId(L_CREATION_TIME)) objectAttr.setLongAttribute(L_CREATION_TIME, toObjectTime(internalFindData.ftCreationTime));
            }
        }
    }

    public void writeAttributes(String objectName, ObjectAttributes objectAttr) throws ReadOnlyFileSystemException, ObjectNotFoundException, ObjectWriteAttributesException, IOException {
        if(objectName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectName" }));
        }
        if(objectAttr == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectAttr" }));
        }
        char[] internalNameChars = toInternalNameChars(objectName, "writeAttributes");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) {
                    objectName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            throw new ObjectWriteAttributesException(platform.independent.filesystem.package.getResourceString("object.write-attributes")) {
                objectName = new String(internalNameChars, 0, internalNameLength)
            };
        }
        {
            int internalNameReadOnlyLength = getReadOnlyPathLength(internalNameChars);
            if(internalNameReadOnlyLength > 0)
            {
                throw new ReadOnlyFileSystemException(platform.independent.filesystem.package.getResourceString("file-system.read-only")) {
                    directoryName = new String(internalNameChars, 0, internalNameReadOnlyLength)
                };
            }
            long internalNamePointer = internalNameChars.getPointer();
            int attributes = Kernel.getFileAttributes(internalNamePointer);
            if(attributes == Kernel.INVALID_FILE_ATTRIBUTES) switch(Kernel.getLastError())
            {
            default:
                throw new IOException(avt.io.package.getResourceString("io"));
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) {
                    objectName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            long fileHandle = Kernel.createFile(internalNamePointer, Kernel.GENERIC_WRITE, 0, 0, Kernel.OPEN_EXISTING, attributes | Kernel.FILE_FLAG_BACKUP_SEMANTICS, 0);
            if(fileHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
            {
            default:
                throw new ObjectWriteAttributesException(platform.independent.filesystem.package.getResourceString("object.write-attributes")) {
                    objectName = new String(internalNameChars, 0, internalNameLength)
                };
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) {
                    objectName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            try
            {
                FileTime creationTime = new FileTime() { ftFileTime = Long.MIN_VALUE };
                FileTime lastWriteTime = new FileTime() { ftFileTime = Long.MIN_VALUE };
                FileTime lastAccessTime = new FileTime() { ftFileTime = Long.MIN_VALUE };
                if(objectAttr.isSupportedAttributeId(L_CREATION_TIME)) creationTime.ftFileTime = toInternalTime(objectAttr.getLongAttribute(L_CREATION_TIME));
                if(objectAttr.isSupportedAttributeId(L_LAST_WRITE_TIME)) lastWriteTime.ftFileTime = toInternalTime(objectAttr.getLongAttribute(L_LAST_WRITE_TIME));
                if(objectAttr.isSupportedAttributeId(L_LAST_ACCESS_TIME)) lastAccessTime.ftFileTime = toInternalTime(objectAttr.getLongAttribute(L_LAST_ACCESS_TIME));
                if(!Kernel.setFileTime(fileHandle, creationTime.getPointer(), lastAccessTime.getPointer(), lastWriteTime.getPointer()))
                {
                    throw new ObjectWriteAttributesException(platform.independent.filesystem.package.getResourceString("object.write-attributes")) {
                        objectName = new String(internalNameChars, 0, internalNameLength)
                    };
                }
            } finally
            {
                if(!Kernel.closeHandle(fileHandle))
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
            }
            attributes &= ~(Kernel.FILE_ATTRIBUTE_READONLY | Kernel.FILE_ATTRIBUTE_HIDDEN | Kernel.FILE_ATTRIBUTE_SYSTEM | Kernel.FILE_ATTRIBUTE_ARCHIVE);
            if(objectAttr.isSupportedAttributeId(B_READ_ONLY) && objectAttr.getBooleanAttribute(B_READ_ONLY)) attributes |= Kernel.FILE_ATTRIBUTE_READONLY;
            if(objectAttr.isSupportedAttributeId(B_HIDDEN) && objectAttr.getBooleanAttribute(B_HIDDEN)) attributes |= Kernel.FILE_ATTRIBUTE_HIDDEN;
            if(objectAttr.isSupportedAttributeId(B_SYSTEM) && objectAttr.getBooleanAttribute(B_SYSTEM)) attributes |= Kernel.FILE_ATTRIBUTE_SYSTEM;
            if(objectAttr.isSupportedAttributeId(B_ARCHIVE) && objectAttr.getBooleanAttribute(B_ARCHIVE)) attributes |= Kernel.FILE_ATTRIBUTE_ARCHIVE;
            if(!Kernel.setFileAttributes(internalNamePointer, attributes))
            {
                throw new ObjectWriteAttributesException(platform.independent.filesystem.package.getResourceString("object.write-attributes")) {
                    objectName = new String(internalNameChars, 0, internalNameLength)
                };
            }
        }
    }

    public void move(String objectOldName, String objectNewName) throws ReadOnlyFileSystemException, ObjectNotFoundException, MoveOperationException, IOException {
        if(objectOldName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectOldName" }));
        }
        if(objectNewName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectNewName" }));
        }
        char[] internalOldNameChars = toInternalNameChars(objectOldName, "move");
        char[] internalNewNameChars = toInternalNameChars(objectNewName, "move");
        int internalOldNameLength = Array.indexOf(0, internalOldNameChars, 0, 0);
        int internalNewNameLength = Array.indexOf(0, internalNewNameChars, 0, 0);
        if(internalOldNameLength <= 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalOldNameChars.getPointer()) == 0)
            {
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) {
                    objectName = new String(internalOldNameChars, 0, internalOldNameLength)
                };
            }
            throw new MoveOperationException(platform.independent.filesystem.package.getResourceString("move-operation")) {
                objectOldName = new String(internalOldNameChars, 0, internalOldNameLength),
                objectNewName = new String(internalNewNameChars, 0, internalNewNameLength)
            };
        }
        if(internalNewNameLength <= 3)
        {
            throw new MoveOperationException(platform.independent.filesystem.package.getResourceString("move-operation")) {
                objectOldName = new String(internalOldNameChars, 0, internalOldNameLength),
                objectNewName = new String(internalNewNameChars, 0, internalNewNameLength)
            };
        }
        {
            int internalOldNameReadOnlyLength = getReadOnlyPathLength(internalOldNameChars);
            if(internalOldNameReadOnlyLength > 0)
            {
                throw new ReadOnlyFileSystemException(platform.independent.filesystem.package.getResourceString("file-system.read-only")) {
                    directoryName = new String(internalOldNameChars, 0, internalOldNameReadOnlyLength)
                };
            }
            int internalNewNameReadOnlyLength = getReadOnlyPathLength(internalNewNameChars);
            if(internalNewNameReadOnlyLength > 0)
            {
                throw new ReadOnlyFileSystemException(platform.independent.filesystem.package.getResourceString("file-system.read-only")) {
                    directoryName = new String(internalNewNameChars, 0, internalNewNameReadOnlyLength)
                };
            }
            if(!Kernel.moveFile(internalOldNameChars.getPointer(), internalNewNameChars.getPointer())) switch(Kernel.getLastError())
            {
            default:
                throw new IOException(avt.io.package.getResourceString("io"));
            case Kernel.ERROR_FILE_EXISTS:
            case Kernel.ERROR_ALREADY_EXISTS:
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new MoveOperationException(platform.independent.filesystem.package.getResourceString("move-operation")) {
                    objectOldName = new String(internalOldNameChars, 0, internalOldNameLength),
                    objectNewName = new String(internalNewNameChars, 0, internalNewNameLength)
                };
            }
        }
    }

    public void deleteFile(String fileName) throws ReadOnlyFileSystemException, FileNotFoundException, FileDeletionException, IOException {
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        char[] internalNameChars = toInternalNameChars(fileName, "deleteFile");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) {
                    fileName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            throw new FileDeletionException(platform.independent.filesystem.package.getResourceString("file.deletion")) {
                fileName = new String(internalNameChars, 0, internalNameLength)
            };
        }
        {
            int internalNameReadOnlyLength = getReadOnlyPathLength(internalNameChars);
            if(internalNameReadOnlyLength > 0)
            {
                throw new ReadOnlyFileSystemException(platform.independent.filesystem.package.getResourceString("file-system.read-only")) {
                    directoryName = new String(internalNameChars, 0, internalNameReadOnlyLength)
                };
            }
            if(!Kernel.deleteFile(internalNameChars.getPointer())) switch(Kernel.getLastError())
            {
            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 = new String(internalNameChars, 0, internalNameLength)
                };
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) {
                    fileName = new String(internalNameChars, 0, internalNameLength)
                };
            }
        }
    }

    public void deleteDirectory(String directoryName) throws ReadOnlyFileSystemException, DirectoryNotFoundException, DirectoryDeletionException, IOException {
        if(directoryName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "directoryName" }));
        }
        char[] internalNameChars = toInternalNameChars(directoryName, "deleteDirectory");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new DirectoryNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.directory")) {
                    directoryName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            throw new DirectoryDeletionException(platform.independent.filesystem.package.getResourceString("directory.deletion")) {
                directoryName = new String(internalNameChars, 0, internalNameLength)
            };
        }
        {
            int internalNameReadOnlyLength = getReadOnlyPathLength(internalNameChars);
            if(internalNameReadOnlyLength > 0)
            {
                throw new ReadOnlyFileSystemException(platform.independent.filesystem.package.getResourceString("file-system.read-only")) {
                    directoryName = new String(internalNameChars, 0, internalNameReadOnlyLength)
                };
            }
            if(!Kernel.removeDirectory(internalNameChars.getPointer())) switch(Kernel.getLastError())
            {
            default:
                if(Kernel.getLastStatus() != Kernel.STATUS_NOT_A_DIRECTORY)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
                /* падение через */
            case Kernel.ERROR_DIR_NOT_EMPTY:
                throw new DirectoryDeletionException(platform.independent.filesystem.package.getResourceString("directory.deletion")) {
                    directoryName = new String(internalNameChars, 0, internalNameLength)
                };
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new DirectoryNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.directory")) {
                    directoryName = new String(internalNameChars, 0, internalNameLength)
                };
            }
        }
    }

    public void createDirectory(String directoryName) throws ReadOnlyFileSystemException, DirectoryCreationException, IOException {
        if(directoryName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "directoryName" }));
        }
        char[] internalNameChars = toInternalNameChars(directoryName, "createDirectory");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            throw new DirectoryCreationException(platform.independent.filesystem.package.getResourceString("directory.creation")) {
                directoryName = new String(internalNameChars, 0, internalNameLength)
            };
        }
        {
            int internalNameReadOnlyLength = getReadOnlyPathLength(internalNameChars);
            if(internalNameReadOnlyLength > 0)
            {
                throw new ReadOnlyFileSystemException(platform.independent.filesystem.package.getResourceString("file-system.read-only")) {
                    directoryName = new String(internalNameChars, 0, internalNameReadOnlyLength)
                };
            }
            if(!Kernel.createDirectory(internalNameChars.getPointer(), 0)) switch(Kernel.getLastError())
            {
            default:
                throw new IOException(avt.io.package.getResourceString("io"));
            case Kernel.ERROR_FILE_EXISTS:
            case Kernel.ERROR_ALREADY_EXISTS:
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new DirectoryCreationException(platform.independent.filesystem.package.getResourceString("directory.creation")) {
                    directoryName = new String(internalNameChars, 0, internalNameLength)
                };
            }
        }
    }

    public boolean isObjectExists(String objectName) throws IOException {
        if(objectName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectName" }));
        }
        char[] internalNameChars = toInternalNameChars(objectName, "isObjectExists");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            return (long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) != 0;
        }
        {
            int attributes = Kernel.getFileAttributes(internalNameChars.getPointer());
            if(attributes == Kernel.INVALID_FILE_ATTRIBUTES) switch(Kernel.getLastError())
            {
            default:
                throw new IOException(avt.io.package.getResourceString("io"));
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                return false;
            }
        }
        return true;
    }

    public boolean isObjectNameCaseSensitive() throws DirectoryNotFoundException, IOException {
        return false;
    }

    public boolean isObjectNameCaseSensitive(String objectPath) throws DirectoryNotFoundException, IOException {
        if(objectPath == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectPath" }));
        }
        char[] internalPathChars = toInternalNameChars(objectPath.substring(0, objectPath.lastIndexOf(DIRECTORY_SEPARATOR) + 1), null);
        int internalPathLength = Array.indexOf(0, internalPathChars, 0, 0);
        if(internalPathLength <= 3)
        {
            return false;
        }
        {
            long findHandle = Kernel.findFirstFile(internalPathChars.getPointer(), fldDummyFindData.getPointer());
            if(findHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
            {
            default:
                throw new IOException(avt.io.package.getResourceString("io"));
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new DirectoryNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.directory")) {
                    directoryName = new String(internalPathChars, 0, internalPathLength - (internalPathLength <= 4 ? 1 : 2))
                };
            }
            if(!Kernel.findClose(findHandle))
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        return false;
    }

    public boolean isReadOnly() throws DirectoryNotFoundException, IOException {
        return false;
    }

    public boolean isReadOnly(String objectPath) throws DirectoryNotFoundException, IOException {
        if(objectPath == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectPath" }));
        }
        char[] internalPathChars = toInternalNameChars(objectPath.substring(0, objectPath.lastIndexOf(DIRECTORY_SEPARATOR) + 1), null);
        int internalPathLength = Array.indexOf(0, internalPathChars, 0, 0);
        if(internalPathLength <= 3)
        {
            return false;
        }
        {
            long findHandle = Kernel.findFirstFile(internalPathChars.getPointer(), fldDummyFindData.getPointer());
            if(findHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
            {
            default:
                throw new IOException(avt.io.package.getResourceString("io"));
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new DirectoryNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.directory")) {
                    directoryName = new String(internalPathChars, 0, internalPathLength - (internalPathLength <= 4 ? 1 : 2))
                };
            }
            if(!Kernel.findClose(findHandle))
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
        }
        return getReadOnlyPathLength(internalPathChars) > 0;
    }

    public boolean isInternalNameFull(String internalName) {
        if(internalName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "internalName" }));
        }
        int nlength = internalName.length;
        return nlength <= 0 || nlength >= 3 && isDriveLetter(internalName[0]) && internalName[1] == INTERNAL_DRIVE_SEPARATOR && internalName[2] == INTERNAL_DIRECTORY_SEPARATOR;
    }

    public boolean isInternalNameValid(String internalName) {
        if(internalName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "internalName" }));
        }
        int nlength = internalName.length;
        if(nlength <= 0) return true;
        if(nlength > MAX_PATH - 1) return false;
        int beginIndex = nlength >= 3 && isDriveLetter(internalName[0]) && internalName[1] == INTERNAL_DRIVE_SEPARATOR && internalName[2] == INTERNAL_DIRECTORY_SEPARATOR ? 3 : 0;
        int apos = internalName.indexOf(INTERNAL_ANY_OBJECT);
        if(
            (
                internalName.indexOf('\0') & internalName.indexOf('<') & internalName.indexOf('>') &
                internalName.indexOf('\"') & internalName.indexOf('?') & internalName.indexOf('|') &
                internalName.indexOf(DIRECTORY_SEPARATOR) &
                internalName.indexOf(INTERNAL_DRIVE_SEPARATOR, beginIndex)
            ) >= 0 || apos >= 0 && apos < nlength - 1 ||
            internalName.indexOf("" + INTERNAL_DIRECTORY_SEPARATOR + INTERNAL_DIRECTORY_SEPARATOR) >= 0 ||
            nlength > beginIndex && internalName[nlength - 1] == INTERNAL_DIRECTORY_SEPARATOR ||
            apos > 0 && internalName[apos - 1] != INTERNAL_DIRECTORY_SEPARATOR
        ) return false;
        for(beginIndex--; beginIndex < nlength; )
        {
            int endIndex = internalName.indexOf(INTERNAL_DIRECTORY_SEPARATOR, ++beginIndex);
            if(endIndex < 0) endIndex = nlength;
            String component = internalName.substring(beginIndex, endIndex);
            if(component.equals(".") || component.equals("..")) return false;
            beginIndex = endIndex;
        }
        return true;
    }

    public boolean isObjectNameValid(String objectName) {
        if(objectName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectName" }));
        }
        int nlength = objectName.length;
        if(nlength > MAX_PATH - 1) return false;
        int beginIndex = 0;
        if(objectName.startsWith("" + DIRECTORY_SEPARATOR))
        {
            if(nlength < 2) return true;
            if(nlength < 3 || !isDriveLetter(objectName[1]) || objectName[2] != INTERNAL_DRIVE_SEPARATOR || nlength > 3 && objectName[3] != DIRECTORY_SEPARATOR) return false;
            beginIndex = 4;
        }
        if(
            (
                objectName.indexOf('\0') & objectName.indexOf('<') & objectName.indexOf('>') &
                objectName.indexOf('\"') & objectName.indexOf('?') & objectName.indexOf('|') &
                objectName.indexOf(INTERNAL_ANY_OBJECT) &
                objectName.indexOf(INTERNAL_DIRECTORY_SEPARATOR) &
                objectName.indexOf(INTERNAL_DRIVE_SEPARATOR, beginIndex)
            ) >= 0 ||
            objectName.indexOf("" + DIRECTORY_SEPARATOR + DIRECTORY_SEPARATOR) >= 0
        ) return false;
        for(beginIndex--; beginIndex < nlength; )
        {
            int endIndex = objectName.indexOf(DIRECTORY_SEPARATOR, ++beginIndex);
            if(endIndex < 0) endIndex = nlength;
            String component = objectName.substring(beginIndex, endIndex);
            if(component.equals(".") || component.equals("..")) return false;
            beginIndex = endIndex;
        }
        return true;
    }

    public int getObjectNameMaximumLength() {
        return MAX_PATH - 1;
    }

    public String toInternalName(String objectName) {
        if(objectName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectName" }));
        }
        /*  Преобразование полных и неполных стандартных имён объектов во внутренние по следующей схеме:
            /           =>  
            /d:         =>  D:\
            /d:/        =>  D:\*
            /d:/obj     =>  D:\obj
            /d:/dir/    =>  D:\dir\*
            /d:/dir/obj =>  D:\dir\obj
                        =>  *
            obj         =>  obj
            dir/        =>  dir\*
            dir/obj     =>  dir\obj
        */
        int nlength = objectName.length;
        if(nlength > MAX_PATH - 1)
        {
            throw new ObjectNameTooLongException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"));
        }
        int beginIndex = 0;
        int rlength = 0;
        char[] result = new char[MAX_PATH];
        if(objectName.startsWith("" + DIRECTORY_SEPARATOR))
        {
            if(nlength < 2)
            {
                return "";
            }
            char letter = objectName[1];
            if(nlength < 3 || !isDriveLetter(letter) || objectName[2] != INTERNAL_DRIVE_SEPARATOR || nlength > 3 && objectName[3] != DIRECTORY_SEPARATOR)
            {
                throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-syntax"));
            }
            result[0] = Char.toUpperCase(letter);
            result[1] = INTERNAL_DRIVE_SEPARATOR;
            result[2] = INTERNAL_DIRECTORY_SEPARATOR;
            rlength = 3;
            beginIndex = 4;
        }
        if((
            objectName.indexOf('\0') & objectName.indexOf('<') & objectName.indexOf('>') &
            objectName.indexOf('\"') & objectName.indexOf('?') & objectName.indexOf('|') &
            objectName.indexOf(INTERNAL_ANY_OBJECT) &
            objectName.indexOf(INTERNAL_DIRECTORY_SEPARATOR) &
            objectName.indexOf(INTERNAL_DRIVE_SEPARATOR, beginIndex)
        ) >= 0)
        {
            throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-characters"));
        }
        if(objectName.indexOf("" + DIRECTORY_SEPARATOR + DIRECTORY_SEPARATOR) >= 0)
        {
            throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-syntax"));
        }
        for(beginIndex--; beginIndex < nlength; )
        {
            int endIndex = objectName.indexOf(DIRECTORY_SEPARATOR, ++beginIndex);
            if(endIndex < 0) endIndex = nlength;
            int clength = endIndex - beginIndex;
            String component = objectName.substring(beginIndex, endIndex);
            if(component.equals(".") || component.equals(".."))
            {
                throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-syntax"));
            }
            if(clength <= 0)
            {
                clength = (component = "" + INTERNAL_ANY_OBJECT).length;
            }
            component.getChars(0, clength, result, rlength);
            rlength += clength;
            if(endIndex < nlength)
            {
                result[rlength++] = INTERNAL_DIRECTORY_SEPARATOR;
            }
            beginIndex = endIndex;
        }
        return new String(result, 0, rlength);
    }

    public String toObjectName(String internalName) {
        if(internalName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "internalName" }));
        }
        /*  Преобразование полных и неполных внутренних имён объектов в стандартные по следующей схеме:
                        =>  /
            D:\         =>  /D:
            D:\*        =>  /D:/
            D:\obj      =>  /D:/obj
            D:\dir\*    =>  /D:/dir/
            D:\dir\obj  =>  /D:/dir/obj
            *           =>  
            obj         =>  obj
            dir\*       =>  dir/
            dir\obj     =>  dir/obj
        */
        int nlength = internalName.length;
        if(nlength <= 0)
        {
            return "" + DIRECTORY_SEPARATOR;
        }
        if(nlength > MAX_PATH - 1)
        {
            throw new ObjectNameTooLongException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.too-long"));
        }
        char letter = internalName[0];
        int beginIndex = 0;
        int rlength = 0;
        char[] result = new char[MAX_PATH];
        if(nlength >= 3 && isDriveLetter(letter) && internalName[1] == INTERNAL_DRIVE_SEPARATOR && internalName[2] == INTERNAL_DIRECTORY_SEPARATOR)
        {
            result[0] = DIRECTORY_SEPARATOR;
            result[1] = Char.toUpperCase(letter);
            result[2] = INTERNAL_DRIVE_SEPARATOR;
            rlength = 3;
            if(nlength > 3) result[rlength++] = DIRECTORY_SEPARATOR;
            beginIndex = 3;
        }
        int apos = internalName.indexOf(INTERNAL_ANY_OBJECT);
        if((
            internalName.indexOf('\0') & internalName.indexOf('<') & internalName.indexOf('>') &
            internalName.indexOf('\"') & internalName.indexOf('?') & internalName.indexOf('|') &
            internalName.indexOf(DIRECTORY_SEPARATOR) &
            internalName.indexOf(INTERNAL_DRIVE_SEPARATOR, beginIndex)
        ) >= 0 || apos >= 0 && apos < nlength - 1)
        {
            throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-characters"));
        }
        if(
            internalName.indexOf("" + INTERNAL_DIRECTORY_SEPARATOR + INTERNAL_DIRECTORY_SEPARATOR) >= 0 ||
            nlength > beginIndex && internalName[nlength - 1] == INTERNAL_DIRECTORY_SEPARATOR ||
            apos > 0 && internalName[apos - 1] != INTERNAL_DIRECTORY_SEPARATOR
        )
        {
            throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-syntax"));
        }
        for(beginIndex--; beginIndex < nlength; )
        {
            int endIndex = internalName.indexOf(INTERNAL_DIRECTORY_SEPARATOR, ++beginIndex);
            if(endIndex < 0) endIndex = nlength;
            int clength = endIndex - beginIndex;
            String component = internalName.substring(beginIndex, endIndex);
            if(component.equals(".") || component.equals(".."))
            {
                throw new IllegalObjectNameException(platform.independent.filesystem.package.getResourceString("illegal-argument.object-name.illegal-syntax"));
            }
            if(clength == 1 && component[0] == INTERNAL_ANY_OBJECT)
            {
                clength = (component = "").length;
            }
            component.getChars(0, clength, result, rlength);
            rlength += clength;
            if(endIndex < nlength)
            {
                result[rlength++] = DIRECTORY_SEPARATOR;
            }
            beginIndex = endIndex;
        }
        return rlength <= 0 ? "" : new String(result, 0, rlength);
    }

    public ObjectEnumeration findFirst() throws ObjectNotFoundException, IOException {
        return new DriveEnumeration();
    }

    public ObjectEnumeration findFirst(String objectPath) throws ObjectNotFoundException, IOException {
        if(objectPath == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "objectPath" }));
        }
        char[] internalNameChars = toInternalNameChars(objectPath, null);
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 2)
        {
            return new DriveEnumeration();
        }
        if(internalNameLength == 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) {
                    objectName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            return new DriveInfo(new String(internalNameChars, 0, 2));
        }
        if(internalNameLength == 4 && internalNameChars[3] == INTERNAL_ANY_OBJECT)
        {
            internalNameChars[--internalNameLength] = '\0';
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) {
                    objectName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            return new ObjectInDriveRootEnumeration(internalNameChars);
        }
        {
            Win32FindData internalFindData = new Win32FindData();
            long findHandle = Kernel.findFirstFile(internalNameChars.getPointer(), internalFindData.getPointer());
            if(findHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
            {
            default:
                throw new IOException(avt.io.package.getResourceString("io"));
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new ObjectNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.object")) {
                    objectName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            return new ObjectInDirectoryEnumeration(findHandle, internalFindData);
        }
    }

    public ByteWriter createFile(String fileName) throws ReadOnlyFileSystemException, FileCreationException, IOException {
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        char[] internalNameChars = toInternalNameChars(fileName, "createFile");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
            throw new FileCreationException(platform.independent.filesystem.package.getResourceString("file.creation")) {
                fileName = new String(internalNameChars, 0, internalNameLength)
            };
        }
        {
            int internalNameReadOnlyLength = getReadOnlyPathLength(internalNameChars);
            if(internalNameReadOnlyLength > 0)
            {
                throw new ReadOnlyFileSystemException(platform.independent.filesystem.package.getResourceString("file-system.read-only")) {
                    directoryName = new String(internalNameChars, 0, internalNameReadOnlyLength)
                };
            }
            long fileHandle = Kernel.createFile(internalNameChars.getPointer(), Kernel.GENERIC_WRITE, 0, 0, Kernel.CREATE_NEW, Kernel.FILE_FLAG_RANDOM_ACCESS, 0);
            if(fileHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
            {
            default:
                if(Kernel.getLastStatus() != Kernel.STATUS_FILE_IS_A_DIRECTORY)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
                /* падение через */
            case Kernel.ERROR_FILE_EXISTS:
            case Kernel.ERROR_ALREADY_EXISTS:
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new FileCreationException(platform.independent.filesystem.package.getResourceString("file.creation")) {
                    fileName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            return new FileOutputStream(fileHandle, CLOSEABLE | SEEKABLE | TRUNCATABLE);
        }
    }

    public ByteWriter rewriteFile(String fileName) throws ReadOnlyFileSystemException, FileCreationException, IOException {
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        char[] internalNameChars = toInternalNameChars(fileName, "rewriteFile");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new IOException(avt.io.package.getResourceString("io"));
            }
            throw new FileCreationException(platform.independent.filesystem.package.getResourceString("file.creation")) {
                fileName = new String(internalNameChars, 0, internalNameLength)
            };
        }
        {
            int internalNameReadOnlyLength = getReadOnlyPathLength(internalNameChars);
            if(internalNameReadOnlyLength > 0)
            {
                throw new ReadOnlyFileSystemException(platform.independent.filesystem.package.getResourceString("file-system.read-only")) {
                    directoryName = new String(internalNameChars, 0, internalNameReadOnlyLength)
                };
            }
            long fileHandle = Kernel.createFile(internalNameChars.getPointer(), Kernel.GENERIC_WRITE, 0, 0, Kernel.CREATE_ALWAYS, Kernel.FILE_FLAG_RANDOM_ACCESS, 0);
            if(fileHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
            {
            default:
                if(Kernel.getLastStatus() != Kernel.STATUS_FILE_IS_A_DIRECTORY)
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
                /* падение через */
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new FileCreationException(platform.independent.filesystem.package.getResourceString("file.creation")) {
                    fileName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            return new FileOutputStream(fileHandle, CLOSEABLE | SEEKABLE | TRUNCATABLE);
        }
    }

    public ByteWriter openFileForAppend(String fileName) throws ReadOnlyFileSystemException, FileNotFoundException, FileOpeningException, IOException {
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        char[] internalNameChars = toInternalNameChars(fileName, "openFileForAppend");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) {
                    fileName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            throw new FileOpeningException(platform.independent.filesystem.package.getResourceString("file.opening.append")) {
                fileName = new String(internalNameChars, 0, internalNameLength)
            };
        }
        {
            int internalNameReadOnlyLength = getReadOnlyPathLength(internalNameChars);
            if(internalNameReadOnlyLength > 0)
            {
                throw new ReadOnlyFileSystemException(platform.independent.filesystem.package.getResourceString("file-system.read-only")) {
                    directoryName = new String(internalNameChars, 0, internalNameReadOnlyLength)
                };
            }
            long fileHandle = Kernel.createFile(internalNameChars.getPointer(), Kernel.GENERIC_WRITE, 0, 0, Kernel.OPEN_ALWAYS, Kernel.FILE_FLAG_RANDOM_ACCESS, 0);
            if(fileHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
            {
            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 = new String(internalNameChars, 0, internalNameLength)
                };
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) {
                    fileName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            ByteWriter result = new FileOutputStream(fileHandle, CLOSEABLE | SEEKABLE | TRUNCATABLE);
            ((SeekExtension) result.getExtension(SeekExtension.class)).seek(0, SeekExtension.END);
            return result;
        }
    }

    public ByteReader openFileForRead(String fileName) throws FileNotFoundException, FileOpeningException, IOException {
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        char[] internalNameChars = toInternalNameChars(fileName, "openFileForRead");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) {
                    fileName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            throw new FileOpeningException(platform.independent.filesystem.package.getResourceString("file.opening.read")) {
                fileName = new String(internalNameChars, 0, internalNameLength)
            };
        }
        {
            long fileHandle = Kernel.createFile(internalNameChars.getPointer(), Kernel.GENERIC_READ, Kernel.FILE_SHARE_READ, 0, Kernel.OPEN_EXISTING, Kernel.FILE_FLAG_RANDOM_ACCESS, 0);
            if(fileHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
            {
            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 = new String(internalNameChars, 0, internalNameLength)
                };
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) {
                    fileName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            return new FileInputStream(fileHandle, CLOSEABLE | SEEKABLE);
        }
    }

    public ByteStream openFile(String fileName) throws ReadOnlyFileSystemException, FileNotFoundException, FileOpeningException, IOException {
        if(fileName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "fileName" }));
        }
        char[] internalNameChars = toInternalNameChars(fileName, "openFile");
        int internalNameLength = Array.indexOf(0, internalNameChars, 0, 0);
        if(internalNameLength <= 3)
        {
            if((long) Kernel.getDiskFreeSpaceEx(internalNameChars.getPointer()) == 0)
            {
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) {
                    fileName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            throw new FileOpeningException(platform.independent.filesystem.package.getResourceString("file.opening")) {
                fileName = new String(internalNameChars, 0, internalNameLength)
            };
        }
        {
            int internalNameReadOnlyLength = getReadOnlyPathLength(internalNameChars);
            if(internalNameReadOnlyLength > 0)
            {
                throw new ReadOnlyFileSystemException(platform.independent.filesystem.package.getResourceString("file-system.read-only")) {
                    directoryName = new String(internalNameChars, 0, internalNameReadOnlyLength)
                };
            }
            long fileHandle = Kernel.createFile(internalNameChars.getPointer(), Kernel.GENERIC_READ | Kernel.GENERIC_WRITE, 0, 0, Kernel.OPEN_ALWAYS, Kernel.FILE_FLAG_RANDOM_ACCESS, 0);
            if(fileHandle == Kernel.INVALID_HANDLE_VALUE) switch(Kernel.getLastError())
            {
            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 = new String(internalNameChars, 0, internalNameLength)
                };
            case Kernel.ERROR_FILE_NOT_FOUND:
            case Kernel.ERROR_PATH_NOT_FOUND:
                throw new FileNotFoundException(platform.independent.filesystem.package.getResourceString("not-found.file")) {
                    fileName = new String(internalNameChars, 0, internalNameLength)
                };
            }
            return new FileBidirectStream(fileHandle);
        }
    }

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

    public int currentOffsetInMillis() {
        TimeZoneInformation tzinfo = new TimeZoneInformation();
        Kernel.getTimeZoneInformation(tzinfo.getPointer());
        return -60000 * tzinfo.bias;
    }

    public long currentTimeInMillis() {
        SystemTime time = new SystemTime();
        Kernel.getSystemTime(time.getPointer());
        int yer;
        int year = yer = time.year - 1 & 0xffff;
        int month = time.month - 1;
        int day = time.dayOfMonth - 1;
        int hour = time.hour;
        int minute = time.minute;
        int second = time.second;
        int millisecond = time.millisecond;
        int days = 146097 * (year / 400);
        year %= 400;
        days += 36524 * (year / 100);
        year %= 100;
        days += 1461 * (year / 4) + 365 * (year % 4) + day;
        for(int mnt = 0; mnt < month; mnt++) days += getDaysCount(yer, mnt);
        return days * 86400000L + hour * 3600000L + minute * 60000L + second * 1000L + millisecond;
    }

    public String[] getEnvironmentVariables() {
        long2 env = Kernel.getEnvironmentStrings();
        long envPointer = (long) env;
        int envLength = (int) env[1];
        if(envPointer != 0 && envLength > 1) try
        {
            int length = 0;
            try
            {
                char[] envChars = (char[]) char[].class.newArrayAt(envPointer, envLength);
                for(int index = 0; (index = Array.indexOf(0, envChars, index, 0)) >= 0; index++) length++;
                String[] result = new String[length];
                for(int beginIndex = length = 0; beginIndex < envLength; )
                {
                    int endIndex = Array.indexOf(0, envChars, beginIndex, 0);
                    result[length++] = new String(envChars, beginIndex, endIndex - beginIndex);
                    beginIndex = endIndex + 1;
                }
                return result;
            }
            catch(Exception exception)
            {
                throw exception instanceof RuntimeException ? (RuntimeException) exception : new RuntimeException(exception.message, exception);
            }
        } finally
        {
            Kernel.freeEnvironmentStrings(envPointer);
        }
        return new String[0];
    }

    public String[] arguments { read = fldArguments }

    public ByteReader standardInput { read = fldStandardInput }

    public ByteWriter standardOutput { read = fldStandardOutput }

    public ByteWriter standardError { read = fldStandardError }

    public String consoleInputCharsetName { read = fldConsoleInputCharsetName }

    public String consoleOutputCharsetName { read = fldConsoleOutputCharsetName }

    public String currentDirectory { read = getCurrentDirectory }

    public void operator []=(String environmentVariableName, String environmentVariableValue) {
        if(environmentVariableName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "environmentVariableName" }));
        }
        if(environmentVariableValue == null)
        {
            int nameLength = environmentVariableName.length;
            if(nameLength < MAX_ENV && (environmentVariableName.indexOf('=') & environmentVariableName.indexOf('\0')) < 0)
            {
                char[] nameChars = new char[MAX_ENV];
                environmentVariableName.getChars(0, nameLength, nameChars, 0);
                Kernel.setEnvironmentVariable(nameChars.getPointer(), 0);
            }
        } else
        {
            int nameLength = environmentVariableName.length;
            int valueLength = environmentVariableValue.length;
            if(nameLength < MAX_ENV && valueLength < MAX_ENV && (environmentVariableName.indexOf('=') & environmentVariableName.indexOf('\0') & environmentVariableValue.indexOf('\0')) < 0)
            {
                char[] nameChars = new char[MAX_ENV];
                char[] valueChars = new char[MAX_ENV];
                environmentVariableName.getChars(0, nameLength, nameChars, 0);
                environmentVariableValue.getChars(0, valueLength, valueChars, 0);
                Kernel.setEnvironmentVariable(nameChars.getPointer(), valueChars.getPointer());
            }
        }
    }

    public String operator [](String environmentVariableName) {
        if(environmentVariableName == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "environmentVariableName" }));
        }
        {
            int nameLength = environmentVariableName.length;
            if(nameLength < MAX_ENV && (environmentVariableName.indexOf('=') & environmentVariableName.indexOf('\0')) < 0)
            {
                char[] nameChars = new char[MAX_ENV];
                char[] valueChars = new char[MAX_ENV];
                environmentVariableName.getChars(0, nameLength, nameChars, 0);
                int valueLength = Kernel.getEnvironmentVariable(nameChars.getPointer(), valueChars.getPointer(), valueChars.length);
                return Kernel.getLastError() == Kernel.ERROR_ENVVAR_NOT_FOUND ? null : new String(valueChars, 0, valueLength);
            }
        }
        return null;
    }

    private String getCurrentDirectory() {
        char[] internalNameChars = new char[MAX_PATH];
        int internalNameLength = Kernel.getCurrentDirectory(internalNameChars.length, internalNameChars.getPointer());
        if(internalNameLength < 3 || internalNameLength > MAX_PATH - 1)
        {
            throw new RuntimeException(platform.dependent.package.getResourceString("current-directory.get"));
        }
        String internalName = new String(internalNameChars, 0, internalNameLength);
        if(!isInternalNameFull(internalName))
        {
            throw new RuntimeException(platform.dependent.package.getResourceString("current-directory.get"));
        }
        return toObjectName(internalName);
    }
}

package class Win32Event(Event)
{
    private static int internalCounter = 0x007fffff;

    private static native int getInternalCounterValue();

    private static int writeStringToCharArray(String value, char[] array, int index) {
        int length = value.length;
        value.getChars(0, length, array, index);
        return index + length;
    }

    private static int writeLongToCharArray(long value, char[] array, int index) {
        for(array[index++] = '.', int bits = 60; bits >= 0; bits -= 5) array[index++] = Char.toChar((int) (value >> bits) & 0x1f);
        return index;
    }

    private long fldEventHandle;

    public (long threadId): super(threadId, new CriticalSection()) {  }

    public void setSignalled() { Kernel.setEvent(fldEventHandle); }

    public void waitSignalled(int timeInMillis) { Kernel.waitForSingleObject(fldEventHandle, timeInMillis <= 0 ? Kernel.INFINITE : timeInMillis); }

    protected void afterConstruction() {
        char[] name = new char[0x50];
        int index = writeStringToCharArray("Event", name, 0);
        index = writeLongToCharArray(Kernel.getCurrentProcessId(), name, index);
        index = writeLongToCharArray(Kernel.getCurrentThreadId(), name, index);
        index = writeLongToCharArray(System.currentTimeInMillis(), name, index);
        index = writeLongToCharArray(System.identityHashCode(this), name, index);
        writeLongToCharArray(getInternalCounterValue(), name, index);
        fldEventHandle = Kernel.createEvent(0, false, false, name.getPointer());
    }

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

class FileStreamExtension(Object, Extension)
{
    protected long fldFileHandle;

    protected (long fileHandle) {
        fldFileHandle = fileHandle;
    }
}

service FileStreamPositioningExtension(FileStreamExtension, SeekExtension, LimitedSizeExtension)
{
    public long seek(long offset, int from) throws IOException {
        if(from < BEGIN || from > END)
        {
            throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument"), new Object[] { "from" }));
        }
        long fileHandle = fldFileHandle;
        if(fileHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        long filePointer = Kernel.setFilePointer(fileHandle, offset, from);
        if(filePointer == Kernel.INVALID_SET_FILE_POINTER)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        return filePointer;
    }

    public long size() throws IOException {
        long fileHandle = fldFileHandle;
        if(fileHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        long fileSize = Kernel.getFileSize(fileHandle);
        if(fileSize == Kernel.INVALID_FILE_SIZE)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        return fileSize;
    }

    public long available() throws IOException {
        long fileHandle = fldFileHandle;
        if(fileHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        long fileSize = Kernel.getFileSize(fileHandle);
        if(fileSize == Kernel.INVALID_FILE_SIZE)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        long filePointer = Kernel.setFilePointer(fileHandle, 0, CURRENT);
        if(filePointer == Kernel.INVALID_SET_FILE_POINTER)
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
        return fileSize - filePointer;
    }
}

service FileStreamTruncatingExtension(FileStreamExtension, TruncateExtension)
{
    public void truncate() throws IOException {
        long fileHandle = fldFileHandle;
        if(fileHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        if(!Kernel.setEndOfFile(fileHandle))
        {
            throw new IOException(avt.io.package.getResourceString("io"));
        }
    }
}

class FileStream(Object, Constants, Closeable, Extendable)
{
    protected long fldFileHandle;
    protected final boolean fldIsCloseable;
    protected final FileStreamExtension[] fldExtensions;

    protected (long fileHandle, int features) {
        fldFileHandle = fileHandle;
        fldIsCloseable = (features & CLOSEABLE) != 0;
        switch(features & (TRUNCATABLE | SEEKABLE))
        {
        default:
            fldExtensions = new FileStreamExtension[] {  };
            break;
        case SEEKABLE:
            fldExtensions = new FileStreamExtension[] { new FileStreamPositioningExtension(fileHandle) };
            break;
        case TRUNCATABLE:
            fldExtensions = new FileStreamExtension[] { new FileStreamTruncatingExtension(fileHandle) };
            break;
        case TRUNCATABLE | SEEKABLE:
            fldExtensions = new FileStreamExtension[] { new FileStreamTruncatingExtension(fileHandle), new FileStreamPositioningExtension(fileHandle) };
        }
    }

    protected (long fileHandle, int features, FileStreamExtension[] extensions) {
        fldFileHandle = fileHandle;
        fldIsCloseable = (features & CLOSEABLE) != 0;
        fldExtensions = extensions;
    }

    public void close() throws IOException {
        if(fldIsCloseable)
        {
            long fileHandle = fldFileHandle;
            if(fileHandle != Kernel.INVALID_HANDLE_VALUE)
            {
                if(!Kernel.closeHandle(fileHandle))
                {
                    throw new IOException(avt.io.package.getResourceString("io"));
                }
                clearHandlers();
            }
        }
    }

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

    protected void beforeDestruction() {
        if(fldIsCloseable)
        {
            long fileHandle = fldFileHandle;
            if(fileHandle != Kernel.INVALID_HANDLE_VALUE) Kernel.closeHandle(fileHandle);
        }
    }

    protected void clearHandlers() {
        for(fldFileHandle = Kernel.INVALID_HANDLE_VALUE, FileStreamExtension[] extensions = fldExtensions, int index = extensions.length; index-- > 0; )
        {
            extensions[index].fldFileHandle = Kernel.INVALID_HANDLE_VALUE;
        }
    }
}

class FileInputStream(FileStream, ByteReader)
{
    public (long stdHandle): super(stdHandle, 0) {  }

    public (long fileHandle, int features): super(fileHandle, features) {  }

    public (long fileHandle, int features, FileStreamExtension[] extensions): super(fileHandle, features, extensions) {  }

    public int read() throws IOException {
        long fileHandle = fldFileHandle;
        if(fileHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        int2 result = Kernel.readFile(fileHandle, 0);
        if((int) result == 0)
        {
            throw new IOException(avt.io.package.getResourceString("io.read"));
        }
        return result[1];
    }

    public int read(byte[] dst, int offset, int length) throws IOException {
        if(dst == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "dst" }));
        }
        Array.checkBounds(dst, offset, length);
        long fileHandle = fldFileHandle;
        if(fileHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        if(length <= 0) return 0;
        int2 result = Kernel.readFile(fileHandle, dst.getPointer() + offset, length, 0);
        if((int) result == 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 {
        SeekExtension positioning = (SeekExtension) getExtension(SeekExtension.class);
        return positioning == null ? ByteReader.super.skip(bytesQuantity) : bytesQuantity <= 0 ? 0 : -positioning.position() + positioning.seek(bytesQuantity, SeekExtension.CURRENT);
    }
}

class FileOutputStream(FileStream, ByteWriter)
{
    public (long stdHandle): super(stdHandle, 0) {  }

    public (long fileHandle, int features): super(fileHandle, features) {  }

    public (long fileHandle, int features, FileStreamExtension[] extensions): super(fileHandle, features, extensions) {  }

    public void write(int byteData) throws IOException {
        long fileHandle = fldFileHandle;
        if(fileHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        int2 result = Kernel.writeFile(fileHandle, byteData, 0);
        if((int) result == 0 || result[1] != 1)
        {
            throw new IOException(avt.io.package.getResourceString("io.write"));
        }
    }

    public void write(byte[] src, int offset, int length) throws IOException {
        if(src == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
        }
        Array.checkBounds(src, offset, length);
        long fileHandle = fldFileHandle;
        if(fileHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        if(length <= 0) return;
        int2 result = Kernel.writeFile(fileHandle, src.getPointer() + offset, length, 0);
        if((int) result == 0 || result[1] != length)
        {
            throw new IOException(avt.io.package.getResourceString("io.write"));
        }
    }

    public void flush() throws IOException {
        long fileHandle = fldFileHandle;
        if(fileHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new ClosedFileException(platform.independent.filesystem.package.getResourceString("closed-file"));
        }
        if(!Kernel.flushFileBuffers(fileHandle))
        {
            throw new IOException(avt.io.package.getResourceString("io.write"));
        }
    }
}

class FileBidirectStream(FileStream, ByteStream)
{
    private final FileInputStream fldReader;
    private final FileOutputStream fldWriter;

    public (long fileHandle): super(fileHandle, CLOSEABLE | TRUNCATABLE | SEEKABLE) {
        FileStreamExtension[] extensions = fldExtensions;
        fldReader = new FileInputStream(fileHandle, 0, new FileStreamExtension[] { extensions[1] });
        fldWriter = new FileOutputStream(fileHandle, 0, extensions);
    }

    public ByteReader reader { read = fldReader }

    public ByteWriter writer { read = fldWriter }

    protected void clearHandlers() {
        super.clearHandlers();
        fldReader.fldFileHandle = Kernel.INVALID_HANDLE_VALUE;
        fldWriter.fldFileHandle = Kernel.INVALID_HANDLE_VALUE;
    }
}

class Win32ObjectAttributes(Object, Constants, Attributes)
{
    private static void stringAttributeIdIsInvalid(String attributeId) {
        if(attributeId == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "attributeId" }));
        }
        throw new IllegalArgumentException(String.format(
            platform.independent.filesystem.package.getResourceString(attributeId.startsWith("s") ? "illegal-argument.attribute-id" : "illegal-argument.attribute-type"), new Object[] { attributeId }
        ));
    }

    private static int booleanAttributeIdToIndex(String attributeId) {
        if(attributeId == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "attributeId" }));
        }
        if(attributeId.equals(B_DIRECTORY)) return 4;
        if(attributeId.equals(B_READ_ONLY)) return 0;
        if(attributeId.equals(B_HIDDEN)) return 1;
        if(attributeId.equals(B_SYSTEM)) return 2;
        if(attributeId.equals(B_ARCHIVE)) return 5;
        throw new IllegalArgumentException(String.format(
            platform.independent.filesystem.package.getResourceString(attributeId.startsWith("b") ? "illegal-argument.attribute-id" : "illegal-argument.attribute-type"), new Object[] { attributeId }
        ));
    }

    private static int longAttributeIdToIndex(String attributeId) {
        if(attributeId == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "attributeId" }));
        }
        if(attributeId.equals(L_LAST_ACCESS_TIME)) return 1;
        if(attributeId.equals(L_LAST_WRITE_TIME)) return 2;
        if(attributeId.equals(L_CREATION_TIME)) return 0;
        throw new IllegalArgumentException(String.format(
            platform.independent.filesystem.package.getResourceString(attributeId.startsWith("l") ? "illegal-argument.attribute-id" : "illegal-argument.attribute-type"), new Object[] { attributeId }
        ));
    }

    protected int fldAttributes;
    protected final long[] fldTimes;

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

    public void setBooleanAttribute(String attributeId, boolean attributeValue) {
        int mask = 1 << booleanAttributeIdToIndex(attributeId);
        fldAttributes = attributeValue ? fldAttributes | mask : fldAttributes & ~mask;
    }

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

    public void setStringAttribute(String attributeId, String attributeValue) {
        stringAttributeIdIsInvalid(attributeId);
    }

    public boolean isSupportedAttributeId(String attributeId) {
        return attributeId != null && (
            attributeId.equals(B_DIRECTORY) ||
            attributeId.equals(B_READ_ONLY) ||
            attributeId.equals(B_HIDDEN) ||
            attributeId.equals(B_SYSTEM) ||
            attributeId.equals(B_ARCHIVE) ||
            attributeId.equals(L_LAST_ACCESS_TIME) ||
            attributeId.equals(L_LAST_WRITE_TIME) ||
            attributeId.equals(L_CREATION_TIME)
        );
    }

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

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

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

    public String displayName(String attributeId) {
        if(attributeId == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "attributeId" }));
        }
        if(attributeId.equals(B_DIRECTORY)) return platform.independent.filesystem.package.getResourceString("display-name.object-attributes.directory");
        if(attributeId.equals(B_READ_ONLY)) return platform.independent.filesystem.package.getResourceString("display-name.object-attributes.read-only");
        if(attributeId.equals(B_HIDDEN)) return package.getResourceString("display-name.object-attributes.hidden");
        if(attributeId.equals(B_SYSTEM)) return package.getResourceString("display-name.object-attributes.system");
        if(attributeId.equals(B_ARCHIVE)) return package.getResourceString("display-name.object-attributes.archive");
        if(attributeId.equals(L_LAST_ACCESS_TIME)) return platform.independent.filesystem.package.getResourceString("display-name.object-attributes.last-access-time");
        if(attributeId.equals(L_LAST_WRITE_TIME)) return platform.independent.filesystem.package.getResourceString("display-name.object-attributes.last-write-time");
        if(attributeId.equals(L_CREATION_TIME)) return package.getResourceString("display-name.object-attributes.creation-time");
        throw new IllegalArgumentException(String.format(platform.independent.filesystem.package.getResourceString("illegal-argument.attribute-id"), new Object[] { attributeId }));
    }

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

class Win32ObjectEnumeration(ObjectEnumeration, Constants)
{
    protected (): super(new Win32ObjectAttributes()) {  }

    public boolean findNext() throws ObjectEnumerationException, IOException {
        return false;
    }

    protected void fillRootAttributes(String rootName) {
        name = rootName;
        size = 0;
        setBooleanAttribute(B_DIRECTORY, true);
        setBooleanAttribute(B_READ_ONLY, false);
        setBooleanAttribute(B_ARCHIVE, false);
        setBooleanAttribute(B_HIDDEN, false);
        setBooleanAttribute(B_SYSTEM, true);
        setLongAttribute(L_LAST_ACCESS_TIME, Long.MIN_VALUE);
        setLongAttribute(L_LAST_WRITE_TIME, Long.MIN_VALUE);
        setLongAttribute(L_CREATION_TIME, Long.MIN_VALUE);
    }

    protected void fillDriveAttributes(String driveName) {
        name = driveName;
        size = 0;
        setBooleanAttribute(B_DIRECTORY, true);
        setBooleanAttribute(B_READ_ONLY, false);
        setBooleanAttribute(B_ARCHIVE, true);
        setBooleanAttribute(B_HIDDEN, false);
        setBooleanAttribute(B_SYSTEM, true);
        setLongAttribute(L_LAST_ACCESS_TIME, Long.MIN_VALUE);
        setLongAttribute(L_LAST_WRITE_TIME, Long.MIN_VALUE);
        setLongAttribute(L_CREATION_TIME, Long.MIN_VALUE);
    }

    protected void fillObjectAttributes(Win32FindData findData) {
        int attributes = findData.dwFileAttributes;
        char[] nameChars = findData.cFileName;
        int nameLength = Array.indexOf(0, nameChars, 0, 0);
        if(nameLength < 0) nameLength = MAX_PATH;
        name = new String(nameChars, 0, nameLength);
        size = ####findData.nFileSizeLow | ^^^^findData.nFileSizeHigh;
        setBooleanAttribute(B_DIRECTORY, (attributes & Kernel.FILE_ATTRIBUTE_DIRECTORY) != 0);
        setBooleanAttribute(B_READ_ONLY, (attributes & Kernel.FILE_ATTRIBUTE_READONLY) != 0);
        setBooleanAttribute(B_ARCHIVE, (attributes & Kernel.FILE_ATTRIBUTE_ARCHIVE) != 0);
        setBooleanAttribute(B_HIDDEN, (attributes & Kernel.FILE_ATTRIBUTE_HIDDEN) != 0);
        setBooleanAttribute(B_SYSTEM, (attributes & Kernel.FILE_ATTRIBUTE_SYSTEM) != 0);
        setLongAttribute(L_LAST_ACCESS_TIME, toObjectTime(findData.ftLastAccessTime));
        setLongAttribute(L_LAST_WRITE_TIME, toObjectTime(findData.ftLastWriteTime));
        setLongAttribute(L_CREATION_TIME, toObjectTime(findData.ftCreationTime));
    }
}

class DriveInfo(Win32ObjectEnumeration)
{
    public (String driveName) {
        fillDriveAttributes(driveName);
    }
}

class DriveEnumeration(Win32ObjectEnumeration)
{
    private final char[] fldDriveChars;

    public () {
        fillRootAttributes(".");
        fldDriveChars = new char[] { 'A', INTERNAL_DRIVE_SEPARATOR, INTERNAL_DIRECTORY_SEPARATOR, '\0' };
    }

    public boolean findNext() throws ObjectEnumerationException, IOException {
        for(char[] driveChars = fldDriveChars, long drivePointer = driveChars.getPointer(); driveChars[0] <= 'Z'; driveChars[0]++) if((long) Kernel.getDiskFreeSpaceEx(drivePointer) != 0)
        {
            fillDriveAttributes(new String(driveChars, 0, 2));
            driveChars[0]++;
            return true;
        }
        return false;
    }
}

class CustomObjectEnumeration(Win32ObjectEnumeration)
{
    protected long fldFindHandle;
    protected Win32FindData fldFindData;

    protected () {  }

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

    public boolean findNext() throws ObjectEnumerationException, IOException {
        long findHandle = fldFindHandle;
        if(findHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            throw new ClosedEnumerationException(platform.independent.filesystem.package.getResourceString("closed-enumeration"));
        }
        Win32FindData findData = fldFindData;
        if(Kernel.findNextFile(findHandle, findData.getPointer()))
        {
            fillObjectAttributes(findData);
            return true;
        }
        if(Kernel.getLastError() != Kernel.ERROR_NO_MORE_FILES)
        {
            throw new ObjectEnumerationException(platform.independent.filesystem.package.getResourceString("object.enumeration"));
        }
        return false;
    }

    protected void beforeDestruction() {
        long findHandle = fldFindHandle;
        if(findHandle != Kernel.INVALID_HANDLE_VALUE) Kernel.findClose(findHandle);
    }
}

class ObjectInDriveRootEnumeration(CustomObjectEnumeration)
{
    private boolean fldFindStatus;
    private final char[] fldDriveChars;

    public (char[] driveChars) {
        fillDriveAttributes(".");
        fldFindHandle = Kernel.INVALID_HANDLE_VALUE;
        fldFindData = new Win32FindData();
        fldDriveChars = driveChars;
    }

    public boolean findNext() throws ObjectEnumerationException, IOException {
        if(!fldFindStatus)
        {
            if((long) Kernel.getDiskFreeSpaceEx(fldDriveChars.getPointer()) != 0)
            {
                fillRootAttributes("..");
                return fldFindStatus = true;
            }
            throw new ObjectEnumerationException(platform.independent.filesystem.package.getResourceString("object.enumeration"));
        }
        if(fldFindHandle == Kernel.INVALID_HANDLE_VALUE)
        {
            char[] driveChars = fldDriveChars;
            Win32FindData findData = fldFindData;
            driveChars[3] = INTERNAL_ANY_OBJECT;
            if((fldFindHandle = Kernel.findFirstFile(driveChars.getPointer(), findData.getPointer())) != Kernel.INVALID_HANDLE_VALUE)
            {
                fillObjectAttributes(findData);
                return true;
            }
            if(Kernel.getLastError() != Kernel.ERROR_FILE_NOT_FOUND)
            {
                throw new ObjectEnumerationException(platform.independent.filesystem.package.getResourceString("object.enumeration"));
            }
            return false;
        }
        return super.findNext();
    }
}

class ObjectInDirectoryEnumeration(CustomObjectEnumeration)
{
    public (long findHandle, Win32FindData findData) {
        fillObjectAttributes(findData);
        fldFindHandle = findHandle;
        fldFindData = findData;
    }
}