//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtPropertiesInit -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus DtPropertiesInit(DtPropertyData* pPropData) { Int Index; // Default no property store found for our device pPropData->m_pPropertyStore = NULL; // Find the property store for our device for (Index=0; Index<DtPropertyStoreCount; Index++) { if (DtPropertyStores[Index].m_TypeNumber==pPropData->m_TypeNumber && DtPropertyStores[Index].m_SubDvc == pPropData->m_SubDvc) { pPropData->m_pPropertyStore = (void*)&DtPropertyStores[Index]; break; } } // Check if we found a property store for our device if (pPropData->m_pPropertyStore == NULL) { DtDbgOut(ERR, PROP, "PropertyStore not found DTA %d, SubDvc %d", pPropData->m_TypeNumber, pPropData->m_SubDvc); return DT_STATUS_NOT_FOUND; } pPropData->m_PropertyNotFoundCounter = 0; return DtStringAlloc(&pPropData->m_PropertyNotFoundString, 50); }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- CheckAndCreateRegistryPath -.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // DtStatus CheckAndCreateRegistryPath( WDFDRIVER Driver, DtString* pItemPath) { DtStringChar* pRegistryPath; DtString RegistryPath; DtString FullKeyName; UInt PathLength; DtStatus Status; Int i; DT_STRING_DECL(ParamItemName, "\\Parameters"); // Build the full path pRegistryPath = WdfDriverGetRegistryPath(Driver); PathLength = wcslen(pRegistryPath); DT_STRING_INIT_CONST(RegistryPath, pRegistryPath, PathLength); // Allocate a new DtString buffer for the complete path inclusive a '\0' character and // extra '\' if (!DT_SUCCESS(DtStringAlloc(&FullKeyName, PathLength+ DtStringGetStringLength(&ParamItemName)+ DtStringGetStringLength(pItemPath)+2))) return STATUS_NO_MEMORY; DtStringAppendDtString(&FullKeyName, &RegistryPath); DtStringAppendDtString(&FullKeyName, &ParamItemName); if (RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer) != STATUS_SUCCESS) RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer); Status = DT_STATUS_OK; i = 1; // Get all subitems from pItemPath and check if the registry entry exist. // If not, create the registry entry. // This function is needed, because Wuindows only allows us to create one registry entry // at a time and not a complete path. while (Status == DT_STATUS_OK) { DtStringAppendChars(&FullKeyName, "\\"); Status = DtStringAppendSubstring(&FullKeyName, pItemPath, i, '\\'); if (DT_SUCCESS(Status)) { if (RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer) != STATUS_SUCCESS) RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, FullKeyName.Buffer); } i++; } DtStringFree(&FullKeyName); return DT_STATUS_OK; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtNonVolatileSettingsWrite -.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // DtStatus DtNonVolatileSettingsWrite( DtDrvObject* pDrvObj, UInt64 DvcSerial, Int Port, Char* pCategory, Char* pName, Int64 BinValue, Char* pStrValue) { DtStatus Status = DT_STATUS_OK; #ifdef WINBUILD // Windows uses the registry to store non volatile settings NTSTATUS NtStatus; DtString RegKeyName; DtString ValueName; // Allocate RegKeyName buffer Status = DtStringAlloc(&RegKeyName, 150); if (DT_SUCCESS(Status)) { Status = DtStringAlloc(&ValueName, 50); if (DT_SUCCESS(Status)) { // Create registry path string Status = PathAppendSettingsSerialPortCategory(&RegKeyName, DvcSerial, Port, pCategory); if (DT_SUCCESS(Status)) { // Convert value name to DtString Status = DtStringAppendChars(&ValueName, pName); if (DT_SUCCESS(Status)) { if (pStrValue!=NULL) { DtString StrValue; Status = DtStringAlloc(&StrValue, 50); if (DT_SUCCESS(Status)) { // Convert value to DtString Status = DtStringAppendChars(&StrValue, pStrValue); if (DT_SUCCESS(Status)) { // Write register string value NtStatus = DriverParametersKeyWrite(pDrvObj->m_WdfDriver, &RegKeyName, &ValueName, -1, &StrValue); } // Free ValueName DtStringFree(&StrValue); } } else { // Write register binary value NtStatus = DriverParametersKeyWrite(pDrvObj->m_WdfDriver, &RegKeyName, &ValueName, BinValue, NULL); } if (!NT_SUCCESS(NtStatus)) Status = DT_STATUS_FAIL; } } // Free ValueName DtStringFree(&ValueName); } // Free RegKeyName DtStringFree(&RegKeyName); } #else // Linux can use config files, but they should not be read / write from a kernel // module --> http://www.linuxjournal.com/article/8110 // Maybe use hotplug event in user space to have helper application to perform // driver load and do the initial settings. Helper application can be DtapiService // or a simple script. Status = DT_STATUS_OK; #endif return Status; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtNonVolatileManufSettingsRead -.-.-.-.-.-.-.-.-.-.-.-.-.-. // // Read a registry key from the manufacturing section, e.g. from // ../Dta/Parameters/Settings/Manuf/2137/ForcedHardwareRevision // DtStatus DtNonVolatileManufSettingsRead( DtDrvObject* pSalDrvObj, Int Type, Char* pName, Int64* pBinValue) { DtStatus Status = DT_STATUS_OK; #ifdef WINBUILD // Windows uses the registry to store non volatile settings NTSTATUS NtStatus; DtString RegKeyName; DtString ValueName; // Allocate RegKeyName buffer Status = DtStringAlloc(&RegKeyName, 150); if (DT_SUCCESS(Status)) { Status = DtStringAlloc(&ValueName, 40); if (DT_SUCCESS(Status)) { // Create registry path string DT_STRING_DECL(SettingsStr, "Settings\\Manuf\\"); // Registry path starts with <\Settings\Manuf\> Status = DtStringAppendDtString(&RegKeyName, &SettingsStr); if (DT_SUCCESS(Status) && Type!=-1) // Convert type to unicode string and append to path Status = DtStringUIntegerToDtStringAppend(&RegKeyName, 10, (UInt)(Type)); if (DT_SUCCESS(Status)) { // Convert value name to DtString Status = DtStringAppendChars(&ValueName, pName); if (DT_SUCCESS(Status)) { // Read register binary value NtStatus = DriverParametersKeyRead(pSalDrvObj->m_WdfDriver, &RegKeyName, &ValueName, pBinValue, NULL); if (!NT_SUCCESS(NtStatus)) { Status = DT_STATUS_FAIL; // Be more specific if object name was not found if (NtStatus == STATUS_OBJECT_NAME_NOT_FOUND) Status = DT_STATUS_NOT_FOUND; } } } // Free ValueName DtStringFree(&ValueName); } // Free RegKeyName DtStringFree(&RegKeyName); } #else // Not yet implemented in Linux. Status = DT_STATUS_NOT_FOUND; #endif return Status; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtNonVolatileSettingsDelete -.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // DtStatus DtNonVolatileSettingsDelete( DtDrvObject* pDrvObj, UInt64 DvcSerial, UInt NumPorts) { DtStatus Status = DT_STATUS_OK; #ifdef WINBUILD NTSTATUS NtStatus; DtString RegKeyName; Int i; // Allocate RegKeyName buffer Status = DtStringAlloc(&RegKeyName, 150); if (!DT_SUCCESS(Status)) return Status; // Remove all port settings for (i = 0; i < (Int)NumPorts; i++) { Status = DtStringClear(&RegKeyName); if (!DT_SUCCESS(Status)) { DtStringFree(&RegKeyName); return Status; } Status = PathAppendSettingsSerialPortCategory(&RegKeyName, DvcSerial, i, NULL); if (!DT_SUCCESS(Status)) { DtStringFree(&RegKeyName); return Status; } // First delete all subitems of PortX (=Categories) NtStatus = DriverParametersSubKeyDelete(pDrvObj->m_WdfDriver, &RegKeyName); // Delete registry item: PortX NtStatus = DriverParametersKeyDelete(pDrvObj->m_WdfDriver, &RegKeyName); } // Remove the device settings Status = DtStringClear(&RegKeyName); if (!DT_SUCCESS(Status)) { DtStringFree(&RegKeyName); return Status; } Status = PathAppendSettingsSerialDeviceCategory(&RegKeyName, DvcSerial, NULL); if (!DT_SUCCESS(Status)) { DtStringFree(&RegKeyName); return Status; } // First delete all subitems of device(=Categories) NtStatus = DriverParametersSubKeyDelete(pDrvObj->m_WdfDriver, &RegKeyName); // Delete registry item: Device NtStatus = DriverParametersKeyDelete(pDrvObj->m_WdfDriver, &RegKeyName); // Now remove the serial number Status = DtStringClear(&RegKeyName); if (!DT_SUCCESS(Status)) { DtStringFree(&RegKeyName); return Status; } // Create path without port number Status = PathAppendSettingsSerialPortCategory(&RegKeyName, DvcSerial, -1, NULL); if (!DT_SUCCESS(Status)) { DtStringFree(&RegKeyName); return Status; } // Delete registry item: serial number NtStatus = DriverParametersKeyDelete(pDrvObj->m_WdfDriver, &RegKeyName); if (!NT_SUCCESS(NtStatus)) { DtStringFree(&RegKeyName); return DT_STATUS_FAIL; } DtStringFree(&RegKeyName); #else // Not yet implemented in Linux. Status = DT_STATUS_OK; #endif return Status; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DriverParametersSubKeyDelete -.-.-.-.-.-.-.-.-.-.-.-.-.-.- // NTSTATUS DriverParametersSubKeyDelete( WDFDRIVER Driver, DtString* pKeyName) { NTSTATUS NtStatus = STATUS_SUCCESS; DtStringChar* pRegistryPath; DtString RegistryPath; DtString FullKeyName; UInt PathLength; HANDLE hKey; OBJECT_ATTRIBUTES ObjectAttributes; KEY_BASIC_INFORMATION* pKeyInfo; ULONG Size; ULONG ResultSize; Int Index; DT_STRING_DECL(ParamItemName, "\\Parameters\\"); DT_ASSERT(KeGetCurrentIrql()<=PASSIVE_LEVEL); // Build the full path pRegistryPath = WdfDriverGetRegistryPath(Driver); PathLength = wcslen(pRegistryPath); DT_STRING_INIT_CONST(RegistryPath, pRegistryPath, PathLength); // Allocate struct for key information result Size = sizeof(KEY_BASIC_INFORMATION)+100; pKeyInfo = DtMemAllocPool(DtPoolNonPaged, Size, SAL_TAG); if (pKeyInfo == NULL) return STATUS_NO_MEMORY; // Allocate a new DtString buffer for the complete path inclusive a '\0' character // and extra '\\' if (!DT_SUCCESS(DtStringAlloc(&FullKeyName, PathLength+ DtStringGetStringLength(&ParamItemName)+ DtStringGetStringLength(pKeyName)+ 100+1+1))) { DtMemFreePool(pKeyInfo, SAL_TAG); return STATUS_NO_MEMORY; } DtStringAppendDtString(&FullKeyName, &RegistryPath); DtStringAppendDtString(&FullKeyName, &ParamItemName); DtStringAppendDtString(&FullKeyName, pKeyName); // Initialize key to open InitializeObjectAttributes(&ObjectAttributes, &FullKeyName, OBJ_KERNEL_HANDLE, NULL, NULL); NtStatus = ZwOpenKey(&hKey, KEY_ENUMERATE_SUB_KEYS , &ObjectAttributes); if (NT_SUCCESS(NtStatus)) { Index = 0; NtStatus = STATUS_SUCCESS; // Enumerate all keys while (NtStatus != STATUS_NO_MORE_ENTRIES) { NtStatus = ZwEnumerateKey(hKey, Index, KeyBasicInformation, pKeyInfo, Size, &ResultSize); if (NT_SUCCESS(NtStatus)) { DtString SubKey; // Build key to delete pKeyInfo->Name[pKeyInfo->NameLength/2] = L'\0'; DT_STRING_INIT_CONST(SubKey, pKeyInfo->Name, ((USHORT)pKeyInfo->NameLength/2)); DtStringClear(&FullKeyName); DtStringAppendDtString(&FullKeyName, pKeyName); DtStringAppendChars(&FullKeyName, "\\"); DtStringAppendDtString(&FullKeyName, &SubKey); DtDbgOut(MAX, SAL, "Delete SubKey %S.", FullKeyName.Buffer); NtStatus = DriverParametersKeyDelete(Driver, &FullKeyName); if (!NT_SUCCESS(NtStatus)) DtDbgOut(ERR, SAL, "Error deleting SubKey %S. Error: %x", FullKeyName.Buffer, NtStatus); } // In case deletion failed, skip this entry if (!NT_SUCCESS(NtStatus)) Index++; } NtStatus = ZwDeleteKey(hKey); ZwClose(hKey); } DtMemFreePool(pKeyInfo, SAL_TAG); DtStringFree(&FullKeyName); return NtStatus; }