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.
952 lines
26 KiB
952 lines
26 KiB
/******************************************************************
|
|
|
|
Copyright (c) 2000-2002 Microsoft Corporation, All Rights Reserved
|
|
|
|
JOProcess.CPP -- WMI provider class implementation
|
|
|
|
******************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#if NTONLY >= 5
|
|
|
|
#include "JOProcess.h"
|
|
#include <autoptr.h>
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CJOProcess MyCJOProcess(
|
|
PROVIDER_NAME_WIN32NAMEDJOBOBJECTPROCESS,
|
|
IDS_CimWin32Namespace);
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CJOProcess::CJOProcess(
|
|
LPCWSTR setName,
|
|
LPCWSTR pszNameSpace /*=NULL*/)
|
|
: Provider(setName, pszNameSpace)
|
|
{
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CJOProcess::~CJOProcess()
|
|
{
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CJOProcess::GetObject(
|
|
CInstance* pInstance,
|
|
long lFlags /*= 0L*/ )
|
|
{
|
|
return FindSingleInstance(pInstance);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CJOProcess::EnumerateInstances(
|
|
MethodContext* pMethodContext,
|
|
long lFlags)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
hr = Enumerate(pMethodContext);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
// We will only optimize for the
|
|
// case where a specific job was
|
|
// specified.
|
|
|
|
HRESULT CJOProcess::ExecQuery (
|
|
|
|
MethodContext *pMethodContext,
|
|
CFrameworkQuery& Query,
|
|
long lFlags
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
std::vector<_bstr_t> rgJOs;
|
|
DWORD dwJOsCount = 0L;
|
|
Query.GetValuesForProp(L"Collection", rgJOs);
|
|
dwJOsCount = rgJOs.size();
|
|
|
|
if(dwJOsCount > 0)
|
|
{
|
|
CInstancePtr pInstJO;
|
|
CHString chstrPath;
|
|
|
|
for(DWORD x = 0; x < dwJOsCount; x++)
|
|
{
|
|
// First we see if the specified JO exists.
|
|
chstrPath.Format(
|
|
L"\\\\.\\%s:%s",
|
|
IDS_CimWin32Namespace,
|
|
(LPCWSTR)rgJOs[x]);
|
|
|
|
hr = CWbemProviderGlue::GetInstanceKeysByPath(
|
|
chstrPath,
|
|
&pInstJO,
|
|
pMethodContext);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Ok, the JO exists. Enumerate its processes...
|
|
// rgJOs[x] contains something like
|
|
// Win32_NamedJobObject.CollectionID="myjob",
|
|
// from which I want just the myjob part.
|
|
CHString chstrInstKey;
|
|
if(GetInstKey(
|
|
CHString((LPCWSTR)rgJOs[x]),
|
|
chstrInstKey))
|
|
{
|
|
hr = EnumerateProcsInJob(
|
|
chstrInstKey,
|
|
pMethodContext);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
hr = Enumerate(pMethodContext);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CJOProcess::PutInstance (
|
|
|
|
const CInstance &Instance,
|
|
long lFlags
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_E_INVALID_PARAMETER;
|
|
MethodContext *pMethodContext = Instance.GetMethodContext();
|
|
long lCreateFlags = lFlags & 3;
|
|
|
|
// Decide how to proceed based on the value of lFlags:
|
|
// (we want to support PutInstance in all cases except
|
|
// where the client asked to update the instance).
|
|
if(lCreateFlags != WBEM_FLAG_UPDATE_ONLY)
|
|
{
|
|
// The caller only wants to create an instance that doesn't exist.
|
|
if((hr = FindSingleInstance(
|
|
&Instance)) == WBEM_E_NOT_FOUND)
|
|
{
|
|
// The association instance does not already exist, so create it...
|
|
// First see that the job object instance exists...
|
|
CHString chstrJOPath;
|
|
if ( ! Instance.GetCHString(L"Collection", chstrJOPath) )
|
|
{
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
CInstancePtr pJOInst;
|
|
|
|
hr = CWbemProviderGlue::GetInstanceKeysByPath(
|
|
chstrJOPath,
|
|
&pJOInst,
|
|
pMethodContext);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Confirm that the process exists...
|
|
CHString chstrProcPath;
|
|
if ( ! Instance.GetCHString(L"Member", chstrProcPath) )
|
|
{
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
CInstancePtr pProcInst;
|
|
|
|
hr = CWbemProviderGlue::GetInstanceKeysByPath(
|
|
chstrProcPath,
|
|
&pProcInst,
|
|
pMethodContext);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = Create(pJOInst, pProcInst);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CJOProcess::FindSingleInstance
|
|
*
|
|
* DESCRIPTION : Internal helper function used to locate a single job
|
|
* object.
|
|
*
|
|
* INPUTS : A pointer to a CInstance containing the instance we are
|
|
* attempting to locate and fill values for.
|
|
*
|
|
* RETURNS : A valid HRESULT
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CJOProcess::FindSingleInstance (
|
|
|
|
const CInstance* pInstance
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if(!pInstance)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
MethodContext* pMethodContext = pInstance->GetMethodContext();
|
|
CHString chstrCollection;
|
|
CHString chstrMember;
|
|
|
|
// Find out which JO and which process are specified...
|
|
if ( ! pInstance->GetCHString(L"Collection", chstrCollection) )
|
|
{
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
if ( ! pInstance->GetCHString(L"Member", chstrMember) )
|
|
{
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
CHString chstrCollectionID;
|
|
CHString chstrProcessHandle;
|
|
CInstancePtr cinstJO;
|
|
CInstancePtr cinstProcess;
|
|
|
|
if(GetInstKey(chstrCollection, chstrCollectionID) &&
|
|
GetInstKey(chstrMember, chstrProcessHandle))
|
|
{
|
|
// See if the specified job exists...
|
|
hr = CWbemProviderGlue::GetInstanceKeysByPath(
|
|
chstrCollection,
|
|
&cinstJO,
|
|
pMethodContext);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// See if the specified process exists...
|
|
hr = CWbemProviderGlue::GetInstanceKeysByPath(
|
|
chstrMember,
|
|
&cinstProcess,
|
|
pMethodContext);
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// The endpoints exist. Is the specified
|
|
// process part of the specified job though?
|
|
CHString chstrProcessID;
|
|
DWORD dwProcessID;
|
|
|
|
if(cinstProcess->GetCHString(L"Handle", chstrProcessID))
|
|
{
|
|
dwProcessID = _wtoi(chstrProcessID);
|
|
|
|
SmartCloseHandle hJob;
|
|
|
|
CHString chstrUndecoratedJOName;
|
|
|
|
UndecorateJOName(
|
|
chstrCollectionID,
|
|
chstrUndecoratedJOName);
|
|
|
|
hJob = ::OpenJobObject(
|
|
MAXIMUM_ALLOWED,
|
|
FALSE,
|
|
chstrUndecoratedJOName);
|
|
|
|
if(hJob != NULL)
|
|
{
|
|
long lSize = 0L;
|
|
bool fGotProcList = false;
|
|
DWORD dwLen = 0L;
|
|
|
|
lSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + (5 * sizeof(ULONG_PTR));
|
|
wmilib::auto_buffer < BYTE > pbBuff ( new BYTE [ lSize ], lSize ) ;
|
|
|
|
if ( pbBuff.get () )
|
|
{
|
|
fGotProcList = ::QueryInformationJobObject(
|
|
hJob,
|
|
JobObjectBasicProcessIdList,
|
|
pbBuff.get (),
|
|
lSize,
|
|
&dwLen);
|
|
|
|
if(!fGotProcList)
|
|
{
|
|
// need to grow the buffer...
|
|
lSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) +
|
|
(((JOBOBJECT_BASIC_PROCESS_ID_LIST*)pbBuff.get ())->NumberOfAssignedProcesses - 1)*sizeof(ULONG_PTR);
|
|
|
|
pbBuff.reset ( new BYTE [ lSize ] ) ;
|
|
if ( pbBuff.get () )
|
|
{
|
|
fGotProcList = ::QueryInformationJobObject(
|
|
hJob,
|
|
JobObjectBasicProcessIdList,
|
|
pbBuff.get (),
|
|
lSize,
|
|
&dwLen);
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
if(fGotProcList)
|
|
{
|
|
PJOBOBJECT_BASIC_PROCESS_ID_LIST pjobpl = static_cast<PJOBOBJECT_BASIC_PROCESS_ID_LIST>(static_cast<PVOID>(pbBuff.get ()));
|
|
|
|
bool fExists = false;
|
|
|
|
for(long m = 0;
|
|
m < pjobpl->NumberOfProcessIdsInList && !fExists;
|
|
m++)
|
|
{
|
|
if(dwProcessID == pjobpl->ProcessIdList[m])
|
|
{
|
|
fExists = true;
|
|
}
|
|
}
|
|
|
|
// If the process wasn't in the job,
|
|
// we didn't find an instance of the
|
|
// requested association, even though
|
|
// the endpoints may have existed.
|
|
if(!fExists)
|
|
{
|
|
hr = WBEM_E_NOT_FOUND;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WinErrorToWBEMhResult(::GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WinErrorToWBEMhResult(::GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CJOProcess::Create
|
|
*
|
|
* DESCRIPTION : Internal helper function used to add a process to a job.
|
|
*
|
|
* INPUTS : A pointer to the JO instance to add the proc to, and
|
|
* a pointer to the proc instance to add
|
|
*
|
|
* RETURNS : A valid HRESULT.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CJOProcess::Create (
|
|
|
|
const CInstance &JOInstance,
|
|
const CInstance &ProcInstance
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
CHString chstrJOID;
|
|
CHString chstrProcHandle;
|
|
|
|
// JO to add the proc to...
|
|
if ( ! JOInstance.GetCHString(L"CollectionID", chstrJOID) )
|
|
{
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
// Proc to add to the job...
|
|
if ( ! ProcInstance.GetCHString(L"Handle", chstrProcHandle) )
|
|
{
|
|
return WBEM_E_FAILED ;
|
|
}
|
|
|
|
DWORD dwProcID = _wtol(chstrProcHandle);
|
|
|
|
// Do the add
|
|
SmartCloseHandle hJob;
|
|
|
|
CHString chstrUndecoratedJOName;
|
|
|
|
UndecorateJOName(
|
|
chstrJOID,
|
|
chstrUndecoratedJOName);
|
|
|
|
hJob = ::OpenJobObject(
|
|
MAXIMUM_ALLOWED,
|
|
FALSE,
|
|
chstrUndecoratedJOName);
|
|
|
|
if(hJob != NULL)
|
|
{
|
|
SmartCloseHandle hProc;
|
|
hProc = ::OpenProcess(
|
|
PROCESS_ALL_ACCESS,
|
|
FALSE,
|
|
dwProcID);
|
|
|
|
if(hProc != NULL)
|
|
{
|
|
if(!::AssignProcessToJobObject(
|
|
hJob,
|
|
hProc))
|
|
{
|
|
hr = MAKE_SCODE(
|
|
SEVERITY_ERROR,
|
|
FACILITY_WIN32,
|
|
GetLastError());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WinErrorToWBEMhResult(::GetLastError());
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CJOProcess::Enumerate
|
|
*
|
|
* DESCRIPTION : Internal helper function used to enumerate instances of
|
|
* this class. All instances are enumerated, but only the
|
|
* properties specified are obtained.
|
|
*
|
|
* INPUTS : A pointer to a the MethodContext for the call.
|
|
* A DWORD specifying which properties are requested.
|
|
*
|
|
* RETURNS : A valid HRESULT
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CJOProcess::Enumerate (
|
|
|
|
MethodContext *pMethodContext
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
TRefPointerCollection<CInstance> JOList;
|
|
|
|
hr = CWbemProviderGlue::GetInstancesByQuery(
|
|
L"SELECT CollectionID FROM Win32_NamedJobObject",
|
|
&JOList,
|
|
pMethodContext,
|
|
IDS_CimWin32Namespace);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
REFPTRCOLLECTION_POSITION pos;
|
|
|
|
// Initialize the enum
|
|
if(JOList.BeginEnum(pos))
|
|
{
|
|
// Set some vars
|
|
CHString chstrJOID;
|
|
CInstancePtr pJOInst;
|
|
|
|
for (pJOInst.Attach(JOList.GetNext(pos)) ;
|
|
(pJOInst != NULL) ;
|
|
pJOInst.Attach(JOList.GetNext(pos)) )
|
|
{
|
|
bool t_Status = pJOInst->GetCHString (
|
|
|
|
L"CollectionID",
|
|
chstrJOID
|
|
) ;
|
|
|
|
if ( t_Status )
|
|
{
|
|
hr = EnumerateProcsInJob (
|
|
|
|
chstrJOID,
|
|
pMethodContext
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_FAILED ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HRESULT CJOProcess::EnumerateProcsInJob (
|
|
|
|
LPCWSTR wstrJobID,
|
|
MethodContext *pMethodContext
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
SmartCloseHandle hJob;
|
|
|
|
CHString chstrUndecoratedJOName;
|
|
|
|
UndecorateJOName(
|
|
wstrJobID,
|
|
chstrUndecoratedJOName);
|
|
|
|
hJob = ::OpenJobObject(
|
|
MAXIMUM_ALLOWED,
|
|
FALSE,
|
|
chstrUndecoratedJOName);
|
|
|
|
if(hJob != NULL)
|
|
{
|
|
long lSize = 0L;
|
|
bool fGotProcList = false;
|
|
DWORD dwLen = 0L;
|
|
|
|
lSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + (5 * sizeof(ULONG_PTR));
|
|
wmilib::auto_buffer < BYTE > pbBuff ( new BYTE [ lSize ], lSize ) ;
|
|
|
|
if ( pbBuff.get () )
|
|
{
|
|
fGotProcList = ::QueryInformationJobObject(
|
|
hJob,
|
|
JobObjectBasicProcessIdList,
|
|
pbBuff.get (),
|
|
lSize,
|
|
&dwLen);
|
|
|
|
if(!fGotProcList)
|
|
{
|
|
// need to grow the buffer...
|
|
lSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) +
|
|
(((JOBOBJECT_BASIC_PROCESS_ID_LIST*)pbBuff.get ())->NumberOfAssignedProcesses - 1)*sizeof(ULONG_PTR);
|
|
|
|
pbBuff.reset ( new BYTE [ lSize ] ) ;
|
|
if ( pbBuff.get () )
|
|
{
|
|
fGotProcList = ::QueryInformationJobObject(
|
|
hJob,
|
|
JobObjectBasicProcessIdList,
|
|
pbBuff.get (),
|
|
lSize,
|
|
&dwLen);
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
if(fGotProcList)
|
|
{
|
|
PJOBOBJECT_BASIC_PROCESS_ID_LIST pjobpl = static_cast<PJOBOBJECT_BASIC_PROCESS_ID_LIST>(static_cast<PVOID>(pbBuff.get ()));
|
|
|
|
for(long m = 0;
|
|
m < pjobpl->NumberOfProcessIdsInList;
|
|
m++)
|
|
{
|
|
// Create association inst for each
|
|
// proc in the job...
|
|
CInstancePtr pInstance(CreateNewInstance(pMethodContext),
|
|
false);
|
|
|
|
// Set the endpoints...
|
|
CHString chstrEscaped;
|
|
|
|
DecorateJOName(chstrUndecoratedJOName, chstrEscaped);
|
|
EscapeBackslashes(chstrEscaped, chstrEscaped);
|
|
EscapeQuotes(chstrEscaped, chstrEscaped);
|
|
|
|
CHString chstrTmp;
|
|
chstrTmp.Format(L"\\\\.\\%s:Win32_NamedJobObject.CollectionID=\"%s\"",
|
|
IDS_CimWin32Namespace,
|
|
(LPCWSTR)chstrEscaped);
|
|
|
|
pInstance->SetCHString(L"Collection", chstrTmp);
|
|
|
|
|
|
CHString chstrHandle;
|
|
chstrHandle.Format(L"%d", pjobpl->ProcessIdList[m]);
|
|
chstrTmp.Format(L"\\\\.\\%s:Win32_Process.Handle=\"%s\"",
|
|
IDS_CimWin32Namespace,
|
|
(LPCWSTR) chstrHandle);
|
|
|
|
pInstance->SetCHString(L"Member", chstrTmp);
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pInstance->Commit();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WinErrorToWBEMhResult(::GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WinErrorToWBEMhResult(::GetLastError());
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
bool CJOProcess::GetInstKey (
|
|
|
|
CHString& chstrInstPath,
|
|
CHString& chstrKeyName
|
|
)
|
|
{
|
|
// the object path is specified in
|
|
// the first arg. It should at a
|
|
// minimum always contain an '=' sign,
|
|
// after which, in quotes is the
|
|
// object key.
|
|
bool fRet = false;
|
|
CHString chstrTmp;
|
|
LONG lPos = chstrInstPath.Find(L'=');
|
|
if(lPos != -1)
|
|
{
|
|
chstrTmp = chstrInstPath.Mid(lPos + 1);
|
|
// Remove quotes...
|
|
if(chstrTmp.Left(1) == L"\"")
|
|
{
|
|
chstrTmp = chstrTmp.Mid(1);
|
|
if(chstrTmp.Right(1) == L"\"")
|
|
{
|
|
chstrTmp = chstrTmp.Left(chstrTmp.GetLength() - 1);
|
|
chstrKeyName = chstrTmp;
|
|
fRet = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
// Takes a decorated job object name and
|
|
// undecorates it. Decorated job object names
|
|
// have a backslash preceeding any character
|
|
// that should be uppercase once undecorated.
|
|
//
|
|
// Due to the way CIMOM handles backslashes,
|
|
// we will get capital letters preceeded by
|
|
// two, not just one, backslashes. Hence, we
|
|
// must strip them both.
|
|
//
|
|
// According to the decoration scheme, the
|
|
// following are both lower case: 'A' and 'a',
|
|
// while the following are both upper case:
|
|
// '\a' and '\A'.
|
|
//
|
|
|
|
void CJOProcess::UndecorateJOName (
|
|
|
|
LPCWSTR wstrDecoratedName,
|
|
CHString& chstrUndecoratedJOName
|
|
)
|
|
{
|
|
if(wstrDecoratedName != NULL &&
|
|
*wstrDecoratedName != L'\0')
|
|
{
|
|
LPWSTR wstrDecoratedNameLower = NULL;
|
|
|
|
try
|
|
{
|
|
wstrDecoratedNameLower = new WCHAR[wcslen(wstrDecoratedName)+1];
|
|
|
|
if(wstrDecoratedNameLower)
|
|
{
|
|
wcscpy(wstrDecoratedNameLower, wstrDecoratedName);
|
|
_wcslwr(wstrDecoratedNameLower);
|
|
|
|
WCHAR* p3 = chstrUndecoratedJOName.GetBuffer(
|
|
wcslen(wstrDecoratedNameLower) + 1);
|
|
|
|
const WCHAR* p1 = wstrDecoratedNameLower;
|
|
const WCHAR* p2 = p1 + 1;
|
|
|
|
while(*p1 != L'\0')
|
|
{
|
|
if(*p1 == L'\\')
|
|
{
|
|
if(*p2 != NULL)
|
|
{
|
|
// Might have any number of
|
|
// backslashes back to back,
|
|
// which we will treat as
|
|
// being the same as one
|
|
// backslash - i.e., we will
|
|
// skip over the backslash(s)
|
|
// and copy over the following
|
|
// letter.
|
|
while(*p2 == L'\\')
|
|
{
|
|
p2++;
|
|
};
|
|
|
|
*p3 = towupper(*p2);
|
|
p3++;
|
|
|
|
p1 = p2 + 1;
|
|
if(*p1 != L'\0')
|
|
{
|
|
p2 = p1 + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p1++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*p3 = *p1;
|
|
p3++;
|
|
|
|
p1 = p2;
|
|
if(*p1 != L'\0')
|
|
{
|
|
p2 = p1 + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
*p3 = NULL;
|
|
|
|
chstrUndecoratedJOName.ReleaseBuffer();
|
|
|
|
delete wstrDecoratedNameLower;
|
|
wstrDecoratedNameLower = NULL;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
if(wstrDecoratedNameLower)
|
|
{
|
|
delete wstrDecoratedNameLower;
|
|
wstrDecoratedNameLower = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Name:
|
|
*
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
// Does the inverse of the above function.
|
|
// However, here, we only need to put in one
|
|
// backslash before each uppercase letter.
|
|
// CIMOM will add the second backslash.
|
|
|
|
void CJOProcess::DecorateJOName (
|
|
|
|
LPCWSTR wstrUndecoratedName,
|
|
CHString& chstrDecoratedJOName
|
|
)
|
|
{
|
|
if(wstrUndecoratedName != NULL &&
|
|
*wstrUndecoratedName != L'\0')
|
|
{
|
|
// Worst case is that we will have
|
|
// a decorated string twice as long
|
|
// as the undecorated string (happens
|
|
// is every character in the undecorated
|
|
// string is a capital letter).
|
|
WCHAR* p3 = chstrDecoratedJOName.GetBuffer(
|
|
2 * (wcslen(wstrUndecoratedName) + 1));
|
|
|
|
const WCHAR* p1 = wstrUndecoratedName;
|
|
|
|
while(*p1 != L'\0')
|
|
{
|
|
if(iswupper(*p1))
|
|
{
|
|
// Add in a backslash...
|
|
*p3 = L'\\';
|
|
p3++;
|
|
|
|
// Add in the character...
|
|
*p3 = *p1;
|
|
|
|
p3++;
|
|
p1++;
|
|
}
|
|
else
|
|
{
|
|
// Add in the character...
|
|
*p3 = *p1;
|
|
|
|
p3++;
|
|
p1++;
|
|
}
|
|
}
|
|
|
|
*p3 = NULL;
|
|
|
|
chstrDecoratedJOName.ReleaseBuffer();
|
|
|
|
// What if we had a job called Job,
|
|
// and someone specified it in the
|
|
// object path as "Job" instead of
|
|
// "\Job"? We DON'T want to find it
|
|
// in such a case, because this would
|
|
// appear to not be adhering to our
|
|
// own convention. Hence, we
|
|
// lowercase the incoming string.
|
|
chstrDecoratedJOName.MakeLower();
|
|
}
|
|
}
|
|
|
|
#endif // #if NTONLY >= 5
|