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.

1343 lines
28 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. inetmgr.cpp
  5. Abstract:
  6. Main program object
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Functions Exported:
  12. Revision History:
  13. --*/
  14. //
  15. // Include files
  16. //
  17. #include "stdafx.h"
  18. #include "inetmgr.h"
  19. #include "constr.h"
  20. #include <dos.h>
  21. #include <direct.h>
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #endif
  26. //
  27. // Default HTML help topics file name
  28. //
  29. #define DEFAULT_HTML _T("htmldocs\\inetdocs.htm")
  30. LPOLESTR
  31. CoTaskDupString(
  32. IN LPCOLESTR szString
  33. )
  34. /*++
  35. Routine Description:
  36. Helper function to duplicate a OLESTR
  37. Arguments:
  38. LPOLESTR szString : Source string
  39. Return Value:
  40. Pointer to the new string or NULL
  41. --*/
  42. {
  43. OLECHAR * lpString = (OLECHAR *)CoTaskMemAlloc(
  44. sizeof(OLECHAR)*(lstrlen(szString) + 1)
  45. );
  46. if (lpString != NULL)
  47. {
  48. lstrcpy(lpString, szString);
  49. }
  50. return lpString;
  51. }
  52. HRESULT
  53. BuildResURL(
  54. OUT CString & str,
  55. IN HINSTANCE hSourceInstance
  56. )
  57. /*++
  58. Routine Description:
  59. Helper function to generate "res://" type string
  60. Arguments:
  61. CString & str : Returns res:// string
  62. HINSTANCE hSourceInstance : Source instance,
  63. : or -1 for current module
  64. : or NULL for calling app (MMC)
  65. Return Value:
  66. HRESULT
  67. --*/
  68. {
  69. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  70. CError err;
  71. TCHAR atchModuleFileName[MAX_PATH + 1];
  72. int cch = ::GetModuleFileName(
  73. (hSourceInstance == (HINSTANCE) - 1)
  74. ? ::AfxGetInstanceHandle()
  75. : hSourceInstance,
  76. atchModuleFileName,
  77. sizeof(atchModuleFileName) / sizeof(OLECHAR)
  78. );
  79. if (!cch)
  80. {
  81. err.GetLastWinError();
  82. ASSERT(FALSE);
  83. return err;
  84. }
  85. str = _T("res://");
  86. str += atchModuleFileName;
  87. return err;
  88. }
  89. //
  90. // Static Initialization
  91. //
  92. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  93. LPCTSTR CServiceInfo::s_cszSupcfg = _T("::SUPCFG:");
  94. //
  95. // ISM Method VTable Definition
  96. //
  97. CServiceInfo::ISM_METHOD_DEF CServiceInfo::s_imdMethods[ISM_NUM_METHODS] =
  98. {
  99. //-----------ID----------------Must Have?--------------Method Name------------
  100. ISM_QUERY_SERVICE_INFO, TRUE, SZ_SERVICEINFO_PROC,
  101. ISM_DISCOVER_SERVERS, FALSE, SZ_DISCOVERY_PROC,
  102. ISM_QUERY_SERVER_INFO, TRUE, SZ_SERVERINFO_PROC,
  103. ISM_CHANGE_SERVICE_STATE, FALSE, SZ_CHANGESTATE_PROC,
  104. ISM_CONFIGURE, TRUE, SZ_CONFIGURE_PROC,
  105. ISM_BIND, FALSE, SZ_BIND_PROC,
  106. ISM_UNBIND, FALSE, SZ_UNBIND_PROC,
  107. ISM_CONFIGURE_CHILD, FALSE, SZ_CONFIGURE_CHILD_PROC,
  108. ISM_ENUMERATE_INSTANCES, FALSE, SZ_ENUMERATE_INSTANCES_PROC,
  109. ISM_ENUMERATE_CHILDREN, FALSE, SZ_ENUMERATE_CHILDREN_PROC,
  110. ISM_ADD_INSTANCE, FALSE, SZ_ADD_INSTANCE_PROC,
  111. ISM_DELETE_INSTANCE, FALSE, SZ_DELETE_INSTANCE_PROC,
  112. ISM_ADD_CHILD, FALSE, SZ_ADD_CHILD_PROC,
  113. ISM_DELETE_CHILD, FALSE, SZ_DELETE_CHILD_PROC,
  114. ISM_RENAME_CHILD, FALSE, SZ_RENAME_CHILD_PROC,
  115. ISM_QUERY_INSTANCE_INFO, FALSE, SZ_QUERY_INSTANCE_INFO_PROC,
  116. ISM_QUERY_CHILD_INFO, FALSE, SZ_QUERY_CHILD_INFO_PROC,
  117. ISM_MMC_CONFIGURE, FALSE, SZ_MMC_CONFIGURE_PROC,
  118. ISM_MMC_CONFIGURE_CHILD, FALSE, SZ_MMC_CONFIGURE_CHILD_PROC,
  119. ISM_SECURITY_WIZARD, FALSE, SZ_SECURITY_WIZARD_PROC
  120. };
  121. CServiceInfo::CServiceInfo(
  122. IN int nID,
  123. IN LPCTSTR lpDLLName
  124. )
  125. /*++
  126. Routine Description:
  127. Constructor for service info object. Load the specified config DLL,
  128. and initialise the entry points.
  129. Arguments:
  130. int nID : The guaranteed unique ID assigned to this service
  131. LPCTSTR lpDLLName : The config DLL name to be loaded
  132. Return Value:
  133. N/A
  134. --*/
  135. : CObjectPlus(),
  136. m_hModule(NULL),
  137. m_psiMaster(NULL),
  138. m_strDLLName(lpDLLName),
  139. m_strSupDLLName(),
  140. #ifndef USE_VTABLE
  141. m_pfnQueryServiceInfo(NULL),
  142. m_pfnDiscoverServers(NULL),
  143. m_pfnQueryServerInfo(NULL),
  144. m_pfnChangeServiceState(NULL),
  145. m_pfnConfigure(NULL),
  146. m_pfnConfigureChild(NULL),
  147. m_pfnEnumerateInstances(NULL),
  148. m_pfnEnumerateChildren(NULL),
  149. m_pfnAddInstance(NULL),
  150. m_pfnDeleteInstance(NULL),
  151. m_pfnAddChild(NULL),
  152. m_pfnDeleteChild(NULL),
  153. m_pfnRenameChild(NULL),
  154. m_pfnQueryInstanceInfo(NULL),
  155. m_pfnQueryChildInfo(NULL),
  156. m_pfnISMMMCConfigureServers(NULL),
  157. m_pfnISMMMCConfigureChild(NULL),
  158. m_pfnISMSecurityWizard(NULL),
  159. #endif // USE_VTABLE
  160. m_nID(nID),
  161. m_iBmpID(-1),
  162. m_iBmpChildID(-1)
  163. {
  164. #ifdef USE_VTABLE
  165. //
  166. // Initialize VTable
  167. //
  168. ZeroMemory(&m_rgpfnISMMethods, sizeof(m_rgpfnISMMethods));
  169. #endif // USE_VTABLE
  170. //
  171. // Check for parameter options.
  172. //
  173. TRACEEOLID("Raw DLL name: " << m_strDLLName);
  174. //
  175. // Load super DLL
  176. //
  177. int nOpt = m_strDLLName.Find(s_cszSupcfg);
  178. if (nOpt >= 0)
  179. {
  180. m_strSupDLLName = m_strDLLName.Mid(nOpt + lstrlen(s_cszSupcfg));
  181. m_strDLLName.ReleaseBuffer(nOpt);
  182. TRACEEOLID("Superceed DLL: " << m_strSupDLLName);
  183. }
  184. TRACEEOLID("Attempting to load " << m_strDLLName);
  185. CError err;
  186. BOOL fMissingMethod = FALSE;
  187. m_hModule = ::AfxLoadLibrary(m_strDLLName);
  188. if (m_hModule == NULL)
  189. {
  190. err.GetLastWinError();
  191. if (err.Succeeded())
  192. {
  193. //
  194. // This shouldn't happen, but it sometimes does.
  195. // AfxLoadLibrary resets the last error somewhere???
  196. //
  197. TRACEEOLID("Error!!! Library not loaded, but last error returned 0");
  198. err = ERROR_DLL_NOT_FOUND;
  199. }
  200. TRACEEOLID("Failed to load "
  201. << m_strDLLName
  202. << " GetLastError() returns "
  203. << err
  204. );
  205. }
  206. else
  207. {
  208. TRACEEOLID(m_strDLLName << " LoadLibrary succeeded");
  209. #ifdef USE_VTABLE
  210. //
  211. // Initialize VTable
  212. //
  213. for (int i = 0; i < ISM_NUM_METHODS; ++i)
  214. {
  215. m_rgpfnISMMethods[CServiceInfo::s_imdMethods[i].iID] =
  216. (pfnISMMethod)GetProcAddress(
  217. m_hModule,
  218. CServiceInfo::s_imdMethods[i].lpszMethodName
  219. );
  220. if (CServiceInfo::s_imdMethods[i].fMustHave
  221. && !m_rgpfnISMMethods[CServiceInfo::s_imdMethods[i].iID])
  222. {
  223. fMissingMethod = TRUE;
  224. }
  225. }
  226. #else
  227. //
  228. // Initialise function pointers (not all need be
  229. // present)
  230. //
  231. m_pfnQueryServiceInfo = (pfnQueryServiceInfo)
  232. ::GetProcAddress(m_hModule, SZ_SERVICEINFO_PROC);
  233. m_pfnDiscoverServers = (pfnDiscoverServers)
  234. ::GetProcAddress(m_hModule, SZ_DISCOVERY_PROC);
  235. m_pfnQueryServerInfo = (pfnQueryServerInfo)
  236. ::GetProcAddress(m_hModule, SZ_SERVERINFO_PROC);
  237. m_pfnChangeServiceState = (pfnChangeServiceState)
  238. ::GetProcAddress(m_hModule, SZ_CHANGESTATE_PROC);
  239. m_pfnConfigure = (pfnConfigure)
  240. ::GetProcAddress(m_hModule, SZ_CONFIGURE_PROC);
  241. m_pfnBind = (pfnBind)
  242. ::GetProcAddress(m_hModule, SZ_BIND_PROC);
  243. m_pfnUnbind = (pfnUnbind)
  244. ::GetProcAddress(m_hModule, SZ_UNBIND_PROC);
  245. m_pfnConfigureChild = (pfnConfigureChild)
  246. ::GetProcAddress(m_hModule, SZ_CONFIGURE_CHILD_PROC);
  247. m_pfnEnumerateInstances = (pfnEnumerateInstances)
  248. ::GetProcAddress(m_hModule, SZ_ENUMERATE_INSTANCES_PROC);
  249. m_pfnEnumerateChildren = (pfnEnumerateChildren)
  250. ::GetProcAddress(m_hModule, SZ_ENUMERATE_CHILDREN_PROC);
  251. m_pfnAddInstance = (pfnAddInstance)
  252. ::GetProcAddress(m_hModule, SZ_ADD_INSTANCE_PROC);
  253. m_pfnDeleteInstance = (pfnDeleteInstance)
  254. ::GetProcAddress(m_hModule, SZ_DELETE_INSTANCE_PROC);
  255. m_pfnAddChild = (pfnAddChild)
  256. ::GetProcAddress(m_hModule, SZ_ADD_CHILD_PROC);
  257. m_pfnDeleteChild = (pfnDeleteChild)
  258. ::GetProcAddress(m_hModule, SZ_DELETE_CHILD_PROC);
  259. m_pfnRenameChild = (pfnRenameChild)
  260. ::GetProcAddress(m_hModule, SZ_RENAME_CHILD_PROC);
  261. m_pfnQueryInstanceInfo = (pfnQueryInstanceInfo)
  262. ::GetProcAddress(m_hModule, SZ_QUERY_INSTANCE_INFO_PROC);
  263. m_pfnQueryChildInfo = (pfnQueryChildInfo)
  264. ::GetProcAddress(m_hModule, SZ_QUERY_CHILD_INFO_PROC);
  265. m_pfnISMMMCConfigureServers = (pfnISMMMCConfigureServers)
  266. ::GetProcAddress(m_hModule, SZ_MMC_CONFIGURE_PROC);
  267. m_pfnISMMMCConfigureChild = (pfnISMMMCConfigureChild)
  268. ::GetProcAddress(m_hModule, SZ_MMC_CONFIGURE_CHILD_PROC);
  269. m_pfnISMSecurityWizard = (pfnISMSecurityWizard)
  270. ::GetProcAddress(m_hModule, SZ_SECURITY_WIZARD_PROC);
  271. fMissingMethod = m_pfnQueryServiceInfo == NULL
  272. || m_pfnQueryServerInfo == NULL
  273. || m_pfnChangeServiceState == NULL
  274. || m_pfnConfigure == NULL;
  275. #endif // USE_VTABLE
  276. ::ZeroMemory(&m_si, sizeof(m_si));
  277. m_si.dwSize = sizeof(m_si);
  278. err = ISMQueryServiceInfo(&m_si);
  279. }
  280. if (err.Failed())
  281. {
  282. //
  283. // Fill in the short and long names
  284. // with default values.
  285. //
  286. CString strMenu, strToolTips, str;
  287. VERIFY(strMenu.LoadString(IDS_DEFAULT_SHORTNAME));
  288. VERIFY(strToolTips.LoadString(IDS_DEFAULT_LONGNAME));
  289. //
  290. // Since the structure was zero-filled to
  291. // begin with, lstrcpyn is ok, because
  292. // we will always have the terminating NULL
  293. //
  294. str.Format(strMenu, (LPCTSTR)lpDLLName);
  295. ::lstrcpyn(
  296. m_si.atchShortName,
  297. (LPCTSTR)str,
  298. sizeof((m_si.atchShortName) - 1) / sizeof(m_si.atchShortName[0])
  299. );
  300. str.Format(strToolTips, (LPCTSTR)lpDLLName);
  301. ::lstrcpyn(
  302. m_si.atchLongName,
  303. (LPCTSTR)str,
  304. sizeof((m_si.atchLongName) - 1) / sizeof(m_si.atchLongName[0])
  305. );
  306. }
  307. BOOL fInitOK = m_hModule != NULL
  308. && !fMissingMethod
  309. && err.Succeeded();
  310. //
  311. // The service is selected at startup
  312. // time if it loaded succesfully
  313. //
  314. m_fIsSelected = fInitOK;
  315. TRACEEOLID("Success = " << fInitOK);
  316. m_hrReturnCode = err;
  317. }
  318. CServiceInfo::~CServiceInfo()
  319. /*++
  320. Routine Description:
  321. Destruct the object by unloading the config DLL
  322. Arguments:
  323. N/A
  324. Return Value:
  325. N/A
  326. --*/
  327. {
  328. TRACEEOLID("Cleaning up service info");
  329. if (m_hModule != NULL)
  330. {
  331. TRACEEOLID("Unloading library");
  332. VERIFY(::AfxFreeLibrary(m_hModule));
  333. }
  334. }
  335. //
  336. // ISM Api Functions
  337. //
  338. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  339. #ifdef USE_VTABLE
  340. DWORD
  341. CServiceInfo::ISMQueryServiceInfo(
  342. OUT ISMSERVICEINFO * psi
  343. )
  344. /*++
  345. Routine Description:
  346. Return service-specific information back to
  347. to the application. This function is called
  348. by the service manager immediately after
  349. LoadLibary();
  350. Arguments:
  351. ISMSERVICEINFO * psi : Service information returned.
  352. Return Value:
  353. Error return code
  354. --*/
  355. {
  356. if (ISM_NO_VTABLE_ENTRY(ISM_QUERY_SERVICE_INFO))
  357. {
  358. return ERROR_CAN_NOT_COMPLETE;
  359. }
  360. DWORD err = ISM_VTABLE(ISM_QUERY_SERVICE_INFO)(psi);
  361. if (RequiresSuperDll() && err == ERROR_SUCCESS)
  362. {
  363. //
  364. // This service is superceded. Add "downlevel" to
  365. // service name, if there's room.
  366. //
  367. CString strDL;
  368. VERIFY(strDL.LoadString(IDS_DOWNLEVEL));
  369. if (lstrlen(psi->atchShortName) + strDL.GetLength() < MAX_SNLEN)
  370. {
  371. lstrcat(psi->atchShortName, (LPCTSTR)strDL);
  372. }
  373. }
  374. return err;
  375. }
  376. DWORD
  377. CServiceInfo::ISMQueryServerInfo(
  378. IN LPCTSTR lpszServerName,
  379. OUT ISMSERVERINFO * psi
  380. )
  381. /*++
  382. Routine Description:
  383. Get information on a single server with regards to
  384. this service.
  385. Arguments:
  386. LPCTSTR lpszServerName : Name of server.
  387. ISMSERVERINFO * psi : Server information returned.
  388. Return Value:
  389. Error return code
  390. --*/
  391. {
  392. DWORD err;
  393. if (HasSuperDll())
  394. {
  395. //
  396. // This config DLL is superceded by another one. If _that_ service
  397. // is installed, then assume this one is not.
  398. //
  399. err = GetSuperDll()->ISMQueryServerInfo(lpszServerName, psi);
  400. if (err == ERROR_SUCCESS)
  401. {
  402. //
  403. // The superceding service is installed. That means this
  404. // service is not.
  405. //
  406. return ERROR_SERVICE_DOES_NOT_EXIST;
  407. }
  408. }
  409. if (ISM_NO_VTABLE_ENTRY(ISM_QUERY_SERVER_INFO))
  410. {
  411. return ERROR_CAN_NOT_COMPLETE;
  412. }
  413. return ISM_VTABLE(ISM_QUERY_SERVER_INFO)(
  414. lpszServerName,
  415. psi
  416. );
  417. }
  418. #else !USE_VTABLE
  419. //
  420. // CODEWORK: Most of these method below could be inlined
  421. //
  422. DWORD
  423. CServiceInfo::ISMQueryServiceInfo(
  424. OUT ISMSERVICEINFO * psi
  425. )
  426. /*++
  427. Routine Description:
  428. Return service-specific information back to
  429. to the application. This function is called
  430. by the service manager immediately after
  431. LoadLibary();
  432. Arguments:
  433. ISMSERVICEINFO * psi : Service information returned.
  434. Return Value:
  435. Error return code
  436. --*/
  437. {
  438. if (m_pfnQueryServiceInfo == NULL)
  439. {
  440. return ERROR_CAN_NOT_COMPLETE;
  441. }
  442. DWORD err = (*m_pfnQueryServiceInfo)(psi);
  443. if (RequiresSuperDll() && err == ERROR_SUCCESS)
  444. {
  445. //
  446. // This service is superceded. Add "downlevel" to
  447. // service name, if there's room.
  448. //
  449. CString strDL;
  450. VERIFY(strDL.LoadString(IDS_DOWNLEVEL));
  451. if (lstrlen(psi->atchShortName) + strDL.GetLength() < MAX_SNLEN)
  452. {
  453. lstrcat(psi->atchShortName, (LPCTSTR)strDL);
  454. }
  455. }
  456. return err;
  457. }
  458. DWORD
  459. CServiceInfo::ISMQueryServerInfo(
  460. IN LPCTSTR lpszServerName, // Name of server.
  461. OUT ISMSERVERINFO * psi // Server information returned.
  462. )
  463. /*++
  464. Routine Description:
  465. Get information on a single server with regards to
  466. this service.
  467. Arguments:
  468. LPCTSTR lpszServerName : Name of server.
  469. ISMSERVERINFO * psi : Server information returned.
  470. Return Value:
  471. Error return code
  472. --*/
  473. {
  474. DWORD err;
  475. if (HasSuperDll())
  476. {
  477. //
  478. // This config DLL is superceded by another one. If _that_ service
  479. // is installed, then assume this one is not.
  480. //
  481. err = GetSuperDll()->ISMQueryServerInfo(lpszServerName, psi);
  482. if (err == ERROR_SUCCESS)
  483. {
  484. //
  485. // The superceding service is installed. That means this
  486. // service is not.
  487. //
  488. return ERROR_SERVICE_DOES_NOT_EXIST;
  489. }
  490. }
  491. if (m_pfnQueryServerInfo != NULL)
  492. {
  493. return (*m_pfnQueryServerInfo)(lpszServerName, psi);
  494. }
  495. return ERROR_CAN_NOT_COMPLETE;
  496. }
  497. #endif // USE_VTABLE
  498. //
  499. // New Instance Command Class
  500. //
  501. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  502. CNewInstanceCmd::CNewInstanceCmd(
  503. IN CServiceInfo * pServiceInfo
  504. )
  505. /*++
  506. Routine Description:
  507. New instance command constructor. Build a menu command
  508. for the create new submenu.
  509. Arguments:
  510. CServiceInfo * pServiceInfo : Service info object
  511. Return Value:
  512. N/A
  513. --*/
  514. : m_pServiceInfo(pServiceInfo)
  515. {
  516. ASSERT(m_pServiceInfo != NULL);
  517. try
  518. {
  519. CString str;
  520. VERIFY(str.LoadString(IDS_MENU_EX_NEWINSTANCE));
  521. m_strMenuCommand.Format(str, m_pServiceInfo->GetShortName());
  522. VERIFY(str.LoadString(IDS_MENU_TT_EX_NEWINSTANCE));
  523. m_strTTText.Format(str, m_pServiceInfo->GetShortName());
  524. }
  525. catch(CMemoryException * e)
  526. {
  527. e->ReportError();
  528. e->Delete();
  529. }
  530. }
  531. /* static */
  532. CServiceInfo *
  533. CServerInfo::FindServiceByMask(
  534. IN ULONGLONG ullTarget,
  535. IN CObListPlus & oblServices
  536. )
  537. /*++
  538. Routine Description:
  539. Given the inetsloc mask, return the service this
  540. fits. Return NULL if the service was not found.
  541. Arguments:
  542. ULONGLONG ullTarget : The mask to look for
  543. CObListPlus & oblServices : List of service objects in which to look
  544. Return Value:
  545. Pointer to service object that uses this mask, or NULL if the
  546. service isn't found
  547. --*/
  548. {
  549. CObListIter obli(oblServices);
  550. CServiceInfo * psi;
  551. //
  552. // Straight sequential search
  553. //
  554. TRACEEOLID("Looking for service with mask " << (DWORD)ullTarget);
  555. while (psi = (CServiceInfo *)obli.Next())
  556. {
  557. if (psi->InitializedOK()
  558. && psi->UseInetSlocDiscover()
  559. && psi->QueryDiscoveryMask() == ullTarget
  560. )
  561. {
  562. TRACEEOLID("Found it: " << psi->GetShortName());
  563. return psi;
  564. }
  565. }
  566. //
  567. // Didn't find it..
  568. //
  569. TRACEEOLID("Error: mask not matched up with any known service");
  570. return NULL;
  571. }
  572. /* static */
  573. LPCTSTR
  574. CServerInfo::CleanServerName(
  575. IN OUT CString & str
  576. )
  577. /*++
  578. Routine Description:
  579. Utility function to clean up a computer/hostname
  580. Arguments:
  581. CString & str : Server name to be cleaned up
  582. Return Value:
  583. Pointer to the string
  584. --*/
  585. {
  586. #ifdef ENFORCE_NETBIOS
  587. //
  588. // Clean up name, and enforce leading slashes
  589. //
  590. str.MakeUpper();
  591. try
  592. {
  593. if (!IS_NETBIOS_NAME(str))
  594. {
  595. str = _T("\\\\") + str;
  596. }
  597. }
  598. catch(CMemoryException * e)
  599. {
  600. TRACEEOLID("!!!exception cleaning up server name");
  601. e->ReportError();
  602. e->Delete();
  603. }
  604. #else
  605. //
  606. // If the name is NETBIOS, convert to upper case. Otherwise
  607. // the name is assumed to be a hostname, and should be
  608. // converted to lower case.
  609. //
  610. if (IS_NETBIOS_NAME(str))
  611. {
  612. str.MakeUpper();
  613. }
  614. else
  615. {
  616. str.MakeLower();
  617. }
  618. #endif // ENFORCE_NETBIOS
  619. return str;
  620. }
  621. CServerInfo::CServerInfo(
  622. IN LPCTSTR lpszServerName,
  623. IN ISMSERVERINFO * psi,
  624. IN CServiceInfo * pServiceInfo
  625. )
  626. /*++
  627. Routine Description:
  628. Construct with a server name. This is typically
  629. in response to a single connection attempt
  630. Arguments:
  631. LPCTSTR lpszServerName : Name of this server
  632. ISMSERVERINFO * psi : Server info
  633. CServiceInfo * pServiceInfo : service that found it.
  634. Return Value:
  635. N/A
  636. --*/
  637. : m_strServerName(lpszServerName),
  638. m_strComment( psi->atchComment),
  639. m_nServiceState(psi->nState),
  640. m_hServer(NULL),
  641. m_pService(pServiceInfo)
  642. {
  643. CServerInfo::CleanServerName(m_strServerName);
  644. if (m_pService != NULL)
  645. {
  646. //
  647. // Bind here
  648. //
  649. if (m_pService->IsK2Service())
  650. {
  651. ASSERT(m_hServer == NULL);
  652. HRESULT hr = m_pService->ISMBind(
  653. m_strServerName,
  654. &m_hServer
  655. );
  656. }
  657. }
  658. else
  659. {
  660. TRACEEOLID("Did not match up server with installed service");
  661. }
  662. }
  663. CServerInfo::CServerInfo(
  664. IN LPCSTR lpszServerName,
  665. IN LPINET_SERVICE_INFO lpisi,
  666. IN CObListPlus & oblServices
  667. )
  668. /*++
  669. Routine Description:
  670. Construct with information from the inetsloc discover
  671. process. Construction of the CString will automatically
  672. perform the ANSI/Unicode conversion,
  673. Arguments:
  674. LPCSTR lpszServerName : Name of this server (no "\\")
  675. LPINET_SERVICE_INFO lpisi : Discovery information
  676. CObListPlus & oblServices : List of installed services
  677. Return Value:
  678. N/A
  679. --*/
  680. : m_strServerName(lpszServerName),
  681. m_strComment(lpisi->ServiceComment),
  682. m_nServiceState(lpisi->ServiceState),
  683. m_hServer(NULL),
  684. m_pService(NULL)
  685. {
  686. CServerInfo::CleanServerName(m_strServerName);
  687. m_pService = FindServiceByMask(lpisi->ServiceMask, oblServices);
  688. if (m_pService != NULL)
  689. {
  690. if (m_pService->IsK2Service())
  691. {
  692. ASSERT(m_hServer == NULL);
  693. HRESULT hr = m_pService->ISMBind(
  694. m_strServerName,
  695. &m_hServer
  696. );
  697. }
  698. }
  699. else
  700. {
  701. TRACEEOLID("Did not match up server with installed service");
  702. }
  703. }
  704. HRESULT
  705. CServerInfo::ISMRebind()
  706. /*++
  707. Routine Description:
  708. Handle lost connection. Attempt to rebind.
  709. Arguments:
  710. None
  711. Return Value:
  712. HRESULT
  713. --*/
  714. {
  715. HRESULT hr = S_OK;
  716. if (m_pService != NULL)
  717. {
  718. if (m_pService->IsK2Service())
  719. {
  720. //
  721. // Must be previously bound
  722. //
  723. ASSERT(m_hServer != NULL);
  724. //
  725. // This may cause a first chance exception, because
  726. // the handle could be invalid at this stage
  727. //
  728. hr = m_pService->ISMUnbind(m_hServer);
  729. hr = m_pService->ISMBind(
  730. m_strServerName,
  731. &m_hServer
  732. );
  733. }
  734. }
  735. return hr;
  736. }
  737. CServerInfo::CServerInfo(
  738. IN const CServerInfo & si
  739. )
  740. /*++
  741. Routine Description:
  742. Copy Constructor
  743. Arguments:
  744. const CServerInfo & si : Source server info object
  745. Return Value:
  746. N/A
  747. --*/
  748. : m_strServerName(si.m_strServerName),
  749. m_strComment(si.m_strComment),
  750. m_nServiceState(si.m_nServiceState),
  751. m_hServer(NULL),
  752. m_pService(si.m_pService)
  753. {
  754. //
  755. // Bind again here
  756. //
  757. if (m_pService->IsK2Service())
  758. {
  759. ASSERT(m_hServer == NULL);
  760. HRESULT hr = m_pService->ISMBind(
  761. m_strServerName,
  762. &m_hServer
  763. );
  764. }
  765. }
  766. CServerInfo::~CServerInfo()
  767. /*++
  768. Routine Description:
  769. Destruct the object. Do not free in the pointer
  770. to the service, because we don't own it.
  771. Arguments:
  772. N/A
  773. Return Value:
  774. N/A
  775. --*/
  776. {
  777. //
  778. // Unbind here
  779. //
  780. if (m_pService->IsK2Service())
  781. {
  782. m_pService->ISMUnbind(m_hServer);
  783. }
  784. }
  785. const CServerInfo &
  786. CServerInfo::operator=(
  787. IN const CServerInfo & si
  788. )
  789. /*++
  790. Routine Description:
  791. Assignment operator
  792. Arguments:
  793. const CServerInfo & si : Source server info object
  794. Return Value:
  795. Reference to this object
  796. --*/
  797. {
  798. m_strServerName = si.m_strServerName;
  799. m_nServiceState = si.m_nServiceState;
  800. m_strComment = si.m_strComment;
  801. m_pService = si.m_pService;
  802. //
  803. // Need to rebind
  804. //
  805. if (m_pService->IsK2Service())
  806. {
  807. ASSERT(m_hServer == NULL);
  808. HRESULT hr = m_pService->ISMBind(
  809. m_strServerName,
  810. &m_hServer
  811. );
  812. }
  813. return *this;
  814. }
  815. BOOL
  816. CServerInfo::operator==(
  817. IN CServerInfo & si
  818. )
  819. /*++
  820. Routine Description:
  821. Comparision Operator
  822. Arguments:
  823. const CServerInfo & si : Server info object to be compared against
  824. Return Value:
  825. TRUE if the objects are the same, FALSE otherwise
  826. --*/
  827. {
  828. //
  829. // Must be the same service type
  830. //
  831. if (m_pService != si.m_pService)
  832. {
  833. return FALSE;
  834. }
  835. //
  836. // And computer name
  837. //
  838. return ::lstrcmpi(
  839. QueryServerDisplayName(),
  840. si.QueryServerDisplayName()
  841. ) == 0;
  842. }
  843. DWORD
  844. CServerInfo::ChangeServiceState(
  845. IN int nNewState,
  846. OUT int * pnCurrentState,
  847. IN DWORD dwInstance
  848. )
  849. /*++
  850. Routine Description:
  851. Change Service State on this computer (running,
  852. stopped, paused)
  853. Arguments:
  854. int nNewState : New service state INetServiceRunning, etc
  855. int * pnCurrentState : Pointer to current state
  856. DWORD dwInstance : Instance ID whose state is to be changed
  857. Return Value:
  858. Error return code
  859. --*/
  860. {
  861. ASSERT(m_pService != NULL);
  862. //
  863. // Allocate string with 2 terminating NULLS,
  864. // as required by the apis.
  865. //
  866. int nLen = m_strServerName.GetLength();
  867. LPTSTR lpServers = AllocTString(nLen + 2);
  868. if (lpServers == NULL)
  869. {
  870. return ERROR_NOT_ENOUGH_MEMORY;
  871. }
  872. ::lstrcpy(lpServers, m_strServerName);
  873. lpServers[nLen+1] = _T('\0');
  874. //
  875. // Call the actual api (0 -- means service)
  876. //
  877. DWORD err = m_pService->ISMChangeServiceState(
  878. nNewState,
  879. pnCurrentState,
  880. dwInstance,
  881. lpServers
  882. );
  883. FreeMem(lpServers);
  884. return err;
  885. }
  886. DWORD
  887. CServerInfo::ConfigureServer(
  888. IN HWND hWnd,
  889. IN DWORD dwInstance
  890. )
  891. /*++
  892. Routine Description:
  893. Perform configuration on this server
  894. Arguments:
  895. HWND hWnd : Parent window handle
  896. DWORD dwInstance : Instance ID to be configured
  897. Return Value:
  898. Error return code
  899. --*/
  900. {
  901. ASSERT(m_pService != NULL);
  902. //
  903. // Allocate string with 2 terminating NULLS
  904. //
  905. // CODEWORK: Make this a helper function
  906. //
  907. int nLen = m_strServerName.GetLength();
  908. LPTSTR lpServers = AllocTString(nLen + 2);
  909. if (lpServers == NULL)
  910. {
  911. return ERROR_NOT_ENOUGH_MEMORY;
  912. }
  913. ::lstrcpy(lpServers, (LPCTSTR)m_strServerName);
  914. lpServers[nLen + 1] = _T('\0');
  915. DWORD err = m_pService->ISMConfigureServers(hWnd, dwInstance, lpServers);
  916. FreeMem(lpServers);
  917. return err;
  918. }
  919. HRESULT
  920. CServerInfo::MMMCConfigureServer(
  921. IN PVOID lpfnProvider,
  922. IN LPARAM param,
  923. IN LONG_PTR handle,
  924. IN DWORD dwInstance
  925. )
  926. /*++
  927. Routine Description:
  928. Bring up the service configuration property sheets, using the MMC
  929. property mechanism.
  930. Arguments:
  931. PVOID lpfnProvider : Provider callback
  932. LPARAM param : lparam to be passed to the sheet
  933. LONG_PTR handle : console handle
  934. DWORD dwInstance : Instance number
  935. Return Value:
  936. Error return code
  937. --*/
  938. {
  939. ASSERT(m_pService != NULL);
  940. /*
  941. //
  942. // Allocate string with 2 terminating NULLS
  943. //
  944. int nLen = m_strServerName.GetLength();
  945. LPTSTR lpServers = AllocTString(nLen + 2);
  946. if (lpServers == NULL)
  947. {
  948. return ERROR_NOT_ENOUGH_MEMORY;
  949. }
  950. ::lstrcpy(lpServers, (LPCTSTR)m_strServerName);
  951. lpServers[nLen + 1] = _T('\0');
  952. */
  953. CError err(m_pService->ISMMMCConfigureServers(
  954. m_hServer,
  955. lpfnProvider,
  956. param,
  957. handle,
  958. dwInstance
  959. ));
  960. // FreeMem(lpServers);
  961. return err;
  962. }
  963. DWORD
  964. CServerInfo::Refresh()
  965. /*++
  966. Routine Description:
  967. Attempt to refresh the comment and server state of
  968. the server object
  969. Arguments:
  970. None
  971. Return Value:
  972. Error return code
  973. --*/
  974. {
  975. ISMSERVERINFO si;
  976. si.dwSize = sizeof(si);
  977. CError err(m_pService->ISMQueryServerInfo(
  978. (LPCTSTR)m_strServerName,
  979. &si
  980. ));
  981. if (err.Succeeded())
  982. {
  983. ASSERT(si.nState == INetServiceStopped ||
  984. si.nState == INetServicePaused ||
  985. si.nState == INetServiceRunning ||
  986. si.nState == INetServiceUnknown);
  987. m_nServiceState = si.nState;
  988. m_strComment = si.atchComment;
  989. }
  990. return err;
  991. }