Win32API システム時刻を設定する

システムの時刻を設定するためには、SetSystemTime関数を用いる。SetSystemTime関数を用いるためには、SE_SYSTEMTIME_NAME特権を有効にしておく必要がある。


  • SetSystemTimeでシステム時刻を設定する例

  • システム時刻を「今日」の零時に設定する

    手順としては、まずEnablePrivileges関数にて、AdjustTokenPrivileges関数でSE_SYSTEMTIME_NAME特権を有効にしてから、SetSystemTime関数を呼び出す。

    SetSystemTime関数の引数であるLPSYSTEMTIME型には、UTCを設定する必要がある。そのため、まずGetLocalTime関数でローカルタイムを取得し、wHour、wMinute、wSecond、wMilliseconds各メンバに「0」をセットする。その後、ローカルタイムをUTCに変換してからSetSystemTime関数を呼び出している。

    #include <windows.h>
    #include <stdio.h>
    
    BOOL EnablePrivileges(LPTSTR lpPrivilegeName, BOOL bEnable)
    {
        HANDLE hToken;
        LUID luid;
        TOKEN_PRIVILEGES tokenPrivileges;
        BOOL bRet;
    
    
        //1.OpenProcessToken関数で、プロセストークンを取得する
        bRet = OpenProcessToken(GetCurrentProcess(),
            TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
            &hToken);
        if (!bRet) {
            return FALSE;
        }
    
        //2.LookupPrivilegeValue関数で、特権に対応するLUID(ローカル一意識別子)を取得する
        bRet = LookupPrivilegeValue(NULL, lpPrivilegeName, &luid);
        if (bRet) {
    
            //3.TOKEN_PRIVILEGES型のオブジェクトに、LUID(ローカル一意識別子)と特権の属性(有効にするか無効にするか)を指定する
            tokenPrivileges.PrivilegeCount = 1;
            tokenPrivileges.Privileges[0].Luid = luid;
            tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
    
            //4.AdjustTokenPrivileges関数で、特権を有効にする
            AdjustTokenPrivileges(hToken,
                FALSE,
                &tokenPrivileges, 0, 0, 0);
    
            bRet = GetLastError() == ERROR_SUCCESS;
    
        }
    
        CloseHandle(hToken);
    
        return bRet;
    }
    
    int main()
    {
        //SE_SHUTDOWN_NAME(シャットダウン特権) を有効にする
        if ( !EnablePrivileges(SE_SYSTEMTIME_NAME, TRUE) ) {
            puts("EnablePrivileges failed");
            return 1;
        }
    
        FILETIME localFileTime, utcFileTime;
        SYSTEMTIME localTime, utcTime;
    
        //ローカルタイムを取得
        GetLocalTime(&localTime);
    
        //時刻を零時に設定する
        localTime.wHour = 0;
        localTime.wMinute = 0;
        localTime.wSecond = 0;
        localTime.wMilliseconds = 0;
    
        ////////////////////////////////////////////////
        //ローカルタイムをUTCをに変換する
        
        //SYSTEMTIME構造体をFILETIME構造体へ変換
        SystemTimeToFileTime(&localTime, &localFileTime);
    
        //FILETIME構造体に変換されたUTCをローカルタイムに変換
        LocalFileTimeToFileTime(&localFileTime, &utcFileTime);
        //FileTimeToLocalFileTime(&utcFileTime, &localFileTime);
        
        //ロールタイムに変換されたFILETIME構造体をSYSTEMTIME構造体に変換
        FileTimeToSystemTime(&utcFileTime, &utcTime);
        //
        ////////////////////////////////////////////////
    
    
        //システム時刻を設定する
        if (SetSystemTime(&utcTime)) {
            puts("SetSystemTime succeeded!");
        } else {
            puts("SetSystemTime failed");
        }
    
        return 0;
    }



    このプログラムを実行を成功させるためには、プロセスに対して、SE_SYSTEMTIME_NAME特権が有効になっていなければならない。

    拙者の実行環境であるWindows Vistaは、ユーザー権限で実行した場合は、SE_SYSTEMTIME_NAME特権が元々割当てられていなかったため、SE_SYSTEMTIME_NAME特権を有効にすることが出来なかった。

    管理者権限で実行した場合は、SE_SYSTEMTIME_NAME特権が割当てられているが、無効になっていたため、EnablePrivileges関数でSE_SYSTEMTIME_NAME特権を有効にして、プログラムの実行を成功させることができた。




    参考
    http://msdn.microsoft.com/ja-jp/library/cc429943.aspx
    http://support.microsoft.com/kb/245786/ja
    http://d.hatena.ne.jp/s-kita/20110409/1302337508