News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

A question on ShellExecuteEx

Started by clamicun, July 16, 2015, 01:06:39 AM

Previous topic - Next topic

clamicun

If we rightclick on a file/Dir and choose properties, we get Info on...

Type
Location
Size
Creation date  and more.
-----------------------

This little prog does the same...

;==================================================================
;progName ShowProps.asm
include   \masm32\include\masm32rt.inc
.686   ; JWasm needs this
   
.data
slash       TCHAR '\',0
cur_path    TCHAR MAX_PATH dup(0),0
fProperties TCHAR 'properties',0
ShExecInfo  SHELLEXECUTEINFO <?>

.code
start:

call Browse4Folder

mov ShExecInfo.cbSize,sizeof SHELLEXECUTEINFO
mov ShExecInfo.fMask, SEE_MASK_INVOKEIDLIST 
mov eax,HWND_DESKTOP
mov ShExecInfo.hwnd,eax
mov ShExecInfo.lpVerb,offset fProperties
mov ShExecInfo.lpFile,offset cur_path            ;Path + File/Dirname from Browse4Folder
mov ShExecInfo.lpParameters,NULL
mov ShExecInfo.lpDirectory,NULL                  ;Current Directory if no path in lpFile
mov ShExecInfo.nShow,SW_SHOW
mov ShExecInfo.hInstApp,NULL                     ;Out: succes > 32 - fail SE_ERR_XXX error codes
INVOKE ShellExecuteEx,offset ShExecInfo

INVOKE MessageBox,0,0,0,0             
;inkey "ok"                                      ;if Console built
jmp start
;==================================================================

Browse4Folder  proc
LOCAL lpbi:BROWSEINFO

mov     eax,HWND_DESKTOP
mov     lpbi.hwndOwner,eax
mov     lpbi.pidlRoot, 0
mov     lpbi.pszDisplayName, offset cur_path   
mov     lpbi.lpszTitle,0       
mov     lpbi.ulFlags,BIF_RETURNONLYFSDIRS  ;+BIF_NEWDIALOGSTYLE+BIF_NONEWFOLDERBUTTON
mov     lpbi.lpfn, 0
mov     lpbi.lParam, 0
mov     lpbi.iImage, 0
INVOKE  SHBrowseForFolder, addr lpbi

.if !eax
INVOKE ExitProcess,0
.endif
   
INVOKE SHGetPathFromIDList, eax, offset cur_path

.if byte ptr cur_path+3 != 0
INVOKE lstrcat,offset cur_path,offset slash
.endif
ret
     
Browse4Folder   endp 
;==================================================================
end start
;==================================================================

I would like to know which function(s) the OS (shellexecuteEx) uses, to obtain these informations.

e.g.
GetFileSizeEx returns the size of a file.
What about the size of a directory ?

Thank you.

adeyblue

I don't think there is such a function, probably due to these reasons. It can be done manually using FindFirstFile and friends to iterate over the files and into directories keeping a total as you go. The WIN32_FIND_DATA you get from those functions contains the size of the file


dedndave

i think there's a way to do it using COM
but - i've never tried it   :P

jj2007

#3
Quote from: adeyblue on July 16, 2015, 02:24:54 AMIt can be done manually using FindFirstFile and friends

Indeed. Here is an example:

include \masm32\MasmBasic\MasmBasic.inc      ; download
  Init
  GetFiles \Masm32\Examples\*
  xorps xmm1, xmm1
  For_ ecx=0 To eax-1
      pshufd xmm0, GfLastWrite(ecx), 1011b       ; GfLastWrite returns size in xmm0     
      paddq xmm1, xmm0
  Next
  Inkey Str$("There are %i bytes in \Masm32\Examples", xmm1)
  Exit
end start

clamicun

JJ,buona notte
yes, I was waiting for an answer from YOU.

I think, I understood.
There is no function whatever to check a foldersize.
That is why - after searching on my computer and in the net for 'some' time, I did not find one.

like e.g.
INVOKE GetDirSize,offset dirName

Seems - and it makes sense - that you have to check the content of a folder.

I tried every variation on....

mov   eax, MAXDWORD 
mov  ebx, wfd.nFileSizeHigh
imul  ebx
add   eax, edx,wfd.nFileSizeLow 
mov  TheSize, eax
....

It returns the correct values on files.
On folders the return is alway 0.

ok.Thanks a lot like always.
Have a good one.
Mic

P.S.
Your prog returns the correct values, but it is awfully slow.
Takes up to 15 seconds.



jj2007

Quote from: clamicun on July 16, 2015, 08:32:09 AMYour prog returns the correct values, but it is awfully slow.
Takes up to 15 seconds.

Version 2 (see above) returns the correct values even for folders with more than 4 GB :redface:
(but don't be surprised if special folders like C:\Windows\ return marginally incorrect values - there is the phenomenon of really well hidden files etc, and it's not easy to define what is "correct")


The 15 seconds are normal. If you read the Old New Thing article linked above, you will realise that Windows doesn't have a built in GetFolderSize function. They find lots of excuses, but as a matter of fact, they simply forgot to keep a per folder size variable. As a consequence, you have to look at all files, all the time. And that is inherently slow...

But run the program a second time, and it will be fast. It's called disk cache ;-)

clamicun

JJ,
one thing.
Might be, the Microsoft programmers forgot to built a function like "GetFolderSize".
Or it never was published, which is very unlikely, with millions of people searching for Win Apis.

But it is a fact, that rightclick on properties (see my proggy) opens immediately a dialog which gives you...

Location
Size
Content
Creation Date

of a folder.

In less than a second.
So how the do it ?

Mic

adeyblue

Like JJ said, if you've checked that directory before and haven't restarted your computer, it'll be in the cache which is miles quicker than hitting the disk / network.

The shell uses a FindNextFile loop, here's a stack trace showing the FindFirstFileEx that starts it off.

Doing it yourself is more involved than just a simple loop though thanks to NTFS. For instance, you probably don't want to follow junction points or directory symlinks as those could cause you to loop indefinitely. Check the find data attributes for FILE_ATTRIBUTE_REPARSE_POINT

Also if you want actual disk space taken then you have to do slightly more than just FindNextFile. If you have sparse files turned on, you can create a 16TB file no matter how big your drive is. For accuracy check the find data attributes for FILE_ATTRIBUTE_SPARSE_FILE and get the real size with GetFileInformationByHandleEx(FileStandardInfo) - AllocationSize

A standard loop also won't account for any NTFS alternate data streams on the file. I don't know if Explorer counts these in the size

So yeah, it all depends how accurate you want it to be and how much work you want to put into it.

clamicun

Thank you adeyblue,
yes, I understand exactely what you mean.
Attached is a prog which gets the foldersize - using FindFirstfile - FindNextFile.
It does the job, but is lightyears away from Windows clickright properties.

dedndave

using COM...

iDispatch::FolderItem.Size

something like that

https://msdn.microsoft.com/en-us/library/windows/desktop/bb787810%28v=vs.85%29.aspx

probably how microsoft does it for folder properties

clamicun

Thank you, dedndave

Now you mentioned 2times "using COM"

and to be honest - I have not the slightest idea what you mean with that.

dedndave

well - there have been several examples in the forum, over time
it's a bit confusing, to be honest - lol
reading about COM is really confusing, because they use terminology that is probably new to the reader

it would probably be best to find some example code, rather than reading a bunch of documentation
but, to get you started, it helps to know what COM is   :biggrin:

https://www.microsoft.com/com/default.mspx