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.

484 lines
13 KiB

  1. // Copyright (C) 1997 Microsoft Corporation. All rights reserved.
  2. #include "header.h"
  3. #include "fs.h"
  4. static const WCHAR txtwUncompressed[] = L"uncompressed";
  5. CFileSystem::CFileSystem()
  6. {
  7. m_pITStorage = NULL;
  8. m_pStorage = NULL;
  9. m_szPathName[0] = 0;
  10. }
  11. CFileSystem::~CFileSystem()
  12. {
  13. ReleaseObjPtr(m_pStorage);
  14. ReleaseObjPtr(m_pITStorage);
  15. }
  16. HRESULT CFileSystem::Init(void)
  17. {
  18. if (! m_pITStorage) {
  19. IClassFactory* pICFITStorage;
  20. HRESULT hr = CoGetClassObject(CLSID_ITStorage, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void **) &pICFITStorage);
  21. if (!SUCCEEDED(hr))
  22. return hr;
  23. hr = pICFITStorage->CreateInstance(NULL, IID_ITStorage,(void **) &m_pITStorage);
  24. ReleaseObjPtr( pICFITStorage );
  25. if (!SUCCEEDED(hr))
  26. return hr;
  27. }
  28. return S_OK;
  29. }
  30. typedef struct tagITSControlData
  31. {
  32. UINT cdwFollowing; // Must be 6 or 13
  33. DWORD cdwITFS_Control; // Must be 5
  34. DWORD dwMagicITS; // Must be MAGIC_ITSFS_CONTROL (see below)
  35. DWORD dwVersionITS; // Must be 1
  36. DWORD cbDirectoryBlock; // Size in bytes of directory blocks (Default is 8192)
  37. DWORD cMinCacheEntries; // Least upper bound on the number of directory blocks
  38. // which we'll cache in memory. (Default is 20)
  39. DWORD fFlags; // Control bit flags (see below).
  40. // Default value is fDefaultIsCompression.
  41. UINT cdwControlData; // Must be 6
  42. DWORD dwLZXMagic; // Must be LZX_MAGIC (see below)
  43. DWORD dwVersion; // Must be 2
  44. DWORD dwMulResetBlock; // Number of blocks between compression resets. (Default: 4)
  45. DWORD dwMulWindowSize; // Maximum number of blocks kept in data history (Default: 4)
  46. DWORD dwMulSecondPartition; // Granularity in blocks of sliding history(Default: 2)
  47. DWORD dwOptions; // Option flags (Default: fOptimizeCodeStreams)
  48. } ITCD;
  49. HRESULT CFileSystem::Create( PCSTR pszPathName )
  50. {
  51. HRESULT hr;
  52. ITCD itcd;
  53. if (! m_pITStorage || m_pStorage )
  54. return E_FAIL;
  55. itcd.cdwFollowing = 13;
  56. itcd.cdwITFS_Control = 5;
  57. itcd.dwMagicITS = MAGIC_ITSFS_CONTROL;
  58. itcd.dwVersionITS = 1;
  59. itcd.cbDirectoryBlock = 4096; // default = 8192
  60. itcd.cMinCacheEntries = 10; // default = 20
  61. itcd.fFlags = 1; // 0 == Uncompressed, 1 == Compressed.
  62. itcd.cdwControlData = 6;
  63. itcd.dwLZXMagic = LZX_MAGIC;
  64. itcd.dwVersion = 2;
  65. itcd.dwMulResetBlock = 2; // Default = 4
  66. itcd.dwMulWindowSize = 2; // Default = 4
  67. itcd.dwMulSecondPartition = 1; // Default = 2
  68. itcd.dwOptions = 0; // Default = fOptimizeCodeStreams
  69. m_pITStorage->SetControlData(PITS_Control_Data(&itcd));
  70. WCHAR wsz[MAX_PATH];
  71. MultiByteToWideChar(CP_ACP, 0, pszPathName, -1, (PWSTR) wsz, MAX_PATH);
  72. hr = m_pITStorage->StgCreateDocfile( (LPCWSTR) wsz, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &m_pStorage);
  73. if (!SUCCEEDED(hr)) {
  74. return hr;
  75. }
  76. strcpy( (LPSTR) m_szPathName, pszPathName );
  77. return S_OK;
  78. }
  79. // NOTE: The below function is required for the ITIR full-text indexer to
  80. // initialize. I'm working to find out why this is and what impact
  81. // the below has on the file system.
  82. //
  83. HRESULT CFileSystem::CreateUncompressed( PCSTR pszPathName )
  84. {
  85. HRESULT hr;
  86. ITCD itcd;
  87. if (! m_pITStorage || m_pStorage )
  88. return E_FAIL;
  89. itcd.cdwFollowing = 6;
  90. itcd.cdwITFS_Control = 5;
  91. itcd.dwMagicITS = MAGIC_ITSFS_CONTROL;
  92. itcd.dwVersionITS = 1;
  93. itcd.cbDirectoryBlock = 8192; // default = 8192
  94. itcd.cMinCacheEntries = 20; // default = 20
  95. itcd.fFlags = 0; // 0 == Uncompressed, 1 == Compressed.
  96. m_pITStorage->SetControlData(PITS_Control_Data(&itcd));
  97. WCHAR wsz[MAX_PATH];
  98. MultiByteToWideChar(CP_ACP, 0, pszPathName, -1, (PWSTR) wsz, MAX_PATH);
  99. hr = m_pITStorage->StgCreateDocfile( (LPCWSTR) wsz, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &m_pStorage);
  100. if (!SUCCEEDED(hr)) {
  101. return hr;
  102. }
  103. strcpy( (LPSTR) m_szPathName, pszPathName );
  104. return S_OK;
  105. }
  106. HRESULT CFileSystem::Open(PCSTR pszPathName, DWORD dwAccess)
  107. {
  108. HRESULT hr = S_OK;
  109. if (! m_pITStorage || m_pStorage )
  110. return E_FAIL;
  111. // force access modes
  112. if( (dwAccess & STGM_WRITE) || (dwAccess & STGM_READWRITE) ) {
  113. dwAccess &= ~STGM_WRITE;
  114. dwAccess |= STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
  115. }
  116. else
  117. dwAccess |= STGM_SHARE_DENY_WRITE;
  118. WCHAR wsz[MAX_PATH];
  119. MultiByteToWideChar(CP_ACP, 0, pszPathName, -1, (PWSTR) wsz, MAX_PATH);
  120. hr = m_pITStorage->StgOpenStorage( (LPCWSTR) wsz, NULL, dwAccess, NULL, 0, &m_pStorage);
  121. if (!SUCCEEDED(hr)) {
  122. return hr;
  123. }
  124. strcpy( (LPSTR) m_szPathName, pszPathName );
  125. return hr;
  126. }
  127. HRESULT CFileSystem::Compact(LPCSTR pszPathName)
  128. {
  129. WCHAR wszPathName[MAX_PATH];
  130. MultiByteToWideChar(CP_ACP, 0, pszPathName, -1, wszPathName, sizeof(wszPathName));
  131. m_pITStorage->Compact(wszPathName, COMPACT_DATA_AND_PATH);
  132. return S_OK;
  133. }
  134. HRESULT CFileSystem::Close()
  135. {
  136. ReleaseObjPtr(m_pStorage);
  137. return S_OK;
  138. }
  139. //////////////////////////////////////////////////////////////////////////////////////////////
  140. //
  141. // Here are a set of "sub" file I/O calls.
  142. //
  143. //
  144. CSubFileSystem::CSubFileSystem(CFileSystem* pFS)
  145. {
  146. m_pFS = pFS;
  147. m_pStorage = NULL;
  148. m_pStream = NULL;
  149. m_szPathName[0] = 0;
  150. }
  151. CSubFileSystem::~CSubFileSystem()
  152. {
  153. if ( m_pStorage && (m_pStorage != m_pFS->m_pStorage) )
  154. ReleaseObjPtr(m_pStorage);
  155. ReleaseObjPtr(m_pStream);
  156. }
  157. HRESULT CSubFileSystem::CreateSub(PCSTR pszPathName)
  158. {
  159. PCSTR pszFilePortion;
  160. HRESULT hr;
  161. if ( m_pStorage || m_pStream )
  162. return E_FAIL;
  163. if ((pszFilePortion = FindFilePortion(pszPathName)) && pszFilePortion > pszPathName)
  164. {
  165. CHAR szPath[MAX_PATH];
  166. strcpy( szPath, pszPathName );
  167. szPath[(pszFilePortion - 1) - pszPathName] = '\0';
  168. WCHAR wszStorage[MAX_PATH];
  169. MultiByteToWideChar(CP_ACP, 0, szPath, -1, (PWSTR) wszStorage, MAX_PATH);
  170. hr = m_pFS->m_pStorage->OpenStorage(wszStorage, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &m_pStorage);
  171. if (!SUCCEEDED(hr) || !m_pStorage) // storage didn't exist, so create it
  172. hr = m_pFS->m_pStorage->CreateStorage(wszStorage, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &m_pStorage);
  173. if (!SUCCEEDED(hr))
  174. {
  175. return hr;
  176. }
  177. }
  178. else // no folder, so store the file in the root
  179. {
  180. m_pStorage = m_pFS->m_pStorage;
  181. pszFilePortion = pszPathName;
  182. }
  183. WCHAR wszStream[MAX_PATH];
  184. MultiByteToWideChar(CP_ACP, 0, pszFilePortion, -1, (PWSTR) wszStream, MAX_PATH);
  185. hr = m_pStorage->CreateStream(wszStream, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &m_pStream);
  186. if (!SUCCEEDED(hr))
  187. {
  188. if (m_pStorage != m_pFS->m_pStorage)
  189. ReleaseObjPtr(m_pStorage);
  190. return hr;
  191. }
  192. // Needed for delete.
  193. strcpy( m_szPathName, pszFilePortion );
  194. return S_OK;
  195. }
  196. HRESULT CSubFileSystem::CreateUncompressedSub(PCSTR pszPathName)
  197. {
  198. PCSTR pszFilePortion;
  199. HRESULT hr;
  200. IStorageITEx* pIStorageEx;
  201. if ( m_pStorage || m_pStream )
  202. return E_FAIL;
  203. if ((pszFilePortion = FindFilePortion(pszPathName)) && pszFilePortion > pszPathName)
  204. {
  205. CHAR szPath[MAX_PATH];
  206. strcpy( szPath, pszPathName );
  207. szPath[(pszFilePortion - 1) - pszPathName] = '\0';
  208. WCHAR wszStorage[MAX_PATH];
  209. MultiByteToWideChar(CP_ACP, 0, szPath, -1, (PWSTR) wszStorage, MAX_PATH);
  210. hr = m_pFS->m_pStorage->OpenStorage(wszStorage, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &m_pStorage);
  211. if (!SUCCEEDED(hr) || !m_pStorage) // storage didn't exist, so create it
  212. hr = m_pFS->m_pStorage->CreateStorage(wszStorage, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &m_pStorage);
  213. if (!SUCCEEDED(hr))
  214. {
  215. return hr;
  216. }
  217. }
  218. else // no folder, so store the file in the root
  219. {
  220. m_pStorage = m_pFS->m_pStorage;
  221. pszFilePortion = pszPathName;
  222. }
  223. if ( !(SUCCEEDED(hr = m_pStorage->QueryInterface(IID_IStorageITEx, (void**)&pIStorageEx))) )
  224. pIStorageEx = (IStorageITEx*)m_pStorage; // BUGBUG the QI call above should work!
  225. WCHAR wszStream[MAX_PATH];
  226. MultiByteToWideChar(CP_ACP, 0, pszFilePortion, -1, (PWSTR) wszStream, MAX_PATH);
  227. hr = pIStorageEx->CreateStreamITEx(wszStream, txtwUncompressed, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, (IStreamITEx**)&m_pStream);
  228. ReleaseObjPtr(pIStorageEx);
  229. if (!SUCCEEDED(hr))
  230. {
  231. if (m_pStorage != m_pFS->m_pStorage)
  232. ReleaseObjPtr(m_pStorage);
  233. return hr;
  234. }
  235. // Needed for delete.
  236. strcpy( m_szPathName, pszFilePortion );
  237. return S_OK;
  238. }
  239. HRESULT CSubFileSystem::CreateSystemFile(PCSTR pszPathName)
  240. {
  241. m_pStorage = m_pFS->m_pStorage;
  242. WCHAR wszStream[MAX_PATH];
  243. MultiByteToWideChar(CP_ACP, 0, pszPathName, -1, (PWSTR) wszStream, MAX_PATH);
  244. HRESULT hr = m_pStorage->CreateStream(wszStream, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &m_pStream);
  245. if (!SUCCEEDED(hr))
  246. {
  247. return hr;
  248. }
  249. // Needed for delete.
  250. strcpy( m_szPathName, pszPathName );
  251. return S_OK;
  252. }
  253. HRESULT CSubFileSystem::CreateUncompressedSystemFile(PCSTR pszPathName)
  254. {
  255. IStorageITEx* pIStorageEx;
  256. HRESULT hr;
  257. m_pStorage = m_pFS->m_pStorage;
  258. if ( !(SUCCEEDED(hr = m_pStorage->QueryInterface(IID_IStorageITEx, (void**)&pIStorageEx))) )
  259. pIStorageEx = (IStorageITEx*)m_pStorage; // BUGBUG the QI call above should work!
  260. WCHAR wszStream[MAX_PATH];
  261. MultiByteToWideChar(CP_ACP, 0, pszPathName, -1, (PWSTR) wszStream, MAX_PATH);
  262. hr = pIStorageEx->CreateStreamITEx(wszStream, txtwUncompressed, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, (IStreamITEx**)&m_pStream);
  263. ReleaseObjPtr(pIStorageEx);
  264. if (!SUCCEEDED(hr))
  265. {
  266. return hr;
  267. }
  268. // Needed for delete.
  269. strcpy( m_szPathName, pszPathName );
  270. return S_OK;
  271. }
  272. HRESULT CSubFileSystem::OpenSub(PCSTR pszPathName, DWORD dwAccess)
  273. {
  274. PCSTR pszFilePortion;
  275. HRESULT hr;
  276. if ( m_pStorage || m_pStream )
  277. return E_FAIL;
  278. // force access modes
  279. if( (dwAccess & STGM_WRITE) || (dwAccess & STGM_READWRITE) ) {
  280. dwAccess &= ~STGM_WRITE;
  281. dwAccess |= STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
  282. }
  283. else
  284. dwAccess |= STGM_SHARE_DENY_WRITE;
  285. if ((pszFilePortion = FindFilePortion(pszPathName)) &&
  286. pszFilePortion > pszPathName + 2) // +2 to support / && ./
  287. {
  288. CHAR szPath[MAX_PATH];
  289. strcpy( szPath, pszPathName );
  290. szPath[(pszFilePortion - 1) - pszPathName] = '\0';
  291. WCHAR wszStorage[MAX_PATH];
  292. MultiByteToWideChar(CP_ACP, 0, szPath, -1, (PWSTR) wszStorage, MAX_PATH);
  293. hr = m_pFS->m_pStorage->OpenStorage(wszStorage, NULL, dwAccess, NULL, 0, &m_pStorage);
  294. if (!SUCCEEDED(hr))
  295. {
  296. return hr;
  297. }
  298. }
  299. else // no folder, so store the file in the root
  300. {
  301. m_pStorage = m_pFS->m_pStorage ? m_pFS->m_pStorage : m_pFS->m_pStorage;
  302. pszFilePortion = pszPathName;
  303. }
  304. WCHAR wszStream[MAX_PATH];
  305. MultiByteToWideChar(CP_ACP, 0, pszFilePortion, -1, (PWSTR) wszStream, MAX_PATH);
  306. hr = m_pStorage->OpenStream(wszStream, NULL, dwAccess, 0, &m_pStream);
  307. if (!SUCCEEDED(hr))
  308. {
  309. if (m_pStorage != m_pFS->m_pStorage)
  310. ReleaseObjPtr(m_pStorage);
  311. return hr;
  312. }
  313. // Needed for delete.
  314. strcpy( m_szPathName, pszFilePortion );
  315. return S_OK;
  316. }
  317. ULONG CSubFileSystem::WriteSub(const void* pData, int cb)
  318. {
  319. if ( !m_pStorage || !m_pStream )
  320. return (ULONG) -1;
  321. ULONG cbWritten;
  322. HRESULT hr = m_pStream->Write(pData, cb, &cbWritten);
  323. if (!SUCCEEDED(hr) || (cbWritten != (ULONG)cb) )
  324. {
  325. return (ULONG) -1;
  326. }
  327. // REVIEW: 30-May-1997 [ralphw] Why are we returning this? We fail if
  328. // we don't write cb bytes.
  329. return cbWritten;
  330. }
  331. /*
  332. * iOrigin:
  333. * 0 = Seek from beginning.
  334. * 1 = Seek from current.
  335. * 2 = Seek from end.
  336. */
  337. ULONG CSubFileSystem::SeekSub(int cb, int iOrigin)
  338. {
  339. LARGE_INTEGER liCount = {0,0};
  340. ULARGE_INTEGER liNewPos;
  341. if ( !m_pStorage || !m_pStream )
  342. return (ULONG) -1;
  343. liCount.LowPart = cb;
  344. HRESULT hr = m_pStream->Seek(liCount, iOrigin, &liNewPos);
  345. if (!SUCCEEDED(hr) )
  346. {
  347. return (ULONG) -1;
  348. }
  349. return liNewPos.LowPart;
  350. }
  351. //
  352. // Pre-allocate the size of the stream.
  353. //
  354. HRESULT CSubFileSystem::SetSize(unsigned uSize)
  355. {
  356. ULARGE_INTEGER liSize = {0,0};
  357. HRESULT hr;
  358. if ( !m_pStorage || !m_pStream )
  359. return E_FAIL;
  360. liSize.LowPart = uSize;
  361. hr = m_pStream->SetSize(liSize);
  362. if (!SUCCEEDED(hr) )
  363. {
  364. return (ULONG) -1;
  365. }
  366. return hr;
  367. }
  368. //
  369. // Delete substorage.
  370. //
  371. HRESULT
  372. CSubFileSystem::DeleteSub()
  373. {
  374. if (m_pStorage)
  375. {
  376. if (m_pStream)
  377. {
  378. // Release the stream.
  379. ReleaseObjPtr(m_pStream) ;
  380. }
  381. // Now delete the storage.
  382. WCHAR element[MAX_PATH];
  383. MultiByteToWideChar(CP_ACP, 0, m_szPathName, -1, (PWSTR) element, MAX_PATH);
  384. HRESULT hr = m_pStorage->DestroyElement(element) ;
  385. if (SUCCEEDED(hr))
  386. {
  387. // Get back to the constructor state.
  388. if ( m_pStorage && (m_pStorage != m_pFS->m_pStorage) )
  389. {
  390. ReleaseObjPtr(m_pStorage);
  391. }
  392. return S_OK ;
  393. }
  394. }
  395. return S_OK ;
  396. }