リモート アシスタンスを提供する

Microsoft Corporation

June 2003

適用対象:
    MicrosoftR リモート アシスタンス
    Microsoft WindowsR XP
    Microsoft Windows Server 2003

要約: このホワイトペーパーでは、リモート アシスタンスの リモート アシスタンスを提供する機能に基づいてカスタマイズしたソリューションを構築するために必要な情報を詳しく説明します。提供されているオブジェクトとサンプル コードを使用して、リモート アシスタンスを提供するというソリューションをヘルプ デスク組織のワークフローに統合できます。

目次

unsolicited リモート アシスタンス オブジェクト

リモート アシスタンス チケット

unsolicited リモート アシスタンス オブジェクト

SAFRemoteDesktopConnection オブジェクト

プロパティ

  • なし

メソッド

  • ConnectRemoteDesktop

    [jscript]
    Obj.ConnectRemoteDesktop(remoteMachineName)
    

    引数

    入力

    remoteMachineName - この引数には、リモート コンピュータの IP アドレスまたは DNS サーバー名を指定できます。

    戻り値

    SAFRemoteConnectionData オブジェクト

    説明

    リモート コンピュータとの接続を確立した後で、このメソッドは、リモート コンピュータにログオンしている各ユーザーのすべてのセッション情報を返します。この情報は、メソッドから返される SAFRemoteConnectionData オブジェクトに挿入されます。

    このメソッドには、切断しているターミナル サーバー セッション、およびターミナル サービス内部で使用される ID 65536 のセッションは含まれません。

    このメソッドは、ヘルプ センター内で実行されるスクリプトからのみ呼び出すことができます。

    リモート アシスタンスを提供するためのサンプル JScript

    要件

    クライアント: Microsoft Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

SAFRemoteConnectionData オブジェクト:

プロパティ

  • なし

メソッド

  • Users

    [jcsript]
    Obj.Users()
    

    引数

    入力

    なし

    戻り値

    PCHCollection オブジェクト

    説明

    このメソッドは、ログオンしているすべてのユーザーのコレクションを返します。すべてのユーザー情報が標準コレクション (PCHCollection) として返されます。このコレクションのメンバは、SAFUser 型のオブジェクトです。

    このメソッドは、ヘルプ センター内で実行されるスクリプトからのみ呼び出すことができます。

    リモート アシスタンスを提供するためのサンプル JScript

    要件:

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

  • Sessions

    [jscript]
    Obj.Sessions(optional var UserName, optional var DomainName)
    

    引数

    入力

    UserName - リモート コンピュータのユーザー

    DomainName - リモート コンピュータのユーザーのドメイン

    戻り値

    PCHCollection オブジェクト

    説明

    入力パラメータが指定されていない場合、このメソッドは、リモート コンピュータにログオンしているすべてのユーザーのセッション情報を含む PCHCollection を返します。このコレクションのメンバは、SAFSession 型のオブジェクトです。入力パラメータが指定されている場合は、指定されたユーザーのセッション情報だけが返されます。

    このメソッドは、ヘルプ センター内で実行されるスクリプトからのみ呼び出すことができます。

    リモート アシスタンスを提供するためのサンプル JScript

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

  • ConnectionParms

    [jscript]
    Obj.ConnectionParms(var RemoteMachineName, var RemoteUserName, var RemoteDomainName, var RemoteSessionID, var bstrUserHelpBlob)
    

    引数

    入力

    RemoteMachineName: リモート アシスタンス チケットの作成対象のリモート コンピュータ名。

    RemoteUserName: リモート コンピュータ上のリモート アシスタンス チケットの作成対象のユーザー名。

    RemoteDomainName: リモート コンピュータ上のリモート アシスタンス チケットの作成対象のユーザーのドメイン名。

    RemoteSessionID: リモート アシスタンス チケットの作成対象のリモート コンピュータ上のセッション ID。

    BstrUserHelpBlob: 予約されており、常に Null 文字列を指定する必要があります。

    戻り値

    接続パラメータ文字列 - リモート (初心者) コンピュータに接続するために支援者によって使用されます。

    説明

    このメソッドは、指定されたユーザー名、ドメイン名、セッション ID の接続パラメータを取得します。返される接続パラメータ文字列は、入力パラメータに基づくリモート アシスタンス チケットです。

    このメソッドは、ヘルプ センター内で実行されるスクリプトからのみ呼び出すことができます。

    リモート アシスタンスを提供するためのサンプル JScript

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

  • ModemConnected

    [jscript]
    Obj.ModemConnected(ServerName)
    

    引数

    入力

    ServerName - 接続の種類 (モデムまたはブロードバンド/その他) を判断する対象のリモート コンピュータ名を含む文字列

    戻り値

    接続の種類を示すブール型 (Boolean) の値

    True = モデム

    False = ブロードバンド/その他

    説明

    このメソッドは、リモート コンピュータの接続の種類の判断に使用されます。このメソッドを使用して、帯域幅を最適化するための色設定を設定できます (「リモート アシスタンス チケット」を参照)。

    このメソッドは、ヘルプ センター内で実行されるスクリプトからのみ呼び出すことができます。Windows XP または Windows XP SP1 ではサポートされていません。

    リモート アシスタンスを提供するためのサンプル JScript

    要件

    クライアント: Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

SAFUser オブジェクト

プロパティ

  • DomainName

    [jscript]
    Obj.DomainName
    

    引数

    入力

    なし

    出力

    リモート コンピュータにログオンしているユーザーのドメイン名

    説明

    DomainName には、リモート コンピュータにログオンしているユーザーのドメイン名が含まれます。

    このオブジェクトは、ヘルプ センターのスクリプトからのみアクセスできます。

    リモート アシスタンスを提供するためのサンプル JScript

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

  • UserName

    [jscript]
    Obj.UserName
    

    引数:

    入力:

    なし

    戻り値

    リモート コンピュータにログオンしているユーザーのユーザー名

    説明

    UserName には、リモート コンピュータにログオンしているユーザーのユーザー名が含まれます。

    このメソッドは、ヘルプ センター内で実行されるスクリプトからのみ呼び出すことができます。

    リモート アシスタンスを提供するためのサンプル JScript

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

SAFSession オブジェクト

説明

SAFSession オブジェクトには、ログオンしているすべてのユーザーのセッション状態、セッション ID、ユーザー名、およびドメイン名情報が含まれます。

プロパティ

  • SessionID

    [jscript]
    Obj.SessionID
    [c]
    [propget, id(DISPID_SAF_SESS__SESSIONID   )] HRESULT SessionID   ( [out, retval] DWORD *pVal   );
    [c]
    [propput, id(DISPID_SAF_SESS__SESSIONID   )] HRESULT SessionID   ( [in      ] DWORD         pVal   );
    

    説明

    リモート コンピュータ上のセッションのセッション ID を含みます。

    リモート アシスタンスを提供するためのサンプル C

    リモート アシスタ

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

  • Session State:

    [jscript]
    Obj.SessionState
    [c]
    [propget, id(DISPID_SAF_SESS__SESSIONSTATE)] HRESULT SessionState( [out, retval] SessionStateEnum         *pVal   );
    [c]
    [propput, id(DISPID_SAF_SESS__SESSIONSTATE)] HRESULT SessionState( [in         ] SessionStateEnum         pVal   );UserName:
    

    説明

    リモート コンピュータ上のセッションのセッション状態を含みます。これは、次のいずれかです。

    PchActive                = 0,     // ユーザーが WinStation にログオンしている

    pchConnected                = 1,    // WinStation がクライアントに接続している

    pchConnectQuery    = 2,     // クライアントへの接続処理中

    pchShadow                = 3,     // 別の WinStation をシャドウイング

    pchDisconnected     = 4,     // WinStation がクライアントなしでログオンしている

    pchIdle                = 5,    // クライアントの接続を待機中

    pchListen                = 6,    // WinStation が接続をリスニング中

    pchReset                = 7,     // WinStation のリセット中

    pchDown                = 8,    // エラーにより WinStation がダウン

    pchInit                = 9,    // WinStation の初期化中

    pchStateInvalid                =10    // Winstation の状態が無効

    リモート アシスタンスを提供するためのサンプル C

    リモート アシスタンスを提供するためのサンプル JScript

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

  • DomainName

    [jscript]
    Obj.DomainName
    [c]
    [propget, id(DISPID_SAF_SESS__DOMAINNAME  )] HRESULT DomainName  ( [out, retval] BSTR                    *pVal   );
    [c]
    [propput, id(DISPID_SAF_SESS__DOMAINNAME  )] HRESULT DomainName  ( [in   ] BSTR    pVal   );
    

    説明

    セッションの所有者のドメイン名を含みます。

    リモート アシスタンスを提供するためのサンプル C

    リモート アシスタンスを提供するためのサンプル JScript

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

  • UserName

    [jscript]
    Obj.UserName
    [c]
    [propget, id(DISPID_SAF_SESS__USERNAME    )] HRESULT UserName    ( [out, retval] BSTR                     *pVal   );
    [c]
    [propput, id(DISPID_SAF_SESS__USERNAME    )] HRESULT UserName    ( [in         ] BSTR                     pVal   );
    

    説明

    セッションの所有者のユーザー名を含みます。

    リモート アシスタンスを提供するためのサンプル C

    リモート アシスタンスを提供するためのサンプル JScript

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

PCHService

  • RemoteConnectionParms

    HRESULT RemoteConnectionParms([in] BSTR bstrUserName, [in ] BSTR  bstrDomainName [in ], [in  ] long  lSessionID , [in ] BSTR bstrUserHelpBlob , [out, retval] BSTR *bstrConnectionString );
    

    パラメータ

    入力

    UserName - 接続パラメータを取得する初心者のコンピュータ上のセッションのユーザー名。

    DomainName - 接続パラメータを取得する初心者のコンピュータ上のセッションのドメイン名。

    SessionID - 接続パラメータを取得する初心者のコンピュータ上のセッションのセッション ID。

    bstrUserHelpBlob - リモート アシスタンスの内部で使用します。このパラメータには常に Null 値を渡すことをお勧めします。

    出力

    接続パラメータ文字列 - リモート (初心者) コンピュータに接続するために支援者によって使用されます。

    戻り値

    成功または失敗を示す標準の HRESULT

    説明

    このメソッドは、指定されたユーザー名、ドメイン名、セッション ID の接続パラメータを取得します。これは、支援者側で使用されるインターフェイスです。

    注意

    リモート アシスタンスが [システムのプロパティ] および [リモート アシスタンス] で無効になっている場合、グループ ポリシーはサーバー (初心者のコンピュータ) 上で構成または無効化されず、有効な引数を指定して RemoteConnectionParms または RemoteUserSessionInfo を呼び出すと E_AccessDenied が返されます。

    UserName と DomainName の両方が Null または空の場合は、戻りコードが S_OK で接続パラメータ文字列が生成されます。この接続文字列は有効ではなく、この接続文字列を使用してリモート アシスタンス接続が試行された場合は動作しません。

    UserName および DomainName が無効な BSTR であり、Null または空ではない場合は、SALEM チケットが生成されず、返される hr は HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) です。

    リモート アシスタンスを提供するためのサンプル C

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

  • RemoteUserSessionInfo:

    HRESULT RemoteUserSessionInfo ([out] PCHCollection* *ppSessions )
    

    パラメータ

    入力:

    なし

    出力

    リモート コンピュータ上のセッションの PCHCollection

    戻り値

    成功または失敗を示す標準の HRESULT

    説明

    このメソッドは、リモート コンピュータ上のセッションのコレクションを返します。すべてのセッション情報が標準コレクション (PCHCollection) として返されます。このコレクションのメンバは、SAFSession 型のオブジェクトです。SAFSession には、各セッションの DomainName、SessionID、SessionState、および UserName が含まれます。

    リモート アシスタンスが [システムのプロパティ] および [リモート アシスタンス] で無効になっている場合、グループ ポリシーはサーバー (初心者のコンピュータ) 上で構成または無効化されず、有効な引数を指定して RemoteConnectionParms または RemoteUserSessionInfo を呼び出すと E_AccessDenied が返されます。

    リモート アシスタンスを提供するためのサンプル JScript

    要件:

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

  • get_RemoteModemConnected

    HRRESULT get_RemoteModemConnected( /*[out,retval]*/ VARIANT_BOOL *fModemConnected )
    

    パラメータ

    出力

    接続の種類を決定するブール型の値

    True = モデム

    False = ブロードバンド/その他

    戻り値

    成功または失敗を示す標準の HRESULT

    説明

    このメソッドは、リモート コンピュータの接続の種類の判断に使用されます。このメソッドを使用して、帯域幅を最適化するための色設定を設定できます (「リモート アシスタンス チケット」を参照)。

    リモート アシスタンスを提供するためのサンプル C

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

PCHCollection

  • get__NewEnum

    HRESULT get__NewEnum(IUnknown** ppUnk);
    

    パラメータ

    出力

    ppUnk

    [出力] 新規に作成された列挙オブジェクトの IUnknown ポインタ

    戻り値

    成功または失敗を示す標準の HRESULT

    説明

    コレクションの列挙オブジェクトを返します。オブジェクトの PCH コレクションの詳細については、「PCHCollection」を参照してください。

    注意

    新規に作成された列挙子は、元のコレクション m_coll の反復子を維持し (したがってコピーは作成されません)、コレクション オブジェクトの COM 参照を保持して、未処理の列挙子が存在する間はコレクションが存続するようにします。

    リモート アシスタンスを提供するためのサンプル C

    要件

    クライアント: Windows XP または Windows Server 2003 に組み込まれています。

    ライブラリ: HelpServiceInterfaces.tlb を使用します。

リモート アシスタンス チケット

はじめに

ここでは、リモート アシスタント (RA) チケットに含まれている詳細を記述します。RA チケットには、RA 支援者 (クライアント) が RA 初心者 (サーバー) に接続するために必要な情報が含まれます。チケットは、RA 初心者によって生成され、既存のエスカレーション方法を通じて RA 支援者に送信されます。

詳細

サンプルの RA チケットは、次の XML のようになります。

注: 次のサンプルは、OS バージョン XP SP1 以上を対象としています。XP SP1 より前のコンピュータでは、* がテキスト値で置換されます。これらは、リモート アシスタンスによって使用される内部値であるため、変更しないでください。

<?xml version="1.0" encoding="Unicode" ?>
<UPLOADINFO TYPE="Escalated">

UPLOADDATA USERNAME="sampleUser" 
RCTICKET="65538,
1,
192.168.1.100:3389Port;sampleMachineName.yourDomain.com:3389,
*,
Wx6F64TmkmR4FizZt8fNUqYIFz6NPgiT1zdYi5XQUKo=,
*,
*,
d4sTmwmZSr3XOcku2pSAOK/qG40=" 
RCTICKETENCRYPTED="1" 
DtStart="1014854217" 
DtLength="60" PassStub="Wx6F64TmkmR4FizZt8fNUqYIFz6NPgiT1zdYi5XQUKo=" 
  L="0" />
</UPLOADINFO>

次に、UPLOADDATA タグの内部にある可能性のある属性と、その定義を示します。

  1. USERNAME

    支援される初心者のユーザー名。

  2. RCTICKET

    リモート アシスタンスに固有の接続パラメータ文字列。この接続文字列の IP アドレス部分はセミコロンで区切られ、複数の IP アドレスを含んでいる場合があります。アドレスのリストには、上に示すように完全修飾ドメイン名が含まれている場合もあります。

  3. RCTICKETENCRYPTED

    • 1 - チケットがパスワードを使用して暗号化されている場合
    • 0 - チケットがパスワードを使用して暗号化されていない場合
  4. DtStart

    チケットが作成された時刻であり、日付 (DATE) 形式です。

  5. DtLength

    チケットの継続時間 (分単位)。

  6. PassStub

    リモート アシスタンス チケットに関連付けられているパスワードの暗号化に使用されるキー。

  7. L

    • 1 - ユーザーがモデムを使用している場合 (低帯域幅)
    • 0 - ユーザーがモデムを使用していない場合
  8. URA

    1 - チケットが、unsolicited リモート アシスタント チケットの場合、またはチケットが MAILTO ActiveX コントロールによって作成され、パスワードを含まない場合。この値は、値が 1 の場合にだけ提示され、それ以外の場合には提示されません。

リモート アシスタンスを提供するためのサンプル JScript

<!--
*  このファイルを、unsolicitedrctest.htm として
  %windir%\PCHEALTH\HELPCTR\System にコピー アンド ペーストします。
*  [スタート] - [ファイル名を指定して実行] に次のように入力する必要があります。
*  %windir%\PCHEALTH\HELPCTR\Binaries\HelpCtr.exe -url 
  hcp://services/centers/support?topic=hcp://system
    /unsolicitedrctest.htm
-->
<HTML>
   <HEAD>
      <TITLE></TITLE>
      <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
   </HEAD>
   <BODY topMargin="0">
      <OBJECT id="oSAFClassFactory" height="0" width="0" 
        classid="CLSID:FC7D9E02-3F9E-11d3-93C0-00C04F72DAF7"
         VIEWASTEXT>
      </OBJECT>
      <P> </P>
      <P> </P>
      <P align="center"><FONT face="Times New Roman" 
        size="5"><STRONG>unsolicited リモート制御 
               Unittest</STRONG></FONT></P>
      <TABLE>
         <TR>
            <TD><I size="20"> 起動するサーバー名を入力します 
              </I><B>ConnectRemoteDesktop </B><INPUT name="ServerName" 
              id="ServerName" style="WIDTH: 310px; HEIGHT: 20px" 
              size="40">   </TD>

         </TR>

         <TR>
            <TD><BUTTON id="Button1" onclick="RunScriptAPIs()" 
              name="RunScriptAPIs" 
              type="button">RunScriptAPIs</BUTTON></TD>
         </TR>
      </TABLE>

   <!--
   -->


   <SCRIPT Language="JScript">

   var oSAFRemoteDesktopConnection = null;
   var oSAFRemoteConnectionData    = null;
   var oUsersCollection            = null;
   var oSessionsCollection         = null;
   var RemConnectionParms          = null;

   function RunScriptAPIs()
   {
      try
      {
         // SAFRemoteDesktopConnection のオブジェクトを作成します。
         oSAFRemoteDesktopConnection = 
           oSAFClassFactory.CreateObject_RemoteDesktopConnection();

         if (oSAFRemoteDesktopConnection != null) 
         {
            // ServerName で指定されたリモート デスクトップに接続します。
            oSAFRemoteConnectionData = 
              oSAFRemoteDesktopConnection.ConnectRemoteDesktop
                (ServerName.value);


            //
            // ログオンしているユーザーのカウントと、
              そのユーザーの UserName および DomainName を取得します。
            //

            // サーバー (初心者) コンピュータにログオンしている
              すべてのユーザーのコレクションを取得します。
            oUsersCollection = oSAFRemoteConnectionData.Users();

            // UsersCollection の詳細を一覧表示します。
            var nUsersLen = oUsersCollection.Count;

            // 各ユーザーについて、UserName および DomainName を表示します。
            for(i=1; i<= nUsersLen; i++)
            {
               oUserObj = oUsersCollection.item(i);

               // ISAFUser.UserName および ISAFUser.DomainName
                 プロパティを使用します。
               alert("Index : " +i+" UserName : "+oUserObj.UserName+" 
                 DomainName : "+oUserObj.DomainName);
            }


            //
            // ログオンしているすべてのユーザーのすべてのセッションの
              UserName、DomainName、SessionID、SessionState を取得します。
            //

            // リモート (サーバー) コンピュータにログオンしているすべてのユーザーの
              すべてのセッションを取得します。
            oSessionsCollection = oSAFRemoteConnectionData.Sessions();

            // SessionsCollection の詳細を一覧表示します。
            var nSessionsLen = oSessionsCollection.Count;

            // 各セッション コレクション オブジェクトの
              UserName、DomainName、SessionID、
            // SessionState を表示します。
            for(i=1; i<= nSessionsLen; i++)
            {
               oSessionObj = oSessionsCollection.item(i);

               // ISAFSession.UserName、ISAFSession.DomainName、
                 ISAFSession.SessionID および ISAFSession.SessionState
                              alert("Index : " +i+" UserName : 
                                "+oSessionObj.UserName+" DomainName : 
                                "+oSessionObj.DomainName+" SessionID
                                "+oSessionObj.SessionID+"  SessionState
                                "+oSessionObj.SessionState);
            }


            //
            // ServerName、UserName、DomainName、および
              SessionID を使用して、
            // ConnectionParms() を呼び出してチケットを
              RemConnectionParms に取得します。
            //
            oSessionObj = oSessionsCollection.item(1);
            RemConnectionParms = 
              oSAFRemoteConnectionData.ConnectionParms
                (ServerName.value, oSessionObj.UserName,
                  oSessionObj.DomainName, oSessionObj.SessionID, "");
            alert("SUCCEEDED : ConnectionParms
              "+RemConnectionParms);

            // この呼び出しは XP ではエラーになりますが、
              Server 2003 では機能します。
            // fConnected =
              oSAFRemoteConnectionData.ModemConnected
                (ServerName.value);
                        // alert("ModemConnected  = "+fConnected);

            alert(" すべての API が正常に呼び出されました。\n GoodBye");
         }
            } catch(e)
            {
         alert("RunScriptAPI() がスローする例外 : "+e.description);
      }
   }

      </SCRIPT>
   </BODY>
</HTML>

リモート アシスタンスを提供するためのサンプル C

説明

次のコード サンプルは、リモート (初心者) コンピュータに存在するユーザー セッションに対して、リモート アシスタンス チケットを生成する方法を示します。

//
// main() の <...> プレースホルダを
  実行に適したデータで置換します。
//

#include <stdio.h>
#include <atlbase.h>

// REMOTE_DESKTOP_SHARING_CLASS の Typedef
typedef enum 
{
    DESKTOPSHARING_DEFAULT   = 0x0,
   NO_DESKTOP_SHARING      = 0x1,
   VIEWDESKTOP_PERMISSION_REQUIRE      = 0x2,
   VIEWDESKTOP_PERMISSION_NOT_REQUIRE   = 0x4,
   CONTROLDESKTOP_PERMISSION_REQUIRE   = 0x8,
   CONTROLDESKTOP_PERMISSION_NOT_REQUIRE   = 0x10
} REMOTE_DESKTOP_SHARING_CLASS;

// タイプ ライブラリをインポートします。
 #import "HelpServiceInterfaces.tlb" rename_namespace("HSITLB") 
  named_guids raw_interfaces_only no_auto_exclude \
    rename("GetUserName", "GetUserName_Renamed")\
    rename("EncryptFile", "EncryptFile_Renamed")\
    rename("DecryptFile", "DecryptFile_Renamed")\
    rename("ULONG_PTR","ULONG_PTR1")

//+--------------------------------------------------------------------
  -------
//
//  関数:   CallRemoteUserSessionInfoAPI
//
//  概要:   RemoteUserSessionInfo API を呼び出します。
//
//  引数:  bstrMachineName [入力] - リモート コンピュータ名
//
//---------------------------------------------------------------------
  -------
HRESULT CallRemoteUserSessionInfoAPI(
    IN BSTR bstrMachineName)
{
    HRESULT hr = S_OK;

    COSERVERINFO            si; ::ZeroMemory( &si, sizeof( si ) );
    MULTI_QI                qi; ::ZeroMemory( &qi, sizeof( qi ) );
    CComPtr<HSITLB::IPCHService>    pIsvc = NULL;
    CComPtr<IUnknown>       pIUnkEnum;
    CComPtr<IEnumVARIANT>   pIEnum;
    CComPtr<HSITLB::ISAFSession>    pIItem;
    CComPtr<IDispatch>      pIDispItem = NULL;
    CComPtr<HSITLB::IPCHCollection> pIColl = NULL;

    long lsizeCollection = 0;
    long lIndex = 0;

  // API から返される値です。
    BSTR bstrUserName = NULL;
    BSTR bstrDomainName = NULL;
    DWORD dwSessionID = 0;
    HSITLB::SessionStateEnum SessionState;

    CComVariant  varSAFSession;
    ULONG        ulFetched;
   
    si.pwszName = bstrMachineName;
    qi.pIID     = &(HSITLB::IID_IPCHService);

    hr = CoCreateInstanceEx(HSITLB::CLSID_PCHService, NULL, 
      CLSCTX_REMOTE_SERVER, &si, 1, &qi );
   if(hr != S_OK)  goto ErrReturn;

    // pIsvc ローカル ポインタへの IPCHService インターフェイス ポインタを取得します。
    pIsvc.Attach((HSITLB::IPCHService*) qi.pItf );

   // RemoteUserSessionInfo() は
     IPCHCollection インターフェイスへのポインタを返します。
    hr = pIsvc->RemoteUserSessionInfo(&pIColl);
   if(hr != S_OK)  goto ErrReturn;

    if(pIColl == NULL)
    {
      // エラー コードを表示します。
      printf("\n 初心者は、unsolicited をオフにしました。");
      goto ErrReturn;
    }

    hr = pIColl->get_Count(&lsizeCollection);
   if(hr != S_OK)  goto ErrReturn;

    hr = pIColl->get__NewEnum(&pIUnkEnum);
   if(hr != S_OK)  goto ErrReturn;

    hr = pIUnkEnum.QueryInterface(&pIEnum);
   if(hr != S_OK)  goto ErrReturn;

    if(lsizeCollection == 0)
    {
      // エラー コードを表示します。
      printf("\n このコンピュータにログインしているユーザーはいません。");
      goto ErrReturn;                                   
    }

   printf("\n\t RemoteUserSessionInfo \n");

    // ポイントしているコンピュータ上の
      個別のユーザー セッションについて、
    // その情報を取得します。
    for (lIndex=0; lIndex < lsizeCollection; lIndex++)
    {
        // セッションとユーザー情報の一覧を表示します。
        hr = pIEnum->Next( 1, &varSAFSession, &ulFetched);
        if ((hr == S_FALSE) || (ulFetched != 1))
        {
            printf("\n 失敗しました。 レコードがこれ以上ありません。");
            break;
        }

        pIDispItem = varSAFSession.pdispVal;

        hr = pIDispItem.QueryInterface(&pIItem);
      if(hr != S_OK)  goto ErrReturn;
                
        hr = pIItem->get_UserName(&bstrUserName);
      if(hr != S_OK)  goto ErrReturn;
        
        hr = pIItem->get_DomainName(&bstrDomainName);
      if(hr != S_OK)  goto ErrReturn;

        hr = pIItem->get_SessionID(&dwSessionID);
      if(hr != S_OK)  goto ErrReturn;

        hr = pIItem->get_SessionState(&SessionState);
      if(hr != S_OK)  goto ErrReturn;

        printf("\n MachineName = %S, \n UserName = %S, \n DomainName = 
          %S, \n SessionID = %u, \n SessionState = %d", 
           bstrMachineName, bstrUserName, bstrDomainName, dwSessionID, 
            SessionState);
    }

 ErrReturn:

    if(hr != S_OK)
       printf("CallRemoteUserSessionInfoAPI のエラー");

    return hr;

}

//+--------------------------------------------------------------------
  -------
//
//  関数:   CallRemoteConnectionParmsAPI
//
//  概要:   RemoteConnectionParms API を呼び出して SALEM チケットを生成します。
//
//  引数:  bstrMachineName [入力] - リモート コンピュータ名
//               bstrUserName     [入力] - ユーザー名  
//                bstrDomainName   [入力] - ドメイン名
//             lSessionID       [入力] - セッション ID
//               bstrUserHelpBlob [入力] - ユーザー ヘルプ BLOB
//
//---------------------------------------------------------------------
  -------

HRESULT CallRemoteConnectionParmsAPI(
    IN BSTR bstrMachineName,
    IN BSTR bstrUserName,  
    IN BSTR bstrDomainName,  
    IN long  lSessionID,  
    IN BSTR bstrUserHelpBlob)
{
    HRESULT hr = S_OK;

    COSERVERINFO            si; ::ZeroMemory( &si, sizeof( si ) );
    MULTI_QI                qi; ::ZeroMemory( &qi, sizeof( qi ) );
    CComPtr<HSITLB::IPCHService>    pIsvc;
    BSTR bstrGeneratedSALEMTicket = NULL;

    si.pwszName = bstrMachineName;
    qi.pIID     = &(HSITLB::IID_IPCHService);

    hr = ::CoCreateInstanceEx(
              HSITLB::CLSID_PCHService, NULL, CLSCTX_REMOTE_SERVER, 
                &si, 1, &qi );
   if(hr != S_OK)  goto ErrReturn;

    // pIsvc ローカル ポインタへの IPCHService インターフェイス ポインタを取得します。
    pIsvc.Attach((HSITLB::IPCHService*)qi.pItf );

   printf("\n\n\t RemoteConnectionParms \n");
    printf("\n MachineName = %S \n UserName = %S \n DomainName = %S \n 
      lSessionID = %d \n UserHelpBlob = %S", 
       bstrMachineName, bstrUserName, bstrDomainName, lSessionID, 
         bstrUserHelpBlob);

   // チケットを生成します。
    hr = pIsvc->RemoteConnectionParms(
        bstrUserName, 
        bstrDomainName, 
        lSessionID, 
        bstrUserHelpBlob, 
        &bstrGeneratedSALEMTicket);
   if(hr != S_OK)  goto ErrReturn;
    
    printf("\n RemoteConnectionParms によって生成されたチケット: \n %S 
      \n", 
          bstrGeneratedSALEMTicket);      

   // モデムのステータスを取得します。  
   // この呼び出しは、XP であるリモート コンピュータでは失敗します。Server 2003 では 
     機能します。
   // VARIANT_BOOL bModemConnected = FALSE;
   // hr = pIsvc->get_RemoteModemConnected(&bModemConnected);   
   // if(hr != S_OK)  goto ErrReturn;
   // printf("\n 接続されたモデム = %d", bModemConnected);

 ErrReturn:

    if(hr != S_OK)
       printf("CallRemoteConnectionParmsAPI のエラー");

    return hr;

}

//+--------------------------------------------------------------------
  -------
//
//  関数:   main
//
//  概要:   API テストのエントリ ポイント
//
//---------------------------------------------------------------------
  -------
int __cdecl main (int argc, char *argv[])
{  
    HRESULT hr = S_OK;

   // <...> プレースホルダを適切なデータで置換します。
    BSTR bstrMachineName  = SysAllocString(L"<machine name>");
    BSTR bstrUserHelpBlob = SysAllocString(L"<help blob>");
    BSTR bstrUserName     = SysAllocString(L"<user name>");
    BSTR bstrDomainName   = SysAllocString(L"<domain name>");
   long lSessionID = 0;

    hr = CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
   if(hr != S_OK)  goto ErrReturn;

   // RemoteUserSessionInfo API を呼び出します。
   hr = CallRemoteUserSessionInfoAPI(bstrMachineName);
   if(hr != S_OK)  goto ErrReturn;

    // RemoteConnectionParms API を呼び出します。
    hr = CallRemoteConnectionParmsAPI(
          bstrMachineName, 
          bstrUserName, 
          bstrDomainName, 
          lSessionID, 
          bstrUserHelpBlob);
   if(hr != S_OK)  goto ErrReturn;

   printf("\n RemoteUserSessionInfo と RemoteConnectionParms の両方の API が 
     正常に呼び出されました。\n\n");

ErrReturn:

    CoUninitialize();
   
    return 0;
    
} // main