243 lines
6.0 KiB
C++
243 lines
6.0 KiB
C++
/********************************************************************
|
|
|
|
wfdlgs2.c
|
|
|
|
More Windows File System Dialog procedures
|
|
|
|
Copyright (C) 1992-1993 Microsoft Corp.
|
|
All rights reserved
|
|
|
|
********************************************************************/
|
|
|
|
#include "windows.h"
|
|
#include "winhstb.h"
|
|
|
|
|
|
DWORD dwHandle; // version subsystem handle
|
|
HANDLE hmemVersion=0; // global handle for version data buffer
|
|
LPTSTR lpVersionBuffer; // pointer to version data
|
|
DWORD dwVersionSize; // size of the version data
|
|
TCHAR szVersionKey[60]; // big enough for anything we need
|
|
LPWORD lpXlate; // ptr to translations data
|
|
UINT cXlate; // count of translations
|
|
LPWSTR pszXlate = NULL;
|
|
UINT cchXlateString;
|
|
|
|
#define LANGLEN 45 // characters per language
|
|
|
|
#define VER_KEY_END 25 // length of "\StringFileInfo\xxxx\yyyy" (chars)
|
|
#define VER_BLOCK_OFFSET 24 // to get block size (chars)
|
|
|
|
// (not localized)
|
|
TCHAR szInternalName[] = TEXT("InternalName");
|
|
|
|
|
|
void FreeVersionInfo(void);
|
|
|
|
|
|
|
|
|
|
// Gets a particular datum about a file. The file's version info
|
|
// should have already been loaded by GetVersionInfo. If no datum
|
|
// by the specified name is available, NULL is returned. The name
|
|
// specified should be just the name of the item itself; it will
|
|
// be concatenated onto "\StringFileInfo\xxxxyyyy\" automatically.
|
|
|
|
// Version datum names are not localized, so it's OK to pass literals
|
|
// such as "FileVersion" to this function.
|
|
|
|
LPTSTR
|
|
GetVersionDatum(LPTSTR pszName)
|
|
{
|
|
DWORD cbValue=0;
|
|
LPTSTR lpValue;
|
|
|
|
if (!hmemVersion)
|
|
return NULL;
|
|
|
|
lstrcpy(szVersionKey + VER_KEY_END, pszName);
|
|
|
|
VerQueryValue(lpVersionBuffer, szVersionKey, (LPVOID*)&lpValue, (PUINT)&cbValue);
|
|
|
|
return (cbValue != 0) ? lpValue : NULL;
|
|
}
|
|
|
|
// Initialize version information for the properties dialog. The
|
|
// above global variables are initialized by this function, and
|
|
// remain valid (for the specified file only) until FreeVersionInfo
|
|
// is called.
|
|
|
|
// Try in the following order
|
|
//
|
|
// 1. Current language winfile is running in.
|
|
// 2. English, 0409 codepage
|
|
// 3. English, 0000 codepage
|
|
// 4. First translation in resource
|
|
// "\VarFileInfo\Translations" section
|
|
|
|
// GetVersionInfo returns LPTSTR (point to Internal Name)
|
|
// if the version info was read OK,
|
|
// otherwise NULL. If the return is NULL, the buffer may still
|
|
// have been allocated; always call FreeVersionInfo to be safe.
|
|
//
|
|
// pszPath is modified by this call (pszName is appended).
|
|
//
|
|
// Note, Codepage is bogus, since everything is really in unicode.
|
|
// Note, Language is bogus, since FindResourceEx takes a langauge already...
|
|
|
|
|
|
LPTSTR
|
|
GetVersionInfo(PTSTR pszPath, PTSTR pszName)
|
|
{
|
|
DWORD cbValue=0;
|
|
DWORD cbValueTranslation=0;
|
|
LPTSTR lpszValue=NULL;
|
|
LCID lcid;
|
|
|
|
|
|
//
|
|
// Just in case, free old version buffer.
|
|
//
|
|
if (hmemVersion)
|
|
FreeVersionInfo();
|
|
|
|
lstrcat(pszPath,L"\\");
|
|
|
|
// pszPath = fully qualified name
|
|
lstrcat(pszPath, pszName);
|
|
|
|
dwVersionSize = GetFileVersionInfoSizeW(pszPath, &dwHandle);
|
|
|
|
if (dwVersionSize == 0L)
|
|
// no version info
|
|
return NULL;
|
|
|
|
//
|
|
// The value returned from GetFileVersionInfoSize is actually
|
|
// a byte count.
|
|
//
|
|
hmemVersion = GlobalAlloc(GPTR, dwVersionSize);
|
|
if (hmemVersion == NULL)
|
|
// can't get memory for version info, blow out
|
|
return NULL;
|
|
|
|
lpVersionBuffer = (LPTSTR)GlobalLock(hmemVersion);
|
|
|
|
//
|
|
// If we fail, just return NULL. hmemVersion will be freed the next
|
|
// time we do a version call.
|
|
//
|
|
if (!GetFileVersionInfoW(pszPath, dwHandle, dwVersionSize, lpVersionBuffer))
|
|
return NULL;
|
|
|
|
//
|
|
// We must always get the translation since we want to display
|
|
// all the languages anyway.
|
|
//
|
|
VerQueryValue(lpVersionBuffer, TEXT("\\VarFileInfo\\Translation"),
|
|
(LPVOID*)&lpXlate, (PUINT)&cbValueTranslation);
|
|
|
|
if (cbValueTranslation != 0) {
|
|
|
|
//
|
|
// We found some translations above; use the first one.
|
|
//
|
|
cXlate = cbValueTranslation / sizeof(DWORD);
|
|
|
|
//
|
|
// figure 45 LANGLEN chars per lang name
|
|
//
|
|
cchXlateString = cXlate * LANGLEN;
|
|
pszXlate = (LPWSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(cchXlateString));
|
|
|
|
} else {
|
|
lpXlate = NULL;
|
|
}
|
|
|
|
//
|
|
// First try the language we are currently in.
|
|
//
|
|
lcid = GetThreadLocale();
|
|
wsprintf(szVersionKey, TEXT("\\StringFileInfo\\%04X04B0\\"),
|
|
LANGIDFROMLCID(lcid));
|
|
|
|
lpszValue = GetVersionDatum(szInternalName);
|
|
|
|
if (lpszValue != NULL)
|
|
return lpszValue;
|
|
|
|
//
|
|
// Now try the first translation
|
|
//
|
|
if (cbValueTranslation != 0) {
|
|
|
|
wsprintf(szVersionKey, TEXT("\\StringFileInfo\\%04X%04X\\"),
|
|
*lpXlate, *(lpXlate+1));
|
|
|
|
//
|
|
// a required field
|
|
//
|
|
lpszValue = GetVersionDatum(szInternalName);
|
|
|
|
if (lpszValue != NULL) {
|
|
|
|
//
|
|
// localized key found version data
|
|
//
|
|
return lpszValue;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Now try the english, unicode
|
|
//
|
|
lstrcpy(szVersionKey, TEXT("\\StringFileInfo\\040904B0\\"));
|
|
lpszValue = GetVersionDatum(szInternalName);
|
|
|
|
if (lpszValue != NULL)
|
|
return lpszValue;
|
|
|
|
|
|
//
|
|
// Try english with various code pages
|
|
// (04E4) here
|
|
//
|
|
lstrcpy(szVersionKey, TEXT("\\StringFileInfo\\040904E4\\"));
|
|
lpszValue = GetVersionDatum(szInternalName);
|
|
|
|
if (lpszValue != NULL)
|
|
return lpszValue; // localized key found version data
|
|
|
|
|
|
//
|
|
// Try english with various code pages
|
|
// (0000) here
|
|
//
|
|
lstrcpy(szVersionKey, TEXT("\\StringFileInfo\\04090000\\"));
|
|
lpszValue = GetVersionDatum(szInternalName);
|
|
|
|
return lpszValue;
|
|
}
|
|
|
|
// Frees global version data about a file. After this call, all
|
|
// GetVersionDatum calls will return NULL. To avoid memory leaks,
|
|
// always call this before the main properties dialog exits.
|
|
|
|
VOID
|
|
FreeVersionInfo(VOID)
|
|
{
|
|
lpVersionBuffer = NULL;
|
|
dwHandle = 0L;
|
|
if (hmemVersion) {
|
|
GlobalUnlock(hmemVersion);
|
|
GlobalFree(hmemVersion);
|
|
hmemVersion = 0;
|
|
}
|
|
if (pszXlate) {
|
|
LocalFree((HANDLE)pszXlate);
|
|
pszXlate = NULL;
|
|
}
|
|
}
|
|
|