Blog. Just Blog

Как получить список ярлыков на рабочем столе

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Как получить список ярлыков на рабочем столе
Как получить список ярлыков на рабочем столе

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

Начинаем с определения структур и констант, которые нам понадобятся для дальнейшей работы, но про которые FASM ничего не знает.
  1. struct DECIMAL
  2.     wReserved dw ?
  3.     union
  4.         struct
  5.             scale db ?
  6.             sign db ?
  7.         ends
  8.         signscale dw ?
  9.     ends
  10.     Hi32 dd ?
  11.     union
  12.         struct
  13.             Lo32 dd ?
  14.             Mid32 dd ?
  15.         ends
  16.         Lo64 dq ?
  17.     ends
  18. ends
  19.  
  20. struct VARIANT
  21.     union
  22.         struct
  23.             vt dw ?
  24.             wReserved rw 3
  25.             union
  26.                 llVal dq ?
  27.                 lVal  dd ?
  28.                 iVal  dw ?
  29.                 bVal  db ?
  30.             ends
  31.         ends
  32.         decVal DECIMAL
  33.     ends
  34. ends
  35.  
  36. struct STRRET
  37.     uType dd ?
  38.     union
  39.         pOleStr dd ?
  40.         uOffset dd ?
  41.         cStr    rb 260
  42.     ends
  43. ends
  44.  
  45. CLSCTX_INPROC_SERVER  = 0x01
  46. CLSCTX_INPROC_HANDLER = 0x02
  47. CLSCTX_LOCAL_SERVER   = 0x04
  48. CLSCTX_REMOTE_SERVER  = 0x10
  49.  
  50. CLSCTX_SERVER = CLSCTX_INPROC_SERVER + CLSCTX_LOCAL_SERVER\
  51.                 + CLSCTX_REMOTE_SERVER
  52. CLSCTX_ALL    = CLSCTX_INPROC_HANDLER + CLSCTX_SERVER
  53. S_OK          = 0
  54.  
  55. SWC_DESKTOP     = 8
  56. SWFO_NEEDDISPATCH = 1
  57. CSIDL_DESKTOP   = 0x0000
  58. SVGIO_ALLVIEW   = 2
  59. SHGDN_NORMAL    = 0
  60.  
  61. VT_EMPTY            = 0
  62. VT_NULL             = 1
  63. VT_I2               = 2
  64. VT_I4               = 3
  65. VT_R4               = 4
  66. VT_R8               = 5
  67. VT_CY               = 6
  68. VT_DATE             = 7
  69. VT_BSTR             = 8
  70. VT_DISPATCH         = 9
  71. VT_ERROR            = 10
  72. VT_BOOL             = 11
  73. VT_VARIANT          = 12
  74. VT_UNKNOWN          = 13
  75. VT_DECIMAL          = 14
  76. VT_I1               = 16
  77. VT_UI1              = 17
  78. VT_UI2              = 18
  79. VT_UI4              = 19
  80. VT_I8               = 20
  81. VT_UI8              = 21
  82. VT_INT              = 22
  83. VT_UINT             = 23
  84. VT_VOID             = 24
  85. VT_HRESULT          = 25
  86. VT_PTR              = 26
  87. VT_SAFEARRAY        = 27
  88. VT_CARRAY           = 28
  89. VT_USERDEFINED      = 29
  90. VT_LPSTR            = 30
  91. VT_LPWSTR           = 31
  92. VT_RECORD           = 36
  93. VT_INT_PTR          = 37
  94. VT_UINT_PTR         = 38
  95. VT_FILETIME         = 64
  96. VT_BLOB             = 65
  97. VT_STREAM           = 66
  98. VT_STORAGE          = 67
  99. VT_STREAMED_OBJECT  = 68
  100. VT_STORED_OBJECT    = 69
  101. VT_BLOB_OBJECT      = 70
  102. VT_CF               = 71
  103. VT_CLSID            = 72
  104. VT_VERSIONED_STREAM = 73
  105. VT_BSTR_BLOB        = 0x0FFF
  106. VT_VECTOR           = 0x1000
  107. VT_ARRAY            = 0x2000
  108. VT_BYREF            = 0x4000
  109. VT_RESERVED         = 0x8000
  110. VT_ILLEGAL          = 0xFFFF
  111. VT_ILLEGALMASKED    = 0x0FFF
  112. VT_TYPEMASK         = 0x0FFF
Теперь GUID для работы с COM-объектами и интерфейсы этих объектов. Я реально задолбался собирать это все по интернету, хорошо, что этим приходится заниматься только один раз, потом можно будет использовать готовые решения.
  1. ; GUID {9BA05972-F6A8-11CF-A442-00A0C90A8F39}
  2. CLSID_ShellWindows      dd 09BA05972h
  3.                         dw 0F6A8h
  4.                         dw 011CFh
  5.                         db 0A4h, 042h, 000h, 0A0h, 0C9h, 00Ah, 08Fh, 039h
  6.  
  7. ; GUID {85CB6900-4D95-11CF-960C-0080C7F4EE85}
  8. IID_IShellWindows       dd 085CB6900h
  9.                         dw 04D95h
  10.                         dw 011CFh
  11.                         db 096h, 00Ch, 000h, 080h, 0C7h, 0F4h, 0EEh, 085h
  12.  
  13. ; GUID {4C96BE40-915C-11CF-99D3-00AA004AE837}
  14. CLSID_STopLevelBrowser  dd 04C96BE40h
  15.                         dw 0915Ch
  16.                         dw 011CFh
  17.                         db 099h, 0D3h, 000h, 0AAh, 000h, 04Ah, 0E8h, 037h
  18.  
  19. ; GUID {000214E2-0000-0000-C000-000000000046}
  20. IID_IShellBrowser       dd 0000214E2h
  21.                         dw 00000h
  22.                         dw 00000h
  23.                         db 0C0h, 000h, 000h, 000h, 000h, 000h, 000h, 046h
  24.  
  25. ; GUID {CDE725B0-CCC9-4519-917E-325D72FAB4CE}
  26. IID_IFolderView         dd 0CDE725B0h
  27.                         dw 0CCC9h
  28.                         dw 04519h
  29.                         db 091h, 07Eh, 032h, 05Dh, 072h, 0FAh, 0B4h, 0CEh
  30.  
  31. ; GUID {000214E6-0000-0000-C000-000000000046}
  32. IID_IShellFolder        dd 0000214E6h
  33.                         dw 00000h
  34.                         dw 00000h
  35.                         db 0C0h, 000h, 000h, 000h, 000h, 000h, 000h, 046h
  36.  
  37. ; GUID {000214F2-0000-0000-C000-000000000046}
  38. IID_IEnumIDList         dd 0000214F2h
  39.                         dw 00000h
  40.                         dw 00000h
  41.                         db 0C0h, 000h, 000h, 000h, 000h, 000h, 000h, 046h
  42.  
  43. ; IID_IShellWindows Interface
  44. struct IShellWindows
  45.     QueryInterface      dd ?
  46.     AddRef              dd ?
  47.     Release             dd ?
  48.  
  49.     GetTypeInfoCount    dd ?
  50.     GetTypeInfo         dd ?
  51.     GetIDsOfNames       dd ?
  52.     _Invoke             dd ?
  53.  
  54.     ; Properties
  55.     get_Count           dd ?
  56.  
  57.     ; IShellWindows
  58.     Item                dd ?
  59.     _NewEnum            dd ?
  60.     Register            dd ?
  61.     RegisterPending     dd ?
  62.     Revoke              dd ?
  63.     OnNavigate          dd ?
  64.     OnActivated         dd ?
  65.     FindWindowSW        dd ?
  66.     OnCreated           dd ?
  67.     ProcessAttachDetach dd ?
  68. ends
  69.  
  70. ; IID_IShellBrowser Interface
  71. struct IShellBrowser
  72.     QueryInterface      dd ?
  73.     AddRef              dd ?
  74.     Release             dd ?
  75.  
  76.     GetWindow           dd ?
  77.     ContextSensitiveHelp dd ?
  78.     InsertMenusSB       dd ?
  79.     SetMenuSB           dd ?
  80.     RemoveMenusSB       dd ?
  81.     SetStatusTextSB     dd ?
  82.     EnableModelessSB    dd ?
  83.     TranslateAcceleratorSB dd ?
  84.     BrowseObject        dd ?
  85.     GetViewStateStream  dd ?
  86.     GetControlWindow    dd ?
  87.     SendControlMsg      dd ?
  88.     QueryActiveShellView dd ?
  89.     OnViewWindowActive  dd ?
  90.     SetToolbarItems     dd ?
  91. ends
  92.  
  93. ; IID_IShellFolder Interface
  94. struct IShellFolder
  95.     QueryInterface      dd ?
  96.     AddRef              dd ?
  97.     Release             dd ?
  98.  
  99.     ParseDisplayName    dd ?
  100.     EnumObjects         dd ?
  101.     BindToObject        dd ?
  102.     BindToStorage       dd ?
  103.     CompareIDs          dd ?
  104.     CreateViewObject    dd ?
  105.     GetAttributesOf     dd ?
  106.     GetUIObjectOf       dd ?
  107.     GetDisplayNameOf    dd ?
  108.     SetNameOf           dd ?
  109. ends
  110.  
  111. ; IID_IFolderView Interface
  112. struct IFolderView
  113.     QueryInterface      dd ?
  114.     AddRef              dd ?
  115.     Release             dd ?
  116.  
  117.     GetCurrentViewMode  dd ?
  118.     SetCurrentViewMode  dd ?
  119.     GetFolder           dd ?
  120.     Item                dd ?
  121.     ItemCount           dd ?
  122.     Items               dd ?
  123.     GetSelectionMarkedItem dd ?
  124.     GetFocusedItem      dd ?
  125.     GetItemPosition     dd ?
  126.     GetSpacing          dd ?
  127.     GetDefaultSpacing   dd ?
  128.     GetAutoArrange      dd ?
  129.     SelectItem          dd ?
  130.     SelectAndPositionItems dd ?
  131. ends
  132.  
  133. ; IID_IEnumIDList Interface
  134. struct IEnumIDList
  135.     QueryInterface      dd ?
  136.     AddRef              dd ?
  137.     Release             dd ?
  138.  
  139.     Next                dd ?
  140.     Skip                dd ?
  141.     Reset               dd ?
  142.     Clone               dd ?
  143. ends
  144.  
  145. struct IUnknown
  146.     QueryInterface      dd ?
  147.     AddRef              dd ?
  148.     Release             dd ?
  149. ends
Список с ярлыками запрятан достаточно глубоко в структуре окна рабочего стола, поэтому и доступ к нему приходится получать, поочередно обращаясь к объектам все более низкого уровня. Больше всего это напоминает разборку игрушки-матрешки. Добравшись до списка, перебираем поочередно его элементы и получаем интересующие нас свойства, то есть координаты и название каждого ярлыка на рабочем столе.
  1.         ; Инициализировать COM-объект
  2.         invoke  CoInitialize,NULL
  3.         ; Создать объект
  4.         invoke  CoCreateInstance,CLSID_ShellWindows,NULL,\
  5.                 CLSCTX_ALL,IID_IShellWindows,pISwDisp
  6.         cmp     eax,S_OK
  7.         jne     loc_exit
  8.  
  9.         ; Найти окно рабочего стола и получить интерфейс
  10.         ; для работы с ним
  11.         mov     [varLoc.vt],VT_I4
  12.         mov     [varLoc.lVal],CSIDL_DESKTOP
  13.         mov     [varLocRoot.vt],VT_EMPTY
  14.         mov     eax,[pISwDisp]
  15.         mov     eax,[eax]
  16.         stdcall dword [eax+IShellWindows.FindWindowSW],[pISwDisp],varLoc,\
  17.                 varLocRoot,SWC_DESKTOP,hwnd,SWFO_NEEDDISPATCH,spdisp
  18.  
  19.         invoke  IUnknown_QueryService,[spdisp],CLSID_STopLevelBrowser,\
  20.                 IID_IShellBrowser,spBrowser
  21.  
  22.         mov     eax,[spBrowser]
  23.         mov     eax,[eax]
  24.         stdcall dword [eax+IShellBrowser.QueryActiveShellView],\
  25.                 [spBrowser],spshView
  26.  
  27.         mov     eax,[spshView]
  28.         mov     eax,[eax]
  29.         stdcall dword [eax+IShellFolder.QueryInterface],[spshView],\
  30.                 IID_IFolderView,spView
  31.  
  32.         mov     eax,[spView]
  33.         mov     eax,[eax]
  34.         stdcall dword [eax+IFolderView.GetFolder],[spView],\
  35.                 IID_IShellFolder,spFolder
  36.  
  37.         ; Получить список объектов
  38.         mov     eax,[spView]
  39.         mov     eax,[eax]
  40.         stdcall dword [eax+IFolderView.Items],[spView],SVGIO_ALLVIEW,\
  41.                 IID_IEnumIDList,spEnum
  42.  
  43. loc_loop:
  44.         ; Получить следующий объект рабочего стола
  45.         mov     eax,[spEnum]
  46.         mov     eax,[eax]
  47.         stdcall dword [eax+IEnumIDList.Next],[spEnum],1,spidl,0
  48.         or      eax,eax
  49.         jne     loc_done
  50.  
  51.         ; Получить название иконки
  52.         mov     eax,[spFolder]
  53.         mov     eax,[eax]
  54.         stdcall dword [eax+IShellFolder.GetDisplayNameOf],[spFolder],\
  55.                 [spidl],SHGDN_NORMAL,strRet
  56.         ; Преобразовать его в привычный вид
  57.         invoke  StrRetToStr,strRet,[spidl],spszName
  58.  
  59.         ; Получить координаты иконки
  60.         mov     eax,[spView]
  61.         mov     eax,[eax]
  62.         stdcall dword [eax+IFolderView.GetItemPosition],[spView],\
  63.                 [spidl],pt
  64.         ; [spszName] --> указатель на строку названия ярлыка
  65.         ; pt --> координаты ярлыка относительно левого верхнего угла
  66.         ...
  67.         ...
  68.         jmp     loc_loop
  69. loc_done:
  70.         ; Прибраться за собой
  71.         mov     eax,[spEnum]
  72.         mov     eax,[eax]
  73.         stdcall dword [eax+IUnknown.Release],[spEnum]
  74.  
  75.         mov     eax,[spFolder]
  76.         mov     eax,[eax]
  77.         stdcall dword [eax+IUnknown.Release],[spFolder]
  78.  
  79.         mov     eax,[spView]
  80.         mov     eax,[eax]
  81.         stdcall dword [eax+IUnknown.Release],[spView]
  82.  
  83.         mov     eax,[spshView]
  84.         mov     eax,[eax]
  85.         stdcall dword [eax+IUnknown.Release],[spshView]
  86.  
  87.         mov     eax,[spBrowser]
  88.         mov     eax,[eax]
  89.         stdcall dword [eax+IUnknown.Release],[spBrowser]
  90.  
  91.         mov     eax,[spdisp]
  92.         mov     eax,[eax]
  93.         stdcall dword [eax+IUnknown.Release],[spdisp]
  94.  
  95.         mov     eax,[pISwDisp]
  96.         mov     eax,[eax]
  97.         stdcall dword [eax+IUnknown.Release],[pISwDisp]
  98.  
  99.         ; Удалить объект
  100.         invoke  CoUninitialize
Естественно, список методов IFolderView не ограничивается только координатами ярлыков, с их помощью можно получить настройки отображения интересующей вас папки, а также управлять положением и выделением элементов. Например, сохранив где-нибудь в сухом прохладном месте положение ярлыков на рабочем столе, в дальнейшем можно будет их восстановить на привычные места, как это делают упомянутые в начале статьи утилиты. Делается это примерно так:
  1.         SVSI_POSITIONITEM = 0x80
  2.  
  3.         ; Установить новые координаты иконки
  4.         mov     eax,[spView]
  5.         mov     eax,[eax]
  6.         stdcall dword [eax+IFolderView.SelectAndPositionItems],[spView],\
  7.                 1,spidl,pt,SVSI_POSITIONITEM
Добираемся до списка ярлыков, как показано в приведенном выше коде, но вместо получения координат меняем их на нужные (сохраненные). Не забудьте только отключить в настройках рабочего стола галочки "Упорядочить значки автоматически" и "Выровнять значки по сетке".

В приложении пример программы с исходным текстом, которая выводит список ярлыков рабочего стола с их координатами.

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

Get.Desktop.Icons.Demo.zip (5,284 bytes)


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

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

Комментарии

Отзывы посетителей сайта о статье
ManHunter (09.08.2020 в 11:25):
Проактивка антивирусов может не одобрить такого поведения.
wet (09.08.2020 в 09:24):
Можно попроще сделать. Найти pid проводника GetWindowThreadProcessId,
подключится к процессу OpenProcess, скопировать структуру LV_ITEM WriteProcessMemory в выделенную для этого память VirtualAllocEx.
А дальше SendMessage к Desktop Handle:
LVM_GETITEMCOUNT общее кол-во иконок
LVM_GETITEMTEXT  их имена
LVM_GETITEMPOSITION их координаты.
Василий (06.08.2020 в 12:46):
ManHunter, такого годного контента ещё поискать... очень хорошие статьи, не вздумай бросать)))
Евгений (05.08.2020 в 13:08):
"Может оно и не надо совсем?" - несогласен, нужно посмотреть на кнопочку "сказать спасибо!".
0101 (05.08.2020 в 10:30):
похоже). Как им бабки зарабатывать? В интсте/ютубе за просмотры и лайки капает денежка! И мозги не напрягаются. Кайми вот в бизнес подался.. Имхо:
1. давно уже надо/пора выдрать файлы костант и структур (из других ЯП), чтобы вообще о них не думать и подключать инкудом.
2. без макросов select/case, прямого сравнения (>=<) и присвоения данных/строк (без постоянного дёрганья eax), объявления строк и переменных "по месту" - совсем скучно. Форки asm'а это давно могут.
3. меня раздражают скобки вместо @/&/*, инвоки, отсутствие процедур - код нечитаем с этими @f/ret.
4. секция ресурсов не наглядна. Почему бы не нарисовать диалоговое окно в ResEd и затем прилинковать? Знаю, есть прога, которые из *.rc переводят в формат ресурсов fasm.. Ты их используешь или из головы сразу пишешь такие большие ресурсы?
5.FASMW в качестве IDE не подходит - нет подсветки и автокомплита. Надо или RadAsm/EasyCode продвигать или к npp автокомплит прикручивать (подходит от RadAsm с небольшими правками) или твой Sublime расшаривать..
6. нужны исходники - литература, откуда всё (идеи статей) взялось, даже на английском. Кому-то проще в си-коде разбираться, кому-то (мне) хотелось бы не просто на код посмотреть, но и теорию почитать. Например: в теме "Создание и обработка улучшенного MessageBox" хотелось бы почитать теорию по хукам или о том, что у MsgBox есть (независимое) текстовое поле со своим хендлом..  Статьи (мне) не достаточно для понимания, приходится гуглить (копаться в chm-форуме RDSN за 2007г..) аналогичные примеры..
A1eksandr1 (05.08.2020 в 04:21):
Ну некоторые всё же почитывают. А комментировать/дискутировать - это уже совсем другая история)
Ещё и публикации появляются задним числом (дата статьи: 25.07; по факту отобразилась только 04.08), не каждый откроет, если не будет пролистывать блог вниз.
ManHunter (04.08.2020 в 23:12):
Похоже, что популяризация Ассемблера проходит мимо. Может оно и не надо совсем? Завести инстаграмм, постить фотки пюрешки с сосисками...

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

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

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