Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

518 lines
18 KiB

  1. /*++
  2. Copyright(c) 1998,99 Microsoft Corporation
  3. Module Name:
  4. host.cpp
  5. Abstract:
  6. Windows Load Balancing Service (WLBS)
  7. Notifier object UI - host config tab
  8. Author:
  9. kyrilf
  10. shouse
  11. --*/
  12. #include "pch.h"
  13. #pragma hdrstop
  14. #include "ncatlui.h"
  15. #include "resource.h"
  16. #include "wlbsparm.h"
  17. #include "wlbscfg.h"
  18. #include "host.h"
  19. #include "utils.h"
  20. #if DBG
  21. static void TraceMsg(PCTSTR pszFormat, ...);
  22. #else
  23. #define TraceMsg NOP_FUNCTION
  24. #endif
  25. /*
  26. * Method: CDialogHost
  27. * Description: The class constructor.
  28. */
  29. CDialogHost::CDialogHost (NETCFG_WLBS_CONFIG * paramp, const DWORD * adwHelpIDs) {
  30. TraceMsg(L"CDialogHost::CDialogHost\n");
  31. m_paramp = paramp;
  32. m_adwHelpIDs = adwHelpIDs;
  33. ZeroMemory(&m_IPFieldChangeState, sizeof(m_IPFieldChangeState));
  34. }
  35. /*
  36. * Method: ~CDialogHost
  37. * Description: The class destructor.
  38. */
  39. CDialogHost::~CDialogHost () {
  40. TraceMsg(L"CDialogHost::~CDialogHost\n");
  41. }
  42. /*
  43. * Method: OnInitDialog
  44. * Description: Called to initialize the host properties dialog.
  45. */
  46. LRESULT CDialogHost::OnInitDialog (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & fHandled) {
  47. TraceMsg(L"CDialogHost::OnInitDialog\n");
  48. /* Always tell NetCfg that the page has changed, so we don't have to keep track of this. */
  49. SetChangedFlag();
  50. /* Limit the field ranges for the address and priority fields. */
  51. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, EM_SETLIMITTEXT, CVY_MAX_DED_IP_ADDR, 0);
  52. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_MASK, EM_SETLIMITTEXT, CVY_MAX_DED_NET_MASK, 0);
  53. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_PRI, EM_SETLIMITTEXT, 2, 0);
  54. ::SendDlgItemMessage(m_hWnd, IDC_SPIN_PRI, UDM_SETRANGE32, CVY_MIN_MAX_HOSTS, m_paramp->dwMaxHosts);
  55. /* Limit the zeroth field of the dedicated IP address between 1 and 223. */
  56. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, IPM_SETRANGE, 0, (LPARAM)MAKEIPRANGE(WLBS_IP_FIELD_ZERO_LOW, WLBS_IP_FIELD_ZERO_HIGH));
  57. /* If the cluster IP address or subnet mask are the default values, set them to NUL strings. */
  58. if (!wcscmp(m_paramp->ded_ip_addr, CVY_DEF_DED_IP_ADDR)) m_paramp->ded_ip_addr[0] = 0;
  59. if (!wcscmp(m_paramp->ded_net_mask, CVY_DEF_DED_NET_MASK)) m_paramp->ded_net_mask[0] = 0;
  60. return 0;
  61. }
  62. /*
  63. * Method: OnContextMenu
  64. * Description:
  65. */
  66. LRESULT CDialogHost::OnContextMenu (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & fHandled) {
  67. TraceMsg(L"CDialogHost::OnContextMenu\n");
  68. /* Spawn a help window. */
  69. if (m_adwHelpIDs != NULL)
  70. ::WinHelp(m_hWnd, CVY_CTXT_HELP_FILE, HELP_CONTEXTMENU, (ULONG_PTR)m_adwHelpIDs);
  71. return 0;
  72. }
  73. /*
  74. * Method: OnHelp
  75. * Description:
  76. */
  77. LRESULT CDialogHost::OnHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & fHandled) {
  78. TraceMsg(L"CDialogHost::OnHelp\n");
  79. LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
  80. /* Spawn a help window. */
  81. if ((HELPINFO_WINDOW == lphi->iContextType) && (m_adwHelpIDs != NULL))
  82. ::WinHelp(static_cast<HWND>(lphi->hItemHandle), CVY_CTXT_HELP_FILE, HELP_WM_HELP, (ULONG_PTR)m_adwHelpIDs);
  83. return 0;
  84. }
  85. /*
  86. * Method: OnActive
  87. * Description: Called when the host settings tab becomes active (is clicked).
  88. */
  89. LRESULT CDialogHost::OnActive (int idCtrl, LPNMHDR pnmh, BOOL & fHandled) {
  90. TraceMsg(L"CDialogHost::OnActive\n");
  91. /* Populate the UI with the current configuration. */
  92. SetInfo();
  93. ::SetWindowLongPtr(m_hWnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  94. return 0;
  95. }
  96. /*
  97. * Method: OnKillActive
  98. * Description: Called When the focus moves away from the host settings tab.
  99. */
  100. LRESULT CDialogHost::OnKillActive (int idCtrl, LPNMHDR pnmh, BOOL & fHandled) {
  101. TraceMsg(L"CDialogHost::OnKillActive\n");
  102. /* Get the new configuration from the UI. */
  103. UpdateInfo();
  104. ::SetWindowLongPtr(m_hWnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  105. return 0;
  106. }
  107. /*
  108. * Method: OnApply
  109. * Description: Called when the user clicks "OK".
  110. */
  111. LRESULT CDialogHost::OnApply (int idCtrl, LPNMHDR pnmh, BOOL & fHandled) {
  112. LRESULT fError = PSNRET_NOERROR;
  113. TraceMsg(L"CDialogHost::OnApply\n");
  114. /* Validate the UI values entered by the user. */
  115. fError = ValidateInfo();
  116. /* If the user has not specified dedicated IP address information, copy the defaults back. */
  117. if (!fError && !m_paramp->ded_ip_addr[0]) lstrcpy(m_paramp->ded_ip_addr, CVY_DEF_DED_IP_ADDR);
  118. if (!fError && !m_paramp->ded_net_mask[0]) lstrcpy(m_paramp->ded_net_mask, CVY_DEF_DED_NET_MASK);
  119. ::SetWindowLongPtr(m_hWnd, DWLP_MSGRESULT, fError);
  120. return fError;
  121. }
  122. /*
  123. * Method: OnCancel
  124. * Description: Called when the user clicks "Cancel".
  125. */
  126. LRESULT CDialogHost::OnCancel (int idCtrl, LPNMHDR pnmh, BOOL & fHandled) {
  127. TraceMsg(L"CDialogHost::OnCancel\n");
  128. return 0;
  129. }
  130. /*
  131. * Method: OnEditDedMask
  132. * Description: Called when the user modifies the host netmask.
  133. */
  134. LRESULT CDialogHost::OnEditDedMask (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL & fHandled) {
  135. WCHAR ded_ip_addr [CVY_MAX_DED_IP_ADDR + 1];
  136. WCHAR ded_mask_addr [CVY_MAX_DED_NET_MASK + 1];
  137. TraceMsg(L"CDialogHost::OnEditDedMask\n");
  138. switch (wNotifyCode) {
  139. case EN_SETFOCUS:
  140. /* Only generate a netmask if the netmask is currently empty and the IP address is not. */
  141. if (::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_ISBLANK, 0, 0) &&
  142. !::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_ISBLANK, 0, 0)) {
  143. /* Retrieve the cluster IP address. */
  144. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, WM_GETTEXT, CVY_MAX_DED_IP_ADDR + 1, (LPARAM)ded_ip_addr);
  145. /* Fill the subnet mask. */
  146. ParamsGenerateSubnetMask(ded_ip_addr, ded_mask_addr);
  147. /* Set the cluster subnet mask. */
  148. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_MASK, WM_SETTEXT, 0, (LPARAM)ded_mask_addr);
  149. break;
  150. }
  151. }
  152. return 0;
  153. }
  154. /*
  155. * Method: PrintRangeError
  156. * Description: Displays a message box warning the user of an out-of-range entry.
  157. */
  158. void CDialogHost::PrintRangeError (unsigned int ids, int low, int high) {
  159. WCHAR szLow[10];
  160. WCHAR szHigh[10];
  161. TraceMsg(L"CDialogHost::PrintRangeError\n");
  162. /* Fill in the range and the offending value. */
  163. wsprintfW(szHigh, L"%d", high);
  164. wsprintfW(szLow, L"%d", low);
  165. /* Pop-up a message box. */
  166. NcMsgBox(m_hWnd, IDS_PARM_ERROR, ids, MB_APPLMODAL | MB_ICONSTOP | MB_OK, szLow, szHigh);
  167. }
  168. /*
  169. * Method: PrintIPRangeError
  170. * Description: Displays a message box warning the user of an out-of-range entry in
  171. * an IP address octet.
  172. */
  173. void CDialogHost::PrintIPRangeError (unsigned int ids, int value, int low, int high) {
  174. WCHAR szCurrent[10];
  175. WCHAR szLow[10];
  176. WCHAR szHigh[10];
  177. TraceMsg(L"CDialogHost::PrintIPRangeError\n");
  178. /* Fill in the range and the offending value. */
  179. wsprintfW(szHigh, L"%d", high);
  180. wsprintfW(szCurrent, L"%d", value);
  181. wsprintfW(szLow, L"%d", low);
  182. /* Pop-up a message box. */
  183. NcMsgBox(m_hWnd, IDS_PARM_ERROR, ids, MB_APPLMODAL | MB_ICONSTOP | MB_OK, szCurrent, szLow, szHigh);
  184. }
  185. /*
  186. * Method: OnIpFieldChange
  187. * Description: Called wnen a field (byte) of the dedicated IP address changes. We use this
  188. * to make sure the first byte of the IP is not < 1 or > 223.
  189. */
  190. LRESULT CDialogHost::OnIpFieldChange (int idCtrl, LPNMHDR pnmh, BOOL & fHandled) {
  191. LPNMIPADDRESS Ip;
  192. int low = WLBS_FIELD_LOW;
  193. int high = WLBS_FIELD_HIGH;
  194. TraceMsg(L"CDialogHost::OnIpFieldChange\n");
  195. Ip = (LPNMIPADDRESS)pnmh;
  196. switch(idCtrl) {
  197. case IDC_EDIT_DED_IP:
  198. /* Field zero of the cluster IP address has different limits. */
  199. if (!Ip->iField) {
  200. low = WLBS_IP_FIELD_ZERO_LOW;
  201. high = WLBS_IP_FIELD_ZERO_HIGH;
  202. }
  203. case IDC_EDIT_DED_MASK:
  204. /* The notifier may call us twice for the same change, so we have to do the bookkeeping to make
  205. sure we only alert the user once. Use static variables to keep track of our state. This will
  206. allow us to ignore duplicate alerts. */
  207. if ((m_IPFieldChangeState.IpControl != Ip->hdr.idFrom) || (m_IPFieldChangeState.Field != Ip->iField) ||
  208. (m_IPFieldChangeState.Value != Ip->iValue) || (m_IPFieldChangeState.RejectTimes > 0)) {
  209. m_IPFieldChangeState.RejectTimes = 0;
  210. m_IPFieldChangeState.IpControl = Ip->hdr.idFrom;
  211. m_IPFieldChangeState.Field = Ip->iField;
  212. m_IPFieldChangeState.Value = Ip->iValue;
  213. /* Check the field value against its limits. */
  214. if ((Ip->iValue != WLBS_FIELD_EMPTY) && ((Ip->iValue < low) || (Ip->iValue > high))) {
  215. /* Alert the user. */
  216. PrintIPRangeError((idCtrl == IDC_EDIT_DED_IP) ? IDS_PARM_DED_IP_FIELD : IDS_PARM_DED_NM_FIELD, Ip->iValue, low, high);
  217. }
  218. } else m_IPFieldChangeState.RejectTimes++;
  219. break;
  220. default:
  221. break;
  222. }
  223. return 0;
  224. }
  225. /*
  226. * Method: SetInfo
  227. * Description: Called to populate the UI with the current host settings.
  228. */
  229. void CDialogHost::SetInfo () {
  230. DWORD addr[4];
  231. TraceMsg(L"CDialogHost::SetInfo\n");
  232. /* Check (or uncheck) the initial cluster statecheckbox. */
  233. ::CheckDlgButton(m_hWnd, IDC_CHECK_ACTIVE, m_paramp->fJoinClusterOnBoot);
  234. /* If the dedicated IP address is empty, then clear the entry box. Otherwise, populate it with the IP address. */
  235. if (!m_paramp->ded_ip_addr[0])
  236. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_CLEARADDRESS, 0, 0);
  237. else {
  238. /* Extract the IP address octects from the IP address string. */
  239. GetIPAddressOctets(m_paramp->ded_ip_addr, addr);
  240. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_SETADDRESS, 0, (LPARAM)MAKEIPADDRESS(addr[0], addr[1], addr[2], addr[3]));
  241. }
  242. /* If the host subnet mask is empty, then clear the entry box. Otherwise, populate it with the netmask. */
  243. if (!m_paramp->ded_net_mask[0])
  244. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_CLEARADDRESS, 0, 0);
  245. else {
  246. /* Extract the IP address octects from the IP address string. */
  247. GetIPAddressOctets(m_paramp->ded_net_mask, addr);
  248. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_SETADDRESS, 0, (LPARAM)MAKEIPADDRESS(addr[0], addr[1], addr[2], addr[3]));
  249. }
  250. /* Fill in the host priority entry box. If the entry is blank, insert an empty string. */
  251. if (m_paramp->dwHostPriority != WLBS_BLANK_HPRI)
  252. ::SetDlgItemInt(m_hWnd, IDC_EDIT_PRI, m_paramp->dwHostPriority, FALSE);
  253. else
  254. ::SetDlgItemText(m_hWnd, IDC_EDIT_PRI, L"");
  255. }
  256. /*
  257. * Method: UpdateInfo
  258. * Description: Called to copy the UI state to the host configuration.
  259. */
  260. void CDialogHost::UpdateInfo () {
  261. BOOL fValid = TRUE;
  262. TraceMsg(L"CDialogHost::UpdateInfo\n");
  263. /* Retrieve the active on boot flag value. */
  264. m_paramp->fJoinClusterOnBoot = ::IsDlgButtonChecked(m_hWnd, IDC_CHECK_ACTIVE) == 1;
  265. /* If the dedicated IP entry box is empty, then the dedicated IP address is NUL. Otherwise, grab it from the UI. */
  266. if (::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_ISBLANK, 0, 0))
  267. m_paramp->ded_ip_addr[0] = 0;
  268. else
  269. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, WM_GETTEXT, CVY_MAX_DED_IP_ADDR, (LPARAM)m_paramp->ded_ip_addr);
  270. /* If the host net mask entry box is empty, then the host net mask is NUL. Otherwise, grab it from the UI. */
  271. if (::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_ISBLANK, 0, 0))
  272. m_paramp->ded_net_mask[0] = 0;
  273. else
  274. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_MASK, WM_GETTEXT, CVY_MAX_DED_NET_MASK, (LPARAM)m_paramp->ded_net_mask);
  275. /* Retrieve the host priority from the entry box. */
  276. m_paramp->dwHostPriority = ::GetDlgItemInt(m_hWnd, IDC_EDIT_PRI, &fValid, FALSE);
  277. /* The error code from GetDlgItemInt() indicates an error converting the alphanumeric
  278. string to an integer. This allows us to check for empty fields, assuming that because
  279. we otherwise limit the user input to digits, there will be no errors of any other type.
  280. In this case, we set the priority to a sentinnel value that will be checked later. */
  281. if (!fValid) m_paramp->dwHostPriority = WLBS_BLANK_HPRI;
  282. }
  283. /*
  284. * Method: ValidateInfo
  285. * Description: Called to validate the entries made by the user.
  286. */
  287. BOOL CDialogHost::ValidateInfo () {
  288. BOOL fError = FALSE;
  289. DWORD IPAddr;
  290. TraceMsg(L"CDialogHost::ValidateInfo\n");
  291. /* Check for an invalid host priority. */
  292. if ((m_paramp->dwHostPriority < CVY_MIN_HOST_PRIORITY) || (m_paramp->dwHostPriority > m_paramp->dwMaxHosts)) {
  293. /* Help the user by setting the priority to the closest viable value. */
  294. if (m_paramp->dwHostPriority != WLBS_BLANK_HPRI) {
  295. /* Alert the user. */
  296. PrintRangeError(IDS_PARM_PRI, CVY_MIN_HOST_PRIORITY, CVY_MAX_HOST_PRIORITY);
  297. CVY_CHECK_MIN(m_paramp->dwHostPriority, CVY_MIN_HOST_PRIORITY);
  298. CVY_CHECK_MAX(m_paramp->dwHostPriority, CVY_MAX_HOST_PRIORITY);
  299. /* Set the handling priority to the now valid entry. */
  300. ::SetDlgItemInt(m_hWnd, IDC_EDIT_PRI, m_paramp->dwHostPriority, FALSE);
  301. } else {
  302. /* Alert the user. */
  303. PrintRangeError(IDS_PARM_PRI_BLANK, CVY_MIN_HOST_PRIORITY, CVY_MAX_HOST_PRIORITY);
  304. }
  305. /* An error occurred. */
  306. return PSNRET_INVALID;
  307. }
  308. /* Check for blank dedicated IP address with a non-empty netmask. */
  309. if (!::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_ISBLANK, 0, 0) &&
  310. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_ISBLANK, 0, 0)) {
  311. /* Alert the user. */
  312. NcMsgBox(::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_DED_IP_BLANK,
  313. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  314. /* An error occurred. */
  315. return PSNRET_INVALID;
  316. }
  317. /* Check for blank netmask with a non-empty dedicated IP address and fill in the netmask if necessary. */
  318. if (!::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_ISBLANK, 0, 0) &&
  319. ::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_ISBLANK, 0, 0)) {
  320. /* Fill in the netmask for the user. */
  321. OnEditDedMask(EN_SETFOCUS, 0, 0, fError);
  322. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_MASK, WM_GETTEXT, CVY_MAX_DED_NET_MASK, (LPARAM)m_paramp->ded_net_mask);
  323. /* Alert the user. */
  324. NcMsgBox(::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_DED_NM_BLANK,
  325. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  326. /* An error occurred. */
  327. return PSNRET_INVALID;
  328. }
  329. /* Only perform the rest of the IP checking if the user has specified both a dedicated
  330. IP address and a corresponding netmask. */
  331. if (!::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_IP), IPM_ISBLANK, 0, 0) &&
  332. !::SendMessage(::GetDlgItem(m_hWnd, IDC_EDIT_DED_MASK), IPM_ISBLANK, 0, 0)) {
  333. /* Get the dedicated IP address. */
  334. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, IPM_GETADDRESS, 0, (LPARAM)&IPAddr);
  335. /* Make sure that the first octet is not zero. If it is, make it 1 and alter the user. */
  336. if (!FIRST_IPADDRESS(IPAddr)) {
  337. /* Make the first octet 1 instead of the erroneous 0. */
  338. IPAddr = IPAddr | (DWORD)(WLBS_IP_FIELD_ZERO_LOW << 24);
  339. /* Set the IP address and update our dedicated IP address string. */
  340. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, IPM_SETADDRESS, 0, (LPARAM)IPAddr);
  341. ::SendDlgItemMessage(m_hWnd, IDC_EDIT_DED_IP, WM_GETTEXT, CVY_MAX_DED_IP_ADDR, (LPARAM)m_paramp->ded_ip_addr);
  342. /* Alert the user. */
  343. PrintIPRangeError(IDS_PARM_DED_IP_FIELD, 0, WLBS_IP_FIELD_ZERO_LOW, WLBS_IP_FIELD_ZERO_HIGH);
  344. return PSNRET_INVALID;
  345. }
  346. /* Check for valid dedicated IP address/netmask pairs. */
  347. if (!IsValidIPAddressSubnetMaskPair(m_paramp->ded_ip_addr, m_paramp->ded_net_mask)) {
  348. /* Alert the user. */
  349. NcMsgBox(::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_INVAL_DED_IP,
  350. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  351. /* An error occurred. */
  352. return PSNRET_INVALID;
  353. }
  354. /* Check to make sure that the netmask is contiguous. */
  355. if (!IsContiguousSubnetMask(m_paramp->ded_net_mask)) {
  356. /* Alert the user. */
  357. NcMsgBox(::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_INVAL_DED_MASK,
  358. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  359. /* An error occurred. */
  360. return PSNRET_INVALID;
  361. }
  362. /* Check if the Dedicated IP Address is not the same as one of the VIPs */
  363. DWORD dwNumRules = m_paramp->dwNumRules;
  364. while(dwNumRules--)
  365. {
  366. if (IpAddressFromAbcdWsz(m_paramp->ded_ip_addr) == IpAddressFromAbcdWsz(m_paramp->port_rules[dwNumRules].virtual_ip_addr))
  367. {
  368. /* Alert the user. */
  369. NcMsgBox(::GetActiveWindow(), IDS_PARM_ERROR, IDS_PARM_DIP_CONFLICT_VIP,
  370. MB_APPLMODAL | MB_ICONSTOP | MB_OK);
  371. /* An error occurred. */
  372. return PSNRET_INVALID;
  373. }
  374. }
  375. }
  376. return PSNRET_NOERROR;
  377. }
  378. #if DBG
  379. /*
  380. * Function: TraceMsg
  381. * Description: Generate a trace or error message.
  382. */
  383. void TraceMsg (PCWSTR pszFormat, ...) {
  384. static WCHAR szTempBufW[4096];
  385. static CHAR szTempBufA[4096];
  386. va_list arglist;
  387. va_start(arglist, pszFormat);
  388. vswprintf(szTempBufW, pszFormat, arglist);
  389. /* Convert the WCHAR to CHAR. This is for backward compatability with TraceMsg
  390. so that it was not necessary to change all pre-existing calls thereof. */
  391. WideCharToMultiByte(CP_ACP, 0, szTempBufW, -1, szTempBufA, 4096, NULL, NULL);
  392. /* Traced messages are now sent through the netcfg TraceTag routine so that
  393. they can be turned on/off dynamically. */
  394. TraceTag(ttidWlbs, szTempBufA);
  395. va_end(arglist);
  396. }
  397. #endif