Blog. Just Blog

Получение списка удаленных файлов в Корзине

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Удалять файлы в Корзину мы уже научились, теперь давайте разберем, как можно получить список удаленных объектов, которые в этой Корзине находятся. С чего начнем? Ну конечно же с описания кучи структур, интерфейсов и констант, которые нам понадобятся.
  1. ; GUID {43826D1E-E718-42EE-BC55-A1E261C37BFE}
  2. IID_IShellItem      dd 043826D1Eh
  3.                     dw 0E718h
  4.                     dw 042EEh
  5.                     db 0BCh, 055h, 0A1h, 0E2h, 061h, 0C3h, 07Bh, 0FEh
  6.  
  7. ; GUID {93F2F68C-1D1B-11D3-A30E-00C04F79ABD1}
  8. IID_IShellFolder2   dd 093F2F68Ch
  9.                     dw 01D1Bh
  10.                     dw 011D3h
  11.                     db 0A3h, 00Eh, 000h, 0C0h, 04Fh, 079h, 0ABh, 0D1h
  12.  
  13. ; IID_IShellFolder2 Interface
  14. struct IShellFolder2
  15.     QueryInterface      dd ?
  16.     AddRef              dd ?
  17.     Release             dd ?
  18.  
  19.     ; IShellFolder
  20.     ParseDisplayName    dd ?
  21.     EnumObjects         dd ?
  22.     BindToObject        dd ?
  23.     BindToStorage       dd ?
  24.     CompareIDs          dd ?
  25.     CreateViewObject    dd ?
  26.     GetAttributesOf     dd ?
  27.     GetUIObjectOf       dd ?
  28.     GetDisplayNameOf    dd ?
  29.     SetNameOf           dd ?
  30.  
  31.     ; IShellFolder2
  32.     GetDefaultSearchGUID  dd ?
  33.     EnumSearches          dd ?
  34.     GetDefaultColumn      dd ?
  35.     GetDefaultColumnState dd ?
  36.     GetDetailsEx          dd ?
  37.     GetDetailsOf          dd ?
  38.     MapColumnToSCID       dd ?
  39. ends
  40.  
  41. ; IID_IEnumIDList Interface
  42. struct IEnumIDList
  43.     QueryInterface      dd ?
  44.     AddRef              dd ?
  45.     Release             dd ?
  46.  
  47.     Next                dd ?
  48.     Skip                dd ?
  49.     Reset               dd ?
  50.     Clone               dd ?
  51. ends
  52.  
  53. struct STRRET
  54.     uType dd ?
  55.     union
  56.         pOleStr dd ?
  57.         uOffset dd ?
  58.         cStr    rb 260
  59.     ends
  60. ends
  61.  
  62. struct SHCOLUMNID
  63.      fmtid rb 16
  64.      pid   dd ?
  65. ends
  66.  
  67. S_OK               = 0
  68. CSIDL_BITBUCKET    = 0Ah
  69. SHCONTF_FOLDERS    = 20h
  70. SHCONTF_NONFOLDERS = 40h
  71. SHGDN_NORMAL       = 0
  72. SHGDN_INFOLDER     = 1
  73. SHGDN_FOREDITING   = 1000h
  74. SHGDN_FORPARSING   = 8000h
  75. PID_DISPLACED_FROM = 2
  76. PID_DISPLACED_DATE = 3
  77. PKEY_SIZE          = 12
  78.  
  79. PSGUID_DISPLACED   dd 09B174B33h
  80.                    dw 040FFh
  81.                    dw 011D2h
  82.                    db 0A2h, 07Eh, 000h, 0C0h, 04Fh, 0C3h, 008h, 071h
  83.  
  84. PKEY_Size dd 0B725F130h
  85.           dw 047EFh
  86.           dw 0101Ah
  87.           db 0A5h, 0F1h, 002h, 060h, 08Ch, 09Eh, 0EBh, 0ACh
Для доступа к Корзине сперва надо получить объект рабочего стола, а уже через него определить объект Корзины. После этого поочередно получаем объекты ее содержимого и выполняем с ними нужные действия.
  1.         ; Инициализировать COM-объект
  2.         invoke  CoInitialize,NULL
  3.         invoke  SHGetSpecialFolderLocation,NULL,CSIDL_BITBUCKET,pidl
  4.         invoke  SHGetDesktopFolder,psfDesktop
  5.  
  6.         ; Получить объект папки Корзины
  7.         mov     eax,[psfDesktop]
  8.         mov     eax,[eax]
  9.         stdcall dword [eax+IShellFolder2.BindToObject],[psfDesktop],\
  10.                 [pidl],NULL,IID_IShellFolder2,psfRecycleBin
  11.  
  12.         ; Обработать содержимое Корзины
  13.         mov     eax,[psfRecycleBin]
  14.         mov     eax,[eax]
  15.         stdcall dword [eax+IShellFolder2.EnumObjects],[psfRecycleBin],\
  16.                 NULL,SHCONTF_FOLDERS+SHCONTF_NONFOLDERS,peidl
  17.  
  18. loc_next:
  19.         ; Очередной элемент содержимого Корзины
  20.         mov     eax,[peidl]
  21.         mov     eax,[eax]
  22.         stdcall dword [eax+IEnumIDList.Next],[peidl],1,pidlItem,NULL
  23.         ; Больше ничего нет
  24.         or      eax,eax
  25.         jnz     loc_done
  26.  
  27.         ; Выполнить необходимые действия с объектом
  28.         ...
  29.         ...
  30.         ...
  31.  
  32.         jmp     loc_next
  33.  
  34. loc_done:
  35.         ; Прибраться за собой
  36.         mov     eax, [psfRecycleBin]
  37.         mov     eax, [eax]
  38.         stdcall dword [eax+IShellFolder2.Release],[psfRecycleBin]
  39.  
  40.         mov     eax, [psfDesktop]
  41.         mov     eax, [eax]
  42.         stdcall dword [eax+IShellFolder2.Release],[psfDesktop]
  43.  
  44.         invoke  CoTaskMemFree,[pidl]
  45.  
  46.         ; Удалить объект
  47.         invoke  CoUninitialize
Получив очередной объект, можно узнать его свойства. Это может быть имя файла, его исходное месторасположение, нынешнее имя в Корзине, дата удаления, размер файла.

Самое простое - определение имени файла и путь его нахождения. Делается это с помощью метода GetDisplayNameOf интерфейса IShellFolder. Полученную структуру надо будет преобразовать в привычный строковый вид при помощи функции StrRetToStr.
  1.         ; Обычный формат представления
  2.         mov     eax,[psfRecycleBin]
  3.         mov     eax,[eax]
  4.         stdcall dword [eax+IShellFolder2.GetDisplayNameOf],[psfRecycleBin],\
  5.                 [pidlItem],SHGDN_NORMAL,strRet
  6.         ; Преобразовать строку в привычный вид
  7.         invoke  StrRetToStr,strRet,[pidlItem],spszName
  8.         ; [spszName] --> указатель на строку
  9.         ...
  10.         ...
  11.         invoke  CoTaskMemFree,[spszName]
  12.  
  13.         ; Формат представления относительно данной папки
  14.         mov     eax,[psfRecycleBin]
  15.         mov     eax,[eax]
  16.         stdcall dword [eax+IShellFolder2.GetDisplayNameOf],[psfRecycleBin],\
  17.                 [pidlItem],SHGDN_INFOLDER,strRet
  18.         invoke  StrRetToStr,strRet,[pidlItem],spszName
  19.         ; [spszName] --> указатель на строку
  20.         ...
  21.         ...
  22.         invoke  CoTaskMemFree,[spszName]
  23.  
  24.         ; Формат представления, используемый для дальнейшего разбора имени
  25.         mov     eax,[psfRecycleBin]
  26.         mov     eax,[eax]
  27.         stdcall dword [eax+IShellFolder2.GetDisplayNameOf],[psfRecycleBin],\
  28.                 [pidlItem],SHGDN_FORPARSING,strRet
  29.         invoke  StrRetToStr,strRet,[pidlItem],spszName
  30.         ; [spszName] --> указатель на строку
  31.         ...
  32.         ...
  33.         invoke  CoTaskMemFree,[spszName]
Чуть сложнее узнать дату удаления и исходное расположение файла. Это делается при помощи метода GetDetailsEx интерфейса IShellFolder2, передавая соответствующий идентификатор запрашиваемых данных. Тут дополнительно придется заполнять структуру SHCOLUMNID, а результат будет передан в указателе структуры VARIANT. Строка исключительно юникодная, но преобразовывать ее не надо, она возвращается в самом обычном виде.
  1.         ; Заполнить GUID в структуре SHCOLUMNID
  2.         mov     edi,pscid.fmtid
  3.         mov     esi,PSGUID_DISPLACED
  4.         movsd
  5.         movsd
  6.         movsd
  7.         movsd
  8.  
  9.         ; Место удаления
  10.         mov     [pscid.pid],PID_DISPLACED_FROM
  11.         mov     eax,[psfRecycleBin]
  12.         mov     eax,[eax]
  13.         stdcall dword [eax+IShellFolder2.GetDetailsEx],[psfRecycleBin],\
  14.                 [pidlItem],pscid,vt
  15.         invoke  VariantChangeType,vt,vt,0,VT_BSTR
  16.         ; [vt.lVal] --> адрес строки
  17.         ...
  18.         ...
  19.         invoke  VariantClear,vt
  20.  
  21.         ; Дата удаления
  22.         mov     [pscid.pid],PID_DISPLACED_DATE
  23.         mov     eax,[psfRecycleBin]
  24.         mov     eax,[eax]
  25.         stdcall dword [eax+IShellFolder2.GetDetailsEx],[psfRecycleBin],\
  26.                 [pidlItem],pscid,vt
  27.         invoke  VariantChangeType,vt,vt,0,VT_BSTR
  28.         ; [vt.lVal] --> адрес строки
  29.         ...
  30.         ...
  31.         invoke  VariantClear,vt
Размер удаленного файла можно получить также через расширенные свойства, только GUID будет другим, он берется из структуры System.Size, идентификатор данных берется оттуда же.
  1.         ; Заполнить GUID в структуре SHCOLUMNID
  2.         mov     edi,pscid.fmtid
  3.         mov     esi,PKEY_Size
  4.         movsd
  5.         movsd
  6.         movsd
  7.         movsd
  8.  
  9.         ; Размер файла
  10.         mov     [pscid.pid],PKEY_SIZE
  11.         mov     eax,[psfRecycleBin]
  12.         mov     eax,[eax]
  13.         stdcall dword [eax+IShellFolder2.GetDetailsEx],[psfRecycleBin],\
  14.                 [pidlItem],pscid,vt
  15.         invoke  VariantChangeType,vt,vt,0,VT_BSTR
  16.         ; [vt.lVal] --> адрес строки с размером файла
  17.         ...
  18.         ...
  19.         invoke  VariantClear,vt
Текста получилось много, но если разобраться, то ничего сложного. Похожим способом можно получить информацию о содержимом не только Корзины, но и любой другой папки на диске.

Для получения общей информации о количестве элементов в Корзине и занимаемом ими объеме можно воспользоваться стандартными функциями, а точнее функцией SHQueryRecycleBin:
  1. struct SHQUERYRBINFO
  2.         cbSize       dd ?
  3.         i64Size      dq ?
  4.         i64NumItems  dq ?
  5. ends
  6.  
  7. path db 'C:\',0
  8. rci   SHQUERYRBINFO
  9.  
  10.         ; Получить размер и количество элементов в Корзине
  11.         mov     [rci.cbSize],sizeof.SHQUERYRBINFO
  12.         invoke  SHQueryRecycleBin,path,rci
При успешном выполнении в структуре SHQUERYRBINFO окажутся два QWORD'а с количеством элементов в Корзине и их общим объемом в байтах. Для очисти содержимого Корзины используется функция SHEmptyRecycleBin:
  1.         ; Очистить Корзину без подтверждения
  2.         SHERB_NOCONFIRMATION = 0x00000001
  3.         invoke  SHEmptyRecycleBin,HWND_DESKTOP,path,SHERB_NOCONFIRMATION
Флагами настраивается поведение системы при удалении: надо ли выводить подтверждение или удалять молча, нужна ли анимация удаления и звуковое сопровождение процесса.

В приложении пример программы с исходным текстом, которая выводит список содержимого Корзины со всеми доступными свойствами каждого файла.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Recycle.Bin.Items.Demo.zip (7,161 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 1190 | Комментариев: 7

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (22.11.2020 в 15:03):
Добавил пример получения общего содержимого Корзины и пример очистки Корзины. Архив тоже обновлен.
Сергей Озеров (06.09.2020 в 00:07):
Огромное спасибо за пример! буду разбираться
ManHunter (01.09.2020 в 12:50):
Запросто, как минимум по расширению
Petya (01.09.2020 в 12:33):
А может ли в обычной папке NORMAL не совпадать с INFOLDER?
ManHunter (27.08.2020 в 13:05):
Сергей Озеров, вот тут https://www.upload.ee/files/12...der.zip.html пример с исходником, получает содержимое папки C:\Windows
ManHunter (27.08.2020 в 12:54):
Статью рисовать не буду, лениво :) Содержимое папки получаем примерно так:

        ; Инициализировать COM-объект
        invoke  CoInitialize,NULL
        invoke  SHGetDesktopFolder,psfDesktop

        ; Получить объект нужной папки
        ; ffname -> строка названия нужной папки в юникоде
        mov     eax,[psfDesktop]
        mov     eax,[eax]
        stdcall dword [eax+IShellFolder2.ParseDisplayName],[psfDesktop],\
                NULL,0,ffname,NULL,pidl,attr

        ; Получить объект папки
        mov     eax,[psfDesktop]
        mov     eax,[eax]
        stdcall dword [eax+IShellFolder2.BindToObject],[psfDesktop],\
                [pidl],NULL,IID_IShellFolder2,psfFolder

        ; Обработать содержимое папки
        mov     eax,[psfFolder]
        mov     eax,[eax]
        stdcall dword [eax+IShellFolder2.EnumObjects],[psfFolder],\
                NULL,SHCONTF_FOLDERS+SHCONTF_NONFOLDERS,peidl

loc_next:
        ; Очередной элемент содержимого папки
        mov     eax,[peidl]
        mov     eax,[eax]
        stdcall dword [eax+IEnumIDList.Next],[peidl],1,pidlItem,NULL
        ; Больше ничего нет
        or      eax,eax
        jnz     loc_done

        ...
        ...
        ...

        jmp     loc_next

loc_done:
        mov     eax, [psfFolder]
        mov     eax, [eax]
        stdcall dword [eax+IShellFolder2.Release],[psfFolder]

        mov     eax, [psfDesktop]
        mov     eax, [eax]
        stdcall dword [eax+IShellFolder2.Release],[psfDesktop]

        invoke  CoTaskMemFree,[pidl]

        ; Удалить объект
        invoke  CoUninitialize

Внутри все свойства получаются точно так же, кроме даты удаления и исходного месторасположения. Пустой SIZE - значит это папка, непустой - файл, если определять по-быстрому без лишних движений.
Сергей Озеров (27.08.2020 в 10:50):
ЦитатаПохожим способом можно получить информацию о содержимом не только Корзины, но и любой другой папки на диске

А можно пример? Спасибо.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.08 сек. / MySQL: 2 (0.0055 сек.) / Память: 4.5 Mb
Наверх