2015-11-08 91 views
0

我正在嘗試導入並使用CryptCATCDFEnumMembersByCDFTagEx以便使用C#創建.cat文件。該函數返回null,參數似乎沒有被初始化。我用C++編寫了相應的代碼,工作正常。我猜我的結構已經關閉了。使用C#創建.cat文件#

任何幫助,將不勝感激。代碼應該在程序的工作目錄中創建一個Good.cat文件,該文件應該包含下面指定文件的散列[CatalogFiles]。

Catalog.cdf

[CatalogHeader] 
Name=Good.cat 
ResultDir=.\ 
PublicVersion=0x0000001 
EncodingType=0x00010001 
CATATTR1=0x10010001:OSAttr:2:6.0 
[CatalogFiles] 
Notepad.exe=C:\Windows\Notepad.exe 

C#示例程序。

class Program 
{ 
    //https://msdn.microsoft.com/en-us/library/windows/desktop/bb427419%28v=vs.85%29.aspx 
    [StructLayout(LayoutKind.Sequential)] 
    public struct CRYPTCATCDF 
    { 
     uint cbStruct; 
     IntPtr hFile; 
     uint dwCurFilePos; 
     uint dwLastMemberOffset; 
     bool fEOF; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     string pwszResultDir; 
     IntPtr hCATStore; 
    } 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/aa381414%28v=vs.85%29.aspx 
    [StructLayout(LayoutKind.Sequential)] 
    public struct CRYPTOAPI_BLOB 
    { 
     public uint cbData; // UInt32 cbData; 
     //[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] 
     public IntPtr pbData; //public byte[] pbData 
    } // CRYPT_INTEGER_BLOB, CRYPT_ATTR_BLOB, CRYPT_OBJID_BLOB, CRYPT_HASH_BLOB 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/bb736433%28v=vs.85%29.aspx 
    [StructLayout(LayoutKind.Sequential)] 
    public struct SIP_INDIRECT_DATA 
    { 
     public CRYPT_ATTRIBUTE_TYPE_VALUE Data; 
     public CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm; 
     public CRYPTOAPI_BLOB Digest; 
    } 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/aa381151%28v=vs.85%29.aspx 
    [StructLayout(LayoutKind.Sequential)] 
    public struct CRYPT_ATTRIBUTE_TYPE_VALUE { 
     [MarshalAs(UnmanagedType.LPStr)] 
     public string pszObjId; 
     public CRYPTOAPI_BLOB Value; 
    } 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/aa381133%28v=vs.85%29.aspx 
    [StructLayout(LayoutKind.Sequential)] 
    public struct CRYPT_ALGORITHM_IDENTIFIER 
    { 
     [MarshalAs(UnmanagedType.LPStr)] 
     public string pszObjId; 
     public CRYPTOAPI_BLOB Parameters; 
    } 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/aa373931%28v=vs.85%29.aspx 
    [StructLayout(LayoutKind.Sequential)] 
    public struct GUID 
    { 
     int  a; 
     short b; 
     short c; 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 
     byte[] d; 
    } 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/aa379905%28v=vs.85%29.aspx 
    [StructLayout(LayoutKind.Sequential)] 
    public class CRYPTCATMEMBER 
    { 
     public uint cbStruct; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string pwszReferenceTag; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string pwszFileName; 
     public GUID gSubjectType; 
     public uint fdwMemberFlags; 
     public IntPtr pIndirectData; //struct SIP_INDIRECT_DATA_ *pIndirectData; 
     public uint dwCertVersion; 
     public uint dwReserved; 
     public IntPtr hReserved; 
     public CRYPTOAPI_BLOB sEncodedIndirectData; 
     public CRYPTOAPI_BLOB sEncodedMemberInfo; 
    } 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/bb410248%28v=vs.85%29.aspx 
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
    public delegate void PFN_CDF_PARSE_ERROR_CALLBACK(
     [In] uint dwErrorArea, 
     [In] uint dwLocalError, 
     [In, MarshalAs(UnmanagedType.LPWStr)] string pwszLine 
    ); 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/bb427424%28v=vs.85%29.aspx 
    [DllImport("wintrust.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)] 
    static extern IntPtr CryptCATCDFOpen(
     [In, MarshalAs(UnmanagedType.LPWStr)] string pwszFilePath, 
     [In, Optional] IntPtr pfnParseError 
    ); 

    //https://msdn.microsoft.com/en-us/library/windows/desktop/bb427423%28v=vs.85%29.aspx 
    [DllImport("wintrust.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)] 
    static extern string CryptCATCDFEnumMembersByCDFTagEx(
     [In] IntPtr pCDF, 
     [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszPrevCDFTag, 
     [In] IntPtr pfnParseError, 
     [In] CRYPTCATMEMBER ppMember, 
     [In] bool fContinueOnError, 
     [In] IntPtr pvReserved 
    ); 

    private static void ParseErrorCallback(uint u1, uint u2, string s) 
    { 
     Console.WriteLine(u1 + " " + u2 + " " + s); 
    } 

    static void Main(string[] args) 
    { 
     PFN_CDF_PARSE_ERROR_CALLBACK pfn = new PFN_CDF_PARSE_ERROR_CALLBACK(ParseErrorCallback); 
     StringBuilder sb = new StringBuilder(256); 
     string s = string.Empty; 

     IntPtr cdfPtr = CryptCATCDFOpen("catalog.cdf", Marshal.GetFunctionPointerForDelegate(pfn)); 
     CRYPTCATCDF cdf = (CRYPTCATCDF)Marshal.PtrToStructure(cdfPtr, typeof(CRYPTCATCDF)); 

     CRYPTCATMEMBER ccm = new CRYPTCATMEMBER(); 
     ccm.pIndirectData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SIP_INDIRECT_DATA))); 

     do 
     { 
      s = CryptCATCDFEnumMembersByCDFTagEx(cdfPtr, sb, Marshal.GetFunctionPointerForDelegate(pfn), ccm, true, IntPtr.Zero); 
      Console.WriteLine(s ?? "N/A"); 
     } while (s != null); 
    } 
} 

工作C++例子

void callback(DWORD u1, DWORD u2, LPWSTR s) 
{ 
    printf("%d %d %s", u1, u2, s); 
} 

typedef LPWSTR(WINAPI *CryptCATCDFEnumMembersByCDFTagEx)(
    CRYPTCATCDF     *pCDF, 
    LPWSTR      pwszPrevCDFTag, 
    PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError, 
    CRYPTCATMEMBER    **ppMember, 
    BOOL       fContinueOnError, 
    LPVOID      pvReserved); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    CRYPTCATCDF  *cdf; 
    CRYPTCATMEMBER *pMember = NULL; 
    LPWSTR   pwszMemberTag = NULL; 
    HINSTANCE  dllHandle = LoadLibrary(L"wintrust.dll"); 

    cdf = CryptCATCDFOpen(L"catalog.cdf", (PFN_CDF_PARSE_ERROR_CALLBACK)callback); 
    CryptCATCDFEnumMembersByCDFTagEx fptr = (CryptCATCDFEnumMembersByCDFTagEx)GetProcAddress(dllHandle, "CryptCATCDFEnumMembersByCDFTagEx"); 

    while (pwszMemberTag = (*fptr)(cdf, pwszMemberTag, NULL, &pMember, TRUE, NULL)) 
    { 
     wprintf(L"%s", pwszMemberTag); 
    } 

    CryptCATCDFClose(cdf); 
} 
+0

'public class CRYPTCATMEMBER'看起來不對。不應該是'struct'嗎? – IInspectable

+0

@IInspectable我已經嘗試使用類和使用結構,然後在更改簽名後將結構作爲ref參數傳遞給CryptCATCDFEnumMembersByCDFTagEx。它編譯並運行,但返回相同。 – citizencane

+0

你沒有告訴我們代碼失敗的地方。你似乎沒有做過任何錯誤檢查。你有一個你沒有分配內存的StringBuilder。看起來你超出了你的深度。我首先要製作一個功能正常的C++程序。那麼至少你會明白這些步驟。 –

回答

0

有了細微的變化到您的程序,我可以創建目錄文件。沒有修改任何結構或其成員。仍然使用 「CRYPTCATMEMBER」 作爲類

變化:

  1. 指定空字符串變量,在這種情況下, 「S」。
  2. 枚舉目錄定義文件(.cdf)中的文件後,調用CryptCATCDFClose函數。

工作控制檯程序。

static void Main(string[] args) 
     { 
      CRYPTCATMEMBER ccm = null; 
      try 
      { 
       PFN_CDF_PARSE_ERROR_CALLBACK pfn = ParseErrorCallback; 
       string s = null; //This null assignment is deliberately done. 

       IntPtr cdfPtr = CryptCATCDFOpen("catalog.cdf", Marshal.GetFunctionPointerForDelegate(pfn)); 
       CRYPTCATCDF cdf = (CRYPTCATCDF) Marshal.PtrToStructure(cdfPtr, typeof(CRYPTCATCDF)); //This call is required else the catlog file creation fails 

       ccm = new CRYPTCATMEMBER 
       { 
        pIndirectData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SIP_INDIRECT_DATA))) 
       }; 

       do 
       { 
        s = CryptCATCDFEnumMembersByCDFTagEx(cdfPtr, s, Marshal.GetFunctionPointerForDelegate(pfn), ccm, true, IntPtr.Zero); 
        Console.WriteLine(s ?? "N/A"); 
       } while (s != null); 
       CryptCATCDFClose(cdfPtr); //This is required to update the .cat with the files details specified in .cdf file. 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e); 
       throw; 
      } 
      finally 
      { 
       // Free the unmanaged memory. 
       if (ccm != null) 
       { 
        Marshal.FreeHGlobal(ccm.pIndirectData); 
       } 
      } 
     }