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.

2168 lines
52 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: irxfer.cxx
  8. //
  9. //--------------------------------------------------------------------------
  10. /*
  11. * IRXFER.C
  12. *
  13. */
  14. #include "precomp.h"
  15. #include <malloc.h>
  16. #include <userenv.h>
  17. #include <winsta.h>
  18. #include <ssdp.h>
  19. #include <devlist.h>
  20. #include <irmon.h>
  21. // If this is defined, then we don't popup the up for devices,
  22. // because MBert in the irmon code is doing a tool bubble for
  23. // this now...
  24. #define TURN_OFF_POPUP
  25. //
  26. #ifndef _ALPHA_
  27. #ifndef VOLATILE
  28. #define VOLATILE volatile
  29. #endif
  30. #endif
  31. //
  32. struct SAVED_IRDA_DEVICE_LIST
  33. {
  34. unsigned MaxDevices;
  35. OBEX_DEVICE_LIST Devices;
  36. };
  37. typedef struct _IRXFER_CONTROL {
  38. CRITICAL_SECTION Lock;
  39. PVOID IrmonContext;
  40. ADHOC_CALLBACK AdhocCallback;
  41. SET_SOUND_STATUS_FN SoundStatusCallback;
  42. LONG AdhocNetworkPresent;
  43. PXFER_LIST TransferList;
  44. FILE_TRANSFER *IrTransfer1;
  45. FILE_TRANSFER *IrTransfer2;
  46. } IRXFER_CONTROL, *PIRXFER_CONTROL;
  47. IRXFER_CONTROL GlobalControl;
  48. //
  49. // choices for IRFTP.EXE command-line switches
  50. //
  51. wchar_t * WSZ_SHOW_NOTHING = L"irftp.exe /h";
  52. wchar_t * WSZ_SHOW_WINDOW = L"irftp.exe";
  53. wchar_t * WSZ_SHOW_PROPERTIES_PAGE = L"irftp.exe /s";
  54. wchar_t g_UiCommandLine[ MAX_PATH ];
  55. //
  56. // Handle for irmon.dll (see ..\irmon\irmon.c).
  57. //
  58. extern "C" HINSTANCE ghInstance;
  59. //
  60. // Entry points for IrTran-P
  61. //
  62. #ifdef IRTRANP_ENABLED
  63. extern DWORD WINAPI IrTranP( IN void *pvRpcBinding );
  64. extern VOID IrTranPEnableIrCOMMFailed( IN DWORD dwStatus );
  65. extern BOOL UninitializeIrTranP( IN HANDLE hThread );
  66. extern DWORD EnableDisableIrCOMM( IN BOOL fDisable );
  67. extern DWORD EnableDisableIrTranPv1( IN BOOL fDisable );
  68. static HANDLE g_hIrTranPThread = INVALID_HANDLE_VALUE;
  69. //static DWORD g_dwIrTranPThreadId;
  70. #endif
  71. //
  72. // registry entries
  73. //
  74. const wchar_t * const WSZ_REG_KEY = L"Control Panel\\Infrared";
  75. const wchar_t * const WSZ_REG_KEY_GLOBAL = L"Control Panel\\Infrared\\Global";
  76. const wchar_t * const WSZ_REG_KEY_XFER = L"Control Panel\\Infrared\\File Transfer";
  77. #ifdef IRTRANP_ENABLED
  78. const wchar_t * const WSZ_REG_KEY_IRTRANP = L"Control Panel\\Infrared\\IrTranP";
  79. #endif
  80. const wchar_t * const WSZ_REG_SHOW_UI = L"PopupApp";
  81. const wchar_t * const WSZ_REG_ALLOW_RECEIVE = L"AllowSend";
  82. const wchar_t * const WSZ_REG_SHOW_TRAY = L"ShowTrayIcon";
  83. const wchar_t * const WSZ_REG_PLAY_SOUND = L"PlaySound";
  84. const wchar_t * const WSZ_REG_RECEIVED_FILES_FOLDER = L"RecvdFilesLocation";
  85. #ifdef IRTRANP_ENABLED
  86. const wchar_t * const WSZ_REG_PICTURES_FOLDER = L"RecvdFilesLocation";
  87. const wchar_t * const WSZ_REG_DISABLE_IRTRANPV1 = L"DisableIrTranPv1";
  88. const wchar_t * const WSZ_REG_DISABLE_IRCOMM = L"DisableIrCOMM";
  89. const wchar_t * const WSZ_REG_EXPLORE = L"ExploreOnCompletion";
  90. const wchar_t * const WSZ_REG_SAVEASUPF = L"SaveAsUPF";
  91. const wchar_t * const WSZ_DEFAULT_MYPICTURES = L"C:\\My Pictures";
  92. #endif
  93. HANDLE NetworkRegistrationHandle=NULL;
  94. SET_TRAY_STATUS_FN g_SetTrayStatus;
  95. SET_LOGON_STATUS_FN g_SetLogonStatus;
  96. HKEY g_hUserKey;
  97. HKEY g_hInfraredKey;
  98. HKEY g_hGlobalKey ;
  99. HKEY g_hFileXferKey;
  100. #ifdef IRTRANP_ENABLED
  101. HKEY g_hIrTranPXferKey = 0;
  102. BOOL g_fIrTranPv1Disabled = FALSE;
  103. BOOL g_fIrCOMMDisabled = TRUE;
  104. BOOL g_fExploreOnCompletion = TRUE;
  105. BOOL g_fSaveAsUPF = FALSE;
  106. #endif
  107. // shared with irmon.c
  108. //
  109. HANDLE g_UserToken;
  110. HANDLE g_RegistryEvent;
  111. MUTEX * g_Mutex;
  112. struct SAVED_IRDA_DEVICE_LIST * g_DeviceList;
  113. wchar_t g_ReceivedFilesFolder [ MAX_PATH ];
  114. wchar_t g_DuplicateFileTemplate[ MAX_PATH ];
  115. wchar_t g_DesktopFolder [ MAX_PATH ];
  116. wchar_t g_UnknownDeviceName [ 100 ];
  117. #ifdef IRTRANP_ENABLED
  118. wchar_t g_DefaultPicturesFolder[ MAX_PATH ];
  119. wchar_t g_SpecifiedPicturesFolder[ MAX_PATH ];
  120. #endif
  121. HANDLE g_RegistryWaitHandle = 0;
  122. void
  123. RegistryMonitorCallback(
  124. PVOID ignore,
  125. BOOLEAN unknown
  126. );
  127. BOOL Uninit_RegistryCallback();
  128. HANDLE g_hUi;
  129. RPC_BINDING_HANDLE rpcBinding = 0;
  130. BOOL fListen = TRUE;
  131. BOOL g_fAllowReceives = FALSE;
  132. BOOL g_fShowTrayIcon = TRUE;
  133. BOOL g_fShutdown = FALSE;
  134. BOOL g_fLogoff = FALSE;
  135. BOOL g_fRegistryWaitComplete = FALSE;
  136. BOOL Init_Rpc();
  137. void __stdcall
  138. ProcessRegistryChange();
  139. unsigned long
  140. RegistryMonitorThread(
  141. PVOID ignore
  142. );
  143. DWORD ReadUserPreferences();
  144. BOOL
  145. GetUserToken(
  146. ULONG LogonId,
  147. PHANDLE pUserToken
  148. );
  149. HMODULE hWinstaDll;
  150. PWINSTATIONQUERYINFORMATIONW pWinstationQueryInformation = 0;
  151. BOOL Uninit_Token();
  152. BOOL Uninit_Rpc();
  153. extern "C"
  154. {
  155. extern RPC_IF_HANDLE _NotifyLogon_ServerIfHandle;
  156. void
  157. _UserLoggedOn( handle_t rpc,
  158. error_status_t __RPC_FAR * pStatus
  159. );
  160. void
  161. _UserLoggedOff( handle_t rpc,
  162. error_status_t __RPC_FAR * pStatus
  163. );
  164. BOOL
  165. ShowSendWindow();
  166. BOOL
  167. ShowPropertiesPage();
  168. } // extern "c"
  169. VOID
  170. RemoveFromTransferList(
  171. FILE_TRANSFER* Transfer
  172. )
  173. {
  174. RemoveTransferFromList(GlobalControl.TransferList,Transfer);
  175. return;
  176. }
  177. BOOL
  178. NewAddressHandler(
  179. HANDLE Context,
  180. SOCKET ListenSocket,
  181. HANDLE *AddressContext
  182. )
  183. {
  184. PIRXFER_CONTROL Control=(PIRXFER_CONTROL)Context;
  185. FILE_TRANSFER* Transfer;
  186. BOOL bResult;
  187. LONG Count;
  188. Transfer=ListenForTransfer(ListenSocket,TYPE_IP);
  189. if (Transfer == NULL) {
  190. return FALSE;
  191. }
  192. bResult=AddTransferToList(Control->TransferList,Transfer);
  193. if (!bResult) {
  194. Transfer->StopListening();
  195. return FALSE;
  196. }
  197. EnterCriticalSection(&Control->Lock);
  198. Count=InterlockedIncrement(&Control->AdhocNetworkPresent);
  199. LeaveCriticalSection(&Control->Lock);
  200. if (Count == 1) {
  201. (*Control->AdhocCallback)(Control->IrmonContext,TRUE);
  202. }
  203. *AddressContext=Transfer;
  204. return TRUE;
  205. }
  206. VOID
  207. AddressRemoveHandler(
  208. HANDLE Context,
  209. HANDLE AddressContext
  210. )
  211. {
  212. PIRXFER_CONTROL Control=(PIRXFER_CONTROL)Context;
  213. FILE_TRANSFER* Transfer=(FILE_TRANSFER*)AddressContext;
  214. LONG Count;
  215. RemoveTransferFromList(Control->TransferList,Transfer);
  216. Transfer->StopListening();
  217. EnterCriticalSection(&Control->Lock);
  218. Count=InterlockedDecrement(&Control->AdhocNetworkPresent);
  219. LeaveCriticalSection(&Control->Lock);
  220. if (Count == 0) {
  221. (*Control->AdhocCallback)(Control->IrmonContext,FALSE);
  222. }
  223. return;
  224. }
  225. BOOL
  226. InitializeIrxfer(
  227. PVOID IrmonContext,
  228. ADHOC_CALLBACK AdhocCallback,
  229. SET_LOGON_STATUS_FN x,
  230. SET_TRAY_STATUS_FN y,
  231. SET_SOUND_STATUS_FN SoundStatusCallback,
  232. PVOID *IrxferContext
  233. )
  234. {
  235. BOOL b;
  236. DWORD status = 0;
  237. DWORD dwIrTranPThreadId;
  238. ZeroMemory(&GlobalControl,sizeof(GlobalControl));
  239. GlobalControl.IrmonContext=IrmonContext;
  240. GlobalControl.AdhocCallback=AdhocCallback;
  241. GlobalControl.SoundStatusCallback=SoundStatusCallback;
  242. InitializeCriticalSection(&GlobalControl.Lock);
  243. *IrxferContext=&GlobalControl;
  244. g_fShutdown = FALSE;
  245. g_SetLogonStatus = x;
  246. g_SetTrayStatus = y;
  247. #ifdef TURN_OFF_POPUP
  248. wcscpy( g_UiCommandLine, WSZ_SHOW_NOTHING);
  249. #endif
  250. //
  251. // Event logging. This will make sure that the system event
  252. // logging is configured in the registry:
  253. //
  254. status = EVENT_LOG::CheckConfiguration( WS_EVENT_SOURCE,
  255. WS_CATALOG_PATH,
  256. CATEGORY_COUNT,
  257. 0x7 );
  258. #ifdef DBG_ERROR
  259. if (dwEventStatus)
  260. {
  261. DbgPrint("IrMon: EVENT_LOG::CheckConfiguration() failed: %d\n",
  262. status );
  263. }
  264. #endif
  265. if (!LoadString( ghInstance,
  266. IDS_DUPLICATE_FILE_PATTERN,
  267. g_DuplicateFileTemplate,
  268. sizeof(g_DuplicateFileTemplate) / sizeof(WCHAR)
  269. ))
  270. {
  271. goto abend;
  272. }
  273. if (!LoadString( ghInstance,
  274. IDS_UNKNOWN_DEVICE,
  275. g_UnknownDeviceName,
  276. sizeof(g_UnknownDeviceName) / sizeof(WCHAR)
  277. ))
  278. {
  279. goto abend;
  280. }
  281. GlobalControl.TransferList=CreateXferList();
  282. if (GlobalControl.TransferList == NULL) {
  283. goto abend;
  284. }
  285. g_Mutex = new MUTEX(&status);
  286. if (!g_Mutex || status)
  287. {
  288. goto abend;
  289. }
  290. #if 0
  291. if (0 != FILE_TRANSFER::Init())
  292. {
  293. goto abend;
  294. }
  295. #endif
  296. if (!Init_Rpc())
  297. {
  298. goto abend;
  299. }
  300. #if 0
  301. if ( !FILE_TRANSFER::Sock_Init() )
  302. {
  303. goto abend;
  304. }
  305. #endif
  306. g_RegistryEvent = CreateEvent( NULL, // no security
  307. FALSE, // auto-reset
  308. FALSE, // initially FALSE
  309. NULL // no name
  310. );
  311. if (!g_RegistryEvent)
  312. {
  313. goto abend;
  314. }
  315. //
  316. // This function allows us to get a copy of the interactive user's token.
  317. //
  318. {
  319. hWinstaDll = LoadLibraryW(L"winsta.dll");
  320. if (hWinstaDll == NULL)
  321. {
  322. goto abend;
  323. }
  324. pWinstationQueryInformation = (PWINSTATIONQUERYINFORMATIONW) GetProcAddress( hWinstaDll, "WinStationQueryInformationW" );
  325. if (!pWinstationQueryInformation)
  326. {
  327. goto abend;
  328. }
  329. }
  330. g_hIrTranPThread = CreateThread( NULL,
  331. 0,
  332. IrTranP,
  333. &rpcBinding,
  334. 0,
  335. &dwIrTranPThreadId );
  336. b = GetUserToken( 0, // Terminal Srv ID for the console
  337. &g_UserToken
  338. );
  339. if (b)
  340. {
  341. if (FAILED( SHGetFolderPath( NULL,
  342. CSIDL_DESKTOPDIRECTORY,
  343. g_UserToken,
  344. 0,
  345. g_DesktopFolder)))
  346. {
  347. wcscpy( g_DesktopFolder, L"C:\\");
  348. }
  349. ReadUserPreferences();
  350. }
  351. else
  352. {
  353. DbgLog1(SEV_INFO, "get user token failed %d", GetLastError());
  354. }
  355. // Start the IrTran-P monitor:
  356. #ifdef IRTRANP_ENABLED
  357. if ( (!g_UserToken)
  358. || FAILED( SHGetFolderPath( NULL,
  359. CSIDL_MYPICTURES,
  360. g_UserToken,
  361. 0,
  362. g_DefaultPicturesFolder)))
  363. {
  364. wcscpy( g_DefaultPicturesFolder, WSZ_DEFAULT_MYPICTURES );
  365. }
  366. #endif
  367. return TRUE;
  368. abend:
  369. DWORD dwEventStatus = 0;
  370. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  371. if (!dwEventStatus)
  372. {
  373. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_SETUP_FAILED, GetLastError());
  374. }
  375. if (GlobalControl.TransferList != NULL) {
  376. DeleteXferList(GlobalControl.TransferList);
  377. }
  378. delete g_Mutex;
  379. if (g_RegistryEvent)
  380. {
  381. Uninit_RegistryCallback();
  382. }
  383. if (hWinstaDll != NULL)
  384. {
  385. FreeLibrary( hWinstaDll );
  386. hWinstaDll = NULL;
  387. }
  388. return FALSE;
  389. }
  390. void
  391. _UserLoggedOn( handle_t rpc,
  392. error_status_t __RPC_FAR * pStatus
  393. )
  394. {
  395. BOOL b;
  396. LONG i=10;
  397. //
  398. // Allow only a single notification at a time, to avoid odd race conditions.
  399. //
  400. CLAIM_MUTEX Lock( g_Mutex );
  401. DbgLog(SEV_INFO, "user logged on");
  402. if (g_UserToken) {
  403. CloseHandle( g_UserToken );
  404. g_UserToken = NULL;
  405. }
  406. while (i > 0) {
  407. b = GetUserToken( 0, // Terminal Srv ID for the console
  408. &g_UserToken
  409. );
  410. if (!b) {
  411. #if DBG
  412. *pStatus = GetLastError();
  413. DbgPrint("irmon: Could not get user token, status=%d, count=%d\n",*pStatus,i);
  414. #endif
  415. Sleep(500);
  416. i--;
  417. } else {
  418. break;
  419. }
  420. }
  421. if (!b && (i == 0)) {
  422. *pStatus = GetLastError();
  423. DWORD dwEventStatus = 0;
  424. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  425. if (!dwEventStatus) {
  426. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_LOGON_FAILED, GetLastError());
  427. }
  428. return;
  429. }
  430. if (FAILED( SHGetFolderPath( NULL,
  431. CSIDL_DESKTOPDIRECTORY,
  432. g_UserToken,
  433. 0,
  434. g_DesktopFolder)))
  435. {
  436. wcscpy( g_DesktopFolder, L"C:\\");
  437. }
  438. #ifdef IRTRANP_ENABLED
  439. if (FAILED( SHGetFolderPath( NULL,
  440. CSIDL_MYPICTURES,
  441. g_UserToken,
  442. 0,
  443. g_DefaultPicturesFolder)))
  444. {
  445. wcscpy( g_DefaultPicturesFolder, WSZ_DEFAULT_MYPICTURES );
  446. }
  447. #endif
  448. *pStatus = ReadUserPreferences();
  449. if (*pStatus)
  450. {
  451. SetLastError(*pStatus);
  452. }
  453. }
  454. DWORD
  455. ReadUserPreferences()
  456. {
  457. TOKEN_USER * TokenData;
  458. DbgLog(SEV_INFO, "ReadUserPreferences");
  459. //
  460. // Protect ourselves from login or logout notifications while using the token.
  461. //
  462. {
  463. CLAIM_MUTEX Lock( g_Mutex );
  464. //
  465. // Open the user's preferences keys.
  466. //
  467. DWORD Status = 0;
  468. DWORD SizeNeeded;
  469. GetTokenInformation ( g_UserToken,
  470. TokenUser,
  471. 0,
  472. 0,
  473. &SizeNeeded
  474. );
  475. __try
  476. {
  477. TokenData = (TOKEN_USER *) _alloca( SizeNeeded );
  478. }
  479. __except( EXCEPTION_EXECUTE_HANDLER )
  480. {
  481. DbgLog1(SEV_WARNING, "GetTokenInfo 1 failed %d", GetLastError());
  482. Status = ERROR_NOT_ENOUGH_MEMORY;
  483. }
  484. if (Status)
  485. {
  486. return Status;
  487. }
  488. if (!GetTokenInformation ( g_UserToken,
  489. TokenUser,
  490. TokenData,
  491. SizeNeeded,
  492. &SizeNeeded
  493. ))
  494. {
  495. DbgLog1(SEV_WARNING, "GetTokenInfo 2 failed %d", GetLastError());
  496. return GetLastError();
  497. }
  498. }
  499. wchar_t UnicodeBuffer[256];
  500. UNICODE_STRING UnicodeString;
  501. UnicodeString.Buffer = UnicodeBuffer;
  502. UnicodeString.Length = 0;
  503. UnicodeString.MaximumLength = sizeof(UnicodeBuffer);
  504. NTSTATUS NtStatus;
  505. NtStatus = RtlConvertSidToUnicodeString( &UnicodeString,
  506. TokenData->User.Sid,
  507. FALSE
  508. );
  509. if (!NT_SUCCESS(NtStatus))
  510. {
  511. DbgLog1(SEV_WARNING, "RtlConvertSid failed %x", NtStatus);
  512. return GetLastError();
  513. }
  514. UnicodeString.Buffer[UnicodeString.Length] = 0;
  515. //
  516. // Open all our keys. If we can't open the user's key
  517. // or the key to watch for changes, we bail.
  518. //
  519. if (RegOpenKeyEx( HKEY_USERS,
  520. UnicodeString.Buffer,
  521. 0,
  522. KEY_READ,
  523. &g_hUserKey
  524. ))
  525. {
  526. DbgLog2(SEV_WARNING, "RegOpenKey %S failed %d", UnicodeString.Buffer, GetLastError());
  527. return GetLastError();
  528. }
  529. DWORD Disposition;
  530. if (RegCreateKeyEx( g_hUserKey,
  531. WSZ_REG_KEY,
  532. 0, // reserved MBZ
  533. 0, // class name
  534. REG_OPTION_NON_VOLATILE,
  535. KEY_READ,
  536. 0, // security attributes
  537. &g_hInfraredKey,
  538. &Disposition
  539. ))
  540. {
  541. DbgLog2(SEV_WARNING, "RegCreateKey '%S' failed %d", WSZ_REG_KEY, GetLastError());
  542. return GetLastError();
  543. }
  544. #ifdef IRTRANP_ENABLED
  545. RegOpenKeyEx( g_hUserKey,
  546. WSZ_REG_KEY_IRTRANP,
  547. 0,
  548. KEY_READ,
  549. &g_hIrTranPXferKey );
  550. #endif
  551. //
  552. // Inform MBert to start PnP'ing printers and maybe to show the tray icon.
  553. //
  554. (*g_SetLogonStatus)( TRUE );
  555. //
  556. // Start the registry snoop.
  557. //
  558. RegistryMonitorCallback(0, 0);
  559. #if 0
  560. NetworkRegistrationHandle=RegisterForAdhocNetworksNotification(
  561. &GlobalControl,
  562. NewAddressHandler,
  563. AddressRemoveHandler
  564. );
  565. #endif
  566. #if 1
  567. BOOL bResult;
  568. GlobalControl.IrTransfer1=InitializeSocket( SERVICE_NAME_1);
  569. if (GlobalControl.IrTransfer1 != NULL) {
  570. bResult=AddTransferToList(GlobalControl.TransferList,GlobalControl.IrTransfer1);
  571. if (!bResult) {
  572. GlobalControl.IrTransfer1->StopListening();
  573. GlobalControl.IrTransfer1=NULL;
  574. }
  575. }
  576. GlobalControl.IrTransfer2=InitializeSocket(SERVICE_NAME_2);
  577. if (GlobalControl.IrTransfer2 != NULL) {
  578. bResult=AddTransferToList(GlobalControl.TransferList,GlobalControl.IrTransfer2);
  579. if (!bResult) {
  580. GlobalControl.IrTransfer2->StopListening();
  581. GlobalControl.IrTransfer2=NULL;
  582. }
  583. }
  584. #endif
  585. return 0;
  586. }
  587. void
  588. _UserLoggedOff( handle_t rpc,
  589. error_status_t __RPC_FAR * pStatus
  590. )
  591. {
  592. error_status_t status = 0;
  593. //
  594. // Allow only a single notification at a time, to avoid odd race conditions.
  595. //
  596. CLAIM_MUTEX Lock( g_Mutex );
  597. DbgLog(SEV_INFO, "user logged off");
  598. g_fLogoff = TRUE;
  599. g_fAllowReceives = FALSE;
  600. #if 0
  601. if (NetworkRegistrationHandle != NULL) {
  602. UnRegisterForAdhocNetworksNotification(NetworkRegistrationHandle);
  603. NetworkRegistrationHandle=NULL;
  604. }
  605. #endif
  606. if (GlobalControl.IrTransfer1 != NULL) {
  607. RemoveTransferFromList(GlobalControl.TransferList,GlobalControl.IrTransfer1);
  608. GlobalControl.IrTransfer1->StopListening();
  609. GlobalControl.IrTransfer1=NULL;
  610. }
  611. if (GlobalControl.IrTransfer2 != NULL) {
  612. RemoveTransferFromList(GlobalControl.TransferList,GlobalControl.IrTransfer2);
  613. GlobalControl.IrTransfer2->StopListening();
  614. GlobalControl.IrTransfer2=NULL;
  615. }
  616. if (g_hUi) {
  617. CloseHandle( g_hUi );
  618. g_hUi = 0;
  619. }
  620. //
  621. // Close down the registry watcher.
  622. //
  623. if (g_RegistryWaitHandle)
  624. {
  625. if (FALSE == UnregisterWait( g_RegistryWaitHandle ))
  626. {
  627. while (!*((BOOL volatile *)&g_fRegistryWaitComplete))
  628. {
  629. Sleep(1000);
  630. }
  631. }
  632. g_RegistryWaitHandle = 0;
  633. }
  634. g_fRegistryWaitComplete = FALSE;
  635. CloseHandle( g_UserToken );
  636. g_UserToken = 0;
  637. //
  638. // Close the registry handles.
  639. //
  640. RegCloseKey( g_hUserKey );
  641. g_hUserKey = 0;
  642. RegCloseKey( g_hFileXferKey );
  643. g_hFileXferKey = 0;
  644. #ifdef IRTRANP_ENABLED
  645. RegCloseKey( g_hIrTranPXferKey );
  646. g_hIrTranPXferKey = 0;
  647. #endif
  648. RegCloseKey( g_hInfraredKey );
  649. g_hInfraredKey = 0;
  650. RegCloseKey( g_hGlobalKey );
  651. g_hGlobalKey = 0;
  652. (*g_SetLogonStatus)( FALSE );
  653. (*g_SetTrayStatus)( GlobalControl.IrmonContext, FALSE );
  654. NoDeviceInRange( rpcBinding, &status );
  655. *pStatus = 0;
  656. g_fLogoff = FALSE;
  657. }
  658. #ifdef IRTRANP_ENABLED
  659. //--------------------------------------------------------------------
  660. // RegistryCheckDwordFlag()
  661. //
  662. // Check to see if the specified registry key value has changed,
  663. // if so, then update the value and return TRUE.
  664. //--------------------------------------------------------------------
  665. BOOL RegistryCheckDwordFlag( IN HKEY hKey,
  666. IN const WCHAR *pwszValueName,
  667. IN BOOL NotPresentValue,
  668. OUT BOOL *pbValue )
  669. {
  670. BOOL fChanged = FALSE;
  671. DWORD dwStatus = 0;
  672. DWORD dwRegDword;
  673. DWORD dwSize = sizeof(dwRegDword);
  674. dwStatus = RegQueryValueEx( hKey,
  675. pwszValueName,
  676. NULL,
  677. NULL,
  678. (UCHAR*)&dwRegDword,
  679. &dwSize );
  680. if (dwStatus != ERROR_SUCCESS) {
  681. //
  682. // failed, no change
  683. //
  684. DbgLog2(SEV_INFO,"REG: Key/Value: %S: Status: %d\n",
  685. pwszValueName, dwStatus );
  686. if (NotPresentValue != *pbValue) {
  687. //
  688. // the not present value is no the same as the current, change and report a change
  689. //
  690. *pbValue=NotPresentValue;
  691. return TRUE;
  692. }
  693. //
  694. // No change
  695. //
  696. return FALSE;
  697. } else {
  698. //
  699. // got value
  700. //
  701. if ( (dwRegDword) && (*pbValue == FALSE)) {
  702. //
  703. // Value changed from FALSE to TRUE.
  704. //
  705. fChanged = TRUE;
  706. *pbValue = TRUE;
  707. } else if ((!dwRegDword) && (*pbValue)) {
  708. //
  709. // Value changed from TRUE to FALSE.
  710. //
  711. fChanged = TRUE;
  712. *pbValue = FALSE;
  713. }
  714. }
  715. return fChanged;
  716. }
  717. //--------------------------------------------------------------------
  718. // IrTranPFlagChanged()
  719. //
  720. // Check to see if the specified registry flag changed. If the value
  721. // changed, return TRUE, if not then return FALSE. Return the new value
  722. // in *pfDisabled.
  723. //--------------------------------------------------------------------
  724. BOOL IrTranPFlagChanged( IN const WCHAR *pwszDisabledValueName,
  725. IN BOOL NotPresentValue,
  726. IN OUT BOOL *pfDisabled )
  727. {
  728. DWORD dwStatus = 0;
  729. DWORD dwSize;
  730. DWORD dwRegDword;
  731. BOOL fChanged = FALSE;
  732. BOOL fDisabled = *pfDisabled;
  733. DbgLog3(SEV_INFO, "Process IrTranP flag Change %S, def=%d, current=%d",
  734. pwszDisabledValueName,
  735. NotPresentValue,
  736. *pfDisabled
  737. );
  738. if (!g_hIrTranPXferKey)
  739. {
  740. // By default, the IrTranP subkey does not exist at all until
  741. // user brings up Wireless Link CPL and makes changes to
  742. // to the Image Transfer page. Without trying to reopen the subkey
  743. // here, we may fail to pick up the changes if this is the first
  744. // time IrTranP subkey gets created.
  745. // The other issue that might rise(although rare) is when the subkey
  746. // is deleted for whatever reasons. We should reset everything to
  747. // default when the key is deleted. An easy but slow solution is to
  748. // reopen the subkey everytime this function is called. This approach
  749. // would ensures that the HKEY to the subkey is always fresh.
  750. // Since the case is rare and implementation is slow, lets forget
  751. // about this for the time being. If the entire Infrared subkey is
  752. // deleted or missing then we will return TRUE (the default is
  753. // enabled).
  754. //
  755. RegOpenKeyEx(g_hUserKey,
  756. WSZ_REG_KEY_IRTRANP,
  757. 0,
  758. KEY_READ,
  759. &g_hIrTranPXferKey );
  760. }
  761. if (!g_hIrTranPXferKey) {
  762. DbgLog(SEV_INFO, "IrTranP: g_hIrTranPXferKey not opened");
  763. if (NotPresentValue != *pfDisabled) {
  764. //
  765. // the not present value does not match the current setting, change it
  766. //
  767. *pfDisabled=NotPresentValue;
  768. return TRUE;
  769. }
  770. //
  771. // it must match, so no change
  772. //
  773. return FALSE;
  774. }
  775. //
  776. // Is IrTranP over the specified channel to be disabled?
  777. //
  778. if (RegistryCheckDwordFlag(g_hIrTranPXferKey,
  779. pwszDisabledValueName,
  780. NotPresentValue,
  781. &fDisabled))
  782. {
  783. #ifdef DBG_REGISTRY
  784. DbgPrint("DisableIrCOMM: Changed: %d\n",g_fIrCOMMDisabled);
  785. #endif
  786. }
  787. if (*pfDisabled != fDisabled)
  788. {
  789. *pfDisabled = fDisabled;
  790. fChanged = TRUE;
  791. }
  792. return fChanged;
  793. }
  794. //--------------------------------------------------------------------
  795. // ProcessIrTranPRegistryChanges()
  796. //
  797. //--------------------------------------------------------------------
  798. void ProcessIrTranPRegistryChanges()
  799. {
  800. DWORD dwStatus = 0;
  801. DWORD dwSize;
  802. DWORD dwRegDword;
  803. DbgLog(SEV_INFO, "Process IrTranP Registry Change");
  804. //
  805. // Is IrTranP over IrCOMM to be disabled?
  806. //
  807. if (IrTranPFlagChanged(WSZ_REG_DISABLE_IRCOMM,TRUE,&g_fIrCOMMDisabled))
  808. {
  809. #ifdef DBG_REGISTRY
  810. DbgPrint("DisableIrCOMM: Changed: %d\n",g_fIrCOMMDisabled);
  811. #endif
  812. dwStatus = EnableDisableIrCOMM(g_fIrCOMMDisabled);
  813. if ((g_fIrCOMMDisabled == FALSE) && (dwStatus))
  814. {
  815. #ifdef DBG_ERROR
  816. if (dwStatus)
  817. {
  818. DbgPrint("IrTranP: EnableDisableIrCOMM() failed: %d\n",dwStatus);
  819. }
  820. #endif
  821. IrTranPEnableIrCOMMFailed(dwStatus);
  822. }
  823. }
  824. //
  825. // Is IrTranP over sockets (IrTranPv1) to be disabled?
  826. //
  827. if (IrTranPFlagChanged(WSZ_REG_DISABLE_IRTRANPV1,FALSE,&g_fIrTranPv1Disabled))
  828. {
  829. #ifdef DBG_REGISTRY
  830. DbgPrint("DisableIrTranPv1: Changed: %d\n",g_fIrTranPv1Disabled);
  831. #endif
  832. dwStatus = EnableDisableIrTranPv1(g_fIrTranPv1Disabled);
  833. }
  834. //
  835. // Explore the new pictures automatically:
  836. //
  837. if (RegistryCheckDwordFlag(g_hIrTranPXferKey,
  838. WSZ_REG_EXPLORE,
  839. TRUE,
  840. &g_fExploreOnCompletion))
  841. {
  842. #ifdef DBG_REGISTRY
  843. DbgPrint("ExploreOnCompletion: Changed: %d\n",g_fExploreOnCompletion);
  844. #endif
  845. }
  846. //
  847. // Save pictures as .UPF files instead of .JPEG files?
  848. //
  849. // NOTE: This is used for testing to create full .UPF files and
  850. // would not normally be set by the customer.
  851. //
  852. if (RegistryCheckDwordFlag(g_hIrTranPXferKey,
  853. WSZ_REG_SAVEASUPF,
  854. FALSE,
  855. &g_fSaveAsUPF))
  856. {
  857. #ifdef DBG_REGISTRY
  858. DbgPrint("SaveAsUPF: Changed: %d\n",g_fSaveAsUPF);
  859. #endif
  860. }
  861. //
  862. // Where pictures are to be stored. If this value exists then it
  863. // is used instead of the default "My Documents\My Pictures\"
  864. // path.
  865. //
  866. dwSize = sizeof(g_SpecifiedPicturesFolder);
  867. dwStatus = RegQueryValueEx( g_hIrTranPXferKey,
  868. WSZ_REG_PICTURES_FOLDER,
  869. NULL,
  870. NULL,
  871. (UCHAR*)g_SpecifiedPicturesFolder,
  872. &dwSize );
  873. if (dwStatus)
  874. {
  875. DbgLog1( SEV_INFO, "REG: Pictures Folder Status: %d\n", dwStatus );
  876. g_SpecifiedPicturesFolder[0] = 0;
  877. }
  878. else
  879. {
  880. DbgLog1( SEV_INFO, "REG: Pictures Folder %S\n",
  881. g_SpecifiedPicturesFolder );
  882. #ifdef DBG_REGISTRY
  883. DbgPrint("RecvdFilesLocation: %S\n",g_SpecifiedPicturesFolder);
  884. #endif
  885. }
  886. }
  887. #endif
  888. //--------------------------------------------------------------------
  889. // ProcessRegistryChange()
  890. //
  891. //--------------------------------------------------------------------
  892. void __stdcall
  893. ProcessRegistryChange()
  894. {
  895. DWORD status = 0;
  896. DWORD size = sizeof(unsigned char);
  897. unsigned char bool = 0;
  898. DbgLog(SEV_INFO, "process registry change");
  899. if (!g_hGlobalKey)
  900. {
  901. status = RegOpenKeyEx( g_hUserKey,
  902. WSZ_REG_KEY_GLOBAL,
  903. 0,
  904. KEY_READ,
  905. & g_hGlobalKey
  906. );
  907. if (status)
  908. {
  909. DbgLog2(SEV_WARNING, "RegOpenKeyEx '%S' failed %d", WSZ_REG_KEY_GLOBAL, status);
  910. }
  911. }
  912. if (!g_hFileXferKey)
  913. {
  914. status = RegOpenKeyEx( g_hUserKey,
  915. WSZ_REG_KEY_XFER,
  916. 0,
  917. KEY_READ,
  918. & g_hFileXferKey
  919. );
  920. if (status)
  921. {
  922. DbgLog2(SEV_WARNING, "RegOpenKeyEx '%S' failed %d", WSZ_REG_KEY_XFER, status);
  923. }
  924. }
  925. #ifndef TURN_OFF_POPUP
  926. status = RegQueryValueEx( g_hFileXferKey,
  927. WSZ_REG_SHOW_UI,
  928. NULL,
  929. NULL,
  930. &bool,
  931. &size
  932. );
  933. if (status || bool)
  934. {
  935. DbgLog1( SEV_INFO, "reg: show ui key, status %d\n", status);
  936. wcscpy( g_UiCommandLine, WSZ_SHOW_WINDOW);
  937. }
  938. else
  939. {
  940. wcscpy( g_UiCommandLine, WSZ_SHOW_NOTHING);
  941. }
  942. #endif
  943. //
  944. // Are other people allowed to send to me?
  945. //
  946. size = sizeof(unsigned char);
  947. status = RegQueryValueEx( g_hFileXferKey,
  948. WSZ_REG_ALLOW_RECEIVE,
  949. NULL,
  950. NULL,
  951. &bool,
  952. &size
  953. );
  954. if (!g_hUserKey)
  955. {
  956. g_fAllowReceives = FALSE;
  957. }
  958. else if (status || bool)
  959. {
  960. DbgLog1( SEV_INFO, "reg: allow receives key, status %d\n", status);
  961. g_fAllowReceives = TRUE;
  962. }
  963. else
  964. {
  965. g_fAllowReceives = FALSE;
  966. }
  967. size = sizeof( g_ReceivedFilesFolder );
  968. status = RegQueryValueEx( g_hFileXferKey,
  969. WSZ_REG_RECEIVED_FILES_FOLDER,
  970. NULL,
  971. NULL,
  972. (unsigned char *) g_ReceivedFilesFolder,
  973. &size
  974. );
  975. if (status)
  976. {
  977. wcscpy( g_ReceivedFilesFolder, g_DesktopFolder );
  978. DbgLog2( SEV_INFO, "reg: received files folder status %d\nfolder %S", status, g_ReceivedFilesFolder);
  979. }
  980. else
  981. {
  982. DbgLog1( SEV_INFO, "reg: received files folder %S\n", g_ReceivedFilesFolder);
  983. }
  984. // always end path with a backslash '\'
  985. if( bNoTrailingSlash(g_ReceivedFilesFolder) )
  986. lstrcat(g_ReceivedFilesFolder, szBACKSLASH );
  987. size = sizeof(unsigned char);
  988. status = RegQueryValueEx( g_hGlobalKey,
  989. WSZ_REG_SHOW_TRAY,
  990. NULL,
  991. NULL,
  992. &bool,
  993. &size
  994. );
  995. if (status || bool)
  996. {
  997. DbgLog1( SEV_INFO, "reg: show tray key, status %d\n", status);
  998. g_fShowTrayIcon = TRUE;
  999. }
  1000. else
  1001. {
  1002. g_fShowTrayIcon = FALSE;
  1003. }
  1004. (*g_SetTrayStatus)( GlobalControl.IrmonContext, g_fShowTrayIcon );
  1005. size = sizeof(unsigned char);
  1006. status = RegQueryValueEx( g_hGlobalKey,
  1007. WSZ_REG_PLAY_SOUND,
  1008. NULL,
  1009. NULL,
  1010. &bool,
  1011. &size
  1012. );
  1013. if ((status != ERROR_SUCCESS)) {
  1014. DbgLog1( SEV_INFO, "reg: play sound key, status %d\n", status);
  1015. bool=TRUE;
  1016. }
  1017. (*GlobalControl.SoundStatusCallback)(
  1018. GlobalControl.IrmonContext,
  1019. bool
  1020. );
  1021. //
  1022. // Process changes specific to IrTran-P:
  1023. //
  1024. #ifdef IRTRANP_ENABLED
  1025. ProcessIrTranPRegistryChanges();
  1026. #endif
  1027. //
  1028. // Look for more changes.
  1029. //
  1030. status = RegNotifyChangeKeyValue( g_hInfraredKey,
  1031. TRUE, // watch child keys
  1032. REG_NOTIFY_CHANGE_LAST_SET,
  1033. g_RegistryEvent,
  1034. TRUE // async
  1035. );
  1036. if (status)
  1037. {
  1038. DWORD dwEventStatus = 0;
  1039. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  1040. if (!dwEventStatus)
  1041. {
  1042. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_REGISTER_NOTIFY_FAILED, status);
  1043. }
  1044. }
  1045. }
  1046. void
  1047. RegistryMonitorCallback(
  1048. PVOID ignore,
  1049. BOOLEAN unknown
  1050. )
  1051. {
  1052. DbgLog(SEV_INFO, "reg callback");
  1053. if (g_fShutdown || g_fLogoff)
  1054. {
  1055. DbgLog(SEV_INFO, "reg callback: terminating");
  1056. if (g_fShutdown)
  1057. {
  1058. CloseHandle( g_RegistryEvent );
  1059. }
  1060. g_fRegistryWaitComplete = TRUE;
  1061. return;
  1062. }
  1063. ProcessRegistryChange();
  1064. if (!RegisterWaitForSingleObject( &g_RegistryWaitHandle,
  1065. g_RegistryEvent,
  1066. RegistryMonitorCallback,
  1067. 0,
  1068. INFINITE,
  1069. WT_EXECUTEDEFAULT
  1070. ))
  1071. {
  1072. g_RegistryWaitHandle = 0;
  1073. DWORD dwEventStatus = 0;
  1074. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  1075. if (!dwEventStatus)
  1076. {
  1077. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_REGISTER_NOTIFY_FAILED, GetLastError());
  1078. }
  1079. }
  1080. }
  1081. void
  1082. UpdateDiscoveredDevices(
  1083. const OBEX_DEVICE_LIST *IrDevices,
  1084. const OBEX_DEVICE_LIST *IpDevices
  1085. )
  1086. {
  1087. BOOL fLaunch = FALSE;
  1088. error_status_t status;
  1089. DbgLog2(SEV_INFO, "device notification: %d Ir devices and %d Ip devices in range", IrDevices->DeviceCount,IpDevices->DeviceCount);
  1090. //
  1091. // Update the saved device list.
  1092. //
  1093. SAVED_IRDA_DEVICE_LIST * list;
  1094. g_Mutex->Enter();
  1095. if ((g_DeviceList == NULL)
  1096. ||
  1097. (g_DeviceList->MaxDevices < (IrDevices->DeviceCount + IpDevices->DeviceCount))) {
  1098. list = (SAVED_IRDA_DEVICE_LIST *)
  1099. new char [ sizeof(SAVED_IRDA_DEVICE_LIST)
  1100. + (IrDevices->DeviceCount + IpDevices->DeviceCount) * sizeof(OBEX_DEVICE)
  1101. ];
  1102. if (!list) {
  1103. g_Mutex->Leave();
  1104. return;
  1105. }
  1106. list->MaxDevices = 1+IrDevices->DeviceCount + IpDevices->DeviceCount;
  1107. if (g_DeviceList) {
  1108. delete g_DeviceList;
  1109. }
  1110. g_DeviceList = list;
  1111. } else {
  1112. list = g_DeviceList;
  1113. }
  1114. //
  1115. // Determine how many of the existing devices support our protocol.
  1116. //
  1117. list->Devices.DeviceCount=0;
  1118. unsigned i;
  1119. for (i=0; i < IrDevices->DeviceCount; i++) {
  1120. list->Devices.DeviceList[list->Devices.DeviceCount]=IrDevices->DeviceList[i];
  1121. list->Devices.DeviceCount++;
  1122. fLaunch = fLaunch || list->Devices.DeviceList[i].DeviceSpecific.s.Irda.ObexSupport;
  1123. }
  1124. //
  1125. // add in any ip devices as well
  1126. //
  1127. for (i=0; i < IpDevices->DeviceCount; i++) {
  1128. list->Devices.DeviceList[list->Devices.DeviceCount]=IpDevices->DeviceList[i];
  1129. list->Devices.DeviceCount++;
  1130. fLaunch = TRUE;
  1131. }
  1132. //
  1133. // Inform the UI program of the new device list. Don't create the process
  1134. // unless at least one of the devices said it supports OBEX.
  1135. //
  1136. if (fLaunch) {
  1137. g_Mutex->Leave();
  1138. LaunchUi( g_UiCommandLine );
  1139. } else {
  1140. if (g_DeviceList->Devices.DeviceCount > 0) {
  1141. DeviceInRange( rpcBinding, &g_DeviceList->Devices, &status );
  1142. g_Mutex->Leave();
  1143. DbgLog1(SEV_INFO, "UpdateDiscoveredDevices: DeviceInRange returned %d", status);
  1144. } else {
  1145. g_Mutex->Leave();
  1146. NoDeviceInRange( rpcBinding, &status );
  1147. }
  1148. }
  1149. }
  1150. BOOL
  1151. UninitializeIrxfer(
  1152. PVOID IrxferContext
  1153. )
  1154. {
  1155. PIRXFER_CONTROL Control=(PIRXFER_CONTROL)IrxferContext;
  1156. error_status_t LogoffStatus;
  1157. g_fShutdown = TRUE;
  1158. DbgLog1(SEV_INFO, "start shutdown: %d", GetTickCount());
  1159. _UserLoggedOff(NULL,&LogoffStatus);
  1160. if (Control->TransferList != NULL) {
  1161. DeleteXferList(Control->TransferList);
  1162. }
  1163. ShutdownUi( rpcBinding );
  1164. DbgLog1(SEV_INFO, "after RPC: %d", GetTickCount());
  1165. BOOL fSuccess = TRUE;
  1166. // fSuccess &= FILE_TRANSFER::Shutdown();
  1167. DbgLog1(SEV_INFO, "after FILE_TRANSFER::Shutdown: %d", GetTickCount());
  1168. fSuccess &= Uninit_Rpc();
  1169. DbgLog1(SEV_INFO, "after Unit_Rpc: %d", GetTickCount());
  1170. fSuccess &= Uninit_RegistryCallback();
  1171. DbgLog1(SEV_INFO, "after registry: %d", GetTickCount());
  1172. fSuccess &= Uninit_Token();
  1173. DbgLog1(SEV_INFO, "after token: %d", GetTickCount());
  1174. #ifdef IRTRANP_ENABLED
  1175. fSuccess &= UninitializeIrTranP(g_hIrTranPThread);
  1176. #endif
  1177. if (hWinstaDll != NULL)
  1178. {
  1179. FreeLibrary( hWinstaDll );
  1180. hWinstaDll = NULL;
  1181. }
  1182. #ifdef LOGGING
  1183. Log_Close();
  1184. #endif
  1185. DeleteCriticalSection(&Control->Lock);
  1186. return fSuccess;
  1187. }
  1188. BOOL
  1189. Uninit_RegistryCallback()
  1190. {
  1191. BOOL fSuccess = TRUE;
  1192. SetEvent( g_RegistryEvent );
  1193. //
  1194. // The handle will be deleted when the callback is completed.
  1195. //
  1196. while (WAIT_TIMEOUT == WaitForSingleObject( g_RegistryEvent, 0 ))
  1197. {
  1198. Sleep(1000);
  1199. }
  1200. return fSuccess;
  1201. }
  1202. BOOL
  1203. Uninit_Token()
  1204. {
  1205. error_status_t status = 0;
  1206. _UserLoggedOff( 0, &status );
  1207. return TRUE;
  1208. }
  1209. BOOL
  1210. Init_Rpc()
  1211. {
  1212. DWORD Status = 0;
  1213. //
  1214. // This is the proper code to enable access by multiple users to an LRPC endpoint.
  1215. // It is the wrong code for a named pipe endpoint; just pass NULL instead.
  1216. //
  1217. SECURITY_DESCRIPTOR sd;
  1218. InitializeSecurityDescriptor(
  1219. &sd,
  1220. SECURITY_DESCRIPTOR_REVISION
  1221. );
  1222. if ( FALSE == SetSecurityDescriptorDacl (
  1223. &sd,
  1224. TRUE, // Dacl present
  1225. NULL, // NULL Dacl
  1226. FALSE // Not defaulted
  1227. ) )
  1228. {
  1229. return FALSE;
  1230. }
  1231. Status = RpcServerUseProtseqIf( (PUSHORT)L"ncalrpc",
  1232. RPC_C_PROTSEQ_MAX_REQS_DEFAULT, _IrSendFiles_v0_2_s_ifspec, &sd);
  1233. if (Status && Status != RPC_S_DUPLICATE_ENDPOINT)
  1234. {
  1235. SetLastError(Status);
  1236. return FALSE;
  1237. }
  1238. Status = RpcServerUseProtseqIf( (PUSHORT)L"ncalrpc", RPC_C_PROTSEQ_MAX_REQS_DEFAULT, _NotifyLogon_ServerIfHandle, &sd);
  1239. if (Status && Status != RPC_S_DUPLICATE_ENDPOINT)
  1240. {
  1241. SetLastError(Status);
  1242. return FALSE;
  1243. }
  1244. Status = RpcServerRegisterIfEx( _IrSendFiles_v0_2_s_ifspec,
  1245. 0, // no EPV nonsense
  1246. 0, // no EPV nonsense
  1247. RPC_IF_AUTOLISTEN,
  1248. RPC_C_LISTEN_MAX_CALLS_DEFAULT,
  1249. NULL // no security callback
  1250. );
  1251. if (Status)
  1252. {
  1253. SetLastError(Status);
  1254. return FALSE;
  1255. }
  1256. Status = RpcServerRegisterIfEx( _NotifyLogon_ServerIfHandle,
  1257. 0, // no EPV nonsense
  1258. 0, // no EPV nonsense
  1259. RPC_IF_AUTOLISTEN,
  1260. RPC_C_LISTEN_MAX_CALLS_DEFAULT,
  1261. NULL // no security callback
  1262. );
  1263. if (Status)
  1264. {
  1265. SetLastError(Status);
  1266. return FALSE;
  1267. }
  1268. Status = RpcBindingFromStringBinding((PUSHORT)L"ncalrpc:", &rpcBinding);
  1269. if (Status)
  1270. {
  1271. SetLastError(Status);
  1272. return FALSE;
  1273. }
  1274. return TRUE;
  1275. }
  1276. BOOL
  1277. Uninit_Rpc()
  1278. {
  1279. BOOL fSuccess = TRUE;
  1280. error_status_t status;
  1281. status = RpcServerUnregisterIf( _IrSendFiles_v0_2_s_ifspec,
  1282. 0, // no EPV nonsense
  1283. TRUE // wait for calls to complete
  1284. );
  1285. if (status)
  1286. {
  1287. DbgLog1(SEV_ERROR, "uninit_rpc: UnregisterIf SendFiles i/f failed %d", status);
  1288. fSuccess = FALSE;
  1289. }
  1290. status = RpcServerUnregisterIf( _NotifyLogon_ServerIfHandle,
  1291. 0, // no EPV nonsense
  1292. TRUE // wait for calls to complete
  1293. );
  1294. if (status)
  1295. {
  1296. DbgLog1(SEV_ERROR, "uninit_rpc: UnregisterIf NotifyLogon i/f failed %d", status);
  1297. fSuccess = FALSE;
  1298. }
  1299. RpcBindingFree( &rpcBinding );
  1300. return fSuccess;
  1301. }
  1302. void
  1303. _SendFiles(
  1304. handle_t RpcHandle,
  1305. COOKIE ClientCookie,
  1306. wchar_t DirectoryName[],
  1307. wchar_t FileNameList[],
  1308. long ListLength,
  1309. unsigned long DeviceId,
  1310. OBEX_DEVICE_TYPE DeviceType,
  1311. error_status_t * pStatus,
  1312. FAILURE_LOCATION * pLocation
  1313. )
  1314. {
  1315. FILE_TRANSFER * Transfer;
  1316. DbgPrint("IRMON: SendFiles address=%08lx, type=%d\n",DeviceId,DeviceType);
  1317. *pStatus = 0;
  1318. *pLocation = locStartup;
  1319. if ( g_fShutdown )
  1320. {
  1321. *pStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  1322. return;
  1323. }
  1324. if (DirectoryName && *DirectoryName)
  1325. {
  1326. *pStatus = ERROR_ACCESS_DENIED;
  1327. return;
  1328. }
  1329. //
  1330. // Try NT-compatible connect.
  1331. //
  1332. Transfer = new FILE_TRANSFER;
  1333. if (!Transfer || !Transfer->Xfer_Init( FileNameList, ListLength, dialNt5, DeviceType,TRUE,INVALID_SOCKET ))
  1334. {
  1335. delete Transfer;
  1336. *pStatus = ERROR_NOT_ENOUGH_MEMORY;
  1337. return;
  1338. }
  1339. Transfer->_rpcHandle = RpcHandle;
  1340. Transfer->_cookie = ClientCookie;
  1341. Transfer->BeginSend( DeviceId, DeviceType, pStatus, pLocation );
  1342. if (*pStatus == ERROR_INVALID_DATA && *pLocation == locConnect) {
  1343. //
  1344. // Try Win98-compatible connect.
  1345. //
  1346. Transfer = new FILE_TRANSFER;
  1347. if (!Transfer || !Transfer->Xfer_Init( FileNameList, ListLength, dialWin95,DeviceType,TRUE,INVALID_SOCKET ))
  1348. {
  1349. delete Transfer;
  1350. *pStatus = ERROR_NOT_ENOUGH_MEMORY;
  1351. return;
  1352. }
  1353. Transfer->_rpcHandle = RpcHandle;
  1354. Transfer->_cookie = ClientCookie;
  1355. Transfer->BeginSend( DeviceId, DeviceType, pStatus, pLocation );
  1356. }
  1357. if (*pStatus != ERROR_SUCCESS) {
  1358. DWORD dwEventStatus = 0;
  1359. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  1360. if (!dwEventStatus) {
  1361. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_CONNECT_FAILED, *pStatus);
  1362. }
  1363. } else {
  1364. //
  1365. // it worked add it to the list
  1366. //
  1367. AddTransferToList(GlobalControl.TransferList,Transfer);
  1368. }
  1369. }
  1370. error_status_t
  1371. _CancelSend(
  1372. /* [in] */ handle_t binding,
  1373. /* [in] */ COOKIE cookie
  1374. )
  1375. {
  1376. FILE_TRANSFER * transfer = TransferFromCookie(GlobalControl.TransferList,cookie);
  1377. if (!transfer) {
  1378. return ERROR_FILE_NOT_FOUND;
  1379. }
  1380. transfer->Cancel();
  1381. // transfer->DecrementRefCount();
  1382. return 0;
  1383. }
  1384. error_status_t
  1385. _CancelReceive(
  1386. /* [in] */ handle_t binding,
  1387. /* [in] */ COOKIE cookie
  1388. )
  1389. {
  1390. FILE_TRANSFER * transfer = TransferFromCookie(GlobalControl.TransferList,cookie);
  1391. if (!transfer) {
  1392. return ERROR_FILE_NOT_FOUND;
  1393. }
  1394. transfer->Cancel();
  1395. // transfer->DecrementRefCount();
  1396. return 0;
  1397. }
  1398. void * __RPC_USER MIDL_user_allocate(size_t Size)
  1399. {
  1400. return MemAlloc( Size );
  1401. }
  1402. void MIDL_user_free( void * Object )
  1403. {
  1404. MemFree( Object );
  1405. }
  1406. BOOL
  1407. LaunchUi(
  1408. wchar_t * cmdline
  1409. )
  1410. {
  1411. PVOID EnvironmentBlock;
  1412. STARTUPINFO si;
  1413. PROCESS_INFORMATION ProcessInformation;
  1414. DWORD UiProcessId;
  1415. si.cb = sizeof(STARTUPINFO);
  1416. si.lpReserved = NULL;
  1417. si.lpTitle = NULL;
  1418. si.lpDesktop = L"WinSta0\\Default";
  1419. si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L;
  1420. si.dwFlags = 0;;
  1421. si.wShowWindow = SW_SHOW;
  1422. si.lpReserved2 = NULL;
  1423. si.cbReserved2 = 0;
  1424. //
  1425. // Protect ourselves from login or logout notifications while using the token.
  1426. //
  1427. {
  1428. CLAIM_MUTEX Lock( g_Mutex );
  1429. if (0 == g_UserToken)
  1430. {
  1431. return FALSE;
  1432. }
  1433. if (!CreateEnvironmentBlock( &EnvironmentBlock,
  1434. g_UserToken,
  1435. FALSE
  1436. ))
  1437. {
  1438. DWORD dwEventStatus = 0;
  1439. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  1440. if (!dwEventStatus)
  1441. {
  1442. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_LAUNCH_FAILED, GetLastError());
  1443. }
  1444. return FALSE;
  1445. }
  1446. if (!CreateProcessAsUser( g_UserToken,
  1447. NULL, // just use the cmd line parm
  1448. cmdline,
  1449. NULL, // default process ACL
  1450. NULL, // default thread ACL
  1451. FALSE, // don't inherit my handles
  1452. CREATE_NEW_PROCESS_GROUP |
  1453. CREATE_UNICODE_ENVIRONMENT,
  1454. EnvironmentBlock,
  1455. NULL, // same working directory
  1456. &si,
  1457. &ProcessInformation
  1458. ))
  1459. {
  1460. DestroyEnvironmentBlock( EnvironmentBlock );
  1461. DWORD dwEventStatus = 0;
  1462. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  1463. if (!dwEventStatus)
  1464. {
  1465. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_LAUNCH_FAILED, GetLastError());
  1466. }
  1467. return FALSE;
  1468. }
  1469. }
  1470. UiProcessId = ProcessInformation.dwProcessId;
  1471. DestroyEnvironmentBlock( EnvironmentBlock );
  1472. WaitForInputIdle( ProcessInformation.hProcess, 10 * 1000 );
  1473. CloseHandle(ProcessInformation.hThread);
  1474. if (g_hUi)
  1475. {
  1476. if (WAIT_TIMEOUT == WaitForSingleObject( g_hUi, 0 ))
  1477. {
  1478. // previous instance still lives; keep current handle
  1479. //
  1480. CloseHandle( ProcessInformation.hProcess );
  1481. }
  1482. else
  1483. {
  1484. // previous instance dead; update
  1485. //
  1486. CloseHandle( g_hUi );
  1487. g_hUi = ProcessInformation.hProcess;
  1488. }
  1489. }
  1490. else
  1491. {
  1492. // no previous instance
  1493. //
  1494. g_hUi = ProcessInformation.hProcess;
  1495. }
  1496. //
  1497. // Give the UI the current device list.
  1498. //
  1499. error_status_t status = 0;
  1500. g_Mutex->Enter();
  1501. if (g_DeviceList)
  1502. {
  1503. DeviceInRange( rpcBinding, &g_DeviceList->Devices, &status );
  1504. }
  1505. DbgLog1(SEV_INFO, "LaunchUi: DeviceInRange returned %d", status);
  1506. g_Mutex->Leave();
  1507. return TRUE;
  1508. }
  1509. BOOL GetReceivedFilesFolder( LPWSTR szDir, DWORD dwLen )
  1510. {
  1511. if (g_ReceivedFilesFolder[0] == 0)
  1512. {
  1513. ProcessRegistryChange();
  1514. }
  1515. wcscpy(szDir, g_ReceivedFilesFolder);
  1516. return TRUE;
  1517. }
  1518. BOOL
  1519. ShowSendWindow()
  1520. {
  1521. wchar_t UiCommandLine[ MAX_PATH ];
  1522. wcscpy( UiCommandLine, WSZ_SHOW_WINDOW );
  1523. return LaunchUi( UiCommandLine );
  1524. }
  1525. BOOL ShowPropertiesPage()
  1526. {
  1527. wchar_t UiCommandLine[ MAX_PATH ];
  1528. wcscpy( UiCommandLine, WSZ_SHOW_PROPERTIES_PAGE );
  1529. return LaunchUi( UiCommandLine );
  1530. }
  1531. error_status_t
  1532. _GetDesktopDirectory(
  1533. handle_t Binding,
  1534. wchar_t Directory[]
  1535. )
  1536. {
  1537. wcscpy( Directory, g_DesktopFolder );
  1538. return 0;
  1539. }
  1540. extern "C"
  1541. {
  1542. LRESULT
  1543. IrxferHandlePowerMessage(
  1544. HWND hWnd,
  1545. UINT message,
  1546. WPARAM wParam,
  1547. LPARAM lParam
  1548. );
  1549. }
  1550. BOOL IrxferQuerySuspend( LPARAM lParam );
  1551. void IrxferResume();
  1552. LRESULT
  1553. IrxferHandlePowerMessage(
  1554. HWND hwnd,
  1555. UINT message,
  1556. WPARAM wParam,
  1557. LPARAM lParam
  1558. )
  1559. {
  1560. if (message == WM_QUERYENDSESSION)
  1561. {
  1562. DbgLog1(SEV_INFO, "POWER: Query logoff %d", lParam);
  1563. return IrxferQuerySuspend( 1 );
  1564. }
  1565. ASSERT( message == WM_POWERBROADCAST );
  1566. switch (wParam)
  1567. {
  1568. case PBT_APMQUERYSUSPEND:
  1569. {
  1570. DbgLog1(SEV_INFO, "POWER: Query Suspend %d", lParam);
  1571. return ( IrxferQuerySuspend( lParam ) ? TRUE : BROADCAST_QUERY_DENY );
  1572. }
  1573. case PBT_APMQUERYSUSPENDFAILED:
  1574. {
  1575. DbgLog(SEV_INFO, "POWER: Suspend Failed");
  1576. IrxferResume();
  1577. break;
  1578. }
  1579. case PBT_APMRESUMESUSPEND:
  1580. {
  1581. DbgLog(SEV_INFO, "POWER: Resume Suspend");
  1582. IrxferResume();
  1583. break;
  1584. }
  1585. case PBT_APMRESUMECRITICAL:
  1586. {
  1587. DbgLog(SEV_INFO, "POWER: Resume Critical");
  1588. //
  1589. // Do nothing. The Winsock layer will send failures
  1590. // for reads and writes on any sockets active before
  1591. // the shutdown.
  1592. //
  1593. break;
  1594. }
  1595. default:
  1596. DbgLog2(SEV_INFO, "POWER: w=0x%x l=0x%x", wParam, lParam);
  1597. }
  1598. return DefWindowProc(hwnd, message, wParam, lParam);
  1599. }
  1600. BOOL
  1601. IrxferQuerySuspend( LPARAM lParam )
  1602. {
  1603. if (!AreThereActiveTransfers(GlobalControl.TransferList)) {
  1604. DbgLog(SEV_INFO, " no transfers active");
  1605. return TRUE;
  1606. }
  1607. if (lParam & 1)
  1608. {
  1609. //
  1610. // The app is allowed to prompt the user if necessary.
  1611. //
  1612. boolean answer;
  1613. DWORD status = ShutdownRequested( rpcBinding, &answer );
  1614. DbgLog2(SEV_INFO, " status %d answer %d", status, answer);
  1615. if (status || answer == TRUE)
  1616. {
  1617. g_fShutdown = 1;
  1618. return TRUE;
  1619. }
  1620. else
  1621. {
  1622. return FALSE;
  1623. }
  1624. }
  1625. else
  1626. {
  1627. DbgLog(SEV_INFO, " not allowed to prompt");
  1628. g_fShutdown = 1;
  1629. return TRUE;
  1630. }
  1631. }
  1632. void
  1633. IrxferResume()
  1634. {
  1635. g_fShutdown = FALSE;
  1636. // update device list
  1637. }
  1638. BOOL IsWorkstationLocked()
  1639. {
  1640. return FALSE;
  1641. }
  1642. /*****************************************************************************
  1643. *
  1644. * GetUserToken
  1645. *
  1646. * Return the token for the user currently logged onto the WinStation
  1647. *
  1648. * ENTRY:
  1649. * LogonId (input)
  1650. * LogonId of WinStation
  1651. *
  1652. * pUserToken (output)
  1653. * Variable to place the returned token handle if successfull.
  1654. *
  1655. * EXIT:
  1656. * STATUS_SUCCESS - no error
  1657. *
  1658. ****************************************************************************/
  1659. BOOL
  1660. GetUserToken(
  1661. ULONG LogonId,
  1662. PHANDLE pUserToken
  1663. )
  1664. {
  1665. BOOL Result;
  1666. ULONG ReturnLength;
  1667. NTSTATUS Status;
  1668. OBJECT_ATTRIBUTES ObjA;
  1669. HANDLE ImpersonationToken;
  1670. WINSTATIONUSERTOKEN Info;
  1671. SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
  1672. //
  1673. // This gets the token of the user logged onto the WinStation
  1674. // if we are an admin caller.
  1675. //
  1676. // This is so that CSRSS can dup the handle to our process
  1677. Info.ProcessId = (HANDLE)LongToHandle(GetCurrentProcessId());
  1678. Info.ThreadId = (HANDLE)LongToHandle(GetCurrentThreadId());
  1679. Result = (*pWinstationQueryInformation)(
  1680. SERVERNAME_CURRENT,
  1681. LogonId,
  1682. WinStationUserToken,
  1683. &Info,
  1684. sizeof(Info),
  1685. &ReturnLength
  1686. );
  1687. if( !Result )
  1688. {
  1689. return( FALSE );
  1690. }
  1691. //
  1692. // The token returned is a duplicate of a primary token.
  1693. //
  1694. *pUserToken = Info.UserToken;
  1695. return( TRUE );
  1696. }