private static void MarshalPOFIW(PatchOldFileInfoW managed, IntPtr native) { PatchAPIMarshaler.MarshalPOFI(managed, native); Marshal.WriteIntPtr(native, oldFileOffset, PatchAPIMarshaler.OptionalUnicodeString(managed.oldFileName)); // OldFileName }
/// <summary> /// Create a binary delta file. /// </summary> /// <param name="deltaFile">Name of the delta file to create.</param> /// <param name="targetFile">Name of updated file.</param> /// <param name="targetSymbolPath">Optional paths to updated file's symbols.</param> /// <param name="targetRetainOffsets">Optional offsets to the delta retain sections in the updated file.</param> /// <param name="basisFiles">Optional array of target files.</param> /// <param name="basisSymbolPaths">Optional array of target files' symbol paths (must match basisFiles array).</param> /// <param name="basisIgnoreLengths">Optional array of target files' delta ignore section lengths (must match basisFiles array)(each entry must match basisIgnoreOffsets entries).</param> /// <param name="basisIgnoreOffsets">Optional array of target files' delta ignore section offsets (must match basisFiles array)(each entry must match basisIgnoreLengths entries).</param> /// <param name="basisRetainLengths">Optional array of target files' delta protect section lengths (must match basisFiles array)(each entry must match basisRetainOffsets and targetRetainOffsets entries).</param> /// <param name="basisRetainOffsets">Optional array of target files' delta protect section offsets (must match basisFiles array)(each entry must match basisRetainLengths and targetRetainOffsets entries).</param> /// <param name="apiPatchingSymbolFlags">ApiPatchingSymbolFlags value.</param> /// <param name="optimizePatchSizeForLargeFiles">OptimizePatchSizeForLargeFiles value.</param> /// <param name="retainRangesIgnored">Flag to indicate retain ranges were ignored due to mismatch.</param> /// <returns>true if delta file was created, false if whole file should be used instead.</returns> static public bool CreateDelta( string deltaFile, string targetFile, string targetSymbolPath, string targetRetainOffsets, string[] basisFiles, string[] basisSymbolPaths, string[] basisIgnoreLengths, string[] basisIgnoreOffsets, string[] basisRetainLengths, string[] basisRetainOffsets, PatchSymbolFlagsType apiPatchingSymbolFlags, bool optimizePatchSizeForLargeFiles, out bool retainRangesIgnored ) { retainRangesIgnored = false; if (0 != (apiPatchingSymbolFlags & ~(PatchSymbolFlagsType.PATCH_SYMBOL_NO_IMAGEHLP | PatchSymbolFlagsType.PATCH_SYMBOL_NO_FAILURES | PatchSymbolFlagsType.PATCH_SYMBOL_UNDECORATED_TOO))) { throw new ArgumentOutOfRangeException("apiPatchingSymbolFlags"); } if (null == deltaFile || 0 == deltaFile.Length) { throw new ArgumentNullException("deltaFile"); } if (null == targetFile || 0 == targetFile.Length) { throw new ArgumentNullException("targetFile"); } if (null == basisFiles || 0 == basisFiles.Length) { return(false); } uint countOldFiles = (uint)basisFiles.Length; if (null != basisSymbolPaths) { if (0 != basisSymbolPaths.Length) { if ((uint)basisSymbolPaths.Length != countOldFiles) { throw new ArgumentOutOfRangeException("basisSymbolPaths"); } } } // a null basisSymbolPaths is allowed. if (null != basisIgnoreLengths) { if (0 != basisIgnoreLengths.Length) { if ((uint)basisIgnoreLengths.Length != countOldFiles) { throw new ArgumentOutOfRangeException("basisIgnoreLengths"); } } } else { basisIgnoreLengths = new string[countOldFiles]; } if (null != basisIgnoreOffsets) { if (0 != basisIgnoreOffsets.Length) { if ((uint)basisIgnoreOffsets.Length != countOldFiles) { throw new ArgumentOutOfRangeException("basisIgnoreOffsets"); } } } else { basisIgnoreOffsets = new string[countOldFiles]; } if (null != basisRetainLengths) { if (0 != basisRetainLengths.Length) { if ((uint)basisRetainLengths.Length != countOldFiles) { throw new ArgumentOutOfRangeException("basisRetainLengths"); } } } else { basisRetainLengths = new string[countOldFiles]; } if (null != basisRetainOffsets) { if (0 != basisRetainOffsets.Length) { if ((uint)basisRetainOffsets.Length != countOldFiles) { throw new ArgumentOutOfRangeException("basisRetainOffsets"); } } } else { basisRetainOffsets = new string[countOldFiles]; } PatchOptionData pod = new PatchOptionData(); pod.symbolOptionFlags = apiPatchingSymbolFlags; pod.newFileSymbolPath = targetSymbolPath; pod.oldFileSymbolPathArray = basisSymbolPaths; pod.extendedOptionFlags = 0; PatchOldFileInfoW[] oldFileInfoArray = new PatchOldFileInfoW[countOldFiles]; string[] newRetainOffsetArray = ((null == targetRetainOffsets) ? new string[0] : targetRetainOffsets.Split(',')); for (uint i = 0; i < countOldFiles; ++i) { PatchOldFileInfoW ofi = new PatchOldFileInfoW(); ofi.oldFileName = basisFiles[i]; string[] ignoreLengthArray = ((null == basisIgnoreLengths[i]) ? new string[0] : basisIgnoreLengths[i].Split(',')); string[] ignoreOffsetArray = ((null == basisIgnoreOffsets[i]) ? new string[0] : basisIgnoreOffsets[i].Split(',')); string[] retainLengthArray = ((null == basisRetainLengths[i]) ? new string[0] : basisRetainLengths[i].Split(',')); string[] retainOffsetArray = ((null == basisRetainOffsets[i]) ? new string[0] : basisRetainOffsets[i].Split(',')); // Validate inputs if (ignoreLengthArray.Length != ignoreOffsetArray.Length) { throw new ArgumentOutOfRangeException("basisIgnoreLengths"); } if (retainLengthArray.Length != retainOffsetArray.Length) { throw new ArgumentOutOfRangeException("basisRetainLengths"); } if (newRetainOffsetArray.Length != retainOffsetArray.Length) { // remove all retain range information retainRangesIgnored = true; for (uint j = 0; j < countOldFiles; ++j) { basisRetainLengths[j] = null; basisRetainOffsets[j] = null; } retainLengthArray = new string[0]; retainOffsetArray = new string[0]; newRetainOffsetArray = new string[0]; for (uint j = 0; j < oldFileInfoArray.Length; ++j) { oldFileInfoArray[j].retainRange = null; } } // Populate IgnoreRange structure PatchIgnoreRange[] ignoreArray = null; if (0 != ignoreLengthArray.Length) { ignoreArray = new PatchIgnoreRange[ignoreLengthArray.Length]; for (int j = 0; j < ignoreLengthArray.Length; ++j) { PatchIgnoreRange ignoreRange = new PatchIgnoreRange(); ignoreRange.offsetInOldFile = ParseHexOrDecimal(ignoreOffsetArray[j]); ignoreRange.lengthInBytes = ParseHexOrDecimal(ignoreLengthArray[j]); ignoreArray[j] = ignoreRange; } ofi.ignoreRange = ignoreArray; } PatchRetainRange[] retainArray = null; if (0 != newRetainOffsetArray.Length) { retainArray = new PatchRetainRange[retainLengthArray.Length]; for (int j = 0; j < newRetainOffsetArray.Length; ++j) { PatchRetainRange retainRange = new PatchRetainRange(); retainRange.offsetInOldFile = ParseHexOrDecimal(retainOffsetArray[j]); retainRange.lengthInBytes = ParseHexOrDecimal(retainLengthArray[j]); retainRange.offsetInNewFile = ParseHexOrDecimal(newRetainOffsetArray[j]); retainArray[j] = retainRange; } ofi.retainRange = retainArray; } oldFileInfoArray[i] = ofi; } if (CreatePatchFileExW( countOldFiles, oldFileInfoArray, targetFile, deltaFile, PatchOptionFlags(optimizePatchSizeForLargeFiles), pod, null, IntPtr.Zero)) { return(true); } // determine if this is an error or a need to use whole file. int err = Marshal.GetLastWin32Error(); switch (err) { case unchecked ((int)ERROR_PATCH_BIGGER_THAN_COMPRESSED): break; // too late to exclude this file -- should have been caught before case unchecked ((int)ERROR_PATCH_SAME_FILE): default: throw new System.ComponentModel.Win32Exception(err); } return(false); }