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.

1189 lines
33 KiB

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