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.

1122 lines
38 KiB

  1. //-----------------------------------------------------------------------------
  2. // This exe runs in the background and wakes up every so often to do it's work.
  3. // When it wakes up it checks to see how much time the user has left on their
  4. // free ISP subscription. At certain intervals it will tell the user time
  5. // is running out and will give the user the chance to signup for rea.
  6. //-----------------------------------------------------------------------------
  7. #define STRICT
  8. #include <windows.h>
  9. #include <stdlib.h>
  10. #include <stdarg.h>
  11. #include <crtdbg.h>
  12. #include <winbase.h>
  13. #include <ras.h>
  14. #include <time.h>
  15. #include "IcwRmind.h"
  16. #include "resource.h"
  17. #include "RegData.h"
  18. //-----------------------------------------------------------------------------
  19. // Forward Declarations
  20. //-----------------------------------------------------------------------------
  21. BOOL InitializeApp (void);
  22. BOOL CheckForRASConnection();
  23. void CheckForSignupAttempt();
  24. int GetISPTrialDaysLeft();
  25. void ShutDownForGood();
  26. void PerformTheSignup();
  27. void CenterTheWindow(HWND hWnd);
  28. DWORD GetTickDelta();
  29. void AttemptTrialOverSignup();
  30. //-----------------------------------------------------------------------------
  31. // Defines
  32. //-----------------------------------------------------------------------------
  33. #define TIMER_DIALOG_STAYUP 319 // Wake up timer to do work.
  34. #define TIMER_RUNONCE_SETUP 320
  35. #define TIME_RUNONCE_INTERVAL 30000 // 30 seconds
  36. #define MAXRASCONNS 8
  37. #define MAX_DIALOGTEXT 512
  38. #define MAX_ATTEMPTCOUNTER 20
  39. #define LONG_WAKEUP_INTERVAL 3600000 // 1 hour
  40. //-----------------------------------------------------------------------------
  41. // Global Handles and other defines
  42. //-----------------------------------------------------------------------------
  43. HINSTANCE g_hModule; // Process Instance handle
  44. HWND g_hwndMain; // Main window handle
  45. bool g_bDoNotRemindAgain; // Used by signup dialog.
  46. time_t g_timeAppStartUp;
  47. DWORD g_dwTickAppStartUp;
  48. int g_nAttemptCounter;
  49. DWORD g_dwMasterWakeupInterval;
  50. bool g_bDialogExpiredMode = false;
  51. static const TCHAR* g_szTrialStartEvent = TEXT("_319IcwTrialStart913_");
  52. static const TCHAR* g_szRunOnceEvent = TEXT("_319IcwRunOnce913_");
  53. //-----------------------------------------------------------------------------
  54. // WinMain
  55. //-----------------------------------------------------------------------------
  56. int WINAPI WinMainT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,
  57. int nCmdShow)
  58. {
  59. MSG msg;
  60. HANDLE hEventTrialStart = NULL;
  61. HANDLE hEventRunOnce = NULL;
  62. DWORD dwRetCode;
  63. bool bStartedViaWizard = false;
  64. // If there is a command line then see who started us.
  65. if (lstrlen(lpCmdLine))
  66. {
  67. // The RunOnce registry stuff will freeze up until we return. Hence
  68. // the RunOnce setting in the registry must have some value for the
  69. // command line. If we see any data we will spawn a second instance
  70. // of ourselves and exit this instance.
  71. if (0 == lstrcmpi(TEXT("-R"), lpCmdLine))
  72. {
  73. LPTSTR lpszFileName = new TCHAR[_MAX_PATH + 1];
  74. if (GetModuleFileName(GetModuleHandle(NULL), lpszFileName, _MAX_PATH + 1))
  75. {
  76. STARTUPINFO sui;
  77. PROCESS_INFORMATION pi;
  78. sui.cb = sizeof (STARTUPINFO);
  79. sui.lpReserved = 0;
  80. sui.lpDesktop = NULL;
  81. sui.lpTitle = NULL;
  82. sui.dwX = 0;
  83. sui.dwY = 0;
  84. sui.dwXSize = 0;
  85. sui.dwYSize = 0;
  86. sui.dwXCountChars = 0;
  87. sui.dwYCountChars = 0;
  88. sui.dwFillAttribute = 0;
  89. sui.dwFlags = 0;
  90. sui.wShowWindow = 0;
  91. sui.cbReserved2 = 0;
  92. sui.lpReserved2 = 0;
  93. BOOL ret = CreateProcess (lpszFileName, NULL, NULL, NULL,
  94. FALSE, DETACHED_PROCESS,
  95. NULL, NULL, &sui, &pi );
  96. _ASSERT(ret);
  97. CloseHandle(pi.hProcess);
  98. CloseHandle(pi.hThread);
  99. }
  100. delete [] lpszFileName;
  101. return 0;
  102. }
  103. // See if this is the start of a new trial.
  104. else if (0 == lstrcmpi(TEXT("-T"), lpCmdLine))
  105. {
  106. bStartedViaWizard = true;
  107. RemoveTrialConvertedFlag();
  108. }
  109. }
  110. // If we got this far let's create the named event and find out if we
  111. // are the first instance to run or if there is another instance already
  112. // running.
  113. hEventTrialStart = CreateEvent(NULL, FALSE, FALSE, g_szTrialStartEvent);
  114. if (hEventTrialStart)
  115. {
  116. // See if the named event already exists. If it does then another
  117. // instance of the IcwRmind exe is already running. Signal the event
  118. // and exit.
  119. if (ERROR_ALREADY_EXISTS == GetLastError())
  120. {
  121. // If we were started via the wizard tell the other instance
  122. // to reset it's trial start data.
  123. if (bStartedViaWizard)
  124. {
  125. SetEvent(hEventTrialStart);
  126. }
  127. // Otherwise assume that RunOnce started us again. In this case
  128. // Open the existing RunOnce named event and signal it. This
  129. // tells the running instance to place us back into RunOnce key.
  130. else
  131. {
  132. hEventRunOnce = OpenEvent(EVENT_MODIFY_STATE, false, g_szRunOnceEvent);
  133. if (hEventRunOnce)
  134. {
  135. SetEvent(hEventRunOnce);
  136. CloseHandle(hEventRunOnce);
  137. }
  138. }
  139. CloseHandle(hEventTrialStart);
  140. return 0;
  141. }
  142. }
  143. else
  144. {
  145. _ASSERT(FALSE);
  146. return 0;
  147. }
  148. hEventRunOnce = CreateEvent(NULL, FALSE, FALSE, g_szRunOnceEvent);
  149. if (!hEventRunOnce)
  150. {
  151. CloseHandle(hEventTrialStart);
  152. return 0;
  153. }
  154. // If this flag is true and we got this far then we are the first
  155. // instance to run after being started by the wizard. Let's clear
  156. // registry data just in case there is old stuff in there.
  157. if (bStartedViaWizard)
  158. {
  159. ResetCachedData();
  160. }
  161. // Check the registry and see if the user has successfully signed up.
  162. // If so then shut down for good.
  163. if (IsSignupSuccessful())
  164. {
  165. ShutDownForGood();
  166. CloseHandle(hEventTrialStart);
  167. CloseHandle(hEventRunOnce);
  168. return 0;
  169. }
  170. g_hModule = hInstance;
  171. ClearCachedData(); // This initializes cache data to zero.
  172. g_nAttemptCounter = 0;
  173. time(&g_timeAppStartUp);
  174. g_dwTickAppStartUp = GetTickCount();
  175. // If the connectoid entry name does not exist in the registry then
  176. // we will shut down for good.
  177. const TCHAR* pcszConnectName = GetISPConnectionName();
  178. if (NULL == pcszConnectName || 0 == lstrlen(pcszConnectName))
  179. {
  180. ShutDownForGood();
  181. CloseHandle(hEventTrialStart);
  182. CloseHandle(hEventRunOnce);
  183. return 0;
  184. }
  185. // If we cannot get or create the start time then something is really
  186. // bad. We will stop never to be run again.
  187. if (0 == GetTrialStartDate())
  188. {
  189. ShutDownForGood();
  190. CloseHandle(hEventTrialStart);
  191. CloseHandle(hEventRunOnce);
  192. return 0;
  193. }
  194. // Initialize and create the window class and window.
  195. if (!InitializeApp())
  196. {
  197. _ASSERT(FALSE);
  198. CloseHandle(hEventTrialStart);
  199. CloseHandle(hEventRunOnce);
  200. return 0;
  201. }
  202. // Testers can make the application visible via the registry.
  203. if (IsApplicationVisible())
  204. {
  205. ShowWindow(g_hwndMain, nCmdShow);
  206. }
  207. // Let's initialize the wake up interval. If we are in the first half
  208. // of the trial then we don't want to wake up very often. As we get
  209. // closer to the half way point we want to wake up more ofter to do
  210. // our polling.
  211. if (GetISPTrialDaysLeft() > (int)((GetISPTrialDays() / 2) + 1))
  212. {
  213. // Don't start polling more often until the day before the
  214. // half way point.
  215. g_dwMasterWakeupInterval = LONG_WAKEUP_INTERVAL;
  216. }
  217. else
  218. {
  219. // Use this method because the wake up interval may be in the
  220. // registry for testing.
  221. g_dwMasterWakeupInterval = GetWakeupInterval();
  222. }
  223. // Set a timer to re-setup the run once data in the registry.
  224. // If we do this too soon the intial run once startup will create
  225. // us multiple times.
  226. SetTimer(g_hwndMain, TIMER_RUNONCE_SETUP, TIME_RUNONCE_INTERVAL, NULL);
  227. HANDLE hEventList[2];
  228. hEventList[0] = hEventTrialStart;
  229. hEventList[1] = hEventRunOnce;
  230. while (TRUE)
  231. {
  232. // We will wait on window messages and also the named event.
  233. dwRetCode = MsgWaitForMultipleObjects(2, &hEventList[0], FALSE, g_dwMasterWakeupInterval, QS_ALLINPUT);
  234. // Determine why we came out of MsgWaitForMultipleObjects(). If
  235. // we timed out then let's do some TrialWatcher work. Otherwise
  236. // process the message that woke us up.
  237. if (WAIT_TIMEOUT == dwRetCode)
  238. {
  239. // If we are still in the long wake up interval do a quick check
  240. // to see if we should switch to the shorter interval.
  241. if (LONG_WAKEUP_INTERVAL == g_dwMasterWakeupInterval)
  242. {
  243. if (GetISPTrialDaysLeft() <= (int)((GetISPTrialDays() / 2) + 1))
  244. {
  245. g_dwMasterWakeupInterval = GetWakeupInterval();
  246. }
  247. }
  248. CheckForSignupAttempt();
  249. }
  250. else if (WAIT_OBJECT_0 == dwRetCode)
  251. {
  252. // If we get in here then the named event was signaled meaning
  253. // a second instance started up. This means the user has
  254. // signed up for a new trial with somebody else. Clear
  255. // all persistant registry data.
  256. ResetCachedData();
  257. // Reset the trial start date. If this fails then something
  258. // is really messed up in the registry.
  259. if (0 == GetTrialStartDate())
  260. {
  261. ShutDownForGood();
  262. break;
  263. }
  264. }
  265. else if (WAIT_OBJECT_0 + 1== dwRetCode)
  266. {
  267. // Signaled by the RunOnce event. We must reset the timer to
  268. // place ourselves back into RunOnce.
  269. KillTimer(g_hwndMain, TIMER_RUNONCE_SETUP); // In case it is already running.
  270. SetTimer(g_hwndMain, TIMER_RUNONCE_SETUP, TIME_RUNONCE_INTERVAL, NULL);
  271. }
  272. else if (WAIT_OBJECT_0 + 2 == dwRetCode)
  273. {
  274. // 0 is returned if no message retrieved.
  275. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  276. {
  277. if (WM_QUIT == msg.message)
  278. {
  279. break;
  280. }
  281. else
  282. {
  283. TranslateMessage(&msg);
  284. DispatchMessage(&msg);
  285. }
  286. }
  287. }
  288. }
  289. CloseHandle(hEventTrialStart);
  290. CloseHandle(hEventRunOnce);
  291. return 1;
  292. UNREFERENCED_PARAMETER(lpCmdLine);
  293. UNREFERENCED_PARAMETER(hPrevInstance);
  294. }
  295. //-----------------------------------------------------------------------------
  296. // InitializeApp
  297. //-----------------------------------------------------------------------------
  298. BOOL InitializeApp(void)
  299. {
  300. WNDCLASS wc;
  301. wc.style = 0;
  302. wc.lpfnWndProc = MainWndProc;
  303. wc.cbClsExtra = 0;
  304. wc.cbWndExtra = 0;
  305. wc.hInstance = g_hModule;
  306. wc.hIcon = NULL;
  307. wc.hCursor = LoadCursor(g_hModule, IDC_ARROW);
  308. wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE);
  309. wc.lpszMenuName = NULL;
  310. wc.lpszClassName = TEXT("IcwRmindClass");
  311. if (!RegisterClass(&wc))
  312. {
  313. return(FALSE);
  314. }
  315. // Create the main window. This window will stay hidden during the
  316. // life of the application.
  317. g_hwndMain = CreateWindow(TEXT("IcwRmindClass"),
  318. TEXT("IcwRmind"),
  319. WS_OVERLAPPEDWINDOW,
  320. CW_USEDEFAULT,
  321. CW_USEDEFAULT,
  322. 100,
  323. 100,
  324. HWND_DESKTOP,
  325. NULL,
  326. g_hModule,
  327. NULL);
  328. if (g_hwndMain == NULL)
  329. {
  330. _ASSERT(FALSE);
  331. return(FALSE);
  332. }
  333. return(TRUE);
  334. }
  335. //-----------------------------------------------------------------------------
  336. // MainWndProc
  337. //-----------------------------------------------------------------------------
  338. LRESULT WINAPI MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  339. {
  340. switch (message)
  341. {
  342. case WM_CREATE:
  343. {
  344. return 0;
  345. }
  346. case WM_TIMER:
  347. {
  348. KillTimer(g_hwndMain, TIMER_RUNONCE_SETUP);
  349. SetupRunOnce();
  350. // Wait for trial days left to drop below -1. The trail to
  351. // do the trial over sign up.
  352. if (GetISPTrialDaysLeft() < -1)
  353. {
  354. AttemptTrialOverSignup();
  355. }
  356. return 1;
  357. }
  358. case WM_TIMECHANGE:
  359. {
  360. // Calculate the relative current time. We do not want to
  361. // grab the system time because that is the new time after
  362. // the time change. Tick count is in milleseconds so we
  363. // convert that to seconds by dividing by 1000.
  364. DWORD dwTickDelta = GetTickDelta();
  365. // If tick count rolls around GetTickDelta() will modify app
  366. // start date, so get the tick delta before actually using it.
  367. time_t timeRelativeCurrent = g_timeAppStartUp + (dwTickDelta / 1000);
  368. // Determine the delta in seconds between the relative
  369. // system time and the new time set by the user.
  370. time_t timeCurrent;
  371. time(&timeCurrent);
  372. // Delta seconds will be negative if the user has turned
  373. // the clock back.
  374. time_t timeDeltaSeconds = timeCurrent - timeRelativeCurrent;
  375. time_t timeNewTrialStartDate = GetTrialStartDate() + timeDeltaSeconds;
  376. #ifdef _DEBUG
  377. TCHAR buf[255];
  378. OutputDebugString(TEXT("-------------------\n"));
  379. time_t timeOldStart = GetTrialStartDate();
  380. wsprintf(buf, TEXT("Old Start: %s\n"), ctime(&timeOldStart));
  381. OutputDebugString(buf);
  382. wsprintf(buf, TEXT("New Start: %s\n"), ctime(&timeNewTrialStartDate));
  383. OutputDebugString(buf);
  384. OutputDebugString(TEXT("-------------------\n"));
  385. #endif
  386. // Now reset the trial start date and the application start
  387. // date. Also reset the app start date and app start tick
  388. // count. This will be our new frame of reference for
  389. // calculating relative dates.
  390. ResetTrialStartDate(timeNewTrialStartDate);
  391. g_timeAppStartUp = timeCurrent;
  392. g_dwTickAppStartUp = GetTickCount();
  393. return 1;
  394. }
  395. case WM_DESTROY:
  396. {
  397. PostQuitMessage(0);
  398. return 1;
  399. }
  400. default:
  401. {
  402. return DefWindowProc(hwnd, message, wParam, lParam);
  403. }
  404. }
  405. }
  406. //-----------------------------------------------------------------------------
  407. // SignUpDialogProc
  408. //-----------------------------------------------------------------------------
  409. INT_PTR CALLBACK SignUpDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  410. {
  411. HICON hIcon = NULL;
  412. switch (message)
  413. {
  414. case WM_INITDIALOG:
  415. {
  416. TCHAR bufOut[MAX_DIALOGTEXT];
  417. TCHAR bufFormat[MAX_DIALOGTEXT];
  418. TCHAR *bufAll = new TCHAR[MAX_DIALOGTEXT * 2 + MAX_ISPMSGSTRING];
  419. g_bDoNotRemindAgain = false;
  420. // This dialog has two modes. Set the text the correct way.
  421. if (g_bDialogExpiredMode)
  422. {
  423. if (LoadString(g_hModule, IDS_EXPIRED_DLG_TITLE, bufFormat, MAX_DIALOGTEXT))
  424. {
  425. SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM) bufFormat);
  426. }
  427. if (bufAll)
  428. {
  429. if (LoadString(g_hModule, IDS_EXPIRED_TEXT1, bufFormat, MAX_DIALOGTEXT))
  430. {
  431. wsprintf(bufOut, bufFormat, GetISPName());
  432. lstrcpy(bufAll, bufOut);
  433. lstrcat(bufAll, TEXT("\n\n"));
  434. }
  435. if(*GetISPMessage() != '\0')
  436. {
  437. lstrcat(bufAll, GetISPMessage());
  438. lstrcat(bufAll, TEXT("\n\n"));
  439. }
  440. if (LoadString(g_hModule, IDS_EXPIRED_TEXT2, bufFormat, MAX_DIALOGTEXT))
  441. {
  442. wsprintf(bufOut, bufFormat, GetISPName(), GetISPName(), GetISPPhone());
  443. lstrcat(bufAll, bufOut);
  444. }
  445. SetDlgItemText(hDlg, IDC_TEXT1, bufAll);
  446. ShowWindow(GetDlgItem(hDlg, IDC_DONTREMIND), SW_HIDE);
  447. if (LoadString(g_hModule, IDS_DONOTSIGNUP, bufOut, MAX_DIALOGTEXT))
  448. {
  449. SetDlgItemText(hDlg, IDCANCEL, bufOut);
  450. }
  451. }
  452. }
  453. else
  454. {
  455. // Set up the text in the dialog box.
  456. if (LoadString(g_hModule, IDS_DLG_TITLE, bufFormat, MAX_DIALOGTEXT))
  457. {
  458. wsprintf(bufOut, bufFormat, GetISPTrialDaysLeft());
  459. SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM) bufOut);
  460. }
  461. if (bufAll)
  462. {
  463. if (LoadString(g_hModule, IDS_TEXT1, bufFormat, MAX_DIALOGTEXT))
  464. {
  465. wsprintf(bufOut, bufFormat, GetISPName(), GetISPTrialDaysLeft());
  466. lstrcpy(bufAll, bufOut);
  467. lstrcat(bufAll, TEXT("\n\n"));
  468. }
  469. if(*GetISPMessage() != '\0')
  470. {
  471. lstrcat(bufAll, GetISPMessage());
  472. lstrcat(bufAll, TEXT("\n\n"));
  473. }
  474. if (LoadString(g_hModule, IDS_TEXT2, bufFormat, MAX_DIALOGTEXT))
  475. {
  476. wsprintf(bufOut, bufFormat, GetISPName(), GetISPName(), GetISPPhone());
  477. lstrcat(bufAll, bufOut);
  478. }
  479. SetDlgItemText(hDlg, IDC_TEXT1, bufAll);
  480. }
  481. // If there are 0 days left then don't give user a change
  482. // to say remind me later.
  483. if (0 == GetISPTrialDaysLeft())
  484. {
  485. ShowWindow(GetDlgItem(hDlg, IDC_DONTREMIND), SW_HIDE);
  486. if (LoadString(g_hModule, IDS_DONOTSIGNUP, bufOut, MAX_DIALOGTEXT))
  487. {
  488. SetDlgItemText(hDlg, IDCANCEL, bufOut);
  489. }
  490. }
  491. }
  492. // Set the timer for how long the dialog will stay up before
  493. // removing itself.
  494. SetTimer(hDlg, TIMER_DIALOG_STAYUP, GetDialogTimeout(), NULL);
  495. CenterTheWindow(hDlg);
  496. if (bufAll)
  497. {
  498. delete [] bufAll;
  499. }
  500. return TRUE;
  501. }
  502. case WM_COMMAND:
  503. {
  504. switch (LOWORD(wParam))
  505. {
  506. // IDOK is the Sign up now button.
  507. case IDOK:
  508. {
  509. KillTimer(hDlg, TIMER_DIALOG_STAYUP);
  510. EndDialog(hDlg, wParam);
  511. break;
  512. }
  513. // If the checkbox is clicked then toggle the button text for the
  514. // signup later button.
  515. case IDC_DONTREMIND:
  516. {
  517. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_DONTREMIND))
  518. {
  519. TCHAR bufOut[MAX_DIALOGTEXT];
  520. if (LoadString(g_hModule, IDS_DONOTREMIND, bufOut, MAX_DIALOGTEXT))
  521. {
  522. SetDlgItemText(hDlg, IDCANCEL, bufOut);
  523. }
  524. }
  525. else
  526. {
  527. TCHAR bufOut[MAX_DIALOGTEXT];
  528. if (LoadString(g_hModule, IDS_SIGNUPLATER, bufOut, MAX_DIALOGTEXT))
  529. {
  530. SetDlgItemText(hDlg, IDCANCEL, bufOut);
  531. }
  532. }
  533. break;
  534. }
  535. // Otherwise assume they hit the close button or the sign up later
  536. // button.
  537. default:
  538. {
  539. // See if the user never wants reminded again.
  540. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_DONTREMIND))
  541. {
  542. g_bDoNotRemindAgain = true;
  543. }
  544. KillTimer(hDlg, TIMER_DIALOG_STAYUP);
  545. EndDialog(hDlg, wParam);
  546. break;
  547. }
  548. }
  549. break;
  550. }
  551. // No user interaction has occurred. remove the dialog but do not count
  552. // this as an attempt to sign up.
  553. case WM_TIMER:
  554. {
  555. KillTimer(hDlg, TIMER_DIALOG_STAYUP);
  556. EndDialog(hDlg, IDABORT);
  557. break;
  558. }
  559. case WM_PAINT:
  560. {
  561. HDC hDC;
  562. PAINTSTRUCT ps;
  563. HICON hIcon;
  564. HWND hWndRect;
  565. RECT rect;
  566. POINT ptUpperLeft;
  567. hDC = BeginPaint(hDlg, &ps);
  568. hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_QUESTION));
  569. if (hIcon)
  570. {
  571. hWndRect = GetDlgItem(hDlg, IDC_ICON1);
  572. GetWindowRect(hWndRect, &rect);
  573. ptUpperLeft.x = rect.left;
  574. ptUpperLeft.y = rect.top;
  575. ScreenToClient(hDlg, &ptUpperLeft);
  576. DrawIcon(hDC, ptUpperLeft.x, ptUpperLeft.y, hIcon);
  577. }
  578. EndPaint(hDlg, &ps);
  579. break;
  580. }
  581. }
  582. return FALSE;
  583. UNREFERENCED_PARAMETER(lParam);
  584. UNREFERENCED_PARAMETER(hDlg);
  585. }
  586. //-----------------------------------------------------------------------------
  587. // CheckForRASConnection
  588. //-----------------------------------------------------------------------------
  589. BOOL CheckForRASConnection()
  590. {
  591. RASCONNSTATUS rascs;
  592. RASCONN rasConn[MAXRASCONNS];
  593. DWORD dwEntries = MAXRASCONNS;
  594. DWORD dwSize = sizeof(rasConn);
  595. DWORD dwRet;
  596. BOOL bRetCode = FALSE;
  597. // This is the connection name of the ISP the user has signed up
  598. // with. We will look for a connectiod with this same name.
  599. const TCHAR* pszConnectionName = GetISPConnectionName();
  600. if (NULL == pszConnectionName || 0 == lstrlen(pszConnectionName))
  601. {
  602. return FALSE;
  603. }
  604. for (int i = 0; i < MAXRASCONNS; ++i)
  605. {
  606. rasConn[i].dwSize = sizeof(RASCONN);
  607. }
  608. dwRet = RasEnumConnections(rasConn, &dwSize, &dwEntries);
  609. if (dwRet == 0)
  610. {
  611. for (dwRet = 0; dwRet < dwEntries; dwRet++)
  612. {
  613. // If this is the connection we are looking for let's make
  614. // sure the connection is all set to go.
  615. if (0 == lstrcmpi(pszConnectionName, rasConn[dwRet].szEntryName))
  616. {
  617. rascs.dwSize = sizeof(RASCONNSTATUS);
  618. dwRet = RasGetConnectStatus(rasConn[dwRet].hrasconn,
  619. &rascs);
  620. if (dwRet == 0 && rascs.rasconnstate == RASCS_Connected)
  621. {
  622. bRetCode = TRUE;
  623. }
  624. }
  625. }
  626. }
  627. return bRetCode;
  628. }
  629. //-----------------------------------------------------------------------------
  630. // CheckForSignupAttempt
  631. //
  632. // This method contains the logic that check to see if we should make an attempt
  633. // to pop up the sign up dialog. If we should make an attempt will will then
  634. // enum the RAS connections to see if the user is connected before popping
  635. // up the dialog.
  636. //-----------------------------------------------------------------------------
  637. void CheckForSignupAttempt()
  638. {
  639. int nDaysLeft = GetISPTrialDaysLeft();
  640. int nRetValue = 0;
  641. // Every some many signup attempts lets read the registry and see if
  642. // a successful signup happened.
  643. ++g_nAttemptCounter;
  644. if (MAX_ATTEMPTCOUNTER == g_nAttemptCounter)
  645. {
  646. g_nAttemptCounter = 0;
  647. if (IsSignupSuccessful())
  648. {
  649. ShutDownForGood();
  650. return;
  651. }
  652. // If the trial is expired then set the IE run once key.
  653. if (nDaysLeft < -1)
  654. {
  655. SetIERunOnce();
  656. }
  657. }
  658. // If we are in negative days left then do not do anything. This means
  659. // the trail is over and the user has not signed up. We will give
  660. // them one more signup attempt on application start up.
  661. if (nDaysLeft < 0)
  662. {
  663. return;
  664. }
  665. bool bAttemptSignup = false;
  666. // Based on the total signup notificaiton attempts we will determine
  667. // if the days left requires another attempt.
  668. switch (GetTotalNotifications())
  669. {
  670. // If we have not made any attempts yet then if we are at the half
  671. // way point in the trial or past the half way point we will make
  672. // a signup attempt.
  673. case 0:
  674. {
  675. if (nDaysLeft <= (int)(GetISPTrialDays() / 2))
  676. {
  677. bAttemptSignup = true;
  678. }
  679. break;
  680. }
  681. // If we have already perfomed 1 attempt then the second attempt
  682. // will come on the next to last day or the last day.
  683. case 1:
  684. {
  685. if (nDaysLeft <= 1)
  686. {
  687. bAttemptSignup = true;
  688. }
  689. break;
  690. }
  691. // The 3rd attempt will not come until the last day.
  692. case 2:
  693. {
  694. if (nDaysLeft == 0)
  695. {
  696. bAttemptSignup = true;
  697. }
  698. break;
  699. }
  700. default:
  701. {
  702. break;
  703. }
  704. }
  705. if (bAttemptSignup)
  706. {
  707. if (CheckForRASConnection())
  708. {
  709. // Before actually showing the dialog do a quick check to see
  710. // if a previous signup was successful. If so we will shut
  711. // down for good.
  712. if (IsSignupSuccessful())
  713. {
  714. ShutDownForGood();
  715. return;
  716. }
  717. g_bDialogExpiredMode = false;
  718. //if we have an isp message we need the right dlg template
  719. if(*GetISPMessage() != '\0')
  720. nRetValue = (int)DialogBox(g_hModule, MAKEINTRESOURCE(IDD_SIGNUP_ISPMSG), g_hwndMain, SignUpDialogProc);
  721. else
  722. nRetValue = (int)DialogBox(g_hModule, MAKEINTRESOURCE(IDD_SIGNUP), g_hwndMain, SignUpDialogProc);
  723. switch (nRetValue)
  724. {
  725. // The user wants to try and signup.
  726. case IDOK:
  727. {
  728. PerformTheSignup();
  729. break;
  730. }
  731. // The user said signup later. Check to see if the don't remind
  732. // me button was pressed. If so then shut down for good.
  733. case IDCANCEL:
  734. {
  735. // If this is the last day of the trial then the remind
  736. // me later button is not the Don't signup button. In
  737. // this case shut down for good.
  738. if (0 == nDaysLeft)
  739. {
  740. ShutDownForGood();
  741. }
  742. else
  743. {
  744. IncrementTotalNotifications();
  745. if (g_bDoNotRemindAgain)
  746. {
  747. ShutDownForGood();
  748. }
  749. }
  750. break;
  751. }
  752. // The dialog timed out. Don't do anything. The does not
  753. // count as an attempt.
  754. case IDABORT:
  755. {
  756. break;
  757. }
  758. // No work in here, in fact we should not get here.
  759. default:
  760. {
  761. _ASSERT(false);
  762. break;
  763. }
  764. }
  765. // If there is 1 day left let's make sure that total notifications
  766. // is 2. If not the dialog may pop up multiple times. Oh yea,
  767. // if dialog timed out then don't do this.
  768. if (IDABORT != nRetValue && 1 == nDaysLeft && 1 == GetTotalNotifications())
  769. {
  770. IncrementTotalNotifications();
  771. }
  772. }
  773. }
  774. }
  775. //-----------------------------------------------------------------------------
  776. // GetISPTrialDaysLeft
  777. //-----------------------------------------------------------------------------
  778. int GetISPTrialDaysLeft()
  779. {
  780. // Calculate the relative current time. The current system time cannot
  781. // be trusted if the System date/time dialog is up. That dialog will
  782. // change the actual system time when every the user pokes around even
  783. // before hitting OK or Apply!!!
  784. time_t timeRelativeCurrent = g_timeAppStartUp + (GetTickDelta() / 1000);
  785. // The relative time and the trial start date are both time_t type
  786. // variables which are in seconds.
  787. int nSecondsSinceStart = (int)(timeRelativeCurrent - GetTrialStartDate());
  788. // Now convert seconds into days. There are 86400 seconds in a day.
  789. // Note that we will always round up one more day if there is any
  790. // remainder.
  791. div_t divResult = div(nSecondsSinceStart, 86400);
  792. int nDaysSinceStart = divResult.quot;
  793. if (divResult.rem)
  794. {
  795. ++nDaysSinceStart;
  796. }
  797. #ifdef _DEBUG
  798. TCHAR buf[255];
  799. wsprintf(buf, TEXT("Days Since = %i\n"), nDaysSinceStart);
  800. OutputDebugString(buf);
  801. wsprintf(buf, TEXT("Check: %s\n"), ctime(&timeRelativeCurrent));
  802. OutputDebugString(buf);
  803. time_t tt = GetTrialStartDate();
  804. wsprintf(buf, TEXT("Start: %s\n"), ctime(&tt));
  805. OutputDebugString(buf);
  806. #endif
  807. int nDaysLeft = GetISPTrialDays() - nDaysSinceStart;
  808. #ifdef _DEBUG
  809. wsprintf(buf, TEXT("Days Left = %i\r\n"), nDaysLeft);
  810. OutputDebugString(buf);
  811. #endif
  812. return nDaysLeft;
  813. }
  814. //-----------------------------------------------------------------------------
  815. // ShutDownForGood
  816. //-----------------------------------------------------------------------------
  817. void ShutDownForGood()
  818. {
  819. RemoveRunOnce();
  820. RemoveIERunOnce();
  821. DeleteAllRegistryData();
  822. PostMessage(g_hwndMain, WM_CLOSE, 0, 0);
  823. }
  824. //-----------------------------------------------------------------------------
  825. // PerformTheSignup
  826. //-----------------------------------------------------------------------------
  827. void PerformTheSignup()
  828. {
  829. // Note that we do not shut down for good. The sign up may fail so
  830. // simply increment the notification count.
  831. const TCHAR* pcszSignupUrl = GetISPSignupUrl();
  832. ShellExecute(g_hwndMain, TEXT("open"), pcszSignupUrl, TEXT(""), TEXT(""), SW_SHOW);
  833. IncrementTotalNotifications();
  834. }
  835. //-----------------------------------------------------------------------------
  836. // CenterTheWindow
  837. //-----------------------------------------------------------------------------
  838. void CenterTheWindow(HWND hWnd)
  839. {
  840. HDC hDC = GetDC(hWnd);
  841. if (hDC)
  842. {
  843. int nScreenWidth = GetDeviceCaps(hDC, HORZRES);
  844. int nScreenHeight = GetDeviceCaps(hDC, VERTRES);
  845. RECT rect;
  846. GetWindowRect(hWnd, &rect);
  847. // Also make the window "always on top".
  848. SetWindowPos(hWnd, HWND_TOPMOST,
  849. (nScreenWidth / 2) - ((rect.right - rect.left) / 2),
  850. (nScreenHeight / 2) - ((rect.bottom - rect.top) / 2),
  851. rect.right - rect.left,
  852. rect.bottom - rect.top,
  853. SWP_SHOWWINDOW);
  854. ReleaseDC(hWnd, hDC);
  855. }
  856. }
  857. //-----------------------------------------------------------------------------
  858. // GetTickDelta
  859. //-----------------------------------------------------------------------------
  860. DWORD GetTickDelta()
  861. {
  862. // This function returns the delta between the startup tick count and
  863. // the current tick count. Note that we must watch for a rollover in
  864. // the tick count.
  865. DWORD dwTickDelta;
  866. DWORD dwTickCurrent = GetTickCount();
  867. // If tick count rolls over we need to reset the app start up date
  868. // and the app tick count in case we roll over a second time.
  869. if (dwTickCurrent < g_dwTickAppStartUp)
  870. {
  871. // Calculate the delta by finding out how many ticks to the MAX
  872. // tick count a DWORD can handle and then add the wrap around amount.
  873. DWORD dwDeltaToMax = 0xFFFFFFFF - g_dwTickAppStartUp;
  874. dwTickDelta = dwDeltaToMax + dwTickCurrent;
  875. // Modify the application startup by the delta in seconds that have
  876. // passed since it was last set. Also reset startup tick count
  877. // to current tick for our new frame of reference.
  878. g_timeAppStartUp += (dwTickDelta / 1000); // Convert to seconds.
  879. g_dwTickAppStartUp = dwTickCurrent;
  880. // Since we have modified the application start up date relative
  881. // to the current tick count and changed the app start up tick
  882. // count to the current tick count, the delta is zero.
  883. dwTickDelta = 0;
  884. }
  885. else
  886. {
  887. dwTickDelta = dwTickCurrent - g_dwTickAppStartUp;
  888. }
  889. return dwTickDelta;
  890. }
  891. //-----------------------------------------------------------------------------
  892. // AttemptTrialOverSignup
  893. //-----------------------------------------------------------------------------
  894. void AttemptTrialOverSignup()
  895. {
  896. int nRetValue = 0;
  897. // Setup the run once data for IE.
  898. g_bDialogExpiredMode = true;
  899. if(*GetISPMessage() != '\0')
  900. nRetValue = (int)DialogBox(g_hModule, MAKEINTRESOURCE(IDD_SIGNUP_ISPMSG), g_hwndMain, SignUpDialogProc);
  901. else
  902. nRetValue = (int)DialogBox(g_hModule, MAKEINTRESOURCE(IDD_SIGNUP), g_hwndMain, SignUpDialogProc);
  903. RemoveIERunOnce();
  904. switch (nRetValue)
  905. {
  906. // The user wants to try and signup.
  907. case IDOK:
  908. {
  909. const TCHAR* pcszSignupUrl = GetISPSignupUrlTrialOver();
  910. ShellExecute(g_hwndMain, TEXT("open"), pcszSignupUrl, TEXT(""), TEXT(""), SW_SHOW);
  911. ShutDownForGood();
  912. break;
  913. }
  914. case IDCANCEL:
  915. {
  916. ShutDownForGood();
  917. break;
  918. }
  919. // If we get IDABORT the dialog timed out so don't do anything.
  920. case IDABORT:
  921. {
  922. break;
  923. }
  924. // No work in here, in fact we should not get here.
  925. default:
  926. {
  927. _ASSERT(false);
  928. ShutDownForGood();
  929. break;
  930. }
  931. }
  932. }
  933. extern "C" void _stdcall ModuleEntry (void)
  934. {
  935. LPTSTR pszCmdLine = GetCommandLine();
  936. if ( *pszCmdLine == TEXT('\"') )
  937. {
  938. /*
  939. * Scan, and skip over, subsequent characters until
  940. * another double-quote or a null is encountered.
  941. */
  942. while ( *++pszCmdLine && (*pszCmdLine != TEXT('\"')) )
  943. ;
  944. /*
  945. * If we stopped on a double-quote (usual case), skip
  946. * over it.
  947. */
  948. if ( *pszCmdLine == TEXT('\"') )
  949. pszCmdLine++;
  950. }
  951. else
  952. {
  953. while (*pszCmdLine > TEXT(' '))
  954. pszCmdLine++;
  955. }
  956. /*
  957. * Skip past any white space preceeding the second token.
  958. */
  959. while (*pszCmdLine && (*pszCmdLine <= TEXT(' ')))
  960. {
  961. pszCmdLine++;
  962. }
  963. int i = WinMainT(GetModuleHandle(NULL), NULL, pszCmdLine, SW_SHOWDEFAULT);
  964. ExitProcess(i); // Were outa here....
  965. } /* ModuleEntry() */