2025-04-27 07:49:33 -04:00

308 lines
9.0 KiB
C++

/*==========================================================================*\
Module: smqutil.cpp
Copyright Microsoft Corporation 1996, All Rights Reserved.
Author: mikepurt
Descriptions: Misc routines that don't belong in classes.
\*==========================================================================*/
#include "_shmem.h"
#include <implstub.h>
const CHAR DAV_IPC_INSTANCE_NAME[] = "DavExIpc";
const WCHAR gc_wszTSGlobal[] = L"Global\\";
const INT gc_cchszTSGlobal = sizeof(gc_wszTSGlobal)/sizeof(WCHAR) - 1;
/*$--BindToMutex============================================================*\
pwszInstanceName & pwszBindingExtension:concatenated to form the name
that the mutex will be created with.
fInitiallyOwn: Passed on to CreateMutex() call
lpMutexAttributes: Passed on to CreateMutex() call
returns: On Success, the mutex handle.
On Failure, NULL. GetLastError() to
get more information.
\*==========================================================================*/
HANDLE
BindToMutex(IN LPCWSTR pwszInstanceName,
IN LPCWSTR pwszBindingExtension,
IN BOOL fInitiallyOwn,
IN LPSECURITY_ATTRIBUTES lpMutexAttributes)
{
Assert(pwszInstanceName);
Assert(pwszBindingExtension);
HANDLE hmtx = NULL;
WCHAR wszBindingName[MAX_PATH+1];
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
UINT cchInstanceName = static_cast<UINT>(wcslen(pwszInstanceName));
UINT cchBindingExtension = static_cast<UINT>(wcslen(pwszBindingExtension));
if (lpMutexAttributes == NULL)
{
// Initialize the security descriptor with completely open access
//
//$HACK - Special case for HTTPEXT
//
// To meet C2 security requirements, we cannot have any completely
// open objects. Fortunately, HTTPEXT only uses this code for its
// perf counters which are both generated and gathered in the same
// process (W3SVC) and same security context (local system). Access
// can thus be left to the default (local system or admin only).
//
if (pwszInstanceName != wcsstr(pwszInstanceName, L"HTTPEXT"))
{
InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl (&sd, TRUE, NULL, FALSE);
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = TRUE;
lpMutexAttributes = &sa;
}
}
//
// Check to make sure we're not going to overrun our character buffer.
//
if (cchInstanceName +
cchBindingExtension +
gc_cchszTSGlobal >= MAX_PATH)
{
hmtx = NULL;
SetLastError(ERROR_INVALID_PARAMETER);
goto Exit;
}
//
// Create the mutex.
//
// Raid 137862
// The mutex must be named so that it will reside
// in the Global Kernel Object Name Space in order to be visible from
// a Terminal Services client.
//
{
LPWSTR pwsz = wszBindingName;
memcpy(pwsz,
gc_wszTSGlobal,
sizeof(WCHAR) * gc_cchszTSGlobal);
pwsz += gc_cchszTSGlobal;
memcpy(pwsz,
pwszInstanceName,
sizeof(WCHAR) * cchInstanceName);
pwsz += cchInstanceName;
memcpy(pwsz,
pwszBindingExtension,
sizeof(WCHAR) * cchBindingExtension);
pwsz += cchBindingExtension;
*pwsz = L'\0';
}
hmtx = CreateMutexW(lpMutexAttributes,
fInitiallyOwn,
wszBindingName);
Exit:
return hmtx;
}
/*$--BindToSharedMemory=====================================================*\
pwszInstanceName & pwszBindingExtension:concatenated to form the name that the
file mapping will be created with.
cbSize: The size of the mapping/view.
ppvFileView: The virtual address of the shared mem.
pfCreatedMapping: Did we create this mapping?
lpFileMappingAttributes: Passed into CreateFileMappin() call
\*==========================================================================*/
HANDLE
BindToSharedMemory(IN LPCWSTR pwszInstanceName,
IN LPCWSTR pwszBindingExtension,
IN DWORD cbSize,
OUT PVOID * ppvFileView,
OUT BOOL * pfCreatedMapping,
IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes)
{
Assert(pwszInstanceName);
Assert(pwszBindingExtension);
Assert(ppvFileView);
HANDLE hReturn = NULL;
DWORD dwLastError = 0;
WCHAR wszBindingName[MAX_PATH+1];
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
UINT cchInstanceName = static_cast<UINT>(wcslen(pwszInstanceName));
UINT cchBindingExtension = static_cast<UINT>(wcslen(pwszBindingExtension));
if (lpFileMappingAttributes == NULL)
{
// Initialize the security descriptor with completely open access
//
//$HACK - Special case for HTTPEXT
//
// To meet C2 security requirements, we cannot have any completely
// open objects. Fortunately, HTTPEXT only uses this code for its
// perf counters which are both generated and gathered in the same
// process (W3SVC) and same security context (local system). Access
// can thus be left to the default (local system or admin only).
//
if (pwszInstanceName != wcsstr(pwszInstanceName, L"HTTPEXT"))
{
InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl (&sd, TRUE, NULL, FALSE);
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = TRUE;
lpFileMappingAttributes = &sa;
}
}
*ppvFileView = NULL;
//
// Check to make sure we're not going to overrun our character buffer.
//
if (cchInstanceName +
cchBindingExtension +
gc_cchszTSGlobal >= MAX_PATH)
{
hReturn = NULL;
SetLastError(ERROR_INVALID_PARAMETER);
goto Exit;
}
//
// Create the file mapping.
//
// Raid 137862
// The mutex must be named so that it will reside
// in the Global Kernel Object Name Space in order to be visible from
// a Terminal Services client.
//
{
LPWSTR pwsz = wszBindingName;
memcpy(pwsz,
gc_wszTSGlobal,
sizeof(WCHAR) * gc_cchszTSGlobal);
pwsz += gc_cchszTSGlobal;
memcpy(pwsz,
pwszInstanceName,
sizeof(WCHAR) * cchInstanceName);
pwsz += cchInstanceName;
memcpy(pwsz,
pwszBindingExtension,
sizeof(WCHAR) * cchBindingExtension);
pwsz += cchBindingExtension;
*pwsz = L'\0';
}
hReturn = CreateFileMappingW(INVALID_HANDLE_VALUE, // Use swap file
lpFileMappingAttributes,
PAGE_READWRITE | SEC_COMMIT,
0, // dwMaximumSizeHigh
cbSize, // dwMaximumSizeLow
wszBindingName);
if (NULL == hReturn)
goto Exit;
//
// Determine if we created the mapping (as opposed to it already existing)
//
if (pfCreatedMapping)
*pfCreatedMapping = GetLastError() != ERROR_ALREADY_EXISTS;
if (*pfCreatedMapping)
{
// Must save the shared memory handle so the memory will not go away when
// the DAV process are all shutdown.
//
IMPLSTUB::SaveHandle(hReturn);
}
//
// Map the file mapping into our virtual address space
//
*ppvFileView = MapViewOfFile(hReturn,
FILE_MAP_ALL_ACCESS,
0, // dwFileOffsetHigh
0, // dwFileOffsetLow
cbSize);
Exit:
if (*ppvFileView == NULL)
{
dwLastError = GetLastError(); // preserve LastError
if (hReturn)
CloseHandle(hReturn);
hReturn = NULL;
SetLastError(dwLastError); // restore LastError
}
return hReturn;
}
/*$--FAcquireMutex==========================================================*\
This returns only after either acquiring the mutex or an error occuring.
If it returns FALSE, an error occurred and GetLastError() can be used to
get more information.
\*==========================================================================*/
BOOL
FAcquireMutex(IN HANDLE hmtx)
{
DWORD dwWait = 0;
dwWait = WaitForSingleObject(hmtx, INFINITE);
if ((WAIT_ABANDONED_0 == dwWait) || (WAIT_OBJECT_0 == dwWait))
return TRUE;
else
return FALSE;
}
/*$--FReleaseMutex==========================================================*\
Provides symmetry with above FAcquireMutex().
\*==========================================================================*/
BOOL
FReleaseMutex(IN HANDLE hmtx)
{
return ReleaseMutex(hmtx);
}