2015-03-27 1 views
0

J'essaye de le faire en utilisant Visual C++. Ce code semble créer une jonction, avec l'ensemble cible correcte, mais la jonction a une taille de 0 et quand je clique dessus j'obtenir:Problème lors de la création de la jonction de répertoire Windows NTFS en C/C++

error message

Voici le code:

#include "stdafx.h" 
#include <stdio.h> 
#include <tchar.h> 
#include <ole2.h> 
#include <errno.h> 

typedef struct _REPARSE_DATA_BUFFER { 
    ULONG ReparseTag; 
    USHORT ReparseDataLength; 
    USHORT Reserved; 
    union { 
     struct { 
      USHORT SubstituteNameOffset; 
      USHORT SubstituteNameLength; 
      USHORT PrintNameOffset; 
      USHORT PrintNameLength; 
      ULONG Flags; 
      WCHAR PathBuffer[1]; 
     } SymbolicLinkReparseBuffer; 
     struct { 
      USHORT SubstituteNameOffset; 
      USHORT SubstituteNameLength; 
      USHORT PrintNameOffset; 
      USHORT PrintNameLength; 
      WCHAR PathBuffer[1]; 
     } MountPointReparseBuffer; 
     struct { 
      UCHAR DataBuffer[1]; 
     } GenericReparseBuffer; 
    }; 
} REPARSE_DATA_BUFFER; 

#define REPARSE_MOUNTPOINT_HEADER_SIZE 8 

bool createJunction(WCHAR *linkPath, WCHAR *newTargetPath) { 
    int create_status = CreateDirectory(linkPath, NULL); 

    // If the directory already existed, treat it as a success. 
    if (create_status == 0 && (GetLastError() != ERROR_ALREADY_EXISTS || (GetFileAttributesW(linkPath) & FILE_ATTRIBUTE_DIRECTORY) != 0)) 
     return false; 

    HANDLE handle = CreateFile(linkPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); 
    if (handle == INVALID_HANDLE_VALUE) 
    { 
     _tprintf(_T("Could not open dir '%s'; error: %d\n"), linkPath, GetLastError()); 
     CloseHandle(handle); 
     return false; 
    } 

    int target_len = wcslen(newTargetPath); 
    if (target_len > MAX_PATH - 1) { 
     CloseHandle(handle); 
     return false; 
    } 

    int reparse_data_buffer_size = sizeof REPARSE_DATA_BUFFER + 2 * MAX_PATH * sizeof WCHAR; 
    REPARSE_DATA_BUFFER* reparse_data_buffer = static_cast<REPARSE_DATA_BUFFER*>(calloc(reparse_data_buffer_size, 1)); 

    reparse_data_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; 
    wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer, newTargetPath); 
    wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer + target_len + 1, newTargetPath); 
    reparse_data_buffer->MountPointReparseBuffer.SubstituteNameOffset = 0; 
    reparse_data_buffer->MountPointReparseBuffer.SubstituteNameLength = target_len * sizeof(WCHAR); 
    reparse_data_buffer->MountPointReparseBuffer.PrintNameOffset = (target_len + 1) * sizeof(WCHAR); 
    reparse_data_buffer->MountPointReparseBuffer.PrintNameLength = target_len * sizeof(WCHAR); 
    reparse_data_buffer->ReparseDataLength = (target_len + 1) * 2 * sizeof(WCHAR) + REPARSE_MOUNTPOINT_HEADER_SIZE; 

    DWORD dummy_received_bytes; 
    int result = DeviceIoControl(
     handle, 
     FSCTL_SET_REPARSE_POINT, 
     reparse_data_buffer, 
     reparse_data_buffer->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE, 
     NULL, 
     0, 
     &dummy_received_bytes, 
     NULL); 
    if (CloseHandle(handle) == 0) 
     return false; 
    free(reparse_data_buffer); 

    return (result != 0); 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    createJunction(L"C:\\Users\\Weston\\Desktop\\New folder\\Junction of asdf", L"C:\\Users\\Weston\\Desktop\\New folder\\asdf"); 

    _tprintf(_T("Execution complete.\n")); 
    getchar(); 
} 

Je suis presque sûr que je ne mets pas la taille correctement quelque part, mais je ne sais pas quoi et où. Il n'y a aucune erreur ou avertissement, la jonction semble simplement être créée (avec le nom et la cible corrects et le type de jonction) avec une taille de 0.

+0

La page MSDN a des commentaires indiquant, entre autres, que « Un chemin jonction/point_de_montage doit commencer par « \ ?? \ »(SC_Win32ReparsePrefix) et se référer à un volume connu sur le système local. Dans le cas contraire erreur ERROR_INVALID_REPARSE_DATA est Le chemin d'accès peut contenir une lettre de lecteur ou un guide de volume, suivi d'un sous-répertoire. " –

+0

Préfixer la cible avec ceci, mais maintenant la jonction semble se lier à elle-même plutôt qu'à la cible, bien que la cible semble correcte dans les propriétés. Je suppose que je ne le fais pas bien: \ – Wes

+0

Attends j'ai trouvé ce que je faisais mal. Allez-y et affichez cela comme la réponse. – Wes

Répondre

0

Ne pas préfixer le chemin cible avec \??\. Ce faisant, c'était tout ce que je devais faire.