| 1 | // XFont.cpp Version 1.1
|
|---|
| 2 | //
|
|---|
| 3 | // Author: Philip Patrick (GetFontProperties)
|
|---|
| 4 | //
|
|---|
| 5 | // Version 1.0 - Initial release of GetFontProperties()
|
|---|
| 6 | //
|
|---|
| 7 | // Modified by: Hans Dietrich
|
|---|
| 8 | // hdietrich2@hotmail.com
|
|---|
| 9 | //
|
|---|
| 10 | // Version 1.1: - Removed MFC dependency from GetFontProperties()
|
|---|
| 11 | // - Converted CFile file I/O to memory mapped file
|
|---|
| 12 | // - Added Unicode support
|
|---|
| 13 | // - Combined with my GetFontFile() routine
|
|---|
| 14 | //
|
|---|
| 15 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 16 |
|
|---|
| 17 | // Slightly modified to build out of the original package available at
|
|---|
| 18 | // http://www.codeproject.com/KB/GDI/xfont.aspx
|
|---|
| 19 |
|
|---|
| 20 | #include <windows.h>
|
|---|
| 21 | #include <tchar.h>
|
|---|
| 22 | #include "XFont.h"
|
|---|
| 23 |
|
|---|
| 24 | #ifdef __GNUC__
|
|---|
| 25 | #define TRACE(a,...) do {} while(0)
|
|---|
| 26 | #else
|
|---|
| 27 | #define TRACE ((void)0)
|
|---|
| 28 | #endif
|
|---|
| 29 | #define _ASSERTE(a) do {} while(0)
|
|---|
| 30 |
|
|---|
| 31 | #ifdef _MSC_VER
|
|---|
| 32 |
|
|---|
| 33 | #pragma warning(disable : 4127) // conditional expression is constant
|
|---|
| 34 |
|
|---|
| 35 | #else
|
|---|
| 36 |
|
|---|
| 37 | #include <minivcrt.h>
|
|---|
| 38 |
|
|---|
| 39 | #endif
|
|---|
| 40 |
|
|---|
| 41 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 42 | // private routines
|
|---|
| 43 | static LONG GetNextNameValue(HKEY key, LPCTSTR subkey, LPTSTR szName, LPTSTR szData);
|
|---|
| 44 | static BOOL GetWinVer(LPTSTR lpszVersion, int nVersionSize, int *nVersion);
|
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 48 | // defines used by GetWinVer()
|
|---|
| 49 | #define WUNKNOWNSTR _T("unknown Windows version")
|
|---|
| 50 |
|
|---|
| 51 | #define W95STR _T("Windows 95")
|
|---|
| 52 | #define W95SP1STR _T("Windows 95 SP1")
|
|---|
| 53 | #define W95OSR2STR _T("Windows 95 OSR2")
|
|---|
| 54 | #define W98STR _T("Windows 98")
|
|---|
| 55 | #define W98SP1STR _T("Windows 98 SP1")
|
|---|
| 56 | #define W98SESTR _T("Windows 98 SE")
|
|---|
| 57 | #define WMESTR _T("Windows ME")
|
|---|
| 58 |
|
|---|
| 59 | #define WNT351STR _T("Windows NT 3.51")
|
|---|
| 60 | #define WNT4STR _T("Windows NT 4")
|
|---|
| 61 | #define W2KSTR _T("Windows 2000")
|
|---|
| 62 | #define WXPSTR _T("Windows XP")
|
|---|
| 63 |
|
|---|
| 64 | #define WCESTR _T("Windows CE")
|
|---|
| 65 |
|
|---|
| 66 |
|
|---|
| 67 | #define WUNKNOWN 0
|
|---|
| 68 |
|
|---|
| 69 | #define W9XFIRST 1
|
|---|
| 70 | #define W95 1
|
|---|
| 71 | #define W95SP1 2
|
|---|
| 72 | #define W95OSR2 3
|
|---|
| 73 | #define W98 4
|
|---|
| 74 | #define W98SP1 5
|
|---|
| 75 | #define W98SE 6
|
|---|
| 76 | #define WME 7
|
|---|
| 77 | #define W9XLAST 99
|
|---|
| 78 |
|
|---|
| 79 | #define WNTFIRST 101
|
|---|
| 80 | #define WNT351 101
|
|---|
| 81 | #define WNT4 102
|
|---|
| 82 | #define W2K 103
|
|---|
| 83 | #define WXP 104
|
|---|
| 84 | #define WNTLAST 199
|
|---|
| 85 |
|
|---|
| 86 | #define WCEFIRST 201
|
|---|
| 87 | #define WCE 201
|
|---|
| 88 | #define WCELAST 299
|
|---|
| 89 |
|
|---|
| 90 |
|
|---|
| 91 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 92 | //
|
|---|
| 93 | // structs used by GetFontProperties()
|
|---|
| 94 | //
|
|---|
| 95 | typedef struct _tagFONT_PROPERTIES_ANSI
|
|---|
| 96 | {
|
|---|
| 97 | char csName[1024];
|
|---|
| 98 | char csCopyright[1024];
|
|---|
| 99 | char csTrademark[1024];
|
|---|
| 100 | char csFamily[1024];
|
|---|
| 101 | } FONT_PROPERTIES_ANSI;
|
|---|
| 102 |
|
|---|
| 103 | typedef struct _tagTT_OFFSET_TABLE
|
|---|
| 104 | {
|
|---|
| 105 | USHORT uMajorVersion;
|
|---|
| 106 | USHORT uMinorVersion;
|
|---|
| 107 | USHORT uNumOfTables;
|
|---|
| 108 | USHORT uSearchRange;
|
|---|
| 109 | USHORT uEntrySelector;
|
|---|
| 110 | USHORT uRangeShift;
|
|---|
| 111 | } TT_OFFSET_TABLE;
|
|---|
| 112 |
|
|---|
| 113 | typedef struct _tagTT_TABLE_DIRECTORY
|
|---|
| 114 | {
|
|---|
| 115 | char szTag[4]; //table name
|
|---|
| 116 | ULONG uCheckSum; //Check sum
|
|---|
| 117 | ULONG uOffset; //Offset from beginning of file
|
|---|
| 118 | ULONG uLength; //length of the table in bytes
|
|---|
| 119 | } TT_TABLE_DIRECTORY;
|
|---|
| 120 |
|
|---|
| 121 | typedef struct _tagTT_NAME_TABLE_HEADER
|
|---|
| 122 | {
|
|---|
| 123 | USHORT uFSelector; //format selector. Always 0
|
|---|
| 124 | USHORT uNRCount; //Name Records count
|
|---|
| 125 | USHORT uStorageOffset; //Offset for strings storage, from start of the table
|
|---|
| 126 | } TT_NAME_TABLE_HEADER;
|
|---|
| 127 |
|
|---|
| 128 | typedef struct _tagTT_NAME_RECORD
|
|---|
| 129 | {
|
|---|
| 130 | USHORT uPlatformID;
|
|---|
| 131 | USHORT uEncodingID;
|
|---|
| 132 | USHORT uLanguageID;
|
|---|
| 133 | USHORT uNameID;
|
|---|
| 134 | USHORT uStringLength;
|
|---|
| 135 | USHORT uStringOffset; //from start of storage area
|
|---|
| 136 | } TT_NAME_RECORD;
|
|---|
| 137 |
|
|---|
| 138 | #define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
|
|---|
| 139 | #define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
|
|---|
| 140 |
|
|---|
| 141 |
|
|---|
| 142 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 143 | //
|
|---|
| 144 | // GetFontFile()
|
|---|
| 145 | //
|
|---|
| 146 | // Purpose: Find the name of font file from the font name
|
|---|
| 147 | //
|
|---|
| 148 | // Parameters: lpszFontName - name of font
|
|---|
| 149 | // lpszDisplayName - pointer to buffer where font display name
|
|---|
| 150 | // will be copied
|
|---|
| 151 | // nDisplayNameSize - size of display name buffer in TCHARs
|
|---|
| 152 | // lpszFontFile - pointer to buffer where font file name
|
|---|
| 153 | // will be copied
|
|---|
| 154 | // nFontFileSize - size of font file buffer in TCHARs
|
|---|
| 155 | //
|
|---|
| 156 | // Returns: BOOL - TRUE = success
|
|---|
| 157 | //
|
|---|
| 158 | // Notes: This is *not* a foolproof method for finding the name of a
|
|---|
| 159 | // font file. If a font has been installed in a normal manner,
|
|---|
| 160 | // and if it is in the Windows "Font" directory, then this method
|
|---|
| 161 | // will probably work. It will probably work for most screen
|
|---|
| 162 | // fonts and TrueType fonts. However, this method might not work
|
|---|
| 163 | // for fonts that are created or installed dynamically, or that
|
|---|
| 164 | // are specific to a particular device, or that are not installed
|
|---|
| 165 | // into the font directory.
|
|---|
| 166 | //
|
|---|
| 167 | extern "C"
|
|---|
| 168 | BOOL GetFontFile(LPCTSTR lpszFontName,
|
|---|
| 169 | LPTSTR lpszDisplayName,
|
|---|
| 170 | int nDisplayNameSize,
|
|---|
| 171 | LPTSTR lpszFontFile,
|
|---|
| 172 | int nFontFileSize)
|
|---|
| 173 | {
|
|---|
| 174 | _ASSERTE(lpszFontName && lpszFontName[0] != 0);
|
|---|
| 175 | if (!lpszFontName || lpszFontName[0] == 0)
|
|---|
| 176 | return FALSE;
|
|---|
| 177 |
|
|---|
| 178 | _ASSERTE(lpszDisplayName);
|
|---|
| 179 | if (!lpszDisplayName)
|
|---|
| 180 | return FALSE;
|
|---|
| 181 |
|
|---|
| 182 | _ASSERTE(lpszFontFile);
|
|---|
| 183 | if (!lpszFontFile)
|
|---|
| 184 | return FALSE;
|
|---|
| 185 |
|
|---|
| 186 | lpszDisplayName[0] = _T('\0');
|
|---|
| 187 | lpszFontFile[0] = _T('\0');
|
|---|
| 188 |
|
|---|
| 189 | TCHAR szName[2 * MAX_PATH];
|
|---|
| 190 | TCHAR szData[2 * MAX_PATH];
|
|---|
| 191 |
|
|---|
| 192 | int nVersion;
|
|---|
| 193 | TCHAR szVersion[100];
|
|---|
| 194 | GetWinVer(szVersion, sizeof(szVersion)/sizeof(TCHAR)-1, &nVersion);
|
|---|
| 195 |
|
|---|
| 196 | TRACE(_T("szVersion=%s\n"), szVersion);
|
|---|
| 197 |
|
|---|
| 198 | TCHAR szFontPath[1000];
|
|---|
| 199 |
|
|---|
| 200 | if ((nVersion >= WNTFIRST) && (nVersion <= WNTLAST))
|
|---|
| 201 | _tcscpy(szFontPath, _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"));
|
|---|
| 202 | else
|
|---|
| 203 | _tcscpy(szFontPath, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Fonts"));
|
|---|
| 204 |
|
|---|
| 205 | BOOL bResult = FALSE;
|
|---|
| 206 |
|
|---|
| 207 | while (GetNextNameValue(HKEY_LOCAL_MACHINE, szFontPath, szName, szData) == ERROR_SUCCESS)
|
|---|
| 208 | {
|
|---|
| 209 | if (_tcsnicmp(lpszFontName, szName, _tcslen(lpszFontName)) == 0)
|
|---|
| 210 | {
|
|---|
| 211 | TRACE(_T("found font\n"));
|
|---|
| 212 | _tcsncpy(lpszDisplayName, szName, nDisplayNameSize-1);
|
|---|
| 213 | _tcsncpy(lpszFontFile, szData, nFontFileSize-1);
|
|---|
| 214 | bResult = TRUE;
|
|---|
| 215 | break;
|
|---|
| 216 | }
|
|---|
| 217 |
|
|---|
| 218 | szFontPath[0] = _T('\0'); // this will get next value, same key
|
|---|
| 219 | }
|
|---|
| 220 |
|
|---|
| 221 | GetNextNameValue(HKEY_LOCAL_MACHINE, NULL, NULL, NULL); // close the registry key
|
|---|
| 222 |
|
|---|
| 223 | return bResult;
|
|---|
| 224 | }
|
|---|
| 225 |
|
|---|
| 226 |
|
|---|
| 227 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 228 | //
|
|---|
| 229 | // GetFontProperties()
|
|---|
| 230 | //
|
|---|
| 231 | // Purpose: Get font name from font file
|
|---|
| 232 | //
|
|---|
| 233 | // Parameters: lpszFilePath - file path of font file
|
|---|
| 234 | // lpFontPropsX - pointer to font properties struct
|
|---|
| 235 | //
|
|---|
| 236 | // Returns: BOOL - TRUE = success
|
|---|
| 237 | //
|
|---|
| 238 | extern "C"
|
|---|
| 239 | BOOL GetFontProperties(LPCTSTR lpszFilePath, FONT_PROPERTIES * lpFontPropsX)
|
|---|
| 240 | {
|
|---|
| 241 | FONT_PROPERTIES_ANSI fp;
|
|---|
| 242 | FONT_PROPERTIES_ANSI * lpFontProps = &fp;
|
|---|
| 243 |
|
|---|
| 244 | memset(lpFontProps, 0, sizeof(FONT_PROPERTIES_ANSI));
|
|---|
| 245 |
|
|---|
| 246 | HANDLE hFile = INVALID_HANDLE_VALUE;
|
|---|
| 247 | hFile = ::CreateFile(lpszFilePath,
|
|---|
| 248 | GENERIC_READ,// | GENERIC_WRITE,
|
|---|
| 249 | 0,
|
|---|
| 250 | NULL,
|
|---|
| 251 | OPEN_ALWAYS,
|
|---|
| 252 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
|---|
| 253 | NULL);
|
|---|
| 254 |
|
|---|
| 255 | if (hFile == INVALID_HANDLE_VALUE)
|
|---|
| 256 | {
|
|---|
| 257 | TRACE(_T("ERROR: failed to open '%s'\n"), lpszFilePath);
|
|---|
| 258 | TRACE(_T("ERROR: %s failed\n"), _T("CreateFile"));
|
|---|
| 259 | return FALSE;
|
|---|
| 260 | }
|
|---|
| 261 |
|
|---|
| 262 | // get the file size
|
|---|
| 263 | DWORD dwFileSize = ::GetFileSize(hFile, NULL);
|
|---|
| 264 |
|
|---|
| 265 | if (dwFileSize == INVALID_FILE_SIZE)
|
|---|
| 266 | {
|
|---|
| 267 | TRACE(_T("ERROR: %s failed\n"), _T("GetFileSize"));
|
|---|
| 268 | ::CloseHandle(hFile);
|
|---|
| 269 | return FALSE;
|
|---|
| 270 | }
|
|---|
| 271 |
|
|---|
| 272 | TRACE(_T("dwFileSize = %d\n"), dwFileSize);
|
|---|
| 273 |
|
|---|
| 274 | // Create a file mapping object that is the current size of the file
|
|---|
| 275 | HANDLE hMappedFile = NULL;
|
|---|
| 276 | hMappedFile = ::CreateFileMapping(hFile,
|
|---|
| 277 | NULL,
|
|---|
| 278 | PAGE_READONLY, //PAGE_READWRITE,
|
|---|
| 279 | 0,
|
|---|
| 280 | dwFileSize,
|
|---|
| 281 | NULL);
|
|---|
| 282 |
|
|---|
| 283 | if (hMappedFile == NULL)
|
|---|
| 284 | {
|
|---|
| 285 | TRACE(_T("ERROR: %s failed\n"), _T("CreateFileMapping"));
|
|---|
| 286 | ::CloseHandle(hFile);
|
|---|
| 287 | return FALSE;
|
|---|
| 288 | }
|
|---|
| 289 |
|
|---|
| 290 | LPBYTE lpMapAddress = (LPBYTE) ::MapViewOfFile(hMappedFile, // handle to file-mapping object
|
|---|
| 291 | FILE_MAP_READ,//FILE_MAP_WRITE, // access mode
|
|---|
| 292 | 0, // high-order DWORD of offset
|
|---|
| 293 | 0, // low-order DWORD of offset
|
|---|
| 294 | 0); // number of bytes to map
|
|---|
| 295 |
|
|---|
| 296 | if (lpMapAddress == NULL)
|
|---|
| 297 | {
|
|---|
| 298 | TRACE(_T("ERROR: %s failed\n"), _T("MapViewOfFile"));
|
|---|
| 299 | ::CloseHandle(hMappedFile);
|
|---|
| 300 | ::CloseHandle(hFile);
|
|---|
| 301 | return FALSE;
|
|---|
| 302 | }
|
|---|
| 303 |
|
|---|
| 304 | BOOL bRetVal = FALSE;
|
|---|
| 305 | int index = 0;
|
|---|
| 306 |
|
|---|
| 307 | TT_OFFSET_TABLE ttOffsetTable;
|
|---|
| 308 | memcpy(&ttOffsetTable, &lpMapAddress[index], sizeof(TT_OFFSET_TABLE));
|
|---|
| 309 | index += sizeof(TT_OFFSET_TABLE);
|
|---|
| 310 |
|
|---|
| 311 | ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
|
|---|
| 312 | ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
|
|---|
| 313 | ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);
|
|---|
| 314 |
|
|---|
| 315 | //check is this is a true type font and the version is 1.0
|
|---|
| 316 | if (ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0)
|
|---|
| 317 | return bRetVal;
|
|---|
| 318 |
|
|---|
| 319 | TT_TABLE_DIRECTORY tblDir;
|
|---|
| 320 | memset(&tblDir, 0, sizeof(TT_TABLE_DIRECTORY));
|
|---|
| 321 | BOOL bFound = FALSE;
|
|---|
| 322 | char szTemp[4096];
|
|---|
| 323 | memset(szTemp, 0, sizeof(szTemp));
|
|---|
| 324 |
|
|---|
| 325 | for (int i = 0; i< ttOffsetTable.uNumOfTables; i++)
|
|---|
| 326 | {
|
|---|
| 327 | //f.Read(&tblDir, sizeof(TT_TABLE_DIRECTORY));
|
|---|
| 328 | memcpy(&tblDir, &lpMapAddress[index], sizeof(TT_TABLE_DIRECTORY));
|
|---|
| 329 | index += sizeof(TT_TABLE_DIRECTORY);
|
|---|
| 330 |
|
|---|
| 331 | strncpy(szTemp, tblDir.szTag, 4);
|
|---|
| 332 | if (stricmp(szTemp, "name") == 0)
|
|---|
| 333 | {
|
|---|
| 334 | bFound = TRUE;
|
|---|
| 335 | tblDir.uLength = SWAPLONG(tblDir.uLength);
|
|---|
| 336 | tblDir.uOffset = SWAPLONG(tblDir.uOffset);
|
|---|
| 337 | break;
|
|---|
| 338 | }
|
|---|
| 339 | else if (szTemp[0] == 0)
|
|---|
| 340 | {
|
|---|
| 341 | break;
|
|---|
| 342 | }
|
|---|
| 343 | }
|
|---|
| 344 |
|
|---|
| 345 | if (bFound)
|
|---|
| 346 | {
|
|---|
| 347 | index = tblDir.uOffset;
|
|---|
| 348 |
|
|---|
| 349 | TT_NAME_TABLE_HEADER ttNTHeader;
|
|---|
| 350 | memcpy(&ttNTHeader, &lpMapAddress[index], sizeof(TT_NAME_TABLE_HEADER));
|
|---|
| 351 | index += sizeof(TT_NAME_TABLE_HEADER);
|
|---|
| 352 |
|
|---|
| 353 | ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
|
|---|
| 354 | ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);
|
|---|
| 355 | TT_NAME_RECORD ttRecord;
|
|---|
| 356 | bFound = FALSE;
|
|---|
| 357 |
|
|---|
| 358 | for (int i = 0;
|
|---|
| 359 | i < ttNTHeader.uNRCount &&
|
|---|
| 360 | (lpFontProps->csCopyright[0] == 0 ||
|
|---|
| 361 | lpFontProps->csName[0] == 0 ||
|
|---|
| 362 | lpFontProps->csTrademark[0] == 0 ||
|
|---|
| 363 | lpFontProps->csFamily[0] == 0);
|
|---|
| 364 | i++)
|
|---|
| 365 | {
|
|---|
| 366 | memcpy(&ttRecord, &lpMapAddress[index], sizeof(TT_NAME_RECORD));
|
|---|
| 367 | index += sizeof(TT_NAME_RECORD);
|
|---|
| 368 |
|
|---|
| 369 | ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
|
|---|
| 370 | ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
|
|---|
| 371 | ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);
|
|---|
| 372 |
|
|---|
| 373 | if (ttRecord.uNameID == 1 || ttRecord.uNameID == 0 || ttRecord.uNameID == 7)
|
|---|
| 374 | {
|
|---|
| 375 | int nPos = index; //f.GetPosition();
|
|---|
| 376 |
|
|---|
| 377 | index = tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset;
|
|---|
| 378 |
|
|---|
| 379 | memset(szTemp, 0, sizeof(szTemp));
|
|---|
| 380 |
|
|---|
| 381 | memcpy(szTemp, &lpMapAddress[index], ttRecord.uStringLength);
|
|---|
| 382 | index += ttRecord.uStringLength;
|
|---|
| 383 |
|
|---|
| 384 | if (szTemp[0] != 0)
|
|---|
| 385 | {
|
|---|
| 386 | _ASSERTE(strlen(szTemp) < sizeof(lpFontProps->csName));
|
|---|
| 387 |
|
|---|
| 388 | switch (ttRecord.uNameID)
|
|---|
| 389 | {
|
|---|
| 390 | case 0:
|
|---|
| 391 | if (lpFontProps->csCopyright[0] == 0)
|
|---|
| 392 | strncpy(lpFontProps->csCopyright, szTemp,
|
|---|
| 393 | sizeof(lpFontProps->csCopyright)-1);
|
|---|
| 394 | break;
|
|---|
| 395 |
|
|---|
| 396 | case 1:
|
|---|
| 397 | if (lpFontProps->csFamily[0] == 0)
|
|---|
| 398 | strncpy(lpFontProps->csFamily, szTemp,
|
|---|
| 399 | sizeof(lpFontProps->csFamily)-1);
|
|---|
| 400 | bRetVal = TRUE;
|
|---|
| 401 | break;
|
|---|
| 402 |
|
|---|
| 403 | case 4:
|
|---|
| 404 | if (lpFontProps->csName[0] == 0)
|
|---|
| 405 | strncpy(lpFontProps->csName, szTemp,
|
|---|
| 406 | sizeof(lpFontProps->csName)-1);
|
|---|
| 407 | break;
|
|---|
| 408 |
|
|---|
| 409 | case 7:
|
|---|
| 410 | if (lpFontProps->csTrademark[0] == 0)
|
|---|
| 411 | strncpy(lpFontProps->csTrademark, szTemp,
|
|---|
| 412 | sizeof(lpFontProps->csTrademark)-1);
|
|---|
| 413 | break;
|
|---|
| 414 |
|
|---|
| 415 | default:
|
|---|
| 416 | break;
|
|---|
| 417 | }
|
|---|
| 418 | }
|
|---|
| 419 | index = nPos;
|
|---|
| 420 | }
|
|---|
| 421 | }
|
|---|
| 422 | }
|
|---|
| 423 |
|
|---|
| 424 | ::UnmapViewOfFile(lpMapAddress);
|
|---|
| 425 | ::CloseHandle(hMappedFile);
|
|---|
| 426 | ::CloseHandle(hFile);
|
|---|
| 427 |
|
|---|
| 428 | if (lpFontProps->csName[0] == 0)
|
|---|
| 429 | strcpy(lpFontProps->csName, lpFontProps->csFamily);
|
|---|
| 430 |
|
|---|
| 431 | memset(lpFontPropsX, 0, sizeof(FONT_PROPERTIES));
|
|---|
| 432 |
|
|---|
| 433 | #ifdef _UNICODE
|
|---|
| 434 | ::MultiByteToWideChar(CP_ACP, 0, lpFontProps->csName, -1, lpFontPropsX->csName,
|
|---|
| 435 | sizeof(lpFontPropsX->csName)/sizeof(TCHAR)-1);
|
|---|
| 436 | ::MultiByteToWideChar(CP_ACP, 0, lpFontProps->csCopyright, -1, lpFontPropsX->csCopyright,
|
|---|
| 437 | sizeof(lpFontPropsX->csCopyright)/sizeof(TCHAR)-1);
|
|---|
| 438 | ::MultiByteToWideChar(CP_ACP, 0, lpFontProps->csTrademark, -1, lpFontPropsX->csTrademark,
|
|---|
| 439 | sizeof(lpFontPropsX->csTrademark)/sizeof(TCHAR)-1);
|
|---|
| 440 | ::MultiByteToWideChar(CP_ACP, 0, lpFontProps->csFamily, -1, lpFontPropsX->csFamily,
|
|---|
| 441 | sizeof(lpFontPropsX->csFamily)/sizeof(TCHAR)-1);
|
|---|
| 442 | #else
|
|---|
| 443 | strcpy(lpFontPropsX->csName, lpFontProps->csName);
|
|---|
| 444 | strcpy(lpFontPropsX->csCopyright, lpFontProps->csCopyright);
|
|---|
| 445 | strcpy(lpFontPropsX->csTrademark, lpFontProps->csTrademark);
|
|---|
| 446 | strcpy(lpFontPropsX->csFamily, lpFontProps->csFamily);
|
|---|
| 447 | #endif
|
|---|
| 448 |
|
|---|
| 449 | return bRetVal;
|
|---|
| 450 | }
|
|---|
| 451 |
|
|---|
| 452 |
|
|---|
| 453 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 454 | //
|
|---|
| 455 | // GetNextNameValue()
|
|---|
| 456 | //
|
|---|
| 457 | // Purpose: Get first/next name/value pair from registry
|
|---|
| 458 | //
|
|---|
| 459 | // Parameters: key - handle to open key, or predefined key
|
|---|
| 460 | // pszSubkey - subkey name
|
|---|
| 461 | // pszName - pointer to buffer that receives the value string
|
|---|
| 462 | // pszData - pointer to buffer that receives the data string
|
|---|
| 463 | //
|
|---|
| 464 | // Returns: LONG - return code from registry function; ERROR_SUCCESS = success
|
|---|
| 465 | //
|
|---|
| 466 | // Notes: If pszSubkey, pszName, and pszData are all NULL, then the open
|
|---|
| 467 | // handle will be closed.
|
|---|
| 468 | //
|
|---|
| 469 | // The first time GetNextNameValue is called, pszSubkey should be
|
|---|
| 470 | // specified. On subsequent calls, pszSubkey should be NULL or
|
|---|
| 471 | // an empty string.
|
|---|
| 472 | //
|
|---|
| 473 | static LONG GetNextNameValue(HKEY key, LPCTSTR pszSubkey, LPTSTR pszName, LPTSTR pszData)
|
|---|
| 474 | {
|
|---|
| 475 | static HKEY hkey = NULL; // registry handle, kept open between calls
|
|---|
| 476 | static DWORD dwIndex = 0; // count of values returned
|
|---|
| 477 | LONG retval;
|
|---|
| 478 |
|
|---|
| 479 | // if all parameters are NULL then close key
|
|---|
| 480 | if (pszSubkey == NULL && pszName == NULL && pszData == NULL)
|
|---|
| 481 | {
|
|---|
| 482 | TRACE(_T("closing key\n"));
|
|---|
| 483 | if (hkey)
|
|---|
| 484 | RegCloseKey(hkey);
|
|---|
| 485 | hkey = NULL;
|
|---|
| 486 | return ERROR_SUCCESS;
|
|---|
| 487 | }
|
|---|
| 488 |
|
|---|
| 489 | // if subkey is specified then open key (first time)
|
|---|
| 490 | if (pszSubkey && pszSubkey[0] != 0)
|
|---|
| 491 | {
|
|---|
| 492 | retval = RegOpenKeyEx(key, pszSubkey, 0, KEY_ALL_ACCESS, &hkey);
|
|---|
| 493 | if (retval != ERROR_SUCCESS)
|
|---|
| 494 | {
|
|---|
| 495 | TRACE(_T("ERROR: RegOpenKeyEx failed\n"));
|
|---|
| 496 | return retval;
|
|---|
| 497 | }
|
|---|
| 498 | else
|
|---|
| 499 | {
|
|---|
| 500 | TRACE(_T("RegOpenKeyEx ok\n"));
|
|---|
| 501 | }
|
|---|
| 502 | dwIndex = 0;
|
|---|
| 503 | }
|
|---|
| 504 | else
|
|---|
| 505 | {
|
|---|
| 506 | dwIndex++;
|
|---|
| 507 | }
|
|---|
| 508 |
|
|---|
| 509 | _ASSERTE(pszName != NULL && pszData != NULL);
|
|---|
| 510 |
|
|---|
| 511 | *pszName = 0;
|
|---|
| 512 | *pszData = 0;
|
|---|
| 513 |
|
|---|
| 514 | TCHAR szValueName[MAX_PATH];
|
|---|
| 515 | DWORD dwValueNameSize = sizeof(szValueName)-1;
|
|---|
| 516 | BYTE szValueData[MAX_PATH];
|
|---|
| 517 | DWORD dwValueDataSize = sizeof(szValueData)-1;
|
|---|
| 518 | DWORD dwType = 0;
|
|---|
| 519 |
|
|---|
| 520 | retval = RegEnumValue(hkey, dwIndex, szValueName, &dwValueNameSize, NULL,
|
|---|
| 521 | &dwType, szValueData, &dwValueDataSize);
|
|---|
| 522 | if (retval == ERROR_SUCCESS)
|
|---|
| 523 | {
|
|---|
| 524 | TRACE(_T("szValueName=<%s> szValueData=<%s>\n"), szValueName, szValueData);
|
|---|
| 525 | lstrcpy(pszName, (LPTSTR)szValueName);
|
|---|
| 526 | lstrcpy(pszData, (LPTSTR)szValueData);
|
|---|
| 527 | }
|
|---|
| 528 | else
|
|---|
| 529 | {
|
|---|
| 530 | TRACE(_T("RegEnumKey failed\n"));
|
|---|
| 531 | }
|
|---|
| 532 |
|
|---|
| 533 | return retval;
|
|---|
| 534 | }
|
|---|
| 535 |
|
|---|
| 536 |
|
|---|
| 537 | // from winbase.h
|
|---|
| 538 | #ifndef VER_PLATFORM_WIN32s
|
|---|
| 539 | #define VER_PLATFORM_WIN32s 0
|
|---|
| 540 | #endif
|
|---|
| 541 | #ifndef VER_PLATFORM_WIN32_WINDOWS
|
|---|
| 542 | #define VER_PLATFORM_WIN32_WINDOWS 1
|
|---|
| 543 | #endif
|
|---|
| 544 | #ifndef VER_PLATFORM_WIN32_NT
|
|---|
| 545 | #define VER_PLATFORM_WIN32_NT 2
|
|---|
| 546 | #endif
|
|---|
| 547 | #ifndef VER_PLATFORM_WIN32_CE
|
|---|
| 548 | #define VER_PLATFORM_WIN32_CE 3
|
|---|
| 549 | #endif
|
|---|
| 550 |
|
|---|
| 551 |
|
|---|
| 552 | /*
|
|---|
| 553 | This table has been assembled from Usenet postings, personal
|
|---|
| 554 | observations, and reading other people's code. Please feel
|
|---|
| 555 | free to add to it or correct it.
|
|---|
| 556 |
|
|---|
| 557 |
|
|---|
| 558 | dwPlatFormID dwMajorVersion dwMinorVersion dwBuildNumber
|
|---|
| 559 | 95 1 4 0 950
|
|---|
| 560 | 95 SP1 1 4 0 >950 && <=1080
|
|---|
| 561 | 95 OSR2 1 4 <10 >1080
|
|---|
| 562 | 98 1 4 10 1998
|
|---|
| 563 | 98 SP1 1 4 10 >1998 && <2183
|
|---|
| 564 | 98 SE 1 4 10 >=2183
|
|---|
| 565 | ME 1 4 90 3000
|
|---|
| 566 |
|
|---|
| 567 | NT 3.51 2 3 51
|
|---|
| 568 | NT 4 2 4 0 1381
|
|---|
| 569 | 2000 2 5 0 2195
|
|---|
| 570 | XP 2 5 1 2600
|
|---|
| 571 |
|
|---|
| 572 | CE 3
|
|---|
| 573 |
|
|---|
| 574 | */
|
|---|
| 575 |
|
|---|
| 576 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 577 | //
|
|---|
| 578 | // GetWinVer()
|
|---|
| 579 | //
|
|---|
| 580 | // Purpose: Get Windows version info
|
|---|
| 581 | //
|
|---|
| 582 | // Parameters: lpszVersion - pointer to buffer that receives the version
|
|---|
| 583 | // string
|
|---|
| 584 | // nVersionSize - size of the version buffer in TCHARs
|
|---|
| 585 | // pnVersion - pointer to int that receives the version code
|
|---|
| 586 | //
|
|---|
| 587 | // Returns: BOOL - TRUE = success
|
|---|
| 588 | //
|
|---|
| 589 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 590 | // GetWinVer
|
|---|
| 591 | static BOOL GetWinVer(LPTSTR lpszVersion, int nVersionSize, int *pnVersion)
|
|---|
| 592 | {
|
|---|
| 593 | _tcsncpy(lpszVersion, WUNKNOWNSTR, nVersionSize-1);
|
|---|
| 594 | *pnVersion = WUNKNOWN;
|
|---|
| 595 |
|
|---|
| 596 | const TCHAR *cp = NULL;
|
|---|
| 597 |
|
|---|
| 598 | OSVERSIONINFO osinfo;
|
|---|
| 599 | osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|---|
| 600 |
|
|---|
| 601 | if (!GetVersionEx(&osinfo))
|
|---|
| 602 | return FALSE;
|
|---|
| 603 |
|
|---|
| 604 | DWORD dwPlatformId = osinfo.dwPlatformId;
|
|---|
| 605 | DWORD dwMinorVersion = osinfo.dwMinorVersion;
|
|---|
| 606 | DWORD dwMajorVersion = osinfo.dwMajorVersion;
|
|---|
| 607 | DWORD dwBuildNumber = osinfo.dwBuildNumber & 0xFFFF; // Win 95 needs this
|
|---|
| 608 | TRACE(_T("%d: %d.%d.%d\n"), dwPlatformId, dwMajorVersion, dwMinorVersion, dwBuildNumber);
|
|---|
| 609 |
|
|---|
| 610 | if ((dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && (dwMajorVersion == 4))
|
|---|
| 611 | {
|
|---|
| 612 | if ((dwMinorVersion < 10) && (dwBuildNumber == 950))
|
|---|
| 613 | {
|
|---|
| 614 | cp = W95STR;
|
|---|
| 615 | *pnVersion = W95;
|
|---|
| 616 | }
|
|---|
| 617 | else if ((dwMinorVersion < 10) &&
|
|---|
| 618 | ((dwBuildNumber > 950) && (dwBuildNumber <= 1080)))
|
|---|
| 619 | {
|
|---|
| 620 | cp = W95SP1STR;
|
|---|
| 621 | *pnVersion = W95SP1;
|
|---|
| 622 | }
|
|---|
| 623 | else if ((dwMinorVersion < 10) && (dwBuildNumber > 1080))
|
|---|
| 624 | {
|
|---|
| 625 | cp = W95OSR2STR;
|
|---|
| 626 | *pnVersion = W95OSR2;
|
|---|
| 627 | }
|
|---|
| 628 | else if ((dwMinorVersion == 10) && (dwBuildNumber == 1998))
|
|---|
| 629 | {
|
|---|
| 630 | cp = W98STR;
|
|---|
| 631 | *pnVersion = W98;
|
|---|
| 632 | }
|
|---|
| 633 | else if ((dwMinorVersion == 10) &&
|
|---|
| 634 | ((dwBuildNumber > 1998) && (dwBuildNumber < 2183)))
|
|---|
| 635 | {
|
|---|
| 636 | cp = W98SP1STR;
|
|---|
| 637 | *pnVersion = W98SP1;
|
|---|
| 638 | }
|
|---|
| 639 | else if ((dwMinorVersion == 10) && (dwBuildNumber >= 2183))
|
|---|
| 640 | {
|
|---|
| 641 | cp = W98SESTR;
|
|---|
| 642 | *pnVersion = W98SE;
|
|---|
| 643 | }
|
|---|
| 644 | else if (dwMinorVersion == 90)
|
|---|
| 645 | {
|
|---|
| 646 | cp = WMESTR;
|
|---|
| 647 | *pnVersion = WME;
|
|---|
| 648 | }
|
|---|
| 649 | }
|
|---|
| 650 | else if (dwPlatformId == VER_PLATFORM_WIN32_NT)
|
|---|
| 651 | {
|
|---|
| 652 | if ((dwMajorVersion == 3) && (dwMinorVersion == 51))
|
|---|
| 653 | {
|
|---|
| 654 | cp = WNT351STR;
|
|---|
| 655 | *pnVersion = WNT351;
|
|---|
| 656 | }
|
|---|
| 657 | else if ((dwMajorVersion == 4) && (dwMinorVersion == 0))
|
|---|
| 658 | {
|
|---|
| 659 | cp = WNT4STR;
|
|---|
| 660 | *pnVersion = WNT4;
|
|---|
| 661 | }
|
|---|
| 662 | else if ((dwMajorVersion == 5) && (dwMinorVersion == 0))
|
|---|
| 663 | {
|
|---|
| 664 | cp = W2KSTR;
|
|---|
| 665 | *pnVersion = W2K;
|
|---|
| 666 | }
|
|---|
| 667 | else if ((dwMajorVersion == 5) && (dwMinorVersion == 1))
|
|---|
| 668 | {
|
|---|
| 669 | cp = WXPSTR;
|
|---|
| 670 | *pnVersion = WXP;
|
|---|
| 671 | }
|
|---|
| 672 | }
|
|---|
| 673 | else if (dwPlatformId == VER_PLATFORM_WIN32_CE)
|
|---|
| 674 | {
|
|---|
| 675 | cp = WCESTR;
|
|---|
| 676 | *pnVersion = WCE;
|
|---|
| 677 | }
|
|---|
| 678 |
|
|---|
| 679 | _tcsncpy(lpszVersion, cp, nVersionSize-1);
|
|---|
| 680 |
|
|---|
| 681 | return TRUE;
|
|---|
| 682 | }
|
|---|
| 683 |
|
|---|