Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

696 lines
17 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. psqfont.c
  5. Abstract:
  6. This DLL is responsible for the FONTLIST management of the PSTODIB
  7. component of MACPRINT. It will enumerate the fontsubtitution table
  8. in the registry and build a composite font list that maps PostScript
  9. font names to TrueType TTF files installed on the current system. This
  10. list is built from scratch, by enumerating the postscript to true
  11. type list and checking to see which fonts are actually installed in
  12. the NT font list.
  13. Author:
  14. James Bratsanos <v-jimbr@microsoft.com or mcrafts!jamesb>
  15. Revision History:
  16. 22 Nov 1992 Initial Version
  17. 14 Jun 1993 Took out code to put new font list into registry
  18. Notes: Tab stop: 4
  19. --*/
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include "psqfont.h"
  24. #include "psqfontp.h"
  25. #include "psqdefp.h"
  26. //GLOBALS
  27. HANDLE hInst; // Global handle to our instance
  28. /* This entry point is called on DLL initialisation.
  29. * We need to know the module handle so we can load resources.
  30. */
  31. BOOL PsQDLLInit(
  32. IN PVOID hmod,
  33. IN DWORD Reason,
  34. IN PCONTEXT pctx OPTIONAL)
  35. {
  36. DBG_UNREFERENCED_PARAMETER(pctx);
  37. if (Reason == DLL_PROCESS_ATTACH)
  38. {
  39. hInst = hmod;
  40. }
  41. return TRUE;
  42. }
  43. LPTSTR LocPsAllocAndCopy( HANDLE hHeap, LPTSTR lptStr )
  44. {
  45. DWORD dwStrLen;
  46. LPTSTR lptRet;
  47. // Get some memory from our heap and the copy the string in
  48. dwStrLen = lstrlen( lptStr );
  49. lptRet = (LPTSTR) HeapAlloc( hHeap, 0, (dwStrLen + 1 ) * sizeof(TCHAR));
  50. if (lptRet != NULL) {
  51. // Copy it since the memory allocation succeded
  52. lstrcpy( lptRet, lptStr);
  53. }
  54. return(lptRet);
  55. }
  56. PS_QFONT_ERROR LocPsMakeSubListEntry( PPS_FONT_QUERY pFontQuery,
  57. LPWSTR lpUniNTFontData,
  58. LPTSTR lpFaceName )
  59. {
  60. CHAR szFullPathToTT[MAX_PATH];
  61. WCHAR uniSzFullPathToTT[MAX_PATH];
  62. DWORD dwSizeOfFullPathToTT;
  63. PPS_FONT_ENTRY pPsFontEntry;
  64. PS_QFONT_ERROR pPsError=PS_QFONT_SUCCESS;
  65. //
  66. // Now that we have found a match we need to get the path to
  67. // the TTF name. The entry we have most likely found is an FOT
  68. // file which we need to pass to an INTERNAL function such that
  69. // we may extract the full path to the TTF file name.
  70. //
  71. //
  72. //***** NOTE **********************************************
  73. //DJC NOTE: This is a call to an INTERNAL FUNCTION!!!!!!!
  74. //***** NOTE **********************************************
  75. //
  76. extern GetFontResourceInfoW(LPWSTR,LPDWORD, LPVOID, DWORD);
  77. //
  78. // Set the initial size of the buffer
  79. //
  80. dwSizeOfFullPathToTT = sizeof( uniSzFullPathToTT);
  81. if ( GetFontResourceInfoW(lpUniNTFontData,
  82. &dwSizeOfFullPathToTT,
  83. (LPVOID) uniSzFullPathToTT,
  84. 4L )) // 4 = GFRI_TTFILENAME out of wingdip.h
  85. {
  86. wcstombs( szFullPathToTT, uniSzFullPathToTT, sizeof(szFullPathToTT) );
  87. //
  88. // Okay were in good shape its a true type font...
  89. // This worked meaning we have a real value so lets write it
  90. // to the current list
  91. //
  92. if (pFontQuery->dwNumFonts < PSQFONT_MAX_FONTS) {
  93. pPsFontEntry = &(pFontQuery->FontEntry[ pFontQuery->dwNumFonts ]);
  94. pPsFontEntry->lpFontName = LocPsAllocAndCopy( pFontQuery->hHeap,
  95. lpFaceName);
  96. pPsFontEntry->dwFontNameLen = lstrlen(lpFaceName) * sizeof(TCHAR)
  97. + sizeof(TCHAR);
  98. pPsFontEntry->lpFontFileName = LocPsAllocAndCopy( pFontQuery->hHeap,
  99. szFullPathToTT);
  100. pPsFontEntry->dwFontFileNameLen = lstrlen(szFullPathToTT) * sizeof(TCHAR)
  101. + sizeof(TCHAR);
  102. pFontQuery->dwNumFonts++;
  103. } else{
  104. //
  105. // Were out of space there are more fonts that match our criteria
  106. // than we are able to report back. This is not a GREAT error message
  107. // but adding a new one would be a change to a semi public header.
  108. //
  109. pPsError = PS_QFONT_ERROR_INDEX_OUT_OF_RANGE;
  110. }
  111. }
  112. return(pPsError);
  113. }
  114. PS_QFONT_ERROR LocPsAddToListIfNTfont( PPS_FONT_QUERY pFontQuery,
  115. HKEY hNTFontlist,
  116. DWORD dwNumNTfonts,
  117. LPTSTR lpPsName,
  118. LPTSTR lpTTData)
  119. {
  120. TCHAR sztNTFontData[MAX_PATH];
  121. WCHAR uniSzNTFontData[MAX_PATH];
  122. DWORD dwNTFontDataLen;
  123. DWORD dwType;
  124. BOOL bFound=FALSE;
  125. // Now query the NT font to see if the font in question exists
  126. dwNTFontDataLen = sizeof(sztNTFontData);
  127. if ( RegQueryValueEx( hNTFontlist,
  128. lpTTData,
  129. NULL,
  130. &dwType,
  131. sztNTFontData,
  132. &dwNTFontDataLen ) == ERROR_SUCCESS ) {
  133. mbstowcs(uniSzNTFontData, sztNTFontData, sizeof(sztNTFontData));
  134. return( LocPsMakeSubListEntry( pFontQuery, uniSzNTFontData, lpPsName ));
  135. }
  136. return( PS_QFONT_SUCCESS );
  137. }
  138. LONG LocPsWriteDefaultSubListToRegistry(void)
  139. {
  140. HKEY hSubstList;
  141. DWORD dwStatus;
  142. LPSTR lpStr;
  143. HRSRC hrSubst;
  144. HRSRC hrLoadSubst;
  145. CHAR szPsName[PSQFONT_SCRATCH_SIZE];
  146. CHAR szTTName[PSQFONT_SCRATCH_SIZE];
  147. LPSTR lpDest;
  148. int iState;
  149. DWORD dwTotalLen;
  150. LONG lRetVal=PS_QFONT_SUCCESS;
  151. // Now lets recreate the new Key
  152. RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  153. PSQFONT_SUBST_LIST,
  154. 0,
  155. NULL,
  156. REG_OPTION_NON_VOLATILE,
  157. KEY_ALL_ACCESS | KEY_WRITE,
  158. NULL,
  159. &hSubstList,
  160. &dwStatus );
  161. hrSubst = FindResourceEx( hInst,
  162. "RAWDATA",
  163. MAKEINTRESOURCE(PSFONTSUB),
  164. 0);
  165. if (hrSubst) {
  166. // Get the size of the resource for future use
  167. dwTotalLen = SizeofResource( hInst, hrSubst);
  168. // We got it... so load it and lock it!!
  169. hrLoadSubst = LoadResource( hInst, hrSubst);
  170. lpStr = (LPSTR) LockResource( hrLoadSubst);
  171. iState = PSP_DOING_PS_NAME;
  172. lpDest = szPsName;
  173. if (lpStr != (LPSTR) NULL) {
  174. // enum through the list adding the keys....
  175. while( dwTotalLen--) {
  176. switch (iState) {
  177. case PSP_DOING_PS_NAME:
  178. if (*lpStr == '=') {
  179. *lpDest = '\000';
  180. iState = PSP_DOING_TT_NAME;
  181. lpDest = szTTName;
  182. }else{
  183. *lpDest++ = *lpStr;
  184. }
  185. break;
  186. case PSP_GETTING_EOL:
  187. if (*lpStr == 0x0a) {
  188. iState = PSP_DOING_PS_NAME;
  189. lpDest = szPsName;
  190. // Now write to the registry
  191. RegSetValueEx( hSubstList,
  192. szPsName,
  193. 0,
  194. REG_SZ,
  195. szTTName,
  196. lstrlen(szTTName)+1);
  197. }
  198. break;
  199. case PSP_DOING_TT_NAME:
  200. if (*lpStr == ';') {
  201. *lpDest = '\000';
  202. iState = PSP_GETTING_EOL;
  203. } else if (*lpStr == 0x0d) {
  204. *lpDest = '\000';
  205. iState = PSP_GETTING_EOL;
  206. }else {
  207. *lpDest++ = *lpStr;
  208. }
  209. break;
  210. }
  211. lpStr++;
  212. }
  213. }
  214. }
  215. RegCloseKey(hSubstList);
  216. return(lRetVal);
  217. }
  218. LONG LocPsGetOrCreateSubstList( PHKEY phKey )
  219. {
  220. LONG lRetVal;
  221. BOOL bDone=FALSE;
  222. lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  223. PSQFONT_SUBST_LIST,
  224. 0,
  225. KEY_READ,
  226. phKey );
  227. if (lRetVal == ERROR_FILE_NOT_FOUND) {
  228. // Since we did not find a font substitute list create a default one!
  229. // in the registry
  230. lRetVal = LocPsWriteDefaultSubListToRegistry();
  231. lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  232. PSQFONT_SUBST_LIST,
  233. 0,
  234. KEY_READ,
  235. phKey );
  236. }
  237. return(lRetVal);
  238. }
  239. //
  240. // LocPsNormalizeFontName
  241. //
  242. // This function takes a font name as Stored in the registry and
  243. // normalizes it by removing all spaces and stops processing when
  244. // it hits a open paren
  245. //
  246. // Parameters:
  247. // LPTSTR lptIN - The source string
  248. // LPTSTR lptOUT - The destination string
  249. //
  250. // Returns:
  251. //
  252. // Nothing...
  253. //
  254. VOID LocPsNormalizeFontName(LPTSTR lptIN, LPTSTR lptOUT)
  255. {
  256. while(*lptIN != '\000' ) {
  257. if (*lptIN == '(' ) {
  258. break;
  259. } else if ( *lptIN != ' ' ) {
  260. *lptOUT++ = *lptIN;
  261. }
  262. lptIN++;
  263. }
  264. *lptOUT = '\000';
  265. }
  266. // verify the list is up to date
  267. PS_QFONT_ERROR LocPsBuildCurrentFontList(PPS_FONT_QUERY pFontQuery )
  268. {
  269. HKEY hNtFontKey;
  270. HKEY hSubstKey;
  271. DWORD dwNumSubstFonts;
  272. FILETIME ftSubstFontsTime;
  273. TCHAR sztPsName[MAX_PATH];
  274. TCHAR sztTTName[MAX_PATH];
  275. DWORD dwPsNameSize;
  276. DWORD dwTTNameSize;
  277. DWORD dwType;
  278. DWORD i;
  279. DWORD dwNumNTFonts;
  280. FILETIME ftNtFontTime;
  281. BOOL bFoundCurrentFontList = FALSE;
  282. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  283. PSQFONT_NT_FONT_LIST,
  284. 0,
  285. KEY_READ,
  286. &hNtFontKey ) != ERROR_SUCCESS ) {
  287. return( PS_QFONT_ERROR_NO_NTFONT_REGISTRY_DATA );
  288. }
  289. LocPsQueryTimeAndValueCount( hNtFontKey,
  290. &dwNumNTFonts,
  291. &ftNtFontTime);
  292. if (LocPsGetOrCreateSubstList( &hSubstKey ) != ERROR_SUCCESS) {
  293. RegCloseKey( hNtFontKey );
  294. return( PS_QFONT_ERROR_FONT_SUB );
  295. }
  296. // Get the value count and file time of the FontSubst entry
  297. LocPsQueryTimeAndValueCount( hSubstKey,
  298. &dwNumSubstFonts,
  299. &ftSubstFontsTime);
  300. // Now we have the real worker code... for each entry in our fontsubstitution
  301. // table we will look to see if the subst font exists in the NT font section
  302. // of the registry. If it does we will generate an enry in our current
  303. // font list that maps a PostScript font name to an TrueType .ttf file
  304. // with the current font.
  305. for( i = 0 ; i < dwNumSubstFonts; i++ ) {
  306. // Query the current font out of the list
  307. dwPsNameSize = sizeof( sztPsName);
  308. dwTTNameSize = sizeof( sztTTName);
  309. if( RegEnumValue( hSubstKey,
  310. i,
  311. sztPsName,
  312. &dwPsNameSize,
  313. NULL,
  314. &dwType,
  315. sztTTName,
  316. &dwTTNameSize ) == ERROR_SUCCESS) {
  317. LocPsAddToListIfNTfont( pFontQuery,
  318. hNtFontKey,
  319. dwNumNTFonts,
  320. sztPsName,
  321. sztTTName);
  322. }
  323. }
  324. RegCloseKey(hNtFontKey);
  325. RegCloseKey(hSubstKey);
  326. return(0);
  327. }
  328. LONG LocPsQueryTimeAndValueCount( HKEY hKey,
  329. LPDWORD lpdwValCount,
  330. PFILETIME lpFileTime)
  331. {
  332. TCHAR lptClassName[500];
  333. DWORD dwClassName=sizeof(lptClassName);
  334. DWORD dwNumSubKeys;
  335. DWORD dwLongestSubKeySize;
  336. DWORD dwMaxClass;
  337. DWORD dwBiggestValueName;
  338. DWORD dwLongestValueName;
  339. DWORD dwSecurityLength;
  340. LONG lRetVal;
  341. lRetVal = RegQueryInfoKey(hKey,
  342. lptClassName,
  343. &dwClassName,
  344. (LPDWORD) NULL,
  345. &dwNumSubKeys,
  346. &dwLongestSubKeySize,
  347. &dwMaxClass,
  348. lpdwValCount,
  349. &dwBiggestValueName,
  350. &dwLongestValueName,
  351. &dwSecurityLength,
  352. lpFileTime);
  353. return(lRetVal);
  354. }
  355. PS_QFONT_ERROR PsBeginFontQuery( PPS_QUERY_FONT_HANDLE pFontQueryHandle)
  356. {
  357. HANDLE hHeap;
  358. PPS_FONT_QUERY pFontQuery;
  359. HANDLE hFontMutex;
  360. // Create the MUTEX that will guarantee us correct behaviour such that
  361. // only one user can go through this code at any time...
  362. //
  363. hFontMutex = CreateMutex( NULL, FALSE, "SFMFontListMutex");
  364. WaitForSingleObject( hFontMutex,INFINITE );
  365. //
  366. // 1st thing create a heap, we make all our allocations off this heap,
  367. // that way cleanup is quick and easy.
  368. //
  369. hHeap = HeapCreate(0, 10000, 0);
  370. if (hHeap == (HANDLE) NULL) {
  371. LocPsEndMutex( hFontMutex);
  372. return( PS_QFONT_ERROR_CANNOT_CREATE_HEAP );
  373. }
  374. pFontQuery = (PPS_FONT_QUERY)
  375. HeapAlloc(
  376. hHeap,
  377. 0,
  378. sizeof( PS_FONT_QUERY) +
  379. (sizeof(PS_FONT_ENTRY) * PSQFONT_MAX_FONTS));
  380. if (pFontQuery == NULL) {
  381. LocPsEndMutex( hFontMutex);
  382. HeapDestroy(hHeap);
  383. return( PS_QFONT_ERROR_NO_MEM);
  384. }
  385. // Now setup up the data for our font query control structure
  386. pFontQuery->hHeap = hHeap;
  387. pFontQuery->dwNumFonts = 0;
  388. pFontQuery->dwSerial = PS_QFONT_SERIAL;
  389. LocPsBuildCurrentFontList( pFontQuery );
  390. *pFontQueryHandle = (PS_QUERY_FONT_HANDLE) pFontQuery;
  391. LocPsEndMutex(hFontMutex);
  392. return(PS_QFONT_SUCCESS);
  393. }
  394. VOID LocPsEndMutex(HANDLE hMutex)
  395. {
  396. // Now release the mutex
  397. ReleaseMutex(hMutex);
  398. // And finally delete it
  399. CloseHandle(hMutex);
  400. }
  401. PS_QFONT_ERROR PsGetNumFontsAvailable( PS_QUERY_FONT_HANDLE pFontQueryHandle,
  402. DWORD *pdwFonts)
  403. {
  404. PPS_FONT_QUERY pFontQuery;
  405. pFontQuery = (PPS_FONT_QUERY) pFontQueryHandle;
  406. if (pFontQueryHandle == NULL || pFontQuery->dwSerial != PS_QFONT_SERIAL) {
  407. return( PS_QFONT_ERROR_INVALID_HANDLE );
  408. }
  409. // Handle is okay so keep going
  410. *pdwFonts = pFontQuery->dwNumFonts;
  411. return(PS_QFONT_SUCCESS);
  412. }
  413. PS_QFONT_ERROR PsGetFontInfo( PS_QUERY_FONT_HANDLE pFontQueryHandle,
  414. DWORD dwIndex,
  415. LPSTR lpFontName,
  416. LPDWORD lpdwSizeOfFontName,
  417. LPSTR lpFontFileName,
  418. LPDWORD lpdwSizeOfFontFileName )
  419. {
  420. PPS_FONT_QUERY pFontQuery;
  421. PPS_FONT_ENTRY pFontEntry;
  422. PS_QFONT_ERROR QfontError=PS_QFONT_SUCCESS;
  423. pFontQuery = (PPS_FONT_QUERY) pFontQueryHandle;
  424. if (pFontQueryHandle == NULL || pFontQuery->dwSerial != PS_QFONT_SERIAL) {
  425. return( PS_QFONT_ERROR_INVALID_HANDLE );
  426. }
  427. // Verify the index is in range and return the info
  428. if (dwIndex >= pFontQuery->dwNumFonts) {
  429. return PS_QFONT_ERROR_INDEX_OUT_OF_RANGE;
  430. }
  431. pFontEntry = &(pFontQuery->FontEntry[ dwIndex ]);
  432. // Dont do the copy if the ptr is null but only return the
  433. // required bytes
  434. if (lpFontName != NULL) {
  435. // Okay the user requested data so make sure there is enough
  436. // room and return the font name
  437. if (*lpdwSizeOfFontName >= pFontEntry->dwFontNameLen) {
  438. lstrcpy( lpFontName, pFontEntry->lpFontName);
  439. }else{
  440. QfontError = PS_QFONT_ERROR_FONTNAMEBUFF_TOSMALL;
  441. }
  442. }
  443. // either way set up the required size
  444. *lpdwSizeOfFontName = pFontEntry->dwFontNameLen;
  445. // Now handle the font file name
  446. if (lpFontFileName != NULL) {
  447. if (*lpdwSizeOfFontFileName >= pFontEntry->dwFontFileNameLen) {
  448. lstrcpy( lpFontFileName, pFontEntry->lpFontFileName);
  449. }else if (QfontError == PS_QFONT_SUCCESS ) {
  450. QfontError = PS_QFONT_ERROR_FONTFILEBUFF_TOSMALL;
  451. }
  452. }
  453. *lpdwSizeOfFontFileName = pFontEntry->dwFontFileNameLen;
  454. return(QfontError);
  455. }
  456. PS_QFONT_ERROR PsEndFontQuery( PS_QUERY_FONT_HANDLE pFontQueryHandle)
  457. {
  458. PPS_FONT_QUERY pFontQuery;
  459. pFontQuery = (PPS_FONT_QUERY) pFontQueryHandle;
  460. if (pFontQueryHandle == NULL || pFontQuery->dwSerial != PS_QFONT_SERIAL) {
  461. return( PS_QFONT_ERROR_INVALID_HANDLE );
  462. }
  463. // very simple verify the handle and destroy the heap, since all allocations
  464. // were done off the heap were done...
  465. HeapDestroy( pFontQuery->hHeap );
  466. return(0);
  467. }
  468. 
  469.