|
|
1.1 root 1: This document describes how messages will be input, stored and formatted
2: by a Win32 application.
3:
4: 1. Message Input
5:
6: Messages are input as ASCII text in a text file. The format of this
7: file supports specifying multiple versions of the same message text,
8: one for each language supported. It also supports automatic assignment
9: of code numbers to each message, along with the generation of a C
10: language include file for use by the application for accessing the
11: messages using symbolic constants. The purpose of the message text
12: file is to define all of the messages needed by an application, in a
13: format that makes it easy to support multiple languages with the same
14: image file.
15:
16: Message text files are converted into binary resource files by the
17: MC program. These binary resource files are then input to the RC
18: compiler which will put them in the resource table for an
19: application or DLL.
20:
21: The format of the message text file (default extension is .mc).
22: Basic syntax is Keyword=Value, where spaces around the equal sign
23: are ignored, and the value is delimited by white space from the next
24: keyword=value pair. Case is ignored when comparing against keyword
25: names. The value portion can either be a numeric integer constant,
26: {NUMBER}, using C syntax; a symbol name, {NAME}, that follows the
27: rules for C identifier names; or a file name that follows the
28: rules for the FAT file system (8 characters or less, no periods).
29:
30: Comment lines are allowed in the message text file. The comment
31: syntax is the same as for WIN.INI, namely a semicolon begins a
32: comment which is terminated by the end of the line. Comments that
33: exist by themselves on a line are copied as is to the output .h
34: file, with the semicolon converted to the C end of line comment
35: syntax (//).
36:
37: The overall structure of a message text file consists of a header
38: section which contains zero or more of the following keywords:
39:
40: MessageIdTypedef={NAME}
41: SeverityNames=({NAME}={NUMBER}:{NAME})
42: FacilityNames=({NAME}={NUMBER}:{NAME})
43: LanguageNames=({NAME}={NUMBER}:{FILENAME})
44:
45: These keywords have the following meaning:
46:
47: MessageIdTypedef - gives a symbolic name that is output as the
48: typedef name for each numeric MessageId value. The default
49: value for this is NULL, which means there will be no type
50: cast output when defining symbolic names for a MessageId.
51:
52: SeverityNames - defines the set of names that are allowed as the
53: value of the Severity keyword in the message definition.
54: The set is delimited by left and right parenthesis.
55: Associated with each severity name is a number that, when
56: shifted left by 30, gives the bit pattern to logically OR
57: with the Facility value and MessageId to come up with the
58: full 32-bit message code. The default value of this keyword
59: is:
60:
61: SeverityNames=(Success=0x0
62: Informational=0x1
63: Warning=0x2
64: Error=0x3
65: )
66:
67: Severity values occupy the high two bits of a 32-bit message
68: code. Any severity value that does not fit in two bits is
69: an error. The severity codes can be given symbolic names
70: by following each value with :{NAME}
71:
72: FacilityNames - defines the set of names that are allowed as the
73: value of the Facility keyword in the message definition.
74: The set is delimited by left and right parenthesis.
75: Associated with each facility name is a number that, when
76: shift it left by 16 bits, gives the bit pattern to logically
77: OR with the Severity value and MessageId to come up with the
78: full 32-bit message code. The default value of this keyword
79: is:
80:
81: FacilityNames=(System=0x0FF
82: Application=0xFFF
83: )
84:
85:
86: Facility codes occupy the low order 12 bits of the high
87: order 16-bits of a 32-bit message code. Any facility code
88: that does not fit in 12 bits is an error. This allows for
89: 4096 facility codes. The first 256 are reserved for
90: use by the system software.
91:
92: The facility codes can be given symbolic names by following
93: each value with :{NAME}
94:
95: LanguageNames - defines the set of names that are allowed as the
96: value of the Language keyword in the message definition.
97: The set is delimited by left and right parenthesis.
98: Associated with each language name is a number and a file
99: name that will be used to name the binary output file that
100: will contain all of the message text for that language. The
101: number corresponds to the Language Id tag to use in the
102: resource table. The number is separate from the file name
103: with a colon. The initial value of this keyword is:
104:
105: LanguageNames=(English=1:MSG00001)
106:
107: Any new names that an application defines in its .mc file
108: which don't override any of the builtin names will be added
109: to the list of valid languages. This allows an application
110: to support private languages with descriptive names.
111:
112: Following the header section are zero or more message definitions.
113: Each message definition begins with one or more of the following
114: keywords.
115:
116: MessageId={|{NUMBER}|+{NUMBER}}
117: Severity={SEVERITY_NAME}
118: Facility={FACILITY_NAME}
119: SymbolicName={NAME}
120:
121: The MessageId keyword is required to mark the beginning of the
122: message definition, although its value is optional. If no value is
123: specified, then the value used will be the last value used for the
124: facility, plus one. If the value is specified as +{NUMBER} then
125: the value used will be the last value used for the facility, plus
126: the number after the plus sign. Otherwise if a numeric value is
127: given, that will be value used. Any MessageId value that does not
128: fit in 16 bits is an error.
129:
130: Severity and Facility are optional keywords that can specify
131: additional bits to OR into the final 32-bit message code. If either
132: of these are not specified they default to the value last specified
133: for a message definition. The initial values of these prior to
134: processing the first message definition is:
135:
136: Severity=Success
137: Facility=Application
138:
139: The value associated with these keywords must match one of the names
140: given to the FacilityNames and SeverityNames keywords. The SymbolicName
141: keyword allows the ISV to associate a C symbolic constant name with the
142: final 32-bit message code that is a result of ORing together the
143: MessageId, Severity and Facility bits. The constant definition is
144: output to the generated .h file with the following format:
145:
146: //
147: // {MESSAGETEXT}
148: //
149:
150: #define CONSTANT_SYMBOL_NAME ((MessageIdTypedef) 0x12345678)
151:
152: where the comment before the definition is a copy of the message
153: text for the first language specified in the message definition.
154: The CONSTANT_SYMBOL_NAME is the value of the SymbolicName keyword.
155: The MessageIdTypedef is not output if it is NULL, the default value.
156:
157: After the message definition keywords, comes one or more message text
158: definitions. Each message text definition begins with the Language
159: keyword that identifies which binary output file this message text
160: is to be output to. Beginning on the very next line is the first
161: line of the message text. The message text is terminated by a line
162: containing a single period at the beginning of the line, immediately
163: followed by a new line. No spaces allowed around keyword. Within
164: the message text, blank lines and white space are preserved as part
165: of the message.
166:
167: Language={LANGUAGE_NAME}
168: {MESSAGETEXT}
169: .
170:
171: Within the message text, several escape sequences are supported for
172: dynamically formatting the message. The percent sign character (%)
173: begins all escape sequences.
174:
175:
176: %0 - This terminates a message text line without a trailing
177: newline. This can be used to build up long lines or to
178: terminate the message itself without a trailing newline,
179: which is useful for prompt messages.
180:
181: %n!printf format string! - This identifies an insert. The
182: value of n can be between 1 and 99. The printf format
183: string must be bracketed by exclamation marks. It is
184: optional and defaults to !s! if not specified.
185:
186: The printf format string can contain the * specifier for
187: either the precision or width components, and if so, they
188: will consume inserts %n+1 and %n+2 for their values at run
189: time. MC will print a warning message if an explicit
190: reference is made to these inserts elsewhere in the message
191: text.
192:
193: Inserts must reference a parameter passed to the FormatMessage API
194: call. It will return an error if a message refers to an insert that
195: was not passed to the FormatMessage API call.
196:
197: Any other character following a percent sign, other than a digit will
198: be formatted in the output message without the percent sign. Some
199: examples:
200:
201: %% - will output a single percent sign in the formatted message text.
202:
203: %n - will output a hard line break when it occurs at the end of a
204: a line. Useful when FormatMessage is supplying normal line
205: breaks so the message fits in a certain width.
206:
207: %r - will output a hard carriage return, without a trailing newline.
208:
209: %b - will output a space in the formatted message text. This
210: can be used to insure there are the appropriate number of
211: trailing spaces in a message text line.
212:
213: %t - will output a tab in the formatted message text.
214:
215: %. - will output a single period in the formatted message text.
216: This can be used to get a single period at the beginning of
217: a line without terminating the message text definition.
218:
219: %! - will output a single exclamation point in the formatted
220: message text. This can be used to get an exclamation point
221: immediately after an insert without it being mistaken for
222: the beginning of a printf format string.
223:
224: Unicode support is not understood yet. If the input file is ASCII
225: text, do we need an escape sequence to allow input of Unicode values?
226: Or do we just let them use DBCS in the text file, assuming they have
227: a text editor that can do this.
228:
229: 2. Message Compiler (MC)
230:
231: This program converts .mc message text files into binary files
232: suitable for inclusion into a .RC file by the resource compiler.
233:
234: Command line syntax:
235:
236: MC [-v] [-w] [-s] [-h DirSpec] [-r DirSpec] filename[.mc] ...
237:
238: where:
239:
240: -v - generates verbose output to stderr.
241:
242: -w - generates a warning message whenever an insert escape
243: sequence is seen that is a superset of the type supported
244: by OS/2 mkmsgf (i.e. anything other than %0 and %n).
245: Useful for converting old OS/2 message files to this
246: format.
247:
248: -s - Add an extra line to the beginning of each message that is
249: the symbolic name associated with the message id.
250:
251: -h DirSpec - specifies the target directory of the generated
252: .h file. The file name is the name of the .mc file with a
253: .h extension.
254:
255: -r DirSpec - specifies the target directory of the generated
256: .rc file. The file name is the name of the .mc file with a
257: .rc extension.
258:
259: filename.mc - specifes one or more input message files that
260: will be compiled into one or more binary resource
261: files, one for each language that the message
262: files contain message text for.
263:
264: The message compiler reads the .mc file and generates a .h file
265: containing all the symbolic name definitions. For each LanguageId
266: that was used to specify message text, it outputs a binary file
267: containing a message table resource. It also outputs a single .rc
268: file that contains the appropriate RC syntax to include each binary
269: file output as a resource with the appropriate name and type ids.
270:
271: 3. Message Win32 API Calls
272:
273: DWORD
274: APIENTRY
275: FormatMessage(
276: DWORD dwFlags,
277: LPVOID lpSource,
278: DWORD dwMessageId,
279: DWORD dwLanguageId,
280: LPSTR lpBuffer,
281: DWORD nSize,
282: va_list Arguments
283: )
284:
285: Routine Description:
286:
287: This function formats a message string. Input to this function is a
288: message definition. It can come from a buffer passed into this
289: function. It can come from a message table resource in a module
290: already loaded. Or the caller can ask this function to search the
291: system message table resource(s) for the message. This function
292: finds the message definition based on the Message Id and the
293: Language Id and copies the message text to the output buffer,
294: processing any imbedded insert sequences if requested.
295:
296: Arguments:
297:
298: dwFlags - Specifies options to the formatting process along with how
299: to interpret the lpSource parameter. The low order 16bits of
300: this parameter are the maximum width of a line, in characters.
301: Possible values are:
302:
303: FORMAT_MESSAGE_ALLOCATE_BUFFER - the lpBuffer is a PVOID * and
304: nSize is the minimum size to allocate. This function will
305: then allocate a buffer large enought to hold the formatted
306: message and store the pointer to the buffer in the location
307: pointed to by lpBuffer. Caller should free the buffer
308: with LocalFree when they are done using it.
309:
310: FORMAT_MESSAGE_IGNORE_INSERTS - insert sequences in the message
311: definition will be ignored and passed through to the output
312: buffer as is. Useful for fetching a message for later
313: formatting. If this flag is set, the lpArguments parameter
314: is ignored.
315:
316: FORMAT_MESSAGE_FROM_STRING - lpSource is a pointer to a null
317: terminated message definition. It can contain insert
318: sequences just as the message text in the .mc file can.
319:
320: FORMAT_MESSAGE_FROM_HMODULE - lpSource is a module handle that
321: contains the message table resource(s) to search. If this
322: handle is NULL, then the current process's application
323: image file will be searched.
324:
325: FORMAT_MESSAGE_FROM_SYSTEM - If the requested message was not
326: found in lpSource or if lpSource was not examined (i.e. neither
327: of the preceeding two flags was specified), then this function
328: will search the system message table resource(s).
329:
330: FORMAT_MESSAGE_ARGUMENT_ARRAY - If set, specifies that the passed
331: Arguments parameter is NOT a va_list structure but instead is
332: just a pointer to an array of 32-bit values that represent
333: the arguments.
334:
335: FORMAT_MESSAGE_MAX_WIDTH_MASK - The low order 8 bits specify the
336: maximum width of each line formatted into the output buffer.
337: A maximum width of zero, means that no restrictions are
338: placed on the width, and only the line breaks in the message
339: definition will be placed in the output buffer. If a non-zero
340: value is specified, then line breaks in the message definition
341: text are ignored, and instead line breaks are calculated based
342: on the maximum width, with white space delimited strings never
343: being split across a line break. Hard coded line breaks in
344: the message definition text, that are identified by the %n
345: escape sequence, are always output to the output buffer.
346:
347: If the width specified is FORMAT_MESSAGE_MAX_WIDTH_MASK, then
348: line breaks in the message file are ignored and only hard coded
349: line breaks are kept and none are generated.
350:
351: lpSource - specifies where to retrieve the message definition from.
352: The type of this parameter depends upon the settings in the
353: dwFlags parameter.
354:
355: FORMAT_MESSAGE_FROM_HMODULE - lpSource is an hModule of the
356: module that contains the message table to search.
357:
358: FORMAT_MESSAGE_FROM_STRING - lpSource is an LPSTR that points
359: to unformatted message text. It will be scanned for
360: inserts and formatted accordingly.
361:
362: If neither of these options is specified, then this parameter is
363: ignored.
364:
365: dwMessageId - specifices the 32-bit message identifier that identifies
366: the message being requested. This parameter is ignored if the
367: FORMAT_MESSAGE_FROM_STRING flag is specified.
368:
369: dwLanguageId - specifices the 32-bit language identifier that
370: identifies the language of the message being requested. This
371: parameter is ignored if the FORMAT_MESSAGE_FROM_STRING flag is
372: specified.
373:
374: lpBuffer - specifies a pointer to a buffer where the formatted message
375: is to be written. A terminating null byte will also be written.
376: If the FORMAT_MESSAGE_ALLOCATE_BUFFER flag was specified, then
377: this parameter points to a 32-bit pointer value that is filled in
378: by this call with a pointer allocated via LocalAlloc to contain
379: the text of the message.
380:
381: nSize - specifies the maximum number of bytes that can be stored in
382: the output buffer. This parameter is ignore if the
383: FORMAT_MESSAGE_ALLOCATE_BUFFER flag is set.
384:
385: Arguments - specifies a pointer to variable number of arguments.
386: These arguments are used to satisfy insert requests in the
387: format string. Thus %1 in the format string specifies the
388: first argument in the variable number of arguments described
389: by the Arguments parameter; %3 would specify the third, etc.
390:
391: The interpretation of each 32-bit arguments value depends upon
392: the formatting information associated with the insert in the
393: message definition. The default is to treat each pointer as a
394: pointer to a null terminated string.
395:
396: By default the Arguments parameter is of type va_list, which is
397: a language and implementation specific data type for describing
398: a variable number of arguments. If you do not have a pointer of
399: type va_list, then specify the FORMAT_MESSAGE_ARGUMENT_ARRAY
400: flag and pass a pointer to an array of 32-bit values that are
401: are input to the message formatted as the insert values.
402: Return Value:
403:
404: DwORD - Returns the number of bytes actually stored in the output
405: buffer, excluding the terminating null character. Returns 0 if
406: an error occurred. Extended error status is available via the
407: GetLastError API.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.