/////////////////////////////////////////////////////////
//
// GetComponentInfo
//
//        This helper function, provided with a component
//        ProgId, gathers the component's name and version
//        info and formats them into output strings
//
// Parameters:
//        CLSID  clsid  : [in] component's CLSID
//        SInfo& info   : [in, out] a structure of buffers
//                        to get the formatted strings into
//
// Return Values:
//        TRUE, if the function succeeds
//        FALSE, if it fails
//
/////////////////////////////////////////////////////////
BOOL GetComponentInfo(CLSID clsid, SInfo& info)
{
    info.wchName[0] = info.wchVersion[0] = 0;

    // Format Registry Key string
    WCHAR wszKey[45] = L"CLSID\\";  // the key buffer should be large enough for a string
                                    // like "CLSID\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
    // Convert CLSID to String
    UINT uPos = lstrlenW(wszKey);
    if (0 == StringFromGUID2(clsid, &wszKey[uPos], countof(wszKey) - uPos))
        return FALSE;
    wszKey[countof(wszKey)-1] = 0;

    // Open key to find path of application
    HKEY hKeyRoot;
    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszKey, 0, KEY_READ, &hKeyRoot) != ERROR_SUCCESS)
        return FALSE;

    // Query value of key to get the name of the component
    ULONG cSize = sizeof(info.wchName);  // size of the buffer in bytes
    if (RegQueryValueExW(hKeyRoot, NULL, NULL, NULL, (BYTE*)info.wchName, &cSize) != ERROR_SUCCESS)
    {
        RegCloseKey(hKeyRoot);
        return FALSE;
    }
    info.wchName[countof(info.wchName) - 1] = 0;

    // Open the version info subkey
    UINT iVersionMaxLen = countof(info.wchVersion);
    HKEY hKey = NULL;
    if (RegOpenKeyExW(hKeyRoot, L"Version", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
    {
        const WCHAR* pcwsVersion = L"version ";
        UINT iLen = lstrlenW(pcwsVersion);
        // Query value of key to get version string
        if (iLen < iVersionMaxLen)
        {
            // copy the "version " string including terminating 0
            wcsncpy_s(info.wchVersion, iVersionMaxLen, pcwsVersion, iLen + 1);

            // get the version string
            cSize = (iVersionMaxLen - iLen) * sizeof(WCHAR); // the size is in bytes
            if (RegQueryValueExW(hKey, NULL, NULL, NULL,
                                 (BYTE*)&info.wchVersion[iLen],
                                 &cSize) == ERROR_SUCCESS)
            {
                info.wchVersion[iVersionMaxLen-1] = 0;
            }
        }
        RegCloseKey(hKey);
    }

    // Open InprocServer32 subkey to get the path to the component
    if (RegOpenKeyExW(hKeyRoot, L"InprocServer32", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
    {
        // Query value of key to get the path string
        WCHAR wchPath[MAX_PATH];
        cSize = sizeof(wchPath);
        if (RegQueryValueExW(hKey, NULL, NULL, NULL, (BYTE*)wchPath, &cSize) == ERROR_SUCCESS)
        {
            // Get the build number from the file version info
            DWORD dwHandle = 0;
            cSize = GetFileVersionInfoSizeW(wchPath, &dwHandle); // returns the size in bytes
            WCHAR* pwchFileVerInfo = NULL;
            if (cSize)
            {
                pwchFileVerInfo = (WCHAR*)new BYTE[cSize];
            }
            if (NULL != pwchFileVerInfo)
            {
                // Retrieve version information for the file
                if (GetFileVersionInfoW(wchPath, 0, cSize, pwchFileVerInfo))
                {
                    // Get the default language id and code page number
                    UINT *pdwLang;
                    UINT cch = 0;
                    if (VerQueryValueW(pwchFileVerInfo, L"\\VarFileInfo\\Translation",
                                       (void**)&pdwLang, &cch) == TRUE)
                    {
                        // Read the file description for the language and code page.
                        const int MAX_SUBBLOCK = 40;
                        WCHAR wchSubBlock[MAX_SUBBLOCK];  // large enough for the string
                        StringCchPrintfExW(wchSubBlock,
                                          MAX_SUBBLOCK,
                                          NULL,
                                          NULL,
                                          STRSAFE_NULL_ON_FAILURE,
                                          L"\\StringFileInfo\\%04x%04x\\FileVersion",
                                          LOWORD(*pdwLang), HIWORD(*pdwLang));

                        WCHAR* pwchBuildVer = NULL;
                        if ((VerQueryValueW(pwchFileVerInfo, wchSubBlock,
                                            (void**)&pwchBuildVer, &cch) == TRUE)
                            && (NULL != pwchBuildVer))
                        {
                            // Format the version string
                            UINT iLen = (UINT)lstrlenW(info.wchVersion);
                            if (0 < iLen)
                            {
                                if (iLen < iVersionMaxLen)
                                {
                                    const WCHAR* pcwsBuild = L", build ";
                                    wcsncpy_s(info.wchVersion + iLen, iVersionMaxLen - iLen, pcwsBuild, iVersionMaxLen - iLen);
                                    iLen += lstrlenW(pcwsBuild);
                                    if (iLen < iVersionMaxLen)
                                    {
                                        wcsncpy_s(info.wchVersion + iLen, iVersionMaxLen - iLen, pwchBuildVer, iVersionMaxLen - iLen);
                                    }
                                }
                            }
                            else
                            {
                                wcsncpy_s(info.wchVersion, iVersionMaxLen, pwchBuildVer, iVersionMaxLen);
                            }
                            info.wchVersion[iVersionMaxLen-1] = 0;
                        }
                    }
                }
                delete [] pwchFileVerInfo;
            }

        }
        RegCloseKey(hKey);
    }

    RegCloseKey(hKeyRoot);

    return TRUE;
}
Example #2
0
static void test_32bit_win(void)
{
    DWORD hdlA, retvalA;
    DWORD hdlW, retvalW = 0;
    BOOL retA,retW;
    PVOID pVersionInfoA = NULL;
    PVOID pVersionInfoW = NULL;
    char *pBufA;
    WCHAR *pBufW;
    UINT uiLengthA, uiLengthW;
    char mypathA[MAX_PATH];
    WCHAR mypathW[MAX_PATH];
    char rootA[] = "\\";
    WCHAR rootW[] = { '\\', 0 };
    WCHAR emptyW[] = { 0 };
    char varfileinfoA[] = "\\VarFileInfo\\Translation";
    WCHAR varfileinfoW[]    = { '\\','V','a','r','F','i','l','e','I','n','f','o',
                                '\\','T','r','a','n','s','l','a','t','i','o','n', 0 };
    char WineVarFileInfoA[] = { 0x09, 0x04, 0xE4, 0x04 };
    char FileDescriptionA[] = "\\StringFileInfo\\040904E4\\FileDescription";
    WCHAR FileDescriptionW[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
                                '\\','0','4','0','9','0','4','E','4',
                                '\\','F','i','l','e','D','e','s','c','r','i','p','t','i','o','n', 0 };
    char WineFileDescriptionA[] = "FileDescription";
    WCHAR WineFileDescriptionW[] = { 'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n', 0 };
    BOOL is_unicode_enabled = TRUE;

    /* A copy from dlls/version/info.c */
    typedef struct
    {
        WORD  wLength;
        WORD  wValueLength;
        WORD  wType;
        WCHAR szKey[1];
#if 0   /* variable length structure */
        /* DWORD aligned */
        BYTE  Value[];
        /* DWORD aligned */
        VS_VERSION_INFO_STRUCT32 Children[];
#endif
    } VS_VERSION_INFO_STRUCT32;

    /* If we call GetFileVersionInfoA on a system that supports Unicode, NT/W2K/XP/W2K3 (by default) and Wine,
     * the versioninfo will contain Unicode strings.
     * Part of the test is to call both the A and W versions, which should have the same Version Information
     * for some requests, on systems that support both calls.
     */

    /* First get the versioninfo via the W versions */
    SetLastError(0xdeadbeef);
    GetModuleFileNameW(NULL, mypathW, MAX_PATH);
    if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
    {
        win_skip("GetModuleFileNameW not existing on this platform, skipping comparison between A- and W-calls\n");
        is_unicode_enabled = FALSE;
    }

    if (is_unicode_enabled)
    { 
        retvalW = GetFileVersionInfoSizeW( mypathW, &hdlW);
        pVersionInfoW = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retvalW );
        retW = GetFileVersionInfoW( mypathW, 0, retvalW, pVersionInfoW );
        ok(retW, "GetFileVersionInfo failed: GetLastError = %u\n", GetLastError());
    }

    GetModuleFileNameA(NULL, mypathA, MAX_PATH);
    retvalA = GetFileVersionInfoSizeA( mypathA, &hdlA);
    pVersionInfoA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retvalA );
    retA = GetFileVersionInfoA( mypathA, 0, retvalA, pVersionInfoA );
    ok(retA, "GetFileVersionInfo failed: GetLastError = %u\n", GetLastError());

    if (is_unicode_enabled)
    { 
        ok( retvalA == retvalW, "The size of the struct should be the same for both A/W calls, it is (%d) vs. (%d)\n",
                                retvalA, retvalW);
        ok( !memcmp(pVersionInfoA, pVersionInfoW, retvalA), "Both structs should be the same, they aren't\n");
    }

    /* The structs on Windows are bigger than just the struct for the basic information. The total struct
     * contains also an empty part, which is used for converted strings. The converted strings are a result
     * of calling VerQueryValueA on a 32bit resource and calling VerQueryValueW on a 16bit resource.
     * The first WORD of the structure (wLength) shows the size of the base struct. The total struct size depends
     * on the Windows version:
     *
     * 16bits resource (numbers are from a sample app):
     *
     * Windows Version    Retrieved with A/W    wLength        StructSize
     * ====================================================================================
     * Win98              A                     0x01B4 (436)   436
     * NT4                A/W                   0x01B4 (436)   2048 ???
     * W2K/XP/W2K3        A/W                   0x01B4 (436)   1536 which is (436 - sizeof(VS_FIXEDFILEINFO)) * 4
     *
     * 32bits resource (numbers are from this test executable version_crosstest.exe):
     * Windows Version    Retrieved with A/W    wLength        StructSize
     * =============================================================
     * Win98              A                     0x01E0 (480)   848 (structure data doesn't seem correct)
     * NT4                A/W                   0x0350 (848)   1272 (848 * 1.5)
     * W2K/XP/W2K3        A/W                   0x0350 (848)   1700 which is (848 * 2) + 4 
     *
     * Wine will follow the implementation (eventually) of W2K/XP/W2K3
     */

    /* Now some tests for the above (only if we are unicode enabled) */

    if (is_unicode_enabled)
    { 
        VS_VERSION_INFO_STRUCT32 *vvis = pVersionInfoW;
        ok ( retvalW == ((vvis->wLength * 2) + 4) || retvalW == (vvis->wLength * 1.5),
             "Structure is not of the correct size\n");
    }

    /* Although the 32bit resource structures contain Unicode strings, VerQueryValueA will always return normal strings,
     * VerQueryValueW will always return Unicode ones. (That means everything returned for StringFileInfo requests).
     */

    /* Get the VS_FIXEDFILEINFO information, this must be the same for both A- and W-Calls */ 

    retA = VerQueryValueA( pVersionInfoA, rootA, (LPVOID *)&pBufA, &uiLengthA );
    ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
    ok ( uiLengthA == sizeof(VS_FIXEDFILEINFO), "Size (%d) doesn't match the size of the VS_FIXEDFILEINFO struct\n", uiLengthA);

    if (is_unicode_enabled)
    { 
        if(0)
        {   /* This causes Vista and w2k8 to crash */
            retW = VerQueryValueW( pVersionInfoW, NULL, (LPVOID *)&pBufW, &uiLengthW );
            ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
        }

        retW = VerQueryValueW( pVersionInfoW, emptyW, (LPVOID *)&pBufW, &uiLengthW );
        ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());

        retW = VerQueryValueW( pVersionInfoW, rootW, (LPVOID *)&pBufW, &uiLengthW );
        ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
        ok ( uiLengthW == sizeof(VS_FIXEDFILEINFO), "Size (%d) doesn't match the size of the VS_FIXEDFILEINFO struct\n", uiLengthW );

        ok( uiLengthA == uiLengthW, "The size of VS_FIXEDFILEINFO should be the same for both A/W calls, it is (%d) vs. (%d)\n",
                                    uiLengthA, uiLengthW);
        ok( !memcmp(pBufA, pBufW, uiLengthA), "Both values should be the same, they aren't\n");
    }

    /* Get some VarFileInfo information, this must be the same for both A- and W-Calls */

    retA = VerQueryValueA( pVersionInfoA, varfileinfoA, (LPVOID *)&pBufA, &uiLengthA );
    ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
    ok( !memcmp(pBufA, WineVarFileInfoA, uiLengthA), "The VarFileInfo should have matched 0904e404 (non case sensitive)\n");

    if (is_unicode_enabled)
    { 
        retW = VerQueryValueW( pVersionInfoW, varfileinfoW, (LPVOID *)&pBufW, &uiLengthW );
        ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
        ok( uiLengthA == uiLengthW, "The size of the VarFileInfo information should be the same for both A/W calls, it is (%d) vs. (%d)\n",
                                    uiLengthA, uiLengthW);
        ok( !memcmp(pBufA, pBufW, uiLengthA), "Both values should be the same, they aren't\n");
    }

    /* Get some StringFileInfo information, this will be ANSI for A-Calls and Unicode for W-Calls */

    retA = VerQueryValueA( pVersionInfoA, FileDescriptionA, (LPVOID *)&pBufA, &uiLengthA );
    ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
    ok( !lstrcmpA(WineFileDescriptionA, pBufA), "expected '%s' got '%s'\n",
        WineFileDescriptionA, pBufA);

    /* Test a second time */
    retA = VerQueryValueA( pVersionInfoA, FileDescriptionA, (LPVOID *)&pBufA, &uiLengthA );
    ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
    ok( !lstrcmpA(WineFileDescriptionA, pBufA), "expected '%s' got '%s'\n",
        WineFileDescriptionA, pBufA);

    if (is_unicode_enabled)
    { 
        retW = VerQueryValueW( pVersionInfoW, FileDescriptionW, (LPVOID *)&pBufW, &uiLengthW );
        ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
        ok( !lstrcmpW(WineFileDescriptionW, pBufW), "FileDescription should have been '%s'\n", WineFileDescriptionA);
    }

    HeapFree( GetProcessHeap(), 0, pVersionInfoA);
    if (is_unicode_enabled)
        HeapFree( GetProcessHeap(), 0, pVersionInfoW);
}
static NTSTATUS NTAPI
patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle)
{
  // We have UCS2 (UTF16?), we want ASCII, but we also just want the filename portion
#define DLLNAME_MAX 128
  char dllName[DLLNAME_MAX+1];
  wchar_t *dll_part;
  DllBlockInfo *info;

  int len = moduleFileName->Length / 2;
  wchar_t *fname = moduleFileName->Buffer;

  // The filename isn't guaranteed to be null terminated, but in practice
  // it always will be; ensure that this is so, and bail if not.
  // This is done instead of the more robust approach because of bug 527122,
  // where lots of weird things were happening when we tried to make a copy.
  if (moduleFileName->MaximumLength < moduleFileName->Length+2 ||
      fname[len] != 0)
  {
#ifdef DEBUG
    printf_stderr("LdrLoadDll: non-null terminated string found!\n");
#endif
    goto continue_loading;
  }

  dll_part = wcsrchr(fname, L'\\');
  if (dll_part) {
    dll_part = dll_part + 1;
    len -= dll_part - fname;
  } else {
    dll_part = fname;
  }

#ifdef DEBUG_very_verbose
  printf_stderr("LdrLoadDll: dll_part '%S' %d\n", dll_part, len);
#endif

  // if it's too long, then, we assume we won't want to block it,
  // since DLLNAME_MAX should be at least long enough to hold the longest
  // entry in our blocklist.
  if (len > DLLNAME_MAX) {
#ifdef DEBUG
    printf_stderr("LdrLoadDll: len too long! %d\n", len);
#endif
    goto continue_loading;
  }

  // copy over to our char byte buffer, lowercasing ASCII as we go
  for (int i = 0; i < len; i++) {
    wchar_t c = dll_part[i];

    if (c > 0x7f) {
      // welp, it's not ascii; if we need to add non-ascii things to
      // our blocklist, we'll have to remove this limitation.
      goto continue_loading;
    }

    // ensure that dll name is all lowercase
    if (c >= 'A' && c <= 'Z')
      c += 'a' - 'A';

    dllName[i] = (char) c;
  }

  dllName[len] = 0;

#ifdef DEBUG_very_verbose
  printf_stderr("LdrLoadDll: dll name '%s'\n", dllName);
#endif

  // then compare to everything on the blocklist
  info = &sWindowsDllBlocklist[0];
  while (info->name) {
    if (strcmp(info->name, dllName) == 0)
      break;

    info++;
  }

  if (info->name) {
    bool load_ok = false;

#ifdef DEBUG_very_verbose
    printf_stderr("LdrLoadDll: info->name: '%s'\n", info->name);
#endif

    if (info->maxVersion != ALL_VERSIONS) {
      // figure out the length of the string that we need
      DWORD pathlen = SearchPathW(filePath, fname, L".dll", 0, NULL, NULL);
      if (pathlen == 0) {
        // uh, we couldn't find the DLL at all, so...
        printf_stderr("LdrLoadDll: Blocking load of '%s' (SearchPathW didn't find it?)\n", dllName);
        return STATUS_DLL_NOT_FOUND;
      }

      wchar_t *full_fname = (wchar_t*) malloc(sizeof(wchar_t)*(pathlen+1));
      if (!full_fname) {
        // couldn't allocate memory?
        return STATUS_DLL_NOT_FOUND;
      }

      // now actually grab it
      SearchPathW(filePath, fname, L".dll", pathlen+1, full_fname, NULL);

      DWORD zero;
      DWORD infoSize = GetFileVersionInfoSizeW(full_fname, &zero);

      // If we failed to get the version information, we block.

      if (infoSize != 0) {
        nsAutoArrayPtr<unsigned char> infoData(new unsigned char[infoSize]);
        VS_FIXEDFILEINFO *vInfo;
        UINT vInfoLen;

        if (GetFileVersionInfoW(full_fname, 0, infoSize, infoData) &&
            VerQueryValueW(infoData, L"\\", (LPVOID*) &vInfo, &vInfoLen))
        {
          unsigned long long fVersion =
            ((unsigned long long)vInfo->dwFileVersionMS) << 32 |
            ((unsigned long long)vInfo->dwFileVersionLS);

          // finally do the version check, and if it's greater than our block
          // version, keep loading
          if (fVersion > info->maxVersion)
            load_ok = true;
        }
      }

      free(full_fname);
    }

    if (!load_ok) {
      printf_stderr("LdrLoadDll: Blocking load of '%s' -- see http://www.mozilla.com/en-US/blocklist/\n", dllName);
      return STATUS_DLL_NOT_FOUND;
    }
  }

continue_loading:
#ifdef DEBUG_very_verbose
  printf_stderr("LdrLoadDll: continuing load... ('%S')\n", moduleFileName->Buffer);
#endif

  NS_SetHasLoadedNewDLLs();

  return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
}
Example #4
0
/**************************************************************************
 *  IQueryAssociations_GetString
 *
 * Get a file association string from the registry.
 *
 * PARAMS
 *  cfFlags  [I]   ASSOCF_ flags from "shlwapi.h"
 *  str      [I]   Type of string to get (ASSOCSTR enum from "shlwapi.h")
 *  pszExtra [I]   Extra information about the string location
 *  pszOut   [O]   Destination for the association string
 *  pcchOut  [I/O] Length of pszOut
 *
 * RETURNS
 *  Success: S_OK. pszOut contains the string, pcchOut contains its length.
 *  Failure: An HRESULT error code indicating the error.
 */
HRESULT STDMETHODCALLTYPE CQueryAssociations::GetString(
    ASSOCF flags,
    ASSOCSTR str,
    LPCWSTR pszExtra,
    LPWSTR pszOut,
    DWORD *pcchOut)
{
    const ASSOCF unimplemented_flags = ~ASSOCF_NOTRUNCATE;
    DWORD len = 0;
    HRESULT hr;
    WCHAR path[MAX_PATH];

    TRACE("(%p)->(0x%08x, %u, %s, %p, %p)\n", this, flags, str, debugstr_w(pszExtra), pszOut, pcchOut);
    if (flags & unimplemented_flags)
    {
        FIXME("%08x: unimplemented flags\n", flags & unimplemented_flags);
    }
    
    if (!pcchOut)
    {
        return E_UNEXPECTED;
    }
    
    if (!this->hkeySource && !this->hkeyProgID)
    {
        return HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION);
    }

    switch (str)
    {
        case ASSOCSTR_COMMAND:
        {
            WCHAR *command;
            hr = this->GetCommand(pszExtra, &command);
            if (SUCCEEDED(hr))
            {
                hr = this->ReturnString(flags, pszOut, pcchOut, command, strlenW(command) + 1);
                HeapFree(GetProcessHeap(), 0, command);
            }
            return hr;
        }
        case ASSOCSTR_EXECUTABLE:
        {
            hr = this->GetExecutable(pszExtra, path, MAX_PATH, &len);
            if (FAILED(hr))
            {
                return hr;
            }
            len++;
            return this->ReturnString(flags, pszOut, pcchOut, path, len);
        }
        case ASSOCSTR_FRIENDLYDOCNAME:
        {
            WCHAR *pszFileType;

            hr = this->GetValue(this->hkeySource, NULL, (void**)&pszFileType, NULL);
            if (FAILED(hr))
            {
                return hr;
            }
            DWORD size = 0;
            DWORD ret = RegGetValueW(HKEY_CLASSES_ROOT, pszFileType, NULL, RRF_RT_REG_SZ, NULL, NULL, &size);
            if (ret == ERROR_SUCCESS)
            {
                WCHAR *docName = static_cast<WCHAR *>(HeapAlloc(GetProcessHeap(), 0, size));
                if (docName)
                {
                    ret = RegGetValueW(HKEY_CLASSES_ROOT, pszFileType, NULL, RRF_RT_REG_SZ, NULL, docName, &size);
                    if (ret == ERROR_SUCCESS)
                    {
                        hr = this->ReturnString(flags, pszOut, pcchOut, docName, strlenW(docName) + 1);
                    }
                    else
                    {
                        hr = HRESULT_FROM_WIN32(ret);
                    }
                    HeapFree(GetProcessHeap(), 0, docName);
                }
                else
                {
                    hr = E_OUTOFMEMORY;
                }
            }
            else
            {
                hr = HRESULT_FROM_WIN32(ret);
            }
            HeapFree(GetProcessHeap(), 0, pszFileType);
            return hr;
        }
        case ASSOCSTR_FRIENDLYAPPNAME:
        {
            PVOID verinfoW = NULL;
            DWORD size, retval = 0;
            UINT flen;
            WCHAR *bufW;
            static const WCHAR translationW[] = L"\\VarFileInfo\\Translation";
            static const WCHAR fileDescFmtW[] = L"\\StringFileInfo\\%04x%04x\\FileDescription";
            WCHAR fileDescW[41];

            hr = this->GetExecutable(pszExtra, path, MAX_PATH, &len);
            if (FAILED(hr))
            {
                return hr;
            }
            retval = GetFileVersionInfoSizeW(path, &size);
            if (!retval)
            {
                goto get_friendly_name_fail;
            }
            verinfoW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, retval);
            if (!verinfoW)
            {
                return E_OUTOFMEMORY;
            }
            if (!GetFileVersionInfoW(path, 0, retval, verinfoW))
            {
                goto get_friendly_name_fail;
            }
            if (VerQueryValueW(verinfoW, translationW, (LPVOID *)&bufW, &flen))
            {
                UINT i;
                DWORD *langCodeDesc = (DWORD *)bufW;
                for (i = 0; i < flen / sizeof(DWORD); i++)
                {
                    sprintfW(fileDescW, fileDescFmtW, LOWORD(langCodeDesc[i]), HIWORD(langCodeDesc[i]));
                    if (VerQueryValueW(verinfoW, fileDescW, (LPVOID *)&bufW, &flen))
                    {
                        /* Does strlenW(bufW) == 0 mean we use the filename? */
                        len = strlenW(bufW) + 1;
                        TRACE("found FileDescription: %s\n", debugstr_w(bufW));
                        hr = this->ReturnString(flags, pszOut, pcchOut, bufW, len);
                        HeapFree(GetProcessHeap(), 0, verinfoW);
                        return hr;
                    }
                }
            }
        get_friendly_name_fail:
            PathRemoveExtensionW(path);
            PathStripPathW(path);
            TRACE("using filename: %s\n", debugstr_w(path));
            hr = this->ReturnString(flags, pszOut, pcchOut, path, strlenW(path) + 1);
            HeapFree(GetProcessHeap(), 0, verinfoW);
            return hr;
        }
        case ASSOCSTR_CONTENTTYPE:
        {
            static const WCHAR Content_TypeW[] = L"Content Type";

            DWORD size = 0;
            DWORD ret = RegGetValueW(this->hkeySource, NULL, Content_TypeW, RRF_RT_REG_SZ, NULL, NULL, &size);
            if (ret != ERROR_SUCCESS)
            {
                return HRESULT_FROM_WIN32(ret);
            }
            WCHAR *contentType = static_cast<WCHAR *>(HeapAlloc(GetProcessHeap(), 0, size));
            if (contentType != NULL)
            {
                ret = RegGetValueW(this->hkeySource, NULL, Content_TypeW, RRF_RT_REG_SZ, NULL, contentType, &size);
                if (ret == ERROR_SUCCESS)
                {
                    hr = this->ReturnString(flags, pszOut, pcchOut, contentType, strlenW(contentType) + 1);
                }
                else
                {
                    hr = HRESULT_FROM_WIN32(ret);
                }
                HeapFree(GetProcessHeap(), 0, contentType);
            }
            else
            {
                hr = E_OUTOFMEMORY;
            }
            return hr;
        }
        case ASSOCSTR_DEFAULTICON:
        {
            static const WCHAR DefaultIconW[] = L"DefaultIcon";
            DWORD ret;
            DWORD size = 0;
            ret = RegGetValueW(this->hkeyProgID, DefaultIconW, NULL, RRF_RT_REG_SZ, NULL, NULL, &size);
            if (ret == ERROR_SUCCESS)
            {
                WCHAR *icon = static_cast<WCHAR *>(HeapAlloc(GetProcessHeap(), 0, size));
                if (icon)
                {
                    ret = RegGetValueW(this->hkeyProgID, DefaultIconW, NULL, RRF_RT_REG_SZ, NULL, icon, &size);
                    if (ret == ERROR_SUCCESS)
                    {
                        hr = this->ReturnString(flags, pszOut, pcchOut, icon, strlenW(icon) + 1);
                    }
                    else
                    {
                        hr = HRESULT_FROM_WIN32(ret);
                    }
                    HeapFree(GetProcessHeap(), 0, icon);
                }
                else
                {
                    hr = HRESULT_FROM_WIN32(ret);
                }
            }
            else
            {
                hr = HRESULT_FROM_WIN32(ret);
            }
            return hr;
        }
        case ASSOCSTR_SHELLEXTENSION:
        {
            static const WCHAR shellexW[] = L"ShellEx\\";
            WCHAR keypath[sizeof(shellexW) / sizeof(shellexW[0]) + 39], guid[39];
            CLSID clsid;
            HKEY hkey;

            hr = CLSIDFromString(pszExtra, &clsid);
            if (FAILED(hr))
            {            
                return hr;
            }
            strcpyW(keypath, shellexW);
            strcatW(keypath, pszExtra);
            LONG ret = RegOpenKeyExW(this->hkeySource, keypath, 0, KEY_READ, &hkey);
            if (ret)
            {
                return HRESULT_FROM_WIN32(ret);
            }
            DWORD size = sizeof(guid);
            ret = RegGetValueW(hkey, NULL, NULL, RRF_RT_REG_SZ, NULL, guid, &size);
            RegCloseKey(hkey);
            if (ret)
            {
                return HRESULT_FROM_WIN32(ret);
            }
            return this->ReturnString(flags, pszOut, pcchOut, guid, size / sizeof(WCHAR));
        }
        
        default:
        {
            FIXME("assocstr %d unimplemented!\n", str);
            return E_NOTIMPL;
        }
    }
}
Example #5
0
bool PluginPackage::fetchInfo()
{
    DWORD versionInfoSize, zeroHandle;
    versionInfoSize = GetFileVersionInfoSizeW(const_cast<UChar*>(m_path.charactersWithNullTermination()), &zeroHandle);
    if (versionInfoSize == 0)
        return false;

    OwnArrayPtr<char> versionInfoData = adoptArrayPtr(new char[versionInfoSize]);

    if (!GetFileVersionInfoW(const_cast<UChar*>(m_path.charactersWithNullTermination()),
            0, versionInfoSize, versionInfoData.get()))
        return false;

    m_name = getVersionInfo(versionInfoData.get(), "ProductName");
    m_description = getVersionInfo(versionInfoData.get(), "FileDescription");
    if (m_name.isNull() || m_description.isNull())
        return false;

    VS_FIXEDFILEINFO* info;
    UINT infoSize;
    if (!VerQueryValueW(versionInfoData.get(), L"\\", (LPVOID*) &info, &infoSize) || infoSize < sizeof(VS_FIXEDFILEINFO))
        return false;
    m_moduleVersion.leastSig = info->dwFileVersionLS;
    m_moduleVersion.mostSig = info->dwFileVersionMS;

    if (isPluginBlacklisted())
        return false;

    Vector<String> types;
    getVersionInfo(versionInfoData.get(), "MIMEType").split('|', types);
    Vector<String> extensionLists;
    getVersionInfo(versionInfoData.get(), "FileExtents").split('|', extensionLists);
    Vector<String> descriptions;
    getVersionInfo(versionInfoData.get(), "FileOpenName").split('|', descriptions);

    for (unsigned i = 0; i < types.size(); i++) {
        String type = types[i].lower();
        String description = i < descriptions.size() ? descriptions[i] : "";
        String extensionList = i < extensionLists.size() ? extensionLists[i] : "";

        Vector<String> extensionsVector;
        extensionList.split(',', extensionsVector);

        // Get rid of the extension list that may be at the end of the description string.
        int pos = description.find("(*");
        if (pos != -1) {
            // There might be a space that we need to get rid of.
            if (pos > 1 && description[pos - 1] == ' ')
                pos--;
            description = description.left(pos);
        }

        // Determine the quirks for the MIME types this plug-in supports
        determineQuirks(type);

        m_mimeToExtensions.add(type, extensionsVector);
        m_mimeToDescriptions.add(type, description);
    }

    return true;
}