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.

878 lines
16 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Abstract:
  6. utility functions
  7. Environment:
  8. Fax configuration applet
  9. Revision History:
  10. 05/26/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. typedef struct _STRING_TABLE {
  19. DWORD ResourceId;
  20. LPTSTR String;
  21. } STRING_TABLE, *PSTRING_TABLE;
  22. static STRING_TABLE StringTable[] =
  23. {
  24. { IDS_DEVICE_ENABLED, NULL},
  25. { IDS_DEVICE_DISABLED, NULL},
  26. { IDS_DEVICE_AUTO_ANSWER, NULL},
  27. { IDS_DEVICE_MANUAL_ANSWER, NULL}
  28. };
  29. #define CountStringTable (sizeof(StringTable)/sizeof(STRING_TABLE))
  30. VOID
  31. InitializeStringTable(
  32. VOID
  33. )
  34. /*++
  35. Routine Description:
  36. Initialize the string table for future use
  37. Arguments:
  38. None
  39. Return Value:
  40. None
  41. --*/
  42. {
  43. DWORD i;
  44. TCHAR szBuffer[256];
  45. for (i=0; i<CountStringTable; i++)
  46. {
  47. if (LoadString(
  48. g_hResource,
  49. StringTable[i].ResourceId,
  50. szBuffer,
  51. sizeof(szBuffer)/sizeof(TCHAR)))
  52. {
  53. StringTable[i].String = (LPTSTR) MemAlloc( StringSize( szBuffer ) );
  54. if (!StringTable[i].String) {
  55. StringTable[i].String = NULL;
  56. } else {
  57. _tcscpy( StringTable[i].String, szBuffer );
  58. }
  59. }
  60. else
  61. {
  62. Error(( "LoadString failed, resource ID is %d.\n", StringTable[i].ResourceId ));
  63. StringTable[i].String = NULL;
  64. }
  65. }
  66. }
  67. VOID
  68. DeInitializeStringTable(
  69. VOID
  70. )
  71. /*++
  72. Routine Description:
  73. Deinitialize the string table and release allocated memory
  74. Arguments:
  75. None
  76. Return Value:
  77. None
  78. --*/
  79. {
  80. DWORD i;
  81. for (i=0; i<CountStringTable; i++)
  82. {
  83. if(StringTable[i].String)
  84. {
  85. MemFree(StringTable[i].String);
  86. StringTable[i].String = NULL;
  87. }
  88. }
  89. }
  90. LPTSTR
  91. GetString(
  92. DWORD ResourceId
  93. )
  94. /*++
  95. Routine Description:
  96. Loads a resource string and returns a pointer to the string.
  97. The caller must free the memory.
  98. Arguments:
  99. ResourceId - resource string id
  100. Return Value:
  101. pointer to the string
  102. --*/
  103. {
  104. DWORD i;
  105. for (i=0; i<CountStringTable; i++)
  106. {
  107. if (StringTable[i].ResourceId == ResourceId)
  108. {
  109. return StringTable[i].String;
  110. }
  111. }
  112. Assert(FALSE);
  113. return NULL;
  114. }
  115. INT
  116. DisplayErrorMessage(
  117. HWND hwndParent,
  118. UINT uiType,
  119. INT iErrorCode,
  120. ...
  121. )
  122. /*++
  123. Routine Description:
  124. Display an Error Message dialog box
  125. Arguments:
  126. hwndParent - Specifies a parent window for the error message dialog
  127. type - Specifies the type of message box to be displayed
  128. iErrorCode - Win32 Error Code
  129. ...
  130. Return Value:
  131. Same as the return value from MessageBox
  132. --*/
  133. {
  134. LPTSTR pTitle = NULL;
  135. LPTSTR pFormat = NULL;
  136. LPTSTR pMessage = NULL;
  137. INT result;
  138. va_list ap;
  139. INT iStringID = 0;
  140. BOOL bOK = TRUE;
  141. if ((pTitle = AllocStringZ(MAX_TITLE_LEN)) &&
  142. (pFormat = AllocStringZ(MAX_STRING_LEN)) &&
  143. (pMessage = AllocStringZ(MAX_MESSAGE_LEN)))
  144. {
  145. //
  146. // Load Title String
  147. //
  148. if (!LoadString(g_hResource, IDS_MSG_TITLE, pTitle, MAX_TITLE_LEN))
  149. {
  150. Error(("Failed to load preview message string. (ec: %lc)",GetLastError()));
  151. bOK = FALSE;
  152. goto Exit;
  153. }
  154. //
  155. // Load Error Message
  156. //
  157. iStringID = GetErrorStringId(iErrorCode);
  158. if (!LoadString(g_hResource, iStringID, pFormat, MAX_STRING_LEN))
  159. {
  160. Error(("Failed to load preview message string. (ec: %lc)",GetLastError()));
  161. bOK = FALSE;
  162. goto Exit;
  163. }
  164. //
  165. // Compose the message string
  166. //
  167. va_start(ap, iErrorCode);
  168. wvsprintf(pMessage, pFormat, ap);
  169. va_end(ap);
  170. //
  171. // Display the message box
  172. //
  173. if (uiType == 0)
  174. {
  175. uiType = MB_OK | MB_ICONERROR;
  176. }
  177. result = AlignedMessageBox(hwndParent, pMessage, pTitle, uiType);
  178. }
  179. else
  180. {
  181. bOK = FALSE;
  182. }
  183. Exit:
  184. if (!bOK)
  185. {
  186. MessageBeep(MB_ICONHAND);
  187. result = 0;
  188. }
  189. MemFree(pTitle);
  190. MemFree(pFormat);
  191. MemFree(pMessage);
  192. return result;
  193. }
  194. BOOL IsLocalPrinter(
  195. LPTSTR pPrinterName
  196. )
  197. /*++
  198. Routine Description:
  199. Check whether given printer is local
  200. Arguments:
  201. pPrinterName - giver printer name
  202. Return Value:
  203. TRUE if it's local, FALSE otherwise
  204. --*/
  205. {
  206. DWORD ErrorCode = 0;
  207. BOOL Found = FALSE;
  208. PPRINTER_INFO_4 pPrinterInfo = NULL;
  209. DWORD BytesNeeded = 0;
  210. DWORD NumPrinters = 0;
  211. PPRINTER_INFO_4 pCurrPrinterInfo;
  212. //
  213. // enumerate local printers
  214. //
  215. if (EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &BytesNeeded, &NumPrinters))
  216. {
  217. // if succeeds, there are no printers
  218. goto CleanUp;
  219. }
  220. else if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  221. || !(pPrinterInfo = (PPRINTER_INFO_4) GlobalAlloc(GMEM_FIXED, BytesNeeded))
  222. || !EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, (LPBYTE) pPrinterInfo,
  223. BytesNeeded, &BytesNeeded, &NumPrinters))
  224. {
  225. ErrorCode = GetLastError();
  226. goto CleanUp;
  227. }
  228. for (pCurrPrinterInfo = pPrinterInfo;
  229. !Found && (pCurrPrinterInfo < (pPrinterInfo + NumPrinters));
  230. pCurrPrinterInfo++)
  231. {
  232. // check for printer name
  233. if (!lstrcmpi(pCurrPrinterInfo->pPrinterName, pPrinterName))
  234. {
  235. Found = TRUE;
  236. }
  237. }
  238. CleanUp:
  239. if (pPrinterInfo)
  240. {
  241. GlobalFree(pPrinterInfo);
  242. }
  243. SetLastError(ErrorCode);
  244. return Found;
  245. }
  246. VOID
  247. DisConnect(
  248. )
  249. /*++
  250. Routine Description:
  251. Close current connection to the fax service
  252. Arguments:
  253. None.
  254. Return Value:
  255. None.
  256. --*/
  257. {
  258. if (g_hFaxSvcHandle) {
  259. FaxClose(g_hFaxSvcHandle);
  260. g_hFaxSvcHandle = NULL;
  261. }
  262. }
  263. BOOL
  264. Connect(
  265. HWND hDlg,
  266. BOOL bDisplayErrorMessage
  267. )
  268. /*++
  269. Routine Description:
  270. Connect to the fax service
  271. Arguments:
  272. hDlg - the caller window handle
  273. bDisplayErrorMessage - indicate whether display the error message to the user
  274. Return Value:
  275. TRUE if successfully connected, FALSE if there is an error.
  276. --*/
  277. {
  278. DWORD dwRes = 0;
  279. //
  280. // Check if already connected to the fax service
  281. //
  282. if (g_hFaxSvcHandle)
  283. {
  284. return TRUE;
  285. }
  286. //
  287. // Connect to the fax service
  288. //
  289. if (!FaxConnectFaxServer(NULL, &g_hFaxSvcHandle))
  290. {
  291. dwRes = GetLastError();
  292. Error(( "Can't connect to the fax server, ec = %d.\n", dwRes));
  293. if(bDisplayErrorMessage)
  294. {
  295. DisplayErrorMessage(hDlg, 0, dwRes);
  296. }
  297. return FALSE;
  298. }
  299. return TRUE;
  300. }
  301. BOOL
  302. DirectoryExists(
  303. LPTSTR pDirectoryName
  304. )
  305. /*++
  306. Routine Description:
  307. Check the existancy of given folder name
  308. Arguments:
  309. pDirectoryName - point to folder name
  310. Return Value:
  311. if the folder exists, return TRUE; else, return FALSE.
  312. --*/
  313. {
  314. TCHAR pFullDirectoryName[MAX_PATH];
  315. DWORD dwFileAttributes;
  316. DWORD dwSize;
  317. if(!pDirectoryName || lstrlen(pDirectoryName) == 0)
  318. {
  319. return FALSE;
  320. }
  321. dwSize = ExpandEnvironmentStrings(pDirectoryName, pFullDirectoryName, MAX_PATH);
  322. if(dwSize == 0)
  323. {
  324. return FALSE;
  325. }
  326. dwFileAttributes = GetFileAttributes(pFullDirectoryName);
  327. if ( dwFileAttributes != 0xffffffff &&
  328. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  329. {
  330. return TRUE;
  331. }
  332. return FALSE;
  333. }
  334. BOOL
  335. FaxDeviceEnableRoutingMethod(
  336. HANDLE hFaxHandle,
  337. DWORD dwDeviceId,
  338. LPCTSTR pRoutingGuid,
  339. LONG Enabled
  340. )
  341. /*++
  342. Routine Description:
  343. Get or set the current status of a routing method for specific device
  344. Arguments:
  345. hFaxHandle - fax handle by FaxConnectFaxServer()
  346. dwDeviceId - device ID
  347. pRoutingGuid - GUID that identifies the fax routing method
  348. Enabled - enabled status for the device and method, if Enabled is QUERY_STATUS,
  349. it means return value is the current state
  350. Return Value:
  351. if Enabled is QUERY_STATUS, return the current state of routing method;
  352. if Enabled is QUERY_ENABLE or QUERY_DISABLE, return TRUE for success, FALSE for failure.
  353. --*/
  354. {
  355. HANDLE hFaxPortHandle = NULL;
  356. BOOL bResult = FALSE;
  357. LPBYTE pRoutingInfoBuffer = NULL;
  358. DWORD dwRoutingInfoBufferSize;
  359. Assert(hFaxHandle);
  360. if(!hFaxHandle || !FaxOpenPort(hFaxHandle, dwDeviceId, PORT_OPEN_QUERY | PORT_OPEN_MODIFY, &hFaxPortHandle))
  361. {
  362. goto exit;
  363. }
  364. if(!FaxGetRoutingInfo(hFaxPortHandle, pRoutingGuid, &pRoutingInfoBuffer, &dwRoutingInfoBufferSize))
  365. {
  366. goto exit;
  367. }
  368. if(Enabled == QUERY_STATUS)
  369. {
  370. //
  371. // for query status
  372. //
  373. bResult = *((LPDWORD)pRoutingInfoBuffer) > 0 ? TRUE : FALSE;
  374. }
  375. else
  376. {
  377. //
  378. // for set status
  379. //
  380. *((LPDWORD)pRoutingInfoBuffer) = (Enabled == STATUS_ENABLE) ? TRUE : FALSE;
  381. if(FaxSetRoutingInfo(hFaxPortHandle, pRoutingGuid, pRoutingInfoBuffer, dwRoutingInfoBufferSize))
  382. {
  383. bResult = TRUE;
  384. }
  385. }
  386. exit:
  387. if(pRoutingInfoBuffer) { FaxFreeBuffer(pRoutingInfoBuffer); }
  388. if(hFaxPortHandle) { FaxClose(hFaxPortHandle); }
  389. return bResult;
  390. }
  391. int CALLBACK BrowseCallbackProc(
  392. HWND hDlg,
  393. UINT uMsg,
  394. LPARAM lParam,
  395. LPARAM dwData)
  396. /*++
  397. Routine Description:
  398. We use this callback function to specify the initial folder
  399. Arguments:
  400. hDlg - Specifies the dialog window on which the Browse button is displayed
  401. uMsg - Value identifying the event.
  402. lParam - Value dependent upon the message contained in the uMsg parameter.
  403. dwData - Application-defined value that was specified in the lParam member of the BROWSEINFO structure.
  404. Return Value:
  405. Returns zero.
  406. --*/
  407. {
  408. switch(uMsg)
  409. {
  410. case BFFM_INITIALIZED:
  411. SendMessage(hDlg, BFFM_SETSELECTION, TRUE, dwData);
  412. break;
  413. case BFFM_SELCHANGED:
  414. {
  415. BOOL bFolderIsOK = FALSE;
  416. TCHAR szPath [MAX_PATH + 1];
  417. if (SHGetPathFromIDList ((LPITEMIDLIST) lParam, szPath))
  418. {
  419. DWORD dwFileAttr = GetFileAttributes(szPath);
  420. if (-1 != dwFileAttr && (dwFileAttr & FILE_ATTRIBUTE_DIRECTORY))
  421. {
  422. //
  423. // The directory exists - enable the 'Ok' button
  424. //
  425. bFolderIsOK = TRUE;
  426. }
  427. }
  428. //
  429. // Enable / disable the 'ok' button
  430. //
  431. SendMessage(hDlg, BFFM_ENABLEOK , 0, (LPARAM)bFolderIsOK);
  432. break;
  433. }
  434. }
  435. return 0;
  436. }
  437. BOOL
  438. BrowseForDirectory(
  439. HWND hDlg,
  440. INT hResource,
  441. DWORD dwMaxPath,
  442. LPTSTR title
  443. )
  444. /*++
  445. Routine Description:
  446. Browse for a directory
  447. Arguments:
  448. hDlg - Specifies the dialog window on which the Browse button is displayed
  449. hResource - resource id to receive the directory
  450. dwMaxPath - max path length
  451. title - the title to be shown in the browse dialog
  452. Return Value:
  453. TRUE if successful, FALSE if the user presses Cancel
  454. --*/
  455. {
  456. LPITEMIDLIST pidl;
  457. TCHAR buffer[MAX_PATH];
  458. BOOL bResult = FALSE;
  459. LPMALLOC pMalloc = NULL;
  460. BROWSEINFO bi = {
  461. hDlg,
  462. NULL,
  463. buffer,
  464. title,
  465. BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE,
  466. BrowseCallbackProc,
  467. (LPARAM) buffer,
  468. };
  469. Verbose(("Entering BrowseForDirectory...\n"));
  470. if (!GetDlgItemText( hDlg, hResource, buffer, MAX_PATH))
  471. buffer[0] = 0;
  472. if(E_FAIL == SHGetMalloc(&pMalloc))
  473. {
  474. return bResult;
  475. }
  476. if (pidl = SHBrowseForFolder(&bi))
  477. {
  478. if (SHGetPathFromIDList(pidl, buffer))
  479. {
  480. if (_tcslen(buffer) > dwMaxPath)
  481. {
  482. DisplayErrorMessage(hDlg, 0, FAXUI_ERROR_NAME_IS_TOO_LONG);
  483. }
  484. else
  485. {
  486. SetDlgItemText(hDlg, hResource, buffer);
  487. bResult = TRUE;
  488. }
  489. }
  490. pMalloc->lpVtbl->Free(pMalloc, (LPVOID)pidl);
  491. }
  492. pMalloc->lpVtbl->Release(pMalloc);
  493. return bResult;
  494. }
  495. LPTSTR
  496. ValidatePath(
  497. LPTSTR szPath
  498. )
  499. /*++
  500. Routine Description:
  501. Check and remove the '\' at the end of the string
  502. Arguments:
  503. szPath - string pointer
  504. Return Value:
  505. return the new string pointer
  506. --*/
  507. {
  508. DWORD i;
  509. if (szPath == NULL || szPath[0] == 0)
  510. {
  511. return szPath;
  512. }
  513. i = lstrlen(szPath)-1;
  514. for (; i>0; i--)
  515. {
  516. if (szPath[i] == TEXT('\\'))
  517. {
  518. szPath[i] = 0;
  519. }
  520. else
  521. {
  522. break;
  523. }
  524. }
  525. return szPath;
  526. }
  527. PFAX_PORT_INFO_EX
  528. FindPortInfo(
  529. DWORD dwDeviceId
  530. )
  531. /*++
  532. Routine Description:
  533. Find FAX_PORT_INFO_EX by dwDeviceId in g_pFaxPortInfo
  534. Arguments:
  535. dwDeviceId - [in] device ID to find
  536. Return Value:
  537. pointer to FAX_PORT_INFO_EX structure if found
  538. NULL otherwise
  539. --*/
  540. {
  541. DWORD dw;
  542. if(!g_pFaxPortInfo || !g_dwPortsNum)
  543. {
  544. return NULL;
  545. }
  546. for(dw=0; dw < g_dwPortsNum; ++dw)
  547. {
  548. if(g_pFaxPortInfo[dw].dwDeviceID == dwDeviceId)
  549. {
  550. return &g_pFaxPortInfo[dw];
  551. }
  552. }
  553. return NULL;
  554. }
  555. BOOL
  556. CALLBACK
  557. PageEnableProc(
  558. HWND hwnd,
  559. LPARAM lParam
  560. )
  561. /*++
  562. Routine Description:
  563. Disable each control of a property page
  564. Arguments:
  565. hwnd - [in] handle to child window
  566. lParam - [in] BOOL bEnable
  567. Return Value:
  568. TRUE to continue enumeration
  569. --*/
  570. {
  571. EnableWindow(hwnd, (BOOL)lParam);
  572. return TRUE;
  573. }
  574. void
  575. PageEnable(
  576. HWND hDlg,
  577. BOOL bEnable
  578. )
  579. /*++
  580. Routine Description:
  581. Enumerate and enable/disable all controls of a property page
  582. Arguments:
  583. hDlg - [in] property page handle
  584. bEnable - [in] TRUE for enable, FALSE for disable
  585. Return Value:
  586. none
  587. --*/
  588. {
  589. if(!EnumChildWindows(hDlg, PageEnableProc, (LPARAM)bEnable))
  590. {
  591. Error(( "EnumChildWindows failed with %d\n", GetLastError()));
  592. }
  593. }
  594. DWORD
  595. CountUsedFaxDevices()
  596. /*++
  597. Routine Description:
  598. Count the number of the devices configured to send or receive faxes
  599. Arguments:
  600. none
  601. Return Value:
  602. Number of the fax devices
  603. --*/
  604. {
  605. DWORD dw;
  606. DWORD dwNum=0;
  607. if(!g_pFaxPortInfo || !g_dwPortsNum)
  608. {
  609. return dwNum;
  610. }
  611. for(dw=0; dw < g_dwPortsNum; ++dw)
  612. {
  613. if(g_pFaxPortInfo[dw].bSend || (FAX_DEVICE_RECEIVE_MODE_OFF != g_pFaxPortInfo[dw].ReceiveMode))
  614. {
  615. ++dwNum;
  616. }
  617. }
  618. return dwNum;
  619. }
  620. BOOL
  621. IsDeviceInUse(
  622. DWORD dwDeviceId
  623. )
  624. /*++
  625. Routine Description:
  626. Determine whether the device is configured for send or receive
  627. Arguments:
  628. dwDeviceId - [in] Device ID
  629. Return Value:
  630. TRUE if the device is configured for send or receive
  631. FALSE otherwise
  632. --*/
  633. {
  634. PFAX_PORT_INFO_EX pPortInfo = FindPortInfo(dwDeviceId);
  635. if(!pPortInfo)
  636. {
  637. return FALSE;
  638. }
  639. if(pPortInfo->bSend || (FAX_DEVICE_RECEIVE_MODE_OFF != pPortInfo->ReceiveMode))
  640. {
  641. return TRUE;
  642. }
  643. return FALSE;
  644. }