2014-08-18 18:01:56 -05:00
|
|
|
// 18 august 2014
|
|
|
|
|
|
|
|
#include "winapi_windows.h"
|
|
|
|
#include "_cgo_export.h"
|
|
|
|
|
|
|
|
// this should be reasonable
|
|
|
|
#define NFILENAME 4096
|
|
|
|
|
2014-08-26 11:52:32 -05:00
|
|
|
struct openFileData {
|
|
|
|
HWND parent;
|
|
|
|
void *f;
|
|
|
|
WCHAR *filenameBuffer;
|
|
|
|
};
|
2014-08-19 02:31:53 -05:00
|
|
|
|
2014-08-26 11:52:32 -05:00
|
|
|
static DWORD WINAPI doOpenFile(LPVOID data)
|
2014-08-18 18:01:56 -05:00
|
|
|
{
|
2014-08-26 11:52:32 -05:00
|
|
|
struct openFileData *o = (struct openFileData *) data;
|
2014-08-18 18:01:56 -05:00
|
|
|
OPENFILENAMEW ofn;
|
|
|
|
DWORD err;
|
|
|
|
|
2014-08-26 11:52:32 -05:00
|
|
|
o->filenameBuffer[0] = L'\0'; // required by GetOpenFileName() to indicate no previous filename
|
2014-08-18 18:01:56 -05:00
|
|
|
ZeroMemory(&ofn, sizeof (OPENFILENAMEW));
|
|
|
|
ofn.lStructSize = sizeof (OPENFILENAMEW);
|
2014-08-26 11:52:32 -05:00
|
|
|
ofn.hwndOwner = o->parent;
|
2014-08-18 18:01:56 -05:00
|
|
|
ofn.hInstance = hInstance;
|
|
|
|
ofn.lpstrFilter = NULL; // no filters
|
2014-08-26 11:52:32 -05:00
|
|
|
ofn.lpstrFile = o->filenameBuffer;
|
2014-08-27 16:49:44 -05:00
|
|
|
ofn.nMaxFile = NFILENAME + 1; // seems to include null terminator according to docs
|
2014-08-18 18:01:56 -05:00
|
|
|
ofn.lpstrInitialDir = NULL; // let system decide
|
|
|
|
ofn.lpstrTitle = NULL; // let system decide
|
|
|
|
// TODO OFN_SHAREAWARE?
|
2014-08-31 18:07:55 -05:00
|
|
|
// better question: TODO keep networking?
|
2014-08-26 11:52:32 -05:00
|
|
|
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_FORCESHOWHIDDEN | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_NOCHANGEDIR | OFN_NODEREFERENCELINKS | OFN_NOTESTFILECREATE | OFN_PATHMUSTEXIST;
|
2014-08-18 18:01:56 -05:00
|
|
|
if (GetOpenFileNameW(&ofn) == FALSE) {
|
|
|
|
err = CommDlgExtendedError();
|
2014-08-26 11:52:32 -05:00
|
|
|
if (err != 0) // user cancelled
|
|
|
|
xpaniccomdlg("error running open file dialog", err);
|
|
|
|
free(o->filenameBuffer); // free now so we can set it to NULL without leaking
|
|
|
|
o->filenameBuffer = NULL;
|
2014-08-18 18:01:56 -05:00
|
|
|
}
|
2014-08-26 11:52:32 -05:00
|
|
|
if (PostMessageW(msgwin, msgOpenFileDone, (WPARAM) (o->filenameBuffer), (LPARAM) (o->f)) == 0)
|
|
|
|
xpanic("error posting OpenFile() finished message to message-only window", GetLastError());
|
|
|
|
free(o); // won't free o->f or o->filenameBuffer in above invocation
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void openFile(HWND hwnd, void *f)
|
|
|
|
{
|
|
|
|
struct openFileData *o;
|
|
|
|
|
|
|
|
// freed by the thread
|
|
|
|
o = (struct openFileData *) malloc(sizeof (struct openFileData));
|
|
|
|
if (o == NULL)
|
|
|
|
xpanic("memory exhausted allocating data structure in OpenFile()", GetLastError());
|
|
|
|
o->parent = hwnd;
|
|
|
|
o->f = f;
|
|
|
|
// freed on the Go side
|
|
|
|
o->filenameBuffer = (WCHAR *) malloc((NFILENAME + 1) * sizeof (WCHAR));
|
|
|
|
if (o->filenameBuffer == NULL)
|
|
|
|
xpanic("memory exhausted allocating filename buffer in OpenFile()", GetLastError());
|
|
|
|
if (CreateThread(NULL, 0, doOpenFile, (LPVOID) o, 0, NULL) == NULL)
|
|
|
|
xpanic("error creating thread for running OpenFIle()", GetLastError());
|
2014-08-18 18:01:56 -05:00
|
|
|
}
|