wjc826194 发表于 2010-3-1 13:00:13

如何修改卷的序列号?(已解决)

本帖最后由 wjc826194 于 2010-3-2 11:30 编辑

AU3函数中有DriveGetSerial那有没有办法DriveSetSerial呢???高手帮帮忙``WMI似乎也只能读不能改.....

最新情况..在官方论坛找到一个原形作者给出的编译过的文件是可以读取 也可以修改的``
但是给出的源代码却无法读 也无法修改... 源代码如下:#AutoIt3Wrapper_Icon=.\Resources\vsc.ico
#AutoIt3Wrapper_Res_Description=Tool for modify the drive Volume Serial Number
#AutoIt3Wrapper_Res_Fileversion=1.0
#AutoIt3Wrapper_Res_LegalCopyright=Copyright ?R.Gilman (a.k.a. rasim) 2008

#NoTrayIcon

;============# Prevent from secondary run #============================================================
Dim $hMutex = DllCall("kernel32.dll", "hwnd", "OpenMutex", "int", 0x1F0001, "int", False, "str", "VSC")

If $hMutex Then
        WinActivate("VSC v1.0")
        Exit
EndIf

DllCall("kernel32.dll", "hwnd", "CreateMutex", "int", 0, "int", False, "str", "VSC")
;=======================================================================================================

Global Const $INVALID_HANDLE_VALUE = 0xFFFFFFFF

If $CmdLine > 0 Then
        Switch $CmdLine
                Case 1
                        MsgBox(64, "VSC", "Command Line Parameters:" & @LF & @LF & _
                                   "VSC.exe <DriveLetter> <SerialNumber>")
                Case 2
                        If DriveStatus(StringLeft($CmdLine, 1) & ":\") <> "READY" Then
                                MsgBox(16, "VSC error", 'Drive "' & $CmdLine & '" not ready')
                        ElseIf (StringIsXDigit($CmdLine) = 0) Or (StringLen($CmdLine) <> 8) Then
                                MsgBox(16, "VSC error", "Please enter the valid serial number")
                        Else
                                If _SerialNumberSet(StringLeft($CmdLine, 1), StringUpper($CmdLine)) Then
                                        MsgBox(64, "VSC", "Volume Serial Number changed successfully!" & @LF & _
                                                   "Please restart your computer for changes to take effect.")
                                Else
                                        MsgBox(16, "VSC error", "Could not read sector")
                                EndIf
                        EndIf
        EndSwitch
        Exit       
EndIf

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ComboConstants.au3>
#include <EditConstants.au3>

FileInstall(".\Resources\Help\Help.htm", @TempDir & "\Help.htm", 1)
FileInstall(".\Resources\Help\vsc.png", @TempDir & "\vsc.png", 1)
FileInstall(".\Resources\Help\serial.png", @TempDir & "\serial.png", 1)

#Region GUI
$hGUI = GUICreate("VSC v1.0", 340, 238)

$Group = GUICtrlCreateGroup("Info", 11, 10, 320, 90, 0x0300)
GUICtrlSetState(-1, $GUI_FOCUS)

GUICtrlCreateLabel("The format of volume serial number is: XXXX-XXXX, X maybe 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F" & @LF & @LF & _
                                   "Reboot is required for changes to take effect", 20, 30, 300, 55)

GUICtrlCreateGroup("", -99, -99, 1, 1)

GUICtrlCreateLabel("Drive:", 11, 120, 30, 15)

Dim $strDrives = _DriveGetDrive()
Dim $strDefault, $i

For $i = 1 To StringLen($strDrives) Step 2
        $strDefault = StringMid($strDrives, $i, 1)
        If StringRegExp($strDefault, "A|B") = 0 Then ExitLoop
Next

$Drive_Combo = GUICtrlCreateCombo("", 161, 115, 170, 20, BitOR($GUI_SS_DEFAULT_COMBO, $CBS_DROPDOWNLIST))
GUICtrlSetData(-1, $strDrives, $strDefault)

GUICtrlCreateLabel("Current Volume Serial Number:", 11, 147, 150, 15)

Dim $sCurrentSerial = _SerialNumberGet(GUICtrlRead($Drive_Combo))

$CurrentSerial_Input = GUICtrlCreateInput($sCurrentSerial, 161, 142, 170, 20, BitOR($ES_LEFT, $ES_READONLY))

GUICtrlCreateLabel("New Volume Serial Number:", 11, 174, 135, 15)
$NewSerial_Input = GUICtrlCreateInput("", 161, 169, 170, 20, BitOR($ES_LEFT, $ES_UPPERCASE))
GUICtrlSetLimit(-1, 9)

$Change_Button = GUICtrlCreateButton("Change", 11, 204, 75, 23)

$Help_Button = GUICtrlCreateButton("Help", 135, 204, 75, 23)

$Close_Button = GUICtrlCreateButton("Close", 255, 204, 75, 23)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

GUISetState()

_ProcessReduceMemory(@AutoItPID)
#EndRegion GUI
;

While 1
        $msg = GUIGetMsg()
        Switch $msg
                Case $GUI_EVENT_CLOSE, $Close_Button
                        FileDelete(@TempDir & "\Help.htm")
                        FileDelete(@TempDir & "\vsc.png")
                        Exit
                Case $Drive_Combo
                        GUICtrlSetData($CurrentSerial_Input, _SerialNumberGet(GUICtrlRead($Drive_Combo)))
                       
                        If GUICtrlRead($CurrentSerial_Input) = "N/A" Then
                                GUICtrlSetState($NewSerial_Input, $GUI_DISABLE)
                        Else
                                GUICtrlSetState($NewSerial_Input, $GUI_ENABLE)
                        EndIf
                Case $Change_Button
                        $sSerial = GUICtrlRead($NewSerial_Input)
                        If ($sSerial = "") Or (StringLen($sSerial) < 9) Then
                                MsgBox(16, "VSC error", "Please enter the valid serial number", 0, $hGUI)
                                GUICtrlSetState($NewSerial_Input, $GUI_FOCUS)
                        Else
                                If _SerialNumberSet(GuiCtrlRead($Drive_Combo), StringReplace($sSerial, "-", "")) Then
                                        GUICtrlSetData($CurrentSerial_Input, GUICtrlRead($NewSerial_Input))
                                        MsgBox(64, "VSC", "Volume Serial Number changed successfully!" & @LF & _
                                                   "Please restart your computer for changes to take effect.", 0, $hGUI)
                                Else
                                        MsgBox(16, "VSC error", "Could not read sector", 0, $hGUI)
                                EndIf
                        EndIf
                Case $Help_Button
                        ShellExecute(@TempDir & "\Help.htm")
        EndSwitch
WEnd

#Region functions
Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
        Local $iIDFrom = BitAND($wParam, 0x0000FFFF)
        Local $iCode = BitShift($wParam, 16)
       
        Switch $iIDFrom
                Case $NewSerial_Input
                        Switch $iCode
                                Case $EN_UPDATE
                                        Local $iRead = GUICtrlRead($NewSerial_Input)
                                       
                                        If StringIsXDigit($iRead) = 0 Then $iRead = StringRegExpReplace($iRead, "[^A-F0-9]", "")
                                        If (StringLen($iRead) > 4) Then $iRead = StringLeft($iRead, 4) & "-" & StringTrimLeft($iRead, 4)
                                       
                                        GUICtrlSetData($NewSerial_Input, $iRead)
                        EndSwitch
        EndSwitch
       
        Return $GUI_RUNDEFMSG
EndFunc   ;==> WM_COMMAND

Func _DriveGetDrive()
        Local $aDrive = DriveGetDrive("ALL")
        If @error Then Return False
       
        Local $iDriveString, $i
       
        For $i = 1 To $aDrive
                If StringRegExp(DriveGetType($aDrive[$i]), "(?i)Fixed|Removable") Then $iDriveString &= StringLeft(StringUpper($aDrive[$i]), 1) & "|"
        Next
       
        Return StringTrimRight($iDriveString, 1)
EndFunc   ;==> _DriveGetDrive

Func _SerialNumberGet($sDrive)
        Local $hDrive = _CreateFile($sDrive)
        If $hDrive = $INVALID_HANDLE_VALUE Then Return "N/A"
       
        If _SetFilePointer($hDrive) = -1 Then
                _CloseHandle($hDrive)
                Return "N/A"
        EndIf
       
        Local $iReadSector = _ReadFile($hDrive)
        If $iReadSector = 0 Then
                _CloseHandle($hDrive)
                Return "N/A"
        EndIf
       
        _CloseHandle($hDrive)
        Local $iOffset
       
        Switch DriveGetFileSystem($sDrive & ":")
                Case "FAT"
                        $iOffset = Dec("27") * 2 + 2
                Case "FAT32"
                        $iOffset = Dec("43") * 2 + 2
                Case "NTFS"
                        $iOffset = Dec("48") * 2 + 2
                Case Else
                        Return "N/A"
        EndSwitch
       
        Local $strSerial = StringMid($iReadSector, $iOffset + 1, 8)
        Local $iSubString, $iSerial
       
        For $i = 1 To StringLen($strSerial) Step 2
                $iSubString = StringMid($strSerial, $i, 2)
                If $i = 5 Then $iSubString &= "-"
                $iSerial = $iSubString & $iSerial
        Next
       
        Return $iSerial
EndFunc   ;==>_SerialNumberGet

Func _SerialNumberSet($sDrive, $sSerial)
        Local $hDrive = _CreateFile($sDrive)
        If $hDrive = $INVALID_HANDLE_VALUE Then Return False
       
        If _SetFilePointer($hDrive) = -1 Then
                _CloseHandle($hDrive)
                Return False
        EndIf
       
        Local $iReadSector = _ReadFile($hDrive)
        If $iReadSector = 0 Then
                _CloseHandle($hDrive)
                Return False
        EndIf
       
        Local $iOffset
       
        Switch DriveGetFileSystem($sDrive & ":")
                Case "FAT"
                        $iOffset = Dec("27") * 2 + 2
                Case "FAT32"
                        $iOffset = Dec("43") * 2 + 2
                Case "NTFS"
                        $iOffset = Dec("48") * 2 + 2
                Case Else
                        _CloseHandle($hDrive)
                        Return False
        EndSwitch

        Local $iSubString, $iNewSerial, $iWriteResult
       
        For $i = 1 To StringLen($sSerial) Step 2
                $iSubString = StringMid($sSerial, $i, 2)
                $iNewSerial = $iSubString & $iNewSerial
        Next
       
        $iReadSector = StringLeft($iReadSector, $iOffset) & $iNewSerial & StringTrimLeft($iReadSector, $iOffset + 8)
       
        If _SetFilePointer($hDrive) = -1 Then
                _CloseHandle($hDrive)
                Return False
        EndIf
       
        $iWriteResult = _WriteFile($hDrive, $iReadSector)
        _CloseHandle($hDrive)
       
        Return $iWriteResult
EndFunc   ;==>_SerialNumberSet

Func _CreateFile($sDrive)
        Local Const $GENERIC_READ= 0x80000000
        Local Const $GENERIC_WRITE = 0x40000000
       
        Local Const $FILE_SHARE_READ= 0x1
        Local Const $FILE_SHARE_WRITE = 0x2
       
        Local Const $OPEN_EXISTING = 3
       
        Local $szVolumeName = "\\.\" & $sDrive & ":"

        $aRet = DllCall("kernel32.dll", "hwnd", "CreateFile", _
                                                                                                "str", $szVolumeName, _
                                                                                                "int", BitOR($GENERIC_READ, $GENERIC_WRITE), _
                                                                                                "int", BitOR($FILE_SHARE_READ, $FILE_SHARE_WRITE), _
                                                                                                "ptr", 0, _
                                                                                                "int", $OPEN_EXISTING, _
                                                                                                "int", 0, _
                                                                                                "int", 0)
        Return $aRet
EndFunc   ;==>_CreateFile

Func _SetFilePointer($hDrive, $sDistance = 0)
        $aRet = DllCall("kernel32.dll", "int", "SetFilePointer", _
                                                                                        "hwnd", $hDrive, _
                                                                                        "long", $sDistance, _
                                                                                        "ptr", 0, _
                                                                                        "dword", 0)
        Return $aRet
EndFunc   ;==>_SetFilePointer

Func _ReadFile($hDrive)
        Local $lpBUFFER = DllStructCreate("byte")
       
        $aRet = DllCall("kernel32.dll", "int", "ReadFile", _
                                                                                        "hwnd", $hDrive, _
                                                                                        "ptr", DllStructGetPtr($lpBUFFER), _
                                                                                        "dword", 512, _
                                                                                        "dword*", 0, _
                                                                                        "ptr", 0)
        If $aRet = 0 Then Return 0
        Return DllStructGetData($lpBUFFER, 1)
EndFunc   ;==>_ReadFile

Func _WriteFile($hDrive, $sData)
        Local $lpBUFFER = DllStructCreate("byte")
        DllStructSetData($lpBUFFER, 1, $sData)
       
        $aRet = DllCall("Kernel32.dll", "int", "WriteFile", _
                                                                                        "hwnd", $hDrive, _
                                                                                        "ptr", DllStructGetPtr($lpBUFFER), _
                                                                                        "dword", 512, _
                                                                                        "dword*", 0, _
                                                                                        "ptr", 0)
        Return $aRet
EndFunc   ;==>_WriteFile

Func _CloseHandle($hDrive)
        $aRet = DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hDrive)
        Return $aRet
EndFunc   ;==>_CloseHandle

Func _ProcessReduceMemory($iPID)
        Local Const $PROCESS_ALL_ACCESS = 0x1F0FFF
    Local $iProcExists = ProcessExists($iPID) ;To get the PID and check process existence
    Local $hOpenProc, $aResult

    If Not $iProcExists Then Return SetError(1, 0, 0)
    If IsString($iPID) Then $iPID = $iProcExists

    $hOpenProc = DllCall("Kernel32.dll", "int", "OpenProcess", "int", $PROCESS_ALL_ACCESS, "int", False, "int", $iPID)
    $aResult = DllCall("Kernel32.dll", "int", "SetProcessWorkingSetSize", "hwnd", $hOpenProc, "int", -1, "int", -1)
        DllCall("Kernel32.dll", "int", "CloseHandle", "int", $hOpenProc)

    If Not IsArray($aResult) Or $aResult = 0 Then Return SetError(2, 0, 0)
    Return $aResult
EndFunc   ;==>_ProcessReduceMemory
#EndRegion functions

wjc826194 发表于 2010-3-1 13:58:18

希望高手能修改一下....

pusofalse 发表于 2010-3-1 14:13:14

本帖最后由 pusofalse 于 2010-3-1 14:29 编辑

直接读写硬盘分区表。对于FAT32分区,第67~71这4个字节存取分区序列号;对于NTFS分区,序列号则在72~76字节处。
上面的代码不能正常工作,是因为没有先将卷锁定。调用DeviceIoControl函数发送IOCTL_LOCK_VOLUME控制码锁定之后再将新的数据写入。

wjc826194 发表于 2010-3-1 14:50:33

- -!
不会锁...
能不能直接把上面的代码修改一下``????多谢了 `

wjc826194 发表于 2010-3-2 01:15:27

再顶顶 看是否有人帮忙..

pusofalse 发表于 2010-3-2 02:19:58

#include <SetupApi.au3>

Const $IOCTL_LOCK_VOLUME = 0x90018
Const $IOCTL_UNLOCK_VOLUME = 0x9001C
Const $tagDRIVE_PER_SECTOR_DATA = "ubyte SectorData"

Local $hDrive, $iAccessMask, $pBuffer, $pSerial
Local $tBuffer, $tSerial, $sDrive = "C:", $bNewSerial = 0xBEEFBEEF

$iAccessMask = bitOR($GENERIC_READ, $GENERIC_WRITE)
$pBuffer = _CM_Heap_Alloc(512)

Switch DriveGetFileSystem($sDrive)
Case "NTFS"
        $pSerial = $pBuffer + 72
Case "FAT32"
        $pSerial = $pBuffer + 67
Case Else
        _CM_Heap_Free($pBuffer)
        Msgbox(48, "Error!", $sDrive & " not support.")
        exit
EndSwitch

$hDrive = _CM_Create_File("\\.\" & $sDrive, $iAccessMask, 3, 0, 3, 0)
_CM_Device_IO_Control($hDrive, $IOCTL_LOCK_VOLUME, 0, 0, 0, 0)
_CM_Read_Device($hDrive, $pBuffer, 512)
_CM_Device_IO_Control($hDrive, $IOCTL_UNLOCK_VOLUME, 0, 0, 0, 0)
_CM_Close_Handle($hDrive)

$tBuffer = DllStructCreate($tagDRIVE_PER_SECTOR_DATA, $pBuffer)

$tSerial = DllStructCreate("hWnd Serial", $pSerial)
DllStructSetData($tSerial, "Serial", $bNewSerial)

$hDrive = _CM_Create_File("\\.\" & $sDrive, $iAccessMask, 3, 0, 3, 0)
_CM_Device_IO_Control($hDrive, $IOCTL_LOCK_VOLUME, 0, 0, 0, 0)
_CM_Write_Device($hDrive, $pBuffer, 512)
_CM_Device_IO_Control($hDrive, $IOCTL_UNLOCK_VOLUME, 0, 0, 0, 0)
_CM_Close_Handle($hDrive)

Msgbox(64, "", "Done!")
If (DriveGetFileSystem($sDrive) = "NTFS") Then
        Msgbox(48, "", "A system reboot is required to update the serial number.")
EndIf
Opt("TrayIconHide", 1)
ProcessClose(@AutoItPid)

wjc826194 发表于 2010-3-2 04:39:20

缺少2个函数

_CM_Read_Device
_CM_Write_Device

netegg 发表于 2010-3-2 08:06:06

udf区 ---- Au3 硬件设备管理UDF - SetupApi.au3

sdc7 发表于 2012-2-12 09:15:18

P 版 真实 咱论坛的人才 为嘛不进群 胡砍呢

kkkpep 发表于 2019-8-19 13:15:40

下载看看,效果如何
页: [1]
查看完整版本: 如何修改卷的序列号?(已解决)