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.

1216 lines
30 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. #include <wtsapi32.h>
  28. #include <strsafe.h>
  29. #include <userenv.h>
  30. #include <sddl.h>
  31. #include "internal.h"
  32. #include <devlist.h>
  33. #include <irtypes.h>
  34. #include <irmon.h>
  35. #include "irdisc.h"
  36. #define WM_IP_DEVICE_CHANGE (WM_USER+500)
  37. #define WM_IR_DEVICE_CHANGE (WM_USER+501)
  38. #define WM_IR_LINK_CHANGE (WM_USER+502)
  39. #define IRMON_SERVICE_NAME TEXT("irmon")
  40. #define EV_STOP_EVENT 0
  41. #define WAIT_EVENT_CNT 1
  42. #define NO_SESSION_ID (0xffffffff)
  43. #define MAX_SESSIONS (32)
  44. typedef struct _IRMON_CONTROL {
  45. CRITICAL_SECTION Lock;
  46. HWND hWnd;
  47. WSAOVERLAPPED Overlapped;
  48. HANDLE DiscoveryObject;
  49. BOOL IrmonStopped;
  50. BOOL ThreadExit;
  51. HANDLE hIrmonEvents[WAIT_EVENT_CNT];
  52. SERVICE_STATUS_HANDLE IrmonStatusHandle;
  53. SERVICE_STATUS IrmonServiceStatus;
  54. BOOL LoggedOn;
  55. BOOL NewLogon;
  56. ULONG TimeOfLastLogon;
  57. DWORD ConnectedConsoleId;
  58. DWORD LoggedOnId[MAX_SESSIONS];
  59. HANDLE ThreadBlockEvent;
  60. HANDLE ThreadHandle;
  61. ULONG PreviousDeviceCount;
  62. HANDLE FileMapping;
  63. PVOID ViewOfFile;
  64. SOCKET Obex1;
  65. SOCKET Obex2;
  66. } IRMON_CONTROL, *PIRMON_CONTROL;
  67. IRMON_CONTROL GlobalIrmonControl;
  68. BOOL
  69. StartThread(
  70. PIRMON_CONTROL IrmonControl
  71. );
  72. BYTE FoundDevListBuf[ sizeof(OBEX_DEVICE_LIST) + sizeof(OBEX_DEVICE)*MAX_OBEX_DEVICES];
  73. OBEX_DEVICE_LIST * const pDeviceList=(POBEX_DEVICE_LIST)FoundDevListBuf;
  74. wchar_t * WSZ_SHOW_NOTHING = L"irftp.exe /z";
  75. WCHAR CommandLine[MAX_PATH];
  76. TCHAR IrmonClassName[] = TEXT("NewIrmonClass");
  77. IRLINK_STATUS LinkStatus;
  78. HINSTANCE ghInstance;
  79. VOID
  80. InitiateLazyDscv(
  81. PIRMON_CONTROL IrmonControl
  82. );
  83. VOID
  84. InitiateLinkStatusQuery(
  85. PIRMON_CONTROL IrmonControl
  86. );
  87. #if DBG
  88. TCHAR *
  89. GetLastErrorText()
  90. {
  91. switch (WSAGetLastError())
  92. {
  93. case WSAEINTR:
  94. return (TEXT("WSAEINTR"));
  95. break;
  96. case WSAEBADF:
  97. return(TEXT("WSAEBADF"));
  98. break;
  99. case WSAEACCES:
  100. return(TEXT("WSAEACCES"));
  101. break;
  102. case WSAEFAULT:
  103. return(TEXT("WSAEFAULT"));
  104. break;
  105. case WSAEINVAL:
  106. return(TEXT("WSAEINVAL"));
  107. break;
  108. case WSAEMFILE:
  109. return(TEXT("WSAEMFILE"));
  110. break;
  111. case WSAEWOULDBLOCK:
  112. return(TEXT("WSAEWOULDBLOCK"));
  113. break;
  114. case WSAEINPROGRESS:
  115. return(TEXT("WSAEINPROGRESS"));
  116. break;
  117. case WSAEALREADY:
  118. return(TEXT("WSAEALREADY"));
  119. break;
  120. case WSAENOTSOCK:
  121. return(TEXT("WSAENOTSOCK"));
  122. break;
  123. case WSAEDESTADDRREQ:
  124. return(TEXT("WSAEDESTADDRREQ"));
  125. break;
  126. case WSAEMSGSIZE:
  127. return(TEXT("WSAEMSGSIZE"));
  128. break;
  129. case WSAEPROTOTYPE:
  130. return(TEXT("WSAEPROTOTYPE"));
  131. break;
  132. case WSAENOPROTOOPT:
  133. return(TEXT("WSAENOPROTOOPT"));
  134. break;
  135. case WSAEPROTONOSUPPORT:
  136. return(TEXT("WSAEPROTONOSUPPORT"));
  137. break;
  138. case WSAESOCKTNOSUPPORT:
  139. return(TEXT("WSAESOCKTNOSUPPORT"));
  140. break;
  141. case WSAEOPNOTSUPP:
  142. return(TEXT("WSAEOPNOTSUPP"));
  143. break;
  144. case WSAEPFNOSUPPORT:
  145. return(TEXT("WSAEPFNOSUPPORT"));
  146. break;
  147. case WSAEAFNOSUPPORT:
  148. return(TEXT("WSAEAFNOSUPPORT"));
  149. break;
  150. case WSAEADDRINUSE:
  151. return(TEXT("WSAEADDRINUSE"));
  152. break;
  153. case WSAEADDRNOTAVAIL:
  154. return(TEXT("WSAEADDRNOTAVAIL"));
  155. break;
  156. case WSAENETDOWN:
  157. return(TEXT("WSAENETDOWN"));
  158. break;
  159. case WSAENETUNREACH:
  160. return(TEXT("WSAENETUNREACH"));
  161. break;
  162. case WSAENETRESET:
  163. return(TEXT("WSAENETRESET"));
  164. break;
  165. case WSAECONNABORTED:
  166. return(TEXT("WSAECONNABORTED"));
  167. break;
  168. case WSAECONNRESET:
  169. return(TEXT("WSAECONNRESET"));
  170. break;
  171. case WSAENOBUFS:
  172. return(TEXT("WSAENOBUFS"));
  173. break;
  174. case WSAEISCONN:
  175. return(TEXT("WSAEISCONN"));
  176. break;
  177. case WSAENOTCONN:
  178. return(TEXT("WSAENOTCONN"));
  179. break;
  180. case WSAESHUTDOWN:
  181. return(TEXT("WSAESHUTDOWN"));
  182. break;
  183. case WSAETOOMANYREFS:
  184. return(TEXT("WSAETOOMANYREFS"));
  185. break;
  186. case WSAETIMEDOUT:
  187. return(TEXT("WSAETIMEDOUT"));
  188. break;
  189. case WSAECONNREFUSED:
  190. return(TEXT("WSAECONNREFUSED"));
  191. break;
  192. case WSAELOOP:
  193. return(TEXT("WSAELOOP"));
  194. break;
  195. case WSAENAMETOOLONG:
  196. return(TEXT("WSAENAMETOOLONG"));
  197. break;
  198. case WSAEHOSTDOWN:
  199. return(TEXT("WSAEHOSTDOWN"));
  200. break;
  201. case WSAEHOSTUNREACH:
  202. return(TEXT("WSAEHOSTUNREACH"));
  203. break;
  204. case WSAENOTEMPTY:
  205. return(TEXT("WSAENOTEMPTY"));
  206. break;
  207. case WSAEPROCLIM:
  208. return(TEXT("WSAEPROCLIM"));
  209. break;
  210. case WSAEUSERS:
  211. return(TEXT("WSAEUSERS"));
  212. break;
  213. case WSAEDQUOT:
  214. return(TEXT("WSAEDQUOT"));
  215. break;
  216. case WSAESTALE:
  217. return(TEXT("WSAESTALE"));
  218. break;
  219. case WSAEREMOTE:
  220. return(TEXT("WSAEREMOTE"));
  221. break;
  222. case WSAEDISCON:
  223. return(TEXT("WSAEDISCON"));
  224. break;
  225. case WSASYSNOTREADY:
  226. return(TEXT("WSASYSNOTREADY"));
  227. break;
  228. case WSAVERNOTSUPPORTED:
  229. return(TEXT("WSAVERNOTSUPPORTED"));
  230. break;
  231. case WSANOTINITIALISED:
  232. return(TEXT("WSANOTINITIALISED"));
  233. break;
  234. /*
  235. case WSAHOST:
  236. return(TEXT("WSAHOST"));
  237. break;
  238. case WSATRY:
  239. return(TEXT("WSATRY"));
  240. break;
  241. case WSANO:
  242. return(TEXT("WSANO"));
  243. break;
  244. */
  245. default:
  246. return(TEXT("Unknown Error"));
  247. }
  248. }
  249. #endif
  250. LONG_PTR FAR PASCAL
  251. WndProc(
  252. HWND hWnd,
  253. unsigned message,
  254. WPARAM wParam,
  255. LPARAM lParam)
  256. {
  257. PIRMON_CONTROL IrmonControl=(PIRMON_CONTROL)GetWindowLongPtr(hWnd,GWLP_USERDATA);
  258. switch (message)
  259. {
  260. case WM_CREATE: {
  261. LPCREATESTRUCT CreateStruct=(LPCREATESTRUCT)lParam;
  262. SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG_PTR)CreateStruct->lpCreateParams);
  263. return 0;
  264. }
  265. break;
  266. case WM_IR_DEVICE_CHANGE: {
  267. ULONG BufferSize=sizeof(FoundDevListBuf);
  268. IrmonControl->PreviousDeviceCount=pDeviceList->DeviceCount;
  269. GetDeviceList(
  270. IrmonControl->DiscoveryObject,
  271. pDeviceList,
  272. &BufferSize
  273. );
  274. if ((IrmonControl->PreviousDeviceCount != pDeviceList->DeviceCount)
  275. &&
  276. (pDeviceList->DeviceCount > 0)) {
  277. SetEvent(IrmonControl->ThreadBlockEvent);
  278. }
  279. DEBUGMSG(("IRMON2: %d IR device(s) found:\n", pDeviceList->DeviceCount));
  280. // DevListChangeOrUpdatedLinkStatus(IrmonControl);
  281. }
  282. break;
  283. case WM_IR_LINK_CHANGE: {
  284. }
  285. break;
  286. default:
  287. //DEBUGMSG(("Msg %X, wParam %d, lParam %d\n", message, wParam, lParam));
  288. return (DefWindowProc(hWnd, message, wParam, lParam));
  289. }
  290. return 0;
  291. }
  292. DWORD
  293. IrmonReportServiceStatus()
  294. {
  295. if (!SetServiceStatus(GlobalIrmonControl.IrmonStatusHandle, &GlobalIrmonControl.IrmonServiceStatus))
  296. {
  297. DEBUGMSG(("IRMON2: SetServiceStatus failed %d\n", GetLastError()));
  298. return GetLastError();
  299. }
  300. return NO_ERROR;
  301. }
  302. DWORD
  303. IrmonUpdateServiceStatus(
  304. DWORD State,
  305. DWORD Win32ExitCode,
  306. DWORD CheckPoint,
  307. DWORD WaitHint
  308. )
  309. {
  310. DWORD Error = NO_ERROR;
  311. GlobalIrmonControl.IrmonServiceStatus.dwCurrentState = State;
  312. GlobalIrmonControl.IrmonServiceStatus.dwWin32ExitCode = Win32ExitCode;
  313. GlobalIrmonControl.IrmonServiceStatus.dwCheckPoint = CheckPoint;
  314. GlobalIrmonControl.IrmonServiceStatus.dwWaitHint = WaitHint;
  315. Error = IrmonReportServiceStatus();
  316. if (Error != NO_ERROR)
  317. {
  318. DEBUGMSG(("IRMON2: IrmonUpdateServiceStatus failed %d\n", GetLastError()));
  319. }
  320. return Error;
  321. }
  322. VOID
  323. NotifyUserChange(
  324. PIRMON_CONTROL IrmonControl
  325. )
  326. {
  327. ULONG i;
  328. if (IrmonControl->ConnectedConsoleId != NO_SESSION_ID) {
  329. //
  330. // The console is currently connected
  331. //
  332. for (i=0; i< MAX_SESSIONS; i++) {
  333. if (IrmonControl->LoggedOnId[i] == IrmonControl->ConnectedConsoleId) {
  334. //
  335. // there is a user logged on for this session
  336. //
  337. if (!IrmonControl->LoggedOn) {
  338. IrmonControl->LoggedOn=TRUE;
  339. if (pDeviceList->DeviceCount > 0) {
  340. SetEvent(IrmonControl->ThreadBlockEvent);
  341. }
  342. }
  343. return;
  344. }
  345. }
  346. //
  347. // user not logged on for this session
  348. //
  349. if (IrmonControl->LoggedOn) {
  350. IrmonControl->LoggedOn=FALSE;
  351. }
  352. } else {
  353. //
  354. // The console is not currently connected
  355. //
  356. if (IrmonControl->LoggedOn) {
  357. IrmonControl->LoggedOn=FALSE;
  358. }
  359. }
  360. }
  361. DWORD
  362. ServiceHandler(
  363. DWORD OpCode,
  364. DWORD EventType,
  365. LPVOID EventData,
  366. LPVOID Context
  367. )
  368. {
  369. WTSSESSION_NOTIFICATION *Notify=(WTSSESSION_NOTIFICATION*) EventData;
  370. ULONG i;
  371. switch( OpCode )
  372. {
  373. case SERVICE_CONTROL_STOP :
  374. DEBUGMSG(("IRMON2: SERVICE_CONTROL_STOP received\n"));
  375. GlobalIrmonControl.IrmonServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  376. IrmonReportServiceStatus();
  377. SetEvent(GlobalIrmonControl.hIrmonEvents[EV_STOP_EVENT]);
  378. return NO_ERROR;;
  379. case SERVICE_CONTROL_PAUSE :
  380. DEBUGMSG(("IRMON2: SERVICE_CONTROL_PAUSE received\n"));
  381. GlobalIrmonControl.IrmonServiceStatus.dwCurrentState = SERVICE_PAUSED;
  382. break;
  383. case SERVICE_CONTROL_CONTINUE :
  384. DEBUGMSG(("IRMON2: SERVICE_CONTROL_CONTINUE received\n"));
  385. GlobalIrmonControl.IrmonServiceStatus.dwCurrentState = SERVICE_RUNNING;
  386. break;
  387. case SERVICE_CONTROL_SESSIONCHANGE:
  388. EnterCriticalSection(&GlobalIrmonControl.Lock);
  389. // DbgPrint("IRMON2: SERVICE_CONTROL_SESSIONCHANGE %d\n",EventType);
  390. switch (EventType) {
  391. case WTS_CONSOLE_CONNECT:
  392. // DbgPrint("IRMON2: WTS_CONSOLE_CONNECT: old=%d, new=%d\n",GlobalIrmonControl.ConnectedConsoleId,Notify->dwSessionId);
  393. GlobalIrmonControl.ConnectedConsoleId=Notify->dwSessionId;
  394. NotifyUserChange(&GlobalIrmonControl);
  395. break;
  396. case WTS_CONSOLE_DISCONNECT:
  397. // DbgPrint("IRMON2: WTS_CONSOLE_DISCONNECT Session=%d\n",Notify->dwSessionId);
  398. GlobalIrmonControl.ConnectedConsoleId=NO_SESSION_ID;
  399. NotifyUserChange(&GlobalIrmonControl);
  400. break;
  401. case WTS_SESSION_LOGON:
  402. // DbgPrint("IRMON2: WTS_SESSION_LOGON new=%d\n",Notify->dwSessionId);
  403. for (i=0; i < MAX_SESSIONS; i++) {
  404. if (GlobalIrmonControl.LoggedOnId[i] == NO_SESSION_ID) {
  405. GlobalIrmonControl.LoggedOnId[i]=Notify->dwSessionId;
  406. //
  407. //
  408. //
  409. GlobalIrmonControl.NewLogon=TRUE;
  410. GlobalIrmonControl.TimeOfLastLogon=GetTickCount();
  411. NotifyUserChange(&GlobalIrmonControl);
  412. break;
  413. }
  414. }
  415. break;
  416. case WTS_SESSION_LOGOFF:
  417. // DbgPrint("IRMON2: WTS_SESSION_LOGOFF Session=%d\n",Notify->dwSessionId);
  418. for (i=0; i < MAX_SESSIONS; i++) {
  419. if (GlobalIrmonControl.LoggedOnId[i] == Notify->dwSessionId) {
  420. GlobalIrmonControl.LoggedOnId[i]=NO_SESSION_ID;
  421. NotifyUserChange(&GlobalIrmonControl);
  422. break;
  423. }
  424. }
  425. break;
  426. default:
  427. break;
  428. // DbgPrint("IRMON2: \n");
  429. }
  430. LeaveCriticalSection(&GlobalIrmonControl.Lock);
  431. break;
  432. default :
  433. break;
  434. }
  435. IrmonReportServiceStatus();
  436. return NO_ERROR;
  437. }
  438. VOID
  439. ServiceMain(
  440. DWORD cArgs,
  441. LPWSTR *pArgs)
  442. {
  443. DWORD Error = NO_ERROR;
  444. DWORD Status;
  445. WNDCLASS Wc;
  446. MSG Msg;
  447. HKEY hKey;
  448. LONG rc;
  449. WSADATA WSAData;
  450. WORD WSAVerReq = MAKEWORD(2,0);
  451. char c;
  452. BOOL bResult;
  453. LONG i;
  454. DWORD CurrentConsoleSession;
  455. // Initialize all necessary globals to 0, FALSE, or NULL because
  456. // we might be restarting within the same services process
  457. pDeviceList->DeviceCount = 0;
  458. RtlZeroMemory(&LinkStatus, sizeof(LinkStatus));
  459. ZeroMemory(&GlobalIrmonControl,sizeof(GlobalIrmonControl));
  460. bResult=InitializeCriticalSectionAndSpinCount(&GlobalIrmonControl.Lock,0x8000000);
  461. if (!bResult) {
  462. return;
  463. }
  464. GlobalIrmonControl.hIrmonEvents[EV_STOP_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
  465. if (GlobalIrmonControl.hIrmonEvents[EV_STOP_EVENT] == NULL) {
  466. goto done;
  467. }
  468. GlobalIrmonControl.ThreadBlockEvent=CreateEvent(NULL, FALSE, FALSE, NULL);
  469. if (GlobalIrmonControl.ThreadBlockEvent == NULL) {
  470. goto done;
  471. }
  472. GlobalIrmonControl.ConnectedConsoleId=NO_SESSION_ID;
  473. for (i=0; i < MAX_SESSIONS; i++) {
  474. GlobalIrmonControl.LoggedOnId[i] = NO_SESSION_ID;
  475. }
  476. EnterCriticalSection(&GlobalIrmonControl.Lock);
  477. CurrentConsoleSession=WTSGetActiveConsoleSessionId();
  478. if (CurrentConsoleSession != 0xffffffff) {
  479. //
  480. // We have a current session
  481. //
  482. HANDLE UserToken;
  483. bResult=WTSQueryUserToken(CurrentConsoleSession,&UserToken);
  484. if (bResult) {
  485. //
  486. // there is a user logged on to this session
  487. //
  488. CloseHandle(UserToken);
  489. GlobalIrmonControl.LoggedOnId[0]=CurrentConsoleSession;
  490. GlobalIrmonControl.ConnectedConsoleId=CurrentConsoleSession;
  491. NotifyUserChange(&GlobalIrmonControl);
  492. }
  493. }
  494. LeaveCriticalSection(&GlobalIrmonControl.Lock);
  495. GlobalIrmonControl.IrmonServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  496. GlobalIrmonControl.IrmonServiceStatus.dwCurrentState = SERVICE_STOPPED;
  497. GlobalIrmonControl.IrmonServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
  498. | SERVICE_ACCEPT_PAUSE_CONTINUE
  499. | SERVICE_ACCEPT_SESSIONCHANGE;
  500. GlobalIrmonControl.IrmonServiceStatus.dwWin32ExitCode = NO_ERROR;
  501. GlobalIrmonControl.IrmonServiceStatus.dwServiceSpecificExitCode = NO_ERROR;
  502. GlobalIrmonControl.IrmonServiceStatus.dwCheckPoint = 0;
  503. GlobalIrmonControl.IrmonServiceStatus.dwWaitHint = 0;
  504. GlobalIrmonControl.IrmonStatusHandle = RegisterServiceCtrlHandlerEx(IRMON_SERVICE_NAME,
  505. ServiceHandler,NULL);
  506. if (!GlobalIrmonControl.IrmonStatusHandle)
  507. {
  508. DEBUGMSG(("IRMON2: RegisterServiceCtrlHandler failed %d\n",
  509. GetLastError()));
  510. goto done;
  511. }
  512. DEBUGMSG(("IRMON2: Start pending\n"));
  513. Error = IrmonUpdateServiceStatus(SERVICE_START_PENDING,
  514. NO_ERROR, 1, 25000);
  515. if (Error != NO_ERROR)
  516. {
  517. goto done;
  518. }
  519. if (WSAStartup(WSAVerReq, &WSAData) != 0)
  520. {
  521. DEBUGMSG(("IRMON2: WSAStartup failed\n"));
  522. Error = 1;
  523. goto done;
  524. }
  525. Wc.style = CS_NOCLOSE;
  526. Wc.cbClsExtra = 0;
  527. Wc.cbWndExtra = 0;
  528. Wc.hInstance = ghInstance;
  529. Wc.hIcon = NULL;
  530. Wc.hCursor = NULL;
  531. Wc.hbrBackground = NULL;
  532. Wc.lpszMenuName = NULL;
  533. Wc.lpfnWndProc = WndProc;
  534. Wc.lpszClassName = IrmonClassName;
  535. if (!RegisterClass(&Wc))
  536. {
  537. DEBUGMSG(("IRMON2: failed to register class\n"));
  538. }
  539. GlobalIrmonControl.hWnd = CreateWindow(
  540. IrmonClassName,
  541. NULL,
  542. WS_OVERLAPPEDWINDOW,
  543. CW_USEDEFAULT,
  544. CW_USEDEFAULT,
  545. CW_USEDEFAULT,
  546. CW_USEDEFAULT,
  547. NULL,
  548. NULL,
  549. ghInstance,
  550. &GlobalIrmonControl
  551. );
  552. if (GlobalIrmonControl.hWnd == NULL) {
  553. DEBUGMSG(("IRMON2: failed to create window class\n"));
  554. goto done;
  555. }
  556. GlobalIrmonControl.DiscoveryObject=CreateIrDiscoveryObject(
  557. GlobalIrmonControl.hWnd,
  558. WM_IR_DEVICE_CHANGE,
  559. WM_IR_LINK_CHANGE
  560. );
  561. if (GlobalIrmonControl.DiscoveryObject == NULL) {
  562. DbgPrint("IRMON2: could not create ir discovery object\n");
  563. goto done;
  564. }
  565. Error = IrmonUpdateServiceStatus(SERVICE_RUNNING,
  566. NO_ERROR, 0, 0);
  567. DEBUGMSG(("IRMON2: Service running\n"));
  568. bResult=StartThread(&GlobalIrmonControl);
  569. if (bResult) {
  570. //
  571. // thread started and memory mapped
  572. //
  573. while (!GlobalIrmonControl.IrmonStopped)
  574. {
  575. Status = MsgWaitForMultipleObjectsEx(WAIT_EVENT_CNT, GlobalIrmonControl.hIrmonEvents, INFINITE,
  576. QS_ALLINPUT | QS_ALLEVENTS | QS_ALLPOSTMESSAGE,
  577. MWMO_ALERTABLE);
  578. switch (Status)
  579. {
  580. case WAIT_OBJECT_0 + EV_STOP_EVENT:
  581. GlobalIrmonControl.IrmonStopped = TRUE;
  582. break;
  583. case WAIT_IO_COMPLETION:
  584. break;
  585. default:
  586. while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
  587. {
  588. if (Msg.message == WM_QUIT)
  589. {
  590. GlobalIrmonControl.IrmonStopped = TRUE;
  591. break;
  592. }
  593. if (!IsDialogMessage(GlobalIrmonControl.hWnd, &Msg))
  594. {
  595. TranslateMessage(&Msg);
  596. DispatchMessage(&Msg);
  597. }
  598. }
  599. }
  600. }
  601. }
  602. done:
  603. GlobalIrmonControl.ThreadExit=TRUE;
  604. SetEvent(GlobalIrmonControl.ThreadBlockEvent);
  605. if (GlobalIrmonControl.ThreadHandle != NULL) {
  606. WaitForSingleObject(GlobalIrmonControl.ThreadHandle,60*1000);
  607. CloseHandle(GlobalIrmonControl.ThreadHandle);
  608. }
  609. if (GlobalIrmonControl.FileMapping != NULL) {
  610. CloseHandle(GlobalIrmonControl.FileMapping);
  611. }
  612. if (GlobalIrmonControl.ViewOfFile != NULL) {
  613. CloseHandle(GlobalIrmonControl.ViewOfFile);
  614. }
  615. if (GlobalIrmonControl.DiscoveryObject != NULL) {
  616. CloseIrDiscoveryObject(GlobalIrmonControl.DiscoveryObject);
  617. GlobalIrmonControl.DiscoveryObject = NULL;
  618. }
  619. if (GlobalIrmonControl.hWnd != NULL) {
  620. DestroyWindow(GlobalIrmonControl.hWnd);
  621. GlobalIrmonControl.hWnd = 0;
  622. }
  623. UnregisterClass(IrmonClassName,ghInstance);
  624. DeleteCriticalSection(&GlobalIrmonControl.Lock);
  625. DEBUGMSG(("IRMON2: Service stopped\n"));
  626. IrmonUpdateServiceStatus(SERVICE_STOPPED, Error, 0, 0);
  627. }
  628. SOCKET
  629. CreateListenSocket(
  630. char* ServiceName
  631. )
  632. {
  633. WSADATA wsadata;
  634. SOCKET listenSocket;
  635. SOCKADDR_IRDA saListen;
  636. int nRet;
  637. listenSocket = socket( AF_IRDA, SOCK_STREAM, 0 );
  638. if( INVALID_SOCKET == listenSocket ) {
  639. UINT uErr = (UINT)WSAGetLastError();
  640. // DbgLog3( SEV_ERROR, "listen on %s socket() failed with %d [0x%x]", ServiceName, uErr, uErr);
  641. goto lErr;
  642. }
  643. // DbgLog2( SEV_INFO, "listen on %s socket ID: %ld", ServiceName, (DWORD)listenSocket );
  644. saListen.irdaAddressFamily = AF_IRDA;
  645. *(UINT *)saListen.irdaDeviceID = 0;
  646. StringCbCopyA(saListen.irdaServiceName, sizeof(saListen.irdaServiceName), ServiceName);
  647. nRet = bind( listenSocket, (const struct sockaddr *)&saListen, sizeof(saListen) );
  648. if( SOCKET_ERROR == nRet ) {
  649. UINT uErr = (UINT)WSAGetLastError();
  650. // DbgLog3( SEV_ERROR, "listen on %s setsockopt failed with %d [0x%x]", ServiceName, uErr, uErr);
  651. goto lErr;
  652. }
  653. nRet = listen( listenSocket, 2 );
  654. lErr:
  655. return listenSocket;
  656. }
  657. #define LOGON_WAIT_TIME (5000)
  658. DWORD
  659. IrmonThreadStart(
  660. PVOID Context
  661. )
  662. {
  663. PIRMON_CONTROL IrmonControl=Context;
  664. // DbgPrint("irmon2: thread start\n");
  665. while (!IrmonControl->ThreadExit) {
  666. WaitForSingleObject(IrmonControl->ThreadBlockEvent,INFINITE);
  667. EnterCriticalSection(&IrmonControl->Lock);
  668. // DbgPrint("irmon2: thread session=%d, Device=%d\n",IrmonControl->ConnectedConsoleId,pDeviceList->DeviceCount);
  669. if (IrmonControl->ConnectedConsoleId != NO_SESSION_ID) {
  670. if (pDeviceList->DeviceCount > 0) {
  671. BOOL bResult;
  672. HANDLE UserToken;
  673. PVOID EnvironmentBlock;
  674. STARTUPINFO si;
  675. PROCESS_INFORMATION ProcessInformation;
  676. DWORD UiProcessId;
  677. si.cb = sizeof(STARTUPINFO);
  678. si.lpReserved = NULL;
  679. si.lpTitle = NULL;
  680. si.lpDesktop = L"WinSta0\\Default";
  681. si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L;
  682. si.dwFlags = 0;;
  683. si.wShowWindow = SW_SHOW;
  684. si.lpReserved2 = NULL;
  685. si.cbReserved2 = 0;
  686. if (IrmonControl->NewLogon) {
  687. //
  688. // new user logging on, system time to set user context corrently
  689. //
  690. ULONG CurrentTime=GetTickCount();
  691. ULONG TimeDifference;
  692. IrmonControl->NewLogon=FALSE;
  693. if (CurrentTime >= IrmonControl->TimeOfLastLogon) {
  694. //
  695. // No rollover
  696. //
  697. TimeDifference=CurrentTime - IrmonControl->TimeOfLastLogon;
  698. } else {
  699. //
  700. // seem to have rolled over
  701. //
  702. TimeDifference=CurrentTime + (0xffffffff - IrmonControl->TimeOfLastLogon);
  703. }
  704. if ( LOGON_WAIT_TIME > TimeDifference ) {
  705. #if DBG
  706. DbgPrint("irmon2: New user, waiting %d ms...\n",LOGON_WAIT_TIME - TimeDifference);
  707. #endif
  708. Sleep(LOGON_WAIT_TIME - TimeDifference);
  709. }
  710. }
  711. bResult=WTSQueryUserToken(IrmonControl->ConnectedConsoleId,&UserToken);
  712. if (bResult) {
  713. bResult=CreateEnvironmentBlock(
  714. &EnvironmentBlock,
  715. UserToken,
  716. FALSE
  717. );
  718. if (bResult) {
  719. LONG RetryCount=10;
  720. while (RetryCount > 0) {
  721. // DbgPrint("irmon2: Start irftp\n");
  722. StringCbCopyW(CommandLine, sizeof(CommandLine), WSZ_SHOW_NOTHING);
  723. bResult=CreateProcessAsUser(
  724. UserToken,
  725. NULL, // just use the cmd line parm
  726. CommandLine,
  727. NULL, // default process ACL
  728. NULL, // default thread ACL
  729. FALSE, // don't inherit my handles
  730. CREATE_NEW_PROCESS_GROUP | CREATE_UNICODE_ENVIRONMENT |CREATE_SUSPENDED,
  731. EnvironmentBlock,
  732. NULL, // same working directory
  733. &si,
  734. &ProcessInformation
  735. );
  736. if (bResult) {
  737. LPWSAPROTOCOL_INFO ProtocolInfo=IrmonControl->ViewOfFile;
  738. WSADuplicateSocket(
  739. IrmonControl->Obex1,
  740. ProcessInformation.dwProcessId,
  741. ProtocolInfo
  742. );
  743. ProtocolInfo++;
  744. WSADuplicateSocket(
  745. IrmonControl->Obex2,
  746. ProcessInformation.dwProcessId,
  747. ProtocolInfo
  748. );
  749. ResumeThread(ProcessInformation.hThread);
  750. LeaveCriticalSection(&IrmonControl->Lock);
  751. WaitForInputIdle( ProcessInformation.hProcess, 10 * 1000 );
  752. WaitForSingleObject(ProcessInformation.hProcess,INFINITE);
  753. EnterCriticalSection(&IrmonControl->Lock);
  754. // DbgPrint("irmon2: irftp exited\n");
  755. CloseHandle(ProcessInformation.hProcess);
  756. CloseHandle(ProcessInformation.hThread);
  757. RetryCount=0;
  758. } else {
  759. // DbgPrint("irmon2: irftp failed to start %d\n",GetLastError());
  760. RetryCount--;
  761. Sleep(1000);
  762. }
  763. }
  764. DestroyEnvironmentBlock( EnvironmentBlock );
  765. }
  766. CloseHandle(UserToken);
  767. }
  768. }
  769. }
  770. LeaveCriticalSection(&IrmonControl->Lock);
  771. }
  772. return 0;
  773. }
  774. #define SERVICE_NAME_1 "OBEX:IrXfer"
  775. #define SERVICE_NAME_2 "OBEX"
  776. BOOL
  777. StartThread(
  778. PIRMON_CONTROL IrmonControl
  779. )
  780. {
  781. DWORD ThreadId;
  782. SECURITY_ATTRIBUTES SA;
  783. WCHAR* SD=L"D:(A;OICI;GA;;;SY) (A;OICI;GR;;;IU)";
  784. BOOL bResult;
  785. SA.nLength=sizeof(SECURITY_ATTRIBUTES);
  786. SA.bInheritHandle=FALSE;
  787. IrmonControl->FileMapping=NULL;
  788. IrmonControl->ViewOfFile=NULL;
  789. IrmonControl->Obex1=CreateListenSocket(SERVICE_NAME_1);
  790. IrmonControl->Obex2=CreateListenSocket(SERVICE_NAME_2);
  791. bResult=ConvertStringSecurityDescriptorToSecurityDescriptor(
  792. SD,
  793. SDDL_REVISION_1,
  794. &SA.lpSecurityDescriptor,
  795. NULL
  796. );
  797. if (bResult) {
  798. IrmonControl->FileMapping=CreateFileMapping(
  799. NULL,
  800. &SA,
  801. PAGE_READWRITE,
  802. 0,
  803. sizeof(WSAPROTOCOL_INFO)*2,
  804. TEXT("Global\\Irmon-shared-memory")
  805. );
  806. if (IrmonControl->FileMapping != NULL) {
  807. IrmonControl->ViewOfFile=MapViewOfFile(
  808. IrmonControl->FileMapping,
  809. FILE_MAP_ALL_ACCESS,
  810. 0,
  811. 0,
  812. 0
  813. );
  814. if (IrmonControl->ViewOfFile != NULL) {
  815. IrmonControl->ThreadHandle=CreateThread(
  816. NULL,
  817. 0,
  818. IrmonThreadStart,
  819. IrmonControl,
  820. 0,
  821. &ThreadId
  822. );
  823. if (IrmonControl->ThreadHandle != NULL) {
  824. return TRUE;
  825. }
  826. }
  827. }
  828. } else {
  829. // DbgPrint("irmon2: failed to create SD %d\n",GetLastError());
  830. }
  831. CloseHandle(IrmonControl->FileMapping);
  832. CloseHandle(IrmonControl->ViewOfFile);
  833. return FALSE;
  834. }
  835. BOOL
  836. WINAPI
  837. DllMain (
  838. HINSTANCE hinst,
  839. DWORD dwReason,
  840. LPVOID pvReserved)
  841. {
  842. if (DLL_PROCESS_ATTACH == dwReason)
  843. {
  844. ghInstance = hinst;
  845. DisableThreadLibraryCalls (hinst);
  846. }
  847. return TRUE;
  848. }