1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                                                                             %
7 %                                 N   N  TTTTT                                %
8 %                                 NN  N    T                                  %
9 %                                 N N N    T                                  %
10 %                                 N  NN    T                                  %
11 %                                 N   N    T                                  %
12 %                                                                             %
13 %                                                                             %
14 %                   Windows NT Feature Methods for MagickCore                 %
15 %                                                                             %
16 %                               Software Design                               %
17 %                                    Cristy                                   %
18 %                                December 1996                                %
19 %                                                                             %
20 %                                                                             %
21 %  Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization      %
22 %  dedicated to making software imaging solutions freely available.           %
23 %                                                                             %
24 %  You may not use this file except in compliance with the License.  You may  %
25 %  obtain a copy of the License at                                            %
26 %                                                                             %
27 %    https://imagemagick.org/script/license.php                               %
28 %                                                                             %
29 %  Unless required by applicable law or agreed to in writing, software        %
30 %  distributed under the License is distributed on an "AS IS" BASIS,          %
31 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
32 %  See the License for the specific language governing permissions and        %
33 %  limitations under the License.                                             %
34 %                                                                             %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 %
37 %
38 */
39 
40 /*
41   Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
45 #define WIN32_LEAN_AND_MEAN
46 #define VC_EXTRALEAN
47 #include <windows.h>
48 #include "MagickCore/cache.h"
49 #include "MagickCore/colorspace.h"
50 #include "MagickCore/colorspace-private.h"
51 #include "MagickCore/draw.h"
52 #include "MagickCore/exception.h"
53 #include "MagickCore/exception-private.h"
54 #include "MagickCore/image-private.h"
55 #include "MagickCore/memory_.h"
56 #include "MagickCore/memory-private.h"
57 #include "MagickCore/monitor.h"
58 #include "MagickCore/monitor-private.h"
59 #include "MagickCore/nt-base.h"
60 #include "MagickCore/nt-base-private.h"
61 #include "MagickCore/pixel-accessor.h"
62 #include "MagickCore/quantum.h"
63 #include "MagickCore/string_.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/splay-tree.h"
66 #include "MagickCore/utility.h"
67 
68 /*
69 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70 %                                                                             %
71 %                                                                             %
72 %                                                                             %
73 %   I s M a g i c k C o n f l i c t                                           %
74 %                                                                             %
75 %                                                                             %
76 %                                                                             %
77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 %
79 %  IsMagickConflict() returns true if the image format conflicts with a logical
80 %  drive (.e.g. X:).
81 %
82 %  The format of the IsMagickConflict method is:
83 %
84 %      MagickBooleanType IsMagickConflict(const char *magick)
85 %
86 %  A description of each parameter follows:
87 %
88 %    o magick: Specifies the image format.
89 %
90 */
NTIsMagickConflict(const char * magick)91 MagickExport MagickBooleanType NTIsMagickConflict(const char *magick)
92 {
93   MagickBooleanType
94     status;
95 
96   assert(magick != (char *) NULL);
97   if (strlen(magick) > 1)
98     return(MagickFalse);
99   status=(GetLogicalDrives() & (1 << ((LocaleUppercase((int)
100     (*magick)))-'A'))) != 0 ? MagickTrue : MagickFalse;
101   return(status);
102 }
103 
104 /*
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 %                                                                             %
107 %                                                                             %
108 %                                                                             %
109 %   N T A c q u i r e T y p e C a c h e                                       %
110 %                                                                             %
111 %                                                                             %
112 %                                                                             %
113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 %
115 %  NTAcquireTypeCache() loads a Windows TrueType fonts.
116 %
117 %  The format of the NTAcquireTypeCache method is:
118 %
119 %      MagickBooleanType NTAcquireTypeCache(SplayTreeInfo *type_cache)
120 %
121 %  A description of each parameter follows:
122 %
123 %    o type_cache: A linked list of fonts.
124 %
125 */
NTAcquireTypeCache(SplayTreeInfo * type_cache,ExceptionInfo * exception)126 MagickExport MagickBooleanType NTAcquireTypeCache(SplayTreeInfo *type_cache,
127   ExceptionInfo *exception)
128 {
129   HKEY
130     reg_key = (HKEY) INVALID_HANDLE_VALUE;
131 
132   LONG
133     res;
134 
135   int
136     list_entries = 0;
137 
138   char
139     buffer[MagickPathExtent],
140     system_root[MagickPathExtent],
141     font_root[MagickPathExtent];
142 
143   DWORD
144     type,
145     system_root_length;
146 
147   MagickBooleanType
148     status;
149 
150   /*
151     Try to find the right Windows*\CurrentVersion key, the SystemRoot and
152     then the Fonts key
153   */
154   res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
155     "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &reg_key);
156   if (res == ERROR_SUCCESS) {
157     system_root_length=sizeof(system_root)-1;
158     res = RegQueryValueExA(reg_key,"SystemRoot",NULL, &type,
159       (BYTE*) system_root, &system_root_length);
160   }
161   if (res != ERROR_SUCCESS) {
162     res = RegOpenKeyExA (HKEY_LOCAL_MACHINE,
163       "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, KEY_READ, &reg_key);
164     if (res == ERROR_SUCCESS) {
165       system_root_length=sizeof(system_root)-1;
166       res = RegQueryValueExA(reg_key,"SystemRoot",NULL, &type,
167         (BYTE*)system_root, &system_root_length);
168     }
169   }
170   if (res == ERROR_SUCCESS)
171     res = RegOpenKeyExA (reg_key, "Fonts",0, KEY_READ, &reg_key);
172   if (res != ERROR_SUCCESS)
173     return(MagickFalse);
174   *font_root='\0';
175   (void) CopyMagickString(buffer,system_root,MagickPathExtent);
176   (void) ConcatenateMagickString(buffer,"\\fonts\\arial.ttf",MagickPathExtent);
177   if (IsPathAccessible(buffer) != MagickFalse)
178     {
179       (void) CopyMagickString(font_root,system_root,MagickPathExtent);
180       (void) ConcatenateMagickString(font_root,"\\fonts\\",MagickPathExtent);
181     }
182   else
183     {
184       (void) CopyMagickString(font_root,system_root,MagickPathExtent);
185       (void) ConcatenateMagickString(font_root,"\\",MagickPathExtent);
186     }
187 
188   {
189     TypeInfo
190       *type_info;
191 
192     DWORD
193       registry_index = 0,
194       type,
195       value_data_size,
196       value_name_length;
197 
198     char
199       value_data[MagickPathExtent],
200       value_name[MagickPathExtent];
201 
202     res = ERROR_SUCCESS;
203 
204     while (res != ERROR_NO_MORE_ITEMS)
205       {
206         char
207           *family_extent,
208           token[MagickPathExtent],
209           *pos,
210           *q;
211 
212         value_name_length = sizeof(value_name) - 1;
213         value_data_size = sizeof(value_data) - 1;
214         res = RegEnumValueA ( reg_key, registry_index, value_name,
215           &value_name_length, 0, &type, (BYTE*)value_data, &value_data_size);
216         registry_index++;
217         if (res != ERROR_SUCCESS)
218           continue;
219         if ( (pos = strstr(value_name, " (TrueType)")) == (char*) NULL )
220           continue;
221         *pos='\0'; /* Remove (TrueType) from string */
222 
223         type_info=(TypeInfo *) AcquireCriticalMemory(sizeof(*type_info));
224         (void) memset(type_info,0,sizeof(TypeInfo));
225 
226         type_info->path=ConstantString("Windows Fonts");
227         type_info->signature=MagickCoreSignature;
228 
229         /* Name */
230         (void) CopyMagickString(buffer,value_name,MagickPathExtent);
231         for(pos = buffer; *pos != 0 ; pos++)
232           if (*pos == ' ')
233             *pos = '-';
234         type_info->name=ConstantString(buffer);
235 
236         /* Fullname */
237         type_info->description=ConstantString(value_name);
238 
239         /* Format */
240         type_info->format=ConstantString("truetype");
241 
242         /* Glyphs */
243         if (strchr(value_data,'\\') != (char *) NULL)
244           (void) CopyMagickString(buffer,value_data,MagickPathExtent);
245         else
246           {
247             (void) CopyMagickString(buffer,font_root,MagickPathExtent);
248             (void) ConcatenateMagickString(buffer,value_data,MagickPathExtent);
249           }
250 
251         LocaleLower(buffer);
252         type_info->glyphs=ConstantString(buffer);
253 
254         type_info->stretch=NormalStretch;
255         type_info->style=NormalStyle;
256         type_info->weight=400;
257 
258         /* Some fonts are known to require special encodings */
259         if ( (LocaleCompare(type_info->name, "Symbol") == 0 ) ||
260              (LocaleCompare(type_info->name, "Wingdings") == 0 ) ||
261              (LocaleCompare(type_info->name, "Wingdings-2") == 0 ) ||
262              (LocaleCompare(type_info->name, "Wingdings-3") == 0 ) )
263           type_info->encoding=ConstantString("AppleRoman");
264 
265         family_extent=value_name;
266 
267         for (q=value_name; *q != '\0'; )
268           {
269             GetNextToken(q,(const char **) &q,MagickPathExtent,token);
270             if (*token == '\0')
271               break;
272 
273             if (LocaleCompare(token,"Italic") == 0)
274               {
275                 type_info->style=ItalicStyle;
276               }
277 
278             else if (LocaleCompare(token,"Oblique") == 0)
279               {
280                 type_info->style=ObliqueStyle;
281               }
282 
283             else if (LocaleCompare(token,"Bold") == 0)
284               {
285                 type_info->weight=700;
286               }
287 
288             else if (LocaleCompare(token,"Thin") == 0)
289               {
290                 type_info->weight=100;
291               }
292 
293             else if ( (LocaleCompare(token,"ExtraLight") == 0) ||
294                       (LocaleCompare(token,"UltraLight") == 0) )
295               {
296                 type_info->weight=200;
297               }
298 
299             else if (LocaleCompare(token,"Light") == 0)
300               {
301                 type_info->weight=300;
302               }
303 
304             else if ( (LocaleCompare(token,"Normal") == 0) ||
305                       (LocaleCompare(token,"Regular") == 0) )
306               {
307                 type_info->weight=400;
308               }
309 
310             else if (LocaleCompare(token,"Medium") == 0)
311               {
312                 type_info->weight=500;
313               }
314 
315             else if ( (LocaleCompare(token,"SemiBold") == 0) ||
316                       (LocaleCompare(token,"DemiBold") == 0) )
317               {
318                 type_info->weight=600;
319               }
320 
321             else if ( (LocaleCompare(token,"ExtraBold") == 0) ||
322                       (LocaleCompare(token,"UltraBold") == 0) )
323               {
324                 type_info->weight=800;
325               }
326 
327             else if ( (LocaleCompare(token,"Heavy") == 0) ||
328                       (LocaleCompare(token,"Black") == 0) )
329               {
330                 type_info->weight=900;
331               }
332 
333             else if (LocaleCompare(token,"Condensed") == 0)
334               {
335                 type_info->stretch = CondensedStretch;
336               }
337 
338             else if (LocaleCompare(token,"Expanded") == 0)
339               {
340                 type_info->stretch = ExpandedStretch;
341               }
342 
343             else if (LocaleCompare(token,"ExtraCondensed") == 0)
344               {
345                 type_info->stretch = ExtraCondensedStretch;
346               }
347 
348             else if (LocaleCompare(token,"ExtraExpanded") == 0)
349               {
350                 type_info->stretch = ExtraExpandedStretch;
351               }
352 
353             else if (LocaleCompare(token,"SemiCondensed") == 0)
354               {
355                 type_info->stretch = SemiCondensedStretch;
356               }
357 
358             else if (LocaleCompare(token,"SemiExpanded") == 0)
359               {
360                 type_info->stretch = SemiExpandedStretch;
361               }
362 
363             else if (LocaleCompare(token,"UltraCondensed") == 0)
364               {
365                 type_info->stretch = UltraCondensedStretch;
366               }
367 
368             else if (LocaleCompare(token,"UltraExpanded") == 0)
369               {
370                 type_info->stretch = UltraExpandedStretch;
371               }
372 
373             else
374               {
375                 family_extent=q;
376               }
377           }
378 
379         (void) CopyMagickString(buffer,value_name,family_extent-value_name+1);
380         StripString(buffer);
381         type_info->family=ConstantString(buffer);
382 
383         list_entries++;
384         status=AddValueToSplayTree(type_cache,type_info->name,type_info);
385         if (status == MagickFalse)
386           (void) ThrowMagickException(exception,GetMagickModule(),
387             ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
388       }
389   }
390   RegCloseKey ( reg_key );
391   return(MagickTrue);
392 }
393 
394 #endif
395