$Include "RapidQ.inc"
$TypeCheck on
Type LUID
LowPart As Long
HighPart As Long
End Type

Type LUID_AND_ATTRIBUTES
' pLuid As LUID
LowPart as Long
HightPart as Long
Attributes As Long
End Type

Type TOKEN_PRIVILEGES
PrivilegeCount As Long
' Privileges(1) As LUID_AND_ATTRIBUTES
LowPart as long
HighPart as long
Attributes as long
End Type

Declare Function ExitWindowsEx Lib "user32" Alias "ExitWindowsEx" _
(uFlags As Long, _
dwReserved As Long) As Long

Declare Function GetCurrentProcess Lib "kernel32" Alias "GetCurrentProcess"() As Long 

Declare Function OpenProcessToken Lib "advapi32" Alias "OpenProcessToken" _
(ProcessHandle As Long, _
DesiredAccess As Long, _
TokenHandle As Long) As Long

Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" _
(lpSystemName As String, _
lpName As String, _
lpLuid As LUID) As Long

Declare Function AdjustTokenPrivileges Lib "advapi32" Alias "AdjustTokenPrivileges" _
(TokenHandle As Long, _
DisableAllPrivileges As Long, _
NewState As TOKEN_PRIVILEGES, _
BufferLength As Long, _
PreviousState As TOKEN_PRIVILEGES, _
ReturnLength As Long) As Long

Const EWX_LOGOFF = 0
Const EWX_SHUTDOWN = 1
Const EWX_REBOOT = 2
Const EWX_FORCE = 4
Const TOKEN_ADJUST_PRIVILEGES = &H20
Const TOKEN_QUERY = &H8
Const SE_PRIVILEGE_ENABLED = &H2


' Copy and paste into your program
DECLARE SUB Button1Click (Sender AS QBUTTON)
DECLARE SUB SetShutDownPrivilege()

CREATE Form AS QFORM
Caption = "Form1"
Width = 320
Height = 240
Center
CREATE ComboBox1 AS QCOMBOBOX
Text = "ComboBox1"
Left = 16
Top = 72
AddItems "Shutdown", "Reboot", "Forced Shutdown", "Logoff"
ItemIndex = 0
END CREATE
CREATE Button1 AS QBUTTON
Caption = "Button1"
Left = 184
Top = 72
TabOrder = 1
OnClick = Button1Click
END CREATE
END CREATE

'Insert your initialization code here
Dim Phndl As Long

Form.ShowModal

'--------- Subroutines ---------

SUB Button1Click (Sender AS QBUTTON)
Dim MyFlag As Long, Ret As Long
' Always execute a force shutdown if a shutdown is required
If ComboBox1.Item(ComboBox1.ItemIndex) = "Shutdown" Then MyFlag = EWX_FORCE
If ComboBox1.Item(ComboBox1.ItemIndex) = "Forced Shutdown" Then MyFlag = EWX_FORCE
If ComboBox1.Item(ComboBox1.ItemIndex) = "Logoff" Then MyFlag = EWX_LOGOFF
If ComboBox1.Item(ComboBox1.ItemIndex) = "Reboot" Then MyFlag = EWX_REBOOT
' Grab the shutdown privilege - else reboot will fail
SetShutDownPrivilege
' Do the required action
Ret = ExitWindowsEx(EWX_FORCE Or EWX_LOGOFF Or EWX_SHUTDOWN Or EWX_REBOOT, 0)
Form.Caption = "RC = " + str$(Ret)
End Sub

Sub SetShutDownPrivilege()
Dim Thndl As Long
Dim MyLUID As LUID
Dim MyPriv As TOKEN_PRIVILEGES, MyNewPriv As TOKEN_PRIVILEGES
Dim ret as long
Phndl = GetCurrentProcess()' <-------------Dont return valid handle
ShowMessage STR$(Phndl)
SHowmessage str$( Application.handle)
ret = OpenProcessToken(Phndl, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, @Thndl)
SHowmessage str$( ret)
ret = LookupPrivilegeValue("", "SeShutdownPrivilege", MyLUID)
SHowmessage str$( ret)
MyPriv.PrivilegeCount = 1
MyPriv.Attributes = SE_PRIVILEGE_ENABLED
MyPriv.LowPart = MyLUID.LowPart
MyPriv.HighPart = MyLUID.HighPart
' Now to set shutdown privilege for my app
DIM pdword as integer
pdword =  4 + (12 * MyNewPriv.PrivilegeCount)
ret = AdjustTokenPrivileges(Thndl, False, MyPriv, 4 + (12 * MyPriv.PrivilegeCount), MyNewPriv,@pdword)' 4 + (12 * MyNewPriv.PrivilegeCount))
SHowmessage str$( ret)
End Sub

