PDA

View Full Version : [Q] API trong .NET



hbspb
18-04-2003, 14:27
Cho hỏi trong .NET có sử dụng được các hàm API không vậy.
Nếu được phải làm sao? (phải include thêm các namespace nào vậy). Ai biết chỉ dùm nhe. Xin cám ơn nhiều.

mynhung
18-04-2003, 15:47
bạn tra MSDN với keyword DllImport để xem samples của DllImportAttribute. Cơ chế Platform Invoke mà .NET cung cấp rất dễ sử dụng nhờ các marshal chuyển đổi kiểu tự động --> dễ dàng gọi các hàm Win32APIs.

hueduongit
21-04-2003, 09:09
//Ví dụ:
[DllImport("shell32.dll")]
static public extern int ShellExecute(int hwnd, string lpOperation ,string lpFile, string lpParameters, string lpDirectory, int nShowCmd );
...
int iResult = ShellExecute(1,null,"Tam.doc",null,"Environment.CurrentDirectory",1);
...

thabeo
24-04-2003, 20:54
Tôi thấy để sử dụng được các API trong .NET không phải là dễ nhất là lúc phải chuyển kiểu (ví dụ từ void* sang Inptr). Tôi cần phải gọi hàm API trong C# mà mãi không được, luôn bị trả về giá trị false:
BOOL WINAPI CryptEncodeObject(
DWORD dwCertEncodingType,
LPCSTR lpszStructType,
const void *pvStructInfo,
BYTE *pbEncoded,
DWORD *pcbEncoded
);
Bác nào biết hay đã từng gọi hàm API này trong C# rồi xin chỉ giáo.

danceswithwolves
24-04-2003, 23:14
void* là kiểu con trỏ tự do, tùy theo mục đích của bạn (muốn trả về con trỏ kiểu gì) mà bạn implement các overloaded methods - tức là bạn phải quy định kiểu rõ ràng (strong-typed mà). Ngoại trừ overloading, tôi nghĩ không có cách nào implement void* được.

Chương trình của bạn hẳn biết rõ kiểu của pvStructInfo trước compile-time, vậy bạn explicitly declare kiểu của nó luôn đi.

thabeo
25-04-2003, 20:15
Mục đích dùng con trỏ void* trong hàm này là để tất cả các cấu trúc với tên tương ứng được lưu trong lpszStructType, đều có thể truyền cho hàm này được. Nhưng mà trong C# không có kiểu con trỏ, vậy phải làm thế nào để truyền biến cho hàm này đây. Ban nào đã từng viết và gọi thành công nhung hàm API tương tự trong C#, thì xin gửi cho tui đoạn code hoặc xin chỉ giáo . Cám ơn rất nhiều.

danceswithwolves
26-04-2003, 07:52
C# hỗ trợ con trỏ mà, bạn tra MSDN từ khoá "unsafe" để lấy thông tin chi tiết.

thabeo
26-04-2003, 10:36
Ok, nhưng sử dụng con trỏ trong C# thì lại phải đi tự quản lí bộ nhớ và đổ rác làm mãi trong VC++ rồi rắc rỗi và mệt lắm, không tận dụng được cái gabrage collection trong C#. Các bạn nào có đoạn code nào không dùng con trỏ mà vẫn sử dụng được hàm API này trong C# không nhỉ thì gửi cho mình đoạn code đó đi, thanks:
BOOL WINAPI CryptEncodeObject(
DWORD dwCertEncodingType,
LPCSTR lpszStructType,
const void *pvStructInfo,
BYTE *pbEncoded,
DWORD *pcbEncoded
);

danceswithwolves
26-04-2003, 23:59
bó tay thabeo@ luôn, nói đến vậy rồi mà vẫn... :D

White_Rose
27-04-2003, 00:55
Các bạn nào có đoạn code nào không dùng con trỏ mà vẫn sử dụng được hàm API này trong C# không nhỉ thì gửi cho mình đoạn code đó điTóm tắt lại các ý trên nhé:
KHÔNG

thabeo
27-04-2003, 10:34
Sorry danceswithwolves !!! Nói thì như vậy nhưng bác cứ thử nhảy vào gọi mấy cái hàm API này xem.

danceswithwolves
27-04-2003, 23:14
sorry thabeo@, nói đến vậy mà bạn vẫn không hiểu ý tôi à ? trước hết, xem chữ KHÔNG to đùng ngã ngửa của WR@ nếu như bạn hỏi về cách implement void* structures without "unsafe" đúng như ý nghĩa generic của void*. Tôi đã chẳng đề nghị bạn specify rõ pstructure thay cho void* hay sao ? còn nếu bạn muốn implement với "unsafe" theo kiểu C++ mà than rằng manage memory khó quá thì làm quái nào được ?

tôi trả lời bạn với thiện chí, vậy đừng khiêu khích nhau.

thabeo
28-04-2003, 20:01
Không có cái gì là "Không " thể cả, chỉ chưa thể được mà thôi. Tôi không có ý khiêu khích bạn. Cám ơn thiện trí trả lời của bạn nếu bạn có thiện chí hơn nữa, bạn có thể chuyển đoạn chương trình sau sang C# được không ? Một lần nữa xin cám ơn bạn rất nhiều.

Platform SDK: Security
Example C Program: Making a Certificate Request
The following example code demonstrates the procedure outlined in the previous section. This example code creates a simple certificate request with one signer, a single relative distinguished name (RDN) attribute, and no general attributes.

This example program illustrates the following CryptoAPI functions:

CryptEncodeObject.
CryptAcquireContext.
CryptExportPublicKeyInfo.
CryptSignAndEncodeCertificate.
This example code also uses the functions ByteToStr and HandleError. C code for these function is included with the sample.

General Purpose Functions lists C code for these and other auxiliary functions.

//-------------------------------------------------------------------
// This example code demonstrates how to create and encode a
// certificate request.
//-------------------------------------------------------------------
// In this and all other sample and example code,
// use the following #define and #include statements. These are
// also listed under #includes and #defines.

#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void HandleError(char *s);

//-------------------------------------------------------------------
// This program use this additional #define statement.

#define CERT_SUBJECT_NAME "This certificate user"

//--------------------------------------------------------------------
// This program uses the function ByteToStr to convert an array
// of BYTEs to a char string.

void ByteToStr(
DWORD cb,
void* pv,
LPSTR sz)
//--------------------------------------------------------------------
// Parameters passed are:
// pv is the array of BYTEs to be converted.
// cb is the number of BYTEs in the array.
// sz is a pointer to the string to be returned.

{
//--------------------------------------------------------------------
// Declare and initialize local variables.

BYTE* pb = (BYTE*) pv; // local pointer to a BYTE in the BYTE array
DWORD i; // local loop counter
int b; // local variable

//--------------------------------------------------------------------
// Begin processing loop.

for (i = 0; i<cb; i++)
{
b = (*pb & 0xF0) >> 4;
*sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A';
b = *pb & 0x0F;
*sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A';
pb++;
}
*sz++ = 0;
}

void main(void)
{
//-------------------------------------------------------------------
// Declare and initialize variables

// Declare and initialize a CERT_RDN_ATTR array.
// In this code, only one array element is used.

CERT_RDN_ATTR rgNameAttr[] = {
"2.5.4.3", // pszObjId
CERT_RDN_PRINTABLE_STRING, // dwValueType
strlen(CERT_SUBJECT_NAME), // value.cbData
(BYTE*)CERT_SUBJECT_NAME}; // value.pbData

//-------------------------------------------------------------------
// Declare and initialize a CERT_RDN array.
// In this code, only one array element is used.

CERT_RDN rgRDN[] = {
1, // rgRDN[0].cRDNAttr
&rgNameAttr[0]}; // rgRDN[0].rgRDNAttr

//-------------------------------------------------------------------
// Declare and initialize a CERT_NAME_INFO structure.

CERT_NAME_INFO Name = {
1, // Name.cRDN
rgRDN}; // Name.rgRDN

//-------------------------------------------------------------------
// Declare and initialize all other variables and structures.

CERT_REQUEST_INFO CertReqInfo;
CERT_NAME_BLOB SubjNameBlob;
DWORD cbNameEncoded;
BYTE* pbNameEncoded;
HCRYPTPROV hCryptProv;
DWORD cbPublicKeyInfo;
CERT_PUBLIC_KEY_INFO* pbPublicKeyInfo;
DWORD cbEncodedCertReqSize;
CRYPT_OBJID_BLOB Parameters;
CRYPT_ALGORITHM_IDENTIFIER SigAlg;
BYTE* pbSignedEncodedCertReq;
char* pSignedEncodedCertReqBlob;

//-------------------------------------------------------------------
// Begin processing.

if(CryptEncodeObject(
MY_ENCODING_TYPE, // Encoding type
X509_NAME, // Structure type
&Name, // Address of CERT_NAME_INFO structure
NULL, // pbEncoded
&cbNameEncoded)) // pbEncoded size
{
printf("The first call to CryptEncodeObject succeeded. \n");
}
else
{
HandleError("First call to CryptEncodeObject failed.\
\nA public/private key pair may not exit in the container. \n");
}
//-------------------------------------------------------------------
// Allocate memory for the encoded name.

if(!(pbNameEncoded = (BYTE*)malloc(cbNameEncoded)))
HandleError("pbNamencoded malloc operation failed.\n");

//-------------------------------------------------------------------
// Call CryptEncodeObject to do the actual encoding of the name.

if(CryptEncodeObject(
MY_ENCODING_TYPE, // Encoding type
X509_NAME, // Structure type
&Name, // Address of CERT_NAME_INFO structure
pbNameEncoded, // pbEncoded
&cbNameEncoded)) // pbEncoded size
{
printf("The object is encoded. \n");
}
else
{
free(pbNameEncoded);
HandleError("Second call to CryptEncodeObject failed.\n");
}
//--------------------------------------------------------------------
// Set the subject member of CertReqInfo to point to
// a CERT_NAME_INFO structure that
// has been initialized with the data from cbNameEncoded
// and pbNameEncoded.

SubjNameBlob.cbData = cbNameEncoded;
SubjNameBlob.pbData = pbNameEncoded;
CertReqInfo.Subject = SubjNameBlob;

//--------------------------------------------------------------------
// Generate custom information. This step is not
// implemented in this code.

CertReqInfo.cAttribute = 0;
CertReqInfo.rgAttribute = NULL;
CertReqInfo.dwVersion = CERT_REQUEST_V1;

//--------------------------------------------------------------------
// Call CryptExportPublicKeyInfo to return an initialized
// CERT_PUBLIC_KEY_INFO structure.
// First, get a cryptographic provider.

if(CryptAcquireContext(
&hCryptProv, // Address for handle to be returned.
NULL, // Use the current user's logon name.
NULL, // Use the default provider.
PROV_RSA_FULL, // Need to both encrypt and sign.
NULL)) // No flags needed.
{
printf("A cryptographic provider has been acquired. \n");
}
else
{
free(pbNameEncoded);
HandleError("CryptAcquireContext failed.");
}
//--------------------------------------------------------------------
// Call CryptExportPublicKeyInfo to get the size of the returned
// information.

if(CryptExportPublicKeyInfo(
hCryptProv, // Provider handle
AT_SIGNATURE, // Key spec
MY_ENCODING_TYPE, // Encoding type
NULL, // pbPublicKeyInfo
&cbPublicKeyInfo)) // Size of PublicKeyInfo
{
printf("The keyinfo structure is %d bytes.\n",cbPublicKeyInfo);
}
else
{
free(pbNameEncoded);
HandleError("First call to CryptExportPublickKeyInfo failed.\
\nProbable cause: No key pair in the key container. \n");
}
//--------------------------------------------------------------------
// Allocate the necessary memory.

if(pbPublicKeyInfo =
(CERT_PUBLIC_KEY_INFO*)malloc(cbPublicKeyInfo))
{
printf("Memory is allocated for the public key structure. \n");
}
else
{
free(pbNameEncoded);
HandleError("Memory allocation failed.");
}
//--------------------------------------------------------------------
// Call CryptExportPublicKeyInfo to get pbPublicKeyInfo.

if(CryptExportPublicKeyInfo(
hCryptProv, // Provider handle
AT_SIGNATURE, // Key spec
MY_ENCODING_TYPE, // Encoding type
pbPublicKeyInfo, // pbPublicKeyInfo
&cbPublicKeyInfo)) // Size of PublicKeyInfo
{
printf("The key has been exported. \n");
}
else
{
free(pbNameEncoded);
free(pbPublicKeyInfo);
HandleError("Second call to CryptExportPublicKeyInfo failed.");
}
//--------------------------------------------------------------------
// Set the SubjectPublicKeyInfo member of the
// CERT_REQUEST_INFO structure to point to the CERT_PUBLIC_KEY_INFO
// structure created.

CertReqInfo.SubjectPublicKeyInfo = *pbPublicKeyInfo;

memset(&Parameters, 0, sizeof(Parameters));
SigAlg.pszObjId = szOID_OIWSEC_sha1RSASign;
SigAlg.Parameters = Parameters;

//--------------------------------------------------------------------
// Call CryptSignAndEncodeCertificate to get the size of the
// returned BLOB.

if(CryptSignAndEncodeCertificate(
hCryptProv, // Crypto provider
AT_KEYEXCHANGE, // Key spec
MY_ENCODING_TYPE, // Encoding type
X509_CERT_REQUEST_TO_BE_SIGNED, // Structure type
&CertReqInfo, // Structure information
&SigAlg, // Signature algorithm
NULL, // Not used
NULL, // pbSignedEncodedCertReq
&cbEncodedCertReqSize)) // Size of certificate
// required
{
printf("The size of the encoded certificate is set. \n");
}
else
{
free(pbNameEncoded);
free(pbPublicKeyInfo);
HandleError("First call to CryptSignandEncode failed.");
}
//--------------------------------------------------------------------
// Allocate memory for the encoded certificate request.

if(pbSignedEncodedCertReq = (BYTE*)malloc(cbEncodedCertReqSize))
{
printf("Memory has been allocated.\n");
}
else
{
free(pbNameEncoded);
free(pbPublicKeyInfo);
HandleError("Malloc operation failed.");
}
//--------------------------------------------------------------------
// Call CryptSignAndEncodeCertificate to get the
// returned BLOB.

if(CryptSignAndEncodeCertificate(
hCryptProv, // Crypto provider
AT_KEYEXCHANGE, // Key spec
MY_ENCODING_TYPE, // Encoding type
X509_CERT_REQUEST_TO_BE_SIGNED, // Struct type
&CertReqInfo, // Struct info
&SigAlg, // Signature algorithm
NULL, // Not used
pbSignedEncodedCertReq, // Pointer
&cbEncodedCertReqSize)) // Length of the message
{
printf("The message is encoded and signed. \n");
}
else
{
free(pbNameEncoded);
free(pbPublicKeyInfo);
free(pbSignedEncodedCertReq);
HandleError("Second call to CryptSignAndEncode failed.");
}
//--------------------------------------------------------------------
// View the signed and encoded certificate request BLOB.

pSignedEncodedCertReqBlob =
new char[(cbEncodedCertReqSize *2) +1];

//--------------------------------------------------------------------
// Call ByteToStr, one of the general purpose functions, to convert
// the byte BLOB to ASCII hexadecimal format.

ByteToStr(cbEncodedCertReqSize,
pbSignedEncodedCertReq,
pSignedEncodedCertReqBlob);

//--------------------------------------------------------------------
// Print the string.
printf("The string created is:\n");
printf("%s\n",pSignedEncodedCertReqBlob);

//--------------------------------------------------------------------
// Free memory.

free(pbNameEncoded);
free(pbPublicKeyInfo);
free(pbSignedEncodedCertReq);
CryptReleaseContext(hCryptProv,0);

printf("\nMemory freed. Program ran without error. \n");
} // End of main

//--------------------------------------------------------------------
// This example uses the function HandleError, a simple error
// handling function, to print an error message to the standard error
// (stderr) file and exit the program.
// For most applications, replace this function with one
// that does more extensive error reporting.

void HandleError(char *s)
{
fprintf(stderr,"An error occurred in running the program. \n");
fprintf(stderr,"%s\n",s);
fprintf(stderr, "Error number %x.\n", GetLastError());
fprintf(stderr, "Program terminating. \n");
exit(1);
} // End of HandleError