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.

856 lines
15 KiB

  1. /*++
  2. Copyright (c) 1994-95 Microsoft Corporation
  3. Module Name:
  4. appobj.cpp
  5. Abstract:
  6. OLE-createable application object implementation.
  7. Author:
  8. Don Ryan (donryan) 27-Dec-1994
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. Jeff Parham (jeffparh) 16-Jan-1996
  13. Added Get/SetLastTargetServer() to help isolate server connection
  14. problems. (Bug #2993.)
  15. --*/
  16. #include "stdafx.h"
  17. #include "llsmgr.h"
  18. #include "lmerr.h"
  19. #include "lmcons.h"
  20. #include "lmwksta.h"
  21. #include "lmapibuf.h"
  22. #include "lmserver.h"
  23. #ifdef _DEBUG
  24. #undef THIS_FILE
  25. static char BASED_CODE THIS_FILE[] = __FILE__;
  26. #endif
  27. IMPLEMENT_DYNCREATE(CApplication, CCmdTarget)
  28. // IMPLEMENT_OLECREATE(CApplication, "Llsmgr.Application.1", 0x2c5dffb3, 0x472f, 0x11ce, 0xa0, 0x30, 0x0, 0xaa, 0x0, 0x33, 0x9a, 0x98)
  29. BEGIN_MESSAGE_MAP(CApplication, CCmdTarget)
  30. //{{AFX_MSG_MAP(CApplication)
  31. // NOTE - the ClassWizard will add and remove mapping macros here.
  32. //}}AFX_MSG_MAP
  33. END_MESSAGE_MAP()
  34. BEGIN_DISPATCH_MAP(CApplication, CCmdTarget)
  35. //{{AFX_DISPATCH_MAP(CApplication)
  36. DISP_PROPERTY_EX(CApplication, "Application", GetApplication, SetNotSupported, VT_DISPATCH)
  37. DISP_PROPERTY_EX(CApplication, "FullName", GetFullName, SetNotSupported, VT_BSTR)
  38. DISP_PROPERTY_EX(CApplication, "Name", GetName, SetNotSupported, VT_BSTR)
  39. DISP_PROPERTY_EX(CApplication, "Parent", GetParent, SetNotSupported, VT_DISPATCH)
  40. DISP_PROPERTY_EX(CApplication, "Visible", GetVisible, SetNotSupported, VT_BOOL)
  41. DISP_PROPERTY_EX(CApplication, "ActiveController", GetActiveController, SetNotSupported, VT_DISPATCH)
  42. DISP_PROPERTY_EX(CApplication, "ActiveDomain", GetActiveDomain, SetNotSupported, VT_DISPATCH)
  43. DISP_PROPERTY_EX(CApplication, "LocalDomain", GetLocalDomain, SetNotSupported, VT_DISPATCH)
  44. DISP_PROPERTY_EX(CApplication, "IsFocusDomain", IsFocusDomain, SetNotSupported, VT_BOOL)
  45. DISP_PROPERTY_EX(CApplication, "LastErrorString", GetLastErrorString, SetNotSupported, VT_BSTR)
  46. DISP_FUNCTION(CApplication, "Quit", Quit, VT_EMPTY, VTS_NONE)
  47. DISP_FUNCTION(CApplication, "SelectDomain", SelectDomain, VT_BOOL, VTS_VARIANT)
  48. DISP_FUNCTION(CApplication, "SelectEnterprise", SelectEnterprise, VT_BOOL, VTS_NONE)
  49. DISP_PROPERTY_PARAM(CApplication, "Domains", GetDomains, SetNotSupported, VT_DISPATCH, VTS_VARIANT)
  50. DISP_DEFVALUE(CApplication, "Name")
  51. //}}AFX_DISPATCH_MAP
  52. END_DISPATCH_MAP()
  53. CApplication::CApplication()
  54. /*++
  55. Routine Description:
  56. Constructor for OLE-createable application object.
  57. To keep the application running as long as an OLE automation
  58. object is active, we must call AfxOleLockApp.
  59. Arguments:
  60. None.
  61. Return Values:
  62. None.
  63. --*/
  64. {
  65. EnableAutomation();
  66. ASSERT(theApp.m_pApplication == NULL);
  67. if (theApp.m_pApplication == NULL)
  68. theApp.m_pApplication = this;
  69. if (theApp.m_bIsAutomated)
  70. AfxOleLockApp();
  71. m_pDomains = NULL;
  72. m_pLocalDomain = NULL;
  73. m_pActiveDomain = NULL;
  74. m_bIsFocusDomain = FALSE;
  75. m_bDomainsRefreshed = FALSE;
  76. m_strLastTargetServer = TEXT("");
  77. m_domainArray.RemoveAll();
  78. m_pActiveController = new CController;
  79. m_idStatus = m_pActiveController ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  80. }
  81. CApplication::~CApplication()
  82. /*++
  83. Routine Description:
  84. Destructor for OLE-createable application object.
  85. Arguments:
  86. None.
  87. Return Values:
  88. None.
  89. --*/
  90. {
  91. ASSERT(theApp.m_pApplication == this);
  92. if (theApp.m_pApplication == this)
  93. theApp.m_pApplication = NULL;
  94. if (theApp.m_bIsAutomated)
  95. AfxOleUnlockApp();
  96. if (m_pDomains)
  97. m_pDomains->InternalRelease();
  98. if (m_pLocalDomain)
  99. m_pLocalDomain->InternalRelease();
  100. if (m_pActiveDomain)
  101. m_pActiveDomain->InternalRelease();
  102. if (m_pActiveController)
  103. m_pActiveController->InternalRelease();
  104. }
  105. void CApplication::OnFinalRelease()
  106. /*++
  107. Routine Description:
  108. When the last reference for an automation object is released
  109. OnFinalRelease is called. This implementation deletes object.
  110. Arguments:
  111. None.
  112. Return Values:
  113. None.
  114. --*/
  115. {
  116. ResetDomains();
  117. delete this;
  118. }
  119. LPDISPATCH CApplication::GetActiveController()
  120. /*++
  121. Routine Description:
  122. Returns the active license controller object.
  123. Arguments:
  124. None.
  125. Return Values:
  126. VT_DISPATCH or VT_EMPTY.
  127. --*/
  128. {
  129. ASSERT_VALID(m_pActiveController);
  130. return m_pActiveController->GetIDispatch(TRUE);
  131. }
  132. LPDISPATCH CApplication::GetActiveDomain()
  133. /*++
  134. Routine Description:
  135. Returns the active domain object.
  136. Arguments:
  137. None.
  138. Return Values:
  139. VT_DISPATCH or VT_EMPTY.
  140. --*/
  141. {
  142. return m_pActiveDomain ? m_pActiveDomain->GetIDispatch(TRUE) : NULL;
  143. }
  144. LPDISPATCH CApplication::GetApplication()
  145. /*++
  146. Routine Description:
  147. Returns the application object.
  148. Arguments:
  149. None.
  150. Return Values:
  151. VT_DISPATCH.
  152. --*/
  153. {
  154. return GetIDispatch(TRUE);
  155. }
  156. LPDISPATCH CApplication::GetDomains(const VARIANT FAR& index)
  157. /*++
  158. Routine Description:
  159. Returns a collection object containing all of the domains
  160. visible to the local machine or returns an individual domain
  161. described by an index into the collection.
  162. Arguments:
  163. index - optional argument that may be a string (VT_BSTR)
  164. indicating a domain name or a number (VT_I4) indicating
  165. the position within collection.
  166. Return Values:
  167. VT_DISPATCH or VT_EMPTY.
  168. --*/
  169. {
  170. LPDISPATCH lpdispatch = NULL;
  171. if (!m_pDomains)
  172. {
  173. m_pDomains = new CDomains(this, &m_domainArray);
  174. }
  175. if (m_pDomains)
  176. {
  177. if (V_ISVOID((VARIANT FAR*)&index))
  178. {
  179. if (RefreshDomains())
  180. {
  181. lpdispatch = m_pDomains->GetIDispatch(TRUE);
  182. }
  183. }
  184. else
  185. {
  186. if (m_bDomainsRefreshed)
  187. {
  188. lpdispatch = m_pDomains->GetItem(index);
  189. }
  190. else if (RefreshDomains())
  191. {
  192. lpdispatch = m_pDomains->GetItem(index);
  193. }
  194. }
  195. }
  196. else
  197. {
  198. SetLastStatus(STATUS_NO_MEMORY);
  199. }
  200. return lpdispatch;
  201. }
  202. BSTR CApplication::GetFullName()
  203. /*++
  204. Routine Description:
  205. Returns the file specification for the application,
  206. including path.
  207. Arguments:
  208. None.
  209. Return Values:
  210. VT_BSTR.
  211. --*/
  212. {
  213. TCHAR szModuleFileName[260];
  214. GetModuleFileName(AfxGetApp()->m_hInstance, szModuleFileName, 260);
  215. return SysAllocStringLen(szModuleFileName, lstrlen(szModuleFileName));
  216. }
  217. BSTR CApplication::GetLastErrorString()
  218. /*++
  219. Routine Description:
  220. Retrieves string for last error.
  221. (Routine stolen from winsadmn...).
  222. Arguments:
  223. None.
  224. Return Values:
  225. VT_BSTR.
  226. --*/
  227. {
  228. CString strLastError;
  229. DWORD nId = m_idStatus;
  230. if (((long)nId == RPC_S_CALL_FAILED) ||
  231. ((long)nId == RPC_NT_SS_CONTEXT_MISMATCH))
  232. {
  233. strLastError.LoadString(IDP_ERROR_DROPPED_LINK);
  234. }
  235. else if (((long)nId == RPC_S_SERVER_UNAVAILABLE) ||
  236. ((long)nId == RPC_NT_SERVER_UNAVAILABLE))
  237. {
  238. strLastError.LoadString(IDP_ERROR_NO_RPC_SERVER);
  239. }
  240. else if ((long)nId == STATUS_MEMBER_IN_GROUP)
  241. {
  242. strLastError.LoadString(IDP_ERROR_MEMBER_IN_GROUP);
  243. }
  244. else
  245. {
  246. HINSTANCE hinstDll = NULL;
  247. if ((nId >= NERR_BASE) && (nId <= MAX_NERR))
  248. {
  249. hinstDll = ::LoadLibrary(_T("netmsg.dll"));
  250. }
  251. else if (nId >= 0x4000000)
  252. {
  253. hinstDll = ::LoadLibrary(_T("ntdll.dll"));
  254. }
  255. TCHAR szLastError[1024];
  256. DWORD cchLastError = sizeof(szLastError) / sizeof(TCHAR);
  257. DWORD dwFlags = FORMAT_MESSAGE_IGNORE_INSERTS|
  258. FORMAT_MESSAGE_MAX_WIDTH_MASK|
  259. (hinstDll ? FORMAT_MESSAGE_FROM_HMODULE
  260. : FORMAT_MESSAGE_FROM_SYSTEM);
  261. cchLastError = ::FormatMessage(
  262. dwFlags,
  263. hinstDll,
  264. nId,
  265. 0,
  266. szLastError,
  267. cchLastError,
  268. NULL
  269. );
  270. if (hinstDll)
  271. {
  272. ::FreeLibrary(hinstDll);
  273. }
  274. if (cchLastError)
  275. {
  276. strLastError = szLastError;
  277. }
  278. else
  279. {
  280. strLastError.LoadString(IDP_ERROR_UNSUCCESSFUL);
  281. }
  282. }
  283. return strLastError.AllocSysString();
  284. }
  285. LPDISPATCH CApplication::GetLocalDomain()
  286. /*++
  287. Routine Description:
  288. Returns the local domain object.
  289. Arguments:
  290. None.
  291. Return Values:
  292. VT_DISPATCH or VT_EMPTY.
  293. --*/
  294. {
  295. if (!m_pLocalDomain)
  296. {
  297. NET_API_STATUS NetStatus;
  298. PWKSTA_INFO_100 pWkstaInfo100 = NULL;
  299. NetStatus = NetWkstaGetInfo(
  300. NULL,
  301. 100,
  302. (LPBYTE*)&pWkstaInfo100
  303. );
  304. if (NetStatus == ERROR_SUCCESS)
  305. {
  306. m_pLocalDomain = new CDomain(this, pWkstaInfo100->wki100_langroup);
  307. if (!m_pLocalDomain)
  308. {
  309. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  310. }
  311. NetApiBufferFree(pWkstaInfo100);
  312. }
  313. SetLastStatus(NetStatus); // called api
  314. }
  315. return m_pLocalDomain ? m_pLocalDomain->GetIDispatch(TRUE) : NULL;
  316. }
  317. BSTR CApplication::GetName()
  318. /*++
  319. Routine Description:
  320. Returns the name of the application.
  321. Arguments:
  322. None.
  323. Return Values:
  324. VT_BSTR.
  325. --*/
  326. {
  327. CString AppName = AfxGetAppName();
  328. return AppName.AllocSysString();
  329. }
  330. LPDISPATCH CApplication::GetParent()
  331. /*++
  332. Routine Description:
  333. Returns the parent of the object.
  334. Arguments:
  335. None.
  336. Return Values:
  337. VT_DISPATCH.
  338. --*/
  339. {
  340. return GetApplication();
  341. }
  342. BOOL CApplication::GetVisible()
  343. /*++
  344. Routine Description:
  345. Returns whether or not the application is visible to the user.
  346. Arguments:
  347. None.
  348. Return Values:
  349. VT_BOOL.
  350. --*/
  351. {
  352. return FALSE;
  353. }
  354. BOOL CApplication::IsFocusDomain()
  355. /*++
  356. Routine Description:
  357. Returns true if application focused on domain.
  358. Arguments:
  359. None.
  360. Return Values:
  361. VT_BOOL.
  362. --*/
  363. {
  364. return m_bIsFocusDomain;
  365. }
  366. BOOL CApplication::RefreshDomains()
  367. /*++
  368. Routine Description:
  369. Refreshs domain object list.
  370. Arguments:
  371. None.
  372. Return Values:
  373. None.
  374. --*/
  375. {
  376. ResetDomains();
  377. NET_API_STATUS NetStatus;
  378. DWORD ResumeHandle = 0L;
  379. int iDomain = 0;
  380. do
  381. {
  382. DWORD EntriesRead;
  383. DWORD TotalEntries;
  384. LPBYTE ReturnBuffer = NULL;
  385. NetStatus = NetServerEnum(
  386. NULL, // servername
  387. 100, // level
  388. &ReturnBuffer,
  389. LLS_PREFERRED_LENGTH,
  390. &EntriesRead,
  391. &TotalEntries,
  392. SV_TYPE_DOMAIN_ENUM,
  393. NULL, // domain
  394. &ResumeHandle
  395. );
  396. if (NetStatus == ERROR_SUCCESS ||
  397. NetStatus == ERROR_MORE_DATA)
  398. {
  399. CDomain* pDomain;
  400. PSERVER_INFO_100 pServerInfo100;
  401. pServerInfo100 = (PSERVER_INFO_100)ReturnBuffer;
  402. ASSERT(iDomain == m_domainArray.GetSize());
  403. m_domainArray.SetSize(m_domainArray.GetSize() + EntriesRead);
  404. while (EntriesRead--)
  405. {
  406. pDomain = new CDomain(this, pServerInfo100->sv100_name);
  407. m_domainArray.SetAt(iDomain++, pDomain); // validate later
  408. pServerInfo100++;
  409. }
  410. NetApiBufferFree(ReturnBuffer);
  411. }
  412. } while (NetStatus == ERROR_MORE_DATA);
  413. SetLastStatus(NetStatus); // called api
  414. if (NetStatus == ERROR_SUCCESS)
  415. {
  416. m_bDomainsRefreshed = TRUE;
  417. }
  418. else
  419. {
  420. ResetDomains();
  421. }
  422. return m_bDomainsRefreshed;
  423. }
  424. void CApplication::ResetDomains()
  425. /*++
  426. Routine Description:
  427. Resets domain object list.
  428. Arguments:
  429. None.
  430. Return Values:
  431. None.
  432. --*/
  433. {
  434. CDomain* pDomain;
  435. INT_PTR iDomain = m_domainArray.GetSize();
  436. while (iDomain--)
  437. {
  438. if (pDomain = (CDomain*)m_domainArray[iDomain])
  439. {
  440. ASSERT(pDomain->IsKindOf(RUNTIME_CLASS(CDomain)));
  441. pDomain->InternalRelease();
  442. }
  443. }
  444. m_domainArray.RemoveAll();
  445. m_bDomainsRefreshed = FALSE;
  446. }
  447. BOOL CApplication::SelectDomain(const VARIANT FAR& domain)
  448. /*++
  449. Routine Description:
  450. Connects to license controller of specified domain.
  451. Arguments:
  452. domain - name of domain.
  453. Return Values:
  454. VT_BOOL.
  455. --*/
  456. {
  457. BOOL bIsSelected = FALSE;
  458. ASSERT_VALID(m_pActiveController);
  459. if (bIsSelected = m_pActiveController->Connect(domain))
  460. {
  461. LPTSTR pszActiveDomain = MKSTR(m_pActiveController->m_strActiveDomainName);
  462. if (m_pActiveDomain)
  463. {
  464. m_pActiveDomain->InternalRelease();
  465. m_pActiveDomain = NULL;
  466. }
  467. if (pszActiveDomain && *pszActiveDomain)
  468. {
  469. m_pActiveDomain = new CDomain(this, pszActiveDomain);
  470. if (m_pActiveDomain)
  471. {
  472. m_bIsFocusDomain = TRUE;
  473. }
  474. else
  475. {
  476. m_bIsFocusDomain = FALSE; // invalidate m_pActiveDomain
  477. SetLastStatus(STATUS_NO_MEMORY);
  478. }
  479. }
  480. else
  481. {
  482. m_bIsFocusDomain = FALSE; // invalidate m_pActiveDomain
  483. }
  484. }
  485. return bIsSelected;
  486. }
  487. BOOL CApplication::SelectEnterprise()
  488. /*++
  489. Routine Description:
  490. Connects to license controller of enterprise.
  491. Arguments:
  492. None.
  493. Return Values:
  494. VT_BOOL.
  495. --*/
  496. {
  497. BOOL bIsSelected = FALSE;
  498. VARIANT va;
  499. VariantInit(&va); // connect to default controller
  500. if (bIsSelected = m_pActiveController->Connect(va))
  501. {
  502. if (m_pActiveDomain)
  503. {
  504. m_pActiveDomain->InternalRelease();
  505. m_pActiveDomain = NULL;
  506. }
  507. m_bIsFocusDomain = FALSE;
  508. }
  509. return bIsSelected;
  510. }
  511. void CApplication::Quit()
  512. /*++
  513. Routine Description:
  514. Closes all documents and exits the application.
  515. Arguments:
  516. None.
  517. Return Values:
  518. None.
  519. --*/
  520. {
  521. AfxPostQuitMessage(0); // no main window...
  522. }
  523. BSTR CApplication::GetLastTargetServer()
  524. /*++
  525. Routine Description:
  526. Retrieves string for last server to which we tried to connect.
  527. Arguments:
  528. None.
  529. Return Values:
  530. VT_BSTR.
  531. --*/
  532. {
  533. if ( m_strLastTargetServer.IsEmpty() )
  534. return NULL;
  535. else
  536. return m_strLastTargetServer.AllocSysString();
  537. }
  538. void CApplication::SetLastTargetServer( LPCTSTR pszServerName )
  539. /*++
  540. Routine Description:
  541. Sets string for last server to which we tried to connect.
  542. Arguments:
  543. pszServerName - last server name to which we tried to connect.
  544. Return Values:
  545. None.
  546. --*/
  547. {
  548. m_strLastTargetServer = pszServerName;
  549. }