Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

517 lines
12 KiB

/*
* X L O C K . C P P
*
* XML push model parsing for LOCK requests
*
* Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
*/
#include "_xml.h"
#include <xlock.h>
#include <statetok.h>
// Here are our LOCK XML elements
//
const WCHAR gc_wszLockActive[] = L"DAV:activelock";
const WCHAR gc_wszLockDepth[] = L"DAV:depth";
const WCHAR gc_wszLockDiscovery[] = L"DAV:lockdiscovery";
const WCHAR gc_wszLockEntry[] = L"DAV:lockentry";
const WCHAR gc_wszLockInfo[] = L"DAV:lockinfo";
const WCHAR gc_wszLockOwner[] = L"DAV:owner";
const WCHAR gc_wszLockScope[] = L"DAV:lockscope";
const WCHAR gc_wszLockScopeExclusive[] = L"DAV:exclusive";
const WCHAR gc_wszLockScopeShared[] = L"DAV:shared";
const WCHAR gc_wszLockSupportedlock[] = L"DAV:supportedlock";
const WCHAR gc_wszLockTimeout[] = L"DAV:timeout";
const WCHAR gc_wszLockToken[] = L"DAV:locktoken";
const WCHAR gc_wszLockType[] = L"DAV:locktype";
const WCHAR gc_wszLockTypeWrite[] = L"DAV:write";
const WCHAR gc_wszLockTypeCheckout[] = L"DAV:checkout";
const WCHAR gc_wszLockTypeTransaction[] = L"DAV:transaction";
const WCHAR gc_wszLockTypeTransactionGOP[] = L"DAV:groupoperation";
const WCHAR gc_wszLockScopeLocal[] = L"DAV:local";
// And one item from the rollback draft.
//
const WCHAR gc_wszLockRollback[] = L"http://www.iana.org/experimental/msrollback/rollback";
// UNLOCK xml elememts
//
const WCHAR gc_wszUnlockInfo[] = L"DAV:unlockinfo";
const WCHAR gc_wszCancelCheckout[] = L"DAV:cancelcheckout";
const WCHAR gc_wszComment[] = L"DAV:comment";
const WCHAR gc_wszTransactionInfo[] = L"DAV:transactioninfo";
const WCHAR gc_wszTransactionStatus[] = L"DAV:transactionstatus";
const WCHAR gc_wszCommit[] = L"DAV:commit";
const WCHAR gc_wszAbort[] = L"DAV:abort";
// class CNFLock -------------------------------------------------------------
//
SCODE
CNFLock::ScCompleteAttribute (void)
{
// When we have gotten here, we have started processing
// owner node attributes and all cached namespaces have
// been added.
//
if (m_state == ST_OWNER)
return m_xo.ScCompleteChildren ( FALSE, XML_ATTRIBUTE, L"", 0 );
return S_OK;
}
SCODE
CNFLock::ScCompleteChildren (
/* [in] */ BOOL fEmptyNode,
/* [in] */ DWORD dwType,
/* [in] */ const WCHAR __RPC_FAR *pwcText,
/* [in] */ ULONG ulLen)
{
SCODE sc = S_OK;
// Handle owner processing first....
//
if (ST_OWNER == m_state)
{
sc = m_xo.ScCompleteChildren (fEmptyNode,
dwType,
pwcText,
ulLen);
if (FAILED (sc))
goto ret;
}
// Handle the rest...
//
switch (dwType)
{
case XML_ELEMENT:
switch (m_state)
{
case ST_LOCKINFO:
m_state = ST_NODOC;
break;
case ST_OWNER:
if (0 == m_xo.LDepth())
{
// Complete the owner comment buffer
//
m_state = ST_LOCKINFO;
m_sbOwner.Append (sizeof(WCHAR), L"\0");
XmlTrace ("Xml: Lock: owner XML body:\n%ws\n",
m_sbOwner.PContents());
}
break;
case ST_TYPE:
m_state = ST_LOCKINFO;
break;
case ST_INTYPE:
m_state = ST_TYPE;
break;
case ST_INTYPE_TRANS:
m_state = ST_INTYPE;
break;
case ST_SCOPE:
m_state = ST_LOCKINFO;
break;
case ST_INSCOPE:
m_state = ST_SCOPE;
break;
case ST_ROLLBACK:
m_state = ST_LOCKINFO;
break;
}
}
ret:
return sc;
}
SCODE
CNFLock::ScHandleNode (
/* [in] */ DWORD dwType,
/* [in] */ DWORD dwSubType,
/* [in] */ BOOL fTerminal,
/* [in] */ const WCHAR __RPC_FAR *pwcText,
/* [in] */ ULONG ulLen,
/* [in] */ ULONG ulNamespaceLen,
/* [in] */ const WCHAR __RPC_FAR *pwcNamespace,
/* [in] */ const ULONG ulNsPrefixLen)
{
CStackBuffer<WCHAR> wsz;
LPCWSTR pwszTag = NULL;
SCODE sc = S_FALSE;
UINT cch;
switch (dwType)
{
case XML_ELEMENT:
// Construct the full name of the node
//
cch = ulNamespaceLen + ulLen;
pwszTag = wsz.resize(CbSizeWsz(cch));
if (NULL == pwszTag)
{
sc = E_OUTOFMEMORY;
break;
}
wcsncpy (wsz.get(), pwcNamespace, ulNamespaceLen);
wcsncpy (wsz.get() + ulNamespaceLen, pwcText, ulLen);
*(wsz.get() + cch) = 0;
switch (m_state)
{
case ST_NODOC:
// If this is the topmost node in a propfind request,
// transition to the next state. Since there is no parent
// node to provide scoping, FIsTag() cannot be used here!
//
if (!wcscmp (pwszTag, gc_wszLockInfo))
{
m_state = ST_LOCKINFO;
sc = S_OK;
}
break;
case ST_LOCKINFO:
// Look for our well know node types
//
if (FIsTag (pwszTag, gc_wszLockOwner))
{
CEmitNmspc cen(m_xo);
// Make the state transition and start recording
//
m_sbOwner.Reset();
m_state = ST_OWNER;
sc = m_xo.ScHandleNode (dwType,
dwSubType,
fTerminal,
pwcText,
ulLen,
ulNamespaceLen,
pwcNamespace,
ulNsPrefixLen);
// Spit out the namespaces.
//
// Note that this will spit out any namespaces
// decl'd in the DAV:owner node itself. So we
// do not really want to emit these out to the
// owners comments until ScCompleteAttribute()
// is called.
//
Assert (!m_xo.FAddNamespaceDecl());
m_cache.ForEach(cen);
sc = S_OK;
}
else if (FIsTag (pwszTag, gc_wszLockRollback))
{
m_dwRollback = DAV_LOCKTYPE_ROLLBACK;
m_state = ST_ROLLBACK;
sc = S_OK;
}
else if (FIsTag (pwszTag, gc_wszLockType))
{
m_state = ST_TYPE;
sc = S_OK;
}
else if (FIsTag (pwszTag, gc_wszLockScope))
{
m_state = ST_SCOPE;
sc = S_OK;
}
break;
case ST_TYPE:
if (FIsTag (pwszTag, gc_wszLockTypeWrite))
{
XmlTrace ("Xml: Lock: request is for a WRITE lock\n");
m_dwLockType |= GENERIC_WRITE;
m_state = ST_INTYPE;
sc = S_OK;
}
else if (FIsTag (pwszTag, gc_wszLockTypeCheckout))
{
XmlTrace ("Xml: Lock: request is for a CHECKOUT lock\n");
m_dwLockType |= DAV_LOCKTYPE_CHECKOUT;
m_state = ST_INTYPE;
sc = S_OK;
}
else if (FIsTag (pwszTag, gc_wszLockTypeTransaction))
{
XmlTrace ("Xml: Lock: request is for a TRANSACTION lock\n");
m_state = ST_INTYPE_TRANS;
sc = S_OK;
}
#ifdef DBG
if (!_wcsicmp (pwszTag, L"read"))
{
XmlTrace ("Xml: Lock: request is for a READ lock\n");
m_dwLockType |= GENERIC_READ;
m_state = ST_INTYPE;
sc = S_OK;
}
#endif // DBG
break;
case ST_SCOPE:
if (FIsTag (pwszTag, gc_wszLockScopeExclusive))
{
XmlTrace ("Xml: Lock: request is for an EXCLUSE lock\n");
m_dwScope = DAV_EXCLUSIVE_LOCK;
m_state = ST_INSCOPE;
sc = S_OK;
}
else if (FIsTag (pwszTag, gc_wszLockScopeShared))
{
XmlTrace ("Xml: Lock: request is for a SHARED lock\n");
m_dwScope = DAV_SHARED_LOCK;
m_state = ST_INSCOPE;
sc = S_OK;
}
else if (FIsTag (pwszTag, gc_wszLockScopeLocal))
{
XmlTrace ("Xml: Lock: request is for a LOCAL scope lock\n");
m_dwScope = DAV_LOCKSCOPE_LOCAL;
m_state = ST_INSCOPE;
sc = S_OK;
}
break;
case ST_OWNER:
sc = m_xo.ScHandleNode (dwType,
dwSubType,
fTerminal,
pwcText,
ulLen,
ulNamespaceLen,
pwcNamespace,
ulNsPrefixLen);
break;
case ST_INTYPE_TRANS:
if (FIsTag (pwszTag, gc_wszLockTypeTransactionGOP))
{
XmlTrace ("Xml: Lock: request is for a TRANSACTION GOP lock\n");
m_dwLockType |= DAV_LOCKTYPE_TRANSACTION_GOP;
m_state = ST_INTYPE_TRANS;
sc = S_OK;
}
}
break;
default:
// If we are processing the owner, continue
// to do so...
//
if (ST_OWNER == m_state)
{
sc = m_xo.ScHandleNode (dwType,
dwSubType,
fTerminal,
pwcText,
ulLen,
ulNamespaceLen,
pwcNamespace,
ulNsPrefixLen);
}
break;
}
return sc;
}
SCODE
CNFLock::ScCompleteCreateNode (
/* [in] */ DWORD dwType)
{
if (ST_OWNER == m_state)
m_xo.CompleteCreateNode (dwType);
return S_OK;
}
// class CNFUnlock -------------------------------------------------------------
//
SCODE
CNFUnlock::ScCompleteAttribute (void)
{
return S_OK;
}
SCODE
CNFUnlock::ScCompleteChildren (
/* [in] */ BOOL fEmptyNode,
/* [in] */ DWORD dwType,
/* [in] */ const WCHAR __RPC_FAR *pwcText,
/* [in] */ ULONG ulLen)
{
// Handle the rest...
//
switch (m_state)
{
case ST_UNLOCKINFO:
m_state = ST_NODOC;
break;
case ST_COMMENT:
case ST_CANCELCHECKOUT:
m_state = ST_UNLOCKINFO;
break;
}
return S_OK;
}
SCODE
CNFUnlock::ScHandleNode (
/* [in] */ DWORD dwType,
/* [in] */ DWORD dwSubType,
/* [in] */ BOOL fTerminal,
/* [in] */ const WCHAR __RPC_FAR *pwcText,
/* [in] */ ULONG ulLen,
/* [in] */ ULONG ulNamespaceLen,
/* [in] */ const WCHAR __RPC_FAR *pwcNamespace,
/* [in] */ const ULONG ulNsPrefixLen)
{
CStackBuffer<WCHAR> wsz;
LPCWSTR pwszTag = NULL;
SCODE sc = S_FALSE;
UINT cch;
switch (dwType)
{
case XML_ELEMENT:
// Construct the full name of the node
//
cch = ulNamespaceLen + ulLen;
pwszTag = wsz.resize(CbSizeWsz(cch));
if (NULL == pwszTag)
{
sc = E_OUTOFMEMORY;
break;
}
wcsncpy (wsz.get(), pwcNamespace, ulNamespaceLen);
wcsncpy (wsz.get() + ulNamespaceLen, pwcText, ulLen);
*(wsz.get() + cch) = 0;
switch (m_state)
{
case ST_NODOC:
// If this is the topmost node in a propfind request,
// transition to the next state. Since there is no parent
// node to provide scoping, FIsTag() cannot be used here!
//
if (!wcscmp (pwszTag, gc_wszUnlockInfo))
{
m_state = ST_UNLOCKINFO;
sc = S_OK;
}
else if (FIsTag (pwszTag, gc_wszTransactionInfo))
{
m_state = ST_TRANSACTIONINFO;
sc = S_OK;
}
break;
case ST_UNLOCKINFO:
// Look for our well know node types
//
if (FIsTag (pwszTag, gc_wszComment))
{
m_state = ST_COMMENT;
sc = S_OK;
}
else if (FIsTag (pwszTag, gc_wszCancelCheckout))
{
m_fCancelCheckout = TRUE;
m_state = ST_CANCELCHECKOUT;
sc = S_OK;
}
break;
case ST_TRANSACTIONINFO:
// Look for our well know node types
//
if (FIsTag (pwszTag, gc_wszTransactionStatus))
{
m_state = ST_TRANSACTIONSTATUS;
sc = S_OK;
}
break;
case ST_TRANSACTIONSTATUS:
// Look for our well know node types
//
if (FIsTag (pwszTag, gc_wszCommit))
{
m_fCommitTransaction = TRUE;
m_state = ST_TRANSACTIONSTATUS_COMMIT;
sc = S_OK;
}
else if (FIsTag (pwszTag, gc_wszAbort))
{
m_fAbortTransaction = TRUE;
m_state = ST_TRANSACTIONSTATUS_ABORT;
sc = S_OK;
}
break;
}
break;
case XML_PCDATA:
// get unlock comment
//
if (m_state == ST_COMMENT)
{
// Keep the comment
// It's a syntax error to have more than one comment
//
if (!m_wszComment.get())
{
m_wszComment = reinterpret_cast<LPWSTR>(ExAlloc((ulLen + 1) * sizeof(WCHAR)));
Assert (m_wszComment.get());
wcsncpy (m_wszComment.get(), pwcText, ulLen);
m_wszComment[ulLen] = L'\0';
sc = S_OK;
}
// else it's an error
else
sc = E_DAV_XML_PARSE_ERROR;
}
break;
}
return sc;
}