Ugi_Fletzet
asked on
ExitWindowsEx API doesn't work from inside a DLL
Hi experts,
My task was to create an ASP file that can restart Windows (on the server side ofcourse).
I wrote the code, but it doesn't restart. nothing happens.
To do that I wrote this piece of ASP code:
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------
<%
Set o = Server.CreateObject("Serve rServices. Restart")
o.RestartWindows
set o = nothing
%>
and here is my DLL (ServerServices.Restart which is registered well and has the proper permissions on the server)
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- -----
Option Explicit
Private Const TOKEN_ADJUST_PRIVILEGES As Long = &H20
Private Const TOKEN_QUERY As Long = &H8
Private Const SE_PRIVILEGE_ENABLED As Long = &H2
Private Const EWX_LOGOFF As Long = &H0
Private Const EWX_SHUTDOWN As Long = &H1
Private Const EWX_REBOOT As Long = &H2
Private Const EWX_FORCE As Long = &H4
Private Const EWX_POWEROFF As Long = &H8
Private Const EWX_FORCEIFHUNG As Long = &H10 '2000/XP only
Private Const VER_PLATFORM_WIN32_NT As Long = 2
Private Type OSVERSIONINFO
OSVSize As Long
dwVerMajor As Long
dwVerMinor As Long
dwBuildNumber As Long
PlatformID As Long
szCSDVersion As String * 128
End Type
Private Type LUID
dwLowPart As Long
dwHighPart As Long
End Type
Private Type LUID_AND_ATTRIBUTES
udtLUID As LUID
dwAttributes As Long
End Type
Private Type TOKEN_PRIVILEGES
PrivilegeCount As Long
laa As LUID_AND_ATTRIBUTES
End Type
Private Declare Function ExitWindowsEx Lib "user32" (ByVal dwOptions As Long, ByVal dwReserved As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As Any, ReturnLength As Long) As Long
Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
Public Sub RestartWindows()
Dim success As Long
If IsWinNTPlus() Then
success = EnableShutdownPrivledges()
If success Then ExitWindowsEx(EWX_REBOOT, 0&)
Else
RestartWindows = ExitWindowsEx(EWX_REBOOT, 0&)
End If
End Sub
Private Function IsWinNTPlus() As Boolean
#If Win32 Then
Dim OSV As OSVERSIONINFO
OSV.OSVSize = Len(OSV)
If GetVersionEx(OSV) = 1 Then
IsWinNTPlus = (OSV.PlatformID = VER_PLATFORM_WIN32_NT) And (OSV.dwVerMajor >= 4)
End If
#End If
End Function
Private Function EnableShutdownPrivledges() As Boolean
Dim hProcessHandle As Long
Dim hTokenHandle As Long
Dim lpv_la As LUID
Dim token As TOKEN_PRIVILEGES
hProcessHandle = GetCurrentProcess()
If hProcessHandle <> 0 Then
If OpenProcessToken(hProcessH andle, (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hTokenHandle) <> 0 Then
If LookupPrivilegeValue(vbNul lString, "SeShutdownPrivilege", lpv_la) <> 0 Then
With token
.PrivilegeCount = 1
.laa.udtLUID = lpv_la
.laa.dwAttributes = SE_PRIVILEGE_ENABLED
End With
If AdjustTokenPrivileges(hTok enHandle, False, token, ByVal 0&, ByVal 0&, ByVal 0&) <> 0 Then
EnableShutdownPrivledges = True
End If
End If
End If
End If
End Function
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------
I know for sure that the DLL works fine. however, when called by ASP from within a DLL - the ExitWindowsEX API returns '1' (Can't quit)....
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- -------
My task was to create an ASP file that can restart Windows (on the server side ofcourse).
I wrote the code, but it doesn't restart. nothing happens.
To do that I wrote this piece of ASP code:
--------------------------
<%
Set o = Server.CreateObject("Serve
o.RestartWindows
set o = nothing
%>
and here is my DLL (ServerServices.Restart which is registered well and has the proper permissions on the server)
--------------------------
Option Explicit
Private Const TOKEN_ADJUST_PRIVILEGES As Long = &H20
Private Const TOKEN_QUERY As Long = &H8
Private Const SE_PRIVILEGE_ENABLED As Long = &H2
Private Const EWX_LOGOFF As Long = &H0
Private Const EWX_SHUTDOWN As Long = &H1
Private Const EWX_REBOOT As Long = &H2
Private Const EWX_FORCE As Long = &H4
Private Const EWX_POWEROFF As Long = &H8
Private Const EWX_FORCEIFHUNG As Long = &H10 '2000/XP only
Private Const VER_PLATFORM_WIN32_NT As Long = 2
Private Type OSVERSIONINFO
OSVSize As Long
dwVerMajor As Long
dwVerMinor As Long
dwBuildNumber As Long
PlatformID As Long
szCSDVersion As String * 128
End Type
Private Type LUID
dwLowPart As Long
dwHighPart As Long
End Type
Private Type LUID_AND_ATTRIBUTES
udtLUID As LUID
dwAttributes As Long
End Type
Private Type TOKEN_PRIVILEGES
PrivilegeCount As Long
laa As LUID_AND_ATTRIBUTES
End Type
Private Declare Function ExitWindowsEx Lib "user32" (ByVal dwOptions As Long, ByVal dwReserved As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As Any, ReturnLength As Long) As Long
Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
Public Sub RestartWindows()
Dim success As Long
If IsWinNTPlus() Then
success = EnableShutdownPrivledges()
If success Then ExitWindowsEx(EWX_REBOOT, 0&)
Else
RestartWindows = ExitWindowsEx(EWX_REBOOT, 0&)
End If
End Sub
Private Function IsWinNTPlus() As Boolean
#If Win32 Then
Dim OSV As OSVERSIONINFO
OSV.OSVSize = Len(OSV)
If GetVersionEx(OSV) = 1 Then
IsWinNTPlus = (OSV.PlatformID = VER_PLATFORM_WIN32_NT) And (OSV.dwVerMajor >= 4)
End If
#End If
End Function
Private Function EnableShutdownPrivledges()
Dim hProcessHandle As Long
Dim hTokenHandle As Long
Dim lpv_la As LUID
Dim token As TOKEN_PRIVILEGES
hProcessHandle = GetCurrentProcess()
If hProcessHandle <> 0 Then
If OpenProcessToken(hProcessH
If LookupPrivilegeValue(vbNul
With token
.PrivilegeCount = 1
.laa.udtLUID = lpv_la
.laa.dwAttributes = SE_PRIVILEGE_ENABLED
End With
If AdjustTokenPrivileges(hTok
EnableShutdownPrivledges = True
End If
End If
End If
End If
End Function
--------------------------
I know for sure that the DLL works fine. however, when called by ASP from within a DLL - the ExitWindowsEX API returns '1' (Can't quit)....
--------------------------
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Hummm...
I don't have an answer, but I've got a suggestion!
You could try using Windows Management Instrumentation (WMI) instead of the APIs to reboot the server. Here is a sample:
' Add Reference to System.Management
Imports System.Management
'
' Use WMI's Win32Shutdown class to remotely logoff the user, reboot the PC, or
' shutdown the PC.
'
Public Class Actions
Public Enum ActionTypes As Integer
Logoff = 0
Reboot = 4
Shutdown = 8
End Enum
Public Sub DoAction(ByVal PC_Name As String, ByVal Flag As Integer, ByVal forced As Boolean)
Dim wmi As ManagementClass
Dim inParams, outParams As ManagementBaseObject
Dim obj As ManagementObject
Dim ans As Boolean
Dim Result As Integer
' force the action regardless of any activity on the remote PC
If forced = True Then
Flag += 4
End If
ans = True
wmi = New ManagementClass("\\" & PC_Name & "\root\cimv2:Win32_Operati ngSystem")
For Each obj In wmi.GetInstances()
' Get an input parameters object for this method
inParams = obj.GetMethodParameters("W in32Shutdo wn")
' fill 'em in
inParams("Flags") = Flag
inParams("Reserved") = 0
' do it!
outParams = obj.InvokeMethod("Win32Shu tdown", inParams, Nothing)
Result = Convert.ToInt32(outParams( "returnVal ue"))
If Result <> 0 Then
Throw New System.ComponentModel.Win3 2Exception (Result)
End If
Next
End Sub
End Class
I don't have an answer, but I've got a suggestion!
You could try using Windows Management Instrumentation (WMI) instead of the APIs to reboot the server. Here is a sample:
' Add Reference to System.Management
Imports System.Management
'
' Use WMI's Win32Shutdown class to remotely logoff the user, reboot the PC, or
' shutdown the PC.
'
Public Class Actions
Public Enum ActionTypes As Integer
Logoff = 0
Reboot = 4
Shutdown = 8
End Enum
Public Sub DoAction(ByVal PC_Name As String, ByVal Flag As Integer, ByVal forced As Boolean)
Dim wmi As ManagementClass
Dim inParams, outParams As ManagementBaseObject
Dim obj As ManagementObject
Dim ans As Boolean
Dim Result As Integer
' force the action regardless of any activity on the remote PC
If forced = True Then
Flag += 4
End If
ans = True
wmi = New ManagementClass("\\" & PC_Name & "\root\cimv2:Win32_Operati
For Each obj In wmi.GetInstances()
' Get an input parameters object for this method
inParams = obj.GetMethodParameters("W
' fill 'em in
inParams("Flags") = Flag
inParams("Reserved") = 0
' do it!
outParams = obj.InvokeMethod("Win32Shu
Result = Convert.ToInt32(outParams(
If Result <> 0 Then
Throw New System.ComponentModel.Win3
End If
Next
End Sub
End Class
ASKER
Thank you Graye, I'll try that and return to you later (It might taks some time...)
ASKER
Sorry for the delay, as I said - it might taks some time.
I tried the WMI way, but it still doesn't work. My guess - it's a special Windows protection, and the answer to my question should be: You're unable to accomplish the task under ASP....
Anyway - I'm giving graye the points, as he was the only one to help...
If someone will ever heard of a way to restart Windows with ASP, or if someone will come across a sample or just even a rumor of someone that did it - I'll appriciate any help.,,
Venabili - You can remove your comment.
I tried the WMI way, but it still doesn't work. My guess - it's a special Windows protection, and the answer to my question should be: You're unable to accomplish the task under ASP....
Anyway - I'm giving graye the points, as he was the only one to help...
If someone will ever heard of a way to restart Windows with ASP, or if someone will come across a sample or just even a rumor of someone that did it - I'll appriciate any help.,,
Venabili - You can remove your comment.
ASKER
Does anyone ever try to do it / heard of someone who did it / know that there is a way to do it / know of an example / what ever...
It looks like a simple & essential task - the aility to restart your server with ASP code called a DLL (ActiveX control)