ThreadList Thread::GetList(UInt32 processId)
	{
		Handle hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, processId);
		if (!hSnapshot.IsValid())
		{
			THROW_LAST_ERROR_EXCEPTION();
		}

		THREADENTRY32 threadEntry = {0};
		threadEntry.dwSize = sizeof(threadEntry);

		BOOL success = ::Thread32First(hSnapshot, &threadEntry);
		if (!success)
		{
			THROW_LAST_ERROR_EXCEPTION();
		}

		ThreadList list;
		while (success)
		{
			if (threadEntry.th32OwnerProcessID == processId)
			{
				list.push_back(Thread(threadEntry.th32ThreadID));
			}
			success = ::Thread32Next(hSnapshot, &threadEntry);
		}

		return list;
	}
	String Process::GetFilePath(UInt32 processId)
	{
		Handle hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId);
		if (hModuleSnap.IsValid())
		{	
			MODULEENTRY32 moduleEntry = {0};
			moduleEntry.dwSize = sizeof(moduleEntry);
			
			if (::Module32First(hModuleSnap, &moduleEntry)) 
			{
				//
				// Native processes on Windows XP are known to have weird paths
				//
				return FileSystem::Path::NtToWin32(moduleEntry.szExePath, False);
			}
		}		
		return String();
	}
	ProcessModuleList Process::GetModuleList() const
	{
		Handle hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, m_id);
		if (hModuleSnap.IsValid())
		{
			MODULEENTRY32 moduleEntry = { 0 };
			moduleEntry.dwSize = sizeof(moduleEntry);

			if (!::Module32First(hModuleSnap, &moduleEntry))
				return ProcessModuleList();

			ProcessModuleList moduleList;
			do
			{
				moduleList.push_back(moduleEntry.szExePath);
			} 
			while (::Module32Next(hModuleSnap, &moduleEntry));
			return std::move(moduleList);
		}
		return ProcessModuleList();
	}
	ProcessList Process::GetList()
	{
		Handle hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		if (!hSnapshot.IsValid())
		{
			THROW_LAST_ERROR_EXCEPTION();
		}

		PROCESSENTRY32 processEntry = {0};
		processEntry.dwSize = sizeof(processEntry);

		BOOL success = ::Process32First(hSnapshot, &processEntry);
		if (!success)
		{
			THROW_LAST_ERROR_EXCEPTION();
		}

		ProcessList list;
		while (success)
		{
#ifdef _DEBUG
			//if (_wcsicmp(processEntry.szExeFile, L"winword.exe") == 0 ||
			//	_wcsicmp(processEntry.szExeFile, L"iexplore.exe") == 0 ||
			//	wcscmp(processEntry.szExeFile, L"firefox.exe") == 0 ||
			//	wcsncmp(processEntry.szExeFile, L"FlashPlayerPlugin", 17) == 0 ||
			//	wcscmp(processEntry.szExeFile, L"AccessEnum.exe") == 0 ||
			//	wcscmp(processEntry.szExeFile, L"TSVNCache.exe") == 0 ||
			//	wcscmp(processEntry.szExeFile, L"plugin-container.exe") == 0)
#endif
			list.push_back(Process(
				processEntry.th32ProcessID,
				processEntry.th32ParentProcessID,
				processEntry.szExeFile));

			success = ::Process32Next(hSnapshot, &processEntry);
		}

		return list;
	}
	Bool Process::IsStillActive() const
	{
		Handle handle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, m_id);
		if (!handle.IsValid())
		{
			THROW_LAST_ERROR_EXCEPTION();
		}

		DWORD exitCode = 0;

		BOOL success = ::GetExitCodeProcess(handle, &exitCode);
		if (!success)
		{
			THROW_LAST_ERROR_EXCEPTION();
		}

		if (STILL_ACTIVE == exitCode)
		{
			return True;
		}
		return False;
	}