Leaked source code of windows server 2003
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

  1. /******************************************************************
  2. Copyright (c) 2000-2002 Microsoft Corporation, All Rights Reserved
  3. JOProcess.CPP -- WMI provider class implementation
  4. ******************************************************************/
  5. #include "precomp.h"
  6. #if NTONLY >= 5
  7. #include "JOProcess.h"
  8. #include <autoptr.h>
  9. /******************************************************************************
  10. *
  11. * Name:
  12. *
  13. *
  14. * Description:
  15. *
  16. *
  17. *****************************************************************************/
  18. CJOProcess MyCJOProcess(
  19. PROVIDER_NAME_WIN32NAMEDJOBOBJECTPROCESS,
  20. IDS_CimWin32Namespace);
  21. /******************************************************************************
  22. *
  23. * Name:
  24. *
  25. *
  26. * Description:
  27. *
  28. *
  29. *****************************************************************************/
  30. CJOProcess::CJOProcess(
  31. LPCWSTR setName,
  32. LPCWSTR pszNameSpace /*=NULL*/)
  33. : Provider(setName, pszNameSpace)
  34. {
  35. }
  36. /******************************************************************************
  37. *
  38. * Name:
  39. *
  40. *
  41. * Description:
  42. *
  43. *
  44. *****************************************************************************/
  45. CJOProcess::~CJOProcess()
  46. {
  47. }
  48. /******************************************************************************
  49. *
  50. * Name:
  51. *
  52. *
  53. * Description:
  54. *
  55. *
  56. *****************************************************************************/
  57. HRESULT CJOProcess::GetObject(
  58. CInstance* pInstance,
  59. long lFlags /*= 0L*/ )
  60. {
  61. return FindSingleInstance(pInstance);
  62. }
  63. /******************************************************************************
  64. *
  65. * Name:
  66. *
  67. *
  68. * Description:
  69. *
  70. *
  71. *****************************************************************************/
  72. HRESULT CJOProcess::EnumerateInstances(
  73. MethodContext* pMethodContext,
  74. long lFlags)
  75. {
  76. HRESULT hr = WBEM_S_NO_ERROR;
  77. hr = Enumerate(pMethodContext);
  78. return hr;
  79. }
  80. /******************************************************************************
  81. *
  82. * Name:
  83. *
  84. *
  85. * Description:
  86. *
  87. *
  88. *****************************************************************************/
  89. // We will only optimize for the
  90. // case where a specific job was
  91. // specified.
  92. HRESULT CJOProcess::ExecQuery (
  93. MethodContext *pMethodContext,
  94. CFrameworkQuery& Query,
  95. long lFlags
  96. )
  97. {
  98. HRESULT hr = WBEM_S_NO_ERROR;
  99. std::vector<_bstr_t> rgJOs;
  100. DWORD dwJOsCount = 0L;
  101. Query.GetValuesForProp(L"Collection", rgJOs);
  102. dwJOsCount = rgJOs.size();
  103. if(dwJOsCount > 0)
  104. {
  105. CInstancePtr pInstJO;
  106. CHString chstrPath;
  107. for(DWORD x = 0; x < dwJOsCount; x++)
  108. {
  109. // First we see if the specified JO exists.
  110. chstrPath.Format(
  111. L"\\\\.\\%s:%s",
  112. IDS_CimWin32Namespace,
  113. (LPCWSTR)rgJOs[x]);
  114. hr = CWbemProviderGlue::GetInstanceKeysByPath(
  115. chstrPath,
  116. &pInstJO,
  117. pMethodContext);
  118. if (SUCCEEDED(hr))
  119. {
  120. // Ok, the JO exists. Enumerate its processes...
  121. // rgJOs[x] contains something like
  122. // Win32_NamedJobObject.CollectionID="myjob",
  123. // from which I want just the myjob part.
  124. CHString chstrInstKey;
  125. if(GetInstKey(
  126. CHString((LPCWSTR)rgJOs[x]),
  127. chstrInstKey))
  128. {
  129. hr = EnumerateProcsInJob(
  130. chstrInstKey,
  131. pMethodContext);
  132. if (FAILED(hr))
  133. {
  134. break;
  135. }
  136. }
  137. else
  138. {
  139. return WBEM_E_INVALID_PARAMETER;
  140. }
  141. }
  142. }
  143. }
  144. else
  145. {
  146. hr = Enumerate(pMethodContext);
  147. }
  148. return hr;
  149. }
  150. /******************************************************************************
  151. *
  152. * Name:
  153. *
  154. *
  155. * Description:
  156. *
  157. *
  158. *****************************************************************************/
  159. HRESULT CJOProcess::PutInstance (
  160. const CInstance &Instance,
  161. long lFlags
  162. )
  163. {
  164. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  165. MethodContext *pMethodContext = Instance.GetMethodContext();
  166. long lCreateFlags = lFlags & 3;
  167. // Decide how to proceed based on the value of lFlags:
  168. // (we want to support PutInstance in all cases except
  169. // where the client asked to update the instance).
  170. if(lCreateFlags != WBEM_FLAG_UPDATE_ONLY)
  171. {
  172. // The caller only wants to create an instance that doesn't exist.
  173. if((hr = FindSingleInstance(
  174. &Instance)) == WBEM_E_NOT_FOUND)
  175. {
  176. // The association instance does not already exist, so create it...
  177. // First see that the job object instance exists...
  178. CHString chstrJOPath;
  179. if ( ! Instance.GetCHString(L"Collection", chstrJOPath) )
  180. {
  181. return WBEM_E_FAILED ;
  182. }
  183. CInstancePtr pJOInst;
  184. hr = CWbemProviderGlue::GetInstanceKeysByPath(
  185. chstrJOPath,
  186. &pJOInst,
  187. pMethodContext);
  188. if (SUCCEEDED(hr))
  189. {
  190. // Confirm that the process exists...
  191. CHString chstrProcPath;
  192. if ( ! Instance.GetCHString(L"Member", chstrProcPath) )
  193. {
  194. return WBEM_E_FAILED ;
  195. }
  196. CInstancePtr pProcInst;
  197. hr = CWbemProviderGlue::GetInstanceKeysByPath(
  198. chstrProcPath,
  199. &pProcInst,
  200. pMethodContext);
  201. if(SUCCEEDED(hr))
  202. {
  203. hr = Create(pJOInst, pProcInst);
  204. }
  205. }
  206. }
  207. }
  208. return hr;
  209. }
  210. /*****************************************************************************
  211. *
  212. * FUNCTION : CJOProcess::FindSingleInstance
  213. *
  214. * DESCRIPTION : Internal helper function used to locate a single job
  215. * object.
  216. *
  217. * INPUTS : A pointer to a CInstance containing the instance we are
  218. * attempting to locate and fill values for.
  219. *
  220. * RETURNS : A valid HRESULT
  221. *
  222. *****************************************************************************/
  223. HRESULT CJOProcess::FindSingleInstance (
  224. const CInstance* pInstance
  225. )
  226. {
  227. HRESULT hr = WBEM_S_NO_ERROR;
  228. if(!pInstance)
  229. {
  230. return WBEM_E_INVALID_PARAMETER;
  231. }
  232. MethodContext* pMethodContext = pInstance->GetMethodContext();
  233. CHString chstrCollection;
  234. CHString chstrMember;
  235. // Find out which JO and which process are specified...
  236. if ( ! pInstance->GetCHString(L"Collection", chstrCollection) )
  237. {
  238. return WBEM_E_FAILED ;
  239. }
  240. if ( ! pInstance->GetCHString(L"Member", chstrMember) )
  241. {
  242. return WBEM_E_FAILED ;
  243. }
  244. CHString chstrCollectionID;
  245. CHString chstrProcessHandle;
  246. CInstancePtr cinstJO;
  247. CInstancePtr cinstProcess;
  248. if(GetInstKey(chstrCollection, chstrCollectionID) &&
  249. GetInstKey(chstrMember, chstrProcessHandle))
  250. {
  251. // See if the specified job exists...
  252. hr = CWbemProviderGlue::GetInstanceKeysByPath(
  253. chstrCollection,
  254. &cinstJO,
  255. pMethodContext);
  256. if(SUCCEEDED(hr))
  257. {
  258. // See if the specified process exists...
  259. hr = CWbemProviderGlue::GetInstanceKeysByPath(
  260. chstrMember,
  261. &cinstProcess,
  262. pMethodContext);
  263. }
  264. if(SUCCEEDED(hr))
  265. {
  266. // The endpoints exist. Is the specified
  267. // process part of the specified job though?
  268. CHString chstrProcessID;
  269. DWORD dwProcessID;
  270. if(cinstProcess->GetCHString(L"Handle", chstrProcessID))
  271. {
  272. dwProcessID = _wtoi(chstrProcessID);
  273. SmartCloseHandle hJob;
  274. CHString chstrUndecoratedJOName;
  275. UndecorateJOName(
  276. chstrCollectionID,
  277. chstrUndecoratedJOName);
  278. hJob = ::OpenJobObject(
  279. MAXIMUM_ALLOWED,
  280. FALSE,
  281. chstrUndecoratedJOName);
  282. if(hJob != NULL)
  283. {
  284. long lSize = 0L;
  285. bool fGotProcList = false;
  286. DWORD dwLen = 0L;
  287. lSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + (5 * sizeof(ULONG_PTR));
  288. wmilib::auto_buffer < BYTE > pbBuff ( new BYTE [ lSize ], lSize ) ;
  289. if ( pbBuff.get () )
  290. {
  291. fGotProcList = ::QueryInformationJobObject(
  292. hJob,
  293. JobObjectBasicProcessIdList,
  294. pbBuff.get (),
  295. lSize,
  296. &dwLen);
  297. if(!fGotProcList)
  298. {
  299. // need to grow the buffer...
  300. lSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) +
  301. (((JOBOBJECT_BASIC_PROCESS_ID_LIST*)pbBuff.get ())->NumberOfAssignedProcesses - 1)*sizeof(ULONG_PTR);
  302. pbBuff.reset ( new BYTE [ lSize ] ) ;
  303. if ( pbBuff.get () )
  304. {
  305. fGotProcList = ::QueryInformationJobObject(
  306. hJob,
  307. JobObjectBasicProcessIdList,
  308. pbBuff.get (),
  309. lSize,
  310. &dwLen);
  311. }
  312. else
  313. {
  314. hr = WBEM_E_OUT_OF_MEMORY;
  315. }
  316. }
  317. if(fGotProcList)
  318. {
  319. PJOBOBJECT_BASIC_PROCESS_ID_LIST pjobpl = static_cast<PJOBOBJECT_BASIC_PROCESS_ID_LIST>(static_cast<PVOID>(pbBuff.get ()));
  320. bool fExists = false;
  321. for(long m = 0;
  322. m < pjobpl->NumberOfProcessIdsInList && !fExists;
  323. m++)
  324. {
  325. if(dwProcessID == pjobpl->ProcessIdList[m])
  326. {
  327. fExists = true;
  328. }
  329. }
  330. // If the process wasn't in the job,
  331. // we didn't find an instance of the
  332. // requested association, even though
  333. // the endpoints may have existed.
  334. if(!fExists)
  335. {
  336. hr = WBEM_E_NOT_FOUND;
  337. }
  338. }
  339. else
  340. {
  341. hr = WinErrorToWBEMhResult(::GetLastError());
  342. }
  343. }
  344. else
  345. {
  346. hr = WBEM_E_OUT_OF_MEMORY;
  347. }
  348. }
  349. else
  350. {
  351. hr = WinErrorToWBEMhResult(::GetLastError());
  352. }
  353. }
  354. else
  355. {
  356. hr = WBEM_E_INVALID_PARAMETER;
  357. }
  358. }
  359. }
  360. else
  361. {
  362. hr = WBEM_E_FAILED;
  363. }
  364. return hr;
  365. }
  366. /*****************************************************************************
  367. *
  368. * FUNCTION : CJOProcess::Create
  369. *
  370. * DESCRIPTION : Internal helper function used to add a process to a job.
  371. *
  372. * INPUTS : A pointer to the JO instance to add the proc to, and
  373. * a pointer to the proc instance to add
  374. *
  375. * RETURNS : A valid HRESULT.
  376. *
  377. *****************************************************************************/
  378. HRESULT CJOProcess::Create (
  379. const CInstance &JOInstance,
  380. const CInstance &ProcInstance
  381. )
  382. {
  383. HRESULT hr = WBEM_S_NO_ERROR;
  384. CHString chstrJOID;
  385. CHString chstrProcHandle;
  386. // JO to add the proc to...
  387. if ( ! JOInstance.GetCHString(L"CollectionID", chstrJOID) )
  388. {
  389. return WBEM_E_FAILED ;
  390. }
  391. // Proc to add to the job...
  392. if ( ! ProcInstance.GetCHString(L"Handle", chstrProcHandle) )
  393. {
  394. return WBEM_E_FAILED ;
  395. }
  396. DWORD dwProcID = _wtol(chstrProcHandle);
  397. // Do the add
  398. SmartCloseHandle hJob;
  399. CHString chstrUndecoratedJOName;
  400. UndecorateJOName(
  401. chstrJOID,
  402. chstrUndecoratedJOName);
  403. hJob = ::OpenJobObject(
  404. MAXIMUM_ALLOWED,
  405. FALSE,
  406. chstrUndecoratedJOName);
  407. if(hJob != NULL)
  408. {
  409. SmartCloseHandle hProc;
  410. hProc = ::OpenProcess(
  411. PROCESS_ALL_ACCESS,
  412. FALSE,
  413. dwProcID);
  414. if(hProc != NULL)
  415. {
  416. if(!::AssignProcessToJobObject(
  417. hJob,
  418. hProc))
  419. {
  420. hr = MAKE_SCODE(
  421. SEVERITY_ERROR,
  422. FACILITY_WIN32,
  423. GetLastError());
  424. }
  425. }
  426. }
  427. else
  428. {
  429. hr = WinErrorToWBEMhResult(::GetLastError());
  430. }
  431. return hr;
  432. }
  433. /*****************************************************************************
  434. *
  435. * FUNCTION : CJOProcess::Enumerate
  436. *
  437. * DESCRIPTION : Internal helper function used to enumerate instances of
  438. * this class. All instances are enumerated, but only the
  439. * properties specified are obtained.
  440. *
  441. * INPUTS : A pointer to a the MethodContext for the call.
  442. * A DWORD specifying which properties are requested.
  443. *
  444. * RETURNS : A valid HRESULT
  445. *
  446. *****************************************************************************/
  447. HRESULT CJOProcess::Enumerate (
  448. MethodContext *pMethodContext
  449. )
  450. {
  451. HRESULT hr = WBEM_S_NO_ERROR;
  452. TRefPointerCollection<CInstance> JOList;
  453. hr = CWbemProviderGlue::GetInstancesByQuery(
  454. L"SELECT CollectionID FROM Win32_NamedJobObject",
  455. &JOList,
  456. pMethodContext,
  457. IDS_CimWin32Namespace);
  458. if(SUCCEEDED(hr))
  459. {
  460. REFPTRCOLLECTION_POSITION pos;
  461. // Initialize the enum
  462. if(JOList.BeginEnum(pos))
  463. {
  464. // Set some vars
  465. CHString chstrJOID;
  466. CInstancePtr pJOInst;
  467. for (pJOInst.Attach(JOList.GetNext(pos)) ;
  468. (pJOInst != NULL) ;
  469. pJOInst.Attach(JOList.GetNext(pos)) )
  470. {
  471. bool t_Status = pJOInst->GetCHString (
  472. L"CollectionID",
  473. chstrJOID
  474. ) ;
  475. if ( t_Status )
  476. {
  477. hr = EnumerateProcsInJob (
  478. chstrJOID,
  479. pMethodContext
  480. );
  481. }
  482. else
  483. {
  484. hr = WBEM_E_FAILED ;
  485. }
  486. }
  487. }
  488. }
  489. return hr;
  490. }
  491. /******************************************************************************
  492. *
  493. * Name:
  494. *
  495. *
  496. * Description:
  497. *
  498. *
  499. *****************************************************************************/
  500. HRESULT CJOProcess::EnumerateProcsInJob (
  501. LPCWSTR wstrJobID,
  502. MethodContext *pMethodContext
  503. )
  504. {
  505. HRESULT hr = WBEM_S_NO_ERROR;
  506. SmartCloseHandle hJob;
  507. CHString chstrUndecoratedJOName;
  508. UndecorateJOName(
  509. wstrJobID,
  510. chstrUndecoratedJOName);
  511. hJob = ::OpenJobObject(
  512. MAXIMUM_ALLOWED,
  513. FALSE,
  514. chstrUndecoratedJOName);
  515. if(hJob != NULL)
  516. {
  517. long lSize = 0L;
  518. bool fGotProcList = false;
  519. DWORD dwLen = 0L;
  520. lSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + (5 * sizeof(ULONG_PTR));
  521. wmilib::auto_buffer < BYTE > pbBuff ( new BYTE [ lSize ], lSize ) ;
  522. if ( pbBuff.get () )
  523. {
  524. fGotProcList = ::QueryInformationJobObject(
  525. hJob,
  526. JobObjectBasicProcessIdList,
  527. pbBuff.get (),
  528. lSize,
  529. &dwLen);
  530. if(!fGotProcList)
  531. {
  532. // need to grow the buffer...
  533. lSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) +
  534. (((JOBOBJECT_BASIC_PROCESS_ID_LIST*)pbBuff.get ())->NumberOfAssignedProcesses - 1)*sizeof(ULONG_PTR);
  535. pbBuff.reset ( new BYTE [ lSize ] ) ;
  536. if ( pbBuff.get () )
  537. {
  538. fGotProcList = ::QueryInformationJobObject(
  539. hJob,
  540. JobObjectBasicProcessIdList,
  541. pbBuff.get (),
  542. lSize,
  543. &dwLen);
  544. }
  545. else
  546. {
  547. hr = WBEM_E_OUT_OF_MEMORY;
  548. }
  549. }
  550. if(fGotProcList)
  551. {
  552. PJOBOBJECT_BASIC_PROCESS_ID_LIST pjobpl = static_cast<PJOBOBJECT_BASIC_PROCESS_ID_LIST>(static_cast<PVOID>(pbBuff.get ()));
  553. for(long m = 0;
  554. m < pjobpl->NumberOfProcessIdsInList;
  555. m++)
  556. {
  557. // Create association inst for each
  558. // proc in the job...
  559. CInstancePtr pInstance(CreateNewInstance(pMethodContext),
  560. false);
  561. // Set the endpoints...
  562. CHString chstrEscaped;
  563. DecorateJOName(chstrUndecoratedJOName, chstrEscaped);
  564. EscapeBackslashes(chstrEscaped, chstrEscaped);
  565. EscapeQuotes(chstrEscaped, chstrEscaped);
  566. CHString chstrTmp;
  567. chstrTmp.Format(L"\\\\.\\%s:Win32_NamedJobObject.CollectionID=\"%s\"",
  568. IDS_CimWin32Namespace,
  569. (LPCWSTR)chstrEscaped);
  570. pInstance->SetCHString(L"Collection", chstrTmp);
  571. CHString chstrHandle;
  572. chstrHandle.Format(L"%d", pjobpl->ProcessIdList[m]);
  573. chstrTmp.Format(L"\\\\.\\%s:Win32_Process.Handle=\"%s\"",
  574. IDS_CimWin32Namespace,
  575. (LPCWSTR) chstrHandle);
  576. pInstance->SetCHString(L"Member", chstrTmp);
  577. if (SUCCEEDED(hr))
  578. {
  579. hr = pInstance->Commit();
  580. }
  581. }
  582. }
  583. else
  584. {
  585. hr = WinErrorToWBEMhResult(::GetLastError());
  586. }
  587. }
  588. else
  589. {
  590. hr = WBEM_E_OUT_OF_MEMORY;
  591. }
  592. }
  593. else
  594. {
  595. hr = WinErrorToWBEMhResult(::GetLastError());
  596. }
  597. return hr;
  598. }
  599. /******************************************************************************
  600. *
  601. * Name:
  602. *
  603. *
  604. * Description:
  605. *
  606. *
  607. *****************************************************************************/
  608. bool CJOProcess::GetInstKey (
  609. CHString& chstrInstPath,
  610. CHString& chstrKeyName
  611. )
  612. {
  613. // the object path is specified in
  614. // the first arg. It should at a
  615. // minimum always contain an '=' sign,
  616. // after which, in quotes is the
  617. // object key.
  618. bool fRet = false;
  619. CHString chstrTmp;
  620. LONG lPos = chstrInstPath.Find(L'=');
  621. if(lPos != -1)
  622. {
  623. chstrTmp = chstrInstPath.Mid(lPos + 1);
  624. // Remove quotes...
  625. if(chstrTmp.Left(1) == L"\"")
  626. {
  627. chstrTmp = chstrTmp.Mid(1);
  628. if(chstrTmp.Right(1) == L"\"")
  629. {
  630. chstrTmp = chstrTmp.Left(chstrTmp.GetLength() - 1);
  631. chstrKeyName = chstrTmp;
  632. fRet = true;
  633. }
  634. }
  635. }
  636. return fRet;
  637. }
  638. /******************************************************************************
  639. *
  640. * Name:
  641. *
  642. *
  643. * Description:
  644. *
  645. *
  646. *****************************************************************************/
  647. // Takes a decorated job object name and
  648. // undecorates it. Decorated job object names
  649. // have a backslash preceeding any character
  650. // that should be uppercase once undecorated.
  651. //
  652. // Due to the way CIMOM handles backslashes,
  653. // we will get capital letters preceeded by
  654. // two, not just one, backslashes. Hence, we
  655. // must strip them both.
  656. //
  657. // According to the decoration scheme, the
  658. // following are both lower case: 'A' and 'a',
  659. // while the following are both upper case:
  660. // '\a' and '\A'.
  661. //
  662. void CJOProcess::UndecorateJOName (
  663. LPCWSTR wstrDecoratedName,
  664. CHString& chstrUndecoratedJOName
  665. )
  666. {
  667. if(wstrDecoratedName != NULL &&
  668. *wstrDecoratedName != L'\0')
  669. {
  670. LPWSTR wstrDecoratedNameLower = NULL;
  671. try
  672. {
  673. wstrDecoratedNameLower = new WCHAR[wcslen(wstrDecoratedName)+1];
  674. if(wstrDecoratedNameLower)
  675. {
  676. wcscpy(wstrDecoratedNameLower, wstrDecoratedName);
  677. _wcslwr(wstrDecoratedNameLower);
  678. WCHAR* p3 = chstrUndecoratedJOName.GetBuffer(
  679. wcslen(wstrDecoratedNameLower) + 1);
  680. const WCHAR* p1 = wstrDecoratedNameLower;
  681. const WCHAR* p2 = p1 + 1;
  682. while(*p1 != L'\0')
  683. {
  684. if(*p1 == L'\\')
  685. {
  686. if(*p2 != NULL)
  687. {
  688. // Might have any number of
  689. // backslashes back to back,
  690. // which we will treat as
  691. // being the same as one
  692. // backslash - i.e., we will
  693. // skip over the backslash(s)
  694. // and copy over the following
  695. // letter.
  696. while(*p2 == L'\\')
  697. {
  698. p2++;
  699. };
  700. *p3 = towupper(*p2);
  701. p3++;
  702. p1 = p2 + 1;
  703. if(*p1 != L'\0')
  704. {
  705. p2 = p1 + 1;
  706. }
  707. }
  708. else
  709. {
  710. p1++;
  711. }
  712. }
  713. else
  714. {
  715. *p3 = *p1;
  716. p3++;
  717. p1 = p2;
  718. if(*p1 != L'\0')
  719. {
  720. p2 = p1 + 1;
  721. }
  722. }
  723. }
  724. *p3 = NULL;
  725. chstrUndecoratedJOName.ReleaseBuffer();
  726. delete wstrDecoratedNameLower;
  727. wstrDecoratedNameLower = NULL;
  728. }
  729. }
  730. catch(...)
  731. {
  732. if(wstrDecoratedNameLower)
  733. {
  734. delete wstrDecoratedNameLower;
  735. wstrDecoratedNameLower = NULL;
  736. }
  737. throw;
  738. }
  739. }
  740. }
  741. /******************************************************************************
  742. *
  743. * Name:
  744. *
  745. *
  746. * Description:
  747. *
  748. *
  749. *****************************************************************************/
  750. // Does the inverse of the above function.
  751. // However, here, we only need to put in one
  752. // backslash before each uppercase letter.
  753. // CIMOM will add the second backslash.
  754. void CJOProcess::DecorateJOName (
  755. LPCWSTR wstrUndecoratedName,
  756. CHString& chstrDecoratedJOName
  757. )
  758. {
  759. if(wstrUndecoratedName != NULL &&
  760. *wstrUndecoratedName != L'\0')
  761. {
  762. // Worst case is that we will have
  763. // a decorated string twice as long
  764. // as the undecorated string (happens
  765. // is every character in the undecorated
  766. // string is a capital letter).
  767. WCHAR* p3 = chstrDecoratedJOName.GetBuffer(
  768. 2 * (wcslen(wstrUndecoratedName) + 1));
  769. const WCHAR* p1 = wstrUndecoratedName;
  770. while(*p1 != L'\0')
  771. {
  772. if(iswupper(*p1))
  773. {
  774. // Add in a backslash...
  775. *p3 = L'\\';
  776. p3++;
  777. // Add in the character...
  778. *p3 = *p1;
  779. p3++;
  780. p1++;
  781. }
  782. else
  783. {
  784. // Add in the character...
  785. *p3 = *p1;
  786. p3++;
  787. p1++;
  788. }
  789. }
  790. *p3 = NULL;
  791. chstrDecoratedJOName.ReleaseBuffer();
  792. // What if we had a job called Job,
  793. // and someone specified it in the
  794. // object path as "Job" instead of
  795. // "\Job"? We DON'T want to find it
  796. // in such a case, because this would
  797. // appear to not be adhering to our
  798. // own convention. Hence, we
  799. // lowercase the incoming string.
  800. chstrDecoratedJOName.MakeLower();
  801. }
  802. }
  803. #endif // #if NTONLY >= 5