基本适应win7,win10,win server 08,win server 12,win server 16的截图

This commit is contained in:
2025-01-03 23:00:47 +08:00
parent 909b89dfce
commit 84362607c2
77 changed files with 69638 additions and 1 deletions

View File

@@ -0,0 +1,864 @@
//go:build windows
// +build windows
// dataobject.go
package cliprdr
import (
"bytes"
"fmt"
"io"
"reflect"
"sync/atomic"
"syscall"
"unsafe"
"ShotRDP/grdp/core"
"ShotRDP/grdp/glog"
"ShotRDP/grdp/win"
)
const (
S_OK = 0x00000000
E_UNEXPECTED = 0x8000FFFF
E_NOTIMPL = 0x80004001
E_OUTOFMEMORY = 0x8007000E
E_INVALIDARG = 0x80070057
E_NOINTERFACE = 0x80004002
E_POINTER = 0x80004003
E_HANDLE = 0x80070006
E_ABORT = 0x80004004
E_FAIL = 0x80004005
E_ACCESSDENIED = 0x80070005
E_PENDING = 0x8000000A
E_ADVISENOTSUPPORTED = 0x80040003
E_FORMATETC = 0x80040064
CO_E_CLASSSTRING = 0x800401F3
)
type HRESULT uintptr
func (hr HRESULT) Error() string {
switch uint32(hr) {
case 0x80040064:
return "DV_E_FORMATETC (0x80040064)"
case 0x800401D3:
return "CLIPBRD_E_BAD_DATA (0x800401D3)"
case 0x80004005:
return "E_FAIL (0x80004005)"
case 0x00000001:
return "S_FALSE (0x00000001)"
}
return fmt.Sprintf("%d", hr)
}
const (
TYMED_NULL = 0x0
TYMED_HGLOBAL = 0x1
TYMED_FILE = 0x2
TYMED_ISTREAM = 0x4
TYMED_ISTORAGE = 0x8
TYMED_GDI = 0x10
TYMED_MFPICT = 0x20
TYMED_ENHMF = 0x40
)
type iUnknownVtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
}
type iDataObjectVtbl struct {
iUnknownVtbl
GetData uintptr
GetDataHere uintptr
QueryGetData uintptr
GetCanonicalFormatEtc uintptr
SetData uintptr
EnumFormatEtc uintptr
DAdvise uintptr
DUnadvise uintptr
EnumDAdvise uintptr
}
type FORMATETC struct {
CFormat uint32
DvTargetDevice uintptr
Aspect uint32
Index int32
Tymed uint32
}
type STGMEDIUM struct {
Tymed uint32
UnionMember uintptr
PUnkForRelease *IUnknown
}
type ISequentialStreamVtbl struct {
iUnknownVtbl
Read uintptr
Write uintptr
}
type IUnknown struct {
vtbl iUnknownVtbl
}
func (obj *IUnknown) Release() error {
ret, _, _ := syscall.Syscall(
obj.vtbl.Release,
1,
uintptr(unsafe.Pointer(obj)),
0,
0,
)
if ret != 0 {
return HRESULT(ret)
}
return nil
}
func (m STGMEDIUM) Release() {
if m.PUnkForRelease == nil {
win.ReleaseStgMedium((*win.STGMEDIUM)(unsafe.Pointer(&m)))
}
}
func (m STGMEDIUM) Stream() (*IStream, error) {
if m.Tymed != TYMED_ISTREAM {
return nil, fmt.Errorf("invalid Tymed")
}
return (*IStream)(unsafe.Pointer(m.UnionMember)), nil
}
func (m STGMEDIUM) Bytes() ([]byte, error) {
if m.Tymed != TYMED_HGLOBAL {
return nil, fmt.Errorf("invalid Tymed")
}
size := GlobalSize(m.UnionMember)
l := GlobalLock(m.UnionMember)
defer GlobalUnlock(m.UnionMember)
result := make([]byte, size)
win.RtlCopyMemory(uintptr(unsafe.Pointer(&result[0])), uintptr(unsafe.Pointer(l)), size)
return result, nil
}
type IDataObject struct {
vtbl *iDataObjectVtbl
}
func (obj *IDataObject) Release() error {
ret, _, _ := syscall.Syscall(
obj.vtbl.Release,
1,
uintptr(unsafe.Pointer(obj)),
0,
0,
)
if ret != 0 {
return HRESULT(ret)
}
return nil
}
func (obj *IDataObject) GetData(formatEtc *FORMATETC, medium *STGMEDIUM) error {
s2 := unsafe.Sizeof(*medium)
_ = s2
ret, _, _ := syscall.Syscall(
obj.vtbl.GetData,
3,
uintptr(unsafe.Pointer(obj)),
uintptr(unsafe.Pointer(formatEtc)),
uintptr(unsafe.Pointer(medium)),
)
if ret != 0 {
return HRESULT(ret)
}
return nil
}
func (obj *IDataObject) GetDataHere(formatEtc *FORMATETC, medium *STGMEDIUM) error {
ret, _, _ := syscall.Syscall(
obj.vtbl.GetDataHere,
3,
uintptr(unsafe.Pointer(obj)),
uintptr(unsafe.Pointer(formatEtc)),
uintptr(unsafe.Pointer(medium)),
)
if ret != 0 {
return HRESULT(ret)
}
return nil
}
func (obj *IDataObject) QueryGetData(formatEtc *FORMATETC) error {
ret, _, _ := syscall.Syscall(
obj.vtbl.QueryGetData,
2,
uintptr(unsafe.Pointer(obj)),
uintptr(unsafe.Pointer(formatEtc)),
0,
)
if ret != 0 {
return HRESULT(ret)
}
return nil
}
func (obj *IDataObject) EnumFormatEtc(direction uint32, pIEnumFORMATETC **IEnumFORMATETC) error {
ret, _, _ := syscall.Syscall(
obj.vtbl.EnumFormatEtc,
3,
uintptr(unsafe.Pointer(obj)),
uintptr(direction),
uintptr(unsafe.Pointer(pIEnumFORMATETC)),
)
if ret != 0 {
return HRESULT(ret)
}
return nil
}
type iEnumFORMATETCVtbl struct {
iUnknownVtbl
Next uintptr
Skip uintptr
Reset uintptr
Clone uintptr
}
type IEnumFORMATETC struct {
vtbl *iEnumFORMATETCVtbl
}
func (obj *IEnumFORMATETC) Release() error {
ret, _, _ := syscall.Syscall(
obj.vtbl.Release,
1,
uintptr(unsafe.Pointer(obj)),
0,
0,
)
if ret != 0 {
return HRESULT(ret)
}
return nil
}
func (obj *IEnumFORMATETC) Next(formatEtc []FORMATETC, celtFetched *uint32) error {
ret, _, _ := syscall.Syscall6(
obj.vtbl.Next,
4,
uintptr(unsafe.Pointer(obj)),
uintptr(len(formatEtc)),
uintptr(unsafe.Pointer(&formatEtc[0])),
uintptr(unsafe.Pointer(celtFetched)),
0,
0,
)
if ret != 1 {
return HRESULT(ret)
}
return nil
}
type EnumInstance struct {
iEnumFORMATETC IEnumFORMATETC
refCount int32
index int
formatEtc []FORMATETC
}
var (
IID_IDataObject = win.GUID{0x10e, 0, 0, [8]byte{0xc0, 0, 0, 0, 0, 0, 0, 0x46}}
IID_IUnknown = win.GUID{0x000, 0, 0, [8]byte{0xc0, 0, 0, 0, 0, 0, 0, 0x46}}
IID_IEnumFORMATETC = win.GUID{0x103, 0, 0, [8]byte{0xc0, 0, 0, 0, 0, 0, 0, 0x46}}
IID_IStream = win.GUID{0x00c, 0, 0, [8]byte{0xc0, 0, 0, 0, 0, 0, 0, 0x46}}
)
func newEnumInstance(fs []FORMATETC) *EnumInstance {
var instance EnumInstance
ie := &instance.iEnumFORMATETC
ie.vtbl = new(iEnumFORMATETCVtbl)
ie.vtbl.QueryInterface = syscall.NewCallback((*EnumInstance).QueryInterface)
ie.vtbl.AddRef = syscall.NewCallback((*EnumInstance).AddRef)
ie.vtbl.Release = syscall.NewCallback((*EnumInstance).Release)
ie.vtbl.Next = syscall.NewCallback((*EnumInstance).Next)
ie.vtbl.Skip = syscall.NewCallback((*EnumInstance).Skip)
ie.vtbl.Reset = syscall.NewCallback((*EnumInstance).Reset)
ie.vtbl.Clone = syscall.NewCallback((*EnumInstance).Clone)
instance.refCount = 1
if len(fs) > 0 {
instance.formatEtc = make([]FORMATETC, len(fs))
copy(instance.formatEtc, fs)
}
return &instance
}
func (i *EnumInstance) QueryInterface(riid win.REFGUID, ppvObject *uintptr) uintptr {
if win.IsEqualGUID(riid, &IID_IEnumFORMATETC) ||
win.IsEqualGUID(riid, &IID_IUnknown) {
*ppvObject = uintptr(unsafe.Pointer(i))
i.AddRef()
return 0
}
*ppvObject = 0
return E_NOINTERFACE
}
func (i *EnumInstance) AddRef() uintptr {
n := atomic.AddInt32(&i.refCount, 1)
return uintptr(n)
}
func (i *EnumInstance) Release() uintptr {
n := atomic.AddInt32(&i.refCount, -1)
if n == 0 {
i = nil
return 0
}
return uintptr(n)
}
func (i *EnumInstance) Next(celt uint32, rgelt *FORMATETC, pceltFetched *uint32) uintptr {
r := make([]FORMATETC, celt)
var idx uint32
for i.index < len(i.formatEtc) && idx < celt {
r[idx] = i.formatEtc[i.index]
i.index++
idx++
}
*rgelt = r[0]
if pceltFetched != nil {
*pceltFetched = idx
}
if idx != celt {
return E_FAIL
}
return 0
}
func (i *EnumInstance) Skip(celt uint32) uintptr {
if i.index+int(celt) > len(i.formatEtc) {
return E_FAIL
}
i.index += int(celt)
return 0
}
func (i *EnumInstance) Reset() uintptr {
i.index = 0
return 0
}
func (i *EnumInstance) Clone(ppEnum **IEnumFORMATETC) uintptr {
ins := newEnumInstance(i.formatEtc)
ins.index = i.index
(*ppEnum) = (*IEnumFORMATETC)(unsafe.Pointer(ins))
return 0
}
func CreateDataObject(c *CliprdrClient) *IDataObject {
fmtetc := make([]FORMATETC, 2)
stgmeds := make([]STGMEDIUM, 2)
fmtetc[0].CFormat = RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW)
fmtetc[0].Aspect = DVASPECT_CONTENT
fmtetc[0].Index = 0
//fmtetc[0].DvTargetDevice = nil
fmtetc[0].Tymed = TYMED_HGLOBAL
stgmeds[0].Tymed = TYMED_HGLOBAL
//stgmeds[0].UnionMember = nil
stgmeds[0].PUnkForRelease = nil
fmtetc[1].CFormat = RegisterClipboardFormat(CFSTR_FILECONTENTS)
fmtetc[1].Aspect = DVASPECT_CONTENT
fmtetc[1].Index = 0
//fmtetc[1].DvTargetDevice = nil
fmtetc[1].Tymed = TYMED_ISTREAM
stgmeds[1].Tymed = TYMED_ISTREAM
//stgmeds[1].UnionMember = nil
stgmeds[1].PUnkForRelease = nil
instance := newDataInstance()
instance.refCount = 1
instance.formatEtc = fmtetc
instance.stgMedium = stgmeds
instance.data = c
return (*IDataObject)(unsafe.Pointer(instance))
}
type DataInstance struct {
iDataObject IDataObject
refCount int32
idx int32
formatEtc []FORMATETC
stgMedium []STGMEDIUM
streams []*StreamInstance
data interface{}
}
func newDataInstance() *DataInstance {
var instance DataInstance
obj := &instance.iDataObject
obj.vtbl = new(iDataObjectVtbl)
obj.vtbl.QueryInterface = syscall.NewCallback((*DataInstance).QueryInterface)
obj.vtbl.AddRef = syscall.NewCallback((*DataInstance).AddRef)
obj.vtbl.Release = syscall.NewCallback((*DataInstance).Release)
obj.vtbl.GetData = syscall.NewCallback((*DataInstance).GetData)
obj.vtbl.GetDataHere = syscall.NewCallback((*DataInstance).GetDataHere)
obj.vtbl.QueryGetData = syscall.NewCallback((*DataInstance).QueryGetData)
obj.vtbl.GetCanonicalFormatEtc = syscall.NewCallback((*DataInstance).GetCanonicalFormatEtc)
obj.vtbl.SetData = syscall.NewCallback((*DataInstance).SetData)
obj.vtbl.EnumFormatEtc = syscall.NewCallback((*DataInstance).EnumFormatEtc)
obj.vtbl.DAdvise = syscall.NewCallback((*DataInstance).DAdvise)
obj.vtbl.DUnadvise = syscall.NewCallback((*DataInstance).DUnadvise)
obj.vtbl.EnumDAdvise = syscall.NewCallback((*DataInstance).EnumDAdvise)
return &instance
}
func (i *DataInstance) QueryInterface(riid win.REFGUID, ppvObject *uintptr) uintptr {
if win.IsEqualGUID(riid, &IID_IDataObject) ||
win.IsEqualGUID(riid, &IID_IUnknown) {
*ppvObject = uintptr(unsafe.Pointer(i))
i.AddRef()
return 0
}
*ppvObject = 0
return E_NOINTERFACE
}
func (i *DataInstance) AddRef() uintptr {
n := atomic.AddInt32(&i.refCount, 1)
return uintptr(n)
}
func (i *DataInstance) Release() uintptr {
n := atomic.AddInt32(&i.refCount, -1)
if n == 0 {
i = nil
return 0
}
return uintptr(n)
}
func (i *DataInstance) GetData(formatEtc *FORMATETC, medium *STGMEDIUM) uintptr {
idx := -1
for j, f := range i.formatEtc {
if formatEtc.Tymed&f.Tymed != 0 &&
formatEtc.CFormat == f.CFormat &&
formatEtc.Aspect&f.Aspect != 0 {
idx = j
}
}
if idx == -1 {
return E_FORMATETC
}
glog.Debugf("GetData:%+v, %s", formatEtc.CFormat, GetClipboardFormatName(formatEtc.CFormat))
medium.Tymed = i.formatEtc[idx].Tymed
if i.formatEtc[idx].CFormat == RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW) {
c := i.data.(*CliprdrClient)
if remoteid, ok := c.formatIdMap[i.formatEtc[idx].CFormat]; ok {
c.sendFormatDataRequest(remoteid)
b := <-c.reply
if len(b) == 0 {
return E_FAIL
}
medium.UnionMember = HmemAlloc(b)
var dsc FileGroupDescriptor
dsc.Unpack(b)
if dsc.CItems > 0 {
glog.Debug("Items:", dsc.CItems)
i.streams = make([]*StreamInstance, dsc.CItems)
var j uint32
for j = 0; j < dsc.CItems; j++ {
glog.Debug("FileName:", core.UnicodeDecode(dsc.Fgd[j].FileName))
s := newStream(j, i.data, &dsc.Fgd[j])
i.streams[j] = s
}
}
}
} else if i.formatEtc[idx].CFormat == RegisterClipboardFormat(CFSTR_FILECONTENTS) {
if formatEtc.Index >= 0 && formatEtc.Index < int32(len(i.streams)) {
medium.UnionMember = uintptr(unsafe.Pointer(i.streams[formatEtc.Index]))
i.AddRef()
} else {
return E_INVALIDARG
}
} else {
return E_UNEXPECTED
}
return 0
}
func (i *DataInstance) GetDataHere(formatEtc *FORMATETC, medium *STGMEDIUM) uintptr {
return E_NOTIMPL
}
func (i *DataInstance) QueryGetData(formatEtc *FORMATETC) uintptr {
for _, f := range i.formatEtc {
if formatEtc.Tymed&f.Tymed != 0 &&
formatEtc.CFormat == f.CFormat &&
formatEtc.Aspect&f.Aspect != 0 {
return 0
}
}
return E_FORMATETC
}
func (i *DataInstance) GetCanonicalFormatEtc(informatEtc, outformatEtc *FORMATETC) uintptr {
return E_NOTIMPL
}
func (i *DataInstance) SetData(formatEtc *FORMATETC, medium *STGMEDIUM, r bool) uintptr {
return E_NOTIMPL
}
func (i *DataInstance) EnumFormatEtc(dwDirection uint32, ppenumFormatEtc **IEnumFORMATETC) uintptr {
if dwDirection == 1 {
ins := newEnumInstance(i.formatEtc)
(*ppenumFormatEtc) = (*IEnumFORMATETC)(unsafe.Pointer(ins))
return 0
}
return E_NOTIMPL
}
func (i *DataInstance) DAdvise(formatEtc *FORMATETC, advf uint32, pAdvSink uintptr, pdwConnection *uint32) uintptr {
return E_ADVISENOTSUPPORTED
}
func (i *DataInstance) DUnadvise(dwDirection uint32) uintptr {
return E_ADVISENOTSUPPORTED
}
func (i *DataInstance) EnumDAdvise(ppenumAdvise uintptr) uintptr {
return E_ADVISENOTSUPPORTED
}
const (
STREAM_SEEK_SET = 0
STREAM_SEEK_CUR = 1
STREAM_SEEK_END = 2
)
const (
STATFLAG_DEFAULT = 0
STATFLAG_NONAME = 1
STATFLAG_NOOPEN = 2
)
const (
STG_E_INSUFFICIENTMEMORY = 0x80030008
STG_E_INVALIDFLAG = 0x800300FF
)
const (
STGTY_STORAGE = 1
STGTY_STREAM = 2
STGTY_LOCKBYTES = 3
STGTY_PROPERTY = 4
)
const (
LOCK_WRITE = 1
LOCK_EXCLUSIVE = 2
LOCK_ONLYONCE = 4
)
const (
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
GENERIC_EXECUTE = 0x20000000
)
type IStreamVtbl struct {
ISequentialStreamVtbl
Seek uintptr
SetSize uintptr
CopyTo uintptr
Commit uintptr
Revert uintptr
LockRegion uintptr
UnlockRegion uintptr
Stat uintptr
Clone uintptr
}
type IStream struct {
vtbl *IStreamVtbl
}
type ULARGE_INTEGER struct {
QuadPart uint64
}
type LARGE_INTEGER struct {
QuadPart int64
}
func (l *ULARGE_INTEGER) LowPart() *uint32 {
return (*uint32)(unsafe.Pointer(&l.QuadPart))
}
func (l *ULARGE_INTEGER) HighPart() *uint32 {
return (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&l.QuadPart)) + uintptr(4)))
}
func (l *LARGE_INTEGER) LowPart() *uint32 {
return (*uint32)(unsafe.Pointer(&l.QuadPart))
}
func (l *LARGE_INTEGER) HighPart() *int32 {
return (*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&l.QuadPart)) + uintptr(4)))
}
type StreamInstance struct {
iStream IStream
streamId uint32
refCount int32
index uint32
lSize ULARGE_INTEGER
lOffset ULARGE_INTEGER
dsc FileDescriptor
data interface{}
}
type STATSTG struct {
pwcsName []uint16
sType uint32
cbSize ULARGE_INTEGER
mtime win.FILETIME
ctime win.FILETIME
atime win.FILETIME
grfMode uint32
grfLocksSupported uint32
clsid win.CLSID
grfStateBits uint32
reserved uint32
}
func (obj *IStream) Read(buffer []byte) (int, error) {
bufPtr := &buffer[0]
var read uint32
ret, _, _ := syscall.Syscall6(
obj.vtbl.Read,
4,
uintptr(unsafe.Pointer(obj)),
uintptr(unsafe.Pointer(bufPtr)),
uintptr(len(buffer)),
uintptr(unsafe.Pointer(&read)),
0,
0,
)
if ret == 1 {
return int(read), io.EOF
}
if ret != 0 {
return int(read), HRESULT(ret)
}
return int(read), nil
}
func (obj *IStream) Close() error {
return obj.Release()
}
func (obj *IStream) Release() error {
ret, _, _ := syscall.Syscall(
obj.vtbl.Release,
1,
uintptr(unsafe.Pointer(obj)),
0,
0,
)
if ret != 0 {
return HRESULT(ret)
}
return nil
}
func newStream(index uint32, data interface{}, dsc *FileDescriptor) *StreamInstance {
var instance StreamInstance
is := &instance.iStream
is.vtbl = new(IStreamVtbl)
is.vtbl.QueryInterface = syscall.NewCallback((*StreamInstance).QueryInterface)
is.vtbl.AddRef = syscall.NewCallback((*StreamInstance).AddRef)
is.vtbl.Release = syscall.NewCallback((*StreamInstance).Release)
is.vtbl.Read = syscall.NewCallback((*StreamInstance).Read)
is.vtbl.Write = syscall.NewCallback((*StreamInstance).Write)
is.vtbl.Seek = syscall.NewCallback((*StreamInstance).Seek)
is.vtbl.SetSize = syscall.NewCallback((*StreamInstance).SetSize)
is.vtbl.CopyTo = syscall.NewCallback((*StreamInstance).CopyTo)
is.vtbl.Commit = syscall.NewCallback((*StreamInstance).Commit)
is.vtbl.Revert = syscall.NewCallback((*StreamInstance).Revert)
is.vtbl.LockRegion = syscall.NewCallback((*StreamInstance).LockRegion)
is.vtbl.UnlockRegion = syscall.NewCallback((*StreamInstance).UnlockRegion)
is.vtbl.Stat = syscall.NewCallback((*StreamInstance).Stat)
is.vtbl.Clone = syscall.NewCallback((*StreamInstance).Clone)
instance.streamId = (uint32)(reflect.ValueOf(&instance).Pointer())
instance.refCount = 1
instance.dsc = *dsc
instance.data = data
instance.index = index
if !instance.dsc.hasFileSize() && !instance.dsc.isDir() {
c := data.(*CliprdrClient)
var r CliprdrFileContentsRequest
r.StreamId = instance.streamId
r.Lindex = instance.index
r.DwFlags = FILECONTENTS_SIZE
r.CbRequested = 8
c.sendFormatContentsRequest(r)
b := <-c.reply
instance.lSize.QuadPart = core.BytesToUint64(b)
} else {
b := &bytes.Buffer{}
core.WriteUInt32LE(dsc.FileSizeLow, b)
core.WriteUInt32LE(dsc.FileSizeHigh, b)
instance.lSize.QuadPart = core.BytesToUint64(b.Bytes())
}
return &instance
}
func (i *StreamInstance) QueryInterface(riid win.REFGUID, ppvObject *uintptr) uintptr {
if win.IsEqualGUID(riid, &IID_IStream) ||
win.IsEqualGUID(riid, &IID_IUnknown) {
*ppvObject = uintptr(unsafe.Pointer(i))
i.AddRef()
return 0
}
*ppvObject = 0
return E_NOINTERFACE
}
func (i *StreamInstance) AddRef() uintptr {
n := atomic.AddInt32(&i.refCount, 1)
return uintptr(n)
}
func (i *StreamInstance) Release() uintptr {
n := atomic.AddInt32(&i.refCount, -1)
if n == 0 {
i = nil
return 0
}
return uintptr(n)
}
func (i *StreamInstance) Read(pv uintptr, cb uint32, cbRead *uint32) uintptr {
glog.Debug("StreamInstance Read:", i.lOffset.QuadPart, i.lSize.QuadPart)
if i.lOffset.QuadPart >= i.lSize.QuadPart {
return 1
}
c := i.data.(*CliprdrClient)
*cbRead = 0
var r CliprdrFileContentsRequest
r.StreamId = i.streamId
r.Lindex = i.index
r.DwFlags = FILECONTENTS_RANGE
r.NPositionHigh = *(i.lOffset.HighPart())
r.NPositionLow = *(i.lOffset.LowPart())
r.CbRequested = cb
c.sendFormatContentsRequest(r)
b := <-c.reply
if len(b) == 0 {
return E_FAIL
}
win.RtlCopyMemory(pv, uintptr(unsafe.Pointer(&b[0])), win.SIZE_T(len(b)))
*cbRead = uint32(len(b))
i.lOffset.QuadPart += uint64(len(b))
glog.Debug("StreamInstance Read:", *cbRead, cb)
if *cbRead < cb {
return 1
}
return 0
}
func (i *StreamInstance) Write(pv uintptr, cb uint32, cbWritten *uint32) uintptr {
return E_ACCESSDENIED
}
func (i *StreamInstance) Seek(dlibMove LARGE_INTEGER, dwOrigin uint32, plibNewPosition *ULARGE_INTEGER) uintptr {
glog.Debug("StreamInstance Seek:", dwOrigin, dlibMove, plibNewPosition)
var newoffset uint64 = i.lOffset.QuadPart
switch dwOrigin {
case STREAM_SEEK_SET:
newoffset = uint64(dlibMove.QuadPart)
break
case STREAM_SEEK_CUR:
newoffset += uint64(dlibMove.QuadPart)
break
case STREAM_SEEK_END:
newoffset = i.lSize.QuadPart + uint64(dlibMove.QuadPart)
break
default:
return E_INVALIDARG
}
glog.Debug("StreamInstance Seek:", newoffset, i.lSize.QuadPart)
if newoffset < 0 || newoffset >= i.lSize.QuadPart {
return 1
}
i.lOffset.QuadPart = newoffset
if plibNewPosition != nil {
(*plibNewPosition).QuadPart = i.lOffset.QuadPart
}
return 0
}
func (i *StreamInstance) SetSize(libNewSize ULARGE_INTEGER) uintptr {
return E_NOTIMPL
}
func (i *StreamInstance) CopyTo(pstm *IStream, cb ULARGE_INTEGER, cbRead, cbWritten *ULARGE_INTEGER) uintptr {
return E_NOTIMPL
}
func (i *StreamInstance) Commit(grfCommitFlags uint32) uintptr {
return E_NOTIMPL
}
func (i *StreamInstance) Revert() uintptr {
return E_NOTIMPL
}
func (i *StreamInstance) LockRegion(libOffset, cb ULARGE_INTEGER, dwLockType uint32) uintptr {
return E_NOTIMPL
}
func (i *StreamInstance) UnlockRegion(libOffset, cb ULARGE_INTEGER, dwLockType uint32) uintptr {
return E_NOTIMPL
}
func (i *StreamInstance) Stat(pstatstg *STATSTG, grfStatFlag uint32) uintptr {
switch grfStatFlag {
case STATFLAG_DEFAULT:
return STG_E_INSUFFICIENTMEMORY
case STATFLAG_NONAME:
pstatstg.cbSize.QuadPart = i.lSize.QuadPart
pstatstg.grfLocksSupported = LOCK_EXCLUSIVE
pstatstg.grfMode = GENERIC_READ
pstatstg.grfStateBits = 0
pstatstg.sType = STGTY_STREAM
break
case STATFLAG_NOOPEN:
return STG_E_INVALIDFLAG
default:
return STG_E_INVALIDFLAG
}
return 0
}
func (i *StreamInstance) Clone(ppstm **IStream) uintptr {
return E_NOTIMPL
}