' Visual Basic Script program to reset the DMA status of all ATA drives

' Copyright © 2006 Hans-Georg Michna

' Version 2007-04-04

' Works in Windows XP, probably also in Windows 2000 and NT.
' Does no harm if Windows version is incompatible.

If MsgBox("This program will now reset the DMA status of all ATA drives with Windows drivers." _
  & vbNewline & "Windows will redetect the status after the next reboot, therefore this procedure" _
  & vbNewline & "should be harmless.", _
    vbOkCancel, "Program start message") _
  = vbOk Then

RegPath = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96A-E325-11CE-BFC1-08002BE10318}\"
ValueName1Master = "MasterIdDataChecksum"
ValueName1Slave = "SlaveIdDataChecksum"
ValueName2Master = "UserMasterDeviceTimingModeAllowed"
ValueName2Slave = "UserSlaveDeviceTimingModeAllowed"
ValueName3 = "ResetErrorCountersOnSuccess"
MessageText = "The following ATA channels have been reset:"
MessageTextLen0 = Len(MessageText)
ConsecutiveMisses = 0
Set WshShell = WScript.CreateObject("WScript.Shell")

For i = 0 to 999
  RegSubPath = Right("000" & i, 4) & "\"

  ' Master

  Err.Clear
  On Error Resume Next
  WshShell.RegRead RegPath & RegSubPath & ValueName1Master
  errMaster = Err.Number
  On Error Goto 0
  If errMaster = 0 Then
    On Error Resume Next
    WshShell.RegDelete RegPath & RegSubPath & ValueName1Master
    WshShell.RegDelete RegPath & RegSubPath & ValueName2Master
    On Error Goto 0
    MessageText = MessageText & vbNewLine & "Master"
  End If

  ' Slave

  Err.Clear
  On Error Resume Next
  WshShell.RegRead RegPath & RegSubPath & ValueName1Slave
  errSlave = Err.Number
  On Error Goto 0
  If errSlave = 0 Then
    On Error Resume Next
    WshShell.RegDelete RegPath & RegSubPath & ValueName1Slave
    WshShell.RegDelete RegPath & RegSubPath & ValueName2Slave
    On Error Goto 0
    If errMaster = 0 Then
      MessageText = MessageText & " and "
    Else
      MessageText = MessageText & vbNewLine
    End If
    MessageText = MessageText & "Slave"
  End If

  If errMaster = 0 Or errSlave = 0 Then
    On Error Resume Next
    WshShell.RegWrite RegPath & RegSubPath & ValueName3, 1, "REG_DWORD"
    On Error Goto 0
    ChannelName = "unnamed channel " & Left(RegSubPath, 4)
    On Error Resume Next
    ChannelName = WshShell.RegRead(RegPath & RegSubPath & "DriverDesc")
    On Error Goto 0
    MessageText = MessageText & " of " & ChannelName & ";"
    ConsecutiveMisses = 0
  Else
    ConsecutiveMisses = ConsecutiveMisses + 1
    If ConsecutiveMisses >= 32 Then Exit For ' Don't search unnecessarily long.
  End If
Next ' i

If Len(MessageText) <= MessageTextLen0 Then
  MessageText = "No resettable ATA channels with Windows drivers found. Nothing changed."
Else
  MessageText = MessageText & vbNewline _
    & "Please reboot now to reset and redetect the DMA status."
End If

MsgBox MessageText, vbOkOnly, "Program finished normally"

End If ' MsgBox(...) = vbOk

' End of Visual Basic Script program
