+// ----------------------------------------------------------------------------
+
+namespace
+{
+
+#if wxUSE_DYNLIB_CLASS
+
+typedef BOOL (WINAPI *GetProcessUserModeExceptionPolicy_t)(LPDWORD);
+typedef BOOL (WINAPI *SetProcessUserModeExceptionPolicy_t)(DWORD);
+
+GetProcessUserModeExceptionPolicy_t gs_pfnGetProcessUserModeExceptionPolicy
+ = (GetProcessUserModeExceptionPolicy_t) -1;
+
+SetProcessUserModeExceptionPolicy_t gs_pfnSetProcessUserModeExceptionPolicy
+ = (SetProcessUserModeExceptionPolicy_t) -1;
+
+DWORD gs_oldExceptionPolicyFlags = 0;
+
+bool gs_changedPolicy = false;
+
+#endif // #if wxUSE_DYNLIB_CLASS
+
+/*
+Since Windows 7 by default (callback) exceptions aren't swallowed anymore
+with native x64 applications. Exceptions can occur in a file dialog when
+using the hook procedure in combination with third-party utilities.
+Since Windows 7 SP1 the swallowing of exceptions can be enabled again
+by using SetProcessUserModeExceptionPolicy.
+*/
+void ChangeExceptionPolicy()
+{
+#if wxUSE_DYNLIB_CLASS
+ gs_changedPolicy = false;
+
+ wxLoadedDLL dllKernel32(wxT("kernel32.dll"));
+
+ if ( gs_pfnGetProcessUserModeExceptionPolicy
+ == (GetProcessUserModeExceptionPolicy_t) -1)
+ {
+ wxDL_INIT_FUNC(gs_pfn, GetProcessUserModeExceptionPolicy, dllKernel32);
+ wxDL_INIT_FUNC(gs_pfn, SetProcessUserModeExceptionPolicy, dllKernel32);
+ }
+
+ if ( !gs_pfnGetProcessUserModeExceptionPolicy
+ || !gs_pfnSetProcessUserModeExceptionPolicy
+ || !gs_pfnGetProcessUserModeExceptionPolicy(&gs_oldExceptionPolicyFlags) )
+ {
+ return;
+ }
+
+ if ( gs_pfnSetProcessUserModeExceptionPolicy(gs_oldExceptionPolicyFlags
+ | 0x1 /* PROCESS_CALLBACK_FILTER_ENABLED */ ) )
+ {
+ gs_changedPolicy = true;
+ }
+
+#endif // wxUSE_DYNLIB_CLASS
+}
+
+void RestoreExceptionPolicy()
+{
+#if wxUSE_DYNLIB_CLASS
+ if (gs_changedPolicy)
+ {
+ gs_changedPolicy = false;
+ (void) gs_pfnSetProcessUserModeExceptionPolicy(gs_oldExceptionPolicyFlags);
+ }
+#endif // wxUSE_DYNLIB_CLASS
+}
+
+} // unnamed namespace
+
+// ----------------------------------------------------------------------------
+// hook function for moving the dialog
+// ----------------------------------------------------------------------------
+
+UINT_PTR APIENTRY
+wxFileDialogHookFunction(HWND hDlg,
+ UINT iMsg,
+ WPARAM WXUNUSED(wParam),
+ LPARAM lParam)
+{
+ switch ( iMsg )
+ {
+#ifndef __WXWINCE__
+ case WM_INITDIALOG:
+ {
+ OPENFILENAME* ofn = reinterpret_cast<OPENFILENAME *>(lParam);
+ reinterpret_cast<wxFileDialog *>(ofn->lCustData)
+ ->MSWOnInitDialogHook((WXHWND)hDlg);
+ }
+ break;
+#endif // __WXWINCE__
+
+ case WM_NOTIFY:
+ {
+ OFNOTIFY *pNotifyCode = reinterpret_cast<OFNOTIFY *>(lParam);
+ if ( pNotifyCode->hdr.code == CDN_INITDONE )
+ {
+ reinterpret_cast<wxFileDialog *>(
+ pNotifyCode->lpOFN->lCustData)
+ ->MSWOnInitDone((WXHWND)hDlg);
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ // reuse the position used for the dialog the next time by default
+ //
+ // NB: at least under Windows 2003 this is useless as after the
+ // first time it's shown the dialog always remembers its size
+ // and position itself and ignores any later SetWindowPos calls
+ wxCopyRECTToRect(wxGetWindowRect(::GetParent(hDlg)), gs_rectDialog);
+ break;
+ }
+
+ // do the default processing
+ return 0;
+}
+