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

  1. #include "precomp.h"
  2. // Private forward decalarations
  3. static LPCTSTR findMatchingBracket(LPCTSTR pszHtml);
  4. static HRESULT findImgSrc(LPCTSTR *ppszHtml, LPTSTR pszSrcBuffer, LPUINT pcch);
  5. static HRESULT buildImagesList(LPCTSTR pszHtml, LPTSTR *ppszList);
  6. BOOL CopyFileToDirEx(LPCTSTR pszSourceFileOrPath, LPCTSTR pszTargetPath, LPCTSTR pszSection /*= NULL*/, LPCTSTR pszIns /*= NULL*/)
  7. {
  8. LPTSTR pszAuxFile;
  9. BOOL fResult;
  10. if (!PathFileExists(pszSourceFileOrPath))
  11. return FALSE;
  12. fResult = TRUE;
  13. if (!PathIsDirectory(pszSourceFileOrPath)) { // file
  14. TCHAR szTargetFile[MAX_PATH];
  15. fResult = PathCreatePath(pszTargetPath);
  16. if (!fResult)
  17. return FALSE;
  18. pszAuxFile = PathFindFileName(pszSourceFileOrPath);
  19. PathCombine(szTargetFile, pszTargetPath, pszAuxFile);
  20. SetFileAttributes(szTargetFile, FILE_ATTRIBUTE_NORMAL);
  21. fResult = CopyFile(pszSourceFileOrPath, szTargetFile, FALSE);
  22. if (!fResult)
  23. return FALSE;
  24. //----- Update the ins file -----
  25. if (pszSection != NULL && pszIns != NULL) {
  26. TCHAR szBuf[16];
  27. UINT nNumFiles;
  28. nNumFiles = (UINT)GetPrivateProfileInt(pszSection, IK_NUMFILES, 0, pszIns);
  29. wnsprintf(szBuf, countof(szBuf), TEXT("%u"), ++nNumFiles);
  30. WritePrivateProfileString(pszSection, IK_NUMFILES, szBuf, pszIns);
  31. ASSERT(nNumFiles > 0);
  32. wnsprintf(szBuf, countof(szBuf), FILE_TEXT, nNumFiles - 1);
  33. WritePrivateProfileString(pszSection, szBuf, pszAuxFile, pszIns);
  34. }
  35. }
  36. else { // directory
  37. // BUGBUG: Won't copy files in sub-dirs under pszSourceFileOrPath
  38. WIN32_FIND_DATA fd;
  39. TCHAR szSourceFile[MAX_PATH];
  40. HANDLE hFindFile;
  41. StrCpy(szSourceFile, pszSourceFileOrPath);
  42. PathAddBackslash(szSourceFile);
  43. // remember the pos where the filename would get copied
  44. pszAuxFile = szSourceFile + StrLen(szSourceFile);
  45. StrCpy(pszAuxFile, TEXT("*.*"));
  46. // copy all the files in pszSourceFileOrPath to pszTargetPath
  47. hFindFile = FindFirstFile(szSourceFile, &fd);
  48. if (hFindFile != INVALID_HANDLE_VALUE) {
  49. fResult = TRUE;
  50. do {
  51. // skip ".", ".." and all sub-dirs
  52. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  53. continue;
  54. StrCpy(pszAuxFile, fd.cFileName);
  55. // keep going even if copying of a file fails, but return FALSE in case of error
  56. fResult = fResult && CopyFileToDirEx(szSourceFile, pszTargetPath, pszSection, pszIns);
  57. } while (FindNextFile(hFindFile, &fd));
  58. FindClose(hFindFile);
  59. }
  60. }
  61. return fResult;
  62. }
  63. BOOL AppendFile(LPCTSTR pcszSrcFile, LPCTSTR pcszDstFile)
  64. // Append the content of pcszSrcFile to pcszDstFile.
  65. {
  66. BOOL fRet = FALSE;
  67. HANDLE hDstFile = INVALID_HANDLE_VALUE,
  68. hSrcFile = INVALID_HANDLE_VALUE;
  69. LPBYTE pbBuffer = NULL;
  70. DWORD cbRead, cbWritten;
  71. if (pcszDstFile == NULL || pcszSrcFile == NULL || ISNULL(pcszDstFile) || ISNULL(pcszSrcFile))
  72. return FALSE;
  73. if ((hDstFile = CreateFile(pcszDstFile, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
  74. {
  75. // DstFile doesn't exist; create one and call CopyFile()
  76. if ((hDstFile = CreateNewFile(pcszDstFile)) != INVALID_HANDLE_VALUE)
  77. {
  78. CloseHandle(hDstFile);
  79. hDstFile = INVALID_HANDLE_VALUE;
  80. fRet = CopyFile(pcszSrcFile, pcszDstFile, FALSE);
  81. }
  82. goto CleanUp;
  83. }
  84. if (SetFilePointer(hDstFile, 0, NULL, FILE_END) == (DWORD) -1)
  85. goto CleanUp;
  86. if ((hSrcFile = CreateFile(pcszSrcFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
  87. goto CleanUp;
  88. // allocate a 4K buffer
  89. if ((pbBuffer = (LPBYTE)CoTaskMemAlloc(4 * 1024)) == NULL)
  90. goto CleanUp;
  91. ZeroMemory(pbBuffer, 4 * 1024);
  92. while ((fRet = ReadFile(hSrcFile, (LPVOID) pbBuffer, 4 * 1024, &cbRead, NULL)) == TRUE)
  93. {
  94. if (cbRead == 0)
  95. break;
  96. fRet = WriteFile(hDstFile, (LPCVOID) pbBuffer, cbRead, &cbWritten, NULL);
  97. if (!fRet)
  98. break;
  99. ASSERT(cbRead == cbWritten);
  100. }
  101. if (!fRet)
  102. goto CleanUp;
  103. fRet = TRUE;
  104. // good thing to do, esp. on Win95 if you combine AppendFile with Get/WritePrivateProfile functions.
  105. FlushFileBuffers(hDstFile);
  106. CleanUp:
  107. if (pbBuffer != NULL)
  108. CoTaskMemFree(pbBuffer);
  109. if (hSrcFile != INVALID_HANDLE_VALUE)
  110. CloseHandle(hSrcFile);
  111. if (hDstFile != INVALID_HANDLE_VALUE)
  112. CloseHandle(hDstFile);
  113. return fRet;
  114. }
  115. // BUGBUG: (andrewgu) there is a number of ways we can improve this:
  116. // 1. (first and foremost) we should be using trident for parsing html. this way will be able to
  117. // pick up not only img tags but dynimg as well and everything else that can reference more files;
  118. // 2. fCopy doesn't quite cut it. we should add support for generic flags. couple of them off the
  119. // top of my head are CopyItself, and MoveNotCopy.
  120. void CopyHtmlImgsEx(LPCTSTR pszHtmlFile, LPCTSTR pszDestPath, LPCTSTR pszSectionName, LPCTSTR pszInsFile, BOOL fCopy /*= TRUE*/)
  121. {
  122. TCHAR szSrcFile[MAX_PATH];
  123. LPTSTR pszFileName, pszList;
  124. LPSTR pszHtmlSourceA;
  125. LPTSTR pszHtmlSource;
  126. HANDLE hHtml;
  127. DWORD dwHtmlFileSize,
  128. dwSizeRead;
  129. // read in the entire source of pszHtmlFile into a buffer
  130. if ((hHtml = CreateFile(pszHtmlFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
  131. if (!fCopy) { /* if (!fCopy) -- meaning delete */
  132. // Note. In this case the semantics of parameters are slightly different. So we try to go to the pszDestPath
  133. // were image files that we are going to delete would live and see if HTML file itself lives there.
  134. PathCombine(szSrcFile, pszDestPath, PathFindFileName(pszHtmlFile));
  135. pszHtmlFile = szSrcFile;
  136. if ((hHtml = CreateFile(pszHtmlFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
  137. return;
  138. }
  139. else
  140. return;
  141. dwHtmlFileSize = GetFileSize(hHtml, NULL);
  142. if ((pszHtmlSourceA = (LPSTR)CoTaskMemAlloc(dwHtmlFileSize + 16)) == NULL) {
  143. CloseHandle(hHtml);
  144. return;
  145. }
  146. ZeroMemory(pszHtmlSourceA, dwHtmlFileSize + 16);
  147. if ((pszHtmlSource = (LPTSTR)CoTaskMemAlloc(StrCbFromCch(dwHtmlFileSize + 16))) == NULL) {
  148. CloseHandle(hHtml);
  149. CoTaskMemFree(pszHtmlSourceA);
  150. return;
  151. }
  152. ZeroMemory(pszHtmlSource, StrCbFromCch(dwHtmlFileSize + 16));
  153. ReadFile(hHtml, (LPVOID)pszHtmlSourceA, dwHtmlFileSize, &dwSizeRead, NULL);
  154. CloseHandle(hHtml);
  155. A2Tbuf(pszHtmlSourceA, pszHtmlSource, dwSizeRead);
  156. // copy the source path of pszHtmlFile to szSrcFile
  157. PathRemoveFileSpec(StrCpy(szSrcFile, pszHtmlFile)); // copy to itself in the worst case
  158. PathAddBackslash(szSrcFile);
  159. pszFileName = szSrcFile + StrLen(szSrcFile); // remember the pos where the filename would get copied
  160. if (SUCCEEDED(buildImagesList(pszHtmlSource, &pszList))) {
  161. LPCTSTR pszImageFile;
  162. UINT nLen;
  163. pszImageFile = pszList;
  164. if (pszImageFile != NULL) {
  165. while ((nLen = StrLen(pszImageFile)) > 0) {
  166. StrCpy(pszFileName, pszImageFile);
  167. if (fCopy)
  168. CopyFileToDirEx(szSrcFile, pszDestPath, pszSectionName, pszInsFile);
  169. else /* if (!fCopy) -- meaning delete */
  170. DeleteFileInDir(szSrcFile, pszDestPath);
  171. pszImageFile += nLen + 1;
  172. }
  173. CoTaskMemFree(pszList);
  174. }
  175. // clean pszInsFile if deleting images
  176. if (!fCopy && pszSectionName != NULL && pszInsFile != NULL) {
  177. TCHAR szBuf[16];
  178. UINT nNumFiles;
  179. nNumFiles = GetPrivateProfileInt(pszSectionName, IK_NUMFILES, 0, pszInsFile);
  180. WritePrivateProfileString(pszSectionName, IK_NUMFILES, NULL, pszInsFile);
  181. for (UINT i = 0; i < nNumFiles; i++) {
  182. wnsprintf(szBuf, countof(szBuf), FILE_TEXT, i);
  183. WritePrivateProfileString(pszSectionName, szBuf, NULL, pszInsFile);
  184. }
  185. // delete the section itself if became empty
  186. GetPrivateProfileSection(pszSectionName, szBuf, countof(szBuf), pszInsFile);
  187. if (szBuf[0] == TEXT('\0') && szBuf[1] == TEXT('\0'))
  188. WritePrivateProfileString(pszSectionName, NULL, NULL, pszInsFile);
  189. }
  190. }
  191. CoTaskMemFree(pszHtmlSource);
  192. CoTaskMemFree(pszHtmlSourceA);
  193. }
  194. HANDLE CreateNewFile(LPCTSTR pcszFileToCreate)
  195. {
  196. TCHAR szPath[MAX_PATH];
  197. PathRemoveFileSpec(StrCpy(szPath, pcszFileToCreate));
  198. PathCreatePath(szPath);
  199. return CreateFile(pcszFileToCreate, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  200. }
  201. DWORD FileSize(LPCTSTR pcszFile)
  202. {
  203. DWORD dwFileSize = 0;
  204. WIN32_FIND_DATA FindFileData;
  205. HANDLE hFile;
  206. if (pcszFile == NULL || *pcszFile == '\0')
  207. return dwFileSize;
  208. if ((hFile = FindFirstFile(pcszFile, &FindFileData)) != INVALID_HANDLE_VALUE)
  209. {
  210. // assumption here is that the size of the file doesn't exceed 4 gigs
  211. dwFileSize = FindFileData.nFileSizeLow;
  212. FindClose(hFile);
  213. }
  214. return dwFileSize;
  215. }
  216. BOOL DeleteFileInDir(LPCTSTR pcszFile, LPCTSTR pcszDir)
  217. // pcszFile can contain wildcards
  218. {
  219. TCHAR szFile[MAX_PATH];
  220. LPTSTR pszPtr;
  221. WIN32_FIND_DATA fileData;
  222. HANDLE hFindFile;
  223. BOOL fSuccess = TRUE;
  224. if (pcszFile == NULL || *pcszFile == TEXT('\0') ||
  225. pcszDir == NULL || *pcszDir == TEXT('\0'))
  226. return FALSE;
  227. StrCpy(szFile, pcszDir);
  228. PathAddBackslash(szFile);
  229. pszPtr = szFile + StrLen(szFile);
  230. pcszFile = PathFindFileName(pcszFile);
  231. if (pcszFile == NULL)
  232. return FALSE;
  233. StrCpy(pszPtr, pcszFile);
  234. if ((hFindFile = FindFirstFile(szFile, &fileData)) != INVALID_HANDLE_VALUE)
  235. {
  236. do
  237. {
  238. if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  239. {
  240. StrCpy(pszPtr, fileData.cFileName);
  241. // DeleteFile would fail if readonly and/or hidden and/or system
  242. // attributes are set; so set the attributes to NORMAL before deleting
  243. SetFileAttributes(szFile, FILE_ATTRIBUTE_NORMAL);
  244. fSuccess &= DeleteFile(szFile);
  245. }
  246. } while (FindNextFile(hFindFile, &fileData));
  247. FindClose(hFindFile);
  248. }
  249. return fSuccess;
  250. }
  251. void SetAttribAllEx(LPCTSTR pcszDir, LPCTSTR pcszFile, DWORD dwAtr, BOOL fRecurse)
  252. {
  253. TCHAR szPath[MAX_PATH];
  254. WIN32_FIND_DATA fd;
  255. HANDLE hFind;
  256. LPTSTR pszFile;
  257. if ((pcszDir == NULL) || (pcszFile == NULL) || (ISNULL(pcszDir)) || (ISNULL(pcszFile)))
  258. return;
  259. StrCpy(szPath, pcszDir);
  260. pszFile = PathAddBackslash(szPath);
  261. if ((StrLen(szPath) + StrLen(pcszFile)) < MAX_PATH)
  262. StrCpy(pszFile, pcszFile);
  263. if ((hFind = FindFirstFile( szPath, &fd)) != INVALID_HANDLE_VALUE)
  264. {
  265. do
  266. {
  267. if ((StrCmp(fd.cFileName, TEXT("."))) &&
  268. (StrCmp(fd.cFileName, TEXT(".."))))
  269. {
  270. StrCpy(pszFile, fd.cFileName);
  271. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  272. {
  273. if (fRecurse)
  274. SetAttribAllEx(szPath, pcszFile, dwAtr, TRUE);
  275. }
  276. else
  277. {
  278. SetFileAttributes(szPath, dwAtr);
  279. }
  280. }
  281. }
  282. while (FindNextFile(hFind, &fd));
  283. FindClose(hFind);
  284. }
  285. }
  286. DWORD GetNumberOfFiles(LPCTSTR pcszFileName, LPCTSTR pcszDir)
  287. // Return the number of pcszFileName files found in pcszDir.
  288. // pcszFileName can contain wildcard characters
  289. {
  290. DWORD nFiles = 0;
  291. TCHAR szPath[MAX_PATH];
  292. WIN32_FIND_DATA fd;
  293. HANDLE hFind;
  294. if (pcszFileName == NULL || pcszDir == NULL || ISNULL(pcszFileName) || ISNULL(pcszDir))
  295. return 0;
  296. PathCombine(szPath, pcszDir, pcszFileName);
  297. if ((hFind = FindFirstFile(szPath, &fd)) != INVALID_HANDLE_VALUE)
  298. {
  299. do
  300. {
  301. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  302. continue;
  303. nFiles++;
  304. } while (FindNextFile(hFind, &fd));
  305. FindClose(hFind);
  306. }
  307. return nFiles;
  308. }
  309. BOOL GetFreeDiskSpace(LPCTSTR pcszDir, LPDWORD pdwFreeSpace, LPDWORD pdwFlags)
  310. // Return the free disk space (in KBytes) in *pdwFreeSpace
  311. {
  312. BOOL bRet = FALSE;
  313. DWORD nSectorsPerCluster, nBytesPerSector, nFreeClusters, nTotalClusters;
  314. TCHAR szDrive[8];
  315. if (pcszDir == NULL || *pcszDir == '\0' || *(pcszDir + 1) != ':')
  316. return FALSE;
  317. if (pdwFreeSpace == NULL)
  318. return FALSE;
  319. StrNCpy(szDrive, pcszDir, 3);
  320. PathAddBackslash(szDrive);
  321. if (GetDiskFreeSpace(szDrive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters))
  322. {
  323. // convert size to KBytes; assumption here is that the free space doesn't exceed 4096 gigs
  324. if ((*pdwFreeSpace = MulDiv(nFreeClusters, nSectorsPerCluster * nBytesPerSector, 1024)) != (DWORD) -1)
  325. {
  326. bRet = TRUE;
  327. if (pdwFlags != NULL)
  328. {
  329. *pdwFlags = 0;
  330. GetVolumeInformation(szDrive, NULL, 0, NULL, NULL, pdwFlags, NULL, 0);
  331. }
  332. }
  333. }
  334. return bRet;
  335. }
  336. DWORD FindSpaceRequired(LPCTSTR pcszSrcDir, LPCTSTR pcszFile, LPCTSTR pcszDstDir)
  337. // Return the difference in size (in KBytes) of pcszFile (can contain wildcards)
  338. // under pcszSrcDir and pcszDstDir (if specified)
  339. {
  340. DWORD dwSizeReq = 0;
  341. TCHAR szSrcFile[MAX_PATH], szDstFile[MAX_PATH];
  342. LPTSTR pszSrcPtr = NULL,
  343. pszDstPtr = NULL;
  344. WIN32_FIND_DATA fileData;
  345. HANDLE hFindFile;
  346. StrCpy(szSrcFile, pcszSrcDir);
  347. PathAddBackslash(szSrcFile);
  348. pszSrcPtr = szSrcFile + StrLen(szSrcFile);
  349. if (pcszDstDir != NULL)
  350. {
  351. StrCpy(szDstFile, pcszDstDir);
  352. PathAddBackslash(szDstFile);
  353. pszDstPtr = szDstFile + StrLen(szDstFile);
  354. }
  355. StrCpy(pszSrcPtr, pcszFile);
  356. if ((hFindFile = FindFirstFile(szSrcFile, &fileData)) != INVALID_HANDLE_VALUE)
  357. {
  358. do
  359. {
  360. if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  361. {
  362. DWORD dwSrcSize, dwDstSize;
  363. // assumption here is that the size of the file doesn't exceed 4 gigs
  364. dwSrcSize = fileData.nFileSizeLow;
  365. dwDstSize = 0;
  366. if (pcszDstDir != NULL)
  367. {
  368. StrCpy(pszDstPtr, fileData.cFileName);
  369. dwDstSize = FileSize(szDstFile);
  370. }
  371. if (dwSrcSize >= dwDstSize)
  372. {
  373. // divide the difference by 1024 (we are interested in KBytes)
  374. dwSizeReq += ((dwSrcSize - dwDstSize) >> 10);
  375. if (dwSrcSize > dwDstSize)
  376. dwSizeReq++; // increment by 1 to promote any fraction to a whole number
  377. }
  378. }
  379. } while (FindNextFile(hFindFile, &fileData));
  380. FindClose(hFindFile);
  381. }
  382. return dwSizeReq;
  383. }
  384. BOOL WriteStringToFileA(HANDLE hFile, LPCVOID pbBuf, DWORD cchSize)
  385. {
  386. DWORD cbWritten;
  387. return WriteFile(hFile, pbBuf, cchSize, &cbWritten, NULL);
  388. }
  389. BOOL WriteStringToFileW(HANDLE hFile, LPCVOID pbBuf, DWORD cchSize)
  390. {
  391. BOOL fRet = FALSE;
  392. LPVOID pbaBuf;
  393. DWORD cbSize, dwErr;
  394. // NOTE: we must use WideCharToMultiByte here because we don't know the exact format of
  395. // the string
  396. pbaBuf = CoTaskMemAlloc(cchSize);
  397. if (pbaBuf == NULL)
  398. return FALSE;
  399. ZeroMemory(pbaBuf, cchSize);
  400. cbSize = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)pbBuf, cchSize, (LPSTR)pbaBuf, cchSize, NULL, NULL);
  401. dwErr = GetLastError();
  402. // NOTE: check to see if we fail, in which case we might be dealing with DBCS chars and
  403. // need to reallocate
  404. if (cbSize)
  405. fRet = WriteStringToFileA(hFile, pbaBuf, cbSize);
  406. else
  407. {
  408. if (dwErr == ERROR_INSUFFICIENT_BUFFER)
  409. {
  410. LPVOID pbaBuf2;
  411. cbSize = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)pbBuf, cchSize, (LPSTR)pbaBuf, 0, NULL, NULL);
  412. pbaBuf2 = CoTaskMemRealloc(pbaBuf, cbSize);
  413. // need this second ptr because CoTaskMemRealloc doesn't free the old block if
  414. // not enough mem for the new one
  415. if (pbaBuf2 != NULL)
  416. {
  417. pbaBuf = pbaBuf2;
  418. if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)pbBuf, cchSize, (LPSTR)pbaBuf, cbSize, NULL, NULL))
  419. fRet = WriteStringToFileA(hFile, pbaBuf, cbSize);
  420. }
  421. }
  422. }
  423. CoTaskMemFree(pbaBuf);
  424. return fRet;
  425. }
  426. BOOL ReadStringFromFileA(HANDLE hFile, LPVOID pbBuf, DWORD cchSize)
  427. {
  428. DWORD cbRead;
  429. return ReadFile(hFile, pbBuf, cchSize, &cbRead, NULL);
  430. }
  431. BOOL ReadStringFromFileW(HANDLE hFile, LPVOID pbBuf, DWORD cchSize)
  432. {
  433. BOOL fRet = FALSE;
  434. DWORD cbRead;
  435. LPSTR pszBuf;
  436. pszBuf = (LPSTR)CoTaskMemAlloc(cchSize);
  437. if (pszBuf == NULL)
  438. return FALSE;
  439. ZeroMemory(pszBuf, cchSize);
  440. fRet = ReadFile(hFile, (LPVOID)pszBuf, cchSize, &cbRead, NULL);
  441. ASSERT(cbRead <= cchSize);
  442. MultiByteToWideChar(CP_ACP, 0, pszBuf, cbRead, (LPWSTR)pbBuf, cbRead);
  443. CoTaskMemFree(pszBuf); //bug 14002, forgot to free local buffer
  444. return fRet;
  445. }
  446. BOOL HasFileAttribute(DWORD dwFileAttrib, LPCTSTR pcszFile, LPCTSTR pcszDir /*= NULL*/)
  447. // dwFileAttrib can accept only one flag.
  448. {
  449. TCHAR szFile[MAX_PATH];
  450. DWORD dwAttrib;
  451. if (pcszFile == NULL || *pcszFile == TEXT('\0'))
  452. return FALSE;
  453. if (pcszDir != NULL && *pcszDir != TEXT('\0'))
  454. {
  455. PathCombine(szFile, pcszDir, pcszFile);
  456. pcszFile = szFile;
  457. }
  458. dwAttrib = GetFileAttributes(pcszFile);
  459. if ((dwAttrib != (DWORD) -1) && HasFlag(dwAttrib, dwFileAttrib))
  460. return TRUE;
  461. else
  462. return FALSE;
  463. }
  464. BOOL IsFileCreatable(LPCTSTR pcszFile)
  465. // Return TRUE if pcszFile does not exist and can be created; otherwise, return FALSE
  466. {
  467. BOOL fRet = FALSE;
  468. HANDLE hFile;
  469. if ((hFile = CreateFile(pcszFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
  470. {
  471. if ((hFile = CreateFile(pcszFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
  472. {
  473. fRet = TRUE;
  474. CloseHandle(hFile);
  475. DeleteFile(pcszFile);
  476. }
  477. }
  478. else
  479. {
  480. fRet = TRUE;
  481. CloseHandle(hFile);
  482. }
  483. return fRet;
  484. }
  485. /////////////////////////////////////////////////////////////////////////////
  486. // Implementation helpers routines (private)
  487. #define DELIMS TEXT(" \t\r\n")
  488. static const TCHAR s_szDelim[] = DELIMS;
  489. #define FindNextWhitespace(psz) \
  490. ((psz) + StrCSpn((psz), s_szDelim))
  491. #define FindNextNonWhitespace(psz) \
  492. ((psz) + StrSpn((psz), s_szDelim))
  493. static LPCTSTR findMatchingBracket(LPCTSTR pszHtml)
  494. {
  495. LPCTSTR psz,
  496. pszBraket;
  497. UINT nBalance;
  498. if (pszHtml == NULL || *pszHtml != TEXT('<'))
  499. return NULL;
  500. psz = pszHtml + 1;
  501. pszBraket = NULL;
  502. nBalance = 1;
  503. while (psz != NULL && nBalance > 0) {
  504. pszBraket = StrPBrk(psz, TEXT("<>"));
  505. if (pszBraket == NULL)
  506. return NULL;
  507. if (*pszBraket == TEXT('<'))
  508. nBalance++;
  509. else /* if (pszBraket == TEXT('>') */
  510. nBalance--;
  511. psz = pszBraket + 1;
  512. }
  513. return pszBraket;
  514. }
  515. static HRESULT findImgSrc(LPCTSTR *ppszHtml, LPTSTR pszSrcBuffer, LPUINT pcch)
  516. {
  517. static const TCHAR c_szImg[] = TEXT("IMG");
  518. static const TCHAR c_szSrc[] = TEXT("SRC");
  519. LPCTSTR psz,
  520. pszLeft, pszRigth,
  521. pszEndImg, pszPrevSrc;
  522. if (ppszHtml == NULL)
  523. return E_POINTER;
  524. if (*ppszHtml == NULL)
  525. return E_INVALIDARG;
  526. if (pszSrcBuffer == NULL || pcch == NULL)
  527. return E_INVALIDARG;
  528. *pszSrcBuffer = TEXT('\0');
  529. // find "<[whitespace]img"
  530. psz = *ppszHtml;
  531. *ppszHtml = NULL;
  532. do {
  533. if ((psz = pszLeft = StrChr(psz, TEXT('<'))) != NULL) {
  534. psz++; // psz is next after '<'
  535. psz = FindNextNonWhitespace(psz);
  536. }
  537. } while (psz != NULL && StrCmpNI(psz, c_szImg, countof(c_szImg)-1) != 0);
  538. if (psz == NULL)
  539. return E_FAIL;
  540. psz += countof(c_szImg)-1; // psz is next after "img"
  541. // found the right token => find the end of this token
  542. pszRigth = findMatchingBracket(pszLeft);
  543. if (pszRigth == NULL)
  544. return E_FAIL;
  545. pszEndImg = pszRigth + 1;
  546. // BUGBUG: Need to look for DYNSRC's to package as well
  547. pszPrevSrc = NULL;
  548. // find [whitespace]src[whitespace|=]
  549. while ((psz = StrStrI(psz, c_szSrc)), (psz != NULL && psz < pszRigth && psz != pszPrevSrc))
  550. if (StrChr(s_szDelim, *(psz - 1)) != NULL &&
  551. StrChr(DELIMS TEXT("="), *(psz + countof(c_szSrc)-1)) != NULL)
  552. break;
  553. else
  554. // IE/OE 65818
  555. // Make sure an IMG tag with no 'src' attribute, but a 'foosrc' attribute doesn't
  556. // cause an infinite loop
  557. pszPrevSrc = psz;
  558. if (psz == NULL)
  559. // No more SRC's in the rest of file
  560. return E_FAIL;
  561. else if ((psz >= pszRigth) || (psz == pszPrevSrc))
  562. {
  563. // No SRC attrib for this tag, could be more in the file
  564. *ppszHtml = pszEndImg;
  565. return S_FALSE;
  566. }
  567. psz += countof(c_szSrc)-1; // psz is next after "src"
  568. // find '='
  569. psz = FindNextNonWhitespace(psz);
  570. if (psz == NULL || *psz != TEXT('='))
  571. return E_FAIL;
  572. psz++;
  573. psz = FindNextNonWhitespace(psz);
  574. if (psz == NULL)
  575. return E_FAIL;
  576. // psz is a winner
  577. if (*psz == TEXT('"')) {
  578. pszLeft = psz + 1;
  579. pszRigth = StrChr(pszLeft, TEXT('"'));
  580. }
  581. else {
  582. pszLeft = psz;
  583. pszRigth = FindNextWhitespace(pszLeft);
  584. }
  585. if (pszLeft == NULL || pszRigth == NULL)
  586. return E_FAIL;
  587. // ASSERT(pszRight >= pszLeft);
  588. if ((UINT)(pszRigth - pszLeft) > *pcch - 1) {
  589. *pcch = UINT(pszRigth - pszLeft);
  590. return E_OUTOFMEMORY;
  591. }
  592. *ppszHtml = pszEndImg;
  593. StrCpyN(pszSrcBuffer, pszLeft, INT(pszRigth - pszLeft) + 1);
  594. *pcch = UINT(pszRigth - pszLeft);
  595. return S_OK;
  596. }
  597. static HRESULT buildImagesList(LPCTSTR pszHtml, LPTSTR *ppszList)
  598. {
  599. TCHAR szImg[MAX_PATH];
  600. LPCTSTR pszCurHtml = pszHtml;
  601. LPTSTR pszBlock, pszNewBlock,
  602. pszCurPos;
  603. UINT nTotalLen,
  604. nLen;
  605. HRESULT hr;
  606. if (ppszList == NULL)
  607. return E_POINTER;
  608. *ppszList = NULL;
  609. pszBlock = (LPTSTR)CoTaskMemAlloc(StrCbFromCch(4 * MAX_PATH));
  610. if (pszBlock == NULL)
  611. return E_OUTOFMEMORY;
  612. ZeroMemory(pszBlock, StrCbFromCch(4 * MAX_PATH));
  613. pszCurPos = pszBlock;
  614. nTotalLen = 0;
  615. nLen = countof(szImg);
  616. while (SUCCEEDED(hr = findImgSrc(&pszCurHtml, szImg, &nLen))) {
  617. // S_FALSE indicates an img with no simple SRC
  618. if (PathIsURL(szImg) || PathIsFullPath(szImg) || S_FALSE == hr)
  619. continue;
  620. if (StrCbFromCch(nLen+1 + nTotalLen+1) > CoTaskMemSize(pszBlock)) {
  621. pszNewBlock = (LPTSTR)CoTaskMemRealloc(pszBlock, StrCbFromCch(nTotalLen+1 + nLen+1 + 2*MAX_PATH));
  622. if (pszNewBlock == NULL) {
  623. CoTaskMemFree(pszBlock);
  624. return E_OUTOFMEMORY;
  625. }
  626. ZeroMemory(pszNewBlock + nTotalLen, StrCbFromCch(1 + nLen+1 + 2*MAX_PATH));
  627. pszBlock = pszNewBlock;
  628. pszCurPos = pszBlock + nTotalLen;
  629. }
  630. StrCpy(pszCurPos, szImg);
  631. nTotalLen += nLen + 1;
  632. pszCurPos += nLen + 1;
  633. nLen = countof(szImg);
  634. }
  635. if (nTotalLen > 0) {
  636. if (StrCbFromCch(nTotalLen+1) < CoTaskMemSize(pszBlock)) {
  637. pszNewBlock = (LPTSTR)CoTaskMemRealloc(pszBlock, StrCbFromCch(nTotalLen+1));
  638. if (pszNewBlock != NULL && pszNewBlock != pszBlock)
  639. pszBlock = pszNewBlock;
  640. }
  641. *ppszList = pszBlock;
  642. }
  643. else
  644. CoTaskMemFree(pszBlock);
  645. return S_OK;
  646. }