The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: maruf10 on April 09, 2010, 04:00:11 AM

Title: GetDiskFreeSpaceEx help
Post by: maruf10 on April 09, 2010, 04:00:11 AM
hello all ...

I am trying to get the free and used disk space of a  specific drive like D:\
This is form MSDN

Quote

BOOL GetDiskFreeSpaceEx(
  LPCWSTR lpDirectoryName,
  PULARGE_INTEGER lpFreeBytesAvailableToCaller,
  PULARGE_INTEGER lpTotalNumberOfBytes,
  PULARGE_INTEGER lpTotalNumberOfFreeBytes
);

The values obtained by this function are of type ULARGE_INTEGER. Be sure not to truncate these values to 32 bits.


how can i get free and used bytes ??
need 64-bit !!??
Title: Re: GetDiskFreeSpaceEx help
Post by: dedndave on April 09, 2010, 04:14:54 AM
Hutch had a great llittle program for that a few months back
let me see if i can find it with the forum search tool...
Title: Re: GetDiskFreeSpaceEx help
Post by: dedndave on April 09, 2010, 04:25:09 AM
here is the thread i was thinking of...
http://www.masm32.com/board/index.php?topic=12385.0

and a related one...
http://www.masm32.com/board/index.php?topic=12365.0
Title: Re: GetDiskFreeSpaceEx help
Post by: Ghandi on April 09, 2010, 08:59:32 AM
You might need to write a sticky note giving a detailed explanation with pictures Dave, its magic that the search button would yield results!!! o0

Sorry, i couldn't help that. Don't mind me, its all tongue in cheek.

HR,
Ghandi
Title: Re: GetDiskFreeSpaceEx help
Post by: jj2007 on April 09, 2010, 10:05:44 AM
Here is a working snippet (only the Print Str$ part requires the MB lib, replace with crt printf or similar if needed).

include \masm32\MasmBasic\MasmBasic.inc

.data
FreeBytesAvailableToCaller dq 0
TotalNumberOfBytes dq 0
TotalNumberOfFreeBytes dq 0
DirectoryName db "D:\", 0
OneGiga = 1024*1024*1024

.code
start: invoke GetDiskFreeSpaceEx,
offset DirectoryName,
offset FreeBytesAvailableToCaller,
offset TotalNumberOfBytes,
offset TotalNumberOfFreeBytes

Print Str$("FreeBytesAvailable:\t%4f GB\n", q:FreeBytesAvailableToCaller/OneGiga)
Print Str$("TotalNumberOfBytes:\t%4f GB\n", q:TotalNumberOfBytes/OneGiga)
Print Str$("TotalNumberOfFreeBytes:\t%4f GB\n", q:TotalNumberOfFreeBytes/OneGiga)

Inkey "bye"
Exit
end start


FreeBytesAvailable:     141.3 GB
TotalNumberOfBytes:     149.0 GB
TotalNumberOfFreeBytes: 141.3 GB
Title: Re: GetDiskFreeSpaceEx help
Post by: maruf10 on April 09, 2010, 12:34:19 PM
Trying to get the used space of drive K: ...
may b the subtraction operatio is wrong
it shows correct output for total and free space .
i am trying to calculate the used space by (total space - free space)

here is the code:
Quote
.data
freeSpace dd ?,?          ;GetDiskFreeSpaceEx expects this to be 64-bits
totalSpace dd ?,?         ;GetDiskFreeSpaceEx expects this to be 64-bits
usedSpace dd ?,?
outputbuffer db 256 dup(?)
totalbuffer db 256 dup(?)
usedbuffer  db 256 dup(?)
freebuffer  db 256 dup(?)
report db  "Total Space ............ %s",13,10,"Used Space ............ %s",13,10,"Free Space ............ %s"

.code
start:

invoke GetDiskFreeSpaceEx, CTEXT("K:\"),addr freeSpace,addr totalSpace,0

invoke StrFormatByteSize64, totalSpace, totalSpace+4, ADDR totalbuffer, SIZEOF totalbuffer
invoke StrFormatByteSize64, freeSpace, freeSpace+4, ADDR freebuffer, SIZEOF freebuffer

mov eax , totalSpace
mov ebx , freeSpace
sub eax , ebx
mov usedSpace , eax

invoke StrFormatByteSize64, usedSpace, usedSpace+4, ADDR usedbuffer, SIZEOF usedbuffer

invoke wsprintf , addr outputbuffer , addr report , addr totalbuffer , addr usedbuffer , addr freebuffer
invoke MessageBox, NULL,addr outputbuffer,CTEXT("K:\ Drive Info"), MB_OK
invoke ExitProcess,NULL
end start



it also shows some extra character after last line ...
here is the output copied from MessageBox.
Quote

Total Space ......... 7.46 GB
Used Space ......... 502 MB
Free Space .......... 2.97 GBK:\

what is the solution ??
Title: Re: GetDiskFreeSpaceEx help
Post by: qWord on April 09, 2010, 01:03:46 PM
Quotereport db  "Total Space ............ %s",13,10,"Used Space ............ %s",13,10,"Free Space ............ %s",0
...
mov eax,totalSpace
mov edx,totalSpace+4
sub eax,freeSpace
sbb edx,freeSpace+4
mov usedSpace,eax
mov usedSpace+4,edx
Title: Re: GetDiskFreeSpaceEx help
Post by: maruf10 on April 09, 2010, 01:06:02 PM
what is the reason for adding 4 ??
actually i didn't understand it  :red
Title: Re: GetDiskFreeSpaceEx help
Post by: qWord on April 09, 2010, 01:08:40 PM
you need 64Bit arithmetic because file/directory sizes are 64 bit width. The '+4' is used to access the high order DWORD of a QWORD. (4 is added to the addres of variable, not to the content)
Title: Re: GetDiskFreeSpaceEx help
Post by: dedndave on April 09, 2010, 01:18:19 PM
Ghandi
this is a case where i knew what to look for - i also knew who the author was, which helped me narrow it down a bit   :P
Title: Re: GetDiskFreeSpaceEx help
Post by: maruf10 on April 10, 2010, 05:54:04 AM
to qWord:

what is the reason for using both sub and sbb??

sub eax,freeSpace
sbb edx,freeSpace+4

what is the reason for using 4 parameters in StrFormatByteSize64 ??
there should be three parameters ..
Title: Re: GetDiskFreeSpaceEx help
Post by: donkey on April 10, 2010, 06:23:08 AM
Quote from: maruf10 on April 10, 2010, 05:54:04 AM
to qWord:

what is the reason for using both sub and sbb??

sub eax,freeSpace
sbb edx,freeSpace+4

It is used to do 64 bit subtraction (subtract then subtract with borrow).

Quotewhat is the reason for using 4 parameters in StrFormatByteSize64 ??
there should be three parameters ..

Because you are pushing 32bit numbers and the first parameter is a 64 bit number, you have to push it in 2 parts hence the 4 parameters instead of 3.
Title: Re: GetDiskFreeSpaceEx help
Post by: ragdog on April 10, 2010, 07:00:01 AM
Here is a Example from Florian Mücke



.data

    lpRootPathName db "\",0
    lpSPerClus dd 0
    lpBPerSec dd 0
    lpNOfFreeClus dd 0
    lpTotalNClus dd 0
ConvertStr db "%lu kB available to caller",13,10,"%lu k total",0
String db 255 dup (0)

caption db "GetDiskFreeSpace",0
lpDir db "\",0
lpFBAvailableQ dq 0
lpTotalBytesQ dq 0
lpFBAvailableD dd 0
lpTotalBytesD dd 0

String1 db 255 dup (0)

OneK REAL10 1024.0

.code
start:
invoke GetDiskFreeSpaceEx, ADDR lpDir, ADDR lpFBAvailableQ, ADDR lpTotalBytesQ, NULL
finit ;initialisiert FPU
fld OneK ;laed eine Realzahl (1024,0) in den TOS
fild lpFBAvailableQ ;laed lpFB... in den TOS
fdiv ST(0),ST(1) ;dividiert zwei Realzahlen
fistp lpFBAvailableD ;speichert Integer aus dem TOS und poppt
fild lpTotalBytesQ
fdiv ST(0),ST(1)
fistp lpTotalBytesD
invoke wsprintf, ADDR String1, ADDR ConvertStr,lpFBAvailableD, lpTotalBytesD
invoke MessageBox,0,ADDR String1,ADDR caption,MB_OK
push 0
call ExitProcess          
end start


Title: Re: GetDiskFreeSpaceEx help
Post by: sinsi on April 10, 2010, 07:42:36 AM
  mov eax,totalSpace
  mov edx,totalSpace+4
  shrd eax,edx,10   ;10 for KB, 20 for MB, eax has value

I prefer to see "4096 Meg" instead of "4294967296 bytes" (or even "4 Gig" but accuracy is lost with too many shifts (3.99 Gig will show as "3 Gig")).
Title: Re: GetDiskFreeSpaceEx help
Post by: clive on April 10, 2010, 12:44:44 PM
Quote from: sinsi
I prefer to see "4096 Meg" instead of "4294967296 bytes" (or even "4 Gig" but accuracy is lost with too many shifts (3.99 Gig will show as "3 Gig")).

The trick of course it to display them in a magnitude appropriate manner, especially when the number may be a few thousand bytes, up to a couple of terabytes.

-Clive
Title: Re: GetDiskFreeSpaceEx help
Post by: dedndave on April 10, 2010, 01:02:10 PM
(eq.1) minimum number of digits

Dmin = FLOOR((N-1) x LOG(2)) + 1

(eq.2) maximum number of digits

Dmax = FLOOR(N x LOG(2)) + 1

D = number of decimal digits
N = number of bits


figure out how many digits you want to see (4 to 5 seems adequate)
test the upper (64 - N) bits for all 0's
if any of those bits are non-zero, SHR,10, increment the magnitude counter, and test again
Title: Re: GetDiskFreeSpaceEx help
Post by: raisul on April 10, 2010, 03:40:09 PM
include \masm32\include\masm32rt.inc
include \masm32\include\debug.inc
include \masm32\include\shlwapi.inc

includelib \masm32\lib\masm32.lib
includelib \masm32\lib\debug.lib
includelib \masm32\lib\shlwapi.lib




.data
freeSpace dd ?,?          ;GetDiskFreeSpaceEx expects this to be 64-bits
totalSpace dd ?,?         ;GetDiskFreeSpaceEx expects this to be 64-bits
usedSpace dd ?,?
outputbuffer db 256 dup(?)
totalbuffer db 256 dup(?)
usedbuffer  db 256 dup(?)
freebuffer  db 256 dup(?)
report db  "Total Space ............ %s",13,10,"Used Space ............ %s",13,10,"Free Space ............ %s",0
MAXPATH equ 512
driveName db MAXPATH dup (?)
colon db ":",0
slash db "/",0
_title db " ",0
space db " ",0
info db " Drive Information",0
info2 db "Submitte By Raisul",0
prompt1 db "ENTER DRIVE NAME : ",0
prompt2 db "DO YOU WANT TO CONTINUE(y/n)?? ",0
decision db MAXPATH dup (?)
Y db "y",0
N db "n",0
newline db 10,13,0
.code
start:

   invoke ClearScreen
   .repeat
      invoke StdOut , addr prompt1
   
      invoke StdIn , addr driveName , MAXPATH
      MOV BYTE PTR [driveName+EAX-2],0

      invoke lstrcat , addr driveName , addr colon
      invoke lstrcat , addr driveName , addr slash

      invoke GetDiskFreeSpaceEx, addr driveName,addr freeSpace,addr totalSpace,0

      invoke StrFormatByteSize64, totalSpace, totalSpace+4, ADDR totalbuffer, SIZEOF totalbuffer
      invoke StrFormatByteSize64, freeSpace, freeSpace+4, ADDR freebuffer, SIZEOF freebuffer

      mov eax,totalSpace
      mov edx,totalSpace+4
      sub eax,freeSpace
      sbb edx,freeSpace+4
      mov usedSpace,eax
      mov usedSpace+4,edx

      invoke StrFormatByteSize64, usedSpace, usedSpace+4, ADDR usedbuffer, SIZEOF usedbuffer

      invoke wsprintf , addr outputbuffer , addr report , addr totalbuffer , addr usedbuffer , addr freebuffer

      invoke lstrcpy , addr _title , addr driveName
      invoke lstrcat , addr _title , addr info
      invoke lstrcat , addr _title , addr info2

      invoke MessageBox, NULL,addr outputbuffer,addr _title, MB_OK
      invoke StdOut , addr newline
      
      
      
      .repeat

         invoke StdOut , addr prompt2
         invoke StdIn , addr decision , MAXPATH
         MOV BYTE PTR [decision+EAX-2],0
         invoke lstrcmp , addr decision , addr Y
         mov ebx , eax
         invoke lstrcmp , addr decision , addr N
         mov ecx , eax
      
      .until (ebx == 0 || ecx == 0)
      
   .until ebx!=0
   
   invoke ExitProcess,NULL

end start

>> give me some idea to add graphical interface with the above code
Title: Re: GetDiskFreeSpaceEx help
Post by: raisul on April 10, 2010, 03:46:01 PM
driveName db MAXPATH dup (?)


What is the use of MAXPATH
Title: Re: GetDiskFreeSpaceEx help
Post by: GregL on April 10, 2010, 03:46:10 PM
Quote from: CliveThe trick of course it to display them in a magnitude appropriate manner, especially when the number may be a few thousand bytes, up to a couple of terabytes.

Someone already worked out a procedure to do that, I wasn't able to find it though.
Title: Re: GetDiskFreeSpaceEx help
Post by: clive on April 10, 2010, 04:06:51 PM
Quote from: Greg Lyon
Someone already worked out a procedure to do that, I wasn't able to find it though.

I wrote this many years ago for a disc media application, take it as a pseudo-code example.
-Clive


// KILO,MEGA,GIGA,TERA,PETA,EXA,ZETTA,YOTTA

char * MemSize(QWORD Size)
{
static const char Symbol[] = "KMGTPEZY?";
static char Str[32];

int Sym;

double Units;
double Capacity;

Sym = 0;

Units = 1024.0;

Capacity = (double)Size / Units;

while((Capacity > Units) || (Sym >= (sizeof(Symbol) - 1)))
{
Capacity = Capacity / Units;

Sym++;
}

sprintf(Str, "%6.2lf %cB", Capacity, Symbol[Sym]);

return(Str);
}
Title: Re: GetDiskFreeSpaceEx help
Post by: clive on April 10, 2010, 04:09:10 PM
Quote from: raisul1
driveName db MAXPATH dup (?)

What is the use of MAXPATH

To allocate enough space for a fully described path. Seems overkill for "C:\", but better than allocating an insufficient one.

-Clive
Title: Re: GetDiskFreeSpaceEx help
Post by: raisul on April 11, 2010, 08:57:22 PM
How can i add background image in my asm code
Title: Re: GetDiskFreeSpaceEx help
Post by: clive on April 13, 2010, 03:44:10 AM
Autoranging capacity conversion in assembler using 64-bit integers.
-Clive

        .386

        .MODEL FLAT,C

        .CODE

; Convert 64-bit capacity number to form xxx.yyy KB, xxx.yyy GB, etc

AutoRange PROC num:QWORD, outstr:PTR BYTE

        push    esi
        push    ebx

        mov     esi,outstr      ; C string output buffer

        mov     eax,dword ptr num[0] ; Low order 32-bits
        mov     edx,dword ptr num[4] ; High order

        ; Fixed point 10.10 bits, autoranging

        xor     ebx,ebx         ; Clear size index

        or      edx,edx         ; Test high order dword
        jnz     next

        test    eax,0FFF00000h  ; Try to confine range to xxx.yyy ie 0.000 to 1023.999
        jz      done            ;  by checking upper 12 bits zero, and lower 20 bits the number

next:   shrd    eax,edx,10      ; edx:eax >> 10 -> eax
        shr     edx,10          ; edx >> 10 -> edx
        inc     ebx             ; step magnitude index

        or      edx,edx         ; Test high order dword
        jnz     next            ; still non zero, shift again
        test    eax,0FFF00000h  ; Check if lower 20 bits hold the number
        jnz     next            ; if upper 12-bits non zero, shift again

done:   push    eax             ; Save fractional portion
        shr     eax,10          ; align to integer portion

        ; convert binary to decimal for integer portion

        push    0               ; Mark end of decimal with NULL
        mov     ecx,10          ; base 10
@@:     xor     edx,edx         ; eax = edx:eax / 10, edx = edx:eax % 10
        div     ecx
        add     edx,030h        ; += '0', convert digit to ASCII
        push    edx             ; stack
        or      eax,eax         ; until decimal fully decoded
        jnz     @B

        pop     eax             ; unstack
@@:     mov     byte ptr [esi],al ; add ASCII digit
        add     esi,1
        pop     eax             ; unstack
        or      eax,eax         ; NULL marks end of digits
        jnz     @B

        mov     byte ptr [esi],'.' ; Add decimal point

        pop     eax             ; Recover fractional portion
        and     eax,03FFh       ; Mask fraction portion
        mov     ecx,1000        ; Convert 0..1023 to 0..999
        mul     ecx             ; eax = (eax * 1000) >> 10
        shr     eax,10

        ; Convert to 3 decimal places for fractional portion

        mov     ecx,10          ; Base 10

        xor     edx,edx         ; eax = edx:eax / 10, edx = edx:eax % 10
        div     ecx
        add     edx,030h        ; += '0', convert digit to ASCII
        mov     byte ptr [esi+3],dl ; .--F

        xor     edx,edx         ; eax = edx:eax / 10, edx = edx:eax % 10
        div     ecx
        add     edx,030h        ; += '0', convert digit to ASCII
        mov     byte ptr [esi+2],dl ; .-F-

        xor     edx,edx         ; eax = edx:eax / 10, edx = edx:eax % 10
        div     ecx
        add     edx,030h        ; += '0', convert digit to ASCII
        mov     byte ptr [esi+1],dl ; .F--

        mov     byte ptr [esi+4],' ' ; space
        mov     al,mag[ebx]
        mov     byte ptr [esi+5],al     ; xB<NUL>
        mov     byte ptr [esi+6],'B'
        mov     byte ptr [esi+7],0

        pop     ebx
        pop     esi

        ret

        ; Magnitude conversion

mag     db      'KMGTPE' ; KMGTPEZY, 64-bits gets to EXABYTES

AutoRange ENDP

        END