Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Disk sector Read-Write on any OS

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Disk sector Read-Write on any OS

    Code:
    'http://www.powerbasic.com/support/forums/Forum7/HTML/002659.html
    'Disk sector Read-Write on any OS
     
    'This demo show how to directly access a hard disk under
    'any version of windows... 95, 98, Millenium, NT4, 2000 and XP.
     
    'Use it at your own risk, very easy to destroy hard-disk
    'if you are not familiar with sector disk content.
     
    'Accessing an NT system is fairly easy using CreateFile("\\.\PhysicalDrive...
     
    'Under Windows 9x the process is more complex,
    'a 16 bit DLL is needed, this DLL is compiled via PBDLL 2.0.
     
    'Thank to Semen for GetProcAddressDirectly, witch enable us to find
    'ordinals MS undocumented functions in Kernel32.DLL: LoadLibrary16,
    'FreeLibrary16 and GetProcAddress16 and also Qt_Thunk.
     
    'Int13.DLL routines are: DiskBufferCreate16, DiskBufferRelease16, DiskRead16,
    'DiskWrite16, DiskGeometry16, DiskInt13ExEnable16 and DiskCount16.
     
    'The process is to call GetProcAddressDirectly to get Qt_Thunk
    'to call a 16 bit function in Int13.DLL to call SimRealInt
    'that will call an int 13 bios function who will write his
    'result in a dos buffer accessible to our 32 bit program...
     
    'Note that this program use &h80 for the first
    'hard disk, &h81 for the second, and so on...
     
    'If you don't have PbDLL 2.0, an already compiled version of
    'Int13.DLL can be generated by running code down this post...
    'Note that PbDLL 2.0 was part of PbDLL 6.0, for PbDLL 7 or PbDLL 8,
    'you can purchase it as a separate package from PowerBASIC.
     
    'The exe code can be compiled with PbDLL7 or PbDLL8
    'It will need some modification to run under PbDLL6.
     
    'Thank to Semen Matusovski, William Burns, Lance Edmonds and Edwin Knoppert.
     
    'Have fun
     
    'Pierre
     
    '______________________________________________________________________________
     
    #COMPILE EXE '#Win 801#
    #REGISTER NONE
    #DIM ALL
    #INCLUDE "Win32Api.Inc" '2005/01/14
     
    GLOBAL hDlg                     AS DWORD
    GLOBAL Win9x                    AS DWORD
    GLOBAL SegmentSelectorDosSector AS DWORD
    GLOBAL SegmentSelectorDosPacket AS DWORD
    GLOBAL DosSectorPtr             AS STRING POINTER
    GLOBAL DosPacketPtr             AS STRING POINTER
    GLOBAL Packet                   AS STRING
    GLOBAL hKernel                  AS DWORD
    GLOBAL hInt13                   AS DWORD
    GLOBAL pQtThunk                 AS DWORD
    GLOBAL pLoadLibrary16           AS DWORD
    GLOBAL pGetProcAddress16        AS DWORD
    GLOBAL pFreeLibrary16           AS DWORD
    GLOBAL pGlobalDosFree16         AS DWORD
    GLOBAL pDiskBufferCreate16      AS DWORD
    GLOBAL pDiskBufferRelease16     AS DWORD
    GLOBAL pDiskRead16              AS DWORD
    GLOBAL pDiskWrite16             AS DWORD
    GLOBAL pDiskGeo16               AS DWORD
    GLOBAL pDiskCount16             AS DWORD
    GLOBAL pDiskInt13ExEnable16     AS DWORD
     
    $PacketHeader  = CHR$(16, 0, 1, 0, 0, 0)
    $Int13         = "Int13.DLL"
    $AppName       = "Direct disk Read/Write"
     
    %LabelDisk      = 101
    %LabelDiskCount = 102
    %LabelInt13Ext  = 103
    %LabelLb        = 104
    %LabelCyl       = 105
    %LabelHead      = 106
    %LabelSect      = 107
    %LabelMeg       = 108
    %LabelStatus    = 109
    %ComboDisk      = 201
    %ButtonRead     = 301
    %ButtonReadUp   = 302
    %ButtonReadDwn  = 303
    %ButtonTry      = 304
    %ListboxSect    = 401
    %TextboxLb      = 402
     
    %SectorSize     = 512
    %IOCTL_DISK_GET_DRIVE_GEOMETRY  = &H00070000
     
    TYPE Disk_Geometry_EX
     Cyl  AS DWORD
     Head AS DWORD
     Sect AS DWORD
     Byt  AS DWORD
     Lb   AS QUAD
    END TYPE
     
    TYPE Disk_Geometry
     Cylinders         AS QUAD
     MediaType         AS DWORD
     TracksPerCylinder AS DWORD
     SectorsPerTrack   AS DWORD
     BytesPerSector    AS DWORD
    END TYPE
     
    DECLARE FUNCTION LoadLibrary16(BYVAL DLLFile AS STRING) AS DWORD
    DECLARE FUNCTION FreeLibrary16(BYVAL hDLL AS DWORD) AS DWORD
    DECLARE FUNCTION GetProcAddress16(BYVAL zDLLFile AS DWORD, BYVAL sFunction AS STRING) AS DWORD
    DECLARE FUNCTION DiskBufferCreate16(BYVAL BufferSize AS DWORD) AS DWORD
    DECLARE FUNCTION DiskBufferRelease16(BYVAL SegmentSelector AS DWORD) AS DWORD
    DECLARE FUNCTION DiskRead16(BYVAL Disk AS DWORD, BYVAL SegmentSelectorPacket AS DWORD) AS DWORD
    DECLARE FUNCTION DiskWrite16(BYVAL Disk AS DWORD, BYVAL SegmentSelectorPacket AS DWORD) AS DWORD
    DECLARE FUNCTION DiskGeometry16(BYVAL Disk AS DWORD, BYVAL SegmentSelector AS DWORD) AS DWORD
    DECLARE FUNCTION DiskInt13ExEnable16(BYVAL Disk AS DWORD) AS LONG 'Return %TRUE if present
    'DECLARE FUNCTION GlobalDosAlloc16(BYVAL dwBytes AS DWORD) AS DWORD
    'DECLARE FUNCTION GlobalDosFree16(BYVAL wSelector AS WORD) AS WORD 'Return 0 if success
    '______________________________________________________________________________
     
    FUNCTION IsWin9x() AS LONG
     LOCAL vi AS OSVERSIONINFO
     
     vi.dwOsVersionInfoSize = SIZEOF(vi)
     GetVersionEx vi
     IF vi.dwPlatformId = %VER_PLATFORM_WIN32_WINDOWS THEN FUNCTION = 1
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION GetProcAddressDirectly(BYVAL lpImageDosHeader AS IMAGE_DOS_HEADER PTR, BYREF FuncName AS ASCIIZ) AS DWORD
     'Thank to Semen Matusovski - http://www.powerbasic.com/support/forums/Forum4/HTML/010410.html
     LOCAL lpImageNtHeaders       AS IMAGE_NT_HEADERS PTR
     LOCAL lpImageExportDirectory AS IMAGE_EXPORT_DIRECTORY PTR
     LOCAL lpNameOrdinals         AS WORD PTR
     LOCAL lpFunctions            AS DWORD PTR
     LOCAL lpExpFuncName          AS ASCIIZ PTR
     LOCAL lpName                 AS DWORD PTR
     LOCAL lpFuncName             AS ASCIIZ PTR
     LOCAL i                      AS DWORD
     LOCAL j                      AS DWORD
     
     IF @lpImageDosHeader.e_magic <> %IMAGE_DOS_SIGNATURE THEN FUNCTION = 0 : EXIT FUNCTION 'Invalid DOS signature
     lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
     IF @lpImageNtHeaders.Signature <> %IMAGE_NT_SIGNATURE THEN FUNCTION = 0 : EXIT FUNCTION 'Invalid NT signature
     IF @lpImageNtHeaders.FileHeader.SizeOfOptionalHeader <> SIZEOF(@lpImageNtHeaders.OptionalHeader) OR _
        @lpImageNtHeaders.OptionalHeader.Magic <> %IMAGE_NT_OPTIONAL_HDR32_MAGIC THEN EXIT FUNCTION
     
     lpImageExportDirectory = @lpImageNtHeaders.OptionalHeader.DataDirectory(%IMAGE_DIRECTORY_ENTRY_EXPORT).VirtualAddress
     IF lpImageExportDirectory = 0 THEN EXIT FUNCTION
     lpImageExportDirectory = lpImageExportDirectory + lpImageDosHeader
     
     lpNameOrdinals = @lpImageExportDirectory.AddressOfNameOrdinals + lpImageDosHeader
     lpName         = @lpImageExportDirectory.AddressOfNames        + lpImageDosHeader
     lpFunctions    = @lpImageExportDirectory.AddressOfFunctions    + lpImageDosHeader
     lpFuncName     = VARPTR(FuncName)
     
     IF HIWRD(lpFuncName) THEN 'Function name is ascii
       FOR i = 0 TO @lpImageExportDirectory.NumberOfFunctions - 1
         IF @lpFunctions[i] THEN
           FOR j = 0 TO @lpImageExportDirectory.NumberOfNames - 1
             IF @lpNameOrdinals[j] = i THEN
               lpExpFuncName = @lpName[j] + lpImageDosHeader
               IF @lpExpFuncName = FuncName THEN
                 FUNCTION = @lpFunctions[i] + lpImageDosHeader
                 EXIT FUNCTION
               END IF
             END IF
           NEXT
         END IF
       NEXT
     ELSE 'Function name is ordinal
       FOR i = 0 TO @lpImageExportDirectory.NumberOfFunctions - 1
         IF lpFuncName = @lpImageExportDirectory.nBase + i THEN
           IF  @lpFunctions[i] THEN FUNCTION = @lpFunctions[i] + lpImageDosHeader
           EXIT FUNCTION
         END IF
       NEXT
     END IF
     
    END FUNCTION
    '______________________________________________________________________________
     
    SUB DiskChsToLb(BYVAL Cyl AS DWORD, BYVAL Head AS DWORD, BYVAL Sect AS DWORD, _
                    BYREF Lb AS QUAD, BYREF DiskGeo AS Disk_Geometry_EX)
     'Convert Cylinder, Head, Sector to LogicalBlock
     
     Lb = (Cyl * DiskGeo.Head * DiskGeo.Sect + Head * DiskGeo.Sect) + Sect - 1
     
    END SUB
    '______________________________________________________________________________
     
    SUB DiskLbToChs(BYVAL Lb AS QUAD, BYREF Cyl AS DWORD, BYREF Head AS DWORD, _
                    BYREF Sect AS DWORD, BYREF DiskGeo AS Disk_Geometry_EX)
     'Convert LogicalBlock to Cylinder, Head, Sector
     LOCAL CHS     AS QUAD
     LOCAL HsCount AS QUAD
     
     HsCount = DiskGeo.Head * DiskGeo.Sect
     Cyl = Lb \ HsCount
     CHS = Cyl * HsCount
     Head = (Lb - Chs) \ DiskGeo.Sect
     Sect = Lb - (Chs + Head * DiskGeo.Sect) + 1
     
    END SUB
    '______________________________________________________________________________
     
    FUNCTION DiskCylSectToWord(BYVAL Cyl AS DWORD, BYVAL Sect AS DWORD) AS WORD
     'Convert Cylinder, Sector to int13:08 format
     LOCAL SX AS DWORD
     LOCAL CH AS DWORD
     LOCAL CL AS DWORD
     
     '  +-- Cylinder Lo ----+       +-Sector--+
     '  15 14 13 12 11 10 9 8 - 7 6 5 4 3 2 1 0
     '                   Cyl Hi +-+
     
     FUNCTION = ((Cyl AND 255) * 256) + _
                ((Cyl AND 768) / 4)   + _
                (Sect AND 63)
     
    END FUNCTION
    '______________________________________________________________________________
     
    SUB DiskWordToCylSect(BYVAL CylSect AS DWORD, BYREF Cyl AS DWORD, BYREF Sect AS DWORD)
     'Convert int13:08 result to Cylinder, Sector
     
     '  +-- Cylindre Lo ----+     +-Sector--+
     '  15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
     '                  Cyl Hi+-+
     
     Cyl = ((CylSect AND 192) * 4) + HIBYT(CylSect)
     Sect = (CylSect AND 63)
     
    END SUB
    '______________________________________________________________________________
     
    FUNCTION DiskInit()AS LONG 'Return 0 on success
     'Under Win9x, get all needed function pointers and prepare
     'one DOS buffer for packet and one 512 bytes DOS buffer for sector.
     LOCAL Retval     AS DWORD
     LOCAL PacketSize AS DWORD
     
     hKernel = LoadLibrary("Kernel32.DLL")
     IF hKernel THEN
       pQtThunk          = GetProcAddressDirectly(hKernel, "QT_Thunk")
       pLoadLibrary16    = GetProcAddressDirectly(hKernel, BYVAL MAKDWD(35, 0)) 'LoadLibrary16
       pFreeLibrary16    = GetProcAddressDirectly(hKernel, BYVAL MAKDWD(36, 0)) 'FreeLibrary16
       pGetProcAddress16 = GetProcAddressDirectly(hKernel, BYVAL MAKDWD(37, 0)) 'GetProcAddress16
      'pGlobalDosAlloc16 = GetProcAddressDirectly(hKernel, BYVAL MAKDWD(24, 0)) 'GlobalDosAlloc16
      'pGlobalDosFree16  = GetProcAddressDirectly(hKernel, BYVAL MAKDWD(31, 0)) 'GlobalDosFree16
       IF pGetProcAddress16 = 0 THEN FUNCTION = 1 'Kernel32.DLL error
     
       CALL DWORD pLoadLibrary16 USING LoadLibrary16($Int13) TO hInt13
       CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskBufferCreate16") TO pDiskBufferCreate16
       CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskBufferRelease16") TO pDiskBufferRelease16
       CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskRead16") TO pDiskRead16
       CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskWrite16") TO pDiskWrite16
       CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskGeometry16") TO pDiskGeo16
       CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskInt13ExEnable16") TO pDiskInt13ExEnable16
       CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskCount16") TO pDiskCount16
      'CALL DWORD pGlobalDosAlloc16 USING GlobalDosAlloc16(%SectorSize) TO hGlobalDosAlloc16
      'CALL DWORD pGlobalDosFree16  USING GlobalDosFree16(LOWRD(hGlobalDosAlloc16)) TO hGlobalDosFree16
       IF pDiskCount16 = 0 THEN FUNCTION = 2 'Int13.DLL error
     
       IF pDiskBufferCreate16 THEN
         ! PUSH %SectorSize
         ! MOV  edx, pDiskBufferCreate16
         ! CALL pQtThunk
         ! MOV  SegmentSelectorDosSector, eax
         IF SegmentSelectorDosSector = 0 THEN FUNCTION = 3 'Dos sector buffer allocation error
         DosSectorPtr = HIWRD(SegmentSelectorDosSector) * 16
     
         PacketSize = 16
         ! PUSH PacketSize
         ! MOV  edx, pDiskBufferCreate16
         ! CALL pQtThunk
         ! MOV  SegmentSelectorDosPacket, eax
         IF SegmentSelectorDosPacket = 0 THEN FUNCTION = 4 'Dos packet buffer allocation error
         DosPacketPtr = HIWRD(SegmentSelectorDosPacket) * 16
       END IF
     END IF
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskRelease()AS DWORD
     'Under Win9x, free memory when program terminate.
     LOCAL Retval AS DWORD
     
     ! PUSH SegmentSelectorDosSector
     ! MOV  edx, pDiskBufferRelease16
     ! CALL pQtThunk
     
     ! PUSH SegmentSelectorDosPacket
     ! MOV  edx, pDiskBufferRelease16
     ! CALL pQtThunk
     
     CALL DWORD pFreeLibrary16 USING FreeLibrary16(hInt13) TO Retval
     FreeLibrary hKernel
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskWrite(BYVAL Disk AS DWORD, BYVAL SectorLB AS QUAD, _
                       BYREF Sector AS STRING * %SectorSize)AS LONG
     LOCAL Retval    AS DWORD
     LOCAL DiskError AS DWORD
     LOCAL hDisk     AS DWORD
     LOCAL zDisk     AS ASCIIZ * 30
     LOCAL dwRead    AS DWORD
     LOCAL FilePtr   AS QUAD
     LOCAL Result    AS LONG
     
     'Use at your own risk...
     'Use at your own risk...
     'Use at your own risk...
     EXIT FUNCTION '<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-
     'Use at your own risk...
     'Use at your own risk...
     'Use at your own risk...
     
     IF Win9x THEN  ' - - - - - - - - - - - - - - - - - - - - - - - - - - Windows 95/98/Millenium
     
       'Prepare a packet made of a header, a pointer to a DOS buffer
       'and the target LogicalBlock for int 13:48
       Packet = $PacketHeader & MKWRD$(HIWRD(SegmentSelectorDosSector))& MKQ$(SectorLB)
       POKE$ DosPacketPtr, Packet
       POKE$ DosSectorPtr, Sector
     
       ! PUSH Disk                     'DiskWrite16 first parameter
       ! PUSH SegmentSelectorDosPacket 'DiskWrite16 second parameter
       ! MOV  edx, pDiskWrite16        'DiskWrite16 pointer
       ! CALL pQtThunk                 'Call Qt_Thunk
       ! MOV  DiskError, eax           'DiskWrite16 function result
     
       IF DiskError THEN FUNCTION = %TRUE
     
     ELSE ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows NT/2000/XP
       'zDisk = "\\.\a:"                                  'Logical Disk
       'zDisk = "\\.\c:"                                  'Logical Disk
       zDisk = "\\.\PhysicalDrive" & FORMAT$(Disk - &H80) 'Physical Disk
       hDisk = CreateFile(zDisk, %GENERIC_WRITE, %FILE_SHARE_READ OR _
                                 %FILE_SHARE_WRITE, BYVAL 0, %OPEN_EXISTING, 0, 0 )
       IF hDisk = %INVALID_HANDLE_VALUE THEN
         FUNCTION = %TRUE
       ELSE
         'PBWin8 SetFilePointer hDisk, LO(DWORD, FilePtr), HI(DWORD, FilePtr), %FILE_BEGIN
         FilePtr = SectorLB * %SectorSize
         DIM QuadLoHi(0 TO 1) AS DWORD AT VARPTR(FilePtr)
         SetFilePointer hDisk, QuadLoHi(0), QuadLoHi(1), %FILE_BEGIN
         Result = WriteFile(hDisk, BYVAL VARPTR(Sector), %SectorSize, dwRead, BYVAL %NULL)
         IF Result = 0 THEN FUNCTION = %TRUE 'Error
         CloseHandle hDisk
       END IF
     
     END IF
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskRead(BYVAL Disk AS DWORD, BYVAL SectorLB AS QUAD, _
                      BYREF Sector AS STRING * %SectorSize)AS LONG
     LOCAL DiskError  AS LONG
     LOCAL hDisk      AS DWORD
     LOCAL zDisk      AS ASCIIZ * 30
     LOCAL dwRead     AS DWORD
     LOCAL FilePtr    AS QUAD
     LOCAL Result     AS LONG
     
     IF Win9x THEN ' - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows 95/98/Millenium
     
       'Prepare a packet made of a header, a pointer to a DOS buffer
       'and the target LogicalBlock for int 13:48
       Packet = $PacketHeader & MKWRD$(HIWRD(SegmentSelectorDosSector))& MKQ$(SectorLB)
       POKE$ DosPacketPtr, Packet
       ! PUSH Disk                     'DiskRead16 first parameter
       ! PUSH SegmentSelectorDosPacket 'DiskRead16 second parameter
       ! MOV  edx, pDiskRead16         'DiskRead16 pointer
       ! CALL pQtThunk                 'Call Qt_Thunk
       ! MOV  DiskError, eax           'DiskRead16 function result
     
       IF DiskError THEN
         Sector = ""
       ELSE
         Sector = PEEK$(DosSectorPtr, %SectorSize)
       END IF
       FUNCTION = DiskError '0 for success
     
     ELSE ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows NT/2000/XP
     
       'zDisk = "\\.\a:"                                  'Logical Disk
       'zDisk = "\\.\c:"                                  'Logical Disk
       zDisk = "\\.\PhysicalDrive" & FORMAT$(Disk - &H80) 'Physical Disk
       hDisk = CreateFile(zDisk, %GENERIC_READ, %FILE_SHARE_READ OR _
                                 %FILE_SHARE_WRITE, BYVAL 0, %OPEN_EXISTING, 0, 0 )
       IF hDisk = %INVALID_HANDLE_VALUE THEN
         FUNCTION = %TRUE 'Error
       ELSE
         'PBWin8 SetFilePointer hDisk, LO(DWORD, FilePtr), HI(DWORD, FilePtr), %FILE_BEGIN
         FilePtr = SectorLB * %SectorSize
         DIM QuadLoHi(0 TO 1) AS DWORD AT VARPTR(FilePtr)
         SetFilePointer hDisk, QuadLoHi(0), QuadLoHi(1), %FILE_BEGIN
         Result = ReadFile(hDisk, BYVAL VARPTR(Sector), %SectorSize, dwRead, BYVAL %NULL)
         IF Result THEN
           IF dwRead <> %SectorSize THEN
             Sector = STRING$(%SectorSize, 0)
             FUNCTION = %TRUE
           END IF
         ELSE
           Sector = STRING$(%SectorSize, 0)
           FUNCTION = %TRUE
         END IF
         CloseHandle hDisk
       END IF
     
     END IF
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskInt13ExEnable(BYVAL Disk AS DWORD) AS DWORD
     LOCAL RegEAX AS DWORD
     
     IF Win9x THEN
       ! PUSH Disk                      'DiskInt13ExEnable parameter
       ! MOV  edx, pDiskInt13ExEnable16 'DiskInt13ExEnable pointer
       ! CALL pQtThunk                  'Call Qt_Thunk
       ! MOV  RegEAX, eax               'DiskInt13ExEnable function result
       FUNCTION = RegEAX
     END IF
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskGeometryGet(BYVAL Disk AS DWORD, BYREF DiskGeo AS Disk_Geometry_EX) AS LONG
     LOCAL Retval     AS DWORD
     LOCAL RegEAX     AS DWORD
     LOCAL OldErrMode AS LONG
     LOCAL hFile      AS DWORD
     LOCAL DiskGeoNT  AS Disk_Geometry
     LOCAL DiskGeo48  AS Disk_Geometry_Ex
     
     IF Win9x THEN ' - - - - - - - - - - - - - - - - - - - - - - - - - - Windows 95/98/Millenium
     
       ! PUSH Disk                     'DiskGeo16 first parameter
       ! PUSH SegmentSelectorDosSector 'DiskGeo16 second parameter
       ! MOV  edx, pDiskGeo16          'DiskGeo16 pointer
       ! CALL pQtThunk                 'Call Qt_Thunk
       ! MOV  RegEAX, eax              'DiskGeo16 function result
     
       IF RegEAX = 0 THEN
         'PBWin8 DiskWordToCylSect(PEEK(WORD, DosSectorPtr + 70), DiskGeo.Cyl, DiskGeo.Sect)
         DiskWordToCylSect CVWRD(PEEK$(DosSectorPtr + 70, 2)), DiskGeo.Cyl, DiskGeo.Sect
         INCR DiskGeo.Cyl
         'PBWin8 DiskGeo.Head = PEEK(BYTE, DosSectorPtr + 73) + 1
         DiskGeo.Head = PEEK(DosSectorPtr + 73) + 1
         '-> MSGBOX "DiskCount = " & STR$(PEEK(BYTE, DosSectorPtr + 72)), %MB_ICONINFORMATION
         CONTROL SET TEXT hDLG, %LabelInt13Ext, "Int 13 ext: no"
     
         IF DiskInt13ExEnable(Disk) THEN
           CONTROL SET TEXT hDLG, %LabelInt13Ext, "Int 13 ext: yes"
           'PBWin8 DiskGeo48.Cyl  = PEEK(DWORD, DosSectorPtr + 4)
           DiskGeo48.Cyl  = CVDWD(PEEK$(DosSectorPtr + 4, 4))
           'PBWin8 DiskGeo48.Head = PEEK(DWORD, DosSectorPtr + 8)
           DiskGeo48.Head = CVDWD(PEEK$(DosSectorPtr + 8, 4))
           'PBWin8 DiskGeo48.Sect = PEEK(DWORD, DosSectorPtr + 12)
           DiskGeo48.Sect = CVDWD(PEEK$(DosSectorPtr + 12, 4))
           'PBWin8 DiskGeo48.LB   = PEEK(QUAD, DosSectorPtr + 16, 8)
           DiskGeo48.LB = CVQ(PEEK$(DosSectorPtr + 16, 8))
           DiskGeo.Cyl  = DiskGeo48.Lb \ (DiskGeo.Head * DiskGeo.Sect)
           DiskGeo.Lb   = DiskGeo.Cyl * DiskGeo.Head * DiskGeo.Sect 'Cut unused end sectors
           '-> DiskGeo.Lb   = DiskGeo48.Lb 'Leave unused end sectors
         END IF
       ELSE
         FUNCTION = %TRUE 'Error
       END IF
     
     ELSE ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows NT/2000/XP
     
       OldErrMode = SetErrorMode(%SEM_FAILCRITICALERRORS)'Prevent pop-up dialogs if device is not present or loaded
       hFile = CreateFile("\\.\PHYSICALDRIVE" & FORMAT$(Disk - &h80), 0, %FILE_SHARE_READ OR _
                          %FILE_SHARE_WRITE, BYVAL 0&, %OPEN_EXISTING, 0, BYVAL 0&)
       IF hFile <> %INVALID_HANDLE_VALUE THEN
         IF DeviceIoControl(hFile, %IOCTL_DISK_GET_DRIVE_GEOMETRY, BYVAL 0, _
                            BYVAL 0, DiskGeoNT, SIZEOF(DiskGeoNT), 0, BYVAL 0& ) THEN
           DiskGeo.Cyl  = DiskGeoNT.Cylinders
           DiskGeo.Head = DiskGeoNT.TracksPerCylinder
           DiskGeo.Sect = DiskGeoNT.SectorsPerTrack
           DiskGeo.LB   = DiskGeo.Cyl * DiskGeo.Head * DiskGeo.Sect
         ELSE
           FUNCTION = %TRUE
         END IF
       ELSE
         FUNCTION = %TRUE
       END IF
       CloseHandle hFile
       SetErrorMode OldErrMode
     
     END IF
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskCountGet() AS DWORD
     LOCAL DiskCount AS DWORD
     LOCAL DiskGeo   AS Disk_Geometry_EX
     
     IF Win9x THEN '- - - - - - - - - - - - - - - - - - - - - - - - - - - Windows 95/98/Millenium
     
       ! MOV  edx, pDiskCount16 'DiskCount16 parameter
       ! CALL pQtThunk          'DiskCount16 pointer
       ! MOV  DiskCount, eax    'Call Qt_Thunk
       FUNCTION = DiskCount     'DiskCount16 function result
     
     ELSE ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows NT/2000/XP
     
       DO
         IF DiskGeometryGet(DiskCount + &h80, DiskGeo) <> 0 THEN EXIT DO
         INCR DiskCount
       LOOP
       FUNCTION = DiskCount
     
     END IF
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskTry(BYVAL Disk AS DWORD, BYREF DiskGeo AS Disk_Geometry_EX) AS LONG
     LOCAL LB        AS QUAD
     LOCAL Cyl       AS DWORD
     LOCAL Head      AS DWORD
     LOCAL Sect      AS DWORD
     LOCAL WordValue AS WORD
     
     Cyl  = 3
     Head = 2
     Sect = 1
     
     DiskChsToLb Cyl, Head, Sect, Lb, DiskGeo
     MessageBox hDlg, ByCopy "Cyl, Head, Sector to LB conversion function" & $CRLF & _
                              "Cyl" & STR$(Cyl) & ", Head" & STR$(Head) & ", Sector" & _
                              STR$(Sect)& " = LB" & Str$(Lb), _
                      ByCopy $AppName, %MB_ICONINFORMATION OR %MB_OK
     
     DiskLbToChs LB, Cyl, Head, Sect, DiskGeo
     MessageBox hDlg, ByCopy "LB to Cyl, Head, Sector conversion function" & $CRLF & _
                             "LB" & STR$(LB) & " = Cyl" & STR$(Cyl) & ", Head" & STR$(Head) & _
                             ", Sector" & STR$(Sect), _
                      ByCopy $AppName, %MB_ICONINFORMATION OR %MB_OK
     
     Cyl  = 567
     Sect = 12
     
     WordValue = DiskCylSectToWord(Cyl, Sect)
     MessageBox hDlg, ByCopy "DiskCylSectToWord conversion function" & $CRLF & _
                             "Cyl" & STR$(Cyl) & ", Sect" & STR$(Sect) & " = WORD " & HEX$(WordValue, 4), _
                      ByCopy $AppName, %MB_ICONINFORMATION OR %MB_OK
     
     DiskWordToCylSect WordValue, Cyl, Sect
     MessageBox hDlg, ByCopy "DiskWordToCylSect conversion function" & $CRLF & _
                             "WORD " & HEX$(WordValue, 4) & " = Cyl" & STR$(Cyl) & ", Sect" & STR$(Sect), _
                      ByCopy $AppName, %MB_ICONINFORMATION OR %MB_OK
     
     IF Win9x THEN
       MessageBox hDlg, ByCopy "DiskInt13ExEnable function" & $CRLF & _
                               "DiskInt13ExEnable =" & Str$(DiskInt13ExEnable(Disk)), _
                        ByCopy $AppName, %MB_ICONINFORMATION OR %MB_OK
     END IF
     
    END FUNCTION
    '______________________________________________________________________________
     
    CALLBACK FUNCTION DlgProc()
     LOCAL  Sector     AS STRING * %SectorSize
     LOCAL  SectorView AS STRING * %SectorSize
     LOCAL  SectorLB   AS QUAD
     LOCAL  DiskError  AS LONG
     LOCAL  Counter    AS LONG
     LOCAL  Buffer     AS STRING
     STATIC Disk       AS DWORD
     STATIC DiskGeo    AS Disk_Geometry_EX
     STATIC DiskCount  AS DWORD
     LOCAL  Cyl        AS DWORD
     LOCAL  Head       AS DWORD
     LOCAL  Sect       AS DWORD
     STATIC hList      AS DWORD
     
     SELECT CASE CBMSG
       CASE %WM_INITDIALOG
         DIM TabStop(1 TO 3) AS LONG
         TabStop(1) = 90
         TabStop(2) = 180
         TabStop(3) = 270
         CONTROL HANDLE hDlg, %ListboxSect TO hList
         CALL SendMessage(hList, %LB_SETTABSTOPS, UBOUND(TabStop), VARPTR(TabStop(1)))
     
         Win9x = IsWin9x
         IF Win9x THEN
           IF DiskInit <> 0 THEN
             MessageBox hDlg, ByCopy "Int13.DLL fatal error", ByCopy $AppName, %MB_ICONINFORMATION OR %MB_OK
             PostMessage CbHndl, %WM_SYSCOMMAND, %SC_CLOSE, ByVal 0
             EXIT FUNCTION
           END IF
         END IF
     
         DiskCount = DiskCountGet()
         CONTROL SET TEXT hDlg, %LabelDiskCount, "Disk found:" & STR$(DiskCount)
         IF DiskCount = 0 THEN
             MessageBox hDlg, ByCopy "No disk fatal error", ByCopy $AppName, %MB_ICONINFORMATION OR %MB_OK
           PostMessage CbHndl, %WM_SYSCOMMAND, %SC_CLOSE, ByVal 0
         ELSE
           FOR Counter = 1 TO DiskCount
             COMBOBOX ADD hDlg, %ComboDisk, HEX$(&H80 + Counter - 1)
           NEXT
           Disk = &h80
           COMBOBOX SELECT hDlg, %ComboDisk, 1
           DIALOG POST hDlg, %WM_COMMAND, MAKDWD(%ComboDisk, %CBN_SELCHANGE), 0
         END IF
     
       CASE %WM_COMMAND
         SELECT CASE LOWRD(CBWPARAM)
     
           CASE %ComboDisk
             IF CBCTLMSG = %CBN_SELCHANGE OR CBCTLMSG = 1 THEN
               CONTROL GET TEXT hDlg, %ComboDisk TO Buffer
               Buffer = "&h" & Buffer
               Disk = VAL(Buffer)
               IF DiskGeometryGet(Disk, DiskGeo) = 0 THEN
                 CONTROL SET TEXT hDlg, %LabelLb,   "LB:    " & FORMAT$(DiskGeo.Lb, "0,")
                 CONTROL SET TEXT hDlg, %LabelMeg,  "Bytes: " & FORMAT$(DiskGeo.Lb * %SectorSize, "0,")
                 CONTROL SET TEXT hDlg, %LabelCyl,  "Cyl : "  & FORMAT$(DiskGeo.Cyl, "0,")
                 CONTROL SET TEXT hDlg, %LabelHead, "Head: "  & FORMAT$(DiskGeo.Head, "0,")
                 CONTROL SET TEXT hDlg, %LabelSect, "Sect: "  & FORMAT$(DiskGeo.Sect, "0,")
                 DIALOG POST hDlg, %WM_COMMAND, %ButtonRead, %BN_CLICKED
               END IF
             END IF
     
           CASE %ButtonTry
             IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
               'Writing to LB 2 'SectorLB = 2 'Select LogicalBlock 2 (Cyl 0, Head 0, Sect 3)
               'Writing to LB 2 'Buffer = TIME$ & "-" 'Create a buffer with current time
               'Writing to LB 2 'Sector = Buffer & STRING$(511 - LEN(Buffer), 120) & "X" 'Create Sector to write
               'Writing to LB 2 'DiskError = DiskWrite(&h80, 2, Sector) 'Write to disk
               'Writing to LB 2 'CONTROL SET TEXT hDlg, %TextboxLb, FORMAT$(SectorLB) 'Set textbox to LB
               'Writing to LB 2 'DIALOG POST hDlg, %WM_COMMAND, %ButtonRead, %BN_CLICKED 'Reread sector
               DiskTry Disk, DiskGeo
               CONTROL SET FOCUS hDlg, %ButtonTry
             END IF
     
           CASE %ButtonReadDwn
             IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
               CONTROL GET TEXT hDlg, %TextboxLb TO Buffer
               SectorLB = VAL(Buffer)
               DECR SectorLB
               IF SectorLB >= DiskGeo.Lb THEN SectorLB = DiskGeo.Lb - 1
               IF SectorLB < 0 THEN SectorLB = 0
               CONTROL SET TEXT hDlg, %TextboxLb, FORMAT$(SectorLB)
               DIALOG POST hDlg, %WM_COMMAND, %ButtonRead, %BN_CLICKED
               CONTROL SET FOCUS hDlg, %ButtonReadDwn
             END IF
     
           CASE %ButtonReadUp
             IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
               CONTROL GET TEXT hDlg, %TextboxLb TO Buffer
               SectorLB = VAL(Buffer)
               INCR SectorLB
               IF SectorLB >= DiskGeo.Lb THEN SectorLB = DiskGeo.Lb - 1
               IF SectorLB < 0 THEN SectorLB = 0
               CONTROL SET TEXT hDlg, %TextboxLb, FORMAT$(SectorLB)
               DIALOG POST hDlg, %WM_COMMAND, %ButtonRead, %BN_CLICKED
               CONTROL SET FOCUS hDlg, %ButtonReadUp
             END IF
     
           CASE %ButtonRead
             IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
               CONTROL DISABLE hDlg, %ButtonRead
               CONTROL GET TEXT hDlg, %TextboxLb TO Buffer
               SectorLB = VAL(Buffer)
               IF SectorLB >= DiskGeo.Lb THEN SectorLB = DiskGeo.Lb - 1
               IF SectorLB < 0 THEN SectorLB = DiskGeo.Lb - 1
               CONTROL SET TEXT hDlg, %TextboxLb, FORMAT$(SectorLB)
               DiskError = DiskRead(Disk, SectorLB, Sector)
               IF DiskError = 0 THEN
                 SectorView = Sector
                 REPLACE $NUL WITH "." IN SectorView
                 REPLACE $TAB WITH "." IN SectorView
                 LISTBOX RESET hDlg, %ListboxSect
                 FOR Counter = 1 to 449 STEP 64
                   LISTBOX ADD hDlg, %ListboxSect, _
                     MID$(SectorView, Counter, 16)      & $TAB & _
                     MID$(SectorView, Counter + 16, 16) & $TAB & _
                     MID$(SectorView, Counter + 32, 16) & $TAB & _
                     MID$(SectorView, Counter + 48, 16)
                 NEXT
                 DiskLbToChs SectorLB, Cyl, Head, Sect, DiskGeo
                 CONTROL SET TEXT hDlg, %LabelStatus, _
                 "Disk: "   & HEX$(Disk) & _
                 ", LB: "   & FORMAT$(SectorLB, "0,") & _
                 ", cyl: "  & FORMAT$(Cyl, "0,") & _
                 ", head: " & FORMAT$(Head) & _
                 ", sect: " & FORMAT$(Sect)
               ELSE
                 LISTBOX RESET hDlg, %ListboxSect
                 CONTROL SET TEXT hDlg, %LabelStatus, "Error" & STR$(DiskError)
               END IF
               CONTROL ENABLE hDlg, %ButtonRead
               CONTROL SET TEXT hDlg, %TextboxLb, FORMAT$(SectorLB)
     
             END IF
         END SELECT
     
       CASE %WM_SYSCOMMAND
         IF (CBWPARAM AND &HFFF0) = %SC_CLOSE THEN
         END IF
     
       CASE %WM_DESTROY
         IF Win9x THEN IF Disk THEN DiskRelease
     
      END SELECT
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION PBMAIN()
     
     DIALOG FONT "Courier New", 8
     DIALOG NEW 0 ,"PowerBASIC - Direct disk Read/Write routines for Windows 95-98-Millenium-NT/2000/XP",,, _
                400, 130, %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, 0 TO hDlg
     
     CONTROL ADD LABEL, hDlg, %LabelDiskCount, "Disk found:", 5, 6, 60, 9
     CONTROL ADD LABEL, hDlg, %LabelDisk, "Hard Disk", 5, 27, 50, 9
     CONTROL ADD COMBOBOX, hDlg, %ComboDisk, , 50, 25, 30, 72, _
                           %CBS_DROPDOWNLIST OR %CBS_HASSTRINGS OR %CBS_SORT OR _
                           %WS_TABSTOP, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT
     CONTROL ADD LABEL, hDlg, %LabelLb, "LB:  00000000", 100, 6, 90, 9
     CONTROL ADD LABEL, hDlg, %LabelMeg, "Meg: 00000000", 100, 16, 90, 9
     CONTROL ADD LABEL, hDlg, %LabelInt13Ext, "", 100, 26, 60, 9 'Int 13 extention
     CONTROL ADD LABEL, hDlg, %LabelCyl, "Cylinder: 00000000", 215, 6, 80, 9
     CONTROL ADD LABEL, hDlg, %LabelHead, "Head:     00000", 215, 16, 80, 9
     CONTROL ADD LABEL, hDlg, %LabelSect, "Sector:   00000", 215, 26, 80, 9
     CONTROL ADD LABEL, hDlg, -1, "LogicalBlock", 300, 6, 90, 9
     CONTROL ADD TEXTBOX, hDlg, %TextboxLb, "0", 300, 16, 45, 12
     CONTROL ADD BUTTON, hDlg, %ButtonRead, "Read", 350, 15, 40, 13
     CONTROL ADD BUTTON, hDlg, %ButtonTry, "Try", 360, 33, 20, 13
     CONTROL ADD BUTTON, hDlg, %ButtonReadDwn, "-", 305, 31, 15, 15
     CONTROL ADD BUTTON, hDlg, %ButtonReadUp, "+", 325, 31, 15, 15
     CONTROL ADD LABEL, hDlg, %LabelStatus, "Status", 47, 45, 250, 9
     CONTROL ADD LISTBOX, hDlg, %ListboxSect, , 5,  60, 390, 70, _
                          %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR %WS_VSCROLL OR _
                          %WS_TABSTOP OR %LBS_NOTIFY OR %LBS_USETABSTOPS, %WS_EX_CLIENTEDGE
     CONTROL SEND hDlg, %ListboxSect, %WM_SETFONT, GetStockObject(%OEM_FIXED_FONT), %TRUE
     
     SetClassLong hDlg, %GCL_HICON, LoadIcon(BYVAL %NULL, BYVAL %IDI_INFORMATION) 'Set a dialog icon
     
     DIALOG SHOW MODAL hDlg CALL DlgProc
     
    END FUNCTION
    '______________________________________________________________________________

  • #2
    Code:
    '16 bit Int13.DLL compiled via PbDLL 2.0
     
    $COMPILE DLL "Int13.DLL" '#DLL 2.0#  
    $DIM ALL
    $INCLUDE "WINAPI.INC"
     
    %SectorSize = 512
     
    TYPE RegStruc
     DI      AS DWORD
     SI      AS DWORD
     BP      AS DWORD
     Reserve AS DWORD
     BX      AS DWORD
     DX      AS DWORD
     CX      AS DWORD
     AX      AS DWORD
     Flags   AS WORD
     ES      AS WORD
     DS      AS WORD
     FS      AS WORD
     GS      AS WORD
     IP      AS WORD
     CS      AS WORD
     SP      AS WORD
     SS      AS WORD
    END TYPE
    '______________________________________________________________________________
     
    SUB SimRealInt(BYVAL IntNum AS BYTE, BYREF Regs AS RegStruc)
     
     ! mov CX, 0       ;'Clear CX
     ! mov BH, CL      ;'Clear BH
     ! les DI, Regs    ;'Point ES:DI to register structure
     ! mov BL, IntNum  ;'Put interrupt number in BL
     ! mov AX, &H0300  ;'DPMI service for real mode simulation
     ! int &H31        ;'Call DPMI server
     
    END SUB
    '______________________________________________________________________________
     
    FUNCTION SegOffTo32(BYVAL wSeg AS WORD, BYVAL wOff AS WORD) AS DWORD
     LOCAL hSelector AS WORD
     
     ! mov  BX, wSeg                     ;'Put segment in BX
     ! mov  AX, 2                        ;'Function 2, convert segment to selector
     ! int  &H31                         ;'Call interrupt 31 to do the job
     ! mov  hSelector, AX                ;'Selector is in ax
      FUNCTION = MAKDWD(wOff, hSelector)  '32 bit address
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskCount16() EXPORT AS DWORD
     
     FUNCTION = PEEK(SegOffTo32(&h40, &h75))
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskBufferCreate16(BYVAL BufferSize AS DWORD) EXPORT AS DWORD
     LOCAL SegmentSelector AS DWORD
     
     SegmentSelector = GlobalDosAlloc(BufferSize) 'Selector is LOWRD
     
     FUNCTION = SegmentSelector
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskBufferRelease16(BYVAL SegmentSelector AS DWORD) EXPORT AS DWORD
     
     FUNCTION = GlobalDosFree(LOWRD(SegmentSelector))  'Return 0 on success
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskWrite16(BYVAL Disk AS DWORD, BYVAL SegmentSelectorPacket AS DWORD) EXPORT AS DWORD
     LOCAL Regs          AS RegStruc
     LOCAL PacketSegment AS WORD
     
     PacketSegment = HIWRD(SegmentSelectorPacket) 'Segment for bios real-mode
     
     Regs.AX = &H4300        'AH = 43, write disk
     Regs.DX = Disk          'DL = Disk, first disk is &H80
     Regs.DS = PacketSegment 'Packet segment pointer
     Regs.SI = 0             'Packet ofset pointer, always zero
     SimRealInt &H13, Regs   'Call int 31 who will call int13
     
     IF (Regs.Flags AND 1) THEN FUNCTION = %TRUE 'Error occured
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskRead16(BYVAL Disk AS DWORD, BYVAL SegmentSelectorPacket AS DWORD) EXPORT AS DWORD
     LOCAL Regs          AS RegStruc
     LOCAL PacketSegment AS WORD
     
     PacketSegment = HIWRD(SegmentSelectorPacket) 'Segment for bios real-mode
     
     Regs.AX = &H4200        'AH = 42, read disk
     Regs.DX = Disk          'DL = Disk, first disk is &H80
     Regs.DS = PacketSegment 'Packet segment pointer
     Regs.SI = 0             'Packet ofset pointer, always zero
     SimRealInt &H13, Regs   'Call int 31 who will call int13
     
     IF (Regs.Flags AND 1) THEN FUNCTION = %TRUE 'Error occured
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskInt13ExEnable16(BYVAL Disk AS DWORD)EXPORT AS LONG
     LOCAL Regs AS RegStruc               'See also int41 and int46
     
     Regs.AX = &H4100        'AH = 41, int 13 extensions installation check
     Regs.DX = Disk          'DL = Disk, first disk is &H80
     Regs.BX = &H55AA        'BX = &H55AA
     SimRealInt &H13, Regs   'Call int 31 who will call int13
     
     IF ISFALSE(Regs.Flags AND 1) THEN
       IF Regs.BX = 43605 THEN FUNCTION = 1 '&HAA55 so int13extended is installed
     END IF
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION DiskGeometry16(BYVAL Disk AS DWORD, BYVAL SegmentSelector AS DWORD) EXPORT AS DWORD
     LOCAL Regs       AS RegStruc
     LOCAL Segment    AS WORD
     LOCAL Selector   AS WORD
     
     Segment = HIWRD(SegmentSelector)  'Segment for bios real-mode
     Selector = LOWRD(SegmentSelector) 'Segment for bios real-mode
     
     'First WORD of buffer must be equal to H1A, H1E or H42 (26, 30 or 66)
     POKE$ MAKDWD(0, Selector), CHR$(66) + STRING$(%SectorSize - 1, 0) 
     
     IF DiskInt13ExEnable16(Disk) THEN
       Regs.AX = &H4800       'AH = 48 for extended disk parameter 
       Regs.DX = Disk         'DL = Disk, first disk is &H80
       Regs.ds = Segment      'Packet segment pointer
       Regs.SI = 0            'Packet offset pointer, always 0
       SimRealInt &H13, Regs  'Call int 31 who will call int13
       'Bug: AH error with HP D9771T bios, AH is not reset to 0 on return
       'Bug: IF Regs.AX AND &HFF00 > 0 THEN "Error: AH in DrvParam"
       IF (Regs.Flags AND 1) THEN FUNCTION = %TRUE 'Error
     END IF
     
     Regs.AX = &H0800      'AH = 08 for disk parameter
     Regs.DX = Disk        'DL = Disk, first disk is &H80 
     Regs.ES = 0           'Reset to prevent some BIOS Bug
     Regs.DI = 0           'Reset to prevent some BIOS Bug
     SimRealInt &H13, Regs
     
     POKE MAKDWD(70, Selector), LOBYT(Regs.CX) 'CL = Cylinder bits 7-6 & Sector bits 5-0
     POKE MAKDWD(71, Selector), HIBYT(Regs.CX) 'CH = Low eight bits for cylinder 
     POKE MAKDWD(72, Selector), LOBYT(Regs.DX) 'DL = Disk count 
     POKE MAKDWD(73, Selector), HIBYT(Regs.DX) 'DH = Head count
     
     IF (Regs.Flags AND 1) THEN FUNCTION = %TRUE 'Error occured
     
    END FUNCTION
    '______________________________________________________________________________
     
    FUNCTION LIBMAIN (BYVAL hInstance AS INTEGER, BYVAL wDataSeg AS WORD, _
                      BYVAL wHeapSize AS WORD, lpszCmdLine AS ASCIIZ) AS INTEGER
     FUNCTION = 1
     
    END FUNCTION
    '______________________________________________________________________________


    [This message has been edited by Pierre Bellisle (edited May 12, 2005).]

    Comment


    • #3
      Code:
      'Code to create Int13.DLL from data for those who do not have PbDLL 2.0
       
      #COMPILE EXE '#Win 801#
      #INCLUDE "Win32api.inc" '2005/01/14
      '______________________________________________________________________________
       
      SUB GetData(pCodePtr AS DWORD, dwSize AS DWORD)
       pCodePtr = CODEPTR(dbdata)
       dwSize   = 6786
       EXIT SUB
       
       dbdata:
       !db 077,090,010,000,002,000,000,000,004,000,015,000,255,255,000,000
       !db 192,000,000,000,000,000,000,000,064,000,000,000,000,000,000,000
       !db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
       !db 000,000,000,000,000,000,000,000,000,000,000,000,144,000,000,000
       !db 180,009,186,016,000,014,031,205,033,184,001,076,205,033,144,144
       !db 084,104,105,115,032,112,114,111,103,114,097,109,032,109,117,115
       !db 116,032,098,101,032,114,117,110,032,117,110,100,101,114,032,077
       !db 105,099,114,111,115,111,102,116,032,087,105,110,100,111,119,115
       !db 046,013,010,036,000,000,000,000,000,000,000,000,000,000,000,000
       !db 078,069,006,000,066,001,052,000,000,000,000,000,009,128,003,000
       !db 000,004,000,000,244,000,001,000,000,000,003,000,004,000,005,000
       !db 013,000,064,000,096,000,096,000,228,000,238,000,006,002,000,000
       !db 008,000,008,000,000,000,002,000,000,000,000,000,000,000,010,003
       !db 003,000,026,013,080,017,026,013,000,000,000,000,209,016,001,000
       !db 019,000,136,000,081,000,130,007,020,000,176,005,080,017,176,005
       !db 005,073,078,084,049,051,000,000,011,068,073,083,075,067,079,085
       !db 078,084,049,054,002,000,018,068,073,083,075,066,085,070,070,069
       !db 082,067,082,069,065,084,069,049,054,003,000,019,068,073,083,075
       !db 066,085,070,070,069,082,082,069,076,069,065,083,069,049,054,004
       !db 000,011,068,073,083,075,087,082,073,084,069,049,054,005,000,010
       !db 068,073,083,075,082,069,065,068,049,054,006,000,019,068,073,083
       !db 075,073,078,084,049,051,069,088,069,078,065,066,076,069,049,054
       !db 007,000,014,068,073,083,075,071,069,079,077,069,084,082,089,049
       !db 054,008,000,000,001,000,005,000,012,000,017,000,025,000,000,003
       !db 071,068,073,006,075,069,082,078,069,076,004,085,083,069,082,007
       !db 087,073,078,056,055,069,077,008,079,076,069,050,068,073,083,080
       !db 006,070,080,073,078,073,084,006,070,080,084,069,082,077,006,070
       !db 080,077,065,084,072,014,071,076,079,066,065,076,068,079,083,065
       !db 076,076,079,067,013,071,076,079,066,065,076,068,079,083,070,082
       !db 069,069,008,255,003,205,063,001,100,005,003,205,063,004,020,001
       !db 003,205,063,004,098,001,003,205,063,004,180,001,003,205,063,004
       !db 254,001,003,205,063,004,144,002,003,205,063,004,034,003,003,205
       !db 063,004,196,003,000,000,009,073,078,084,049,051,046,068,076,076
       !db 000,000,000,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 000,000,233,167,006,233,164,006,233,161,006,233,158,006,233,155
       !db 006,233,152,006,233,149,006,233,146,006,255,255,255,255,255,255
       !db 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
       !db 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
       !db 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
       !db 000,002,032,000,255,255,000,000,255,255,000,000,255,255,000,000
       !db 255,255,000,000,255,255,000,000,255,255,000,000,255,255,000,000
       !db 255,255,000,000,255,255,000,000,255,255,000,000,255,255,000,000
       !db 255,255,000,000,255,255,000,000,255,255,000,000,255,255,000,000
       !db 255,255,000,000,255,255,000,000,255,255,000,000,255,255,000,000
       !db 255,255,000,000,255,255,000,000,255,255,000,000,255,255,000,000
       !db 255,255,000,000,255,255,000,000,255,255,000,000,255,255,000,000
       !db 255,255,000,000,255,255,000,000,255,255,000,000,255,255,000,000
       !db 255,255,000,000,255,255,000,000,255,255,000,000,255,255,000,000
       !db 255,255,000,000,255,255,000,000,255,255,000,000,255,255,000,000
       !db 255,255,000,000,232,198,000,199,006,064,005,000,000,046,247,006
       !db 050,007,004,000,117,095,255,006,064,005,046,255,030,156,000,011
       !db 192,116,075,137,014,068,005,137,022,062,005,137,030,052,005,140
       !db 006,054,005,137,062,070,005,137,054,072,005,140,006,046,005,046
       !db 255,030,112,000,163,048,005,137,022,050,005,087,051,192,080,046
       !db 255,030,228,000,046,255,030,152,000,011,192,116,017,232,220,000
       !db 232,089,000,114,009,255,014,064,005,030,232,065,000,031,160,064
       !db 005,180,076,205,033,137,054,052,005,140,006,054,005,137,014,068
       !db 005,137,062,070,005,199,006,072,005,000,000,046,255,030,112,000
       !db 163,048,005,137,022,050,005,232,162,000,232,031,000,114,011,255
       !db 006,064,005,085,030,232,006,000,031,093,161,064,005,203,137,038
       !db 066,005,232,059,003,234,138,000,255,255,203,203,232,001,000,195
       !db 128,062,060,005,003,114,001,195,184,004,001,195,195,156,081,086
       !db 087,006,253,139,014,024,000,003,014,032,000,190,040,000,003,241
       !db 078,139,062,028,000,003,249,079,030,007,243,164,185,024,000,191
       !db 033,007,243,164,007,095,094,089,157,195,252,051,192,139,014,010
       !db 007,139,062,014,007,030,007,243,170,232,081,007,195,252,102,199
       !db 006,032,000,000,000,000,000,030,014,030,007,031,051,192,185,078
       !db 000,191,156,004,243,170,072,185,008,000,191,234,004,243,170,185
       !db 014,000,190,056,000,191,242,004,243,165,031,195,051,192,163,056
       !db 005,180,048,205,033,134,196,163,058,005,232,004,000,232,033,000
       !db 195,156,084,088,059,196,176,001,117,018,156,088,013,000,064,080
       !db 157,156,088,169,000,064,176,002,116,002,176,003,162,060,005,157
       !db 195,187,011,000,046,255,030,240,000,011,192,116,030,131,014,056
       !db 005,002,187,005,000,046,255,030,240,000,163,130,005,037,064,224
       !db 163,132,005,187,009,000,046,255,030,240,000,195,046,247,006,050
       !db 007,032,000,116,003,232,020,004,139,038,066,005,195,010,192,117
       !db 002,176,005,233,018,004,232,065,255,232,081,255,184,050,019,232
       !db 010,255,090,089,051,192,080,139,236,131,236,034,080,080,080,080
       !db 081,082,203,000,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,128,012,172,006,172,006,172,006,172,006,172,006
       !db 172,006,140,002,172,006,157,002,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,242,012,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,238,011,190,011,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,166,002,172,006,147,011
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,229,011,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,192,007,216,007,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,172,006,172,006,172,006,155,011,172,006
       !db 172,006,172,006,241,008,172,006,172,006,172,006,172,006,172,006
       !db 172,006,172,006,172,006,148,008,179,008,172,006,172,006,172,006
       !db 172,006,014,012,052,012,090,012,247,011,049,008,050,008,059,008
       !db 063,008,073,008,092,008,102,008,113,008,113,008,124,008,124,008
       !db 136,008,139,000,049,186,049,031,172,063,010,000,014,100,225,255
       !db 140,200,185,007,001,190,196,002,191,128,000,030,030,007,142,216
       !db 252,165,171,226,252,031,195,100,138,004,038,136,005,070,071,010
       !db 192,117,244,195,169,015,000,116,005,232,002,000,064,195,209,232
       !db 209,232,209,232,209,232,195,080,083,081,082,106,000,046,255,030
       !db 168,000,090,089,091,088,195,060,097,114,006,060,122,119,002,052
       !db 032,195,083,006,015,160,232,005,000,015,161,007,091,195,104,066
       !db 032,102,080,046,255,030,128,000,011,192,116,019,080,080,046,255
       !db 030,140,000,089,011,192,117,007,139,194,011,192,116,001,195,176
       !db 007,249,195,000,140,216,144,085,139,236,030,142,216,139,094,010
       !db 011,219,117,008,139,070,006,163,156,004,235,089,131,251,001,119
       !db 006,140,200,051,210,235,081,131,251,016,119,011,209,227,046,139
       !db 135,022,000,051,210,235,065,129,251,000,001,117,007,184,158,004
       !db 140,218,235,052,129,251,000,002,117,005,232,048,000,235,041,129
       !db 251,000,004,117,003,233,233,000,129,251,000,008,117,023,051,201
       !db 046,247,006,050,007,128,000,116,012,139,118,006,232,049,005,139
       !db 198,140,226,235,003,051,192,153,031,093,202,008,000,102,086,102
       !db 087,184,003,053,046,255,030,096,000,006,083,184,003,037,186,069
       !db 006,030,014,031,046,255,030,096,000,031,137,038,202,004,140,022
       !db 204,004,015,178,038,186,004,196,030,182,004,006,083,255,054,192
       !db 004,255,054,200,004,102,161,158,004,102,139,030,162,004,102,139
       !db 014,166,004,102,139,022,170,004,102,139,054,174,004,102,139,062
       !db 178,004,139,046,190,004,142,006,194,004,142,038,196,004,142,046
       !db 198,004,157,031,203,030,046,142,030,101,005,102,163,158,004,102
       !db 137,030,162,004,102,137,014,166,004,102,137,022,170,004,102,137
       !db 054,174,004,102,137,062,178,004,137,046,190,004,140,006,194,004
       !db 140,038,196,004,140,046,198,004,143,006,192,004,102,143,006,182
       !db 004,143,006,200,004,137,038,186,004,140,022,188,004,015,178,038
       !db 202,004,184,003,037,090,031,046,255,030,096,000,102,095,102,094
       !db 195,031,093,235,160,000,178,052,186,178,005,186,178,244,186,178
       !db 006,182,128,137,086,218,235,005,180,128,137,070,218,246,070,218
       !db 255,117,005,199,070,218,051,128,128,126,218,241,115,001,203,203
       !db 176,000,207,000,080,111,119,101,114,066,097,115,105,099,000,067
       !db 079,077,083,080,069,067,000,069,114,114,111,114,032,097,116,032
       !db 112,103,109,045,099,116,114,058,078,111,032,068,079,083,032,050
       !db 046,048,043,036,078,111,032,056,048,056,055,036,080,114,111,103
       !db 114,097,109,032,116,111,111,032,098,105,103,036,078,111,032,056
       !db 048,050,056,054,043,036,078,111,032,056,048,051,056,054,043,036
       !db 000,000,196,000,066,098,072,104,079,111,081,113,008,008,008,008
       !db 016,016,002,002,063,019,050,019,063,027,063,031,063,023,044,034
       !db 005,132,000,064,028,070,000,000,200,066,000,000,000,127,000,000
       !db 000,063,000,000,192,255,000,000,128,127,053,194,104,033,162,218
       !db 015,201,255,063,053,194,104,033,162,218,015,201,254,063,133,100
       !db 222,249,051,243,004,181,255,063,000,066,192,255,000,072,192,255
       !db 000,074,192,255,172,006,013,010,032,032,032,032,032,032,032,032
       !db 032,032,032,032,032,032,032,032,010,128,010,000,010,000,000,000
       !db 010,128,246,127,000,000,000,000,246,127,000,000,000,000,000,000
       !db 081,185,001,000,232,207,001,114,008,038,136,005,232,042,005,089
       !db 203,232,034,005,089,233,224,254,102,143,006,198,006,137,014,202
       !db 006,139,200,232,176,001,114,020,003,249,079,088,038,136,005,226
       !db 249,232,005,005,139,014,202,006,255,046,198,006,209,225,003,225
       !db 139,014,202,006,102,255,054,198,006,233,172,254,080,046,255,030
       !db 136,000,011,192,116,023,080,080,046,255,030,148,000,011,192,117
       !db 010,046,255,030,132,000,011,192,117,003,195,088,195,176,051,249
       !db 195,152,163,166,006,155,223,006,166,006,203,102,015,183,192,102
       !db 163,166,006,155,219,006,166,006,203,102,163,166,006,102,199,006
       !db 170,006,000,000,000,000,155,223,046,166,006,203,102,163,166,006
       !db 155,217,006,166,006,203,155,223,062,166,006,144,155,160,166,006
       !db 203,155,223,062,166,006,144,155,161,166,006,203,155,223,062,166
       !db 006,144,155,102,161,166,006,203,155,217,030,166,006,144,155,102
       !db 161,166,006,203,135,217,232,253,000,114,018,232,091,004,252,138
       !db 224,209,233,243,171,128,209,000,243,170,135,217,203,232,070,004
       !db 233,005,254,080,135,217,139,118,216,102,139,122,242,232,088,002
       !db 176,000,116,003,038,138,005,232,186,002,232,201,000,114,020,102
       !db 137,082,242,252,138,224,209,233,243,171,128,209,000,243,170,135
       !db 217,088,203,102,199,066,242,000,000,000,000,139,208,088,233,192
       !db 253,083,081,139,118,216,102,139,114,242,232,003,002,247,225,139
       !db 217,139,200,232,144,000,114,050,139,193,252,139,203,059,193,119
       !db 002,139,200,043,193,227,022,086,030,015,160,031,081,193,233,002
       !db 243,102,165,089,131,225,003,243,164,031,094,235,222,232,084,002
       !db 139,118,216,102,137,082,242,089,091,203,232,071,002,139,118,216
       !db 102,199,066,242,000,000,000,000,089,091,233,107,253,232,049,000
       !db 140,006,134,005,102,199,006,136,005,000,000,000,000,199,006,148
       !db 005,228,004,140,030,150,005,195,252,086,087,030,014,031,185,008
       !db 000,190,168,007,051,255,243,165,173,191,254,127,171,031,095,094
       !db 195,083,081,102,184,000,128,000,000,232,166,251,114,005,142,192
       !db 232,213,255,089,091,195,227,088,129,249,238,127,114,003,185,238
       !db 127,131,193,007,142,006,134,005,051,255,038,139,125,002,011,255
       !db 015,132,128,000,038,059,013,119,241,038,139,021,043,209,131,250
       !db 018,114,053,038,137,021,003,250,131,199,004,038,137,085,250,139
       !db 209,128,206,128,131,233,007,038,137,077,254,038,137,085,252,003
       !db 249,038,198,005,000,038,137,085,001,043,249,006,087,102,090,195
       !db 102,051,210,196,062,148,005,195,003,209,038,128,077,001,128,003
       !db 250,038,128,077,255,128,043,250,131,199,004,131,233,007,038,135
       !db 077,254,038,139,021,135,207,038,137,085,004,135,215,038,137,085
       !db 002,139,249,038,139,077,254,003,249,038,198,005,000,043,249,006
       !db 087,102,090,195,038,139,022,006,000,011,210,116,005,142,194,233
       !db 102,255,080,030,006,232,057,255,114,010,031,140,006,006,000,031
       !db 088,233,084,255,007,031,089,185,000,000,102,186,000,000,000,000
       !db 196,062,148,005,195,011,246,126,072,083,081,030,102,086,094,031
       !db 131,238,004,139,028,128,231,127,139,076,254,011,201,120,051,043
       !db 241,003,217,137,028,137,088,254,003,243,129,254,000,128,116,108
       !db 139,012,011,201,120,102,043,243,001,012,003,217,137,088,254,003
       !db 243,043,241,139,092,002,139,116,004,137,119,004,137,092,002,235
       !db 075,195,003,243,129,254,000,128,116,041,139,012,011,201,120,035
       !db 255,116,004,255,116,002,135,217,001,072,254,043,241,003,217,137
       !db 028,089,091,137,076,002,137,092,004,137,119,002,139,217,137,119
       !db 004,235,025,136,124,255,043,243,136,124,001,139,222,135,030,002
       !db 000,137,092,002,199,068,004,000,000,137,119,004,031,089,091,195
       !db 129,230,255,127,116,010,102,086,094,015,161,100,139,076,254,195
       !db 051,201,015,180,054,148,005,195,129,231,255,127,116,009,102,087
       !db 095,007,038,139,085,254,195,051,210,196,062,148,005,195,129,230
       !db 255,127,116,019,030,102,086,094,031,059,076,254,119,008,137,076
       !db 254,003,241,198,004,000,031,195,083,081,082,086,006,142,006,134
       !db 005,184,000,128,187,010,000,043,195,190,006,000,038,139,012,227
       !db 028,140,194,142,193,038,059,007,117,242,038,139,004,142,194,038
       !db 137,004,139,193,006,232,148,252,007,115,214,235,001,248,007,094
       !db 090,089,091,195,102,086,139,118,216,102,139,114,242,232,213,254
       !db 102,094,195,102,150,232,205,254,102,150,203,135,217,102,080,232
       !db 244,253,252,094,015,161,030,015,160,031,081,193,233,002,243,102
       !db 165,089,131,225,003,243,164,031,232,062,001,135,217,203,139,118
       !db 216,102,139,114,242,232,056,255,227,023,252,102,080,095,007,030
       !db 015,160,031,081,193,233,002,243,102,165,089,131,225,003,243,164
       !db 031,232,035,001,203,102,080,094,007,038,015,182,004,203,102,080
       !db 088,007,147,038,136,007,203,155,223,062,198,006,144,155,102,247
       !db 022,198,006,102,247,022,202,006,155,223,046,198,006,203,155,223
       !db 062,166,006,155,223,062,198,006,144,155,102,139,022,166,006,102
       !db 033,022,198,006,102,139,022,170,006,102,033,022,202,006,155,223
       !db 046,198,006,203,155,223,062,166,006,155,223,062,198,006,144,155
       !db 102,139,022,166,006,102,009,022,198,006,102,139,022,170,006,102
       !db 009,022,202,006,155,223,046,198,006,203,155,223,062,166,006,155
       !db 223,062,198,006,144,155,102,139,022,166,006,102,049,022,198,006
       !db 102,139,022,170,006,102,049,022,202,006,155,223,046,198,006,203
       !db 083,081,139,126,216,102,139,115,242,232,116,254,139,217,086,015
       !db 160,102,139,115,246,232,104,254,003,217,135,217,232,247,252,114
       !db 073,135,217,043,217,252,030,015,160,031,081,193,233,002,243,102
       !db 165,089,131,225,003,243,164,031,015,161,094,139,203,030,015,160
       !db 031,081,193,233,002,243,102,165,089,131,225,003,243,164,031,139
       !db 126,216,102,139,242,102,135,115,246,232,137,253,102,139,115,242
       !db 232,130,253,131,070,216,004,089,091,203,015,161,094,089,091,233
       !db 198,249,232,001,000,203,102,051,210,085,131,110,216,004,003,110
       !db 216,102,137,086,242,093,195,102,086,139,118,216,102,139,114,242
       !db 131,070,216,004,232,078,253,102,094,195,082,000,002,000,026,000
       !db 002,000,000,000,002,000,028,000,003,000,000,000,005,001,056,000
       !db 002,000,114,000,005,001,058,000,002,000,113,000,005,001,060,000
       !db 002,000,183,000,005,001,062,000,002,000,193,000,005,001,064,000
       !db 002,000,174,000,005,001,066,000,002,000,181,000,005,001,068,000
       !db 002,000,182,000,005,001,070,000,002,000,195,000,005,001,072,000
       !db 002,000,179,000,005,001,074,000,002,000,190,000,005,001,076,000
       !db 002,000,194,000,005,001,078,000,002,000,173,000,002,000,168,001
       !db 004,000,000,000,003,001,084,000,002,000,175,000,003,001,088,000
       !db 003,000,218,000,003,001,092,000,003,000,114,000,003,001,096,000
       !db 002,000,102,000,003,001,100,000,003,000,088,000,003,001,104,000
       !db 002,000,176,000,003,001,108,000,003,000,091,000,003,001,112,000
       !db 002,000,131,000,003,001,116,000,003,000,108,000,003,001,120,000
       !db 002,000,048,000,003,001,124,000,003,000,036,000,003,001,128,000
       !db 002,000,015,000,003,001,132,000,002,000,017,000,003,001,136,000
       !db 002,000,021,000,003,001,140,000,002,000,018,000,003,001,144,000
       !db 002,000,016,000,003,001,148,000,002,000,019,000,003,001,152,000
       !db 003,000,005,000,003,001,156,000,002,000,091,000,003,001,160,000
       !db 002,000,095,000,003,001,164,000,002,000,051,000,003,001,168,000
       !db 003,000,104,000,003,001,172,000,003,000,001,000,003,001,180,000
       !db 003,000,109,000,003,001,184,000,003,000,101,000,003,001,188,000
       !db 003,000,111,000,003,001,192,000,002,000,107,000,003,001,196,000
       !db 003,000,022,000,003,001,200,000,002,000,187,000,003,001,204,000
       !db 002,000,189,000,003,001,208,000,003,000,232,000,003,001,212,000
       !db 005,000,004,000,003,001,216,000,005,000,006,000,003,001,220,000
       !db 005,000,007,000,003,001,224,000,003,000,113,000,003,001,228,000
       !db 002,000,030,000,003,001,232,000,002,000,166,000,003,001,236,000
       !db 002,000,029,000,003,001,240,000,004,000,001,000,002,000,030,000
       !db 004,000,000,000,005,007,053,008,005,000,000,000,005,007,067,008
       !db 005,000,000,000,005,007,086,008,005,000,000,000,005,007,096,008
       !db 005,000,000,000,005,007,102,008,005,000,000,000,005,007,107,008
       !db 006,000,000,000,005,007,113,008,005,000,000,000,005,007,118,008
       !db 006,000,000,000,005,007,124,008,005,000,000,000,005,007,129,008
       !db 006,000,000,000,005,007,136,008,005,000,000,000,005,007,141,008
       !db 006,000,000,000,005,007,247,011,005,000,000,000,005,007,252,011
       !db 006,000,000,000,005,007,008,012,005,000,000,000,005,007,014,012
       !db 005,000,000,000,005,007,019,012,005,000,000,000,005,007,024,012
       !db 006,000,000,000,005,007,046,012,005,000,000,000,005,007,052,012
       !db 005,000,000,000,005,007,057,012,005,000,000,000,005,007,062,012
       !db 006,000,000,000,005,007,084,012,005,000,000,000,005,007,090,012
       !db 005,000,000,000,005,007,095,012,005,000,000,000,005,007,100,012
       !db 006,000,000,000,005,007,122,012,005,000,000,000,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000
       !db 000,000,000,000,034,007,000,000,000,000,000,000,034,007,000,000
       !db 096,000,000,000,034,007,000,000,255,255,255,255,000,002,000,000
       !db 032,000,000,000,000,000,000,000,255,255,255,255,255,255,255,255
       !db 000,002,000,000,064,000,000,000,117,000,000,000,000,067,000,000
       !db 000,000,000,000,019,000,000,000,001,000,000,000,000,066,000,000
       !db 000,065,000,000,170,085,000,000,085,170,000,000,066,000,000,000
       !db 000,072,000,000,000,008,000,000,070,000,000,000,071,000,000,000
       !db 072,000,000,000,073,000,000,000,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170
       !db 248,247,006,224,004,255,255,117,014,195,156,248,247,006,224,004
       !db 255,255,117,002,157,195,157,235,011,195,195,119,005,043,194,120
       !db 001,195,176,009,090,014,082,255,046,004,001,011,210,117,005,010
       !db 228,117,001,195,176,006,235,236,011,210,120,248,195,081,139,202
       !db 153,059,202,089,117,238,195,011,192,120,233,011,210,117,229,195
       !db 080,140,192,011,195,088,116,001,195,176,009,235,199,102,081,102
       !db 015,183,202,102,051,210,102,247,241,080,082,102,088,102,089,195
       !db 247,070,218,000,128,117,001,195,129,118,218,000,128,139,078,220
       !db 227,245,129,078,218,000,064,090,255,225,255,030,204,001,255,054
       !db 070,005,030,255,054,068,005,255,054,054,005,255,054,052,005,154
       !db 141,005,255,255,137,006,064,005,255,030,252,000,000,000,112,098
       !db 085,139,236,131,236,034,102,106,000,106,000,185,000,000,138,249
       !db 196,126,006,138,094,010,184,000,003,205,049,139,229,093,202,006
       !db 000,000,000,112,098,085,139,236,131,236,034,102,106,000,102,106
       !db 000,102,106,000,139,094,008,184,002,000,205,049,137,070,214,102
       !db 015,183,070,006,102,139,200,102,015,183,070,214,102,193,224,016
       !db 139,193,102,137,070,210,102,139,070,210,139,229,093,202,004,000
       !db 000,000,112,098,140,216,144,085,139,236,102,083,102,086,102,087
       !db 030,142,216,131,236,020,102,106,000,102,106,000,106,000,102,015
       !db 191,006,062,007,080,102,015,191,006,066,007,080,014,232,149,255
       !db 255,030,048,003,102,152,102,137,070,212,102,139,070,212,102,080
       !db 088,090,141,102,242,031,102,095,102,094,102,091,093,203,000,000
       !db 112,098,140,216,144,085,139,236,102,083,102,086,102,087,030,142
       !db 216,131,236,020,102,106,000,102,106,000,102,106,000,106,000,102
       !db 139,070,006,102,080,154,255,255,255,255,082,080,102,088,102,137
       !db 070,212,102,139,070,212,102,137,070,208,102,139,070,208,102,080
       !db 088,090,141,102,242,031,102,095,102,094,102,091,093,202,004,000
       !db 000,000,112,098,140,216,144,085,139,236,102,083,102,086,102,087
       !db 030,142,216,131,236,020,102,106,000,102,106,000,106,000,102,139
       !db 070,006,102,015,183,192,080,154,255,255,255,255,102,015,183,192
       !db 102,137,070,212,102,139,070,212,102,080,088,090,141,102,242,031
       !db 102,095,102,094,102,091,093,202,004,000,000,000,112,098,140,216
       !db 144,085,139,236,102,083,102,086,102,087,030,142,216,131,236,020
       !db 102,051,192,185,015,000,102,080,073,117,251,080,102,139,070,006
       !db 102,193,232,016,137,070,214,102,199,070,192,000,067,000,000,102
       !db 139,070,010,102,137,070,184,102,015,183,070,214,137,070,200,102
       !db 199,070,168,000,000,000,000,184,019,000,080,141,094,164,022,083
       !db 014,232,092,254,155,217,232,139,070,196,255,030,116,004,255,030
       !db 092,004,155,217,228,155,223,224,158,155,221,216,116,008,102,199
       !db 070,160,255,255,255,255,102,139,070,160,102,080,088,090,141,102
       !db 242,031,102,095,102,094,102,091,093,202,008,000,000,000,112,098
       !db 140,216,144,085,139,236,102,083,102,086,102,087,030,142,216,131
       !db 236,020,102,051,192,185,015,000,102,080,073,117,251,080,102,139
       !db 070,006,102,193,232,016,137,070,214,102,199,070,192,000,066,000
       !db 000,102,139,070,010,102,137,070,184,102,015,183,070,214,137,070
       !db 200,102,199,070,168,000,000,000,000,184,019,000,080,141,094,164
       !db 022,083,014,232,202,253,155,217,232,139,070,196,255,030,116,004
       !db 255,030,092,004,155,217,228,155,223,224,158,155,221,216,116,008
       !db 102,199,070,160,255,255,255,255,102,139,070,160,102,080,088,090
       !db 141,102,242,031,102,095,102,094,102,091,093,202,008,000,000,000
       !db 112,098,140,216,144,085,139,236,102,083,102,086,102,087,030,142
       !db 216,131,236,020,102,051,192,185,015,000,102,080,073,117,251,102
       !db 199,070,194,000,065,000,000,102,139,070,006,102,137,070,186,102
       !db 199,070,182,170,085,000,000,184,019,000,080,141,094,166,022,083
       !db 014,232,076,253,155,217,232,139,070,198,255,030,116,004,255,030
       !db 092,004,155,217,228,155,223,224,158,155,221,216,184,255,255,116
       !db 001,064,255,030,112,004,155,217,228,155,223,224,158,155,221,216
       !db 015,132,022,000,102,139,006,098,007,102,139,078,182,102,059,200
       !db 117,008,102,199,070,162,001,000,000,000,102,139,070,162,102,080
       !db 088,090,141,102,242,031,102,095,102,094,102,091,093,202,004,000
       !db 000,000,112,098,140,216,144,085,139,236,102,083,102,086,102,087
       !db 030,142,216,131,236,020,102,051,192,185,016,000,102,080,073,117
       !db 251,102,139,070,006,102,193,232,016,137,070,212,102,139,070,006
       !db 102,015,183,192,137,070,214,102,015,191,006,074,007,102,139,200
       !db 102,015,183,070,214,102,193,224,016,139,193,185,066,000,102,137
       !db 006,014,005,139,193,255,030,128,003,184,001,000,247,216,003,006
       !db 058,007,139,216,049,192,255,030,068,004,255,030,224,000,102,139
       !db 006,014,005,255,030,164,001,102,139,070,010,102,080,014,232,225
       !db 254,082,080,102,088,102,133,192,015,132,079,000,102,199,070,190
       !db 000,072,000,000,102,139,070,010,102,137,070,182,102,015,183,070
       !db 212,137,070,198,102,199,070,166,000,000,000,000,184,019,000,080
       !db 141,094,162,022,083,014,232,055,252,155,217,232,139,070,194,255
       !db 030,116,004,255,030,092,004,155,217,228,155,223,224,158,155,221
       !db 216,116,008,102,199,070,158,255,255,255,255,102,199,070,190,000
       !db 008,000,000,102,139,070,010,102,137,070,182,102,015,191,006,074
       !db 007,137,070,196,102,199,070,162,000,000,000,000,184,019,000,080
       !db 141,094,162,022,083,014,232,231,251,102,015,191,006,114,007,102
       !db 139,200,102,015,183,070,214,102,193,224,016,139,193,102,139,078
       !db 186,102,015,182,201,139,217,255,030,160,001,102,015,191,006,118
       !db 007,102,139,200,102,015,183,070,214,102,193,224,016,139,193,102
       !db 139,078,186,102,015,182,205,139,217,255,030,160,001,102,015,191
       !db 006,122,007,102,139,200,102,015,183,070,214,102,193,224,016,139
       !db 193,102,139,078,182,102,015,182,201,139,217,255,030,160,001,102
       !db 015,191,006,126,007,102,139,200,102,015,183,070,214,102,193,224
       !db 016,139,193,102,139,078,182,102,015,182,205,139,217,255,030,160
       !db 001,155,217,232,139,070,194,255,030,116,004,255,030,092,004,155
       !db 217,228,155,223,224,158,155,221,216,116,008,102,199,070,158,255
       !db 255,255,255,102,139,070,158,102,080,088,090,141,102,242,031,102
       !db 095,102,094,102,091,093,202,008,000,000,000,112,098,085,139,236
       !db 131,236,034,102,106,000,102,106,000,199,070,214,001,000,139,070
       !db 214,139,229,093,202,010,000,000,000,000,000,000,000,000,000,000
       !db 026,000,003,002,134,001,002,000,055,000,003,002,216,001,002,000
       !db 070,000,005,007,084,002,005,000,000,000,005,007,098,002,005,000
       !db 000,000,005,007,101,002,005,000,000,000,005,007,105,002,005,000
       !db 000,000,005,007,230,002,005,000,000,000,005,007,244,002,005,000
       !db 000,000,005,007,247,002,005,000,000,000,005,007,251,002,005,000
       !db 000,000,005,007,100,003,005,000,000,000,005,007,114,003,005,000
       !db 000,000,005,007,117,003,005,000,000,000,005,007,121,003,005,000
       !db 000,000,005,007,134,003,005,000,000,000,005,007,137,003,005,000
       !db 000,000,005,007,141,003,005,000,000,000,005,007,121,004,005,000
       !db 000,000,005,007,135,004,005,000,000,000,005,007,138,004,005,000
       !db 000,000,005,007,142,004,005,000,000,000,005,007,081,005,005,000
       !db 000,000,005,007,095,005,005,000,000,000,005,007,098,005,005,000
       !db 000,000,005,007,102,005,005,000,000,000,002,000,162,000,004,000
       !db 000,000
      END SUB
      '______________________________________________________________________________
       
      FUNCTION PBMAIN
       LOCAL pCodePtr AS DWORD
       LOCAL dwSize   AS DWORD
       LOCAL FileNo   AS DWORD
       LOCAL FileName AS STRING
       
       GetData pCodePtr, dwSize
       DIM Aray(1 TO dwSize) AS BYTE AT pCodePtr
       
       FileName = "Int13.DLL"
       FileNo = FREEFILE
       OPEN FileName FOR BINARY SHARED AS FileNo
       PUT FileNo, 1, Aray()
       CLOSE FileNo
       
       MessageBox 0, ByCopy Filename & " created.", _
                     ByCopy Filename & " creator", %MB_ICONINFORMATION OR %MB_OK
       
      END FUNCTION
      '______________________________________________________________________________


      [This message has been edited by Pierre Bellisle (edited May 12, 2005).]

      Comment


      • #4
        This is an update of the first post.

        Pierre

        Code:
         
        '_____________________________________________________________________________
         
        'Added IsAdmin for Vista+ and many littles corrections.
         
        'Int13.dll is needed only for 9.x Windows.
        '_____________________________________________________________________________
         
        'This is a demo to show how to directly access a hard disk under any version of windows.
         
        'Use it at your own risk, very easy to destroy the content of a hard-disk
        'if you are not familiar with direct disk access.
         
        'Accessing an NT system is fairly easy using CreateFile("\\.\PhysicalDrive0"...
        'Under Windows 9x the process is more complex,
        'the need of a 16 bit DLL is mandatory, this DLL is compiled via PBDLL 2.0.
         
        'Thank to Semen for GetProcAddressDirectly, witch enable us to find
        'ordinal MS undocumented function in Kernel32.DLL,
        'Qt_Thunk, LoadLibrary16, FreeLibrary16 and GetProcAddress16.
         
        'Int13.DLL routines are, DiskBufferCreate16, DiskBufferRelease16, DiskRead16,
        'DiskWrite16, DiskGeometry16, DiskInt13ExEnable16 and DiskCount16.
         
        'The process is to call GetProcAddressDirectly to get Qt_Thunk
        'to call GetProcAddress16 to call a 16 bit function in Int13.DLL
        'to call SimRealInt that will call an int 13 bios function
        'who will write his result in a dos buffer...
         
        'Note that this program use &h80 for the first hard disk,
        '&h81 for the second, and so on...
         
        'If you don't have PbDLL 2.0, an already compiled version of
        'Int13.DLL can be generated by running code down this post...
        'Note that PbDLL 2.0 was part of PbDLL 6.0, for PbDLL 7 or PbDLL 8,
        'you can purchase it as a separate package from PowerBASIC.
         
        'The exe code can be compiled with PbDLL7 or PbDLL8
        'It will need some modification to run under PbDLL6.
         
        'Thank to Semen Matusovski, William Burns and Lance Edmonds
         
        'Have fun
         
        'Pierre
         
        '_____________________________________________________________________________
         
        #COMPILE EXE '#Win 8.04#
        #REGISTER NONE
        #DIM ALL
        #INCLUDE "Win32Api.inc"
        #INCLUDE "CommCtrl.inc" 'Needed if manifest and WinXP
         
        'Optionnal rc file, need admin right for Vista+
        #RESOURCE "Admin.pbr" 'Need admin right for Vista+ http://somesite.host-ed.me/PowerBASIC/rcFileAdmin.html
         
        GLOBAL DosSectorPtr             AS STRING POINTER
        GLOBAL DosPacketPtr             AS STRING POINTER
        GLOBAL Packet                   AS STRING
        GLOBAL hDlg                     AS DWORD
        GLOBAL Win9x                    AS DWORD
        GLOBAL SegmentSelectorDosSector AS DWORD
        GLOBAL SegmentSelectorDosPacket AS DWORD
        GLOBAL hKernel                  AS DWORD
        GLOBAL hInt13                   AS DWORD
        GLOBAL pQtThunk                 AS DWORD
        GLOBAL pLoadLibrary16           AS DWORD
        GLOBAL pGetProcAddress16        AS DWORD
        GLOBAL pFreeLibrary16           AS DWORD
        GLOBAL pGlobalDosFree16         AS DWORD
        GLOBAL pDiskBufferCreate16      AS DWORD
        GLOBAL pDiskBufferRelease16     AS DWORD
        GLOBAL pDiskRead16              AS DWORD
        GLOBAL pDiskWrite16             AS DWORD
        GLOBAL pDiskGeo16               AS DWORD
        GLOBAL pDiskCount16             AS DWORD
        GLOBAL pDiskInt13ExEnable16     AS DWORD
        GLOBAL hKeyboardHook            AS DWORD
        GLOBAL LogicalDisk              AS LONG
         
        %KeyboardMessage = %WM_USER + 401
         
        $PacketHeader    = CHR$(16, 0, 1, 0, 0, 0)
        $Int13           = "Int13.DLL"
        $AppName         = "Direct disk Read/Write"
         
        %LabelDisk       = 101
        %LabelDiskCount  = 102
        %LabelInt13Ext   = 103
        %LabelLb         = 104
        %LabelCyl        = 105
        %LabelHead       = 106
        %LabelSect       = 107
        %LabelMeg        = 108
        %LabelStatus     = 109
        %ComboDisk       = 201
        %ButtonRead      = 301
        %ButtonReadUp    = 302
        %ButtonReadDwn   = 303
        %ButtonTry       = 304
        %ListboxSect     = 401
        %TextboxLb       = 402
        %OptionPhysical  = 501
        %OptionLogical   = 502
        %TimerOne        = 601
        %TimerTwo        = 602
         
        %SECURITY_NT_AUTHORITY = 005
        %SectorSize            = 512
         
        %IOCTL_DISK_GET_DRIVE_GEOMETRY  = &H00070000
        %FILE_DEVICE_DISK               = &H07              '%IOCTL_DISK_GET_LENGTH_INFO
        %IOCTL_DISK_BASE                = %FILE_DEVICE_DISK '%IOCTL_DISK_GET_LENGTH_INFO
        %METHOD_BUFFERED                = 0                 '%IOCTL_DISK_GET_LENGTH_INFO
        %FILE_READ_ACCESS               = &H01              '%IOCTL_DISK_GET_LENGTH_INFO
        %IOCTL_DISK_GET_LENGTH_INFO     = &H7405C           '%IOCTL_DISK_GET_LENGTH_INFO
         
        TYPE DISK_GEOMETRY_EX
         Cyl  AS DWORD
         Head AS DWORD
         Sect AS DWORD
         Byt  AS DWORD
         Lb   AS QUAD
        END TYPE
         
        TYPE DISK_GEOMETRY
         Cylinders         AS QUAD
         MediaType         AS DWORD
         TracksPerCylinder AS DWORD
         SectorsPerTrack   AS DWORD
         BytesPerSector    AS DWORD
        END TYPE
         
        DECLARE FUNCTION LoadLibrary16(BYVAL DLLFile AS STRING) AS DWORD
        DECLARE FUNCTION FreeLibrary16(BYVAL hDLL AS DWORD) AS DWORD
        DECLARE FUNCTION GetProcAddress16(BYVAL zDLLFile AS DWORD, BYVAL sFunction AS STRING) AS DWORD
        DECLARE FUNCTION DiskBufferCreate16(BYVAL BufferSize AS DWORD) AS DWORD
        DECLARE FUNCTION DiskBufferRelease16(BYVAL SegmentSelector AS DWORD) AS DWORD
        DECLARE FUNCTION DiskRead16(BYVAL Disk AS DWORD, BYVAL SegmentSelectorPacket AS DWORD) AS DWORD
        DECLARE FUNCTION DiskWrite16(BYVAL Disk AS DWORD, BYVAL SegmentSelectorPacket AS DWORD) AS DWORD
        DECLARE FUNCTION DiskGeometry16(BYVAL Disk AS DWORD, BYVAL SegmentSelector AS DWORD) AS DWORD
        DECLARE FUNCTION DiskInt13ExEnable16(BYVAL Disk AS DWORD) AS LONG 'Return %TRUE if present
        '_____________________________________________________________________________
         
        FUNCTION IsUserAdmin() AS LONG
         LOCAL NtAuthority         AS SID_IDENTIFIER_AUTHORITY
         LOCAL AdministratorsGroup AS LONG
         LOCAL IsMember            AS LONG
         
         'IsUserAnAdmin api may not be there in future Windows release, so doing it following way.
         
         NtAuthority.value(5) = %SECURITY_NT_AUTHORITY 'SECURITY_NT_AUTHORITY = 5
         
         IF AllocateAndInitializeSid(NtAuthority, 2, %SECURITY_BUILTIN_DOMAIN_RID, _
                                     %DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, _
                                     AdministratorsGroup) THEN
            IF CheckTokenMembership(%NULL, BYVAL AdministratorsGroup, IsMember) THEN
              FUNCTION = IsMember
            END IF
            FreeSid(BYVAL AdministratorsGroup)
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION IsWin9x() AS LONG
         LOCAL vi AS OSVERSIONINFO
         
         vi.dwOsVersionInfoSize = SIZEOF(OSVERSIONINFO)
         GetVersionEx(vi)
         IF vi.dwPlatformId = %VER_PLATFORM_WIN32_WINDOWS THEN
           FUNCTION = %TRUE
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION DiskSizeGet(sDisk AS STRING) AS QUAD
         LOCAL qDiskSizeLogical       AS QUAD
         LOCAL FreeBytesAvailable     AS QUAD 'Available to user
         LOCAL TotalNumberOfFreeBytes AS QUAD 'Available to user
         LOCAL hDevice                AS DWORD
         LOCAL pOutBuffer             AS DWORD
         LOCAL OutBufferSize          AS DWORD
         LOCAL BytesReturned          AS DWORD
         
         qDiskSizeLogical = 0
         hDevice = CreateFile("\\.\" & sDisk, %GENERIC_READ, %FILE_SHARE_READ OR _ 'Danger >> OR %GENERIC_WRITE be carefull
                              %FILE_SHARE_WRITE, BYVAL 0, %OPEN_EXISTING, 0, 0 )
         
         IF hDevice <> %INVALID_HANDLE_VALUE THEN
           OutBufferSize = SIZEOF(qDiskSizeLogical) '8
           pOutBuffer    = VARPTR(qDiskSizeLogical)
           IF DeviceIoControl(BYVAL hDevice, %IOCTL_DISK_GET_LENGTH_INFO, BYVAL %NULL, 0, _
                              BYVAL pOutBuffer, OutBufferSize, BytesReturned, BYVAL %NULL) THEN
                             'If the operation completes successfully, DeviceIoControl returns a nonzero value.
           ELSE 'Floppy & CD
             'SetErrorMode(%SEM_FAILCRITICALERRORS) 'Windows does not display the critical-error-handler message box
             GetDiskFreeSpaceEx(BYCOPY sDisk, FreeBytesAvailable, qDiskSizeLogical, TotalNumberOfFreeBytes)
           END IF
           CloseHandle(hDevice)
         END IF
         
         FUNCTION = qDiskSizeLogical
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION DiskListGet(BYREF DiskCount AS LONG) AS LONG
         LOCAL sDisk            AS STRING
         LOCAL sBuffer          AS STRING
         LOCAL qDiskSizeLogical AS QUAD
         LOCAL DiskBit          AS DWORD
         LOCAL Looper           AS LONG
         
         DiskCount = 0
         COMBOBOX RESET hDlg, %ComboDisk
         
         DiskBit = GetLogicalDrives 'Return a bitmask representing available disk. Bit 0 is drive A. If fails return value is zero.
         
         FOR Looper = 0 TO 25
           IF BIT(DiskBit, Looper) THEN
             sDisk = CHR$(Looper + 65) & ":"
             qDiskSizeLogical = DiskSizeGet(sDisk)
             IF qDiskSizeLogical > 0 THEN
               INCR DiskCount
               COMBOBOX ADD hDlg, %ComboDisk, sDisk
               IF ASC(sDisk) = 67 THEN 'C:
                 COMBOBOX SELECT hDlg, %ComboDisk, DiskCount 'C:
               END IF
             END IF
           END IF
         NEXT
         
         COMBOBOX GET TEXT hDlg, %ComboDisk TO sBuffer
         IF ASC(sBuffer) <> 67 THEN
           COMBOBOX SELECT hDlg, %ComboDisk, 1 'A:
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION GetProcAddressDirectly(BYVAL lpImageDosHeader AS IMAGE_DOS_HEADER PTR, BYREF FuncName AS ASCIIZ) AS DWORD
         LOCAL lpImageNtHeaders       AS IMAGE_NT_HEADERS POINTER
         LOCAL lpImageExportDirectory AS IMAGE_EXPORT_DIRECTORY POINTER
         LOCAL lpExpFuncName          AS ASCIIZ POINTER
         LOCAL lpFuncName             AS ASCIIZ POINTER
         LOCAL lpName                 AS DWORD POINTER
         LOCAL lpFunctions            AS DWORD POINTER
         LOCAL lpNameOrdinals         AS WORD POINTER
         LOCAL i                      AS DWORD
         LOCAL j                      AS DWORD
         
         'Thank to Semen Matusovski - http://www.powerbasic.com/support/forums/Forum4/HTML/010410.html
         IF @lpImageDosHeader.e_magic <> %IMAGE_DOS_SIGNATURE THEN FUNCTION = 0 : EXIT FUNCTION 'Invalid DOS signature
         lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
         IF @lpImageNtHeaders.Signature <> %IMAGE_NT_SIGNATURE THEN FUNCTION = 0 : EXIT FUNCTION 'Invalid NT signature
         IF @lpImageNtHeaders.FileHeader.SizeOfOptionalHeader <> SIZEOF(@lpImageNtHeaders.OptionalHeader) OR _
            @lpImageNtHeaders.OptionalHeader.Magic <> %IMAGE_NT_OPTIONAL_HDR32_MAGIC THEN EXIT FUNCTION
         
         lpImageExportDirectory = @lpImageNtHeaders.OptionalHeader.DataDirectory(%IMAGE_DIRECTORY_ENTRY_EXPORT).VirtualAddress
         IF lpImageExportDirectory = 0 THEN EXIT FUNCTION
         lpImageExportDirectory = lpImageExportDirectory + lpImageDosHeader
         
         lpNameOrdinals = @lpImageExportDirectory.AddressOfNameOrdinals + lpImageDosHeader
         lpName         = @lpImageExportDirectory.AddressOfNames        + lpImageDosHeader
         lpFunctions    = @lpImageExportDirectory.AddressOfFunctions    + lpImageDosHeader
         
         lpFuncName     = VARPTR(FuncName)
         IF HIWRD(lpFuncName) THEN 'FuncName is ascii
           FOR i = 0 TO @lpImageExportDirectory.NumberOfFunctions - 1
             IF @lpFunctions[i] THEN
               FOR j = 0 TO @lpImageExportDirectory.NumberOfNames - 1
                 IF @lpNameOrdinals[j] = i THEN
                   lpExpFuncName = @lpName[j] + lpImageDosHeader
                   IF @lpExpFuncName = FuncName THEN
                     FUNCTION = @lpFunctions[i] + lpImageDosHeader
                     EXIT FUNCTION
                   END IF
                 END IF
               NEXT
             END IF
           NEXT
         ELSE 'FuncName is ordinal
           FOR i = 0 TO @lpImageExportDirectory.NumberOfFunctions - 1
             IF lpFuncName = @lpImageExportDirectory.nBase + i THEN
               IF  @lpFunctions[i] THEN FUNCTION = @lpFunctions[i] + lpImageDosHeader
               EXIT FUNCTION
             END IF
           NEXT
         END IF
        END FUNCTION
        '_____________________________________________________________________________
         
        SUB DiskChsToLb(BYVAL Cyl AS DWORD, BYVAL Head AS DWORD, BYVAL Sect AS DWORD, _
                        BYREF Lb AS QUAD, BYREF DiskGeo AS DISK_GEOMETRY_EX)
         
         'Convert Cylinder, Head, Sector to LogicalBlockAddress
         Lb = (Cyl * DiskGeo.Head * DiskGeo.Sect + Head * DiskGeo.Sect) + Sect - 1
         
        END SUB
        '_____________________________________________________________________________
         
        SUB DiskLbToChs(BYVAL Lb AS QUAD, BYREF Cyl AS DWORD, BYREF Head AS DWORD, _
                        BYREF Sect AS DWORD, BYREF DiskGeo AS DISK_GEOMETRY_EX)
         LOCAL CHS     AS QUAD
         LOCAL HsCount AS QUAD
         
         'Convert LogicalBlockAddress to Cylinder, Head, Sector
         HsCount = DiskGeo.Head * DiskGeo.Sect
         Cyl     = Lb \ HsCount '2,147,483,648 Maximum before error, 1.1 terra
         CHS     = Cyl * HsCount
         Head    = (Lb - Chs) \ DiskGeo.Sect
         Sect    = Lb - (Chs + Head * DiskGeo.Sect) + 1
         
         'Maximum LBA sector = 256 * 256 * 256 * 256 - 1
         'Max Lb             =  4,294,967,295
         '2,199,023,255,040 bytes or 2.2 terra
         'If 63 sectors and 255 heads then 267,349 cylinders maximum (267,349.3492)
         
        END SUB
        '_____________________________________________________________________________
         
        FUNCTION DiskCylSectToWord(BYVAL Cyl AS DWORD, BYVAL Sect AS DWORD) AS WORD
         LOCAL SX AS DWORD
         LOCAL CH AS DWORD
         LOCAL CL AS DWORD
         
         'Convert Cylinder, Sector to int13:08 format
         
         '  +-- Cylinder Lo ----+       +-Sector--+
         '  15 14 13 12 11 10 9 8 - 7 6 5 4 3 2 1 0
         '                   Cyl Hi +-+
         
         FUNCTION = ((Cyl  AND 255) * 256) + _
                    ((Cyl  AND 768) / 4)   + _
                     (Sect AND  63)
         
        END FUNCTION
        '_____________________________________________________________________________
         
        SUB DiskWordToCylSect(BYVAL CylSect AS DWORD, BYREF Cyl AS DWORD, BYREF Sect AS DWORD)
         
         'Convert int13:08 result to Cylinder, Sector
         
         '  +-- Cylindre Lo ----+     +-Sector--+
         '  15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
         '                  Cyl Hi+-+
         
         Cyl  = ((CylSect AND 192) * 4) + HIBYT(CylSect)
         Sect =  (CylSect AND  63)
         
        END SUB
        '_____________________________________________________________________________
         
        FUNCTION DiskInit()AS LONG 'Return 0 on success
         LOCAL Retval     AS DWORD
         LOCAL PacketSize AS DWORD
         
         'Under Win9x, get all needed function pointers and prepare
         'one DOS buffer for packet and one 512 bytes DOS buffer for sector.
         
         hKernel = LoadLibrary("Kernel32.DLL")
         IF hKernel THEN
           pQtThunk          = GetProcAddressDirectly(hKernel, "QT_Thunk")
           pLoadLibrary16    = GetProcAddressDirectly(hKernel, BYVAL MAKDWD(35, 0)) 'LoadLibrary16
           pFreeLibrary16    = GetProcAddressDirectly(hKernel, BYVAL MAKDWD(36, 0)) 'FreeLibrary16
           pGetProcAddress16 = GetProcAddressDirectly(hKernel, BYVAL MAKDWD(37, 0)) 'GetProcAddress16
           IF pGetProcAddress16 = 0 THEN FUNCTION = 1 'Kernel32.DLL error
         
           CALL DWORD pLoadLibrary16 USING LoadLibrary16($Int13) TO hInt13
           CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskBufferCreate16") TO pDiskBufferCreate16
           CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskBufferRelease16") TO pDiskBufferRelease16
           CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskRead16") TO pDiskRead16
           CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskWrite16") TO pDiskWrite16
           CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskGeometry16") TO pDiskGeo16
           CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskInt13ExEnable16") TO pDiskInt13ExEnable16
           CALL DWORD pGetProcAddress16 USING GetProcAddress16(hInt13, "DiskCount16") TO pDiskCount16
           IF pDiskCount16 = 0 THEN FUNCTION = 2 'Int13.DLL error
         
           IF pDiskBufferCreate16 THEN
             ! PUSH %SectorSize
             ! MOV  edx, pDiskBufferCreate16
             ! CALL pQtThunk
             ! MOV  SegmentSelectorDosSector, eax
             IF SegmentSelectorDosSector = 0 THEN FUNCTION = 3 'Dos sector buffer allocation error
             DosSectorPtr = HIWRD(SegmentSelectorDosSector) * 16
         
             PacketSize = 16
             ! PUSH PacketSize
             ! MOV  edx, pDiskBufferCreate16
             ! CALL pQtThunk
             ! MOV  SegmentSelectorDosPacket, eax
             IF SegmentSelectorDosPacket = 0 THEN FUNCTION = 4 'Dos packet buffer allocation error
             DosPacketPtr = HIWRD(SegmentSelectorDosPacket) * 16
           END IF
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION DiskRelease()AS DWORD
         LOCAL Retval AS DWORD
         
         'Under Win9x, free memory when program terminate.
         
         ! PUSH SegmentSelectorDosSector
         ! MOV  edx, pDiskBufferRelease16
         ! CALL pQtThunk
         
         ! PUSH SegmentSelectorDosPacket
         ! MOV  edx, pDiskBufferRelease16
         ! CALL pQtThunk
         
         CALL DWORD pFreeLibrary16 USING FreeLibrary16(hInt13) TO Retval
         FreeLibrary(hKernel)
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION DiskWrite(BYVAL Disk AS DWORD, BYVAL SectorLB AS QUAD, _
                           BYREF Sector AS STRING * %SectorSize)AS LONG
         LOCAL zDisk      AS ASCIIZ * 30
         LOCAL pFilePtrLo AS DWORD POINTER
         LOCAL pFilePtrHi AS DWORD POINTER
         LOCAL FilePtr    AS QUAD
         LOCAL Retval     AS DWORD
         LOCAL DiskError  AS DWORD
         LOCAL hDisk      AS DWORD
         LOCAL dwRead     AS DWORD
         LOCAL Result     AS LONG
         
         'Use at your own risk...
         'Use at your own risk...
         'Use at your own risk...
         EXIT FUNCTION '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
         'Use at your own risk...
         'Use at your own risk...
         'Use at your own risk...
         
         IF Win9x THEN  ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows 95/98/Millenium
         
           'Prepare a packet made of a pointer to a DOS buffer and the target LogicalBlock for int 13:48
           Packet = $PacketHeader & MKWRD$(HIWRD(SegmentSelectorDosSector))& MKQ$(SectorLB)
           POKE$ DosPacketPtr, Packet
           POKE$ DosSectorPtr, Sector
         
           ! PUSH Disk                     'DiskWrite16 first parameter
           ! PUSH SegmentSelectorDosPacket 'DiskWrite16 second parameter
           ! MOV  edx, pDiskWrite16        'DiskWrite16 pointer
           ! CALL pQtThunk                 'Call Qt_Thunk
           ! MOV  DiskError, eax           'DiskWrite16 function result
         
           IF DiskError THEN FUNCTION = %TRUE  'Error
         
         ELSE ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows NT/2000/XP/Vista/7/8
         
           zDisk = "\\.\PhysicalDrive" & FORMAT$(Disk - &H80) 'Physical Disk
           hDisk = CreateFile(zDisk, %GENERIC_WRITE, %FILE_SHARE_READ OR _
                                     %FILE_SHARE_WRITE, BYVAL 0, %OPEN_EXISTING, 0, 0 )
           IF hDisk = %INVALID_HANDLE_VALUE THEN
             FUNCTION = %TRUE
           ELSE
             FilePtr = SectorLB * %SectorSize
             pFilePtrLo = VARPTR(FilePtr)
             pFilePtrHi = pFilePtrLo + 4
             SetFilePointer(hDisk, @pFilePtrLo, @pFilePtrHi, %FILE_BEGIN)
             Result = WriteFile(hDisk, BYVAL VARPTR(Sector), %SectorSize, dwRead, BYVAL %NULL)
             IF Result = 0 THEN FUNCTION = %TRUE 'Error
             CloseHandle(hDisk)
           END IF
         
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION DiskRead(BYVAL Disk AS DWORD, BYVAL SectorLB AS QUAD, _
                          BYREF Sector AS STRING * %SectorSize)AS LONG
         LOCAL zDisk      AS ASCIIZ * 30
         LOCAL pFilePtrLo AS DWORD POINTER
         LOCAL pFilePtrHi AS DWORD POINTER
         LOCAL FilePtr    AS QUAD
         LOCAL hDisk      AS DWORD
         LOCAL dwRead     AS DWORD
         LOCAL DiskError  AS LONG
         LOCAL Result     AS LONG
         
         IF Win9x THEN ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows 95/98/Millenium
         
           'Prepare a packet made of a pointer to a DOS buffer and the target LogicalBlock for int 13:48
           Packet = $PacketHeader & MKWRD$(HIWRD(SegmentSelectorDosSector))& MKQ$(SectorLB)
           POKE$ DosPacketPtr, Packet
         
           ! PUSH Disk                     'DiskRead16 first parameter
           ! PUSH SegmentSelectorDosPacket 'DiskRead16 second parameter
           ! MOV  edx, pDiskRead16         'DiskRead16 pointer
           ! CALL pQtThunk                 'Call Qt_Thunk
           ! MOV  DiskError, eax           'DiskRead16 function result
         
           IF DiskError THEN
             Sector = ""
           ELSE
             Sector = PEEK$(DosSectorPtr, %SectorSize)
           END IF
           FUNCTION = DiskError '0 for success
         
         ELSE ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows NT/2000/XP/Vista/7/8
           'A CD-ROM sector is normally 2048 bytes, the buffer that receives the sector data must be a multiple of 2048
           'and must start on an address that is a multiple of 2048. An easy way to guarantee the that the buffer will start on
           'a multiple of 2048 is to allocate it with VirtualAlloc. Finally, although sectors on compact discs are normally 2048 bytes,
           'you should use the DeviceIoControl IOCTL_CDROM_GET_DRIVE_GEOMETRY command to return the sector size to avoid hard-coded limits.
         
           IF LogicalDisk THEN
             zDisk = "\\.\" & CHR$(Disk) & ":"
           ELSE
             zDisk = "\\.\PhysicalDrive" & FORMAT$(Disk - &H80) 'Physical Disk
           END IF
           hDisk = CreateFile(zDisk, %GENERIC_READ, %FILE_SHARE_READ OR _
                                     %FILE_SHARE_WRITE, BYVAL 0, %OPEN_EXISTING, 0, 0 )
           IF hDisk = %INVALID_HANDLE_VALUE THEN
             FUNCTION = %TRUE 'Error
           ELSE
             FilePtr = SectorLB * %SectorSize
             pFilePtrLo = VARPTR(FilePtr)
             pFilePtrHi = pFilePtrLo + 4
             SetFilePointer(hDisk, @pFilePtrLo, @pFilePtrHi, %FILE_BEGIN)
             Result = ReadFile(hDisk, BYVAL VARPTR(Sector), %SectorSize, dwRead, BYVAL %NULL)
             IF Result THEN
               IF dwRead <> %SectorSize THEN
                 Sector = STRING$(%SectorSize, 0)
                 FUNCTION = %TRUE
               END IF
             ELSE
               Sector = STRING$(%SectorSize, 0)
               FUNCTION = %TRUE
             END IF
             CloseHandle(hDisk)
           END IF
         
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION DiskInt13ExEnable(BYVAL Disk AS DWORD) AS DWORD
         LOCAL RegEAX AS DWORD
         
         IF Win9x THEN
           ! PUSH Disk                      'DiskInt13ExEnable parameter
           ! MOV  edx, pDiskInt13ExEnable16 'DiskInt13ExEnable pointer
           ! CALL pQtThunk                  'Call Qt_Thunk
           ! MOV  RegEAX, eax               'DiskInt13ExEnable function result
           FUNCTION = RegEAX
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION DiskGeometryGet(BYVAL Disk AS DWORD, BYREF DiskGeo AS DISK_GEOMETRY_EX) AS LONG
         LOCAL DiskGeo48  AS DISK_GEOMETRY_EX
         LOCAL DiskGeoNT  AS DISK_GEOMETRY
         LOCAL Retval     AS DWORD
         LOCAL RegEAX     AS DWORD
         LOCAL hFile      AS DWORD
         LOCAL OldErrMode AS LONG
         
         IF Win9x THEN ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows 95/98/Millenium
         
           ! PUSH Disk                     'DiskGeo16 first parameter
           ! PUSH SegmentSelectorDosSector 'DiskGeo16 second parameter
           ! MOV  edx, pDiskGeo16          'DiskGeo16 pointer
           ! CALL pQtThunk                 'Call Qt_Thunk
           ! MOV  RegEAX, eax              'DiskGeo16 function result
         
           IF RegEAX = 0 THEN
             DiskWordToCylSect CVWRD(PEEK$(DosSectorPtr + 70, 2)), DiskGeo.Cyl, DiskGeo.Sect
             INCR DiskGeo.Cyl
             DiskGeo.Head = PEEK(DosSectorPtr + 73) + 1
             CONTROL SET TEXT hDLG, %LabelInt13Ext, "Int 13 ext: no"
         
             IF DiskInt13ExEnable(Disk) THEN
               CONTROL SET TEXT hDLG, %LabelInt13Ext, "Int 13 ext: yes"
               DiskGeo48.Cyl  = CVDWD(PEEK$(DosSectorPtr + 4, 4))
               DiskGeo48.Head = CVDWD(PEEK$(DosSectorPtr + 8, 4))
               DiskGeo48.Sect = CVDWD(PEEK$(DosSectorPtr + 12, 4))
               DiskGeo48.LB   = CVQ(PEEK$(DosSectorPtr + 16, 8))
         
               DiskGeo.Cyl  = DiskGeo48.Lb \ (DiskGeo.Head * DiskGeo.Sect)
               DiskGeo.Lb   = DiskGeo.Cyl * DiskGeo.Head * DiskGeo.Sect 'Cut unused end sectors
             END IF
           ELSE
             FUNCTION = %TRUE 'Error
           END IF
         
         ELSE ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows NT/2000/XP/Vista/7/8
         
           OldErrMode = SetErrorMode(%SEM_FAILCRITICALERRORS)'Prevent pop-up dialogs if device is not present or loaded
           hFile = CreateFile("\\.\PHYSICALDRIVE" & FORMAT$(Disk - &H80), 0, %FILE_SHARE_READ OR _
                              %FILE_SHARE_WRITE, BYVAL 0&, %OPEN_EXISTING, 0, BYVAL 0&)
           IF hFile <> %INVALID_HANDLE_VALUE THEN
             IF DeviceIoControl(hFile, %IOCTL_DISK_GET_DRIVE_GEOMETRY, BYVAL 0, _
                                BYVAL 0, BYVAL VARPTR(DiskGeoNT), SIZEOF(DiskGeoNT), 0, BYVAL 0& ) THEN
               DiskGeo.Cyl  = DiskGeoNT.Cylinders
               DiskGeo.Head = DiskGeoNT.TracksPerCylinder
               DiskGeo.Sect = DiskGeoNT.SectorsPerTrack
               DiskGeo.LB   = DiskGeo.Cyl * DiskGeo.Head * DiskGeo.Sect
             ELSE
               FUNCTION = %TRUE
             END IF
           ELSE
             FUNCTION = %TRUE
           END IF
           CloseHandle(hFile)
           SetErrorMode(OldErrMode)
         
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION DiskCountGet() AS DWORD
         LOCAL DiskGeo   AS DISK_GEOMETRY_EX
         LOCAL Retval    AS DWORD
         LOCAL DiskCount AS DWORD
         
         IF Win9x THEN '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows 95/98/Millenium
         
           ! MOV  edx, pDiskCount16 'DiskCount16 parameter
           ! CALL pQtThunk          'DiskCount16 pointer
           ! MOV  DiskCount, eax    'Call Qt_Thunk
           FUNCTION = DiskCount     'DiskCount16 function result
         
         ELSE ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Windows NT/2000/XP/Vista/7/8
         
           DO
             'Not necessarely consecutive like in the case od a USB drive that is removed
             IF DiskGeometryGet(DiskCount + &H80, DiskGeo) <> 0 THEN EXIT DO
             INCR DiskCount
           LOOP
           FUNCTION = DiskCount
         
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION DiskTry(BYVAL Disk AS DWORD, BYREF DiskGeo AS DISK_GEOMETRY_EX) AS LONG
         LOCAL LB        AS QUAD
         LOCAL Cyl       AS DWORD
         LOCAL Head      AS DWORD
         LOCAL Sect      AS DWORD
         LOCAL WordValue AS WORD
         
         Cyl  = 3
         Head = 2
         Sect = 1
         
         DiskChsToLb(Cyl, Head, Sect, Lb, DiskGeo)
         MessageBox(hDlg, BYCOPY "Cyl, Head, Sector to LB conversion function" & $CRLF & _
                                  "Cyl" & STR$(Cyl) & ", Head" & STR$(Head) & ", Sector" & _
                                  STR$(Sect)& " = LB" & STR$(Lb), _
                          BYCOPY $AppName, %MB_ICONINFORMATION OR %MB_OK)
         
         DiskLbToChs(LB, Cyl, Head, Sect, DiskGeo)
         MessageBox(hDlg, BYCOPY "LB to Cyl, Head, Sector conversion function" & $CRLF & _
                                 "LB" & STR$(LB) & " = Cyl" & STR$(Cyl) & ", Head" & STR$(Head) & _
                                 ", Sector" & STR$(Sect), _
                          BYCOPY $AppName, %MB_ICONINFORMATION OR %MB_OK)
         
         Cyl  = 567
         Sect = 012
         
         WordValue = DiskCylSectToWord(Cyl, Sect)
         MessageBox(hDlg, BYCOPY "DiskCylSectToWord conversion function" & $CRLF & _
                                 "Cyl" & STR$(Cyl) & ", Sect" & STR$(Sect) & " = WORD " & HEX$(WordValue, 4), _
                          BYCOPY $AppName, %MB_ICONINFORMATION OR %MB_OK)
         
         DiskWordToCylSect(WordValue, Cyl, Sect)
         MessageBox(hDlg, BYCOPY "DiskWordToCylSect conversion function" & $CRLF & _
                                 "WORD " & HEX$(WordValue, 4) & " = Cyl" & STR$(Cyl) & ", Sect" & STR$(Sect), _
                          BYCOPY $AppName, %MB_ICONINFORMATION OR %MB_OK)
         
         IF Win9x THEN
           MessageBox(hDlg, BYCOPY "DiskInt13ExEnable function" & $CRLF & _
                                   "DiskInt13ExEnable =" & STR$(DiskInt13ExEnable(Disk)), _
                            BYCOPY $AppName, %MB_ICONINFORMATION OR %MB_OK)
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION KeyboardHook(BYVAL HookCode AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS DWORD
         STATIC KeyUp           AS LONG
         STATIC KeyDown         AS LONG
         
         FUNCTION = CallNextHookEx(hKeyboardHook, HookCode, wParam, lParam)
         
         IF HookCode = %HC_ACTION THEN
           IF (lParam AND &H80000000) = 0 THEN
             KeyDown = %TRUE : KeyUp = %FALSE 'Allow auto repeat
           ELSE
             KeyUp = %TRUE : KeyDown = %FALSE 'Does not allow auto repeat, one shot only
           END IF
         
           SELECT CASE wParam
         
             CASE %VK_RETURN
               IF KeyDown THEN 'Keydown for auto repeat else one shot with keyup
                 PostMessage(hDlg, %WM_COMMAND, MAKDWD(%ButtonRead, %BN_CLICKED), GetDlgItem(hDlg, %ButtonRead))
               END IF
               FUNCTION = %TRUE 'If function is true, key will not be forwarded to dialog
         
             CASE %VK_R
               IF KeyUp THEN 'Keydown for auto repeat else one shot with keyup
                 PostMessage(hDlg, %WM_COMMAND, MAKDWD(%ButtonRead, %BN_CLICKED), GetDlgItem(hDlg, %ButtonRead))
               END IF
               FUNCTION = %TRUE 'If function is true, key will not be forwarded to dialog
         
             CASE %VK_OEM_PLUS, %VK_ADD '+, + on NumPad
               IF KeyDown THEN 'Keydown for auto repeat else one shot with keyup
                 PostMessage(hDlg, %WM_COMMAND, MAKDWD(%ButtonReadUp, %BN_CLICKED), GetDlgItem(hDlg, %ButtonReadUp))
               END IF
               FUNCTION = %TRUE 'If function is true, key will not be forwarded to dialog
         
             CASE %VK_OEM_MINUS, %VK_SUBTRACT '-, - on NumPad
               IF KeyDown THEN  'Keydown for auto repeat else one shot with keyup
                 PostMessage(hDlg, %WM_COMMAND, MAKDWD(%ButtonReadDwn, %BN_CLICKED), GetDlgItem(hDlg, %ButtonReadDwn))
               END IF
               FUNCTION = %TRUE 'If function is true, key will not be forwarded to dialog
           END SELECT
         
         END IF
         
        END FUNCTION
        '_____________________________________________________________________________
         
        CALLBACK FUNCTION DlgProc()
         STATIC DiskGeo          AS DISK_GEOMETRY_EX
         LOCAL  Sector           AS STRING * %SectorSize
         LOCAL  SectorView       AS STRING * %SectorSize
         STATIC sLogicalDisk     AS STRING
         LOCAL  sBuffer          AS STRING
         LOCAL  SectorLB         AS QUAD
         STATIC LastLB           AS QUAD
         STATIC qDiskSizeLogical AS QUAD
         STATIC Disk             AS DWORD
         STATIC DiskCount        AS DWORD
         LOCAL  Cyl              AS DWORD
         LOCAL  Head             AS DWORD
         LOCAL  Sect             AS DWORD
         STATIC hList            AS DWORD
         LOCAL  DiskError        AS LONG
         LOCAL  Looper           AS LONG
         STATIC ButtonDown1      AS LONG
         STATIC ButtonDown2      AS LONG
         
         SELECT CASE CBMSG
         
           CASE %WM_INITDIALOG
             hKeyboardHook = SetWindowsHookEx(%WH_KEYBOARD, CODEPTR(KeyboardHook), 0, GetCurrentThreadId) 'Hook the keyboard
         
             DIM TabStop(1 TO 3) AS LONG
             TabStop(1) = 90
             TabStop(2) = 180
             TabStop(3) = 270
             CONTROL HANDLE hDlg, %ListboxSect TO hList
             SendMessage(hList, %LB_SETTABSTOPS, UBOUND(TabStop), VARPTR(TabStop(1)))
         
             Win9x = IsWin9x
             IF Win9x THEN
               IF DiskInit <> 0 THEN
                 MessageBox(hDlg, BYCOPY "Int13.DLL fatal error", BYCOPY $AppName, %MB_ICONINFORMATION OR %MB_OK)
                 PostMessage(hDlg, %WM_SYSCOMMAND, %SC_CLOSE, BYVAL 0)
                 EXIT FUNCTION
               END IF
             END IF
             PostMessage(hDlg, %WM_COMMAND, MAKDWD(%OptionPhysical, %BN_CLICKED), GetDlgItem(hDlg, %OptionPhysical))
         
           CASE %KeyboardMessage
             SELECT CASE CBWPARAM
               CASE %VK_UP
               CASE %VK_DOWN
             END SELECT
         
           CASE %WM_CTLCOLORBTN
             IF CBLPARAM = GetDlgItem(hDlg, %ButtonReadUp) THEN 'Is it the button handle ?
               IF (SendMessage(CBLPARAM, %BM_GETSTATE, 0, 0) AND %BST_PUSHED) = %BST_PUSHED THEN 'Is button down ?
                 IF ButtonDown1 = %FALSE THEN 'Up to down transition is occuring
                   ButtonDown1 = %TRUE
                   SetTimer(hDlg, %TimerOne, 110, BYVAL %NULL) 'Set the timer
                 END IF
               ELSE
                 IF ButtonDown1 = %TRUE THEN 'Down to up transition is occuring
                   ButtonDown1 = %FALSE
                   KillTimer(hDlg, %TimerOne)
                 END IF
               END IF
             END IF
             IF CBLPARAM = GetDlgItem(hDlg, %ButtonReadDwn) THEN 'Is it the button handle ?
               IF (SendMessage(CBLPARAM, %BM_GETSTATE, 0, 0) AND %BST_PUSHED) = %BST_PUSHED THEN 'Is button down ?
                 IF ButtonDown2 = %FALSE THEN 'Up to down transition is occuring
                   ButtonDown2 = %TRUE
                   SetTimer(hDlg, %TimerTwo, 110, BYVAL %NULL) 'Set the timer
                 END IF
               ELSE
                 IF ButtonDown2 = %TRUE THEN 'Down to up transition is occuring
                   ButtonDown2 = %FALSE
                   KillTimer(hDlg, %TimerTwo)
                 END IF
               END IF
             END IF
         
           CASE %WM_TIMER 'wParam = TimerID, lParam = AddressOfCallback
             IF CBWPARAM = %TimerOne THEN
               PostMessage(hDlg, %WM_COMMAND, MAKDWD(%ButtonReadUp, %BN_CLICKED), GetDlgItem(hDlg, %ButtonReadUp))
             END IF
         
             IF CBWPARAM = %TimerTwo THEN
               PostMessage(hDlg, %WM_COMMAND, MAKDWD(%ButtonReadDwn, %BN_CLICKED), GetDlgItem(hDlg, %ButtonReadDwn))
             END IF
         
           CASE %WM_COMMAND
             SELECT CASE LOWRD(CBWPARAM)
         
               CASE %OptionLogical, %OptionPhysical
                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
         
                   SectorLB = 0
                   CONTROL SET TEXT hDlg, %TextboxLb, "0"
                   CONTROL GET CHECK hDlg, %OptionLogical TO LogicalDisk
                   COMBOBOX RESET hDlg, %ComboDisk
                   IF LogicalDisk THEN
                     DiskListGet(DiskCount)
                     COMBOBOX GET TEXT hDlg, %ComboDisk TO sLogicalDisk
                   ELSE
                     DiskCount = DiskCountGet()
                     IF DiskCount = 0 THEN
                       MessageBox(hDlg, BYCOPY "No disk fatal error", BYCOPY $AppName, %MB_ICONINFORMATION OR %MB_OK)
                       PostMessage(hDlg, %WM_SYSCOMMAND, %SC_CLOSE, BYVAL 0)
                     ELSE
                       FOR Looper = 1 TO DiskCount
                         COMBOBOX ADD hDlg, %ComboDisk, HEX$(&H80 + Looper - 1)
                       NEXT
                       Disk = &H80
                       COMBOBOX SELECT hDlg, %ComboDisk, 1
                     END IF
                   END IF
                   CONTROL SET TEXT hDlg, %LabelDiskCount, "Disk found: " & STR$(DiskCount)
                   PostMessage(hDlg, %WM_COMMAND, MAKDWD(%ComboDisk, %CBN_SELCHANGE), GetDlgItem(hDlg, %ComboDisk))
                 END IF
         
               CASE %ComboDisk
                 IF CBCTLMSG = %CBN_SELCHANGE OR CBCTLMSG = 1 THEN
                   IF LogicalDisk THEN
                     COMBOBOX GET TEXT hDlg, %ComboDisk TO sLogicalDisk
                     qDiskSizeLogical = DiskSizeGet(sLogicalDisk)
                     LastLb = (qDiskSizeLogical / %SectorSize) - 1
                     IF qDiskSizeLogical THEN
                       CONTROL SET TEXT hDlg, %LabelMeg,  "Bytes: " & FORMAT$(qDiskSizeLogical, "0,")
                       CONTROL SET TEXT hDlg, %LabelLb,   "LB:    " & FORMAT$(LastLb + 1, "0,")
                       CONTROL SET TEXT hDlg, %LabelCyl,  "" '"Cyl : " & FORMAT$(DiskGeo.Cyl, "0,")
                       CONTROL SET TEXT hDlg, %LabelHead, "" '"Head: " & FORMAT$(DiskGeo.Head, "0,")
                       CONTROL SET TEXT hDlg, %LabelSect, "" '"Sect: " & FORMAT$(DiskGeo.Sect, "0,")
                       DIALOG POST hDlg, %WM_COMMAND, %ButtonRead, %BN_CLICKED
                     END IF
                   ELSE
                     CONTROL GET TEXT hDlg, %ComboDisk TO sBuffer
                     sBuffer = "&h" & sBuffer
                     Disk = VAL(sBuffer)
                     IF DiskGeometryGet(Disk, DiskGeo) = 0 THEN
                       LastLb = DiskGeo.Lb - 1
                       CONTROL SET TEXT hDlg, %LabelLb,   "LB:    " & FORMAT$(DiskGeo.Lb, "0,")
                       CONTROL SET TEXT hDlg, %LabelMeg,  "Bytes: " & FORMAT$(DiskGeo.Lb * %SectorSize, "0,")
                       CONTROL SET TEXT hDlg, %LabelCyl,  "Cyl : "  & FORMAT$(DiskGeo.Cyl, "0,")
                       CONTROL SET TEXT hDlg, %LabelHead, "Head: "  & FORMAT$(DiskGeo.Head, "0,")
                       CONTROL SET TEXT hDlg, %LabelSect, "Sect: "  & FORMAT$(DiskGeo.Sect, "0,")
                       DIALOG POST hDlg, %WM_COMMAND, %ButtonRead, %BN_CLICKED
                     END IF
                   END IF
                 END IF
         
               CASE %ButtonTry
                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                   DiskTry Disk, DiskGeo
                   CONTROL SET FOCUS hDlg, %ButtonTry 'to del
                 END IF
         
               CASE %ButtonReadDwn
                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                   CONTROL GET TEXT hDlg, %TextboxLb TO sBuffer
                   SectorLB = VAL(sBuffer)
                   DECR SectorLB
                   IF SectorLB < 0 THEN SectorLB = 0
                   CONTROL SET TEXT hDlg, %TextboxLb, FORMAT$(SectorLB)
                   DIALOG POST hDlg, %WM_COMMAND, %ButtonRead, %BN_CLICKED
                   CONTROL SET FOCUS hDlg, %ButtonReadDwn
                 END IF
         
               CASE %ButtonReadUp
                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                   CONTROL GET TEXT hDlg, %TextboxLb TO sBuffer
                   SectorLB = VAL(sBuffer)
                   INCR SectorLB
                   IF SectorLB > LastLb THEN SectorLB = LastLb 'DiskGeo.Lb - 1
                   CONTROL SET TEXT hDlg, %TextboxLb, FORMAT$(SectorLB)
                   DIALOG POST hDlg, %WM_COMMAND, %ButtonRead, %BN_CLICKED
                   CONTROL SET FOCUS hDlg, %ButtonReadUp
                 END IF
         
               CASE %ButtonRead
                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                   CONTROL DISABLE hDlg, %ButtonRead
                   CONTROL GET TEXT hDlg, %TextboxLb TO sBuffer
                   SectorLB = VAL(sBuffer)
                   IF SectorLB > LastLb THEN SectorLB = LastLb
                   IF SectorLB < 0 THEN SectorLB = 0
                   CONTROL SET TEXT hDlg, %TextboxLb, FORMAT$(SectorLB)
                   IF LogicalDisk THEN
                     DiskError = DiskRead(ASC(sLogicalDisk), SectorLB, Sector)
                   ELSE
                     DiskError = DiskRead(Disk, SectorLB, Sector)
                   END IF
                   IF DiskError = 0 THEN
                     SectorView = Sector
                     REPLACE $NUL WITH "." IN SectorView
                     REPLACE $TAB WITH "." IN SectorView
                     LISTBOX RESET hDlg, %ListboxSect
                     FOR Looper = 1 TO 449 STEP 64
                       LISTBOX ADD hDlg, %ListboxSect, MID$(SectorView, Looper, 16)      & $TAB & _
                                                       MID$(SectorView, Looper + 16, 16) & $TAB & _
                                                       MID$(SectorView, Looper + 32, 16) & $TAB & _
                                                       MID$(SectorView, Looper + 48, 16)
                     NEXT
                     DiskLbToChs(SectorLB, Cyl, Head, Sect, DiskGeo)
                     IF LogicalDisk THEN
                       CONTROL SET TEXT hDlg, %LabelStatus, "Disk: " & sLogicalDisk & _
                                                            ", LB: " & FORMAT$(SectorLB, "0,")
                     ELSE
                       CONTROL SET TEXT hDlg, %LabelStatus, "Disk: " & HEX$(Disk) & _
                                                            ", LB: " & FORMAT$(SectorLB, "0,") & _
                                                            ", cyl: " & FORMAT$(Cyl, "0,") & _
                                                            ", head: " & FORMAT$(Head) & _
                                                            ", sect: " & FORMAT$(Sect)
                     END IF
                   ELSE
                     LISTBOX RESET hDlg, %ListboxSect
                     CONTROL SET TEXT hDlg, %LabelStatus, "Error" & STR$(DiskError)
                   END IF
                   CONTROL ENABLE hDlg, %ButtonRead
                   CONTROL SET TEXT hDlg, %TextboxLb, FORMAT$(SectorLB)
         
                 END IF
             END SELECT
         
           CASE %WM_SYSCOMMAND
             IF (CBWPARAM AND &HFFF0) = %SC_CLOSE THEN
             END IF
         
           CASE %WM_DESTROY
             UnhookWindowsHookEx(hKeyboardHook)
             IF Win9x THEN
               IF Disk THEN
                 DiskRelease
               END IF
             END IF
         
          END SELECT
         
        END FUNCTION
        '_____________________________________________________________________________
         
        FUNCTION PBMAIN()
         LOCAL hIconBig   AS DWORD
         LOCAL hIconSmall AS DWORD
         
         IF IsUserAdmin = %FALSE THEN
           MessageBox(%HWND_DESKTOP, "Please restart program as administrator.", $AppName & " - Error", %MB_OK)
         ELSE
           DIALOG FONT "Segoe UI", 9
           DIALOG NEW %HWND_DESKTOP, $AppName & _
           " for Windows 95-98-Millenium-NT/2000/XP/Vista/Seven/Eight",,, _
           400, 132, %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, 0 TO hDlg
         
           CONTROL ADD FRAME, hDlg, -1, "", 02, 0, 394, 58, %BS_LEFT OR %BS_TOP, %WS_EX_LEFT
         
           CONTROL ADD OPTION, hDlg, %OptionPhysical, "&Physical", 7, 5, 35, 9, _
           %BS_LEFT OR %BS_VCENTER OR %WS_TABSTOP OR %WS_GROUP, %WS_EX_LEFT
         
           CONTROL ADD OPTION, hDlg, %OptionLogical, "&Logical", 47, 5, 35, 9, _
           %BS_LEFT OR %BS_VCENTER OR %WS_TABSTOP, %WS_EX_LEFT
         
           CONTROL SET OPTION hDlg, %OptionPhysical, %OptionPhysical, %OptionLogical
         
           CONTROL ADD LABEL, hDlg, %LabelDiskCount, "Disk found:", 7, 17, 60, 9
         
           CONTROL ADD LABEL, hDlg, %LabelDisk, "Hard Disk", 7, 30, 50, 9
         
           CONTROL ADD COMBOBOX, hDlg, %ComboDisk, , 57, 29, 30, 72, _
           %CBS_DROPDOWNLIST OR %CBS_HASSTRINGS OR %CBS_SORT OR _
           %WS_TABSTOP, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT
         
           CONTROL ADD LABEL, hDlg, %LabelLb, "LB:  00000000", 100, 6, 90, 9
         
           CONTROL ADD LABEL, hDlg, %LabelMeg, "Meg: 00000000", 100, 16, 90, 9
         
           CONTROL ADD LABEL, hDlg, %LabelInt13Ext, "", 100, 26, 60, 9 'Int 13 extention
         
           CONTROL ADD LABEL, hDlg, %LabelCyl, "Cylinder: 00000000", 215, 6, 80, 9
         
           CONTROL ADD LABEL, hDlg, %LabelHead, "Head:     00000", 215, 16, 80, 9
         
           CONTROL ADD LABEL, hDlg, %LabelSect, "Sector:   00000", 215, 26, 80, 9
         
           CONTROL ADD LABEL, hDlg, -1, "LogicalBlock", 300, 6, 90, 9
         
           CONTROL ADD TEXTBOX, hDlg, %TextboxLb, "0", 300, 16, 45, 12
         
           CONTROL ADD BUTTON, hDlg, %ButtonRead, "Read", 350, 15, 40, 13
         
           CONTROL ADD BUTTON, hDlg, %ButtonTry, "Try", 360, 33, 20, 13
         
           CONTROL ADD BUTTON, hDlg, %ButtonReadDwn, "-", 305, 31, 15, 15
         
           CONTROL ADD BUTTON, hDlg, %ButtonReadUp, "+", 325, 31, 15, 15
         
           CONTROL ADD LABEL, hDlg, %LabelStatus, "Status", 47, 45, 250, 9
         
           CONTROL ADD LISTBOX, hDlg, %ListboxSect, , 5,  62, 390, 72, _
           %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR %WS_VSCROLL OR _
           %WS_TABSTOP OR %LBS_NOTIFY OR %LBS_USETABSTOPS, %WS_EX_STATICEDGE
           CONTROL SEND hDlg, %ListboxSect, %WM_SETFONT, GetStockObject(%OEM_FIXED_FONT), %TRUE
         
           'SetClassLong(hDlg, %GCL_HICON, LoadIcon(GetModuleHandle(BYVAL 0), BYVAL 101))
           ExtractIconEx("shell32.dll", 8, BYVAL VARPTR(hIconBig), BYVAL VARPTR(hIconSmall), 1)
           SetClassLong(hDlg, %GCL_HICONSM, hIconSmall) 'Set an icon
           SetClassLong(hDlg, %GCL_HICON, hIconBig) 'Set an icon
           SendMessage(hDlg, %WM_SETICON, %ICON_SMALL, hIconSmall)
           SendMessage(hDlg, %WM_SETICON, %ICON_BIG, hIconBig)
         
           DIALOG SHOW MODAL hDlg CALL DlgProc
         
           DestroyIcon(hIconSmall)
           DestroyIcon(hIconBig)
         
        END IF
         
        END FUNCTION
        '_____________________________________________________________________________
        '

        Comment

        Working...
        X