Implements OleLoadPicturePath

Robert Shearman rob at codeweavers.com
Mon Feb 28 15:22:33 CST 2005


Maxime Bellengé wrote:

>Hello, here is an implementation of OleLoadPicturePath.
>The filename can be either a local file or an url.
>In case of a url, I needed a user-agent for wininet. I put a dummy value
>as I didn't find a default wine value. Is there a default value
>somewhere for the whole project ?
>
>a+
>
>Max
>
>ChangeLog:
>    * Implements OleLoadPicturePath
>
>  
>
>------------------------------------------------------------------------
>
>Index: wine/dlls/oleaut32/olepicture.c
>===================================================================
>RCS file: /home/wine/wine/dlls/oleaut32/olepicture.c,v
>retrieving revision 1.55
>diff -u -r1.55 olepicture.c
>--- wine/dlls/oleaut32/olepicture.c	25 Feb 2005 14:07:57 -0000	1.55
>+++ wine/dlls/oleaut32/olepicture.c	27 Feb 2005 10:51:43 -0000
>@@ -71,7 +71,9 @@
> #include "olectl.h"
> #include "oleauto.h"
> #include "connpt.h"
>+#include "wininet.h"
> #include "wine/debug.h"
>+#include "wine/unicode.h"
> 
> #include "wine/wingdi16.h"
> #include "cursoricon.h"
>@@ -1998,11 +2000,122 @@
> 		DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
> 		LPVOID *ppvRet )
> {
>-  FIXME("(%s,%p,%ld,%08lx,%s,%p): stub\n",
>+  static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
>+  static const WCHAR name[] = { 'w','i','n','e','-','a','g','e','n','t',0};
>+  IPicture *ipicture;
>+  HANDLE hFile;
>+  DWORD dwFileSize;
>+  HGLOBAL hGlobal = NULL;
>+  DWORD dwBytesRead = 0;
>+  IStream *stream;
>+  BOOL bRead;
>+  IPersistStream *pStream;
>+  HRESULT hRes;
>+
>+  TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
>         debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
>         debugstr_guid(riid), ppvRet);
> 
>-  return E_NOTIMPL;
>+  if (!ppvRet) return E_POINTER;
>+
>+  if (strncmpW(szURLorPath, file, 7) == 0) {	    
>+      szURLorPath += 7;
>+  
>+      hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
>+				   0, NULL);
>+      if (hFile == INVALID_HANDLE_VALUE)
>+	  return E_UNEXPECTED;
>+
>+      dwFileSize = GetFileSize(hFile, NULL);
>+      if (dwFileSize != INVALID_FILE_SIZE )
>+      {
>+	  hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
>+	  if ( hGlobal)
>+	  {
>+	      bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
>+	      if (!bRead)
>+	      {
>+		  GlobalFree(hGlobal);
>+		  hGlobal = 0;
>+	      }
>+	  }
>+      }
>+      CloseHandle(hFile);      
>+  } else {
>+      HINTERNET hInternet;
>+      BOOL res = FALSE;
>+
>+      hInternet = InternetOpenW(name, INTERNET_OPEN_TYPE_PRECONFIG, NULL,
>+				NULL, 0);
>+      if (hInternet) 
>+      {
>+	  HINTERNET hFile;
>+	  hFile = InternetOpenUrlW(hInternet, szURLorPath, NULL, -1L, 
>+			  INTERNET_FLAG_RESYNCHRONIZE, (DWORD_PTR)NULL);
>+	  if (hFile)
>+	  {	      
>+	      DWORD total = 4096;
>+	      DWORD nbRead;	      
>+
>+	      hGlobal = GlobalAlloc(GMEM_FIXED, 4096);
>+	      if (hGlobal)
>+	      {
>+		  do {
>+		      res = InternetReadFile(hFile, hGlobal, 4096, &nbRead);
>+		      if (res && (nbRead>0))
>+		      {
>+			  HGLOBAL hNewGlobal;
>+			  hNewGlobal = GlobalReAlloc(hGlobal, total+4096, 0);
>+			  if (!hNewGlobal)
>+			  {
>+			      res = FALSE;
>+			      break;
>+			  }		      
>+		      }
>+		  } while (res && (nbRead>0));
>+	      }
>+	  }
>+	  
>+	  InternetCloseHandle(hInternet);
>+      }
>+      if (!res) 
>+      {
>+	  GlobalFree(hGlobal);	  
>+      }
>+  }
>+
>+  if (!hGlobal)
>+      return E_UNEXPECTED;
>+
>+  hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
>+  if (FAILED(hRes)) 
>+  {
>+      if (stream != NULL) IStream_Release(stream);
>  
>

A valid stream will not be returned on failure, so no need for the extra 
check here.

>+      GlobalFree(hGlobal);
>+      return hRes;
>+  }
>+
>+  hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER, 
>+		   &IID_IPicture, (LPVOID*)&ipicture);
>+  if (hRes != S_OK) {
>  
>

Lack of cleanup code here.

>+       return hRes;
>+  }
>+  
>+  hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
>+  if (hRes) {
>+      IPicture_Release(ipicture);
>  
>

And here.

>+      return hRes;
>+  }
>+
>+  IPersistStream_Load(pStream, stream);
>  
>

You should probably check the return value from this function as it is 
kinda vital to the function you are implementing.

>+  IPersistStream_Release(pStream);
>+  IStream_Release(stream);
>+  hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
>+  if (hRes)
>+      FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
>+  
>+  IPicture_Release(ipicture);
>+  return hRes;
> }
> 
> /*******************************************************************************
>  
>

>Index: wine/dlls/oleaut32/Makefile.in
>===================================================================
>RCS file: /home/wine/wine/dlls/oleaut32/Makefile.in,v
>retrieving revision 1.57
>diff -u -r1.57 Makefile.in
>--- wine/dlls/oleaut32/Makefile.in	27 Oct 2004 00:47:53 -0000	1.57
>+++ wine/dlls/oleaut32/Makefile.in	27 Feb 2005 10:52:08 -0000
>@@ -4,7 +4,7 @@
> SRCDIR    = @srcdir@
> VPATH     = @srcdir@
> MODULE    = oleaut32.dll
>-IMPORTS   = ole32 rpcrt4 user32 gdi32 advapi32 kernel32 ntdll
>+IMPORTS   = ole32 rpcrt4 user32 gdi32 advapi32 kernel32 ntdll wininet
> DELAYIMPORTS = comctl32
> EXTRALIBS = $(LIBUNICODE) -luuid 
>  
>

I don't think oleaut32 should be importing from wininet for just the 
implementation of OleLoadPicturePath. It surprises me that there is not 
already an implementation of IStream for URLs that can be re-used. If 
there is no alternative, I think we should just make wininet a delayed 
import.

Rob



More information about the wine-devel mailing list