|
|
1.1 root 1:
2: /******************************************************************************\
3: * This is a part of the Microsoft Source Code Samples.
4: * Copyright (C) 1993 Microsoft Corporation.
5: * All rights reserved.
6: * This source code is only intended as a supplement to
7: * Microsoft Development Tools and/or WinHelp documentation.
8: * See these sources for detailed information regarding the
9: * Microsoft samples programs.
10: \******************************************************************************/
11:
12: /****************************** Module Header *******************************
13: * Module Name: resutil.c
14: *
15: * Contains utility functions for working with the Windows resource file.
16: *
17: * Functions:
18: * ParseDialogBoxHeader()
19: * ParseControlData()
20: * DWordAlign()
21: * DWordPad()
22: * ResourceType)
23: * ResourceName()
24: * ResourcePart2()
25: * ResourceSize()
26: * SkipResHeader()
27: * SkipSz()
28: * SkipDialogBoxHeader()
29: * SkipControlData()
30: * NameOrdCpy()
31: * NameOrdCmp()
32: * NameOrdLen()
33: * NameOrdDup()
34: * StrToNameOrd()
35: * WriteOrd()
36: * WriteResHeader()
37: * WriteSz()
38: *
39: ****************************************************************************/
40:
41: #include "dlgedit.h"
42: #include "dlgfuncs.h"
43: #include "dlgextrn.h"
44:
45: #include <string.h>
46: #include <wchar.h>
47:
48:
49:
50: /************************************************************************
51: * ParseDialogBoxHeader
52: *
53: *
54: * Arguments:
55: * PDIALOGBOXHEADER pdbh - Points to dialog box header to parse.
56: * PDWORD pflStyle - Receives the style.
57: * PDWORD pflExtStyle - Receives the extended style.
58: * PINT pcdit - Receives the number of controls in the dialog.
59: * PINT px - Receives starting x location.
60: * PINT py - Receives starting y location.
61: * PINT pcx - Receives the width.
62: * PINT pcy - Receives the height.
63: * LPTSTR *ppszMenuName - Receives the menu name.
64: * LPTSTR *ppszClass - Receives the class name.
65: * LPTSTR *ppszCaption - Receives the caption.
66: * PINT pPointSize - Receives the point size.
67: * LPTSTR *ppszFontName - Receives the font name.
68: *
69: * Returns:
70: * A pointer to the first dialog item past the dialog template header.
71: *
72: ************************************************************************/
73:
74: PCONTROLDATA ParseDialogBoxHeader(
75: PDIALOGBOXHEADER pdbh,
76: PDWORD pflStyle,
77: PDWORD pflExtStyle,
78: PINT pcdit,
79: PINT px,
80: PINT py,
81: PINT pcx,
82: PINT pcy,
83: LPTSTR *ppszMenuName,
84: LPTSTR *ppszClass,
85: LPTSTR *ppszCaption,
86: PINT pPointSize,
87: LPTSTR *ppszFontName)
88: {
89: BYTE UNALIGNED *pb;
90:
91: *pflStyle = pdbh->lStyle;
92: *pflExtStyle = pdbh->lExtendedStyle;
93: *pcdit = pdbh->NumberOfItems;
94: *px = (SHORT)pdbh->x;
95: *py = (SHORT)pdbh->y;
96: *pcx = (SHORT)pdbh->cx;
97: *pcy = (SHORT)pdbh->cy;
98:
99: pb = (PBYTE)pdbh + SIZEOF_DIALOGBOXHEADER;
100: *ppszMenuName = (LPTSTR)pb;
101: pb += NameOrdLen((LPTSTR)pb);
102:
103: *ppszClass = (LPTSTR)pb;
104: pb += NameOrdLen((LPTSTR)pb);
105:
106: *ppszCaption = (LPTSTR)pb;
107: pb += (lstrlen((LPTSTR)pb) + 1) * sizeof(TCHAR);
108:
109: /*
110: * Does the template specify a font?
111: */
112: if (pdbh->lStyle & DS_SETFONT) {
113: *pPointSize = (SHORT)(*(PWORD)pb);
114: pb += sizeof(WORD);
115: *ppszFontName = (LPTSTR)pb;
116: pb += (lstrlen((LPTSTR)pb) + 1) * sizeof(TCHAR);
117: }
118: else {
119: *pPointSize = 0;
120: *ppszFontName = NULL;
121: }
122:
123: DWordAlign((PBYTE *)&pb);
124:
125: return (PCONTROLDATA)pb;
126: }
127:
128:
129:
130: /************************************************************************
131: * ParseControlData
132: *
133: *
134: * Arguments:
135: * PCONTROLDATA pcd - Points to the control data to parse.
136: * PDWORD pflStyle - Receives the control style.
137: * PDWORD pflExtStyle - Receives the extended control style.
138: * PINT px - Receives starting x location.
139: * PINT py - Receives starting y location.
140: * PINT pcx - Receives the width.
141: * PINT pcy - Receives the height.
142: * PINT pid - Receives the control id.
143: * LPTSTR *ppszClass - Receives the class name.
144: * LPTSTR *ppszText - Receives the text.
145: *
146: * Returns:
147: * A pointer to the next dialog item past the given one.
148: *
149: ************************************************************************/
150:
151: PCONTROLDATA ParseControlData(
152: PCONTROLDATA pcd,
153: PDWORD pflStyle,
154: PDWORD pflExtStyle,
155: PINT px,
156: PINT py,
157: PINT pcx,
158: PINT pcy,
159: PINT pid,
160: LPTSTR *ppszClass,
161: LPTSTR *ppszText)
162: {
163: BYTE UNALIGNED *pb;
164:
165: *pflStyle = pcd->lStyle;
166: *pflExtStyle = pcd->lExtendedStyle;
167:
168: *px = (SHORT)pcd->x;
169: *py = (SHORT)pcd->y;
170: *pcx = (SHORT)pcd->cx;
171: *pcy = (SHORT)pcd->cy;
172: *pid = (SHORT)pcd->wId;
173:
174: pb = (PBYTE)pcd + SIZEOF_CONTROLDATA;
175: *ppszClass = (LPTSTR)pb;
176: pb += NameOrdLen((LPTSTR)pb);
177:
178: *ppszText = (LPTSTR)pb;
179: pb += NameOrdLen((LPTSTR)pb);
180:
181: /*
182: * Finally, skip the Create Struct Data.
183: * After this, pb will be pointing to the next control.
184: */
185: pb += *(PWORD)pb + sizeof(WORD);
186:
187: DWordAlign((PBYTE *)&pb);
188:
189: return (PCONTROLDATA)pb;
190: }
191:
192:
193:
194: /************************************************************************
195: * DWordAlign
196: *
197: * This function aligns the passed pointer to a DWORD boundary.
198: *
199: * Arguments:
200: * PBYTE *ppb - Points to the pointer to align.
201: *
202: ************************************************************************/
203:
204: VOID DWordAlign(
205: PBYTE *ppb)
206: {
207: *ppb += (4 - (((WORD)(DWORD)*ppb) & 3)) % 4;
208: }
209:
210:
211:
212: /************************************************************************
213: * DWordPad
214: *
215: * This function aligns the passed pointer to a DWORD boundary, padding
216: * with nulls as it goes.
217: *
218: * Arguments:
219: * PBYTE *ppb - Points to the pointer to align.
220: *
221: ************************************************************************/
222:
223: VOID DWordPad(
224: PBYTE *ppb)
225: {
226: WORD cbytes;
227:
228: cbytes = (WORD)((4 - (((WORD)(DWORD)*ppb) & 3)) % 4);
229: while (cbytes) {
230: *((*ppb)++) = 0;
231: cbytes--;
232: }
233: }
234:
235:
236:
237: /************************************************************************
238: * ResourceType
239: *
240: * This function returns a pointer to the type of the resource.
241: * The type can be either a string or an ordinal.
242: *
243: * Arguments:
244: * PRES pRes - Points to the start of the resource.
245: *
246: * Returns:
247: * Pointer to the type of the resource.
248: *
249: ************************************************************************/
250:
251: LPTSTR ResourceType(
252: PRES pRes)
253: {
254: /*
255: * Skip past the two size fields.
256: */
257: return (LPTSTR)((PBYTE)pRes + sizeof(DWORD) + sizeof(DWORD));
258: }
259:
260:
261:
262: /************************************************************************
263: * ResourceName
264: *
265: * This function returns a pointer to the name of the resource.
266: * The name can be either a string or an ordinal.
267: *
268: * Arguments:
269: * PRES pRes - Points to the start of the resource.
270: *
271: * Returns:
272: * Pointer to the name of the resource.
273: *
274: ************************************************************************/
275:
276: LPTSTR ResourceName(
277: PRES pRes)
278: {
279: PBYTE pb;
280:
281: /*
282: * Skip past the two size fields.
283: */
284: pb = (PBYTE)pRes + sizeof(DWORD) + sizeof(DWORD);
285:
286: /*
287: * Skip past the "Type" field to the name.
288: */
289: return (LPTSTR)SkipSz((LPTSTR)pb);
290: }
291:
292:
293:
294: /************************************************************************
295: * ResourcePart2
296: *
297: * This function returns a pointer to the second half of the resource
298: * header.
299: *
300: * Arguments:
301: * PRES pRes - Points to the start of the resource.
302: *
303: * Returns:
304: * A pointer to the second part of the resource header.
305: *
306: ************************************************************************/
307:
308: PRES2 ResourcePart2(
309: PRES pRes)
310: {
311: PBYTE pb;
312:
313: /*
314: * Skip past the first part of the resource header.
315: */
316: pb = (PBYTE)pRes + sizeof(RES);
317:
318: /*
319: * Skip past the "Type" field to the name.
320: */
321: pb = SkipSz((LPTSTR)pb);
322:
323: /*
324: * Skip past the name field also.
325: */
326: pb = SkipSz((LPTSTR)pb);
327: DWordAlign(&pb);
328:
329: return (PRES2)pb;
330: }
331:
332:
333:
334: /************************************************************************
335: * ResourceSize
336: *
337: * This returns the size of the given resource.
338: *
339: * Arguments:
340: * PRES pRes - Points to the start of the resource.
341: *
342: * Returns:
343: * Size of the resource, including the header.
344: *
345: ************************************************************************/
346:
347: DWORD ResourceSize(
348: PRES pRes)
349: {
350: return pRes->HeaderSize + pRes->DataSize;
351: }
352:
353:
354:
355: /************************************************************************
356: * SkipResHeader
357: *
358: * This function returns a pointer to the start of the resource data,
359: * just past it's header.
360: *
361: * Arguments:
362: * PRES pRes - Pointer to the resource.
363: *
364: ************************************************************************/
365:
366: PBYTE SkipResHeader(
367: PRES pRes)
368: {
369: return (PBYTE)pRes + pRes->HeaderSize;
370: }
371:
372:
373:
374: /************************************************************************
375: * SkipSz
376: *
377: * This function skips past a string and returns a pointer to just
378: * past it. It detects if the string is really an ordinal and skips
379: * past these also.
380: *
381: * Arguments:
382: * LPTSTR pNameOrd - Pointer to the string/ordinal.
383: *
384: ************************************************************************/
385:
386: PBYTE SkipSz(
387: LPTSTR pNameOrd)
388: {
389: if (IsOrd(pNameOrd))
390: pNameOrd = (LPTSTR)((PBYTE)pNameOrd + sizeof(ORDINAL));
391: else
392: pNameOrd += lstrlen(pNameOrd) + 1;
393:
394: return (PBYTE)pNameOrd;
395: }
396:
397:
398:
399: /************************************************************************
400: * SkipDialogBoxHeader
401: *
402: * This function skips past a dialog template structure and returns
403: * a pointer to the first dialog item template just past it.
404: *
405: * Arguments:
406: * PDIALOGBOXHEADER pdbh - Points to the dialog box header.
407: *
408: * Returns:
409: * A pointer to the first dialog item control data in the resource,
410: * just past the dialog box header that was skipped.
411: *
412: ************************************************************************/
413:
414: PCONTROLDATA SkipDialogBoxHeader(
415: PDIALOGBOXHEADER pdbh)
416: {
417: BYTE UNALIGNED *pb;
418:
419: /*
420: * Skip the fixed portion.
421: */
422: pb = (PBYTE)pdbh + SIZEOF_DIALOGBOXHEADER;
423:
424: /*
425: * Skip the menu.
426: */
427: pb += NameOrdLen((LPTSTR)pb);
428:
429: /*
430: * Skip the class.
431: */
432: pb += NameOrdLen((LPTSTR)pb);
433:
434: /*
435: * Skip the caption.
436: */
437: pb += (lstrlen((LPTSTR)pb) + 1) * sizeof(TCHAR);
438:
439: /*
440: * Does the template specify a font?
441: */
442: if (pdbh->lStyle & DS_SETFONT) {
443: pb += sizeof(WORD);
444: pb += (lstrlen((LPTSTR)pb) + 1) * sizeof(TCHAR);
445: }
446:
447: DWordAlign((PBYTE *)&pb);
448:
449: return (PCONTROLDATA)pb;
450: }
451:
452:
453:
454: /************************************************************************
455: * SkipControlData
456: *
457: * This function skips past the given control data to the next control.
458: *
459: * Arguments:
460: * PCONTROLDATA pcd - Points to the control data structure to skip.
461: *
462: * Returns:
463: * A pointer to the next control data structure.
464: *
465: ************************************************************************/
466:
467: PCONTROLDATA SkipControlData(
468: PCONTROLDATA pcd)
469: {
470: BYTE UNALIGNED *pb;
471:
472: /*
473: * Skip the fixed portion.
474: */
475: pb = (PBYTE)pcd + SIZEOF_CONTROLDATA;
476:
477: /*
478: * Skip the class.
479: */
480: pb += NameOrdLen((LPTSTR)pb);
481:
482: /*
483: * Skip the text.
484: */
485: pb += NameOrdLen((LPTSTR)pb);
486:
487: /*
488: * Finally, skip the Create Struct Data.
489: * After this, pb will be pointing to the next control.
490: */
491: pb += *(PWORD)pb + sizeof(WORD);
492:
493: DWordAlign((PBYTE *)&pb);
494:
495: return (PCONTROLDATA)pb;
496: }
497:
498:
499:
500: /************************************************************************
501: * NameOrdCpy
502: *
503: * This function copies a string or ordinal. This function needs to be
504: * used whenever a string could possibly be an ordinal. It returns a
505: * pointer to the first byte after the copied name/ordinal.
506: *
507: * Arguments:
508: * LPTSTR pNameOrdDest - The destination buffer.
509: * LPTSTR pNameOrdSrc - The source string or ordinal.
510: *
511: ************************************************************************/
512:
513: PBYTE NameOrdCpy(
514: LPTSTR pNameOrdDest,
515: LPTSTR pNameOrdSrc)
516: {
517: if (IsOrd(pNameOrdSrc)) {
518: memcpy((PBYTE)pNameOrdDest, (PBYTE)pNameOrdSrc, sizeof(ORDINAL));
519: return (PBYTE)pNameOrdDest + sizeof(ORDINAL);
520: }
521: else {
522: lstrcpy(pNameOrdDest, pNameOrdSrc);
523: return (PBYTE)(pNameOrdDest + (lstrlen(pNameOrdDest) + 1));
524: }
525: }
526:
527:
528:
529: /************************************************************************
530: * NameOrdCmp
531: *
532: * This function compares two strings or ordinals. It returns a
533: * zero if they are equal, or non-zero if they are not. This
534: * follows the convention of lstrcmp(), but the return should
535: * not be relied upon to determine which is "greater" than
536: * the other.
537: *
538: * Arguments:
539: * LPTSTR pNameOrd1 - The first string or ordinal.
540: * LPTSTR pNameOrd2 - The second string or ordinal.
541: *
542: ************************************************************************/
543:
544: INT NameOrdCmp(
545: LPTSTR pNameOrd1,
546: LPTSTR pNameOrd2)
547: {
548: BOOL fIsOrd1;
549: BOOL fIsOrd2;
550:
551: fIsOrd1 = IsOrd(pNameOrd1);
552: fIsOrd2 = IsOrd(pNameOrd2);
553:
554: if (fIsOrd1 != fIsOrd2)
555: return 1;
556:
557: if (fIsOrd1)
558: return memcmp((PBYTE)pNameOrd1, (PBYTE)pNameOrd2, sizeof(ORDINAL));
559: else
560: return lstrcmp(pNameOrd1, pNameOrd2);
561: }
562:
563:
564:
565: /************************************************************************
566: * NameOrdLen
567: *
568: * This function returns the length of a string or ordinal.
569: * If the given name is a string, the length of the string
570: * plus the terminating null is returned. Otherwise,
571: * the size of an ORDINAL structure is returned.
572: *
573: * The length returned is in bytes, not wide-chars.
574: *
575: * Arguments:
576: * LPTSTR pNameOrd - The string or ordinal.
577: *
578: ************************************************************************/
579:
580: INT NameOrdLen(
581: LPTSTR pNameOrd)
582: {
583: if (IsOrd(pNameOrd))
584: return sizeof(ORDINAL);
585: else
586: return (lstrlen(pNameOrd) + 1) * sizeof(TCHAR);
587: }
588:
589:
590:
591: /****************************************************************************
592: * NameOrdDup
593: *
594: * This function allocates a copy of the given name or ordinal.
595: *
596: * Arguments:
597: * LPTSTR pNameOrd - The name or ordinal to duplicate.
598: *
599: * Returns a pointer to the new copy if successful, NULL if it fails.
600: *
601: ****************************************************************************/
602:
603: LPTSTR NameOrdDup(
604: LPTSTR pNameOrd)
605: {
606: register INT iLen;
607: LPTSTR psz;
608:
609: iLen = NameOrdLen(pNameOrd);
610:
611: if (!(psz = (LPTSTR)MyAlloc(iLen)))
612: return NULL;
613:
614: NameOrdCpy(psz, pNameOrd);
615:
616: return psz;
617: }
618:
619:
620:
621: /************************************************************************
622: * StrToNameOrd
623: *
624: * This function takes the given string, determines if it is
625: * all numeric and if so, converts it in place into an ordinal.
626: * It is used to convert the string from an edit field for
627: * a value that can be an ordinal, such as the dialog name or
628: * an icon's text.
629: *
630: * Note that the pszNameOrd buffer must be large enough for an
631: * ordinal in case the string gets converted to an ordinal.
632: *
633: * Arguments:
634: * LPTSTR pszNameOrd - On input, contains the string to possibly
635: * convert. On output, it will contain the
636: * original string or the string converted to
637: * an ordinal.
638: * BOOL fDecOnly - TRUE if hex values and negative values (the
639: * string starts with a '-') are not allowed.
640: * This flag prevents these types of strings
641: * from being candidates for conversion to
642: * ordinals.
643: *
644: ************************************************************************/
645:
646: VOID StrToNameOrd(
647: LPTSTR pszNameOrd,
648: BOOL fDecOnly)
649: {
650: register INT i;
651: INT nOrd;
652: INT nLen;
653:
654: /*
655: * Empty string?
656: */
657: if (!(*pszNameOrd))
658: return;
659:
660: nLen = lstrlen(pszNameOrd);
661:
662: /*
663: * Is a hex value ok and does this appear to be a hex value?
664: */
665: if (!fDecOnly && pszNameOrd[0] == CHAR_0 &&
666: (pszNameOrd[1] == CHAR_X || pszNameOrd[1] == CHAR_CAP_X)) {
667: for (i = 2; i < nLen; i++) {
668: if (!iswxdigit(pszNameOrd[i]))
669: return;
670: }
671:
672: nOrd = axtoi(&pszNameOrd[2]);
673: }
674: else {
675: /*
676: * All characters must be numeric. Negative numbers may
677: * or may not be allowed, based on the fDecOnly flag.
678: */
679: for (i = 0; i < nLen; i++) {
680: if (!iswdigit(pszNameOrd[i]) &&
681: (fDecOnly || i != 0 || pszNameOrd[0] != CHAR_MINUS))
682: return;
683: }
684:
685: nOrd = awtoi(pszNameOrd);
686: }
687:
688: /*
689: * Return the ordinal in the original buffer.
690: */
691: WriteOrd((PORDINAL)pszNameOrd, nOrd);
692: }
693:
694:
695:
696: /************************************************************************
697: * WriteOrd
698: *
699: * This function writes out the given ordinal to the specified
700: * memory location. It returns the first byte past the newly
701: * written ordinal.
702: *
703: * Arguments:
704: * PORDINAL pMem - Pointer to the location to write the ordinal.
705: * INT nOrdinalID - Ordinal ID to write.
706: *
707: ************************************************************************/
708:
709: PBYTE WriteOrd(
710: PORDINAL pOrd,
711: INT nOrdinalID)
712: {
713: pOrd->wReserved = 0xffff;
714: pOrd->wOrdID = (WORD)nOrdinalID;
715:
716: return (PBYTE)pOrd + sizeof(ORDINAL);
717: }
718:
719:
720:
721: /************************************************************************
722: * WriteResHeader
723: *
724: * This function writes out a resource header to the memory location
725: * specified.
726: *
727: * Arguments:
728: *
729: * PRES pRes - pointer to the resource
730: * DWORD DataSize - size of the data
731: * INT iResType - resource type
732: * LPTSTR pszResName - resource name
733: * WORD fResFlags - resource flags
734: * WORD LanguageId - language id
735: * DWORD DataVersion - data version
736: * DWORD Version - version
737: * DWORD Characteristics-characterstics
738: *
739: * Returns:
740: * number of bytes written
741: *
742: ************************************************************************/
743:
744: PBYTE WriteResHeader(
745: PRES pRes,
746: DWORD DataSize,
747: INT iResType,
748: LPTSTR pszResName,
749: WORD fResFlags,
750: WORD LanguageId,
751: DWORD DataVersion,
752: DWORD Version,
753: DWORD Characteristics)
754: {
755: PBYTE pb;
756: PRES2 pRes2;
757:
758: pb = (PBYTE)pRes + sizeof(RES);
759: pb = WriteOrd((PORDINAL)pb, iResType);
760: pb = NameOrdCpy((LPTSTR)pb, pszResName);
761: DWordPad(&pb);
762:
763: pRes->DataSize = DataSize;
764: pRes->HeaderSize = (pb - (PBYTE)pRes) + sizeof(RES2);
765:
766: pRes2 = (PRES2)pb;
767: pRes2->DataVersion = DataVersion;
768: pRes2->MemoryFlags = fResFlags;
769: pRes2->LanguageId = LanguageId;
770: pRes2->Version = Version;
771: pRes2->Characteristics = Characteristics;
772:
773: return (PBYTE)pRes + pRes->HeaderSize;
774: }
775:
776:
777:
778: /************************************************************************
779: * WriteSz
780: *
781: * This function writes out the string given to the specified
782: * memory location. It returns the first byte past the newly
783: * written string.
784: *
785: * Arguments:
786: * LPTSTR pszDest - Pointer to the location to write the string.
787: * LPTSTR pszSrc - The string to write.
788: *
789: ************************************************************************/
790:
791: PBYTE WriteSz(
792: LPTSTR pszDest,
793: LPTSTR pszSrc)
794: {
795: while (*pszSrc)
796: *pszDest++ = *pszSrc++;
797:
798: *pszDest++ = CHAR_NULL;
799:
800: return (PBYTE)pszDest;
801: }
802:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.