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.

1079 lines
37 KiB

  1. #include "stdafx.h"
  2. #include "sceattch.h"
  3. #ifdef _DEBUG
  4. #define new DEBUG_NEW
  5. #undef THIS_FILE
  6. static char THIS_FILE[] = __FILE__;
  7. #endif
  8. // polstore is not threadsafe: we have multiple threads so we wrap critical sections around our calls to polstore
  9. CCriticalSection g_csPolStore;
  10. ///////////////////////////////////////////////////////////////////////////////
  11. // IComponentData implementation
  12. DEBUG_DECLARE_INSTANCE_COUNTER(CComponentDataImpl);
  13. CComponentDataImpl::CComponentDataImpl()
  14. {
  15. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  16. DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentDataImpl);
  17. // Initialize members
  18. m_pConsoleNameSpace = NULL;
  19. m_pPrshtProvider = NULL;
  20. m_pConsole = NULL;
  21. m_pRootFolderScopeItem = NULL;
  22. m_bIsDirty = FALSE;
  23. m_enumLocation = LOCATION_LOCAL;
  24. m_bDontDisplayRootFolderProperties = FALSE;
  25. m_bStorageWarningIssued = FALSE;
  26. m_bLocationStorageWarningIssued = FALSE;
  27. m_bAttemptReconnect = TRUE;
  28. m_bNeedCleanUpWSA = FALSE;
  29. m_hPolicyStore = NULL;
  30. m_pScopeRootFolder = NULL;
  31. m_pGPEInformation = NULL;
  32. m_bRsop = FALSE;
  33. m_pRSOPInformation = NULL;
  34. #ifdef _DEBUG
  35. m_cDataObjects = 0;
  36. #endif
  37. // create our initial folder
  38. CComObject <CWirelessManagerFolder>::CreateInstance(&m_pScopeRootFolder);
  39. if (m_pScopeRootFolder == NULL)
  40. {
  41. // note: we are in a seriously bad state(!)
  42. // but this is ok, because we will now 'fail to initialize' and
  43. // mmc deals ok
  44. return;
  45. }
  46. // we are storing, and later using, m_pScopeRootFolder so AddRef it
  47. m_pScopeRootFolder->AddRef();
  48. m_pScopeRootFolder->SetDataObjectType( CCT_SCOPE );
  49. m_pScopeRootFolder->Initialize (this, NULL, FOLDER_IMAGE_IDX, OPEN_FOLDER_IMAGE_IDX, FALSE);
  50. m_pScopeRootFolder->GetScopeItem()->mask |= SDI_PARAM;
  51. m_pScopeRootFolder->GetScopeItem()->lParam = (LPARAM)m_pScopeRootFolder;
  52. #ifdef _DEBUG
  53. m_pScopeRootFolder->SetComponentData(this);
  54. #endif
  55. }
  56. CComponentDataImpl::~CComponentDataImpl()
  57. {
  58. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  59. DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentDataImpl);
  60. // Some snap-in is hanging on to data objects.
  61. // If they access, it will crash!!!
  62. ASSERT(m_cDataObjects == 0);
  63. // release our interfaces
  64. SAFE_RELEASE(m_pScopeRootFolder); // triggers delete up sub folders
  65. SAFE_RELEASE(m_pConsoleNameSpace);
  66. SAFE_RELEASE(m_pConsole);
  67. SAFE_RELEASE(m_pPrshtProvider);
  68. SAFE_RELEASE(m_pGPEInformation);
  69. // cleanup winsock if we got it
  70. if (m_bNeedCleanUpWSA)
  71. WSACleanup();
  72. }
  73. STDMETHODIMP CComponentDataImpl::Initialize(LPUNKNOWN pUnknown)
  74. {
  75. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  76. HRESULT hr = E_UNEXPECTED;
  77. // TODO: clean this up and add error checking!
  78. ASSERT(pUnknown != NULL);
  79. // MMC should only call ::Initialize once!
  80. ASSERT(m_pConsoleNameSpace == NULL);
  81. pUnknown->QueryInterface(IID_IConsoleNameSpace, reinterpret_cast<void**>(&m_pConsoleNameSpace));
  82. pUnknown->QueryInterface(IID_IPropertySheetProvider, reinterpret_cast<void**>(&m_pPrshtProvider));
  83. // add the images for the scope tree
  84. CBitmap bmp16x16;
  85. LPIMAGELIST lpScopeImage;
  86. hr = pUnknown->QueryInterface(IID_IConsole, reinterpret_cast<void**>(&m_pConsole));
  87. ASSERT(hr == S_OK);
  88. hr = m_pConsole->QueryScopeImageList(&lpScopeImage);
  89. ASSERT(hr == S_OK);
  90. // Load the bitmaps from the dll
  91. bmp16x16.LoadBitmap(IDB_16x16);
  92. // Set the images
  93. lpScopeImage->ImageListSetStrip(reinterpret_cast<LONG_PTR*>(static_cast<HBITMAP>(bmp16x16)),
  94. reinterpret_cast<LONG_PTR*>(static_cast<HBITMAP>(bmp16x16)), 0, RGB(255, 0, 255));
  95. lpScopeImage->Release();
  96. // attempt to start winsock
  97. WORD wsaVersion = MAKEWORD(2,0);
  98. DWORD dwRet;
  99. dwRet = WSAStartup(wsaVersion, &wsaData);
  100. ASSERT (0 == dwRet);
  101. if (0 == dwRet)
  102. {
  103. // make sure we got a version we expected, but don't really
  104. // bother with any other failures as all this will effect is the
  105. // DNS lookup, which will just cram in a DNS name without looking
  106. // it up first... shrug.
  107. if ((LOBYTE(wsaData.wVersion) != LOBYTE(wsaVersion)) ||
  108. (HIBYTE(wsaData.wVersion) != HIBYTE(wsaVersion))) {
  109. WSACleanup();
  110. }
  111. else
  112. {
  113. m_bNeedCleanUpWSA = TRUE;
  114. }
  115. }
  116. return S_OK;
  117. }
  118. DWORD
  119. CComponentDataImpl::OpenPolicyStore(
  120. )
  121. {
  122. DWORD dwError = 0;
  123. HANDLE hPolicyStore = NULL;
  124. if (m_hPolicyStore)
  125. {
  126. WirelessClosePolicyStore(m_hPolicyStore);
  127. m_hPolicyStore = NULL;
  128. }
  129. DWORD dwProvider = WIRELESS_REGISTRY_PROVIDER;
  130. CString strLocationName;
  131. CString strDSGPOName;
  132. switch(EnumLocation())
  133. {
  134. case LOCATION_REMOTE:
  135. strLocationName = RemoteMachineName();
  136. break;
  137. case LOCATION_GLOBAL:
  138. strLocationName = RemoteMachineName();
  139. strDSGPOName = DomainGPOName();
  140. dwProvider = WIRELESS_DIRECTORY_PROVIDER;
  141. break;
  142. case LOCATION_WMI:
  143. strLocationName = RemoteMachineName(); //rsop namespace
  144. dwProvider = WIRELESS_WMI_PROVIDER;
  145. break;
  146. case LOCATION_LOCAL:
  147. default:
  148. break;
  149. }
  150. /*
  151. dwError = WirelessOpenPolicyStore(
  152. (LPWSTR) (LPCWSTR) strLocationName,
  153. dwProvider,
  154. NULL,
  155. &hPolicyStore
  156. );
  157. */
  158. dwError = WirelessGPOOpenPolicyStore(
  159. (LPWSTR) (LPCWSTR) strLocationName,
  160. dwProvider,
  161. (LPWSTR) (LPCWSTR) strDSGPOName,
  162. NULL,
  163. &hPolicyStore
  164. );
  165. if (dwError) {
  166. Destroy();
  167. return(dwError);
  168. }
  169. m_hPolicyStore = hPolicyStore;
  170. return dwError;
  171. }
  172. STDMETHODIMP CComponentDataImpl::CreateComponent(LPCOMPONENT* ppComponent)
  173. {
  174. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  175. ASSERT(ppComponent != NULL);
  176. CComObject<CComponentImpl>* pObject;
  177. CComObject<CComponentImpl>::CreateInstance(&pObject);
  178. ASSERT(pObject != NULL);
  179. // Store IComponentData
  180. pObject->SetIComponentData(this);
  181. return pObject->QueryInterface(IID_IComponent, reinterpret_cast<void**>(ppComponent));
  182. }
  183. STDMETHODIMP CComponentDataImpl::Notify(LPDATAOBJECT pDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
  184. {
  185. OPT_TRACE( _T("CComponentDataImpl::Notify pDataObject-%p\n"), pDataObject );
  186. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  187. ASSERT(m_pConsoleNameSpace != NULL);
  188. HRESULT hr = S_FALSE;
  189. // Need pDataObject unless the event is one of these:
  190. // -MMCN_PROPERTY_CHANGE because this event is generated by a
  191. // MMCPropertyChangeNotify() which does not take pDataObject as an argument.
  192. //
  193. // -MMCN_COLUMN_CLICK because it is defined as having a NULL pDataObject.
  194. if (pDataObject == NULL && MMCN_PROPERTY_CHANGE != event && MMCN_COLUMN_CLICK != event)
  195. {
  196. TRACE(_T("CComponentDataImpl::Notify ERROR(?) called with pDataObject==NULL on event-%i\n"), event);
  197. // Is this an event for which there should be no IDataObj? If so, add it to
  198. // the if statement above.
  199. ASSERT( FALSE );
  200. return E_UNEXPECTED;
  201. }
  202. switch(event)
  203. {
  204. case MMCN_REMOVE_CHILDREN:
  205. {
  206. //
  207. // In RSoP, we may get called to refresh the scope pane when the query
  208. // is re-executed -- if this happens, current nodes will be removed and
  209. // we must reset all of our cached information. We reset the relevant
  210. // information below
  211. //
  212. if ( ((HSCOPEITEM)arg != NULL) && m_bRsop && (m_pRSOPInformation != NULL) )
  213. {
  214. m_pRSOPInformation->Release();
  215. m_pRSOPInformation = NULL;
  216. }
  217. break;
  218. }
  219. case MMCN_EXPANDSYNC:
  220. {
  221. //this event is not supported
  222. return S_FALSE;
  223. break;
  224. }
  225. case MMCN_EXPAND:
  226. {
  227. if (pDataObject)
  228. {
  229. // if we are an extension snap-in, IDataObject is from the parent snap-in and so it
  230. // won't know about the IID_IWirelessSnapInDataObject interface. Otherwise we created
  231. // the root now (IDataObject) so it does respond to the query, and we don't want
  232. // to do our extension snapin stuff
  233. CComQIPtr <IWirelessSnapInDataObject, &IID_IWirelessSnapInDataObject> spData(pDataObject);
  234. if ( spData )
  235. {
  236. //should be internal format, as the external snapin does not know about our format
  237. return spData->Notify( event, arg, param, TRUE, m_pConsole, NULL );
  238. }
  239. else
  240. {
  241. //we may be in extension sanpin now
  242. UINT cfModeType = RegisterClipboardFormat(CCF_SCE_RSOP_UNKNOWN);
  243. STGMEDIUM ObjMediumMode = { TYMED_HGLOBAL, NULL };
  244. FORMATETC fmteMode = {(CLIPFORMAT)cfModeType, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  245. ObjMediumMode.hGlobal = GlobalAlloc(GMEM_SHARE|GMEM_ZEROINIT, sizeof(DWORD*));
  246. if (NULL == ObjMediumMode.hGlobal)
  247. {
  248. DWORD dwError = GetLastError();
  249. hr = HRESULT_FROM_WIN32(dwError);
  250. return hr;
  251. }
  252. hr = pDataObject->GetDataHere (&fmteMode, &ObjMediumMode);
  253. LPUNKNOWN pUnkRSOP = *((LPUNKNOWN*) (ObjMediumMode.hGlobal));
  254. ASSERT (pUnkRSOP);
  255. if(pUnkRSOP) {
  256. if ( m_pRSOPInformation )
  257. {
  258. m_pRSOPInformation->Release();
  259. m_pRSOPInformation = NULL;
  260. }
  261. hr = pUnkRSOP->QueryInterface(IID_IRSOPInformation, (LPVOID *)&m_pRSOPInformation);
  262. pUnkRSOP->Release();
  263. }
  264. GlobalFree(ObjMediumMode.hGlobal);
  265. if(m_pRSOPInformation)
  266. {
  267. m_bRsop = TRUE;
  268. }
  269. if(m_pRSOPInformation)
  270. {
  271. ////RSOP case
  272. UINT cfModeType = RegisterClipboardFormat(CCF_SCE_MODE_TYPE);
  273. STGMEDIUM ObjMediumMode = { TYMED_HGLOBAL, NULL };
  274. FORMATETC fmteMode = {(CLIPFORMAT)cfModeType, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  275. ObjMediumMode.hGlobal = GlobalAlloc(GMEM_SHARE|GMEM_ZEROINIT, sizeof(DWORD*));
  276. if (NULL == ObjMediumMode.hGlobal)
  277. {
  278. DWORD dwError = GetLastError();
  279. m_pRSOPInformation->Release();
  280. m_pRSOPInformation = NULL;
  281. return HRESULT_FROM_WIN32(dwError);
  282. }
  283. DWORD dwSCEMode = SCE_MODE_UNKNOWN;
  284. hr = pDataObject->GetDataHere (&fmteMode, &ObjMediumMode);
  285. dwSCEMode = *(DWORD*)(ObjMediumMode.hGlobal);
  286. GlobalFree(ObjMediumMode.hGlobal);
  287. //Bug296532, Wireless shouldn't show up as an extention unless we are in
  288. // the following SCE modes
  289. if (!
  290. (SCE_MODE_LOCAL_COMPUTER == dwSCEMode ||
  291. SCE_MODE_DOMAIN_COMPUTER == dwSCEMode ||
  292. SCE_MODE_OU_COMPUTER == dwSCEMode ||
  293. SCE_MODE_REMOTE_COMPUTER == dwSCEMode ||
  294. SCE_MODE_RSOP_COMPUTER == dwSCEMode)
  295. )
  296. {
  297. m_pRSOPInformation->Release();
  298. m_pRSOPInformation = NULL;
  299. hr = S_FALSE;
  300. return hr;
  301. }
  302. const int cchMaxLength = 512;
  303. WCHAR szNameSpace[cchMaxLength];
  304. if (m_pRSOPInformation->GetNamespace(GPO_SECTION_MACHINE, szNameSpace, cchMaxLength) == S_OK)
  305. {
  306. RemoteMachineName(szNameSpace);
  307. }
  308. else
  309. {
  310. RemoteMachineName (L"");
  311. }
  312. EnumLocation (LOCATION_WMI);
  313. m_pScopeRootFolder->SetExtScopeObject( m_pScopeRootFolder );
  314. } //if(m_pRSOPInformation)
  315. else
  316. {
  317. // The GPT knows where we are loaded from (DS, Local, Remote)
  318. // and will provide that information via its interface
  319. UINT cfModeType = RegisterClipboardFormat(CCF_SCE_GPT_UNKNOWN);
  320. STGMEDIUM ObjMediumMode = { TYMED_HGLOBAL, NULL };
  321. FORMATETC fmteMode = {(CLIPFORMAT)cfModeType, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  322. ObjMediumMode.hGlobal = GlobalAlloc(GMEM_SHARE|GMEM_ZEROINIT, sizeof(DWORD*));
  323. if (NULL == ObjMediumMode.hGlobal)
  324. {
  325. DWORD dwError = GetLastError();
  326. hr = HRESULT_FROM_WIN32(dwError);
  327. return hr;
  328. }
  329. hr = pDataObject->GetDataHere (&fmteMode, &ObjMediumMode);
  330. // yes, CCF_SCE_GPT_UNKNOWN implies a GPT unknown, but what we actually
  331. // get is an unknown for a GPE!!
  332. LPUNKNOWN pUnkGPE = *((LPUNKNOWN*) (ObjMediumMode.hGlobal));
  333. ASSERT (pUnkGPE);
  334. // if we didn't get an IUNKNOWN something is serously wrong
  335. if (pUnkGPE == NULL)
  336. {
  337. GlobalFree(ObjMediumMode.hGlobal);
  338. hr = E_FAIL;
  339. return hr;
  340. }
  341. // need to look for the GPE interface
  342. if ( m_pGPEInformation )
  343. {
  344. m_pGPEInformation->Release();
  345. m_pGPEInformation = NULL;
  346. }
  347. hr = pUnkGPE->QueryInterface(cGPEguid, (void**) &m_pGPEInformation);
  348. // this is an alternative way of doing that QI if we wanted, I like the
  349. // more direct approach
  350. // CComQIPtr <IGPTInformation, &cGPTguid> spGPTInformation(pUnkGPT);
  351. // since calling GetDataHere is equivalent (so to speak) to a CreateInstance call
  352. // we need to release the IUnknown
  353. pUnkGPE->Release();
  354. GlobalFree(ObjMediumMode.hGlobal);
  355. // check to see if we got it
  356. if (m_pGPEInformation != NULL)
  357. {
  358. UINT cfModeType = RegisterClipboardFormat(CCF_SCE_MODE_TYPE);
  359. STGMEDIUM ObjMediumMode = { TYMED_HGLOBAL, NULL };
  360. FORMATETC fmteMode = {(CLIPFORMAT)cfModeType, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  361. ObjMediumMode.hGlobal = GlobalAlloc(GMEM_SHARE|GMEM_ZEROINIT, sizeof(DWORD*));
  362. if (NULL == ObjMediumMode.hGlobal)
  363. {
  364. DWORD dwError = GetLastError();
  365. return HRESULT_FROM_WIN32(dwError);
  366. }
  367. DWORD dwSCEMode = SCE_MODE_UNKNOWN;
  368. hr = pDataObject->GetDataHere (&fmteMode, &ObjMediumMode);
  369. dwSCEMode = *(DWORD*)(ObjMediumMode.hGlobal);
  370. GlobalFree(ObjMediumMode.hGlobal);
  371. //Bug296532, Wireless shouldn't show up as an extention unless we are in
  372. // the following SCE modes
  373. if (!
  374. (SCE_MODE_LOCAL_COMPUTER == dwSCEMode ||
  375. SCE_MODE_DOMAIN_COMPUTER == dwSCEMode ||
  376. SCE_MODE_OU_COMPUTER == dwSCEMode ||
  377. SCE_MODE_REMOTE_COMPUTER == dwSCEMode ||
  378. SCE_MODE_RSOP_COMPUTER == dwSCEMode)
  379. )
  380. {
  381. m_pGPEInformation->Release();
  382. m_pGPEInformation = NULL;
  383. return S_FALSE;
  384. }
  385. CString strName;
  386. m_pGPEInformation->GetName (strName.GetBuffer(MAX_PATH), MAX_PATH);
  387. strName.ReleaseBuffer (-1);
  388. GROUP_POLICY_OBJECT_TYPE gpoType;
  389. m_pGPEInformation->GetType (&gpoType);
  390. switch (gpoType)
  391. {
  392. case GPOTypeLocal:
  393. {
  394. // redirect to local machine
  395. RemoteMachineName (L"");
  396. EnumLocation (LOCATION_LOCAL);
  397. hr = S_FALSE;
  398. return(hr);
  399. break;
  400. }
  401. case GPOTypeRemote:
  402. // redirect to the GetName machine
  403. RemoteMachineName (strName);
  404. EnumLocation (LOCATION_REMOTE);
  405. break;
  406. case GPOTypeDS:
  407. {
  408. hr = GetDomainDnsName(strName);
  409. if ( FAILED(hr) )
  410. return hr;
  411. RemoteMachineName (strName);
  412. hr = GetDomainGPOName(strName);
  413. if ( FAILED(hr) )
  414. return hr;
  415. DomainGPOName(strName);
  416. EnumLocation (LOCATION_GLOBAL);
  417. break;
  418. }
  419. }//switch (gpoType)
  420. // we save the m_pGPEInformation interface for later use instead of:
  421. // pGPEInformation->Release();
  422. }//if (m_pGPEInformation != NULL)
  423. // If we made it here we were loaded as an extension snap-in. Only do this once.
  424. m_pScopeRootFolder->SetExtScopeObject( m_pScopeRootFolder );
  425. } //else if(m_pRSOPInformation)
  426. }
  427. } //if (pDataObject)
  428. break;
  429. } //case MMCN_EXPAND
  430. default:
  431. break;
  432. }//switch
  433. CComQIPtr<IWirelessSnapInDataObject, &IID_IWirelessSnapInDataObject> spData(pDataObject);
  434. if (spData == NULL)
  435. {
  436. // Either we are loaded as an extension snapin (so it doesn't know about our
  437. // internal interface), or pDataObject is NULL. In either case, we can pass
  438. // the event on.
  439. LPUNKNOWN pUnkScope;
  440. if (NULL != m_pScopeRootFolder->GetExtScopeObject())
  441. {
  442. // We are loaded as an extension snapin, let the designated extension
  443. // scope object handle the event.
  444. pUnkScope = reinterpret_cast<LPUNKNOWN>(m_pScopeRootFolder->GetExtScopeObject());
  445. }
  446. else
  447. {
  448. // Let our static scope object handle the event.
  449. pUnkScope = reinterpret_cast<LPUNKNOWN>(m_pScopeRootFolder);
  450. }
  451. // Pass on event
  452. ASSERT( NULL != pUnkScope );
  453. if (NULL != pUnkScope)
  454. {
  455. CComQIPtr<IWirelessSnapInDataObject, &IID_IWirelessSnapInDataObject>
  456. spExtData( pUnkScope );
  457. if (spExtData != NULL)
  458. {
  459. return spExtData->Notify( event, arg, param, TRUE, m_pConsole, NULL );
  460. }
  461. ASSERT( FALSE );
  462. }
  463. TRACE(_T("CComponentDataImpl::Notify - QI for IWirelessSnapInDataObject failed\n"));
  464. ASSERT( FALSE );
  465. hr = E_UNEXPECTED;
  466. }
  467. else
  468. {
  469. return spData->Notify( event, arg, param, TRUE, m_pConsole, NULL );
  470. }
  471. return hr;
  472. }
  473. HRESULT CComponentDataImpl::GetDomainGPOName(CString & strName)
  474. {
  475. WCHAR szADsPathName[MAX_PATH];
  476. HRESULT hr = S_OK;
  477. CString szName;
  478. CString szPrefixName;
  479. hr = m_pGPEInformation->GetDSPath(
  480. GPO_SECTION_MACHINE,
  481. szADsPathName,
  482. MAX_PATH
  483. );
  484. //Truncate the LDAP:// from the string
  485. szName = _wcsninc( szADsPathName, 7);
  486. //szPrefixName = L"CN=Windows,CN=Microsoft,";
  487. //strName = szPrefixName+szName;
  488. strName = szName;
  489. return hr;
  490. }
  491. HRESULT CComponentDataImpl::GetDomainDnsName(CString & strName)
  492. {
  493. WCHAR szADsPathName[MAX_PATH];
  494. WCHAR *szDnsName = NULL;
  495. LPWSTR pszDirectoryName = NULL;
  496. ULONG ulSize = 0;
  497. HRESULT hr = S_OK;
  498. m_pGPEInformation->GetDSPath(
  499. GPO_SECTION_MACHINE,
  500. szADsPathName,
  501. MAX_PATH
  502. );
  503. pszDirectoryName = wcsstr(szADsPathName, L"DC");
  504. TranslateName (
  505. pszDirectoryName , // object name
  506. NameFullyQualifiedDN, // name format
  507. NameCanonical, // new name format
  508. szDnsName, // name buffer
  509. &ulSize // buffer size
  510. );
  511. szDnsName = (WCHAR *) LocalAlloc(LMEM_ZEROINIT, sizeof(TCHAR)* (ulSize+1));
  512. if ( szDnsName == NULL )
  513. {
  514. hr = E_OUTOFMEMORY;
  515. return hr;
  516. }
  517. if ( !TranslateName (
  518. pszDirectoryName , // object name
  519. NameFullyQualifiedDN, // name format
  520. NameCanonical, // new name format
  521. szDnsName, // name buffer
  522. &ulSize // buffer size
  523. ))
  524. {
  525. hr = HRESULT_FROM_WIN32(GetLastError());
  526. LocalFree( szDnsName );
  527. return hr;
  528. }
  529. if ( szDnsName[lstrlen(szDnsName) -1 ] == _T('/') )
  530. {
  531. szDnsName[lstrlen(szDnsName) -1 ] = _T('\0');
  532. }
  533. strName = szDnsName;
  534. LocalFree( szDnsName );
  535. return hr;
  536. }
  537. STDMETHODIMP CComponentDataImpl::Destroy()
  538. {
  539. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  540. // since they are shutting us down, we use our static node
  541. // Use our member data object to handle call.
  542. IUnknown* pUnk = (IUnknown*) NULL;
  543. HRESULT hr = GetStaticScopeObject()->QueryInterface(IID_IUnknown, (void**)&pUnk);
  544. ASSERT (hr == S_OK);
  545. if (NULL == pUnk)
  546. return E_UNEXPECTED;
  547. CComQIPtr<IWirelessSnapInDataObject, &IID_IWirelessSnapInDataObject> spData( pUnk );
  548. if (spData == NULL)
  549. {
  550. TRACE(_T("CComponentDataImpl::GetDisplayInfo QI for IWirelessSnapInDataObject FAILED\n"));
  551. return E_UNEXPECTED;
  552. }
  553. spData->Destroy ();
  554. // Used our member data object to handle call, release it.
  555. pUnk->Release();
  556. return hr;
  557. }
  558. STDMETHODIMP CComponentDataImpl::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject)
  559. {
  560. OPT_TRACE( _T("CComponentDataImpl::QueryDataObject this-%p, cookie-%p\n"), this, cookie );
  561. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  562. // return failure since we weren't able to get up and running
  563. // causes mmc to report 'snapin failed to initialize'
  564. if (m_pScopeRootFolder == NULL)
  565. {
  566. return E_UNEXPECTED;
  567. }
  568. ASSERT( m_pScopeRootFolder->NodeName().GetLength() ); // we should know our own display name
  569. if (NULL == ppDataObject)
  570. {
  571. TRACE(_T("CComponentDataImpl::QueryDataObject - ERROR ppDataObject is NULL\n"));
  572. return E_UNEXPECTED;
  573. }
  574. *ppDataObject = NULL;
  575. #ifdef _DEBUG
  576. HRESULT hr;
  577. if (cookie == NULL)
  578. {
  579. hr = m_pScopeRootFolder->QueryInterface( IID_IDataObject, (void**)(ppDataObject) );
  580. OPT_TRACE(_T(" QI on m_pScopeRootFolder-%p -> pDataObj-%p\n"), m_pScopeRootFolder, *ppDataObject);
  581. ASSERT(hr == S_OK);
  582. ASSERT( NULL != *ppDataObject );
  583. return hr;
  584. }
  585. IUnknown* pUnk = (IUnknown*) cookie;
  586. hr = pUnk->QueryInterface( IID_IDataObject, (void**)(ppDataObject) );
  587. OPT_TRACE(_T(" QI on cookie-%p -> pDataObj-%p\n"), cookie, *ppDataObject);
  588. ASSERT(hr == S_OK);
  589. return hr;
  590. #else
  591. if (cookie == NULL)
  592. return m_pScopeRootFolder->QueryInterface( IID_IDataObject, (void**)(ppDataObject) );
  593. IUnknown* pUnk = (IUnknown*) cookie;
  594. return pUnk->QueryInterface( IID_IDataObject, (void**)(ppDataObject) );
  595. #endif
  596. }
  597. ///////////////////////////////////////////////////////////////////////////////
  598. //// IPersistStream interface members
  599. STDMETHODIMP CComponentDataImpl::GetClassID(CLSID *pClassID)
  600. {
  601. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  602. ASSERT (0);
  603. // TODO: CComponentDataImpl::GetClassID and CComponentImpl::GetClassID are identical (?)
  604. ASSERT(pClassID != NULL);
  605. // Copy the CLSID for this snapin
  606. *pClassID = CLSID_Snapin;
  607. return S_OK;
  608. }
  609. STDMETHODIMP CComponentDataImpl::IsDirty()
  610. {
  611. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  612. // return dirty state
  613. return InternalIsDirty() ? S_OK : S_FALSE;
  614. }
  615. STDMETHODIMP CComponentDataImpl::Load(IStream *pStm)
  616. {
  617. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  618. unsigned long read;
  619. // NOTE: it looks like there is a strange case were the MMC will
  620. // attempt to load the properties for the root node a second (or more)
  621. // time. To do so right click on an item in the results pane and then
  622. // double click on the empty space in the results pane
  623. m_bDontDisplayRootFolderProperties = TRUE;
  624. // read the location enum
  625. HRESULT hr = pStm->Read (&m_enumLocation, sizeof (enum STORAGE_LOCATION), &read);
  626. if ((hr != S_OK) || (read != sizeof (enum STORAGE_LOCATION)))
  627. {
  628. // for debug purposes, we should assert here
  629. ASSERT (0);
  630. // make sure we have a valid (even if incorrect) value
  631. m_enumLocation = LOCATION_LOCAL;
  632. // TODO: look into better return value(s)
  633. return E_UNEXPECTED;
  634. }
  635. // read the size of the location string
  636. unsigned int iStrLen;
  637. hr = pStm->Read (&iStrLen, sizeof (unsigned int), &read);
  638. if ((hr == S_OK) && (read == sizeof (unsigned int)))
  639. {
  640. // read the string itself
  641. LPCTSTR szStr = (LPCTSTR) malloc (iStrLen);
  642. hr = pStm->Read ((void*) szStr, iStrLen, &read);
  643. if ((hr == S_OK) && (read == iStrLen))
  644. {
  645. m_sRemoteMachineName = szStr;
  646. free ((void*)szStr);
  647. // we don't want to allow the location page to come up
  648. if (m_pScopeRootFolder)
  649. {
  650. m_pScopeRootFolder->LocationPageDisplayEnable(FALSE);
  651. }
  652. return S_OK;
  653. }
  654. // need to delete here as well
  655. free ((void*)szStr);
  656. }
  657. // we only get to here in an error situation
  658. ASSERT (0);
  659. // make sure we have a valid (even if incorrect) value
  660. m_enumLocation = LOCATION_GLOBAL;
  661. m_sRemoteMachineName = _T("");
  662. // TODO: look into better return value(s)
  663. return E_UNEXPECTED;
  664. }
  665. STDMETHODIMP CComponentDataImpl::Save(IStream *pStm, BOOL fClearDirty)
  666. {
  667. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  668. unsigned long written;
  669. // save the storage location
  670. HRESULT hr = pStm->Write(&m_enumLocation, sizeof (enum STORAGE_LOCATION), &written);
  671. if ((hr != S_OK) || (written != sizeof (enum STORAGE_LOCATION)))
  672. {
  673. ASSERT (0);
  674. // TODO: look into better return value(s)
  675. return E_UNEXPECTED;
  676. }
  677. // save the length of the location string
  678. unsigned int iStrLen = m_sRemoteMachineName.GetLength()*sizeof(wchar_t)+sizeof(wchar_t);
  679. hr = pStm->Write(&iStrLen, sizeof (unsigned int), &written);
  680. if ((hr != S_OK) || (written != sizeof (unsigned int)))
  681. {
  682. ASSERT (0);
  683. // TODO: look into better return value(s)
  684. return E_UNEXPECTED;
  685. }
  686. // save the location string itself
  687. hr = pStm->Write((LPCTSTR) m_sRemoteMachineName, iStrLen, &written);
  688. if ((hr != S_OK) || (written != iStrLen))
  689. {
  690. ASSERT (0);
  691. // TODO: look into better return value(s)
  692. return E_UNEXPECTED;
  693. }
  694. // if fClearDirty we clear it out
  695. if (fClearDirty == TRUE)
  696. {
  697. ClearDirty();
  698. }
  699. return S_OK;
  700. }
  701. STDMETHODIMP CComponentDataImpl::GetSizeMax(ULARGE_INTEGER *pcbSize)
  702. {
  703. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  704. // Set the size of the string to be saved
  705. ULISet32(*pcbSize, sizeof (enum STORAGE_LOCATION));
  706. return S_OK;
  707. }
  708. STDMETHODIMP CComponentDataImpl::GetDisplayInfo(SCOPEDATAITEM* pScopeDataItem)
  709. {
  710. if (pScopeDataItem == NULL)
  711. {
  712. TRACE(_T("CComponentDataImpl::GetDisplayInfo called with pScopeDataItem == NULL\n"));
  713. return E_UNEXPECTED;
  714. }
  715. IUnknown* pUnk = (IUnknown*) pScopeDataItem->lParam;
  716. if (pUnk == NULL)
  717. {
  718. // Use our member data object to handle call.
  719. HRESULT hr = GetStaticScopeObject()->QueryInterface(IID_IUnknown, (void**)&pUnk);
  720. ASSERT (hr == S_OK);
  721. if (NULL == pUnk)
  722. return E_UNEXPECTED;
  723. }
  724. CComQIPtr<IWirelessSnapInDataObject, &IID_IWirelessSnapInDataObject> spData( pUnk );
  725. if (spData == NULL)
  726. {
  727. TRACE(_T("CComponentDataImpl::GetDisplayInfo QI for IWirelessSnapInDataObject FAILED\n"));
  728. return E_UNEXPECTED;
  729. }
  730. HRESULT hr = spData->GetScopeDisplayInfo( pScopeDataItem );
  731. if (NULL == pScopeDataItem->lParam)
  732. // Used our member data object to handle call, release it.
  733. pUnk->Release();
  734. return hr;
  735. }
  736. STDMETHODIMP CComponentDataImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
  737. {
  738. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  739. ASSERT (0);
  740. return E_UNEXPECTED;
  741. // NOTE: to implement look to CComponentImpl::CompareObjects
  742. }
  743. /////////////////////////////////////////////////////////////////////////////
  744. // IExtendPropertySheet Implementation
  745. STDMETHODIMP CComponentDataImpl::QueryPagesFor(LPDATAOBJECT lpDataObject)
  746. {
  747. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  748. if (lpDataObject == NULL)
  749. {
  750. TRACE(_T("CComponentDataImpl::QueryPagesFor called with lpDataObject == NULL\n"));
  751. return E_UNEXPECTED;
  752. }
  753. CComQIPtr <IWirelessSnapInDataObject, &IID_IWirelessSnapInDataObject> spData(lpDataObject);
  754. if (spData == NULL)
  755. {
  756. TRACE(_T("CComponentDataImpl::QueryPagesFor - QI for IWirelessSnapInDataObject FAILED\n"));
  757. ASSERT( FALSE );
  758. return E_UNEXPECTED;
  759. }
  760. return spData->QueryPagesFor();
  761. }
  762. STDMETHODIMP CComponentDataImpl::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpDataObject)
  763. {
  764. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  765. if (lpDataObject == NULL)
  766. {
  767. TRACE(_T("CComponentDataImpl::CreatePropertyPages called with lpDataObject==NULL\n"));
  768. return E_UNEXPECTED;
  769. }
  770. CComQIPtr <IWirelessSnapInDataObject, &IID_IWirelessSnapInDataObject> spData(lpDataObject);
  771. if (spData == NULL)
  772. {
  773. TRACE(_T("CComponentDataImpl::CreatePropertyPages QI for IWirelessSnapInDataObject FAILED\n"));
  774. return E_UNEXPECTED;
  775. }
  776. return spData->CreatePropertyPages( lpProvider, handle );
  777. }
  778. #ifdef WIZ97WIZARDS
  779. STDMETHODIMP CComponentDataImpl::GetWatermarks (LPDATAOBJECT lpDataObject, HBITMAP* lphWatermark, HBITMAP* lphHeader, HPALETTE* lphPalette, BOOL* bStretch)
  780. {
  781. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  782. CBitmap* pbmpWatermark = new CBitmap;
  783. CBitmap* pbmpHeader = new CBitmap;
  784. if ((pbmpWatermark == NULL) || (pbmpHeader == NULL))
  785. return E_UNEXPECTED;
  786. // Load the bitmaps
  787. pbmpWatermark->LoadBitmap(IDB_WPOLICY);
  788. pbmpHeader->LoadBitmap(IDB_BPOLICY);
  789. *lphWatermark = static_cast<HBITMAP>(*pbmpWatermark);
  790. *lphHeader = static_cast<HBITMAP>(*pbmpHeader);
  791. *lphPalette = NULL;
  792. *bStretch = TRUE;
  793. return S_OK;
  794. }
  795. #endif
  796. STDMETHODIMP CComponentDataImpl::AddMenuItems(LPDATAOBJECT lpDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, long *pInsertionAllowed)
  797. {
  798. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  799. if (lpDataObject == NULL)
  800. {
  801. TRACE(_T("CComponentDataImpl::AddMenuItems called with piDataObject==NULL\n"));
  802. return E_UNEXPECTED;
  803. }
  804. CComQIPtr<IWirelessSnapInDataObject, &IID_IWirelessSnapInDataObject> spData(lpDataObject);
  805. if (spData == NULL)
  806. {
  807. TRACE(_T("CComponentDataImpl::AddMenuItems QI for IWirelessSnapInDataObject FAILED\n"));
  808. return E_UNEXPECTED;
  809. }
  810. return spData->AddMenuItems( pContextMenuCallback, pInsertionAllowed );
  811. }
  812. STDMETHODIMP CComponentDataImpl::Command(long nCommandID, LPDATAOBJECT lpDataObject)
  813. {
  814. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  815. ASSERT( NULL != m_pConsoleNameSpace );
  816. if (lpDataObject == NULL)
  817. {
  818. TRACE(_T("CComponentDataImpl::Command called with lpDataObject==NULL\n"));
  819. return E_UNEXPECTED;
  820. }
  821. CComQIPtr<IWirelessSnapInDataObject, &IID_IWirelessSnapInDataObject> spData(lpDataObject);
  822. if (spData == NULL)
  823. {
  824. TRACE(_T("CComponentDataImpl::Command QI for IWirelessSnapInDataObject FAILED\n"));
  825. return E_UNEXPECTED;
  826. }
  827. return spData->Command( nCommandID, m_pConsoleNameSpace );
  828. }
  829. STDMETHODIMP CComponentDataImpl::GetHelpTopic (LPOLESTR* lpCompiledHelpFile)
  830. {
  831. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  832. if (lpCompiledHelpFile == NULL)
  833. return E_POINTER;
  834. // need to form a complete path to the .chm file
  835. CString s, s2;
  836. s.LoadString(IDS_HELPCONTENTSFILE);
  837. DWORD dw = ExpandEnvironmentStrings (s, s2.GetBuffer (512), 512);
  838. s2.ReleaseBuffer (-1);
  839. if ((dw == 0) || (dw > 512))
  840. {
  841. return E_UNEXPECTED;
  842. }
  843. *lpCompiledHelpFile = reinterpret_cast<LPOLESTR>
  844. (CoTaskMemAlloc((s2.GetLength() + 1)* sizeof(wchar_t)));
  845. if (*lpCompiledHelpFile == NULL)
  846. return E_OUTOFMEMORY;
  847. USES_CONVERSION;
  848. wcscpy(*lpCompiledHelpFile, T2OLE((LPTSTR)(LPCTSTR)s2));
  849. return S_OK;
  850. }
  851. void CComponentDataImpl::EnumLocation (enum STORAGE_LOCATION enumLocation)
  852. {
  853. SetDirty();
  854. m_enumLocation = enumLocation;
  855. // our enumlocation changed, so we should change the nodename of our
  856. // manager folder
  857. if (m_pScopeRootFolder)
  858. {
  859. m_pScopeRootFolder->SetNodeNameByLocation();
  860. }
  861. }
  862. ///////////////////////////////////////////////////////////////////////////////
  863. // class CComponentDataPrimaryImpl : IComponentData implementation
  864. CComponentDataPrimaryImpl::CComponentDataPrimaryImpl() : CComponentDataImpl()
  865. {
  866. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  867. ASSERT( NULL != GetStaticScopeObject() );
  868. // Store the coclass with the data object
  869. // GetStaticScopeObject()->INTERNALclsid( GetCoClassID() );
  870. GetStaticScopeObject()->clsid (GetCoClassID());
  871. }