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.

1463 lines
36 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 <devlist.h>
  17. #include <irmon.h>
  18. #include <irmonftp.h>
  19. #ifndef VOLATILE
  20. #define VOLATILE volatile
  21. #endif
  22. //
  23. struct SAVED_IRDA_DEVICE_LIST
  24. {
  25. unsigned MaxDevices;
  26. OBEX_DEVICE_LIST Devices;
  27. };
  28. typedef struct _IRXFER_CONTROL {
  29. CRITICAL_SECTION Lock;
  30. PVOID IrmonContext;
  31. SET_SOUND_STATUS_FN SoundStatusCallback;
  32. PXFER_LIST TransferList;
  33. FILE_TRANSFER *IrTransfer1;
  34. FILE_TRANSFER *IrTransfer2;
  35. } IRXFER_CONTROL, *PIRXFER_CONTROL;
  36. IRXFER_CONTROL GlobalControl;
  37. //
  38. // Handle for irmon.dll (see ..\irmon\irmon.c).
  39. //
  40. extern "C" HINSTANCE ghInstance;
  41. //
  42. // Entry points for IrTran-P
  43. //
  44. #ifdef IRTRANP_ENABLED
  45. #include <irtranpp.h>
  46. static HANDLE g_hIrTranPThread = NULL;
  47. #endif
  48. //
  49. // registry entries
  50. //
  51. const wchar_t * const WSZ_REG_KEY = L"Control Panel\\Infrared";
  52. const wchar_t * const WSZ_REG_KEY_GLOBAL = L"Control Panel\\Infrared\\Global";
  53. const wchar_t * const WSZ_REG_KEY_XFER = L"Control Panel\\Infrared\\File Transfer";
  54. #ifdef IRTRANP_ENABLED
  55. const wchar_t * const WSZ_REG_KEY_IRTRANP = L"Control Panel\\Infrared\\IrTranP";
  56. #endif
  57. const wchar_t * const WSZ_REG_SHOW_UI = L"PopupApp";
  58. const wchar_t * const WSZ_REG_ALLOW_RECEIVE = L"AllowSend";
  59. const wchar_t * const WSZ_REG_SHOW_TRAY = L"ShowTrayIcon";
  60. const wchar_t * const WSZ_REG_PLAY_SOUND = L"PlaySound";
  61. const wchar_t * const WSZ_REG_RECEIVED_FILES_FOLDER = L"RecvdFilesLocation";
  62. #ifdef IRTRANP_ENABLED
  63. const wchar_t * const WSZ_REG_PICTURES_FOLDER = L"RecvdFilesLocation";
  64. const wchar_t * const WSZ_REG_DISABLE_IRTRANPV1 = L"DisableIrTranPv1";
  65. const wchar_t * const WSZ_REG_DISABLE_IRCOMM = L"DisableIrCOMM";
  66. const wchar_t * const WSZ_REG_EXPLORE = L"ExploreOnCompletion";
  67. const wchar_t * const WSZ_REG_SAVEASUPF = L"SaveAsUPF";
  68. const wchar_t * const WSZ_DEFAULT_MYPICTURES = L"C:\\My Pictures";
  69. #endif
  70. SET_TRAY_STATUS_FN g_SetTrayStatus;
  71. HKEY g_hUserKey;
  72. HKEY g_hInfraredKey;
  73. HKEY g_hGlobalKey ;
  74. HKEY g_hFileXferKey;
  75. #ifdef IRTRANP_ENABLED
  76. HKEY g_hIrTranPXferKey = 0;
  77. BOOL g_fIrTranPv1Disabled = FALSE;
  78. BOOL g_fIrCOMMDisabled = TRUE;
  79. BOOL g_fExploreOnCompletion = TRUE;
  80. BOOL g_fSaveAsUPF = FALSE;
  81. #endif
  82. HANDLE g_RegistryEvent;
  83. MUTEX * g_Mutex;
  84. struct SAVED_IRDA_DEVICE_LIST * g_DeviceList;
  85. wchar_t g_ReceivedFilesFolder [ MAX_PATH ];
  86. wchar_t g_DuplicateFileTemplate[ MAX_PATH ];
  87. wchar_t g_DesktopFolder [ MAX_PATH ];
  88. wchar_t g_UnknownDeviceName [ 100 ];
  89. #ifdef IRTRANP_ENABLED
  90. wchar_t g_DefaultPicturesFolder[ MAX_PATH ];
  91. wchar_t g_SpecifiedPicturesFolder[ MAX_PATH ];
  92. #endif
  93. HANDLE g_RegistryWaitHandle = 0;
  94. void
  95. RegistryMonitorCallback(
  96. PVOID ignore,
  97. BOOLEAN unknown
  98. );
  99. BOOL Uninit_RegistryCallback();
  100. RPC_BINDING_HANDLE rpcBinding = 0;
  101. BOOL fListen = TRUE;
  102. BOOL g_fAllowReceives = FALSE;
  103. BOOL g_fShowTrayIcon = TRUE;
  104. BOOL g_fShutdown = FALSE;
  105. BOOL g_fLogoff = FALSE;
  106. BOOL g_fRegistryWaitComplete = FALSE;
  107. void __stdcall
  108. ProcessRegistryChange();
  109. unsigned long
  110. RegistryMonitorThread(
  111. PVOID ignore
  112. );
  113. DWORD ReadUserPreferences();
  114. extern "C"
  115. {
  116. BOOL
  117. ShowSendWindow();
  118. BOOL
  119. ShowPropertiesPage();
  120. } // extern "c"
  121. VOID
  122. RemoveFromTransferList(
  123. FILE_TRANSFER* Transfer
  124. )
  125. {
  126. RemoveTransferFromList(GlobalControl.TransferList,Transfer);
  127. return;
  128. }
  129. BOOL
  130. InitializeIrxfer(
  131. PVOID IrmonContext,
  132. SET_TRAY_STATUS_FN y,
  133. SET_SOUND_STATUS_FN SoundStatusCallback,
  134. PVOID *IrxferContext
  135. )
  136. {
  137. BOOL b;
  138. DWORD status = 0;
  139. g_DefaultPicturesFolder[0]='\0';
  140. g_DesktopFolder[0]='\0';
  141. ZeroMemory(&GlobalControl,sizeof(GlobalControl));
  142. GlobalControl.IrmonContext=IrmonContext;
  143. GlobalControl.SoundStatusCallback=SoundStatusCallback;
  144. InitializeCriticalSection(&GlobalControl.Lock);
  145. *IrxferContext=&GlobalControl;
  146. g_fShutdown = FALSE;
  147. g_SetTrayStatus = y;
  148. //
  149. // Event logging. This will make sure that the system event
  150. // logging is configured in the registry:
  151. //
  152. status = EVENT_LOG::CheckConfiguration( WS_EVENT_SOURCE,
  153. WS_CATALOG_PATH,
  154. CATEGORY_COUNT,
  155. 0x7 );
  156. #ifdef DBG_ERROR
  157. if (dwEventStatus)
  158. {
  159. DbgPrint("IrMon: EVENT_LOG::CheckConfiguration() failed: %d\n",
  160. status );
  161. }
  162. #endif
  163. if (!LoadString( ghInstance,
  164. IDS_DUPLICATE_FILE_PATTERN,
  165. g_DuplicateFileTemplate,
  166. sizeof(g_DuplicateFileTemplate) / sizeof(WCHAR)
  167. ))
  168. {
  169. #if DBG
  170. DbgPrint("InitializeIrxfer(): LoadString(1) failed\n");
  171. #endif
  172. goto abend;
  173. }
  174. if (!LoadString( ghInstance,
  175. IDS_UNKNOWN_DEVICE2,
  176. g_UnknownDeviceName,
  177. sizeof(g_UnknownDeviceName) / sizeof(WCHAR)
  178. ))
  179. {
  180. #if DBG
  181. DbgPrint("InitializeIrxfer(): LoadString(2) failed\n");
  182. #endif
  183. goto abend;
  184. }
  185. GlobalControl.TransferList=CreateXferList();
  186. if (GlobalControl.TransferList == NULL) {
  187. #if DBG
  188. DbgPrint("InitializeIrxfer(): CreateXferList() failed\n");
  189. #endif
  190. goto abend;
  191. }
  192. g_Mutex = new MUTEX(&status);
  193. if (!g_Mutex || status)
  194. {
  195. goto abend;
  196. }
  197. if (FAILED( SHGetFolderPath( NULL,
  198. CSIDL_DESKTOPDIRECTORY,
  199. NULL,
  200. 0,
  201. g_DesktopFolder)))
  202. {
  203. #if DBG
  204. DbgPrint("InitializeIrxfer(): SHGetFolderPath(desktop) failed\n");
  205. #endif
  206. goto abend;
  207. }
  208. g_RegistryEvent = CreateEvent( NULL, // no security
  209. FALSE, // auto-reset
  210. FALSE, // initially FALSE
  211. NULL // no name
  212. );
  213. if (!g_RegistryEvent) {
  214. #if DBG
  215. DbgPrint("InitializeIrxfer(): CreateEvent() failed\n");
  216. #endif
  217. goto abend;
  218. }
  219. g_hIrTranPThread=StartIrTranP();
  220. if (g_hIrTranPThread == NULL)
  221. {
  222. #if DBG
  223. DbgPrint("InitializeIrxfer(): StartIrTranP() failed\n");
  224. #endif
  225. goto abend;
  226. }
  227. if (ReadUserPreferences() != 0)
  228. {
  229. // force Uninit_RegistryCallback to properly terminate registry watcher thread.
  230. g_fShutdown = true;
  231. goto abend;
  232. }
  233. return TRUE;
  234. abend:
  235. DWORD dwEventStatus = 0;
  236. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  237. if (!dwEventStatus)
  238. {
  239. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_SETUP_FAILED, GetLastError());
  240. }
  241. if (GlobalControl.TransferList != NULL) {
  242. DeleteXferList(GlobalControl.TransferList);
  243. }
  244. delete g_Mutex;
  245. if (g_RegistryEvent)
  246. {
  247. Uninit_RegistryCallback();
  248. }
  249. return FALSE;
  250. }
  251. DWORD
  252. ReadUserPreferences()
  253. {
  254. DbgLog(SEV_INFO, "ReadUserPreferences");
  255. //
  256. // Open all our keys. If we can't open the user's key
  257. // or the key to watch for changes, we bail.
  258. //
  259. if (RegOpenKeyEx( HKEY_CURRENT_USER,
  260. NULL,
  261. 0,
  262. KEY_READ,
  263. &g_hUserKey
  264. ))
  265. {
  266. DbgLog1(SEV_WARNING, "RegOpenKey failed %d", GetLastError());
  267. return GetLastError();
  268. }
  269. DWORD Disposition;
  270. if (RegCreateKeyEx( g_hUserKey,
  271. WSZ_REG_KEY,
  272. 0, // reserved MBZ
  273. 0, // class name
  274. REG_OPTION_NON_VOLATILE,
  275. KEY_READ,
  276. 0, // security attributes
  277. &g_hInfraredKey,
  278. &Disposition
  279. ))
  280. {
  281. DbgLog2(SEV_WARNING, "RegCreateKey '%S' failed %d", WSZ_REG_KEY, GetLastError());
  282. return GetLastError();
  283. }
  284. #ifdef IRTRANP_ENABLED
  285. RegOpenKeyEx( g_hUserKey,
  286. WSZ_REG_KEY_IRTRANP,
  287. 0,
  288. KEY_READ,
  289. &g_hIrTranPXferKey );
  290. #endif
  291. //
  292. // Start the registry snoop.
  293. //
  294. RegistryMonitorCallback(0, 0);
  295. BOOL bResult;
  296. GlobalControl.IrTransfer1=InitializeSocket( SERVICE_NAME_1);
  297. if (GlobalControl.IrTransfer1 != NULL) {
  298. bResult=AddTransferToList(GlobalControl.TransferList,GlobalControl.IrTransfer1);
  299. if (!bResult) {
  300. GlobalControl.IrTransfer1->StopListening();
  301. GlobalControl.IrTransfer1=NULL;
  302. }
  303. }
  304. GlobalControl.IrTransfer2=InitializeSocket(SERVICE_NAME_2);
  305. if (GlobalControl.IrTransfer2 != NULL) {
  306. bResult=AddTransferToList(GlobalControl.TransferList,GlobalControl.IrTransfer2);
  307. if (!bResult) {
  308. GlobalControl.IrTransfer2->StopListening();
  309. GlobalControl.IrTransfer2=NULL;
  310. }
  311. }
  312. if (GlobalControl.IrTransfer1 == NULL && GlobalControl.IrTransfer2 == NULL)
  313. {
  314. DbgPrint("IrMon: ReadUserPreferences::Failed to init sockets\n");
  315. return -1;
  316. }
  317. return 0;
  318. }
  319. void
  320. _UserLoggedOff( handle_t rpc,
  321. error_status_t __RPC_FAR * pStatus
  322. )
  323. {
  324. error_status_t status = 0;
  325. //
  326. // Allow only a single notification at a time, to avoid odd race conditions.
  327. //
  328. CLAIM_MUTEX Lock( g_Mutex );
  329. DbgLog(SEV_INFO, "user logged off");
  330. g_fLogoff = TRUE;
  331. g_fAllowReceives = FALSE;
  332. if (GlobalControl.IrTransfer1 != NULL) {
  333. RemoveTransferFromList(GlobalControl.TransferList,GlobalControl.IrTransfer1);
  334. GlobalControl.IrTransfer1->StopListening();
  335. GlobalControl.IrTransfer1=NULL;
  336. }
  337. if (GlobalControl.IrTransfer2 != NULL) {
  338. RemoveTransferFromList(GlobalControl.TransferList,GlobalControl.IrTransfer2);
  339. GlobalControl.IrTransfer2->StopListening();
  340. GlobalControl.IrTransfer2=NULL;
  341. }
  342. //
  343. // Close down the registry watcher.
  344. //
  345. if (g_RegistryWaitHandle)
  346. {
  347. if (FALSE == UnregisterWait( g_RegistryWaitHandle ))
  348. {
  349. while (!*((BOOL volatile *)&g_fRegistryWaitComplete))
  350. {
  351. Sleep(1000);
  352. }
  353. }
  354. g_RegistryWaitHandle = 0;
  355. }
  356. g_fRegistryWaitComplete = FALSE;
  357. //
  358. // Close the registry handles.
  359. //
  360. RegCloseKey( g_hUserKey );
  361. g_hUserKey = 0;
  362. RegCloseKey( g_hFileXferKey );
  363. g_hFileXferKey = 0;
  364. #ifdef IRTRANP_ENABLED
  365. RegCloseKey( g_hIrTranPXferKey );
  366. g_hIrTranPXferKey = 0;
  367. #endif
  368. RegCloseKey( g_hInfraredKey );
  369. g_hInfraredKey = 0;
  370. RegCloseKey( g_hGlobalKey );
  371. g_hGlobalKey = 0;
  372. *pStatus = 0;
  373. g_fLogoff = FALSE;
  374. }
  375. #ifdef IRTRANP_ENABLED
  376. //--------------------------------------------------------------------
  377. // RegistryCheckDwordFlag()
  378. //
  379. // Check to see if the specified registry key value has changed,
  380. // if so, then update the value and return TRUE.
  381. //--------------------------------------------------------------------
  382. BOOL RegistryCheckDwordFlag( IN HKEY hKey,
  383. IN const WCHAR *pwszValueName,
  384. IN BOOL NotPresentValue,
  385. OUT BOOL *pbValue )
  386. {
  387. BOOL fChanged = FALSE;
  388. DWORD dwStatus = 0;
  389. DWORD dwRegDword;
  390. DWORD dwSize = sizeof(dwRegDword);
  391. dwStatus = RegQueryValueEx( hKey,
  392. pwszValueName,
  393. NULL,
  394. NULL,
  395. (UCHAR*)&dwRegDword,
  396. &dwSize );
  397. if (dwStatus != ERROR_SUCCESS) {
  398. //
  399. // failed, no change
  400. //
  401. DbgLog2(SEV_INFO,"REG: Key/Value: %S: Status: %d\n",
  402. pwszValueName, dwStatus );
  403. if (NotPresentValue != *pbValue) {
  404. //
  405. // the not present value is no the same as the current, change and report a change
  406. //
  407. *pbValue=NotPresentValue;
  408. return TRUE;
  409. }
  410. //
  411. // No change
  412. //
  413. return FALSE;
  414. } else {
  415. //
  416. // got value
  417. //
  418. if ( (dwRegDword) && (*pbValue == FALSE)) {
  419. //
  420. // Value changed from FALSE to TRUE.
  421. //
  422. fChanged = TRUE;
  423. *pbValue = TRUE;
  424. } else if ((!dwRegDword) && (*pbValue)) {
  425. //
  426. // Value changed from TRUE to FALSE.
  427. //
  428. fChanged = TRUE;
  429. *pbValue = FALSE;
  430. }
  431. }
  432. return fChanged;
  433. }
  434. //--------------------------------------------------------------------
  435. // IrTranPFlagChanged()
  436. //
  437. // Check to see if the specified registry flag changed. If the value
  438. // changed, return TRUE, if not then return FALSE. Return the new value
  439. // in *pfDisabled.
  440. //--------------------------------------------------------------------
  441. BOOL IrTranPFlagChanged( IN const WCHAR *pwszDisabledValueName,
  442. IN BOOL NotPresentValue,
  443. IN OUT BOOL *pfDisabled )
  444. {
  445. DWORD dwStatus = 0;
  446. DWORD dwSize;
  447. DWORD dwRegDword;
  448. BOOL fChanged = FALSE;
  449. BOOL fDisabled = *pfDisabled;
  450. DbgLog3(SEV_INFO, "Process IrTranP flag Change %S, def=%d, current=%d",
  451. pwszDisabledValueName,
  452. NotPresentValue,
  453. *pfDisabled
  454. );
  455. if (!g_hIrTranPXferKey)
  456. {
  457. // By default, the IrTranP subkey does not exist at all until
  458. // user brings up Wireless Link CPL and makes changes to
  459. // to the Image Transfer page. Without trying to reopen the subkey
  460. // here, we may fail to pick up the changes if this is the first
  461. // time IrTranP subkey gets created.
  462. // The other issue that might rise(although rare) is when the subkey
  463. // is deleted for whatever reasons. We should reset everything to
  464. // default when the key is deleted. An easy but slow solution is to
  465. // reopen the subkey everytime this function is called. This approach
  466. // would ensures that the HKEY to the subkey is always fresh.
  467. // Since the case is rare and implementation is slow, lets forget
  468. // about this for the time being. If the entire Infrared subkey is
  469. // deleted or missing then we will return TRUE (the default is
  470. // enabled).
  471. //
  472. RegOpenKeyEx(g_hUserKey,
  473. WSZ_REG_KEY_IRTRANP,
  474. 0,
  475. KEY_READ,
  476. &g_hIrTranPXferKey );
  477. }
  478. if (!g_hIrTranPXferKey) {
  479. DbgLog(SEV_INFO, "IrTranP: g_hIrTranPXferKey not opened");
  480. if (NotPresentValue != *pfDisabled) {
  481. //
  482. // the not present value does not match the current setting, change it
  483. //
  484. *pfDisabled=NotPresentValue;
  485. return TRUE;
  486. }
  487. //
  488. // it must match, so no change
  489. //
  490. return FALSE;
  491. }
  492. //
  493. // Is IrTranP over the specified channel to be disabled?
  494. //
  495. if (RegistryCheckDwordFlag(g_hIrTranPXferKey,
  496. pwszDisabledValueName,
  497. NotPresentValue,
  498. &fDisabled))
  499. {
  500. #ifdef DBG_REGISTRY
  501. DbgPrint("DisableIrCOMM: Changed: %d\n",g_fIrCOMMDisabled);
  502. #endif
  503. }
  504. if (*pfDisabled != fDisabled)
  505. {
  506. *pfDisabled = fDisabled;
  507. fChanged = TRUE;
  508. }
  509. return fChanged;
  510. }
  511. //--------------------------------------------------------------------
  512. // ProcessIrTranPRegistryChanges()
  513. //
  514. //--------------------------------------------------------------------
  515. void ProcessIrTranPRegistryChanges()
  516. {
  517. DWORD dwStatus = 0;
  518. DWORD dwSize;
  519. DWORD dwRegDword;
  520. DbgLog(SEV_INFO, "Process IrTranP Registry Change");
  521. //
  522. // Is IrTranP over IrCOMM to be disabled?
  523. //
  524. if (IrTranPFlagChanged(WSZ_REG_DISABLE_IRCOMM,TRUE,&g_fIrCOMMDisabled))
  525. {
  526. #ifdef DBG_REGISTRY
  527. DbgPrint("DisableIrCOMM: Changed: %d\n",g_fIrCOMMDisabled);
  528. #endif
  529. dwStatus = EnableDisableIrCOMM(g_hIrTranPThread,g_fIrCOMMDisabled);
  530. if ((g_fIrCOMMDisabled == FALSE) && (dwStatus))
  531. {
  532. #ifdef DBG_ERROR
  533. if (dwStatus)
  534. {
  535. DbgPrint("IrTranP: EnableDisableIrCOMM() failed: %d\n",dwStatus);
  536. }
  537. #endif
  538. IrTranPEnableIrCOMMFailed(g_hIrTranPThread,dwStatus);
  539. }
  540. }
  541. //
  542. // Is IrTranP over sockets (IrTranPv1) to be disabled?
  543. //
  544. if (IrTranPFlagChanged(WSZ_REG_DISABLE_IRTRANPV1,FALSE,&g_fIrTranPv1Disabled))
  545. {
  546. #ifdef DBG_REGISTRY
  547. DbgPrint("DisableIrTranPv1: Changed: %d\n",g_fIrTranPv1Disabled);
  548. #endif
  549. dwStatus = EnableDisableIrTranPv1(g_hIrTranPThread,g_fIrTranPv1Disabled);
  550. }
  551. //
  552. // Explore the new pictures automatically:
  553. //
  554. if (RegistryCheckDwordFlag(g_hIrTranPXferKey,
  555. WSZ_REG_EXPLORE,
  556. TRUE,
  557. &g_fExploreOnCompletion))
  558. {
  559. #ifdef DBG_REGISTRY
  560. DbgPrint("ExploreOnCompletion: Changed: %d\n",g_fExploreOnCompletion);
  561. #endif
  562. }
  563. //
  564. // Save pictures as .UPF files instead of .JPEG files?
  565. //
  566. // NOTE: This is used for testing to create full .UPF files and
  567. // would not normally be set by the customer.
  568. //
  569. if (RegistryCheckDwordFlag(g_hIrTranPXferKey,
  570. WSZ_REG_SAVEASUPF,
  571. FALSE,
  572. &g_fSaveAsUPF))
  573. {
  574. #ifdef DBG_REGISTRY
  575. DbgPrint("SaveAsUPF: Changed: %d\n",g_fSaveAsUPF);
  576. #endif
  577. }
  578. //
  579. // Where pictures are to be stored. If this value exists then it
  580. // is used instead of the default "My Documents\My Pictures\"
  581. // path.
  582. //
  583. dwSize = sizeof(g_SpecifiedPicturesFolder);
  584. dwStatus = RegQueryValueEx( g_hIrTranPXferKey,
  585. WSZ_REG_PICTURES_FOLDER,
  586. NULL,
  587. NULL,
  588. (UCHAR*)g_SpecifiedPicturesFolder,
  589. &dwSize );
  590. if (dwStatus)
  591. {
  592. DbgLog1( SEV_INFO, "REG: Pictures Folder Status: %d\n", dwStatus );
  593. g_SpecifiedPicturesFolder[0] = 0;
  594. }
  595. else
  596. {
  597. DbgLog1( SEV_INFO, "REG: Pictures Folder %S\n",
  598. g_SpecifiedPicturesFolder );
  599. #ifdef DBG_REGISTRY
  600. DbgPrint("RecvdFilesLocation: %S\n",g_SpecifiedPicturesFolder);
  601. #endif
  602. }
  603. }
  604. #endif
  605. //--------------------------------------------------------------------
  606. // ProcessRegistryChange()
  607. //
  608. //--------------------------------------------------------------------
  609. void __stdcall
  610. ProcessRegistryChange()
  611. {
  612. DWORD status = 0;
  613. DWORD size = sizeof(unsigned char);
  614. unsigned char boolVal = 0;
  615. DbgLog(SEV_INFO, "process registry change");
  616. if (!g_hGlobalKey)
  617. {
  618. status = RegOpenKeyEx( g_hUserKey,
  619. WSZ_REG_KEY_GLOBAL,
  620. 0,
  621. KEY_READ,
  622. & g_hGlobalKey
  623. );
  624. if (status)
  625. {
  626. DbgLog2(SEV_WARNING, "RegOpenKeyEx '%S' failed %d", WSZ_REG_KEY_GLOBAL, status);
  627. }
  628. }
  629. if (!g_hFileXferKey)
  630. {
  631. status = RegOpenKeyEx( g_hUserKey,
  632. WSZ_REG_KEY_XFER,
  633. 0,
  634. KEY_READ,
  635. & g_hFileXferKey
  636. );
  637. if (status)
  638. {
  639. DbgLog2(SEV_WARNING, "RegOpenKeyEx '%S' failed %d", WSZ_REG_KEY_XFER, status);
  640. }
  641. }
  642. //
  643. // Are other people allowed to send to me?
  644. //
  645. size = sizeof(unsigned char);
  646. status = RegQueryValueEx( g_hFileXferKey,
  647. WSZ_REG_ALLOW_RECEIVE,
  648. NULL,
  649. NULL,
  650. &boolVal,
  651. &size
  652. );
  653. if (!g_hUserKey)
  654. {
  655. g_fAllowReceives = FALSE;
  656. }
  657. else if (status || boolVal)
  658. {
  659. DbgLog1( SEV_INFO, "reg: allow receives key, status %d\n", status);
  660. g_fAllowReceives = TRUE;
  661. }
  662. else
  663. {
  664. g_fAllowReceives = FALSE;
  665. }
  666. size = sizeof( g_ReceivedFilesFolder );
  667. status = RegQueryValueEx( g_hFileXferKey,
  668. WSZ_REG_RECEIVED_FILES_FOLDER,
  669. NULL,
  670. NULL,
  671. (unsigned char *) g_ReceivedFilesFolder,
  672. &size
  673. );
  674. if (status) {
  675. StringCbCopy(g_ReceivedFilesFolder,sizeof(g_ReceivedFilesFolder), g_DesktopFolder );
  676. DbgLog2( SEV_INFO, "reg: received files folder status %d\nfolder %S", status, g_ReceivedFilesFolder);
  677. } else {
  678. //
  679. // normalize the path so that we can compare it to other normalized paths
  680. //
  681. WCHAR szNormalized[MAX_PATH];
  682. DWORD dwLen = GetFullPathName(g_ReceivedFilesFolder, MAX_PATH, szNormalized, NULL);
  683. if (dwLen != 0 && dwLen < MAX_PATH) {
  684. StringCbCopy(g_ReceivedFilesFolder,sizeof(g_ReceivedFilesFolder), szNormalized);
  685. } else {
  686. StringCbCopy( g_ReceivedFilesFolder,sizeof(g_ReceivedFilesFolder), g_DesktopFolder );
  687. }
  688. DbgLog1( SEV_INFO, "reg: received files folder %S\n", g_ReceivedFilesFolder);
  689. }
  690. //
  691. // always end path with a backslash '\'
  692. //
  693. if ( bNoTrailingSlash(g_ReceivedFilesFolder) ) {
  694. StringCbCat(g_ReceivedFilesFolder,sizeof(g_ReceivedFilesFolder), szBACKSLASH );
  695. }
  696. size = sizeof(unsigned char);
  697. status = RegQueryValueEx( g_hGlobalKey,
  698. WSZ_REG_SHOW_TRAY,
  699. NULL,
  700. NULL,
  701. &boolVal,
  702. &size
  703. );
  704. if (status || boolVal)
  705. {
  706. DbgLog1( SEV_INFO, "reg: show tray key, status %d\n", status);
  707. g_fShowTrayIcon = TRUE;
  708. }
  709. else
  710. {
  711. g_fShowTrayIcon = FALSE;
  712. }
  713. (*g_SetTrayStatus)( GlobalControl.IrmonContext, g_fShowTrayIcon );
  714. size = sizeof(unsigned char);
  715. status = RegQueryValueEx( g_hGlobalKey,
  716. WSZ_REG_PLAY_SOUND,
  717. NULL,
  718. NULL,
  719. &boolVal,
  720. &size
  721. );
  722. if ((status != ERROR_SUCCESS)) {
  723. DbgLog1( SEV_INFO, "reg: play sound key, status %d\n", status);
  724. boolVal=TRUE;
  725. }
  726. (*GlobalControl.SoundStatusCallback)(
  727. GlobalControl.IrmonContext,
  728. boolVal
  729. );
  730. //
  731. // Process changes specific to IrTran-P:
  732. //
  733. #ifdef IRTRANP_ENABLED
  734. ProcessIrTranPRegistryChanges();
  735. #endif
  736. //
  737. // Look for more changes.
  738. //
  739. status = RegNotifyChangeKeyValue( g_hInfraredKey,
  740. TRUE, // watch child keys
  741. REG_NOTIFY_CHANGE_LAST_SET,
  742. g_RegistryEvent,
  743. TRUE // async
  744. );
  745. if (status)
  746. {
  747. DWORD dwEventStatus = 0;
  748. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  749. if (!dwEventStatus)
  750. {
  751. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_REGISTER_NOTIFY_FAILED, status);
  752. }
  753. }
  754. }
  755. void
  756. RegistryMonitorCallback(
  757. PVOID ignore,
  758. BOOLEAN unknown
  759. )
  760. {
  761. DbgLog(SEV_INFO, "reg callback");
  762. if (g_fShutdown || g_fLogoff)
  763. {
  764. DbgLog(SEV_INFO, "reg callback: terminating");
  765. if (g_fShutdown)
  766. {
  767. CloseHandle( g_RegistryEvent );
  768. }
  769. g_fRegistryWaitComplete = TRUE;
  770. return;
  771. }
  772. ProcessRegistryChange();
  773. if (!RegisterWaitForSingleObject( &g_RegistryWaitHandle,
  774. g_RegistryEvent,
  775. RegistryMonitorCallback,
  776. 0,
  777. INFINITE,
  778. WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE
  779. ))
  780. {
  781. g_RegistryWaitHandle = 0;
  782. DWORD dwEventStatus = 0;
  783. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  784. if (!dwEventStatus)
  785. {
  786. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_REGISTER_NOTIFY_FAILED, GetLastError());
  787. }
  788. }
  789. }
  790. void
  791. UpdateDiscoveredDevices(
  792. const OBEX_DEVICE_LIST *IrDevices
  793. )
  794. {
  795. BOOL fLaunch = FALSE;
  796. error_status_t status;
  797. //
  798. // Update the saved device list.
  799. //
  800. SAVED_IRDA_DEVICE_LIST * list;
  801. g_Mutex->Enter();
  802. if ((g_DeviceList == NULL)
  803. ||
  804. (g_DeviceList->MaxDevices < IrDevices->DeviceCount)) {
  805. list = (SAVED_IRDA_DEVICE_LIST *)
  806. new char [ sizeof(SAVED_IRDA_DEVICE_LIST)
  807. + (IrDevices->DeviceCount ) * sizeof(OBEX_DEVICE)
  808. ];
  809. if (!list) {
  810. g_Mutex->Leave();
  811. return;
  812. }
  813. list->MaxDevices = 1+IrDevices->DeviceCount;
  814. if (g_DeviceList) {
  815. delete g_DeviceList;
  816. }
  817. g_DeviceList = list;
  818. } else {
  819. list = g_DeviceList;
  820. }
  821. //
  822. // Determine how many of the existing devices support our protocol.
  823. //
  824. list->Devices.DeviceCount=0;
  825. unsigned i;
  826. for (i=0; i < IrDevices->DeviceCount; i++) {
  827. list->Devices.DeviceList[list->Devices.DeviceCount]=IrDevices->DeviceList[i];
  828. list->Devices.DeviceCount++;
  829. fLaunch = fLaunch || list->Devices.DeviceList[i].DeviceSpecific.s.Irda.ObexSupport;
  830. }
  831. //
  832. // Inform the UI program of the new device list. Don't create the process
  833. // unless at least one of the devices said it supports OBEX.
  834. //
  835. if (fLaunch) {
  836. g_Mutex->Leave();
  837. LaunchUi( NULL );
  838. } else {
  839. if (g_DeviceList->Devices.DeviceCount > 0) {
  840. _DeviceInRange( rpcBinding, &g_DeviceList->Devices, &status );
  841. g_Mutex->Leave();
  842. DbgLog1(SEV_INFO, "UpdateDiscoveredDevices: DeviceInRange returned %d", status);
  843. } else {
  844. g_Mutex->Leave();
  845. _NoDeviceInRange( rpcBinding, &status );
  846. }
  847. }
  848. }
  849. BOOL
  850. UninitializeIrxfer(
  851. PVOID IrxferContext
  852. )
  853. {
  854. PIRXFER_CONTROL Control=(PIRXFER_CONTROL)IrxferContext;
  855. error_status_t LogoffStatus;
  856. g_fShutdown = TRUE;
  857. DbgLog1(SEV_INFO, "start shutdown: %d", GetTickCount());
  858. _UserLoggedOff(NULL,&LogoffStatus);
  859. if (Control->TransferList != NULL) {
  860. DeleteXferList(Control->TransferList);
  861. }
  862. _ShutdownUi( rpcBinding );
  863. BOOL fSuccess = TRUE;
  864. fSuccess &= Uninit_RegistryCallback();
  865. DbgLog1(SEV_INFO, "after registry: %d", GetTickCount());
  866. #ifdef IRTRANP_ENABLED
  867. StopIrTranP(g_hIrTranPThread);
  868. #endif
  869. #ifdef LOGGING
  870. Log_Close();
  871. #endif
  872. DeleteCriticalSection(&Control->Lock);
  873. return fSuccess;
  874. }
  875. BOOL
  876. Uninit_RegistryCallback()
  877. {
  878. BOOL fSuccess = TRUE;
  879. SetEvent( g_RegistryEvent );
  880. //
  881. // The handle will be deleted when the callback is completed.
  882. //
  883. while (WAIT_TIMEOUT == WaitForSingleObject( g_RegistryEvent, 0 ))
  884. {
  885. Sleep(1000);
  886. }
  887. return fSuccess;
  888. }
  889. void
  890. _SendFiles(
  891. handle_t RpcHandle,
  892. COOKIE ClientCookie,
  893. wchar_t DirectoryName[],
  894. wchar_t FileNameList[],
  895. long ListLength,
  896. unsigned long DeviceId,
  897. OBEX_DEVICE_TYPE DeviceType,
  898. error_status_t * pStatus,
  899. int * pLocation
  900. )
  901. {
  902. FILE_TRANSFER * Transfer;
  903. DbgPrint("IRMON: SendFiles address=%08lx, type=%d\n",DeviceId,DeviceType);
  904. *pStatus = 0;
  905. *pLocation = (int)locStartup;
  906. if ( g_fShutdown )
  907. {
  908. *pStatus = ERROR_SHUTDOWN_IN_PROGRESS;
  909. return;
  910. }
  911. if (DirectoryName && *DirectoryName)
  912. {
  913. *pStatus = ERROR_ACCESS_DENIED;
  914. return;
  915. }
  916. //
  917. // Try NT-compatible connect.
  918. //
  919. Transfer = new FILE_TRANSFER;
  920. if (!Transfer || !Transfer->Xfer_Init( FileNameList, ListLength, dialNt5, DeviceType,TRUE,INVALID_SOCKET ))
  921. {
  922. delete Transfer;
  923. *pStatus = ERROR_NOT_ENOUGH_MEMORY;
  924. return;
  925. }
  926. Transfer->_rpcHandle = RpcHandle;
  927. Transfer->_cookie = ClientCookie;
  928. Transfer->BeginSend( DeviceId, DeviceType, pStatus, (FAILURE_LOCATION*)pLocation );
  929. if (*pStatus == ERROR_INVALID_DATA && *pLocation == locConnect) {
  930. //
  931. // Try Win98-compatible connect.
  932. //
  933. Transfer = new FILE_TRANSFER;
  934. if (!Transfer || !Transfer->Xfer_Init( FileNameList, ListLength, dialWin95,DeviceType,TRUE,INVALID_SOCKET ))
  935. {
  936. delete Transfer;
  937. *pStatus = ERROR_NOT_ENOUGH_MEMORY;
  938. return;
  939. }
  940. Transfer->_rpcHandle = RpcHandle;
  941. Transfer->_cookie = ClientCookie;
  942. Transfer->BeginSend( DeviceId, DeviceType, pStatus, (FAILURE_LOCATION*)pLocation );
  943. }
  944. if (*pStatus != ERROR_SUCCESS) {
  945. DWORD dwEventStatus = 0;
  946. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  947. if (!dwEventStatus) {
  948. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_CONNECT_FAILED, *pStatus);
  949. }
  950. } else {
  951. //
  952. // it worked add it to the list
  953. //
  954. AddTransferToList(GlobalControl.TransferList,Transfer);
  955. }
  956. }
  957. error_status_t
  958. _CancelSend(
  959. /* [in] */ handle_t binding,
  960. /* [in] */ COOKIE cookie
  961. )
  962. {
  963. FILE_TRANSFER * transfer = TransferFromCookie(GlobalControl.TransferList,cookie);
  964. if (!transfer) {
  965. return ERROR_FILE_NOT_FOUND;
  966. }
  967. transfer->Cancel();
  968. return 0;
  969. }
  970. error_status_t
  971. _CancelReceive(
  972. /* [in] */ handle_t binding,
  973. /* [in] */ COOKIE cookie
  974. )
  975. {
  976. FILE_TRANSFER * transfer = TransferFromCookie(GlobalControl.TransferList,cookie);
  977. if (!transfer) {
  978. return ERROR_FILE_NOT_FOUND;
  979. }
  980. transfer->Cancel();
  981. return 0;
  982. }
  983. BOOL
  984. LaunchUi(
  985. wchar_t * cmdline
  986. )
  987. {
  988. //
  989. // Give the UI the current device list.
  990. //
  991. error_status_t status = 0;
  992. g_Mutex->Enter();
  993. if (g_DeviceList)
  994. {
  995. _DeviceInRange( rpcBinding, &g_DeviceList->Devices, &status );
  996. }
  997. DbgLog1(SEV_INFO, "LaunchUi: DeviceInRange returned %d", status);
  998. g_Mutex->Leave();
  999. return TRUE;
  1000. }
  1001. BOOL GetReceivedFilesFolder( LPWSTR szDir, DWORD dwLen )
  1002. {
  1003. if (g_ReceivedFilesFolder[0] == L'\0') {
  1004. ProcessRegistryChange();
  1005. }
  1006. StringCchCopy(szDir, dwLen, g_ReceivedFilesFolder);
  1007. return TRUE;
  1008. }
  1009. BOOL
  1010. ShowSendWindow()
  1011. {
  1012. _PopupUI(NULL);
  1013. return TRUE;
  1014. }
  1015. BOOL ShowPropertiesPage()
  1016. {
  1017. _DisplaySettings(NULL);
  1018. return TRUE;
  1019. }
  1020. extern "C"
  1021. {
  1022. LRESULT
  1023. IrxferHandlePowerMessage(
  1024. HWND hWnd,
  1025. UINT message,
  1026. WPARAM wParam,
  1027. LPARAM lParam
  1028. );
  1029. }
  1030. BOOL IrxferQuerySuspend( LPARAM lParam );
  1031. void IrxferResume();
  1032. LRESULT
  1033. IrxferHandlePowerMessage(
  1034. HWND hwnd,
  1035. UINT message,
  1036. WPARAM wParam,
  1037. LPARAM lParam
  1038. )
  1039. {
  1040. if (message == WM_QUERYENDSESSION)
  1041. {
  1042. DbgLog1(SEV_INFO, "POWER: Query logoff %d", lParam);
  1043. return IrxferQuerySuspend( 1 );
  1044. }
  1045. ASSERT( message == WM_POWERBROADCAST );
  1046. switch (wParam)
  1047. {
  1048. case PBT_APMQUERYSUSPEND:
  1049. {
  1050. DbgLog1(SEV_INFO, "POWER: Query Suspend %d", lParam);
  1051. return ( IrxferQuerySuspend( lParam ) ? TRUE : BROADCAST_QUERY_DENY );
  1052. }
  1053. case PBT_APMQUERYSUSPENDFAILED:
  1054. {
  1055. DbgLog(SEV_INFO, "POWER: Suspend Failed");
  1056. IrxferResume();
  1057. break;
  1058. }
  1059. case PBT_APMRESUMESUSPEND:
  1060. {
  1061. DbgLog(SEV_INFO, "POWER: Resume Suspend");
  1062. IrxferResume();
  1063. break;
  1064. }
  1065. case PBT_APMRESUMECRITICAL:
  1066. {
  1067. DbgLog(SEV_INFO, "POWER: Resume Critical");
  1068. //
  1069. // Do nothing. The Winsock layer will send failures
  1070. // for reads and writes on any sockets active before
  1071. // the shutdown.
  1072. //
  1073. break;
  1074. }
  1075. default:
  1076. DbgLog2(SEV_INFO, "POWER: w=0x%x l=0x%x", wParam, lParam);
  1077. }
  1078. return DefWindowProc(hwnd, message, wParam, lParam);
  1079. }
  1080. BOOL
  1081. IrxferQuerySuspend( LPARAM lParam )
  1082. {
  1083. if (!AreThereActiveTransfers(GlobalControl.TransferList)) {
  1084. DbgLog(SEV_INFO, " no transfers active");
  1085. return TRUE;
  1086. }
  1087. if (lParam & 1)
  1088. {
  1089. //
  1090. // The app is allowed to prompt the user if necessary.
  1091. //
  1092. boolean answer;
  1093. DWORD status = _ShutdownRequested( rpcBinding, &answer );
  1094. DbgLog2(SEV_INFO, " status %d answer %d", status, answer);
  1095. if (status || answer == TRUE)
  1096. {
  1097. g_fShutdown = 1;
  1098. return TRUE;
  1099. }
  1100. else
  1101. {
  1102. return FALSE;
  1103. }
  1104. }
  1105. else
  1106. {
  1107. DbgLog(SEV_INFO, " not allowed to prompt");
  1108. g_fShutdown = 1;
  1109. return TRUE;
  1110. }
  1111. }
  1112. void
  1113. IrxferResume()
  1114. {
  1115. g_fShutdown = FALSE;
  1116. // update device list
  1117. }