Что показалось плохим
Многие аспекты Win32 показались автору плохими. Первым среди них была сложность интерфейса. Похоже, что сложная модель защиты является причиной проблем с безопасностью, поскольку, вероятно, только эксперты в состоянии применить эту модель корректно.
Список экспортируемых имен показывает, что библиотека kernel32 включает около 675 функций; библиотека advapi32, определяющая интерфейс безопасности, содержит приблизительно 400 функций; библиотека users32, обеспечивающая интерфейс пользователя, содержит примерно 600 функций. Набор средств разработки включает более 225K строк включаемых файлов и поставляется вместе с 400 дополнительными динамически компонуемыми библиотеками.
Одним из примеров чрезмерной сложности является интерфейс CreateFile(). Этот интерфейс обеспечивает функциональность функции ОС UNIX open(). У функции CreateFile семь аргументов:
- pathname;
- access - битовая маска из трех или более бит;
- share - битовая маска чтения, записи, удаления;
- security - дескриптор безопасности + наследование;
- mode - пять режимов;
- flags_attr - восемь флагов + 11 атрибутов;
- template - хендл файла.
Имеется по меньшей мере 33,554,432 возможных комбинаций опций для данного путевого имени, не считая дескриптора безопасности и хендла файла.
Функция CreateProcess(), которая заменяет семейство функций fork() и exec() ОС UNIX, принимает десять аргументов; некоторые из них являются структурами, содержащими много полей. При наличии большого числа возможных комбинаций флагов отсутствует установка флага, которая обеспечивала бы функциональность семейства функций exec. Эти функции заменяют текущий процесс некоторым новым процессом. Реализация семейства exec ОС UNIX была одной из наиболее хитроумных задач.
Другим примером сложности может служить реестр (registry). Реестр служит для сбора в одном месте параметров конфигурирования и обеспечения к ним быстрого доступа. Реестр структурирован подобно файловой системе, но доступ обеспечивается оотдельным набором функций API. Реестр обладает бесчисленным количеством ключей, и их организацию часто трудно предсказать, тем более, что она различна для Windows 95 и Windows NT.
В дополнение к сложности, вторым плохим свойством API Win32 является его неполнота. Хендлы могут наследоваться одним процессом от другого или дублироваться, но отсутствует функция API, которая позволила бы по заданному хендлу определить его тип. Хотя функции ReadFile() и WriteFile() могут выполнять через хендл асинхронный ввод/вывод (только в Windows NT), этот хендл должен быть создан через вызов CreateFile() с флагом FILE_FLAG_OVERLAPPED. Более того, если хендл был создан с использованием этого флага, то синхронный ввод/вывод через этот хендл невозможен. При наличии этих ограничений отсутствуют функции API, которые позволили бы переустановить флаги или хотя бы узнать, какие флаги использовались при создании хендла.
Другим примером неполноты является невозможность управлять полным пространством имен файлов. В дополнение к отсутствию возможности создания каталогов и, в меньшей степени, файлов с именами, различающимися регистром букв, в интерфейсе Win32 не допускаются такие имена файлов как aux.c и com0.sh. Невозможно обеспечить доступ или создать файлы, которые заканчиваются точкой. API Win32 не обеспечивает вызов для создания жесткой ссылки, хотя в самой файловой системе NTFS такая возможность имеется.
Третим аспектом Win32, который автор считает плохим, является отсутствие согласованности. Этот аспект можно было бы считать "неприятным", а не "плохим", если бы он не являлся источником ошибок и не приводил к потребности траты времени на чтение руководств. В ОС UNIX тоже часто встречается несогласованность, и похоже, что разработчики Win32 не старались учиться на чужих ошибках. Одна из областей несогласованности API Win32 - это значения, возвращаемые функциями. Например, CreateFile() возвращает -1 при ошибке и хендл в противном случае. Функция CreateEvent() возвращает 0 при ошибке и хендл в противном случае. Функция RegCreateKey() возвращает код ошибки, а передается ей адрес хендла.
Использование аргументов тоже является несогласованным. Первым аргументом функции OpenProcess() является желаемый режим доступа.
Таким же образом обстоят дела с OpenEvent(). Однако в функции OpenProcessToken() желаемый режим доступа передается в качестве второго параметра.
В отличие от Windows 95, в интерфейсах Windows NT используется UNICODE, что позволяет хранить в этой кодировке имена файлов и других ресурсов, управляемых системой. К сожалению, вместо того, чтобы применять кодировку переменной длины UFT8, выбран способ представления символов в кодировке постоянной длины (16 бит). В результате отсутствует совместимость с 7-битовой кодировкой ASCII. Кроме того, приходится компилировать программы либо в расчете на UNICODE, либо в расчете на ASCII вместо того, чтобы применять некоторую унифицированную версию.
Другими плохими аспектами Windows NT, по мнению автора, являются планирование загрузки, необходимость в частых перезапусках и менталитет однопользовательской системы. Примером последнего является то, что когда пользователь входит в систему в рамках сессии telnet, то ftp приглашает ввести пароль на консоли, а не на терминале пользователя.