Partial implementation of MsiGetFileVersionA/W.

diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c
index 6af95f5..1f67146 100644
--- a/dlls/msi/msi.c
+++ b/dlls/msi/msi.c
@@ -35,6 +35,7 @@
 #include "wincrypt.h"
 #include "wine/unicode.h"
 #include "objbase.h"
+#include "winver.h"
 
 #include "initguid.h"
 
@@ -1332,6 +1333,103 @@
     return INSTALLSTATE_UNKNOWN;
 }
 
+UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf)
+{
+    UINT len;
+    UINT ret;
+    LPWSTR szwFilePath = NULL;
+    LPWSTR lpwVersionBuff = NULL;
+    LPWSTR lpwLangBuff = NULL;
+    
+    if(szFilePath) {
+        len = MultiByteToWideChar( CP_ACP, 0, szFilePath, -1, NULL, 0 );
+        szwFilePath = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+        if( !szwFilePath)
+            return ERROR_OUTOFMEMORY;
+        MultiByteToWideChar( CP_ACP, 0, szFilePath, -1, szwFilePath, len );
+    }
+    
+    if(lpVersionBuf && pcchVersionBuf && *pcchVersionBuf) {
+        lpwVersionBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf * sizeof(WCHAR));
+        if( !lpwVersionBuff)
+            return ERROR_OUTOFMEMORY;
+    }
+
+    if(lpLangBuf && pcchLangBuf && *pcchLangBuf) {
+        lpwLangBuff = HeapAlloc(GetProcessHeap(), 0, *pcchVersionBuf * sizeof(WCHAR));
+        if( !lpwLangBuff)
+            return ERROR_OUTOFMEMORY;
+    }
+        
+    ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf, lpwLangBuff, pcchLangBuf);
+    
+    if(lpwVersionBuff)
+        WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1, lpVersionBuf, *pcchVersionBuf, NULL, NULL);
+    if(lpwLangBuff)
+        WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1, lpLangBuf, *pcchLangBuf, NULL, NULL);
+    
+    if(szwFilePath) HeapFree(GetProcessHeap(), 0, szwFilePath);
+    if(lpwVersionBuff) HeapFree(GetProcessHeap(), 0, lpwVersionBuff);
+    if(lpwLangBuff) HeapFree(GetProcessHeap(), 0, lpwLangBuff);
+    
+    return ret;
+}
+
+UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf)
+{
+    static const WCHAR szVersionResource[] = {'\\',0};
+    static const WCHAR szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
+    static const WCHAR szLangFormat[] = {'%','d',0};
+    UINT ret = 0;
+    DWORD dwVerLen;
+    LPVOID lpVer = NULL;
+    VS_FIXEDFILEINFO *ffi;
+    UINT puLen;
+    WCHAR tmp[32];
+
+    TRACE("(%s,%p,%ld,%p,%ld)\n", debugstr_w(szFilePath),
+          lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0,
+          lpLangBuf, pcchLangBuf?*pcchLangBuf:0);
+
+    dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL);
+    if(!dwVerLen)
+        return GetLastError();
+
+    lpVer = HeapAlloc(GetProcessHeap(), 0, dwVerLen);
+    if(!lpVer) {
+        ret = ERROR_OUTOFMEMORY;
+        goto end;
+    }
+
+    if(!GetFileVersionInfoW(szFilePath, 0, dwVerLen, lpVer)) {
+        ret = GetLastError();
+        goto end;
+    }
+    if(lpVersionBuf && pcchVersionBuf && *pcchVersionBuf) {
+        if(VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) && puLen > 0) {
+            wsprintfW(tmp, szVersionFormat, HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS));
+            lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf);
+            *pcchVersionBuf = strlenW(lpVersionBuf);
+        }
+        else {
+            *lpVersionBuf = 0;
+            *pcchVersionBuf = 0;
+        }
+    }
+
+    if(lpLangBuf && pcchLangBuf && *pcchLangBuf) {
+        DWORD lang = GetUserDefaultLangID();
+        FIXME("Retrieve language from file\n");
+        wsprintfW(tmp, szLangFormat, lang);
+        lstrcpynW(lpLangBuf, tmp, *pcchLangBuf);
+        *pcchLangBuf = strlenW(lpLangBuf);
+    }
+
+end:
+    if(lpVer) HeapFree(GetProcessHeap(), 0, lpVer);
+    return ret;
+}
+
 
 /******************************************************************
  *		DllMain
diff --git a/dlls/msi/msi.spec b/dlls/msi/msi.spec
index bd8092d..0310438 100644
--- a/dlls/msi/msi.spec
+++ b/dlls/msi/msi.spec
@@ -191,8 +191,8 @@
 191 stub MsiInvalidateFeatureCache
 192 stub MsiUseFeatureExA
 193 stub MsiUseFeatureExW
-194 stub MsiGetFileVersionA
-195 stub MsiGetFileVersionW
+194 stdcall MsiGetFileVersionA(str str ptr str ptr)
+195 stdcall MsiGetFileVersionW(wstr wstr ptr wstr ptr)
 196 stdcall MsiLoadStringA(long long long long long)
 197 stdcall MsiLoadStringW(long long long long long)
 198 stdcall MsiMessageBoxA(long long long long long long)
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index d8ea714..03d34e0 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -719,12 +719,12 @@
     if (NULL == szName) {
       return ERROR_INVALID_PARAMETER;
     }
-
-    TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
-
     if (NULL != szValueBuf && NULL == pchValueBuf) {
       return ERROR_INVALID_PARAMETER;
     }
+
+    TRACE("%lu %s %lu\n", hInstall, debugstr_a(szName), *pchValueBuf);
+
     if( szName )
     {
         UINT len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 );
diff --git a/include/msi.h b/include/msi.h
index f461e99..5d9a17b 100644
--- a/include/msi.h
+++ b/include/msi.h
@@ -246,6 +246,10 @@
 INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature);
 #define MsiQueryFeatureState WINELIB_NAME_AW(MsiQueryFeatureState)
 
+UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, DWORD* pcchVersionBuf, LPSTR lpLangBuf, DWORD* pcchLangBuf);
+UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, DWORD* pcchVersionBuf, LPWSTR lpLangBuf, DWORD* pcchLangBuf);
+#define MsiGetFileVersion WINELIB_NAME_AW(MsiGetFileVersion)
+
 /**
  * Non Unicode
  */