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.

720 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 (!IsValidReadPtrIn(pwcsName, cchMax))
  296. sc = STG_E_INVALIDNAME;
  297. else
  298. {
  299. if (FAILED(StringCchLength(pwcsName, cchMax, NULL)))
  300. sc = STG_E_INVALIDNAME;
  301. }
  302. return sc;
  303. }
  304. //+--------------------------------------------------------------
  305. //
  306. // Function: CheckName, public
  307. //
  308. // Synopsis: Checks name for illegal characters and length
  309. //
  310. // Arguments: [pwcsName] - Name
  311. //
  312. // Returns: Appropriate status code
  313. //
  314. // History: 11-Feb-92 DrewB Created
  315. // 04-Dec-95 SusiA Optimized
  316. //
  317. //---------------------------------------------------------------
  318. SCODE CheckName(WCHAR const *pwcsName)
  319. {
  320. LPCWSTR pChar;
  321. //Each character's position in the array is detrmined by its ascii numeric
  322. //value. ":" is 58, so bit 58 of the array will be 1 if ":" is illegal.
  323. //32bits per position in the array, so 58/32 is in Invalid[1].
  324. //58%32 = 28th bit ( 0x04000000 ) in Invalid[1].
  325. /* Invalid characters: : / ! \ */
  326. static ULONG const Invalid[128/32] =
  327. {0x00000000,0x04008002,0x10000000,0x00000000};
  328. SCODE sc = STG_E_INVALIDNAME;
  329. olDebugOut((DEB_ITRACE, "In CheckName(%ws)\n", pwcsName));
  330. __try
  331. {
  332. for (pChar = (LPCWSTR)pwcsName;
  333. pChar < (LPCWSTR) &pwcsName[CWCMAXPATHCOMPLEN];
  334. pChar++)
  335. {
  336. if (*pChar == L'\0')
  337. {
  338. sc = S_OK;
  339. break; // Success
  340. }
  341. // Test to see if this is an invalid character
  342. if (*pChar < 128 &&
  343. // All values above 128 are valid
  344. (Invalid[*pChar / 32] & (1 << (*pChar % 32))) != 0)
  345. // check to see if this character's bit is set
  346. {
  347. break; // Failure: invalid Char
  348. }
  349. }
  350. }
  351. __except (EXCEPTION_EXECUTE_HANDLER)
  352. {
  353. }
  354. olDebugOut((DEB_ITRACE, "Out CheckName\n"));
  355. return sc;
  356. }
  357. //+--------------------------------------------------------------
  358. //
  359. // Function: ValidateSNB, private
  360. //
  361. // Synopsis: Validates SNB memory
  362. //
  363. // Arguments: [snb] - SNB
  364. //
  365. // Returns: Appropriate status code
  366. //
  367. // History: 10-Jun-92 DrewB Created
  368. //
  369. //---------------------------------------------------------------
  370. SCODE ValidateSNB(SNBW snb)
  371. {
  372. SCODE sc;
  373. olDebugOut((DEB_ITRACE, "In ValidateSNB(%p)\n", snb));
  374. for (;;)
  375. {
  376. olChk(ValidatePtrBuffer(snb));
  377. if (*snb == NULL)
  378. break;
  379. olChk(ValidateNameW(*snb, CWCMAXPATHCOMPLEN));
  380. snb++;
  381. }
  382. olDebugOut((DEB_ITRACE, "Out ValidateSNB\n"));
  383. return S_OK;
  384. EH_Err:
  385. return sc;
  386. }
  387. //+--------------------------------------------------------------
  388. //
  389. // Function: CopySStreamToSStream
  390. //
  391. // Synopsis: Copies the contents of a stream to another stream
  392. //
  393. // Arguments: [psstFrom] - Stream to copy from
  394. // [psstTo] - Stream to copy to
  395. //
  396. // Returns: Appropriate status code
  397. //
  398. // History: 13-Sep-91 DrewB Created
  399. //
  400. // Notes: This function may fail due to out of memory. It
  401. // may not be used by callers who must not fail due
  402. // to out of memory.
  403. //
  404. //---------------------------------------------------------------
  405. SCODE CopySStreamToSStream(PSStream *psstFrom, PSStream *psstTo)
  406. {
  407. BYTE *pbBuffer = NULL;
  408. SCODE sc;
  409. #ifdef LARGE_STREAMS
  410. ULONGLONG cbSize = 0, cbPos;
  411. ULONG cbRead, cbWritten;
  412. #else
  413. ULONG cbRead, cbWritten, cbSize, cbPos;
  414. #endif
  415. // We're allowed to fail due to out of memory
  416. olMem(pbBuffer = (BYTE *) DfMemAlloc(STREAMBUFFERSIZE));
  417. // Set destination size for contiguity
  418. psstFrom->GetSize(&cbSize);
  419. olChk(psstTo->SetSize(cbSize));
  420. // Copy between streams
  421. cbPos = 0;
  422. for (;;)
  423. {
  424. olChk(psstFrom->ReadAt(cbPos, pbBuffer, STREAMBUFFERSIZE,
  425. (ULONG STACKBASED *)&cbRead));
  426. if (cbRead == 0) // EOF
  427. break;
  428. olChk(psstTo->WriteAt(cbPos, pbBuffer, cbRead,
  429. (ULONG STACKBASED *)&cbWritten));
  430. if (cbRead != cbWritten)
  431. olErr(EH_Err, STG_E_WRITEFAULT);
  432. cbPos += cbWritten;
  433. }
  434. EH_Err:
  435. if (pbBuffer != NULL)
  436. DfMemFree(pbBuffer);
  437. return sc;
  438. }
  439. //+---------------------------------------------------------------------------
  440. //
  441. // Function: dfwcsnicmp, public
  442. //
  443. // Synopsis: wide character string compare that interoperates with what
  444. // we did on 16-bit windows.
  445. //
  446. // Arguments: [wcsa] -- First string
  447. // [wcsb] -- Second string
  448. // [len] -- Length to compare to
  449. //
  450. // Returns: > 0 if wcsa > wcsb
  451. // < 0 if wcsa < wcsb
  452. // 0 is wcsa == wcsb
  453. //
  454. // History: 11-May-95 PhilipLa Created
  455. // 22-Nov-95 SusiA Optimize comparisons
  456. //
  457. // Notes: This function is necessary because on 16-bit windows our
  458. // wcsnicmp function converted everything to uppercase and
  459. // compared the strings, whereas the 32-bit runtimes convert
  460. // everything to lowercase and compare. This means that the
  461. // sort order is different for string containing [\]^_`
  462. //
  463. //----------------------------------------------------------------------------
  464. int dfwcsnicmp(const WCHAR *wcsa, const WCHAR *wcsb, size_t len)
  465. {
  466. if (!len)
  467. return 0;
  468. while (--len && *wcsa &&
  469. ( *wcsa == *wcsb ||
  470. CharUpperW((LPWSTR)*wcsa) == CharUpperW((LPWSTR)*wcsb)))
  471. {
  472. wcsa++;
  473. wcsb++;
  474. }
  475. return (int)(LONG_PTR)CharUpperW((LPWSTR)*wcsa) -
  476. (int)(LONG_PTR)CharUpperW((LPWSTR)*wcsb);
  477. }
  478. //+--------------------------------------------------------------
  479. //
  480. // Function: NameInSNB, private
  481. //
  482. // Synopsis: Determines whether the given name is in the SNB
  483. //
  484. // Arguments: [dfn] - Name
  485. // [snb] - SNB
  486. //
  487. // Returns: S_OK or S_FALSE
  488. //
  489. // History: 19-Mar-92 DrewB Created
  490. //
  491. //---------------------------------------------------------------
  492. SCODE NameInSNB(CDfName const *dfn, SNBW snb)
  493. {
  494. SCODE sc = S_FALSE;
  495. olDebugOut((DEB_ITRACE, "In NameInSNB(%ws, %p)\n", dfn, snb));
  496. TRY
  497. {
  498. for (; *snb; snb++)
  499. if ((lstrlenW(*snb)+1)*sizeof(WCHAR) == dfn->GetLength() &&
  500. #ifdef CASE_SENSITIVE
  501. memcmp(dfn->GetBuffer(), *snb, dfn->GetLength()) == 0)
  502. #else
  503. dfwcsnicmp((WCHAR *)dfn->GetBuffer(), (WCHAR *)*snb,
  504. dfn->GetLength()/sizeof(WCHAR)) == 0)
  505. #endif
  506. {
  507. sc = S_OK;
  508. break;
  509. }
  510. }
  511. CATCH(CException, e)
  512. {
  513. sc = e.GetErrorCode();
  514. }
  515. END_CATCH
  516. olDebugOut((DEB_ITRACE, "Out NameInSNB\n"));
  517. return sc;
  518. }
  519. //+---------------------------------------------------------------------------
  520. //
  521. // Function: Win32ErrorToScode, public
  522. //
  523. // Synopsis: Map a Win32 error into a corresponding scode, remapping
  524. // into Facility_Storage if appropriate.
  525. //
  526. // Arguments: [dwErr] -- Win32 error to map
  527. //
  528. // Returns: Appropriate scode
  529. //
  530. // History: 22-Sep-93 PhilipLa Created
  531. //
  532. //----------------------------------------------------------------------------
  533. SCODE Win32ErrorToScode(DWORD dwErr)
  534. {
  535. olAssert((dwErr != NO_ERROR) &&
  536. aMsg("Win32ErrorToScode called on NO_ERROR"));
  537. SCODE sc = STG_E_UNKNOWN;
  538. switch (dwErr)
  539. {
  540. case ERROR_INVALID_FUNCTION:
  541. sc = STG_E_INVALIDFUNCTION;
  542. break;
  543. case ERROR_FILE_NOT_FOUND:
  544. sc = STG_E_FILENOTFOUND;
  545. break;
  546. case ERROR_PATH_NOT_FOUND:
  547. sc = STG_E_PATHNOTFOUND;
  548. break;
  549. case ERROR_TOO_MANY_OPEN_FILES:
  550. sc = STG_E_TOOMANYOPENFILES;
  551. break;
  552. case ERROR_ACCESS_DENIED:
  553. case ERROR_NETWORK_ACCESS_DENIED:
  554. sc = STG_E_ACCESSDENIED;
  555. break;
  556. case ERROR_INVALID_HANDLE:
  557. sc = STG_E_INVALIDHANDLE;
  558. break;
  559. case ERROR_NOT_ENOUGH_MEMORY:
  560. sc = STG_E_INSUFFICIENTMEMORY;
  561. break;
  562. case ERROR_NO_MORE_FILES:
  563. sc = STG_E_NOMOREFILES;
  564. break;
  565. case ERROR_WRITE_PROTECT:
  566. sc = STG_E_DISKISWRITEPROTECTED;
  567. break;
  568. case ERROR_SEEK:
  569. sc = STG_E_SEEKERROR;
  570. break;
  571. case ERROR_WRITE_FAULT:
  572. sc = STG_E_WRITEFAULT;
  573. break;
  574. case ERROR_READ_FAULT:
  575. sc = STG_E_READFAULT;
  576. break;
  577. case ERROR_SHARING_VIOLATION:
  578. sc = STG_E_SHAREVIOLATION;
  579. break;
  580. case ERROR_LOCK_VIOLATION:
  581. sc = STG_E_LOCKVIOLATION;
  582. break;
  583. case ERROR_HANDLE_DISK_FULL:
  584. case ERROR_DISK_FULL:
  585. sc = STG_E_MEDIUMFULL;
  586. break;
  587. case ERROR_FILE_EXISTS:
  588. case ERROR_ALREADY_EXISTS:
  589. sc = STG_E_FILEALREADYEXISTS;
  590. break;
  591. case ERROR_INVALID_PARAMETER:
  592. sc = STG_E_INVALIDPARAMETER;
  593. break;
  594. case ERROR_INVALID_NAME:
  595. case ERROR_BAD_PATHNAME:
  596. case ERROR_FILENAME_EXCED_RANGE:
  597. sc = STG_E_INVALIDNAME;
  598. break;
  599. case ERROR_INVALID_FLAGS:
  600. sc = STG_E_INVALIDFLAG;
  601. break;
  602. case ERROR_CANT_ACCESS_FILE:
  603. sc= STG_E_DOCFILECORRUPT;
  604. break;
  605. default:
  606. sc = WIN32_SCODE(dwErr);
  607. break;
  608. }
  609. return sc;
  610. }
  611. //+---------------------------------------------------------------------------
  612. //
  613. // Function: IsValidStgInterface
  614. //
  615. // Synopsis: a copy of the old IsValidInterface() from COM
  616. //
  617. // Arguments: [pv] -- interface to validate
  618. //
  619. // Returns: Appropriate flag
  620. //
  621. // History: 08-May-2000 HenryLee Created
  622. //
  623. //----------------------------------------------------------------------------
  624. BOOL IsValidStgInterface( void * pv )
  625. {
  626. ULONG_PTR * pVtbl;
  627. BYTE * pFcn;
  628. volatile BYTE bInstr;
  629. __try {
  630. pVtbl = *(ULONG_PTR **) pv; // beginning of vtable
  631. #if DBG==1
  632. for (int i=0 ; i<3; ++i) // loop through qi,addref,rel
  633. #else
  634. int i=1; // in retail, just do AddRef
  635. #endif
  636. {
  637. pFcn = *(BYTE **) &pVtbl[i];
  638. bInstr = *(BYTE *) pFcn; // get 1st byte of 1st instruction
  639. }
  640. }
  641. __except(EXCEPTION_EXECUTE_HANDLER)
  642. {
  643. return FALSE;
  644. }
  645. return TRUE;
  646. }