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.

911 lines
24 KiB

  1. // ProvInfo.cpp
  2. #include "precomp.h"
  3. #include "ProvInfo.h"
  4. #include "NCDefs.h"
  5. #include "dutils.h"
  6. #include "NCProv.h"
  7. #include "NCProvider.h"
  8. #include "QueryHelp.h" // For parsing stuff.
  9. #include <comutl.h>
  10. #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
  11. extern BOOL bIgnore;
  12. CClientInfo::~CClientInfo()
  13. {
  14. }
  15. CSinkInfo *CClientInfo::GetSinkInfo(DWORD dwID)
  16. {
  17. if (dwID == 0)
  18. return m_pProvider->m_pProv;
  19. return NULL;
  20. }
  21. HRESULT CClientInfo::PostBuffer(LPBYTE pData, DWORD dwDataSize)
  22. {
  23. CBuffer buffer(pData, dwDataSize);
  24. while (!buffer.IsEOF())
  25. {
  26. DWORD dwMsg = buffer.ReadDWORD();
  27. switch(dwMsg)
  28. {
  29. case NC_SRVMSG_CLIENT_INFO:
  30. DEBUGTRACE(
  31. (LOG_ESS,
  32. "NCProv: Got NC_SRVMSG_CLIENT_INFO\n"));
  33. if (ProcessClientInfo(&buffer))
  34. m_pProvider->m_pProv->AddClient(this);
  35. else
  36. m_pProvider->DisconnectAndClose(this);
  37. // Ignore the rest of this client's messages since the client
  38. // info message can't be accompanied by any other messages.
  39. buffer.SetEOF();
  40. break;
  41. case NC_SRVMSG_EVENT_LAYOUT:
  42. {
  43. LPBYTE pTop = buffer.m_pCurrent - sizeof(DWORD);
  44. DWORD dwSize = buffer.ReadDWORD(),
  45. dwFuncIndex = buffer.ReadDWORD(),
  46. dwSinkIndex = buffer.ReadDWORD();
  47. DEBUGTRACE(
  48. (LOG_ESS,
  49. "NCProv: Got event layout: index = %d, sink = %d\n",
  50. dwFuncIndex, dwSinkIndex));
  51. CEventInfo *pEvent = new CEventInfo;
  52. if (pEvent)
  53. {
  54. CSinkInfo *pSinkInfo = GetSinkInfo(dwSinkIndex);
  55. if (pSinkInfo && pEvent->InitFromBuffer(this, &buffer))
  56. {
  57. pEvent->SetSink(pSinkInfo->GetSink());
  58. m_mapEvents.AddNormalEventInfo(dwFuncIndex, pEvent);
  59. }
  60. else
  61. {
  62. delete pEvent;
  63. DEBUGTRACE(
  64. (LOG_ESS,
  65. "NCProv: Failed to init event layout: index = %d, sink = %d\n",
  66. dwFuncIndex, dwSinkIndex));
  67. }
  68. }
  69. // Move past the current message.
  70. buffer.m_pCurrent = pTop + dwSize;
  71. //
  72. // validation of dwSize will be done on next iteration when
  73. // retrieving dword.
  74. //
  75. break;
  76. }
  77. case NC_SRVMSG_PREPPED_EVENT:
  78. {
  79. LPBYTE pTop = buffer.m_pCurrent - sizeof(DWORD);
  80. DWORD dwSize = buffer.ReadDWORD(),
  81. dwEventIndex = buffer.ReadDWORD();
  82. CEventInfo *pEvent;
  83. pEvent = m_mapEvents.GetNormalEventInfo(dwEventIndex);
  84. DEBUGTRACE(
  85. (LOG_ESS,
  86. "NCProv: NCMSG_PREPPED_EVENT index %d\n", dwEventIndex));
  87. if (pEvent)
  88. {
  89. if (pEvent->SetPropsWithBuffer(&buffer))
  90. {
  91. #ifndef NO_INDICATE
  92. pEvent->Indicate();
  93. #else
  94. m_dwEvents++;
  95. #endif
  96. }
  97. else
  98. ERRORTRACE(
  99. (LOG_ESS,
  100. "NCProv: SetPropsWithBuffer failed, index %d",
  101. dwEventIndex));
  102. }
  103. else
  104. ERRORTRACE(
  105. (LOG_ESS,
  106. "NCProv: Didn't find function info for index %d",
  107. dwEventIndex));
  108. // Move past the current message.
  109. buffer.m_pCurrent = pTop + dwSize;
  110. //
  111. // validation of dwSize will be done on next iteration when
  112. // retrieving dword.
  113. //
  114. break;
  115. }
  116. case NC_SRVMSG_ACCESS_CHECK_REPLY:
  117. {
  118. try
  119. {
  120. NC_SRVMSG_REPLY *pReply = (NC_SRVMSG_REPLY*) buffer.m_pBuffer;
  121. CPipeClient *pClient = (CPipeClient*) pReply->dwMsgCookie;
  122. pClient->m_hrClientReply = pReply->hrRet;
  123. SetEvent(pClient->m_heventMsgReceived);
  124. }
  125. catch(...)
  126. {
  127. }
  128. buffer.SetEOF();
  129. break;
  130. }
  131. default:
  132. // Unknown message!
  133. _ASSERT(FALSE, L"NCProv: Received unknown message");
  134. // Ignore the rest of this message.
  135. buffer.SetEOF();
  136. }
  137. }
  138. return S_OK;
  139. }
  140. /////////////////////////////////////////////////////////////////////////////
  141. // CPipeClient
  142. CPipeClient::CPipeClient(CNCProvider *pProvider, HANDLE hPipe) :
  143. m_hPipe(hPipe),
  144. #ifndef NO_DECODE
  145. m_bufferRecv(MAX_MSG_SIZE)
  146. #else
  147. m_bufferRecv(500000) // We need to make this really big since we won't know
  148. // how big to make it.
  149. #endif
  150. {
  151. m_pProvider = pProvider;
  152. memset(&m_info.overlap, 0, sizeof(m_info.overlap));
  153. m_info.pInfo = this;
  154. // We'll set this to indicate we've received a message from our client.
  155. m_heventMsgReceived = CreateEvent(NULL, FALSE, FALSE, NULL);
  156. }
  157. CPipeClient::~CPipeClient()
  158. {
  159. if (m_hPipe)
  160. {
  161. DisconnectNamedPipe(m_hPipe);
  162. // Close the handle to the pipe instance.
  163. CloseHandle(m_hPipe);
  164. }
  165. if (m_heventMsgReceived)
  166. CloseHandle(m_heventMsgReceived);
  167. }
  168. BOOL CPipeClient::ProcessClientInfo(CBuffer *pBuffer)
  169. {
  170. DWORD dwBufferSize = pBuffer->ReadDWORD();
  171. //
  172. // ignore what the client says here. we've already determined our msg size.
  173. //
  174. m_bufferRecv.Reset(MAX_MSG_SIZE);
  175. return TRUE;
  176. }
  177. /////////////////////////////////////////////////////////////////////////////
  178. // CProvInfo
  179. #ifdef _UNICODE
  180. #define USTR_INSERT _T("%s")
  181. #else
  182. #define USTR_INSERT _T("%S")
  183. #endif
  184. CProvInfo::CProvInfo() : m_heventProviderReady(NULL), CSinkInfo(0)
  185. {
  186. }
  187. void GetBaseName(LPCWSTR szName, LPWSTR szBase)
  188. {
  189. // Normalize this by making sure it doesn't start with "\\.\"
  190. if (wcsstr(szName, L"\\\\.\\") == szName)
  191. StringCchCopyW( szBase, MAX_PATH*2, szName + 4);
  192. else
  193. StringCchCopyW( szBase, MAX_PATH*2, szName );
  194. _wcsupr(szBase);
  195. // Get rid of the '\' chars since we can't use it in OS object names.
  196. for (WCHAR *szCurrent = szBase; *szCurrent; szCurrent++)
  197. {
  198. if (*szCurrent == '\\')
  199. *szCurrent = '/';
  200. }
  201. }
  202. // SDDL string description:
  203. // D: Security Descriptor
  204. // A: Access allowed
  205. // 0x1f0003: EVENT_ALL_ACCESS
  206. // BA: Built-in administrators
  207. // 0x100000: SYNCHRONIZE
  208. // WD: Everyone
  209. #define ESS_EVENT_SDDL L"D:(A;;0x1f0003;;;BA)(A;;0x100000;;;WD)"
  210. BOOL CProvInfo::Init(LPCWSTR szNamespace, LPCWSTR szProvider)
  211. {
  212. WCHAR szReadyEventName[MAX_PATH * 2],
  213. szBaseNamespace[MAX_PATH * 2] = L"",
  214. szBaseProvider[MAX_PATH * 2] = L"";
  215. if (!szNamespace || !szProvider)
  216. return FALSE;
  217. DEBUGTRACE(
  218. (LOG_ESS,
  219. "NCProv: CProvInfo::Init: %S, %S\n", szNamespace, szProvider));
  220. GetBaseName(szNamespace, szBaseNamespace);
  221. GetBaseName(szProvider, szBaseProvider);
  222. // Get the ready event.
  223. StringCchPrintfW(
  224. szReadyEventName,
  225. MAX_PATH*2,
  226. OBJNAME_EVENT_READY L"%s%s",
  227. szBaseNamespace,
  228. szBaseProvider);
  229. _wcsupr(szReadyEventName);
  230. // Save these for later.
  231. m_strName = szProvider;
  232. m_strBaseName = szBaseProvider;
  233. m_strBaseNamespace = szBaseNamespace;
  234. // Create the provider ready event.
  235. m_heventProviderReady =
  236. OpenEventW(
  237. EVENT_ALL_ACCESS,
  238. FALSE,
  239. szReadyEventName);
  240. if (!m_heventProviderReady)
  241. {
  242. PSECURITY_DESCRIPTOR pSD = NULL;
  243. DWORD dwSize;
  244. if ( !ConvertStringSecurityDescriptorToSecurityDescriptorW(
  245. ESS_EVENT_SDDL, // security descriptor string
  246. SDDL_REVISION_1, // revision level
  247. &pSD, // SD
  248. &dwSize) )
  249. return FALSE;
  250. SECURITY_ATTRIBUTES sa = { sizeof(sa), pSD, FALSE };
  251. m_heventProviderReady =
  252. CreateEventW(
  253. &sa,
  254. TRUE,
  255. FALSE,
  256. szReadyEventName);
  257. if (!m_heventProviderReady)
  258. {
  259. ERRORTRACE(
  260. (LOG_ESS,
  261. "NCProv: Couldn't init provider event: err = %d", GetLastError()));
  262. }
  263. if (pSD)
  264. LocalFree((HLOCAL) pSD);
  265. }
  266. BOOL bRet;
  267. if (m_heventProviderReady)
  268. {
  269. SetEvent(m_heventProviderReady);
  270. bRet = TRUE;
  271. }
  272. else
  273. bRet = FALSE;
  274. return bRet;
  275. }
  276. CProvInfo::~CProvInfo()
  277. {
  278. if (m_heventProviderReady)
  279. {
  280. DEBUGTRACE(
  281. (LOG_ESS,
  282. "NCProv: In ~CProvInfo, resetting ready event.\n"));
  283. ResetEvent(m_heventProviderReady);
  284. CloseHandle(m_heventProviderReady);
  285. DWORD dwMsg = NC_CLIMSG_PROVIDER_UNLOADING;
  286. DEBUGTRACE(
  287. (LOG_ESS,
  288. "NCProv: Sending the NC_CLIMSG_PROVIDER_UNLOADING message.\n"));
  289. // Tell our clients that we're going away.
  290. SendMessageToClients((LPBYTE) &dwMsg, sizeof(dwMsg), FALSE);
  291. }
  292. CClientInfoListIterator info;
  293. Lock();
  294. for ( info = m_listClients.begin( );
  295. info != m_listClients.end( );
  296. ++info )
  297. {
  298. (*info)->Release();
  299. }
  300. Unlock();
  301. }
  302. DWORD WINAPI TempThreadProc(IWbemEventSink *pSink)
  303. {
  304. HRESULT hr;
  305. hr = CoInitializeEx( 0, COINIT_MULTITHREADED );
  306. if ( FAILED(hr) )
  307. {
  308. return hr;
  309. }
  310. DWORD dwRet = ERROR_SUCCESS;
  311. try
  312. {
  313. // Since we got a new client, we'll have to recheck our subscriptions
  314. pSink->SetStatus(
  315. WBEM_STATUS_REQUIREMENTS,
  316. WBEM_REQUIREMENTS_RECHECK_SUBSCRIPTIONS,
  317. NULL,
  318. NULL);
  319. }
  320. catch( CX_MemoryException )
  321. {
  322. dwRet = ERROR_OUTOFMEMORY;
  323. }
  324. pSink->Release();
  325. CoUninitialize();
  326. return dwRet;
  327. }
  328. // Functions called as clients connect/disconnect with pipe.
  329. void CProvInfo::AddClient(CClientInfo *pInfo)
  330. {
  331. DEBUGTRACE(
  332. (LOG_ESS,
  333. "NCProv: In AddClient...\n"));
  334. Lock();
  335. m_listClients.push_back(pInfo);
  336. Unlock();
  337. DWORD dwID;
  338. IWbemEventSink *pSink = pInfo->m_pProvider->m_pProv->GetSink();
  339. // Will get released by TempThreadProc.
  340. pSink->AddRef();
  341. // We have to do this stuff off a thread, because AddClient is
  342. // called from the completed read routine (which means the routine
  343. // isn't free to receive a response to a client AccessCheck query).
  344. CloseHandle(
  345. CreateThread(
  346. NULL,
  347. 0,
  348. (LPTHREAD_START_ROUTINE) TempThreadProc,
  349. pSink,
  350. 0,
  351. &dwID));
  352. }
  353. void CProvInfo::RemoveClient(CClientInfo *pInfo)
  354. {
  355. DEBUGTRACE(
  356. (LOG_ESS,
  357. "NCProv: Client removed...\n"));
  358. CClientInfoListIterator info;
  359. Lock();
  360. for (info = m_listClients.begin();
  361. info != m_listClients.end();
  362. info++)
  363. {
  364. if (*info == pInfo)
  365. {
  366. m_listClients.erase(info);
  367. //delete pInfo;
  368. pInfo->Release();
  369. break;
  370. }
  371. }
  372. Unlock();
  373. }
  374. BOOL CSinkInfo::BuildClassDescendentList(
  375. LPCWSTR szClass,
  376. CBstrList &listClasses)
  377. {
  378. if ( szClass == NULL )
  379. return FALSE;
  380. IEnumWbemClassObject *pClassEnum = NULL;
  381. // Add the class name itself to the list.
  382. listClasses.push_front(szClass);
  383. if (SUCCEEDED(m_pNamespace->CreateClassEnum(
  384. (const BSTR) szClass,
  385. WBEM_FLAG_DEEP,
  386. NULL,
  387. &pClassEnum)))
  388. {
  389. IWbemClassObject *pClass = NULL;
  390. DWORD nCount;
  391. while(SUCCEEDED(pClassEnum->Next(
  392. WBEM_INFINITE,
  393. 1,
  394. &pClass,
  395. &nCount)) && nCount == 1)
  396. {
  397. _variant_t vClass;
  398. if (SUCCEEDED(pClass->Get(
  399. L"__CLASS",
  400. 0,
  401. &vClass,
  402. NULL,
  403. NULL) && vClass.vt == VT_BSTR))
  404. {
  405. // Upper it to simplify our comparisons later.
  406. _wcsupr(V_BSTR(&vClass));
  407. listClasses.push_back(V_BSTR(&vClass));
  408. }
  409. pClass->Release();
  410. }
  411. pClassEnum->Release();
  412. }
  413. return TRUE;
  414. }
  415. HRESULT CProvInfo::SendMessageToClients(LPBYTE pData, DWORD dwSize, BOOL bGetReply)
  416. {
  417. HRESULT hr = S_OK;
  418. Lock();
  419. for (CClientInfoListIterator client = m_listClients.begin();
  420. client != m_listClients.end(); client++)
  421. {
  422. hr = (*client)->SendClientMessage(pData, dwSize, bGetReply);
  423. if (bGetReply && FAILED(hr))
  424. break;
  425. }
  426. Unlock();
  427. return hr;
  428. }
  429. // Functions called as CNCProvider:: functions are called by WMI.
  430. HRESULT STDMETHODCALLTYPE CSinkInfo::NewQuery(
  431. DWORD dwID,
  432. WBEM_WSTR szLang,
  433. WBEM_WSTR szQuery)
  434. {
  435. CQueryParser parser;
  436. HRESULT hr;
  437. _bstr_t strClass;
  438. DEBUGTRACE(
  439. (LOG_ESS,
  440. "NCProv: CSinkInfo::NewQuery: %d, %S, %S\n", dwID, szLang, szQuery));
  441. if (SUCCEEDED(hr = parser.Init(szQuery)) &&
  442. SUCCEEDED(hr = parser.GetClassName(strClass)))
  443. {
  444. CBstrList listClasses;
  445. // Make sure this is upper cased (optimizes compares).
  446. _wcsupr(strClass);
  447. BuildClassDescendentList(strClass, listClasses);
  448. Lock();
  449. BOOL bAlreadyInMap = m_mapQueries.find(dwID) != m_mapQueries.end();
  450. // Keep this in our map.
  451. if (!bAlreadyInMap)
  452. {
  453. m_mapQueries[dwID] = listClasses;
  454. //pList->assign(listClasses.begin(), listClasses.end());
  455. }
  456. Unlock();
  457. if (GetClientCount() != 0)
  458. {
  459. char buff[256];
  460. CBuffer buffer( buff, 256, CBuffer::ALIGN_DWORD_PTR);
  461. // Header stuff
  462. buffer.Write((DWORD) NC_CLIMSG_NEW_QUERY_REQ);
  463. buffer.Write(m_dwID); // Write the sink ID.
  464. buffer.Write((DWORD_PTR) 0); // No cookie needed.
  465. // New Query data
  466. buffer.Write(dwID);
  467. buffer.WriteAlignedLenString(szLang);
  468. buffer.WriteAlignedLenString(szQuery);
  469. buffer.Write( (DWORD)listClasses.size() );
  470. // Write the newly activated classes.
  471. for (CBstrListIterator i = listClasses.begin();
  472. i != listClasses.end();
  473. i++)
  474. {
  475. if (!bAlreadyInMap)
  476. AddClassRef(*i);
  477. buffer.WriteAlignedLenString((LPCWSTR) *i);
  478. }
  479. DWORD dwSize = buffer.GetUsedSize();
  480. SendMessageToClients(buffer.m_pBuffer, dwSize, FALSE);
  481. }
  482. else
  483. {
  484. // Add a ref to each class if the query wasn't already in our map.
  485. if (!bAlreadyInMap)
  486. {
  487. for (CBstrListIterator i = listClasses.begin();
  488. i != listClasses.end();
  489. i++)
  490. {
  491. AddClassRef(*i);
  492. }
  493. }
  494. }
  495. }
  496. return hr;
  497. }
  498. HRESULT STDMETHODCALLTYPE CSinkInfo::CancelQuery(DWORD dwID)
  499. {
  500. DEBUGTRACE(
  501. (LOG_ESS,
  502. "NCProv: CSinkInfo::CancelQuery: %d\n", dwID));
  503. Lock();
  504. //BOOL bProvGoingAway;
  505. CQueryToClassMapIterator query = m_mapQueries.find(dwID);
  506. // If this isn't in our map, winmgmt is doing something strange.
  507. if (query == m_mapQueries.end())
  508. {
  509. Unlock();
  510. return S_OK;
  511. }
  512. CBstrList &listClasses = (*query).second;
  513. // Remove this query's ref on its classes, and remove the classes from the
  514. // list that still have a positive ref. The classes left in the list are
  515. // the ones that we need to tell our clients to deactivate.
  516. for (CBstrListIterator i = listClasses.begin();
  517. i != listClasses.end();
  518. )
  519. {
  520. if (RemoveClassRef(*i) > 0)
  521. {
  522. i = listClasses.erase(i);
  523. if (i == listClasses.end())
  524. break;
  525. }
  526. else
  527. // We can't have this in the for loop because listClasses.erase
  528. // already moves us ahead.
  529. i++;
  530. }
  531. if (GetClientCount() != 0)
  532. {
  533. char buff[256];
  534. CBuffer buffer( buff, 256, CBuffer::ALIGN_DWORD_PTR);
  535. // Header stuff
  536. buffer.Write((DWORD) NC_CLIMSG_CANCEL_QUERY_REQ);
  537. buffer.Write(m_dwID); // Write the sink ID.
  538. buffer.Write((DWORD_PTR) 0); // No cookie needed.
  539. // Cancel Query data
  540. buffer.Write(dwID);
  541. buffer.Write( (DWORD)listClasses.size() );
  542. // Write the newly deactivated classes.
  543. for (CBstrListIterator i = listClasses.begin();
  544. i != listClasses.end();
  545. i++)
  546. {
  547. buffer.WriteAlignedLenString((LPCWSTR) *i);
  548. }
  549. DWORD dwSize = buffer.GetUsedSize();
  550. SendMessageToClients(buffer.m_pBuffer, dwSize, FALSE);
  551. }
  552. // Erase this query ID from our map.
  553. m_mapQueries.erase(query);
  554. Unlock();
  555. return S_OK;
  556. }
  557. HRESULT STDMETHODCALLTYPE CProvInfo::AccessCheck(
  558. LPCWSTR szLang,
  559. LPCWSTR szQuery,
  560. DWORD dwSidLen,
  561. LPBYTE pSid)
  562. {
  563. DEBUGTRACE(
  564. (LOG_ESS,
  565. "NCProv: CProvInfo::AccessCheck: %S, %S\n", szLang, szQuery));
  566. HRESULT hr;
  567. char szBuffer[256];
  568. CBuffer buffer(szBuffer, sizeof(szBuffer), CBuffer::ALIGN_DWORD_PTR);
  569. // Header stuff
  570. buffer.Write((DWORD) NC_CLIMSG_ACCESS_CHECK_REQ);
  571. buffer.Write((DWORD) 0); // We only send this to the main sink (for now).
  572. buffer.Write((DWORD_PTR) 0); // We'll fill this in later with the real cookie.
  573. // Access Check data
  574. buffer.WriteAlignedLenString(szLang);
  575. buffer.WriteAlignedLenString(szQuery);
  576. buffer.Write(dwSidLen);
  577. buffer.Write(pSid, dwSidLen);
  578. DWORD dwSize = buffer.GetUsedSize();
  579. hr = SendMessageToClients(buffer.m_pBuffer, dwSize, TRUE);
  580. return hr;
  581. }
  582. int CSinkInfo::AddClassRef(LPCWSTR szClass)
  583. {
  584. CBstrToIntIterator i = m_mapEnabledClasses.find(szClass);
  585. int iRet = 1;
  586. if (i == m_mapEnabledClasses.end())
  587. {
  588. iRet = 1;
  589. m_mapEnabledClasses[szClass] = 1;
  590. }
  591. else
  592. iRet = ++(*i).second;
  593. return iRet;
  594. }
  595. int CSinkInfo::RemoveClassRef(LPCWSTR szClass)
  596. {
  597. CBstrToIntIterator i = m_mapEnabledClasses.find(szClass);
  598. int iRet = 0;
  599. if (i != m_mapEnabledClasses.end())
  600. {
  601. iRet = --(*i).second;
  602. if (iRet <= 0)
  603. m_mapEnabledClasses.erase(i);
  604. }
  605. return iRet;
  606. }
  607. _COM_SMARTPTR_TYPEDEF(IWbemClassObject, __uuidof(IWbemClassObject));
  608. // retrieve the acl from the provider registration
  609. // upon success, *pDacl points to a byte array containing the dacl
  610. // will be NULL if dacl is NULL
  611. // caller's responsibility to delete memory
  612. HRESULT CProvInfo::GetProviderDacl(IWbemServices *pNamespace, BYTE** pDacl)
  613. {
  614. HRESULT hr = WBEM_E_INVALID_PROVIDER_REGISTRATION;
  615. DEBUGTRACE((LOG_ESS, "NCProv: GetProviderDacl\n"));
  616. WCHAR szObjPath[MAX_PATH * 2];
  617. StringCchPrintfW(
  618. szObjPath,
  619. MAX_PATH*2,
  620. L"__Win32Provider.Name=\"%s\"",
  621. (LPCWSTR) m_strName);
  622. IWbemClassObjectPtr pRegistration;
  623. if (SUCCEEDED(hr =
  624. pNamespace->GetObject(CWbemBSTR( szObjPath ), 0, NULL, &pRegistration, NULL)))
  625. {
  626. _variant_t vSD;
  627. if (SUCCEEDED(hr = pRegistration->Get(L"SecurityDescriptor", 0, &vSD, NULL, NULL)))
  628. {
  629. if (vSD.vt == VT_NULL)
  630. {
  631. hr = WBEM_S_NO_ERROR;
  632. *pDacl = NULL;
  633. DEBUGTRACE((LOG_ESS, "NCProv: GetProviderDacl - NULL SD\n"));
  634. }
  635. else
  636. {
  637. _ASSERT(vSD.vt == VT_BSTR, L"");
  638. PSECURITY_DESCRIPTOR pSD;
  639. if (ConvertStringSecurityDescriptorToSecurityDescriptorW(
  640. vSD.bstrVal, SDDL_REVISION_1, &pSD, NULL))
  641. {
  642. PACL pAcl;
  643. BOOL bDaclPresent, bDaclDefaulted;
  644. if (GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pAcl, &bDaclDefaulted))
  645. {
  646. if (bDaclPresent)
  647. {
  648. ACL_SIZE_INFORMATION sizeInfo;
  649. if ( GetAclInformation(pAcl, &sizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) )
  650. {
  651. if (*pDacl = new BYTE[sizeInfo.AclBytesInUse + sizeInfo.AclBytesFree])
  652. memcpy(*pDacl, pAcl, sizeInfo.AclBytesInUse);
  653. else
  654. hr = WBEM_E_OUT_OF_MEMORY;
  655. }
  656. else
  657. {
  658. ERRORTRACE((LOG_ESS, "NCProv: Failed to retrieve ACL Information\n"));
  659. hr = WBEM_E_FAILED;
  660. }
  661. }
  662. else
  663. {
  664. pDacl = NULL;
  665. hr = WBEM_S_NO_ERROR;
  666. }
  667. }
  668. else
  669. {
  670. ERRORTRACE((LOG_ESS, "NCProv: Failed to retrieve DACL\n"));
  671. hr = WBEM_E_FAILED;
  672. }
  673. LocalFree(pSD);
  674. }
  675. else
  676. {
  677. ERRORTRACE((LOG_ESS, "NCProv: Failed to convert SecurityDescriptor property\n"));
  678. hr = WBEM_E_INVALID_PARAMETER;
  679. }
  680. }
  681. }
  682. else
  683. ERRORTRACE((LOG_ESS, "NCProv: Failed to retrieve SecurityDescriptor property, 0x%08X\n", hr));
  684. }
  685. DEBUGTRACE((LOG_ESS, "NCProv: GetProviderDacl returning 0x%08X\n", hr));
  686. return hr;
  687. }
  688. #define REPLY_WAIT_TIMEOUT 5000
  689. HRESULT CPipeClient::SendClientMessage(LPVOID pData, DWORD dwSize, BOOL bGetReply)
  690. {
  691. CPipeClient **pCookie = (CPipeClient**) ((LPBYTE) pData + sizeof(DWORD) * 2);
  692. DWORD dwWritten;
  693. if (bGetReply)
  694. *pCookie = this;
  695. //
  696. // Allocate a bigger buffer to put the length in
  697. //
  698. BYTE* pBuffer = new BYTE[dwSize + sizeof(DWORD)];
  699. if(pBuffer == NULL)
  700. return WBEM_E_OUT_OF_MEMORY;
  701. *(DWORD*)pBuffer = dwSize + sizeof(DWORD);
  702. memcpy(pBuffer + sizeof(DWORD), pData, dwSize);
  703. BOOL bRes = WriteFile(m_hPipe, pBuffer, dwSize + sizeof(DWORD),
  704. &dwWritten, NULL);
  705. delete [] pBuffer;
  706. if(!bRes)
  707. return WBEM_E_FAILED;
  708. if(dwWritten != dwSize + sizeof(DWORD))
  709. return WBEM_E_FAILED;
  710. if (bGetReply)
  711. {
  712. HRESULT hr;
  713. if (WaitForSingleObject(m_heventMsgReceived, REPLY_WAIT_TIMEOUT) == 0)
  714. hr = m_hrClientReply;
  715. else
  716. hr = WBEM_E_FAILED;
  717. return hr;
  718. }
  719. else
  720. return S_OK;
  721. }