windows-nt/Source/XPSP1/NT/inetsrv/intlwb/thai2/sth/mapio.c

415 lines
10 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*+---------------------------------------------------------------------------
//
// mapio.c - mapped file i/o routines
//
// History:
// 9/4/97 DougP Create this header
allow and deal with input map files of zero length
11/20/97 DougP Move these routines from misc.c to here
Add option to spec codepage
//
// <20>1997 Microsoft Corporation
//----------------------------------------------------------------------------*/
#include <windows.h>
#include <assert.h>
#include "NLGlib.h"
//#ifdef WINCE
void Assert(x)
{
if (x)
MessageBox(0,"assert","assert",MB_OK);
}
//#endif
BOOL WINAPI CloseMapFile(PMFILE pmf)
{
if (pmf==NULL) {
return FALSE;
}
// only unmap what existed - DougP
if (pmf->pvMap && !UnmapViewOfFile(pmf->pvMap)) {
return FALSE;
}
// ditto
if (pmf->hFileMap && !CloseHandle(pmf->hFileMap)) {
return FALSE;
}
if (!CloseHandle(pmf->hFile)) {
return FALSE;
}
NLGFreeMemory(pmf);
return TRUE;
}
PMFILE WINAPI OpenMapFileWorker(const WCHAR * pwszFileName,BOOL fDstUnicode)
{
PMFILE pmf;
const WCHAR * pwszExt;
if (!fNLGNewMemory(&pmf, sizeof(MFILE)))
{
goto Error;
}
pmf->fDstUnicode = fDstUnicode;
#ifdef WINCE
pmf->hFile = CreateFileForMapping(
#else
pmf->hFile = CMN_CreateFileW(
#endif
pwszFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (pmf->hFile == INVALID_HANDLE_VALUE)
{
goto Error;
}
pmf->cbSize1 = GetFileSize(pmf->hFile, &pmf->cbSize2);
if (pmf->cbSize1 == 0xFFFFFFFF)
{
CMN_OutputSystemErrW(L"Can't get size for", pwszFileName);
CloseHandle(pmf->hFile);
goto Error;
}
else if (pmf->cbSize1 == 0)
{
// can't map a zero length file so mark this appropriately
pmf->hFileMap = 0;
pmf->pvMap = 0;
pmf->fSrcUnicode = TRUE;
}
else
{
#ifdef WINCE
pmf->hFileMap = CreateFileMapping(pmf->hFile, NULL, PAGE_READONLY, 0, 0, NULL);
#else
pmf->hFileMap = CreateFileMappingA(pmf->hFile, NULL, PAGE_READONLY, 0, 0, NULL);
#endif
if (pmf->hFileMap == NULL)
{
CMN_OutputSystemErrW(L"Can't Map", pwszFileName);
CloseHandle(pmf->hFile);
goto Error;
}
// Map the entire file starting at the first byte
//
pmf->pvMap = MapViewOfFile(pmf->hFileMap, FILE_MAP_READ, 0, 0, 0);
if (pmf->pvMap == NULL)
{
CloseHandle(pmf->hFileMap);
CloseHandle(pmf->hFile);
goto Error;
}
// HACK: Since IsTextUnicode returns false for sorted stem files, preset
// unicode status here based on utf file extension
pwszExt = pwszFileName;
while (*pwszExt && *pwszExt != L'.' ) pwszExt++;
if (*pwszExt && !wcscmp(pwszExt, L".utf"))
{
pmf->fSrcUnicode = TRUE;
}
else if (pmf->cbSize1 >= 2 && *(WORD *)pmf->pvMap == 0xFEFF)
{
// Safe to assume that anything starting with a BOM is Unicode
pmf->fSrcUnicode = TRUE;
}
else
{
#ifdef WINCE
pmf->fSrcUnicode = TRUE;
#else
pmf->fSrcUnicode = IsTextUnicode(pmf->pvMap, pmf->cbSize1, NULL);
#endif
}
if (pmf->fSrcUnicode)
{
pmf->pwsz = (WCHAR *)pmf->pvMap;
}
else
{
pmf->psz = (PSTR)pmf->pvMap;
}
}
pmf->uCodePage = CP_ACP; // DWP - use default unless client specifies otherwise
return pmf;
Error:
if (pmf)
{
NLGFreeMemory(pmf);
}
return NULL;
}
#ifndef WINCE
PMFILE WINAPI OpenMapFileA(const char * pszFileName)
{
WCHAR * pwszFileName;
DWORD cchFileNameLen;
int iRet;
cchFileNameLen = lstrlenA(pszFileName) + 1;
if (!fNLGNewMemory(&pwszFileName, cchFileNameLen * sizeof(WCHAR)))
{
return NULL;
}
iRet = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszFileName, -1,
pwszFileName, cchFileNameLen);
if (iRet ==0)
{
NLGFreeMemory(pwszFileName);
return NULL;
}
return (OpenMapFileWorker(pwszFileName, FALSE));
}
#endif
BOOL WINAPI ResetMap(PMFILE pmf)
{
if (pmf == NULL) {
return FALSE;
}
if (pmf->fSrcUnicode) {
pmf->pwsz = (WCHAR*)pmf->pvMap;
if (*pmf->pwsz == 0xFEFF) {
pmf->pwsz++;
}
} else {
pmf->psz = (CHAR*)pmf->pvMap;
}
return TRUE;
}
// Same side effect as GetMapLine (incrememnt map pointer) but without returning contents
// in buffer. This is useful in situations where the line may be longer than the max cch and
// when the buffer isn't actually needed (counting lines, etc.)
//
BOOL WINAPI NextMapLine(PMFILE pmf)
{
DWORD cbOffset;
if (!pmf || !pmf->hFileMap) // check for zero length file
return FALSE;
if (pmf->fSrcUnicode)
{
WCHAR wch;
cbOffset = (DWORD) ((PBYTE)pmf->pwsz - (PBYTE)pmf->pvMap);
// test for EOF
Assert (cbOffset <= pmf->cbSize1);
if (cbOffset == pmf->cbSize1)
return FALSE;
while (cbOffset < pmf->cbSize1)
{
cbOffset += sizeof(WCHAR);
wch = *pmf->pwsz++;
// Break out if this is the newline or the control-Z
if (wch == 0x001A || wch == L'\n')
break;
}
}
else
{
CHAR ch;
cbOffset = (DWORD) ((PBYTE)pmf->psz - (PBYTE)pmf->pvMap);
// test for EOF
Assert (cbOffset <= pmf->cbSize1);
if (cbOffset == pmf->cbSize1)
return FALSE;
while (cbOffset < pmf->cbSize1)
{
cbOffset += sizeof(CHAR);
ch = *pmf->psz++;
// Break out if this is the newline or the control-Z
if (ch == 0x1A || ch == '\n')
break;
}
}
return TRUE;
}
PVOID WINAPI GetMapLine(PVOID pv0, DWORD cbMac, PMFILE pmf)
{
PVOID pv1;
DWORD cbOffset, cbBuff;
Assert(pv0);
// Make sure that the buffer is at least as big as the caller says it is.
// (If the buffer was allocated with the debug memory allocator, this access
// should cause an exception if pv0 isn't at least cbMac bytes long.
Assert(((char *)pv0)[cbMac-1] == ((char *)pv0)[cbMac-1]);
if (!pmf || !pmf->hFileMap) // check for zero length file
return NULL;
if (pmf->fSrcUnicode != pmf->fDstUnicode)
{
if (!fNLGNewMemory(&pv1, cbMac))
return NULL;
cbBuff = cbMac;
}
else
{
pv1 = pv0;
}
if (pmf->fSrcUnicode)
{
WCHAR wch, *pwsz = pv1;
cbOffset = (DWORD) ((PBYTE)pmf->pwsz - (PBYTE)pmf->pvMap);
// test for EOF
Assert (cbOffset <= pmf->cbSize1);
if (cbOffset == pmf->cbSize1)
goto Error;
// don't want deal with odd-sized buffers
if (cbMac % sizeof(WCHAR) != 0)
cbMac -= (cbMac % sizeof(WCHAR));
// reserve space for terminating 0
//
Assert (cbMac > 0);
cbMac -= sizeof(WCHAR);
while (cbOffset < pmf->cbSize1)
{
cbOffset += sizeof(WCHAR);
wch = *pmf->pwsz++;
switch (wch)
{
case L'\r':
case L'\n': // end of line
case 0xFEFF: // Unicode BOM
break;
case 0x001A: // ctrl-Z
wch = L'\n'; // Replace it so that the last line can be read
break;
default:
*pwsz++ = wch;
cbMac -= sizeof(WCHAR);
}
// Break out if this is the newline or buffer is full
if (wch == L'\n' || cbMac <= 0)
break;
}
*pwsz = L'\0';
}
else
{
CHAR ch, *psz = pv1;
cbOffset = (DWORD) ((PBYTE)pmf->psz - (PBYTE)pmf->pvMap);
// test for EOF
Assert (cbOffset <= pmf->cbSize1);
if (cbOffset == pmf->cbSize1)
goto Error;
// reserve space for terminating 0
//
Assert (cbMac > 0);
cbMac -= sizeof(CHAR);
while (cbOffset < pmf->cbSize1)
{
cbOffset += sizeof(CHAR);
ch = *pmf->psz++;
switch (ch)
{
case '\r':
case '\n': // end of line
break;
case 0x1A: // ctrl-Z
ch = '\n'; // Replace it so that the last line can be read
break;
default:
cbMac -= sizeof(CHAR);
*psz++ = ch;
}
// Break out if this is the newline or buffer is full
if (ch == '\n' || cbMac <= 0)
break;
}
*psz = '\0';
}
if (pmf->fSrcUnicode != pmf->fDstUnicode)
{
DWORD cch = cbBuff; // our argument is a count of bytes
if (pmf->fDstUnicode)
{
// MultiByteToWideChar wants the size of the destination in wide characters
cch /= sizeof(WCHAR);
cch = MultiByteToWideChar(pmf->uCodePage, MB_PRECOMPOSED,(PSTR)pv1,-1, (WCHAR *)pv0,cch);
}
else
{
cch = WideCharToMultiByte(pmf->uCodePage, 0, (WCHAR *)pv1, -1, (PSTR)pv0, cch, NULL, NULL);
}
if (cch == 0)
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
// Ignore truncation (for consistency with no-conversion cases)
//
if (pmf->fDstUnicode)
{
((WCHAR *)pv0)[(cbBuff / sizeof(WCHAR)) - 1] = 0;
}
else
{
((CHAR *)pv0)[cbBuff - 1] = 0;
}
}
else
{
// not a truncation error
NLGFreeMemory(pv1);
return NULL;
}
}
NLGFreeMemory(pv1);
}
return(pv0);
Error:
if (pmf->fSrcUnicode != pmf->fDstUnicode)
{
NLGFreeMemory(pv1);
}
return NULL;
}