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.

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