// Create a symbolic link at "newpath" that points to "oldpath". // Throws "NotSupportedException" if the filesystem does not // support the creation of symbolic links or ".lnk" files. public static void CreateLink(String oldpath, String newpath) { // Validate and normalize the parameters. Directory.ValidatePath(oldpath); Directory.ValidatePath(newpath); oldpath = Path.NormalizeSeparators(oldpath); newpath = Path.NormalizeSeparators(newpath); // Try to create the symlink using the engine. Errno error = FileMethods.CreateLink(oldpath, newpath); if (error == Errno.Success) { return; } else if (error != Errno.EPERM) { Directory.HandleErrorsFile(error); } // Bail out if we are not on Windows. if (!IsWindows()) { throw new NotSupportedException(_("IO_NotSupp_Symlinks")); } // Make sure that we have ".lnk" on the end of the pathname. if (!EndsInLnk(newpath)) { if (FileMethods.GetFileType(newpath) != FileType.unknown) { // There already exists something at this location. Directory.HandleErrorsFile(Errno.EEXIST); } newpath += ".lnk"; } if (FileMethods.GetFileType(newpath) != FileType.unknown) { // There already exists something at this location. Directory.HandleErrorsFile(Errno.EEXIST); } // Create the shortcut information to place in the file. ShortcutInformation info = new ShortcutInformation(); info.Description = oldpath; info.RelativePath = oldpath; info.ShowWindow = ShowWindow.Normal; // Write the shortcut information to the file. WriteShortcut(newpath, info, false); }
// Write a Windows shortcut file. If "createIfExists" is "false", // then an exception will be thrown if "pathname" already exists. public static void WriteShortcut(String pathname, ShortcutInformation info, bool createIfExists) { // Validate the "info" parameter. if(info == null) { throw new ArgumentNullException("info"); } // Create the shortcut file stream. FileStream stream = new FileStream (pathname, (createIfExists ? FileMode.Create : FileMode.CreateNew), FileAccess.Write); byte[] buffer = new byte [64]; try { // Write the magic number to the file. stream.Write(magic, 0, 20); // Determine the flags to put in the file header. uint flags = 0; if(info.ShellIdInfo != null) { flags |= 0x0001; } if(info.FileLocationInfo != null) { flags |= 0x0002; } if(info.Description != null) { flags |= 0x0004; } if(info.RelativePath != null) { flags |= 0x0008; } if(info.WorkingDirectory != null) { flags |= 0x0010; } if(info.CommandLineArguments != null) { flags |= 0x0020; } if(info.Icon != null) { flags |= 0x0040; } if(info.Rest != null) { flags |= 0x0080; } // Write out the file header. WriteUInt32(stream, buffer, flags); WriteUInt32(stream, buffer, (uint)(info.Attributes)); WriteFileTime(stream, buffer, info.CreationTime); WriteFileTime(stream, buffer, info.ModificationTime); WriteFileTime(stream, buffer, info.LastAccessTime); WriteUInt32(stream, buffer, info.FileLength); WriteUInt32(stream, buffer, info.IconNumber); WriteUInt32(stream, buffer, (uint)(info.ShowWindow)); WriteUInt32(stream, buffer, info.Hotkey); WriteUInt32(stream, buffer, 0); // reserved WriteUInt32(stream, buffer, 0); // reserved // Write the shell item id information. if(info.ShellIdInfo != null) { WriteInt16(stream, buffer, info.ShellIdInfo.Length); stream.Write(info.ShellIdInfo, 0, info.ShellIdInfo.Length); } // Write the file location information. if(info.FileLocationInfo != null) { stream.Write(info.FileLocationInfo, 0, info.FileLocationInfo.Length); } // Write the string information. if(info.Description != null) { WriteString(stream, buffer, info.Description); } if(info.RelativePath != null) { WriteString(stream, buffer, info.RelativePath); } if(info.WorkingDirectory != null) { WriteString(stream, buffer, info.WorkingDirectory); } if(info.CommandLineArguments != null) { WriteString(stream, buffer, info.CommandLineArguments); } if(info.Icon != null) { WriteString(stream, buffer, info.Icon); } // Write the rest of the data for the shortcut file. if(info.Rest != null) { stream.Write(info.Rest, 0, info.Rest.Length); } } finally { stream.Close(); } }
// Read the contents of a Windows shortcut file. Returns null if // the file does not appear to be a shortcut, or throws an exception // if the pathname is invalid in some fashion. public static ShortcutInformation ReadShortcut(String pathname) { byte[] buffer = new byte [64]; ShortcutInformation info = new ShortcutInformation(); int posn; // Open the shortcut file. FileStream stream = new FileStream (pathname, FileMode.Open, FileAccess.Read); try { // Check the magic number in the header. if(stream.Read(buffer, 0, 20) != 20) { return null; } for(posn = 0; posn < 20; ++posn) { if(buffer[posn] != magic[posn]) { return null; } } // Read the rest of the header and decode it. uint flags = ReadUInt32(stream, buffer); info.Attributes = (ShortcutAttributes)(ReadUInt32(stream, buffer)); info.CreationTime = ReadFileTime(stream, buffer); info.ModificationTime = ReadFileTime(stream, buffer); info.LastAccessTime = ReadFileTime(stream, buffer); info.FileLength = ReadUInt32(stream, buffer); info.IconNumber = ReadUInt32(stream, buffer); info.ShowWindow = (ShowWindow)(ReadUInt32(stream, buffer)); info.Hotkey = ReadUInt32(stream, buffer); ReadUInt32(stream, buffer); // reserved ReadUInt32(stream, buffer); // reserved // Read the shell item id list as an opaque blob. int dataLen; byte[] data; if((flags & 0x0001) != 0) { dataLen = ReadInt16(stream, buffer); data = new byte [dataLen]; stream.Read(data, 0, dataLen); info.ShellIdInfo = data; } // Read the file location information as an opaque blob. if((flags & 0x0002) != 0) { dataLen = (int)(ReadUInt32(stream, buffer)); data = new byte [dataLen + 4]; Array.Copy(buffer, 0, data, 0, 4); stream.Read(data, 4, dataLen - 4); info.FileLocationInfo = data; } // Read the string information that is present. if((flags & 0x0004) != 0) { info.Description = ReadString(stream, buffer); } if((flags & 0x0008) != 0) { info.RelativePath = ReadString(stream, buffer); } if((flags & 0x0010) != 0) { info.WorkingDirectory = ReadString(stream, buffer); } if((flags & 0x0020) != 0) { info.CommandLineArguments = ReadString(stream, buffer); } if((flags & 0x0040) != 0) { info.Icon = ReadString(stream, buffer); } // Read the rest of the file as an opaque blob. if((flags & 0x0080) != 0 && stream.CanSeek) { dataLen = (int)(stream.Length - stream.Position); if(dataLen > 0) { data = new byte [dataLen]; stream.Read(data, 0, dataLen); info.Rest = data; } } } finally { stream.Close(); } return info; }
// Create a symbolic link at "newpath" that points to "oldpath". // Throws "NotSupportedException" if the filesystem does not // support the creation of symbolic links or ".lnk" files. public static void CreateLink(String oldpath, String newpath) { // Validate and normalize the parameters. Directory.ValidatePath(oldpath); Directory.ValidatePath(newpath); oldpath = Path.NormalizeSeparators(oldpath); newpath = Path.NormalizeSeparators(newpath); // Try to create the symlink using the engine. Errno error = FileMethods.CreateLink(oldpath, newpath); if(error == Errno.Success) { return; } else if(error != Errno.EPERM) { Directory.HandleErrorsFile(error); } // Bail out if we are not on Windows. if(!IsWindows()) { throw new NotSupportedException(_("IO_NotSupp_Symlinks")); } // Make sure that we have ".lnk" on the end of the pathname. if(!EndsInLnk(newpath)) { if(FileMethods.GetFileType(newpath) != FileType.unknown) { // There already exists something at this location. Directory.HandleErrorsFile(Errno.EEXIST); } newpath += ".lnk"; } if(FileMethods.GetFileType(newpath) != FileType.unknown) { // There already exists something at this location. Directory.HandleErrorsFile(Errno.EEXIST); } // Create the shortcut information to place in the file. ShortcutInformation info = new ShortcutInformation(); info.Description = oldpath; info.RelativePath = oldpath; info.ShowWindow = ShowWindow.Normal; // Write the shortcut information to the file. WriteShortcut(newpath, info, false); }
// Write a Windows shortcut file. If "createIfExists" is "false", // then an exception will be thrown if "pathname" already exists. public static void WriteShortcut(String pathname, ShortcutInformation info, bool createIfExists) { // Validate the "info" parameter. if (info == null) { throw new ArgumentNullException("info"); } // Create the shortcut file stream. FileStream stream = new FileStream (pathname, (createIfExists ? FileMode.Create : FileMode.CreateNew), FileAccess.Write); byte[] buffer = new byte [64]; try { // Write the magic number to the file. stream.Write(magic, 0, 20); // Determine the flags to put in the file header. uint flags = 0; if (info.ShellIdInfo != null) { flags |= 0x0001; } if (info.FileLocationInfo != null) { flags |= 0x0002; } if (info.Description != null) { flags |= 0x0004; } if (info.RelativePath != null) { flags |= 0x0008; } if (info.WorkingDirectory != null) { flags |= 0x0010; } if (info.CommandLineArguments != null) { flags |= 0x0020; } if (info.Icon != null) { flags |= 0x0040; } if (info.Rest != null) { flags |= 0x0080; } // Write out the file header. WriteUInt32(stream, buffer, flags); WriteUInt32(stream, buffer, (uint)(info.Attributes)); WriteFileTime(stream, buffer, info.CreationTime); WriteFileTime(stream, buffer, info.ModificationTime); WriteFileTime(stream, buffer, info.LastAccessTime); WriteUInt32(stream, buffer, info.FileLength); WriteUInt32(stream, buffer, info.IconNumber); WriteUInt32(stream, buffer, (uint)(info.ShowWindow)); WriteUInt32(stream, buffer, info.Hotkey); WriteUInt32(stream, buffer, 0); // reserved WriteUInt32(stream, buffer, 0); // reserved // Write the shell item id information. if (info.ShellIdInfo != null) { WriteInt16(stream, buffer, info.ShellIdInfo.Length); stream.Write(info.ShellIdInfo, 0, info.ShellIdInfo.Length); } // Write the file location information. if (info.FileLocationInfo != null) { stream.Write(info.FileLocationInfo, 0, info.FileLocationInfo.Length); } // Write the string information. if (info.Description != null) { WriteString(stream, buffer, info.Description); } if (info.RelativePath != null) { WriteString(stream, buffer, info.RelativePath); } if (info.WorkingDirectory != null) { WriteString(stream, buffer, info.WorkingDirectory); } if (info.CommandLineArguments != null) { WriteString(stream, buffer, info.CommandLineArguments); } if (info.Icon != null) { WriteString(stream, buffer, info.Icon); } // Write the rest of the data for the shortcut file. if (info.Rest != null) { stream.Write(info.Rest, 0, info.Rest.Length); } } finally { stream.Close(); } }
// Read the contents of a Windows shortcut file. Returns null if // the file does not appear to be a shortcut, or throws an exception // if the pathname is invalid in some fashion. public static ShortcutInformation ReadShortcut(String pathname) { byte[] buffer = new byte [64]; ShortcutInformation info = new ShortcutInformation(); int posn; // Open the shortcut file. FileStream stream = new FileStream (pathname, FileMode.Open, FileAccess.Read); try { // Check the magic number in the header. if (stream.Read(buffer, 0, 20) != 20) { return(null); } for (posn = 0; posn < 20; ++posn) { if (buffer[posn] != magic[posn]) { return(null); } } // Read the rest of the header and decode it. uint flags = ReadUInt32(stream, buffer); info.Attributes = (ShortcutAttributes)(ReadUInt32(stream, buffer)); info.CreationTime = ReadFileTime(stream, buffer); info.ModificationTime = ReadFileTime(stream, buffer); info.LastAccessTime = ReadFileTime(stream, buffer); info.FileLength = ReadUInt32(stream, buffer); info.IconNumber = ReadUInt32(stream, buffer); info.ShowWindow = (ShowWindow)(ReadUInt32(stream, buffer)); info.Hotkey = ReadUInt32(stream, buffer); ReadUInt32(stream, buffer); // reserved ReadUInt32(stream, buffer); // reserved // Read the shell item id list as an opaque blob. int dataLen; byte[] data; if ((flags & 0x0001) != 0) { dataLen = ReadInt16(stream, buffer); data = new byte [dataLen]; stream.Read(data, 0, dataLen); info.ShellIdInfo = data; } // Read the file location information as an opaque blob. if ((flags & 0x0002) != 0) { dataLen = (int)(ReadUInt32(stream, buffer)); data = new byte [dataLen + 4]; Array.Copy(buffer, 0, data, 0, 4); stream.Read(data, 4, dataLen - 4); info.FileLocationInfo = data; } // Read the string information that is present. if ((flags & 0x0004) != 0) { info.Description = ReadString(stream, buffer); } if ((flags & 0x0008) != 0) { info.RelativePath = ReadString(stream, buffer); } if ((flags & 0x0010) != 0) { info.WorkingDirectory = ReadString(stream, buffer); } if ((flags & 0x0020) != 0) { info.CommandLineArguments = ReadString(stream, buffer); } if ((flags & 0x0040) != 0) { info.Icon = ReadString(stream, buffer); } // Read the rest of the file as an opaque blob. if ((flags & 0x0080) != 0 && stream.CanSeek) { dataLen = (int)(stream.Length - stream.Position); if (dataLen > 0) { data = new byte [dataLen]; stream.Read(data, 0, dataLen); info.Rest = data; } } } finally { stream.Close(); } return(info); }
// Read the contents of a symbolic link. Returns null if not a // symbolic link, or throws an exception if the pathname is invalid. public static String ReadLink(String pathname) { // Validate the parameter and normalize it. Directory.ValidatePath(pathname); pathname = Path.NormalizeSeparators(pathname); // Read the contents of the symlink using the engine. String contents; Errno error = FileMethods.ReadLink(pathname, out contents); if (error != Errno.Success) { Directory.HandleErrorsFile(error); } if (contents != null) { return(contents); } // Bail out if we aren't on Windows. if (!IsWindows()) { return(null); } // Make sure that we have ".lnk" on the end of the name. if (!EndsInLnk(pathname)) { if (FileMethods.GetFileType(pathname) != FileType.unknown) { // Something exists here and it does not have a ".lnk" // extension, so it cannot possibly be a symlink. return(null); } pathname += ".lnk"; } FileType type = FileMethods.GetFileType(pathname); if (type == FileType.unknown) { // The pathname does not exist. Directory.HandleErrorsFile(Errno.ENOENT); } else if (type != FileType.regularFile) { // The pathname exists but it is not a regular file, // so it cannot possibly be a symbolic link. return(null); } // Read the contents of the Windows shortcut file. ShortcutInformation info = ReadShortcut(pathname); if (info == null) { return(null); } else { return(info.RelativePath); } }