├── CDropTarget.asm ├── COleCommandTarget.asm ├── COleInPlaceFrame.asm ├── CServiceProvider.asm ├── CShellBrowser.asm ├── CShellBrowser.inc ├── CVViewer.asm ├── CVViewer.def ├── CVViewer.inc ├── CVViewer.manifest ├── CVViewer.txt ├── DDEStuff.asm ├── Debugout.inc ├── ExplASM.asm ├── ExplASM.txt ├── MAKE.BAT ├── MODULES.INC ├── Macros.inc ├── Makefile ├── OleCntrl.inc ├── RSRC.H ├── RSRC.RC ├── Readme.MD ├── Res ├── Explorer.ico └── Splith.cur ├── Wincrack.inc └── rsrc.inc /CDropTarget.asm: -------------------------------------------------------------------------------- 1 | 2 | ;--- IDropTarget installs left explorer panel as a drop target 3 | 4 | .386 5 | .model flat, stdcall 6 | option casemap:none 7 | option proc:private 8 | 9 | .nolist 10 | .nocref 11 | WIN32_LEAN_AND_MEAN equ 1 12 | INCL_OLE2 equ 1 13 | _WIN32_IE equ 500h 14 | include windows.inc 15 | include commctrl.inc 16 | include windowsx.inc 17 | 18 | include shellapi.inc 19 | include objidl.inc 20 | include olectl.inc 21 | include shlguid.inc 22 | include shlobj.inc 23 | include shlwapi.inc 24 | include shobjidl.inc 25 | 26 | include macros.inc 27 | 28 | ?AGGREGATION = 0 ;no aggregation 29 | ?EVENTSUPPORT = 0 ;no event support 30 | 31 | include olecntrl.inc 32 | include debugout.inc 33 | include rsrc.inc 34 | .list 35 | .cref 36 | 37 | INSIDE_CShellBrowser equ 1 38 | 39 | LPDROPTARGETHELPER typedef ptr IDropTargetHelper 40 | LPSHELLLINK typedef ptr IShellLink 41 | 42 | include CShellBrowser.inc 43 | 44 | if ?DROPTARGET 45 | 46 | includelib shlwapi.lib 47 | 48 | .const 49 | 50 | CDropTargetVtbl label dword 51 | IUnknownVtbl {QueryInterface_, AddRef_, Release_} 52 | dd DragEnter_, DragOver_, DragLeave_, Drop_ 53 | 54 | ;CLSID_ShellLink GUID sCLSID_ShellLink 55 | ;IID_IShellLink sIID_IShellLinkA 56 | 57 | .code 58 | 59 | __this textequ 60 | _this textequ <[__this].CShellBrowser> 61 | 62 | MEMBER hWnd, hWndTV, bRButton 63 | MEMBER pMalloc 64 | 65 | @MakeStubsEx CShellBrowser, IDropTarget, QueryInterface, AddRef, Release 66 | @MakeStubs CShellBrowser, IDropTarget, DragEnter, DragOver, DragLeave, Drop 67 | 68 | DragEnter proc uses __this this_:ptr CShellBrowser, pDataObject:LPDATAOBJECT, grfKeyState:DWORD, pt:POINTL, pdwEffect:ptr DWORD 69 | 70 | local fe:FORMATETC 71 | 72 | mov __this,this_ 73 | 74 | ;----------------------------- check if data is acceptable 75 | 76 | mov fe.cfFormat, CF_HDROP 77 | mov fe.ptd, NULL 78 | mov fe.dwAspect, DVASPECT_CONTENT 79 | mov fe.lindex, -1 80 | mov fe.tymed, TYMED_HGLOBAL 81 | invoke vf(pDataObject, IDataObject, QueryGetData), addr fe 82 | mov ecx, pdwEffect 83 | DebugOut "IShellBrowser::DragEnter(%X), IDataObject::QueryGetData=%X %X", grfKeyState, eax, dword ptr [ecx] 84 | .IF (eax != S_OK) 85 | mov dword ptr [ecx], DROPEFFECT_NONE 86 | if 1 87 | .ELSE 88 | mov edx, grfKeyState 89 | and edx, MK_CONTROL or MK_SHIFT 90 | mov eax, [ecx] 91 | .if (edx == (MK_CONTROL or MK_SHIFT)) 92 | and eax, DROPEFFECT_LINK 93 | .elseif (edx == MK_CONTROL) 94 | and eax,DROPEFFECT_COPY 95 | .else 96 | and eax,DROPEFFECT_MOVE 97 | .endif 98 | .if (!eax) 99 | mov eax, DROPEFFECT_COPY 100 | .endif 101 | and DWORD PTR [ecx], eax 102 | endif 103 | .endif 104 | .if (grfKeyState & MK_RBUTTON) 105 | mov m_bRButton, TRUE 106 | .else 107 | mov m_bRButton, FALSE 108 | .endif 109 | if ?DRAGDROPHELPER 110 | .if (g_pDropTargetHelper) 111 | mov ecx, pdwEffect 112 | invoke vf(g_pDropTargetHelper, IDropTargetHelper, DragEnter), m_hWnd, pDataObject, addr pt, [ecx] 113 | DebugOut "IDropTargetHelper::DragEnter=%X", eax 114 | .endif 115 | endif 116 | 117 | return S_OK 118 | align 4 119 | 120 | DragEnter endp 121 | 122 | DragOver proc uses __this this_:ptr CShellBrowser, grfKeyState:DWORD, pt:POINTL, pdwEffect:ptr DWORD 123 | 124 | local tvht:TV_HITTESTINFO 125 | 126 | mov __this,this_ 127 | DebugOut "IShellBrowser::DragOver(%X)", grfKeyState 128 | 129 | mov eax, pt.x 130 | mov tvht.pt.x, eax 131 | mov eax, pt.y 132 | mov tvht.pt.y, eax 133 | invoke ScreenToClient, m_hWndTV, addr tvht.pt 134 | invoke TreeView_HitTest( m_hWndTV, addr tvht) 135 | .if (eax) 136 | invoke TreeView_SelectDropTarget( m_hWndTV, eax) 137 | mov ecx, pdwEffect 138 | mov eax, [ecx] 139 | mov edx, grfKeyState 140 | and edx, MK_CONTROL or MK_SHIFT 141 | .if (edx == (MK_CONTROL or MK_SHIFT)) 142 | and eax, DROPEFFECT_LINK 143 | .elseif (edx == MK_CONTROL) 144 | and eax,DROPEFFECT_COPY 145 | .else 146 | and eax,DROPEFFECT_MOVE 147 | .endif 148 | .if (!eax) 149 | mov eax, DROPEFFECT_COPY 150 | .endif 151 | .else 152 | mov eax, DROPEFFECT_NONE 153 | .endif 154 | mov ecx, pdwEffect 155 | and DWORD PTR [ecx], eax 156 | 157 | if ?DRAGDROPHELPER 158 | .if (g_pDropTargetHelper) 159 | invoke vf(g_pDropTargetHelper, IDropTargetHelper, DragOver), addr pt, [ecx] 160 | ifdef _DEBUG 161 | mov ecx, pdwEffect 162 | endif 163 | DebugOut "IDropTargetHelper::DragOver=%X, %X", eax, dword ptr [ecx] 164 | .endif 165 | endif 166 | 167 | return S_OK 168 | align 4 169 | 170 | DragOver endp 171 | 172 | DragLeave proc uses __this this_:ptr CShellBrowser 173 | 174 | mov __this,this_ 175 | DebugOut "IShellBrowser::DragLeave" 176 | 177 | invoke TreeView_SelectDropTarget( m_hWndTV, NULL) 178 | if ?DRAGDROPHELPER 179 | .if (g_pDropTargetHelper) 180 | invoke vf(g_pDropTargetHelper, IDropTargetHelper, DragLeave) 181 | DebugOut "IDropTargetHelper::DragLeave=%X", eax 182 | .endif 183 | endif 184 | return S_OK 185 | align 4 186 | 187 | DragLeave endp 188 | 189 | IDM_MOVE equ FCIDM_BROWSERFIRST+0 190 | IDM_COPY equ FCIDM_BROWSERFIRST+1 191 | IDM_CREATESHORTCUT equ FCIDM_BROWSERFIRST+2 192 | IDM_CANCEL equ FCIDM_BROWSERFIRST+3 193 | 194 | DisplayContextMenu proc uses esi grfKeyState:DWORD, dwEffect:DWORD 195 | 196 | local dwDefault:DWORD 197 | local pt:POINT 198 | 199 | mov dwDefault, 0 200 | invoke CreatePopupMenu 201 | mov esi, eax 202 | .if (dwEffect & DROPEFFECT_MOVE) 203 | invoke AppendMenu, esi, MF_STRING, IDM_MOVE, CStr("Move Here") 204 | .if (!(grfKeyState & MK_CONTROL)) 205 | mov dwDefault, IDM_MOVE 206 | .endif 207 | .endif 208 | .if (dwEffect & DROPEFFECT_COPY) 209 | invoke AppendMenu, esi, MF_STRING, IDM_COPY, CStr("Copy Here") 210 | .if (grfKeyState & MK_CONTROL) 211 | mov dwDefault, IDM_COPY 212 | .endif 213 | .endif 214 | .if (dwEffect & DROPEFFECT_LINK) 215 | invoke AppendMenu, esi, MF_STRING, IDM_CREATESHORTCUT, CStr("Create Shortcut(s) Here") 216 | mov ecx, grfKeyState 217 | and ecx, MK_CONTROL or MK_SHIFT 218 | .if (ecx == MK_CONTROL or MK_SHIFT) 219 | mov dwDefault, IDM_CREATESHORTCUT 220 | .endif 221 | .endif 222 | invoke AppendMenu, esi, MF_SEPARATOR, -1, 0 223 | invoke AppendMenu, esi, MF_STRING, IDM_CANCEL, CStr("Cancel") 224 | .if (dwDefault) 225 | invoke SetMenuDefaultItem, esi, dwDefault, FALSE 226 | .endif 227 | invoke GetCursorPos, addr pt 228 | invoke TrackPopupMenu, esi, TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_RETURNCMD,\ 229 | pt.x, pt.y, 0, m_hWnd, NULL 230 | .if (eax == IDM_COPY) 231 | mov eax, MK_CONTROL 232 | .elseif (eax == IDM_CREATESHORTCUT) 233 | mov eax, MK_CONTROL or MK_SHIFT 234 | .elseif (eax == IDM_MOVE) 235 | mov eax, MK_RBUTTON 236 | .else 237 | xor eax, eax 238 | .endif 239 | push eax 240 | invoke DestroyMenu, esi 241 | pop eax 242 | ret 243 | 244 | DisplayContextMenu endp 245 | 246 | 247 | CreateLink proc lpszPathObj:LPSTR, lpszPathLink:LPSTR , lpszDesc:LPSTR 248 | 249 | local hres:DWORD 250 | local pShellLink:LPSHELLLINK 251 | local pPersistFile:LPPERSISTFILE 252 | local wsz[MAX_PATH]:WORD 253 | 254 | invoke CoCreateInstance, addr CLSID_ShellLink, NULL, 255 | CLSCTX_INPROC_SERVER, addr IID_IShellLinkA, addr pShellLink 256 | .if (eax == S_OK) 257 | 258 | ; // Set the path to the shortcut target and add the 259 | ; // description. 260 | invoke vf(pShellLink, IShellLinkA, SetPath), lpszPathObj 261 | invoke vf(pShellLink, IShellLinkA, SetDescription), lpszDesc 262 | 263 | ; // Query IShellLink for the IPersistFile interface for saving the 264 | ; // shortcut in persistent storage. 265 | invoke vf(pShellLink, IShellLinkA, QueryInterface), addr IID_IPersistFile, 266 | addr pPersistFile 267 | 268 | .if (eax == S_OK) 269 | invoke MultiByteToWideChar, CP_ACP, 0, lpszPathLink, -1, addr wsz, MAX_PATH 270 | ; // Save the link by calling IPersistFile::Save. 271 | invoke vf(pPersistFile, IPersistFile, Save), addr wsz, TRUE 272 | invoke vf(pPersistFile, IUnknown, Release) 273 | .endif 274 | invoke vf(pShellLink, IUnknown, Release) 275 | .endif 276 | ret 277 | CreateLink endp 278 | 279 | 280 | ?COPYDROPFILES equ 1 281 | 282 | ;--- grfKeyState doesnt show mouse button state (because the drop 283 | ;--- gets into effect if the mouse button is released!) 284 | 285 | Drop proc uses __this esi this_:ptr CShellBrowser, pDataObject:LPDATAOBJECT, grfKeyState:DWORD, pt:POINTL, pdwEffect:ptr DWORD 286 | 287 | local pidl:LPITEMIDLIST 288 | local fe:FORMATETC 289 | local dwFiles:DWORD 290 | local dwSize:DWORD 291 | local stgmedium:STGMEDIUM 292 | local shfos:SHFILEOPSTRUCT 293 | local szPath[MAX_PATH]:BYTE 294 | local szPathTmp[MAX_PATH]:BYTE 295 | local szDesc[MAX_PATH]:BYTE 296 | local szFile[MAX_PATH]:BYTE 297 | 298 | mov __this,this_ 299 | DebugOut "IShellBrowser::Drop(%X)", grfKeyState 300 | 301 | mov fe.cfFormat, CF_HDROP 302 | mov fe.ptd, NULL 303 | mov fe.dwAspect,DVASPECT_CONTENT 304 | mov fe.lindex,-1 305 | mov fe.tymed, TYMED_HGLOBAL 306 | invoke vf(pDataObject, IDataObject, GetData), ADDR fe, ADDR stgmedium 307 | .if (eax != S_OK) 308 | jmp exit 309 | .endif 310 | 311 | if ?COPYDROPFILES 312 | ;--------------------------------- get number of files dropped 313 | invoke DragQueryFile, stgmedium.hGlobal, -1, 0, 0 314 | mov dwFiles, eax 315 | mov dwSize, 1 316 | xor esi, esi 317 | .while (esi < dwFiles) 318 | invoke DragQueryFile, stgmedium.hGlobal, esi, 0, 0 319 | inc eax 320 | add dwSize, eax 321 | inc esi 322 | .endw 323 | 324 | invoke LocalAlloc, LMEM_FIXED, dwSize 325 | .if (!eax) 326 | jmp exit2 327 | .endif 328 | mov shfos.pFrom, eax 329 | mov edx, eax 330 | 331 | xor esi, esi 332 | .while (esi < dwFiles) 333 | push edx 334 | invoke DragQueryFile, stgmedium.hGlobal, esi, edx, MAX_PATH 335 | pop edx 336 | add edx, eax 337 | mov byte ptr [edx],0 338 | inc edx 339 | inc esi 340 | .endw 341 | mov byte ptr [edx],0 342 | else 343 | mov eax, stgmedium.hGlobal ;that doesnt work with wide chars 344 | add eax,[eax].DROPFILES.pFiles 345 | mov shfos.pFrom, eax 346 | endif 347 | mov eax, m_hWnd 348 | mov shfos.hwnd, eax 349 | 350 | invoke TreeView_GetDropHilight( m_hWndTV) 351 | invoke GetFullPidl@CShellBrowser, eax 352 | mov pidl, eax 353 | invoke SHGetPathFromIDList, pidl, addr szPath 354 | invoke vf(m_pMalloc, IMalloc, Free), pidl 355 | lea eax, szPath 356 | mov shfos.pTo, eax 357 | 358 | mov edx, grfKeyState 359 | .if (m_bRButton) 360 | mov ecx, pdwEffect 361 | invoke DisplayContextMenu, edx, [ecx] 362 | .if (!eax) 363 | jmp exit2 364 | .endif 365 | mov edx, eax 366 | .endif 367 | 368 | mov ecx, pdwEffect 369 | mov ecx, [ecx] 370 | and edx, MK_CONTROL or MK_SHIFT 371 | .if ((ecx & DROPEFFECT_LINK) && (edx == MK_CONTROL or MK_SHIFT)) 372 | mov esi, shfos.pFrom 373 | .while (byte ptr [esi]) 374 | invoke lstrlen, esi 375 | mov dwSize, eax 376 | invoke lstrcpy, addr szFile, esi 377 | invoke PathStripPath, addr szFile 378 | invoke wsprintf, addr szDesc, CStr("Shortcut of %s"), addr szFile 379 | invoke wsprintf, addr szPathTmp, CStr("%s\%s.lnk"), shfos.pTo, addr szFile 380 | invoke CreateLink, esi, addr szPathTmp, addr szDesc 381 | add esi, dwSize 382 | inc esi 383 | .endw 384 | .else 385 | .if ((ecx & DROPEFFECT_MOVE) && (!edx)) 386 | mov shfos.wFunc, FO_MOVE 387 | .elseif (ecx & DROPEFFECT_COPY) 388 | mov shfos.wFunc, FO_COPY 389 | .else 390 | jmp exit3 391 | .endif 392 | mov shfos.fFlags, FOF_ALLOWUNDO 393 | mov shfos.fAnyOperationsAborted, FALSE 394 | ;; mov shfos.hNameMappings, xxx 395 | ;; mov shfos.lpszProgressTitle, xxx 396 | invoke SHFileOperation, addr shfos 397 | .endif 398 | exit3: 399 | if ?COPYDROPFILES 400 | invoke LocalFree, shfos.pFrom 401 | endif 402 | exit2: 403 | invoke ReleaseStgMedium, addr stgmedium 404 | exit: 405 | invoke TreeView_SelectDropTarget( m_hWndTV, NULL) 406 | 407 | if ?DRAGDROPHELPER 408 | .if (g_pDropTargetHelper) 409 | mov ecx, pdwEffect 410 | invoke vf(g_pDropTargetHelper, IDropTargetHelper, Drop), pDataObject, addr pt, [ecx] 411 | DebugOut "IDropTargetHelper::Drop=%X", eax 412 | .endif 413 | endif 414 | 415 | return S_OK 416 | align 4 417 | 418 | Drop endp 419 | 420 | endif 421 | 422 | end 423 | -------------------------------------------------------------------------------- /COleCommandTarget.asm: -------------------------------------------------------------------------------- 1 | 2 | ;--- the IShellBrowser is requested for IOleCommandTarget 3 | ;--- currently we dont allow any commands 4 | 5 | .386 6 | .model flat, stdcall 7 | option casemap:none 8 | option proc:private 9 | 10 | .nolist 11 | .nocref 12 | WIN32_LEAN_AND_MEAN equ 1 13 | INCL_OLE2 equ 1 14 | _WIN32_IE equ 500h 15 | include windows.inc 16 | include commctrl.inc 17 | include windowsx.inc 18 | 19 | include shellapi.inc 20 | include objidl.inc 21 | include olectl.inc 22 | include shlguid.inc 23 | include shlobj.inc 24 | include shlwapi.inc 25 | include shobjidl.inc 26 | 27 | include macros.inc 28 | 29 | LPDROPTARGETHELPER typedef ptr IDropTargetHelper 30 | 31 | ?AGGREGATION = 0 ;no aggregation 32 | ?EVENTSUPPORT = 0 ;no event support 33 | 34 | include olecntrl.inc 35 | include debugout.inc 36 | include rsrc.inc 37 | .list 38 | .cref 39 | 40 | INSIDE_CShellBrowser equ 1 41 | 42 | include CShellBrowser.inc 43 | 44 | if ?OLECOMMANDTARGET 45 | 46 | .const 47 | 48 | COleCommandTargetVtbl label dword 49 | IUnknownVtbl {QueryInterface_, AddRef_, Release_} 50 | dd QueryStatus_, Exec_ 51 | 52 | 53 | .code 54 | 55 | __this textequ 56 | _this textequ <[__this].CShellBrowser> 57 | 58 | MEMBER hWnd, hWndTV 59 | 60 | @MakeStubsEx CShellBrowser, IOleCommandTarget, QueryInterface, AddRef, Release 61 | @MakeStubs CShellBrowser, IOleCommandTarget, QueryStatus, Exec 62 | 63 | ;;CGID_Explorer sCGID_Explorer 64 | 65 | QueryStatus proc uses __this this_:ptr CShellBrowser, pguidCmdGroup:REFGUID, cCmds:DWORD, prgCmds:ptr OLECMD, pCmdText:ptr OLECMDTEXT 66 | ifdef _DEBUG 67 | local szGUID[40]:byte 68 | local wszGUID[40]:word 69 | .if (pguidCmdGroup) 70 | invoke StringFromGUID2, pguidCmdGroup, addr wszGUID, 40 71 | invoke WideCharToMultiByte, CP_ACP, 0, addr wszGUID, -1, addr szGUID, 40, NULL, NULL 72 | .else 73 | invoke lstrcpy, addr szGUID, CStr("NULL") 74 | .endif 75 | DebugOut "CShellBrowser::QueryStatus(%s, %X)", addr szGUID, cCmds 76 | endif 77 | .if (pguidCmdGroup) 78 | invoke IsEqualGUID, pguidCmdGroup, addr CGID_Explorer 79 | .if (eax) 80 | mov ecx, cCmds 81 | mov edx, prgCmds 82 | mov eax, pCmdText 83 | .while (ecx) 84 | pushad 85 | mov [edx].OLECMD.cmdf, 0 86 | .if (eax) 87 | mov [eax].OLECMDTEXT.cmdtextf,OLECMDTEXTF_NONE 88 | mov [eax].OLECMDTEXT.cwActual,0 89 | .endif 90 | popad 91 | dec ecx 92 | add edx, sizeof OLECMD 93 | .if (eax) 94 | add eax, sizeof OLECMDTEXT 95 | .endif 96 | .endw 97 | return S_OK 98 | .endif 99 | .endif 100 | return OLECMDERR_E_UNKNOWNGROUP 101 | 102 | QueryStatus endp 103 | 104 | Exec proc uses __this this_:ptr CShellBrowser, pguidCmdGroup:REFGUID, nCmdID:DWORD, nCmdExecOpt:DWORD, pvaIn:ptr VARIANT, pvaOut:ptr VARIANT 105 | ifdef _DEBUG 106 | local szGUID[40]:byte 107 | local wszGUID[40]:word 108 | .if (pguidCmdGroup) 109 | invoke StringFromGUID2, pguidCmdGroup, addr wszGUID, 40 110 | invoke WideCharToMultiByte, CP_ACP, 0, addr wszGUID, -1, addr szGUID, 40, NULL, NULL 111 | .else 112 | invoke lstrcpy, addr szGUID, CStr("NULL") 113 | .endif 114 | DebugOut "CShellBrowser::Exec(%s, %X, %X)", addr szGUID, nCmdID, nCmdExecOpt 115 | endif 116 | return OLECMDERR_E_DISABLED 117 | Exec endp 118 | 119 | 120 | endif 121 | 122 | end 123 | -------------------------------------------------------------------------------- /COleInPlaceFrame.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | .386 4 | .model flat, stdcall 5 | option casemap:none 6 | option proc:private 7 | 8 | .nolist 9 | .nocref 10 | WIN32_LEAN_AND_MEAN equ 1 11 | INCL_OLE2 equ 1 12 | _WIN32_IE equ 500h 13 | include windows.inc 14 | include commctrl.inc 15 | include windowsx.inc 16 | 17 | include shellapi.inc 18 | include objidl.inc 19 | include olectl.inc 20 | include shlguid.inc 21 | include shlobj.inc 22 | include shlwapi.inc 23 | include shobjidl.inc 24 | 25 | include macros.inc 26 | 27 | LPDROPTARGETHELPER typedef ptr IDropTargetHelper 28 | 29 | ?AGGREGATION = 0 ;no aggregation 30 | ?EVENTSUPPORT = 0 ;no event support 31 | 32 | include olecntrl.inc 33 | include debugout.inc 34 | include rsrc.inc 35 | .list 36 | .cref 37 | 38 | ;protostrlenW typedef proto :ptr WORD 39 | ;externdef _imp__lstrlenW@4:PTR protostrlenW 40 | ;lstrlenW equ <_imp__lstrlenW@4> 41 | 42 | INSIDE_CShellBrowser equ 1 43 | 44 | include CShellBrowser.inc 45 | 46 | if ?OLEINPLACEFRAME 47 | 48 | E_NOTOOLSPACE equ 800401A1h 49 | 50 | .const 51 | 52 | COleInPlaceFrameVtbl label DWORD 53 | IUnknownVtbl {QueryInterface_, AddRef_, Release_} 54 | dd offset GetWindow__ 55 | dd offset ContextSensitiveHelp_ 56 | dd offset GetBorder_ 57 | dd offset RequestBorderSpace_ 58 | dd offset SetBorderSpace_ 59 | dd offset SetActiveObject_ 60 | dd offset InsertMenus_ 61 | dd offset SetMenu__ 62 | dd offset RemoveMenus_ 63 | dd offset SetStatusText_ 64 | dd offset EnableModeless_ 65 | dd offset TranslateAccelerator__ 66 | 67 | .code 68 | 69 | __this textequ 70 | _this textequ <[__this].CShellBrowser> 71 | 72 | MEMBER hWnd, pOleInPlaceActiveObject 73 | 74 | @MakeStubsEx CShellBrowser, IOleInPlaceFrame, QueryInterface, AddRef, Release 75 | @MakeStubs CShellBrowser, IOleInPlaceFrame, GetWindow_, ContextSensitiveHelp 76 | @MakeStubs CShellBrowser, IOleInPlaceFrame, GetBorder, RequestBorderSpace 77 | @MakeStubs CShellBrowser, IOleInPlaceFrame, SetBorderSpace, SetActiveObject 78 | @MakeStubs CShellBrowser, IOleInPlaceFrame, InsertMenus, SetMenu_, RemoveMenus 79 | @MakeStubs CShellBrowser, IOleInPlaceFrame, SetStatusText, EnableModeless, TranslateAccelerator_ 80 | 81 | GetWindow_ proc uses __this this_:ptr CShellBrowser, phwnd:ptr HWND 82 | 83 | DebugOut "IOleInPlaceSite::GetWindow" 84 | mov __this, this_ 85 | mov eax, phwnd 86 | mov ecx, m_hWnd 87 | mov [eax], ecx 88 | return S_OK 89 | 90 | GetWindow_ endp 91 | 92 | 93 | ContextSensitiveHelp proc this_:ptr CShellBrowser, fEnterMode:BYTE 94 | DebugOut "IOleInPlaceSite::ContextSensitiveHelp" 95 | return E_NOTIMPL 96 | ContextSensitiveHelp endp 97 | 98 | 99 | GetBorder proc uses __this this_:ptr CShellBrowser, lprectBorder:ptr RECT 100 | 101 | DebugOut "IOleInPlaceUIWindow::GetBorder" 102 | return E_NOTOOLSPACE 103 | 104 | GetBorder endp 105 | 106 | 107 | RequestBorderSpace proc this_:ptr CShellBrowser, pborderwidths:ptr BORDERWIDTHS 108 | 109 | DebugOut "IOleInPlaceUIWindow::RequestBorderSpace" 110 | return E_NOTOOLSPACE 111 | 112 | RequestBorderSpace endp 113 | 114 | 115 | SetBorderSpace proc uses __this esi this_:ptr CShellBrowser, pborderwidths:ptr BORDERWIDTHS 116 | 117 | DebugOut "IOleInPlaceUIWindow::SetBorderSpace(%X)", pborderwidths 118 | mov eax,pborderwidths 119 | .if (!eax) 120 | return S_OK 121 | .else 122 | mov ecx,[eax].BORDERWIDTHS.left 123 | add ecx,[eax].BORDERWIDTHS.top 124 | add ecx,[eax].BORDERWIDTHS.right 125 | add ecx,[eax].BORDERWIDTHS.bottom 126 | .if (!ecx) 127 | return S_OK 128 | .endif 129 | .endif 130 | return E_UNEXPECTED 131 | 132 | SetBorderSpace endp 133 | 134 | 135 | SetActiveObject proc uses __this this_:ptr CShellBrowser, pActiveObject:LPOLEINPLACEACTIVEOBJECT, pszObjName:ptr WORD 136 | 137 | DebugOut "IOleInPlaceUIWindow::SetActiveObject(%X)", pActiveObject 138 | mov __this,this_ 139 | .if (m_pOleInPlaceActiveObject) 140 | invoke vf(m_pOleInPlaceActiveObject, IOleInPlaceActiveObject, Release) 141 | .endif 142 | mov eax, pActiveObject 143 | mov m_pOleInPlaceActiveObject, eax 144 | .if (m_pOleInPlaceActiveObject) 145 | invoke vf(m_pOleInPlaceActiveObject, IOleInPlaceActiveObject, AddRef) 146 | .endif 147 | return S_OK 148 | 149 | SetActiveObject endp 150 | 151 | 152 | InsertMenus proc uses esi this_:ptr CShellBrowser, hmenuShared:HMENU, lpMenuWidths:ptr OLEMENUGROUPWIDTHS 153 | 154 | DebugOut "IOleInPlaceFrame::InsertMenus(%X)", hmenuShared 155 | return E_UNEXPECTED 156 | 157 | InsertMenus endp 158 | 159 | SetMenu_ proc uses __this this_:ptr CShellBrowser, hmenuShared:HMENU, holemenu:HANDLE, hwndActiveObject:HWND 160 | 161 | DebugOut "IOleInPlaceFrame::SetMenu(%X, %X, %X)", hmenuShared, holemenu, hwndActiveObject 162 | return E_UNEXPECTED 163 | 164 | SetMenu_ endp 165 | 166 | RemoveMenus proc uses __this this_:ptr CShellBrowser, hmenuShared:HMENU 167 | 168 | DebugOut "IOleInPlaceFrame::RemoveMenus(%X)", hmenuShared 169 | return E_UNEXPECTED 170 | 171 | RemoveMenus endp 172 | 173 | SetStatusText proc uses __this this_:ptr CShellBrowser, pszStatusText:ptr WORD 174 | 175 | local dwSize:DWORD 176 | 177 | mov __this,this_ 178 | .if (pszStatusText) 179 | invoke lstrlenW, pszStatusText 180 | add eax, 4 181 | and al, 0FCh 182 | sub esp, eax 183 | mov dwSize, eax 184 | mov edx, esp 185 | invoke WideCharToMultiByte, CP_ACP, 0, pszStatusText, -1, edx, dwSize, NULL, NULL 186 | ;; invoke SetStatusText@CViewObjectDlg, m_pViewObjectDlg, 0, esp 187 | add esp, dwSize 188 | .endif 189 | 190 | return S_OK 191 | 192 | SetStatusText endp 193 | 194 | EnableModeless proc this_:ptr CShellBrowser, fEnable:DWORD 195 | 196 | DebugOut "IOleInPlaceFrame::EnableModeless(%u)", fEnable 197 | return S_OK 198 | 199 | EnableModeless endp 200 | 201 | TranslateAccelerator_ proc this_:ptr CShellBrowser, lpmsg:ptr MSG, wID:WORD 202 | 203 | DebugOut "IOleInPlaceFrame::TranslateAccelerator" 204 | return S_FALSE 205 | 206 | TranslateAccelerator_ endp 207 | 208 | endif 209 | 210 | end 211 | -------------------------------------------------------------------------------- /CServiceProvider.asm: -------------------------------------------------------------------------------- 1 | 2 | ;--- the IShellBrowser object may be asked for IServiceProvider 3 | ;--- main purpose seems to get an IShellBrowser instance of 4 | ;--- the top level explorer (SID_STopLevelBrowser) 5 | ;--- In this case we just return the current IShellBrowser object 6 | 7 | .386 8 | .model flat, stdcall 9 | option casemap:none 10 | option proc:private 11 | 12 | .nolist 13 | .nocref 14 | WIN32_LEAN_AND_MEAN equ 1 15 | INCL_OLE2 equ 1 16 | _WIN32_IE equ 500h 17 | include windows.inc 18 | include commctrl.inc 19 | include windowsx.inc 20 | 21 | include macros.inc 22 | 23 | include shellapi.inc 24 | include objidl.inc 25 | include olectl.inc 26 | include shlguid.inc 27 | include shlobj.inc 28 | include shlwapi.inc 29 | include shobjidl.inc 30 | 31 | 32 | ?AGGREGATION = 0 ;no aggregation 33 | ?EVENTSUPPORT = 0 ;no event support 34 | 35 | include olecntrl.inc 36 | include debugout.inc 37 | include rsrc.inc 38 | .list 39 | .cref 40 | 41 | INSIDE_CShellBrowser equ 1 42 | 43 | include CShellBrowser.inc 44 | 45 | ?TOPLEVELBROWSER equ 0 46 | 47 | if ?SERVICEPROVIDER 48 | 49 | .data 50 | if ?TOPLEVELBROWSER 51 | g_pShellBrowser LPSHELLBROWSER NULL 52 | g_pServiceProvider LPSERVICEPROVIDER NULL 53 | endif 54 | g_bInit BOOLEAN FALSE 55 | 56 | .const 57 | 58 | CServiceProviderVtbl label dword 59 | IUnknownVtbl {QueryInterface_, AddRef_, Release_} 60 | dd QueryService_ 61 | 62 | 63 | if ?TOPLEVELBROWSER 64 | CLSID_Browser GUID {0A5E46E3Ah, 8849h, 11D1h, {9Dh,8Ch,00h,0C0h,4Fh,0C9h,9Dh,61h}} 65 | endif 66 | if ?WEBBROWSER 67 | CLSID_NotKnown GUID {0D7D1D00h, 6FC0h, 11D0h, {0A9h,74h,00h,0C0h,4Fh,0D7h,05h,0A2h}} 68 | CLSID_WebBrowser GUID {8856F961h,340Ah,11D0h, {0A9h,6Bh,00h,0C0h,4Fh,0D7h,05h,0A2h}} 69 | endif 70 | ;SID_STopWindow sSID_STopWindow 71 | 72 | .code 73 | 74 | __this textequ 75 | _this textequ <[__this].CShellBrowser> 76 | 77 | MEMBER hWnd, hWndTV 78 | if ?WEBBROWSER 79 | MEMBER pWebBrowser 80 | endif 81 | 82 | @MakeStubsEx CShellBrowser, IServiceProvider, QueryInterface, AddRef, Release 83 | @MakeStubs CShellBrowser, IServiceProvider, QueryService 84 | 85 | ;SID_STopLevelBrowser sSID_STopLevelBrowser 86 | 87 | 88 | Init proc 89 | 90 | mov g_bInit, TRUE 91 | if ?TOPLEVELBROWSER 92 | invoke CoCreateInstance, addr CLSID_Browser, NULL, CLSCTX_INPROC_SERVER,\ 93 | addr IID_IServiceProvider, addr g_pServiceProvider 94 | .if (eax == S_OK) 95 | invoke vf(g_pServiceProvider, IServiceProvider, QueryService), addr SID_STopLevelBrowser,\ 96 | addr IID_IShellBrowser, addr g_pShellBrowser 97 | .endif 98 | .if (!g_pShellBrowser) 99 | mov eax, __this 100 | mov g_pShellBrowser, eax 101 | invoke vf(g_pShellBrowser, IUnknown, AddRef) 102 | .endif 103 | endif 104 | ret 105 | Init endp 106 | 107 | Deinit@IServiceProvider proc public 108 | if ?TOPLEVELBROWSER 109 | .if (g_pShellBrowser) 110 | invoke vf(g_pShellBrowser, IUnknown, Release) 111 | .endif 112 | .if (g_pServiceProvider) 113 | invoke vf(g_pServiceProvider, IUnknown, Release) 114 | .endif 115 | endif 116 | ret 117 | Deinit@IServiceProvider endp 118 | 119 | QueryService proc uses __this this_:ptr CShellBrowser, guidService:REFGUID, riid:REFIID, ppv:ptr LPVOID 120 | ifdef _DEBUG 121 | local szGUID[40]:byte 122 | local wszGUID[40]:word 123 | local szIID[40]:byte 124 | local wszIID[40]:word 125 | invoke StringFromGUID2, guidService, addr wszGUID, 40 126 | invoke WideCharToMultiByte, CP_ACP, 0, addr wszGUID, -1, addr szGUID, 40, NULL, NULL 127 | invoke StringFromGUID2, riid, addr wszIID, 40 128 | invoke WideCharToMultiByte, CP_ACP, 0, addr wszIID, -1, addr szIID, 40, NULL, NULL 129 | endif 130 | mov __this, this_ 131 | .if (!g_bInit) 132 | invoke Init 133 | .endif 134 | invoke IsEqualGUID, guidService, addr SID_SShellBrowser 135 | .if (eax) 136 | DebugOut "CShellBrowser::QueryService(SID_SShellBrowser[%s], %s)", addr szGUID, addr szIID 137 | invoke vf(__this, IUnknown, QueryInterface), riid, ppv 138 | ret 139 | .endif 140 | invoke IsEqualGUID, guidService, addr SID_STopWindow 141 | .if (eax) 142 | DebugOut "CShellBrowser::QueryService(SID_STopWindow[%s], %s)", addr szGUID, addr szIID 143 | invoke vf(__this, IUnknown, QueryInterface), riid, ppv 144 | ret 145 | .endif 146 | ;------------------- without that query the statusline remains blank in XP 147 | invoke IsEqualGUID, guidService, addr SID_STopLevelBrowser 148 | .if (eax) 149 | DebugOut "CShellBrowser::QueryService(SID_STopLevelBrowser[%s], %s)", addr szGUID, addr szIID 150 | if ?TOPLEVELBROWSER 151 | invoke vf(g_pShellBrowser, IShellBrowser, QueryInterface), riid, ppv 152 | else 153 | invoke vf(__this, IUnknown, QueryInterface), riid, ppv 154 | endif 155 | ret 156 | .endif 157 | DebugOut "CShellBrowser::QueryService(%s, %s)", addr szGUID, addr szIID 158 | if ?WEBBROWSER 159 | invoke IsEqualGUID, guidService, addr CLSID_NotKnown 160 | .if (eax) 161 | .if (!m_pWebBrowser) 162 | invoke CoCreateInstance, addr CLSID_WebBrowser, NULL, CLSCTX_INPROC_SERVER,\ 163 | addr IID_IWebBrowser, addr m_pWebBrowser 164 | .endif 165 | .if (m_pWebBrowser) 166 | invoke vf(m_pWebBrowser, IUnknown, AddRef) 167 | .endif 168 | mov ecx,ppv 169 | mov eax, m_pWebBrowser 170 | mov [ecx], eax 171 | return S_OK 172 | .endif 173 | endif 174 | mov ecx, ppv 175 | mov dword ptr [ecx], NULL 176 | return E_NOINTERFACE 177 | 178 | QueryService endp 179 | 180 | endif 181 | 182 | end 183 | -------------------------------------------------------------------------------- /CShellBrowser.asm: -------------------------------------------------------------------------------- 1 | 2 | ;--- CShellBrowser object 3 | ;--- that's a simple explorer 4 | 5 | .386 6 | .model flat, stdcall 7 | option casemap:none 8 | option proc:private 9 | 10 | .nolist 11 | .nocref 12 | WIN32_LEAN_AND_MEAN equ 1 13 | INCL_OLE2 equ 1 14 | _WIN32_IE equ 500h 15 | include windows.inc 16 | include commctrl.inc 17 | include dde.inc 18 | include windowsx.inc 19 | include wincrack.inc 20 | 21 | include shellapi.inc 22 | include objidl.inc 23 | include olectl.inc 24 | include shlguid.inc 25 | include shlobj.inc 26 | include shlwapi.inc 27 | include shobjidl.inc 28 | 29 | ?AGGREGATION = 0 ;no aggregation 30 | ?EVENTSUPPORT = 0 ;no event support 31 | 32 | include olecntrl.inc 33 | include debugout.inc 34 | include rsrc.inc 35 | .list 36 | .cref 37 | 38 | include macros.inc 39 | 40 | 41 | INSIDE_CShellBrowser equ 1 42 | 43 | include CShellBrowser.inc 44 | 45 | 46 | SFGAOF typedef DWORD 47 | 48 | ?IMAGELIST equ 1 ;use IExtractIcon and set icons in tree view 49 | ?RETURNCMD equ 1 50 | 51 | WM_SHNOTIFY equ 401h ;window message for shell change notifications 52 | WM_GETISHELLBROWSER equ 407h ;undocumented window message 53 | 54 | ;--- pointer to SHNOTIFYSTRUCT is in wParam of WM_SHNOTIFY 55 | 56 | SHNOTIFYSTRUCT struct 57 | dwItem1 DWORD ? 58 | dwItem2 DWORD ? 59 | SHNOTIFYSTRUCT ends 60 | 61 | 62 | IDM_FIRST equ FCIDM_SHVIEWFIRST 63 | IDM_LAST equ IDM_FIRST+100 64 | 65 | 66 | WndProc PROTO :HWND, :DWORD, :WPARAM, :LPARAM 67 | WndProc@CShellBrowser PROTO :ptr CShellBrowser, :DWORD, :WPARAM, :LPARAM 68 | Destroy@CShellBrowser PROTO :ptr CShellBrowser 69 | SetShellView@CShellBrowser PROTO :ptr CShellBrowser, :LPSHELLVIEW 70 | ;SHBindToParent PROTO :LPITEMIDLIST, :REFIID, :ptr LPUNKNOWN, :ptr LPITEMIDLIST 71 | OnSize PROTO 72 | InsertChildItems PROTO :HANDLE 73 | GetFolder PROTO :HANDLE 74 | GetDDEVariables PROTO 75 | OnDDEExecute PROTO :LPSTR 76 | TranslateAcceleratorSB PROTO :ptr CShellBrowser, lpmsg:ptr MSG, wID:WORD 77 | 78 | 79 | .data 80 | 81 | g_hAccel HACCEL NULL 82 | g_hCursor HCURSOR NULL 83 | g_hHalftoneBrush HBRUSH NULL 84 | g_hWndFocus HWND NULL 85 | g_dwCount DWORD 0 86 | g_rect RECT {0,0,0,0} 87 | g_himl HANDLE NULL 88 | g_EditWndProc DWORD 0 89 | if ?DRAGDROPHELPER 90 | g_pDropTargetHelper LPDROPTARGETHELPER NULL 91 | endif 92 | g_szPath db MAX_PATH dup(9) 93 | 94 | 95 | protoSHChangeNotifyRegister typedef proto :HWND, :DWORD, :DWORD, :DWORD, :DWORD, :ptr LPITEMIDLIST 96 | protoSHChangeNotifyUnregister typedef proto :HANDLE 97 | protoSHParseDisplayName typedef proto :ptr WORD, :DWORD, :ptr LPITEMIDLIST, :SFGAOF, :ptr SFGAOF 98 | 99 | LPFNSHCHANGENOTIFYREGISTER typedef ptr protoSHChangeNotifyRegister 100 | LPFNSHCHANGENOTIFYUNREGISTER typedef ptr protoSHChangeNotifyUnregister 101 | LPFNSHPARSEDISPLAYNAME typedef ptr protoSHParseDisplayName 102 | 103 | g_lpfnSHChangeNotifyRegister LPFNSHCHANGENOTIFYREGISTER NULL 104 | g_lpfnSHChangeNotifyUnregister LPFNSHCHANGENOTIFYUNREGISTER NULL 105 | g_lpfnSHParseDisplayName LPFNSHPARSEDISPLAYNAME NULL 106 | 107 | g_bSort BOOLEAN TRUE 108 | g_bRegistered BOOLEAN FALSE 109 | g_bGetUIObjectOf BOOLEAN TRUE 110 | g_bCreateView BOOLEAN FALSE 111 | g_bCompMenus BOOLEAN TRUE 112 | g_bStatusBar BOOLEAN TRUE 113 | g_bDropTarget BOOLEAN TRUE 114 | g_bTrackSelect BOOLEAN TRUE 115 | g_bBrowseFiles BOOLEAN TRUE 116 | 117 | .const 118 | 119 | align 4 120 | 121 | ;IID_IShellBrowser sIID_IShellBrowser 122 | ;IID_IShellFolder sIID_IShellFolder 123 | ;IID_IShellView sIID_IShellView 124 | ;IID_IContextMenu sIID_IContextMenu 125 | if ?DRAGDROPHELPER 126 | ;CLSID_DragDropHelper sCLSID_DragDropHelper 127 | ;IID_IDropTargetHelper sIID_IDropTargetHelper 128 | endif 129 | 130 | ;--- vtable for interface IShellBrowser 131 | 132 | CShellBrowserVtbl label dword 133 | IUnknownVtbl {QueryInterface@CShellBrowser, AddRef@CShellBrowser, Release@CShellBrowser} 134 | dd GetWindow_, ContextSensitiveHelp 135 | dd InsertMenusSB, SetMenuSB, RemoveMenusSB 136 | dd SetStatusTextSB, EnableModelessSB, TranslateAcceleratorSB 137 | dd BrowseObject, GetViewStateStream, GetControlWindow 138 | dd SendControlMsg, QueryActiveShellView, OnViewWindowActive, SetToolbarItems 139 | 140 | 141 | if ?OLECOMMANDTARGET 142 | @if1 textequ <, IOleCommandTarget> 143 | else 144 | @if1 textequ <> 145 | endif 146 | if ?SERVICEPROVIDER 147 | @if2 textequ <, IServiceProvider> 148 | else 149 | @if2 textequ <> 150 | endif 151 | if ?DROPTARGET 152 | @if3 textequ <, IDropTarget> 153 | else 154 | @if3 textequ <> 155 | endif 156 | if ?OLEINPLACEFRAME 157 | @if4 textequ <, IOleWindow, IOleInPlaceUIWindow, IOleInPlaceFrame> 158 | else 159 | @if4 textequ <> 160 | endif 161 | 162 | % DEFINE_KNOWN_INTERFACES CShellBrowser, IShellBrowser @if1 @if2 @if3 @if4 163 | 164 | szAppNameEx db " - " 165 | szAppName db "ExplorerASM",0 166 | 167 | ifdef _DEBUG 168 | DEBUGPREFIX LPSTR CStr("ExplorerASM:") 169 | endif 170 | 171 | szShell32 db "Shell32.dll",0 172 | 173 | .code 174 | 175 | __this textequ 176 | _this textequ <[__this].CShellBrowser> 177 | 178 | MEMBER _IShellBrowser, ObjRefCount 179 | MEMBER hWnd, hWndTV, hWndView, hWndSB, hWndFocus 180 | MEMBER pShellFolder, pShellView, pContextMenu2, pStream, pMalloc 181 | MEMBER rect, dwSizeTV, hSHNotify 182 | MEMBER bCreateView, bGetUIObjectOf, bCompMenus, bStatusBar 183 | MEMBER bDropTarget, bDontRespond, bLabelEdit 184 | if ?OLEINPLACEFRAME 185 | MEMBER _IOleInPlaceFrame, pOleInPlaceActiveObject 186 | endif 187 | if ?WEBBROWSER 188 | MEMBER pWebBrowser 189 | endif 190 | 191 | DEFINE_STD_COM_METHODS CShellBrowser 192 | 193 | 194 | ;--- InitApp: this proc is called only once 195 | 196 | 197 | InitApp proc 198 | 199 | local hShell32:HINSTANCE 200 | local pShellIcon:LPSHELLICON 201 | local wNullPidl:WORD 202 | local iIndex:DWORD 203 | local osvi:OSVERSIONINFO 204 | local hIcon:HICON 205 | local dwSize:DWORD 206 | local dwType:DWORD 207 | local szPath[MAX_PATH]:byte 208 | 209 | mov osvi.dwOSVersionInfoSize, sizeof OSVERSIONINFO 210 | invoke GetVersionEx, addr osvi 211 | 212 | invoke LoadLibrary, addr szShell32 213 | mov hShell32, eax 214 | 215 | .if (eax > 32) 216 | invoke GetProcAddress, hShell32, 2 217 | mov g_lpfnSHChangeNotifyRegister, eax 218 | invoke GetProcAddress, hShell32, 4 219 | mov g_lpfnSHChangeNotifyUnregister, eax 220 | invoke GetProcAddress, hShell32, CStr("SHParseDisplayName") 221 | mov g_lpfnSHParseDisplayName, eax 222 | .endif 223 | 224 | invoke LoadCursor, g_hInstance, IDC_CURSOR1 225 | mov g_hCursor, eax 226 | invoke LoadAccelerators, g_hInstance, IDR_ACCELERATOR1 227 | mov g_hAccel, eax 228 | if ?IMAGELIST 229 | if 0 230 | invoke GetSystemMetrics, SM_CXSMICON ;returns 0014h ????? 231 | else 232 | mov eax, 0010h 233 | endif 234 | .if ((osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osvi.dwMajorVersion >= 5)) 235 | invoke ImageList_Create, eax, eax, ILC_COLOR32 or ILC_MASK, 4, 4 236 | .else 237 | mov g_bBrowseFiles, FALSE 238 | invoke ImageList_Create, eax, eax, ILC_COLORDDB or ILC_MASK, 4, 4 239 | .endif 240 | mov g_himl, eax 241 | if 0 242 | mov dwSize, sizeof szPath 243 | invoke SHGetValue, HKEY_CLASSES_ROOT, CStr("Folder\DefaultIcon"),CStr(""), 244 | addr dwType, addr szPath, addr dwSize 245 | .if (eax == S_OK) 246 | mov eax, ',' 247 | invoke StrChr, addr szPath, eax 248 | .if (eax) 249 | mov byte ptr [eax], 0 250 | xor eax, eax 251 | invoke ExtractIcon, g_hInstance, addr szPath, eax 252 | push eax 253 | invoke ImageList_AddIcon, g_himl, eax 254 | pop eax 255 | invoke DestroyIcon, eax 256 | .endif 257 | .endif 258 | else 259 | invoke ExtractIcon, g_hInstance, addr szShell32, 3 260 | .if (eax) 261 | push eax 262 | invoke ImageList_AddIcon( g_himl, eax) 263 | pop eax 264 | invoke DestroyIcon, eax 265 | .endif 266 | invoke ExtractIcon, g_hInstance, addr szShell32, 4 267 | .if (eax) 268 | push eax 269 | invoke ImageList_AddIcon( g_himl, eax) 270 | pop eax 271 | invoke DestroyIcon, eax 272 | .endif 273 | endif 274 | if 0 275 | mov iIndex, 34 276 | invoke vf(m_pShellFolder, IUnknown, QueryInterface), addr IID_IShellIcon, addr pShellIcon 277 | .if (eax == S_OK) 278 | mov wNullPidl,0 279 | invoke vf(pShellIcon, IShellIcon, GetIconOf), addr wNullPidl, GIL_FORSHELL, addr iIndex 280 | invoke vf(pShellIcon, IUnknown, Release) 281 | .endif 282 | invoke ExtractIcon, g_hInstance, addr szShell32, iIndex 283 | else 284 | invoke ExtractIcon, g_hInstance, addr szShell32, 34 285 | endif 286 | .if (eax) 287 | push eax 288 | invoke ImageList_AddIcon( g_himl, eax) 289 | pop eax 290 | invoke DestroyIcon, eax 291 | .endif 292 | endif 293 | invoke GetDDEVariables 294 | if ?DRAGDROPHELPER 295 | invoke CoCreateInstance, addr CLSID_DragDropHelper, NULL, 296 | CLSCTX_INPROC_SERVER, addr IID_IDropTargetHelper, addr g_pDropTargetHelper 297 | endif 298 | 299 | invoke FreeLibrary, hShell32 300 | 301 | ret 302 | 303 | InitApp endp 304 | 305 | 306 | ;--- create a CShellBrowser object 307 | 308 | 309 | Create@CShellBrowser proc public uses __this pUnknown:LPUNKNOWN 310 | 311 | 312 | DebugOut "Create@CShellBrowser" 313 | invoke LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT,sizeof CShellBrowser 314 | .if (eax == NULL) 315 | ret 316 | .endif 317 | mov __this,eax 318 | 319 | mov m__IShellBrowser.lpVtbl, offset CShellBrowserVtbl 320 | 321 | if ?SERVICEPROVIDER 322 | mov m__IServiceProvider.lpVtbl, offset CServiceProviderVtbl 323 | endif 324 | if ?OLECOMMANDTARGET 325 | mov m__IOleCommandTarget.lpVtbl, offset COleCommandTargetVtbl 326 | endif 327 | if ?DROPTARGET 328 | mov m__IDropTarget.lpVtbl, offset CDropTargetVtbl 329 | endif 330 | if ?OLEINPLACEFRAME 331 | mov m__IOleInPlaceFrame.lpVtbl, offset COleInPlaceFrameVtbl 332 | endif 333 | 334 | STD_COM_CONSTRUCTOR CShellBrowser 335 | 336 | invoke vf(pUnknown, IUnknown, QueryInterface), addr IID_IShellFolder, addr m_pShellFolder 337 | .if (eax != S_OK) 338 | invoke Destroy@CShellBrowser, __this 339 | return 0 340 | .endif 341 | 342 | mov m_dwSizeTV, -1 343 | 344 | invoke SHGetMalloc, addr m_pMalloc 345 | 346 | .if (!g_dwCount) 347 | invoke InitApp 348 | .endif 349 | 350 | inc g_dwCount 351 | 352 | return __this 353 | align 4 354 | 355 | Create@CShellBrowser endp 356 | 357 | ;--- delete a CShellBrowser object 358 | 359 | Destroy@CShellBrowser proc uses __this this_:ptr CShellBrowser 360 | 361 | DebugOut "Destroy@CShellBrowser(%X)", this_ 362 | 363 | mov __this, this_ 364 | 365 | STD_COM_DESTRUCTOR CShellBrowser 366 | 367 | if ?WEBBROWSER 368 | .if (m_pWebBrowser) 369 | invoke vf(m_pWebBrowser, IUnknown, Release) 370 | .endif 371 | endif 372 | .if (m_pShellView) 373 | invoke vf(m_pShellView, IUnknown, Release) 374 | .endif 375 | .if (m_pShellFolder) 376 | invoke vf(m_pShellFolder, IUnknown, Release) 377 | .endif 378 | .if (m_pStream) 379 | invoke vf(m_pStream, IUnknown, Release) 380 | .endif 381 | .if (m_pMalloc) 382 | invoke vf(m_pMalloc, IUnknown, Release) 383 | .endif 384 | 385 | dec g_dwCount 386 | .if (!g_dwCount) 387 | if ?DRAGDROPHELPER 388 | .if (g_pDropTargetHelper) 389 | invoke vf(g_pDropTargetHelper, IUnknown, Release) 390 | .endif 391 | endif 392 | if ?IMAGELIST 393 | .if (g_himl) 394 | invoke ImageList_Destroy, g_himl 395 | .endif 396 | endif 397 | .if (g_aApplication) 398 | invoke GlobalDeleteAtom, g_aApplication 399 | .endif 400 | .if (g_aTopic) 401 | invoke GlobalDeleteAtom, g_aTopic 402 | .endif 403 | .endif 404 | 405 | invoke LocalFree, this_ 406 | ret 407 | align 4 408 | 409 | Destroy@CShellBrowser endp 410 | 411 | 412 | Show@CShellBrowser proc public uses __this this_:ptr CShellBrowser, hWnd:HWND 413 | 414 | local wc:WNDCLASSEX 415 | 416 | mov __this, this_ 417 | .if (hWnd) 418 | invoke GetWindowRect, hWnd, addr m_rect 419 | mov eax, m_rect.right 420 | sub eax, m_rect.left 421 | mov m_rect.right, eax 422 | mov eax, m_rect.bottom 423 | sub eax, m_rect.top 424 | mov m_rect.bottom, eax 425 | add m_rect.left, 16 426 | add m_rect.top, 16 427 | .endif 428 | .if (!g_bRegistered) 429 | invoke RtlZeroMemory, addr wc, sizeof WNDCLASSEX 430 | mov wc.cbSize, sizeof WNDCLASSEX 431 | mov wc.style, 0 432 | mov wc.lpfnWndProc, WndProc 433 | mov eax, g_hInstance 434 | mov wc.hInstance, eax 435 | invoke LoadIcon, g_hInstance, IDI_ICON1 436 | mov wc.hIcon, eax 437 | invoke LoadCursor, NULL, IDC_ARROW 438 | mov wc.hCursor, eax 439 | mov wc.hbrBackground, COLOR_BTNFACE + 1 440 | mov wc.lpszMenuName, IDR_MENU1 441 | mov wc.lpszClassName, offset szAppName 442 | mov wc.hIconSm, NULL 443 | invoke RegisterClassEx, addr wc 444 | mov g_bRegistered, TRUE 445 | .endif 446 | invoke CreateWindowEx, 0, offset szAppName, CStr(""), 447 | WS_OVERLAPPEDWINDOW or WS_VISIBLE, m_rect.left, m_rect.top, m_rect.right, m_rect.bottom,\ 448 | hWnd, NULL, g_hInstance, __this 449 | ret 450 | align 4 451 | 452 | Show@CShellBrowser endp 453 | 454 | ;--- send key to view (but do NOT if treeview is in label edit mode) 455 | 456 | TranslateAccelerator@CShellBrowser proc public uses __this this_:ptr CShellBrowser, lpmsg:ptr MSG 457 | 458 | mov __this, this_ 459 | mov eax, S_FALSE 460 | .if (!m_bLabelEdit) 461 | mov eax, m_hWndFocus 462 | .if (eax == m_hWndView) 463 | invoke vf(m_pShellView, IShellView, TranslateAccelerator), lpmsg 464 | .if (eax == S_FALSE) 465 | invoke TranslateAcceleratorSB, __this, lpmsg, NULL 466 | .endif 467 | .else 468 | invoke TranslateAcceleratorSB, __this, lpmsg, NULL 469 | .if (eax == S_FALSE && m_pShellView) 470 | invoke vf(m_pShellView, IShellView, TranslateAccelerator), lpmsg 471 | .endif 472 | .endif 473 | .endif 474 | ret 475 | align 4 476 | 477 | TranslateAccelerator@CShellBrowser endp 478 | 479 | 480 | ;---------------------------------------------------------------- 481 | 482 | if 0 483 | ;--- this function is not available in win9x and winnt systems 484 | 485 | SHBindToParent proc uses esi edi pidl:LPITEMIDLIST, riid:REFIID, ppUnknown:ptr LPUNKNOWN, ppidl:ptr LPITEMIDLIST 486 | 487 | local pShellFolder:LPSHELLFOLDER 488 | local hr:DWORD 489 | 490 | xor ecx, ecx 491 | 492 | mov eax, ppidl 493 | .if (eax) 494 | mov [eax],ecx 495 | .endif 496 | mov eax, ppUnknown 497 | mov [eax], ecx 498 | 499 | mov edx, pidl 500 | .while (edx) 501 | movzx eax,[edx].SHITEMID.cb 502 | .break .if (!eax) 503 | mov esi, ecx 504 | add ecx, eax 505 | lea edx, [eax][edx] 506 | .endw 507 | add esi, sizeof WORD 508 | invoke vf(m_pMalloc, IMalloc, Alloc), esi 509 | .if (eax) 510 | mov ecx, esi 511 | mov esi, pidl 512 | mov edi, eax 513 | rep movsb 514 | mov [edi-2],cx 515 | mov edi, eax 516 | invoke vf(m_pShellFolder, IShellFolder, BindToObject), edi, NULL,\ 517 | riid, addr pShellFolder 518 | mov hr, eax 519 | .if (eax == S_OK) 520 | .if (ppidl) 521 | mov ecx, ppidl 522 | mov [ecx],edi 523 | .else 524 | invoke vf(m_pMalloc, IMalloc, Free), edi 525 | .endif 526 | mov ecx, ppUnknown 527 | mov eax, pShellFolder 528 | mov [ecx], eax 529 | .else 530 | invoke vf(m_pMalloc, IMalloc, Free), edi 531 | .endif 532 | mov eax, hr 533 | .else 534 | mov eax, E_OUTOFMEMORY 535 | .endif 536 | ret 537 | align 4 538 | 539 | SHBindToParent endp 540 | endif 541 | 542 | ;---------------------------------------------------------------- 543 | 544 | ;--- release IShellView 545 | 546 | ReleaseShellView proc uses esi 547 | 548 | .if (m_pShellView) 549 | invoke vf(m_pShellView, IShellView, UIActivate), SVUIA_DEACTIVATE 550 | .if (m_hWndView) 551 | mov eax, m_hWndFocus 552 | .if (eax == m_hWndView) 553 | mov m_hWndFocus, NULL 554 | .endif 555 | invoke vf(m_pShellView, IShellView, DestroyViewWindow) 556 | mov m_hWndView, NULL 557 | .endif 558 | invoke vf(m_pShellView, IUnknown, Release) 559 | mov m_pShellView, NULL 560 | .endif 561 | ret 562 | align 4 563 | 564 | ReleaseShellView endp 565 | 566 | 567 | ;--- update menu items 568 | 569 | UpdateMenu proc 570 | 571 | local hMenu:HMENU 572 | 573 | invoke GetMenu, m_hWnd 574 | mov hMenu, eax 575 | 576 | .if (m_bStatusBar) 577 | mov ecx, MF_CHECKED 578 | .else 579 | mov ecx, MF_UNCHECKED 580 | .endif 581 | invoke CheckMenuItem, hMenu, IDM_STATUSLINE, ecx 582 | 583 | .if (m_bCreateView) 584 | mov ecx, MF_CHECKED 585 | .else 586 | mov ecx, MF_UNCHECKED 587 | .endif 588 | invoke CheckMenuItem, hMenu, IDM_CREATEVIEWOBJECT, ecx 589 | 590 | .if (m_bGetUIObjectOf) 591 | mov ecx, MF_CHECKED 592 | .else 593 | mov ecx, MF_UNCHECKED 594 | .endif 595 | invoke CheckMenuItem, hMenu, IDM_GETUIOBJECTOF, ecx 596 | 597 | .if (m_bCompMenus) 598 | mov ecx, MF_CHECKED 599 | .else 600 | mov ecx, MF_UNCHECKED 601 | .endif 602 | invoke CheckMenuItem, hMenu, IDM_COMPMENUS, ecx 603 | 604 | .if (m_bDropTarget) 605 | mov ecx, MF_CHECKED 606 | .else 607 | mov ecx, MF_UNCHECKED 608 | .endif 609 | invoke CheckMenuItem, hMenu, IDM_DROPTARGET, ecx 610 | 611 | .if (g_bTrackSelect) 612 | mov ecx, MF_CHECKED 613 | .else 614 | mov ecx, MF_UNCHECKED 615 | .endif 616 | invoke CheckMenuItem, hMenu, IDM_TRACKSELECT, ecx 617 | 618 | .if (!m_bDontRespond) 619 | mov ecx, MF_CHECKED 620 | .else 621 | mov ecx, MF_UNCHECKED 622 | .endif 623 | invoke CheckMenuItem, hMenu, IDM_DDERESPOND, ecx 624 | 625 | .if (g_bBrowseFiles) 626 | mov ecx, MF_CHECKED 627 | .else 628 | mov ecx, MF_UNCHECKED 629 | .endif 630 | invoke CheckMenuItem, hMenu, IDM_BROWSEFILES, ecx 631 | 632 | ret 633 | align 4 634 | 635 | UpdateMenu endp 636 | 637 | ;--- get attributes of an item 638 | 639 | GetAttributes proc hItem:HANDLE, pdwAttributes:ptr DWORD 640 | 641 | local pShellFolder:LPSHELLFOLDER 642 | local pItemIDList:LPITEMIDLIST 643 | local tvi:TV_ITEM 644 | 645 | mov eax, hItem 646 | mov tvi.hItem, eax 647 | mov tvi.mask_, TVIF_PARAM 648 | invoke TreeView_GetItem( m_hWndTV, addr tvi) 649 | mov eax, tvi.lParam 650 | .if (!eax) 651 | ret 652 | .endif 653 | mov pItemIDList, eax 654 | 655 | invoke TreeView_GetParent( m_hWndTV, hItem) 656 | invoke GetFolder, eax 657 | .if (eax) 658 | mov pShellFolder, eax 659 | invoke vf(pShellFolder, IShellFolder, GetAttributesOf), 1, addr pItemIDList, 660 | pdwAttributes 661 | push eax 662 | invoke vf(pShellFolder, IShellFolder, Release) 663 | pop eax 664 | .if (eax == S_OK) 665 | mov eax, TRUE 666 | .else 667 | xor eax, eax 668 | .endif 669 | .endif 670 | ret 671 | align 4 672 | 673 | GetAttributes endp 674 | 675 | 676 | if 0 677 | 678 | ;--- check if a folder is on a removeable device 679 | 680 | IsRemoveable proc hItem:HANDLE 681 | 682 | local sfgaof:SFGAOF 683 | 684 | mov sfgaof, SFGAO_REMOVABLE 685 | invoke GetAttributes, hItem, addr sfgaof 686 | .if ((eax) && (sfgaof & SFGAO_REMOVABLE)) 687 | mov eax, TRUE 688 | .else 689 | mov eax, FALSE 690 | .endif 691 | ret 692 | align 4 693 | 694 | IsRemoveable endp 695 | 696 | endif 697 | 698 | StrRet2String proc pItemIDList:LPITEMIDLIST, pstrret:ptr STRRET, pszText:LPSTR, dwMax:DWORD 699 | 700 | mov ecx, pstrret 701 | .if ([ecx].STRRET.uType == STRRET_WSTR) 702 | invoke WideCharToMultiByte, CP_ACP, 0, [ecx].STRRET.pOleStr, -1, pszText, dwMax, 0, 0 703 | mov ecx, pstrret 704 | invoke vf(m_pMalloc, IMalloc, Free), [ecx].STRRET.pOleStr 705 | mov eax, pszText 706 | .elseif ([ecx].STRRET.uType == STRRET_CSTR) 707 | lea eax, [ecx].STRRET.cStr 708 | .else 709 | mov eax, pItemIDList 710 | add eax,[ecx].STRRET.uOffset 711 | .endif 712 | ret 713 | align 4 714 | 715 | StrRet2String endp 716 | 717 | HRESULT_CODE macro 718 | movsx eax, ax 719 | endm 720 | 721 | SortChildrenCB proc lParam1:LPARAM, lParam2:LPARAM, lParamSort:LPARAM 722 | 723 | local pShellFolder:LPSHELLFOLDER 724 | 725 | mov eax, lParamSort 726 | mov pShellFolder, eax 727 | invoke vf(pShellFolder, IShellFolder, CompareIDs), 0, lParam1, lParam2 728 | HRESULT_CODE 729 | ret 730 | align 4 731 | 732 | SortChildrenCB endp 733 | 734 | 735 | ?TESTMODE equ 0 736 | 737 | if 1 738 | 739 | InsertItem proc hItem:HANDLE, pShellFolder:LPSHELLFOLDER, pidl:LPITEMIDLIST, bValidate:BOOL 740 | 741 | local dwRC:BOOL 742 | local sfgaof:SFGAOF 743 | local strret:STRRET 744 | local tvi:TV_INSERTSTRUCT 745 | local szText[MAX_PATH]:byte 746 | 747 | mov eax, hItem 748 | mov tvi.hParent, eax 749 | .if (bValidate) 750 | mov tvi.hInsertAfter, TVI_SORT 751 | .else 752 | mov tvi.hInsertAfter, TVI_LAST 753 | .endif 754 | lea eax, szText 755 | mov tvi.item.pszText, eax 756 | mov szText,0 757 | 758 | mov dwRC, FALSE 759 | mov strret.uType, STRRET_CSTR 760 | invoke vf(pShellFolder, IShellFolder, GetDisplayNameOf), pidl,\ 761 | SHGDN_INFOLDER, addr strret 762 | .if (eax == S_OK) 763 | mov tvi.item.mask_, TVIF_TEXT or TVIF_PARAM or TVIF_CHILDREN 764 | mov eax, pidl 765 | mov tvi.item.lParam, eax 766 | mov sfgaof, SFGAO_HASSUBFOLDER 767 | .if (g_bBrowseFiles) 768 | or sfgaof, SFGAO_BROWSABLE or SFGAO_FOLDER 769 | .endif 770 | if ?TESTMODE 771 | or sfgaof, SFGAO_COMPRESSED or SFGAO_REMOVABLE 772 | endif 773 | invoke vf(pShellFolder, IShellFolder, GetAttributesOf), 1, addr pidl,\ 774 | addr sfgaof 775 | .if ((eax == S_OK) && (sfgaof & SFGAO_HASSUBFOLDER)) 776 | mov tvi.item.cChildren, 1 777 | .else 778 | .if (g_bBrowseFiles) 779 | mov tvi.item.cChildren, I_CHILDRENCALLBACK 780 | .else 781 | mov tvi.item.cChildren, 0 782 | .endif 783 | .endif 784 | if ?IMAGELIST 785 | or tvi.item.mask_, TVIF_IMAGE or TVIF_SELECTEDIMAGE 786 | mov tvi.item.iSelectedImage, I_IMAGECALLBACK 787 | mov tvi.item.iImage, I_IMAGECALLBACK 788 | endif 789 | .if ((!g_bBrowseFiles) || (sfgaof & (SFGAO_BROWSABLE or SFGAO_FOLDER))) 790 | invoke StrRet2String, pidl, addr strret, tvi.item.pszText, MAX_PATH 791 | mov tvi.item.pszText, eax 792 | if ?TESTMODE 793 | lea ecx, szText 794 | .if (ecx != eax) 795 | mov tvi.item.pszText, ecx 796 | invoke wsprintf, addr szText, CStr("%s,%X"), eax, sfgaof 797 | .else 798 | invoke lstrlen, ecx 799 | lea ecx, szText 800 | add ecx, eax 801 | invoke wsprintf, ecx, CStr(",%X"), sfgaof 802 | .endif 803 | endif 804 | invoke TreeView_InsertItem( m_hWndTV, addr tvi) 805 | mov dwRC, TRUE 806 | .endif 807 | .endif 808 | return dwRC 809 | 810 | InsertItem endp 811 | 812 | 813 | ;--- returns number of childs 814 | 815 | 816 | InsertChildItems proc public hItem:HANDLE 817 | 818 | local pShellFolder:LPSHELLFOLDER 819 | local pEnumIDList:LPENUMIDLIST 820 | local pidl:LPITEMIDLIST 821 | local dwChildren:DWORD 822 | local sortcb:TVSORTCB 823 | local tvi:TV_ITEM 824 | 825 | invoke GetFolder, hItem 826 | .if (!eax) 827 | return -1 828 | .endif 829 | mov pShellFolder, eax 830 | 831 | mov dwChildren, 0 832 | 833 | .if (g_bBrowseFiles) 834 | mov ecx,SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN 835 | .else 836 | mov ecx,SHCONTF_FOLDERS or SHCONTF_INCLUDEHIDDEN 837 | .endif 838 | invoke vf(pShellFolder, IShellFolder, EnumObjects_), m_hWnd, ecx, addr pEnumIDList 839 | .if (eax != S_OK) 840 | invoke vf(pShellFolder, IShellFolder, Release) 841 | return -1 842 | .endif 843 | 844 | ;--------- now enumerate the objects of the folder and insert them 845 | ;--------- into the treeview 846 | 847 | .while (1) 848 | invoke vf(pEnumIDList, IEnumIDList, Next), 1, addr pidl, NULL 849 | .break .if (eax != S_OK) 850 | 851 | invoke InsertItem, hItem, pShellFolder, pidl, FALSE 852 | .if (eax) 853 | inc dwChildren 854 | .endif 855 | .endw 856 | 857 | invoke vf(pEnumIDList, IUnknown, Release) 858 | .if (g_bSort) 859 | mov eax, hItem 860 | mov sortcb.hParent, eax 861 | mov sortcb.lpfnCompare, SortChildrenCB 862 | mov eax, pShellFolder 863 | mov sortcb.lParam, eax 864 | invoke TreeView_SortChildrenCB( m_hWndTV, addr sortcb, 0) 865 | .endif 866 | 867 | invoke vf(pShellFolder, IShellFolder, Release) 868 | 869 | exit: 870 | mov eax, dwChildren 871 | .if (eax) 872 | mov eax, 1 873 | .endif 874 | mov tvi.cChildren, eax 875 | mov eax, hItem 876 | mov tvi.hItem, eax 877 | mov tvi.mask_, TVIF_CHILDREN or TVIF_STATE 878 | mov tvi.state, TVIS_EXPANDEDONCE 879 | mov tvi.stateMask, TVIS_EXPANDEDONCE 880 | invoke TreeView_SetItem( m_hWndTV, addr tvi) 881 | return dwChildren 882 | align 4 883 | 884 | InsertChildItems endp 885 | 886 | 887 | else 888 | 889 | InsertChildItems proc public hItem:HANDLE 890 | 891 | local pShellFolder:LPSHELLFOLDER 892 | local pEnumIDList:LPENUMIDLIST 893 | local pidl:LPITEMIDLIST 894 | local sfgaof:SFGAOF 895 | local dwChildren:DWORD 896 | local strret:STRRET 897 | local sortcb:TVSORTCB 898 | local tvi:TV_INSERTSTRUCT 899 | local szText[MAX_PATH]:byte 900 | 901 | invoke GetFolder, hItem 902 | .if (!eax) 903 | return -1 904 | .endif 905 | mov pShellFolder, eax 906 | 907 | mov eax, hItem 908 | mov tvi.hParent, eax 909 | mov tvi.hInsertAfter, TVI_LAST 910 | 911 | mov dwChildren, 0 912 | 913 | .if (g_bBrowseFiles) 914 | mov ecx,SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN 915 | .else 916 | mov ecx,SHCONTF_FOLDERS or SHCONTF_INCLUDEHIDDEN 917 | .endif 918 | invoke vf(pShellFolder, IShellFolder, EnumObjects), m_hWnd, ecx, addr pEnumIDList 919 | .if (eax != S_OK) 920 | invoke vf(pShellFolder, IShellFolder, Release) 921 | return -1 922 | .endif 923 | 924 | ;--------- now enumerate the objects of the folder and insert them 925 | ;--------- into the treeview 926 | 927 | .while (1) 928 | invoke vf(pEnumIDList, IEnumIDList, Next), 1, addr pidl, NULL 929 | .break .if (eax != S_OK) 930 | mov strret.uType, STRRET_CSTR 931 | invoke vf(pShellFolder, IShellFolder, GetDisplayNameOf), pidl,\ 932 | SHGDN_INFOLDER, addr strret 933 | .if (eax == S_OK) 934 | mov tvi.item.imask, TVIF_TEXT or TVIF_PARAM or TVIF_CHILDREN 935 | mov eax, pidl 936 | mov tvi.item.lParam, eax 937 | mov sfgaof, SFGAO_HASSUBFOLDER 938 | .if (g_bBrowseFiles) 939 | or sfgaof, SFGAO_BROWSABLE or SFGAO_FOLDER 940 | .endif 941 | if ?TESTMODE 942 | or sfgaof, SFGAO_COMPRESSED or SFGAO_REMOVABLE 943 | endif 944 | invoke vf(pShellFolder, IShellFolder, GetAttributesOf), 1, addr pidl,\ 945 | addr sfgaof 946 | .if ((eax == S_OK) && (sfgaof & SFGAO_HASSUBFOLDER)) 947 | mov tvi.item.cChildren, 1 948 | .else 949 | .if (g_bBrowseFiles) 950 | mov tvi.item.cChildren, I_CHILDRENCALLBACK 951 | .else 952 | mov tvi.item.cChildren, 0 953 | .endif 954 | .endif 955 | if ?IMAGELIST 956 | or tvi.item.imask, TVIF_IMAGE or TVIF_SELECTEDIMAGE 957 | mov tvi.item.iSelectedImage, I_IMAGECALLBACK 958 | mov tvi.item.iImage, I_IMAGECALLBACK 959 | endif 960 | .if ((!g_bBrowseFiles) || (sfgaof & (SFGAO_BROWSABLE or SFGAO_FOLDER))) 961 | invoke StrRet2String, pidl, addr strret, addr szText, sizeof szText 962 | if ?TESTMODE 963 | sub esp, 256 964 | mov edx,esp 965 | invoke wsprintf, edx, CStr("%s,%X"), eax, sfgaof 966 | mov eax,esp 967 | endif 968 | mov tvi.item.pszText, eax 969 | invoke TreeView_InsertItem( m_hWndTV, addr tvi) 970 | if ?TESTMODE 971 | add esp,256 972 | endif 973 | inc dwChildren 974 | .endif 975 | .endif 976 | .endw 977 | 978 | invoke vf(pEnumIDList, IUnknown, Release) 979 | .if (g_bSort) 980 | mov eax, tvi.hParent 981 | mov sortcb.hParent, eax 982 | mov sortcb.lpfnCompare, SortChildrenCB 983 | mov eax, pShellFolder 984 | mov sortcb.lParam, eax 985 | invoke TreeView_SortChildrenCB( m_hWndTV, addr sortcb, 0) 986 | .endif 987 | 988 | invoke vf(pShellFolder, IShellFolder, Release) 989 | 990 | exit: 991 | mov eax, dwChildren 992 | .if (eax) 993 | mov eax, 1 994 | .endif 995 | mov tvi.item.cChildren, eax 996 | mov eax, hItem 997 | mov tvi.item.hItem, eax 998 | mov tvi.item.imask, TVIF_CHILDREN or TVIF_STATE 999 | mov tvi.item.state, TVIS_EXPANDEDONCE 1000 | mov tvi.item.stateMask, TVIS_EXPANDEDONCE 1001 | invoke TreeView_SetItem( m_hWndTV, addr tvi.item) 1002 | return dwChildren 1003 | align 4 1004 | 1005 | InsertChildItems endp 1006 | 1007 | endif 1008 | 1009 | 1010 | GetTextFromCLSID proc pGUID:ptr GUID, pStr:LPSTR, dwSize:dword 1011 | 1012 | local szStr[128]:byte 1013 | local wszStr[40]:word 1014 | local szGUID[40]:byte 1015 | local hKey:HANDLE 1016 | local dwType:dword 1017 | 1018 | mov ecx, pStr 1019 | mov byte ptr [ecx],0 1020 | invoke StringFromGUID2,pGUID,addr wszStr,40 1021 | invoke WideCharToMultiByte,CP_ACP,0,addr wszStr,40,addr szGUID, sizeof szGUID,0,0 1022 | invoke wsprintf,addr szStr,CStr("CLSID\%s"), addr szGUID 1023 | invoke RegOpenKeyEx,HKEY_CLASSES_ROOT,addr szStr,0,KEY_READ,addr hKey 1024 | .if (eax == S_OK) 1025 | invoke RegQueryValueEx,hKey,CStr(""),NULL,addr dwType,pStr,addr dwSize 1026 | invoke RegCloseKey,hKey 1027 | .endif 1028 | ret 1029 | align 4 1030 | 1031 | GetTextFromCLSID endp 1032 | 1033 | 1034 | RefreshView proc 1035 | 1036 | local pItemIDList:LPITEMIDLIST 1037 | local pidl:LPITEMIDLIST 1038 | local pPersistFolder:LPPERSISTFOLDER 1039 | local dwSize:DWORD 1040 | local tvi:TV_INSERTSTRUCT 1041 | local hItem:HANDLE 1042 | local clsid:CLSID 1043 | local szText[128]:byte 1044 | 1045 | invoke TreeView_GetSelection( m_hWndTV) 1046 | .if (eax) 1047 | invoke GetFullPidl@CShellBrowser, eax 1048 | mov pidl, eax 1049 | .else 1050 | mov pidl, NULL 1051 | .endif 1052 | 1053 | ;; invoke ReleaseShellView 1054 | 1055 | invoke SetWindowRedraw( m_hWndTV, FALSE) 1056 | 1057 | ;----------------------------- remove selection before deleteall 1058 | invoke TreeView_SelectItem( m_hWndTV, NULL) 1059 | 1060 | invoke TreeView_DeleteAllItems( m_hWndTV) 1061 | 1062 | mov tvi.hParent, 0 1063 | mov tvi.hInsertAfter, TVI_LAST 1064 | 1065 | invoke vf(m_pShellFolder, IUnknown, QueryInterface), addr IID_IPersistFolder, addr pPersistFolder 1066 | .if (eax == S_OK) 1067 | mov szText, 0 1068 | invoke vf(pPersistFolder, IPersistFolder, GetClassID), addr clsid 1069 | invoke GetTextFromCLSID, addr clsid, addr szText, sizeof szText 1070 | invoke vf(pPersistFolder, IUnknown, Release) 1071 | .else 1072 | invoke lstrcpy, addr szText, CStr("Desktop") 1073 | .endif 1074 | lea eax, szText 1075 | mov tvi.item.pszText, eax 1076 | mov tvi.item.lParam, 0 1077 | if ?IMAGELIST 1078 | mov tvi.item.mask_, TVIF_TEXT or TVIF_PARAM or TVIF_IMAGE or TVIF_SELECTEDIMAGE 1079 | mov tvi.item.iSelectedImage, I_IMAGECALLBACK 1080 | mov tvi.item.iImage, I_IMAGECALLBACK 1081 | else 1082 | mov tvi.item.imask, TVIF_TEXT or TVIF_PARAM 1083 | endif 1084 | invoke TreeView_InsertItem( m_hWndTV, addr tvi) 1085 | mov hItem, eax 1086 | 1087 | if 0 1088 | invoke lstrcat, addr szText, addr szAppNameEx 1089 | invoke SetWindowText, m_hWnd, addr szText 1090 | endif 1091 | 1092 | invoke InsertChildItems, hItem 1093 | 1094 | invoke TreeView_Expand( m_hWndTV, hItem, TVE_EXPAND ) 1095 | 1096 | invoke SetWindowRedraw( m_hWndTV, TRUE) 1097 | 1098 | .if (pidl) 1099 | invoke NavigateToPidl, pidl 1100 | invoke vf(m_pMalloc, IMalloc, Free), pidl 1101 | .else 1102 | invoke TreeView_SelectItem( m_hWndTV, hItem) 1103 | .endif 1104 | 1105 | ret 1106 | align 4 1107 | 1108 | RefreshView endp 1109 | 1110 | ;--- get a full pidl of a treeview item 1111 | ;--- in lParam of TV_ITEM is a relative pidl (from EnumObjects) only 1112 | 1113 | GetFullPidl@CShellBrowser proc public uses esi edi hItem:HANDLE 1114 | 1115 | local dwESP:DWORD 1116 | local tvi:TV_ITEM 1117 | 1118 | mov eax, hItem 1119 | mov tvi.hItem, eax 1120 | 1121 | mov dwESP, esp 1122 | 1123 | xor esi, esi 1124 | xor edi, edi 1125 | mov tvi.mask_, TVIF_PARAM 1126 | .while (eax) 1127 | invoke TreeView_GetItem( m_hWndTV, addr tvi) 1128 | mov eax, tvi.lParam 1129 | .break .if (!eax) 1130 | movzx ecx, [eax].SHITEMID.cb 1131 | add edi, ecx 1132 | inc esi 1133 | push eax 1134 | invoke TreeView_GetParent( m_hWndTV, tvi.hItem) 1135 | mov tvi.hItem, eax 1136 | .endw 1137 | .if (!edi) 1138 | jmp exit 1139 | .endif 1140 | add edi, sizeof WORD 1141 | invoke vf(m_pMalloc, IMalloc, Alloc), edi 1142 | .if (!eax) 1143 | jmp exit 1144 | .endif 1145 | mov edi, eax 1146 | 1147 | mov edx, esi 1148 | .while (edx) 1149 | pop esi 1150 | movzx ecx,[esi].SHITEMID.cb 1151 | rep movsb 1152 | dec edx 1153 | .endw 1154 | mov [edi].SHITEMID.cb,0 1155 | exit: 1156 | mov esp, dwESP 1157 | ret 1158 | align 4 1159 | 1160 | GetFullPidl@CShellBrowser endp 1161 | 1162 | ;--- get an IShellFolder object of a treeview item 1163 | 1164 | GetFolder proc public uses esi hItem:HANDLE 1165 | 1166 | local pidl:LPITEMIDLIST 1167 | local pShellFolder:LPSHELLFOLDER 1168 | 1169 | invoke GetFullPidl@CShellBrowser, hItem 1170 | mov pidl, eax 1171 | .if (eax) 1172 | mov pShellFolder, NULL 1173 | invoke vf(m_pShellFolder, IShellFolder, BindToObject), 1174 | pidl, NULL, addr IID_IShellFolder, addr pShellFolder 1175 | invoke vf(m_pMalloc, IMalloc, Free), pidl 1176 | mov eax, pShellFolder 1177 | .else 1178 | invoke vf(m_pShellFolder, IShellFolder, AddRef) 1179 | mov eax, m_pShellFolder 1180 | .endif 1181 | ret 1182 | align 4 1183 | 1184 | GetFolder endp 1185 | 1186 | 1187 | GetTrueClientRect proc prect:ptr RECT 1188 | 1189 | local rect:RECT 1190 | 1191 | invoke GetClientRect, m_hWnd, prect 1192 | .if (m_bStatusBar) 1193 | invoke GetWindowRect, m_hWndSB, addr rect 1194 | mov ecx, rect.bottom 1195 | sub ecx, rect.top 1196 | mov eax, prect 1197 | sub [eax].RECT.bottom, ecx 1198 | .endif 1199 | ret 1200 | align 4 1201 | 1202 | GetTrueClientRect endp 1203 | 1204 | GetLeftPanelWidth proc prect:ptr RECT 1205 | mov ecx, prect 1206 | .if (m_dwSizeTV != -1) 1207 | mov eax, m_dwSizeTV 1208 | .else 1209 | mov eax, [ecx].RECT.right 1210 | sub eax, [ecx].RECT.left 1211 | invoke MulDiv, eax, 3, 10 1212 | sub eax, GRIPSIZE 1213 | .endif 1214 | ret 1215 | align 4 1216 | 1217 | GetLeftPanelWidth endp 1218 | 1219 | ;--- create a view object based on pidl stored in a treeview item 1220 | 1221 | CreateViewObject proc uses esi hItem:HANDLE 1222 | 1223 | local pShellFolder:LPSHELLFOLDER 1224 | local pShellView:LPSHELLVIEW 1225 | local hWndView:HWND 1226 | local dwWidth:DWORD 1227 | local rect:RECT 1228 | local dwUIActivateFlags:DWORD 1229 | local tvi:TV_ITEM 1230 | local folderset:FOLDERSETTINGS 1231 | 1232 | 1233 | .if ((!m_bCreateView) || (hItem == NULL)) 1234 | invoke ReleaseShellView 1235 | invoke LoadMenu, g_hInstance, IDR_MENU1 1236 | invoke SetMenu, m_hWnd, eax 1237 | invoke UpdateMenu 1238 | invoke OnSize 1239 | return TRUE 1240 | .endif 1241 | 1242 | mov pShellView, NULL 1243 | 1244 | ;------------------------------- get a IShellFolder object 1245 | invoke GetFolder, hItem 1246 | mov pShellFolder, eax 1247 | 1248 | .if (eax) 1249 | DebugOut "will call IShellFolder::CreateViewObject" 1250 | invoke vf(pShellFolder, IShellFolder, CreateViewObject), 1251 | m_hWnd, addr IID_IShellView, addr pShellView 1252 | invoke vf(pShellFolder, IShellFolder, Release) 1253 | .endif 1254 | .if (pShellView) 1255 | 1256 | invoke GetTrueClientRect, addr rect 1257 | invoke GetLeftPanelWidth, addr rect 1258 | mov dwWidth, eax 1259 | .if (!m_pShellView) 1260 | invoke SetWindowPos, m_hWndTV, 0, 0, 0, dwWidth, rect.bottom, SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE 1261 | .endif 1262 | 1263 | mov folderset.ViewMode, FVM_DETAILS 1264 | mov folderset.fFlags, 0 1265 | .if (m_pShellView) 1266 | invoke vf(m_pShellView, IShellView, GetCurrentInfo), addr folderset 1267 | .endif 1268 | 1269 | mov eax, dwWidth 1270 | add eax, GRIPSIZE 1271 | mov rect.left, eax 1272 | DebugOut "will call IShellView::CreateViewWindow" 1273 | mov hWndView, NULL 1274 | invoke vf(pShellView, IShellView, CreateViewWindow), 1275 | m_pShellView, addr folderset, __this, addr rect, addr hWndView 1276 | .if (eax == S_OK) 1277 | mov dwUIActivateFlags, SVUIA_ACTIVATE_NOFOCUS 1278 | mov eax, m_hWndView 1279 | .if (eax && (eax == m_hWndFocus)) 1280 | mov dwUIActivateFlags, SVUIA_ACTIVATE_FOCUS 1281 | .endif 1282 | invoke ReleaseShellView 1283 | mov eax, hWndView 1284 | mov m_hWndView, eax 1285 | mov eax, pShellView 1286 | mov m_pShellView, eax 1287 | invoke vf(m_pShellView, IShellView, UIActivate), dwUIActivateFlags 1288 | .if (dwUIActivateFlags == SVUIA_ACTIVATE_FOCUS) 1289 | invoke SetFocus, m_hWndView 1290 | .endif 1291 | ;--------------------- some extensions dont create window with WS_TABSTOP 1292 | ;--------------------- so add it now 1293 | invoke GetWindowLong, m_hWndView, GWL_STYLE 1294 | or eax, WS_TABSTOP 1295 | invoke SetWindowLong, m_hWndView, GWL_STYLE, eax 1296 | 1297 | mov eax, TRUE 1298 | .else 1299 | invoke vf(pShellView, IShellView, Release) 1300 | mov eax, FALSE 1301 | .endif 1302 | .else 1303 | mov eax, FALSE 1304 | .endif 1305 | ret 1306 | align 4 1307 | 1308 | CreateViewObject endp 1309 | 1310 | InsertNewChild proc pidlNew:LPITEMIDLIST 1311 | 1312 | local hItem:HANDLE 1313 | local pidl:LPITEMIDLIST 1314 | local pidl2:LPITEMIDLIST 1315 | local pidl3:LPITEMIDLIST 1316 | local pShellFolder:LPSHELLFOLDER 1317 | local strret:STRRET 1318 | local sfgaof:SFGAOF 1319 | local tvi:TV_ITEM 1320 | 1321 | invoke Pidl_SkipLastItem, pidlNew, addr pidl 1322 | mov pidl2, eax 1323 | invoke FindPidl, eax, FALSE 1324 | .if (eax) 1325 | mov hItem, eax 1326 | mov tvi.hItem, eax 1327 | mov tvi.mask_, TVIF_STATE 1328 | mov tvi.stateMask, TVIS_EXPANDEDONCE 1329 | invoke TreeView_GetItem( m_hWndTV, addr tvi) 1330 | ;------------------------------------- if this item wasnt expanded yet, do nothing 1331 | .if (!(tvi.state & TVIS_EXPANDEDONCE)) 1332 | jmp done 1333 | .endif 1334 | invoke GetFolder, hItem 1335 | .if (eax) 1336 | mov pShellFolder, eax 1337 | 1338 | ;--------------------------- this is very odd, but seems unavoidable: 1339 | ;--------------------------- the new name has to parsed again to get the 1340 | ;--------------------------- proper pidl 1341 | 1342 | mov strret.uType, STRRET_WSTR 1343 | invoke vf(pShellFolder, IShellFolder, GetDisplayNameOf), pidl, 1344 | SHGDN_INFOLDER, addr strret 1345 | .if (eax == S_OK && (strret.uType == STRRET_WSTR)) 1346 | invoke vf(pShellFolder, IShellFolder, ParseDisplayName), m_hWnd, 1347 | NULL, strret.pOleStr, NULL, addr pidl3, NULL 1348 | invoke vf(m_pMalloc, IMalloc, Free), strret.pOleStr 1349 | invoke vf(m_pMalloc, IMalloc, Free), pidl 1350 | mov eax, pidl3 1351 | mov pidl, eax 1352 | .endif 1353 | 1354 | invoke InsertItem, hItem, pShellFolder, pidl, TRUE 1355 | .if (eax) 1356 | mov pidl, NULL 1357 | .endif 1358 | invoke vf(pShellFolder, IShellFolder, Release) 1359 | .endif 1360 | .endif 1361 | done: 1362 | invoke vf(m_pMalloc, IMalloc, Free), pidl2 1363 | .if (pidl) 1364 | invoke vf(m_pMalloc, IMalloc, Free), pidl 1365 | .endif 1366 | ret 1367 | 1368 | InsertNewChild endp 1369 | 1370 | ;--- WM_SHNOTIFY 1371 | 1372 | OnSHNotify proc uses esi wParam:WPARAM, lParam:LPARAM 1373 | 1374 | local hItem:HANDLE 1375 | local pidl:LPITEMIDLIST 1376 | local pidl2:LPITEMIDLIST 1377 | local pShellFolder:LPSHELLFOLDER 1378 | local tvi:TV_ITEM 1379 | local szText[MAX_PATH]:byte 1380 | 1381 | mov esi,wParam 1382 | ifdef _DEBUG 1383 | mov ecx, lParam 1384 | .if (ecx & SHCNE_RENAMEITEM) 1385 | mov ecx, CStr("SHCNE_RENAMEITEM") 1386 | .elseif (ecx & SHCNE_CREATE) 1387 | mov ecx, CStr("SHCNE_CREATE") 1388 | .elseif (ecx & SHCNE_DELETE) 1389 | mov ecx, CStr("SHCNE_DELETE") 1390 | .elseif (ecx & SHCNE_MKDIR) 1391 | mov ecx, CStr("SHCNE_MKDIR") 1392 | .elseif (ecx & SHCNE_RMDIR) 1393 | mov ecx, CStr("SHCNE_RMDIR") 1394 | .elseif (ecx & SHCNE_RENAMEFOLDER) 1395 | mov ecx, CStr("SHCNE_RENAMEFOLDER") 1396 | .elseif (ecx & SHCNE_EXTENDED_EVENT) 1397 | mov ecx, CStr("SHCNE_EXTENDED_EVENT") 1398 | .elseif (ecx & SHCNE_UPDATEITEM) 1399 | mov ecx, CStr("SHCNE_UPDATEITEM") 1400 | .else 1401 | invoke wsprintf, addr szText, CStr("%X"), ecx 1402 | lea ecx, szText 1403 | .endif 1404 | DebugOut "WM_SHNOTIFY(%s,[%X,%X],%X)", ecx, [esi].SHNOTIFYSTRUCT.dwItem1,\ 1405 | [esi].SHNOTIFYSTRUCT.dwItem2, lParam 1406 | endif 1407 | .if (lParam & SHCNE_RMDIR) 1408 | ifdef _DEBUG 1409 | invoke SHGetPathFromIDList, [esi].SHNOTIFYSTRUCT.dwItem1, addr szText 1410 | .if (eax) 1411 | DebugOut "%s", addr szText 1412 | .endif 1413 | endif 1414 | invoke FindPidl, [esi].SHNOTIFYSTRUCT.dwItem1, FALSE 1415 | .if (eax) 1416 | invoke TreeView_DeleteItem( m_hWndTV, eax) 1417 | .endif 1418 | .endif 1419 | 1420 | .if (lParam & SHCNE_MKDIR) 1421 | ifdef _DEBUG 1422 | invoke SHGetPathFromIDList, [esi].SHNOTIFYSTRUCT.dwItem1, addr szText 1423 | .if (eax) 1424 | DebugOut "%s", addr szText 1425 | .endif 1426 | endif 1427 | invoke InsertNewChild, [esi].SHNOTIFYSTRUCT.dwItem1 1428 | .endif 1429 | 1430 | .if (lParam & SHCNE_RENAMEFOLDER) 1431 | ifdef _DEBUG 1432 | invoke SHGetPathFromIDList, [esi].SHNOTIFYSTRUCT.dwItem1, addr szText 1433 | .if (eax) 1434 | DebugOut "%s", addr szText 1435 | .endif 1436 | invoke SHGetPathFromIDList, [esi].SHNOTIFYSTRUCT.dwItem2, addr szText 1437 | .if (eax) 1438 | DebugOut "%s", addr szText 1439 | .endif 1440 | endif 1441 | mov hItem, NULL 1442 | .if ([esi].SHNOTIFYSTRUCT.dwItem1) 1443 | invoke FindPidl, [esi].SHNOTIFYSTRUCT.dwItem1, FALSE 1444 | .if (eax) 1445 | mov hItem, eax 1446 | invoke TreeView_DeleteItem( m_hWndTV, eax) 1447 | .endif 1448 | .endif 1449 | .if (hItem && [esi].SHNOTIFYSTRUCT.dwItem2) 1450 | invoke InsertNewChild, [esi].SHNOTIFYSTRUCT.dwItem2 1451 | .endif 1452 | .endif 1453 | ;------------------------------------ local folder now shared, refresh icon 1454 | .if (lParam & SHCNE_NETSHARE) 1455 | if ?IMAGELIST 1456 | invoke FindPidl, [esi].SHNOTIFYSTRUCT.dwItem1, FALSE 1457 | .if (eax) 1458 | mov tvi.hItem, eax 1459 | mov tvi.mask_, TVIF_IMAGE or TVIF_SELECTEDIMAGE 1460 | mov tvi.iImage, I_IMAGECALLBACK 1461 | mov tvi.iSelectedImage, I_IMAGECALLBACK 1462 | invoke TreeView_SetItem( m_hWndTV, addr tvi) 1463 | .endif 1464 | endif 1465 | .endif 1466 | ifdef _DEBUG 1467 | .if (lParam & SHCNE_UPDATEITEM) 1468 | invoke SHGetPathFromIDList, [esi].SHNOTIFYSTRUCT.dwItem1, addr szText 1469 | .if (eax) 1470 | DebugOut "%s", addr szText 1471 | .endif 1472 | .endif 1473 | endif 1474 | ret 1475 | OnSHNotify endp 1476 | 1477 | 1478 | ;--- WM_NOTIFY, TVN_GETDISPINFO 1479 | 1480 | 1481 | OnGetDispInfo proc uses esi ptvdi:ptr TV_DISPINFO 1482 | 1483 | local pShellFolder:LPSHELLFOLDER 1484 | local tvi:TV_ITEM 1485 | if ?IMAGELIST 1486 | local pExtractIcon:LPEXTRACTICON 1487 | local dwFlags:DWORD 1488 | local iIndex:DWORD 1489 | local szIconFile[MAX_PATH]:BYTE 1490 | local hIconSmall:HICON 1491 | local hIconLarge:HICON 1492 | endif 1493 | 1494 | mov esi, ptvdi 1495 | assume esi:ptr TV_DISPINFO 1496 | 1497 | if 1 1498 | .if ([esi].item.mask_ & TVIF_CHILDREN) 1499 | invoke InsertChildItems, [esi].item.hItem 1500 | .if (eax == -1) 1501 | mov eax, 0 1502 | .elseif (eax) 1503 | mov eax, 1 1504 | .endif 1505 | mov [esi].item.cChildren, eax 1506 | mov tvi.cChildren, eax 1507 | mov eax, [esi].item.hItem 1508 | mov tvi.hItem, eax 1509 | mov tvi.mask_, TVIF_CHILDREN 1510 | invoke TreeView_SetItem( m_hWndTV, addr tvi) 1511 | .endif 1512 | endif 1513 | 1514 | if ?IMAGELIST 1515 | .if ([esi].item.mask_ & (TVIF_IMAGE or TVIF_SELECTEDIMAGE)) 1516 | mov [esi].item.iImage, 0 1517 | mov [esi].item.iSelectedImage, 1 1518 | invoke TreeView_GetParent( m_hWndTV, [esi].item.hItem) 1519 | .if (eax) 1520 | invoke GetFolder, eax 1521 | .if (eax) 1522 | mov pShellFolder, eax 1523 | invoke vf(pShellFolder, IShellFolder, GetUIObjectOf), m_hWnd, 1524 | 1, addr [esi].item.lParam, 1525 | addr IID_IExtractIcon, NULL, addr pExtractIcon 1526 | .if (eax == S_OK) 1527 | .if ([esi].item.mask_ & TVIF_IMAGE) 1528 | invoke vf(pExtractIcon, IExtractIcon, GetIconLocation), GIL_FORSHELL, 1529 | addr szIconFile, sizeof szIconFile, addr iIndex, addr dwFlags 1530 | .if (eax == S_OK) 1531 | invoke vf(pExtractIcon, IExtractIcon, Extract), addr szIconFile, 1532 | iIndex, addr hIconLarge, addr hIconSmall, 00100020h 1533 | .if (eax == S_OK) 1534 | invoke ImageList_AddIcon( g_himl, hIconSmall) 1535 | mov [esi].item.iImage, eax 1536 | invoke DestroyIcon, hIconLarge 1537 | invoke DestroyIcon, hIconSmall 1538 | .endif 1539 | .endif 1540 | .endif 1541 | .if ([esi].item.mask_ & TVIF_SELECTEDIMAGE) 1542 | invoke vf(pExtractIcon, IExtractIcon, GetIconLocation), 1543 | GIL_FORSHELL or GIL_OPENICON, 1544 | addr szIconFile, sizeof szIconFile, addr iIndex, addr dwFlags 1545 | .if (eax == S_OK) 1546 | invoke vf(pExtractIcon, IExtractIcon, Extract), addr szIconFile,\ 1547 | iIndex, addr hIconLarge, addr hIconSmall, 00100020h 1548 | .if (eax == S_OK) 1549 | invoke ImageList_AddIcon( g_himl, hIconSmall) 1550 | mov [esi].item.iSelectedImage, eax 1551 | invoke DestroyIcon, hIconLarge 1552 | invoke DestroyIcon, hIconSmall 1553 | .endif 1554 | .endif 1555 | .endif 1556 | invoke vf(pExtractIcon, IExtractIcon, Release) 1557 | .endif 1558 | invoke vf(pShellFolder, IShellFolder, Release) 1559 | .endif 1560 | .else 1561 | mov [esi].item.iImage, 2 1562 | mov [esi].item.iSelectedImage, 2 1563 | .endif 1564 | 1565 | mov eax, [esi].item.hItem 1566 | mov tvi.hItem, eax 1567 | mov ecx, [esi].item.mask_ 1568 | and ecx, TVIF_IMAGE or TVIF_SELECTEDIMAGE 1569 | mov tvi.mask_, ecx 1570 | mov eax,[esi].item.iImage 1571 | mov tvi.iImage, eax 1572 | mov eax,[esi].item.iSelectedImage 1573 | mov tvi.iSelectedImage, eax 1574 | invoke TreeView_SetItem( m_hWndTV, addr tvi) 1575 | .endif 1576 | 1577 | endif 1578 | ret 1579 | assume esi:nothing 1580 | 1581 | OnGetDispInfo endp 1582 | 1583 | 1584 | editwndproc proc hWnd:HWND, message:DWORD, wParam:WPARAM, lParam:LPARAM 1585 | 1586 | .if (message == WM_GETDLGCODE) 1587 | mov eax,DLGC_WANTALLKEYS 1588 | .else 1589 | invoke CallWindowProc, g_EditWndProc, hWnd, message, wParam, lParam 1590 | .endif 1591 | ret 1592 | 1593 | editwndproc endp 1594 | 1595 | 1596 | ;--- WM_NOTIFY, TVN_ENDLABELEDIT: rename a folder 1597 | 1598 | 1599 | OnEndLabelEdit proc uses esi pnmtvdi:ptr NMTVDISPINFO 1600 | 1601 | local pShellFolder:LPSHELLFOLDER 1602 | local pidl:LPITEMIDLIST 1603 | local dwSize:DWORD 1604 | local bRC:BOOL 1605 | local tvi:TV_ITEM 1606 | 1607 | mov bRC, FALSE 1608 | 1609 | mov esi, pnmtvdi 1610 | 1611 | ;--- the parent folder is needed for SetNameOf function 1612 | 1613 | invoke TreeView_GetParent( m_hWndTV, [esi].NMTVDISPINFO.item.hItem) 1614 | .if (eax) 1615 | invoke GetFolder, eax 1616 | .if (eax) 1617 | mov pShellFolder, eax 1618 | invoke lstrlen, [esi].NMTVDISPINFO.item.pszText 1619 | add eax, 4 1620 | and al,0FCh 1621 | shl eax, 1 1622 | mov dwSize, eax 1623 | sub esp, eax 1624 | shr eax, 1 1625 | mov ecx, esp 1626 | invoke MultiByteToWideChar,CP_ACP,MB_PRECOMPOSED, 1627 | [esi].NMTVDISPINFO.item.pszText, -1, ecx, eax 1628 | mov ecx, esp 1629 | invoke vf(pShellFolder, IShellFolder, SetNameOf), m_hWnd, 1630 | [esi].NMTVDISPINFO.item.lParam, ecx, SHGDN_INFOLDER, addr pidl 1631 | .if (eax == S_OK) 1632 | invoke vf(m_pMalloc, IMalloc, Free), [esi].NMTVDISPINFO.item.lParam 1633 | mov eax, pidl 1634 | mov tvi.lParam, eax 1635 | mov tvi.mask_, TVIF_PARAM 1636 | mov eax, [esi].NMTVDISPINFO.item.hItem 1637 | mov tvi.hItem, eax 1638 | invoke TreeView_SetItem( m_hWndTV, addr tvi) 1639 | mov bRC, TRUE 1640 | .endif 1641 | add esp, dwSize 1642 | invoke vf(pShellFolder, IShellFolder, Release) 1643 | .endif 1644 | .endif 1645 | return bRC 1646 | 1647 | OnEndLabelEdit endp 1648 | 1649 | 1650 | 1651 | ExecuteVerb proc hItem:HANDLE, lpVerb:LPSTR 1652 | 1653 | local pShellFolder:LPSHELLFOLDER 1654 | local pContextMenu:LPCONTEXTMENU 1655 | local tvht:TV_HITTESTINFO 1656 | local hPopupMenu:HMENU 1657 | local sfgaof:SFGAOF 1658 | local tvi:TV_ITEM 1659 | local pt:POINT 1660 | local cmic:CMINVOKECOMMANDINFO 1661 | local szText[64]:byte 1662 | 1663 | DebugOut "EvecuteVerb enter" 1664 | invoke TreeView_GetParent( m_hWndTV, hItem) 1665 | .if (!eax) 1666 | jmp exit 1667 | .endif 1668 | invoke GetFolder, eax 1669 | .if (eax) 1670 | DebugOut "EvecuteVerb: pShellFolder=%X", eax 1671 | mov pShellFolder, eax 1672 | mov tvi.mask_, TVIF_PARAM or TVIF_STATE or TVIF_CHILDREN 1673 | mov tvi.stateMask, TVIS_EXPANDED 1674 | mov eax, hItem 1675 | mov tvi.hItem, eax 1676 | invoke TreeView_GetItem( m_hWndTV, addr tvi) 1677 | DebugOut "EvecuteVerb: TreeView_GetItem=%X", eax 1678 | .if (eax) 1679 | mov eax, lpVerb 1680 | mov cmic.lpVerb, eax 1681 | invoke vf(pShellFolder, IShellFolder, GetUIObjectOf), 1682 | m_hWnd, 1, addr tvi.lParam, addr IID_IContextMenu, 1683 | NULL, addr pContextMenu 1684 | DebugOut "EvecuteVerb: IShellFolder.GetUIObjectOf=%X, lpVerb=%X", eax, lpVerb 1685 | .if (eax == S_OK) 1686 | .if (lpVerb == NULL) 1687 | invoke vf(pContextMenu, IContextMenu, QueryInterface), 1688 | addr IID_IContextMenu2, addr m_pContextMenu2 1689 | DebugOut "EvecuteVerb: IContextMeny.QueryInterface=%X", eax 1690 | invoke CreatePopupMenu 1691 | mov hPopupMenu, eax 1692 | .if (tvi.state & TVIS_EXPANDED) 1693 | mov ecx, CStr("Collapse") 1694 | .else 1695 | mov ecx, CStr("Expand") 1696 | .endif 1697 | .if (tvi.cChildren) 1698 | mov edx, MF_ENABLED or MF_BYPOSITION or MF_STRING 1699 | .else 1700 | mov edx, MF_GRAYED or MF_BYPOSITION or MF_STRING 1701 | .endif 1702 | invoke InsertMenu, hPopupMenu, 0, edx, IDM_EXPAND, ecx 1703 | invoke InsertMenu, hPopupMenu, 1, MF_BYPOSITION or MF_SEPARATOR, -1, NULL 1704 | mov sfgaof, SFGAO_CANRENAME 1705 | invoke vf(pShellFolder, IShellFolder, GetAttributesOf), 1, 1706 | addr tvi.lParam, addr sfgaof 1707 | mov ecx, CMF_NORMAL or CMF_EXPLORE 1708 | .if ((eax == S_OK) && (sfgaof & SFGAO_CANRENAME)) 1709 | or ecx, CMF_CANRENAME 1710 | .endif 1711 | invoke vf(pContextMenu, IContextMenu, QueryContextMenu), 1712 | hPopupMenu, 2, IDM_FIRST, IDM_LAST, ecx 1713 | DebugOut "EvecuteVerb: IContextMeny.QueryContextMenu=%X", eax 1714 | .if (SUCCEEDED(eax)) 1715 | invoke SetMenuDefaultItem, hPopupMenu, 0, TRUE 1716 | invoke GetMenuItemCount, hPopupMenu 1717 | .if (eax == 2) 1718 | invoke DeleteMenu, hPopupMenu, 1, MF_BYPOSITION 1719 | .endif 1720 | DebugOut "EvecuteVerb: calling TrackPopupMenu" 1721 | invoke GetCursorPos, addr pt 1722 | invoke TrackPopupMenu, hPopupMenu, TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_RETURNCMD,\ 1723 | pt.x, pt.y, 0, m_hWnd, NULL 1724 | .if ((eax >= IDM_FIRST) && (eax <= IDM_LAST)) 1725 | sub eax, IDM_FIRST 1726 | mov cmic.lpVerb, eax 1727 | mov ecx, eax 1728 | invoke vf(pContextMenu, IContextMenu, GetCommandString), ecx, 1729 | GCS_VERBA, NULL, addr szText, sizeof szText 1730 | .if (eax == S_OK) 1731 | lea eax, szText 1732 | mov lpVerb, eax 1733 | .endif 1734 | .elseif (eax == IDM_EXPAND) 1735 | invoke TreeView_Expand( m_hWndTV, hItem, TVE_TOGGLE ) 1736 | mov lpVerb, NULL 1737 | mov cmic.lpVerb, NULL 1738 | .endif 1739 | .endif 1740 | invoke DestroyMenu, hPopupMenu 1741 | .endif 1742 | .if (cmic.lpVerb || lpVerb) 1743 | mov cmic.cbSize, sizeof CMINVOKECOMMANDINFO 1744 | mov cmic.fMask, 0 1745 | mov eax, m_hWnd 1746 | mov cmic.hwnd, eax 1747 | mov cmic.lpParameters, NULL 1748 | mov cmic.lpDirectory, NULL 1749 | mov cmic.nShow, SW_SHOWNORMAL 1750 | .if (lpVerb) 1751 | invoke lstrcmpi, lpVerb, CStr("RENAME") 1752 | .if (!eax) 1753 | invoke TreeView_EditLabel( m_hWndTV, tvi.hItem) 1754 | jmp done 1755 | .endif 1756 | .endif 1757 | invoke vf(pContextMenu, IContextMenu, InvokeCommand), addr cmic 1758 | done: 1759 | .endif 1760 | invoke vf(pContextMenu, IUnknown, Release) 1761 | .if (m_pContextMenu2) 1762 | invoke vf(m_pContextMenu2, IUnknown, Release) 1763 | mov m_pContextMenu2, NULL 1764 | .endif 1765 | .endif 1766 | .endif 1767 | invoke vf(pShellFolder, IUnknown, Release) 1768 | .endif 1769 | exit: 1770 | ret 1771 | ExecuteVerb endp 1772 | 1773 | 1774 | ;--- WM_NOTIFY, NM_RCLICK: show context menu 1775 | 1776 | 1777 | OnRightClick proc pnmhdr:ptr NMHDR 1778 | 1779 | local tvht:TV_HITTESTINFO 1780 | 1781 | DebugOut "OnRightClick enter" 1782 | invoke GetCursorPos,addr tvht.pt 1783 | ; get the item below hit point 1784 | invoke ScreenToClient, m_hWndTV, addr tvht.pt 1785 | invoke TreeView_HitTest( m_hWndTV, addr tvht ) 1786 | .if (tvht.hItem) 1787 | invoke ExecuteVerb, tvht.hItem, NULL 1788 | .endif 1789 | ret 1790 | align 4 1791 | 1792 | OnRightClick endp 1793 | 1794 | ;--- WM_NOTIFY, TVN_KEYDOWN 1795 | 1796 | OnKeyDown proc vk:DWORD, flags:DWORD 1797 | 1798 | local tvi:TV_ITEM 1799 | 1800 | invoke TreeView_GetSelection( m_hWndTV) 1801 | mov tvi.hItem, eax 1802 | mov tvi.mask_, TVIF_PARAM 1803 | 1804 | .if (vk == VK_DELETE) 1805 | .if (tvi.hItem) 1806 | invoke ExecuteVerb, tvi.hItem, CStr("delete") 1807 | .else 1808 | invoke MessageBeep, MB_OK 1809 | .endif 1810 | .endif 1811 | exit: 1812 | ret 1813 | 1814 | OnKeyDown endp 1815 | 1816 | ;--- WM_NOTIFY 1817 | 1818 | 1819 | OnNotify proc uses esi pNMHDR:ptr NMHDR 1820 | 1821 | local pShellFolder:LPSHELLFOLDER 1822 | local pExtractIcon:LPEXTRACTICON 1823 | local sfgaof:SFGAOF 1824 | ;local pt:POINT 1825 | local tvi:TV_ITEM 1826 | 1827 | xor eax, eax 1828 | mov esi, pNMHDR 1829 | .if ([esi].NMHDR.code == NM_SETFOCUS) 1830 | 1831 | mov eax, [esi].NMHDR.hwndFrom 1832 | mov m_hWndFocus, eax 1833 | .if (m_pShellView) 1834 | invoke vf(m_pShellView, IShellView, UIActivate), SVUIA_ACTIVATE_NOFOCUS 1835 | .endif 1836 | 1837 | .elseif (([esi].NMHDR.code == NM_RCLICK) && (m_bGetUIObjectOf)) 1838 | 1839 | invoke OnRightClick, esi 1840 | 1841 | .elseif ([esi].NMHDR.code == TVN_KEYDOWN) 1842 | 1843 | movzx ecx, [esi].TV_KEYDOWN.wVKey 1844 | invoke OnKeyDown, ecx, [esi].TV_KEYDOWN.flags 1845 | 1846 | .elseif ([esi].NMHDR.code == TVN_ITEMEXPANDING) 1847 | 1848 | xor eax, eax 1849 | mov ecx, [esi].NM_TREEVIEW.itemNew.lParam 1850 | .if (ecx && (!([esi].NM_TREEVIEW.itemNew.state & TVIS_EXPANDEDONCE))) 1851 | invoke InsertChildItems, [esi].NM_TREEVIEW.itemNew.hItem 1852 | .if (eax == -1) 1853 | mov eax, 1 1854 | .else 1855 | xor eax, eax 1856 | .endif 1857 | .endif 1858 | 1859 | .elseif ([esi].NMHDR.code == TVN_DELETEITEM) 1860 | 1861 | mov ecx, [esi].NM_TREEVIEW.itemOld.lParam 1862 | invoke vf(m_pMalloc, IMalloc, Free), ecx 1863 | 1864 | .elseif ([esi].NMHDR.code == TVN_GETDISPINFO) 1865 | 1866 | .if ([esi].TV_DISPINFO.item.mask_ & (TVIF_CHILDREN or TVIF_IMAGE or TVIF_SELECTEDIMAGE)) 1867 | invoke OnGetDispInfo, esi 1868 | .endif 1869 | 1870 | .elseif ([esi].NMHDR.code == TVN_BEGINLABELEDIT) 1871 | 1872 | mov m_bLabelEdit, TRUE 1873 | mov sfgaof, SFGAO_CANRENAME 1874 | invoke GetAttributes, [esi].NMTVDISPINFO.item.hItem, addr sfgaof 1875 | .if (sfgaof) 1876 | ;------------------------------ set edit controls window proc 1877 | invoke TreeView_GetEditControl( m_hWndTV) 1878 | invoke SetWindowLong, eax, GWL_WNDPROC, editwndproc 1879 | mov g_EditWndProc, eax 1880 | xor eax, eax 1881 | .else 1882 | mov eax, TRUE 1883 | .endif 1884 | 1885 | .elseif ([esi].NMHDR.code == TVN_ENDLABELEDIT) 1886 | 1887 | mov m_bLabelEdit, FALSE 1888 | .if ([esi].NMTVDISPINFO.item.pszText) 1889 | invoke OnEndLabelEdit, esi 1890 | .if (!eax) 1891 | invoke TreeView_EditLabel( m_hWndTV, [esi].NMTVDISPINFO.item.hItem) 1892 | invoke TreeView_GetEditControl( m_hWndTV) 1893 | mov ecx, eax 1894 | invoke SetWindowText, ecx, [esi].NMTVDISPINFO.item.pszText 1895 | xor eax, eax 1896 | .endif 1897 | .endif 1898 | 1899 | .elseif ([esi].NMHDR.code == TVN_SELCHANGING) 1900 | 1901 | if 0 1902 | ;----------------------------------- if removeable, refresh folder content 1903 | 1904 | invoke IsRemoveable, [esi].NM_TREEVIEW.itemNew.hItem 1905 | .if (eax) 1906 | .while (1) 1907 | invoke TreeView_GetChild( m_hWndTV, [esi].NM_TREEVIEW.itemNew.hItem) 1908 | .break .if (!eax) 1909 | invoke TreeView_DeleteItem( m_hWndTV, eax) 1910 | .endw 1911 | 1912 | invoke InsertChildItems, [esi].NM_TREEVIEW.itemNew.hItem 1913 | .if (eax == -1) 1914 | mov eax, 1 1915 | ret 1916 | .elseif (eax) 1917 | mov eax, 1 1918 | .endif 1919 | mov tvi.cChildren, eax 1920 | mov tvi.imask, TVIF_CHILDREN 1921 | mov eax, [esi].NM_TREEVIEW.itemNew.hItem 1922 | mov tvi.hItem, eax 1923 | invoke TreeView_SetItem( m_hWndTV, addr tvi) 1924 | .endif 1925 | endif 1926 | 1927 | .if ([esi].NM_TREEVIEW.itemNew.hItem == NULL) 1928 | xor eax, eax 1929 | jmp exit 1930 | .endif 1931 | invoke CreateViewObject, [esi].NM_TREEVIEW.itemNew.hItem 1932 | ;------------------------------ if successful, set main window title 1933 | .if (eax) 1934 | mov eax, [esi].NM_TREEVIEW.itemNew.hItem 1935 | mov tvi.hItem, eax 1936 | mov tvi.mask_, TVIF_TEXT 1937 | sub esp, 128 1938 | mov tvi.pszText, esp 1939 | mov tvi.cchTextMax, 128 1940 | invoke TreeView_GetItem( m_hWndTV, addr tvi) 1941 | mov ecx, esp 1942 | invoke lstrcat, ecx, addr szAppNameEx 1943 | invoke SetWindowText, m_hWnd, esp 1944 | add esp, 128 1945 | xor eax, eax 1946 | .else 1947 | mov eax, 1 1948 | .endif 1949 | 1950 | .endif 1951 | exit: 1952 | ret 1953 | align 4 1954 | 1955 | OnNotify endp 1956 | 1957 | 1958 | aboutdlgproc proc hWnd:HWND, message:DWORD, wParam:WPARAM, lParam:LPARAM 1959 | 1960 | .if (message == WM_INITDIALOG) 1961 | invoke GetDlgItem, hWnd, IDC_EDIT1 1962 | mov ecx, eax 1963 | invoke SetWindowText, ecx, 1964 | CStr(<13,10,"ExplorerASM Version 1.2.0",13,10,"Public Domain (Japheth 2003-2007)",13,10,"http://github.com/Baron-von-Riedesel/ExplASM",13,10>) 1965 | mov eax, 1 1966 | .elseif (message == WM_CLOSE) 1967 | invoke EndDialog, hWnd, 0 1968 | .elseif (message == WM_COMMAND) 1969 | movzx eax, word ptr wParam 1970 | .if (eax == IDCANCEL) 1971 | invoke PostMessage, hWnd, WM_CLOSE, 0, 0 1972 | .endif 1973 | .else 1974 | xor eax, eax 1975 | .endif 1976 | ret 1977 | align 4 1978 | 1979 | aboutdlgproc endp 1980 | 1981 | ;--- WM_COMMAND 1982 | 1983 | 1984 | OnCommand proc wParam:WPARAM, lParam:LPARAM 1985 | 1986 | local hMenu:HMENU 1987 | local pidl:LPITEMIDLIST 1988 | local pOleCommandTarget:LPOLECOMMANDTARGET 1989 | local rect:RECT 1990 | 1991 | invoke GetMenu, m_hWnd 1992 | mov hMenu, eax 1993 | 1994 | xor eax, eax 1995 | movzx ecx, word ptr wParam+0 1996 | .if (ecx == IDM_EXIT) 1997 | 1998 | invoke PostMessage, m_hWnd, WM_CLOSE, 0, 0 1999 | 2000 | .elseif (ecx == IDOK) ;comes from labeledit 2001 | 2002 | DebugOut "IDOK, wParam=%X, lParam=%X", wParam, lParam 2003 | 2004 | .elseif (ecx == IDM_REFRESH) 2005 | 2006 | invoke RefreshView 2007 | if 0 2008 | .if (m_pShellView) 2009 | invoke vf(m_pShellView, IShellView, Refresh) 2010 | .endif 2011 | endif 2012 | .elseif (ecx == IDM_ABOUT) 2013 | 2014 | invoke DialogBoxParam, g_hInstance, IDD_DIALOG2, m_hWnd, aboutdlgproc, 0 2015 | 2016 | .elseif (ecx == IDM_STATUSLINE) 2017 | 2018 | xor m_bStatusBar, 1 2019 | mov al, m_bStatusBar 2020 | mov g_bStatusBar, al 2021 | .if (m_bStatusBar) 2022 | mov ecx, SW_SHOWNORMAL 2023 | .else 2024 | mov ecx, SW_HIDE 2025 | .endif 2026 | invoke ShowWindow, m_hWndSB, ecx 2027 | invoke UpdateMenu 2028 | invoke OnSize 2029 | 2030 | .elseif (ecx == IDM_CREATEVIEWOBJECT) 2031 | 2032 | xor m_bCreateView, 1 2033 | mov al, m_bCreateView 2034 | mov g_bCreateView, al 2035 | invoke UpdateMenu 2036 | invoke TreeView_GetSelection( m_hWndTV) 2037 | .if (eax) 2038 | invoke CreateViewObject, eax 2039 | .endif 2040 | 2041 | .elseif (ecx == IDM_GETUIOBJECTOF) 2042 | 2043 | xor m_bGetUIObjectOf, 1 2044 | mov al, m_bGetUIObjectOf 2045 | mov g_bGetUIObjectOf, al 2046 | invoke UpdateMenu 2047 | 2048 | .elseif (ecx == IDM_COMPMENUS) 2049 | 2050 | xor m_bCompMenus, 1 2051 | mov al, m_bCompMenus 2052 | mov g_bCompMenus, al 2053 | .if (!m_bCompMenus) 2054 | invoke LoadMenu, g_hInstance, IDR_MENU1 2055 | invoke SetMenu, m_hWnd, eax 2056 | .endif 2057 | invoke UpdateMenu 2058 | 2059 | .elseif (ecx == IDM_DROPTARGET) 2060 | 2061 | xor m_bDropTarget, 1 2062 | mov al, m_bDropTarget 2063 | mov g_bDropTarget, al 2064 | .if (al) 2065 | lea ecx, m__IDropTarget 2066 | invoke RegisterDragDrop, m_hWndTV, ecx 2067 | .else 2068 | invoke RevokeDragDrop, m_hWndTV 2069 | .endif 2070 | invoke UpdateMenu 2071 | 2072 | .elseif (ecx == IDM_TRACKSELECT) 2073 | 2074 | xor g_bTrackSelect, 1 2075 | invoke GetWindowLong, m_hWndTV, GWL_STYLE 2076 | .if (g_bTrackSelect) 2077 | or eax, TVS_TRACKSELECT 2078 | .else 2079 | and eax, NOT (TVS_TRACKSELECT) 2080 | .endif 2081 | invoke SetWindowLong, m_hWndTV, GWL_STYLE, eax 2082 | invoke UpdateMenu 2083 | 2084 | .elseif (ecx == IDM_DDERESPOND) 2085 | 2086 | xor m_bDontRespond, 1 2087 | invoke UpdateMenu 2088 | 2089 | .elseif (ecx == IDM_BROWSEFILES) 2090 | 2091 | xor g_bBrowseFiles, 1 2092 | invoke UpdateMenu 2093 | invoke RefreshView 2094 | 2095 | .elseif (ecx == IDM_DELETE) 2096 | 2097 | invoke OnKeyDown, VK_DELETE, 0 2098 | 2099 | .else 2100 | .if (m_pShellView) 2101 | .if ((eax >= FCIDM_SHVIEWFIRST) && (eax <= FCIDM_SHVIEWLAST)) 2102 | invoke SendMessage, m_hWndView, WM_COMMAND, wParam, lParam 2103 | .endif 2104 | .endif 2105 | .endif 2106 | 2107 | ret 2108 | align 4 2109 | 2110 | OnCommand endp 2111 | 2112 | GRIPSIZE equ 4 2113 | 2114 | ;--- user resizes TreeView 2115 | 2116 | DrawResizeLine proc uses esi hWnd:HWND , xPos:DWORD 2117 | 2118 | local hBrushOld:HBRUSH 2119 | local hdc:HDC 2120 | local rect:RECT 2121 | local hBitmap:HBITMAP 2122 | local pattern[8]:WORD 2123 | local iToolbarHeight:DWORD 2124 | 2125 | .data 2126 | g_iOldResizeLine DWORD 0 2127 | .code 2128 | 2129 | mov iToolbarHeight,0 2130 | .if (!g_hHalftoneBrush) 2131 | lea ecx, pattern 2132 | xor esi, esi 2133 | mov eax, 5555h 2134 | .while (esi < 8) 2135 | mov [ecx+esi*2], eax 2136 | xor eax, 0FFFFh 2137 | inc esi 2138 | .endw 2139 | invoke CreateBitmap, 8,8,1,1,addr pattern 2140 | mov hBitmap,eax 2141 | invoke CreatePatternBrush, hBitmap 2142 | mov g_hHalftoneBrush, eax 2143 | invoke DeleteObject, hBitmap 2144 | .endif 2145 | 2146 | invoke GetClientRect, m_hWndTV, addr rect 2147 | 2148 | invoke GetDC, hWnd 2149 | mov hdc, eax 2150 | invoke SelectObject, hdc, g_hHalftoneBrush 2151 | mov hBrushOld, eax 2152 | mov ecx, iToolbarHeight 2153 | add ecx, 2 2154 | invoke PatBlt, hdc, xPos, ecx, GRIPSIZE, rect.bottom, PATINVERT 2155 | 2156 | invoke SelectObject, hdc, hBrushOld 2157 | invoke ReleaseDC, hWnd, hdc 2158 | mov eax, xPos 2159 | mov g_iOldResizeLine, eax 2160 | ret 2161 | align 4 2162 | 2163 | DrawResizeLine endp 2164 | 2165 | 2166 | ;--- WM_SIZE 2167 | 2168 | 2169 | OnSize proc 2170 | 2171 | local rect:RECT 2172 | local rectSB:RECT 2173 | 2174 | invoke GetClientRect, m_hWnd, addr rect 2175 | .if (m_bStatusBar) 2176 | invoke GetWindowRect, m_hWndSB, addr rectSB 2177 | mov ecx, rectSB.bottom 2178 | sub ecx, rectSB.top 2179 | sub rect.bottom, ecx 2180 | invoke SetWindowPos, m_hWndSB, NULL, 0, rect.bottom, rect.right, ecx, SWP_NOZORDER or SWP_NOACTIVATE 2181 | .endif 2182 | 2183 | .if (!m_bCreateView) 2184 | invoke SetWindowPos, m_hWndTV, NULL, 0, 0, rect.right, rect.bottom, SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE 2185 | .else 2186 | invoke GetLeftPanelWidth, addr rect 2187 | mov m_dwSizeTV, eax 2188 | mov ecx, eax 2189 | push ecx 2190 | invoke SetWindowPos, m_hWndTV, NULL, 0, 0, ecx, rect.bottom, SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE 2191 | pop edx 2192 | add edx, GRIPSIZE 2193 | mov ecx, rect.right 2194 | sub ecx, edx 2195 | invoke SetWindowPos, m_hWndView, NULL, edx, 0, ecx, rect.bottom, SWP_NOZORDER or SWP_NOACTIVATE 2196 | .endif 2197 | ret 2198 | align 4 2199 | 2200 | OnSize endp 2201 | 2202 | ;---------------------------------------------------------- 2203 | ;--- WM_CREATE 2204 | ;---------------------------------------------------------- 2205 | 2206 | OnCreate proc uses esi edi 2207 | 2208 | local dummy:DWORD 2209 | ;local sfs:SHELLFLAGSTATE 2210 | local dwWidth:DWORD 2211 | local dwXMax:DWORD 2212 | local dwYMax:DWORD 2213 | local rect:RECT 2214 | 2215 | ;-------------------------- got a window rect? 2216 | .if (m_rect.left) 2217 | invoke SetWindowPos, m_hWnd, NULL, m_rect.left, m_rect.top, 2218 | m_rect.right, m_rect.bottom, SWP_NOZORDER or SWP_NOACTIVATE 2219 | .else 2220 | ;-------------------------- no. check sizes are suitable 2221 | invoke GetSystemMetrics, SM_CXSCREEN 2222 | mov dwXMax, eax 2223 | invoke GetSystemMetrics, SM_CYSCREEN 2224 | mov dwYMax, eax 2225 | mov ecx, g_rect.right 2226 | mov edx, g_rect.bottom 2227 | .if ((!ecx) || (!edx) || (ecx > dwXMax) || (edx > dwYMax)) 2228 | invoke MulDiv, dwXMax, 2, 3 2229 | mov g_rect.right, eax 2230 | invoke MulDiv, dwYMax, 2, 3 2231 | mov g_rect.bottom, eax 2232 | .endif 2233 | mov ecx, g_rect.left 2234 | mov edx, g_rect.top 2235 | .if (((!ecx) && (!edx)) || (ecx >= dwXMax) || (edx >= dwYMax)) 2236 | mov eax, dwXMax 2237 | sub eax, g_rect.right 2238 | shr eax, 1 2239 | mov g_rect.left, eax 2240 | 2241 | mov eax, dwYMax 2242 | sub eax, g_rect.bottom 2243 | shr eax, 1 2244 | mov g_rect.top, eax 2245 | .endif 2246 | invoke SetWindowPos, m_hWnd, NULL, g_rect.left, g_rect.top, 2247 | g_rect.right, g_rect.bottom, SWP_NOZORDER or SWP_NOACTIVATE 2248 | .endif 2249 | 2250 | mov ecx, WS_CHILD or WS_VISIBLE or WS_TABSTOP or TVS_HASBUTTONS or TVS_HASLINES or TVS_SHOWSELALWAYS or TVS_EDITLABELS or 4000h 2251 | .if (g_bTrackSelect) 2252 | or ecx, TVS_TRACKSELECT 2253 | .endif 2254 | 2255 | invoke CreateWindowEx, WS_EX_CLIENTEDGE, CStr("SysTreeView32"), NULL, ecx, 2256 | 0,0,0,0, m_hWnd, IDC_TREE1, g_hInstance, NULL 2257 | mov m_hWndTV, eax 2258 | 2259 | if ?IMAGELIST 2260 | .if (g_himl) 2261 | invoke TreeView_SetImageList( m_hWndTV, g_himl, TVSIL_NORMAL) 2262 | .endif 2263 | endif 2264 | 2265 | invoke CreateWindowEx, 0, CStr("msctls_statusbar32"), NULL, 2266 | WS_CHILD or WS_VISIBLE or SBARS_SIZEGRIP or CCS_BOTTOM, 2267 | 0,0,0,0, m_hWnd, IDC_STATUSBAR, g_hInstance, NULL 2268 | mov m_hWndSB, eax 2269 | 2270 | mov dwWidth,-1 2271 | StatusBar_SetParts m_hWndSB, 1, addr dwWidth 2272 | 2273 | mov al, g_bCreateView 2274 | mov m_bCreateView, al 2275 | mov al,g_bGetUIObjectOf 2276 | mov m_bGetUIObjectOf, al 2277 | mov al, g_bCompMenus 2278 | mov m_bCompMenus, al 2279 | mov al, g_bStatusBar 2280 | mov m_bStatusBar, al 2281 | mov al, g_bDropTarget 2282 | mov m_bDropTarget, al 2283 | 2284 | invoke UpdateMenu 2285 | 2286 | .if (!m_bStatusBar) 2287 | invoke ShowWindow, m_hWndSB, SW_HIDE 2288 | .endif 2289 | 2290 | .if (m_bDropTarget) 2291 | lea ecx, m__IDropTarget 2292 | invoke RegisterDragDrop, m_hWndTV, ecx 2293 | .endif 2294 | 2295 | ret 2296 | align 4 2297 | 2298 | OnCreate endp 2299 | 2300 | 2301 | ParseDisplayName proc 2302 | 2303 | local hinstShell:HINSTANCE 2304 | local pidl:LPITEMIDLIST 2305 | local sfgaof:SFGAOF 2306 | local wszPath[MAX_PATH]:word 2307 | 2308 | .if (!g_szPath) 2309 | return 0 2310 | .endif 2311 | 2312 | mov pidl, NULL 2313 | invoke MultiByteToWideChar, CP_ACP, MB_PRECOMPOSED, 2314 | addr g_szPath, -1, addr wszPath, MAX_PATH 2315 | if 0 2316 | .if (g_lpfnSHParseDisplayName) 2317 | invoke g_lpfnSHParseDisplayName, addr wszPath, NULL, 2318 | addr pidl, NULL, NULL 2319 | .endif 2320 | else 2321 | invoke vf(m_pShellFolder, IShellFolder, ParseDisplayName), m_hWnd, 2322 | NULL, addr wszPath, NULL, addr pidl, NULL 2323 | endif 2324 | mov eax, pidl 2325 | ret 2326 | ParseDisplayName endp 2327 | 2328 | ;---------------------------------------------------------- 2329 | ;--- dialog proc CShellBrowser 2330 | ;---------------------------------------------------------- 2331 | 2332 | WndProc@CShellBrowser proc uses __this this_:ptr CShellBrowser, message:DWORD, wParam:WPARAM, lParam:LPARAM 2333 | 2334 | local lo:DWORD 2335 | local hi:DWORD 2336 | local pidl:LPITEMIDLIST 2337 | local wp:WINDOWPLACEMENT 2338 | local rect:RECT 2339 | local rect2:RECT 2340 | 2341 | mov __this, this_ 2342 | 2343 | if 0 2344 | .if (message == WM_SETCURSOR) 2345 | .elseif (message == WM_NOTIFY) 2346 | .elseif (message == WM_NCHITTEST) 2347 | .elseif (message == WM_NCMOUSEMOVE) 2348 | .elseif (message == WM_ENTERIDLE) 2349 | .else 2350 | DebugOut "DlgProc, msg=%X", message 2351 | .endif 2352 | endif 2353 | 2354 | mov eax, message 2355 | .if (eax == WM_CREATE) 2356 | invoke OnCreate 2357 | invoke SetFocus, m_hWndTV 2358 | invoke SendMessage, m_hWnd, WM_COMMAND, IDM_REFRESH, 0 2359 | invoke ParseDisplayName 2360 | .if (eax) 2361 | mov pidl, eax 2362 | invoke NavigateToPidl, pidl 2363 | invoke vf(m_pMalloc, IMalloc, Free), pidl 2364 | .endif 2365 | .if (g_lpfnSHChangeNotifyRegister) 2366 | invoke SHGetSpecialFolderLocation, m_hWnd, CSIDL_DESKTOP, addr pidl 2367 | invoke g_lpfnSHChangeNotifyRegister, m_hWnd, 2, 2368 | SHCNE_ALLEVENTS, WM_SHNOTIFY, 1, addr pidl 2369 | mov m_hSHNotify, eax 2370 | invoke vf(m_pMalloc, IMalloc, Free), pidl 2371 | .endif 2372 | 2373 | xor eax, eax 2374 | 2375 | .elseif (eax == WM_CLOSE) 2376 | 2377 | .if (m_hSHNotify && g_lpfnSHChangeNotifyUnregister) 2378 | invoke g_lpfnSHChangeNotifyUnregister, m_hSHNotify 2379 | .endif 2380 | invoke Deinit@IServiceProvider 2381 | invoke TreeView_GetSelection( m_hWndTV) 2382 | .if (eax) 2383 | invoke GetFullPidl@CShellBrowser, eax 2384 | mov pidl, eax 2385 | mov g_szPath, 0 2386 | invoke SHGetPathFromIDList, pidl, addr g_szPath 2387 | invoke vf(m_pMalloc, IMalloc, Free), pidl 2388 | .endif 2389 | invoke ReleaseShellView 2390 | invoke DestroyWindow, m_hWnd 2391 | invoke Destroy@CShellBrowser, __this 2392 | 2393 | .elseif (eax == WM_NOTIFY) 2394 | 2395 | invoke OnNotify, lParam 2396 | 2397 | .elseif (eax == WM_SIZE) 2398 | 2399 | invoke OnSize 2400 | 2401 | mov wp.length_, sizeof WINDOWPLACEMENT 2402 | invoke GetWindowPlacement, m_hWnd, addr wp 2403 | invoke CopyRect, addr g_rect, addr wp.rcNormalPosition 2404 | mov eax, g_rect.right 2405 | sub eax, g_rect.left 2406 | mov g_rect.right, eax 2407 | mov eax, g_rect.bottom 2408 | sub eax, g_rect.top 2409 | mov g_rect.bottom, eax 2410 | xor eax, eax 2411 | 2412 | .elseif (eax == WM_COMMAND) 2413 | 2414 | invoke OnCommand, wParam, lParam 2415 | 2416 | .elseif (eax == WM_SETCURSOR) 2417 | 2418 | movzx eax, word ptr lParam+0 2419 | mov ecx, wParam 2420 | .if ((eax == HTCLIENT) && (ecx == m_hWnd)) 2421 | invoke SetCursor, g_hCursor 2422 | mov eax, 1 2423 | .else 2424 | jmp default 2425 | .endif 2426 | 2427 | .elseif (eax == WM_GETISHELLBROWSER) 2428 | 2429 | DebugOut "undocumented message WM_GETISHELLBROWSER received" 2430 | mov eax, __this 2431 | 2432 | .elseif (eax == WM_SHNOTIFY) 2433 | 2434 | invoke OnSHNotify, wParam, lParam 2435 | 2436 | .elseif ((eax == WM_INITMENUPOPUP) || (eax == WM_ENTERMENULOOP) || (eax == WM_EXITMENULOOP)) 2437 | 2438 | xor eax, eax 2439 | .if (m_pContextMenu2) 2440 | .if (message == WM_INITMENUPOPUP) 2441 | invoke vf(m_pContextMenu2, IContextMenu2, HandleMenuMsg), message, wParam, lParam 2442 | mov eax, 1 2443 | .endif 2444 | .elseif (m_hWndView) 2445 | DebugOut "WM_INITMENUPOPUP/ENTERMENULOOP/EXITMENULOOP enter(%X)", message 2446 | invoke SendMessage, m_hWndView, message, wParam, lParam 2447 | DebugOut "WM_INITMENUPOPUP/ENTERMENULOOP/EXITMENULOOP exit" 2448 | .endif 2449 | 2450 | .elseif (eax == WM_MENUSELECT) 2451 | 2452 | xor eax, eax 2453 | movzx ecx, word ptr wParam 2454 | .if ((ecx >= FCIDM_BROWSERFIRST) && (ecx <= FCIDM_BROWSERLAST)) 2455 | ; 2456 | .elseif (m_hWndView) 2457 | DebugOut "WM_MENUSELECT enter(%X)", ecx 2458 | invoke SendMessage, m_hWndView, message, wParam, lParam 2459 | DebugOut "WM_MENUSELECT exit" 2460 | .endif 2461 | 2462 | .elseif ((eax == WM_MEASUREITEM) || (eax == WM_DRAWITEM)) 2463 | 2464 | DebugOut "WM_MEASUREITEM/WM_DRAWITEM" 2465 | xor eax, eax 2466 | .if (m_pContextMenu2) 2467 | invoke vf(m_pContextMenu2, IContextMenu2, HandleMenuMsg), message, wParam, lParam 2468 | mov eax, 1 2469 | .elseif (m_hWndView) 2470 | invoke SendMessage, m_hWndView, message, wParam, lParam 2471 | .endif 2472 | 2473 | .elseif (eax == WM_LBUTTONDOWN) 2474 | 2475 | xor eax, eax 2476 | .if (m_hWndView) 2477 | invoke SetCapture, m_hWnd 2478 | 2479 | invoke GetWindowRect, m_hWndTV, addr rect 2480 | invoke GetWindowRect, m_hWndView, addr rect2 2481 | invoke UnionRect, addr rect, addr rect, addr rect2 2482 | invoke ClipCursor, addr rect 2483 | mov g_iOldResizeLine, -1 2484 | movzx eax, word ptr lParam+0 2485 | invoke DrawResizeLine, m_hWnd, eax 2486 | .endif 2487 | 2488 | .elseif (eax == WM_LBUTTONUP) 2489 | 2490 | invoke GetCapture 2491 | .if (eax == m_hWnd) 2492 | invoke ClipCursor, NULL 2493 | invoke ReleaseCapture 2494 | invoke DrawResizeLine, m_hWnd, g_iOldResizeLine 2495 | movzx eax, word ptr lParam 2496 | mov m_dwSizeTV, eax 2497 | invoke OnSize 2498 | .endif 2499 | 2500 | .elseif (eax == WM_MOUSEMOVE) 2501 | 2502 | invoke GetCapture 2503 | .if (eax == m_hWnd) 2504 | invoke DrawResizeLine, m_hWnd, g_iOldResizeLine 2505 | movzx eax, word ptr lParam+0 2506 | invoke DrawResizeLine, m_hWnd, eax 2507 | .endif 2508 | 2509 | .elseif (eax == WM_SETFOCUS) 2510 | 2511 | .if (m_hWndFocus) 2512 | invoke SetFocus, m_hWndFocus 2513 | .endif 2514 | 2515 | .elseif (eax == WM_DDE_INITIATE) 2516 | 2517 | DebugOut "WM_DDE_INITIATE, wParam=%X, lParam=%X, m_hWndView=%X", wParam, lParam, m_hWndView 2518 | .if (!m_bDontRespond) 2519 | ;------------------------------- respond to windows from this thread only 2520 | movzx ecx, word ptr lParam+0 2521 | movzx edx, word ptr lParam+2 2522 | .if ((ecx == g_aApplication) && (edx == g_aTopic)) 2523 | invoke GetWindowThreadProcessId, wParam, NULL 2524 | push eax 2525 | invoke GetCurrentThreadId 2526 | pop ecx 2527 | .if (ecx == eax) 2528 | invoke SendMessage, wParam, WM_DDE_ACK, m_hWnd, lParam 2529 | .endif 2530 | .endif 2531 | .endif 2532 | 2533 | .elseif (eax == WM_DDE_EXECUTE) 2534 | 2535 | DebugOut "WM_DDE_EXECUTE, wParam=%X, lParam=%X", wParam, lParam 2536 | invoke UnpackDDElParam, WM_DDE_EXECUTE, lParam, addr lo, addr hi 2537 | invoke GlobalLock, hi 2538 | ;------------------------------- now a fantastic amount of work is to be done 2539 | invoke OnDDEExecute, eax 2540 | .if (eax) 2541 | mov lo, 8000h 2542 | .else 2543 | mov lo, 0 2544 | .endif 2545 | invoke GlobalUnlock, hi 2546 | invoke ReuseDDElParam, lParam, WM_DDE_EXECUTE, WM_DDE_ACK, lo, hi 2547 | invoke PostMessage, wParam, WM_DDE_ACK, m_hWnd, eax 2548 | 2549 | .elseif (eax == WM_DDE_TERMINATE) 2550 | 2551 | DebugOut "WM_DDE_TERMINATE, wParam=%X", wParam 2552 | invoke PostMessage, wParam, WM_DDE_TERMINATE, m_hWnd, lParam 2553 | 2554 | .else 2555 | default: 2556 | invoke DefWindowProc, m_hWnd, message, wParam, lParam 2557 | .endif 2558 | exit: 2559 | ret 2560 | align 4 2561 | 2562 | WndProc@CShellBrowser endp 2563 | 2564 | 2565 | ;--- true dialog proc 2566 | 2567 | 2568 | WndProc proc hWnd:HWND, message:DWORD, wParam:WPARAM, lParam:LPARAM 2569 | 2570 | .if (message == WM_NCCREATE) 2571 | mov ecx, lParam 2572 | mov ecx,[ecx].CREATESTRUCT.lpCreateParams 2573 | mov eax, hWnd 2574 | mov [ecx].CShellBrowser.hWnd, eax 2575 | push ecx 2576 | invoke SetWindowLong, hWnd, GWL_USERDATA, ecx 2577 | pop eax 2578 | .else 2579 | invoke GetWindowLong, hWnd, GWL_USERDATA 2580 | .endif 2581 | 2582 | .if (eax) 2583 | invoke WndProc@CShellBrowser, eax, message, wParam, lParam 2584 | .endif 2585 | ret 2586 | align 4 2587 | 2588 | WndProc endp 2589 | 2590 | ;---------------------------------------------------------------- 2591 | ;--- IShellBrowser methods 2592 | ;---------------------------------------------------------------- 2593 | 2594 | GetWindow_ proc uses __this this_:ptr CShellBrowser, phwnd:ptr HWND 2595 | 2596 | mov __this, this_ 2597 | DebugOut "IShellBrowser::GetWindow(%X)",phwnd 2598 | mov eax, m_hWnd 2599 | mov ecx, phwnd 2600 | mov [ecx],eax 2601 | return S_OK 2602 | align 4 2603 | 2604 | GetWindow_ endp 2605 | 2606 | 2607 | ContextSensitiveHelp proc uses __this this_:ptr CShellBrowser, fEnterMode:BOOL 2608 | 2609 | mov __this, this_ 2610 | DebugOut "IShellBrowser::ContextSensitiveHelp" 2611 | return E_UNEXPECTED 2612 | align 4 2613 | 2614 | ContextSensitiveHelp endp 2615 | 2616 | 2617 | InsertMenusSB proc uses __this esi this_:ptr CShellBrowser, hmenuShared:HMENU, lpMenuWidths:ptr OLEMENUGROUPWIDTHS 2618 | 2619 | local hMenu:HMENU 2620 | local hSubMenu:HMENU 2621 | local mii:MENUITEMINFO 2622 | 2623 | mov __this, this_ 2624 | 2625 | DebugOut "IShellBrowser::InsertMenusSB(%X)", hmenuShared 2626 | 2627 | .if (!m_bCompMenus) 2628 | return S_OK 2629 | .endif 2630 | 2631 | invoke LoadMenu, g_hInstance, IDR_MENU1 2632 | mov hMenu, eax 2633 | 2634 | invoke RtlZeroMemory, addr mii, sizeof MENUITEMINFO 2635 | mov mii.cbSize, sizeof MENUITEMINFO 2636 | mov mii.fMask, MIIM_SUBMENU or MIIM_STATE or MIIM_TYPE or MIIM_ID 2637 | mov mii.fType, MFT_STRING 2638 | mov mii.fState, MFS_ENABLED 2639 | 2640 | mov esi, lpMenuWidths 2641 | invoke GetSubMenu, hMenu, 0 2642 | .if (eax) 2643 | mov mii.hSubMenu, eax 2644 | mov mii.wID, FCIDM_MENU_FILE 2645 | mov mii.dwTypeData, CStr("&File") 2646 | invoke InsertMenuItem, hmenuShared, -1, TRUE, addr mii 2647 | inc dword ptr [esi+0*sizeof DWORD] 2648 | .endif 2649 | invoke CreatePopupMenu 2650 | .if (eax) 2651 | mov mii.hSubMenu, eax 2652 | mov mii.wID, FCIDM_MENU_EDIT 2653 | mov mii.dwTypeData, CStr("&Edit") 2654 | invoke InsertMenuItem, hmenuShared, -1, TRUE, addr mii 2655 | inc dword ptr [esi+0*sizeof DWORD] 2656 | .endif 2657 | 2658 | invoke GetSubMenu, hMenu, 1 2659 | .if (eax) 2660 | mov hSubMenu, eax 2661 | mov mii.fMask, MIIM_TYPE or MIIM_ID 2662 | mov mii.wID, FCIDM_MENU_VIEW_SEP_OPTIONS 2663 | mov mii.fType, MFT_SEPARATOR 2664 | invoke InsertMenuItem, hSubMenu, 1, TRUE, addr mii 2665 | 2666 | mov eax, hSubMenu 2667 | mov mii.hSubMenu, eax 2668 | mov mii.fMask, MIIM_SUBMENU or MIIM_STATE or MIIM_TYPE or MIIM_ID 2669 | mov mii.fType, MFT_STRING 2670 | mov mii.wID, FCIDM_MENU_VIEW 2671 | mov mii.dwTypeData, CStr("&View") 2672 | invoke InsertMenuItem, hmenuShared, -1, TRUE, addr mii 2673 | inc dword ptr [esi+2*sizeof DWORD] 2674 | .endif 2675 | 2676 | invoke GetSubMenu, hMenu, 2 2677 | .if (eax) 2678 | mov mii.hSubMenu, eax 2679 | mov mii.wID, FCIDM_MENU_TOOLS 2680 | mov mii.dwTypeData, CStr("&Tools") 2681 | invoke InsertMenuItem, hmenuShared, -1, TRUE, addr mii 2682 | inc dword ptr [esi+2*sizeof DWORD] 2683 | .endif 2684 | 2685 | invoke GetSubMenu, hMenu, 3 2686 | .if (eax) 2687 | mov mii.hSubMenu, eax 2688 | mov mii.wID, FCIDM_MENU_HELP 2689 | mov mii.dwTypeData, CStr("&Help") 2690 | invoke InsertMenuItem, hmenuShared, -1, TRUE, addr mii 2691 | inc dword ptr [esi+4*sizeof DWORD] 2692 | .endif 2693 | return S_OK 2694 | align 4 2695 | 2696 | InsertMenusSB endp 2697 | 2698 | 2699 | SetMenuSB proc uses __this this_:ptr CShellBrowser, hmenuShared:HMENU, dwReserved:DWORD, hwndActiveObject:HWND 2700 | 2701 | mov __this, this_ 2702 | DebugOut "IShellBrowser::SetMenuSB(%X,%X,%X)", hmenuShared, dwReserved, hwndActiveObject 2703 | .if (!m_bCompMenus) 2704 | return S_OK 2705 | .endif 2706 | if 1 2707 | .if (hmenuShared) 2708 | invoke SetMenu, m_hWnd, hmenuShared 2709 | .else 2710 | invoke LoadMenu, g_hInstance, IDR_MENU1 2711 | invoke SetMenu, m_hWnd, eax 2712 | .endif 2713 | invoke UpdateMenu 2714 | else 2715 | invoke SetMenu, m_hWnd, hmenuShared 2716 | .if (hmenuShared) 2717 | invoke UpdateMenu 2718 | .endif 2719 | endif 2720 | return S_OK 2721 | align 4 2722 | 2723 | SetMenuSB endp 2724 | 2725 | 2726 | RemoveMenusSB proc uses __this this_:ptr CShellBrowser, hmenuShared:HMENU 2727 | 2728 | mov __this, this_ 2729 | DebugOut "IShellBrowser::RemoveMenusSB(%X)", hmenuShared 2730 | if 0 2731 | invoke DeleteMenu, hmenuShared, FCIDM_MENU_FILE, MF_BYCOMMAND 2732 | invoke DeleteMenu, hmenuShared, FCIDM_MENU_EDIT, MF_BYCOMMAND 2733 | invoke DeleteMenu, hmenuShared, FCIDM_MENU_TOOLS, MF_BYCOMMAND 2734 | endif 2735 | return S_OK 2736 | align 4 2737 | 2738 | RemoveMenusSB endp 2739 | 2740 | 2741 | SetStatusTextSB proc uses __this this_:ptr CShellBrowser, lpszStatusText:LPCOLESTR 2742 | 2743 | local szText[256]:byte 2744 | 2745 | mov __this, this_ 2746 | DebugOut "IShellBrowser::SetStatusTextSB(%X)", lpszStatusText 2747 | .if ( lpszStatusText ) 2748 | invoke WideCharToMultiByte, CP_ACP, 0, lpszStatusText, -1, addr szText, sizeof szText, NULL, NULL 2749 | lea eax, szText 2750 | .else 2751 | mov eax, CStr("") 2752 | .endif 2753 | StatusBar_SetText m_hWndSB, 0, eax 2754 | return S_OK 2755 | align 4 2756 | 2757 | SetStatusTextSB endp 2758 | 2759 | 2760 | EnableModelessSB proc uses __this this_:ptr CShellBrowser, fEnable:BOOL 2761 | 2762 | mov __this, this_ 2763 | DebugOut "IShellBrowser::EnableModelessSB(%X)", fEnable 2764 | return S_OK 2765 | align 4 2766 | 2767 | EnableModelessSB endp 2768 | 2769 | 2770 | TranslateAcceleratorSB proc uses __this this_:ptr CShellBrowser, lpmsg:ptr MSG, wID:WORD 2771 | 2772 | mov __this, this_ 2773 | ;; DebugOut "IShellBrowser::TranslateAcceleratorSB" 2774 | invoke TranslateAccelerator, m_hWnd, g_hAccel, lpmsg 2775 | .if (eax) 2776 | mov eax, S_OK 2777 | .else 2778 | mov eax, S_FALSE 2779 | .endif 2780 | ret 2781 | align 4 2782 | 2783 | TranslateAcceleratorSB endp 2784 | 2785 | ;--- function should allow a view to navigate to an item 2786 | ;--- (inside or outside of the current folder). But is 2787 | ;--- not used currently 2788 | 2789 | BrowseObject proc uses __this this_:ptr CShellBrowser, pidl:LPITEMIDLIST, wFlags:DWORD 2790 | 2791 | mov __this, this_ 2792 | DebugOut "IShellBrowser::BrowseObject(%X, %X)", pidl, wFlags 2793 | .if (wFlags & SBSP_ABSOLUTE) 2794 | invoke NavigateToPidl, pidl 2795 | .if (eax) 2796 | return S_OK 2797 | .endif 2798 | .endif 2799 | return E_FAIL 2800 | align 4 2801 | 2802 | BrowseObject endp 2803 | 2804 | 2805 | GetViewStateStream proc uses __this this_:ptr CShellBrowser, grfMode:DWORD, ppStrm:ptr LPSTREAM 2806 | 2807 | mov __this, this_ 2808 | DebugOut "IShellBrowser::GetViewStateStream(%X, %X)", grfMode, ppStrm 2809 | .if (!m_pStream) 2810 | invoke CreateStreamOnHGlobal, NULL, TRUE, addr m_pStream 2811 | .endif 2812 | mov ecx, ppStrm 2813 | mov eax, m_pStream 2814 | mov dword ptr [ecx], eax 2815 | .if (eax) 2816 | invoke vf(m_pStream, IUnknown, AddRef) 2817 | return S_OK 2818 | .else 2819 | return E_OUTOFMEMORY 2820 | .endif 2821 | align 4 2822 | 2823 | GetViewStateStream endp 2824 | 2825 | ;--- get control hwnds 2826 | ;--- FCW_STATUS(1), FCW_TOOLBAR(2), FCW_TREE (3) 2827 | 2828 | GetControlWindow proc uses __this this_:ptr CShellBrowser, id:DWORD, lphwnd:ptr HWND 2829 | 2830 | mov __this, this_ 2831 | DebugOut "IShellBrowser::GetControlWindow(%X, %X)", id, lphwnd 2832 | .if (id == FCW_TREE) 2833 | mov edx, m_hWndTV 2834 | mov eax, S_OK 2835 | .elseif (id == FCW_STATUS) 2836 | mov edx, m_hWndSB 2837 | mov eax, S_OK 2838 | .else 2839 | xor edx, edx 2840 | mov eax, E_FAIL 2841 | .endif 2842 | mov ecx, lphwnd 2843 | mov [ecx], edx 2844 | ret 2845 | align 4 2846 | 2847 | GetControlWindow endp 2848 | 2849 | ;SB_SETTEXTA equ 2850 | ;SB_SETICON equ 2851 | 2852 | SendControlMsg proc uses __this this_:ptr CShellBrowser, id:DWORD, uMsg:DWORD, wParam:WPARAM, lParam:LPARAM, pres:ptr DWORD 2853 | 2854 | mov __this, this_ 2855 | ifdef _DEBUG 2856 | .if (id == FCW_STATUS) 2857 | .if ((uMsg == SB_SETTEXTW) || (uMsg == SB_SETTEXTA)) 2858 | sub esp,64*2 2859 | mov edx, esp 2860 | .if (uMsg == SB_SETTEXTW) 2861 | invoke WideCharToMultiByte, CP_ACP, 0, lParam, -1, edx, 64, 0, 0 2862 | .else 2863 | invoke lstrcpyn, edx, lParam, 64 2864 | .endif 2865 | mov edx, esp 2866 | DebugOut "IShellBrowser::SendControlMsg(FCW_STATUS,SB_SETTEXT,%u,'%s')", wParam, edx 2867 | add esp,64*2 2868 | .elseif (uMsg == SB_SETICON) 2869 | DebugOut "IShellBrowser::SendControlMsg(FCW_STATUS,SB_SETICON,%u,%X)", wParam, lParam 2870 | .elseif (uMsg == SB_SETPARTS) 2871 | DebugOut "IShellBrowser::SendControlMsg(FCW_STATUS,SB_SETPARTS,%u)", wParam 2872 | .else 2873 | DebugOut "IShellBrowser::SendControlMsg(%X,%X,%X,%X)", id, uMsg, wParam, lParam 2874 | .endif 2875 | .else 2876 | DebugOut "IShellBrowser::SendControlMsg(%X,%X,%X,%X)", id, uMsg, wParam, lParam 2877 | .endif 2878 | endif 2879 | .if (id == FCW_TREE) 2880 | mov eax, m_hWndTV 2881 | .elseif (id == FCW_STATUS) 2882 | mov eax, m_hWndSB 2883 | .else 2884 | xor eax, eax 2885 | .endif 2886 | 2887 | .if (eax) 2888 | invoke SendMessage, eax, uMsg, wParam, lParam 2889 | mov ecx, pres 2890 | .if (ecx) 2891 | mov [ecx], eax 2892 | .endif 2893 | mov eax, S_OK 2894 | .else 2895 | mov ecx, pres 2896 | .if (ecx) 2897 | mov dword ptr [ecx],0 2898 | .endif 2899 | mov eax, E_FAIL 2900 | .endif 2901 | ret 2902 | align 4 2903 | 2904 | SendControlMsg endp 2905 | 2906 | 2907 | QueryActiveShellView proc uses __this this_:ptr CShellBrowser, ppshv:ptr LPSHELLVIEW 2908 | 2909 | mov __this, this_ 2910 | DebugOut "IShellBrowser::QueryActiveShellView" 2911 | mov ecx, ppshv 2912 | mov eax, m_pShellView 2913 | mov dword ptr [ecx], eax 2914 | .if (eax) 2915 | invoke vf(eax, IShellView, AddRef) 2916 | mov eax, S_OK 2917 | .else 2918 | mov eax, E_FAIL 2919 | .endif 2920 | ret 2921 | align 4 2922 | 2923 | QueryActiveShellView endp 2924 | 2925 | ;--- the view window has got the focus 2926 | 2927 | OnViewWindowActive proc uses __this this_:ptr CShellBrowser, pshv:LPSHELLVIEW 2928 | 2929 | mov __this, this_ 2930 | DebugOut "IShellBrowser::OnViewWindowActive(%X)", pshv 2931 | mov eax, m_hWndView 2932 | mov m_hWndFocus, eax 2933 | return S_OK 2934 | align 4 2935 | 2936 | OnViewWindowActive endp 2937 | 2938 | 2939 | SetToolbarItems proc uses __this this_:ptr CShellBrowser, lpButtons:ptr TBBUTTON, nButtons:DWORD, uFlags:DWORD 2940 | 2941 | mov __this, this_ 2942 | DebugOut "IShellBrowser::SetToolbarItems" 2943 | return S_OK 2944 | align 4 2945 | 2946 | SetToolbarItems endp 2947 | 2948 | 2949 | end 2950 | -------------------------------------------------------------------------------- /CShellBrowser.inc: -------------------------------------------------------------------------------- 1 | 2 | ?SERVICEPROVIDER equ 1 ;support IServiceProvider 3 | ?OLECOMMANDTARGET equ 1 ;support IOleCommandTarget 4 | ?DROPTARGET equ 1 ;support IDropTarget 5 | ?DRAGDROPHELPER equ 1 ;use DragDropHelper 6 | ?OLEINPLACEFRAME equ 0 ;support IOleInPlaceFrame+IOleInPlaceUIWindow 7 | ?WEBBROWSER equ 0 ;browsing in explorer for win98 (not finished) 8 | 9 | LPDROPTARGETHELPER typedef ptr IDropTargetHelper 10 | 11 | if ?SERVICEPROVIDER 12 | include servprov.inc 13 | endif 14 | if ?OLECOMMANDTARGET 15 | include docobj.inc 16 | endif 17 | if ?WEBBROWSER 18 | include exdisp.inc 19 | endif 20 | 21 | CShellBrowser struct 22 | 23 | ifdef INSIDE_CShellBrowser 24 | 25 | BEGIN_COM_MAP CShellBrowser 26 | COM_INTERFACE_ENTRY IShellBrowser 27 | if ?SERVICEPROVIDER 28 | COM_INTERFACE_ENTRY IServiceProvider 29 | endif 30 | if ?OLECOMMANDTARGET 31 | COM_INTERFACE_ENTRY IOleCommandTarget 32 | endif 33 | if ?DROPTARGET 34 | COM_INTERFACE_ENTRY IDropTarget 35 | endif 36 | if ?OLEINPLACEFRAME 37 | COM_INTERFACE_ENTRY_EX IOleInPlaceFrame, IOleInPlaceUIWindow, IOleWindow 38 | endif 39 | END_COM_MAP 40 | 41 | hWnd HWND ? 42 | hWndTV HWND ? 43 | hWndView HWND ? 44 | hWndSB HWND ? 45 | hWndFocus HWND ? 46 | pShellFolder LPSHELLFOLDER ? 47 | pShellView LPSHELLVIEW ? 48 | pContextMenu2 LPCONTEXTMENU2 ? 49 | if ?OLEINPLACEFRAME 50 | pOleInPlaceActiveObject LPOLEINPLACEACTIVEOBJECT ? 51 | endif 52 | if ?WEBBROWSER 53 | pWebBrowser LPWEBBROWSER2 ? 54 | endif 55 | pMalloc LPMALLOC ? 56 | pStream LPSTREAM ? 57 | hSHNotify HANDLE ? 58 | dwSizeTV DWORD ? 59 | rect RECT <> 60 | bCreateView BOOLEAN ? ;create right panel views 61 | bGetUIObjectOf BOOLEAN ? ;call IShellFolder::GetUIObjectOf for context menu 62 | bCompMenus BOOLEAN ? ;support composite menus 63 | bStatusBar BOOLEAN ? ;status bar is visible 64 | bDropTarget BOOLEAN ? ;treeview is a drop target 65 | bDontRespond BOOLEAN ? ;do not respond to DDE messages 66 | bLabelEdit BOOLEAN ? ;currently in label edit mode 67 | bRButton BOOLEAN ? ;drag&drop with right mouse button? 68 | 69 | endif 70 | 71 | CShellBrowser ends 72 | 73 | 74 | Create@CShellBrowser PROTO :LPUNKNOWN 75 | Show@CShellBrowser PROTO :ptr CShellBrowser, :HWND 76 | TranslateAccelerator@CShellBrowser PROTO :ptr CShellBrowser, :ptr MSG 77 | GetFullPidl@CShellBrowser PROTO :HANDLE 78 | Deinit@IServiceProvider PROTO 79 | GetFolder PROTO :HANDLE 80 | InsertChildItems PROTO :HANDLE 81 | _StrToLong PROTO :LPSTR 82 | FindPidl PROTO :LPITEMIDLIST, :BOOL 83 | NavigateToPidl PROTO :LPITEMIDLIST 84 | Pidl_Copy PROTO :LPITEMIDLIST 85 | Pidl_GetLastItem PROTO :LPITEMIDLIST 86 | Pidl_SkipLastItem PROTO :LPITEMIDLIST, :ptr LPITEMIDLIST 87 | 88 | externdef CServiceProviderVtbl: DWORD 89 | externdef COleCommandTargetVtbl: DWORD 90 | externdef CDropTargetVtbl: DWORD 91 | externdef COleInPlaceFrameVtbl: DWORD 92 | 93 | externdef g_DllRefCount:DWORD 94 | externdef g_bGetUIObjectOf:BOOLEAN 95 | externdef g_bCreateView:BOOLEAN 96 | externdef g_bCompMenus:BOOLEAN 97 | externdef g_aApplication:DWORD 98 | externdef g_aTopic:DWORD 99 | externdef g_rect:RECT 100 | externdef g_szPath:BYTE 101 | if ?DRAGDROPHELPER 102 | externdef g_pDropTargetHelper:LPDROPTARGETHELPER 103 | endif 104 | 105 | ;--- macros + equates 106 | 107 | @MakeStubs macro classname, interface, memberlist:VARARG 108 | for member, 109 | member&_: 110 | sub DWORD ptr [esp+4], classname&._&interface 111 | jmp member 112 | endm 113 | endm 114 | 115 | @MakeStubsEx macro classname, interface, memberlist:VARARG 116 | for member, 117 | member&_: 118 | sub DWORD ptr [esp+4], classname&._&interface 119 | % jmp member&@&classname 120 | endm 121 | endm 122 | 123 | ifdef _DEBUG 124 | externdef DEBUGPREFIX:LPSTR 125 | endif 126 | -------------------------------------------------------------------------------- /CVViewer.asm: -------------------------------------------------------------------------------- 1 | 2 | ;--- interface viewer dll for COMView 1.7.0+ and OLEView 3 | ;--- currently viewer for IShellFolder is implemented 4 | 5 | .386 6 | .model flat, stdcall 7 | option casemap:none 8 | option proc:private 9 | 10 | .nolist 11 | .nocref 12 | WIN32_LEAN_AND_MEAN equ 1 13 | INCL_OLE2 equ 1 14 | _WIN32_IE equ 500h 15 | include windows.inc 16 | include commctrl.inc 17 | include windowsx.inc 18 | 19 | include shellapi.inc 20 | include objidl.inc 21 | include olectl.inc 22 | include shlguid.inc 23 | include shlobj.inc 24 | include shlwapi.inc 25 | include shobjidl.inc 26 | 27 | include macros.inc 28 | .list 29 | .cref 30 | 31 | ?AGGREGATION = 0 ;no aggregation 32 | ?EVENTSUPPORT = 0 ;no event support 33 | 34 | include olecntrl.inc 35 | include debugout.inc 36 | include rsrc.inc 37 | 38 | INSIDE_CVViewer equ 1 39 | 40 | include CVViewer.inc 41 | include CShellBrowser.inc 42 | 43 | includelib kernel32.lib 44 | includelib advapi32.lib 45 | includelib user32.lib 46 | includelib gdi32.lib 47 | includelib oleaut32.lib 48 | includelib ole32.lib 49 | includelib uuid.lib 50 | includelib shell32.lib 51 | includelib comctl32.lib 52 | 53 | CVViewer struct 54 | 55 | BEGIN_COM_MAP CVViewer 56 | COM_INTERFACE_ENTRY IInterfaceViewer 57 | END_COM_MAP 58 | 59 | pUnknown LPUNKNOWN ? 60 | 61 | CVViewer ends 62 | 63 | ;-------------------------------------------------------------------------- 64 | 65 | .data 66 | 67 | externdef g_DllRefCount:DWORD 68 | 69 | .const 70 | 71 | CLSID_CVViewer GUID sCLSID_CVViewer 72 | 73 | 74 | ;--- the object table: defines coclasses installed by this module 75 | ;--- used by DllGetClassObject, DllRegisterServer + DllUnregisterServer 76 | 77 | BEGIN_OBJECT_MAP ObjectMap 78 | ObjectEntry {\ 79 | offset CLSID_CVViewer,\ 80 | offset 0, 0, 0,\ 81 | offset RegKeys_CVViewer,\ 82 | Create@CVViewer} 83 | END_OBJECT_MAP 84 | 85 | ;-------------------------------------------------------------------------- 86 | 87 | ;--- define standard COM functions 88 | ;--- one instance for all coclasses in this module 89 | 90 | DEFINE_COMHELPER 91 | DEFINE_CLASSFACTORY 92 | DEFINE_GETCLASSOBJECT offset ObjectMap 93 | DEFINE_REGISTERSERVER offset ObjectMap 94 | DEFINE_UNREGISTERSERVER offset ObjectMap 95 | DEFINE_CANUNLOADNOW 96 | DEFINE_DLLMAIN ;DllMain std (saves hInstance in g_hInstance) 97 | 98 | ;------------------------------------------------------------- 99 | ;--- coclass CVViewer 100 | ;------------------------------------------------------------- 101 | 102 | .const 103 | 104 | IID_IInterfaceViewer IID {0fc37e5bah, 4a8eh, 11ceh, {87h,0bh,08h,00h,36h,8dh,23h,02h}} 105 | 106 | Description textequ <"Interface Viewers for COMView and OLEView"> 107 | 108 | ;--- registry infos for registration/unregister CVViewer coclass 109 | 110 | RegKeys_CVViewer label REGSTRUCT 111 | REGSTRUCT <-1, 0, CStr("CLSID\%s")> 112 | REGSTRUCT <0, 0, CStr(Description)> 113 | REGSTRUCT 114 | REGSTRUCT 115 | REGSTRUCT <-1, 0, CStr("Interface\{000214E6-0000-0000-C000-000000000046}")> 116 | REGSTRUCT 117 | REGSTRUCT <-1, 0, CStr("Interface\{000214E4-0000-0000-C000-000000000046}")> 118 | REGSTRUCT 119 | REGSTRUCT <-1, 0, 0> 120 | 121 | ;--- vtable for interface IInterfaceViewer 122 | 123 | CInterfaceViewerVtbl label dword 124 | IUnknownVtbl {QueryInterface@CVViewer, AddRef@CVViewer, Release@CVViewer} 125 | dd View 126 | 127 | ;--- define interfaces known by IUnknown::QueryInterface 128 | 129 | DEFINE_KNOWN_INTERFACES CVViewer, IInterfaceViewer 130 | 131 | .code 132 | 133 | __this textequ 134 | _this textequ <[__this].CVViewer> 135 | 136 | MEMBER pUnknown 137 | 138 | ;--- standard code (won't be much here besides IUnknown methods) 139 | 140 | DEFINE_STD_COM_METHODS CVViewer 141 | 142 | ;--- constructor coclass CVViewer 143 | 144 | Create@CVViewer proc public uses esi __this pClass: ptr ObjectEntry, pUnkOuter:LPUNKNOWN 145 | 146 | invoke LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT,sizeof CVViewer 147 | .if (eax == NULL) 148 | ret 149 | .endif 150 | mov __this,eax 151 | 152 | mov m__IInterfaceViewer, OFFSET CInterfaceViewerVtbl 153 | 154 | STD_COM_CONSTRUCTOR CVViewer 155 | 156 | return __this 157 | 158 | Create@CVViewer endp 159 | 160 | ;--- destructor coclass CVViewer 161 | 162 | Destroy@CVViewer proc public uses __this this_:ptr CVViewer 163 | 164 | mov __this,this_ 165 | 166 | STD_COM_DESTRUCTOR CVViewer 167 | 168 | .if (m_pUnknown) 169 | invoke vf(m_pUnknown, IUnknown, Release) 170 | .endif 171 | 172 | invoke LocalFree, __this 173 | ret 174 | 175 | Destroy@CVViewer endp 176 | 177 | IDM_FIRST equ 1 178 | IDM_LAST equ 100 179 | 180 | DisplayMenu proc hWnd:HWND, pUnknown:LPUNKNOWN 181 | 182 | local hMenu:HMENU 183 | local pContextMenu:LPCONTEXTMENU 184 | local pShellExtInit:LPSHELLEXTINIT 185 | local pt:POINT 186 | 187 | invoke vf(pUnknown, IUnknown, QueryInterface), addr IID_IContextMenu, addr pContextMenu 188 | .if (eax == S_OK) 189 | if 0 190 | invoke vf(pUnknown, IUnknown, QueryInterface), addr IID_IShellExtInit, addr pShellExtInit 191 | .if (eax == S_OK) 192 | invoke vf(pShellExtInit, IShellExtInit, Initialize), xx,yy,zz 193 | invoke vf(pShellExtInit, IUnknown, Release) 194 | .endif 195 | endif 196 | invoke CreatePopupMenu 197 | mov hMenu, eax 198 | invoke vf(pContextMenu, IContextMenu, QueryContextMenu), hMenu, \ 199 | 0, IDM_FIRST, IDM_LAST, CMF_NORMAL 200 | invoke GetCursorPos, addr pt 201 | invoke TrackPopupMenu, hMenu, TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_RETURNCMD,\ 202 | pt.x, pt.y, 0, hWnd, NULL 203 | invoke DestroyMenu, hMenu 204 | invoke vf(pContextMenu, IUnknown, Release) 205 | .endif 206 | ret 207 | 208 | DisplayMenu endp 209 | 210 | ;---------------------------------------------------------------- 211 | 212 | ;--- IInterfaceViewer::View method 213 | 214 | View proc uses __this this_:ptr CVViewer, hwndParent:HWND, riid:REFIID, punk:LPUNKNOWN 215 | 216 | mov __this, this_ 217 | mov eax, punk 218 | mov m_pUnknown, eax 219 | invoke vf(eax, IUnknown, AddRef) 220 | 221 | invoke IsEqualGUID, riid, addr IID_IShellFolder 222 | .if (eax) 223 | invoke Create@CShellBrowser, punk 224 | .if (eax) 225 | invoke Show@CShellBrowser, eax, NULL;hwndParent 226 | .endif 227 | mov eax, S_OK 228 | ret 229 | .endif 230 | invoke IsEqualGUID, riid, addr IID_IContextMenu 231 | .if (eax) 232 | invoke DisplayMenu, hwndParent, punk 233 | mov eax, S_OK 234 | ret 235 | .endif 236 | return S_OK 237 | 238 | View endp 239 | 240 | end DllMain 241 | -------------------------------------------------------------------------------- /CVViewer.def: -------------------------------------------------------------------------------- 1 | 2 | LIBRARY "CVViewer.dll" 3 | 4 | EXPORTS 5 | DllCanUnloadNow PRIVATE 6 | DllGetClassObject PRIVATE 7 | DllRegisterServer PRIVATE 8 | DllUnregisterServer PRIVATE 9 | -------------------------------------------------------------------------------- /CVViewer.inc: -------------------------------------------------------------------------------- 1 | 2 | ;--- define interface IInterfaceViewer 3 | 4 | BEGIN_INTERFACE IInterfaceViewer, IUnknown 5 | STDMETHOD View ,hwndParent:HWND, riid:REFIID, punk:LPUNKNOWN 6 | END_INTERFACE 7 | 8 | LPINTERFACEVIEWER typedef ptr IInterfaceViewer 9 | 10 | 11 | sCLSID_CVViewer textequ <{ 500bc6a0h, 04268h, 011d7h, { 0b5h, 023h, 00h, 050h, 0fch, 04ah, 093h, 073h }}> 12 | 13 | ;--- define CVViewer coclass structure 14 | 15 | ifndef INSIDE_CVViewer 16 | CVViewer struct 17 | CVViewer ends 18 | endif 19 | 20 | ;--- externals + prototypes 21 | 22 | externdef IID_IInterfaceViewer: IID 23 | 24 | Create@CVViewer PROTO :ptr ObjectEntry, :LPUNKNOWN 25 | Destroy@CVViewer PROTO this_:ptr CVViewer 26 | 27 | -------------------------------------------------------------------------------- /CVViewer.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Explorer written in ASM. 10 | 11 | 12 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /CVViewer.txt: -------------------------------------------------------------------------------- 1 | 2 | This dll works only in conjunction with COMView 1.7.0+ or OLEView. It has to 3 | be registered with regsvr32 and will show interface IShellFolder in a bit 4 | more detail. 5 | 6 | An object which exposes interface IShellFolder is CLSID "desktop" for example. 7 | 8 | Source code is included, so you may add more interfaces to the viewer. 9 | That's very simple. Just do 10 | 11 | - add code for your interface viewer somewhere in CVViewer.asm 12 | - add a call of your new viewer code in proc "View" in CVViewer.asm 13 | - add some data for registry stuff. Search for "RegKeys_CVViewer" in 14 | CVViewer.asm and copy these 2 lines: 15 | REGSTRUCT <-1, 0, CStr("Interface\{000214E6-0000-0000-C000-000000000046}")> 16 | REGSTRUCT 17 | In the first line there is the IID of the interface your new viewer is 18 | for and this has to be modified accordingly. The second line should be 19 | left unchanged. 20 | 21 | Japheth 22 | 23 | 24 | -------------------------------------------------------------------------------- /DDEStuff.asm: -------------------------------------------------------------------------------- 1 | 2 | ;--- all the routines needed for this DDE communication 3 | ;--- that takes place if user clicks "open", "explore" ... 4 | ;--- in the right panel (view window) 5 | 6 | .386 7 | .model flat, stdcall 8 | option casemap:none 9 | option proc:private 10 | 11 | .nolist 12 | .nocref 13 | WIN32_LEAN_AND_MEAN equ 1 14 | INCL_OLE2 equ 1 15 | _WIN32_IE equ 500h 16 | include windows.inc 17 | include commctrl.inc 18 | include windowsx.inc 19 | 20 | include shellapi.inc 21 | include objidl.inc 22 | include olectl.inc 23 | include shlguid.inc 24 | include shlobj.inc 25 | include shlwapi.inc 26 | include shobjidl.inc 27 | 28 | include macros.inc 29 | 30 | ?AGGREGATION = 0 ;no aggregation 31 | ?EVENTSUPPORT = 0 ;no event support 32 | 33 | include olecntrl.inc 34 | include debugout.inc 35 | include rsrc.inc 36 | .list 37 | .cref 38 | 39 | INSIDE_CShellBrowser equ 1 40 | 41 | include CShellBrowser.inc 42 | 43 | NO_COMMAND equ 0 44 | VIEW_COMMAND equ 1 45 | EXPLORE_COMMAND equ 2 46 | FIND_COMMAND equ 3 47 | 48 | .data 49 | 50 | g_aApplication DWORD 0 51 | g_aTopic DWORD 0 52 | 53 | protoSHLockShared typedef proto :HANDLE, :DWORD 54 | protoSHUnlockShared typedef proto :LPVOID 55 | protoSHFreeShared typedef proto :LPVOID, :DWORD 56 | protoFree typedef proto :LPVOID 57 | 58 | LPFNSHLOCKSHARED typedef ptr protoSHLockShared 59 | LPFNSHUNLOCKSHARED typedef ptr protoSHUnlockShared 60 | LPFNSHFREESHARED typedef ptr protoSHFreeShared 61 | LPFNFREE typedef ptr protoFree 62 | 63 | g_lpfnSHLockShared LPFNSHLOCKSHARED NULL 64 | g_lpfnSHUnlockShared LPFNSHUNLOCKSHARED NULL 65 | g_lpfnSHFreeShared LPFNSHFREESHARED NULL 66 | g_lpfnFree LPFNFREE NULL 67 | 68 | .data? 69 | 70 | g_szFoldersApp BYTE MAX_PATH dup (?) 71 | g_szFoldersTopic BYTE MAX_PATH dup (?) 72 | g_szOpenFolder BYTE MAX_PATH dup (?) 73 | g_szExploreFolder BYTE MAX_PATH dup (?) 74 | g_szFindFolder BYTE MAX_PATH dup (?) 75 | 76 | .code 77 | 78 | __this textequ 79 | _this textequ <[__this].CShellBrowser> 80 | 81 | MEMBER hWndTV 82 | MEMBER pShellFolder, pMalloc 83 | MEMBER bDontRespond 84 | 85 | ;--- calc size of a pidl 86 | 87 | Pidl_GetSize proc uses esi pidl:LPITEMIDLIST 88 | 89 | mov esi, 0 90 | mov eax, pidl 91 | .if (eax) 92 | .while ([eax].SHITEMID.cb) 93 | movzx ecx,[eax].SHITEMID.cb 94 | add esi, ecx 95 | add eax, ecx 96 | .endw 97 | add esi, sizeof WORD 98 | .endif 99 | return esi 100 | 101 | Pidl_GetSize endp 102 | 103 | ;--- copy a pidl to a newly allocated one 104 | 105 | Pidl_Copy proc public uses esi edi pidlSource:LPITEMIDLIST 106 | 107 | mov esi, pidlSource 108 | .if (!esi) 109 | return NULL 110 | .endif 111 | 112 | invoke Pidl_GetSize, esi 113 | push eax 114 | invoke vf(m_pMalloc, IMalloc, Alloc), eax 115 | pop ecx 116 | .if (eax) 117 | mov edi, eax 118 | rep movsb 119 | .endif 120 | ret 121 | Pidl_Copy endp 122 | 123 | ;--- copy an item of a pidl 124 | 125 | Pidl_GetItem proc uses esi edi pidl:LPITEMIDLIST, item:DWORD 126 | 127 | mov eax, pidl 128 | .if (eax) 129 | mov esi, item 130 | .while (esi) 131 | .if ([eax].SHITEMID.cb) 132 | movzx edx,[eax].SHITEMID.cb 133 | add eax, edx 134 | .else 135 | return 0 136 | .endif 137 | dec esi 138 | .endw 139 | mov esi, eax 140 | movzx ecx,[esi].SHITEMID.cb 141 | .if (!ecx) 142 | return 0 143 | .endif 144 | add ecx, sizeof WORD 145 | push ecx 146 | invoke vf(m_pMalloc, IMalloc, Alloc), ecx 147 | pop ecx 148 | mov edi, eax 149 | rep movsb 150 | mov [edi-2], cx 151 | .endif 152 | ret 153 | Pidl_GetItem endp 154 | 155 | ;--- copy a pidl, but skip the last item 156 | 157 | Pidl_SkipLastItem proc public pidlSource:LPITEMIDLIST, pLastItem:ptr LPITEMIDLIST 158 | 159 | invoke Pidl_Copy, pidlSource 160 | .if (eax) 161 | push eax 162 | mov edx, eax 163 | .while ([eax].SHITEMID.cb) 164 | movzx ecx,[eax].SHITEMID.cb 165 | mov edx, eax 166 | add eax, ecx 167 | .endw 168 | .if (pLastItem) 169 | push edx 170 | invoke Pidl_Copy, edx 171 | mov ecx, pLastItem 172 | mov [ecx], eax 173 | pop edx 174 | .endif 175 | mov [edx].SHITEMID.cb, 0 176 | pop eax 177 | .endif 178 | ret 179 | 180 | Pidl_SkipLastItem endp 181 | 182 | ;--- get last item 183 | 184 | Pidl_GetLastItem proc public pidlSource:LPITEMIDLIST 185 | 186 | mov eax, pidlSource 187 | .if (eax) 188 | mov edx, eax 189 | .while ([eax].SHITEMID.cb) 190 | movzx ecx,[eax].SHITEMID.cb 191 | mov edx, eax 192 | add eax, ecx 193 | .endw 194 | invoke Pidl_Copy, edx 195 | .endif 196 | ret 197 | 198 | Pidl_GetLastItem endp 199 | 200 | ;--- get default value of a key in HKEY_CLASSES_ROOT 201 | 202 | GetValue proc pszKey:LPSTR, pszValue:LPSTR, dwSize:DWORD 203 | 204 | local hKey:HANDLE 205 | local dwType:DWORD 206 | 207 | invoke RegOpenKeyEx, HKEY_CLASSES_ROOT, pszKey, 208 | 0, KEY_READ, addr hKey 209 | .if (eax != ERROR_SUCCESS) 210 | return FALSE 211 | .endif 212 | invoke RegQueryValueEx, hKey, NULL, NULL, addr dwType, pszValue, addr dwSize 213 | push eax 214 | invoke RegCloseKey, hKey 215 | pop eax 216 | .if (eax == ERROR_SUCCESS) 217 | return TRUE 218 | .else 219 | return FALSE 220 | .endif 221 | GetValue endp 222 | 223 | ;--- get Command part of a DDE command string in registry 224 | 225 | GetCmd proc pszKey:LPSTR, pszValue:LPSTR, dwSize:DWORD 226 | 227 | local szTemp[MAX_PATH]:BYTE 228 | 229 | invoke GetValue, pszKey, addr szTemp, sizeof szTemp 230 | mov ecx, pszValue 231 | mov byte ptr [ecx],0 232 | .if (eax) 233 | lea edx, szTemp 234 | mov ah,00 235 | .while (byte ptr [edx]) 236 | mov al,[edx] 237 | .if (ah) 238 | .break .if (al == '(') 239 | mov [ecx],al 240 | inc ecx 241 | .elseif (al == '[') 242 | mov ah, 1 243 | .endif 244 | inc edx 245 | .endw 246 | mov byte ptr [ecx],0 247 | mov eax, 1 248 | .endif 249 | ret 250 | GetCmd endp 251 | 252 | ;--- read in some registry variables needed for DDE stuff 253 | 254 | GetDDEVariables proc public 255 | 256 | local hinstLib:HINSTANCE 257 | 258 | invoke GetValue, CStr("Folder\shell\explore\ddeexec\application"), 259 | addr g_szFoldersApp, sizeof g_szFoldersApp 260 | 261 | invoke GetValue, CStr("Folder\shell\explore\ddeexec\topic"), 262 | addr g_szFoldersTopic, sizeof g_szFoldersTopic 263 | 264 | invoke GetCmd, CStr("Folder\shell\open\ddeexec"), 265 | addr g_szOpenFolder, sizeof g_szOpenFolder 266 | 267 | invoke GetCmd, CStr("Folder\shell\explore\ddeexec"), 268 | addr g_szExploreFolder, sizeof g_szExploreFolder 269 | 270 | invoke GetCmd, CStr("Directory\shell\find\ddeexec"), 271 | addr g_szFindFolder, sizeof g_szFindFolder 272 | 273 | invoke GlobalAddAtom, addr g_szFoldersApp 274 | movzx eax, ax 275 | mov g_aApplication, eax 276 | invoke GlobalAddAtom, addr g_szFoldersTopic 277 | movzx eax, ax 278 | mov g_aTopic, eax 279 | 280 | invoke LoadLibrary, CStr("shell32.dll") 281 | mov hinstLib, eax 282 | .if (eax) 283 | invoke GetProcAddress, hinstLib, 521 284 | mov g_lpfnSHLockShared, eax 285 | invoke GetProcAddress, hinstLib, 522 286 | mov g_lpfnSHUnlockShared, eax 287 | invoke GetProcAddress, hinstLib, 523 288 | mov g_lpfnSHFreeShared, eax 289 | invoke FreeLibrary, hinstLib 290 | .endif 291 | invoke LoadLibrary, CStr("comctl32.dll") 292 | mov hinstLib, eax 293 | .if (eax) 294 | invoke GetProcAddress, hinstLib, 73 295 | mov g_lpfnFree, eax 296 | invoke FreeLibrary, hinstLib 297 | .endif 298 | 299 | DebugOut "GetDDEVariables, Application=%X, Topic=%X", g_aApplication, g_aTopic 300 | 301 | ret 302 | 303 | GetDDEVariables endp 304 | 305 | ;--- check if we can handle command in a DDE command string 306 | 307 | GetCommandTypeFromDDEString proc pszCommand:LPSTR 308 | 309 | local pszCopy:LPSTR 310 | local dwChars:DWORD 311 | local nCommand:DWORD 312 | local pszTemp:LPSTR 313 | 314 | mov nCommand, NO_COMMAND 315 | invoke lstrlen, pszCommand 316 | inc eax 317 | mov dwChars, eax 318 | invoke LocalAlloc, LPTR, dwChars 319 | mov pszCopy, eax 320 | .if (eax) 321 | invoke lstrcpy, pszCopy, pszCommand 322 | 323 | mov ecx, pszCopy 324 | .while (byte ptr [ecx]) 325 | mov al, [ecx] 326 | .if (al == '(') 327 | mov byte ptr [ecx],0 328 | .break 329 | .endif 330 | inc ecx 331 | .endw 332 | 333 | ;---- Find the beginning of the command portion by getting the first character 334 | ;---- after the first '['. 335 | 336 | mov ecx, pszCopy 337 | .while (byte ptr [ecx]) 338 | mov al, [ecx] 339 | .if (al == '[') 340 | inc ecx 341 | .break 342 | .endif 343 | inc ecx 344 | .endw 345 | mov pszTemp, ecx 346 | 347 | ;------------------------------- check the command 348 | 349 | invoke lstrcmpi, pszTemp, addr g_szOpenFolder 350 | .if (!eax) 351 | mov nCommand, VIEW_COMMAND 352 | .else 353 | invoke lstrcmpi, pszTemp, addr g_szExploreFolder 354 | .if (!eax) 355 | mov nCommand, EXPLORE_COMMAND 356 | .else 357 | invoke lstrcmpi, pszTemp, addr g_szFindFolder 358 | .if (!eax) 359 | mov nCommand, FIND_COMMAND 360 | .endif 361 | .endif 362 | .endif 363 | 364 | invoke LocalFree, pszCopy 365 | 366 | .endif 367 | 368 | return nCommand 369 | 370 | GetCommandTypeFromDDEString endp 371 | 372 | ;--- get a parameter from a DDE command string 373 | 374 | GetParameter proc pszCommand:LPSTR, uParm:DWORD, pszParameter:LPSTR, dwMax:DWORD 375 | 376 | mov ecx, pszParameter 377 | mov edx, pszCommand 378 | mov ah,0 379 | .while (byte ptr [edx]) 380 | mov al,[edx] 381 | .if (ah) 382 | .if (ah == 1) 383 | .break .if ((al == ')') || (al == ',')) 384 | .endif 385 | .if (al == '"') 386 | ; .if (byte ptr [edx+1] == '"') 387 | ; mov [ecx], al 388 | ; inc edx 389 | ; inc ecx 390 | ; .else 391 | xor ah,2 392 | ; .endif 393 | .else 394 | mov [ecx], al 395 | inc ecx 396 | .endif 397 | .elseif ((al == '(') || (al == ',')) 398 | dec uParm 399 | .if (uParm == 0) 400 | mov ah, 01 401 | .if (byte ptr [edx+1] == ' ') 402 | inc edx 403 | .endif 404 | .endif 405 | .endif 406 | inc edx 407 | .endw 408 | mov byte ptr [ecx],0 409 | ret 410 | GetParameter endp 411 | 412 | ;--- convert string to DWORD 413 | 414 | _StrToLong proc public pStr:LPSTR 415 | 416 | local bNegative:BOOL 417 | 418 | mov bNegative, FALSE 419 | xor edx, edx 420 | mov ecx, pStr 421 | mov al,[ecx] 422 | .if ((al == '-') || (al == '+')) 423 | inc ecx 424 | .if (al == '-') 425 | mov bNegative, TRUE 426 | .endif 427 | .endif 428 | .while (byte ptr [ecx]) 429 | mov al, [ecx] 430 | .break .if (!al) 431 | sub al, '0' 432 | movzx eax, al 433 | push ecx 434 | shl edx, 1 435 | mov ecx, edx 436 | shl edx, 2 437 | add edx, ecx 438 | pop ecx 439 | add edx, eax 440 | inc ecx 441 | .endw 442 | mov eax, edx 443 | .if (bNegative) 444 | neg eax 445 | .endif 446 | ret 447 | _StrToLong endp 448 | 449 | ;--- get path (1. parameter) from a DDE command string 450 | 451 | GetPathFromDDEString proc pszCommand:LPSTR , pszFolder:LPSTR , dwSize:DWORD 452 | 453 | invoke GetParameter, pszCommand, 1, pszFolder, dwSize 454 | ret 455 | 456 | GetPathFromDDEString endp 457 | 458 | 459 | ;--- get 2. parameter from DDE execute string 460 | 461 | 462 | GetPidlFromDDEString proc pszCommand:LPSTR 463 | 464 | local pidl:LPITEMIDLIST 465 | local pidlShared:LPITEMIDLIST 466 | local pidlGlobal:LPITEMIDLIST 467 | local pszHandle:LPSTR 468 | local pszProcessId:LPSTR 469 | local pszEnd:LPSTR 470 | local hShared:HANDLE 471 | local dwProcessId:DWORD 472 | local szTemp[256]:byte 473 | 474 | invoke GetParameter, pszCommand, 2, addr szTemp, sizeof szTemp 475 | lea eax, szTemp 476 | mov pszHandle, eax 477 | 478 | mov ecx, pszHandle 479 | .while (byte ptr [ecx]) 480 | mov al,[ecx] 481 | .break .if ((al == '-') || (al == '+') || ((al >= '0') && (al <= '9'))) 482 | inc ecx 483 | .endw 484 | mov pszHandle, ecx 485 | 486 | mov ecx, pszHandle 487 | .while (byte ptr [ecx]) 488 | mov al,[ecx] 489 | .if (al == ':') 490 | mov byte ptr [ecx],0 491 | inc ecx 492 | .break 493 | .endif 494 | inc ecx 495 | .endw 496 | mov pszProcessId, ecx 497 | .while (byte ptr [ecx]) 498 | mov al,[ecx] 499 | .if (al == ':') 500 | mov byte ptr [ecx],0 501 | inc ecx 502 | .break 503 | .endif 504 | inc ecx 505 | .endw 506 | mov ecx, pszProcessId 507 | .if (byte ptr [ecx] == 0) 508 | mov pszProcessId, NULL 509 | .endif 510 | 511 | .if (pszProcessId) 512 | invoke _StrToLong, pszHandle 513 | mov hShared, eax 514 | invoke _StrToLong, pszProcessId 515 | mov dwProcessId, eax 516 | 517 | .if (g_lpfnSHLockShared && g_lpfnSHUnlockShared && g_lpfnSHFreeShared) 518 | invoke g_lpfnSHLockShared, hShared, dwProcessId 519 | mov pidlShared, eax 520 | .if (eax) 521 | ;------------------------------------ make a local copy of the PIDL 522 | invoke Pidl_Copy, pidlShared 523 | mov pidl, eax 524 | invoke g_lpfnSHUnlockShared, pidlShared 525 | .endif 526 | invoke g_lpfnSHFreeShared, hShared, dwProcessId 527 | .endif 528 | .else 529 | 530 | invoke _StrToLong, pszHandle 531 | mov pidlGlobal, eax 532 | 533 | invoke Pidl_Copy, pidlGlobal 534 | mov pidl, eax 535 | 536 | ;--- The shared PIDL was allocated by the shell using a heap that the shell 537 | ;--- maintains. The only way to free this memory is to call the Free 538 | ;--- function in COMCTL32.DLL at ordinal 73. 539 | 540 | .if (g_lpfnFree) 541 | invoke g_lpfnFree, pidlGlobal 542 | .endif 543 | .endif 544 | 545 | return pidl 546 | 547 | GetPidlFromDDEString endp 548 | 549 | ;--- get 3. parameter from DDE execute string 550 | 551 | GetShowCmdFromDDEString proc pszCommand:LPSTR 552 | 553 | local nShow:DWORD 554 | local szTemp[256]:byte 555 | 556 | mov nShow, SW_SHOWDEFAULT 557 | invoke GetParameter, pszCommand, 3, addr szTemp, sizeof szTemp 558 | .if (szTemp) 559 | invoke _StrToLong, addr szTemp 560 | mov nShow, eax 561 | .endif 562 | 563 | return nShow 564 | 565 | GetShowCmdFromDDEString endp 566 | 567 | 568 | ;--- get command, path, pidl and cmdShow from DDE execute string 569 | 570 | 571 | ParseDDECommand proc pszCommand:LPSTR, pszFolder:LPSTR, dwSize:DWORD , ppidl:ptr LPITEMIDLIST,pnShow:ptr DWORD 572 | 573 | local uCommand:DWORD 574 | 575 | mov ecx, pszFolder 576 | mov byte ptr [ecx],0 577 | mov ecx,ppidl 578 | mov dword ptr [ecx], NULL 579 | mov ecx,pnShow 580 | mov dword ptr [ecx],0 581 | 582 | invoke GetCommandTypeFromDDEString, pszCommand 583 | mov uCommand, eax 584 | 585 | ;--- If the command was not recognized, then don't try to free any memory because 586 | ;--- we have no idea what is actually contained on the command line. 587 | 588 | .if (uCommand != NO_COMMAND) 589 | invoke GetPathFromDDEString, pszCommand, pszFolder, dwSize 590 | invoke GetPidlFromDDEString, pszCommand 591 | mov ecx, ppidl 592 | mov [ecx],eax 593 | invoke GetShowCmdFromDDEString, pszCommand 594 | mov ecx, pnShow 595 | mov [ecx],eax 596 | .endif 597 | 598 | return uCommand 599 | 600 | ParseDDECommand endp 601 | 602 | ;--- find a pidl in treeview 603 | ;--- dont expand treeview for that 604 | 605 | FindPidl proc public uses esi pidl:LPITEMIDLIST, bExpand:BOOL 606 | 607 | local pShellFolder:LPSHELLFOLDER 608 | local hItem:HANDLE 609 | local pidl2:LPITEMIDLIST 610 | local tvi:TV_ITEM 611 | 612 | invoke TreeView_GetRoot( m_hWndTV) 613 | mov tvi.hItem, eax 614 | xor esi, esi 615 | .while (eax) 616 | ;-------------------------------- get next item of the pidl 617 | invoke Pidl_GetItem, pidl, esi 618 | .if (!eax) 619 | mov eax, tvi.hItem 620 | .break 621 | .endif 622 | mov pidl2, eax 623 | invoke GetFolder, tvi.hItem 624 | mov pShellFolder, eax 625 | .if (!eax) 626 | invoke vf(m_pMalloc, IMalloc, Free), pidl2 627 | xor eax, eax 628 | .break 629 | .endif 630 | ;-------------------------------- make sure the item's children are inserted 631 | .if (bExpand) 632 | mov tvi.mask_, TVIF_STATE 633 | mov tvi.stateMask, TVIS_EXPANDEDONCE 634 | invoke TreeView_GetItem( m_hWndTV, addr tvi) 635 | .if (!(tvi.state & TVIS_EXPANDEDONCE)) 636 | invoke InsertChildItems, tvi.hItem 637 | .endif 638 | .endif 639 | ;-------------------------------- now scan all children's lParam (is a pidl) 640 | invoke TreeView_GetChild( m_hWndTV, tvi.hItem) 641 | .while (eax) 642 | mov tvi.hItem, eax 643 | mov tvi.mask_,TVIF_PARAM 644 | invoke TreeView_GetItem( m_hWndTV, addr tvi) 645 | .if (eax) 646 | invoke vf(pShellFolder, IShellFolder, CompareIDs), 0, pidl2, tvi.lParam 647 | .if (!eax) 648 | inc eax 649 | .break 650 | .endif 651 | .endif 652 | invoke TreeView_GetNextSibling( m_hWndTV, tvi.hItem) 653 | .endw 654 | push eax 655 | invoke vf(pShellFolder, IShellFolder, Release) 656 | invoke vf(m_pMalloc, IMalloc, Free), pidl2 657 | pop eax 658 | inc esi 659 | .endw 660 | ret 661 | FindPidl endp 662 | 663 | ;--- navigate to pidl in treeview 664 | ;--- returns TRUE if navigation succeeded 665 | 666 | 667 | NavigateToPidl proc public uses esi pidl:LPITEMIDLIST 668 | 669 | invoke FindPidl, pidl, TRUE 670 | .if (eax) 671 | invoke TreeView_SelectItem( m_hWndTV, eax) 672 | .endif 673 | ret 674 | 675 | NavigateToPidl endp 676 | 677 | 678 | ;--- handle WM_DDE_EXECUTE 679 | 680 | 681 | OnDDEExecute proc public pszCommand:LPSTR 682 | 683 | local lpTemp:LPSTR 684 | local szFolder[MAX_PATH]:BYTE 685 | local pidl:LPITEMIDLIST 686 | local nShow:DWORD 687 | local uCommand:DWORD 688 | local dwRC:DWORD 689 | local sei:SHELLEXECUTEINFO 690 | 691 | mov dwRC, FALSE 692 | DebugOut "%s", pszCommand 693 | 694 | .if (pszCommand) 695 | invoke ParseDDECommand, pszCommand, addr szFolder, MAX_PATH, addr pidl, addr nShow 696 | mov uCommand, eax 697 | 698 | .if (eax == EXPLORE_COMMAND) 699 | 700 | DebugOut "Explore" 701 | invoke NavigateToPidl, pidl 702 | mov dwRC, TRUE 703 | 704 | .elseif ((eax == VIEW_COMMAND) || (eax == FIND_COMMAND)) 705 | 706 | ;---------------------------------- we dont handle "view" and "find" 707 | ;---------------------------------- and hence must call ShellExecuteEx 708 | mov m_bDontRespond, TRUE 709 | 710 | invoke RtlZeroMemory, addr sei, sizeof SHELLEXECUTEINFO 711 | mov sei.cbSize, sizeof SHELLEXECUTEINFO 712 | 713 | movzx eax, word ptr szFolder 714 | .if (szFolder) 715 | mov sei.fMask, 0 716 | lea eax, szFolder 717 | mov sei.lpFile, eax 718 | .else 719 | mov sei.fMask, SEE_MASK_IDLIST 720 | mov eax, pidl 721 | mov sei.lpIDList, eax 722 | .endif 723 | 724 | mov sei.hwnd, NULL 725 | mov eax, nShow 726 | mov sei.nShow, eax 727 | .if (uCommand == VIEW_COMMAND) 728 | or sei.fMask, SEE_MASK_CLASSNAME 729 | mov sei.lpClass, CStr("folder") 730 | mov sei.lpVerb, CStr("open") 731 | .else 732 | mov sei.lpVerb, CStr("find") 733 | .endif 734 | 735 | invoke ShellExecuteEx, addr sei 736 | 737 | mov m_bDontRespond, FALSE 738 | 739 | mov dwRC, TRUE 740 | 741 | .endif 742 | 743 | .if (pidl) 744 | invoke vf(m_pMalloc, IMalloc, Free), pidl 745 | .endif 746 | 747 | .endif 748 | return dwRC 749 | 750 | OnDDEExecute endp 751 | 752 | end 753 | -------------------------------------------------------------------------------- /Debugout.inc: -------------------------------------------------------------------------------- 1 | 2 | ;--- define macros for debugging output 3 | ;--- DebugOutNoLF: printf format OutputDebugStringA 4 | ;--- DebugOut: printf format OutputDebugStringA 5 | ;--- @trace: output a string via OutputDebugStringA 6 | ;--- @tracew: output a wide string via OutputDebugStringW 7 | ;--- @tracedw: output a dword (use __dw2aDebug) 8 | 9 | ifndef CStr 10 | 11 | CStr macro y:req 12 | local sym,xxx 13 | xxx textequ @CurSeg 14 | .const 15 | ifidni ,<""> 16 | sym db 0 17 | else 18 | sym db y,0 19 | endif 20 | ifidni xxx,<_TEXT> 21 | .code 22 | else 23 | .data 24 | endif 25 | exitm 26 | endm 27 | 28 | endif 29 | 30 | ifndef wsprintf 31 | wsprintfAproto typedef PROTO C :DWORD,:DWORD,:VARARG 32 | externdef c _imp__wsprintfA:ptr wsprintfAproto 33 | wsprintf equ <_imp__wsprintfA> 34 | endif 35 | 36 | ifndef _DEBUG 37 | DEBUG = 0 38 | else 39 | DEBUG = 1 40 | endif 41 | 42 | DebugOutNoLF Macro x:req,y:VARARG 43 | local sym,ii 44 | if DEBUG 45 | .const 46 | sym db x,0 47 | .code 48 | pushad 49 | if 0;def DEBUGPREFIX 50 | invoke OutputDebugString,DEBUGPREFIX 51 | popad 52 | pushad 53 | endif 54 | ifnb 55 | sub esp,256 56 | ii = 0 57 | for parname, 58 | ii = ii + 4 59 | endm 60 | push esp 61 | invoke wsprintf,[esp+ii+4],addr sym,y 62 | pop esp 63 | invoke OutputDebugString,esp 64 | add esp,256 65 | else 66 | invoke OutputDebugString,addr sym 67 | endif 68 | popad 69 | endif 70 | endm 71 | 72 | DebugOut macro x:req,y:VARARG 73 | ifnb 74 | DebugOutNoLF ,y 75 | else 76 | DebugOutNoLF 77 | endif 78 | endm 79 | 80 | ;--- simple string output if wsprintf is not available 81 | 82 | @trace macro x 83 | local y, defConst 84 | ifdef _DEBUG 85 | defConst = 1 86 | for operand, 87 | if (OPATTR(operand)) and 10010y 88 | defConst = 0 89 | endif 90 | endm 91 | pushad 92 | if defConst 93 | .const 94 | y db x, 0 95 | .code 96 | invoke OutputDebugString, offset y 97 | else 98 | invoke OutputDebugString, x 99 | endif 100 | popad 101 | endif 102 | endm 103 | 104 | ;--- same for wide chars (OutputDebugStringW doesnt work for win9x) 105 | 106 | @tracew macro x 107 | ifdef _DEBUG 108 | OutputDebugStringW proto stdcall :ptr WORD 109 | defConst = 1 110 | for operand, 111 | if (OPATTR(operand)) and 10010y 112 | defConst = 0 113 | endif 114 | endm 115 | pushad 116 | if defConst 117 | .const 118 | y dw L(x) 119 | .code 120 | invoke OutputDebugStringW, offset y 121 | else 122 | invoke OutputDebugStringW, x 123 | endif 124 | popad 125 | endif 126 | endm 127 | 128 | ;--- simple number output if wsprintf is not available 129 | 130 | @tracedw macro x 131 | ifdef _DEBUG 132 | __dw2aDebug proto stdcall 133 | pushad 134 | mov eax, x 135 | call __dw2aDebug 136 | popad 137 | endif 138 | endm 139 | 140 | -------------------------------------------------------------------------------- /ExplASM.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | .386 4 | .model flat, stdcall 5 | option casemap:none 6 | option proc:private 7 | 8 | .nolist 9 | .nocref 10 | WIN32_LEAN_AND_MEAN equ 1 11 | INCL_OLE2 equ 1 12 | _WIN32_IE equ 500h 13 | include windows.inc 14 | include commctrl.inc 15 | include windowsx.inc 16 | 17 | include shellapi.inc 18 | include objidl.inc 19 | include olectl.inc 20 | include shlguid.inc 21 | include shlobj.inc 22 | include shlwapi.inc 23 | include shobjidl.inc 24 | 25 | include macros.inc 26 | 27 | include debugout.inc 28 | include rsrc.inc 29 | .list 30 | .cref 31 | 32 | include CShellBrowser.inc 33 | 34 | includelib kernel32.lib 35 | includelib advapi32.lib 36 | includelib user32.lib 37 | includelib gdi32.lib 38 | includelib oleaut32.lib 39 | includelib ole32.lib 40 | includelib shell32.lib 41 | includelib comctl32.lib 42 | includelib uuid.lib 43 | 44 | ;-------------------------------------------------------------------------- 45 | 46 | ?MULTIWINDOW equ 0 ;explorer will create just 1 window 47 | 48 | .data 49 | 50 | externdef g_hInstance:HINSTANCE 51 | externdef g_DllRefCount:DWORD 52 | 53 | g_DllRefCount DWORD 0 54 | g_hInstance HINSTANCE 0 55 | g_hWndDlg HWND 0 56 | g_oldwndproc DWORD 0 57 | g_saverect RECT <> 58 | g_argc DWORD 0 59 | g_argv LPSTR NULL 60 | 61 | .const 62 | 63 | szOptions db "Options",0 64 | szWindowPos db "WndDim",0 65 | szLastFolder db "Folder",0 66 | 67 | .code 68 | 69 | IsInterfaceSupported proc public uses ebx esi edi pReqIF:ptr IID, pIFTab:ptr ptr IID, dwEntries:dword, pThis:ptr, ppReturn:ptr LPUNKNOWN 70 | 71 | mov ecx,dwEntries 72 | mov esi,pIFTab 73 | mov ebx,0 74 | .while (ecx) 75 | lodsd 76 | mov edi,eax 77 | lodsd 78 | mov edx,eax 79 | mov eax,esi 80 | mov esi,pReqIF 81 | push ecx 82 | mov ecx,4 83 | repz cmpsd 84 | pop ecx 85 | .if (ZERO?) 86 | mov ebx,edx 87 | add ebx,pThis 88 | .break 89 | .endif 90 | mov esi,eax 91 | dec ecx 92 | .endw 93 | mov ecx,ppReturn 94 | mov [ecx],ebx 95 | 96 | .if (ebx) 97 | invoke vf(ebx,IUnknown,AddRef) 98 | mov eax,S_OK 99 | .else 100 | mov eax,E_NOINTERFACE 101 | .endif 102 | ret 103 | 104 | IsInterfaceSupported endp 105 | 106 | 107 | ;--- setup arguments: will set g_argc and g_argv global vars 108 | 109 | 110 | SetArguments proc public uses esi edi ebx 111 | 112 | local argc:dword 113 | 114 | invoke GetCommandLine 115 | and eax,eax 116 | jz exit 117 | mov esi,eax 118 | xor edi,edi ;EDI will count the number of arguments 119 | xor edx,edx ;EDX will count the number of bytes 120 | ;needed for the arguments 121 | ;(not including the null terminators) 122 | nextarg: ;<---- get next argument 123 | .while (1) 124 | lodsb 125 | .break .if ((al != ' ') && (al != 9)) ;skip spaces and tabs 126 | .endw 127 | or al,al 128 | je donescanX ;done commandline scan 129 | inc edi ;Another argument 130 | xor ebx,ebx ;EBX will count characters in argument 131 | dec esi ;back up to reload character 132 | push esi ;save start of argument 133 | mov cl,00 134 | .while (1) 135 | lodsb 136 | .break .if (!al) 137 | .if (!cl) 138 | .if ((al == ' ') || (al == 9)) ;white space term. argument 139 | push ebx ;save argument length 140 | jmp nextarg 141 | .endif 142 | .if ((!ebx) && al == '"') ;starts argument with "? 143 | or cl,1 144 | ;handle argument beginning with doublequote 145 | pop eax ;throw away old start 146 | push esi ;and set new start 147 | .continue 148 | .endif 149 | .elseif (al == '"') 150 | and cl,0FEh 151 | .continue 152 | .endif 153 | 154 | .if ((al == '\') && (byte ptr [esi] == '"')) 155 | inc esi 156 | .endif 157 | inc ebx 158 | inc edx ;one more space 159 | .endw 160 | push ebx ; save length of last argument 161 | donescanX: 162 | mov argc,edi ; Store number of arguments 163 | add edx,edi ; add terminator bytes 164 | inc edi ; add one for NULL pointer 165 | shl edi,2 ; every pointer takes 4 bytes 166 | add edx,edi ; add that space to space for strings 167 | 168 | invoke LocalAlloc, LMEM_FIXED, edx 169 | and eax,eax 170 | jz exit 171 | 172 | mov g_argv,eax 173 | add edi,eax ; edi -> behind vector table (strings) 174 | mov ecx,argc 175 | mov g_argc,ecx 176 | lea ebx,[edi-4] 177 | mov dword ptr [ebx],0 ;mark end of argv 178 | sub ebx,4 179 | mov edx,ecx 180 | .while (edx) 181 | pop ecx ;get length 182 | pop esi ;get address 183 | mov [ebx],edi 184 | sub ebx,4 185 | .while (ecx) 186 | lodsb 187 | .if (al == '\') 188 | .continue .if (byte ptr [esi] == '"') 189 | .endif 190 | stosb 191 | dec ecx 192 | .endw 193 | xor al,al 194 | stosb 195 | dec edx 196 | .endw 197 | exit: 198 | ret 199 | align 4 200 | 201 | SetArguments endp 202 | 203 | LoadParms proc uses esi ebx edi 204 | 205 | local dwNums:DWORD 206 | local pNum:ptr DWORD 207 | local szPath[MAX_PATH]:byte 208 | local szText[128]:byte 209 | 210 | invoke GetModuleFileName, NULL, addr szPath, sizeof szPath 211 | lea ecx, szPath 212 | mov dword ptr [ecx+eax-3],"ini" 213 | 214 | invoke GetPrivateProfileString, addr szOptions, addr szWindowPos, 215 | CStr(""), addr szText, sizeof szText, addr szPath 216 | 217 | .if (eax) 218 | lea ebx, szText 219 | lea edx, g_rect.right 220 | mov pNum, edx 221 | mov esi, ebx 222 | mov dwNums, 2 223 | .while (dwNums) 224 | mov al, [ebx] 225 | .if ((al == ',') || (al == 0)) 226 | mov byte ptr [ebx],0 227 | push eax 228 | xor eax, eax 229 | .if (esi != ebx) 230 | invoke StrToLong, esi 231 | .endif 232 | mov edx, pNum 233 | mov [edx],eax 234 | add edx, 4 235 | mov pNum, edx 236 | dec dwNums 237 | lea esi, [ebx+1] 238 | pop eax 239 | .break .if (al == 0) 240 | .endif 241 | inc ebx 242 | .endw 243 | .endif 244 | lea edi, g_saverect.right 245 | lea esi, g_rect.right 246 | movsd 247 | movsd 248 | 249 | invoke GetPrivateProfileString, addr szOptions, addr szLastFolder, 250 | CStr(""), addr g_szPath, MAX_PATH, addr szPath 251 | 252 | ret 253 | 254 | LoadParms endp 255 | 256 | SaveParms proc uses esi edi 257 | 258 | local szPath[MAX_PATH]:byte 259 | local szText[128]:byte 260 | 261 | invoke GetModuleFileName, NULL, addr szPath, sizeof szPath 262 | lea ecx, szPath 263 | mov dword ptr [ecx+eax-3],"ini" 264 | 265 | lea esi, g_rect.right 266 | lea edi, g_saverect.right 267 | mov ecx, 2 268 | repe cmpsd 269 | .if (ZERO?) 270 | jmp next 271 | .endif 272 | invoke wsprintf, addr szText, CStr("%u,%u"), g_rect.right, g_rect.bottom 273 | invoke WritePrivateProfileString, addr szOptions, addr szWindowPos, 274 | addr szText, addr szPath 275 | next: 276 | invoke WritePrivateProfileString, addr szOptions, addr szLastFolder, 277 | addr g_szPath, addr szPath 278 | exit: 279 | ret 280 | SaveParms endp 281 | 282 | if ?MULTIWINDOW 283 | EnumThreadWindowsCB proc hWnd:HWND, lParam:LPARAM 284 | 285 | invoke GetWindowLong, hWnd, GWL_WNDPROC 286 | .if (eax == mywndproc) 287 | mov ecx, lParam 288 | inc dword ptr [ecx] 289 | .endif 290 | return TRUE 291 | 292 | EnumThreadWindowsCB endp 293 | 294 | IsLastWindow proc 295 | 296 | local dwNumWindows:DWORD 297 | 298 | mov dwNumWindows, 0 299 | invoke GetCurrentThreadId 300 | lea ecx, dwNumWindows 301 | invoke EnumThreadWindows, eax, offset EnumThreadWindowsCB, ecx 302 | .if (dwNumWindows <= 1) 303 | invoke PostQuitMessage, 0 304 | .endif 305 | ret 306 | IsLastWindow endp 307 | endif 308 | 309 | mywndproc proc hWnd:HWND, message:DWORD, wParam:WPARAM, lParam:LPARAM 310 | 311 | if 0 312 | .if (message == WM_INITDIALOG) 313 | invoke SetWindowText, hWnd, CStr("ExplorerASM") 314 | if ?MULTIWINDOW 315 | .elseif (message == WM_ACTIVATE) 316 | movzx eax,word ptr wParam 317 | .if (eax == WA_INACTIVE) 318 | mov g_hWndDlg, NULL 319 | .else 320 | mov eax, hWnd 321 | mov g_hWndDlg, eax 322 | .endif 323 | endif 324 | .endif 325 | endif 326 | 327 | .if (message == WM_DESTROY) 328 | if ?MULTIWINDOW 329 | invoke IsLastWindow 330 | else 331 | invoke PostQuitMessage, 0 332 | endif 333 | .endif 334 | invoke CallWindowProc, g_oldwndproc, hWnd, message, wParam, lParam 335 | ret 336 | mywndproc endp 337 | 338 | 339 | WinMain proc hInstance:HINSTANCE,hPrevInstance:HINSTANCE,lpszCmdLine:LPSTR,iCmdShow:dword 340 | 341 | local hWndMain:HWND 342 | local msg:MSG 343 | local pShellFolder:LPSHELLFOLDER 344 | local pShellBrowser:LPSHELLBROWSER 345 | local iccx:INITCOMMONCONTROLSEX 346 | 347 | if 1 348 | mov iccx.dwSize,sizeof INITCOMMONCONTROLSEX 349 | mov iccx.dwICC, ICC_WIN95_CLASSES 350 | invoke InitCommonControlsEx,addr iccx 351 | else 352 | invoke InitCommonControls 353 | endif 354 | invoke LoadLibrary, CStr("SHDOC401") ;someone needs that 355 | 356 | ;; invoke CoInitialize, NULL 357 | invoke OleInitialize, NULL 358 | 359 | invoke LoadParms 360 | 361 | invoke SetArguments 362 | mov ecx, g_argc 363 | mov edx, g_argv 364 | .while (ecx) 365 | pushad 366 | mov ecx, [edx] 367 | mov al,[ecx] 368 | .if ((al == '-') || (al == '/')) 369 | ;--------------------------- handle options 370 | .else 371 | .if (edx != g_argv) 372 | invoke lstrcpy, addr g_szPath, ecx 373 | .endif 374 | .endif 375 | popad 376 | add edx, 4 377 | dec ecx 378 | .endw 379 | 380 | mov g_bCreateView, TRUE 381 | 382 | invoke SHGetDesktopFolder, addr pShellFolder 383 | .if (eax == S_OK) 384 | invoke Create@CShellBrowser, pShellFolder 385 | .if (eax) 386 | mov pShellBrowser, eax 387 | invoke Show@CShellBrowser, eax, NULL 388 | .if (eax) 389 | mov hWndMain, eax 390 | mov g_hWndDlg, eax 391 | invoke SetWindowLong, hWndMain, GWL_WNDPROC, offset mywndproc 392 | mov g_oldwndproc, eax 393 | if ?MULTIWINDOW 394 | invoke SetClassLong, hWndMain, GCL_WNDPROC, offset mywndproc 395 | endif 396 | .else 397 | invoke MessageBox, 0, CStr("couldn't create main window"), 0, MB_OK 398 | .endif 399 | .else 400 | invoke MessageBox, 0, CStr("couldn't create CShellBrowser object"), 0, MB_OK 401 | .endif 402 | invoke vf(pShellFolder, IShellFolder, Release) 403 | .endif 404 | 405 | 406 | .while (1) ;main message loop 407 | invoke GetMessage, addr msg, NULL, 0, 0 408 | .break .if (eax == 0) 409 | .if ((msg.message == WM_KEYDOWN) || (msg.message == WM_SYSKEYDOWN)) 410 | invoke TranslateAccelerator@CShellBrowser, pShellBrowser, addr msg 411 | .continue .if (eax == S_OK) 412 | .endif 413 | invoke IsDialogMessage, g_hWndDlg, addr msg 414 | .continue .if (eax) 415 | invoke TranslateMessage, addr msg 416 | invoke DispatchMessage, addr msg 417 | .endw 418 | 419 | invoke SaveParms 420 | exit: 421 | ;; invoke CoUninitialize 422 | invoke OleUninitialize 423 | ret 424 | 425 | WinMain endp 426 | 427 | start: 428 | invoke GetModuleHandle,0 429 | mov g_hInstance, eax 430 | invoke WinMain,eax,0,0,0 431 | if 0 432 | invoke GetCurrentProcess 433 | invoke TerminateProcess, eax, 0 434 | endif 435 | invoke ExitProcess,eax 436 | 437 | end start 438 | -------------------------------------------------------------------------------- /ExplASM.txt: -------------------------------------------------------------------------------- 1 | 2 | ExplorerASM 3 | 4 | ExplorerASM is an explorer application written in assembly. 5 | 6 | From a technical point of view this app consists of: 7 | - a simple window with a treeview client. The treeview is filled 8 | from IShellFolder clients, the root of which is received from 9 | function SHGetDesktopFolder. 10 | - an IShellBrowser object to let the views created communicate with 11 | the application. 12 | 13 | The original purpose of this app was to provide a test platform for 14 | self-written shell namespace extensions. But of course if you want 15 | you may use it as explorer "substitute" (possibly after some enhancements). 16 | But be cautious: some features are (still) missing and some 17 | features of original explorer are undocumented. In no case rename ExplASM.exe 18 | to explorer.exe! 19 | 20 | 21 | Restrictions 22 | 23 | Option "Include Browsable Items" doesn't work in windows 98. If activated, 24 | selecting a file in treeview will terminate the application. 25 | 26 | 27 | Building Binary 28 | 29 | The assembly source is written in Masm syntax, it has been tested with 30 | JWasm and Masm. The WinInc include files are used, which may be found at 31 | http://github.com/Baron-von-Riedesel/WinInc. 32 | A Makefile (NMAKE) is supplied as well to build the binaries. Please note 33 | that besides ExplASM.EXE there will a dll be build. This is an "interface" 34 | viewer for interface IShellFolder, to be used by COMView or OLEView only. 35 | 36 | 37 | History 38 | 39 | version 0.9.0: the first version uploaded. 40 | version 1.0.0: DDE communication added, thus allowing to handle "explore" menu command 41 | version 1.1.0: icons are displayed in left panel. 42 | version 1.1.1: folders may be in-place-renamed in left panel 43 | version 1.1.2: support for windows XP (visual styles, 32-bit anti-aliased icons) 44 | version 1.1.3: refresh function implemented, IDropTargetHelper used if available 45 | version 1.1.4: drag&drop shortcut menu supported, creating shortcuts implemented, 46 | last folder saved in private profile 47 | version 1.1.5: browsable items may be included in treeview list (is default for 48 | windows XP) 49 | version 1.1.6: changes in the namespace (new, deleted or renamed folders) now 50 | automatically reflected in the left panel (function SHChangeNotifyRegister 51 | is used). Folder name as commandline argument accepted. 52 | 02/2005 v1.1.7: changed to h2incx generated include files, MASM32 no longer 53 | used. 54 | 02/2005 v1.1.8: message cracker macro calls adjusted to windowsx.inc of 55 | wininc.zip. 56 | 08/2007 v1.1.9: source and makefiles adjusted so that no files from the 57 | MS platform SDK are needed to build the binary. 58 | 06/2008 v1.2.0: Switched to JWasm to be used as default assembler. 59 | 60 | 61 | License 62 | 63 | ExplorerASM is public domain. 64 | 65 | 66 | Japheth (http://github.com/Baron-von-Riedesel) 67 | 68 | -------------------------------------------------------------------------------- /MAKE.BAT: -------------------------------------------------------------------------------- 1 | @echo off 2 | rem adjust include/lib paths if necessary 3 | jwasm -c -coff -nologo -I\wininc\Include -Fo Release\ -Fl=Release\ *.asm 4 | rc -i \wininc\Include -fo Release\rsrc.res rsrc.rc 5 | set LIB=\wininc\Lib 6 | cd Release 7 | link /NOLOGO /SUBSYSTEM:WINDOWS /OUT:CVViewer.dll CVViewer CShellBrowser DDEStuff CServiceProvider COleCommandTarget CDropTarget rsrc.res /DEF:..\CVViewer.def /DLL 8 | link /NOLOGO /SUBSYSTEM:WINDOWS /OUT:ExplASM.exe ExplASM CShellBrowser DDEStuff CServiceProvider COleCommandTarget CDropTarget COleInPlaceFrame.obj rsrc.res /OPT:NOWIN98 9 | cd .. 10 | -------------------------------------------------------------------------------- /MODULES.INC: -------------------------------------------------------------------------------- 1 | .\CDropTarget.ASM \ 2 | .\COleCommandTarget.ASM \ 3 | .\COleInPlaceFrame.ASM \ 4 | .\CServiceProvider.ASM \ 5 | .\CShellBrowser.ASM \ 6 | .\DDEStuff.ASM 7 | -------------------------------------------------------------------------------- /Macros.inc: -------------------------------------------------------------------------------- 1 | 2 | ;--- macros: 3 | ;--- CStr() 4 | ;--- L() 5 | ;--- CStrW() 6 | ;--- smalloc, sfree, sreload 7 | ;--- return 8 | ;--- @mov 9 | ;--- MEMBER 10 | 11 | ifndef CStr 12 | 13 | ;--- CStr() define a string in .CONST 14 | ;--- or in .CONST$2 if .CONST is the current section 15 | 16 | CStr macro text:VARARG 17 | local sym 18 | ifidni @CurSeg, 19 | CONST$2 segment dword flat public 'CONST' 20 | else 21 | CONST segment dword flat public 'CONST' 22 | endif 23 | ifidni ,<""> 24 | sym db 0 25 | else 26 | sym db text,0 27 | endif 28 | @CurSeg ends 29 | exitm 30 | endm 31 | 32 | endif 33 | 34 | ifndef L 35 | 36 | ;---- L() defines a wide string 37 | ;---- usage: StringName dw L(stringvalue) 38 | if 0 39 | L macro y:req 40 | local x 41 | x textequ <> 42 | forc chr$, 43 | x CatStr x,<'&chr$'>,<,> 44 | endm 45 | x CatStr x,<0> 46 | exitm 47 | endm 48 | 49 | endif ;L() 50 | else 51 | L macro parms:VARARG 52 | local wstr,i,c,tstr 53 | wstr textequ <> 54 | i = 0 55 | for parm, 56 | c SubStr ,1,1 57 | ifidn c,<"> 58 | tstr SubStr ,2,@SizeStr(parm)-2 59 | % forc chr$, 60 | if i 61 | wstr CatStr wstr,<,> 62 | endif 63 | wstr CatStr wstr,<'&chr$'> 64 | i = i + 1 65 | endm 66 | else 67 | if i 68 | wstr CatStr wstr,<,> 69 | endif 70 | wstr CatStr wstr, 71 | endif 72 | endm 73 | exitm 74 | endm 75 | endif 76 | 77 | ;--- CStrW defines a wide string in .CONST 78 | ;--- returns a pointer to that string 79 | 80 | CStrW macro text:req 81 | local sym 82 | 83 | ifidni @CurSeg, 84 | CONST$2 segment dword flat public 'CONST' 85 | else 86 | CONST segment dword flat public 'CONST' 87 | endif 88 | align 2 89 | sym dw text,0 90 | 91 | @CurSeg ends 92 | exitm 93 | endm 94 | 95 | 96 | ifndef smalloc 97 | 98 | ;--- the smalloc + sfree macros are used to alloc space 99 | ;--- on the stack. 100 | ;--- usage: "smalloc register,numBytes" and "sfree" 101 | 102 | smalloc macro reg:req,bytes:req ;alloc space on the stack (local only) 103 | local ?bytes 104 | ?bytes = (bytes + 3) and 0fffffffch 105 | sub esp,?bytes 106 | mov reg,esp 107 | push ?bytes+4 108 | endm 109 | sreload macro reg:req,index ;reload address of stack items 110 | ifnb 111 | mov reg,esp 112 | repeat index 113 | add reg,[reg] 114 | endm 115 | add reg,4 116 | else 117 | lea reg,[esp+4] 118 | endif 119 | endm 120 | sfree macro 121 | add esp,[esp] 122 | endm 123 | 124 | endif ;smalloc 125 | 126 | 127 | ;--- return: return a value in eax 128 | 129 | ifndef return 130 | 131 | return macro x 132 | ifnb 133 | if (OPATTR x) and 4 ;;constant? 134 | if x 135 | mov eax,x 136 | else 137 | xor eax,eax 138 | endif 139 | else 140 | mov eax,x 141 | endif 142 | endif 143 | ret 144 | endm 145 | 146 | endif ;return 147 | 148 | ;--- simple macro for a 3 byte move, used i.e.: @mov ecx, 3 149 | 150 | @mov macro x, y 151 | push y 152 | pop x 153 | endm 154 | 155 | ifndef MEMBER 156 | 157 | ;--- MEMBER: create member names 158 | ;--- requires at least one other definition in program itself. 159 | ;--- assume ebx is used to access this_. so define in program 160 | ;--- "_this textequ <[ebx].CClassName>" 161 | ;--- "MEMBER VarName" 162 | ;--- so access to member 163 | ;--- "[ebx].CClassName.VarName" simplifies to "m_VarName" 164 | 165 | MEMBER macro names:VARARG 166 | local x 167 | for y, 168 | x CatStr <_this.>, 169 | m_&y textequ x 170 | endm 171 | endm 172 | 173 | endif ;MEMBER 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | # nmake Makefile to create ExplASM.exe and CVViewer.dll 3 | # tools used: 4 | # - JWasm 5 | # - MS Link 6 | # - MS RC 7 | # 8 | # adjust the WinInc paths for includes/libs before running it 9 | 10 | !ifndef DEBUG 11 | DEBUG = 0 12 | !endif 13 | 14 | !ifndef MASM 15 | MASM=0 16 | !endif 17 | 18 | WININC=\wininc 19 | 20 | !if $(DEBUG) 21 | AOPTD=-Zi -D_DEBUG 22 | LOPTD=/DEBUG 23 | !endif 24 | 25 | SRCMODS = \ 26 | !include modules.inc 27 | OBJNAMES = $(SRCMODS:.ASM=.OBJ) 28 | !if $(DEBUG) 29 | OBJMODS = $(OBJNAMES:.\=DEBUG\) 30 | !else 31 | OBJMODS = $(OBJNAMES:.\=RELEASE\) 32 | !endif 33 | 34 | NAMEDLL = CVViewer 35 | NAMEEXE = ExplASM 36 | 37 | AOPT=-nologo -c -coff -Sg $(AOPTD) -Fl$* -Sg -Fo$* -I$(WININC)\Include 38 | !if $(MASM) 39 | ASM = ml.exe $(AOPT) 40 | !else 41 | ASM = jwasm.exe $(AOPT) 42 | !endif 43 | LINK = link.exe 44 | RC = rc.exe 45 | 46 | DEPS = CVViewer.inc CShellBrowser.inc 47 | 48 | !if $(DEBUG) 49 | OUTDIR=DEBUG 50 | !else 51 | OUTDIR=RELEASE 52 | !endif 53 | 54 | .SUFFIXES: .asm .obj 55 | 56 | .asm{$(OUTDIR)}.obj: 57 | @$(ASM) $< 58 | 59 | LIBS=kernel32.lib advapi32.lib user32.lib gdi32.lib uuid.lib ole32.lib oleaut32.lib shell32.lib comctl32.lib 60 | 61 | ALL: $(OUTDIR) $(OUTDIR)\$(NAMEDLL).dll $(OUTDIR)\$(NAMEEXE).exe 62 | 63 | $(OUTDIR): 64 | @mkdir $(OUTDIR) 65 | 66 | $(OUTDIR)\$(NAMEDLL).dll: $*.obj $(OUTDIR)\rsrc.res $(OBJMODS) Makefile 67 | @$(LINK) @<< /NOLOGO $(LOPTD) 68 | $*.obj $(OBJMODS) $(OUTDIR)\rsrc.res 69 | /OUT:$*.dll /DLL /MAP:$*.map /DEF:$(NAMEDLL).def /SUBSYSTEM:windows 70 | /LIBPATH:$(WININC)\Lib $(LIBS) 71 | << 72 | 73 | $(OUTDIR)\$(NAMEEXE).exe: $*.obj $(OUTDIR)\rsrc.res $(OBJMODS) Makefile 74 | @$(LINK) @<< /NOLOGO $(LOPTD) 75 | $*.obj $(OBJMODS) $(OUTDIR)\rsrc.res 76 | /OUT:$*.exe /MAP:$*.map /SUBSYSTEM:windows /OPT:NOWIN98 77 | /LIBPATH:$(WININC)\Lib 78 | << 79 | 80 | $(OUTDIR)\rsrc.res: rsrc.rc 81 | @$(RC) -i$(WININC)\Include -fo$*.res rsrc.rc 82 | 83 | $(OBJMODS): $(DEBS) 84 | 85 | clean: 86 | erase $(OUTDIR)\*.obj 87 | erase $(OUTDIR)\*.map 88 | erase $(OUTDIR)\*.exe 89 | erase $(OUTDIR)\*.lst 90 | erase $(OUTDIR)\*.res 91 | -------------------------------------------------------------------------------- /RSRC.H: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by rsrc.rc 4 | // 5 | #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 6 | #define RT_MANIFEST 24 7 | #define IDD_DIALOG1 101 8 | #define IDR_MENU1 102 9 | #define IDD_DIALOG2 104 10 | #define IDC_CURSOR1 105 11 | #define IDI_ICON1 106 12 | #define IDR_ACCELERATOR1 107 13 | #define IDI_ICON2 115 14 | #define CONTROL_PANEL_RESOURCE_ID 123 15 | #define IDC_LIST1 1000 16 | #define IDC_STATUSBAR 1001 17 | #define IDC_EDIT1 1002 18 | #define IDC_TREE1 1003 19 | #define IDM_CREATEVIEWOBJECT 40960 20 | #define IDM_BINDTOOBJECT 40961 21 | #define IDM_GETUIOBJECTOF 40962 22 | #define IDM_OPENNEWWND 40963 23 | #define IDM_STATUSLINE 40964 24 | #define IDM_ABOUT 40965 25 | #define IDM_COMPMENUS 40966 26 | #define IDM_REFRESH 40967 27 | #define IDM_EXIT 40968 28 | #define IDM_SORT 40969 29 | #define IDM_DROPTARGET 40970 30 | #define IDM_TRACKSELECT 40971 31 | #define IDM_DDERESPOND 40972 32 | #define IDM_BROWSEFILES 40973 33 | #define IDM_DELETE 40974 34 | #define IDM_EXPAND 40975 35 | 36 | // Next default values for new objects 37 | // 38 | #ifdef APSTUDIO_INVOKED 39 | #ifndef APSTUDIO_READONLY_SYMBOLS 40 | #define _APS_NEXT_RESOURCE_VALUE 116 41 | #define _APS_NEXT_COMMAND_VALUE 40976 42 | #define _APS_NEXT_CONTROL_VALUE 1004 43 | #define _APS_NEXT_SYMED_VALUE 101 44 | #endif 45 | #endif 46 | -------------------------------------------------------------------------------- /RSRC.RC: -------------------------------------------------------------------------------- 1 | 2 | #include "rsrc.h" 3 | #include 4 | 5 | IDC_CURSOR1 CURSOR DISCARDABLE "Res\\Splith.cur" 6 | 7 | IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE 8 | BEGIN 9 | VK_DELETE, IDM_DELETE, VIRTKEY, NOINVERT 10 | VK_F5, IDM_REFRESH, VIRTKEY, NOINVERT 11 | END 12 | 13 | // Icon with lowest ID value placed first to ensure application icon 14 | // remains consistent on all systems. 15 | IDI_ICON1 ICON DISCARDABLE "Res\\explorer.ico" 16 | 17 | IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 166, 85 18 | STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU 19 | CAPTION "About CVViewer" 20 | FONT 8, "MS Sans Serif" 21 | BEGIN 22 | PUSHBUTTON "Close",IDCANCEL,58,64,50,14 23 | EDITTEXT IDC_EDIT1,7,7,152,51,ES_CENTER | ES_MULTILINE | 24 | ES_AUTOHSCROLL | ES_READONLY 25 | END 26 | 27 | 28 | IDR_MENU1 MENU DISCARDABLE 29 | BEGIN 30 | POPUP "&File" 31 | BEGIN 32 | MENUITEM "E&xit", IDM_EXIT 33 | END 34 | POPUP "&View" 35 | BEGIN 36 | MENUITEM "&Statusline", IDM_STATUSLINE 37 | MENUITEM "&Refresh", IDM_REFRESH 38 | END 39 | POPUP "&Tools" 40 | BEGIN 41 | MENUITEM "Create ViewObject", IDM_CREATEVIEWOBJECT 42 | MENUITEM "GetUIObjectOf with RClick", IDM_GETUIOBJECTOF 43 | MENUITEM "Support Composite Menus", IDM_COMPMENUS 44 | MENUITEM "Register as Drop Target", IDM_DROPTARGET 45 | MENUITEM "TrackSelect Style", IDM_TRACKSELECT 46 | MENUITEM "Respond to DDE messages", IDM_DDERESPOND 47 | MENUITEM "Include Browsable Items", IDM_BROWSEFILES 48 | END 49 | POPUP "&Help" 50 | BEGIN 51 | MENUITEM "About ...", IDM_ABOUT 52 | END 53 | END 54 | 55 | -------------------------------------------------------------------------------- /Readme.MD: -------------------------------------------------------------------------------- 1 | [ExplASM.txt](./ExplASM.txt) 2 | -------------------------------------------------------------------------------- /Res/Explorer.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baron-von-Riedesel/ExplASM/c663593ab2a960bbab1cb075baf3d298d62ccfd4/Res/Explorer.ico -------------------------------------------------------------------------------- /Res/Splith.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baron-von-Riedesel/ExplASM/c663593ab2a960bbab1cb075baf3d298d62ccfd4/Res/Splith.cur -------------------------------------------------------------------------------- /Wincrack.inc: -------------------------------------------------------------------------------- 1 | 2 | ;--- this file was previously named windowsx.inc 3 | ;--- but windowsx.inc is now generated by h2incx.exe 4 | ;--- what's remaining here are statusbar message cracker macros 5 | 6 | ;--- ListView (now in h2incx generated commctrl.inc) 7 | 8 | if 0 9 | ListView_GetItemText macro hwndLV,i,iSubItem_,pszText_,cchTextMax_ 10 | sub esp,sizeof LV_ITEM 11 | mov [esp].LV_ITEM.iSubItem,iSubItem_ 12 | mov [esp].LV_ITEM.pszText,pszText_ 13 | mov [esp].LV_ITEM.cchTextMax,cchTextMax_ 14 | invoke SendMessage,hwndLV,LVM_GETITEMTEXT,i,esp 15 | add esp,sizeof LV_ITEM 16 | endm 17 | ListView_SetItemText macro hwndLV,i,iSubItem_,pszText_ 18 | sub esp,sizeof LV_ITEM 19 | mov [esp].LV_ITEM.iSubItem,iSubItem_ 20 | mov [esp].LV_ITEM.pszText,pszText_ 21 | invoke SendMessage,hwndLV,LVM_SETITEMTEXT,i,esp 22 | add esp,sizeof LV_ITEM 23 | endm 24 | ListView_SetItemState macro hwndLV,i,data,mask_ 25 | sub esp,sizeof LV_ITEM 26 | mov [esp].LV_ITEM.state,data 27 | mov [esp].LV_ITEM.stateMask,mask_ 28 | invoke SendMessage,hwndLV,LVM_SETITEMSTATE,i,esp 29 | add esp,sizeof LV_ITEM 30 | endm 31 | endif 32 | ListView_SetCheckState macro hwndLV,i,fCheck 33 | mov eax,fCheck 34 | inc eax 35 | shl eax,12 36 | ListView_SetItemState hwndLV,i,eax,0F000h 37 | endm 38 | 39 | 40 | ;--- StatusBar 41 | 42 | if 1 43 | ;*** StatusBar macros (not found in MS C) 44 | 45 | SB_ISSIMPLE equ (WM_USER+14) 46 | SB_SETTIPTEXT equ (WM_USER+16) 47 | 48 | StatusBar_GetText macro hWnd, iPart, pText 49 | invoke SendMessage, hWnd, SB_GETTEXT, iPart, pText 50 | endm 51 | StatusBar_SetText macro hWnd, iPart, pText 52 | invoke SendMessage, hWnd, SB_SETTEXT, iPart, pText 53 | endm 54 | StatusBar_GetTextLength macro hWnd, iPart 55 | invoke SendMessage, hWnd, SB_GETTEXTLENGTH, iPart, 0 56 | endm 57 | StatusBar_SetSimpleMode macro hWnd, bFlag 58 | invoke SendMessage, hWnd, SB_SIMPLE, bFlag, 0 59 | endm 60 | StatusBar_SetParts macro hWnd, iParts, pdwWidths 61 | invoke SendMessage, hWnd, SB_SETPARTS, iParts, pdwWidths 62 | endm 63 | StatusBar_IsSimple macro hWnd 64 | invoke SendMessage, hWnd, SB_ISSIMPLE, 0, 0 65 | endm 66 | StatusBar_SetTipText macro hWnd, iPart, pszText 67 | invoke SendMessage, hWnd, SB_SETTIPTEXT, iPart, pszText 68 | endm 69 | endif 70 | 71 | ;*** EOF 72 | -------------------------------------------------------------------------------- /rsrc.inc: -------------------------------------------------------------------------------- 1 | 2 | option expr32 3 | option casemap:none 4 | 5 | ; Begin of file resource.h 6 | CREATEPROCESS_MANIFEST_RESOURCE_ID EQU 1t 7 | RT_MANIFEST EQU 24t 8 | IDD_DIALOG1 EQU 101t 9 | IDR_MENU1 EQU 102t 10 | IDD_DIALOG2 EQU 104t 11 | IDC_CURSOR1 EQU 105t 12 | IDI_ICON1 EQU 106t 13 | IDR_ACCELERATOR1 EQU 107t 14 | IDI_ICON2 EQU 115t 15 | CONTROL_PANEL_RESOURCE_ID EQU 123t 16 | IDC_LIST1 EQU 1000t 17 | IDC_STATUSBAR EQU 1001t 18 | IDC_EDIT1 EQU 1002t 19 | IDC_TREE1 EQU 1003t 20 | IDM_CREATEVIEWOBJECT EQU 40960t 21 | IDM_BINDTOOBJECT EQU 40961t 22 | IDM_GETUIOBJECTOF EQU 40962t 23 | IDM_OPENNEWWND EQU 40963t 24 | IDM_STATUSLINE EQU 40964t 25 | IDM_ABOUT EQU 40965t 26 | IDM_COMPMENUS EQU 40966t 27 | IDM_REFRESH EQU 40967t 28 | IDM_EXIT EQU 40968t 29 | IDM_SORT EQU 40969t 30 | IDM_DROPTARGET EQU 40970t 31 | IDM_TRACKSELECT EQU 40971t 32 | IDM_DDERESPOND EQU 40972t 33 | IDM_BROWSEFILES EQU 40973t 34 | IDM_DELETE EQU 40974t 35 | IDM_EXPAND EQU 40975t 36 | ; End of file resource.h 37 | --------------------------------------------------------------------------------