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.

735 lines
20 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: funcs.cxx
  7. //
  8. // Contents: Generic DocFile support functions
  9. //
  10. // Functions: ModeToTFlags
  11. // CheckName
  12. // VerifyPerms
  13. //
  14. // History: 22-Jan-92 DrewB Created
  15. //
  16. //---------------------------------------------------------------
  17. #include <dfhead.cxx>
  18. #pragma hdrstop
  19. #include <df32.hxx>
  20. //+--------------------------------------------------------------
  21. //
  22. // Function: ModeToDFlags, private
  23. //
  24. // Synopsis: Translates STGM flags to DF flags
  25. //
  26. // Arguments: [dwModeFlags]
  27. //
  28. // Returns: DF_*
  29. //
  30. // History: 04-Feb-92 DrewB Created
  31. //
  32. //---------------------------------------------------------------
  33. DFLAGS ModeToDFlags(DWORD const dwModeFlags)
  34. {
  35. DFLAGS df;
  36. olDebugOut((DEB_ITRACE, "In ModeToDFlags(%lX)\n", dwModeFlags));
  37. if ((dwModeFlags & STGM_TRANSACTED) == 0)
  38. df = DF_DIRECT;
  39. else
  40. df = DF_TRANSACTED;
  41. if ((dwModeFlags & STGM_TRANSACTED) &&
  42. (dwModeFlags & STGM_PRIORITY) == 0 &&
  43. (dwModeFlags & STGM_DENY) != STGM_SHARE_DENY_WRITE &&
  44. (dwModeFlags & STGM_DENY) != STGM_SHARE_EXCLUSIVE)
  45. df |= DF_INDEPENDENT;
  46. switch(dwModeFlags & STGM_RDWR)
  47. {
  48. case STGM_READ:
  49. df |= DF_READ;
  50. break;
  51. case STGM_WRITE:
  52. df |= DF_WRITE;
  53. break;
  54. case STGM_READWRITE:
  55. df |= DF_READWRITE;
  56. break;
  57. default:
  58. olAssert(FALSE);
  59. break;
  60. }
  61. switch(dwModeFlags & STGM_DENY)
  62. {
  63. case STGM_SHARE_DENY_READ:
  64. df |= DF_DENYREAD;
  65. break;
  66. case STGM_SHARE_DENY_WRITE:
  67. df |= DF_DENYWRITE;
  68. break;
  69. case STGM_SHARE_EXCLUSIVE:
  70. df |= DF_DENYALL;
  71. break;
  72. // Default is deny none
  73. }
  74. if (dwModeFlags & STGM_PRIORITY)
  75. df |= DF_PRIORITY;
  76. #ifdef USE_NOSNAPSHOT_ALWAYS
  77. //This makes all transacted-writeable !deny-write instances no-snapshot,
  78. // for testing.
  79. if ((dwModeFlags & STGM_TRANSACTED) &&
  80. !(df & DF_DENYWRITE) &&
  81. (df & DF_WRITE))
  82. {
  83. df |= DF_NOSNAPSHOT;
  84. df &= ~DF_INDEPENDENT;
  85. }
  86. #else
  87. if (dwModeFlags & STGM_NOSNAPSHOT)
  88. {
  89. df |= DF_NOSNAPSHOT;
  90. df &= ~DF_INDEPENDENT;
  91. }
  92. #endif //USE_NOSNAPSHOT_ALWAYS
  93. #ifdef USE_NOSCRATCH_ALWAYS
  94. //This makes everything NOSCRATCH, for testing.
  95. if ((dwModeFlags & STGM_TRANSACTED) && (df & DF_WRITE))
  96. df |= DF_NOSCRATCH;
  97. #else
  98. if (dwModeFlags & STGM_NOSCRATCH)
  99. df |= DF_NOSCRATCH;
  100. #endif
  101. #if WIN32 == 300
  102. if (dwModeFlags & STGM_EDIT_ACCESS_RIGHTS)
  103. df |= DF_ACCESSCONTROL;
  104. #endif
  105. olDebugOut((DEB_ITRACE, "Out ModeToDFlags => %lX\n", df));
  106. return df;
  107. }
  108. //+--------------------------------------------------------------
  109. //
  110. // Function: DFlagsToMode, private
  111. //
  112. // Synopsis: Converts the read/write/denials/transacted/priority
  113. // to STGM flags
  114. //
  115. // Arguments: [df] - DFlags
  116. //
  117. // Returns: STGM flags
  118. //
  119. // History: 24-Jul-92 DrewB Created
  120. //
  121. //---------------------------------------------------------------
  122. DWORD DFlagsToMode(DFLAGS const df)
  123. {
  124. DWORD dwMode = 0;
  125. olDebugOut((DEB_ITRACE, "In DFlagsToMode(%X)\n", df));
  126. if (P_READ(df))
  127. if (P_WRITE(df))
  128. dwMode = STGM_READWRITE;
  129. else
  130. dwMode = STGM_READ;
  131. else if (P_WRITE(df))
  132. dwMode = STGM_WRITE;
  133. // Must have either read or write, so no else
  134. if (P_DENYREAD(df))
  135. if (P_DENYWRITE(df))
  136. dwMode |= STGM_SHARE_EXCLUSIVE;
  137. else
  138. dwMode |= STGM_SHARE_DENY_READ;
  139. else if (P_DENYWRITE(df))
  140. dwMode |= STGM_SHARE_DENY_WRITE;
  141. else
  142. dwMode |= STGM_SHARE_DENY_NONE;
  143. if (P_TRANSACTED(df))
  144. dwMode |= STGM_TRANSACTED;
  145. if (P_PRIORITY(df))
  146. dwMode |= STGM_PRIORITY;
  147. if (P_NOSCRATCH(df))
  148. dwMode |= STGM_NOSCRATCH;
  149. if (P_NOSNAPSHOT(df))
  150. dwMode |= STGM_NOSNAPSHOT;
  151. olDebugOut((DEB_ITRACE, "Out DFlagsToMode\n"));
  152. return dwMode;
  153. }
  154. //+--------------------------------------------------------------
  155. //
  156. // Function: VerifyPerms, private
  157. //
  158. // Synopsis: Checks flags to see if they are valid
  159. //
  160. // Arguments: [grfMode] - Permissions
  161. // [fRoot] - TRUE if checking root storage
  162. //
  163. // Returns: Appropriate status code
  164. //
  165. // Notes: This routine is called when opening a root storage
  166. // or a subelement. When changing root permissions,
  167. // use the fRoot flag to preserve compatibily for
  168. // return codes when opening subelements
  169. //
  170. // History: 19-Mar-92 DrewB Created
  171. //
  172. //---------------------------------------------------------------
  173. SCODE VerifyPerms(DWORD grfMode, BOOL fRoot)
  174. {
  175. SCODE sc = S_OK;
  176. olDebugOut((DEB_ITRACE, "In VerifyPerms(%lX)\n", grfMode));
  177. // Check for valid flags
  178. if ((grfMode & STGM_RDWR) > STGM_READWRITE ||
  179. (grfMode & STGM_DENY) > STGM_SHARE_DENY_NONE ||
  180. (grfMode & ~(STGM_RDWR | STGM_DENY | STGM_DIRECT | STGM_TRANSACTED |
  181. STGM_PRIORITY | STGM_CREATE | STGM_CONVERT | STGM_SIMPLE |
  182. STGM_NOSCRATCH |
  183. #ifndef DISABLE_NOSNAPSHOT
  184. STGM_NOSNAPSHOT |
  185. #endif
  186. #if WIN32 >= 300
  187. STGM_EDIT_ACCESS_RIGHTS |
  188. #endif
  189. #ifdef DIRECTWRITERLOCK
  190. STGM_DIRECT_SWMR |
  191. #endif
  192. STGM_FAILIFTHERE | STGM_DELETEONRELEASE)))
  193. olErr(EH_Err, STG_E_INVALIDFLAG);
  194. // If priority is specified...
  195. if (grfMode & STGM_PRIORITY)
  196. {
  197. // Make sure no priority-denied permissions are specified
  198. if ((grfMode & STGM_RDWR) == STGM_WRITE ||
  199. (grfMode & STGM_RDWR) == STGM_READWRITE ||
  200. (grfMode & STGM_TRANSACTED))
  201. olErr(EH_Err, STG_E_INVALIDFLAG);
  202. }
  203. // Check to make sure only one existence flag is specified
  204. // FAILIFTHERE is zero so it can't be checked
  205. if ((grfMode & (STGM_CREATE | STGM_CONVERT)) ==
  206. (STGM_CREATE | STGM_CONVERT))
  207. olErr(EH_Err, STG_E_INVALIDFLAG);
  208. // If not transacted and not priority, you can either be
  209. // read-only deny write or read-write deny all
  210. if ((grfMode & (STGM_TRANSACTED | STGM_PRIORITY)) == 0)
  211. {
  212. if ((grfMode & STGM_RDWR) == STGM_READ)
  213. {
  214. // we're asking for read-only access
  215. if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE &&
  216. #ifdef DIRECTWRITERLOCK
  217. (!fRoot ||
  218. (grfMode & STGM_DIRECT_SWMR) == 0 ||
  219. (grfMode & STGM_DENY) != STGM_SHARE_DENY_NONE) &&
  220. #endif
  221. (grfMode & STGM_DENY) != STGM_SHARE_DENY_WRITE)
  222. {
  223. // Can't allow others to have write access
  224. olErr(EH_Err, STG_E_INVALIDFLAG);
  225. }
  226. }
  227. else
  228. {
  229. // we're asking for write access
  230. #ifdef DIRECTWRITERLOCK
  231. if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE &&
  232. (!fRoot ||
  233. (grfMode & STGM_DIRECT_SWMR) == 0 ||
  234. (grfMode & STGM_DENY) != STGM_SHARE_DENY_WRITE))
  235. #else
  236. if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE)
  237. #endif
  238. {
  239. // Can't allow others to have any access
  240. olErr(EH_Err, STG_E_INVALIDFLAG);
  241. }
  242. }
  243. }
  244. //If this is not a root open, we can't pass STGM_NOSCRATCH or
  245. // STGM_NOSNAPSHOT
  246. if (!fRoot && (grfMode & (STGM_NOSCRATCH | STGM_NOSNAPSHOT)))
  247. {
  248. olErr(EH_Err, STG_E_INVALIDFLAG);
  249. }
  250. if (grfMode & STGM_NOSCRATCH)
  251. {
  252. if (((grfMode & STGM_RDWR) == STGM_READ) ||
  253. ((grfMode & STGM_TRANSACTED) == 0))
  254. {
  255. olErr(EH_Err, STG_E_INVALIDFLAG);
  256. }
  257. }
  258. if (grfMode & STGM_NOSNAPSHOT)
  259. {
  260. if (((grfMode & STGM_DENY) == STGM_SHARE_EXCLUSIVE) ||
  261. ((grfMode & STGM_DENY) == STGM_SHARE_DENY_WRITE) ||
  262. ((grfMode & STGM_TRANSACTED) == 0) ||
  263. ((grfMode & STGM_NOSCRATCH) != 0) ||
  264. ((grfMode & STGM_CREATE) != 0) ||
  265. ((grfMode & STGM_CONVERT) != 0))
  266. {
  267. olErr(EH_Err, STG_E_INVALIDFLAG);
  268. }
  269. }
  270. olDebugOut((DEB_ITRACE, "Out VerifyPerms\n"));
  271. // Fall through
  272. EH_Err:
  273. return sc;
  274. }
  275. //+---------------------------------------------------------------------------
  276. //
  277. // Member: ValidateNameW, public
  278. //
  279. // Synopsis: Validate that a name is valid and no longer than the
  280. // size specified.
  281. //
  282. // Arguments: [pwcsName] -- Pointer to wide character string
  283. // [cchMax] -- Maximum length for string
  284. //
  285. // Returns: Appropriate status code
  286. //
  287. // History: 23-Nov-98 PhilipLa Created
  288. //
  289. // Notes:
  290. //
  291. //----------------------------------------------------------------------------
  292. SCODE ValidateNameW(LPCWSTR pwcsName, UINT cchMax)
  293. {
  294. SCODE sc = S_OK;
  295. #if WIN32 == 200
  296. if (IsBadReadPtrW(pwcsName, sizeof(WCHAR)))
  297. sc = STG_E_INVALIDNAME;
  298. #else
  299. if (IsBadStringPtrW(pwcsName, cchMax))
  300. sc = STG_E_INVALIDNAME;
  301. #endif
  302. else
  303. {
  304. __try
  305. {
  306. if ((UINT)lstrlenW(pwcsName) >= cchMax)
  307. sc = STG_E_INVALIDNAME;
  308. }
  309. __except (EXCEPTION_EXECUTE_HANDLER)
  310. {
  311. sc = STG_E_INVALIDNAME;
  312. }
  313. }
  314. return sc;
  315. }
  316. //+--------------------------------------------------------------
  317. //
  318. // Function: CheckName, public
  319. //
  320. // Synopsis: Checks name for illegal characters and length
  321. //
  322. // Arguments: [pwcsName] - Name
  323. //
  324. // Returns: Appropriate status code
  325. //
  326. // History: 11-Feb-92 DrewB Created
  327. // 04-Dec-95 SusiA Optimized
  328. //
  329. //---------------------------------------------------------------
  330. SCODE CheckName(WCHAR const *pwcsName)
  331. {
  332. LPCWSTR pChar;
  333. //Each character's position in the array is detrmined by its ascii numeric
  334. //value. ":" is 58, so bit 58 of the array will be 1 if ":" is illegal.
  335. //32bits per position in the array, so 58/32 is in Invalid[1].
  336. //58%32 = 28th bit ( 0x04000000 ) in Invalid[1].
  337. /* Invalid characters: : / ! \ */
  338. static ULONG const Invalid[128/32] =
  339. {0x00000000,0x04008002,0x10000000,0x00000000};
  340. SCODE sc = STG_E_INVALIDNAME;
  341. olDebugOut((DEB_ITRACE, "In CheckName(%ws)\n", pwcsName));
  342. __try
  343. {
  344. for (pChar = (LPCWSTR)pwcsName;
  345. pChar < (LPCWSTR) &pwcsName[CWCMAXPATHCOMPLEN];
  346. pChar++)
  347. {
  348. if (*pChar == L'\0')
  349. {
  350. sc = S_OK;
  351. break; // Success
  352. }
  353. // Test to see if this is an invalid character
  354. if (*pChar < 128 &&
  355. // All values above 128 are valid
  356. (Invalid[*pChar / 32] & (1 << (*pChar % 32))) != 0)
  357. // check to see if this character's bit is set
  358. {
  359. break; // Failure: invalid Char
  360. }
  361. }
  362. }
  363. __except (EXCEPTION_EXECUTE_HANDLER)
  364. {
  365. }
  366. olDebugOut((DEB_ITRACE, "Out CheckName\n"));
  367. return sc;
  368. }
  369. //+--------------------------------------------------------------
  370. //
  371. // Function: ValidateSNB, private
  372. //
  373. // Synopsis: Validates SNB memory
  374. //
  375. // Arguments: [snb] - SNB
  376. //
  377. // Returns: Appropriate status code
  378. //
  379. // History: 10-Jun-92 DrewB Created
  380. //
  381. //---------------------------------------------------------------
  382. SCODE ValidateSNB(SNBW snb)
  383. {
  384. SCODE sc;
  385. olDebugOut((DEB_ITRACE, "In ValidateSNB(%p)\n", snb));
  386. for (;;)
  387. {
  388. olChk(ValidatePtrBuffer(snb));
  389. if (*snb == NULL)
  390. break;
  391. olChk(ValidateNameW(*snb, CWCMAXPATHCOMPLEN));
  392. snb++;
  393. }
  394. olDebugOut((DEB_ITRACE, "Out ValidateSNB\n"));
  395. return S_OK;
  396. EH_Err:
  397. return sc;
  398. }
  399. //+--------------------------------------------------------------
  400. //
  401. // Function: CopySStreamToSStream
  402. //
  403. // Synopsis: Copies the contents of a stream to another stream
  404. //
  405. // Arguments: [psstFrom] - Stream to copy from
  406. // [psstTo] - Stream to copy to
  407. //
  408. // Returns: Appropriate status code
  409. //
  410. // History: 13-Sep-91 DrewB Created
  411. //
  412. // Notes: This function may fail due to out of memory. It
  413. // may not be used by callers who must not fail due
  414. // to out of memory.
  415. //
  416. //---------------------------------------------------------------
  417. SCODE CopySStreamToSStream(PSStream *psstFrom, PSStream *psstTo)
  418. {
  419. BYTE *pbBuffer = NULL;
  420. SCODE sc;
  421. #ifdef LARGE_STREAMS
  422. ULONGLONG cbSize = 0, cbPos;
  423. ULONG cbRead, cbWritten;
  424. #else
  425. ULONG cbRead, cbWritten, cbSize, cbPos;
  426. #endif
  427. // We're allowed to fail due to out of memory
  428. olMem(pbBuffer = (BYTE *) DfMemAlloc(STREAMBUFFERSIZE));
  429. // Set destination size for contiguity
  430. psstFrom->GetSize(&cbSize);
  431. olChk(psstTo->SetSize(cbSize));
  432. // Copy between streams
  433. cbPos = 0;
  434. for (;;)
  435. {
  436. olChk(psstFrom->ReadAt(cbPos, pbBuffer, STREAMBUFFERSIZE,
  437. (ULONG STACKBASED *)&cbRead));
  438. if (cbRead == 0) // EOF
  439. break;
  440. olChk(psstTo->WriteAt(cbPos, pbBuffer, cbRead,
  441. (ULONG STACKBASED *)&cbWritten));
  442. if (cbRead != cbWritten)
  443. olErr(EH_Err, STG_E_WRITEFAULT);
  444. cbPos += cbWritten;
  445. }
  446. EH_Err:
  447. DfMemFree(pbBuffer);
  448. return sc;
  449. }
  450. //+---------------------------------------------------------------------------
  451. //
  452. // Function: dfwcsnicmp, public
  453. //
  454. // Synopsis: wide character string compare that interoperates with what
  455. // we did on 16-bit windows.
  456. //
  457. // Arguments: [wcsa] -- First string
  458. // [wcsb] -- Second string
  459. // [len] -- Length to compare to
  460. //
  461. // Returns: > 0 if wcsa > wcsb
  462. // < 0 if wcsa < wcsb
  463. // 0 is wcsa == wcsb
  464. //
  465. // History: 11-May-95 PhilipLa Created
  466. // 22-Nov-95 SusiA Optimize comparisons
  467. //
  468. // Notes: This function is necessary because on 16-bit windows our
  469. // wcsnicmp function converted everything to uppercase and
  470. // compared the strings, whereas the 32-bit runtimes convert
  471. // everything to lowercase and compare. This means that the
  472. // sort order is different for string containing [\]^_`
  473. //
  474. //----------------------------------------------------------------------------
  475. int dfwcsnicmp(const WCHAR *wcsa, const WCHAR *wcsb, size_t len)
  476. {
  477. if (!len)
  478. return 0;
  479. while (--len && *wcsa &&
  480. ( *wcsa == *wcsb ||
  481. CharUpperW((LPWSTR)*wcsa) == CharUpperW((LPWSTR)*wcsb)))
  482. {
  483. wcsa++;
  484. wcsb++;
  485. }
  486. return (int)(LONG_PTR)CharUpperW((LPWSTR)*wcsa) -
  487. (int)(LONG_PTR)CharUpperW((LPWSTR)*wcsb);
  488. }
  489. //+--------------------------------------------------------------
  490. //
  491. // Function: NameInSNB, private
  492. //
  493. // Synopsis: Determines whether the given name is in the SNB
  494. //
  495. // Arguments: [dfn] - Name
  496. // [snb] - SNB
  497. //
  498. // Returns: S_OK or S_FALSE
  499. //
  500. // History: 19-Mar-92 DrewB Created
  501. //
  502. //---------------------------------------------------------------
  503. SCODE NameInSNB(CDfName const *dfn, SNBW snb)
  504. {
  505. SCODE sc = S_FALSE;
  506. olDebugOut((DEB_ITRACE, "In NameInSNB(%ws, %p)\n", dfn, snb));
  507. TRY
  508. {
  509. for (; *snb; snb++)
  510. if ((lstrlenW(*snb)+1)*sizeof(WCHAR) == dfn->GetLength() &&
  511. #ifdef CASE_SENSITIVE
  512. memcmp(dfn->GetBuffer(), *snb, dfn->GetLength()) == 0)
  513. #else
  514. dfwcsnicmp((WCHAR *)dfn->GetBuffer(), (WCHAR *)*snb,
  515. dfn->GetLength()/sizeof(WCHAR)) == 0)
  516. #endif
  517. {
  518. sc = S_OK;
  519. break;
  520. }
  521. }
  522. CATCH(CException, e)
  523. {
  524. sc = e.GetErrorCode();
  525. }
  526. END_CATCH
  527. olDebugOut((DEB_ITRACE, "Out NameInSNB\n"));
  528. return sc;
  529. }
  530. //+---------------------------------------------------------------------------
  531. //
  532. // Function: Win32ErrorToScode, public
  533. //
  534. // Synopsis: Map a Win32 error into a corresponding scode, remapping
  535. // into Facility_Storage if appropriate.
  536. //
  537. // Arguments: [dwErr] -- Win32 error to map
  538. //
  539. // Returns: Appropriate scode
  540. //
  541. // History: 22-Sep-93 PhilipLa Created
  542. //
  543. //----------------------------------------------------------------------------
  544. SCODE Win32ErrorToScode(DWORD dwErr)
  545. {
  546. olAssert((dwErr != NO_ERROR) &&
  547. aMsg("Win32ErrorToScode called on NO_ERROR"));
  548. SCODE sc = STG_E_UNKNOWN;
  549. switch (dwErr)
  550. {
  551. case ERROR_INVALID_FUNCTION:
  552. sc = STG_E_INVALIDFUNCTION;
  553. break;
  554. case ERROR_FILE_NOT_FOUND:
  555. sc = STG_E_FILENOTFOUND;
  556. break;
  557. case ERROR_PATH_NOT_FOUND:
  558. sc = STG_E_PATHNOTFOUND;
  559. break;
  560. case ERROR_TOO_MANY_OPEN_FILES:
  561. sc = STG_E_TOOMANYOPENFILES;
  562. break;
  563. case ERROR_ACCESS_DENIED:
  564. case ERROR_NETWORK_ACCESS_DENIED:
  565. sc = STG_E_ACCESSDENIED;
  566. break;
  567. case ERROR_INVALID_HANDLE:
  568. sc = STG_E_INVALIDHANDLE;
  569. break;
  570. case ERROR_NOT_ENOUGH_MEMORY:
  571. sc = STG_E_INSUFFICIENTMEMORY;
  572. break;
  573. case ERROR_NO_MORE_FILES:
  574. sc = STG_E_NOMOREFILES;
  575. break;
  576. case ERROR_WRITE_PROTECT:
  577. sc = STG_E_DISKISWRITEPROTECTED;
  578. break;
  579. case ERROR_SEEK:
  580. sc = STG_E_SEEKERROR;
  581. break;
  582. case ERROR_WRITE_FAULT:
  583. sc = STG_E_WRITEFAULT;
  584. break;
  585. case ERROR_READ_FAULT:
  586. sc = STG_E_READFAULT;
  587. break;
  588. case ERROR_SHARING_VIOLATION:
  589. sc = STG_E_SHAREVIOLATION;
  590. break;
  591. case ERROR_LOCK_VIOLATION:
  592. sc = STG_E_LOCKVIOLATION;
  593. break;
  594. case ERROR_HANDLE_DISK_FULL:
  595. case ERROR_DISK_FULL:
  596. sc = STG_E_MEDIUMFULL;
  597. break;
  598. case ERROR_FILE_EXISTS:
  599. case ERROR_ALREADY_EXISTS:
  600. sc = STG_E_FILEALREADYEXISTS;
  601. break;
  602. case ERROR_INVALID_PARAMETER:
  603. sc = STG_E_INVALIDPARAMETER;
  604. break;
  605. case ERROR_INVALID_NAME:
  606. case ERROR_BAD_PATHNAME:
  607. case ERROR_FILENAME_EXCED_RANGE:
  608. sc = STG_E_INVALIDNAME;
  609. break;
  610. case ERROR_INVALID_FLAGS:
  611. sc = STG_E_INVALIDFLAG;
  612. break;
  613. case ERROR_CANT_ACCESS_FILE:
  614. sc= STG_E_DOCFILECORRUPT;
  615. break;
  616. default:
  617. sc = WIN32_SCODE(dwErr);
  618. break;
  619. }
  620. return sc;
  621. }
  622. //+---------------------------------------------------------------------------
  623. //
  624. // Function: IsValidStgInterface
  625. //
  626. // Synopsis: a copy of the old IsValidInterface() from COM
  627. //
  628. // Arguments: [pv] -- interface to validate
  629. //
  630. // Returns: Appropriate flag
  631. //
  632. // History: 08-May-2000 HenryLee Created
  633. //
  634. //----------------------------------------------------------------------------
  635. BOOL IsValidStgInterface( void * pv )
  636. {
  637. ULONG_PTR * pVtbl;
  638. BYTE * pFcn;
  639. volatile BYTE bInstr;
  640. __try {
  641. pVtbl = *(ULONG_PTR **) pv; // beginning of vtable
  642. #if DBG==1
  643. for (int i=0 ; i<3; ++i) // loop through qi,addref,rel
  644. #else
  645. int i=1; // in retail, just do AddRef
  646. #endif
  647. {
  648. pFcn = *(BYTE **) &pVtbl[i];
  649. #if DBG==1
  650. if (IsBadCodePtr((FARPROC)pFcn)) {
  651. return FALSE;
  652. }
  653. #endif
  654. bInstr = *(BYTE *) pFcn; // get 1st byte of 1st instruction
  655. }
  656. }
  657. __except(EXCEPTION_EXECUTE_HANDLER)
  658. {
  659. return FALSE;
  660. }
  661. return TRUE;
  662. }