Skip to content

Commit

Permalink
Windows: Make open/save dialogs long path aware.
Browse files Browse the repository at this point in the history
At least, in most cases.  If the filename is super long, it'll open twice,
but we try to avoid.
  • Loading branch information
unknownbrackets committed Jan 4, 2020
1 parent 46464d2 commit 97ac18c
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 76 deletions.
53 changes: 19 additions & 34 deletions Windows/Debugger/CtrlDisAsmView.cpp
Expand Up @@ -4,6 +4,7 @@
#include "Core/MemMap.h"
#include "Core/MIPS/JitCommon/JitCommon.h"
#include "Windows/W32Util/Misc.h"
#include "Windows/W32Util/ShellUtil.h"
#include "Windows/MainWindow.h"
#include "Windows/InputBox.h"

Expand Down Expand Up @@ -1323,47 +1324,31 @@ std::string CtrlDisAsmView::disassembleRange(u32 start, u32 size)
return result;
}

void CtrlDisAsmView::disassembleToFile()
{
wchar_t fileName[MAX_PATH];
u32 size;

void CtrlDisAsmView::disassembleToFile() {
// get size
if (executeExpressionWindow(wnd,debugger,size) == false) return;
if (size == 0 || size > 10*1024*1024)
{
u32 size;
if (executeExpressionWindow(wnd,debugger,size) == false)
return;
if (size == 0 || size > 10*1024*1024) {
MessageBox(wnd,L"Invalid size!",L"Error",MB_OK);
return;
}

// get file name
OPENFILENAME ofn;
ZeroMemory( &ofn , sizeof( ofn));
ofn.lStructSize = sizeof ( ofn );
ofn.hwndOwner = NULL ;
ofn.lpstrFile = fileName ;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof( fileName );
ofn.lpstrFilter = L"All Files\0*.*\0\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL ;
ofn.nMaxFileTitle = 0 ;
ofn.lpstrInitialDir = NULL ;
ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_OVERWRITEPROMPT;

if (GetSaveFileName(&ofn) == false) return;

FILE* output = _wfopen(fileName, L"wb");
if (output == NULL) {
MessageBox(wnd,L"Could not open file!",L"Error",MB_OK);
return;
}
std::string filename;
if (W32Util::BrowseForFileName(false, nullptr, L"Save Disassembly As...", nullptr, L"All Files\0*.*\0\0", nullptr, filename)) {
std::wstring fileName = ConvertUTF8ToWString(filename);
FILE *output = _wfopen(fileName.c_str(), L"wb");
if (output == nullptr) {
MessageBox(wnd, L"Could not open file!", L"Error", MB_OK);
return;
}

std::string disassembly = disassembleRange(curAddress,size);
fprintf(output,"%s",disassembly.c_str());
std::string disassembly = disassembleRange(curAddress, size);
fprintf(output, "%s", disassembly.c_str());

fclose(output);
MessageBox(wnd,L"Finished!",L"Done",MB_OK);
fclose(output);
MessageBox(wnd, L"Finished!", L"Done", MB_OK);
}
}

void CtrlDisAsmView::getOpcodeText(u32 address, char* dest, int bufsize)
Expand Down
96 changes: 54 additions & 42 deletions Windows/W32Util/ShellUtil.cpp
Expand Up @@ -9,10 +9,10 @@

#include "util/text/utf8.h"
#include "ShellUtil.h"
#include "CommDlg.h"

#include <shlobj.h>
#include <commdlg.h>
#include <cderr.h>

namespace W32Util
{
Expand Down Expand Up @@ -44,80 +44,92 @@ namespace W32Util
//---------------------------------------------------------------------------------------------------
// function WinBrowseForFileName
//---------------------------------------------------------------------------------------------------
bool BrowseForFileName (bool _bLoad, HWND _hParent, const wchar_t *_pTitle,
const wchar_t *_pInitialFolder,const wchar_t *_pFilter,const wchar_t *_pExtension,
std::string& _strFileName)
{
wchar_t szFile [MAX_PATH+1] = {0};
wchar_t szFileTitle [MAX_PATH+1] = {0};
bool BrowseForFileName(bool _bLoad, HWND _hParent, const wchar_t *_pTitle,
const wchar_t *_pInitialFolder, const wchar_t *_pFilter, const wchar_t *_pExtension,
std::string &_strFileName) {
// Let's hope this is large enough, don't want to trigger the dialog twice...
std::wstring filenameBuffer(32768 * 10, '\0');

OPENFILENAME ofn{ sizeof(OPENFILENAME) };

auto resetFileBuffer = [&] {
ofn.nMaxFile = (DWORD)filenameBuffer.size();
ofn.lpstrFile = &filenameBuffer[0];
if (!_strFileName.empty())
wcsncpy(ofn.lpstrFile, ConvertUTF8ToWString(_strFileName).c_str(), filenameBuffer.size() - 1);
};

resetFileBuffer();
ofn.lpstrInitialDir = _pInitialFolder;
ofn.lpstrFilter = _pFilter;
ofn.nMaxFile = ARRAY_SIZE(szFile);
ofn.lpstrFile = szFile;
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = ARRAY_SIZE(szFileTitle);
ofn.lpstrFileTitle = nullptr;
ofn.nMaxFileTitle = 0;
ofn.lpstrDefExt = _pExtension;
ofn.hwndOwner = _hParent;
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY;

if (!_strFileName.empty())
wcsncpy(ofn.lpstrFile, ConvertUTF8ToWString(_strFileName).c_str(), MAX_PATH);
int success = _bLoad ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn);
if (success == 0 && CommDlgExtendedError() == FNERR_BUFFERTOOSMALL) {
size_t sz = *(unsigned short *)&filenameBuffer[0];
// Documentation is unclear if this is WCHARs to CHARs.
filenameBuffer.resize(filenameBuffer.size() + sz * 2);
resetFileBuffer();
success = _bLoad ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn);
}

if (((_bLoad) ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn)))
{
if (success) {
_strFileName = ConvertWStringToUTF8(ofn.lpstrFile);
return true;
}
else
return false;
return false;
}

std::vector<std::string> BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const wchar_t *_pTitle,
const wchar_t *_pInitialFolder,const wchar_t *_pFilter,const wchar_t *_pExtension)
{
wchar_t szFile [MAX_PATH+1+2048*2] = {0};
wchar_t szFileTitle [MAX_PATH+1] = {0};
const wchar_t *_pInitialFolder, const wchar_t *_pFilter, const wchar_t *_pExtension) {
// Let's hope this is large enough, don't want to trigger the dialog twice...
std::wstring filenameBuffer(32768 * 10, '\0');

OPENFILENAME ofn{ sizeof(OPENFILENAME) };

auto resetFileBuffer = [&] {
ofn.nMaxFile = (DWORD)filenameBuffer.size();
ofn.lpstrFile = &filenameBuffer[0];
};

resetFileBuffer();
ofn.lpstrInitialDir = _pInitialFolder;
ofn.lpstrFilter = _pFilter;
ofn.nMaxFile = ARRAY_SIZE(szFile);
ofn.lpstrFile = szFile;
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = ARRAY_SIZE(szFileTitle);
ofn.lpstrFileTitle = nullptr;
ofn.nMaxFileTitle = 0;
ofn.lpstrDefExt = _pExtension;
ofn.hwndOwner = _hParent;
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT;

std::vector<std::string> files;
int success = _bLoad ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn);
if (success == 0 && CommDlgExtendedError() == FNERR_BUFFERTOOSMALL) {
size_t sz = *(unsigned short *)&filenameBuffer[0];
// Documentation is unclear if this is WCHARs to CHARs.
filenameBuffer.resize(filenameBuffer.size() + sz * 2);
resetFileBuffer();
success = _bLoad ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn);
}

if (((_bLoad) ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn)))
{
if (success) {
std::string directory = ConvertWStringToUTF8(ofn.lpstrFile);
wchar_t *temp = ofn.lpstrFile;
wchar_t *oldtemp = temp;
temp += wcslen(temp)+1;
if (*temp==0)
{
temp += wcslen(temp) + 1;
if (*temp == 0) {
//we only got one file
files.push_back(ConvertWStringToUTF8(oldtemp));
}
else
{
while (*temp)
{
files.push_back(directory+"\\"+ConvertWStringToUTF8(temp));
temp += wcslen(temp)+1;
files.push_back(directory);
} else {
while (*temp) {
files.push_back(directory + "\\" + ConvertWStringToUTF8(temp));
temp += wcslen(temp) + 1;
}
}
return files;
}
else
return std::vector<std::string>(); // empty vector;
return files;
}

AsyncBrowseDialog::AsyncBrowseDialog(HWND parent, UINT completeMsg, std::wstring title)
Expand Down

0 comments on commit 97ac18c

Please sign in to comment.