Hi I have written some code for calling a stored procedure in a MySQL database using a MariaDB client, however the stmt->bind parameter is not being populated with the necessary MYSQL_BIND array for receiving the necessary data.
Am I doing something wrong or is there a bug with the driver? Malloc'ing the data does not break the implementation, but MySQL has its own more efficient means of managing memory for these arrays than malloc.
If you are asking, I am using and abusing a switch statement, as I would like this function to be made eventually asynchronous in a cooroutine functor class working against a pool of connections, where a state value is used to control where we are in the switch statement.
//the function that does all the heavy lifting for persistence
xt::data::io::ret_val mysql_model::call_stored_proc(xt::data::model_factory& factory,
const xt::object& obj,
const xt::object* p_prev_obj,
xt::data::io_call_back*& cb,
const char* command)
{
MYSQL *mysql = NULL;
int state = 0;
MYSQL_STMT* stmt = NULL;
int status = 0;
size_t parameter_length = 0;
std::vector<MYSQL_BIND> ps_params;
xt::data::io::ret_val ret = xt::data::io::io_success;
xt::string sql("CALL ");
xt::messaging::event_type type = xt::messaging::new_object;
if(std::strcmp(command, "update") == 0)
{
sql += m_update_proc;
type = xt::messaging::update_object;
}
else if(std::strcmp(command, "delete") == 0)
{
sql += m_delete_proc;
type = xt::messaging::delete_object;
}
else
{
sql += m_insert_proc;
assert(command == "insert");
}
sql += "(?";
for(size_t i = 0;i < m_p_mem_row_set->get_field_handlers().size();i++)
{
sql += ",?";
}
sql += ")";
switch(state)
{
case 0:
mysql= mysql_init(NULL);
if(!mysql_set_server_option(mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON))
{
show_error(mysql);
return xt::data::io::io_exception;
}
if (!mysql_real_connect(mysql, m_server.data(),
m_user_name.data(),
m_password.data(),
m_schema.data(),
0,
NULL,
0))
{
LOG_ERROR3("Could not connect error(%s) [%s] \"%s\"", xt::longToString(mysql_errno(mysql)), mysql_sqlstate(mysql), mysql_error(mysql));
ret = xt::data::io::io_exception;
break;
}
stmt = mysql_stmt_init(mysql);
if(!stmt)
{
LOG_ERROR("Could not initialize statement\n");
ret = xt::data::io::io_exception;
break;
}
stmt->bind = NULL;
if(mysql_stmt_prepare(stmt, sql.data(), (unsigned long)sql.size()))
{
LOG_ERROR3("Could not prepare statement error(%s) [%s] \"%s\"", xt::longToString(mysql_errno(mysql)), mysql_sqlstate(mysql), mysql_error(mysql));
ret = xt::data::io::io_exception;
break;
}
parameter_length = m_p_mem_row_set->get_field_handlers().size() + 2;
ps_params.resize(parameter_length);
{
xt::data::io::ret_val r = prepare_memset(ps_params, m_p_mem_row_set->get_field_handlers(), obj, command);
if(r != xt::data::io::io_success)
{
ret = xt::data::io::io_exception;
break;
}
}
//reuse params so offset from 1
if(mysql_stmt_bind_param(stmt, &ps_params[1]))
{
LOG_ERROR2("Could not bind parameters error: %s (errno: %s)\n", mysql_stmt_error(stmt), xt::longToString(mysql_stmt_errno(stmt)));
ret = xt::data::io::io_exception;
break;
}
status = mysql_stmt_execute(stmt);
if(status)
{
LOG_ERROR2("Could not execute stored procedure error: %s (errno: %s)\n", mysql_stmt_error(stmt), xt::longToString(mysql_stmt_errno(stmt)));
ret = xt::data::io::io_exception;
break;
}
{
/* the column count is > 0 if there is a result set */
/* 0 if the result is only the final status packet */
int num_fields = mysql_stmt_field_count(stmt);
if (num_fields > 0)
{
if(num_fields != parameter_length)
{
LOG_ERROR("parameter fields do not match returned resultset");
ret = xt::data::io::io_exception;
break;
}
//buffer to be a write target
for(size_t i = 0;i < parameter_length;i++)
{
if(ps_params[i].buffer_type == MYSQL_TYPE_STRING || ps_params[i].buffer_type == MYSQL_TYPE_DECIMAL)
{
ps_params[i].buffer = (char *) new char[ps_params[i].buffer_length + 1];
memset(ps_params[i].buffer, 0, ps_params[i].buffer_length + 1);
ps_params[i].length = new unsigned long;
*ps_params[i].length = ps_params[i].buffer_length;
}
}
#pragma message("hack!!!!! bind not being allocated for stored proc")
if (!(stmt->bind= (MYSQL_BIND *)malloc(stmt->field_count * sizeof(MYSQL_BIND))))
{
// SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
LOG_ERROR("Out of memory");
ret = xt::data::io::io_exception;
break;
}
status = mysql_stmt_bind_result(stmt, &ps_params[0]);
if(status)
{
LOG_ERROR2("Could not bind results error: %s (errno: %s)\n", mysql_stmt_error(stmt), xt::longToString(mysql_stmt_errno(stmt)));
ret = xt::data::io::io_exception;
break;
}
status = mysql_stmt_fetch(stmt);
if (status == 1 || status == MYSQL_NO_DATA)
{
LOG_ERROR("No data returned from stored proc");
ret = xt::data::io::io_exception;
break;
}
else if(status)
{
LOG_ERROR2("Error on fetching results error: %s (errno: %s)\n", mysql_stmt_error(stmt), xt::longToString(mysql_stmt_errno(stmt)));
ret = xt::data::io::io_exception;
break;
}
else
{
ret = (xt::data::io::ret_val) *((int *) ps_params[0].buffer);
if(ret != xt::data::io::io_success)
{
const char* error_message = ((char *) ps_params[1].buffer);
LOG_ERROR(error_message);
// dont break; we want to clean memory up regardless
}
//now clean up memory
delete ps_params[1].length;
ps_params[1].length = NULL;
delete [] ps_params[1].buffer;
ps_params[1].buffer = NULL;
for (int i = 2; i < parameter_length && ret == xt::data::io::io_success; ++i)
{
rowset_item* item = m_p_mem_row_set->get_field_handlers()[i - 2];
switch (ps_params[i].buffer_type)
{
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_DECIMAL:
if(ret == xt::data::io::io_success)
{
((rowset_item_string_t<char>&)*item).set_data(static_cast<char*>(ps_params[i].buffer), const_cast<xt::object*>(&obj), 0);
}
delete ps_params[i].length;
ps_params[i].length = NULL;
delete [] ps_params[i].buffer;
ps_params[i].buffer = NULL;
break;
case MYSQL_TYPE_DATE:
delete (DATE_STRUCT*)ps_params[i].buffer;
ps_params[i].buffer = NULL;
break;
case MYSQL_TYPE_TIME:
delete (TIME_STRUCT*)ps_params[i].buffer;
ps_params[i].buffer = NULL;
break;
case MYSQL_TYPE_TIMESTAMP:
delete (TIMESTAMP_STRUCT*)ps_params[i].buffer;
ps_params[i].buffer = NULL;
break;
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_BIT:
break;
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
default:
LOG_ERROR1("unexpected type (%s)",xt::longToString(ps_params[i].buffer_type));
assert(false);
ret = xt::data::io::io_exception;
break;
}
}
}
}
else
{
LOG_ERROR("no data returned from stored proc");
assert(false);
ret = xt::data::io::io_exception;
break;
}
}
default:
break;
}
if(stmt != NULL)
{
free(stmt->bind);
mysql_stmt_close(stmt);
}
if(mysql != NULL)
{
mysql_close(mysql);
}
cb->on_model_request_complete( ret,
type,
factory,
*this,
obj,
p_prev_obj,
true);
cb = NULL;
return ret;
}
Related
There is a minifilter driver that should hide files, when there is only one file in the folder, for some reason it does not hide it, in other cases everything works correctly.
template <typename InfoType>
NTSTATUS hf(PVOID buff, UNICODE_STRING filePath)
{
if (buff == NULL)
{
DbgPrint("BUFF IS NULL\n");
return STATUS_SUCCESS;
}
//InfoType* DirBuff = (InfoType*)buff;
InfoType* nextInfo = NULL;
InfoType* prevInfo = NULL;
InfoType* info = (InfoType*)(buff);
UNICODE_STRING fileName, fullFileName;
UINT32 offset, moveLength;
BOOLEAN search=true;
NTSTATUS status = STATUS_SUCCESS;
offset = 0;
do
{
fileName.Buffer = info->FileName;
fileName.Length = (USHORT)info->FileNameLength;
fileName.MaximumLength = (USHORT)info->FileNameLength;
UNICODE_STRING sl;
if (!compareNames(filePath.Buffer, L"*:\\")) {
sl.Buffer = L"\\";
sl.Length = 2;
sl.MaximumLength = 2;
}
else
{
sl.Buffer = L"";
sl.Length = 0;
sl.MaximumLength = 0;
}
fullFileName.Buffer = (PWCH)ExAllocatePoolWithTag(PagedPool, filePath.MaximumLength + sl.MaximumLength + fileName.MaximumLength + 2, ALLOCATION_TAG);
if (fullFileName.Buffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
fullFileName.MaximumLength = sl.MaximumLength + fileName.MaximumLength + filePath.MaximumLength + 2;
fullFileName.Length = sl.MaximumLength + fileName.MaximumLength + filePath.Length + 2;
RtlCopyUnicodeString(&fullFileName, &filePath);
RtlAppendUnicodeStringToString(&fullFileName, &sl);
RtlAppendUnicodeStringToString(&fullFileName, &fileName);
if (isInList(masks, fileName) || isInList(masks, fullFileName))
{
BOOLEAN retn = FALSE;
if (prevInfo != NULL)
{
if (info->NextEntryOffset != 0)
{
prevInfo->NextEntryOffset += info->NextEntryOffset;
offset = info->NextEntryOffset;
}
else
{
prevInfo->NextEntryOffset = 0;
status = STATUS_SUCCESS;
retn = TRUE;
}
RtlFillMemory(info, sizeof(InfoType), 0);
}
else
{
if (info->NextEntryOffset != 0)
{
nextInfo = (InfoType*)((PUCHAR)info + info->NextEntryOffset);
moveLength = 0;
while (nextInfo->NextEntryOffset != 0)
{
moveLength += nextInfo->NextEntryOffset;
nextInfo = (InfoType*)((PUCHAR)nextInfo + nextInfo->NextEntryOffset);
}
moveLength += FIELD_OFFSET(InfoType, FileName) + nextInfo->FileNameLength;
RtlMoveMemory(info, (PUCHAR)info + info->NextEntryOffset, moveLength);//continue
}
else
{
status = STATUS_NO_MORE_ENTRIES;
retn = TRUE;
RtlFillMemory(info, sizeof(InfoType), 0);
DbgPrint("%wZ", fileName);
}
}
if (retn)
return status;
info = (InfoType*)((PCHAR)info + offset);
continue;
}
offset = info->NextEntryOffset;
prevInfo = info;
info = (InfoType*)((PCHAR)info + offset);
if (offset == 0)
return STATUS_SUCCESS;
} while (search);
ExFreePoolWithTag(fullFileName.Buffer, ALLOCATION_TAG);
return STATUS_SUCCESS;
}
Here it is called:
FLT_POSTOP_CALLBACK_STATUS
PostDirectoryControlCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
{
PFLT_PARAMETERS params = &Data->Iopb->Parameters;
NTSTATUS status = STATUS_SUCCESS;
POBJECT_NAME_INFORMATION fileinf;
if (!NT_SUCCESS(IoQueryFileDosDeviceName(FltObjects->FileObject, &fileinf)))
{
return FLT_POSTOP_FINISHED_PROCESSING;
}
if (!NT_SUCCESS(Data->IoStatus.Status) || !active)
return FLT_POSTOP_FINISHED_PROCESSING;
switch (params->DirectoryControl.QueryDirectory.FileInformationClass)
{
case FileDirectoryInformation:
status=HideFile<FILE_DIRECTORY_INFORMATION>(params->DirectoryControl.QueryDirectory.DirectoryBuffer, fileinf->Name);
break;
case FileFullDirectoryInformation:
status=HideFile<FILE_FULL_DIR_INFORMATION>(params->DirectoryControl.QueryDirectory.DirectoryBuffer, fileinf->Name);
break;
case FileBothDirectoryInformation:
status=HideFile<FILE_BOTH_DIR_INFORMATION>(params->DirectoryControl.QueryDirectory.DirectoryBuffer, fileinf->Name);
break;
case FileNamesInformation:
status= HideFile<FILE_NAMES_INFORMATION>(params->DirectoryControl.QueryDirectory.DirectoryBuffer, fileinf->Name);
break;
case FileIdBothDirectoryInformation: // Used by Vista and later explorer
status= hf<FILE_ID_BOTH_DIR_INFORMATION>(params->DirectoryControl.QueryDirectory.DirectoryBuffer, fileinf->Name);
break;
case FileIdFullDirectoryInformation: // Used by Vista and later explorer
status= HideFile<FILE_ID_FULL_DIR_INFORMATION>(params->DirectoryControl.QueryDirectory.DirectoryBuffer, fileinf->Name);
break;
default:break;
}
Data->IoStatus.Status = status;
ExFreePool(fileinf);
return FLT_POSTOP_FINISHED_PROCESSING;
}
These are the callbacks that are used (it is used in IRP_MJ_DIRECTORY_CONTROL)
CONST FLT_OPERATION_REGISTRATION g_callbacks[] =
{
{
IRP_MJ_CREATE,
0,
PreOperationCreate,
PostOperationCreate
},
{ IRP_MJ_DIRECTORY_CONTROL,
0,
PreDirectoryControlCallback,
PostDirectoryControlCallback },
{ IRP_MJ_OPERATION_END }
};
The error in my opinion is in this place.For some reason, it does not completely reset the buffer.But I may be wrong and the error may be elsewhere
else
{
status = STATUS_NO_MORE_ENTRIES;
retn = TRUE;
RtlFillMemory(info, sizeof(InfoType), 0);
DbgPrint("%wZ", fileName);
}
Tell me what I'm doing wrong, and how to fix it so that it hides all the files. The hf and HideFile functions are the same, I just use hf to find the error
For example, my computer has two monitors, the primary monitor's resolution is 800*600, the other monitor's resolution is 1600*900.
I would like define the resolution on one monitor only ?
The function 'SetDisplayConfig' change the resolution screen on the two minotors...
https://learn.microsoft.com/fr-fr/windows-hardware/drivers/display/ccd-apis
https://learn.microsoft.com/fr-fr/windows/win32/api/winuser/nf-winuser-setdisplayconfig
[DllImport("User32.dll")]
public static extern int SetDisplayConfig(
uint numPathArrayElements,
[In] DisplayConfigPathInfo[] pathArray,
uint numModeInfoArrayElements,
[In] DisplayConfigModeInfo[] modeInfoArray,
SdcFlags flags
);
private static Boolean SetDisplaySettings(int Id_Monitor, uint Width, uint Height, uint Scaling)
{
try
{
CCDWrapper.DisplayConfigPathInfo[] pathInfoArray = new CCDWrapper.DisplayConfigPathInfo[0] { };
CCDWrapper.DisplayConfigModeInfo[] modeInfoArray = new CCDWrapper.DisplayConfigModeInfo[0] { };
CCDWrapper.MonitorAdditionalInfo[] additionalInfo = new CCDWrapper.MonitorAdditionalInfo[0] { };
bool Status = GetDisplaySettings(ref pathInfoArray, ref modeInfoArray, ref additionalInfo, true);
CCDWrapper.DisplayConfigPathInfo[] pathInfoArrayCurrent = new CCDWrapper.DisplayConfigPathInfo[0] { };
CCDWrapper.DisplayConfigModeInfo[] modeInfoArrayCurrent = new CCDWrapper.DisplayConfigModeInfo[0] { };
CCDWrapper.MonitorAdditionalInfo[] additionalInfoCurrent = new CCDWrapper.MonitorAdditionalInfo[0] { };
bool StatusCurrent = GetDisplaySettings(ref pathInfoArrayCurrent, ref modeInfoArrayCurrent, ref additionalInfoCurrent, false);
if (StatusCurrent)
{
for (int iPathInfo = 0; iPathInfo <= pathInfoArray.Length-1; iPathInfo++)
//for (int iPathInfo = 0; iPathInfo <= pathInfoArray.Length - 1; iPathInfo++)
{
for (int iPathInfoCurrent = 0; iPathInfoCurrent <= pathInfoArrayCurrent.Length - 1; iPathInfoCurrent++)
{
if ((pathInfoArray[iPathInfo].sourceInfo.id == pathInfoArrayCurrent[iPathInfoCurrent].sourceInfo.id) && (pathInfoArray[iPathInfo].targetInfo.id == pathInfoArrayCurrent[iPathInfoCurrent].targetInfo.id))
{
pathInfoArray[iPathInfo].sourceInfo.adapterId.LowPart = pathInfoArrayCurrent[iPathInfoCurrent].sourceInfo.adapterId.LowPart;
pathInfoArray[iPathInfo].targetInfo.adapterId.LowPart = pathInfoArrayCurrent[iPathInfoCurrent].targetInfo.adapterId.LowPart;
pathInfoArray[iPathInfo].targetInfo.scaling = (CCDWrapper.DisplayConfigScaling)Scaling;
break;
}
}
}
for (int iModeInfo = 0; iModeInfo <= modeInfoArray.Length - 1; iModeInfo++)
{
for (int iPathInfo = 0; iPathInfo <= pathInfoArray.Length - 1; iPathInfo++)
{
if ((modeInfoArray[iModeInfo].id == pathInfoArray[iPathInfo].targetInfo.id) && (modeInfoArray[iModeInfo].infoType == CCDWrapper.DisplayConfigModeInfoType.Target))
{
for (int iModeInfoSource = 0; iModeInfoSource <= modeInfoArray.Length - 1; iModeInfoSource++)
{
if ((modeInfoArray[iModeInfoSource].id == pathInfoArray[iPathInfo].sourceInfo.id) && (modeInfoArray[iModeInfoSource].adapterId.LowPart == modeInfoArray[iModeInfo].adapterId.LowPart) && (modeInfoArray[iModeInfoSource].infoType == CCDWrapper.DisplayConfigModeInfoType.Source))
{
modeInfoArray[iModeInfoSource].adapterId.LowPart = pathInfoArray[iPathInfo].sourceInfo.adapterId.LowPart;
modeInfoArray[iModeInfoSource].sourceMode.height = Height;
modeInfoArray[iModeInfoSource].sourceMode.width = Width;
break;
}
}
modeInfoArray[iModeInfo].adapterId.LowPart = pathInfoArray[iPathInfo].targetInfo.adapterId.LowPart;
break;
}
}
}
uint numPathArrayElements = System.Convert.ToUInt32(pathInfoArray.Length);
uint numModeInfoArrayElements = System.Convert.ToUInt32(modeInfoArray.Length);
long Result = CCDWrapper.SetDisplayConfig(numPathArrayElements, pathInfoArray, numModeInfoArrayElements, modeInfoArray, CCDWrapper.SdcFlags.Apply | CCDWrapper.SdcFlags.UseSuppliedDisplayConfig | CCDWrapper.SdcFlags.SaveToDatabase | CCDWrapper.SdcFlags.NoOptimization | CCDWrapper.SdcFlags.AllowChanges);
if (Result == 0)
return true;
else
return false;
}
else
return false;
}
catch (Exception ex)
{
EventLog.WriteEntry("ResolutionEcran", "Erreur SetDisplaySettings : " + ex.Message, EventLogEntryType.Error);
return false;
}
}
private static Boolean GetDisplaySettings(ref CCDWrapper.DisplayConfigPathInfo[] pathInfoArray, ref CCDWrapper.DisplayConfigModeInfo[] modeInfoArray, ref CCDWrapper.MonitorAdditionalInfo[] additionalInfo, Boolean ActiveOnly, [System.Runtime.InteropServices.Optional] int ID_Monitor)
{
uint numPathArrayElements;
uint numModeInfoArrayElements;
CCDWrapper.QueryDisplayFlags queryFlags = CCDWrapper.QueryDisplayFlags.AllPaths;
if (ActiveOnly)
{
//queryFlags = CCDWrapper.QueryDisplayFlags.OnlyActivePaths;
queryFlags = CCDWrapper.QueryDisplayFlags.OnlyActivePaths;
}
var status = CCDWrapper.GetDisplayConfigBufferSizes(queryFlags, out numPathArrayElements, out numModeInfoArrayElements);
if (status == 0)
{
pathInfoArray = new CCDWrapper.DisplayConfigPathInfo[numPathArrayElements];
modeInfoArray = new CCDWrapper.DisplayConfigModeInfo[numModeInfoArrayElements];
additionalInfo = new CCDWrapper.MonitorAdditionalInfo[numModeInfoArrayElements];
status = CCDWrapper.QueryDisplayConfig(queryFlags, ref numPathArrayElements, pathInfoArray, ref numModeInfoArrayElements, modeInfoArray, IntPtr.Zero);
if (status == 0)
{
for (var iMode = 0; iMode < numModeInfoArrayElements; iMode++)
{
if (modeInfoArray[iMode].infoType == CCDWrapper.DisplayConfigModeInfoType.Target)
{
try
{
additionalInfo[iMode] = CCDWrapper.GetMonitorAdditionalInfo(modeInfoArray[iMode].adapterId, modeInfoArray[iMode].id);
}
catch (Exception)
{
additionalInfo[iMode].valid = false;
}
}
}
return true;
}
else
{
//Erreur : Querying display;
}
}
else
{
//Erreur : Taille Buffer;
}
return false;
}
Use ChangeDisplaySettingsEx function to change the settings of the specified display device to the specified graphics mode. The following is an example you can refer to.
#include <windows.h>
int main()
{
for (DWORD devNum = 0; ; devNum++)
{
DISPLAY_DEVICE dev = {0};
dev.cb = sizeof(DISPLAY_DEVICE);
if (!EnumDisplayDevices(NULL, devNum, &dev, EDD_GET_DEVICE_INTERFACE_NAME))
break;
wprintf(L"Display name: %s \n", dev.DeviceName);
DEVMODE dMode = { 0 };
dMode.dmSize = sizeof(dMode);
if (!EnumDisplaySettings(dev.DeviceName, ENUM_CURRENT_SETTINGS, &dMode))
{
wprintf(L"EnumDisplaySettings error: %d \n", GetLastError());
continue;
}
wprintf(L"Display old settings: \n");
wprintf(L"dmBitsPerPel: %d \n", dMode.dmBitsPerPel);
wprintf(L"dmPelsWidth: %d \n", dMode.dmPelsWidth);
wprintf(L"dmPelsHeight: %d \n", dMode.dmPelsHeight);
wprintf(L"dmDisplayFlags: %x \n", dMode.dmDisplayFlags);
wprintf(L"dmDisplayFrequency: %d \n", dMode.dmDisplayFrequency);
dMode.dmPelsWidth = 800;
dMode.dmPelsHeight = 600;
ChangeDisplaySettingsEx(dev.DeviceName, &dMode, NULL, 0, NULL);
DEVMODE dModeNew = { 0 };
dModeNew.dmSize = sizeof(DEVMODE);
if (!EnumDisplaySettings(dev.DeviceName, ENUM_CURRENT_SETTINGS, &dModeNew))
{
wprintf(L"EnumDisplaySettings error: %d \n", GetLastError());
continue;
}
wprintf(L"Display new settings: \n");
wprintf(L"dmBitsPerPel: %d \n", dModeNew.dmBitsPerPel);
wprintf(L"dmPelsWidth: %d \n", dModeNew.dmPelsWidth);
wprintf(L"dmPelsHeight: %d \n", dModeNew.dmPelsHeight);
wprintf(L"dmDisplayFlags: %x \n", dModeNew.dmDisplayFlags);
wprintf(L"dmDisplayFrequency: %d \n", dModeNew.dmDisplayFrequency);
}
getchar();
}
I set dwflags to 0 let the graphics mode for the current screen change dynamically. Refer to dwflags parameter part of ChangeDisplaySettingsEx's document for deciding how you would like the graphics mode should be changed.
Sorry for my late response...I was absent.
I also need to change the scaling of monitor (Black bars removed on certain resolutions).
[Flags]
public enum DisplayConfigScaling : uint
{
Zero = 0x0,
Identity = 1,
Centered = 2,
Stretched = 3,
Aspectratiocenteredmax = 4,
Custom = 5,
Preferred = 128,
ForceUint32 = 0xFFFFFFFF
}
The function 'ChangeDisplaySettingsEx' may change the scale of monitor ?
Thank you very for your help.
I thought it would be a good best practice to search thru my code for any references like ..
char buf[MAX_STRING_LENGTH];
... and replace them with ...
char buf[MAX_STRING_LENGTH] = {'\0'};
Doing a search in the code I have a number that are set to null (around 239) and others that are not (1,116).
When I replaced the remaining 1,116 instances with char buf[MAX_STRING_LENGTH] = {'\0'}; and pushed the code live the game was noticeably laggy.
Reverting the change removed the lag.
Can someone explain why setting these to null would cause the game to lag while running?
Example code setting to Null
void do_olist(Character *ch, char *argument, int cmd)
{
int header = 1;
int type = -1;
int wear_bit = -1;
int i = 0;
int inclusive;
int zone = -1;
int yes_key1 = 0;
int yes_key2 = 0;
int yes_key3 = 0;
int count = 0;
Object *obj;
bool found = false;
char key1 [MAX_STRING_LENGTH] = {'\0'};
char key2 [MAX_STRING_LENGTH] = {'\0'};
char key3 [MAX_STRING_LENGTH] = {'\0'};
char buf [MAX_STRING_LENGTH];
argument = one_argument(argument, buf);
if (!*buf)
{
ch->send("Selection Parameters:\n\n");
ch->send(" +/-<object keyword> Include/exclude object keyword.\n");
ch->send(" <zone> Objects from zone only.\n");
ch->send(" <item-type> Include items of item-type.\n");
ch->send(" <wear-bits> Include items of wear type.\n");
ch->send("\nExample: olist +sword -rusty weapon 10\n");
ch->send("will only get non-rusty swords of type weapon from zone 10.\n");
return;
}
while (*buf)
{
inclusive = 1;
if (strlen(buf) > 1 && isalpha(*buf) &&
(type = index_lookup(item_types, buf)) != -1)
{
argument = one_argument(argument, buf);
continue;
}
if (strlen(buf) > 1 && isalpha(*buf) &&
(wear_bit = index_lookup(wear_bits, buf)) != -1)
{
argument = one_argument(argument, buf);
continue;
}
if (isdigit(*buf))
{
if ((zone = atoi(buf)) >= MAX_ZONE)
{
ch->send("Zone not in range 0..99\n");
return;
}
argument = one_argument(argument, buf);
continue;
}
switch (*buf)
{
case '-':
inclusive = 0;
case '+':
if (!buf [1])
{
ch->send("Expected keyname after 'k'.\n");
return;
}
if (!*key1)
{
yes_key1 = inclusive;
strcpy(key1, buf + 1);
}
else if (!*key2)
{
yes_key2 = inclusive;
strcpy(key2, buf + 1);
}
else if (*key3)
{
ch->send("Sorry, at most three keywords.\n");
return;
}
else
{
yes_key3 = inclusive;
strcpy(key3, buf + 1);
}
break;
case 'z':
argument = one_argument(argument, buf);
if (!isdigit(*buf) || atoi(buf) >= MAX_ZONE)
{
ch->send("Expected valid zone after 'z'.\n");
return;
}
zone = atoi(buf);
break;
}
argument = one_argument(argument, buf);
}
*b_buf = '\0';
for (obj = full_object_list; obj; obj = obj->lnext)
{
if (zone != -1 && obj->zone != zone)
continue;
if (type != -1 && obj->obj_flags.type_flag != type)
continue;
if (wear_bit != -1)
{
for (i = 0; (*wear_bits[i] != '\n'); i++)
{
if (IS_SET(obj->obj_flags.wear_flags, (1 << i)))
{
if (i != wear_bit)
continue;
else
found = true;
}
}
if (found)
found = false;
else
continue;
}
if (*key1)
{
if (yes_key1 && !strcasestr(const_cast<char*> (obj->getName().c_str()), key1))
continue;
else if (!yes_key1 && strcasestr(const_cast<char*> (obj->getName().c_str()), key1))
continue;
}
if (*key2)
{
if (yes_key2 && !strcasestr(const_cast<char*> (obj->getName().c_str()), key2))
continue;
else if (!yes_key2 && strcasestr(const_cast<char*> (obj->getName().c_str()), key2))
continue;
}
if (*key3)
{
if (yes_key3 && !strcasestr(const_cast<char*> (obj->getName().c_str()), key3))
continue;
else if (!yes_key3 && strcasestr(const_cast<char*> (obj->getName().c_str()), key3))
continue;
}
count++;
if (count < 200)
olist_show(obj, type, header);
header = 0;
}
if (count > 200)
{
sprintf(buf, "You have selected %d objects (too many to print all at once).\n",
count);
ch->send(buf);
//return;
}
else {
sprintf(buf, "You have selected %d objects.\n",
count);
ch->send(buf);
}
page_string(ch->desc, b_buf);
}
I took the advice to replace instances of ...
char buf[MAX_STRING_LENGTH] = {'\0'};
with ...
char buf[MAX_STRING_LENGTH]; *buf = 0;
Environment:
Ubuntu 16.04 (x64)
C++
ffmpeg
Use-case
Multiple MPEG-TS fragments are rapidly decoded ( numerous every sec )
The format of the TS fragments is dynamic and can't be known ahead of time
The first A/V frames of each fragment are needed to be extracted
Problem statement
The code bellow successfully decodes A/V, BUT, has a huge memory leak ( MBytes/sec )
According to the docs seems all memory is freed as it should ( does it... ? )
Why do I get this huge mem leak, what am I missing in the following code snap ?
struct MEDIA_TYPE {
ffmpeg::AVMediaType eType;
union {
struct {
ffmpeg::AVPixelFormat colorspace;
int width, height;
float fFPS;
} video;
struct : WAVEFORMATEX {
short sSampleFormat;
} audio;
} format;
};
struct FRAME {
enum { MAX_PALNES = 3 + 1 };
int iStrmId;
int64_t pts; // Duration in 90Khz clock resolution
uint8_t** ppData; // Null terminated
int32_t* pStride;// Zero terminated
};
HRESULT ProcessTS(IN Operation op, IN uint8_t* pTS, IN uint32_t uiBytes, bool(*cb)(IN const MEDIA_TYPE& mt, IN FRAME& frame, IN PVOID pCtx), IN PVOID pCbCtx)
{
uiBytes -= uiBytes % 188;// align to 188 packet size
struct CONTEXT {
uint8_t* pTS;
uint32_t uiBytes;
int32_t iPos;
} ctx = { pTS, uiBytes, 0 };
LOGTRACE(TSDecoder, "ProcessTS(%d, 0x%.8x, %d, 0x%.8x, 0x%.8x), this=0x%.8x\r\n", (int)op, pTS, uiBytes, cb, pCbCtx, this);
ffmpeg::AVFormatContext* pFmtCtx = 0;
if (0 == (pFmtCtx = ffmpeg::avformat_alloc_context()))
return E_OUTOFMEMORY;
ffmpeg::AVIOContext* pIoCtx = ffmpeg::avio_alloc_context(pTS, uiBytes, 0, &ctx
, [](void *opaque, uint8_t *buf, int buf_size)->int {
auto pCtx = (CONTEXT*)opaque;
int size = pCtx->uiBytes;
if (pCtx->uiBytes - pCtx->iPos < buf_size)
size = pCtx->uiBytes - pCtx->iPos;
if (size > 0) {
memcpy(buf, pCtx->pTS + pCtx->iPos, size);
pCtx->iPos += size;
}
return size;
}
, 0
, [](void* opaque, int64_t offset, int whence)->int64_t {
auto pCtx = (CONTEXT*)opaque;
switch (whence)
{
case SEEK_SET:
pCtx->iPos = offset;
break;
case SEEK_CUR:
pCtx->iPos += offset;
break;
case SEEK_END:
pCtx->iPos = pCtx->uiBytes - offset;
break;
case AVSEEK_SIZE:
return pCtx->uiBytes;
}
return pCtx->iPos;
});
pFmtCtx->pb = pIoCtx;
int iRet = ffmpeg::avformat_open_input(&pFmtCtx, "fakevideo.ts", m_pInputFmt, 0);
if (ERROR_SUCCESS != iRet) {
assert(false);
pFmtCtx = 0;// a user-supplied AVFormatContext will be freed on failure.
return E_FAIL;
}
struct DecodeContext {
ffmpeg::AVStream* pStream;
ffmpeg::AVCodec* pDecoder;
int iFramesProcessed;
};
HRESULT hr = S_OK;
int iStreamsProcessed = 0;
bool bVideoFound = false;
int64_t ptsLast = 0;
int64_t dtsLast = 0;
auto pContext = (DecodeContext*)alloca(sizeof(DecodeContext) * pFmtCtx->nb_streams);
for (unsigned int i = 0; i < pFmtCtx->nb_streams; i++) {
assert(pFmtCtx->streams[i]->index == i);
pContext[i].pStream = pFmtCtx->streams[i];
pContext[i].pDecoder = ffmpeg::avcodec_find_decoder(pFmtCtx->streams[i]->codec->codec_id);
pContext[i].iFramesProcessed= 0;
if (0 == pContext[i].pDecoder)
continue;
if ((iRet = ffmpeg::avcodec_open2(pFmtCtx->streams[i]->codec, pContext[i].pDecoder, NULL)) < 0) {
_ASSERT(FALSE);
hr = E_FAIL;
goto ErrExit;
}
}
while (S_OK == hr) {
ffmpeg::AVFrame* pFrame = 0;
ffmpeg::AVPacket pkt;
ffmpeg::av_init_packet(&pkt);
if (ERROR_SUCCESS != (iRet = ffmpeg::av_read_frame(pFmtCtx, &pkt))) {
hr = E_FAIL;
break;
}
if ((0 == dtsLast) && (0 != pkt.dts))
dtsLast = pkt.dts;
if ((0 == ptsLast) && (0 != pkt.pts))
ptsLast = pkt.pts;
DecodeContext& ctx = pContext[pkt.stream_index];
if (Operation::DECODE_FIRST_FRAME_OF_EACH_STREAM == op) {
if (iStreamsProcessed == pFmtCtx->nb_streams) {
hr = S_FALSE;
goto Next;
}
if (ctx.iFramesProcessed > 0)
goto Next;
iStreamsProcessed++;
}
if (0 == ctx.pDecoder)
goto Next;
if (0 == (pFrame = ffmpeg::av_frame_alloc())) {
hr = E_OUTOFMEMORY;
goto Next;
}
LOGTRACE(TSDecoder, "ProcessTS(%d, 0x%.8x, %d, 0x%.8x, 0x%.8x), this=0x%.8x, decode, S:%d, T:%d\r\n", (int)op, pTS, uiBytes, cb, pCbCtx, this, pkt.stream_index, ctx.pStream->codec->codec_type);
int bGotFrame = false;
int iBytesUsed = 0;
MEDIA_TYPE mt;
memset(&mt, 0, sizeof(mt));
mt.eType = ctx.pStream->codec->codec_type;
switch (mt.eType) {
case ffmpeg::AVMediaType::AVMEDIA_TYPE_AUDIO:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if((iRet = ffmpeg::avcodec_decode_audio4(ctx.pStream->codec, pFrame, &bGotFrame, &pkt)) < 0) {
hr = E_FAIL;
goto Next;
}
_ASSERT(pkt.size == iRet);
// FFMPEG AAC decoder oddity, first call to 'avcodec_decode_audio4' results mute audio where the second result the expected audio
bGotFrame = false;
if ((iRet = ffmpeg::avcodec_decode_audio4(ctx.pStream->codec, pFrame, &bGotFrame, &pkt)) < 0) {
hr = E_FAIL;
goto Next;
}
_ASSERT(pkt.size == iRet);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (false == bGotFrame)
goto Next;
iBytesUsed = ctx.pStream->codec->frame_size;
mt.format.audio.nChannels = ctx.pStream->codec->channels;
mt.format.audio.nSamplesPerSec = ctx.pStream->codec->sample_rate;
mt.format.audio.wBitsPerSample = ffmpeg::av_get_bytes_per_sample(ctx.pStream->codec->sample_fmt) * 8;
mt.format.audio.nBlockAlign = mt.format.audio.nChannels * mt.format.audio.wBitsPerSample / 8;
mt.format.audio.sSampleFormat = (short)pFrame->format;
break;
case ffmpeg::AVMediaType::AVMEDIA_TYPE_VIDEO:
if ((iRet = ffmpeg::avcodec_decode_video2(ctx.pStream->codec, pFrame, &bGotFrame, &pkt)) < 0) {
hr = E_FAIL;
break;
}
if (false == bGotFrame)
goto Next;
assert(ffmpeg::AVPixelFormat::AV_PIX_FMT_YUV420P == ctx.pStream->codec->pix_fmt);// Thats is the only color space currently supported
iBytesUsed = (ctx.pStream->codec->width * ctx.pStream->codec->height * 3) / 2;
mt.format.video.width = ctx.pStream->codec->width;
mt.format.video.height = ctx.pStream->codec->height;
mt.format.video.colorspace = ctx.pStream->codec->pix_fmt;
mt.format.video.fFPS = (float)ctx.pStream->codec->framerate.num / ctx.pStream->codec->framerate.den;
bVideoFound = true;
break;
default:
goto Next;
}
ctx.iFramesProcessed++;
{
FRAME f = { ctx.pStream->index, ((0 == ptsLast) ? dtsLast : ptsLast), (uint8_t**)pFrame->data, (int32_t*)pFrame->linesize };
if ((iRet > 0) && (false == cb(mt, f, pCbCtx)))
hr = S_FALSE;// Breaks the loop
}
Next:
ffmpeg::av_free_packet(&pkt);
if (0 != pFrame) {
//ffmpeg::av_frame_unref(pFrame);
ffmpeg::av_frame_free(&pFrame);
pFrame = 0;
}
}
ErrExit:
for (unsigned int i = 0; i < pFmtCtx->nb_streams; i++)
ffmpeg::avcodec_close(pFmtCtx->streams[i]->codec);
pIoCtx->buffer = 0;// We have allocated the buffer, no need for ffmpeg to free it 4 us
pFmtCtx->pb = 0;
ffmpeg::av_free(pIoCtx);
ffmpeg::avformat_close_input(&pFmtCtx);
ffmpeg::avformat_free_context(pFmtCtx);
return hr;
}
You need to unref the packets before reusing them. And there's no need to allocate and deallocate them all the time.
Here's how I do it which might help you:
// Initialise a packet queue
std::list<AVPacket *> packets;
...
for (int c = 0; c < MAX_PACKETS; c++) {
ff->packets.push_back(av_packet_alloc());
}
while (!quit) {
... get packet from queue
int err = av_read_frame(ff->context, packet);
... process packet (audio, video, etc)
av_packet_unref(packet); // add back to queue for reuse
}
// Release packets
while (ff->packets.size()) { // free packets
AVPacket *packet = ff->packets.front();
av_packet_free(&packet);
ff->packets.pop_front();
}
In your code you've freed a packet which wasn't allocated in the first place.
I am trying to write an application that pairs a remote bluetooth device with Windows Mobile/CE handheld and get the service of the device.
I noticed that when you manually pair a device and set the service through the system(eg. go to settings->Bluetooth-> add device) it generates an sdprecord value in the following registry
HKLM/Software/Microsoft/Bluetooth/Device/{deviceAddress}/{*Service_UUID*}.
I am basically trying to implement this in my program.
I followed the following documentations:
http://msdn.microsoft.com/en-us/library/ms883458.aspx
http://msdn.microsoft.com/en-us/library/ms883398.aspx
and then convert the SDPrecord into binary and write it to the registry:
RegSetValueEx(hSerialPortKey,_T("sdprecord"),0,REG_BINARY,(BYTE*)&pRecord,sizeof(pRecord)*2+1);
The result is not the same as what I would get when I manually pair the device.
What am I doing wrong? How can I retrieve the SDP record? Thank you in advance.
Below is my code
BTHNS_RESTRICTIONBLOB RBlob;
memset(&RBlob,0,sizeof(BTHNS_RESTRICTIONBLOB));
RBlob.type = SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST;
RBlob.numRange = 1;
RBlob.uuids[0].uuidType= SDP_ST_UUID16;//SDP_ST_UUID128;
RBlob.uuids[0].u.uuid16= SerialPortServiceClassID_UUID16;
RBlob.pRange[0].minAttribute =SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST;
RBlob.pRange[0].maxAttribute = SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST;
SOCKADDR_BTH sa;
memset (&sa, 0, sizeof(SOCKADDR_BTH));
BTH_ADDR *pDeviceAddr = &devAddress;
*(BTH_ADDR *)(&sa.btAddr) = *pDeviceAddr;
sa.addressFamily = AF_BTH;
CSADDR_INFO csai;
memset(&csai,0,sizeof(CSADDR_INFO));
csai.RemoteAddr.lpSockaddr = (sockaddr*)&sa;
csai.RemoteAddr.iSockaddrLength = sizeof(sa);
BLOB blob;
blob.cbSize = sizeof(BTHNS_RESTRICTIONBLOB);
blob.pBlobData = (BYTE *)&RBlob;
WSAQUERYSET wsaq;
memset(&wsaq,0,sizeof(WSAQUERYSET));
wsaq.dwSize = sizeof(WSAQUERYSET);
wsaq.dwNumberOfCsAddrs = 1;
wsaq.dwNameSpace = NS_BTH;
wsaq.lpBlob = &blob;
wsaq.lpcsaBuffer = &csai;
wsaq.lpServiceClassId = &serialPortUUID;
//Initialising winsock
WSADATA data;
int result = WSAStartup(MAKEWORD(2, 2), &data);//initializing winsock
if (hLib == NULL)
{
return S_FALSE;
}
result = WSALookupServiceBegin (&wsaq,0, &hLookup);
while (result ==ERROR_SUCCESS )
{
BYTE sdpBuffer[4096];
memset(sdpBuffer,0,sizeof(sdpBuffer));
LPWSAQUERYSET pResult = (LPWSAQUERYSET)&sdpBuffer;
dwSize = sizeof(sdpBuffer);
pResult->dwSize = sizeof(WSAQUERYSET);
pResult->dwNameSpace = NS_BTH;
pResult->lpBlob = NULL;
pResult->lpServiceClassId = &serialPortUUID;
result = WSALookupServiceNext(hLookup,0,&dwSize,pResult);
if(result == -1 )
{
int error;
error = WSAGetLastError();
if (error == WSA_E_NO_MORE)
break;
}
else
{
//Get SDP record
if (pResult != NULL)
{
if (ERROR_SUCCESS != ServiceAndAttributeSearchParse(pResult->lpBlob->pBlobData,pResult->lpBlob->cbSize,&pRecordArg,&ulRecords)) { //error handling}
ULONG recordIndex;
for (recordIndex = 0; recordIndex < ulRecords; recordIndex++) {
pRecord = pRecordArg[recordIndex];}
I think the code should be ok.Here's my code
int FindRFCOMMChannel (unsigned char *pStream, int cStream, unsigned char *pChann)
{
ISdpRecord **pRecordArg;
int cRecordArg = 0;
*pChann = 0;
int hr = ServiceAndAttributeSearch(pStream, cStream, &pRecordArg, (ULONG *)&cRecordArg);
if (hr != ERROR_SUCCESS)
{
BT_ERROR( CBTRFCOMMMgr, PerformServiceSearch, "ServiceAndAttributeSearch ERROR %d\n");
return hr;
}
for (int i = 0; (! *pChann) && (i < cRecordArg); i++)
{
ISdpRecord *pRecord = pRecordArg[i]; // particular record to examine in this loop
CNodeDataFreeString protocolList; // contains SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST data, if available
if (ERROR_SUCCESS != pRecord->GetAttribute(SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST,&protocolList) ||
(protocolList.type != SDP_TYPE_CONTAINER))
continue;
ISdpNodeContainer *pRecordContainer = protocolList.u.container;
int cProtocols = 0;
NodeData protocolDescriptor; // information about a specific protocol (i.e. L2CAP, RFCOMM, ...)
pRecordContainer->GetNodeCount((DWORD *)&cProtocols);
for (int j = 0; (! *pChann) && (j < cProtocols); j++) {
pRecordContainer->GetNode(j,&protocolDescriptor);
if (protocolDescriptor.type != SDP_TYPE_CONTAINER)
continue;
ISdpNodeContainer *pProtocolContainer = protocolDescriptor.u.container;
int cProtocolAtoms = 0;
pProtocolContainer->GetNodeCount((DWORD *)&cProtocolAtoms);
for (int k = 0; (! *pChann) && (k < cProtocolAtoms); k++) {
NodeData nodeAtom; // individual data element, such as what protocol this is or RFCOMM channel id.
pProtocolContainer->GetNode(k,&nodeAtom);
if (IsRfcommUuid(&nodeAtom)) {
if (k+1 == cProtocolAtoms) {
// misformatted response. Channel ID should follow RFCOMM uuid
break;
}
NodeData channelID;
pProtocolContainer->GetNode(k+1,&channelID);
*pChann = (unsigned char)GetChannel(&channelID);
break; // formatting error
}
}
}
}
for (i = 0; i < cRecordArg; i++)
pRecordArg[i]->Release();
CoTaskMemFree(pRecordArg);
return (*pChann != 0) ? 1:0;
}
int IsRfcommUuid(NodeData *pNode) {
if (pNode->type != SDP_TYPE_UUID)
return FALSE;
if (pNode->specificType == SDP_ST_UUID16)
return (pNode->u.uuid16 == RFCOMM_PROTOCOL_UUID16);
else if (pNode->specificType == SDP_ST_UUID32)
return (pNode->u.uuid32 == RFCOMM_PROTOCOL_UUID16);
else if (pNode->specificType == SDP_ST_UUID128)
return (0 == memcmp(&RFCOMM_PROTOCOL_UUID,&pNode->u.uuid128,sizeof(GUID)));
return FALSE;
}
int GetChannel (NodeData *pChannelNode) {
if (pChannelNode->specificType == SDP_ST_UINT8)
return pChannelNode->u.uint8;
else if (pChannelNode->specificType == SDP_ST_INT8)
return pChannelNode->u.int8;
else if (pChannelNode->specificType == SDP_ST_UINT16)
return pChannelNode->u.uint16;
else if (pChannelNode->specificType == SDP_ST_INT16)
return pChannelNode->u.int16;
else if (pChannelNode->specificType == SDP_ST_UINT32)
return pChannelNode->u.uint32;
else if (pChannelNode->specificType == SDP_ST_INT32)
return pChannelNode->u.int32;
return 0;
}