2017-01-12 21 views
0

comポートにGPSユニットを接続しています。私は自分のシステムをタイムサーバとして作りたいと思っていました。これを行う方法?C++でのWindowsシステム時刻の設定

私はsettime()SetLocalTime()SetSystemTime()などを使ってみましたが、私のために働いていません。 system("cmd")を使ってみましたが、もう一度私は管理者権限を取得していません。 system("runas cmd")を使用すると、コマンドプロンプトが開いて閉じて点滅します。何が起こっているのか理解できません。

どうすればこの仕事をすることができますか?

+2

これらのAPI(SetSystemTimeなど)を使用する場合、関数は何を返しますか? falseを返すと、GetLastErrorは何を返しますか? –

+0

両方の戻り値は0(ゼロ)です。 –

+0

CheckTokenMembershipを使用すると、現在のプロセスに管理者権限があるかどうかを確認できます。システム( "runas cmd")が動作するかどうかわからない – Asesh

答えて

1

Windowsでの特権管理は、常に難しい部分です。 MSoftは、通常の人間はそれに気を付けるべきではなく、ドキュメントはしばしば不完全であると仮定します。

ここで問題となるのは、通常のプロセス(管理者として実行していない)にはシステム時間を変更する特権がない可能性があります。

しかし、何が可能であることは次のとおりです。

  • チェックと同じパラメータを使用してプロセスを再起動しない場合、それは単に時間
  • を設定されている場合SeSystemtimePrivilegeは、実行中のプロセス
    • に付与されているかどうか管理者:ShellExectute、動詞= "runas"
ここで210

(一部は時間文字列を解析し、実際に実装されていない時間を設定する)コードの例である:まだ上で動作する

#include <iostream> 
#include <windows.h> 
#include <tchar.h> 

#ifdef UNICODE 
#define tcout std::wcout 
#else 
#define tcout std::cout 
#endif 

// utility used to display error messages 
void errmsg() { 
    DWORD err = ::GetLastError(); 
    LPTSTR msg; 
    ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, 
     err, LANG_NEUTRAL, (LPTSTR) &msg, 0, NULL); 
    tcout << _T("Error") << std::endl; 
} 

int _tmain(int argc, TCHAR *argv[]) { 
    // syntax check 
    if (argc != 2) { 
     tcout << _T("Usage ") << argv[0] << " _time_" << std::endl; 
     return 1; 
    } 
    LPCTSTR time = argv[1]; 
    // get access to the current process token 
    HANDLE process = ::GetCurrentProcess(); 
    HANDLE token; 
    if (! ::OpenProcessToken(process, TOKEN_ALL_ACCESS, &token)) { 
     errmsg(); 
     return 1; 
    } 
    // get priviledges from current token 
    DWORD sz = 0, sz2; 
    TOKEN_PRIVILEGES *privs; 
    ::GetTokenInformation(token, TokenPrivileges, NULL, 0, &sz); // first only size 
    if (sz == 0) { 
     errmsg(); 
     return 1; 
    } 
    privs = (TOKEN_PRIVILEGES *) malloc(sz); 
    if (! ::GetTokenInformation(token, TokenPrivileges, privs, sz, &sz2)) { 
     errmsg(); 
     return 1; 
    } 

    // display found priviledges and look if SE_SYSTEMTIME_NAME is present 
    BOOL ok = FALSE; 
    for (size_t i=0; i<privs->PrivilegeCount; i++) { 
     sz = 0; 
     ::LookupPrivilegeName(NULL, &(privs->Privileges[i].Luid), NULL, &sz); 
     LPTSTR name = (LPTSTR) malloc(sz * sizeof(TCHAR)); 
     if (! ::LookupPrivilegeName(NULL, &(privs->Privileges[i].Luid), name, &sz)) { 
      errmsg(); 
      return 1; 
     } 
     if (0 == ::lstrcmp(name, SE_SYSTEMTIME_NAME)) { 
      ok = TRUE; 
     } 
     // tcout << name << std::endl; 
     free(name); 
    } 
    free(privs); // done with it 
    tcout << (ok ? _T("Can") : _T("Cannot")) << _T(" change time") << std::endl; 

    if (ok) { 
     tcout << _T("Setting time with ") << time << std::endl; 
     // actually parse the time string and call SetSystemTime 
     //... 
    } 
    else { 
     tcout << _T("Restart self as admin...") << std::endl; 
     // start as cmd /K "full path" to have a chance to see eventual errors 
     LPTSTR params = (LPTSTR) malloc(MAX_PATH + 7 + lstrlen(time)); 
     lstrcpy(params, _T(" /K \"")); 
     sz = ::GetModuleFileName(NULL, params + 5, MAX_PATH); 
     // tcout << params + 5 << std::endl; 
     ::lstrcat(params,_T("\" ")); // do not forget the trailing " 
     lstrcat(params, time); 
     // Let's go, the UAC control should pop to allow the privilege elevation 
     if (((int) ShellExecute(NULL, _T("runas"), _T("cmd.exe"), params, 
       _T("."), SW_SHOW)) < 32) { 
      tcout << _T("Could not start self with elevated privileges") << std::endl; 
      return 1; 
     } 
     free(params); 
    } 
    // time to clean... 
    ::CloseHandle(token); 
    ::CloseHandle(process); 
    return 0; 
} 

もの:

  • コマンドである場合管理者モードで再起動された場合は、cmd /Kのコンソールを使用して、ユーザーに何が起こったかを確認できるようにします。より静かにすることを希望する場合は、cmd /Cを代わりに使用し、SW_HIDEShellExecuteです。
  • このプログラムは、新しい時間をしたり、ユースケースのために適切ではないかもしれません単純な文字列として指定されることを前提としてい
  • 冗長性を
  • システムはたrunas管理者を試して防ぐ必要があるオプションの引数で制御されなければなりません 2回以上(おそらく2番目またはオプションのパラメータ)
関連する問題