РЕДАКТИРОВАНО 23.11.2010 23:20 (постарался более подробно все описать) Вот код программы на C++ который получает IDList указатель из текстового названия каталога. Этот IDList указатель можно потом использовать в структуре BROWSEINFO конкретно параметр pidlRoot для задания корневого каталога для отображения функцией ShBrowseForFolder. Во всех примерах в интернете всегда параметр pidlRoot установлен в ноль, в том числе и по той ссылке что ниже оставил Flint_ta. В прикрепленном файле я постарался реализовать код получения IDList указателя из названия каталога, но что-то не так работает. С вызовом функции ShBrowseForFolder проблем нет, но из-за того, что не получается создать IDList указатель из названия каталога, соответственно не получается задать корневой каталог для отображения. Код (Text): BOOL GetItemIdListFromPath (LPWSTR lpszPath, LPITEMIDLIST *lpItemIdList) { LPSHELLFOLDER pShellFolder = NULL; HRESULT hr; ULONG chUsed; // Get desktop IShellFolder interface if (SHGetDesktopFolder (&pShellFolder) != NOERROR) return FALSE; // failed // convert the path to an ITEMIDLIST hr = pShellFolder->ParseDisplayName ( NULL, // owner window NULL, // reserved (must be NULL) lpszPath, // folder name &chUsed, // number of chars parsed lpItemIdList, // ITEMIDLIST NULL // attributes (can be NULL) ); if (FAILED(hr)) { pShellFolder->Release(); *lpItemIdList = NULL; return FALSE; } pShellFolder->Release(); return TRUE; } // GetItemIdListFromPath Задача: сделать аналогичный вариант на MASM32, чтобы функция ShBrowseForFolder отображала для выбора только диск С:\ и его подкаталоги Вопросы: 1) что неправильно в моем варианте вызова функции ParseDisplayName (в прикреплённом файле) ? 2) Какова общая методика определения смещений методов объектов (тоесть как их искать) для их вызова в коде ассемблера (или может быть есть кардинально другой способ вызова методов объектов, чтобы не искать смещения) ?
Есть такой вариант, если кто-то может, откомпилировать Сишный код и выложить здесь. Постараюсь сам разобраться.
отредактировал шапку, подробно описал что именно не получается, пример по ссылке выше не объясняет того, что нужно получить.
kiosun А сам скомпилсть не можешь? вызов: Код (Text): int _tmain(int argc, _TCHAR* argv[]) { LPITEMIDLIST lpItemIdList = NULL; GetItemIdListFromPath(L"C:\\", &lpItemIdList); return 0; } реализация от MS VC 2008 Debug: Код (Text): BOOL GetItemIdListFromPath (LPWSTR lpszPath, LPITEMIDLIST *lpItemIdList) { 004113E0 push ebp 004113E1 mov ebp,esp 004113E3 sub esp,0E4h 004113E9 push ebx 004113EA push esi 004113EB push edi 004113EC lea edi,[ebp-0E4h] 004113F2 mov ecx,39h 004113F7 mov eax,0CCCCCCCCh 004113FC rep stos dword ptr es:[edi] LPSHELLFOLDER pShellFolder = NULL; 004113FE mov dword ptr [pShellFolder],0 HRESULT hr; ULONG chUsed; // Get desktop IShellFolder interface if (SHGetDesktopFolder (&pShellFolder) != NOERROR) 00411405 mov esi,esp 00411407 lea eax,[pShellFolder] 0041140A push eax 0041140B call dword ptr [__imp__SHGetDesktopFolder@4 (418338h)] 00411411 cmp esi,esp 00411413 call @ILT+330(__RTC_CheckEsp) (41114Fh) 00411418 test eax,eax 0041141A je GetItemIdListFromPath+40h (411420h) return FALSE; // failed 0041141C xor eax,eax 0041141E jmp GetItemIdListFromPath+0B2h (411492h) // convert the path to an ITEMIDLIST hr = pShellFolder->ParseDisplayName ( NULL, // owner window NULL, // reserved (must be NULL) lpszPath, // folder name &chUsed, // number of chars parsed lpItemIdList, // ITEMIDLIST NULL // attributes (can be NULL) ); 00411420 mov esi,esp 00411422 push 0 00411424 mov eax,dword ptr [lpItemIdList] 00411427 push eax 00411428 lea ecx,[chUsed] 0041142B push ecx 0041142C mov edx,dword ptr [lpszPath] 0041142F push edx 00411430 push 0 00411432 push 0 00411434 mov eax,dword ptr [pShellFolder] 00411437 mov ecx,dword ptr [eax] 00411439 mov edx,dword ptr [pShellFolder] 0041143C push edx 0041143D mov eax,dword ptr [ecx+0Ch] 00411440 call eax 00411442 cmp esi,esp 00411444 call @ILT+330(__RTC_CheckEsp) (41114Fh) 00411449 mov dword ptr [hr],eax if (FAILED(hr)) 0041144C cmp dword ptr [hr],0 00411450 jge GetItemIdListFromPath+96h (411476h) { pShellFolder->Release(); 00411452 mov eax,dword ptr [pShellFolder] 00411455 mov ecx,dword ptr [eax] 00411457 mov esi,esp 00411459 mov edx,dword ptr [pShellFolder] 0041145C push edx 0041145D mov eax,dword ptr [ecx+8] 00411460 call eax 00411462 cmp esi,esp 00411464 call @ILT+330(__RTC_CheckEsp) (41114Fh) *lpItemIdList = NULL; 00411469 mov eax,dword ptr [lpItemIdList] 0041146C mov dword ptr [eax],0 return FALSE; 00411472 xor eax,eax 00411474 jmp GetItemIdListFromPath+0B2h (411492h) } pShellFolder->Release(); 00411476 mov eax,dword ptr [pShellFolder] 00411479 mov ecx,dword ptr [eax] 0041147B mov esi,esp 0041147D mov edx,dword ptr [pShellFolder] 00411480 push edx 00411481 mov eax,dword ptr [ecx+8] 00411484 call eax 00411486 cmp esi,esp 00411488 call @ILT+330(__RTC_CheckEsp) (41114Fh) return TRUE; 0041148D mov eax,1 } // GetItemIdListFromPath 00411492 push edx 00411493 mov ecx,ebp 00411495 push eax 00411496 lea edx,[ (4114B8h)] 0041149C call @ILT+135(@_RTC_CheckStackVars@8) (41108Ch) 004114A1 pop eax 004114A2 pop edx 004114A3 pop edi 004114A4 pop esi 004114A5 pop ebx 004114A6 add esp,0E4h 004114AC cmp ebp,esp 004114AE call @ILT+330(__RTC_CheckEsp) (41114Fh) 004114B3 mov esp,ebp 004114B5 pop ebp 004114B6 ret реализация от MS VC 2008 Release: Код (Text): int _tmain(int argc, _TCHAR* argv[]) { 00401000 sub esp,0Ch LPITEMIDLIST lpItemIdList = NULL; GetItemIdListFromPath(L"C:\\", &lpItemIdList); 00401003 lea eax,[esp] 00401006 push eax 00401007 mov dword ptr [esp+8],0 0040100F mov dword ptr [esp+4],0 00401017 call dword ptr [__imp__SHGetDesktopFolder@4 (4020A4h)] 0040101D test eax,eax 0040101F jne wmain+4Eh (40104Eh) 00401021 mov eax,dword ptr [esp] 00401024 mov ecx,dword ptr [eax] 00401026 push 0 00401028 lea edx,[esp+8] 0040102C push edx 0040102D lea edx,[esp+10h] 00401031 push edx 00401032 push offset string L"C:\\" (4020F4h) 00401037 push 0 00401039 push 0 0040103B push eax 0040103C mov eax,dword ptr [ecx+0Ch] 0040103F call eax 00401041 test eax,eax 00401043 mov eax,dword ptr [esp] 00401046 mov ecx,dword ptr [eax] 00401048 mov edx,dword ptr [ecx+8] 0040104B push eax 0040104C call edx return 0; 0040104E xor eax,eax } 00401050 add esp,0Ch 00401053 ret
Поправил код. Теперь функцию IShellFolder->ParseDisplayName вызываю так(этот вызов идентичен тому, что в листингах выше): Str1 db "d:\Pictures",0 .............. push NULL lea eax, BI.pidlRoot push eax push NULL push offset Str1 push NULL push hWnd mov eax, pShellFolder push eax mov eax, [eax] call dword ptr [eax+12] Если Str1 равно "d:\Pictures" или "d:\Pictures\" или "d:\1.txt" (этот каталог и файл точно существуют) , то функция возвращает значение 80070002 (тип HRESULT) - как я понял это означает The system cannot find the file specified. что не так?
COM\OLE обычно использует юникод см. внимательней ParseDisplayName(...[in] LPWSTR pszDisplayName..) может в этом и причина. и я не знаю как в масме но для фасма есть в стандартной поставке макросы для работы с COM. неужели для масм ничего нет? сомнительно как-то.
Спасибо, BaGiE, всего-то надо было использовать Юникод строку, всё из-за моей невнимательности. То что в FASM есть макросы для работы с COM я обязательно почитаю, но что есть такие же в MASM или есть какая-то дополнительная библиотека для этих целей, я ничего не знаю. Буду копать, может кто и подскажет чего. П.С. первое что сразу нашлось: в более ранних версиях MASM вроде как была папка COM, у меня же стоит последняя версия - такой папки нет ...