audacia/lib-src/portburn/portburn_winxp.cpp

412 lines
9.3 KiB
C++

/*
* PortBurn
* Windows XP IMAPI implementation
*
* Authors:
* Leland Lucius
*
* The following MSDN page was used as a guide:
* http://msdn2.microsoft.com/en-us/library/aa366236.aspx
*
* License: LGPL
*/
#include "portburn.h"
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <imapi.h>
#include <imapi2.h>
typedef struct {
int ver;
void *realhandle;
} PBHandle;
#define PBFUNC(r,f) \
extern r PortBurn_v1_ ## f; \
extern r PortBurn_v2_ ## f;
PBFUNC(void *, Open());
PBFUNC(void, Close(void *handle));
PBFUNC(char *, LastError(void *handle));
PBFUNC(int, GetNumDevices(void *handle));
PBFUNC(char *, GetDeviceName(void *handle, int index));
PBFUNC(int, OpenDevice(void *handle, int index));
PBFUNC(int, CloseDevice(void *handle));
PBFUNC(int, EjectDevice(void *handle));
PBFUNC(int, StartErasing(void *handle, int type));
PBFUNC(int, GetEraseStatus(void *handle, float *out_fraction_complete));
PBFUNC(int, StartStaging(void *handle, const char *tmpdir));
PBFUNC(int, StartTrack(void *handle, const char *name));
PBFUNC(int, AddFrame(void *handle, short *buffer));
PBFUNC(int, EndTrack(void *handle));
PBFUNC(int, StartBurning(void *handle));
PBFUNC(int, CancelBurning(void *handle));
PBFUNC(int, GetStatus(void *handle, float *out_fraction_complete));
PBFUNC(int, GetOption(void *handle, int option, int *value));
PBFUNC(int, SetOption(void *handle, int option, int value));
PBFUNC(int, GetSupportedSpeeds(void *handle, int *cnt, int *option[]));
PBFUNC(int, GetMediaState(void *handle, int *state));
enum {
IMAPI_V1,
IMAPI_V2,
IMAPI_VERS
};
struct
{
void *(*Open)();
void (*Close)(void *handle);
char *(*LastError)(void *handle);
int (*GetNumDevices)(void *handle);
char *(*GetDeviceName)(void *handle, int index);
int (*OpenDevice)(void *handle, int index);
int (*CloseDevice)(void *handle);
int (*EjectDevice)(void *handle);
int (*StartErasing)(void *handle, int type);
int (*GetEraseStatus)(void *handle, float *out_fraction_complete);
int (*StartStaging)(void *handle, const char *tmpdir);
int (*StartTrack)(void *handle, const char *name);
int (*AddFrame)(void *handle, short *buffer);
int (*EndTrack)(void *handle);
int (*StartBurning)(void *handle);
int (*CancelBurning)(void *handle);
int (*GetStatus)(void *handle, float *out_fraction_complete);
int (*GetOption)(void *handle, int option, int *value);
int (*SetOption)(void *handle, int option, int value);
int (*GetSupportedSpeeds)(void *handle, int *cnt, int *option[]);
int (*GetMediaState)(void *handle, int *state);
}
vectors[IMAPI_VERS] =
{
{
PortBurn_v1_Open,
PortBurn_v1_Close,
PortBurn_v1_LastError,
PortBurn_v1_GetNumDevices,
PortBurn_v1_GetDeviceName,
PortBurn_v1_OpenDevice,
PortBurn_v1_CloseDevice,
PortBurn_v1_EjectDevice,
PortBurn_v1_StartErasing,
PortBurn_v1_GetEraseStatus,
PortBurn_v1_StartStaging,
PortBurn_v1_StartTrack,
PortBurn_v1_AddFrame,
PortBurn_v1_EndTrack,
PortBurn_v1_StartBurning,
PortBurn_v1_CancelBurning,
PortBurn_v1_GetStatus,
PortBurn_v1_GetOption,
PortBurn_v1_SetOption,
PortBurn_v1_GetSupportedSpeeds,
PortBurn_v1_GetMediaState,
},
{
PortBurn_v2_Open,
PortBurn_v2_Close,
PortBurn_v2_LastError,
PortBurn_v2_GetNumDevices,
PortBurn_v2_GetDeviceName,
PortBurn_v2_OpenDevice,
PortBurn_v2_CloseDevice,
PortBurn_v2_EjectDevice,
PortBurn_v2_StartErasing,
PortBurn_v2_GetEraseStatus,
PortBurn_v2_StartStaging,
PortBurn_v2_StartTrack,
PortBurn_v2_AddFrame,
PortBurn_v2_EndTrack,
PortBurn_v2_StartBurning,
PortBurn_v2_CancelBurning,
PortBurn_v2_GetStatus,
PortBurn_v2_GetOption,
PortBurn_v2_SetOption,
PortBurn_v2_GetSupportedSpeeds,
PortBurn_v2_GetMediaState,
}
};
void *PortBurn_Open()
{
PBHandle *h;
HRESULT hres;
IDiscMaster *pV1;
IDiscMaster2 *pV2;
hres = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
if (FAILED(hres)) {
return NULL;
}
h = (PBHandle *) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(PBHandle));
if (h == NULL) {
CoUninitialize();
return NULL;
}
hres = CoCreateInstance(__uuidof(MsftDiscMaster2),
NULL,
CLSCTX_ALL,
IID_IDiscMaster2,
(void **)&pV2);
if (FAILED(hres)) {
hres = CoCreateInstance(__uuidof(MSDiscMasterObj),
NULL,
CLSCTX_ALL,
IID_IDiscMaster,
(void **)&pV1);
if (FAILED(hres)) {
HeapFree(GetProcessHeap(), 0, h);
CoUninitialize();
return NULL;
}
pV1->Release();
h->ver = IMAPI_V1;
}
else {
pV2->Release();
h->ver = IMAPI_V2;
}
//h->ver = IMAPI_V1;
h->realhandle = vectors[h->ver].Open();
if (h->realhandle == NULL) {
HeapFree(GetProcessHeap(), 0, h);
CoUninitialize();
return NULL;
}
return h;
}
/* Cleanup */
void PortBurn_Close(void *handle)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return;
}
vectors[h->ver].Close(h->realhandle);
HeapFree(GetProcessHeap(), 0, h);
CoUninitialize();
}
char *PortBurn_LastError(void *handle)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return NULL;
}
return vectors[h->ver].LastError(h->realhandle);
}
int PortBurn_GetNumDevices(void *handle)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return 0;
}
return vectors[h->ver].GetNumDevices(h->realhandle);
}
/* Get the name of the device with a given index. Only valid
after a call to GetNumDevices. */
char *PortBurn_GetDeviceName(void *handle, int index)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return NULL;
}
return vectors[h->ver].GetDeviceName(h->realhandle, index);
}
int PortBurn_OpenDevice(void *handle, int index)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].OpenDevice(h->realhandle, index);
}
int PortBurn_CloseDevice(void *handle)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].CloseDevice(h->realhandle);
}
int PortBurn_EjectDevice(void *handle)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].EjectDevice(h->realhandle);
}
int PortBurn_StartStaging(void *handle, const char *tmpdir)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].StartStaging(h->realhandle, tmpdir);
}
int PortBurn_StartTrack(void *handle, const char *name)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].StartTrack(h->realhandle, name);
}
int PortBurn_AddFrame(void *handle, short *buffer)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].AddFrame(h->realhandle, buffer);
}
int PortBurn_EndTrack(void *handle)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].EndTrack(h->realhandle);
}
int PortBurn_StartBurning(void *handle)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].StartBurning(h->realhandle);
}
int PortBurn_CancelBurning(void *handle)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].CancelBurning(h->realhandle);
}
int PortBurn_GetStatus(void *handle, float *out_fraction_complete)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].GetStatus(h->realhandle, out_fraction_complete);
}
int PortBurn_GetOption(void *handle, int option, int *value)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].GetOption(h->realhandle, option, value);
}
int PortBurn_SetOption(void *handle, int option, int value)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].SetOption(h->realhandle, option, value);
}
int PortBurn_GetSpeeds(void *handle, int *cnt, int *speeds[])
{
return -1;
}
/* Erase the media in the currently opened device */
int PortBurn_StartErasing(void *handle, int type)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].StartErasing(h->realhandle, type);
}
int PortBurn_GetEraseStatus(void *handle, float *out_fraction_complete)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].GetEraseStatus(h->realhandle, out_fraction_complete);
}
/* */
int PortBurn_GetMediaState(void *handle, int *state)
{
PBHandle *h = (PBHandle *) handle;
if (h == NULL) {
return pbErrNoHandle;
}
return vectors[h->ver].GetMediaState(h->realhandle, state);
}