home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / dlgedit / resutil.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  20KB  |  803 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 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.  
  803.