Source code of Windows XP (NT5)
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.

306 lines
7.6 KiB

  1. // Copyright 1997 Microsoft Corporation. All Rights Reserved.
  2. #include "header.h"
  3. #include "fsclient.h"
  4. #include "sitemap.h"
  5. static const UINT CSTREAM_BUF_SIZE = (4 * 1024);
  6. CFSClient::CFSClient()
  7. {
  8. ClearMemory(this, sizeof(CFSClient));
  9. }
  10. CFSClient::CFSClient(CFileSystem* pFS, PCSTR pszSubFile)
  11. {
  12. ClearMemory(this, sizeof(CFSClient));
  13. m_pFS = pFS;
  14. m_fNoDeleteFS = TRUE;
  15. OpenStream(pszSubFile);
  16. }
  17. CFSClient::~CFSClient()
  18. {
  19. if (m_pSubFS)
  20. delete m_pSubFS;
  21. if (m_pFS && !m_fNoDeleteFS)
  22. delete m_pFS;
  23. if (m_pbuf)
  24. lcFree(m_pbuf);
  25. }
  26. BOOL CFSClient::Initialize(PCSTR pszCompiledFile)
  27. {
  28. CStr cszCompiledFile;
  29. PCSTR pszFilePortion = GetCompiledName(pszCompiledFile, &cszCompiledFile);
  30. ASSERT(cszCompiledFile.IsNonEmpty());
  31. ASSERT(!m_pFS);
  32. m_pFS = new CFileSystem;
  33. if (! SUCCEEDED(m_pFS->Init()) )
  34. return FALSE;
  35. if ( !SUCCEEDED(m_pFS->Open((PSTR)cszCompiledFile)) )
  36. {
  37. delete m_pFS;
  38. m_pFS = NULL;
  39. return FALSE;
  40. }
  41. if (pszFilePortion)
  42. return SUCCEEDED(OpenStream(pszFilePortion));
  43. return TRUE;
  44. }
  45. HRESULT CFSClient::OpenStream(PCSTR pszFile, DWORD dwAccess)
  46. {
  47. HRESULT hr;
  48. ASSERT(m_pFS);
  49. if (! m_pFS )
  50. return E_FAIL;
  51. m_pSubFS = new CSubFileSystem(m_pFS);
  52. PSTR pszFileCopy = _strdup(pszFile);
  53. ReplaceEscapes(pszFile, pszFileCopy, ESCAPE_URL);
  54. if (! SUCCEEDED(hr = m_pSubFS->OpenSub(pszFileCopy, dwAccess)) )
  55. {
  56. delete m_pSubFS;
  57. m_pSubFS = NULL;
  58. }
  59. free(pszFileCopy);
  60. return hr;
  61. }
  62. void CFSClient::WriteStorageContents(PCSTR pszRootFolder, OLECHAR* wszFSName)
  63. {
  64. IStorage* pStorage;
  65. HRESULT hr;
  66. BOOL fDoRelease = FALSE;
  67. if (! m_pFS )
  68. return;
  69. if (wszFSName != NULL)
  70. {
  71. IStorage* pStorage2 = m_pFS->GetITStorageDocObj();
  72. HRESULT hr = pStorage2->OpenStorage(wszFSName, NULL, STGM_READ, NULL, 0, &pStorage);
  73. if (!SUCCEEDED(hr))
  74. {
  75. DEBUG_ReportOleError(hr);
  76. return;
  77. }
  78. fDoRelease = TRUE;
  79. }
  80. else
  81. pStorage = m_pFS->GetITStorageDocObj();
  82. IEnumSTATSTG* pEnum;
  83. hr = pStorage->EnumElements(0, NULL, 0, &pEnum);
  84. if (!SUCCEEDED(hr)) {
  85. DEBUG_ReportOleError(hr);
  86. return;
  87. }
  88. STATSTG Stat;
  89. if (GetFileAttributes(pszRootFolder) == HFILE_ERROR) {
  90. // Only ask about creating the root folder
  91. if (!CreateFolder(pszRootFolder))
  92. return;
  93. }
  94. while (GetElementStat(pEnum, &Stat)) {
  95. char szFullPath[MAX_PATH];
  96. CStr cszName(Stat.pwcsName); // convert to Multi-Byte
  97. CoTaskMemFree(GetStatName());
  98. if (cszName.psz[0] == '#' || cszName.psz[0] == '$') {
  99. continue; // we don't decompile system files
  100. }
  101. if (Stat.type == STGTY_STORAGE) {
  102. strcpy(szFullPath, pszRootFolder);
  103. AddTrailingBackslash(szFullPath);
  104. strcat(szFullPath, cszName);
  105. WCHAR wszTemp[MAX_PATH];
  106. wszTemp[0] = NULL;
  107. if (wszFSName)
  108. {
  109. lstrcpyW(wszTemp,wszFSName);
  110. lstrcatW(wszTemp, L"\\");
  111. }
  112. lstrcatW(wszTemp, Stat.pwcsName);
  113. WriteStorageContents(szFullPath, wszTemp);
  114. }
  115. else {
  116. strcpy(szFullPath, pszRootFolder);
  117. AddTrailingBackslash(szFullPath);
  118. strcat(szFullPath, cszName);
  119. HANDLE hf = CreateFile(szFullPath, GENERIC_WRITE, 0,
  120. NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  121. if (hf == INVALID_HANDLE_VALUE)
  122. continue;
  123. CMem mem(Stat.cbSize.LowPart);
  124. ULONG cbRead;
  125. if (wszFSName) {
  126. CStr cszFsName(wszFSName);
  127. strcpy(szFullPath, cszFsName);
  128. AddTrailingBackslash(szFullPath);
  129. strcat(szFullPath, cszName);
  130. cszName = szFullPath;
  131. }
  132. hr = OpenStream(cszName);
  133. if (SUCCEEDED(hr)) {
  134. hr = Read(mem, Stat.cbSize.LowPart, &cbRead);
  135. DWORD cbWritten;
  136. if (SUCCEEDED(hr))
  137. WriteFile(hf, mem, cbRead, &cbWritten, NULL);
  138. CloseStream();
  139. }
  140. CloseHandle(hf);
  141. if (!SUCCEEDED(hr))
  142. DeleteFile(szFullPath);
  143. }
  144. }
  145. ReleaseObjPtr(pEnum);
  146. if ( fDoRelease )
  147. ReleaseObjPtr(pStorage);
  148. }
  149. ULONG CFSClient::GetElementStat(ULONG nNumber, STATSTG* stat, IEnumSTATSTG* pEnum)
  150. {
  151. ULONG nReturned = 0;
  152. HRESULT hr;
  153. if (pEnum == NULL) {
  154. if (m_pEnum) {
  155. hr = m_pEnum->Next(nNumber, stat, &nReturned);
  156. }
  157. else
  158. hr = S_FALSE;
  159. }
  160. else {
  161. hr = pEnum->Next(nNumber, stat, &nReturned);
  162. }
  163. return (SUCCEEDED(hr) ? nReturned : 0);
  164. }
  165. HRESULT CFSClient::Read(void* pDst, const ULONG cbRead, ULONG* pcbRead)
  166. {
  167. ASSERT(m_pFS);
  168. ASSERT(m_pSubFS);
  169. if (m_cbBuf) { // we've streamed it
  170. *pcbRead = Read((PBYTE) pDst, cbRead);
  171. return S_OK;
  172. }
  173. else
  174. return m_pSubFS->ReadSub(pDst, cbRead, pcbRead);
  175. }
  176. ULONG CFSClient::Read(PBYTE pbDest, ULONG cbBytes)
  177. {
  178. if (!m_cbBuf)
  179. ReadBuf();
  180. if (m_pEndBuf - m_pbuf < m_cbBuf) { // adjust cbBytes for actual remaining size
  181. if (m_pEndBuf - m_pCurBuf < (int) cbBytes)
  182. cbBytes = (ULONG)(m_pEndBuf - m_pCurBuf);
  183. }
  184. if (m_pCurBuf + cbBytes < m_pEndBuf) {
  185. memcpy(pbDest, m_pCurBuf, cbBytes);
  186. m_pCurBuf += cbBytes;
  187. return cbBytes;
  188. }
  189. PBYTE pbDst = (PBYTE) pbDest;
  190. // If destination buffer is larger then our internal buffer, then
  191. // recursively call until we have filled up the destination.
  192. int cbRead = (int)(m_pEndBuf - m_pCurBuf);
  193. memcpy(pbDest, m_pCurBuf, cbRead);
  194. pbDst += cbRead;
  195. if (!m_fEndOfFile)
  196. ReadBuf();
  197. if (m_fEndOfFile)
  198. return cbRead;
  199. return Read(pbDst, cbBytes - cbRead) + cbRead;
  200. }
  201. void CFSClient::ReadBuf(void)
  202. {
  203. ULONG cRead;
  204. if (!m_cbBuf) {
  205. m_cbBuf = CSTREAM_BUF_SIZE; // use constant in case we pull in read-ahead code from CStream
  206. // +2 because we add a zero just past the buffer in case anyone expects strings
  207. m_pbuf = (PBYTE) lcMalloc(CSTREAM_BUF_SIZE);
  208. m_pSubFS->ReadSub(m_pbuf, m_cbBuf, &cRead);
  209. m_pCurBuf = m_pbuf;
  210. m_pEndBuf = m_pbuf + cRead;
  211. m_lFilePos = cRead;
  212. m_lFileBuf = 0;
  213. return;
  214. }
  215. m_pSubFS->ReadSub(m_pbuf, m_cbBuf, &cRead);
  216. m_lFileBuf = m_lFilePos;
  217. m_lFilePos += cRead;
  218. m_pCurBuf = m_pbuf;
  219. m_pEndBuf = m_pbuf + cRead;
  220. if (!cRead)
  221. m_fEndOfFile = TRUE;
  222. }
  223. HRESULT CFSClient::seek(int pos, SEEK_TYPE seek)
  224. {
  225. ASSERT(seek != SK_END); // we don't support this one
  226. if (seek == SK_CUR) // convert to SEEK_SET equivalent
  227. pos = m_lFileBuf + (int)(m_pCurBuf - m_pbuf) + pos;
  228. if (pos >= m_lFileBuf && pos < m_lFilePos) {
  229. m_pCurBuf = m_pbuf + (pos - m_lFileBuf);
  230. if (m_pCurBuf >= m_pEndBuf && m_pEndBuf < m_pbuf + m_cbBuf)
  231. m_fEndOfFile = TRUE;
  232. return S_OK;
  233. }
  234. else {
  235. m_lFileBuf = m_pSubFS->SeekSub(pos, SK_SET);
  236. ULONG cread;
  237. if (FAILED(m_pSubFS->ReadSub(m_pbuf, m_cbBuf, &cread))) {
  238. m_fEndOfFile = TRUE;
  239. return STG_E_READFAULT;
  240. }
  241. m_lFilePos = m_lFileBuf + cread;
  242. m_pCurBuf = m_pbuf;
  243. m_pEndBuf = m_pbuf + cread;
  244. if (cread == 0)
  245. m_fEndOfFile = TRUE;
  246. return S_OK;
  247. }
  248. }
  249. void CFSClient::CloseStream(void)
  250. {
  251. if (m_pSubFS) {
  252. delete m_pSubFS;
  253. m_pSubFS = NULL;
  254. }
  255. if (m_pbuf) {
  256. lcFree(m_pbuf);
  257. m_pbuf = NULL;
  258. m_cbBuf = 0;
  259. }
  260. }