|
|
#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; }
|