]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - win/inspircd_win32wrapper.cpp
Add poll to build system if kqueue/epoll/ports are not used, above select.
[user/henk/code/inspircd.git] / win / inspircd_win32wrapper.cpp
index e6f25df18f8d33837b4ea7a2401abec89accfb68..7e72220e858d6bcebeb204cd94f7f83eddccda0f 100644 (file)
@@ -2,7 +2,7 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
  * See: http://www.inspircd.org/wiki/index.php/Credits
  *
  * This program is free but copyrighted software; see
 #include <string>
 #include <errno.h>
 #include <assert.h>
+#define _WIN32_DCOM
+#include <comdef.h>
+#include <Wbemidl.h>
+
+#pragma comment(lib, "wbemuuid.lib")
+#pragma comment(lib, "comsuppwd.lib")
 #pragma comment(lib, "winmm.lib")
 using namespace std;
 
@@ -26,6 +32,9 @@ using namespace std;
 
 #include <mmsystem.h>
 
+IWbemLocator *pLoc = NULL;
+IWbemServices *pSvc = NULL;
+
 /* This MUST remain static and delcared outside the class, so that WriteProcessMemory can reference it properly */
 static DWORD owner_processid = 0;
 
@@ -302,7 +311,6 @@ int getopt_long_only(int ___argc, char *const *___argv, const char *__shortopts,
                return -1;
 
        const char * opt = ___argv[arg_counter];
-       int return_val = 0;
 
        // if we're not an option, return an error.
        if (strnicmp(opt, "--", 2) != 0)
@@ -364,21 +372,7 @@ int getopt_long_only(int ___argc, char *const *___argv, const char *__shortopts,
        return 1;
 }
 
-/* IPC Messages */
-#define IPC_MESSAGE_REHASH     1
-#define IPC_MESSAGE_DIE                2
-#define IPC_MESSAGE_RESTART    3
-
-IPC::IPC(InspIRCd* Srv) : Instance(Srv)
-{
-       static DWORD buflen = 1024;
-       static const char * pipename = "\\\\.\\mailslot\\Inspircd";
-       hIPCPipe = CreateMailslot(pipename, buflen, 0, 0);
-       if (hIPCPipe == INVALID_HANDLE_VALUE)
-               printf("IPC Pipe could not be created. Are you sure you didn't start InspIRCd twice?\n");
-}
-
-void IPC::Check()
+/*void IPC::Check()
 {
        if (hIPCPipe == INVALID_HANDLE_VALUE)
                return;
@@ -390,14 +384,14 @@ void IPC::Check()
        if (!res)
        {
                if (GetLastError() != ERROR_SEM_TIMEOUT)
-                       Instance->Log(DEFAULT, "IPC Pipe Error %u: %s", GetLastError(), dlerror());
+                       Instance->Logs->Log("win32",DEFAULT, "IPC Pipe Error %u: %s", GetLastError(), dlerror());
                return;
        }
 
        switch (action)
        {
                case IPC_MESSAGE_REHASH:
-                       Instance->Rehash();
+                       Instance->Rehash("due to IPC message");
                break;
                
                case IPC_MESSAGE_DIE:
@@ -408,12 +402,7 @@ void IPC::Check()
                        Instance->Restart("IPC_MESSAGE_RESTART received by mailslot.");
                break;
        }
-}
-
-IPC::~IPC()
-{
-       CloseHandle(hIPCPipe);
-}
+}*/
 
 
 /* These three functions were created from looking at how ares does it
@@ -523,7 +512,7 @@ void ClearConsole()
  */
 void ChangeWindowsSpecificPointers(InspIRCd* Instance)
 {
-       Instance->Log(DEBUG,"Changing to windows specific pointer and functor set");
+       Instance->Logs->Log("win32",DEBUG,"Changing to windows specific pointer and functor set");
        Instance->Config->DNSServerValidator = &ValidateWindowsDnsServer;
 }
 
@@ -631,15 +620,20 @@ bool ValidateWindowsDnsServer(ServerConfig* conf, const char* tag, const char* v
        if (!*(data.GetString()))
        {
                std::string nameserver;
-               conf->GetInstance()->Log(DEFAULT,"WARNING: <dns:server> not defined, attempting to find working server in the registry...");
+               conf->GetInstance()->Logs->Log("win32",DEFAULT,"WARNING: <dns:server> not defined, attempting to find working server in the registry...");
                nameserver = FindNameServerWin();
                /* Windows stacks multiple nameservers in one registry key, seperated by commas.
                 * Spotted by Cataclysm.
                 */
                if (nameserver.find(',') != std::string::npos)
                        nameserver = nameserver.substr(0, nameserver.find(','));
+               /* Just to be FUCKING AKWARD, windows fister... err i mean vista...
+                * seperates the nameservers with spaces instead.
+                */
+               if (nameserver.find(' ') != std::string::npos)
+                       nameserver = nameserver.substr(0, nameserver.find(' '));
                data.Set(nameserver.c_str());
-               conf->GetInstance()->Log(DEFAULT,"<dns:server> set to '%s' as first active resolver in registry.", nameserver.c_str());
+               conf->GetInstance()->Logs->Log("win32",DEFAULT,"<dns:server> set to '%s' as first active resolver in registry.", nameserver.c_str());
        }
        return true;
 }
@@ -652,5 +646,133 @@ int gettimeofday(struct timeval * tv, void * tz)
        DWORD mstime = timeGetTime();
        tv->tv_sec   = time(NULL);
        tv->tv_usec  = (mstime - (tv->tv_sec * 1000)) * 1000;
-    return 0;  
+       return 0;       
+}
+
+/* Initialise WMI. Microsoft have the silliest ideas about easy ways to
+ * obtain the CPU percentage of a running process!
+ * The whole API for this uses evil DCOM and is entirely unicode, giving
+ * all results and accepting queries as wide strings.
+ */
+bool initwmi()
+{
+       HRESULT hres;
+
+       /* Initialise COM. This can kill babies. */
+       hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
+       if (FAILED(hres))
+               return false;
+
+       /* COM security. This stuff kills kittens */
+       hres =  CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
+               RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
+
+       if (FAILED(hres))
+       {
+               CoUninitialize();
+               return false;
+       }
+    
+       /* Instance to COM object */
+       pLoc = NULL;
+       hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
+       if (FAILED(hres))
+       {
+               CoUninitialize();
+               return false;
+       }
+
+       pSvc = NULL;
+
+       /* Connect to DCOM server */
+       hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
+    
+       /* That didn't work, maybe no kittens found to kill? */
+       if (FAILED(hres))
+       {
+               pLoc->Release();
+               CoUninitialize();
+               return false;
+       }
+
+       /* Don't even ASK what this does. I'm still not too sure myself. */
+       hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL,
+               RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
+
+       if (FAILED(hres))
+       {
+               pSvc->Release();
+               pLoc->Release();     
+               CoUninitialize();
+               return false;
+       }
+       return true;
+}
+
+void donewmi()
+{
+       pSvc->Release();
+       pLoc->Release();
+       CoUninitialize();
+}
+
+/* Return the CPU usage in percent of this process */
+int getcpu()
+{
+       HRESULT hres;
+
+       /* Use WQL, similar to SQL, to construct a query that lists the cpu usage and pid of all processes */
+       IEnumWbemClassObject* pEnumerator = NULL;
+       hres = pSvc->ExecQuery(bstr_t("WQL"),
+               bstr_t("Select PercentProcessorTime,IDProcess from Win32_PerfFormattedData_PerfProc_Process"),
+               WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
+    
+       /* Query didn't work */
+       if (FAILED(hres))
+               return -1;
+
+       IWbemClassObject *pclsObj = NULL;
+       ULONG uReturn = 0;
+   
+       /* Iterate the query results */
+       while (pEnumerator)
+       {
+               VARIANT vtProp;
+               /* Next item */
+               HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
+
+               /* No more items left */
+               if (uReturn == 0)
+                       break;
+
+               /* Find process ID */
+               hr = pclsObj->Get(L"IDProcess", 0, &vtProp, 0, 0);
+               if (!FAILED(hr))
+               {
+                       /* Matches our process ID? */
+                       if (vtProp.uintVal == GetCurrentProcessId())
+                       {
+                               VariantClear(&vtProp);
+                               /* Get CPU percentage for this process */
+                               hr = pclsObj->Get(L"PercentProcessorTime", 0, &vtProp, 0, 0);
+                               if (!FAILED(hr))
+                               {
+                                       /* Deal with wide string ickyness. Who in their right
+                                        * mind puts a number in a bstrVal wide string item?!
+                                        */
+                                       VariantClear(&vtProp);
+                                       int cpu = 0;
+                                       std::wstringstream out(vtProp.bstrVal);
+                                       out >> cpu;
+                                       pEnumerator->Release();
+                                       pclsObj->Release();
+                                       return cpu;
+                               }
+                       }
+               }
+       }
+       pEnumerator->Release();
+       pclsObj->Release();
+       return -1;
 }