MIGINF.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:17k
源码类别:

Windows编程

开发平台:

Visual C++

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