Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

W10 + Delphi Seattle, TFileOpenDialog + fdoForcePreviewPaneOn = crash on some images

Tags:

delphi

There seems to be a problem with TFileOpenDialog's preview pane setting, when selecting certain images the app crashes. Is there a fix for this?

Test image

Demo source:

procedure TForm1.Button1Click(Sender: TObject);
begin
  FileOpenDialog1.Execute;
end;

object FileOpenDialog1: TFileOpenDialog
  FavoriteLinks = <>
  FileTypes = <>
  Options = [fdoForcePreviewPaneOn]
  Left = 200
  Top = 32
end

Edit: it seems to happen only in Windows10 (AN. update), works normally in Win7. Some debug:

callstack crc      : $6ac33669, $66c06792, $66c06792
exception number   : 1
exception class    : EInvalidOp
exception message  : Invalid floating point operation.

main thread ($ae0):
6ac33669 +000 PhotoMetadataHandler.dll
71f6447f +09f PROPSYS.dll                                   PSCreateDelayedMultiplexPropertyStore
773ef71a +00a combase.dll                                   PropVariantClear
74d317c2 +082 KERNELBASE.dll                                QISearch
71f4f677 +097 PROPSYS.dll                                   #424
71f4f829 +249 PROPSYS.dll                                   #424
6c5f1bba +11a DUI70.dll                                     ?_PreSourceChange@Element@DirectUI@@AAEJPBUPropertyInfo@2@HPAVValue@2@1@Z
6c5ee3a6 +246 DUI70.dll                                     ?_SetValue@Element@DirectUI@@IAEJPBUPropertyInfo@2@HPAVValue@2@_N@Z
6c5ee46e +30e DUI70.dll                                     ?_SetValue@Element@DirectUI@@IAEJPBUPropertyInfo@2@HPAVValue@2@_N@Z
6c5ecf15 +025 DUI70.dll                                     ?SetContentAlign@Element@DirectUI@@QAEJH@Z
6c5e6813 +033 DUI70.dll                                     ?_BroadcastEventWorker@Element@DirectUI@@AAEXPAUEvent@2@@Z
6c5e6867 +087 DUI70.dll                                     ?_BroadcastEventWorker@Element@DirectUI@@AAEXPAUEvent@2@@Z
6c5e68a2 +012 DUI70.dll                                     ?BroadcastEvent@Element@DirectUI@@QAEXPAUEvent@2@@Z
6c5e6813 +033 DUI70.dll                                     ?_BroadcastEventWorker@Element@DirectUI@@AAEXPAUEvent@2@@Z
6c5e6867 +087 DUI70.dll                                     ?_BroadcastEventWorker@Element@DirectUI@@AAEXPAUEvent@2@@Z
6c5e68a2 +012 DUI70.dll                                     ?BroadcastEvent@Element@DirectUI@@QAEXPAUEvent@2@@Z
6c54d590 +0b0 DUser.dll                                     DUserSendEvent
6c5e68ef +03f DUI70.dll                                     ?FireEvent@Element@DirectUI@@QAEXPAUEvent@2@_N1@Z
7529df12 +092 user32.dll                                    CallWindowProcW
752ac53c +0fc user32.dll                                    IsDialogMessageW
752abd8d +02d user32.dll                                    DialogBoxIndirectParamAorW
752abd46 +016 user32.dll                                    DialogBoxIndirectParamW
005af784 +370 Project1.exe             Vcl.Dialogs          TCustomFileDialog.Execute
005af3f9 +045 Project1.exe             Vcl.Dialogs          TCustomFileDialog.Execute
006375ec +008 Project1.exe             Unit1          29 +0 TForm1.Button1Click
005880d3 +073 Project1.exe             Vcl.Controls         TControl.Click
0059f1d2 +01e Project1.exe             Vcl.StdCtrls         TCustomButton.Click
0059fce0 +010 Project1.exe             Vcl.StdCtrls         TCustomButton.CNCommand
00587b65 +2bd Project1.exe             Vcl.Controls         TControl.WndProc
0058c6a5 +5e9 Project1.exe             Vcl.Controls         TWinControl.WndProc
0059ee7c +06c Project1.exe             Vcl.StdCtrls         TButtonControl.WndProc
005877a0 +024 Project1.exe             Vcl.Controls         TControl.Perform
0058c80b +023 Project1.exe             Vcl.Controls         DoControlMsg
0058d293 +00b Project1.exe             Vcl.Controls         TWinControl.WMCommand
00627ed9 +045 Project1.exe             Vcl.Forms            TCustomForm.WMCommand
00587b65 +2bd Project1.exe             Vcl.Controls         TControl.WndProc
0058c6a5 +5e9 Project1.exe             Vcl.Controls         TWinControl.WndProc
00624d08 +62c Project1.exe             Vcl.Forms            TCustomForm.WndProc
0058bcc4 +02c Project1.exe             Vcl.Controls         TWinControl.MainWndProc
0052f48c +014 Project1.exe             System.Classes       StdWndProc
77630004 +034 ntdll.dll                                     KiUserCallbackDispatcher
752a0bfb +13b user32.dll                                    SendMessageW
7529df12 +092 user32.dll                                    CallWindowProcW
0058c7b6 +0e6 Project1.exe             Vcl.Controls         TWinControl.DefaultHandler
00588528 +010 Project1.exe             Vcl.Controls         TControl.WMLButtonUp
00587b65 +2bd Project1.exe             Vcl.Controls         TControl.WndProc
0058c6a5 +5e9 Project1.exe             Vcl.Controls         TWinControl.WndProc
0059ee7c +06c Project1.exe             Vcl.StdCtrls         TButtonControl.WndProc
0058bcc4 +02c Project1.exe             Vcl.Controls         TWinControl.MainWndProc
0052f48c +014 Project1.exe             System.Classes       StdWndProc
7529df9b +00b user32.dll                                    DispatchMessageW
0062e363 +0f3 Project1.exe             Vcl.Forms            TApplication.ProcessMessage
0062e3a6 +00a Project1.exe             Vcl.Forms            TApplication.HandleMessage
0062e6d9 +0c9 Project1.exe             Vcl.Forms            TApplication.Run
00640801 +049 Project1.exe             Project1       18 +4 initialization
74fa62c2 +022 KERNEL32.DLL                                  BaseThreadInitThunk

disassembling:
006375e4    public Unit1.TForm1.Button1Click:  ; function entry point
006375e4 29   mov     eax, [eax+$3c4]
006375ea      mov     edx, [eax]
006375ec    > call    dword ptr [edx+$4c]
006375ef 30   ret
like image 890
hikari Avatar asked Dec 05 '16 00:12

hikari


1 Answers

You are seeing an FPU exception that originates from PhotoMetadataHandler.dll, The reason why it is crashing is unknown but it seems that some JPG files can cause floating point exceptions. For instance Total Commander (which is written in Delphi) has been hit with the same problem a number of times. The fix is quite simple, disable all exceptions before executing the dialog and reenable them afterwards:

procedure TForm1.Button1Click(Sender: TObject);

var
  OrgMask : TArithmeticExceptionMask;

begin
 OrgMask := GetExceptionMask;
 // disable all exceptions
 SetExceptioNMask([exInvalidOp,exDenormalized, exZeroDivide, exOverflow,
                   exUnderflow, exPrecision]);
 FileOpenDialog1.Execute;
 SetExceptionMask(OrgMask);
end;

EDIT

based on the comment of Craig Young, I would implement an interface to make sure that we always restore the original exception mask.

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Math;

type
  ICatchAllFPUExceptions = interface
  ['{7F429ECA-B458-4F39-832B-429839A8E948}']
  end;

  TCatchAllFPUExceptions = class(TInterfacedObject, ICatchAllFPUExceptions)
  private
    OrgExceptionMask : TArithmeticExceptionMask;
  public
    class function Activate : ICatchAllFPUExceptions; static;
    constructor Create;
    destructor Destroy; override;
  end;

  TForm1 = class(TForm)
    FileOpenDialog1: TFileOpenDialog;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TCatchAllFPUExceptions }
class function TCatchAllFPUExceptions.Activate: ICatchAllFPUExceptions;
begin
 Result := TCatchAllFPUExceptions.Create;
end;

constructor TCatchAllFPUExceptions.Create;
begin
 inherited;
 OrgExceptionMask := GetExceptionMask;
 SetExceptioNMask([exInvalidOp,exDenormalized, exZeroDivide,
                   exOverflow, exUnderflow, exPrecision]);
end;

destructor TCatchAllFPUExceptions.Destroy;
begin
 SetExceptioNMask(OrgExceptionMask);
 inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);       
begin
 // disable all exceptions
 TCatchAllFPUExceptions.Activate;     
 FileOpenDialog1.Execute;
 // mask will be restored here due to internal function variable going out of scope
end;

end.
like image 54
whosrdaddy Avatar answered Oct 07 '22 16:10

whosrdaddy