Confused by failuer of CDialog::Create() - mfc

ZTRACE_RUNTIME("Creating Processing Panel");
BOOL result = processingDlg.Create(IDD_PROCESSING);
if (FALSE == result)
{
int lastErr = GetLastError();
ZTRACE_RUNTIME("lastErr = %d", lastErr);
}
This is a debug build.
Problems:
I can't step into Create using F11???
Result was set to 0, so GetLastError was invoked, but that returned 0!
What am I doing wrong?

Related

How Do I Use NotifyServiceStatusChange to Get Notified When a Service Is Deleted?

How can I use NotifyServiceStatusChange properly so I can get notified when the service specified is deleted? My current code successfully stops the service and marks it for deletion. However, I want to be notified when the service is fully deleted.
Here are the main points of my code:
SC_HANDLE SCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
HANDLE EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
SERVICE_NOTIFY ServiceNotify;
ServiceNotify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
ServiceNotify.pszServiceNames = ServiceName;
ServiceNotify.pContext = &EventHandle;
ServiceNotify.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)CallbackFunction;
DWORD status = NotifyServiceStatusChangeW(SCManager, SERVICE_NOTIFY_DELETED, &ServiceNotify);
WaitForSingleObject(EventHandle, INFINITE);
CloseServiceHandle(SCManager);
CloseHandle(EventHandle);
(ServiceName is WCHAR*)
CallbackFunction code:
VOID CALLBACK CallbackFunction(IN PVOID pParameter) {
SERVICE_NOTIFY* ServiceNotify = pParameter;
HANDLE EventHandle = *(HANDLE*)ServiceNotify->pContext;
SetEvent(EventHandle);
}
NotifyServiceStatusChange is returning ERROR_SUCCESS (0). However, my callback function is not being called at all. How can I fix this?
Edit:
Here is minimal reproducible code:
void ErrorExit(char* FunctionName, unsigned long ErrorCode) {
char* ErrorMessage;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, ErrorCode, LANG_USER_DEFAULT, (LPTSTR)&ErrorMessage, 0, NULL);
int MessageSize = (strlen(ErrorMessage) + strlen(FunctionName) + 50) * sizeof(char);
char* FullMessage = malloc(MessageSize);
sprintf_s(FullMessage, MessageSize, "%s failed with error %d: %s", FunctionName, ErrorCode, ErrorMessage);
MessageBoxA(NULL, FullMessage, "Error", MB_OK);
ExitProcess(ErrorCode);
}
PFN_SC_NOTIFY_CALLBACK CallbackFunction(PVOID pParameter) {
printf("CallbackFunction has been called.\r\n");
SERVICE_NOTIFY* ServiceNotify = pParameter;
HANDLE EventHandle = ServiceNotify->pContext;
if (!SetEvent(EventHandle)) {
ErrorExit("SetEvent", GetLastError());
}
}
int main()
{
WCHAR* ServiceName = L"SERVICE NAME"; // Input service name here
SC_HANDLE SCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
if (!SCManager) {
ErrorExit("OpenSCManagerW", GetLastError());
}
SC_HANDLE ServiceHandle = OpenServiceW(SCManager, ServiceName,
SERVICE_ENUMERATE_DEPENDENTS | SERVICE_STOP | DELETE);
if (!ServiceHandle) {
ErrorExit("ServiceHandle", GetLastError());
}
if (!DeleteService(ServiceHandle)) {
ErrorExit("DeleteService", GetLastError());
}
if (!CloseServiceHandle(ServiceHandle)) {
ErrorExit("CloseServiceHandle", GetLastError());
}
HANDLE EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!EventHandle) {
ErrorExit("CreateEventW", GetLastError());
}
SERVICE_NOTIFY ServiceNotify;
ServiceNotify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
ServiceNotify.pszServiceNames = ServiceName;
ServiceNotify.pContext = EventHandle;
ServiceNotify.pfnNotifyCallback = CallbackFunction;
DWORD status = NotifyServiceStatusChangeW(SCManager, SERVICE_NOTIFY_DELETED, &ServiceNotify);
if (status != ERROR_SUCCESS) {
ErrorExit("NotifyServiceStatusChangeW", GetLastError());
}
status = WaitForSingleObjectEx(EventHandle, INFINITE, TRUE);
if (status == WAIT_FAILED) {
ErrorExit("WaitForSingleObjectEx", GetLastError());
}
printf("WaitForSingleObjectEx Result: %lu\r\n", status);
system("pause");
return 0;
}
When I run this, no other service depends on the service being deleted, and the service being deleted is already stopped. My error handling function "ErrorExit" is never called. Nothing is printed on the screen. My program simply pauses, which I assume is from WaitForSingleObjectEx.
I know the service is being deleted because I have ProcessHacker open, and it is giving me notifications that the service is being deleted.
NotifyServiceStatusChange is returning ERROR_SUCCESS (0). However, my callback function is not being called at all.
The NotifyServiceStatusChangeW documentation says:
When the service status changes, the system invokes the specified callback function as an asynchronous procedure call (APC) queued to the calling thread. The calling thread must enter an alertable wait (for example, by calling the SleepEx function) to receive notification. For more information, see Asynchronous Procedure Calls.
So, make sure you are actually processing APC notifications while you wait. WaitForSingleObject() will not do that for you.
Use WaitForSingleObjectEx() instead. It has a bAlertable parameter you can set to TRUE. You will have to call it in a loop, since it will return when any APC call is processed by the calling thread, which may not be the one you are expecting.
You also need to call NotifyServiceStatusChangeW() in a loop, too. The documentation does not mention this, but the callback will be called only 1 time per use. Once the callback is called, you need to call NotifyServiceStatusChangeW() again to receive another notification if the current one is not the event you are expecting.
With that said, try something more like this:
struct MyCallbackInfo {
HANDLE EventHandle;
LPCWSTR pszServiceName;
bool bDeleted;
};
...
VOID CALLBACK CallbackFunction(PVOID pParameter) {
SERVICE_NOTIFYW* ServiceNotify = (SERVICE_NOTIFYW*) pParameter;
MyCallbackInfo *ci = (MyCallbackInfo*) ServiceNotify->pContext;
if (ServiceNotify->dwNotificationStatus == ERROR_SUCCESS) {
LPWSTR pServiceName = ServiceNotify->pszServiceNames;
while (*pServiceName != L'\0') {
if (lstrcmpW(pServiceName, ci->pszServiceName) == 0) {
ci.bDeleted = true;
break;
}
pServiceName += (lstrlenW(pServiceName) + 1);
}
LocalFree(ServiceNotify->pszServiceNames);
}
SetEvent(ci->EventHandle);
}
...
MyCallbackInfo ci;
ci.EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
ci.pszServiceName = ServiceName;
ci.bDeleted = false;
if (!ci.EventHandle) {
// error handling...
}
SC_HANDLE SCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
if (!SCManager) {
// error handling...
}
SERVICE_NOTIFYW ServiceNotify = {};
ServiceNotify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
ServiceNotify.pContext = &ci;
ServiceNotify.pfnNotifyCallback = CallbackFunction;
DWORD status;
do {
status = NotifyServiceStatusChangeW(SCManager, SERVICE_NOTIFY_DELETED, &ServiceNotify);
if (status != ERROR_SUCCESS) {
// error handling...
}
while ((status = WaitForSingleObjectEx(ci.EventHandle, INFINITE, TRUE)) == WAIT_IO_COMPLETION);
if (status == WAIT_FAILED) {
// error handling...
}
if (ci.bDeleted) {
// service has been deleted ...
break;
}
ResetEvent(ci.EventHandle);
}
while (true);
CloseServiceHandle(SCManager);
CloseHandle(ci.EventHandle);

Why does GetExitCodeThread() return FALSE here?

I have a small test code. My assumption is in below code, since I didn't set flag to stop the thread, then in the line of GetExitCodeThread(). it should return TRUE and return code is STILL_ACTIVE.
While in actual test, the result is:
Every time, the return value of GetExitCodeThread() is FALSE, so in main(), the while loop never entered. Could somebody please tell me the reason? What's wrong in my code. Thanks.
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "afxwin.h"
bool bExit = false;
HANDLE hOriginalThread;
static UINT ThreadFunc(LPVOID pParam)
{
int iCount = 0;
printf("start thread--ThreadFunc\n");
printf("Thread loop start: --ThreadFunc");
while (!bExit)
{
iCount++;
if (iCount % 50 == 0)
printf(".");
}
printf("Thread loop end: %d--ThreadFunc\n", iCount++);
printf("end thread--ThreadFunc\n");
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
hOriginalThread = AfxBeginThread(ThreadFunc, (LPVOID)0, THREAD_PRIORITY_NORMAL, 0, 0);
Sleep(500);
DWORD dwEC;
int iTry = 0;
BOOL bStatus;
bStatus = GetExitCodeThread(hOriginalThread, &dwEC);
if (!bStatus)
{
printf("error GetExitCodeThread: %d--Main\n", GetLastError());
}
while (bStatus && dwEC == STILL_ACTIVE)
{
printf("Check Thread in active: %d--Main\n", iTry);
Sleep(1);
iTry++;
if (iTry>5)
{
printf("Try to terminate Thread loop: %d--Main\n", iTry++);
TerminateThread(hOriginalThread, 0);// Force thread exit
}
bStatus = GetExitCodeThread(hOriginalThread, &dwEC);
}
hThread = NULL;
printf("End Main --Main\n");
return 0;
}
AfxBeginThread() returns a CWinThread* object pointer, not a Win32 HANDLE like CreateThread() does. So GetExitCodeThread() fails due to an invalid thread handle, which GetLastError() should have told you.
CWinThread has an operator HANDLE() to get the proper Win32 handle of the thread, eg:
CWinThread *pThread = AfxBeginThread(...);
if (!pThread) ... // error handling
hOriginalThread = *pThread;
The reason your code even compiles is because you are likely not compiling with STRICT Type Checking enabled, so HANDLE is just a simple void*, which any kind of pointer can be assigned to. If you enable STRICT, HANDLE will not be void* and assigning the return value of AfxBeginThread() directly to hOriginalThread will cause a compiler error due to a type incompatibility.

How can I update PROC_THREAD_ATTRIBUTE_LIST for my process?

Say, when my process was created using STARTUPINFOEX struct and the PROC_THREAD_ATTRIBUTE_LIST member:
DWORD ProtectionLevel = PROTECTION_LEVEL_SAME;
SIZE_T AttributeListSize;
STARTUPINFOEXW StartupInfoEx = { 0 };
StartupInfoEx.StartupInfo.cb = sizeof(StartupInfoEx);
InitializeProcThreadAttributeList(NULL, 1, 0, &AttributeListSize)
StartupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc(
GetProcessHeap(),
0,
AttributeListSize
);
if (InitializeProcThreadAttributeList(StartupInfoEx.lpAttributeList,
1,
0,
&AttributeListSize) == FALSE)
{
Result = GetLastError();
goto exitFunc;
}
if (UpdateProcThreadAttribute(StartupInfoEx.lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_PROTECTION_LEVEL,
&ProtectionLevel,
sizeof(ProtectionLevel),
NULL,
NULL) == FALSE)
{
Result = GetLastError();
goto exitFunc;
}
PROCESS_INFORMATION ProcessInformation = { 0 };
if (CreateProcessW(ApplicationName,
CommandLine,
ProcessAttributes,
ThreadAttributes,
InheritHandles,
EXTENDED_STARTUPINFO_PRESENT | CREATE_PROTECTED_PROCESS,
Environment,
CurrentDirectory,
(LPSTARTUPINFOW)&StartupInfoEx,
&ProcessInformation) == FALSE)
{
Result = GetLastError();
goto exitFunc;
}
How can I update that attribute list for my own process?
For instance, I want to modify my own process' PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY to prevent it from creating any child processes.
This doesn't answer my question entirely. It's a follow-up to the comments thread for my original post above.
So just for disabling creation of child processes (similar to PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY) one can enable this feature for their own process as such:
DWORD dwNoChild = 1;
BOOL bResult = ::SetProcessMitigationPolicy((PROCESS_MITIGATION_POLICY)13 /*ProcessChildProcessPolicy*/,
&dwNoChild, sizeof(dwNoChild));
Note that your process doesn't have to be elevated for this to work.
(Don't hold me to it, but I think that ProcessChildProcessPolicy flag is supported on Windows 10 only.)

GetWindow(GetForegroundWindow() fails

So far I tried to use GetWindow using GetForegroundWindow and this always returns NULL. when I use The GetLastError I have a msg saying 1400, Invalid windows Handle.
When I first debug I have Null as I said befor, but when I redo the execution I have a valid handle and all work fine.
What could be the problem.
static int CheckZOrder2Windows(HWND FirstWindow, HWND SecondWindow)
{
int zOrderWnd1 = -1, zOrderWnd2 =-1;
HWND tempHwnd = GetWindow(GetForegroundWindow(), GW_HWNDFIRST);
if (!tempHwnd)
ErrorExit(TEXT(""));
DWORD dwFGThread1 = GetWindowThreadProcessId(FirstWindow, NULL);
DWORD dwFGThread2 = GetWindowThreadProcessId(SecondWindow, NULL);
int currentOrder = 0;
DWORD dwFGThread = 0;
while(tempHwnd)
{
++currentOrder;
if(IsWindowVisible(tempHwnd))
{
dwFGThread = GetWindowThreadProcessId(tempHwnd, NULL);
if (dwFGThread == dwFGThread1)
zOrderWnd1 = currentOrder;
else if (dwFGThread == dwFGThread2)
zOrderWnd2 = currentOrder;
}
tempHwnd=GetWindow(tempHwnd,GW_HWNDNEXT);
}
if ((zOrderWnd1 == -1) || (zOrderWnd2 == -1))
return 0;
return (zOrderWnd1 - zOrderWnd2);
}
GetForegroundWindow is allowed to return NULL and you never check for that.
MSDN also says:
The Enum[Child]Windows function is more reliable than calling GetWindow in a loop. An application that calls GetWindow to perform this task risks being caught in an infinite loop or referencing a handle to a window that has been destroyed.

Sending http request repeatedly, more fast (async mode)

I need to send one request to server more quickly and repeatedly.
So I implemented code like this.
BOOL CTestDlg::OnInitDialog()
{
...
m_hInstance = InternetOpen(L"asynchttp", INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,INTERNET_FLAG_ASYNC);
if(m_hInstance == NULL)
{
ErrorLog(L"InternetOpen Failed");
return TRUE;
}
if (InternetSetStatusCallback(m_hInstance,(INTERNET_STATUS_CALLBACK)&Callback) == INTERNET_INVALID_STATUS_CALLBACK)
{
ErrorLog(L"Set Callback Function Failed");
return TRUE;
}
m_hConnect = InternetConnect(m_hInstance, L"192.168.2.116", 8080,NULL,NULL,INTERNET_SERVICE_HTTP,INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_KEEP_CONNECTION,1);
if(m_hConnect == NULL)
{
if(DWORD dwError = GetLastError() != ERROR_IO_PENDING)
{
ErrorLog(L"Fail to Connect Server");
return TRUE;
}
WaitForSingleObject(hConnectedEvent, INFINITE);
}
CreateThread(0 , 0 , (LPTHREAD_START_ROUTINE)SendThread , 0 , 0 , 0);
return TRUE;
}
void __stdcall Callback(HINTERNET hInternet,DWORD dwContext,DWORD dwInternetStatus,LPVOID lpStatusInfo,DWORD dwStatusInfoLen)
{
switch(dwContext)
{
case 1:
{
SetEvent(hConnectedEvent);
}
break;
}
}
DWORD SendThread(LPVOID lpParam)
{
TCHAR *szAceptType[] = {_T("*/*") , NULL};
CString szContentType = _T("Content-Type: application/x-www-form-urlencoded\r\n");
char szPostData[MAX_PATH];
sprintf(szPostData , "num=1234&str=3240");
HINTERNET hRequest = HttpOpenRequest(m_hConnect, L"POST", L"/TestWeb/index.jsp", HTTP_VERSION , NULL , (LPCTSTR*)szAceptType , 0, 2);
while(1)
{
try
{
if (!HttpSendRequest(hRequest, szContentType, (DWORD)szContentType.GetLength(), szPostData,(DWORD)strlen(szPostData)))
{
if (DWORD dwError = GetLastError() != ERROR_IO_PENDING)
ErrorLog(L"SendRequest: Error = %d" , dwError);
}
}
catch (CException* e)
{
UNREFERENCED_PARAMETER(e);
}
Sleep(100);
}
return 0;
}
When execute or debug program, I saw this "SendRequest; Error = 1" log frequently.
And Server does not record anymore to database , after one or two request data recorded
It seems like HttpSendRequest API doesn't work correctly after error occured.
I aim to send one request to server more fast and more correctly, without loss.
Please teach me what is wrong problem.
Or if you got another best way, then please tell me.
Thanks.
Error code 1 is "Invalid Parameter".
You appear to be mixing ASCII (char and sprintf) and Unicode strings in your sample above. Have you tried with all Unicode strings (making szPostData a WCHAR array)? From MSDN: "There two versions of HttpSendRequest —HttpSendRequestA (used with ANSI builds) and HttpSendRequestW (used with Unicode builds)". It goes on to talk about when ERROR_INVALID_PARAMETER is returned. http://msdn.microsoft.com/en-us/library/windows/desktop/aa384247(v=vs.85).aspx
Also, I haven't used MFC in a long time, but I remember that you should call e->Delete() in your exception handler (unless you re-throw). The CException::Delete method will delete any thrown exception created on the heap (and do nothing otherwise).