diff --git a/bindings/java/build.xml b/bindings/java/build.xml index 9392588b..a51edf01 100644 --- a/bindings/java/build.xml +++ b/bindings/java/build.xml @@ -259,6 +259,7 @@ + diff --git a/src/os/win32/peb.c b/src/os/win32/peb.c index 7815d531..153effe9 100644 --- a/src/os/win32/peb.c +++ b/src/os/win32/peb.c @@ -55,7 +55,8 @@ static int sigar_pbi_get(sigar_t *sigar, HANDLE proc, PEB *peb) } if (!pbi.PebBaseAddress) { - return !SIGAR_OK; + /* likely we are 32-bit, pid process is 64-bit */ + return ERROR_DATATYPE_MISMATCH; } size = sizeof(*peb); diff --git a/src/os/win32/sigar_os.h b/src/os/win32/sigar_os.h index 479dd160..861ff26e 100644 --- a/src/os/win32/sigar_os.h +++ b/src/os/win32/sigar_os.h @@ -173,6 +173,10 @@ typedef enum { SC_STATUS_PROCESS_INFO = 0 } SC_STATUS_TYPE; +#ifndef ERROR_DATATYPE_MISMATCH +#define ERROR_DATATYPE_MISMATCH 1629L +#endif + #endif /* _MSC_VER */ #include @@ -571,6 +575,12 @@ int sigar_proc_args_peb_get(sigar_t *sigar, HANDLE proc, int sigar_proc_env_peb_get(sigar_t *sigar, HANDLE proc, WCHAR *env, DWORD envlen); +int sigar_proc_args_wmi_get(sigar_t *sigar, sigar_pid_t pid, + sigar_proc_args_t *procargs); + +int sigar_proc_exe_wmi_get(sigar_t *sigar, sigar_pid_t pid, + sigar_proc_exe_t *procexe); + int sigar_parse_proc_args(sigar_t *sigar, WCHAR *buf, sigar_proc_args_t *procargs); diff --git a/src/os/win32/win32_sigar.c b/src/os/win32/win32_sigar.c index ea92b681..4b776849 100644 --- a/src/os/win32/win32_sigar.c +++ b/src/os/win32/win32_sigar.c @@ -1443,6 +1443,11 @@ static int sigar_remote_proc_args_get(sigar_t *sigar, sigar_pid_t pid, CloseHandle(proc); + if (status == ERROR_DATATYPE_MISMATCH) { + /* we are 32-bit, pid process is 64-bit */ + status = sigar_proc_args_wmi_get(sigar, pid, procargs); + } + return status; } @@ -1603,6 +1608,12 @@ SIGAR_DECLARE(int) sigar_proc_exe_get(sigar_t *sigar, sigar_pid_t pid, } status = sigar_proc_exe_peb_get(sigar, proc, procexe); + if (status == ERROR_DATATYPE_MISMATCH) { + /* we are 32-bit, pid process is 64-bit */ + procexe->cwd[0] = '\0'; /* XXX where else can we try? */ + status = sigar_proc_exe_wmi_get(sigar, pid, procexe); + } + if (procexe->cwd[0] != '\0') { /* strip trailing '\' */ int len = strlen(procexe->cwd); diff --git a/src/os/win32/wmi.cpp b/src/os/win32/wmi.cpp new file mode 100644 index 00000000..a816bbd9 --- /dev/null +++ b/src/os/win32/wmi.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (C) [2004-2009], Hyperic, Inc. + * This file is part of SIGAR. + * + * SIGAR is free software; you can redistribute it and/or modify + * it under the terms version 2 of the GNU General Public License as + * published by the Free Software Foundation. This program is distributed + * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + */ + +#define UNICODE +#define _UNICODE +#define _WIN32_DCOM + +#include +#include +#include +#include +#include "sigar.h" + +#pragma comment(lib, "wbemuuid.lib") + +#ifndef SIGAR_CMDLINE_MAX +#define SIGAR_CMDLINE_MAX 4096 +#endif + +class WMI { + + public: + WMI(); + ~WMI(); + HRESULT Open(LPCTSTR machine=NULL, LPCTSTR user=NULL, LPCTSTR pass=NULL); + void Close(); + HRESULT GetProcStringProperty(DWORD pid, TCHAR *name, TCHAR *value, DWORD len); + HRESULT GetProcExecutablePath(DWORD pid, TCHAR *value); + HRESULT GetProcCommandLine(DWORD pid, TCHAR *value); + + private: + IWbemServices *wbem; + BSTR GetProcQuery(DWORD pid); +}; + +WMI::WMI() +{ + wbem = NULL; + CoInitializeEx(NULL, COINIT_MULTITHREADED); +} + +WMI::~WMI() +{ + Close(); + CoUninitialize(); +} + +HRESULT WMI::Open(LPCTSTR machine, LPCTSTR user, LPCTSTR pass) +{ + HRESULT result; + IWbemLocator *locator; + wchar_t path[MAX_PATH]; + + if (wbem) { + return S_OK; + } + + result = + CoInitializeSecurity(NULL, //Security Descriptor + -1, //COM authentication + NULL, //Authentication services + NULL, //Reserved + RPC_C_AUTHN_LEVEL_DEFAULT, //Default authentication + RPC_C_IMP_LEVEL_IMPERSONATE, //Default Impersonation + NULL, //Authentication info + EOAC_NONE, //Additional capabilities + NULL); //Reserved + + result = CoCreateInstance(CLSID_WbemLocator, + NULL, /* IUnknown */ + CLSCTX_INPROC_SERVER, + IID_IWbemLocator, + (LPVOID *)&locator); + + if (FAILED(result)) { + return result; + } + + if (machine == NULL) { + machine = L"."; + } + + wsprintf(path, L"\\\\%S\\ROOT\\CIMV2", machine); + + result = locator->ConnectServer(bstr_t(path), //Object path of WMI namespace + bstr_t(user), //User name. NULL = current user + bstr_t(pass), //User password. NULL = current + NULL, //Locale. NULL indicates current + 0, //Security flags + NULL, //Authority (e.g. Kerberos) + NULL, //Context object + &wbem); //pointer to IWbemServices proxy + + locator->Release(); + + return result; +} + +void WMI::Close() +{ + if (wbem) { + wbem->Release(); + wbem = NULL; + } +} + +BSTR WMI::GetProcQuery(DWORD pid) +{ + wchar_t query[56]; + wsprintf(query, L"Win32_Process.Handle=%d", pid); + return bstr_t(query); +} + +HRESULT WMI::GetProcStringProperty(DWORD pid, TCHAR *name, TCHAR *value, DWORD len) +{ + HRESULT result; + IWbemClassObject *obj; + VARIANT var; + + result = wbem->GetObject(GetProcQuery(pid), 0, 0, &obj, 0); + + if (FAILED(result)) { + return result; + } + + result = obj->Get(name, 0, &var, 0, 0); + + if (SUCCEEDED(result)) { + if (var.vt == VT_NULL) { + result = E_INVALIDARG; + } + else { + lstrcpyn(value, var.bstrVal, len); + } + VariantClear(&var); + } + + obj->Release(); + + return result; +} + +HRESULT WMI::GetProcExecutablePath(DWORD pid, TCHAR *value) +{ + return GetProcStringProperty(pid, L"ExecutablePath", value, MAX_PATH); +} + +HRESULT WMI::GetProcCommandLine(DWORD pid, TCHAR *value) +{ + return GetProcStringProperty(pid, L"CommandLine", value, SIGAR_CMDLINE_MAX); +} + +/* in peb.c */ +extern "C" int sigar_parse_proc_args(sigar_t *sigar, WCHAR *buf, + sigar_proc_args_t *procargs); + +extern "C" int sigar_proc_args_wmi_get(sigar_t *sigar, sigar_pid_t pid, + sigar_proc_args_t *procargs) +{ + int status; + TCHAR buf[SIGAR_CMDLINE_MAX]; + WMI *wmi = new WMI(); + + if (FAILED(wmi->Open())) { + return GetLastError(); + } + + if (FAILED(wmi->GetProcCommandLine(pid, buf))) { + status = GetLastError(); + } + else { + status = sigar_parse_proc_args(sigar, buf, procargs); + } + + wmi->Close(); + delete wmi; + + return status; +} + +extern "C" int sigar_proc_exe_wmi_get(sigar_t *sigar, sigar_pid_t pid, + sigar_proc_exe_t *procexe) +{ + int status; + TCHAR buf[MAX_PATH+1]; + WMI *wmi = new WMI(); + + if (FAILED(wmi->Open())) { + return GetLastError(); + } + + procexe->name[0] = '\0'; + + if (FAILED(wmi->GetProcExecutablePath(pid, buf))) { + status = GetLastError(); + } + else { + status = SIGAR_OK; + /* SIGAR_W2A(buf, procexe->name, sizeof(procexe->name)); */ + WideCharToMultiByte(CP_ACP, 0, buf, -1, + (LPSTR)procexe->name, sizeof(procexe->name), + NULL, NULL); + } + + wmi->Close(); + delete wmi; + + return status; +}