Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmklink.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
1.7.6.1
|