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.

1469 lines
39 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. devinfo.c
  5. Abstract:
  6. Property sheet handler for "Device" page
  7. Environment:
  8. Fax driver user interface
  9. Revision History:
  10. 04/09/00 -taoyuan-
  11. Created it.
  12. mm/dd/yy -author-
  13. description
  14. --*/
  15. #include <stdio.h>
  16. #include "faxui.h"
  17. #include "resource.h"
  18. const static COLUMN_HEADER ColumnHeader[] =
  19. {
  20. { IDS_DEVICE_NAME, 190 },
  21. { IDS_SEND, 60 },
  22. { IDS_RECEIVE, 60 }
  23. };
  24. #define ColumnHeaderCount sizeof(ColumnHeader)/sizeof(COLUMN_HEADER)
  25. PFAX_PORT_INFO_EX
  26. GetSelectedPortInfo(
  27. HWND hDlg
  28. )
  29. /*++
  30. Routine Description:
  31. Find port info of the selected device
  32. Arguments:
  33. hDlg - Identifies the property sheet page
  34. Return Value:
  35. FAX_PORT_INFO_EX if successful,
  36. NULL if failed or no device is selected
  37. --*/
  38. {
  39. HWND hwndLv;
  40. INT iItem;
  41. LVITEM lvi = {0};
  42. PFAX_PORT_INFO_EX pFaxPortInfo = NULL;
  43. hwndLv = GetDlgItem(hDlg, IDC_DEVICE_LIST);
  44. if(!hwndLv)
  45. {
  46. Assert(FALSE);
  47. return NULL;
  48. }
  49. iItem = ListView_GetNextItem(hwndLv, -1, LVNI_ALL | LVNI_SELECTED);
  50. if(iItem == -1)
  51. {
  52. return NULL;
  53. }
  54. lvi.iItem = iItem;
  55. lvi.mask = LVIF_PARAM;
  56. ListView_GetItem(hwndLv, &lvi);
  57. pFaxPortInfo = FindPortInfo((DWORD)lvi.lParam);
  58. if(!pFaxPortInfo)
  59. {
  60. Error(("FindPortInfo() failed\n"));
  61. Assert(FALSE);
  62. return NULL;
  63. }
  64. return pFaxPortInfo;
  65. }
  66. BOOL
  67. FillInDeviceInfo(
  68. HWND hDlg
  69. )
  70. /*++
  71. Routine Description:
  72. Fill in device information for currently selected device, if no
  73. device is selected, all text windows are empty
  74. Arguments:
  75. hDlg - Identifies the property sheet page
  76. Return Value:
  77. TRUE if successful, FALSE if failed or no device is selected
  78. --*/
  79. {
  80. PFAX_PORT_INFO_EX pFaxPortInfo; // receive the fax port info
  81. TCHAR szBuffer[MAX_TITLE_LEN];
  82. Verbose(("Entering FillInDeviceInfo...\n"));
  83. pFaxPortInfo = GetSelectedPortInfo(hDlg);
  84. if(!pFaxPortInfo)
  85. {
  86. Error(("GetSelectedPortInfo() failed\n"));
  87. goto error;
  88. }
  89. SetDlgItemText(hDlg, IDC_DEVICE_INFO_GRP, pFaxPortInfo->lpctstrDeviceName);
  90. SetDlgItemText(hDlg, IDC_TSID, pFaxPortInfo->bSend ? pFaxPortInfo->lptstrTsid : TEXT(""));
  91. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_TSID), pFaxPortInfo->bSend);
  92. if(pFaxPortInfo->ReceiveMode != FAX_DEVICE_RECEIVE_MODE_OFF)
  93. {
  94. SetDlgItemText(hDlg, IDC_CSID, pFaxPortInfo->lptstrCsid);
  95. if(FAX_DEVICE_RECEIVE_MODE_AUTO == pFaxPortInfo->ReceiveMode)
  96. {
  97. DWORD dwRes;
  98. BOOL bVirtual;
  99. if(!Connect(hDlg, TRUE))
  100. {
  101. return FALSE;
  102. }
  103. dwRes = IsDeviceVirtual (g_hFaxSvcHandle, pFaxPortInfo->dwDeviceID, &bVirtual);
  104. if (ERROR_SUCCESS != dwRes)
  105. {
  106. return FALSE;
  107. }
  108. SetDlgItemInt (hDlg, IDC_RINGS, bVirtual? 1 : pFaxPortInfo->dwRings, FALSE);
  109. }
  110. else
  111. {
  112. SetDlgItemText(hDlg, IDC_RINGS, TEXT(""));
  113. }
  114. }
  115. else // receive off
  116. {
  117. SetDlgItemText(hDlg, IDC_RINGS, TEXT(""));
  118. SetDlgItemText(hDlg, IDC_CSID, TEXT(""));
  119. }
  120. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CSID), (pFaxPortInfo->ReceiveMode != FAX_DEVICE_RECEIVE_MODE_OFF));
  121. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_RINGS), (pFaxPortInfo->ReceiveMode == FAX_DEVICE_RECEIVE_MODE_AUTO));
  122. return TRUE;
  123. error:
  124. //
  125. // make all info fields empty
  126. //
  127. if(!LoadString(g_hResource, IDS_NO_DEVICE_SELECTED, szBuffer, MAX_TITLE_LEN))
  128. {
  129. Error(( "LoadString failed, string ID is %d.\n", IDS_NO_DEVICE_SELECTED ));
  130. lstrcpy(szBuffer, TEXT(""));
  131. }
  132. SetDlgItemText(hDlg, IDC_DEVICE_INFO_GRP, szBuffer);
  133. SetDlgItemText(hDlg, IDC_TSID, TEXT(""));
  134. SetDlgItemText(hDlg, IDC_CSID, TEXT(""));
  135. SetDlgItemText(hDlg, IDC_RINGS, TEXT(""));
  136. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_TSID), FALSE);
  137. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CSID), FALSE);
  138. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_RINGS), FALSE);
  139. return FALSE;
  140. }
  141. BOOL
  142. UpdateDeviceInfo(
  143. HWND hDlg
  144. )
  145. /*++
  146. Routine Description:
  147. Display the send and receive information in the list view
  148. Arguments:
  149. hDlg - Identifies the property sheet page
  150. Return Value:
  151. TRUE if successful, FALSE if failed
  152. --*/
  153. {
  154. HWND hwndLv;
  155. INT iItem;
  156. INT iDeviceCount;
  157. LVITEM lvi = {0};
  158. PFAX_PORT_INFO_EX pFaxPortInfo;
  159. DWORD dwResId;
  160. Verbose(("Entering UpdateDeviceInfo...\n"));
  161. hwndLv = GetDlgItem(hDlg, IDC_DEVICE_LIST);
  162. iDeviceCount = ListView_GetItemCount(hwndLv);
  163. for(iItem = 0; iItem < iDeviceCount; ++iItem)
  164. {
  165. lvi.iItem = iItem;
  166. lvi.mask = LVIF_PARAM;
  167. ListView_GetItem(hwndLv, &lvi);
  168. pFaxPortInfo = FindPortInfo((DWORD)lvi.lParam);
  169. if(!pFaxPortInfo)
  170. {
  171. Error(("FindPortInfo() failed\n"));
  172. Assert(FALSE);
  173. continue;
  174. }
  175. //
  176. // Send
  177. //
  178. dwResId = pFaxPortInfo->bSend ? IDS_DEVICE_ENABLED : IDS_DEVICE_DISABLED;
  179. ListView_SetItemText(hwndLv, iItem, 1, GetString(dwResId));
  180. //
  181. // Receive
  182. //
  183. switch (pFaxPortInfo->ReceiveMode)
  184. {
  185. case FAX_DEVICE_RECEIVE_MODE_OFF:
  186. dwResId = IDS_DEVICE_DISABLED;
  187. break;
  188. case FAX_DEVICE_RECEIVE_MODE_AUTO:
  189. dwResId = IDS_DEVICE_AUTO_ANSWER;
  190. break;
  191. case FAX_DEVICE_RECEIVE_MODE_MANUAL:
  192. dwResId = IDS_DEVICE_MANUAL_ANSWER;
  193. break;
  194. default:
  195. Assert (FALSE);
  196. dwResId = IDS_DEVICE_DISABLED;
  197. break;
  198. }
  199. ListView_SetItemText(hwndLv, iItem, 2, GetString(dwResId));
  200. }
  201. return TRUE;
  202. }
  203. BOOL
  204. DoInitDeviceList(
  205. HWND hDlg // window handle of the device info page
  206. )
  207. /*++
  208. Routine Description:
  209. Initialize the list view and fill in device info of the first device in the list
  210. Arguments:
  211. hDlg - Identifies the property sheet page
  212. Return Value:
  213. TRUE if successful, FALSE if failed
  214. --*/
  215. {
  216. HWND hwndLv; // list view window
  217. LVITEM lv = {0};
  218. DWORD dwDeviceIndex;
  219. DWORD dwResId;
  220. PFAX_OUTBOUND_ROUTING_GROUP pFaxRoutingGroup = NULL;
  221. DWORD dwGroups; // group number
  222. DWORD dwGroupIndex;
  223. DWORD dwDeviceCount; // the return device number from FaxEnumOutboundGroups
  224. LPDWORD lpdwDevices = NULL; // temporary pointer to save group device info
  225. PFAX_PORT_INFO_EX pFaxPortInfo;
  226. Verbose(("Entering DoInitDeviceList...\n"));
  227. hwndLv = GetDlgItem(hDlg, IDC_DEVICE_LIST);
  228. if (!IsDesktopSKU())
  229. {
  230. if(!Connect(hDlg, TRUE))
  231. {
  232. return FALSE;
  233. }
  234. //
  235. // FaxEnumPortsEx doesn't provide device list under send device order
  236. // so we need to use FaxEnumOutboundGroups to do that.
  237. //
  238. if(!FaxEnumOutboundGroups(g_hFaxSvcHandle, &pFaxRoutingGroup, &dwGroups))
  239. {
  240. dwResId = GetLastError();
  241. Error(( "FaxEnumOutboundGroups() failed with %d.\n", dwResId));
  242. DisplayErrorMessage(hDlg, 0, dwResId);
  243. DisConnect();
  244. return FALSE;
  245. }
  246. DisConnect();
  247. for(dwGroupIndex = 0; dwGroupIndex < dwGroups; dwGroupIndex++)
  248. {
  249. if(!lstrcmp(pFaxRoutingGroup[dwGroupIndex].lpctstrGroupName, ROUTING_GROUP_ALL_DEVICES))
  250. {
  251. dwDeviceCount = pFaxRoutingGroup[dwGroupIndex].dwNumDevices;
  252. lpdwDevices = pFaxRoutingGroup[dwGroupIndex].lpdwDevices;
  253. Verbose(( "Total device number is %d.\n", dwDeviceCount ));
  254. Verbose(( "Group status is %d.\n", pFaxRoutingGroup[dwGroupIndex].Status ));
  255. break;
  256. }
  257. }
  258. // the device number from FaxEnumPortsEx and in the <All Devices> group should be the same.
  259. Assert(g_dwPortsNum == dwDeviceCount);
  260. }
  261. else
  262. {
  263. //
  264. // In desktop SKU
  265. // Fax outbound routing groups do not exist.
  266. // Fake the <All Devices> group now.
  267. //
  268. lpdwDevices = MemAlloc (sizeof (DWORD) * g_dwPortsNum);
  269. if (!lpdwDevices)
  270. {
  271. dwResId = GetLastError();
  272. Error(( "MemAlloc() failed with %d.\n", dwResId));
  273. DisplayErrorMessage(hDlg, 0, dwResId);
  274. DisConnect();
  275. return FALSE;
  276. }
  277. dwDeviceCount = g_dwPortsNum;
  278. for (dwDeviceIndex = 0; dwDeviceIndex < g_dwPortsNum; dwDeviceIndex++)
  279. {
  280. lpdwDevices[dwDeviceIndex] = g_pFaxPortInfo[dwDeviceIndex].dwDeviceID;
  281. }
  282. }
  283. lv.mask = LVIF_TEXT | LVIF_PARAM;
  284. for(dwDeviceIndex = 0; dwDeviceIndex < dwDeviceCount; dwDeviceIndex++)
  285. {
  286. pFaxPortInfo = FindPortInfo(lpdwDevices[dwDeviceIndex]);
  287. if(!pFaxPortInfo)
  288. {
  289. Error(("FindPortInfo() failed\n"));
  290. Assert(FALSE);
  291. continue;
  292. }
  293. lv.iItem = dwDeviceIndex;
  294. lv.pszText = (LPTSTR)pFaxPortInfo->lpctstrDeviceName;
  295. lv.lParam = (LPARAM)pFaxPortInfo->dwDeviceID;
  296. ListView_InsertItem(hwndLv, &lv);
  297. //
  298. // Send column
  299. //
  300. dwResId = pFaxPortInfo->bSend ? IDS_DEVICE_ENABLED : IDS_DEVICE_DISABLED;
  301. ListView_SetItemText(hwndLv, dwDeviceIndex, 1, GetString(dwResId));
  302. //
  303. // Receive column
  304. //
  305. switch (pFaxPortInfo->ReceiveMode)
  306. {
  307. case FAX_DEVICE_RECEIVE_MODE_OFF:
  308. dwResId = IDS_DEVICE_DISABLED;
  309. break;
  310. case FAX_DEVICE_RECEIVE_MODE_AUTO:
  311. dwResId = IDS_DEVICE_AUTO_ANSWER;
  312. break;
  313. case FAX_DEVICE_RECEIVE_MODE_MANUAL:
  314. dwResId = IDS_DEVICE_MANUAL_ANSWER;
  315. break;
  316. default:
  317. Assert (FALSE);
  318. dwResId = IDS_DEVICE_DISABLED;
  319. break;
  320. }
  321. ListView_SetItemText(hwndLv, dwDeviceIndex, 2, GetString(dwResId));
  322. }
  323. if (!IsDesktopSKU())
  324. {
  325. //
  326. // Server SKU
  327. //
  328. FaxFreeBuffer(pFaxRoutingGroup);
  329. pFaxRoutingGroup = NULL;
  330. }
  331. else
  332. {
  333. //
  334. // Desktop SKU
  335. //
  336. MemFree (lpdwDevices);
  337. lpdwDevices = NULL;
  338. //
  339. // Hide the label that talks about device priorities
  340. //
  341. ShowWindow(GetDlgItem(hDlg, IDC_STATIC_DEVICE), SW_HIDE);
  342. //
  343. // Hide the priority arrows
  344. //
  345. ShowWindow(GetDlgItem(hDlg, IDC_PRI_UP), SW_HIDE);
  346. ShowWindow(GetDlgItem(hDlg, IDC_PRI_DOWN), SW_HIDE);
  347. }
  348. //
  349. // Select the first device and show its information
  350. //
  351. if(dwDeviceCount >= 1)
  352. {
  353. ListView_SetItemState(hwndLv, 0, LVIS_SELECTED, LVIS_SELECTED);
  354. ValidateControl(hDlg, 0);
  355. }
  356. else
  357. {
  358. ValidateControl(hDlg, -1);
  359. }
  360. if (dwDeviceCount < 2)
  361. {
  362. //
  363. // Less than 2 devices - hide the label which talks about priorities
  364. //
  365. ShowWindow(GetDlgItem(hDlg, IDC_STATIC_DEVICE), SW_HIDE);
  366. }
  367. FillInDeviceInfo(hDlg);
  368. return TRUE;
  369. }
  370. BOOL
  371. ValidateControl(
  372. HWND hDlg,
  373. INT iItem
  374. )
  375. /*++
  376. Routine Description:
  377. Validate the up and down button in the property page
  378. Arguments:
  379. hDlg - Handle to the property sheet page
  380. iItem - index of the item being selected
  381. Return Value:
  382. TRUE -- if no error
  383. FALSE -- if error
  384. --*/
  385. {
  386. INT iDeviceCount;
  387. HWND hwndLv;
  388. hwndLv = GetDlgItem(hDlg, IDC_DEVICE_LIST);
  389. iDeviceCount = ListView_GetItemCount(hwndLv);
  390. if(!g_bUserCanChangeSettings)
  391. {
  392. PageEnable(hDlg, FALSE);
  393. EnableWindow(hwndLv, TRUE);
  394. }
  395. EnableWindow(GetDlgItem(hDlg, IDC_DEVICE_PROP), (iItem != -1));
  396. //
  397. // if there is only one device or we don't click on any item
  398. // up and down buttons are disabled
  399. //
  400. if(iDeviceCount < 2 || iItem == -1)
  401. {
  402. EnableWindow(GetDlgItem(hDlg, IDC_PRI_UP), FALSE);
  403. EnableWindow(GetDlgItem(hDlg, IDC_PRI_DOWN), FALSE);
  404. return TRUE;
  405. }
  406. if(g_bUserCanChangeSettings)
  407. {
  408. EnableWindow(GetDlgItem(hDlg, IDC_PRI_UP), iItem > 0); // not the top one
  409. EnableWindow(GetDlgItem(hDlg, IDC_PRI_DOWN), iItem < iDeviceCount - 1); // not the last one
  410. }
  411. if (!IsWindowEnabled (GetFocus()))
  412. {
  413. //
  414. // The currently selected control turned disabled - select the list control
  415. //
  416. SetFocus (GetDlgItem (hDlg, IDC_DEVICE_LIST));
  417. }
  418. return TRUE;
  419. }
  420. BOOL
  421. ChangePriority(
  422. HWND hDlg,
  423. BOOL bMoveUp
  424. )
  425. /*++
  426. Routine Description:
  427. Validate the up and down button in the fax property page
  428. Arguments:
  429. hDlg - Handle to the fax property sheet page
  430. bMoveUp -- TRUE for moving up, FALSE for moving down
  431. Return Value:
  432. TRUE -- if no error
  433. FALSE -- if error
  434. --*/
  435. {
  436. INT iItem;
  437. BOOL rslt;
  438. LVITEM lv = {0};
  439. TCHAR pszText[MAX_DEVICE_NAME];
  440. TCHAR szEnableSend[64]; // for enable/disable send text
  441. TCHAR szEnableReceive[64]; // for enable/disable receive text
  442. INT iDeviceCount;
  443. HWND hwndLv;
  444. hwndLv = GetDlgItem(hDlg, IDC_DEVICE_LIST);
  445. iDeviceCount = ListView_GetItemCount(hwndLv);
  446. //
  447. // find the current selected Item
  448. //
  449. iItem = ListView_GetNextItem(hwndLv, -1, LVNI_ALL | LVNI_SELECTED);
  450. if(iItem == -1)
  451. {
  452. Error(("No device is selected. Can't change priority.\n"));
  453. return FALSE;
  454. }
  455. //
  456. // get selected item information and then remove it
  457. //
  458. lv.iItem = iItem;
  459. lv.iSubItem = 0;
  460. lv.mask = LVIF_TEXT | LVIF_PARAM;
  461. lv.pszText = pszText;
  462. lv.cchTextMax = ARRAYSIZE(pszText);
  463. ListView_GetItem(hwndLv, &lv);
  464. ListView_GetItemText(hwndLv, iItem, 1, szEnableSend, ARRAYSIZE(szEnableSend)); // for send
  465. ListView_GetItemText(hwndLv, iItem, 2, szEnableReceive, ARRAYSIZE(szEnableReceive)); // for receive
  466. rslt = ListView_DeleteItem(hwndLv, iItem);
  467. //
  468. // recalculate the item index;
  469. //
  470. if(bMoveUp)
  471. {
  472. lv.iItem--;
  473. }
  474. else
  475. {
  476. lv.iItem++;
  477. }
  478. //
  479. // reinsert the item and validate button state
  480. //
  481. iItem = ListView_InsertItem(hwndLv, &lv);
  482. ListView_SetItemText(hwndLv, iItem, 1, szEnableSend);
  483. ListView_SetItemText(hwndLv, iItem, 2, szEnableReceive);
  484. ListView_SetItemState(hwndLv, iItem, LVIS_SELECTED, LVIS_SELECTED);
  485. ValidateControl(hDlg, iItem);
  486. return TRUE;
  487. }
  488. BOOL
  489. DoSaveDeviceList(
  490. HWND hDlg // window handle of the device info page
  491. )
  492. /*++
  493. Routine Description:
  494. Save the list view info to the system
  495. Arguments:
  496. hDlg - Identifies the property sheet page
  497. Return Value:
  498. TRUE if successful, FALSE if failed
  499. --*/
  500. {
  501. PFAX_PORT_INFO_EX pFaxPortInfo = NULL; // receive port information
  502. INT iItem;
  503. INT iDeviceCount;
  504. HWND hwndLv; // list view window
  505. LVITEM lv;
  506. DWORD dwDeviceId;
  507. DWORD dwRes = 0;
  508. Verbose(("Entering DoSaveDeviceList...\n"));
  509. //
  510. // Get the list view window handle
  511. //
  512. hwndLv = GetDlgItem(hDlg, IDC_DEVICE_LIST);
  513. if(!Connect(hDlg, TRUE))
  514. {
  515. return FALSE;
  516. }
  517. //
  518. // Get total number of fax devices
  519. //
  520. iDeviceCount = ListView_GetItemCount(hwndLv);
  521. //
  522. // 1st iteration - disabled receive and send devices only
  523. //
  524. for(iItem = 0; iItem < iDeviceCount; ++iItem)
  525. {
  526. // Get device ID first, then save the changes.
  527. ZeroMemory(&lv, sizeof(lv));
  528. lv.iItem = iItem;
  529. lv.mask = LVIF_PARAM;
  530. ListView_GetItem(hwndLv, &lv);
  531. dwDeviceId = (DWORD)lv.lParam;
  532. pFaxPortInfo = FindPortInfo(dwDeviceId);
  533. if(!pFaxPortInfo)
  534. {
  535. Error(("FindPortInfo() failed\n"));
  536. Assert(FALSE);
  537. continue;
  538. }
  539. if (pFaxPortInfo->bSend || (FAX_DEVICE_RECEIVE_MODE_OFF != pFaxPortInfo->ReceiveMode))
  540. {
  541. //
  542. // Fax device is active - skip it for now
  543. //
  544. continue;
  545. }
  546. if(!FaxSetPortEx(g_hFaxSvcHandle, dwDeviceId, pFaxPortInfo))
  547. {
  548. dwRes = GetLastError();
  549. Error(("FaxSetPortEx() failed with %d.\n", dwRes));
  550. break;
  551. }
  552. }
  553. //
  554. // 2nd iteration - enabled receive or send devices only
  555. //
  556. for(iItem = 0; iItem < iDeviceCount; ++iItem)
  557. {
  558. // Get device ID first, then save the changes.
  559. ZeroMemory(&lv, sizeof(lv));
  560. lv.iItem = iItem;
  561. lv.mask = LVIF_PARAM;
  562. ListView_GetItem(hwndLv, &lv);
  563. dwDeviceId = (DWORD)lv.lParam;
  564. pFaxPortInfo = FindPortInfo(dwDeviceId);
  565. if(!pFaxPortInfo)
  566. {
  567. Error(("FindPortInfo() failed\n"));
  568. Assert(FALSE);
  569. continue;
  570. }
  571. if (!pFaxPortInfo->bSend && (FAX_DEVICE_RECEIVE_MODE_OFF == pFaxPortInfo->ReceiveMode))
  572. {
  573. //
  574. // Fax device is inactive - skip it.
  575. // It was already set in the 1st iteration.
  576. //
  577. continue;
  578. }
  579. if(!FaxSetPortEx(g_hFaxSvcHandle, dwDeviceId, pFaxPortInfo))
  580. {
  581. dwRes = GetLastError();
  582. Error(("FaxSetPortEx() failed with %d.\n", dwRes));
  583. break;
  584. }
  585. }
  586. if (!IsDesktopSKU())
  587. {
  588. //
  589. // 3rd iteration.
  590. // Save send priority, FAX_PORT_INFO_EX doesn't have Priority field, so use FaxSetDeviceOrderInGroup
  591. // Send priority is only relevant to server SKUs.
  592. //
  593. for(iItem = 0; iItem < iDeviceCount; ++iItem)
  594. {
  595. // Get device ID first, then save the changes.
  596. ZeroMemory(&lv, sizeof(lv));
  597. lv.iItem = iItem;
  598. lv.mask = LVIF_PARAM;
  599. ListView_GetItem(hwndLv, &lv);
  600. dwDeviceId = (DWORD)lv.lParam;
  601. pFaxPortInfo = FindPortInfo(dwDeviceId);
  602. if(!pFaxPortInfo)
  603. {
  604. Error(("FindPortInfo() failed\n"));
  605. Assert(FALSE);
  606. continue;
  607. }
  608. if(!FaxSetDeviceOrderInGroup(g_hFaxSvcHandle, ROUTING_GROUP_ALL_DEVICES, dwDeviceId, iItem + 1))
  609. {
  610. dwRes = GetLastError();
  611. Error(("FaxSetDeviceOrderInGroup() failed with %d.\n", dwRes));
  612. break;
  613. }
  614. }
  615. }
  616. DisConnect();
  617. switch (dwRes)
  618. {
  619. case ERROR_SUCCESS:
  620. //
  621. // Don't do nothing
  622. //
  623. break;
  624. case FAXUI_ERROR_DEVICE_LIMIT:
  625. case FAX_ERR_DEVICE_NUM_LIMIT_EXCEEDED:
  626. //
  627. // Some additional parameters are needed
  628. //
  629. DisplayErrorMessage(hDlg, 0, dwRes, GetDeviceLimit());
  630. break;
  631. default:
  632. DisplayErrorMessage(hDlg, 0, dwRes);
  633. break;
  634. }
  635. return (dwRes == 0);
  636. } // DoSaveDeviceList
  637. void
  638. DisplayDeviceProperty(
  639. HWND hDlg
  640. )
  641. /*++
  642. Routine Description:
  643. Open a property sheet for a specific device
  644. Arguments:
  645. hDlg - Identifies the property sheet page
  646. Return Value:
  647. none
  648. --*/
  649. {
  650. HWND hwndLv;
  651. INT iDeviceCount;
  652. INT iItem;
  653. TCHAR szDeviceName[MAX_PATH] = {0};
  654. PROPSHEETHEADER psh = {0};
  655. PROPSHEETPAGE psp[3] = {0}; // property sheet pages info for device info
  656. HPROPSHEETPAGE hPropSheetPages[3];
  657. LVITEM lvi = {0};
  658. DWORD dw;
  659. PFAX_PORT_INFO_EX pFaxPortInfo = NULL;
  660. DWORD dwPortsNum;
  661. Verbose(("Entering DisplayDeviceProperty...\n"));
  662. hwndLv = GetDlgItem(hDlg, IDC_DEVICE_LIST);
  663. iDeviceCount = ListView_GetItemCount(hwndLv);
  664. //
  665. // find the current selected Item
  666. //
  667. iItem = ListView_GetNextItem(hwndLv, -1, LVNI_ALL | LVNI_SELECTED);
  668. if(iItem == -1)
  669. {
  670. Verbose(("No device is selected. Can't display properties.\n"));
  671. return;
  672. }
  673. lvi.iItem = iItem;
  674. lvi.mask = LVIF_PARAM | LVIF_TEXT;
  675. lvi.pszText = szDeviceName;
  676. lvi.cchTextMax = MAX_PATH;
  677. ListView_GetItem(hwndLv, &lvi);
  678. //
  679. // Get an array of property sheet page handles
  680. //
  681. psp[0].dwSize = sizeof(PROPSHEETPAGE);
  682. psp[0].hInstance = g_hResource;
  683. psp[0].pszTemplate = MAKEINTRESOURCE(IDD_SEND_PROP);
  684. psp[0].pfnDlgProc = DevSendDlgProc;
  685. psp[0].lParam = lvi.lParam;
  686. psp[1].dwSize = sizeof(PROPSHEETPAGE);
  687. psp[1].hInstance = g_hResource;
  688. psp[1].pszTemplate = MAKEINTRESOURCE(IDD_RECEIVE_PROP);
  689. psp[1].pfnDlgProc = DevRecvDlgProc;
  690. psp[1].lParam = lvi.lParam;
  691. psp[2].dwSize = sizeof(PROPSHEETPAGE);
  692. psp[2].hInstance = g_hResource;
  693. psp[2].pszTemplate = MAKEINTRESOURCE(IDD_CLEANUP_PROP);
  694. psp[2].pfnDlgProc = DevCleanupDlgProc;
  695. psp[2].lParam = lvi.lParam;
  696. hPropSheetPages[0] = CreatePropertySheetPage( &psp[0] );
  697. hPropSheetPages[1] = CreatePropertySheetPage( &psp[1] );
  698. if (IsDesktopSKU())
  699. {
  700. hPropSheetPages[2] = CreatePropertySheetPage( &psp[2] );
  701. }
  702. Assert(hPropSheetPages[0]);
  703. Assert(hPropSheetPages[1]);
  704. if (IsDesktopSKU())
  705. {
  706. Assert(hPropSheetPages[2]);
  707. }
  708. //
  709. // Fill out PROPSHEETHEADER structure
  710. //
  711. psh.dwSize = sizeof(PROPSHEETHEADER);
  712. psh.dwFlags = PSH_USEICONID;
  713. psh.hwndParent = hDlg;
  714. psh.hInstance = g_hResource;
  715. psh.pszIcon = MAKEINTRESOURCE(IDI_DEVICE_INFO);
  716. psh.pszCaption = szDeviceName;
  717. psh.nPages = IsDesktopSKU() ? 3 : 2;
  718. psh.nStartPage = 0;
  719. psh.phpage = hPropSheetPages;
  720. //
  721. // Display the property sheet
  722. //
  723. if(PropertySheet(&psh) == -1)
  724. {
  725. Error(( "PropertySheet() failed with %d\n", GetLastError() ));
  726. return;
  727. }
  728. if(!g_bPortInfoChanged)
  729. {
  730. return;
  731. }
  732. //
  733. // merge the changes into the g_pFaxPortInfo
  734. //
  735. if(Connect(NULL, FALSE))
  736. {
  737. if(!FaxEnumPortsEx(g_hFaxSvcHandle, &pFaxPortInfo, &dwPortsNum))
  738. {
  739. Error(( "FaxEnumPortsEx failed with %d\n", GetLastError()));
  740. }
  741. DisConnect();
  742. }
  743. if(!pFaxPortInfo || !dwPortsNum)
  744. {
  745. FaxFreeBuffer(pFaxPortInfo);
  746. return;
  747. }
  748. for(dw = 0; dw < dwPortsNum; ++dw)
  749. {
  750. PFAX_PORT_INFO_EX pPortInfo;
  751. if(pFaxPortInfo[dw].dwDeviceID == (DWORD)lvi.lParam)
  752. {
  753. //
  754. // Selected device already updated
  755. //
  756. continue;
  757. }
  758. pPortInfo = FindPortInfo(pFaxPortInfo[dw].dwDeviceID);
  759. if(!pPortInfo)
  760. {
  761. continue;
  762. }
  763. pFaxPortInfo[dw].bSend = pPortInfo->bSend;
  764. pFaxPortInfo[dw].ReceiveMode = pPortInfo->ReceiveMode;
  765. }
  766. FaxFreeBuffer(g_pFaxPortInfo);
  767. g_pFaxPortInfo = pFaxPortInfo;
  768. g_dwPortsNum = dwPortsNum;
  769. NotifyDeviceUsageChanged ();
  770. g_bPortInfoChanged = FALSE;
  771. }
  772. BOOL
  773. ShowContextMenu(
  774. HWND hDlg
  775. )
  776. /*++
  777. Routine Description:
  778. Display the context menu in the device list
  779. Arguments:
  780. hDlg - Identifies the property sheet page
  781. Return Value:
  782. TRUE if successful, FALSE if failed
  783. --*/
  784. {
  785. DWORD dwMessagePos;
  786. DWORD dwRes;
  787. BOOL bVirtual;
  788. PFAX_PORT_INFO_EX pFaxPortInfo;
  789. HMENU hMenu;
  790. HMENU hSubMenu;
  791. HMENU hSubSubMenu;
  792. Verbose(("Entering ShowContextMenu...\n"));
  793. pFaxPortInfo = GetSelectedPortInfo(hDlg);
  794. if(!pFaxPortInfo)
  795. {
  796. Error(("GetSelectedPortInfo() failed\n"));
  797. return FALSE;
  798. }
  799. //
  800. // Load context-sensitive menu
  801. //
  802. hMenu = LoadMenu(g_hResource, MAKEINTRESOURCE(IDR_SEND_RECEIVE));
  803. if(!hMenu)
  804. {
  805. Assert(FALSE);
  806. return FALSE;
  807. }
  808. hSubMenu = GetSubMenu(hMenu, 0);
  809. if(!hSubMenu)
  810. {
  811. Assert(FALSE);
  812. DestroyMenu (hMenu);
  813. return FALSE;
  814. }
  815. //
  816. // Send
  817. //
  818. hSubSubMenu = GetSubMenu(hSubMenu, 0);
  819. if(!hSubSubMenu)
  820. {
  821. Assert(FALSE);
  822. DestroyMenu (hMenu);
  823. return FALSE;
  824. }
  825. CheckMenuItem(hSubSubMenu,
  826. IDM_SEND_ENABLE,
  827. pFaxPortInfo->bSend ? MF_BYCOMMAND | MF_CHECKED : MF_BYCOMMAND | MF_UNCHECKED);
  828. CheckMenuItem(hSubSubMenu,
  829. IDM_SEND_DISABLE,
  830. !pFaxPortInfo->bSend ? MF_BYCOMMAND | MF_CHECKED : MF_BYCOMMAND | MF_UNCHECKED);
  831. //
  832. // Receive
  833. //
  834. hSubSubMenu = GetSubMenu(hSubMenu, 1);
  835. if(!hMenu)
  836. {
  837. Assert(FALSE);
  838. DestroyMenu (hMenu);
  839. return FALSE;
  840. }
  841. CheckMenuItem(hSubSubMenu,
  842. IDM_RECEIVE_AUTO,
  843. (FAX_DEVICE_RECEIVE_MODE_AUTO == pFaxPortInfo->ReceiveMode) ?
  844. MF_BYCOMMAND | MF_CHECKED :
  845. MF_BYCOMMAND | MF_UNCHECKED);
  846. CheckMenuItem(hSubSubMenu,
  847. IDM_RECEIVE_MANUAL,
  848. (FAX_DEVICE_RECEIVE_MODE_MANUAL == pFaxPortInfo->ReceiveMode) ?
  849. MF_BYCOMMAND | MF_CHECKED :
  850. MF_BYCOMMAND | MF_UNCHECKED);
  851. CheckMenuItem(hSubSubMenu,
  852. IDM_RECEIVE_DISABLE,
  853. (FAX_DEVICE_RECEIVE_MODE_OFF == pFaxPortInfo->ReceiveMode) ?
  854. MF_BYCOMMAND | MF_CHECKED :
  855. MF_BYCOMMAND | MF_UNCHECKED);
  856. if(!Connect(hDlg, TRUE))
  857. {
  858. DestroyMenu (hMenu);
  859. return FALSE;
  860. }
  861. dwRes = IsDeviceVirtual (g_hFaxSvcHandle, pFaxPortInfo->dwDeviceID, &bVirtual);
  862. if (ERROR_SUCCESS != dwRes)
  863. {
  864. DestroyMenu (hMenu);
  865. return FALSE;
  866. }
  867. if (bVirtual)
  868. {
  869. //
  870. // If the device is virtual, can't set to to manual answer mode
  871. //
  872. Assert (FAX_DEVICE_RECEIVE_MODE_MANUAL != pFaxPortInfo->ReceiveMode);
  873. EnableMenuItem (hSubSubMenu, IDM_RECEIVE_MANUAL, MF_BYCOMMAND | MF_GRAYED);
  874. }
  875. SetMenuDefaultItem(hSubMenu, IDM_PROPERTY, FALSE);
  876. // Get the cursor position
  877. dwMessagePos = GetMessagePos();
  878. // Display the context menu
  879. TrackPopupMenu(hSubMenu,
  880. TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  881. LOWORD(dwMessagePos),
  882. HIWORD(dwMessagePos), 0, hDlg, NULL);
  883. DestroyMenu (hMenu);
  884. DisConnect();
  885. return TRUE;
  886. } // ShowContextMenu
  887. INT_PTR
  888. CALLBACK
  889. DeviceInfoDlgProc(
  890. HWND hDlg,
  891. UINT uMsg,
  892. WPARAM wParam,
  893. LPARAM lParam
  894. )
  895. /*++
  896. Routine Description:
  897. Procedure for handling the device info tab
  898. Arguments:
  899. hDlg - Identifies the property sheet page
  900. uMsg - Specifies the message
  901. wParam - Specifies additional message-specific information
  902. lParam - Specifies additional message-specific information
  903. Return Value:
  904. Depends on the value of message parameter
  905. --*/
  906. {
  907. switch (uMsg)
  908. {
  909. case WM_INITDIALOG :
  910. {
  911. HICON hIconUp, hIconDown;
  912. LV_COLUMN lvc = {0};
  913. DWORD dwIndex;
  914. TCHAR szBuffer[RESOURCE_STRING_LEN];
  915. HWND hwndLv;
  916. //
  917. // Load icons.
  918. //
  919. hIconUp = LoadIcon(g_hResource, MAKEINTRESOURCE(IDI_UP));
  920. hIconDown = LoadIcon(g_hResource, MAKEINTRESOURCE(IDI_DOWN));
  921. // icon handles for up and down arrows.
  922. SendDlgItemMessage(hDlg, IDC_PRI_UP, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hIconUp);
  923. SendDlgItemMessage(hDlg, IDC_PRI_DOWN, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hIconDown);
  924. SendDlgItemMessage(hDlg, IDC_TSID, EM_SETLIMITTEXT, TSID_LIMIT, 0);
  925. SendDlgItemMessage(hDlg, IDC_CSID, EM_SETLIMITTEXT, CSID_LIMIT, 0);
  926. //
  927. // Set list view style and columns
  928. //
  929. hwndLv = GetDlgItem(hDlg, IDC_DEVICE_LIST);
  930. ListView_SetExtendedListViewStyle(hwndLv, LVS_EX_FULLROWSELECT);
  931. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  932. lvc.fmt = LVCFMT_LEFT;
  933. lvc.pszText = szBuffer;
  934. for(dwIndex = 0; dwIndex < ColumnHeaderCount; dwIndex++)
  935. {
  936. if(!LoadString(g_hResource, ColumnHeader[dwIndex].uResourceId ,szBuffer, RESOURCE_STRING_LEN))
  937. {
  938. Error(( "LoadString failed, string ID is %d.\n", ColumnHeader[dwIndex].uResourceId ));
  939. lstrcpy(szBuffer, TEXT(""));
  940. }
  941. lvc.cx = ColumnHeader[dwIndex].ColumnWidth;
  942. lvc.iSubItem = (INT)dwIndex;
  943. ListView_InsertColumn( hwndLv, dwIndex, &lvc );
  944. }
  945. DoInitDeviceList(hDlg);
  946. return TRUE;
  947. break;
  948. }
  949. case WM_COMMAND:
  950. switch(LOWORD(wParam))
  951. {
  952. case IDC_PRI_UP:
  953. case IDC_PRI_DOWN:
  954. ChangePriority(hDlg, (LOWORD(wParam) == IDC_PRI_UP) ? TRUE : FALSE);
  955. Notify_Change(hDlg);
  956. break;
  957. case IDM_PROPERTY:
  958. case IDC_DEVICE_PROP:
  959. {
  960. HWND hwndLv; // handle of the list view window
  961. INT iItem = -1; // default value for non client area
  962. //
  963. // Get current selected item
  964. //
  965. hwndLv = GetDlgItem(hDlg, IDC_DEVICE_LIST);
  966. iItem = ListView_GetNextItem(hwndLv, -1, LVNI_ALL | LVNI_SELECTED);
  967. if(iItem == -1)
  968. {
  969. Verbose(("No device is selected. Can't display device info.\n"));
  970. break;
  971. }
  972. DisplayDeviceProperty(hDlg);
  973. // refresh the list view
  974. UpdateDeviceInfo(hDlg);
  975. FillInDeviceInfo(hDlg);
  976. break;
  977. }
  978. case IDM_SEND_ENABLE:
  979. case IDM_SEND_DISABLE:
  980. case IDM_RECEIVE_AUTO:
  981. case IDM_RECEIVE_MANUAL:
  982. case IDM_RECEIVE_DISABLE:
  983. {
  984. PFAX_PORT_INFO_EX pFaxPortInfo;
  985. pFaxPortInfo = GetSelectedPortInfo(hDlg);
  986. if(!pFaxPortInfo)
  987. {
  988. Error(("GetSelectedPortInfo() failed\n"));
  989. break;
  990. }
  991. if(IDM_SEND_ENABLE == LOWORD(wParam) ||
  992. IDM_RECEIVE_AUTO == LOWORD(wParam) ||
  993. IDM_RECEIVE_MANUAL == LOWORD(wParam))
  994. {
  995. if(!IsDeviceInUse(pFaxPortInfo->dwDeviceID) &&
  996. GetDeviceLimit() == CountUsedFaxDevices())
  997. {
  998. //
  999. // Device is *NOT* in use and we're about to make it used and
  1000. // we're at the limit point.
  1001. //
  1002. BOOL bLimitExceeded = TRUE;
  1003. if (IDM_RECEIVE_MANUAL == LOWORD(wParam))
  1004. {
  1005. //
  1006. // Do one more check: if we make the device manual-answer, let's make sure the
  1007. // previous manual-answer device will turn to inactive. If that's the case, we don't exceed
  1008. // the device limit.
  1009. //
  1010. DWORD dw;
  1011. for (dw = 0; dw < g_dwPortsNum; dw++)
  1012. {
  1013. if (FAX_DEVICE_RECEIVE_MODE_MANUAL == g_pFaxPortInfo[dw].ReceiveMode)
  1014. {
  1015. //
  1016. // We found the other device who's about to loose its manual-answer mode
  1017. //
  1018. if (!g_pFaxPortInfo[dw].bSend)
  1019. {
  1020. //
  1021. // This is the special case we were looking for
  1022. //
  1023. bLimitExceeded = FALSE;
  1024. }
  1025. break;
  1026. }
  1027. }
  1028. }
  1029. if (bLimitExceeded)
  1030. {
  1031. DisplayErrorMessage(hDlg,
  1032. MB_OK | MB_ICONSTOP,
  1033. FAXUI_ERROR_DEVICE_LIMIT,
  1034. GetDeviceLimit());
  1035. break;
  1036. }
  1037. }
  1038. }
  1039. if(IDM_RECEIVE_MANUAL == LOWORD(wParam))
  1040. {
  1041. //
  1042. // Turn off manual-answer for ALL devices.
  1043. //
  1044. DWORD dw;
  1045. for (dw = 0; dw < g_dwPortsNum; dw++)
  1046. {
  1047. if (FAX_DEVICE_RECEIVE_MODE_MANUAL == g_pFaxPortInfo[dw].ReceiveMode)
  1048. {
  1049. g_pFaxPortInfo[dw].ReceiveMode = FAX_DEVICE_RECEIVE_MODE_OFF;
  1050. }
  1051. }
  1052. //
  1053. // Turn on manual-answer for selected device only.
  1054. //
  1055. pFaxPortInfo->ReceiveMode = FAX_DEVICE_RECEIVE_MODE_MANUAL;
  1056. }
  1057. else if(IDM_RECEIVE_AUTO == LOWORD(wParam))
  1058. {
  1059. pFaxPortInfo->ReceiveMode = FAX_DEVICE_RECEIVE_MODE_AUTO;
  1060. }
  1061. else if(IDM_RECEIVE_DISABLE == LOWORD(wParam))
  1062. {
  1063. pFaxPortInfo->ReceiveMode = FAX_DEVICE_RECEIVE_MODE_OFF;
  1064. }
  1065. else if(IDM_SEND_ENABLE == LOWORD(wParam) ||
  1066. IDM_SEND_DISABLE == LOWORD(wParam))
  1067. {
  1068. pFaxPortInfo->bSend = (IDM_SEND_ENABLE == LOWORD(wParam)) ? TRUE : FALSE;
  1069. }
  1070. UpdateDeviceInfo(hDlg);
  1071. FillInDeviceInfo(hDlg);
  1072. Notify_Change(hDlg);
  1073. NotifyDeviceUsageChanged ();
  1074. break;
  1075. }
  1076. default:
  1077. break;
  1078. }
  1079. break;
  1080. case WM_CONTEXTMENU:
  1081. //
  1082. // Also handle keyboard-originated context menu (<Shift>+F10 or VK_APP)
  1083. //
  1084. if (!g_bUserCanChangeSettings)
  1085. {
  1086. //
  1087. // User has no rights to change the device settings - show no menu
  1088. //
  1089. break;
  1090. }
  1091. if (GetDlgItem(hDlg, IDC_DEVICE_LIST) != GetFocus())
  1092. {
  1093. //
  1094. // Only show context sensitive menu if the focus is on the list control
  1095. //
  1096. break;
  1097. }
  1098. if(ListView_GetItemCount(GetDlgItem(hDlg, IDC_DEVICE_LIST)) == 0)
  1099. {
  1100. //
  1101. // If there aren't item in the list, return immediately.
  1102. //
  1103. break;
  1104. }
  1105. //
  1106. // Popup context menu near mouse cursor
  1107. //
  1108. ShowContextMenu(hDlg);
  1109. break;
  1110. case WM_NOTIFY:
  1111. {
  1112. LPNMHDR lpnm = (LPNMHDR) lParam;
  1113. switch (lpnm->code)
  1114. {
  1115. case NM_CLICK:
  1116. case NM_RCLICK:
  1117. {
  1118. //
  1119. // Handle a Click event
  1120. //
  1121. LPNMITEMACTIVATE lpnmitem;
  1122. lpnmitem = (LPNMITEMACTIVATE)lParam;
  1123. if (IDC_DEVICE_LIST != lpnmitem->hdr.idFrom)
  1124. {
  1125. //
  1126. // Not our list view control
  1127. //
  1128. break;
  1129. }
  1130. //
  1131. // If there aren't item in the list, return immediately.
  1132. //
  1133. if(ListView_GetItemCount(GetDlgItem(hDlg, IDC_DEVICE_LIST)) == 0)
  1134. {
  1135. break;
  1136. }
  1137. if(lpnmitem->iItem == -1)
  1138. {
  1139. //
  1140. // User just un-selected the selected item from the list.
  1141. // Update the other controls on the dialog
  1142. //
  1143. ValidateControl(hDlg, lpnmitem->iItem);
  1144. FillInDeviceInfo(hDlg);
  1145. }
  1146. break;
  1147. }
  1148. case NM_DBLCLK:
  1149. {
  1150. // do the same thing as clicking the "Properties" button
  1151. SendMessage(hDlg, WM_COMMAND, MAKELONG(IDC_DEVICE_PROP, BN_CLICKED), 0L);
  1152. break;
  1153. }
  1154. case LVN_ITEMCHANGED:
  1155. {
  1156. //
  1157. // need to validate the control after changing selection by keyboard
  1158. //
  1159. LPNMLISTVIEW pnmv;
  1160. pnmv = (LPNMLISTVIEW) lParam;
  1161. if(pnmv->uNewState & LVIS_SELECTED)
  1162. {
  1163. ValidateControl(hDlg, pnmv->iItem);
  1164. FillInDeviceInfo(hDlg);
  1165. }
  1166. break;
  1167. }
  1168. case PSN_APPLY:
  1169. if(g_bUserCanChangeSettings)
  1170. {
  1171. if (DoSaveDeviceList(hDlg))
  1172. {
  1173. FillInDeviceInfo(hDlg);
  1174. Notify_UnChange(hDlg);
  1175. }
  1176. else
  1177. {
  1178. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
  1179. }
  1180. }
  1181. return TRUE;
  1182. default :
  1183. break;
  1184. } // switch
  1185. break;
  1186. }
  1187. case WM_HELP:
  1188. WinHelpContextPopup(((LPHELPINFO)lParam)->dwContextId, hDlg);
  1189. return TRUE;
  1190. default:
  1191. break;
  1192. }
  1193. return FALSE;
  1194. }