NT4/private/ole32/stg/ofsstg/ostgsupp.cxx
2020-09-30 17:12:29 +02:00

1164 lines
36 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: ostgsupp.cxx
//
// Contents: Storage create/open support routines
//
// History: 14-Jul-93 DrewB Created
//
//----------------------------------------------------------------------------
#include "headers.cxx"
#pragma hdrstop
#include <iofs.h>
#include <stgprop.h>
#include <ntlkb.hxx>
#include <stgutil.hxx>
//#include "prstg.hxx"
#include "ofscs.hxx"
#include <dfentry.hxx>
#include <initguid.h> // IID is defined in stgint.h for Internal Use Only
DEFINE_GUID (IID_IStorageReplica,
0x521a28f3,0xe40b,0x11ce,0xb2,0xc9,0x00,0xaa,0x00,0x68,0x09,0x37);
// Docfiles require read permission on the file so give it
#define PERM_MASK (STGM_READ | STGM_WRITE | STGM_READWRITE)
#define FORCE_READ(grfMode) \
if (((grfMode) & PERM_MASK) == STGM_WRITE) \
(grfMode) = ((grfMode) & ~PERM_MASK) | STGM_READWRITE; \
else 1
//+---------------------------------------------------------------------------
//
// Function: OfsTaskAlloc, public
//
// Synopsis: Task allocator function for OFS property APIs
//
// Arguments: [cb] - Count of bytes to allocate
//
// Returns: Appropriate status code
//
// History: 05-Jan-94 DrewB Created
//
//----------------------------------------------------------------------------
LPVOID WINAPI OfsTaskAlloc(ULONG cb)
{
ssDebugOut((DEB_ITRACE, "In OfsTaskAlloc(%lu)\n", cb));
ssDebugOut((DEB_ITRACE, "Out OfsTaskAlloc\n"));
return CoTaskMemAlloc(cb);
}
#if 0
//+---------------------------------------------------------------------------
//
// Function: OfsDfCreateStorage, public
//
// Synopsis: BUGBUG - Stub function
//
// History: 13-Jul-93 DrewB Created
// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
//
//----------------------------------------------------------------------------
STDAPI OfsDfCreateStorage(HANDLE hParent,
WCHAR const *pwcsName,
HANDLE h,
DWORD grfMode,
LPSECURITY_ATTRIBUTES pssSecurity,
IStorage **ppstg)
{
SCODE sc;
SafeCNtLockBytes pnlb;
SafeIStorage pstg;
FORCE_READ(grfMode);
pnlb.Attach(new CNtLockBytes(TRUE));
ssMem((CNtLockBytes *)pnlb);
if (h != NULL)
{
ssChk(pnlb->InitFromHandle(h, pwcsName, grfMode));
}
else
{
ssChk(pnlb->InitFromPath(hParent, pwcsName, grfMode,
CO_CREATE, pssSecurity));
}
grfMode = (grfMode & ~STGM_DELETEONRELEASE) | STGM_CREATE;
ssChk(StgCreateDocfileOnILockBytes(pnlb, grfMode, 0, &pstg));
TRANSFER_INTERFACE(pstg, IStorage, ppstg);
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Function: OfsDfOpenStorage, public
//
// Synopsis: BUGBUG - Stub function
//
// History: 13-Jul-93 DrewB Created
// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
//
//----------------------------------------------------------------------------
STDAPI OfsDfOpenStorage(HANDLE hParent,
WCHAR const *pwcsName,
HANDLE h,
IStorage *pstgPriority,
DWORD grfMode,
SNB snbExclude,
IStorage **ppstg)
{
SCODE sc;
SafeCNtLockBytes pnlb;
SafeIStorage pstg;
FORCE_READ(grfMode);
pnlb.Attach(new CNtLockBytes(TRUE));
ssMem((CNtLockBytes *)pnlb);
if (h != NULL)
{
ssChk(pnlb->InitFromHandle(h, pwcsName, grfMode));
}
else
{
ssChk(pnlb->InitFromPath(hParent, pwcsName, grfMode,
CO_OPEN, NULL));
}
ssChk(StgOpenStorageOnILockBytes(pnlb, pstgPriority, grfMode,
snbExclude, 0, &pstg));
TRANSFER_INTERFACE(pstg, IStorage, ppstg);
EH_Err:
return sc;
}
// OfsDfCreateStorage and OfsDfOpenStorage have been replaced
// by DfCreateDocfile and DfOpenDocfile
#endif // 0
//+---------------------------------------------------------------------------
//
// Function: OfsDocCreateStorage, public
//
// Synopsis: Create a new document storage
//
// History: 11-Feb-94 PhilipLa Created.
// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
//
//----------------------------------------------------------------------------
STDAPI OfsDocCreateStorage(HANDLE hParent,
WCHAR const *pwcsName,
HANDLE h,
DWORD grfMode,
LPSECURITY_ATTRIBUTES pssSecurity,
BOOL fRoot,
IStorage **ppstg)
{
SCODE sc;
SafeCOfsDocStorage pstg;
FORCE_READ(grfMode);
pstg.Attach(new COfsDocStorage());
ssMem((COfsDocStorage *)pstg);
if (h != NULL)
{
ssChk(pstg->InitFromHandle(h, pwcsName, grfMode, fRoot));
}
else
{
ssChk(pstg->InitFromPath(hParent, pwcsName, grfMode,
CO_CREATE, pssSecurity, fRoot));
}
TRANSFER_INTERFACE(pstg, IStorage, ppstg);
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Function: OfsDocOpenStorage, public
//
// Synopsis: Open an existing document storage
//
// History: 11-Feb-94 PhilipLa Created.
// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
//
//----------------------------------------------------------------------------
STDAPI OfsDocOpenStorage(HANDLE hParent,
WCHAR const *pwcsName,
HANDLE *ph,
IStorage *pstgPriority,
DWORD grfMode,
SNB snbExclude,
BOOL fRoot,
IStorage **ppstg)
{
SCODE sc;
SafeCOfsDocStorage pstg;
//BUGBUG: What do we do for PRIORITY mode?
ssAssert(((grfMode & STGM_PRIORITY) == 0) ||
aMsg("Priority mode not supported yet."));
FORCE_READ(grfMode);
pstg.Attach(new COfsDocStorage());
ssMem((COfsDocStorage *)pstg);
if (*ph != NULL)
{
ssChk(pstg->InitFromHandle(*ph, pwcsName, grfMode, fRoot));
}
else
{
ssChk(pstg->InitFromPath(hParent, pwcsName, grfMode,
CO_OPEN, NULL, fRoot));
}
if (snbExclude)
{
HANDLE hDummy;
sc = pstg->ExcludeEntries(snbExclude);
if (FAILED(sc)) // On failure, pstg will destroy object
*ph = NULL; // and automatically close the handle
ssChk (sc); // Inform outer routine not to close
}
TRANSFER_INTERFACE(pstg, IStorage, ppstg);
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Function: OfsDirOpenStorage, public
//
// Synopsis: Open an existing document storage
//
// History: 11-Feb-94 PhilipLa Created.
// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
//
//----------------------------------------------------------------------------
STDAPI OfsDirOpenStorage(HANDLE hParent,
WCHAR const *pwcsName,
HANDLE h,
IStorage *pstgPriority,
DWORD grfMode,
SNB snbExclude,
BOOL fRoot,
IStorage **ppstg)
{
SCODE sc;
SafeCOfsDirStorage pdirstg;
//BUGBUG: What do we do for PRIORITY mode?
ssAssert(((grfMode & STGM_PRIORITY) == 0) ||
aMsg("Priority mode not supported yet."));
ssAssert((pstgPriority == NULL) && (snbExclude == NULL));
FORCE_READ(grfMode);
pdirstg.Attach(new COfsDirStorage());
ssMem((COfsDirStorage *)pdirstg);
if (h != NULL)
{
ssChk(pdirstg->InitFromHandle(h, pwcsName, grfMode));
}
else
{
ssChk(pdirstg->InitFromPath(hParent, pwcsName, grfMode,
CO_OPEN, FALSE, NULL));
}
TRANSFER_INTERFACE(pdirstg, IStorage, ppstg);
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Function: OfsCreateStorageType, public
//
// Synopsis: Creates a storage of the appropriate type
//
// Arguments: [hParent] - Parent handle or NULL
// [pwcsName] - Name or path
// [grfMode] - Mode
// [dwStgFmt] - Type of storage
// [pssSecurity] - Security
// [fRoot] - TRUE => creating root of storage
// [ppstg] - New storage return
//
// Returns: Appropriate status code
//
// Modifies: [ppstg]
//
// History: 24-Jun-93 DrewB Created
// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
//
//----------------------------------------------------------------------------
SCODE OfsCreateStorageType(HANDLE hParent,
WCHAR const *pwcsName,
HANDLE h,
DWORD grfMode,
DWORD dwStgFmt,
LPSECURITY_ATTRIBUTES pssSecurity,
BOOL fRoot,
IStorage **ppstg)
{
SCODE sc;
SafeCOfsDirStorage pds;
SafeCOfsFileStorage pfs;
SafeCOfsCatalogFile pcf;
ssDebugOut((DEB_ITRACE, "In OfsCreateStorageType("
"%p, %ws, %p, %lX, %lu, %p, %p)\n",
hParent, pwcsName, h, grfMode, dwStgFmt, pssSecurity, ppstg));
sc = S_OK;
switch(dwStgFmt)
{
case STGFMT_DOCUMENT:
sc = GetScode(OfsDocCreateStorage(hParent, pwcsName, h, grfMode,
pssSecurity, fRoot, ppstg));
break;
case STGFMT_CATALOG:
pcf.Attach(new COfsCatalogFile());
ssMem((COfsCatalogFile *)pcf);
ssChk(pcf->InitPath(pwcsName));
if (h != NULL)
{
ssChk(pcf->InitFromHandle(h, grfMode, pwcsName));
}
else
{
ssChk(pcf->InitFromPath(hParent, pwcsName, grfMode, CO_CREATE,
pssSecurity));
}
TRANSFER_INTERFACE(pcf, IStorage, ppstg);
break;
case STGFMT_DIRECTORY:
case STGFMT_JUNCTION:
pds.Attach(new COfsDirStorage());
ssMem((COfsDirStorage *)pds);
if (h != NULL)
{
ssChk(pds->InitFromHandle(h, pwcsName, grfMode));
}
else
{
ssChk(pds->InitFromPath(hParent, pwcsName, grfMode,
CO_CREATE, FALSE, pssSecurity));
}
TRANSFER_INTERFACE(pds, IStorage, ppstg);
break;
case STGFMT_FILE:
pfs.Attach(new COfsFileStorage());
ssMem((COfsFileStorage *)pfs);
if (h != NULL)
{
ssChk(pfs->InitFromHandle(h, grfMode));
}
else
{
ssChk(pfs->InitFromPath(hParent, pwcsName, grfMode, CO_CREATE,
pssSecurity));
}
TRANSFER_INTERFACE(pfs, IStorage, ppstg);
break;
default:
ssAssert(!aMsg("OfsCreateStorageType default hit"));
*ppstg = NULL;
break;
}
ssDebugOut((DEB_ITRACE, "Out OfsCreateStorageType => %p, 0x%lX\n",
*ppstg, sc));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Function: OfsOpenAnyStorage, public
//
// Synopsis: Opens a storage of the appropriate type
//
// Arguments: [hParent] - Parent handle or NULL
// [pwcsName] - Name or path
// [h] - Handle if already open or NULL
// [dwStgFmt] - Storage format for [h]
// [pstgPriority] - Priority mode prior open
// [grfMode] - Mode
// [snbExclude] - Exclusions
// [fRoot] - TRUE -> root storage
// [ppstg] - Storage return
//
// Returns: Appropriate status code
//
// Modifies: [ppstg]
//
// History: 14-Jul-93 DrewB Created
//
//----------------------------------------------------------------------------
SCODE OfsOpenAnyStorage(HANDLE hParent,
WCHAR const *pwcsName,
HANDLE *ph,
DWORD dwStgFmt,
IStorage *pstgPriority,
DWORD grfMode,
SNB snbExclude,
BOOL fRoot,
IStorage **ppstg)
{
SCODE sc;
SafeCOfsFileStorage pfs;
SafeCOfsCatalogFile pcf;
SafeNtHandle hSafe;
HANDLE h = (ph == NULL) ? NULL : *ph;
ssDebugOut((DEB_ITRACE, "In OfsOpenAnyStorage("
"%p, %ws, %p, %lu, %p, %lX, %p, %p)\n", hParent, pwcsName,
h, dwStgFmt, pstgPriority, grfMode, snbExclude, ppstg));
sc = S_OK;
if (h == NULL)
{
ssChk(DetermineStgType(hParent, pwcsName, grfMode,
&dwStgFmt, &hSafe));
h = hSafe;
}
switch(dwStgFmt)
{
case STGFMT_DOCUMENT:
sc = DfIsDocfile(h);
if (sc == S_OK)
{
// docfile will reopen the storage will different permissions
if (h)
{
NTSTATUS nts = NtClose(h);
h = NULL;
}
sc = DfOpenDocfile (pwcsName, NULL, pstgPriority, grfMode,
snbExclude, NULL, ppstg);
} else if ( sc == S_FALSE ) {
sc = GetScode(OfsDocOpenStorage(hParent, pwcsName, ph,
pstgPriority, grfMode,
snbExclude, fRoot, ppstg));
}
break;
case STGFMT_DIRECTORY:
case STGFMT_JUNCTION:
if (pstgPriority != NULL || snbExclude != NULL)
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
sc = GetScode(OfsDirOpenStorage(hParent, pwcsName, h,
pstgPriority, grfMode,
snbExclude, fRoot, ppstg));
break;
case STGFMT_CATALOG:
if (pstgPriority != NULL || snbExclude != NULL)
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
pcf.Attach(new COfsCatalogFile());
ssMem((COfsCatalogFile *)pcf);
ssChk(pcf->InitPath(pwcsName));
ssChk(pcf->InitFromHandle(h, grfMode, pwcsName));
TRANSFER_INTERFACE(pcf, IStorage, ppstg);
break;
case STGFMT_FILE:
#if 0
// BUGBUG [mikese] "File as an IStorage" behaviour has been disabled,
// because it causes compatibility problems. For example, Excel 5.0
// expects StgOpenStorage on a non-Docfile to fail, not for it to
// return successfully.
// This behaviour may be reenabled, through a different public API
// at a later time.
if (pstgPriority != NULL || snbExclude != NULL)
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
pfs.Attach(new COfsFileStorage());
ssMem((COfsFileStorage *)pfs);
ssChk(pfs->InitFromHandle(h, grfMode));
TRANSFER_INTERFACE(pfs, IStorage, ppstg);
#else
// This is the status code returned by Daytona OLE if you attempt to
// open a non-Docfile with StgOpenStorage.
sc = STG_E_FILEALREADYEXISTS;
#endif
break;
default:
ssAssert(!aMsg("OfsOpenAnyStorage default hit"));
*ppstg = NULL;
break;
}
ssDebugOut((DEB_ITRACE, "Out OfsOpenAnyStorage => %p, %lX\n", *ppstg, sc));
EH_Err:
return sc;
}
#if 0
//+---------------------------------------------------------------------------
//
// Function: CopyProperties, public
//
// Synopsis: Copies all properties from one property storage to another
//
// Arguments: [ppstgFrom] - Source
// [ppstgTo] - Destination
// [fSkipOid] - TRUE iff this is the system properties and we are
// to skip the object id.
//
// Returns: Appropriate status code
//
// History: 22-Sep-93 DrewB Created
//
// Notes: This function is separate only for readability, and this is
// declared inline.
//
//----------------------------------------------------------------------------
inline SCODE CopyProperties(
IPropertyStorage *ppstgFrom,
IPropertyStorage *ppstgTo,
BOOL fSkipOid )
{
SafeIEnumSTATPROPSTG penm;
STATPROPSTG stat;
SCODE sc;
PROPVARIANT var;
ssDebugOut((DEB_ITRACE, "In CopyProperties(%p, %p)\n",
ppstgFrom, ppstgTo));
olHChk(ppstgFrom->Enum(&penm));
for (;;)
{
sc = GetScode(penm->Next(1, &stat, NULL));
if (FAILED(sc) || sc == S_FALSE)
{
if (sc == S_FALSE)
sc = S_OK;
break;
}
else
{
PROPSPEC pspec;
WCHAR awcName[CWCSTORAGENAME];
if (stat.lpwstrName)
{
pspec.ulKind = PRSPEC_LPWSTR;
pspec.lpwstr = awcName;
olAssert(wcslen(stat.lpwstrName) < CWCSTORAGENAME);
wcscpy(awcName, stat.lpwstrName);
olHVerSucc(CoMemFree(stat.lpwstrName));
}
else
{
pspec.ulKind = PRSPEC_PROPID;
pspec.propid = stat.propid;
}
if ( !( fSkipOid
&& (pspec.ulKind == PRSPEC_PROPID)
&& (pspec.propid == PROPID_STG_OBJECTID)) )
{
olHChk(ppstgFrom->ReadMultiple(1, &pspec, NULL, NULL, &var));
sc = ppstgTo->WriteMultiple(1, &pspec, NULL, &var);
StgVariantClear(&var);
olChk(sc);
}
}
}
ssDebugOut((DEB_ITRACE, "Out CopyProperties\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Function: CopyPropSets, public
//
// Synopsis: Copies all property sets from one property set storage
// to another
//
// Arguments: [ppsstgFrom] - Source
// [ppsstgTo] - Destination
// [ciidExclude] - Count of IIDs to exclude
// [rgiidExclude] - IIDs to exclude from the copy
//
// Returns: Appropriate status code
//
// History: 22-Sep-93 DrewB Created
//
//----------------------------------------------------------------------------
SAFE_INTERFACE_PTR(SafeIEnumSTATPROPSETSTG, IEnumSTATPROPSETSTG);
SCODE CopyPropSets(IPropertySetStorage *ppsstgFrom,
IPropertySetStorage *ppsstgTo,
ULONG ciidExclude,
IID const *rgiidExclude)
{
SafeIEnumSTATPROPSETSTG penm;
STATPROPSETSTG stat;
SCODE sc;
ULONG i;
ULONG j;
ssDebugOut((DEB_ITRACE, "In CopyPropSets(%p, %p, %lu, %p)\n",
ppsstgFrom, ppsstgTo, ciidExclude, rgiidExclude));
// The following loop leaves j as is the index of IEnableObjectIdCopy
// if specified, or as ciidExclude is not specified.
for (j=0; j<ciidExclude;j++)
{
if (IsEqualIID(rgiidExclude[j], IID_IEnableObjectIdCopy))
break;
}
BOOL fEnableObjectIdCopy = ( j != ciidExclude );
olHChk(ppsstgFrom->Enum(&penm));
for (;;)
{
sc = GetScode(penm->Next(1, &stat, NULL));
if (FAILED(sc) || sc == S_FALSE)
{
if (sc == S_FALSE)
sc = S_OK;
break;
}
for (i = 0; i < ciidExclude; i++)
if (IsEqualIID(stat.iid, rgiidExclude[i]))
break;
if (i != ciidExclude)
{
continue;
}
else
{
SafeIPropertyStorage ppstgFrom, ppstgTo;
olHChk(ppsstgFrom->Open(stat.iid, STGM_DIRECT | STGM_READ |
STGM_SHARE_EXCLUSIVE, &ppstgFrom));
sc = GetScode(ppsstgTo->Open(stat.iid, STGM_DIRECT | STGM_WRITE |
STGM_SHARE_EXCLUSIVE, &ppstgTo));
if (sc == STG_E_FILENOTFOUND)
sc = GetScode(ppsstgTo->Create(stat.iid, STGM_DIRECT |
STGM_WRITE |
STGM_SHARE_EXCLUSIVE,
&ppstgTo));
olChk(sc);
// Does this property set contain the object id and property, and
// should we skip it?
BOOL fSkipOid = !fEnableObjectIdCopy
&& IsEqualGUID ( stat.iid, guidSysProp );
olChk(CopyProperties(ppstgFrom, ppstgTo, fSkipOid));
}
}
ssDebugOut((DEB_ITRACE, "Out CopyPropSets\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Function: PropCopyTo, public
//
// Synopsis: Performs property portion of CopyTo
//
// Arguments: [pstgFrom] - Source
// [pstgTo] - Destination
// [ciidExclude] - IID exclusions
// [rgiidExclude] - IIDs to exclude
//
// Returns: Appropriate status code
//
// History: 30-Sep-93 DrewB Created
//
// Notes: Assumes source supports IPropertySetStorage
//
//----------------------------------------------------------------------------
SAFE_INTERFACE_PTR(SafeIPropertySetStorage, IPropertySetStorage);
SCODE PropCopyTo(IStorage *pstgFrom,
IStorage *pstgTo,
ULONG ciidExclude,
IID const *rgiidExclude)
{
SCODE sc;
SafeIPropertySetStorage ppsstgFrom, ppsstgTo;
BOOL fCopyProps = TRUE;
ULONG i;
ssDebugOut((DEB_ITRACE, "In PropCopyTo(%p, %p, %lu, rgiid)\n",
pstgTo, pstgFrom, ciidExclude));
sc = S_OK;
for (i = 0; i < ciidExclude; i++)
if (IsEqualIID(rgiidExclude[i], IID_IPropertySetStorage))
{
fCopyProps = FALSE;
break;
}
if (fCopyProps)
{
olVerSucc(pstgFrom->QueryInterface(IID_IPropertySetStorage,
(void **)&ppsstgFrom));
sc = pstgTo->QueryInterface(IID_IPropertySetStorage,
(void **)&ppsstgTo);
if (SUCCEEDED(sc))
{
sc = CopyPropSets(ppsstgFrom, ppsstgTo, ciidExclude, rgiidExclude);
}
else if (sc == E_NOINTERFACE)
{
// BUGBUG - STG_E_DESTLACKSINTERFACE seems to be gone,
// but it's in the spec
// sc = STG_E_DESTLACKSINTERFACE;
}
}
ssDebugOut((DEB_ITRACE, "Out PropCopyTo => %lX\n", sc));
return sc;
}
#endif // 0
//+---------------------------------------------------------------------------
//
// Function: CopyTemplateProperties, public
//
// Synopsis: copy contents from a template object
//
// Arguments: [pstgSource] - source storage containing properties
// [pstgDest] - destination storage to receive properties
//
// Returns: Appropriate status code
//
// History: 10-July-1995 HenryLee created
//
// Notes:
//
//----------------------------------------------------------------------------
SCODE CopyTemplateProperties (IStorage *pstgSource, IStorage *pstgDest)
{
SCODE sc = S_OK;
IEnumSTATSTG *penum;
STATSTG statstg;
// BUGBUG IStorage should enumerate the OLE namespace
ssChk(pstgSource->EnumElements(NULL,NULL,NULL,&penum));
while ((sc = penum->Next(1,&statstg,NULL)) == S_OK)
{
// BUGBUG when ready, use Vic's new method to determine property set
if (statstg.pwcsName && statstg.pwcsName[0] == L'\005')
{
sc = pstgSource->MoveElementTo(statstg.pwcsName,
pstgDest, statstg.pwcsName, STGMOVE_COPY);
}
if (statstg.pwcsName)
ssVerSucc(CoMemFree(statstg.pwcsName));
if (!SUCCEEDED(sc))
break;
}
penum->Release();
if (sc == S_FALSE)
sc = S_OK;
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Function: CopyTemplateObject, public
//
// Synopsis: copy contents from a template object
//
// Arguments: [pTemplate] - source object and interfaces to copy
// [pUnkDest] - destination object
// [riid] - interface supported on destination object
//
// Returns: Appropriate status code
//
// History: 10-July-1995 HenryLee created
//
// Notes:
//
//----------------------------------------------------------------------------
SCODE CopyTemplateObject (STGTEMPLATE *pTemplate,IUnknown *pUnkDest,REFIID riid)
{
SCODE sc = S_OK;
if (pTemplate->pUnkTemplate == NULL || pTemplate->riidTemplate == NULL)
ssErr (EH_Err, STG_E_INVALIDPOINTER);
if (riid == IID_IStorage)
{
for (DWORD dw=0; dw < pTemplate->ciidTemplate; dw++)
{
if (pTemplate->riidTemplate[dw] == IID_IPropertySetStorage)
{
// enum the property sets and copy them
IStorage *pstgSource;
IStorage *pstgDest = (IStorage *) pUnkDest;
sc = pTemplate->pUnkTemplate->QueryInterface (IID_IStorage,
(void**)&pstgSource);
if (SUCCEEDED(sc))
{
sc = CopyTemplateProperties (pstgSource, pstgDest);
pstgSource->Release();
}
}
}
}
else if (riid == IID_IDirectory)
{
for (DWORD dw=0; dw < pTemplate->ciidTemplate; dw++)
{
if (pTemplate->riidTemplate[dw] == IID_IPropertySetStorage)
{
// enum the property sets and copy them
IStorage *pstgSource;
IStorage *pstgDest;
if (SUCCEEDED(sc = pTemplate->pUnkTemplate->QueryInterface
(IID_IStorage,
(void**)&pstgSource)))
{
if (SUCCEEDED(sc = pUnkDest->QueryInterface (IID_IStorage,
(void**)&pstgDest)))
{
sc = CopyTemplateProperties (pstgSource, pstgDest);
pstgDest->Release();
}
pstgSource->Release();
}
}
}
}
else if (riid == IID_IStream)
{
for (DWORD dw=0; dw < pTemplate->ciidTemplate; dw++);
{
// properties on files not supported yet
}
}
else sc = STG_E_INVALIDPARAMETER;
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Function: InitDirectory, public
//
// Synopsis: creates or opens an IDirectory object
//
// Arguments: [hParent] - parent file handle for relative opens
// [pwcsName] - directory name
// [h] - initialize with this handle
// [co] - create or open flag
// [grfMode] - open/create mode
// [pSecurity] - initial security attributes
// [scOfs] - S_OK if OFS, S_FALSE if not, STG_E_INVALIDFLAG
// [riid] - IID of interface pointer to return
// [ppObjectOpen] - interface pointer to return
//
// Returns: Appropriate status code
//
// History: 10-July-1995 HenryLee created
//
// Notes:
//
//----------------------------------------------------------------------------
SCODE InitDirectory (HANDLE hParent,
WCHAR const *pwcsName,
HANDLE h,
CREATEOPEN co,
STGOPEN *pStgOpen,
STGCREATE *pStgCreate,
SCODE scOfs,
REFIID riid,
void ** ppObjectOpen)
{
SCODE sc = S_OK;
COfsDirStorage *pds;
LPSECURITY_ATTRIBUTES pSecurity = NULL;
ssAssert (pStgOpen != NULL);
// if (co == CO_CREATE) ssAssert (pStgCreate != NULL);
ssAssert (!(co == CO_CREATE) || pStgCreate != NULL);
*ppObjectOpen = NULL;
if (co == CO_CREATE)
{
if (pStgOpen->grfMode & (STGM_CONVERT | STGM_SIMPLE))
ssErr(EH_Err, STG_E_INVALIDFLAG);
// BUGBUG convert OBJECT_SECURITY_INIT to SECURITY_ATTRIBUTES
pSecurity = (LPSECURITY_ATTRIBUTES) pStgCreate->pSecurity;
}
else if (co == CO_OPEN)
{
if (pStgOpen->grfMode & (STGM_CREATE | STGM_CONVERT | STGM_SIMPLE |
STGM_DELETEONRELEASE))
ssErr(EH_Err, STG_E_INVALIDFLAG);
}
else ssErr (EH_Err, STG_E_INVALIDPARAMETER);
if (scOfs == STG_E_INVALIDFLAG)
if (hParent != NULL)
scOfs = HandleRefersToOfsVolume (hParent);
else
ssChk (scOfs = RefersToOfsVolume (pwcsName, CO_CREATE));
pds = new COfsDirStorage(scOfs == S_OK ? TRUE : FALSE);
ssMem((COfsDirStorage *)pds);
if (h != NULL)
{
ssChk(pds->InitFromHandle(h, pwcsName, pStgOpen->grfMode));
}
else
{
ssChk(pds->InitFromPath(hParent, pwcsName, pStgOpen->grfMode,
co, pStgOpen->stgfmt==STGFMT_JUNCTION, pSecurity));
}
sc = pds->QueryInterface (riid, ppObjectOpen);
// success case, undo QI AddRef
pds->Release(); // failure case, destroy obj
if (co == CO_CREATE && pStgCreate->pTemplate != NULL)
{
IDirectory * pdir = (IDirectory *) pds;
CopyTemplateObject (pStgCreate->pTemplate, pdir, IID_IDirectory);
}
EH_Err:
return sc;
};
//+---------------------------------------------------------------------------
//
// Function: InitStorage, public
//
// Synopsis: creates or opens an IStorage object
//
// Arguments: [hParent] - parent file handle for relative opens
// [pwcsName] - directory name
// [h] - initialize with this handle (not supported)
// [grfMode] - open/create mode
// [stgfmt] - intended storage format
// [co] - create or open flag
// [pSecurity] - initial security attributes
// [wcDrive] - drive letter of hParent
// [pscOfs] - if hParent is on an OFS drive
// [riid] - IID of interface pointer to return
// [ppObjectOpen] - interface pointer to return
//
// Returns: Appropriate status code
//
// History: 10-July-1995 HenryLee created
//
// Notes:
//
//
//----------------------------------------------------------------------------
SCODE InitStorage (HANDLE hParent,
WCHAR const *pwcsName,
HANDLE h,
CREATEOPEN co,
STGOPEN *pStgOpen,
STGCREATE *pStgCreate,
WCHAR const wcDrive,
SCODE *pscOfs,
BOOL fRestricted,
REFIID riid,
void **ppObjectOpen)
{
SCODE sc = S_OK;
DWORD dwStgfmt = STGFMT_DOCUMENT;
IStorage *pstg;
NTSTATUS nts;
LPSECURITY_ATTRIBUTES pSecurity = NULL;
ssAssert (pscOfs != NULL);
ssAssert (pStgOpen != NULL);
// if (co == CO_CREATE) ssAssert (pStgCreate != NULL);
ssAssert (!(co == CO_CREATE) || pStgCreate != NULL);
STGFMT stgfmt = pStgOpen->stgfmt;
if (*pscOfs == STG_E_INVALIDFLAG) // true, false, or uninitialized
if (hParent != NULL)
*pscOfs = HandleRefersToOfsVolume (hParent);
else
{
#ifdef TRANSACT_OLE
ssChk (sc = RefersToOfsVolume (pwcsName, CO_CREATE));
#else
ssChk (sc = RefersToOfsVolume (pwcsName, co));
#endif
*pscOfs = sc;
}
#ifdef TRANSACT_OLE
if (*pscOfs == S_OK && stgfmt != STGFMT_DOCFILE)
{
if (fRestricted && // Dsys API, no direct mode
(pStgOpen->grfMode & STGM_TRANSACTED) == 0)
ssErr (EH_Err, STG_E_INVALIDPARAMETER);
if (!fRestricted && // Stg API, map transacted into direct
(pStgOpen->grfMode & STGM_TRANSACTED))
pStgOpen->grfMode &= ~STGM_TRANSACTED;
}
#endif
if (co == CO_CREATE)
{
// BUGBUG convert OBJECT_SECURITY_INIT to SECURITY_ATTRIBUTES
pSecurity = (LPSECURITY_ATTRIBUTES) pStgCreate->pSecurity;
if (*pscOfs == S_OK && stgfmt != STGFMT_DOCFILE)
{
if (stgfmt == STGFMT_STORAGE)
stgfmt = STGFMT_DOCUMENT;
sc = OfsCreateStorageType(hParent, pwcsName,NULL,pStgOpen->grfMode,
(DWORD) stgfmt, pSecurity,
TRUE, &pstg);
}
else
{
ssAssert ((*pscOfs == S_FALSE || stgfmt == STGFMT_DOCFILE));
// structured storage and summary catalog not supported non-OFS
if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_CATALOG)
ssErr (EH_Err, STG_E_INVALIDFUNCTION);
if (stgfmt == STGFMT_DOCFILE)
stgfmt = STGFMT_DOCUMENT;
WCHAR awcsFullName[_MAX_PATH];
if (hParent != NULL)
sc = NameNtHandle (hParent, wcDrive, awcsFullName, pwcsName);
else
wcscpy (awcsFullName, pwcsName);
sc = DfCreateDocfile (awcsFullName,
pStgOpen->pTransaction,
pStgOpen->grfMode,
#if WIN32 == 300
pSecurity, &pstg);
#else
0, &pstg);
#endif
}
}
else if (co == CO_OPEN)
{
if (*pscOfs == S_OK && stgfmt != STGFMT_DOCFILE)
{
if (stgfmt == STGFMT_DOCUMENT || stgfmt == STGFMT_STORAGE)
{
sc = OfsDocOpenStorage(hParent, pwcsName, &h,
NULL, pStgOpen->grfMode,
NULL, TRUE, &pstg);
}
else if (stgfmt == STGFMT_CATALOG)
{
SafeCOfsCatalogFile pcf;
pcf.Attach(new COfsCatalogFile());
ssMem((COfsCatalogFile *)pcf);
ssChk(pcf->InitPath(pwcsName));
ssChk(GetNtHandle(hParent, pwcsName, pStgOpen->grfMode, 0, co,
FD_CATALOG, NULL, &h));
ssChk(pcf->InitFromHandle(h, pStgOpen->grfMode, pwcsName));
TRANSFER_INTERFACE(pcf, IStorage, &pstg);
}
else ssErr (EH_Err, STG_E_INVALIDFUNCTION);
}
else
{
ssAssert ((*pscOfs == S_FALSE || stgfmt == STGFMT_DOCFILE));
// structured storage and summary catalog not supported non-OFS
if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_CATALOG)
ssErr (EH_Err, STG_E_INVALIDFUNCTION);
WCHAR pwcsFullName[_MAX_PATH];
if (stgfmt == STGFMT_CATALOG)
ssErr (EH_Err, STG_E_INVALIDFLAG);
if (hParent != NULL)
ssChk(NameNtHandle (hParent,wcDrive,pwcsFullName,pwcsName));
else
wcscpy (pwcsFullName, pwcsName);
//BUGBUG: Remove cast on pTransaction
sc = DfOpenDocfile (pwcsFullName,
(ITransaction *)pStgOpen->pTransaction,
NULL, pStgOpen->grfMode,
NULL, NULL, &pstg);
}
}
else ssErr (EH_Err, STG_E_INVALIDPARAMETER);
if (SUCCEEDED(sc))
{
sc = pstg->QueryInterface (riid, ppObjectOpen);
// success case, undo QI AddRef
pstg->Release(); // failure case, destroy obj
}
if (co == CO_CREATE && pStgCreate->pTemplate != NULL)
CopyTemplateObject (pStgCreate->pTemplate, pstg, IID_IStorage);
EH_Err:
return sc;
};