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.

1168 lines
25 KiB

  1. /*++
  2. Copyright (c) 1999 - 2000 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Abstract:
  6. Common used functions in fax configuration wizard
  7. Environment:
  8. Fax configuration wizard
  9. Revision History:
  10. 03/13/00 -taoyuan-
  11. Created it.
  12. mm/dd/yy -author-
  13. description
  14. --*/
  15. #include "faxcfgwz.h"
  16. #include <devguid.h>
  17. #include <shlwapi.h>
  18. //
  19. // Information about list of dependent services which we stopped
  20. //
  21. typedef struct {
  22. PVOID pNext;
  23. TCHAR serviceName[1];
  24. } DEPENDENT_SERVICE_LIST, *PDEPENDENT_SERVICE_LIST;
  25. //
  26. // offset of field m in a struct s
  27. // copied from stddef.h, so we don't need to include stddef.h
  28. //
  29. #define offsetof(s,m) (size_t)( (char *)&(((s *)0)->m) - (char *)0 )
  30. VOID
  31. LimitTextFields(
  32. HWND hDlg,
  33. INT *pLimitInfo
  34. )
  35. /*++
  36. Routine Description:
  37. Limit the maximum length for a number of text fields
  38. Arguments:
  39. hDlg - Specifies the handle to the dialog window
  40. pLimitInfo - Array of text field control IDs and their maximum length
  41. ID for the 1st text field, maximum length for the 1st text field
  42. ID for the 2nd text field, maximum length for the 2nd text field
  43. ...
  44. 0
  45. Note: The maximum length counts the NUL-terminator.
  46. Return Value:
  47. NONE
  48. --*/
  49. {
  50. while (*pLimitInfo != 0) {
  51. SendDlgItemMessage(hDlg, pLimitInfo[0], EM_SETLIMITTEXT, pLimitInfo[1]-1, 0);
  52. pLimitInfo += 2;
  53. }
  54. }
  55. INT
  56. DisplayMessageDialog(
  57. HWND hwndParent,
  58. UINT type,
  59. INT titleStrId,
  60. INT formatStrId,
  61. ...
  62. )
  63. /*++
  64. Routine Description:
  65. Display a message dialog box
  66. Arguments:
  67. hwndParent - Specifies a parent window for the error message dialog
  68. titleStrId - Title string (could be a string resource ID)
  69. formatStrId - Message format string (could be a string resource ID)
  70. ...
  71. Return Value:
  72. NONE
  73. --*/
  74. {
  75. TCHAR tszTitle[MAX_TITLE_LEN + 1];
  76. TCHAR tszFormat[MAX_MESSAGE_LEN + 1];
  77. TCHAR tszMessage[MAX_MESSAGE_LEN + 1];
  78. va_list ap;
  79. DEBUG_FUNCTION_NAME(TEXT("DisplayMessageDialog()"));
  80. //
  81. // Load dialog box title string resource
  82. //
  83. if (titleStrId == 0)
  84. {
  85. titleStrId = IDS_ERROR_TITLE;
  86. }
  87. if(!LoadString(g_hResource, titleStrId, tszTitle, ARR_SIZE(tszTitle)))
  88. {
  89. DebugPrintEx(DEBUG_ERR,
  90. TEXT("LoadString failed: string ID=%d, error=%d"),
  91. titleStrId,
  92. GetLastError());
  93. return IDCANCEL;
  94. }
  95. //
  96. // Load message format string resource
  97. //
  98. if(!LoadString(g_hResource, formatStrId, tszFormat, ARR_SIZE(tszFormat)))
  99. {
  100. DebugPrintEx(DEBUG_ERR,
  101. TEXT("LoadString failed: string ID=%d, error=%d"),
  102. formatStrId,
  103. GetLastError());
  104. return IDCANCEL;
  105. }
  106. //
  107. // Compose the message string
  108. //
  109. va_start(ap, formatStrId);
  110. wvnsprintf(tszMessage, ARR_SIZE(tszMessage), tszFormat, ap);
  111. va_end(ap);
  112. //
  113. // Terminate string with NULL regardless of success / failure of wvnsprintf
  114. //
  115. tszMessage[ARR_SIZE(tszMessage) - 1] = TEXT('\0');
  116. //
  117. // Display the message box
  118. //
  119. if (type == 0)
  120. {
  121. type = MB_OK | MB_ICONERROR;
  122. }
  123. return AlignedMessageBox(hwndParent, tszMessage, tszTitle, type);
  124. }
  125. int CALLBACK
  126. BrowseCallbackProc(
  127. HWND hDlg,
  128. UINT uMsg,
  129. LPARAM lParam,
  130. LPARAM dwData
  131. )
  132. /*++
  133. Routine Description:
  134. We use this callback function to specify the initial folder
  135. Arguments:
  136. hDlg - Specifies the dialog window on which the Browse button is displayed
  137. uMsg - Value identifying the event.
  138. lParam - Value dependent upon the message contained in the uMsg parameter.
  139. dwData - Application-defined value that was specified in the lParam member of the BROWSEINFO structure.
  140. Return Value:
  141. Returns zero.
  142. --*/
  143. {
  144. switch(uMsg)
  145. {
  146. case BFFM_INITIALIZED:
  147. SendMessage(hDlg, BFFM_SETSELECTION, TRUE, dwData);
  148. break;
  149. case BFFM_SELCHANGED:
  150. {
  151. BOOL bFolderIsOK = FALSE;
  152. TCHAR szPath [MAX_PATH + 1];
  153. if (SHGetPathFromIDList ((LPITEMIDLIST) lParam, szPath))
  154. {
  155. DWORD dwFileAttr = GetFileAttributes(szPath);
  156. if (-1 != dwFileAttr && (dwFileAttr & FILE_ATTRIBUTE_DIRECTORY))
  157. {
  158. //
  159. // The directory exists - enable the 'Ok' button
  160. //
  161. bFolderIsOK = TRUE;
  162. }
  163. }
  164. //
  165. // Enable / disable the 'ok' button
  166. //
  167. SendMessage(hDlg, BFFM_ENABLEOK , 0, (LPARAM)bFolderIsOK);
  168. break;
  169. }
  170. }
  171. return 0;
  172. }
  173. BOOL
  174. BrowseForDirectory(
  175. HWND hDlg,
  176. INT hResource,
  177. LPTSTR title
  178. )
  179. /*++
  180. Routine Description:
  181. Browse for a directory
  182. Arguments:
  183. hDlg - Specifies the dialog window on which the Browse button is displayed
  184. hResource - resource id to receive the directory
  185. title - the title to be shown in the browse dialog
  186. Return Value:
  187. TRUE if successful, FALSE if the user presses Cancel
  188. --*/
  189. {
  190. LPITEMIDLIST pidl;
  191. TCHAR buffer[MAX_PATH];
  192. BOOL bResult = FALSE;
  193. LPMALLOC pMalloc = NULL;
  194. BROWSEINFO bi = {
  195. hDlg,
  196. NULL,
  197. buffer,
  198. title,
  199. BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE | BIF_NONEWFOLDERBUTTON,
  200. BrowseCallbackProc,
  201. (LPARAM) buffer,
  202. };
  203. DEBUG_FUNCTION_NAME(TEXT("BrowseForDirectory()"));
  204. if (!GetDlgItemText( hDlg, hResource, buffer, MAX_PATH))
  205. {
  206. buffer[0] = 0;
  207. }
  208. if(E_FAIL == SHGetMalloc(&pMalloc))
  209. {
  210. DebugPrintEx(DEBUG_ERR, TEXT("SHGetMalloc failed"));
  211. return bResult;
  212. }
  213. if (pidl = SHBrowseForFolder(&bi))
  214. {
  215. if (SHGetPathFromIDList(pidl, buffer))
  216. {
  217. if (lstrlen(buffer) > MAX_ARCHIVE_DIR)
  218. {
  219. DisplayMessageDialog(hDlg, 0, 0,IDS_ERR_DIR_TOO_LONG);
  220. }
  221. else
  222. {
  223. SetDlgItemText(hDlg, hResource, buffer);
  224. bResult = TRUE;
  225. }
  226. }
  227. pMalloc->lpVtbl->Free(pMalloc, (LPVOID)pidl);
  228. }
  229. pMalloc->lpVtbl->Release(pMalloc);
  230. return bResult;
  231. }
  232. VOID
  233. DisConnect(
  234. )
  235. /*++
  236. Routine Description:
  237. Close current connection to the fax service
  238. Arguments:
  239. None.
  240. Return Value:
  241. None.
  242. --*/
  243. {
  244. if (g_hFaxSvcHandle) {
  245. FaxClose(g_hFaxSvcHandle);
  246. g_hFaxSvcHandle = NULL;
  247. }
  248. }
  249. BOOL
  250. Connect(
  251. )
  252. /*++
  253. Routine Description:
  254. Connect to the fax service
  255. Arguments:
  256. None.
  257. Return Value:
  258. TRUE if successfully connected, FALSE if there is an error.
  259. --*/
  260. {
  261. DEBUG_FUNCTION_NAME(TEXT("Connect()"));
  262. //
  263. // Check if already connected to the fax service
  264. //
  265. if (g_hFaxSvcHandle) {
  266. return TRUE;
  267. }
  268. //
  269. // Connect to the fax service
  270. //
  271. if (!FaxConnectFaxServer(NULL, &g_hFaxSvcHandle))
  272. {
  273. LPCTSTR faxDbgFunction = TEXT("Connect()");
  274. DebugPrintEx(DEBUG_ERR, TEXT("Can't connect to the fax server, ec = %d."), GetLastError());
  275. return FALSE;
  276. }
  277. return TRUE;
  278. }
  279. DWORD
  280. DoesTAPIHaveDialingLocation (
  281. LPBOOL lpbRes
  282. )
  283. /*++
  284. Routine name : DoesTAPIHaveDialingLocation
  285. Routine description:
  286. Checks if TAPI as at least one dialing location
  287. Author:
  288. Eran Yariv (EranY), Dec, 2000
  289. Arguments:
  290. lpbRes [out] - TRUE if TAPI has at least one dialing location. FALSE if none
  291. Return Value:
  292. Standard Win32 error code
  293. --*/
  294. {
  295. DWORD dwRes = ERROR_SUCCESS;
  296. HLINEAPP hLineApp = HandleToULong(NULL);
  297. DWORD dwNumDevs;
  298. LINEINITIALIZEEXPARAMS LineInitializeExParams;
  299. DWORD dwAPIVer = 0x00020000;
  300. LINETRANSLATECAPS LineTransCaps;
  301. HANDLE hEvent = NULL;
  302. DEBUG_FUNCTION_NAME(TEXT("DoesTAPIHaveDialingLocation"));
  303. //
  304. // Create a dummy event
  305. //
  306. hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  307. if (!hEvent)
  308. {
  309. DebugPrintEx(DEBUG_ERR,
  310. TEXT("CreateEvent failed: %#lx"),
  311. GetLastError());
  312. return GetLastError ();
  313. }
  314. //
  315. // Initialize TAPI
  316. //
  317. LineInitializeExParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
  318. LineInitializeExParams.dwNeededSize = 0;
  319. LineInitializeExParams.dwUsedSize = 0;
  320. LineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT ;
  321. LineInitializeExParams.Handles.hEvent = hEvent;
  322. dwRes = (DWORD)lineInitializeEx(
  323. &hLineApp,
  324. GetModuleHandle(NULL),
  325. NULL,
  326. NULL,
  327. &dwNumDevs,
  328. &dwAPIVer,
  329. &LineInitializeExParams
  330. );
  331. if (ERROR_SUCCESS != dwRes)
  332. {
  333. DebugPrintEx(DEBUG_ERR,
  334. TEXT("lineInitializeEx failed: %#lx"),
  335. dwRes);
  336. goto exit;
  337. }
  338. LineTransCaps.dwTotalSize = sizeof(LINETRANSLATECAPS);
  339. dwRes = (DWORD)lineGetTranslateCaps (hLineApp, 0x00020000, &LineTransCaps);
  340. if ((DWORD)LINEERR_INIFILECORRUPT == dwRes)
  341. {
  342. //
  343. // This is a special return code from TAPI which indicates no dialing rules are defined.
  344. //
  345. *lpbRes = FALSE;
  346. }
  347. else
  348. {
  349. *lpbRes = TRUE;
  350. }
  351. dwRes = ERROR_SUCCESS;
  352. exit:
  353. if (hLineApp)
  354. {
  355. lineShutdown (hLineApp);
  356. }
  357. if (hEvent)
  358. {
  359. CloseHandle (hEvent);
  360. }
  361. return dwRes;
  362. } // DoesTAPIHaveDialingLocation
  363. void
  364. InstallModem (
  365. HWND hWnd
  366. )
  367. /*++
  368. Routine Description:
  369. Pop up the hardware installation wizard to install a modem.
  370. Arguments:
  371. hWnd - window handle of the caller.
  372. Return Value:
  373. None.
  374. --*/
  375. {
  376. HINSTANCE hInst = NULL;
  377. PINSTNEWDEV pInstNewDev;
  378. DEBUG_FUNCTION_NAME(TEXT("InstallModem()"));
  379. hInst = LoadLibrary (NEW_DEV_DLL);
  380. if (NULL == hInst)
  381. {
  382. DebugPrintEx(DEBUG_ERR, TEXT("LoadLibrary failed: %#lx"), GetLastError());
  383. return;
  384. }
  385. pInstNewDev = (PINSTNEWDEV)GetProcAddress (hInst, INSTALL_NEW_DEVICE);
  386. if (NULL != pInstNewDev)
  387. {
  388. EnableWindow (hWnd, FALSE);
  389. pInstNewDev (hWnd, (LPGUID)&GUID_DEVCLASS_MODEM, NULL);
  390. EnableWindow (hWnd, TRUE);
  391. }
  392. else
  393. {
  394. DebugPrintEx(DEBUG_ERR, TEXT("GetProcAddress failed: %#lx"), GetLastError());
  395. }
  396. FreeLibrary (hInst);
  397. DebugPrintEx(DEBUG_MSG, TEXT("Exit modem installation."));
  398. return;
  399. } // InstallModem
  400. BOOL
  401. StartFaxService(
  402. LPTSTR pServerName
  403. )
  404. /*++
  405. Routine Description:
  406. Start the fax service
  407. Arguments:
  408. pServerName - Specifies the name of the server computer, NULL for local machine
  409. Return Value:
  410. TRUE if successful, FALSE if there is an error
  411. --*/
  412. {
  413. BOOL success = FALSE;
  414. DEBUG_FUNCTION_NAME(TEXT("StartFaxService()"));
  415. //
  416. // Start the fax service and wait for it to be in the running state
  417. //
  418. if (EnsureFaxServiceIsStarted(pServerName))
  419. {
  420. success = WaitForServiceRPCServer(60 * 1000);
  421. if(!success)
  422. {
  423. DebugPrintEx(DEBUG_ERR, TEXT("WaitForServiceRPCServer failed: %d"), GetLastError());
  424. }
  425. }
  426. return success;
  427. }
  428. BOOL
  429. IsUserInfoConfigured()
  430. /*++
  431. Routine Description:
  432. Check whether it's the first time starting the wizard
  433. Arguments:
  434. Return Value:
  435. TRUE if User Info Configured, FALSE if not
  436. --*/
  437. {
  438. //
  439. // Set flag in the registry to specify we have done the
  440. // fax configuration wizard
  441. //
  442. HKEY hRegKey;
  443. BOOL bRes = FALSE;
  444. DEBUG_FUNCTION_NAME(TEXT("IsUserInfoConfigured()"));
  445. //
  446. // Open the user registry key for writing and create it if necessary
  447. //
  448. if ((hRegKey = OpenRegistryKey(HKEY_CURRENT_USER, REGKEY_FAX_SETUP, TRUE, KEY_QUERY_VALUE)))
  449. {
  450. bRes = GetRegistryDword(hRegKey, REGVAL_CFGWZRD_USER_INFO);
  451. //
  452. // Close the registry key before returning to the caller
  453. //
  454. RegCloseKey(hRegKey);
  455. }
  456. else
  457. {
  458. LPCTSTR faxDbgFunction = TEXT("IsUserInfoConfigured()");
  459. DebugPrintEx(DEBUG_ERR, TEXT("Can't open registry to set the wizard flag."));
  460. }
  461. return bRes;
  462. }
  463. BOOL
  464. FaxDeviceEnableRoutingMethod(
  465. HANDLE hFaxHandle,
  466. DWORD dwDeviceId,
  467. LPCTSTR pRoutingGuid,
  468. LONG Enabled
  469. )
  470. /*++
  471. Routine Description:
  472. Get or set the current status of a routing method for specific device
  473. Arguments:
  474. hFaxHandle - fax handle by FaxConnectFaxServer()
  475. dwDeviceId - device ID
  476. pRoutingGuid - GUID that identifies the fax routing method
  477. Enabled - enabled status for the device and method, if Enabled is QUERY_STATUS,
  478. it means return value is the current state
  479. Return Value:
  480. if Enabled is QUERY_STATUS, return the current state of routing method;
  481. if Enabled is QUERY_ENABLE or QUERY_DISABLE, return TRUE for success, FALSE for failure.
  482. --*/
  483. {
  484. BOOL bRes = FALSE;
  485. PFAX_ROUTING_METHOD pRoutMethod = NULL;
  486. DWORD dwMethodsNum;
  487. HANDLE hFaxPortHandle = NULL;
  488. DWORD dwInx;
  489. DEBUG_FUNCTION_NAME(TEXT("FaxDeviceEnableRoutingMethod()"));
  490. if(!hFaxHandle)
  491. {
  492. Assert(FALSE);
  493. return bRes;
  494. }
  495. if(!FaxOpenPort(hFaxHandle,
  496. dwDeviceId,
  497. PORT_OPEN_QUERY | PORT_OPEN_MODIFY,
  498. &hFaxPortHandle))
  499. {
  500. DebugPrintEx(DEBUG_ERR, TEXT("FaxOpenPort failed: %d."), GetLastError());
  501. goto exit;
  502. }
  503. if(Enabled == QUERY_STATUS)
  504. {
  505. if(!FaxEnumRoutingMethods(hFaxPortHandle, &pRoutMethod, &dwMethodsNum))
  506. {
  507. DebugPrintEx(DEBUG_ERR, TEXT("FaxEnumRoutingMethods failed: %d."), GetLastError());
  508. goto exit;
  509. }
  510. for(dwInx=0; dwInx < dwMethodsNum; ++dwInx)
  511. {
  512. if(!_tcsicmp(pRoutMethod[dwInx].Guid, pRoutingGuid))
  513. {
  514. bRes = pRoutMethod[dwInx].Enabled;
  515. goto exit;
  516. }
  517. }
  518. DebugPrintEx(DEBUG_MSG, TEXT("Routing method not found"));
  519. goto exit;
  520. }
  521. else
  522. {
  523. if(!FaxEnableRoutingMethod(hFaxPortHandle,
  524. pRoutingGuid,
  525. (Enabled == STATUS_ENABLE) ? TRUE : FALSE))
  526. {
  527. DebugPrintEx(DEBUG_ERR, TEXT("FaxEnableRoutingMethod failed: %d."), GetLastError());
  528. goto exit;
  529. }
  530. }
  531. bRes = TRUE;
  532. exit:
  533. if(pRoutMethod)
  534. {
  535. FaxFreeBuffer(pRoutMethod);
  536. }
  537. if(hFaxPortHandle)
  538. {
  539. FaxClose(hFaxPortHandle);
  540. }
  541. return bRes;
  542. }
  543. BOOL
  544. VerifyDialingLocations (
  545. HWND hWndParent
  546. )
  547. /*++
  548. Routine name : VerifyDialingLocations
  549. Routine description:
  550. Makes sure there's at least one TAPI dialing location defined.
  551. If none are defined, pops the system U/I for defining one.
  552. If the user cancels that U/I, offer the user a chance to re-enter a dialing location.
  553. If the user still refuses, return FALSE.
  554. Author:
  555. Eran Yariv (EranY), Jan, 2001
  556. Arguments:
  557. hWndParent [in] - Parent window handle
  558. Return Value:
  559. See discussion on the return value in the description above.
  560. --*/
  561. {
  562. BOOL bDialingRulesDefined;
  563. DWORD dwRes;
  564. DEBUG_FUNCTION_NAME(TEXT("VerifyDialingLocations"));
  565. //
  566. // Check if there are dialing rules defined
  567. //
  568. dwRes = DoesTAPIHaveDialingLocation (&bDialingRulesDefined);
  569. if (ERROR_SUCCESS != dwRes)
  570. {
  571. //
  572. // Can't detect - return now.
  573. // Assume TRUE.
  574. //
  575. return TRUE;
  576. }
  577. if (bDialingRulesDefined)
  578. {
  579. //
  580. // Good. Return TRUE
  581. //
  582. return TRUE;
  583. }
  584. for (;;)
  585. {
  586. //
  587. // No dialing rules defined, pop the simple dialing rules dialog
  588. //
  589. extern LONG LOpenDialAsst(
  590. IN HWND hwnd,
  591. IN LPCTSTR lpszAddressIn,
  592. IN BOOL fSimple, // if TRUE, uses a dialog for dialing locations. Otherwise, uses a property sheet.
  593. IN BOOL fSilentInstall );
  594. EnableWindow (hWndParent, FALSE);
  595. LOpenDialAsst(hWndParent, NULL, TRUE, TRUE);
  596. EnableWindow (hWndParent, TRUE);
  597. //
  598. // After we popped the system dialing locations dialog, we should check and see if a location was really added.
  599. //
  600. dwRes = DoesTAPIHaveDialingLocation (&bDialingRulesDefined);
  601. if (ERROR_SUCCESS != dwRes)
  602. {
  603. //
  604. // Can't detect - return now.
  605. // Assume TRUE.
  606. //
  607. return TRUE;
  608. }
  609. if (bDialingRulesDefined)
  610. {
  611. //
  612. // Good. The user just added a dialing rule
  613. //
  614. return TRUE;
  615. }
  616. //
  617. // Oh no - the user canceled.
  618. // Pop a message box asking him to retry
  619. //
  620. if (IDYES == DisplayMessageDialog(hWndParent,
  621. MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2,
  622. 0,
  623. IDS_ERR_NO_DIALING_LOCATION))
  624. {
  625. //
  626. // User chose to abort the wizard - return now
  627. //
  628. return FALSE;
  629. }
  630. //
  631. // Try again
  632. //
  633. }
  634. ASSERT_FALSE;
  635. } // VerifyDialingLocations
  636. DWORD
  637. CountFaxDevices ()
  638. /*++
  639. Routine name : CountFaxDevices
  640. Routine description:
  641. Counts the number of fax devices (ports) the service knows about
  642. Author:
  643. Eran Yariv (EranY), Apr, 2001
  644. Arguments:
  645. Return Value:
  646. Standard Win32 error code
  647. --*/
  648. {
  649. PFAX_PORT_INFO_EX pPortsInfo = NULL;
  650. DWORD dwPorts;
  651. DEBUG_FUNCTION_NAME(TEXT("CountFaxDevices()"));
  652. if(!FaxEnumPortsEx(g_hFaxSvcHandle, &pPortsInfo, &dwPorts))
  653. {
  654. DebugPrintEx(DEBUG_MSG, TEXT("FaxEnumPortsEx: failed: error=%d."), GetLastError());
  655. return 0;
  656. }
  657. if(pPortsInfo)
  658. {
  659. FaxFreeBuffer(pPortsInfo);
  660. }
  661. return dwPorts;
  662. } // CountFaxDevices
  663. BOOL
  664. IsFaxDeviceInstalled(
  665. HWND hWnd,
  666. LPBOOL lpbAbort
  667. )
  668. /*++
  669. Routine Description:
  670. Checks if some fax devices are installed.
  671. If not, suggest to the user to install a device.
  672. Also, checks if TAPI has a dialing location.
  673. If not, asks the user to add one.
  674. If the user refuses, sets lpbAbort to TRUE and return FALSE.
  675. Arguments:
  676. hWnd - [in] caller window handle
  677. lpbAbort - [out] TRUE if the user refused to enter a dialing location and the calling process should abort.
  678. Return Value:
  679. return TRUE for YES, FALSE for NO
  680. --*/
  681. {
  682. DWORD dwDevices;
  683. DEBUG_FUNCTION_NAME(TEXT("IsFaxDeviceInstalled()"));
  684. //
  685. // See how many fax devices the server has found
  686. //
  687. dwDevices = CountFaxDevices();
  688. if(0 == dwDevices)
  689. {
  690. int iInstallNewModem;
  691. //
  692. // no available device, pop up a U/I to install modem
  693. //
  694. iInstallNewModem = DisplayMessageDialog(hWnd,
  695. MB_YESNO | MB_ICONQUESTION,
  696. 0,
  697. IDS_ERR_NO_DEVICE);
  698. if(iInstallNewModem == IDYES)
  699. {
  700. //
  701. // Make sure we have at least one TAPI dialing location.
  702. // If not, pop a system U/I for the dialing locations.
  703. //
  704. HCURSOR hOldCursor;
  705. int i;
  706. if (!VerifyDialingLocations (hWnd))
  707. {
  708. //
  709. // The user refused to enter a dialing location and the calling process should abort.
  710. //
  711. *lpbAbort = TRUE;
  712. return FALSE;
  713. }
  714. hOldCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  715. InstallModem(hWnd);
  716. //
  717. // We don't need to restart the service because the
  718. // service can detect the addition of new fax devices.
  719. // Let's wait a while for the service to discover the new device.
  720. // We wait up to 12 seconds.
  721. //
  722. for (i=0; i < 4; i++)
  723. {
  724. Sleep (3000);
  725. dwDevices = CountFaxDevices();
  726. if (dwDevices)
  727. {
  728. //
  729. // Hooray. Device found by service
  730. //
  731. break;
  732. }
  733. }
  734. SetCursor (hOldCursor);
  735. }
  736. }
  737. else
  738. {
  739. //
  740. // At least one device is already installed.
  741. // Make sure we have at least one TAPI dialing location.
  742. // If not, pop a system U/I for the dialing locations.
  743. //
  744. if (!VerifyDialingLocations (hWnd))
  745. {
  746. //
  747. // The user refused to enter a dialing location and the calling process should abort.
  748. //
  749. *lpbAbort = TRUE;
  750. return FALSE;
  751. }
  752. }
  753. return (dwDevices != 0);
  754. } // IsFaxDeviceInstalled
  755. VOID
  756. ListView_SetDeviceImageList(
  757. HWND hwndLv,
  758. HINSTANCE hinst
  759. )
  760. /*++
  761. Routine Description:
  762. Sets ImageList to list view
  763. Arguments:
  764. hwndLv - list view handle
  765. hinst - application instance
  766. Return Value:
  767. none
  768. --*/
  769. {
  770. HICON hIcon;
  771. HIMAGELIST himl;
  772. himl = ImageList_Create(
  773. GetSystemMetrics( SM_CXSMICON ),
  774. GetSystemMetrics( SM_CYSMICON ),
  775. ILC_MASK, 2, 2 );
  776. hIcon = LoadIcon( hinst, MAKEINTRESOURCE( IDI_Modem ) );
  777. Assert(hIcon);
  778. ImageList_ReplaceIcon( himl, -1, hIcon );
  779. DestroyIcon( hIcon );
  780. ListView_SetImageList( hwndLv, himl, LVSIL_SMALL );
  781. }
  782. BOOL
  783. IsSendEnable()
  784. /*++
  785. Routine Description:
  786. Determine if the any of the devices configured to send faxes
  787. Arguments:
  788. Return Value:
  789. TRUE or FALSE
  790. --*/
  791. {
  792. DWORD dw;
  793. if(NULL == g_wizData.pDevInfo)
  794. {
  795. return FALSE;
  796. }
  797. for(dw=0; dw < g_wizData.dwDeviceCount; ++dw)
  798. {
  799. if(g_wizData.pDevInfo[dw].bSend)
  800. {
  801. return TRUE;
  802. }
  803. }
  804. return FALSE;
  805. }
  806. BOOL
  807. IsReceiveEnable()
  808. /*++
  809. Routine Description:
  810. Determine if the any of the devices configured to receive faxes
  811. Arguments:
  812. Return Value:
  813. TRUE or FALSE
  814. --*/
  815. {
  816. DWORD dw;
  817. if(NULL == g_wizData.pDevInfo)
  818. {
  819. return FALSE;
  820. }
  821. for(dw=0; dw < g_wizData.dwDeviceCount; ++dw)
  822. {
  823. if(FAX_DEVICE_RECEIVE_MODE_OFF != g_wizData.pDevInfo[dw].ReceiveMode)
  824. {
  825. return TRUE;
  826. }
  827. }
  828. return FALSE;
  829. }
  830. int
  831. GetDevIndexByDevId(
  832. DWORD dwDeviceId
  833. )
  834. /*++
  835. Routine Description:
  836. Finds appropriate item index in WIZARDDATA.pDevInfo array
  837. by device ID
  838. Arguments:
  839. dwDeviceId - device ID
  840. Return Value:
  841. device index in WIZARDDATA.pDevInfo array
  842. or -1 on failure
  843. --*/
  844. {
  845. DWORD dwIndex;
  846. if(NULL == g_wizData.pDevInfo)
  847. {
  848. Assert(FALSE);
  849. return -1;
  850. }
  851. for(dwIndex = 0; dwIndex < g_wizData.dwDeviceCount; ++dwIndex)
  852. {
  853. if(g_wizData.pDevInfo[dwIndex].dwDeviceId == dwDeviceId)
  854. {
  855. return (int)dwIndex;
  856. }
  857. }
  858. Assert(FALSE);
  859. return -1;
  860. }
  861. VOID
  862. InitDeviceList(
  863. HWND hDlg,
  864. DWORD dwListViewResId
  865. )
  866. /*++
  867. Routine Description:
  868. Initializes devices list view control
  869. Arguments:
  870. hDlg - Handle to property page
  871. dwListViewResId - list view resource ID
  872. Return Value:
  873. NONE
  874. --*/
  875. {
  876. HWND hwndLv;
  877. LV_COLUMN col = {0};
  878. DEBUG_FUNCTION_NAME(TEXT("InitDeviceList()"));
  879. Assert(hDlg);
  880. hwndLv = GetDlgItem(hDlg, dwListViewResId);
  881. Assert(hwndLv);
  882. //
  883. // Add the modem images.
  884. //
  885. ListView_SetDeviceImageList(hwndLv, g_hResource );
  886. ListView_SetExtendedListViewStyle(hwndLv, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
  887. //
  888. // Add a single column exactly wide enough to fully display
  889. // the widest member of the list.
  890. //
  891. col.mask = LVCF_FMT;
  892. col.fmt = LVCFMT_LEFT;
  893. ListView_InsertColumn(hwndLv, 0, &col );
  894. return;
  895. }