testconns/statdesktop/desktop/testsource/dlltester/src/utils.cpp
changeset 4 b8d1455fddc0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testconns/statdesktop/desktop/testsource/dlltester/src/utils.cpp	Mon Oct 04 02:58:21 2010 +0300
@@ -0,0 +1,519 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+
+
+
+// CUtils.cpp : Handy bits and pieces for apps
+//
+
+#include "stdafx.h"
+#include <windows.h>
+#include <tchar.h>
+#include "Utils.h"
+
+CUtils::CUtils()
+: m_hMutex((HANDLE)0)
+{
+    // open the Service Control Manager
+    hSCM = OpenSCManager(NULL,						// local machine
+                         NULL,						// ServicesActive database
+                         SC_MANAGER_ALL_ACCESS);	// full access
+}
+
+CUtils::~CUtils()
+{
+    if (hSCM)
+	    CloseServiceHandle(hSCM);
+
+	if (m_hMutex)
+		CloseHandle(m_hMutex);
+}
+
+
+// attempts to create a mutex for this process.
+// if it fails, another process of the same name is already running
+bool CUtils::AlreadyRunning(LPCTSTR szAppName)
+{
+	m_hMutex = CreateMutex(NULL, FALSE, szAppName);
+	if ((!m_hMutex) || (WaitForSingleObject( m_hMutex, 0 ) == WAIT_TIMEOUT))
+    {
+		return true;   
+    }
+
+	return false;
+}
+
+
+// invokes an application then waits for it to exit
+bool CUtils::CallProcessAndWait(LPCTSTR szApplication, LPTSTR szCommandLine, LPCTSTR szDirectory, bool bRunMinimised)
+{
+	bool valid = false;
+	STARTUPINFO startInfo = {0};
+	startInfo.cb = sizeof(STARTUPINFO);
+	retCode = -1;
+
+	// run window minimised and not active
+	if (bRunMinimised)
+	{
+		startInfo.dwFlags = STARTF_USESHOWWINDOW;
+		startInfo.wShowWindow = SW_SHOWMINIMIZED | SW_SHOWMINNOACTIVE;
+	}
+
+	PROCESS_INFORMATION procInfo = {0};
+
+	// event attributes for the child process
+	SECURITY_ATTRIBUTES eventAttr;
+	eventAttr.nLength = sizeof(eventAttr);
+	eventAttr.lpSecurityDescriptor = NULL;
+	eventAttr.bInheritHandle = TRUE;
+
+	// NOTE: if passing a command line, include the application name in szCommandLine and pass NULL for szApplication
+	if (CreateProcess(szApplication, szCommandLine, NULL, NULL, FALSE, NULL, NULL,
+					  szDirectory, &startInfo, &procInfo))
+	{
+		if (WAIT_OBJECT_0 == WaitForSingleObject(procInfo.hProcess, INFINITE))
+		{
+			GetExitCodeProcess(procInfo.hProcess, &retCode);
+			CloseHandle(procInfo.hThread);
+			CloseHandle(procInfo.hProcess);
+			valid = true;
+		}
+	}
+	else
+		_GetWindowsError();
+
+	return valid;
+}
+
+
+bool CUtils::CallProcess(LPCTSTR szApplication, LPTSTR szCommandLine, LPCTSTR szDirectory)
+{
+	bool valid = false;
+	STARTUPINFO startInfo = {0};
+	startInfo.cb = sizeof(STARTUPINFO);
+
+	PROCESS_INFORMATION procInfo = {0};
+
+	// event attributes for the child process
+	SECURITY_ATTRIBUTES eventAttr;
+	eventAttr.nLength = sizeof(eventAttr);
+	eventAttr.lpSecurityDescriptor = NULL;
+	eventAttr.bInheritHandle = TRUE;
+
+	if (CreateProcess(szApplication, szCommandLine, NULL, NULL, FALSE, NULL, NULL,
+					  szDirectory, &startInfo, &procInfo))
+	{
+		CloseHandle(procInfo.hThread);
+		CloseHandle(procInfo.hProcess);
+		valid = true;
+	}
+	else
+		_GetWindowsError();
+
+	return valid;
+}
+
+// requests an NT service to perform a particular request
+bool CUtils::ServiceRequest(const char *szServiceName, const unsigned int iRequest)
+{
+	bool valid = false;
+
+    if (hSCM)
+	{
+		switch(iRequest)
+		{
+		case REQ_START:
+			if (Validate(hSCM, szServiceName, SERVICE_INACTIVE))
+			{
+				SC_HANDLE hService = OpenService(hSCM, szServiceName, SERVICE_ALL_ACCESS);
+				if (hService) 
+				{
+					DealWithDependentServices(szServiceName, iRequest);
+
+					if (StartService(hService, 0, NULL))
+						valid = true;
+
+					CloseServiceHandle(hService);
+				}
+				else
+					_GetWindowsError();
+			}
+			else
+			{
+				valid = true;	// already started
+			}
+			break;
+		case REQ_STOP:
+			if (Validate(hSCM, szServiceName, SERVICE_ACTIVE))
+			{
+				SC_HANDLE hService = OpenService(hSCM, szServiceName, SERVICE_STOP);
+				if (hService) 
+				{
+					DealWithDependentServices(szServiceName, iRequest);
+
+					SERVICE_STATUS status;
+					if (ControlService(hService, SERVICE_CONTROL_STOP, &status))
+						valid = true;
+
+					CloseServiceHandle(hService);
+				}
+				else
+					_GetWindowsError();
+			}
+			else
+			{
+				valid = true;	// already stopped
+			}
+			break;
+		default:
+			break;
+		};
+
+    }
+	return valid;
+}
+
+
+
+// recurses through a directory structure, performing an action on the files/directories within
+unsigned int CUtils::RecurseDir(const char *szDirectory, const unsigned int iCommand)
+{
+	iFileCommand = iCommand;
+	iFileCount = 0;
+
+	Recurse(szDirectory);
+
+	return iFileCount;
+}
+
+
+// adds a backslash to a path if it doesn't already have one
+void CUtils::AddSlash(char *szPath)
+{
+	if (*(szPath + strlen(szPath) - 1) != '\\')
+		strcat(szPath, "\\");
+}
+
+
+bool CUtils::ListServices(DWORD dwState)
+{
+	return Validate(hSCM, NULL, dwState, true);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Private Methods
+//
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool CUtils::Validate(SC_HANDLE hSCM, const char *szServiceName, DWORD dwState, bool bDisplayOnly)
+{
+	bool valid = false;
+	DWORD dwBytes = 0;
+	DWORD dwNumServices = 0;
+	DWORD dwResumeHandle = 0;
+	static ENUM_SERVICE_STATUS status[200];
+
+	// get list of services in particular state
+	if (EnumServicesStatus(hSCM,							// handle
+						 SERVICE_WIN32,						// service
+						 dwState,							// state
+						 (ENUM_SERVICE_STATUS *)status,		// returned info
+						 200 * sizeof(ENUM_SERVICE_STATUS),	// length of buffer
+						 &dwBytes,							// returned length
+						 &dwNumServices,					// number services returned
+						 &dwResumeHandle))					// point to continue
+	{
+		if (bDisplayOnly)
+		{
+			printf("\n\nServices\n========\n\n");
+		}
+
+		for (DWORD i=0;i<dwNumServices;i++)
+		{
+			if (bDisplayOnly)
+			{
+				if (status[i].ServiceStatus.dwCurrentState == SERVICE_RUNNING)
+					printf("STARTED  %s  (%s)\n", status[i].lpDisplayName, status[i].lpServiceName);
+				else if (status[i].ServiceStatus.dwCurrentState == SERVICE_STOPPED)
+					printf("STOPPED  %s  (%s)\n", status[i].lpDisplayName, status[i].lpServiceName);
+				else if (status[i].ServiceStatus.dwCurrentState == SERVICE_PAUSED)
+					printf("PAUSED   %s  (%s)\n", status[i].lpDisplayName, status[i].lpServiceName);
+				else
+					printf("PENDING  %s  (%s)\n", status[i].lpDisplayName, status[i].lpServiceName);
+			}
+			else
+			{
+				if (stricmp(status[i].lpServiceName, szServiceName) == 0)
+				{
+					valid = true;
+					break;
+				}
+			}
+		}
+	}
+
+	// check the driver list, just in case it's in there...
+	if (!valid)
+	{
+		if (EnumServicesStatus(hSCM,							// handle
+							 SERVICE_DRIVER,					// driver
+							 dwState,							// state
+							 (ENUM_SERVICE_STATUS *)status,		// returned info
+							 200 * sizeof(ENUM_SERVICE_STATUS),	// length of buffer
+							 &dwBytes,							// returned length
+							 &dwNumServices,					// number services returned
+							 &dwResumeHandle))					// point to continue
+		{
+			if (bDisplayOnly)
+			{
+				printf("\n\nDrivers\n=======\n\n");
+			}
+
+			for (DWORD i=0;i<dwNumServices;i++)
+			{
+				if (bDisplayOnly)
+				{
+					if (status[i].ServiceStatus.dwCurrentState == SERVICE_RUNNING)
+						printf("STARTED  %s  (%s)\n", status[i].lpDisplayName, status[i].lpServiceName);
+					else if (status[i].ServiceStatus.dwCurrentState == SERVICE_STOPPED)
+						printf("STOPPED  %s  (%s)\n", status[i].lpDisplayName, status[i].lpServiceName);
+					else if (status[i].ServiceStatus.dwCurrentState == SERVICE_PAUSED)
+						printf("PAUSED   %s  (%s)\n", status[i].lpDisplayName, status[i].lpServiceName);
+					else
+						printf("PENDING  %s  (%s)\n", status[i].lpDisplayName, status[i].lpServiceName);
+				}
+				else
+				{
+					if (stricmp(status[i].lpServiceName, szServiceName) == 0)
+					{
+						valid = true;
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	return valid;
+}
+
+
+void
+CUtils::Recurse(const char * rootDir)
+{
+    char fullname[MAX_PATH + 1];
+	HANDLE hFind;
+	
+	sprintf( fullname, "%s\\*", rootDir );
+	hFind = FindFirstFile(fullname, &ffd);
+
+	if(hFind != INVALID_HANDLE_VALUE)
+	{
+		do
+		{
+	        sprintf( fullname, "%s\\%s", rootDir, ffd.cFileName );
+
+			// directory so recurse into it
+			if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+			{
+				// ignore current and previous dirs
+				if ((stricmp (ffd.cFileName, ".") != 0) && (strcmp (ffd.cFileName, "..") != 0))
+				{
+					Recurse(fullname);
+
+					// remove it
+					if (iFileCommand == DELETEALL)
+						if (RemoveDirectory(fullname))
+							iFileCount++;
+				}
+			}
+			else
+			{ 
+				// remove now empty directory
+				if (iFileCommand == DELETEALL || iFileCommand == DELETEFILESONLY)
+					if (DeleteFile( fullname ))
+						iFileCount++;
+
+				// clear the attributes
+				if (iFileCommand == REMOVEALLATTRIBUTES)
+					if (SetFileAttributes(fullname, FILE_ATTRIBUTE_NORMAL))
+						iFileCount++;
+			}
+		}
+		while(FindNextFile(hFind, &ffd));
+
+		FindClose( hFind );
+	}
+
+	// remove this root now we are finished with it
+	if (iFileCommand == DELETEALL)
+		if (RemoveDirectory(rootDir))
+			iFileCount++;
+}
+
+
+void
+CUtils::DealWithDependentServices(const char *szServiceName, const unsigned int iRequest)
+{
+	DWORD dwBytes = 0;
+	DWORD dwNumServices = 0;
+	DWORD dwResumeHandle = 0;
+	ENUM_SERVICE_STATUS status[100];
+
+	// service may have dependent services so stop them first
+	SC_HANDLE hService = OpenService(hSCM, szServiceName, SERVICE_ENUMERATE_DEPENDENTS);
+	if (hService) 
+	{
+		if (EnumDependentServices(hService, 
+								SERVICE_ACTIVE,
+								(ENUM_SERVICE_STATUS *)status,		// returned info
+								100 * sizeof(ENUM_SERVICE_STATUS),	// length of buffer
+								&dwBytes,							// returned length
+								&dwNumServices))					// number services returned
+		{
+			for (DWORD i=0;i<dwNumServices;i++)
+			{
+				// recurse until we stop the last dependant
+				ServiceRequest(status[i].lpServiceName, iRequest);
+			}
+		}
+
+		CloseServiceHandle(hService);
+
+		// if there were dependents, allow some time register service stops
+		if (dwNumServices)
+			Sleep(2000);
+	}
+	else
+		_GetWindowsError();
+}
+
+void
+CUtils::_GetWindowsError()
+{
+	LPVOID lpSysError;
+	DWORD dwRet = GetLastError();
+
+	FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+				   NULL,
+				   dwRet,
+				   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+				   ( LPTSTR ) &lpSysError,
+				   0,
+				   NULL );
+
+	if (lpSysError)
+		_tcscpy(szError, ( LPTSTR )lpSysError);
+
+	LocalFree( lpSysError );
+}
+
+LPTSTR
+CUtils::GetWindowsError()
+{
+	return szError;
+}
+
+LPTSTR
+CUtils::GetWindowsErrorNow()
+{
+	_GetWindowsError();
+	return szError;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////
+// Trim the text of unwanted characters
+//
+void
+CUtils::TrimTabsCRAndWhitespace(char *szBuffer)
+{
+	// strip any unwanted chars off the end of each value
+	char *ptr = szBuffer + strlen(szBuffer) - 1;
+	if (ptr && (*ptr))
+	{
+		while ((*ptr) == '\r' || (*ptr) == '\n' || (*ptr) == '\t' || (*ptr) == ' ')
+			ptr--;
+
+		*(ptr + 1) = (char)0;
+	}
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////
+// Trim the buffered text to the first EOL and adjust the file pointer to suit
+// If EOL's included, include all up to the next occurance of text or EOF
+//
+int
+CUtils::TrimBufferToFirstEOL(HANDLE mmphndl, char *szBuffer, bool bIncludeCR)
+{
+	int count = 0;
+	int length = strlen(szBuffer);
+	int actualend = 0;
+
+	// move to first CR
+	while (*(szBuffer + count) && (*(szBuffer + count) != '\r') && (*(szBuffer + count) != '\n'))
+		count++;
+
+
+	// move to after CRs
+	actualend = count;
+	while ((*(szBuffer + actualend) == '\r') || (*(szBuffer + actualend) == '\n'))
+		actualend++;
+
+	if (count)
+	{
+		// include the CRs
+		if (bIncludeCR)
+			count = actualend;
+
+		// terminate the string at our desired point
+		*(szBuffer + count) = (char)0;
+
+		// set file pointer accordingly
+		if (mmphndl)
+			SetFilePointer(mmphndl, 0 - (length - actualend), NULL, FILE_CURRENT);
+	}
+
+	return count;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////
+// Trim the buffered text to the last EOL and adjust the file pointer to suit
+//
+void
+CUtils::TrimBufferToLastEOL(HANDLE mmphndl, char *szBuffer)
+{
+	// move back to last CR
+	char *end = szBuffer + strlen(szBuffer) - 1;
+	while ((end != szBuffer) && (*end != '\r') && (*end != '\n'))
+		end--;
+
+	// NULL-terminate line and adjust file pointer
+	if (end != (szBuffer + strlen(szBuffer) - 1))
+	{
+		int diff = (szBuffer + strlen(szBuffer) - 1) - end;
+		(*end) = (char)0;
+
+		// back up the file pointer to the end of the last line
+		if (mmphndl)
+			SetFilePointer(mmphndl, 0 - diff, NULL, FILE_CURRENT);
+	}
+}