发信人: dark_hu() 
整理人: hunter__fox(2002-03-16 21:48:54), 站内信件
 | 
 
 
 *-- Winnt.h 中的定义   
 #DEFINE TOKEN_ADJUST_PRIVILEGES 0x0020   
 #DEFINE TOKEN_QUERY             0x0008   
 #DEFINE SE_PRIVILEGE_ENABLED    2   
    
 *-- Winbase.h 中的定义   
 #DEFINE VER_PLATFORM_WIN32s             0   
 #DEFINE VER_PLATFORM_WIN32_WINDOWS      1   
 #DEFINE VER_PLATFORM_WIN32_NT           2   
    
 *-- WinUser.h 中的定义   
 #DEFINE EWX_LOGOFF           0  && 调用 ExitWindowsEx 函数,   
                                 && 在安全相关进程下, 关闭所有运行的进程.   
                                 && 然后它登录用户离开.   
    
 #DEFINE EWX_SHUTDOWN         1  && 安全关闭电源. 所有文件缓存已经写入磁盘,   
                                 && 且所有运行着的进程被停止.   
    
                                 && Windows NT/2000: 调用进程必须具有 SE_SHUTDOWN_NAME   
                                 && 权限.   
    
 #DEFINE EWX_REBOOT           2  && 关闭并重启系统.   
    
                                 && Windows NT/2000: 调用进程必须具有 SE_SHUTDOWN_NAME   
                                 && 权限.   
    
 #DEFINE EWX_POWEROFF         8  && 关闭系统并关掉电源. 系统必须支持关电源功能.   
    
                                 && Windows NT/2000: 调用进程必须具有 SE_SHUTDOWN_NAME   
                                 && 权限.   
    
 *-- 修改 EWX_SHUTDOWN 到任何上面的 #define 值来注销, 关闭, 重启或关掉电源.   
 DO ExitWindowsFox WITH EWX_SHUTDOWN   
    
 *----------------------------------   
 PROCEDURE ExitWindowsFox   
 *----------------------------------   
     PARAMETERS ExitMode   
     LOCAL iRc   
     iRc = 0   
     DECLARE ExitWindowsEx IN Win32Api INTEGER, INTEGER   
    
     *-- 检查操作系统版本, 如果是 NT/Win2K 还要调用 SetPrivilege 函数   
     liPlatform = GetPlatform()   
     IF liPlatform != VER_PLATFORM_WIN32_NT  && 我们可以做我们想做的事   
                                                 && 而不用担心安全   
         iRc = ExitWindowsEx(ExitMode, 0)  
         IF ExitMode = EWX_LOGOFF OR ExitMode = EWX_POWEROFF   
    
             *-- 必须的, 因为在 Win9x 下任何一个这些参数 VFP 将不会退出.   
             QUIT   
         ENDIF   
     ELSE  && 我们必须设置进程安全   
         iRc = SetProcPrivilege()   
         IF iRc <> 0   
             iRc = ExitWindowsEx(ExitMode, 0)   
         ENDIF   
     ENDIF   
    
 *----------------------------------   
 PROCEDURE SetProcPrivilege   
 *-- 设置适当的进程特权来允许关闭 NT/Win2K   
 *----------------------------------   
 *-- 定义获取当前 Process ID, 需要打开进程来取得进程令牌.   
     LOCAL iRc   
     iRc = 0   
     DECLARE INTEGER GetCurrentProcessId IN kernel32.DLL   
     DECLARE INTEGER OpenProcess IN Kernel32.DLL INTEGER, ;   
         INTEGER, ;   
         INTEGER   
     DECLARE INTEGER OpenProcessToken IN AdvApi32.DLL INTEGER, ;   
         INTEGER, ;   
         INTEGER@   
    
     *-- 定义为必要的安全特权获取一个 LUID 的函数.   
     DECLARE INTEGER LookupPrivilegeValue IN AdvApi32.DLL STRING, ;   
         STRING, ;   
         INTEGER@ lsLuid   
    
     *-- 定义调整进程令牌特权的函数, 这样我们可以关闭 NT/Windows 2000   
     DECLARE INTEGER AdjustTokenPrivileges IN AdvApi32.DLL INTEGER, ;   
         INTEGER, ;   
         STRING@ lsNewState, ;   
         INTEGER, ;   
         INTEGER, ;   
         INTEGER   
    
     liAccessToken = 0        && 访问我们要改变特权的令牌的占位符   
     lsLuidBuffer = SPACE(8)  && 用于改变访问特权的 LUID 的占位符   
     lsName = SPACE(15)       && 计算机名字占位符   
     liBufferLen = 15         && 计算机名字缓存长度占位符   
     liLuid = 0   
     liProc = 0   
     liProc = GetCurrentProcessId()   
     hProc = OpenProcess(2035711, 0, liProc)   
     iRc = OpenProcessToken(hProc, BITOR(TOKEN_ADJUST_PRIVILEGES, TOKEN_QUERY), @liAccessToken)  
     IF iRc <> 0   
         IF iRc <> 0   
    
             *-- "SeShutdownPrivilege" 是 SE_SHUTDOWN_NAME 值的串值.   
             LookupPrivilegeValue("", "SeShutdownPrivilege", @liLuid)   
             lsLuidBuffer = LongToStr(liLuid) + CHR(0) + CHR(0) + CHR(0) + CHR(0)   
    
             *-- 定义一个串来保存 TOKEN_PRIVILEGES 结构   
             lsNewState = SPACE(16)   
    
             *-- 填充结构   
             lsNewState = LongToStr(1) + lsLuidBuffer + LongToStr(SE_PRIVILEGE_ENABLED)  
             iRc = AdjustTokenPrivileges(liAccessToken, 0, @lsNewState, LEN(lsNewState), 0, 0)   
             RETURN iRc   
         ELSE   
             RETURN iRc   
         ENDIF   
     ELSE   
         RETURN iRc   
     ENDIF   
 ENDPROC   
    
 *----------------------------------   
 PROCEDURE GetPlatform   
 *----------------------------------   
     LOCAL liPlatform, iRc   
     liPlatform = 0   
     iRc = 0   
    
     DECLARE INTEGER GetVersionEx IN Win32Api STRING@   
    
     *-- 定义保存 OSVERSIONINFO 结构的串   
     lsOSVersionInfo = LongToStr(148) + SPACE(144)   
     iRc = GetVersionEx(@lsOSVersionInfo)   
     liPlatform = StrToLong(SUBSTR(lsOSVersionInfo, 17, 4))   
     RETURN liPlatform   
 ENDPROC   
    
 *-- 以下函数转换长整型到一个代表传递值的低高格式的 ASCII 字符串.   
 *----------------------------------   
 FUNCTION LongToStr   
     *----------------------------------   
     * Passed : 32-bit non-negative numeric value (lnLongval)   
     * Returns : ascii character representation of passed value in low-high   
     * format (lcRetstr)   
     * Example :   
     *   m.long = "999999"   
     *   m.longstr = long2str(m.long)   
    
     PARAMETERS lnLongval   
    
     PRIVATE i, lcRetstr   
    
     lcRetstr = ""   
     FOR i = 24 TO 0 STEP -8   
         lcRetstr = CHR(INT(lnLongval/(2^i))) + lcRetstr   
         lnLongval = MOD(lnLongval, (2^i))   
     NEXT   
     RETURN lcRetstr   
    
     *-- 以下函数转换一个低高格式串为长整型.   
     *----------------------------------   
 FUNCTION StrToLong   
     *----------------------------------   
     * Passed:  4-byte character string (lcLongstr) in low-high ASCII format   
     * Returns:  long integer value   
     * Example:   
     * m.longstr = "1111"   
     * m.longval = str2long(m.longstr)   
    
     PARAMETERS lcLongstr   
    
     PRIVATE i, lnRetval   
    
     lnRetval = 0   
     FOR i = 0 TO 24 STEP 8   
         lnRetval = lnRetval + (ASC(lcLongstr) * (2^i))   
         lcLongstr = RIGHT(lcLongstr, LEN(lcLongstr) - 1)   
     NEXT   
    
     RETURN lnRetval  | 
 
 
 |