nochmal zum Thema Software-Runterfahren:
Windows mag es auf dauer gar nicht, wenn man ihm einfach den Saft abdreht, selbst dann, wenn nichts mehr läuft sind oft noch Änderungen des MFT (Master-File-Table) im RAM statt auf der Platte; das kann auf Dauer zu Problemen führen. Per Software ist sicherlich der gesündere Weg.
Man kann ja eigentlich auch die POWER-LED oder den POWER_ON anschluss zum Netzteil überwachen: dann weiss die C-Control, was das Glöckchen geschlagen hat und kann zur Not doch noch den großen Entsafter spielen.

Win9X und Win2k sind nebenbei ein klein bisschen unterschiedlich, was den Power-Down angeht:
Unter win 95, 98 Me sieht das so aus:
Code:
Declare Function ExitWindowsEx& Lib "user32" (ByVal uFlags As Long, _
                                              ByVal dwReserved As Long)

Public Const EWX_FORCE = 4
Public Const EWX_LOGOFF = 0
Public Const EWX_REBOOT = 2
Public Const EWX_SHUTDOWN = 1

Private Sub cmdShutdown_Click()

Dim MsgRes As Long

'Make sure that the user really want to shutdown
MsgRes = MsgBox("Are you sure you want to Shut Down Windows 95?", vbYesNo Or vbQuestion)

'If the user selects no, exit this sub
If MsgRes = vbNo Then Exit Sub

'else, shutdown windows and unload this form
Call ExitWindowsEx(EWX_SHUTDOWN, 0)
Unter 2000 und XP so:

Code:
Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Boolean, ByRef NewState As typTOKEN_PRIVILEGES, ByVal BufferLength As Long, ByRef PreviousState As typTOKEN_PRIVILEGES, ByRef ReturnLength As Long) As Boolean
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, ByRef TokenHandle As Long) As Boolean
Private Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, ByRef lpLuid As typLUID) As Boolean
Private Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Const TOKEN_QUERY As Long = &H8
Private Const TOKEN_ADJUST_PRIVILEGES As Long = &H20
Private Const SE_SHUTDOWN_NAME = "SeShutdownPrivilege"
Private Const SE_PRIVILEGE_ENABLED As Long = &H2

Private Const EWX_LOGOFF As Long = 0
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

Private Type typLUID
    LowPart As Long
    HighPart As Long
End Type

Private Type typLUID_AND_ATTRIBUTES
    pLuid As typLUID
    Attributes As Long
End Type

Private Type typTOKEN_PRIVILEGES
    PrivilegeCount As Long
    Privileges(64) As typLUID_AND_ATTRIBUTES
End Type

        If OpenProcessToken(GetCurrentProcess(), (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hTokenHandle) Then
            If LookupPrivilegeValue(vbNullString, SE_SHUTDOWN_NAME, tmpLuid) Then
        
                With tkpNewState
                    ' Ok we can now adjust the shutdown priviledges:
                    .PrivilegeCount = 1
                    With .Privileges(0)
                        .Attributes = SE_PRIVILEGE_ENABLED
                        .pLuid.HighPart = tmpLuid.HighPart
                        .pLuid.LowPart = tmpLuid.LowPart
                    End With '.privileges(0)
                End With 'tkpnewstate
        
                If AdjustTokenPrivileges(hTokenHandle, 0, tkpNewState, Len(tkpPreviousState), tkpPreviousState, lngBufferLen) Then
                    CloseHandle hTokenHandle
                    If ExitWindowsEx(Flags, &H0) Then
                        ShutDownMachine = True
                    End If
                End If
            End If
        End If