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.

2623 lines
114 KiB

  1. To Do:
  2. 1. Resolve vi problem.
  3. 551410 NLB:nlbmgr: Can't create new cluster via nlbmgr uitility
  4. 571762 NLB does not properly filter dedicated IP address traffic
  5. 585280 NLBMgr fails when cluster instance has nlb was bound but not cfg
  6. 5. See if we can call RegWriteParams BEFORE binding.
  7. 2. 535616 memory leak running remove from view
  8. 587508 Wmiprvse.exe is using too much memory cause exception
  9. 599165 nlbmgr:remember host properties when update is pending
  10. 591265 VERIFIER STOP 0000000A: unexpected exception raised in DLL entry
  11. 3. HostID analysis -- look for duplicates, missing ones and partitions
  12. 1. Queue calls to handle-engine-event and handle them in the main proc.
  13. - checkin, but make it disabled...
  14. - remove ALL (or almost ALL) calls to ProcesMsgQueue.
  15. Remove most occurrances of calls to ProcessMsgQueue in engine.cpp --
  16. replace by calls in document.cpp for log and handleengineevent.
  17. 4. Make GetConfig, UpdateCfg, etc, properly fill out the WBEM_NOT_FOUND
  18. value on error.
  19. 5. Fake: Implement fHidden flag in NIC, set it in debugger in between
  20. operations, and make sure mgr behaves propertly when guids disappear
  21. (kerry problem). Make sure not-found interfaces are DELETED.
  22. 7. Make sure error is logged if operation doesn't succeed properly.
  23. -- on operation timeout, do a final read of properties and report any
  24. misconfig.
  25. 11. Change MsgBox to a Dlg -- in reporting problems, changes, etc.
  26. 12. Error messages -- make them more actionable.
  27. 13. Add list of changes to log.
  28. 14. Investigate nlbmgr's resource usage.
  29. -------------------
  30. - Error checking:
  31. CfgUtilAnalyze is failing because ded-ip matches cluster-ip -- but the
  32. UI simply reports invalid cluster specification.
  33. We need to do our own checks (in the UI) and report all discrepencies to
  34. the UI itself.
  35. - Cluster properties:
  36. -- define the right primitivies for analysis
  37. -- always show a specific host's properties
  38. -- if update failed, cluster properties will pick up the 1st
  39. host's properties that match.
  40. - Implement DetailsView.UpdateInterfaceInCluster
  41. - Cleanup log (including details lparam)
  42. - Host-properties:
  43. good defaults and preserve existing for host-port-rule-priorities.
  44. - Add support for multiple VIPSs:
  45. See "10/02/2001 JosephJ managing multiple VIPs"
  46. Some outstanding issues:
  47. - Create 10.0.0.11 cluster on cheese-x, try to add cheese-y to it --
  48. fails because it complains of invalid cluster spec.
  49. - In badcluster case, we don't populate the dedicated ip, then complain?
  50. - IP Address database (IP_INFO)
  51. - More corner cases
  52. DeleteInterface: if host is in an unreachable state, then prompt user and
  53. remove.
  54. - Handle keeping track of pending operations
  55. - Update:
  56. - display partial log output
  57. - Add to FakeNlbHostXxx apis -- update should return async.
  58. - Update phase 2:
  59. - Send proper status updates and log entries.
  60. - Do update in background thread.
  61. (Look for "Pending" under 09/19/2001 JosephJ Notes to self)
  62. - Deal with refreshes *while* there is pending activity.
  63. - Log: add critical section to document class -- protect changes
  64. to log and credentials.
  65. - Fix waitcuror in AddHost ??
  66. - Do basic checking -- same host can't be twice in same cluster,
  67. same cluster IP can't be in two clusters, etc.
  68. keep a global map of cluster IPs to interface IDs (see 09/14/2001
  69. log entry for details).
  70. - Put up message box warning the user that they are adding a NIC that has
  71. a different cluster IP -- for all versions, especially Add host.
  72. - Port Rules: track available port-rule-priorities, put correct defaults
  73. in apply_cluster_configuration and in the UI.
  74. - Preserve host-specific information as far as possible.
  75. - Report to log on error.
  76. - Implement rudimentary analyze functionality -- at least cluster IPs.
  77. - Encrypt passwords
  78. - Fix localization problems.
  79. --------
  80. - Add automatically querying for other cluster members.
  81. - Get rid of netcfg stuff in application.cpp -- use cfgutil stuff instead.
  82. Later:
  83. - Deal with HOST NAME change while running NLB manager.
  84. - Deal with Adapters coming and going while running NLB manager.
  85. - Deal with upgrades and/or re-installs of adapters -- GUIDs change but
  86. friendly name can be the same.
  87. - Track update generation -- warn if there's been a change.
  88. RELEASE NOTES:
  89. Port rules:
  90. Mode == Single -- priorities aren't created right.
  91. If you change a start/end ports, host-specific settings are lost.
  92. Mode = multiple -- if you hit "OK" in host-portrule-edit, then
  93. "equal" gets changed to 50.
  94. - documentation -- see "Documentation" below.
  95. - figure out how to de-initialize cleanly -- not clear how to do this with
  96. MFC apps -- use destructor
  97. ------------
  98. JosephJ 5/19/01 Code paths for main operations
  99. 1. Create New Cluster, add a host
  100. 2. Connect to existing cluster
  101. 3. Modify existing cluster's properties.
  102. 05/19/2001 JosephJ
  103. Cluster node in treview is created in several places --
  104. LeftView::OnWorldNewCluster.
  105. LeftView::OnWorldConnect
  106. LeftView::OnWorldConnectIndirect
  107. The name is set there (currently the cluster ip address)
  108. Application Initialization
  109. ---------------------------
  110. 05/20/2001 JosephJ
  111. When implementing the disclaimer dialog box, which has a checkbox...
  112. DDX macros don't work in the context of the Application::InitInstance
  113. function. So I had to use the CWnd::IsDlgButtonChecked macro.
  114. This works. HOWEVER the DDX macros now work too -- so I changed something
  115. and now it works.
  116. JosephJ 07/20/2001 Main aspects of new code
  117. --------------------------------------------
  118. INTERFACE (keys: GUID, friendly-name)
  119. HOST (keys: machine-name (if known), connection ip)
  120. CLUSTER (Keys: cluster name, cluster ip, internally-generated name)
  121. INTERFACE operations:
  122. Add/remove/refresh/update-props
  123. HOST operations:
  124. Add/remove/refresh/update-props
  125. CLUSTER operations:
  126. Validate/Add-host/remove-host/update-props
  127. Reorganization operations
  128. -------------------------
  129. Goals:
  130. 1. nlbmprov.dll can run on both w2k and xp
  131. 2. nlbmgr.exe can ron on w2k and xp and a client
  132. 3. tprov and nlbmgr share code in a common lib
  133. List of existing functionality:
  134. 1. Utilities that wrap wlbsctrl functionality
  135. 2. WMI client utilities
  136. 3. WMI server utilities
  137. 4. Self-contained utilities
  138. NLB manager considers a cluster to consist of a list of interfaces. An interface is idenified by (Machine, Adapter-GUID). The adapter's friendly name is used to
  139. resolve the adapter if the GUID doesn't exist (as can happen on a clean install). The friendly name is also used to identify the adapter in the UI.
  140. NLB manager does NOT index a cluster by the cluster IP address. NLB Manager supports having individual interfaces in the same cluster be configured with different cluster IP addresses. Likewise, the same cluster IP can occur on interfaces from different clusters. Of course these are cases of mis-configured clusters and NLB manager will report them as such and provides the user with UI to bring the clusters into a consistant state.
  141. NLB manager keeps track of the list of hosts it is managing. These hosts can
  142. be in an unavailable state (either due to connectivity problems or because the host has been shut down or re-purposed into some different configuration).
  143. The authoratitative state of NLB configuration data resides on the hosts. NLB manager's version of the cluster configuration is purely a cache.
  144. NLB manager persists the following information:
  145. 1. List of machines to manage, and how to get to them (connectivity information)
  146. 2. List of clusters managed (since cluster is defined as a list of interfaces, the list of interfaces associated with a cluster is persisted).
  147. When NLB manager is launched, it will retrieve this list of machines and
  148. clusters and attempt to connect to these machines and enumerate the adapters
  149. looking for the persisted list of interfaces. It will suitably display any
  150. missing hosts or interfaces (with appropriate icons). If it discovers hosts
  151. have been ADDED it will automically add them to the view. If it discovers
  152. that interfaces have
  153. been removed it will still list those interfaves, but with an appropriate
  154. icon to indicate that that interface apperas to be no longer part of the
  155. cluster. The user has the option of removing (from view) such interfaces.
  156. Initialization: From scratch, manage existing cluster.
  157. 1. User selects "Connect to Existing"
  158. 2. UI: bring up the connect/select-interface dialog.
  159. 3. Engine: connect to host, suck up information on ALL adapters in the
  160. specified host and enter the info into the engine's data structures.
  161. Issue: may need to do some resolving if info already exists.
  162. 4. UI: allow user to select the interface (only allow user to select interfaces
  163. which are bound to NLB.
  164. 5. Engine: Create a cluster with the specified host. Query the host for other
  165. cluster members. Get their machine-names (XP), host IDs and dedicated IPs.
  166. Create PLACEHOLDERS for those in the cluster data structure. Attempt to
  167. connect to each of these remote hosts. If we can't (either because we can't
  168. ping their machinenames (if specified) or dedicated-ip (if specified) or
  169. neither is specified we call back to UI to get a connection-string or to
  170. retry. For hosts that we DO connect to, we follow process #3 and add
  171. the interfaces to the cluster.
  172. 6. UI: creates cluster node in tree view, updates status
  173. (callbacks from Engine), bring up connect-to-host page for any additional
  174. hosts discovered.
  175. Initialization: From scratch, create new cluster.
  176. 1. UI: User selects "Configure New Cluster"
  177. 2. UI: #2 above, but modified to indicate we're creating a new cluster.
  178. 3. Engine: #3 above
  179. 4. UI: allow user to select interface (only allow user to select interfaces
  180. which are NOT bound to existing NLB manager clusters that NLB Manager
  181. already knows about). Bring up the cluster and host pages and let the user
  182. enter all the relevant information.
  183. 5. Engine: Configure the cluster on the specified host. If NLB HAS been bound
  184. (even if the rest failed), create a cluster node. Call back to UI for
  185. onging status.
  186. 6. UI: creates cluster node in tree view, update status.
  187. Add host to existing cluster
  188. 1. UI: let user select cluster-add host.
  189. 2. UI: #2 above, but modified to indicate "select interface to add to cluster".
  190. 3. Engine: #3 above
  191. 4. UI: Allow user to select any interface except ones that NLB manager already
  192. knows as being part of another cluster. Bring up warning dialog if
  193. NLB is already bound to the specified interface with different cluster-ip
  194. address.
  195. 5. Engine: #5 above.
  196. 6. UI: Add node to tree view.
  197. Refresh:
  198. 1. Go through host list, refreshing everything, updateing status and
  199. picking up new hosts.
  200. Retreiving persisted state on startup:
  201. 1. Create shell host and cluster data structures and tree view.
  202. 2. Do a refresh.
  203. Fixing up broken cluster:
  204. 1. Engine: maintains a fMisconfigured flag for the cluster and each interface.
  205. 2. UI: reflects this by icon state
  206. 3. UI: has "Analyze" menu option -- will re-do analysis
  207. 4. Engine: Analyze -- runs through existing cache, spitting out problems it
  208. finds to the log.
  209. 5. UI: Fixing cluster -- same as changing cluster properties.
  210. --------------------------------------------------
  211. 08/03/2001 JosephJ Gutting of NLBMGR.EXE -- Phase I (DONE)
  212. - Removed references to externall nlbmgr
  213. libraries (wmibase etc) and "reaching-over" includes, copying over
  214. files as required.
  215. - Removed calls to wmi-client side code.
  216. - Ensures that the resultant exe builds and comes up ok.
  217. 08/03/2001 JosephJ Differences between NLBMGR UI and NETCFGUI
  218. Cluster Properties Page -- OK
  219. Port Rules page (from cluster and host)
  220. - VIP missing
  221. - Port rule description missing
  222. - Note that load and priority are displayed differently by design
  223. Host Properties
  224. - MGR has a NIC combobox -- replace by static text FriendlyName
  225. - "Unique Host ID" change to "Unique host identifier"
  226. - New initial-host-state and persist-suspend UI.
  227. That's it!
  228. 08/03/2001 JosephJ Where do we store the "cluster" version of config info?
  229. Engine will keep a "cluster" version of the config info, along with which
  230. host it obtained it from and when, and whether/not it is modified but not
  231. committed.
  232. 08/03/2001 JosephJ Gutting of NLBMGR.EXE -- Phase II
  233. - Replacd different flavors of port rules by a single flavor. (DONE)
  234. - Get rid of tiny classes and their files -- consolidate. (DONE)
  235. 08/03/2001 JosephJ Moving to new infrastructure Phase I
  236. - define update methods to the LeftView and RightView
  237. - replace all places where these views are updated directly by calls
  238. to the engine (and migrate the code that updates the views to
  239. the update methods in LaftView and RightView) and callback handlers in
  240. the document.
  241. 08/04/2001 JosephJ Partial xml schema
  242. Its just hit me what a big bang for the buck it is to add a Load Template support to NLB to load a partial description of the configuration properties.
  243. This template will contain NO host-specific information (no priorities, load weights, dedicated IPs). It will optionally contain the cluster-ips, cluster-mode, and port-rules. For vip-specific portrules, the vip for each port rule is optional.
  244. What this lets us do (because theres no host-specific information, and things like cluster IP addresses are optional) is that we or others can publish template descriptions for things like load balance FTP traffic, etc and that xml file can be loaded AS IS into the UI!
  245. 08/04/2001 JosephJ New save/restore semantics...
  246. NLB Manager will let you load a list of hosts this is a simple text file listing hosts (ip addresses or machine names or FQDNs) one per line. This can be done via the command line or from the application menu.
  247. NLB Manager will attempt to connect to each of these hosts, reporting to the user if it cannot connect (thus reporting #1 in the list above).
  248. It will suck up information about ALL clusters installed on these hosts, and add them to the cluster tree view based on their IP address (there will be a special placeholder for 0.0.0.0 ip addresses, which can happen).
  249. It will report any inconsistencies in configuration or in the list of hosts visible from each node (this addresses #2). Note that if a botched update operation results in incorrect IP address assignments we will not detect this well just report the hosts under multiple clusters. However, read on
  250. [Well do this if we have time to spare, the prospect is unlikely, but schedules can change] NLB Manager will support a validate against snapshot command this command will take an xml file which has the information structured as I indicate below, and validates the current view against it.
  251. The Validate operation simply reports any discrepancies against the current view.
  252. There will be a save snapshot command to save the snapshot.
  253. 08/04/2001 JosephJ Add to server-side: ping ip addresses
  254. We should have an fNew flag, which if set, server-side will
  255. (a) check that the ip address is not already on any other nic in the
  256. machine
  257. (b) ping all the cluster ip addresses to make sure that they do not
  258. exist.
  259. 08/05/2001 Josephj Documentation: things to document
  260. - top level classes: application, document, engine, leftview, logview, etc.
  261. - flow of control for typical operations:
  262. - program initialization
  263. - adding new cluster
  264. - reading filelist
  265. - etc.
  266. - list of dialogs.
  267. - how to add a dialog.
  268. - how columns are added to the log and details list views.
  269. - how to add/remove those little "+"es in the tree view.
  270. - how to edit icons, issues with editing icons.
  271. - dialog operation -- DDX, message map, etc.
  272. - wait cursors: CCmdTarged::BeginWaitCursor/EndWaitCursor/RestoreWaitCursor
  273. - Menu operation -- dropdown and pop up -- how to enable/disable them,
  274. how to add items.
  275. See: 12/15/2001 How to add a menu item
  276. - ENGINEHANDLE -- its properties, design motivations.
  277. - Tab order -- see 09/17/2001 tab order entry.
  278. - Cool listctrl functions FindItem and GetNextItem
  279. - use of type-specific context-sensitive map:
  280. ConnectDialog::OnHelpInfo
  281. - Splitter windows and the organization of views -- see
  282. 10/27/2001 JosephJ Note on the layout of the views
  283. - Choosing good host-specific default properties when adding
  284. a new host to an existing cluster -- see
  285. 10/25/2001 JosephJ Host and Port priorities.
  286. - Managing virtual IP addresses, preserving order of ip addresses
  287. on individual hosts as far as possible -- see
  288. 10/07/2001 JosephJ managing multiple VIPs
  289. - Hooking TreeView double-click and key strokes -- see
  290. 11/13/2001 JosephJ Hooking TreeView double-click and key strokes
  291. 08/05/2001 JosephJ Location of msvc sample icons...
  292. C:\Program Files\Microsoft Visual Studio\Common\Graphics\Icons
  293. 08/05/2001 JosephJ setting the background on the icons
  294. The icons I
  295. 08/06/2001 JosephJ feedback from team at today's NLB meeting
  296. 1. Change "not bound to NLB" to be "NLB not bound to adapter"
  297. 2. Make Host Parameters go before Port Rules, to conform to cfgui.
  298. 3. Don't bother with restricting users from moving from page-to-page --
  299. just gray out the OK button until all parameters are filled in and put
  300. up an informational message box when focus is removed from the pane
  301. _snwprintf
  302. while leaving incomplete information specified.
  303. 4. Rename or get rid of "Event ID" -- Maybe change it to "Event No."
  304. 5. If we implement "check for duplicate IP in the network", then do this
  305. AFTER the dedicated IP has been set up.
  306. d:\nt\net\wlbs\nlbmgr\exe2\obj\i386;symsrv*symsrv.dll*\\symbols\symbols
  307. nlbmgr2!LeftView__OnWorldNewCluster
  308. ChildEBP RetAddr Args to Child
  309. 0006e57c 77d47797 00000040 40010444 010369e8 ntdll!KiUserExceptionDispatcher+0x4 (FPO: [2,0,0]) [D:\xpclient\base\ntos\rtl\i386\userdisp.asm @ 206]
  310. 0006e7d8 77357f04 010369e8 0006e7fc 00000000 USER32!RealDefWindowProcWorker+0x119 (FPO: [Non-Fpo])
  311. 0006e818 77357edb 0009d030 0009d2d8 00130958 COMCTL32!_CreatePageDialog+0x1e (FPO: [Non-Fpo]) [d:\xpclient\shell\comctl32\v5\prpage.c @ 575]
  312. 0006e838 77357d20 0009d030 0009d2d8 00130958 COMCTL32!_CreatePage+0x3d (FPO: [Non-Fpo]) [d:\xpclient\shell\comctl32\v5\prpage.c @ 708]
  313. 0006ea4c 77358f10 00130958 00000001 77d45944 COMCTL32!PageChange+0x99 (FPO: [2,124,3]) [d:\xpclient\shell\comctl32\v5\prsht.c @ 1909]
  314. 0006ee00 77358f2e 00130958 00000143 0009d030 COMCTL32!InitPropSheetDlg+0x9a2 (FPO: [2,230,3]) [d:\xpclient\shell\comctl32\v5\prsht.c @ 1562]
  315. 0006ea4c 77358f10 00130958 00000001 77d45944 COMCTL32!PropSheetDlgProc+0x463 (FPO: [Non-Fpo]) [d:\xpclient\shell\comctl32\v5\prsht.c @ 3461]
  316. 0006ee30 5ad94828 00000110 5adbd7b8 00000006 COMCTL32!InitPropSheetDlg+0x9a2 (FPO: [2,230,3]) [d:\xpclient\shell\comctl32\v5\prsht.c @ 1562]
  317. 0006ee44 5ad93c89 00aea3b8 00aea3a8 77357445 uxtheme!FindDdpHandler+0x18 (FPO: [3,0,0]) [d:\xpclient\shell\themes\uxtheme\handlers.cpp @ 561]
  318. 0006ee64 77d43a50 00130958 00000110 000b09c6 uxtheme!CThemeWnd__Release+0xe (FPO: [0,0,2]) [d:\xpclient\shell\themes\uxtheme\nctheme.cpp @ 1460]
  319. 0006eda8 77d43ee7 00aea3a8 00000000 0000000a USER32!_InternalCallWinProc+0x1b [D:\xpclient\windows\core\ntuser\client\i386\callproc.asm @ 102]
  320. ffffffec 00000000 00000000 00000000 00000000 USER32!GetWindowLongW+0x49 (FPO: [Non-Fpo]) [d:\xpclient\windows\core\ntuser\client\cltxt.h @ 430]
  321. :w
  322. \\netvbl2\sources\shell\comctl32\v5\prpage.c
  323. EditPropSheetTemplate:
  324. ...
  325. pdwStyle = &pDlgTemplate->style;
  326. ...
  327. *pdwStyle = dwNewStyle;
  328. It looks like this pDlgTemplate->style is not WRITEABLE, even though
  329. it appears readable...
  330. 0:000> dd 010369e8 l 1
  331. 010369e8 80c800c0
  332. 0:000> ed 010369e8 0
  333. ^ Memory access error in 'ed 010369e8 0'
  334. Looks like it's pointing into read-only resource data...
  335. 0:000> dc 010369e8
  336. 010369e8 80c800c0 00000000 00000013 00f00000 ................
  337. 010369f8 000000d7 00430000 0075006c 00740073 ......C.l.u.s.t.
  338. 01036a08 00720065 00500020 00720061 006d0061 e.r. .P.a.r.a.m.
  339. 01036a18 00740065 00720065 00000073 004d0008 e.t.e.r.s.....M.
  340. 01036a28 00200053 00680053 006c0065 0020006c S. .S.h.e.l.l. .
  341. 01036a38 006c0044 00000067 50000007 00000000 D.l.g......P....
  342. 01036a48 00070007 005400e2 ffff03e8 00430080 ......T.......C.
  343. 01036a58 0075006c 00740073 00720065 00260020 l.u.s.t.e.r. .&.
  344. 0:000> dc
  345. 01036a68 00500049 00430020 006e006f 00690066 I.P. .C.o.n.f.i.
  346. 01036a78 00750067 00610072 00690074 006e006f g.u.r.a.t.i.o.n.
  347. 01036a88 00000000 50020100 00000000 0015000f .......P........
  348. 08/09/2001 JosephJ problems with msdn
  349. tried searching for random -- very poor showing. Online help is vague,
  350. sync to toc doesn't work.
  351. also look for info on how to define string literals in visual basic.
  352. 08/09/2001 JosephJ The "copy operator" for vectors.
  353. Looks like vectors copy the dimensions, but their content's don't get copied
  354. if they're pointers -- this is reasonable, but it means that when
  355. crating a copy of, say CHostSpec, the vector of interface IDs will not be
  356. copied.
  357. 08/09/2001 JosephJ TODO: when copying NlbCfg we need to copy addresses
  358. appropriately.
  359. 08/09/2001 JosephJ determing the selection of a list ctrl:
  360. POSITION pos = m_portList.GetFirstSelectedItemPosition();
  361. if( pos == NULL ) return;
  362. int index = m_portList.GetNextSelectedItem( pos );
  363. m_portList.DeleteItem( index );
  364. 08/09/2001 JosephJ Allowing a full row of a multicol list view to be selected..
  365. m_portList.SetExtendedStyle( m_portList.GetExtendedStyle() | LVS_EX_FULLROWSELECT );
  366. 08/10/2001 JosephJ wlbsctrl.dll functions used in cfgutil.lib:
  367. CWlbsControl::Initialize
  368. CWlbsControl::CWlbsControl
  369. CWlbsControl::~CWlbsControl
  370. CWlbsControl::GetClusterFromAdapter
  371. CWlbsControl::ReInitialize
  372. CWlbsCluster::ReadConfig
  373. CWlbsCluster::CommitChanges
  374. CWlbsCluster::WriteConfig
  375. CWlbsControl::ValidateParam
  376. CWlbsControl::LocalClusterControl
  377. WlbsSetDefaults
  378. WlbsEnumPortRules
  379. WlbsAddPortRule
  380. WlbsDeleteAllPortRules
  381. 08/10/2001 JosephJ CPropertySheet -- has stuff about wizards in it!
  382. 08/10/2001 JosephJ ClusterPage directly handles OnNotify, so our
  383. virtual OnSetActive method doesn't get called.
  384. So I call OnSetActive from ClusterPage::OnNotify
  385. 08/12/2001 JosephJ Code that gets notified when focus is set on a control..
  386. Check out the following in hostpage.cpp ...
  387. ON_EN_SETFOCUS( IDC_EDIT_DED_MASK, OnGainFocusDedicatedMask )
  388. It fills out the control with defaults.
  389. 08/13/2001 JosephJ WlbsToNetcfgConfig (in netcfg\wlbscfg)
  390. 08/13/2001 JosephJ somehow m_pCommonClusterPage->Update()
  391. is not working when called after the do-modal is done.
  392. Also it looks like ClusterPage->OnOk is not called for wizard.
  393. Temporary workaround: added the following
  394. case PSN_WIZFINISH:
  395. void External_UpdateInfo(void) {UpdateInfo();}
  396. *pResult = m_pCommonClusterPage->OnKillActive(idCtrl, pNmhdr, *(BOOL*)pResult);
  397. this->mfn_SaveToNlbCfg();
  398. return TRUE;
  399. TODO: look for mfn_SaveToNlbCfg() -- clean up.
  400. 08/14/2001 JosephJ Wizards ....
  401. Override CPropertyPage::OnWizardFinish() (eg CHostPage)
  402. OR, if you're directly processing OnNotify (eg CClusterPage),
  403. you intercept the PSN_WIZFINISH (see 8/13/2001 log entry).
  404. 08/14/2001 JosephJ Trying to make the "Connect" button in ConnectDialog
  405. the default button.
  406. The API is CDialog::SetDefID( UINT nID );
  407. However it's tricky to figure out where to call this from.
  408. I was able to call it when the connect-to-host edit control gets
  409. called, and from SetActive, but neither gets called when the
  410. connect dialog is first put up. Calling DetDefID from OnInitDialog
  411. doesn't work either.
  412. Tried calling from ConnectDialog::OnActivate -- didn't work.
  413. ON_WM_ACTIVATE()
  414. ...
  415. void ConnectDialog::OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized )
  416. {
  417. this->SetDefID(IDC_BUTTON_CONNECT);
  418. }
  419. Actually the above were getting called in special circumstances, like
  420. if the windows is being redrawn, or we move back to to this page
  421. once there is already something else to focus on.
  422. Final solution: Hook the ON_EN_UPDATE messages!
  423. Works like a charm. I check the text length, and if it 0 or
  424. the string is all whitespace, I disable the button. It remains the
  425. default button, but I think that's ok.
  426. 08/14/2001 JosephJ engine notifying the ui about cluster/host arrival....
  427. New cluster:
  428. The moment the user clicks "Finish" in the new cluster wizard,
  429. we populate the tree view with the cluster and the
  430. first host -- they should both have the pending icons.
  431. We spit something out to the log.
  432. On successful completion, we change the icons.
  433. We spit something out to the log.
  434. On failed status it depends on what failed -- if nlb is bound, we
  435. show the cluster and host appropriately -- if things look ok we
  436. show it ok, otherwise with appropriate icons.
  437. We spit something out to the log.
  438. 08/15/2001 JosephJ Properly sizing the list columns.
  439. GeorgeJ suggested using GetClientRect to get the size of the list box,
  440. then partitioning that space appropriately.
  441. 08/15/2001 Displaying pending status0
  442. engine.cpp: implemented process_msgqueue() (got from msdn)
  443. and also CWaitCursor. Works like a charm!
  444. 09/12/2001 JosephJ
  445. Types of operations involving wizards/properties:
  446. NewCluster wizard
  447. ExistingCluster wizard
  448. AddHost wizard
  449. HostProperties propertysheet
  450. ClusterProperties propertysheet
  451. ClusterPage
  452. -- can be brought up in several modes:
  453. 1: NewCluster first page in wizard, all fields enabled
  454. 2: ClusterProperties all fields enabled
  455. 3: HostProperties all fields DISABLED
  456. Connect page:
  457. 1: NewCluster middle page in wizard
  458. 2: ExistingCluster first page in wizard
  459. 3: AddHost first page in wizard
  460. Hosts Properties:
  461. 1: NewCluster last page in wizard, all fields enabled
  462. 2. AddHost last page in wizard, all fields enabled
  463. 3: HostProperties all fields enabled
  464. PortRules:
  465. 1: NewCluster middle page in wizard, all fields enabled
  466. 2. AddHost middle page in wizard, only load weight enabled
  467. 3: HostProperties only load weight enabled
  468. 4: ClusterProperties all fields enabled, except load weight
  469. So we'll add an enum:
  470. OP_NEWCLUSTER
  471. OP_EXISTINGCLUSTER
  472. OP_ADDHOST
  473. OP_HOSTPROPERTIES
  474. OP_CLUSTERPROPERTIES
  475. That's passed into the constructor for each of the dialog pages.
  476. DOC bug _snprintf, _snwprintf -- mix up byte- and char- counts
  477. 09/14/2001 JosephJ Dealing with exlusive resources -- priorities, IPs, etc
  478. - CEngine: Define a private class CEngineCluster which encapsulates a
  479. CClusterSpec and also keeps a bitmap of taken host priorities,
  480. and a 32-bit array per-port-rule priorities. Also a ref count.
  481. The ehClusterSpec maps to this structure. Add access functions.
  482. - Pass in the cluster handle to the constructor for host properties.
  483. Host properties then gets access to the bitmap of taken properties.
  484. (Engine is responsible for maintaining the bitmap).
  485. IP addresses:
  486. Global map of ip addresses to it's properties.
  487. IP Properties: IsVip, IsDip, ehCluster, ehInterface
  488. Need to implement:
  489. HostPage::mfn_Load/SaveToNlbCfg()
  490. PortsPage::mfn_Load/SaveToNlbCfg()
  491. and call them for both property-sheet and wizard mode.
  492. Following still unacounted for...
  493. LOAD:
  494. NETCFG_WLBS_PORT_RULE port_rules[CVY_MAX_RULES];
  495. TODO: These fields are set if the user has changed the password -- in this
  496. case we need to send this to the host.
  497. bool fChangePassword;
  498. TCHAR szPassword[CVY_MAX_RCT_CODE + 1];
  499. SAVE:
  500. NETCFG_WLBS_PORT_RULE port_rules[CVY_MAX_RULES];
  501. TODO: These fields are set if the user has changed the password -- in this
  502. case we need to send this to the host.
  503. bool fChangePassword;
  504. TCHAR szPassword[CVY_MAX_RCT_CODE + 1];
  505. 09/14/2001 JosephJ GJack suggestions.
  506. 1. Make "create new cluster" -- adapter list can potentially show
  507. all nics. checkbox can restrict. If nic has a nlb cluster ip
  508. which matches the cluster ip, select it as the default,
  509. otherwise try to select the interface that appears to be on the
  510. same subnet as other interfaces already in the cluster.
  511. 09/15/2001 JosephJ Keeping nlbmgr's view upto date.
  512. 1. Everytime we present data to the viewer, it's always after
  513. refreshing it from the host. This is true even for cluster
  514. properties.
  515. So
  516. 1. Viewing/changing cluster properties:
  517. We refresh the cluster properties using the 1st host, then
  518. present it.
  519. 2. Viewing/changing host properties
  520. We get the latest view of the host's properties.
  521. 09/16/2001 JosephJ WLBS_PORT_RULE structure and constants
  522. typedef struct
  523. {
  524. TCHAR virtual_ip_addr [WLBS_MAX_CL_IP_ADDR + 1];
  525. DWORD start_port;
  526. DWORD end_port;
  527. DWORD mode; CVY_SINGLE CVY_MULTI CVY_NEVER
  528. DWORD protocol; CVY_TCP CVY_UDP CVY_TCP_UDP
  529. union
  530. {
  531. struct
  532. {
  533. DWORD priority;
  534. } single;
  535. struct
  536. {
  537. WORD equal_load; // 0/1
  538. WORD affinity;
  539. CVY_AFFINITY_NONE CVY_AFFINITY_SINGLE CVY_AFFINITY_CLASSC
  540. DWORD load; // 0...100
  541. } multi;
  542. } mode_data;
  543. }
  544. WLBS_PORT_RULE, * PWLBS_PORT_RULE;
  545. 09/16/2001 JosephJ Supplying unique host priorities and port-rule priorities
  546. CEngine should have two functions
  547. NLBERR GetAvailableHostPriorities(IN ehCluster, OUT ULONG &bitmap);
  548. NLBERR GetAvailablePortRulePriorities(
  549. IN ehCluster,
  550. IN LPCWSTR szVip,
  551. IN UINT start_port,
  552. OUT ULONG bitmap);
  553. These functions go through the list of interfaces/port-rules, and
  554. compile a bitmap of available priorities.
  555. 09/16/2001 JosephJ Merging cluster portrules into host's portrules
  556. For each rule in cluster
  557. if (find rule in host && makes sense)
  558. {
  559. copy priority or load
  560. }
  561. else
  562. {
  563. priority = host id
  564. load = 50
  565. }
  566. TODO: if you edit the start port, you will loose the interface-specific
  567. information. To fix this is not trivial -- need some kind of
  568. a key which is common between the cluster-specific version and
  569. the port-specific version.
  570. IDC_RADIO_EQUAL IDC_RADIO_UNEQUAL
  571. 09/17/2001 JosephJ Tab orders are important for radio buttons!
  572. I changed the tab order and radio buttons become uncoordinated --
  573. turns out that radio buttions must be in sequential tab order
  574. to have the toggle effect.
  575. 09/17/2001 JosephJ OnWizardFinish is NOT called unless the page is the
  576. last page. So for middle pages you need to do stuff in KillActive.
  577. 09/17/2001 JosephJ regexp searh for "if (x=y)" error
  578. if.*[^=!<>]=[^=]
  579. 09/17/2001 Connect dialog
  580. if (!existing)
  581. Show:
  582. "Interface Name|Interface IP |Cluster IP"
  583. 111.111.111.111|111.111.111.111
  584. 111.111.111.111|
  585. mfn_LookupClusterByIPLk(..., REF pECluster...)
  586. pECluster->m_cSpec.m_ehInterfaceIdList.push_back(ehIfId);
  587. 09/19/2001 JosephJ Notes to self
  588. NLBMGR.EXE
  589. Context sensitive help, UI-Ids match those in netcfgx.dll, help linkages.
  590. VIP (port rule) support
  591. Suspend-state and start-suspended support.
  592. Save log: use application event log
  593. Analyze cluster functionality see below
  594. Demo switch : put up message box.
  595. Add fLog field to connect host.
  596. LoadHost: connect (fLog=TRUE); then for each ehIF for bound Ifs, lookup
  597. clusterip, if new update cluster properties; then AddInterfaceToCluster.
  598. Add ehCluster to CInterfaceSpec.
  599. Analyze functionality:
  600. CNlbEngine::AnalyzeInterfaceClusterPropsLk(pISpec, pCSpec);
  601. CNlbEngine::AnalyzeIntefaceHostProps(pISpec, pOtherISpec); -- these also
  602. set/clear misconfig flag.
  603. CNlbEngine::GetIpInfo(szIp, pIP_INFO) (IP_INFO: ehCluster; ehConnectionIp;
  604. ehDedicatedIp; Call above from UI (in validate-data kill-active, etc.)
  605. ControlCluster:
  606. New methods: ControlCluster(szNIC, operation); ControlPort(szNIC, szVIP,
  607. szStartPort); But we'll need also to do query
  608. Pending operations
  609. [Also see 11/18/2001 JosephJ Pending operations -- take 2]
  610. 1. Don't keep any pointers to global dyamic data structures in the
  611. background thread.
  612. 2. Only one pending operation per interface. fPending flag tracks this.
  613. --Add a common superclass "CSpec" to CInterfaceSpec, CClusterSpec,
  614. and CHostSpec. CSpec has the following members:
  615. type,fPending,fDeinitializing,fCancelOperation,
  616. bstrOperationDescription (
  617. eg "Modifying cluster properties"
  618. "Modifying host properties"
  619. Engine method: mfn_Begin/EndOperation(ehObj)
  620. Each of these:
  621. Check global fDeinitializing flag is set
  622. Check if this object's fDeinitializing flag is set
  623. Check if this object's fPending flag is set
  624. Set the pending-flag and update the UI appropriately
  625. Bump up global head count
  626. On decrement, if unloading and zero
  627. - Get rid of CEngineCluster
  628. - Re-write validate cluster to use the type
  629. - Special checks:
  630. - If a cluster operation is pending, don't allow interface-level
  631. operations to start unless it's in the context of a cluster-wide
  632. operation.
  633. - If an interface operation is pending, don't allow a cluster-level
  634. operation to start.
  635. 5. UI: message box if attempt is made to change config while pending
  636. operation in progress.
  637. 6. For now: Always create thread for the update sequence:
  638. get-config,update, sleep,ping,get-result. Later use thread pool.
  639. 7. Log updates: pszLog maintained in pISpec � log new data
  640. (like tprov does)
  641. 8. Cancel operation: will stop the sleep-get-result loop in background
  642. thread.
  643. FAKE support:
  644. Update: Pending: fpending, hthread; Dummy log entries created;
  645. Per host delay + random failure
  646. Ping: per-host delay/ramdom variation (max is what ping arg specifies);
  647. ping host: return connection IP; ping ip any ip on interfaces that are
  648. marked as management capable
  649. All operations: per host connectivity delay (could be never i.e., host not
  650. reachable).
  651. Change BRIE, etc. to CHEESE1
  652. Schedule meeting/design review; show demo, docs, code, handout.
  653. 09/20/2001 JosephJ map wierdness.
  654. [see also 11/10/2001 JosephJ Redesign of the format of ENGINEHANDLE]
  655. When iterating through a map using "iterator", you can get entries
  656. which have never been set! The second value of these will be NULL.
  657. so if
  658. mymap[1] = p1;
  659. mymap[3] = p3;
  660. and you iterate, you'll get an iteration whose first is 2 and 2nd is NULL --
  661. even if you never explicitly inserted that. Pretty creepy.
  662. I wonder if you were to insert
  663. mymap[100000] = p100 and you iterate you'll get all values
  664. from 1 to 100000!
  665. GOT It: if you *ever* refer to the map in an expression -- like
  666. if (mymap[45] != NULL) {}
  667. then a map entry for that value is created.
  668. We do this in ValidateHandle. Todo: need to change validate handle so
  669. that it doesn't call the map functions.
  670. 09/20/2001 JosephJ plan for LoadHosts:
  671. LoadHost is implemented *outside* CNlbEngine
  672. pseudo code:
  673. LoadHost(pConnInfo)
  674. {
  675. gEngine.ConnectToHost(pConnInfo, REF ehHost);
  676. for (each interface ehIF in ehHost)
  677. {
  678. CInterfaceSpec *pISpec=NULL;
  679. gEngine.GetInterfaceSpec(ehIF, REF pISpec);
  680. if (pISpec->ehCluster == NULL)
  681. {
  682. // interface is not part of a cluster...
  683. szClusterIp = (extract cluster ip from pISpec.m_NlbConfig);
  684. gEngine.LookupClusterByIp(szClusterIp, TRUE, REF ehCluster, REF fIsNew);
  685. gEngine.AddInterfeToCluster(ehCluster, ehIF);
  686. if (fNew) {
  687. gEngine.UpdateCluster(ehCluster, pISpec.m_NlbConfig);
  688. }
  689. // TODO: call gEngine.AnalyzeXXX functions to report
  690. // misconfigured host: or conflicts with other
  691. // hosts and/or mismatches with cluster.
  692. }
  693. }
  694. }
  695. 09/20/2001 JosephJ -- used real NlbHostXXX functions for the first time
  696. -- simply commented out the call to NlbHostFake in CNlbEngine::Initialize
  697. -- worked like a charm, first time!!!!!!!!!
  698. -- now need to implement update config.
  699. 09/21/2001 JosephJ command line processing
  700. Created subclass CNlbMgrCommandLineInfo of CCommandLineInfo.
  701. This subclass overrides the ParseParam virtual function.
  702. Then from Application::InitInstance, call CWinApp::ParseCommandLine.
  703. I additinally overrode the function ProcessShellCommand. Turns out
  704. that you NEED to call CWinApp::ProcessShellCommand or else the
  705. application doesn't start. So I call CWinAPP::ProcessShellCommand from
  706. Application::ProcessShellCommand.
  707. 09/21/2001 JosephJ implemented command line processing
  708. There is a global instance of a new class (defined in document.h),
  709. called gCmdLineInfo. This class is filled in by the Application class.
  710. It includes the hostlist option.
  711. If you type nlbmgr2.exe /help, you'll get a little popup showing the
  712. command line options. They are:
  713. /demo run in demo mode
  714. /hostlist <file> load the hosts specified in <file>
  715. /help display this message
  716. If the /hostlist option is specified (along with <file>), then
  717. gCmdLine.m_bHostList is TRUE, and gCmdLine.m_bstrHostListFile contains
  718. the file name.
  719. So given that we'll need to load hosts both from LeftView and on
  720. initialization, the place to implement the loadhosts functionality is
  721. In the Document class. So add a public method
  722. Document::LoadHosts(szFileName) and a private method
  723. Document::mfn_LoadHost(szHostConnectiString).
  724. Call these methods from Document::Document (the last thing done).
  725. In both cases, LoadHostList may need to do stuff in a background
  726. thread -- as you suggested.
  727. 09/21/2001 JosephJ NewCluster: JosephJ show error if new cluste ip matches
  728. any ip on some other nic in host.
  729. 09/22/2001 JosephJ Making code organization of the host properties UI
  730. The host-specific properties are implemented in class HostPage,
  731. which is in hostpage.cpp and hostpage.h.
  732. Class HostPage is derived from CPropertyPage. It's resource ID
  733. is IDD_HOST_PAGE, defined in resource.h and resource.rc.
  734. The various controls are members of this class, for example:
  735. CIPAddressCtrl ipAddress;
  736. CIPAddressCtrl subnetMask;
  737. CButton initialState;
  738. The mapping between the UI and these controls is "automagically"
  739. done in overridden virtual functino DoDataExchange:
  740. HostPage::DoDataExchange( CDataExchange* pDX )
  741. {
  742. DDX_Control( pDX, IDC_EDIT_PRI, priority );
  743. DDX_Control( pDX, IDC_CHECK_ACTIVE, initialState );
  744. DDX_Control( pDX, IDC_EDIT_DED_IP, ipAddress );
  745. DDX_Control( pDX, IDC_EDIT_DED_MASK, subnetMask );
  746. }
  747. The initial state of these controls is set in the function
  748. mfn_LoadFromNlbCfg. On losing focus or the ok button being pressed,
  749. the state of the controls are validated using mfn_ValidateData
  750. (which is partially disabled because it had some old code),
  751. and saved using mfn_SaveToNlbCfg.
  752. mfn_LoadFromNlbCfg and mfn_SaveToNlbCfg load from/save to a
  753. class of type NLB_EXTENDED_CLUSTER_CONFIGURATION,
  754. which is defined in nlbmgr\inc\cfgutil.h, and implemented in
  755. nlbmgr\cfgutillib\extcfg.cpp (goes into static library cfgutil.lib).
  756. Now NLB_EXTENDED_CLUSTER_CONFIGURATION as not particularly elegant.
  757. It includes as it's members the list of IP addresses bound to the NIC,
  758. as well as NlbParams, which is of type WLBS_REG_PARAMS.
  759. The class is messy, it's get/set functions ugly, and it's use
  760. of WLBS_REG_PARAMS unfortunate, because we don't use many of the
  761. arcane fields of WLBS_REG_PARAMS, and we are forced to use the
  762. WlbsEnumPortRules, etc functions.
  763. Anyway, there are access methods in the class for various members,
  764. although since the members are not private, I sometimes access
  765. members directly, for example (from hostpage.cpp):
  766. _bstr_t bstrDedIp = (LPCWSTR) m_pNlbCfg->NlbParams.ded_ip_addr;
  767. It definately would be good to cleanup this class, but it's used
  768. pretty extensively across all nlbmgr code (including the provider
  769. and the console app), so it's nontrivial to change.
  770. Getting back to HostPage, the load/save functions (mfn_Load/Save...)
  771. access member m_pNlbCfg of type NLB_EXTENDED_CLUSTER_CONFIGURATION.
  772. This pointer is initialized in the constructor of class NlbHost.
  773. 09/22/2001 JosephJ Making code organization of the ports-related UI
  774. [Read note above for reference to location of resource ids,
  775. and NLB_EXTENDED_CLUSTER_CONFIGURATION, DoDataExchange,
  776. and semantics of mfn_LoadFrom/SaveToNlbCfg.]
  777. There are 3 ports-related property-pages/dialogs. These are
  778. - PortsPage: public CPropertyPage -- list of ports
  779. - ClusterPortsDlg: public CDialog -- cluster-ver of edit port dlg
  780. - HostPortsDlg: public CDialog -- host-ver of edit port dlg.
  781. Details ...
  782. PortsPage: public CPropertyPage -- this contains the list
  783. of ports with the add/edit/remove buttons.
  784. This class can be invoked in "cluster mode" or in "host
  785. mode" -- the fIsClusterLevel argument passed into
  786. its constructor indicates which.
  787. The resource ID is IDD_DIALOG_PORTS.
  788. Depending on fIsClusterLeve, the class selectively enables/
  789. disables certain elements.
  790. As with HostPage, the controls are members, which interfact
  791. "automagically" with the UI, using DoDataExchange, and these
  792. controls are loaded/saved using mfn_LoadFrom/SaveToNlbCfg.
  793. ClusterPortsDlg: public CDialog -- launched to edit a portrule
  794. from a cluster perspective -- only cluster wide changes are
  795. allowed.
  796. Resource ID: IDD_DIALOG_PORT_RULE_PROP_CLUSTER
  797. UNLIKE PortsPage, this class doesn't use dde to
  798. map ui to member controls -- instead it uses win32 apis,
  799. for example:
  800. :SendDlgItemMessage(m_hWnd, IDC_EDIT_MULTI, ....);
  801. Also it loads/saves UI state to/from member
  802. m_portData, which is passed by REFERENCE to its
  803. constructor. The parent window (expected to be of type
  804. PortsPage) is also passed into the constructor.
  805. Stuff is loaded from m_portData by method SetControlData,
  806. and saved to m_portData by method OnOk.
  807. m_portData is of type PortsPage::PortData,
  808. which is simply:
  809. struct PortData
  810. {
  811. PortData();
  812. DWORD key;
  813. _bstr_t start_port;
  814. _bstr_t end_port;
  815. _bstr_t protocol;
  816. _bstr_t mode;
  817. _bstr_t priority;
  818. _bstr_t load;
  819. _bstr_t affinity;
  820. };
  821. Historical note: this code has been modified from the
  822. original version, not re-written. In the original version
  823. there were subclasses for each type of port rule, a bunch
  824. of methods for handling each type and so forth.
  825. Also it's unfortunate that this is "yet another" data
  826. structure for port rule info.
  827. HostPortsDlg: public CDialog -- launched to edit a portrule
  828. from a host perspective -- only host-specific properties can
  829. be changed.
  830. Resource ID: IDD_DIALOG_PORT_RULE_PROP_HOSTS
  831. Its orginaziation is very similar to ClusterPortsDlg above.
  832. 09/22/2001 JosephJ details on the "LogView"
  833. The lower region of nlbmgr is maintained by an instance of
  834. class LogView : public CListView. The class is implemented in
  835. logview.h and logview.cpp.
  836. It's constructor gets called (probably) in the context of
  837. Application::InitInstance, as does it's initialization function,
  838. LogView::OnInitialUpdate. In OnInitialUpdate, LogView
  839. inserts a bunch of columns into it's list control, and
  840. adds a starting entry (which needs to be localized!)
  841. "NLB Manager session started".
  842. Thereafter, the only interesting thing it does, is to get
  843. calls to it's LogString function from the document instance.
  844. The LogString prototype is:
  845. void
  846. LogString(
  847. IN IUICallbacks::LogEntryType Type,
  848. IN const wchar_t *szCluster, OPTIONAL
  849. IN const wchar_t *szHost, OPTIONAL
  850. IN const wchar_t *szText
  851. );
  852. LogString adds an entry to the log, with an icon determined by
  853. the value of "Type".
  854. TODO: how do we save logs -- by symultaneously logging to
  855. the application event log or by adding a "save log" feature
  856. (the menu item "save log" is already present, and does nothing
  857. currently). If we decide to save the log, we need to decide
  858. on a format: plain text or simple xml like:
  859. <NLBMGRLOG>
  860. <EVENT
  861. id=xxx LEVEL=INFO
  862. year=xxx month=xxx day=xxx hour=xxx minute=xxx second=xxx>
  863. <TITLE>NLB Manager session started</TITLE>
  864. </EVENT>
  865. </NLBMGRLOG>
  866. Of course we want to avoid creating ad hoc formats!
  867. paramp -> i_convert_mac = TRUE; // TODO
  868. 09/15/01, shouse
  869. Context sensitive help has been attached to all known dialogs.
  870. For the three NLB netcfg UI clones, all help appears to work
  871. except for the "Cluster IP address" group box on the Add/Edit
  872. port rule (properties) page - this is also missing in the
  873. netcfg UI.
  874. To add the hook for context sensitive help on other dialogs,
  875. you need to add a help handler to the class - see hostpage.cpp
  876. and hostpage.h for an example (OnHelpInfo and OnContextMenu).
  877. Further, you need to create a table of mappings from UI IDs
  878. to help IDs - in NLB we always use the UI ID as the host ID
  879. to simplify things. See hostpage.h for an example table.
  880. Then, have the UI text people (Joe Holliday) write the help
  881. for the needed components and give him the UI ID to hook into.
  882. Joe will send a private wlbs.hlp to test with (place this
  883. file in %WINDIR%\help\. Be sure to review and edit the help -
  884. Joe is VERY open to our suggestions on wording and content.
  885. Support for the new initial host state, persisted states and
  886. per-VIP port rules has been added to the appropriate dialogs.
  887. Most dialogs were reviewed for layout and text and were mod-
  888. ified - several new dialogs, or some legacy dialogs that may
  889. not be used any more were not updated yet.
  890. Also, the equal checkbox has been added to the cluster-level
  891. port rule properties dialog. At this time, the host-level
  892. can not change this setting - if the rule is equal, the host
  893. can not make it unequal and set a load weight (the rule must
  894. be changed to unequal at the cluster-level first), so if we
  895. want hosts to be able to change this, changes will be necess-
  896. ary in at least clusterportsdlg.cpp.
  897. 09/25/01 karthicn : Notes to self
  898. The FinalInitialize function (in document.cpp) is called in a background
  899. thread from Document::registerLeftView. The only thing that FinalInitialize
  900. does is : If a file name is provided in the command line, it reads host
  901. names from the file connects to them. May want to check if the file name is
  902. specified in the command line before spawning off the thread.
  903. 09/26/2001 Credentials UI -- the proper way of managing utilities.
  904. From Mike Lai of the secure windows initiative team (http://swiweb,
  905. email: switeam): "Please use Cred UI, Cred Mgr in LSA makes sure the
  906. sensitive data is protected via LsaProtectMemory/LsaEncryptMemory which
  907. is encrypting the data while the data is memory."
  908. John Franco in MSCS (Dave Potter's) team pointed me to http://benhutzdev,
  909. which contains API documentation for the Credentials API. From those
  910. docs, it appears that the APIs I nead to call are:
  911. - CredUIPromptForCredentials with the CREDUI_FLAGS_GENERIC_CREDENTIALS
  912. - CredWrite specifying CRED_TYPE_DOMAIN_VISIBLE_PASSWORD.
  913. - CredRead
  914. Additinally, it appears that I don't need to call CredWrite if I specify
  915. the CREDUI_FLAGS_PERSIST flag in CredUIPromptForCredentials.
  916. I've asked John Franco for sample code.
  917. From: Cliff Van Dyke
  918. Sent: Wednesday, September 26, 2001 10:17 AM
  919. Subject: RE: Question on how to safely cache user credentials
  920. in a user-mode program.
  921. OK. Here's my recommendation.
  922. You should you credui to prompt for the credential since we want to have
  923. that as the only UI being used. You shouldn't use credman to store the cred
  924. since credman creds are used by all processes and not just yours.
  925. If NLB manager isn't the process doing the prompting, you should encrypt the
  926. password using RtlEncryptMemory with the RTL_ENCRYPT_OPTION_CROSS_PROCESS
  927. flag as you pass the password between processes.
  928. In the NLB manager, while the password isn't actively being used, you should
  929. encrypt the password using RtlEncryptMemory with no special flags.
  930. Any buffer that temporarily contains the password should be zeroes as soon
  931. as you're done with it. SwiTeam should be able to point you to a web page
  932. with more detailed related info.
  933. In a future release, the "password" returned to you from credui will be a
  934. "handle" to data stored more securely. That handle will be accepted as the
  935. password parameter to any API that uses NTLM or Kerberos.
  936. 9/27/01 ChrisDar
  937. Things that still need to be fixed with logging:
  938. 1. Macro var names MAXFILEPATHLEN and MAXSTRINGLEN are hokey and should be changed. Also value should be reviewed.
  939. 2. Currently logging class is called even when logging is not enabled because internal to method is where enabled flag is checked. Need to move the check into LogView::LogString for efficiency.
  940. 3. Related to 2., LogView gets back LOG_RESULT enum for some calls to document class to tell it what error to report in error message dialog. I realize now that this can be done in the document class itslef. This should changed so that the LogView class just knows an error occurred and can react as needed. The dialog should be popped in the document class.
  941. 4. When reading log file name from registry, we don't truncate but give an error if file name is too long. Need to figure out how to read N bytes even if there is more available.
  942. 10/07/2001 Got the following error in setupapi.log during an install...
  943. Build 3563.Lab03_N.011003-1919
  944. [2001/10/05 15:40:37 1740.157 Driver Install]
  945. #-019 Searching for hardware ID(s): ms_wlbsmp
  946. #-198 Command line processed: D:\WHISTLER\System32\wbem\wmiprvse.exe
  947. #I022 Found "ms_wlbsmp" in D:\WHISTLER\inf\netwlbsm.inf;
  948. Device: "Network Load Balancing Filter Device";
  949. Driver: "Network Load Balancing Filter Device";
  950. Provider: "Microsoft"; Mfg: "Microsoft"; Section name: "WLBSMP.ndi".
  951. #I023 Actual install section: [WLBSMP.ndi]. Rank: 0x00000000.
  952. Effective driver date: 07/01/2001.
  953. #I063 Selected driver installs from section [WLBSMP.ndi] in
  954. "d:\whistler\inf\netwlbsm.inf".
  955. #I320 Class GUID of device remains: {4D36E972-E325-11CE-BFC1-08002BE10318}.
  956. #I060 Set selected driver.
  957. #I058 Selected best compatible driver.
  958. #-166 Device install function: DIF_INSTALLDEVICEFILES.
  959. #I124 Doing copy-only install of "ROOT\MS_WLBSMP\0000".
  960. #-166 Device install function: DIF_REGISTER_COINSTALLERS.
  961. #I056 Coinstallers registered.
  962. #-166 Device install function: DIF_INSTALLINTERFACES.
  963. #-011 Installing section [WLBSMP.ndi.Interfaces] from
  964. "d:\whistler\inf\netwlbsm.inf".
  965. #I054 Interfaces installed.
  966. #-166 Device install function: DIF_INSTALLDEVICE.
  967. #I123 Doing full install of "ROOT\MS_WLBSMP\0000".
  968. #-035 Processing service Add/Delete section [WLBSMP.ndi.Services].
  969. #E279 Add Service: Failed to create service "WLBS".
  970. Error 1021: Cannot create a stable subkey under a volatile parent key.
  971. #E033 Error 1021: Cannot create a stable subkey under a volatile parent key.
  972. #E275 Error while installing services.
  973. Error 1021: Cannot create a stable subkey under a volatile parent key.
  974. #E122 Device install failed.
  975. Error 1021: Cannot create a stable subkey under a volatile parent key.
  976. #E154 Class installer failed.
  977. Error 1021: Cannot create a stable subkey under a volatile parent key.
  978. #-166 Device install function: DIF_REMOVE.
  979. #I289 Removing device "ROOT\MS_WLBSMP\0000".
  980. #I048 Device removed.
  981. 10/07/2001 JosephJ managing multiple VIPs
  982. - New cluster:
  983. NlbCfg list includes only primary vip.
  984. - Existing cluster:
  985. NlbCfg list includes all ips in tcpip except dip, if present.
  986. - Per-host cluster info:
  987. NlbCfg list includes all ips in tcpip except dip, if present.
  988. So to simply the vipslist code, it'll alwaws exclude the dip from the
  989. list, if it sees a non-null dip.
  990. Todo:
  991. 1. vipspage: reload on set-active, save on kill active.
  992. reload:
  993. Clear and re-build list view
  994. save:
  995. if list view modified:
  996. re-populate addresses, adding dip and then vip at head of the
  997. list.
  998. 2. vipspage: add:
  999. call gEngine.ValidateAddress(
  1000. szAddress, ehCluster, ehHost, cip/pprvip/dip, out szErr);
  1001. 3. Apply-to-per-host:
  1002. - for each ip in old list
  1003. if found in new list add to tmp list
  1004. (this preserves the order of old addresses)
  1005. - for each ip in new list
  1006. if found in tmp list
  1007. set cursor to this location in tmp list
  1008. else
  1009. insert after cursor,
  1010. set cursor to this location in tmp list
  1011. Add new host/connect to existing:
  1012. - The trick here is that we need to preserve the existing
  1013. host-specific settings as far as possible (ONLY if the NIC already
  1014. has the *save* cluster IP). The user can select
  1015. an arbitrary NIC -- we need to use that's NIC's host-specific settings.
  1016. If the user goes back to the connect page and selects a different NIC,
  1017. we need to switch to the new NIC's settings.
  1018. - On startup, if a NIC has the same IP address, we make that the default
  1019. selection.
  1020. - So each time the NIC selection changes
  1021. - Make a copy of of the NIC's current settings
  1022. - If bound to NLB
  1023. - if it has a different IP address: put warning msg
  1024. - We apply the cluster-wide properties in the current m_pNlbCfg
  1025. (which is the cluster's version) to the copy of the NIC's current
  1026. settings.
  1027. - We copy the result back to m_pNlbCfg.
  1028. 10/25/2001 JosephJ Host and Port priorities.
  1029. Because NLB manager allows multiple hosts to have pending activity
  1030. at the same time, we need to keep a list of pending
  1031. host priorities and port-priorities. The UNION of current and pending
  1032. host priorities and port-priorities is used to get the list of currently
  1033. taken priorities -- the inverse consists of available priorities.
  1034. This inverse set *could* be empty -- tough luck.
  1035. So each cluster in the engine needs to keep:
  1036. (a) bitmap of pending host ids
  1037. (b) map[start-port] of bitmaps of pending port-rule ids
  1038. NewCluster
  1039. AddHost
  1040. HostProperties
  1041. ConnectDialog:
  1042. Constructor:
  1043. AddHost: set the host priority in m_pNlbCfg to a good default,
  1044. taking into account available hosts in the cluster (ask
  1045. engine). Likewise, set the single-host port priorities
  1046. appropriately (ask engine).
  1047. NewCluster: may as well do the same as above, so we don't
  1048. differentiate.
  1049. NONONO: instead, changed this so that where add host is CALLED
  1050. (in leftview) we set up the defaults appropriately.
  1051. OnButtonConnect:
  1052. NewCluster:
  1053. AddHost:
  1054. if (IF already bound to cluster with same IP)
  1055. {
  1056. apply cluster properties to existing interface props, save
  1057. the config to m_pNlbCfg.
  1058. }
  1059. OnSelChange:
  1060. (we don't allow changing if there exists an IF which is already
  1061. bound to the clsuter (i.e. cluster IP matches).
  1062. NewCluster:
  1063. AddHost:
  1064. don't need to modify m_pNlbCfg.
  1065. HostPage:
  1066. Constructor:
  1067. if (!new cluster)
  1068. {
  1069. -- initialize host prority bitmap with
  1070. currently available priorities (ask engine)
  1071. -- initialize array of port-rule-priorities bitmap.
  1072. }
  1073. On mfn_LoadFromNlbCfg:
  1074. populate the host priorities listbox with list of available
  1075. host priorities + m_pNlbCfg->host-priority, select the
  1076. current value of the latter.
  1077. On mfn_SaveToNlbCfg:
  1078. save the selected host priority to m_pNlbCfg->host-priority.
  1079. HostPortsDialog:
  1080. SetControlData:
  1081. if (single-host)
  1082. {
  1083. Get list of available priorities for this port rule (ask
  1084. engine).
  1085. }
  1086. Fill out list box accordingly.
  1087. Q: What if on new-cluster, user specifies port rules, connect, select an
  1088. IF, go back to the port rules and change them around?
  1089. A: Since its a new cluster, all port priorities are available at this point.
  1090. 10/27/2001 JosephJ Note on the layout of the views
  1091. This is done in MainForm.CPP -- in class MainForm.
  1092. The class has two splitter windows (CSplitterWnd) splitterWindow,
  1093. and splitterWindow2. The individual views are refered by a
  1094. coordinate system --
  1095. splitterWindow.CreateStatic( this, 2, 1 );
  1096. <-- creates a static splitter window with two rows and one column.
  1097. splitterWindow2.CreateStatic( &splitterWindow, 1, 2,
  1098. WS_CHILD | WS_VISIBLE | WS_BORDER,
  1099. splitterWindow.IdFromRowCol( 0, 0 )
  1100. );
  1101. <-- creates a CHILD splitter window, with one row and two columns
  1102. (the 1,2 as second and third args)
  1103. The location of the child in the PARENT splitter window
  1104. is (0,0) -- the call to splitterWindow.IdFromRowCol(0, 0);
  1105. splitterWindow2.CreateView( 0,
  1106. 0,
  1107. RUNTIME_CLASS( LeftView ),
  1108. CSize( 0, 0 ),
  1109. pContext );
  1110. <--- says to create an instance of LeftView at coordinate
  1111. (0,0) of the CHILD splitter window.
  1112. Etc...
  1113. 10/27/2001 JosephJ Note on handling menu controls
  1114. Moved handling of menu controls from LeftView to MainForm,
  1115. because left view wasn't getting the control messages (naturally)
  1116. when the focus was not on the left view.
  1117. Currently MainForm calls left view's public methods for control
  1118. operations -- strictly speaking these methods also need to migrate
  1119. over to MainForm -- left view should just be consulted on the
  1120. currently selected item. However, in the interest of minimizing
  1121. code changes, the implementation of the controls remains in LeftView.
  1122. So with this change the menu items work even if the focus is not
  1123. on the left view.
  1124. 10/30/2001 JosephJ
  1125. Cases to test:
  1126. 1. Connect to existing:
  1127. a: 0 nics are bound to cluster OK
  1128. b: 1 nics is bound to cluster OK
  1129. c: 2 nics are bound to clusters OK if no change in sel
  1130. e: switch NIC selections and verify things work. BUG
  1131. f: switch host names and verify things work. OK (recheck)
  1132. 2. New cluster:
  1133. a: 0 nics are bound to cluster
  1134. b: 1 nic is bound to cluster (a different cluster)
  1135. c: 1 nics are bound to cluster (same cluster)
  1136. d: 2 nics are bound to cluster (one same one different)
  1137. e: switch NIC selections and verify things work.
  1138. f: switch host names and verify things work.
  1139. If same: check that all host-specific properties are preserved.
  1140. (including null ded-ip if specified)
  1141. If not same: check that dedicated IP address is filled in:
  1142. - with 1st IP address on NIC
  1143. 3. Add Host:
  1144. a: 0 nics are bound to cluster
  1145. b: 1 nic is bound to cluster (a different cluster)
  1146. BUG -- priority clashes with existing
  1147. c: 1 nics are bound to cluster (same cluster)
  1148. d: 2 nics are bound to cluster (one same one different)
  1149. e: switch NIC selections and verify things work.
  1150. f: switch host names and verify things work.
  1151. BUGS that were fixed recently:
  1152. x AV when connecting (via new cluster) to an existing cluster, then
  1153. moving back and forth between pages. Via add host also, I think.
  1154. - Seems to be fixed by taking out a reference to uninitialized memory.
  1155. x In connect-to-existing, if 2 nics are bound, on selecting
  1156. a nic we get the "next" button, not finished button.
  1157. x In new-cluster UI, got some host-priorities blanked out -- should
  1158. be all available? Once cluster was created, didn't see this problem.
  1159. x In add host the host priority was 1 -- clashes with the first host.
  1160. 10/30/2001 JosephJ Handling the "F5" key
  1161. The CWnd method is OnKeyDown, need to check that the
  1162. first arg (nChar) is equal to VK_F5.
  1163. I tried getting mainform to take the F5, but its OnKeyDown afx handler
  1164. was not getting called. I then added the handler to LeftView instead and
  1165. it works -- need to add the afx handler as well as mention it in
  1166. the message map -- search for OnKeyDown in leftview.cpp.
  1167. 10/31/2001 JosephJ handling the double clicking of list view items (logview)
  1168. Add the following message handler to the listview:
  1169. ON_NOTIFY_REFLECT(NM_DBLCLK, OnDoubleClick)
  1170. In OnDoubleClick, cast the first arg to LPNMLISTVIEW.
  1171. LPNMLISTVIEW.iItem is the list view item index (zero based).
  1172. See LogView::OnDoubleClick for details.
  1173. 11/05/2001 JosephJ trying to get the right (details) view to have a caption:
  1174. Setting the WS_CAPTION windows style didn't work -- produced a large blue
  1175. caption with rounded borders, and allowed resizing within the application.
  1176. I tried other combinations of the WBL_STYLE property -- no luck.
  1177. I then tried putting an additional splitter window above the existing one
  1178. -- this produced a movable border between the two windows -- I didn't want
  1179. any border -- couldn't figure out how to get rid of the border.
  1180. Finally tried using a CFormView -- this appears to be the way to go.
  1181. Need to specify the dilog ID in the RC file, and this dialog should have
  1182. only WS_CHILD as it's window properties.
  1183. 11/05/01 update:
  1184. The details view comes up with the valid dialog template.
  1185. HOWEVER it was not being filled out -- inserting columns and items etc
  1186. into the list control wasn't being updated in the uI.
  1187. Fix: Call UpdateData(FALSE); in OnInitialUpdate -- this is mentioned
  1188. in Chapter fifteen (Separating the Document from Its View),
  1189. step #8 (Edit the file Ex15aView.cpp, pp 356), in the book
  1190. Inside Visual C++ 4th ed (MS Press).
  1191. Apparantly unlike true Dialogs, the CFormView class doesn't call
  1192. UpdateData automatically, so we have to call it ourselves. Go Figure
  1193. (took me a while to figure this out).
  1194. 11/05/2001 JosephJ Details view: selectively displaying the icons:
  1195. If you don't want to display the icons next to each item,
  1196. call SetImageList(NULL,...). Otherwise the first icon of the previously
  1197. used image list is used whether you want it or not. For example,
  1198. when listing the port rules, the image list for the cluster view was
  1199. being used.
  1200. 11/10/2001 JosephJ Redesign of the format of ENGINEHANDLE
  1201. See "09/20/2001 JosephJ map wierdness."
  1202. 1. Keep separate counters for each kind of handle.
  1203. 2. First 2 bits of ENGINEHANDLE define type of handle.
  1204. 0 -- invalid
  1205. 1 -- interface
  1206. 2 -- host
  1207. 3 -- cluster
  1208. Implemented the above, except that I keep a single counter for
  1209. simplicity, through we'll run out of handles after 1billion creations
  1210. vs 4 billion.
  1211. 11/13/2001 JosephJ more things to test: picking username and pwd in connect
  1212. Connecting to machine -- we look up the connection string -- if we find
  1213. a match, we'll use that machine's username and password, rather than
  1214. the default.
  1215. 11/13/2001 JosephJ Hooking TreeView double-click and key strokes
  1216. DoubleClick:
  1217. Message map: ON_WM_LBUTTONDBLCLK()
  1218. afx function: OnLButtonDblClk( UINT nFlags, CPoint point )
  1219. Keystrokes:
  1220. Message map: ON_WM_KEYDOWN()
  1221. afx function: LeftView::OnKeyDown( UINT nChar, UINT nRepCnt, ...);
  1222. 11/18/2001 JosephJ Pending operations -- take 2
  1223. [See 09/19/2001 JosephJ Notes to self]
  1224. - Engine has private method: mfn_BeginOperationLk(ENGINEHANDLE ehObj,
  1225. bstrOperation, OUT bstrPendingOp).
  1226. if ehObj is type cluster:
  1227. - we'll first check if there's any pending operation on this cluster, if
  1228. not we mark cluster started
  1229. - we'll then try to start this operation on all the member interfaces.
  1230. - if failure, we stop all we tried to start above and return failure,
  1231. filling bstrPendingOp with the description of any pending op that
  1232. caused the failure.
  1233. if ehObj is type interface:
  1234. - we'll first check if there's any pending operation on this interface,
  1235. if not we mark interface op started.
  1236. - we'll then try to start this operation on the host
  1237. - if failure, we stop all we tried to start above and return failure,
  1238. filling bstrPendingOp with the description of any pending op that
  1239. caused the failure.
  1240. if ehObj is type host:
  1241. - we'll first check if there's any pending operation on this host,
  1242. if not we mark host op started.
  1243. - on failure, we'll bstrPendingOp with the description of any pending
  1244. op that caused the failure.
  1245. EXCEPTION: if the operation we're asked to start is already started,
  1246. we won't fail -- instead we bump up an internal repeat count.
  1247. This is so that we can start a cluster-wide operation and as part of
  1248. that operation start a host or interface operation without the latter
  1249. failing claiming that an operation is already pending.
  1250. CAUTION: need to make sure that interfaces aren't added to or removed
  1251. from clusters
  1252. or hosts while a cluster-wide operation or a host-wide operation is
  1253. pending. This is so that the correct list of interfaces are stopped
  1254. when the cluster/host operation is stopped.
  1255. mfn_EndOperationLk is the inverse of mfn_BeginOperationLk.
  1256. Helper class Operation below will help with the implementation.
  1257. EXTRA:
  1258. need way to (a) cancel pending operations and
  1259. (b) disallow new pending operations and
  1260. (c) enumerate pending operations --
  1261. This is mainly to handle proper cleanup on existing the program.
  1262. class Operation
  1263. {
  1264. ...
  1265. public:
  1266. static OPERATIONHANDLE NewOperationHandle();
  1267. static void ReleaseOperationHandle(OPERATIONHANDLE);
  1268. NLBERR
  1269. Start(OPERATIONHANDLE oh, _bstr_t bstrDescription, OUT pendingDescr);
  1270. void
  1271. Stop(OPERATIONHANDLE oh);
  1272. private:
  1273. static UINT next_handle;
  1274. _bstr_t m_bstrDescritpion;
  1275. OPERATIONHANDLE m_ohCurrent;
  1276. UINT m_uRepeatCount;
  1277. }
  1278. 12/12/2001 KarthicN Redundant calls from ClusterPage.cpp & HostPage.cpp
  1279. ClusterPage.cpp :
  1280. During cluster creation, ie. wizard mode
  1281. ClusterPage::OnNotify is called with PSN_KILLACTIVE.
  1282. The calls made are
  1283. 1. CCommonClusterPage::OnKillActive to read data from UI
  1284. 2. CCommonClusterPage::OnApply to validate the data
  1285. 3. If validation is successful, ClusterPage::mfn_SaveToNlbCfg : This function calls CCommonClusterPage::OnKillActive. This call seems to be redundant
  1286. During modification of cluster properties, ie. non-wizard mode
  1287. 1. ClusterPage::OnNotify is called with PSN_KILLACTIVE. The calls listed above are made
  1288. 2. ClusterPage::OnNotify is called with PSN_APPLY.
  1289. The following calls are made in this step
  1290. 2.1 : CCommonClusterPage::OnApply to validate the data : This call is redundant since it was called in #1.
  1291. 2.2 : CPropertyPage::OnNotify : This leads to a call to ClusterPage::OnOK(). ClusterPage::OnOK() calls ClusterPage::mfn_SaveToNlbCfg. This call is redundant since ClusterPage::mfn_SaveToNlbCfg was called in step #1.
  1292. Summarizing, the actions to be taken are :
  1293. 1. In ClusterPage::mfn_SaveToNlbCfg, remove the call to CCommonClusterPage::OnKillActive
  1294. 2. In ClusterPage::OnNotify for PSN_APPLY, remove call to CCommonClusterPage::OnApply
  1295. 3. In ClusterPage::OnOK(), remove call to ClusterPage::mfn_SaveToNlbCfg
  1296. HostPage.cpp :
  1297. During host addition, ie. wizard mode
  1298. HostPage::OnWizardFinish() is called
  1299. The calls made are
  1300. 1. mfn_ValidateData to validate the data
  1301. 2. If validation is successful, mfn_SaveToNlbCfg
  1302. During modification of host properties, ie. non-wizard mode
  1303. 1. HostPage::OnKillActive() is called.
  1304. The following calls are made in this step
  1305. 1.1 : mfn_ValidateData to validate data
  1306. 1.2 : If validation is successful, mfn_SaveToNlbCfg
  1307. 2. HostPage::OnOK() is called. mfn_SaveToNlbCfg is called here. This call is redundant since it was just made in #1.2.
  1308. Summarizing, the actions to be taken are :
  1309. 1. In HostPage::OnOK(), remove call to mfn_SaveToNlbCfg
  1310. 12/15/2001 JosephJ How to add a menu item
  1311. There are two kinds of menus -- the application menu and the ctxt-sensitive
  1312. menu. Most functionality is available in both, so when adding a menu item
  1313. they probably need to go to both places.
  1314. 1. Add to RC file:
  1315. -- [Main menu] Add under IDR_MAINFRAME MENU DISCARDABLE
  1316. this adds items to the main menu.
  1317. -- [Ctxt sensitive menu] Add under IDR_POPUP MENU DISCARDABLE
  1318. -- add the constants to resource.h
  1319. 2. Add OnXXX menu item handler to MainForm (mainform.h, .cpp)
  1320. follow the form of the existing menu item handlers -- you'll
  1321. see that it just calls the LeftView handler by the same name
  1322. (see note 10/27/2001 JosephJ Note on handling menu controls)
  1323. 3. Add OnXXX menu item handlers to LeftView (leftview.h, .cpp)
  1324. this handler will actually do the action of the item.
  1325. 4. Control whether you want the menu item to be enabled or disabled
  1326. depending on what item is selected in the leftview --
  1327. add items to LeftView::mfn_EnableHostMenuItems
  1328. and LeftView::mfn_EnableClusterMenuItems
  1329. (or create a NEW mfn_EnableXXXMenuItems if it's a whole new catigory).
  1330. 12/15/2001 JosephJ misconfiguration UI
  1331. Implemented the following:
  1332. 1. 207015 Reporting Cluster Misconfiguations
  1333. - Add "View Status" menu item to ctxt-sensitive and main manu.
  1334. - Bring up status dialog when user selects this.
  1335. - Maintain status -- misconfiguration adds the status caption and
  1336. details string. It's a bstr, so should be ok.
  1337. 12/15/2001 JosephJ Logview: LVS_NOSORTHEADER
  1338. Added LVS_NOSORTHEADER to logview style because
  1339. we don't need to sort columns.
  1340. 12/15/2001 JosephJ Fixed unresponsive dialogs spawned by ctxt-sensitive mnu
  1341. I noticed that the dialogs are responsive to keystrokes just not
  1342. responsive to the mouse (well, until you force a re-draw of the window by
  1343. temporarily overlapping it with another window).
  1344. So I figured that its a mouse-specific thing that somehow the processing
  1345. of the r-button click was not proper so on a hunch I called the base class
  1346. function FIRST: i.e, moved the call CTreeView::OnRButtonDown(nFlags, point)
  1347. to the START of the function LeftView::OnRButtonDown.
  1348. That did the trick!
  1349. 12/16/2001 JosephJ Dealing with remote control password
  1350. 1. Add new fields to EXTCFG:
  1351. BOOL fSetPassword;
  1352. DWORD dwNewHashedPassword;
  1353. 2. Add related methods to EXTCFG:
  1354. SetNewRemoteControlPassword(szPwd)
  1355. SetNewHashedRemoteControlPassword(dwPwd)
  1356. ClearNewRemoteControlPassword(void)
  1357. 3. In nlbclientlib, it will ONLY set the szPassword or the hashed pwd
  1358. if the fSetPassword field is set.
  1359. 4. EXTCFG::Update does not copy over the newpwd field -- instead
  1360. it clears it.
  1361. 5. In analyze-interface, an error is reported if:
  1362. - rct-enabled is different in cluster vs IF props
  1363. - rct-enabled in both cluster and IF props, but dwHash value is
  1364. different.
  1365. In the misconfig report, the user is asked to fix this by re-entering
  1366. the rct password.
  1367. 6. ONLY place where new Hashed rct pwd is specified is when adding a
  1368. node to a cluster.
  1369. clusocm.dll copies files and handles upgrade scenarios, etc.
  1370. On a fresh install, it puts cluster admin to the adminstrative tools thing.
  1371. 12/26/2001 JosephJ done the following a week ago:
  1372. 506822 Port control window unresponsive
  1373. 207015 Reporting Cluster Misconfiguations
  1374. 499068 save host list includes clusters or hosts that were removed
  1375. 503027 Connect dialog: duplicate hotkey (N)
  1376. 503031 Duplicate hotkey (N)
  1377. 503046 Log Settings: duplicate hotkey (E)
  1378. 504165 "Host\Delete" menu item is disabled when host is selected.
  1379. 209117 UI to manage cluster VIPS: troubleshoot and fix any issues
  1380. 502585 Update details view
  1381. 12/27/2001 JosephJ fixed the following ...
  1382. 203647 NLBManager should wrap the WMI error...
  1383. 326514 Modify remote-control pwd, report differences in pwd:
  1384. 509397 error check: when inital state conflicts a warning is given...
  1385. 509400 error check: add check for conflicting port rule where affinity..
  1386. 12/27/2001 JosephJ Getting rid of literal strings in Nlbmgr.exe
  1387. 484842 For localization compatibility, replace all %xx fields by %num
  1388. This was a pretty big effort -- there were literal strings all over the
  1389. place. I grepped for " (dquote), made a list of each one, went through
  1390. each and tested each case.
  1391. I added the Log method to CLocalLogger and used it in numerous places.
  1392. Another effort was to move to the %1,%2 etc FormatMessage format for a
  1393. bunch of strings, mainly port-rule-descriptions.
  1394. 12/29/2001 JosephJ Making "equal/unequal" port rule state host-specific
  1395. 202129 Make equal/unequal property of port rules a host-specific property.
  1396. Look for BUGFIX202129 conditionally compiled code.
  1397. Summary of changes:
  1398. clusterportsdlg: hide the equal/unequal checkbox and don't try to
  1399. read/write it. Change the load description from equal/unequal to
  1400. "empty" (i.e. "--").
  1401. hostportsdlg: enable the equal/unequal checkbox, and read it's value.
  1402. Add a handler for the checkbox events, and in the handler
  1403. enable/disable the load-weight controls appropriately.
  1404. portspage.cpp: change logic for handling equal/unequal when in
  1405. cluster vs host mode.
  1406. engine.cpp: ignore cluster equal/unequal and load weight when
  1407. applying cluster wide properties to an individual host.
  1408. 12/29/2001 JosephJ Reporting provider-side update results log.
  1409. Relevant bug: 203634 Nlb Manager should report useful error when netcfgs..
  1410. To do:
  1411. 1. Nlb Manager should report the results of the log.
  1412. -- In GetUpdateResult, pick up the log and set the host status field
  1413. with that info. YES!!!
  1414. -- On update completion, fill in the log with the result.
  1415. 2. NLBMPROV.DLL -- if fAsync, should do a check if it can get the netcfg
  1416. write lock, and fail if it cant (with appropriate log message).
  1417. [Addendum] Implemented both of the above.
  1418. 01/01/2002 JosephJ Tracking available single-host port rule priorities
  1419. Implemented gNlbEngine::GetAvailablePortRulePriorities, and
  1420. use it in hostportsdlg.cpp and engine.cpp to choose proper host priorities.
  1421. Relevant bug: 485541 Provide valid defaults for host-priorities to
  1422. single-host port rule
  1423. 01/01/2002 JosephJ Full reporting of misconfigurations and config difs
  1424. Relevant bugs:
  1425. 360469 Warn user if whole cluster will come down because of operation.
  1426. 502793 warn user when attempting to remove / change DIP
  1427. 288769 error check: Verify that Primary IP, DIP and additional VIPs' ..
  1428. The plan is to write a utility function with the following prototype:
  1429. NLBERROR
  1430. AnalyzeConfigurationPair(
  1431. IN const EXTCFG &Cfg,
  1432. IN const EXTCFG *pOtherCfg,
  1433. IN BOOL fOtherIsCluster,
  1434. IN BOOL fCheckOtherForConsistancy,
  1435. OUT BOOL fConnectivityChange,
  1436. IN OUT CLocalLogger &logErrors,
  1437. IN OUT CLocalLogger &logDifferences
  1438. );
  1439. //
  1440. // logErrors - a log of config errors
  1441. // logDifferences - a log of differences between
  1442. // Cfg and UpOtherCfg.
  1443. // fCheckOtherForConsistancy -- if true, we will check Cfg
  1444. // against pOtherCfg. If fOtherIsCluster, we expect
  1445. // cluster wide properties to match, else we expect
  1446. // cluster-wide properties to match as well as host-specific
  1447. // properteis to not conflict.
  1448. //
  1449. Also a new related function for analyzing a SINGLE configuration for
  1450. validity with itself (eg CIP should be in the IP address list):
  1451. NLBERROR
  1452. AnalyzeNlbConfiguration(
  1453. IN const NLB_EXTENDED_CLUSTER_CONFIGURATION &Cfg,
  1454. IN OUT CLocalLogger &logErrors
  1455. );
  1456. These two functions are a superset of the existing functions
  1457. analyze_nlbcfg(in engine.cpp) and EXTCFG::AnalyzeUpdate and
  1458. CfgUtilsAnalyzeNlbUpdate.
  1459. So we'll stop using those functions and use these functions instead.
  1460. Traffic mode change:
  1461. From unicast to multicast
  1462. WARNING: asda asdfasdf asdfasdf
  1463. IP addresses to be added:
  1464. 10.0.0.1/255.255.255.0
  1465. 10.0.0.1/255.255.255.0
  1466. 10.0.0.1/255.255.255.0
  1467. 10.0.0.1/255.255.255.0
  1468. IP addresses to be removed:
  1469. 10.0.0.1/255.255.255.0
  1470. 10.0.0.1/255.255.255.0
  1471. IP addresses to have subnet mask changed:
  1472. 10.0.0.1: From 255.255.255.0 to 255.255.0.0
  1473. Cluster name change:
  1474. From "" to ""
  1475. Remote Control:
  1476. From enabled to disabled
  1477. New password specified
  1478. Some port rules were added, removed or modified.
  1479. Cluster-wide-control: stops and suspends.
  1480. 502793 warn user when attempting to remove / change DIP
  1481. 01/04/2002 JosephJ Bug in CNlbEngine::mfn_ReallyUpdateInterface -- keep copy
  1482. of a internal bstr pointer without lock held.
  1483. ConnInfo.szUserName = (LPCWSTR) pHSpec->m_UserName;
  1484. (and related bstrs) -- should replace by keeping keeping bstr local
  1485. variables. Check for other places where this can occur.
  1486. 01/04/2002 JosephJ -- wierd "/" ip addresses showing up (gjack)
  1487. 01/08/2002 JosephJ checked in to LAB03 fixes for the following
  1488. 203647 NLBManager should wrap the WMI error...
  1489. 326514 Modify remote-control pwd, report differences in pwd:
  1490. 509397 error check: when inital state conflicts a warning is given...
  1491. 509400 error check: add check for conflicting port rule where affinity..
  1492. 484842 For localization compatibility, replace all %xx fields by %num
  1493. 202129 Make equal/unequal property of port rules a host-specific property.
  1494. 203634 Nlb Manager should report useful error when netcfgs..
  1495. 485541 Provide valid defaults for host-priorities to single-host port rule
  1496. 288769 error check: Verify that Primary IP, DIP and additional VIPs' ..
  1497. 360469 Warn user if whole cluster will come down because of operation.
  1498. 01/08/2002 JosephJ Checks for preventing attempt to remove/change DIP
  1499. 502793 warn user when attempting to remove / change DIP
  1500. (Also, check if new dip is already used elsewhere)
  1501. 1. Place to add check: HostPage::mfn_ValidateDip
  1502. 2. What to check for?
  1503. LookupIfByIP, see if IF matches
  1504. LookupHostByConnIP -- see if we find one.
  1505. LookupClusterByIp -- fail if we find one.
  1506. 01/10/2002 More IP address checks
  1507. If adding a new host or creating a new cluster, and the cip matches
  1508. the IF already on that cluster, we end up having the same dip and VIP.
  1509. Need to fix this case.
  1510. Still problems:
  1511. If you pick an IF with first IF matching cip, we now put blank.
  1512. However, if you go back to cluster page, make a change, then
  1513. back again to host page, we don't appear to re-do this change.
  1514. We should LOCK DOWN the if if we find that the cip matches that IF.
  1515. 01/11/2002 JosephJ Steps to add support for query cluster members
  1516. 1. Implement SKELETON CfgUtilGetClusterMembers -- just return failure
  1517. Prototype is already defined in nlbmgr\inc\cfgutil.h
  1518. Implementation goes in nlbmgr\cfgutillib\cfgutil.cpp,
  1519. below function CfgUtilControlCluster.
  1520. 2. Implement test harness in nlbmgr\provider\tests\tprov.cpp
  1521. Implement function parse_query (see parse_control for sample code)
  1522. Suggestded output format:
  1523. HosdID DedicatedIP HostName
  1524. ----------------------------------------------------
  1525. 1 0.0.0.0 "nlb-x.cheesegalaxy.com"
  1526. 2 0.0.0.0 "nlb-y.cheesegalaxy.com"
  1527. ... etc
  1528. 3. Test test harness itself...
  1529. Compile tprov.exe with the line
  1530. "// NlbHostFake();" in tprov.cpp UNcommented.
  1531. Using this version, type:
  1532. tprov.exe nlb-x u nic1
  1533. query ; to call function parse_query
  1534. q ; to quit
  1535. The above exercises the WMI version. Since it's useing the fake (demo)
  1536. version, it connects to fake host "nlb-x" and loads the configuration
  1537. for NIC "nic1". The "query" command applies to that nic.
  1538. NlbHostGetClusterMembers (running in fake mode) will return info
  1539. for a single member -- so you can test your parse_query() code to
  1540. make sure it is displaying the output correctly (see sample format
  1541. above).
  1542. Now using the same tprov.exe, type:
  1543. tprov.exe - al
  1544. This will list a list of REAL NICs and guids on your test machine.
  1545. Then pick a NIC xxx and type
  1546. tprov - u xxx
  1547. query
  1548. q
  1549. This will again call parse_query, but this time it should call
  1550. CfgUtilGetClusterMembers (which you have implemented a skeleton
  1551. version in sstep 1).
  1552. NOTE: the Real function is called for this, not any fake stuff (the
  1553. fake stuff applies only to WMI).
  1554. 4. Implement CfgUtilGetClusterMembers fully
  1555. (By now your test harness has been implemented and tested)
  1556. Test using:
  1557. tprov.exe - u xxx (where xxx is the adapter name)
  1558. query
  1559. q
  1560. 5. Implement NlbHostGetClusterMembers
  1561. Prototype is already defined in nlbmgr\inc\nlbclient.h
  1562. Skeletion implementation exists in nlbmgr\nlbclientlib\nlbclient.cpp
  1563. Look at NlbHostGetCompatibleNics for an example of dealing with
  1564. arrays of strings.
  1565. 6. Implement SKELETON ProvGetClusterMembers in nlbmgr\provider\nlbsnic.cpp
  1566. The prototype is already defined in nlbsnic.cpp.
  1567. Implement it below existing function ProvControlCluster
  1568. Call it from ProvExecStaticMethod (just below the call to
  1569. ProvControlCluster, if bstrMethodName matches "GetClusterMembers").
  1570. The skeleton implementation can just populate the 3 string
  1571. arrays with fake data, just so you can make sure that all
  1572. the wmi gook (both client and server) are working before you
  1573. plug in the real call to CfgUtilGetClusterMembers
  1574. 7. Test the above skeleton implementation using (locally, using WMI):
  1575. tprov . u xxx (where xxx is the adapter name)
  1576. query
  1577. q
  1578. The query output should list the fake info you added in Step 6.
  1579. 8. Implement and test ProvGetClusterMembers fully
  1580. Make it call CfgUtilGetClusterMembers.
  1581. Refer to ProvControlCluster, and ProvGetCompatibleAdapterGuids
  1582. for sample code.
  1583. Test using procedure in Step 7.
  1584. Additionally test remote operation by using:
  1585. tprov mmm u xxx (where mmm is machine name and xxx is the adapter name)
  1586. query
  1587. q
  1588. 01/15/2002 JosephJ Plan for Mode Change
  1589. 1. If mode change, bring up a message box explaining the steps...
  1590. 2. Save away a copy of the cluster params IP address list.
  1591. 3. Do the update operation once.
  1592. 4. When it completes, check that all IFs have the same mode and
  1593. that they match the cluster-specific version.
  1594. If NO, list the IPaddresses and subnets in the log entry and mention what
  1595. happened.
  1596. If YES, re-enter the cluster IP addresses and try again.
  1597. Issue: once we make update parallel, what will we do?
  1598. UpdateInterface
  1599. 01/21/2002 JosephJ Latest thoughts on RefreseshInterface, RefreshCluster, etc..
  1600. New policy on when the cluster-wide copy of properties is updated.
  1601. Cluster-props are ONLY updated on a refresh-cluster. In this case,
  1602. the properties are updated only for the FIRST host that has NLB
  1603. bound to the specified IP address.
  1604. They are NOT updated when:
  1605. add host
  1606. refresh host
  1607. update cluster props
  1608. update host props
  1609. The above behavior is different than what is implemented currently, when
  1610. the cluster is refreshed more aggressively, for example, when updating
  1611. a host's properties.
  1612. However it is an improvement, as it has simpler semantics and makes it
  1613. more clear (via misconfig reporting) when there are discrepancies between
  1614. the cluster-wide version and host versions.
  1615. So there will be two RefreshInterface versions:
  1616. RefreshInterface(BOOL fClusterRefresh) has the following semantics:
  1617. if (!fClusterRefresh)
  1618. {
  1619. Verify that there is no cluster-wide operation ongoing.
  1620. }
  1621. Start interface operation (bail if we can't start)
  1622. call mfn_RefreshInterface(TRUE); // TRUE == report misconfig.
  1623. Remove interface if not in cluster
  1624. Remove cluster if no more interfaces in cluster
  1625. mfn_RefreshInterface(BOOL fReportMisconfig)
  1626. {
  1627. really refresh interface
  1628. if (fReportMisconfig)
  1629. {
  1630. Check against cluster props and all non-misconfig hosts upto
  1631. this one, and report misconfigurations if any
  1632. }
  1633. }
  1634. RefreshCluster (or rather UpdateInter with NULL pConfig)
  1635. {
  1636. start-cluster-opearation (bail if can't start)
  1637. BOOL fClusterPropsUpdated = FALSE;
  1638. for each interface
  1639. {
  1640. fRet = RefreshInterface(TRUE); // TRUE == cluster refresh
  1641. if ( fRet
  1642. && !fClusterPropsUpdated
  1643. && props bound to NLB
  1644. && cluster-ip matches )
  1645. {
  1646. Update cluster props for
  1647. fClusterPropsUpdated = TRUE;
  1648. }
  1649. }
  1650. }
  1651. 01/22/2002 shouse
  1652. Features added:
  1653. * F5 refreshes only the cluster or interface selected in the tree view. CTRL+F5
  1654. refreshes ALL clusters in the tree view.
  1655. * A new command line option, /autorefresh [interval], will instruct NLB manager
  1656. to automatically refresh its view every <interval> seconds. By default, this
  1657. is not turned on and must be specified on the command line to activate it. The
  1658. default <interval> is 60 seconds and the minimal allowable <interval> is 15
  1659. seconds.
  1660. * Cluster IPs dialog is now a listview with IP address control popups to edit
  1661. and add virtual IP addresses to a cluster.
  1662. * Added columns in the host and port rule detail views to contain statistics and
  1663. state, such as the state of a port rule and approximate load being handled, and
  1664. some convergence information, such as the total number of convergences by a
  1665. particular host and the time of the last convergence. Along with auto-refresh,
  1666. these should give a user a nice way to monitor some information about a live
  1667. cluster, rather than just using NLB manager for configuration. Note the the
  1668. WMI support for retrieving this information is not yet available, so the columns
  1669. are empty - they will be supported soon.
  1670. * Lots of UI cleanup was done - hopefully this is the last round.
  1671. Notes:
  1672. To eliminate the selected text in an edit box, which seems to select everything
  1673. by default, subscribe to the WM_ACTIVE notification and SetSel(0, 0, FALSE).
  1674. This does not work when executed from OnInitDialog for some unknown reason.
  1675. To decipher multiple key combinations such as CTRL+F5, subscribe to the WM_KEYDOWN
  1676. notification and ignore all keys other than the one(s) you're filtering for,
  1677. including modifiers (CTRL, ALT, Shift, etc.). When the key you're interested in
  1678. is pressed, use GetKeyState(VK_WHATEVER) to retrieve the up/down state of any
  1679. modifiers you're interested in. GetKeyState returns a SHORT. If the most signif-
  1680. icant bit it set, the key is pressed down; otherwise, it is not. For example:
  1681. void OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags) {
  1682. if (nChar == VK_F5) {
  1683. if (GetKeyState(VK_CONTROL) & 0x8000)
  1684. ::MessageBox(NULL, L"The CTRL is pressed!!!\n", L"Notice", MB_ICONINFORMATION | MB_OK);
  1685. else
  1686. ::MessageBox(NULL, L"The CTRL is NOT pressed!!!\n", L"Notice", MB_ICONINFORMATION | MB_OK);
  1687. }
  1688. }
  1689. To re-size a control within a window or frame, subscribe to the WM_SIZE noti-
  1690. fication of the window or frame. In the handler for this notification, use
  1691. GetClientRect to get the window coordinates of the window or any controls within
  1692. it. Use MoveWindow to resize the control you wish to modify. For example,
  1693. suppose you wanted to resize an edit control to be the size of the window around
  1694. it, but with a border of 15 pixels on each side. To do this:
  1695. void OnSize (UINT nType, int cx, int cy) {
  1696. RECT WindowRect;
  1697. RECT MyRect;
  1698. /* Get a pointer to the edit box. */
  1699. CWnd * pEdit = GetDlgItem(IDC_EDIT_WHATEVER);
  1700. /* Get the client rectangle of the window. */
  1701. GetClientRect(&WindowRect);
  1702. MyRect.top = WindowRect.top + 15;
  1703. MyRect.left = WindowRect.left + 15;
  1704. MyRect.bottom = WindowRect.bottom - 15;
  1705. MyRect.right = WindowRect.right - 15;
  1706. pEdit->MoveWindow(&MyRect, TRUE);
  1707. }
  1708. 01/23/2002 JosephJ DEADLOCK in Leftview::mfn_Lock
  1709. Background (thread pool) thread aquires LeftView lock, then gets stuck in
  1710. CTreeCtrl::SetItem, which does a SendMessage and blocks, I guess waiting for
  1711. the main application windows message loop to process the message.
  1712. USER32!SendMessageW+0x44
  1713. CTreeCtrl::SetItem+0x1f
  1714. LeftView::mfn_InsertInterface+0x258
  1715. LeftView::HandleEngineEvent+0x344
  1716. Document::HandleEngineEvent+0x72
  1717. CNlbEngine::ControlClusterOnInterface+0x1
  1718. CNlbEngine::RefreshInterfaceNew+0x4fe
  1719. CNlbEngine::mfn_ReallyUpdateInterface+0x4
  1720. CNlbEngine::UpdateInterfaceWorkItem+0x205
  1721. UpdateInterfaceWorkItemRoutine+0x11
  1722. Unfortunately, the main (winmsg) thread, cant process messages because it's
  1723. stuck trying to acquire the LeftView lock!
  1724. LeftView::mfn_Lock+0x22
  1725. LeftView::mfn_InsertCluster+0x11f
  1726. LeftView::HandleEngineEvent+0x13c
  1727. Document::HandleEngineEvent+0x72
  1728. CNlbEngine::UpdateCluster+0x22b (FPO: [No
  1729. LeftView::OnRefresh+0x150
  1730. LeftView::OnKeyDown+0x37
  1731. RESOLUTION:
  1732. Changed the implementation of CLeftView::mfn_Lock from
  1733. EnterCriticalSection(&m_crit)
  1734. to
  1735. while (!TryEnterCriticalSection(&m_crit))
  1736. {
  1737. ProcessMsgQueue();
  1738. Sleep(100);
  1739. }
  1740. I verified this by deliberatly producing the deadlock by introducing
  1741. sleeps, then verifying that the deadlock doesn't happen if the above
  1742. version of mfn_Lock is used.
  1743. 01/24/2002 JosephJ How to hook the "CLOSE" message
  1744. 1. To MainForm add:
  1745. afx_msg void OnClose( );
  1746. 2. Implement OnClose ...
  1747. void MainForm::OnClose( )
  1748. {
  1749. int sel = MessageBox(
  1750. L"OK to close?",
  1751. L"OK to close?",
  1752. MB_OKCANCEL | MB_ICONEXCLAMATION
  1753. );
  1754. if ( sel == IDOK )
  1755. {
  1756. CFrameWnd::OnClose( );
  1757. }
  1758. }
  1759. 3. Make sure it gets called ...
  1760. BEGIN_MESSAGE_MAP( MainForm, CFrameWnd )
  1761. ...
  1762. ON_WM_CLOSE()
  1763. ...
  1764. END_MESSAGE_MAP()
  1765. 01/24/2002 JosephJ Dealing with app closing
  1766. On wm close, put up msgbox/dlg:
  1767. Title: Close NLB Manager
  1768. Text:
  1769. OK to close NLB Manager while the following operation(s)
  1770. are in progress?
  1771. <list of operations>
  1772. OK CANCEL
  1773. On OK -- call Document->PrepareToClose() ....
  1774. VOID
  1775. Document::PrepareToClose(void)
  1776. {
  1777. //
  1778. // Cancel any pending operations in the engine, and prevent any
  1779. // new operations to be launched. During this time, we want the
  1780. // views and the log to be updated, so we don't PrepareToDeinitialize
  1781. // for ourselves or the views yet...
  1782. //
  1783. {
  1784. CWaitCursor wait;
  1785. gEngine.PrepareToDeinitialize();
  1786. // After the Engine's PrepareToDeinitialize function is called, it
  1787. // fails attempts to create new handles and new operations.
  1788. gEngine.CancelAllPendingOperations(TRUE); // TRUE == block
  1789. }
  1790. //
  1791. // At this time there should be no more pending activity. Block
  1792. // any further updates to the views...
  1793. //
  1794. m_fPrepareToDeinitialize = TRUE;
  1795. if (m_pLeftView != NULL)
  1796. {
  1797. m_pLeftView->PrepareToDeinitialize();
  1798. }
  1799. if (m_pDetailsView != NULL)
  1800. {
  1801. m_pDetailsView->PrepareToDeinitialize();
  1802. }
  1803. if (m_pLogView != NULL)
  1804. {
  1805. m_pLogView->PrepareToDeinitialize();
  1806. }
  1807. }
  1808. (See also entry right below ...)
  1809. 01/24/2002 JosephJ Dealing with work items on app closing.
  1810. The classic problem here is that the moment the work item signals
  1811. that it's done, it can trigger the deinitialization of the app,
  1812. before the work item completes.
  1813. So to avoid this, I keep a CNlbEngine::m_WorkItemCount, which
  1814. is maintained by InterlockedIncrement/Decrement.
  1815. CNlbEngine::CancelAllPendingOperations will block until this count
  1816. goes to zoro (as well as until the operations go to zero). The
  1817. logic is quite subtle -- see this function for details.
  1818. 01/24/2002 JosephJ Creating our own extended MessageBox:
  1819. Uses:
  1820. Report misconfigs -- OK
  1821. Report pending operations on close -- OK CANCEL
  1822. Report proposed cluster changes -- YES NO
  1823. Format:
  1824. text
  1825. <listbox>
  1826. text
  1827. <buttons>
  1828. 01/29/2002 JosephJ problems with updating UI in the background thread.
  1829. Backing out of doing updates in a work items for now, because of misc
  1830. AVs and deadlocks during the update process.
  1831. 01/29/2002 JosephJ problems with re-entrancy of Application::ProcessMsgQueue
  1832. ProcessMsgQueue was getting reentered and we got a deadlock
  1833. in handling WM_CLOSE (which ends up calling Document::PrepareToClose,
  1834. which calls CNlbEngine::CancelAllPendingOperations which deadlocks
  1835. waiting for all operations to go to zero because the WM_CLOSE msg was
  1836. handled in the context of waiting to retry to get an update completion
  1837. status.
  1838. Temporary fix:
  1839. - Keep a reentrancy count in Application: m_lMsgProcReentrancyCount.
  1840. - Application::ProcessMsgQueue will do an interlocked increment on this,
  1841. and if the result is > 1, it simply does a decrement and returns.
  1842. - Various UI-initiated functions don't do anything if called in
  1843. the context of ProcessMsgQueue (i.e, called when m_lMsgProcReentrancyCount
  1844. is > 0. The function Application::IsProcessMsgQueueExecuting checks
  1845. for this case.
  1846. 01/30/2002 JosephJ checked in the following
  1847. 334243 perform extended operations in the background; allow a cancel
  1848. 484025 When using alt-F4 to close nlbmgr.exe, the process stays in memory.
  1849. 513056 add host failed because nlbmgr ended up pinging for "13:36:48".
  1850. 502793 warn user when attempting to remove / change DIP
  1851. 512303 Block user from merging 2 clusters that are in the nlbmgr context
  1852. 512370 update sometims fails when IP is zero (0.0.0.0)
  1853. 478932 ipconflict when changing modes of operation ( unicast to multicast )
  1854. 505153 NlbConfigurationUpdate::DoUpdate returns WBEM_E_ALREADY_EXISTS
  1855. 509346 delete host adds a homenet IP when it should keep the DIP
  1856. 509355 replace or remove home net ip functions like IP with the real home
  1857. 02/08/2002 JosephJ suspicious imported functions
  1858. FormatMessageW
  1859. lstrcpyW
  1860. WideCharToMultiByte
  1861. lstrlenW
  1862. GetFileAttributesW
  1863. LockResource
  1864. LoadResource
  1865. FindResourceW
  1866. GetCurrentProcess
  1867. InitializeCriticalSection
  1868. GetComputerNameExW
  1869. MultiByteToWideChar
  1870. GetStartupInfoW
  1871. LoadLibraryW
  1872. VirtualQuery
  1873. _XcptFilter
  1874. _wspawnlp
  1875. _wgetenv
  1876. _ftol
  1877. _wfsopen
  1878. RegCreateKeyExW
  1879. TraceEvent
  1880. RegQueryValueExW
  1881. RegSetValueExW
  1882. LoadStringW
  1883. WinHelpW
  1884. wsprintfW
  1885. GetClientRect
  1886. LoadIconW
  1887. LoadMenuW
  1888. CoCreateInstance
  1889. CLSIDFromString
  1890. CoSetProxyBlanket
  1891. CredUIPromptForCredentialsW
  1892. IcmpCreateFile
  1893. IcmpSendEcho2
  1894. Code review tool:
  1895. http://shell/Development/Danger/Dangerous%20APIs.htm
  1896. http://massweb/security/Lists/Announcements/DispForm.htm?ID=8&Source=http%3a%2f%2fmassweb%2fsecurity%2f
  1897. // 2/12/02 JosephJ SECURITY BUGBUG:
  1898. 02/14/2002 JosephJ Processing UI updates in the foreground
  1899. This is completing the fix to:
  1900. 334243 perform extended operations in the background; allow a cancel
  1901. Changes:
  1902. Added a application-specific message: MYWM_DEFER_UI_MSG
  1903. Added class CUIWorkItem in document.h -- this data class encapsulates
  1904. the parameters for (a) log messages and (b) HandleEngineEvent
  1905. notifications.
  1906. Added Document::mfn_DeferUIOperation(CUIWorkItem *pWorkItem) --
  1907. it posts a MYWM_DEFER_UI_MSG message to the MainForm's window's queue
  1908. (the pointer to the mainform object is saved in global g_pMainFormWnd --
  1909. a bit of a hack).
  1910. Added Document::HandleDeferedUIWorkItem(pWorkItem) --
  1911. will actually call the Log or HandleEngineEvent encapsulated in
  1912. a work item.
  1913. Added virtual function MainForm::WindowProc that overrides the default
  1914. window handling proc, and on getting a MYWM_DEFER_UI_MSG, will
  1915. extract the work item (lParam) and call
  1916. pDocument->HandleDeferedUIWorkItem.
  1917. 04/09/2002 JosephJ Bugs at this point:
  1918. P1's
  1919. 489012 If ICMP is disabled by customer for security reasons, they cannot
  1920. 538191 user's password saved in user-mode memory
  1921. 540636 password is not updated locally
  1922. 535616 memory leak running remove from view
  1923. 535969 too much memory allocated for event logs
  1924. 568198 remove from view should not remember cluster properties
  1925. P2's:
  1926. 540917 Duplicate shortcut character "P" are there.
  1927. 565697 delete host when host is unreachalbe
  1928. 563150 PREFIX:net: \nt\net\wlbs\nlbmgr\provider\updatecfg.cpp:
  1929. 566671 NLBS:NET3:nlbmgr.exe:Typo:Cluster configuration
  1930. 585280 NLBMgr fails to look up a cluster instance where nlb was bound
  1931. 552641 autorefresh require valid input as int and is in a reasonable
  1932. 528007 Error message pops up stating "invalid cluster IP" when viewing
  1933. 532302 invalid user credentials:If machine is not on a domain anything is
  1934. 535561 mgr says that ping failed but ping.exe succeeds
  1935. Done:
  1936. 1. Remove demo mode in retail build -- remove it from the help message too
  1937. 2. 489012 If ICMP is disabled by customer for security reasons, they ...
  1938. x Add NoPing option (remember to add it to cmdline help)
  1939. x Add fNoPing and fNlbMgr flag to CfgUtilsInitialize
  1940. 3. 538191 user's password saved in user-mode memory
  1941. 7. 540917 Duplicate shortcut character "P" are there.
  1942. 9. 566671 NLBS:NET3:nlbmgr.exe:Typo:Cluster configuration
  1943. 3. 540636 password is not updated locally
  1944. 7. Make nlbmgr.exe NOT load wlbsctrl.dll -- even if it's not there
  1945. (so make CfgUtilInitialize take a "nlbmgr.exe" flag).
  1946. 04/15/2002 JosephJ details of fix to: 538191 user's password saved in
  1947. user-mode memory
  1948. The password is stored internally in an encrypted form. It is
  1949. decrypted only when
  1950. (a) bringing up UI to modify the password -- this is done
  1951. in PromptForEncryptedCreds; and
  1952. (b) when connecting to a host -- this is done in
  1953. nlbclient.lib!connect_to_server
  1954. (in wlbs\nlbmgr\nlbclientlib\nlbclient.cpp).
  1955. Encryption scheme: We call RtlEncrypt/DecryptMemory with "0" as flags.
  1956. Additional, we "encode" the binary encrypted form into a printable
  1957. version (which is also guaranteed to not have any 0 characters, so
  1958. it can be stored and processed as any other string). This was done because
  1959. the password is stored and processed in several places where it is assumed
  1960. to be a string, or bstr etc. The encrypt/decrypt and encode/decode is
  1961. done in cfgutillib!CfgUtilEncrypt/DecryptPassword
  1962. (in wlbs\nlbmgr\cfgutillib\cfgutil.cpp). Test program
  1963. nlbmgr\provider\tprov.cpp has function test_encrypt_memory() which
  1964. does rudimentary functional tests on CfgUtilEncrypt/DecryptMemory.
  1965. 04/15/2002 JosephJ details of fix for 540636 password is not updated locally
  1966. Problem is that on setting a new remote control password (a cluster level
  1967. change), the cluster's NLB properties hashed password value is not
  1968. updated, so after each host is updated, it reports an config error because
  1969. its hash value doesn't match the cluster's (obsolete) value.
  1970. Fix is to:
  1971. 1. Mark the cluster's hash value as being stale -- this is done
  1972. by a new flag CClusterSpec::m_fNewRctPassword
  1973. which is set to true IFF the user has just specifed a new
  1974. passord, and the hosts are in the process of carrying out the
  1975. update. It is set in CNlbEngine::UpdateCluster (look
  1976. for m_fNewRctPassword).
  1977. 2. When analyzing an interface for config errors, when checking
  1978. the interface's config against the cluster config, the
  1979. check of remote control hash is NOT made if the cluster's
  1980. m_fNewRctPassword flag is set. This is done in
  1981. CNlbEngine::mfn_AnalyzeInterfaceLk which calls
  1982. analyze_nlbcfg with a parameter "ignore rct password" set
  1983. appropriately. analyze_nlbcfg will ignore the rct password check
  1984. if this flag is set.
  1985. 3. Once an interface update is complete, AND if a new password has
  1986. been set, AND the update completed successfully, AND
  1987. the cluster's m_fNewRctPassword flag is TRUE, THEN
  1988. we update the clusters's remote control hash value and clear
  1989. the cluster's m_fNewRctPassword flag. This is all done in
  1990. CNlbEngine::mfn_ReallyUpdateInterface, which actually performs
  1991. the interface update and synchronously waits for the update to
  1992. complete.
  1993. 04/15/2002 JosephJ details of fix for 568198 remove from view should not
  1994. remember cluster properties
  1995. Problem is that we remember all configs on all hosts we have ever
  1996. connected to. So even if we've unmanaged a cluster, we report a conflict
  1997. if some config conflicts with this removed cluster.
  1998. Fix is to (gulp) delete hosts from nlbmgr once the last managed
  1999. cluster goes away. One side effect will be that the credentials used
  2000. to connect to that host are lost -- we can keep a separate datastructure
  2001. just for that if needed.
  2002. New function CNlbEngine::mfn_DeleteHostIfNotManagedLk
  2003. deletes the host and its interfaces if the interfaces
  2004. are not part of any cluster (and have no ongoing operation on them,
  2005. although the latter should never happen if the interface is not part
  2006. of a cluster). Need to watch for the case of pruning hosts wile
  2007. they are in the process of being added in the context of
  2008. hostlist (we don't check -- could be a potential problem).
  2009. CNlbEngine::DeleteCluster calls mfn_DeleteHostIfNotManagedLk
  2010. for each of its interfaces.
  2011. CNlbEngine::UpdateInterfaceWorkItem calls
  2012. mfn_DeleteHostIfNotManagedLk if once done updating, the interface is
  2013. now unbound.
  2014. New function CNlbEngine::PurgeUnmanagedHosts:
  2015. This function effectively calls mfn_DeleteHostIfNotManagedLk for
  2016. all hosts.
  2017. This function is called from leftview.cpp from all the places that
  2018. bring up the ConnectDialog UI, after it is done with processing the UI.
  2019. It is called here because the ConnectDialog UI can create several
  2020. unmanaged hosts -- either if the user keeps connecting to different
  2021. computers or because the user cancels from the dialog. We could have
  2022. cleaned this up in the ConnectDialog itself, but it's a bit tricky.
  2023. We also call this function at the end of LeftView::OnRefresh.
  2024. This need to call this purge function from several places is not
  2025. very clean.
  2026. 04/17/2002 JosephJ Not overwriting the user-entered connection string
  2027. with the FQDN obtained from the hosts via connect-to-existing
  2028. This was causing a subsequent attempt to connect to the same host to fail
  2029. because the user didn't specify the fqdn.
  2030. Added a boolean paramater "fOverwriteConnectionInfo" to
  2031. CNlbEngine::ConnectToHost. If this is true, it will overwrite any
  2032. previously-existing connection info (connection string, username pwd)
  2033. with those specified in pConnectionInfo.
  2034. The UI (ConnectDialog::OnButtonConnect) calls ConnectToHost specifying
  2035. TRUE (override), while CNlbEngine::LoadHost calls ConnectToHost specifying
  2036. false (don't override). LoadHost is called in the context of
  2037. Connect-to-existing, so with this fix, it doesn't overwrite the
  2038. info intered via the UI.
  2039. Also needed to added this same flag to CNlbEngine::mfn_RefreshHost.
  2040. 04/17/2002 Preventing the cluster from being unmanaged if there are pending ops
  2041. CNlbEngine::DeleteCluster now calls a newly written function
  2042. CNlbEngine::mfn_ClusterOrInterfaceOperationsPendingLk,
  2043. which reports whether there are any pending operations on a cluster or
  2044. on its interfaces. If this is the case, the DeleteCluster
  2045. (which is what "unmanages" the cluster) fails.
  2046. 04/17/2002 Details of fix for 535969 too much memory allocated for
  2047. event logs -- also limit growth of log file...
  2048. Logfile:
  2049. On file open, seek to the end (but don't check for file size) -- we
  2050. don't check so that a message gets logged in the case of
  2051. starting nlbmgr with a size already too large.
  2052. In Document::logStatus , check (using ftell) if the position exceeds
  2053. the max size (tentatively 10MB) -- if so it logs an event and closes
  2054. the log file.
  2055. In the context of Document::logStatus, I log a message saying that
  2056. the file-size has exceeded. This gets logged even on starting
  2057. up nlbmgr with a file that is too large -- so the user is
  2058. notified of this.
  2059. Pruning in-memory log:
  2060. In log-string, if in-memory count of lines is exceeded by 100, it
  2061. will delete the earliest 100 and then add a warning log msg about
  2062. deletinon.
  2063. This is done in LogView::LogString.
  2064. 04/18/2002 JosephJ Details of fix to 565697 delete host when host is
  2065. unreachalbe.
  2066. In LeftView::OnHostRemove, if the host state is unreachable,
  2067. bring up UI asking if we should simply stop managing this host.
  2068. We also need to properly track the reachable/unreachable state of
  2069. the host -- we now do this in mfn_Refresh
  2070. 05/10/2002 JosephJ Details of fix to 603411 nlbmgr:ACCESSIBILITY:can not tab
  2071. between window panes
  2072. 1. Need to catch VK_TAB and VK_F6 in each of the views --
  2073. this was simple to do on the left and log views, but a pain on
  2074. the details-view (and in fact we could not figure out out to capture
  2075. TAB in the detail's view (which is a form view)).
  2076. -- for left and log view:
  2077. Add a OnKeyDown handler (including add a ON_WM_KEYDOWN() entry
  2078. in the message map.
  2079. Check the OnKeyDown functions for LeftView and LogView, under
  2080. VK_TAB and VK_F6 -- check also how we check for the SHIFT key
  2081. being pressed (because if it is we go anticlockwise around the
  2082. views).
  2083. -- for DetailsView:
  2084. Add to message map:
  2085. ON_NOTIFY(LVN_KEYDOWN, IDC_LIST_DETAILS, OnNotifyKeyDown)
  2086. See DetailsView::OnNotifyKeyDown for more details...
  2087. 2. Need to decide which view to shift focus to -- this is done
  2088. in Document::SetFocusNextView and SetFocusPrevView.
  2089. 3. For setting the focus on DetailsView, we can't simply call
  2090. SetFocus on that view's CWnd -- instead we need to call
  2091. SetFocus on the detail view's list control -- (we got very flaky
  2092. behavior calling SetFocus in DetailsView's CWnd).
  2093. Also we need to select an item in the list control if none is selected
  2094. so the user can get some visual cue.
  2095. All this is implemented in DetailsView::SetFocus.
  2096. 4. Because we can't hook the TAB key in the details view, we
  2097. just toggle between leftview and log view when the user presses TAB,
  2098. but cycle between all three when F6 is pressed.
  2099. 05/13/2002 ChriDar
  2100. Need to check code for memory allocation failures. One example noted is
  2101. in the Document class constructor. A CImageList is constructed and dereferenced,
  2102. but the memory alloc wasn't verifed.
  2103. 08/22/2002 JosephJ
  2104. Fix for:
  2105. CyndaR:
  2106. So, if you connect to the to be NLB host with the DHCP assigned ip
  2107. address of the nic to be bound to NLB, the wizard will show the DIP
  2108. and subnet mask as blank. If you try to specify anything it produces
  2109. the error that Frank referenced. The wizard allows you to continue
  2110. even if the DIP is left blank and will result in only the cluster ip
  2111. address being bound to the nic. The dip is now blank in NLB properties
  2112. of network connections and NLBMgr can no longer connect to the host to
  2113. get status update. NLBMgr will indicate that NLB is not bound to the
  2114. NLB host and if you refresh it will tell you that the host is
  2115. unreachable.
  2116. Fix is to add the check in ConnectDialog::mfn_ValidateData() (connect.cpp):
  2117. ...
  2118. if (ehConnectionIF == *m_pehSelectedInterfaceId)
  2119. {
  2120. if (iSpec.m_NlbCfg.fDHCP)
  2121. {
  2122. put up a message box and return error.
  2123. }
  2124. }