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.

1809 lines
43 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (C) Microsoft Corporation, 1995 - 1999
  4. *
  5. * File: irmon.c
  6. *
  7. * Description: Infrared monitor
  8. *
  9. * Author: mbert/mikezin
  10. *
  11. * Date: 3/1/98
  12. *
  13. */
  14. #define UNICODE
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <windows.h>
  21. #include <winsock2.h>
  22. #include <af_irda.h>
  23. #include <shellapi.h>
  24. #include <resource.h>
  25. #include <resrc1.h>
  26. #include <irioctl.h>
  27. // allocate storage! and initialize the GUIDS
  28. #include <initguid.h>
  29. #include <devguid.h>
  30. #include <setupapi.h>
  31. #include <cfgmgr32.h>
  32. #include <mmsystem.h>
  33. #include "internal.h"
  34. #include <devlist.h>
  35. #include <irtypes.h>
  36. #include <ssdp.h>
  37. #include <irmon.h>
  38. #include "irdisc.h"
  39. #define BUILD_SERVICE_EXE 1
  40. #define WM_IP_DEVICE_CHANGE (WM_USER+500)
  41. #define WM_IR_DEVICE_CHANGE (WM_USER+501)
  42. #define WM_IR_LINK_CHANGE (WM_USER+502)
  43. #define IRXFER_DLL TEXT("irxfer.dll")
  44. #define IAS_LSAP_SEL "IrDA:TinyTP:LsapSel"
  45. #define IRXFER_CLASSNAME "OBEX:IrXfer"
  46. #define IRXFER_CLASSNAME2 "OBEX"
  47. #define IRMON_SERVICE_NAME TEXT("irmon")
  48. #define IRMON_CONFIG_KEY TEXT("System\\CurrentControlSet\\Services\\Irmon")
  49. #define IRMON_SHOW_ICON_KEY TEXT("ShowTrayIcon")
  50. #define IRMON_NO_SOUND_KEY TEXT("NoSound")
  51. #define TRANSFER_EXE TEXT("irxfer")
  52. #define PROPERTIES_EXE TEXT("irxfer /s")
  53. #define TASK_BAR_CREATED TEXT("TaskbarCreated")
  54. #define IRDA_DEVICE_NAME TEXT("\\Device\\IrDA")
  55. #define DEVICE_LIST_LEN 5
  56. #define TOOL_TIP_STR_SIZE 64
  57. #define EMPTY_STR TEXT("")
  58. #define SYSTRAYEVENTID WM_USER + 1
  59. #define EV_STOP_EVENT 0
  60. #define EV_LOGON_EVENT 1
  61. #define EV_LOGOFF_EVENT 2
  62. #define EV_REG_CHANGE_EVENT 3
  63. #define EV_TRAY_STATUS_EVENT 4
  64. #define MAX_ATTRIB_LEN 64
  65. #define MAKE_LT_UPDATE(a,b) (a << 16) + b
  66. #define RETRY_DSCV_TIMER 1
  67. #define RETRY_DSCV_INTERVAL 10000 // 10 seconds
  68. #define CONN_ANIMATION_TIMER 2
  69. #define CONN_ANIMATION_INTERVAL 250
  70. #define RETRY_TRAY_UPDATE_TIMER 3
  71. #define RETRY_TRAY_UPDATE_INTERVAL 4000 // 4 seconds
  72. #define WAIT_EVENT_CNT 5
  73. typedef enum
  74. {
  75. ICON_ST_NOICON,
  76. ICON_ST_CONN1 = 1,
  77. ICON_ST_CONN2,
  78. ICON_ST_CONN3,
  79. ICON_ST_CONN4,
  80. ICON_ST_IN_RANGE,
  81. ICON_ST_IP_IN_RANGE,
  82. /*
  83. ICON_ST_IDLE,
  84. ICON_ST_RX,
  85. ICON_ST_TX,
  86. ICON_ST_RXTX,
  87. */
  88. ICON_ST_INTR
  89. } ICON_STATE;
  90. typedef struct _IRMON_CONTROL {
  91. CRITICAL_SECTION Lock;
  92. PVOID IrxferContext;
  93. #ifdef IP_OBEX
  94. HANDLE SsdpContext;
  95. #endif
  96. HWND hWnd;
  97. WSAOVERLAPPED Overlapped;
  98. HANDLE DiscoveryObject;
  99. BOOL SoundOn;
  100. } IRMON_CONTROL, *PIRMON_CONTROL;
  101. IRMON_CONTROL GlobalIrmonControl;
  102. extern WAVE_NUM_DEV_FN WaveNumDev;
  103. SERVICE_STATUS_HANDLE IrmonStatusHandle;
  104. SERVICE_STATUS IrmonServiceStatus;
  105. HANDLE hIrmonEvents[WAIT_EVENT_CNT];
  106. BYTE FoundDevListBuf[ sizeof(OBEX_DEVICE_LIST) + sizeof(OBEX_DEVICE)*MAX_OBEX_DEVICES];
  107. OBEX_DEVICE_LIST * const pDeviceList=(POBEX_DEVICE_LIST)FoundDevListBuf;
  108. BYTE FoundIpListBuffer[sizeof(OBEX_DEVICE_LIST) + sizeof(OBEX_DEVICE)*MAX_OBEX_DEVICES];
  109. OBEX_DEVICE_LIST * const IpDeviceList=(POBEX_DEVICE_LIST)FoundIpListBuffer;
  110. LONG UpdatingIpAddressList=0;
  111. TCHAR IrmonClassName[] = TEXT("IrmonClass");
  112. BOOLEAN IconInTray;
  113. BOOLEAN IrmonStopped;
  114. HICON hInRange;
  115. HICON hIpInRange;
  116. HICON hInterrupt;
  117. HICON hConn1;
  118. HICON hConn2;
  119. HICON hConn3;
  120. HICON hConn4;
  121. /*
  122. HICON hIdle;
  123. HICON hTx;
  124. HICON hRxTx;
  125. HICON hRx;
  126. */
  127. IRLINK_STATUS LinkStatus;
  128. HINSTANCE ghInstance;
  129. BOOLEAN UserLoggedIn;
  130. BOOLEAN TrayEnabled;
  131. BOOLEAN DeviceListUpdated;
  132. //UINT gTaskbarCreated;
  133. UINT LastTrayUpdate; // debug purposes
  134. UINT_PTR RetryTrayUpdateTimerId;
  135. BOOLEAN RetryTrayUpdateTimerRunning;
  136. int TrayUpdateFailures;
  137. extern HANDLE g_UserToken;
  138. UINT_PTR ConnAnimationTimerId;
  139. TCHAR ConnDevName[64];
  140. UINT ConnIcon;
  141. int ConnAddition;
  142. BOOLEAN InterruptedSoundPlaying;
  143. HKEY ghCurrentUserKey = 0;
  144. BOOLEAN ShowBalloonTip;
  145. BOOLEAN IrxferDeviceInRange;
  146. HMODULE hIrxfer;
  147. HWINSTA hWinStaUser = 0;
  148. HWINSTA hSaveWinSta = 0;
  149. HDESK hDeskUser = 0;
  150. HDESK hSaveDesk = 0;
  151. extern BOOL ShowSendWindow();
  152. extern BOOL ShowPropertiesPage();
  153. extern
  154. void
  155. UpdateDiscoveredDevices(
  156. const OBEX_DEVICE_LIST *IrDevices,
  157. const OBEX_DEVICE_LIST *IpDevices
  158. );
  159. VOID
  160. InitiateLazyDscv(
  161. PIRMON_CONTROL IrmonControl
  162. );
  163. VOID
  164. InitiateLinkStatusQuery(
  165. PIRMON_CONTROL IrmonControl
  166. );
  167. VOID
  168. SetLogonStatus(BOOL LoggedOn);
  169. VOID
  170. MySetLogonStatus(BOOL LoggedOn);
  171. #if DBG
  172. TCHAR *
  173. GetLastErrorText()
  174. {
  175. switch (WSAGetLastError())
  176. {
  177. case WSAEINTR:
  178. return (TEXT("WSAEINTR"));
  179. break;
  180. case WSAEBADF:
  181. return(TEXT("WSAEBADF"));
  182. break;
  183. case WSAEACCES:
  184. return(TEXT("WSAEACCES"));
  185. break;
  186. case WSAEFAULT:
  187. return(TEXT("WSAEFAULT"));
  188. break;
  189. case WSAEINVAL:
  190. return(TEXT("WSAEINVAL"));
  191. break;
  192. case WSAEMFILE:
  193. return(TEXT("WSAEMFILE"));
  194. break;
  195. case WSAEWOULDBLOCK:
  196. return(TEXT("WSAEWOULDBLOCK"));
  197. break;
  198. case WSAEINPROGRESS:
  199. return(TEXT("WSAEINPROGRESS"));
  200. break;
  201. case WSAEALREADY:
  202. return(TEXT("WSAEALREADY"));
  203. break;
  204. case WSAENOTSOCK:
  205. return(TEXT("WSAENOTSOCK"));
  206. break;
  207. case WSAEDESTADDRREQ:
  208. return(TEXT("WSAEDESTADDRREQ"));
  209. break;
  210. case WSAEMSGSIZE:
  211. return(TEXT("WSAEMSGSIZE"));
  212. break;
  213. case WSAEPROTOTYPE:
  214. return(TEXT("WSAEPROTOTYPE"));
  215. break;
  216. case WSAENOPROTOOPT:
  217. return(TEXT("WSAENOPROTOOPT"));
  218. break;
  219. case WSAEPROTONOSUPPORT:
  220. return(TEXT("WSAEPROTONOSUPPORT"));
  221. break;
  222. case WSAESOCKTNOSUPPORT:
  223. return(TEXT("WSAESOCKTNOSUPPORT"));
  224. break;
  225. case WSAEOPNOTSUPP:
  226. return(TEXT("WSAEOPNOTSUPP"));
  227. break;
  228. case WSAEPFNOSUPPORT:
  229. return(TEXT("WSAEPFNOSUPPORT"));
  230. break;
  231. case WSAEAFNOSUPPORT:
  232. return(TEXT("WSAEAFNOSUPPORT"));
  233. break;
  234. case WSAEADDRINUSE:
  235. return(TEXT("WSAEADDRINUSE"));
  236. break;
  237. case WSAEADDRNOTAVAIL:
  238. return(TEXT("WSAEADDRNOTAVAIL"));
  239. break;
  240. case WSAENETDOWN:
  241. return(TEXT("WSAENETDOWN"));
  242. break;
  243. case WSAENETUNREACH:
  244. return(TEXT("WSAENETUNREACH"));
  245. break;
  246. case WSAENETRESET:
  247. return(TEXT("WSAENETRESET"));
  248. break;
  249. case WSAECONNABORTED:
  250. return(TEXT("WSAECONNABORTED"));
  251. break;
  252. case WSAECONNRESET:
  253. return(TEXT("WSAECONNRESET"));
  254. break;
  255. case WSAENOBUFS:
  256. return(TEXT("WSAENOBUFS"));
  257. break;
  258. case WSAEISCONN:
  259. return(TEXT("WSAEISCONN"));
  260. break;
  261. case WSAENOTCONN:
  262. return(TEXT("WSAENOTCONN"));
  263. break;
  264. case WSAESHUTDOWN:
  265. return(TEXT("WSAESHUTDOWN"));
  266. break;
  267. case WSAETOOMANYREFS:
  268. return(TEXT("WSAETOOMANYREFS"));
  269. break;
  270. case WSAETIMEDOUT:
  271. return(TEXT("WSAETIMEDOUT"));
  272. break;
  273. case WSAECONNREFUSED:
  274. return(TEXT("WSAECONNREFUSED"));
  275. break;
  276. case WSAELOOP:
  277. return(TEXT("WSAELOOP"));
  278. break;
  279. case WSAENAMETOOLONG:
  280. return(TEXT("WSAENAMETOOLONG"));
  281. break;
  282. case WSAEHOSTDOWN:
  283. return(TEXT("WSAEHOSTDOWN"));
  284. break;
  285. case WSAEHOSTUNREACH:
  286. return(TEXT("WSAEHOSTUNREACH"));
  287. break;
  288. case WSAENOTEMPTY:
  289. return(TEXT("WSAENOTEMPTY"));
  290. break;
  291. case WSAEPROCLIM:
  292. return(TEXT("WSAEPROCLIM"));
  293. break;
  294. case WSAEUSERS:
  295. return(TEXT("WSAEUSERS"));
  296. break;
  297. case WSAEDQUOT:
  298. return(TEXT("WSAEDQUOT"));
  299. break;
  300. case WSAESTALE:
  301. return(TEXT("WSAESTALE"));
  302. break;
  303. case WSAEREMOTE:
  304. return(TEXT("WSAEREMOTE"));
  305. break;
  306. case WSAEDISCON:
  307. return(TEXT("WSAEDISCON"));
  308. break;
  309. case WSASYSNOTREADY:
  310. return(TEXT("WSASYSNOTREADY"));
  311. break;
  312. case WSAVERNOTSUPPORTED:
  313. return(TEXT("WSAVERNOTSUPPORTED"));
  314. break;
  315. case WSANOTINITIALISED:
  316. return(TEXT("WSANOTINITIALISED"));
  317. break;
  318. /*
  319. case WSAHOST:
  320. return(TEXT("WSAHOST"));
  321. break;
  322. case WSATRY:
  323. return(TEXT("WSATRY"));
  324. break;
  325. case WSANO:
  326. return(TEXT("WSANO"));
  327. break;
  328. */
  329. default:
  330. return(TEXT("Unknown Error"));
  331. }
  332. }
  333. #endif
  334. HKEY
  335. OpenCurrentUserKey()
  336. {
  337. HKEY hUserKey;
  338. DWORD SizeNeeded;
  339. TOKEN_USER *TokenData;
  340. WCHAR UnicodeBuffer[256];
  341. UNICODE_STRING UnicodeString;
  342. NTSTATUS NtStatus;
  343. // Get current user token so we can access the sound data in the
  344. // user's hive
  345. if (!GetTokenInformation(g_UserToken, TokenUser, 0, 0, &SizeNeeded))
  346. {
  347. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  348. {
  349. TokenData = (TOKEN_USER *) _alloca( SizeNeeded );
  350. }
  351. else
  352. {
  353. DEBUGMSG(("IRMON: GetTokenInformation failed %d\n", GetLastError()));
  354. return 0;
  355. }
  356. }
  357. else
  358. {
  359. DEBUGMSG(("IRMON: GetTokenInformation should have failed\n"));
  360. return 0;
  361. }
  362. if (!TokenData)
  363. {
  364. DEBUGMSG(("IRMON: alloc failed\n"));
  365. return 0;
  366. }
  367. if (!GetTokenInformation(g_UserToken, TokenUser, TokenData,
  368. SizeNeeded, &SizeNeeded))
  369. {
  370. DEBUGMSG(("IRMON: GetTokenInformation failed %d\n", GetLastError()));
  371. return 0;
  372. }
  373. UnicodeString.Buffer = UnicodeBuffer;
  374. UnicodeString.Length = 0;
  375. UnicodeString.MaximumLength = sizeof(UnicodeBuffer);
  376. NtStatus = RtlConvertSidToUnicodeString(&UnicodeString,
  377. TokenData->User.Sid,
  378. FALSE);
  379. if (!NT_SUCCESS(NtStatus))
  380. {
  381. DEBUGMSG(("IRMON: RtlConvertSidToUnicodeString failed %\n", GetLastError()));
  382. return 0;
  383. }
  384. UnicodeString.Buffer[UnicodeString.Length] = 0;
  385. //
  386. // Open all our keys. If we can't open the user's key
  387. // or the key to watch for changes, we bail.
  388. //
  389. if (RegOpenKeyEx(HKEY_USERS, UnicodeString.Buffer, 0, KEY_READ, &hUserKey))
  390. {
  391. DEBUGMSG(("IRMON: RegOpenKey1 failed %d\n", GetLastError()));
  392. return 0;
  393. }
  394. return hUserKey;
  395. }
  396. VOID
  397. LoadTrayIconImages()
  398. {
  399. hInRange = LoadImage(ghInstance, MAKEINTRESOURCE(IDI_IN_RANGE),
  400. IMAGE_ICON, 16,16,0);
  401. hInterrupt= LoadImage(ghInstance, MAKEINTRESOURCE(IDI_INTR),
  402. IMAGE_ICON, 16,16,0);
  403. hConn1 = LoadImage(ghInstance, MAKEINTRESOURCE(IDI_CONN1),
  404. IMAGE_ICON, 16,16,0);
  405. hConn2 = LoadImage(ghInstance, MAKEINTRESOURCE(IDI_CONN2),
  406. IMAGE_ICON, 16,16,0);
  407. hConn3 = LoadImage(ghInstance, MAKEINTRESOURCE(IDI_CONN3),
  408. IMAGE_ICON, 16,16,0);
  409. hConn4 = LoadImage(ghInstance, MAKEINTRESOURCE(IDI_CONN4),
  410. IMAGE_ICON, 16,16,0);
  411. hIpInRange= LoadImage(ghInstance, MAKEINTRESOURCE(IDI_IP),
  412. IMAGE_ICON, 16,16,0);
  413. }
  414. VOID
  415. UpdateTray(
  416. PIRMON_CONTROL IrmonControl,
  417. ICON_STATE IconState,
  418. DWORD MsgId,
  419. LPTSTR DeviceName,
  420. UINT Baud
  421. )
  422. {
  423. NOTIFYICONDATA NotifyIconData;
  424. DWORD Cnt;
  425. TCHAR FormatStr[256];
  426. BOOL Result = TRUE;
  427. BOOLEAN TrayUpdateFailed = FALSE;
  428. if (!TrayEnabled && IconState != ICON_ST_NOICON)
  429. {
  430. return;
  431. }
  432. if (!hInRange)
  433. {
  434. LoadTrayIconImages();
  435. }
  436. NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
  437. NotifyIconData.uID = 0;
  438. NotifyIconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO;
  439. NotifyIconData.uCallbackMessage = SYSTRAYEVENTID;
  440. NotifyIconData.hWnd = IrmonControl->hWnd;
  441. NotifyIconData.hIcon = 0;
  442. NotifyIconData.szInfo[0] = 0;
  443. NotifyIconData.szInfoTitle[0] = 0;
  444. if (MsgId == 0)
  445. {
  446. lstrcpy(NotifyIconData.szTip, EMPTY_STR);
  447. }
  448. else
  449. {
  450. if (LoadString(ghInstance, MsgId, FormatStr, sizeof(FormatStr)/sizeof(TCHAR)))
  451. {
  452. wsprintf(NotifyIconData.szTip, FormatStr, DeviceName, Baud);
  453. }
  454. }
  455. if (IrmonStopped && IconState != ICON_ST_NOICON)
  456. return;
  457. switch (IconState)
  458. {
  459. case ICON_ST_NOICON:
  460. ShowBalloonTip = TRUE;
  461. if (IconInTray)
  462. {
  463. NotifyIconData.uFlags = 0;
  464. IconInTray = FALSE;
  465. if (Shell_NotifyIcon(NIM_DELETE, &NotifyIconData)) {
  466. LastTrayUpdate = MAKE_LT_UPDATE(NIM_DELETE,ICON_ST_NOICON);
  467. if (IrmonControl->SoundOn) {
  468. PlayIrSound(OUTOFRANGE_SOUND);
  469. }
  470. } else {
  471. DEBUGMSG(("IRMON: Shell_NotifyIcon(Delete) failed %d, %d\n", TrayUpdateFailures, GetLastError()));
  472. }
  473. }
  474. return;
  475. case ICON_ST_IN_RANGE:
  476. case ICON_ST_IP_IN_RANGE:
  477. if (IconState == ICON_ST_IP_IN_RANGE) {
  478. NotifyIconData.hIcon = hIpInRange;
  479. } else {
  480. NotifyIconData.hIcon = hInRange;
  481. }
  482. if (ShowBalloonTip)
  483. {
  484. ShowBalloonTip = FALSE;
  485. if (IrxferDeviceInRange &&
  486. LoadString(ghInstance, IDS_BALLOON_TITLE,
  487. NotifyIconData.szInfoTitle,
  488. sizeof(NotifyIconData.szInfoTitle)/sizeof(TCHAR)))
  489. {
  490. NotifyIconData.uFlags |= NIF_INFO;
  491. NotifyIconData.uTimeout = 10000; // in milliseconds
  492. // NotifyIconData.dwInfoFlags = NIIF_INFO;
  493. if (DeviceName)
  494. {
  495. LoadString(ghInstance, IDS_BALLOON_TXT,
  496. FormatStr,
  497. sizeof(FormatStr)/sizeof(TCHAR));
  498. wsprintf(NotifyIconData.szInfo, FormatStr, DeviceName);
  499. }
  500. else
  501. {
  502. LoadString(ghInstance, IDS_BALLOON_TXT2,
  503. NotifyIconData.szInfo,
  504. sizeof(NotifyIconData.szInfo)/sizeof(TCHAR));
  505. }
  506. }
  507. }
  508. break;
  509. case ICON_ST_CONN1:
  510. NotifyIconData.hIcon = hConn1;
  511. break;
  512. case ICON_ST_CONN2:
  513. NotifyIconData.hIcon = hConn2;
  514. break;
  515. case ICON_ST_CONN3:
  516. NotifyIconData.hIcon = hConn3;
  517. break;
  518. case ICON_ST_CONN4:
  519. NotifyIconData.hIcon = hConn4;
  520. break;
  521. /*
  522. case ICON_ST_IDLE:
  523. NotifyIconData.hIcon = hIdle;
  524. break;
  525. case ICON_ST_RX:
  526. NotifyIconData.hIcon = hRx;
  527. break;
  528. case ICON_ST_TX:
  529. NotifyIconData.hIcon = hTx;
  530. break;
  531. case ICON_ST_RXTX:
  532. NotifyIconData.hIcon = hRxTx;
  533. break;
  534. */
  535. case ICON_ST_INTR:
  536. NotifyIconData.hIcon = hInterrupt;
  537. if (LoadString(ghInstance, IDS_BLOCKED_TITLE,
  538. NotifyIconData.szInfoTitle,
  539. sizeof(NotifyIconData.szInfoTitle)/sizeof(TCHAR)) &&
  540. LoadString(ghInstance, IDS_BLOCKED_TXT,
  541. NotifyIconData.szInfo,
  542. sizeof(NotifyIconData.szInfo)/sizeof(TCHAR)))
  543. {
  544. NotifyIconData.uFlags |= NIF_INFO;
  545. NotifyIconData.uTimeout = 10000; // in milliseconds
  546. NotifyIconData.dwInfoFlags = NIIF_WARNING;
  547. }
  548. break;
  549. }
  550. if (IconState == ICON_ST_INTR) {
  551. if (IrmonControl->SoundOn) {
  552. PlayIrSound(INTERRUPTED_SOUND);
  553. InterruptedSoundPlaying = TRUE;
  554. }
  555. } else {
  556. if (InterruptedSoundPlaying) {
  557. InterruptedSoundPlaying = FALSE;
  558. PlayIrSound(END_INTERRUPTED_SOUND);
  559. }
  560. }
  561. if (!IconInTray)
  562. {
  563. if (Shell_NotifyIcon(NIM_ADD, &NotifyIconData))
  564. {
  565. LastTrayUpdate = MAKE_LT_UPDATE(NIM_ADD, IconState);
  566. if (IrmonControl->SoundOn) {
  567. PlayIrSound(INRANGE_SOUND);
  568. }
  569. IconInTray = TRUE;
  570. }
  571. else
  572. {
  573. TrayUpdateFailures++;
  574. DEBUGMSG(("IRMON: Shell_NotifyIcon(ADD) failed %d, %d\n", TrayUpdateFailures, GetLastError()));
  575. NotifyIconData.uFlags = 0;
  576. NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
  577. NotifyIconData.uID = 0;
  578. NotifyIconData.uCallbackMessage = SYSTRAYEVENTID;
  579. NotifyIconData.hWnd = IrmonControl->hWnd;
  580. NotifyIconData.hIcon = 0;
  581. NotifyIconData.szInfo[0] = 0;
  582. NotifyIconData.szInfoTitle[0] = 0;
  583. Shell_NotifyIcon(NIM_DELETE, &NotifyIconData);
  584. TrayUpdateFailed = TRUE;
  585. ShowBalloonTip = TRUE;
  586. }
  587. }
  588. else
  589. {
  590. if (!Shell_NotifyIcon(NIM_MODIFY, &NotifyIconData))
  591. {
  592. TrayUpdateFailures++;
  593. DEBUGMSG(("IRMON: Shell_NotifyIcon(Modify) failed %d, %d\n", TrayUpdateFailures, GetLastError()));
  594. TrayUpdateFailed = TRUE;
  595. }
  596. else
  597. {
  598. LastTrayUpdate = MAKE_LT_UPDATE(NIM_MODIFY, IconState);
  599. }
  600. }
  601. if (TrayUpdateFailed && !RetryTrayUpdateTimerRunning)
  602. {
  603. RetryTrayUpdateTimerId = SetTimer(IrmonControl->hWnd, RETRY_TRAY_UPDATE_TIMER,
  604. RETRY_TRAY_UPDATE_INTERVAL, NULL);
  605. RetryTrayUpdateTimerRunning = TRUE;
  606. }
  607. }
  608. VOID
  609. ConnAnimationTimerExp(
  610. PIRMON_CONTROL IrmonControl
  611. )
  612. {
  613. /* if (ConnDevName[0] == 0)
  614. {
  615. UpdateTray(ICON_ST_CONN1, 0, NULL, 0);
  616. }
  617. else
  618. {
  619. */
  620. UpdateTray(IrmonControl,ConnIcon, IDS_CONNECTED_TO, ConnDevName,
  621. LinkStatus.ConnectSpeed);
  622. // }
  623. ConnIcon += ConnAddition;
  624. if (ConnIcon == 4)
  625. {
  626. ConnAddition = -1;
  627. }
  628. else if (ConnIcon == 1)
  629. {
  630. ConnAddition = 1;
  631. }
  632. }
  633. VOID
  634. IsIrxferDeviceInRange()
  635. {
  636. int i, LsapSel, Attempt, Status;
  637. IrxferDeviceInRange = FALSE;
  638. if (IpDeviceList->DeviceCount > 0) {
  639. IrxferDeviceInRange = TRUE;
  640. return;
  641. }
  642. for (i = 0; i < (int)pDeviceList->DeviceCount; i++) {
  643. if (pDeviceList->DeviceList[i].DeviceSpecific.s.Irda.ObexSupport) {
  644. IrxferDeviceInRange = TRUE;
  645. break;
  646. }
  647. }
  648. return;
  649. }
  650. VOID
  651. DevListChangeOrUpdatedLinkStatus(
  652. PIRMON_CONTROL IrmonControl
  653. )
  654. {
  655. if (!UserLoggedIn)
  656. {
  657. DEBUGMSG(("IRMON: User not logged in, ignoring device change\n"));
  658. return;
  659. }
  660. if (DeviceListUpdated)
  661. {
  662. IsIrxferDeviceInRange();
  663. }
  664. if (LinkStatus.Flags & LF_INTERRUPTED)
  665. {
  666. KillTimer(IrmonControl->hWnd, ConnAnimationTimerId);
  667. UpdateTray(IrmonControl,ICON_ST_INTR, IDS_INTERRUPTED, NULL, 0);
  668. }
  669. else if (LinkStatus.Flags & LF_CONNECTED)
  670. {
  671. // ICON_STATE IconState = ICON_ST_IDLE;
  672. ULONG i;
  673. ConnDevName[0] = 0;
  674. ConnIcon = 1;
  675. ConnAddition = 1;
  676. for (i = 0; i < pDeviceList->DeviceCount; i++)
  677. {
  678. if (memcmp(&pDeviceList->DeviceList[i].DeviceSpecific.s.Irda.DeviceId,
  679. LinkStatus.ConnectedDeviceId, 4) == 0)
  680. {
  681. //
  682. // the name is in unicode
  683. //
  684. ZeroMemory(ConnDevName,sizeof(ConnDevName));
  685. lstrcpy(
  686. ConnDevName,
  687. pDeviceList->DeviceList[i].DeviceName
  688. );
  689. break;
  690. }
  691. }
  692. ConnAnimationTimerExp(IrmonControl);
  693. ConnAnimationTimerId = SetTimer(IrmonControl->hWnd, CONN_ANIMATION_TIMER,
  694. CONN_ANIMATION_INTERVAL, NULL);
  695. }
  696. else
  697. {
  698. KillTimer(IrmonControl->hWnd, ConnAnimationTimerId);
  699. if ((pDeviceList->DeviceCount == 0) && (IpDeviceList->DeviceCount == 0)) {
  700. //
  701. // no devices in range
  702. //
  703. UpdateTray(IrmonControl,ICON_ST_NOICON, 0, NULL, 0);
  704. } else {
  705. //
  706. // atleast on device in range
  707. //
  708. if ((pDeviceList->DeviceCount == 1) && (IpDeviceList->DeviceCount == 0)) {
  709. //
  710. // one ir device in range
  711. //
  712. lstrcpy(
  713. ConnDevName,
  714. pDeviceList->DeviceList[0].DeviceName
  715. );
  716. UpdateTray(IrmonControl,ICON_ST_IN_RANGE, IDS_IN_RANGE, ConnDevName, 0);
  717. } else {
  718. if ((pDeviceList->DeviceCount == 0) && (IpDeviceList->DeviceCount == 1)) {
  719. //
  720. // one ip device in range
  721. //
  722. lstrcpy(
  723. ConnDevName,
  724. IpDeviceList->DeviceList[0].DeviceName
  725. );
  726. lstrcat(ConnDevName,TEXT("(IP)"));
  727. UpdateTray(IrmonControl,ICON_ST_IP_IN_RANGE, IDS_IN_RANGE, ConnDevName, 0);
  728. } else {
  729. //
  730. // more than one device total
  731. //
  732. if (pDeviceList->DeviceCount > IpDeviceList->DeviceCount) {
  733. UpdateTray(IrmonControl,ICON_ST_IN_RANGE, IDS_DEVS_IN_RANGE, NULL, 0);
  734. } else {
  735. UpdateTray(IrmonControl,ICON_ST_IP_IN_RANGE, IDS_DEVS_IN_RANGE, NULL, 0);
  736. }
  737. }
  738. }
  739. }
  740. }
  741. if (!UserLoggedIn)
  742. {
  743. // Check again because UpdateTray() may have changed logon status
  744. // because of premature notification from irxfer
  745. DEBUGMSG(("IRMON: User not logged in because UpdateTray must have logged us off\n"));
  746. return;
  747. }
  748. if (DeviceListUpdated)
  749. {
  750. HANDLE hThread;
  751. DWORD ThreadId;
  752. DeviceListUpdated = FALSE;
  753. // PnP Printers, Notify transfer app
  754. UpdateDiscoveredDevices(pDeviceList,IpDeviceList);
  755. }
  756. }
  757. VOID
  758. UserLogonEvent(
  759. PIRMON_CONTROL IrmonControl
  760. )
  761. {
  762. UINT DevListLen;
  763. NTSTATUS Status;
  764. OBJECT_ATTRIBUTES ObjAttr;
  765. UNICODE_STRING DeviceName;
  766. IO_STATUS_BLOCK IoStatusBlock;
  767. //
  768. // save current desktop and window station
  769. // so that it can be restored when the user logs off.
  770. //
  771. hSaveWinSta = GetProcessWindowStation();
  772. hSaveDesk = GetThreadDesktop(GetCurrentThreadId());
  773. //
  774. // Open the current user's window station and desktop so
  775. // we can add an icon to the taskbar
  776. //
  777. hWinStaUser = OpenWindowStation(L"WinSta0", FALSE, MAXIMUM_ALLOWED);
  778. if (hWinStaUser == NULL)
  779. {
  780. DEBUGMSG(("IRMON: OpenWindowStation FAILED %d\n", GetLastError()));
  781. }
  782. else
  783. {
  784. if (!SetProcessWindowStation(hWinStaUser))
  785. {
  786. DEBUGMSG(("IRMON: SetProcessWindowStation failed %d\n", GetLastError()));
  787. }
  788. else
  789. {
  790. DEBUGMSG(("IRMON: SetProcessWindowStation succeeded\n"));
  791. }
  792. }
  793. hDeskUser = OpenDesktop(L"Default", 0 , FALSE, MAXIMUM_ALLOWED);
  794. if (hDeskUser == NULL)
  795. {
  796. DEBUGMSG(("IRMON: OpenDesktop failed %d\n", GetLastError()));
  797. }
  798. else
  799. {
  800. if (!SetThreadDesktop(hDeskUser))
  801. {
  802. DEBUGMSG(("IRMON: SetThreadDesktop failed %d\n", GetLastError()));
  803. }
  804. else
  805. {
  806. DEBUGMSG(("IRMON: SetThreadDesktop succeeded %d\n"));
  807. }
  808. }
  809. //
  810. // Create the window that will receive the taskbar menu messages.
  811. // The window has to be created after opening the user's desktop
  812. // or the call to SetThreadDesktop() will if the thread has
  813. // any windows
  814. //
  815. IrmonControl->hWnd = CreateWindow(
  816. IrmonClassName,
  817. NULL,
  818. WS_OVERLAPPEDWINDOW,
  819. CW_USEDEFAULT,
  820. CW_USEDEFAULT,
  821. CW_USEDEFAULT,
  822. CW_USEDEFAULT,
  823. NULL,
  824. NULL,
  825. ghInstance,
  826. &GlobalIrmonControl
  827. );
  828. ShowWindow(IrmonControl->hWnd, SW_HIDE);
  829. UpdateWindow(IrmonControl->hWnd);
  830. ghCurrentUserKey = OpenCurrentUserKey();
  831. InitializeSound(
  832. ghCurrentUserKey,
  833. hIrmonEvents[EV_REG_CHANGE_EVENT]
  834. );
  835. ShowBalloonTip = TRUE;
  836. IrmonControl->DiscoveryObject=CreateIrDiscoveryObject(
  837. IrmonControl->hWnd,
  838. WM_IR_DEVICE_CHANGE,
  839. WM_IR_LINK_CHANGE
  840. );
  841. if (IrmonControl->DiscoveryObject == NULL) {
  842. DbgPrint("irmon: could not create ir discovery object\n");
  843. return;
  844. }
  845. }
  846. VOID
  847. UserLogoffEvent(
  848. PIRMON_CONTROL IrmonControl
  849. )
  850. {
  851. DEBUGMSG(("IRMON: User logoff event\n"));
  852. UserLoggedIn = FALSE;
  853. IconInTray = FALSE;
  854. KillTimer(IrmonControl->hWnd, ConnAnimationTimerId);
  855. if (IrmonControl->DiscoveryObject != NULL) {
  856. CloseIrDiscoveryObject(IrmonControl->DiscoveryObject);
  857. IrmonControl->DiscoveryObject = NULL;
  858. }
  859. UninitializeSound();
  860. if (ghCurrentUserKey)
  861. {
  862. RegCloseKey(ghCurrentUserKey);
  863. ghCurrentUserKey = 0;
  864. }
  865. if (hSaveDesk)
  866. {
  867. SetThreadDesktop(hSaveDesk);
  868. if (hSaveWinSta)
  869. {
  870. SetProcessWindowStation(hSaveWinSta);
  871. }
  872. CloseDesktop(hSaveDesk);
  873. hSaveDesk = 0;
  874. if (hSaveWinSta)
  875. {
  876. CloseWindowStation(hSaveWinSta);
  877. hSaveWinSta = 0;
  878. }
  879. }
  880. if (hDeskUser)
  881. {
  882. CloseDesktop(hDeskUser);
  883. hDeskUser = 0;
  884. }
  885. if (hWinStaUser)
  886. {
  887. CloseWindowStation(hWinStaUser);
  888. hWinStaUser = 0;
  889. }
  890. if (IrmonControl->hWnd) {
  891. if (IconInTray) {
  892. UpdateTray(&GlobalIrmonControl,ICON_ST_NOICON, 0, NULL, 0);
  893. }
  894. DestroyWindow(IrmonControl->hWnd);
  895. IrmonControl->hWnd = 0;
  896. }
  897. }
  898. VOID
  899. SetLogonStatus(BOOL LoggedOn)
  900. {
  901. MySetLogonStatus(LoggedOn);
  902. }
  903. VOID
  904. MySetLogonStatus(BOOL LoggedOn)
  905. {
  906. if (LoggedOn)
  907. {
  908. if (UserLoggedIn)
  909. {
  910. DEBUGMSG(("IRMON: SetLogonStatus(TRUE) && UserLoggedIn==TRUE (OK)\n"));
  911. return;
  912. }
  913. else
  914. {
  915. DEBUGMSG(("IRMON: User logged in\n"));
  916. UserLoggedIn = TRUE;
  917. SetEvent(hIrmonEvents[EV_LOGON_EVENT]);
  918. }
  919. }
  920. else
  921. {
  922. SetEvent(hIrmonEvents[EV_LOGOFF_EVENT]);
  923. }
  924. }
  925. VOID
  926. SetSoundStatus(
  927. PVOID Context,
  928. BOOL SoundOn
  929. )
  930. {
  931. PIRMON_CONTROL IrmonControl=(PIRMON_CONTROL)Context;
  932. // DbgPrint("Irmon: sound %d\n",SoundOn);
  933. IrmonControl->SoundOn=SoundOn;
  934. return;
  935. }
  936. VOID
  937. SetTrayStatus(
  938. PVOID Context,
  939. BOOL lTrayEnabled
  940. )
  941. {
  942. PIRMON_CONTROL IrmonControl=(PIRMON_CONTROL)Context;
  943. if (lTrayEnabled)
  944. {
  945. DEBUGMSG(("IRMON: Tray enabled\n"));
  946. TrayEnabled = TRUE;
  947. }
  948. else
  949. {
  950. DEBUGMSG(("IRMON: Tray disabled\n"));
  951. TrayEnabled = FALSE;
  952. }
  953. SetEvent(hIrmonEvents[EV_TRAY_STATUS_EVENT]);
  954. }
  955. LONG_PTR FAR PASCAL
  956. WndProc(
  957. HWND hWnd,
  958. unsigned message,
  959. WPARAM wParam,
  960. LPARAM lParam)
  961. {
  962. PIRMON_CONTROL IrmonControl=(PIRMON_CONTROL)GetWindowLongPtr(hWnd,GWLP_USERDATA);
  963. switch (message)
  964. {
  965. case WM_CREATE: {
  966. LPCREATESTRUCT CreateStruct=(LPCREATESTRUCT)lParam;
  967. SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG_PTR)CreateStruct->lpCreateParams);
  968. return 0;
  969. }
  970. break;
  971. case WM_COMMAND:
  972. {
  973. switch (wParam)
  974. {
  975. case IDC_TX_FILES:
  976. ShowSendWindow();
  977. break;
  978. case IDC_PROPERTIES:
  979. DEBUGMSG(("IRMON: Launch Properties page\n"));
  980. ShowPropertiesPage();
  981. break;
  982. default:
  983. ;
  984. //DEBUGMSG(("Other WM_COMMAND %X\n", wParam));
  985. }
  986. break;
  987. }
  988. case SYSTRAYEVENTID:
  989. {
  990. POINT pt;
  991. HMENU hMenu, hMenuPopup;
  992. switch (lParam)
  993. {
  994. case WM_LBUTTONDOWN:
  995. ShowSendWindow();
  996. break;
  997. case WM_RBUTTONDOWN:
  998. SetForegroundWindow(hWnd);
  999. GetCursorPos(&pt);
  1000. hMenu = LoadMenu(ghInstance, MAKEINTRESOURCE(IDR_TRAY_MENU));
  1001. if (!hMenu)
  1002. {
  1003. DEBUGMSG(("IRMON: failed to load menu\n"));
  1004. break;
  1005. }
  1006. hMenuPopup = GetSubMenu(hMenu, 0);
  1007. SetMenuDefaultItem(hMenuPopup, 0, TRUE);
  1008. TrackPopupMenuEx(hMenuPopup,
  1009. TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  1010. pt.x, pt.y, hWnd, NULL);
  1011. DestroyMenu(hMenu);
  1012. break;
  1013. //default:DEBUGMSG(("IRMON: Systray other %d\n", lParam));
  1014. }
  1015. break;
  1016. }
  1017. case WM_TIMER:
  1018. if (wParam == ConnAnimationTimerId)
  1019. {
  1020. ConnAnimationTimerExp(IrmonControl);
  1021. }
  1022. else if (wParam == RetryTrayUpdateTimerId)
  1023. {
  1024. DEBUGMSG(("IRMON: RetryTrayUpdateTimer expired\n"));
  1025. KillTimer(IrmonControl->hWnd, RetryTrayUpdateTimerId);
  1026. RetryTrayUpdateTimerRunning = FALSE;
  1027. DevListChangeOrUpdatedLinkStatus(IrmonControl);
  1028. }
  1029. break;
  1030. case WM_QUERYENDSESSION:
  1031. {
  1032. extern BOOL IrxferHandlePowerMessage( HWND hWnd, unsigned message, WPARAM wParam, LPARAM lParam );
  1033. return IrxferHandlePowerMessage( hWnd, message, wParam, lParam );
  1034. break;
  1035. }
  1036. case WM_ENDSESSION:
  1037. break;
  1038. case WM_POWERBROADCAST:
  1039. {
  1040. extern BOOL IrxferHandlePowerMessage( HWND hWnd, unsigned message, WPARAM wParam, LPARAM lParam );
  1041. return IrxferHandlePowerMessage( hWnd, message, wParam, lParam );
  1042. break;
  1043. }
  1044. case WM_IP_DEVICE_CHANGE: {
  1045. ULONG BufferSize=sizeof(FoundIpListBuffer);
  1046. ULONG i;
  1047. LONG lResult;
  1048. LONG Count;
  1049. EnterCriticalSection(&IrmonControl->Lock);
  1050. Count=InterlockedIncrement(&UpdatingIpAddressList);
  1051. if (Count > 1) {
  1052. //
  1053. // re-eneter, just skip
  1054. //
  1055. DbgPrint("irmon: re-entered device notify message %d\n",Count);
  1056. } else {
  1057. //
  1058. // first one in, up date the list
  1059. //
  1060. #ifdef IP_OBEX
  1061. if (IrmonControl->SsdpContext != NULL) {
  1062. lResult=GetSsdpDevices(
  1063. IrmonControl->SsdpContext,
  1064. IpDeviceList,
  1065. &BufferSize
  1066. );
  1067. if (lResult == ERROR_SUCCESS) {
  1068. for (i=0; i<IpDeviceList->DeviceCount; i++) {
  1069. DbgPrint(
  1070. "IRMON: ip device %ws, addr=%08lx, port=%d\n",\
  1071. IpDeviceList->DeviceList[i].DeviceName,
  1072. IpDeviceList->DeviceList[i].DeviceSpecific.s.Ip.IpAddress,
  1073. IpDeviceList->DeviceList[i].DeviceSpecific.s.Ip.Port
  1074. );
  1075. }
  1076. DeviceListUpdated = TRUE;
  1077. DevListChangeOrUpdatedLinkStatus(IrmonControl);
  1078. } else {
  1079. DbgPrint("IRMON: GetSsdpDevices() failed\n");
  1080. }
  1081. } else {
  1082. DbgPrint("irmon: ssdp context == null\n");
  1083. }
  1084. #endif //IP_OBEX
  1085. }
  1086. InterlockedDecrement(&UpdatingIpAddressList);
  1087. LeaveCriticalSection(&IrmonControl->Lock);
  1088. break;
  1089. }
  1090. case WM_IR_DEVICE_CHANGE: {
  1091. ULONG BufferSize=sizeof(FoundDevListBuf);
  1092. GetDeviceList(
  1093. IrmonControl->DiscoveryObject,
  1094. pDeviceList,
  1095. &BufferSize
  1096. );
  1097. DeviceListUpdated = TRUE;
  1098. DEBUGMSG(("IRMON: %d IR device(s) found:\n", pDeviceList->DeviceCount));
  1099. DevListChangeOrUpdatedLinkStatus(IrmonControl);
  1100. }
  1101. break;
  1102. case WM_IR_LINK_CHANGE: {
  1103. GetLinkStatus(
  1104. IrmonControl->DiscoveryObject,
  1105. &LinkStatus
  1106. );
  1107. DEBUGMSG(("IRMON: link state change\n"));
  1108. DevListChangeOrUpdatedLinkStatus(IrmonControl);
  1109. }
  1110. break;
  1111. default:
  1112. #if 0
  1113. if (message == gTaskbarCreated)
  1114. {
  1115. DevListChangeOrUpdatedLinkStatus(IrmonControl);
  1116. }
  1117. #endif
  1118. //DEBUGMSG(("Msg %X, wParam %d, lParam %d\n", message, wParam, lParam));
  1119. return (DefWindowProc(hWnd, message, wParam, lParam));
  1120. }
  1121. return 0;
  1122. }
  1123. DWORD
  1124. IrmonReportServiceStatus()
  1125. {
  1126. #ifdef BUILD_SERVICE_EXE
  1127. if (!SetServiceStatus(IrmonStatusHandle, &IrmonServiceStatus))
  1128. {
  1129. DEBUGMSG(("IRMON: SetServiceStatus failed %d\n", GetLastError()));
  1130. return GetLastError();
  1131. }
  1132. #endif
  1133. return NO_ERROR;
  1134. }
  1135. DWORD
  1136. IrmonUpdateServiceStatus(
  1137. DWORD State,
  1138. DWORD Win32ExitCode,
  1139. DWORD CheckPoint,
  1140. DWORD WaitHint
  1141. )
  1142. {
  1143. DWORD Error = NO_ERROR;
  1144. #ifdef BUILD_SERVICE_EXE
  1145. IrmonServiceStatus.dwCurrentState = State;
  1146. IrmonServiceStatus.dwWin32ExitCode = Win32ExitCode;
  1147. IrmonServiceStatus.dwCheckPoint = CheckPoint;
  1148. IrmonServiceStatus.dwWaitHint = WaitHint;
  1149. Error = IrmonReportServiceStatus();
  1150. if (Error != NO_ERROR)
  1151. {
  1152. DEBUGMSG(("IRMON: IrmonUpdateServiceStatus failed %d\n", GetLastError()));
  1153. }
  1154. #endif
  1155. return Error;
  1156. }
  1157. VOID
  1158. AdhocNotworkNotification(
  1159. PVOID Context,
  1160. BOOL Availible
  1161. )
  1162. {
  1163. PIRMON_CONTROL IrmonControl=(PIRMON_CONTROL)Context;
  1164. #ifdef IP_OBEX
  1165. if (Availible) {
  1166. //
  1167. // there is an adhok network availible
  1168. //
  1169. EnterCriticalSection(&IrmonControl->Lock);
  1170. DbgPrint("irmon: new adhoc networks\n");
  1171. IrmonControl->SsdpContext=CreateSsdpDiscoveryObject(
  1172. "OBEX",
  1173. IrmonControl->hWnd,
  1174. WM_IP_DEVICE_CHANGE
  1175. );
  1176. LeaveCriticalSection(&IrmonControl->Lock);
  1177. } else {
  1178. DbgPrint("irmon: no adhoc networks\n");
  1179. EnterCriticalSection(&IrmonControl->Lock);
  1180. if (IrmonControl->SsdpContext != NULL) {
  1181. CloseSsdpDiscoveryObject(IrmonControl->SsdpContext);
  1182. IrmonControl->SsdpContext=NULL;
  1183. }
  1184. IpDeviceList->DeviceCount=0;
  1185. DeviceListUpdated = TRUE;
  1186. LeaveCriticalSection(&IrmonControl->Lock);
  1187. DevListChangeOrUpdatedLinkStatus(IrmonControl);
  1188. }
  1189. #endif
  1190. return;
  1191. }
  1192. #ifdef BUILD_SERVICE_EXE
  1193. VOID
  1194. ServiceHandler(
  1195. DWORD OpCode)
  1196. {
  1197. switch( OpCode )
  1198. {
  1199. case SERVICE_CONTROL_STOP :
  1200. DEBUGMSG(("IRMON: SERVICE_CONTROL_STOP received\n"));
  1201. IrmonServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  1202. IrmonReportServiceStatus();
  1203. SetEvent(hIrmonEvents[EV_STOP_EVENT]);
  1204. return;
  1205. case SERVICE_CONTROL_PAUSE :
  1206. DEBUGMSG(("IRMON: SERVICE_CONTROL_PAUSE received\n"));
  1207. IrmonServiceStatus.dwCurrentState = SERVICE_PAUSED;
  1208. break;
  1209. case SERVICE_CONTROL_CONTINUE :
  1210. DEBUGMSG(("IRMON: SERVICE_CONTROL_CONTINUE received\n"));
  1211. IrmonServiceStatus.dwCurrentState = SERVICE_RUNNING;
  1212. break;
  1213. default :
  1214. break;
  1215. }
  1216. IrmonReportServiceStatus();
  1217. }
  1218. #endif
  1219. VOID
  1220. ServiceMain(
  1221. DWORD cArgs,
  1222. LPWSTR *pArgs)
  1223. {
  1224. DWORD Error = NO_ERROR;
  1225. DWORD Status;
  1226. WNDCLASS Wc;
  1227. MSG Msg;
  1228. HKEY hKey;
  1229. LONG rc;
  1230. WSADATA WSAData;
  1231. WORD WSAVerReq = MAKEWORD(2,0);
  1232. char c;
  1233. BOOL bResult;
  1234. hIrmonEvents[EV_STOP_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
  1235. hIrmonEvents[EV_LOGON_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
  1236. hIrmonEvents[EV_LOGOFF_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
  1237. hIrmonEvents[EV_REG_CHANGE_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
  1238. hIrmonEvents[EV_TRAY_STATUS_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
  1239. // Initialize all necessary globals to 0, FALSE, or NULL because
  1240. // we might be restarting within the same services process
  1241. pDeviceList->DeviceCount = 0;
  1242. IconInTray = FALSE;
  1243. IrmonStopped = FALSE;
  1244. UserLoggedIn = FALSE;
  1245. TrayEnabled = FALSE;
  1246. DeviceListUpdated = FALSE;
  1247. LastTrayUpdate = 0;
  1248. // RetryLazyDscvTimerRunning = FALSE;
  1249. RetryTrayUpdateTimerRunning = FALSE;
  1250. hInRange = 0;
  1251. WaveNumDev = NULL;
  1252. RtlZeroMemory(&LinkStatus, sizeof(LinkStatus));
  1253. ZeroMemory(&GlobalIrmonControl,sizeof(GlobalIrmonControl));
  1254. InitializeCriticalSection(&GlobalIrmonControl.Lock);
  1255. #ifdef BUILD_SERVICE_EXE
  1256. IrmonServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  1257. IrmonServiceStatus.dwCurrentState = SERVICE_STOPPED;
  1258. IrmonServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
  1259. | SERVICE_ACCEPT_PAUSE_CONTINUE;
  1260. IrmonServiceStatus.dwWin32ExitCode = NO_ERROR;
  1261. IrmonServiceStatus.dwServiceSpecificExitCode = NO_ERROR;
  1262. IrmonServiceStatus.dwCheckPoint = 0;
  1263. IrmonServiceStatus.dwWaitHint = 0;
  1264. IrmonStatusHandle = RegisterServiceCtrlHandler(IRMON_SERVICE_NAME,
  1265. ServiceHandler);
  1266. if (!IrmonStatusHandle)
  1267. {
  1268. DEBUGMSG(("IRMON: RegisterServiceCtrlHandler failed %d\n",
  1269. GetLastError()));
  1270. goto done;
  1271. }
  1272. DEBUGMSG(("IRMON: Start pending\n"));
  1273. Error = IrmonUpdateServiceStatus(SERVICE_START_PENDING,
  1274. NO_ERROR, 1, 25000);
  1275. if (Error != NO_ERROR)
  1276. {
  1277. goto done;
  1278. }
  1279. #endif
  1280. LoadSoundApis();
  1281. if (WSAStartup(WSAVerReq, &WSAData) != 0)
  1282. {
  1283. DEBUGMSG(("IRMON: WSAStartup failed\n"));
  1284. Error = 1;
  1285. goto done;
  1286. }
  1287. // Initialize OBEX and IrTran-P:
  1288. bResult=InitializeIrxfer(
  1289. &GlobalIrmonControl,
  1290. AdhocNotworkNotification,
  1291. SetLogonStatus,
  1292. SetTrayStatus,
  1293. SetSoundStatus,
  1294. &GlobalIrmonControl.IrxferContext
  1295. );
  1296. if (bResult) {
  1297. DEBUGMSG(("IRMON: Irxfer initialized\n"));
  1298. } else {
  1299. DEBUGMSG(("IRMON: Irxfer initializtion failed\n"));
  1300. goto done;
  1301. }
  1302. // gTaskbarCreated = RegisterWindowMessage(TASK_BAR_CREATED);
  1303. Wc.style = CS_NOCLOSE;
  1304. Wc.cbClsExtra = 0;
  1305. Wc.cbWndExtra = 0;
  1306. Wc.hInstance = ghInstance;
  1307. Wc.hIcon = NULL;
  1308. Wc.hCursor = NULL;
  1309. Wc.hbrBackground = NULL;
  1310. Wc.lpszMenuName = NULL;
  1311. Wc.lpfnWndProc = WndProc;
  1312. Wc.lpszClassName = IrmonClassName;
  1313. if (!RegisterClass(&Wc))
  1314. {
  1315. DEBUGMSG(("IRMON: failed to register class\n"));
  1316. }
  1317. IrmonStopped = FALSE;
  1318. Error = IrmonUpdateServiceStatus(SERVICE_RUNNING,
  1319. NO_ERROR, 0, 0);
  1320. DEBUGMSG(("IRMON: Service running\n"));
  1321. while (!IrmonStopped)
  1322. {
  1323. Status = MsgWaitForMultipleObjectsEx(WAIT_EVENT_CNT, hIrmonEvents, INFINITE,
  1324. QS_ALLINPUT | QS_ALLEVENTS | QS_ALLPOSTMESSAGE,
  1325. MWMO_ALERTABLE);
  1326. switch (Status)
  1327. {
  1328. case WAIT_OBJECT_0 + EV_STOP_EVENT:
  1329. IrmonStopped = TRUE;
  1330. break;
  1331. case WAIT_OBJECT_0 + EV_LOGON_EVENT:
  1332. UserLogonEvent(&GlobalIrmonControl);
  1333. break;
  1334. case WAIT_OBJECT_0 + EV_LOGOFF_EVENT:
  1335. UserLogoffEvent(&GlobalIrmonControl);
  1336. break;
  1337. case WAIT_OBJECT_0 + EV_REG_CHANGE_EVENT:
  1338. if (UserLoggedIn)
  1339. {
  1340. GetRegSoundData(hIrmonEvents[EV_REG_CHANGE_EVENT]);
  1341. }
  1342. break;
  1343. case WAIT_OBJECT_0 + EV_TRAY_STATUS_EVENT:
  1344. if (TrayEnabled)
  1345. {
  1346. DevListChangeOrUpdatedLinkStatus(&GlobalIrmonControl);
  1347. }
  1348. else if (IconInTray)
  1349. {
  1350. UpdateTray(&GlobalIrmonControl,ICON_ST_NOICON, 0, NULL, 0);
  1351. }
  1352. break;
  1353. case WAIT_IO_COMPLETION:
  1354. break;
  1355. default:
  1356. while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
  1357. {
  1358. if (Msg.message == WM_QUIT)
  1359. {
  1360. IrmonStopped = TRUE;
  1361. break;
  1362. }
  1363. if (!IsDialogMessage(GlobalIrmonControl.hWnd, &Msg))
  1364. {
  1365. TranslateMessage(&Msg);
  1366. DispatchMessage(&Msg);
  1367. }
  1368. }
  1369. }
  1370. }
  1371. if (UserLoggedIn) {
  1372. UserLogoffEvent(&GlobalIrmonControl);
  1373. }
  1374. if (!UninitializeIrxfer(GlobalIrmonControl.IrxferContext)) {
  1375. DEBUGMSG(("IRMON: Failed to unitialize irxfer!!\n"));
  1376. IrmonStopped = FALSE;
  1377. } else {
  1378. DEBUGMSG(("IRMON: irxfer unitialized\n"));
  1379. }
  1380. UpdateTray(&GlobalIrmonControl,ICON_ST_NOICON, 0, NULL, 0);
  1381. done:
  1382. DeleteCriticalSection(&GlobalIrmonControl.Lock);
  1383. if (IrmonStatusHandle)
  1384. {
  1385. DEBUGMSG(("IRMON: Service stopped\n"));
  1386. IrmonUpdateServiceStatus(SERVICE_STOPPED, Error, 0, 0);
  1387. }
  1388. }
  1389. BOOL
  1390. WINAPI
  1391. DllMain (
  1392. HINSTANCE hinst,
  1393. DWORD dwReason,
  1394. LPVOID pvReserved)
  1395. {
  1396. if (DLL_PROCESS_ATTACH == dwReason)
  1397. {
  1398. ghInstance = hinst;
  1399. DisableThreadLibraryCalls (hinst);
  1400. }
  1401. return TRUE;
  1402. }