2017-02-23 4 views
1

ここに私の問題があります: Microsoft serenum.sysに依存してシリアルポートを列挙するカスタムシリアルドライバを開発しました。今、このシリアルドライバを、6つの異なるシリアルポートで1つのデバイスを分割するマルチファンクションデバイスの上に適用しました。この場合、ポート番号は完全にスクランブルされているので、Serial0はCOM1を取得する必要があります。シリアルCOMポート番号をプログラムで変更するにはどうすればよいですか?

は、私は少しを検索し、これを見つけた: Change COM port via registry, command line or software?

は私が必要とするポート名を取得するためにComDBを使用しようとしましたが、私は可能なポート名を作ることができますが、私は持っていないようですSPECIFICシリアルポート(すなわちSerial0)を特定のCOMポート番号(すなわちCOM1)に関連付けるための効率的な方法です。

すでにこの問題を解決している人はいますか?

+1

固定シリアルポートがまれであり、USBシリアルアダプターが使用される場合、これは達成するのが非常に難しいです...まだ醜いですが、おそらく最良の解決策は、すべての(現在未使用の)シリアルポート(またはユーザーがもちろん正しいものを選択できるようにする)の上にデバイスの "スキャン"を実装することです。 – Ctx

+0

これは避けようとしています。私のドライバはSerialPropPagesと完全に互換性があるので、いつものようにUIでポート名を変更することができます。私の問題は、例えば、名前がひどく与えられているので、COM5からCOM1に名前を変更する必要があるということです。 –

+0

IoCreateSymbolicLink()でレガシーDos名(「COM1」など)を作成するのはシリアルポートドライバです。名前の変更はオプションではありません。ドライバを修正できない場合は、ドライバを調べることを検討してください。 Backgrounder:http://www.osronline.com/article.cfm?id=381 –

答えて

0

未解決の問題があり、2つの部分で解決されました。 GitHubの上のWDKドライバのサンプルから始めて 、SerialReadSymName()機能にhttps://github.com/Microsoft/Windows-driver-samples

  1. は、私が望んでいたシンボリック名を返すのではなく、それはComDBから提供されたインデックスを使用できるようにするには、それを変更しました。私がUpperFiltersのキーからserenumを削除して、このファイルで動作させなければならないことに注意してください。

  2. 私は使用可能な作業デバイス名(すなわちCOM1、COM2など)を持っていましたが、この段階で私はシリアルポート "Friendly Name"の名前を変更しました。

    NTSTATUS MySerialSetFriendlyName(PSERIAL_DEVICE_EXTENSION pDevExt) 
    { 
        NTSTATUS status = STATUS_SUCCESS; 
    
        WCHAR *FriendlyName, *fnprefix, *fnsuffix, *instanceId; 
        ULONG FriendlyNameLength, instanceLength, temp, i; 
    
        fnprefix = BASE_FRIENDLY_NAME_PREFIX_STR; 
        fnsuffix = BASE_FRIENDLY_NAME_SUFFIX_STR; 
    
    
    
        temp = pDevExt->InstanceIdentifier; 
        instanceLength = 0; 
        while (temp) 
        { 
         instanceLength++; 
    
         if (temp < 10) 
          temp = 0; 
         else 
         { 
          temp /= 10; 
          if (!temp) 
           instanceLength++; 
         } 
        } 
    
        if (instanceLength) 
        { 
         instanceId = ExAllocatePool(NonPagedPool, instanceLength); 
         temp = pDevExt->InstanceIdentifier; 
         WCHAR digit = L'X'; 
    
         for (i = 0; i < instanceLength; i++) 
         { 
          switch (temp % 10) 
          { 
          case 0: digit = L'0'; break; 
          case 1: digit = L'1'; break; 
          case 2: digit = L'2'; break; 
          case 3: digit = L'3'; break; 
          case 4: digit = L'4'; break; 
          case 5: digit = L'5'; break; 
          case 6: digit = L'6'; break; 
          case 7: digit = L'7'; break; 
          case 8: digit = L'8'; break; 
          case 9: digit = L'9'; break; 
          default: digit = L'X'; break; 
          } 
    
          instanceId[instanceLength - i - 1] = digit; 
          temp /= 10; 
         } 
    
        FriendlyNameLength = BASE_FRIENDLY_NAME_PREFIX_LEN + instanceLength + BASE_FRIENDLY_NAME_SUFFIX_LEN + 1; 
    
        FriendlyName = ExAllocatePool(NonPagedPool, FriendlyNameLength * sizeof(WCHAR)); 
        RtlZeroMemory(FriendlyName, FriendlyNameLength * sizeof(WCHAR)); 
    
        for (i = 0; i < BASE_FRIENDLY_NAME_PREFIX_LEN; i++) 
        { 
         FriendlyName[i] = fnprefix[i]; 
        } 
    
        for (i = 0; i < instanceLength; i++) 
        { 
         FriendlyName[i + BASE_FRIENDLY_NAME_PREFIX_LEN] = instanceId[i]; 
        } 
    
        for (i = 0; i < BASE_FRIENDLY_NAME_SUFFIX_LEN; i++) 
        { 
         FriendlyName[i + BASE_FRIENDLY_NAME_PREFIX_LEN + instanceLength] = fnsuffix[i]; 
        } 
    
        if (pDevExt->PnpRegistryKey) 
         status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, (PCWSTR)pDevExt->PnpRegistryKey, (PCWSTR)L"FriendlyName", REG_SZ, FriendlyName, FriendlyNameLength * sizeof(WCHAR)); 
        else 
         status = STATUS_INSUFFICIENT_RESOURCES; 
    
        KdPrintEx((DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, "%s :: Changed friendly name to %S (NTSTATUS %08X)\n", __FUNCTION__, FriendlyName, status)); 
    
        if (!NT_SUCCESS(status)) 
        { 
         status = STATUS_SUCCESS; //it is enough that we came through here 
        } 
    } 
    
    return status; 
    } 
    

    BASE_FRIENDLY_NAME_...は私の選択したフレンドリーを保存するマクロですが、次のように定義された関数MySerialSetFriendlyName()

    if (!extension->FriendlyNameSet) //Added this guard to the device extension { DWORD f_set = 1; HANDLE keyHandle; MySerialSetFriendlyName(extension); extension->FriendlyNameSet = TRUE; }

:文脈これを解決するために、私は次のコードでSerialCreateOpen()を更新します名前接頭辞(例:L"Communications Port (COM"と言う)と接尾辞(L")"としましょう。必要なものはすべて作成できますが、実際にはその長さを保存する必要があります別のマクロでは)

このようにして、フレンドリ名は最初のデバイスオープン時に設定されます。すぐにデバイスが正しい名前を取得できることを確認するため、Device Coinstallerを書いて、DIF_INSTALLDEVICEコマンドで、後処理ですぐにポートを開いて閉じました。これは記事そのものにふさわしく、それは十分に簡単なので、私はこれを今公開しません。

唯一の未解決の問題は次のとおりです。 - この方法では、ComDBは引き続き間違った番号付け順序を記憶しています。 Windowsレジストリ内のCom Name Arbiterビットマスクを変更することで、質問に記載されているリンクに指定されているように強制的に動作させることができますが、特定のI/O範囲に依然としてバインドされているCOM1およびCOM2およびIRQ。

したがって、アプリケーションでComDBにアクセスする必要はありません。

関連する問題