//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1994. // // File: odocstg.cxx // // Contents: IStorage for compound docs on OFS implementation // // History: 07-Feb-94 PhilipLa Created // // Notes: BUGBUG [mikese] Many of these routines are identical // to those for COfsDirStorage. We should create a common // base class to contain the common code. // //---------------------------------------------------------------------------- #include "headers.cxx" #pragma hdrstop #include #include "odsenm.hxx" #include "odocstm.hxx" #include #include //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::QueryInterface, public // // Synopsis: Returns an object for the requested interface // // Arguments: [iid] - Interface ID // [ppvObj] - Object return // // Returns: Appropriate status code // // Modifies: [ppvObj] // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::QueryInterface(REFIID iid, void **ppvObj) { SCODE sc; ssDebugOut((DEB_TRACE, "In COfsDocStorage::QueryInterface:%p(riid, %p)\n", this, ppvObj)); if (!IsValidIid(iid)) olErr(EH_Err, STG_E_INVALIDPARAMETER); ssChk(Validate()); if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown)) { *ppvObj = (IStorage *)this; COfsDocStorage::AddRef(); } else if (IsEqualIID(iid, IID_IPropertySetStorage)) { *ppvObj = (IPropertySetStorage *)this; COfsDocStorage::AddRef(); } else if (IsEqualIID(iid, IID_INativeFileSystem)) { *ppvObj = (INativeFileSystem *)this; COfsDocStorage::AddRef(); } else if (IsEqualIID(iid, IID_IAccessControl)) { // BUGBUG need to artifically restrict to root & property storages *ppvObj = (IAccessControl *)this; COfsDocStorage::AddRef(); } else if (IsEqualIID(iid, IID_IMarshal) && (_grfMode & STGM_DELETEONRELEASE) == 0) { *ppvObj = (IMarshal *)this; COfsDocStorage::AddRef(); } else if (IsEqualIID(iid, IID_IStorageReplica)) { *ppvObj = (IStorageReplica *)this; COfsDocStorage::AddRef(); } else { sc = E_NOINTERFACE; *ppvObj = NULL; } ssDebugOut((DEB_TRACE, "Out COfsDocStorage::QueryInterface => %p\n", *ppvObj)); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::COfsDocStorage, public // // Synopsis: Empty object construction // // History: 07-Feb-94 PhilipLa Created // 24-Mar-95 HenryLee Store drive letter to fix Stat problem // //---------------------------------------------------------------------------- #pragma warning(disable: 4355) COfsDocStorage::COfsDocStorage(void) : CPropertySetStorage(this) #pragma warning(default: 4355) { ssDebugOut((DEB_ITRACE, "In COfsDocStorage::COfsDocStorage:%p()\n", this)); _sig = 0; _wcDrive = L'\0'; ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::COfsDocStorage\n")); ENLIST_TRACKING(COfsDocStorage); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::InitFromHandle, public // // Synopsis: From-handle constructor // // Arguments: [h] - Handle of directory // [grfMode] - Mode of handle // [fRoot] - TRUE => storage is a root storage // // Returns: Appropriate status code // // History: 07-Feb-94 PhilipLa Created // 24-Mar-95 HenryLee Store drive letter to fix Stat problem // // Notes: Takes a new reference on the handle // //---------------------------------------------------------------------------- SCODE COfsDocStorage::InitFromHandle(HANDLE h, WCHAR const *pwcsName, DWORD grfMode, BOOL fRoot) { SCODE sc; ssDebugOut((DEB_ITRACE, "In COfsDocStorage::InitFromHandle:%p(%p, %lX)\n", this, h, grfMode)); ssChk(ValidateMode(grfMode)); _h = h; ssAssert(_h != NULL); _grfMode = grfMode; _sig = COfsDocStorage_SIG; _fRoot = fRoot; _wcDrive = GetDriveLetter (pwcsName); ssChk(InitAccessControl(_h, _grfMode, FALSE, NULL)); ssChk(InitNtHandleMarshal(_h, _grfMode, STGFMT_DOCUMENT)); ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::InitFromHandle\n")); EH_Err: return sc; } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::InitFromPath, public // // Synopsis: From-path constructor // // Arguments: [pwcsName] - Name of document // [grfMode] - Mode // [fCreate] - Create or open // [pssSecurity] - Security // [fRoot] - TRUE => root storage // // Returns: Appropriate status code // // History: 07-Feb-94 PhilipLa Created // 24-Mar-95 HenryLee Store drive letter to fix Stat problem // //---------------------------------------------------------------------------- SCODE COfsDocStorage::InitFromPath(HANDLE hParent, WCHAR const *pwcsName, DWORD grfMode, CREATEOPEN co, LPSECURITY_ATTRIBUTES pssSecurity, BOOL fRoot) { SCODE sc; ssDebugOut((DEB_ITRACE, "In COfsDocStorage::InitFromPath:%p(" "%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName, grfMode, co, pssSecurity)); ssChk(ValidateMode(grfMode)); // BUGBUG: [mikese] This class is used for both root documents and // embeddings, so FD_STORAGE is not always correct. ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co, FD_STORAGE, (LPSECURITY_ATTRIBUTES)pssSecurity, &_h)); _grfMode = grfMode; _sig = COfsDocStorage_SIG; _fRoot = fRoot; _wcDrive = GetDriveLetter (pwcsName); ssChk(InitAccessControl(_h, _grfMode, FALSE, NULL)); ssChk(InitNtHandleMarshal(_h, _grfMode, STGFMT_DOCUMENT)); ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::InitFromPath\n")); EH_Err: return sc; } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::~COfsDocStorage, public // // Synopsis: Destructor // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- COfsDocStorage::~COfsDocStorage(void) { ssDebugOut((DEB_ITRACE, "In COfsDocStorage::~COfsDocStorage()\n")); _sig = COfsDocStorage_SIGDEL; //BUGBUG: Replace with real delete on release support? if ((HANDLE)_h != NULL && (_grfMode & STGM_DELETEONRELEASE)) { SCODE sc = DestroyTree(NULL, NULL, _h, FD_STORAGE); if (!SUCCEEDED(sc)) { ssDebugOut ((DEB_ERROR, " DestroyTree => %x\n", sc)); ssVerSucc(sc); } } ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::~COfsDocStorage\n")); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::CreateStream, public // // Synopsis: Creates a stream // // Arguments: [pwcsName] - Name // [grfMode] - Permissions // [reserved1] // [reserved2] // [ppstm] - Stream return // // Returns: Appropriate status code // // Modifies: [ppstm] // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::CreateStream(WCHAR const *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm) { SCODE sc; SafeCOfsDocStream pst; WCHAR *pwcsNewName = NULL; ssDebugOut((DEB_TRACE, "In COfsDocStorage::CreateStream:%p(" "%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode, reserved1, reserved2, ppstm)); ssChk(Validate()); if (reserved1 != 0 || reserved2 != 0) ssErr(EH_Err, STG_E_INVALIDPARAMETER); if (grfMode & (STGM_CONVERT | STGM_PRIORITY | STGM_DELETEONRELEASE)) ssErr(EH_Err, STG_E_INVALIDFUNCTION); #ifdef TRANSACT_OLE if (_grfMode & STGM_TRANSACTED) { if (grfMode & (STGM_CREATE | STGM_TRANSACTED)) ssErr(EH_Err, STG_E_INVALIDPARAMETER); if ((grfMode & STGM_SHARE_EXCLUSIVE) == 0) ssErr(EH_Err, STG_E_INVALIDPARAMETER); } #endif ssChk(ValidateOutPtrBuffer(ppstm)); *ppstm = NULL; pst.Attach(new COfsDocStream()); ssMem((COfsDocStream *)pst); ssMem(pwcsNewName = MakeStreamName(pwcsName)); #ifdef TRANSACT_OLE ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_CREATE, (_grfMode & STGM_TRANSACTED) == STGM_TRANSACTED, NULL)); #else ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_CREATE, FALSE, NULL)); #endif TRANSFER_INTERFACE(pst, IStream, ppstm); ssDebugOut((DEB_TRACE, "Out COfsDocStorage::CreateStream => %p\n", *ppstm)); EH_Err: delete pwcsNewName; return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::OpenStream, public // // Synopsis: Opens an existing stream // // Arguments: [pwcsName] - Name // [reserved1] // [grfMode] - Permissions // [reserved2] // [ppstm] - Stream return // // Returns: Appropriate status code // // Modifies: [ppstm] // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::OpenStream(WCHAR const *pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm) { SCODE sc; SafeCOfsDocStream pst; WCHAR *pwcsNewName = NULL; ssDebugOut((DEB_TRACE, "COfsDocStorage::OpenStream:%p(" "%ws, %p, %lX, %lu, %p)\n", this, pwcsName, reserved1, grfMode, reserved2, ppstm)); ssChk(ValidateSimple()); ssChk(Validate()); if (reserved1 != 0 || reserved2 != 0) ssErr(EH_Err, STG_E_INVALIDPARAMETER); if (grfMode & (STGM_CREATE | STGM_CONVERT)) ssErr(EH_Err, STG_E_INVALIDFLAG); if (grfMode & (STGM_PRIORITY | STGM_DELETEONRELEASE)) ssErr(EH_Err, STG_E_INVALIDFUNCTION); #ifdef TRANSACT_OLE if (_grfMode & STGM_TRANSACTED) { if (grfMode & (STGM_CREATE | STGM_TRANSACTED)) ssErr(EH_Err, STG_E_INVALIDPARAMETER); if ((grfMode & STGM_SHARE_EXCLUSIVE) == 0) ssErr(EH_Err, STG_E_INVALIDPARAMETER); } #endif ssChk(ValidateOutPtrBuffer(ppstm)); *ppstm = NULL; pst.Attach(new COfsDocStream()); ssMem((COfsDocStream *)pst); ssMem(pwcsNewName = MakeStreamName(pwcsName)); #ifdef TRANSACT_OLE ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_OPEN, (_grfMode & STGM_TRANSACTED) == STGM_TRANSACTED, NULL)); #else ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_OPEN, FALSE, NULL)); #endif TRANSFER_INTERFACE(pst, IStream, ppstm); ssDebugOut((DEB_TRACE, "Out COfsDocStorage:: OpenStream => %p\n", *ppstm)); EH_Err: delete pwcsNewName; return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::CreateStorage, public // // Synopsis: Creates a child storage // // Arguments: [pwcsName] - Name // [grfMode] - Permissions // [dwStgFmt] - Type of storage to create // [pssSecurity] - Security // [ppstg] - New storage return // // Returns: Appropriate status code // // Modifies: [ppstg] // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::CreateStorage( WCHAR const *pwcsName, DWORD grfMode, DWORD dwStgFmt, LPSTGSECURITY pssSecurity, IStorage **ppstg) { SCODE sc; SafeCOfsDocStorage pstg; ssDebugOut((DEB_TRACE, "In COfsDocStorage::CreateStorage:%p(" "%ws, %lX, %lu, %p, %p)\n", this, pwcsName, grfMode, dwStgFmt, pssSecurity, ppstg)); ssChk(ValidateSimple()); ssChk(Validate()); ssChk(VerifyStgFmt(dwStgFmt)); ssAssert(_h != NULL); ssChk(ValidateOutPtrBuffer(ppstg)); *ppstg = NULL; //FORCE_READ(grfMode); pstg.Attach(new COfsDocStorage()); ssMem((COfsDocStorage *)pstg); ssChk(pstg->InitFromPath(_h, pwcsName, grfMode, CO_CREATE, (LPSECURITY_ATTRIBUTES) pssSecurity, FALSE)); if ((grfMode & STGM_EDIT_ACCESS_RIGHTS) && // child is editing ACLS (_grfMode & STGM_TRANSACTED)) // parent is transacted { InsertChild (pstg); // hold on to the child for pstg->AddRef(); // nested transactions } TRANSFER_INTERFACE(pstg, IStorage, ppstg); ssDebugOut((DEB_TRACE, "Out COfsDocStorage::CreateStorage => %p\n",*ppstg)); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::OpenStorage, public // // Synopsis: Gets an existing child storage // // Arguments: [pwcsName] - Name // [pstgPriority] - Priority reopens // [grfMode] - Permissions // [snbExclude] - Priority reopens // [reserved] // [ppstg] - Storage return // // Returns: Appropriate status code // // Modifies: [ppstg] // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::OpenStorage(WCHAR const *pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstg) { SCODE sc; SafeCOfsDocStorage pstg; ssDebugOut((DEB_TRACE, "In COfsDocStorage::OpenStorage:%p(" "%ws, %p, %lX, %p, %lu, %p)\n", this, pwcsName, pstgPriority, grfMode, snbExclude, reserved, ppstg)); ssChk(ValidateSimple()); ssChk(Validate()); if (pstgPriority != NULL || snbExclude != NULL || reserved != 0) ssErr(EH_Err, STG_E_INVALIDPARAMETER); if (grfMode & (STGM_CREATE | STGM_CONVERT)) ssErr(EH_Err, STG_E_INVALIDFLAG); ssChk(ValidateOutPtrBuffer(ppstg)); *ppstg = NULL; ssAssert(_h != NULL); // The only thing we can open inside a document is an embedding pstg.Attach(new COfsDocStorage()); ssMem((COfsDocStorage *)pstg); ssChk(pstg->InitFromPath(_h, pwcsName, grfMode, CO_OPEN, NULL, FALSE)); if (snbExclude != NULL) ssChk(pstg->ExcludeEntries(snbExclude)); if ((grfMode & STGM_EDIT_ACCESS_RIGHTS) && // child is editing ACLS (_grfMode & STGM_TRANSACTED)) // parent is transacted { InsertChild (pstg); // hold on to the child for pstg->AddRef(); // nested transactions } TRANSFER_INTERFACE(pstg, IStorage, ppstg); ssDebugOut((DEB_TRACE, "Out COfsDocStorage::OpenStorage => %p\n", *ppstg)); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::CopyTo, public // // Synopsis: Makes a copy of a storage // // Arguments: [ciidExclude] - Length of rgiid array // [rgiidExclude] - Array of IIDs to exclude // [snbExclude] - Names to exclude // [pstgDest] - Parent of copy // // Returns: Appropriate status code // // History: 07-Feb-94 PhilipLa Copied from DrewB's stuff // // Notes: BUGBUG - This function operates recursively and so // is bounded by stack space // It could also be optimized to recognize special cases // of copying (like treating a docfile as a file) // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::CopyTo(DWORD ciidExclude, IID const *rgiidExclude, SNB snbExclude, IStorage *pstgDest) { ssDebugOut((DEB_TRACE, "In COfsDocStorage::CopyTo:%p(%lu, %p, %p, %p)\n", this, ciidExclude, rgiidExclude, snbExclude, pstgDest)); SCODE sc; ULONG i; BOOL fCopyStorage = TRUE; BOOL fCopyStreams = TRUE; STATSTG stat; STATSTG statDest; DWORD grfModeFrom; DWORD grfModeTo; DWORD grfModeTo2; ssChk(ValidateSimple()); ssChk(Validate()); if (!IsValidInterface(pstgDest)) olErr(EH_Err, STG_E_INVALIDPARAMETER); // Stat the source to obtain the open mode (and also class id and // state bits). ssChk(Stat(&stat, STATFLAG_NONAME)); // The open mode for subelements of the source is derived from that // of the root. We preserve the sharing mode part, force read only // and direct (because we do not want a nested transaction). grfModeFrom = (stat.grfMode & (STGM_SHARE_EXCLUSIVE| STGM_SHARE_DENY_READ| STGM_SHARE_DENY_WRITE| STGM_SHARE_DENY_NONE)) | STGM_READ | STGM_DIRECT; // Stat the destination to obtain the open mode ssChk(pstgDest->Stat(&statDest,STATFLAG_NONAME)); // The open mode for subelements of the destination is derived from that // of the root. We force direct mode, since we do not want nested // transactions. grfModeTo = statDest.grfMode & (~(STGM_TRANSACTED | STGM_DELETEONRELEASE)); // Copy class ID and state bits if the destination supports them // BUGBUG [mikese] Do we really need to do this, since won't these // get copied as part of the system properties? sc = GetScode(pstgDest->SetClass(stat.clsid)); if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION) olErr(EH_Err, sc); sc = GetScode(pstgDest->SetStateBits(stat.grfStateBits, 0xffffffff)); if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION) olErr(EH_Err, sc); // Check IID exclusions for (i = 0; i < ciidExclude; i++) { if (IsEqualIID(rgiidExclude[i], IID_IStorage)) { fCopyStorage = FALSE; } else if ( IsEqualIID ( rgiidExclude[i], IID_IStream ) ) { fCopyStreams = FALSE; } } sc = S_OK; if (fCopyStorage) { SCODE scFinal; WCHAR pwcsName[MAXIMUM_FILENAME_LENGTH]; FILEDIR fd; CNtEnum nte; CDfName dfn; BOOL fOfs; HANDLE hDest = NULL; // henrylee: BUGBUG this is a hack to detect copyto a docfile INativeFileSystem *pINFS; if (SUCCEEDED(pstgDest->QueryInterface (IID_INativeFileSystem, (void**) &pINFS))) { pINFS->GetHandle(&hDest); pINFS->Release(); grfModeTo2 = grfModeTo; fOfs = TRUE; } else { // permissions for docfile compatibility grfModeTo = STGM_WRITE | STGM_SHARE_EXCLUSIVE; grfModeTo2 = STGM_READWRITE | STGM_SHARE_EXCLUSIVE; fOfs = FALSE; } scFinal = S_OK; ssAssert(_h != NULL); ssChk(nte.InitFromHandle(_h, TRUE)); for (;;) { sc = nte.Next(&stat, pwcsName, NTE_BUFFERNAME, &fd); if (sc == S_FALSE) break; else if (FAILED(sc)) olErr(EH_Err, sc); // Ignore . and .. if (!wcscmp(pwcsName, L".") || !wcscmp(pwcsName, L"..")) continue; // BUGBUG: [mikese] What's wrong with raw pwcsName? dfn.Set(pwcsName); if (snbExclude == NULL || !NameInSNB(&dfn, snbExclude)) { if ( stat.type == STGTY_STORAGE ) { SafeIStorage pstgFrom, pstgTo; STATSTG statTo; olHChkTo(EH_Next, OpenStorage(pwcsName, NULL, grfModeFrom, NULL, NULL, &pstgFrom)); // We know that the source must be an embedding (STGFMT_DOCUMENT) sc = pstgDest->CreateStorage( pwcsName, grfModeTo | STGM_FAILIFTHERE, STGFMT_DOCUMENT, NULL, &pstgTo ); if (FAILED(sc)) { if (sc == STG_E_FILEALREADYEXISTS) { // Try to open rather than creating sc = pstgDest->OpenStorage( pwcsName, NULL, grfModeTo2, NULL, NULL, &pstgTo ); if (SUCCEEDED(sc)) { sc = pstgTo->Stat ( &statTo, STATFLAG_NONAME ); if (FAILED(sc) || statTo.STATSTG_dwStgFmt != STGFMT_DOCUMENT) { sc = STG_E_INVALIDFUNCTION; } } } } if (SUCCEEDED(sc)) sc = pstgFrom->CopyTo( ciidExclude, rgiidExclude, snbExclude, pstgTo); } else if ( (stat.type == STGTY_STREAM) && fCopyStreams ) { SafeIStream pstmTo, pstmFrom; static ULARGE_INTEGER uli = { 0xFFFFFFFF, 0xFFFFFFFF }; olHChkTo(EH_Next, OpenStream ( pwcsName, NULL, grfModeFrom, 0, &pstmFrom ) ); // BUGBUG instead of overwriting, we create another // stream and rename -- really need transacted mode sc = pstgDest->CreateStream ( pwcsName, grfModeTo | STGM_FAILIFTHERE, 0, 0, &pstmTo ); if (sc == STG_E_FILEALREADYEXISTS) { WCHAR awcsName[MAXIMUM_FILENAME_LENGTH]; wcscpy (awcsName, pwcsName); if (fOfs) awcsName[0] = L'@'; IStream *pstm; olHChkTo(EH_Next, pstgDest->CreateStream ( awcsName, grfModeTo|STGM_CREATE, 0, 0, &pstm )); sc = pstmFrom->CopyTo ( pstm, uli, NULL, NULL ); pstm->Release(); if (SUCCEEDED(sc) && fOfs) { ssAssert (hDest != NULL); WCHAR awcsSave[MAXIMUM_FILENAME_LENGTH+4]; wcscpy (awcsSave, pwcsName); wcscat (awcsSave, L".old"); sc = RenameChild (hDest, pwcsName, awcsSave); if (!SUCCEEDED(sc)) { sc = DestroyTree (hDest, awcsSave, NULL, FD_FILE); sc = RenameChild (hDest, pwcsName, awcsSave); } olHChkTo(EH_Next,RenameChild (hDest, awcsName, pwcsName)); sc = DestroyTree (hDest, awcsSave, NULL, FD_FILE); } else if (fOfs) olHChkTo(EH_Next,pstgDest->DestroyElement (awcsName)); } else if ( SUCCEEDED(sc) ) { sc = pstmFrom->CopyTo ( pstmTo, uli, NULL, NULL ); } } EH_Next: if (FAILED(sc)) scFinal = sc; } } sc = scFinal; } EH_Err: ssDebugOut((DEB_TRACE, "Out COfsDocStorage::CopyTo\n")); return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::MoveElementTo, public // // Synopsis: Move an element of a storage to another storage // // Arguments: [pwcsName] - Current name // [ptcsNewName] - New name // // Returns: Appropriate status code // // Algorithm: Open source as storage or stream (whatever works) // Create appropriate destination // Copy source to destination // Set create time of destination equal to create time of source // If appropriate, delete source // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::MoveElementTo(WCHAR const *pwcsName, IStorage *pstgParent, WCHAR const *ptcsNewName, DWORD grfFlags) { SCODE sc; ssDebugOut((DEB_TRACE, "In COfsDocStorage::MoveElementTo:%p(" "%ws, %p, %ws, %lu)\n", this, pwcsName, pstgParent, ptcsNewName, grfFlags)); ssChk(ValidateSimple()); ssChk(Validate()); ssChk(VerifyMoveFlags(grfFlags)); sc = GenericMoveElement(this, pwcsName, pstgParent, ptcsNewName, grfFlags); ssDebugOut((DEB_TRACE, "Out COfsDocStorage::MoveElementTo => %lX\n", sc)); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::Commit, public // // Synopsis: Commits transacted changes // // Arguments: [dwFlags] - DFC_* // // Returns: Appropriate status code // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::Commit(DWORD dwFlags) { SCODE sc = S_OK; ssDebugOut((DEB_TRACE, "In COfsDocStorage::Commit:%p(%lX)\n", this, dwFlags)); #ifdef TRANSACT_OLE if (_grfMode & STGM_TRANSACTED) { IO_STATUS_BLOCK iosb; COMMIT_PARAMETERS ftci = {FALSE, dwFlags}; NTSTATUS nts; if ((dwFlags & ~(STGC_DEFAULT | STGC_ONLYIFCURRENT)) != 0) ssErr (EH_Err, STG_E_INVALIDPARAMETER); if (!NT_SUCCESS(nts = NtFsControlFile (_h, NULL, NULL, NULL, &iosb, FSCTL_XOLE_COMMIT, &ftci, sizeof(ftci), NULL, 0))) sc = NtStatusToScode(nts); else sc = S_OK; } #endif // TRANSACT_OLE if (_grfMode & STGM_EDIT_ACCESS_RIGHTS) ssChk(CommitAccessRights(0)); EH_Err: ssDebugOut((DEB_TRACE, "Out COfsDocStorage::Commit => %lX\n",sc)); return ssResult (sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::Revert, public // // Synopsis: Reverts transacted changes // // Returns: Appropriate status code // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::Revert(void) { ssDebugOut((DEB_TRACE, "In COfsDocStorage::Revert:%p\n", this)); SCODE sc = S_OK; ssChk(ValidateSimple()); #ifdef TRANSACT_OLE if (_grfMode & STGM_TRANSACTED) { ssErr(EH_Err, STG_E_INVALIDFUNCTION); IO_STATUS_BLOCK iosb; COMMIT_PARAMETERS ftci = {TRUE, 0L}; NTSTATUS nts; if (!NT_SUCCESS(nts = NtFsControlFile (_h, NULL, NULL, NULL, &iosb, FSCTL_XOLE_COMMIT, &ftci, sizeof(ftci), NULL, 0))) sc = NtStatusToScode(nts); else sc = S_OK; } #endif // TRANSACT_OLE if (_grfMode & STGM_EDIT_ACCESS_RIGHTS) ssChk(RevertAccessRights()); ssDebugOut((DEB_TRACE, "Out COfsDocStorage::Revert => %lX\n",sc)); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::EnumElements, public // // Synopsis: Starts an iterator // // Arguments: [reserved1] // [reserved2] // [reserved3] // [ppenm] - Enumerator return // // Returns: Appropriate status code // // Modifies: [ppenm] // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::EnumElements(DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenm) { SCODE sc; SafeCOfsDirEnum pde; ssDebugOut((DEB_TRACE, "In COfsDocStorage::EnumElements:%p(" "%lu, %p, %lu, %p)\n", this, reserved1, reserved2, reserved3, ppenm)); ssChk(ValidateSimple()); if (ppenm == NULL) ssErr (EH_Err, STG_E_INVALIDPOINTER) // missing ';' macro problem else ssChk(ValidateOutPtrBuffer(ppenm)); *ppenm = NULL; if (reserved1 != 0 || reserved2 != NULL || reserved3 != 0) olErr(EH_Err, STG_E_INVALIDPARAMETER); ssChk(Validate()); pde.Attach(new COfsDirEnum(TRUE)); olMem((COfsDirEnum *)pde); ssAssert(_h != NULL); ssChk(pde->InitFromHandle(_h)); TRANSFER_INTERFACE(pde, IEnumSTATSTG, ppenm); ssDebugOut((DEB_TRACE, "Out COfsDocStorage::EnumElements => %p\n", *ppenm)); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::DestroyElement, public // // Synopsis: Permanently deletes an element of a storage // // Arguments: [pwcsName] - Name of element // // Returns: Appropriate status code // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::DestroyElement(WCHAR const *pwcsName) { SCODE sc = S_OK; ssDebugOut((DEB_TRACE, "In COfsDocStorage::DestroyElement:%p(%ws)\n", this, pwcsName)); ssChk(ValidateSimple()); ssChk(Validate()); ssAssert(_h != NULL); #ifdef TRANSACT_OLE if (_grfMode & STGM_TRANSACTED) sc = DestroyTree(_h, pwcsName, NULL, FD_STREAM); else #endif sc = DestroyTree(_h, pwcsName, NULL, FD_FILE); ssDebugOut((DEB_TRACE, "Out COfsDocStorage::DestroyElement\n")); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::RenameElement, public // // Synopsis: Renames an element of a storage // // Arguments: [pwcsName] - Current name // [pwcsNewName] - New name // // Returns: Appropriate status code // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::RenameElement(WCHAR const *pwcsName, WCHAR const *pwcsNewName) { //BUGBUG: Reimplement? SCODE sc; ssDebugOut((DEB_TRACE, "In COfsDocStorage::RenameElement:%p(%ws, %ws)\n", this, pwcsName, pwcsNewName)); #ifdef TRANSACT_OLE if (_grfMode & STGM_TRANSACTED) ssErr (EH_Err, STG_E_INVALIDFUNCTION); #endif ssChk(ValidateSimple()); ssChk(Validate()); // pwcsName is checked by GetFileOrDirHandle ssChk(CheckFdName(pwcsNewName)); ssAssert(_h != NULL); sc = RenameChild(_h, pwcsName, pwcsNewName); ssDebugOut((DEB_TRACE, "Out COfsDocStorage::RenameElement\n")); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::SetElementTimes, public // // Synopsis: Sets element time stamps // // Arguments: [pwcsName] - Name // [pctime] - Create time // [patime] - Access time // [pmtime] - Modify time // // Returns: Appropriate status code // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::SetElementTimes(WCHAR const *pwcsName, FILETIME const *pctime, FILETIME const *patime, FILETIME const *pmtime) { SCODE sc; SafeNtHandle h; ssDebugOut((DEB_TRACE, "In COfsDocStorage::SetElementTimes:%p(" "%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime)); if (pwcsName != NULL) ssChk(ValidateSimple()); ssChk(Validate()); ssAssert(_h != NULL); if (pwcsName != NULL) { #ifdef TRANSACT_OLE if (_grfMode & STGM_TRANSACTED) ssErr (EH_Err, STG_E_INVALIDFUNCTION); #endif ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_WRITE, &h,NULL,NULL,NULL)); sc = SetTimes(h, pctime, patime, pmtime); } else sc = SetTimes(_h, pctime, patime, pmtime); ssDebugOut((DEB_TRACE, "Out COfsDocStorage::SetElementTimes\n")); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::SetClass, public // // Synopsis: Sets storage class // // Arguments: [clsid] - class id // // Returns: Appropriate status code // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::SetClass(REFCLSID clsid) { SCODE sc = S_OK; ssDebugOut((DEB_TRACE, "In COfsDocStorage::SetClass:%p(clsid)\n", this)); NTSTATUS nts = RtlSetClassId(_h, &clsid); if (!NT_SUCCESS(nts)) sc = NtStatusToScode(nts); ssDebugOut((DEB_TRACE, "Out COfsDocStorage::SetClass => %lX\n", sc)); return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::SetStateBits, public // // Synopsis: Sets state bits // // Arguments: [grfStateBits] - state bits // [grfMask] - state bits mask // // Returns: Appropriate status code // // History: 07-Feb-94 PhilipLa Created // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask) { NTSTATUS nts; SCODE sc = S_OK; IO_STATUS_BLOCK iosb; FILE_OLE_STATE_BITS_INFORMATION fosbi; ssDebugOut((DEB_TRACE, "In COfsDocStorage::SetStateBits:%p(" "%lu, %lu)\n", this, grfStateBits, grfMask)); ssChk(ValidateSimple()); fosbi.StateBits = grfStateBits; fosbi.StateBitsMask = grfMask; nts = NtSetInformationFile(_h, &iosb, &fosbi, sizeof(FILE_OLE_STATE_BITS_INFORMATION), FileOleStateBitsInformation); if (!NT_SUCCESS(nts)) ssErr(EH_Err, NtStatusToScode(nts)); EH_Err: ssDebugOut((DEB_TRACE, "Out COfsDocStorage::SetStateBits => %lX\n", sc)); return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::Stat, public // // Synopsis: Fills in a buffer of information about this object // // Arguments: [pstatstg] - Buffer // // Returns: Appropriate status code // // Modifies: [pstatstg] // // History: 07-Feb-94 PhilipLa Created // 24-Mar-95 HenryLee Set drive letter to fix Stat problem // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag) { SCODE sc; STATSTG stat; FILEDIR fd; ssDebugOut((DEB_TRACE, "In COfsDocStorage::Stat:%p(%p, %lX)\n", this, pstatstg, grfStatFlag)); ssChk(ValidateSimple()); ssChk(VerifyStatFlag(grfStatFlag)); ssChk(Validate()); __try { ssAssert(_h != NULL); stat.clsid = CLSID_NULL; sc = StatNtHandle(_h, grfStatFlag, 0, &stat, NULL, NULL, &fd); if (SUCCEEDED(sc)) { if (stat.pwcsName) if (!_fRoot) { // The name coming back from StatNtHandle is a full // path from the root. We scan forward looking for // the final "\" which delimits the name of the stream. WCHAR *pwcs = stat.pwcsName; WCHAR *pwcsSlash = pwcs; while (*pwcs != L'\0') if (*pwcs++ == L'\\') pwcsSlash = pwcs; // pwcsSlash now points at the name of the stream. Move it // back to the beginning of the block wcscpy (stat.pwcsName, pwcsSlash); } else { // Now we tack on the drive letter to the filename, since // NtQueryInformationFile doesn't return the drive letter, // and NtQueryObject returns something like // "\Device\Harddisk1\Partition1" // HenryLee SetDriveLetter (stat.pwcsName, _wcDrive); } // BUGBUG: Can't put this assert in until we have a way to distinguish // an empty storage from a directory. :-( // ssAssert(fd == FD_STORAGE); stat.grfMode = _grfMode & (STGM_DIRECT | STGM_TRANSACTED | STGM_READ | STGM_WRITE | STGM_READWRITE | STGM_SHARE_DENY_NONE | STGM_SHARE_DENY_READ | STGM_SHARE_DENY_WRITE | STGM_SHARE_EXCLUSIVE | STGM_PRIORITY | STGM_DELETEONRELEASE); stat.cbSize.HighPart = stat.cbSize.LowPart = 0; stat.STATSTG_dwStgFmt = STGFMT_DOCUMENT; *pstatstg = stat; } } __except(EXCEPTION_EXECUTE_HANDLER) { if (stat.pwcsName) ssVerSucc(CoMemFree(stat.pwcsName)); sc = HRESULT_FROM_NT(GetExceptionCode()); } ssDebugOut((DEB_TRACE, "Out COfsDocStorage::Stat\n")); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::ValidateMode, private // // Synopsis: Checks for legal access modes // // Arguments: [grfMode] - Mode // // Returns: Appropriate status code // // History: 09-Jul-94 PhilipLa Created // //---------------------------------------------------------------------------- SCODE COfsDocStorage::ValidateMode(DWORD grfMode) { SCODE sc = S_OK; ssDebugOut((DEB_ITRACE, "In COfsDocStorage::ValidateMode:%p(0x%lX)\n", this, grfMode)); // BUGBUG - Can we simply ignore priority mode? #ifdef TRANSACT_OLE if (grfMode & STGM_TRANSACTED) { if ((grfMode & (STGM_SHARE_DENY_NONE | STGM_SHARE_DENY_READ | STGM_SHARE_DENY_WRITE | STGM_SHARE_EXCLUSIVE)) != STGM_SHARE_DENY_NONE) ssErr (EH_Err, STG_E_INVALIDPARAMETER); if (grfMode & STGM_DELETEONRELEASE) ssErr (EH_Err, STG_E_INVALIDPARAMETER); } #endif if ((grfMode & STGM_CONVERT) != 0) ssErr (EH_Err, STG_E_INVALIDFLAG); ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::ValidateMode => 0x%lX\n", sc)); EH_Err: return sc; } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::ExtValidate, private // // Synopsis: COfsPropSet validation routine // // History: 18-Aug-94 PhilipLa Created // //---------------------------------------------------------------------------- SCODE COfsDocStorage::ExtValidate(void) { return Validate(); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::GetHandle, private from INativeFileSystem // // Synopsis: Get the internal handle // //---------------------------------------------------------------------------- SCODE COfsDocStorage::GetHandle(HANDLE *ph) { *ph = _h; return(S_OK); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::ExcludeEntries, public // // Synopsis: excludes the SNB list after opening // // Arguments: [snbExclude] - zero out these elements // // Returns: Appropriate status code // // History: 09-Aug-95 HenryLee Created // //---------------------------------------------------------------------------- SCODE COfsDocStorage::ExcludeEntries (SNB snbExclude) { SCODE sc = S_OK; IEnumSTATSTG *penm; IStorage *pstg; IStream *pstm; STATSTG sstg; CDfName dfnName; const ULARGE_INTEGER uli = {0, 0}; ssAssert (this != NULL); ssDebugOut((DEB_ITRACE, "In COfsDocStorage::ExcludeEntries(%p)\n", this)); ssChk(EnumElements(0, NULL, 0, &penm)); for (;;) { olChkTo(EH_penm, penm->Next(1, &sstg, NULL)); if (S_FALSE == sc) { sc = S_OK; break; } dfnName.Set (sstg.pwcsName); if (NameInSNB (&dfnName, snbExclude) == S_OK) { switch (REAL_STGTY(sstg.type)) { case STGTY_STORAGE: ssChkTo(EH_pwcsName, DestroyTree(_h, sstg.pwcsName, NULL, FD_STORAGE)); ssChkTo(EH_pwcsName, CreateStorage(sstg.pwcsName, STGM_READWRITE | STGM_CREATE, STGFMT_DOCUMENT, NULL, &pstg)); ssVerSucc(pstg->Release()); break; case STGTY_STREAM: ssChkTo(EH_pwcsName, OpenStream(sstg.pwcsName, NULL, STGM_WRITE, NULL, &pstm)); sc = pstm->SetSize(uli); ssVerSucc(pstm->Release()); break; default: break; } } EH_pwcsName: TaskMemFree(sstg.pwcsName); if (FAILED(sc)) break; } EH_penm: ssVerSucc(penm->Release()); ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::ExcludeEntries\n")); EH_Err: return ssResult(sc); } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::GetStorage, public IPrivateStorage // // Synopsis: Returns the IStorage for this object. // // Notes: This member is called by CPropertyStorage. // //---------------------------------------------------------------------------- STDMETHODIMP_(IStorage *) COfsDocStorage::GetStorage(VOID) { return this; } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::Lock, public IPrivateStorage // // Synopsis: Acquires the semaphore associated with the docfile. // // Notes: This member is called by CPropertyStorage. // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::Lock(DWORD dwTimeout) { return STG_E_UNIMPLEMENTEDFUNCTION; } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::Unlock, public IPrivateStorage // // Synopsis: Releases the semaphore associated with the docfile. // // Notes: This member is called by CPropertyStorage. // //---------------------------------------------------------------------------- STDMETHODIMP_(VOID) COfsDocStorage::Unlock(VOID) { } //+--------------------------------------------------------------------------- // // Member: COfsDocStorage::GetServerInfo, public IStorageReplica // // Synopsis: Get the actual DFS path for a storage's home location // // Notes: This member is exposed for Internal Use Only // //---------------------------------------------------------------------------- STDMETHODIMP COfsDocStorage::GetServerInfo( IN OUT LPWSTR lpServerName, IN OUT LPDWORD lpcbServerName, IN OUT LPWSTR lpReplSpecificPath, IN OUT LPDWORD lpcbReplSpecificPath) { return GetHandleServerInfo (_h, lpServerName, lpcbServerName, lpReplSpecificPath, lpcbReplSpecificPath); }