Beispiel #1
0
static HRESULT WINAPI NoStatStreamImpl_Write(
	          IStream*     iface,
		  const void*    pv,          /* [size_is][in] */
		  ULONG          cb,          /* [in] */
		  ULONG*         pcbWritten)  /* [out] */
{
  NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
  void*          supportBuffer;
  ULARGE_INTEGER newSize;
  ULONG          bytesWritten = 0;

  if (pcbWritten == 0)
    pcbWritten = &bytesWritten;
  if (cb == 0)
    return S_OK;
  newSize.u.HighPart = 0;
  newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
  if (newSize.u.LowPart > This->streamSize.u.LowPart)
   IStream_SetSize(iface, newSize);

  supportBuffer = GlobalLock(This->supportHandle);
  memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
  This->currentPosition.u.LowPart+=cb;
  *pcbWritten = cb;
  GlobalUnlock(This->supportHandle);
  return S_OK;
}
Beispiel #2
0
static HRESULT WINAPI IDirectMusicLoaderGenericStream_IStream_SetSize (LPSTREAM iface, ULARGE_INTEGER libNewSize) {
	ICOM_THIS_MULTI(IDirectMusicLoaderGenericStream, StreamVtbl, iface);	
	TRACE("(%p, 0x%08llX): redirecting to low-level stream\n", This, libNewSize.QuadPart);
	if (!This->pStream)
		return E_FAIL;

	return IStream_SetSize (This->pStream, libNewSize);
}
Beispiel #3
0
static HRESULT WINAPI IWICStreamImpl_SetSize(IWICStream *iface,
    ULARGE_INTEGER libNewSize)
{
    IWICStreamImpl *This = impl_from_IWICStream(iface);
    TRACE("(%p): relay\n", This);

    if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
    return IStream_SetSize(This->pStream, libNewSize);
}
Beispiel #4
0
/* read the data in a file into an IStream */
static UINT RECORD_StreamFromFile(LPCWSTR szFile, IStream **pstm)
{
    DWORD sz, szHighWord = 0, read;
    HANDLE handle;
    HGLOBAL hGlob = 0;
    HRESULT hr;
    ULARGE_INTEGER ulSize;

    TRACE("reading %s\n", debugstr_w(szFile));

    /* read the file into memory */
    handle = CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    if( handle == INVALID_HANDLE_VALUE )
        return GetLastError();
    sz = GetFileSize(handle, &szHighWord);
    if( sz != INVALID_FILE_SIZE && szHighWord == 0 )
    {
        hGlob = GlobalAlloc(GMEM_FIXED, sz);
        if( hGlob )
        {
            BOOL r = ReadFile(handle, hGlob, sz, &read, NULL) && read == sz;
            if( !r )
            {
                GlobalFree(hGlob);
                hGlob = 0;
            }
        }
    }
    CloseHandle(handle);
    if( !hGlob )
        return ERROR_FUNCTION_FAILED;

    /* make a stream out of it, and set the correct file size */
    hr = CreateStreamOnHGlobal(hGlob, TRUE, pstm);
    if( FAILED( hr ) )
    {
        GlobalFree(hGlob);
        return ERROR_FUNCTION_FAILED;
    }

    /* set the correct size - CreateStreamOnHGlobal screws it up */
    ulSize.QuadPart = sz;
    IStream_SetSize(*pstm, ulSize);

    TRACE("read %s, %d bytes into IStream %p\n", debugstr_w(szFile), sz, *pstm);

    return ERROR_SUCCESS;
}
Beispiel #5
0
static void test_freed_hglobal(void)
{
    static const char teststring[] = "this is a test string";
    HRESULT hr;
    IStream *pStream;
    HGLOBAL hglobal;
    char *p;
    char buffer[sizeof(teststring) + 8];
    ULARGE_INTEGER ull;
    ULONG read, written;

    hglobal = GlobalAlloc(GMEM_DDESHARE|GMEM_NODISCARD|GMEM_MOVEABLE, strlen(teststring) + 1);
    ok(hglobal != NULL, "GlobalAlloc failed with error %d\n", GetLastError());
    p = GlobalLock(hglobal);
    strcpy(p, teststring);
    GlobalUnlock(hglobal);

    hr = CreateStreamOnHGlobal(hglobal, FALSE, &pStream);
    ok_ole_success(hr, "CreateStreamOnHGlobal");

    hr = IStream_Read(pStream, buffer, sizeof(buffer), &read);
    ok_ole_success(hr, "IStream_Read");
    ok(!strcmp(buffer, teststring), "buffer data %s differs\n", buffer);
    ok(read == sizeof(teststring) ||
       broken(read == ((sizeof(teststring) + 3) & ~3)), /* win9x rounds the size */
       "read should be sizeof(teststring) instead of %d\n", read);

    GlobalFree(hglobal);

    memset(buffer, 0, sizeof(buffer));
    read = -1;
    hr = IStream_Read(pStream, buffer, sizeof(buffer), &read);
    ok_ole_success(hr, "IStream_Read");
    ok(buffer[0] == 0, "buffer data should be untouched\n");
    ok(read == 0, "read should be 0 instead of %d\n", read);

    ull.QuadPart = sizeof(buffer);
    hr = IStream_SetSize(pStream, ull);
    ok(hr == E_OUTOFMEMORY, "IStream_SetSize with invalid HGLOBAL should return E_OUTOFMEMORY instead of 0x%08x\n", hr);

    hr = IStream_Write(pStream, buffer, sizeof(buffer), &written);
    ok(hr == E_OUTOFMEMORY, "IStream_Write with invalid HGLOBAL should return E_OUTOFMEMORY instead of 0x%08x\n", hr);
    ok(written == 0, "written should be 0 instead of %d\n", written);

    IStream_Release(pStream);
}
Beispiel #6
0
static GpBitmap *
gdip_buffer_to_bitmap (GdipContext *context, GError **error)
{
  HRESULT hr;
  HGLOBAL hg = NULL;
  GpBitmap *bitmap = NULL;
  IStream *stream = NULL;
  GpStatus status;
  guint64 size64 = context->buffer->len;

  hg = gdip_buffer_to_hglobal (context->buffer->data, context->buffer->len, error);

  if (!hg)
    return NULL;

  hr = CreateStreamOnHGlobal (hg, FALSE, (LPSTREAM *)&stream);

  if (!SUCCEEDED (hr)) {
    gdip_set_error_from_hresult (error, GDK_PIXBUF_ERROR_FAILED, hr, _("Could not create stream: %s"));
    GlobalFree (hg);
    return NULL;
  }

  IStream_SetSize (stream, *(ULARGE_INTEGER *)&size64);

  status = GdipCreateBitmapFromStream (stream, &bitmap);

  if (Ok != status) {
    gdip_set_error_from_gpstatus (error, GDK_PIXBUF_ERROR_FAILED, status);
    IStream_Release (stream);
    GlobalFree (hg);
    return NULL;
  }

  context->stream = stream;
  context->hg = hg;

  return bitmap;
}
Beispiel #7
0
static void test_createconfigstream(void)
{
    IStream *stream = NULL;
    WCHAR file[] = {'c', 'o', 'n', 'f', '.', 'x', 'm', 'l', 0};
    WCHAR nonexistent[] = {'n', 'o', 'n', 'e', 'x', 'i', 's', 't', '.', 'x', 'm', 'l', 0};
    WCHAR path[MAX_PATH];
    HRESULT hr;
    char buffer[256] = {0};

    if (!pCreateConfigStream)
    {
        win_skip("CreateConfigStream not available\n");
        return;
    }

    create_xml_file(file);
    GetFullPathNameW(file, MAX_PATH, path, NULL);

    hr = pCreateConfigStream(NULL, &stream);
    ok(hr == E_FAIL ||
       broken(hr == HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND)) || /* some WinXP, Win2K3 and Win7 */
       broken(hr == S_OK && !stream), /* some Win2K3 */
       "CreateConfigStream returned %x\n", hr);

    hr = pCreateConfigStream(path, NULL);
    ok(hr == COR_E_NULLREFERENCE, "CreateConfigStream returned %x\n", hr);

    hr = pCreateConfigStream(NULL, NULL);
    ok(hr == COR_E_NULLREFERENCE, "CreateConfigStream returned %x\n", hr);

    hr = pCreateConfigStream(nonexistent, &stream);
    ok(hr == COR_E_FILENOTFOUND, "CreateConfigStream returned %x\n", hr);
    ok(stream == NULL, "Expected stream to be NULL\n");

    hr = pCreateConfigStream(path, &stream);
    ok(hr == S_OK, "CreateConfigStream failed, hr=%x\n", hr);
    ok(stream != NULL, "Expected non-NULL stream\n");

    if (stream)
    {
        DWORD count;
        LARGE_INTEGER pos;
        ULARGE_INTEGER size;
        IStream *stream2 = NULL;
        ULONG ref;

        hr = IStream_Read(stream, buffer, strlen(xmldata), &count);
        ok(hr == S_OK, "IStream_Read failed, hr=%x\n", hr);
        ok(count == strlen(xmldata), "wrong count: %u\n", count);
        ok(!strcmp(buffer, xmldata), "Strings do not match\n");

        hr = IStream_Read(stream, buffer, sizeof(buffer), &count);
        ok(hr == S_OK, "IStream_Read failed, hr=%x\n", hr);
        ok(!count, "wrong count: %u\n", count);

        hr = IStream_Write(stream, xmldata, strlen(xmldata), &count);
        ok(hr == E_FAIL, "IStream_Write returned hr=%x\n", hr);

        pos.QuadPart = strlen(xmldata);
        hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
        ok(hr == E_NOTIMPL, "IStream_Seek returned hr=%x\n", hr);

        size.QuadPart = strlen(xmldata);
        hr = IStream_SetSize(stream, size);
        ok(hr == E_NOTIMPL, "IStream_SetSize returned hr=%x\n", hr);

        hr = IStream_Clone(stream, &stream2);
        ok(hr == E_NOTIMPL, "IStream_Clone returned hr=%x\n", hr);

        hr = IStream_Commit(stream, STGC_DEFAULT);
        ok(hr == E_NOTIMPL, "IStream_Commit returned hr=%x\n", hr);

        hr = IStream_Revert(stream);
        ok(hr == E_NOTIMPL, "IStream_Revert returned hr=%x\n", hr);

        ref = IStream_Release(stream);
        ok(!ref, "IStream_Release returned %u\n", ref);
    }
    DeleteFileW(file);
}
Beispiel #8
0
/***
 * This method is part of the ISequentialStream interface.
 *
 * It writes a block of information to the stream at the current
 * position. It then moves the current position at the end of the
 * written block. If the stream is too small to fit the block,
 * the stream is grown to fit.
 *
 * See the documentation of ISequentialStream for more info.
 */
static HRESULT WINAPI HGLOBALStreamImpl_Write(
	          IStream*     iface,
		  const void*    pv,          /* [size_is][in] */
		  ULONG          cb,          /* [in] */
		  ULONG*         pcbWritten)  /* [out] */
{
  HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface;

  void*          supportBuffer;
  ULARGE_INTEGER newSize;
  ULONG          bytesWritten = 0;

  TRACE("(%p, %p, %d, %p)\n", iface, pv, cb, pcbWritten);

  /*
   * If the caller is not interested in the number of bytes written,
   * we use another buffer to avoid "if" statements in the code.
   */
  if (pcbWritten == 0)
    pcbWritten = &bytesWritten;

  if (cb == 0)
    goto out;

  *pcbWritten = 0;

  newSize.u.HighPart = 0;
  newSize.u.LowPart = This->currentPosition.u.LowPart + cb;

  /*
   * Verify if we need to grow the stream
   */
  if (newSize.u.LowPart > This->streamSize.u.LowPart)
  {
    /* grow stream */
    HRESULT hr = IStream_SetSize(iface, newSize);
    if (FAILED(hr))
    {
      ERR("IStream_SetSize failed with error 0x%08x\n", hr);
      return hr;
    }
  }

  /*
   * Lock the buffer in position and copy the data.
   */
  supportBuffer = GlobalLock(This->supportHandle);
  if (!supportBuffer)
  {
      WARN("write to invalid hglobal %p\n", This->supportHandle);
      return S_OK;
  }

  memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);

  /*
   * Move the current position to the new position
   */
  This->currentPosition.u.LowPart+=cb;

  /*
   * Cleanup
   */
  GlobalUnlock(This->supportHandle);

out:
  /*
   * Return the number of bytes read.
   */
  *pcbWritten = cb;

  return S_OK;
}
Beispiel #9
0
static void test_saxreader(void)
{
    HRESULT hr;
    ISAXXMLReader *reader = NULL;
    VARIANT var;
    ISAXContentHandler *lpContentHandler;
    ISAXErrorHandler *lpErrorHandler;
    SAFEARRAY *pSA;
    SAFEARRAYBOUND SADim[1];
    char *pSAData = NULL;
    IStream *iStream;
    ULARGE_INTEGER liSize;
    LARGE_INTEGER liPos;
    ULONG bytesWritten;
    HANDLE file;
    static const CHAR testXmlA[] = "test.xml";
    static const WCHAR testXmlW[] = {'t','e','s','t','.','x','m','l',0};
    IXMLDOMDocument *domDocument;
    BSTR bstrData;
    VARIANT_BOOL vBool;

    hr = CoCreateInstance(&CLSID_SAXXMLReader, NULL, CLSCTX_INPROC_SERVER,
            &IID_ISAXXMLReader, (LPVOID*)&reader);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);

    hr = ISAXXMLReader_getContentHandler(reader, NULL);
    ok(hr == E_POINTER, "Expected E_POINTER, got %08x\n", hr);

    hr = ISAXXMLReader_getErrorHandler(reader, NULL);
    ok(hr == E_POINTER, "Expected E_POINTER, got %08x\n", hr);

    hr = ISAXXMLReader_getContentHandler(reader, &lpContentHandler);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
    ok(lpContentHandler == NULL, "Expected %p, got %p\n", NULL, lpContentHandler);

    hr = ISAXXMLReader_getErrorHandler(reader, &lpErrorHandler);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
    ok(lpErrorHandler == NULL, "Expected %p, got %p\n", NULL, lpErrorHandler);

    hr = ISAXXMLReader_putContentHandler(reader, NULL);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);

    hr = ISAXXMLReader_putContentHandler(reader, &contentHandler);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);

    hr = ISAXXMLReader_putErrorHandler(reader, &errorHandler);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);

    hr = ISAXXMLReader_getContentHandler(reader, &lpContentHandler);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
    ok(lpContentHandler == &contentHandler, "Expected %p, got %p\n", &contentHandler, lpContentHandler);

    V_VT(&var) = VT_BSTR;
    V_BSTR(&var) = SysAllocString(szSimpleXML);

    expectCall = contentHandlerTest1;
    hr = ISAXXMLReader_parse(reader, var);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
    test_expect_call(CH_ENDTEST);

    VariantClear(&var);

    SADim[0].lLbound= 0;
    SADim[0].cElements= sizeof(szTestXML)-1;
    pSA = SafeArrayCreate(VT_UI1, 1, SADim);
    SafeArrayAccessData(pSA, (void**)&pSAData);
    memcpy(pSAData, szTestXML, sizeof(szTestXML)-1);
    SafeArrayUnaccessData(pSA);
    V_VT(&var) = VT_ARRAY|VT_UI1;
    V_ARRAY(&var) = pSA;

    expectCall = contentHandlerTest1;
    hr = ISAXXMLReader_parse(reader, var);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
    test_expect_call(CH_ENDTEST);

    SafeArrayDestroy(pSA);

    CreateStreamOnHGlobal(NULL, TRUE, &iStream);
    liSize.QuadPart = strlen(szTestXML);
    IStream_SetSize(iStream, liSize);
    IStream_Write(iStream, szTestXML, strlen(szTestXML), &bytesWritten);
    liPos.QuadPart = 0;
    IStream_Seek(iStream, liPos, STREAM_SEEK_SET, NULL);
    V_VT(&var) = VT_UNKNOWN|VT_DISPATCH;
    V_UNKNOWN(&var) = (IUnknown*)iStream;

    expectCall = contentHandlerTest1;
    hr = ISAXXMLReader_parse(reader, var);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
    test_expect_call(CH_ENDTEST);

    IStream_Release(iStream);

    V_VT(&var) = VT_BSTR;
    V_BSTR(&var) = SysAllocString(szCarriageRetTest);

    expectCall = contentHandlerTest2;
    hr = ISAXXMLReader_parse(reader, var);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
    test_expect_call(CH_ENDTEST);

    VariantClear(&var);

    file = CreateFileA(testXmlA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
    WriteFile(file, szTestXML, sizeof(szTestXML)-1, &bytesWritten, NULL);
    CloseHandle(file);

    expectCall = contentHandlerTest1;
    hr = ISAXXMLReader_parseURL(reader, testXmlW);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
    test_expect_call(CH_ENDTEST);

    DeleteFileA(testXmlA);

    hr = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
            &IID_IXMLDOMDocument, (LPVOID*)&domDocument);
    if(FAILED(hr))
    {
        skip("Failed to create DOMDocument instance\n");
        return;
    }
    bstrData = SysAllocString(szSimpleXML);
    hr = IXMLDOMDocument_loadXML(domDocument, bstrData, &vBool);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
    V_VT(&var) = VT_UNKNOWN;
    V_UNKNOWN(&var) = (IUnknown*)domDocument;

    expectCall = contentHandlerTest2;
    hr = ISAXXMLReader_parse(reader, var);
    ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
    test_expect_call(CH_ENDTEST);
    IXMLDOMDocument_Release(domDocument);

    ISAXXMLReader_Release(reader);
    SysFreeString(bstrData);
}
Beispiel #10
0
/***
 * This method is part of the ISequentialStream interface.
 *
 * It writes a block of information to the stream at the current
 * position. It then moves the current position at the end of the
 * written block. If the stream is too small to fit the block,
 * the stream is grown to fit.
 *
 * See the documentation of ISequentialStream for more info.
 */
static HRESULT WINAPI StgStreamImpl_Write(
	          IStream*     iface,
		  const void*    pv,          /* [size_is][in] */
		  ULONG          cb,          /* [in] */
		  ULONG*         pcbWritten)  /* [out] */
{
  StgStreamImpl* const This=(StgStreamImpl*)iface;

  ULARGE_INTEGER newSize;
  ULONG bytesWritten = 0;

  TRACE("(%p, %p, %ld, %p)\n",
	iface, pv, cb, pcbWritten);

  /*
   * Do we have permission to write to this stream?
   */
  switch(STGM_ACCESS_MODE(This->grfMode))
  {
  case STGM_WRITE:
  case STGM_READWRITE:
      break;
  default:
      WARN("access denied by flags: 0x%lx\n", STGM_ACCESS_MODE(This->grfMode));
      return STG_E_ACCESSDENIED;
  }

  if (!pv)
    return STG_E_INVALIDPOINTER;

  if (!This->parentStorage)
  {
    WARN("storage reverted\n");
    return STG_E_REVERTED;
  }
 
  /*
   * If the caller is not interested in the number of bytes written,
   * we use another buffer to avoid "if" statements in the code.
   */
  if (pcbWritten == 0)
    pcbWritten = &bytesWritten;

  /*
   * Initialize the out parameter
   */
  *pcbWritten = 0;

  if (cb == 0)
  {
    TRACE("<-- S_OK, written 0\n");
    return S_OK;
  }
  else
  {
    newSize.u.HighPart = 0;
    newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
  }

  /*
   * Verify if we need to grow the stream
   */
  if (newSize.u.LowPart > This->streamSize.u.LowPart)
  {
    /* grow stream */
    IStream_SetSize(iface, newSize);
  }

  /*
   * Depending on the type of chain that was opened when the stream was constructed,
   * we delegate the work to the method that readwrites to the block chains.
   */
  if (This->smallBlockChain!=0)
  {
    SmallBlockChainStream_WriteAt(This->smallBlockChain,
				  This->currentPosition,
				  cb,
				  pv,
				  pcbWritten);

  }
  else if (This->bigBlockChain!=0)
  {
    BlockChainStream_WriteAt(This->bigBlockChain,
			     This->currentPosition,
			     cb,
			     pv,
			     pcbWritten);
  }
  else
    assert(FALSE);

  /*
   * Advance the position pointer for the number of positions written.
   */
  This->currentPosition.u.LowPart += *pcbWritten;

  TRACE("<-- S_OK, written %lu\n", *pcbWritten);
  return S_OK;
}
Beispiel #11
0
static void test_streamonhglobal(IStream *pStream)
{
    const char data[] = "Test String";
    ULARGE_INTEGER ull;
    LARGE_INTEGER ll;
    char buffer[128];
    ULONG read;
    STATSTG statstg;
    HRESULT hr;

    ull.QuadPart = sizeof(data);
    hr = IStream_SetSize(pStream, ull);
    ok_ole_success(hr, "IStream_SetSize");

    hr = IStream_Write(pStream, data, sizeof(data), NULL);
    ok_ole_success(hr, "IStream_Write");

    ll.QuadPart = 0;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, NULL);
    ok_ole_success(hr, "IStream_Seek");

    /* should return S_OK, not S_FALSE */
    hr = IStream_Read(pStream, buffer, sizeof(buffer), &read);
    ok_ole_success(hr, "IStream_Read");
    ok(read == sizeof(data), "IStream_Read returned read %d\n", read);

    /* ignores HighPart */
    ull.u.HighPart = -1;
    ull.u.LowPart = 0;
    hr = IStream_SetSize(pStream, ull);
    ok_ole_success(hr, "IStream_SetSize");

    /* IStream_Seek -- NULL position argument */
    ll.u.HighPart = 0;
    ll.u.LowPart = 0;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, NULL);
    ok_ole_success(hr, "IStream_Seek");

    /* IStream_Seek -- valid position argument (seek from current position) */
    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 0;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == sizeof(data), "LowPart set to %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- invalid seek argument */
    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 123;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_END+1, &ull);
    ok(hr == STG_E_SEEKERROR, "IStream_Seek should have returned STG_E_SEEKERROR instead of 0x%08x\n", hr);
    ok(ull.u.LowPart == sizeof(data), "LowPart set to %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should not have changed HighPart, got %d\n", ull.u.HighPart);

    /* IStream_Seek -- valid position argument (seek to beginning) */
    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 0;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == 0, "should have set LowPart to 0 instead of %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- valid position argument (seek to end) */
    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 0;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_END, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == 0, "should have set LowPart to 0 instead of %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- ignore HighPart in the move value (seek from current position) */
    ll.u.HighPart = 0;
    ll.u.LowPart = sizeof(data);
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");

    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = -1;
    ll.u.LowPart = 0;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == sizeof(data), "LowPart set to %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- ignore HighPart in the move value (seek to beginning) */
    ll.u.HighPart = 0;
    ll.u.LowPart = sizeof(data);
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");

    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = -1;
    ll.u.LowPart = 0;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == 0, "should have set LowPart to 0 instead of %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- invalid LowPart value (seek before start of stream) */
    ll.u.HighPart = 0;
    ll.u.LowPart = sizeof(data);
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");

    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 0x80000000;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
    ok(hr == STG_E_SEEKERROR, "IStream_Seek should have returned STG_E_SEEKERROR instead of 0x%08x\n", hr);
    ok(ull.u.LowPart == sizeof(data), "LowPart set to %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- valid LowPart value (seek to start of stream) */
    ll.u.HighPart = 0;
    ll.u.LowPart = sizeof(data);
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");

    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = -(DWORD)sizeof(data);
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == 0, "LowPart set to %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- invalid LowPart value (seek to start of stream-1) */
    ll.u.HighPart = 0;
    ll.u.LowPart = sizeof(data);
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");

    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = -(DWORD)sizeof(data)-1;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
    ok(hr == STG_E_SEEKERROR, "IStream_Seek should have returned STG_E_SEEKERROR instead of 0x%08x\n", hr);
    ok(ull.u.LowPart == sizeof(data), "LowPart set to %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- valid LowPart value (seek forward to 0x80000000) */
    ll.u.HighPart = 0;
    ll.u.LowPart = sizeof(data);
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");

    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 0x80000000 - sizeof(data);
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == 0x80000000, "LowPart set to %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- invalid LowPart value (seek to beginning) */
    ll.u.HighPart = 0;
    ll.u.LowPart = sizeof(data);
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");

    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 0x80000000;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok(hr == STG_E_SEEKERROR, "IStream_Seek should have returned STG_E_SEEKERROR instead of 0x%08x\n", hr);
    ok(ull.u.LowPart == sizeof(data), "LowPart set to %d\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- valid LowPart value (seek to beginning) */
    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 0x7FFFFFFF;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == 0x7FFFFFFF, "should have set LowPart to 0x7FFFFFFF instead of %08x\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- valid LowPart value (seek from current position) */
    ll.u.HighPart = 0;
    ll.u.LowPart = 0;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, &ull);
    ok_ole_success(hr, "IStream_Seek");

    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 0x7FFFFFFF;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == 0x7FFFFFFF, "should have set LowPart to 0x7FFFFFFF instead of %08x\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- second seek allows you to go past 0x7FFFFFFF size */
    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 9;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == 0x80000008, "should have set LowPart to 0x80000008 instead of %08x\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    /* IStream_Seek -- seek wraps position/size on integer overflow */
    ull.u.HighPart = 0xCAFECAFE;
    ull.u.LowPart = 0xCAFECAFE;
    ll.u.HighPart = 0;
    ll.u.LowPart = 0x7FFFFFFF;
    hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
    ok_ole_success(hr, "IStream_Seek");
    ok(ull.u.LowPart == 0x00000007, "should have set LowPart to 0x00000007 instead of %08x\n", ull.u.LowPart);
    ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);

    hr = IStream_Commit(pStream, STGC_DEFAULT);
    ok_ole_success(hr, "IStream_Commit");

    hr = IStream_Revert(pStream);
    ok_ole_success(hr, "IStream_Revert");

    hr = IStream_LockRegion(pStream, ull, ull, LOCK_WRITE);
    ok(hr == STG_E_INVALIDFUNCTION, "IStream_LockRegion should have returned STG_E_INVALIDFUNCTION instead of 0x%08x\n", hr);

    hr = IStream_Stat(pStream, &statstg, STATFLAG_DEFAULT);
    ok_ole_success(hr, "IStream_Stat");
    ok(statstg.type == STGTY_STREAM, "statstg.type should have been STGTY_STREAM instead of %d\n", statstg.type);

    /* test OOM condition */
    ull.u.HighPart = -1;
    ull.u.LowPart = -1;
    hr = IStream_SetSize(pStream, ull);
    ok(hr == E_OUTOFMEMORY || broken(hr == S_OK), /* win9x */
       "IStream_SetSize with large size should have returned E_OUTOFMEMORY instead of 0x%08x\n", hr);
}