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.

607 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: api.cxx
  7. //
  8. // Contents: API entry points
  9. //
  10. // History: 30-Jun-93 DrewB Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "exphead.cxx"
  14. #pragma hdrstop
  15. #include <propapi.h>
  16. #include <hntfsstg.hxx>
  17. #include <dfentry.hxx>
  18. #include <winefs.h> // for DuplicateEncryptionInfoFile
  19. SCODE ValidateGrfMode( DWORD grfMode, BOOL fCreateAPI );
  20. HRESULT GetNFFTempName (const WCHAR *pwcsFileName, WCHAR *awcsTmpName);
  21. SCODE ValidateStgOptions (STGOPTIONS * pStgOptions, DWORD stgfmt, BOOL fCreate);
  22. inline SCODE ValidateGrfAttrs (DWORD grfAttrs, DWORD stgfmt)
  23. {
  24. if (stgfmt != STGFMT_DOCFILE)
  25. {
  26. if (grfAttrs != 0)
  27. return STG_E_INVALIDFLAG;
  28. }
  29. else
  30. {
  31. if ((grfAttrs & ~FILE_FLAG_NO_BUFFERING) != 0)
  32. return STG_E_INVALIDFLAG;
  33. }
  34. return S_OK;
  35. }
  36. //+---------------------------------------------------------------------------
  37. //
  38. // Function: DfOpenStorageEx
  39. //
  40. // Synopsis: Open storage and stream objects
  41. //
  42. // Arguments: [pwcsUsersName] - pathanme of the file
  43. // [fCreateAPI] - create or open
  44. // [grfMode] - open mode flags
  45. // [grfAttrs] - reserved
  46. // [stgfmt] - storage format
  47. // [pSecurity] - reserved
  48. // [pTransaction] - reserved
  49. // [riid] - GUID of interface pointer to return
  50. // [ppObjectOpen] - interface pointer to return
  51. // Returns: Appropriate status code
  52. //
  53. // History: 12-Jul-95 HenryLee Created
  54. //
  55. //----------------------------------------------------------------------------
  56. STDAPI DfOpenStorageEx (
  57. const WCHAR* pwcsUsersName,
  58. BOOL fCreateAPI, // create vs open
  59. DWORD grfMode,
  60. DWORD stgfmt, // enum
  61. DWORD grfAttrs, // reserved
  62. STGOPTIONS *pStgOptions,
  63. void * reserved,
  64. REFIID riid,
  65. void ** ppObjectOpen)
  66. {
  67. HRESULT sc = S_OK;
  68. CSmAllocator *pMalloc = NULL;
  69. ULONG_PTR uHeapBase;
  70. DWORD dwFullPathLen;
  71. WCHAR awcsFullName[_MAX_PATH], *pwcsFile;
  72. WCHAR awcsTmpPath[_MAX_PATH], *pwcsNameSnapshot = NULL;
  73. //
  74. // The ANY and STORAGE formats recursivly call back through here
  75. // for the correct real format (DOCFILE, NATIVE or FILE). We only call
  76. // GetFullPathName on real formats, to avoid redundant calls as we
  77. // recurse.
  78. // This then *requires* that the ANY and STORAGE must recurse (i.e. can't
  79. // call NFFOpen or NSS directly) because the filename has not been
  80. // properly prepared.
  81. //
  82. // For STGFMT_DOCFILE, let the docfile layer handle name checking
  83. //
  84. if(STGFMT_ANY != stgfmt &&
  85. STGFMT_STORAGE != stgfmt &&
  86. STGFMT_DOCFILE != stgfmt)
  87. {
  88. dwFullPathLen = GetFullPathNameW(pwcsUsersName, _MAX_PATH,
  89. awcsFullName,&pwcsFile);
  90. if (dwFullPathLen == 0)
  91. {
  92. DWORD dwErr = GetLastError();
  93. // In some circumstances (name == " ", for instance),
  94. // GetFullPathNameW can return 0 and GetLastError returns 0.
  95. // We want to return STG_E_INVALIDNAME for these.
  96. if (dwErr != NOERROR)
  97. {
  98. olErr(EH_Err, Win32ErrorToScode(dwErr));
  99. }
  100. else
  101. {
  102. olErr(EH_Err, STG_E_INVALIDNAME);
  103. }
  104. }
  105. else if (dwFullPathLen > _MAX_PATH)
  106. olErr(EH_Err, STG_E_PATHNOTFOUND);
  107. }
  108. //-----------------------------------------
  109. // Switch on STGFMT_
  110. // STORAGE, NATIVE, DOCFILE, FILE, ANY
  111. //
  112. switch(stgfmt)
  113. {
  114. case STGFMT_FILE:
  115. {
  116. olChk( NFFOpen( awcsFullName, grfMode, NFFOPEN_NORMAL,
  117. fCreateAPI, riid, ppObjectOpen) );
  118. } // case STGFMT_FILE
  119. break;
  120. case STGFMT_ANY:
  121. {
  122. DWORD stgfmt=STGFMT_STORAGE;
  123. //
  124. // Attempting to CREATE a Storage with STGFMT_ANY is ambiguous,
  125. // On NTFS either STGFMT_NATIVE or STGFMT_FILE could be appropriate,
  126. // and is therefore invalid.
  127. //
  128. if (fCreateAPI)
  129. olChk (STG_E_INVALIDPARAMETER);
  130. //
  131. // If IsNffAppropriate() returns S_OK use STGFMT_FILE
  132. // If it returns STG_E_INVALIDFUNCTION try storage (FAT-FS or Docfile).
  133. // Any other Error, bubble back to the user
  134. //
  135. sc = CNtfsStorage::IsNffAppropriate( pwcsUsersName );
  136. if( SUCCEEDED( sc ) )
  137. {
  138. stgfmt = STGFMT_FILE;
  139. }
  140. else
  141. {
  142. if( STG_E_INVALIDFUNCTION == sc )
  143. stgfmt = STGFMT_STORAGE;
  144. else
  145. olChk( sc );
  146. }
  147. sc = DfOpenStorageEx (pwcsUsersName, fCreateAPI, grfMode, stgfmt,
  148. grfAttrs, pStgOptions, reserved,
  149. riid, ppObjectOpen);
  150. olChk(sc);
  151. } // case STGFMT_ANY;
  152. break;
  153. case STGFMT_STORAGE:
  154. case STGFMT_DOCFILE: // GetFullPathName has not yet been called.
  155. {
  156. IStorage *pstg = NULL;
  157. ULONG ulSectorSize;
  158. if( fCreateAPI )
  159. {
  160. if (grfAttrs & FILE_ATTRIBUTE_TEMPORARY) // create temp file
  161. pwcsUsersName = NULL;
  162. olChk( DfCreateDocfile (pwcsUsersName,
  163. NULL, grfMode, NULL,
  164. pStgOptions ? pStgOptions->ulSectorSize : 512,
  165. grfAttrs, &pstg));
  166. }
  167. else
  168. olChk( DfOpenDocfile (pwcsUsersName,
  169. NULL,
  170. NULL,
  171. grfMode,
  172. NULL,
  173. 0,
  174. &ulSectorSize,
  175. grfAttrs,
  176. &pstg));
  177. if( IID_IStorage != riid )
  178. {
  179. sc = pstg->QueryInterface( riid, ppObjectOpen );
  180. pstg->Release();
  181. if (fCreateAPI && !SUCCEEDED(sc) && pwcsUsersName != NULL)
  182. {
  183. DeleteFileW (pwcsUsersName); //delete newly create file
  184. }
  185. }
  186. else
  187. {
  188. *ppObjectOpen = pstg;
  189. if (pStgOptions != NULL && !fCreateAPI)
  190. pStgOptions->ulSectorSize = ulSectorSize;
  191. }
  192. olChk(sc);
  193. } // case STGFMT_DOCFILE
  194. break;
  195. case STGFMT_NATIVE:
  196. default:
  197. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  198. break;
  199. }
  200. EH_Err:
  201. return sc;
  202. };
  203. //+---------------------------------------------------------------------------
  204. //
  205. // Function: StgCreateStorageEx, public
  206. //
  207. // Synopsis: Creates a storage or stream object
  208. //
  209. // Arguments: [pwcsName] - pathname of file
  210. // [grfMode] - open mode flags
  211. // [stgfmt] - storage format
  212. // [grfAttrs] - reserved
  213. // [pSecurity] - reserved
  214. // [pTransaction] - reserved
  215. // [riid] - GUID of interface pointer to return
  216. // [ppObjectOpen] - interface pointer to return
  217. //
  218. // Returns: Appropriate status code
  219. //
  220. // History: 12-Jul-95 HenryLee Created
  221. //
  222. //----------------------------------------------------------------------------
  223. STDAPI StgCreateStorageEx (const WCHAR* pwcsName,
  224. DWORD grfMode,
  225. DWORD stgfmt, // enum
  226. DWORD grfAttrs, // reserved
  227. STGOPTIONS * pStgOptions,
  228. void * reserved,
  229. REFIID riid,
  230. void ** ppObjectOpen)
  231. {
  232. HRESULT sc = S_OK;
  233. WCHAR awcsTmpPath[_MAX_PATH];
  234. olDebugOut((DEB_TRACE, "In StgCreateStorageEx(%ws, %p, %p, %p, %p)\n",
  235. pwcsName, grfMode, stgfmt, riid, ppObjectOpen));
  236. olChk(ValidatePtrBuffer(ppObjectOpen));
  237. *ppObjectOpen = NULL;
  238. if (reserved != NULL)
  239. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  240. olChk( ValidateGrfAttrs (grfAttrs, stgfmt));
  241. olChk( ValidateGrfMode( grfMode, TRUE ) );
  242. olChk( VerifyPerms( grfMode, TRUE ) );
  243. if (pStgOptions != NULL)
  244. olChk( ValidateStgOptions(pStgOptions, stgfmt, TRUE));
  245. if (stgfmt == STGFMT_FILE)
  246. {
  247. if (pwcsName != NULL)
  248. {
  249. olChk (ValidateNameW (pwcsName, _MAX_PATH));
  250. }
  251. else
  252. {
  253. olChk (GetNFFTempName (pwcsName, awcsTmpPath));
  254. pwcsName = awcsTmpPath;
  255. //Add the STGM_CREATE flag so we don't fail with
  256. //STG_E_FILEALREADYEXISTS when we see that the file already exists
  257. //later.
  258. grfMode |= STGM_CREATE;
  259. grfAttrs |= FILE_ATTRIBUTE_TEMPORARY;
  260. }
  261. }
  262. if (stgfmt == STGFMT_DOCFILE &&
  263. pStgOptions != NULL &&
  264. pStgOptions->usVersion >= 2 &&
  265. pStgOptions->pwcsTemplateFile != NULL)
  266. {
  267. DWORD dwAttrs = GetFileAttributes (pStgOptions->pwcsTemplateFile);
  268. if (dwAttrs == 0xFFFFFFFF)
  269. olChk (WIN32_SCODE (GetLastError()));
  270. if (dwAttrs & FILE_ATTRIBUTE_ENCRYPTED)
  271. {
  272. DWORD dwErr = DuplicateEncryptionInfoFile(
  273. pStgOptions->pwcsTemplateFile,
  274. pwcsName,
  275. grfMode & STGM_CREATE ? CREATE_ALWAYS : CREATE_NEW,
  276. FILE_ATTRIBUTE_NORMAL,
  277. NULL);
  278. if (dwErr != ERROR_SUCCESS)
  279. olChk (WIN32_SCODE(dwErr));
  280. grfAttrs |= FILE_ATTRIBUTE_ENCRYPTED;
  281. }
  282. }
  283. olChk (DfOpenStorageEx (pwcsName, TRUE, grfMode, stgfmt, grfAttrs,
  284. pStgOptions, reserved, riid, ppObjectOpen));
  285. olDebugOut((DEB_TRACE, "Out StgCreateStorageEx => %p\n", *ppObjectOpen));
  286. EH_Err:
  287. return sc;
  288. }
  289. //+---------------------------------------------------------------------------
  290. //
  291. // Function: StgOpenStorageEx
  292. //
  293. // Synopsis: Open storage and stream objects
  294. //
  295. // Arguments: [pwcsName] - pathanme of the file
  296. // [grfMode] - open mode flags
  297. // [grfAttrs] - reserved
  298. // [stgfmt] - storage format
  299. // [pSecurity] - reserved
  300. // [pTransaction] - reserved
  301. // [riid] - GUID of interface pointer to return
  302. // [ppObjectOpen] - interface pointer to return
  303. // Returns: Appropriate status code
  304. //
  305. // History: 12-Jul-95 HenryLee Created
  306. //
  307. //----------------------------------------------------------------------------
  308. STDAPI StgOpenStorageEx (const WCHAR *pwcsName,
  309. DWORD grfMode,
  310. DWORD stgfmt, // enum
  311. DWORD grfAttrs, // reserved
  312. STGOPTIONS * pStgOptions,
  313. void * reserved,
  314. REFIID riid,
  315. void ** ppObjectOpen)
  316. {
  317. HRESULT sc = S_OK;
  318. olDebugOut((DEB_TRACE, "In StgOpenStorageEx(%ws, %p, %p, %p, %p)\n",
  319. pwcsName, grfMode, stgfmt, riid, ppObjectOpen));
  320. olChk(ValidatePtrBuffer(ppObjectOpen));
  321. *ppObjectOpen = NULL;
  322. if (reserved != NULL)
  323. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  324. olChk (ValidateNameW (pwcsName, _MAX_PATH));
  325. olChk( ValidateGrfAttrs (grfAttrs, stgfmt));
  326. olChk( ValidateGrfMode( grfMode, FALSE ) );
  327. olChk( VerifyPerms( grfMode, TRUE ) );
  328. if (pStgOptions != NULL)
  329. olChk( ValidateStgOptions(pStgOptions, stgfmt, FALSE));
  330. olChk (DfOpenStorageEx (pwcsName, FALSE, grfMode, stgfmt, grfAttrs,
  331. pStgOptions, reserved, riid, ppObjectOpen));
  332. olDebugOut((DEB_TRACE, "Out StgOpenStorageEx => %p\n", *ppObjectOpen));
  333. EH_Err:
  334. return sc;
  335. }
  336. //+---------------------------------------------------------------------------
  337. //
  338. // Function: ValidateGrfMode
  339. //
  340. // Synopsis: Sanity checking for the grfMode. (all implementations)
  341. //
  342. // Arguments: [grfMode] -- grfMode to check
  343. // [fCreateAPI] -- Called from CreateStorage vs. OpenStorage.
  344. //
  345. // Returns: Appropriate status code
  346. //
  347. // History: 30-Mar-98 BChapman Created
  348. //
  349. //----------------------------------------------------------------------------
  350. SCODE ValidateGrfMode( DWORD grfMode, BOOL fCreateAPI )
  351. {
  352. HRESULT sc=S_OK;
  353. // If there are any invalid bits set (error)
  354. if( 0 != ( grfMode & ~( STGM_DIRECT | // 0
  355. STGM_TRANSACTED | // 1 0000
  356. STGM_SIMPLE | // 800 0000
  357. STGM_READ | // 0
  358. STGM_WRITE | // 1
  359. STGM_READWRITE | // 2
  360. STGM_SHARE_DENY_NONE | // 40
  361. STGM_SHARE_DENY_READ | // 30
  362. STGM_SHARE_DENY_WRITE | // 20
  363. STGM_SHARE_EXCLUSIVE | // 10
  364. STGM_PRIORITY | // 4 0000
  365. STGM_DELETEONRELEASE | // 400 0000
  366. STGM_NOSCRATCH | // 10 0000
  367. STGM_CREATE | // 1000
  368. STGM_CONVERT | // 2 0000
  369. STGM_FAILIFTHERE | // 0
  370. STGM_DIRECT_SWMR |
  371. STGM_NOSNAPSHOT ) ) ) // 20 0000
  372. {
  373. olErr( EH_Err, STG_E_INVALIDFLAG );
  374. }
  375. // If you Create for ReadOnly (error)
  376. if( fCreateAPI && ( ( grfMode & STGM_RDWR ) == STGM_READ ) )
  377. olErr( EH_Err, STG_E_INVALIDFLAG );
  378. // if you Open/Create for Convert And DeleteOnRelease (error)
  379. if( ( grfMode & ( STGM_DELETEONRELEASE | STGM_CONVERT ) )
  380. == ( STGM_DELETEONRELEASE | STGM_CONVERT ) )
  381. {
  382. olErr(EH_Err, STG_E_INVALIDFLAG);
  383. }
  384. if( grfMode & STGM_SIMPLE )
  385. {
  386. if( fCreateAPI )
  387. {
  388. // If you Create Simple it must be exactly this way.
  389. if( grfMode != ( STGM_SIMPLE | STGM_READWRITE |
  390. STGM_SHARE_EXCLUSIVE | STGM_CREATE ) )
  391. olErr( EH_Err, STG_E_INVALIDFLAG );
  392. }
  393. else
  394. {
  395. // If you Open Simple it must be one of these two ways.
  396. if( grfMode != (STGM_SIMPLE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE )
  397. && grfMode != (STGM_SIMPLE | STGM_SHARE_EXCLUSIVE | STGM_READ ) )
  398. olErr( EH_Err, STG_E_INVALIDFLAG );
  399. }
  400. }
  401. if( !fCreateAPI )
  402. {
  403. if (grfMode & STGM_DELETEONRELEASE)
  404. olErr(EH_Err, STG_E_INVALIDFUNCTION);
  405. if (grfMode & (STGM_CREATE | STGM_CONVERT))
  406. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  407. }
  408. EH_Err:
  409. return sc;
  410. }
  411. //+---------------------------------------------------------------------------
  412. //
  413. // Function: ValidateStgOptions
  414. //
  415. // Synopsis: Sanity checking for the StgOptions
  416. //
  417. // Arguments: [pStgOptions] -- options to check
  418. // [stgfmt] -- intended storage format
  419. //
  420. // Returns: Appropriate status code
  421. //
  422. // History: 30-Mar-98 HenryLee Created
  423. //
  424. //----------------------------------------------------------------------------
  425. SCODE ValidateStgOptions (STGOPTIONS * pStgOptions, DWORD stgfmt, BOOL fCreate)
  426. {
  427. #ifdef LARGE_DOCFILE
  428. HRESULT sc = S_OK;
  429. olChk(ValidatePtrBuffer(pStgOptions));
  430. if (pStgOptions->usVersion > STGOPTIONS_VERSION ||
  431. pStgOptions->usVersion == 0 ||
  432. pStgOptions->reserved != 0)
  433. {
  434. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  435. }
  436. if (fCreate)
  437. {
  438. // enable large sector support only for docfiles
  439. if (pStgOptions->ulSectorSize != 512 && stgfmt != STGFMT_DOCFILE)
  440. {
  441. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  442. }
  443. if (pStgOptions->ulSectorSize != 512 &&
  444. pStgOptions->ulSectorSize != 4096)
  445. /* pStgOptions->ulSectorSize != 8192 && */
  446. /* pStgOptions->ulSectorSize != 16384 && */
  447. /* pStgOptions->ulSectorSize != 32768) */
  448. {
  449. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  450. }
  451. if (pStgOptions->usVersion >= 2)
  452. {
  453. if (stgfmt != STGFMT_DOCFILE)
  454. {
  455. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  456. }
  457. else if (pStgOptions->pwcsTemplateFile != NULL)
  458. olChk (ValidatePtrBuffer (pStgOptions->pwcsTemplateFile));
  459. }
  460. }
  461. else
  462. {
  463. if (stgfmt != STGFMT_DOCFILE)
  464. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  465. if (pStgOptions->usVersion >= 2 && pStgOptions->pwcsTemplateFile !=NULL)
  466. olErr (EH_Err, STG_E_INVALIDPARAMETER);
  467. }
  468. EH_Err:
  469. #else
  470. HRESULT sc = STG_E_INVALIDPARAMETER;
  471. #endif
  472. return sc;
  473. }
  474. //+---------------------------------------------------------------------------
  475. //
  476. // Member: GetNFFTempName, public
  477. //
  478. // Synopsis: returns a filename for temporary NSS files
  479. //
  480. // Arguments: [pwcsFileName] - original file name
  481. // [ppwcsTmpName] - output temporary name
  482. //
  483. // Returns: Appropriate status code
  484. //
  485. // History: 01-Jul-97 HenryLee Created
  486. //
  487. //----------------------------------------------------------------------------
  488. HRESULT GetNFFTempName (const WCHAR *pwcsFileName, WCHAR *awcsTmpName)
  489. {
  490. HRESULT sc = S_OK;
  491. WCHAR awcsDir[_MAX_PATH];
  492. WCHAR *pwcsFile = NULL;
  493. //
  494. // Create a temp file in pwcsFileName's directory
  495. //
  496. if (pwcsFileName != NULL)
  497. {
  498. if (GetFullPathNameW (pwcsFileName, _MAX_PATH, awcsDir, &pwcsFile) == 0)
  499. {
  500. const DWORD dwErr = GetLastError();
  501. //In some circumstances (name == " ", for instance),
  502. // GetFullPathNameW can return 0 and GetLastError returns 0.
  503. // We want to return STG_E_INVALIDNAME for these.
  504. olErr(EH_Err, (dwErr != NOERROR) ? Win32ErrorToScode(dwErr) :
  505. STG_E_INVALIDNAME);
  506. }
  507. else if (pwcsFile) *pwcsFile = L'\0';
  508. }
  509. else
  510. {
  511. // Create a temp file for StgCreateDocfile (NULL name)
  512. //
  513. // try %temp%
  514. if(0 == GetTempPath(_MAX_PATH, awcsDir))
  515. {
  516. // next try %windir%
  517. if(0 == GetWindowsDirectory(awcsDir, _MAX_PATH))
  518. {
  519. // finally use current directory
  520. lstrcpyW (awcsDir, L".");
  521. }
  522. }
  523. }
  524. if (GetTempFileNameW (awcsDir, TEMPFILE_PREFIX, 0, awcsTmpName)==FALSE)
  525. olErr (EH_Err, Win32ErrorToScode(GetLastError()));
  526. EH_Err:
  527. return sc;
  528. }