//----------------------------------------------------------------------------- // This exe runs in the background and wakes up every so often to do it's work. // When it wakes up it checks to see how much time the user has left on their // free ISP subscription. At certain intervals it will tell the user time // is running out and will give the user the chance to signup for rea. //----------------------------------------------------------------------------- #define STRICT #include #include #include #include #include #include #include #include "IcwRmind.h" #include "resource.h" #include "RegData.h" //----------------------------------------------------------------------------- // Forward Declarations //----------------------------------------------------------------------------- BOOL InitializeApp (void); BOOL CheckForRASConnection(); void CheckForSignupAttempt(); int GetISPTrialDaysLeft(); void ShutDownForGood(); void PerformTheSignup(); void CenterTheWindow(HWND hWnd); DWORD GetTickDelta(); void AttemptTrialOverSignup(); //----------------------------------------------------------------------------- // Defines //----------------------------------------------------------------------------- #define TIMER_DIALOG_STAYUP 319 // Wake up timer to do work. #define TIMER_RUNONCE_SETUP 320 #define TIME_RUNONCE_INTERVAL 30000 // 30 seconds #define MAXRASCONNS 8 #define MAX_DIALOGTEXT 512 #define MAX_ATTEMPTCOUNTER 20 #define LONG_WAKEUP_INTERVAL 3600000 // 1 hour //----------------------------------------------------------------------------- // Global Handles and other defines //----------------------------------------------------------------------------- HINSTANCE g_hModule; // Process Instance handle HWND g_hwndMain; // Main window handle bool g_bDoNotRemindAgain; // Used by signup dialog. time_t g_timeAppStartUp; DWORD g_dwTickAppStartUp; int g_nAttemptCounter; DWORD g_dwMasterWakeupInterval; bool g_bDialogExpiredMode = false; static const TCHAR* g_szTrialStartEvent = TEXT("_319IcwTrialStart913_"); static const TCHAR* g_szRunOnceEvent = TEXT("_319IcwRunOnce913_"); //----------------------------------------------------------------------------- // WinMain //----------------------------------------------------------------------------- int WINAPI WinMainT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MSG msg; HANDLE hEventTrialStart = NULL; HANDLE hEventRunOnce = NULL; DWORD dwRetCode; bool bStartedViaWizard = false; // If there is a command line then see who started us. if (lstrlen(lpCmdLine)) { // The RunOnce registry stuff will freeze up until we return. Hence // the RunOnce setting in the registry must have some value for the // command line. If we see any data we will spawn a second instance // of ourselves and exit this instance. if (0 == lstrcmpi(TEXT("-R"), lpCmdLine)) { LPTSTR lpszFileName = new TCHAR[_MAX_PATH + 1]; if (GetModuleFileName(GetModuleHandle(NULL), lpszFileName, _MAX_PATH + 1)) { STARTUPINFO sui; PROCESS_INFORMATION pi; sui.cb = sizeof (STARTUPINFO); sui.lpReserved = 0; sui.lpDesktop = NULL; sui.lpTitle = NULL; sui.dwX = 0; sui.dwY = 0; sui.dwXSize = 0; sui.dwYSize = 0; sui.dwXCountChars = 0; sui.dwYCountChars = 0; sui.dwFillAttribute = 0; sui.dwFlags = 0; sui.wShowWindow = 0; sui.cbReserved2 = 0; sui.lpReserved2 = 0; BOOL ret = CreateProcess (lpszFileName, NULL, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &sui, &pi ); _ASSERT(ret); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } delete [] lpszFileName; return 0; } // See if this is the start of a new trial. else if (0 == lstrcmpi(TEXT("-T"), lpCmdLine)) { bStartedViaWizard = true; RemoveTrialConvertedFlag(); } } // If we got this far let's create the named event and find out if we // are the first instance to run or if there is another instance already // running. hEventTrialStart = CreateEvent(NULL, FALSE, FALSE, g_szTrialStartEvent); if (hEventTrialStart) { // See if the named event already exists. If it does then another // instance of the IcwRmind exe is already running. Signal the event // and exit. if (ERROR_ALREADY_EXISTS == GetLastError()) { // If we were started via the wizard tell the other instance // to reset it's trial start data. if (bStartedViaWizard) { SetEvent(hEventTrialStart); } // Otherwise assume that RunOnce started us again. In this case // Open the existing RunOnce named event and signal it. This // tells the running instance to place us back into RunOnce key. else { hEventRunOnce = OpenEvent(EVENT_MODIFY_STATE, false, g_szRunOnceEvent); if (hEventRunOnce) { SetEvent(hEventRunOnce); CloseHandle(hEventRunOnce); } } CloseHandle(hEventTrialStart); return 0; } } else { _ASSERT(FALSE); return 0; } hEventRunOnce = CreateEvent(NULL, FALSE, FALSE, g_szRunOnceEvent); if (!hEventRunOnce) { CloseHandle(hEventTrialStart); return 0; } // If this flag is true and we got this far then we are the first // instance to run after being started by the wizard. Let's clear // registry data just in case there is old stuff in there. if (bStartedViaWizard) { ResetCachedData(); } // Check the registry and see if the user has successfully signed up. // If so then shut down for good. if (IsSignupSuccessful()) { ShutDownForGood(); CloseHandle(hEventTrialStart); CloseHandle(hEventRunOnce); return 0; } g_hModule = hInstance; ClearCachedData(); // This initializes cache data to zero. g_nAttemptCounter = 0; time(&g_timeAppStartUp); g_dwTickAppStartUp = GetTickCount(); // If the connectoid entry name does not exist in the registry then // we will shut down for good. const TCHAR* pcszConnectName = GetISPConnectionName(); if (NULL == pcszConnectName || 0 == lstrlen(pcszConnectName)) { ShutDownForGood(); CloseHandle(hEventTrialStart); CloseHandle(hEventRunOnce); return 0; } // If we cannot get or create the start time then something is really // bad. We will stop never to be run again. if (0 == GetTrialStartDate()) { ShutDownForGood(); CloseHandle(hEventTrialStart); CloseHandle(hEventRunOnce); return 0; } // Initialize and create the window class and window. if (!InitializeApp()) { _ASSERT(FALSE); CloseHandle(hEventTrialStart); CloseHandle(hEventRunOnce); return 0; } // Testers can make the application visible via the registry. if (IsApplicationVisible()) { ShowWindow(g_hwndMain, nCmdShow); } // Let's initialize the wake up interval. If we are in the first half // of the trial then we don't want to wake up very often. As we get // closer to the half way point we want to wake up more ofter to do // our polling. if (GetISPTrialDaysLeft() > (int)((GetISPTrialDays() / 2) + 1)) { // Don't start polling more often until the day before the // half way point. g_dwMasterWakeupInterval = LONG_WAKEUP_INTERVAL; } else { // Use this method because the wake up interval may be in the // registry for testing. g_dwMasterWakeupInterval = GetWakeupInterval(); } // Set a timer to re-setup the run once data in the registry. // If we do this too soon the intial run once startup will create // us multiple times. SetTimer(g_hwndMain, TIMER_RUNONCE_SETUP, TIME_RUNONCE_INTERVAL, NULL); HANDLE hEventList[2]; hEventList[0] = hEventTrialStart; hEventList[1] = hEventRunOnce; while (TRUE) { // We will wait on window messages and also the named event. dwRetCode = MsgWaitForMultipleObjects(2, &hEventList[0], FALSE, g_dwMasterWakeupInterval, QS_ALLINPUT); // Determine why we came out of MsgWaitForMultipleObjects(). If // we timed out then let's do some TrialWatcher work. Otherwise // process the message that woke us up. if (WAIT_TIMEOUT == dwRetCode) { // If we are still in the long wake up interval do a quick check // to see if we should switch to the shorter interval. if (LONG_WAKEUP_INTERVAL == g_dwMasterWakeupInterval) { if (GetISPTrialDaysLeft() <= (int)((GetISPTrialDays() / 2) + 1)) { g_dwMasterWakeupInterval = GetWakeupInterval(); } } CheckForSignupAttempt(); } else if (WAIT_OBJECT_0 == dwRetCode) { // If we get in here then the named event was signaled meaning // a second instance started up. This means the user has // signed up for a new trial with somebody else. Clear // all persistant registry data. ResetCachedData(); // Reset the trial start date. If this fails then something // is really messed up in the registry. if (0 == GetTrialStartDate()) { ShutDownForGood(); break; } } else if (WAIT_OBJECT_0 + 1== dwRetCode) { // Signaled by the RunOnce event. We must reset the timer to // place ourselves back into RunOnce. KillTimer(g_hwndMain, TIMER_RUNONCE_SETUP); // In case it is already running. SetTimer(g_hwndMain, TIMER_RUNONCE_SETUP, TIME_RUNONCE_INTERVAL, NULL); } else if (WAIT_OBJECT_0 + 2 == dwRetCode) { // 0 is returned if no message retrieved. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (WM_QUIT == msg.message) { break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } } } CloseHandle(hEventTrialStart); CloseHandle(hEventRunOnce); return 1; UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(hPrevInstance); } //----------------------------------------------------------------------------- // InitializeApp //----------------------------------------------------------------------------- BOOL InitializeApp(void) { WNDCLASS wc; wc.style = 0; wc.lpfnWndProc = MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = g_hModule; wc.hIcon = NULL; wc.hCursor = LoadCursor(g_hModule, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE); wc.lpszMenuName = NULL; wc.lpszClassName = TEXT("IcwRmindClass"); if (!RegisterClass(&wc)) { return(FALSE); } // Create the main window. This window will stay hidden during the // life of the application. g_hwndMain = CreateWindow(TEXT("IcwRmindClass"), TEXT("IcwRmind"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, HWND_DESKTOP, NULL, g_hModule, NULL); if (g_hwndMain == NULL) { _ASSERT(FALSE); return(FALSE); } return(TRUE); } //----------------------------------------------------------------------------- // MainWndProc //----------------------------------------------------------------------------- LRESULT WINAPI MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: { return 0; } case WM_TIMER: { KillTimer(g_hwndMain, TIMER_RUNONCE_SETUP); SetupRunOnce(); // Wait for trial days left to drop below -1. The trail to // do the trial over sign up. if (GetISPTrialDaysLeft() < -1) { AttemptTrialOverSignup(); } return 1; } case WM_TIMECHANGE: { // Calculate the relative current time. We do not want to // grab the system time because that is the new time after // the time change. Tick count is in milleseconds so we // convert that to seconds by dividing by 1000. DWORD dwTickDelta = GetTickDelta(); // If tick count rolls around GetTickDelta() will modify app // start date, so get the tick delta before actually using it. time_t timeRelativeCurrent = g_timeAppStartUp + (dwTickDelta / 1000); // Determine the delta in seconds between the relative // system time and the new time set by the user. time_t timeCurrent; time(&timeCurrent); // Delta seconds will be negative if the user has turned // the clock back. time_t timeDeltaSeconds = timeCurrent - timeRelativeCurrent; time_t timeNewTrialStartDate = GetTrialStartDate() + timeDeltaSeconds; #ifdef _DEBUG TCHAR buf[255]; OutputDebugString(TEXT("-------------------\n")); time_t timeOldStart = GetTrialStartDate(); wsprintf(buf, TEXT("Old Start: %s\n"), ctime(&timeOldStart)); OutputDebugString(buf); wsprintf(buf, TEXT("New Start: %s\n"), ctime(&timeNewTrialStartDate)); OutputDebugString(buf); OutputDebugString(TEXT("-------------------\n")); #endif // Now reset the trial start date and the application start // date. Also reset the app start date and app start tick // count. This will be our new frame of reference for // calculating relative dates. ResetTrialStartDate(timeNewTrialStartDate); g_timeAppStartUp = timeCurrent; g_dwTickAppStartUp = GetTickCount(); return 1; } case WM_DESTROY: { PostQuitMessage(0); return 1; } default: { return DefWindowProc(hwnd, message, wParam, lParam); } } } //----------------------------------------------------------------------------- // SignUpDialogProc //----------------------------------------------------------------------------- INT_PTR CALLBACK SignUpDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { HICON hIcon = NULL; switch (message) { case WM_INITDIALOG: { TCHAR bufOut[MAX_DIALOGTEXT]; TCHAR bufFormat[MAX_DIALOGTEXT]; TCHAR *bufAll = new TCHAR[MAX_DIALOGTEXT * 2 + MAX_ISPMSGSTRING]; g_bDoNotRemindAgain = false; // This dialog has two modes. Set the text the correct way. if (g_bDialogExpiredMode) { if (LoadString(g_hModule, IDS_EXPIRED_DLG_TITLE, bufFormat, MAX_DIALOGTEXT)) { SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM) bufFormat); } if (bufAll) { if (LoadString(g_hModule, IDS_EXPIRED_TEXT1, bufFormat, MAX_DIALOGTEXT)) { wsprintf(bufOut, bufFormat, GetISPName()); lstrcpy(bufAll, bufOut); lstrcat(bufAll, TEXT("\n\n")); } if(*GetISPMessage() != '\0') { lstrcat(bufAll, GetISPMessage()); lstrcat(bufAll, TEXT("\n\n")); } if (LoadString(g_hModule, IDS_EXPIRED_TEXT2, bufFormat, MAX_DIALOGTEXT)) { wsprintf(bufOut, bufFormat, GetISPName(), GetISPName(), GetISPPhone()); lstrcat(bufAll, bufOut); } SetDlgItemText(hDlg, IDC_TEXT1, bufAll); ShowWindow(GetDlgItem(hDlg, IDC_DONTREMIND), SW_HIDE); if (LoadString(g_hModule, IDS_DONOTSIGNUP, bufOut, MAX_DIALOGTEXT)) { SetDlgItemText(hDlg, IDCANCEL, bufOut); } } } else { // Set up the text in the dialog box. if (LoadString(g_hModule, IDS_DLG_TITLE, bufFormat, MAX_DIALOGTEXT)) { wsprintf(bufOut, bufFormat, GetISPTrialDaysLeft()); SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM) bufOut); } if (bufAll) { if (LoadString(g_hModule, IDS_TEXT1, bufFormat, MAX_DIALOGTEXT)) { wsprintf(bufOut, bufFormat, GetISPName(), GetISPTrialDaysLeft()); lstrcpy(bufAll, bufOut); lstrcat(bufAll, TEXT("\n\n")); } if(*GetISPMessage() != '\0') { lstrcat(bufAll, GetISPMessage()); lstrcat(bufAll, TEXT("\n\n")); } if (LoadString(g_hModule, IDS_TEXT2, bufFormat, MAX_DIALOGTEXT)) { wsprintf(bufOut, bufFormat, GetISPName(), GetISPName(), GetISPPhone()); lstrcat(bufAll, bufOut); } SetDlgItemText(hDlg, IDC_TEXT1, bufAll); } // If there are 0 days left then don't give user a change // to say remind me later. if (0 == GetISPTrialDaysLeft()) { ShowWindow(GetDlgItem(hDlg, IDC_DONTREMIND), SW_HIDE); if (LoadString(g_hModule, IDS_DONOTSIGNUP, bufOut, MAX_DIALOGTEXT)) { SetDlgItemText(hDlg, IDCANCEL, bufOut); } } } // Set the timer for how long the dialog will stay up before // removing itself. SetTimer(hDlg, TIMER_DIALOG_STAYUP, GetDialogTimeout(), NULL); CenterTheWindow(hDlg); if (bufAll) { delete [] bufAll; } return TRUE; } case WM_COMMAND: { switch (LOWORD(wParam)) { // IDOK is the Sign up now button. case IDOK: { KillTimer(hDlg, TIMER_DIALOG_STAYUP); EndDialog(hDlg, wParam); break; } // If the checkbox is clicked then toggle the button text for the // signup later button. case IDC_DONTREMIND: { if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_DONTREMIND)) { TCHAR bufOut[MAX_DIALOGTEXT]; if (LoadString(g_hModule, IDS_DONOTREMIND, bufOut, MAX_DIALOGTEXT)) { SetDlgItemText(hDlg, IDCANCEL, bufOut); } } else { TCHAR bufOut[MAX_DIALOGTEXT]; if (LoadString(g_hModule, IDS_SIGNUPLATER, bufOut, MAX_DIALOGTEXT)) { SetDlgItemText(hDlg, IDCANCEL, bufOut); } } break; } // Otherwise assume they hit the close button or the sign up later // button. default: { // See if the user never wants reminded again. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_DONTREMIND)) { g_bDoNotRemindAgain = true; } KillTimer(hDlg, TIMER_DIALOG_STAYUP); EndDialog(hDlg, wParam); break; } } break; } // No user interaction has occurred. remove the dialog but do not count // this as an attempt to sign up. case WM_TIMER: { KillTimer(hDlg, TIMER_DIALOG_STAYUP); EndDialog(hDlg, IDABORT); break; } case WM_PAINT: { HDC hDC; PAINTSTRUCT ps; HICON hIcon; HWND hWndRect; RECT rect; POINT ptUpperLeft; hDC = BeginPaint(hDlg, &ps); hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_QUESTION)); if (hIcon) { hWndRect = GetDlgItem(hDlg, IDC_ICON1); GetWindowRect(hWndRect, &rect); ptUpperLeft.x = rect.left; ptUpperLeft.y = rect.top; ScreenToClient(hDlg, &ptUpperLeft); DrawIcon(hDC, ptUpperLeft.x, ptUpperLeft.y, hIcon); } EndPaint(hDlg, &ps); break; } } return FALSE; UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(hDlg); } //----------------------------------------------------------------------------- // CheckForRASConnection //----------------------------------------------------------------------------- BOOL CheckForRASConnection() { RASCONNSTATUS rascs; RASCONN rasConn[MAXRASCONNS]; DWORD dwEntries = MAXRASCONNS; DWORD dwSize = sizeof(rasConn); DWORD dwRet; BOOL bRetCode = FALSE; // This is the connection name of the ISP the user has signed up // with. We will look for a connectiod with this same name. const TCHAR* pszConnectionName = GetISPConnectionName(); if (NULL == pszConnectionName || 0 == lstrlen(pszConnectionName)) { return FALSE; } for (int i = 0; i < MAXRASCONNS; ++i) { rasConn[i].dwSize = sizeof(RASCONN); } dwRet = RasEnumConnections(rasConn, &dwSize, &dwEntries); if (dwRet == 0) { for (dwRet = 0; dwRet < dwEntries; dwRet++) { // If this is the connection we are looking for let's make // sure the connection is all set to go. if (0 == lstrcmpi(pszConnectionName, rasConn[dwRet].szEntryName)) { rascs.dwSize = sizeof(RASCONNSTATUS); dwRet = RasGetConnectStatus(rasConn[dwRet].hrasconn, &rascs); if (dwRet == 0 && rascs.rasconnstate == RASCS_Connected) { bRetCode = TRUE; } } } } return bRetCode; } //----------------------------------------------------------------------------- // CheckForSignupAttempt // // This method contains the logic that check to see if we should make an attempt // to pop up the sign up dialog. If we should make an attempt will will then // enum the RAS connections to see if the user is connected before popping // up the dialog. //----------------------------------------------------------------------------- void CheckForSignupAttempt() { int nDaysLeft = GetISPTrialDaysLeft(); int nRetValue = 0; // Every some many signup attempts lets read the registry and see if // a successful signup happened. ++g_nAttemptCounter; if (MAX_ATTEMPTCOUNTER == g_nAttemptCounter) { g_nAttemptCounter = 0; if (IsSignupSuccessful()) { ShutDownForGood(); return; } // If the trial is expired then set the IE run once key. if (nDaysLeft < -1) { SetIERunOnce(); } } // If we are in negative days left then do not do anything. This means // the trail is over and the user has not signed up. We will give // them one more signup attempt on application start up. if (nDaysLeft < 0) { return; } bool bAttemptSignup = false; // Based on the total signup notificaiton attempts we will determine // if the days left requires another attempt. switch (GetTotalNotifications()) { // If we have not made any attempts yet then if we are at the half // way point in the trial or past the half way point we will make // a signup attempt. case 0: { if (nDaysLeft <= (int)(GetISPTrialDays() / 2)) { bAttemptSignup = true; } break; } // If we have already perfomed 1 attempt then the second attempt // will come on the next to last day or the last day. case 1: { if (nDaysLeft <= 1) { bAttemptSignup = true; } break; } // The 3rd attempt will not come until the last day. case 2: { if (nDaysLeft == 0) { bAttemptSignup = true; } break; } default: { break; } } if (bAttemptSignup) { if (CheckForRASConnection()) { // Before actually showing the dialog do a quick check to see // if a previous signup was successful. If so we will shut // down for good. if (IsSignupSuccessful()) { ShutDownForGood(); return; } g_bDialogExpiredMode = false; //if we have an isp message we need the right dlg template if(*GetISPMessage() != '\0') nRetValue = (int)DialogBox(g_hModule, MAKEINTRESOURCE(IDD_SIGNUP_ISPMSG), g_hwndMain, SignUpDialogProc); else nRetValue = (int)DialogBox(g_hModule, MAKEINTRESOURCE(IDD_SIGNUP), g_hwndMain, SignUpDialogProc); switch (nRetValue) { // The user wants to try and signup. case IDOK: { PerformTheSignup(); break; } // The user said signup later. Check to see if the don't remind // me button was pressed. If so then shut down for good. case IDCANCEL: { // If this is the last day of the trial then the remind // me later button is not the Don't signup button. In // this case shut down for good. if (0 == nDaysLeft) { ShutDownForGood(); } else { IncrementTotalNotifications(); if (g_bDoNotRemindAgain) { ShutDownForGood(); } } break; } // The dialog timed out. Don't do anything. The does not // count as an attempt. case IDABORT: { break; } // No work in here, in fact we should not get here. default: { _ASSERT(false); break; } } // If there is 1 day left let's make sure that total notifications // is 2. If not the dialog may pop up multiple times. Oh yea, // if dialog timed out then don't do this. if (IDABORT != nRetValue && 1 == nDaysLeft && 1 == GetTotalNotifications()) { IncrementTotalNotifications(); } } } } //----------------------------------------------------------------------------- // GetISPTrialDaysLeft //----------------------------------------------------------------------------- int GetISPTrialDaysLeft() { // Calculate the relative current time. The current system time cannot // be trusted if the System date/time dialog is up. That dialog will // change the actual system time when every the user pokes around even // before hitting OK or Apply!!! time_t timeRelativeCurrent = g_timeAppStartUp + (GetTickDelta() / 1000); // The relative time and the trial start date are both time_t type // variables which are in seconds. int nSecondsSinceStart = (int)(timeRelativeCurrent - GetTrialStartDate()); // Now convert seconds into days. There are 86400 seconds in a day. // Note that we will always round up one more day if there is any // remainder. div_t divResult = div(nSecondsSinceStart, 86400); int nDaysSinceStart = divResult.quot; if (divResult.rem) { ++nDaysSinceStart; } #ifdef _DEBUG TCHAR buf[255]; wsprintf(buf, TEXT("Days Since = %i\n"), nDaysSinceStart); OutputDebugString(buf); wsprintf(buf, TEXT("Check: %s\n"), ctime(&timeRelativeCurrent)); OutputDebugString(buf); time_t tt = GetTrialStartDate(); wsprintf(buf, TEXT("Start: %s\n"), ctime(&tt)); OutputDebugString(buf); #endif int nDaysLeft = GetISPTrialDays() - nDaysSinceStart; #ifdef _DEBUG wsprintf(buf, TEXT("Days Left = %i\r\n"), nDaysLeft); OutputDebugString(buf); #endif return nDaysLeft; } //----------------------------------------------------------------------------- // ShutDownForGood //----------------------------------------------------------------------------- void ShutDownForGood() { RemoveRunOnce(); RemoveIERunOnce(); DeleteAllRegistryData(); PostMessage(g_hwndMain, WM_CLOSE, 0, 0); } //----------------------------------------------------------------------------- // PerformTheSignup //----------------------------------------------------------------------------- void PerformTheSignup() { // Note that we do not shut down for good. The sign up may fail so // simply increment the notification count. const TCHAR* pcszSignupUrl = GetISPSignupUrl(); ShellExecute(g_hwndMain, TEXT("open"), pcszSignupUrl, TEXT(""), TEXT(""), SW_SHOW); IncrementTotalNotifications(); } //----------------------------------------------------------------------------- // CenterTheWindow //----------------------------------------------------------------------------- void CenterTheWindow(HWND hWnd) { HDC hDC = GetDC(hWnd); if (hDC) { int nScreenWidth = GetDeviceCaps(hDC, HORZRES); int nScreenHeight = GetDeviceCaps(hDC, VERTRES); RECT rect; GetWindowRect(hWnd, &rect); // Also make the window "always on top". SetWindowPos(hWnd, HWND_TOPMOST, (nScreenWidth / 2) - ((rect.right - rect.left) / 2), (nScreenHeight / 2) - ((rect.bottom - rect.top) / 2), rect.right - rect.left, rect.bottom - rect.top, SWP_SHOWWINDOW); ReleaseDC(hWnd, hDC); } } //----------------------------------------------------------------------------- // GetTickDelta //----------------------------------------------------------------------------- DWORD GetTickDelta() { // This function returns the delta between the startup tick count and // the current tick count. Note that we must watch for a rollover in // the tick count. DWORD dwTickDelta; DWORD dwTickCurrent = GetTickCount(); // If tick count rolls over we need to reset the app start up date // and the app tick count in case we roll over a second time. if (dwTickCurrent < g_dwTickAppStartUp) { // Calculate the delta by finding out how many ticks to the MAX // tick count a DWORD can handle and then add the wrap around amount. DWORD dwDeltaToMax = 0xFFFFFFFF - g_dwTickAppStartUp; dwTickDelta = dwDeltaToMax + dwTickCurrent; // Modify the application startup by the delta in seconds that have // passed since it was last set. Also reset startup tick count // to current tick for our new frame of reference. g_timeAppStartUp += (dwTickDelta / 1000); // Convert to seconds. g_dwTickAppStartUp = dwTickCurrent; // Since we have modified the application start up date relative // to the current tick count and changed the app start up tick // count to the current tick count, the delta is zero. dwTickDelta = 0; } else { dwTickDelta = dwTickCurrent - g_dwTickAppStartUp; } return dwTickDelta; } //----------------------------------------------------------------------------- // AttemptTrialOverSignup //----------------------------------------------------------------------------- void AttemptTrialOverSignup() { int nRetValue = 0; // Setup the run once data for IE. g_bDialogExpiredMode = true; if(*GetISPMessage() != '\0') nRetValue = (int)DialogBox(g_hModule, MAKEINTRESOURCE(IDD_SIGNUP_ISPMSG), g_hwndMain, SignUpDialogProc); else nRetValue = (int)DialogBox(g_hModule, MAKEINTRESOURCE(IDD_SIGNUP), g_hwndMain, SignUpDialogProc); RemoveIERunOnce(); switch (nRetValue) { // The user wants to try and signup. case IDOK: { const TCHAR* pcszSignupUrl = GetISPSignupUrlTrialOver(); ShellExecute(g_hwndMain, TEXT("open"), pcszSignupUrl, TEXT(""), TEXT(""), SW_SHOW); ShutDownForGood(); break; } case IDCANCEL: { ShutDownForGood(); break; } // If we get IDABORT the dialog timed out so don't do anything. case IDABORT: { break; } // No work in here, in fact we should not get here. default: { _ASSERT(false); ShutDownForGood(); break; } } } extern "C" void _stdcall ModuleEntry (void) { LPTSTR pszCmdLine = GetCommandLine(); if ( *pszCmdLine == TEXT('\"') ) { /* * Scan, and skip over, subsequent characters until * another double-quote or a null is encountered. */ while ( *++pszCmdLine && (*pszCmdLine != TEXT('\"')) ) ; /* * If we stopped on a double-quote (usual case), skip * over it. */ if ( *pszCmdLine == TEXT('\"') ) pszCmdLine++; } else { while (*pszCmdLine > TEXT(' ')) pszCmdLine++; } /* * Skip past any white space preceeding the second token. */ while (*pszCmdLine && (*pszCmdLine <= TEXT(' '))) { pszCmdLine++; } int i = WinMainT(GetModuleHandle(NULL), NULL, pszCmdLine, SW_SHOWDEFAULT); ExitProcess(i); // Were outa here.... } /* ModuleEntry() */