Solved

ExitWindowsEx API doesn't work from inside a DLL

Posted on 2006-07-19
6
479 Views
Last Modified: 2013-11-13
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("ServerServices.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(hProcessHandle, (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hTokenHandle) <> 0 Then
         If LookupPrivilegeValue(vbNullString, "SeShutdownPrivilege", lpv_la) <> 0 Then
            With token
               .PrivilegeCount = 1
               .laa.udtLUID = lpv_la
               .laa.dwAttributes = SE_PRIVILEGE_ENABLED
            End With
            If AdjustTokenPrivileges(hTokenHandle, 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)....




---------------------------------------------------------------------------------------------


0
Comment
Question by:Ugi_Fletzet
  • 3
  • 2
6 Comments
 
LVL 41

Accepted Solution

by:
graye earned 300 total points
ID: 17205627
I assume you've adjusted the impersonation of that section of the web page to take on the rights of the logged on user (who would have to be an administrator)?

Just a note... The security associated with the IIS accounts are specifically desgined to reduce the risk of an intrusion and therefore have the "least privileges" required to function.  That means they probably don't have the appropriate authority/permissions to perform a shutdown.



0
 

Author Comment

by:Ugi_Fletzet
ID: 17257942
As an intra-net application, I've adjusted the impersonation of that section of the web page to take on the rights of the server administrator which has full rights and not IUSR_xxx (IIS default user, xxx is the computer name) which has very few rights...

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)
0
 
LVL 41

Expert Comment

by:graye
ID: 17259169
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_OperatingSystem")
        For Each obj In wmi.GetInstances()

            ' Get an input parameters object for this method
            inParams = obj.GetMethodParameters("Win32Shutdown")

            ' fill 'em in
            inParams("Flags") = Flag
            inParams("Reserved") = 0

            ' do it!
            outParams = obj.InvokeMethod("Win32Shutdown", inParams, Nothing)
            Result = Convert.ToInt32(outParams("returnValue"))
            If Result <> 0 Then
                Throw New System.ComponentModel.Win32Exception(Result)
            End If
        Next
    End Sub
End Class
0
 

Author Comment

by:Ugi_Fletzet
ID: 17259420
Thank you Graye, I'll try that and return to you later (It might taks some time...)
0
 

Author Comment

by:Ugi_Fletzet
ID: 17404944
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.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
bunnyEars challenge 6 64
noX challenge 17 76
endX challenge 2 50
mapAB Challlenge 35 88
Displaying an arrayList in a listView using the default adapter is rarely the best solution. To get full control of your display data, and to be able to refresh it after editing, requires the use of a custom adapter.
Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now