I'm using ado to connect SQL Server in my C++ project.
So I want to insert/update my database and I wrote some queries (see the code) and I'm trying to execute my connection or command.
But it goes on an error at pConnection->Execute(InsertQuery, NULL, adCmdUnspecified);, it says Microsoft C++ exception: _com_error at memory location and in the debug window there is _hr with value _hr : DB_E_ERRORSINCOMMAND One or more errors occurred during processing of command. TYPE: HRESULT
I also tried to execute Command, but I have the same result as Connection.
Should I change adCmdUnspecified into something or am I go wrong somewhere?
What is the solution? Thank you in advance.
//connections above
VARIANT vNameStringType;
_bstr_t InsertQuery(L"Insert Into TestTB(AccountID, Name) Values(#AccountID, #Name)");
hr = pCommand.CreateInstance(__uuidof(Command));
pCommand->ActiveConnection = pConnection;
pCommand->CommandText = InsertQuery;
pCommand->CommandType = adCmdText;
for (int i = 0; i < size; i++)
{
a[i].name;
a[i].login;
vIntegerType.vt = VT_I4;
vIntegerType.intVal = a[i].login;
vNameStringType.vt = VT_BSTR;
vNameStringType.bstrVal = _bstr_t(a[i].name);
int DataExistCounter = 0;
NameParam = pCommand->CreateParameter(_bstr_t("#Name"), adVarChar, adParamInput, 150, _bstr_t(vNameStringType));
pCommand->Parameters->Append(NameParam);
AccIDParam = pCommand->CreateParameter("#AccountID", adInteger, adParamInput, sizeof(int), vIntegerType);
pCommand->Parameters->Append(AccIDParam);
pRecordset->MoveFirst();
while (!pRecordset->EndOfFile)
{
valFieldNam = pRecordset->Fields->GetItem("Name")->Value;
valFieldAcc = pRecordset->Fields->GetItem("AccountID")->Value;
if (valFieldAcc == a[i].login)
{
DataExistCounter++;
}
pRecordset->MoveNext();
}
if (DataExistCounter > 0)
{
//update
}
else
{
pConnection->Execute(InsertQuery, NULL, adCmdUnspecified);
}
}
pRecordset->Close();
pConnection->Close();
CoUninitialize();
Related
I have the following code in my COM Add-In for MS Office to go through all hyperlinks in winword document and then parse them:
...
HRESULT hr;
ULONG nRet;
CComQIPtr<MSWORD::Hyperlinks> hylinks = doc->Hyperlinks; // CComQIPtr<_Document> doc
ATLASSERT(hylinks);
IEnumVARIANTPtr pEnum = hylinks->Get_NewEnum();
for (int i = 1; i <= hylinks->Count; i++)
{
VARIANT v = {};
hr = pEnum->Next(1, &v, &nRet);
if (FAILED(hr)) continue;
CComQIPtr<MSWORD::Hyperlink> link;
ATLASSERT(link);
hr = hylinks->raw_Item(&v, &link);
if (FAILED(hr)) continue;
...
// parse hyperlink's address
}
...
The result (hr) when raw_Item() is called, is 80020005 (DISP_E_TYPEMISMATCH)). And there is no trouble with code like this one when I go through Shapes.
Does anyone can help me?
Finally, found out. How many collections have office application, so many ways to iterate them. Here we can do it like following, assign index of type VARIANT manually, not with enumerator:
CComQIPtr<MSWORD::Hyperlinks> hylinks = doc->Hyperlinks; // CComQIPtr<_Document> doc
ATLASSERT(hylinks);
for (int i = 1; i <= hylinks->Count; i++)
{
VARIANT ind;
ind.iVal = i;
ind.vt = VT_I2;
CComQIPtr<MSWORD::Hyperlink> link;
ATLASSERT(link);
link = hylinks->Item(&ind);
// do your magic
}
I'm using the OLE DB bulk copy operation against a SQL Server database but I'm having trouble while loading data into bit columns - they are always populated with true!
I created a simple reproduction program from Microsoft's sample code with the snippet that I adjusted below. My program includes a little SQL script to create the destination table. I had to download and install the x64 version of the SQL Server OLE DB driver to build this.
// Set up custom bindings.
oneBinding.dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
oneBinding.iOrdinal = 1;
oneBinding.pTypeInfo = NULL;
oneBinding.obValue = ulOffset + offsetof(COLUMNDATA, bData);
oneBinding.obLength = ulOffset + offsetof(COLUMNDATA, dwLength);
oneBinding.obStatus = ulOffset + offsetof(COLUMNDATA, dwStatus);
oneBinding.cbMaxLen = 1; // Size of varchar column.
oneBinding.pTypeInfo = NULL;
oneBinding.pObject = NULL;
oneBinding.pBindExt = NULL;
oneBinding.dwFlags = 0;
oneBinding.eParamIO = DBPARAMIO_NOTPARAM;
oneBinding.dwMemOwner = DBMEMOWNER_CLIENTOWNED;
oneBinding.bPrecision = 0;
oneBinding.bScale = 0;
oneBinding.wType = DBTYPE_BOOL;
ulOffset = oneBinding.cbMaxLen + offsetof(COLUMNDATA, bData);
ulOffset = ROUND_UP(ulOffset, COLUMN_ALIGNVAL);
if (FAILED(hr =
pIFastLoad->QueryInterface(IID_IAccessor, (void**)&pIAccessor)))
return hr;
if (FAILED(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
1,
&oneBinding,
ulOffset,
&hAccessor,
&oneStatus)))
return hr;
// Set up memory buffer.
pData = new BYTE[40];
if (!(pData /* = new BYTE[40]*/)) {
hr = E_FAIL;
goto cleanup;
}
pcolData = (COLUMNDATA*)pData;
pcolData->dwLength = 1;
pcolData->dwStatus = 0;
for (i = 0; i < 10; i++)
{
if (i % 2 == 0)
{
pcolData->bData[0] = 0x00;
}
else
{
pcolData->bData[0] = 0xFF;
}
if (FAILED(hr = pIFastLoad->InsertRow(hAccessor, pData)))
goto cleanup;
}
It's entirely likely that I'm putting the wrong value into the buffer, or have some other constant value incorrect. I did find an article describing the safety of various data type conversions and it looks like byte to bool is safe... but how would the buffer know what kind of data I'm putting in there if it's just a byte array?
Figured this out, I had not correctly switched over the demo from loading strings to fixed-width values. For strings, the data blob gets a 1-width pointer to the value whereas fixed-width values get the actual data.
So my COLUMNDATA struct now looks like this:
// How to lay out each column in memory.
struct COLUMNDATA {
DBLENGTH dwLength; // Length of data (not space allocated).
DWORD dwStatus; // Status of column.
VARIANT_BOOL bData; // Value, or if a string, a pointer to the value.
};
With the relevant length fix here:
pcolData = (COLUMNDATA*)pData;
pcolData->dwLength = sizeof(VARIANT_BOOL); // using a short.. make it two
pcolData->dwStatus = DBSTATUS_S_OK; // Indicates that the data value is to be used, not null
And the little value-setting for loop looks like this:
for (i = 0; i < 10; i++)
{
if (i % 2 == 0)
{
pcolData->bData = VARIANT_TRUE;
}
else
{
pcolData->bData = VARIANT_FALSE;
}
if (FAILED(hr = pIFastLoad->InsertRow(hAccessor, pData)))
goto cleanup;
}
I've updated the repository with the working code. I was inspired to make this change after reading the documentation for the obValue property.
Sometimes I get quite strange error message from SQLExecute() during INSERT. Have no idea how I can deal with this, other queries are ok.
Log
[ODBC][67383][1485443238.457802][SQLPrepare.c][196]
Entry:
Statement = 0x101022600
SQL = [INSERT INTO Core_Message(channel_id, date, member_id, reply_id) VALUES(25, '2017-01-26 18:07:18', 4, NULL)
][length = 109 (SQL_NTS)]
[ODBC][67383][1485443238.457893][SQLPrepare.c][377]
Exit:[SQL_SUCCESS]
[ODBC][67383][1485443238.458014][SQLExecute.c][187]
Entry:
Statement = 0x101022600
[ODBC][67383][1485443238.458189][SQLExecute.c][357]
Exit:[SQL_ERROR]
DIAG [HY000] no error information;
Error while preparing parameters
[ODBC][67383][1485443238.458543][SQLFreeHandle.c][381]
Entry:
Handle Type = 3
Input Handle = 0x101022600
[ODBC][67383][1485443238.458670][SQLFreeHandle.c][494]
Exit:[SQL_SUCCESS]
Code
SQLLEN length(0);
if (!isSuccess(SQLPrepare(_statement, (unsigned char *)query.c_str(), SQL_NTS))) {
_status = StatementStatus::Fault;
return false;
}
for (std::size_t i=0; i<reference_vector.size(); i++) {
length = reference_vector.at(i).get().length();
if (!isSuccess(SQLBindParameter(_statement, i + 1, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, reference_vector.at(i).get().length(), 0, (char *)reference_vector.at(i).get().c_str(), (SQLLEN)reference_vector.at(i).get().length(), &length))) {
_status = StatementStatus::Fault;
return false;
}
}
if (!isSuccess(SQLExecute(_statement))) {
_status = StatementStatus::Fault;
return false;
}
Tricky block with SQLBindParameter() event don't used in runtime.
Thanks in advance.
I have an application that tries to verify the mmc.exe (services) signature. (the context of the application I think is irrelevant) I am trying with winapi function which both fails with
WinVerifyTrust. I get TRUST_E_BAD_DIGEST when I am trying with verification from catalog, and
TRUST_E_NOSIGNATURE when trying from file info. it is very important to mention that my function succeeds on win7, XP but fails on win8.
this is the code snippet for the function
CATALOG_INFO InfoStruct = {0};
InfoStruct.cbStruct = sizeof(CATALOG_INFO);
WINTRUST_CATALOG_INFO WintrustCatalogStructure = {0};
WintrustCatalogStructure.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
WINTRUST_FILE_INFO WintrustFileStructure = {0};
WintrustFileStructure.cbStruct = sizeof(WINTRUST_FILE_INFO);
GUID ActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
//Get a context for signature verification.
HCATADMIN Context = NULL;
if(!::CryptCATAdminAcquireContext(&Context, NULL, 0) ){
return false;
}
//Open file.
cx_handle hFile(::CreateFileW(filename_.c_str(), GENERIC_READ, 7, NULL, OPEN_EXISTING, 0, NULL));
if( INVALID_HANDLE_VALUE == (HANDLE)hFile )
{
CryptCATAdminReleaseContext(Context, 0);
return false;
}
//Get the size we need for our hash.
DWORD HashSize = 0;
::CryptCATAdminCalcHashFromFileHandle(hFile, &HashSize, NULL, 0);
if( HashSize == 0 )
{
//0-sized has means error!
::CryptCATAdminReleaseContext(Context, 0);
return false;
}
//Allocate memory.
buffer hashbuf(HashSize);
//Actually calculate the hash
if( !CryptCATAdminCalcHashFromFileHandle(hFile, &HashSize, hashbuf.data, 0) )
{
CryptCATAdminReleaseContext(Context, 0);
return false;
}
//Convert the hash to a string.
buffer MemberTag(((HashSize * 2) + 1) * sizeof(wchar_t));
for( unsigned int i = 0; i < HashSize; i++ ){
swprintf(&((PWCHAR)MemberTag.data)[i * 2], L"%02X", hashbuf.data[i ]);
}
//Get catalog for our context.
HCATINFO CatalogContext = CryptCATAdminEnumCatalogFromHash(Context, hashbuf, HashSize, 0, NULL);
if ( CatalogContext )
{
//If we couldn't get information
if ( !CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0) )
{
//Release the context and set the context to null so it gets picked up below.
CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
CatalogContext = NULL;
}
}
//If we have a valid context, we got our info.
//Otherwise, we attempt to verify the internal signature.
WINTRUST_DATA WintrustStructure = {0};
WintrustStructure.cbStruct = sizeof(WINTRUST_DATA);
if( !CatalogContext )
{
load_signature_verification_from_file_info(WintrustFileStructure, WintrustStructure);
}
else
{
load_signature_verification_from_catalog(WintrustStructure, WintrustCatalogStructure, InfoStruct, MemberTag);
}
//Call our verification function.
long verification_res = ::WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
//Check return.
bool is_success = SUCCEEDED(verification_res) ? true : false;
// if failed with CatalogContext, try with FILE_INFO
if(!is_success && CatalogContext && verification_res != TRUST_E_NOSIGNATURE)
{
//warning2(L"Failed verification with Catalog Context: 0x%x %s ; Retrying with FILE_INFO.", verification_res, (const wchar_t*)format_last_error(verification_res));
load_signature_verification_from_file_info(WintrustFileStructure, WintrustStructure);
verification_res = ::WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
is_success = SUCCEEDED(verification_res) ? true : false;
}
if(perr && !is_success && verification_res != TRUST_E_NOSIGNATURE)
{
perr->code = verification_res;
perr->description = format_last_error(verification_res);
}
//Free context.
if( CatalogContext ){
::CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
}
//If we successfully verified, we need to free.
if( is_success )
{
WintrustStructure.dwStateAction = WTD_STATEACTION_CLOSE;
::WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
}
::CryptCATAdminReleaseContext(Context, 0);
return is_success;
I don't think any thing had changed in this function from win7 to win 8 so what could possibly go wrong?
UPDATE
I did notice that my function does work for task manager at win 8.
but again for the mmc it does not work.
It appears that your general approach is correct and the functions themselves haven't changed. However there are subtle changes; namely the data on which they operate has changed. The hashes stored for files on Windows 8, according to comments on CryptCATAdminCalcHashFromFileHandle, are calculated using SHA-256 hashes.
The SHA-256 hashing algorithm is not supported by CryptCATAdminCalcHashFromFileHandle, so you must update the code to use CryptCATAdminAcquireContext2 and CryptCATAdminCalcHashFromFileHandle2 on Windows 8; the former allows you to acquire a HCATADMIN with a specified hash algorithm, and the latter allows using that HCATADMIN.
(Interestingly, WINTRUST_CATALOG_INFO also points this direction with its HCATADMIN hCatAdmin member, documented as "Windows 8 and Windows Server 2012: Support for this member begins.")
I want to implement port-forwarding using intel-upnp.
I got XML data like:
Device found at location: http://192.168.10.1:49152/gatedesc.xml
service urn:schemas-upnp-org:service:WANIPConnection:1
controlurl /upnp/control/WANIPConn1
eventsuburl : /upnp/control/WANIPConn1
scpdurl : /gateconnSCPD.xml
And now, I want to make upnp-action. But, I don't know how to make it.
If you know some code snippet or helpful URL in C, please tell me.
char actionxml[250];
IXML_Document *action = NULL;
strcpy(actionxml, "<u:GetConnectionTypeInfo xmlns:u=\"urn:schemas-upnp- org:service:WANCommonInterfaceConfig:1\">");
action = ixmlParseBuffer(actionxml);
int ret = UpnpSendActionAsync( g_handle,
"http:192.168.10.1:49152/upnp/control/WANCommonIFC1",
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",
NULL,
action,
upnp_callback,
NULL);
I know this is an old question, but it can be kept for reference. You can take a look at the sample code in the libupnp library here: https://github.com/mrjimenez/pupnp/blob/master/upnp/sample/common/tv_ctrlpt.c
The relevant code is in the function TvCtrlPointSendAction():
int TvCtrlPointSendAction(
int service,
int devnum,
const char *actionname,
const char **param_name,
char **param_val,
int param_count)
{
struct TvDeviceNode *devnode;
IXML_Document *actionNode = NULL;
int rc = TV_SUCCESS;
int param;
ithread_mutex_lock(&DeviceListMutex);
rc = TvCtrlPointGetDevice(devnum, &devnode);
if (TV_SUCCESS == rc) {
if (0 == param_count) {
actionNode =
UpnpMakeAction(actionname, TvServiceType[service],
0, NULL);
} else {
for (param = 0; param < param_count; param++) {
if (UpnpAddToAction
(&actionNode, actionname,
TvServiceType[service], param_name[param],
param_val[param]) != UPNP_E_SUCCESS) {
SampleUtil_Print
("ERROR: TvCtrlPointSendAction: Trying to add action param\n");
/*return -1; // TBD - BAD! leaves mutex locked */
}
}
}
rc = UpnpSendActionAsync(ctrlpt_handle,
devnode->device.
TvService[service].ControlURL,
TvServiceType[service], NULL,
actionNode,
TvCtrlPointCallbackEventHandler, NULL);
if (rc != UPNP_E_SUCCESS) {
SampleUtil_Print("Error in UpnpSendActionAsync -- %d\n",
rc);
rc = TV_ERROR;
}
}
ithread_mutex_unlock(&DeviceListMutex);
if (actionNode)
ixmlDocument_free(actionNode);
return rc;
}
The explanation is that you should create the action with UpnpMakeAction() if you have no parameters or UpnpAddToAction() if you have parameters to create your action, and then send it either synchronously or asynchronously.