Blog. Just Blog

Быстрый поиск

Введите фрагмент названия статьи для поиска

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

22.08.2020 | Категория: Образ мышления: 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
Получив очередной объект, можно узнать его свойства. Это может быть имя файла, его исходное месторасположение, нынешнее имя в Корзине, дата удаления, размер файла.

Читать статью целиком »
Просмотров: 1188 | Комментариев: 7

Программное удаление файла в Корзину

18.08.2020 | Категория: Образ мышления: Assembler | Автор: ManHunter
Небольшой сниппет - удаление файла или группы файлов в Корзину. Делается это при помощи функции SHFileOperation, но сперва нам надо будет определить необходимую структуру SHFILEOPSTRUCT и несколько констант.
  1. struct SHFILEOPSTRUCT
  2.         hwnd                  dd ?
  3.         wFunc                 dd ?
  4.         pFrom                 dd ?
  5.         pTo                   dd ?
  6.         fFlags                dw ?
  7.         fAnyOperationsAborted dd ?
  8.         hNameMappings         dd ?
  9.         lpszProgressTitle     dd ?
  10. ends
  11.  
  12. FO_DELETE = 3h
  13.  
  14. FOF_ALLOWUNDO      = 40h
  15. FOF_NOCONFIRMATION = 10h
  16. FOF_SILENT         = 4h
Сам код очень простой. Указываем тип операции FO_DELETE, то есть удаление, в параметре pFrom передаем список объектов на удаление, флагами настраиваем поведение - удалять с возможностью отката (то есть в Корзину), не показывать никаких подтверждений и диалогов.
  1.         mov     [fos.hwnd],HWND_DESKTOP
  2.         mov     [fos.wFunc],FO_DELETE
  3.         mov     [fos.pFrom],fname
  4.         mov     [fos.fFlags],FOF_ALLOWUNDO+FOF_NOCONFIRMATION+FOF_SILENT
  5.         invoke  SHFileOperation,fos
Обратите внимание, что список объектов должен заканчиваться двойным нулевым символом, даже если удаляется один файл. Также при удалении файлов со съемных носителей они могут удаляться без попадания в Корзину, но это как и при удалении через Проводник Windows.

Читать статью целиком »
Просмотров: 1112 | Комментариев: 1

Использование мультимедийного таймера

16.08.2020 | Категория: Образ мышления: Assembler | Автор: ManHunter
Интересная разновидность системных событий - высокоточный мультимедийный таймер. Гарантированный интервал срабатывания мультимедийных таймеров - около 10 миллисекунд против 50 миллисекунд обычных таймеров, устанавливаемых при помощи функции SetTimer. Кроме того, мультимедийные таймеры позволяют использовать обработчики, которые будут срабатывать в нужные интервалы, тогда как сообщения WM_TIMER от обычных таймеров идут через общую очередь. Если главный поток подвис, заснул или продолжительное время реагирует на какое-нибудь тяжелое сообщение, то таймеру придется ожидать, пока обработчик дойдет до него. Таким образом, добиться предсказуемой периодичности таймера будет очень сложно. Мультимедийные таймеры выполняются в собственном потоке, поэтому лишены перечисленных недостатков.

Слова словами, но давайте проверим это на практике. Для этого в простом оконном приложении установим обычный таймер на интервал 1 миллисекунду, вместе с этим создадим мультимедийный таймер с таким же интервалом срабатывания. При каждом срабатывании каждого из этих таймеров будет увеличен соответствующий счетчик. По истечении определенного времени, например, 5 секунд, сравним результаты.

Обработчик окна будет выглядеть примерно так. Для удобства я оставил только минимально необходимый код.
  1.         cmp     [msg],WM_INITDIALOG
  2.         je      wminitdialog
  3.         cmp     [msg],WM_TIMER
  4.         je      wmtimer
  5.         ...
  6.         ...
  7. wminitdialog:
  8.         ; Обнулить счетчики
  9.         mov     [dCntTim],0
  10.         mov     [dCntMM],0
  11.  
  12.         ; Получить начальное время
  13.         invoke  GetTickCount
  14.         mov     [dTime],eax
  15.  
  16.         ; Установить обычный таймер на интервал 1 мс
  17.         invoke  SetTimer,[hwnddlg],1,1,NULL
  18.  
  19.         ; Установить мультимедийный таймер на интервал 1 мс
  20.         TIME_PERIODIC = 0x0001
  21.         invoke  timeSetEvent,1,1,TimeProc,777,TIME_PERIODIC
  22.  
  23.         ...
  24.         ...
  25. wmtimer:
  26.         ; Увеличить счетчик по событию WM_TIMER
  27.         inc     [dCntTim]
  28.  
  29.         ; Прошло 5 секунд?
  30.         invoke  GetTickCount
  31.         sub     eax,[dTime]
  32.         cmp     eax,5000
  33.         jb      processed
  34.         jmp     wmclose
  35.  
  36. wmclose:
  37.         ; Удалить оба счетчика
  38.         invoke  KillTimer,[hwnddlg],1
  39.         invoke  timeKillEvent,[hTimer]
При инициализации окна устанавливается обычный и мультимедийный таймеры, при получении сообщения WM_TIMER увеличиваем обычный счетчик, а в функции-обработчике высокоточного таймера увеличиваем мультимедийный счетчик.
  1. ;-----------------------------------------------------------
  2. ; Обработчик высокоточного таймера
  3. ;-----------------------------------------------------------
  4. proc TimeProc uTimerID:DWORD,uMsg:DWORD,dwUser:DWORD,dw1:DWORD,dw2:DWORD
  5.         ; Увеличить счетчик по системному событию
  6.         inc     [dCntMM]
  7.         ret
  8. endp
Ну и момент истины. По результатам тестирования выяснилось, что за 5 секунд обычный таймер вызывается всего около 320 раз, тогда как обработчик мультимедийного таймера вызывается четко не менее 5000 раз. Что и требовалось доказать.

Читать статью целиком »
Просмотров: 1205 | Комментариев: 4

Прячем ярлыки на рабочем столе

05.08.2020 | Категория: Образ мышления: Assembler | Автор: ManHunter
Очередная мелкая развлекушка на Ассемблере. Сегодня будем прятать все ярлыки на рабочем столе. Нам не понадобится никаких громоздких структур, объектов, интерфейсов и прочей паранормальщины. И что хорошо, фактически все ярлыки остаются на своих местах, ничего не надо потом восстанавливать, ведь при прятании просто скрывается дочерний элемент окна десктопа, в котором ярлыки находятся.
  1. ; Сегмент данных
  2. section '.data' data readable writeable
  3.  
  4. szProg db 'ProgMan',0
  5.  
  6. ; Сегмент кода
  7. section '.code' code readable executable
  8.         ...
  9.         invoke  FindWindow,szProg,NULL
  10.         invoke  GetWindow,eax,GW_CHILD
  11.         invoke  GetWindow,eax,GW_CHILD
  12.         ; Сохранить хэндл окна с ярлыками
  13.         mov     ebx,eax
  14.         ; Ярлыки показываются?
  15.         invoke  IsWindowVisible,ebx
  16.         or      eax,eax
  17.         jne     @f
  18.         ; Нет, показать
  19.         invoke  ShowWindow,ebx,SW_SHOW
  20.         jmp     loc_exit
  21. @@:
  22.         ; Да, скрыть
  23.         invoke  ShowWindow,ebx,SW_HIDE
  24. loc_exit:
При запуске первым делом ищется окно с названием класса "ProgMan", затем поочередно находятся его первое дочернее окно и дочернее окно этого окна. Именно в нем находится Listbox со всеми ярлыками. Затем проверяется видимость этого окна. Если ярлыки отображаются, то они будут спрятаны, ну и наоборот. Если повесить такую программу на какую-нибудь горячую клавишу, то получится этакий ультра-лайтовый вариант блокировки компьютера, чтобы временно скрыть содержимое рабочего стола от излишне любопытных глаз, не запрещая при этом возможность работы за компьютером. Или можно использовать как программу-шутку для пугания юзеров. Естественно, после перезагрузки все возвращается на свои места.

Читать статью целиком »
Просмотров: 1067 | Комментариев: 3

Перехват и обработка изменения заголовка окна другого приложения

03.08.2020 | Категория: Образ мышления: Assembler | Автор: ManHunter
В предыдущих примерах обработки системных событий мы рассматривали глобальные события, которые происходят во всей системе. Чтобы завершить эту тему, хотелось бы рассказать о системных событиях, ограниченных конкретным приложением. В качестве примера возьмем перехват и обработку изменения заголовка окна какого-нибудь приложения. Немного констант, некоторые из которых вы уже знаете.
  1. EVENT_OBJECT_NAMECHANGE = 0x800C
  2. WINEVENT_OUTOFCONTEXT   = 0x0000
  3. OBJID_WINDOW            = 0x0000
  4. CHILDID_SELF            = 0x0000
Процесс установки хука немного отличается по используемым параметрам. Чтобы связать обработчик с конкретным процессом, сперва надо получить идентификаторы этого процесса и потока. Для дочерних процессов это вообще не проблема, а для стороннего придется воспользоваться функцией GetWindowThreadProcessId, ведь хэндл обрабатываемого окна мы знаем. В SetWinEventHook указываем полученные идентификаторы.
  1.         ; Найти нужное окно
  2.         invoke  FindWindow,NULL,szName
  3.         ; Сохранить хэндл найденного окна
  4.         mov     [hExample],eax
  5.  
  6.         ; Получить идентификаторы процесса и потока, относящиеся к окну
  7.         invoke  GetWindowThreadProcessId,[hExample],pID
  8.         mov     [tID],eax
  9.  
  10.         ; Установить хук на системные события
  11.         invoke  SetWinEventHook,EVENT_OBJECT_NAMECHANGE,\
  12.                 EVENT_OBJECT_NAMECHANGE,NULL,WinEventProc,\
  13.                 [pID],[tID],WINEVENT_OUTOFCONTEXT
А вот обработчик изменился не сильно. Проверяем, что изменяемый объект - окно, что это действительно нужное нам окно, после этого каким-то образом реагируем на изменение его заголовка.
  1. proc WinEventProc hWinEventHook:DWORD, event:DWORD, hwnd:DWORD,\
  2.                   idObject:DWORD, idChild:DWORD, idEventThread:DWORD,\
  3.                   dwmsEventTime:DWORD
  4.         pusha
  5.         ; Изменяемый объект - окно?
  6.         cmp     [idObject],OBJID_WINDOW
  7.         jne     .loc_ret
  8.  
  9.         ; Изменяется само окно?
  10.         cmp     [idChild],CHILDID_SELF
  11.         jne     .loc_ret
  12.  
  13.         ; Точно-точно изменяется?
  14.         cmp     [event],EVENT_OBJECT_NAMECHANGE
  15.         jne     .loc_ret
  16.  
  17.         ; И меняется именно нужное окно?
  18.         mov     eax,[hwnd]
  19.         cmp     eax,[hExample]
  20.         jne     .loc_ret
  21.         ... 
  22.         ...
  23.         ; Выполняются какие-то действия по факту события
  24.         ... 
  25.         ... 
  26. .loc_ret:
  27.         popa
  28.         ret
  29. endp
Таким образом, например, можно доработать автокликалку для Total Commander, чтобы она висела в фоне и модифицировала заголовок окна программы, мгновенно убирая из него надпись "UNREGISTERED" в случае ее появления.

Безусловно, возможности и область применения системных событий не ограничиваются приведенными примерами. Зато теперь вы знаете, насколько это нужный и мощный инструмент, особенно при грамотном использовании.

Читать статью целиком »
Просмотров: 1065 | Комментариев: 0

01 ... 25 26 27 28 29 30 31 ... 70
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.11 сек. / MySQL: 3 (0.0205 сек.) / Память: 4.5 Mb
Наверх