このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
ドライブの割り当ては、2 種類あった。
ローカルパスとネットワークボリューム。
利用者から見てみれば両者は同じような物だが、
プログラム的に考えると、全く別のものだ。
ローカルパスの割り当ては、
ドライブ(MS-DOS デバイス)に対して、
別のデバイスパスへリンクを定義する作業となり、
DefineDosDevice API を使う。
ネットワークボリュームの割り当ては、
まず、ファイル共有を提供しているサーバに接続し、
そして、その接続をローカルドライブにマッピングする。
これは、LAN Manager 系の NetUseAdd API か、
Windows 系の、WNetAddConnection API を使う。
では、これらをまとめた関数を作ってみよう。
カテゴリは、DriveMap とし、
作成関数を DriveMapCreate と命名する。
========== drivemap.h ==========
/* インクルードガード */
#ifndef drivemap_h_included
#define drivemap_h_included
#include <windows.h>
#include <ole2.h>
/* プロトタイプ定義 */
HRESULT DriveMapCreate(const wchar_t *driveName,
const wchar_t *target);
#endif /* !drivemap_h_included */
========== end of folderlink.h ==========
関数では、Z: などのドライブ名と、
C:\TEMP、\\server\share などのパスを受け取り、
パスに応じて自動的に API を切り替えるようにしよう。
NetUseAdd と WNetAddConnection は歴史が違うだけで、
どちらを使っても構わない。
まあ、WNetAddConnection の方が簡単なのでこっちにする。
========== drivemap.c ==========
#define UNICODE
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include "drivemap.h"
/* wcsncmp */
#include <string.h>
/* WNetAddConnection */
#include <winnetwk.h>
HRESULT DriveMapCreate(const wchar_t *driveName,
const wchar_t *target) {
/* 先頭が \\ で始まるなら */
if (wcsncmp(target, L"\\\\", 2)) {
/* UNC パス */
return HRESULT_FROM_WIN32(
WNetAddConnection(target, NULL, driveName));
} else {
/* ローカルパス */
if (!DefineDosDevice(0, driveName, target))
return HRESULT_FROM_WIN32(GetLastError());
return S_OK;
}
}
========== end of drivemap.c ==========
API が強力なので、拍子抜けするくらい簡単である。
WNetAddConnection も DefineDosDevice も、
パラメータを渡すだけで全てやってくれる。
さて、ネットワーク共有にアクセスする場合は、
通常ユーザ認証を行う必要がある。
WNetAddConnection は、古い API であるため、
Windows 95 のようなパスワードだけの認証が可能だ。
ここでユーザ名を指定することはできない。
今回は、ユーザ認証を行うつもりはないので、
パスワードの部分(第 2 引数)に NULL を指定している。
API で認証情報を指定しなかった場合、
最初にパススルー認証を試すことになっている。
この場合、現在のユーザとパスワードが使われる。
例えば、ドメインに所属しない Windows XP が 2 台あり、
双方に同じパスワードの同じユーザ名を登録しておく。
片方に上記ユーザでログオンして使用しており、
もう一方でファイル共有を開始しているとすると、
ログオンユーザは、確認なしにもう一方にアクセスできる。
これが、パススルー認証という機能だ。
上で作った関数の場合は、パススルーのみをサポートする。
利用者と異なるユーザ名やパスワードを入力させる場合は、
NetUseAdd や、WNetAddConnection2 等を使う必要がある。