2017-02-23 20 views
1

Hier ist mein Problem: Ich entwickelte einen benutzerdefinierten seriellen Treiber, der auf Microsoft Serenum.sys angewiesen ist, um serielle Anschlüsse aufgezählt zu bekommen. Jetzt habe ich diesen seriellen Treiber auf ein Multifunktionsgerät angewendet, das ein einzelnes Gerät in sechs verschiedene serielle Ports aufteilt - wenn dies passiert, ist die Portnummerierung komplett verschlüsselt, also brauche ich, dass Serial0 zB COM1 bekommt, und so weiter.Wie kann ich eine serielle COM-Portnummer programmgesteuert ändern?

Ich suchte ein wenig, und fand diese: Change COM port via registry, command line or software?

Ich versuchte ComDB zu verwenden, um den Port-Namen zu bekommen, die ich brauche, aber während ich Port-Namen zur Verfügung stellen, kann ich nicht scheinen, ein zu haben effiziente Möglichkeit, einen bestimmten seriellen Port (dh Serial0) mit einer spezifischen COM-Port-Nummer (dh COM1) zu verbinden.

Hat es schon jemand geschafft, dieses Problem zu lösen?

+1

In Zeiten, in denen feste serielle Schnittstellen selten sind und USB-Seriell-Adapter verwendet werden, ist dies ziemlich schwer zu erreichen ...Eine immer noch hässliche, aber wahrscheinlich die beste Lösung ist es, eine Art "Scannen" für Ihr Gerät über alle (derzeit nicht verwendeten) seriellen Schnittstellen zu implementieren (oder natürlich den richtigen zu wählen) – Ctx

+0

Das war ich versuche zu vermeiden . Mein Treiber ist vollständig kompatibel mit den SerialPropPages, so dass Sie den Portnamen wie gewohnt über die Benutzeroberfläche ändern können. Mein Problem ist, dass ich zum Beispiel COM5 zu COM1 umbenennen muss, weil Namen schrecklich gegeben sind. –

+0

Es ist der Treiber für den seriellen Port, der den alten DOS-Namen (wie "COM1") mit IoCreateSymbolicLink() erstellt. Umbenennen ist keine Option. Wenn Sie den Treiber nicht reparieren können, sollten Sie nachsehen. Backgrounder: http://www.osronline.com/article.cfm?id=381 –

Antwort

0

Gelöst in zwei Teilen, mit noch offenen Fragen. vom Fahrer WDK Start Proben auf GitHub, https://github.com/Microsoft/Windows-driver-samples

  1. Auf der SerialReadSymName() Funktion, änderte ich es den symbolischen Namen zurückkehren Ich wollte, anstatt haben sie den Index von ComDB vorgesehen verwenden. Beachten Sie, dass ich Serenum von UpperFilters Schlüssel in der Inf-Datei entfernen musste, damit es damit funktioniert.

  2. Jetzt hatte ich den Arbeitsgerät-Namen (dh. COM1, COM2 usw.), die verwendet werden konnte, aber in diesem Stadium habe ich die serielle Schnittstelle "Friendly Name" sowieso umbenannt. Um dies zu lösen, die kontextuell, ich die SerialCreateOpen() mit dem folgenden Code aktualisiert:

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

Mit der Funktion MySerialSetFriendlyName() wie folgt definiert:

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_... sind Makros, die meine speichern gewählt freundlich Name Präfix (sagen wir L"Communications Port (COM") und Suffix (sagen wir L")". Sie können sie machen, was Sie brauchen, aber Sie müssen wirklich ihre Länge speichern in separaten Makros, dann)

Auf diese Weise würde der freundliche Name beim ersten Gerät geöffnet werden. Um sicher zu gehen, dass das Gerät sofort den richtigen Namen bekommt, habe ich einfach einen Device Coinstaller geschrieben, der auf dem DIF_INSTALLDEVICE Befehl den Port nach der Verarbeitung schnell öffnet und schließt. Dies verdient einen Artikel in sich und es ist einfach genug, also werde ich das jetzt nicht veröffentlichen.

Das einzige offene Problem ist das: - Auf diese Weise speichert ComDB immer noch die falsche Nummerierungssequenz. Sie können es zwingen, sich wie gewünscht zu verhalten, indem Sie die Bitmasken Com Name Arbiter in der Windows-Registrierung ändern, wie in der Verknüpfung in der Frage angegeben, aber Sie können dies nicht für COM1 und COM2 tun, die immer noch an bestimmte E/A-Bereiche gebunden sind und IRQs.

Also, es funktioniert, vorausgesetzt, Sie werden nie auf ComDB in Ihren Anwendungen zugreifen müssen!

Verwandte Themen