Creating a hard link

Windows specific forum
Bitblazer
Enthusiast
Enthusiast
Posts: 736
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Creating a hard link

Post by Bitblazer »

The hard link requirements by microsoft for windows are : NTFS file system V5 or above, administrator rights to create them, with win32 API : CreateHardLinkW or via commandline "{systemfolder}\cmd.exe /q /s mklink /h" (its a standard cmd.exe internal command with recent windows versions). I tried both methods and try to get a clean simple win32 api method running, but no matter which kind of string passing or pototype for import i use, i always get the result of "failed" with a lasterror() of 2 (see error codes). I tried pointers and direct argument passing as p-utf8, p-unicode and string on PB 5.62 x86. The NTFS versions are the latest official, so it should be above Ver. 5. My OS is Windows7 x64, i wonder if i have to use the 64bit PB 5.62 version :(

Any hint why it does'nt work?

The snippet was comiled in a project with admin rights and i get the UAC confirmation request so that should be fine.

Code: Select all

Import "Kernel32.lib"
  CreateHardLinkW(lpLinkFileName.p-unicode, lpExistingFileName.p-unicode, lpSecurityAttributes.i = 0)
  GetLastError.i()
EndImport

EnableExplicit

Define LinkResult.i, ErrorCode.i = 0

Debug "link test"

LinkResult = CreateHardLinkW("e:\linktest.exe", "e:\streamwriter.exe")
If (LinkResult = 0)
  Debug "Ein fehler ist aufgetreten"
  ErrorCode = GetLastError()
EndIf
Debug "Ergebnis war " + Str(LinkResult) + " ErrorCode = " + Str(ErrorCode)
ignore the german text, it should be irrelevant to the problem :)
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: Creating a hard link

Post by RSBasic »

My code works:

Code: Select all

EnableExplicit

Define lpFileName$
Define lpExistingFileName$

If OpenLibrary(0, "Kernel32.dll")
  Prototype CreateHardLink(lpFileName, lpExistingFileName, lpSecurityAttributes)
  Define CreateHardLink.CreateHardLink = GetFunction(0, "CreateHardLinkW")
  CloseLibrary(0)
EndIf

lpFileName$ = "D:\Hardlink.png"
lpExistingFileName$ = "D:\Originalfile.png"

If CreateHardLink(@lpFileName$, @lpExistingFileName$, 0)
  MessageRequester("", "Hard link was created.", 0)
Else
  MessageRequester("", "Hard link could not be created.", 0)
EndIf
Tested with x86 (Unicode) and x64 (Unicode).
Image
Image
fryquez
Enthusiast
Enthusiast
Posts: 367
Joined: Mon Dec 21, 2015 8:12 pm

Re: Creating a hard link

Post by fryquez »

Works fine here, even without admin rights. What error code do you get?
User avatar
skywalk
Addict
Addict
Posts: 3994
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Creating a hard link

Post by skywalk »

Both codes work. v562 x64 on Windows 10 Pro.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Bitblazer
Enthusiast
Enthusiast
Posts: 736
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: Creating a hard link

Post by Bitblazer »

Thanks for the help. I am still not sure why my attempt with the .lib didnt work, but the method with .dll works even without admin mode in win7 x64. That's a definitive plus and to make this reply useful for others, here is a cleaned up and re-useable snippet for general use. Thanks again :)

Code snippet to create a hard link to a file

Code: Select all

EnableExplicit

Define LibraryID.i
Prototype CreateHardLink_Type(lpFileName, lpExistingFileName, lpSecurityAttributes)
Global CreateHardLink.CreateHardLink_Type = GetFunction(0, "CreateHardLinkW")

Procedure.i CreateLink(lpFileName$, lpExistingFileName$)
  Define Result.i
  
  Result = CreateHardLink(@lpFileName$, @lpExistingFileName$, 0)
  
  ProcedureReturn Result
EndProcedure

LibraryID = OpenLibrary(#PB_Any, "Kernel32.dll")

If (LibraryID = 0)
  MessageRequester("Fatal error!", "Could not open kernel32.dll" + Chr(10) + "this should not be possible.", #PB_MessageRequester_Error | #PB_MessageRequester_Ok)
  End 999
EndIf

CreateHardLink = GetFunction(LibraryID, "CreateHardLinkW")
CloseLibrary(LibraryID)
LibraryID = 0

CreateLink("e:\zz_linktest.jpg", "e:\testpicture.jpg")
MessageRequester("Success!", "Link 'zz_linktest.jpg' created", #PB_MessageRequester_Ok | #PB_MessageRequester_Info)
Post Reply