How To Create Hard Symbolic Links in Windows NT

ID: Q153181

3.51 4.00 WINDOWS NT kbprg kbhowto

The information in this article applies to:

SUMMARY

Windows NT supports hard symbolic links on NTFS disk volumes for Posix compatibility. This article describes how to use the two programmatic approaches that exist for creating hard symbolic links in Windows NT:

1. Write a Posix application that uses the link() call. Use the Posix

   development files included with the Win32 SDK to build a Posix
   application.

2. Use the Win32 BackupWrite() function to construct a hard symbolic link.

Hard symbolic links and the files they reference must reside on the same NTFS volume; a link cannot reference a file on another volume. That is, a link cannot span multiple volumes.

 MORE INFORMATION

Sample Code

/*++

Copyright (c) 1996 Microsoft Corporation

Module Name:

   ln.c

Abstract:

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

NOTE: The new link filename path must be supplied to the BackupWrite() Win32 API call in Unicode.

--*/

#ifndef UNICODE

#define UNICODE
#define _UNICODE
#endif

#include <windows.h>
#include <stdio.h>

#define RTN_OK 0
#define RTN_USAGE 1
#define RTN_ERROR 13

int __cdecl wmain(
    int argc,
    wchar_t *argv[]
    )
{
    LPTSTR 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 <existing_source_file> <link_file>\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;
}

KBCategory: kbprg kbhowto KBSubcategory: BseFileIo BseMisc CodeSam Additional reference words: 3.51 4.00 ln link symbolic

Keywords          : kbnokeyword kbAPI kbKernBase CodeSam kbGrpKernBase 
Version           : 3.51 4.00
Platform          : NT WINDOWS

Last Reviewed: December 18, 1996