EternalWindows
RPC / ネームサービス
対応するクライアントはこちら

ネームサービスは、前節で述べたエンドポイントマッパーと同じように、 クライアントがプロトコルシーケンスやエンドポイントを把握していない場合でも、 サーバーの関数を呼び出せるような機能を提供します。 具体的には、サーバーがネームサービス(locator.exeというサービス)に情報をエクスポートし、 クライアントはこれをインポートすることでバインディングを成立させることになります。 エンドポイントマッパーとネームサービスの大きな違いは、 前者に登録した情報がアプリケーションの終了時に自動的に削除されるのに対して、 後者に登録した情報はアプリケーションの終了時にも存在し続けるという点です。 また、ネームサービスは、Windows Vista以降のWindowsでサポートされていません。

ネームサービスに情報をエクスポートするには、RpcNsBindingExportを呼び出します。

RPC_STATUS RPC_ENTRY RpcNsBindingExport(
    unsigned long EntryNameSyntax,
    unsigned char *EntryName,
    RPC_IF_HANDLE IfSpec,
    RPC_BINDING_VECTOR *BindingVec,
    UUID_VECTOR *ObjectUuidVec
);

EntryNameSyntaxは、EntryNameのシンタックスを指定します。 通常は、RPC_C_NS_SYNTAX_DEFAULTを指定します。 EntryNameは、エントリの名前を指定します。 IfSpecは、インターフェースハンドルを指定します。 BindingVecは、バインディングベクタを指定します。 ObjectUuidVecは、オブジェクトUUIDを指定します。

ネームサービスにエクスポートした情報が不要になった場合は、 RpcNsBindingUnexportで削除します。

RPC_STATUS RPC_ENTRY RpcNsBindingUnexport(
    unsigned long EntryNameSyntax,
    unsigned char *EntryName,
    RPC_IF_HANDLE IfSpec,
    UUID_VECTOR *ObjectUuidVec
);

EntryNameSyntaxは、EntryNameのシンタックスを指定します。 通常は、RPC_C_NS_SYNTAX_DEFAULTを指定します。 EntryNameは、エントリの名前を指定します。 IfSpecは、インターフェースハンドルを指定します。 ObjectUuidVecは、オブジェクトUUIDを指定します。

次に、今回のIDLファイルを示します。

[
	uuid (b3413999-1386-4bc0-8329-b5ec82c7eb87),
	version (1.0)
]
interface sample
{
	int ServerFunction(void);
	void Shutdown(void);
}

次に、今回のACFファイルを示します。

[
	implicit_handle(handle_t hBinding)
]
interface sample
{
}

次に、今回のプログラムを示します。 ネームサービスの関数を呼び出す場合は、rpcns4.libへのリンクが必要になります。

#include <windows.h>
#include <rpc.h>
#include "sample_h.h"

#pragma comment (lib, "rpcrt4.lib")
#pragma comment (lib, "rpcns4.lib")

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	WCHAR              szEntryName[] = L"/.:/sample";
	RPC_BINDING_VECTOR *pBindingVector;

	if (RpcServerUseProtseqEpW((USHORT *)L"ncacn_np", 1, (USHORT *)L"\\pipe\\sample", NULL) != RPC_S_OK) {
		MessageBox(NULL, TEXT("プロトコルシーケンスの指定に失敗しました。"), NULL, MB_ICONWARNING);
		return 0;
	}

	RpcServerRegisterIf(sample_v1_0_s_ifspec, NULL, NULL);

	if (RpcServerInqBindings(&pBindingVector) != RPC_S_OK) {
		MessageBox(NULL, TEXT("バインディングの問い合わせに失敗しました。"), NULL, MB_ICONWARNING);
		RpcServerUnregisterIf(NULL, NULL, FALSE);
		return 0;
	}
	
	if (RpcNsBindingExportW(RPC_C_NS_SYNTAX_DEFAULT, (USHORT *)szEntryName, sample_v1_0_s_ifspec, pBindingVector, NULL) != RPC_S_OK) {
		MessageBox(NULL, TEXT("バインディングのエクスポートに失敗しました。"), NULL, MB_ICONWARNING);
		RpcBindingVectorFree(&pBindingVector);
		RpcServerUnregisterIf(NULL, NULL, FALSE);
		return 0;
	}

	if (RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE) != RPC_S_OK) {
		MessageBox(NULL, TEXT("リッスンに失敗しました。"), NULL, MB_ICONWARNING);
		RpcNsBindingUnexportW(RPC_C_NS_SYNTAX_DEFAULT, (USHORT *)szEntryName, sample_v1_0_s_ifspec, NULL);
		RpcBindingVectorFree(&pBindingVector);
		RpcServerUnregisterIf(NULL, NULL, FALSE);
		return 0;
	}
	
	MessageBox(NULL, TEXT("終了します。"), TEXT("OK"), MB_OK);

	RpcNsBindingUnexportW(RPC_C_NS_SYNTAX_DEFAULT, (USHORT *)szEntryName, sample_v1_0_s_ifspec, NULL);
	RpcBindingVectorFree(&pBindingVector);
	RpcServerUnregisterIf(NULL, NULL, FALSE);
	
	return 0;
}

int ServerFunction(void)
{
	return 1;
}

void Shutdown(void)
{
	RpcMgmtStopServerListening(NULL);
}

void __RPC_FAR * __RPC_API midl_user_allocate(size_t len)
{
	return(malloc(len));
}

void __RPC_API midl_user_free(void __RPC_FAR * ptr)
{
	free(ptr);
}

RpcNsBindingExportでエクスポートできる情報は、インターフェース、バインディングベクタ、オブジェクトUUIDの3つです。 バインディングベクタは、RpcServerInqBindingsで取得することができます。 オブジェクトUUIDはオプションであるため、NULLを指定しています。 エントリ名のフォーマットは、szEntryNameの通りです。 sampleの部分は任意の文字列を指定することができます。

ネームサービスにエクスポートされた情報が永続的に存在することに注意してください。 サーバーが終了しても、エクスポートしたエントリが自動で削除されることはありませんから、 サーバーの終了と同時にエントリを削除したい場合は、RpcNsBindingUnexportを呼び出すことになります。 ただし、このように、一時的に情報をエクスポートしたいのであれば、 ネームサービスではなくエンドポイントマッパーを使用したほうがよいでしょう。 基本的に、RpcNsBindingExportはサーバーのインストール時に呼び出し、 RpcNsBindingUnexportはサーバーのアンインストール時に呼び出すものと思われます。

RpcNsBindingExportの処理は、多少の時間が掛かります。 ネームサービスはlocator.exeのことですが、 このサービスはシステムの起動時と同時に開始されるようになっていません。 このため、ネームサービス系の関数を始めて呼び出し時に、 locator.exeが起動されるようなことが起こる得るため、 若干の遅延が発生してしまいます。


戻る