How To Create Hard Symbolic Links in Windows NT

Last reviewed: December 16, 1996
Article ID: Q153181
The information in this article applies to:
  • Microsoft Win32 Application Programming Interface (API) included with Microsoft Windows NT, versions 3.51, 4.0

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



THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: December 16, 1996
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.