1026 lines
32 KiB
C++
1026 lines
32 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1995-1995.
|
|
//
|
|
// File: dirdir.cxx
|
|
//
|
|
// Contents: CDirectory implementation for OFS and FAT/NTFS
|
|
//
|
|
// Classes: CDirectory
|
|
//
|
|
// History: 19-Jun-95 HenryLee Created
|
|
//
|
|
// Notes: Requires NtIoApi.h
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "headers.cxx"
|
|
#pragma hdrstop
|
|
|
|
#include <stgutil.hxx>
|
|
#include <iofs.h>
|
|
#include <odirdir.hxx>
|
|
#include <odirstg.hxx>
|
|
#include <filstm.hxx>
|
|
#include <dfentry.hxx>
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::~COleDirectory
|
|
//
|
|
// Synopsis: Destroy the generic directory object.
|
|
//
|
|
// Arguments: none
|
|
//
|
|
//--------------------------------------------------------------------
|
|
COleDirectory::~COleDirectory ()
|
|
{
|
|
ssDebugOut((DEB_TRACE, "In COleDiretory::~COleDirectory\n"));
|
|
_sig = COFSDIRSTORAGE_SIGDEL;
|
|
ssDebugOut((DEB_TRACE, "Out COleDiretory::~COleDirectory\n"));
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::InitFromHandle
|
|
//
|
|
// Synopsis: Initialize a constructed COleDirectory object
|
|
//
|
|
// Arguments: handle file handle to duplicate
|
|
// wcDrive drive letter
|
|
// grfMode open option bit flags
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SCODE COleDirectory::InitFromHandle (HANDLE handle,
|
|
const WCHAR *pwcsName,
|
|
DWORD grfMode)
|
|
{
|
|
SCODE sc = S_OK;
|
|
ssDebugOut((DEB_TRACE, "In COleDiretory::InitFromHandle\n"));
|
|
_h = handle;
|
|
_grfMode = grfMode;
|
|
_sig = COFSDIRSTORAGE_SIG;
|
|
_wcDrive = GetDriveLetter (pwcsName);
|
|
ssDebugOut((DEB_TRACE, "Out COleDiretory::InitFromHandle\n"));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::InitFromPath
|
|
//
|
|
// Synopsis: Initialize a constructed COleDirectory object
|
|
//
|
|
// Arguments: hParent parent handle for relative open
|
|
// pwcsName name relative to the parent handle
|
|
// grfMode open option bit flags
|
|
// co create or open flag
|
|
// psa initial security descriptor
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SCODE COleDirectory::InitFromPath (HANDLE hParent,
|
|
const WCHAR *pwcsName,
|
|
DWORD grfMode,
|
|
CREATEOPEN co,
|
|
LPSECURITY_ATTRIBUTES psa)
|
|
{
|
|
SCODE sc = S_OK;
|
|
ssDebugOut((DEB_TRACE, "In COleDirectory::InitFromPath:%p("
|
|
"%p, %ws, %lX, %p)\n", this, hParent, pwcsName, grfMode, psa));
|
|
|
|
ssChk(ValidateMode(grfMode));
|
|
ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co, FD_DIR, psa, &_h));
|
|
|
|
_grfMode = grfMode;
|
|
_sig = COFSDIRSTORAGE_SIG;
|
|
_wcDrive = GetDriveLetter (pwcsName);
|
|
_fOfs = HandleRefersToOfsVolume (_h) == S_OK ? TRUE : FALSE;
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COleDirectory::InitFromPath\n"));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::CreateElement
|
|
//
|
|
// Synopsis: create a child object in this directory
|
|
// The child object is visible in the Win32 namespace
|
|
//
|
|
// Arguments: pwcsName name relative to the parent handle
|
|
// stgcreate create options
|
|
// stgopen open option bit flags
|
|
// riid interface GUID of object to return
|
|
// ppObject pointer to returned object
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP COleDirectory::CreateElement (
|
|
/* [in] */ const WCHAR *pwcsName,
|
|
/* [in] */ STGCREATE *pStgCreate,
|
|
/* [in] */ STGOPEN *pStgOpen,
|
|
/* [in] */ REFIID riid,
|
|
/* [out] */ void **ppObjectOpen)
|
|
{
|
|
SCODE sc = S_OK;
|
|
ssDebugOut((DEB_TRACE, "In COleDirectory::CreateElement:%p("
|
|
"%ws, %p, %p, %p)\n", this, pwcsName, pStgCreate,
|
|
pStgOpen, ppObjectOpen));
|
|
|
|
if (pStgCreate == NULL || pStgOpen == NULL)
|
|
ssErr (EH_Err, STG_E_INVALIDPOINTER);
|
|
if (pwcsName == NULL)
|
|
ssErr (EH_Err, STG_E_INVALIDNAME);
|
|
|
|
ssChk(Validate());
|
|
ssChk(ValidateStgfmt(pStgOpen->stgfmt, FALSE));
|
|
ssChk(ValidateOutPtrBuffer(ppObjectOpen));
|
|
*ppObjectOpen = NULL;
|
|
//BUGBUG need to convert security formats
|
|
ssAssert(_h != NULL);
|
|
|
|
if (pStgOpen->stgfmt==STGFMT_STORAGE ||
|
|
pStgOpen->stgfmt==STGFMT_DOCUMENT ||
|
|
pStgOpen->stgfmt==STGFMT_DOCFILE ||
|
|
pStgOpen->stgfmt==STGFMT_CATALOG )
|
|
{
|
|
SCODE scOfs = _fOfs ? S_OK : S_FALSE;
|
|
sc = InitStorage (_h, pwcsName, NULL,
|
|
CO_CREATE, pStgOpen, pStgCreate,
|
|
_wcDrive, &scOfs, FALSE, riid, ppObjectOpen);
|
|
}
|
|
else if (pStgOpen->stgfmt==STGFMT_DIRECTORY ||
|
|
pStgOpen->stgfmt==STGFMT_JUNCTION)
|
|
{
|
|
SCODE scOfs = _fOfs ? S_OK : S_FALSE;
|
|
ssChk(InitDirectory (_h, pwcsName, NULL,
|
|
CO_CREATE, pStgOpen, pStgCreate,
|
|
scOfs, riid, ppObjectOpen));
|
|
}
|
|
else if (pStgOpen->stgfmt==STGFMT_FILE)
|
|
{
|
|
CNtFileStream *pfs = new CNtFileStream();
|
|
ssMem((CNtFileStream *)pfs);
|
|
|
|
ssChk(pfs->InitFromPath (_h, pwcsName, pStgOpen->grfMode,
|
|
pStgCreate->grfAttrs, CO_CREATE, NULL));
|
|
sc = pfs->QueryInterface(riid, ppObjectOpen);
|
|
// success case, undo QI AddRef
|
|
pfs->Release(); // failure case, destroy obj
|
|
}
|
|
else ssErr (EH_Err, STG_E_INVALIDPARAMETER);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COleDirectory::CreateElement => %p\n",
|
|
*ppObjectOpen));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::OpenElement
|
|
//
|
|
// Synopsis: open a child object in this directory
|
|
// The child object is visible in the Win32 namespace
|
|
//
|
|
// Arguments: pwcsName name relative to the parent handle
|
|
// stgopen open option bit flags
|
|
// riid interface GUID of object to return
|
|
// pStgfmt storage format of ppObject
|
|
// ppObject pointer to returned object
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP COleDirectory::OpenElement (
|
|
/* [in] */ const WCHAR *pwcsName,
|
|
/* [in] */ STGOPEN *pStgOpen,
|
|
/* [in] */ REFIID riid,
|
|
/* [out] */ STGFMT * pStgfmt,
|
|
/* [out] */ void **ppObjectOpen)
|
|
{
|
|
SCODE sc = S_OK;
|
|
DWORD dwStgfmt;
|
|
ssDebugOut((DEB_TRACE, "In COleDirectory::OpenElement:%p("
|
|
"%ws, %p, %p)\n", this, pwcsName, pStgOpen, ppObjectOpen));
|
|
|
|
if (pStgOpen == NULL || pStgfmt == NULL || ppObjectOpen == NULL)
|
|
ssErr (EH_Err, STG_E_INVALIDPOINTER);
|
|
if (pwcsName == NULL)
|
|
ssErr (EH_Err, STG_E_INVALIDNAME);
|
|
|
|
ssChk(Validate());
|
|
ssChk(ValidateStgfmt(pStgOpen->stgfmt, TRUE));
|
|
ssChk(ValidateOutPtrBuffer(ppObjectOpen));
|
|
*ppObjectOpen = NULL;
|
|
//BUGBUG need to convert security formats
|
|
ssAssert(_h != NULL);
|
|
|
|
*ppObjectOpen = NULL;
|
|
dwStgfmt = pStgOpen->stgfmt;
|
|
if (dwStgfmt==STGFMT_ANY)
|
|
{
|
|
HANDLE h = NULL;
|
|
ssChk(DetermineStgType(_h,pwcsName,pStgOpen->grfMode,&dwStgfmt,&h));
|
|
if (_fOfs && dwStgfmt == STGFMT_DOCUMENT && S_OK==DfIsDocfile(h))
|
|
dwStgfmt = STGFMT_DOCFILE;
|
|
if (h != NULL)
|
|
NTSTATUS nts = NtClose (h);
|
|
pStgOpen->stgfmt = (STGFMT) dwStgfmt;// BUGBUG changing input parameter
|
|
}
|
|
if (dwStgfmt==STGFMT_STORAGE ||
|
|
dwStgfmt==STGFMT_DOCUMENT ||
|
|
dwStgfmt==STGFMT_DOCFILE ||
|
|
dwStgfmt==STGFMT_CATALOG )
|
|
{
|
|
STGFMT stgfmtTemp = (STGFMT) dwStgfmt;
|
|
SCODE scOfs = _fOfs ? S_OK : S_FALSE;
|
|
sc = InitStorage (_h, pwcsName, NULL,
|
|
CO_OPEN, pStgOpen, NULL,
|
|
_wcDrive, &scOfs, FALSE, riid, ppObjectOpen);
|
|
if (pStgfmt != NULL)
|
|
*pStgfmt = stgfmtTemp;
|
|
}
|
|
else if (dwStgfmt == STGFMT_DIRECTORY ||
|
|
dwStgfmt == STGFMT_JUNCTION)
|
|
{
|
|
SCODE scOfs = _fOfs ? S_OK : S_FALSE;
|
|
ssChk(InitDirectory (_h, pwcsName, NULL,
|
|
CO_OPEN, pStgOpen, NULL,
|
|
scOfs, riid, ppObjectOpen));
|
|
if (pStgfmt != NULL)
|
|
*pStgfmt = (STGFMT) dwStgfmt;
|
|
}
|
|
else if (dwStgfmt == STGFMT_FILE)
|
|
{
|
|
CNtFileStream *pfs = new CNtFileStream();
|
|
ssMem((CNtFileStream *)pfs);
|
|
|
|
ssChk(pfs->InitFromPath(_h, pwcsName, pStgOpen->grfMode,
|
|
0, CO_OPEN,NULL));
|
|
if (SUCCEEDED(sc = pfs->QueryInterface(riid, ppObjectOpen)))
|
|
{
|
|
if (pStgfmt != NULL)
|
|
*pStgfmt = STGFMT_FILE;
|
|
} // success case, undo QI AddRef
|
|
pfs->Release(); // failure case, destroy obj
|
|
}
|
|
else ssErr (EH_Err, STG_E_INVALIDPARAMETER);
|
|
|
|
EH_Err:
|
|
ssDebugOut((DEB_TRACE, "Out COleDirectory::CreateElement => %p %p\n",
|
|
*ppObjectOpen, pStgfmt));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::MoveElement
|
|
//
|
|
// Synopsis: move or rename a directory element
|
|
//
|
|
// Arguments: pwcsName name relative to the parent handle
|
|
// pDestDir destination directory
|
|
// pwcsNewName new name
|
|
// grfFlags move flags
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP COleDirectory::MoveElement (
|
|
/* [in] */ const WCHAR *pwcsName,
|
|
/* [in] */ IDirectory *pDestDir,
|
|
/* [in] */ const WCHAR *pwcsNewName,
|
|
/* [in] */ DWORD grfFlags)
|
|
{
|
|
SCODE sc = S_OK;
|
|
HANDLE h = NULL;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COleDirectory::MoveElement:%p(%ws, %ws)\n",
|
|
this, pwcsName, pwcsNewName));
|
|
if (pwcsName == NULL)
|
|
ssErr (EH_Err, STG_E_INVALIDNAME);
|
|
if (grfFlags & ~(STGMOVE_MOVE|STGMOVE_COPY|STGMOVE_SHALLOWCOPY))
|
|
ssErr (EH_Err, STG_E_INVALIDPARAMETER);
|
|
if (pDestDir == NULL && pwcsNewName == NULL)
|
|
ssErr (EH_Err, STG_E_INVALIDNAME);
|
|
|
|
if (pDestDir == NULL && (grfFlags & STGMOVE_COPY) == 0)
|
|
{
|
|
ssChk(Validate());
|
|
ssChk(CheckFdName(pwcsNewName));
|
|
ssAssert(_h != NULL);
|
|
// pwcsName is checked by GetFileOrDirHandle
|
|
sc = RenameChild(_h, pwcsName, pwcsNewName);
|
|
}
|
|
else
|
|
{
|
|
STATDIR statDir, statNewDir;
|
|
STGCREATE stgcreate = {0,0,0};
|
|
STGOPEN stgopen = {STGFMT_DIRECTORY, STGM_READ |
|
|
STGM_SHARE_DENY_WRITE, NULL};
|
|
STGOPEN stgopen2 = {STGFMT_DIRECTORY, STGM_CREATE |
|
|
STGM_READWRITE | STGM_SHARE_DENY_NONE , NULL};
|
|
STGFMT stgfmt2;
|
|
FILEDIR fd;
|
|
IDirectory *pIDir0, *pIDirDest;
|
|
IStorage *pIStg, *pIStgDest;
|
|
COleDirectory *pIDir;
|
|
DWORD stgfmt;
|
|
|
|
ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_READ, &h, NULL, NULL, &fd));
|
|
ssChk(DetermineHandleStgType (h, fd, &stgfmt));
|
|
NTSTATUS nts = NtClose(h);
|
|
|
|
switch (stgfmt)
|
|
{
|
|
case STGFMT_FILE:
|
|
BOOL bOK;
|
|
WCHAR awcsToPath[_MAX_PATH], awcsFromPath[_MAX_PATH];
|
|
ULONG ulToPath;
|
|
|
|
ulToPath = (pwcsNewName != NULL) ? wcslen(pwcsNewName) :
|
|
wcslen(pwcsName);
|
|
if (pDestDir != NULL)
|
|
{
|
|
|
|
ssChk(StatElement(NULL, &statDir, STATFLAG_DEFAULT));
|
|
ssChk(pDestDir->StatElement(NULL, &statNewDir,
|
|
STATFLAG_DEFAULT));
|
|
|
|
if ((wcslen(statDir.pwcsName)+wcslen(pwcsName)+2) > _MAX_PATH
|
|
|| (wcslen(statNewDir.pwcsName)+ulToPath+2) > _MAX_PATH)
|
|
{
|
|
ssVerSucc(CoMemFree(statDir.pwcsName));
|
|
ssVerSucc(CoMemFree(statNewDir.pwcsName));
|
|
ssErr (EH_Err, STG_E_INVALIDNAME);
|
|
}
|
|
wcscpy (awcsFromPath, statDir.pwcsName);
|
|
wcscat (awcsFromPath, L"\\");
|
|
wcscat (awcsFromPath, pwcsName);
|
|
wcscpy (awcsToPath, statNewDir.pwcsName);
|
|
wcscat (awcsToPath, L"\\");
|
|
wcscat (awcsToPath, (pwcsNewName!=NULL) ? pwcsNewName:pwcsName);
|
|
}
|
|
else
|
|
{
|
|
if ((wcslen(pwcsName) +1) > _MAX_PATH ||
|
|
(ulToPath + 2) > _MAX_PATH)
|
|
{
|
|
ssErr (EH_Err, STG_E_INVALIDNAME);
|
|
}
|
|
wcscpy (awcsFromPath, pwcsName);
|
|
wcscat (awcsToPath, (pwcsNewName!=NULL) ? pwcsNewName:pwcsName);
|
|
}
|
|
|
|
ssVerSucc(CoMemFree(statDir.pwcsName));
|
|
ssVerSucc(CoMemFree(statNewDir.pwcsName));
|
|
|
|
bOK = CopyFileW (awcsFromPath, awcsToPath, FALSE);
|
|
if(!(bOK))
|
|
ssErr (EH_Err, Win32ErrorToScode(GetLastError()));
|
|
break;
|
|
case STGFMT_DIRECTORY:
|
|
// if no new name given, move/copy the old name
|
|
if (pwcsNewName == NULL)
|
|
pwcsNewName = pwcsName;
|
|
// if the destination directory is null, use the source
|
|
ssChk( ((pDestDir == NULL) ? this : pDestDir)->
|
|
CreateElement(pwcsNewName, &stgcreate, &stgopen2,
|
|
IID_IDirectory, (void **) &pIDirDest));
|
|
// if this is deep copy, then we enumerate & recurse
|
|
if ((grfFlags & STGMOVE_SHALLOWCOPY) == 0)
|
|
{
|
|
IEnumSTATDIR *penum;
|
|
STATDIR stat;
|
|
ssChkTo(EH_Release, OpenElement(pwcsName, &stgopen,
|
|
IID_IDirectory, &stgfmt2, (void **) &pIDir));
|
|
if (SUCCEEDED(sc = pIDir->EnumDirectoryElements(&penum)))
|
|
{
|
|
while ((sc = penum->Next(1, &stat, NULL)) == S_OK)
|
|
{
|
|
sc = pIDir->MoveElement(stat.pwcsName, pIDirDest,
|
|
NULL, grfFlags);
|
|
if (stat.pwcsName)
|
|
ssVerSucc(CoMemFree(stat.pwcsName));
|
|
if (!SUCCEEDED(sc)) break;
|
|
}
|
|
penum->Release();
|
|
if (sc == S_FALSE)
|
|
sc = S_OK;
|
|
}
|
|
// BUGBUG when storages properly enum OLE namespace
|
|
// turn this function on
|
|
//sc = pIDir->MoveEmbeddings (pIDirDest, STGMOVE_COPY);
|
|
pIDir->Release();
|
|
}
|
|
EH_Release:
|
|
pIDirDest->Release();
|
|
break;
|
|
case STGFMT_DOCUMENT:
|
|
case STGFMT_DOCFILE:
|
|
case STGFMT_STORAGE:
|
|
case STGFMT_CATALOG:
|
|
stgopen.stgfmt = (STGFMT) stgfmt;
|
|
if (pwcsNewName == NULL)
|
|
pwcsNewName = pwcsName;
|
|
ssChk(OpenElement(pwcsName, &stgopen,
|
|
IID_IStorage, &stgfmt2, (void **) &pIStg));
|
|
|
|
stgopen2.stgfmt = stgfmt2;
|
|
stgopen2.grfMode = STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
|
|
ssChkTo(EH_Storage, ((pDestDir == NULL) ? this : pDestDir)->
|
|
CreateElement(pwcsNewName, &stgcreate, &stgopen2,
|
|
IID_IStorage, (void **) &pIStgDest));
|
|
sc = pIStg->CopyTo(0, NULL, NULL, pIStgDest);
|
|
pIStgDest->Release();
|
|
EH_Storage:
|
|
pIStg->Release();
|
|
break;
|
|
default:
|
|
ssErr(EH_Err, STG_E_INVALIDFLAG);
|
|
};
|
|
|
|
if (grfFlags & STGMOVE_MOVE)
|
|
{
|
|
ssChk(DeleteElement (pwcsName));
|
|
}
|
|
}
|
|
EH_Err:
|
|
ssDebugOut((DEB_TRACE, "Out COleDireectory::MoveElement\n"));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::MoveEmbeddings
|
|
//
|
|
// Synopsis: Move or Copy all embeddings on a directory
|
|
//
|
|
// Arguments: grfCommitFlags commit flags
|
|
//
|
|
// Notes: both source and destination must support IStorage
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
SCODE COleDirectory::MoveEmbeddings (IDirectory *pdirDest, DWORD grfFlags)
|
|
{
|
|
SCODE sc;
|
|
IStorage *pIStg, *pIStgDest;
|
|
DWORD dwFlags = grfFlags == STGMOVE_MOVE ? STGMOVE_MOVE : STGMOVE_COPY;
|
|
if (SUCCEEDED(sc = QueryInterface(IID_IStorage, (void **) &pIStg)))
|
|
{
|
|
if (SUCCEEDED(sc=pdirDest->QueryInterface(IID_IStorage,
|
|
(void **) &pIStgDest)))
|
|
{
|
|
IEnumSTATSTG *pIEnumStatStg;
|
|
STATSTG statstg;
|
|
if (SUCCEEDED(sc = pIStg->EnumElements(NULL, NULL,
|
|
NULL, &pIEnumStatStg)))
|
|
{
|
|
while ((sc = pIEnumStatStg->Next(1,&statstg,NULL)) == S_OK)
|
|
{
|
|
sc = pIStg->MoveElementTo(statstg.pwcsName,
|
|
pIStgDest, statstg.pwcsName, dwFlags);
|
|
if (statstg.pwcsName)
|
|
ssVerSucc(CoMemFree(statstg.pwcsName));
|
|
if (!SUCCEEDED(sc))
|
|
break;
|
|
}
|
|
pIEnumStatStg->Release();
|
|
if (sc == S_FALSE)
|
|
sc = S_OK;
|
|
}
|
|
pIStgDest->Release();
|
|
}
|
|
pIStg->Release();
|
|
}
|
|
|
|
// if either source or destination does not support IStorage
|
|
// we do not copy any embeddings and return S_OK
|
|
if (sc == E_NOINTERFACE) sc = S_OK;
|
|
return sc;
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::CommitDirectory
|
|
//
|
|
// Synopsis: commit a direction transaction, no-op for direct mode
|
|
//
|
|
// Arguments: grfCommitFlags commit flags
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP COleDirectory::CommitDirectory(
|
|
/* [in] */ DWORD grfCommitFlags)
|
|
{
|
|
SCODE sc = S_OK;
|
|
ssDebugOut((DEB_TRACE, "In COleDiretory::CommitDirectory\n"));
|
|
if (grfCommitFlags & ~(STGC_DEFAULT))
|
|
ssErr (EH_Err, STG_E_INVALIDPARAMETER);
|
|
EH_Err:
|
|
ssDebugOut((DEB_TRACE, "Out COleDiretory::CommitDirectory\n"));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
STDMETHODIMP COleDirectory::RevertDirectory ()
|
|
{
|
|
SCODE sc = S_OK;
|
|
ssDebugOut((DEB_TRACE, "In COleDiretory::RevertDirectory\n"));
|
|
ssDebugOut((DEB_TRACE, "Out COleDiretory::RevertDirectory\n"));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::DeleteElement
|
|
//
|
|
// Synopsis: delete a directory element, if possible
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP COleDirectory::DeleteElement (
|
|
/* [in] */ const WCHAR *pwcsName)
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COleDirectory::DestroyElement:%p(%ws)\n",
|
|
this, pwcsName));
|
|
|
|
if (pwcsName == NULL)
|
|
ssErr (EH_Err, STG_E_INVALIDNAME);
|
|
ssChk(Validate());
|
|
|
|
ssChk(CheckFdName(pwcsName));
|
|
ssAssert(_h != NULL);
|
|
sc = DestroyTree(_h, pwcsName, NULL, FD_FILE); //non-recursive
|
|
|
|
ssDebugOut((DEB_TRACE, "Out COleDirectory::DestroyElement\n"));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::SetTimes
|
|
//
|
|
// Synopsis: set change, modification, and access times
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Notes: renamed from SetElementTimes, IStorage conflict
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP COleDirectory::SetTimes(
|
|
/* [in] */ const WCHAR *pwcsName,
|
|
/* [in] */ const FILETIME *pctime,
|
|
/* [in] */ const FILETIME *patime,
|
|
/* [in] */ const FILETIME *pmtime)
|
|
{
|
|
SCODE sc = S_OK;
|
|
HANDLE h = _h;
|
|
FILEDIR fd = FD_DIR;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COleDirectory::SetElementTimes:%p("
|
|
"%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
|
|
|
|
ssChk(Validate());
|
|
|
|
ssAssert(_h != NULL);
|
|
if (pwcsName != NULL)
|
|
ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_WRITE, &h, NULL,NULL, &fd));
|
|
|
|
sc = ::SetTimes(h, pctime, patime, pmtime);
|
|
|
|
EH_Err:
|
|
if (pwcsName != NULL && h != _h)
|
|
NTSTATUS nts = NtClose(h);
|
|
ssDebugOut((DEB_TRACE, "Out COleDirectory::SetElementTimes\n"));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::SetDirectoryClass
|
|
//
|
|
// Synopsis: set the clsid
|
|
//
|
|
// Arguments: [clsid] the class GUID of this directory
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP COleDirectory::SetDirectoryClass(
|
|
/* [in] */ REFCLSID clsid)
|
|
{
|
|
SCODE sc = S_OK;
|
|
NTSTATUS nts = ERROR_SUCCESS;
|
|
olDebugOut((DEB_TRACE,"In COleDirectory::SetDirectoryClass:%p(clsid %p)\n",
|
|
this, &clsid));
|
|
if (_fOfs)
|
|
{
|
|
NTSTATUS nts = RtlSetClassId(_h, &clsid);
|
|
if (!NT_SUCCESS(nts))
|
|
sc = NtStatusToScode (nts);
|
|
}
|
|
else
|
|
{
|
|
IO_STATUS_BLOCK iosb;
|
|
HANDLE h = NULL;
|
|
if (SUCCEEDED( sc = GetNtHandle (_h, CLSID_FILENAME,
|
|
STGM_WRITE | STGM_CREATE, FILE_ATTRIBUTE_HIDDEN,
|
|
CO_CREATE, FD_FILE, NULL, &h)))
|
|
{
|
|
nts = NtWriteFile (h, NULL, NULL, NULL, &iosb, (void *) &clsid,
|
|
sizeof(clsid), NULL, NULL);
|
|
if (!NT_SUCCESS(nts))
|
|
sc = NtStatusToScode (nts);
|
|
if (h != NULL)
|
|
nts = NtClose(h);
|
|
}
|
|
}
|
|
//EH_Err:
|
|
olDebugOut((DEB_TRACE, "Out COleDirectory::SetDirectoryClass => %lX\n",sc));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::GetDirectoryClass
|
|
//
|
|
// Synopsis: set the clsid
|
|
//
|
|
// Arguments: [clsid] the class GUID of this directory
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SCODE COleDirectory::GetDirectoryClass (HANDLE h, CLSID *pclsid)
|
|
{
|
|
SCODE sc = S_OK;
|
|
NTSTATUS nts = ERROR_SUCCESS;
|
|
HANDLE hHidden = NULL;
|
|
olDebugOut((DEB_TRACE,"In COleDirectory::GetDirectoryClass:%p(clsid %p)\n",
|
|
this, pclsid));
|
|
*pclsid = CLSID_NULL;
|
|
if (!_fOfs)
|
|
{
|
|
IO_STATUS_BLOCK iosb;
|
|
HANDLE h = NULL;
|
|
if (SUCCEEDED( sc = GetNtHandle ((h == NULL ? _h : h), CLSID_FILENAME,
|
|
STGM_READ, 0, CO_OPEN, FD_FILE, NULL, &hHidden)))
|
|
{
|
|
nts = NtReadFile (hHidden, NULL, NULL, NULL, &iosb, (void *)pclsid,
|
|
sizeof(*pclsid), NULL, NULL);
|
|
if (!NT_SUCCESS(nts))
|
|
sc = NtStatusToScode (nts);
|
|
if (hHidden != NULL)
|
|
nts = NtClose(hHidden);
|
|
if (iosb.Information < sizeof(*pclsid))
|
|
sc = STG_E_READFAULT;
|
|
}
|
|
}
|
|
//EH_Err:
|
|
olDebugOut((DEB_TRACE, "Out COleDirectory::GetDirectoryClass => %lX\n",sc));
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::SetAttributes
|
|
//
|
|
// Synopsis: set a file's attributes
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP COleDirectory::SetAttributes(
|
|
/* [in] */ const WCHAR *pwcsName,
|
|
/* [in] */ DWORD grfAttrs)
|
|
{
|
|
SCODE sc = S_OK;
|
|
HANDLE h = _h;
|
|
FILEDIR fd = FD_DIR;
|
|
ssDebugOut((DEB_TRACE, "In COleDiretory::SetAttributes\n"));
|
|
|
|
ssAssert(_h != NULL);
|
|
if (pwcsName != NULL)
|
|
ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_WRITE, &h, NULL,NULL, &fd));
|
|
|
|
sc = SetNtFileAttributes (h, grfAttrs);
|
|
|
|
EH_Err:
|
|
if (pwcsName != NULL && h != _h)
|
|
NTSTATUS nts = NtClose(h);
|
|
ssDebugOut((DEB_TRACE, "Out COleDiretory::SetAttributes\n"));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::StatElement
|
|
//
|
|
// Synopsis: retrieve information about a directory or element
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP COleDirectory::StatElement(
|
|
/* [in] */ const WCHAR *pwcsName,
|
|
/* [out] */ STATDIR *pstatdir,
|
|
/* [in] */ DWORD grfStatFlag)
|
|
{
|
|
SCODE sc = S_OK;
|
|
HANDLE h = _h;
|
|
STATSTG stat;
|
|
FILEDIR fd;
|
|
NTSTATUS nts;
|
|
|
|
ssDebugOut((DEB_TRACE, "In COleDiretory::StatElement\n"));
|
|
if (pstatdir == NULL)
|
|
ssErr (EH_Err, STG_E_INVALIDPOINTER);
|
|
if (grfStatFlag & ~(STATFLAG_DEFAULT|STATFLAG_NONAME|STATFLAG_NOOPEN))
|
|
ssErr (EH_Err, STG_E_INVALIDPARAMETER);
|
|
|
|
ssChk(VerifyStatFlag(grfStatFlag));
|
|
ssChk(Validate());
|
|
|
|
if (pwcsName != NULL)
|
|
ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_READ, &h, NULL,NULL, &fd));
|
|
|
|
__try
|
|
{
|
|
DWORD grfAttrs;
|
|
ssAssert(h != NULL);
|
|
sc = StatNtHandle(h, grfStatFlag, 0, &stat, NULL, &grfAttrs, &fd);
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
sc = SetDriveLetter (stat.pwcsName, _wcDrive);
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
stat.grfMode = _grfMode;
|
|
stat.cbSize.HighPart = stat.cbSize.LowPart = 0;
|
|
pstatdir->pwcsName = stat.pwcsName;
|
|
pstatdir->atime = stat.atime;
|
|
pstatdir->ctime = stat.ctime;
|
|
pstatdir->mtime = stat.mtime;
|
|
pstatdir->grfMode = stat.grfMode;
|
|
pstatdir->grfStateBits = stat.grfStateBits;
|
|
pstatdir->clsid = stat.clsid;
|
|
if (_fOfs)
|
|
pstatdir->clsid = stat.clsid;
|
|
else
|
|
GetDirectoryClass (h, &pstatdir->clsid);
|
|
pstatdir->cbSize = stat.cbSize;
|
|
pstatdir->stgfmt = (STGFMT) stat.STATSTG_dwStgFmt;
|
|
pstatdir->grfAttrs = grfAttrs;
|
|
}
|
|
else if (stat.pwcsName)
|
|
ssVerSucc(CoMemFree(stat.pwcsName));
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
if (stat.pwcsName != NULL)
|
|
ssVerSucc(CoMemFree(stat.pwcsName));
|
|
sc = HRESULT_FROM_NT(GetExceptionCode());
|
|
}
|
|
|
|
EH_Err:
|
|
if (pwcsName != NULL && h != _h)
|
|
nts = NtClose(h);
|
|
ssDebugOut((DEB_TRACE, "Out COleDiretory::StatElement\n"));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: COleDirectory::EnumDirectoryElements
|
|
//
|
|
// Synopsis: enumerate child elements
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP COleDirectory::EnumDirectoryElements(
|
|
/* [out] */ IEnumSTATDIR **ppenum)
|
|
{
|
|
SCODE sc = S_OK;
|
|
SafeCEnumSTATDIR pde;
|
|
|
|
olDebugOut((DEB_TRACE, "In COleDirectory::EnumElements:%p(%p)\n", this,
|
|
ppenum));
|
|
|
|
if (ppenum == NULL)
|
|
ssErr (EH_Err, STG_E_INVALIDPOINTER) // missing ';' macro problem
|
|
else
|
|
ssChk(ValidateOutPtrBuffer(ppenum));
|
|
*ppenum = NULL;
|
|
olChk(Validate());
|
|
|
|
pde.Attach(new CEnumSTATDIR(_fOfs));
|
|
olMem((CEnumSTATDIR *)pde);
|
|
olAssert(_h != NULL);
|
|
olChk(pde->InitFromHandle(_h));
|
|
TRANSFER_INTERFACE(pde, IEnumSTATDIR, ppenum);
|
|
|
|
olDebugOut((DEB_TRACE, "Out COleDirectory::EnumElements => %p\n",
|
|
*ppenum));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CEnumSTATDIR
|
|
//
|
|
// Purpose: Implements IEnumSTATDIR for Win32 directories
|
|
//
|
|
// Interface: See below
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CEnumSTATDIR::~CEnumSTATDIR ()
|
|
{
|
|
ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::~CEnumSTATDIR\n"));
|
|
m_sig = CENUMSTATDIR_SIGDEL;
|
|
ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::~CEnumSTATDIR\n"));
|
|
};
|
|
|
|
STDMETHODIMP CEnumSTATDIR::Next (
|
|
/* [in] */ ULONG celt,
|
|
/* [in] */ STATDIR *rgelt,
|
|
/* [out] */ ULONG *pceltFetched)
|
|
{
|
|
SCODE sc = S_OK;
|
|
STATDIR *pelt = rgelt;
|
|
STATSTG stat;
|
|
ULONG celtDone;
|
|
FILEDIR fd;
|
|
CPtrCache pc;
|
|
WCHAR *pwcs;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::Next\n"));
|
|
if (pceltFetched == NULL && celt > 1)
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
ssChk(Validate());
|
|
|
|
__try
|
|
{
|
|
for (celtDone = 0; pelt<rgelt+celt; pelt++, celtDone++)
|
|
{
|
|
if (m_fOfs)
|
|
sc = m_nte.NextOfs(&stat, NULL, NTE_STATNAME, &fd);
|
|
else
|
|
sc = m_nte.Next(&stat, NULL, NTE_STATNAME, &fd);
|
|
|
|
if (FAILED(sc) || sc == S_FALSE)
|
|
break;
|
|
if (FAILED(sc = pc.Add(stat.pwcsName)))
|
|
break;
|
|
pelt->pwcsName = stat.pwcsName;
|
|
pelt->atime = stat.atime;
|
|
pelt->ctime = stat.ctime;
|
|
pelt->mtime = stat.mtime;
|
|
pelt->grfMode = stat.grfMode;
|
|
pelt->grfStateBits = stat.grfStateBits;
|
|
pelt->clsid = stat.clsid;
|
|
pelt->cbSize = stat.cbSize;
|
|
pelt->stgfmt = (STGFMT) stat.STATSTG_dwStgFmt;
|
|
pelt->grfAttrs = 0;
|
|
}
|
|
|
|
if (SUCCEEDED(sc) && pceltFetched)
|
|
*pceltFetched = celtDone;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
pc.StartEnum();
|
|
while (pc.Next((void **)&pwcs))
|
|
ssHVerSucc(CoMemFree(pwcs));
|
|
sc = HRESULT_FROM_NT(GetExceptionCode());
|
|
// BUGBUG are we freeing twice?
|
|
}
|
|
EH_Err:
|
|
if (FAILED(sc))
|
|
{
|
|
pc.StartEnum();
|
|
while (pc.Next((void **)&pwcs))
|
|
ssHVerSucc(CoMemFree(pwcs));
|
|
}
|
|
ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::Next\n"));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
STDMETHODIMP CEnumSTATDIR::Skip (
|
|
/* [in] */ ULONG celt)
|
|
{
|
|
SCODE sc = S_OK;
|
|
STATSTG stat; // dummy buffer
|
|
FILEDIR fd;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::Skip (%p,%lu)\n",this,celt));
|
|
ssChk(Validate());
|
|
|
|
while (celt-- > 0)
|
|
{
|
|
sc = m_nte.Next(&stat, NULL, NTE_NONAME, &fd);
|
|
if (FAILED(sc) || sc == S_FALSE)
|
|
break;
|
|
}
|
|
EH_Err:
|
|
ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::Skip\n"));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
STDMETHODIMP CEnumSTATDIR::Reset()
|
|
{
|
|
SCODE sc = S_OK;
|
|
ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::Reset\n"));
|
|
ssChk(Validate());
|
|
m_nte.Reset();
|
|
EH_Err:
|
|
ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::Reset\n"));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
STDMETHODIMP CEnumSTATDIR::Clone (
|
|
/* [out] */ IEnumSTATDIR **ppenum)
|
|
{
|
|
SCODE sc = S_OK;
|
|
SafeCEnumSTATDIR pde;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::Clone\n"));
|
|
|
|
ssChk(Validate());
|
|
|
|
pde.Attach(new CEnumSTATDIR(m_fOfs));
|
|
ssMem((CEnumSTATDIR *)pde);
|
|
ssChk(pde->InitFromHandle(m_nte.GetHandle()));
|
|
TRANSFER_INTERFACE(pde, IEnumSTATDIR, ppenum);
|
|
// BUGBUG need to allow multiple enumerators
|
|
|
|
EH_Err:
|
|
ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::Clone (%p)\n", ppenum));
|
|
return ssResult(sc);
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CEnumSTATDIR::QueryInterface, public
|
|
//
|
|
// Synopsis: Returns an object for the requested interface
|
|
//
|
|
// Arguments: [iid] - Interface ID
|
|
// [ppvObj] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 28-Jun-95 HenryLee Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CEnumSTATDIR::QueryInterface(REFIID iid, void **ppvObj)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::QueryInterface:%p(riid, %p)\n",
|
|
this, ppvObj));
|
|
if (!IsValidIid(iid))
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
ssChk(Validate());
|
|
if (IsEqualIID(iid, IID_IEnumSTATDIR) || IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppvObj = (IEnumSTATDIR *)this;
|
|
CEnumSTATDIR::AddRef();
|
|
}
|
|
else
|
|
{
|
|
sc = E_NOINTERFACE;
|
|
*ppvObj = NULL;
|
|
}
|
|
ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::QueryInterface => %p\n",
|
|
*ppvObj));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|