c# - 使用 C# 创建 .cat 文件

标签 c# c++ winapi cryptography pinvoke

我正在尝试导入和使用 CryptCATCDFEnumMembersByCDFTagEx,以便使用 C# 创建 .cat 文件。该函数返回 null 并且参数似乎没有被初始化。我用 C++ 编写了相应的代码,效果很好。我猜我的结构有问题。

如有任何帮助,我们将不胜感激。该代码应在程序的工作目录中创建一个 Good.cat 文件,其中应包含 [CatalogFiles] 下指定文件的哈希值。

目录.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);
}

最佳答案

只要对您的程序稍作改动,我就可以创建目录文件。没有修改任何结构或其成员。仍然使用“CRYPTCATMEMBER”作为类

变化:

  1. 将 null 分配给字符串变量,在本例中为“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);
                }
            }
        }

关于c# - 使用 C# 创建 .cat 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33594111/

相关文章:

c++ - C++中的重载运算符

c++ - "Unresolved external _WinMain@16"如果我将 WndProc 移动到另一个 cpp 文件

c++ - 如何以编程方式区分 subst 命令创建的虚拟驱动器和实际可移动驱动器

C++ Win32 改变静态颜色

c# - 如何从 httpclient 调用中获取内容主体?

c# - 如果禁用,则设置无值 datetimepicker 的方法

c# - 如何在 C# 中使用 IUIAutomation::ElementFromIAccessible 方法?

c# - 如何正确序列化可排序的 SQLCLR 用户定义类型?

c++ - 如何在不破坏主框架的情况下终止 wxWidgets 消息循环?

c# - 通过共享内存将数据从 C++ 流式传输到 C#