16 ビットでのシャットダウン処理サンプル
このコードは、Win16 と Win32 の双方で利用できるシャットダウンコードです。さらに Win16 下では、実際に実行している OS のバージョンで場合分けを行っています。
※ Win16 環境では必ず thunk16.lib (→ ここに詳細) をインポートしてください。
※ 自分のアプリケーションのコードをそのまま持ってきたため、コメントなどが一部そのままだったり、説明が無い部分もあります。
色分け: Win16 (16 ビット)用、Win32 (32 ビット)用
ヘッダー
#ifndef _WIN32 #define _WIN16 #endif // 独自のシャットダウン フラグ (SDF_FORCE のみ組み合わせ可) #define SDF_LOGOFF 1 #define SDF_REBOOT 2 #define SDF_SYSREBOOT 3 #define SDF_SHUTDOWN 4 #define SDF_POWEROFF 5 #define SDF_FORCE 0x10 #ifdef _WIN16 #ifndef WINAPIV #define WINAPIV CDECL #endif extern "C" { DWORD FAR PASCAL LoadLibraryEx32W(LPCSTR lpszLibFile, DWORD hFile, DWORD dwFlags); DWORD FAR PASCAL GetProcAddress32W(DWORD hModule, LPCSTR lpszProc); DWORD FAR PASCAL FreeLibrary32W(DWORD hLibModule); DWORD FAR WINAPIV CallProcEx32W(DWORD nParams, DWORD fAddressConvert, DWORD lpProcAddress, ... ); DWORD FAR PASCAL GetVDMPointer32W(LPVOID lpPointer, UINT fMode); } #define SE_PRIVILEGE_ENABLED_BY_DEFAULT (0x00000001L) #define SE_PRIVILEGE_ENABLED (0x00000002L) #define SE_PRIVILEGE_USED_FOR_ACCESS (0x80000000L) #ifndef TEXT #define TEXT(x) (x) #endif #define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege") #define TOKEN_ASSIGN_PRIMARY (0x0001) #define TOKEN_DUPLICATE (0x0002) #define TOKEN_IMPERSONATE (0x0004) #define TOKEN_QUERY (0x0008) #define TOKEN_QUERY_SOURCE (0x0010) #define TOKEN_ADJUST_PRIVILEGES (0x0020) #define TOKEN_ADJUST_GROUPS (0x0040) #define TOKEN_ADJUST_DEFAULT (0x0080) #define TOKEN_ADJUST_SESSIONID (0x0100) #define ANYSIZE_ARRAY_32 1 typedef struct _LUID { DWORD LowPart; LONG HighPart; } LUID, *PLUID; // #pragma pack(push, 4) #include <pshpack4.h> typedef struct _LUID_AND_ATTRIBUTES { LUID Luid; DWORD Attributes; } LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES; typedef LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES_ARRAY[ANYSIZE_ARRAY_32]; typedef LUID_AND_ATTRIBUTES_ARRAY *PLUID_AND_ATTRIBUTES_ARRAY; // #pragma pack(pop) #include <poppack.h> typedef struct _TOKEN_PRIVILEGES { DWORD PrivilegeCount; LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY_32]; } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES; #ifndef ERROR_SUCCESS #define ERROR_SUCCESS 0L #endif #ifndef ERROR_CALL_NOT_IMPLEMENTED #define ERROR_CALL_NOT_IMPLEMENTED 120L #endif // GetWinFlags() の戻り値の 1 つ (Windows NT 下で返される値) #ifndef WF_WINNT #define WF_WINNT 0x4000 #endif #define SYNCHRONIZE (0x00100000L) #define STANDARD_RIGHTS_REQUIRED (0x000F0000L) #define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF) #endif #ifndef EW_RESTARTWINDOWS #define EW_EXITWINDOWS 0 #define EW_RESTARTWINDOWS 0x42 // Windows のみを再起動 #define EW_REBOOTSYSTEM 0x43 // Windows 終了後、コンピュータを再起動 #endif #ifndef EWX_LOGOFF #define EWX_LOGOFF 0 #define EWX_SHUTDOWN 0x00000001 #define EWX_REBOOT 0x00000002 #define EWX_FORCE 0x00000004 #define EWX_POWEROFF 0x00000008 #define EWX_FORCEIFHUNG 0x00000010 #endif
ソース
#include <malloc.h> #ifdef _WIN16 // 32 ビットの ExitWindowsEx で使うフラグから // 16 ビットの ExitWindows で使うフラグに変換 static DWORD __stdcall ConvertEWFlag(DWORD dw32Bit) { if (dw32Bit & (EWX_LOGOFF | EWX_POWEROFF | EWX_SHUTDOWN)) return EW_EXITWINDOWS; if (dw32Bit & (EWX_REBOOT)) return EW_REBOOTSYSTEM; return EW_EXITWINDOWS; } #endif // uFlags: SDF_ フラグを指定 extern "C" bool __stdcall DoExitWindows(UINT uFlags) { // 16 ビットのみのコード - 32 ビットコードでは不要 #ifdef _WIN16 DWORD dwVersion; BYTE bMajorVersion; DWORD dwKernel32; DWORD dwUser32; DWORD dwAdvapi32; // 実行中の Windows のバージョンを取得して、 // Win16 か Win32 かどうかをチェック dwVersion = GetVersion(); if (GetWinFlags() & WF_WINNT) // WinNT 系かどうか bMajorVersion = 4; else if (HIBYTE(LOWORD(dwVersion)) >= 95) // Win95 以降かどうか bMajorVersion = 4; else bMajorVersion = 3; // Win3.1 など if (bMajorVersion >= 4) { dwKernel32 = LoadLibraryEx32W("kernel32.dll", NULL, 0); dwUser32 = LoadLibraryEx32W("user32.dll", NULL, 0); dwAdvapi32 = LoadLibraryEx32W("advapi32.dll", NULL, 0); } else { dwKernel32 = 0; dwUser32 = 0; dwAdvapi32 = 0; } #endif // SDF_ フラグから EW(X)_ フラグに変換 DWORD dwFlags = 0; bool bSucceeded = false; // SDF_FORCE を EWX_FORCE に if ((uFlags & SDF_FORCE) #ifdef _WIN16 && bMajorVersion >= 4 // Win32 で実行されているかどうか #endif ) { uFlags &= ~(SDF_FORCE); dwFlags |= EWX_FORCE; } switch (uFlags & 0x0F) { case SDF_LOGOFF: #ifdef _WIN16 // Win16 にはログオフは無い if (bMajorVersion >= 4) #endif { dwFlags |= EWX_LOGOFF; break; } case SDF_POWEROFF: #ifdef _WIN16 // Win16 には「電源を切る」は無い if (bMajorVersion >= 4) #endif dwFlags |= EWX_POWEROFF; case SDF_SHUTDOWN: #ifdef _WIN16 if (bMajorVersion >= 4) #endif dwFlags |= EWX_SHUTDOWN; #ifdef _WIN16 else dwFlags = EW_EXITWINDOWS; #endif break; case SDF_SYSREBOOT: #ifdef _WIN16 if (bMajorVersion < 4) { dwFlags |= EW_REBOOTSYSTEM; break; } #endif case SDF_REBOOT: #ifdef _WIN16 if (bMajorVersion >= 4) #endif dwFlags |= EWX_REBOOT; #ifdef _WIN16 else dwFlags |= EW_RESTARTWINDOWS; #endif break; } #ifdef _WIN16 if (bMajorVersion >= 4) { DWORD dwGetCurrentProcess; DWORD dwOpenProcessToken; DWORD dwGetLastError; DWORD dwLookupPrivilegeValue; DWORD dwAdjustTokenPrivileges; DWORD dwCloseHandle; DWORD dwExitWindowsEx; bool bRet = true; if (dwAdvapi32 && dwKernel32) { DWORD hProcessMe; DWORD hToken; TOKEN_PRIVILEGES tkp; bool bUseDef = false; DWORD dwRet; DWORD dwPParam1, dwPParam2; dwOpenProcessToken = GetProcAddress32W(dwAdvapi32, "OpenProcessToken"); dwGetCurrentProcess = GetProcAddress32W(dwKernel32, "GetCurrentProcess"); dwGetLastError = GetProcAddress32W(dwKernel32, "GetLastError"); // Get this process handle. hProcessMe = CallProcEx32W(0 | CPEX_DEST_STDCALL, 0, dwGetCurrentProcess); // Get a token for this process. if (dwOpenProcessToken) { dwPParam1 = GetVDMPointer32W(&hToken, 1); dwRet = CallProcEx32W(3 | CPEX_DEST_STDCALL, 0, dwOpenProcessToken, hProcessMe, (DWORD) (TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY), dwPParam1); } else dwRet = 0; if (!dwRet) { if (dwGetLastError) { dwRet = CallProcEx32W(0 | CPEX_DEST_STDCALL, 0, dwGetLastError); if (dwRet != ERROR_CALL_NOT_IMPLEMENTED) bRet = false; } } else { // Get the LUID for the shutdown privilege. dwLookupPrivilegeValue = GetProcAddress32W(dwAdvapi32, "LookupPrivilegeValueA"); dwPParam1 = GetVDMPointer32W(SE_SHUTDOWN_NAME, 1); dwPParam2 = GetVDMPointer32W(&tkp.Privileges[0].Luid, 1); CallProcEx32W(3 | CPEX_DEST_STDCALL, 0, dwLookupPrivilegeValue, (DWORD) NULL, dwPParam1, dwPParam2); tkp.PrivilegeCount = 1; // one privilege to set tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // Get the shutdown privilege for this process. dwAdjustTokenPrivileges = GetProcAddress32W(dwAdvapi32, "AdjustTokenPrivileges"); dwPParam1 = GetVDMPointer32W((LPBYTE) &tkp, 1); dwRet = CallProcEx32W(6 | CPEX_DEST_STDCALL, 0, dwAdjustTokenPrivileges, hToken, (DWORD) FALSE, dwPParam1, (DWORD) 0, (DWORD) NULL, (DWORD) NULL); // Cannot test the return value of AdjustTokenPrivileges. dwRet = CallProcEx32W(0 | CPEX_DEST_STDCALL, 0, dwGetLastError); if (dwRet != ERROR_SUCCESS) bRet = false; dwCloseHandle = GetProcAddress32W(dwKernel32, "CloseHandle"); CallProcEx32W(1 | CPEX_DEST_STDCALL, 0, dwCloseHandle, hToken); } } if (dwAdvapi32) FreeLibrary32W(dwAdvapi32); if (dwKernel32) FreeLibrary32W(dwKernel32); if (bRet) { if (dwUser32) { // Call ExitWindowsEx() in USER32.DLL to shutdown dwExitWindowsEx = GetProcAddress32W(dwUser32, "ExitWindowsEx"); bSucceeded = (CallProcEx32W(2 | CPEX_DEST_STDCALL, 0, dwExitWindowsEx, dwFlags, 0) != 0); } else // Couldn't load USER32.DLL, so we call ExitWindows() in USER.EXE. bSucceeded = (ExitWindows(ConvertEWFlag(dwFlags), 0) != 0); } if (dwUser32) FreeLibrary32W(dwUser32); } else // Call ExitWindows() in USER.EXE because this program is running under Windows 3.1 or earlier. bSucceeded = (ExitWindows(dwFlags, 0) != 0); #else HANDLE hProcessMe; HANDLE hToken; TOKEN_PRIVILEGES tkp; // Get this process handle. hProcessMe = GetCurrentProcess(); // Get a token for this process. if (!OpenProcessToken(hProcessMe, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) goto OnExit; } else { // Get the LUID for the shutdown privilege. LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; // one privilege to set tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // Get the shutdown privilege for this process. AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); // Cannot test the return value of AdjustTokenPrivileges. if (GetLastError() != ERROR_SUCCESS) { CloseHandle(hToken); goto OnExit; } CloseHandle(hToken); } bSucceeded = (ExitWindowsEx((UINT) dwFlags, 0) != 0); OnExit: #endif return bSucceeded; }
最終更新日: 2004/12/25