/* IntHookModuleUnloaded: Sends a internal message to all threads of the requested desktop and notifies them that a global hook was destroyed and an injected module must be unloaded. As a result, IntLoadHookModule will be called for all the threads that will receive the special purpose internal message. */ BOOL IntHookModuleUnloaded(PDESKTOP pdesk, int iHookID, HHOOK hHook) { PTHREADINFO ptiCurrent; PLIST_ENTRY ListEntry; PPROCESSINFO ppiCsr; TRACE("IntHookModuleUnloaded: iHookID=%d\n", iHookID); ppiCsr = PsGetProcessWin32Process(gpepCSRSS); ListEntry = pdesk->PtiList.Flink; while(ListEntry != &pdesk->PtiList) { ptiCurrent = CONTAINING_RECORD(ListEntry, THREADINFO, PtiLink); /* FIXME: Do some more security checks here */ /* FIXME: The first check is a reactos specific hack for system threads */ if(!PsIsSystemProcess(ptiCurrent->ppi->peProcess) && ptiCurrent->ppi != ppiCsr) { if(ptiCurrent->ppi->W32PF_flags & W32PF_APIHOOKLOADED) { TRACE("IntHookModuleUnloaded: sending message to PID %p, ppi=%p\n", PsGetProcessId(ptiCurrent->ppi->peProcess), ptiCurrent->ppi); co_MsqSendMessageAsync( ptiCurrent, 0, iHookID, TRUE, (LPARAM)hHook, NULL, 0, FALSE, MSQ_INJECTMODULE); } } ListEntry = ListEntry->Flink; } return TRUE; }
/* API Call */ BOOL FASTCALL IntAllowSetForegroundWindow(DWORD dwProcessId) { PPROCESSINFO ppi, ppiCur; PEPROCESS Process = NULL; ppi = NULL; if (dwProcessId != ASFW_ANY) { if (!NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)dwProcessId, &Process))) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } ppi = PsGetProcessWin32Process(Process); if (!ppi) { ObDereferenceObject(Process); return FALSE; } } ppiCur = PsGetCurrentProcessWin32Process(); if (!CanForceFG(ppiCur)) { if (Process) ObDereferenceObject(Process); EngSetLastError(ERROR_ACCESS_DENIED); return FALSE; } if (dwProcessId == ASFW_ANY) { // All processes will be enabled to set the foreground window. ptiLastInput = NULL; } else { // Rule #3, last input event in force. ERR("Fixme: ptiLastInput is SET!!\n"); //ptiLastInput = ppi->ptiList; ObDereferenceObject(Process); } return TRUE; }
BOOL FASTCALL UserRegisterUserApiHook( PUNICODE_STRING pstrDllName, PUNICODE_STRING pstrFuncName) { PTHREADINFO pti, ptiCurrent; HWND *List; PWND DesktopWindow, pwndCurrent; ULONG i; PPROCESSINFO ppiCsr; pti = PsGetCurrentThreadWin32Thread(); ppiCsr = PsGetProcessWin32Process(gpepCSRSS); /* Fail if the api hook is already registered */ if(gpsi->dwSRVIFlags & SRVINFO_APIHOOK) { return FALSE; } TRACE("UserRegisterUserApiHook. Server PID: %p\n", PsGetProcessId(pti->ppi->peProcess)); /* Register the api hook */ gpsi->dwSRVIFlags |= SRVINFO_APIHOOK; strUahModule = *pstrDllName; strUahInitFunc = *pstrFuncName; ppiUahServer = pti->ppi; /* Broadcast an internal message to every top level window */ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()); List = IntWinListChildren(DesktopWindow); if (List != NULL) { for (i = 0; List[i]; i++) { pwndCurrent = UserGetWindowObject(List[i]); if(pwndCurrent == NULL) { continue; } ptiCurrent = pwndCurrent->head.pti; /* FIXME: The first check is a reactos specific hack for system threads */ if(PsIsSystemProcess(ptiCurrent->ppi->peProcess) || ptiCurrent->ppi == ppiCsr) { continue; } co_MsqSendMessageAsync( ptiCurrent, 0, WH_APIHOOK, FALSE, /* Load the module */ 0, NULL, 0, FALSE, MSQ_INJECTMODULE); } ExFreePoolWithTag(List, USERTAG_WINDOWLIST); } return TRUE; }
NTSTATUS APIENTRY Win32kProcessCallback(struct _EPROCESS *Process, BOOLEAN Create) { PPROCESSINFO ppiCurrent, *pppi; NTSTATUS Status; ASSERT(Process->Peb); UserEnterExclusive(); if (Create) { SIZE_T ViewSize = 0; LARGE_INTEGER Offset; PVOID UserBase = NULL; PRTL_USER_PROCESS_PARAMETERS pParams = Process->Peb->ProcessParameters; /* We might be called with an already allocated win32 process */ ppiCurrent = PsGetProcessWin32Process(Process); if (ppiCurrent != NULL) { /* There is no more to do for us (this is a success code!) */ Status = STATUS_ALREADY_WIN32; goto Leave; } /* Allocate a new win32 process */ ppiCurrent = ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESSINFO), USERTAG_PROCESSINFO); if (ppiCurrent == NULL) { ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n", HandleToUlong(Process->UniqueProcessId)); Status = STATUS_NO_MEMORY; goto Leave; } RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO)); PsSetProcessWin32Process(Process, ppiCurrent, NULL); #if DBG DbgInitDebugChannels(); #if KDBG KdRosRegisterCliCallback(DbgGdiKdbgCliCallback); #endif #endif TRACE_CH(UserProcess,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent, HandleToUlong(Process->UniqueProcessId)); /* map the global heap into the process */ Offset.QuadPart = 0; Status = MmMapViewOfSection(GlobalUserHeapSection, PsGetCurrentProcess(), &UserBase, 0, 0, &Offset, &ViewSize, ViewUnmap, SEC_NO_CHANGE, PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */ if (!NT_SUCCESS(Status)) { TRACE_CH(UserProcess,"Failed to map the global heap! 0x%x\n", Status); goto Leave; } ppiCurrent->HeapMappings.Next = NULL; ppiCurrent->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap; ppiCurrent->HeapMappings.UserMapping = UserBase; ppiCurrent->HeapMappings.Count = 1; InitializeListHead(&ppiCurrent->MenuListHead); InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList); InitializeListHead(&ppiCurrent->GDIDcAttrFreeList); InitializeListHead(&ppiCurrent->PrivateFontListHead); ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock); InitializeListHead(&ppiCurrent->DriverObjListHead); ExInitializeFastMutex(&ppiCurrent->DriverObjListLock); ppiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout(); if (!EngCreateEvent((PEVENT *)&ppiCurrent->InputIdleEvent)) { KeBugCheck(0); } KeInitializeEvent(ppiCurrent->InputIdleEvent, NotificationEvent, FALSE); /* map the gdi handle table to user land */ Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process); Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT; pParams = Process->Peb->ProcessParameters; ppiCurrent->peProcess = Process; /* setup process flags */ ppiCurrent->W32PF_flags = W32PF_THREADCONNECTED; if ( pParams && pParams->WindowFlags & STARTF_SCRNSAVER ) { ppiScrnSaver = ppiCurrent; ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER; } // Fixme check if this process is allowed. ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application it will get toggled off. /* Create pools for GDI object attributes */ ppiCurrent->pPoolDcAttr = GdiPoolCreate(sizeof(DC_ATTR), 'acdG'); ppiCurrent->pPoolBrushAttr = GdiPoolCreate(sizeof(BRUSH_ATTR), 'arbG'); ppiCurrent->pPoolRgnAttr = GdiPoolCreate(sizeof(RGN_ATTR), 'agrG'); ASSERT(ppiCurrent->pPoolDcAttr); ASSERT(ppiCurrent->pPoolBrushAttr); ASSERT(ppiCurrent->pPoolRgnAttr); /* Add the process to the global list */ ppiCurrent->ppiNext = gppiList; gppiList = ppiCurrent; } else { /* Get the Win32 Process */ ppiCurrent = PsGetProcessWin32Process(Process); ASSERT(ppiCurrent); TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent); ppiCurrent->W32PF_flags |= W32PF_TERMINATED; if (ppiScrnSaver == ppiCurrent) ppiScrnSaver = NULL; if (ppiCurrent->InputIdleEvent) { EngFreeMem(ppiCurrent->InputIdleEvent); ppiCurrent->InputIdleEvent = NULL; } IntCleanupMenus(Process, ppiCurrent); IntCleanupCurIcons(Process, ppiCurrent); GDI_CleanupForProcess(Process); co_IntGraphicsCheck(FALSE); /* * Deregister logon application automatically */ if(LogonProcess == ppiCurrent) { LogonProcess = NULL; } /* Close the startup desktop */ if(ppiCurrent->rpdeskStartup) ObDereferenceObject(ppiCurrent->rpdeskStartup); if(ppiCurrent->hdeskStartup) ZwClose(ppiCurrent->hdeskStartup); /* Close the current window station */ UserSetProcessWindowStation(NULL); /* Destroy GDI pools */ GdiPoolDestroy(ppiCurrent->pPoolDcAttr); GdiPoolDestroy(ppiCurrent->pPoolBrushAttr); GdiPoolDestroy(ppiCurrent->pPoolRgnAttr); if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL; pppi = &gppiList; while (*pppi != NULL && *pppi != ppiCurrent) pppi = &(*pppi)->ppiNext; ASSERT(*pppi == ppiCurrent); *pppi = ppiCurrent->ppiNext; TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent); #if DBG if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL)) { DbgUserDumpHandleTable(); } #endif /* Free the PROCESSINFO */ PsSetProcessWin32Process(Process, NULL, ppiCurrent); ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO); } Status = STATUS_SUCCESS; Leave: UserLeave(); return Status; }