# 機能設計書 91-RegistryKey

## 概要

本ドキュメントは、VBCorLibライブラリにおけるRegistryKey機能の設計を記述するものである。RegistryKeyは、Windowsレジストリのキーレベルノードを表現し、レジストリキーおよび値の操作を提供するクラスである。

### 本機能の処理概要

RegistryKeyは、Windowsレジストリへのアクセスと操作を提供するクラスである。フォルダに似たキー名の命名規則を使用して、レジストリ内のキーと値を走査および変更することができる。

**業務上の目的・背景**：Windowsアプリケーションでは、設定情報や状態を永続化するためにレジストリを使用することが一般的である。RegistryKeyクラスは、VB6/VBAアプリケーションから.NET互換の方法でレジストリにアクセスする手段を提供し、アプリケーション設定の保存・読み込み、システム構成情報へのアクセスを可能にする。

**機能の利用シーン**：アプリケーション設定の保存・復元、インストール済みソフトウェアの情報取得、システム構成の読み取り、ファイル関連付けの管理、スタートアッププログラムの管理などに使用される。

**主要な処理内容**：
1. サブキーのオープン（OpenSubKey）- 指定されたサブキーを読み取り専用または書き込み可能モードで開く
2. サブキーの作成（CreateSubKey）- 新しいレジストリノードを作成する
3. サブキーの削除（DeleteSubKey/DeleteSubKeyTree）- 既存のキーを単独または再帰的に削除する
4. 値の取得・設定（GetValue/SetValue）- キーの値を読み書きする
5. 値の削除（DeleteValue）- キーから値を削除する
6. キー情報の取得（GetSubKeyNames/GetValueNames/GetValueKind）- サブキー名、値名、値の型を取得する

**関連システム・外部連携**：Windows Registry API（RegOpenKeyEx、RegCreateKeyEx、RegDeleteKey、RegQueryValueEx、RegSetValueEx等）をWindows API経由で呼び出す。

**権限による制御**：Writableパラメータにより読み取り専用/書き込み可能を制御する。システムキーへのアクセスには管理者権限が必要な場合がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | Simply VB Unit Runner | 参照画面 | テストスイート内のRegistryKeyテスト（RegistryKeyTests）の実行 |
| 9 | Simple Registry Browser | 主画面 | レジストリキーの操作（GetSubKeyNames、GetValueNames、GetValue、GetValueKind、OpenSubKey） |

## 機能種別

CRUD操作 / データアクセス

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Name | String | Yes | 開く/作成するサブキーの名前 | キー長は255文字以内 |
| Writable | Boolean | No | 書き込み可能かどうか（デフォルト: False） | - |
| SubKey | String | Yes | 作成/削除するサブキーの名前 | スラッシュは両端からトリミング |
| Value | Variant | Yes | 設定する値 | 型に応じた自動変換 |
| ValueKind | RegistryValueKind | No | 値の種類 | UnknownKind/StringKind/DWordKind/BinaryKind/MultiStringKind/ExpandStringKind/QWordKind |
| Default | Variant | No | 値が存在しない場合のデフォルト値 | - |
| ThrowOnMissingSubKey | Boolean | No | キーが見つからない場合に例外をスローするか | - |

### 入力データソース

- アプリケーションからの直接呼び出し
- Registryクラス経由でのルートキーアクセス

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| RegistryKey | RegistryKey | 開いた/作成したレジストリキーオブジェクト |
| Value | Variant | 取得した値（String/Long/Byte()/String()/Currency） |
| Names | String() | サブキー名または値名の配列 |
| ValueKind | RegistryValueKind | 値の種類を示す列挙値 |
| SubKeyCount | Long | サブキーの数 |
| ValueCount | Long | 値の数 |
| LastWriteTime | CorDateTime | 最終書き込み時刻 |

### 出力先

- 呼び出し元への戻り値
- Windowsレジストリへの書き込み

## 処理フロー

### 処理シーケンス

```
1. キー操作の初期化
   └─ Init: ハンドル、名前、書き込み権限を設定

2. サブキーのオープン
   └─ OpenSubKey: RegOpenKeyExでキーを開き、新しいRegistryKeyを返す

3. 値の読み取り
   └─ GetValue: RegQueryValueExで値を取得し、型に応じて変換

4. 値の書き込み
   └─ SetValue: 型を判定し、適切なRegSetValueExを呼び出す

5. キーのクローズ
   └─ CloseKey: システムキー以外はRegCloseKeyで閉じる
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|OpenSubKey| C[RegOpenKeyEx呼び出し]
    B -->|CreateSubKey| D[RegCreateKeyEx呼び出し]
    B -->|GetValue| E[RegQueryValueEx呼び出し]
    B -->|SetValue| F[値の型を判定]
    C --> G{成功?}
    G -->|Yes| H[RegistryKey生成]
    G -->|No| I[Nothing返却]
    D --> J[RegistryKey生成]
    E --> K[値の型変換]
    F --> L[適切なSetValue呼び出し]
    H --> M[終了]
    I --> M
    J --> M
    K --> M
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-91-01 | 書き込み権限チェック | Writableがfalseの場合、書き込み操作は失敗する | SetValue, CreateSubKey, DeleteSubKey, DeleteValue呼び出し時 |
| BR-91-02 | システムキー保護 | ルートキー（HKEY_*）はCloseKeyで閉じない | CloseKey呼び出し時 |
| BR-91-03 | キー長制限 | キー名の各セグメントは255文字以内 | キー名を含む全操作 |
| BR-91-04 | 値名長制限 | 値名は16383文字以内 | GetValue, SetValue呼び出し時 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

該当なし（レジストリ操作）

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ObjectDisposed | ObjectDisposedException | 閉じられたキーに対する操作 | キーを再度開く |
| UnauthorizedAccess | UnauthorizedAccessException | 書き込み権限がないキーへの書き込み | Writable=Trueでキーを開き直す |
| Arg_RegSubKeyAbsent | ArgumentException | 存在しないサブキーの削除 | キーの存在を確認 |
| Arg_RegKeyStrLenBug | ArgumentException | キー名が長すぎる | キー名を短くする |
| Arg_RegValStrLenBug | ArgumentException | 値名が長すぎる | 値名を短くする |
| InvalidOperation_RegRemoveSubKey | InvalidOperationException | サブキーを持つキーの単純削除 | DeleteSubKeyTreeを使用 |

### リトライ仕様

特になし

## トランザクション仕様

レジストリ操作にはトランザクション機能は提供されない。個別の操作は即座にレジストリに反映される。Flush呼び出しで明示的にディスクへの書き込みを強制できる。

## パフォーマンス要件

- レジストリ操作は一般的に高速（数ミリ秒）
- 大量のサブキー列挙時は処理時間が増加する可能性がある
- Flushの過度な呼び出しはシステム性能に影響を与える

## セキュリティ考慮事項

- HKEY_LOCAL_MACHINE配下への書き込みには管理者権限が必要
- 機密情報をレジストリに保存する場合は暗号化を推奨
- レジストリアクセスはシステム監査ログに記録される場合がある

## 備考

- .NET FrameworkのMicrosoft.Win32.RegistryKeyクラスと互換性を持つ設計
- QWord（64ビット整数）の格納にはCurrency型またはInt64 UDTを使用
- Windows 95/98/MEではGetLastWriteTimeはMinValueを返す

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、レジストリ値の型を定義する列挙体を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RegistryKey.cls | `Source/CorLib/Microsoft.Win32/RegistryKey.cls` | RegistryValueKind列挙体（104-112行目）で値の型を定義 |
| 1-2 | RegistryKeyStatic.cls | `Source/CorLib/Microsoft.Win32/RegistryKeyStatic.cls` | RegistryHive列挙体（64-71行目）でルートキーを定義 |

**読解のコツ**: VB6のEnum定義は.NETと同様の構文。UnknownKind=0から始まり、各値型に対応する定数を持つ。

#### Step 2: エントリーポイントを理解する

処理の起点となるRegistryクラス経由でのアクセスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RegistryKeyStatic.cls | `Source/CorLib/Microsoft.Win32/RegistryKeyStatic.cls` | OpenRemoteBaseKey（84-94行目）でリモートレジストリに接続 |

**主要処理フロー**:
1. **84-94行目**: OpenRemoteBaseKey - RegConnectRegistryでリモートレジストリに接続
2. **88行目**: RegConnectRegistry API呼び出し
3. **93行目**: NewRegistryKeyで新しいRegistryKeyオブジェクトを生成

#### Step 3: コア操作を理解する

RegistryKeyクラスの主要メソッドを順に理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RegistryKey.cls | `Source/CorLib/Microsoft.Win32/RegistryKey.cls` | OpenSubKey（144-155行目）でサブキーを開く |
| 3-2 | RegistryKey.cls | `Source/CorLib/Microsoft.Win32/RegistryKey.cls` | GetValue（402-476行目）で値を取得 |
| 3-3 | RegistryKey.cls | `Source/CorLib/Microsoft.Win32/RegistryKey.cls` | SetValue（352-380行目）で値を設定 |

**主要処理フロー**:
- **144-155行目**: OpenSubKey - RegOpenKeyExでキーを開き、成功時にNewRegistryKeyで新オブジェクト生成
- **269-290行目**: GetSubKeyNames - RegEnumKeyExでサブキー名を列挙
- **402-476行目**: GetValue - RegQueryValueExで値を取得し、型に応じて適切なVB型に変換
- **352-380行目**: SetValue - SetValueDirect/SetValueWithConvertで値を書き込み
- **163-168行目**: CloseKey - システムキー以外をRegCloseKeyで閉じる

### プログラム呼び出し階層図

```
Registry（静的クラス）
    │
    └─ RegistryKey.OpenSubKey
           │
           ├─ RegOpenKeyEx（Windows API）
           │
           ├─ RegistryKey.GetValue
           │      └─ RegQueryValueEx（Windows API）
           │
           ├─ RegistryKey.SetValue
           │      └─ RegSetValueEx（Windows API）
           │
           ├─ RegistryKey.GetSubKeyNames
           │      └─ RegEnumKeyEx（Windows API）
           │
           └─ RegistryKey.CloseKey
                  └─ RegCloseKey（Windows API）
```

### データフロー図

```
[入力]                    [処理]                         [出力]

キー名・値名 ────────▶ RegistryKey.OpenSubKey ────────▶ RegistryKeyオブジェクト
                            │
                            ▼
                     RegOpenKeyEx API
                            │
値名・デフォルト ─────▶ RegistryKey.GetValue ──────────▶ Variant（値）
                            │
                            ▼
                     RegQueryValueEx API
                            │
値名・値・型 ─────────▶ RegistryKey.SetValue ──────────▶ レジストリ更新
                            │
                            ▼
                     RegSetValueEx API
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RegistryKey.cls | `Source/CorLib/Microsoft.Win32/RegistryKey.cls` | ソース | レジストリキー操作の実装 |
| RegistryKeyStatic.cls | `Source/CorLib/Microsoft.Win32/RegistryKeyStatic.cls` | ソース | 静的メソッド（OpenRemoteBaseKey） |
| RegistryKeyTests.cls | `Source/Tests/Microsoft.Win32/RegistryKeyTests.cls` | テスト | ユニットテスト |
