IMAPIv2 for Vista

Share your advanced PureBasic knowledge/code with the community.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

IMAPIv2 for Vista

Post by SFSxOI »

Yet another IMAPIv2 thing for Vista (and XP SP2 if you have the KB update - see remarks in code). The commented items in the Interface's are some things i'm not sure of for full implementation so if anyone has suggestions or ideas....

Converted from msdn VB script example:
http://msdn2.microsoft.com/en-us/library/aa364817.aspx

With help from the code by bingo at:
http://www.purebasic.fr/english/viewtop ... iscmaster2

Anyway, here ya go:

Code: Select all

; see imapi2sample.cpp in sdk
; folder to .iso Vista and winXP SP2
; On XP sp2 you have To install KB932716 (Image Mastering API v2.0) firstVista And winXP SP2 With 
; For testing edit the line: 
; 
; isofile.s = "c:\tmp\mein.iso" 
; foldertoiso.s = "c:\temp\"
; folder To iso created by bingo - http://www.purebasic.fr/english/viewtopic.php?t=29757

Import "shlwapi.lib" 
SHCreateStreamOnFileEx(pszFile.p-unicode,grfMode.l,dwAttributes.l,fCreate.b,pstmTemplate.l,ppstm.l); 
EndImport

#STGM_SHARE_DENY_NONE=$00000040
#STGM_READ=$00000000
#STGM_WRITE = 1 
#STGM_CREATE = $1000 
#STATFLAG_NONAME = 0
#adFileTypeBinary = 1 

Enumeration
  #FsiFileSystemNone = 0 
  #FsiFileSystemISO9660 = 1
  #FsiFileSystemJoliet = 2 
  #FsiFileSystemUDF = 4 
  ;#FsiFileSystemUnknown = 1073741824
  #FsiFileSystemUnknown = $40000000
EndEnumeration

Enumeration ; EmulationType
  #EmulationNone = 0
  #Emulation12MFloppy = 1
  #Emulation144MFloppy = 2
  #Emulation288MFloppy = 3
  #EmulationHardDisk = 4
EndEnumeration

Enumeration ;_#IMAPI_MEDIA_PHYSICAL_TYPE 
  #IMAPI_MEDIA_TYPE_UNKNOWN = 0
  #IMAPI_MEDIA_TYPE_CDROM = $1
  #IMAPI_MEDIA_TYPE_CDR = $2
  #IMAPI_MEDIA_TYPE_CDRW = $3
  #IMAPI_MEDIA_TYPE_DVDROM = $4
  #IMAPI_MEDIA_TYPE_DVDRAM = $5
  #IMAPI_MEDIA_TYPE_DVDPLUSR = $6
  #IMAPI_MEDIA_TYPE_DVDPLUSRW = $7
  #IMAPI_MEDIA_TYPE_DVDPLUSR_DUALLAYER = $8
  #IMAPI_MEDIA_TYPE_DVDDASHR = $9
  #IMAPI_MEDIA_TYPE_DVDDASHRW = $a
  #IMAPI_MEDIA_TYPE_DVDDASHR_DUALLAYER = $b
  #IMAPI_MEDIA_TYPE_DISK = $c
  #IMAPI_MEDIA_TYPE_DVDPLUSRW_DUALLAYER = $0D
  #IMAPI_MEDIA_TYPE_HDDVDROM = $0E
  #IMAPI_MEDIA_TYPE_HDDVDR = $0F
  #IMAPI_MEDIA_TYPE_HDDVDRAM = $10
  #IMAPI_MEDIA_TYPE_BDROM = $11
  #IMAPI_MEDIA_TYPE_BDR = $12
  #IMAPI_MEDIA_TYPE_BDRE = $13
  #IMAPI_MEDIA_TYPE_MAX = $13
EndEnumeration

Interface IBootOptions Extends IDispatch
  get_BootImage(dispidMember.l) 
  get_Manufacturer(dispidMember.l) 
  put_Manufacturer(dispidMember.p-bstr) 
  get_PlatformId(dispidMember.l) 
  put_PlatformId(dispidMember.l) 
  get_Emulation(dispidMember.l) 
  put_Emulation(dispidMember.l) 
  get_ImageSize(dispidMember.l) 
  AssignBootImage(newVal.l) 
EndInterface

Interface IDiscMaster2 Extends IDispatch 
  get__NewEnum(a)
  ;get__NewEnum(ppunk.IEnumVARIANT) ; IEnumVARIANT** ppunk - need IEnumVARIANT?? 
  get_Item(index,value) ; [in]LONG index, [out]BSTR* value
  ;get_Item(index) ; [in]LONG index, [out]BSTR* value
  get_Count(a.l) 
  get_IsSupportedEnvironment(value.l) 
EndInterface

Interface IDiscRecorder2 Extends IDispatch
  EjectMedia() 
  CloseTray() 
  AcquireExclusiveAccess(a.l,b.s)
  ;AcquireExclusiveAccess(a.l,b.p-bstr) ;??
  ReleaseExclusiveAccess() 
  DisableMcn() 
  EnableMcn() 
  InitializeDiscRecorder(a.l)
  get_ActiveDiscRecorder(value.p-bstr)
  get_VendorId(value) 
  get_ProductId(value.p-bstr) 
  get_ProductRevision(value.p-bstr) 
  get_VolumeName(value.p-bstr) 
  get_VolumePathNames(a) ;??
  ;get_VolumePathNames(value.SAFEARRAY) ; ???
  get_DeviceCanLoadMedia(a.l) 
  get_LegacyDeviceNumber(a.l) 
  get_SupportedFeaturePages(a)
  ;get_SupportedFeaturePages(value.SAFEARRAY) ;?? 
  get_CurrentFeaturePages(a)
  ;get_CurrentFeaturePages(value.SAFEARRAY) ;??
  get_SupportedProfiles(a)
  ;get_SupportedProfiles(value.SAFEARRAY) ;??
  get_CurrentProfiles(a)
  ;get_CurrentProfiles(value.SAFEARRAY) ;??
  get_SupportedModePages(a)
  ;get_SupportedModePages(value.SAFEARRAY) ;?? 
  ;get_ExclusiveAccessOwner(a)
  get_ExclusiveAccessOwner(value.p-bstr) 
EndInterface 

Interface IFileSystemImage Extends IDispatch
  get_Root(dispidMember.l) 
  get_SessionStartBlock(dispidMember.l) 
  put_SessionStartBlock(dispidMember.l) 
  get_FreeMediaBlocks(dispidMember.l) 
  put_FreeMediaBlocks(dispidMember.l) 
  SetMaxMediaBlocksFromDevice(discRecorder.l) 
  get_UsedBlocks(discRecorder.l) 
  get_VolumeName(discRecorder.l) 
  put_VolumeName(discRecorder.p-bstr) 
  get_ImportedVolumeName(discRecorder.l) 
  get_BootImageOptions(discRecorder.l) 
  put_BootImageOptions(discRecorder.l) 
  get_FileCount(discRecorder.l) 
  get_DirectoryCount(discRecorder.l) 
  get_WorkingDirectory(discRecorder.l) 
  put_WorkingDirectory(discRecorder.p-bstr) 
  get_ChangePoint(discRecorder.l) 
  get_StrictFileSystemCompliance(discRecorder.l) 
  put_StrictFileSystemCompliance(discRecorder.w) 
  get_UseRestrictedCharacterSet(discRecorder.l) 
  put_UseRestrictedCharacterSet(discRecorder.w) 
  get_FileSystemsToCreate(discRecorder.l) 
  put_FileSystemsToCreate(discRecorder.l) 
  get_FileSystemsSupported(discRecorder.l) 
  put_UDFRevision(discRecorder.l) 
  get_UDFRevision(discRecorder.l) 
  get_UDFRevisionsSupported(discRecorder.l) 
  ChooseImageDefaults(discRecorder.l) 
  ChooseImageDefaultsForMediaType(value.l) 
  put_ISO9660InterchangeLevel(value.l) 
  get_ISO9660InterchangeLevel(value.l) 
  get_ISO9660InterchangeLevelsSupported(value.l) 
  CreateResultImage(a.l) 
  Exists(FullPath.p-bstr) 
  ;CalculateDiscIdentifier() ;<<<<<<<<<<<<<<<<<
  CalculateDiscIdentifier(discIdentifier.p-bstr)
  IdentifyFileSystemsOnDisc(discRecorder.l) 
  GetDefaultFileSystemForImport(fileSystems.l) 
  ;ImportFileSystem() ;<<<<<<<<<<<<<<<<<
  ImportFileSystem(importedFileSystem.l) 
  ImportSpecificFileSystem(fileSystemToUse.l) 
  RollbackToChangePoint(ChangePoint.l) 
  LockInChangePoint() 
  CreateDirectoryItem(Name.p-bstr) 
  CreateFileItem(Name.p-bstr) 
  get_VolumeNameUDF(Name.l) 
  get_VolumeNameJoliet(Name.l) 
  get_VolumeNameISO9660(Name.l) 
  get_StageFiles(Name.l) 
  put_StageFiles(Name.w) 
  get_MultisessionInterfaces(Name.l) 
  put_MultisessionInterfaces(Name.l) 
EndInterface

Interface IFileSystemImage2 Extends IFileSystemImage
  get_BootImageOptionsArray(pVal.l)
  put_BootImageOptionsArray(newVal.l)
EndInterface

Interface IFileSystemImageResult Extends IDispatch 
  get_ImageStream(dispidMember.l) 
  get_ProgressItems(dispidMember.l) 
  get_TotalBlocks(dispidMember.l) 
  get_BlockSize(dispidMember.l) 
  get_DiscId(dispidMember.l) 
EndInterface

Interface IDiscFormat2 Extends IDispatch
  IsRecorderSupported(recorder.l, value.l) ; [in]IDiscRecorder2* recorder, [out]VARIANT_BOOL* value
  IsCurrentMediaSupported(recorder.l, value.l) ; [in]IDiscRecorder2* recorder, [out]VARIANT_BOOL* value
  get_MediaPhysicallyBlank(value.l) ; [out]VARIANT_BOOL* value
  get_MediaHeuristicallyBlank(value.l) ; [out]VARIANT_BOOL* value
  get_SupportedMediaTypes(value.l) ; [out]SAFEARRAY* value
EndInterface

Interface IDiscFormat2Erase Extends IDiscFormat2
  put_Recorder(value) ;[in]IDiscRecorder2* value - value = An IDiscRecorder2 Interface that identifies the recording device To use in the erase operation
  get_Recorder(value) ; [out]IDiscRecorder2** value - value = An IDiscRecorder2 Interface that identifies the recording device To use in the erase operation
  put_FullErase(value) ; [in]VARIANT_BOOL value - value = #VARIANT_TRUE to fully erase the disc by overwriting the entire medium at least once. Set #VARIANT_FALSE To 
  ;overwrite the directory tracks, but Not entire disc. #VARIANT_FALSE requires less time To perform than the full erase option. The Default is VARIANT_FALSE.
  get_FullErase(value) ;[out]VARIANT_BOOL* value - value = #VARIANT_TRUE if the erase operation fully erases the disc by overwriting the entire medium at least once.
  ; #VARIANT_FALSE If the erase operation overwrites the directory tracks, but Not the entire disc. This option requires less time To perform than the full erase option
  ;this is the quick erase
  get_CurrentPhysicalMediaType(value) ; [out]IMAPI_MEDIA_PHYSICAL_TYPE* value - see the IMAPI_MEDIA_PHYSICAL_TYPE enumeration type
  put_ClientName(value.p-bstr) ; [in]BSTR value
  get_ClientName(value) ; [out]BSTR* value
  EraseMedia()
EndInterface

Interface IDiscFormat2Data Extends IDiscFormat2
  put_Recorder(Recorder.l)
  get_Recorder(Recorder.l)
  put_BufferUnderrunFreeDisabled(Recorder.w)
  get_BufferUnderrunFreeDisabled(Recorder.l)
  put_PostgapAlreadyInImage(Recorder.w)
  get_PostgapAlreadyInImage(Recorder.l)
  get_CurrentMediaStatus(Recorder.l)
  get_WriteProtectStatus(Recorder.l)
  get_TotalSectorsOnMedia(Recorder.l)
  get_FreeSectorsOnMedia(Recorder.l)
  get_NextWritableAddress(Recorder.l)
  get_StartAddressOfPreviousSession(Recorder.l)
  get_LastWrittenAddressOfPreviousSession(Recorder.l)
  put_ForceMediaToBeClosed(Recorder.w)
  get_ForceMediaToBeClosed(value.l)
  put_DisableConsumerDvdCompatibilityMode(Recorder.w)
  get_DisableConsumerDvdCompatibilityMode(Recorder.l)
  get_CurrentPhysicalMediaType(Recorder.l)
  put_ClientName(Recorder.p-bstr)
  get_ClientName(Recorder.p-bstr)
  get_RequestedWriteSpeed(Recorder.l)
  get_RequestedRotationTypeIsPureCAV(Recorder.l)
  get_CurrentWriteSpeed(Recorder.l)
  get_CurrentRotationTypeIsPureCAV(Recorder.l)
  get_SupportedWriteSpeeds(Recorder.l)
  get_SupportedWriteSpeedDescriptors(Recorder.l)
  put_ForceOverwrite(Recorder.w) 
  get_ForceOverwrite(Recorder.l)
  get_MultisessionInterfaces(Recorder.l)
  Write(Data_.l)
  CancelWrite()
  SetWriteSpeed(RequestedSectorsPerSecond.l,RotationTypeIsPureCAV.w)
EndInterface

Interface IFsiItem Extends IDispatch
  get_Name(pVal.l)
  get_FullPath(pVal.l)
  get_CreationTime(pVal.l)
  put_CreationTime(newVal.l)
  get_LastAccessedTime(pVal.l)
  put_LastAccessedTime(newval.l)
  get_LastModifiedTime(pVal.l)
  put_LastModifiedTime(newVal.l)
  get_IsHidden(pVal.l)
  put_IsHidden(newVal.l)
  FileSystemName(fileSystem.l, pVal.l)
  FileSystemPath(fileSystem.l, pVal.l)
EndInterface

Interface IFsiDirectoryItem Extends IFsiItem
  get__NewEnum(fileSystem.l) 
  get_Item(path.p-bstr) 
  get_Count(path.l) 
  get_EnumFsiItems(path.l) 
  AddDirectory(path.p-bstr) 
  AddFile(path.p-bstr,fileData.l) 
  AddTree(sourceDirectory.p-bstr,includeBaseDirectory.w) 
  Add(Item.l) 
  Remove(path.p-bstr) 
  RemoveTree(path.p-bstr) 
EndInterface

Interface IFsiFileItem Extends IFsiItem
  get_DataSize(pVal.l)
  get_DataSize32BitLow(pVal.l)
  get_DataSize32BitHigh(pVal.l)
  get_Data(pVal.l)
  put_Data(newVal.l)
EndInterface

pp.variant 
pp\vt = #VT_BSTR 

Index = 0 ; only one drive at this time, first drive at index 0 
Path$ = "C:\somefolder" 
Volume_Name$ = "My_VOLUME_NAME" 
Type_File_Sys.l = #FsiFileSystemJoliet 

burnstream.IStream ; stream 

CreateStreamOnHGlobal_(0,#True,@burnstream) ; create the stream 
CoInitialize_(0) 

;Create a DiscMaster2 object to connect to optical drives 
  If CoCreateInstance_(?CLSID_MsftDiscMaster2,0,1,?IID_IDiscMaster2,@DiscMaster.IDiscMaster2) = 0 
  
  ; Create a DiscRecorder object for the specified burning device 
    If CoCreateInstance_(?CLSID_MsftDiscRecorder2,0,1,?IID_IDiscRecorder2,@Recorder.IDiscRecorder2) = 0 
    ;pp\bstrval contains the uniqueId referenced at msdn example 
    DiscMaster\get_Item(Index,@pp\bstrval) ; we find our drive - enumerate for all drives 
    Recorder\InitializeDiscRecorder(pp\bstrval) ;init our selected drive 
    
    ;Create a new file system image And retrieve root directory / create an image stream for a specified directory 
      If CoCreateInstance_(?CLSID_MsftFileSystemImage,0,1,?IID_IFileSystemImage,@FSIOBJ.IFileSystemImage) = 0 
      FSIOBJ\put_FreeMediaBlocks(0) ;infinite number of blocks = 0 - not in msdn example, I added 
      FSIOBJ\put_FileSystemsToCreate(Type_File_Sys) ; not in msdn example, I added 
      FSIOBJ\put_VolumeName(Volume_Name$) ; not in msdn example, I added 
      FSIOBJ\get_root(@DIROBJ.IFsiDirectoryItem) 
      
      ;create the new disc format and set the recorder 
        If CoCreateInstance_(?CLSID_MsftDiscFormat2Data,0,1,?IID_IDiscFormat2Data,@dataWriter.IDiscFormat2Data) = 0 
        
        dataWriter\put_Recorder(Recorder) ; set the recorder 
        dataWriter\put_ClientName("IMAPIv2") ; the client name 
        dataWriter\SetWriteSpeed($FFFFFFFF, #VARIANT_FALSE) ; not in msdn example, I added 
        FSIOBJ\ChooseImageDefaults(Recorder) 
        ; Add the directory and its contents to the file system 
        DIROBJ\AddTree(Path$, #VARIANT_FALSE) ; change #VARIANT_FALSE to #VARIANT_TRUE to include the root folder 
        ; Create an image from the file system 
        FSIOBJ\CreateResultImage(@result.IFileSystemImageResult) 
        result\get_ImageStream(@burnstream) 
        ;Write stream to disc using the specified recorder 
        ;put_ForceMediaToBeClosed causes the CD\DVD to be closed 
        dataWriter\put_ForceMediaToBeClosed(#VARIANT_TRUE) ; this has to come before the write to tell it what to do when the burn is complete 
        dataWriter\write(burnstream) 
        
        EndIf 
      EndIf 
    EndIf 
  EndIf 


Recorder\EjectMedia() ;eject the tray 
; release stuff and clean up 
FSIOBJ\Release() 
DIROBJ\Release() 
DiscMaster\Release() 
Recorder\Release() 
dataWriter\Release() 
burnstream\Release() 

CoUninitialize_() 

End ; finished



DataSection
  CLSID_BootOptions:
    Data.l $2C941FCE
    Data.w $975B,$59BE 
    Data.b $A9,$60,$9A,$2A,$26,$28,$53,$A5
  CLSID_MsftFileSystemImage:
    Data.l $2C941FC5
    Data.w $975B,$59BE 
    Data.b $A9,$60,$9A,$2A,$26,$28,$53,$A5
  CLSID_MsftDiscMaster2:
    Data.l $2735412E
    Data.w $7F64,$5B0F 
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E 
  CLSID_MsftDiscRecorder2: 
    Data.l $2735412D
    Data.w $7F64,$5B0F 
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
  CLSID_MsftDiscFormat2Data:
    Data.l $2735412A
    Data.w $7F64,$5B0F
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
  CLSID_MsftDiscFormat2Erase:
    Data.l $2735412B
    Data.w $7F64,$5B0F
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
  IID_IBootOptions:
    Data.l $2C941FD4 
    Data.w $975B,$59BE 
    Data.b $A9,$60,$9A,$2A,$26,$28,$53,$A5 
  IID_IFileSystemImage: 
    Data.l $2C941FE1 
    Data.w $975B,$59BE 
    Data.b $A9,$60,$9A,$2A,$26,$28,$53,$A5 
  IID_IDiscMaster2:
    Data.l $27354130 
    Data.w $7F64,$5B0F 
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E 
  IID_IDiscRecorder2: 
    Data.l $27354133 
    Data.w $7F64,$5B0F 
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
  IID_IDiscFormat2Data:
    Data.l $27354153 
    Data.w $9F64,$5B0F 
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
  IID_IDiscFormat2Erase:
    Data.l $27354156
    Data.w $8F64,$5B0F
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
EndDataSection
Last edited by SFSxOI on Wed Jan 16, 2008 12:30 am, edited 8 times in total.
harff182
Enthusiast
Enthusiast
Posts: 105
Joined: Thu Dec 08, 2005 4:58 pm
Location: Duesseldorf, Germany

Post by harff182 »

I just stumbled over your code...
... and I don't understand much of it :oops: , as it only opens my first drive.

Since I still look for a reliable way to check, what kind of media is in one of my drives ( I have 2 Burners at y: and z: ), I ask myself (without answers ;) ), how this code has to be changed to be used as a procedure, that gets a drive-letter and returns the type of media in the drive.

Could you be so gracious and show me/us how that could be done ?

tia... scholly
Sorry 4 my poor English, it's the only one I learned 40 years ago...
since 17.12.08: XPHome(SP3) + PB 4.30
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

the above code is for only a single burner in the computer. It should however select the first drive in the computer which would be at index 0.

It burns a folder of files to CD or DVD, then opens the drive after its finished burning the CD/DVD.

Yes, you can return the type of media and a specific drive. I didn't do any of the media parameters checks in the above, but i kind of alluded to the drives...you have to enumerate the drives with IMAPIv2 to get them all then select the one you want to use, I'm working on multiple drives and when i get something working i'll post it for you.
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Post by Hroudtwolf »

Thank you very much for sharing this code and your knowledge.

Best regards

Wolf
harff182
Enthusiast
Enthusiast
Posts: 105
Joined: Thu Dec 08, 2005 4:58 pm
Location: Duesseldorf, Germany

Post by harff182 »

@SFSxOI: Thanks for clearing it up for me.

Well, I don't know whether you are interested in some tests or whether they can help you, but I did some out of sheer curiosity :)

My system:
- WinXP Home SP2 (uptodate)
- PB 4.10
- Index = 0 :arrow: y:\ = secondary slave = LG 4163B
- Index = 1 :arrow: z:\ = primary slave = Samsung SH-S182D

using Index = 0:

Test 1: Medium = CDRW (new)................: works
Test 2: Medium = CDRW (quick erased)....: works
Test 3: Medium = DVD+RW (new)............: works
Test 4: Medium = DVD+RW (quick erased): doesn't work
Test 5: Medium = DVD+RW (full erased)...: works

using Index = 1:

Test 6: Medium = CDRW (quick erased)....: works
Test 7: Medium = DVD+RW (quick erased): doesn't work
Test 8: Medium = DVD+RW (full erased)...: works

hihalb... scholly
Last edited by harff182 on Tue Jan 15, 2008 6:33 pm, edited 2 times in total.
Sorry 4 my poor English, it's the only one I learned 40 years ago...
since 17.12.08: XPHome(SP3) + PB 4.30
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

DVD+RW -----------quick erase is, from what I understand so far has something to do with the interface:

Code: Select all

Interface IDiscFormat2 Extends IDispatch
  IsRecorderSupported(recorder.l, value.l) ; [in]IDiscRecorder2* recorder, [out]VARIANT_BOOL* value
  IsCurrentMediaSupported(recorder.l, value.l) ; [in]IDiscRecorder2* recorder, [out]VARIANT_BOOL* value
  get_MediaPhysicallyBlank(value.l) ; [out]VARIANT_BOOL* value
  get_MediaHeuristicallyBlank(value.l) ; [out]VARIANT_BOOL* value
  get_SupportedMediaTypes(value.l) ; [out]SAFEARRAY* value
EndInterface
and in particular the interface function 'get_MediaPhysicallyBlank' which is mainly for DVD+RW and DVD-RAM media.

I also noticed that the quick erase issue seems to involve the DVD+RW, it could be that your recorders don't natively support quick erase for this type of media and needs some outside help from what ever burning software you use....which leads us back to the IDiscFormat2 Interface. BTW - quick erase doesn't erase the whole disc, it only removes the directories and their structure.
Last edited by SFSxOI on Sun Jan 13, 2008 3:47 pm, edited 1 time in total.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

OK, got the erase figured out I think, this is how to do a disc erase. Add the below to the code from the first post:

@harff182 - see the part below about the quick erase

Code: Select all

Procedure EraseDisc(erse_yn.l) ; erse_yn = either #VARIANT_TRUE = full erase - takes a while, #VARIANT_FALSE = Quick erase - pretty fast
Index.l = 0 ; only one recorder the first one at index 0
pp.variant 
pp\vt = #VT_BSTR

CoInitialize_(0)
objDiscMaster = CoCreateInstance_(?CLSID_MsftDiscMaster2,0,1,?IID_IDiscMaster2,@DiscMaster.IDiscMaster2)
DiscMaster_Item = DiscMaster\get_Item(Index,@pp\bstrval)
   
objEraseRecorder = CoCreateInstance_(?CLSID_MsftDiscRecorder2,0,1,?IID_IDiscRecorder2,@EraseRecorder.IDiscRecorder2)
init = EraseRecorder\InitializeDiscRecorder(pp\bstrval)
    
objEraser = CoCreateInstance_(?CLSID_MsftDiscFormat2Erase,0,1,?IID_IDiscFormat2Erase,@Eraser.IDiscFormat2Erase)
Erase_Recorder = Eraser\put_Recorder(EraseRecorder)
Media_Type = Eraser\get_CurrentPhysicalMediaType(@mediaType)
;// CLIENT NAME REQUIRED - any name you choose to use
Client_Name = Eraser\put_ClientName("my_app")
Full_Quick = Eraser\put_FullErase(erse_yn) ;#VARIANT_TRUE = full erase - takes a while, #VARIANT_FALSE = Quick erase - pretty fast    
Erase_Media = Eraser\EraseMedia()

DiscMaster\Release()
EraseRecorder\Release()   
Eraser\Release()

CoUninitialize_()
        
EndProcedure
This is actually beginning to look easy, simple steps are the same each time:

1. do the interface
2. do the CLSID and IID
3. create the objects
4. do the action
5. release the objects

Anyone else seeing a trend here? :)

The biggest pain so far seems to be three things, making sure the values are correct in the interface, passing the correct values, and then making sure things are in the right order. IMAPI seems very literal, things have to happen in a certain order.
Last edited by SFSxOI on Tue Jan 15, 2008 2:06 am, edited 5 times in total.
harff182
Enthusiast
Enthusiast
Posts: 105
Joined: Thu Dec 08, 2005 4:58 pm
Location: Duesseldorf, Germany

Post by harff182 »

Seems my English really is not good enough to express what I want to say :oops: Hope I do better now.

My tests were "writing a folder to medium" and the part in brackets should show the state of the RWs I tried.
So I didn't try to erase the disks, I tried to burn to them.

I normally use the freeware "CDBurnerXP Pro 3.0.116" to burn and erase and had never probs to write to quick-erased-DVD-RWs, so I thought, I tell you about the failure when trying to burn to them.

Sorry, my only personal interest is to use part of your code to get the correct media-type for my video-database, as I want to replace the ComboBoxGadget with a procedure, that returns the type reliably.
As I understand very little of your code, I can't even strip it down to the procedure I can use.

But shurely, if you want me to test something, I will try to help, as there's nothing more I can offer.

tia... scholly
Sorry 4 my poor English, it's the only one I learned 40 years ago...
since 17.12.08: XPHome(SP3) + PB 4.30
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

If you already have a .iso file that you want to burn to CD or DVD, you do it like this:

Code: Select all

Procedure IsoToDisk(file_complete_path.s) ;file_complete_path.s looks like this "E:\My_iso.iso" 
pp.variant 
pp\vt = #VT_BSTR

Index = 0 ; only one drive
strISOFile$ = file_complete_path

objStream.IStream

CoInitialize_(0)

Create_objDiscMaster = CoCreateInstance_(?CLSID_MsftDiscMaster2,0,1,?IID_IDiscMaster2,@DiscMaster.IDiscMaster2)
Get_Recorder_Unique_ID = DiscMaster_Item = DiscMaster\get_Item(Index,@pp\bstrval)
; pp\bstrval = UniqueID

Create_objRecorder = CoCreateInstance_(?CLSID_MsftDiscRecorder2,0,1,?IID_IDiscRecorder2,@Recorder.IDiscRecorder2)
init_Recorder = Recorder\InitializeDiscRecorder(pp\bstrval)

Ceate_objDataWriter = CoCreateInstance_(?CLSID_MsftDiscFormat2Data,0,1,?IID_IDiscFormat2Data,@dataWriter.IDiscFormat2Data)
Assign_Data_Writer_Recorder = dataWriter\put_Recorder(Recorder)
;//Client name is required - can be anything you want
Put_Client_Name = dataWriter\put_ClientName("ISOTest1")

Create_objStream = SHCreateStreamOnFileEx(strISOFile$,#STGM_READ|#STGM_SHARE_DENY_NONE,0,0,0,@objStream)

If DataWriter\get_NextWritableAddress(Recorder) = 0
    Wite_ISO_to_Disc = DataWriter\Write(objStream)
    Debug "Done"
Else
    Debug "Cannot write to disc"
EndIf

DiscMaster\Release()

; you don't do a Recorder\Release() this time because when the write is
;done the recorder is automatically released. If you try to release it here
;you will get an Invalid Memory Access error (although the .iso will still
;have burned to CD/DVD just fine. 

dataWriter\Release()
objStream\Release()

CoUninitialize_()

EndProcedure
Just add this to the code in the first post in this thread. Don't forget to release the objects and the stream.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

@harff182

Look above at the erase code (Procedure EraseDisc(erse_yn.l)), see the line:

Code: Select all

Media_Type = Eraser\get_CurrentPhysicalMediaType(@mediaType)
Thats how you get the media type, it gives you a hex value, then look at the Enumeration ;_#IMAPI_MEDIA_PHYSICAL_TYPE at the top of the code in the first post to find out what type of media it is.

The erase code also has the option to do a quick erase like you showed interest in, read the comments in the code. See if that quick erase works OK for you now, works fine here for Sony DVD+RW.

Also; here is some very rough code, and there is a lot of bloat in this sample and some un-needed items, but it should give you an idea to help you get some of the information you were seeking. It should enumerate all the recorders on your machine and provide the ID of the drive, the vendor, and the current type of media in the drive in the form of a hex number. You can look at the enumeration 'Enumeration ;_#IMAPI_MEDIA_PHYSICAL_TYPE' to match the value given to the type of media. i put this together real fast so I didn't do a select/case thing to provide a friendly name of each type of media but you should be bale to figure it out from here, so here ya go:

Code: Select all

Enumeration ;_#IMAPI_MEDIA_PHYSICAL_TYPE 
  #IMAPI_MEDIA_TYPE_UNKNOWN = 0
  #IMAPI_MEDIA_TYPE_CDROM = $1
  #IMAPI_MEDIA_TYPE_CDR = $2
  #IMAPI_MEDIA_TYPE_CDRW = $3
  #IMAPI_MEDIA_TYPE_DVDROM = $4
  #IMAPI_MEDIA_TYPE_DVDRAM = $5
  #IMAPI_MEDIA_TYPE_DVDPLUSR = $6
  #IMAPI_MEDIA_TYPE_DVDPLUSRW = $7
  #IMAPI_MEDIA_TYPE_DVDPLUSR_DUALLAYER = $8
  #IMAPI_MEDIA_TYPE_DVDDASHR = $9
  #IMAPI_MEDIA_TYPE_DVDDASHRW = $a
  #IMAPI_MEDIA_TYPE_DVDDASHR_DUALLAYER = $b
  #IMAPI_MEDIA_TYPE_DISK = $c
  #IMAPI_MEDIA_TYPE_DVDPLUSRW_DUALLAYER = $0D
  #IMAPI_MEDIA_TYPE_HDDVDROM = $0E
  #IMAPI_MEDIA_TYPE_HDDVDR = $0F
  #IMAPI_MEDIA_TYPE_HDDVDRAM = $10
  #IMAPI_MEDIA_TYPE_BDROM = $11
  #IMAPI_MEDIA_TYPE_BDR = $12
  #IMAPI_MEDIA_TYPE_BDRE = $13
  #IMAPI_MEDIA_TYPE_MAX = $13
EndEnumeration

Interface IDiscMaster2 Extends IDispatch 
  get__NewEnum(a)
  ;get__NewEnum(ppunk.IEnumVARIANT) ; IEnumVARIANT** ppunk - need IEnumVARIANT?? 
  get_Item(index,value) ; [in]LONG index, [out]BSTR* value
  ;get_Item(index) ; [in]LONG index, [out]BSTR* value
  get_Count(a.l) 
  get_IsSupportedEnvironment(value.l) 
EndInterface

Interface IDiscRecorder2 Extends IDispatch
  EjectMedia() 
  CloseTray() 
  AcquireExclusiveAccess(a.l,b.s)
  ;AcquireExclusiveAccess(a.l,b.p-bstr) ;??
  ReleaseExclusiveAccess() 
  DisableMcn() 
  EnableMcn() 
  InitializeDiscRecorder(a.l)
  get_ActiveDiscRecorder(value.p-bstr)
  ;get_VendorId(value.p-bstr)
  get_VendorId(value) 
  get_ProductId(value) 
  get_ProductRevision(value) 
  ;get_VolumeName(value.p-bstr)
  get_VolumeName(value) 
  get_VolumePathNames(value) ;??
  ;get_VolumePathNames(value.SAFEARRAY) ; ???
  get_DeviceCanLoadMedia(a.l) 
  get_LegacyDeviceNumber(a.l) 
  get_SupportedFeaturePages(a)
  ;get_SupportedFeaturePages(value.SAFEARRAY) ;?? 
  get_CurrentFeaturePages(a)
  ;get_CurrentFeaturePages(value.SAFEARRAY) ;??
  get_SupportedProfiles(a)
  ;get_SupportedProfiles(value.SAFEARRAY) ;??
  get_CurrentProfiles(a)
  ;get_CurrentProfiles(value.SAFEARRAY) ;??
  get_SupportedModePages(a)
  ;get_SupportedModePages(value.SAFEARRAY) ;?? 
  ;get_ExclusiveAccessOwner(a)
  get_ExclusiveAccessOwner(value) 
EndInterface 

Interface IDiscFormat2 Extends IDispatch
  IsRecorderSupported(recorder.l, value.l)
  IsCurrentMediaSupported(recorder.l, value.l)
  get_MediaPhysicallyBlank(value.l)
  get_MediaHeuristicallyBlank(value.l)
  get_SupportedMediaTypes(value.l)
EndInterface

Interface IDiscFormat2Erase Extends IDiscFormat2
  put_Recorder(value) 
  get_Recorder(value) 
  put_FullErase(value)
  get_FullErase(value)
  get_CurrentPhysicalMediaType(value)
  put_ClientName(value.p-bstr)
  get_ClientName(value)
  EraseMedia()
EndInterface

pp.variant 
pp\vt = #VT_BSTR

CoInitialize_(0)
CoCreateInstance_(?CLSID_MsftDiscMaster2,0,1,?IID_IDiscMaster2,@DiscMaster.IDiscMaster2)
DiscMaster\get_Count(@count)
DiscMaster\get_Item(Index,@pp\bstrval)
   
CoCreateInstance_(?CLSID_MsftDiscRecorder2,0,1,?IID_IDiscRecorder2,@Recorder.IDiscRecorder2)
Recorder\InitializeDiscRecorder(pp\bstrval)
    
CoCreateInstance_(?CLSID_MsftDiscFormat2Erase,0,1,?IID_IDiscFormat2Erase,@Format.IDiscFormat2Erase)
Format\put_Recorder(Recorder)

For x = 0 To count

  If x = count
  Break
  EndIf
    DiscMaster\get_Item(x,@pp\bstrval)
    Recorder\InitializeDiscRecorder(pp\bstrval)
    Debug "drive:   " +Str(count) +"   is ID:    " +Uni2Ansi(pp\bstrval)
    med_type = Format\get_CurrentPhysicalMediaType(@mediaType)
           
    Select mediaType
    
      Case #IMAPI_MEDIA_TYPE_UNKNOWN
      Debug "Media Type is Unknown or no media loaded"
      
      Case #IMAPI_MEDIA_TYPE_CDROM
      Debug "Media Type is CDROM"
      
      Case #IMAPI_MEDIA_TYPE_CDR
      Debug "Media Type is CDR"
      
      Case #IMAPI_MEDIA_TYPE_CDRW
      Debug "Media Type is CD-R/W"
      
      Case #IMAPI_MEDIA_TYPE_DVDROM
      Debug "Media Type is DVD-ROM"
      
      Case #IMAPI_MEDIA_TYPE_DVDRAM
      Debug "Media Type is DVD-RAM"
      
      Case #IMAPI_MEDIA_TYPE_DVDPLUSR
      Debug "Media Type is DVD-Plus R"
      
      Case #IMAPI_MEDIA_TYPE_DVDPLUSRW
      Debug "Media Type is DVD-Plus R/W"
      
      Case #IMAPI_MEDIA_TYPE_DVDPLUSR_DUALLAYER
      Debug "Media Type is DVD-Plus R Dual Layer"
    
    EndSelect
    
    Recorder\get_VendorId(@pp\bstrval) 
    Debug Uni2Ansi(pp\bstrval)
    Recorder\get_ProductId(@pp\bstrval)
    Debug Uni2Ansi(pp\bstrval)
    Recorder\get_ProductRevision(@pp\bstrval)
    Debug Uni2Ansi(pp\bstrval)
    Recorder\get_VolumeName(@pp\bstrval)
    Debug Uni2Ansi(pp\bstrval)
    Recorder\get_VolumePathNames(@pp\bstrval) ;;;<<<<< this doesn't work yet, gotta work out a SAFEARRAY thing first
    Debug Uni2Ansi(pp\bstrval)
Next x

DiscMaster\Release()
Recorder\Release()   
Format\Release()

CoUninitialize_()
        
End


DataSection
  CLSID_BootOptions:
    Data.l $2C941FCE
    Data.w $975B,$59BE 
    Data.b $A9,$60,$9A,$2A,$26,$28,$53,$A5
  CLSID_MsftFileSystemImage:
    Data.l $2C941FC5
    Data.w $975B,$59BE 
    Data.b $A9,$60,$9A,$2A,$26,$28,$53,$A5
  CLSID_MsftDiscMaster2:
    Data.l $2735412E
    Data.w $7F64,$5B0F 
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E 
  CLSID_MsftDiscRecorder2: 
    Data.l $2735412D
    Data.w $7F64,$5B0F 
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
  CLSID_MsftDiscFormat2Data:
    Data.l $2735412A
    Data.w $7F64,$5B0F
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
  CLSID_MsftDiscFormat2Erase:
    Data.l $2735412B
    Data.w $7F64,$5B0F
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
  IID_IBootOptions:
    Data.l $2C941FD4 
    Data.w $975B,$59BE 
    Data.b $A9,$60,$9A,$2A,$26,$28,$53,$A5 
  IID_IFileSystemImage: 
    Data.l $2C941FE1 
    Data.w $975B,$59BE 
    Data.b $A9,$60,$9A,$2A,$26,$28,$53,$A5 
  IID_IDiscMaster2:
    Data.l $27354130 
    Data.w $7F64,$5B0F 
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E 
  IID_IDiscRecorder2: 
    Data.l $27354133 
    Data.w $7F64,$5B0F 
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
  IID_IDiscFormat2Data:
    Data.l $27354153 
    Data.w $9F64,$5B0F 
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
  IID_IDiscFormat2Erase:
    Data.l $27354156
    Data.w $8F64,$5B0F
    Data.b $8F,$00,$5D,$77,$AF,$BE,$26,$1E
EndDataSection

Last edited by SFSxOI on Wed Jan 16, 2008 1:19 am, edited 2 times in total.
harff182
Enthusiast
Enthusiast
Posts: 105
Joined: Thu Dec 08, 2005 4:58 pm
Location: Duesseldorf, Germany

Post by harff182 »

SFSxOI wrote: It should enumerate all the recorders on your machine and provide the ID of the drive, the vendor, and the current type of media in the drive in the form of a hex number.
If I enable Procedure.s Uni2Ansi(unicode.l) I get
POLINK: error: Unresolved external symbol '_SHUnicodeToAnsi.
If I replace Uni2Ansi() by Str(), the code compiles, but I only get "0" for the media, no matter what kind is inside the drive(s):
drive: 0 is ID: 1397540
media type is: 0
1480508

drive: 1 is ID: 1465436
media type is: 0
1483244
I tested with CD-R, CD-RW, DVD-RAM, DVD-R and DVD+RW.

:cry: helpless... scholly
Sorry 4 my poor English, it's the only one I learned 40 years ago...
since 17.12.08: XPHome(SP3) + PB 4.30
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

You get the POLINK error because you have a library installed that uses the Uni2Ansi already, maybe the Droopy library possibly. Just comment out the procedure in the code and don't use it, I just included it for those that don't have a library with the function already.

I corrected the code above, it should work now except for the get_VolumePathNames function as commented in the code.

harff182 wrote:
SFSxOI wrote: It should enumerate all the recorders on your machine and provide the ID of the drive, the vendor, and the current type of media in the drive in the form of a hex number.
If I enable Procedure.s Uni2Ansi(unicode.l) I get
POLINK: error: Unresolved external symbol '_SHUnicodeToAnsi.
If I replace Uni2Ansi() by Str(), the code compiles, but I only get "0" for the media, no matter what kind is inside the drive(s):
drive: 0 is ID: 1397540
media type is: 0
1480508

drive: 1 is ID: 1465436
media type is: 0
1483244
I tested with CD-R, CD-RW, DVD-RAM, DVD-R and DVD+RW.

:cry: helpless... scholly
harff182
Enthusiast
Enthusiast
Posts: 105
Joined: Thu Dec 08, 2005 4:58 pm
Location: Duesseldorf, Germany

Post by harff182 »

After removing the Droopy-stuff (that I installed for testing long ago), I tried your code.
Uni2Ansi() is missing, as I expected, so I replace it with Str().
Now I get infos about the media, BUT always the mediatype of x = 0 for both !!!

If I put in the procedure Uni2Ansi() from your former code:
SHUnicodeToAnsi() is not a function, array or linked list

Seems it is NOT found anywhere else.

If I now put in the Import "shlwapi.lib", I get the Linker error again:
POLINK: error: Unresolved external symbol '_SHUnicodeToAnsi'.

I'm lost....

Another thing I don't understand:
- if I check empty or burned CD-RW, DVD-RAM, DVD+RW or DVD+R, I get the right info
- if I check empty CD-R or DVD-R, I get the right info
- if I check burned CD-R or DVD-R, I get "CDROM" and "DVD-ROM"

However, this doesn't seem to be a result of your code, since I cross-checked with the vbs-script and got those (FMPOV) wrong results, too.
Sorry 4 my poor English, it's the only one I learned 40 years ago...
since 17.12.08: XPHome(SP3) + PB 4.30
jack
Addict
Addict
Posts: 1358
Joined: Fri Apr 25, 2003 11:10 pm

Post by jack »

just copy and paste the Uni2Ansi procedure from here http://www.purebasic.fr/english/viewtop ... ght=comlib
harff182
Enthusiast
Enthusiast
Posts: 105
Joined: Thu Dec 08, 2005 4:58 pm
Location: Duesseldorf, Germany

Post by harff182 »

@jack
Wow, no I can see real values instead of numbers.
Thanks a lot...

@SFSxOI
after inserting this proc, the output shows, that only

Code: Select all

Recorder\InitializeDiscRecorder(pp\bstrval)
shows an info of the sh-s182d (x=1); all other infos are from the GSA-4163B (x=0):
Debugger wrote: drive: 0 is ID: \\?\ide#cdromhl-dt-st_dvdram_gsa-4163b_______________a106____#334b354333313242313020322020202020202020#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}
Media Type is DVD-ROM
HL-DT-ST
DVDRAM GSA-4163B
A106
\\?\Volume{fcfbbcce-478a-11dc-bd62-806d6172696f}\
?
drive: 1 is ID: \\?\ide#cdromtsstcorp_cd#dvdw_sh-s182d_______________sb06____#5&39971a7a&0&0.1.0#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}
Media Type is DVD-ROM
HL-DT-ST
DVDRAM GSA-4163B
A106
\\?\Volume{fcfbbcce-478a-11dc-bd62-806d6172696f}\
?
I tried a few things, but none forced output for the sh-s182d. :(
Sorry 4 my poor English, it's the only one I learned 40 years ago...
since 17.12.08: XPHome(SP3) + PB 4.30
Post Reply