/***************************************************** * ApplyPatchToFileByHandles (MSPATCHA.2) */ BOOL WINAPI ApplyPatchToFileByHandles(HANDLE patch_file, HANDLE old_file, HANDLE new_file, ULONG apply_flags) { SAFE_READ Patch, OldFile; DWORD dwStatus; PATCH_HEADER Header; Patch.Root = Patch.Ptr = MapFile(patch_file, &Patch.Size); if (!Patch.Root) { SetLastError(ERROR_PATCH_CORRUPT); return FALSE; } /* Let's decode the header */ dwStatus = ParseHeader(&Patch, &Header); if (dwStatus != STATUS_SUCCESS) { UnmapViewOfFile(Patch.Root); SetLastError(dwStatus); return FALSE; } OldFile.Root = OldFile.Ptr = MapFile(old_file, &OldFile.Size); if (OldFile.Root) { DWORD dwCrc; /* Verify the input file */ dwCrc = RtlComputeCrc32(0, OldFile.Root, OldFile.Size); if (OldFile.Size == Header.OldSize && dwCrc == Header.OldCrc) { if (apply_flags & APPLY_OPTION_TEST_ONLY) dwStatus = STATUS_SUCCESS; else dwStatus = CreateNewFileFromPatch(&Header, &Patch, new_file); } else { dwStatus = ERROR_PATCH_WRONG_FILE; } UnmapViewOfFile(OldFile.Root); } else { dwStatus = GetLastError(); if (dwStatus == STATUS_SUCCESS) dwStatus = ERROR_PATCH_NOT_AVAILABLE; } UnmapViewOfFile(Patch.Root); SetLastError(dwStatus); return dwStatus == STATUS_SUCCESS; }
/** * @name ParseHeader * Parse a Patch file header * @note The current implementation is far from complete! * * @param Patch * Buffer pointing to the raw patch data * * @param Header * The result of the parsed header * * @return STATUS_SUCCESS on success, an error code otherwise */ DWORD ParseHeader(SAFE_READ* Patch, PATCH_HEADER* Header) { DWORD Crc, Unknown; int Delta; ZeroMemory(Header, sizeof(*Header)); /* Validate the patch */ Crc = RtlComputeCrc32(0, Patch->Root, Patch->Size); if (Crc != ~0) return ERROR_PATCH_CORRUPT; if (ReadDWord(Patch) != '91AP') return ERROR_PATCH_DECODE_FAILURE; /* Read the flags, warn about an unknown combination */ Header->Flags = ReadDWord(Patch); if (Header->Flags ^ UNKNOWN_FLAGS_COMBINATION) ERR("Unknown flags: 0x%x, patch will most likely fail\n", Header->Flags ^ UNKNOWN_FLAGS_COMBINATION); /* 0x5bb3284e, 0x5bb33562, 0x5bb357b1 */ Unknown = ReadDWord(Patch); TRACE("Unknown: 0x%x\n", Unknown); Header->OutputSize = DecodeDWord(Patch); Header->OutputCrc = ReadDWord(Patch); Unknown = ReadByte(Patch); if (Unknown != 1) ERR("Field after CRC is not 1 but %u\n", Unknown); Delta = DecodeInt(Patch); Header->OldSize = Header->OutputSize + Delta; Header->OldCrc = ReadDWord(Patch); Unknown = ReadUShort(Patch); if (Unknown != 0) ERR("Field1 after OldCrc is not 0 but %u\n", Unknown); Unknown = DecodeDWord(Patch); if (Unknown != 0) ERR("Field2 after OldCrc is not 0 but %u\n", Unknown); Header->DataSize = DecodeDWord(Patch); /* Remaining data, minus the CRC appended */ if (Header->DataSize != (Patch->Size - (Patch->Ptr - Patch->Root) - sizeof(DWORD))) { ERR("Unable to read header, check previous logging!\n"); return ERROR_PATCH_DECODE_FAILURE; } return STATUS_SUCCESS; }
/***************************************************** * GetFilePatchSignatureA (MSPATCHA.7) */ BOOL WINAPI GetFilePatchSignatureByHandle(HANDLE hFile, ULONG flags, PVOID data, ULONG ignore_range_count, PPATCH_IGNORE_RANGE ignore_range, ULONG retain_range_count, PPATCH_RETAIN_RANGE retain_range, ULONG bufsize, PVOID buffer) { BOOL ret = FALSE; DWORD dwSize, ulCrc; PBYTE pData; if (flags) FIXME("Unhandled flags 0x%x\n", flags); if (ignore_range_count) FIXME("Unhandled ignore_range_count %u\n", ignore_range_count); if (retain_range_count) FIXME("Unhandled ignore_range_count %u\n", retain_range_count); if ((pData = MapFile(hFile, &dwSize))) { if (dwSize >= 2 && *(PWORD)pData == IMAGE_DOS_SIGNATURE) { FIXME("Potentially unimplemented case, normalized signature\n"); } ulCrc = RtlComputeCrc32(0, pData, dwSize); if (bufsize >= SIGNATURE_MIN_SIZE) { char *pBuffer = buffer; pBuffer[8] = '\0'; for (dwSize = 0; dwSize < 8; ++dwSize) { pBuffer[7 - dwSize] = szHexString[ulCrc & 0xf]; ulCrc >>= 4; } ret = TRUE; } UnmapViewOfFile(pData); if (bufsize < SIGNATURE_MIN_SIZE) SetLastError(ERROR_INSUFFICIENT_BUFFER); }
PVOID NTAPI INIT_FUNCTION FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN ULONG ResourceId) { UNICODE_STRING UpString = RTL_CONSTANT_STRING(L"ntoskrnl.exe"); UNICODE_STRING MpString = RTL_CONSTANT_STRING(L"ntkrnlmp.exe"); PLIST_ENTRY NextEntry, ListHead; PLDR_DATA_TABLE_ENTRY LdrEntry; PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry; LDR_RESOURCE_INFO ResourceInfo; NTSTATUS Status; PVOID Data = NULL; /* Loop the driver list */ ListHead = &LoaderBlock->LoadOrderListHead; NextEntry = ListHead->Flink; while (NextEntry != ListHead) { /* Get the entry */ LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); /* Check for a match */ if ((RtlEqualUnicodeString(&LdrEntry->BaseDllName, &UpString, TRUE)) || (RtlEqualUnicodeString(&LdrEntry->BaseDllName, &MpString, TRUE))) { /* Break out */ break; } } /* Check if we found it */ if (NextEntry != ListHead) { /* Try to find the resource */ ResourceInfo.Type = 2; //RT_BITMAP; ResourceInfo.Name = ResourceId; ResourceInfo.Language = 0; Status = LdrFindResource_U(LdrEntry->DllBase, &ResourceInfo, RESOURCE_DATA_LEVEL, &ResourceDataEntry); if (NT_SUCCESS(Status)) { /* Access the resource */ ULONG Size = 0; Status = LdrAccessResource(LdrEntry->DllBase, ResourceDataEntry, &Data, &Size); if ((Data) && (ResourceId < 3)) { KiBugCheckData[4] ^= RtlComputeCrc32(0, Data, Size); } if (!NT_SUCCESS(Status)) Data = NULL; } } /* Return the pointer */ return Data; }