Page 1 of 1

Enumerate hard links (Windows)

Posted: Tue Mar 24, 2015 12:27 am
by bbanelli
Windows Vista and above only (NTFS only)
PB 5.31, Unicode only

Code: Select all

; No advanced error checking is done, this is just a pure concept
; Check documentation for full implementation
; FindFirstFileNameW
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa364421(v=vs.85).aspx
; FindNextFileNameW 
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa364429(v=vs.85).aspx

CompilerIf #PB_Compiler_Unicode = #False
  CompilerError "Please check 'Create Unicode executable' in 'Compiler options'"
CompilerEndIf

EnableExplicit

Prototype.i FindFirstFileNameW(lpFileName.s, dwFlags.i, *StringLength, *LinkName)
Prototype.i FindNextFileNameW(hFindStream.i, *StringLength, *LinkName)

If OpenLibrary(0, "Kernel32.dll")
  Global FindFirstFileNameW.i : FindFirstFileNameW.FindFirstFileNameW  = GetFunction(0, "FindFirstFileNameW")
  Global FindNextFileNameW.i  : FindNextFileNameW.FindNextFileNameW    = GetFunction(0, "FindNextFileNameW")
  CloseLibrary(0)
EndIf

Define.i NameSize, hSearch
Define.s FileName, Volume
Define *Name
Define NewList Links.s()

*Name = AllocateMemory(#MAX_PATH*2) : NameSize = MemorySize(*Name)

FileName = OpenFileRequester("Examine hard link", "", "", 0)
If FileName
  Volume = Left(FileName, 2)
  hSearch = FindFirstFileNameW(FileName, 0, @NameSize, *Name)
  If hSearch > 0
    AddElement(Links()) : Links() = Volume + PeekS(*Name)
    FreeMemory(*Name) : *Name = AllocateMemory(#MAX_PATH*2) : NameSize = MemorySize(*Name)
    While FindNextFileNameW(hSearch, @NameSize, *Name)
      AddElement(Links()) : Links() = Volume + PeekS(*Name)
      FreeMemory(*Name) : *Name = AllocateMemory(#MAX_PATH*2) : NameSize = MemorySize(*Name)
    Wend
    FindClose_(hSearch)
  EndIf
  If ListSize(Links()) > 1
    ResetList(Links())
    ForEach Links()
      Debug Links()
    Next
  Else
    Debug "No hard links found"
  EndIf
Else
  End 1
EndIf

End 0

Re: Enumerate hard links (Windows)

Posted: Tue Mar 24, 2015 8:19 am
by infratec
Hi,

isn't it working also without unicode mode when you use

Code: Select all

PeekS(*Name, -1, #PB_Unicode)
But since I don't know how to test it ...
Is there a file which is always hard linked ?

Bernd

Re: Enumerate hard links (Windows)

Posted: Tue Mar 24, 2015 8:45 am
by bbanelli
infratec wrote:Hi,

isn't it working also without unicode mode when you use

Code: Select all

PeekS(*Name, -1, #PB_Unicode)
Note the W after function names, there is no A version of these functions, so you can't compile without Unicode support. Well, you can compile, but it won't work. :)
Is there a file which is always hard linked ?
You can always make your own on Windows with mklink tool.

Re: Enumerate hard links (Windows)

Posted: Tue Mar 24, 2015 1:33 pm
by hallodri
You have a memory leak. ;)
Used p-unicode and follow the advice of infratec, and it also works in ASCII mode.

@infratec

Code: Select all

C:\Windows\Cursors\aero_link.cur

Re: Enumerate hard links (Windows)

Posted: Tue Mar 24, 2015 2:36 pm
by bbanelli
hallodri wrote:You have a memory leak. ;)
:cry: Where?

I have used FindClose_(hSearch), could you tell which line(s) is(are) problematic?
Used p-unicode and follow the advice of infratec, and it also works in ASCII mode.
It is still not working if compiled in ASCII, I have tried with:

Code: Select all

Prototype.i FindFirstFileNameW(lpFileName.p-ascii, dwFlags.i, *StringLength, LinkName.p-ascii)
Prototype.i FindNextFileNameW(hFindStream.i, *StringLength, LinkName.p-ascii)
Can you post code where it works for you?

Re: Enumerate hard links (Windows)

Posted: Tue Mar 24, 2015 2:51 pm
by hallodri
Use p-unicode, not p-ascii.

The memoryleak can find you here :

Code: Select all

While FindNextFileNameW(hSearch, @NameSize, *Name)
      AddElement(Links()) : Links() = Volume + PeekS(*Name)
      FreeMemory(*Name) : *Name = AllocateMemory(#MAX_PATH*2) : NameSize = MemorySize(*Name)
    Wend
FreeMemory is not called when the loop is exited. You can use normal strings:

Code: Select all

NameSize = #MAX_PATH * 2
Name.s = space(NameSize)

Re: Enumerate hard links (Windows)

Posted: Tue Mar 24, 2015 3:45 pm
by infratec
Hi,

Code: Select all

Prototype.i FindFirstFileNameW(lpFileName.p-Unicode, dwFlags.i, *StringLength, *LinkName)
is enough.
And, of course,

Code: Select all

PeekS(*Name, -1, #PB_Unicode)
Why you always release and allocate memory?
Why not FillMemory() to 'free' it.
Than you can release the memory at the end.

Bernd

Re: Enumerate hard links (Windows)

Posted: Tue Mar 24, 2015 6:15 pm
by bbanelli
hallodri wrote:Use p-unicode, not p-ascii.
Ups, sorrr! Great, seems to work now in both Unicode and ASCII.

Is there any undefined behavior is code is not compiled in Unicode and W functions are used?
FreeMemory is not called when the loop is exited. You can use normal strings:
Oh well. That's true, but why would you call it a "leek", since I just didn't explicitly freed memory allocation, since it will already be done on the end of this particular code? I didn't write FreeList() either, for that matter... :)
infratec wrote:Hi,

Code: Select all

Prototype.i FindFirstFileNameW(lpFileName.p-Unicode, dwFlags.i, *StringLength, *LinkName)
is enough.
And, of course,

Code: Select all

PeekS(*Name, -1, #PB_Unicode)
Why you always release and allocate memory?
Why not FillMemory() to 'free' it.
Than you can release the memory at the end.

Bernd
Hi infratec,

I'll modify first post. I thought "freeing" memory is cheaper than filling it with zeroes. Or am I wrong?

Re: Enumerate hard links (Windows)

Posted: Tue Mar 24, 2015 8:07 pm
by infratec
Hi,

if you don't use the #PB_Memory_NoClear flag, a FillMemory() is done.
So FillMemory() only is faster (in my opinion).
But is necessary?
I think you don't need this stuff, since a new string is always written with the terminating 0.
You don't need to erase the buffer before.

Bernd

Re: Enumerate hard links (Windows)

Posted: Wed Mar 25, 2015 10:44 am
by Kwai chang caine
Work fine here on W7

Very interesting, thanks to you i know now the Symbolic/Hard/Junction link :shock:

Thanks for sharing 8)