MakeNSIS can now generate Unicode or Ansi installers based on a script attribute. SCons generates both Ansi and Unicode stubs and plugins.

The official plugins are now stored in architecture specific subdirectories under NSIS\Plugins. !AddPluginDir also gained a new (optional) architecture flag because MakeNSIS now stores separate plugin information for each target architecture. Storing plugins in the root of the Plugins directory is no longer supported.

MinGW does not implement the unicode CRT startup functions so the entry point functions and linker parameters had to be changed. The unicode tools use the ansi entry point and a small helper function that calls into the real code: _tmain has full argc+argv emulation while wWinMain does not pass the command line parameters. The stubs do not use any CRT functions and have no CRT or unicode helper code, they call our entry point directly.



git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6269 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2012-10-13 01:47:50 +00:00
parent 8f330bbbdf
commit 7cc150c464
73 changed files with 936 additions and 713 deletions

View file

@ -40,7 +40,52 @@ using namespace std;
extern FILE *g_output;
void Plugins::FindCommands(const tstring &path, bool displayInfo)
namespace {
template <class C, class K>
bool contains(const C& cntnr, const K& key)
{
return cntnr.find(key) != cntnr.end();
}
template <class C, class K>
const typename C::const_iterator get_iterator(const C& cntnr, const K& key)
{
assert( contains(cntnr, key) );
return cntnr.find(key);
}
template <class C, class K>
typename C::const_iterator::value_type get_value(const C& cntnr, const K& key)
{
return *get_iterator(cntnr,key);
}
template <class C, class K>
typename C::value_type::second_type get_paired_value(const C& cntnr, const K& key)
{
return get_iterator(cntnr,key)->second;
}
template <class V,class C, class K>
V get_paired_value(const C& cntnr, const K& key, const V& defval)
{
typename C::const_iterator it = cntnr.find(key);
return cntnr.end() == it ? defval : it->second;
}
}
static inline tstring GetDllName(const tstring&command)
{
return get_string_prefix(command, _T("::"));
}
static inline void PrintCommandSig(const tstring sig)
{
_ftprintf(g_output, _T(" + %s\n"), sig.c_str());
}
void Plugins::AddPluginsDir(const tstring &path, bool displayInfo)
{
boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
dr->read(path);
@ -71,11 +116,10 @@ struct NSISException : public NSISExceptionInner
namespace {
// This function slurps the whole file into the vector.
// Modified so the huge vector isn't returned by value.
void read_file(const tstring& filename, vector<unsigned char>& data) {
void read_file(const tstring& filename, vector<unsigned char>& data)
{
FILE*file = FOPEN(filename.c_str(), ("rb"));
if (!file) throw NSISException(_T("Can't open file '") + filename + _T("'"));
MANAGE_WITH(file, fclose);
bool succ = false;
@ -104,9 +148,10 @@ void Plugins::GetExports(const tstring &pathToDll, bool displayInfo)
}
tstring dllName = remove_file_extension(get_file_name(pathToDll));
#ifdef _UNICODE
bool unicodeDll = dllName[dllName.size()-1] == 'W';
#endif
if (DllHasDataHandle(dllName))
{
m_dllname_conflicts.insert(dllName);
}
FIX_ENDIAN_INT16_INPLACE(NTHeaders->FileHeader.Characteristics);
if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
@ -135,19 +180,16 @@ void Plugins::GetExports(const tstring &pathToDll, bool displayInfo)
LPDWORD names = (LPDWORD)((ULONG_PTR)exports + na - ExportDirVA);
for (DWORD j = 0; j < FIX_ENDIAN_INT32(exports->NumberOfNames); j++)
{
if (0 == j) m_dllname_to_path[dllName] = pathToDll;
const string name = string((char*)exports + FIX_ENDIAN_INT32(names[j]) - ExportDirVA);
const tstring signature = dllName + _T("::") + tstring(CtoTString(name));
const tstring lcsig = lowercase(signature);
m_command_to_path[lcsig] = pathToDll;
m_command_lowercase_to_command[lcsig] = signature;
#ifdef _UNICODE
const tstring lcsigA = lowercase(dllName.substr(0,dllName.size()-1) + _T("::") + tstring(CtoTString(name)));
if (unicodeDll && m_command_to_path.find(lcsigA) != m_command_to_path.end())
m_unicode_variant[lcsigA] = signature;
else
#endif
const tstring canoniccmd = dllName + _T("::") + tstring(CtoTString(name));
if (displayInfo)
_ftprintf(g_output, _T(" - %s\n"), signature.c_str());
{
bool hadCmd = contains(m_commands, canoniccmd);
if (!hadCmd) PrintCommandSig(canoniccmd);
}
m_commands.insert(canoniccmd);
}
break;
}
@ -155,59 +197,54 @@ void Plugins::GetExports(const tstring &pathToDll, bool displayInfo)
}
}
bool Plugins::IsPluginCommand(const tstring& token) const {
return m_command_to_path.find(lowercase(token)) != m_command_to_path.end();
}
namespace {
template <class Key, class Value>
Value get_value(const map<Key, Value>& the_map,
const Key& key)
int Plugins::GetDllDataHandle(bool uninst, const tstring& command) const
{
assert(the_map.find(key) != the_map.end());
return the_map.find(key)->second;
const tstring dllname = GetDllName(command);
if (uninst)
return get_paired_value(m_dllname_to_unst_datahandle, dllname, -1);
else
return get_paired_value(m_dllname_to_inst_datahandle, dllname, -1);
}
template <class Key, class Value>
Value get_value(const map<Key, Value>& the_map,
const Key& key,
const Value& defaultValue)
void Plugins::SetDllDataHandle(bool uninst, tstring&canoniccmd, int dataHandle)
{
if (the_map.find(key) == the_map.end())
return defaultValue;
return the_map.find(key)->second;
}
const tstring dllname = GetDllName(canoniccmd);
if (uninst)
m_dllname_to_unst_datahandle[dllname] = dataHandle;
else
m_dllname_to_inst_datahandle[dllname] = dataHandle;
}
tstring Plugins::NormalizedCommand(const tstring& command) const {
return get_value(m_command_lowercase_to_command, lowercase(command));
}
tstring Plugins::UseUnicodeVariant(const tstring& command) const {
return get_value(m_unicode_variant, lowercase(command), command);
}
int Plugins::GetPluginHandle(bool uninst, const tstring& command) const {
if (uninst) {
return get_value(m_command_to_uninstall_data_handle, command, -1);
}
else {
return get_value(m_command_to_data_handle, command, -1);
}
}
tstring Plugins::GetPluginPath(const tstring& command) const {
return get_value(m_command_to_path, lowercase(command));
}
void Plugins::SetDllDataHandle(bool uninst, const tstring& command, int dataHandle)
bool Plugins::DllHasDataHandle(const tstring& dllnamelowercase) const
{
if (uninst) {
m_command_to_uninstall_data_handle[command] = dataHandle;
}
else {
m_command_to_data_handle[command] = dataHandle;
}
int h = GetDllDataHandle(false, dllnamelowercase);
if (-1 == h) h = GetDllDataHandle(true, dllnamelowercase);
return -1 != h;
}
bool Plugins::Initialize(const TCHAR*arcsubdir, bool displayInfo)
{
if (m_initialized) return true;
m_initialized = true;
AddPluginsDir(tstring(arcsubdir), displayInfo);
return true;
}
bool Plugins::GetCommandInfo(const tstring&command, tstring&canoniccmd, tstring&dllPath)
{
const tstring dllname = GetDllName(command);
dllPath = get_paired_value(m_dllname_to_path, dllname);
canoniccmd = get_value(m_commands, command);
return !contains(m_dllname_conflicts, dllname);
}
bool Plugins::IsPluginCommand(const tstring& token) const
{
return contains(m_commands, token);
}
#endif