FileReadUTF16LE skips optional BOM and FileWriteUTF16LE can write a BOM with the /BOM switch

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6626 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2015-10-26 23:29:39 +00:00
parent 37c81f74f8
commit b54c831ff0
7 changed files with 59 additions and 13 deletions

View file

@ -1370,11 +1370,12 @@ static int NSISCALL ExecuteEntry(entry *entry_)
DWORD dw;
int l; // number of bytes to write
TCHAR *t=var0;
if (parm2) // FileWriteByte or FileWriteWord
const int writeCodPt = parm2, ansi = EW_FPUTS == which;
if (writeCodPt) // FileWriteByte or FileWriteWord
{
// Note: In Unicode version, we put a WORD in buf1[0] and will write 1 or 2 bytes, depending on FileWriteByte/Word.
((_TUCHAR *)buf1)[0]=(_TUCHAR) GetIntFromParm(1); // FIX_ENDIAN_INT16 needed?
l=(which==EW_FPUTS)?1:sizeof(TCHAR); // Note: This is optimized by the compiler into l=1 for ANSI compilation
l=(ansi)?1:sizeof(TCHAR);
}
#ifdef _UNICODE
else if (which==EW_FPUTS)
@ -1388,10 +1389,16 @@ static int NSISCALL ExecuteEntry(entry *entry_)
{
l=mystrlen(GetStringFromParm(0x11))*sizeof(TCHAR);
}
if (!*t || !WriteFile((HANDLE)strtoiptr(t),buf1,l,&dw,NULL))
if (*t)
{
exec_error++;
const HANDLE hFile = (HANDLE) strtoiptr(t);
#ifdef _UNICODE
if ((ansi | writeCodPt) || !parm3 || SUCCEEDED(UTF16LEBOM(hFile,(INT_PTR)hFile)))
#endif
if (WriteFile(hFile,buf1,l,&dw,NULL))
break; // Success
}
exec_error++;
}
break;
case EW_FGETS:
@ -1433,6 +1440,9 @@ static int NSISCALL ExecuteEntry(entry *entry_)
else
#endif
{
#ifdef _UNICODE
if (!parm3 && 0 == rpos && FAILED(UTF16LEBOM(h,FALSE))) break;
#endif
// Read 1 TCHAR (FileReadUTF16LE, (Ansi)FileRead, FileReadWord)
if (!myReadFile(h,&c,sizeof(TCHAR))) break;
}

View file

@ -456,6 +456,31 @@ BOOL NSISCALL myReadFile(HANDLE h, LPVOID buf, DWORD cb)
return r && cb == cbio;
}
// Reading skips the BOM if present, writing writes it to a empty file
HRESULT NSISCALL UTF16LEBOM(HANDLE h, INT_PTR ForWrite)
{
DWORD orgpos = SetFilePointer(h, 0, NULL, FILE_CURRENT), cbio;
if (0 == orgpos)
{
BYTE bom[2];
if (myReadFile(h, bom, 2) && (0xff == bom[0] && 0xfe == bom[1]))
{
return S_OK;
}
else if (ForWrite)
{
if (0 == SetFilePointer(h, 0, NULL, FILE_CURRENT)) // Is the file empty?
{
static const BYTE bom16le[] = { 0xff, 0xfe };
return (WriteFile(h, bom16le, 2, &cbio, NULL) && 2 == cbio)
? S_OK : E_FAIL;
}
}
SetFilePointer(h, 0, NULL, FILE_BEGIN); // The file may have starting with something that was not a BOM, undo the read
}
return S_FALSE;
}
#ifdef NSIS_SUPPORT_MOVEONREBOOT
#ifndef _WIN64
/** Modifies the wininit.ini file to rename / delete a file.

View file

@ -44,6 +44,7 @@ TCHAR * NSISCALL mystrstr(TCHAR *a, TCHAR *b);
WIN32_FIND_DATA * NSISCALL file_exists(TCHAR *buf);
TCHAR * NSISCALL my_GetTempFileName(TCHAR *buf, const TCHAR *dir);
BOOL NSISCALL myReadFile(HANDLE h, LPVOID buf, DWORD cb);
HRESULT NSISCALL UTF16LEBOM(HANDLE h, INT_PTR ForWrite);
//BOOL NSISCALL my_SetWindowText(HWND hWnd, const TCHAR *val);
#define my_SetWindowText SetWindowText

View file

@ -5690,11 +5690,17 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
ERROR_MSG(_T("Error: %") NPRIs _T(" is only available when building a Unicode installer\n"), line.gettoken_str(0));
return PS_ERROR;
}
ent.which=EW_FPUTWS;
ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
ent.offsets[1]=add_string(line.gettoken_str(2));
if (ent.offsets[0]<0) PRINTHELP()
SCRIPT_MSG(_T("FileWriteUTF16LE: %") NPRIs _T("->%") NPRIs _T("\n"),line.gettoken_str(2),line.gettoken_str(1));
{
UINT bom=0, swofs=0;
if (!_tcsicmp(_T("/BOM"),line.gettoken_str(swofs+1))) ++bom, ++swofs;
if (!_tcsicmp(_T("/NoBOM"),line.gettoken_str(swofs+1))) bom = 0, ++swofs; // Undocumented switch
ent.which=EW_FPUTWS;
ent.offsets[0]=GetUserVarIndex(line, swofs+1); // file handle
ent.offsets[1]=add_string(line.gettoken_str(swofs+2));
ent.offsets[3]=bom;
if (ent.offsets[0]<0 || line.getnumtokens()-swofs != 3) PRINTHELP()
SCRIPT_MSG(_T("FileWriteUTF16LE: %") NPRIs _T("->%") NPRIs _T("\n"),line.gettoken_str(swofs+2),line.gettoken_str(swofs+1));
}
return add_entry(&ent);
case TOK_FILEREADWORD:
if (!build_unicode)

View file

@ -99,7 +99,7 @@ static tokenType tokenlist[TOK__LAST] =
{TOK_FILEWRITEBYTE,_T("FileWriteByte"),2,0,_T("$(user_var: handle input) bytevalue"),TP_CODE},
#ifdef _UNICODE
{TOK_FILEREADUTF16LE,_T("FileReadUTF16LE"),2,1,_T("$(user_var: handle input) $(user_var: text output) [maxlen]"),TP_CODE},
{TOK_FILEWRITEUTF16LE,_T("FileWriteUTF16LE"),2,0,_T("$(user_var: handle input) text"),TP_CODE},
{TOK_FILEWRITEUTF16LE,_T("FileWriteUTF16LE"),2,1,_T("[/BOM] $(user_var: handle input) text"),TP_CODE},
{TOK_FILEREADWORD,_T("FileReadWord"),2,0,_T("$(user_var: handle input) $(user_var: wordvalue output)"),TP_CODE},
{TOK_FILEWRITEWORD,_T("FileWriteWord"),2,0,_T("$(user_var: handle input) wordvalue"),TP_CODE},
#endif