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:
anders_k 2020-04-20 17:21:04 +00:00
parent 13121dacfe
commit 322c7ac6d2
6 changed files with 131 additions and 15 deletions

View file

@ -2646,8 +2646,8 @@ int CEXEBuild::write_output(void)
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);
notify(MakensisAPI::NOTIFY_OUTPUT, full_path.c_str());
@ -2667,6 +2667,7 @@ int CEXEBuild::write_output(void)
if (!fp)
{
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;
}
@ -2677,6 +2678,7 @@ int CEXEBuild::write_output(void)
return PS_ERROR;
}
crc32_t crc=0;
#ifdef NSIS_CONFIG_CRC_SUPPORT
#ifdef NSIS_CONFIG_CRC_ANAL
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
MakensisAPI::notify_e hostevent = MakensisAPI::NOTIFY_WARNING;
MakensisAPI::datatransfer_e hostevent = MakensisAPI::NOTIFY_WARNING;
if (aserror)
hostevent = MakensisAPI::NOTIFY_ERROR, display_warnings = display_errors;
@ -3571,7 +3573,7 @@ void CEXEBuild::print_warnings()
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
if (notify_hwnd)
@ -3595,6 +3597,64 @@ void CEXEBuild::notify(MakensisAPI::notify_e code, const TCHAR *data) const
#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
int CEXEBuild::initialize_default_plugins(bool newtargetarc)
{

View file

@ -143,11 +143,12 @@ namespace MakensisAPI {
extern const TCHAR* SigintEventNameFmt;
extern const TCHAR* SigintEventNameLegacy;
enum notify_e {
NOTIFY_SCRIPT, // main nsi file(s)
enum datatransfer_e {
NOTIFY_SCRIPT, // Compiler -> Host: main nsi file(s)
NOTIFY_WARNING,
NOTIFY_ERROR,
NOTIFY_OUTPUT // generated .exe file
NOTIFY_OUTPUT, // Compiler -> Host: Generated .exe file
PROMPT_FILEPATH // [0x03006000] Compiler -> Host -> Compiler
};
#ifdef _WIN32
enum sndmsg_e {
@ -156,8 +157,14 @@ namespace MakensisAPI {
#endif
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_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
@ -273,7 +280,14 @@ class CEXEBuild {
NStreamLineReader* curlinereader;
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:
int check_write_output_errors() const;

View file

@ -122,6 +122,7 @@ class GrowBuf : public IGrowBuf
class TinyGrowBuf : public GrowBuf {
public:
TinyGrowBuf() : GrowBuf() { m_bs=1024; }
TinyGrowBuf(size_type cb) : GrowBuf() { m_bs=1024; resize(cb); }
};
#endif