View Issue Details

IDProjectCategoryView StatusLast Update
0000729PluginsProcListpublic2011-03-22 00:05
Reporteralexeypa Assigned Tovskirdin  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Fixed in Version2.0 
Summary0000729: Resource leaks в плагине Proclist.
DescriptionProclist не освобождает ресурсы в нескольких местах:

1. WMIConnection вызывает CoInitialize, но не вызывает парный CoUninitialize.
2. PerfThread::PerfThread использует событие hEvtRefreshDone до того, как оно будет создано. (Это не лик, конечно, но создавать для этого целый новый баг?)
3. Функция ChangePrivileges имеет целый букет проблем:
    - Не освобождается hToken;
    - Не удаляется критическая секция cs;
    - Результат AdjustTokenPrivileges проверяется через GetLastError вне зависимости от результата функции.
    - Поток поже может иметь свой токен (OpenThreadToken) и его нужно пробовать в первую очередь.

Приаттаченый патч решает #1 и #2.
TagsNo tags attached.

Activities

2009-02-09 01:06

 

proclist.patch (2,003 bytes)   
==== Patch <proclist> level 1
Source: [No source]
Target: 72235d2c-c60c-0410-a47a-a0032694dc5d:/trunk/plugins/proclist:2527
        (http://farmanager.com/svn/trunk)
Log:
1. The event hEvtRefreshDone was used before it was created.
2. Each CoInitialize should have corresponding CoUninitialize.
=== perfthread.cpp
==================================================================
--- perfthread.cpp	(revision 2527)
+++ perfthread.cpp	(patch proclist level 1)
@@ -138,12 +138,12 @@
     }
     delete buf;
 
-    Refresh();
-
     hEvtBreak = CreateEvent(0, 0, 0, 0);
     hEvtRefresh = CreateEvent(0, 0, 0, 0);
     hEvtRefreshDone = CreateEvent(0, 0, 0, 0);
 
+    Refresh();
+
     hThread = CreateThread(0, 0, ThreadProc, this, 0, &dwThreadId);
     bOK = true;
 }
=== wmi.cpp
==================================================================
--- wmi.cpp	(revision 2527)
+++ wmi.cpp	(patch proclist level 1)
@@ -271,4 +271,6 @@
         pIWbemServices->Release();
         pIWbemServices = 0;
     }
+
+    CoUninitialize();
 }

==== BEGIN SVK PATCH BLOCK ====
Version: svk v2.0.99_01 (MSWin32)

eJx9Ustu1DAUHRZI1UgVP8Aii1Qqi5n6mcdUGo0ERUIIhGhhB5Fj30ws0jhyPFOKzIIN4iP4hfIL
/Q0+ByfTIqgQkTfOPfecc6/PU3t2vMJ+uUQ+xsifvn2+WLwSTtYH4RYnHpR2xsbcN7CFJqa+MeuY
+VacQ6g6YdfglkscmrNd88nYcEvCBo5SONP2cT6SFc4CxNjTFfMrOpwixrnvIVRGtsLCVvfatEEs
xTwAAhqHbtNBW1hjXNAnnLMVGVqRl43poRi4Bz4+wMktvNJNEGO+A1u52oJQc9l1I+ENyYinf+FT
f3Gu7+JGn/xGTGkLMox5OSCCj8AyVkXXNZeFg49OQePE6IQSjyrJJQJaCkQkVbgqK1wiSlOaJLnM
WUyTsLyXk8mXr+/DebA3uXoRLntXxbfJz3s/3r2GykJfH4aV/THxbradAuFphrOSy5IzlCVEooRk
jErKSyRzof7rkQ4MUOKcSEUrxRHOgCGVC8EqmgtOec4hZmzn8XpxfXr/4eQ6nXzfn0bhe2zetLrV
TotGf4LDR8f708/70396HZWQECAriQlSUgmJMCZKZiTJ0zIrU1aOW8eEejyPzmqIQvBaF9UnW3ez
hyemhehC9NGmBxWVUBkLkXbjLxne2IGaT8k8OhGyDu6e/fYW9bXZNCqqxRYiaWwg60yrdLu+M8Q8
znxnjWx0H9JNfEzILt1nY0QXiwDegu1Fc5D4kJBOuDrENSQ3XDYbreJg/8jZTfvhqGs2a932R7d8
Y6BIOrx5SgjlisiZTJCcIYbRTLBUzARCNOyDKcnVL5oOLL0=
==== END SVK PATCH BLOCK ====
proclist.patch (2,003 bytes)   

vskirdin

2009-02-10 18:07

administrator   bugnote:0002405

а по п.3 патчи будут?

alexeypa

2009-02-10 20:35

reporter   bugnote:0002408

Позже, когда руки дойдут.

vskirdin

2009-02-11 16:26

administrator   bugnote:0002432

когда руки дойдут - выкладывай, все до кучи сделаем ;-)

alexeypa

2009-02-12 16:51

reporter   bugnote:0002448

Прикрепленный патч для CoUninitialize не работает. Разбираюсь как это исправить...

2009-02-13 08:00

 

proclist2.patch (18,339 bytes)   
==== Patch <proclist> level 1
Source: [No source]
Target: 72235d2c-c60c-0410-a47a-a0032694dc5d:/trunk/plugins/proclist:2527
        (http://farmanager.com/svn/trunk)
Log:
1. Fixed resource leaks when enabling debug priviledge;
2. Fixed CoInitialize/CoUninitialize balancing;
3. The event hEvtRefreshDone was used before it was created.
=== Proclist.cpp
==================================================================
--- Proclist.cpp	(revision 2527)
+++ Proclist.cpp	(patch proclist level 1)
@@ -34,9 +34,19 @@
 BOOL WINAPI DllMainCRTStartup(HMODULE hDll,DWORD dwReason,LPVOID lpReserved)
 {
   (void) lpReserved;
-  if(dwReason == DLL_PROCESS_ATTACH)
+
+  BOOL rc = TRUE;
+  switch(dwReason)
+  {
+    case DLL_PROCESS_ATTACH:
       DisableThreadLibraryCalls(hDll);
-  return TRUE;
+      break;
+    case DLL_PROCESS_DETACH:
+      DebugToken::CloseToken();
+      break;
+  }
+
+  return rc;
 }
 
 #ifndef __GNUC__
@@ -177,6 +187,9 @@
   FSF.sprintf(PluginRootKey,_T("%s\\Plist"),Info->RootKey);
   _ui64Table = new ui64Table;
   Opt.Read();
+
+  if (NT)
+    DebugToken::CreateToken();
 }
 
 
=== Proclist.hpp
==================================================================
--- Proclist.hpp	(revision 2527)
+++ Proclist.hpp	(patch proclist level 1)
@@ -197,8 +197,29 @@
 void DeleteRegKey(LPCTSTR Key);
 
 int WinError(TCHAR* pSourceModule=0, BOOL bDown=FALSE);
-BOOL ChangePrivileges(BOOL bAdd, BOOL bAsk);
 
+class DebugToken
+{
+    // Debug thread token
+    static volatile HANDLE hDebugToken;
+
+    // Saved impersonation token
+    HANDLE hSavedToken;
+
+    bool saved;
+    bool enabled;
+
+  public:
+    DebugToken(): hSavedToken(NULL), saved(false), enabled(false) {}
+    ~DebugToken() { Revert(); }
+
+    bool Enable();
+    bool Revert();
+
+    static bool CreateToken();
+    static void CloseToken();
+};
+
 #ifndef UNICODE
 class OemString {
         char* pStr;
@@ -223,7 +244,7 @@
         TCHAR* pFullPath=0, DWORD cbFullPath=0, TCHAR* pCommandLine=0, DWORD cbCommandLine=0,
         TCHAR** ppEnvStrings=0, CURDIR_STR_TYPE** pCurDir=0);
 
-HANDLE OpenProcessForced(DWORD dwFlags, DWORD dwProcessId, BOOL bInh = FALSE);
+HANDLE OpenProcessForced(DebugToken* token, DWORD dwFlags, DWORD dwProcessId, BOOL bInh = FALSE);
 
 enum { SM_CUSTOM=64, SM_PID, SM_PARENTPID, SM_PRIOR, SM_PERFCOUNTER,  SM_PERSEC=128 };
 
=== handles.cpp
==================================================================
--- handles.cpp	(revision 2527)
+++ handles.cpp	(patch proclist level 1)
@@ -327,7 +327,8 @@
     bool remote = dwPID != GetCurrentProcessId();
     if ( remote )
     {
-        hRemoteProcess = OpenProcessForced( PROCESS_DUP_HANDLE, dwPID, TRUE );
+        DebugToken token;
+        hRemoteProcess = OpenProcessForced(&token, PROCESS_DUP_HANDLE, dwPID, TRUE);
         if( hRemoteProcess == NULL )
             return false;
         if(!DuplicateHandle( hRemoteProcess, h, GetCurrentProcess(), &handle,0,0, DUPLICATE_SAME_ACCESS))
=== perfthread.cpp
==================================================================
--- perfthread.cpp	(revision 2527)
+++ perfthread.cpp	(patch proclist level 1)
@@ -138,12 +138,12 @@
     }
     delete buf;
 
-    Refresh();
-
     hEvtBreak = CreateEvent(0, 0, 0, 0);
     hEvtRefresh = CreateEvent(0, 0, 0, 0);
     hEvtRefreshDone = CreateEvent(0, 0, 0, 0);
 
+    Refresh();
+
     hThread = CreateThread(0, 0, ThreadProc, this, 0, &dwThreadId);
     bOK = true;
 }
@@ -174,6 +174,7 @@
 
 void PerfThread::Refresh()
 {
+    DebugToken token;
     DWORD dwTicksBeforeRefresh = GetTickCount();
 
     // allocate the initial buffer for the performance data
@@ -329,7 +330,7 @@
         }
         else {
           HANDLE hProcess = *HostName || Task.dwProcessId<=8 ? 0 :
-                OpenProcessForced(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ|READ_CONTROL, Task.dwProcessId);
+                OpenProcessForced(&token, PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|READ_CONTROL, Task.dwProcessId);
           if(hProcess) {
             GetOpenProcessDataNT(hProcess, Task.ProcessName, ArraySize(Task.ProcessName),
                 Task.FullPath, ArraySize(Task.FullPath), Task.CommandLine, ArraySize(Task.CommandLine));
@@ -372,7 +373,6 @@
     }
 //    if(!PlistPlugin.PostUpdate())
     bUpdated = true;
-    ChangePrivileges(FALSE,FALSE);
 
     dwLastRefreshTicks = GetTickCount() - dwTicksBeforeRefresh;
     SetEvent(hEvtRefreshDone);
=== Pclass.cpp
==================================================================
--- Pclass.cpp	(revision 2527)
+++ Pclass.cpp	(patch proclist level 1)
@@ -673,8 +673,8 @@
             if (*((ProcessDataNT*)pdata)->CommandLine)
                 fprintf(InfoFile, _T("\n%s:\n%s\n"), GetMsg(MCommandLine), OUT_STRING(((ProcessDataNT*)pdata)->CommandLine));
 
-            SetLastError(0);
-            hProcess = OpenProcessForced(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|READ_CONTROL,pdata->dwPID);
+            DebugToken token;
+            hProcess = OpenProcessForced(&token, PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|READ_CONTROL,pdata->dwPID);
 
             if(hProcess) {
                 PrintNTCurDirAndEnv(InfoFile, hProcess, Opt.ExportEnvironment);
@@ -690,7 +690,6 @@
                 if(pd.dwUSERObjects)
                     fprintf(InfoFile,_T("%s %u\n"),PrintTitle(MUSERObjects), pd.dwUSERObjects);
             }
-            ChangePrivileges(FALSE,FALSE);
         }// NT && !*HostName
 
         if(Opt.ExportPerformance && pPerfThread)
@@ -1271,6 +1270,7 @@
               HIGH_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS};
         const int N = bNewPri ? ArraySize(PrClasses2k) : ArraySize(PrClasses);
 
+        DebugToken token;
         for(int i=0; i<PInfo.SelectedItemsNumber; i++)
         {
 #ifndef UNICODE
@@ -1283,9 +1283,7 @@
             if(((ProcessData*)Item.UserData)->dwPID) {
 
                 if(!*HostName) {
-                    HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION,FALSE,((ProcessData*)Item.UserData)->dwPID);
-                    if(GetLastError()==ERROR_ACCESS_DENIED && ChangePrivileges(TRUE,FALSE))
-                        hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION, FALSE, ((ProcessData*)Item.UserData)->dwPID);
+                    HANDLE hProcess=OpenProcessForced(&token, PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION,((ProcessData*)Item.UserData)->dwPID);
                     if(hProcess) {
                         DWORD dwPriorityClass = GetPriorityClass(hProcess);
                         if(dwPriorityClass==0)
@@ -1339,7 +1337,7 @@
             Info.Control(this,FCTL_FREEPANELITEM,0,(LONG_PTR)&Item);
 #endif
         }
-        ChangePrivileges(FALSE,FALSE);
+        token.Revert();
         /*    // Copy flags from SelectedItems to PanelItems
         for(int i1=0; i1<PInfo.SelectedItemsNumber; i1++)
         for(int i2=0; i2<PInfo.ItemsNumber; i2++)
=== perfthread.hpp
==================================================================
--- perfthread.hpp	(revision 2527)
+++ perfthread.hpp	(patch proclist level 1)
@@ -70,8 +70,8 @@
 
   public:
 
-    WMIConnection() { pIWbemServices = NULL; hrLast = 0; }
-    ~WMIConnection() { Disconnect(); }
+    WMIConnection();
+    ~WMIConnection();
     operator bool () { return pIWbemServices!=0; }
     bool Connect(LPCTSTR pMachineName, LPCTSTR pUser=0, LPCTSTR pPassword=0);
     void Disconnect();
=== wmi.cpp
==================================================================
--- wmi.cpp	(revision 2527)
+++ wmi.cpp	(patch proclist level 1)
@@ -42,6 +42,17 @@
     PathStr = SysAllocString(path);
 }
 
+WMIConnection::WMIConnection(): pIWbemServices(NULL), hrLast(0)
+{
+  CoInitialize(NULL);
+}
+
+WMIConnection::~WMIConnection()
+{
+  Disconnect();
+  CoUninitialize();
+}
+
 void WMIConnection::GetProcessExecutablePath(DWORD dwPID, TCHAR* pPath)
 {
     hrLast = WBEM_S_NO_ERROR;
@@ -234,7 +245,6 @@
         pUser = pPassword = 0; // Empty username means default security
 
     hrLast = WBEM_S_NO_ERROR;
-    CoInitialize(0);
 
     //nt 3.51 dont' have CoInitializeSecurity
     // It must called per thread, otherwise returns
=== PlistNT.cpp
==================================================================
--- PlistNT.cpp	(revision 2527)
+++ PlistNT.cpp	(patch proclist level 1)
@@ -254,12 +254,16 @@
     return sz+1;
 }
 
-HANDLE OpenProcessForced(DWORD dwFlags, DWORD dwProcessId, BOOL bInh)
+HANDLE OpenProcessForced(DebugToken* token, DWORD dwFlags, DWORD dwProcessId, BOOL bInh)
 {
-    SetLastError(0);
     HANDLE hProcess = OpenProcess(dwFlags, bInh, dwProcessId);
-    if(GetLastError()==ERROR_ACCESS_DENIED && ChangePrivileges(TRUE,FALSE))
-      hProcess = OpenProcess(dwFlags, bInh, dwProcessId);
+    if(hProcess==NULL && GetLastError()==ERROR_ACCESS_DENIED)
+    {
+      if (token->Enable())
+      {
+        hProcess = OpenProcess(dwFlags, bInh, dwProcessId);
+      }
+    }
     return hProcess;
 }
 
@@ -462,61 +466,138 @@
     }
 }
 
-BOOL ChangePrivileges(BOOL bAdd, BOOL bAsk)
+volatile HANDLE DebugToken::hDebugToken = NULL;
+
+bool DebugToken::Enable()
 {
-    static BOOL bPrivChanged = FALSE;
+  if (enabled || hDebugToken == NULL)
+    return true;
 
-    if(bAdd==bPrivChanged)
-      return TRUE;
+  BOOL rc = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, &hSavedToken);
+  if (!rc)
+  {
+    hSavedToken = NULL;
+    if (GetLastError()==ERROR_NO_TOKEN)
+      rc = ERROR_SUCCESS;
+    else
+      return false;
+  }
 
-    if(bAdd && bAsk)
+  rc = SetThreadToken(NULL, hDebugToken);
+  if (!rc)
+  {
+    if (hSavedToken != NULL)
     {
-      const TCHAR *MsgItems[]={ GetMsg(MDeleteTitle),
-        GetMsg(MCannotDeleteProc), GetMsg(MRetryWithDebug),
-        GetMsg(MDangerous), GetMsg(MYes), GetMsg(MNo)};
-      if(Message(FMSG_WARNING,NULL,MsgItems,ArraySize(MsgItems),2)!=0)
-        return FALSE;
+      CloseHandle(hSavedToken);
+      hSavedToken = NULL;
     }
-    static HANDLE hToken=0;
-    static CRITICAL_SECTION cs;
-    if(!*(DWORD*)&cs)
-      InitializeCriticalSection(&cs);
-    EnterCriticalSection(&cs);
+    return false;
+  }
 
-    BOOL rc = FALSE;
-    if (hToken || OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
-    {
-       TOKEN_PRIVILEGES tp;
-       tp.PrivilegeCount = 1;
-       SetLastError(0);
-       LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
-       tp.Privileges[0].Attributes = bAdd ? SE_PRIVILEGE_ENABLED : 0;
-       SetLastError(0);
-       AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
-       rc = GetLastError()==0;
-       if(rc) bPrivChanged = bAdd;
-    }
+  enabled = true;
+  return true;
+}
 
-   LeaveCriticalSection(&cs);
-   return rc;
+bool DebugToken::Revert()
+{
+  if (!enabled)
+    return true;
+
+  BOOL rc = SetThreadToken(NULL, hSavedToken);
+  if (!rc)
+    return false;
+
+  if (hSavedToken != NULL)
+  {
+    CloseHandle(hSavedToken);
+    hSavedToken = NULL;
+  }
+
+  enabled = false;
+  return true;
 }
 
+bool DebugToken::CreateToken()
+{
+  HANDLE hProcessToken = NULL;
+  BOOL rc = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &hProcessToken);
+  if (!rc)
+    return false;
+
+  HANDLE hToken = NULL;
+  rc = DuplicateTokenEx(
+         hProcessToken,
+         TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
+         NULL,
+         SecurityAnonymous,
+         TokenImpersonation,
+         &hToken);
+
+  if (!rc)
+  {
+    CloseHandle(hProcessToken);
+    return false;
+  }
+
+  TOKEN_PRIVILEGES tp;
+  tp.PrivilegeCount = 1;
+  tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+  rc = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
+  if (!rc)
+  {
+    CloseHandle(hToken);
+    CloseHandle(hProcessToken);
+    return false;
+  }
+
+  rc = AdjustTokenPrivileges(
+         hToken,
+         FALSE,
+         &tp,
+         sizeof(tp),
+         NULL,
+         NULL);
+
+  if (!rc)
+  {
+    CloseHandle(hToken);
+    CloseHandle(hProcessToken);
+    return false;
+  }
+
+  hDebugToken = hToken;
+  return true;
+}
+
+void DebugToken::CloseToken()
+{
+  CloseHandle(hDebugToken);
+  hDebugToken = NULL;
+}
+
 BOOL KillProcessNT(DWORD pid,HWND hwnd)
 {
-  HANDLE hProcess;
-  BOOL bPrivilegesAdded = FALSE;
+  DebugToken token;
+  HANDLE hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, pid );
 
-  while(1)
+  // If access denied, try to assign debug privileges
+  if (hProcess==NULL && GetLastError()==ERROR_ACCESS_DENIED)
   {
-      SetLastError(0);
-      hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, pid );
-      if(hProcess || bPrivilegesAdded)
-      break;
-      // If access denied, try to assign debug privileges
-      if(GetLastError()!=ERROR_ACCESS_DENIED ||
-      !ChangePrivileges(TRUE,TRUE))
-      break;
-      bPrivilegesAdded = TRUE;
+    const TCHAR *MsgItems[]=
+    {
+      GetMsg(MDeleteTitle),
+      GetMsg(MCannotDeleteProc),
+      GetMsg(MRetryWithDebug),
+      GetMsg(MDangerous),
+      GetMsg(MYes),
+      GetMsg(MNo)
+    };
+
+    if(Message(FMSG_WARNING,NULL,MsgItems,ArraySize(MsgItems),2)==0)
+    {
+      if (token.Enable())
+        hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, pid );
+    }
   }
 
   BOOL bRet = FALSE;
@@ -526,8 +607,6 @@
     bRet = TerminateProcess( hProcess, 1 );
     CloseHandle( hProcess );
   }
-  if(bPrivilegesAdded)
-      ChangePrivileges(FALSE,FALSE);
 
   return bRet;
 }
@@ -660,10 +739,8 @@
 void PrintModulesNT(HANDLE InfoFile, DWORD dwPID, _Opt& Opt)
 {
     ModuleData Data;
-    HANDLE hProcess =
-    OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ|READ_CONTROL, FALSE, dwPID);
-    if(GetLastError()==ERROR_ACCESS_DENIED && ChangePrivileges(TRUE,FALSE))
-    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ|READ_CONTROL , FALSE, dwPID);
+    DebugToken token;
+    HANDLE hProcess = OpenProcessForced(&token, PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|READ_CONTROL, dwPID);
     PROCESS_PARAMETERS* pProcessParams;
     char *pEnd;
     if(hProcess && GetInternalProcessData( hProcess, &Data, pProcessParams, pEnd, true)) {

==== BEGIN SVK PATCH BLOCK ====
Version: svk v2.0.99_01 (MSWin32)

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
==== END SVK PATCH BLOCK ====
proclist2.patch (18,339 bytes)   

alexeypa

2009-02-13 08:05

reporter   bugnote:0002452

Last edited: 2009-02-13 08:06

Прикрепил заплатку для всех трех проблем: proclist2.patch.

Для #1 CoInitialize/CoUninitialize перенесены в конструктор/деструктор. Не очень красиво, но работает.

#2 фикс остался таким же как и был.

#3: теперь создается отдельный токен с включенной отладочной привилегией. При необходимости воспользоваться привилегией этот токен назначается текущему потоку, а затем оперативно восстанавливается предыдущий токен.

alexeypa

2009-02-19 06:30

reporter   bugnote:0002492

Перенес баг в более подходящее место: http://bugs.farmanager.com/view.php?id=745

DrKnS

2009-02-19 08:17

administrator   bugnote:0002495

Last edited: 2009-02-19 08:17

> Перенес баг в более подходящее место

Пожалуйста, не надо переносить баги методом копипаста. Есть более культурные способы.

vskirdin

2009-02-19 11:45

administrator   bugnote:0002507

proclist2.patch - это "последнее слово"?

alexeypa

2009-02-19 15:16

reporter   bugnote:0002523

> proclist2.patch - это "последнее слово"?

Да.

vskirdin

2009-02-19 16:58

administrator   bugnote:0002524

Хмм...

Вот это "моё" (1.75.0.146):
**********************************************
Module: ICQ.exe
Full path: C:\Program Files\ICQ6.5\ICQ.exe
File version: 6.5.0.1005
Description: ICQ Library
PID: 2776
Parent PID: 3908 (Explorer.EXE)
Priority: 8
Threads: 25

Started at: 11.02.2009 9:35:20
Uptime: 8 10:19:57

Command Line:
"C:\Program Files\ICQ6.5\ICQ.exe"

Current Directory: C:\Program Files\ICQ6.5\
**********************************************

вот это после наложения патча proclist2.patch (1.75.0.147, версия пока не менялась):
**********************************************
Module: ICQ.exe
PID: 2776
Parent PID: 3908 (explorer.exe)
Priority: 8
Threads: 25

Started at: 11.02.2009 9:35:20
Uptime: 8 10:19:51

Current Directory: C:\Program Files\ICQ6.5\
**********************************************

как то... что-то... не совсем то...

alexeypa

2009-02-19 17:38

reporter   bugnote:0002528

Да, нехорошо. Подвернется свободная минутка - гляну что там.

2009-02-20 07:26

 

proclist3.patch (18,344 bytes)   
==== Patch <proclist3> level 1
Source: [No source]
Target: 72235d2c-c60c-0410-a47a-a0032694dc5d:/trunk/plugins/proclist:2579
        (http://farmanager.com/svn/trunk)
Log:
1. Fixed resource leaks when enabling debug priviledge;
2. Fixed CoInitialize/CoUninitialize balancing;
3. The event hEvtRefreshDone was used before it was created.
=== Proclist.cpp
==================================================================
--- Proclist.cpp	(revision 2579)
+++ Proclist.cpp	(patch proclist3 level 1)
@@ -34,9 +34,19 @@
 BOOL WINAPI DllMainCRTStartup(HMODULE hDll,DWORD dwReason,LPVOID lpReserved)
 {
   (void) lpReserved;
-  if(dwReason == DLL_PROCESS_ATTACH)
+
+  BOOL rc = TRUE;
+  switch(dwReason)
+  {
+    case DLL_PROCESS_ATTACH:
       DisableThreadLibraryCalls(hDll);
-  return TRUE;
+      break;
+    case DLL_PROCESS_DETACH:
+      DebugToken::CloseToken();
+      break;
+  }
+
+  return rc;
 }
 
 #ifndef __GNUC__
@@ -177,6 +187,9 @@
   FSF.sprintf(PluginRootKey,_T("%s\\Plist"),Info->RootKey);
   _ui64Table = new ui64Table;
   Opt.Read();
+
+  if (NT)
+    DebugToken::CreateToken();
 }
 
 
=== Proclist.hpp
==================================================================
--- Proclist.hpp	(revision 2579)
+++ Proclist.hpp	(patch proclist3 level 1)
@@ -197,8 +197,29 @@
 void DeleteRegKey(LPCTSTR Key);
 
 int WinError(TCHAR* pSourceModule=0, BOOL bDown=FALSE);
-BOOL ChangePrivileges(BOOL bAdd, BOOL bAsk);
 
+class DebugToken
+{
+    // Debug thread token
+    static volatile HANDLE hDebugToken;
+
+    // Saved impersonation token
+    HANDLE hSavedToken;
+
+    bool saved;
+    bool enabled;
+
+  public:
+    DebugToken(): hSavedToken(NULL), saved(false), enabled(false) {}
+    ~DebugToken() { Revert(); }
+
+    bool Enable();
+    bool Revert();
+
+    static bool CreateToken();
+    static void CloseToken();
+};
+
 #ifndef UNICODE
 class OemString {
         char* pStr;
@@ -223,7 +244,7 @@
         TCHAR* pFullPath=0, DWORD cbFullPath=0, TCHAR* pCommandLine=0, DWORD cbCommandLine=0,
         TCHAR** ppEnvStrings=0, CURDIR_STR_TYPE** pCurDir=0);
 
-HANDLE OpenProcessForced(DWORD dwFlags, DWORD dwProcessId, BOOL bInh = FALSE);
+HANDLE OpenProcessForced(DebugToken* token, DWORD dwFlags, DWORD dwProcessId, BOOL bInh = FALSE);
 
 enum { SM_CUSTOM=64, SM_PID, SM_PARENTPID, SM_PRIOR, SM_PERFCOUNTER,  SM_PERSEC=128 };
 
=== handles.cpp
==================================================================
--- handles.cpp	(revision 2579)
+++ handles.cpp	(patch proclist3 level 1)
@@ -327,7 +327,8 @@
     bool remote = dwPID != GetCurrentProcessId();
     if ( remote )
     {
-        hRemoteProcess = OpenProcessForced( PROCESS_DUP_HANDLE, dwPID, TRUE );
+        DebugToken token;
+        hRemoteProcess = OpenProcessForced(&token, PROCESS_DUP_HANDLE, dwPID, TRUE);
         if( hRemoteProcess == NULL )
             return false;
         if(!DuplicateHandle( hRemoteProcess, h, GetCurrentProcess(), &handle,0,0, DUPLICATE_SAME_ACCESS))
=== perfthread.cpp
==================================================================
--- perfthread.cpp	(revision 2579)
+++ perfthread.cpp	(patch proclist3 level 1)
@@ -138,12 +138,12 @@
     }
     delete buf;
 
-    Refresh();
-
     hEvtBreak = CreateEvent(0, 0, 0, 0);
     hEvtRefresh = CreateEvent(0, 0, 0, 0);
     hEvtRefreshDone = CreateEvent(0, 0, 0, 0);
 
+    Refresh();
+
     hThread = CreateThread(0, 0, ThreadProc, this, 0, &dwThreadId);
     bOK = true;
 }
@@ -174,6 +174,7 @@
 
 void PerfThread::Refresh()
 {
+    DebugToken token;
     DWORD dwTicksBeforeRefresh = GetTickCount();
 
     // allocate the initial buffer for the performance data
@@ -329,7 +330,7 @@
         }
         else {
           HANDLE hProcess = *HostName || Task.dwProcessId<=8 ? 0 :
-                OpenProcessForced(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ|READ_CONTROL, Task.dwProcessId);
+                OpenProcessForced(&token, PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|READ_CONTROL, Task.dwProcessId);
           if(hProcess) {
             GetOpenProcessDataNT(hProcess, Task.ProcessName, ArraySize(Task.ProcessName),
                 Task.FullPath, ArraySize(Task.FullPath), Task.CommandLine, ArraySize(Task.CommandLine));
@@ -372,7 +373,6 @@
     }
 //    if(!PlistPlugin.PostUpdate())
     bUpdated = true;
-    ChangePrivileges(FALSE,FALSE);
 
     dwLastRefreshTicks = GetTickCount() - dwTicksBeforeRefresh;
     SetEvent(hEvtRefreshDone);
=== Pclass.cpp
==================================================================
--- Pclass.cpp	(revision 2579)
+++ Pclass.cpp	(patch proclist3 level 1)
@@ -673,8 +673,8 @@
             if (*((ProcessDataNT*)pdata)->CommandLine)
                 fprintf(InfoFile, _T("\n%s:\n%s\n"), GetMsg(MCommandLine), OUT_STRING(((ProcessDataNT*)pdata)->CommandLine));
 
-            SetLastError(0);
-            hProcess = OpenProcessForced(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|READ_CONTROL,pdata->dwPID);
+            DebugToken token;
+            hProcess = OpenProcessForced(&token, PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|READ_CONTROL,pdata->dwPID);
 
             if(hProcess) {
                 PrintNTCurDirAndEnv(InfoFile, hProcess, Opt.ExportEnvironment);
@@ -690,7 +690,6 @@
                 if(pd.dwUSERObjects)
                     fprintf(InfoFile,_T("%s %u\n"),PrintTitle(MUSERObjects), pd.dwUSERObjects);
             }
-            ChangePrivileges(FALSE,FALSE);
         }// NT && !*HostName
 
         if(Opt.ExportPerformance && pPerfThread)
@@ -1271,6 +1270,7 @@
               HIGH_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS};
         const int N = bNewPri ? ArraySize(PrClasses2k) : ArraySize(PrClasses);
 
+        DebugToken token;
         for(int i=0; i<PInfo.SelectedItemsNumber; i++)
         {
 #ifndef UNICODE
@@ -1283,9 +1283,7 @@
             if(((ProcessData*)Item.UserData)->dwPID) {
 
                 if(!*HostName) {
-                    HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION,FALSE,((ProcessData*)Item.UserData)->dwPID);
-                    if(GetLastError()==ERROR_ACCESS_DENIED && ChangePrivileges(TRUE,FALSE))
-                        hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION, FALSE, ((ProcessData*)Item.UserData)->dwPID);
+                    HANDLE hProcess=OpenProcessForced(&token, PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION,((ProcessData*)Item.UserData)->dwPID);
                     if(hProcess) {
                         DWORD dwPriorityClass = GetPriorityClass(hProcess);
                         if(dwPriorityClass==0)
@@ -1339,7 +1337,7 @@
             Info.Control(this,FCTL_FREEPANELITEM,0,(LONG_PTR)&Item);
 #endif
         }
-        ChangePrivileges(FALSE,FALSE);
+        token.Revert();
         /*    // Copy flags from SelectedItems to PanelItems
         for(int i1=0; i1<PInfo.SelectedItemsNumber; i1++)
         for(int i2=0; i2<PInfo.ItemsNumber; i2++)
=== perfthread.hpp
==================================================================
--- perfthread.hpp	(revision 2579)
+++ perfthread.hpp	(patch proclist3 level 1)
@@ -70,8 +70,8 @@
 
   public:
 
-    WMIConnection() { pIWbemServices = NULL; hrLast = 0; }
-    ~WMIConnection() { Disconnect(); }
+    WMIConnection();
+    ~WMIConnection();
     operator bool () { return pIWbemServices!=0; }
     bool Connect(LPCTSTR pMachineName, LPCTSTR pUser=0, LPCTSTR pPassword=0);
     void Disconnect();
=== wmi.cpp
==================================================================
--- wmi.cpp	(revision 2579)
+++ wmi.cpp	(patch proclist3 level 1)
@@ -42,6 +42,17 @@
     PathStr = SysAllocString(path);
 }
 
+WMIConnection::WMIConnection(): pIWbemServices(NULL), hrLast(0)
+{
+  CoInitialize(NULL);
+}
+
+WMIConnection::~WMIConnection()
+{
+  Disconnect();
+  CoUninitialize();
+}
+
 void WMIConnection::GetProcessExecutablePath(DWORD dwPID, TCHAR* pPath)
 {
     hrLast = WBEM_S_NO_ERROR;
@@ -234,7 +245,6 @@
         pUser = pPassword = 0; // Empty username means default security
 
     hrLast = WBEM_S_NO_ERROR;
-    CoInitialize(0);
 
     //nt 3.51 dont' have CoInitializeSecurity
     // It must called per thread, otherwise returns
=== PlistNT.cpp
==================================================================
--- PlistNT.cpp	(revision 2579)
+++ PlistNT.cpp	(patch proclist3 level 1)
@@ -254,12 +254,16 @@
     return sz+1;
 }
 
-HANDLE OpenProcessForced(DWORD dwFlags, DWORD dwProcessId, BOOL bInh)
+HANDLE OpenProcessForced(DebugToken* token, DWORD dwFlags, DWORD dwProcessId, BOOL bInh)
 {
-    SetLastError(0);
     HANDLE hProcess = OpenProcess(dwFlags, bInh, dwProcessId);
-    if(GetLastError()==ERROR_ACCESS_DENIED && ChangePrivileges(TRUE,FALSE))
-      hProcess = OpenProcess(dwFlags, bInh, dwProcessId);
+    if(hProcess==NULL && GetLastError()==ERROR_ACCESS_DENIED)
+    {
+      if (token->Enable())
+      {
+        hProcess = OpenProcess(dwFlags, bInh, dwProcessId);
+      }
+    }
     return hProcess;
 }
 
@@ -462,61 +466,138 @@
     }
 }
 
-BOOL ChangePrivileges(BOOL bAdd, BOOL bAsk)
+volatile HANDLE DebugToken::hDebugToken = NULL;
+
+bool DebugToken::Enable()
 {
-    static BOOL bPrivChanged = FALSE;
+  if (enabled || hDebugToken == NULL)
+    return true;
 
-    if(bAdd==bPrivChanged)
-      return TRUE;
+  BOOL rc = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, &hSavedToken);
+  if (!rc)
+  {
+    hSavedToken = NULL;
+    if (GetLastError()==ERROR_NO_TOKEN)
+      rc = ERROR_SUCCESS;
+    else
+      return false;
+  }
 
-    if(bAdd && bAsk)
+  rc = SetThreadToken(NULL, hDebugToken);
+  if (!rc)
+  {
+    if (hSavedToken != NULL)
     {
-      const TCHAR *MsgItems[]={ GetMsg(MDeleteTitle),
-        GetMsg(MCannotDeleteProc), GetMsg(MRetryWithDebug),
-        GetMsg(MDangerous), GetMsg(MYes), GetMsg(MNo)};
-      if(Message(FMSG_WARNING,NULL,MsgItems,ArraySize(MsgItems),2)!=0)
-        return FALSE;
+      CloseHandle(hSavedToken);
+      hSavedToken = NULL;
     }
-    static HANDLE hToken=0;
-    static CRITICAL_SECTION cs;
-    if(!*(DWORD*)&cs)
-      InitializeCriticalSection(&cs);
-    EnterCriticalSection(&cs);
+    return false;
+  }
 
-    BOOL rc = FALSE;
-    if (hToken || OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
-    {
-       TOKEN_PRIVILEGES tp;
-       tp.PrivilegeCount = 1;
-       SetLastError(0);
-       LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
-       tp.Privileges[0].Attributes = bAdd ? SE_PRIVILEGE_ENABLED : 0;
-       SetLastError(0);
-       AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
-       rc = GetLastError()==0;
-       if(rc) bPrivChanged = bAdd;
-    }
+  enabled = true;
+  return true;
+}
 
-   LeaveCriticalSection(&cs);
-   return rc;
+bool DebugToken::Revert()
+{
+  if (!enabled)
+    return true;
+
+  BOOL rc = SetThreadToken(NULL, hSavedToken);
+  if (!rc)
+    return false;
+
+  if (hSavedToken != NULL)
+  {
+    CloseHandle(hSavedToken);
+    hSavedToken = NULL;
+  }
+
+  enabled = false;
+  return true;
 }
 
+bool DebugToken::CreateToken()
+{
+  HANDLE hProcessToken = NULL;
+  BOOL rc = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &hProcessToken);
+  if (!rc)
+    return false;
+
+  HANDLE hToken = NULL;
+  rc = DuplicateTokenEx(
+         hProcessToken,
+         TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
+         NULL,
+         SecurityImpersonation,
+         TokenImpersonation,
+         &hToken);
+
+  if (!rc)
+  {
+    CloseHandle(hProcessToken);
+    return false;
+  }
+
+  TOKEN_PRIVILEGES tp;
+  tp.PrivilegeCount = 1;
+  tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+  rc = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
+  if (!rc)
+  {
+    CloseHandle(hToken);
+    CloseHandle(hProcessToken);
+    return false;
+  }
+
+  rc = AdjustTokenPrivileges(
+         hToken,
+         FALSE,
+         &tp,
+         sizeof(tp),
+         NULL,
+         NULL);
+
+  if (!rc)
+  {
+    CloseHandle(hToken);
+    CloseHandle(hProcessToken);
+    return false;
+  }
+
+  hDebugToken = hToken;
+  return true;
+}
+
+void DebugToken::CloseToken()
+{
+  CloseHandle(hDebugToken);
+  hDebugToken = NULL;
+}
+
 BOOL KillProcessNT(DWORD pid,HWND hwnd)
 {
-  HANDLE hProcess;
-  BOOL bPrivilegesAdded = FALSE;
+  DebugToken token;
+  HANDLE hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, pid );
 
-  while(1)
+  // If access denied, try to assign debug privileges
+  if (hProcess==NULL && GetLastError()==ERROR_ACCESS_DENIED)
   {
-      SetLastError(0);
-      hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, pid );
-      if(hProcess || bPrivilegesAdded)
-      break;
-      // If access denied, try to assign debug privileges
-      if(GetLastError()!=ERROR_ACCESS_DENIED ||
-      !ChangePrivileges(TRUE,TRUE))
-      break;
-      bPrivilegesAdded = TRUE;
+    const TCHAR *MsgItems[]=
+    {
+      GetMsg(MDeleteTitle),
+      GetMsg(MCannotDeleteProc),
+      GetMsg(MRetryWithDebug),
+      GetMsg(MDangerous),
+      GetMsg(MYes),
+      GetMsg(MNo)
+    };
+
+    if(Message(FMSG_WARNING,NULL,MsgItems,ArraySize(MsgItems),2)==0)
+    {
+      if (token.Enable())
+        hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, pid );
+    }
   }
 
   BOOL bRet = FALSE;
@@ -526,8 +607,6 @@
     bRet = TerminateProcess( hProcess, 1 );
     CloseHandle( hProcess );
   }
-  if(bPrivilegesAdded)
-      ChangePrivileges(FALSE,FALSE);
 
   return bRet;
 }
@@ -660,10 +739,8 @@
 void PrintModulesNT(HANDLE InfoFile, DWORD dwPID, _Opt& Opt)
 {
     ModuleData Data;
-    HANDLE hProcess =
-    OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ|READ_CONTROL, FALSE, dwPID);
-    if(GetLastError()==ERROR_ACCESS_DENIED && ChangePrivileges(TRUE,FALSE))
-    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ|READ_CONTROL , FALSE, dwPID);
+    DebugToken token;
+    HANDLE hProcess = OpenProcessForced(&token, PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|READ_CONTROL, dwPID);
     PROCESS_PARAMETERS* pProcessParams;
     char *pEnd;
     if(hProcess && GetInternalProcessData( hProcess, &Data, pProcessParams, pEnd, true)) {

==== BEGIN SVK PATCH BLOCK ====
Version: svk v2.0.99_01 (MSWin32)

eJytWd1vHFcVHyGVD1eRSlQpPCB0K7bOumzs+f5YY+PN7jpZst41u+tYpYTVnTt3vEMmM6uZWTsm
48obt0kKilqQqvapQkiVAKmlqlR4QIivF3gCCZAQ/0L/At64c2dmPfvZUCFFse+95/7uOb9z7jnn
jre9zvoWF25usmGOY8P2zRvF4i4MUO95MsrJITaswPVyUmjjQ2znhNB2D3Ji6MA7mKwG0DvAweYm
Rzar8eYq3ZCCiBGGDgPX8XMaBesGHsY5LtS2yAFbQvSvm+O00MdkicJ1PXxo+ZbrkNMURSICRJwj
290+drqe6wZEAV5S2S0+2sqGyHZ93I3At7RwS4rE+VTctGxyGh/uei6yLT9YRf0+hUsgqLQwV7o3
Q1ocl+bCHnQMG/szoaVxYTHsY88Meh6Gxkx5eVyeDXeRDf3Z2MoC7FmKq2PySnh0x5qJq00auBtx
0ehMClPPSQn9huVhRDx/HEkQzxAougr7ffu4G+C7gYHtAFLfCHxoSJKsspoMsY5ljRd4qGuSiU3I
GSILNZzjNYkEVINh/vzMX8oX73+BebXOnA4h84tnH1z+GfPWtz+QLywBcLXZrAMPgQ3Qae1V16Mp
/8gikZc3jloY+q6zEs3di/4DAEEfg0q93t1tNcvVdrtb6nRK5evFeBWAiuVD3cYdSmHd0j3oHZeh
bfv5XsW2V9ZTOZ2s316fg1mpjmNifXDQcW9jp1gsR0zR3/OzwE4uLEU/PBwMPIdYFQ0sE+QbnZVY
eAyLbAtisC0xew9ip8UsQyzqAtJkTdEEQ1Z4xIuY41iEVE7kFVVY6CchQhA5KIlQ43ieg6aEJV0U
DFXCOqtzKmSRkhNlPvbTP7V/fePiGcv88h5zevYV5uFnPlj+MfPOxV9fvrBEQzij/YWlxCFra/Es
iKMWBPFqtOQHMLAQOHRt8tPG4HqpUalXQe8cZT2mi6K04SE2gHWH3ADic7LDdbJg6WYqNr5Zd10b
+NH8emYCO1EgGIlUf6DbFipOOiG/UsxC5ht79fpKIQbLm9D2MRklSMkY3DuJUV7OwoB7oEXSqxeQ
sEijIFGkSrePwoXOjWRTyYQrupiJi9GuEZeWASZi8GSkxgsxYQUwM5xoMBimygkmNDisIglCzlRU
SSLRoLCmhGR18bUXaTiJhiQqPKvLCJuihlgJIZ6ToKYamNU1niTf5NoP7z8zvM89jZm/XmVOMfPh
0t8+e05ZrOroCgHQa+E7boCjvI1JqG2AJslfyWjb9RBxwHJi3uie7u1247goAONot1Yp0Bwy03qq
u4mgybMcJFobSNQkToYCJOqTAVLJFVlovRQhsCaSEIsFHbI8EgzO1E1OZwVBEWRZQ5pIzhUS6x98
d/hgHxSZ93bI4PPvdR8xDxrv33qD+aj6Ue6nzOOXP36Keaz853ILmx72e/lJZiaN/dZetfVit9bY
brZ2Sp1asxHOtJNqKZsshJqgcRyCrMGKuiHqmIO6IvEGJ0vyQjvlCAGpsqggUcKaik1W1BRZ0AVW
xRxrQkHl1RxPCj6185UfPPvKo0svDL/KDP9+zJxWmFd3hv8QmeHPLw3/feVHzNn62VnxtMS8mTt7
7cuPmY/Vs3e+syAKaCQ8SQxMYcyJkWna0pV2tZOdL9CNq8nNnMktZUYyZWRi2UACywnQIL9pGhSw
rgkSJ8qGupBbJUIQkKRgU0GmIJCwE7BCrhPZa+gaB1nJIAk5uUDvNt69tPQl5nWZeZt5s/bGUwlP
L+/v1Mqu45BiTZIkyQEzlaVHyRoLkW6aAidjRWGRjhRVM3mepABWlzR+obJqhIB1TuORIZiGxHIq
FllDg1A0BQ1KgqRJ5KS0yv+u+Pv2F4fLzMNdUuWXmffxw2vMo7u/ujqmbbE4oXwR9Gv7Or7Txt6h
RfycpuCeV4d+kGdXkkpTdmuOFVjQtr6PY5ko9UXpcwJ/kp1kP2kMUDyb5NSyu+dY55AzOaQMIEEz
DQMhTiMJg3Q6GkkfOkc4NTGpwEhcyKEWIfC8rpuawXKGIJq6TtMGyZaYpFBelSDxFEd77yhr/ObG
8I83vvbWgPkDy5ze15jf7v7p66c/NJlrw4fa6aNbzPBzw8cW85OT4eurp8fMa08PP9yazv+V/War
QlLitg0P/PNhcpNqRiHuuvSa01sZVfK0ws68ffkRWLSpkAVLS5Rl5tO9GxuRh8DyMriGg8iPVc9z
vfzKxka11Wq2uqVy0mc1atVK0hndS5NA1C9RO65spqVzJV27l6kXn1ZP2qXRH5OdSbY5y3Qp5ITI
HFqraYHOyqUqJjRGyif9AghDMIYSwyS2JC1i4A1w0gScN8KRPXEHG1d5QmJ54HnYCeLZPLkfneaN
aqNb29mtttrNRqlTjWtfASxn+pnY5Ein5zyUbaMzMufWpeTP9lmj2aVnjnxBVY3X2nvUoQkGJm3S
SCg2k7ZOYx1ytLmNg6yZkRqFLGVz1Y+msiY8N0btKEhoo3SdPu3yU6wspOFkzElT2qce3kj9N+nP
k5mxknZ9mVh5LoF6gqiYzdYiZ08ZkArM4y5h7hN4m8PaFDfntD0JOWNdb8LQREqaOnL8ymSlMncm
zQyjS0PaxnqtTK/M8hj0EzKYajWlDtWkMuiTl0ZqSvVuPtPcjJ1WyCxM3WYQJnO0fxmNSpVv7rU7
5KFau1mrV69V21kQGhGZcRujgWcFx7Xsm2rs1EiNuavLvREpc67hWJxMEzn//sTGnFsBgj5dDvqr
u551SFLyAS67AycgfHJTK/5L7K3VUhB4lj4IcFQA2tVzsG61Ubpar1ZGHvkkxcc0/tQmUd+XjO8N
/IDKn2s7FgBTnt8u1dvVMdqDfnbok+bENfNBf2WRq9OG6Ekc9f+xd7w+9tIX+cy7Tl+t876ipP1d
VpHJEjCzGFNomgFuWLad6N7o5ONup28Zhev7jQroHTnGqAmc9fBY3PeMHhKdamunFhfa2GfRESAl
fW0N1ExA3pIRgoEdC5MmK/COyTkA+r514JDZ6DNJfxQXo2T8qZum9JuY6/gB6JSvl1rghR3/oBbg
O/5LtzYmqiFBJYv5nQq2MclOVmDj85hKF8vQcdwgFon0mpZoYWLWvhXEPpler0DnAHvuwJ9eehHP
mGy4SaY9GX0MIZ3kDiEEHuD89k77Wne/1GrUGtcKNOpTAwslz4PH7ah3T6dWCjxhi53bUK5O9ZNz
28gncDvVec5TdmFM/c8v1Zs73Va1VAmj/7rlZqPTatZnvlfoa0NgdQXLJnmqi4Yi8JpmcLygYUEz
JNVgdYN+/+VkMeRWwbZ1l5RqD/vugOgEbAxv++CoR6yhZdxyDsbD1jjA60t8ui/7Jlsbf08BHdrQ
QQRgfUlYBZ0eBqT5IQm9Vz0Mkk8eFdfB4Aj6YOATMB2broeBFdApRLsBYzWnhf3kS76wucmHOZ6P
/0jRoX9oKBbJoaSp8qH9vBzmxLAPg15OCD18SAaDgWXkeCFcI8nIub3WtwcHluOvpYD0I7hCOJND
hTyJJYNHV5DMoiusyLFXoKjAK5BlBV7WRANJxn8BvC6bYw==
==== END SVK PATCH BLOCK ====
proclist3.patch (18,344 bytes)   

alexeypa

2009-02-20 07:27

reporter   bugnote:0002543

Прикрепил обновленную версию: proclist3.patch

Проблема была в том, что при вызове DuplicateTokenEx указывался неверный impersonation level.

vskirdin

2009-02-20 10:13

administrator   bugnote:0002546

build 148
проверь, все ли нормально: пришлось руками поковыряться, т.к. патч на PlistNT.cpp немного бреханул.

alexeypa

2009-02-20 16:42

reporter   bugnote:0002553

> проверь, все ли нормально: пришлось руками поковыряться, т.к. патч на PlistNT.cpp немного бреханул.

"svk pull" никаких дополнительных изменений в PlistNT.cpp не нашел - значит все в порядке.

sdindikov

2010-02-08 14:51

developer   bugnote:0004887

смена на impersonation level помогла исправить проблему только на просмотре данных на локальном компе, если смотреть удалённый то проблема осталась. Надо фиксить дальше.

Вот вывод
FAR v1.75 (build 2619) x86 [1.75.0.2619] (Win7 local, смотрю под доменным админом процессы на W2003 R2)

Proclist.dll 1.75 build 147 [1.75.0.147]

Модуль: ConEmu.exe
Полный путь: C:\Program Files\Far2\ConEmu.exe
Версия файла: 2010.2.7a
Описание: Console Emulator (x86)
PID: 8104
Parent PID: 7424 (explorer.exe)
Приоритет: 8
Нитей: 6
Владелец: GOMELENERGO\s.dindikov (S-1-5-21-2030351553-2826686770-609815184-1249)
Сеанс: 2

Запущен: 05.02.2010 9:40:20
Выполняется: 3 07:00:07

------------------------------8<--- CUT HERE ---8<------------------------------
Proclist.dll 1.75 build 148 [1.75.0.148]/ 1.75 build 159 [1.75.0.159]
Модуль: ConEmu.exe
PID: 8104
Parent PID: 7424 (explorer.exe)
Приоритет: 8
Нитей: 6

Запущен: 05.02.2010 9:40:18
Выполняется: 3 07:01:40

sdindikov

2010-02-08 14:52

developer   bugnote:0004888

переоткрыл...

vskirdin

2011-01-14 08:16

administrator   bugnote:0006110

автор, ау!!!

alexeypa

2011-01-16 04:33

reporter   bugnote:0006123

Да тут я. :-) Сейчас посмотрю в чем дело.

alexeypa

2011-01-16 08:14

reporter  

proclist4.patch (4,518 bytes)   
Index: perfthread.cpp
===================================================================
--- perfthread.cpp	(revision 5446)
+++ perfthread.cpp	(working copy)
@@ -440,6 +440,7 @@
 {
 	HANDLE handles[2] = {hEvtBreak, hEvtRefresh};
 
+	CoInitialize(NULL);
 	while (1)
 	{
 		Refresh();
@@ -458,6 +459,7 @@
 	}
 
 	WMI.Disconnect();
+	CoUninitialize();
 	return 1;
 }
 
Index: perfthread.hpp
===================================================================
--- perfthread.hpp	(revision 5446)
+++ perfthread.hpp	(working copy)
@@ -72,6 +72,7 @@
 class WMIConnection
 {
 
+		DebugToken token;
 		IWbemServices *pIWbemServices;
 		int ExecMethod(DWORD dwPID, PCWSTR wsMethod, PCWSTR wsParamName=0, DWORD dwParam=0);
 		HRESULT hrLast;
Index: Proclist.cpp
===================================================================
--- Proclist.cpp	(revision 5446)
+++ Proclist.cpp	(working copy)
@@ -100,11 +100,10 @@
 PLookupAccountName pLookupAccountName = fLookupAccountName;
 
 
-static HRESULT WINAPI fCoInitializeSecurity(
-    PSECURITY_DESCRIPTOR, LONG, SOLE_AUTHENTICATION_SERVICE*, void*,
-    DWORD, DWORD, SOLE_AUTHENTICATION_LIST*, DWORD, void*)
+static HRESULT WINAPI fCoSetProxyBlanket(
+    IUnknown*, DWORD, DWORD, OLECHAR*, DWORD, DWORD, RPC_AUTH_IDENTITY_HANDLE, DWORD)
 { return E_FAIL; }
-PCoInitializeSecurity pCoInitializeSecurity = fCoInitializeSecurity;
+PCoSetProxyBlanket pCoSetProxyBlanket = fCoSetProxyBlanket;
 
 #ifndef UNICODE
 #define FUNC_AW_SUFFIX  "A"
@@ -170,8 +169,8 @@
 
 		if ((h = GetModuleHandle(_T("ole32"))) != NULL)
 		{
-			if ((f = GetProcAddress(h, "CoInitializeSecurity")) != NULL)
-				pCoInitializeSecurity = (PCoInitializeSecurity)f;
+			if ((f = GetProcAddress(h, "CoSetProxyBlanket")) != NULL)
+				pCoSetProxyBlanket = (PCoSetProxyBlanket)f;
 		}
 
 		Inited = TRUE;
Index: Proclist.hpp
===================================================================
--- Proclist.hpp	(revision 5446)
+++ Proclist.hpp	(working copy)
@@ -320,8 +320,8 @@
 extern PIsWow64Process pIsWow64Process;
 typedef DWORD (WINAPI *PGetGuiResources)(IN HANDLE hProcess, IN DWORD uiFlags);
 extern PGetGuiResources pGetGuiResources;
-typedef HRESULT(WINAPI *PCoInitializeSecurity)(PSECURITY_DESCRIPTOR,LONG,SOLE_AUTHENTICATION_SERVICE*, void*,DWORD,DWORD,SOLE_AUTHENTICATION_LIST*,DWORD,void*);
-extern PCoInitializeSecurity pCoInitializeSecurity;
+typedef HRESULT(WINAPI *PCoSetProxyBlanket)(IUnknown*, DWORD, DWORD, OLECHAR*, DWORD, DWORD, RPC_AUTH_IDENTITY_HANDLE, DWORD);
+extern PCoSetProxyBlanket pCoSetProxyBlanket;
 //------
 
 extern TCHAR FPRINTFbuffer[];
Index: wmi.cpp
===================================================================
--- wmi.cpp	(revision 5446)
+++ wmi.cpp	(working copy)
@@ -49,13 +49,12 @@
 
 WMIConnection::WMIConnection(): pIWbemServices(NULL), hrLast(0)
 {
-	CoInitialize(NULL);
+	token.Enable();
 }
 
 WMIConnection::~WMIConnection()
 {
 	Disconnect();
-	CoUninitialize();
 }
 
 void WMIConnection::GetProcessExecutablePath(DWORD dwPID, TCHAR* pPath)
@@ -282,10 +281,6 @@
 		pUser = pPassword = 0; // Empty username means default security
 
 	hrLast = WBEM_S_NO_ERROR;
-	//nt 3.51 dont' have CoInitializeSecurity
-	// It must called per thread, otherwise returns
-	pCoInitializeSecurity(0, -1, 0, 0, RPC_C_AUTHN_LEVEL_DEFAULT,
-	                      RPC_C_IMP_LEVEL_IMPERSONATE, 0, EOAC_NONE, 0);
 	IWbemLocator *pIWbemLocator = NULL;
 
 	if ((hrLast=CoCreateInstance(CLSID_WbemLocator,
@@ -310,8 +305,27 @@
 #endif
 
 		if ((hrLast=pIWbemLocator->ConnectServer(Namespace, BStr(pUser), BStr(pPassword),0,0,0,0,
-		            &pIWbemServices)) != S_OK)
+		            &pIWbemServices)) == S_OK)
+		{
+			// We impersonate a token to enable SeDebugPrivilege privilege.
+			// Enable static cloacking here to make sure the server sees it.
+			//
+			// Some privileged information (like the full EXE path) will not be
+			// returned if this call fails. However it is not fatal so the error
+			// can be ignored.
+			pCoSetProxyBlanket(pIWbemServices,
+			                   RPC_C_AUTHN_DEFAULT,
+			                   RPC_C_AUTHN_DEFAULT,
+			                   NULL,
+			                   RPC_C_AUTHN_LEVEL_DEFAULT,
+			                   RPC_C_IMP_LEVEL_IMPERSONATE,
+			                   NULL,
+			                   EOAC_STATIC_CLOAKING);
+		}
+		else
+		{
 			pIWbemServices = 0;
+		}
 
 		pIWbemLocator->Release();
 	}
proclist4.patch (4,518 bytes)   

alexeypa

2011-01-16 08:19

reporter   bugnote:0006124

А вот и патчик подоспел, и год не прошел. :-) Надо было меня по-раньше пнуть.

Патч (proclist4.patch) исправляет три проблемы:

1. Помещает CoInitialize и CoUninitialize в более подходящее место.
2. Вместо влияющей на весь процесс CoInitializeSecurity используется CoSetProxyBlanket, которая влияет только на конктерный COM proxy.
3. Ставится cloacking mode, при котором SeDebugPrivilege подхватывается WMI сервером.

vskirdin

2011-01-17 11:25

administrator   bugnote:0006139

build 165

sdindikov

2011-02-02 11:47

developer   bugnote:0006327

Last edited: 2011-02-02 12:06

alexeypa


Если захожу на удалённую машину под доменным админом
то бывает не сразу виден путь к просматриваемому процессу

например первый раз посмотрели

Module: JNBDotNetSide.exe
PID: 1332
Parent PID: 1312 (CFDotNetsvc.exe)
Priority: 8
Threads: 16
Owner: NT AUTHORITY\система (S-1-5-18)
Session: 0

Started at: 13.01.2011 17:11:34
Uptime: 3 20:21:29

второй:
Module: JNBDotNetSide.exe
Full path: d:\ColdFusion9\jnbridge\JNBDotNetSide.exe
PID: 1332
Parent PID: 1312 (CFDotNetsvc.exe)
Priority: 8
Threads: 16
Owner: NT AUTHORITY\система (S-1-5-18)
Session: 0

Started at: 13.01.2011 17:11:34
Uptime: 3 20:22:18

разница тока в
Full path: d:\ColdFusion9\jnbridge\JNBDotNetSide.exe

возможно нехватило времени на инициализацию какую-то просто?


сейчас вот проверял путь до процесса появился не ранее через 20 секунд.

делал постоянно F3-esc на процессе.


в 147 и ранее версии такого небыло, путь показывался сразу.
Vskirdin тоже говорит что заметил такой эффект у себя.

alexeypa

2011-02-04 07:56

reporter   bugnote:0006351

> в 147 и ранее версии такого небыло, путь показывался сразу.
Vskirdin тоже говорит что заметил такой эффект у себя.

Я это тоже заметил, но решил что это by design. Пути появляются по мере прогресса WMI потока. Я посмотрю в чем разница, когда будет свободная минута.

Issue History

Date Modified Username Field Change
2009-02-09 01:06 alexeypa New Issue
2009-02-09 01:06 alexeypa File Added: proclist.patch
2009-02-10 18:07 vskirdin Note Added: 0002405
2009-02-10 20:35 alexeypa Note Added: 0002408
2009-02-11 16:26 vskirdin Note Added: 0002432
2009-02-12 16:51 alexeypa Note Added: 0002448
2009-02-13 08:00 alexeypa File Added: proclist2.patch
2009-02-13 08:05 alexeypa Note Added: 0002452
2009-02-13 08:06 alexeypa Note Edited: 0002452
2009-02-13 08:06 alexeypa Note Edited: 0002452
2009-02-19 06:30 alexeypa Note Added: 0002492
2009-02-19 06:30 alexeypa Duplicate ID 0 => 745
2009-02-19 06:30 alexeypa Status new => resolved
2009-02-19 06:30 alexeypa Resolution open => duplicate
2009-02-19 06:30 alexeypa Assigned To => alexeypa
2009-02-19 08:15 DrKnS Project Far Manager => Plugins
2009-02-19 08:17 DrKnS Assigned To alexeypa =>
2009-02-19 08:17 DrKnS Note Added: 0002495
2009-02-19 08:17 DrKnS Status resolved => new
2009-02-19 08:17 DrKnS Resolution duplicate => reopened
2009-02-19 08:17 DrKnS Note Edited: 0002495
2009-02-19 08:18 DrKnS Category _Common => ProcList
2009-02-19 11:45 vskirdin Note Added: 0002507
2009-02-19 15:16 alexeypa Note Added: 0002523
2009-02-19 16:58 vskirdin Note Added: 0002524
2009-02-19 17:38 alexeypa Note Added: 0002528
2009-02-19 19:38 alexy Status new => assigned
2009-02-19 19:38 alexy Assigned To => vskirdin
2009-02-20 07:26 alexeypa File Added: proclist3.patch
2009-02-20 07:27 alexeypa Note Added: 0002543
2009-02-20 10:13 vskirdin Note Added: 0002546
2009-02-20 10:13 vskirdin Status assigned => feedback
2009-02-20 16:42 alexeypa Note Added: 0002553
2009-02-20 16:42 alexeypa Status feedback => resolved
2009-02-20 16:42 alexeypa Resolution reopened => fixed
2009-02-20 16:42 alexeypa Duplicate ID 745 => 0
2009-02-24 07:43 vskirdin Status resolved => closed
2009-02-24 07:43 vskirdin Fixed in Version => 2.0
2010-02-08 14:51 sdindikov Note Added: 0004887
2010-02-08 14:52 sdindikov Note Added: 0004888
2010-02-08 14:52 sdindikov Status closed => new
2010-02-08 14:52 sdindikov Resolution fixed => reopened
2011-01-14 08:16 vskirdin Note Added: 0006110
2011-01-16 04:33 alexeypa Note Added: 0006123
2011-01-16 08:14 alexeypa File Added: proclist4.patch
2011-01-16 08:19 alexeypa Note Added: 0006124
2011-01-17 11:25 vskirdin Note Added: 0006139
2011-01-17 11:25 vskirdin Status new => feedback
2011-01-17 15:53 alexeypa Status feedback => resolved
2011-02-02 11:47 sdindikov Note Added: 0006327
2011-02-02 11:53 sdindikov Note Edited: 0006327
2011-02-02 11:54 sdindikov Note Edited: 0006327
2011-02-02 11:55 sdindikov Note Edited: 0006327
2011-02-02 12:06 sdindikov Note Edited: 0006327
2011-02-04 07:56 alexeypa Note Added: 0006351
2011-03-22 00:05 alexy Status resolved => closed
2011-03-22 00:05 alexy Resolution reopened => fixed