วิธีรับรูปแบบไฟล์ที่ลงทะเบียนทั้งหมดจาก VCL.Graphics แต่เป็น 64 บิต

ในแอปพลิเคชัน 32 บิตของฉัน ฉันใช้หน่วย FindRegisteredPictureFileFormats จัดทำโดย Cosmin Prund => (จะรับรูปแบบไฟล์ที่รองรับทั้งหมดจากหน่วยกราฟิกได้อย่างไร)

ฉันต้องการเหมือนกัน แต่สำหรับ 64 บิต David Heffernan ตอบว่ามีเวอร์ชัน 64 บิตอยู่แล้ว รหัสนี้สามารถเปิดเผยต่อสาธารณะได้หรือไม่?

ขอบคุณมาก !!


person Frédéric SCHENCKEL    schedule 04.03.2016    source แหล่งที่มา
comment
วิธีแก้ปัญหาของ Remy (คำตอบที่ยอมรับสำหรับคำถามที่เชื่อมโยง) จะทำงานได้ดีในโค้ด 64 บิต มีเหตุผลที่คุณเลือกคำตอบที่แฮ็กมากขึ้นที่ Cosmin โพสต์แทนที่จะเป็น Remy's หรือไม่   -  person Ken White    schedule 04.03.2016
comment
เนื่องจากฉันมีกราฟิกอยู่ในสตรีม ฉันจึงต้องมีคลาสกราฟิกจึงจะโหลดได้อย่างถูกต้อง ฉันไม่สามารถใช้เคล็ดลับนี้โดยการโหลดไฟล์และดูว่าคลาสกราฟิกใดที่ใช้... ฉันรู้ว่า FindRegisteredPictureFileFormats เป็นการแฮ็ก แต่ทำงานได้ดีมากใน 32 บิต แต่ถ้าฉันได้ผลลัพธ์ด้วยวิธีอื่นฉันก็สามารถปรับโค้ดของฉันได้แน่นอน!   -  person Frédéric SCHENCKEL    schedule 05.03.2016
comment
คุณสามารถแก้ไขโค้ดของ Remy ให้โหลดจากสตรีมแทนจากไฟล์ และใช้วิธีการเดียวกัน โดยไม่ต้องใช้โค้ดแอสเซมบลีที่ไม่ใช่ข้ามแพลตฟอร์ม (และรวมถึง Windows 32/64 บิต)   -  person Ken White    schedule 05.03.2016
comment
คุณได้กระแสมาจากไหน? ฐานข้อมูล ทรัพยากร ...?   -  person Sir Rufo    schedule 05.03.2016
comment
คุณไม่ทราบว่ารองรับรูปแบบใดบ้าง? หรือคุณกำลังเขียนโค้ดที่เสียบเข้ากับแอปโฮสต์?   -  person David Heffernan    schedule 05.03.2016
comment
ว้าว มีความคิดเห็นรบกวนมากมายที่นี่ คำตอบของ Remy ดูเหมือนจะแก้ไขปัญหา XY ที่ระบุไว้ในความคิดเห็นที่ถูกลบ   -  person Free Consulting    schedule 05.03.2016
comment
ใช่ แอปนี้ประกอบด้วยปลั๊กอิน ดังนั้นรูปแบบรูปภาพที่ใช้ได้อาจแตกต่างกันไปตามแอปที่เขียนสตรีมและแอปที่ใช้งาน ฉันต้องเลือกอันที่มีอยู่จากแพลตฟอร์มการอ่าน และไม่จำเป็นจากแพลตฟอร์มการเขียน แน่นอนว่าฉันสามารถเปลี่ยนแปลงพฤติกรรมนี้ได้ แต่นั่นหมายความว่าฉันจะสูญเสียความยืดหยุ่นเล็กน้อย และแพลตฟอร์ม Win32 มีพฤติกรรมแตกต่างจาก Win64   -  person Frédéric SCHENCKEL    schedule 05.03.2016
comment
@Ken เท่าที่ฉันรู้มันเป็น LoadFromFile ที่ตรวจสอบคลาสที่ถูกต้อง LoadFromStream ต้องการคลาสที่ถูกต้องโดยตรงหรือฉันผิด แน่นอนว่าความเข้ากันได้ข้ามแพลตฟอร์มก็น่าจะดีเช่นกัน !!!   -  person Frédéric SCHENCKEL    schedule 05.03.2016
comment
การแก้ไขหน่วย Graphics.pas ก็ไม่ใช่วิธีแก้ปัญหาที่น่าสนใจที่สุดเนื่องจากฉันใช้แพ็คเกจ มันค่อนข้างยากที่จะทำให้แพ็คเกจทั้งหมดใช้ Graphics.pas ที่แก้ไขแล้วของฉัน   -  person Frédéric SCHENCKEL    schedule 05.03.2016


คำตอบ (1)


ฉันเชื่อว่าหน่วยนี้ทำสิ่งที่คุณกำลังมองหา ฉันได้ทดสอบบน Windows 32 บิตและ 64 บิต โดยมีแพ็คเกจรันไทม์และไม่มี ฉันไม่ได้ทดสอบด้วยการจัดสรรหน่วยความจำจากบนลงล่าง แต่ฉันไม่เชื่อว่ามีข้อบกพร่องในการตัดทอนตัวชี้

unit FindRegisteredPictureFileFormats;

{$POINTERMATH ON}

interface

uses Classes, Contnrs;

// Extracts the file extension + the description; Returns True if the hack was successful,
// False if unsuccesful.
function GetListOfRegisteredPictureFileFormats(List: TStrings): Boolean;

// This returns the list of TGraphicClass registered; True for successful hack, false
// for unsuccesful hach
function GetListOfRegisteredPictureTypes(List: TClassList): Boolean;

implementation

uses Graphics;

type
  TRelativeCallOpcode = packed record
    OpCode: Byte;
    Offset: Integer;
  end;

  PRelativeCallOpcode = ^TRelativeCallOpcode;

  TLongAbsoluteJumpOpcode = packed record
    OpCode: array [0 .. 1] of Byte;
    Destination: Cardinal;
  end;

  PLongAbsoluteJumpOpcode = ^TLongAbsoluteJumpOpcode;

  TReturnTList = function: TList;

  // Structure copied from Graphics unit.
  PFileFormat = ^TFileFormat;

  TFileFormat = record
    GraphicClass: TGraphicClass;
    Extension: string;
    Description: string;
    DescResID: Integer;
  end;

function FindFirstRelativeCallOpcode(StartOffset: NativeUInt): NativeUInt;
var
  Ram: ^Byte;
  i: Integer;
  PLongJump: PLongAbsoluteJumpOpcode;
begin
  Ram := nil;

  PLongJump := PLongAbsoluteJumpOpcode(@Ram[StartOffset]);
  if (PLongJump^.OpCode[0] = $FF) and (PLongJump^.OpCode[1] = $25) then
{$IF Defined(WIN32)}
    Result := FindFirstRelativeCallOpcode(PNativeUInt(PLongJump^.Destination)^)
{$ELSEIF Defined(Win64)}
    Result := FindFirstRelativeCallOpcode(PNativeUInt(PLongJump^.Destination + StartOffset + SizeOf(PLongJump^))^)
{$ELSE}
    {$MESSAGE Fatal 'Architecture not supported'}
{$ENDIF}
  else
  begin
    for i := 0 to 64 do
      if PRelativeCallOpcode(@Ram[StartOffset + i])^.OpCode = $E8 then
        Exit(StartOffset + i + PRelativeCallOpcode(@Ram[StartOffset + i])
          ^.Offset + 5);
    Result := 0;
  end;
end;

procedure FindGetFileFormatsFunc(out ProcAddr: TReturnTList);
var
  Offset_from_RegisterFileFormat: NativeUInt;
  Offset_from_RegisterFileFormatRes: NativeUInt;
begin
  Offset_from_RegisterFileFormat := FindFirstRelativeCallOpcode(NativeUInt(@TPicture.RegisterFileFormat));
  Offset_from_RegisterFileFormatRes := FindFirstRelativeCallOpcode(NativeUInt(@TPicture.RegisterFileFormatRes));

  if (Offset_from_RegisterFileFormat = Offset_from_RegisterFileFormatRes) then
    ProcAddr := TReturnTList(Pointer(Offset_from_RegisterFileFormat))
  else
    ProcAddr := nil;
end;

function GetListOfRegisteredPictureFileFormats(List: TStrings): Boolean;
var
  GetListProc: TReturnTList;
  L: TList;
  i: Integer;
begin
  FindGetFileFormatsFunc(GetListProc);
  if Assigned(GetListProc) then
  begin
    Result := True;
    L := GetListProc;
    for i := 0 to L.Count - 1 do
      List.Add(PFileFormat(L[i])^.Extension + '=' + PFileFormat(L[i])
        ^.Description);
  end
  else
    Result := False;
end;

function GetListOfRegisteredPictureTypes(List: TClassList): Boolean;
var
  GetListProc: TReturnTList;
  L: TList;
  i: Integer;
begin
  FindGetFileFormatsFunc(GetListProc);
  if Assigned(GetListProc) then
  begin
    Result := True;
    L := GetListProc;
    for i := 0 to L.Count - 1 do
      List.Add(PFileFormat(L[i])^.GraphicClass);
  end
  else
    Result := False;
end;

end.
person David Heffernan    schedule 05.03.2016
comment
ขอบคุณมากงานนี้ !! หมายเหตุ: จำเป็นต้องปิดใช้งานการตรวจสอบโอเวอร์โฟลว์และดีบักของ Dcu เมื่อเปิดใช้งาน debug Dcus การทดสอบ Offset_from_RegisterFileFormat = Offset_from_RegisterFileFormatRes จะกลายเป็นเท็จ - person Frédéric SCHENCKEL; 07.03.2016