- 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

@ -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,