home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sysmgmt / setup / win9xmig / scrnsave / miginf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-13  |  17.4 KB  |  753 lines

  1. #include "pch.h"
  2.  
  3. #define MIGRATEINF              ".\\migrate.inf"
  4. #define INITIALBUFFERSIZE       1024
  5. #define MIGINF_NOCREATE         FALSE
  6. #define MIGINF_CREATE           TRUE
  7.  
  8.  
  9. typedef struct tagMIGOBJECT MIGOBJECT, *PMIGOBJECT;
  10. struct tagMIGOBJECT {
  11.  
  12.     PSTR        Key;
  13.     PSTR        Value;
  14.     
  15.     PMIGOBJECT  Next;
  16. };
  17.  
  18. typedef struct tagMIGSECTION MIGSECTION, * PMIGSECTION;
  19. struct tagMIGSECTION {
  20.  
  21.     PSTR        Name;
  22.     PMIGOBJECT  Items;
  23.  
  24.     PMIGSECTION Next;
  25. };
  26.  
  27. PMIGSECTION g_MigrationInf;
  28. POOLHANDLE  g_Pool = NULL;
  29.  
  30.  
  31. static
  32. PCSTR
  33. pGetTypeAsString (
  34.     IN MIGTYPE Type
  35.     )
  36. {
  37.     //
  38.     // Note: Strings must be in the same order as the 
  39.     // corresponding types in the MIGTYPE enumeration above.
  40.     //
  41.     static PCHAR typeStrings[] = {
  42.             "FIRST - Invalid",
  43.             "File",
  44.             "Path",
  45.             "Registry",
  46.             "Message - Invalid",
  47.             "LAST - Invalid"
  48.         };
  49.  
  50.     assert(Type > MIG_FIRSTTYPE && Type < MIG_LASTTYPE);
  51.  
  52.     return typeStrings[Type];
  53. }
  54.  
  55. static
  56. PMIGSECTION 
  57. pFindSection (
  58.     IN PCSTR SectionString,
  59.     IN BOOL  CreateIfNotExist
  60.     )
  61. {
  62.     PMIGSECTION rSection;
  63.  
  64.     //
  65.     // We assume that SectionString is not null.
  66.     //
  67.     assert(SectionString);
  68.  
  69.     rSection = g_MigrationInf;
  70.  
  71.     while (rSection && (_mbsicmp(rSection -> Name,SectionString) != 0)) {
  72.  
  73.         //
  74.         // Continue looking.
  75.         //
  76.         rSection = rSection -> Next;
  77.     }
  78.         
  79.     if (!rSection && CreateIfNotExist) {
  80.         //
  81.         // No section was found matching this name. Make a new section and add it 
  82.         // to the list.
  83.         //
  84.         rSection = PoolMemGetMemory(g_Pool,sizeof(MIGSECTION));
  85.         if (rSection) {
  86.  
  87.             ZeroMemory(rSection,sizeof(MIGSECTION));
  88.             rSection -> Name  = PoolMemDuplicateStringA(g_Pool,SectionString);
  89.             rSection -> Next  = g_MigrationInf;
  90.             g_MigrationInf    = rSection;
  91.  
  92.             if (!rSection -> Name) {
  93.                 //
  94.                 // Something went wrong when we tried to duplicate the SectionString.
  95.                 // NULL out the rSection so that the caller doesn't get back a 
  96.                 // malformed section object.
  97.                 //
  98.                 rSection = NULL;
  99.             }
  100.         }
  101.     }
  102.  
  103.     return rSection;
  104. }
  105.  
  106. static
  107. BOOL
  108. pPathIsInPath(
  109.     IN PCSTR    SubPath,
  110.     IN PCSTR    ParentPath
  111.     )
  112. {
  113.     DWORD parentLength;
  114.     BOOL  rInPath;
  115.  
  116.     //
  117.     // This function assumes both parameters are non-NULL.
  118.     //
  119.     assert(SubPath);
  120.     assert(ParentPath);
  121.     
  122.     parentLength = _mbslen(ParentPath);
  123.  
  124.     //
  125.     // A path is considered "in" another path if the path is in the ParentPath
  126.     // or a subdirectory of it.
  127.     //
  128.     rInPath = !_mbsnicmp(SubPath,ParentPath,parentLength);
  129.  
  130.     if (rInPath) {
  131.         rInPath = SubPath[parentLength] == 0 || SubPath[parentLength] == '\\';
  132.     }
  133.  
  134.     return rInPath;
  135.  
  136. }
  137.  
  138. static
  139. DWORD
  140. pGetMbsSize (
  141.     IN  LPCSTR  String
  142.     )
  143. {
  144.     DWORD rLength;
  145.     
  146.     rLength = (DWORD) _mbschr(String,0) - (DWORD) String + 1;
  147.  
  148.     return rLength;
  149.  
  150. }
  151.  
  152.  
  153. static
  154. LPSTR 
  155. pEscapeString (
  156.     IN  MIGTYPE Type,
  157.     OUT LPSTR   EscapedString, 
  158.     IN  LPCSTR  String
  159.     )
  160.  
  161. {
  162.     LPSTR   stringStart;
  163.     static  CHAR exclusions[] = "[]~,;%\"";
  164.     INT     currentChar;
  165.  
  166.     //
  167.     // We assume that all parameters are valid.
  168.     //
  169.     assert(EscapedString && String);
  170.  
  171.     stringStart = EscapedString;
  172.  
  173.     while (*String)  {
  174.         currentChar = _mbsnextc (String);
  175.         
  176.         if (Type == MIG_REGKEY) {
  177.             
  178.             //
  179.             // Registry keys require more complex escaping than do normal INF strings.
  180.             //
  181.             if (!_ismbcprint (currentChar) || _mbschr (exclusions, currentChar)) {
  182.                 
  183.                 //
  184.                 // Escape unprintable or excluded character
  185.                 //
  186.                 wsprintfA (EscapedString, "~%X~", currentChar);
  187.                 EscapedString = _mbschr (EscapedString, 0);
  188.                 String = _mbsinc (String);
  189.             }
  190.             else {
  191.                 //
  192.                 // Copy multibyte character
  193.                 //
  194.                 if (isleadbyte (*String)) {
  195.                     *EscapedString = *String;
  196.                     EscapedString++;
  197.                     String++;
  198.                 }
  199.                 
  200.                 *EscapedString = *String;
  201.                 EscapedString++;
  202.                 String++;
  203.             }
  204.         }
  205.         else {
  206.  
  207.             //
  208.             // Escaping is pretty simple for non-registry keys. All we do is double up
  209.             // quotes and percents.
  210.             //
  211.             if (*String == '\"' || *String == '%') {
  212.  
  213.                 *EscapedString = *String;
  214.                 EscapedString++;
  215.             }
  216.             
  217.             //
  218.             // Copy multibyte character
  219.             //
  220.             if (isleadbyte (*String)) {
  221.                 *EscapedString = *String;
  222.                 EscapedString++;
  223.                 String++;
  224.             }
  225.             
  226.             *EscapedString = *String;
  227.             EscapedString++;
  228.             String++;
  229.         }
  230.     }
  231.  
  232.     //
  233.     // Ensure that returned string is NULL terminated.
  234.     //
  235.     *EscapedString = 0;
  236.  
  237.     return stringStart;
  238. }
  239.  
  240.  
  241. static
  242. PSTR
  243. pGetValueString (
  244.     IN MIGTYPE    ObjectType,
  245.     IN LPCSTR     StringOne,
  246.     IN LPCSTR     StringTwo
  247.     )
  248. {
  249.     static PSTR     buffer;
  250.     static DWORD    bufferSize;
  251.     DWORD           maxLength;
  252.     PSTR            bufferEnd;
  253.     
  254.     //
  255.     // This function assumes that StringOne exists.
  256.     //
  257.     assert(StringOne);
  258.  
  259.     if (ObjectType == MIG_REGKEY) {
  260.         //
  261.         // Size: size of both strings, plus the size of the quotes, plus the size of the brackets 
  262.         // for the value, * 6. This is the maximum size one of these could grow to, if every 
  263.         // character had to be escaped out.
  264.         //
  265.         maxLength = (pGetMbsSize(StringOne) + (StringTwo ? pGetMbsSize(StringTwo) + 2 : 0)) * 6 + 2;
  266.     }
  267.     else {
  268.         //
  269.         // Size: size of the string * 2 (The max size if every char was a '%' or '"' plus the quotes.
  270.         //
  271.         maxLength = pGetMbsSize(StringOne) * 2 + 2;
  272.     }
  273.  
  274.     if (maxLength > bufferSize) {
  275.  
  276.         //
  277.         // Initialize our buffer, or create a larger one.
  278.         //
  279.         bufferSize = (maxLength > INITIALBUFFERSIZE) ? maxLength : INITIALBUFFERSIZE;
  280.         buffer = PoolMemCreateStringA(g_Pool,bufferSize);
  281.     }
  282.  
  283.     if (buffer != NULL) {
  284.         
  285.         //
  286.         // Insert initial quote.
  287.         //
  288.         *buffer = '"';
  289.  
  290.         //
  291.         // Massage the string to ensure it is a valid INF file string.
  292.         //
  293.         pEscapeString(ObjectType,_mbsinc(buffer),StringOne);
  294.  
  295.         //
  296.         // If this is a REGISTRY entry, then we also need to add the value part of the string, 
  297.         // if one was specified (In StringTwo)
  298.         //
  299.  
  300.         if (ObjectType == MIG_REGKEY && StringTwo) {
  301.  
  302.             //
  303.             // Add the opening bracket.
  304.             //
  305.             bufferEnd = _mbschr(buffer,0);
  306.             *bufferEnd = '[';
  307.             
  308.             //
  309.             // Add the value string in, again making sure the string is valid for an INF file.
  310.             //
  311.             pEscapeString(ObjectType,_mbsinc(bufferEnd),StringTwo);
  312.  
  313.             //
  314.             // Now, add the closing braket.
  315.             //
  316.             bufferEnd = _mbschr(buffer,0);
  317.             *bufferEnd = ']';
  318.  
  319.             //
  320.             // Terminate the string.
  321.             //
  322.             bufferEnd = _mbsinc(bufferEnd);
  323.             *bufferEnd = 0;
  324.         }
  325.  
  326.         //
  327.         // Add the final quote.
  328.         //
  329.         bufferEnd = _mbschr(buffer,0);
  330.         *bufferEnd = '"';
  331.         bufferEnd = _mbsinc(bufferEnd);
  332.         *bufferEnd = 0;
  333.     }
  334.     
  335.     return buffer;
  336. }
  337.  
  338. static
  339. BOOL
  340. pCreateMigObject (
  341.     IN MIGTYPE          ObjectType,
  342.     IN PCSTR            ParamOne,
  343.     IN PCSTR            ParamTwo,
  344.     IN PMIGSECTION      Section
  345.     )
  346. {
  347.     BOOL            rSuccess;
  348.     PMIGOBJECT      newObject = NULL;
  349.  
  350.     //
  351.     // pCreateMigObject uses a set of hueristics to correctly assemble an object. 
  352.     // These hueristics are based on the ObjectType and the contents of ParamTwo.
  353.     // 
  354.     // ObjectType       ParamTwo      Key                   Value
  355.     // -------------------------------------------------------------------------
  356.     // MIG_REGKEY       <any>         ParamOne[ParamTwo]    Registry
  357.     // <other>          NULL          ParamOne              <ObjectType As String>
  358.     // <other>          non-NULL      ParamOne              ParamTwo
  359.     //
  360.     //
  361.  
  362.  
  363.     if (Section) {
  364.  
  365.         //
  366.         // First, create an object...
  367.         //
  368.         newObject = PoolMemGetMemory(g_Pool,sizeof(MIGOBJECT));
  369.  
  370.         if (newObject) {
  371.  
  372.             if (ObjectType == MIG_REGKEY) {
  373.  
  374.                 newObject -> Key = 
  375.                     PoolMemDuplicateStringA(g_Pool,pGetValueString(ObjectType,ParamOne,ParamTwo));
  376.  
  377.                 newObject -> Value = PoolMemDuplicateStringA(g_Pool,pGetTypeAsString(ObjectType));
  378.             }
  379.             else {
  380.                 
  381.                 newObject -> Key = 
  382.                     PoolMemDuplicateStringA(g_Pool,pGetValueString(ObjectType,ParamOne,NULL));
  383.  
  384.                 if (ParamTwo) {
  385.                     newObject -> Value =
  386.                         PoolMemDuplicateStringA(g_Pool,pGetValueString(ObjectType,ParamTwo,NULL));
  387.                 }
  388.                 else {
  389.  
  390.                     newObject -> Value = 
  391.                         PoolMemDuplicateStringA(g_Pool,pGetTypeAsString(ObjectType));
  392.                 }
  393.             }
  394.         }
  395.     }
  396.  
  397.  
  398.     if (newObject && newObject -> Key && newObject -> Value) {
  399.  
  400.         //
  401.         // The object has been successfully created. Link it into the section.
  402.         //
  403.         newObject -> Next = Section -> Items;
  404.         Section -> Items = newObject;
  405.         rSuccess = TRUE;
  406.     }
  407.     else {
  408.         rSuccess = FALSE;
  409.     }
  410.  
  411.     return newObject && newObject -> Key && newObject -> Value;
  412. }
  413.  
  414.  
  415. static
  416. BOOL
  417. pWriteInfSectionToDisk (
  418.     IN PMIGSECTION Section
  419.     )
  420. {
  421.     PMIGOBJECT curObject;
  422.     BOOL       rSuccess = TRUE;
  423.  
  424.     if (Section) {
  425.  
  426.         curObject = Section -> Items;
  427.  
  428.         while (curObject && rSuccess) {
  429.  
  430.             if (Section -> Name && curObject -> Key && curObject -> Value) {
  431.             
  432.                 rSuccess = WritePrivateProfileString(
  433.                     Section   -> Name,
  434.                     curObject -> Key, 
  435.                     curObject -> Value,
  436.                     MIGRATEINF
  437.                     );
  438.             }
  439.  
  440.             curObject = curObject -> Next;
  441.         }
  442.     }
  443.     else {
  444.         rSuccess = FALSE;
  445.     }
  446.  
  447.     return rSuccess;
  448. }
  449.  
  450.  
  451. static
  452. BOOL
  453. pBuildListFromSection (
  454.     IN PCSTR    SectionString
  455.     )
  456. {
  457.     HINF            infHandle;
  458.     PMIGSECTION     section;
  459.     PMIGOBJECT      currentObject;
  460.     INFCONTEXT      ic;
  461.     DWORD           size;
  462.     BOOL            rSuccess = TRUE;
  463.  
  464.     //
  465.     // This function assumes that Section is non-NULL.
  466.     //
  467.     assert(SectionString);
  468.  
  469.     currentObject = NULL;
  470.     
  471.     //
  472.     // First find the section specified.
  473.     //
  474.     section = pFindSection(SectionString,MIGINF_CREATE);
  475.  
  476.     if (section) {
  477.         
  478.         infHandle = SetupOpenInfFileA(MIGRATEINF,NULL,INF_STYLE_WIN4,NULL);
  479.         
  480.         if (infHandle != INVALID_HANDLE_VALUE) {
  481.             
  482.             if (SetupFindFirstLine(infHandle,SectionString,NULL,&ic)) {
  483.                 
  484.                 do {
  485.  
  486.                     //
  487.                     // Create the object.
  488.                     //
  489.                     currentObject = (PMIGOBJECT) PoolMemGetMemory(g_Pool,sizeof(MIGOBJECT));
  490.                     
  491.                     if (!currentObject) {
  492.                         rSuccess = FALSE;
  493.                         break;
  494.                     }
  495.                     
  496.                     //
  497.                     // Get the size of the string.
  498.                     //
  499.                     if (!SetupGetLineTextA(&ic,NULL,NULL,NULL,NULL,0,&size)) {
  500.                         rSuccess = FALSE;
  501.                         break;
  502.                     }
  503.                     
  504.                     //
  505.                     // Create a string large enough.
  506.                     //
  507.                     currentObject -> Key = PoolMemCreateStringA(g_Pool,size);
  508.                     
  509.                     if (!currentObject -> Key) {
  510.                         rSuccess = FALSE;
  511.                         break;
  512.                     }
  513.                     
  514.                     //
  515.                     // Get the string.
  516.                     //
  517.                     if (!SetupGetLineTextA(&ic,NULL,NULL,NULL,currentObject -> Key,size,NULL)) {
  518.                         rSuccess = FALSE;
  519.                         break;
  520.                     }
  521.                     
  522.                     //
  523.                     // Successfully retrieved the line.
  524.                     //
  525.                     currentObject -> Value  = (PSTR) pGetTypeAsString(MIG_FILE);
  526.                     currentObject -> Next   = section -> Items;
  527.                     section -> Items        = currentObject;
  528.                     
  529.                 } while(SetupFindNextLine(&ic,&ic));
  530.                 
  531.             }
  532.             
  533.             SetupCloseInfFile(infHandle);
  534.         }
  535.     }
  536.     else {
  537.         rSuccess = FALSE;
  538.     }
  539.  
  540.     return rSuccess;
  541. }
  542.  
  543.  
  544. BOOL
  545. WINAPI
  546. MigInf_Initialize(
  547.     VOID
  548.     )
  549. {
  550.  
  551.     //
  552.     // First, initialize our pool and Zero out the structure.
  553.     //
  554.     g_Pool = PoolMemInitPool();
  555.  
  556.  
  557.     if (g_Pool) {
  558.         
  559.         //
  560.         // Now, read in the migration paths and excluded paths sections.
  561.         //
  562.         if (!pBuildListFromSection(SECTION_MIGRATIONPATHS) ||
  563.             !pBuildListFromSection(SECTION_EXCLUDEDPATHS)) {
  564.             //
  565.             // Something went wrong (i.e. out of memory. Destroy and NULL our pool.
  566.             //
  567.             PoolMemDestroyPool(g_Pool);
  568.             g_Pool = NULL;
  569.         }
  570.     }
  571.  
  572.     //
  573.     // If our memory pool initialized successfully, return TRUE.
  574.     //
  575.     return (g_Pool != NULL);
  576.  
  577. }
  578.  
  579.  
  580. VOID
  581. WINAPI
  582. MigInf_CleanUp (
  583.     VOID
  584.     )
  585. {
  586.     //
  587.     // Only thing we need to do is clean out pool mem. We'll NULL out the list header to make
  588.     // sure it isn't usable.
  589.     //
  590.     if (g_Pool) {
  591.         PoolMemDestroyPool(g_Pool);
  592.         g_Pool = NULL;
  593.     }
  594.     
  595.     g_MigrationInf = NULL;
  596.  
  597. }
  598.  
  599.  
  600. BOOL
  601. WINAPI
  602. MigInf_AddObject (
  603.     IN MIGTYPE  ObjectType,
  604.     IN PCSTR    SectionString,
  605.     IN PCSTR    ParamOne,
  606.     IN PCSTR    ParamTwo
  607.     )
  608. {
  609.  
  610.     return pCreateMigObject(
  611.         ObjectType,
  612.         ParamOne,
  613.         ParamTwo,
  614.         pFindSection(SectionString,MIGINF_CREATE)
  615.         );
  616. }
  617.  
  618. BOOL 
  619. WINAPI 
  620. MigInf_FirstInSection(
  621.     IN PCSTR SectionName, 
  622.     OUT PMIGINFSECTIONENUM Enum
  623.     )
  624. {
  625.     PMIGSECTION section;
  626.  
  627.     //
  628.     // We assume that Enum is valid.
  629.     //
  630.     assert(Enum);
  631.  
  632.     section = pFindSection(SectionName,MIGINF_NOCREATE);
  633.  
  634.     if (section) {
  635.         Enum -> EnumKey = (PVOID) section -> Items;
  636.     }
  637.  
  638.     return MigInf_NextInSection(Enum);
  639. }
  640.  
  641. BOOL 
  642. WINAPI 
  643. MigInf_NextInSection(
  644.     IN OUT PMIGINFSECTIONENUM Enum
  645.     )
  646. {
  647.  
  648.  
  649.     BOOL            rSuccess = FALSE;
  650.  
  651.     //
  652.     // We assume that the Enum is valid.
  653.     //
  654.     assert(Enum);
  655.  
  656.     if (Enum -> EnumKey) {
  657.  
  658.         Enum -> Key     = ((PMIGOBJECT) (Enum -> EnumKey)) -> Key;
  659.         Enum -> Value   = ((PMIGOBJECT) (Enum -> EnumKey)) -> Value;
  660.         Enum -> EnumKey = ((PVOID) ((PMIGOBJECT) (Enum -> EnumKey)) -> Next);
  661.         rSuccess = TRUE;
  662.     }
  663.  
  664.     return rSuccess;
  665. }
  666.  
  667.  
  668. BOOL
  669. WINAPI
  670. MigInf_WriteInfToDisk (
  671.     VOID
  672.     )
  673. {
  674.  
  675.     BOOL        rSuccess = TRUE;
  676.     PMIGSECTION curSection;
  677.     
  678.     //
  679.     // Simply loop through all of the sections, writing each of them to disk.
  680.     // As long as WriteSectionToDisk works, we work.
  681.     //
  682.     curSection = g_MigrationInf;
  683.  
  684.     while (curSection && rSuccess) {
  685.  
  686.         //
  687.         // We skip the [Excluded Paths] and [Migration Paths] sections.
  688.         //
  689.         if (_mbsicmp(curSection -> Name,SECTION_EXCLUDEDPATHS) &&
  690.             _mbsicmp(curSection -> Name,SECTION_MIGRATIONPATHS)) {
  691.             
  692.             rSuccess = pWriteInfSectionToDisk(curSection);
  693.         } 
  694.  
  695.         curSection = curSection -> Next;
  696.         
  697.     }
  698.  
  699.     return rSuccess;
  700. }
  701.  
  702. BOOL
  703. WINAPI
  704. MigInf_PathIsExcluded (
  705.     IN PCSTR    Path
  706.     )
  707. {
  708.     PMIGOBJECT  curExcluded;
  709.     PMIGSECTION section;
  710.     BOOL        rIsExcluded = FALSE;
  711.  
  712.     //
  713.     // We assume Path is valid.
  714.     //
  715.     assert(Path);
  716.     
  717.     section = pFindSection(SECTION_EXCLUDEDPATHS,MIGINF_NOCREATE);
  718.  
  719.     if (section) {
  720.  
  721.         curExcluded = section -> Items;
  722.         
  723.         while (curExcluded && !rIsExcluded) {
  724.             
  725.             rIsExcluded = pPathIsInPath(Path,curExcluded -> Key);
  726.             curExcluded = curExcluded -> Next;
  727.         }
  728.     }
  729.     
  730.     return rIsExcluded;
  731. }
  732.  
  733.  
  734.  
  735. PCSTR
  736. WINAPI
  737. MigInf_GetNewSectionName (
  738.     VOID
  739.     )
  740. {
  741.  
  742.     static CHAR     sectionName[20];
  743.     static DWORD    seedNum=0;
  744.  
  745.  
  746.     sprintf(sectionName,"msg%0.7u",seedNum++);
  747.  
  748.     return sectionName;
  749. }
  750.  
  751.  
  752.  
  753.