CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Uruchomienie zewnętrznego programu jako administrator

Uruchomienie zewnętrznego programu jako administrator

dział ogólny

Uruchomienie zewnętrznego programu jako administrator

Nowy postprzez Krzysiu555 » czwartek, 13 maja 2010, 19:21

Witam,
otóż do uruchomienia zewnętrznego programu używam tego kodu:
Kod: Zaznacz cały
WinExec("C:\\nazwakatalogu\\nazwaprogramu.exe", SW_SHOW);

w XP jest wszystko ok ale windows 7 odmawia programowi dostępu do plików i folderów, rozwiązaniem byłoby uruchomienie tego programu jako administrator (taka opcja jest w menu kontekstowym każdego exe w w7). Jak to zrobić z poziomu kodu?
Pozdrawiam
Avatar użytkownika
Krzysiu555
Intelektryk
Intelektryk
 
Posty: 161
Dołączył(a): sobota, 23 sierpnia 2008, 16:55
Podziękował : 2
Otrzymał podziękowań: 1
System operacyjny: Windows 7 Professional 64
Kompilator: C++ Builder 6 Personal
Gadu Gadu: 0
    Windows XPFirefox

Re: Uruchomienie zewnętrznego programu jako administrator

Nowy postprzez Cyfrowy Baron » piątek, 14 maja 2010, 07:10

W serwisie Cyfrowy Baron w dziale: porady -> API w poradzie: Uruchamianie programu z poświadczeniami dla wybranego użytkownika (tylko WinXP) jest przykład uruchamiania programu z poświadczeniami innego użytkownika. Zastrzeżenie tylko WinXP tyczy się wcześniejszych wersji systemu Windows, być może zadziała w Windows Vista i Windows 7. Użycie funkcji CreateProcessWithLogonW może w przypadku tych systemów wymagać użycia tokenów i na pewno tak jest. Nie korzystam z systemu Windows 7, wiec nie mogę tego sprawdzić, ale mogę podać kod z pliku pomocy dla C++Builder 2007 i 2010.

KOD cpp:     UKRYJ  
#define UNICODE
#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <stdio.h>
#include <userenv.h>

void DisplayError(LPWSTR pszAPI)
{
    LPVOID lpvMessageBuffer;

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, GetLastError()
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
        (LPWSTR)&lpvMessageBuffer, 0, NULL);

    //
    //... now display this string
    //
    wprintf(L"ERROR: API        = %s.\n", pszAPI);
    wprintf(L"       error code = %d.\n", GetLastError());
    wprintf(L"       message    = %s.\n"(LPWSTR)lpvMessageBuffer);

    //
    // Free the buffer allocated by the system
    //
    LocalFree(lpvMessageBuffer);

    ExitProcess(GetLastError());
}

void wmain(int argc, WCHAR *argv[])
{
    DWORD     dwSize;
    HANDLE    hToken;
    LPVOID    lpvEnv;
    PROCESS_INFORMATION pi = {0};
    STARTUPINFO         si = {0};
    WCHAR               szUserProfile[256] = L"";

    si.cb = sizeof(STARTUPINFO);
    
    if (argc != 4)
    {
        wprintf(L"Usage: %s [user@domain] [password] [cmd]", argv[0]);
        wprintf(L"\n\n");
        return;
    }

    //
    // TO DO: change NULL to '.' to use local account database
    //
    if (!LogonUser(argv[1]NULL, argv[2], LOGON32_LOGON_INTERACTIVE, 
            LOGON32_PROVIDER_DEFAULT, &hToken))
        DisplayError(L"LogonUser");

    if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
        DisplayError(L"CreateEnvironmentBlock");

    dwSize = sizeof(szUserProfile)/sizeof(WCHAR);

    if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
        DisplayError(L"GetUserProfileDirectory");

    //
    // TO DO: change NULL to '.' to use local account database
    //
    if (!CreateProcessWithLogonW(argv[1]NULL, argv[2]
            LOGON_WITH_PROFILE, NULL, argv[3]
            CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile, 
            &si, &pi))
        DisplayError(L"CreateProcessWithLogonW");

    if (!DestroyEnvironmentBlock(lpvEnv))
        DisplayError(L"DestroyEnvironmentBlock");

    CloseHandle(hToken);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}
 
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Uruchomienie zewnętrznego programu jako administrator

Nowy postprzez mckri » wtorek, 22 maja 2012, 09:14

Nie chcę zakładać nowego wątku w podobnej sprawie...
Czy korzystając z funkcji 'CreateProcessWithLogonW' można uruchomić program na innym użytkowniku ale bez ładowania profilu tego użytkownika?
Np. z konta gościa uruchamiam program jako administrator, ale nie chcę, żeby był ładowany profil administratora. Poprzez profil rozumiem np. ścieżki dostępu do katalogów specjalnych (np. CSIDL_PERSONAL) i zmiennych środowiskowych, (np. %temp%).
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows 7Opera

Re: Uruchomienie zewnętrznego programu jako administrator

Nowy postprzez polymorphism » wtorek, 22 maja 2012, 10:15

A próbowałeś bez flagi LOGON_WITH_PROFILE?
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Uruchomienie zewnętrznego programu jako administrator

Nowy postprzez mckri » wtorek, 22 maja 2012, 11:30

Tak, próbowałem. Mimo to odczyt CSIDL_PERSONAL wskazuje na katalog innego uzytkownika (administratora), który podany był w 'CreateProcessWithLogonW'.
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows 7Opera

Re: Uruchomienie zewnętrznego programu jako administrator

Nowy postprzez Cyfrowy Baron » wtorek, 22 maja 2012, 18:07

Wielki możliwości w przypadku tej funkcji nie ma. Zamiast flagi LOGON_WITH_PROFILE możesz podać wartość 0 lub flagę LOGON_NETCREDENTIALS_ONLY i to w zasadzie kończy kombinacje.

Być może funkcja CreateProcessAsUser w połączeniu z funkcją LogonUser potrafi zrobić to co chcesz.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Uruchomienie zewnętrznego programu jako administrator

Nowy postprzez mckri » środa, 23 maja 2012, 09:36

Ok, dzieki Baronie, tylko jak tego dokładnie użyć.
Sprawdziłem taką kombinację...

KOD cpp:     UKRYJ  
//Dane wejściowe
Edit1->Text="c:\\program.exe";
Edit2->Text="username";
Edit3->Text="passw";

  DWORD dwPID;
  HANDLE hProcess;
  HANDLE hToken;
  BOOL bResult = FALSE;
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  ZeroMemory(&si, sizeof(STARTUPINFO));
  si.cb= sizeof(STARTUPINFO);

  if(LogonUser(Edit2->Text.t_str(),NULL,Edit3->Text.t_str(),LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&hToken))
   ShowMessage("OK");  else   ShowMessage("NOT OK");

//Tutaj funkcja zwraca TRUE, jednak dalej wykonanie CreateProcessAsUser zwraca FALSE


  bResult = CreateProcessAsUser(
          hToken,            // client's access token
          Edit1->Text.t_str(),              // file to execute
          NULL,     // command line
          NULL,              // pointer to process SECURITY_ATTRIBUTES
          NULL,              // pointer to thread SECURITY_ATTRIBUTES
          FALSE,             // handles are not inheritable
          NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,   // creation flags
          NULL,              // pointer to new environment block
          NULL,              // name of current directory
          &si,               // pointer to STARTUPINFO structure
          &pi                // receives information about new process
          );

       if(bResult==true) ShowMessage("OK"); else ShowMessage("NOT OK");  //zwraca FALSE, Dlaczego?
 
Ostatnio edytowano środa, 23 maja 2012, 11:08 przez polymorphism, łącznie edytowano 1 raz
Powód: używaj znaczników CPP!
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows 7Opera

Re: Uruchomienie zewnętrznego programu jako administrator

Nowy postprzez Cyfrowy Baron » środa, 23 maja 2012, 16:16

Przykładowy kod z pliku pomocy dla środowiska C++Builder 2010:

KOD cpp:     UKRYJ  
define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \
DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | \
DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \
DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED)

#define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \
WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | \
WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | \
WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | \
STANDARD_RIGHTS_REQUIRED)


#define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | \
GENERIC_EXECUTE | GENERIC_ALL)


BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid);

BOOL AddAceToDesktop(HDESK hdesk, PSID psid);

BOOL StartInteractiveClientProcess (
    LPTSTR lpszUsername,    // client to log on
    LPTSTR lpszDomain,      // domain of client's account
    LPTSTR lpszPassword,    // client's password
    LPTSTR lpCommandLine    // command line to execute
)
{
   HANDLE      hToken;
   HDESK       hdesk = NULL;
   HWINSTA     hwinsta = NULL, hwinstaSave = NULL;
   PROCESS_INFORMATION pi;
   PSID pSid = NULL;
   STARTUPINFO si;
   BOOL bResult = FALSE;

// Log the client on to the local computer.

   if (!LogonUser(
           lpszUsername,
           lpszDomain,
           lpszPassword,
           LOGON32_LOGON_INTERACTIVE,
           LOGON32_PROVIDER_DEFAULT,
           &hToken) )
   {
      goto Cleanup;
   }

// Save a handle to the caller's current window station.

   if ( (hwinstaSave = GetProcessWindowStation() ) == NULL)
      goto Cleanup;

// Get a handle to the interactive window station.

   hwinsta = OpenWindowStation(
       "winsta0",                   // the interactive window station
       FALSE,                       // handle is not inheritable
       READ_CONTROL | WRITE_DAC);   // rights to read/write the DACL

   if (hwinsta == NULL)
      goto Cleanup;

// To get the correct default desktop, set the caller's
// window station to the interactive window station.

   if (!SetProcessWindowStation(hwinsta))
      goto Cleanup;

// Get a handle to the interactive desktop.

   hdesk = OpenDesktop(
      "default",     // the interactive window station
      0,             // no interaction with other desktop processes
      FALSE,         // handle is not inheritable
      READ_CONTROL | // request the rights to read and write the DACL
      WRITE_DAC |
      DESKTOP_WRITEOBJECTS |
      DESKTOP_READOBJECTS);

// Restore the caller's window station.

   if (!SetProcessWindowStation(hwinstaSave))
      goto Cleanup;

   if (hdesk == NULL)
      goto Cleanup;

// Get the SID for the client's logon session.

   if (!GetLogonSID(hToken, &pSid))
      goto Cleanup;

// Allow logon SID full access to interactive window station.

   if (! AddAceToWindowStation(hwinsta, pSid) )
      goto Cleanup;

// Allow logon SID full access to interactive desktop.

   if (! AddAceToDesktop(hdesk, pSid) )
      goto Cleanup;

// Impersonate client to ensure access to executable file.

   if (! ImpersonateLoggedOnUser(hToken) )
      goto Cleanup;

// Initialize the STARTUPINFO structure.
// Specify that the process runs in the interactive desktop.

   ZeroMemory(&si, sizeof(STARTUPINFO));
   si.cb= sizeof(STARTUPINFO);
   si.lpDesktop = TEXT("winsta0\\default");

// Launch the process in the client's logon session.

   bResult = CreateProcessAsUser(
      hToken,            // client's access token
      NULL,              // file to execute
      lpCommandLine,     // command line
      NULL,              // pointer to process SECURITY_ATTRIBUTES
      NULL,              // pointer to thread SECURITY_ATTRIBUTES
      FALSE,             // handles are not inheritable
      NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,   // creation flags
      NULL,              // pointer to new environment block
      NULL,              // name of current directory
      &si,               // pointer to STARTUPINFO structure
      &pi                // receives information about new process
   );

// End impersonation of client.

   RevertToSelf();

   if (bResult && pi.hProcess != INVALID_HANDLE_VALUE)
   {
      WaitForSingleObject(pi.hProcess, INFINITE);
      CloseHandle(pi.hProcess);
   }

   if (pi.hThread != INVALID_HANDLE_VALUE)
      CloseHandle(pi.hThread);  

Cleanup:

   if (hwinstaSave != NULL)
      SetProcessWindowStation (hwinstaSave);

// Free the buffer for the logon SID.

   if (pSid)
      FreeLogonSID(&pSid);

// Close the handles to the interactive window station and desktop.

   if (hwinsta)
      CloseWindowStation(hwinsta);

   if (hdesk)
      CloseDesktop(hdesk);

// Close the handle to the client's access token.

   if (hToken != INVALID_HANDLE_VALUE)
      CloseHandle(hToken);  

   return bResult;
}

BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid)
{
   ACCESS_ALLOWED_ACE   *pace;
   ACL_SIZE_INFORMATION aclSizeInfo;
   BOOL                 bDaclExist;
   BOOL                 bDaclPresent;
   BOOL                 bSuccess = FALSE;
   DWORD                dwNewAclSize;
   DWORD                dwSidSize = 0;
   DWORD                dwSdSizeNeeded;
   PACL                 pacl;
   PACL                 pNewAcl;
   PSECURITY_DESCRIPTOR psd = NULL;
   PSECURITY_DESCRIPTOR psdNew = NULL;
   PVOID                pTempAce;
   SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
   unsigned int         i;

   __try
   {
      // Obtain the DACL for the window station.

      if (!GetUserObjectSecurity(
             hwinsta,
             &si,
             psd,
             dwSidSize,
             &dwSdSizeNeeded)
      )
      if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
      {
         psd = (PSECURITY_DESCRIPTOR)HeapAlloc(
               GetProcessHeap(),
               HEAP_ZERO_MEMORY,
               dwSdSizeNeeded);

         if (psd == NULL)
            __leave;

         psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(
               GetProcessHeap(),
               HEAP_ZERO_MEMORY,
               dwSdSizeNeeded);

         if (psdNew == NULL)
            __leave;

         dwSidSize = dwSdSizeNeeded;

         if (!GetUserObjectSecurity(
               hwinsta,
               &si,
               psd,
               dwSidSize,
               &dwSdSizeNeeded)
         )
            __leave;
      }
      else
         __leave;

      // Create a new DACL.

      if (!InitializeSecurityDescriptor(
            psdNew,
            SECURITY_DESCRIPTOR_REVISION)
      )
         __leave;

      // Get the DACL from the security descriptor.

      if (!GetSecurityDescriptorDacl(
            psd,
            &bDaclPresent,
            &pacl,
            &bDaclExist)
      )
         __leave;

      // Initialize the ACL.

      ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
      aclSizeInfo.AclBytesInUse = sizeof(ACL);

      // Call only if the DACL is not NULL.

      if (pacl != NULL)
      {
         // get the file ACL size info
         if (!GetAclInformation(
               pacl,
               (LPVOID)&aclSizeInfo,
               sizeof(ACL_SIZE_INFORMATION),
               AclSizeInformation)
         )
            __leave;
      }

      // Compute the size of the new ACL.

      dwNewAclSize = aclSizeInfo.AclBytesInUse +
            (2*sizeof(ACCESS_ALLOWED_ACE)) + (2*GetLengthSid(psid)) -
            (2*sizeof(DWORD));

      // Allocate memory for the new ACL.

      pNewAcl = (PACL)HeapAlloc(
            GetProcessHeap(),
            HEAP_ZERO_MEMORY,
            dwNewAclSize);

      if (pNewAcl == NULL)
         __leave;

      // Initialize the new DACL.

      if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
         __leave;

      // If DACL is present, copy it to a new DACL.

      if (bDaclPresent)
      {
         // Copy the ACEs to the new ACL.
         if (aclSizeInfo.AceCount)
         {
            for (i=0; i < aclSizeInfo.AceCount; i++)
            {
               // Get an ACE.
               if (!GetAce(pacl, i, &pTempAce))
                  __leave;

               // Add the ACE to the new ACL.
               if (!AddAce(
                     pNewAcl,
                     ACL_REVISION,
                     MAXDWORD,
                     pTempAce,
                    ((PACE_HEADER)pTempAce)->AceSize)
               )
                  __leave;
            }
         }
      }

      // Add the first ACE to the window station.

      pace = (ACCESS_ALLOWED_ACE *)HeapAlloc(
            GetProcessHeap(),
            HEAP_ZERO_MEMORY,
            sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) -
                  sizeof(DWORD));

      if (pace == NULL)
         __leave;

      pace->Header.AceType  = ACCESS_ALLOWED_ACE_TYPE;
      pace->Header.AceFlags = CONTAINER_INHERIT_ACE |
                   INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
      pace->Header.AceSize  = sizeof(ACCESS_ALLOWED_ACE) +
                   GetLengthSid(psid) - sizeof(DWORD);
      pace->Mask            = GENERIC_ACCESS;

      if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid))
         __leave;

      if (!AddAce(
            pNewAcl,
            ACL_REVISION,
            MAXDWORD,
            (LPVOID)pace,
            pace->Header.AceSize)
      )
         __leave;

      // Add the second ACE to the window station.

      pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
      pace->Mask            = WINSTA_ALL;

      if (!AddAce(
            pNewAcl,
            ACL_REVISION,
            MAXDWORD,
            (LPVOID)pace,
            pace->Header.AceSize)
      )
         __leave;

      // Set a new DACL for the security descriptor.

      if (!SetSecurityDescriptorDacl(
            psdNew,
            TRUE,
            pNewAcl,
            FALSE)
      )
         __leave;

      // Set the new security descriptor for the window station.

      if (!SetUserObjectSecurity(hwinsta, &si, psdNew))
         __leave;

      // Indicate success.

      bSuccess = TRUE;
   }
   __finally
   {
      // Free the allocated buffers.

      if (pace != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)pace);

      if (pNewAcl != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);

      if (psd != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)psd);

      if (psdNew != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);
   }

   return bSuccess;

}

BOOL AddAceToDesktop(HDESK hdesk, PSID psid)
{
   ACL_SIZE_INFORMATION aclSizeInfo;
   BOOL                 bDaclExist;
   BOOL                 bDaclPresent;
   BOOL                 bSuccess = FALSE;
   DWORD                dwNewAclSize;
   DWORD                dwSidSize = 0;
   DWORD                dwSdSizeNeeded;
   PACL                 pacl;
   PACL                 pNewAcl;
   PSECURITY_DESCRIPTOR psd = NULL;
   PSECURITY_DESCRIPTOR psdNew = NULL;
   PVOID                pTempAce;
   SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
   unsigned int         i;

   __try
   {
      // Obtain the security descriptor for the desktop object.

      if (!GetUserObjectSecurity(
            hdesk,
            &si,
            psd,
            dwSidSize,
            &dwSdSizeNeeded))
      {
         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
         {
            psd = (PSECURITY_DESCRIPTOR)HeapAlloc(
                  GetProcessHeap(),
                  HEAP_ZERO_MEMORY,
                  dwSdSizeNeeded );

            if (psd == NULL)
               __leave;

            psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(
                  GetProcessHeap(),
                  HEAP_ZERO_MEMORY,
                  dwSdSizeNeeded);

            if (psdNew == NULL)
               __leave;

            dwSidSize = dwSdSizeNeeded;

            if (!GetUserObjectSecurity(
                  hdesk,
                  &si,
                  psd,
                  dwSidSize,
                  &dwSdSizeNeeded)
            )
               __leave;
         }
         else
            __leave;
      }

      // Create a new security descriptor.

      if (!InitializeSecurityDescriptor(
            psdNew,
            SECURITY_DESCRIPTOR_REVISION)
      )
         __leave;

      // Obtain the DACL from the security descriptor.

      if (!GetSecurityDescriptorDacl(
            psd,
            &bDaclPresent,
            &pacl,
            &bDaclExist)
      )
         __leave;

      // Initialize.

      ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
      aclSizeInfo.AclBytesInUse = sizeof(ACL);

      // Call only if NULL DACL.

      if (pacl != NULL)
      {
         // Determine the size of the ACL information.

         if (!GetAclInformation(
               pacl,
               (LPVOID)&aclSizeInfo,
               sizeof(ACL_SIZE_INFORMATION),
               AclSizeInformation)
         )
            __leave;
      }

      // Compute the size of the new ACL.

      dwNewAclSize = aclSizeInfo.AclBytesInUse +
            sizeof(ACCESS_ALLOWED_ACE) +
            GetLengthSid(psid) - sizeof(DWORD);

      // Allocate buffer for the new ACL.

      pNewAcl = (PACL)HeapAlloc(
            GetProcessHeap(),
            HEAP_ZERO_MEMORY,
            dwNewAclSize);

      if (pNewAcl == NULL)
         __leave;

      // Initialize the new ACL.

      if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
         __leave;

      // If DACL is present, copy it to a new DACL.

      if (bDaclPresent)
      {
         // Copy the ACEs to the new ACL.
         if (aclSizeInfo.AceCount)
         {
            for (i=0; i < aclSizeInfo.AceCount; i++)
            {
               // Get an ACE.
               if (!GetAce(pacl, i, &pTempAce))
                  __leave;

               // Add the ACE to the new ACL.
               if (!AddAce(
                  pNewAcl,
                  ACL_REVISION,
                  MAXDWORD,
                  pTempAce,
                  ((PACE_HEADER)pTempAce)->AceSize)
               )
                  __leave;
            }
         }
      }

      // Add ACE to the DACL.

      if (!AddAccessAllowedAce(
            pNewAcl,
            ACL_REVISION,
            DESKTOP_ALL,
            psid)
      )
         __leave;

      // Set new DACL to the new security descriptor.

      if (!SetSecurityDescriptorDacl(
            psdNew,
            TRUE,
            pNewAcl,
            FALSE)
      )
         __leave;

      // Set the new security descriptor for the desktop object.

      if (!SetUserObjectSecurity(hdesk, &si, psdNew))
         __leave;

      // Indicate success.

      bSuccess = TRUE;
   }
   __finally
   {
      // Free buffers.

      if (pNewAcl != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);

      if (psd != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)psd);

      if (psdNew != NULL)
         HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);
   }

   return bSuccess;
}
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Uruchomienie zewnętrznego programu jako administrator

Nowy postprzez mckri » sobota, 26 maja 2012, 07:59

Jest pewien postęp. Udało się uruchomić proces jako administrator z konta zwyklego użytkownika z zachowaniem profilu użytkownika.
Wygląda to tak:
KOD cpp:     UKRYJ  
//   Edit1->Text=sciezka_do_programu
//  Edit2->Text=nazwa_usera
//  Edit3->Text=haslo
   DWORD     dwSize;
   LPVOID    lpvEnv;
   HANDLE    hToken;
   STARTUPINFOW si = { 0 };
   PROCESS_INFORMATION pi = { 0 };
   si.cb = sizeof(si);
   DWORD dwPID;
   HANDLE hProcess;
   LUID Luid;
   TOKEN_PRIVILEGES tpDebug;
   dwPID = GetCurrentProcessId();

   if ((hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID)) == NULL) ShowMessage("OpenProcess");
   if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) ShowMessage("OpenProcessToken");
   if (!(LookupPrivilegeValue(0, SE_DEBUG_NAME, &Luid))) ShowMessage("LookupPrivilegeValue");
   else
   {
        tpDebug.PrivilegeCount = 1;
        tpDebug.Privileges[0].Luid = Luid;
        tpDebug.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
   }
   if (!AdjustTokenPrivileges(hToken, FALSE, &tpDebug, sizeof(tpDebug), NULL, NULL)) ShowMessage("AdjustTokenPrivileges");
   if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))  ShowMessage(L"CreateEnvironmentBlock");

   CloseHandle(hToken);
   CloseHandle(hProcess);

   return CreateProcessWithLogonW( WideString(Edit2->Text).c_bstr(), NULL,WideString(Edit3->Text).c_bstr(), NULL,
   WideString(Edit1->Text).c_bstr(), NULL , CREATE_UNICODE_ENVIRONMENT, lpvEnv, NULL, &si, &pi);


Działa to fajnie, na XP i na wyższych OS z wyłączonym UAC (Vista, 7). Jednak gdy włączone jest UAC, potrzebuję nadać pełne uprawnienia administracyjne zalogowanego admina. Wiem że można wykorzystać strukturę SHELLEXECUTEINFO i ustawić lpVerb = "runas", jednak wywołanie funkcji ShellExecuteEx kończy sie załadowaniem profilu administratora - a mnie chodzi caly czas o to aby pracowac jako admin z zachowaniem profilu uzytkownika.

Na stronie http://www.codeproject.com/Articles/19165/Vista-UAC-The-Definitive-Guide podane jest rozwiązanie załadowania biblioteki "elevate.dll", która poprzez podobne do Winapi funkcji, może wykonać polecenie uruchomienia procesu - od razu z wyzszymi uprawnieniami. Próbowałem wykonać to w ten sposób:

KOD cpp:     UKRYJ  
//   Edit1->Text=sciezka_do_programu
//  Edit2->Text=nazwa_usera
//  Edit3->Text=haslo
   DWORD     dwSize;
   LPVOID    lpvEnv;
   HANDLE    hToken;
   STARTUPINFO si = { 0 };
   PROCESS_INFORMATION pi = { 0 };
   si.cb = sizeof(si);
   DWORD dwPID;
   HANDLE hProcess;
   LUID Luid;
   TOKEN_PRIVILEGES tpDebug;
   dwPID = GetCurrentProcessId();

   if ((hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID)) == NULL) ShowMessage("OpenProcess");
   if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) ShowMessage("OpenProcessToken");
   if (!(LookupPrivilegeValue(0, SE_DEBUG_NAME, &Luid))) ShowMessage("LookupPrivilegeValue");
   else
   {
        tpDebug.PrivilegeCount = 1;
        tpDebug.Privileges[0].Luid = Luid;
        tpDebug.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
   }
   if (!AdjustTokenPrivileges(hToken, FALSE, &tpDebug, sizeof(tpDebug), NULL, NULL)) ShowMessage("AdjustTokenPrivileges");
   if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))  ShowMessage(L"CreateEnvironmentBlock");


   //typedef BOOL (WINAPI *DLL_CreateProcessWithLogonElevatedWType)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPCWSTR, LPWSTR, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
   //typedef BOOL (WINAPI *DLL_CreateProcessElevatedAType)(LPCSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION);
   typedef BOOL (WINAPI *DLL_CreateProcessAsUserElevatedAType)(HANDLE, LPCSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION);
   HMODULE LibHandle = LoadLibrary("Elevate.dll");
   if (LibHandle != NULL)
   {
        //ShowMessage(1);
        //DLL_CreateProcessWithLogonElevatedWType CreateProcessWithLogonElevatedW = (DLL_CreateProcessWithLogonElevatedWType)GetProcAddress(LibHandle,"CreateProcessWithLogonElevatedW");
        //if(CreateProcessWithLogonElevatedW(Edit2->Text.c_str(),NULL,Edit3->Text.c_str(),NULL,Edit1->Text.c_str(),NULL,
        //CREATE_UNICODE_ENVIRONMENT,lpvEnv,NULL, &si, &pi))  ShowMessage("OK");

        //DLL_CreateProcessElevatedAType CreateProcessElevatedA = (DLL_CreateProcessElevatedAType)GetProcAddress(LibHandle,"CreateProcessElevatedA");
        //if(CreateProcessElevatedA(Edit1->Text.t_str() ,  NULL,NULL,NULL,FALSE, CREATE_UNICODE_ENVIRONMENT, lpvEnv,NULL, &si, &pi)) ShowMessage("OK");

        DLL_CreateProcessAsUserElevatedAType CreateProcessAsUserElevatedA = (DLL_CreateProcessAsUserElevatedAType)GetProcAddress(LibHandle,"CreateProcessAsUserElevatedA");
        CreateProcessAsUserElevatedA(hToken,Edit1->Text.t_str() , NULL,NULL,NULL,FALSE, CREATE_UNICODE_ENVIRONMENT, lpvEnv,NULL, &si, &pi);
   }
   FreeLibrary(LibHandle);
   CloseHandle(hToken);
   CloseHandle(hProcess);


Próbowalem z 3 funkcjami:
CreateProcessWithLogonElevatedW
CreateProcessAsUserElevatedA
CreateProcessElevatedA

Udalo sie uruchomic tylko poprawnie CreateProcessElevatedA. Przy pozostalych jest ok.10s oczekiwanie i zadany proces sie nie uruchamia.
Czy ktos wie gdzie robie blad? Albo jezeli nie ma bledu moze ktos probowal korzystac z tej biblioteki ""elevate.dll"?
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows 7Opera


Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 24 gości

cron