Windows: ReportEvent function - windows

As far as I understood, the ReportEvent function requires Message Text Files associated through the registry to receive properly formatted messages. Is there any common Event Ids or any simple way to report an event with no Message Text Files associated?
Or may be, is there special common Event Source which I can use in my application? Something like RegisterEventSource(NULL, "Application")?

You don't have to register your messages in HKLM. (Which is a good thing, because you can't register messages if you're not an administrator).
But that doesn't stop you from writing events to the Windows Application event log. The only downside is that starting with Windows Vista you'll just get some ugly text along with it.
HRESULT LogToEventLog(String Source, String EventText, int EventType, DWORD EventID)
{
/*
EventType is one of:
EVENTLOG_ERROR_TYPE = $0001;
EVENTLOG_WARNING_TYPE = $0002;
EVENTLOG_INFORMATION_TYPE = $0004;
EVENTLOG_AUDIT_SUCCESS = $0008;
EVENTLOG_AUDIT_FAILURE = $0010;
Source is your name for your app or feature, e.g.:
"My Cool App"
"Outlook"
"ESENT"
"Chrome"
*/
HANDLE h = RegisterEventSource(null, Source); //null --> local computer
if (h == 0)
return HResultFromWin32(GetLastError);
try
{
PChar[1] ss;
ss[0] = PChar(EventText);
if (!ReportEvent(
h, // event log handle
EventType, // event type
0, // category zero
EventID, // event identifier
null, // no user security identifier
1, // one substitution string
0, // no data
#ss, // pointer to string array
null // pointer to data
))
{
return HResultFromWin32(GetLastError);
}
}
finally
{
DeregisterEventSource(h);
}
return S_OK;
}
And so now you can log events to the Application event log:
LogToEventLog("Stackoverflow", "Question 5399066 was answered by Ian Boyd",
EVENTLOG_INFORMATION_TYPE, 0x45);
Steal someone else's registration
Unfortunately, starting with Windows Vista, Windows will give ugly complaints that you didn't register the event beforehand:
The description for Event ID 69 from source Stackoverflow cannot be
found. Either the component that raises this event is not installed on
your local computer or the installation is corrupted. You can install
or repair the component on the local computer.
If the event originated on another computer, the display information
had to be saved with the event.
The following information was included with the event:
Question 5399066 was answered by Ian Boyd
But you don't have to live with it. Just because you didn't register an message source file in HKLM, doesn't mean nobody else did.
Notice, for example, a message from the Outlook source in the Event log:
Source: Outlook
EventID: 0x40000020
Event Data: D:\win32app\Exchange\Outlook2003.pst
Message: The store D:\win32app\Exchange\Outlook2003.pst has detected a catalog checkpoint.
You can check registration information for Outlook in:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\Outlook
And see:
MessageEventFile: REG_SZ = "D:\Programs\MICROS~4\Office14\1033\MAPIR.DLL"
If you peek into the resources of MAPIR.dll binary, you'll see its Message Table:
1 MESSAGETABLE
{
0x12, "Connection stats for server (%1). Rpcs Attempted (%2), Rpcs Succeeded (%3), Rpcs Failed (%4), Rpcs Canceled (%5), Rpc UI shown (%6), Avg request time (%7) ms, Min request time (%8) ms, Max request time (%9) ms.\r\n"
0x14, "Cancelable RPC started.\r\n"
0x15, "Cancelable RPC shutdown.\r\n"
0x40000010, "Cancelable RPC dialog shown for server (%1), total wait time was (%2) ms, result was (%3).\r\n"
0x40000011, "User canceled request against server (%1) after waiting (%2) ms.\r\n"
0x40000013, "Rpc call (%1) on transport (%2) to server (%3) failed with error code (%4) after waiting (%5) ms; eeInfo (%6).\r\n"
0x40000016, "There was a problem reading one or more of your reminders. Some reminders may not appear.\r\n"
0x40000017, "Unable to update public free/busy data.\r\n"
0x4000001A, "%1\r\n"
0x4000001B, "%1\r\n"
0x4000001D, "The store %1 is being re-pushed to the indexer for the following reason: %2.\r\n"
0x4000001E, "Starting reconciliation for the store %1 for the following reason: %2.\r\n"
0x4000001F, "The store %1 has detected a catalog rebuild.\r\n"
0x40000020, "The store %1 has detected a catalog checkpoint.\r\n"
...
}
You can see that eventid 0x40000020 is assocated with a formatting string:
"The store %1 has detected a catalog checkpoint.\r\n"
You can hijack Outlook's registration:
LogToEventLog("Outlook", "Your mom", EVENTLOG_INFORMATION_TYPE, $40000020);
and you'll get your event added to the event log without all the ugly warnings:

No, you just have to follow the rules and define your message text files, build them into resources, link them to your app etc.
The example provided at MSDN leads you through everything you need to do.

Try this out, it's worked for me before..
http://www.codeproject.com/KB/system/xeventlog.aspx

Related

How to open windows' service-specific event log

We need to read service-specific event log "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" programmatically. Following code
LPWSTR pwsLogName = L"Microsoft-Windows-TerminalServices-LocalSessionManager/Operational";
HANDLE hEventLog = OpenEventLog(nullptr, pwsLogName);
results opening "Application" log instead of required.
In the same time command line utility wevtutil can succesfuly read needed log:
wevtutil query-events Microsoft-Windows-TerminalServices-LocalSessionManager/Operational
What are we doing wrong?
Finally we've found OpenEventLog() is dead and we need to use Evt* functions (EvtQuery & company)
The behaviour is by design; see: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openeventloga
Todo: check if registry key exists first, then use openEventLog() if succeeded.
_stprintf_s(szKeyName, _T("System\\CurrentControlSet\\Services\\EventLog\\%s"),szLogName);
dwRet = RegOpenKey(HKEY_LOCAL_MACHINE, szKeyName, &hKey);
if (ERROR_SUCCESS == dwRet)
{
RegCloseKey(hKey);
// continue with openEventLog()

InitiateShutdown fails with RPC_S_SERVER_UNAVAILABLE error for a remote computer

I'm trying to implement rebooting of a remote computer with InitiateShutdown API using the following code, but it fails with RPC_S_SERVER_UNAVAILABLE or 1722 error code:
//Process is running as administrator
//Select a remote machine to reboot:
//INFO: Tried it with and w/o two opening slashes.
LPCTSTR pServerName = L"192.168.42.105";
//Or use 127.0.0.1 if you don't have access to another machine on your network.
//This will attempt to reboot your local machine.
//In that case make sure to call shutdown /a /m \\127.0.0.1 to cancel it.
if(AdjustPrivilege(NULL, L"SeShutdownPrivilege", TRUE) &&
AdjustPrivilege(pServerName, L"SeRemoteShutdownPrivilege", TRUE))
{
int nErrorCode = ::InitiateShutdown(pServerName, NULL, 30,
SHUTDOWN_INSTALL_UPDATES | SHUTDOWN_RESTART, 0);
//Receive nErrorCode == 1722, or RPC_S_SERVER_UNAVAILABLE
}
BOOL AdjustPrivilege(LPCTSTR pStrMachine, LPCTSTR pPrivilegeName, BOOL bEnable)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
BOOL bRes = FALSE;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE;
if(LookupPrivilegeValue(pStrMachine, pPrivilegeName, &tkp.Privileges[0].Luid))
{
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
bRes = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
int nOSError = GetLastError();
if(bRes)
{
if(nOSError != ERROR_SUCCESS)
bRes = FALSE;
}
}
CloseHandle(hToken);
return bRes;
}
So to prepare for this code to run I do the following on this computer, which is Windows 7 Pro (as I would do for the Microsoft's shutdown tool):
Run the following "as administrator" to allow SMB access to the logged in user D1 on the 192.168.42.105 computer (per this answer):
NET USE \\192.168.42.105\IPC$ 1234 /USER:D1
Run the process with my code above "as administrator".
And then do the following on remote computer, or 192.168.42.105, that has Windows 7 Pro (per answer here with most upvotes):
Control Panel, Network and Sharing Center, Change Advanced Sharing settings
"Private" enable "Turn on File and Printer sharing"
Set the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
LocalAccountTokenFilterPolicy=dword:1
RUN secpol.msc, then go to Local Security Policy, Security Settings, Local Policies, User Rights Assignment. Add "Everyone" to "Force shutdown from a remote system". (Just remember to remove it after you're done testing!)
Note that the following shutdown command seems to work just fine to reboot the remote computer:
shutdown /r /m \\192.168.42.105 /t 30
What am I missing with my code?
EDIT:
OK. I will admit that I was merely interested in why InitiateShutdown doesn't seem to "want" to work with a remote server connection, while InitiateSystemShutdownEx or InitiateSystemShutdown had no issues at all. (Unfortunately the latter two did not have the dwShutdownFlags parameter, which I needed to pass the SHUTDOWN_INSTALL_UPDATES flag to, which caused my persistence...)
At this point I had no other way of finding out than dusting out a copy of WinDbg... I'm still trying to dig into it, but so far this is what I found...
(A) It turns out that InitiateSystemShutdownEx internally uses a totally different RPC call. W/o too many details, it initiates RPC binding with RpcStringBindingComposeW using the following parameters:
ObjUuid = NULL
ProtSeq = ncacn_np
NetworkAddr = \\192.168.42.105
EndPoint = \\PIPE\\InitShutdown
Options = NULL
or the following binding string:
ncacn_np:\\\\192.168.42.105[\\PIPE\\InitShutdown]
(B) While InitiateShutdown on the other hand uses the following binding parameters:
ObjUuid = 765294ba-60bc-48b8-92e9-89fd77769d91
ProtSeq = ncacn_ip_tcp
NetworkAddr = 192.168.42.105
EndPoint = NULL
Options = NULL
which it later translates into the following binding string:
ncacn_np:\\\\192.168.42.105[\\PIPE\\lsarpc]
that it uses to obtain the RPC handle that it passes to WsdrInitiateShutdown (that seems to have its own specification):
So as you see, the InitiateShutdown call is technically treated as Unknown RPC service (for the UUID {765294ba-60bc-48b8-92e9-89fd77769d91}), which later causes a whole bunch of credential checks between the server and the client:
which, honestly, I'm not sure I want to step into with a low-level debugger :)
At this stage I will say that I am not very well versed on "Local Security Authority" interface (or the \PIPE\lsarpc named pipe configuration.) So if anyone knows what configuration is missing on the server side to allow this RPC call to go through, I would appreciate if you could post your take on it?

Pebble JS app_message_outbox_send() in a for loop

I am using sdk2 for pebble, with the js appmessage features:
I am trying to send consecutive messages to pebble js on the phone, for each one of my menu items. A variable movie_count = 5 exists, and I use this for looping, It gets logged out as 5 as the code shows below, so it should be getting to all 5 , logging errors at least, but it just doesn't log anything after the first time:
static void up_click_handler(ClickRecognizerRef recognizer, void *context) {
int i;
APP_LOG(APP_LOG_LEVEL_DEBUG, "movie_count int %u", movie_count);
for(i = 0;i<movie_count;i++){
Tuplet build_menu_tuple = TupletInteger(BUILD_MENU_KEY, 1); // just a flag for the appmessage js code
Tuplet menu_id_tuple = TupletInteger(MENU_ID_KEY, i);
DictionaryIterator *iter;
app_message_outbox_begin(&iter);
if (iter == NULL) {
return;
}
dict_write_tuplet(iter, &build_menu_tuple);
dict_write_tuplet(iter, &menu_id_tuple);
dict_write_end(iter);
app_message_outbox_send();
}
}
in JS appmessage
this code in the js is executed, although only once, I have logged the output in my in_receiver() callback in my watchapp, and my first item gets logged, but the logger just quits after that... Is this because the watchapp cannnot send blutooth messages in a loop like this? Is there a way to make sure the message is sent, or pause the execution so it sends at a slower pace? (the movies_json exists above the code below, i left it out for brevity, but it is there, a json object with an inner array of movies)
if(e.payload.build_menu){
var menu_id = e.payload.menu_id;
console.log("menu_id" + menu_id);
Pebble.sendAppMessage({"title":movies_json.movies[menu_id].title,
"stars":movies_json.movies[menu_id].stars,
"menu_id":menu_id
});
console.log("movie title:" + movies_json.movies[i].title);
}
in_recived_handler callback code to handle messages from the js
this code is in the callback that takes in messsages from the phones js... it only gets to the first item, logs just the first item's menu_id and title, and then logging just stops.
if(menu_id_tuple){
int menu_id;
menu_id = menu_id_tuple->value->int32;
char movie_title[30];
strncpy(movie_title, movie_title_tuple->value->cstring, 30);
APP_LOG(APP_LOG_LEVEL_DEBUG, "In received handler movie_title: %s" , movie_title);
APP_LOG(APP_LOG_LEVEL_DEBUG, "In received handler menu_id: %u" , menu_id);
}
You need to wait until the first message is sent to send the next one.
The proper way to do this is to register a callback for the outbox_sent event and to queue the next message in this event.
Explanation
There is only one bluetooth buffer on pebble and it can only hold one message at a time. If you send messages in a for loop, this buffer gets filled with the first message and all the other messages are rejected.
You would see the error messages if you checked the return value of app_message_outbox_send(). You should also implement a AppMessageOutboxFailed handler.

How to add synchronisation right in a SDDL string for CreateEvent

My Windows service creates 2 Events with CreateEvent for communication with a user app.
The service and the user app are not running under the same user account.
The user app opens the event and set it to signaled without error. But the event is never received by the service. The other event works in the opposite direction.
So I think the events miss the syncronization right.
Service:
SECURITY_ATTRIBUTES security;
ZeroMemory(&security, sizeof(security));
security.nLength = sizeof(security);
ConvertStringSecurityDescriptorToSecurityDescriptor(L"D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GWGR;;;IU)", SDDL_REVISION_1, &security.lpSecurityDescriptor, NULL);
EvtCreateNewUserSession = CreateEventW(
&security, // security attributes
TRUE, // manual-reset event
FALSE, // initial state is not signaled
L"Global\\MyEvent" // object name
);
Interactive App:
HANDLE EvtCreateNewUserSession = OpenEventW(
EVENT_MODIFY_STATE | SYNCHRONIZE, // default security attributes
FALSE, // initial state is not signaled
L"Global\\MyEvent" // object name
;
Thanks for your help,
Olivier
Instead of using 'string SDDL rights' (like GA) use 0xXXXXXXXX format (you can combine flags and then convert them to hex-string).
For example this SDDL: D:(A;;0x001F0003;;;BA)(A;;0x00100002;;;AU) creates DACL for:
- BA=Administrators, 0x001F0003=EVENT_ALL_ACCESS (LocalSystem and LocalService are in Administrators group, but NetworkService is not)
- AU=Authenticated Users, 0x00100002=SYNCHRONIZE | EVENT_MODIFY_STATE
http://msdn.microsoft.com/en-us/library/windows/desktop/aa374928(v=vs.85).aspx - field rights
A string that indicates the access rights controlled by the ACE.
This string can be a hexadecimal string representation of the access rights,
such as "0x7800003F", or it can be a concatenation of the following strings.
...

Worklight 5.0.6 : Ajax request exception: Form too large while sending large data to data adapter

My question is relatively the same than the one posted on developerworks forum (forum is read only due to migration) wich is :
I have a http adapter that interfaces with external web services. Part
of the payload is audio, and images. We're hitting a form size limit.
Please see attached exception at end of this post. I've read on
previous posts that jetty configurations need to be adjusted to
accommodate the larger payload. We want to control this size limit at
the server side application layer, and thought that of creating a
jetty-web.xml to define the max form size:
400000
In Worklight is this the proper approach to resolve this issue?
If this is the proper approach can you provide details whether the
jetty-web.xml should be placed under server/conf, or does it need to
be under WEB-INF of the application war?
If the file needs to be placed under WEB-INF can you explain how to
accomplish this file being placed under WEB-INF during the WL project
build.
Thanks E: Ajax request exception: Form too large802600>200000
2013-02-06 11:39:48 FWLSE0117E: Error code: 1, error description:
INTERNAL_ERROR, error message: FWLSE0069E: An internal error occurred
during gadget request Form too large802600>200000, User Identity
{wl_authenticityRealm=null, GersServiceAdapterRealm=(name:USAEMP4,
loginModule:GersServiceAdapterLoginModule),
wl_remoteDisableRealm=(name:NullLoginModule,
loginModule:NullLoginModule), SampleAppRealm=null,
wl_antiXSRFRealm=(name:antiXSRF, loginModule:WLAntiXSRFLoginModule),
wl_deviceAutoProvisioningRealm=null, WorklightConsole=null,
wl_deviceNoProvisioningRealm=(name:device,
loginModule:WLDeviceNoProvisioningLoginModule),
myserver=(name:3e857b6a-d2f6-40d1-8c9c-10ca1b96c8df,
loginModule:WeakDummy),
wl_anonymousUserRealm=(name:3e857b6a-d2f6-40d1-8c9c-10ca1b96c8df,
loginModule:WeakDummy)}.
I have exactly the same problem :
I send a large amount of data to a worklight adapter and my application fail with the following error message into the log :
2013-08-21 09:48:17] FWLSE0020E: Ajax request exception: Form too large202534>200000
[2013-08-21 09:48:18] FWLSE0117E: Error code: 1, error description: INTERNAL_ERROR, error message: FWLSE0069E: An internal error occurred during gadget request Form too large202534>200000, User Identity {wl_authenticityRealm=null, wl_remoteDisableRealm=(name:null, loginModule:NullLoginModule), SampleAppRealm=null, wl_antiXSRFRealm=(name:b2isf3704k2fl8hovpa6lv9mig, loginModule:WLAntiXSRFLoginModule), wl_deviceAutoProvisioningRealm=null, WorklightConsole=null, wl_deviceNoProvisioningRealm=(name:40a24da9-0a32-464a-8dec-2ab402c683ae, loginModule:WLDeviceNoProvisioningLoginModule), myserver=(name:2b1a7864-37c4-47f0-9f5c-49621b6915b5, loginModule:WeakDummy), wl_anonymousUserRealm=(name:2b1a7864-37c4-47f0-9f5c-49621b6915b5, loginModule:WeakDummy)}.
This occurs on calling an adapter procedure by calling WL.Client.invokeProcedure(...) and before the first line of the called procedure... If I try to log the start of the called procedure I have nothing written in my debug log...
I can give you my source code :
This one is called by a dhtml user event (onclick) :
// Construct the param to pass to the WL adapter insert procedure
var paramObject = {
QCDART: machine, // machine is a javascript variable as long int
QTITRE: title, // title is a javascript variable as string(255)
QDESC: desc, // desc is a javascript variable as string(255)
QHODAT: todayDateDb2IntFormat, // todayDateDb2IntFormat is a javascript variable as long int
QACTIF: active, // active is a javascript variable as int
SSRCFIC: currentPdfFileDataBase64, // currentPdfFileDataBase64 is a javascript variable as base64 encoded string from a binary file > 150 ko approx.
SMIMFIC: 'application/pdf',
SSIZFIC: currentPdfFileSize // currentPdfFileSize is a javascript variable as long int
};
// Construct adapter invocation data
var invocationData = {
adapter : 'IseriesDB2Backend', // adapter name
procedure : 'addModeleReleves', // procedure name
parameters : [paramObject] // parameters if any
};
WL.Client.invokeProcedure(invocationData, {
timeout: 60000,
onSuccess: function() {
// Notify success
alert('OK');
}, // invokeProcedure success callback
onFailure: function(invocationResult) {
alert('ERROR');
} // invokeProcedure failure callback
});
This one is my adapter source code :
var addModeleReleveStatement = WL.Server.createSQLStatement("select QCDDOC from FINAL TABLE (insert into ERIHACFICH.DOCENTQ (QCDART, QTITRE, QDESC, QHODAT, QACTIF) values (?, ?, ?, ?, ?))");
function addModeleReleves(params) {
WL.Logger.debug('Starting adapter procedure...');
var modeleReleveResult = WL.Server.invokeSQLStatement({
preparedStatement : addModeleReleveStatement,
parameters : [params.QCDART, params.QTITRE, params.QDESC, params.QHODAT, params.QACTIF]
});
if(modeleReleveResult.isSuccessful) {
WL.Logger.debug('Success !');
}
WL.Logger.debug('Adapter procedure ended !');
// Return result (with the last id inside)
return modeleReleveResult;
}
if the javascript varable called currentPdfFileDataBase64 is small, all is working normally but if it exceeds approximatively 200000 chars length it fails...
Last, I ca say that the problem occurs in development environment (WL Studio 5.0.6 + WL Server 5.0.6), I didn't test it on the production environment based on SLES + Websphere application server 7 + worklight.
Thanks for any help
I understand you are using the test server provided by Worklight.
It looks like this is a Jetty limitation so you could try any of these:
1) Set the system property org.eclipse.jetty.server.Request.maxFormContentSize to a bigger value (i.e. adding -Dorg.eclipse.jetty.server.Request.maxFormContentSize=25000000) to the end of eclipse.ini before launching Worklight.
or
2) Instead, set this other system property -Dorg.mortbay.jetty.Request.maxFormContentSize=25000000 to the same place.
Another way to solve the problem was to use WL Studio version 6 that doesn't use Jetty anymore as test environment

Resources