Source code of Windows XP (NT5)
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

/*++
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);
}