ISO Maker / CD/DVD Checker

Share your advanced PureBasic knowledge/code with the community.
peterb
User
User
Posts: 60
Joined: Sun Oct 02, 2005 8:55 am
Location: Czech Republic
Contact:

ISO Maker / CD/DVD Checker

Post by peterb »

Simple CD/DVD Checker and ISO Maker with GUI :D

2007.02.18 - fixed small bug ( Str( dg\DiskSize ) -> StrQ( dg\DiskSize ) )

Code: Select all

;- Author   : Petr Vavrin (peterb)
;- Location : Czech Republic

Structure DISK_GEOMETRY 
   Cylinders.q 
   MediaType.l 
   TracksPerCylinder.l 
   SectorsPerTrack.l 
   BytesPerSector.l 
EndStructure 

Structure DISK_GEOMETRY_EX 
  geometry.DISK_GEOMETRY 
  DiskSize.q 
  byte.b[1]; 
EndStructure 

#IOCTL_DISK_BASE        = 7 
#METHOD_BUFFERED        = 0
#FILE_ANY_ACCESS        = 0

#FILE_READ_ACCESS       = 1
#FILE_DEVICE_CD_ROM     = 2
#IOCTL_CDROM_BASE       = #FILE_DEVICE_CD_ROM 

#boxes                  = 1000
#box_width              = 7
#box_height             = 7
#box_distance           = 2

#boxes_width            = 290
#boxes_height           = 290

#cols                   = #boxes_width / (#box_width + #box_distance)

Global boxes_left.l
Global boxes_top.l
Global boxes_image_background.l = RGB (250, 250, 250)

Global box_blank_background.l   = RGB (240, 240, 240)
Global box_blank_outline.l      = RGB (220, 220, 220)

Global box_set_background.l     = RGB (  0, 255,   0)
Global box_set_outline.l        = RGB (100, 255, 100)

Global box_error_background.l   = RGB (255,   0,   0)
Global box_error_outline.l      = RGB (255, 100, 100)

Enumeration
  #main_window
  #boxes_gadget
  #boxes_image
  #OutputFile
  #BrowseOutput
  #Drive_Combo
  #Start
  #State
  #Check_Only
  #Disk_Size
  #Sectors
  #Actual_Sector
  #Percents
  #Error_List
  #Wrong_Sectors
  #File
  #Exit
EndEnumeration

Macro IIf (expr, truepart, falsepart)
  If expr : truepart : Else : falsepart : EndIf
EndMacro

Procedure make_blank_box ()

  If StartDrawing(ImageOutput(#boxes_image))
    For box_number = 0 To #boxes - 1

      x = #box_distance + ((box_number % #cols) * (#box_width  + #box_distance))
      y = #box_distance + ((box_number / #cols) * (#box_height + #box_distance))
      
      Box(x,     y,     #box_width,     #box_height,     box_blank_outline)
      Box(x + 1, y + 1, #box_width - 2, #box_height - 2, box_blank_background)

    Next

    StopDrawing()
    SetGadgetState(#boxes_gadget, ImageID(#boxes_image))
  EndIf  

EndProcedure

Procedure change_box_state (box_number, type.s)
  
  box_number = box_number - 1
  
  If StartDrawing(ImageOutput(#boxes_image))

    x = #box_distance + ((box_number % #cols) * (#box_width  + #box_distance))
    y = #box_distance + ((box_number / #cols) * (#box_height + #box_distance))
    
    outline    = RGB (255, 255, 255)
    background = RGB (255, 255, 255)
    
    Select type
      Case "blank"
        outline    = box_blank_outline
        background = box_blank_background

      Case "set"
        outline    = box_set_outline
        background = box_set_background
        
      Case "error"
        outline    = box_error_outline
        background = box_error_background
      
    EndSelect
    
    Box(x,     y,     #box_width,     #box_height,     outline)
    Box(x + 1, y + 1, #box_width - 2, #box_height - 2, background)

    StopDrawing()
    SetGadgetState(#boxes_gadget, ImageID(#boxes_image))

  EndIf

EndProcedure

Procedure.s Make_ISO ()

  make_blank_box ()
  ClearGadgetItemList( #Error_List )
  
  drive.s = GetGadgetText ( #Drive_Combo )
  return_state.s = "Finished"

  If GetDriveType_( drive + "\" ) <> #DRIVE_CDROM
    return_state = "Selected drive is not CD-ROM / DVD-ROM"

  Else  

    dg.DISK_GEOMETRY_EX 

    IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX = ((#IOCTL_CDROM_BASE) << 16) | ((#FILE_READ_ACCESS) << 14) | $50 | #METHOD_BUFFERED
    hDevice = CreateFile_("\\.\\" + drive, #GENERIC_READ, #FILE_SHARE_READ | #FILE_SHARE_WRITE, 0, #OPEN_EXISTING, #FILE_ATTRIBUTE_NORMAL, 0) 
    If Not hDevice 
      return_state = "Can't create handle to device!"
      
    Else
      output_file.s = GetGadgetText ( #OutputFile )
      
      file_status = #True
      If GetGadgetState ( #Check_Only ) = 1
        write = #False
      Else
        write = #True
        
        If Not CreateFile(#File, output_file )
          return_state = "Can't create the output file!"
          file_status = #False
        
        EndIf

      EndIf

      If file_status = #True
        DeviceIoControl_(hDevice, IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX, 0, 0, @dg, SizeOf(dg), @bytesret, 0) 
        If dg\geometry\BytesPerSector = 0
          return_state = "Invalid drive geometry!"
        Else
          
          If write = #False
            SetGadgetText ( #State, "Checking ... " )
          Else
            SetGadgetText ( #State, "Copying ... " )
          EndIf
            
          sectors.l = (dg\DiskSize / dg\geometry\BytesPerSector) - 1 
          bps.l = dg\geometry\BytesPerSector
          is_error = #False
          *pmembuf = AllocateMemory ( bps ) 
          *blank   = AllocateMemory ( bps ) 
            
          SetGadgetText ( #Disk_Size, StrQ( dg\DiskSize ) + " Bytes" ) 
          SetGadgetText ( #Sectors,   Str( sectors + 1 ) ) 
          SetGadgetText ( #Wrong_Sectors, "0" )
  
          For sector = 0 To sectors 
            
            SetGadgetText ( #Actual_Sector,   Str( sector + 1 ) ) 
        
            proz.f = (sector / sectors) * 100
            position = proz * 10
    
            SetGadgetText ( #Percents, StrF(proz, 1) + " %" ) 
    
            If ReadFile_(hDevice, *pmembuf, bps, @ret, 0) = 0 
              is_error = #True
              SetGadgetText (#Wrong_Sectors, Str ( Val ( GetGadgetText ( #Wrong_Sectors ) ) + 1 ) )
              
              AddGadgetItem (#Error_List, -1, GetGadgetText ( #Wrong_Sectors ) + Chr(10) + Str (sector) )
              return_state = "Wrong sectors"
              
              If write = #True
                WriteData(#File, *blank, bps)
              EndIf
          
            Else
              If write = #True
                WriteData(#File, *pmembuf, bps)
              EndIf
  
            EndIf
        
            If position <> last_position Or sector = sectors
                
              If is_error = #True
                change_box_state ( position, "error")
              
              Else
                change_box_state ( position, "set")
               
              EndIf
              is_error = #False
              
            EndIf
              
            last_position = position
              
            Repeat 
              Event = WindowEvent() 
              If Event = #PB_Event_Gadget And EventGadget() = #Start 
                return_state = "Stopped"
                Break 2 
              EndIf 
            Until Not Event 
    
          Next 
          
          FreeMemory(*pmembuf)
          FreeMemory(*blank)
  
        EndIf
        If IsFile(#File)
          CloseFile(#File)
        EndIf        
        
      EndIf
    EndIf
  EndIf
  
  ProcedureReturn return_state

EndProcedure

If OpenWindow(#main_window, 0, 0, 600, 390, "ISO Maker / CD/DVD Checker", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(#main_window))

  TextGadget        (#PB_Any,            10, 15, 60, 20, "Input Drive:")
  ComboBoxGadget    (#Drive_Combo,       80, 10, 70, 100)

  For c = 65 To 90
    If GetDriveType_( Chr(c) + ":\" ) = #DRIVE_CDROM
      AddGadgetItem (#Drive_Combo, -1, Chr(c) + ":")
    EndIf
  Next

  SetGadgetState    (#Drive_Combo, 0)
  
  CheckBoxGadget    (#Check_Only,        180, 12, 150, 20, "Check Only (Don't Copy)")
  TextGadget        (#PB_Any,            410, 15, 150, 20, "Author: Petr Vavrin")
  ButtonGadget      (#Exit,              510, 10,  80, 20, "Exit", #BS_FLAT )
  TextGadget        (#PB_Any,            10,  40,  60, 20, "Output File:")
  StringGadget      (#OutputFile,        80,  35, 420, 20, "", #WS_EX_STATICEDGE | #WS_BORDER)
  ButtonGadget      (#BrowseOutput,      510, 35,  80, 20, "Browse", #BS_FLAT )
  TextGadget        (#PB_Any,            10,  65,  60, 20, "State:")
  TextGadget        (#State,             80,  65, 420, 20, "")
  ButtonGadget      (#Start,             510, 60,  80, 20, "Start", #BS_FLAT )
  
  CreateImage(#boxes_image, #boxes_width, #boxes_height)
  If StartDrawing(ImageOutput(#boxes_image))
    Box(0, 0, #boxes_width, #boxes_width, boxes_image_background)
    StopDrawing()
  EndIf
  
  boxes_left = 10
  boxes_top  = 90

  ImageGadget(#boxes_gadget, boxes_left, boxes_top, #boxes_width, #boxes_height, ImageID(#boxes_image))

  make_blank_box ()
  
  TextGadget        (#PB_Any,            310,   95,  60, 20, "Disk Size:")
  TextGadget        (#PB_Any,            310,  120,  60, 20, "Sectors:")
  TextGadget        (#PB_Any,            310,  145,  75, 20, "Actual Sector:")
  TextGadget        (#PB_Any,            310,  170,  75, 20, "Percents:")
  TextGadget        (#PB_Any,            310,  195,  75, 20, "Wrong Sectors:")
  
  TextGadget        (#Disk_Size,         400,   95,  150, 20, "")
  TextGadget        (#Sectors,           400,  120,  150, 20, "")
  TextGadget        (#Actual_Sector,     400,  145,  150, 20, "")
  TextGadget        (#Percents,          400,  170,  150, 20, "")
  TextGadget        (#Wrong_Sectors,     400,  195,   75, 20, "0")

  ListIconGadget    (#Error_List, 310, 220, 280, 160, "Error #", 100, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_GridLines )
  AddGadgetColumn   (#Error_List, 1, "Sector #", 160):

  Repeat
    Event = WaitWindowEvent()

    If Event = #PB_Event_Gadget
  
      If EventGadget() = #BrowseOutput
        last_path.s = GetPathPart(GetGadgetText(#OutputFile))
        
        IIf ( last_path <> "", StandardFile$ = last_path, StandardFile$ = "C:\" )
        File$ = SaveFileRequester("Please choose file to save", StandardFile$, "ISO (*.iso)|*.iso", 0)
              
        If File$
          If UCase ( GetExtensionPart( File$ ) ) <> "ISO"
            File$ + ".iso"
          EndIf
        
          SetGadgetText( #OutputFile, File$ )
        EndIf
      EndIf 
      
      If EventGadget() = #Start

        SetGadgetText ( #Start, "Stop" )
        DisableGadget ( #OutputFile,    #True ) 
        DisableGadget ( #Drive_Combo,   #True ) 
        DisableGadget ( #Check_Only,    #True ) 
        DisableGadget ( #BrowseOutput,  #True ) 
        SetGadgetText ( #Disk_Size,     " " ) 
        SetGadgetText ( #Sectors,       " " ) 
        SetGadgetText ( #Wrong_Sectors, " " )
        SetGadgetText ( #Actual_Sector, " " ) 
        SetGadgetText ( #Percents,      " " ) 

        state.s = Make_ISO ()

        SetGadgetText ( #Start, "Start" )
        DisableGadget ( #Drive_Combo,  #False ) 
        DisableGadget ( #Check_Only,   #False ) 
        
        If GetGadgetState ( #Check_Only ) = 1
          DisableGadget ( #OutputFile,    #True ) 
          DisableGadget ( #BrowseOutput,  #True )
        Else
          DisableGadget ( #OutputFile,    #False ) 
          DisableGadget ( #BrowseOutput,  #False )
        EndIf
        SetGadgetText ( #State, state )

      EndIf
      
      If EventGadget() = #Check_Only
        If GetGadgetState ( #Check_Only ) = 1
          DisableGadget ( #OutputFile,    #True ) 
          DisableGadget ( #BrowseOutput,  #True )
        Else
          DisableGadget ( #OutputFile,    #False ) 
          DisableGadget ( #BrowseOutput,  #False )
        EndIf          
      EndIf
      
      If EventGadget() = #Exit 
        End
      EndIf

    EndIf
     
   Until Event = #PB_Event_CloseWindow
 EndIf
End

Last edited by peterb on Sun Feb 18, 2007 12:15 pm, edited 1 time in total.
User avatar
bingo
Enthusiast
Enthusiast
Posts: 210
Joined: Fri Apr 02, 2004 12:21 pm
Location: germany/thueringen
Contact:

Post by bingo »

8) great ... !
["1:0>1"]
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

Good to see the IIf macro being used in a real-world app. :)
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
va!n
Addict
Addict
Posts: 1104
Joined: Wed Apr 20, 2005 12:48 pm

Post by va!n »

@peterb:
great work and very good looking and user friendly GUI...

btw, i think IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX should be defined and declared as constant...?

Code: Select all

#IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX  = 147536
va!n aka Thorsten

Intel i7-980X Extreme Edition, 12 GB DDR3, Radeon 5870 2GB, Windows7 x64,
peterb
User
User
Posts: 60
Joined: Sun Oct 02, 2005 8:55 am
Location: Czech Republic
Contact:

Post by peterb »

@va!n: yes, you're right :D
Tranquil
Addict
Addict
Posts: 952
Joined: Mon Apr 28, 2003 2:22 pm
Location: Europe

Post by Tranquil »

Wow!

This is realy great. One hint:

You should change the displaytype of the Disc-Size using StrQ instead of Str like this way:

Code: Select all

 SetGadgetText ( #Disk_Size, StrQ( dg\DiskSize ) + " Bytes" )
So that DVD sizes above 2 Gigs are correctly shown and not as a negative value.
Tranquil
peterb
User
User
Posts: 60
Joined: Sun Oct 02, 2005 8:55 am
Location: Czech Republic
Contact:

Post by peterb »

Tranquil: thanks for suggestion :)
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

peterb;

is that the latest version of the code posted? with the bug fixes?

Good job, thank you :)
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

Another Nominee for best PB code :D
techjunkie
Addict
Addict
Posts: 1126
Joined: Wed Oct 15, 2003 12:40 am
Location: Sweden
Contact:

Post by techjunkie »

Very impressive! and all within 375 LOC... Great work! :D
Image
(\__/)
(='.'=) This is Bunny. Copy and paste Bunny into your
(")_(") signature to help him gain world domination.
JCV
Enthusiast
Enthusiast
Posts: 580
Joined: Fri Jun 30, 2006 4:30 pm
Location: Philippines

Post by JCV »

very nice piece of code! Thanks!
Derek
Addict
Addict
Posts: 2354
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Post by Derek »

Very good, thanks for sharing. :)
johnfermor
User
User
Posts: 29
Joined: Wed Dec 31, 2003 3:17 pm

Post by johnfermor »

Excellent job. This'll be great for non-Nero Burning ROM users to create ISO files for use with DaeMon Tools!

Thanks for sharing!
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Post by Edwin Knoppert »

Great!
But.. can you make iso's from a folder instead?

PS, i'm using cdburnerxp (3.x) for iso's

http://www.cdburnerxp.se/
Post Reply