CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 18
  1. #1
    Join Date
    Apr 2002
    Location
    Cleveland, Ohio, USA
    Posts
    200

    How do I change a floppy's serial number

    I am working on an application where I need to change the volume id (serial number) of a floppy disk. I have not found a way to do this through the API yet. Can anyone help?

  2. #2
    Join Date
    Apr 2000
    Location
    South Carolina,USA
    Posts
    2,210
    The Volume ID and the Sericl number of any disk are to different aninals. YOu can not change theSerial number. It is hardcoded in the disk.
    The SetVolumeLabel API can be used to change the Volume label
    '
    Public Declare Function SetVolumeLabel Lib "kernel32" _
    Alias "SetVolumeLabelA" _
    (ByVal lpRootPathName As String, _
    ByVal lpVolumeName As String) As Long
    '
    '
    Public Function Label_Disk(ByVal Drive As String, Optional VolLabel As String)
    ' Input looks like "C:\","Label"
    If Right(Drive, 1) <> "\" Then Drive = Drive & "\"
    If VolLabel = "" Then
    Label_Disk = SetVolumeLabel(Drive, vbNullChar)
    Else
    Label_Disk = SetVolumeLabel(Drive, VolLabel)
    End If

    End Function

  3. #3
    Join Date
    Apr 2002
    Location
    Cleveland, Ohio, USA
    Posts
    200
    You are correct that the volume label and serial number are two different items, but I know that it is possible to change the serial number of a floppy, or even a hard disk, because I have found several utilities that do this.

    The problem is that I have to do it from within the application i'm working on.

    Since it is possible, hopefully someone out there knows how to do it...

  4. #4
    Join Date
    Apr 2002
    Posts
    65
    Yeah.. i agree.. im still looking for the way to change floopy serial no.

    everytime i format the diskette, the serial no. will change

  5. #5
    Join Date
    Dec 2001
    Posts
    6,332
    Since it changes when you format the disk, one (cheesy) way to do it for a floppy would be to grab all the data on the disk and store it in a temp file, format the disk, then put the data back.

  6. #6
    Join Date
    Apr 2002
    Location
    Cleveland, Ohio, USA
    Posts
    200
    Unfortunately just copying the data from the disk does not change the serial number.

    I can use GetVolumeInformation to read the serial number, but I need to change it.

    I even have a sample of QBasic code that can do this, but it does not translate well to VB (or at least I don't know how to do that).

    If QBasic could do this, shouldn't there be a way in VB?

  7. #7
    Join Date
    Apr 2002
    Posts
    65
    i found tat Delphi can do it easily too......

    here the code..

    function SetSerial(DiskNum : Byte; var I : TInfoBuffer) : word; assembler;
    asm
    mov ah, 69h
    mov al, 01h
    mov bl, DiskNum
    push ds
    lds dx, I
    int 21h
    pop ds
    jc @bad
    xor ax, ax
    @bad:
    end;




  8. #8
    Join Date
    Apr 2000
    Location
    South Carolina,USA
    Posts
    2,210
    Ron Stone. Post the Qbasic code./ Maybe some one can figure it out.

  9. #9
    Join Date
    Feb 2002
    Location
    Makati City, Philippines
    Posts
    1,054
    I even have a sample of QBasic code that can do this, but it does not translate well to VB (or at least I don't know how to do that).

    If QBasic could do this, shouldn't there be a way in VB?
    I suspect it was written in Assembly language form -- though inserted in QBasic program. I recall, using Data statement in QBasic (which was lost in VB3 to VB6) you can actually write/insert pseudo-assembly code and run it on QBasic allowing it to access DOS system's level.

    If you have this code, please post it here and let's see. If it is in pure QBasic form, I might be able to help because I spent more than 3 years in that language. But if it is in pseudo-Assembly, sorry. That is one thing I didn't learn in QBasic.

    Aio
    Marketing our skills - please participate in the survey and share your insights
    -

  10. #10
    Join Date
    Apr 2002
    Location
    Cleveland, Ohio, USA
    Posts
    200
    Here is the QBasic code I found to change the serial number.

    '===========================================================================
    ' Subject: CHANGE DISK SERIAL NUMBER Date: 09/93 (00:00)
    ' Author: Andy Thomas Code: QB, PDS
    ' Keys: CHANGE,DISK,SERIAL,NUMBER Packet: DISK.ABC
    '===========================================================================
    DEFINT A-Z
    ' Purpose: To change the serial number on any DOS disk.
    ' WARNING THE FOLLOWING PROGRAM USES DIRECT DISK WRITES!
    ' by Andy Thomas 9/93
    ' Author not responsible for misuse or errors of any kind.
    ' Use of this program could, but should not, damage your disk
    ' or render data unusable.
    '$INCLUDE: 'QB.BI'
    ' QB must be started with the /L switch!
    DIM inreg AS RegTypeX, outreg AS RegTypeX
    CLS
    TYPE DiskPacketType
    Sector AS LONG ' DWORD - starting sector number
    CountWrite AS INTEGER ' WORD - Number of sectors affected
    TransAddres AS STRING * 4 ' DWORD - Location of data transfer
    ' Address
    END TYPE
    ' Note: Sector is a LONG while TransAddres is a string
    ' because we know Sector is going to be zero for this program.
    ' In other uses Sector would need to be made a string to avoid
    ' QuickBasic OVERFLOW errors.

    DIM DiskPacket AS DiskPacketType ' Disk Write Packet
    DIM DataStorage AS STRING * 512 ' string to read/write sector

    PRINT "Place disk in drive." ' get drive to change
    PRINT "Enter drive letter:";
    DO
    Drive$ = UCASE$(INKEY$)
    LOOP UNTIL Drive$ <> ""
    PRINT Drive$
    PRINT

    DriveNumb = ASC(Drive$) - 65 ' drive number: A:=0, B:=1....
    inreg.cx = &HFFFF ' Read/Write Absolute Sector
    inreg.ax = DriveNumb ' Drive id
    DiskPacket.Sector = 0 ' start at sector 0
    DiskPacket.CountWrite = 1 ' load one sector

    'DWORD -- Seg:Off of DataStorage
    DiskPacket.TransAddres = CHR$(VARPTR(DataStorage) AND &HFF) +_
    CHR$(((VARPTR(DataStorage) AND &HFF00) \ 256) AND &HFF) +_
    CHR$((VARSEG(DataStorage) AND &HFF)) +_
    CHR$(((VARSEG(DataStorage) AND &HFF00) \ 256) AND &HFF)

    inreg.ds = VARSEG(DiskPacket) ' DS:BX = Disk write packet
    inreg.bx = VARPTR(DiskPacket)

    CALL INTERRUPTX(&H25, inreg, outreg) ' read disk sector

    ' Get serial number from boot sector
    FOR I = &H2B TO &H28 STEP -1
    OldSerial$ = OldSerial$ + HEX$(ASC(MID$(DataStorage, I, 1)))
    IF LEN(OldSerial$) = 4 THEN OldSerial$ = OldSerial$ + "-"
    NEXT I

    PRINT " Old serial number:"; OldSerial$
    LOCATE 5, 1
    PRINT "Enter new serial Number:"

    ' get user input for new serial number
    ' making sure only a valid serial number is entered
    Ptr = 0
    DashAdj = 0
    DO
    DO
    A$ = UCASE$(INKEY$)
    LOOP UNTIL (INSTR("0123456789ABCDEF" + CHR$(8), A$) > 0) AND_
    A$ <> ""
    IF A$ = CHR$(8) THEN ' backspace for corrections
    IF Ptr > 0 THEN
    Ptr = Ptr - 1
    NewSerial$ = LEFT$(NewSerial$, Ptr)
    ELSE
    NewSerial$ = ""
    END IF
    ELSE
    Ptr = Ptr + 1
    NewSerial$ = NewSerial$ + A$
    END IF
    LOCATE 5, 25
    PRINT " "

    LOCATE 5, 25
    PRINT LEFT$(NewSerial$, 4)
    IF Ptr > 4 THEN
    LOCATE 5, 29
    PRINT "-" + MID$(NewSerial$, 5, 8)
    END IF
    LOOP UNTIL Ptr = 8
    Ptr = 0

    ' Convert NewSerial$ into numerical ASCII codes
    ' and save within DataStorage
    FOR I = &H2B TO &H28 STEP -1
    Sbyte = 0
    FOR J = 1 TO 2
    A$ = MID$(NewSerial$, J + Ptr, 1)
    IF ASC(A$) > 64 AND ASC(A$) < 71 THEN Adj = 55 ELSE Adj= 48
    Sbyte = (Sbyte * 16) + (ASC(A$) - Adj)
    NEXT J
    DEF SEG = VARSEG(DataStorage)
    POKE VARPTR(DataStorage) + I - 1, Sbyte
    Ptr = Ptr + 2
    NEXT I

    ' Check to make sure new serial number was placed in
    ' correct location (this is a redundant check for safety)
    FOR I = &H2B TO &H28 STEP -1
    ChkSerial$ = ChkSerial$ + HEX$(ASC(MID$(DataStorage, I, 1)))
    IF LEN(ChkSerial$) = 4 THEN ChkSerial$ = ChkSerial$ + "-"
    NEXT I

    ' confirm change
    PRINT
    PRINT " disk:"; Drive$
    PRINT " from serial number:"; OldSerial$
    PRINT "to new serial number:"; ChkSerial$
    PRINT "Confirm change: (Y/N)"
    DO
    A$ = UCASE$(INKEY$)
    LOOP UNTIL A$ = "Y" OR A$ = "N"
    IF A$ = "Y" THEN ' make the change
    DiskPacket.TransAddres = CHR$(VARPTR(DataStorage) AND &HFF) +_
    CHR$(((VARPTR(DataStorage) AND &HFF00) \ 256) AND &HFF) +_
    CHR$((VARSEG(DataStorage) AND &HFF)) +_
    CHR$(((VARSEG(DataStorage) AND &HFF00) \ 256) AND &HFF)

    inreg.ds = VARSEG(DiskPacket) ' DS:BX = Disk write packet
    inreg.bx = VARPTR(DiskPacket)

    CALL INTERRUPTX(&H26, inreg, outreg) ' write disk sector
    ELSE
    PRINT "Change Aborted."
    END IF

    END

    ' Methodology: The disk serial number is stored as a Double
    ' Word in the boot sector (sector zero) of every disk at
    ' location 27h. This program reads sector zero into a string,
    ' changes the dword value at offset 27h and writes the changed
    ' data back to sector zero. While this program should work, and
    ' has been tested on both hard drives and floppy disks, I
    ' suggest it only be used on floppy drives, as a error
    ' occurring while writing to sector zero on the hard drive
    ' could be disastrous.

  11. #11
    Join Date
    Feb 2002
    Location
    Makati City, Philippines
    Posts
    1,054

    Awwkkkkk

    Awk -- Interrupt handling.

    Though I understand the code very well, I am at a loss. These functions are lost in VB (Var Seg, Poke, VarPtr). I think Interrupt handling was also lost.

    Will check first the (probable) API equivalent. Hope someone here can point the way.

    The program was actually wriiten in QuickBasic -- Not QBasic. They are slightly different. QBasic could not handle this statement:
    Code:
    '$INCLUDE: 'QB.BI'
    QBasic treat it as comment while QuickBasic treat it as compiler directive.
    Last edited by aio; June 8th, 2002 at 10:40 PM.
    Marketing our skills - please participate in the survey and share your insights
    -

  12. #12
    Join Date
    Apr 2002
    Location
    Cleveland, Ohio, USA
    Posts
    200
    Is it not possible tp read and write to sector zero like the above QuickBasic code?

    If I am reading it correctly, that code reads sector zero, chanves the values for the serial number, then writes the sector again.

  13. #13
    Join Date
    Apr 2000
    Location
    South Carolina,USA
    Posts
    2,210
    Using direct Reads and Writes I am sure is forbidden under Windows, at least it willl be available only the priviledged few like Format.
    Qbasic runs under DOS which could care less what Program A does since it is the only program running. Under Windows you can have many programs running at the same time and getting down to that level of modifications could impact many programs and screw up Windows quite badly.
    Don't forget also that you have AntiVirus programs to contend with. Most of them get upset also if you try to screw around with System reserved components.
    '
    You might want to review why you need to do this.

  14. #14
    Join Date
    Apr 2002
    Location
    Cleveland, Ohio, USA
    Posts
    200
    As I stated earlier, I have already found utilities that can modify the floppy's serial number. These programs are doing it under windows without interfering with the operating system or anti-virus software, so maybe they are not using the direct read-write shown in the QuickBasic code above, but there obviously is a way to do it.

    What I need is help with a solution.

  15. #15
    Join Date
    Apr 2002
    Location
    Melbourne, Victoria, Australia
    Posts
    1,792
    I don't think you can use in-line assembler in VB6 - you *might* be able to use it in vb.net. Anyway, to answer your question (theoretically) , the only way I can think of is to create a C/C++ dll using in-line assembler code, exposing the functions as required, then call that dll from your vbcode.

    (MSDN)
    The __asm keyword invokes the inline assembler and can appear wherever a C or C++ statement is legal. It cannot appear by itself. It must be followed by an assembly instruction, a group of instructions enclosed in braces, or, at the very least, an empty pair of braces. The term “__asm block” here refers to any instruction or group of instructions, whether or not in braces.

    The following code fragment is a simple __asm block enclosed in braces:

    __asm
    {
    mov al, 2
    mov dx, 0xD007
    out al, dx
    }

    Alternatively, you can put __asm in front of each assembly instruction:

    __asm mov al, 2
    __asm mov dx, 0xD007
    __asm out al, dx




    As to actually writing the serial no - that's a little beyond me.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured