void driver::close()
{
	TRACEI("[driver] [close]  > Entering routine.");

	tstring strBuf = boost::str(tformat(_T("[driver] [close]   closing driver - name: [%1%]")) % m_name.c_str() );
	TRACEBUFI(strBuf);

	if(!m_loaded)
	{
		TRACEW("[driver] [close]    Tried to close driver, but it wasn't loaded.");
		TRACEI("[driver] [close]  < Leaving routine (without doing anything).");
		return;
	}

	stop();

	if(this->removable)
	{
		TRACEV("[driver] [close]    driver is removable");
		SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
		if(!manager) throw win32_error("OpenSCManager");

		SC_HANDLE service = OpenService(manager, m_name.c_str(), SERVICE_ALL_ACCESS);
		if(!service) {
			DWORD err = GetLastError();

			CloseServiceHandle(manager);
			throw win32_error("OpenService", err);
		}

		DeleteService(service);

		CloseServiceHandle(service);
		CloseServiceHandle(manager);
	}

	TRACEI("[driver] [close]    unloaded driver");
	m_loaded = false;

	TRACEI("[driver] [close]  < Leaving routine.");

} // End of close()
Esempio n. 2
0
int main(){
	// Note that the console output is created by default

	// Create a formatted HTML file output
	TdOutputHandle html = td_createFileOutput("log.html", eTD_FMT_HTML);

	// Create a plain text output
	TdOutputHandle plain = td_createFileOutput("log.txt", eTD_FMT_PLAIN_TEXT);

	// Basic log macros
	LOGV("Verbose LOG");

	LOGD("Debug LOG");

	LOGI("Info LOG");

	LOGW("Warning LOG");

	LOGE("Error LOG");

	// Tracing macro
	TRACEV("Verbose TRACE");

	TRACED("Debug TRACE");

	TRACEI("Info TRACE");

	TRACEW("Warning TRACE");

	TRACEE("Error TRACE");

	// Destroy previously created outputs
	td_destroyOutput(html);

	td_destroyOutput(plain);

	system("pause");

	return 0;
}
Esempio n. 3
0
	// -----------------------------------------------------------------------
	//	GetNodeInfoFromHeader
	// -----------------------------------------------------------------------
	bool GetNodeInfoFromHeader(const HTTPHeader &header
							 , const ulong ip
							 , const ushort port
							 , O2Node &node)
	{
		strmap::const_iterator it;

		//ID
		it = header.fields.find(X_O2_NODE_ID);
		if (it == header.fields.end())
			return false;
		node.id.assign(it->second.c_str(), it->second.size());

		//IP
		node.ip = ip;

		//Port
		if (header.GetType() == HTTPHEADERTYPE_REQUEST) {
			it = header.fields.find(X_O2_PORT);
			if (it == header.fields.end())
				return false;
			node.port = (ushort)strtoul(it->second.c_str(), NULL, 10);
		}
		else
			node.port = port;

		//RSA Public Key
		it = header.fields.find(X_O2_RSAPUBLICKEY);
		if (it == header.fields.end())
			return false;
		node.pubkey.assign(it->second.c_str(), it->second.size());

		//NodeName
		it = header.fields.find(X_O2_NODENAME);
		if (it != header.fields.end())
			ToUnicode(_T(DEFAULT_XML_CHARSET), it->second, node.name);

		//Flags
		it = header.fields.find(X_O2_NODE_FLAGS);
		if (it != header.fields.end())
			ascii2unicode(it->second, node.flags);

		//User-Agent
		byte status;
		switch (header.GetType()) {
			case HTTPHEADERTYPE_REQUEST:
				it = header.fields.find("User-Agent");
				status = O2_NODESTATUS_LINKEDFROM;
				break;
			case HTTPHEADERTYPE_RESPONSE:
				it = header.fields.find("Server");
				status = O2_NODESTATUS_LINKEDTO;
				break;
			default:
				return false;
		}
		if (it == header.fields.end())
			return false;
		ascii2unicode(it->second, node.ua);

		// ノードのユーザーエージェントから情報を取得
		// O2/0.2 (o2on/0.02.0027; Win32)
		// O2/0.2 (opy2on/0.00.0001; Linux x86_64)
		//など「O2/プロトコルバージョン (アプリ名/アプリバージョン; 環境等)」形式であること
		size_t ProtoNamePos = node.ua.find(L"O2/", 0);
		if (ProtoNamePos != 0) {
			// プロトコル名が見つからない
			return false;
		}
		size_t AppNamePeriodPos = node.ua.find(L" ", ProtoNamePos);
		if ( AppNamePeriodPos == wstring::npos ) {
			// プロトコル・アプリ名の区切りが見つからない
			return false;
		}
		node.proto_ver = node.ua.substr( 3, AppNamePeriodPos - 3 );
		size_t AppNameStartPos = node.ua.find(L"(", AppNamePeriodPos);
		if (( AppNameStartPos == wstring::npos ) || ((AppNameStartPos + 1) == node.ua.size() )) {
			// アプリ名の開始位置が見つからない
			return false;
		}
		AppNameStartPos++;
		size_t AppNameEndPos = node.ua.find(L"/", AppNameStartPos);
		if ( AppNameEndPos == wstring::npos ) {
			// アプリ名の終了位置が見つからない
			return false;
		}
		node.app_name = node.ua.substr( AppNameStartPos, AppNameEndPos - AppNameStartPos );
 		if ((wcscmp(node.app_name.c_str(), _T(APP_NAME)) == 0) && ((AppNameEndPos + 1) < node.ua.size() )) {
			// 同じアプリならバージョン番号を取得
			AppNameEndPos++;
			size_t VerEndPos = node.ua.find(L";", AppNameEndPos);
			if ( VerEndPos == wstring::npos ) {
				// バージョン番号の終了位置が見つからない
				return false;
			}
			node.app_ver = node.ua.substr(AppNameEndPos, VerEndPos - AppNameEndPos);
		}
		else 
		{
			wchar_t tmpW[128];
			swprintf_s(tmpW, 128, L"異なるアプリ:%s\n", node.app_name.c_str());
			TRACEW(tmpW);
		}

		return true;
	}
Esempio n. 4
0
	void JobThreadFunc(void)
	{
		Lock();
		O2IMessages queue(Queue);
		Queue.clear();
		Unlock();

		if (queue.size() == 0)
			return;

		hashT myid;
		Profile->GetID(myid);

		O2IMessagesIt it;
		for (it = queue.begin(); it != queue.end() && IsActive(); it++) {
			O2IMessage &im = *it;

			TRACEA("[BroadcastJob]");
			TRACEW(it->msg.c_str());
			TRACEA("\n");

			O2NodeDB::NodeListT neighbors;
			if (NodeDB->neighbors(myid, neighbors, false, O2_BROADCAST_PATH_LIMIT+2) == 0)
				return;

			O2NodeDB::NodeListT::iterator nit = neighbors.begin();
			while (nit != neighbors.end()) {
				if (nit->id == im.id) {
					nit = neighbors.erase(nit);
					continue;
				}
				hashListT::iterator hit = std::find(im.paths.begin(), im.paths.end(), nit->id);
				if (hit != im.paths.end()) {
					nit = neighbors.erase(nit);
					continue;
				}
				nit++;
			}

			if (neighbors.empty())
				continue;

			hashT myid;
			Profile->GetID(myid);
			im.paths.push_back(myid);
			while (im.paths.size() > O2_BROADCAST_PATH_LIMIT)
				im.paths.pop_front();

			for (nit = neighbors.begin(); nit != neighbors.end() && IsActive(); nit++) {
				nit->lastlink = 0;
				nit->reset();

				// Broadcast発行
				O2SocketSession ss;
				ss.ip = nit->ip;
				ss.port = nit->port;

				string xml;
				BroadcastDB->MakeSendXML(im, xml);

				string url;
				MakeURL(ss.ip, ss.port, O2PROTOPATH_BROADCAST, url);

				HTTPHeader hdr(HTTPHEADERTYPE_REQUEST);
				hdr.method = "POST";
				hdr.SetURL(url.c_str());
				AddRequestHeaderFields(hdr, Profile);
				AddContentFields(hdr, xml.size(), "text/xml", DEFAULT_XML_CHARSET);
				hdr.Make(ss.sbuff);
				ss.sbuff += xml;

				Client->AddRequest(&ss);
				ss.Wait();

				HTTPHeader *header = (HTTPHeader*)ss.data;
				if (CheckResponse(&ss, header, NodeDB, *nit)) {
					;
				}

				if (header) delete header;
				Sleep(1000);
			}

			for (nit = neighbors.begin(); nit != neighbors.end() && IsActive(); nit++) {
				if (nit->lastlink) {
					// 成功したノードをtouch
					NodeDB->touch(*nit);
				}
				else {
					// 失敗したノードをremove
					NodeDB->remove(*nit);
					KeyDB->DeleteKeyByNodeID(nit->id);
				}
			}

			Sleep(IsActive() ? 1000 : 0);
		}
	}
Esempio n. 5
0
uint
O2Agent::
NetIOThread(void)
{
	O2SocketSessionListIt ssit;
	int lasterror;

	while (Active) {
		//setup FD
		fd_set readfds;
		fd_set writefds;
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);

		//wait
		Lock();
		uint n = sss.size();
		Unlock();
		if (n == 0) {
			ResetEvent(SessionAvailableEvent);
		}
		WaitForSingleObject(SessionAvailableEvent, INFINITE);
		if (!Active)
			break;

		//FD
		Lock();
		for (ssit = sss.begin(); ssit != sss.end(); ssit++) {
			O2SocketSession *ss = *ssit;
			if (!ss->sendcomplete)
				FD_SET(ss->sock, &writefds);
			else
				FD_SET(ss->sock, &readfds);
		}
		Unlock();

		//select
		struct timeval tv;
		tv.tv_sec = SELECT_TIMEOUT_MS/1000;
		tv.tv_usec = SELECT_TIMEOUT_MS%1000;
		select(0, &readfds, &writefds, NULL, &tv);

		//
		//	既存セッションとの送受信
		//
		Lock();
		ssit = sss.begin();
		Unlock();
		while (1) {
			bool loopend = false;
			Lock();
			if (ssit == sss.end())
				loopend = true;
			Unlock();
			if (loopend)
				break;

#if DEBUG_THREADLOOP && defined(_DEBUG)
			TRACEA("[NetIO]\n");
#endif
			O2SocketSession *ss = *ssit;
			O2AgentService *service = (O2AgentService*)ss->service;

			ushort port = htons(ss->sin.sin_port);
			wstring ipstr;
#if defined (_DEBUG)
			ulong2ipstr(ss->sin.sin_addr.S_un.S_addr, ipstr);
#else
			ip2e(ss->sin.sin_addr.S_un.S_addr, ipstr);
#endif
			//send
			if (FD_ISSET(ss->sock, &writefds)) {
				int len;
				const char *buff = ss->GetSendBuffer(len);
				if (len > 0) {
					int n = send(ss->sock, buff, len, 0);
#if DEBUG_THREADLOOP && defined(_DEBUG)
					TRACEA("[A]send\n");
#endif
					if (n > 0) {
						ss->UpdateSend(n);
						NodeDB->IncrementSendByte_me2n(ss->sin.sin_addr.S_un.S_addr, n);
						service->IncrementSendByte(n);
						service->OnSend(ss);
						ss->UpdateTimer();

						if (hwndSetIconCallback) {
							PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0);
						}
					}
					else if (n == 0) {
						;
					}
					else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) {
						if (Logger) {
							Logger->AddLog(O2LT_NET, MODULE,
								L"送信エラー(%d) (%s %s:%d %dbyte)",
								lasterror, service->GetName(), ipstr.c_str(), port, ss->sbuff.size());
						}
						ss->SetActive(false);
					}
				}
			}

			//recv
			if (FD_ISSET(ss->sock, &readfds)) {
				char buff[RECVBUFFSIZE];
				int n = recv(ss->sock, buff, RECVBUFFSIZE, 0);
#if DEBUG_THREADLOOP && defined(_DEBUG)
				TRACEA("[A]recv\n");
#endif
				if (n > 0) {
					ss->AppendRecv(buff, n);
					NodeDB->IncrementRecvByte_me2n(ss->sin.sin_addr.S_un.S_addr, n);
					service->IncrementRecvByte(n);
					service->OnRecv(ss);
					ss->UpdateTimer();

					if (hwndSetIconCallback) {
						PostMessage(hwndSetIconCallback, msgSetIconCallback, 0, 0);
					}
				}
				else if (n == 0) {
					if (Logger) {
						Logger->AddLog(O2LT_NET, MODULE,
							L"受信0 (%s %s:%d)",
								service->GetName(), ipstr.c_str(), port);
					}
					ss->SetActive(false);

				}
				else if ((lasterror = WSAGetLastError()) != WSAEWOULDBLOCK) {
					if (Logger) {
						Logger->AddLog(O2LT_NET, MODULE,
						L"受信エラー(%d) (%s %s:%d %dbyte)",
						lasterror, service->GetName(), ipstr.c_str(), port, ss->rbuff.size());
					}
					ss->SetActive(false);
				}
			}

			//delete
			if (!ss->IsActive() || ss->GetPastTime() >= SOCKET_TIMEOUT_S) {
				void *databk = ss->data;
				ulong ip = ss->sin.sin_addr.S_un.S_addr;
				closesocket(ss->sock);
				service->OnClose(ss);
				NodeDB->RemoveStatusBit(ip, O2_NODESTATUS_LINKEDTO);
				NodeDB->AddStatusBit(ip, O2_NODESTATUS_PASTLINKEDTO);
				service->DecrementCount();

				if (!ss->rbuff.empty() && !ss->sbuff.empty()) {
					NodeDB->UpdateLastModified(ip, 2);
					service->IncrementTotalSessionCount();
				}
				else if (ss->rbuff.empty())
					NodeDB->IncrementErrorCount(ip, 1);
				if (!ss->rbuff.empty() && (!databk || ss->rbuff[0] != 'H')) {
					NodeDB->DeleteNode(ip);

					if (Logger) {
						Logger->AddLog(O2LT_WARNING, MODULE,
							L"不正データ受信 (ノード削除: %s:%d)",
							ipstr.c_str(), htons(ss->sin.sin_port));
					}

					if (O2DEBUG) {
						char filename[256];
						sprintf_s(filename, 256, "dump\\A_%d.txt", rand());
						FILE *fp;
						fopen_s(&fp, filename, "wb");
						fwrite(ss->rbuff.c_str(), ss->rbuff.size(), 1, fp);
						fclose(fp);
					}
				}
#if DEBUG_SESSION_COUNT && defined(_DEBUG)
				wchar_t abc[256]; swprintf(abc, L"■■削除■■ count:%d  limit:%d  %s\n",
					service->GetSessionCount(), service->GetSessionLimit(), service->GetName());
				TRACEW(abc);
#endif
				Lock();
				ssit = sss.erase(ssit);
				Unlock();
				delete ss;
				continue;
			}

			Sleep(1);
			ssit++;
		}
	}

	//end
	Lock();
	for (ssit = sss.begin(); ssit != sss.end(); ssit++) {
		O2SocketSession *ss = *ssit;
		closesocket(ss->sock);
		ss->sock = 0;
		((O2AgentService*)((O2AgentService*)ss->service))->OnClose(ss);
		delete ss;
	}
	sss.clear();
	Unlock();

	return (0);
}
Esempio n. 6
0
uint
O2Agent::
LaunchThread(void)
{
	for (uint i = 0; i < Services.size(); i++) {
		Services[i]->SetActive(true);
		Services[i]->OnServiceStart();
	}
	Agent_GetGlobalIP->SetActive(true);
	Agent_GetGlobalIP->OnServiceStart();

	if (Logger)
		Logger->AddLog(O2LT_INFO, MODULE, L"エージェント正常起動");

	time_t prevconnecttime = time(NULL);
	uint index = 0;

	while (Active) {

		index %= Services.size();

		/*
		 *	ウェイト処理
		 */
		if (NodeDB->Count() == 0) {
#if DEBUG_THREADLOOP && defined(_DEBUG)
			TRACEA("■Node 0\n");
#endif
			Sleep(1000);
			continue;
		}

		uint pasttime_ms = ((uint)time(NULL) - (uint)prevconnecttime) * 1000;
		if (pasttime_ms < Interval) {
			uint sleeptime_ms = Interval - pasttime_ms;
#if DEBUG_THREADLOOP && defined(_DEBUG)
			TRACEA("Wait interval\n");
#endif
			if (Agent_GetGlobalIP->IsActive()) {
				;
				//グローバルIP未確定のときは急ぐ
			}
			else {
				if (sleeptime_ms < 1000)
					Sleep(sleeptime_ms);
				else
					Sleep(1000);
				continue;
			}
		}

		/*
		 *	サービス起動
		 */
		O2AgentService *service = Services[index];
		if (Agent_GetGlobalIP->IsActive())	//グローバルIP未決定のとき
			service = Agent_GetGlobalIP;	//強制的にAgent_GetGlobalIP起動

#if DEBUG_SESSION_COUNT && defined(_DEBUG)
		wchar_t abc[256]; swprintf(abc, L"● count:%d  limit:%d  %s\n",
			service->GetSessionCount(), service->GetSessionLimit(), service->GetName());
		TRACEW(abc);
#endif
		
		if (!service->IsActive()) {
			index++;
			continue;
		}
		if (service->GetSessionCount() >= service->GetSessionLimit()) {
			Sleep(500);
			index++;
			continue;
		}
		
		O2SocketSession *ss = new O2SocketSession();
		ss->service = (void*)service;
		
		ulong ip;
		ushort port;
		wstring ipstr;

		//接続先ノード決定
		//接続 TODO:クラスタリング
		if (service->HaveNodeDecision()) {
			service->OnLaunch(ss);
			if (!ss->IsActive()) {
				delete ss;
				index++;
				continue;
			}
			ip = ss->sin.sin_addr.S_un.S_addr;
			port = htons(ss->sin.sin_port);
		}
		else if (!NodeDB->GetNodeByPriority(ip, port)) {
			if (Logger) {
				Logger->AddLog(O2LT_WARNING, MODULE,
					L"有効なノード情報が無いので接続不可(%s)",
					service->GetName());
			}
			delete ss;
			index++;
			continue;
		}

#if !defined(_DEBUG)
		if (ip == Profile->GetIP() || ip == 0x0100007f) {
#if 0
			struct in_addr addr;
			addr.S_un.S_addr = ip;
			if (Logger) {
				Logger->AddLog(O2LT_WARNING, MODULE,
					"自ノード情報破棄 IP: %s Port: %d",
					inet_ntoa(addr), port);
			}
#endif
			NodeDB->DeleteNode(ip);
			delete ss;
			index++;
			continue;
		}
#endif

#if defined(_DEBUG)
		ulong2ipstr(ip, ipstr);
#else
		ip2e(ip, ipstr);
#endif
		
		/*
		 *	Socket生成
		 */
		ss->sock = socket(AF_INET, SOCK_STREAM, 0);
		if (ss->sock == INVALID_SOCKET) {
			if (Logger)
				Logger->AddLog(O2LT_ERROR, MODULE, L"ソケット生成に失敗");
			delete ss;
			index++;
			continue;
		}

		ss->sin.sin_family = AF_INET;
		ss->sin.sin_port = htons(port);
		ss->sin.sin_addr.S_un.S_addr = ip;
		

		/*
		 *	Connect
		 */
		int timeout = service == Agent_GetGlobalIP ? GIP_CONNECT_TIMEOUT_MS : CONNECT_TIMEOUT_MS;
		if (connect2(ss->sock, (struct sockaddr*)&ss->sin, sizeof(ss->sin), timeout) != 0) {
			//NodeDB->DeleteNode(ip);
			NodeDB->IncrementErrorCount(ip, 1);
			if (Logger) {
				Logger->AddLog(O2LT_NET, MODULE,
					L"connect失敗(%s %s:%d)",
					service->GetName(), ipstr.c_str(), port);
			}
			closesocket(ss->sock);
			delete ss;
			index++;
			continue;
		}
		if (hwndSetIconCallback) {
			PostMessage(hwndSetIconCallback, msgSetIconCallback, 1, 0);
		}

		//launch
		if (!service->HaveNodeDecision()) {
			service->OnLaunch(ss);
			if (!ss->IsActive()) {
				closesocket(ss->sock);
				delete ss;
				index++;
				continue;
			}
		}
		ss->UpdateTimer();
		service->IncrementCount();

		Lock();
		sss.push_back(ss);
		Unlock();
		SetEvent(SessionAvailableEvent);
		
		NodeDB->AddStatusBit(ip, O2_NODESTATUS_LINKEDTO);
		prevconnecttime = time(NULL);
		index++;
		
#if DEBUG_SESSION_COUNT && defined(_DEBUG)
		swprintf(abc, L"●● count:%d  limit:%d  %s\n",
			service->GetSessionCount(), service->GetSessionLimit(), service->GetName());
		TRACEW(abc);
#endif
		if (Logger) {
			Logger->AddLog(O2LT_NET, MODULE,
				L"connect成功 (%s %s:%d)",
				service->GetName(), ipstr.c_str(), port);
		}
	}

	//end
	Lock();
	SetEvent(SessionAvailableEvent);
	Unlock();

	for (uint i = 0; i < Services.size(); i++) {
		O2AgentService *service = Services[i];
		if (service->IsActive()) {
			service->SetActive(false);
			service->OnServiceEnd();
		}
	}

	if (Logger)
		Logger->AddLog(O2LT_INFO, MODULE, L"エージェント正常終了");
	return (0);
}
//================================================================================================
//
//  PerformPrevRelUpdates()
//
//    - Called by Main_OnInitDialog()
//
/// <summary>
///   Checks the version of the last time we ran, and if that number falls within certain ranges
///   we'll do some release-specific cleanup.
/// </summary>
//
void PerformPrevRelUpdates(HWND _hwnd)
{
	int prevRelease = g_config.LastVersionRun;

	if (prevRelease == PB_VER_BUILDNUM)
	{
		TRACEW("[mainproc] [PerformPrevRelUpdates]    no version change, so no updates to perform");
		return;
	}

	if (prevRelease > PB_VER_BUILDNUM)
	{
		TRACEW("[mainproc] [PerformPrevRelUpdates]    WARNING:  Downgrade detected!");
		return;
	}


	//--------------------------------------------------
	// Update PG hosted lists to iblocklist

	if (prevRelease < 134)
	{
		TRACEW("[mainproc] [PerformPrevRelUpdates]    Checking for old peerguardian-hosted lists, and updating any found to iblocklist.com-hosted ones");

		vector<DynamicList> tempList;

		// check each list in configured lists
		for(vector<DynamicList>::size_type i = 0; i < g_config.DynamicLists.size(); ++i)
		{
			// if it's a peerguardian list
			DynamicList *list = &(g_config.DynamicLists[i]);
			if (list->Url.find(_T("http://peerguardian.sourceforge.net/lists/")) != string::npos)
			{
				// swap it out
				tstring strBuf = boost::str(tformat(_T("[mainproc] [PerformPrevRelUpdates]    found old URL: [%1%]")) % list->Url );
				TRACEBUFW(strBuf);

				if (list->Url.find(_T("ads.php")) != string::npos)
				{
					// http://list.iblocklist.com/?list=bt_ads
					TRACEW("[mainproc] [PerformPrevRelUpdates]    - replacing ads.php list with bt_ads");
					//list->Url = _T("http://list.iblocklist.com/?list=bt_ads");
					DynamicList newList = *list;
					newList.Url = _T("http://list.iblocklist.com/lists/bluetack/ads-trackers-and-bad-pr0n");
					tempList.push_back(newList);
				}
				else if (list->Url.find(_T("edu.php")) != string::npos)
				{
					// http://list.iblocklist.com/?list=bt_edu
					TRACEW("[mainproc] [PerformPrevRelUpdates]    - replacing edu.php list with bt_edu");
					//list->Url = _T("http://list.iblocklist.com/?list=bt_edu");
					DynamicList newList = *list;
					newList.Url = _T("http://list.iblocklist.com/lists/bluetack/edu");
					tempList.push_back(newList);
				}
				else if (list->Url.find(_T("p2p.php")) != string::npos)
				{
					// http://list.iblocklist.com/?list=bt_level1
					TRACEW("[mainproc] [PerformPrevRelUpdates]    - replacing p2p.php list with bt_level1");
					//list->Url = _T("http://list.iblocklist.com/?list=bt_level1");
					DynamicList newList = *list;
					newList.Url = _T("http://list.iblocklist.com/lists/bluetack/level-1");
					tempList.push_back(newList);
				}
				else if (list->Url.find(_T("spy.php")) != string::npos)
				{
					// http://list.iblocklist.com/?list=bt_spyware
					TRACEW("[mainproc] [PerformPrevRelUpdates]    - replacing spy.php list with bt_spyware");
					//list->Url = _T("http://list.iblocklist.com/?list=bt_spyware");
					DynamicList newList = *list;
					newList.Url = _T("http://list.iblocklist.com/lists/bluetack/spyware");
					tempList.push_back(newList);
				}
				else if (list->Url.find(_T("gov.php")) != string::npos)
				{
					// remove list
					TRACEW("[mainproc] [PerformPrevRelUpdates]    - removing gov list");
				}
				else
				{
					TRACEE("[mainproc] [PerformPrevRelUpdates]    ERROR:  Unknown PG2 list!!");
				}
			}
			else
			{
				TRACED("[mainproc] [PerformPrevRelUpdates]    found non-PG2 URL");
				DynamicList newList = *list;
				tempList.push_back(newList);
			}
		}

		// Rebuild list if we need to remove Gov list.  Also, check for duplicates.
		g_config.DynamicLists.clear();
		for(vector<DynamicList>::size_type i = 0; i < tempList.size(); ++i)
		{
			if (std::find(g_config.DynamicLists.begin(), g_config.DynamicLists.end(), tempList[i]) == g_config.DynamicLists.end())
			{
				g_config.DynamicLists.push_back(tempList[i]);
			}
		}
	}


	//--------------------------------------------------
	// Update old list-names to new ones

	// Now that iblocklist.com has support for some "friendly" URLs for lists, we can migrate people
	// away from the slow, unreliable bluetack.co.uk servers and over to iblocklist.  We're checking
	// against any of the bluetack URLs from our old dropdown list, and changing 'em over.  Same
	// thing for any of the old naming-scheme iblocklist URLs.  We're also removing the bluetack
	// "trojan" list, since it resolves to an unusable file and there is no iblocklist equivalent.

	if (prevRelease < 268)
	{
		TRACEW("[mainproc] [PerformPrevRelUpdates]    Checking for old-URL lists, and migrating them to the new naming scheme (r268)");
		int result = MessageBox(_hwnd, IDS_PREVREL268TEXT, IDS_PREVREL, MB_ICONINFORMATION|MB_YESNO);
		if (result == IDNO)
		{
			TRACEI("[mainproc] [PerformPrevRelUpdates]    user clicked No");
		}
		else if (result == IDYES)
		{
			TRACEI("[mainproc] [PerformPrevRelUpdates]    user clicked Yes");

			vector<DynamicList> tempList;
			ListUrls listUrls;
			listUrls.Init();

			// check each list in configured lists
			for(vector<DynamicList>::size_type i = 0; i < g_config.DynamicLists.size(); ++i)
			{
				DynamicList *list = &(g_config.DynamicLists[i]);
				LISTNAME listId = listUrls.FindListNum(list->Url);
				if (listId != LISTNAME_COUNT)
				{
					DynamicList newList = *list;
					newList.Url = listUrls.GetBestUrl(listId);
					tempList.push_back(newList);
					if (newList.Url.compare(list->Url) == 0)
					{
						tstring strBuf = boost::str(tformat(_T("[mainproc] [PerformPrevRelUpdates]    - found no better list url than [%1%]"))
							% list->Url.c_str() );
						TRACEBUFW(strBuf);
					}
					else
					{
						tstring strBuf = boost::str(tformat(_T("[mainproc] [PerformPrevRelUpdates]    - migrated list from [%1%] to [%2%]"))
							% list->Url.c_str() % newList.Url.c_str() );
						TRACEBUFW(strBuf);
					}
				}
				else if (list->Url.compare(_T("http://www.bluetack.co.uk/config/trojan.zip")) == 0)
				{
					TRACEW("[mainproc] [PerformPrevRelUpdates]    - removing no-longer-existant bt trojan");
				}
				else
				{
					tstring strBuf = boost::str(tformat(_T("[mainproc] [PerformPrevRelUpdates]    - found unknown list url [%1%], copying over as-is"))
						% list->Url.c_str() );
					TRACEBUFW(strBuf);
					DynamicList newList = *list;
					tempList.push_back(newList);
				}
			}

			// Rebuild list, checking for duplicates.
			g_config.DynamicLists.clear();
			for(vector<DynamicList>::size_type i = 0; i < tempList.size(); ++i)
			{
				if (std::find(g_config.DynamicLists.begin(), g_config.DynamicLists.end(), tempList[i]) == g_config.DynamicLists.end())
				{
					g_config.DynamicLists.push_back(tempList[i]);
				}
			}
		}
	}


	//--------------------------------------------------
	// Update max history.db size from old default of 0 (unlimited) to 100 MB

	if (prevRelease < 341)
	{
		TRACEW("[mainproc] [PerformPrevRelUpdates]    Checking for old History defaults of 0, and migrating it to the new default of 100 MB (r341)");

		if (g_config.CleanupType == None && g_config.MaxHistorySize > 0)
		{
			TRACEW("[mainproc] [PerformPrevRelUpdates]    CleanupType = None, updating it to Delete every 7 Days");
			MessageBox(_hwnd, IDS_PREVREL341TEXT_DEL, IDS_PREVREL, MB_ICONINFORMATION|MB_OK);
			g_config.CleanupType = Delete;
			g_config.CleanupInterval = 7;
			g_config.Save();
		}
		else if (g_config.MaxHistorySize == 0 && g_config.CleanupType != None)
		{
			TRACEW("[mainproc] [PerformPrevRelUpdates]    Max history.db size 0 ('unlimited'), updating it to 100 MB");
			MessageBox(_hwnd, IDS_PREVREL341TEXT_MAX, IDS_PREVREL, MB_ICONINFORMATION|MB_OK);
			g_config.MaxHistorySize = 100 * 1000000;	// g_config.MaxHistory is in bytes...
			g_config.Save();
		}
		else if (g_config.MaxHistorySize == 0 && g_config.CleanupType == None)
		{
			TRACEW("[mainproc] [PerformPrevRelUpdates]    Changing history.db max size to 100 MB, and CleaupType to Delete every 7 days");
			MessageBox(_hwnd, IDS_PREVREL341TEXT_BOTH, IDS_PREVREL, MB_ICONINFORMATION|MB_OK);
			g_config.CleanupType = Delete;
			g_config.CleanupInterval = 7;
			g_config.MaxHistorySize = 100 * 1000000;	// g_config.MaxHistory is in bytes...
			g_config.Save();
		}
		else
		{
			TRACEW("[mainproc] [PerformPrevRelUpdates]    Not changing config");
			tstring strBuf = boost::str(tformat(_T("[mainproc] [PerformPrevRelUpdates]    Max history.db size (%1%) ")) % g_config.MaxHistorySize );
			g_tlog.LogMessage(strBuf, TRACELOG_LEVEL_WARNING);
		}
	}


	//--------------------------------------------------
	// Update Bluetack Webexploit/Forumspam merged list to new individual lists, and cw_bogon list
	// to the most frequently updated one, cidr_bogon

	if (prevRelease < 411)
	{
		TRACEW("[mainproc] [PerformPrevRelUpdates]    Checking for Bluetack Webexploit/Forumspam, cr_bogon, or default lists (r411)");

		vector<DynamicList> tempList;
		ListUrls listUrls;
		listUrls.Init();

		// check each list in configured lists
		for(vector<DynamicList>::size_type i = 0; i < g_config.DynamicLists.size(); ++i)
		{
			DynamicList *list = &(g_config.DynamicLists[i]);
			LISTNAME listId = listUrls.FindListNum(list->Url);
			if (listId == LISTNAME_BT_WEBEX_FSPAM)
			{
				TRACEW("[mainproc] [PerformPrevRelUpdates]    Updating Bluetack Webexploit/Forumspam merged list to new individual lists");
				MessageBox(_hwnd, IDS_PREVREL411TEXT_WEBEX, IDS_PREVREL, MB_ICONINFORMATION|MB_OK);

				DynamicList * newList = new DynamicList;
				newList->Url = listUrls.GetBestUrl(LISTNAME_BT_WEBEXPLOIT);
				newList->Enabled = list->Enabled;
				newList->Description = listUrls.GetListDesc(LISTNAME_BT_WEBEXPLOIT);
				tempList.push_back(*newList);

				DynamicList * newList2 = new DynamicList;
				newList2->Url = listUrls.GetBestUrl(LISTNAME_BT_FORUMSPAM);
				newList2->Enabled = list->Enabled;
				newList2->Description = listUrls.GetListDesc(LISTNAME_BT_FORUMSPAM);
				tempList.push_back(*newList2);
			}
			else if (listId == LISTNAME_CW_BOGON)
			{
				TRACEW("[mainproc] [PerformPrevRelUpdates]    Updating CW Bogon list to CIDR Bogon");
				MessageBox(_hwnd, IDS_PREVREL411TEXT_BOGON, IDS_PREVREL, MB_ICONINFORMATION|MB_OK);

				DynamicList * newList = new DynamicList;
				newList->Url = listUrls.GetBestUrl(LISTNAME_CIDR_BOGON);
				newList->Enabled = list->Enabled;
				newList->Description = listUrls.GetListDesc(LISTNAME_CIDR_BOGON);
				tempList.push_back(*newList);
			}
			else if ( listId == LISTNAME_BT_LEVEL1 || listId == LISTNAME_BT_ADS ||
					  listId == LISTNAME_BT_SPY || listId == LISTNAME_BT_EDU )
			{
				// Make sure Default Lists are set to Block, not Allow.  This will also take care
				// of any misconfigured PG2 lists, and is especially important since the PeerBlock
				// List Manager has no easy way to set lists to Block instead of Allow, nor will
				// it show you that it's an Allow list.

				if (list->Type == List::Allow)
				{
					tstring strBuf = boost::str(tformat(_T("[mainproc] [PerformPrevRelUpdates]    Updating list:[%1%] from type:[Allow] to type:[Block]")) % list->Description );
					TRACEBUFW(strBuf);

					DynamicList * newList = new DynamicList;
					newList->Url = list->Url;
					newList->Enabled = list->Enabled;
					newList->Description = list->Description;
					newList->Type = List::Block;
					tempList.push_back(*newList);
				}
				else
				{
					tempList.push_back(*list);
				}
			}
			else
			{
				// not LISTNAME_BT_WEBEX_FSPAM, LISTNAME_CIDR_BOGON, or a default list
				tempList.push_back(*list);
			}
		}

		// Rebuild list, checking for duplicates.
		g_config.DynamicLists.clear();
		for(vector<DynamicList>::size_type i = 0; i < tempList.size(); ++i)
		{
			if (std::find(g_config.DynamicLists.begin(), g_config.DynamicLists.end(), tempList[i]) == g_config.DynamicLists.end())
			{
				g_config.DynamicLists.push_back(tempList[i]);
			}
		}

	} // end of webex/forumspam update (r411)


	//--------------------------------------------------
	// Delete history.db if it's too large

	if (prevRelease < 454)
	{
		// check for filesize of history.db
		TRACEI("[mainproc] [PerformPrevRelUpdates]    checking size of history.db (r454)");

		struct _stat64 fileStat;
		path history_file = path::base_dir()/_T("history.db");
		int ret = _tstat64( history_file.c_str(), &fileStat );

		if (ret == 0)
		{
			// if it's too-large, delete it outright
			if (fileStat.st_size > g_config.MaxHistorySize*1.5) // 150 MB, by default
			{
				TRACEW("[mainproc] [PerformPrevRelUpdates]    Too-large history.db file detected!");
				path::remove(history_file);
				TRACEW("[mainproc] [PerformPrevRelUpdates]    Deleted history.db");
			}
		}

	} // end of delete too-large history.db (r454)


	//--------------------------------------------------
	// Remove I-Blocklist Subscription URL params if present, add them to peerblock.conf instead

	if (prevRelease < 653)
	{
		TRACEW("[mainproc] [PerformPrevRelUpdates]    Checking for I-Blocklist Subscription list URL params (r653)");

		ListUrls listUrls;
		listUrls.Init();
		tstring username;
		tstring pin;

		// check each list in configured lists
		for(vector<DynamicList>::size_type i = 0; i < g_config.DynamicLists.size(); ++i)
		{
			DynamicList *list = &(g_config.DynamicLists[i]);

			if (string::npos != list->Url.find(_T("http://list.iblocklist.com/?list=")))
			{
				// split url up into tokens
				size_t start = 0;
				size_t end = 0;
				map<tstring, tstring> params;

				start = list->Url.find(_T("?")) + 1;
				while (string::npos != end && string::npos != start)
				{
					end = list->Url.find(_T("&"), start);
					tstring paramSet = list->Url.substr(start,
						(end == string::npos) ? string::npos : end - start);
					start = (end > (string::npos - 1) ) ? string::npos : end + 1;

					size_t eqPos = 0;
					eqPos = paramSet.find(_T("="));
					if (string::npos != eqPos)
					{
						tstring key = paramSet.substr(0, eqPos);
						tstring val = paramSet.substr(eqPos + 1);
						params[key] = val;
					}
				}

				if (params.find(_T("username")) != params.end())
				{
					username = params.at(_T("username"));
				}

				if (params.find(_T("id")) != params.end())
				{
					username = params.at(_T("id"));
				}

				if (params.find(_T("pin")) != params.end())
				{
					pin = params.at(_T("pin"));
				}

				// sanity-check, make sure we didn't screw up and lost the list-param
				if (params.find(_T("list")) != params.end())
				{
					list->Url = tstring(_T("http://list.iblocklist.com/?list=")) + params.at(_T("list"));
				}
			}

			else if (string::npos != list->Url.find(_T("http://list.iblocklist.com/lists/")))
			{
				// split url up into tokens
				size_t urlRootEndPos = 0;
				size_t start = 0;
				size_t end = 0;
				map<tstring, tstring> params;

				urlRootEndPos = list->Url.find(_T("?"));
				if (string::npos != urlRootEndPos)
				{
					// we've got some params here
					start = urlRootEndPos + 1;
					while (string::npos != end && string::npos != start)
					{
						end = list->Url.find(_T("&"), start);
						tstring paramSet = list->Url.substr(start,
							(end == string::npos) ? string::npos : end - start);
						start = (end > (string::npos - 1) ) ? string::npos : end + 1;

						size_t eqPos = 0;
						eqPos = paramSet.find(_T("="));
						if (string::npos != eqPos)
						{
							tstring key = paramSet.substr(0, eqPos);
							tstring val = paramSet.substr(eqPos + 1);
							params[key] = val;
						}
					}

					if (params.find(_T("username")) != params.end())
					{
						username = params.at(_T("username"));
					}

					if (params.find(_T("id")) != params.end())
					{
						username = params.at(_T("id"));
					}

					if (params.find(_T("pin")) != params.end())
					{
						pin = params.at(_T("pin"));
					}

					// strip away all params from this URL, since none are applicable any longer
					list->Url = list->Url.substr(0, urlRootEndPos);
				}
			}
		}

		// if we have a username (id) and pin, save them to config, and remove them from here
		if (!username.empty() && !pin.empty())
		{
			g_config.IblUsername = username;
			g_config.IblPin = pin;
			g_config.Save();
		}

	} // end of i-blocklist subscription list-url param cleanup (r653)


	//--------------------------------------------------
	// Inform user about I-Blocklist's list-update limit

	if (prevRelease < 681)
	{
		TRACEI("[mainproc] [PerformPrevRelUpdates]    displaying info about I-Blocklist list-update limits (r681)");
        MessageBox(_hwnd, IDS_PREVREL681TEXT, IDS_PREVREL, MB_ICONINFORMATION|MB_OK);

	} // end of i-blocklist list-update limit info (r681)

}; // End of PerformPrevRelUpdates()
Esempio n. 8
0
	void JobThreadFunc(void)
	{
		Lock();
		O2KeyList keylist(RequestQueue);
		RequestQueue.clear();
		Unlock();

		if (keylist.size() == 0)
			return;

		O2NodeDB::NodeListT Nodes;

		// キーでループ
		O2KeyListIt it;
		for (it = keylist.begin(); it != keylist.end() && IsActive(); it++) {
			O2Key &key = *it;

			TRACEA("[GETDAT]");
			TRACEW(it->url.c_str());
			TRACEA("\n");

			O2Node node;
			node.id = it->nodeid;
			node.ip = it->ip;
			node.port = it->port;

			// リクエスト発行
			O2SocketSession ss;
			ss.ip = key.ip;
			ss.port = key.port;
			MakeRequest_Dat(&key.hash, NULL, &ss, Profile, DatIO, ss.sbuff);

			Client->AddRequest(&ss);
			ss.Wait();

			HTTPHeader *header = (HTTPHeader*)ss.data;
			if (CheckResponse(&ss, header, NodeDB, node)) {
				// 本文のdat取り込み
				const char *rawdata = &ss.rbuff[header->length];
				uint64 datsize = ss.rbuff.size() - header->length;

				ImportDat(DatIO, Profile, NULL, *header, rawdata, datsize,
					Logger, ss.ip, ss.port, QueryDB, hwndBaloonCallback, msgBaloonCallback);
			}

			if (header) delete header;
			Nodes.push_back(node);

			Sleep(IsActive() ? QUERY_DAT_INTERVAL_MS : 0);
		}

		O2NodeDB::NodeListT::iterator nit;
		for (nit = Nodes.begin(); nit != Nodes.end() && IsActive(); nit++) {
			if (nit->lastlink) {
				// 成功したノードをtouch
				NodeDB->touch(*nit);
			}
			else {
				// 失敗したノードをremove
				NodeDB->remove(*nit);
				KeyDB->DeleteKeyByNodeID(nit->id);
			}
		}
	}
void driver::load(const std::wstring &name, const std::wstring &file, const std::wstring &devfile)
{
	TRACEV("[driver] [load(3)]  > Entering routine.");
	if(m_loaded) throw std::exception("driver already loaded", 0);

	{
		tstring strBuf = boost::str(tformat(_T("[driver] [load(3)]    loading driver - name: [%1%], file: [%2%], devfile: [%3%]"))
			% name.c_str() % file.c_str() % devfile.c_str() );
		TRACEBUFI(strBuf);
	}

	m_name = name;
	m_file = file;
	m_devfile = devfile;

	SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if(!manager) throw win32_error("OpenSCManager");

	SC_HANDLE service = CreateService(manager, m_name.c_str(), m_name.c_str(),
		SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
		m_file.c_str(), NULL, NULL, NULL, NULL, NULL);

	if(!service)
	{
		DWORD err = 0;

		TRACEERR("[driver] [load(3)]", L"driver not currently installed as service", err = GetLastError());

		err = 0;
		service = OpenService(manager, m_name.c_str(), SERVICE_ALL_ACCESS);
		if(!service)
		{
			TRACEERR("[driver] [load(3)]", L"opening service", err = GetLastError());
			CloseServiceHandle(manager);
			throw win32_error("OpenService", err);
		}

		// make sure it has the same path as m_file.

		DWORD bytes;
		BOOL ret = QueryServiceConfig(service, NULL, 0, &bytes);

		if(ret || (err = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
		{
			TRACEERR("[driver] [load(3)]", L"calling QueryServiceConfig", err);
			CloseServiceHandle(service);
			CloseServiceHandle(manager);
			throw win32_error("QueryServiceConfig", err);
		}
		err = 0; // reset error-code, so that nobody else accidentally trips over it.

		QUERY_SERVICE_CONFIG *qsc = (QUERY_SERVICE_CONFIG*)malloc(bytes);
		if(!qsc)
		{
			TRACEERR("[driver] [load(3)]", L"allocating memory for QueryServiceConfig", err = GetLastError());
			CloseServiceHandle(service);
			CloseServiceHandle(manager);
			throw std::bad_alloc();
		}

		ret = QueryServiceConfig(service, qsc, bytes, &bytes);
		if(!ret)
		{
			TRACEERR("[driver] [load(3)]", L"second call to QueryServiceConfig", err = GetLastError());
			CloseServiceHandle(service);
			CloseServiceHandle(manager);
			throw win32_error("QueryServiceConfig", err);
		}

		bool del = _wcsicmp(qsc->lpBinaryPathName, m_file.c_str()) != 0;
		if (del)
		{
			// check for e.g. \??\C:\WINDOWS\System32\DRIVERS\ipfltdrv.sys
			wchar_t * descr = _wgetenv(L"WINDIR");
			if (descr)
			{
				wstring strFullPath(L"\\??\\");
				strFullPath += descr;
				strFullPath += L"\\";
				strFullPath += m_file;

				tstring strBuf = boost::str(tformat(_T("[driver] [load(3)]    comparing against driver full-path:[%1%]")) % strFullPath );
				TRACEBUFI(strBuf);

				del = _wcsicmp(qsc->lpBinaryPathName, strFullPath.c_str()) != 0;
			}
			else
			{
				TRACEW("[driver] [load(3)]    WINDIR environment variable not found!");
			}
		}

		tstring strBuf = boost::str(tformat(_T("[driver] [load(3)]    service name: [%1%], file name: [%2%]"))
			% qsc->lpBinaryPathName % m_file.c_str() );
		TRACEBUFI(strBuf);

		free(qsc);

		// paths don't match, remove service and recreate.
		if(del)
		{
			TRACEW("[driver] [load(3)]    paths don't match, removing and recreating driver-service");
			TCHAR buf[128];

			// if it's not removable, bail out.
			if(!this->removable)
			{
				TRACEC("[driver] [load(3)]    ERROR trying to remove driver-service");
				CloseServiceHandle(service);
				CloseServiceHandle(manager);
				throw std::exception("unremovable service mismatch", 0);
			}

			// check if its running
			SERVICE_STATUS status;
			ret = QueryServiceStatus(service, &status);
			if(!ret)
			{
				TRACEERR("[driver] [load(3)]", L"ERROR calling QueryServiceStatus", err = GetLastError());
				CloseServiceHandle(service);
				CloseServiceHandle(manager);
				throw win32_error("QueryServiceStatus", err);
			}

			// and stop it if it is.
			switch(status.dwCurrentState)
			{
				case SERVICE_STOPPED:
					TRACEI("[driver] [load(3)]    service state: [SERVICE_STOPPED]");
					break;

				case SERVICE_START_PENDING:
					TRACEI("[driver] [load(3)]    service state: [SERVICE_START_PENDING]");
					break;

				case SERVICE_STOP_PENDING:
					TRACEI("[driver] [load(3)]    service state: [SERVICE_STOP_PENDING]");
					break;

				case SERVICE_RUNNING:
					TRACEI("[driver] [load(3)]    service state: [SERVICE_RUNNING]");
					break;

				case SERVICE_CONTINUE_PENDING:
					TRACEI("[driver] [load(3)]    service state: [SERVICE_CONTINUE_PENDING]");
					break;

				case SERVICE_PAUSE_PENDING:
					TRACEI("[driver] [load(3)]    service state: [SERVICE_PAUSE_PENDING]");
					break;

				case SERVICE_PAUSED:
					TRACEI("[driver] [load(3)]    service state: [SERVICE_PAUSED]");
					break;

				default:
					swprintf_s(buf, _countof(buf), L"[driver] [load(3)]  * ERROR: Unknown service state: [%u]", status.dwCurrentState);
					TRACEBUFE(buf);
					break;
			}
			if(status.dwCurrentState != SERVICE_STOPPED && status.dwCurrentState != SERVICE_STOP_PENDING)
			{
				ret = ControlService(service, SERVICE_CONTROL_STOP, &status);
				if(!ret)
				{
					TRACEERR("[driver] [load(3)]", L"ERROR stopping driver-service", err = GetLastError());
					CloseServiceHandle(service);
					CloseServiceHandle(manager);
					throw win32_error("ControlService", err);
				}
			}

			// now delete the service.
			ret = DeleteService(service);
			err = GetLastError();
			CloseServiceHandle(service);

			if(!ret && err != ERROR_SERVICE_MARKED_FOR_DELETE)
			{
				TRACEERR("[driver] [load(3)]", L"ERROR deleting driver-service", err);
				CloseServiceHandle(manager);
				throw win32_error("DeleteService", err);
			}

			// finally recreate it.
			service = CreateService(manager, m_name.c_str(), m_name.c_str(),
				SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
				m_file.c_str(), NULL, NULL, NULL, NULL, NULL);

			if(!service && (err = GetLastError()) == ERROR_SERVICE_MARKED_FOR_DELETE)
			{
				TRACEW("[driver] [load(3)]    Service marked for delete; trying closing/reopening SCM");
				CloseServiceHandle(manager);
				Sleep(10000);
				manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

				if (!manager)
				{
					TRACEERR("[driver] [load(3)]", L"ERROR while re-opening SCM", err = GetLastError());
					throw win32_error("OpenSCManager 2", err);
				}

				service = CreateService(manager, m_name.c_str(), m_name.c_str(),
					SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
					m_file.c_str(), NULL, NULL, NULL, NULL, NULL);
			}

			if(!service)
			{
				TRACEERR("[driver] [load(3)]", L"ERROR re-creating driver-service", err = GetLastError());
				CloseServiceHandle(manager);
				throw win32_error("CreateService", err);
			}

			TRACEI("[driver] [load(3)]    finished re-creating driver-service");
		}
	}

	SERVICE_STATUS status;
	if(QueryServiceStatus(service, &status))
	{
		if (status.dwCurrentState == SERVICE_RUNNING)
		{
			TRACES("[driver] [load(3)]    Driver-service is running");
			m_started = true;
		}
		else if (status.dwCurrentState == SERVICE_START_PENDING)
		{
			TRACEI("[driver] [load(3)]    Driver-service is starting");
		}
		else
		{
			TRACEI("[driver] [load(3)]    driver-service not running");
			TCHAR buf[128];
			swprintf_s(buf, _countof(buf), L"[driver] [load(3)]    - service state: [%u]", status.dwCurrentState);
			TRACEBUFW(buf);
		}
	}

	CloseServiceHandle(service);
	CloseServiceHandle(manager);

	m_loaded = true;
	TRACEV("[driver] [load(3)]  < Leaving routine.");
}
void driver::stop()
{
	TRACEI("[driver] [stop]  > Entering routine.");

	if(!m_started)
	{
		TRACEW("[driver] [stop]    Tried to stop driver, but it is not started");
		TRACEI("[driver] [stop]  < Leaving routine (without doing anything).");
		return;
	}
	else if (!m_stoppable)
	{
		TRACEW("[driver] [stop]    Tried to stop driver, but it is not flagged as a stoppable driver");
		TRACEI("[driver] [stop]  < Leaving routine (without doing anything).");
		return;
	}

	TRACEI("[driver] [stop]    stopping driver");

	if(m_dev != INVALID_HANDLE_VALUE) {
		CloseHandle(m_dev);
		m_dev = INVALID_HANDLE_VALUE;
	}

	SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if(!manager)
	{
		TRACEE("[driver] [stop]    ERROR:  Can't OpenSCManager");
		throw win32_error("OpenSCManager");
	}

	SC_HANDLE service=OpenService(manager, m_name.c_str(), SERVICE_ALL_ACCESS);
	if(!service) {
		DWORD err = GetLastError();

		CloseServiceHandle(manager);
		TRACEE("[driver] [stop]    ERROR:  Can't OpenService");
		throw win32_error("OpenService", err);
	}

	SERVICE_STATUS status;
	if(
		(
			!QueryServiceStatus(service, &status) ||
			(
				status.dwCurrentState != SERVICE_STOPPED &&
				status.dwCurrentState != SERVICE_STOP_PENDING
			)
		) &&
		!ControlService(service, SERVICE_CONTROL_STOP, &status))
	{
		DWORD err = GetLastError();

		CloseServiceHandle(service);
		CloseServiceHandle(manager);

		TRACEE("[driver] [stop]    ERROR:  Can't ControlService");
		throw win32_error("ControlService", err);
	}

	CloseServiceHandle(service);
	CloseServiceHandle(manager);

	TRACEI("[driver] [stop]    driver has been stopped");
	m_started = false;

	TRACEI("[driver] [stop]  < Leaving routine.");

} // End of stop()
void driver::start(bool _gethandle)
{
	TRACEV("[driver] [start]  > Entering routine.");
	if(m_started)
	{
		TRACEI("[driver] [start]    driver already started");
		return;
	}

	TRACEI("[driver] [start]    starting driver");

	DWORD err = 0;

	SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if(!manager)
	{
		TRACEERR("[driver] [start]", L"ERROR: OpenSCManager", err = GetLastError());
		throw win32_error("OpenSCManager");
	}

	SC_HANDLE service = OpenService(manager, m_name.c_str(), SERVICE_ALL_ACCESS);
	if(!service)
	{
		CloseServiceHandle(manager);
		TRACEERR("[driver] [start]", L"ERROR: OpenService", err = GetLastError());
		throw win32_error("OpenService", err);
	}

	if(!StartService(service, 0, NULL) && (err = GetLastError()) != ERROR_SERVICE_ALREADY_RUNNING)
	{
		bool startFailed = true;

		if (err == ERROR_SERVICE_DATABASE_LOCKED)
		{
			int numRetries = 0;

			do
			{
				TRACEW("[driver] [start]    experiencing ERROR_SERVICE_DATABASE_LOCKED condition; waiting 10 seconds and trying again");
				Sleep(10000); // 10 seconds
				err = 0;

				if (!StartService(service, 0, NULL) && (err = GetLastError()) != ERROR_SERVICE_ALREADY_RUNNING)
					// still having problems
					++numRetries;
				else
					// either success, or another error
					break;

			} while (err == ERROR_SERVICE_DATABASE_LOCKED && numRetries < 6);

			if (numRetries < 6 && (err == 0 || err == ERROR_SERVICE_ALREADY_RUNNING))
			{
				startFailed = false;
				TRACES("[driver] [start]    successfully recovered from ERROR_SERVICE_DATABASE_LOCKED condition");
			}
			else if (err == ERROR_SERVICE_DATABASE_LOCKED)
			{
				TRACEE("[driver] [start]    cannot recover from ERROR_SERVICE_DATABASE_LOCKED condition; giving up");
			}
			else
			{
				TRACEE("[driver] [start]    cannot recover from ERROR_SERVICE_DATABASE_LOCKED condition; another error surfaced; giving up");
			}
		}

		if (startFailed)
		{
			CloseServiceHandle(service);
			CloseServiceHandle(manager);

			TRACEERR("[driver] [start]", L"ERROR: StartService", err);
			throw win32_error("StartService", err);
		}
	}

	CloseServiceHandle(service);
	CloseServiceHandle(manager);

	if (_gethandle)
	{
		tstring strBuf = boost::str(tformat(_T("[driver] [start]    getting handle to driver - devfile: [%1%]")) % m_devfile.c_str() );
		TRACEBUFI(strBuf);

		m_dev = CreateFile(m_devfile.c_str(), GENERIC_READ | GENERIC_WRITE,
			0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

		if(m_dev == INVALID_HANDLE_VALUE)
		{
			TRACEERR("[driver] [start]", L"ERROR: CreateFile", err = GetLastError());
			throw win32_error("CreateFile");
		}

		m_stoppable = true;
	}
	else
	{
		m_stoppable = false; // should only be false for MS IpFilterDriver
		TRACEI("[driver] [start]    flagging driver as not stoppable");
	}

	TRACEI("[driver] [start]    started driver");
	m_started = true;

	TRACEV("[driver] [start]  < Leaving routine.");

} // End of start()