Сейчас на форуме: jinoweb (+4 невидимых)

 eXeL@B —› Программирование —› Получени пути
Посл.ответ Сообщение

Ранг: 2.0 (гость)
Активность: 0.04=0.04
Статус: Участник

Создано: 04 апреля 2020 22:41 · Поправил: AntiE
· Личное сообщение · #1

Здравствуйте.
Суть проблемы - при перетаскивании файла на окно программы нужно получить полный путь к файлу, казалось бы тривиальная задача, но на системах < десятки если путь длиннее MAX_PATH, IDataObject::GetData с CF_HDROP не отрабатывает.
Тут нужен какой-то финт, скорее всего путь "ломается" еще где-то на уровне ОС, до попадания объекта в приложение.

Поскольку у многих стоит свежая ОС и заморачиваться с тестами на виртуалках с Вин7 вам будет лень, на 10-ке можно воспроизвести немного иной вектор того же кейса - создать файл с "кривым" именем и тащить его, например:
echo.>"\\?\X:\ badname.txt "

На васме никто пока решения не нашел, решил попытать удачу здесь, надеясь на иной уровень знания ОС у местных спецов.



Ранг: 158.4 (ветеран), 123thx
Активность: 0.140.49
Статус: Участник

Создано: 04 апреля 2020 22:57
· Личное сообщение · #2

AntiE
Полное имя файла ни на одной винде не может быть больше MAX_PATH. Если ты попытаешься создать такой файл любыми штатными апи, то получишь ошибку и файл создан не будет. Если же ты вручную поизвращаешься над фс для создания такого файла, то это твои проблемы и система их хендлить не обязана.



Ранг: 173.8 (ветеран), 208thx
Активность: 0.120.36
Статус: Участник

Создано: 04 апреля 2020 23:02
· Личное сообщение · #3

rmn пишет:
Полное имя файла ни на одной винде не может быть больше MAX_PATH

Ну я бы MSDN почитал все же, даже на XP можно обычным CreateFile создать файл с путем сильно больше max_path



Ранг: 158.4 (ветеран), 123thx
Активность: 0.140.49
Статус: Участник

Создано: 04 апреля 2020 23:05
· Личное сообщение · #4

VOLKOFF
Ну, не знаю, что там сейчас пишут, я когда-то пробовал - не получалось. Разве что через сим(хард)-линки такое замутить можно.



Ранг: 590.6 (!), 408thx
Активность: 0.360.18
Статус: Модератор

Создано: 04 апреля 2020 23:11
· Личное сообщение · #5

rmn
In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function (GetFullPathNameW), and prepend "\?" to the path. For more information, see Naming a File.

У него специфическая проблема с драгидропом.

-----
старый пень




Ранг: 2.0 (гость)
Активность: 0.04=0.04
Статус: Участник

Создано: 04 апреля 2020 23:19 · Поправил: AntiE
· Личное сообщение · #6

Безусловно в описываемой ситуации в качестве IDropSource будет выступать любой файловый менеджер умеющий работать с длинными путями (штатный виндовый эксплорер их не умеет). Чтобы использовать их из кода на WinXP - Win8 достаточно в начало пути добавить префикс "\\?\" и писать на чистом WinAPI без програмных оберток вашего ЯП.

В хидерах сдк часто встречается конструкция WCHAR cFileName[ MAX_PATH ], возможно и OLE спотыкается на этом. Вот тут-то и нужно придумать способ поймать полный путь при перетаскивании.



Ранг: 590.6 (!), 408thx
Активность: 0.360.18
Статус: Модератор

Создано: 04 апреля 2020 23:20
· Личное сообщение · #7

AntiE пишет:
IDataObject::GetData с CF_HDROP не отрабатывает

А ты уверен что там CF_HDROP для такого случая кидается?
Подебажь внутрь
HRESULT QueryGetData(
FORMATETC *pformatetc
);
и попробуй найти что там в HGLOBAL -> STGMEDIUM

-----
старый пень




Ранг: 2.0 (гость)
Активность: 0.04=0.04
Статус: Участник

Создано: 04 апреля 2020 23:33 · Поправил: AntiE
· Личное сообщение · #8

r_e пишет:
А ты уверен что там CF_HDROP для такого случая кидается?


Ну я естественно предварительно проверяю формат через QueryGetData и только потом пытаюсь получить данные, так что да, уверен.

Вот вывод всех доступных форматов при перетаскивании файла из длинного пути:
Code:
  1. Shell IDList Array
  2. InShellDragLoop
  3. UsingDefaultDragImage
  4. DragImageBits
  5. DragContext
  6. CF_HDROP  <------
  7. FileName
  8. FileNameW


r_e пишет:
попробуй найти что там в HGLOBAL -> STGMEDIUM

STGMEDIUM заполняется вызовом IDataObject::GetData который собственно и фэйлится.

P.S.
Если вы тестируете на Win10 с файлом созданным командной строкой из первого поста, форматы будут точно такими же, однако из-за специфики имени файл будет восприниматься как директория и если это смущает, можно заменить невалидный символ с пробела на что-то еще итп. Хотя суть остается, в данном случае путь просто будет обрезаться и задача получить его целиком, в остальном все идентично.




Ранг: 590.6 (!), 408thx
Активность: 0.360.18
Статус: Модератор

Создано: 05 апреля 2020 10:16
· Личное сообщение · #9

AntiE пишет:
STGMEDIUM заполняется вызовом IDataObject::GetData который собственно и фэйлится.

Ну так и подебажь внутрь его, чтобы понять где фейлится и что там вообще есть.

-----
старый пень




Ранг: 173.8 (ветеран), 208thx
Активность: 0.120.36
Статус: Участник

Создано: 05 апреля 2020 21:09 · Поправил: VOLKOFF
· Личное сообщение · #10

r_e пишет:
чтобы понять где фейлится и что там вообще есть


Code:
  1. Call OLE32.DLL:IDataObject::GetData ( *pformatetcIn, *pmedium )         E_INVALIDARG     0x80070057 = Параметр задан неверно

В MSDN 'E_INVALIDARG' - The dwDirection value is not valid

Цепочка вызовов выглядит приблизительно так:

Code:
  1. ole32.IDataObject_GetData
  2.          ole32.IDataObject_GetData_Proxy
  3.                  ole32.IDataObject_RemoteGetData_Proxy
  4.                         rpcrt4.NdrClientCall3                        | << RET:E_INVALIDARG
  5.                               rpcrt4.MulNdrpInitializeContextFromProc
  6.                               rpcrt4.NdrpClientCall3
  7.                               rpcrt4.Ndr64pClientSetupTransferSyntax
  8.                               rpcrt4.NdrpClientInit
  9.                               rpcrt4.NdrpSizing
  10.                               rpcrt4.NdrExtpProxyGetBuffer
  11.                               rpcrt4.NdrpClientMarshal
  12.                               rpcrt4.NdrExtpProxySendReceive
  13.                               rpcrt4.NdrpClientUnMarshal
  14.                               rpcrt4.NdrUserMarshalUnmarshall
  15.                               rpcrt4.NdrpClientFinally


Хотя по логике вещей нужно сначала посмотреть источник на предмет формирования корректного IDataObject и проблема может быть там.

| Сообщение посчитали полезным: AntiE

Ранг: 2.0 (гость)
Активность: 0.04=0.04
Статус: Участник

Создано: 05 апреля 2020 23:03 · Поправил: AntiE
· Личное сообщение · #11

Действительно, насколько мне удалось отследить, OLE прерывает формирование пути в файловом менеджере по достижению MAX_PATH при начале перетаскивания файла и соответственно объект получается целевым окном уже не валидным.

Механизм стал более понятен, однако вопрос остается, есть ли способ "перехватить" весь этот процесс для получения полного пути, или задача не решаемая?



Ранг: 251.3 (наставник), 81thx
Активность: 0.140.11
Статус: Участник

Создано: 06 апреля 2020 09:54
· Личное сообщение · #12

Или я чего-то не понимаю, или OLE используется для передачи информации между приложениями.
Windows Explorer не поддерживает пути длиннее MAX_PATH, на этом ваши приключения заканчиваются.
Нельзя получить то, чего тебе не отправили.
Или вы с каким-то другим файловым менеджером проверяете?



Ранг: 63.5 (постоянный), 35thx
Активность: 0.290.96
Статус: Участник

Создано: 06 апреля 2020 11:02 · Поправил: _MBK_
· Личное сообщение · #13

Ну человек же на хакерский форум вопрос задал, возможно, он хочет некий подпольный способ в обход OLE влезть в память процесса и прочухать какой именно файл был последний раз схвачен мышкой
Смех смехом, но сейчас глянул последовательность действий, которую проделывает эксплорер с файловой системой и реестром при каждом выборе нового файла - это можно отследить снаружи безо всякого влезания в процесс.
Пока что данный способ единственный номинант на самое извращенное решение




Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 06 апреля 2020 17:10
· Личное сообщение · #14

Нельзя ли сабклассить окно и получать путь через WinAPI?

-----
Stuck to the plan, always think that we would stand up, never ran.



 eXeL@B —› Программирование —› Получени пути
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати