- Improved file mapping so you can now esaily compile installers up to 2GB with a minimum requirment of memory (changable by FileBufSize)

- Fixed DirText
- Fixed new browse dialog style problems (thanks LIGHTNING UK!)


git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2919 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
kichik 2003-09-15 22:05:06 +00:00
parent 624f7225f4
commit de0104cc39
10 changed files with 727 additions and 176 deletions

View file

@ -8,6 +8,12 @@ The following commands change how the compiler generates code and compresses dat
This command specifies whether the user should be able to skip a file or not. A user has an option to skip a file if \R{asetoverwrite}{SetOverwrite} is set to on (default) and the installer fails to open a file for writing when trying to extract a file. If \e{off} is used the ignore button which allows the user to skip the file will not show and the user will only have an option to abort the installation (Cancel button) or retry opening the file for writing (Retry button). If \e{on} is used the user will have an option to skip the file (error flag will be set - see \R{asetoverwrite}{SetOverwrite}).
\S2{afilebufsize} FileBufSize
\c buffer_size_in_mb
This command sets the size of the compiler's internal file buffers. This command allows you to control the compiler's memory usage by limiting how much of a given file it will load into memory at once. Since the compiler needs both input and output, twice the memory size specified could be used at any given time for file buffers. This command does not limit the compression buffers which could take another couple of MB, neither does it limit the compiler's other internal buffers, but those shouldn't normally top 1MB anyway. Specifying a very small number could decrease performance. Specifying a very large number could exhaust system resources and force the compiler to cancel the compilation process. The default value is 32MB.
\S2{asetcompress} SetCompress
\c \\<b\\>auto\\</b\\>|force|off

View file

@ -9,6 +9,10 @@
\b Extraction progress
\b Improved large files handling (way lower requirements to compile a 2GB installer now)
\b Added \R{afilebufsize}{FileBufSize}
\b \W{../Contrib/Modern UI/Readme.html}{Modern UI 1.65}: Easier page macro system, language specific fonts, \R{alicenseforceselection}{LicenseForceSelection} support, new options for Finish page / language selection dialog, fixes, more
\b Added \R{asetallowskipfiles}{AllowSkipFiles}: Set whether the user should be able to skip a file when overwriting failed

View file

@ -13,6 +13,8 @@
#include "DialogTemplate.h"
#include "ResourceVersionInfo.h"
int MMapFile::m_iAllocationGranularity = 0;
bool isSimpleChar(char ch)
{
return (ch == '.' ) || (ch == '_' ) || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
@ -269,6 +271,8 @@ CEXEBuild::CEXEBuild()
cur_page=0;
cur_page_type=-1;
build_filebuflen=32<<20; // 32mb
subsection_open_cnt=0;
build_cursection_isfunc=0;
build_cursection=NULL;
@ -678,28 +682,205 @@ int CEXEBuild::preprocess_string(char *out, const char *in)
int CEXEBuild::datablock_optimize(int start_offset)
{
int this_len = cur_datablock->getlen()-start_offset;
int pos=0;
int this_len = cur_datablock->getlen() - start_offset;
int pos = 0;
if (!build_optimize_datablock) return start_offset;
if (!build_optimize_datablock || this_len < sizeof(int))
return start_offset;
char *db=(char*)cur_datablock->get();
int first_int=*(int*)(db+start_offset);
if (this_len >= 4) while (pos < start_offset)
MMapBuf *db = (MMapBuf *) cur_datablock;
db->setro(TRUE);
int first_int = *(int *) db->get(start_offset, sizeof(int));
db->release();
while (pos < start_offset)
{
int this_int = *(int*)(db+pos);
if (this_int == first_int && !memcmp(db+pos,db+start_offset,this_len))
int this_int = *(int *) db->get(pos, sizeof(int));
db->release();
if (this_int == first_int)
{
db_opt_save+=this_len;
cur_datablock->resize(max(start_offset,pos+this_len));
return pos;
int left = this_len;
while (left > 0)
{
int l = min(left, build_filebuflen);
void *newstuff = db->get(start_offset + this_len - left, l);
void *oldstuff = db->getmore(pos + this_len - left, l);
int res = memcmp(newstuff, oldstuff, l);
db->release(oldstuff);
db->release();
if (res)
{
break;
}
left -= l;
}
if (!left)
{
db_opt_save += this_len;
db->resize(max(start_offset, pos + this_len));
return pos;
}
}
pos += 4 + (this_int&0x7fffffff);
pos += sizeof(int) + (this_int & 0x7fffffff);
}
db->setro(FALSE);
return start_offset;
}
int CEXEBuild::add_db_data(IMMap *map) // returns offset
{
build_compressor_set = true;
int done = 0;
if (!map)
{
ERROR_MSG("Error: add_db_data() called with invalid mapped file\n");
return -1;
}
int length = map->getsize();
if (length < 0)
{
ERROR_MSG("Error: add_db_data() called with length=%d\n", length);
return -1;
}
MMapBuf *db = (MMapBuf *) cur_datablock;
int st = db->getlen();
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
if (!build_compress_whole && build_compress)
{
// grow datablock so that there is room to compress into
int bufferlen = length + 1024 + length / 4; // give a nice 25% extra space
db->resize(st + bufferlen + sizeof(int));
int n;
if ((n = compressor->Init(9)) != C_OK)
{
ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%d).\n", n);
extern void quit(); quit();
}
int avail_in = length;
int avail_out = bufferlen;
int ret;
while (avail_in > 0)
{
int in_len = min(build_filebuflen, avail_in);
int out_len = min(build_filebuflen, avail_out);
compressor->SetNextIn((char *) map->get(length - avail_in, in_len), in_len);
compressor->SetNextOut((char *) db->get(st + sizeof(int) + bufferlen - avail_out, out_len), out_len);
if ((ret = compressor->Compress(0)) < 0)
{
ERROR_MSG("Error: add_db_data() - compress() failed - %d\n", ret);
return -1;
}
map->release();
db->flush(out_len);
db->release();
avail_in -= in_len - compressor->GetAvailIn();
avail_out -= out_len - compressor->GetAvailOut();
if (!avail_out)
// not enough space in the output buffer - no compression is better
break;
}
// if not enough space in the output buffer - no compression is better
if (avail_out)
{
char *out;
do
{
int out_len = min(build_filebuflen, avail_out);
out = (char *) db->get(st + sizeof(int) + bufferlen - avail_out, out_len);
compressor->SetNextOut(out, out_len);
if ((ret = compressor->Compress(C_FINISH)) < 0)
{
ERROR_MSG("Error: add_db_data() - compress() failed - %d\n", ret);
return -1;
}
db->flush(out_len);
db->release();
avail_out -= out_len - compressor->GetAvailOut();
}
while (compressor->GetNextOut() - out > 0);
int used = bufferlen - avail_out;
// never store compressed if output buffer is full (compression increased the size...)
if (avail_out && (build_compress == 2 || used < length))
{
done=1;
db->resize(st + used + sizeof(int));
*(int*)db->get(st, sizeof(int)) = used | 0x80000000;
db->release();
int nst = datablock_optimize(st);
if (nst == st) db_comp_save += length - used;
else st = nst;
}
}
compressor->End();
}
#endif // NSIS_CONFIG_COMPRESSION_SUPPORT
if (!done)
{
db->resize(st + length + sizeof(int));
int *plen = (int *) db->get(st, sizeof(int));
*plen = length;
db->release();
int left = length;
while (left > 0)
{
int l = min(build_filebuflen, left);
int *p = (int *) db->get(st + sizeof(int) + length - left, l);
memcpy(p, map->get(length - left, l), l);
db->flush(l);
db->release();
map->release();
left -= l;
}
st = datablock_optimize(st);
}
db_full_size += length + sizeof(int);
return st;
}
int CEXEBuild::add_db_data(const char *data, int length) // returns offset
{
MMapFake fakemap;
fakemap.set(data, length);
return add_db_data(&fakemap);
}
int CEXEBuild::add_data(const char *data, int length, IGrowBuf *dblock) // returns offset
{
build_compressor_set=true;
@ -712,8 +893,6 @@ int CEXEBuild::add_data(const char *data, int length, IGrowBuf *dblock) // retur
return -1;
}
if (!dblock) dblock=cur_datablock;
int st=dblock->getlen();
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
@ -744,12 +923,6 @@ int CEXEBuild::add_data(const char *data, int length, IGrowBuf *dblock) // retur
dblock->resize(st+used+sizeof(int));
*((int*)((char *)dblock->get()+st)) = used|0x80000000;
if (dblock == cur_datablock)
{
int nst=datablock_optimize(st);
if (nst == st) db_comp_save+=length-used;
else st=nst;
}
}
compressor->End();
}
@ -760,15 +933,6 @@ int CEXEBuild::add_data(const char *data, int length, IGrowBuf *dblock) // retur
dblock->resize(st);
dblock->add(&length,sizeof(int));
dblock->add(data,length);
if (dblock == cur_datablock)
{
st=datablock_optimize(st);
}
}
if (dblock == cur_datablock)
{
db_full_size += length + sizeof(int);
}
return st;
@ -2143,18 +2307,6 @@ int CEXEBuild::write_output(void)
// update the header info
}
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
// Get offsets of icons to replace for uninstall
// Also makes sure that the icons are there and in the right size.
if (uninstaller_writes_used) {
SCRIPT_MSG("Finding icons offsets for uninstaller... ");
icon_offset = generate_unicons_offsets(header_data_new, m_unicon_data);
if (icon_offset == 0)
return PS_ERROR;
SCRIPT_MSG("Done!\n");
}
#endif //NSIS_CONFIG_UNINSTALL_SUPPORT
build_optimize_datablock=0;
int data_block_size_before_uninst = build_datablock.getlen();
@ -2405,12 +2557,13 @@ int CEXEBuild::write_output(void)
if (build_datablock.getlen())
{
char *dbptr=(char *)build_datablock.get();
int dbl=build_datablock.getlen();
while (dbl > 0)
build_datablock.setro(TRUE);
int dbl = build_datablock.getlen();
int left = dbl;
while (left > 0)
{
int l=dbl;
if (l > 32768) l=32768;
int l = min(build_filebuflen, left);
char *dbptr = (char *) build_datablock.get(dbl - left, l);
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
if (build_compress_whole) {
if (deflateToFile(fp,dbptr,l))
@ -2431,10 +2584,13 @@ int CEXEBuild::write_output(void)
fclose(fp);
return PS_ERROR;
}
fflush(fp);
}
dbptr+=l;
dbl-=l;
build_datablock.release();
left -= l;
}
build_datablock.setro(FALSE);
build_datablock.clear();
}
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
if (build_compress_whole)
@ -2501,7 +2657,7 @@ int CEXEBuild::deflateToFile(FILE *fp, char *buf, int len) // len==0 to flush
{
build_compressor_set=true;
char obuf[32768];
char obuf[65536];
int flush=0;
compressor->SetNextIn(buf,len);
if (!buf||!len)
@ -2527,6 +2683,7 @@ int CEXEBuild::deflateToFile(FILE *fp, char *buf, int len) // len==0 to flush
ERROR_MSG("Error: deflateToFile fwrite(%d) failed\n",l);
return 1;
}
fflush(fp);
}
if (!compressor->GetAvailIn() && (!flush || !l)) break;
}
@ -2539,6 +2696,8 @@ int CEXEBuild::uninstall_generate()
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
if (ubuild_entries.getlen() && uninstaller_writes_used)
{
SCRIPT_MSG("Generating uninstaller... ");
firstheader fh={0,};
GrowBuf uhd;
@ -2557,10 +2716,16 @@ int CEXEBuild::uninstall_generate()
int crc=0;
// Get offsets of icons to replace for uninstall
// Also makes sure that the icons are there and in the right size.
icon_offset = generate_unicons_offsets(header_data_new, m_unicon_data);
if (icon_offset == 0)
return PS_ERROR;
build_header.uninstdata_offset=build_datablock.getlen();
build_header.uninsticon_size=unicondata_size;
if (add_data((char *)m_unicon_data,unicondata_size) < 0)
if (add_db_data((char *)m_unicon_data,unicondata_size) < 0)
return PS_ERROR;
#ifdef NSIS_CONFIG_CRC_SUPPORT
#ifdef NSIS_CONFIG_CRC_ANAL
@ -2602,40 +2767,75 @@ int CEXEBuild::uninstall_generate()
fh.length_of_all_following_data=
uhd.getlen()+ubuild_datablock.getlen()+(int)sizeof(firstheader)+(build_crcchk?sizeof(int):0);
GrowBuf udata;
MMapBuf udata;
#ifdef NSIS_CONFIG_CRC_SUPPORT
if (build_crcchk)
crc = CRC32(crc, (unsigned char *) &fh, sizeof(fh));
#endif
udata.add(&fh, sizeof(fh));
ubuild_datablock.setro(TRUE);
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
if (build_compress_whole) {
// compress uninstaller too
udata.add(&fh,sizeof(fh));
{
char obuf[32768];
char obuf[65536];
if ((compressor->Init(9)) != C_OK)
{
ERROR_MSG("Error: deflateInit() returned < 0\n");
return PS_ERROR;
}
int x;
for (x = 0; x < 2; x ++)
compressor->SetNextIn((char*)uhd.get(), uhd.getlen());
while (compressor->GetAvailIn())
{
if (!x)
compressor->SetNextIn((char*)uhd.get(),uhd.getlen());
else
compressor->SetNextIn((char*)ubuild_datablock.get(),ubuild_datablock.getlen());
while (compressor->GetAvailIn())
compressor->SetNextOut(obuf, sizeof(obuf));
compressor->Compress(0);
if (compressor->GetNextOut() - obuf > 0)
{
compressor->SetNextOut(obuf,sizeof(obuf));
compressor->Compress(0);
if (compressor->GetNextOut()-obuf > 0)
udata.add(obuf,compressor->GetNextOut()-obuf);
#ifdef NSIS_CONFIG_CRC_SUPPORT
if (build_crcchk)
crc=CRC32(crc, (unsigned char *)obuf, compressor->GetNextOut() - obuf);
#endif
udata.add(obuf, compressor->GetNextOut() - obuf);
}
}
int avail_in = ubuild_datablock.getlen();
int in_pos = 0;
while (avail_in > 0) {
int l = min(avail_in, build_filebuflen);
char *p = (char*)ubuild_datablock.get(in_pos, l);
#ifdef NSIS_CONFIG_CRC_SUPPORT
if (build_crcchk)
crc=CRC32(crc, (unsigned char *)p, l);
#endif
compressor->SetNextIn(p, l);
while (compressor->GetAvailIn())
{
compressor->SetNextOut(obuf, sizeof(obuf));
compressor->Compress(0);
if (compressor->GetNextOut() - obuf > 0)
udata.add(obuf, compressor->GetNextOut() - obuf);
}
ubuild_datablock.release();
avail_in -= l;
in_pos += l;
}
for (;;)
{
compressor->SetNextOut(obuf,sizeof(obuf));
compressor->SetNextOut(obuf, sizeof(obuf));
compressor->Compress(C_FINISH);
if (compressor->GetNextOut()-obuf > 0)
udata.add(obuf,compressor->GetNextOut()-obuf);
if (compressor->GetNextOut() - obuf > 0)
udata.add(obuf, compressor->GetNextOut() - obuf);
else break;
}
compressor->End();
@ -2647,26 +2847,51 @@ int CEXEBuild::uninstall_generate()
else
#endif//NSIS_CONFIG_COMPRESSION_SUPPORT
{
udata.add(&fh,sizeof(fh));
udata.add(uhd.get(),uhd.getlen());
udata.add(ubuild_datablock.get(),ubuild_datablock.getlen());
#ifdef NSIS_CONFIG_CRC_SUPPORT
if (build_crcchk)
crc = CRC32(crc, (unsigned char *)uhd.get(), uhd.getlen());
#endif
udata.add(uhd.get(), uhd.getlen());
int st = udata.getlen();
int length = ubuild_datablock.getlen();
int left = length;
udata.resize(st + left);
while (left > 0)
{
int l = min(build_filebuflen, left);
void *p = ubuild_datablock.get(length - left, l);
#ifdef NSIS_CONFIG_CRC_SUPPORT
if (build_crcchk)
crc = CRC32(crc, (unsigned char *)p, l);
#endif
memcpy(udata.get(st + length - left, l), p, l);
udata.flush(l);
udata.release();
ubuild_datablock.release();
left -= l;
}
}
ubuild_datablock.clear();
#ifdef NSIS_CONFIG_CRC_SUPPORT
if (build_crcchk)
{
int s=CRC32(crc,(unsigned char *)udata.get(),udata.getlen());
udata.add(&s,sizeof(int));
}
udata.add(&crc, sizeof(crc));
#endif
if (add_data((char*)udata.get(),udata.getlen()) < 0)
if (add_db_data(&udata) < 0)
return PS_ERROR;
udata.clear();
//uninstall_size_full=fh.length_of_all_following_data + sizeof(int) + unicondata_size - 32 + sizeof(int);
uninstall_size_full=fh.length_of_all_following_data+unicondata_size;
// compressed size
uninstall_size=build_datablock.getlen()-build_header.uninstdata_offset;
SCRIPT_MSG("Done!\n");
}
#endif
return PS_OK;

View file

@ -170,7 +170,9 @@ class CEXEBuild {
int add_label(const char *name);
int add_entry(const entry *ent);
int add_entry_direct(int which, int o0=0, int o1=0, int o2=0, int o3=0, int o4=0, int o5=0);
int add_data(const char *data, int length, IGrowBuf *dblock=NULL); // returns offset
int add_db_data(IMMap *map); // returns offset
int add_db_data(const char *data, int length); // returns offset
int add_data(const char *data, int length, IGrowBuf *dblock); // returns offset
int add_string(const char *string, int process=1); // returns offset (in string table)
int add_intstring(const int i); // returns offset in stringblock
@ -249,7 +251,7 @@ class CEXEBuild {
// User variables stuff
int GetUserVarIndex(LineParser &line, int token);
// Added by ramon 3 jun 2003
// Added by ramon 3 jun 2003
#ifdef NSIS_SUPPORT_NAMED_USERVARS
UserVarsStringList m_UserVarNames;
int DeclaredUserVar(const char *VarName);
@ -316,16 +318,18 @@ class CEXEBuild {
TinyGrowBuf build_pages, ubuild_pages, *cur_pages;
TinyGrowBuf build_ctlcolors, ubuild_ctlcolors, *cur_ctlcolors;
MMapBuf build_datablock, ubuild_datablock; // use GrowBuf here instead of MMapBuf if you want
MMapBuf build_datablock, ubuild_datablock;
IGrowBuf *cur_datablock;
int build_filebuflen;
TinyGrowBuf verbose_stack;
unsigned char *header_data_new;
int exeheader_size_new;
int icon_offset;
bool branding_image_found; // Added by Amir Szekely 29nd July 2002
WORD branding_image_id; // Added by Amir Szekely 29nd July 2002
bool branding_image_found;
WORD branding_image_id;
unsigned char *m_unicon_data;
#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
int deflateToFile(FILE *fp, char *buf, int len); // len==0 to flush

View file

@ -335,8 +335,12 @@ static int CALLBACK WINAPI BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lPara
{
if (uMsg==BFFM_INITIALIZED)
{
my_GetDialogItemText((HWND)lpData,IDC_DIR,g_tmp,sizeof(g_tmp));
SendMessage(hwnd,BFFM_SETSELECTION,(WPARAM)1,(LPARAM)g_tmp);
my_GetDialogItemText(m_curwnd,IDC_DIR,(char*)lpData,sizeof(g_tmp));
SendMessage(hwnd,BFFM_SETSELECTION,(WPARAM)1,lpData);
}
if (uMsg==BFFM_SELCHANGED)
{
SendMessage(hwnd,BFFM_ENABLEOK,0,SHGetPathFromIDList((LPITEMIDLIST)lParam,(char*)lpData));
}
return 0;
}
@ -738,15 +742,13 @@ static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
if (id == IDC_BROWSE)
{
char name[MAX_PATH];
BROWSEINFO bi={0,};
BROWSEINFO bi = {0,};
ITEMIDLIST *idlist;
GetUIText(IDC_DIR,name,MAX_PATH);
//GetUIText(IDC_SELDIRTEXT,str,256);
bi.hwndOwner = hwndDlg;
bi.pszDisplayName = name;
bi.lpfn=BrowseCallbackProc;
bi.lParam=(LPARAM)hwndDlg;
bi.lpszTitle=GetNSISStringTT(browse_text);
bi.lpfn = BrowseCallbackProc;
bi.lParam = (LPARAM)g_tmp;
bi.lpszTitle = GetNSISStringTT(browse_text);
#ifndef BIF_NEWDIALOGSTYLE
#define BIF_NEWDIALOGSTYLE 0x0040
#endif
@ -755,7 +757,6 @@ static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
if (idlist)
{
IMalloc *m;
SHGetPathFromIDList(idlist, name);
SHGetMalloc(&m);
if (m)
{
@ -765,16 +766,16 @@ static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
if (g_header->install_directory_auto_append)
{
const char *p, *post_str=ps_tmpbuf;
const char *post_str=ps_tmpbuf;
GetNSISStringTT(g_header->install_directory_auto_append);
p=name+mystrlen(name)-mystrlen(post_str);
if (p <= name || *CharPrev(name,p)!='\\' || lstrcmpi(p,post_str))
// name gives just the folder name
if (lstrcmpi(post_str,name))
{
lstrcat(addtrailingslash(name),post_str);
lstrcat(addtrailingslash(g_tmp),post_str);
}
}
SetUITextNT(IDC_DIR,name);
SetUITextNT(IDC_DIR,g_tmp);
}
}
}

View file

@ -2749,6 +2749,16 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
if (build_optimize_datablock==-1) PRINTHELP()
SCRIPT_MSG("SetDatablockOptimize: %s\n",line.gettoken_str(1));
return PS_OK;
case TOK_FILEBUFSIZE:
build_filebuflen=line.gettoken_int(1);
build_filebuflen<<=20;
if (build_filebuflen<=0)
{
ERROR_MSG("Error: FileBufSize: invalid buffer size -- %d\n",build_filebuflen);
return PS_ERROR;
}
SCRIPT_MSG("FileBufSize: %smb (%d bytes)\n",line.gettoken_str(1),build_filebuflen);
return PS_OK;
case TOK_ADDSIZE:
{
int s;
@ -4298,7 +4308,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
if (*p) PRINTHELP()
SCRIPT_MSG("WriteRegBin: %s\\%s\\%s=%s\n",
line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
ent.offsets[3]=add_data(data,data_len);
ent.offsets[3]=add_db_data(data,data_len);
if (ent.offsets[3] < 0) return PS_ERROR;
ent.offsets[4]=3;
}
@ -5036,7 +5046,8 @@ int CEXEBuild::do_add_file(const char *lgss, int attrib, int recurse, int linecn
{
if ((d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
{
HANDLE hFile,hFileMap;
MMapFile mmap;
HANDLE hFile;
DWORD len;
(*total_files)++;
sprintf(newfn,"%s%s%s",dir,dir[0]?"\\":"",d.cFileName);
@ -5054,26 +5065,13 @@ int CEXEBuild::do_add_file(const char *lgss, int attrib, int recurse, int linecn
ERROR_MSG("%sFile: failed opening file \"%s\"\n",generatecode?"":"Reserve",newfn);
return PS_ERROR;
}
hFileMap=NULL;
len = GetFileSize(hFile, NULL);
if (len && !(hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)))
if (len && !mmap.setfile(hFile, len))
{
CloseHandle(hFile);
ERROR_MSG("%sFile: failed creating mmap of \"%s\"\n",generatecode?"":"Reserve",newfn);
return PS_ERROR;
}
char *filedata=NULL;
if (len)
{
filedata=(char*)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
if (!filedata)
{
if (hFileMap) CloseHandle(hFileMap);
CloseHandle(hFile);
ERROR_MSG("%sFile: failed mmapping file \"%s\"\n",generatecode?"":"Reserve",newfn);
return PS_ERROR;
}
}
if (generatecode&1)
section_add_size_kb((len+1023)/1024);
@ -5113,10 +5111,9 @@ int CEXEBuild::do_add_file(const char *lgss, int attrib, int recurse, int linecn
ent.offsets[1]=add_string(buf);
}
}
ent.offsets[2]=add_data(filedata?filedata:"",len);
ent.offsets[2]=add_db_data(&mmap);
if (filedata) UnmapViewOfFile(filedata);
if (hFileMap) CloseHandle(hFileMap);
mmap.clear();
if (ent.offsets[2] < 0)
{

View file

@ -12,6 +12,20 @@ class IGrowBuf
virtual void *get()=0;
};
class IMMap
{
public:
virtual void resize(int newlen)=0;
virtual int getsize()=0;
virtual void *get(int offset, int size)=0;
virtual void *getmore(int offset, int size)=0;
virtual void release()=0;
virtual void release(void *view)=0;
virtual void clear()=0;
virtual void setro(BOOL bRO)=0;
virtual void flush(int num)=0;
};
class GrowBuf : public IGrowBuf
{
public:
@ -461,87 +475,387 @@ class FastStringList : public SortedStringListND<struct string_t>
}
};
class MMapBuf : public IGrowBuf
class MMapFile : public IMMap
{
public:
MMapBuf()
{
m_hFile = INVALID_HANDLE_VALUE;
m_hFileMap = 0;
m_mapping=NULL;
m_gb_u=0;
m_alloc=m_used=0;
}
~MMapBuf()
{
if (m_mapping) UnmapViewOfFile(m_mapping);
if (m_hFileMap) CloseHandle(m_hFileMap);
if (m_hFile != INVALID_HANDLE_VALUE) CloseHandle(m_hFile);
}
int add(const void *data, int len)
{
if (len<=0) return 0;
resize(getlen()+len);
memcpy((char*)get()+getlen()-len,data,len);
return getlen()-len;
}
void resize(int newlen)
MMapFile()
{
if (!m_gb_u && newlen < (16<<20)) // still in db mode
m_hFile = INVALID_HANDLE_VALUE;
m_hFileMap = NULL;
m_pView = NULL;
m_iSize = 0;
m_bReadOnly = FALSE;
m_bTempHandle = FALSE;
if (!m_iAllocationGranularity)
{
m_gb.resize(newlen);
return;
SYSTEM_INFO si;
GetSystemInfo(&si);
m_iAllocationGranularity = (int) si.dwAllocationGranularity;
}
m_gb_u=1;
m_used=newlen;
if (newlen > m_alloc)
}
~MMapFile()
{
clear();
}
void clear()
{
release();
if (m_hFileMap)
CloseHandle(m_hFileMap);
if (m_bTempHandle && m_hFile)
CloseHandle(m_hFile);
m_hFileMap = 0;
}
void setro(BOOL bRO)
{
m_bReadOnly = bRO;
}
int setfile(HANDLE hFile, DWORD dwSize)
{
release();
if (m_hFileMap)
CloseHandle(m_hFileMap);
if (m_bTempHandle && m_hFile)
CloseHandle(m_hFile);
m_hFileMap = 0;
m_hFile = hFile;
m_bTempHandle = FALSE;
if (m_hFile == INVALID_HANDLE_VALUE)
return 0;
m_iSize = (int) dwSize;
if (m_iSize <= 0)
return 0;
m_hFileMap = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, m_iSize, NULL);
if (!m_hFileMap)
return 0;
m_bReadOnly = TRUE;
return 1;
}
void resize(int newsize)
{
release();
if (newsize > m_iSize)
{
if (m_mapping) UnmapViewOfFile(m_mapping);
if (m_hFileMap) CloseHandle(m_hFileMap);
m_hFileMap=0;
m_mapping=NULL;
m_alloc = newlen + (16<<20); // add 16mb to top of mapping
if (m_hFileMap)
CloseHandle(m_hFileMap);
m_hFileMap = 0;
m_iSize = newsize;
if (m_hFile == INVALID_HANDLE_VALUE)
{
char buf[MAX_PATH],buf2[MAX_PATH];
GetTempPath(MAX_PATH,buf);
GetTempFileName(buf,"nsd",0,buf2);
m_hFile=CreateFile(buf2,GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
char buf[MAX_PATH], buf2[MAX_PATH];
GetTempPath(MAX_PATH, buf);
GetTempFileName(buf, "nsd", 0, buf2);
m_hFile = CreateFile(
buf2,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
m_bTempHandle = TRUE;
}
if (m_hFile != INVALID_HANDLE_VALUE)
m_hFileMap=CreateFileMapping(m_hFile,NULL,PAGE_READWRITE,0,m_alloc,NULL);
if (m_hFileMap)
m_mapping=MapViewOfFile(m_hFileMap,FILE_MAP_WRITE,0,0,m_alloc);
if (!m_mapping)
{
m_hFileMap = CreateFileMapping(
m_hFile,
NULL,
m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE,
0,
m_iSize,
NULL
);
}
if (!m_hFileMap)
{
MessageBox(0, "failed", "asd", MB_OK);
extern FILE *g_output;
extern void quit(); extern int g_display_errors;
if (g_display_errors)
if (g_display_errors)
{
fprintf(g_output,"\nInternal compiler error #12345: error mmapping datablock to %d.\n",m_alloc);
fprintf(g_output,"\nInternal compiler error #12345: error creating mmap the size of %d.\n", m_iSize);
fflush(g_output);
}
quit();
}
}
}
int getsize()
{
return m_iSize;
}
void *get(int offset, int size)
{
if (m_pView)
release();
if (!m_iSize || offset + size > m_iSize)
{
extern FILE *g_output;
extern void quit(); extern int g_display_errors;
if (g_display_errors)
{
fprintf(g_output,"\nInternal compiler error #12345: error mmapping file (%d, %d) is out of range.\n", offset, size);
fflush(g_output);
}
quit();
}
// fix offset
int alignedoffset = offset - (offset % m_iAllocationGranularity);
size += offset - alignedoffset;
m_pView = MapViewOfFile(m_hFileMap, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, 0, alignedoffset, size);
if (!m_pView)
{
extern FILE *g_output;
extern void quit(); extern int g_display_errors;
if (g_display_errors)
{
fprintf(g_output,"\nInternal compiler error #12345: error mmapping datablock to %d.\n", size);
fflush(g_output);
}
quit();
}
return (void *)((char *)m_pView + offset - alignedoffset);
}
void *getmore(int offset, int size)
{
void *pView;
void *pViewBackup = m_pView;
m_pView = 0;
pView = get(offset, size);
m_pView = pViewBackup;
return pView;
}
void release()
{
if (!m_pView)
return;
UnmapViewOfFile(m_pView);
m_pView = NULL;
}
void release(void *pView)
{
if (!pView)
return;
UnmapViewOfFile(pView);
}
void flush(int num)
{
if (m_pView)
FlushViewOfFile(m_pView, num);
}
private:
HANDLE m_hFile, m_hFileMap;
void *m_pView;
int m_iSize;
BOOL m_bReadOnly;
BOOL m_bTempHandle;
static int m_iAllocationGranularity;
};
class MMapFake : public IMMap
{
public:
MMapFake()
{
m_pMem = NULL;
m_iSize = 0;
}
void set(const char *pMem, int iSize)
{
m_pMem = pMem;
m_iSize = iSize;
}
int getsize()
{
return m_iSize;
}
void *get(int offset, int size)
{
if (offset + size > m_iSize)
return NULL;
return (void *)(m_pMem + offset);
}
void *getmore(int offset, int size)
{
return get(offset, size);
}
void resize(int n) {}
void release() {}
void release(void *p) {}
void clear() {}
void setro(BOOL b) {}
void flush(BOOL b) {}
private:
const char *m_pMem;
int m_iSize;
};
class MMapBuf : public IGrowBuf, public IMMap
{
public:
MMapBuf()
{
m_gb_u=0;
m_alloc=m_used=0;
}
~MMapBuf()
{
m_fm.release();
}
int add(const void *data, int len)
{
if (len <= 0) return 0;
resize(getlen() + len);
memcpy((char*)get(getlen() - len, len), data, len);
return getlen() - len;
}
void setro(BOOL bRO)
{
m_fm.setro(bRO);
}
void resize(int newlen)
{
if (!m_gb_u && newlen < (16 << 20)) // still in db mode
{
m_gb.resize(newlen);
return;
}
// not in db mode
m_gb_u = 1;
m_used = newlen;
if (newlen > m_alloc)
{
m_alloc = newlen + (16 << 20); // add 16mb to top of mapping
m_fm.resize(m_alloc);
if (m_gb.getlen())
{
memcpy(m_mapping,m_gb.get(),m_gb.getlen());
memcpy(m_fm.get(0, m_gb.getlen()), m_gb.get(), m_gb.getlen());
m_fm.flush(m_gb.getlen());
m_fm.release();
m_gb.resize(0);
}
}
}
int getlen() { if (m_gb_u) return m_used; return m_gb.getlen(); }
void *get() { if (m_gb_u) return m_mapping; return m_gb.get(); }
int getsize()
{
if (m_gb_u)
return m_fm.getsize();
return m_gb.getlen();
}
int getlen()
{
if (m_gb_u)
return m_used;
return m_gb.getlen();
}
void *get()
{
return get(0, m_alloc);
}
void *get(int offset, int size)
{
if (m_gb_u)
return m_fm.get(offset, size);
return (void *) ((char *) m_gb.get() + offset);
}
void *getmore(int offset, int size)
{
if (m_gb_u)
return m_fm.getmore(offset, size);
return (void *) ((char *) m_gb.get() + offset);
}
void release()
{
if (m_gb_u)
m_fm.release();
}
void release(void *pView)
{
if (m_gb_u)
m_fm.release(pView);
}
void clear()
{
if (m_gb_u)
m_fm.clear();
}
void flush(int num)
{
if (m_gb_u)
m_fm.flush(num);
}
private:
GrowBuf m_gb;
int m_gb_u;
MMapFile m_fm;
HANDLE m_hFile, m_hFileMap;
void *m_mapping;
int m_gb_u;
int m_alloc, m_used;
};

View file

@ -46,7 +46,7 @@ static tokenType tokenlist[TOK__LAST] =
{TOK_DELETEREGVALUE,"DeleteRegValue",3,0,"root_key subkey entry_name\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"},
{TOK_DELETE,"Delete",1,1,"[/REBOOTOK] filespec"},
{TOK_DETAILPRINT,"DetailPrint",1,0,"message"},
{TOK_DIRTEXT,"DirText",0,3,"[directory_page_description] [directory_page_subtext] [browse_button_text] [browse_dlg_text]"},
{TOK_DIRTEXT,"DirText",0,4,"[directory_page_description] [directory_page_subtext] [browse_button_text] [browse_dlg_text]"},
{TOK_DIRSHOW,"DirShow",1,0,"(show|hide)"},
{TOK_DIRVAR,"DirVar",1,0,"$(user_var: dir in/out))"},
{TOK_ROOTDIRINST,"AllowRootDirInstall",1,0,"(true|false)"},
@ -64,6 +64,7 @@ static tokenType tokenlist[TOK__LAST] =
{TOK_FINDFIRST,"FindFirst",3,0,"$(user_var: handle output) $(user_var: filename output) filespec"},
{TOK_FINDNEXT,"FindNext",2,0,"$(user_var: handle input) $(user_var: filename output)"},
{TOK_FILE,"File",1,-1,"[/nonfatal] [/a] ([/r] filespec [...]|/oname=outfile one_file_only)"},
{TOK_FILEBUFSIZE,"FileBufSize",1,0,"buf_size"},
{TOK_FLUSHINI,"FlushINI",1,0,"ini_file"},
{TOK_RESERVEFILE,"ReserveFile",1,-1,"[/nonfatal] [/r] file [file...]"},
{TOK_FILECLOSE,"FileClose",1,0,"$(user_var: handle input)"},

View file

@ -44,7 +44,6 @@ enum
TOK_CHANGEUI,
TOK_ADDBRANDINGIMAGE,
TOK_SETFONT,
TOK_SETCOMPRESSOR,
TOK_LOADNLF,
TOK_RESERVEFILE,
TOK_ALLOWSKIPFILES,
@ -61,6 +60,12 @@ enum
TOK_LANGSTRING,
TOK_LANGSTRINGUP,
// comrpession stuff
TOK_SETCOMPRESS,
TOK_DBOPTIMIZE,
TOK_SETCOMPRESSOR,
TOK_FILEBUFSIZE,
// system "preprocessor"ish tokens
TOK_P_IFDEF,
@ -97,19 +102,17 @@ enum
// page oredering shit
TOK_PAGE,
TOK_UNINSTPAGE,
TOK_PAGEEX,
TOK_PAGECALLBACKS,
TOK_PAGEEXEND,
// PageEx stuff
TOK_PAGEEX,
TOK_PAGEEXEND,
TOK_DIRVAR,
TOK_PAGECALLBACKS,
// flag setters
TOK_SETDATESAVE,
TOK_SETOVERWRITE,
TOK_SETPLUGINUNLOAD,
TOK_SETCOMPRESS,
TOK_DBOPTIMIZE,
// instructions
TOK_NOP,

View file

@ -6,10 +6,6 @@ NSIS
* empty subsections should not show
* start optimizing datablock after file mapping was released
* map files part by part to save memory
* skip plugin calls, file instructions that add more than one file with +1 with goto
* more powerful plug-ins (access to ExecFunc and flags and even more)