mirror of
https://github.com/UzixLS/KernelEx.git
synced 2025-07-19 07:21:20 +03:00
import KernelEx-4.5-RC5
This commit is contained in:
275
apilibs/kexbasen/comdlg32/opensavefile.c
Executable file
275
apilibs/kexbasen/comdlg32/opensavefile.c
Executable file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright (C) 2010, Tihiy
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include "opensavefile.h"
|
||||
|
||||
static UINT WM_HELPMSGSTRING;
|
||||
static UINT WM_FILEOKSTRING;
|
||||
static UINT WM_SHAREVISTRING;
|
||||
|
||||
//this procedure adapts unicode hook proc, both old and new
|
||||
static UINT_PTR CALLBACK OFNHookProcWAdapter(
|
||||
LPOFNHOOKPROC pfnhook, LPOPENFILENAMEW lpofnW, HWND hdlg, UINT uiMsg,
|
||||
WPARAM wParam, LPARAM lParam
|
||||
)
|
||||
{
|
||||
switch(uiMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
return pfnhook(hdlg,uiMsg,wParam,(LPARAM)lpofnW);
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
if (!lParam) return 0;
|
||||
LPOFNOTIFYA notif = (LPOFNOTIFYA)lParam;
|
||||
switch (notif->hdr.code)
|
||||
{
|
||||
case CDN_FILEOK:
|
||||
case CDN_FOLDERCHANGE:
|
||||
case CDN_HELP:
|
||||
case CDN_INCLUDEITEM:
|
||||
case CDN_INITDONE:
|
||||
case CDN_SELCHANGE:
|
||||
case CDN_SHAREVIOLATION:
|
||||
case CDN_TYPECHANGE:
|
||||
{
|
||||
if (notif->hdr.code == CDN_FILEOK || notif->hdr.code == CDN_SHAREVIOLATION)
|
||||
{
|
||||
//pszFile is updated
|
||||
if (notif->lpOFN->Flags & (OFN_EXPLORER|OFN_ALLOWMULTISELECT))
|
||||
{
|
||||
//many files could be selected, convert \0-separated list
|
||||
MultiByteToWideChar(CP_ACP, 0, notif->lpOFN->lpstrFile,
|
||||
strlenAA(notif->lpOFN->lpstrFile),
|
||||
lpofnW->lpstrFile, lpofnW->nMaxFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
MultiByteToWideChar(CP_ACP, 0, notif->lpOFN->lpstrFile,
|
||||
-1,lpofnW->lpstrFile,lpofnW->nMaxFile);
|
||||
}
|
||||
}
|
||||
lpofnW->nFilterIndex = notif->lpOFN->nFilterIndex;
|
||||
lpofnW->Flags = notif->lpOFN->Flags;
|
||||
((LPOFNOTIFYW)notif)->lpOFN = lpofnW;
|
||||
}
|
||||
default:
|
||||
return pfnhook(hdlg,uiMsg,wParam,lParam);
|
||||
}
|
||||
}
|
||||
//old style hooks messages
|
||||
default:
|
||||
if (uiMsg == WM_HELPMSGSTRING || uiMsg == WM_FILEOKSTRING || uiMsg == WM_SHAREVISTRING)
|
||||
{
|
||||
LPOPENFILENAMEA lpofnA = (LPOPENFILENAMEA)lParam;
|
||||
lpofnW->nFilterIndex = lpofnA->nFilterIndex;
|
||||
lpofnW->Flags = lpofnA->Flags;
|
||||
if (uiMsg == WM_FILEOKSTRING || uiMsg == WM_SHAREVISTRING)
|
||||
{
|
||||
//pszFile is updated
|
||||
if (lpofnW->Flags & (OFN_EXPLORER|OFN_ALLOWMULTISELECT))
|
||||
{
|
||||
//many files could be selected, convert \0-separated list
|
||||
MultiByteToWideChar(CP_ACP, 0, lpofnA->lpstrFile,
|
||||
strlenAA(lpofnA->lpstrFile),
|
||||
lpofnW->lpstrFile, lpofnW->nMaxFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
MultiByteToWideChar(CP_ACP, 0, lpofnA->lpstrFile, -1,
|
||||
lpofnW->lpstrFile,lpofnW->nMaxFile);
|
||||
}
|
||||
}
|
||||
lParam = (LPARAM)lpofnW;
|
||||
}
|
||||
return pfnhook(hdlg,uiMsg,wParam,lParam);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//this procedure handles unicode CDM_ messages. makes sense only to Explorer-style dlgs
|
||||
static INT_PTR CALLBACK OpenSaveDlgProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
DLGPROC DlgProc = (DLGPROC)GetProp(hWnd,OLDDLGPROCPROP);
|
||||
if (!DlgProc) return 0;
|
||||
|
||||
switch(Msg)
|
||||
{
|
||||
case CDM_GETSPEC:
|
||||
case CDM_GETFILEPATH:
|
||||
case CDM_GETFOLDERPATH:
|
||||
{
|
||||
LPSTR bufA;
|
||||
ABUFFER_ALLOC(bufA,wParam);
|
||||
LRESULT ret = DlgProc(hWnd,Msg,wParam,(LPARAM)bufA);
|
||||
ABUFFER_toW(bufA,lParam,wParam);
|
||||
BUFFER_FREE(bufA);
|
||||
return ret;
|
||||
}
|
||||
case CDM_SETCONTROLTEXT:
|
||||
case CDM_SETDEFEXT:
|
||||
{
|
||||
LPSTR strA;
|
||||
STACK_WtoA(lParam,strA);
|
||||
return DlgProc(hWnd,Msg,wParam,(LPARAM)strA);
|
||||
}
|
||||
default:
|
||||
return DlgProc(hWnd,Msg,wParam,lParam);
|
||||
}
|
||||
}
|
||||
|
||||
static void CALLBACK WinCreateEvent(
|
||||
HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject,
|
||||
LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime
|
||||
)
|
||||
{
|
||||
//catch "Open"(Save) button creation, since on dialog window creation no dlgproc set yet
|
||||
if (GetDlgCtrlID(hwnd) == IDOK)
|
||||
{
|
||||
hwnd = GetParent(hwnd);
|
||||
//mark dialog created as unicode. really, everything should be marked unicode
|
||||
//with thunilay but then dialog may choke on unicode common controls
|
||||
if (GetClassWord(hwnd,GCW_ATOM) == DIALOG_ATOM
|
||||
&& GetProp(hwnd,OLDDLGPROCPROP) == NULL)
|
||||
{
|
||||
SetWindowUnicode(hwnd,TRUE);
|
||||
HANDLE h = (HANDLE)SetWindowLongA(hwnd,DWL_DLGPROC,(LONG)OpenSaveDlgProcW);
|
||||
SetProp(hwnd,OLDDLGPROCPROP,h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL WINAPI GetOpenOrSaveFileNameW(LPOPENFILENAMEW lpofn, BOOL IsSave)
|
||||
{
|
||||
BOOL ret;
|
||||
OPENFILENAMEA ofnA;
|
||||
memcpy(&ofnA,lpofn,sizeof(OPENFILENAME));
|
||||
//File filters
|
||||
STACK_WWtoAA(lpofn->lpstrFilter,ofnA.lpstrFilter);
|
||||
//Custom filter [NOBODY USES LOL]
|
||||
ofnA.lpstrCustomFilter = NULL;
|
||||
if (lpofn->lpstrCustomFilter && lpofn->nMaxCustFilter)
|
||||
{
|
||||
ofnA.nMaxCustFilter = lpofn->nMaxCustFilter * 2;
|
||||
ofnA.lpstrCustomFilter = StrAllocA(ofnA.nMaxCustFilter);
|
||||
WideCharToMultiByte(CP_ACP, 0, lpofn->lpstrCustomFilter, -1,
|
||||
ofnA.lpstrCustomFilter, ofnA.nMaxCustFilter, NULL, NULL);
|
||||
}
|
||||
//File path buffer - nMaxFile is byte count
|
||||
if (lpofn->lpstrFile)
|
||||
{
|
||||
ofnA.nMaxFile = lpofn->nMaxFile * 2;
|
||||
ofnA.lpstrFile = StrAllocA(ofnA.nMaxFile);
|
||||
WideCharToMultiByte(CP_ACP, 0, lpofn->lpstrFile, -1,
|
||||
ofnA.lpstrFile, ofnA.nMaxFile, "_", NULL);
|
||||
}
|
||||
//File title buffer - same
|
||||
if (lpofn->lpstrFileTitle)
|
||||
{
|
||||
ofnA.nMaxFileTitle = lpofn->nMaxFileTitle * 2;
|
||||
ofnA.lpstrFileTitle = StrAllocA(ofnA.nMaxFileTitle);
|
||||
}
|
||||
//Misc stuff
|
||||
STACK_WtoA(lpofn->lpstrInitialDir, ofnA.lpstrInitialDir);
|
||||
STACK_WtoA(lpofn->lpstrTitle, ofnA.lpstrTitle);
|
||||
STACK_WtoA(lpofn->lpstrDefExt, ofnA.lpstrDefExt);
|
||||
if (ofnA.Flags & OFN_ENABLETEMPLATE)
|
||||
STACK_WtoA(lpofn->lpTemplateName, ofnA.lpTemplateName);
|
||||
//Hook: build hook thunk on stack
|
||||
if (ofnA.Flags & OFN_ENABLEHOOK)
|
||||
{
|
||||
POFN_THUNK thunk;
|
||||
WM_HELPMSGSTRING = RegisterWindowMessage(HELPMSGSTRING);
|
||||
WM_FILEOKSTRING = RegisterWindowMessage(FILEOKSTRING);
|
||||
WM_SHAREVISTRING = RegisterWindowMessage(SHAREVISTRING);
|
||||
ALLOC_OFNTHUNK(thunk, lpofn, lpofn->lpfnHook, OFNHookProcWAdapter);
|
||||
ofnA.lpfnHook = (LPOFNHOOKPROC)thunk;
|
||||
}
|
||||
//Set up eventhook to make dialog unicode
|
||||
HWINEVENTHOOK eventhook = SetWinEventHook(EVENT_OBJECT_CREATE,
|
||||
EVENT_OBJECT_CREATE, GetModuleHandle("USER32.DLL"),
|
||||
(WINEVENTPROC)WinCreateEvent, GetCurrentProcessId(),
|
||||
GetCurrentThreadId(), WINEVENT_INCONTEXT);
|
||||
|
||||
if (IsSave)
|
||||
ret = GetSaveFileNameA_fix(&ofnA);
|
||||
else
|
||||
ret = GetOpenFileNameA_fix(&ofnA);
|
||||
|
||||
UnhookWinEvent(eventhook);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
//copy stuff back
|
||||
lpofn->nFilterIndex = ofnA.nFilterIndex;
|
||||
lpofn->Flags = ofnA.Flags;
|
||||
//translate buffers back
|
||||
if (ofnA.lpstrCustomFilter)
|
||||
MultiByteToWideChar(CP_ACP, 0, ofnA.lpstrCustomFilter, -1,
|
||||
lpofn->lpstrCustomFilter, lpofn->nMaxCustFilter);
|
||||
if (ofnA.lpstrFile)
|
||||
{
|
||||
if (ofnA.Flags & (OFN_EXPLORER|OFN_ALLOWMULTISELECT))
|
||||
{
|
||||
//many files could be selected, convert \0-separated list
|
||||
MultiByteToWideChar(CP_ACP, 0, ofnA.lpstrFile,
|
||||
strlenAA(ofnA.lpstrFile), lpofn->lpstrFile, lpofn->nMaxFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
MultiByteToWideChar(CP_ACP, 0, ofnA.lpstrFile, -1,
|
||||
lpofn->lpstrFile, lpofn->nMaxFile);
|
||||
}
|
||||
//translate buffer offsets
|
||||
lpofn->nFileOffset = MultiByteToWideChar(CP_ACP, 0, ofnA.lpstrFile,
|
||||
ofnA.nFileOffset, NULL, 0);
|
||||
lpofn->nFileExtension = MultiByteToWideChar(CP_ACP, 0, ofnA.lpstrFile,
|
||||
ofnA.nFileExtension, NULL, 0);
|
||||
}
|
||||
if (ofnA.lpstrFileTitle)
|
||||
MultiByteToWideChar(CP_ACP, 0, ofnA.lpstrFileTitle, -1,
|
||||
lpofn->lpstrFileTitle, lpofn->nMaxFileTitle);
|
||||
}
|
||||
else //function failed
|
||||
{
|
||||
//buffer too small? lpstrFile contains proper size
|
||||
if ( CommDlgExtendedError() == FNERR_BUFFERTOOSMALL )
|
||||
*(WORD*)lpofn->lpstrFile = *(WORD*)ofnA.lpstrFile;
|
||||
}
|
||||
//free buffers
|
||||
StrFree(ofnA.lpstrCustomFilter);
|
||||
StrFree(ofnA.lpstrFile);
|
||||
StrFree(ofnA.lpstrFileTitle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* MAKE_EXPORT GetSaveFileNameW_new=GetSaveFileNameW */
|
||||
BOOL WINAPI GetSaveFileNameW_new(LPOPENFILENAMEW lpofn)
|
||||
{
|
||||
return GetOpenOrSaveFileNameW(lpofn,TRUE);
|
||||
}
|
||||
|
||||
/* MAKE_EXPORT GetOpenFileNameW_new=GetOpenFileNameW */
|
||||
BOOL WINAPI GetOpenFileNameW_new(LPOPENFILENAMEW lpofn)
|
||||
{
|
||||
return GetOpenOrSaveFileNameW(lpofn,FALSE);
|
||||
}
|
Reference in New Issue
Block a user