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.

461 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998.
  5. //
  6. // File: S M U T I L . C P P
  7. //
  8. // Contents: Utility functions to help out the status monitor
  9. //
  10. // Notes:
  11. //
  12. // Author: CWill 2 Dec 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "netcon.h"
  18. #include "nsres.h"
  19. #include "sminc.h"
  20. const UINT c_uiKilo = 1000;
  21. const UINT c_cmsSecond = 1;
  22. const UINT c_cmsMinute = (c_cmsSecond * 60);
  23. const UINT c_cmsHour = (c_cmsMinute * 60);
  24. const UINT c_cmsDay = (c_cmsHour * 24);
  25. static const WCHAR c_szZero[] = L"0";
  26. extern const WCHAR c_szSpace[];
  27. struct StatusIconMapEntry
  28. {
  29. NETCON_MEDIATYPE ncm;
  30. BOOL fInbound;
  31. BOOL fTransmitting;
  32. BOOL fReceiving;
  33. INT iStatusIcon;
  34. };
  35. static const StatusIconMapEntry c_SIMEArray[] =
  36. {
  37. // Mediatype
  38. // | Inbound
  39. // | | Transmitting
  40. // | | | Receiving
  41. // | | | | 32x32 Status Icon
  42. // | | | | |
  43. // v v v v v
  44. // Dial-up
  45. NCM_PHONE, FALSE, FALSE, FALSE, IDI_PO_NON_M_16,
  46. NCM_PHONE, FALSE, FALSE, TRUE, IDI_PO_RCV_M_16,
  47. NCM_PHONE, FALSE, TRUE, FALSE, IDI_PO_TRN_M_16,
  48. NCM_PHONE, FALSE, TRUE, TRUE, IDI_PO_CON_M_16,
  49. NCM_PHONE, TRUE, FALSE, FALSE, IDI_PI_NON_M_16,
  50. NCM_PHONE, TRUE, FALSE, TRUE, IDI_PI_RCV_M_16,
  51. NCM_PHONE, TRUE, TRUE, FALSE, IDI_PI_TRN_M_16,
  52. NCM_PHONE, TRUE, TRUE, TRUE, IDI_PI_CON_M_16,
  53. // LAN
  54. NCM_LAN, FALSE, FALSE, FALSE, IDI_LB_NON_M_16,
  55. NCM_LAN, FALSE, FALSE, TRUE, IDI_LB_RCV_M_16,
  56. NCM_LAN, FALSE, TRUE, FALSE, IDI_LB_TRN_M_16,
  57. NCM_LAN, FALSE, TRUE, TRUE, IDI_LB_CON_M_16,
  58. // Direct connect
  59. NCM_DIRECT, FALSE, FALSE, FALSE, IDI_DO_NON_M_16,
  60. NCM_DIRECT, FALSE, FALSE, TRUE, IDI_DO_RCV_M_16,
  61. NCM_DIRECT, FALSE, TRUE, FALSE, IDI_DO_TRN_M_16,
  62. NCM_DIRECT, FALSE, TRUE, TRUE, IDI_DO_CON_M_16,
  63. NCM_DIRECT, TRUE, FALSE, FALSE, IDI_DI_NON_M_16,
  64. NCM_DIRECT, TRUE, FALSE, TRUE, IDI_DI_RCV_M_16,
  65. NCM_DIRECT, TRUE, TRUE, FALSE, IDI_DI_TRN_M_16,
  66. NCM_DIRECT, TRUE, TRUE, TRUE, IDI_DI_CON_M_16,
  67. // Tunnel
  68. NCM_TUNNEL, FALSE, FALSE, FALSE, IDI_TO_NON_M_16,
  69. NCM_TUNNEL, FALSE, FALSE, TRUE, IDI_TO_RCV_M_16,
  70. NCM_TUNNEL, FALSE, TRUE, FALSE, IDI_TO_TRN_M_16,
  71. NCM_TUNNEL, FALSE, TRUE, TRUE, IDI_TO_CON_M_16,
  72. NCM_TUNNEL, TRUE, FALSE, FALSE, IDI_TI_NON_M_16,
  73. NCM_TUNNEL, TRUE, FALSE, TRUE, IDI_TI_RCV_M_16,
  74. NCM_TUNNEL, TRUE, TRUE, FALSE, IDI_TI_TRN_M_16,
  75. NCM_TUNNEL, TRUE, TRUE, TRUE, IDI_TI_CON_M_16,
  76. // ISDN
  77. NCM_ISDN, FALSE, FALSE, FALSE, IDI_PO_NON_M_16,
  78. NCM_ISDN, FALSE, FALSE, TRUE, IDI_PO_RCV_M_16,
  79. NCM_ISDN, FALSE, TRUE, FALSE, IDI_PO_TRN_M_16,
  80. NCM_ISDN, FALSE, TRUE, TRUE, IDI_PO_CON_M_16,
  81. NCM_ISDN, TRUE, FALSE, FALSE, IDI_PI_NON_M_16,
  82. NCM_ISDN, TRUE, FALSE, TRUE, IDI_PI_RCV_M_16,
  83. NCM_ISDN, TRUE, TRUE, FALSE, IDI_PI_TRN_M_16,
  84. NCM_ISDN, TRUE, TRUE, TRUE, IDI_PI_CON_M_16,
  85. // PPPoE
  86. NCM_PPPOE, FALSE, FALSE, FALSE, IDI_BR_NON_M_16,
  87. NCM_PPPOE, FALSE, FALSE, TRUE, IDI_BR_RCV_M_16,
  88. NCM_PPPOE, FALSE, TRUE, FALSE, IDI_BR_TRN_M_16,
  89. NCM_PPPOE, FALSE, TRUE, TRUE, IDI_BR_CON_M_16,
  90. // SHAREDACCESSHOST
  91. NCM_SHAREDACCESSHOST_LAN, FALSE, FALSE, FALSE, IDI_LB_NON_M_16,
  92. NCM_SHAREDACCESSHOST_LAN, FALSE, FALSE, TRUE, IDI_LB_RCV_M_16,
  93. NCM_SHAREDACCESSHOST_LAN, FALSE, TRUE, FALSE, IDI_LB_TRN_M_16,
  94. NCM_SHAREDACCESSHOST_LAN, FALSE, TRUE, TRUE, IDI_LB_CON_M_16,
  95. NCM_SHAREDACCESSHOST_RAS, FALSE, FALSE, FALSE, IDI_LB_NON_M_16,
  96. NCM_SHAREDACCESSHOST_RAS, FALSE, FALSE, TRUE, IDI_LB_RCV_M_16,
  97. NCM_SHAREDACCESSHOST_RAS, FALSE, TRUE, FALSE, IDI_LB_TRN_M_16,
  98. NCM_SHAREDACCESSHOST_RAS, FALSE, TRUE, TRUE, IDI_LB_CON_M_16,
  99. };
  100. const DWORD g_dwStatusIconMapEntryCount = celems(c_SIMEArray);
  101. //+---------------------------------------------------------------------------
  102. //
  103. // Function: HrGetPcpFromPnse
  104. //
  105. // Purpose: Gets the connection point off of an INetStatistics Engine
  106. //
  107. // Arguments: pnseSrc - The interface we want to get the connection
  108. // point off of
  109. // ppcpStatEng - Where to return the connection point
  110. //
  111. // Returns: Error code.
  112. //
  113. HRESULT HrGetPcpFromPnse(
  114. INetStatisticsEngine* pnseSrc,
  115. IConnectionPoint** ppcpStatEng)
  116. {
  117. HRESULT hr = S_OK;
  118. IConnectionPointContainer* pcpcStatEng = NULL;
  119. AssertSz(pnseSrc, "We should have a pnseSrc");
  120. AssertSz(ppcpStatEng, "We should have a ppcpStatEng");
  121. hr = pnseSrc->QueryInterface(IID_IConnectionPointContainer,
  122. reinterpret_cast<VOID**>(&pcpcStatEng));
  123. if (SUCCEEDED(hr))
  124. {
  125. // Find the interface
  126. hr = pcpcStatEng->FindConnectionPoint(
  127. IID_INetConnectionStatisticsNotifySink,
  128. ppcpStatEng);
  129. // Release the connection point
  130. ReleaseObj(pcpcStatEng);
  131. }
  132. TraceError("HrGetPcpFromPnse", hr);
  133. return hr;
  134. }
  135. //+---------------------------------------------------------------------------
  136. //
  137. // Member: IGetCurrentConnectionTrayIconId
  138. //
  139. // Purpose: Get the INetConnection pointer from the persisted data
  140. //
  141. // Arguments: ncmType - Media type
  142. // dwChangeFlags - What states have changed
  143. //
  144. // Returns: The id of the small icon for the connection or -1 on failure
  145. //
  146. // Notes:
  147. //
  148. INT IGetCurrentConnectionTrayIconId(NETCON_MEDIATYPE ncmType, NETCON_STATUS ncsStatus, DWORD dwChangeFlags)
  149. {
  150. INT iBaseIcon = -1;
  151. // Check the trans/recv flags to see what our base icon is.
  152. //
  153. if (ncsStatus == NCS_INVALID_ADDRESS)
  154. {
  155. iBaseIcon = IDI_CFT_INVALID_ADDRESS;
  156. }
  157. else
  158. {
  159. if (SMDCF_TRANSMITTING & dwChangeFlags)
  160. {
  161. if (SMDCF_RECEIVING & dwChangeFlags)
  162. {
  163. // Transmitting and receiving
  164. iBaseIcon = IDI_CFT_XMTRECV;
  165. }
  166. else
  167. {
  168. // Transmitting only
  169. iBaseIcon = IDI_CFT_XMT;
  170. }
  171. }
  172. else
  173. {
  174. if (SMDCF_RECEIVING & dwChangeFlags)
  175. {
  176. // Receiving only
  177. iBaseIcon = IDI_CFT_RECV;
  178. }
  179. else
  180. {
  181. // Neither transmitting nor receiving
  182. iBaseIcon = IDI_CFT_BLANK;
  183. }
  184. }
  185. }
  186. return iBaseIcon;
  187. }
  188. //+---------------------------------------------------------------------------
  189. //
  190. // Member: GetCurrentConnectionStatusIconId
  191. //
  192. // Purpose: Get the INetConnection pointer from the persisted data
  193. //
  194. // Arguments: ncmType - Media type
  195. // ncsmType - SubMedia type
  196. // dwCharacteristics - Connection characteristics
  197. // dwChangeFlags - What states have changed
  198. //
  199. // Returns: The id of the small icon for the connection or -1 on failure
  200. //
  201. // Notes:
  202. //
  203. HICON GetCurrentConnectionStatusIconId(
  204. NETCON_MEDIATYPE ncmType,
  205. NETCON_SUBMEDIATYPE ncsmType,
  206. DWORD dwCharacteristics,
  207. DWORD dwChangeFlags)
  208. {
  209. HICON hMyIcon = NULL;
  210. DWORD dwLoop = 0;
  211. BOOL fValidIcon = FALSE;
  212. BOOL fTransmitting = !!(dwChangeFlags & SMDCF_TRANSMITTING);
  213. BOOL fReceiving = !!(dwChangeFlags & SMDCF_RECEIVING);
  214. INT iStatusIcon = -1;
  215. // Loop through the map and find the appropriate icon
  216. //
  217. DWORD dwConnectionIcon = 0x4;
  218. dwConnectionIcon |= fTransmitting ? 0x2 : 0;
  219. dwConnectionIcon |= fReceiving ? 0x1 : 0;
  220. HRESULT hr = HrGetIconFromMediaType(GetSystemMetrics(SM_CXICON), ncmType, ncsmType, dwConnectionIcon, (dwCharacteristics & NCCF_INCOMING_ONLY), &hMyIcon);
  221. if (FAILED(hr))
  222. {
  223. return NULL;
  224. }
  225. return hMyIcon;
  226. }
  227. //+---------------------------------------------------------------------------
  228. //
  229. // Member: FIsStringInList
  230. //
  231. // Purpose: To see if a string is in a string list
  232. //
  233. // Arguments: plstpstrList - The list in which the string is to be found
  234. // szString - The string being looked for
  235. //
  236. // Returns: TRUE if the string is in the list
  237. // FALSE otherwise (including the case where the list is empty)
  238. //
  239. // Notes: It is an case insensitive search
  240. //
  241. BOOL FIsStringInList(list<tstring*>* plstpstrList, const WCHAR* szString)
  242. {
  243. BOOL fRet = FALSE;
  244. // Only look in non-empty lists
  245. //
  246. if (!plstpstrList->empty())
  247. {
  248. list<tstring*>::iterator iterLstpstr;
  249. iterLstpstr = plstpstrList->begin();
  250. while ((!fRet)
  251. && (iterLstpstr != plstpstrList->end()))
  252. {
  253. // See if the string in the list matches the string we are
  254. // comparing against
  255. //
  256. if (!lstrcmpiW((*iterLstpstr)->c_str(), szString))
  257. {
  258. fRet = TRUE;
  259. }
  260. iterLstpstr++;
  261. }
  262. }
  263. return fRet;
  264. }
  265. //+---------------------------------------------------------------------------
  266. //
  267. // Function: FormatBytesPerSecond
  268. //
  269. // Purpose: To format nicely BPS into a readable string.
  270. //
  271. // Arguments:
  272. // uiBps []
  273. // pchBuffer []
  274. //
  275. // Returns: Number of characters put into the buffer.
  276. //
  277. INT
  278. FormatBytesPerSecond (
  279. UINT64 uiBps,
  280. WCHAR* pchBuffer)
  281. {
  282. enum {eZero = 0, eKilo, eMega, eGiga, eTera, eMax};
  283. const WCHAR* pszBPSFormat = NULL;
  284. INT iOffset = 0;
  285. UINT uiDecimal = 0;
  286. // Make sure our resources are still in the correct order
  287. //
  288. AssertSz(((((IDS_SM_BPS_ZERO + eKilo) == IDS_SM_BPS_KILO)
  289. && (IDS_SM_BPS_ZERO + eMega) == IDS_SM_BPS_MEGA)
  290. && ((IDS_SM_BPS_ZERO + eGiga) == IDS_SM_BPS_GIGA)
  291. && ((IDS_SM_BPS_ZERO + eTera) == IDS_SM_BPS_TERA)),
  292. "Someone's been messing with the BPS format strings");
  293. for (iOffset = eZero; iOffset < eMax; iOffset++)
  294. {
  295. // If we still have data, increment the counter
  296. //
  297. if (c_uiKilo > uiBps)
  298. {
  299. break;
  300. }
  301. // Divide up the string
  302. //
  303. uiDecimal = (UINT)(uiBps % c_uiKilo);
  304. uiBps /= c_uiKilo;
  305. }
  306. // We only want one digit for the decimal
  307. //
  308. uiDecimal /= (c_uiKilo/10);
  309. // Get the string used to display
  310. //
  311. pszBPSFormat = SzLoadIds(IDS_SM_BPS_ZERO + iOffset);
  312. AssertSz(pszBPSFormat, "We need a format string for BPS");
  313. // Create the string
  314. //
  315. return wsprintfW(pchBuffer, pszBPSFormat, uiBps, uiDecimal);
  316. }
  317. INT
  318. FormatTransmittingReceivingSpeed(
  319. UINT64 nTransmitSpeed,
  320. UINT64 nRecieveSpeed,
  321. WCHAR* pchBuf)
  322. {
  323. WCHAR* pch = pchBuf;
  324. pch += FormatBytesPerSecond(nTransmitSpeed, pch);
  325. if (nTransmitSpeed != nRecieveSpeed)
  326. {
  327. // Separate with a backslash.
  328. //
  329. lstrcatW(pch, L"\\");
  330. pch += 1;
  331. pch += FormatBytesPerSecond(nRecieveSpeed, pch);
  332. }
  333. return lstrlenW(pchBuf);
  334. }
  335. //+---------------------------------------------------------------------------
  336. //
  337. // Function: FormatTimeDuration
  338. //
  339. // Purpose: Takes a millisecond count and formats a string with the
  340. // duration represented by the millisecond count.
  341. //
  342. // Arguments:
  343. // uiMilliseconds []
  344. // pstrOut []
  345. //
  346. // Returns: nothing
  347. //
  348. VOID FormatTimeDuration(UINT uiSeconds, tstring* pstrOut)
  349. {
  350. WCHAR achSep[4];
  351. WCHAR achBuf[64];
  352. UINT uiNumTemp;
  353. AssertSz(pstrOut, "We should have a pstrOut");
  354. // Get the seperator for the locale.
  355. //
  356. SideAssert(GetLocaleInfo(
  357. LOCALE_USER_DEFAULT,
  358. LOCALE_STIME,
  359. achSep,
  360. celems(achSep)));
  361. //
  362. // Concatenate the strings together
  363. //
  364. // Add the days if there are more than zero
  365. //
  366. uiNumTemp = (uiSeconds / c_cmsDay);
  367. if (uiNumTemp > 0)
  368. {
  369. pstrOut->append(_itow(uiNumTemp, achBuf, 10));
  370. uiSeconds %= c_cmsDay;
  371. if (uiNumTemp>1)
  372. pstrOut->append(SzLoadIds(IDS_Days));
  373. else
  374. pstrOut->append(SzLoadIds(IDS_Day));
  375. pstrOut->append(c_szSpace);
  376. }
  377. // Append hours
  378. //
  379. uiNumTemp = (uiSeconds / c_cmsHour);
  380. if (10 > uiNumTemp)
  381. {
  382. pstrOut->append(c_szZero);
  383. }
  384. pstrOut->append(_itow(uiNumTemp, achBuf, 10));
  385. pstrOut->append(achSep);
  386. uiSeconds %= c_cmsHour;
  387. // Append minutes
  388. //
  389. uiNumTemp = (uiSeconds / c_cmsMinute);
  390. if (10 > uiNumTemp)
  391. {
  392. pstrOut->append(c_szZero);
  393. }
  394. pstrOut->append(_itow(uiNumTemp, achBuf, 10));
  395. pstrOut->append(achSep);
  396. uiSeconds %= c_cmsMinute;
  397. // Append seconds
  398. //
  399. uiNumTemp = (uiSeconds / c_cmsSecond);
  400. if (10 > uiNumTemp)
  401. {
  402. pstrOut->append(c_szZero);
  403. }
  404. pstrOut->append(_itow(uiNumTemp, achBuf, 10));
  405. }