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.

1009 lines
29 KiB

  1. // Copyright (c) 2000-2002 Microsoft Corporation, All Rights Reserved
  2. // Helpers.cpp: Helper functions for the SecUtil component
  3. //#include "FWCommon.h"
  4. //#include <windows.h>
  5. //#include <winnt.h>
  6. /*
  7. #ifndef USE_POLARITY
  8. // For most users, this is the correct setting for POLARITY.
  9. #define USE_POLARITY
  10. #endif
  11. */
  12. #include "precomp.h"
  13. #include <cominit.h>
  14. #include <vector>
  15. #include "Helpers.h"
  16. #include "AssertBreak.h"
  17. #include "CVARIANT.H"
  18. #include <crtdbg.h>
  19. #define IDS_NTDLLDOTDLL L"NTDLL.DLL"
  20. #define IDS_NTOPENDIRECTORYOBJECT "NtOpenDirectoryObject"
  21. #define IDS_NTQUERYDIRECTORYOBJECT "NtQueryDirectoryObject"
  22. #define IDS_RTLINITUNICODESTRING "RtlInitUnicodeString"
  23. #define IDS_WHACKWHACKBASENAMEDOBJECTS L"\\BaseNamedObjects"
  24. #define IDS_NTQUERYINFORMATIONPROCESS "NtQueryInformationProcess"
  25. #define IDS_NTOPENPROCESS "NtOpenProcess"
  26. #define IDS_WIN32_ERROR_CODE L"Win32ErrorCode"
  27. #define IDS_ADDITIONAL_DESCRIPTION L"AdditionalDescription"
  28. #define IDS_OPERATION L"Operation"
  29. typedef NTSTATUS (NTAPI *PFN_NT_OPEN_DIRECTORY_OBJECT)
  30. (
  31. OUT PHANDLE DirectoryHandle,
  32. IN ACCESS_MASK DesiredAccess,
  33. IN POBJECT_ATTRIBUTES ObjectAttributes
  34. );
  35. typedef NTSTATUS (NTAPI *PFN_NT_QUERY_DIRECTORY_OBJECT)
  36. (
  37. IN HANDLE DirectoryHandle,
  38. OUT PVOID Buffer,
  39. IN ULONG Length,
  40. IN BOOLEAN ReturnSingleEntry,
  41. IN BOOLEAN RestartScan,
  42. IN OUT PULONG Context,
  43. OUT PULONG ReturnLength OPTIONAL
  44. );
  45. typedef VOID (WINAPI *PFN_NTDLL_RTL_INIT_UNICODE_STRING)
  46. (
  47. OUT PUNICODE_STRING DestinationString,
  48. IN PCWSTR SourceString
  49. );
  50. typedef NTSTATUS (NTAPI *PFN_NTDLL_NT_QUERY_INFORMATION_PROCESS)
  51. (
  52. IN HANDLE ProcessHandle,
  53. IN PROCESSINFOCLASS ProcessInformationClass,
  54. OUT PVOID ProcessInformation,
  55. IN ULONG ProcessInformationLength,
  56. OUT PULONG ReturnLength OPTIONAL
  57. );
  58. typedef NTSTATUS (NTAPI *PFN_NT_OPEN_PROCESS)
  59. (
  60. OUT PHANDLE ProcessHandle,
  61. IN ACCESS_MASK DesiredAccess,
  62. IN POBJECT_ATTRIBUTES ObjectAttributes,
  63. IN PCLIENT_ID ClientId OPTIONAL
  64. );
  65. //***************************************************************************
  66. //
  67. // CreateInst
  68. //
  69. // Purpose: Creates a new instance.
  70. //
  71. // Return: S_OK if all is well, otherwise an error code is returned
  72. //
  73. //***************************************************************************
  74. HRESULT CreateInst(
  75. IWbemServices *pNamespace,
  76. IWbemClassObject **pNewInst,
  77. BSTR bstrClassName,
  78. IWbemContext *pCtx)
  79. {
  80. HRESULT hr = S_OK;
  81. IWbemClassObjectPtr pClass;
  82. hr = pNamespace->GetObject(
  83. bstrClassName,
  84. 0,
  85. pCtx,
  86. &pClass,
  87. NULL);
  88. if(SUCCEEDED(hr))
  89. {
  90. hr = pClass->SpawnInstance(
  91. 0,
  92. pNewInst);
  93. }
  94. return hr;
  95. }
  96. //***************************************************************************
  97. //
  98. // GetObjInstKeyVal
  99. //
  100. // Purpose: Obtains an object's instance key from an object path.
  101. //
  102. // Return: true if the key was obtained.
  103. //
  104. //***************************************************************************
  105. HRESULT GetObjInstKeyVal(
  106. const BSTR ObjectPath,
  107. LPCWSTR wstrClassName,
  108. LPCWSTR wstrKeyPropName,
  109. LPWSTR wstrObjInstKeyVal,
  110. long lBufLen)
  111. {
  112. HRESULT hr = WBEM_S_NO_ERROR;
  113. WCHAR* pwcEqualSign = NULL;
  114. WCHAR* pwcTmp = NULL;
  115. if(!ObjectPath)
  116. {
  117. return WBEM_E_INVALID_PARAMETER;
  118. }
  119. if((pwcEqualSign = wcschr(ObjectPath, L'=')) != NULL)
  120. {
  121. pwcEqualSign++;
  122. long lLen = wcslen(pwcEqualSign) * sizeof(WCHAR);
  123. if(*pwcEqualSign &&
  124. lLen > 0 &&
  125. lLen < (long)(lBufLen - sizeof(WCHAR)))
  126. {
  127. wcscpy(wstrObjInstKeyVal, pwcEqualSign);
  128. // Remove any quotation marks that might
  129. // be there...
  130. RemoveQuotes(wstrObjInstKeyVal);
  131. // Also need to check that the class name
  132. // matches the name specified...
  133. WCHAR wstrClass[_MAX_PATH];
  134. wcscpy(wstrClass, ObjectPath);
  135. pwcTmp = wcschr(wstrClass, L'=');
  136. if(pwcTmp)
  137. {
  138. *pwcTmp = '\0';
  139. // Either the key property was specified or
  140. // it wasn't...
  141. pwcTmp = NULL;
  142. pwcTmp = wcschr(wstrClass, L'.');
  143. if(pwcTmp)
  144. {
  145. // Key property specified, so check that
  146. // both it and the class name are correct...
  147. *pwcTmp = '\0';
  148. if(_wcsicmp(wstrClassName, wstrClass) == 0)
  149. {
  150. if(_wcsicmp(wstrKeyPropName, ++pwcTmp) != 0)
  151. {
  152. hr = WBEM_E_INVALID_PARAMETER;
  153. }
  154. }
  155. else
  156. {
  157. hr = WBEM_E_INVALID_CLASS;
  158. }
  159. }
  160. else
  161. {
  162. // No key prop specified, so only need
  163. // to check that the class name is correct...
  164. if(_wcsicmp(wstrClassName, wstrClass) != 0)
  165. {
  166. hr = WBEM_E_INVALID_CLASS;
  167. }
  168. }
  169. }
  170. else
  171. {
  172. hr = WBEM_E_INVALID_PARAMETER;
  173. }
  174. }
  175. else
  176. {
  177. hr = WBEM_E_INVALID_PARAMETER;
  178. }
  179. }
  180. else
  181. {
  182. hr = WBEM_E_INVALID_PARAMETER;
  183. }
  184. return hr;
  185. }
  186. HRESULT GetJobObjectList(
  187. std::vector<_bstr_t>& rgbstrtJOs)
  188. {
  189. HRESULT hr = S_OK;
  190. HINSTANCE hinst = NULL;
  191. SmartCloseHANDLE hDir;
  192. PBYTE pbBuff = NULL;
  193. try
  194. {
  195. if((hinst = ::LoadLibrary(IDS_NTDLLDOTDLL)) != NULL)
  196. {
  197. PFN_NT_OPEN_DIRECTORY_OBJECT pfnNtOpenDirectoryObject = NULL;
  198. PFN_NT_QUERY_DIRECTORY_OBJECT pfnNtQueryDirectoryObject = NULL;
  199. PFN_NTDLL_RTL_INIT_UNICODE_STRING pfnRtlInitUnicodeString = NULL;
  200. pfnNtOpenDirectoryObject = (PFN_NT_OPEN_DIRECTORY_OBJECT)
  201. ::GetProcAddress(hinst, IDS_NTOPENDIRECTORYOBJECT);
  202. pfnNtQueryDirectoryObject = (PFN_NT_QUERY_DIRECTORY_OBJECT)
  203. ::GetProcAddress(hinst, IDS_NTQUERYDIRECTORYOBJECT);
  204. pfnRtlInitUnicodeString = (PFN_NTDLL_RTL_INIT_UNICODE_STRING)
  205. ::GetProcAddress(hinst, IDS_RTLINITUNICODESTRING);
  206. if(pfnNtOpenDirectoryObject != NULL &&
  207. pfnNtQueryDirectoryObject != NULL &&
  208. pfnRtlInitUnicodeString != NULL)
  209. {
  210. OBJECT_ATTRIBUTES oaAttributes;
  211. UNICODE_STRING ustrNtFileName;
  212. NTSTATUS ntstat = -1L;
  213. pfnRtlInitUnicodeString(&ustrNtFileName,
  214. IDS_WHACKWHACKBASENAMEDOBJECTS);
  215. InitializeObjectAttributes(&oaAttributes,
  216. &ustrNtFileName,
  217. OBJ_CASE_INSENSITIVE,
  218. NULL,
  219. NULL);
  220. ntstat = pfnNtOpenDirectoryObject(&hDir,
  221. FILE_READ_DATA,
  222. &oaAttributes);
  223. if(NT_SUCCESS(ntstat))
  224. {
  225. ULONG ulContext = -1L;
  226. ntstat = STATUS_SUCCESS;
  227. ULONG ulBufLen = 0L;
  228. ULONG ulNewBufLen = 0L;
  229. // First query to get buffer size to allocate...
  230. ntstat = pfnNtQueryDirectoryObject(hDir, // IN HANDLE DirectoryHandle,
  231. NULL, // OUT PVOID Buffer,
  232. 0L, // IN ULONG Length,
  233. FALSE, // IN BOOLEAN ReturnSingleEntry,
  234. TRUE, // IN BOOLEAN RestartScan,
  235. &ulContext, // IN OUT PULONG Context,
  236. &ulBufLen); // OUT PULONG ReturnLength OPTIONAL
  237. pbBuff = new BYTE[ulBufLen];
  238. if(pbBuff)
  239. {
  240. // then loop through all the entries...
  241. for(; ntstat != STATUS_NO_MORE_ENTRIES && pbBuff != NULL;)
  242. {
  243. ntstat = pfnNtQueryDirectoryObject(hDir, // IN HANDLE DirectoryHandle,
  244. pbBuff, // OUT PVOID Buffer,
  245. ulBufLen, // IN ULONG Length,
  246. TRUE, // IN BOOLEAN ReturnSingleEntry,
  247. FALSE, // IN BOOLEAN RestartScan,
  248. &ulContext, // IN OUT PULONG Context,
  249. &ulNewBufLen); // OUT PULONG ReturnLength OPTIONAL
  250. if(ntstat == STATUS_BUFFER_TOO_SMALL)
  251. {
  252. // Deallocate buffer and reallocate...
  253. if(pbBuff != NULL)
  254. {
  255. delete pbBuff;
  256. pbBuff = NULL;
  257. }
  258. pbBuff = new BYTE[ulNewBufLen];
  259. ulBufLen = ulNewBufLen;
  260. }
  261. else if(NT_SUCCESS(ntstat))
  262. {
  263. // All went well, should have data...
  264. if(pbBuff != NULL)
  265. {
  266. POBJECT_DIRECTORY_INFORMATION podi = (POBJECT_DIRECTORY_INFORMATION) pbBuff;
  267. LPWSTR wstrName = (LPWSTR)podi->Name.Buffer;
  268. LPWSTR wstrType = (LPWSTR)podi->TypeName.Buffer;
  269. // do something...
  270. // offset to string name is in four bytes...
  271. if(wstrName != NULL &&
  272. wstrType != NULL &&
  273. wcslen(wstrType) == 3)
  274. {
  275. WCHAR wstrTmp[4]; wstrTmp[3] = '\0';
  276. wcsncpy(wstrTmp, wstrType, 3);
  277. if(_wcsicmp(wstrTmp, L"job") == 0)
  278. {
  279. rgbstrtJOs.push_back(_bstr_t(wstrName));
  280. }
  281. }
  282. }
  283. }
  284. else if(ntstat == STATUS_NO_MORE_ENTRIES)
  285. {
  286. // we will break
  287. }
  288. else
  289. {
  290. // Something we weren't expecting happened, so bail out...
  291. hr = E_FAIL;
  292. }
  293. } // while we still have entries
  294. delete pbBuff;
  295. pbBuff = NULL;
  296. }
  297. else
  298. {
  299. hr = E_OUTOFMEMORY;
  300. }
  301. } // NtOpenDirectoryObject succeeded
  302. else
  303. {
  304. hr = E_FAIL;
  305. }
  306. } // Got the fn ptrs
  307. else
  308. {
  309. hr = E_FAIL;
  310. }
  311. ::FreeLibrary(hinst);
  312. }
  313. else
  314. {
  315. hr = E_FAIL;
  316. }
  317. }
  318. catch(...)
  319. {
  320. if(pbBuff != NULL)
  321. {
  322. delete pbBuff; pbBuff = NULL;
  323. }
  324. if(hinst != NULL)
  325. {
  326. ::FreeLibrary(hinst); hinst = NULL;
  327. }
  328. throw;
  329. }
  330. return hr;
  331. }
  332. void StringFromSid(PSID psid, _bstr_t& strSID)
  333. {
  334. // Initialize m_strSid - human readable form of our SID
  335. SID_IDENTIFIER_AUTHORITY *psia = NULL;
  336. psia = ::GetSidIdentifierAuthority(psid);
  337. WCHAR wstrTmp[_MAX_PATH];
  338. // We assume that only last byte is used
  339. // (authorities between 0 and 15).
  340. // Correct this if needed.
  341. ASSERT( psia->Value[0] ==
  342. psia->Value[1] ==
  343. psia->Value[2] ==
  344. psia->Value[3] ==
  345. psia->Value[4] == 0 );
  346. DWORD dwTopAuthority = psia->Value[5];
  347. wsprintf(wstrTmp, L"S-1-%u", dwTopAuthority);
  348. WCHAR wstrSubAuthority[_MAX_PATH];
  349. int iSubAuthorityCount = *(GetSidSubAuthorityCount(psid));
  350. for ( int i = 0; i < iSubAuthorityCount; i++ ) {
  351. DWORD dwSubAuthority = *(GetSidSubAuthority(psid, i));
  352. wsprintf(wstrSubAuthority, L"%u", dwSubAuthority);
  353. wcscat(wstrTmp, L"-");
  354. wcscat(wstrTmp, wstrSubAuthority);
  355. }
  356. strSID = wstrTmp;
  357. }
  358. void RemoveQuotes(LPWSTR wstrObjInstKeyVal)
  359. {
  360. WCHAR wstrTmp[MAX_PATH] = { L'\0' };
  361. WCHAR* pwchr = NULL;
  362. // Get rid of the first quote...
  363. if((pwchr = wcschr(wstrObjInstKeyVal, L'"')) != NULL)
  364. {
  365. wcscpy(wstrTmp, pwchr+1);
  366. }
  367. // now the last...
  368. if((pwchr = wcsrchr(wstrTmp, L'"')) != NULL)
  369. {
  370. *pwchr = L'\0';
  371. }
  372. wcscpy(wstrObjInstKeyVal, wstrTmp);
  373. }
  374. HRESULT CheckImpersonationLevel()
  375. {
  376. HRESULT hr = WBEM_E_ACCESS_DENIED;
  377. OSVERSIONINFOW OsVersionInfoW;
  378. OsVersionInfoW.dwOSVersionInfoSize = sizeof (OSVERSIONINFOW);
  379. GetVersionExW(&OsVersionInfoW);
  380. if (OsVersionInfoW.dwPlatformId == VER_PLATFORM_WIN32_NT)
  381. {
  382. HRESULT hRes = WbemCoImpersonateClient();
  383. if (SUCCEEDED(hRes)) // From cominit.cpp - needed for nt3.51
  384. {
  385. // Now, let's check the impersonation level. First, get the thread token
  386. SmartCloseHANDLE hThreadTok;
  387. DWORD dwImp, dwBytesReturned;
  388. if (!OpenThreadToken(
  389. GetCurrentThread(),
  390. TOKEN_QUERY,
  391. TRUE,
  392. &hThreadTok
  393. ))
  394. {
  395. DWORD dwLastError = GetLastError();
  396. if (dwLastError == ERROR_NO_TOKEN)
  397. {
  398. // If the CoImpersonate works, but the OpenThreadToken fails due to ERROR_NO_TOKEN, we
  399. // are running under the process token (either local system, or if we are running
  400. // with /exe, the rights of the logged in user). In either case, impersonation rights
  401. // don't apply. We have the full rights of that user.
  402. hr = WBEM_S_NO_ERROR;
  403. }
  404. else
  405. {
  406. // If we failed to get the thread token for any other reason, an error.
  407. hr = WBEM_E_ACCESS_DENIED;
  408. }
  409. }
  410. else
  411. {
  412. // We really do have a thread token, so let's retrieve its level
  413. if (GetTokenInformation(
  414. hThreadTok,
  415. TokenImpersonationLevel,
  416. &dwImp,
  417. sizeof(DWORD),
  418. &dwBytesReturned
  419. ))
  420. {
  421. // Is the impersonation level Impersonate?
  422. if ((dwImp == SecurityImpersonation) || (dwImp == SecurityDelegation))
  423. {
  424. hr = WBEM_S_NO_ERROR;
  425. }
  426. else
  427. {
  428. hr = WBEM_E_ACCESS_DENIED;
  429. }
  430. }
  431. else
  432. {
  433. hr = WBEM_E_FAILED;
  434. }
  435. }
  436. if (FAILED(hr))
  437. {
  438. WbemCoRevertToSelf();
  439. }
  440. }
  441. else if (hRes == E_NOTIMPL)
  442. {
  443. // On 3.51 or vanilla 95, this call is not implemented, we should work anyway
  444. hr = WBEM_S_NO_ERROR;
  445. }
  446. }
  447. else
  448. {
  449. // let win9X in...
  450. hr = WBEM_S_NO_ERROR;
  451. }
  452. return hr;
  453. }
  454. HRESULT SetStatusObject(
  455. IWbemContext* pCtx,
  456. IWbemServices* pSvcs,
  457. DWORD dwError,
  458. LPCWSTR wstrErrorDescription,
  459. LPCWSTR wstrOperation,
  460. LPCWSTR wstrNamespace,
  461. IWbemClassObject** ppStatusObjOut)
  462. {
  463. HRESULT hr = WBEM_S_NO_ERROR;
  464. IWbemClassObject* pStatusObj = NULL;
  465. ASSERT_BREAK(pCtx != NULL);
  466. ASSERT_BREAK(pSvcs != NULL);
  467. if(pSvcs && ppStatusObjOut && pCtx)
  468. {
  469. pStatusObj = GetStatusObject(
  470. pCtx,
  471. pSvcs);
  472. if(pStatusObj != NULL)
  473. {
  474. CVARIANT v;
  475. // Set the error code:
  476. v.SetLONG(dwError);
  477. pStatusObj->Put(
  478. IDS_WIN32_ERROR_CODE,
  479. 0,
  480. &v,
  481. NULL);
  482. v.Clear();
  483. // Set the error description
  484. if(wstrErrorDescription != NULL &&
  485. *wstrErrorDescription != L'\0')
  486. {
  487. v.SetStr(wstrErrorDescription);
  488. pStatusObj->Put(
  489. IDS_ADDITIONAL_DESCRIPTION,
  490. 0,
  491. &v,
  492. NULL);
  493. v.Clear();
  494. }
  495. if(wstrOperation != NULL &&
  496. *wstrOperation != L'\0')
  497. {
  498. v.SetStr(wstrOperation);
  499. pStatusObj->Put(
  500. IDS_OPERATION,
  501. 0,
  502. &v,
  503. NULL);
  504. v.Clear();
  505. }
  506. }
  507. if(pStatusObj)
  508. {
  509. if(*ppStatusObjOut != NULL)
  510. {
  511. (*ppStatusObjOut)->Release();
  512. *ppStatusObjOut = NULL;
  513. }
  514. *ppStatusObjOut = pStatusObj;
  515. }
  516. else
  517. {
  518. hr = WBEM_E_FAILED;
  519. }
  520. }
  521. else
  522. {
  523. hr = WBEM_E_FAILED;
  524. }
  525. return hr;
  526. }
  527. IWbemClassObject* GetStatusObject(
  528. IWbemContext* pContext,
  529. IWbemServices* pSrvc)
  530. {
  531. ASSERT_BREAK(pContext != NULL);
  532. ASSERT_BREAK(pSrvc != NULL);
  533. IWbemClassObjectPtr pStatusObjClass;
  534. IWbemClassObject* pStatusObjectInstance = NULL;
  535. if(pContext && pSrvc)
  536. {
  537. if(pSrvc)
  538. {
  539. // not checking return code, error object should be NULL on error
  540. pSrvc->GetObject(
  541. _bstr_t(JOB_OBJECT_STATUS_OBJECT),
  542. 0,
  543. pContext,
  544. &pStatusObjClass,
  545. NULL);
  546. if(pStatusObjClass)
  547. {
  548. pStatusObjClass->SpawnInstance(
  549. 0,
  550. &pStatusObjectInstance);
  551. }
  552. }
  553. }
  554. ASSERT_BREAK(pStatusObjectInstance);
  555. return pStatusObjectInstance;
  556. }
  557. void UndecorateNamesInNamedJONameList(
  558. std::vector<_bstr_t>& rgNamedJOs)
  559. {
  560. std::vector<_bstr_t> rgUndecoratedNames;
  561. CHString chstrTemp;
  562. for(long m = 0L;
  563. m < rgNamedJOs.size();
  564. m++)
  565. {
  566. UndecorateJOName(
  567. rgNamedJOs[m],
  568. chstrTemp);
  569. _bstr_t bstrtTemp((LPCWSTR)chstrTemp);
  570. rgUndecoratedNames.push_back(
  571. bstrtTemp);
  572. }
  573. // Wipe out the original vector...
  574. rgNamedJOs.clear();
  575. // Push in new vector's contents...
  576. for(m = 0L;
  577. m < rgUndecoratedNames.size();
  578. m++)
  579. {
  580. rgNamedJOs.push_back(
  581. rgUndecoratedNames[m]);
  582. }
  583. }
  584. // Takes a decorated job object name and
  585. // undecorates it. Decorated job object names
  586. // have a backslash preceeding any character
  587. // that should be uppercase once undecorated.
  588. //
  589. // Due to the way CIMOM handles backslashes,
  590. // we will get capital letters preceeded by
  591. // two, not just one, backslashes. Hence, we
  592. // must strip them both.
  593. //
  594. // According to the decoration scheme, the
  595. // following are both lower case: 'A' and 'a',
  596. // while the following are both upper case:
  597. // '\a' and '\A'.
  598. //
  599. void UndecorateJOName(
  600. LPCWSTR wstrDecoratedName,
  601. CHString& chstrUndecoratedJOName)
  602. {
  603. if(wstrDecoratedName != NULL &&
  604. *wstrDecoratedName != L'\0')
  605. {
  606. LPWSTR wstrDecoratedNameLower = NULL;
  607. try
  608. {
  609. wstrDecoratedNameLower = new WCHAR[wcslen(wstrDecoratedName)+1];
  610. if(wstrDecoratedNameLower)
  611. {
  612. wcscpy(wstrDecoratedNameLower, wstrDecoratedName);
  613. _wcslwr(wstrDecoratedNameLower);
  614. WCHAR* p3 = chstrUndecoratedJOName.GetBuffer(
  615. wcslen(wstrDecoratedNameLower) + 1);
  616. const WCHAR* p1 = wstrDecoratedNameLower;
  617. const WCHAR* p2 = p1 + 1;
  618. while(*p1 != L'\0')
  619. {
  620. if(*p1 == L'\\')
  621. {
  622. if(*p2 != NULL)
  623. {
  624. // Might have any number of
  625. // backslashes back to back,
  626. // which we will treat as
  627. // being the same as one
  628. // backslash - i.e., we will
  629. // skip over the backslash(s)
  630. // and copy over the following
  631. // letter.
  632. while(*p2 == L'\\')
  633. {
  634. p2++;
  635. };
  636. *p3 = towupper(*p2);
  637. p3++;
  638. p1 = p2 + 1;
  639. if(*p1 != L'\0')
  640. {
  641. p2 = p1 + 1;
  642. }
  643. }
  644. else
  645. {
  646. p1++;
  647. }
  648. }
  649. else
  650. {
  651. *p3 = *p1;
  652. p3++;
  653. p1 = p2;
  654. if(*p1 != L'\0')
  655. {
  656. p2 = p1 + 1;
  657. }
  658. }
  659. }
  660. *p3 = NULL;
  661. chstrUndecoratedJOName.ReleaseBuffer();
  662. delete wstrDecoratedNameLower;
  663. wstrDecoratedNameLower = NULL;
  664. }
  665. }
  666. catch(...)
  667. {
  668. if(wstrDecoratedNameLower)
  669. {
  670. delete wstrDecoratedNameLower;
  671. wstrDecoratedNameLower = NULL;
  672. }
  673. throw;
  674. }
  675. }
  676. }
  677. // Does the inverse of the above function.
  678. // However, here, we only need to put in one
  679. // backslash before each uppercase letter.
  680. // CIMOM will add the second backslash.
  681. void DecorateJOName(
  682. LPCWSTR wstrUndecoratedName,
  683. CHString& chstrDecoratedJOName)
  684. {
  685. if(wstrUndecoratedName != NULL &&
  686. *wstrUndecoratedName != L'\0')
  687. {
  688. // Worst case is that we will have
  689. // a decorated string twice as long
  690. // as the undecorated string (happens
  691. // is every character in the undecorated
  692. // string is a capital letter).
  693. WCHAR* p3 = chstrDecoratedJOName.GetBuffer(
  694. 2 * (wcslen(wstrUndecoratedName) + 1));
  695. const WCHAR* p1 = wstrUndecoratedName;
  696. while(*p1 != L'\0')
  697. {
  698. if(iswupper(*p1))
  699. {
  700. // Add in a backslash...
  701. *p3 = L'\\';
  702. p3++;
  703. // Add in the character...
  704. *p3 = *p1;
  705. p3++;
  706. p1++;
  707. }
  708. else
  709. {
  710. // Add in the character...
  711. *p3 = *p1;
  712. p3++;
  713. p1++;
  714. }
  715. }
  716. *p3 = NULL;
  717. chstrDecoratedJOName.ReleaseBuffer();
  718. // What if we had a job called Job,
  719. // and someone specified it in the
  720. // object path as "Job" instead of
  721. // "\Job"? We DON'T want to find it
  722. // in such a case, because this would
  723. // appear to not be adhering to our
  724. // own convention. Hence, we
  725. // lowercase the incoming string.
  726. chstrDecoratedJOName.MakeLower();
  727. }
  728. }
  729. // map standard API return values (defined WinError.h)
  730. // to WBEMish hresults (defined in WbemCli.h)
  731. HRESULT WinErrorToWBEMhResult(LONG error)
  732. {
  733. HRESULT hr = WBEM_E_FAILED;
  734. switch (error)
  735. {
  736. case ERROR_SUCCESS:
  737. hr = WBEM_S_NO_ERROR;
  738. break;
  739. case ERROR_ACCESS_DENIED:
  740. hr = WBEM_E_ACCESS_DENIED;
  741. break;
  742. case ERROR_NOT_ENOUGH_MEMORY:
  743. case ERROR_OUTOFMEMORY:
  744. hr = WBEM_E_OUT_OF_MEMORY;
  745. break;
  746. case ERROR_ALREADY_EXISTS:
  747. hr = WBEM_E_ALREADY_EXISTS;
  748. break;
  749. case ERROR_BAD_NETPATH:
  750. case ERROR_INVALID_DATA:
  751. case ERROR_BAD_PATHNAME:
  752. case REGDB_E_INVALIDVALUE:
  753. case ERROR_PATH_NOT_FOUND:
  754. case ERROR_FILE_NOT_FOUND:
  755. case ERROR_INVALID_PRINTER_NAME:
  756. case ERROR_BAD_USERNAME:
  757. case ERROR_NOT_READY:
  758. case ERROR_INVALID_NAME:
  759. hr = WBEM_E_NOT_FOUND;
  760. break;
  761. default:
  762. hr = WBEM_E_FAILED;
  763. }
  764. return hr;
  765. }
  766. // Copied from sid.h
  767. bool GetNameAndDomainFromPSID(
  768. PSID pSid,
  769. CHString& chstrName,
  770. CHString& chstrDomain)
  771. {
  772. bool fRet = false;
  773. // pSid should be valid...
  774. _ASSERT( (pSid != NULL) && ::IsValidSid( pSid ) );
  775. if ( (pSid != NULL) && ::IsValidSid( pSid ) )
  776. {
  777. // Initialize account name and domain name
  778. LPTSTR pszAccountName = NULL;
  779. LPTSTR pszDomainName = NULL;
  780. DWORD dwAccountNameSize = 0;
  781. DWORD dwDomainNameSize = 0;
  782. DWORD dwLastError = ERROR_SUCCESS;
  783. BOOL bResult = TRUE;
  784. try
  785. {
  786. // This call should fail
  787. SID_NAME_USE snuAccountType;
  788. bResult = ::LookupAccountSid( NULL,
  789. pSid,
  790. pszAccountName,
  791. &dwAccountNameSize,
  792. pszDomainName,
  793. &dwDomainNameSize,
  794. &snuAccountType );
  795. dwLastError = ::GetLastError();
  796. if ( ERROR_INSUFFICIENT_BUFFER == dwLastError )
  797. {
  798. // Allocate buffers
  799. if ( dwAccountNameSize != 0 )
  800. {
  801. pszAccountName = (LPTSTR) new TCHAR[ dwAccountNameSize * sizeof(TCHAR) ];
  802. }
  803. if ( dwDomainNameSize != 0 )
  804. {
  805. pszDomainName = (LPTSTR) new TCHAR[ dwDomainNameSize * sizeof(TCHAR) ];
  806. }
  807. // Make second call
  808. bResult = ::LookupAccountSid( NULL,
  809. pSid,
  810. pszAccountName,
  811. &dwAccountNameSize,
  812. pszDomainName,
  813. &dwDomainNameSize,
  814. &snuAccountType );
  815. if ( bResult == TRUE )
  816. {
  817. chstrName = pszAccountName;
  818. chstrDomain = pszDomainName;
  819. }
  820. else
  821. {
  822. // There are some accounts that do not have names, such as Logon Ids,
  823. // for example S-1-5-X-Y. So this is still legal
  824. chstrName = _T("Unknown Account");
  825. chstrDomain = _T("Unknown Domain");
  826. }
  827. if ( NULL != pszAccountName )
  828. {
  829. delete pszAccountName;
  830. pszAccountName = NULL;
  831. }
  832. if ( NULL != pszDomainName )
  833. {
  834. delete pszDomainName;
  835. pszDomainName = NULL;
  836. }
  837. fRet = true;
  838. } // If ERROR_INSUFFICIENT_BUFFER
  839. } // try
  840. catch(...)
  841. {
  842. if ( NULL != pszAccountName )
  843. {
  844. delete pszAccountName;
  845. pszAccountName = NULL;
  846. }
  847. if ( NULL != pszDomainName )
  848. {
  849. delete pszDomainName;
  850. pszDomainName = NULL;
  851. }
  852. throw;
  853. }
  854. } // IF IsValidSid
  855. return fRet;
  856. }