⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 davlock.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	m_pLockList    = pLock;

	return TRUE;
}

void CWebDavFileNode::DeInitAndFreeLock(CWebDavLock *pLockList) {
	DebugCheckCacheManagerLocked();
	pLockList->DeInitLock();
	g_pFileLockManager->FreeFixedLock(pLockList);
}

BOOL CWebDavFileNode::DeleteLock(CWebDavLock *pLockList) {
	DebugCheckCacheManagerLocked();

	// If another thread is using lock in PUT/MOVE/COPY/... then leave it alone.
	if (IsBusy())
		return FALSE;

	CWebDavLock *pTrav   = m_pLockList;
	CWebDavLock *pFollow = NULL;

	// remove item from linked list
	while (pTrav && (pTrav != pLockList)) {
		pFollow = pTrav;
		pTrav   = pTrav->m_pNext;
	}
	DEBUGCHK(pTrav); // pLockList must be a valid node.

	if (pFollow)
		pFollow->m_pNext = pTrav->m_pNext;
	else {
		DEBUGCHK(pLockList == m_pLockList);
		m_pLockList = pLockList->m_pNext;
	}

	DeInitAndFreeLock(pLockList);
	return TRUE;
}

void CWebDavFileNode::RemoveTimedOutLocks(FILETIME *pft) {
	DebugCheckCacheManagerLocked();

	// If another thread is using lock in PUT/MOVE/COPY/... then leave it alone.
	if (IsBusy())
		return;

	CWebDavLock *pTrav   = m_pLockList;
	CWebDavLock *pFollow = NULL;

	while (pTrav) {
		CWebDavLock *pNext = pTrav->m_pNext;

		if (pTrav->HasLockExpired(pft)) {
			DEBUGMSG(ZONE_WEBDAV,(L"HTTPD: Lock for file %s, lockID=%I64d has expired, removing\r\n",m_szFileName,pTrav->m_i64LockId));
			DeInitAndFreeLock(pTrav);

			if (pFollow)
				pFollow->m_pNext = pNext;
			else {
				DEBUGCHK(pTrav == m_pLockList);
				m_pLockList = pNext;
			}
		}
		else {
			pFollow = pTrav;
		}
		pTrav = pNext;
	}
}


BOOL CWebDavFileNode::HasLockId(__int64 iLockId, CWebDavLock **ppLockMatch) {
	DEBUGCHK(m_pLockList); // if list is NULL, *this should've been deleted.
	DebugCheckCacheManagerLocked();

	CWebDavLock *pLock = m_pLockList;

	while (pLock) {
		if (pLock->m_i64LockId == iLockId) {
			if (ppLockMatch)
				*ppLockMatch = pLock;
			return TRUE;
		}

		pLock = pLock->m_pNext;
	}
	return FALSE;
}

// A client has passed one or more LockIDs to our server.  Verify that at least one
// of them corresponds with the lockIDs associated with this file.
BOOL CWebDavFileNode::HasLockIdInArray(LockIdArray *pLockIDs, int numLockIds) {
	DebugCheckCacheManagerLocked();
	DEBUGCHK(pLockIDs && numLockIds);	

	for (int i = 0; i < numLockIds; i++) {
		if (HasLockId((*pLockIDs)[i]))
			return TRUE;
	}
	return FALSE;
}

// 
//  Utility
//
unsigned short us_rand (void) {
	unsigned short usRes = (unsigned short)rand();
	if (rand() > RAND_MAX / 2)
		usRes |= 0x8000;

	return usRes;
}

typedef int (*CeGenerateGUID_t) (GUID *);

void GenerateGUID (GUID *pGuid) {
	HMODULE hLib = LoadLibrary (L"\\windows\\lpcrt.dll");
	if (hLib) {
		CeGenerateGUID_t CeGenerateGUID = (CeGenerateGUID_t)GetProcAddress (hLib, L"CeGenerateGUID");
		int fRet = (CeGenerateGUID && CeGenerateGUID (pGuid) == 0);
		FreeLibrary (hLib);

		if (fRet)
			return;
	}

	srand (GetTickCount ());
	pGuid->Data1 = (us_rand () << 16) | us_rand();
	pGuid->Data2 = us_rand();
	pGuid->Data3 = us_rand();
	for (int i = 0 ; i < 8 ; i += 2) {
		unsigned short usRand = us_rand();
		pGuid->Data4[i]     = (unsigned char)(usRand & 0xff);
		pGuid->Data4[i + 1] = (unsigned char)(usRand >> 8);
	}
}

//
// CWebDavFileLockManager
//

// start with same LockID as IIS
#define DAV_INITIAL_LOCK_ID      ((((__int64)50 << 32)) + 50)

#if defined (DEBUG)
// Debug verification that CWebDavFileLockManager is only instantiated once 
// per web server being loaded / unloaded
int cWebDavFileLockManagerInitializations = 0;
#endif

CWebDavFileLockManager::CWebDavFileLockManager() {
#if defined (DEBUG)
	DEBUGCHK(cWebDavFileLockManagerInitializations == 0);
	cWebDavFileLockManagerInitializations++;
#endif

	m_pFileLockList = NULL;

	m_iNextLockId = DAV_INITIAL_LOCK_ID;

	GUID lockGuid;
	GenerateGUID(&lockGuid);

	HRESULT hr = StringCchPrintfA(m_szLockGUID,SVSUTIL_ARRLEN(m_szLockGUID),SVSUTIL_GUID_FORMAT_A,SVSUTIL_RGUID_ELEMENTS(lockGuid));
	DEBUGCHK(hr == S_OK && (strlen(m_szLockGUID) == SVSUTIL_GUID_STR_LENGTH));

	m_pfmdFileNodes = svsutil_AllocFixedMemDescr (sizeof(CWebDavFileNode), 10);
	m_pfmdLocks = svsutil_AllocFixedMemDescr (sizeof(CWebDavLock), 10);

	m_pFileLockList = NULL;
}

CWebDavFileLockManager::~CWebDavFileLockManager() {
	DEBUGCHK(g_fState == SERVICE_STATE_SHUTTING_DOWN || g_fState == SERVICE_STATE_UNLOADING);

	Lock();

	// remove everything in FileLock List
	while (m_pFileLockList) {
		CWebDavFileNode *pNext = m_pFileLockList->m_pNext;
		DeInitAndFreeFileNode(m_pFileLockList);
		m_pFileLockList = pNext;
	}

	if (m_pfmdFileNodes)
		svsutil_ReleaseFixedNonEmpty(m_pfmdFileNodes);

	if (m_pfmdLocks)
		svsutil_ReleaseFixedNonEmpty (m_pfmdLocks);

	Unlock();
}


CWebDavFileNode* CWebDavFileLockManager::GetNodeFromID(__int64 iLockId, CWebDavLock **ppLockMatch) {
	DEBUGCHK(IsLocked());
	CWebDavFileNode *pFile = m_pFileLockList;

	while (pFile) {
		if (pFile->HasLockId(iLockId,ppLockMatch))
			return pFile;

		pFile = pFile->m_pNext;
	}
	return NULL;
}

CWebDavFileNode * CWebDavFileLockManager::GetNodeFromFileName(WCHAR *szFileName) {
	DEBUGCHK(IsLocked());
	CWebDavFileNode *pTrav = m_pFileLockList;

	while (pTrav) {
		if (0 == PathNameCompare(pTrav->m_szFileName,szFileName))
			return pTrav;

		pTrav = pTrav->m_pNext;
	}
	return NULL;
}

BOOL CWebDavFileLockManager::IsFileAssociatedWithLockId(WCHAR *szFileName, __int64 iLockId) {
	BOOL fRet = FALSE;
	Lock();

	CWebDavFileNode *pFileNode = GetNodeFromFileName(szFileName);

	if (pFileNode)
		fRet = pFileNode->HasLockId(iLockId);

	Unlock();

#if defined (DEBUG)
	if (!fRet)
		DEBUGMSG(ZONE_WEBDAV,(L"HTTPD: File <%s> is not associated with LockID %I64d\r\n",szFileName,iLockId));
#endif

	return fRet;
}

	
void CWebDavFileLockManager::RemoveTimedOutLocks(void) {
	Lock();

	FILETIME ft;
	GetCurrentFT(&ft);

	DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: file lock cleanup thread woke up, ft.dwHighDateTime = 0x%08x, ft.dwLowDateTime = 0x%08x\r\n",
	                              ft.dwHighDateTime,ft.dwLowDateTime));

	CWebDavFileNode *pTrav   = m_pFileLockList;
	CWebDavFileNode *pFollow = NULL;

	while (pTrav) {
		CWebDavFileNode *pNext = pTrav->m_pNext;
		pTrav->RemoveTimedOutLocks(&ft);

		// if there are no more locks associated with file resource, remove the node.
		if (! pTrav->HasLocks()) { 
			DeInitAndFreeFileNode(pTrav);
			
			if (pFollow)
				pFollow->m_pNext = pNext;
			else {
				DEBUGCHK(pTrav == m_pFileLockList);
				m_pFileLockList = pNext;
			}
		}
		else {
			pFollow = pTrav;
		}
		pTrav = pNext;
	}

	Unlock();
}

void CWebDavFileLockManager::DeInitAndFreeFileNode(CWebDavFileNode *pFileNode) {
	DEBUGCHK(IsLocked());
	pFileNode->DeInitFileNode();
	svsutil_FreeFixed(pFileNode,m_pfmdFileNodes);
}

BOOL CWebDavFileLockManager::CreateLock(CLockParse *pLockParams, CWebDav *pWebDav) {
	CWebDavFileNode *pFileNode        = NULL;
	CWebDavLock     *pLock            = NULL;
	BOOL       fRet                   = FALSE;
	HANDLE     hFile                  = INVALID_HANDLE_VALUE;
	WCHAR      *szFile                = pWebDav->m_pRequest->m_wszPath;
	DWORD      dwTimeout              = 0;
	BOOL       fCreateFileNode        = TRUE;
	BOOL       fFileCreated           = FALSE;
	CHAR       szLockToken[256];      // response header "Lock-token: <opaquelocktoken:GUID:LockID>"
	__int64    iLockId;


	if (pLockParams->m_lockShareMode == DAV_LOCK_UNKNOWN) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: LOCK fails, client did not set <lockscope> to <exclusive> or <shared>\r\n"));
		pWebDav->SetStatus(STATUS_BADREQ);
		return FALSE;
	}

	// Get HTTP timeout header.  If timeout not set, then no problem (will use default)
	// Function will return FALSE on syntax errors
	if (!pWebDav->GetLockTimeout(&dwTimeout))
		return FALSE;

	if (dwTimeout == 0)
		dwTimeout = pWebDav->m_pRequest->m_pWebsite->m_dwDavDefaultLockTimeout; 

	Lock();

	if (NULL != (pFileNode = GetNodeFromFileName(szFile))) {
		// found the file already has a lock associated with it.
		fCreateFileNode = FALSE;

		if (pFileNode->IsExclusiveLock() || (pLockParams->m_lockShareMode == DAV_LOCK_EXCLUSIVE)) {
			DEBUGMSG(ZONE_ERROR,(L"HTTPD: LOCK attempted to either gain exclusive ownership of an existing lock, or shared ownership of an exclusive lock for file <%s>\r\n",szFile));
			pWebDav->SetStatusAndXMLBody(STATUS_LOCKED);
			pWebDav->SendLockTags(pFileNode);
			goto done;
		}
	}

	if (fCreateFileNode) {
		// file does not have a lock associated with it already, create a new one now.
		DEBUGCHK(!pFileNode);

		if (INVALID_HANDLE_VALUE == (hFile = CreateFile(szFile,DAV_FILE_ACCESS,DAV_SHARE_ACCESS,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))) {
			DEBUGMSG(ZONE_ERROR,(L"HTTPD: LOCK call to CreateFile(%s) failed, GLE=0x%08x\r\n",szFile,GetLastError()));
			pWebDav->SetStatus(GLEtoStatus());
			goto done;
		}
		fFileCreated = (GetLastError() != ERROR_ALREADY_EXISTS);

		if (NULL == (pFileNode = (CWebDavFileNode*) svsutil_GetFixed(m_pfmdFileNodes))) {
			pWebDav->SetStatus(STATUS_INTERNALERR);
			goto done;
		}

		if (! pFileNode->InitFileNode(szFile,pLockParams->m_lockShareMode,hFile)) {
			pWebDav->SetStatus(STATUS_INTERNALERR);
			goto done;
		}
	}

	iLockId = GetNextID();
	if (! pFileNode->AddLock(pLockParams->m_szLockOwner,pLockParams->m_NSList,iLockId,dwTimeout)) {
		pWebDav->SetStatus(STATUS_INTERNALERR);
		goto done;
	}

	// after this point no calls that can fail should be added, or if they are
	// be sure to cleanup linked list in 'done:' handeling.
	if (fCreateFileNode) {
		pFileNode->m_pNext = m_pFileLockList;
		m_pFileLockList    = pFileNode;
	}

	if (fFileCreated) {
		pWebDav->m_pRequest->m_bufRespHeaders.AppendData(cszLocation,ccLocation);
		pWebDav->m_pRequest->m_bufRespHeaders.AppendData(" ",1);
		pWebDav->BuildBaseURLFromSourceURL(TRUE);
	}

	WriteOpaqueLockToken(szLockToken,iLockId,TRUE);
	pWebDav->m_pRequest->m_bufRespHeaders.AddHeader(cszLockToken,szLockToken,FALSE);

	pWebDav->SetStatusAndXMLBody(fFileCreated ? STATUS_CREATED : STATUS_OK);
	pWebDav->SendLockTags(pFileNode);

	fRet = TRUE;
done:
	DEBUGCHK(IsLocked());

	if (!fRet) {
		if (hFile != INVALID_HANDLE_VALUE)
			CloseHandle(hFile);
		
		if (fCreateFileNode && pFileNode)
			pFileNode->DeInitFileNode();
	}
#if defined (DEBUG)
	else 
		DEBUGMSG(ZONE_WEBDAV,(L"HTTPD: LOCK created lock for file %s, lockID=%I64d, timeout=%d seconds\r\n",szFile,iLockId,dwTimeout));
#endif

	Unlock();
	return fRet;
}


BOOL CWebDavFileLockManager::CanPerformLockedOperation(WCHAR *szFile1, WCHAR *szFile2, LockIdArray *pLockIDs, int numLocks, CWebDavFileNode **ppFileNode1, CWebDavFileNode **ppFileNode2) {
	DEBUGCHK(IsLocked());
	BOOL fRet = FALSE;

	CWebDavFileNode *pFileNode1 = NULL;
	CWebDavFileNode *pFileNode2 = NULL;

	pFileNode1 = GetNodeFromFileName(szFile1);
	if (szFile2)
		pFileNode2 = GetNodeFromFileName(szFile2);

	if (numLocks == 0) {
		if (pFileNode1 || pFileNode2) {
			DEBUGMSG(ZONE_ERROR,(L"HTTPD: File %s and/or %s require a lock token for access, but none sent by client\r\n",szFile1,szFile2));
			goto done;
		}
		fRet = TRUE;
		goto done;
	}

	if (!pFileNode1 && !pFileNode2) {
		DEBUGMSG(ZONE_WEBDAV,(L"HTTPD: CanPerformLockedOperation cannot proceed, neither %s nor %s have any locks associated with them\r\n",szFile1,szFile2));
		goto done;
	}
	
	if (pFileNode1 && !pFileNode1->HasLockIdInArray(pLockIDs,numLocks)) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: File %s has lock, but none of client lockIDS match\r\n",szFile1));
		goto done;
	}

	if (pFileNode2 && !pFileNode2->HasLockIdInArray(pLockIDs,numLocks)) {
		DEBUGMSG(ZONE_ERROR,(L"HTTPD: File %s has lock, but none of client lockIDS match\r\n",szFile2));
		goto done;
	}

	fRet = TRUE;
done:
	if (ppFileNode1)
		*ppFileNode1 = pFileNode1;

	if (ppFileNode2)
		*ppFileNode2 = pFileNode2;

	DEBUGMSG(ZONE_WEBDAV_VERBOSE,(L"HTTPD: Found mapping between file names (%s,%s) and Lock tokens client sent\r\n",szFile1,szFile2));
	return fRet;
}

void CWebDavFileLockManager::RemoveFileNodeFromLinkedList(CWebDavFileNode *pNode) {
	DEBUGCHK(IsLocked());

	CWebDavFileNode *pTrav    = m_pFileLockList;
	CWebDavFileNode *pFollow  = NULL;

	while (pTrav != pNode) {
		pFollow = pTrav;
		pTrav   = pTrav->m_pNext;
	}
	DEBUGCHK(pTrav); // we know it's in list

	if (pFollow)
		pFollow->m_pNext = pTrav->m_pNext;
	else {
		DEBUGCHK(pTrav == m_pFileLockList);
		m_pFileLockList = pTrav->m_pNext;
	}
}

BOOL CWebDavFileLockManager::DeleteLock(__int64 iLockId) {
	CWebDavFileNode *pFileNode;
	CWebDavLock     *pLock;
	BOOL            fRet = FALSE;

	Lock();

	if (NULL == (pFileNode = GetNodeFromID(iLockId,&pLock)))
		goto done;

	DEBUGCHK(pLock);
	if (pFileNode->DeleteLock(pLock)) {
		if (! pFileNode->HasLocks()) {
			RemoveFileNodeFromLinkedList(pFileNode);
			DeInitAndFreeFileNode(pFileNode);
		}
		fRet = TRUE;
	}

done:
	Unlock();
	return fRet;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -