Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

809 lines
25 KiB

#include "precomp.h"
// Private forward decalarations
static LPCTSTR findMatchingBracket(LPCTSTR pszHtml);
static HRESULT findImgSrc(LPCTSTR *ppszHtml, LPTSTR pszSrcBuffer, LPUINT pcch);
static HRESULT buildImagesList(LPCTSTR pszHtml, LPTSTR *ppszList);
BOOL CopyFileToDirEx(LPCTSTR pszSourceFileOrPath, LPCTSTR pszTargetPath, LPCTSTR pszSection /*= NULL*/, LPCTSTR pszIns /*= NULL*/)
{
LPTSTR pszAuxFile;
BOOL fResult;
if (!PathFileExists(pszSourceFileOrPath))
return FALSE;
fResult = TRUE;
if (!PathIsDirectory(pszSourceFileOrPath)) { // file
TCHAR szTargetFile[MAX_PATH];
fResult = PathCreatePath(pszTargetPath);
if (!fResult)
return FALSE;
pszAuxFile = PathFindFileName(pszSourceFileOrPath);
PathCombine(szTargetFile, pszTargetPath, pszAuxFile);
SetFileAttributes(szTargetFile, FILE_ATTRIBUTE_NORMAL);
fResult = CopyFile(pszSourceFileOrPath, szTargetFile, FALSE);
if (!fResult)
return FALSE;
//----- Update the ins file -----
if (pszSection != NULL && pszIns != NULL) {
TCHAR szBuf[16];
UINT nNumFiles;
nNumFiles = (UINT)GetPrivateProfileInt(pszSection, IK_NUMFILES, 0, pszIns);
wnsprintf(szBuf, countof(szBuf), TEXT("%u"), ++nNumFiles);
WritePrivateProfileString(pszSection, IK_NUMFILES, szBuf, pszIns);
ASSERT(nNumFiles > 0);
wnsprintf(szBuf, countof(szBuf), FILE_TEXT, nNumFiles - 1);
WritePrivateProfileString(pszSection, szBuf, pszAuxFile, pszIns);
}
}
else { // directory
// BUGBUG: Won't copy files in sub-dirs under pszSourceFileOrPath
WIN32_FIND_DATA fd;
TCHAR szSourceFile[MAX_PATH];
HANDLE hFindFile;
StrCpy(szSourceFile, pszSourceFileOrPath);
PathAddBackslash(szSourceFile);
// remember the pos where the filename would get copied
pszAuxFile = szSourceFile + StrLen(szSourceFile);
StrCpy(pszAuxFile, TEXT("*.*"));
// copy all the files in pszSourceFileOrPath to pszTargetPath
hFindFile = FindFirstFile(szSourceFile, &fd);
if (hFindFile != INVALID_HANDLE_VALUE) {
fResult = TRUE;
do {
// skip ".", ".." and all sub-dirs
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
StrCpy(pszAuxFile, fd.cFileName);
// keep going even if copying of a file fails, but return FALSE in case of error
fResult = fResult && CopyFileToDirEx(szSourceFile, pszTargetPath, pszSection, pszIns);
} while (FindNextFile(hFindFile, &fd));
FindClose(hFindFile);
}
}
return fResult;
}
BOOL AppendFile(LPCTSTR pcszSrcFile, LPCTSTR pcszDstFile)
// Append the content of pcszSrcFile to pcszDstFile.
{
BOOL fRet = FALSE;
HANDLE hDstFile = INVALID_HANDLE_VALUE,
hSrcFile = INVALID_HANDLE_VALUE;
LPBYTE pbBuffer = NULL;
DWORD cbRead, cbWritten;
if (pcszDstFile == NULL || pcszSrcFile == NULL || ISNULL(pcszDstFile) || ISNULL(pcszSrcFile))
return FALSE;
if ((hDstFile = CreateFile(pcszDstFile, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
{
// DstFile doesn't exist; create one and call CopyFile()
if ((hDstFile = CreateNewFile(pcszDstFile)) != INVALID_HANDLE_VALUE)
{
CloseHandle(hDstFile);
hDstFile = INVALID_HANDLE_VALUE;
fRet = CopyFile(pcszSrcFile, pcszDstFile, FALSE);
}
goto CleanUp;
}
if (SetFilePointer(hDstFile, 0, NULL, FILE_END) == (DWORD) -1)
goto CleanUp;
if ((hSrcFile = CreateFile(pcszSrcFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
goto CleanUp;
// allocate a 4K buffer
if ((pbBuffer = (LPBYTE)CoTaskMemAlloc(4 * 1024)) == NULL)
goto CleanUp;
ZeroMemory(pbBuffer, 4 * 1024);
while ((fRet = ReadFile(hSrcFile, (LPVOID) pbBuffer, 4 * 1024, &cbRead, NULL)) == TRUE)
{
if (cbRead == 0)
break;
fRet = WriteFile(hDstFile, (LPCVOID) pbBuffer, cbRead, &cbWritten, NULL);
if (!fRet)
break;
ASSERT(cbRead == cbWritten);
}
if (!fRet)
goto CleanUp;
fRet = TRUE;
// good thing to do, esp. on Win95 if you combine AppendFile with Get/WritePrivateProfile functions.
FlushFileBuffers(hDstFile);
CleanUp:
if (pbBuffer != NULL)
CoTaskMemFree(pbBuffer);
if (hSrcFile != INVALID_HANDLE_VALUE)
CloseHandle(hSrcFile);
if (hDstFile != INVALID_HANDLE_VALUE)
CloseHandle(hDstFile);
return fRet;
}
// BUGBUG: (andrewgu) there is a number of ways we can improve this:
// 1. (first and foremost) we should be using trident for parsing html. this way will be able to
// pick up not only img tags but dynimg as well and everything else that can reference more files;
// 2. fCopy doesn't quite cut it. we should add support for generic flags. couple of them off the
// top of my head are CopyItself, and MoveNotCopy.
void CopyHtmlImgsEx(LPCTSTR pszHtmlFile, LPCTSTR pszDestPath, LPCTSTR pszSectionName, LPCTSTR pszInsFile, BOOL fCopy /*= TRUE*/)
{
TCHAR szSrcFile[MAX_PATH];
LPTSTR pszFileName, pszList;
LPSTR pszHtmlSourceA;
LPTSTR pszHtmlSource;
HANDLE hHtml;
DWORD dwHtmlFileSize,
dwSizeRead;
// read in the entire source of pszHtmlFile into a buffer
if ((hHtml = CreateFile(pszHtmlFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
if (!fCopy) { /* if (!fCopy) -- meaning delete */
// Note. In this case the semantics of parameters are slightly different. So we try to go to the pszDestPath
// were image files that we are going to delete would live and see if HTML file itself lives there.
PathCombine(szSrcFile, pszDestPath, PathFindFileName(pszHtmlFile));
pszHtmlFile = szSrcFile;
if ((hHtml = CreateFile(pszHtmlFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
return;
}
else
return;
dwHtmlFileSize = GetFileSize(hHtml, NULL);
if ((pszHtmlSourceA = (LPSTR)CoTaskMemAlloc(dwHtmlFileSize + 16)) == NULL) {
CloseHandle(hHtml);
return;
}
ZeroMemory(pszHtmlSourceA, dwHtmlFileSize + 16);
if ((pszHtmlSource = (LPTSTR)CoTaskMemAlloc(StrCbFromCch(dwHtmlFileSize + 16))) == NULL) {
CloseHandle(hHtml);
CoTaskMemFree(pszHtmlSourceA);
return;
}
ZeroMemory(pszHtmlSource, StrCbFromCch(dwHtmlFileSize + 16));
ReadFile(hHtml, (LPVOID)pszHtmlSourceA, dwHtmlFileSize, &dwSizeRead, NULL);
CloseHandle(hHtml);
A2Tbuf(pszHtmlSourceA, pszHtmlSource, dwSizeRead);
// copy the source path of pszHtmlFile to szSrcFile
PathRemoveFileSpec(StrCpy(szSrcFile, pszHtmlFile)); // copy to itself in the worst case
PathAddBackslash(szSrcFile);
pszFileName = szSrcFile + StrLen(szSrcFile); // remember the pos where the filename would get copied
if (SUCCEEDED(buildImagesList(pszHtmlSource, &pszList))) {
LPCTSTR pszImageFile;
UINT nLen;
pszImageFile = pszList;
if (pszImageFile != NULL) {
while ((nLen = StrLen(pszImageFile)) > 0) {
StrCpy(pszFileName, pszImageFile);
if (fCopy)
CopyFileToDirEx(szSrcFile, pszDestPath, pszSectionName, pszInsFile);
else /* if (!fCopy) -- meaning delete */
DeleteFileInDir(szSrcFile, pszDestPath);
pszImageFile += nLen + 1;
}
CoTaskMemFree(pszList);
}
// clean pszInsFile if deleting images
if (!fCopy && pszSectionName != NULL && pszInsFile != NULL) {
TCHAR szBuf[16];
UINT nNumFiles;
nNumFiles = GetPrivateProfileInt(pszSectionName, IK_NUMFILES, 0, pszInsFile);
WritePrivateProfileString(pszSectionName, IK_NUMFILES, NULL, pszInsFile);
for (UINT i = 0; i < nNumFiles; i++) {
wnsprintf(szBuf, countof(szBuf), FILE_TEXT, i);
WritePrivateProfileString(pszSectionName, szBuf, NULL, pszInsFile);
}
// delete the section itself if became empty
GetPrivateProfileSection(pszSectionName, szBuf, countof(szBuf), pszInsFile);
if (szBuf[0] == TEXT('\0') && szBuf[1] == TEXT('\0'))
WritePrivateProfileString(pszSectionName, NULL, NULL, pszInsFile);
}
}
CoTaskMemFree(pszHtmlSource);
CoTaskMemFree(pszHtmlSourceA);
}
HANDLE CreateNewFile(LPCTSTR pcszFileToCreate)
{
TCHAR szPath[MAX_PATH];
PathRemoveFileSpec(StrCpy(szPath, pcszFileToCreate));
PathCreatePath(szPath);
return CreateFile(pcszFileToCreate, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
DWORD FileSize(LPCTSTR pcszFile)
{
DWORD dwFileSize = 0;
WIN32_FIND_DATA FindFileData;
HANDLE hFile;
if (pcszFile == NULL || *pcszFile == '\0')
return dwFileSize;
if ((hFile = FindFirstFile(pcszFile, &FindFileData)) != INVALID_HANDLE_VALUE)
{
// assumption here is that the size of the file doesn't exceed 4 gigs
dwFileSize = FindFileData.nFileSizeLow;
FindClose(hFile);
}
return dwFileSize;
}
BOOL DeleteFileInDir(LPCTSTR pcszFile, LPCTSTR pcszDir)
// pcszFile can contain wildcards
{
TCHAR szFile[MAX_PATH];
LPTSTR pszPtr;
WIN32_FIND_DATA fileData;
HANDLE hFindFile;
BOOL fSuccess = TRUE;
if (pcszFile == NULL || *pcszFile == TEXT('\0') ||
pcszDir == NULL || *pcszDir == TEXT('\0'))
return FALSE;
StrCpy(szFile, pcszDir);
PathAddBackslash(szFile);
pszPtr = szFile + StrLen(szFile);
pcszFile = PathFindFileName(pcszFile);
if (pcszFile == NULL)
return FALSE;
StrCpy(pszPtr, pcszFile);
if ((hFindFile = FindFirstFile(szFile, &fileData)) != INVALID_HANDLE_VALUE)
{
do
{
if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
StrCpy(pszPtr, fileData.cFileName);
// DeleteFile would fail if readonly and/or hidden and/or system
// attributes are set; so set the attributes to NORMAL before deleting
SetFileAttributes(szFile, FILE_ATTRIBUTE_NORMAL);
fSuccess &= DeleteFile(szFile);
}
} while (FindNextFile(hFindFile, &fileData));
FindClose(hFindFile);
}
return fSuccess;
}
void SetAttribAllEx(LPCTSTR pcszDir, LPCTSTR pcszFile, DWORD dwAtr, BOOL fRecurse)
{
TCHAR szPath[MAX_PATH];
WIN32_FIND_DATA fd;
HANDLE hFind;
LPTSTR pszFile;
if ((pcszDir == NULL) || (pcszFile == NULL) || (ISNULL(pcszDir)) || (ISNULL(pcszFile)))
return;
StrCpy(szPath, pcszDir);
pszFile = PathAddBackslash(szPath);
if ((StrLen(szPath) + StrLen(pcszFile)) < MAX_PATH)
StrCpy(pszFile, pcszFile);
if ((hFind = FindFirstFile( szPath, &fd)) != INVALID_HANDLE_VALUE)
{
do
{
if ((StrCmp(fd.cFileName, TEXT("."))) &&
(StrCmp(fd.cFileName, TEXT(".."))))
{
StrCpy(pszFile, fd.cFileName);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (fRecurse)
SetAttribAllEx(szPath, pcszFile, dwAtr, TRUE);
}
else
{
SetFileAttributes(szPath, dwAtr);
}
}
}
while (FindNextFile(hFind, &fd));
FindClose(hFind);
}
}
DWORD GetNumberOfFiles(LPCTSTR pcszFileName, LPCTSTR pcszDir)
// Return the number of pcszFileName files found in pcszDir.
// pcszFileName can contain wildcard characters
{
DWORD nFiles = 0;
TCHAR szPath[MAX_PATH];
WIN32_FIND_DATA fd;
HANDLE hFind;
if (pcszFileName == NULL || pcszDir == NULL || ISNULL(pcszFileName) || ISNULL(pcszDir))
return 0;
PathCombine(szPath, pcszDir, pcszFileName);
if ((hFind = FindFirstFile(szPath, &fd)) != INVALID_HANDLE_VALUE)
{
do
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
nFiles++;
} while (FindNextFile(hFind, &fd));
FindClose(hFind);
}
return nFiles;
}
BOOL GetFreeDiskSpace(LPCTSTR pcszDir, LPDWORD pdwFreeSpace, LPDWORD pdwFlags)
// Return the free disk space (in KBytes) in *pdwFreeSpace
{
BOOL bRet = FALSE;
DWORD nSectorsPerCluster, nBytesPerSector, nFreeClusters, nTotalClusters;
TCHAR szDrive[8];
if (pcszDir == NULL || *pcszDir == '\0' || *(pcszDir + 1) != ':')
return FALSE;
if (pdwFreeSpace == NULL)
return FALSE;
StrNCpy(szDrive, pcszDir, 3);
PathAddBackslash(szDrive);
if (GetDiskFreeSpace(szDrive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters))
{
// convert size to KBytes; assumption here is that the free space doesn't exceed 4096 gigs
if ((*pdwFreeSpace = MulDiv(nFreeClusters, nSectorsPerCluster * nBytesPerSector, 1024)) != (DWORD) -1)
{
bRet = TRUE;
if (pdwFlags != NULL)
{
*pdwFlags = 0;
GetVolumeInformation(szDrive, NULL, 0, NULL, NULL, pdwFlags, NULL, 0);
}
}
}
return bRet;
}
DWORD FindSpaceRequired(LPCTSTR pcszSrcDir, LPCTSTR pcszFile, LPCTSTR pcszDstDir)
// Return the difference in size (in KBytes) of pcszFile (can contain wildcards)
// under pcszSrcDir and pcszDstDir (if specified)
{
DWORD dwSizeReq = 0;
TCHAR szSrcFile[MAX_PATH], szDstFile[MAX_PATH];
LPTSTR pszSrcPtr = NULL,
pszDstPtr = NULL;
WIN32_FIND_DATA fileData;
HANDLE hFindFile;
StrCpy(szSrcFile, pcszSrcDir);
PathAddBackslash(szSrcFile);
pszSrcPtr = szSrcFile + StrLen(szSrcFile);
if (pcszDstDir != NULL)
{
StrCpy(szDstFile, pcszDstDir);
PathAddBackslash(szDstFile);
pszDstPtr = szDstFile + StrLen(szDstFile);
}
StrCpy(pszSrcPtr, pcszFile);
if ((hFindFile = FindFirstFile(szSrcFile, &fileData)) != INVALID_HANDLE_VALUE)
{
do
{
if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
DWORD dwSrcSize, dwDstSize;
// assumption here is that the size of the file doesn't exceed 4 gigs
dwSrcSize = fileData.nFileSizeLow;
dwDstSize = 0;
if (pcszDstDir != NULL)
{
StrCpy(pszDstPtr, fileData.cFileName);
dwDstSize = FileSize(szDstFile);
}
if (dwSrcSize >= dwDstSize)
{
// divide the difference by 1024 (we are interested in KBytes)
dwSizeReq += ((dwSrcSize - dwDstSize) >> 10);
if (dwSrcSize > dwDstSize)
dwSizeReq++; // increment by 1 to promote any fraction to a whole number
}
}
} while (FindNextFile(hFindFile, &fileData));
FindClose(hFindFile);
}
return dwSizeReq;
}
BOOL WriteStringToFileA(HANDLE hFile, LPCVOID pbBuf, DWORD cchSize)
{
DWORD cbWritten;
return WriteFile(hFile, pbBuf, cchSize, &cbWritten, NULL);
}
BOOL WriteStringToFileW(HANDLE hFile, LPCVOID pbBuf, DWORD cchSize)
{
BOOL fRet = FALSE;
LPVOID pbaBuf;
DWORD cbSize, dwErr;
// NOTE: we must use WideCharToMultiByte here because we don't know the exact format of
// the string
pbaBuf = CoTaskMemAlloc(cchSize);
if (pbaBuf == NULL)
return FALSE;
ZeroMemory(pbaBuf, cchSize);
cbSize = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)pbBuf, cchSize, (LPSTR)pbaBuf, cchSize, NULL, NULL);
dwErr = GetLastError();
// NOTE: check to see if we fail, in which case we might be dealing with DBCS chars and
// need to reallocate
if (cbSize)
fRet = WriteStringToFileA(hFile, pbaBuf, cbSize);
else
{
if (dwErr == ERROR_INSUFFICIENT_BUFFER)
{
LPVOID pbaBuf2;
cbSize = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)pbBuf, cchSize, (LPSTR)pbaBuf, 0, NULL, NULL);
pbaBuf2 = CoTaskMemRealloc(pbaBuf, cbSize);
// need this second ptr because CoTaskMemRealloc doesn't free the old block if
// not enough mem for the new one
if (pbaBuf2 != NULL)
{
pbaBuf = pbaBuf2;
if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)pbBuf, cchSize, (LPSTR)pbaBuf, cbSize, NULL, NULL))
fRet = WriteStringToFileA(hFile, pbaBuf, cbSize);
}
}
}
CoTaskMemFree(pbaBuf);
return fRet;
}
BOOL ReadStringFromFileA(HANDLE hFile, LPVOID pbBuf, DWORD cchSize)
{
DWORD cbRead;
return ReadFile(hFile, pbBuf, cchSize, &cbRead, NULL);
}
BOOL ReadStringFromFileW(HANDLE hFile, LPVOID pbBuf, DWORD cchSize)
{
BOOL fRet = FALSE;
DWORD cbRead;
LPSTR pszBuf;
pszBuf = (LPSTR)CoTaskMemAlloc(cchSize);
if (pszBuf == NULL)
return FALSE;
ZeroMemory(pszBuf, cchSize);
fRet = ReadFile(hFile, (LPVOID)pszBuf, cchSize, &cbRead, NULL);
ASSERT(cbRead <= cchSize);
MultiByteToWideChar(CP_ACP, 0, pszBuf, cbRead, (LPWSTR)pbBuf, cbRead);
CoTaskMemFree(pszBuf); //bug 14002, forgot to free local buffer
return fRet;
}
BOOL HasFileAttribute(DWORD dwFileAttrib, LPCTSTR pcszFile, LPCTSTR pcszDir /*= NULL*/)
// dwFileAttrib can accept only one flag.
{
TCHAR szFile[MAX_PATH];
DWORD dwAttrib;
if (pcszFile == NULL || *pcszFile == TEXT('\0'))
return FALSE;
if (pcszDir != NULL && *pcszDir != TEXT('\0'))
{
PathCombine(szFile, pcszDir, pcszFile);
pcszFile = szFile;
}
dwAttrib = GetFileAttributes(pcszFile);
if ((dwAttrib != (DWORD) -1) && HasFlag(dwAttrib, dwFileAttrib))
return TRUE;
else
return FALSE;
}
BOOL IsFileCreatable(LPCTSTR pcszFile)
// Return TRUE if pcszFile does not exist and can be created; otherwise, return FALSE
{
BOOL fRet = FALSE;
HANDLE hFile;
if ((hFile = CreateFile(pcszFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
{
if ((hFile = CreateFile(pcszFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
{
fRet = TRUE;
CloseHandle(hFile);
DeleteFile(pcszFile);
}
}
else
{
fRet = TRUE;
CloseHandle(hFile);
}
return fRet;
}
/////////////////////////////////////////////////////////////////////////////
// Implementation helpers routines (private)
#define DELIMS TEXT(" \t\r\n")
static const TCHAR s_szDelim[] = DELIMS;
#define FindNextWhitespace(psz) \
((psz) + StrCSpn((psz), s_szDelim))
#define FindNextNonWhitespace(psz) \
((psz) + StrSpn((psz), s_szDelim))
static LPCTSTR findMatchingBracket(LPCTSTR pszHtml)
{
LPCTSTR psz,
pszBraket;
UINT nBalance;
if (pszHtml == NULL || *pszHtml != TEXT('<'))
return NULL;
psz = pszHtml + 1;
pszBraket = NULL;
nBalance = 1;
while (psz != NULL && nBalance > 0) {
pszBraket = StrPBrk(psz, TEXT("<>"));
if (pszBraket == NULL)
return NULL;
if (*pszBraket == TEXT('<'))
nBalance++;
else /* if (pszBraket == TEXT('>') */
nBalance--;
psz = pszBraket + 1;
}
return pszBraket;
}
static HRESULT findImgSrc(LPCTSTR *ppszHtml, LPTSTR pszSrcBuffer, LPUINT pcch)
{
static const TCHAR c_szImg[] = TEXT("IMG");
static const TCHAR c_szSrc[] = TEXT("SRC");
LPCTSTR psz,
pszLeft, pszRigth,
pszEndImg, pszPrevSrc;
if (ppszHtml == NULL)
return E_POINTER;
if (*ppszHtml == NULL)
return E_INVALIDARG;
if (pszSrcBuffer == NULL || pcch == NULL)
return E_INVALIDARG;
*pszSrcBuffer = TEXT('\0');
// find "<[whitespace]img"
psz = *ppszHtml;
*ppszHtml = NULL;
do {
if ((psz = pszLeft = StrChr(psz, TEXT('<'))) != NULL) {
psz++; // psz is next after '<'
psz = FindNextNonWhitespace(psz);
}
} while (psz != NULL && StrCmpNI(psz, c_szImg, countof(c_szImg)-1) != 0);
if (psz == NULL)
return E_FAIL;
psz += countof(c_szImg)-1; // psz is next after "img"
// found the right token => find the end of this token
pszRigth = findMatchingBracket(pszLeft);
if (pszRigth == NULL)
return E_FAIL;
pszEndImg = pszRigth + 1;
// BUGBUG: Need to look for DYNSRC's to package as well
pszPrevSrc = NULL;
// find [whitespace]src[whitespace|=]
while ((psz = StrStrI(psz, c_szSrc)), (psz != NULL && psz < pszRigth && psz != pszPrevSrc))
if (StrChr(s_szDelim, *(psz - 1)) != NULL &&
StrChr(DELIMS TEXT("="), *(psz + countof(c_szSrc)-1)) != NULL)
break;
else
// IE/OE 65818
// Make sure an IMG tag with no 'src' attribute, but a 'foosrc' attribute doesn't
// cause an infinite loop
pszPrevSrc = psz;
if (psz == NULL)
// No more SRC's in the rest of file
return E_FAIL;
else if ((psz >= pszRigth) || (psz == pszPrevSrc))
{
// No SRC attrib for this tag, could be more in the file
*ppszHtml = pszEndImg;
return S_FALSE;
}
psz += countof(c_szSrc)-1; // psz is next after "src"
// find '='
psz = FindNextNonWhitespace(psz);
if (psz == NULL || *psz != TEXT('='))
return E_FAIL;
psz++;
psz = FindNextNonWhitespace(psz);
if (psz == NULL)
return E_FAIL;
// psz is a winner
if (*psz == TEXT('"')) {
pszLeft = psz + 1;
pszRigth = StrChr(pszLeft, TEXT('"'));
}
else {
pszLeft = psz;
pszRigth = FindNextWhitespace(pszLeft);
}
if (pszLeft == NULL || pszRigth == NULL)
return E_FAIL;
// ASSERT(pszRight >= pszLeft);
if ((UINT)(pszRigth - pszLeft) > *pcch - 1) {
*pcch = UINT(pszRigth - pszLeft);
return E_OUTOFMEMORY;
}
*ppszHtml = pszEndImg;
StrCpyN(pszSrcBuffer, pszLeft, INT(pszRigth - pszLeft) + 1);
*pcch = UINT(pszRigth - pszLeft);
return S_OK;
}
static HRESULT buildImagesList(LPCTSTR pszHtml, LPTSTR *ppszList)
{
TCHAR szImg[MAX_PATH];
LPCTSTR pszCurHtml = pszHtml;
LPTSTR pszBlock, pszNewBlock,
pszCurPos;
UINT nTotalLen,
nLen;
HRESULT hr;
if (ppszList == NULL)
return E_POINTER;
*ppszList = NULL;
pszBlock = (LPTSTR)CoTaskMemAlloc(StrCbFromCch(4 * MAX_PATH));
if (pszBlock == NULL)
return E_OUTOFMEMORY;
ZeroMemory(pszBlock, StrCbFromCch(4 * MAX_PATH));
pszCurPos = pszBlock;
nTotalLen = 0;
nLen = countof(szImg);
while (SUCCEEDED(hr = findImgSrc(&pszCurHtml, szImg, &nLen))) {
// S_FALSE indicates an img with no simple SRC
if (PathIsURL(szImg) || PathIsFullPath(szImg) || S_FALSE == hr)
continue;
if (StrCbFromCch(nLen+1 + nTotalLen+1) > CoTaskMemSize(pszBlock)) {
pszNewBlock = (LPTSTR)CoTaskMemRealloc(pszBlock, StrCbFromCch(nTotalLen+1 + nLen+1 + 2*MAX_PATH));
if (pszNewBlock == NULL) {
CoTaskMemFree(pszBlock);
return E_OUTOFMEMORY;
}
ZeroMemory(pszNewBlock + nTotalLen, StrCbFromCch(1 + nLen+1 + 2*MAX_PATH));
pszBlock = pszNewBlock;
pszCurPos = pszBlock + nTotalLen;
}
StrCpy(pszCurPos, szImg);
nTotalLen += nLen + 1;
pszCurPos += nLen + 1;
nLen = countof(szImg);
}
if (nTotalLen > 0) {
if (StrCbFromCch(nTotalLen+1) < CoTaskMemSize(pszBlock)) {
pszNewBlock = (LPTSTR)CoTaskMemRealloc(pszBlock, StrCbFromCch(nTotalLen+1));
if (pszNewBlock != NULL && pszNewBlock != pszBlock)
pszBlock = pszNewBlock;
}
*ppszList = pszBlock;
}
else
CoTaskMemFree(pszBlock);
return S_OK;
}