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

Windows编程

开发平台:

Visual C++

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