fakedate.ini:
[fakedate]
; program to run
run=progname.exe
; Extra command line arguments for the application
; Note: FakeDate passes on any command line arguments that are passed
; to it by Windows
; If you want to pass extra arguments, uncomment the following line and
; fill in the arguments
;cmdline=""
; faked date
date=1994/01/31
; stay resident / re-fake date every 10 seconds
stay=yes
timer=10
; normal logging mode
debug=no
fakedate.cpp:
//////////////////////////////////////////////////////////////////////////////
// FakeDate\fakedate.cpp Padre & Lord Link 06/1999
;
//
http://www.g
eocities.com/yesh20 Mail: yesh20@yahoo.com
//////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <direct.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// versions
// --------
// 1.000 1999/06/18 initial
// 1.001 1999/12/31 bug fix: LogC
lose time now correct
static TCHAR FD_version[] = "FakeDate version 1.001, 1
57;99/12/31";
// constants...
// ...general
const int FD_maxargs = 256;
const int FD_unspecified = -1;
const int FD_buflen = 4096;
const TCHAR FD_realname[] = "fakedate";
// ...default values for user-definable parameters
const int FD_defaultCleanup = 5;
const int FD_defaultTimer = 10;
// recongnized parameter values
const TCHAR FD_showMaximized[] = "maximize";
const TCHAR FD_showMinimized[] = "minimize";
const TCHAR FD_showNormal[] = "normal";
// ...command line options
const TCHAR FD_debug[] = "debug";
const TCHAR FD_profile[] = "profile";
const TCHAR FD_runapp[] = "run";
const TCHAR FD_cmdline[] = "cmdline";
const TCHAR FD_date[] = "date";
const TCHAR FD_timer[] = "timer";
const TCHAR FD_stay[] = "stay";
const TCHAR FD_cleanup[] = "cleanup";
const TCHAR FD_window[] = "window";
const TCHAR FD_optstring[] = "-fakedateargs";
// ...error levels
const TCHAR FD_info[] = "Info ";
const TCHAR FD_warn[] = "Warning";
const TCHAR FD_error[] = "Error ";
const TCHAR FD_fatal[] = "Fatal ";
// miscellaneous
const TCHAR FD_separator[] = "----------------------------------------&
#34;
"--------------------------------------\n&
#34;;
const TCHAR FD_mutexwarning[] = "There's another instance of %s &
#34;
"running! This will probably lead to "
"conflicts regarding date manipulation.
34;
"Do you wish to continue anyway?";
const TCHAR FD_mutexerror[] = "Unable to find out if there are othe
r "
"%s instances running!\nAborting program.&
#34;;
// array for command line arguments
static struct {
int argc;
TCHAR* argv[FD_maxargs];
} FD_Args = {
0, ""
};
// global variables
static struct {
// user-definable parameters
TCHAR* profile; TCHAR* dateArg;
TCHAR* runapp; TCHAR* cmdline;
TCHAR* windowArg; int debug;
int stay; long timer;
long childCleanup; int cmdShow;
// process characteristics
HANDLE runappHandle; DWORD runappThreadID;
// time-specific variables
SYSTEMTIME systmOrig; SYSTEMTIME systmFaked;
time_t elapsedSeconds;
// logging-specific variables
FILE* log;
} FD_Globals = {
NULL, NULL, NULL, NULL, NULL,
FD_unspecified, FD_unspecified, FD_unspecified, FD_unspecified, FALSE,
NULL, 0,
{0, 0, 0, 0, 0, 0, 0, 0 }, {0, 0, 0
;, 0, 0, 0, 0, 0 }, 0,
NULL
};
int GetSemaphore()
{
TCHAR message[FD_buflen];
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
HANDLE handle = CreateMutex(&sa, FALSE, FD_realname);
if (GetLastError() == ERROR_ALREADY_EXISTS) {
sprintf(message, FD_mutexwarning, FD_realname);
return((MessageBox(NULL, message, FD_warn, MB_YESNO |
MB_ICONWARNING) == IDYES) ? 0 : 1);
}
if (handle == NULL) {
sprintf(message, FD_mutexerror, FD_realname);
MessageBox(NULL, message, FD_error, MB_OK | MB_ICONERROR);
return(-1);
}
return(0);
}
int LogInit()
{
int rc = 0;
TCHAR logFilename[MAX_PATH+1];
TCHAR drive[_MAX_DRIVE];
TCHAR dir[_MAX_DIR];
_splitpath(__argv[0], drive, dir, NULL, NULL);
_stprintf(logFilename, "%c:%s%s.log", *drive, dir, FD_realname);
// open log file
if ((FD_Globals.log = fopen(logFilename,"wc")) == NULL) {
FD_Globals.log = stderr;
_ftprintf(stderr, "Unable to open file '%s' as log file, using s
tderr.\n",
logFilename);
rc = -1;
}
// generate starting message
// initialize time
GetLocalTime(&FD_Globals.systmOrig);
_ftprintf(FD_Globals.log, "Error logging of %s started on %04d/%02
d/%02d, "
"%02d:%02d:%02d GMT\n", FD_realname,
FD_Globals.systmOrig.wYear, FD_Globals.systmOrig.wMonth,
FD_Globals.systmOrig.wDay, FD_Globals.systmOrig.wHour,
FD_Globals.systmOrig.wMinute, FD_Globals.systmOrig.wSecond);
_ftprintf(FD_Globals.log, FD_separator);
return(rc);
}
int Log(const TCHAR* level, TCHAR* message, ...)
{
if (message == NULL)
return(-1);
// print informationals only in debug mode
if (!_tcsicmp(level, FD_info) && FD_Globals.debug != 1)
return(0);
TCHAR* logMsg = new TCHAR[FD_buflen];
va_list varArgs;
va_start(varArgs, message);
_vstprintf(logMsg, message, varArgs);
// compute time
long elapsedSeconds = FD_Globals.elapsedSeconds;
long hrs = (long)elapsedSeconds / 3600;
long min = ((long)elapsedSeconds - hrs*3600) / 60;
long sec = elapsedSeconds % 60;
// print log message
if (_ftprintf(FD_Globals.log, "[%02ld:%02ld:%02ld] %s : %s\n
34;,
hrs, min, sec, level, logMsg) < 0) {
fprintf(stderr,"Log: Write to log failed!\n");
return(-1);
}
return(0);
}
void LogClose()
{
// Generate goodbye message
_ftprintf(FD_Globals.log, FD_separator);
_ftprintf(FD_Globals.log, "Error logging terminated on %04d/%02d/%
02d, "
"%02d:%02d:%02d GMT",
FD_Globals.systmOrig.wYear, FD_Globals.systmOrig.wMonth,
FD_Globals.systmOrig.wDay, FD_Globals.systmOrig.wHour,
FD_Globals.systmOrig.wMinute, FD_Globals.systmOrig.wSecond);
// close log file
if (FD_Globals.log != stderr)
fclose(FD_Globals.log);
}
// helper function: read command line string
void String2Args(TCHAR* string)
{
BOOL quote = FALSE;
TCHAR* buffer = new TCHAR[_tcslen(string)];
TCHAR* pbuf = buffer;
TCHAR* p = string;
TCHAR* p2 = p;
while (*p2) {
if ((*p2 == ' ' || *p2 == '\t') && !quote) {
if (_tcslen(p)) {
*pbuf = 0;
if (FD_Args.argc < FD_maxargs) {
FD_Args.argv[FD_Args.argc] = new char[_tcslen(buffer)+1];
_tcscpy(FD_Args.argv[FD_Args.argc++], buffer);
}
pbuf = buffer;
}
p = p2 + 1;
} else if (*p2 == '\"' && (p2 == p || *(p2-1) != '\\'
;))
quote = !quote;
else if (*p2 == '\"')
--*pbuf++ = *p2;
else
*pbuf++ = *p2;
p2++;
};
if (_tcslen(p)) {
*pbuf = 0;
if (FD_Args.argc < FD_maxargs) {
FD_Args.argv[FD_Args.argc] = new char[_tcslen(buffer)+1];
_tcscpy(FD_Args.argv[FD_Args.argc++], buffer);
}
pbuf = buffer;
}
delete[] buffer;
}
// get specified argument from command line string
TCHAR* GetArg(const TCHAR* argname)
{
if (argname == NULL)
return(NULL);
for (int arg=0; arg<FD_Args.argc; arg++)
if ((*FD_Args.argv[arg] == '-' || *FD_Args.argv[arg] == '/')
&& !_tcsicmp(argname, FD_Args.argv[arg]+1))
return((arg < FD_Args.argc - 1)
? FD_Args.argv[arg+1] : strdup(""));
return(NULL);
}
// parse the command line string
void ParseCommandLine(TCHAR* commandLine)
{
TCHAR* p;
String2Args(commandLine);
if (GetArg(FD_debug) != NULL)
FD_Globals.debug = TRUE;
FD_Globals.profile = GetArg(FD_profile);
FD_Globals.runapp = GetArg(FD_runapp);
FD_Globals.cmdline = GetArg(FD_cmdline);
FD_Globals.dateArg = GetArg(FD_date);
if (GetArg(FD_stay) != NULL)
FD_Globals.stay = 1;
if ((p = GetArg(FD_timer)) != NULL)
FD_Globals.timer = atol(p);
if ((p = GetArg(FD_cleanup)) != NULL)
FD_Globals.childCleanup = atol(p);
FD_Globals.windowArg = GetArg(FD_window);
}
// change to the directory the child application runs in
void ChangeDirToRunApp()
{
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
if (FD_Globals.runapp == NULL)
return;
_splitpath(FD_Globals.runapp, drive, dir, fname, ext);
if (*drive != 0)
_chdrive(*drive - 'A');
if (*dir != 0)
_tchdir(dir);
}
// determine location of profile
// the search order is:
// 1. the child application's directory
// 2. the directory where fakedate resides
// 3. the current working directory
BOOL GetProfileLocation()
{
// check if profile was specified on the command line
if (FD_Globals.profile != NULL)
return((access(FD_Globals.profile, 0)) ? FALSE : TRUE);
// if a child application was specified, change to the
// application's directory
FD_Globals.profile = new char[MAX_PATH+1];
if (FD_Globals.runapp != NULL) {
ChangeDirToRunApp();
_tgetcwd(FD_Globals.profile, MAX_PATH-13);
_tcscat(FD_Globals.profile, "\\");
_tcscat(FD_Globals.profile, FD_realname);
_tcscat(FD_Globals.profile, ".ini");
if (!access(FD_Globals.profile, 0))
return(TRUE);
}
// expect profile to be in the directory where fakedate resides
TCHAR drive[_MAX_DRIVE];
TCHAR dir[_MAX_DIR];
_splitpath(__argv[0], drive, dir, NULL, NULL);
_stprintf(FD_Globals.profile, "%c:%s%s.ini", *drive, dir, FD_realname)
;
if (!access(FD_Globals.profile, 0))
return(TRUE);
// last chance: current working directory becomes directory for profile
_tgetcwd(FD_Globals.profile, MAX_PATH-13);
_tcscat(FD_Globals.profile, "\\");
_tcscat(FD_Globals.profile, FD_realname);
_tcscat(FD_Globals.profile, ".ini");
return((access(FD_Globals.profile, 0)) ? FALSE : TRUE);
}
// read INI file
void ReadPrivateProfile()
{
// try to find profile
BOOL profileExists = GetProfileLocation();
if (!profileExists)
Log(FD_warn, "Unable to find profile!");
else
Log(FD_info, "Reading profile '%s'.", FD_Globals.profile);
// read keys from profile...
// ...first look for debug flag (needed to determine if the
// next informational should be written to log file)
if (FD_Globals.debug == FD_unspecified) {
TCHAR s[256] = "";
GetPrivateProfileString(FD_realname, FD_debug, "", s,
256, FD_Globals.profile);
FD_Globals.debug = (!_tcsicmp(s, "yes")) ? 1 : 0;
}
if (FD_Globals.runapp == NULL) {
FD_Globals.runapp = new char[MAX_PATH+1];
GetPrivateProfileString(FD_realname, FD_runapp, "", FD_Globals.runap
p,
MAX_PATH+1, FD_Globals.profile);
}
ChangeDirToRunApp();
if (FD_Globals.cmdline == NULL) {
FD_Globals.cmdline = new char[256];
GetPrivateProfileString(FD_realname, FD_cmdline, "", FD_Globals.cmdl
ine,
256, FD_Globals.profile);
}
if (FD_Globals.dateArg == NULL) {
FD_Globals.dateArg = new char[40];
GetPrivateProfileString(FD_realname, FD_date, "", FD_Globals.dateArg
,
40, FD_Globals.profile);
}
if (FD_Globals.stay == FD_unspecified) {
TCHAR s[256] = "";
GetPrivateProfileString(FD_realname, FD_stay, "", s,
256, FD_Globals.profile);
FD_Globals.stay = (!_tcsicmp(s, "yes")) ? 1 : 0;
}
if (FD_Globals.timer == FD_unspecified)
FD_Globals.timer = GetPrivateProfileInt(FD_realname, FD_timer,
0, FD_Globals.profile);
if (FD_Globals.childCleanup == FD_unspecified)
FD_Globals.childCleanup = GetPrivateProfileInt(FD_realname, FD_cleanup,
0, FD_Globals.profile);
if (FD_Globals.windowArg == NULL) {
FD_Globals.windowArg = new char[256];
GetPrivateProfileString(FD_realname, FD_window, "", FD_Globals.windo
wArg,
256, FD_Globals.profile);
}
// set show window parameter
if (FD_Globals.windowArg != NULL && *(FD_Globals.windowArg) != 0) {
if (!strcmp(FD_Globals.windowArg, FD_showMaximized))
FD_Globals.cmdShow = SW_SHOWMAXIMIZED;
else if (!strcmp(FD_Globals.windowArg, FD_showMinimized))
FD_Globals.cmdShow = SW_SHOWMINNOACTIVE;
else if (!strcmp(FD_Globals.windowArg, FD_showNormal))
FD_Globals.cmdShow = SW_SHOWNORMAL;
else
Log(FD_warn, "Unknown value for window appearance parameter: '%s
39;",
FD_Globals.windowArg);
}
}
// compute the faked date
BOOL ComputeFakedDate()
{
TCHAR* p = _tcsdup(FD_Globals.dateArg);
TCHAR* p2, *p3;
if ((p2 = _tcschr(p, '/')) == NULL ||
(p3 = _tcschr(p2+1, '/')) == NULL)
return(FALSE);
*p2++ = 1;
*p3++ = 0;
if ((FD_Globals.systmFaked.wYear = atoi(p)) <= 0 ||
(FD_Globals.systmFaked.wMonth = atoi(p2)) <= 0 ||
(FD_Globals.systmFaked.wDay = atoi(p3)) <= 0)
return(FALSE);
free(p);
return(TRUE);
}
// helper function: check if all essential parameters were supplied
BOOL CheckEssentialParams()
{
Log(FD_info, "Checking essential parameters...");
if (FD_Globals.runapp == NULL || *FD_Globals.runapp == 0) {
Log(FD_error, "No application to run.");
return(FALSE);
} else
Log(FD_info, "...child application: '%s'", FD_Globals.runapp
);
if (FD_Globals.stay != 1 && FD_Globals.timer <= 0) {
TCHAR s[] = "<unspecified>";
if (FD_Globals.timer != FD_unspecified)
_stprintf(s, "%d", FD_Globals.timer);
Log(FD_error, "Illegal combination of '%s' and '%s' valu
es: "
"(%s, %s)", FD_stay, FD_timer,
(FD_Globals.stay) ? "True" : "False", s);
return(FALSE);
} else {
Log(FD_info, "...stay-resident flag: %s",
(FD_Globals.stay) ? "True" : "False");
Log(FD_info, "...timer value: %ld seconds", FD_Globals.timer);
}
if (!ComputeFakedDate()) {
Log(FD_error, "Wrong date format: '%s'", FD_Globals.dateArg)
;
return(FALSE);
} else
Log(FD_info, "...faked date: %s", FD_Globals.dateArg);
if (FD_Globals.childCleanup < 0)
FD_Globals.childCleanup = FD_defaultCleanup;
return(TRUE);
}
// well...
BOOL FakeDate(BOOL saveSystemTime)
{
SYSTEMTIME systmCurrent;
GetLocalTime(&systmCurrent);
FD_Globals.systmFaked.wHour = systmCurrent.wHour;
FD_Globals.systmFaked.wMinute = systmCurrent.wMinute;
FD_Globals.systmFaked.wSecond = systmCurrent.wSecond;
if (saveSystemTime) {
FD_Globals.systmOrig = systmCurrent;
Log(FD_info, "Old system time: %02d/%02d/%02d %02d:%0
;2d:%02d GMT",
FD_Globals.systmOrig.wYear, FD_Globals.systmOrig.wMonth,
FD_Globals.systmOrig.wDay, FD_Globals.systmOrig.wHour,
FD_Globals.systmOrig.wMinute, FD_Globals.systmOrig.wSecond);
}
if (!SetLocalTime(&FD_Globals.systmFaked)) {
Log(FD_error, "Call of SetLocalTime() returned error %ld",
GetLastError());
return(FALSE);
} else
Log(FD_info, "System time set to current time on faked date.");
return(TRUE);
}
// start child application
BOOL LaunchChildApp()
{
STARTUPINFO StartupInfo = { sizeof(STARTUPINFO), NULL, NULL, NULL,
0, 0, 0, 0, 0, 0, 0,
(FD_Globals.cmdShow) ? STARTF_USESHOWWINDOW : 0
;,
FD_Globals.cmdShow,
0, NULL, NULL, NULL, NULL };
PROCESS_INFORMATION ProcInfo;
TCHAR* fullCmdLine;
if (FD_Globals.cmdline == NULL)
fullCmdLine = FD_Globals.runapp;
else {
fullCmdLine = new TCHAR[_tcslen(FD_Globals.runapp) +
_tcslen(FD_Globals.cmdline) + 2];
_stprintf(fullCmdLine, "%s %s", FD_Globals.runapp, FD_Globals.cmdlin
e);
}
Log(FD_info, "Starting child '%s'...", FD_Globals.runapp);
Log(FD_info, "...command line string: '%s'", FD_Globals.cmdlin
e);
if (!CreateProcess(NULL, fullCmdLine,
NULL, NULL, FALSE, FALSE, NULL, NULL,
&StartupInfo, &ProcInfo)) {
Log(FD_error, "Unable to start child '%s' -- error %ld.",
FD_Globals.runapp, GetLastError());
return(FALSE);
} else
Log(FD_info, "...child launched successfully.", FD_Globals.runapp);
if (FD_Globals.cmdline != NULL)
delete fullCmdLine;
FD_Globals.runappHandle = ProcInfo.hProcess;
FD_Globals.runappThreadID = ProcInfo.dwThreadId;
return(TRUE);
}
// callback function called by windows (the function is called once for each
// of the child application's top-level windows when fakedate requests to
// end the child application)
BOOL CALLBACK EnumChildCallback(HWND hwnd, LPARAM)
{
PostMessage(hwnd, WM_CLOSE, 0, 0);
return(TRUE);
}
// end child application (two-step mechanism: first a polite request, then
// the hard way if necessary)
void KillChildApp()
{
if (FD_Globals.childCleanup > 0) {
Log(FD_info, "Asking child application to exit...");
if (!EnumThreadWindows(FD_Globals.runappThreadID,
(WNDENUMPROC)EnumChildCallback, 0))
Log(FD_error, "...unable to determine window handle of child.");
else {
int rc = WaitForSingleObject(FD_Globals.runappHandle,
1000*FD_Globals.childCleanup)
;
switch(rc) {
case WAIT_OBJECT_0:
Log(FD_info, "...child did an exit.");
return;
case WAIT_TIMEOUT:
Log(FD_error, "Child didn't exit within %d seconds.",
FD_Globals.childCleanup);
break;
default:
Log(FD_error, "Unable to wait for child termination.");
break;
}
}
}
// this code is executed only if soft termination of child failed
// or allowed child cleanup time is zero
Log(FD_warn, "Terminating child without notifying it.");
TerminateProcess(FD_Globals.runappHandle, 0);
}
// helper function: convert system time to large integer
// (which is then stored)
LARGE_INTEGER LargeIntFromSysTime(SYSTEMTIME* systm)
{
FILETIME filetm;
LARGE_INTEGER timeval;
SystemTimeToFileTime(systm, &filetm);
timeval.LowPart = filetm.dwLowDateTime;
timeval.HighPart = filetm.dwHighDateTime;
return(timeval);
}
// helper function: convert large integer to system time
void SysTimeFromLargeInt(SYSTEMTIME* systm, LARGE_INTEGER* timeval)
{
FILETIME filetm;
filetm.dwLowDateTime = timeval->LowPart;
filetm.dwHighDateTime = timeval->HighPart;
FileTimeToSystemTime(&filetm, systm);
}
// restore original date (the time elapsed since the start of fakedate
// is added)
void RestoreDate()
{
Log(FD_info, "Restoring system time...");
long hrs = (long)FD_Globals.elapsedSeconds / 3600;
long min = ((long)FD_Globals.elapsedSeconds - hrs*3600) / 60;
long sec = FD_Globals.elapsedSeconds % 60;
Log(FD_info, "...elapsed time since start of program: "
"%ldh %02d:%02ld", hrs, min, sec);
// add elapsed time since start of fake job to original time
LARGE_INTEGER timevalOrig = LargeIntFromSysTime(&FD_Globals.systmOrig);
timevalOrig.QuadPart += (LONGLONG)(1e+7)*FD_Globals.elapsedSeconds;
// restore system time
SYSTEMTIME systmNewReal;
SysTimeFromLargeInt(&systmNewReal, &timevalOrig);
FD_Globals.systmOrig = systmNewReal;
if (SetLocalTime(&systmNewReal))
Log(FD_info, "...system time restored.");
else
Log(FD_error, "Call of SetLocalTime() returned error %ld",
GetLastError());
}
// the main processing loop
BOOL StartFakeDateJob()
{
// set faked date, but save original system time
if (!FakeDate(TRUE)) {
Log(FD_error, "Unable to set faked date!");
return(FALSE);
}
if (!LaunchChildApp()) {
RestoreDate();
Log(FD_error, "Launch of child '%s' failed.", FD_Globals.run
app);
return(FALSE);
}
// main processing loop...
// ...stay resident?...
if (FD_Globals.stay != 1) {
// ...no - wait once, then restore date and exit
Sleep(1000*FD_Globals.timer);
FD_Globals.elapsedSeconds = FD_Globals.timer;
Log(FD_info, "One-time waiting period ended.");
RestoreDate();
return(TRUE);
}
// ...yes -- loop until child application exits
// (store elapsed time since start of processing)
long timer = (FD_Globals.timer > 0) ? FD_Globals.timer : FD_defaultTim
er;
DWORD rc;
time_t tm;
do {
time(&tm);
rc = WaitForSingleObject(FD_Globals.runappHandle, 1000*timer
);
if (rc == WAIT_TIMEOUT) {
// re-fake date if a timer value was specified
FD_Globals.elapsedSeconds += timer;
if (FD_Globals.timer != 0)
FakeDate(FALSE);
}
} while (rc == WAIT_TIMEOUT);
time_t tmNew;
time(&tmNew);
FD_Globals.elapsedSeconds += (tmNew - tm);
switch(rc) {
DWORD exitCode;
case WAIT_OBJECT_0:
if (!GetExitCodeProcess(FD_Globals.runappHandle, &exitCode))
Log(FD_info, "Child exited -- unable to determine exit cod
e");
else
Log(FD_info, "Child left with exit code %ld", exitCode
);
RestoreDate();
return(TRUE);
case WAIT_FAILED:
Log(FD_error, "Call to WaitForSingleObject() returned error %ld.",
GetLastError());
KillChildApp();
RestoreDate();
return(FALSE);
default:
Log(FD_error, "Unexpected return code from WaitForSingleObject():
"
"%ld", rc);
KillChildApp();
RestoreDate();
return(FALSE);
}
}
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int)
{
// check if there's another FakeDate running
if (GetSemaphore() != 0)
return(0);
// initialize error logging
LogInit();
// look for special string signalling existence of further
// command line options
if (_tcsstr(lpCmdLine, FD_optstring) == lpCmdLine)
ParseCommandLine(lpCmdLine+_tcslen(FD_optstring+1));
// no such string present...
else if (*lpCmdLine != 0) {
// ...but command line arguments were specified, so save the whole
// argument string to pass it to the child application later
FD_Globals.cmdline = new char[_tcslen(lpCmdLine)+1];
_tcscpy(FD_Globals.cmdline, lpCmdLine);
}
ReadPrivateProfile();
if (!CheckEssentialParams())
Log(FD_fatal, "Essential parameter(s) missing or invalid!");
// start main processing loop
else if (!StartFakeDateJob())
Log(FD_fatal, "Fake job unsuccessful!");
// terminate error logging
LogClose();
return(0);
}
//////////////////////////////////////////////////////////////////////////////
// This is the end, my friend
//////////////////////////////////////////////////////////////////////////////
FAKEDATE.TXT:
//////////////////////////////////////////////////////////////////////////////
// FakeDate\fakedate.txt Padre & Lord Link 06/199
;9
//
http://www.g
eocities.com/yesh20 Mail: yesh20@yahoo.com
//////////////////////////////////////////////////////////////////////////////
This is the documentation to FakeDate.
Versions of this text file:
---------------------------
V1.000 1999/06/18 initial
V1.001 1999/12/31 included 'Ex
;ample'
V1.002 2000/01/11 updated information
about Windows file types
What's a date cracker?
----------------------
A date cracker is a tool that fools other applications by temporarily changing
the system time. There are several reasons why one would want to to this:
* Many applications, like trial versions or beta test versions of new
programs, will only run during a certain time span after the installation.
The date cracker is used to pretend to them that they're always running at
the same date.
* Some programs may have whatever problems running at certain times. The most
infamous example here is the Y2K problem. The date cracker is used as a
workaround for this problem.
Why do I need a tool for that?
------------------------------
Good question - why not just setting the system time back and forward
manually when starting an application that has "date problems"? Again th
ere
are several possible reasons:
* If you use a program frequently, you most certainly don't want to set the
time back and forth at every session.
* It would also be hard to remember which date you have to pretend to which
application. This is so important because some programs will recognize it
when the system time is older than the installation time of the program, in
which case they won't run.
* There's a reason why it's better to restore the 'real' date as
soon as
possible: If the program makes use of the system time information in any way
and gets the 'wrong' date back, you might run into problems.
* If the system clock is adjusted to real time periodically, e.g. via the
Internet, setting the time manually doesn't help much.
* In case you're not perfect, you might just forget to reset the date ;-) -
note that there's a very serious background to this: Some evil programs wi
ll
do awful things like 'stamping' your hard disk when they see that thei
r
trial days are over. This means that they won't run anymore after that,
until you format your hard disk.
The Conclusion?
---------------
Let's say you have a number of applications, and you have to pretend to each
of them a specific date. Some of those applications check the date once a
while, some of them only once when they're started, etc. Wouldn't it be
better
to be able to configure the 'date faking' options for them individually
instead of having to watch over all this each time?
Platforms
---------
FakeDate was developed and tested under Windows 95 and Windows NT 4.0.
How it works
------------
FakeDate is designed to run in the background and therefore doesn't have a
user interface. There are three ways to tell it what to do:
* Passing arguments on the command line, or
* using an INI file, or
* using a combination of both methods.
If you use an INI file only, you have to name it "fakedate.ini" and plac
e it
in the directory where fakedate resides. FakeDate will find and interpret it
automatically then. If you want the existing Windows shortcuts and Start me
nu
entries to your target application to work as before, you have to rename the
target application to something else, then put fakedate.ini and fakedate.ex
e
into the target application's directory, rename fakedate.exe to the ori
ginal
name of the target application and finally adjust fakedate.ini so that it
starts the target application with the name you gave it.
Important note: If your target application is registered as the default
application for one or more document types (such as Corel Draw for .cdr files
etc.), and you rename the application, Windows updates the registry to reflect
the changes, i.e. if you open a file associated with the application, the
renamed application will _still_ get started. There are two possibilities to
avoid this:
1. Update the 'file types' information in Explorer manually to
make sure
FakeDate gets started instead of the application: Select 'View / Options
/
File Types' from the Explorer menu. You see a list with all known fi
le
types. Scroll down the list until you see the file type(s) of your app.
Choose 'edit', then edit all actions for the type ('open' etc
.) and set
the name of the application to the name you gave fakedate.exe. Warning:
If the check box 'enable DDE' is checked, Windows uses DDE to op
en files
of this type. FakeDate doesn't support DDE (see 'Notes'). Disable
DDE, and
try to figure out how the application is invoked when opening a certain
file (usually the line is: progname.exe "%1"). This _should_
work, but
there's no guarantee.
2. Rename FakeDate and the application externally to Windows. That is, star
t
another operating system like plain DOS (a DOS box won't help!), or
Linux,
and rename the files from there.
You can also pass all desired arguments to FakeDate directly on the command
line. For each recognized INI file entry, there is a command line parameter
with the same name. This provides another elegant way to configure FakeDate:
For each target application, create a Windows shortcut to FakeDate.exe and
specify the desired command line parameters in the shortcut's property page.
You won't need an INI file anymore.
You have to tell FakeDate explicitly that it has to parse the command line.
You do this by specifying "-fakedateargs" as the first argument. There
39;s a
special reason for this: In some rare cases, an application ("B") that c
hecks
the date is started programmatically by another application "A", and A p
asses
command line arguments to B. (We did encounter exactly ONE such case, and f
or
sure, this certain program alone was worth the whole effort :-))) !) Now, you
have to rename "B.exe" to something else, then place a copy of Fake
Date in B's
directory and rename it to "B.exe". Place FakeDate's INI file i
n B's directory
and specify the name you gave your "B.exe" as target application.
Of course, FakeDate must now pass the command line arguments that A provides
on to B. Therefore, whenever the command line string doesn't start with
"-fakedateargs", FakeDate will think that the whole command line is to b
e
passed on to the target application. In this case, it will also ignore the
command line arguments for the target application that are specified in the
INI file. (FakeDate will look for an INI file in the directory it resides in,
and in the current working directory).
Example:
--------
Let's say you have a 30-day trial version of an application app.exe
. You
installed it on November 01, 1999. FakeDate is used with
app.exe the
following way:
1.Take the file fakedate.ini from the FakeDate package and put a
copy of it into app's directory.
2.Rename app.exe to, for instance, realapp.exe.
3.Place a copy of fakedate.exe in app's directory and name it
app.exe. If you want to, you can give it the icon of your original
app.exe to make the Windows shortcuts to the application look like
they used to, because now they reference of course FakeDate instead
of app!
4.Edit fakedate.ini. There's a line run=progname.exe in it.
Change it to run=realapp.exe.
5.There's also a line date=1994/01/31. Change it to,
for instance,
date=1999/11/10 (you could also use older date
s of course, but as
already said, some programs won't run if the system time is older than
their installation time). Note that the date must be of the format
YYYY/MM/DD. You can also adjust the other parameters if you like.
That's it: From now on, your trial app won't expire anymore, ever :
-) !
Parameters (overview):
----------------------
FakeDate recognizes the following parameters (see "Syntax" below fo
r more
details):
"-run <pathname>" : Specifies the target application (<pathn
ame> denotes the
absolute path to the application).
"-cmdline <...>" : The command line for the target application.
"-window <window state>" : Denotes how the target application
9;s main window
is to be shown (maximized, minimized, etc.).
"-date <date format string>" : The date to change to.
"-timer <time span>" : If FakeDate is told to re-fake the date p
eriodically
(see "stay" below), this parameter denotes the time span to wait between
'date-re-fakings'.
"-stay <yes/no>" : Tells FakeDate whether it shall stay resident
after
manipulating the date the first time. If no, FakeDate will quit after the
time interval specified with '-timer', restoring the original date. (Fak
eDate
won't close the target application.) If yes, FakeDate will continue to
re-fake the date periodically and exit only when the target application
exits.
"-cleanup <time span>" : If FakeDate is unsuccessful in re-fakin
g the date
and the target application has already been started, FakeDate advises
the target application to end itself (to avoid that it checks the date,
possibly getting the real date back and doing rude things like stamping
your hard disk ;-) ). Some applications follow such an advice, others don't
(mostly those which don't have a message loop). To avoid the above-mentioned
consequences, FakeDate will hard-terminate the application after a certain
amount of time if the application refused to end itself. This parameter says
how long FakeDate shall wait after the 'polite request' before killing t
he
wilful application.
"-profile <pathname>" : (command line only) Tells FakeDate which
INI file
to use.
"-debug <yes/no>" : Specifies if FakeDate shall produce more ver
bose output
to its log file.
Syntax
------
fakedate
fakedate -fakedateargs <args>
fakedate <cmdline>
<args> : ( <option> [<argument>] ) *
<option> : ("-"|"/") <keyword>
<cmdline> : .* // arbitrary command line options
Keyword Type Meaning Argument Must Default
-----------------------------------------------------------------------------
run string target application path name yes ---
(rel./abs.)
cmdline string command line for target arbitrary no ---
window string initial state of the *1 no ---
target's main window
date string faked date YYYY:MM:DD yes ---
stay flag stay resident after date *2 no*3 false
manipulation?*4
timer integer interval between date time/sec. no*3 0
re-fakings*4
cleanup integer time to give target to time/sec. no 5 sec.
clean up in case of an
error
profile string INI file for FakeDate path name no .\fakedate.ini
debug flag verbose logging? *2 no false
*1 Value State of target's main window
----- -----------------------------
"maximize" window is shown maximized
"minimize" window is shown minimized; currently active window
remains active
"normal" window size is defined by target application, but win
dow
is not shown maximized or minimized
(none) window is shown as determined by target application
*2 command line: no argument necessary (flag is set if parameter is
specified)
INI file: ("yes"|"no")
*3 At least one of the parameters "stay" and "timer" has to be s
pecified.
"stay" and "timer" must not be ("no", 0).
*4 stay timer Meaning
---- ----- -------
"no" 0 (not allowed)
"no" n>0 restore original date after n seconds, then q
uit
"yes" n loop: re-fake date each n seconds (n==0 -> ea
ch
15 seconds); restore date when child exits
Output
------
* FakeDate doesn't create any windows or other visible output, except f
or a
message box at the beginning of program execution if it detects any
other
running FakeDate instances. It's also possible that Windows shows a messag
e
box if a child application was specified but could not be executed.
* Each session is logged to the file 'fakedate.log' in FakeDate's di
rectory.
The verbosity of the output can be increased by setting the 'debug'
flag on the command line or in the INI file.
Notes:
------
* Parameters enclosed in ┤"┤ may contain white spaces.
* Command line options override INI entries of the same name. The presence
of an INI file is not mandatory. However, all the values defined as
"must" above must be specified.
* "fakedate.exe" may be executed under another name. The defau
lt name for
INI files is still "fakedate.ini", though.
* If there's a target application, but no INI file specified on the
command line, the INI file is expected to be "fakedate.ini" in t
he
target application's directory.
* If there's neither a target application nor an INI file specified on the
command line, the INI file is expected to be "fakedate.ini" in t
he
directory where FakeDate resides. If this file doesn't exist, FakeDa
te
looks for fakedate.ini in the current working directory. If this file
doesn't exist either, no INI file will be loaded.
* The path of the log file is always "fakedate.log" in the directory in
which FakeDate resides.
* FakeDate doesn't notice when a target application starts other processes.
So, if the target starts other processes and then ends itself, FakeDate
will exit, too, if "stay" is set to "yes". In this case,
it is more
helpful to set "stay" to "no" and "wait" to a large v
alue.
* The way FakeDate must be used to work with applications which have
registered file types if somewhat awkward and dirty under Windows: You
either have to rename FakeDate and the application externally to Windows
,
or you must edit the file type settings manually.
* If the file type settings specify that DDE is to be used when 'opening'
;
a file, there's another problem: FakeDate doesn't have a message loop
and thus doesn't support DDE. In such cases the Explorer or drive wi
ndow
the operation was started from will be blocked. Update the file type
information manually and disable DDE.
* Currently, soft termination of target applications is done by sending
WM_CLOSE messages to all top-level windows of the target application.
This can lead to problems if the application tries to interact with its
top level windows and doesn't check if they're already closed.
* FakeDate makes no use of the security attributes feature of Windows NT.
It hasn't been tested if this leads to problems when trying to
hard-terminate a target application.
* Programs may install their own exception handlers that can react to the
attempt to hard-terminate the application. FakeDate does not check if
hard termination of a target application was successful (Note: very few
programs install such mechanisms).
* If FakeDate is hard-terminated externally (e.g. in case of a system
crash), the original date is not restored. FakeDate doesn't check if
another FakeDate instance terminated at some point before without
restoring the original date.
* At the moment, FakeDate can't run multiple target applications
concurrently.
If you have problems or suggestions, and especially if you have a better
solution than ours to handle one of the difficulties mentioned in the above
paragraph, please let us know: Send a mail to yesh20@yahoo.com. Thanks.
Note: All crack requests will be ignored.
Padre & Lord Link
2000/01/11