C# 用C创建.cat文件#
我正在尝试导入并使用CryptCatCdfenummbersByCdftagex,以便使用C#创建.cat文件。函数返回null,参数似乎未初始化。我用C++编写了相应的代码,效果不错。我猜我的结构是错的 任何帮助都将不胜感激。代码应该在程序的工作目录中创建一个Good.cat文件,该文件应该包含下面指定的文件的哈希值[CatalogFiles] Catalog.cdfC# 用C创建.cat文件#,c#,c++,winapi,cryptography,pinvoke,C#,C++,Winapi,Cryptography,Pinvoke,我正在尝试导入并使用CryptCatCdfenummbersByCdftagex,以便使用C#创建.cat文件。函数返回null,参数似乎未初始化。我用C++编写了相应的代码,效果不错。我猜我的结构是错的 任何帮助都将不胜感激。代码应该在程序的工作目录中创建一个Good.cat文件,该文件应该包含下面指定的文件的哈希值[CatalogFiles] Catalog.cdf [CatalogHeader] Name=Good.cat ResultDir=.\ PublicVersion=0x0000
[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);
}
}
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++示例< /P>
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”作为类 变化:
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);
}
}
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);
}
}
}
公共类CRYPTCATMEMBER
看起来有误。这不应该是一个结构吗?@IInspectable我尝试过使用class和struct,然后在更改签名后将该结构作为ref参数传递给CryptCatCdFenumMembersByCDTagex。它编译并运行,但返回相同的结果。您没有告诉我们代码在哪里失败。您似乎没有执行任何错误检查。您有一个没有分配内存的StringBuilder。看来你太过分了。我先从一个功能性的C++程序开始。至少你会明白这些步骤。@DavidHeffernan,在SO上发问的人通常都是深不可测的。它在函数CufftCCADFEUMUMYNESBYBCDFTAGEX中失败,而C++代码返回正确的值(返回值和参数),C代码不返回。我删除错误代码的原因是没有错误代码。Marshal.GetLastWin32Error();返回0。StringBuilder,是的。我在最后一分钟把它改成了字符串。但仍然不工作。您可以通过检查返回值来检查错误。你不能那样做。不管怎样,因为你有C++和C代码,你可以把你传递的值记录为参数,并寻找差异。在我的例子中,用完全相同的代码,它不枚举文件,除了第一个文件,同时在指定的路径中创建“.CAT”文件。但是创建的“.cat”文件大小为零。