I faced this same problem in making my own OS. Using information I found on Toshihiro Horie's website, I made these routines to do the job:
DEFINT A-Z
SUB APMGetVer(vMajor, vMinor, APMState)
'returns Advanced Power Management BIOS version
rAX = 0
rCX = 0
!mov ax, &h5300
!mov bx, &h0
!int &h15
!mov rAX, ax
!mov rCX, cx
vMajor = rAX \ 256
vMinor = rAX AND 255
IF rCX AND 8 THEN
APMState = 0
ELSE
APMState = 1
END IF
END SUB
DEFINT A-Z
SUB APMActivate (activateFlag)
'enables APM for everything controlled by the APM BIOS
'to enable APM, activateFlag = 1
'to disable APM, activateFlag = 0
af = 0
rAX = 0
!mov ax, &h530D
!mov bx, &h01
!mov cx, af
!int &h15
!mov rAX, ax
errorFlag = rAX \ 256
select case errorFlag
CASE 1:sysErr = &h21C:error 1
CASE 3:sysErr = &h21E:error 1
CASE 9:sysErr = &h221:error 1
CASE &h0A:sysErr = &h222:error 1
end select
END SUB
DEFINT A-Z
SUB APMShutdown
rAX = 0
!mov ax, &h5301
!mov bx, &h0
!int &h15
!mov rAX, ax
SELECT CASE rAX \ 256
CASE 2:sysErr = &h21D:error 1
CASE 5:sysErr = &h21F:error 1
CASE 7:sysErr = &h220:error 1
CASE 9:sysErr = &h221:error 1
CASE &h86:sysErr = &h223:error 1
END SELECT
!mov ax, &h530E
!mov bx, &h00
!mov cx, &h102
!int &h15
'SET POWER STATE OF ALL DEVICES TO OFF...
!mov ax, &h5307
!mov bx, &h01
!mov cx, &h03
!int &h15
END SUB
You would need to execute these routines in the order they're listed. First, determine if the APM BIOS is available, then activate it, then shut everything down. This has worked on every machine I've tried it on so far. In case you're wondering about the lines beginning with "!", this code is in a language called PowerBASIC, which allows the mixing of assembly and traditional BASIC code in one file. Also keep in mind, there's no way to do this under Windows XP and later since Windows traps and stops all direct runs at the hardware. Instead, it just terminates your program.
Hope this helps :)
Mercury0x000D