Added API for compiler host to choose a different output path on output error
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7169 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
13121dacfe
commit
322c7ac6d2
6 changed files with 131 additions and 15 deletions
|
@ -497,9 +497,10 @@ INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam
|
||||||
case MakensisAPI::QUERYHOST: {
|
case MakensisAPI::QUERYHOST: {
|
||||||
if (MakensisAPI::QH_OUTPUTCHARSET == wParam) {
|
if (MakensisAPI::QH_OUTPUTCHARSET == wParam) {
|
||||||
const UINT reqcp = 1200; // We want UTF-16LE
|
const UINT reqcp = 1200; // We want UTF-16LE
|
||||||
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)(1+reqcp));
|
return DlgRet(hwndDlg, (LONG_PTR)(1+reqcp));
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
else if (MakensisAPI::QH_SUPPORTEDVERSION == wParam)
|
||||||
|
return DlgRet(hwndDlg, 0x03006000);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
case WM_NOTIFY:
|
case WM_NOTIFY:
|
||||||
|
@ -546,7 +547,8 @@ INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case WM_COPYDATA:
|
case WM_COPYDATA:
|
||||||
{
|
{
|
||||||
PCOPYDATASTRUCT cds = PCOPYDATASTRUCT(lParam);
|
using namespace MakensisAPI;
|
||||||
|
COPYDATASTRUCT *cds = (COPYDATASTRUCT*) lParam, cdsret;
|
||||||
switch (cds->dwData) {
|
switch (cds->dwData) {
|
||||||
case MakensisAPI::NOTIFY_SCRIPT:
|
case MakensisAPI::NOTIFY_SCRIPT:
|
||||||
MemSafeFree(g_sdata.input_script);
|
MemSafeFree(g_sdata.input_script);
|
||||||
|
@ -564,6 +566,24 @@ INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam
|
||||||
g_sdata.output_exe = (TCHAR*) MemAlloc(cds->cbData * sizeof(TCHAR));
|
g_sdata.output_exe = (TCHAR*) MemAlloc(cds->cbData * sizeof(TCHAR));
|
||||||
lstrcpy(g_sdata.output_exe, (TCHAR *)cds->lpData);
|
lstrcpy(g_sdata.output_exe, (TCHAR *)cds->lpData);
|
||||||
break;
|
break;
|
||||||
|
case MakensisAPI::PROMPT_FILEPATH:
|
||||||
|
if ((((PROMPT_FILEPATH_DATA*)cds->lpData)->Platform & 7) == sizeof(TCHAR))
|
||||||
|
{
|
||||||
|
TCHAR buf[MAX_PATH];
|
||||||
|
lstrcpyn(buf, FSPath::FindLastComponent(((PROMPT_FILEPATH_DATA*)cds->lpData)->Path), COUNTOF(buf));
|
||||||
|
OPENFILENAME of = { sizeof(of) };
|
||||||
|
of.hwndOwner = hwndDlg;
|
||||||
|
of.lpstrFilter = _T("*.exe\0*.exe\0*\0*.*\0");
|
||||||
|
of.lpstrFile = buf, of.nMaxFile = COUNTOF(buf);
|
||||||
|
of.Flags = OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR;
|
||||||
|
if (GetSaveFileName(&of))
|
||||||
|
{
|
||||||
|
cdsret.dwData = cds->dwData, cdsret.cbData = (lstrlen(buf) + 1) * sizeof(TCHAR), cdsret.lpData = buf;
|
||||||
|
SendMessage((HWND) wParam, WM_COPYDATA, (SIZE_T) hwndDlg, (SIZE_T) &cdsret);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,18 +94,26 @@ namespace MakensisAPI {
|
||||||
extern const TCHAR* SigintEventNameFmt;
|
extern const TCHAR* SigintEventNameFmt;
|
||||||
extern const TCHAR* SigintEventNameLegacy;
|
extern const TCHAR* SigintEventNameLegacy;
|
||||||
|
|
||||||
enum notify_e {
|
enum datatransfer_e {
|
||||||
NOTIFY_SCRIPT,
|
NOTIFY_SCRIPT,
|
||||||
NOTIFY_WARNING,
|
NOTIFY_WARNING,
|
||||||
NOTIFY_ERROR,
|
NOTIFY_ERROR,
|
||||||
NOTIFY_OUTPUT
|
NOTIFY_OUTPUT,
|
||||||
|
PROMPT_FILEPATH
|
||||||
};
|
};
|
||||||
enum sndmsg_e {
|
enum sndmsg_e {
|
||||||
QUERYHOST = WM_APP
|
QUERYHOST = WM_APP
|
||||||
};
|
};
|
||||||
enum QUERYHOST_e {
|
enum QUERYHOST_e {
|
||||||
QH_OUTPUTCHARSET = 1
|
QH_OUTPUTCHARSET = 1,
|
||||||
|
QH_ENABLESTDERR,
|
||||||
|
QH_SUPPORTEDVERSION
|
||||||
};
|
};
|
||||||
|
typedef struct {
|
||||||
|
unsigned char Platform;
|
||||||
|
unsigned char Reserved;
|
||||||
|
TCHAR Path[1];
|
||||||
|
} PROMPT_FILEPATH_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -64,6 +64,7 @@ void LogMessage(HWND hwnd,const TCHAR *str);
|
||||||
void ErrorMessage(HWND hwnd,const TCHAR *str);
|
void ErrorMessage(HWND hwnd,const TCHAR *str);
|
||||||
void CenterOnParent(HWND hwnd);
|
void CenterOnParent(HWND hwnd);
|
||||||
void SetDialogFocus(HWND hDlg, HWND hCtl); // Use this and not SetFocus()!
|
void SetDialogFocus(HWND hDlg, HWND hCtl); // Use this and not SetFocus()!
|
||||||
|
#define DlgRet(hDlg, val) ( SetWindowLongPtr((hDlg), DWLP_MSGRESULT, (val)) | TRUE )
|
||||||
HWND GetComboEdit(HWND hCB);
|
HWND GetComboEdit(HWND hCB);
|
||||||
#define DisableItems(hwnd) EnableDisableItems(hwnd, 0)
|
#define DisableItems(hwnd) EnableDisableItems(hwnd, 0)
|
||||||
#define EnableItems(hwnd) EnableDisableItems(hwnd, 1)
|
#define EnableItems(hwnd) EnableDisableItems(hwnd, 1)
|
||||||
|
@ -90,6 +91,18 @@ void BuildMRUMenus();
|
||||||
void LoadMRUFile(int position);
|
void LoadMRUFile(int position);
|
||||||
void ClearMRUList();
|
void ClearMRUList();
|
||||||
|
|
||||||
|
struct FSPath {
|
||||||
|
template<class T> static inline bool IsAgnosticSeparator(const T c) { return '\\' == c || '/' == c; }
|
||||||
|
template<class T> static T* FindLastComponent(T*p) // Note: Returns "" for "dir\"
|
||||||
|
{
|
||||||
|
for (T *sep = 0, *start = p;; ++p)
|
||||||
|
if (!*p)
|
||||||
|
return sep ? ++sep : start;
|
||||||
|
else if (IsAgnosticSeparator(*p))
|
||||||
|
sep = p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool FileExists(const TCHAR *fname);
|
bool FileExists(const TCHAR *fname);
|
||||||
bool OpenUrlInDefaultBrowser(HWND hwnd, LPCSTR Url);
|
bool OpenUrlInDefaultBrowser(HWND hwnd, LPCSTR Url);
|
||||||
|
|
||||||
|
|
|
@ -2646,8 +2646,8 @@ int CEXEBuild::write_output(void)
|
||||||
|
|
||||||
RET_UNLESS_OK( uninstall_generate() );
|
RET_UNLESS_OK( uninstall_generate() );
|
||||||
|
|
||||||
crc32_t crc=0;
|
unsigned char limit = 0; // Limit the number of retries in case the host has some kind of bug
|
||||||
|
retry_output:
|
||||||
{
|
{
|
||||||
tstring full_path = get_full_path(build_output_filename), fnamebuf = get_file_name(build_output_filename);
|
tstring full_path = get_full_path(build_output_filename), fnamebuf = get_file_name(build_output_filename);
|
||||||
notify(MakensisAPI::NOTIFY_OUTPUT, full_path.c_str());
|
notify(MakensisAPI::NOTIFY_OUTPUT, full_path.c_str());
|
||||||
|
@ -2667,6 +2667,7 @@ int CEXEBuild::write_output(void)
|
||||||
if (!fp)
|
if (!fp)
|
||||||
{
|
{
|
||||||
ERROR_MSG(_T("Can't open output file\n"));
|
ERROR_MSG(_T("Can't open output file\n"));
|
||||||
|
if (++limit && prompt_for_output_path(build_output_filename, COUNTOF(CEXEBuild::build_output_filename))) goto retry_output;
|
||||||
return PS_ERROR;
|
return PS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2677,6 +2678,7 @@ int CEXEBuild::write_output(void)
|
||||||
return PS_ERROR;
|
return PS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crc32_t crc=0;
|
||||||
#ifdef NSIS_CONFIG_CRC_SUPPORT
|
#ifdef NSIS_CONFIG_CRC_SUPPORT
|
||||||
#ifdef NSIS_CONFIG_CRC_ANAL
|
#ifdef NSIS_CONFIG_CRC_ANAL
|
||||||
crc=CRC32(crc,m_exehead,(DWORD)m_exehead_size);
|
crc=CRC32(crc,m_exehead,(DWORD)m_exehead_size);
|
||||||
|
@ -3479,7 +3481,7 @@ void CEXEBuild::warninghelper(DIAGCODE dc, bool fl, const TCHAR *fmt, va_list ar
|
||||||
|
|
||||||
m_warnings.add(msg,0); // Add to list of warnings to display at the end
|
m_warnings.add(msg,0); // Add to list of warnings to display at the end
|
||||||
|
|
||||||
MakensisAPI::notify_e hostevent = MakensisAPI::NOTIFY_WARNING;
|
MakensisAPI::datatransfer_e hostevent = MakensisAPI::NOTIFY_WARNING;
|
||||||
if (aserror)
|
if (aserror)
|
||||||
hostevent = MakensisAPI::NOTIFY_ERROR, display_warnings = display_errors;
|
hostevent = MakensisAPI::NOTIFY_ERROR, display_warnings = display_errors;
|
||||||
|
|
||||||
|
@ -3571,7 +3573,7 @@ void CEXEBuild::print_warnings()
|
||||||
FlushOutputAndResetPrintColor();
|
FlushOutputAndResetPrintColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXEBuild::notify(MakensisAPI::notify_e code, const TCHAR *data) const
|
void CEXEBuild::notify(MakensisAPI::datatransfer_e code, const TCHAR *data) const
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (notify_hwnd)
|
if (notify_hwnd)
|
||||||
|
@ -3595,6 +3597,64 @@ void CEXEBuild::notify(MakensisAPI::notify_e code, const TCHAR *data) const
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CEXEBuild::hostapi_request_data(MakensisAPI::datatransfer_e operation, UINT minver, HOSTAPIREQUESTDATAPROC proc, void*cookie, const void* input, UINT inputsize) const
|
||||||
|
{
|
||||||
|
using namespace MakensisAPI;
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct helper {
|
||||||
|
static INT_PTR CALLBACK Proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
size_t *data = (size_t*) GetWindowLongPtr(hWnd, DWLP_USER);
|
||||||
|
if (Msg == WM_CLOSE)
|
||||||
|
{
|
||||||
|
if (lParam) SendMessage((HWND) wParam, WM_COPYDATA, (SIZE_T) hWnd, lParam);
|
||||||
|
return DestroyWindow(hWnd) | PostMessage(NULL, WM_QUIT, 0, 0);
|
||||||
|
}
|
||||||
|
return data && ((HOSTAPIREQUESTDATAPROC)data[0])((void*) data[1], hWnd, Msg, wParam, lParam); // We don't set DWLP_MSGRESULT nor care about the return value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!notify_hwnd || (minver && SendMessage(notify_hwnd, QUERYHOST, QH_SUPPORTEDVERSION, 0) < minver)) return false;
|
||||||
|
size_t data[] = { (size_t) proc, (size_t) cookie };
|
||||||
|
COPYDATASTRUCT cds = { (DWORD) operation, inputsize, (void*) input };
|
||||||
|
HWND hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, WC_DIALOG, NULL, WS_POPUP|WS_DISABLED, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
|
||||||
|
SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR) data);
|
||||||
|
SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR) helper::Proc);
|
||||||
|
SendMessage(hWnd, WM_CLOSE, (SIZE_T) notify_hwnd, (SIZE_T) &cds);
|
||||||
|
for (MSG msg; (int) GetMessage(&msg, NULL, 0, 0) > 0;) DispatchMessage(&msg);
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CEXEBuild::prompt_for_output_path(TCHAR*path, UINT pathcap) const
|
||||||
|
{
|
||||||
|
using namespace MakensisAPI;
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct handler {
|
||||||
|
static bool CALLBACK proc(void*cookie, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
size_t *io = (size_t*) cookie;
|
||||||
|
COPYDATASTRUCT*pCDS = (COPYDATASTRUCT*) lParam;
|
||||||
|
if (Msg == WM_COPYDATA && pCDS->cbData > sizeof(TCHAR) && pCDS->cbData <= io[2] * sizeof(TCHAR))
|
||||||
|
{
|
||||||
|
_tcscpy((TCHAR*) io[1], (TCHAR*) ((COPYDATASTRUCT*)lParam)->lpData);
|
||||||
|
return (io[0] = pCDS->dwData == PROMPT_FILEPATH);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
size_t io[] = { false, (size_t) path, pathcap }, cb;
|
||||||
|
TinyGrowBuf inputbuf((cb = FIELD_OFFSET(PROMPT_FILEPATH_DATA, Path[pathcap])));
|
||||||
|
PROMPT_FILEPATH_DATA *p = (PROMPT_FILEPATH_DATA*) inputbuf.get();
|
||||||
|
p->Platform = (sizeof(void*) * 8) | sizeof(TCHAR), p->Reserved = 0;
|
||||||
|
_tcscpy(p->Path, path);
|
||||||
|
return hostapi_request_data(PROMPT_FILEPATH, 0x03006000, handler::proc, io, p, cb) && io[0];
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
|
#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
|
||||||
int CEXEBuild::initialize_default_plugins(bool newtargetarc)
|
int CEXEBuild::initialize_default_plugins(bool newtargetarc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -143,11 +143,12 @@ namespace MakensisAPI {
|
||||||
extern const TCHAR* SigintEventNameFmt;
|
extern const TCHAR* SigintEventNameFmt;
|
||||||
extern const TCHAR* SigintEventNameLegacy;
|
extern const TCHAR* SigintEventNameLegacy;
|
||||||
|
|
||||||
enum notify_e {
|
enum datatransfer_e {
|
||||||
NOTIFY_SCRIPT, // main nsi file(s)
|
NOTIFY_SCRIPT, // Compiler -> Host: main nsi file(s)
|
||||||
NOTIFY_WARNING,
|
NOTIFY_WARNING,
|
||||||
NOTIFY_ERROR,
|
NOTIFY_ERROR,
|
||||||
NOTIFY_OUTPUT // generated .exe file
|
NOTIFY_OUTPUT, // Compiler -> Host: Generated .exe file
|
||||||
|
PROMPT_FILEPATH // [0x03006000] Compiler -> Host -> Compiler
|
||||||
};
|
};
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
enum sndmsg_e {
|
enum sndmsg_e {
|
||||||
|
@ -156,8 +157,14 @@ namespace MakensisAPI {
|
||||||
#endif
|
#endif
|
||||||
enum QUERYHOST_e {
|
enum QUERYHOST_e {
|
||||||
QH_OUTPUTCHARSET = 1, // [0x03000000] return (wincodepage+1) or 0 for default (This encoding is used by stdout, stderr and the notify messages)
|
QH_OUTPUTCHARSET = 1, // [0x03000000] return (wincodepage+1) or 0 for default (This encoding is used by stdout, stderr and the notify messages)
|
||||||
QH_ENABLESTDERR // [0x03001000] return 1 to output error messages to stderr or 0 to output error messages to stdout
|
QH_ENABLESTDERR, // [0x03001000] return 1 to output error messages to stderr or 0 to output error messages to stdout
|
||||||
|
QH_SUPPORTEDVERSION, // [0x03006000] The host must return new highest makensis compiler version it supports
|
||||||
};
|
};
|
||||||
|
typedef struct {
|
||||||
|
unsigned char Platform; // Bitness OR'ed with sizeof(TCHAR) of the compiler
|
||||||
|
unsigned char Reserved;
|
||||||
|
TCHAR Path[1];
|
||||||
|
} PROMPT_FILEPATH_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PAGE_CUSTOM 0
|
#define PAGE_CUSTOM 0
|
||||||
|
@ -273,7 +280,14 @@ class CEXEBuild {
|
||||||
NStreamLineReader* curlinereader;
|
NStreamLineReader* curlinereader;
|
||||||
|
|
||||||
HWND notify_hwnd;
|
HWND notify_hwnd;
|
||||||
void notify(MakensisAPI::notify_e code, const TCHAR *data) const;
|
void notify(MakensisAPI::datatransfer_e code, const TCHAR *data) const;
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef bool (CALLBACK*HOSTAPIREQUESTDATAPROC)(void*cookie, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
#else
|
||||||
|
typedef bool (*HOSTAPIREQUESTDATAPROC)(void*cookie);
|
||||||
|
#endif
|
||||||
|
bool hostapi_request_data(MakensisAPI::datatransfer_e operation, UINT minver, HOSTAPIREQUESTDATAPROC proc, void*cookie, const void* input, UINT inputsize) const;
|
||||||
|
bool prompt_for_output_path(TCHAR*path, UINT pathcap) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int check_write_output_errors() const;
|
int check_write_output_errors() const;
|
||||||
|
|
|
@ -122,6 +122,7 @@ class GrowBuf : public IGrowBuf
|
||||||
class TinyGrowBuf : public GrowBuf {
|
class TinyGrowBuf : public GrowBuf {
|
||||||
public:
|
public:
|
||||||
TinyGrowBuf() : GrowBuf() { m_bs=1024; }
|
TinyGrowBuf() : GrowBuf() { m_bs=1024; }
|
||||||
|
TinyGrowBuf(size_type cb) : GrowBuf() { m_bs=1024; resize(cb); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue