mirror of https://github.com/tongzx/nt5src
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.
420 lines
11 KiB
420 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rtutil.cpp
|
|
|
|
Abstract:
|
|
|
|
Contains various utility functions.
|
|
|
|
Author:
|
|
|
|
Boaz Feldbaum (BoazF) Mar 5, 1996
|
|
|
|
Revision History:
|
|
|
|
Erez Haba (erezh) 17-Jan-1997
|
|
|
|
--*/
|
|
|
|
#include "stdh.h"
|
|
#include "acrt.h"
|
|
#include <mqdbmgr.h>
|
|
#include <ad.h>
|
|
#include <_secutil.h>
|
|
#include <mqsec.h>
|
|
|
|
#include "rtutil.tmh"
|
|
|
|
//---------------------------------------------------------
|
|
//
|
|
// Function:
|
|
// RTpGetQueuePropVar
|
|
//
|
|
// Description:
|
|
// Find a queue property in the properties array
|
|
//
|
|
//---------------------------------------------------------
|
|
PROPVARIANT*
|
|
RTpGetQueuePropVar(
|
|
PROPID PropID,
|
|
MQQUEUEPROPS *pqp
|
|
)
|
|
{
|
|
DWORD i;
|
|
DWORD cProp;
|
|
PROPID *aPropID;
|
|
|
|
for (i = 0, cProp = pqp->cProp, aPropID = pqp->aPropID;
|
|
i < cProp;
|
|
i++, aPropID++) {
|
|
|
|
if (*aPropID == PropID) {
|
|
return(&(pqp->aPropVar[i]));
|
|
}
|
|
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------
|
|
//
|
|
// Function:
|
|
// RTpGetQueuePathNamePropVar
|
|
//
|
|
// Description:
|
|
// Find a the queue path name property in the properties array
|
|
//
|
|
//---------------------------------------------------------
|
|
LPWSTR
|
|
RTpGetQueuePathNamePropVar(
|
|
MQQUEUEPROPS *pqp
|
|
)
|
|
{
|
|
PROPVARIANT *p;
|
|
|
|
if ((p = RTpGetQueuePropVar(PROPID_Q_PATHNAME, pqp)) != NULL)
|
|
return(p->pwszVal);
|
|
else
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------
|
|
//
|
|
// Function:
|
|
// RTpGetQueueGuidPropVar
|
|
//
|
|
// Description:
|
|
// Find the queue guid (instance) property in the properties array
|
|
//
|
|
//---------------------------------------------------------
|
|
GUID*
|
|
RTpGetQueueGuidPropVar(
|
|
MQQUEUEPROPS *pqp
|
|
)
|
|
{
|
|
PROPVARIANT *p;
|
|
|
|
if ((p = RTpGetQueuePropVar(PROPID_Q_INSTANCE, pqp)) != NULL)
|
|
return(p->puuid);
|
|
else
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------
|
|
//
|
|
// Function:
|
|
// RTpMakeSelfRelativeSDAndGetSize
|
|
//
|
|
// Parameters:
|
|
// pSecurityDescriptor - The input security descriptor.
|
|
// pSelfRelativeSecurityDescriptor - A pointer to a temporary buffer
|
|
// that holds the converted security descriptor.
|
|
// pSDSize - A pointer to a variable that receives the length of the
|
|
// self relative security descriptor. This is an optional parameter.
|
|
//
|
|
// Description:
|
|
// Convert an absolute security descriptor to a self relative security
|
|
// descriptor and get the size of the self relative security descriptor.
|
|
// This function should be call before passing a security descriptor to
|
|
// a function that passes the security descriptor to an RPC function.
|
|
//
|
|
// If the input security descriptor is already a self relative security
|
|
// descriptor, the function only computes the length of the security
|
|
// descriptor and returns. If the input security descriptor is an absolute
|
|
// security descriptor, the function allocates a buffer large enough to
|
|
// accomodate the self relative security descripr, converts the absolute
|
|
// security descriptor to a self relative security descriptor and modifies
|
|
// the pointer of the input security descriptor to point to the self relative
|
|
// security descriptor.
|
|
//
|
|
// The temporar buffer that is being allocated for the self relative
|
|
// security descriptor should be freed by the calling code.
|
|
//
|
|
//---------------------------------------------------------
|
|
HRESULT
|
|
RTpMakeSelfRelativeSDAndGetSize(
|
|
PSECURITY_DESCRIPTOR *pSecurityDescriptor,
|
|
PSECURITY_DESCRIPTOR *pSelfRelativeSecurityDescriptor,
|
|
DWORD *pSDSize)
|
|
{
|
|
SECURITY_DESCRIPTOR_CONTROL sdcSDControl;
|
|
DWORD dwSDRevision;
|
|
|
|
ASSERT(pSecurityDescriptor);
|
|
ASSERT(pSelfRelativeSecurityDescriptor);
|
|
|
|
*pSelfRelativeSecurityDescriptor = NULL;
|
|
|
|
if (!*pSecurityDescriptor)
|
|
{
|
|
// Set the security descriptor size.
|
|
if (pSDSize)
|
|
{
|
|
*pSDSize = 0;
|
|
}
|
|
return(MQ_OK);
|
|
}
|
|
|
|
// Verify that this is a valid security descriptor.
|
|
if (!IsValidSecurityDescriptor(*pSecurityDescriptor))
|
|
{
|
|
return(MQ_ERROR_ILLEGAL_SECURITY_DESCRIPTOR);
|
|
}
|
|
|
|
// Check whether this is a self relative or absolute security
|
|
// descriptor.
|
|
if (!GetSecurityDescriptorControl(*pSecurityDescriptor,
|
|
&sdcSDControl,
|
|
&dwSDRevision))
|
|
{
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
if (!(sdcSDControl & SE_SELF_RELATIVE))
|
|
{
|
|
// This is an absolute security descriptor, we should convert it
|
|
// to a self relative one.
|
|
DWORD dwBufferLength = 0;
|
|
|
|
#ifdef _DEBUG
|
|
SetLastError(0);
|
|
#endif
|
|
// Get the buffer size.
|
|
MakeSelfRelativeSD(*pSecurityDescriptor, NULL, &dwBufferLength);
|
|
ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
// Allocate the buffer for the self relative security descriptor.
|
|
*pSelfRelativeSecurityDescriptor =
|
|
(PSECURITY_DESCRIPTOR) new char[dwBufferLength];
|
|
|
|
// Convert the security descriptor.
|
|
if (!MakeSelfRelativeSD(
|
|
*pSecurityDescriptor,
|
|
*pSelfRelativeSecurityDescriptor,
|
|
&dwBufferLength))
|
|
{
|
|
ASSERT(FALSE);
|
|
}
|
|
ASSERT(IsValidSecurityDescriptor(*pSelfRelativeSecurityDescriptor));
|
|
*pSecurityDescriptor = *pSelfRelativeSecurityDescriptor;
|
|
|
|
// Set the security descriptor size.
|
|
if (pSDSize)
|
|
{
|
|
*pSDSize = dwBufferLength;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// The security descriptor is already in self relative format, just
|
|
// set the security descriptor size.
|
|
if (pSDSize)
|
|
{
|
|
*pSDSize = GetSecurityDescriptorLength(*pSecurityDescriptor);
|
|
}
|
|
|
|
}
|
|
|
|
return(MQ_OK);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------
|
|
//
|
|
// Function:
|
|
// RTpConvertToMQCode
|
|
//
|
|
// Parameters:
|
|
// hr - Error vode that is generated by any kind of module.
|
|
//
|
|
// Return value:
|
|
// The imput parameter convetrted to some equivalent MQ_ERROR constant.
|
|
//
|
|
//---------------------------------------------------------
|
|
HRESULT
|
|
RTpConvertToMQCode(
|
|
HRESULT hr,
|
|
DWORD dwObjectType
|
|
)
|
|
{
|
|
|
|
if ((hr == MQ_OK) ||
|
|
(hr == MQ_INFORMATION_REMOTE_OPERATION) ||
|
|
(hr == MQ_ERROR_Q_DNS_PROPERTY_NOT_SUPPORTED) ||
|
|
((MQ_E_BASE <= hr) && (hr < MQ_E_BASE + 0x100)) ||
|
|
((MQ_I_BASE <= hr) && (hr < MQ_I_BASE + 0x100)))
|
|
{
|
|
// This is our codes, do not modify it.
|
|
return(hr);
|
|
}
|
|
|
|
if (hr == MQDS_OK_REMOTE)
|
|
{
|
|
//
|
|
// success - we use MQDS_OK_REMOTE for internal use, e.g. explorer
|
|
//
|
|
return(MQ_OK);
|
|
}
|
|
|
|
if (HRESULT_FACILITY(MQ_E_BASE) == HRESULT_FACILITY(hr))
|
|
{
|
|
switch (hr)
|
|
{
|
|
case MQDB_E_NO_MORE_DATA:
|
|
case MQDS_GET_PROPERTIES_ERROR:
|
|
case MQDS_OBJECT_NOT_FOUND:
|
|
hr = (dwObjectType == MQDS_QUEUE) ?
|
|
MQ_ERROR_QUEUE_NOT_FOUND :
|
|
MQ_ERROR_MACHINE_NOT_FOUND;
|
|
break;
|
|
|
|
case MQDS_NO_RSP_FROM_OWNER:
|
|
hr = MQ_ERROR_NO_RESPONSE_FROM_OBJECT_SERVER;
|
|
break;
|
|
|
|
case MQDS_OWNER_NOT_REACHED:
|
|
hr = MQ_ERROR_OBJECT_SERVER_NOT_AVAILABLE;
|
|
break;
|
|
|
|
case MQDB_E_NON_UNIQUE_SORT:
|
|
hr = MQ_ERROR_ILLEGAL_SORT;
|
|
break;
|
|
|
|
default:
|
|
// Some DS error occured. This should not happen, but anyway...
|
|
DBGMSG((DBGMOD_API, DBGLVL_WARNING,
|
|
TEXT("A DS error (%x) has propagated to the RT DLL. Converting to MQ_ERROR_DS_ERROR"), hr));
|
|
hr = MQ_ERROR_DS_ERROR;
|
|
break;
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
if (hr == CPP_EXCEPTION_CODE)
|
|
{
|
|
// A C++ exception occured. This can happen only when in an allocation failure.
|
|
return(MQ_ERROR_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
// Now we hope that we know how to convert an NTSTATUS to some of our error
|
|
// codes. Good luck...
|
|
switch(hr)
|
|
{
|
|
case STATUS_INVALID_HANDLE:
|
|
case STATUS_OBJECT_TYPE_MISMATCH:
|
|
hr = MQ_ERROR_INVALID_HANDLE;
|
|
break;
|
|
|
|
case STATUS_ACCESS_DENIED:
|
|
hr = MQ_ERROR_ACCESS_DENIED;
|
|
break;
|
|
|
|
case STATUS_ACCESS_VIOLATION:
|
|
case STATUS_INVALID_PARAMETER:
|
|
hr = MQ_ERROR_INVALID_PARAMETER;
|
|
break;
|
|
|
|
case STATUS_SHARING_VIOLATION:
|
|
hr = MQ_ERROR_SHARING_VIOLATION;
|
|
break;
|
|
|
|
case STATUS_PENDING:
|
|
hr = MQ_INFORMATION_OPERATION_PENDING;
|
|
break;
|
|
|
|
case STATUS_CANCELLED:
|
|
hr = MQ_ERROR_OPERATION_CANCELLED;
|
|
break;
|
|
|
|
case STATUS_INSUFFICIENT_RESOURCES:
|
|
hr = MQ_ERROR_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
|
|
case STATUS_INVALID_DEVICE_REQUEST:
|
|
hr = MQ_ERROR_SERVICE_NOT_AVAILABLE;
|
|
break;
|
|
|
|
default:
|
|
DBGMSG((DBGMOD_API, DBGLVL_WARNING,
|
|
TEXT("Unfamiliar error code:%x, not converted to a MQ error"), hr));
|
|
break;
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------
|
|
//
|
|
// Function:
|
|
// RTpGetThreadUserSid
|
|
//
|
|
// Parameters:
|
|
// pUserSid - A pointer to a buffer that receives the address of a buffer
|
|
// that contains the SID of the user of the current thread.
|
|
// pdwUserSidLen - A pointer to a DWORD that receives the length of the
|
|
// SID.
|
|
//
|
|
// Description:
|
|
// The function allocates the buffer for the SID and fils it with the SID
|
|
// of the user of the current thread. The calling code is responsible for
|
|
// freeing the allocated buffer.
|
|
//
|
|
//---------------------------------------------------------
|
|
|
|
HRESULT
|
|
RTpGetThreadUserSid( BOOL *pfLocalUser,
|
|
BOOL *pfLocalSystem,
|
|
LPBYTE *pUserSid,
|
|
DWORD *pdwUserSidLen )
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = MQSec_GetUserType( NULL,
|
|
pfLocalUser,
|
|
pfLocalSystem );
|
|
if (FAILED(hr))
|
|
{
|
|
return(hr);
|
|
}
|
|
|
|
if (*pfLocalSystem)
|
|
{
|
|
*pUserSid = (LPBYTE) MQSec_GetLocalMachineSid( TRUE, // allocate
|
|
pdwUserSidLen ) ;
|
|
if (!(*pUserSid))
|
|
{
|
|
//
|
|
// this may happen if the machine belong to a NT4 domain
|
|
// and it doesn't have any computer account and sid.
|
|
// In that case, make it a local user.
|
|
//
|
|
ASSERT(*pdwUserSidLen == 0) ;
|
|
*pdwUserSidLen = 0 ;
|
|
|
|
*pfLocalSystem = FALSE ;
|
|
if (pfLocalUser)
|
|
{
|
|
ASSERT(!(*pfLocalUser)) ;
|
|
*pfLocalUser = TRUE ;
|
|
}
|
|
}
|
|
}
|
|
else if (!(*pfLocalUser))
|
|
{
|
|
hr = GetThreadUserSid(pUserSid, pdwUserSidLen);
|
|
}
|
|
|
|
return(hr);
|
|
}
|