internal static IntPtr FdiOpen(string filename, int oflag, int pmode) { FileMode mode = CabinetNativeApi.ConvertOpflagToFileMode(oflag); FileAccess access = CabinetNativeApi.ConvertPermissionModeToFileAccess(pmode); FileShare share = CabinetNativeApi.ConvertPermissionModeToFileShare(pmode); // This method is used for opening the cab file as well as saving the extracted files. // When we are opening the cab file we only need read permissions. // We force read permissions so that non-elevated users can extract cab files. if (mode == FileMode.Open || mode == FileMode.OpenOrCreate) { access = FileAccess.Read; share = FileShare.Read; } try { FileStream stream = new FileStream(filename, mode, access, share); if (stream == null) { return(new IntPtr(-1)); } return(GCHandle.ToIntPtr(GCHandle.Alloc(stream))); } catch (IOException) { return(new IntPtr(-1)); } }
internal override bool Extract(string cabinetName, string srcPath, string destPath) { IntPtr nativeDestPath = Marshal.StringToHGlobalAnsi(destPath); bool result = CabinetNativeApi.FDICopy( fdiContext, cabinetName, srcPath, 0, // Not used Marshal.GetFunctionPointerForDelegate(_notifyDelegate), IntPtr.Zero, nativeDestPath); Marshal.FreeHGlobal(nativeDestPath); return(result); }
internal CabinetNativeApi.FdiContextHandle fdiContext; // HFDI internal CabinetExtractor() { CabinetNativeApi.FdiERF err = new CabinetNativeApi.FdiERF(); populateDelegates(); // marshal the delegate to a unmanaged function pointer so that AppDomain reference is stored correctly. fdiContext = CabinetNativeApi.FDICreate( Marshal.GetFunctionPointerForDelegate(_allocDelegate), Marshal.GetFunctionPointerForDelegate(_freeDelegate), Marshal.GetFunctionPointerForDelegate(_openDelegate), Marshal.GetFunctionPointerForDelegate(_readDelegate), Marshal.GetFunctionPointerForDelegate(_writeDelegate), Marshal.GetFunctionPointerForDelegate(_closeDelegate), Marshal.GetFunctionPointerForDelegate(_seekDelegate), CabinetNativeApi.FdiCreateCpuType.Cpu80386, err); }
internal static int FdiSeek(IntPtr fp, int offset, int origin) { GCHandle handle = GCHandle.FromIntPtr(fp); FileStream stream = (FileStream)handle.Target; SeekOrigin seekOrigin = CabinetNativeApi.ConvertOriginToSeekOrigin(origin); long status = 0; try { status = stream.Seek(offset, seekOrigin); } catch (NotSupportedException) { status = -1; } catch (IOException) { status = -1; } catch (ArgumentException) { status = -1; } catch (ObjectDisposedException) { status = -1; } return((int)status); }
protected override bool ReleaseHandle() { return(CabinetNativeApi.FDIDestroy(this.handle)); }
// Handles FDI notification internal static IntPtr FdiNotify(FdiNotificationType fdint, FdiNotification fdin) { switch (fdint) { case FdiNotificationType.FdintCOPY_FILE: { // TODO: Should I catch exceptions for the new functions? // Copy target directory string destPath = Marshal.PtrToStringAnsi(fdin.pv); // Split the path to a filename and path string fileName = Path.GetFileName(fdin.psz1); string remainingPsz1Path = Path.GetDirectoryName(fdin.psz1); destPath = Path.Combine(destPath, remainingPsz1Path); Directory.CreateDirectory(destPath); // Creates all intermediate directories if necessary. // Create the file string absoluteFilePath = Path.Combine(destPath, fileName); return(CabinetNativeApi.FdiOpen(absoluteFilePath, (int)OpFlags.Create, (int)(PermissionMode.Read | PermissionMode.Write))); // TODO: OK to ignore _O_SEQUENTIAL, WrOnly, and _O_BINARY? } case FdiNotificationType.FdintCLOSE_FILE_INFO: { // Close the file CabinetNativeApi.FdiClose(fdin.hf); // Set the file attributes string destPath = Marshal.PtrToStringAnsi(fdin.pv); string absoluteFilePath = Path.Combine(destPath, fdin.psz1); IntPtr hFile = PlatformInvokes.CreateFile( absoluteFilePath, PlatformInvokes.FileDesiredAccess.GenericRead | PlatformInvokes.FileDesiredAccess.GenericWrite, PlatformInvokes.FileShareMode.Read, IntPtr.Zero, PlatformInvokes.FileCreationDisposition.OpenExisting, PlatformInvokes.FileAttributes.Normal, IntPtr.Zero); if (hFile != IntPtr.Zero) { PlatformInvokes.FILETIME ftFile = new PlatformInvokes.FILETIME(); if (PlatformInvokes.DosDateTimeToFileTime(fdin.date, fdin.time, ftFile)) { PlatformInvokes.FILETIME ftLocal = new PlatformInvokes.FILETIME(); if (PlatformInvokes.LocalFileTimeToFileTime(ftFile, ftLocal)) { PlatformInvokes.SetFileTime(hFile, ftLocal, null, ftLocal); } } PlatformInvokes.CloseHandle(hFile); } PlatformInvokes.SetFileAttributesW( absoluteFilePath, (PlatformInvokes.FileAttributes)fdin.attribs & (PlatformInvokes.FileAttributes.ReadOnly | PlatformInvokes.FileAttributes.Hidden | PlatformInvokes.FileAttributes.System | PlatformInvokes.FileAttributes.Archive)); // Call notification function return(new IntPtr(1)); } } return(new IntPtr(0)); }