
Вдохновленсегодняшняя статья DailyWTF.
Автор утверждает, что файл C:\Program.exe
будет запущен при нажатии на ярлык, например, C:\Program Files\Doom 2\doom2.exe -nomusic
.
Предположительно, Windows сначала пытается вызвать C:\Program
с аргументами Files\Doom 2/doom2.exe -nomusic
.
Если нет C:\Program.exe
, то он пытается C:\Program Files\Doom
использовать аргументы 2/doom2.exe -nomusic
.
А если нет C:\Program Files\Doom.exe\
, то он наконец пытается C:\Program Files\Doom 2\doom2.exe -nomusic
и добивается успеха.
Мне это кажется полным бредом. Не могу поверить, что это когда-то работало таким образом.Комментатор выразился хорошо:
Мне трудно поверить, что какая-либо выпущенная версия Windows когда-либо использовала метод проб и ошибок, описанный автором.
Я абсолютно уверен, что выпущенная версия Windows имела поведение brain-dead по умолчанию. Я испытал это на себе много-много раз.
Во что я не верю, так это в то, что выпущенная версия Windows имелаэтотПоведение, граничащее с безмозглым поведением, как описано в статье. Это слишком большой недостаток безопасности, чтобы остаться незамеченным, пока случайный пост Daily WTF не раскрыл его, по крайней мере, десятилетие спустя, поскольку это должна была быть версия Windows, предшествующая XP.
Изменить для ясности:Вот как я это проверил сам.
- Скопируйте notepad.exe в C:\program.exe
- Запустите C:\program files\Internet explorer\iexplore.exe
- Открывается блокнот. Это ожидаемо, потому что он находит что-то под названием C:\program
- Переместить progam.exe в C:\program files\Internet.exe
- Запустите C:\program files\Internet explorer\iexplore.exe
По словам автора статьи (и эта статья от Microsoft), блокнот должен все равно открыться. Но этого не происходит, команда завершается сбоем с таким сообщением:
C:\program is not recognized as an internal or external command, operable program or batch file.
Опять же, я не обсуждаю утверждение статьи о том, что будет вызван C:\program. Я обсуждаю, что Windows рекурсивно пробует каждый каталог, пока не найдет совпадение.
Итак, работала ли когда-либо хоть одна версия Windows таким образом?
решение1
Все версии Windows, начиная с Windows 95 и до Windows 7, включающей добавление длинных имен файлов, работают таким образом.
Это поведениезадокументировано:
ThelpИмяПриложенияпараметр может бытьНУЛЕВОЙ. В этом случае имя модуля должно быть первым токеном, разделенным пробелом, в lpКомандная строкаstring. Если вы используете длинное имя файла, содержащее пробел, используйте строки в кавычках, чтобы указать, где заканчивается имя файла и начинаются аргументы; в противном случае имя файла будет неоднозначным. Например, рассмотрим строку "c:\program files\sub dir\program name". Эту строку можно интерпретировать несколькими способами. Система пытается интерпретировать возможности в следующем порядке:
c:\program.exe files\sub dir\program name c:\program files\sub.exe dir\program name c:\program files\sub dir\program.exe name c:\program files\sub dir\program name.exe
А почему он спрашивает именно так - чтобы онне нарушает работу программ, которые не могут правильно обрабатывать пробелы в именах файлов.
Редактировать
Похоже, команда "Run" не ведет себя так - в нее, должно быть, добавлена какая-то дополнительная логика для обработки именно этого случая. Однако попытка запустить ее из любого другого места - включая использование функции CreateProcess
напрямую, что большинство приложений используют для запуска команды.
Посмотрите на это поведение в действии:
- Откройте административную командную строку.
- Бегать:
copy c:\Windows\System32\notepad.exe c:\program.exe
- Бегать:
c:\Program Files\Internet Explorer\iexplore.exe
- Откроется Блокнот и сообщит, что не может найти
Files\Internet Explorer\iexplore.exe
- Введите текст
c:\Program Files\Internet Explorer\iexplore.exe
в поле «Выполнить», и IE откроется корректно.
Редактировать 2В случае вашего C:\program files\internet.exe
примера; я думаю, что это интерпретатор командной строки вмешивается. Он пытается обработать и разбить командную строку на параметры, разбитые пробелами. Поэтому он берет C:\program
первый токен и интерпретирует его как имя программы, а все остальное как параметры.
Для теста я создал небольшое приложение, которое вызывает CreateProcess
напрямую, и оно ведет себя точно так, как описано в документации. Ваш C:\program files\internet.exe
пример запустит C:\program files\internet.exe
. Так что, похоже, поведение зависит от того, как именно выполняется команда — что-то может обрабатывать командную строку перед передачей ее в CreateProcess
.
Пример программы:
#include <Windows.h>
void main()
{
STARTUPINFO si = {0};
si.cb= sizeof(si);
PROCESS_INFORMATION pi = {0};
CreateProcess(NULL, "c:\\program files\\internet explorer\\iexplore.exe",
NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
}
решение2
Я просто хочу кое-что добавить к предыдущим ответам.
Хотя возможно вызвать такое поведение усилием, плохим программированием (не RTFM) или непроверяемым идеальным штормом, вызванным этой конкретной антивирусной программой, ничто не вызвало бы поведение, описанное в статье. Абсолютно ни при каких обстоятельствах ярлык, созданный правильно, например, нацеленный на "C:\Program Files\Microsoft\Office\Word.exe" с кавычками, не запустит C:\Program.exe. То же самое и с Firefox. Черт, в принципе невозможно создать ярлык, который не будет экранирован должным образом, потому что это сделано разумно.
Если вы создадите ярлык на рабочем столе, указывающий на Firefox, он будет правильно экранирован. Если вы щелкните правой кнопкой мыши -> свойства и попытаетесь удалить кавычки, он автоматически вставит их, когда вы нажмете применить, даже если C:\Program.exe существует. Когда он это анализирует, я предполагаю, что он либо отдает предпочтение папке, либо рассматривает все до последнего '\' как часть пути. Только если вы вставите два пробела между Program и Files, он будет проанализирован как указывающий на C:\Program.exe с аргументами. Если вы можете редактировать ярлык в текстовом редакторе (это не простой текст), это может сработать.
Подобно сочетаниям клавиш, диалог «Выполнить» также правильно анализирует строку. Только в сравнительно низкоуровневой командной консоли он неправильно вызовет C:\Program.exe, но не попробует другие различные возможности. То есть, он неправильно попытается вызвать «C:\Program.exe», но не попытается вызвать «C:\Program Files\Internet.exe» или что-либо еще, даже если такие возможности существуют. Он вернет ошибку, сообщающую о том, что не может найти C:\Program.exe.
И в довершение всего, когда в папке C:\ есть Program.exe, он предупредит вас при запуске и спросит, хотите ли вы переименовать его. Это было проверено для XP, Vista, Windows 7, и теперь я могу проверить Windows 8 (http://goo.gl/eeNCp).Может бытьэто было возможно в Windows 9x, но я сомневаюсь.
По сути, это очевидно, и ни один программист Windows не допустит такой ошибки.