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.

659 lines
16 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: filelkb.cxx
  7. //
  8. // Contents: File ILockBytes implementation for async storage
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 19-Dec-95 PhilipLa Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "astghead.cxx"
  18. #pragma hdrstop
  19. #include "filelkb.hxx"
  20. #include <valid.h>
  21. #define WIN32_SCODE(err) HRESULT_FROM_WIN32(err)
  22. #define LAST_STG_SCODE Win32ErrorToScode(GetLastError())
  23. #define boolChk(e) \
  24. if (!(e)) astgErr(Err, LAST_STG_SCODE) else 1
  25. #define boolChkTo(l, e) \
  26. if (!(e)) astgErr(l, LAST_STG_SCODE) else 1
  27. #define negChk(e) \
  28. if ((e) == 0xffffffff) astgErr(Err, LAST_STG_SCODE) else 1
  29. #define negChkTo(l, e) \
  30. if ((e) == 0xffffffff) astgErr(l, LAST_STG_SCODE) else 1
  31. class CSafeCriticalSection
  32. {
  33. public:
  34. inline CSafeCriticalSection(CRITICAL_SECTION *pcs);
  35. inline ~CSafeCriticalSection();
  36. private:
  37. CRITICAL_SECTION *_pcs;
  38. };
  39. inline CSafeCriticalSection::CSafeCriticalSection(CRITICAL_SECTION *pcs)
  40. {
  41. _pcs = pcs;
  42. EnterCriticalSection(_pcs);
  43. }
  44. inline CSafeCriticalSection::~CSafeCriticalSection()
  45. {
  46. LeaveCriticalSection(_pcs);
  47. #if DBG == 1
  48. _pcs = NULL;
  49. #endif
  50. }
  51. #define TAKE_CS CSafeCriticalSection scs(&_cs);
  52. //+---------------------------------------------------------------------------
  53. //
  54. // Function: Win32ErrorToScode, public
  55. //
  56. // Synopsis: Map a Win32 error into a corresponding scode, remapping
  57. // into Facility_Storage if appropriate.
  58. //
  59. // Arguments: [dwErr] -- Win32 error to map
  60. //
  61. // Returns: Appropriate scode
  62. //
  63. // History: 22-Sep-93 PhilipLa Created
  64. //
  65. //----------------------------------------------------------------------------
  66. SCODE Win32ErrorToScode(DWORD dwErr)
  67. {
  68. astgAssert((dwErr != NO_ERROR) &&
  69. "Win32ErrorToScode called on NO_ERROR");
  70. SCODE sc = STG_E_UNKNOWN;
  71. switch (dwErr)
  72. {
  73. case ERROR_INVALID_FUNCTION:
  74. sc = STG_E_INVALIDFUNCTION;
  75. break;
  76. case ERROR_FILE_NOT_FOUND:
  77. sc = STG_E_FILENOTFOUND;
  78. break;
  79. case ERROR_PATH_NOT_FOUND:
  80. sc = STG_E_PATHNOTFOUND;
  81. break;
  82. case ERROR_TOO_MANY_OPEN_FILES:
  83. sc = STG_E_TOOMANYOPENFILES;
  84. break;
  85. case ERROR_ACCESS_DENIED:
  86. case ERROR_NETWORK_ACCESS_DENIED:
  87. sc = STG_E_ACCESSDENIED;
  88. break;
  89. case ERROR_INVALID_HANDLE:
  90. sc = STG_E_INVALIDHANDLE;
  91. break;
  92. case ERROR_NOT_ENOUGH_MEMORY:
  93. sc = STG_E_INSUFFICIENTMEMORY;
  94. break;
  95. case ERROR_NO_MORE_FILES:
  96. sc = STG_E_NOMOREFILES;
  97. break;
  98. case ERROR_WRITE_PROTECT:
  99. sc = STG_E_DISKISWRITEPROTECTED;
  100. break;
  101. case ERROR_SEEK:
  102. sc = STG_E_SEEKERROR;
  103. break;
  104. case ERROR_WRITE_FAULT:
  105. sc = STG_E_WRITEFAULT;
  106. break;
  107. case ERROR_READ_FAULT:
  108. sc = STG_E_READFAULT;
  109. break;
  110. case ERROR_SHARING_VIOLATION:
  111. sc = STG_E_SHAREVIOLATION;
  112. break;
  113. case ERROR_LOCK_VIOLATION:
  114. sc = STG_E_LOCKVIOLATION;
  115. break;
  116. case ERROR_HANDLE_DISK_FULL:
  117. case ERROR_DISK_FULL:
  118. sc = STG_E_MEDIUMFULL;
  119. break;
  120. case ERROR_FILE_EXISTS:
  121. case ERROR_ALREADY_EXISTS:
  122. sc = STG_E_FILEALREADYEXISTS;
  123. break;
  124. case ERROR_INVALID_PARAMETER:
  125. sc = STG_E_INVALIDPARAMETER;
  126. break;
  127. case ERROR_INVALID_NAME:
  128. case ERROR_BAD_PATHNAME:
  129. case ERROR_FILENAME_EXCED_RANGE:
  130. sc = STG_E_INVALIDNAME;
  131. break;
  132. case ERROR_INVALID_FLAGS:
  133. sc = STG_E_INVALIDFLAG;
  134. break;
  135. default:
  136. sc = WIN32_SCODE(dwErr);
  137. break;
  138. }
  139. return sc;
  140. }
  141. //+---------------------------------------------------------------------------
  142. //
  143. // Member: CFileLockBytes::CFileLockBytes, public
  144. //
  145. // Synopsis: Default constructor
  146. //
  147. // Arguments:
  148. //
  149. // Returns: Appropriate status code
  150. //
  151. // Modifies:
  152. //
  153. // History: 28-Dec-95 PhilipLa Created
  154. //
  155. // Notes:
  156. //
  157. //----------------------------------------------------------------------------
  158. CFileLockBytes::CFileLockBytes(void)
  159. {
  160. _cReferences = 1;
  161. _h = INVALID_HANDLE_VALUE;
  162. InitializeCriticalSection(&_cs);
  163. }
  164. //+---------------------------------------------------------------------------
  165. //
  166. // Member: CFileLockBytes::~CFileLockBytes, public
  167. //
  168. // Synopsis: Destructor
  169. //
  170. // Returns: Appropriate status code
  171. //
  172. // History: 28-Dec-95 PhilipLa Created
  173. //
  174. //----------------------------------------------------------------------------
  175. CFileLockBytes::~CFileLockBytes()
  176. {
  177. if (_h != INVALID_HANDLE_VALUE)
  178. {
  179. CloseHandle(_h);
  180. }
  181. DeleteCriticalSection(&_cs);
  182. }
  183. //+---------------------------------------------------------------------------
  184. //
  185. // Member: CFileLockBytes::Init, public
  186. //
  187. // Synopsis: Initialization function
  188. //
  189. // Arguments:
  190. //
  191. // Returns: Appropriate status code
  192. //
  193. // History: 28-Dec-95 PhilipLa Created
  194. //
  195. // Notes:
  196. //
  197. //----------------------------------------------------------------------------
  198. SCODE CFileLockBytes::Init(OLECHAR const *pwcsName)
  199. {
  200. astgDebugOut((DEB_ITRACE, "In CFileLockBytes::Init:%p()\n", this));
  201. #ifndef UNICODE
  202. TCHAR atcPath[_MAX_PATH + 1];
  203. UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  204. if (!WideCharToMultiByte(
  205. uCodePage,
  206. 0,
  207. pwcsName,
  208. -1,
  209. atcPath,
  210. _MAX_PATH + 1,
  211. NULL,
  212. NULL))
  213. {
  214. return STG_E_INVALIDNAME;
  215. }
  216. _h = CreateFileA(atcPath,
  217. GENERIC_READ | GENERIC_WRITE, //Read-write
  218. 0, // No sharing
  219. NULL,
  220. CREATE_NEW, //Create if necessary
  221. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
  222. NULL);
  223. #else
  224. _h = CreateFile(pwcsName,
  225. GENERIC_READ | GENERIC_WRITE, //Read-write
  226. 0, // No sharing
  227. NULL,
  228. CREATE_NEW, //Create if necessary
  229. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
  230. NULL);
  231. #endif
  232. if (_h == INVALID_HANDLE_VALUE)
  233. {
  234. return LAST_STG_SCODE;
  235. }
  236. wcscpy(_acName, pwcsName);
  237. astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::Init\n"));
  238. return S_OK;
  239. }
  240. //+--------------------------------------------------------------
  241. //
  242. // Member: CFileLockBytes::QueryInterface, public
  243. //
  244. // Synopsis: Returns an object for the requested interface
  245. //
  246. // Arguments: [iid] - Interface ID
  247. // [ppvObj] - Object return
  248. //
  249. // Returns: Appropriate status code
  250. //
  251. // Modifies: [ppvObj]
  252. //
  253. // History: 26-Mar-92 DrewB Created
  254. //
  255. //---------------------------------------------------------------
  256. STDMETHODIMP CFileLockBytes::QueryInterface(REFIID iid, void **ppvObj)
  257. {
  258. TAKE_CS;
  259. SCODE sc;
  260. astgDebugOut((DEB_ITRACE, "In CFileLockBytes::QueryInterface(?, %p)\n",
  261. ppvObj));
  262. astgChk(ValidateOutPtrBuffer(ppvObj));
  263. *ppvObj = NULL;
  264. sc = S_OK;
  265. if (IsEqualIID(iid, IID_IUnknown))
  266. {
  267. *ppvObj = (IUnknown *)this;
  268. CFileLockBytes::AddRef();
  269. }
  270. else if (IsEqualIID(iid, IID_ILockBytes))
  271. {
  272. *ppvObj = (ILockBytes *)this;
  273. CFileLockBytes::AddRef();
  274. }
  275. else
  276. {
  277. sc = E_NOINTERFACE;
  278. }
  279. astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::QueryInterface => %p\n",
  280. ppvObj));
  281. Err:
  282. return ResultFromScode(sc);
  283. }
  284. //+--------------------------------------------------------------
  285. //
  286. // Member: CFileLockBytes::AddRef, public
  287. //
  288. // Synopsis: Increments the ref count
  289. //
  290. // Returns: Appropriate status code
  291. //
  292. // History: 16-Mar-92 DrewB Created
  293. //
  294. //---------------------------------------------------------------
  295. STDMETHODIMP_(ULONG) CFileLockBytes::AddRef(void)
  296. {
  297. ULONG ulRet;
  298. astgDebugOut((DEB_TRACE, "In CFileLockBytes::AddRef()\n"));
  299. InterlockedIncrement(&_cReferences);
  300. ulRet = _cReferences;
  301. astgDebugOut((DEB_TRACE, "Out CFileLockBytes::AddRef\n"));
  302. return ulRet;
  303. }
  304. //+---------------------------------------------------------------------------
  305. //
  306. // Member: CFileLockBytes::Release, public
  307. //
  308. // History: 28-Dec-95 PhilipLa Created
  309. //
  310. //----------------------------------------------------------------------------
  311. STDMETHODIMP_(ULONG) CFileLockBytes::Release(void)
  312. {
  313. LONG lRet;
  314. astgDebugOut((DEB_ITRACE, "In CFileLockBytes::Release:%p()\n", this));
  315. lRet = InterlockedDecrement(&_cReferences);
  316. if (lRet == 0)
  317. {
  318. delete this;
  319. }
  320. else if (lRet < 0)
  321. {
  322. lRet = 0;
  323. }
  324. astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::Release\n"));
  325. return lRet;
  326. }
  327. //+---------------------------------------------------------------------------
  328. //
  329. // Member: CFileLockBytes::ReadAt, public
  330. //
  331. // Synopsis:
  332. //
  333. // Arguments:
  334. //
  335. // Returns: Appropriate status code
  336. //
  337. // Modifies:
  338. //
  339. // History: 28-Dec-95 PhilipLa Created
  340. //
  341. // Notes:
  342. //
  343. //----------------------------------------------------------------------------
  344. STDMETHODIMP CFileLockBytes::ReadAt(ULARGE_INTEGER ulOffset,
  345. VOID HUGEP *pv,
  346. ULONG cb,
  347. ULONG *pcbRead)
  348. {
  349. TAKE_CS;
  350. SCODE sc = S_OK;
  351. astgDebugOut((DEB_ITRACE, "In CFileLockBytes::ReadAt:%p()\n", this));
  352. ULONG ulLow = ulOffset.LowPart;
  353. LONG lHigh = (LONG)ulOffset.HighPart;
  354. negChk(SetFilePointer(_h,
  355. ulLow,
  356. &lHigh,
  357. FILE_BEGIN));
  358. boolChk(ReadFile(_h, pv, cb, pcbRead, NULL));
  359. astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::ReadAt\n"));
  360. Err:
  361. return sc;
  362. }
  363. //+---------------------------------------------------------------------------
  364. //
  365. // Member: CFileLockBytes::WriteAt, public
  366. //
  367. // Synopsis:
  368. //
  369. // Arguments:
  370. //
  371. // Returns: Appropriate status code
  372. //
  373. // Modifies:
  374. //
  375. // History: 28-Dec-95 PhilipLa Created
  376. //
  377. // Notes:
  378. //
  379. //----------------------------------------------------------------------------
  380. STDMETHODIMP CFileLockBytes::WriteAt(ULARGE_INTEGER ulOffset,
  381. VOID const HUGEP *pv,
  382. ULONG cb,
  383. ULONG *pcbWritten)
  384. {
  385. TAKE_CS;
  386. SCODE sc = S_OK;
  387. astgDebugOut((DEB_ITRACE, "In CFileLockBytes::WriteAt:%p()\n", this));
  388. ULONG ulLow = ulOffset.LowPart;
  389. LONG lHigh = (LONG)ulOffset.HighPart;
  390. negChk(SetFilePointer(_h,
  391. ulLow,
  392. &lHigh,
  393. FILE_BEGIN));
  394. boolChk(WriteFile(_h, pv, cb, pcbWritten, NULL));
  395. astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::WriteAt\n"));
  396. Err:
  397. return sc;
  398. }
  399. //+---------------------------------------------------------------------------
  400. //
  401. // Member: CFileLockBytes::Flush, public
  402. //
  403. // Synopsis:
  404. //
  405. // Arguments:
  406. //
  407. // Returns: Appropriate status code
  408. //
  409. // Modifies:
  410. //
  411. // History: 28-Dec-95 PhilipLa Created
  412. //
  413. // Notes:
  414. //
  415. //----------------------------------------------------------------------------
  416. //BUGBUG: Implement something here?
  417. STDMETHODIMP CFileLockBytes::Flush(void)
  418. {
  419. TAKE_CS;
  420. astgDebugOut((DEB_ITRACE, "In CFileLockBytes::Flush:%p()\n", this));
  421. astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::Flush\n"));
  422. return S_OK;
  423. }
  424. //+---------------------------------------------------------------------------
  425. //
  426. // Member: CFileLockBytes::SetSize, public
  427. //
  428. // Synopsis:
  429. //
  430. // Arguments:
  431. //
  432. // Returns: Appropriate status code
  433. //
  434. // Modifies:
  435. //
  436. // History: 28-Dec-95 PhilipLa Created
  437. //
  438. // Notes:
  439. //
  440. //----------------------------------------------------------------------------
  441. STDMETHODIMP CFileLockBytes::SetSize(ULARGE_INTEGER cb)
  442. {
  443. TAKE_CS;
  444. SCODE sc = S_OK;
  445. astgDebugOut((DEB_ITRACE, "In CFileLockBytes::SetSize:%p()\n", this));
  446. LONG lHigh = (LONG)cb.HighPart;
  447. ULONG ulLow = cb.LowPart;
  448. negChk(SetFilePointer(_h, ulLow, &lHigh, FILE_BEGIN));
  449. boolChk(SetEndOfFile(_h));
  450. astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::SetSize\n"));
  451. Err:
  452. return sc;
  453. }
  454. //+---------------------------------------------------------------------------
  455. //
  456. // Member: CFileLockBytes::LockRegion, public
  457. //
  458. // Synopsis:
  459. //
  460. // Arguments:
  461. //
  462. // Returns: Appropriate status code
  463. //
  464. // Modifies:
  465. //
  466. // History: 28-Dec-95 PhilipLa Created
  467. //
  468. // Notes:
  469. //
  470. //----------------------------------------------------------------------------
  471. STDMETHODIMP CFileLockBytes::LockRegion(ULARGE_INTEGER libOffset,
  472. ULARGE_INTEGER cb,
  473. DWORD dwLockType)
  474. {
  475. TAKE_CS;
  476. SCODE sc = S_OK;
  477. astgDebugOut((DEB_ITRACE, "In CFileLockBytes::LockRegion:%p()\n", this));
  478. if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
  479. {
  480. return STG_E_INVALIDFUNCTION;
  481. }
  482. boolChk(LockFile(_h,
  483. libOffset.LowPart,
  484. libOffset.HighPart,
  485. cb.LowPart,
  486. cb.HighPart));
  487. astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::LockRegion\n"));
  488. Err:
  489. return sc;
  490. }
  491. //+---------------------------------------------------------------------------
  492. //
  493. // Member: CFileLockBytes::UnlockRegion, public
  494. //
  495. // Synopsis:
  496. //
  497. // Arguments:
  498. //
  499. // Returns: Appropriate status code
  500. //
  501. // Modifies:
  502. //
  503. // History: 28-Dec-95 PhilipLa Created
  504. //
  505. // Notes:
  506. //
  507. //----------------------------------------------------------------------------
  508. STDMETHODIMP CFileLockBytes::UnlockRegion(ULARGE_INTEGER libOffset,
  509. ULARGE_INTEGER cb,
  510. DWORD dwLockType)
  511. {
  512. TAKE_CS;
  513. SCODE sc = S_OK;
  514. astgDebugOut((DEB_ITRACE, "In CFileLockBytes::UnlockRegion:%p()\n", this));
  515. if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
  516. {
  517. return STG_E_INVALIDFUNCTION;
  518. }
  519. boolChk(UnlockFile(_h,
  520. libOffset.LowPart,
  521. libOffset.HighPart,
  522. cb.LowPart,
  523. cb.HighPart));
  524. astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::UnlockRegion\n"));
  525. Err:
  526. return sc;
  527. }
  528. //+---------------------------------------------------------------------------
  529. //
  530. // Member: CFIleLockBytes::Stat, public
  531. //
  532. // Synopsis:
  533. //
  534. // Arguments:
  535. //
  536. // Returns: Appropriate status code
  537. //
  538. // Modifies:
  539. //
  540. // History: 28-Dec-95 PhilipLa Created
  541. //
  542. // Notes:
  543. //
  544. //----------------------------------------------------------------------------
  545. STDMETHODIMP CFileLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  546. {
  547. TAKE_CS;
  548. SCODE sc;
  549. astgDebugOut((DEB_ITRACE, "In CFIleLockBytes::Stat:%p()\n", this));
  550. negChk(pstatstg->cbSize.LowPart =
  551. GetFileSize(_h, &pstatstg->cbSize.HighPart));
  552. boolChk(GetFileTime(_h, &pstatstg->ctime, &pstatstg->atime,
  553. &pstatstg->mtime));
  554. pstatstg->grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
  555. pstatstg->type = STGTY_LOCKBYTES;
  556. //BUGBUG: Set grfMode
  557. //pstatstg->grfMode = DFlagsToMode(_pgfst->GetDFlags());
  558. pstatstg->pwcsName = NULL;
  559. if ((grfStatFlag & STATFLAG_NONAME) == 0)
  560. {
  561. pstatstg->pwcsName = (OLECHAR *)CoTaskMemAlloc(
  562. (wcslen(_acName) + 1) * sizeof(OLECHAR));
  563. if (pstatstg->pwcsName == NULL)
  564. return STG_E_INSUFFICIENTMEMORY;
  565. wcscpy(pstatstg->pwcsName, _acName);
  566. }
  567. sc = S_OK;
  568. astgDebugOut((DEB_ITRACE, "Out CFIleLockBytes::Stat\n"));
  569. return NOERROR;
  570. Err:
  571. return sc;
  572. }