?
Hi,
bin ein kleines Stück weiter gekommen.
Man benötigt zum runterfahren spezielle Rechte.
Nach ein wenig googeln hab ich auch ein pa lösungen gefunden.
Leider funktioniert das nicht ganz so wie es soll.
//Header
#pragma once
using namespace System;
public __gc class WinExit
{
public:
static __value enum ExitOptions
{
LogOff = 0,
PowerOff = 8,
Reboot = 2,
ShutDown = 1,
Suspend = -1,
Hibernate = -2
};
[System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential, Pack=4)]
static __value struct LUID_AND_ATTRIBUTES
{
long Luid;
int Attributes;
};
[System::Runtime::InteropServices::StructLayout (System::Runtime::InteropServices::LayoutKind::Sequential, Pack = 4)]
static __value struct TOKEN_PRIVILEGES // tp
{
int PrivilegeCount;
// Statt des zweite Elements:
// LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
// setze ich die Definition der Struktur LUID_AND_ATTRIBUTES direkt ein,
// da ANYSIZE_ARRAY = 1
long Luid;
int Attributes;
//LUID_AND_ATTRIBUTES LuidAndAttributes;
};
private:
static int SE_PRIVILEGE_ENABLED = 0x00000002;
static int TOKEN_QUERY = 0x0008;
static int TOKEN_ADJUST_PRIVILEGES = 0x0020;
static String* SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
ExitOptions m_ExitOption;
bool m_force;
System::Threading::Timer* pTimer;
private:
//========================================================================
[System::Runtime::InteropServices::DllImport("User32")]
static int ExitWindowsEx(int uFlags, int dwReserved);
//========================================================================
//[System::Runtime::InteropServices::DllImport("kernel32.dll")]
//static IntPtr GetCurrentProcess();//error C3385: 'WinExit::GetCurrentProcess':
//Eine Funktion, die ein DllImport benutzerdefiniertes
//Attribut hat, kann keine Instanz einer Klasse zurückgeben
//========================================================================
[System::Runtime::InteropServices::DllImport("advapi32.dll")]
static bool LookupPrivilegeValue (
String* lpSystemName, // address of string specifying the system
String* lpName, // address of string specifying the privilege
long &lpLuid // address of locally unique identifier
);
//========================================================================
[System::Runtime::InteropServices::DllImport ("advapi32.dll")]
static bool OpenProcessToken (
IntPtr hProcess, // handle of process
int dwAccessMask, // desired access to process
IntPtr &phToken // address of handle of open access token
);
//========================================================================
[System::Runtime::InteropServices::DllImport ("advapi32.dll")]
static bool AdjustTokenPrivileges (
IntPtr hTokenHandle, // handle of token that contains privileges
bool fDisableAllPrivileges, // flag for disabling all privileges
TOKEN_PRIVILEGES &NewState, // address of new privilege information
int dwBufferLength, // size of previous information buffer
// Eigentlich kommt jetzt
//TOKEN_PRIVILEGES &PreviousState, // address of previous information
//int &pdwReturnLength // address of required buffer size
// Aber das wir für beides NULL übergeben wollen, schreiben wir stattdessen
IntPtr PreviousState, // address of previous information
IntPtr pdwReturnLength // address of required buffer size
);
//========================================================================
void ExitWindows(System::Object* sender);
bool SetPrevileges();
public:
WinExit(void);
~WinExit(void);
void ExitWindows(ExitOptions how, bool force);
void ExitWindows(ExitOptions how, bool force,int WaitTime);
};
...
//CPP
#include "StdAfx.h"
#include ".\winexit.h"
#using <mscorlib.dll>
using namespace System;
using namespace System::Diagnostics;
WinExit::WinExit(void)
{
this->pTimer = new System::Threading::Timer(new System::Threading::TimerCallback(this,WinExit::ExitWindows),this,-1,0);
}
//-----------------------------------------------------------------------------------------------
WinExit::~WinExit(void)
{
this->pTimer = NULL;
}
//-----------------------------------------------------------------------------------------------
void WinExit::ExitWindows(ExitOptions how, bool force)
{
//if(how != ExitOptions::LogOff)
// this->SetPrevileges();
int EWX_FORCE = 4;
int ioption = System::Convert::ToInt32(how);
if(force)
{
ioption = ioption | EWX_FORCE;
}
int iOK = WinExit::ExitWindowsEx(ioption,NULL);
if(!iOK)
System::Windows::Forms::MessageBox::Show(Convert::ToString(System::Runtime::InteropServices::Marshal::GetLastWin32Error()));
//System::Windows::Forms::MessageBox::Show(S"Fehler ExitWindowsEX.");
if(this->pTimer)
this->pTimer->Change(-1,0);
this->pTimer = NULL;
}
bool WinExit::SetPrevileges()
{
bool bOK = false;
IntPtr hToken = IntPtr::Zero;
bOK = OpenProcessToken(System::Diagnostics::Process::GetCurrentProcess()->Handle,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,hToken);
if(!bOK)
System::Windows::Forms::MessageBox::Show(S"Fehler OpenProcessToken");
long luid;
bOK = LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, luid);
if(!bOK)
System::Windows::Forms::MessageBox::Show(S"Fehler OpenProcessToken");
WinExit::TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Luid = luid;
tp.Attributes = SE_PRIVILEGE_ENABLED;
bOK = AdjustTokenPrivileges (hToken, false, tp, 0, IntPtr::Zero, IntPtr::Zero);
if(!bOK)
System::Windows::Forms::MessageBox::Show(S"Fehler AdjustTokenPrivileges");
return bOK;
}
//-----------------------------------------------------------------------------------------------
void WinExit::ExitWindows(ExitOptions how, bool force,int WaitTime)
{
this->m_ExitOption = how;
this->m_force = force;
this->pTimer->Change(WaitTime,-1);
}
//-----------------------------------------------------------------------------------------------
void WinExit::ExitWindows(System::Object* sender)
{
this->ExitWindows(this->m_ExitOption, this->m_force);
}
//-----------------------------------------------------------------------------------------------
Die SetPrevileges() Funktion wird erfolgreich beenet. Aber die ExitWindowsEx() nicht.
Habe auch schon die Fehlercodes mit und ohne setzen der Privilegien verglichen. Die Werte sind verschieden. (127 und -1163005939)
Laut meinen Quellen (http://www.mycsharp.de/wbb2/thread.php?threadid=5379
und
http://www.mycsharp.de/wbb2/thread.php?threadid=1772)
soll das funktionieren, zumindest in C#.
Vieleicht hab ich nen Fehler bei der Umsetzung von C# zu Managed C++ gemacht?
Ich hoffe hier hat jemand mehr Ahnung von der Materie als ich.
Ich bin echt am Verzweifeln, ich glaub wenn das so weiter geht beiß ich noch ne Ecke aus meiner Tastatur!
GuenniAtWork