Ejemplo n.º 1
0
BOOL CPrime95App::InitInstance()
{
	int	orig_cmdShow;
	int	named_ini_files = -1;
	int	torture_test = 0;
	char	*p;

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

	//SetRegistryKey(_T("GIMPS"));
	//LoadStdProfileSettings(0);  // Load standard INI file options (including MRU)

	// Register the application's document templates.  Document templates
	//  serve as the connection between documents, frame windows and views.

	CMultiDocTemplate* pDocTemplate;
	pDocTemplate = new CMultiDocTemplate(
		IDR_MDITYPE,
		RUNTIME_CLASS(CPrime95Doc),
		RUNTIME_CLASS(CChildFrame),       // custom MDI child frame
		RUNTIME_CLASS(CPrime95View));
	if (!pDocTemplate)
		return FALSE;
	AddDocTemplate(pDocTemplate);

	// Init our view mutexes
	gwmutex_init (&VIEW_MUTEX);
	gwmutex_init (&VIEW_LINES_MUTEX);

	// create main MDI Frame window
	CMainFrame* pMainFrame = new CMainFrame;
	if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
	{
		delete pMainFrame;
		return FALSE;
	}
	m_pMainWnd = pMainFrame;

	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);

	// Dispatch commands specified on the command line
	orig_cmdShow = m_nCmdShow;
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;

/* Change the working directory to the same directory that */
/* the executable is located.  This is especially important */
/* for running prime95 as a Windows 95 service */

	{
		char	buf[256];
		GetModuleFileName (NULL, buf, sizeof (buf));
		strrchr (buf, '\\')[1] = 0;
		_chdir (buf);
	}

/* Initialize gwnum call back routines.  Using callback routines lets the */
/* gwnum library have a nice clean interface for users that do not need */
/* additional functionality that only prime95 uses. */

	StopCheckRoutine = stopCheck;
	OutputBothRoutine = OutputBoth;

/* NT services are not passed command line arguments.  In this case we */
/* encode the -An information in the NT service name. */

	if (NTSERVICENAME[0] && NTSERVICENAME[15] == '-')
		named_ini_files = atoi (&NTSERVICENAME[16]);

// Process command line switches

	for (p = m_lpCmdLine; *p == '//' || *p == '-'; ) {
		p++;
		switch (*p++) {

// Accept a -A switch indicating an alternate set of INI files
// are to be used.

		case 'A':
		case 'a':
			named_ini_files = 0;
			while (isspace (*p)) p++;
			while (isdigit (*p)) {
				named_ini_files = named_ini_files * 10 + (*p - '0');
				p++;
			}
			break;

// Accept a -T switch to run the torture test.

		case 'T':
		case 't':
			torture_test = 1;
			break;

// Accept a -W switch indicating an alternate working directory.

		case 'W':
		case 'w':
			{
			char	buf[256];
			char	*bufp = buf;
			while (isspace (*p)) p++;
			while (*p && !isspace (*p)) *bufp++ = *p++;
			*bufp = 0;
			_chdir (buf);
			}
			break;
		}

// Skip whitespace between switches

		while (isspace (*p)) p++;
	}

// Make sure only one copy of prime95 is running at a time.
// This code is courtesy of Jeroen C. van Gelderen
// I enhanced it to allow multiple copies if they are running
// from different directories or use different -A switches.

	{
		char	buf[256];
		char	*p;
		DWORD mutex_error_code;
		PSID pEveryoneSID = NULL, pAdminSID = NULL;
		PACL pACL = NULL;
		PSECURITY_DESCRIPTOR pSD = NULL;
		EXPLICIT_ACCESS ea[1];
		SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
		SECURITY_ATTRIBUTES sa;

// Turn directory name into a (likely) unique integer
// Add in the -A value.  Use this integer to create a mutex name.

		_getcwd (buf, 255);
		for (p = buf; *p; p++)
			g_MutexNum = g_MutexNum * 17 + *p;
		g_MutexNum += named_ini_files;
		sprintf (buf, "Global\\GIMPS%ld", g_MutexNum);

/* Create a world access security descriptor to share the Mutex we */
/* are about to create.  If we run into any troubles, assume this is */
/* a Windows 95/98/Me system and create a simple Mutex. */
		
// Create a well-known SID for the Everyone group.

		if (! AllocateAndInitializeSid (
				&SIDAuthWorld, 1, SECURITY_WORLD_RID,
				0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
			goto simple_mutex;

// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow the Administrators group full access to the key.

		ZeroMemory (&ea, sizeof (EXPLICIT_ACCESS));
		ea[0].grfAccessPermissions = EVENT_ALL_ACCESS;
		ea[0].grfAccessMode = SET_ACCESS;
		ea[0].grfInheritance= NO_INHERITANCE;
		ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
		ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
		ea[0].Trustee.ptstrName  = (LPTSTR) pEveryoneSID;

// Create a new ACL that contains the new ACEs.

		if (SetEntriesInAcl (1, ea, NULL, &pACL) != ERROR_SUCCESS)
			goto simple_mutex;

// Initialize a security descriptor.

		pSD = (PSECURITY_DESCRIPTOR)
			LocalAlloc (LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
		if (pSD == NULL) goto simple_mutex;
		if (! InitializeSecurityDescriptor (pSD, SECURITY_DESCRIPTOR_REVISION))
			goto simple_mutex;

// Add the ACL to the security descriptor.

		if (! SetSecurityDescriptorDacl (pSD, TRUE, pACL, FALSE))
			goto simple_mutex;

// Initialize a security attributes structure.

		sa.nLength = sizeof (SECURITY_ATTRIBUTES);
		sa.lpSecurityDescriptor = pSD;
		sa.bInheritHandle = FALSE;

// Create our mutex.  Windows XP uses terminal services to support user
// switching.  The "Global\" prefix is required so that this mutex is
// is created in the global kernel objects namespace.  Unfortunately,
// the "\" character raises an error on Windows 95/98/Me systems.

		g_hMutexInst = CreateMutex (
			&sa,   // World access
			FALSE, // Not owned !!
			buf);  // Unique name
		if (g_hMutexInst == NULL)
simple_mutex:	 	g_hMutexInst = CreateMutex (
				NULL,  // No security stuff
				FALSE, // Not owned !!
				buf+7);  // Unique name
		mutex_error_code = GetLastError ();

// Cleanup all the security structures we initialized

		if (pEveryoneSID) FreeSid (pEveryoneSID);
		if (pACL) LocalFree (pACL);
	        if (pSD) LocalFree (pSD);

// Test for failure

		if (g_hMutexInst == NULL)
			return 0;

// If mutex already exists then another instance is already running

		if (mutex_error_code == ERROR_ALREADY_EXISTS) {
			HWND	hwndPrevInst = 0;

// Give other instance a little time to display it's main window

			Sleep (750);

// Find the window handle

			EnumWindows (&MyEnumProc, (LPARAM) &hwndPrevInst);

// Unhide the other instance's window

			if (hwndPrevInst) {
				ShowWindow (hwndPrevInst, SW_HIDE);
				ShowWindow (hwndPrevInst, SW_SHOWMINIMIZED);
				ShowWindow (hwndPrevInst, SW_SHOWNORMAL);
			}
			CloseHandle (g_hMutexInst);
			g_hMutexInst = NULL;
			return 0;
		}

// Set the window user data so we can be identified by
// another instance of this program.

		SetWindowLongPtr (m_pMainWnd->m_hWnd, GWLP_USERDATA, (LONG_PTR) g_MutexNum);
	}

/* Cache icon handles to work around Windows deadlocking bug */

	ICON_IDLE = LoadIcon (IDI_YELLOW_ICON);
	ICON_WORKING = LoadIcon (IDR_MAINFRAME);

/* Name and read the INI files.  Perform some other startup initializations. */

	nameAndReadIniFiles (named_ini_files);
	initCommCode ();

/* Before processing the INI file, hide and/or position the */
/* main window so that we can display error messages */

	m_pMainWnd->SetWindowText ("Prime95");

	WINDOWPLACEMENT wp;
	m_pMainWnd->GetWindowPlacement (&wp);
	int left = IniGetInt (INI_FILE, "Left", 0);
	int top = IniGetInt (INI_FILE, "Top", 0);
	int right = IniGetInt (INI_FILE, "Right", 0);
	int bottom = IniGetInt (INI_FILE, "Bottom", 0);
	if (right + left + top + bottom != 0) {
		wp.rcNormalPosition.left = left;
		wp.rcNormalPosition.top = top;
		wp.rcNormalPosition.right = right;
		wp.rcNormalPosition.bottom = bottom;
	}
	wp.showCmd = HIDE_ICON ? SW_HIDE : SW_SHOWMINIMIZED;
	m_pMainWnd->SetWindowPlacement (&wp);

/* Now show the main window and post initial messages */

	// Put prime95 in the system tray
	if (TRAY_ICON) TrayMessage (NIM_ADD, "Prime95", 0);

	// See if we are running as a Windows95 service
	WINDOWS95_SERVICE = IniGetInt (INI_FILE, "Windows95Service", 0);
	WINDOWS95_A_SWITCH = named_ini_files;
	Service95 ();

	// Run the torture test if asked to by a command line argument
	if (torture_test) {
		m_pMainWnd->ShowWindow (orig_cmdShow);
		m_pMainWnd->PostMessage (WM_COMMAND, USR_TORTURE, 0);
	}

	// On first run, see if this is a stress tester.  If not, step
	// user throught the primenet dialog boxes.
	else if (STRESS_TESTER == 99) {
		m_pMainWnd->ShowWindow (orig_cmdShow);
		m_pMainWnd->PostMessage (WM_COMMAND, USR_WELCOME, 0);
	}

	// Take stress testers straight to the torture dialog box
	else if (STRESS_TESTER) {
		m_pMainWnd->ShowWindow (orig_cmdShow);
		m_pMainWnd->PostMessage (WM_COMMAND, IDM_TORTURE, 0);
	}

	// Auto-continue if there is any work to do.
	else if (USE_PRIMENET || WELL_BEHAVED_WORK || WORKTODO_COUNT) {
		m_pMainWnd->PostMessage (WM_COMMAND, IDM_CONTINUE, 0);
	}

	// Otherwise, show the window
	else if (!HIDE_ICON) {
		m_pMainWnd->ShowWindow (orig_cmdShow);
		ChangeIcon (MAIN_THREAD_NUM, IDLE_ICON);
	}

	// Initialization complete
	return TRUE;
}
Ejemplo n.º 2
0
int main (
	int	argc,
	char	*argv[])
{
	char	buf[256];
	int	named_ini_files = -1;
	int	contact_server = 0;
	int	torture_test = 0;
	int	i, nice_level;
	char	*p;

/* catch termination signals */

	(void)signal(SIGTERM, sigterm_handler);
	(void)signal(SIGINT, sigterm_handler);

/* No buffering of output */

	setvbuf (stdout, NULL, _IONBF, 0);

/* Change to the executable's directory */
/* NOTE:  This only changes the working directory if the user typed */
/* in a full path to the executable (as opposed to finding it on the PATH) */

	strcpy (buf, argv[0]);
	p = strrchr (buf, '/');
	if (p != NULL) {
		*p = 0;
		(void) _chdir (buf);
	}

/* Initialize gwnum call back routines.  Using callback routines lets the */
/* gwnum library have a nice clean interface for users that do not need */
/* additional functionality that only prime95 uses. */

	StopCheckRoutine = stopCheck;
	OutputBothRoutine = OutputBoth;

/* Process command line switches */

	for (i = 1; i < argc; i++) {
		p = argv[i];

		if (*p++ != '-') break;
		switch (*p++) {

/* Accept a -A switch indicating an alternate set of INI files */
/* are to be used. */

		case 'A':
		case 'a':
			named_ini_files = 0;
			while (isspace (*p)) p++;
			while (isdigit (*p)) {
				named_ini_files = named_ini_files * 10 + (*p - '0');
				p++;
			}
			break;

/* -C - contact the server now, then exit */

		case 'C':
		case 'c':
			contact_server = 1;
			VERBOSE = TRUE;
			NO_GUI = FALSE;
			break;
			
/* -D - debug */

		case 'D':
		case 'd':
			VERBOSE = TRUE;
			NO_GUI = FALSE;
			break;

/* -H - help */

		case 'H':
		case 'h':
		case '?':
			goto usage;

/* -M - Menu */

		case 'M':
		case 'm':
			MENUING = 1;
			NO_GUI = FALSE;
			break;

/* -S - status */

		case 'S':
		case 's':
			MENUING = 2;
			NO_GUI = FALSE;
			break;
		  

/* -T - Torture test */

		case 'T':
		case 't':
			torture_test = TRUE;
			break;

/* -V - version number */

		case 'V':
		case 'v':
			printf ("Mersenne Prime Test Program, Version %s.%d\n", VERSION, PORT);
			return (0); 

/* -W - use a different working directory */

		case 'W':
		case 'w':
			(void) _chdir (p);
			break; 

/* Otherwise unknown switch */

		default:
			printf ("Invalid switch\n");
			goto usage;
		}
	}

/* Determine the names of the INI files, read them, do other initialization. */
/* Skip the comm code initialization if we are just displaying the status */
/* or running a torture test */

	nameAndReadIniFiles (named_ini_files);
	if (MENUING != 2 && !torture_test) initCommCode ();

/* If not running a torture test, set the program to nice priority. */
/* Technically, this is not necessary since worker threads are set to */
/* the lowest possible priority.  However, sysadmins might be alarmed */
/* to see a CPU intensive program not running at nice priority when */
/* executing a ps command. */

#if defined (__linux__) || defined (__APPLE__) || defined (__FreeBSD__)
	/* Linux/FreeBSD ranges from -20 to +19, lower values give more favorable scheduling */
	nice_level = IniGetInt (INI_FILE, "Nice", 10);
	if (!torture_test && nice_level) {
		setpriority (PRIO_PROCESS, 0, nice_level);
	}
#endif

/* If running the torture test, do so now. */

	if (torture_test) {
		int	num_threads;

		VERBOSE = TRUE;
		NO_GUI = FALSE;
		num_threads = IniGetInt (INI_FILE, "TortureThreads",
					 NUM_CPUS * CPU_HYPERTHREADS);
		LaunchTortureTest (num_threads, TRUE);
	}

/* If this is a stress tester, then turn on menuing. */

	else if (IniGetInt (INI_FILE, "StressTester", 99) == 1) {
		MENUING = 1;
		VERBOSE = TRUE;
		NO_GUI = FALSE;
		main_menu ();
	}

/* On first run, get user id before contacting server */
/* for a work assignment.  To make first time user more comfortable, we will */
/* display data to the screen, rather than running silently. */

	else if (IniGetInt (INI_FILE, "StressTester", 99) == 99) {
		VERBOSE = TRUE;
		NO_GUI = FALSE;
		test_welcome ();
	}

/* If we are to contact the server, do so now.  This option lets the */
/* user create a batch file that contacts the server at regular intervals */
/* or when the ISP is contacted, etc. */

	else if (contact_server) {
		do_manual_comm_now ();
		while (COMMUNICATION_THREAD) Sleep (50);
	}

/* Bring up the main menu */

	else if (MENUING == 1)
		main_menu ();
	else if (MENUING == 2)
		test_status();

/* Continue testing, return when worker threads exit. */

	else {
		linuxContinue ("Another mprime is already running!\n", ALL_WORKERS, TRUE);
	}

/* Write the worktodo file in case the WELL_BEHAVED_WORK flag caused us */
/* to delay writing the file. */

	writeWorkToDoFile (TRUE);

/* All done */

	return (0);

/* Invalid args message */

usage:	printf ("Usage: mprime [-cdhmstv] [-aN] [-wDIR]\n");
	printf ("-c\tContact the PrimeNet server, then exit.\n");
	printf ("-d\tPrint detailed information to stdout.\n");
	printf ("-h\tPrint this.\n");
	printf ("-m\tMenu to configure mprime.\n");
	printf ("-s\tDisplay status.\n");
	printf ("-t\tRun the torture test.\n");
	printf ("-v\tPrint the version number.\n");
	printf ("-aN\tUse an alternate set of INI and output files (obsolete).\n");
	printf ("-wDIR\tRun from a different working directory.\n");
	printf ("\n");
	return (1);
}