ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mklink.c
Go to the documentation of this file.
00001 /*
00002  *  MKLINK.C - mklink internal command.
00003  */
00004 
00005 #include <precomp.h>
00006 
00007 #ifdef INCLUDE_CMD_MKLINK
00008 
00009 /* There is no API for creating junctions, so we must do it the hard way */
00010 static BOOL CreateJunction(LPCTSTR LinkName, LPCTSTR TargetName)
00011 {
00012     /* Structure for reparse point daya when ReparseTag is one of
00013      * the tags defined by Microsoft. Copied from MinGW winnt.h */
00014     typedef struct _REPARSE_DATA_BUFFER {
00015         DWORD  ReparseTag;
00016         WORD   ReparseDataLength;
00017         WORD   Reserved;
00018         _ANONYMOUS_UNION union {
00019             struct {
00020                 WORD   SubstituteNameOffset;
00021                 WORD   SubstituteNameLength;
00022                 WORD   PrintNameOffset;
00023                 WORD   PrintNameLength;
00024                 ULONG  Flags;
00025                 WCHAR PathBuffer[1];
00026             } SymbolicLinkReparseBuffer;
00027             struct {
00028                 WORD   SubstituteNameOffset;
00029                 WORD   SubstituteNameLength;
00030                 WORD   PrintNameOffset;
00031                 WORD   PrintNameLength;
00032                 WCHAR PathBuffer[1];
00033             } MountPointReparseBuffer;
00034             struct {
00035                 BYTE   DataBuffer[1];
00036             } GenericReparseBuffer;
00037         } DUMMYUNIONNAME;
00038     } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
00039 
00040     HMODULE hNTDLL = GetModuleHandle(_T("NTDLL"));
00041     BOOLEAN (WINAPI *RtlDosPathNameToNtPathName_U)(PCWSTR, PUNICODE_STRING, PCWSTR *, CURDIR *)
00042         = (BOOLEAN (WINAPI *)(PCWSTR, PUNICODE_STRING, PCWSTR *, CURDIR *))GetProcAddress(hNTDLL, "RtlDosPathNameToNtPathName_U");
00043     VOID (WINAPI *RtlFreeUnicodeString)(PUNICODE_STRING)
00044         = (VOID (WINAPI *)(PUNICODE_STRING))GetProcAddress(hNTDLL, "RtlFreeUnicodeString");
00045 
00046     TCHAR TargetFullPath[MAX_PATH];
00047 #ifdef UNICODE
00048 #define TargetFullPathW TargetFullPath
00049 #else
00050     WCHAR TargetFullPathW[MAX_PATH];
00051 #endif
00052     UNICODE_STRING TargetNTPath;
00053     HANDLE hJunction;
00054 
00055     /* The data for this kind of reparse point has two strings:
00056      * The first ("SubstituteName") is the full target path in NT format,
00057      * the second ("PrintName") is the full target path in Win32 format.
00058      * Both of these must be wide-character strings. */
00059     if (!RtlDosPathNameToNtPathName_U ||
00060         !RtlFreeUnicodeString ||
00061         !GetFullPathName(TargetName, MAX_PATH, TargetFullPath, NULL) ||
00062 #ifndef UNICODE
00063         !MultiByteToWideChar(CP_ACP, 0, TargetFullPath, -1, TargetFullPathW, -1) ||
00064 #endif
00065         !RtlDosPathNameToNtPathName_U(TargetFullPathW, &TargetNTPath, NULL, NULL))
00066     {
00067         return FALSE;
00068     }
00069 
00070     /* We have both the names we need, so time to create the junction.
00071      * Start with an empty directory */
00072     if (!CreateDirectory(LinkName, NULL))
00073     {
00074         RtlFreeUnicodeString(&TargetNTPath);
00075         return FALSE;
00076     }
00077 
00078     /* Open the directory we just created */
00079     hJunction = CreateFile(LinkName, GENERIC_WRITE, 0, NULL,
00080         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
00081     if (hJunction != INVALID_HANDLE_VALUE)
00082     {
00083         /* Allocate a buffer large enough to hold both strings, including trailing NULs */
00084         SIZE_T TargetLen = wcslen(TargetFullPathW) * sizeof(WCHAR);
00085         DWORD DataSize = (DWORD)(FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer)
00086                           + TargetNTPath.Length + sizeof(WCHAR)
00087                           + TargetLen           + sizeof(WCHAR));
00088         PREPARSE_DATA_BUFFER Data = _alloca(DataSize);
00089 
00090         /* Fill it out and use it to turn the directory into a reparse point */
00091         Data->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
00092         Data->ReparseDataLength = (WORD)(DataSize - FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer));
00093         Data->Reserved = 0;
00094         Data->MountPointReparseBuffer.SubstituteNameOffset = 0;
00095         Data->MountPointReparseBuffer.SubstituteNameLength = TargetNTPath.Length;
00096         wcscpy(Data->MountPointReparseBuffer.PathBuffer,
00097                TargetNTPath.Buffer);
00098         Data->MountPointReparseBuffer.PrintNameOffset = TargetNTPath.Length + sizeof(WCHAR);
00099         Data->MountPointReparseBuffer.PrintNameLength = (USHORT)TargetLen;
00100         wcscpy((WCHAR *)((BYTE *)Data->MountPointReparseBuffer.PathBuffer
00101                          + Data->MountPointReparseBuffer.PrintNameOffset),
00102                TargetFullPathW);
00103         if (DeviceIoControl(hJunction, FSCTL_SET_REPARSE_POINT,
00104                             Data, DataSize, NULL, 0, &DataSize, NULL))
00105         {
00106             /* Success */
00107             CloseHandle(hJunction);
00108             RtlFreeUnicodeString(&TargetNTPath);
00109             return TRUE;
00110         }
00111         CloseHandle(hJunction);
00112     }
00113     RemoveDirectory(LinkName);
00114     RtlFreeUnicodeString(&TargetNTPath);
00115     return FALSE;
00116 }
00117 
00118 INT
00119 cmd_mklink(LPTSTR param)
00120 {
00121     HMODULE hKernel32 = GetModuleHandle(_T("KERNEL32"));
00122     DWORD Flags = 0;
00123     enum { SYMBOLIC, HARD, JUNCTION } LinkType = SYMBOLIC;
00124     INT NumFiles = 0;
00125     LPTSTR Name[2];
00126     INT argc, i;
00127     LPTSTR *arg;
00128 
00129     if (!_tcsncmp(param, _T("/?"), 2))
00130     {
00131         ConOutResPuts(STRING_MKLINK_HELP);
00132         return 0;
00133     }
00134 
00135     arg = split(param, &argc, FALSE, FALSE);
00136     for (i = 0; i < argc; i++)
00137     {
00138         if (arg[i][0] == _T('/'))
00139         {
00140             if (!_tcsicmp(arg[i], _T("/D")))
00141                 Flags |= 1; /* SYMBOLIC_LINK_FLAG_DIRECTORY */
00142             else if (!_tcsicmp(arg[i], _T("/H")))
00143                 LinkType = HARD;
00144             else if (!_tcsicmp(arg[i], _T("/J")))
00145                 LinkType = JUNCTION;
00146             else
00147             {
00148                 error_invalid_switch(arg[i][1]);
00149                 freep(arg);
00150                 return 1;
00151             }
00152         }
00153         else
00154         {
00155             if (NumFiles == 2)
00156             {
00157                 error_too_many_parameters(arg[i]);
00158                 freep(arg);
00159                 return 1;
00160             }
00161             Name[NumFiles++] = arg[i];
00162         }
00163     }
00164     freep(arg);
00165 
00166     if (NumFiles != 2)
00167     {
00168         error_req_param_missing();
00169         return 1;
00170     }
00171 
00172     nErrorLevel = 0;
00173 
00174     if (LinkType == SYMBOLIC)
00175     {
00176         /* CreateSymbolicLink doesn't exist in old versions of Windows,
00177          * so load dynamically */
00178         BOOL (WINAPI *CreateSymbolicLink)(LPCTSTR, LPCTSTR, DWORD)
00179 #ifdef UNICODE
00180             = (BOOL (WINAPI *)(LPCTSTR, LPCTSTR, DWORD))GetProcAddress(hKernel32, "CreateSymbolicLinkW");
00181 #else
00182             = (BOOL (WINAPI *)(LPCTSTR, LPCTSTR, DWORD))GetProcAddress(hKernel32, "CreateSymbolicLinkA");
00183 #endif
00184         if (CreateSymbolicLink && CreateSymbolicLink(Name[0], Name[1], Flags))
00185         {
00186             ConOutResPrintf(STRING_MKLINK_CREATED_SYMBOLIC, Name[0], Name[1]);
00187             return 0;
00188         }
00189     }
00190     else if (LinkType == HARD)
00191     {
00192         /* CreateHardLink doesn't exist in old versions of Windows,
00193          * so load dynamically */
00194         BOOL (WINAPI *CreateHardLink)(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES)
00195 #ifdef UNICODE
00196             = (BOOL (WINAPI *)(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES))GetProcAddress(hKernel32, "CreateHardLinkW");
00197 #else
00198             = (BOOL (WINAPI *)(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES))GetProcAddress(hKernel32, "CreateHardLinkA");
00199 #endif
00200         if (CreateHardLink && CreateHardLink(Name[0], Name[1], NULL))
00201         {
00202             ConOutResPrintf(STRING_MKLINK_CREATED_HARD, Name[0], Name[1]);
00203             return 0;
00204         }
00205     }
00206     else
00207     {
00208         if (CreateJunction(Name[0], Name[1]))
00209         {
00210             ConOutResPrintf(STRING_MKLINK_CREATED_JUNCTION, Name[0], Name[1]);
00211             return 0;
00212         }
00213     }
00214 
00215     ErrorMessage(GetLastError(), _T("MKLINK"));
00216     return 1;
00217 }
00218 
00219 #endif /* INCLUDE_CMD_MKLINK */

Generated on Sun May 27 2012 04:18:13 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.