Where can I find a good example of ReportEvent function usage? - winapi

As with most "legacy" MSDN pages, the page for ReportEvent has too little information for me to make much sense of it. I've tried searching, but can't find a good, clean, simple example of the function's usage. Could anyone suggest one?

I ended up using this:
HANDLE eventLog;
WORD type;
const char* msg;
// ... snip ...
ReportEvent(eventLog, type, 0, 1, NULL, 1, 0, &LPCTSTR(msg), NULL);
Seems to work well enough.

Well this seems to be a very old thread, landed here looking for a good example of Report Event... but figured out you have not received any replies...and would have probably already found the solution.
The reason you see "Event Id not found" is because the EventViewer is not able to load/lookup the text resource to be displayed for the event Id. Sorry if last line sounded geeky.. but this is what i understand of EventLog:
-EventLogging has two aspects
Registering with EventLog (or in other terms creating EventSource)
Logging or Writing into Event Log
Viewing or Reading from log
When you register in event log, you simply specify a eventSource (any name that identifies that log) + EventMessageFile, Category File and SupportedEventTypes. Here EventMessageFile points to a DLL/EXE that contains your message descriptions/resources.
When you log an event, you simply log it with some data like EventID, Category ID and EventData. But when you view it using any EventViewer (or Windows eventVwr.exe) the viewer reads your events, looks for a DLL/EXE associated with your eventSource(pointed by EventMessageFile), and renders the decription from the resource section of that DLL/EXE.
This DLL is nothing but a simple resource file that was compiled using MessageCompiler, and contains a "MessageTable". This is done to provide culture specific event logging
This is the reason, When you export the log into XML/TXT etc from your EventViewer, It asks you if you want to Save it "with Display informaion" or "without display information", so that you can view it on computers that do not have EventMessageFile.
JFYI the reg entry is located at:
HKLM\CurrentControlSet\System\Services\EventLog\Application
one catch: If you're wondering how .Net does it..., it simply does it by providing a default EventMessageFile called EventLogMessage.dll (found under %SYSTEMROOT%\Microsoft.Net\Framework\vXXXX\)

As I recall it is a pain to set up correctly - you need to add messages to you application using the Message Compiler - if you skip this you won't see useful messages only error codes. Take a look at Creating a Windows NT Service by Using ATL for an example

The sample Windows Service C++, is a windows service reporting to event log, you can get the code from https://code.msdn.microsoft.com/windowsapps/CppWindowsService-cacf4948
in particular, the following function (quoted from ServiceBase.cpp) does it
//
// FUNCTION: CServiceBase::WriteEventLogEntry(PWSTR, WORD)
//
// PURPOSE: Log a message to the Application event log.
//
// PARAMETERS:
// * pszMessage - string message to be logged.
// * wType - the type of event to be logged. The parameter can be one of
// the following values.
//
// EVENTLOG_SUCCESS
// EVENTLOG_AUDIT_FAILURE
// EVENTLOG_AUDIT_SUCCESS
// EVENTLOG_ERROR_TYPE
// EVENTLOG_INFORMATION_TYPE
// EVENTLOG_WARNING_TYPE
//
void CServiceBase::WriteEventLogEntry(PWSTR pszMessage, WORD wType)
{
HANDLE hEventSource = NULL;
LPCWSTR lpszStrings[2] = { NULL, NULL };
hEventSource = RegisterEventSource(NULL, m_name);
if (hEventSource)
{
lpszStrings[0] = m_name;
lpszStrings[1] = pszMessage;
ReportEvent(hEventSource, // Event log handle
wType, // Event type
0, // Event category
0, // Event identifier
NULL, // No security identifier
2, // Size of lpszStrings array
0, // No binary data
lpszStrings, // Array of strings
NULL // No binary data
);
DeregisterEventSource(hEventSource);
}
}

Related

Can I delete a field from a protobuf message?

I'm implementing a policy enforcement point between a client and a server that receives messages from the server, and, if the client doesn't have adequate authorization to see some parts of the message deletes those parts before sending them to the client.
message {
string not_sensitive = 1;
optional string sensitive = 2;
}
pseudo code
from_server >> my_msg;
if (!authorized) {
my_msg.delete("sensitive");
}
to_client << my_msg;
Yes.
As I understand current v3 pb schema language, all fields are optional. But regardless of that, a field marked optional in v2 is something that need not be there. So expanding your pseudo code to, say, C++ (see here), one can see that the generated class would end up with a has_sensitive() method and a clear_sensitive() method. Calling the latter and then serialising the object would result in wire format data that omitted the sensitive field.

Updating display of directory/folder path in MFC File-Open dialog [duplicate]

I'm trying to make a 'Save As' dialog with an event that would change the default path based on the type of file we choose from the filters combo box. The problem is, all the examples I've seen execute the code on result IDOK or IDCANCEL while I'd need the code to be executed while the dialog is still opened.
Also, is there any way to differentiate between what filter has been chosen if the filters have the same type? The GetFileExt() method just returns the extension but I have no way of telling if it was the first .my filter or the template .my filter.
I've seen something like LPOFNHOOKPROC but there was no example of how would I even use it and I'm not sure whether it would even solve my problem or not.
void CMyClass::OnFileOpen()
{
CString pathNam;
CString fileName;
TCHAR szFilters[]= _T("MyType Files (*.my)|*.my|Template MyType (*.my)|*.my||");
CFileDialog fileDlg(TRUE, _T("my"), _T("*.my"),
OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters);
if(fileDlg.DoModal() == IDOK)
{
pathName = fileDlg.GetPathName();
fileName = fileDlg.GetFileTitle();
}
}
EDIT:
I am now able to get the specific filter that's been chosen by getting the OFN and checking the nFilterIndex value. So the remaining problem is whether I can update the path based on the chosen file format?
EDIT2:
I've found the OnChangeType method and overloaded it in the subclass and it indeed executes the method and the code within, but when I try to update the file path I get an access violation:
void TFileDialogExt::OnTypeChange()
{
LPWSTR buff = L"C:\\TEST\\template.my";
if(m_pOFN->nFilterIndex == 2)
m_ofn.lpstrFile = buff;
}
Basically you have to subclass CFileDialog and handle its CFileDialog::OnTypeChange method.
But, as suggested by Microsoft: you'd better use a new Common Item Dialog instead.
I did some research about this and found some useful questions:
Programmatically pre-select using IFileDialog in C++
How to use SHCreateItemFromParsingName with names from the shell namespace?
Also, have a look at: SHCreateItemFromParsingName.
Here is a sample OnTypeChange handler:
void CMyFileDialog::OnTypeChange()
{
{
IFileOpenDialog* pfod = NULL;
HRESULT hr = (static_cast<IFileDialog*>(m_pIFileDialog))->QueryInterface(IID_PPV_ARGS(&pfod));
if (SUCCEEDED(hr))
{
IShellItem* psiInitialDir;
CString strFolder = L"d:\\";
hr = SHCreateItemFromParsingName(strFolder.GetString(), NULL, IID_PPV_ARGS(&psiInitialDir));
if(SUCCEEDED(hr))
{
pfod->SetFolder(psiInitialDir);
}
}
}
CFileDialog::OnTypeChange();
}
My code uses a hard coded path for testing purposes, but you should now be able to complete your code:
Determine which path you want to use based on the currently selected filter index.
Use similar logic as here to navigate to that folder.

How to get the timestamp of when a disk is made offline from diskmgmt or other ways in windows?

I want to know the time when a disk is made offline by user. Is there a way to know this through WMI classes or other ways?
If you cannot find a way to do it through the Win32 API/WMI or other, I do know of an alternate way which you could look into as a last-resort.
What about using NtQueryVolumeInformationFile with the FileFsVolumeInformation class? You can do this to retrieve the data about the volume and then access the data through the FILE_FS_VOLUME_INFORMATION structure. This includes the creation time.
At the end of the post, I've left some resource links for you to read more on understanding this so you can finish it off the way you'd like to implement it; I do need to quickly address something important though, which is that the documentation will lead you to
an enum definition for the _FSINFOCLASS, but just by copy-pasting it from MSDN, it probably won't work. You need to set the first entry of the enum definition to 1 manually, otherwise it will mess up and NtQueryVolumeInformationFile will return an error status of STATUS_INVALID_INFO_CLASS (because the first entry will be identified as 0 and not 1 and then all the entries following it will be -1 to what they should be unless you manually set the = 1).
Here is the edited version which should work.
typedef enum _FSINFOCLASS {
FileFsVolumeInformation = 1,
FileFsLabelInformation,
FileFsSizeInformation,
FileFsDeviceInformation,
FileFsAttributeInformation,
FileFsControlInformation,
FileFsFullSizeInformation,
FileFsObjectIdInformation,
FileFsDriverPathInformation,
FileFsVolumeFlagsInformation,
FileFsSectorSizeInformation,
FileFsDataCopyInformation,
FileFsMetadataSizeInformation,
FileFsMaximumInformation
} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
Once you've opened a handle to the disk, you can call NtQueryVolumeInformationFile like this:
NTSTATUS NtStatus = 0;
HANDLE FileHandle = NULL;
IO_STATUS_BLOCK IoStatusBlock = { 0 };
FILE_FS_VOLUME_INFORMATION FsVolumeInformation = { 0 };
...
Open the handle to the disk here, and then check that you have a valid handle.
...
NtStatus = NtQueryVolumeInformationFile(FileHandle,
&IoStatusBlock,
&FsVolumeInformation,
sizeof(FILE_FS_VOLUME_INFORMATION),
FileFsVolumeInformation);
...
If NtStatus represents an NTSTATUS error code for success (e.g. STATUS_SUCCESS) then you can access the VolumeCreationTime (LARGE_INTEGER) field of the FILE_FS_VOLUME_INFORMATION structure with the FsVolumeInformation variable.
Your final task at this point will be using the LARGE_INTEGER field named VolumeCreationTime to gather proper time/date information. There are two links included at the end of the post which are focused on that topic, they should help you sort it out.
See the following for more information.
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-ntqueryvolumeinformationfile
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ne-wdm-_fsinfoclass
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/ns-ntddk-_file_fs_volume_information
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724280.aspx
https://blogs.msdn.microsoft.com/joshpoley/2007/12/19/datetime-formats-and-conversions/

Solving tcsncpy_s.inl assertion (line 24)

I've a fairly simple program which needs user input in the form of a text string. I've a CLR form with an edit box and I need to take that input and pass it into my class which just copies it to a member variable.
In the Form.h code, handling the TextChanged event is...
int textLength = m_userDest->TextLength;
if (textLength > 2 && textLength < 5)
{
// Could be an ICAO code in here
char dest[5];
String^ text = m_userDest->Text->ToUpper();
sprintf_s(dest, 5, "%s", text);
airTraffic.SetUserDest(dest);
}
My class (airTraffic) SetUserDest function is just
void CAirTraffic::SetUserDest(char* dest)
{
strncpy_s(m_userDest, 5, dest, 5);
}
When this is run I get this debug assertion, it doesn't stay on the screen and automatically clears after a few seconds.
Debug Assertion Failed!
Program: ...sual Studio 2010\Projects\FSAirTraffic\Debug\FSAirTraffic.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\tcsncpy_s.inl
Line: 24
Expression: ((_Dst)) != NULL && ((_SizeInBytes)) > 0
I don't have an f:\ drive so I'm guessing this is some internal Microsoft(?) code so I can't see the context of the assertion and exactly what it's problem is. I don't have a file called tcsncpy_s.inl on my machine.
If I don't call my class function then there's no assertion so I assumed that was the problem.
Curiously though, when stepping through the debugger the assertion occurs as I step out of the TextChanged event, with the rest of the functions operating as intended (as far as I can see).
Does anyone know what the problem is and how I can go about solving it?
I don't understand how your code works. You use m_userDest twice, first it appears to be a pointer to a structure of some sort, maybe a handle to a TextBox control:
int textLength = m_userDest->TextLength;
Later you pass it to strncpy_s, which needs a char*, not a pointer to some structure.
void CAirTraffic::SetUserDest(char* dest)
{
strncpy_s(m_userDest, 5, dest, 5);
}
While it's possible for a structure to implicitly convert to a char*, it's not possible for a structure pointer to do so. Perhaps there's a smart pointer involved? Or you are using the same member variable name for completely different purposes in different classes1?
In any case, strncpy_s is inspecting the value of its first argument and not liking it.
1 Note that the new "wisdom" saying not to use Hungarian notation has destroyed the ability to understand this code in textual form. We don't have an IDE providing mouseover information about the data type of variables. Applications Hungarian is still a good idea in the real world, despite how many "best practices" documents decry it. Amazing how many code style documents are written from a purely theoretical basis.

emit code crashes at runtime but not in debug, why

I have some code, that build up a proxy from a type. It work perfekt.
Then I have add in the setter emit code, that it has to push a isDirty bit, when it is call. This fail, why?
If I run the code without the isDirty bit, it works.
If I run the code with the isDirty bit, it works in debug, but is start the disassembly window up in visual studio.
If I run the code with the isDirty (without-debug) the program crash (not responding) but when I hit cancel, it starts working and show all de rigth data.
PropertyBuilder property = proxy.DefineProperty(propertyInfo.Name, propertyInfo.Attributes, propertyInfo.PropertyType, null);
MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Virtual;
MethodBuilder setMethod = proxy.DefineMethod("set_" + propertyInfo.Name, attributes, typeof(void), new Type[] { propertyInfo.PropertyType });
ILGenerator setIL = setMethod.GetILGenerator();
setIL.Emit(OpCodes.Ldarg_0); // load this on the stack - where this is the type we are creating
setIL.Emit(OpCodes.Ldarg_1); // load first parameter on the stack
setIL.Emit(OpCodes.Call, propertyInfo.GetSetMethod());
{
//error here: when this is uncomment, it fails
// // set the isDirty bit
// setIL.Emit(OpCodes.Ldarg_0); // load this on the stack
// setIL.Emit(OpCodes.Ldc_I4_1, 1); // push a number on the stack
// setIL.Emit(OpCodes.Stfld, isDirtyField); // save the value on the stack in field
}
setIL.Emit(OpCodes.Ret);
property.SetSetMethod(setMethod);
I have a hard time, seeing why this fails? Need some help from the experts :)
// dennis
I'm not sure if this is your only issue, but you are using the wrong Emit overload when emitting your Ldc_I4_1 opcode. You should do either:
setIL.Emit(OpCodes.Ldc_I4_1)
or
setIL.Emit(OpCodes.Ldc_I4, 1)
The first option will result in a slightly smaller IL method body since it uses a specialized opcode, whereas the second one is not specific to the number being loaded.

Resources