NT4/private/windows/win4help/winhstb/wfdlgs2.cpp
2020-09-30 17:12:29 +02:00

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;
}
}