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.

890 lines
25 KiB

  1. #include <pch.cxx>
  2. #include <funcs.hxx>
  3. #include <dfentry.hxx>
  4. DECLARE_INFOLEVEL(ol)
  5. #define ntfsChk(a) olChk(a)
  6. #define ntfsErr(a,b) olErr(a,b)
  7. #define ntfsDebugOut(a) olDebugOut(a)
  8. #define ntfsAssert(a) olAssert(a)
  9. //+---------------------------------------------------------------------------
  10. //
  11. // Function: DfOpenStorageEx
  12. //
  13. // Synopsis: Open storage and stream objects
  14. //
  15. // Arguments: [pwcsUsersName] - pathanme of the file
  16. // [fCreateAPI] - create or open
  17. // [grfMode] - open mode flags
  18. // [grfAttrs] - reserved
  19. // [stgfmt] - storage format
  20. // [pSecurity] - reserved
  21. // [pTransaction] - reserved
  22. // [riid] - GUID of interface pointer to return
  23. // [ppObjectOpen] - interface pointer to return
  24. // Returns: Appropriate status code
  25. //
  26. // History: 12-Jul-95 HenryLee Created
  27. //
  28. //----------------------------------------------------------------------------
  29. STDAPI DfOpenStorageEx (
  30. const WCHAR* pwcsUsersName,
  31. BOOL fCreateAPI, // create vs open
  32. DWORD grfMode,
  33. DWORD stgfmt, // enum
  34. DWORD grfAttrs, // reserved
  35. STGOPTIONS *pStgOptions,
  36. void * reserved,
  37. WCHAR * pwcsNameSnapshot,
  38. REFIID riid,
  39. void ** ppObjectOpen)
  40. {
  41. HRESULT sc = S_OK;
  42. DWORD dwFullPathLen;
  43. WCHAR awcsFullName[_MAX_PATH], *pwcsFile;
  44. //
  45. // The ANY and STORAGE formats recursivly call back through here
  46. // for the correct real format (DOCFILE, NATIVE or FILE). We only call
  47. // GetFullPathName on real formats, to avoid redundant calls as we
  48. // recurse.
  49. // This then *requires* that the ANY and STORAGE must recurse (i.e. can't
  50. // call NFFOpen or NSS directly) because the filename has not been
  51. // properly prepared.
  52. //
  53. // For STGFMT_DOCFILE, let the docfile layer handle name checking
  54. //
  55. if(STGFMT_ANY != stgfmt &&
  56. STGFMT_STORAGE != stgfmt &&
  57. STGFMT_DOCFILE != stgfmt)
  58. {
  59. dwFullPathLen = GetFullPathNameW(pwcsUsersName, _MAX_PATH,
  60. awcsFullName,&pwcsFile);
  61. if (dwFullPathLen == 0)
  62. {
  63. DWORD dwErr = GetLastError();
  64. // In some circumstances (name == " ", for instance),
  65. // GetFullPathNameW can return 0 and GetLastError returns 0.
  66. // We want to return STG_E_INVALIDNAME for these.
  67. if (dwErr != NOERROR)
  68. {
  69. ntfsErr(EH_Err, Win32ErrorToScode(dwErr));
  70. }
  71. else
  72. {
  73. ntfsErr(EH_Err, STG_E_INVALIDNAME);
  74. }
  75. }
  76. else if (dwFullPathLen > _MAX_PATH)
  77. ntfsErr(EH_Err, STG_E_PATHNOTFOUND);
  78. }
  79. //-----------------------------------------
  80. // Switch on STGFMT_
  81. // STORAGE, NATIVE, DOCFILE, FILE, ANY
  82. //
  83. switch(stgfmt)
  84. {
  85. case STGFMT_FILE:
  86. {
  87. ntfsChk( NFFOpen( awcsFullName, grfMode, NFFOPEN_NORMAL,
  88. fCreateAPI, riid, ppObjectOpen) );
  89. } // case STGFMT_FILE
  90. break;
  91. case STGFMT_ANY:
  92. {
  93. DWORD stgfmt=STGFMT_STORAGE;
  94. //
  95. // Attempting to CREATE a Storage with STGFMT_ANY is ambiguous,
  96. // On NTFS either STGFMT_NATIVE or STGFMT_FILE could be appropriate,
  97. // and is therefore invalid.
  98. //
  99. if (fCreateAPI)
  100. ntfsChk (STG_E_INVALIDPARAMETER);
  101. //
  102. // If the file is a storage then try STGFMT_STORAGE.
  103. // Otherwise try STGFMT_FILE.
  104. // If StgIsStorageFile() error'ed go ahead into the STGFMT_STORAGE
  105. // for consistant error return values.
  106. //
  107. if( S_OK == CNtfsStorage::IsNffAppropriate( pwcsUsersName ) )
  108. stgfmt = STGFMT_FILE;
  109. sc = DfOpenStorageEx (pwcsUsersName, fCreateAPI, grfMode, stgfmt,
  110. grfAttrs, pStgOptions, reserved,
  111. pwcsNameSnapshot, riid, ppObjectOpen);
  112. ntfsChk(sc);
  113. } // case STGFMT_ANY;
  114. break;
  115. default:
  116. ntfsErr (EH_Err, STG_E_INVALIDPARAMETER);
  117. break;
  118. }
  119. EH_Err:
  120. return sc;
  121. };
  122. //+---------------------------------------------------------------------------
  123. //
  124. // Function: StgCreateStorageEx, public
  125. //
  126. // Synopsis: Creates a storage or stream object
  127. //
  128. // Arguments: [pwcsName] - pathname of file
  129. // [grfMode] - open mode flags
  130. // [stgfmt] - storage format
  131. // [grfAttrs] - reserved
  132. // [pSecurity] - reserved
  133. // [pTransaction] - reserved
  134. // [riid] - GUID of interface pointer to return
  135. // [ppObjectOpen] - interface pointer to return
  136. //
  137. // Returns: Appropriate status code
  138. //
  139. // History: 12-Jul-95 HenryLee Created
  140. //
  141. //----------------------------------------------------------------------------
  142. typedef HRESULT (*PFNStgCreateStorageEx)( const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt,
  143. DWORD grfAttrs, void *pSecurity, void *pTransaction,
  144. REFIID riid, void **ppObjectOpen );
  145. typedef HRESULT (*PFNStgOpenStorageEx)( const WCHAR *pwcsName, DWORD grfMode, DWORD stgfmt,
  146. DWORD grfAttrs, void *pSecurity, void *pTransaction,
  147. REFIID riid, void **ppObjectOpen );
  148. HINSTANCE HInstOle32()
  149. {
  150. static HINSTANCE hinstOLE32 = NULL;
  151. if( NULL == hinstOLE32 )
  152. hinstOLE32 = LoadLibrary( TEXT("ole32.dll") );
  153. return( hinstOLE32 );
  154. }
  155. WINOLEAPI StgCreateStorageEx (IN const WCHAR* pwcsName,
  156. IN DWORD grfMode,
  157. IN DWORD stgfmt, // enum
  158. IN DWORD grfAttrs, // reserved
  159. IN STGOPTIONS * pStgOptions,
  160. IN void * reserved,
  161. IN REFIID riid,
  162. OUT void ** ppObjectOpen)
  163. {
  164. HRESULT sc = S_OK;
  165. WCHAR awcsTmpPath[_MAX_PATH];
  166. ntfsChk(ValidatePtrBuffer(ppObjectOpen));
  167. *ppObjectOpen = NULL;
  168. if (grfAttrs != 0)
  169. ntfsErr(EH_Err, STG_E_INVALIDFLAG);
  170. if ((grfMode & STGM_RDWR) == STGM_READ ||
  171. (grfMode & (STGM_DELETEONRELEASE | STGM_CONVERT)) ==
  172. (STGM_DELETEONRELEASE | STGM_CONVERT))
  173. ntfsErr(EH_Err, STG_E_INVALIDFLAG);
  174. if( STGFMT_FILE == stgfmt
  175. &&
  176. (IID_IPropertySetStorage == riid || IID_IStorage == riid || IID_IPropertyBagEx == riid)
  177. )
  178. {
  179. ntfsChk (DfOpenStorageEx (pwcsName, TRUE, grfMode, stgfmt, grfAttrs,
  180. pStgOptions, reserved, NULL, riid, ppObjectOpen));
  181. }
  182. else
  183. {
  184. static PFNStgCreateStorageEx pfnStgCreateStorageEx = NULL;
  185. if( NULL == pfnStgCreateStorageEx )
  186. pfnStgCreateStorageEx = (PFNStgCreateStorageEx) GetProcAddress( HInstOle32(), "StgCreateStorageEx" );
  187. if( NULL == pfnStgCreateStorageEx )
  188. ntfsChk( E_FAIL );
  189. ntfsChk( pfnStgCreateStorageEx( pwcsName, grfMode, stgfmt, grfAttrs, pStgOptions, reserved, riid, ppObjectOpen ));
  190. }
  191. ntfsDebugOut((DEB_TRACE, "Out StgCreateStorageEx => %p\n", *ppObjectOpen));
  192. EH_Err:
  193. return sc;
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Function: StgOpenStorageEx
  198. //
  199. // Synopsis: Open storage and stream objects
  200. //
  201. // Arguments: [pwcsName] - pathanme of the file
  202. // [grfMode] - open mode flags
  203. // [grfAttrs] - reserved
  204. // [stgfmt] - storage format
  205. // [pSecurity] - reserved
  206. // [pTransaction] - reserved
  207. // [riid] - GUID of interface pointer to return
  208. // [ppObjectOpen] - interface pointer to return
  209. // Returns: Appropriate status code
  210. //
  211. // History: 12-Jul-95 HenryLee Created
  212. //
  213. //----------------------------------------------------------------------------
  214. WINOLEAPI StgOpenStorageEx (IN const WCHAR* pwcsName,
  215. IN DWORD grfMode,
  216. IN DWORD stgfmt, // enum
  217. IN DWORD grfAttrs, // reserved
  218. IN STGOPTIONS * pStgOptions,
  219. IN void * reserved,
  220. IN REFIID riid,
  221. OUT void ** ppObjectOpen)
  222. {
  223. HRESULT sc = S_OK;
  224. WCHAR awcsTmpPath[_MAX_PATH];
  225. WCHAR * pwcsNameSnapshot = NULL;
  226. ntfsDebugOut((DEB_TRACE, "In StgOpenStorageEx(%ws, %p, %p, %p, %p)\n",
  227. pwcsName, grfMode, stgfmt, riid, ppObjectOpen));
  228. ntfsChk(ValidatePtrBuffer(ppObjectOpen));
  229. *ppObjectOpen = NULL;
  230. if (pStgOptions!= NULL || reserved != NULL)
  231. ntfsErr (EH_Err, STG_E_INVALIDPARAMETER);
  232. if (grfAttrs != 0)
  233. ntfsErr(EH_Err, STG_E_INVALIDFLAG);
  234. ntfsChk (ValidateNameW (pwcsName, _MAX_PATH));
  235. if( (IID_IPropertySetStorage == riid || IID_IStorage == riid || IID_IPropertyBagEx == riid)
  236. &&
  237. ( STGFMT_FILE == stgfmt
  238. ||
  239. STGFMT_ANY == stgfmt && S_OK != StgIsStorageFile(pwcsName)
  240. )
  241. )
  242. {
  243. ntfsChk (DfOpenStorageEx (pwcsName, FALSE, grfMode, stgfmt, grfAttrs,
  244. pStgOptions, reserved, pwcsNameSnapshot, riid, ppObjectOpen));
  245. }
  246. else
  247. {
  248. static PFNStgOpenStorageEx pfnStgOpenStorageEx = NULL;
  249. if( NULL == pfnStgOpenStorageEx )
  250. pfnStgOpenStorageEx = (PFNStgOpenStorageEx) GetProcAddress( HInstOle32(), "StgOpenStorageEx" );
  251. if( NULL == pfnStgOpenStorageEx )
  252. ntfsChk( E_FAIL );
  253. ntfsChk( pfnStgOpenStorageEx( pwcsName, grfMode, stgfmt, grfAttrs, pStgOptions, reserved,
  254. riid, ppObjectOpen ));
  255. }
  256. ntfsDebugOut((DEB_TRACE, "Out StgOpenStorageEx => %p\n", *ppObjectOpen));
  257. EH_Err:
  258. return sc;
  259. }
  260. // Copied from stg\docfile\funcs.cxx
  261. #ifdef WIN32
  262. SCODE Win32ErrorToScode(DWORD dwErr)
  263. {
  264. olAssert((dwErr != NO_ERROR) &&
  265. aMsg("Win32ErrorToScode called on NO_ERROR"));
  266. SCODE sc = STG_E_UNKNOWN;
  267. switch (dwErr)
  268. {
  269. case ERROR_INVALID_FUNCTION:
  270. sc = STG_E_INVALIDFUNCTION;
  271. break;
  272. case ERROR_FILE_NOT_FOUND:
  273. sc = STG_E_FILENOTFOUND;
  274. break;
  275. case ERROR_PATH_NOT_FOUND:
  276. sc = STG_E_PATHNOTFOUND;
  277. break;
  278. case ERROR_TOO_MANY_OPEN_FILES:
  279. sc = STG_E_TOOMANYOPENFILES;
  280. break;
  281. case ERROR_ACCESS_DENIED:
  282. case ERROR_NETWORK_ACCESS_DENIED:
  283. sc = STG_E_ACCESSDENIED;
  284. break;
  285. case ERROR_INVALID_HANDLE:
  286. sc = STG_E_INVALIDHANDLE;
  287. break;
  288. case ERROR_NOT_ENOUGH_MEMORY:
  289. sc = STG_E_INSUFFICIENTMEMORY;
  290. break;
  291. case ERROR_NO_MORE_FILES:
  292. sc = STG_E_NOMOREFILES;
  293. break;
  294. case ERROR_WRITE_PROTECT:
  295. sc = STG_E_DISKISWRITEPROTECTED;
  296. break;
  297. case ERROR_SEEK:
  298. sc = STG_E_SEEKERROR;
  299. break;
  300. case ERROR_WRITE_FAULT:
  301. sc = STG_E_WRITEFAULT;
  302. break;
  303. case ERROR_READ_FAULT:
  304. sc = STG_E_READFAULT;
  305. break;
  306. case ERROR_SHARING_VIOLATION:
  307. sc = STG_E_SHAREVIOLATION;
  308. break;
  309. case ERROR_LOCK_VIOLATION:
  310. sc = STG_E_LOCKVIOLATION;
  311. break;
  312. case ERROR_HANDLE_DISK_FULL:
  313. case ERROR_DISK_FULL:
  314. sc = STG_E_MEDIUMFULL;
  315. break;
  316. case ERROR_FILE_EXISTS:
  317. case ERROR_ALREADY_EXISTS:
  318. sc = STG_E_FILEALREADYEXISTS;
  319. break;
  320. case ERROR_INVALID_PARAMETER:
  321. sc = STG_E_INVALIDPARAMETER;
  322. break;
  323. case ERROR_INVALID_NAME:
  324. case ERROR_BAD_PATHNAME:
  325. case ERROR_FILENAME_EXCED_RANGE:
  326. sc = STG_E_INVALIDNAME;
  327. break;
  328. case ERROR_INVALID_FLAGS:
  329. sc = STG_E_INVALIDFLAG;
  330. break;
  331. default:
  332. sc = WIN32_SCODE(dwErr);
  333. break;
  334. }
  335. return sc;
  336. }
  337. #endif
  338. //+--------------------------------------------------------------
  339. //
  340. // Function: ValidateSNB, private
  341. //
  342. // Synopsis: Validates SNB memory
  343. //
  344. // Arguments: [snb] - SNB
  345. //
  346. // Returns: Appropriate status code
  347. //
  348. // History: 10-Jun-92 DrewB Created
  349. //
  350. //---------------------------------------------------------------
  351. #include <docfilep.hxx>
  352. // ***** From stg\docfile\funcs.cxx
  353. SCODE ValidateSNB(SNBW snb)
  354. {
  355. SCODE sc;
  356. olDebugOut((DEB_ITRACE, "In ValidateSNB(%p)\n", snb));
  357. for (;;)
  358. {
  359. olChk(ValidatePtrBuffer(snb));
  360. if (*snb == NULL)
  361. break;
  362. olChk(ValidateNameW(*snb, CWCMAXPATHCOMPLEN));
  363. snb++;
  364. }
  365. olDebugOut((DEB_ITRACE, "Out ValidateSNB\n"));
  366. return S_OK;
  367. EH_Err:
  368. return sc;
  369. }
  370. //+--------------------------------------------------------------
  371. //
  372. // Function: CheckName, public
  373. //
  374. // Synopsis: Checks name for illegal characters and length
  375. //
  376. // Arguments: [pwcsName] - Name
  377. //
  378. // Returns: Appropriate status code
  379. //
  380. // History: 11-Feb-92 DrewB Created
  381. // 04-Dec-95 SusiA Optimized
  382. //
  383. //---------------------------------------------------------------
  384. // ***** From stg\docfile\funcs.cxx
  385. #ifdef OLEWIDECHAR
  386. SCODE CheckName(WCHAR const *pwcsName)
  387. {
  388. LPCWSTR pChar;
  389. //Each character's position in the array is detrmined by its ascii numeric
  390. //value. ":" is 58, so bit 58 of the array will be 1 if ":" is illegal.
  391. //32bits per position in the array, so 58/32 is in Invalid[1].
  392. //58%32 = 28th bit ( 0x04000000 ) in Invalid[1].
  393. /* Invalid characters: : / ! \ */
  394. static ULONG const Invalid[128/32] =
  395. {0x00000000,0x04008002,0x10000000,0x00000000};
  396. SCODE sc = STG_E_INVALIDNAME;
  397. olDebugOut((DEB_ITRACE, "In CheckName(%ws)\n", pwcsName));
  398. __try
  399. {
  400. for (pChar = (LPCWSTR)pwcsName;
  401. pChar <= (LPCWSTR) &pwcsName[CWCMAXPATHCOMPLEN];
  402. pChar++)
  403. {
  404. if (*pChar == L'\0')
  405. {
  406. sc = S_OK;
  407. break; // Success
  408. }
  409. // Test to see if this is an invalid character
  410. if (*pChar < 128 &&
  411. // All values above 128 are valid
  412. (Invalid[*pChar / 32] & (1 << (*pChar % 32))) != 0)
  413. // check to see if this character's bit is set
  414. {
  415. break; // Failure: invalid Char
  416. }
  417. }
  418. }
  419. __except (EXCEPTION_EXECUTE_HANDLER)
  420. {
  421. }
  422. olDebugOut((DEB_ITRACE, "Out CheckName\n"));
  423. return sc;
  424. }
  425. #endif
  426. /*
  427. // Forwarders to the nt5props.dll version of the property APIs.
  428. EXTERN_C HRESULT
  429. PrivPropVariantCopy ( PROPVARIANT * pvarDest, const PROPVARIANT * pvarSrc )
  430. {
  431. return( PropVariantCopy( pvarDest, pvarSrc ));
  432. }
  433. EXTERN_C HRESULT
  434. PrivPropVariantClear ( PROPVARIANT * pvar )
  435. {
  436. return( PropVariantClear( pvar ));
  437. }
  438. EXTERN_C HRESULT
  439. PrivFreePropVariantArray ( ULONG cVariants, PROPVARIANT * rgvars )
  440. {
  441. return( FreePropVariantArray( cVariants, rgvars ));
  442. }
  443. EXTERN_C ULONG
  444. PrivStgPropertyLengthAsVariant( IN SERIALIZEDPROPERTYVALUE const *pprop,
  445. IN ULONG cbprop, IN USHORT CodePage,
  446. IN BYTE flags )
  447. {
  448. return( StgPropertyLengthAsVariant( pprop, cbprop, CodePage, flags ));
  449. }
  450. EXTERN_C SERIALIZEDPROPERTYVALUE *
  451. PrivStgConvertVariantToProperty(
  452. IN PROPVARIANT const *pvar,
  453. IN USHORT CodePage,
  454. OPTIONAL OUT SERIALIZEDPROPERTYVALUE *pprop,
  455. IN OUT ULONG *pcb,
  456. IN PROPID pid,
  457. IN BOOLEAN fVariantVectorOrArray, // Used for recursive calls
  458. OPTIONAL OUT ULONG *pcIndirect)
  459. {
  460. return( StgConvertVariantToProperty( pvar, CodePage, pprop, pcb, pid, fVariantVectorOrArray, pcIndirect ));
  461. }
  462. */
  463. //+--------------------------------------------------------------
  464. //
  465. // Function: VerifyPerms, private
  466. //
  467. // Synopsis: Checks flags to see if they are valid
  468. //
  469. // Arguments: [grfMode] - Permissions
  470. // [fRoot] - TRUE if checking root storage
  471. //
  472. // Returns: Appropriate status code
  473. //
  474. // Notes: This routine is called when opening a root storage
  475. // or a subelement. When changing root permissions,
  476. // use the fRoot flag to preserve compatibily for
  477. // return codes when opening subelements
  478. //
  479. // History: 19-Mar-92 DrewB Created
  480. //
  481. //---------------------------------------------------------------
  482. SCODE VerifyPerms(DWORD grfMode, BOOL fRoot)
  483. {
  484. SCODE sc = S_OK;
  485. olDebugOut((DEB_ITRACE, "In VerifyPerms(%lX)\n", grfMode));
  486. // Check for valid flags
  487. if ((grfMode & STGM_RDWR) > STGM_READWRITE ||
  488. (grfMode & STGM_DENY) > STGM_SHARE_DENY_NONE ||
  489. (grfMode & ~(STGM_RDWR | STGM_DENY | STGM_DIRECT | STGM_TRANSACTED |
  490. STGM_PRIORITY | STGM_CREATE | STGM_CONVERT |
  491. STGM_NOSCRATCH |
  492. #ifndef DISABLE_NOSNAPSHOT
  493. STGM_NOSNAPSHOT |
  494. #endif
  495. #if WIN32 >= 300
  496. STGM_EDIT_ACCESS_RIGHTS |
  497. #endif
  498. STGM_FAILIFTHERE | STGM_DELETEONRELEASE)))
  499. olErr(EH_Err, STG_E_INVALIDFLAG);
  500. // If priority is specified...
  501. if (grfMode & STGM_PRIORITY)
  502. {
  503. // Make sure no priority-denied permissions are specified
  504. if ((grfMode & STGM_RDWR) == STGM_WRITE ||
  505. (grfMode & STGM_RDWR) == STGM_READWRITE ||
  506. (grfMode & STGM_TRANSACTED))
  507. olErr(EH_Err, STG_E_INVALIDFLAG);
  508. }
  509. // Check to make sure only one existence flag is specified
  510. // FAILIFTHERE is zero so it can't be checked
  511. if ((grfMode & (STGM_CREATE | STGM_CONVERT)) ==
  512. (STGM_CREATE | STGM_CONVERT))
  513. olErr(EH_Err, STG_E_INVALIDFLAG);
  514. // If not transacted and not priority, you can either be
  515. // read-only deny write or read-write deny all
  516. if ((grfMode & (STGM_TRANSACTED | STGM_PRIORITY)) == 0)
  517. {
  518. if ((grfMode & STGM_RDWR) == STGM_READ)
  519. {
  520. // we're asking for read-only access
  521. if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE &&
  522. #ifdef DIRECTWRITERLOCK
  523. (!fRoot || (grfMode & STGM_DENY) != STGM_SHARE_DENY_NONE) &&
  524. #endif
  525. (grfMode & STGM_DENY) != STGM_SHARE_DENY_WRITE)
  526. {
  527. // Can't allow others to have write access
  528. olErr(EH_Err, STG_E_INVALIDFLAG);
  529. }
  530. }
  531. else
  532. {
  533. // we're asking for write access
  534. #ifdef DIRECTWRITERLOCK
  535. if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE &&
  536. (!fRoot || (grfMode & STGM_DENY) != STGM_SHARE_DENY_WRITE))
  537. #else
  538. if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE)
  539. #endif
  540. {
  541. // Can't allow others to have any access
  542. olErr(EH_Err, STG_E_INVALIDFLAG);
  543. }
  544. }
  545. }
  546. //If this is not a root open, we can't pass STGM_NOSCRATCH or
  547. // STGM_NOSNAPSHOT
  548. if (!fRoot && (grfMode & (STGM_NOSCRATCH | STGM_NOSNAPSHOT)))
  549. {
  550. olErr(EH_Err, STG_E_INVALIDFLAG);
  551. }
  552. if (grfMode & STGM_NOSCRATCH)
  553. {
  554. if (((grfMode & STGM_RDWR) == STGM_READ) ||
  555. ((grfMode & STGM_TRANSACTED) == 0))
  556. {
  557. olErr(EH_Err, STG_E_INVALIDFLAG);
  558. }
  559. }
  560. if (grfMode & STGM_NOSNAPSHOT)
  561. {
  562. if (((grfMode & STGM_DENY) == STGM_SHARE_EXCLUSIVE) ||
  563. ((grfMode & STGM_DENY) == STGM_SHARE_DENY_WRITE) ||
  564. ((grfMode & STGM_TRANSACTED) == 0) ||
  565. ((grfMode & STGM_NOSCRATCH) != 0) ||
  566. ((grfMode & STGM_CREATE) != 0) ||
  567. ((grfMode & STGM_CONVERT) != 0))
  568. {
  569. olErr(EH_Err, STG_E_INVALIDFLAG);
  570. }
  571. }
  572. olDebugOut((DEB_ITRACE, "Out VerifyPerms\n"));
  573. // Fall through
  574. EH_Err:
  575. return sc;
  576. }
  577. //+--------------------------------------------------------------
  578. //
  579. // Function: StgIsStorageFileHandle, private
  580. //
  581. // Synopsis: Determines whether a handle is open on a storage file.
  582. // Spun off from StgIsStorageFile. Internaly we use this
  583. //
  584. // Arguments: [hf] - Open File Handle (caller must seek it to 0)
  585. //
  586. // Returns: S_OK, S_FALSE or error codes
  587. //
  588. // History: 07-May-98 MikeHill Created
  589. // 05-June-98 BChapman Return Errors not just S_FALSE.
  590. // Add optional Overlapped pointer.
  591. //
  592. //---------------------------------------------------------------
  593. STDAPI StgIsStorageFileHandle( HANDLE hf, LPOVERLAPPED povlp )
  594. {
  595. DWORD cbRead;
  596. BYTE stgHeader[sizeof(SStorageFile)];
  597. SCODE sc;
  598. LONG status;
  599. OVERLAPPED ovlp;
  600. FillMemory( stgHeader, sizeof(SStorageFile), 0xDE );
  601. if (povlp == NULL)
  602. {
  603. ovlp.Offset = 0;
  604. ovlp.OffsetHigh = 0;
  605. ovlp.hEvent = NULL;
  606. }
  607. if( !ReadFile( hf,
  608. &stgHeader,
  609. sizeof( stgHeader ),
  610. &cbRead,
  611. (povlp == NULL) ? &ovlp : povlp ) )
  612. {
  613. if( NULL != povlp )
  614. {
  615. status = GetLastError();
  616. if( ERROR_IO_PENDING == status)
  617. {
  618. status = ERROR_SUCCESS;
  619. if( !GetOverlappedResult( hf, povlp, &cbRead, TRUE ) )
  620. status = GetLastError();
  621. }
  622. if(ERROR_SUCCESS != status && ERROR_HANDLE_EOF != status)
  623. olChk( HRESULT_FROM_WIN32( status ) );
  624. }
  625. else
  626. olErr( EH_Err, LAST_STG_SCODE );
  627. }
  628. // Don't worry about short reads. If the read is short then
  629. // the signature checks will fail.
  630. sc = CheckSignature( ((SStorageFile*)stgHeader)->abSig );
  631. if(S_OK == sc)
  632. goto EH_Err; // Done, return "Yes"
  633. olChk(sc);
  634. // It didn't error. sc != S_OK then it
  635. // Must be S_FALSE.
  636. olAssert(S_FALSE == sc);
  637. EH_Err:
  638. if( (STG_E_OLDFORMAT == sc) || (STG_E_INVALIDHEADER == sc) )
  639. sc = S_FALSE;
  640. return sc;
  641. }
  642. //+---------------------------------------------------------------------------
  643. //
  644. // Function: CheckSignature, private
  645. //
  646. // Synopsis: Checks the given memory against known signatures
  647. //
  648. // Arguments: [pb] - Pointer to memory to check
  649. //
  650. // Returns: S_OK - Current signature
  651. // S_FALSE - Beta 2 signature, but still successful
  652. // Appropriate status code
  653. //
  654. // History: 23-Jul-93 DrewB Created from header.cxx code
  655. //
  656. //----------------------------------------------------------------------------
  657. //Identifier for first bytes of Beta 1 Docfiles
  658. const BYTE SIGSTG_B1[] = {0xd0, 0xcf, 0x11, 0xe0, 0x0e, 0x11, 0xfc, 0x0d};
  659. const USHORT CBSIGSTG_B1 = sizeof(SIGSTG_B1);
  660. //Identifier for first bytes of Beta 2 Docfiles
  661. const BYTE SIGSTG_B2[] = {0x0e, 0x11, 0xfc, 0x0d, 0xd0, 0xcf, 0x11, 0xe0};
  662. const BYTE CBSIGSTG_B2 = sizeof(SIGSTG_B2);
  663. SCODE CheckSignature(BYTE *pb)
  664. {
  665. SCODE sc;
  666. olDebugOut((DEB_ITRACE, "In CheckSignature(%p)\n", pb));
  667. // Check for ship Docfile signature first
  668. if (memcmp(pb, SIGSTG, CBSIGSTG) == 0)
  669. sc = S_OK;
  670. // Check for Beta 2 Docfile signature
  671. else if (memcmp(pb, SIGSTG_B2, CBSIGSTG_B2) == 0)
  672. sc = S_FALSE;
  673. // Check for Beta 1 Docfile signature
  674. else if (memcmp(pb, SIGSTG_B1, CBSIGSTG_B1) == 0)
  675. sc = STG_E_OLDFORMAT;
  676. else
  677. sc = STG_E_INVALIDHEADER;
  678. olDebugOut((DEB_ITRACE, "Out CheckSignature => %lX\n", sc));
  679. return sc;
  680. }
  681. //+---------------------------------------------------------------------------
  682. //
  683. // Function: dfwcsnicmp, public
  684. //
  685. // Synopsis: wide character string compare that interoperates with what
  686. // we did on 16-bit windows.
  687. //
  688. // Arguments: [wcsa] -- First string
  689. // [wcsb] -- Second string
  690. // [len] -- Length to compare to
  691. //
  692. // Returns: > 0 if wcsa > wcsb
  693. // < 0 if wcsa < wcsb
  694. // 0 is wcsa == wcsb
  695. //
  696. // History: 11-May-95 PhilipLa Created
  697. // 22-Nov-95 SusiA Optimize comparisons
  698. //
  699. // Notes: This function is necessary because on 16-bit windows our
  700. // wcsnicmp function converted everything to uppercase and
  701. // compared the strings, whereas the 32-bit runtimes convert
  702. // everything to lowercase and compare. This means that the
  703. // sort order is different for string containing [\]^_`
  704. //
  705. //----------------------------------------------------------------------------
  706. int dfwcsnicmp(const WCHAR *wcsa, const WCHAR *wcsb, size_t len)
  707. {
  708. if (!len)
  709. return 0;
  710. while (--len && *wcsa &&
  711. ( *wcsa == *wcsb ||
  712. CharUpperW((LPWSTR)*wcsa) == CharUpperW((LPWSTR)*wcsb)))
  713. {
  714. wcsa++;
  715. wcsb++;
  716. }
  717. return (int)(LONG_PTR)CharUpperW((LPWSTR)*wcsa) -
  718. (int)(LONG_PTR)CharUpperW((LPWSTR)*wcsb);
  719. }
  720. //+---------------------------------------------------------------------------
  721. //
  722. // Member: ValidateNameW, public
  723. //
  724. // Synopsis: Validate that a name is valid and no longer than the
  725. // size specified.
  726. //
  727. // Arguments: [pwcsName] -- Pointer to wide character string
  728. // [cchMax] -- Maximum length for string
  729. //
  730. // Returns: Appropriate status code
  731. //
  732. // History: 23-Nov-98 PhilipLa Created
  733. //
  734. // Notes:
  735. //
  736. //----------------------------------------------------------------------------
  737. SCODE ValidateNameW(LPCWSTR pwcsName, UINT cchMax)
  738. {
  739. SCODE sc = S_OK;
  740. #if WIN32 == 200
  741. if (IsBadReadPtrW(pwcsName, sizeof(WCHAR)))
  742. sc = STG_E_INVALIDNAME;
  743. #else
  744. if (IsBadStringPtrW(pwcsName, cchMax))
  745. sc = STG_E_INVALIDNAME;
  746. #endif
  747. else
  748. {
  749. __try
  750. {
  751. if ((UINT)lstrlenW(pwcsName) >= cchMax)
  752. sc = STG_E_INVALIDNAME;
  753. }
  754. __except (EXCEPTION_EXECUTE_HANDLER)
  755. {
  756. sc = STG_E_INVALIDNAME;
  757. }
  758. }
  759. return sc;
  760. }