Windows API

BlitzMax Forums/BlitzMax Beginners Area/Windows API

I'm trying to get BlitzMax to call a Windows API function, without much success... Anyone can shed some light on what I need to do here?

Global SetSystemPowerState(fSuspend, fForce) "win32"

lib = LoadLibraryA ("kernel32.dll")
If lib
   SetSystemPowerState = GetProcAddress(lib, "SetSystemPowerStateA")
Else
   Print "Dead"; End
EndIf

SetSystemPowerState(0,0)


It compiles without error, but attempting to run it returns the error: Attempt to call uninitialized function pointer

Any help would be appreciated!

Strict

Extern "Win32"
	Function SetSystemPowerState(fSuspend, fForce)
End Extern

SetSystemPowerState(False, False)


??

Thanks!

<testing>

Well... It doesn't give any errors, but it also doesn't actually seem to *do* anything... even with the 'force' parameter in place, which is supposed to forcefully terminate any program holding up sleep/hibernation

Hm.

Global SetSystemPowerState:Int(fSuspend, fForce) "win32"
Global GetLastError:Int() "win32"


lib = LoadLibraryA ("kernel32.dll")
If lib
	SetSystemPowerState = GetProcAddress(lib, "SetSystemPowerState")
	GetLastError=GetProcAddress(lib, "GetLastError")

Else
   Print "Dead"; End
EndIf

SetSystemPowerState(False,False)
e=GetLastError()
Print e

ERROR_PRIVILEGE_NOT_HELD=1314!

do enjoy the windows api it is *such* a joy to use NOT!!! lol

You aren't trying to do such stuff with a regular user account are you?
System control calls only work with administration rights on real windows (XP SP2 and similar) as they are considered to be the same security level as system settings.

From MSDN...*SHUDDER*...
The calling process must have the SE_SHUTDOWN_NAME privilege. To enable the SE_SHUTDOWN_NAME privilege, use the AdjustTokenPrivileges function. For more information, see Changing Privileges in a Token.
...I haven't a clue what that means exactly, but have fun. ;o)

I spent a whole day yesterday trying to get some mouse hook (via Windows API) and dll code working in Delphi, what a stinker.

First off, thanks ChrisC - you answered a question I was about to ask. But another question...

Suppose you have more than one module that 'LoadLibraryA's the same dll.... is this wasteful or is the routine smart enough to use one copy?

it'll just use the same dll ;)

You aren't trying to do such stuff with a regular user account are you?


I also get the 1314 error when running as Administrator, so it looks like there is something weird going on indeed... I verified that the process in the taks manager's process list is running as 'administrator' indeed...

some more googling found others with similar issues, and supposedly "the caller requires the SE_SHUTDOWN_NAME privilege", whatever that means...
Supposedly there's a call for AdjustTokenPrivileges that needs to be invoked, but I have absolutely no idea on how to translate that to blitzmax...

I found some visual basic code that does it here:
http://www.vbaccelerator.com/home/VB/Tips/How_to_Shutdown_the_System_in_Windows_9x_and_NT/article.asp

but the syntax is very different from BlitzMax's API stuff and I haven't been able to get anything workable out of it. Anyone else has any idea on how to convert this?

All I'm trying to do is to programatically put my computer in Hibernation mode, but not having a whole lot of luck so far...

Had a go here but I'm getting a failure at OpenProcessToken() call in the EnableShutDown() function.
I'm not sure if GetCurrentProcess() is causing the problem here. I always get -1 as the return value.

See if this works for you:
Strict
Framework BRL.Blitz

' =========================================================================
Extern "Win32"
	Function LoadLibraryA(lib$z)
	Function GetProcAddress:Byte Ptr(lib%,fname$z)
	Function SetSystemPowerState(fSuspend%,fForce%)
	Function ExitWindowsEx(uFlags%,dwReserved%=0)
	Function GetCurrentProcess%()
	Function CloseHandle(hObject%)
End Extern

Global OpenProcessToken%(ProcessHandle%,DesiredAccess%,TokenHandle%) "Win32"
Global LookupPrivilegeValue%(lpSystemName$z,lpName$z,lpLuid:Byte Ptr) "Win32"
Global AdjustTokenPrivileges%(TokenHandle%,DisableAllPrivileges%, NewState:Byte Ptr,BufferLength%,PreviousState:Byte Ptr,ReturnLength%) "Win32"

Local lib%=LoadLibraryA ("advapi32.dll")
If lib
	OpenProcessToken = GetProcAddress(lib, "OpenProcessToken")
	LookupPrivilegeValue = GetProcAddress(lib, "LookupPrivilegeValueA")
	AdjustTokenPrivileges = GetProcAddress(lib, "AdjustTokenPrivileges")
Else
	RuntimeError "Unable to open ADVAPI32.DLL"
EndIf
' =========================================================================


Type LUID
    Field LowPart%
    Field HighPart%
End Type
Type LUID_AND_ATTRIBUTES
    Field pLuid:LUID=New LUID
    Field Attributes%
End Type
Type TOKEN_PRIVILEGES
    Field PrivilegeCount%
    Field Privileges:LUID_AND_ATTRIBUTES=New LUID_AND_ATTRIBUTES
End Type

Const ANYSIZE_ARRAY = $1
Const TOKEN_ADJUST_PRIVILEGES = $20
Const TOKEN_QUERY = $8
Const SE_PRIVILEGE_ENABLED = $2

Const EWX_LOGOFF = 0 
Const EWX_SHUTDOWN = $1 
Const EWX_REBOOT = $2 
Const EWX_FORCE = $4 
Const EWX_POWEROFF = $8 
Const EWX_FORCEIFHUNG = $10 ' NT5 only 
Const EWX_RESET = EWX_LOGOFF | EWX_FORCE | EWX_REBOOT 


' =========================================================================

' Enable shutdown privilege for the current application
Function EnableShutDown()
	Local hToken%
	Local nLuid:LUID=New LUID
	Local mPriv:TOKEN_PRIVILEGES=New TOKEN_PRIVILEGES
	Local mNewPriv:TOKEN_PRIVILEGES=New TOKEN_PRIVILEGES
	DebugLog LookupPrivilegeValue("", "SeShutdownPrivilege", Byte Ptr(nLuid))
	Local hProc% = GetCurrentProcess()
	DebugLog hproc
	DebugLog OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, hToken)
	DebugLog hToken
	mPriv.PrivilegeCount = 1
	mPriv.Privileges.pLuid.LowPart = nLuid.LowPart
	mPriv.Privileges.pLuid.HighPart = nLuid.HighPart
	mPriv.Privileges.Attributes = SE_PRIVILEGE_ENABLED
	DebugLog AdjustTokenPrivileges(hToken, 0, Byte Ptr(mNewPriv), SizeOf mNewPriv, Byte Ptr(mPriv), SizeOf mPriv)
	'CloseHandle hToken ' not needed for pseudo handles
End Function

' =========================================================================

' TEST

EnableShutDown
SetSystemPowerState False, False
'ExitWindowsEx EWX_POWEROFF


Still no go... No errors, yet nothing happens.

Strict

Framework brl.blitz
Import "-lkernel32"
Import "-ladvapi32"

Extern "Win32"
  'advapi32
  Function OpenProcessToken(ProcessHandle, DesiredAccess, TokenHandle:Byte Ptr)
  Function LookupPrivilegeValue(lpSystemName$z, lpName$z, lpLuid:Byte Ptr) = "LookupPrivilegeValueA@12"
  Function AdjustTokenPrivileges(TokenHandle, DisableAllPrivileges, NewState:Byte Ptr,..
                                BufferLength, PreviousState:Byte Ptr, ReturnLength:Byte Ptr)
  'kernel32
  Function GetCurrentProcess()
  Function SetSystemPowerState(fSuspend, fForce)
  Function GetLastError()                               
End Extern

Const TOKEN_ADJUST_PRIVILEGES = $20
Const TOKEN_QUERY = $8
Const SE_PRIVILEGE_ENABLED = $2


StandBy() ' Bye Bye

End


Function StandBy()
  Local tokenPrivilege[4]
  
  If LookupPrivilegeValue(Null, "SeShutdownPrivilege", Byte Ptr(tokenPrivilege) + 4) = 0
    DebugLog "LookupPrivilegeValue error : " + GetLastError()
    Return
  EndIf
  
  Local hProc = GetCurrentProcess() ' -1
  Local hToken
  
  If OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, Varptr(hToken)) = 0
    DebugLog "OpenProcessToken error : " + GetLastError()
    Return
  EndIf
  
  tokenPrivilege[0] = 1
  tokenPrivilege[3] = SE_PRIVILEGE_ENABLED
    
  If AdjustTokenPrivileges(hToken, False, Byte Ptr(tokenPrivilege), Null, Null, Null) = 0
    DebugLog "AdjustTokenPrivileges error : " + GetLastError()
    Return
  EndIf
  
  If SetSystemPowerState(True, False) = 0
    DebugLog "SetSystemPowerState error : " + GetLastError()
    Return
  EndIf
End Function


Fantastic! Looks like that did the trick.

Thank you so much.

Good work Yan. Works on my system.

I've created a set of functions and a GUI test window to try them out.

Functions:

Standby [flag]
Hibernate [flag]
Shutdown [flag]
Restart [flag]
LogOff [flag]

If optional flag is TRUE all programs are forced to close



GUI Test Window
SuperStrict

Framework BRL.Win32MaxGui

Import "Shutdown.bmx"

Global win:TGadget=CreateWindow("ShutDown Test",200,40,206,122,Null,WINDOW_TITLEBAR)
Global combo:TGadget=CreateComboBox(20,32,80,20,win)
AddGadgetItem combo,"Standby"
AddGadgetItem combo,"Log Off"
AddGadgetItem combo,"Hibernate"
AddGadgetItem combo,"Shutdown"
AddGadgetItem combo,"Restart"
SelectGadgetItem combo,0
Global btn:TGadget=CreateButton("Do it",128,32,50,22,win,1)
Global forcebtn:TGadget=CreateButton("Force other programs to close",20,68,180,24,win,BUTTON_CHECKBOX)

'-mainloop--------------------------------------------------------------

Repeat
	Select WaitEvent()
		Case EVENT_GADGETACTION
		If EventSource()=btn
			Select SelectedGadgetItem(combo)
				Case 0 ; Standby ButtonState(forcebtn)
				Case 1 ; LogOff ButtonState(forcebtn)
				Case 2 ; Hibernate ButtonState(forcebtn)
				Case 3 ; Shutdown ButtonState(forcebtn)
				Case 4 ; Restart ButtonState(forcebtn)
			End Select
		EndIf
		Case EVENT_WINDOWCLOSE
		Exit
	End Select
Forever


Shutdown Functions - Shutdown.bmx
Rem
	ShutDown functions
   ____________________________
	Standby [flag]
	Hibernate [flag]
	Shutdown [flag]
	Restart [flag]
	LogOff [flag]
	
	If optional flag is TRUE all programs are forced to close
EndRem


Strict

Import brl.retro
Import "-lkernel32"
Import "-ladvapi32"

Extern "Win32"
	'advapi32
	Function OpenProcessToken(ProcessHandle, DesiredAccess, TokenHandle:Byte Ptr)
	Function LookupPrivilegeValue(lpSystemName$z, lpName$z, lpLuid:Byte Ptr) = "LookupPrivilegeValueA@12"
	Function AdjustTokenPrivileges(TokenHandle, DisableAllPrivileges, NewState:Byte Ptr,..
		BufferLength, PreviousState:Byte Ptr, ReturnLength:Byte Ptr)
	'kernel32
	Function GetVersion()
	Function GetCurrentProcess()
	Function SetSystemPowerState(fSuspend, fForce)
	Function ExitWindowsEx(uFlags%,dwReserved%=0)
	Function GetLastError()                               
End Extern

Function Standby(forced%=False)
	If EnableShutdownPrivileges()
		SetSystemPowerState(True, forced)
	EndIf
End Function

Function Hibernate(forced%=False)
	If EnableShutdownPrivileges()
		SetSystemPowerState(False, forced)
	EndIf	
End Function

Function Shutdown(forced%=False)
	If EnableShutdownPrivileges()
		ExitWindowsEx $8 | $4 * forced
	EndIf
End Function

Function Restart(forced%=False)
	If EnableShutdownPrivileges()
		ExitWindowsEx $2 | $4 * forced
	EndIf
End Function

Function LogOff(forced%=False)
	If EnableShutdownPrivileges()
		ExitWindowsEx $0 | $4 * forced
	EndIf
End Function

Function EnableShutdownPrivileges%()
	Const TOKEN_ADJUST_PRIVILEGES% = $20
	Const TOKEN_QUERY% = $8
	Const SE_PRIVILEGE_ENABLED% = $2
	Local tokenPrivilege%[4]
	If LookupPrivilegeValue(Null, "SeShutdownPrivilege", Byte Ptr(tokenPrivilege)+4)
		Local hProc% = GetCurrentProcess() ' -1
		Local hToken%
		If OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, Varptr(hToken))
			tokenPrivilege[0] = 1
			tokenPrivilege[3] = SE_PRIVILEGE_ENABLED
			If AdjustTokenPrivileges(hToken, False, Byte Ptr(tokenPrivilege), Null, Null, Null)
				Return True
			EndIf
		EndIf
	EndIf
End Function