- Sync rsaenh, schannel, shlwapi, sti, urlmon, usp10, version, windowscodecs, wininet...
authorAleksey Bragin <aleksey@reactos.org>
Tue, 20 Apr 2010 21:18:54 +0000 (21:18 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Tue, 20 Apr 2010 21:18:54 +0000 (21:18 +0000)
- Update README.WINE.

svn path=/trunk/; revision=46967

51 files changed:
reactos/dll/win32/lpk/dllmain.c
reactos/dll/win32/rsaenh/rsaenh.c
reactos/dll/win32/rsaenh/sha2.c
reactos/dll/win32/schannel/lsamode.c
reactos/dll/win32/shlwapi/ordinal.c
reactos/dll/win32/shlwapi/shlwapi.spec
reactos/dll/win32/shlwapi/url.c
reactos/dll/win32/sti/regsvr.c
reactos/dll/win32/sti/sti.c [new file with mode: 0644]
reactos/dll/win32/sti/sti.rbuild
reactos/dll/win32/sti/sti.spec
reactos/dll/win32/sti/sti_main.c
reactos/dll/win32/sti/sti_private.h [new file with mode: 0644]
reactos/dll/win32/sti/sti_wia.idl [new file with mode: 0644]
reactos/dll/win32/urlmon/bindprot.c
reactos/dll/win32/urlmon/regsvr.c
reactos/dll/win32/urlmon/urlmon_main.c
reactos/dll/win32/urlmon/urlmon_main.h
reactos/dll/win32/urlmon/urlmon_urlmon.idl
reactos/dll/win32/urlmon/usrmarshal.c
reactos/dll/win32/usp10/bidi.c [new file with mode: 0644]
reactos/dll/win32/usp10/usp10.c
reactos/dll/win32/usp10/usp10.rbuild
reactos/dll/win32/usp10/usp10.spec
reactos/dll/win32/usp10/usp10_internal.h [new file with mode: 0644]
reactos/dll/win32/version/resource.c
reactos/dll/win32/windowscodecs/bmpdecode.c
reactos/dll/win32/windowscodecs/clsfactory.c
reactos/dll/win32/windowscodecs/converter.c
reactos/dll/win32/windowscodecs/gifformat.c
reactos/dll/win32/windowscodecs/icoformat.c
reactos/dll/win32/windowscodecs/jpegformat.c
reactos/dll/win32/windowscodecs/palette.c
reactos/dll/win32/windowscodecs/pngformat.c
reactos/dll/win32/windowscodecs/regsvr.c
reactos/dll/win32/windowscodecs/stream.c
reactos/dll/win32/windowscodecs/tiffformat.c [new file with mode: 0644]
reactos/dll/win32/windowscodecs/wincodecs_private.h
reactos/dll/win32/windowscodecs/windowscodecs.rbuild
reactos/dll/win32/wininet/internet.c
reactos/dll/win32/wininet/urlcache.c
reactos/dll/win32/wintrust/asn.c
reactos/include/psdk/ntsecpkg.h
reactos/include/psdk/psdk.rbuild
reactos/include/psdk/shdeprecated.idl [new file with mode: 0644]
reactos/include/psdk/shlwapi.h
reactos/include/psdk/sti.h
reactos/include/psdk/wia.h [new file with mode: 0644]
reactos/include/psdk/wia_lh.idl [new file with mode: 0644]
reactos/include/psdk/wia_xp.idl [new file with mode: 0644]
reactos/media/doc/README.WINE

index 9b7c8e1..1d5bdc0 100644 (file)
@@ -36,7 +36,7 @@ LpkDllInitialize (
         case DLL_PROCESS_ATTACH:
             DisableThreadLibraryCalls(hDll);
             /* Tell usp10 it is activated usp10 */
-            LpkPresent();
+            //LpkPresent();
             break;
 
         default:
index 74ad392..8a5be99 100644 (file)
@@ -3354,6 +3354,33 @@ BOOL WINAPI RSAENH_CPSetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam
             setup_key(pCryptKey);
             return TRUE;
 
+        case KP_SALT:
+            switch (pCryptKey->aiAlgid) {
+                case CALG_RC2:
+                case CALG_RC4:
+                    if (!pbData)
+                    {
+                        SetLastError(ERROR_INVALID_PARAMETER);
+                        return FALSE;
+                    }
+                    /* MSDN: the base provider always sets eleven bytes of
+                     * salt value.
+                     */
+                    memcpy(pCryptKey->abKeyValue + pCryptKey->dwKeyLen,
+                           pbData, 11);
+                    pCryptKey->dwSaltLen = 11;
+                    setup_key(pCryptKey);
+                    /* Strange but true: salt length reset to 0 after setting
+                     * it via KP_SALT.
+                     */
+                    pCryptKey->dwSaltLen = 0;
+                    break;
+                default:
+                    SetLastError(NTE_BAD_KEY);
+                    return FALSE;
+            }
+            return TRUE;
+
         case KP_SALT_EX:
         {
             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pbData;
@@ -3486,8 +3513,16 @@ BOOL WINAPI RSAENH_CPGetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam
                               pCryptKey->dwBlockLen);
         
         case KP_SALT:
-            return copy_param(pbData, pdwDataLen, 
-                    &pCryptKey->abKeyValue[pCryptKey->dwKeyLen], pCryptKey->dwSaltLen);
+            switch (pCryptKey->aiAlgid) {
+                case CALG_RC2:
+                case CALG_RC4:
+                    return copy_param(pbData, pdwDataLen,
+                            &pCryptKey->abKeyValue[pCryptKey->dwKeyLen],
+                            pCryptKey->dwSaltLen);
+                default:
+                    SetLastError(NTE_BAD_KEY);
+                    return FALSE;
+            }
 
         case KP_PADDING:
             dwValue = PKCS5_PADDING;
index 559323c..ea5bb28 100644 (file)
@@ -273,7 +273,7 @@ static const char sha2_hex_digits[] = "0123456789abcdef";
 
 /*** SHA-256: *********************************************************/
 void SHA256_Init(SHA256_CTX* context) {
-       if (context == (SHA256_CTX*)0) {
+       if (context == NULL) {
                return;
        }
        MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH);
@@ -465,7 +465,7 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
        }
 
        /* Sanity check: */
-       assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
+       assert(context != NULL && data != NULL);
 
        usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
        if (usedspace > 0) {
@@ -490,7 +490,7 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
        }
        while (len >= SHA256_BLOCK_LENGTH) {
                /* Process as many complete blocks as we can */
-               SHA256_Transform(context, (sha2_word32*)data);
+               SHA256_Transform(context, (const sha2_word32*)data);
                context->bitcount += SHA256_BLOCK_LENGTH << 3;
                len -= SHA256_BLOCK_LENGTH;
                data += SHA256_BLOCK_LENGTH;
@@ -509,10 +509,10 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
        unsigned int    usedspace;
 
        /* Sanity check: */
-       assert(context != (SHA256_CTX*)0);
+       assert(context != NULL);
 
        /* If no digest buffer is passed, we don't bother doing this: */
-       if (digest != (sha2_byte*)0) {
+       if (digest != NULL) {
                usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
 #ifndef WORDS_BIGENDIAN
                /* Convert FROM host byte order */
@@ -572,9 +572,9 @@ char *SHA256_End(SHA256_CTX* context, char buffer[]) {
        int             i;
 
        /* Sanity check: */
-       assert(context != (SHA256_CTX*)0);
+       assert(context != NULL);
 
-       if (buffer != (char*)0) {
+       if (buffer != NULL) {
                SHA256_Final(digest, context);
 
                for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
@@ -582,7 +582,7 @@ char *SHA256_End(SHA256_CTX* context, char buffer[]) {
                        *buffer++ = sha2_hex_digits[*d & 0x0f];
                        d++;
                }
-               *buffer = (char)0;
+               *buffer = 0;
        } else {
                MEMSET_BZERO(context, sizeof(context));
        }
@@ -601,7 +601,7 @@ char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_S
 
 /*** SHA-512: *********************************************************/
 void SHA512_Init(SHA512_CTX* context) {
-       if (context == (SHA512_CTX*)0) {
+       if (context == NULL) {
                return;
        }
        MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);
@@ -787,7 +787,7 @@ void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
        }
 
        /* Sanity check: */
-       assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
+       assert(context != NULL && data != NULL);
 
        usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
        if (usedspace > 0) {
@@ -812,7 +812,7 @@ void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
        }
        while (len >= SHA512_BLOCK_LENGTH) {
                /* Process as many complete blocks as we can */
-               SHA512_Transform(context, (sha2_word64*)data);
+               SHA512_Transform(context, (const sha2_word64*)data);
                ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
                len -= SHA512_BLOCK_LENGTH;
                data += SHA512_BLOCK_LENGTH;
@@ -871,10 +871,10 @@ void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
        sha2_word64     *d = (sha2_word64*)digest;
 
        /* Sanity check: */
-       assert(context != (SHA512_CTX*)0);
+       assert(context != NULL);
 
        /* If no digest buffer is passed, we don't bother doing this: */
-       if (digest != (sha2_byte*)0) {
+       if (digest != NULL) {
                SHA512_Last(context);
 
                /* Save the hash data for output: */
@@ -901,9 +901,9 @@ char *SHA512_End(SHA512_CTX* context, char buffer[]) {
        int             i;
 
        /* Sanity check: */
-       assert(context != (SHA512_CTX*)0);
+       assert(context != NULL);
 
-       if (buffer != (char*)0) {
+       if (buffer != NULL) {
                SHA512_Final(digest, context);
 
                for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
@@ -911,7 +911,7 @@ char *SHA512_End(SHA512_CTX* context, char buffer[]) {
                        *buffer++ = sha2_hex_digits[*d & 0x0f];
                        d++;
                }
-               *buffer = (char)0;
+               *buffer = 0;
        } else {
                MEMSET_BZERO(context, sizeof(context));
        }
@@ -930,7 +930,7 @@ char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_S
 
 /*** SHA-384: *********************************************************/
 void SHA384_Init(SHA384_CTX* context) {
-       if (context == (SHA384_CTX*)0) {
+       if (context == NULL) {
                return;
        }
        MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH);
@@ -946,10 +946,10 @@ void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
        sha2_word64     *d = (sha2_word64*)digest;
 
        /* Sanity check: */
-       assert(context != (SHA384_CTX*)0);
+       assert(context != NULL);
 
        /* If no digest buffer is passed, we don't bother doing this: */
-       if (digest != (sha2_byte*)0) {
+       if (digest != NULL) {
                SHA512_Last((SHA512_CTX*)context);
 
                /* Save the hash data for output: */
@@ -976,9 +976,9 @@ char *SHA384_End(SHA384_CTX* context, char buffer[]) {
        int             i;
 
        /* Sanity check: */
-       assert(context != (SHA384_CTX*)0);
+       assert(context != NULL);
 
-       if (buffer != (char*)0) {
+       if (buffer != NULL) {
                SHA384_Final(digest, context);
 
                for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
@@ -986,7 +986,7 @@ char *SHA384_End(SHA384_CTX* context, char buffer[]) {
                        *buffer++ = sha2_hex_digits[*d & 0x0f];
                        d++;
                }
-               *buffer = (char)0;
+               *buffer = 0;
        } else {
                MEMSET_BZERO(context, sizeof(context));
        }
index 23d8599..f43150e 100644 (file)
@@ -109,6 +109,12 @@ static SECPKG_FUNCTION_TABLE secPkgFunctionTable[2] =
     NULL, /* SetExtendedInformation */
     NULL, /* SetContextAttributes */
     NULL, /* SetCredentialsAttributes */
+    NULL, /* ChangeAccountPassword */
+    NULL, /* QueryMetaData */
+    NULL, /* ExchangeMetaData */
+    NULL, /* GetCredUIContext */
+    NULL, /* UpdateCredentials */
+    NULL, /* ValidateTargetInfo */
   }, {
     NULL, /* InitializePackage */
     NULL, /* LsaLogonUser */
@@ -139,6 +145,12 @@ static SECPKG_FUNCTION_TABLE secPkgFunctionTable[2] =
     NULL, /* SetExtendedInformation */
     NULL, /* SetContextAttributes */
     NULL, /* SetCredentialsAttributes */
+    NULL, /* ChangeAccountPassword */
+    NULL, /* QueryMetaData */
+    NULL, /* ExchangeMetaData */
+    NULL, /* GetCredUIContext */
+    NULL, /* UpdateCredentials */
+    NULL, /* ValidateTargetInfo */
   }
 };
 
@@ -150,7 +162,7 @@ NTSTATUS WINAPI SpLsaModeInitialize(ULONG LsaVersion, PULONG PackageVersion,
 {
     TRACE("(%u, %p, %p, %p)\n", LsaVersion, PackageVersion, ppTables, pcTables);
 
-    *PackageVersion = SECPKG_INTERFACE_VERSION_3;
+    *PackageVersion = SECPKG_INTERFACE_VERSION_6;
     *pcTables = 2;
     *ppTables = secPkgFunctionTable;
 
index 364bbfe..332bdb6 100644 (file)
@@ -42,6 +42,7 @@
 #include "mmsystem.h"
 #include "objbase.h"
 #include "exdisp.h"
+#include "shdeprecated.h"
 #include "shlobj.h"
 #include "shlwapi.h"
 #include "shellapi.h"
@@ -309,24 +310,22 @@ HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
   BSTR property;
   IEnumFORMATETC* pIEnumFormatEtc = NULL;
   VARIANTARG var;
-  HRESULT hRet;
-  IWebBrowserApp* pBrowser = NULL;
+  HRESULT hr;
+  IWebBrowserApp* pBrowser;
 
   TRACE("(%p, %p)\n", lpBC, lpUnknown);
 
-  /* Get An IWebBrowserApp interface from  lpUnknown */
-  hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
-  if (FAILED(hRet) || !pBrowser)
-    return E_NOINTERFACE;
+  hr = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (void**)&pBrowser);
+  if (FAILED(hr))
+    return hr;
 
   V_VT(&var) = VT_EMPTY;
 
   /* The property we get is the browsers clipboard enumerator */
   property = SysAllocString(szProperty);
-  hRet = IWebBrowserApp_GetProperty(pBrowser, property, &var);
+  hr = IWebBrowserApp_GetProperty(pBrowser, property, &var);
   SysFreeString(property);
-  if (FAILED(hRet))
-    return hRet;
+  if (FAILED(hr)) goto exit;
 
   if (V_VT(&var) == VT_EMPTY)
   {
@@ -340,7 +339,10 @@ HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
 
     if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
                      "Version\\Internet Settings\\Accepted Documents", &hDocs))
-      return E_FAIL;
+    {
+      hr = E_FAIL;
+      goto exit;
+    }
 
     /* Get count of values in key */
     while (!dwRet)
@@ -355,7 +357,11 @@ HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
     /* Note: dwCount = number of items + 1; The extra item is the end node */
     format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
     if (!formatList)
-      return E_OUTOFMEMORY;
+    {
+      RegCloseKey(hDocs);
+      hr = E_OUTOFMEMORY;
+      goto exit;
+    }
 
     if (dwNumValues > 1)
     {
@@ -372,7 +378,12 @@ HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
         dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
                               (PBYTE)szValueBuff, &dwValueSize);
         if (!dwRet)
-          return E_FAIL;
+        {
+          HeapFree(GetProcessHeap(), 0, formatList);
+          RegCloseKey(hDocs);
+          hr = E_FAIL;
+          goto exit;
+        }
 
         format->cfFormat = RegisterClipboardFormatA(szValueBuff);
         format->ptd = NULL;
@@ -385,6 +396,8 @@ HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
       }
     }
 
+    RegCloseKey(hDocs);
+
     /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
     format->cfFormat = 0;
     format->ptd = NULL;
@@ -393,22 +406,21 @@ HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
     format->tymed = -1;
 
     /* Create a clipboard enumerator */
-    hRet = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
-
-    if (FAILED(hRet) || !pIEnumFormatEtc)
-      return hRet;
+    hr = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
+    HeapFree(GetProcessHeap(), 0, formatList);
+    if (FAILED(hr)) goto exit;
 
     /* Set our enumerator as the browsers property */
     V_VT(&var) = VT_UNKNOWN;
     V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
 
     property = SysAllocString(szProperty);
-    hRet = IWebBrowserApp_PutProperty(pBrowser, property, var);
+    hr = IWebBrowserApp_PutProperty(pBrowser, property, var);
     SysFreeString(property);
-    if (FAILED(hRet))
+    if (FAILED(hr))
     {
        IEnumFORMATETC_Release(pIEnumFormatEtc);
-       goto RegisterDefaultAcceptHeaders_Exit;
+       goto exit;
     }
   }
 
@@ -422,28 +434,26 @@ HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
 
     /* Get an IEnumFormatEtc interface from the variants value */
     pIEnumFormatEtc = NULL;
-    hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
-                                   (PVOID)&pIEnumFormatEtc);
-    if (hRet == S_OK && pIEnumFormatEtc)
+    hr = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC, (void**)&pIEnumFormatEtc);
+    if (hr == S_OK && pIEnumFormatEtc)
     {
       /* Clone and register the enumerator */
-      hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
-      if (hRet == S_OK && pClone)
+      hr = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
+      if (hr == S_OK && pClone)
       {
         RegisterFormatEnumerator(lpBC, pClone, 0);
 
         IEnumFORMATETC_Release(pClone);
       }
 
-      /* Release the IEnumFormatEtc interface */
       IEnumFORMATETC_Release(pIUnknown);
     }
     IUnknown_Release(V_UNKNOWN(&var));
   }
 
-RegisterDefaultAcceptHeaders_Exit:
+exit:
   IWebBrowserApp_Release(pBrowser);
-  return hRet;
+  return hr;
 }
 
 /*************************************************************************
@@ -500,7 +510,7 @@ HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
         return S_OK;
     }
 
-    /* Did not find a value in the registry or the user buffer is to small */
+    /* Did not find a value in the registry or the user buffer is too small */
     mylcid = GetUserDefaultLCID();
     retval = LcidToRfc1766W(mylcid, mystr, mystrlen);
     len = lstrlenW(mystr);
@@ -1201,7 +1211,7 @@ HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL f
 /*************************************************************************
  *     @       [SHLWAPI.169]
  *
- * Release an interface.
+ * Release an interface and zero a supplied pointer.
  *
  * PARAMS
  *  lpUnknown [I] Object to release
@@ -1209,19 +1219,16 @@ HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL f
  * RETURNS
  *  Nothing.
  */
-DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
+void WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
 {
-    IUnknown *temp;
-
-    TRACE("(%p)\n",lpUnknown);
+    TRACE("(%p)\n", lpUnknown);
 
-    if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
-    temp = *lpUnknown;
-    *lpUnknown = NULL;
+    if(!lpUnknown || !*lpUnknown) return;
 
     TRACE("doing Release\n");
 
-    return IUnknown_Release(temp);
+    IUnknown_Release(*lpUnknown);
+    *lpUnknown = NULL;
 }
 
 /*************************************************************************
@@ -1258,9 +1265,10 @@ LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
  */
 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
 {
-  LPVOID lpUnknown1, lpUnknown2;
+  IUnknown *lpUnknown1, *lpUnknown2;
+  BOOL ret;
 
-  TRACE("%p %p\n", lpInt1, lpInt2);
+  TRACE("(%p %p)\n", lpInt1, lpInt2);
 
   if (!lpInt1 || !lpInt2)
     return FALSE;
@@ -1268,16 +1276,21 @@ BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
   if (lpInt1 == lpInt2)
     return TRUE;
 
-  if (FAILED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown, &lpUnknown1)))
+  if (IUnknown_QueryInterface(lpInt1, &IID_IUnknown, (void**)&lpUnknown1) != S_OK)
     return FALSE;
 
-  if (FAILED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown, &lpUnknown2)))
+  if (IUnknown_QueryInterface(lpInt2, &IID_IUnknown, (void**)&lpUnknown2) != S_OK)
+  {
+    IUnknown_Release(lpUnknown1);
     return FALSE;
+  }
 
-  if (lpUnknown1 == lpUnknown2)
-    return TRUE;
+  ret = lpUnknown1 == lpUnknown2;
 
-  return FALSE;
+  IUnknown_Release(lpUnknown1);
+  IUnknown_Release(lpUnknown2);
+
+  return ret;
 }
 
 /*************************************************************************
@@ -1337,36 +1350,32 @@ HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
 /*************************************************************************
  *      @      [SHLWAPI.173]
  *
- * Call a method on as as yet unidentified object.
+ * Call a SetOwner method of IShellService from specified object.
  *
  * PARAMS
- *  pUnk [I] Object supporting the unidentified interface,
- *  arg  [I] Argument for the call on the object.
+ *  iface [I] Object that supports IShellService
+ *  pUnk  [I] Argument for the SetOwner call
  *
  * RETURNS
- *  S_OK.
+ *  Corresponding return value from last call or E_FAIL for null input
  */
-HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
+HRESULT WINAPI IUnknown_SetOwner(IUnknown *iface, IUnknown *pUnk)
 {
-  static const GUID guid_173 = {
-    0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
-  };
-  IMalloc *pUnk2;
+  IShellService *service;
+  HRESULT hr;
 
-  TRACE("(%p,%d)\n", pUnk, arg);
+  TRACE("(%p, %p)\n", iface, pUnk);
 
-  /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
-   *       We use this interface as its vtable entry is compatible with the
-   *       object in question.
-   * FIXME: Find out what this object is and where it should be defined.
-   */
-  if (pUnk &&
-      SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
+  if (!iface) return E_FAIL;
+
+  hr = IUnknown_QueryInterface(iface, &IID_IShellService, (void**)&service);
+  if (hr == S_OK)
   {
-    IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
-    IMalloc_Release(pUnk2);
+    hr = IShellService_SetOwner(service, pUnk);
+    IShellService_Release(service);
   }
-  return S_OK;
+
+  return hr;
 }
 
 /*************************************************************************
@@ -1473,7 +1482,6 @@ HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID ri
   if (!lpUnknown)
     return E_FAIL;
 
-  /* Get an IServiceProvider interface from the object */
   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
                                  (LPVOID*)&pService);
 
@@ -1486,12 +1494,92 @@ HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID ri
 
     TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
 
-    /* Release the IServiceProvider interface */
     IUnknown_Release(pService);
   }
   return hRet;
 }
 
+/*************************************************************************
+ *      @      [SHLWAPI.484]
+ *
+ * Calls IOleCommandTarget::Exec() for specified service object.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object to get an IServiceProvider interface from
+ *  service   [I] Service ID for IServiceProvider_QueryService() call
+ *  group     [I] Group ID for IOleCommandTarget::Exec() call
+ *  cmdId     [I] Command ID for IOleCommandTarget::Exec() call
+ *  cmdOpt    [I] Options flags for command
+ *  pIn       [I] Input arguments for command
+ *  pOut      [O] Output arguments for command
+ *
+ * RETURNS
+ *  Success: S_OK. lppOut contains an object providing the requested service
+ *  Failure: An HRESULT error code
+ *
+ * NOTES
+ *  lpUnknown is expected to support the IServiceProvider interface.
+ */
+HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *lpUnknown, REFIID service,
+    const GUID *group, DWORD cmdId, DWORD cmdOpt, VARIANT *pIn, VARIANT *pOut)
+{
+    IOleCommandTarget *target;
+    HRESULT hr;
+
+    TRACE("%p %s %s %d %08x %p %p\n", lpUnknown, debugstr_guid(service),
+        debugstr_guid(group), cmdId, cmdOpt, pIn, pOut);
+
+    hr = IUnknown_QueryService(lpUnknown, service, &IID_IOleCommandTarget, (void**)&target);
+    if (hr == S_OK)
+    {
+        hr = IOleCommandTarget_Exec(target, group, cmdId, cmdOpt, pIn, pOut);
+        IOleCommandTarget_Release(target);
+    }
+
+    TRACE("<-- hr=0x%08x\n", hr);
+
+    return hr;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.514]
+ *
+ * Calls IProfferService methods to proffer/revoke specified service.
+ *
+ * PARAMS
+ *  lpUnknown [I]  Object to get an IServiceProvider interface from
+ *  service   [I]  Service ID for IProfferService::Proffer/Revoke calls
+ *  pService  [I]  Service to proffer. If NULL ::Revoke is called
+ *  pCookie   [IO] Group ID for IOleCommandTarget::Exec() call
+ *
+ * RETURNS
+ *  Success: S_OK. IProffer method returns S_OK
+ *  Failure: An HRESULT error code
+ *
+ * NOTES
+ *  lpUnknown is expected to support the IServiceProvider interface.
+ */
+HRESULT WINAPI IUnknown_ProfferService(IUnknown *lpUnknown, REFGUID service, IServiceProvider *pService, DWORD *pCookie)
+{
+    IProfferService *proffer;
+    HRESULT hr;
+
+    TRACE("%p %s %p %p\n", lpUnknown, debugstr_guid(service), pService, pCookie);
+
+    hr = IUnknown_QueryService(lpUnknown, &IID_IProfferService, &IID_IProfferService, (void**)&proffer);
+    if (hr == S_OK)
+    {
+        if (pService)
+            hr = IProfferService_ProfferService(proffer, service, pService, pCookie);
+        else
+            hr = IProfferService_RevokeService(proffer, *pCookie);
+
+        IProfferService_Release(proffer);
+    }
+
+    return hr;
+}
+
 /*************************************************************************
  *      @      [SHLWAPI.479]
  *
@@ -1546,6 +1634,8 @@ BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
 {
   HMENU hMenu;
 
+  TRACE("%p %s\n", hInst, debugstr_w(szName));
+
   if ((hMenu = LoadMenuW(hInst, szName)))
   {
     if (GetSubMenu(hMenu, 0))
@@ -1629,6 +1719,9 @@ void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lP
 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
 {
   int iItemCount = GetMenuItemCount(hMenu) - 1;
+
+  TRACE("%p\n", hMenu);
+
   while (iItemCount >= 0)
   {
     HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
@@ -1654,6 +1747,7 @@ DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
  */
 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
 {
+  TRACE("%p, %u, %d\n", hMenu, wItemID, bEnable);
   return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
 }
 
@@ -1672,6 +1766,7 @@ UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
  */
 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
 {
+  TRACE("%p, %u, %d\n", hMenu, uID, bCheck);
   return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
 }
 
@@ -1703,6 +1798,8 @@ BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
   DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
   POINTL pt = { 0, 0 };
 
+  TRACE("%p %p 0x%08x %p %p\n", pDrop, pDataObj, grfKeyState, lpPt, pdwEffect);
+
   if (!lpPt)
     lpPt = &pt;
 
@@ -1711,7 +1808,7 @@ BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
 
   IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
 
-  if (*pdwEffect)
+  if (*pdwEffect != DROPEFFECT_NONE)
     return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
 
   IDropTarget_DragLeave(pDrop);
@@ -1803,7 +1900,7 @@ HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
   IOleControlSite* lpCSite = NULL;
   HRESULT hRet = E_FAIL;
 
-  TRACE("(%p,%s)\n", lpUnknown, fGotFocus ? "TRUE" : "FALSE");
+  TRACE("(%p, %d)\n", lpUnknown, fGotFocus);
   if (lpUnknown)
   {
     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
@@ -2061,12 +2158,10 @@ VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
 {
   TRACE("(%p,%p)\n", lppDest, lpUnknown);
 
-  if (lppDest)
-    IUnknown_AtomicRelease(lppDest); /* Release existing interface */
+  IUnknown_AtomicRelease(lppDest);
 
   if (lpUnknown)
   {
-    /* Copy */
     IUnknown_AddRef(lpUnknown);
     *lppDest = lpUnknown;
   }
@@ -2256,12 +2351,6 @@ BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
     return TRUE;
 }
 
-
-typedef struct {
-    REFIID   refid;
-    DWORD    indx;
-} IFACE_INDEX_TBL;
-
 /*************************************************************************
  *      @      [SHLWAPI.219]
  *
@@ -2272,22 +2361,22 @@ typedef struct {
  *  Failure: E_POINTER or E_NOINTERFACE.
  */
 HRESULT WINAPI QISearch(
-       LPVOID w,           /* [in]   Table of interfaces */
-       IFACE_INDEX_TBL *x, /* [in]   Array of REFIIDs and indexes into the table */
+       void *base,         /* [in]   Table of interfaces */
+       const QITAB *table, /* [in]   Array of REFIIDs and indexes into the table */
        REFIID riid,        /* [in]   REFIID to get interface for */
-       LPVOID *ppv)          /* [out]  Destination for interface pointer */
+       void **ppv)         /* [out]  Destination for interface pointer */
 {
        HRESULT ret;
        IUnknown *a_vtbl;
-       IFACE_INDEX_TBL *xmove;
+       const QITAB *xmove;
 
-       TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
+       TRACE("(%p %p %s %p)\n", base, table, debugstr_guid(riid), ppv);
        if (ppv) {
-           xmove = x;
-           while (xmove->refid) {
-               TRACE("trying (indx %d) %s\n", xmove->indx, debugstr_guid(xmove->refid));
-               if (IsEqualIID(riid, xmove->refid)) {
-                   a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
+           xmove = table;
+           while (xmove->piid) {
+               TRACE("trying (offset %d) %s\n", xmove->dwOffset, debugstr_guid(xmove->piid));
+               if (IsEqualIID(riid, xmove->piid)) {
+                   a_vtbl = (IUnknown*)(xmove->dwOffset + (LPBYTE)base);
                    TRACE("matched, returning (%p)\n", a_vtbl);
                     *ppv = a_vtbl;
                    IUnknown_AddRef(a_vtbl);
@@ -2297,7 +2386,7 @@ HRESULT WINAPI QISearch(
            }
 
            if (IsEqualIID(riid, &IID_IUnknown)) {
-               a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
+               a_vtbl = (IUnknown*)(table->dwOffset + (LPBYTE)base);
                TRACE("returning first for IUnknown (%p)\n", a_vtbl);
                 *ppv = a_vtbl;
                IUnknown_AddRef(a_vtbl);
@@ -2506,27 +2595,27 @@ HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
  *  dwExStyle  [I] Extra style flags
  *  dwStyle    [I] Style flags
  *  hMenu      [I] Window menu
- *  z          [I] Unknown
+ *  wnd_extra  [I] Window extra bytes value
  *
  * RETURNS
  *  Success: The window handle of the newly created window.
  *  Failure: 0.
  */
 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
-                        DWORD dwStyle, HMENU hMenu, LONG z)
+                                  DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra)
 {
   static const char szClass[] = "WorkerA";
   WNDCLASSA wc;
   HWND hWnd;
 
-  TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
-         wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
+  TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
+         wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
 
   /* Create Window class */
   wc.style         = 0;
   wc.lpfnWndProc   = DefWindowProcA;
   wc.cbClsExtra    = 0;
-  wc.cbWndExtra    = 4;
+  wc.cbWndExtra    = sizeof(LONG_PTR);
   wc.hInstance     = shlwapi_hInstance;
   wc.hIcon         = NULL;
   wc.hCursor       = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
@@ -2534,19 +2623,17 @@ HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle
   wc.lpszMenuName  = NULL;
   wc.lpszClassName = szClass;
 
-  SHRegisterClassA(&wc); /* Register class */
-
-  /* FIXME: Set extra bits in dwExStyle */
+  SHRegisterClassA(&wc);
 
   hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
                          hWndParent, hMenu, shlwapi_hInstance, 0);
   if (hWnd)
   {
-    SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
+    SetWindowLongPtrW(hWnd, 0, wnd_extra);
 
-    if (wndProc)
-      SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
+    if (wndProc) SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
   }
+
   return hWnd;
 }
 
@@ -2729,7 +2816,7 @@ BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
  */
 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
 {
-    return SUCCEEDED(CLSIDFromString((LPOLESTR)idstr, id));
+    return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id));
 }
 
 /*************************************************************************
@@ -2804,18 +2891,21 @@ DWORD WINAPI WhichPlatform(void)
  * Unicode version of SHCreateWorkerWindowA.
  */
 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
-                        DWORD dwStyle, HMENU hMenu, LONG z)
+                        DWORD dwStyle, HMENU hMenu, LONG msg_result)
 {
-  static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
+  static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
   WNDCLASSW wc;
   HWND hWnd;
 
-  TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
-         wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
+  TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
+         wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
 
-  /* If our OS is natively ASCII, use the ASCII version */
-  if (!(GetVersion() & 0x80000000))  /* NT */
-    return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
+  /* If our OS is natively ANSI, use the ANSI version */
+  if (GetVersion() & 0x80000000)  /* not NT */
+  {
+    TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
+    return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
+  }
 
   /* Create Window class */
   wc.style         = 0;
@@ -2829,19 +2919,17 @@ HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle
   wc.lpszMenuName  = NULL;
   wc.lpszClassName = szClass;
 
-  SHRegisterClassW(&wc); /* Register class */
-
-  /* FIXME: Set extra bits in dwExStyle */
+  SHRegisterClassW(&wc);
 
   hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
                          hWndParent, hMenu, shlwapi_hInstance, 0);
   if (hWnd)
   {
-    SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
+    SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, msg_result);
 
-    if (wndProc)
-      SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
+    if (wndProc) SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
   }
+
   return hWnd;
 }
 
@@ -2861,7 +2949,8 @@ HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle
  */
 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
 {
-  return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
+    TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl);
+    return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
 }
 
 /*************************************************************************
@@ -3376,12 +3465,12 @@ UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags,
 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
 {
   IContextMenu *iContext;
-  HRESULT hRet = E_FAIL;
+  HRESULT hRet;
 
-  TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
+  TRACE("(%p, %p, %p, %d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
 
   if (!lpFolder)
-    return hRet;
+    return E_FAIL;
 
   /* Get the context menu from the shell folder */
   hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
@@ -3401,7 +3490,7 @@ HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST
       if (SUCCEEDED(hQuery))
       {
         if (bInvokeDefault &&
-            (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
+            (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != (UINT)-1)
         {
           CMINVOKECOMMANDINFO cmIci;
           /* Invoke the default item */
@@ -3810,7 +3899,7 @@ DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam)
  */
 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
 {
-    return CLSIDFromString((LPOLESTR)idstr, id);
+    return CLSIDFromString((LPCOLESTR)idstr, id);
 }
 
 /*************************************************************************
@@ -4171,18 +4260,24 @@ BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
  */
 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
 {
- MENUITEMINFOW mi;
- INT nCount = GetMenuItemCount(hMenu), nIter = 0;
+    MENUITEMINFOW mi;
+    INT nCount = GetMenuItemCount(hMenu), nIter = 0;
+
+    TRACE("%p %u\n", hMenu, wID);
 
- while (nIter < nCount)
- {
-   mi.cbSize = sizeof(mi);
-   mi.fMask = MIIM_ID;
-   if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
-     return nIter;
-   nIter++;
- }
- return -1;
+    while (nIter < nCount)
+    {
+        mi.cbSize = sizeof(mi);
+        mi.fMask = MIIM_ID;
+        if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
+        {
+            TRACE("ret %d\n", nIter);
+            return nIter;
+        }
+        nIter++;
+    }
+
+    return -1;
 }
 
 /*************************************************************************
@@ -4192,6 +4287,7 @@ INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
  */
 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
 {
+    TRACE("%p %u\n", hMenu, uID);
     return GetMenuPosFromID(hMenu, uID);
 }
 
@@ -4270,10 +4366,10 @@ BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
 /***********************************************************************
  *             SHGetShellKey (SHLWAPI.@)
  */
-DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
+HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create)
 {
-    FIXME("(%x, %x, %x): stub\n", a, b, c);
-    return 0x50;
+    FIXME("(0x%08x, %s, %d): stub\n", flags, debugstr_w(sub_key), create);
+    return (HKEY)0x50;
 }
 
 /***********************************************************************
@@ -4422,20 +4518,6 @@ INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
     return ret;
 }
 
-HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *unk, REFIID service, REFIID clsid,
-                                         DWORD x1, DWORD x2, DWORD x3, void **ppvOut)
-{
-    FIXME("%p %s %s %08x %08x %08x %p\n", unk,
-          debugstr_guid(service), debugstr_guid(clsid), x1, x2, x3, ppvOut);
-    return E_NOTIMPL;
-}
-
-HRESULT WINAPI IUnknown_ProfferService(IUnknown *unk, void *x0, void *x1, void *x2)
-{
-    FIXME("%p %p %p %p\n", unk, x0, x1, x2);
-    return E_NOTIMPL;
-}
-
 /***********************************************************************
  *              ZoneComputePaneSize [SHLWAPI.382]
  */
index d899232..367046b 100644 (file)
 216 stdcall -noname SHAnsiToUnicodeCP(long str ptr long)
 217 stdcall -noname SHUnicodeToAnsi(wstr ptr ptr)
 218 stdcall -noname SHUnicodeToAnsiCP(long wstr ptr long)
-219 stdcall -noname QISearch(long long long long)
+219 stdcall QISearch(long long long long)
 220 stdcall -noname SHSetDefaultDialogFont(ptr long)
 221 stdcall -noname SHRemoveDefaultDialogFont(ptr)
 222 stdcall -noname SHGlobalCounterCreate(long)
index 958a842..cd83b45 100644 (file)
@@ -278,7 +278,8 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,
 {
     HRESULT hr = S_OK;
     DWORD EscapeFlags;
-    LPWSTR lpszUrlCpy, wk1, wk2, mp, mp2, root;
+    LPCWSTR wk1, root;
+    LPWSTR lpszUrlCpy, wk2, mp, mp2;
     INT state;
     DWORD nByteLen, nLen, nWkLen;
     WCHAR slash = '/';
@@ -322,7 +323,7 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,
      *         6   have location (found /) save root location
      */
 
-    wk1 = (LPWSTR)pszUrl;
+    wk1 = pszUrl;
     wk2 = lpszUrlCpy;
     state = 0;
 
@@ -662,7 +663,7 @@ HRESULT WINAPI UrlCombineW(LPCWSTR pszBase, LPCWSTR pszRelative,
             }
         }
 
-        /* If there is a '#' and the characters immediately preceeding it are
+        /* If there is a '#' and the characters immediately preceding it are
          * ".htm[l]", then begin looking for the last leaf starting from
          * the '#'. Otherwise the '#' is not meaningful and just start
          * looking from the end. */
@@ -1718,6 +1719,9 @@ BOOL WINAPI UrlIsA(LPCSTR pszUrl, URLIS Urlis)
 
     TRACE("(%s %d)\n", debugstr_a(pszUrl), Urlis);
 
+    if(!pszUrl)
+        return FALSE;
+
     switch (Urlis) {
 
     case URLIS_OPAQUE:
@@ -1768,6 +1772,9 @@ BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis)
 
     TRACE("(%s %d)\n", debugstr_w(pszUrl), Urlis);
 
+    if(!pszUrl)
+        return FALSE;
+
     switch (Urlis) {
 
     case URLIS_OPAQUE:
index 018c178..3e582ec 100644 (file)
@@ -19,7 +19,6 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-
 #include <stdarg.h>
 #include <string.h>
 
@@ -31,6 +30,7 @@
 #include "objbase.h"
 #include "initguid.h"
 #include "sti.h"
+#include "wia_lh.h"
 
 #include "wine/debug.h"
 #include "wine/unicode.h"
@@ -395,8 +395,11 @@ static struct regsvr_interface const interface_list[] = {
     { NULL }                   /* list terminator */
 };
 
+extern HRESULT WINAPI STI_DllRegisterServer(void) DECLSPEC_HIDDEN;
+extern HRESULT WINAPI STI_DllUnregisterServer(void) DECLSPEC_HIDDEN;
+
 /***********************************************************************
- *             DllRegisterServer (INETCOMM.@)
+ *             DllRegisterServer (STI.@)
  */
 HRESULT WINAPI DllRegisterServer(void)
 {
@@ -404,14 +407,16 @@ HRESULT WINAPI DllRegisterServer(void)
 
     TRACE("\n");
 
-    hr = register_coclasses(coclass_list);
+    hr = STI_DllRegisterServer();
+    if (SUCCEEDED(hr))
+        hr = register_coclasses(coclass_list);
     if (SUCCEEDED(hr))
        hr = register_interfaces(interface_list);
     return hr;
 }
 
 /***********************************************************************
- *             DllUnregisterServer (INETCOMM.@)
+ *             DllUnregisterServer (STI.@)
  */
 HRESULT WINAPI DllUnregisterServer(void)
 {
@@ -422,5 +427,7 @@ HRESULT WINAPI DllUnregisterServer(void)
     hr = unregister_coclasses(coclass_list);
     if (SUCCEEDED(hr))
        hr = unregister_interfaces(interface_list);
+    if (SUCCEEDED(hr))
+        hr = STI_DllUnregisterServer();
     return hr;
 }
diff --git a/reactos/dll/win32/sti/sti.c b/reactos/dll/win32/sti/sti.c
new file mode 100644 (file)
index 0000000..974bd06
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2002 Aric Stewart for CodeWeavers
+ * Copyright (C) 2009 Damjan Jovanovic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winerror.h"
+#include "objbase.h"
+#include "sti.h"
+
+#include "sti_private.h"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(sti);
+
+static const WCHAR registeredAppsLaunchPath[] = {
+    'S','O','F','T','W','A','R','E','\\',
+    'M','i','c','r','o','s','o','f','t','\\',
+    'W','i','n','d','o','w','s','\\',
+    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+    'S','t','i','l','l','I','m','a','g','e','\\',
+    'R','e','g','i','s','t','e','r','e','d',' ','A','p','p','l','i','c','a','t','i','o','n','s',0
+};
+
+static inline stillimage *impl_from_StillImageW(IStillImageW *iface)
+{
+    return (stillimage *)((char*)iface - FIELD_OFFSET(stillimage, lpVtbl));
+}
+
+static HRESULT WINAPI stillimagew_QueryInterface(IStillImageW *iface, REFIID riid, void **ppvObject)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    TRACE("(%p %s %p)\n", This, debugstr_guid(riid), ppvObject);
+    return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject);
+}
+
+static ULONG WINAPI stillimagew_AddRef(IStillImageW *iface)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    return IUnknown_AddRef(This->pUnkOuter);
+}
+
+static ULONG WINAPI stillimagew_Release(IStillImageW *iface)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    return IUnknown_Release(This->pUnkOuter);
+}
+
+static HRESULT WINAPI stillimagew_Initialize(IStillImageW *iface, HINSTANCE hinst, DWORD dwVersion)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    TRACE("(%p, %p, 0x%X)\n", This, hinst, dwVersion);
+    return S_OK;
+}
+
+static HRESULT WINAPI stillimagew_GetDeviceList(IStillImageW *iface, DWORD dwType, DWORD dwFlags,
+                                                DWORD *pdwItemsReturned, LPVOID *ppBuffer)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %u, 0x%X, %p, %p): stub\n", This, dwType, dwFlags, pdwItemsReturned, ppBuffer);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_GetDeviceInfo(IStillImageW *iface, LPWSTR pwszDeviceName,
+                                                LPVOID *ppBuffer)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %s, %p): stub\n", This, debugstr_w(pwszDeviceName), ppBuffer);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_CreateDevice(IStillImageW *iface, LPWSTR pwszDeviceName, DWORD dwMode,
+                                               PSTIDEVICEW *pDevice, LPUNKNOWN pUnkOuter)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %s, %u, %p, %p): stub\n", This, debugstr_w(pwszDeviceName), dwMode, pDevice, pUnkOuter);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_GetDeviceValue(IStillImageW *iface, LPWSTR pwszDeviceName, LPWSTR pValueName,
+                                                 LPDWORD pType, LPBYTE pData, LPDWORD cbData)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %s, %s, %p, %p, %p): stub\n", This, debugstr_w(pwszDeviceName), debugstr_w(pValueName),
+        pType, pData, cbData);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_SetDeviceValue(IStillImageW *iface, LPWSTR pwszDeviceName, LPWSTR pValueName,
+                                                 DWORD type, LPBYTE pData, DWORD cbData)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %s, %s, %u, %p, %u): stub\n", This, debugstr_w(pwszDeviceName), debugstr_w(pValueName),
+        type, pData, cbData);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_GetSTILaunchInformation(IStillImageW *iface, LPWSTR pwszDeviceName,
+                                                          DWORD *pdwEventCode, LPWSTR pwszEventName)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %p, %p, %p): stub\n", This, pwszDeviceName,
+        pdwEventCode, pwszEventName);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_RegisterLaunchApplication(IStillImageW *iface, LPWSTR pwszAppName,
+                                                            LPWSTR pwszCommandLine)
+{
+    static const WCHAR format[] = {'%','s',' ','%','s',0};
+    static const WCHAR commandLineSuffix[] = {
+        '/','S','t','i','D','e','v','i','c','e',':','%','1',' ',
+        '/','S','t','i','E','v','e','n','t',':','%','2',0};
+    HKEY registeredAppsKey = NULL;
+    DWORD ret;
+    HRESULT hr = S_OK;
+    stillimage *This = impl_from_StillImageW(iface);
+
+    TRACE("(%p, %s, %s)\n", This, debugstr_w(pwszAppName), debugstr_w(pwszCommandLine));
+
+    ret = RegCreateKeyW(HKEY_LOCAL_MACHINE, registeredAppsLaunchPath, &registeredAppsKey);
+    if (ret == ERROR_SUCCESS)
+    {
+        WCHAR *value = HeapAlloc(GetProcessHeap(), 0,
+            (lstrlenW(pwszCommandLine) + 1 + lstrlenW(commandLineSuffix) + 1) * sizeof(WCHAR));
+        if (value)
+        {
+            sprintfW(value, format, pwszCommandLine, commandLineSuffix);
+            ret = RegSetValueExW(registeredAppsKey, pwszAppName, 0,
+                REG_SZ, (BYTE*)value, (lstrlenW(value)+1)*sizeof(WCHAR));
+            if (ret != ERROR_SUCCESS)
+                hr = HRESULT_FROM_WIN32(ret);
+            HeapFree(GetProcessHeap(), 0, value);
+        }
+        else
+            hr = E_OUTOFMEMORY;
+        RegCloseKey(registeredAppsKey);
+    }
+    else
+        hr = HRESULT_FROM_WIN32(ret);
+    return hr;
+}
+
+static HRESULT WINAPI stillimagew_UnregisterLaunchApplication(IStillImageW *iface, LPWSTR pwszAppName)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    HKEY registeredAppsKey = NULL;
+    DWORD ret;
+    HRESULT hr = S_OK;
+
+    TRACE("(%p, %s)\n", This, debugstr_w(pwszAppName));
+
+    ret = RegCreateKeyW(HKEY_LOCAL_MACHINE, registeredAppsLaunchPath, &registeredAppsKey);
+    if (ret == ERROR_SUCCESS)
+    {
+        ret = RegDeleteValueW(registeredAppsKey, pwszAppName);
+        if (ret != ERROR_SUCCESS)
+            hr = HRESULT_FROM_WIN32(ret);
+        RegCloseKey(registeredAppsKey);
+    }
+    else
+        hr = HRESULT_FROM_WIN32(ret);
+    return hr;
+}
+
+static HRESULT WINAPI stillimagew_EnableHwNotifications(IStillImageW *iface, LPCWSTR pwszDeviceName,
+                                                        BOOL bNewState)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %s, %u): stub\n", This, debugstr_w(pwszDeviceName), bNewState);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_GetHwNotificationState(IStillImageW *iface, LPCWSTR pwszDeviceName,
+                                                         BOOL *pbCurrentState)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %s, %p): stub\n", This, debugstr_w(pwszDeviceName), pbCurrentState);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_RefreshDeviceBus(IStillImageW *iface, LPCWSTR pwszDeviceName)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %s): stub\n", This, debugstr_w(pwszDeviceName));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_LaunchApplicationForDevice(IStillImageW *iface, LPWSTR pwszDeviceName,
+                                                             LPWSTR pwszAppName, LPSTINOTIFY pStiNotify)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %s, %s, %p): stub\n", This, debugstr_w(pwszDeviceName), debugstr_w(pwszAppName),
+        pStiNotify);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_SetupDeviceParameters(IStillImageW *iface, PSTI_DEVICE_INFORMATIONW pDevInfo)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %p): stub\n", This, pDevInfo);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI stillimagew_WriteToErrorLog(IStillImageW *iface, DWORD dwMessageType, LPCWSTR pszMessage)
+{
+    stillimage *This = impl_from_StillImageW(iface);
+    FIXME("(%p, %u, %s): stub\n", This, dwMessageType, debugstr_w(pszMessage));
+    return E_NOTIMPL;
+}
+
+static const struct IStillImageWVtbl stillimagew_vtbl =
+{
+    stillimagew_QueryInterface,
+    stillimagew_AddRef,
+    stillimagew_Release,
+    stillimagew_Initialize,
+    stillimagew_GetDeviceList,
+    stillimagew_GetDeviceInfo,
+    stillimagew_CreateDevice,
+    stillimagew_GetDeviceValue,
+    stillimagew_SetDeviceValue,
+    stillimagew_GetSTILaunchInformation,
+    stillimagew_RegisterLaunchApplication,
+    stillimagew_UnregisterLaunchApplication,
+    stillimagew_EnableHwNotifications,
+    stillimagew_GetHwNotificationState,
+    stillimagew_RefreshDeviceBus,
+    stillimagew_LaunchApplicationForDevice,
+    stillimagew_SetupDeviceParameters,
+    stillimagew_WriteToErrorLog
+};
+
+static inline stillimage *impl_from_InternalUnknown(IUnknown *iface)
+{
+    return (stillimage *)((char*)iface - FIELD_OFFSET(stillimage, lpInternalUnkVtbl));
+}
+
+static HRESULT WINAPI Internal_QueryInterface(IUnknown *iface, REFIID riid, void **ppvObject)
+{
+    stillimage *This = impl_from_InternalUnknown(iface);
+
+    TRACE("(%p %s %p)\n", This, debugstr_guid(riid), ppvObject);
+
+    if (IsEqualGUID(riid, &IID_IUnknown))
+        *ppvObject = iface;
+    else if (IsEqualGUID(riid, &IID_IStillImageW))
+        *ppvObject = &This->lpVtbl;
+    else
+    {
+        if (IsEqualGUID(riid, &IID_IStillImageA))
+            FIXME("interface IStillImageA is unsupported on Windows Vista too, please report if it's needed\n");
+        else
+            FIXME("interface %s not implemented\n", debugstr_guid(riid));
+        *ppvObject = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IUnknown_AddRef((IUnknown*) *ppvObject);
+    return S_OK;
+}
+
+static ULONG WINAPI Internal_AddRef(IUnknown *iface)
+{
+    stillimage *This = impl_from_InternalUnknown(iface);
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI Internal_Release(IUnknown *iface)
+{
+    ULONG ref;
+    stillimage *This = impl_from_InternalUnknown(iface);
+
+    ref = InterlockedDecrement(&This->ref);
+    if (ref == 0)
+        HeapFree(GetProcessHeap(), 0, This);
+    return ref;
+}
+
+static const struct IUnknownVtbl internal_unk_vtbl =
+{
+    Internal_QueryInterface,
+    Internal_AddRef,
+    Internal_Release
+};
+
+/******************************************************************************
+ *           StiCreateInstanceA   (STI.@)
+ */
+HRESULT WINAPI StiCreateInstanceA(HINSTANCE hinst, DWORD dwVer, PSTIA *ppSti, LPUNKNOWN pUnkOuter)
+{
+    FIXME("(%p, %u, %p, %p): stub, unimplemented on Windows Vista too, please report if it's needed\n", hinst, dwVer, ppSti, pUnkOuter);
+    return STG_E_UNIMPLEMENTEDFUNCTION;
+}
+
+/******************************************************************************
+ *           StiCreateInstanceW   (STI.@)
+ */
+HRESULT WINAPI StiCreateInstanceW(HINSTANCE hinst, DWORD dwVer, PSTIW *ppSti, LPUNKNOWN pUnkOuter)
+{
+    stillimage *This;
+    HRESULT hr;
+
+    TRACE("(%p, %u, %p, %p)\n", hinst, dwVer, ppSti, pUnkOuter);
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(stillimage));
+    if (This)
+    {
+        This->lpVtbl = &stillimagew_vtbl;
+        This->lpInternalUnkVtbl = &internal_unk_vtbl;
+        if (pUnkOuter)
+            This->pUnkOuter = pUnkOuter;
+        else
+            This->pUnkOuter = (IUnknown*) &This->lpInternalUnkVtbl;
+        This->ref = 1;
+
+        hr = IStillImage_Initialize((IStillImageW*) &This->lpVtbl, hinst, dwVer);
+        if (SUCCEEDED(hr))
+        {
+            if (pUnkOuter)
+                *ppSti = (IStillImageW*) &This->lpInternalUnkVtbl;
+            else
+                *ppSti = (IStillImageW*) &This->lpVtbl;
+        }
+    }
+    else
+        hr = E_OUTOFMEMORY;
+
+    return hr;
+}
index 592c5f1..edce67a 100644 (file)
@@ -8,11 +8,29 @@
        <include base="ReactOS">include/reactos/wine</include>
        <redefine name="_WIN32_WINNT">0x600</redefine>
        <define name="__WINESRC__" />
+       <define name="ENTRY_PREFIX">STI_</define>
+       <define name="PROXY_DELEGATION" />
+       <define name="REGISTER_PROXY_DLL" />
+
        <file>regsvr.c</file>
+       <file>sti.c</file>
        <file>sti_main.c</file>
+       <file>sti_wia.idl</file>
        <library>wine</library>
-       <library>advapi32</library>
+       <library>sti_proxy</library>
        <library>ole32</library>
+       <library>oleaut32</library>
+       <library>rpcrt4</library>
+       <library>advapi32</library>
+       <library>pseh</library>
+       <library>uuid</library>
        <library>ntdll</library>
 </module>
+<module name="sti_proxy" type="rpcproxy" allowwarnings="true">
+       <define name="__WINESRC__" />
+       <define name="ENTRY_PREFIX">STI_</define>
+       <define name="REGISTER_PROXY_DLL"/>
+       <define name="PROXY_DELEGATION" />
+       <file>sti_wia.idl</file>
+</module>
 </group>
index 186f382..300e7fa 100644 (file)
@@ -1,7 +1,7 @@
-@ stub DllCanUnloadNow
-@ stub DllGetClassObject
+@ stdcall -private DllCanUnloadNow()
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
 @ stdcall -private DllRegisterServer()
 @ stdcall -private DllUnregisterServer()
-@ stdcall StiCreateInstance(ptr long ptr ptr)
+@ stdcall StiCreateInstance(ptr long ptr ptr) StiCreateInstanceW
 @ stdcall StiCreateInstanceA(ptr long ptr ptr)
 @ stdcall StiCreateInstanceW(ptr long ptr ptr)
index 1d4e6ad..711c17f 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2002 Aric Stewart for CodeWeavers
+ * Copyright (C) 2009 Damjan Jovanovic
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 
 #include <stdarg.h>
 
+#define COBJMACROS
+
 #include "windef.h"
 #include "winbase.h"
 #include "winreg.h"
 #include "winerror.h"
+#include "objbase.h"
+#include "sti.h"
 
-/******************************************************************************
- *           StiCreateInstance   (STI.@)
- */
-HRESULT WINAPI StiCreateInstance( HINSTANCE a, DWORD b, LPVOID c, LPVOID d)
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(sti);
+
+extern HRESULT WINAPI STI_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC_HIDDEN;
+extern BOOL WINAPI STI_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN;
+
+typedef HRESULT (*fnCreateInstance)(REFIID riid, IUnknown *pUnkOuter, LPVOID *ppObj);
+
+typedef struct
+{
+    const struct IClassFactoryVtbl *vtbl;
+    fnCreateInstance pfnCreateInstance;
+} sti_cf;
+
+static inline sti_cf *impl_from_IClassFactory( IClassFactory *iface )
+{
+    return (sti_cf *)((char *)iface - FIELD_OFFSET( sti_cf, vtbl ));
+}
+
+static HRESULT sti_create( REFIID riid, IUnknown *pUnkOuter, LPVOID *ppObj )
+{
+    if (pUnkOuter != NULL && !IsEqualIID(riid, &IID_IUnknown))
+        return CLASS_E_NOAGGREGATION;
+
+    if (IsEqualGUID(riid, &IID_IUnknown))
+        return StiCreateInstanceW(GetCurrentProcess(), STI_VERSION_REAL | STI_VERSION_FLAG_UNICODE, (PSTIW*) ppObj, pUnkOuter);
+    else if (IsEqualGUID(riid, &IID_IStillImageW))
+        return StiCreateInstanceW(GetCurrentProcess(), STI_VERSION_REAL | STI_VERSION_FLAG_UNICODE, (PSTIW*) ppObj, NULL);
+    else if (IsEqualGUID(riid, &IID_IStillImageA))
+        return StiCreateInstanceA(GetCurrentProcess(), STI_VERSION_REAL, (PSTIA*) ppObj, NULL);
+    else
+    {
+        FIXME("no interface %s\n", debugstr_guid(riid));
+        return E_NOINTERFACE;
+    }
+}
+
+static HRESULT WINAPI sti_cf_QueryInterface( IClassFactory *iface, REFIID riid, LPVOID *ppobj )
+{
+    if (IsEqualGUID(riid, &IID_IUnknown) ||
+        IsEqualGUID(riid, &IID_IClassFactory))
+    {
+        IClassFactory_AddRef( iface );
+        *ppobj = iface;
+        return S_OK;
+    }
+    FIXME("interface %s not implemented\n", debugstr_guid(riid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI sti_cf_AddRef( IClassFactory *iface )
+{
+    return 2;
+}
+
+static ULONG WINAPI sti_cf_Release( IClassFactory *iface )
 {
-    return STG_E_UNIMPLEMENTEDFUNCTION;
+    return 1;
+}
+
+static HRESULT WINAPI sti_cf_CreateInstance( IClassFactory *iface, LPUNKNOWN pOuter,
+                                             REFIID riid, LPVOID *ppobj )
+{
+    sti_cf *This = impl_from_IClassFactory( iface );
+    HRESULT r;
+    IUnknown *punk;
+
+    TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj);
+
+    *ppobj = NULL;
+
+    r = This->pfnCreateInstance( riid, pOuter, (LPVOID *)&punk );
+    if (FAILED(r))
+        return r;
+
+    r = IUnknown_QueryInterface( punk, riid, ppobj );
+    if (FAILED(r))
+        return r;
+
+    IUnknown_Release( punk );
+    return r;
+}
+
+static HRESULT WINAPI sti_cf_LockServer( IClassFactory *iface, BOOL dolock )
+{
+    FIXME("(%p)->(%d)\n", iface, dolock);
+    return S_OK;
+}
+
+static const struct IClassFactoryVtbl sti_cf_vtbl =
+{
+    sti_cf_QueryInterface,
+    sti_cf_AddRef,
+    sti_cf_Release,
+    sti_cf_CreateInstance,
+    sti_cf_LockServer
+};
+
+static sti_cf the_sti_cf = { &sti_cf_vtbl, sti_create };
+
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    TRACE("(0x%p, %d, %p)\n",hInstDLL,fdwReason,lpvReserved);
+
+    if (fdwReason == DLL_WINE_PREATTACH)
+        return FALSE;
+    return STI_DllMain(hInstDLL, fdwReason, lpvReserved);
 }
 
 /******************************************************************************
- *           StiCreateInstanceA   (STI.@)
+ *           DllGetClassObject   (STI.@)
  */
-HRESULT WINAPI StiCreateInstanceA( HINSTANCE a, DWORD b, LPVOID c, LPVOID d)
+HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID iid, LPVOID *ppv )
 {
-    return STG_E_UNIMPLEMENTEDFUNCTION;
+    IClassFactory *cf = NULL;
+
+    TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
+
+    if (IsEqualGUID( rclsid, &CLSID_Sti ))
+    {
+       cf = (IClassFactory *)&the_sti_cf.vtbl;
+    }
+
+    if (cf)
+        return IClassFactory_QueryInterface( cf, iid, ppv );
+    return STI_DllGetClassObject( rclsid, iid, ppv );
 }
 
 /******************************************************************************
- *           StiCreateInstanceW   (STI.@)
+ *           DllCanUnloadNow   (STI.@)
  */
-HRESULT WINAPI StiCreateInstanceW( HINSTANCE a, DWORD b, LPVOID c, LPVOID d)
+HRESULT WINAPI DllCanUnloadNow( void )
 {
-    return STG_E_UNIMPLEMENTEDFUNCTION;
+    return S_FALSE;
 }
diff --git a/reactos/dll/win32/sti/sti_private.h b/reactos/dll/win32/sti/sti_private.h
new file mode 100644 (file)
index 0000000..b5e106b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * STI private definitions
+ *
+ * Copyright 2009 Damjan Jovanovic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __STI_PRIVATE__
+#define __STI_PRIVATE__
+
+typedef struct _stillimage
+{
+    const struct IStillImageWVtbl *lpVtbl;
+    const struct IUnknownVtbl *lpInternalUnkVtbl;
+    IUnknown *pUnkOuter;
+    LONG ref;
+} stillimage;
+
+#endif /* __STI_PRIVATE__ */
diff --git a/reactos/dll/win32/sti/sti_wia.idl b/reactos/dll/win32/sti/sti_wia.idl
new file mode 100644 (file)
index 0000000..aaac943
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009 Damjan Jovanovic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wia_lh.idl"
index 07d6fc2..29b8532 100644 (file)
@@ -155,7 +155,7 @@ HWND get_notif_hwnd(void)
             NULL
         };
 
-        wndclass.hInstance = URLMON_hInstance;
+        wndclass.hInstance = hProxyDll;
 
         wnd_class = RegisterClassExW(&wndclass);
         if (!wnd_class && GetLastError() == ERROR_CLASS_ALREADY_EXISTS)
@@ -164,7 +164,7 @@ HWND get_notif_hwnd(void)
 
     tls_data->notif_hwnd = CreateWindowExW(0, wszURLMonikerNotificationWindow,
             wszURLMonikerNotificationWindow, 0, 0, 0, 0, 0, HWND_MESSAGE,
-            NULL, URLMON_hInstance, NULL);
+            NULL, hProxyDll, NULL);
     if(tls_data->notif_hwnd)
         tls_data->notif_hwnd_cnt++;
 
index 9e27825..6e417ac 100644 (file)
@@ -560,7 +560,7 @@ static HRESULT register_inf(BOOL doregister)
     hAdvpack = LoadLibraryW(wszAdvpack);
     pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
 
-    hres = pRegInstall(URLMON_hInstance, doregister ? "RegisterDll" : "UnregisterDll", &strtable);
+    hres = pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", &strtable);
 
     for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++)
         heap_free(pse[i].pszValue);
index 272884e..edaad42 100644 (file)
@@ -34,7 +34,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
 LONG URLMON_refCount = 0;
 
-HINSTANCE URLMON_hInstance = 0;
 static HMODULE hCabinet = NULL;
 static DWORD urlmon_tls = TLS_OUT_OF_INDEXES;
 
@@ -144,9 +143,10 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
 {
     TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
 
+    URLMON_DllMain( hinstDLL, fdwReason, fImpLoad );
+
     switch(fdwReason) {
     case DLL_PROCESS_ATTACH:
-        URLMON_hInstance = hinstDLL;
         init_session(TRUE);
         break;
 
index 8db786b..071af8d 100644 (file)
@@ -36,7 +36,7 @@
 #include "wine/unicode.h"
 #include "wine/list.h"
 
-extern HINSTANCE URLMON_hInstance;
+extern HINSTANCE hProxyDll DECLSPEC_HIDDEN;
 extern HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
 extern HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
 extern HRESULT StdURLMoniker_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
@@ -48,6 +48,7 @@ extern HRESULT GopherProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
 extern HRESULT MkProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
 extern HRESULT MimeFilter_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
 
+extern BOOL WINAPI URLMON_DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI URLMON_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI URLMON_DllRegisterServer(void) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI URLMON_DllUnregisterServer(void) DECLSPEC_HIDDEN;
index 71a0719..d45ba07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009 Piotr Caban for Codeweavers
+ * Copyright 2009 Piotr Caban for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
index b945563..6ff8f04 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009 Piotr Caban for Codeweavers
+ * Copyright 2009 Piotr Caban for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
diff --git a/reactos/dll/win32/usp10/bidi.c b/reactos/dll/win32/usp10/bidi.c
new file mode 100644 (file)
index 0000000..28b5d3e
--- /dev/null
@@ -0,0 +1,893 @@
+/*
+ * Uniscribe BiDirectional handling
+ *
+ * Copyright 2003 Shachar Shemesh
+ * Copyright 2007 Maarten Lankhorst
+ * Copyright 2010 CodeWeavers, Aric Stewart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Code derived from the modified reference implementation
+ * that was found in revision 17 of http://unicode.org/reports/tr9/
+ * "Unicode Standard Annex #9: THE BIDIRECTIONAL ALGORITHM"
+ *
+ * -- Copyright (C) 1999-2005, ASMUS, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of the Unicode data files and any associated documentation (the
+ * "Data Files") or Unicode software and any associated documentation (the
+ * "Software") to deal in the Data Files or Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, and/or sell copies of the Data Files or Software,
+ * and to permit persons to whom the Data Files or Software are furnished
+ * to do so, provided that (a) the above copyright notice(s) and this
+ * permission notice appear with all copies of the Data Files or Software,
+ * (b) both the above copyright notice(s) and this permission notice appear
+ * in associated documentation, and (c) there is clear notice in each
+ * modified Data File or in the Software as well as in the documentation
+ * associated with the Data File(s) or Software that the data or software
+ * has been modified.
+ */
+
+#include "config.h"
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winnls.h"
+#include "usp10.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+#include "usp10_internal.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(bidi);
+
+#define ASSERT(x) do { if (!(x)) FIXME("assert failed: %s\n", #x); } while(0)
+#define MAX_LEVEL 61
+
+/* HELPER FUNCTIONS AND DECLARATIONS */
+
+/*------------------------------------------------------------------------
+    Bidirectional Character Types
+
+    as defined by the Unicode Bidirectional Algorithm Table 3-7.
+
+    Note:
+
+      The list of bidirectional character types here is not grouped the
+      same way as the table 3-7, since the numberic values for the types
+      are chosen to keep the state and action tables compact.
+------------------------------------------------------------------------*/
+enum directions
+{
+    /* input types */
+             /* ON MUST be zero, code relies on ON = N = 0 */
+    ON = 0,  /* Other Neutral */
+    L,       /* Left Letter */
+    R,       /* Right Letter */
+    AN,      /* Arabic Number */
+    EN,      /* European Number */
+    AL,      /* Arabic Letter (Right-to-left) */
+    NSM,     /* Non-spacing Mark */
+    CS,      /* Common Separator */
+    ES,      /* European Separator */
+    ET,      /* European Terminator (post/prefix e.g. $ and %) */
+
+    /* resolved types */
+    BN,      /* Boundary neutral (type of RLE etc after explicit levels) */
+
+    /* input types, */
+    S,       /* Segment Separator (TAB)        // used only in L1 */
+    WS,      /* White space                    // used only in L1 */
+    B,       /* Paragraph Separator (aka as PS) */
+
+    /* types for explicit controls */
+    RLO,     /* these are used only in X1-X9 */
+    RLE,
+    LRO,
+    LRE,
+    PDF,
+
+    /* resolved types, also resolved directions */
+    N = ON,  /* alias, where ON, WS and S are treated the same */
+};
+
+/* HELPER FUNCTIONS */
+/* the character type contains the C1_* flags in the low 12 bits */
+/* and the C2_* type in the high 4 bits */
+static __inline unsigned short get_char_typeW( WCHAR ch )
+{
+    WORD CharType;
+    GetStringTypeW(CT_CTYPE1, &ch, 1, &CharType);
+    return CharType;
+}
+
+/* Convert the libwine information to the direction enum */
+static void classify(LPCWSTR lpString, WORD *chartype, DWORD uCount, const SCRIPT_CONTROL *c)
+{
+    static const enum directions dir_map[16] =
+    {
+        L,  /* unassigned defaults to L */
+        L,
+        R,
+        EN,
+        ES,
+        ET,
+        AN,
+        CS,
+        B,
+        S,
+        WS,
+        ON,
+        AL,
+        NSM,
+        BN,
+        PDF  /* also LRE, LRO, RLE, RLO */
+    };
+
+    unsigned i;
+
+    for (i = 0; i < uCount; ++i)
+    {
+        chartype[i] = dir_map[get_char_typeW(lpString[i]) >> 12];
+        switch (chartype[i])
+        {
+        case ES:
+            if (!c->fLegacyBidiClass) break;
+            switch (lpString[i])
+            {
+            case '-':
+            case '+': chartype[i] = N; break;
+            case '/': chartype[i] = CS; break;
+            }
+            break;
+        case PDF:
+            switch (lpString[i])
+            {
+            case 0x202A: chartype[i] = LRE; break;
+            case 0x202B: chartype[i] = RLE; break;
+            case 0x202C: chartype[i] = PDF; break;
+            case 0x202D: chartype[i] = LRO; break;
+            case 0x202E: chartype[i] = RLO; break;
+            }
+            break;
+        }
+    }
+}
+
+/* Set a run of cval values at locations all prior to, but not including */
+/* iStart, to the new value nval. */
+static void SetDeferredRun(WORD *pval, int cval, int iStart, int nval)
+{
+    int i = iStart - 1;
+    for (; i >= iStart - cval; i--)
+    {
+        pval[i] = nval;
+    }
+}
+
+/* RESOLVE EXPLICIT */
+
+static WORD GreaterEven(int i)
+{
+    return odd(i) ? i + 1 : i + 2;
+}
+
+static WORD GreaterOdd(int i)
+{
+    return odd(i) ? i + 2 : i + 1;
+}
+
+static WORD EmbeddingDirection(int level)
+{
+    return odd(level) ? R : L;
+}
+
+/*------------------------------------------------------------------------
+    Function: resolveExplicit
+
+    Recursively resolves explicit embedding levels and overrides.
+    Implements rules X1-X9, of the Unicode Bidirectional Algorithm.
+
+    Input: Base embedding level and direction
+           Character count
+
+    Output: Array of embedding levels
+
+    In/Out: Array of direction classes
+
+
+    Note: The function uses two simple counters to keep track of
+          matching explicit codes and PDF. Use the default argument for
+          the outermost call. The nesting counter counts the recursion
+          depth and not the embedding level.
+------------------------------------------------------------------------*/
+
+static int resolveExplicit(int level, int dir, WORD *pcls, WORD *plevel, int cch, int nNest)
+{
+    /* always called with a valid nesting level
+       nesting levels are != embedding levels */
+    int nLastValid = nNest;
+    int ich = 0;
+
+    /* check input values */
+    ASSERT(nNest >= 0 && level >= 0 && level <= MAX_LEVEL);
+
+    /* process the text */
+    for (; ich < cch; ich++)
+    {
+        WORD cls = pcls[ich];
+        switch (cls)
+        {
+        case LRO:
+        case LRE:
+            nNest++;
+            if (GreaterEven(level) <= MAX_LEVEL - (cls == LRO ? 2 : 0))
+            {
+                plevel[ich] = GreaterEven(level);
+                pcls[ich] = BN;
+                ich += resolveExplicit(plevel[ich], (cls == LRE ? N : L),
+                            &pcls[ich+1], &plevel[ich+1],
+                             cch - (ich+1), nNest);
+                nNest--;
+                continue;
+            }
+            cls = pcls[ich] = BN;
+            break;
+
+        case RLO:
+        case RLE:
+            nNest++;
+            if (GreaterOdd(level) <= MAX_LEVEL - (cls == RLO ? 2 : 0))
+            {
+                plevel[ich] = GreaterOdd(level);
+                pcls[ich] = BN;
+                ich += resolveExplicit(plevel[ich], (cls == RLE ? N : R),
+                                &pcls[ich+1], &plevel[ich+1],
+                                 cch - (ich+1), nNest);
+                nNest--;
+                continue;
+            }
+            cls = pcls[ich] = BN;
+            break;
+
+        case PDF:
+            cls = pcls[ich] = BN;
+            if (nNest)
+            {
+                if (nLastValid < nNest)
+                {
+                    nNest--;
+                }
+                else
+                {
+                    cch = ich; /* break the loop, but complete body */
+                }
+            }
+        }
+
+        /* Apply the override */
+        if (dir != N)
+        {
+            cls = dir;
+        }
+        plevel[ich] = level;
+        if (pcls[ich] != BN)
+            pcls[ich] = cls;
+    }
+
+    return ich;
+}
+
+/* RESOLVE WEAK TYPES */
+
+enum states /* possible states */
+{
+    xa,        /*  arabic letter */
+    xr,        /*  right letter */
+    xl,        /*  left letter */
+
+    ao,        /*  arabic lett. foll by ON */
+    ro,        /*  right lett. foll by ON */
+    lo,        /*  left lett. foll by ON */
+
+    rt,        /*  ET following R */
+    lt,        /*  ET following L */
+
+    cn,        /*  EN, AN following AL */
+    ra,        /*  arabic number foll R */
+    re,        /*  european number foll R */
+    la,        /*  arabic number foll L */
+    le,        /*  european number foll L */
+
+    ac,        /*  CS following cn */
+    rc,        /*  CS following ra */
+    rs,        /*  CS,ES following re */
+    lc,        /*  CS following la */
+    ls,        /*  CS,ES following le */
+
+    ret,    /*  ET following re */
+    let,    /*  ET following le */
+} ;
+
+static const int stateWeak[][10] =
+{
+    /*    N,  L,  R, AN, EN, AL,NSM, CS, ES, ET */
+/*xa*/ { ao, xl, xr, cn, cn, xa, xa, ao, ao, ao }, /* arabic letter          */
+/*xr*/ { ro, xl, xr, ra, re, xa, xr, ro, ro, rt }, /* right letter           */
+/*xl*/ { lo, xl, xr, la, le, xa, xl, lo, lo, lt }, /* left letter            */
+
+/*ao*/ { ao, xl, xr, cn, cn, xa, ao, ao, ao, ao }, /* arabic lett. foll by ON*/
+/*ro*/ { ro, xl, xr, ra, re, xa, ro, ro, ro, rt }, /* right lett. foll by ON */
+/*lo*/ { lo, xl, xr, la, le, xa, lo, lo, lo, lt }, /* left lett. foll by ON  */
+
+/*rt*/ { ro, xl, xr, ra, re, xa, rt, ro, ro, rt }, /* ET following R         */
+/*lt*/ { lo, xl, xr, la, le, xa, lt, lo, lo, lt }, /* ET following L         */
+
+/*cn*/ { ao, xl, xr, cn, cn, xa, cn, ac, ao, ao }, /* EN, AN following AL    */
+/*ra*/ { ro, xl, xr, ra, re, xa, ra, rc, ro, rt }, /* arabic number foll R   */
+/*re*/ { ro, xl, xr, ra, re, xa, re, rs, rs,ret }, /* european number foll R */
+/*la*/ { lo, xl, xr, la, le, xa, la, lc, lo, lt }, /* arabic number foll L   */
+/*le*/ { lo, xl, xr, la, le, xa, le, ls, ls,let }, /* european number foll L */
+
+/*ac*/ { ao, xl, xr, cn, cn, xa, ao, ao, ao, ao }, /* CS following cn        */
+/*rc*/ { ro, xl, xr, ra, re, xa, ro, ro, ro, rt }, /* CS following ra        */
+/*rs*/ { ro, xl, xr, ra, re, xa, ro, ro, ro, rt }, /* CS,ES following re     */
+/*lc*/ { lo, xl, xr, la, le, xa, lo, lo, lo, lt }, /* CS following la        */
+/*ls*/ { lo, xl, xr, la, le, xa, lo, lo, lo, lt }, /* CS,ES following le     */
+
+/*ret*/{ ro, xl, xr, ra, re, xa,ret, ro, ro,ret }, /* ET following re        */
+/*let*/{ lo, xl, xr, la, le, xa,let, lo, lo,let }, /* ET following le        */
+};
+
+enum actions /* possible actions */
+{
+    /* primitives */
+    IX = 0x100,                    /* increment */
+    XX = 0xF,                    /* no-op */
+
+    /* actions */
+    xxx = (XX << 4) + XX,        /* no-op */
+    xIx = IX + xxx,                /* increment run */
+    xxN = (XX << 4) + ON,        /* set current to N */
+    xxE = (XX << 4) + EN,        /* set current to EN */
+    xxA = (XX << 4) + AN,        /* set current to AN */
+    xxR = (XX << 4) + R,        /* set current to R */
+    xxL = (XX << 4) + L,        /* set current to L */
+    Nxx = (ON << 4) + 0xF,        /* set run to neutral */
+    Axx = (AN << 4) + 0xF,        /* set run to AN */
+    ExE = (EN << 4) + EN,        /* set run to EN, set current to EN */
+    NIx = (ON << 4) + 0xF + IX, /* set run to N, increment */
+    NxN = (ON << 4) + ON,        /* set run to N, set current to N */
+    NxR = (ON << 4) + R,        /* set run to N, set current to R */
+    NxE = (ON << 4) + EN,        /* set run to N, set current to EN */
+
+    AxA = (AN << 4) + AN,        /* set run to AN, set current to AN */
+    NxL = (ON << 4) + L,        /* set run to N, set current to L */
+    LxL = (L << 4) + L,            /* set run to L, set current to L */
+}  ;
+
+static const int actionWeak[][10] =
+{
+       /*  N,   L,   R,  AN,  EN,  AL, NSM,  CS,  ES,  ET */
+/*xa*/ { xxx, xxx, xxx, xxx, xxA, xxR, xxR, xxN, xxN, xxN }, /* arabic letter           */
+/*xr*/ { xxx, xxx, xxx, xxx, xxE, xxR, xxR, xxN, xxN, xIx }, /* right letter            */
+/*xl*/ { xxx, xxx, xxx, xxx, xxL, xxR, xxL, xxN, xxN, xIx }, /* left letter             */
+
+/*ao*/ { xxx, xxx, xxx, xxx, xxA, xxR, xxN, xxN, xxN, xxN }, /* arabic lett. foll by ON */
+/*ro*/ { xxx, xxx, xxx, xxx, xxE, xxR, xxN, xxN, xxN, xIx }, /* right lett. foll by ON  */
+/*lo*/ { xxx, xxx, xxx, xxx, xxL, xxR, xxN, xxN, xxN, xIx }, /* left lett. foll by ON   */
+
+/*rt*/ { Nxx, Nxx, Nxx, Nxx, ExE, NxR, xIx, NxN, NxN, xIx }, /* ET following R         */
+/*lt*/ { Nxx, Nxx, Nxx, Nxx, LxL, NxR, xIx, NxN, NxN, xIx }, /* ET following L         */
+
+/*cn*/ { xxx, xxx, xxx, xxx, xxA, xxR, xxA, xIx, xxN, xxN }, /* EN, AN following  AL    */
+/*ra*/ { xxx, xxx, xxx, xxx, xxE, xxR, xxA, xIx, xxN, xIx }, /* arabic number foll R   */
+/*re*/ { xxx, xxx, xxx, xxx, xxE, xxR, xxE, xIx, xIx, xxE }, /* european number foll R */
+/*la*/ { xxx, xxx, xxx, xxx, xxL, xxR, xxA, xIx, xxN, xIx }, /* arabic number foll L   */
+/*le*/ { xxx, xxx, xxx, xxx, xxL, xxR, xxL, xIx, xIx, xxL }, /* european number foll L */
+
+/*ac*/ { Nxx, Nxx, Nxx, Axx, AxA, NxR, NxN, NxN, NxN, NxN }, /* CS following cn         */
+/*rc*/ { Nxx, Nxx, Nxx, Axx, NxE, NxR, NxN, NxN, NxN, NIx }, /* CS following ra         */
+/*rs*/ { Nxx, Nxx, Nxx, Nxx, ExE, NxR, NxN, NxN, NxN, NIx }, /* CS,ES following re      */
+/*lc*/ { Nxx, Nxx, Nxx, Axx, NxL, NxR, NxN, NxN, NxN, NIx }, /* CS following la         */
+/*ls*/ { Nxx, Nxx, Nxx, Nxx, LxL, NxR, NxN, NxN, NxN, NIx }, /* CS,ES following le      */
+
+/*ret*/{ xxx, xxx, xxx, xxx, xxE, xxR, xxE, xxN, xxN, xxE }, /* ET following re            */
+/*let*/{ xxx, xxx, xxx, xxx, xxL, xxR, xxL, xxN, xxN, xxL }, /* ET following le            */
+};
+
+static int GetDeferredType(int action)
+{
+    return (action >> 4) & 0xF;
+}
+
+static int GetResolvedType(int action)
+{
+    return action & 0xF;
+}
+
+/* Note on action table:
+
+  States can be of two kinds:
+     - Immediate Resolution State, where each input token
+       is resolved as soon as it is seen. These states have
+       only single action codes (xxN) or the no-op (xxx)
+       for static input tokens.
+     - Deferred Resolution State, where input tokens either
+       either extend the run (xIx) or resolve its Type (e.g. Nxx).
+
+   Input classes are of three kinds
+     - Static Input Token, where the class of the token remains
+       unchanged on output (AN, L, N, R)
+     - Replaced Input Token, where the class of the token is
+       always replaced on output (AL, BN, NSM, CS, ES, ET)
+     - Conditional Input Token, where the class of the token is
+       changed on output in some, but not all, cases (EN)
+
+     Where tokens are subject to change, a double action
+     (e.g. NxA, or NxN) is _required_ after deferred states,
+     resolving both the deferred state and changing the current token.
+*/
+
+/*------------------------------------------------------------------------
+    Function: resolveWeak
+
+    Resolves the directionality of numeric and other weak character types
+
+    Implements rules X10 and W1-W6 of the Unicode Bidirectional Algorithm.
+
+    Input: Array of embedding levels
+           Character count
+
+    In/Out: Array of directional classes
+
+    Note: On input only these directional classes are expected
+          AL, HL, R, L,  ON, BN, NSM, AN, EN, ES, ET, CS,
+------------------------------------------------------------------------*/
+static void resolveWeak(int baselevel, WORD *pcls, WORD *plevel, int cch)
+{
+    int state = odd(baselevel) ? xr : xl;
+    int cls;
+
+    int level = baselevel;
+    int action, clsRun, clsNew;
+    int cchRun = 0;
+    int ich = 0;
+
+    for (; ich < cch; ich++)
+    {
+        /* ignore boundary neutrals */
+        if (pcls[ich] == BN)
+        {
+            /* must flatten levels unless at a level change; */
+            plevel[ich] = level;
+
+            /* lookahead for level changes */
+            if (ich + 1 == cch && level != baselevel)
+            {
+                /* have to fixup last BN before end of the loop, since
+                 * its fix-upped value will be needed below the assert */
+                pcls[ich] = EmbeddingDirection(level);
+            }
+            else if (ich + 1 < cch && level != plevel[ich+1] && pcls[ich+1] != BN)
+            {
+                /* fixup LAST BN in front / after a level run to make
+                 * it act like the SOR/EOR in rule X10 */
+                int newlevel = plevel[ich+1];
+                if (level > newlevel) {
+                    newlevel = level;
+                }
+                plevel[ich] = newlevel;
+
+                /* must match assigned level */
+                pcls[ich] = EmbeddingDirection(newlevel);
+                level = plevel[ich+1];
+            }
+            else
+            {
+                /* don't interrupt runs */
+                if (cchRun)
+                {
+                    cchRun++;
+                }
+                continue;
+            }
+        }
+
+        ASSERT(pcls[ich] <= BN);
+        cls = pcls[ich];
+
+        action = actionWeak[state][cls];
+
+        /* resolve the directionality for deferred runs */
+        clsRun = GetDeferredType(action);
+        if (clsRun != XX)
+        {
+            SetDeferredRun(pcls, cchRun, ich, clsRun);
+            cchRun = 0;
+        }
+
+        /* resolve the directionality class at the current location */
+        clsNew = GetResolvedType(action);
+        if (clsNew != XX)
+            pcls[ich] = clsNew;
+
+        /* increment a deferred run */
+        if (IX & action)
+            cchRun++;
+
+        state = stateWeak[state][cls];
+    }
+
+    /* resolve any deferred runs
+     * use the direction of the current level to emulate PDF */
+    cls = EmbeddingDirection(level);
+
+    /* resolve the directionality for deferred runs */
+    clsRun = GetDeferredType(actionWeak[state][cls]);
+    if (clsRun != XX)
+        SetDeferredRun(pcls, cchRun, ich, clsRun);
+}
+
+/* RESOLVE NEUTRAL TYPES */
+
+/* action values */
+enum neutralactions
+{
+    /* action to resolve previous input */
+    nL = L,         /* resolve EN to L */
+    En = 3 << 4,    /* resolve neutrals run to embedding level direction */
+    Rn = R << 4,    /* resolve neutrals run to strong right */
+    Ln = L << 4,    /* resolved neutrals run to strong left */
+    In = (1<<8),    /* increment count of deferred neutrals */
+    LnL = (1<<4)+L, /* set run and EN to L */
+};
+
+static int GetDeferredNeutrals(int action, int level)
+{
+    action = (action >> 4) & 0xF;
+    if (action == (En >> 4))
+        return EmbeddingDirection(level);
+    else
+        return action;
+}
+
+static int GetResolvedNeutrals(int action)
+{
+    action = action & 0xF;
+    if (action == In)
+        return 0;
+    else
+        return action;
+}
+
+/* state values */
+enum resolvestates
+{
+    /* new temporary class */
+    r,  /* R and characters resolved to R */
+    l,  /* L and characters resolved to L */
+    rn, /* N preceded by right */
+    ln, /* N preceded by left */
+    a,  /* AN preceded by left (the abbreviation 'la' is used up above) */
+    na, /* N preceded by a */
+} ;
+
+
+/*------------------------------------------------------------------------
+  Notes:
+
+  By rule W7, whenever a EN is 'dominated' by an L (including start of
+  run with embedding direction = L) it is resolved to, and further treated
+  as L.
+
+  This leads to the need for 'a' and 'na' states.
+------------------------------------------------------------------------*/
+
+static const int actionNeutrals[][5] =
+{
+/*   N,  L,  R,  AN, EN = cls */
+  { In,  0,  0,  0,  0 }, /* r    right */
+  { In,  0,  0,  0,  L }, /* l    left */
+
+  { In, En, Rn, Rn, Rn }, /* rn   N preceded by right */
+  { In, Ln, En, En, LnL}, /* ln   N preceded by left */
+
+  { In,  0,  0,  0,  L }, /* a   AN preceded by left */
+  { In, En, Rn, Rn, En }, /* na   N  preceded by a */
+} ;
+
+static const int stateNeutrals[][5] =
+{
+/*   N, L,  R, AN, EN */
+  { rn, l,  r,  r,  r }, /* r   right */
+  { ln, l,  r,  a,  l }, /* l   left */
+
+  { rn, l,  r,  r,  r }, /* rn  N preceded by right */
+  { ln, l,  r,  a,  l }, /* ln  N preceded by left */
+
+  { na, l,  r,  a,  l }, /* a  AN preceded by left */
+  { na, l,  r,  a,  l }, /* na  N preceded by la */
+} ;
+
+/*------------------------------------------------------------------------
+    Function: resolveNeutrals
+
+    Resolves the directionality of neutral character types.
+
+    Implements rules W7, N1 and N2 of the Unicode Bidi Algorithm.
+
+    Input: Array of embedding levels
+           Character count
+           Baselevel
+
+    In/Out: Array of directional classes
+
+    Note: On input only these directional classes are expected
+          R,  L,  N, AN, EN and BN
+
+          W8 resolves a number of ENs to L
+------------------------------------------------------------------------*/
+static void resolveNeutrals(int baselevel, WORD *pcls, const WORD *plevel, int cch)
+{
+    /* the state at the start of text depends on the base level */
+    int state = odd(baselevel) ? r : l;
+    int cls;
+
+    int cchRun = 0;
+    int level = baselevel;
+
+    int action, clsRun, clsNew;
+    int ich = 0;
+    for (; ich < cch; ich++)
+    {
+        /* ignore boundary neutrals */
+        if (pcls[ich] == BN)
+        {
+            /* include in the count for a deferred run */
+            if (cchRun)
+                cchRun++;
+
+            /* skip any further processing */
+            continue;
+        }
+
+        ASSERT(pcls[ich] < 5); /* "Only N, L, R,  AN, EN are allowed" */
+        cls = pcls[ich];
+
+        action = actionNeutrals[state][cls];
+
+        /* resolve the directionality for deferred runs */
+        clsRun = GetDeferredNeutrals(action, level);
+        if (clsRun != N)
+        {
+            SetDeferredRun(pcls, cchRun, ich, clsRun);
+            cchRun = 0;
+        }
+
+        /* resolve the directionality class at the current location */
+        clsNew = GetResolvedNeutrals(action);
+        if (clsNew != N)
+            pcls[ich] = clsNew;
+
+        if (In & action)
+            cchRun++;
+
+        state = stateNeutrals[state][cls];
+        level = plevel[ich];
+    }
+
+    /* resolve any deferred runs */
+    cls = EmbeddingDirection(level);    /* eor has type of current level */
+
+    /* resolve the directionality for deferred runs */
+    clsRun = GetDeferredNeutrals(actionNeutrals[state][cls], level);
+    if (clsRun != N)
+        SetDeferredRun(pcls, cchRun, ich, clsRun);
+}
+
+/* RESOLVE IMPLICIT */
+
+/*------------------------------------------------------------------------
+    Function: resolveImplicit
+
+    Recursively resolves implicit embedding levels.
+    Implements rules I1 and I2 of the Unicode Bidirectional Algorithm.
+
+    Input: Array of direction classes
+           Character count
+           Base level
+
+    In/Out: Array of embedding levels
+
+    Note: levels may exceed 15 on output.
+          Accepted subset of direction classes
+          R, L, AN, EN
+------------------------------------------------------------------------*/
+static const WORD addLevel[][4] =
+{
+          /* L,  R, AN, EN */
+/* even */ { 0,  1,  2,  2, },
+/* odd  */ { 1,  0,  1,  1, }
+
+};
+
+static void resolveImplicit(const WORD * pcls, WORD *plevel, int cch)
+{
+    int ich = 0;
+    for (; ich < cch; ich++)
+    {
+        /* cannot resolve bn here, since some bn were resolved to strong
+         * types in resolveWeak. To remove these we need the original
+         * types, which are available again in resolveWhiteSpace */
+        if (pcls[ich] == BN)
+        {
+            continue;
+        }
+        ASSERT(pcls[ich] > 0); /* "No Neutrals allowed to survive here." */
+        ASSERT(pcls[ich] < 5); /* "Out of range." */
+        plevel[ich] += addLevel[odd(plevel[ich])][pcls[ich] - 1];
+    }
+}
+
+/*************************************************************
+ *    BIDI_DeterminLevels
+ */
+BOOL BIDI_DetermineLevels(
+                LPCWSTR lpString,       /* [in] The string for which information is to be returned */
+                INT uCount,     /* [in] Number of WCHARs in string. */
+                const SCRIPT_STATE *s,
+                const SCRIPT_CONTROL *c,
+                WORD *lpOutLevels /* [out] final string levels */
+    )
+{
+    WORD *chartype;
+    unsigned baselevel = 0,j;
+    TRACE("%s, %d", debugstr_wn(lpString, uCount), uCount);
+
+    chartype = HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WORD));
+    if (!chartype)
+    {
+        WARN("Out of memory\n");
+        return FALSE;
+    }
+
+    baselevel = s->uBidiLevel;
+
+    classify(lpString, chartype, uCount, c);
+
+    for (j = 0; j < uCount; ++j)
+        switch(chartype[j])
+        {
+            case B:
+            case S:
+            case WS:
+            case ON: chartype[j] = N;
+            default: continue;
+        }
+
+    /* resolve explicit */
+    resolveExplicit(baselevel, N, chartype, lpOutLevels, uCount, 0);
+
+    /* resolve weak */
+    resolveWeak(baselevel, chartype, lpOutLevels, uCount);
+
+    /* resolve neutrals */
+    resolveNeutrals(baselevel, chartype, lpOutLevels, uCount);
+
+    /* resolveImplicit */
+    resolveImplicit(chartype, lpOutLevels, uCount);
+
+    HeapFree(GetProcessHeap(), 0, chartype);
+    return TRUE;
+}
+
+/* reverse cch indexes */
+static void reverse(int *pidx, int cch)
+{
+    int temp;
+    int ich = 0;
+    for (; ich < --cch; ich++)
+    {
+        temp = pidx[ich];
+        pidx[ich] = pidx[cch];
+        pidx[cch] = temp;
+    }
+}
+
+
+/*------------------------------------------------------------------------
+    Functions: reorder/reorderLevel
+
+    Recursively reorders the display string
+    "From the highest level down, reverse all characters at that level and
+    higher, down to the lowest odd level"
+
+    Implements rule L2 of the Unicode bidi Algorithm.
+
+    Input: Array of embedding levels
+           Character count
+           Flag enabling reversal (set to false by initial caller)
+
+    In/Out: Text to reorder
+
+    Note: levels may exceed 15 resp. 61 on input.
+
+    Rule L3 - reorder combining marks is not implemented here
+    Rule L4 - glyph mirroring is implemented as a display option below
+
+    Note: this should be applied a line at a time
+-------------------------------------------------------------------------*/
+int BIDI_ReorderV2lLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse)
+{
+    int ich = 0;
+
+    /* true as soon as first odd level encountered */
+    fReverse = fReverse || odd(level);
+
+    for (; ich < cch; ich++)
+    {
+        if (plevel[ich] < level)
+        {
+            break;
+        }
+        else if (plevel[ich] > level)
+        {
+            ich += BIDI_ReorderV2lLevel(level + 1, pIndexs + ich, plevel + ich,
+                cch - ich, fReverse) - 1;
+        }
+    }
+    if (fReverse)
+    {
+        reverse(pIndexs, ich);
+    }
+    return ich;
+}
+
+/* Applies the reorder in reverse. Taking an already reordered string and returing the original */
+int BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse)
+{
+    int ich = 0;
+    int newlevel = -1;
+
+    /* true as soon as first odd level encountered */
+    fReverse = fReverse || odd(level);
+
+    for (; ich < cch; ich++)
+    {
+        if (plevel[ich] < level)
+            break;
+        else if (plevel[ich] > level)
+            newlevel = ich;
+    }
+    if (fReverse)
+    {
+        reverse(pIndexs, ich);
+    }
+
+    if (newlevel > 1)
+    {
+        ich = 0;
+        for (; ich < cch; ich++)
+            if (plevel[ich] > level)
+                ich += BIDI_ReorderL2vLevel(level + 1, pIndexs + ich, plevel + ich,
+                cch - ich, fReverse) - 1;
+    }
+
+    return ich;
+}
index cdd6d7b..8595714 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright 2005 Steven Edwards for CodeWeavers
  * Copyright 2006 Hans Leidekker
+ * Copyright 2010 CodeWeavers, Aric Stewart
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -32,6 +33,8 @@
 #include "winnls.h"
 #include "usp10.h"
 
+#include "usp10_internal.h"
+
 #include "wine/debug.h"
 #include "wine/unicode.h"
 
@@ -524,6 +527,7 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem
 
     int   cnt = 0, index = 0;
     int   New_Script = SCRIPT_UNDEFINED;
+    WORD  *levels = NULL;
 
     TRACE("%s,%d,%d,%p,%p,%p,%p\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems, 
           psControl, psState, pItems, pcItems);
@@ -531,6 +535,24 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem
     if (!pwcInChars || !cInChars || !pItems || cMaxItems < 2)
         return E_INVALIDARG;
 
+    if (psState && psControl)
+    {
+        int i;
+        levels = heap_alloc_zero(cInChars * sizeof(WORD));
+        if (!levels)
+            return E_OUTOFMEMORY;
+
+        BIDI_DetermineLevels(pwcInChars, cInChars, psState, psControl, levels);
+        for (i = 0; i < cInChars; i++)
+            if (levels[i]!=levels[0])
+                break;
+        if (i >= cInChars)
+        {
+            heap_free(levels);
+            levels = NULL;
+        }
+    }
+
     pItems[index].iCharPos = 0;
     memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS));
 
@@ -549,15 +571,29 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem
     if  (pwcInChars[cnt] >= Latin_start && pwcInChars[cnt] <= Latin_stop)
         pItems[index].a.eScript = Script_Latin;
 
-    if  (pItems[index].a.eScript  == Script_Arabic)
+    if (levels)
+    {
+        pItems[index].a.fRTL = odd(levels[cnt]);
+        pItems[index].a.fLayoutRTL = odd(levels[cnt]);
+        pItems[index].a.s.uBidiLevel = levels[cnt];
+    }
+    else if (pItems[index].a.eScript  == Script_Arabic)
+    {
         pItems[index].a.s.uBidiLevel = 1;
+        pItems[index].a.fRTL = 1;
+        pItems[index].a.fLayoutRTL = 1;
+    }
+
 
-    TRACE("New_Script=%d, eScript=%d index=%d cnt=%d iCharPos=%d\n",
-          New_Script, pItems[index].a.eScript, index, cnt,
+    TRACE("New_Level=%i New_Script=%d, eScript=%d index=%d cnt=%d iCharPos=%d\n",
+          levels?levels[cnt]:-1, New_Script, pItems[index].a.eScript, index, cnt,
           pItems[index].iCharPos);
 
     for (cnt=1; cnt < cInChars; cnt++)
     {
+        if (levels && (levels[cnt] == pItems[index].a.s.uBidiLevel))
+            continue;
+
         if  (pwcInChars[cnt] == '\r')
             New_Script = Script_CR;
         else
@@ -578,9 +614,9 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem
         else
             New_Script = SCRIPT_UNDEFINED;
 
-        if  (New_Script != pItems[index].a.eScript)
+        if ((levels && (levels[cnt] != pItems[index].a.s.uBidiLevel)) || New_Script != pItems[index].a.eScript)
         {
-            TRACE("New_Script=%d, eScript=%d ", New_Script, pItems[index].a.eScript);
+            TRACE("New_Level = %i, New_Script=%d, eScript=%d ", levels?levels[cnt]:-1, New_Script, pItems[index].a.eScript);
             index++;
             if  (index+1 > cMaxItems)
                 return E_OUTOFMEMORY;
@@ -588,9 +624,18 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem
             pItems[index].iCharPos = cnt;
             memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS));
 
-            if  (New_Script == Script_Arabic)
+            if (levels)
+            {
+                pItems[index].a.fRTL = odd(levels[cnt]);
+                pItems[index].a.fLayoutRTL = odd(levels[cnt]);
+                pItems[index].a.s.uBidiLevel = levels[cnt];
+            }
+            else if  (New_Script == Script_Arabic)
+            {
                 pItems[index].a.s.uBidiLevel = 1;
-
+                pItems[index].a.fRTL = 1;
+                pItems[index].a.fLayoutRTL = 1;
+            }
             pItems[index].a.eScript = New_Script;
 
             TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos);
@@ -610,6 +655,7 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem
     /*  Set SCRIPT_ITEM                                     */
     pItems[index+1].iCharPos = cnt;       /* the last + 1 item
                                              contains the ptr to the lastchar */
+    heap_free(levels);
     return S_OK;
 }
 
@@ -686,7 +732,7 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString,
         int numGlyphsReturned;
 
         /* FIXME: non unicode strings */
-        WCHAR* pStr = (WCHAR*)pString;
+        const WCHAR* pStr = (const WCHAR*)pString;
         hr = ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos],
                          cChar, numGlyphs, &analysis->pItem[i].a,
                          glyphs, pwLogClust, psva, &numGlyphsReturned);
@@ -1286,6 +1332,7 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
 {
     HRESULT hr;
     unsigned int i;
+    BOOL rtl;
 
     TRACE("(%p, %p, %s, %d, %d, %p, %p, %p, %p, %p)\n", hdc, psc, debugstr_wn(pwcChars, cChars),
           cChars, cMaxGlyphs, psa, pwOutGlyphs, pwLogClust, psva, pcGlyphs);
@@ -1295,6 +1342,7 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
 
     if (!psva || !pcGlyphs) return E_INVALIDARG;
     if (cChars > cMaxGlyphs) return E_OUTOFMEMORY;
+    rtl = (!psa->fLogicalOrder && psa->fRTL);
 
     *pcGlyphs = cChars;
     if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
@@ -1304,33 +1352,42 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars,
     {
         for (i = 0; i < cChars; i++)
         {
-            if (!(pwOutGlyphs[i] = get_cache_glyph(psc, pwcChars[i])))
+            int idx = i;
+            if (rtl) idx = cChars - 1 - i;
+            if (!(pwOutGlyphs[i] = get_cache_glyph(psc, pwcChars[idx])))
             {
                 WORD glyph;
                 if (!hdc) return E_PENDING;
-                if (GetGlyphIndicesW(hdc, &pwcChars[i], 1, &glyph, 0) == GDI_ERROR) return S_FALSE;
-                pwOutGlyphs[i] = set_cache_glyph(psc, pwcChars[i], glyph);
+                if (GetGlyphIndicesW(hdc, &pwcChars[idx], 1, &glyph, 0) == GDI_ERROR) return S_FALSE;
+                pwOutGlyphs[i] = set_cache_glyph(psc, pwcChars[idx], glyph);
             }
         }
     }
     else
     {
         TRACE("no glyph translation\n");
-        for (i = 0; i < cChars; i++) pwOutGlyphs[i] = pwcChars[i];
+        for (i = 0; i < cChars; i++)
+        {
+            int idx = i;
+            if (rtl) idx = cChars - 1 - i;
+            pwOutGlyphs[i] = pwcChars[idx];
+        }
     }
 
     /* set up a valid SCRIPT_VISATTR and LogClust for each char in this run */
     for (i = 0; i < cChars; i++)
     {
+        int idx = i;
+        if (rtl) idx = cChars - 1 - i;
         /* FIXME: set to better values */
-        psva[i].uJustification = (pwcChars[i] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER;
+        psva[i].uJustification = (pwcChars[idx] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER;
         psva[i].fClusterStart  = 1;
         psva[i].fDiacritic     = 0;
         psva[i].fZeroWidth     = 0;
         psva[i].fReserved      = 0;
         psva[i].fShapeReserved = 0;
 
-        pwLogClust[i] = i;
+        pwLogClust[i] = idx;
     }
     return S_OK;
 }
@@ -1573,28 +1630,45 @@ HRESULT WINAPI ScriptGetGlyphABCWidth(HDC hdc, SCRIPT_CACHE *psc, WORD glyph, AB
  */
 HRESULT WINAPI ScriptLayout(int runs, const BYTE *level, int *vistolog, int *logtovis)
 {
-    int i, j = runs - 1, k = 0;
+    int* indexs;
+    int ich;
 
     TRACE("(%d, %p, %p, %p)\n", runs, level, vistolog, logtovis);
 
     if (!level || (!vistolog && !logtovis))
         return E_INVALIDARG;
 
-    for (i = 0; i < runs; i++)
+    indexs = heap_alloc(sizeof(int) * runs);
+    if (!indexs)
+        return E_OUTOFMEMORY;
+
+
+    if (vistolog)
     {
-        if (level[i] % 2)
-        {
-            if (vistolog) *vistolog++ = j;
-            if (logtovis) *logtovis++ = j;
-            j--;
-        }
-        else
-        {
-            if (vistolog) *vistolog++ = k;
-            if (logtovis) *logtovis++ = k;
-            k++;
-        }
+        for( ich = 0; ich < runs; ich++)
+            indexs[ich] = ich;
+
+        ich = 0;
+        while (ich < runs)
+            ich += BIDI_ReorderV2lLevel(0, indexs+ich, level+ich, runs - ich, FALSE);
+        for (ich = 0; ich < runs; ich++)
+            vistolog[ich] = indexs[ich];
     }
+
+
+    if (logtovis)
+    {
+        for( ich = 0; ich < runs; ich++)
+            indexs[ich] = ich;
+
+        ich = 0;
+        while (ich < runs)
+            ich += BIDI_ReorderL2vLevel(0, indexs+ich, level+ich, runs - ich, FALSE);
+        for (ich = 0; ich < runs; ich++)
+            logtovis[ich] = indexs[ich];
+    }
+    heap_free(indexs);
+
     return S_OK;
 }
 
@@ -1839,9 +1913,3 @@ HRESULT WINAPI ScriptJustify(const SCRIPT_VISATTR *sva, const int *advance,
     for (i = 0; i < num_glyphs; i++) justify[i] = advance[i];
     return S_OK;
 }
-
-BOOL gbLpkPresent = FALSE;
-VOID WINAPI LpkPresent()
-{
-    gbLpkPresent = TRUE; /* Turn it on this way! Wine is out of control! */
-}
index ad07101..527578c 100644 (file)
@@ -6,6 +6,7 @@
        <include base="usp10">.</include>
        <include base="ReactOS">include/reactos/wine</include>
        <define name="__WINESRC__" />
+       <file>bidi.c</file>
        <file>usp10.c</file>
        <library>wine</library>
        <library>gdi32</library>
index 0f7b0aa..5e35870 100644 (file)
@@ -1,4 +1,4 @@
-@ stdcall LpkPresent()
+@ stub LpkPresent
 @ stdcall ScriptApplyDigitSubstitution(ptr ptr ptr)
 @ stdcall ScriptApplyLogicalWidth(ptr long long ptr ptr ptr ptr ptr ptr)
 @ stdcall ScriptBreak(ptr long ptr ptr)
diff --git a/reactos/dll/win32/usp10/usp10_internal.h b/reactos/dll/win32/usp10/usp10_internal.h
new file mode 100644 (file)
index 0000000..60e4eff
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Implementation of Uniscribe Script Processor (usp10.dll)
+ *
+ * Copyright 2010 CodeWeavers, Aric Stewart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ */
+
+#define odd(x) ((x) & 1)
+
+BOOL BIDI_DetermineLevels( LPCWSTR lpString, INT uCount, const SCRIPT_STATE *s,
+                const SCRIPT_CONTROL *c, WORD *lpOutLevels );
+
+INT BIDI_ReorderV2lLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse);
+INT BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse);
index e7d34e0..16d9eac 100644 (file)
@@ -199,7 +199,11 @@ static BOOL find_ne_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff )
  */
 static BOOL find_pe_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff )
 {
-    IMAGE_NT_HEADERS pehd;
+    union
+    {
+        IMAGE_NT_HEADERS32 nt32;
+        IMAGE_NT_HEADERS64 nt64;
+    } pehd;
     DWORD pehdoffset;
     PIMAGE_DATA_DIRECTORY resDataDir;
     PIMAGE_SECTION_HEADER sections;
@@ -208,14 +212,27 @@ static BOOL find_pe_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff )
     const void *resDir;
     const IMAGE_RESOURCE_DIRECTORY *resPtr;
     const IMAGE_RESOURCE_DATA_ENTRY *resData;
-    int i, nSections;
+    int i, len, nSections;
     BOOL ret = FALSE;
 
     /* Read in PE header */
     pehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
-    if ( sizeof(pehd) != LZRead( lzfd, (LPSTR)&pehd, sizeof(pehd) ) ) return 0;
+    len = LZRead( lzfd, (LPSTR)&pehd, sizeof(pehd) );
+    if (len < sizeof(pehd.nt32.FileHeader)) return 0;
+    if (len < sizeof(pehd)) memset( (char *)&pehd + len, 0, sizeof(pehd) - len );
+
+    switch (pehd.nt32.OptionalHeader.Magic)
+    {
+    case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
+        resDataDir = pehd.nt32.OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_RESOURCE;
+        break;
+    case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+        resDataDir = pehd.nt64.OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_RESOURCE;
+        break;
+    default:
+        return 0;
+    }
 
-    resDataDir = pehd.OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE;
     if ( !resDataDir->Size )
     {
         TRACE("No resources in PE dll\n" );
@@ -223,15 +240,13 @@ static BOOL find_pe_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff )
     }
 
     /* Read in section table */
-    nSections = pehd.FileHeader.NumberOfSections;
+    nSections = pehd.nt32.FileHeader.NumberOfSections;
     sections = HeapAlloc( GetProcessHeap(), 0,
                           nSections * sizeof(IMAGE_SECTION_HEADER) );
     if ( !sections ) return FALSE;
 
-    LZSeek( lzfd, pehdoffset +
-                    sizeof(DWORD) + /* Signature */
-                    sizeof(IMAGE_FILE_HEADER) +
-                    pehd.FileHeader.SizeOfOptionalHeader, SEEK_SET );
+    len = FIELD_OFFSET( IMAGE_NT_HEADERS32, OptionalHeader ) + pehd.nt32.FileHeader.SizeOfOptionalHeader;
+    LZSeek( lzfd, pehdoffset + len, SEEK_SET );
 
     if ( nSections * sizeof(IMAGE_SECTION_HEADER) !=
          LZRead( lzfd, (LPSTR)sections, nSections * sizeof(IMAGE_SECTION_HEADER) ) )
index 5c805c8..854b337 100644 (file)
@@ -58,12 +58,14 @@ typedef struct {
     DWORD bc2AppData;
 } BITMAPCOREHEADER2;
 
-struct BmpFrameDecode;
-typedef HRESULT (*ReadDataFunc)(struct BmpFrameDecode* This);
+struct BmpDecoder;
+typedef HRESULT (*ReadDataFunc)(struct BmpDecoder* This);
 
-typedef struct BmpFrameDecode {
-    const IWICBitmapFrameDecodeVtbl *lpVtbl;
+typedef struct BmpDecoder {
+    const IWICBitmapDecoderVtbl *lpVtbl;
+    const IWICBitmapFrameDecodeVtbl *lpFrameVtbl;
     LONG ref;
+    BOOL initialized;
     IStream *stream;
     BITMAPFILEHEADER bfh;
     BITMAPV5HEADER bih;
@@ -73,12 +75,17 @@ typedef struct BmpFrameDecode {
     INT stride;
     BYTE *imagedata;
     BYTE *imagedatastart;
-} BmpFrameDecode;
+    CRITICAL_SECTION lock; /* must be held when initialized/imagedata is set or stream is accessed */
+} BmpDecoder;
+
+static inline BmpDecoder *impl_from_frame(IWICBitmapFrameDecode *iface)
+{
+    return CONTAINING_RECORD(iface, BmpDecoder, lpFrameVtbl);
+}
 
 static HRESULT WINAPI BmpFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
     void **ppv)
 {
-    BmpFrameDecode *This = (BmpFrameDecode*)iface;
     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
 
     if (!ppv) return E_INVALIDARG;
@@ -87,7 +94,7 @@ static HRESULT WINAPI BmpFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface
         IsEqualIID(&IID_IWICBitmapSource, iid) ||
         IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
     {
-        *ppv = This;
+        *ppv = iface;
     }
     else
     {
@@ -101,35 +108,22 @@ static HRESULT WINAPI BmpFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface
 
 static ULONG WINAPI BmpFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
 {
-    BmpFrameDecode *This = (BmpFrameDecode*)iface;
-    ULONG ref = InterlockedIncrement(&This->ref);
-
-    TRACE("(%p) refcount=%u\n", iface, ref);
+    BmpDecoder *This = impl_from_frame(iface);
 
-    return ref;
+    return IUnknown_AddRef((IUnknown*)This);
 }
 
 static ULONG WINAPI BmpFrameDecode_Release(IWICBitmapFrameDecode *iface)
 {
-    BmpFrameDecode *This = (BmpFrameDecode*)iface;
-    ULONG ref = InterlockedDecrement(&This->ref);
-
-    TRACE("(%p) refcount=%u\n", iface, ref);
-
-    if (ref == 0)
-    {
-        IStream_Release(This->stream);
-        HeapFree(GetProcessHeap(), 0, This->imagedata);
-        HeapFree(GetProcessHeap(), 0, This);
-    }
+    BmpDecoder *This = impl_from_frame(iface);
 
-    return ref;
+    return IUnknown_Release((IUnknown*)This);
 }
 
 static HRESULT WINAPI BmpFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
     UINT *puiWidth, UINT *puiHeight)
 {
-    BmpFrameDecode *This = (BmpFrameDecode*)iface;
+    BmpDecoder *This = impl_from_frame(iface);
     TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
 
     if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
@@ -149,7 +143,7 @@ static HRESULT WINAPI BmpFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
 static HRESULT WINAPI BmpFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
     WICPixelFormatGUID *pPixelFormat)
 {
-    BmpFrameDecode *This = (BmpFrameDecode*)iface;
+    BmpDecoder *This = impl_from_frame(iface);
     TRACE("(%p,%p)\n", iface, pPixelFormat);
 
     memcpy(pPixelFormat, This->pixelformat, sizeof(GUID));
@@ -180,7 +174,7 @@ static HRESULT BmpHeader_GetResolution(BITMAPV5HEADER *bih, double *pDpiX, doubl
 static HRESULT WINAPI BmpFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
     double *pDpiX, double *pDpiY)
 {
-    BmpFrameDecode *This = (BmpFrameDecode*)iface;
+    BmpDecoder *This = impl_from_frame(iface);
     TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
 
     return BmpHeader_GetResolution(&This->bih, pDpiX, pDpiY);
@@ -190,13 +184,15 @@ static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
     IWICPalette *pIPalette)
 {
     HRESULT hr;
-    BmpFrameDecode *This = (BmpFrameDecode*)iface;
+    BmpDecoder *This = impl_from_frame(iface);
     int count;
     WICColor *wiccolors=NULL;
     RGBTRIPLE *bgrcolors=NULL;
 
     TRACE("(%p,%p)\n", iface, pIPalette);
 
+    EnterCriticalSection(&This->lock);
+
     if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
     {
         BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
@@ -238,7 +234,8 @@ static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
         }
         else
         {
-            return WINCODEC_ERR_PALETTEUNAVAILABLE;
+            hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
+            goto end;
         }
     }
     else
@@ -256,7 +253,11 @@ static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
 
             tablesize = sizeof(WICColor) * count;
             wiccolors = HeapAlloc(GetProcessHeap(), 0, tablesize);
-            if (!wiccolors) return E_OUTOFMEMORY;
+            if (!wiccolors)
+            {
+                hr = E_OUTOFMEMORY;
+                goto end;
+            }
 
             offset.QuadPart = sizeof(BITMAPFILEHEADER) + This->bih.bV5Size;
             hr = IStream_Seek(This->stream, offset, STREAM_SEEK_SET, NULL);
@@ -275,13 +276,18 @@ static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
         }
         else
         {
-            return WINCODEC_ERR_PALETTEUNAVAILABLE;
+            hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
+            goto end;
         }
     }
 
-    hr = IWICPalette_InitializeCustom(pIPalette, wiccolors, count);
-
 end:
+
+    LeaveCriticalSection(&This->lock);
+
+    if (SUCCEEDED(hr))
+        hr = IWICPalette_InitializeCustom(pIPalette, wiccolors, count);
+
     HeapFree(GetProcessHeap(), 0, wiccolors);
     HeapFree(GetProcessHeap(), 0, bgrcolors);
     return hr;
@@ -290,16 +296,18 @@ end:
 static HRESULT WINAPI BmpFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
 {
-    BmpFrameDecode *This = (BmpFrameDecode*)iface;
-    HRESULT hr;
+    BmpDecoder *This = impl_from_frame(iface);
+    HRESULT hr=S_OK;
     UINT width, height;
     TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
 
+    EnterCriticalSection(&This->lock);
     if (!This->imagedata)
     {
         hr = This->read_data_func(This);
-        if (FAILED(hr)) return hr;
     }
+    LeaveCriticalSection(&This->lock);
+    if (FAILED(hr)) return hr;
 
     hr = BmpFrameDecode_GetSize(iface, &width, &height);
     if (FAILED(hr)) return hr;
@@ -330,7 +338,7 @@ static HRESULT WINAPI BmpFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
     return WINCODEC_ERR_CODECNOTHUMBNAIL;
 }
 
-static HRESULT BmpFrameDecode_ReadUncompressed(BmpFrameDecode* This)
+static HRESULT BmpFrameDecode_ReadUncompressed(BmpDecoder* This)
 {
     UINT bytesperrow;
     UINT width, height;
@@ -387,7 +395,7 @@ fail:
     return hr;
 }
 
-static HRESULT BmpFrameDecode_ReadRLE8(BmpFrameDecode* This)
+static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
 {
     UINT bytesperrow;
     UINT width, height;
@@ -493,7 +501,7 @@ fail:
     return hr;
 }
 
-static HRESULT BmpFrameDecode_ReadRLE4(BmpFrameDecode* This)
+static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
 {
     UINT bytesperrow;
     UINT width, height;
@@ -614,7 +622,7 @@ fail:
     return hr;
 }
 
-static HRESULT BmpFrameDecode_ReadUnsupported(BmpFrameDecode* This)
+static HRESULT BmpFrameDecode_ReadUnsupported(BmpDecoder* This)
 {
     return E_FAIL;
 }
@@ -637,7 +645,7 @@ static const struct bitfields_format bitfields_formats[] = {
     {0}
 };
 
-static const IWICBitmapFrameDecodeVtbl BmpFrameDecode_Vtbl = {
+static const IWICBitmapFrameDecodeVtbl BmpDecoder_FrameVtbl = {
     BmpFrameDecode_QueryInterface,
     BmpFrameDecode_AddRef,
     BmpFrameDecode_Release,
@@ -651,19 +659,6 @@ static const IWICBitmapFrameDecodeVtbl BmpFrameDecode_Vtbl = {
     BmpFrameDecode_GetThumbnail
 };
 
-typedef struct {
-    const IWICBitmapDecoderVtbl *lpVtbl;
-    LONG ref;
-    BOOL initialized;
-    IStream *stream;
-    BITMAPFILEHEADER bfh;
-    BITMAPV5HEADER bih;
-    BmpFrameDecode *framedecode;
-    const WICPixelFormatGUID *pixelformat;
-    int bitsperpixel;
-    ReadDataFunc read_data_func;
-} BmpDecoder;
-
 static HRESULT BmpDecoder_ReadHeaders(BmpDecoder* This, IStream *stream)
 {
     HRESULT hr;
@@ -873,7 +868,9 @@ static ULONG WINAPI BmpDecoder_Release(IWICBitmapDecoder *iface)
     if (ref == 0)
     {
         if (This->stream) IStream_Release(This->stream);
-        if (This->framedecode) IUnknown_Release((IUnknown*)This->framedecode);
+        HeapFree(GetProcessHeap(), 0, This->imagedata);
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -886,7 +883,9 @@ static HRESULT WINAPI BmpDecoder_QueryCapability(IWICBitmapDecoder *iface, IStre
     HRESULT hr;
     BmpDecoder *This = (BmpDecoder*)iface;
 
+    EnterCriticalSection(&This->lock);
     hr = BmpDecoder_ReadHeaders(This, pIStream);
+    LeaveCriticalSection(&This->lock);
     if (FAILED(hr)) return hr;
 
     if (This->read_data_func == BmpFrameDecode_ReadUnsupported)
@@ -903,6 +902,7 @@ static HRESULT WINAPI BmpDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
     HRESULT hr;
     BmpDecoder *This = (BmpDecoder*)iface;
 
+    EnterCriticalSection(&This->lock);
     hr = BmpDecoder_ReadHeaders(This, pIStream);
 
     if (SUCCEEDED(hr))
@@ -910,6 +910,7 @@ static HRESULT WINAPI BmpDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
         This->stream = pIStream;
         IStream_AddRef(pIStream);
     }
+    LeaveCriticalSection(&This->lock);
 
     return hr;
 }
@@ -992,25 +993,8 @@ static HRESULT WINAPI BmpDecoder_GetFrame(IWICBitmapDecoder *iface,
 
     if (!This->stream) return WINCODEC_ERR_WRONGSTATE;
 
-    if (!This->framedecode)
-    {
-        This->framedecode = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpFrameDecode));
-        if (!This->framedecode) return E_OUTOFMEMORY;
-
-        This->framedecode->lpVtbl = &BmpFrameDecode_Vtbl;
-        This->framedecode->ref = 1;
-        This->framedecode->stream = This->stream;
-        IStream_AddRef(This->stream);
-        This->framedecode->bfh = This->bfh;
-        This->framedecode->bih = This->bih;
-        This->framedecode->pixelformat = This->pixelformat;
-        This->framedecode->bitsperpixel = This->bitsperpixel;
-        This->framedecode->read_data_func = This->read_data_func;
-        This->framedecode->imagedata = NULL;
-    }
-
-    *ppIBitmapFrame = (IWICBitmapFrameDecode*)This->framedecode;
-    IWICBitmapFrameDecode_AddRef((IWICBitmapFrameDecode*)This->framedecode);
+    *ppIBitmapFrame = (IWICBitmapFrameDecode*)&This->lpFrameVtbl;
+    IWICBitmapDecoder_AddRef(iface);
 
     return S_OK;
 }
@@ -1047,10 +1031,13 @@ HRESULT BmpDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
     if (!This) return E_OUTOFMEMORY;
 
     This->lpVtbl = &BmpDecoder_Vtbl;
+    This->lpFrameVtbl = &BmpDecoder_FrameVtbl;
     This->ref = 1;
     This->initialized = FALSE;
     This->stream = NULL;
-    This->framedecode = NULL;
+    This->imagedata = NULL;
+    InitializeCriticalSection(&This->lock);
+    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BmpDecoder.lock");
 
     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
     IUnknown_Release((IUnknown*)This);
index d8d2105..68e0530 100644 (file)
@@ -50,6 +50,7 @@ static classinfo wic_classes[] = {
     {&CLSID_WICGifDecoder, GifDecoder_CreateInstance},
     {&CLSID_WICIcoDecoder, IcoDecoder_CreateInstance},
     {&CLSID_WICJpegDecoder, JpegDecoder_CreateInstance},
+    {&CLSID_WICTiffDecoder, TiffDecoder_CreateInstance},
     {&CLSID_WICDefaultFormatConverter, FormatConverter_CreateInstance},
     {0}};
 
index 15c7b0f..b1c0952 100644 (file)
@@ -71,6 +71,7 @@ typedef struct FormatConverter {
     WICBitmapDitherType dither;
     double alpha_threshold;
     WICBitmapPaletteType palette_type;
+    CRITICAL_SECTION lock; /* must be held when initialized */
 } FormatConverter;
 
 static void make_grayscale_palette(WICColor *colors, UINT num_colors)
@@ -765,6 +766,8 @@ static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface)
 
     if (ref == 0)
     {
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
         if (This->source) IWICBitmapSource_Release(This->source);
         HeapFree(GetProcessHeap(), 0, This);
     }
@@ -841,38 +844,56 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
     const struct pixelformatinfo *srcinfo, *dstinfo;
     static INT fixme=0;
     GUID srcFormat;
-    HRESULT res;
+    HRESULT res=S_OK;
 
     TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface, pISource, debugstr_guid(dstFormat),
         dither, pIPalette, alphaThresholdPercent, paletteTranslate);
 
     if (pIPalette && !fixme++) FIXME("ignoring palette\n");
 
-    if (This->source) return WINCODEC_ERR_WRONGSTATE;
+    EnterCriticalSection(&This->lock);
+
+    if (This->source)
+    {
+        res = WINCODEC_ERR_WRONGSTATE;
+        goto end;
+    }
 
     res = IWICBitmapSource_GetPixelFormat(pISource, &srcFormat);
-    if (FAILED(res)) return res;
+    if (FAILED(res)) goto end;
 
     srcinfo = get_formatinfo(&srcFormat);
-    if (!srcinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+    if (!srcinfo)
+    {
+        res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+        goto end;
+    }
 
     dstinfo = get_formatinfo(dstFormat);
-    if (!dstinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+    if (!dstinfo)
+    {
+        res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+        goto end;
+    }
 
     if (dstinfo->copy_function)
     {
         IWICBitmapSource_AddRef(pISource);
-        This->source = pISource;
         This->src_format = srcinfo;
         This->dst_format = dstinfo;
         This->dither = dither;
         This->alpha_threshold = alphaThresholdPercent;
         This->palette_type = paletteTranslate;
+        This->source = pISource;
     }
     else
-        return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+        res = WINCODEC_ERR_UNSUPPORTEDOPERATION;
 
-    return S_OK;
+end:
+
+    LeaveCriticalSection(&This->lock);
+
+    return res;
 }
 
 static HRESULT WINAPI FormatConverter_CanConvert(IWICFormatConverter *iface,
@@ -930,6 +951,8 @@ HRESULT FormatConverter_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** p
     This->lpVtbl = &FormatConverter_Vtbl;
     This->ref = 1;
     This->source = NULL;
+    InitializeCriticalSection(&This->lock);
+    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FormatConverter.lock");
 
     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
     IUnknown_Release((IUnknown*)This);
index 0597b1a..3443b2c 100644 (file)
@@ -40,6 +40,7 @@ typedef struct {
     LONG ref;
     BOOL initialized;
     GifFileType *gif;
+    CRITICAL_SECTION lock;
 } GifDecoder;
 
 typedef struct {
@@ -302,6 +303,8 @@ static ULONG WINAPI GifDecoder_Release(IWICBitmapDecoder *iface)
 
     if (ref == 0)
     {
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
         DGifCloseFile(This->gif);
         HeapFree(GetProcessHeap(), 0, This);
     }
@@ -341,9 +344,12 @@ static HRESULT WINAPI GifDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
 
     TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
 
+    EnterCriticalSection(&This->lock);
+
     if (This->initialized || This->gif)
     {
         WARN("already initialized\n");
+        LeaveCriticalSection(&This->lock);
         return WINCODEC_ERR_WRONGSTATE;
     }
 
@@ -353,16 +359,26 @@ static HRESULT WINAPI GifDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
 
     /* read all data from the stream */
     This->gif = DGifOpen((void*)pIStream, _gif_inputfunc);
-    if (!This->gif) return E_FAIL;
+    if (!This->gif)
+    {
+        LeaveCriticalSection(&This->lock);
+        return E_FAIL;
+    }
 
     ret = DGifSlurp(This->gif);
-    if (ret == GIF_ERROR) return E_FAIL;
+    if (ret == GIF_ERROR)
+    {
+        LeaveCriticalSection(&This->lock);
+        return E_FAIL;
+    }
 
     /* make sure we don't use the stream after this method returns */
     This->gif->UserData = NULL;
 
     This->initialized = TRUE;
 
+    LeaveCriticalSection(&This->lock);
+
     return S_OK;
 }
 
@@ -502,6 +518,8 @@ HRESULT GifDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
     This->ref = 1;
     This->initialized = FALSE;
     This->gif = NULL;
+    InitializeCriticalSection(&This->lock);
+    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": GifDecoder.lock");
 
     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
     IUnknown_Release((IUnknown*)This);
index ab30ab0..e1ea7c6 100644 (file)
@@ -62,6 +62,7 @@ typedef struct {
     BOOL initialized;
     IStream *stream;
     ICONHEADER header;
+    CRITICAL_SECTION lock; /* must be held when accessing stream */
 } IcoDecoder;
 
 typedef struct {
@@ -512,15 +513,17 @@ static HRESULT WINAPI IcoFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
 {
     IcoFrameDecode *This = (IcoFrameDecode*)iface;
-    HRESULT hr;
+    HRESULT hr=S_OK;
     UINT width, height, stride;
     TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
 
+    EnterCriticalSection(&This->parent->lock);
     if (!This->bits)
     {
         hr = IcoFrameDecode_ReadPixels(This);
-        if (FAILED(hr)) return hr;
     }
+    LeaveCriticalSection(&This->parent->lock);
+    if (FAILED(hr)) return hr;
 
     width = This->entry.bWidth ? This->entry.bWidth : 256;
     height = This->entry.bHeight ? This->entry.bHeight : 256;
@@ -606,6 +609,8 @@ static ULONG WINAPI IcoDecoder_Release(IWICBitmapDecoder *iface)
 
     if (ref == 0)
     {
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
         if (This->stream) IStream_Release(This->stream);
         HeapFree(GetProcessHeap(), 0, This);
     }
@@ -629,23 +634,37 @@ static HRESULT WINAPI IcoDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
     ULONG bytesread;
     TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
 
-    if (This->initialized) return WINCODEC_ERR_WRONGSTATE;
+    EnterCriticalSection(&This->lock);
+
+    if (This->initialized)
+    {
+        hr = WINCODEC_ERR_WRONGSTATE;
+        goto end;
+    }
 
     seek.QuadPart = 0;
     hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
-    if (FAILED(hr)) return hr;
+    if (FAILED(hr)) goto end;
 
     hr = IStream_Read(pIStream, &This->header, sizeof(ICONHEADER), &bytesread);
-    if (FAILED(hr)) return hr;
+    if (FAILED(hr)) goto end;
     if (bytesread != sizeof(ICONHEADER) ||
         This->header.idReserved != 0 ||
-        This->header.idType != 1) return E_FAIL;
+        This->header.idType != 1)
+    {
+        hr = E_FAIL;
+        goto end;
+    }
 
     This->initialized = TRUE;
     This->stream = pIStream;
     IStream_AddRef(pIStream);
 
-    return S_OK;
+end:
+
+    LeaveCriticalSection(&This->lock);
+
+    return hr;
 }
 
 static HRESULT WINAPI IcoDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
@@ -715,18 +734,32 @@ static HRESULT WINAPI IcoDecoder_GetFrame(IWICBitmapDecoder *iface,
     UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
 {
     IcoDecoder *This = (IcoDecoder*)iface;
-    IcoFrameDecode *result;
+    IcoFrameDecode *result=NULL;
     LARGE_INTEGER seek;
     HRESULT hr;
     ULONG bytesread;
     TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
 
-    if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED;
+    EnterCriticalSection(&This->lock);
+
+    if (!This->initialized)
+    {
+        hr = WINCODEC_ERR_NOTINITIALIZED;
+        goto fail;
+    }
 
-    if (This->header.idCount < index) return E_INVALIDARG;
+    if (This->header.idCount < index)
+    {
+        hr = E_INVALIDARG;
+        goto fail;
+    }
 
     result = HeapAlloc(GetProcessHeap(), 0, sizeof(IcoFrameDecode));
-    if (!result) return E_OUTOFMEMORY;
+    if (!result)
+    {
+        hr = E_OUTOFMEMORY;
+        goto fail;
+    }
 
     result->lpVtbl = &IcoFrameDecode_Vtbl;
     result->ref = 1;
@@ -745,9 +778,12 @@ static HRESULT WINAPI IcoDecoder_GetFrame(IWICBitmapDecoder *iface,
 
     *ppIBitmapFrame = (IWICBitmapFrameDecode*)result;
 
+    LeaveCriticalSection(&This->lock);
+
     return S_OK;
 
 fail:
+    LeaveCriticalSection(&This->lock);
     HeapFree(GetProcessHeap(), 0, result);
     if (SUCCEEDED(hr)) hr = E_FAIL;
     TRACE("<-- %x\n", hr);
@@ -789,6 +825,8 @@ HRESULT IcoDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
     This->ref = 1;
     This->stream = NULL;
     This->initialized = FALSE;
+    InitializeCriticalSection(&This->lock);
+    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IcoDecoder.lock");
 
     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
     IUnknown_Release((IUnknown*)This);
index 017e604..b5676ea 100644 (file)
@@ -103,6 +103,7 @@ typedef struct {
     struct jpeg_source_mgr source_mgr;
     BYTE source_buffer[1024];
     BYTE *image_data;
+    CRITICAL_SECTION lock;
 } JpegDecoder;
 
 static inline JpegDecoder *decoder_from_decompress(j_decompress_ptr decompress)
@@ -156,6 +157,8 @@ static ULONG WINAPI JpegDecoder_Release(IWICBitmapDecoder *iface)
 
     if (ref == 0)
     {
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
         if (This->cinfo_initialized) pjpeg_destroy_decompress(&This->cinfo);
         if (This->stream) IStream_Release(This->stream);
         HeapFree(GetProcessHeap(), 0, This->image_data);
@@ -225,7 +228,13 @@ static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream *
     int ret;
     TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions);
 
-    if (This->cinfo_initialized) return WINCODEC_ERR_WRONGSTATE;
+    EnterCriticalSection(&This->lock);
+
+    if (This->cinfo_initialized)
+    {
+        LeaveCriticalSection(&This->lock);
+        return WINCODEC_ERR_WRONGSTATE;
+    }
 
     This->cinfo.err = pjpeg_std_error(&This->jerr);
 
@@ -249,6 +258,7 @@ static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream *
 
     if (ret != JPEG_HEADER_OK) {
         WARN("Jpeg image in stream has bad format, read header returned %d.\n",ret);
+        LeaveCriticalSection(&This->lock);
         return E_FAIL;
     }
 
@@ -260,11 +270,14 @@ static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream *
     if (!pjpeg_start_decompress(&This->cinfo))
     {
         ERR("jpeg_start_decompress failed\n");
+        LeaveCriticalSection(&This->lock);
         return E_FAIL;
     }
 
     This->initialized = TRUE;
 
+    LeaveCriticalSection(&This->lock);
+
     return S_OK;
 }
 
@@ -448,10 +461,16 @@ static HRESULT WINAPI JpegDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
     max_row_needed = prc->Y + prc->Height;
     if (max_row_needed > This->cinfo.output_height) return E_INVALIDARG;
 
+    EnterCriticalSection(&This->lock);
+
     if (!This->image_data)
     {
         This->image_data = HeapAlloc(GetProcessHeap(), 0, data_size);
-        if (!This->image_data) return E_OUTOFMEMORY;
+        if (!This->image_data)
+        {
+            LeaveCriticalSection(&This->lock);
+            return E_OUTOFMEMORY;
+        }
     }
 
     while (max_row_needed > This->cinfo.output_scanline)
@@ -471,6 +490,7 @@ static HRESULT WINAPI JpegDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
         if (ret == 0)
         {
             ERR("read_scanlines failed\n");
+            LeaveCriticalSection(&This->lock);
             return E_FAIL;
         }
 
@@ -492,6 +512,8 @@ static HRESULT WINAPI JpegDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
         }
     }
 
+    LeaveCriticalSection(&This->lock);
+
     return copy_pixels(bpp, This->image_data,
         This->cinfo.output_width, This->cinfo.output_height, stride,
         prc, cbStride, cbBufferSize, pbBuffer);
@@ -559,6 +581,8 @@ HRESULT JpegDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
     This->cinfo_initialized = FALSE;
     This->stream = NULL;
     This->image_data = NULL;
+    InitializeCriticalSection(&This->lock);
+    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JpegDecoder.lock");
 
     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
     IUnknown_Release((IUnknown*)This);
index 842d3b5..40ab190 100644 (file)
@@ -40,6 +40,7 @@ typedef struct {
     UINT count;
     WICColor *colors;
     WICBitmapPaletteType type;
+    CRITICAL_SECTION lock; /* must be held when count, colors, or type is accessed */
 } PaletteImpl;
 
 static HRESULT WINAPI PaletteImpl_QueryInterface(IWICPalette *iface, REFIID iid,
@@ -83,6 +84,8 @@ static ULONG WINAPI PaletteImpl_Release(IWICPalette *iface)
 
     if (ref == 0)
     {
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
         HeapFree(GetProcessHeap(), 0, This->colors);
         HeapFree(GetProcessHeap(), 0, This);
     }
@@ -117,10 +120,12 @@ static HRESULT WINAPI PaletteImpl_InitializeCustom(IWICPalette *iface,
         memcpy(new_colors, pColors, sizeof(WICColor) * colorCount);
     }
 
+    EnterCriticalSection(&This->lock);
     HeapFree(GetProcessHeap(), 0, This->colors);
     This->colors = new_colors;
     This->count = colorCount;
     This->type = WICBitmapPaletteTypeCustom;
+    LeaveCriticalSection(&This->lock);
 
     return S_OK;
 }
@@ -148,7 +153,9 @@ static HRESULT WINAPI PaletteImpl_GetType(IWICPalette *iface,
 
     if (!pePaletteType) return E_INVALIDARG;
 
+    EnterCriticalSection(&This->lock);
     *pePaletteType = This->type;
+    LeaveCriticalSection(&This->lock);
 
     return S_OK;
 }
@@ -161,7 +168,9 @@ static HRESULT WINAPI PaletteImpl_GetColorCount(IWICPalette *iface, UINT *pcCoun
 
     if (!pcCount) return E_INVALIDARG;
 
+    EnterCriticalSection(&This->lock);
     *pcCount = This->count;
+    LeaveCriticalSection(&This->lock);
 
     return S_OK;
 }
@@ -175,12 +184,16 @@ static HRESULT WINAPI PaletteImpl_GetColors(IWICPalette *iface, UINT colorCount,
 
     if (!pColors || !pcActualColors) return E_INVALIDARG;
 
+    EnterCriticalSection(&This->lock);
+
     if (This->count < colorCount) colorCount = This->count;
 
     memcpy(pColors, This->colors, sizeof(WICColor) * colorCount);
 
     *pcActualColors = colorCount;
 
+    LeaveCriticalSection(&This->lock);
+
     return S_OK;
 }
 
@@ -192,10 +205,12 @@ static HRESULT WINAPI PaletteImpl_IsBlackWhite(IWICPalette *iface, BOOL *pfIsBla
 
     if (!pfIsBlackWhite) return E_INVALIDARG;
 
+    EnterCriticalSection(&This->lock);
     if (This->type == WICBitmapPaletteTypeFixedBW)
         *pfIsBlackWhite = TRUE;
     else
         *pfIsBlackWhite = FALSE;
+    LeaveCriticalSection(&This->lock);
 
     return S_OK;
 }
@@ -208,6 +223,7 @@ static HRESULT WINAPI PaletteImpl_IsGrayscale(IWICPalette *iface, BOOL *pfIsGray
 
     if (!pfIsGrayscale) return E_INVALIDARG;
 
+    EnterCriticalSection(&This->lock);
     switch(This->type)
     {
         case WICBitmapPaletteTypeFixedBW:
@@ -219,6 +235,7 @@ static HRESULT WINAPI PaletteImpl_IsGrayscale(IWICPalette *iface, BOOL *pfIsGray
         default:
             *pfIsGrayscale = FALSE;
     }
+    LeaveCriticalSection(&This->lock);
 
     return S_OK;
 }
@@ -234,12 +251,14 @@ static HRESULT WINAPI PaletteImpl_HasAlpha(IWICPalette *iface, BOOL *pfHasAlpha)
 
     *pfHasAlpha = FALSE;
 
+    EnterCriticalSection(&This->lock);
     for (i=0; i<This->count; i++)
         if ((This->colors[i]&0xff000000) != 0xff000000)
         {
             *pfHasAlpha = TRUE;
             break;
         }
+    LeaveCriticalSection(&This->lock);
 
     return S_OK;
 }
@@ -272,6 +291,8 @@ HRESULT PaletteImpl_Create(IWICPalette **palette)
     This->count = 0;
     This->colors = NULL;
     This->type = WICBitmapPaletteTypeCustom;
+    InitializeCriticalSection(&This->lock);
+    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PaletteImpl.lock");
 
     *palette = (IWICPalette*)This;
 
index 5af680e..3dcbd9a 100644 (file)
@@ -162,6 +162,7 @@ typedef struct {
     UINT stride;
     const WICPixelFormatGUID *format;
     BYTE *image_bits;
+    CRITICAL_SECTION lock; /* must be held when png structures are accessed or initialized is set */
 } PngDecoder;
 
 static inline PngDecoder *impl_from_frame(IWICBitmapFrameDecode *iface)
@@ -214,6 +215,8 @@ static ULONG WINAPI PngDecoder_Release(IWICBitmapDecoder *iface)
     {
         if (This->png_ptr)
             ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info);
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
         HeapFree(GetProcessHeap(), 0, This->image_bits);
         HeapFree(GetProcessHeap(), 0, This);
     }
@@ -246,7 +249,7 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
 {
     PngDecoder *This = (PngDecoder*)iface;
     LARGE_INTEGER seek;
-    HRESULT hr;
+    HRESULT hr=S_OK;
     png_bytep *row_pointers=NULL;
     UINT image_size;
     UINT i;
@@ -259,16 +262,23 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
 
     TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
 
+    EnterCriticalSection(&This->lock);
+
     /* initialize libpng */
     This->png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-    if (!This->png_ptr) return E_FAIL;
+    if (!This->png_ptr)
+    {
+        hr = E_FAIL;
+        goto end;
+    }
 
     This->info_ptr = ppng_create_info_struct(This->png_ptr);
     if (!This->info_ptr)
     {
         ppng_destroy_read_struct(&This->png_ptr, NULL, NULL);
         This->png_ptr = NULL;
-        return E_FAIL;
+        hr = E_FAIL;
+        goto end;
     }
 
     This->end_info = ppng_create_info_struct(This->png_ptr);
@@ -276,7 +286,8 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
     {
         ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, NULL);
         This->png_ptr = NULL;
-        return E_FAIL;
+        hr = E_FAIL;
+        goto end;
     }
 
     /* set up setjmp/longjmp error handling */
@@ -285,14 +296,15 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
         ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info);
         HeapFree(GetProcessHeap(), 0, row_pointers);
         This->png_ptr = NULL;
-        return E_FAIL;
+        hr = E_FAIL;
+        goto end;
     }
     ppng_set_error_fn(This->png_ptr, &jmpbuf, user_error_fn, user_warning_fn);
 
     /* seek to the start of the stream */
     seek.QuadPart = 0;
     hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
-    if (FAILED(hr)) return hr;
+    if (FAILED(hr)) goto end;
 
     /* set up custom i/o handling */
     ppng_set_read_fn(This->png_ptr, pIStream, user_read_data);
@@ -340,7 +352,8 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
         case 16: This->format = &GUID_WICPixelFormat16bppGray; break;
         default:
             ERR("invalid grayscale bit depth: %i\n", bit_depth);
-            return E_FAIL;
+            hr = E_FAIL;
+            goto end;
         }
         break;
     case PNG_COLOR_TYPE_GRAY_ALPHA:
@@ -357,7 +370,8 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
         case 16: This->format = &GUID_WICPixelFormat64bppRGBA; break;
         default:
             ERR("invalid RGBA bit depth: %i\n", bit_depth);
-            return E_FAIL;
+            hr = E_FAIL;
+            goto end;
         }
         break;
     case PNG_COLOR_TYPE_PALETTE:
@@ -370,7 +384,8 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
         case 8: This->format = &GUID_WICPixelFormat8bppIndexed; break;
         default:
             ERR("invalid indexed color bit depth: %i\n", bit_depth);
-            return E_FAIL;
+            hr = E_FAIL;
+            goto end;
         }
         break;
     case PNG_COLOR_TYPE_RGB:
@@ -384,12 +399,14 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
         case 16: This->format = &GUID_WICPixelFormat48bppRGB; break;
         default:
             ERR("invalid RGB color bit depth: %i\n", bit_depth);
-            return E_FAIL;
+            hr = E_FAIL;
+            goto end;
         }
         break;
     default:
         ERR("invalid color type %i\n", color_type);
-        return E_FAIL;
+        hr = E_FAIL;
+        goto end;
     }
 
     /* read the image data */
@@ -399,10 +416,18 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
     image_size = This->stride * This->height;
 
     This->image_bits = HeapAlloc(GetProcessHeap(), 0, image_size);
-    if (!This->image_bits) return E_OUTOFMEMORY;
+    if (!This->image_bits)
+    {
+        hr = E_OUTOFMEMORY;
+        goto end;
+    }
 
     row_pointers = HeapAlloc(GetProcessHeap(), 0, sizeof(png_bytep)*This->height);
-    if (!row_pointers) return E_OUTOFMEMORY;
+    if (!row_pointers)
+    {
+        hr = E_OUTOFMEMORY;
+        goto end;
+    }
 
     for (i=0; i<This->height; i++)
         row_pointers[i] = This->image_bits + i * This->stride;
@@ -416,7 +441,11 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
 
     This->initialized = TRUE;
 
-    return S_OK;
+end:
+
+    LeaveCriticalSection(&This->lock);
+
+    return hr;
 }
 
 static HRESULT WINAPI PngDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
@@ -570,6 +599,8 @@ static HRESULT WINAPI PngDecoder_Frame_GetResolution(IWICBitmapFrameDecode *ifac
     png_uint_32 ret, xres, yres;
     int unit_type;
 
+    EnterCriticalSection(&This->lock);
+
     ret = ppng_get_pHYs(This->png_ptr, This->info_ptr, &xres, &yres, &unit_type);
 
     if (ret && unit_type == PNG_RESOLUTION_METER)
@@ -583,6 +614,8 @@ static HRESULT WINAPI PngDecoder_Frame_GetResolution(IWICBitmapFrameDecode *ifac
         *pDpiX = *pDpiY = 96.0;
     }
 
+    LeaveCriticalSection(&This->lock);
+
     TRACE("(%p)->(%0.2f,%0.2f)\n", iface, *pDpiX, *pDpiY);
 
     return S_OK;
@@ -600,16 +633,24 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
     int num_trans;
     png_color_16p trans_values;
     int i;
+    HRESULT hr=S_OK;
 
     TRACE("(%p,%p)\n", iface, pIPalette);
 
+    EnterCriticalSection(&This->lock);
+
     ret = ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette);
-    if (!ret) return WINCODEC_ERR_PALETTEUNAVAILABLE;
+    if (!ret)
+    {
+        hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
+        goto end;
+    }
 
     if (num_palette > 256)
     {
         ERR("palette has %i colors?!\n", num_palette);
-        return E_FAIL;
+        hr = E_FAIL;
+        goto end;
     }
 
     for (i=0; i<num_palette; i++)
@@ -629,7 +670,14 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
         }
     }
 
-    return IWICPalette_InitializeCustom(pIPalette, palette, num_palette);
+end:
+
+    LeaveCriticalSection(&This->lock);
+
+    if (SUCCEEDED(hr))
+        hr = IWICPalette_InitializeCustom(pIPalette, palette, num_palette);
+
+    return hr;
 }
 
 static HRESULT WINAPI PngDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
@@ -706,6 +754,8 @@ HRESULT PngDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
     This->end_info = NULL;
     This->initialized = FALSE;
     This->image_bits = NULL;
+    InitializeCriticalSection(&This->lock);
+    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PngDecoder.lock");
 
     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
     IUnknown_Release((IUnknown*)This);
@@ -752,6 +802,7 @@ typedef struct PngEncoder {
     UINT lines_written;
     BOOL frame_committed;
     BOOL committed;
+    CRITICAL_SECTION lock;
 } PngEncoder;
 
 static inline PngEncoder *encoder_from_frame(IWICBitmapFrameEncode *iface)
@@ -800,10 +851,18 @@ static HRESULT WINAPI PngFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
     PngEncoder *This = encoder_from_frame(iface);
     TRACE("(%p,%p)\n", iface, pIEncoderOptions);
 
-    if (This->frame_initialized) return WINCODEC_ERR_WRONGSTATE;
+    EnterCriticalSection(&This->lock);
+
+    if (This->frame_initialized)
+    {
+        LeaveCriticalSection(&This->lock);
+        return WINCODEC_ERR_WRONGSTATE;
+    }
 
     This->frame_initialized = TRUE;
 
+    LeaveCriticalSection(&This->lock);
+
     return S_OK;
 }
 
@@ -813,11 +872,19 @@ static HRESULT WINAPI PngFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
     PngEncoder *This = encoder_from_frame(iface);
     TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
 
-    if (!This->frame_initialized || This->info_written) return WINCODEC_ERR_WRONGSTATE;
+    EnterCriticalSection(&This->lock);
+
+    if (!This->frame_initialized || This->info_written)
+    {
+        LeaveCriticalSection(&This->lock);
+        return WINCODEC_ERR_WRONGSTATE;
+    }
 
     This->width = uiWidth;
     This->height = uiHeight;
 
+    LeaveCriticalSection(&This->lock);
+
     return S_OK;
 }
 
@@ -827,11 +894,19 @@ static HRESULT WINAPI PngFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
     PngEncoder *This = encoder_from_frame(iface);
     TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
 
-    if (!This->frame_initialized || This->info_written) return WINCODEC_ERR_WRONGSTATE;
+    EnterCriticalSection(&This->lock);
+
+    if (!This->frame_initialized || This->info_written)
+    {
+        LeaveCriticalSection(&This->lock);
+        return WINCODEC_ERR_WRONGSTATE;
+    }
 
     This->xres = dpiX;
     This->yres = dpiY;
 
+    LeaveCriticalSection(&This->lock);
+
     return S_OK;
 }
 
@@ -842,7 +917,13 @@ static HRESULT WINAPI PngFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface
     int i;
     TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
 
-    if (!This->frame_initialized || This->info_written) return WINCODEC_ERR_WRONGSTATE;
+    EnterCriticalSection(&This->lock);
+
+    if (!This->frame_initialized || This->info_written)
+    {
+        LeaveCriticalSection(&This->lock);
+        return WINCODEC_ERR_WRONGSTATE;
+    }
 
     for (i=0; formats[i].guid; i++)
     {
@@ -855,6 +936,8 @@ static HRESULT WINAPI PngFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface
     This->format = &formats[i];
     memcpy(pPixelFormat, This->format->guid, sizeof(GUID));
 
+    LeaveCriticalSection(&This->lock);
+
     return S_OK;
 }
 
@@ -888,15 +971,24 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
     jmp_buf jmpbuf;
     TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
 
+    EnterCriticalSection(&This->lock);
+
     if (!This->frame_initialized || !This->width || !This->height || !This->format)
+    {
+        LeaveCriticalSection(&This->lock);
         return WINCODEC_ERR_WRONGSTATE;
+    }
 
     if (lineCount == 0 || lineCount + This->lines_written > This->height)
+    {
+        LeaveCriticalSection(&This->lock);
         return E_INVALIDARG;
+    }
 
     /* set up setjmp/longjmp error handling */
     if (setjmp(jmpbuf))
     {
+        LeaveCriticalSection(&This->lock);
         HeapFree(GetProcessHeap(), 0, row_pointers);
         return E_FAIL;
     }
@@ -927,7 +1019,10 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
 
     row_pointers = HeapAlloc(GetProcessHeap(), 0, lineCount * sizeof(png_byte*));
     if (!row_pointers)
+    {
+        LeaveCriticalSection(&This->lock);
         return E_OUTOFMEMORY;
+    }
 
     for (i=0; i<lineCount; i++)
         row_pointers[i] = pbPixels + cbStride * i;
@@ -935,6 +1030,8 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
     ppng_write_rows(This->png_ptr, row_pointers, lineCount);
     This->lines_written += lineCount;
 
+    LeaveCriticalSection(&This->lock);
+
     HeapFree(GetProcessHeap(), 0, row_pointers);
 
     return S_OK;
@@ -1019,12 +1116,18 @@ static HRESULT WINAPI PngFrameEncode_Commit(IWICBitmapFrameEncode *iface)
     jmp_buf jmpbuf;
     TRACE("(%p)\n", iface);
 
+    EnterCriticalSection(&This->lock);
+
     if (!This->info_written || This->lines_written != This->height || This->frame_committed)
+    {
+        LeaveCriticalSection(&This->lock);
         return WINCODEC_ERR_WRONGSTATE;
+    }
 
     /* set up setjmp/longjmp error handling */
     if (setjmp(jmpbuf))
     {
+        LeaveCriticalSection(&This->lock);
         return E_FAIL;
     }
     ppng_set_error_fn(This->png_ptr, &jmpbuf, user_error_fn, user_warning_fn);
@@ -1033,6 +1136,8 @@ static HRESULT WINAPI PngFrameEncode_Commit(IWICBitmapFrameEncode *iface)
 
     This->frame_committed = TRUE;
 
+    LeaveCriticalSection(&This->lock);
+
     return S_OK;
 }
 
@@ -1102,6 +1207,8 @@ static ULONG WINAPI PngEncoder_Release(IWICBitmapEncoder *iface)
 
     if (ref == 0)
     {
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
         if (This->png_ptr)
             ppng_destroy_write_struct(&This->png_ptr, &This->info_ptr);
         if (This->stream)
@@ -1137,19 +1244,28 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface,
 
     TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
 
+    EnterCriticalSection(&This->lock);
+
     if (This->png_ptr)
+    {
+        LeaveCriticalSection(&This->lock);
         return WINCODEC_ERR_WRONGSTATE;
+    }
 
     /* initialize libpng */
     This->png_ptr = ppng_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
     if (!This->png_ptr)
+    {
+        LeaveCriticalSection(&This->lock);
         return E_FAIL;
+    }
 
     This->info_ptr = ppng_create_info_struct(This->png_ptr);
     if (!This->info_ptr)
     {
         ppng_destroy_write_struct(&This->png_ptr, NULL);
         This->png_ptr = NULL;
+        LeaveCriticalSection(&This->lock);
         return E_FAIL;
     }
 
@@ -1163,6 +1279,7 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface,
         This->png_ptr = NULL;
         IStream_Release(This->stream);
         This->stream = NULL;
+        LeaveCriticalSection(&This->lock);
         return E_FAIL;
     }
     ppng_set_error_fn(This->png_ptr, &jmpbuf, user_error_fn, user_warning_fn);
@@ -1170,6 +1287,8 @@ static HRESULT WINAPI PngEncoder_Initialize(IWICBitmapEncoder *iface,
     /* set up custom i/o handling */
     ppng_set_write_fn(This->png_ptr, This, user_write_data, user_flush);
 
+    LeaveCriticalSection(&This->lock);
+
     return S_OK;
 }
 
@@ -1219,17 +1338,31 @@ static HRESULT WINAPI PngEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
     HRESULT hr;
     TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
 
+    EnterCriticalSection(&This->lock);
+
     if (This->frame_count != 0)
+    {
+        LeaveCriticalSection(&This->lock);
         return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+    }
 
     if (!This->stream)
+    {
+        LeaveCriticalSection(&This->lock);
         return WINCODEC_ERR_NOTINITIALIZED;
+    }
 
     hr = CreatePropertyBag2(ppIEncoderOptions);
-    if (FAILED(hr)) return hr;
+    if (FAILED(hr))
+    {
+        LeaveCriticalSection(&This->lock);
+        return hr;
+    }
 
     This->frame_count = 1;
 
+    LeaveCriticalSection(&This->lock);
+
     IWICBitmapEncoder_AddRef(iface);
     *ppIFrameEncode = (IWICBitmapFrameEncode*)&This->lpFrameVtbl;
 
@@ -1241,11 +1374,18 @@ static HRESULT WINAPI PngEncoder_Commit(IWICBitmapEncoder *iface)
     PngEncoder *This = (PngEncoder*)iface;
     TRACE("(%p)\n", iface);
 
+    EnterCriticalSection(&This->lock);
+
     if (!This->frame_committed || This->committed)
+    {
+        LeaveCriticalSection(&This->lock);
         return WINCODEC_ERR_WRONGSTATE;
+    }
 
     This->committed = TRUE;
 
+    EnterCriticalSection(&This->lock);
+
     return S_OK;
 }
 
@@ -1309,6 +1449,8 @@ HRESULT PngEncoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
     This->lines_written = 0;
     This->frame_committed = FALSE;
     This->committed = FALSE;
+    InitializeCriticalSection(&This->lock);
+    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PngEncoder.lock");
 
     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
     IUnknown_Release((IUnknown*)This);
index c87aa4b..c5828a6 100644 (file)
@@ -727,25 +727,25 @@ static struct regsvr_coclass const coclass_list[] = {
        "WIC Imaging Factory",
        NULL,
        "windowscodecs.dll",
-       "Apartment"
+       "Both"
     },
     {   &CLSID_WICBmpDecoder,
        "WIC BMP Decoder",
        NULL,
        "windowscodecs.dll",
-       "Apartment"
+       "Both"
     },
     {   &CLSID_WICPngDecoder,
        "WIC PNG Decoder",
        NULL,
        "windowscodecs.dll",
-       "Apartment"
+       "Both"
     },
     {   &CLSID_WICPngEncoder,
        "WIC PNG Encoder",
        NULL,
        "windowscodecs.dll",
-       "Apartment"
+       "Both"
     },
     {   &CLSID_WICBmpEncoder,
        "WIC BMP Encoder",
@@ -757,25 +757,31 @@ static struct regsvr_coclass const coclass_list[] = {
        "WIC GIF Decoder",
        NULL,
        "windowscodecs.dll",
-       "Apartment"
+       "Both"
     },
     {   &CLSID_WICIcoDecoder,
        "WIC ICO Decoder",
        NULL,
        "windowscodecs.dll",
-       "Apartment"
+       "Both"
     },
     {   &CLSID_WICJpegDecoder,
        "WIC JPEG Decoder",
        NULL,
        "windowscodecs.dll",
-       "Apartment"
+       "Both"
+    },
+    {   &CLSID_WICTiffDecoder,
+       "WIC TIFF Decoder",
+       NULL,
+       "windowscodecs.dll",
+       "Both"
     },
     {   &CLSID_WICDefaultFormatConverter,
        "WIC Default Format Converter",
        NULL,
        "windowscodecs.dll",
-       "Apartment"
+       "Both"
     },
     { NULL }                   /* list terminator */
 };
@@ -868,6 +874,27 @@ static struct decoder_pattern const png_patterns[] = {
     {0}
 };
 
+static const BYTE tiff_magic_le[] = {0x49,0x49,42,0};
+static const BYTE tiff_magic_be[] = {0x4d,0x4d,0,42};
+
+static GUID const * const tiff_formats[] = {
+    &GUID_WICPixelFormatBlackWhite,
+    &GUID_WICPixelFormat4bppGray,
+    &GUID_WICPixelFormat8bppGray,
+    &GUID_WICPixelFormat4bppIndexed,
+    &GUID_WICPixelFormat8bppIndexed,
+    &GUID_WICPixelFormat32bppBGR,
+    &GUID_WICPixelFormat32bppBGRA,
+    &GUID_WICPixelFormat32bppPBGRA,
+    NULL
+};
+
+static struct decoder_pattern const tiff_patterns[] = {
+    {4,0,tiff_magic_le,mask_all,0},
+    {4,0,tiff_magic_be,mask_all,0},
+    {0}
+};
+
 static struct regsvr_decoder const decoder_list[] = {
     {   &CLSID_WICBmpDecoder,
        "The Wine Project",
@@ -919,6 +946,16 @@ static struct regsvr_decoder const decoder_list[] = {
        png_formats,
        png_patterns
     },
+    {   &CLSID_WICTiffDecoder,
+       "The Wine Project",
+       "TIFF Decoder",
+       "1.0.0.0",
+       &GUID_VendorMicrosoft,
+       "image/tiff",
+       ".tif;.tiff",
+       tiff_formats,
+       tiff_patterns
+    },
     { NULL }                   /* list terminator */
 };
 
index c59a9d2..bd5592b 100644 (file)
@@ -41,6 +41,8 @@ typedef struct StreamOnMemory {
     BYTE *pbMemory;
     DWORD dwMemsize;
     DWORD dwCurPos;
+
+    CRITICAL_SECTION lock; /* must be held when pbMemory or dwCurPos is accessed */
 } StreamOnMemory;
 
 static HRESULT WINAPI StreamOnMemory_QueryInterface(IStream *iface,
@@ -82,6 +84,8 @@ static ULONG WINAPI StreamOnMemory_Release(IStream *iface)
     TRACE("(%p) refcount=%u\n", iface, ref);
 
     if (ref == 0) {
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
         HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
@@ -96,9 +100,12 @@ static HRESULT WINAPI StreamOnMemory_Read(IStream *iface,
 
     if (!pv) return E_INVALIDARG;
 
+    EnterCriticalSection(&This->lock);
     uBytesRead = min(cb, This->dwMemsize - This->dwCurPos);
     memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead);
     This->dwCurPos += uBytesRead;
+    LeaveCriticalSection(&This->lock);
+
     if (pcbRead) *pcbRead = uBytesRead;
 
     return S_OK;
@@ -108,18 +115,24 @@ static HRESULT WINAPI StreamOnMemory_Write(IStream *iface,
     void const *pv, ULONG cb, ULONG *pcbWritten)
 {
     StreamOnMemory *This = (StreamOnMemory*)iface;
+    HRESULT hr;
     TRACE("(%p)\n", This);
 
     if (!pv) return E_INVALIDARG;
 
-    if (cb > This->dwMemsize - This->dwCurPos) return STG_E_MEDIUMFULL;
-    if (cb) {
+    EnterCriticalSection(&This->lock);
+    if (cb > This->dwMemsize - This->dwCurPos) {
+        hr = STG_E_MEDIUMFULL;
+    }
+    else {
         memcpy(This->pbMemory + This->dwCurPos, pv, cb);
         This->dwCurPos += cb;
+        hr = S_OK;
+        if (pcbWritten) *pcbWritten = cb;
     }
-    if (pcbWritten) *pcbWritten = cb;
+    LeaveCriticalSection(&This->lock);
 
-    return S_OK;
+    return hr;
 }
 
 static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface,
@@ -127,20 +140,29 @@ static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface,
 {
     StreamOnMemory *This = (StreamOnMemory*)iface;
     LARGE_INTEGER NewPosition;
+    HRESULT hr=S_OK;
     TRACE("(%p)\n", This);
 
+    EnterCriticalSection(&This->lock);
     if (dwOrigin == STREAM_SEEK_SET) NewPosition.QuadPart = dlibMove.QuadPart;
     else if (dwOrigin == STREAM_SEEK_CUR) NewPosition.QuadPart = This->dwCurPos + dlibMove.QuadPart;
     else if (dwOrigin == STREAM_SEEK_END) NewPosition.QuadPart = This->dwMemsize + dlibMove.QuadPart;
-    else return E_INVALIDARG;
+    else hr = E_INVALIDARG;
 
-    if (NewPosition.u.HighPart) return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
-    if (NewPosition.QuadPart > This->dwMemsize) return E_INVALIDARG;
-    if (NewPosition.QuadPart < 0) return E_INVALIDARG;
-    This->dwCurPos = NewPosition.u.LowPart;
+    if (SUCCEEDED(hr)) {
+        if (NewPosition.u.HighPart) hr = HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
+        else if (NewPosition.QuadPart > This->dwMemsize) hr = E_INVALIDARG;
+        else if (NewPosition.QuadPart < 0) hr = E_INVALIDARG;
+    }
 
-    if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos;
-    return S_OK;
+    if (SUCCEEDED(hr)) {
+        This->dwCurPos = NewPosition.u.LowPart;
+
+        if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos;
+    }
+    LeaveCriticalSection(&This->lock);
+
+    return hr;
 }
 
 /* SetSize isn't implemented in the native windowscodecs DLL either */
@@ -450,8 +472,16 @@ static HRESULT WINAPI IWICStreamImpl_InitializeFromMemory(IWICStream *iface,
     pObject->pbMemory = pbBuffer;
     pObject->dwMemsize = cbBufferSize;
     pObject->dwCurPos = 0;
+    InitializeCriticalSection(&pObject->lock);
+    pObject->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": StreamOnMemory.lock");
+
+    if (InterlockedCompareExchangePointer((void**)&This->pStream, pObject, NULL))
+    {
+        /* Some other thread set the stream first. */
+        IStream_Release((IStream*)pObject);
+        return WINCODEC_ERR_WRONGSTATE;
+    }
 
-    This->pStream = (IStream*)pObject;
     return S_OK;
 }
 
diff --git a/reactos/dll/win32/windowscodecs/tiffformat.c b/reactos/dll/win32/windowscodecs/tiffformat.c
new file mode 100644 (file)
index 0000000..fe87ddd
--- /dev/null
@@ -0,0 +1,866 @@
+/*
+ * Copyright 2010 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_TIFFIO_H
+#include <tiffio.h>
+#endif
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "wincodec.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+#include "wine/library.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+#ifdef SONAME_LIBTIFF
+
+static CRITICAL_SECTION init_tiff_cs;
+static CRITICAL_SECTION_DEBUG init_tiff_cs_debug =
+{
+    0, 0, &init_tiff_cs,
+    { &init_tiff_cs_debug.ProcessLocksList,
+      &init_tiff_cs_debug.ProcessLocksList },
+    0, 0, { (DWORD_PTR)(__FILE__ ": init_tiff_cs") }
+};
+static CRITICAL_SECTION init_tiff_cs = { &init_tiff_cs_debug, -1, 0, 0, 0, 0 };
+
+static void *libtiff_handle;
+#define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(TIFFClientOpen);
+MAKE_FUNCPTR(TIFFClose);
+MAKE_FUNCPTR(TIFFCurrentDirectory);
+MAKE_FUNCPTR(TIFFGetField);
+MAKE_FUNCPTR(TIFFReadDirectory);
+MAKE_FUNCPTR(TIFFReadEncodedStrip);
+MAKE_FUNCPTR(TIFFSetDirectory);
+#undef MAKE_FUNCPTR
+
+static void *load_libtiff(void)
+{
+    void *result;
+
+    EnterCriticalSection(&init_tiff_cs);
+
+    if (!libtiff_handle &&
+        (libtiff_handle = wine_dlopen(SONAME_LIBTIFF, RTLD_NOW, NULL, 0)) != NULL)
+    {
+
+#define LOAD_FUNCPTR(f) \
+    if((p##f = wine_dlsym(libtiff_handle, #f, NULL, 0)) == NULL) { \
+        ERR("failed to load symbol %s\n", #f); \
+        libtiff_handle = NULL; \
+        LeaveCriticalSection(&init_tiff_cs); \
+        return NULL; \
+    }
+        LOAD_FUNCPTR(TIFFClientOpen);
+        LOAD_FUNCPTR(TIFFClose);
+        LOAD_FUNCPTR(TIFFCurrentDirectory);
+        LOAD_FUNCPTR(TIFFGetField);
+        LOAD_FUNCPTR(TIFFReadDirectory);
+        LOAD_FUNCPTR(TIFFReadEncodedStrip);
+        LOAD_FUNCPTR(TIFFSetDirectory);
+#undef LOAD_FUNCPTR
+
+    }
+
+    result = libtiff_handle;
+
+    LeaveCriticalSection(&init_tiff_cs);
+    return result;
+}
+
+static tsize_t tiff_stream_read(thandle_t client_data, tdata_t data, tsize_t size)
+{
+    IStream *stream = (IStream*)client_data;
+    ULONG bytes_read;
+    HRESULT hr;
+
+    hr = IStream_Read(stream, data, size, &bytes_read);
+    if (FAILED(hr)) bytes_read = 0;
+    return bytes_read;
+}
+
+static tsize_t tiff_stream_write(thandle_t client_data, tdata_t data, tsize_t size)
+{
+    IStream *stream = (IStream*)client_data;
+    ULONG bytes_written;
+    HRESULT hr;
+
+    hr = IStream_Write(stream, data, size, &bytes_written);
+    if (FAILED(hr)) bytes_written = 0;
+    return bytes_written;
+}
+
+static toff_t tiff_stream_seek(thandle_t client_data, toff_t offset, int whence)
+{
+    IStream *stream = (IStream*)client_data;
+    LARGE_INTEGER move;
+    DWORD origin;
+    ULARGE_INTEGER new_position;
+    HRESULT hr;
+
+    move.QuadPart = offset;
+    switch (whence)
+    {
+        case SEEK_SET:
+            origin = STREAM_SEEK_SET;
+            break;
+        case SEEK_CUR:
+            origin = STREAM_SEEK_CUR;
+            break;
+        case SEEK_END:
+            origin = STREAM_SEEK_END;
+            break;
+        default:
+            ERR("unknown whence value %i\n", whence);
+            return -1;
+    }
+
+    hr = IStream_Seek(stream, move, origin, &new_position);
+    if (SUCCEEDED(hr)) return new_position.QuadPart;
+    else return -1;
+}
+
+static int tiff_stream_close(thandle_t client_data)
+{
+    /* Caller is responsible for releasing the stream object. */
+    return 0;
+}
+
+static toff_t tiff_stream_size(thandle_t client_data)
+{
+    IStream *stream = (IStream*)client_data;
+    STATSTG statstg;
+    HRESULT hr;
+
+    hr = IStream_Stat(stream, &statstg, STATFLAG_NONAME);
+
+    if (SUCCEEDED(hr)) return statstg.cbSize.QuadPart;
+    else return -1;
+}
+
+static int tiff_stream_map(thandle_t client_data, tdata_t *addr, toff_t *size)
+{
+    /* Cannot mmap streams */
+    return 0;
+}
+
+static void tiff_stream_unmap(thandle_t client_data, tdata_t addr, toff_t size)
+{
+    /* No need to ever do this, since we can't map things. */
+}
+
+static TIFF* tiff_open_stream(IStream *stream, const char *mode)
+{
+    return pTIFFClientOpen("<IStream object>", mode, stream, tiff_stream_read,
+        tiff_stream_write, tiff_stream_seek, tiff_stream_close,
+        tiff_stream_size, tiff_stream_map, tiff_stream_unmap);
+}
+
+typedef struct {
+    const IWICBitmapDecoderVtbl *lpVtbl;
+    LONG ref;
+    IStream *stream;
+    CRITICAL_SECTION lock; /* Must be held when tiff is used or initiailzed is set */
+    TIFF *tiff;
+    BOOL initialized;
+} TiffDecoder;
+
+typedef struct {
+    const WICPixelFormatGUID *format;
+    int bpp;
+    int indexed;
+    int reverse_bgr;
+    UINT width, height;
+    UINT tile_width, tile_height;
+    UINT tile_stride;
+    UINT tile_size;
+} tiff_decode_info;
+
+typedef struct {
+    const IWICBitmapFrameDecodeVtbl *lpVtbl;
+    LONG ref;
+    TiffDecoder *parent;
+    UINT index;
+    tiff_decode_info decode_info;
+    INT cached_tile_x, cached_tile_y;
+    BYTE *cached_tile;
+} TiffFrameDecode;
+
+static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl;
+
+static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info)
+{
+    uint16 photometric, bps, samples, planar;
+    int ret;
+
+    decode_info->indexed = 0;
+    decode_info->reverse_bgr = 0;
+
+    ret = pTIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
+    if (!ret)
+    {
+        WARN("missing PhotometricInterpretation tag\n");
+        return E_FAIL;
+    }
+
+    ret = pTIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bps);
+    if (!ret) bps = 1;
+
+    switch(photometric)
+    {
+    case 1: /* BlackIsZero */
+        decode_info->bpp = bps;
+        switch (bps)
+        {
+        case 1:
+            decode_info->format = &GUID_WICPixelFormatBlackWhite;
+            break;
+        case 4:
+            decode_info->format = &GUID_WICPixelFormat4bppGray;
+            break;
+        case 8:
+            decode_info->format = &GUID_WICPixelFormat8bppGray;
+            break;
+        default:
+            FIXME("unhandled greyscale bit count %u\n", bps);
+            return E_FAIL;
+        }
+        break;
+    case 2: /* RGB */
+        if (bps != 8)
+        {
+            FIXME("unhandled RGB bit count %u\n", bps);
+            return E_FAIL;
+        }
+        ret = pTIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples);
+        if (samples != 3)
+        {
+            FIXME("unhandled RGB sample count %u\n", samples);
+            return E_FAIL;
+        }
+        ret = pTIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &planar);
+        if (!ret) planar = 1;
+        if (planar != 1)
+        {
+            FIXME("unhandled planar configuration %u\n", planar);
+            return E_FAIL;
+        }
+        decode_info->bpp = bps * samples;
+        decode_info->reverse_bgr = 1;
+        decode_info->format = &GUID_WICPixelFormat24bppBGR;
+        break;
+    case 3: /* RGB Palette */
+        decode_info->indexed = 1;
+        decode_info->bpp = bps;
+        switch (bps)
+        {
+        case 4:
+            decode_info->format = &GUID_WICPixelFormat4bppIndexed;
+            break;
+        case 8:
+            decode_info->format = &GUID_WICPixelFormat8bppIndexed;
+            break;
+        default:
+            FIXME("unhandled indexed bit count %u\n", bps);
+            return E_FAIL;
+        }
+        break;
+    case 0: /* WhiteIsZero */
+    case 4: /* Transparency mask */
+    case 5: /* CMYK */
+    case 6: /* YCbCr */
+    case 8: /* CIELab */
+    default:
+        FIXME("unhandled PhotometricInterpretation %u\n", photometric);
+        return E_FAIL;
+    }
+
+    ret = pTIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &decode_info->width);
+    if (!ret)
+    {
+        WARN("missing image width\n");
+        return E_FAIL;
+    }
+
+    ret = pTIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &decode_info->height);
+    if (!ret)
+    {
+        WARN("missing image length\n");
+        return E_FAIL;
+    }
+
+    ret = pTIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &decode_info->tile_height);
+    if (ret)
+    {
+        decode_info->tile_width = decode_info->width;
+        decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
+        decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
+    }
+    else
+    {
+        /* Probably a tiled image */
+        FIXME("missing RowsPerStrip value\n");
+        return E_FAIL;
+    }
+
+    return S_OK;
+}
+
+static HRESULT WINAPI TiffDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
+    void **ppv)
+{
+    TiffDecoder *This = (TiffDecoder*)iface;
+    TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+    if (!ppv) return E_INVALIDARG;
+
+    if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
+    {
+        *ppv = This;
+    }
+    else
+    {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IUnknown_AddRef((IUnknown*)*ppv);
+    return S_OK;
+}
+
+static ULONG WINAPI TiffDecoder_AddRef(IWICBitmapDecoder *iface)
+{
+    TiffDecoder *This = (TiffDecoder*)iface;
+    ULONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p) refcount=%u\n", iface, ref);
+
+    return ref;
+}
+
+static ULONG WINAPI TiffDecoder_Release(IWICBitmapDecoder *iface)
+{
+    TiffDecoder *This = (TiffDecoder*)iface;
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) refcount=%u\n", iface, ref);
+
+    if (ref == 0)
+    {
+        if (This->tiff) pTIFFClose(This->tiff);
+        if (This->stream) IStream_Release(This->stream);
+        This->lock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&This->lock);
+        HeapFree(GetProcessHeap(), 0, This);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI TiffDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
+    DWORD *pdwCapability)
+{
+    FIXME("(%p,%p,%p): stub\n", iface, pIStream, pdwCapability);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TiffDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
+    WICDecodeOptions cacheOptions)
+{
+    TiffDecoder *This = (TiffDecoder*)iface;
+    TIFF *tiff;
+    HRESULT hr=S_OK;
+
+    TRACE("(%p,%p,%x): stub\n", iface, pIStream, cacheOptions);
+
+    EnterCriticalSection(&This->lock);
+
+    if (This->initialized)
+    {
+        hr = WINCODEC_ERR_WRONGSTATE;
+        goto exit;
+    }
+
+    tiff = tiff_open_stream(pIStream, "r");
+
+    if (!tiff)
+    {
+        hr = E_FAIL;
+        goto exit;
+    }
+
+    This->tiff = tiff;
+    This->stream = pIStream;
+    IStream_AddRef(pIStream);
+    This->initialized = TRUE;
+
+exit:
+    LeaveCriticalSection(&This->lock);
+    return hr;
+}
+
+static HRESULT WINAPI TiffDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
+    GUID *pguidContainerFormat)
+{
+    memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID));
+    return S_OK;
+}
+
+static HRESULT WINAPI TiffDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
+    IWICBitmapDecoderInfo **ppIDecoderInfo)
+{
+    FIXME("(%p,%p): stub\n", iface, ppIDecoderInfo);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface,
+    IWICPalette *pIPalette)
+{
+    FIXME("(%p,%p): stub\n", iface, pIPalette);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
+    IWICMetadataQueryReader **ppIMetadataQueryReader)
+{
+    FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TiffDecoder_GetPreview(IWICBitmapDecoder *iface,
+    IWICBitmapSource **ppIBitmapSource)
+{
+    FIXME("(%p,%p): stub\n", iface, ppIBitmapSource);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TiffDecoder_GetColorContexts(IWICBitmapDecoder *iface,
+    UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+    FIXME("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TiffDecoder_GetThumbnail(IWICBitmapDecoder *iface,
+    IWICBitmapSource **ppIThumbnail)
+{
+    TRACE("(%p,%p)\n", iface, ppIThumbnail);
+    return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static HRESULT WINAPI TiffDecoder_GetFrameCount(IWICBitmapDecoder *iface,
+    UINT *pCount)
+{
+    TiffDecoder *This = (TiffDecoder*)iface;
+
+    if (!This->tiff)
+    {
+        WARN("(%p) <-- WINCODEC_ERR_WRONGSTATE\n", iface);
+        return WINCODEC_ERR_WRONGSTATE;
+    }
+
+    EnterCriticalSection(&This->lock);
+    while (pTIFFReadDirectory(This->tiff)) { }
+    *pCount = pTIFFCurrentDirectory(This->tiff)+1;
+    LeaveCriticalSection(&This->lock);
+
+    TRACE("(%p) <-- %i\n", iface, *pCount);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI TiffDecoder_GetFrame(IWICBitmapDecoder *iface,
+    UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
+{
+    TiffDecoder *This = (TiffDecoder*)iface;
+    TiffFrameDecode *result;
+    int res;
+    tiff_decode_info decode_info;
+    HRESULT hr;
+
+    TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
+
+    if (!This->tiff)
+        return WINCODEC_ERR_WRONGSTATE;
+
+    EnterCriticalSection(&This->lock);
+    res = pTIFFSetDirectory(This->tiff, index);
+    if (!res) hr = E_INVALIDARG;
+    else hr = tiff_get_decode_info(This->tiff, &decode_info);
+    LeaveCriticalSection(&This->lock);
+
+    if (SUCCEEDED(hr))
+    {
+        result = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffFrameDecode));
+
+        if (result)
+        {
+            result->lpVtbl = &TiffFrameDecode_Vtbl;
+            result->ref = 1;
+            result->parent = This;
+            result->index = index;
+            result->decode_info = decode_info;
+            result->cached_tile_x = -1;
+            result->cached_tile = HeapAlloc(GetProcessHeap(), 0, decode_info.tile_size);
+
+            if (result->cached_tile)
+                *ppIBitmapFrame = (IWICBitmapFrameDecode*)result;
+            else
+            {
+                hr = E_OUTOFMEMORY;
+                HeapFree(GetProcessHeap(), 0, result);
+            }
+        }
+        else hr = E_OUTOFMEMORY;
+    }
+
+    if (FAILED(hr)) *ppIBitmapFrame = NULL;
+
+    return hr;
+}
+
+static const IWICBitmapDecoderVtbl TiffDecoder_Vtbl = {
+    TiffDecoder_QueryInterface,
+    TiffDecoder_AddRef,
+    TiffDecoder_Release,
+    TiffDecoder_QueryCapability,
+    TiffDecoder_Initialize,
+    TiffDecoder_GetContainerFormat,
+    TiffDecoder_GetDecoderInfo,
+    TiffDecoder_CopyPalette,
+    TiffDecoder_GetMetadataQueryReader,
+    TiffDecoder_GetPreview,
+    TiffDecoder_GetColorContexts,
+    TiffDecoder_GetThumbnail,
+    TiffDecoder_GetFrameCount,
+    TiffDecoder_GetFrame
+};
+
+static HRESULT WINAPI TiffFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
+    void **ppv)
+{
+    TiffFrameDecode *This = (TiffFrameDecode*)iface;
+    TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+    if (!ppv) return E_INVALIDARG;
+
+    if (IsEqualIID(&IID_IUnknown, iid) ||
+        IsEqualIID(&IID_IWICBitmapSource, iid) ||
+        IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
+    {
+        *ppv = This;
+    }
+    else
+    {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IUnknown_AddRef((IUnknown*)*ppv);
+    return S_OK;
+}
+
+static ULONG WINAPI TiffFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
+{
+    TiffFrameDecode *This = (TiffFrameDecode*)iface;
+    ULONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p) refcount=%u\n", iface, ref);
+
+    return ref;
+}
+
+static ULONG WINAPI TiffFrameDecode_Release(IWICBitmapFrameDecode *iface)
+{
+    TiffFrameDecode *This = (TiffFrameDecode*)iface;
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) refcount=%u\n", iface, ref);
+
+    if (ref == 0)
+    {
+        HeapFree(GetProcessHeap(), 0, This->cached_tile);
+        HeapFree(GetProcessHeap(), 0, This);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI TiffFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
+    UINT *puiWidth, UINT *puiHeight)
+{
+    TiffFrameDecode *This = (TiffFrameDecode*)iface;
+
+    *puiWidth = This->decode_info.width;
+    *puiHeight = This->decode_info.height;
+
+    TRACE("(%p) <-- %ux%u\n", iface, *puiWidth, *puiHeight);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI TiffFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
+    WICPixelFormatGUID *pPixelFormat)
+{
+    TiffFrameDecode *This = (TiffFrameDecode*)iface;
+
+    memcpy(pPixelFormat, This->decode_info.format, sizeof(GUID));
+
+    TRACE("(%p) <-- %s\n", This, debugstr_guid(This->decode_info.format));
+
+    return S_OK;
+}
+
+static HRESULT WINAPI TiffFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
+    double *pDpiX, double *pDpiY)
+{
+    FIXME("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TiffFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
+    IWICPalette *pIPalette)
+{
+    FIXME("(%p,%p)\n", iface, pIPalette);
+    return E_NOTIMPL;
+}
+
+static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT tile_y)
+{
+    HRESULT hr=S_OK;
+    tsize_t ret;
+
+    ret = pTIFFSetDirectory(This->parent->tiff, This->index);
+
+    if (ret == -1)
+        hr = E_FAIL;
+
+    if (hr == S_OK)
+    {
+        ret = pTIFFReadEncodedStrip(This->parent->tiff, tile_y, This->cached_tile, This->decode_info.tile_size);
+
+        if (ret == -1)
+            hr = E_FAIL;
+    }
+
+    if (hr == S_OK && This->decode_info.reverse_bgr)
+    {
+        if (This->decode_info.format == &GUID_WICPixelFormat24bppBGR)
+        {
+            UINT i, total_pixels;
+            BYTE *pixel, temp;
+
+            total_pixels = This->decode_info.tile_width * This->decode_info.tile_height;
+            pixel = This->cached_tile;
+            for (i=0; i<total_pixels; i++)
+            {
+                temp = pixel[2];
+                pixel[2] = pixel[0];
+                pixel[0] = temp;
+                pixel += 3;
+            }
+        }
+    }
+
+    if (hr == S_OK)
+    {
+        This->cached_tile_x = tile_x;
+        This->cached_tile_y = tile_y;
+    }
+
+    return hr;
+}
+
+static HRESULT WINAPI TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
+    const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
+{
+    TiffFrameDecode *This = (TiffFrameDecode*)iface;
+    UINT min_tile_x, max_tile_x, min_tile_y, max_tile_y;
+    UINT tile_x, tile_y;
+    WICRect rc;
+    HRESULT hr=S_OK;
+    BYTE *dst_tilepos;
+    UINT bytesperrow;
+
+    TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
+
+    if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->decode_info.width ||
+        prc->Y+prc->Height > This->decode_info.height)
+        return E_INVALIDARG;
+
+    bytesperrow = ((This->decode_info.bpp * prc->Width)+7)/8;
+
+    if (cbStride < bytesperrow)
+        return E_INVALIDARG;
+
+    if ((cbStride * prc->Height) > cbBufferSize)
+        return E_INVALIDARG;
+
+    min_tile_x = prc->X / This->decode_info.tile_width;
+    min_tile_y = prc->Y / This->decode_info.tile_height;
+    max_tile_x = (prc->X+prc->Width-1) / This->decode_info.tile_width;
+    max_tile_y = (prc->Y+prc->Height-1) / This->decode_info.tile_height;
+
+    EnterCriticalSection(&This->parent->lock);
+
+    for (tile_x=min_tile_x; tile_x <= max_tile_x; tile_x++)
+    {
+        for (tile_y=min_tile_y; tile_y <= max_tile_y; tile_y++)
+        {
+            if (tile_x != This->cached_tile_x || tile_y != This->cached_tile_y)
+            {
+                hr = TiffFrameDecode_ReadTile(This, tile_x, tile_y);
+            }
+
+            if (SUCCEEDED(hr))
+            {
+                if (prc->X < tile_x * This->decode_info.tile_width)
+                    rc.X = 0;
+                else
+                    rc.X = prc->X - tile_x * This->decode_info.tile_width;
+
+                if (prc->Y < tile_y * This->decode_info.tile_height)
+                    rc.Y = 0;
+                else
+                    rc.Y = prc->Y - tile_y * This->decode_info.tile_height;
+
+                if (prc->X+prc->Width > (tile_x+1) * This->decode_info.tile_width)
+                    rc.Width = This->decode_info.tile_width - rc.X;
+                else
+                    rc.Width = prc->Width + rc.X - prc->X;
+
+                if (prc->Y+prc->Height > (tile_y+1) * This->decode_info.tile_height)
+                    rc.Height = This->decode_info.tile_height - rc.Y;
+                else
+                    rc.Height = prc->Height + rc.Y - prc->Y;
+
+                dst_tilepos = pbBuffer + (cbStride * (rc.Y - prc->Y)) +
+                    ((This->decode_info.bpp * (rc.X - prc->X) + 7) / 8);
+
+                hr = copy_pixels(This->decode_info.bpp, This->cached_tile,
+                    This->decode_info.tile_width, This->decode_info.tile_height, This->decode_info.tile_stride,
+                    &rc, cbStride, cbBufferSize, dst_tilepos);
+            }
+
+            if (FAILED(hr))
+            {
+                LeaveCriticalSection(&This->parent->lock);
+                TRACE("<-- 0x%x\n", hr);
+                return hr;
+            }
+        }
+    }
+
+    LeaveCriticalSection(&This->parent->lock);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI TiffFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
+    IWICMetadataQueryReader **ppIMetadataQueryReader)
+{
+    FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TiffFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
+    UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+    FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TiffFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
+    IWICBitmapSource **ppIThumbnail)
+{
+    FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
+    return E_NOTIMPL;
+}
+
+static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl = {
+    TiffFrameDecode_QueryInterface,
+    TiffFrameDecode_AddRef,
+    TiffFrameDecode_Release,
+    TiffFrameDecode_GetSize,
+    TiffFrameDecode_GetPixelFormat,
+    TiffFrameDecode_GetResolution,
+    TiffFrameDecode_CopyPalette,
+    TiffFrameDecode_CopyPixels,
+    TiffFrameDecode_GetMetadataQueryReader,
+    TiffFrameDecode_GetColorContexts,
+    TiffFrameDecode_GetThumbnail
+};
+
+HRESULT TiffDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+{
+    HRESULT ret;
+    TiffDecoder *This;
+
+    TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
+
+    *ppv = NULL;
+
+    if (pUnkOuter) return CLASS_E_NOAGGREGATION;
+
+    if (!load_libtiff())
+    {
+        ERR("Failed reading TIFF because unable to load %s\n",SONAME_LIBTIFF);
+        return E_FAIL;
+    }
+
+    This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffDecoder));
+    if (!This) return E_OUTOFMEMORY;
+
+    This->lpVtbl = &TiffDecoder_Vtbl;
+    This->ref = 1;
+    This->stream = NULL;
+    InitializeCriticalSection(&This->lock);
+    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffDecoder.lock");
+    This->tiff = NULL;
+    This->initialized = FALSE;
+
+    ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
+    IUnknown_Release((IUnknown*)This);
+
+    return ret;
+}
+
+#else /* !SONAME_LIBTIFF */
+
+HRESULT TiffDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+{
+    ERR("Trying to load TIFF picture, but Wine was compiled without TIFF support.\n");
+    return E_FAIL;
+}
+
+#endif
index 632f822..0e72793 100644 (file)
@@ -28,6 +28,7 @@ extern HRESULT BmpEncoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void**
 extern HRESULT GifDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void** ppv);
 extern HRESULT IcoDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv);
 extern HRESULT JpegDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv);
+extern HRESULT TiffDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv);
 
 extern HRESULT PaletteImpl_Create(IWICPalette **palette);
 extern HRESULT StreamImpl_Create(IWICStream **stream);
index 563a7a9..da8e3e4 100644 (file)
@@ -28,6 +28,7 @@
        <file>propertybag.c</file>
        <file>regsvr.c</file>
        <file>stream.c</file>
+       <file>tiffformat.c</file>
        <file>ungif.c</file>
 
        <file>version.rc</file>
index f4b8a0a..6fc8a21 100644 (file)
@@ -102,8 +102,8 @@ static CRITICAL_SECTION_DEBUG WININET_cs_debug =
 static CRITICAL_SECTION WININET_cs = { &WININET_cs_debug, -1, 0, 0, 0, 0 };
 
 static object_header_t **WININET_Handles;
-static UINT WININET_dwNextHandle;
-static UINT WININET_dwMaxHandles;
+static UINT_PTR WININET_dwNextHandle;
+static UINT_PTR WININET_dwMaxHandles;
 
 typedef struct
 {
@@ -122,7 +122,7 @@ static const WCHAR szProxyEnable[] = { 'P','r','o','x','y','E','n','a','b','l','
 HINTERNET WININET_AllocHandle( object_header_t *info )
 {
     object_header_t **p;
-    UINT handle = 0, num;
+    UINT_PTR handle = 0, num;
 
     list_init( &info->children );
 
@@ -173,7 +173,7 @@ object_header_t *WININET_AddRef( object_header_t *info )
 object_header_t *WININET_GetObject( HINTERNET hinternet )
 {
     object_header_t *info = NULL;
-    UINT handle = (UINT) hinternet;
+    UINT_PTR handle = (UINT_PTR) hinternet;
 
     EnterCriticalSection( &WININET_cs );
 
@@ -183,7 +183,7 @@ object_header_t *WININET_GetObject( HINTERNET hinternet )
 
     LeaveCriticalSection( &WININET_cs );
 
-    TRACE("handle %d -> %p\n", handle, info);
+    TRACE("handle %ld -> %p\n", handle, info);
 
     return info;
 }
@@ -218,7 +218,7 @@ BOOL WININET_Release( object_header_t *info )
 BOOL WININET_FreeHandle( HINTERNET hinternet )
 {
     BOOL ret = FALSE;
-    UINT handle = (UINT) hinternet;
+    UINT_PTR handle = (UINT_PTR) hinternet;
     object_header_t *info = NULL, *child, *next;
 
     EnterCriticalSection( &WININET_cs );
@@ -229,7 +229,7 @@ BOOL WININET_FreeHandle( HINTERNET hinternet )
         if( WININET_Handles[handle] )
         {
             info = WININET_Handles[handle];
-            TRACE( "destroying handle %d for object %p\n", handle+1, info);
+            TRACE( "destroying handle %ld for object %p\n", handle+1, info);
             WININET_Handles[handle] = NULL;
             ret = TRUE;
         }
@@ -245,8 +245,8 @@ BOOL WININET_FreeHandle( HINTERNET hinternet )
         /* Free all children as native does */
         LIST_FOR_EACH_ENTRY_SAFE( child, next, &info->children, object_header_t, entry )
         {
-            TRACE( "freeing child handle %d for parent handle %d\n",
-                   (UINT)child->hInternet, handle+1);
+            TRACE( "freeing child handle %ld for parent handle %ld\n",
+                   (UINT_PTR)child->hInternet, handle+1);
             WININET_FreeHandle( child->hInternet );
         }
         WININET_Release( info );
index 29d26ab..6a39c69 100644 (file)
@@ -986,9 +986,9 @@ static DWORD URLCache_CopyEntry(
         ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
     dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
     if (bUnicode)
-        lenUrl = MultiByteToWideChar(CP_ACP, 0, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl, -1, NULL, 0);
+        lenUrl = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetUrl, -1, NULL, 0);
     else
-        lenUrl = strlen((LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl);
+        lenUrl = strlen((LPCSTR)pUrlEntry + pUrlEntry->dwOffsetUrl);
     dwRequiredSize += (lenUrl + 1) * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
 
     /* FIXME: is source url optional? */
@@ -998,9 +998,9 @@ static DWORD URLCache_CopyEntry(
 
         lpCacheEntryInfo->lpszSourceUrlName = (LPSTR)lpCacheEntryInfo + dwRequiredSize - lenUrlBytes;
         if (bUnicode)
-            MultiByteToWideChar(CP_ACP, 0, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl, -1, (LPWSTR)lpCacheEntryInfo->lpszSourceUrlName, lenUrl + 1);
+            MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetUrl, -1, (LPWSTR)lpCacheEntryInfo->lpszSourceUrlName, lenUrl + 1);
         else
-            memcpy(lpCacheEntryInfo->lpszSourceUrlName, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl, lenUrlBytes);
+            memcpy(lpCacheEntryInfo->lpszSourceUrlName, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetUrl, lenUrlBytes);
     }
 
     if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
@@ -1029,7 +1029,7 @@ static DWORD URLCache_CopyEntry(
     if (*lpdwBufferSize >= dwRequiredSize)
     {
         lpCacheEntryInfo->lpHeaderInfo = (LPBYTE)lpCacheEntryInfo + dwRequiredSize - pUrlEntry->dwHeaderInfoSize - 1;
-        memcpy(lpCacheEntryInfo->lpHeaderInfo, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo, pUrlEntry->dwHeaderInfoSize);
+        memcpy(lpCacheEntryInfo->lpHeaderInfo, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo, pUrlEntry->dwHeaderInfoSize);
         ((LPBYTE)lpCacheEntryInfo)[dwRequiredSize - 1] = '\0';
     }
     if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
@@ -1041,18 +1041,18 @@ static DWORD URLCache_CopyEntry(
         int lenExtension;
 
         if (bUnicode)
-            lenExtension = MultiByteToWideChar(CP_ACP, 0, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension, -1, NULL, 0);
+            lenExtension = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension, -1, NULL, 0);
         else
-            lenExtension = strlen((LPSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension) + 1;
+            lenExtension = strlen((LPCSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension) + 1;
         dwRequiredSize += lenExtension * (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
 
         if (*lpdwBufferSize >= dwRequiredSize)
         {
             lpCacheEntryInfo->lpszFileExtension = (LPSTR)lpCacheEntryInfo + dwRequiredSize - lenExtension;
             if (bUnicode)
-                MultiByteToWideChar(CP_ACP, 0, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension, -1, (LPWSTR)lpCacheEntryInfo->lpszSourceUrlName, lenExtension);
+                MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension, -1, (LPWSTR)lpCacheEntryInfo->lpszSourceUrlName, lenExtension);
             else
-                memcpy(lpCacheEntryInfo->lpszFileExtension, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension, lenExtension * sizeof(CHAR));
+                memcpy(lpCacheEntryInfo->lpszFileExtension, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetFileExtension, lenExtension * sizeof(CHAR));
         }
 
         if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
@@ -1175,8 +1175,8 @@ static inline HASH_CACHEFILE_ENTRY * URLCache_HashEntryFromOffset(LPCURLCACHE_HE
 static inline BOOL URLCache_IsHashEntryValid(LPCURLCACHE_HEADER pHeader, const HASH_CACHEFILE_ENTRY *pHashEntry)
 {
     /* check pHashEntry located within acceptable bounds in the URL cache mapping */
-    return ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) >= ENTRY_START_OFFSET) &&
-           ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) < pHeader->dwFileSize);
+    return ((DWORD)((const BYTE*)pHashEntry - (const BYTE*)pHeader) >= ENTRY_START_OFFSET) &&
+           ((DWORD)((const BYTE*)pHashEntry - (const BYTE*)pHeader) < pHeader->dwFileSize);
 }
 
 static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct _HASH_ENTRY ** ppHashEntry)
@@ -1557,15 +1557,15 @@ BOOL WINAPI GetUrlCacheEntryInfoA(
     if (pEntry->dwSignature != URL_SIGNATURE)
     {
         URLCacheContainer_UnlockIndex(pContainer, pHeader);
-        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
+        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPCSTR)&pEntry->dwSignature, sizeof(DWORD)));
         SetLastError(ERROR_FILE_NOT_FOUND);
         return FALSE;
     }
 
     pUrlEntry = (const URL_CACHEFILE_ENTRY *)pEntry;
-    TRACE("Found URL: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl));
+    TRACE("Found URL: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->dwOffsetUrl));
     if (pUrlEntry->dwOffsetHeaderInfo)
-        TRACE("Header info: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo));
+        TRACE("Header info: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo));
 
     if (lpdwCacheEntryInfoBufferSize)
     {
@@ -1639,14 +1639,14 @@ BOOL WINAPI GetUrlCacheEntryInfoW(LPCWSTR lpszUrl,
     if (pEntry->dwSignature != URL_SIGNATURE)
     {
         URLCacheContainer_UnlockIndex(pContainer, pHeader);
-        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
+        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPCSTR)&pEntry->dwSignature, sizeof(DWORD)));
         SetLastError(ERROR_FILE_NOT_FOUND);
         return FALSE;
     }
 
     pUrlEntry = (const URL_CACHEFILE_ENTRY *)pEntry;
-    TRACE("Found URL: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl));
-    TRACE("Header info: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo));
+    TRACE("Found URL: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->dwOffsetUrl));
+    TRACE("Header info: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo));
 
     if (lpdwCacheEntryInfoBufferSize)
     {
@@ -3265,9 +3265,9 @@ BOOL WINAPI FindNextUrlCacheEntryA(
                 if (pEntry->dwSignature != URL_SIGNATURE)
                     continue;
 
-                pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
-                TRACE("Found URL: %s\n", (LPSTR)pUrlEntry + pUrlEntry->dwOffsetUrl);
-                TRACE("Header info: %s\n", (LPBYTE)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo);
+                pUrlEntry = (const URL_CACHEFILE_ENTRY *)pEntry;
+                TRACE("Found URL: %s\n", (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetUrl);
+                TRACE("Header info: %s\n", (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo);
 
                 error = URLCache_CopyEntry(
                     pContainer,
@@ -3563,7 +3563,7 @@ BOOL WINAPI IsUrlCacheEntryExpiredA( LPCSTR url, DWORD dwFlags, FILETIME* pftLas
     if (pEntry->dwSignature != URL_SIGNATURE)
     {
         URLCacheContainer_UnlockIndex(pContainer, pHeader);
-        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
+        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPCSTR)&pEntry->dwSignature, sizeof(DWORD)));
         SetLastError(ERROR_FILE_NOT_FOUND);
         return FALSE;
     }
@@ -3625,7 +3625,7 @@ BOOL WINAPI IsUrlCacheEntryExpiredW( LPCWSTR url, DWORD dwFlags, FILETIME* pftLa
     if (pEntry->dwSignature != URL_SIGNATURE)
     {
         URLCacheContainer_UnlockIndex(pContainer, pHeader);
-        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
+        FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPCSTR)&pEntry->dwSignature, sizeof(DWORD)));
         SetLastError(ERROR_FILE_NOT_FOUND);
         return FALSE;
     }
index 69c9dd3..8659266 100644 (file)
@@ -1348,7 +1348,7 @@ static BOOL CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType,
                     link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
                     for (i = 0; i < dataLen / sizeof(WCHAR); i++)
                         link->u.pwszFile[i] =
-                         hton16(*(WORD *)(ptr + i * sizeof(WCHAR)));
+                         hton16(*(const WORD *)(ptr + i * sizeof(WCHAR)));
                     link->u.pwszFile[realDataLen / sizeof(WCHAR)] = '\0';
                     TRACE("returning file %s\n", debugstr_w(link->u.pwszFile));
                 }
index 4de56cc..b83d364 100644 (file)
 #ifndef _NTSECPKG_H
 #define _NTSECPKG_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Flags for the MachineState field in SECPKG_PARAMETERS */
 #define SECPKG_STATE_ENCRYPTION_PERMITTED               0x01
 #define SECPKG_STATE_STRONG_ENCRYPTION_PERMITTED        0x02
@@ -30,6 +34,9 @@
 #define SECPKG_INTERFACE_VERSION                     0x10000
 #define SECPKG_INTERFACE_VERSION_2                   0x20000
 #define SECPKG_INTERFACE_VERSION_3                   0x40000
+#define SECPKG_INTERFACE_VERSION_4                   0x80000
+#define SECPKG_INTERFACE_VERSION_5                  0x100000
+#define SECPKG_INTERFACE_VERSION_6                  0x200000
 
 /* enum definitions for Secure Service Provider/Authentication Packages */
 typedef enum _LSA_TOKEN_INFORMATION_TYPE {
@@ -140,6 +147,11 @@ typedef struct _SECPKG_EXTENDED_INFORMATION {
     } Info;
 } SECPKG_EXTENDED_INFORMATION, *PSECPKG_EXTENDED_INFORMATION;
 
+typedef struct  _SECPKG_TARGETINFO {
+    PSID DomainSid;
+    PCWSTR ComputerName;
+} SECPKG_TARGETINFO, *PSECPKG_TARGETINFO;
+
 /* callbacks implemented by SSP/AP dlls and called by the LSA */
 typedef VOID (NTAPI *PLSA_CALLBACK_FUNCTION)(ULONG_PTR, ULONG_PTR, PSecBuffer,
  PSecBuffer);
@@ -341,6 +353,18 @@ typedef NTSTATUS (NTAPI SpSetContextAttributesFn)(LSA_SEC_HANDLE, ULONG, PVOID,
  ULONG);
 typedef NTSTATUS (NTAPI SpSetCredentialsAttributesFn)(LSA_SEC_HANDLE, ULONG,
  PVOID, ULONG);
+typedef NTSTATUS (NTAPI SpChangeAccountPasswordFn)(PUNICODE_STRING,
+ PUNICODE_STRING, PUNICODE_STRING, PUNICODE_STRING, BOOLEAN, PSecBufferDesc);
+typedef NTSTATUS (NTAPI SpQueryMetaDataFn)(LSA_SEC_HANDLE, PUNICODE_STRING,
+ ULONG, PULONG, PUCHAR *, PLSA_SEC_HANDLE);
+typedef NTSTATUS (NTAPI SpExchangeMetaDataFn)(LSA_SEC_HANDLE, PUNICODE_STRING,
+ ULONG, ULONG, PUCHAR, PLSA_SEC_HANDLE);
+typedef NTSTATUS (NTAPI SpGetCredUIContextFn)(LSA_SEC_HANDLE, GUID *, PULONG,
+ PUCHAR *);
+typedef NTSTATUS (NTAPI SpUpdateCredentialsFn)(LSA_SEC_HANDLE, GUID *, ULONG,
+ PUCHAR);
+typedef NTSTATUS (NTAPI SpValidateTargetInfoFn)(PLSA_CLIENT_REQUEST, PVOID,
+ PVOID, ULONG, PSECPKG_TARGETINFO);
 
 /* User-mode functions implemented by SSP/AP obtainable by a dispatch table */
 typedef NTSTATUS (NTAPI SpInstanceInitFn)(ULONG, PSECPKG_DLL_FUNCTIONS,
@@ -402,6 +426,15 @@ typedef struct SECPKG_FUNCTION_TABLE {
     /* Packages with version SECPKG_INTERFACE_VERSION_2 end here */
     SpSetCredentialsAttributesFn *SetCredentialsAttributes;
     /* Packages with version SECPKG_INTERFACE_VERSION_3 end here */
+    SpChangeAccountPasswordFn *ChangeAccountPassword;
+    /* Packages with version SECPKG_INTERFACE_VERSION_4 end here */
+    SpQueryMetaDataFn *QueryMetaData;
+    SpExchangeMetaDataFn *ExchangeMetaData;
+    SpGetCredUIContextFn *GetCredUIContext;
+    SpUpdateCredentialsFn *UpdateCredentials;
+    /* Packages with version SECPKG_INTERFACE_VERSION_5 end here */
+    SpValidateTargetInfoFn *ValidateTargetInfo;
+    /* Packages with version SECPKG_INTERFACE_VERSION_6 end here */
 } SECPKG_FUNCTION_TABLE,
  *PSECPKG_FUNCTION_TABLE;
 
@@ -432,4 +465,7 @@ typedef NTSTATUS (NTAPI *SpLsaModeInitializeFn)(ULONG, PULONG,
 typedef NTSTATUS (WINAPI *SpUserModeInitializeFn)(ULONG, PULONG,
  PSECPKG_USER_FUNCTION_TABLE *, PULONG);
 
+#ifdef __cplusplus
+}
+#endif
 #endif /* _NTSECPKG_H */
index 02256eb..ebf38da 100644 (file)
@@ -47,6 +47,7 @@
        <file>richole.idl</file>
        <file>sensevts.idl</file>
        <file>servprov.idl</file>
+       <file>shdeprecated.idl</file>
        <file>shldisp.idl</file>
        <file>shobjidl.idl</file>
        <file>shtypes.idl</file>
@@ -68,6 +69,8 @@
        <file>xmldso.idl</file>
        <file>xmldom.idl</file>
        <file>xmllite.idl</file>
+       <file>wia_lh.idl</file>
+       <file>wia_xp.idl</file>
 </module>
 <module name="stdole2" type="embeddedtypelib">
        <file>stdole2.idl</file>
diff --git a/reactos/include/psdk/shdeprecated.idl b/reactos/include/psdk/shdeprecated.idl
new file mode 100644 (file)
index 0000000..304b087
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Deprecated shell interfaces
+ *
+ * Copyright (C) 2010 Nikolay Sivov for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "objidl.idl";
+
+[
+    object,
+    local,
+    uuid(5836fb00-8187-11cf-a12b-00aa004ae837)
+]
+interface IShellService : IUnknown
+{
+    HRESULT SetOwner( [in] IUnknown *pUnk );
+}
index 29e70b7..223bcdd 100644 (file)
@@ -1028,24 +1028,6 @@ typedef struct _DLLVERSIONINFO2 {
 HRESULT WINAPI DllInstall(BOOL,LPCWSTR) DECLSPEC_HIDDEN;
 
 
-#if (_WIN32_IE >= 0x0600)
-#define SHGVSPB_PERUSER        0x00000001
-#define SHGVSPB_ALLUSERS       0x00000002
-#define SHGVSPB_PERFOLDER      0x00000004
-#define SHGVSPB_ALLFOLDERS     0x00000008
-#define SHGVSPB_INHERIT        0x00000010
-#define SHGVSPB_ROAM           0x00000020
-#define SHGVSPB_NOAUTODEFAULTS 0x80000000
-
-#define SHGVSPB_FOLDER           (SHGVSPB_PERUSER | SHGVSPB_PERFOLDER)
-#define SHGVSPB_FOLDERNODEFAULTS (SHGVSPB_PERUSER | SHGVSPB_PERFOLDER | SHGVSPB_NOAUTODEFAULTS)
-#define SHGVSPB_USERDEFAULTS     (SHGVSPB_PERUSER | SHGVSPB_ALLFOLDERS)
-#define SHGVSPB_GLOBALDEAFAULTS  (SHGVSPB_ALLUSERS | SHGVSPB_ALLFOLDERS)
-
-HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name, DWORD flags, REFIID riid, void **ppv);
-#endif  /* (_WIN32_IE >= 0x0600) */
-
-
 /* IsOS definitions */
 
 #define OS_WIN32SORGREATER        0x00
@@ -1103,6 +1085,15 @@ BOOL WINAPI IsOS(DWORD);
 #define FDTF_RTLDATE            0x00000200
 #define FDTF_NOAUTOREADINGORDER 0x00000400
 
+
+typedef struct
+{
+    const IID *piid;
+    int        dwOffset;
+} QITAB, *LPQITAB;
+
+HRESULT WINAPI QISearch(void* base, const QITAB *pqit, REFIID riid, void **ppv);
+
 #include <poppack.h> 
 
 #ifdef __cplusplus
index 56650f5..204492d 100644 (file)
@@ -31,6 +31,147 @@ extern "C" {
 
 DEFINE_GUID(CLSID_Sti, 0xB323F8E0L, 0x2E68, 0x11D0, 0x90, 0xEA, 0x00, 0xAA, 0x00, 0x60, 0xF8, 0x6C);
 
+DEFINE_GUID(IID_IStillImageW, 0x641BD880, 0x2DC8, 0x11D0, 0x90, 0xEA, 0x00, 0xAA, 0x00, 0x60, 0xF8, 0x6C);
+
+DEFINE_GUID(IID_IStillImageA, 0xA7B1F740, 0x1D7F, 0x11D1, 0xAC, 0xA9, 0x00, 0xA0, 0x24, 0x38, 0xAD, 0x48);
+
+#define STI_VERSION_REAL         0x00000002
+#define STI_VERSION_FLAG_UNICODE 0x01000000
+
+#ifndef WINE_NO_UNICODE_MACROS
+# ifdef UNICODE
+#  define STI_VERSION (STI_VERSION_REAL | STI_VERSION_FLAG_UNICODE)
+# else
+#  define STI_VERSION (STI_VERSION_REAL)
+# endif
+#endif
+
+typedef struct IStillImageA *PSTIA;
+typedef struct IStillImageW *PSTIW;
+DECL_WINELIB_TYPE_AW(PSTI)
+typedef struct IStillImageA *LPSTILLIMAGEA;
+typedef struct IStillImageW *LPSTILLIMAGEW;
+DECL_WINELIB_TYPE_AW(LPSTILLIMAGE)
+typedef struct IStiDeviceA *PSTIDEVICEA;
+typedef struct IStiDeviceW *PSTIDEVICEW;
+DECL_WINELIB_TYPE_AW(PSTIDEVICE)
+
+HRESULT WINAPI StiCreateInstanceA(HINSTANCE hinst, DWORD dwVer, PSTIA *ppSti, LPUNKNOWN pUnkOuter);
+HRESULT WINAPI StiCreateInstanceW(HINSTANCE hinst, DWORD dwVer, PSTIW *ppSti, LPUNKNOWN pUnkOuter);
+#define        StiCreateInstance WINELIB_NAME_AW(StiCreateInstance)
+
+typedef DWORD STI_DEVICE_TYPE;
+typedef enum _STI_DEVICE_MJ_TYPE
+{
+    StiDeviceTypeDefault           = 0,
+    StiDeviceTypeScanner           = 1,
+    StiDeviceTypeDigitalCamera     = 2,
+    StiDeviceTypeStreamingVideo    = 3
+} STI_DEVICE_MJ_TYPE;
+
+#define GET_STIDEVICE_TYPE(dwDevType) HIWORD(dwDevType)
+#define GET_STIDEVICE_SUBTYPE(dwDevType) LOWORD(dwDevType)
+
+typedef struct _STI_DEV_CAPS {
+    DWORD dwGeneric;
+} STI_DEV_CAPS, *PSTI_DEV_CAPS;
+
+#define STI_MAX_INTERNAL_NAME_LENGTH 128
+
+typedef struct _STI_DEVICE_INFORMATIONW {
+    DWORD dwSize;
+    STI_DEVICE_TYPE DeviceType;
+    WCHAR szDeviceInternalName[STI_MAX_INTERNAL_NAME_LENGTH];
+    STI_DEV_CAPS DeviceCapabilities;
+    DWORD dwHardwareConfiguration;
+    LPWSTR pszVendorDescription;
+    LPWSTR pszDeviceDescription;
+    LPWSTR pszPortName;
+    LPWSTR pszPropProvider;
+    LPWSTR pszLocalName;
+} STI_DEVICE_INFORMATIONW, *PSTI_DEVICE_INFORMATIONW;
+
+typedef STI_DEVICE_INFORMATIONW STI_DEVICE_INFORMATION;
+typedef PSTI_DEVICE_INFORMATIONW PSTI_DEVICE_INFORMATION;
+
+#define MAX_NOTIFICATION_DATA 64
+
+typedef struct _STINOTIFY {
+    DWORD dwSize;
+    GUID guidNotificationCode;
+    BYTE abNotificationData[MAX_NOTIFICATION_DATA];
+} STINOTIFY,*LPSTINOTIFY;
+
+#define INTERFACE IStillImageW
+DECLARE_INTERFACE_(IStillImageW, IUnknown)
+{
+    /*** IUnknown methods ***/
+    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IStillImageW methods ***/
+    STDMETHOD(Initialize)(THIS_ HINSTANCE hinst, DWORD dwVersion) PURE;
+    STDMETHOD(GetDeviceList)(THIS_ DWORD dwType, DWORD dwFlags, DWORD *pdwItemsReturned, LPVOID *ppBuffer) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPWSTR pwszDeviceName, LPVOID *ppBuffer) PURE;
+    STDMETHOD(CreateDevice)(THIS_ LPWSTR pwszDeviceName, DWORD dwMode, PSTIDEVICEW *pDevice, LPUNKNOWN pUnkOuter) PURE;
+    STDMETHOD(GetDeviceValue)(THIS_ LPWSTR pwszDeviceName, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, LPDWORD cbData) PURE;
+    STDMETHOD(SetDeviceValue)(THIS_ LPWSTR pwszDeviceName, LPWSTR pValueName, DWORD type, LPBYTE pData, DWORD cbData) PURE;
+    STDMETHOD(GetSTILaunchInformation)(THIS_ LPWSTR pwszDeviceName, DWORD *pdwEventCode, LPWSTR pwszEventName) PURE;
+    STDMETHOD(RegisterLaunchApplication)(THIS_ LPWSTR pwszAppName, LPWSTR pwszCommandLine) PURE;
+    STDMETHOD(UnregisterLaunchApplication)(THIS_ LPWSTR pwszAppName) PURE;
+    STDMETHOD(EnableHwNotifications)(THIS_ LPCWSTR pwszDeviceName, BOOL bNewState) PURE;
+    STDMETHOD(GetHwNotificationState)(THIS_ LPCWSTR pwszDeviceName, BOOL *pbCurrentState) PURE;
+    STDMETHOD(RefreshDeviceBus)(THIS_ LPCWSTR pwszDeviceName) PURE;
+    STDMETHOD(LaunchApplicationForDevice)(THIS_ LPWSTR pwszDeviceName, LPWSTR pwszAppName, LPSTINOTIFY pStiNotify);
+    STDMETHOD(SetupDeviceParameters)(THIS_ PSTI_DEVICE_INFORMATIONW pDevInfo);
+    STDMETHOD(WriteToErrorLog)(THIS_ DWORD dwMessageType, LPCWSTR pszMessage) PURE;
+};
+#undef INTERFACE
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+/*** IUnknown methods ***/
+#define IStillImage_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IStillImage_AddRef(p)             (p)->lpVtbl->AddRef(p)
+#define IStillImage_Release(p)            (p)->lpVtbl->Release(p)
+/*** IStillImage methods ***/
+#define IStillImage_Initialize(p,a,b)                   (p)->lpVtbl->Initialize(p,a,b)
+#define IStillImage_GetDeviceList(p,a,b,c,d)            (p)->lpVtbl->GetDeviceList(p,a,b,c,d)
+#define IStillImage_GetDeviceInfo(p,a,b)                (p)->lpVtbl->GetDeviceInfo(p,a,b)
+#define IStillImage_CreateDevice(p,a,b,c,d)             (p)->lpVtbl->CreateDevice(p,a,b,c,d)
+#define IStillImage_GetDeviceValue(p,a,b,c,d,e)         (p)->lpVtbl->GetDeviceValue(p,a,b,c,d,e)
+#define IStillImage_SetDeviceValue(p,a,b,c,d,e)         (p)->lpVtbl->SetDeviceValue(p,a,b,c,d,e)
+#define IStillImage_GetSTILaunchInformation(p,a,b,c)    (p)->lpVtbl->GetSTILaunchInformation(p,a,b,c)
+#define IStillImage_RegisterLaunchApplication(p,a,b)    (p)->lpVtbl->RegisterLaunchApplication(p,a,b)
+#define IStillImage_UnregisterLaunchApplication(p,a)    (p)->lpVtbl->UnregisterLaunchApplication(p,a)
+#define IStillImage_EnableHwNotifications(p,a,b)        (p)->lpVtbl->EnableHwNotifications(p,a,b)
+#define IStillImage_GetHwNotificationState(p,a,b)       (p)->lpVtbl->GetHwNotificationState(p,a,b)
+#define IStillImage_RefreshDeviceBus(p,a)               (p)->lpVtbl->RefreshDeviceBus(p,a)
+#define IStillImage_LaunchApplicationForDevice(p,a,b,c) (p)->lpVtbl->LaunchApplicationForDevice(p,a,b,c)
+#define IStillImage_SetupDeviceParameters(p,a)          (p)->lpVtbl->SetupDeviceParameters(p,a)
+#define IStillImage_WriteToErrorLog(p,a,b)              (p)->lpVtbl->WriteToErrorLog(p,a,b)
+#else
+/*** IUnknown methods ***/
+#define IStillImage_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IStillImage_AddRef(p)             (p)->AddRef()
+#define IStillImage_Release(p)            (p)->Release()
+/*** IStillImage methods ***/
+#define IStillImage_Initialize(p,a,b)                   (p)->Initialize(a,b)
+#define IStillImage_GetDeviceList(p,a,b,c,d)            (p)->GetDeviceList(a,b,c,d)
+#define IStillImage_GetDeviceInfo(p,a,b)                (p)->GetDeviceInfo(a,b)
+#define IStillImage_CreateDevice(p,a,b,c,d)             (p)->CreateDevice(a,b,c,d)
+#define IStillImage_GetDeviceValue(p,a,b,c,d,e)         (p)->GetDeviceValue(a,b,c,d,e)
+#define IStillImage_SetDeviceValue(p,a,b,c,d,e)         (p)->SetDeviceValue(a,b,c,d,e)
+#define IStillImage_GetSTILaunchInformation(p,a,b,c)    (p)->GetSTILaunchInformation(a,b,c)
+#define IStillImage_RegisterLaunchApplication(p,a,b)    (p)->RegisterLaunchApplication(a,b)
+#define IStillImage_UnregisterLaunchApplication(p,a)    (p)->UnregisterLaunchApplication(a)
+#define IStillImage_EnableHwNotifications(p,a,b)        (p)->EnableHwNotifications(a,b)
+#define IStillImage_GetHwNotificationState(p,a,b)       (p)->GetHwNotificationState(a,b)
+#define IStillImage_RefreshDeviceBus(p,a)               (p)->RefreshDeviceBus(a)
+#define IStillImage_LaunchApplicationForDevice(p,a,b,c) (p)->LaunchApplicationForDevice(a,b,c)
+#define IStillImage_SetupDeviceParameters(p,a)          (p)->SetupDeviceParameters(a)
+#define IStillImage_WriteToErrorLog(p,a,b)              (p)->WriteToErrorLog(a,b)
+#endif
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/reactos/include/psdk/wia.h b/reactos/include/psdk/wia.h
new file mode 100644 (file)
index 0000000..3a0497e
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 Damjan Jovanovic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#ifdef __WINESRC__
+#error Specify wia_lh.h or wia_xp.h explicitly in Wine
+#endif
+
+#if (_WIN32_WINNT >= 0x0600)
+#include <wia_lh.h>
+#elif (_WIN32_WINNT >= 0x0501)
+#include <wia_xp.h>
+#endif
diff --git a/reactos/include/psdk/wia_lh.idl b/reactos/include/psdk/wia_lh.idl
new file mode 100644 (file)
index 0000000..5024787
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2009 Damjan Jovanovic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "wtypes.idl";
+import "objidl.idl";
+
+interface IEnumWIA_DEV_INFO;
+interface IWiaItem;
+interface IWiaEventCallback;
+
+cpp_quote("DEFINE_GUID(CLSID_WiaDevMgr, 0xa1f4e726,0x8cf1,0x11d1,0xbf,0x92,0x00,0x60,0x08,0x1e,0xd8,0x11);")
+
+[
+    object,
+    uuid(5eb2502a-8cf1-11d1-bf92-0060081ed811)
+]
+interface IWiaDevMgr : IUnknown
+{
+    HRESULT EnumDeviceInfo(
+        [in] LONG lFlag,
+        [retval, out] IEnumWIA_DEV_INFO **ppIEnum);
+
+    HRESULT CreateDevice(
+        [in] BSTR bstrDeviceID,
+        [out] IWiaItem **ppWiaItemRoot);
+
+    HRESULT SelectDeviceDlg(
+        [in] HWND hwndParent,
+        [in] LONG lDeviceType,
+        [in] LONG lFlags,
+        [in, out] BSTR *pbstrDeviceID,
+        [retval, out] IWiaItem **ppItemRoot);
+
+    HRESULT SelectDeviceDlgID(
+        [in] HWND hwndParent,
+        [in] LONG lDeviceType,
+        [in] LONG lFlags,
+        [retval, out] BSTR *pbstrDeviceID);
+
+    HRESULT GetImageDlg(
+        [in] HWND hwndParent,
+        [in] LONG lDeviceType,
+        [in] LONG lFlags,
+        [in] LONG lIntent,
+        [in] IWiaItem *pItemRoot,
+        [in] BSTR bstrFilename,
+        [in, out] GUID *pguidFormat);
+
+    HRESULT RegisterEventCallbackProgram(
+        [in] LONG lFlags,
+        [in] BSTR bstrDeviceID,
+        [in] const GUID *pEventGUID,
+        [in] BSTR bstrCommandline,
+        [in] BSTR bstrName,
+        [in] BSTR bstrDescription,
+        [in] BSTR bstrIcon);
+
+    HRESULT RegisterEventCallbackInterface(
+        [in] LONG lFlags,
+        [in] BSTR bstrDeviceID,
+        [in] const GUID *pEventGUID,
+        [unique, in] IWiaEventCallback *pIWiaEventCallback,
+        [out] IUnknown **pEventObject);
+
+    HRESULT RegisterEventCallbackCLSID(
+        [in] LONG lFlags,
+        [in] BSTR bstrDeviceID,
+        [in] const GUID *pEventGUID,
+        [unique, in] const GUID *pClsID,
+        [in] BSTR bstrName,
+        [in] BSTR bstrDescription,
+        [in] BSTR bstrIcon);
+
+    HRESULT AddDeviceDlg(
+        [in] HWND hwndParent,
+        [in] LONG lFlags);
+}
+
+[
+    object,
+    uuid(5e38b83c-8cf1-11d1-bf92-0060081ed811)
+]
+interface IEnumWIA_DEV_INFO : IUnknown
+{
+    /* fill in */
+}
+
+[
+    object,
+    uuid(4db1ad10-3391-11d2-9a33-00c04fa36145)
+]
+interface IWiaItem : IUnknown
+{
+    /* FIXME: fill in */
+}
+
+[
+    object,
+    uuid(ae6287b0-0084-11d2-973b-00a0c9068f2e)
+]
+interface IWiaEventCallback : IUnknown
+{
+    HRESULT ImageEventCallback(
+        [in] const GUID *pEventGUID,
+        [in] BSTR bstrEventDescription,
+        [in] BSTR bstrDeviceID,
+        [in] BSTR bstrDeviceDescription,
+        [in] DWORD dwDeviceType,
+        [in] BSTR bstrFullItemName,
+        [in,out] ULONG *pulEventType,
+        [in] ULONG ulReserved);
+}
diff --git a/reactos/include/psdk/wia_xp.idl b/reactos/include/psdk/wia_xp.idl
new file mode 100644 (file)
index 0000000..5024787
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2009 Damjan Jovanovic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "wtypes.idl";
+import "objidl.idl";
+
+interface IEnumWIA_DEV_INFO;
+interface IWiaItem;
+interface IWiaEventCallback;
+
+cpp_quote("DEFINE_GUID(CLSID_WiaDevMgr, 0xa1f4e726,0x8cf1,0x11d1,0xbf,0x92,0x00,0x60,0x08,0x1e,0xd8,0x11);")
+
+[
+    object,
+    uuid(5eb2502a-8cf1-11d1-bf92-0060081ed811)
+]
+interface IWiaDevMgr : IUnknown
+{
+    HRESULT EnumDeviceInfo(
+        [in] LONG lFlag,
+        [retval, out] IEnumWIA_DEV_INFO **ppIEnum);
+
+    HRESULT CreateDevice(
+        [in] BSTR bstrDeviceID,
+        [out] IWiaItem **ppWiaItemRoot);
+
+    HRESULT SelectDeviceDlg(
+        [in] HWND hwndParent,
+        [in] LONG lDeviceType,
+        [in] LONG lFlags,
+        [in, out] BSTR *pbstrDeviceID,
+        [retval, out] IWiaItem **ppItemRoot);
+
+    HRESULT SelectDeviceDlgID(
+        [in] HWND hwndParent,
+        [in] LONG lDeviceType,
+        [in] LONG lFlags,
+        [retval, out] BSTR *pbstrDeviceID);
+
+    HRESULT GetImageDlg(
+        [in] HWND hwndParent,
+        [in] LONG lDeviceType,
+        [in] LONG lFlags,
+        [in] LONG lIntent,
+        [in] IWiaItem *pItemRoot,
+        [in] BSTR bstrFilename,
+        [in, out] GUID *pguidFormat);
+
+    HRESULT RegisterEventCallbackProgram(
+        [in] LONG lFlags,
+        [in] BSTR bstrDeviceID,
+        [in] const GUID *pEventGUID,
+        [in] BSTR bstrCommandline,
+        [in] BSTR bstrName,
+        [in] BSTR bstrDescription,
+        [in] BSTR bstrIcon);
+
+    HRESULT RegisterEventCallbackInterface(
+        [in] LONG lFlags,
+        [in] BSTR bstrDeviceID,
+        [in] const GUID *pEventGUID,
+        [unique, in] IWiaEventCallback *pIWiaEventCallback,
+        [out] IUnknown **pEventObject);
+
+    HRESULT RegisterEventCallbackCLSID(
+        [in] LONG lFlags,
+        [in] BSTR bstrDeviceID,
+        [in] const GUID *pEventGUID,
+        [unique, in] const GUID *pClsID,
+        [in] BSTR bstrName,
+        [in] BSTR bstrDescription,
+        [in] BSTR bstrIcon);
+
+    HRESULT AddDeviceDlg(
+        [in] HWND hwndParent,
+        [in] LONG lFlags);
+}
+
+[
+    object,
+    uuid(5e38b83c-8cf1-11d1-bf92-0060081ed811)
+]
+interface IEnumWIA_DEV_INFO : IUnknown
+{
+    /* fill in */
+}
+
+[
+    object,
+    uuid(4db1ad10-3391-11d2-9a33-00c04fa36145)
+]
+interface IWiaItem : IUnknown
+{
+    /* FIXME: fill in */
+}
+
+[
+    object,
+    uuid(ae6287b0-0084-11d2-973b-00a0c9068f2e)
+]
+interface IWiaEventCallback : IUnknown
+{
+    HRESULT ImageEventCallback(
+        [in] const GUID *pEventGUID,
+        [in] BSTR bstrEventDescription,
+        [in] BSTR bstrDeviceID,
+        [in] BSTR bstrDeviceDescription,
+        [in] DWORD dwDeviceType,
+        [in] BSTR bstrFullItemName,
+        [in,out] ULONG *pulEventType,
+        [in] ULONG ulReserved);
+}
index 828e413..a1fbc15 100644 (file)
@@ -52,13 +52,13 @@ reactos/dll/win32/comctl32        # Autosync ??
 reactos/dll/win32/comdlg32        # Autosync
 reactos/dll/win32/compstui        # Autosync
 reactos/dll/win32/credui          # Autosync
-reactos/dll/win32/crypt32         # Synced to Wine-1_1_40
+reactos/dll/win32/crypt32         # Synced to Wine-1_1_43
 reactos/dll/win32/cryptdlg        # Autosync
 reactos/dll/win32/cryptdll        # Autosync
 reactos/dll/win32/cryptnet        # Autosync
 reactos/dll/win32/cryptui         # Autosync
 reactos/dll/win32/dbghelp         # Synced to Wine-20080802
-reactos/dll/win32/dciman32        # Synced to Wine-1_0-rc2
+reactos/dll/win32/dciman32        # Synced to Wine-1_1_43
 reactos/dll/win32/dwmapi          # Autosync
 reactos/dll/win32/fusion          # Autosync
 reactos/dll/win32/gdiplus         # Autosync
@@ -113,7 +113,7 @@ reactos/dll/win32/mstask          # Autosync
 reactos/dll/win32/msvcrt20        # Autosync
 reactos/dll/win32/msvfw32         # Autosync
 reactos/dll/win32/msvidc32        # Autosync
-reactos/dll/win32/msxml3          # Synced to Wine-1_1_40
+reactos/dll/win32/msxml3          # Synced to Wine-1_1_43
 reactos/dll/win32/nddeapi         # Autosync
 reactos/dll/win32/netapi32        # Autosync
 reactos/dll/win32/ntdsapi         # Autosync
@@ -144,6 +144,8 @@ reactos/dll/win32/rsabase         # Autosync
 reactos/dll/win32/rsaenh          # Autosync
 reactos/dll/win32/sccbase         # Autosync
 reactos/dll/win32/schannel        # Autosync ??
+reactos/dll/win32/secur32         # Forked
+reactos/dll/win32/security        # Forked (different .spec)
 reactos/dll/win32/sensapi         # Autosync
 reactos/dll/win32/setupapi        # Forked at Wine-20050524
 reactos/dll/win32/shell32         # Forked at Wine-20071011
@@ -154,7 +156,7 @@ reactos/dll/win32/slbcsp          # Autosync
 reactos/dll/win32/softpub         # Autosync
 reactos/dll/win32/spoolss         # Autosync
 reactos/dll/win32/stdole2.tlb     # Autosync
-reactos/dll/win32/sti             # Autosync ??
+reactos/dll/win32/sti             # Autosync
 reactos/dll/win32/sxs             # Autosync
 reactos/dll/win32/tapi32          # Autosync
 reactos/dll/win32/traffic         # Autosync
@@ -203,7 +205,7 @@ In addition the following libs, dlls and source files are mostly based on code p
 from Winehq CVS. If you are looking to update something in these files
 check Wine current souces first as it may already be fixed.
 
-reactos/lib/uuid                  # Synced to Wine-20080114
+reactos/lib/sdk/uuid                  # Synced to Wine-1.1.42
 
 advapi32 -
   reactos/dll/win32/advapi32/crypt/*.c          # ekohl says we're not sharing this