📄 objexp.bat
字号:
.break
.endif
add ebx, sizeof LPWSTR ; next type name
.break .if ebx > g_cbObjectTypeNames ; break if end of array
.endw
; Get selected list view item (object name)
mov [esi].imask, LVIF_PARAM
m2m [esi].iItem, iSelectedItem
and [esi].iSubItem, 0
ListView_GetItem g_hwndListView, esi
mov eax, [esi].lParam
assume esi:nothing
.else
xor eax, eax
.endif
.else
; Get selected tree view item (directory path)
lea esi, tvi
assume esi:ptr TV_ITEM
mov [esi]._mask, TVIF_PARAM
TreeView_GetSelection g_hwndTreeView ; our tree view has always something selected, but...
mov [esi].hItem, eax
; Each tree view item contains associated string with directory path in lParam
TreeView_GetItem g_hwndTreeView, esi
mov eax, [esi].lParam
mov ebx, IMG_ID_DIRECTORY
assume edi:nothing
.endif
; eax -> object path (unicode) or NULL
; ecx = object type
.if eax != NULL
invoke OpenObject, eax, ebx
.endif
ret
OpenSelectedObject endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; GetSelectedObjectTypeIndex
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
GetSelectedObjectTypeIndex proc uses esi ebx
; Returns object type index or -1 on errors
local tvi:TV_ITEM
local lvi:LV_ITEM
local buffer[256]:CHAR
invoke GetFocus
.if eax == g_hwndListView
lea esi, lvi
assume esi:ptr LV_ITEM
; Get object type
mov [esi].imask, LVIF_TEXT
ListView_GetNextItem g_hwndListView, -1, LVNI_SELECTED
.if eax != -1
mov [esi].iItem, eax
mov [esi].iSubItem, 1
lea eax, buffer
mov [esi].pszText, eax
mov [esi].cchTextMax, sizeof buffer
invoke SendMessage, g_hwndListView, LVM_GETITEMW, 0, esi
xor ebx, ebx ; undex
.while TRUE
; Which type ?
; invoke wcscmp, addr buffer, g_apuszObjectTypeNames[ebx]
invoke _wcsicmp, addr buffer, g_apuszObjectTypeNames[ebx]
.if eax == 0
shr ebx, 2 ; / sizeof LPWSTR = object type index
.break
.endif
add ebx, sizeof LPWSTR ; next type name
.break .if ebx > g_cbObjectTypeNames ; break if end of array
.endw
.else
xor eax, eax
.endif
.elseif eax == g_hwndTreeView
mov ebx, IMG_ID_DIRECTORY
.endif
mov eax, ebx
ret
GetSelectedObjectTypeIndex endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; ShowObjectProperties
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ShowObjectProperties proc uses esi edi
local hObject:HANDLE
local psp:PROPSHEETPAGE
local psh:PROPSHEETHEADER
;local obi:OBJECT_BASIC_INFORMATION
local dwLenghtReturned:DWORD
local oi:OBJECT_INFORMATION
local poni:POBJECT_NAME_INFORMATION
local poti:POBJECT_TYPE_INFORMATION
invoke OpenSelectedObject
.if eax != NULL
mov hObject, eax
lea esi, oi
assume esi:ptr OBJECT_INFORMATION
invoke ZwQueryObject, hObject, ObjectBasicInformation, addr [esi].BasicInformation, sizeof OBJECT_BASIC_INFORMATION, addr dwLenghtReturned
.if eax == STATUS_SUCCESS
dec [esi].BasicInformation.HandleCount ; correct count of handles
dec [esi].BasicInformation.PointerCount ; the ref count is also one more
Fix Add error checking
invoke malloc, 1000h
mov poni, eax
invoke ZwQueryObject, hObject, ObjectNameInformation, poni, 1000h, addr dwLenghtReturned
; If object is file QueryDirectoryObject tells that it's 'Device'
; but ZwQueryObject,, ObjectTypeInformation, tells that it's 'File'
invoke malloc, 1000h
mov poti, eax
invoke ZwQueryObject, hObject, ObjectTypeInformation, poti, 1000h, addr dwLenghtReturned
invoke ZwClose, hObject
and hObject, NULL
invoke memcpy, addr [esi]._Name, poni, sizeof UNICODE_STRING
invoke memcpy, addr [esi].TypeName, poti, sizeof UNICODE_STRING
invoke GetSelectedObjectTypeIndex
mov [esi].ObjectTypeIndex, eax
lea edi, psp
assume edi:ptr PROPSHEETPAGE
mov [edi].dwSize, sizeof PROPSHEETPAGE
mov [edi].dwFlags, PSP_USEICONID + PSP_USETITLE
m2m [edi].hInstance, g_hInstance
mov [edi].pszTemplate, IDD_PROPERTIES
and [edi].pszIcon, NULL
mov [edi].pfnDlgProc, offset PropertyDialogProc
mov [edi].pszTitle, $CTA0("Object Info")
mov [edi].lParam, esi
and [edi].pfnCallback, NULL
lea edi, psh
assume edi:ptr PROPSHEETHEADER
mov [edi].dwSize, sizeof PROPSHEETHEADER
mov [edi].dwFlags, PSH_USEICONID + PSH_PROPSHEETPAGE
m2m [edi].hwndParent, g_hWnd
m2m [edi].hInstance, g_hInstance
and [edi].pszIcon, NULL
mov [edi].pszCaption, $CTA0("Properties")
mov [edi].nPages, 1 ; sizeof psp / sizeof PROPSHEETPAGE
and [edi].nStartPage, 0
lea eax, psp
mov [edi].ppsp, eax
and [edi].pfnCallback, NULL
assume edi:nothing
invoke PropertySheet, edi
invoke free, poni
invoke free, poti
.else
invoke GetFocus
push eax
invoke MessageBox, g_hWnd, $CTA0("Couldn't query object info."), NULL, MB_ICONERROR
call SetFocus
.endif
assume esi:nothing
.if hObject != NULL
invoke ZwClose, hObject
.endif
.endif
ret
ShowObjectProperties endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; QueryDirectoryObject
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
QueryDirectoryObject proc uses esi ebx puszDirectoryPath:LPWSTR
; Returns - pointer to array of DIRECTORY_BASIC_INFORMATION
; NULL if unsuccesseful
local status:NTSTATUS
local oa:OBJECT_ATTRIBUTES
local us:UNICODE_STRING
local hDirectory:HANDLE
;local cb:UINT
local dwLenghtReturned:DWORD
local Context:LPVOID
xor esi, esi ; assume unsuccess
invoke RtlInitUnicodeString, addr us, puszDirectoryPath
lea ecx, oa
lea edx, us
InitializeObjectAttributes ecx, edx, OBJ_CASE_INSENSITIVE, NULL, NULL
invoke ZwOpenDirectoryObject, addr hDirectory, DIRECTORY_QUERY, addr oa
.if eax == STATUS_SUCCESS
mov ebx, 800h
.while TRUE
invoke malloc, ebx
.break .if eax == NULL
mov esi, eax
invoke ZwQueryDirectoryObject, hDirectory, esi, ebx, FALSE, TRUE, addr Context, addr dwLenghtReturned
.if eax == STATUS_SUCCESS
.break
.elseif ( eax == STATUS_NO_MORE_ENTRIES ) || ( eax == STATUS_ACCESS_DENIED )
; directory is empty or access denied
invoke free, esi
xor esi, esi
.break
.elseif ( eax == STATUS_MORE_ENTRIES ) || ( eax == STATUS_BUFFER_TOO_SMALL )
invoke free, esi ; Try again
xor esi, esi
shl ebx, 1 ; Ask twice more memory
.if ebx > 1000h * 100 ; 400k
.break ; We need to big buffer -> something went wrong
; Better go away from here
.endif
.else
.endif
.endw
invoke ZwClose, hDirectory
.endif
mov eax, esi
ret
QueryDirectoryObject endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; QuerySymbolicLinkObject
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
QuerySymbolicLinkObject proc uses esi ebx puszSymbolicLinkPath:LPWSTR
; Allocates memory from process heap
; Retrieves name of the object symbolic link links to
; Stores retrieved UNICODE_STRING and name into allocated memory
; Returns - pointer to UNICODE_STRING
; NULL if unsuccesseful
local status:NTSTATUS
local oa:OBJECT_ATTRIBUTES
local us:UNICODE_STRING
local hSymbolicLink:HANDLE
;local cb:UINT
local dwLenghtReturned:DWORD
local Context:LPVOID
xor esi, esi ; assume unsuccess
invoke RtlInitUnicodeString, addr us, puszSymbolicLinkPath
lea ecx, oa
lea edx, us
InitializeObjectAttributes ecx, edx, OBJ_CASE_INSENSITIVE, NULL, NULL
invoke ZwOpenSymbolicLinkObject, addr hSymbolicLink, SYMBOLIC_LINK_QUERY, addr oa
.if eax == STATUS_SUCCESS
mov ebx, 800h
.while TRUE
invoke malloc, ebx
.break .if eax == NULL
mov esi, eax
assume esi:ptr UNICODE_STRING
and [esi]._Length, 0
mov eax, ebx
sub eax, sizeof UNICODE_STRING
mov [esi].MaximumLength, ax
lea eax, [esi][sizeof UNICODE_STRING]
mov [esi].Buffer, eax
assume esi:nothing
invoke ZwQuerySymbolicLinkObject, hSymbolicLink, esi, addr dwLenghtReturned
.if eax == STATUS_SUCCESS
.break
.elseif eax == STATUS_ACCESS_DENIED
; directory is empty or access denied
invoke free, esi
xor esi, esi
.break
.elseif ( eax == STATUS_BUFFER_TOO_SMALL )
invoke free, esi ; Try again
xor esi, esi
shl ebx, 1 ; Ask twice more memory
.if ebx > 1000h * 10 ; 40k is enough for symbolic link object
.break ; We need to big buffer -> something went wrong
; Better go away from here
.endif
.else
.endif
.endw
invoke ZwClose, hSymbolicLink
.endif
mov eax, esi
ret
QuerySymbolicLinkObject endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; MakeFullPath
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
MakeFullPath proc uses esi edi puszDirectoryPath:LPWSTR, pusObjectName:PTR UNICODE_STRING
; Makes full path to object from directory path and object name
; Allocates buffer from process heap and stores created full path into it
; Returns pointer to allocated memory with full path or NULL if unsuccessful
invoke wcslen, puszDirectoryPath
shl eax, 1 ; * sizeof WCHAR = len in bytes (not including terminated zero)
mov esi, pusObjectName
add ax, (UNICODE_STRING PTR [esi])._Length ; + srtlen(ObjectName). Hope len of path never grows above FFFFh
add eax, 4 ; take into account separating '\' and terminating zero
invoke malloc, eax
.if eax != NULL
mov edi, eax
invoke wcscpy, edi, puszDirectoryPath
invoke wcscmp, puszDirectoryPath, offset g_uszBackSlash
; If it not the root directory add backslash
.if eax
invoke wcscat, edi, offset g_uszBackSlash
.endif
invoke wcscat, edi, (UNICODE_STRING PTR [esi]).Buffer
.else
xor edi, edi
.endif
mov eax, edi
ret
MakeFullPath endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; FillTreeViewNode
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
FillTreeViewNode proc uses esi edi ebx hTvUpperNode:HTREEITEM, puszDirectoryPath:LPWSTR
local status:NTSTATUS
local oa:OBJECT_ATTRIBUTES
local us:UNICODE_STRING
local hDirectory:HANDLE
;local pdbi:PDIRECTORY_BASIC_INFORMATION
local cb:UINT
local dwLenghtReturned:DWORD
local Context:LPVOID
local tvins:TV_INSERTSTRUCTW
local hTvNode:HTREEITEM
invoke QueryDirectoryObject, puszDirectoryPath
.if eax != NULL
mov esi, eax ; -> array of DIRECTORY_BASIC_INFORMATION
push esi ; save for invoke free, esi
assume esi:ptr DIRECTORY_BASIC_INFORMATION
; Create TreeView Node
lea edi, tvins
assume edi:ptr TV_INSERTSTRUCTW
mrm [edi].hParent, hTvUpperNode
mov [edi].hInsertAfter, TVI_LAST
mov [edi].item._mask, TVIF_TEXT + TVIF_SELECTEDIMAGE + TVIF_IMAGE + TVIF_PARAM
mov [edi].item.iImage, IMG_ID_DIRECTORY
mov [edi].item.iSelectedImage, IMG_ID_DIRECTORY_OPN
; The array is terminated with zeroed DIRECTORY_BASIC_INFORMATION structure
; But we check only first two dwords. It's enough.
.while (dword ptr [esi] != 0) && (dword ptr [esi][4] != 0)
mov eax, [esi].ObjectTypeName.Buffer
; invoke wcscmp, eax, $CTW0("Directory")
invoke _wcsicmp, eax, $CTW0("Directory")
; Only objects of type "Directory" is of interest for us
.if eax == 0
; Make full path to object and associate it with tree view item
; Later we have manually free this memory
invoke MakeFullPath, puszDirectoryPath, addr [esi].ObjectName
mov [edi].item.lParam, eax
mrm [edi].item.pszText, [esi].ObjectName.Buffer
;TreeView_InsertItem g_hwndTreeView, edi
invoke SendMessage, g_hwndTreeView, TVM_INSERTITEMW, 0, edi
; If current directory contains other directories fill it recursivelly
invoke FillTreeViewNode, eax, [edi].item.lParam
.endif
add esi, sizeof DIRECTORY_BASIC_INFORMATION
.endw
assume edi:nothing
pop esi
invoke free, esi
assume esi:nothing
.endif
ret
FillTreeViewNode endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; DeleteListView
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
DeleteListView proc uses esi ebx
; Frees all memory associated with each list view item and deletes all items
local lvi:LV_ITEM
ListView_GetItemCount g_hwndListView
.if eax != 0
mov ebx, eax
lea esi, lvi
assume esi:ptr LV_ITEM
mov lvi.imask, LVIF_PARAM
.while ebx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -