//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: api.cxx // // Contents: API entry points // // History: 30-Jun-93 DrewB Created // //---------------------------------------------------------------------------- #include "exphead.cxx" #pragma hdrstop #include #include #include #include // for DuplicateEncryptionInfoFile SCODE ValidateGrfMode( DWORD grfMode, BOOL fCreateAPI ); HRESULT GetNFFTempName (const WCHAR *pwcsFileName, WCHAR *awcsTmpName); SCODE ValidateStgOptions (STGOPTIONS * pStgOptions, DWORD stgfmt, BOOL fCreate); inline SCODE ValidateGrfAttrs (DWORD grfAttrs, DWORD stgfmt) { if (stgfmt != STGFMT_DOCFILE) { if (grfAttrs != 0) return STG_E_INVALIDFLAG; } else { if ((grfAttrs & ~FILE_FLAG_NO_BUFFERING) != 0) return STG_E_INVALIDFLAG; } return S_OK; } //+--------------------------------------------------------------------------- // // Function: DfOpenStorageEx // // Synopsis: Open storage and stream objects // // Arguments: [pwcsUsersName] - pathanme of the file // [fCreateAPI] - create or open // [grfMode] - open mode flags // [grfAttrs] - reserved // [stgfmt] - storage format // [pSecurity] - reserved // [pTransaction] - reserved // [riid] - GUID of interface pointer to return // [ppObjectOpen] - interface pointer to return // Returns: Appropriate status code // // History: 12-Jul-95 HenryLee Created // //---------------------------------------------------------------------------- STDAPI DfOpenStorageEx ( const WCHAR* pwcsUsersName, BOOL fCreateAPI, // create vs open DWORD grfMode, DWORD stgfmt, // enum DWORD grfAttrs, // reserved STGOPTIONS *pStgOptions, void * reserved, REFIID riid, void ** ppObjectOpen) { HRESULT sc = S_OK; DWORD dwFullPathLen; WCHAR awcsFullName[_MAX_PATH], *pwcsFile; // // The ANY and STORAGE formats recursivly call back through here // for the correct real format (DOCFILE or FILE). We only call // GetFullPathName on real formats, to avoid redundant calls as we // recurse. // This then *requires* that the ANY and STORAGE must recurse (i.e. can't // call NFFOpen or docfile directly) because the filename has not been // properly prepared. // // For STGFMT_DOCFILE, let the docfile layer handle name checking // if(STGFMT_ANY != stgfmt && STGFMT_STORAGE != stgfmt && STGFMT_DOCFILE != stgfmt) { dwFullPathLen = GetFullPathNameW(pwcsUsersName, _MAX_PATH, awcsFullName,&pwcsFile); if (dwFullPathLen == 0) { DWORD dwErr = GetLastError(); // In some circumstances (name == " ", for instance), // GetFullPathNameW can return 0 and GetLastError returns 0. // We want to return STG_E_INVALIDNAME for these. if (dwErr != NOERROR) { olErr(EH_Err, Win32ErrorToScode(dwErr)); } else { olErr(EH_Err, STG_E_INVALIDNAME); } } else if (dwFullPathLen > _MAX_PATH) olErr(EH_Err, STG_E_PATHNOTFOUND); } //----------------------------------------- // Switch on STGFMT_ // STORAGE, DOCFILE, FILE, ANY // switch(stgfmt) { case STGFMT_FILE: { olChk( NFFOpen( awcsFullName, grfMode, NFFOPEN_NORMAL, fCreateAPI, riid, ppObjectOpen) ); } // case STGFMT_FILE break; case STGFMT_ANY: { DWORD stgfmt2=STGFMT_STORAGE; // // Attempting to CREATE a Storage with STGFMT_ANY is ambiguous, // On NTFS STGFMT_FILE could be appropriate, // and is therefore invalid. // if (fCreateAPI) olChk (STG_E_INVALIDPARAMETER); // // If IsNffAppropriate() returns S_OK use STGFMT_FILE // If it returns STG_E_INVALIDFUNCTION try storage (FAT-FS or Docfile). // Any other Error, bubble back to the user // sc = CNtfsStorage::IsNffAppropriate( pwcsUsersName ); if( SUCCEEDED( sc ) ) { stgfmt2 = STGFMT_FILE; } else { if( STG_E_INVALIDFUNCTION == sc ) stgfmt2 = STGFMT_STORAGE; else olChk( sc ); } sc = DfOpenStorageEx (pwcsUsersName, fCreateAPI, grfMode, stgfmt2, grfAttrs, pStgOptions, reserved, riid, ppObjectOpen); olChk(sc); } // case STGFMT_ANY; break; case STGFMT_STORAGE: case STGFMT_DOCFILE: // GetFullPathName has not yet been called. { IStorage *pstg = NULL; ULONG ulSectorSize = 0; if( fCreateAPI ) { if (grfAttrs & FILE_ATTRIBUTE_TEMPORARY) // create temp file pwcsUsersName = NULL; olChk( DfCreateDocfile (pwcsUsersName, NULL, grfMode, NULL, pStgOptions ? pStgOptions->ulSectorSize : 512, grfAttrs, &pstg)); } else olChk( DfOpenDocfile (pwcsUsersName, NULL, NULL, grfMode, NULL, 0, &ulSectorSize, grfAttrs, &pstg)); if( IID_IStorage != riid ) { sc = pstg->QueryInterface( riid, ppObjectOpen ); pstg->Release(); if (fCreateAPI && !SUCCEEDED(sc) && pwcsUsersName != NULL) { DeleteFileW (pwcsUsersName); //delete newly create file } } else { *ppObjectOpen = pstg; if (pStgOptions != NULL && !fCreateAPI) pStgOptions->ulSectorSize = ulSectorSize; } olChk(sc); } // case STGFMT_DOCFILE break; default: olErr (EH_Err, STG_E_INVALIDPARAMETER); break; } EH_Err: return sc; }; //+--------------------------------------------------------------------------- // // Function: StgCreateStorageEx, public // // Synopsis: Creates a storage or stream object // // Arguments: [pwcsName] - pathname of file // [grfMode] - open mode flags // [stgfmt] - storage format // [grfAttrs] - reserved // [pSecurity] - reserved // [pTransaction] - reserved // [riid] - GUID of interface pointer to return // [ppObjectOpen] - interface pointer to return // // Returns: Appropriate status code // // History: 12-Jul-95 HenryLee Created // //---------------------------------------------------------------------------- STDAPI StgCreateStorageEx (const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, // enum DWORD grfAttrs, // reserved STGOPTIONS * pStgOptions, void * reserved, REFIID riid, void ** ppObjectOpen) { HRESULT sc = S_OK; WCHAR awcsTmpPath[_MAX_PATH]; olDebugOut((DEB_TRACE, "In StgCreateStorageEx(%ws, %p, %p, %p, %p)\n", pwcsName, grfMode, stgfmt, riid, ppObjectOpen)); olChk(ValidatePtrBuffer(ppObjectOpen)); *ppObjectOpen = NULL; if (reserved != NULL) olErr (EH_Err, STG_E_INVALIDPARAMETER); olChk( ValidateGrfAttrs (grfAttrs, stgfmt)); olChk( ValidateGrfMode( grfMode, TRUE ) ); olChk( VerifyPerms( grfMode, TRUE ) ); if (pStgOptions != NULL) olChk( ValidateStgOptions(pStgOptions, stgfmt, TRUE)); if (stgfmt == STGFMT_FILE) { if (pwcsName != NULL) { olChk (ValidateNameW (pwcsName, _MAX_PATH)); } else { olChk (GetNFFTempName (pwcsName, awcsTmpPath)); pwcsName = awcsTmpPath; //Add the STGM_CREATE flag so we don't fail with //STG_E_FILEALREADYEXISTS when we see that the file already exists //later. grfMode |= STGM_CREATE; grfAttrs |= FILE_ATTRIBUTE_TEMPORARY; } } if (stgfmt == STGFMT_DOCFILE && pStgOptions != NULL && pStgOptions->usVersion >= 2 && pStgOptions->pwcsTemplateFile != NULL) { DWORD dwAttrs = GetFileAttributes (pStgOptions->pwcsTemplateFile); if (dwAttrs == 0xFFFFFFFF) olChk (WIN32_SCODE (GetLastError())); if (dwAttrs & FILE_ATTRIBUTE_ENCRYPTED) { DWORD dwErr = DuplicateEncryptionInfoFile( pStgOptions->pwcsTemplateFile, pwcsName, grfMode & STGM_CREATE ? CREATE_ALWAYS : CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (dwErr != ERROR_SUCCESS) olChk (WIN32_SCODE(dwErr)); grfAttrs |= FILE_ATTRIBUTE_ENCRYPTED; } } olChk (DfOpenStorageEx (pwcsName, TRUE, grfMode, stgfmt, grfAttrs, pStgOptions, reserved, riid, ppObjectOpen)); olDebugOut((DEB_TRACE, "Out StgCreateStorageEx => %p\n", *ppObjectOpen)); EH_Err: return sc; } //+--------------------------------------------------------------------------- // // Function: StgOpenStorageEx // // Synopsis: Open storage and stream objects // // Arguments: [pwcsName] - pathanme of the file // [grfMode] - open mode flags // [grfAttrs] - reserved // [stgfmt] - storage format // [pSecurity] - reserved // [pTransaction] - reserved // [riid] - GUID of interface pointer to return // [ppObjectOpen] - interface pointer to return // Returns: Appropriate status code // // History: 12-Jul-95 HenryLee Created // //---------------------------------------------------------------------------- STDAPI StgOpenStorageEx (const WCHAR *pwcsName, DWORD grfMode, DWORD stgfmt, // enum DWORD grfAttrs, // reserved STGOPTIONS * pStgOptions, void * reserved, REFIID riid, void ** ppObjectOpen) { HRESULT sc = S_OK; olDebugOut((DEB_TRACE, "In StgOpenStorageEx(%ws, %p, %p, %p, %p)\n", pwcsName, grfMode, stgfmt, riid, ppObjectOpen)); olChk(ValidatePtrBuffer(ppObjectOpen)); *ppObjectOpen = NULL; if (reserved != NULL) olErr (EH_Err, STG_E_INVALIDPARAMETER); olChk (ValidateNameW (pwcsName, _MAX_PATH)); olChk( ValidateGrfAttrs (grfAttrs, stgfmt)); olChk( ValidateGrfMode( grfMode, FALSE ) ); olChk( VerifyPerms( grfMode, TRUE ) ); if (pStgOptions != NULL) olChk( ValidateStgOptions(pStgOptions, stgfmt, FALSE)); olChk (DfOpenStorageEx (pwcsName, FALSE, grfMode, stgfmt, grfAttrs, pStgOptions, reserved, riid, ppObjectOpen)); olDebugOut((DEB_TRACE, "Out StgOpenStorageEx => %p\n", *ppObjectOpen)); EH_Err: return sc; } //+--------------------------------------------------------------------------- // // Function: ValidateGrfMode // // Synopsis: Sanity checking for the grfMode. (all implementations) // // Arguments: [grfMode] -- grfMode to check // [fCreateAPI] -- Called from CreateStorage vs. OpenStorage. // // Returns: Appropriate status code // // History: 30-Mar-98 BChapman Created // //---------------------------------------------------------------------------- SCODE ValidateGrfMode( DWORD grfMode, BOOL fCreateAPI ) { HRESULT sc=S_OK; // If there are any invalid bits set (error) if( 0 != ( grfMode & ~( STGM_DIRECT | // 0 STGM_TRANSACTED | // 1 0000 STGM_SIMPLE | // 800 0000 STGM_READ | // 0 STGM_WRITE | // 1 STGM_READWRITE | // 2 STGM_SHARE_DENY_NONE | // 40 STGM_SHARE_DENY_READ | // 30 STGM_SHARE_DENY_WRITE | // 20 STGM_SHARE_EXCLUSIVE | // 10 STGM_PRIORITY | // 4 0000 STGM_DELETEONRELEASE | // 400 0000 STGM_NOSCRATCH | // 10 0000 STGM_CREATE | // 1000 STGM_CONVERT | // 2 0000 STGM_FAILIFTHERE | // 0 STGM_DIRECT_SWMR | STGM_NOSNAPSHOT ) ) ) // 20 0000 { olErr( EH_Err, STG_E_INVALIDFLAG ); } // If you Create for ReadOnly (error) if( fCreateAPI && ( ( grfMode & STGM_RDWR ) == STGM_READ ) ) olErr( EH_Err, STG_E_INVALIDFLAG ); // if you Open/Create for Convert And DeleteOnRelease (error) if( ( grfMode & ( STGM_DELETEONRELEASE | STGM_CONVERT ) ) == ( STGM_DELETEONRELEASE | STGM_CONVERT ) ) { olErr(EH_Err, STG_E_INVALIDFLAG); } if( grfMode & STGM_SIMPLE ) { if( fCreateAPI ) { // If you Create Simple it must be exactly this way. if( grfMode != ( STGM_SIMPLE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE ) ) olErr( EH_Err, STG_E_INVALIDFLAG ); } else { // If you Open Simple it must be one of these two ways. if( grfMode != (STGM_SIMPLE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE ) && grfMode != (STGM_SIMPLE | STGM_SHARE_EXCLUSIVE | STGM_READ ) ) olErr( EH_Err, STG_E_INVALIDFLAG ); } } if( !fCreateAPI ) { if (grfMode & STGM_DELETEONRELEASE) olErr(EH_Err, STG_E_INVALIDFUNCTION); if (grfMode & (STGM_CREATE | STGM_CONVERT)) olErr (EH_Err, STG_E_INVALIDPARAMETER); } EH_Err: return sc; } //+--------------------------------------------------------------------------- // // Function: ValidateStgOptions // // Synopsis: Sanity checking for the StgOptions // // Arguments: [pStgOptions] -- options to check // [stgfmt] -- intended storage format // // Returns: Appropriate status code // // History: 30-Mar-98 HenryLee Created // //---------------------------------------------------------------------------- SCODE ValidateStgOptions (STGOPTIONS * pStgOptions, DWORD stgfmt, BOOL fCreate) { #ifdef LARGE_DOCFILE HRESULT sc = S_OK; olChk(ValidatePtrBuffer(pStgOptions)); if (pStgOptions->usVersion > STGOPTIONS_VERSION || pStgOptions->usVersion == 0 || pStgOptions->reserved != 0) { olErr (EH_Err, STG_E_INVALIDPARAMETER); } if (fCreate) { // enable large sector support only for docfiles if (pStgOptions->ulSectorSize != 512 && stgfmt != STGFMT_DOCFILE) { olErr (EH_Err, STG_E_INVALIDPARAMETER); } if (pStgOptions->ulSectorSize != 512 && pStgOptions->ulSectorSize != 4096) /* pStgOptions->ulSectorSize != 8192 && */ /* pStgOptions->ulSectorSize != 16384 && */ /* pStgOptions->ulSectorSize != 32768) */ { olErr (EH_Err, STG_E_INVALIDPARAMETER); } if (pStgOptions->usVersion >= 2) { if (stgfmt != STGFMT_DOCFILE) { olErr (EH_Err, STG_E_INVALIDPARAMETER); } else if (pStgOptions->pwcsTemplateFile != NULL) olChk (ValidatePtrBuffer (pStgOptions->pwcsTemplateFile)); } } else { if (stgfmt != STGFMT_DOCFILE) olErr (EH_Err, STG_E_INVALIDPARAMETER); if (pStgOptions->usVersion >= 2 && pStgOptions->pwcsTemplateFile !=NULL) olErr (EH_Err, STG_E_INVALIDPARAMETER); } EH_Err: #else HRESULT sc = STG_E_INVALIDPARAMETER; #endif return sc; } //+--------------------------------------------------------------------------- // // Member: GetNFFTempName, public // // Synopsis: returns a filename for temporary NSS files // // Arguments: [pwcsFileName] - original file name // [ppwcsTmpName] - output temporary name // // Returns: Appropriate status code // // History: 01-Jul-97 HenryLee Created // //---------------------------------------------------------------------------- HRESULT GetNFFTempName (const WCHAR *pwcsFileName, WCHAR *awcsTmpName) { HRESULT sc = S_OK; WCHAR awcsDir[_MAX_PATH]; WCHAR *pwcsFile = NULL; // // Create a temp file in pwcsFileName's directory // if (pwcsFileName != NULL) { if (GetFullPathNameW (pwcsFileName, _MAX_PATH, awcsDir, &pwcsFile) == 0) { const DWORD dwErr = GetLastError(); //In some circumstances (name == " ", for instance), // GetFullPathNameW can return 0 and GetLastError returns 0. // We want to return STG_E_INVALIDNAME for these. olErr(EH_Err, (dwErr != NOERROR) ? Win32ErrorToScode(dwErr) : STG_E_INVALIDNAME); } else if (pwcsFile) *pwcsFile = L'\0'; } else { DWORD cch; // Create a temp file for StgCreateDocfile (NULL name) // // try %tmp%, %temp% cch = GetTempPath(_MAX_PATH, awcsDir); if(0 == cch || cch > _MAX_PATH) { // finally use current directory awcsDir[0] = L'.'; awcsDir[1] = L'\0'; } } if (GetTempFileNameW (awcsDir, TEMPFILE_PREFIX, 0, awcsTmpName)==FALSE) olErr (EH_Err, Win32ErrorToScode(GetLastError())); EH_Err: return sc; }