Windows 7 GdipCreateBitmapFromStream在Windows 7上更改合同?

Windows 7 GdipCreateBitmapFromStream在Windows 7上更改合同?,windows-7,gdi+,Windows 7,Gdi+,我们有一个功能完善的应用程序,它刚刚在Windows7上崩溃,因为(GDI+原语)GdipCreateBitmapFromStream拒绝向它提供JPEG图像(在XP甚至Vista上都没有问题) 我们不直接调用GDI+,我们调用有文档记录的ATL CImage类,它调用该类,并获取错误 这是我们自己的OLE流实现 有人看到了解决这个问题的方法吗 下面是一个完整的测试用例: #include <atlbase.h> #include <atlimage.h> #includ

我们有一个功能完善的应用程序,它刚刚在Windows7上崩溃,因为(GDI+原语)
GdipCreateBitmapFromStream
拒绝向它提供JPEG图像(在XP甚至Vista上都没有问题)

我们不直接调用GDI+,我们调用有文档记录的ATL CImage类,它调用该类,并获取错误

这是我们自己的OLE流实现

有人看到了解决这个问题的方法吗

下面是一个完整的测试用例:

#include <atlbase.h>
#include <atlimage.h>
#include <gdiplus.h>
#include <time.h>
#include <sys/stat.h>

// GSMemoryStream.h : Declaration of the GSMemoryStream

/* No ATL or class factory support is needed here.  You get one of these via "new", with zero reference count...
    Image.Load(IStreamPtr(new GSMemoryStream(ptr, len));
    and the smart pointer will provoke its deletion at the right time....
    */

// GSMemoryStream

class  GSMemoryStream : 
    public IStream
{
    private:
        ULONG m_Length;
        ULONG m_CurPtr;
        PBYTE m_Base;
        int m_rc;
public:

    GSMemoryStream(PBYTE _p, DWORD _len) {
        m_Length = _len;
        m_CurPtr = 0;
        m_Base = _p;
        m_rc = 0;
    }

    GSMemoryStream () {
        m_Length = 0;
        m_CurPtr = 0;
        m_Base = NULL;
        m_rc = 0;
    }

        STDMETHODIMP Read(void *,ULONG,ULONG *);
        STDMETHODIMP Write(const void *,ULONG,ULONG *) {return E_FAIL;}
        STDMETHODIMP Seek(LARGE_INTEGER,DWORD,ULARGE_INTEGER *);
        STDMETHODIMP SetSize(ULARGE_INTEGER) {return E_FAIL;}
        STDMETHODIMP CopyTo(IStream *,ULARGE_INTEGER,ULARGE_INTEGER *,ULARGE_INTEGER *);
        STDMETHODIMP Commit(DWORD) {return S_OK;}
        STDMETHODIMP Revert(void) {return S_OK;}
        STDMETHODIMP LockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD) {return S_OK;}
        STDMETHODIMP UnlockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD) {return S_OK;}
        STDMETHODIMP Stat(STATSTG *,DWORD);
        STDMETHODIMP Clone(IStream ** ) {return E_FAIL;}

        STDMETHODIMP QueryInterface(const IID & iid,void ** d) throw() {
            if (IsEqualGUID(iid, IID_IUnknown) || IsEqualGUID (iid, __uuidof(IStream))) {
                *d = (PVOID)this;
                AddRef();
                return S_OK;
            }
            return E_FAIL;
        }

        ULONG STDMETHODCALLTYPE AddRef(void) throw() {
            m_rc++;
            return S_OK;
        }
        ULONG STDMETHODCALLTYPE Release(void) throw() {
            if (--m_rc == 0)
                delete this; // can never go negative, because the m_rc won't be around any more once it is 0.
            // so it's not even meaningful to test for it and breakpoint or throw.
            return S_OK;
        }
};



// CGSMemoryStream

STDMETHODIMP GSMemoryStream::Read(void * p,ULONG n, ULONG * pNread) {
    ATLTRACE(L"GSMS$Read p %p  bufct %d m_curptr %d\r\n", p, n, m_CurPtr);

    if ((n + m_CurPtr) > m_Length)
        n = m_Length - m_CurPtr;
    memcpy(p, m_Base + m_CurPtr, n);
    if (pNread)
        *pNread = n;
    m_CurPtr += n;
    ATLTRACE(L"GSMS$Read(final) n %d m_CurPtr %d\r\n", n, m_CurPtr);
    return S_OK;
}

STDMETHODIMP GSMemoryStream::Seek(LARGE_INTEGER pos,DWORD type,ULARGE_INTEGER * newpos) {
    LONG lpos = (LONG)pos.LowPart;
    ATLTRACE(L"GSMS$Seek type %d lpos %d m_CurPtr %d\r\n", type, lpos, m_CurPtr);
    switch (type) {
        case STREAM_SEEK_SET:
            if (lpos < 0 || lpos > (LONG) m_Length)
                return E_POINTER;
            m_CurPtr = (ULONG)lpos;
            break;

        case STREAM_SEEK_CUR:
            if (lpos + m_CurPtr < 0 || lpos + m_CurPtr > m_Length)
                return E_POINTER;
            m_CurPtr += lpos;
            break;

        case STREAM_SEEK_END:
            if (lpos > 0)
                lpos = -lpos;
            if (lpos + m_Length < 0)
                return E_POINTER;
            m_CurPtr = m_Length + lpos;
            break;
        default:
            return E_FAIL;

    }
    ATLTRACE(L"GSMS$Seek end m_CurPtr %d\r\n", m_CurPtr);
    if (newpos) {
        newpos->HighPart = 0;
        newpos->LowPart = m_CurPtr;
    }

    return S_OK;
}

STDMETHODIMP GSMemoryStream::CopyTo(IStream * pstm,ULARGE_INTEGER cb,ULARGE_INTEGER * pNread,ULARGE_INTEGER * pNwritten){
    ATLTRACE("GSMS$CopyTo\r\n");
    if (cb.HighPart)
        return E_INVALIDARG;
    ULONG n = cb.LowPart;
    if ((n + m_CurPtr) > m_Length)
        n = m_Length - m_CurPtr;
    ULONG nwritten = 0;
    HRESULT hr = pstm->Write(m_Base+m_CurPtr, n, &nwritten);
    if (nwritten < n)
        nwritten = n;

    if (pNread) {
        pNread->HighPart = 0;
        pNread->LowPart = n;
    }
    if (pNwritten) {
        pNwritten->HighPart = 0;
        pNwritten->LowPart = nwritten;
    }
    m_CurPtr += n;
    return hr;
}

STDMETHODIMP GSMemoryStream::Stat(STATSTG * ps,DWORD krazyflag) {
    ATLTRACE(L"GSMS$Stat kf %d\r\n", krazyflag);
    memset(ps, 0, sizeof(STATSTG));
    ps->type = STGTY_STREAM;
    ps->cbSize.LowPart = m_Length;
    ps->cbSize.HighPart = 0;
#if 0
    ps->mtime = (DWORD)time(NULL);
    ps->ctime = (DWORD)time(NULL);
    ps->atime = (DWORD)time(NULL);
#endif
    return S_OK;
}






int main (int argc, char ** argv) {

    if (argc < 2) {
        fprintf(stderr, "Need image file pathname\n");
        exit(2);
    }
    struct _stat SSTAT;
    const char* fn = argv[1];
    int failed = _stat(fn, &SSTAT);
    if (failed) {
        fprintf(stderr, "Can't open file: %s\n", fn);
        exit(3);
    }
    size_t len = SSTAT.st_size;
    printf ("Len = %d\n", len);
    FILE* f = fopen(fn, "rb");
    unsigned char * buf = new unsigned char [len];
    size_t got = fread (buf, 1, len, f);
    printf ("Got = %d\n", got);
    fclose(f);

    CoInitialize(NULL);
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;

    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    GSMemoryStream G(buf, len);
    CImage cim;
    HRESULT hr = cim.Load(&G);
    printf("HRESULT = 0x%08X\n", hr);
    delete [] buf;
    CoUninitialize();
    return 0;
}
#包括
#包括
#包括
#包括
#包括
//GSMemoryStream.h:GSMemoryStream的声明
/*这里不需要ATL或类工厂支持。你可以通过“新建”得到其中一个,引用计数为零。。。
加载(IStreamPtr(新的GSMemoryStream(ptr,len));
智能指针将在正确的时间触发其删除。。。。
*/
//记忆流
GSMemoryStream类:
公共IStream
{
私人:
乌隆长度;
乌隆·穆库普特;
PBYTE m_碱;
国际货币联盟;
公众:
GSMemoryStream(PBYTE p,DWORD len){
m_长度=_长度;
m_CurPtr=0;
m_Base=_p;
m_rc=0;
}
GSMemoryStream(){
m_长度=0;
m_CurPtr=0;
m_Base=NULL;
m_rc=0;
}
STDMETHODIMP读取(void*、ULONG、ULONG*);
STDMETHODIMP Write(const void*,ULONG,ULONG*){return E_FAIL;}
STDMETHODIMP Seek(大整数、DWORD、大整数*);
STDMETHODIMP SetSize(ULARGE_INTEGER){返回E_FAIL;}
STDMETHODIMP CopyTo(IStream*,ULARGE_INTEGER,ULARGE_INTEGER*,ULARGE_INTEGER*);
STDMETHODIMP提交(DWORD){返回S_OK;}
STDMETHODIMP Revert(void){返回S_OK;}
STDMETHODIMP LockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD){返回S_OK;}
STDMETHODIMP UnlockRegion(ULARGE_INTEGER,ULARGE_INTEGER,DWORD){返回S_OK;}
标准方法统计(STATSTG*,DWORD);
STDMETHODIMP克隆(IStream**){返回E_FAIL;}
STDMETHODIMP查询接口(常量IID和IID,无效**d)抛出(){
如果(IsEqualGUID(iid,iid_IUnknown)| | IsEqualGUID(iid,iUIdof(IStream))){
*d=(PVOID)这个;
AddRef();
返回S_OK;
}
返回E_失败;
}
ULONG STDMETHODCALLTYPE AddRef(无效)抛出(){
m_rc++;
返回S_OK;
}
ULONG标准方法调用类型释放(无效)抛出(){
如果(--m_rc==0)
删除此;//永远不能变为负数,因为m_rc一旦变为0就不再存在。
//所以测试它和断点或抛出都没有意义。
返回S_OK;
}
};
//CGSMemoryStream
STDMETHODIMP GSMemoryStream::Read(void*p,ULONG n,ULONG*pNread){
ATLTRACE(L“GSMS$Read p%p bufct%d m_curptr%d\r\n”,p,n,m_curptr);
如果((n+m_CurPtr)>m_长度)
n=m_长度-m_电流;
memcpy(p,m_Base+m_CurPtr,n);
如果(pNread)
*pNread=n;
m_CurPtr+=n;
ATLTRACE(L“GSMS$Read(最终)n%d m\u CurPtr%d\r\n”,n,m\u CurPtr);
返回S_OK;
}
STDMETHODIMP GSMemoryStream::Seek(大整数位置,DWORD类型,ULARGE整数*新位置){
长LPO=(长)位置低部分;
ATLTRACE(L“GSMS$Seek type%d LPO%d m_CurPtr%d\r\n”,type,LPO,m_CurPtr);
开关(类型){
案例流搜索集:
如果(lpos<0 | | lpos>(长)m|u长度)
返回E_指针;
m_CurPtr=(ULONG)低截获概率;
打破
案例流_SEEK_CUR:
如果(lpos+m|u CurPtr<0 | lpos+m|u CurPtr>m|u长度)
返回E_指针;
m_CurPtr+=低截获概率;
打破
案例流_SEEK_END:
如果(lpos>0)
lpos=-lpos;
如果(lpos+m_长度<0)
返回E_指针;
m_CurPtr=m_长度+LPO;
打破
违约:
返回E_失败;
}
ATLTRACE(L“GSMS$Seek end m_CurPtr%d\r\n”,m_CurPtr);
if(新POS){
newpos->HighPart=0;
newpos->LowPart=m_CurPtr;
}
返回S_OK;
}
STDMETHODIMP GSMemoryStream::CopyTo(IStream*pstm、ULARGE_INTEGER cb、ULARGE_INTEGER*pNread、ULARGE_INTEGER*pnwrite){
ATLTRACE(“GSMS$CopyTo\r\n”);
如果(cb.高部分)
返回E_INVALIDARG;
ULONG n=cb.LowPart;
如果((n+m_CurPtr)>m_长度)
n=m_长度-m_电流;
ULONG nwrited=0;
HRESULT hr=pstm->Write(m_Base+m_CurPtr,n,&nwrited);
如果(nwritedHighPart=0;
pNread->LowPart=n;
}
如有(书面){
pnwrited->HighPart=0;
pnwrited->LowPart=nwrited;
}
m_CurPtr+=n;
返回人力资源;
}
STDMETHODIMP GSMemoryStream::Stat(STATSTG*ps,DWORD krazyflag){
ATLTRACE(L“GSMS$Stat kf%d\r\n”,krazyflag);
memset(ps,0,sizeof(STATSTG));
ps->type=STGTY\U流;
ps->cbSize.LowPart=m_长度;
ps->cbSize.HighPart=0;
#如果0
ps->mtime=(DWORD)时间(空);
ps->ctime=(DWORD)时间(空);
ps->atime=(DWORD)时间(空);
#恩迪夫
返回S_OK;
}
int main(int argc,字符**argv){
如果(argc<2){
fprintf(stderr,“需要图像文件路径名\n”);
出口(2);
}
结构统计数据;
常量字符*fn=argv[1];
int failed=_stat(fn和SSTAT);
如果(失败){
fprintf(stderr,“无法打开文件:%s\n”,fn);
出口(3);
}
尺寸长度=SSTAT.st\u尺寸;
printf(“Len=%d\n”,Len);
文件*f=fopen(fn,“rb”);
无符号字符*buf=新的无符号字符[len];
尺寸=fread(buf,1,len,f);
printf(“Got=%d\n”,Got);
fclose(f);
共初始化(空);
Gdiplus::GdiplusStartupInput GdiplusStartupInput;
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
GSMemoryStream G(buf,len);
CImage-cim;
HRESULT hr=cim.Load(&G)