Rename file Preoperation Windows Minifilter driver - c

I have a minifilter driver and would like to action file renames but i am unsure how to get the new file name. I would like to run the new filename through the same criteria as Creating a file - IRP_MJ_CREATE.
I currently monitor all files within the filter and move accordingly on a set of rules.
I have found a link on SO that relates to cancelling a rename, but unsure how to get the new filename.
The link is How to cancel a rename operation in minifilter driver
At this moment i can get the existing file name in case FileRenameInformation but i need to know what the new file name information is.
I have tried using :
PFILE_RENAME_INFORMATION renameInfo
Iopb->Parameters.SetFileInformation.InfoBuffer;
In the switch - FileRenameInformation, but the output is always empty.
My PreOperation callback is as follows:
FLT_PREOP_CALLBACK_STATUS PreOperationCallback(_Inout_
PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID* CompletionContext)
{
PFILE_RENAME_INFORMATION renameInfo;
//WCHAR buf[4096] = { 0 };
/* IRP-based I/O operation? */
if (FLT_IS_IRP_OPERATION(Data)) {
/* Open file? */
if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
/* Open file for writing/appending? */
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &
(FILE_WRITE_DATA | FILE_APPEND_DATA)) {
return process_irp(Data, FltObjects, CompletionContext, DEFERRED_IO, FALSE);
}
} else if (Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION) {
switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass) {
case FileDispositionInformation:
if (((FILE_DISPOSITION_INFORMATION*) Data->Iopb->Parameters.SetFileInformation.InfoBuffer)->DeleteFile) {
return process_irp(Data, FltObjects, CompletionContext, FALSE, FALSE);
}
break;
case FileEndOfFileInformation:
case FileRenameInformation:
//https://stackoverflow.com/questions/40564824/how-to-cancel-a-rename-operation-in-minifilter-driver
renameInfo = Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
//memcpy(buf, renameInfo->FileName, renameInfo->FileNameLength);
DbgPrint("Rename info - '%wZ'", renameInfo->FileName);
return process_irp(Data, FltObjects, CompletionContext, FALSE, TRUE);
}
}
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}

The issue lies in the DbgPrint you need to use %ws
FLT_PREOP_CALLBACK_STATUS PreOperationCallback(_Inout_
PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID* CompletionContext)
{
PFILE_RENAME_INFORMATION renameInfo;
//WCHAR buf[4096] = { 0 };
/* IRP-based I/O operation? */
if (FLT_IS_IRP_OPERATION(Data)) {
/* Open file? */
if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
/* Open file for writing/appending? */
if (Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess &
(FILE_WRITE_DATA | FILE_APPEND_DATA)) {
return process_irp(Data, FltObjects, CompletionContext, DEFERRED_IO,
FALSE);
}
} else if (Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION) {
switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass) {
case FileDispositionInformation:
if (((FILE_DISPOSITION_INFORMATION*) Data->Iopb->Parameters.SetFileInformation.InfoBuffer)->DeleteFile) {
return process_irp(Data, FltObjects, CompletionContext, FALSE, FALSE);
}
break;
case FileEndOfFileInformation:
case FileRenameInformation:
DbgPrint("Original file - '%wZ'", name_info->Name);
renameInfo = Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
DbgPrint("Rename info length- '%u'", renameInfo->FileNameLength);
DbgPrint("Rename File info - '%ws'", renameInfo->FileName);
return process_irp(Data, FltObjects, CompletionContext, FALSE, TRUE);
}
}
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
You can call get_file_name_information to get the original file location in the code above like:
PFLT_FILE_NAME_INFORMATION name_info;
get_file_name_information(Data, &name_info);
//Release
FltReleaseFileNameInformation(name_info);
Now there is one problem the rename->FileName is in a different format to name_info->Name
The example below rename C:\temp\1.rtf to C:\temp\12.rtf
DbgPrint("Original file - '%wZ'", name_info->Name);
Will be in the format\output of:
\Device\HarddiskVolume4\Temp\1.rtf
Where as the
DbgPrint("Rename File info - '%ws'", renameInfo->FileName);
Will be in the format\output of:
\??\C:\Temp\12.rtf
BOOLEAN get_file_name_information(PFLT_CALLBACK_DATA data,
PFLT_FILE_NAME_INFORMATION* name_info)
{
/* Get name information. */
if (NT_SUCCESS(FltGetFileNameInformation(
data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
name_info
))) {
/* Parse file name information. */
if (NT_SUCCESS(FltParseFileNameInformation(*name_info))) {
return TRUE;
}
FltReleaseFileNameInformation(*name_info);
#if OSVER(NTDDI_VERSION) > NTDDI_WIN2K
} else {
/*
* We couldn't get the "normalized" name, try to get the "opened"
* name.
*/
if (NT_SUCCESS(FltGetFileNameInformation(data,
FLT_FILE_NAME_OPENED |
FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
name_info
))) {
if (NT_SUCCESS(FltParseFileNameInformation(*name_info))) {
return TRUE;
}
FltReleaseFileNameInformation(*name_info);
}
#endif /* OSVER(NTDDI_VERSION) > NTDDI_WIN2K */
}
return FALSE;
}
Not sure whether this needs to be another post on Stack overflow, but if anyone knows how to change the rename->FileName to the same format/structure as name_info->Name, can they update the answer.

Related

Sending log schema to kaa server from RPI3 with optional fields

I am trying to send a log schema from raspberry pi C application, to back end kaa server.
Here is the schema
{
"type" : "record",
"name" : "RemoteSensorLog",
"namespace" : "org.kaa.iot.log.sensor",
"fields" : [ {
"name" : "deviceId",
"type" : {
"type" : "string",
"avro.java.string" : "String"
}
}, {
"name" : "temperature",
"type" : [ "double", "null" ]
}, {
"name" : "humidity",
"type" : [ "long", "null" ]
}, {
"name" : "batteryLevel",
"type" : [ "int", "null" ]
} ],
"version" : 1,
"dependencies" : [ ],
"displayName" : "RemoteSensorLog",
"description" : "This is the log sent by remote sensors"
}
Some of the items in the log schema are optional, Here is the initialization function
void kaaLogInitializing(void *context)
{
void *log_storage_context = NULL;
void *log_upload_strategy_context = NULL;
printf("Initializing the Kaa log\n");
kaa_client_t * kaa_client_context = context;
if (context == NULL) {
return;
}
/* Log delivery listener callbacks. Each callback called whenever something happen with a log bucket. */
kaa_log_delivery_listener_t log_listener = {
.on_success = success_log_delivery_callback, /* Called if log delivered successfully */
.on_failed = failed_log_delivery_callback, /* Called if delivery failed */
.on_timeout = timeout_log_delivery_callback, /* Called if timeout occurs */
.ctx = kaa_client_context, /* Optional context */
};
/* The internal memory log storage distributed with Kaa SDK */
kaa_error_t error_code = ext_unlimited_log_storage_create(&log_storage_context,
kaa_client_get_context(
kaa_client_context
)->logger
);
if (error_code) {
printf("Failed to create Kaa log storage %d\r\n", error_code);
return;
}
error_code = ext_log_upload_strategy_create(kaa_client_get_context(
kaa_client_context),
&log_upload_strategy_context, KAA_LOG_UPLOAD_VOLUME_STRATEGY);
if (error_code) {
printf("Failed to create log upload strategy, error code %d\r\n", error_code);
return;
}
error_code = ext_log_upload_strategy_set_threshold_count(log_upload_strategy_context,
LOG_UPLOAD_THRESHOLD);
if (error_code) {
printf("Failed to set threshold log record count, error code %d\r\n", error_code);
return;
}
error_code = kaa_logging_set_strategy(kaa_client_get_context(kaa_client_context)->log_collector,
log_upload_strategy_context);
if (error_code) {
printf("Failed to set log upload strategy, error code %d\r\n", error_code);
return;
}
/* Specify log bucket size constraints */
kaa_log_bucket_constraints_t bucket_sizes = {
.max_bucket_size = MAX_LOG_BUCKET_SIZE, /* Bucket size in bytes */
.max_bucket_log_count = MAX_LOG_COUNT, /* Maximum log count in one bucket */
};
/* Initialize the log storage and strategy (by default it is not set) */
error_code = kaa_logging_init(kaa_client_get_context(
kaa_client_context)->log_collector
, log_storage_context
, log_upload_strategy_context
, &bucket_sizes);
if (error_code) {
printf("Failed to initialize Kaa log %d\r\n", error_code);
return;
}
/* Add listeners to a log collector */
kaa_logging_set_listeners(kaa_client_get_context(
kaa_client_context)->log_collector,
&log_listener);
}
Here is the function I use to send log
void sendLog(void *context)
{
kaa_client_t * kaa_client_context = context;
float temperature = 25.5;
if (context == NULL) {
return;
}
logDelivered = LOG_DELIVERY_DELIVERING;
printf("Start attempt to send Log\n");
kaa_logging_remote_sensor_log_t *log_record = kaa_logging_remote_sensor_log_create();
log_record->device_id = kaa_string_copy_create("Dev1");
log_record->temperature = kaa_logging_union_double_or_null_branch_0_create();
log_record->temperature->data = &temperature; /* create subobject */
log_record->humidity = kaa_logging_union_long_or_null_branch_1_create();
log_record->battery_level = kaa_logging_union_int_or_null_branch_1_create();
printf("Log record created\n");
/* Log information. Populated when log is added via kaa_logging_add_record() */
kaa_log_record_info_t log_info;
kaa_error_t error = kaa_logging_add_record(
kaa_client_get_context(kaa_client_context)->log_collector,
log_record, &log_info);
if (error) {
printf("Failed to add log record, error code\r\n");
kaa_client_stop(kaa_client_context);
return;
}
//log_record->destroy(log_record);
}
I have 2 problems
Problem1 #### : if I uncomment the last line in sendLog function log_record->destroy(log_record); I got this error double free or corruption (out): 0x7efe05
Problem2 #### : after commenting the mentioned line and running the application I never get any error or the server get the log nothing seems to happen neither I receive log was sent successfully or failure or timeout.
You need to manually allocate memory to store the temperature value. It will be freed in thelog_record->destroy(log_record).
So, you need to do something like this:
double *p_temperature = KAA_MALLOC(sizeof(double));
if (!p_temperature) {
// error handling
}
*p_temperature = 25.5;
log_record->temperature->data = p_temperature;

How to cancel a rename operation in minifilter driver

I would like to cancel a rename operation in my minifilter. I've written the
code that detects when a file is being rename, but I'm unclear on how to
actually cancel the operation. Can anyone help me out with this?
Here is my callback routine that detects for file rename.
FLT_PREOP_CALLBACK_STATUS
PreSetInformation(
_Inout_ PFLT_CALLBACK_DATA Cbd,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
{
if (Cbd->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation)
{
WCHAR buf[MAX_PATH] = { 0 };
PFILE_RENAME_INFORMATION renameInfo = Cbd->Iopb->Parameters.SetFileInformation.InfoBuffer;
memcpy(buf, renameInfo->FileName, renameInfo->FileNameLength);
DbgPrint("renameInfo %ws\n", buf);
if (anCondition(buf))
{
// TO DO: cancel a rename
}
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
you need fill Cbd->IoStatus and return FLT_PREOP_COMPLETE
so in your code:
if (anCondition(buf))
{
// TO DO: cancel a rename
Cbd->IoStatus.Status = <some_status>;
Cbd->IoStatus.Information = <some_information>;//usually 0
return FLT_PREOP_COMPLETE;
}

groovy: parsing files with different extensions and using if/else

I have a script:
def tmn_file = ~/.*\.tmn/
def tmc_file = ~/.*\.tmc/
def newTerm = new Properties().with { props ->
new File(inputPath).eachFile(tmn_file) { file ->
file.withReader { reader ->
load( reader )
println "Read data from file $file:"
something read from file...
switch( props.ACTION ) {
case 'NEW':
do something...
}
switch( props.ACTION ) {
case 'CHANGE':
do something...
}
this script looking in directory with path inputPath file with extension tmn_file, which can containt ACTION - NEW or CHANGE.
Script works great, but i want to make another thing:
if file have extension *.tmn (tmn_file) - start only ACTION with NEW case
if file have extension *.tmc (tmc_file) - start only ACTION with CHANGE case
How i can realize decision?
Here is solution:
new Properties().with { props ->
new File(inputPath).eachFile(FileType.FILES) { file ->
file.withReader { reader ->
load(reader)
println "Read data from file $file:"
if (file.name.endsWith('tmn') & props.ACTION == 'NEW' || file.name.endsWith('tmc') & props.ACTION == 'CHANGE') {
// NEW mode
switch( props.ACTION ) {
case 'NEW':
...do someth...
break
// CHANGE mode
case 'CHANGE':
println "***CHANGE mode is on***"
...do someth...
break
default:
throw new RuntimeException("Unknown ACTION $props.ACTION")
}
} else {
if (file.name.endsWith('tmn') || file.name.endsWith('tmc')){
println "$file dont match for action $props.ACTION"
} else {
println "$file have wrong extension "}
}
}
}
}

Dynamics AX 4.0 Export Forms

I created a method to export AOT (application object tree) Objects.
It works, but when I export the Forms-Treenodes cant find it.
The method is a server method and it runs on a BatchServer.
My idea was to export the objects as xpo files every 2 hours.
By the backup I can track the Code changes.
void run(str Path)
{
List _ValueList = new List(Types::String);
Counter _ListCounter;
ListIterator _ListIterator;
str _RootFolder;
str _FileName;
str _FolderName;
TreeNode _TreeNode;
TreeNode _InnerTreeNode;
TreeNodeIterator _TreeNodeIt;
FileIoPermission _Perm;
#define.ExportMode("w")
;
_RootFolder = Path;
//Objektbaum definition
_ValueList.addEnd("Forms");
_ValueList.addEnd("Reports");
_ValueList.addEnd("Queries");
_ValueList.addEnd("Classes");
_ValueList.addEnd("Macros");
_ValueList.addEnd("Jobs");
_ValueList.addEnd(#"Data Dictionary\Tables");
_ValueList.addEnd(#"Data Dictionary\Maps");
_ValueList.addEnd(#"Data Dictionary\Views");
_ValueList.addEnd(#"Data Dictionary\Extended Data Types");
_ValueList.addEnd(#"Data Dictionary\Base Enums");
_ListIterator = new ListIterator(_ValueList);
info(strfmt("RootExportPath: %1",_RootFolder));
// durch die zuvor definierte Liste laufen
while(_ListIterator.more())
{
try
{
info(strfmt(#"\%1",_ListIterator.value()));
//Haupttreenode objekt laden
_TreeNode = TreeNode::findNode(strfmt(#"\%1",_ListIterator.value()));
if (_TreeNode != null)
{
//Splitten des HauptNodes
_TreeNodeIt = _TreeNode.AOTiterator();
_InnerTreeNode = _TreeNodeIt.next();
//Durchlaufen der SubNodes
info(strfmt("Object found in Node: %1 ",_TreeNode.AOTchildNodeCount()));
while(_InnerTreeNode)
{
//Pfad und Filename bereitstellen
_FolderName = strfmt(#"%1\%2",_RootFolder,strreplace(_ListIterator.value(),#" ","_"));
_FileName = strfmt(#"\%1.xpo",strreplace(_InnerTreeNode.AOTname(),#" ","_"));
//Fileperms setzen ("w") = Write (OverWrite)
_Perm = new FileIoPermission(_FolderName+_FileName , #ExportMode);
if (_Perm == null)
{
return;
}
_Perm.assert();
try
{
if(!WinApi::pathExists(_FolderName))
{
if(WinApi::createDirectory(_FolderName))
{
throw error(strfmt("Pfad konnte nicht erstellt werden %1\n",_FolderName));
}
if(!WinApi::pathExists(_FolderName))
{
throw error(strfmt("Fehler beim erstellen des Pfades %1\n",_FolderName));
}
}
//Export in definierten Filename
if(WinApi::fileLocked(_FolderName+_FileName))
{
throw error("File ist ReadOnly\n");
}
_InnerTreeNode.treeNodeExport(_Foldername+_FileName);
}
catch
{
error(strfmt(#"xpo File %1 konnte nicht geschrieben werden\n",_FolderName+_Filename));
throw error("Abbruch des Jobs\n");
}
CodeAccessPermission::revertAssert();
_InnerTreeNode = _TreeNodeIt.next();
}
// BP deviation documented.
_TreeNode.treeNodeExport(_FileName);
}
else
{
error(strfmt("TreeNode empty %1",_ListIterator.value()));
}
}
catch
{
throw error("Fehler in der Verarbeitungsroutine\n");
}
_ListIterator.next();
}
}
Does the Forms folder exist in your export location?
You are attempting to assert permissions on a folder BEFORE checking it exists and creating it.
Forms can no be exported by a batch-server because the form's ar not loadet.
This ist a litle bit strange but the batchserver calls only class layer in AOT... the Forms ar hirarchical top of it and so on not exportable.

file upload cakephp

when uploading an image to the server using cakephp
$this->Model->Behaviors->attach('ImageUpload', Configure::read('photo.files'));
photo uploaded successfully, and the database fields also
but shows following error instead of returning to index page.
Notice (8): Undefined index: class [CORE\cake\libs\model\behaviors\upload.php, line 104]
Notice (8): Undefined index: class [CORE\cake\libs\model\behaviors\upload.php, line 107]
Warning (2): Cannot modify header information - headers already sent by (output started at E:\umoorthy_105act10\projects\dev1base\core\cake\basics.php:111) [CORE\cake\libs\controller\controller.php, line 614]
wat to do?
Cake has already wrote where to look for a problem
Configure::read('photo.files')
do following to check if everything is ok
pr(Configure::read('photo.files'))
public function uploadFilesIphone($folder, $formdata, $replace , $itemId = null) {
// setup dir names absolute and relative echo "<pre>"; print_r($formdata); exit;
$folder_url = WWW_ROOT.$folder;
$rel_url = $folder; //echo
// create the folder if it does not exist
if(!is_dir($folder_url)) {
mkdir($folder_url);
}
// if itemId is set create an item folder
if($itemId) {
// set new absolute folder
$folder_url = WWW_ROOT.$folder.'/'.$itemId;
// set new relative folder
$rel_url = $folder.'/'.$itemId;
// create directory
if(!is_dir($folder_url)) {
mkdir($folder_url);
}
}
// list of permitted file types, this is only images but documents can be added
$permitted = array('image/gif','image/jpeg','image/pjpeg','image/png','application/octet-stream');
// loop through and deal with the files;
$key = array();
$value = array();
foreach($formdata as $key => $value)
{
if($key == is_array($value))
{
$filename = str_replace(".", $replace , $value['name']);
}
// replace spaces with underscores
// assume filetype is false
$typeOK = false;
// check filetype is ok
foreach($permitted as $type)
{
if($key == is_array($value))
{
if($type == $value['type'])
{
$typeOK = true;
break;
}
}
}
// if file type ok upload the file
if($typeOK) {
// switch based on error code
if($key == is_array($value))
{
switch($value['error'])
{
case 0:
// check filename already exists
if(!file_exists($folder_url.'/'.$filename))
{
// create full filename
$full_url = $folder_url.'/'.$filename;
$url = $rel_url.'/'.$filename;
// upload the file
if($key == is_array($value))
{
$success = move_uploaded_file($value['tmp_name'], $url);
}
}
else
{
// create unique filename and upload file
// ini_set('date.timezone', 'Europe/London');
$now = date('Y-m-d-His');
$full_url = $folder_url.'/'.$now.$filename;
$url = $rel_url.'/'.$now.$filename;
if($key == is_array($value))
{
$success = move_uploaded_file($value['tmp_name'], $url);
}
}
// if upload was successful
if($success)
{
// save the url of the file
$result['urls'][] = $url;
}
else
{
$result['errors'][] = "Error uploaded $filename. Please try again.";
}
break;
case 3:
// an error occured
$result['errors'][] = "Error uploading $filename. Please try again.";
break;
default:
// an error occured
$result['errors'][] = "System error uploading $filename. Contact webmaster.";
break;
}
}
elseif($value['error'] == 4)
{
// no file was selected for upload
$result['nofiles'][] = "No file Selected";
}
else
{
// unacceptable file type
$result['errors'][] = "$filename cannot be uploaded. Acceptable file types: gif, jpg, png.";
}
}
}
return $result;
}

Resources