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.

1745 lines
47 KiB

  1. /****************************************************************************
  2. PROGRAM: Telephony Location Manager
  3. PURPOSE:
  4. FUNCTIONS:
  5. ****************************************************************************/
  6. #define STRICT
  7. #include "windows.h"
  8. #include "windowsx.h"
  9. #include "shellapi.h"
  10. #include "prsht.h"
  11. #include "dbt.h"
  12. //#include "stdio.h"
  13. #if WINNT
  14. #else
  15. #include "pbt.h"
  16. #endif
  17. #include "tapi.h"
  18. #include "tapitna.h"
  19. #include "clientr.h"
  20. #include "general.h"
  21. #if DBG
  22. #define DBGOUT(arg) DbgPrt arg
  23. VOID
  24. DbgPrt(
  25. IN DWORD dwDbgLevel,
  26. IN PTCHAR DbgMessage,
  27. IN ...
  28. );
  29. #define DOFUNC(arg1,arg2) DoFunc(arg1,arg2)
  30. #else
  31. #define DBGOUT(arg)
  32. #define DOFUNC(arg1,arg2) DoFunc(arg1)
  33. #endif
  34. int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int );
  35. LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message,
  36. WPARAM wParam, LPARAM lParam);
  37. static BOOL InitApplication( void );
  38. static BOOL InitInstance( void );
  39. static HINSTANCE ghInst;
  40. static HWND ghWnd; /* handle to main window */
  41. static const TCHAR gszConfigMe[] = TEXT("ConfigMe");
  42. LPDWORD lpdwLocationIDs = NULL;
  43. TCHAR buf[356];
  44. TCHAR buf2[356];
  45. int i;
  46. //***************************************************************************
  47. //***************************************************************************
  48. //***************************************************************************
  49. //#define TAPI_API_VERSION 0x00020000
  50. #define TAPI_API_VERSION 0x00010004
  51. //***************************************************************************
  52. extern TCHAR gszCurrentProfileKey[];
  53. extern TCHAR gszStaticProfileKey[];
  54. extern TCHAR gszAutoLaunchKey[];
  55. extern TCHAR gszAutoLaunchValue[];
  56. extern TCHAR gszAutoLocationID[];
  57. extern BOOL GetTranslateCaps( LPLINETRANSLATECAPS FAR * pptc);
  58. //***************************************************************************
  59. // Need to keep tapi initialized so that we can get
  60. // location id changes from Xlate dialog (or lineSetCurrentLocation()...)
  61. HLINEAPP ghLineApp = 0;
  62. //DWORD gdwTapiAPIVersion = 0;
  63. //***************************************************************************
  64. //***************************************************************************
  65. //***************************************************************************
  66. //***************************************************************************
  67. BOOL MachineHasMultipleHWProfiles()
  68. {
  69. DWORD dwDataSize;
  70. DWORD dwDataType;
  71. HKEY hKey;
  72. LONG lResult;
  73. //
  74. // Try to get the friendly name for profile #2. If
  75. // this fails, that means we only have one config,
  76. // so there's no point in confusing the user with
  77. // hotdocking options they can't use...
  78. //
  79. lResult = RegOpenKeyEx(
  80. HKEY_LOCAL_MACHINE,
  81. TEXT("System\\CurrentControlSet\\Control\\IDConfigDB"),
  82. 0,
  83. KEY_READ,
  84. &hKey
  85. );
  86. if (ERROR_SUCCESS == lResult)
  87. {
  88. dwDataSize = sizeof(buf);
  89. lResult = RegQueryValueEx(
  90. hKey,
  91. TEXT("FriendlyName0002"),
  92. 0,
  93. &dwDataType,
  94. (LPBYTE)buf,
  95. &dwDataSize
  96. );
  97. RegCloseKey( hKey );
  98. }
  99. return ( ERROR_SUCCESS == lResult);
  100. }
  101. //***************************************************************************
  102. //***************************************************************************
  103. //***************************************************************************
  104. LONG SaveNewLocation( DWORD dwNewLocation )
  105. {
  106. HKEY hKey;
  107. DWORD dwTemp;
  108. LONG lResult;
  109. //
  110. // Ok, the user wants to change the location
  111. //
  112. DBGOUT((0, TEXT("SaveNewLocation...")));
  113. {
  114. //
  115. // Update the AutoLocationID entry in the current
  116. // profile config
  117. //
  118. lResult = RegCreateKeyEx(
  119. HKEY_CURRENT_CONFIG,
  120. gszCurrentProfileKey,
  121. 0,
  122. TEXT(""),
  123. REG_OPTION_NON_VOLATILE,
  124. KEY_ALL_ACCESS,
  125. NULL,
  126. &hKey,
  127. &dwTemp
  128. );
  129. if ( 0 == lResult )
  130. {
  131. lResult = RegSetValueEx(
  132. hKey,
  133. gszAutoLocationID,
  134. 0,
  135. REG_DWORD,
  136. (LPBYTE)&dwNewLocation,
  137. sizeof(DWORD)
  138. );
  139. RegCloseKey( hKey );
  140. }
  141. }
  142. return lResult;
  143. }
  144. //***************************************************************************
  145. //***************************************************************************
  146. //***************************************************************************
  147. VOID PASCAL TapiCallbackProc( DWORD hDevice, DWORD dwMsg, DWORD dwCallbackInstance,
  148. DWORD dwParam1, DWORD dwParam2, DWORD dwParam3 )
  149. {
  150. TCHAR buf[256];
  151. //{
  152. //char buf[100];
  153. //wsprintf(buf, "dwMsg=0x%08lx dwParam1=0x%08lx dwParam2=0x%08lx dwParam3=0x%08lx",
  154. // dwMsg, dwParam1, dwParam2, dwParam3 );
  155. //MessageBox(GetFocus(), buf, "LINEDEVSTATE", MB_OK);
  156. //}
  157. //
  158. // Since we don't bother doing a negotiate (like, cause if there are no
  159. // devices, we _can't_, so why bother at all?), we use the 1.4 cheat of
  160. // looking at dwParam2 and dwParam3 on a REINIT for the real dwMsg and
  161. // dwParam1
  162. //
  163. if (
  164. (dwMsg == LINE_LINEDEVSTATE)
  165. &&
  166. (dwParam1 == LINEDEVSTATE_REINIT)
  167. )
  168. {
  169. if (
  170. (dwParam2 == LINE_LINEDEVSTATE)
  171. &&
  172. (dwParam3 == LINEDEVSTATE_TRANSLATECHANGE)
  173. )
  174. {
  175. LPLINETRANSLATECAPS ptc;
  176. DBGOUT((0,TEXT("XlateChange!!")));
  177. if ( GetTranslateCaps(&ptc) )
  178. {
  179. SaveNewLocation( ptc->dwCurrentLocationID );
  180. GlobalFreePtr(ptc);
  181. }
  182. }
  183. else
  184. if (
  185. (dwParam2 == 0)
  186. &&
  187. (dwParam3 == 0)
  188. )
  189. {
  190. LONG lResult=1;
  191. UINT nTooManyTries;
  192. DWORD dwNumDevs;
  193. DBGOUT((0,TEXT("Reinit!!")));
  194. lineShutdown( ghLineApp );
  195. LoadString( ghInst,
  196. IDS_CAPTION,
  197. buf,
  198. sizeof(buf) );
  199. for ( nTooManyTries=0;
  200. (nTooManyTries<500) && (lResult != 0);
  201. nTooManyTries++)
  202. {
  203. Sleep(1000);
  204. lResult = lineInitialize( &ghLineApp,
  205. ghInst,
  206. // use the MainWndProc as the callback
  207. // cause we're gonna ignore all of the
  208. // messages anyway...
  209. (LINECALLBACK) TapiCallbackProc,
  210. (LPCSTR) buf,
  211. &dwNumDevs
  212. );
  213. }
  214. }
  215. }
  216. }
  217. //***************************************************************************
  218. //***************************************************************************
  219. //***************************************************************************
  220. void ChangeTapiLocation( UINT nCallersFlag )
  221. {
  222. HKEY hKey;
  223. DWORD dwNewLocationID;
  224. DWORD dwSize = sizeof(dwNewLocationID);
  225. DWORD dwType;
  226. DWORD dwMyFlags = 0;
  227. LONG lResult;
  228. //
  229. // read our flags
  230. //
  231. lResult = RegOpenKeyEx(
  232. HKEY_LOCAL_MACHINE,
  233. gszAutoLaunchKey,
  234. 0,
  235. KEY_ALL_ACCESS,
  236. &hKey
  237. );
  238. if (ERROR_SUCCESS == lResult)
  239. {
  240. RegQueryValueEx(
  241. hKey,
  242. TEXT("AutoLaunchFlags"),
  243. 0,
  244. &dwType,
  245. (LPBYTE)&dwMyFlags,
  246. &dwSize
  247. );
  248. RegCloseKey( hKey );
  249. }
  250. //
  251. // If the user doesn't want to get involved,
  252. // let's get out now.
  253. //
  254. if ( 0 == (dwMyFlags & nCallersFlag) )
  255. {
  256. return;
  257. }
  258. lResult = RegOpenKeyEx(
  259. HKEY_CURRENT_CONFIG,
  260. gszCurrentProfileKey,
  261. 0,
  262. KEY_ALL_ACCESS,
  263. &hKey
  264. );
  265. if ( ERROR_SUCCESS == lResult )
  266. {
  267. dwSize = sizeof(dwNewLocationID);
  268. lResult = RegQueryValueEx(
  269. hKey,
  270. gszAutoLocationID,
  271. 0,
  272. &dwType,
  273. (LPBYTE)&dwNewLocationID,
  274. &dwSize
  275. );
  276. }
  277. #if DBG
  278. else
  279. {
  280. MessageBox( GetFocus(), TEXT("...and there's no key"), TEXT("Config changed"), MB_OK);
  281. }
  282. #endif
  283. //
  284. // Did we find the key\value?
  285. //
  286. if ( ERROR_SUCCESS == lResult )
  287. {
  288. LONG lTranslateCapsResult;
  289. LPLINETRANSLATECAPS ptc;
  290. //
  291. // Ok, the user wants to change the location
  292. //
  293. lTranslateCapsResult = GetTranslateCaps(&ptc);
  294. //
  295. // If the location to be set to is the same as the
  296. // current, do nothing.
  297. //
  298. if ( ptc &&
  299. ptc->dwCurrentLocationID != dwNewLocationID )
  300. {
  301. //
  302. // Check flag - should we confirm with user?
  303. //
  304. if ( dwMyFlags & FLAG_PROMPTAUTOLOCATIONID )
  305. {
  306. }
  307. DBGOUT((0, TEXT("ChangeLocation...")));
  308. lineSetCurrentLocation( ghLineApp, dwNewLocationID );
  309. DBGOUT((0,TEXT("Done.")));
  310. //
  311. // Should we tell the user what we've done?
  312. //
  313. if ( dwMyFlags & FLAG_ANNOUNCEAUTOLOCATIONID )
  314. {
  315. LPTSTR pstrOldLocation = NULL;
  316. LPTSTR pstrNewLocation = NULL;
  317. //FEATUREFEATURE Tell the user from what location and to what location
  318. if ( lTranslateCapsResult )
  319. {
  320. DWORD i;
  321. LPLINELOCATIONENTRY ple;
  322. DWORD dwCurLocID = ptc->dwCurrentLocationID;
  323. DWORD dwNumLocations = ptc->dwNumLocations;
  324. //
  325. // Allocate an array of DWORDs. This will allow us
  326. // to map the menuID to the TAPI perm provider ID.
  327. //
  328. lpdwLocationIDs = GlobalAllocPtr( GMEM_FIXED, sizeof(DWORD)*dwNumLocations );
  329. //
  330. // Put each location in the menu. When we hit the
  331. // "current" location, put a check next to it.
  332. //
  333. ple = (LPLINELOCATIONENTRY)((LPBYTE)ptc + ptc->dwLocationListOffset);
  334. for (i = 0; i < dwNumLocations; i++, ple++)
  335. {
  336. if (ptc->dwCurrentLocationID ==
  337. ple->dwPermanentLocationID)
  338. {
  339. pstrOldLocation = (LPTSTR)((LPBYTE)ptc +
  340. ple->dwLocationNameOffset);
  341. }
  342. if (dwNewLocationID ==
  343. ple->dwPermanentLocationID)
  344. {
  345. pstrNewLocation = (LPTSTR)((LPBYTE)ptc +
  346. ple->dwLocationNameOffset);
  347. }
  348. }
  349. }
  350. //
  351. // If the location has since been deleted, we should
  352. // say something about it.
  353. //
  354. if (
  355. (NULL == pstrOldLocation)
  356. ||
  357. (NULL == pstrNewLocation)
  358. )
  359. {
  360. LoadString( ghInst,
  361. IDS_CANTFINDLOCATIONID,
  362. buf2,
  363. sizeof(buf2) );
  364. wsprintf( buf,
  365. buf2,
  366. dwNewLocationID
  367. );
  368. }
  369. else
  370. {
  371. LoadString( ghInst,
  372. IDS_LOCATIONCHANGED,
  373. buf2,
  374. sizeof(buf2) );
  375. wsprintf( buf,
  376. buf2,
  377. pstrOldLocation,
  378. pstrNewLocation );
  379. }
  380. // We're done using buf2, so reuse it.
  381. LoadString( ghInst,
  382. IDS_CAPTION,
  383. buf2,
  384. sizeof(buf2) );
  385. MessageBox(
  386. NULL, //GetFocus(),
  387. buf,
  388. buf2, // caption
  389. MB_OK
  390. );
  391. }
  392. GlobalFreePtr(ptc);
  393. }
  394. }
  395. else
  396. {
  397. #if DBG
  398. MessageBox( GetFocus(), TEXT("...and there's no key (or value)"), TEXT("Config changed"), MB_OK);
  399. #endif
  400. }
  401. }
  402. //***************************************************************************
  403. //***************************************************************************
  404. //***************************************************************************
  405. PTSTR SkipSpaces( PTSTR const ptStr )
  406. {
  407. PTSTR pStr = ptStr;
  408. while ( *pStr && (*pStr == ' ' ) )
  409. {
  410. pStr++;
  411. }
  412. return pStr;
  413. }
  414. //***************************************************************************
  415. //***************************************************************************
  416. //***************************************************************************
  417. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  418. LPSTR lpCmdLine, int nCmdShow)
  419. {
  420. MSG msg;
  421. // int nResult = 1;
  422. // UINT nSwitchLen;
  423. TCHAR *pCommandLine;
  424. TCHAR *pCommandLineSave;
  425. // TCHAR *pLastStart;
  426. DWORD dwParmLocationID;
  427. LONG lResult;
  428. BOOL fDieNow = FALSE;
  429. DWORD dwCommandLineLength;
  430. TCHAR buf[256];
  431. DBGOUT((0, TEXT("Main...")));
  432. ghInst = GetModuleHandle(0);
  433. if (InitApplication() == 0)
  434. {
  435. return (FALSE);
  436. }
  437. if (InitInstance() == 0)
  438. {
  439. return (FALSE);
  440. }
  441. {
  442. DWORD dwNumDevs;
  443. LoadString( ghInst,
  444. IDS_CAPTION,
  445. buf,
  446. sizeof(buf) );
  447. //
  448. // We initialize TAPI and we never shutdown (except to reinit) so
  449. // we get notifications if someone changes the location from
  450. // the Dialing Properties dialog.
  451. //
  452. lineInitialize( &ghLineApp,
  453. ghInst,
  454. // use the MainWndProc as the callback
  455. // cause we're gonna ignore all of the
  456. // messages anyway...
  457. (LINECALLBACK) TapiCallbackProc,
  458. (LPCSTR) buf,
  459. &dwNumDevs
  460. );
  461. }
  462. //----------------------
  463. // //
  464. // // If the user wants it, startup in the config dialog
  465. // // But we'll only do this if there is more than one HW config...
  466. // //
  467. // if ( MachineHasMultipleHWProfiles() )
  468. // {
  469. // //
  470. // // (We do a bunch of stuff "manually" here so we don't have to
  471. // // drag in the entire MSVCRT20 for this one function...)
  472. // //
  473. // nSwitchLen = lstrlen(gszConfigMe);
  474. //
  475. // //
  476. // // 'pLastStart' is the last possible char the string could start on
  477. // //
  478. // pLastStart = pCommandLine + 1 + (lstrlen(pCommandLine) - nSwitchLen);
  479. //
  480. // for ( ; pCommandLine < pLastStart; pCommandLine++)
  481. // {
  482. // //
  483. // // Do a hack so we can use lstrcmpi
  484. // //
  485. // TCHAR c;
  486. //
  487. // c = pCommandLine[nSwitchLen];
  488. // pCommandLine[nSwitchLen] = '\0';
  489. //
  490. // nResult = lstrcmpi( (LPSTR)pCommandLine, gszConfigMe );
  491. //
  492. // pCommandLine[nSwitchLen] = c;
  493. //
  494. // if (0 == nResult)
  495. // {
  496. // break;
  497. // }
  498. // }
  499. //
  500. // //
  501. // // Did we find our string?
  502. // //
  503. // if ( 0 == nResult )
  504. // {
  505. // PostMessage(ghWnd, WM_COMMAND, IDM_PROPERTIES, 0);
  506. // }
  507. // }
  508. //----------------------
  509. dwCommandLineLength = (lstrlen( GetCommandLine() ) + 1) * sizeof(TCHAR);
  510. pCommandLine = LocalAlloc( LPTR, dwCommandLineLength );
  511. pCommandLineSave = pCommandLine; // We'll need this later to free it...
  512. lstrcpy( pCommandLine, GetCommandLine() );
  513. while ( *pCommandLine )
  514. {
  515. //
  516. // Is this an arg?
  517. //
  518. if (
  519. ('-' == *pCommandLine)
  520. ||
  521. ('/' == *pCommandLine)
  522. )
  523. {
  524. TCHAR c;
  525. //
  526. // Figger out what the arg is
  527. //
  528. pCommandLine = SkipSpaces( pCommandLine + 1 );
  529. //
  530. // Just looking?
  531. //
  532. if (
  533. ('?' == *pCommandLine)
  534. ||
  535. ('H' == *pCommandLine)
  536. ||
  537. ('h' == *pCommandLine)
  538. )
  539. {
  540. LoadString( ghInst,
  541. IDS_HELP,
  542. buf,
  543. sizeof(buf) );
  544. LoadString( ghInst,
  545. IDS_CAPTION,
  546. buf2,
  547. sizeof(buf2) );
  548. MessageBox(GetFocus(), buf, buf2, MB_OK);
  549. // MessageBox(NULL, buf, buf2, MB_OK);
  550. //
  551. // Ok, now that we're leaving, we can shut this down...
  552. //
  553. fDieNow = TRUE;
  554. }
  555. //
  556. // Is this a location die-now request?
  557. //
  558. if (
  559. ('X' == *pCommandLine)
  560. ||
  561. ('x' == *pCommandLine)
  562. )
  563. {
  564. fDieNow = TRUE;
  565. }
  566. //
  567. // Is this a location ID?
  568. //
  569. if (
  570. ('I' == *pCommandLine)
  571. ||
  572. ('i' == *pCommandLine)
  573. )
  574. {
  575. pCommandLine = SkipSpaces( pCommandLine + 1 );
  576. dwParmLocationID = 0;
  577. //
  578. // get digits
  579. //
  580. while (
  581. (*pCommandLine >= '0')
  582. &&
  583. (*pCommandLine <= '9')
  584. )
  585. {
  586. dwParmLocationID = ( dwParmLocationID * 10 ) +
  587. (*pCommandLine - '0');
  588. pCommandLine++;
  589. }
  590. //
  591. // Now set the current location to the ID we just gathered
  592. //
  593. lResult = lineSetCurrentLocation( ghLineApp, dwParmLocationID );
  594. if ( 0 == lResult )
  595. lResult = SaveNewLocation( dwParmLocationID );
  596. if ( 0 != lResult )
  597. {
  598. LoadString( ghInst,
  599. IDS_CANTFINDLOCATIONID,
  600. buf2,
  601. sizeof(buf2) );
  602. wsprintf( buf, buf2, dwParmLocationID);
  603. LoadString( ghInst,
  604. IDS_CAPTION,
  605. buf2,
  606. sizeof(buf2) );
  607. //
  608. // Messagebox to tell the user what happened
  609. //
  610. MessageBox(
  611. NULL,
  612. buf,
  613. buf2,
  614. MB_OK | MB_ICONERROR
  615. );
  616. }
  617. }
  618. //
  619. // Is this a location name?
  620. //
  621. if (
  622. ('N' == *pCommandLine)
  623. ||
  624. ('n' == *pCommandLine)
  625. )
  626. {
  627. LPLINETRANSLATECAPS ptc;
  628. PTSTR pszMyString;
  629. PTSTR pszMyStringPointer;
  630. pCommandLine = SkipSpaces( pCommandLine + 1 );
  631. //
  632. // We'll never need more than the entire command line's len...
  633. // (and that's better than some arbitraty large number)
  634. //
  635. pszMyString = LocalAlloc( LPTR, dwCommandLineLength );
  636. if (pszMyString == NULL)
  637. {
  638. return (FALSE);
  639. }
  640. pszMyStringPointer = pszMyString;
  641. pCommandLine = SkipSpaces( pCommandLine );
  642. while (
  643. (*pCommandLine != '\0')
  644. &&
  645. (*pCommandLine != '/')
  646. &&
  647. (*pCommandLine != '-')
  648. )
  649. {
  650. //
  651. // add this char to the string
  652. //
  653. *pszMyStringPointer = *pCommandLine;
  654. pszMyStringPointer++;
  655. pCommandLine++;
  656. }
  657. //
  658. // First, get back to the last char
  659. //
  660. pszMyStringPointer--;
  661. //
  662. // Now chop off any trailing spaces
  663. //
  664. while (
  665. (' ' == *pszMyStringPointer)
  666. &&
  667. (pszMyStringPointer > pszMyString )
  668. )
  669. {
  670. pszMyStringPointer--;
  671. }
  672. //
  673. // Set the end of the string to be the last non-space in the name
  674. //
  675. *(pszMyStringPointer + 1) = '\0';
  676. if (GetTranslateCaps(&ptc))
  677. {
  678. DWORD i;
  679. LPLINELOCATIONENTRY ple;
  680. DWORD dwCurLocID = ptc->dwCurrentLocationID;
  681. DWORD dwNumLocations = ptc->dwNumLocations;
  682. DBGOUT((0, TEXT("There seem to be %ld locations - ptc=0x%08lx"), dwNumLocations,
  683. ptc));
  684. //
  685. // See if we can find the string...
  686. //
  687. ple = (LPLINELOCATIONENTRY)((LPBYTE)ptc + ptc->dwLocationListOffset);
  688. for (i = 0; i < dwNumLocations; i++, ple++)
  689. {
  690. DBGOUT((0, TEXT("Location #%ld is [%s] at 0x%08lx"),
  691. i,
  692. (LPTSTR)((LPBYTE)ptc + ple->dwLocationNameOffset),
  693. (LPTSTR)((LPBYTE)ptc + ple->dwLocationNameOffset) ));
  694. if ( 0 == lstrcmpi( (LPTSTR)((LPBYTE)ptc + ple->dwLocationNameOffset),
  695. pszMyString
  696. )
  697. )
  698. {
  699. dwParmLocationID = ple->dwPermanentLocationID;
  700. break;
  701. }
  702. }
  703. //
  704. // Did we run the list without finding a match?
  705. //
  706. if ( i == dwNumLocations )
  707. {
  708. LoadString( ghInst,
  709. IDS_CANTFINDLOCATIONNAME,
  710. buf2,
  711. sizeof(buf2) );
  712. wsprintf( buf, buf2, pszMyString );
  713. LoadString( ghInst,
  714. IDS_CAPTION,
  715. buf2,
  716. sizeof(buf2) );
  717. //
  718. // Messagebox to tell the user what happened
  719. //
  720. MessageBox(
  721. NULL,
  722. buf,
  723. buf2,
  724. MB_OK | MB_ICONERROR
  725. );
  726. lResult = LINEERR_INVALLOCATION;
  727. }
  728. else
  729. {
  730. lResult = lineSetCurrentLocation( ghLineApp, dwParmLocationID );
  731. if ( 0 == lResult )
  732. lResult = SaveNewLocation( dwParmLocationID );
  733. }
  734. GlobalFreePtr(ptc);
  735. LocalFree( pszMyString );
  736. }
  737. }
  738. //
  739. // Is this parm "ConfigMe" ?
  740. //
  741. c = pCommandLine[ lstrlen( gszConfigMe ) ];
  742. if ( 0 == lstrcmpi( pCommandLine, gszConfigMe ) )
  743. {
  744. //
  745. // Found this arg.
  746. //
  747. //
  748. // If the user wants it, startup in the config dialog
  749. // But we'll only do this if there is more than one HW config...
  750. //
  751. if ( MachineHasMultipleHWProfiles() )
  752. {
  753. PostMessage( ghWnd, WM_COMMAND, IDM_PROPERTIES, 0 );
  754. }
  755. //
  756. // In either case, get past this arg
  757. //
  758. pCommandLine[ lstrlen( gszConfigMe ) ] = c;
  759. pCommandLine += lstrlen( gszConfigMe );
  760. }
  761. }
  762. else
  763. {
  764. pCommandLine++;
  765. }
  766. }
  767. LocalFree( pCommandLineSave );
  768. //
  769. // Go see if we should auto-update the TAPI location on startup
  770. //
  771. ChangeTapiLocation( FLAG_UPDATEONSTARTUP );
  772. //
  773. // Should we quit before we start?
  774. //
  775. if ( fDieNow )
  776. {
  777. DestroyWindow( ghWnd );
  778. }
  779. while (GetMessage(&msg, 0, 0, 0) != 0)
  780. {
  781. TranslateMessage(&msg);
  782. DispatchMessage(&msg);
  783. }
  784. //
  785. // Ok, now that we're leaving, we can shut this down...
  786. lineShutdown( ghLineApp );
  787. return ((int) msg.wParam);
  788. }
  789. /****************************************************************************
  790. FUNCTION: InitApplication(HANDLE)
  791. PURPOSE: Initializes window data and registers window class
  792. ****************************************************************************/
  793. static BOOL InitApplication( void )
  794. {
  795. WNDCLASS wc;
  796. wc.style = 0;
  797. wc.lpfnWndProc = MainWndProc;
  798. wc.cbClsExtra = 0;
  799. wc.cbWndExtra = 0;
  800. wc.hInstance = ghInst;
  801. wc.hIcon = NULL;
  802. wc.hCursor = NULL;
  803. wc.hbrBackground = NULL;
  804. wc.lpszMenuName = NULL;
  805. wc.lpszClassName = TEXT("TLOCMGR_WINCLSS");
  806. return (RegisterClass(&wc));
  807. }
  808. //***************************************************************************
  809. //***************************************************************************
  810. //***************************************************************************
  811. static BOOL InitInstance( void )
  812. {
  813. ghWnd = CreateWindow(
  814. TEXT("TLOCMGR_WINCLSS"),
  815. NULL,
  816. WS_OVERLAPPED | WS_MINIMIZE,
  817. CW_USEDEFAULT,
  818. CW_USEDEFAULT,
  819. CW_USEDEFAULT,
  820. CW_USEDEFAULT,
  821. 0,
  822. 0,
  823. ghInst,
  824. 0 );
  825. if (ghWnd == 0 )
  826. {
  827. return ( FALSE );
  828. }
  829. ShowWindow(ghWnd, SW_HIDE);
  830. #if WINNT
  831. #else
  832. RegisterServiceProcess( 0, RSP_SIMPLE_SERVICE);
  833. #endif
  834. return (TRUE);
  835. }
  836. //***************************************************************************
  837. //***************************************************************************
  838. //***************************************************************************
  839. LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message,
  840. WPARAM wParam, LPARAM lParam)
  841. {
  842. HICON hIcon;
  843. static DWORD dwCurrentChoice = 0;
  844. DWORD i;
  845. static NOTIFYICONDATA nid = {
  846. sizeof(NOTIFYICONDATA),
  847. 0, //hWnd,
  848. IDI_TAPITNAICON,
  849. NIF_ICON | NIF_MESSAGE | NIF_TIP,
  850. WM_USER+0x42,
  851. 0, //hIcon,
  852. 0 //pCaption
  853. };
  854. switch ( message )
  855. {
  856. #if WINNT
  857. case WM_POWER:
  858. {
  859. if (
  860. (PWR_SUSPENDRESUME == LOWORD(wParam))
  861. ||
  862. (PWR_CRITICALRESUME == LOWORD(wParam))
  863. )
  864. {
  865. DBGOUT((0, TEXT("Power resume(normal or critical)")));
  866. ChangeTapiLocation( FLAG_UPDATEONSTARTUP );
  867. }
  868. }
  869. break;
  870. #else
  871. case WM_POWERBROADCAST:
  872. {
  873. if (
  874. (PBT_APMRESUMESUSPEND == wParam)
  875. ||
  876. (PBT_APMRESUMESTANDBY == wParam)
  877. ||
  878. (PBT_APMRESUMECRITICAL == wParam)
  879. )
  880. {
  881. DBGOUT((0, TEXT("Power resume(normal or critical)")));
  882. ChangeTapiLocation( FLAG_UPDATEONSTARTUP );
  883. }
  884. }
  885. break;
  886. #endif
  887. case WM_DEVICECHANGE:
  888. {
  889. switch (wParam)
  890. {
  891. // case DBT_DEVICEARRIVAL:
  892. //MessageBox( GetFocus(), "DBT_DEVICEARRIVAL", "WM_DEVICECHANGE", MB_OK);
  893. // break;
  894. //
  895. // case DBT_DEVICEREMOVECOMPLETE:
  896. //MessageBox( GetFocus(), "DBT_DEVICEREMOVECOMPLETE", "WM_DEVICECHANGE", MB_OK);
  897. // break;
  898. //
  899. // case DBT_MONITORCHANGE:
  900. //MessageBox( GetFocus(), "DBT_MONITORCHANGE", "WM_DEVICECHANGE", MB_OK);
  901. //// lParam = new resolution LOWORD=x HIWORD=y
  902. // break;
  903. case DBT_CONFIGCHANGED:
  904. {
  905. DBGOUT((0, TEXT("DBG_CONFIGCHANGED")));
  906. ChangeTapiLocation( FLAG_AUTOLOCATIONID );
  907. }
  908. break;
  909. }
  910. }
  911. break;
  912. case WM_SETTINGCHANGE:
  913. {
  914. //
  915. // Is it something we're interested in?
  916. //
  917. // if ( SPI_SETICONMETRICS == wParam )
  918. {
  919. // hIcon = LoadImage(ghInst,
  920. // MAKEINTRESOURCE(IDI_TAPITNAICON),
  921. // IMAGE_ICON,
  922. // GetSystemMetrics(SM_CXSMICON),
  923. // GetSystemMetrics(SM_CYSMICON),
  924. // 0);
  925. hIcon = LoadImage(ghInst,
  926. MAKEINTRESOURCE(IDI_TAPITNAICON),
  927. IMAGE_ICON,
  928. 0,
  929. 0,
  930. 0);
  931. Shell_NotifyIcon( NIM_MODIFY, &nid );
  932. return 0;
  933. }
  934. // else
  935. // {
  936. // return (DefWindowProc(hWnd, message, wParam, lParam));
  937. // }
  938. }
  939. // break;
  940. case WM_CREATE:
  941. {
  942. //
  943. // Well, we're not gonna create a window, but we can do other
  944. // stuff...
  945. //
  946. LoadString (ghInst, IDS_CAPTION, nid.szTip, sizeof (nid.szTip));
  947. // hIcon = LoadIcon(ghInst, MAKEINTRESOURCE(IDI_TAPITNAICON) );
  948. hIcon = LoadImage(ghInst,
  949. MAKEINTRESOURCE(IDI_TAPITNAICON),
  950. IMAGE_ICON,
  951. 0,
  952. 0,
  953. // GetSystemMetrics(SM_CXSMICON),
  954. // GetSystemMetrics(SM_CYSMICON),
  955. 0);
  956. // IMAGE_ICON, 32, 32, 0);
  957. // IMAGE_ICON, 16, 16, 0);
  958. nid.hWnd = hWnd;
  959. nid.hIcon = hIcon;
  960. // fResult =
  961. Shell_NotifyIcon( NIM_ADD, &nid );
  962. }
  963. break;
  964. case WM_USER+0x42:
  965. {
  966. switch ( lParam )
  967. {
  968. case WM_LBUTTONDOWN:
  969. {
  970. switch ( wParam )
  971. {
  972. case IDI_TAPITNAICON:
  973. {
  974. //
  975. // User is left clicking on our icon.
  976. //
  977. PostMessage(hWnd, WM_COMMAND, IDM_LOCATIONMENU, 0L);
  978. }
  979. break;
  980. default:
  981. break;
  982. }
  983. }
  984. break;
  985. case WM_LBUTTONDBLCLK:
  986. {
  987. PostMessage(hWnd, WM_COMMAND, IDM_DIALINGPROPERTIES, 0L);
  988. }
  989. break;
  990. case WM_RBUTTONDOWN:
  991. {
  992. switch ( wParam )
  993. {
  994. case IDI_TAPITNAICON:
  995. {
  996. //
  997. // User is right clicking on our icon. Now what?
  998. //
  999. //MessageBox(GetFocus(), "RCLICK", "RCLICK", MB_OK);
  1000. PostMessage(hWnd, WM_COMMAND, IDM_CONTEXTMENU, 0L);
  1001. }
  1002. break;
  1003. default:
  1004. break;
  1005. }
  1006. }
  1007. break;
  1008. default:
  1009. break;
  1010. }
  1011. }
  1012. break;
  1013. case WM_COMMAND:
  1014. switch ( wParam )
  1015. {
  1016. case IDM_ABOUT:
  1017. {
  1018. LoadString(ghInst, IDS_CAPTION, buf, sizeof(buf));
  1019. LoadString(ghInst, IDS_ABOUTTEXT, buf2, sizeof(buf2));
  1020. hIcon = LoadIcon(ghInst, MAKEINTRESOURCE(IDI_TAPITNAICON) );
  1021. return ShellAbout(hWnd, buf, buf2, hIcon);
  1022. }
  1023. break;
  1024. case IDM_CONTEXTMENU:
  1025. {
  1026. HMENU popup;
  1027. HMENU subpopup;
  1028. POINT mousepos;
  1029. popup = LoadMenu(ghInst,MAKEINTRESOURCE(IDR_RBUTTONMENU));
  1030. if(popup)
  1031. {
  1032. //
  1033. // So? Is there more than one config?
  1034. //
  1035. if ( !MachineHasMultipleHWProfiles() )
  1036. {
  1037. //
  1038. // Nope, remove the hotdock options. :-(
  1039. //
  1040. RemoveMenu( popup,
  1041. IDM_PROPERTIES,
  1042. MF_BYCOMMAND
  1043. );
  1044. }
  1045. subpopup = GetSubMenu(popup, 0);
  1046. if (subpopup)
  1047. {
  1048. SetMenuDefaultItem(subpopup,IDM_DIALINGPROPERTIES,FALSE);
  1049. if(GetCursorPos(&mousepos))
  1050. {
  1051. SetForegroundWindow(ghWnd);
  1052. ShowWindow(ghWnd, SW_HIDE);
  1053. TrackPopupMenuEx( subpopup,
  1054. TPM_LEFTALIGN |
  1055. TPM_LEFTBUTTON |
  1056. TPM_RIGHTBUTTON,
  1057. mousepos.x,
  1058. mousepos.y,
  1059. ghWnd,
  1060. NULL
  1061. );
  1062. }
  1063. RemoveMenu(popup, 0, MF_BYPOSITION);
  1064. DestroyMenu(subpopup);
  1065. }
  1066. DestroyMenu(popup);
  1067. }
  1068. }
  1069. break;
  1070. case IDM_LOCATIONMENU:
  1071. {
  1072. HMENU fakepopup = NULL;
  1073. POINT mousepos;
  1074. LPLINETRANSLATECAPS ptc;
  1075. UINT nPrefixSize;
  1076. fakepopup = CreatePopupMenu();
  1077. nPrefixSize = LoadString( ghInst,
  1078. IDS_SELECTNEWLOCATION,
  1079. buf,
  1080. sizeof(buf) );
  1081. // AppendMenu( fakepopup,
  1082. // MF_BYPOSITION | MF_STRING | MF_DISABLED, // | MF_GRAYED,
  1083. // 0,
  1084. // buf
  1085. // );
  1086. //
  1087. // AppendMenu( fakepopup,
  1088. // MF_BYPOSITION | MF_STRING | MF_SEPARATOR,
  1089. // 0,
  1090. // 0
  1091. // );
  1092. if (GetTranslateCaps(&ptc))
  1093. {
  1094. LPLINELOCATIONENTRY ple;
  1095. DWORD dwCurLocID = ptc->dwCurrentLocationID;
  1096. DWORD dwNumLocations = ptc->dwNumLocations;
  1097. DBGOUT((0, TEXT("There seem to be %ld locations - ptc=0x%08lx"), dwNumLocations,
  1098. ptc));
  1099. //
  1100. // Allocate an array of DWORDs. This will allow us
  1101. // to map the menuID to the TAPI perm provider ID.
  1102. //
  1103. lpdwLocationIDs = GlobalAllocPtr( GMEM_FIXED, sizeof(DWORD)*dwNumLocations );
  1104. //
  1105. // Put each location in the menu. When we hit the
  1106. // "current" location, put a check next to it.
  1107. //
  1108. ple = (LPLINELOCATIONENTRY)((LPBYTE)ptc + ptc->dwLocationListOffset);
  1109. for (i = 0; i < dwNumLocations; i++, ple++)
  1110. {
  1111. lpdwLocationIDs[i] = ple->dwPermanentLocationID;
  1112. //
  1113. // Now make a proper displayable string
  1114. lstrcpy( &buf[nPrefixSize],
  1115. (LPTSTR)((LPBYTE)ptc + ple->dwLocationNameOffset)
  1116. );
  1117. AppendMenu( fakepopup,
  1118. MF_BYPOSITION |
  1119. MF_STRING |
  1120. MF_ENABLED |
  1121. ((dwCurLocID == ple->dwPermanentLocationID) ?
  1122. MF_CHECKED : 0),
  1123. IDM_LOCATION0+i,
  1124. buf
  1125. );
  1126. DBGOUT((0, TEXT("Location #%ld is [%s] at 0x%08lx"),
  1127. i,
  1128. (LPTSTR)((LPBYTE)ptc + ple->dwLocationNameOffset),
  1129. (LPTSTR)((LPBYTE)ptc + ple->dwLocationNameOffset) ));
  1130. if (dwCurLocID == ple->dwPermanentLocationID)
  1131. {
  1132. dwCurrentChoice = IDM_LOCATION0+i;
  1133. }
  1134. }
  1135. GlobalFreePtr(ptc);
  1136. }
  1137. else
  1138. {
  1139. DBGOUT((0, TEXT("Gettranscaps failed")));
  1140. }
  1141. if (fakepopup)
  1142. {
  1143. // SetMenuDefaultItem(fakepopup,0,MF_BYPOSITION);
  1144. GetCursorPos(&mousepos);
  1145. SetForegroundWindow(ghWnd);
  1146. ShowWindow(ghWnd, SW_HIDE);
  1147. TrackPopupMenu(fakepopup, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON , mousepos.x, mousepos.y-20, 0, ghWnd, NULL);
  1148. DestroyMenu(fakepopup);
  1149. }
  1150. // {
  1151. // subpopup = GetSubMenu(fakepopup, 0);
  1152. //
  1153. // //put a check next to the current location
  1154. //
  1155. // SetMenuDefaultItem(subpopup,0,MF_BYPOSITION);
  1156. // if(GetCursorPos(&mousepos))
  1157. // {
  1158. // SetForegroundWindow(ghWnd);
  1159. // TrackPopupMenuEx(subpopup, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON ,mousepos.x,mousepos.y,ghWnd,NULL);
  1160. // }
  1161. // RemoveMenu(popup, 0, MF_BYPOSITION);
  1162. // DestroyMenu(fakepopup);
  1163. // DestroyMenu(popup);
  1164. // DestroyMenu(subpopup);
  1165. // }
  1166. }
  1167. break;
  1168. case IDM_DIALINGPROPERTIES:
  1169. {
  1170. {
  1171. lineTranslateDialog(ghLineApp, 0, TAPI_API_VERSION, ghWnd, NULL);
  1172. ShowWindow( ghWnd, SW_HIDE );
  1173. // lineTranslateDialog(ghLineApp, 0, TAPI_API_VERSION, GetFocus(), NULL);
  1174. }
  1175. }
  1176. break;
  1177. case IDM_PROPERTIES:
  1178. {
  1179. #ifdef NASHVILLE_BUILD_FLAG
  1180. // Should we just hack into the TAPI dialing properties?
  1181. #else
  1182. HPROPSHEETPAGE rPages[1];
  1183. PROPSHEETPAGE psp;
  1184. PROPSHEETHEADER psh;
  1185. //
  1186. // Let's configure TAPITNA
  1187. //
  1188. psh.dwSize = sizeof(psh);
  1189. psh.dwFlags = PSH_DEFAULT; //PSH_NOAPPLYNOW;
  1190. psh.hwndParent = GetFocus(); //NULL; //hwnd;
  1191. psh.hInstance = ghInst;
  1192. LoadString(ghInst, IDS_CAPTION, buf, sizeof(buf)/sizeof(TCHAR));
  1193. psh.pszCaption = buf;
  1194. psh.nPages = 0;
  1195. psh.nStartPage = 0;
  1196. psh.phpage = rPages;
  1197. psp.dwSize = sizeof(psp);
  1198. psp.dwFlags = PSP_DEFAULT;
  1199. psp.hInstance = ghInst;
  1200. psp.pszTemplate = MAKEINTRESOURCE(IDD_GENERAL);
  1201. psp.pfnDlgProc = GeneralDlgProc;
  1202. psp.lParam = 0;
  1203. psh.phpage[psh.nPages] = CreatePropertySheetPage (&psp);
  1204. if (psh.phpage[psh.nPages])
  1205. {
  1206. psh.nPages++;
  1207. }
  1208. PropertySheet (&psh);
  1209. #endif
  1210. }
  1211. break;
  1212. // case IDM_OTHERMENUITEM:
  1213. // {
  1214. // }
  1215. // break;
  1216. case IDM_LAUNCHDIALER:
  1217. {
  1218. ShellExecute( ghWnd,
  1219. NULL,
  1220. TEXT("Dialer.exe"),
  1221. NULL,
  1222. NULL,
  1223. SW_SHOWDEFAULT);
  1224. }
  1225. break;
  1226. case IDM_CLOSEIT:
  1227. {
  1228. DestroyWindow(ghWnd);
  1229. }
  1230. break;
  1231. default:
  1232. {
  1233. //
  1234. // Ok, we actually have to do work in this default.
  1235. // If the user has the location menu open and selects one,
  1236. // we deal with it here (instead of having 100 case
  1237. // statements). This is the limitation: 100 locations is
  1238. // the max we put up with (would that many even display?).
  1239. //
  1240. if (
  1241. (wParam >= IDM_LOCATION0)
  1242. &&
  1243. (wParam <= IDM_LOCATION0 + 100)
  1244. )
  1245. {
  1246. //
  1247. // Ok, set this to be the new current location
  1248. //
  1249. // there's a bug in TAPI - either the docs or the code, but the following
  1250. // _should_ work but doesn't...
  1251. // lineSetCurrentLocation(NULL, currentlocation);
  1252. //
  1253. // If the user is selecting the same location,
  1254. // do nothing.
  1255. //
  1256. if ( dwCurrentChoice == wParam )
  1257. {
  1258. }
  1259. else
  1260. {
  1261. i = lineSetCurrentLocation( ghLineApp,
  1262. lpdwLocationIDs[wParam-IDM_LOCATION0] );
  1263. if ( 0 == i )
  1264. SaveNewLocation( lpdwLocationIDs[wParam-IDM_LOCATION0] );
  1265. }
  1266. GlobalFreePtr( lpdwLocationIDs );
  1267. return( TRUE );
  1268. }
  1269. else
  1270. {
  1271. return (DefWindowProc(hWnd, message, wParam, lParam));
  1272. }
  1273. }
  1274. break;
  1275. }
  1276. break;
  1277. case WM_DESTROY:
  1278. Shell_NotifyIcon( NIM_DELETE, &nid );
  1279. PostQuitMessage(0);
  1280. break;
  1281. #if WINNT
  1282. #else
  1283. case WM_ENDSESSION:
  1284. if (wParam) {
  1285. RegisterServiceProcess( 0, RSP_UNREGISTER_SERVICE);
  1286. DestroyWindow(hWnd);
  1287. }
  1288. #endif
  1289. default:
  1290. return (DefWindowProc(hWnd, message, wParam, lParam));
  1291. }
  1292. return (FALSE);
  1293. }
  1294. //{
  1295. //char buf[100];
  1296. //wsprintf(buf, "GetActiveWindwow() = 0x%08lx", (DWORD) GetActiveWindow());
  1297. //OutputDebugString(buf);
  1298. //}
  1299. //{
  1300. //char buf[60];
  1301. //wsprintf (buf, "fResult = 0x%08lx",
  1302. // fResult);
  1303. //MessageBox(GetFocus(), buf, "", MB_OK);
  1304. //}
  1305. #if DBG
  1306. #include "stdarg.h"
  1307. #include "stdio.h"
  1308. VOID
  1309. DbgPrt(
  1310. IN DWORD dwDbgLevel,
  1311. IN PTCHAR lpszFormat,
  1312. IN ...
  1313. )
  1314. /*++
  1315. Routine Description:
  1316. Formats the incoming debug message & calls DbgPrint
  1317. Arguments:
  1318. DbgLevel - level of message verboseness
  1319. DbgMessage - printf-style format string, followed by appropriate
  1320. list of arguments
  1321. Return Value:
  1322. --*/
  1323. {
  1324. static DWORD gdwDebugLevel = 0; //HACKHACK
  1325. if (dwDbgLevel <= gdwDebugLevel)
  1326. {
  1327. TCHAR buf[256] = TEXT("TLOCMGR: ");
  1328. va_list ap;
  1329. va_start(ap, lpszFormat);
  1330. wvsprintf (&buf[8],
  1331. lpszFormat,
  1332. ap
  1333. );
  1334. lstrcat(buf, TEXT("\n"));
  1335. OutputDebugString(buf);
  1336. va_end(ap);
  1337. }
  1338. }
  1339. #endif