Microsoft KB Archive/234727

{|
 * width="100%"|

HOWTO: Create Hard Links in Windows NT and Windows 2000

 * }

Q234727

-

The information in this article applies to:


 * Microsoft Win32 Application Programming Interface (API), included with:
 * Microsoft Windows NT Server versions 3.51, 4.0
 * Microsoft Windows NT Workstation versions 3.51, 4.0
 * the operating system: Microsoft Windows 2000

-

SUMMARY
Windows NT and Windows 2000 support hard links on NTFS disk volumes. Following are two programmatic approaches that exist for creating hard links:


 * 1) Use CreateHardLink in Windows 2000.
 * 2) Use the Win32 BackupWrite function to construct a hard link in Windows NT and Windows 2000.

If your application requires Windows 2000, use method one because it is simpler; if your application must run on Windows NT and Windows 2000, you should use method two. The remainder of this article provides more detailed information about hard links and how to create them with both methods.

MORE INFORMATION
A hard link is a directory entry for a file. Every file can be considered to have at least one hard link. On NTFS volumes, each file can have multiple hard links, and thus a single file can appear in many directories (or even in the same directory with different names). Since all of the links reference the same file, applications can open any of the links and modify the file. A file is deleted from the file system only after all links to it have been deleted. Once a hard link is created, applications can use it like any other file name. Therefore, you can use the full Win32 file I/O API to access a file through a link. The changes made to a file through one link will be reflected by all other links (because they point to the same file). To remove a link use DeleteFile. Hard links are supported on NTFS only; they may not be created on FAT or FAT32 volumes. In addition, a hard link must reside on the same volume as the file it references. You cannot create a hard link on one volume that points to a file on another volume. This is because a hard link is a directory entry that points to a file.

The security descriptor for a file belongs to the file, not the links that reference it. Thus, all links to a file grant the same access to the file. If the security descriptor for the file is changed by using one link, all other links will reflect that change.

The hard links created with BackupWrite and CreateHardLink are identical; the only difference is in the functions the applications call to create them. Creating hard links with BackupWrite is supported on Windows 2000 and should be used when your application must also run on Windows NT version 4.0 and earlier. If your application is designed to run on Windows 2000, use CreateHardLink because it is easier to use.

CreateHardLink Example
The following code snippet demonstrates how to call CreateHardLink so that it doesn't modify the file's security descriptor.

/* Set security descriptor argument to NULL to leave file's security descriptor alone. fCreatedLink = CreateHardLink (pszNewLinkName, pszExistingFileName,                               NULL); if (!fCreatedLink) // error occurred, handle it. NOTE: PszExistingFileName can be the original filename, or any already-existing link to the file. After this code is executed, pszNewLinkName will refer to the file.

BackupWrite Example
The following sample code demonstrates how to use BackupWrite to create a hard link on an NTFS volume. Basically, it "restores" a link to the file.

/*++

Copyright (c) 1996-1999 Microsoft Corporation

Module Name:

ln.c

Abstract:

This module illustrates how to use the Win32 BackupWrite API to create hard links.

NOTE: The new link file name path must be supplied to the BackupWriteWin32 API call in Unicode.

--*/


 * 1) ifndef UNICODE
 * 2) define UNICODE
 * 3) define _UNICODE
 * 4) endif


 * 1) include 
 * 2) include 


 * 1) define RTN_OK 0
 * 2) define RTN_USAGE 1
 * 3) define RTN_ERROR 13

int __cdecl wmain( int argc, wchar_t *argv[] ) {  LPWSTR FileSource; WCHAR FileLink[ MAX_PATH + 1 ]; LPWSTR FilePart;

HANDLE hFileSource;

WIN32_STREAM_ID StreamId; DWORD dwBytesWritten; LPVOID lpContext; DWORD cbPathLen; DWORD StreamHeaderSize;

BOOL bSuccess;

if (argc != 3) {     printf("Usage: %ls  \n",             argv[0]); return RTN_USAGE; }

FileSource = argv[1];

//   // open existing file that we link to   // hFileSource = CreateFile(                          FileSource,                           FILE_WRITE_ATTRIBUTES,                           FILE_SHARE_READ | FILE_SHARE_WRITE                           | FILE_SHARE_DELETE,                           NULL, // sa                           OPEN_EXISTING,                           0,                           NULL                           );

if (hFileSource == INVALID_HANDLE_VALUE) {     printf("CreateFile (source) error! (rc=%lu)\n", GetLastError); return RTN_ERROR; }

//   // validate and sanitize supplied link path and use the result // the full path MUST be Unicode for BackupWrite //   cbPathLen = GetFullPathNameW( argv[2], MAX_PATH, FileLink, &FilePart);

if (cbPathLen == 0) {     printf("GetFullPathName error! (rc=%lu)\n", GetLastError); return RTN_ERROR; }

cbPathLen = (cbPathLen + 1) * sizeof(WCHAR); // adjust for byte count

//   // it might also be a good idea to verify the existence of the link, // (and possibly bail), as the file specified in FileLink will be  // overwritten if it already exists //

//   // prepare and write the WIN32_STREAM_ID out //   lpContext = NULL;

StreamId.dwStreamId = BACKUP_LINK; StreamId.dwStreamAttributes = 0; StreamId.dwStreamNameSize = 0; StreamId.Size.HighPart = 0; StreamId.Size.LowPart = cbPathLen;

//   // compute length of variable size WIN32_STREAM_ID //   StreamHeaderSize = (LPBYTE)&StreamId.cStreamName - (LPBYTE)& StreamId+ StreamId.dwStreamNameSize ;

bSuccess = BackupWrite(                        hFileSource,                         (LPBYTE)&StreamId,  // buffer to write                         StreamHeaderSize,   // number of bytes to write                         &dwBytesWritten,                         FALSE,              // don't abort yet                         FALSE,              // don't process security                         &lpContext                         );

if (bSuccess) {

//      // write out the buffer containing the path //      bSuccess = BackupWrite(                            hFileSource,                            (LPBYTE)FileLink,   // buffer to write                            cbPathLen,          // number of bytes to write                            &dwBytesWritten,                            FALSE,              // don't abort yet                            FALSE,              // don't process security                            &lpContext                            );

//      // free context //      BackupWrite(                 hFileSource,                 NULL,               // buffer to write                 0,                  // number of bytes to write                 &dwBytesWritten,                 TRUE,               // abort                 FALSE,              // don't process security                 &lpContext                 ); }

CloseHandle( hFileSource );

if (!bSuccess) {     printf("BackupWrite error! (rc=%lu)\n", GetLastError); return RTN_ERROR; }

return RTN_OK; } Additional query words: ln link symbolic hard POSIX

Keywords : kbAPI kbFileIO kbKernBase kbOSWinNT351 kbOSWinNT400 kbOSWin2000 kbFAQ kbDSupport kbGrpDSKernBase

Issue type : kbhowto

Technology : kbAudDeveloper kbWin32sSearch kbWin32API