HRESULT STDMETHODCALLTYPE DnCLRDataTarget_GetThreadContext( _In_ ICLRDataTarget *This, _In_ ULONG32 threadID, _In_ ULONG32 contextFlags, _In_ ULONG32 contextSize, _Out_ BYTE *context ) { NTSTATUS status; HANDLE threadHandle; CONTEXT buffer; if (contextSize < sizeof(CONTEXT)) return E_INVALIDARG; memset(&buffer, 0, sizeof(CONTEXT)); buffer.ContextFlags = contextFlags; if (NT_SUCCESS(status = PhOpenThread(&threadHandle, THREAD_GET_CONTEXT, UlongToHandle(threadID)))) { status = PhGetThreadContext(threadHandle, &buffer); NtClose(threadHandle); } if (NT_SUCCESS(status)) { memcpy(context, &buffer, sizeof(CONTEXT)); return S_OK; } else { return HRESULT_FROM_WIN32(RtlNtStatusToDosError(status)); } }
/* * @implemented */ HANDLE WINAPI OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) { NTSTATUS errCode; HANDLE ProcessHandle; OBJECT_ATTRIBUTES ObjectAttributes; CLIENT_ID ClientId; ClientId.UniqueProcess = UlongToHandle(dwProcessId); ClientId.UniqueThread = 0; InitializeObjectAttributes(&ObjectAttributes, NULL, (bInheritHandle ? OBJ_INHERIT : 0), NULL, NULL); errCode = NtOpenProcess(&ProcessHandle, dwDesiredAccess, &ObjectAttributes, &ClientId); if (!NT_SUCCESS(errCode)) { SetLastErrorByStatus(errCode); return NULL; } return ProcessHandle; }
HANDLE WINAPI ProcessIdToHandle(IN DWORD dwProcessId) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE Handle; CLIENT_ID ClientId; /* If we don't have a PID, look it up */ if (dwProcessId == MAXDWORD) dwProcessId = (DWORD_PTR)CsrGetProcessId(); /* Open a handle to the process */ ClientId.UniqueThread = NULL; ClientId.UniqueProcess = UlongToHandle(dwProcessId); InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); Status = NtOpenProcess(&Handle, PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION, &ObjectAttributes, &ClientId); if (!NT_SUCCESS(Status)) { /* Fail */ BaseSetLastNTError(Status); return 0; } /* Return the handle */ return Handle; }
/** * Retrieves current system statistics. */ VOID PhPluginGetSystemStatistics( _Out_ PPH_PLUGIN_SYSTEM_STATISTICS Statistics ) { Statistics->Performance = &PhPerfInformation; Statistics->NumberOfProcesses = PhTotalProcesses; Statistics->NumberOfThreads = PhTotalThreads; Statistics->NumberOfHandles = PhTotalHandles; Statistics->CpuKernelUsage = PhCpuKernelUsage; Statistics->CpuUserUsage = PhCpuUserUsage; Statistics->IoReadDelta = PhIoReadDelta; Statistics->IoWriteDelta = PhIoWriteDelta; Statistics->IoOtherDelta = PhIoOtherDelta; Statistics->CommitPages = PhGetItemCircularBuffer_ULONG(&PhCommitHistory, 0); Statistics->PhysicalPages = PhGetItemCircularBuffer_ULONG(&PhPhysicalHistory, 0); Statistics->MaxCpuProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&PhMaxCpuHistory, 0)); Statistics->MaxIoProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&PhMaxIoHistory, 0)); Statistics->CpuKernelHistory = &PhCpuKernelHistory; Statistics->CpuUserHistory = &PhCpuUserHistory; Statistics->CpusKernelHistory = &PhCpusKernelHistory; Statistics->CpusUserHistory = &PhCpusUserHistory; Statistics->IoReadHistory = &PhIoReadHistory; Statistics->IoWriteHistory = &PhIoWriteHistory; Statistics->IoOtherHistory = &PhIoOtherHistory; Statistics->CommitHistory = &PhCommitHistory; Statistics->PhysicalHistory = &PhPhysicalHistory; Statistics->MaxCpuHistory = &PhMaxCpuHistory; Statistics->MaxIoHistory = &PhMaxIoHistory; #ifdef PH_RECORD_MAX_USAGE Statistics->MaxCpuUsageHistory = &PhMaxCpuUsageHistory; Statistics->MaxIoReadOtherHistory = &PhMaxIoReadOtherHistory; Statistics->MaxIoWriteHistory = &PhMaxIoWriteHistory; #else Statistics->MaxCpuUsageHistory = NULL; Statistics->MaxIoReadOtherHistory = NULL; Statistics->MaxIoWriteHistory = NULL; #endif }
static PPH_STRING PhpaGetSendMessageReceiver( _In_ HANDLE ThreadId ) { static HWND (WINAPI *GetSendMessageReceiver_I)( _In_ HANDLE ThreadId ); HWND windowHandle; ULONG threadId; ULONG processId; CLIENT_ID clientId; PPH_STRING clientIdName; WCHAR windowClass[64]; PPH_STRING windowText; // GetSendMessageReceiver is an undocumented function exported by // user32.dll. It retrieves the handle of the window which a thread // is sending a message to. if (!GetSendMessageReceiver_I) GetSendMessageReceiver_I = PhGetDllProcedureAddress(L"user32.dll", "GetSendMessageReceiver", 0); if (!GetSendMessageReceiver_I) return NULL; windowHandle = GetSendMessageReceiver_I(ThreadId); if (!windowHandle) return NULL; threadId = GetWindowThreadProcessId(windowHandle, &processId); clientId.UniqueProcess = UlongToHandle(processId); clientId.UniqueThread = UlongToHandle(threadId); clientIdName = PH_AUTO(PhGetClientIdName(&clientId)); if (!GetClassName(windowHandle, windowClass, sizeof(windowClass) / sizeof(WCHAR))) windowClass[0] = UNICODE_NULL; windowText = PH_AUTO(PhGetWindowText(windowHandle)); return PhaFormatString(L"Window 0x%Ix (%s): %s \"%s\"", windowHandle, clientIdName->Buffer, windowClass, PhGetStringOrEmpty(windowText)); }
NTSTATUS PhInvokeRunAsService( _In_ PPH_RUNAS_SERVICE_PARAMETERS Parameters ) { NTSTATUS status; PPH_STRING domainName; PPH_STRING userName; PH_CREATE_PROCESS_AS_USER_INFO createInfo; ULONG flags; if (Parameters->UserName) { PhpSplitUserName(Parameters->UserName, &domainName, &userName); } else { domainName = NULL; userName = NULL; } memset(&createInfo, 0, sizeof(PH_CREATE_PROCESS_AS_USER_INFO)); createInfo.ApplicationName = Parameters->FileName; createInfo.CommandLine = Parameters->CommandLine; createInfo.CurrentDirectory = Parameters->CurrentDirectory; createInfo.DomainName = PhGetString(domainName); createInfo.UserName = PhGetString(userName); createInfo.Password = Parameters->Password; createInfo.LogonType = Parameters->LogonType; createInfo.SessionId = Parameters->SessionId; createInfo.DesktopName = Parameters->DesktopName; flags = PH_CREATE_PROCESS_SET_SESSION_ID; if (Parameters->ProcessId) { createInfo.ProcessIdWithToken = UlongToHandle(Parameters->ProcessId); flags |= PH_CREATE_PROCESS_USE_PROCESS_TOKEN; } if (Parameters->UseLinkedToken) flags |= PH_CREATE_PROCESS_USE_LINKED_TOKEN; status = PhCreateProcessAsUser( &createInfo, flags, NULL, NULL, NULL ); if (domainName) PhDereferenceObject(domainName); if (userName) PhDereferenceObject(userName); return status; }
VOID WepFillWindowInfo( _In_ PWE_WINDOW_NODE Node ) { HWND hwnd; ULONG threadId; ULONG processId; hwnd = Node->WindowHandle; GetClassName(hwnd, Node->WindowClass, sizeof(Node->WindowClass) / sizeof(WCHAR)); Node->WindowText = PhGetWindowText(hwnd); if (!Node->WindowText) Node->WindowText = PhReferenceEmptyString(); threadId = GetWindowThreadProcessId(hwnd, &processId); Node->ClientId.UniqueProcess = UlongToHandle(processId); Node->ClientId.UniqueThread = UlongToHandle(threadId); Node->WindowVisible = !!IsWindowVisible(hwnd); Node->HasChildren = !!FindWindowEx(hwnd, NULL, NULL, NULL); }
/**************************************************************************** * The main async help function. * * It either starts a thread or just calls the function directly for platforms * with no thread support. This relies on the fact that PostMessage() does * not actually call the windowproc before the function returns. */ static HANDLE run_query( HWND hWnd, UINT uMsg, LPARAM (*func)(struct async_query_header *), struct async_query_header *query, void *sbuf, INT sbuflen ) { static LONG next_handle = 0xdead; ULONG handle; do handle = LOWORD( InterlockedIncrement( &next_handle )); while (!handle); /* avoid handle 0 */ query->func = func; query->hWnd = hWnd; query->uMsg = uMsg; query->handle = UlongToHandle( handle ); query->sbuf = sbuf; query->sbuflen = sbuflen; if (!TrySubmitThreadpoolCallback( async_worker, query, NULL )) { SetLastError( WSAEWOULDBLOCK ); HeapFree( GetProcessHeap(), 0, query ); return 0; } return UlongToHandle( handle ); }
VOID WepAddChildWindows( _In_ PWINDOWS_CONTEXT Context, _In_opt_ PWE_WINDOW_NODE ParentNode, _In_ HWND hwnd, _In_opt_ HANDLE FilterProcessId, _In_opt_ HANDLE FilterThreadId ) { HWND childWindow = NULL; ULONG i = 0; // We use FindWindowEx because EnumWindows doesn't return Metro app windows. // Set a reasonable limit to prevent infinite loops. while (i < 0x800 && (childWindow = FindWindowEx(hwnd, childWindow, NULL, NULL))) { ULONG processId; ULONG threadId; threadId = GetWindowThreadProcessId(childWindow, &processId); if ( (!FilterProcessId || UlongToHandle(processId) == FilterProcessId) && (!FilterThreadId || UlongToHandle(threadId) == FilterThreadId) ) { PWE_WINDOW_NODE childNode = WepAddChildWindowNode(&Context->TreeContext, ParentNode, childWindow); if (childNode->HasChildren) { WepAddChildWindows(Context, childNode, childWindow, NULL, NULL); } } i++; } }
PPH_PROCESS_RECORD EtpReferenceMaxNodeRecord( _In_ LONG Index ) { LARGE_INTEGER time; ULONG maxProcessId; maxProcessId = PhGetItemCircularBuffer_ULONG(&EtMaxGpuNodeHistory, Index); if (!maxProcessId) return NULL; PhGetStatisticsTime(NULL, Index, &time); time.QuadPart += PH_TICKS_PER_SEC - 1; return PhFindProcessRecord(UlongToHandle(maxProcessId), &time); }
static PPH_PROCESS_RECORD PhSipReferenceMaxIoRecord( _In_ LONG Index ) { LARGE_INTEGER time; ULONG maxProcessId; // Find the process record for the max. I/O process for the particular time. maxProcessId = PhGetItemCircularBuffer_ULONG(SystemStatistics.MaxIoHistory, Index); if (!maxProcessId) return NULL; // See above for the explanation. PhGetStatisticsTime(NULL, Index, &time); time.QuadPart += PH_TICKS_PER_SEC - 1; return PhFindProcessRecord(UlongToHandle(maxProcessId), &time); }
HWND CreateCheckButton(const char* lpWindowName, DWORD xSize, DWORD id) { HWND h; h = CreateWindowEx(0, "BUTTON", lpWindowName, WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, xButPos, /* x */ yButPos, /* y */ xSize, /* nWidth */ 20, /* nHeight */ g_hwnd, UlongToHandle(id), g_hInst, NULL ); yButPos += 21; return h; }
/* * UserGetKeyboardLayout * * Returns hkl of given thread keyboard layout */ HKL FASTCALL UserGetKeyboardLayout( DWORD dwThreadId) { PTHREADINFO pti; PLIST_ENTRY ListEntry; PKL pKl; pti = PsGetCurrentThreadWin32Thread(); if (!dwThreadId) { pKl = pti->KeyboardLayout; return pKl ? pKl->hkl : NULL; } ListEntry = pti->rpdesk->PtiList.Flink; // // Search the Desktop Thread list for related Desktop active Threads. // while(ListEntry != &pti->rpdesk->PtiList) { pti = CONTAINING_RECORD(ListEntry, THREADINFO, PtiLink); if (PsGetThreadId(pti->pEThread) == UlongToHandle(dwThreadId)) { pKl = pti->KeyboardLayout; return pKl ? pKl->hkl : NULL; } ListEntry = ListEntry->Flink; } return NULL; }
BOOLEAN WeSendServerRequest( __in HWND hWnd ) { ULONG threadId; ULONG processId; LARGE_INTEGER timeout; if (!WeServerSharedData || !WeServerSharedSectionEvent) return FALSE; threadId = GetWindowThreadProcessId(hWnd, &processId); if (UlongToHandle(processId) == NtCurrentProcessId()) { // We are trying to get information about the server. Call the procedure directly. WepWriteClientData(hWnd); return TRUE; } // Call the client and wait for the client to finish. WeCurrentMessageId++; WeServerSharedData->MessageId = WeCurrentMessageId; NtResetEvent(WeServerSharedSectionEvent, NULL); if (!SendNotifyMessage(hWnd, WeServerMessage, (WPARAM)NtCurrentProcessId(), WeCurrentMessageId)) return FALSE; timeout.QuadPart = -WE_CLIENT_MESSAGE_TIMEOUT * PH_TIMEOUT_MS; if (NtWaitForSingleObject(WeServerSharedSectionEvent, FALSE, &timeout) != STATUS_WAIT_0) return FALSE; return TRUE; }
void test_CShellMenu_params() { HRESULT hResult; IShellMenu* shellMenu; IDockingWindow* dockingMenu; IObjectWithSite* menuWithSite; IShellMenuCallback *psmc; UINT uId; UINT uIdAncestor; DWORD dwFlags; HWND hwndToolbar; HMENU hmenu; HWND hwndOwner; DWORD menuFlagss; IShellFolder *shellFolder; if (!CreateCShellMenu(&shellMenu, &dockingMenu, &menuWithSite)) { skip("failed to create CShellMenuObject\n"); return; } hResult = shellMenu->Initialize(NULL, 11, 22, 0xdeadbeef); test_S_OK(hResult, "Initialize failed"); hResult = shellMenu->GetMenuInfo(&psmc, &uId, &uIdAncestor, &dwFlags); test_S_OK(hResult, "GetMenuInfo failed"); ok (psmc == NULL, "wrong psmc\n"); ok (uId == 11, "wrong uid\n"); ok (uIdAncestor == 22, "wrong uIdAncestor\n"); ok (dwFlags == 0xdeadbeef, "wrong dwFlags\n"); hResult = shellMenu->Initialize(NULL, 0, ANCESTORDEFAULT, SMINIT_TOPLEVEL|SMINIT_VERTICAL); test_S_OK(hResult, "Initialize failed"); hResult = dockingMenu->GetWindow(&hwndToolbar); test_HRES(hResult, E_FAIL, "GetWindow should fail"); hResult = shellMenu->GetMenu(&hmenu, &hwndOwner, &menuFlagss); test_HRES(hResult, E_FAIL, "GetMenu should fail"); hmenu = CreatePopupMenu(); hResult = shellMenu->SetMenu(hmenu, NULL, 0); test_S_OK(hResult, "SetMenu failed"); hwndToolbar = (HWND)UlongToPtr(0xdeadbeef); hResult = dockingMenu->GetWindow(&hwndToolbar); test_S_OK(hResult, "GetWindow failed"); ok (hwndToolbar == NULL, "Expected NULL window\n"); hResult = shellMenu->SetMenu(NULL, NULL, 0); test_S_OK(hResult, "SetMenu failed"); hResult = shellMenu->GetMenu(&hmenu, &hwndOwner, &menuFlagss); test_S_OK(hResult, "GetMenu failed"); ok (hmenu == NULL, "Got a menu\n"); hResult = dockingMenu->GetWindow(&hwndToolbar); test_S_OK(hResult, "GetWindow failed"); hResult = SHGetDesktopFolder(&shellFolder); test_S_OK(hResult, "SHGetDesktopFolder failed"); hResult = shellMenu->SetShellFolder(shellFolder, NULL, 0, 0); test_S_OK(hResult, "SetShellFolder failed"); hResult = shellMenu->SetShellFolder(NULL, NULL, 0, 0); test_HRES(hResult, E_INVALIDARG, "SetShellFolder should fail"); hwndToolbar = (HWND)UlongToHandle(0xdeadbeef); hResult = dockingMenu->GetWindow(&hwndToolbar); test_S_OK(hResult, "GetWindow failed"); ok (hwndToolbar == NULL, "Expected NULL window\n"); hResult = dockingMenu->ShowDW(TRUE); test_HRES(hResult, S_FALSE, "ShowDW should fail"); menuWithSite->Release(); dockingMenu->Release(); shellMenu->Release(); }
BOOL FindWinMMDeviceIndex( LPFILTERINFO CurInfo, BOOL bRecord) { ULONG DeviceCount, Index; WCHAR Buffer[MAX_PATH]; DWORD Size, dwResult; if (bRecord) DeviceCount = waveInGetNumDevs(); else DeviceCount = waveOutGetNumDevs(); /* sanity check */ //ASSERT(DeviceCount); for(Index = 0; Index < DeviceCount; Index++) { Size = 0; /* query device interface size */ if (bRecord) dwResult = waveInMessage(UlongToHandle(Index), DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&Size, 0); else dwResult = waveOutMessage(UlongToHandle(Index), DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&Size, 0); if (dwResult != MMSYSERR_NOERROR) { DPRINT("Failed DRV_QUERYDEVICEINTERFACESIZE with %lx bRecord %u Index %u\n", dwResult, bRecord, Index); continue; } /* sanity check */ ASSERT(Size < MAX_PATH); /* now get the device interface string */ if (bRecord) dwResult = waveInMessage(UlongToHandle(Index), DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)Buffer, MAX_PATH); else dwResult = waveOutMessage(UlongToHandle(Index), DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)Buffer, MAX_PATH); if (dwResult != MMSYSERR_NOERROR) { DPRINT("Failed DRV_QUERYDEVICEINTERFACE with %lx bRecord %u Index %u\n", dwResult, bRecord, Index); continue; } if (!wcsicmp(CurInfo->DevicePath, Buffer)) { if (bRecord) CurInfo->MappedId[0] = Index; else CurInfo->MappedId[1] = Index; return TRUE; } } DPRINT1("Failed to find device %ws bRecord %u Count %u\n", CurInfo->DevicePath, bRecord, DeviceCount); // HACK if (bRecord) CurInfo->MappedId[0] = 0; else CurInfo->MappedId[1] = 0; return TRUE; }
/* * @implemented */ HWND WINAPI DECLSPEC_HOTPATCH CreateWindowExW(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { MDICREATESTRUCTW mdi; HWND hwnd; if (!RegisterDefaultClasses) { ERR("CreateWindowExW RegisterSystemControls\n"); RegisterSystemControls(); } if (dwExStyle & WS_EX_MDICHILD) { POINT mPos[2]; UINT id = 0; HWND top_child; PWND pWndParent; pWndParent = ValidateHwnd(hWndParent); if (!pWndParent) return NULL; if (pWndParent->fnid != FNID_MDICLIENT) { WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", hWndParent); return NULL; } /* lpParams of WM_[NC]CREATE is different for MDI children. * MDICREATESTRUCT members have the originally passed values. */ mdi.szClass = lpClassName; mdi.szTitle = lpWindowName; mdi.hOwner = hInstance; mdi.x = x; mdi.y = y; mdi.cx = nWidth; mdi.cy = nHeight; mdi.style = dwStyle; mdi.lParam = (LPARAM)lpParam; lpParam = (LPVOID)&mdi; if (pWndParent->style & MDIS_ALLCHILDSTYLES) { if (dwStyle & WS_POPUP) { WARN("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n"); return(0); } dwStyle |= (WS_CHILD | WS_CLIPSIBLINGS); } else { dwStyle &= ~WS_POPUP; dwStyle |= (WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX); } top_child = GetWindow(hWndParent, GW_CHILD); if (top_child) { /* Restore current maximized child */ if((dwStyle & WS_VISIBLE) && IsZoomed(top_child)) { TRACE("Restoring current maximized child %p\n", top_child); SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 ); ShowWindow(top_child, SW_RESTORE); SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 ); } } MDI_CalcDefaultChildPos(hWndParent, -1, mPos, 0, &id); if (!(dwStyle & WS_POPUP)) hMenu = UlongToHandle(id); if (dwStyle & (WS_CHILD | WS_POPUP)) { if (x == CW_USEDEFAULT || x == CW_USEDEFAULT16) { x = mPos[0].x; y = mPos[0].y; } if (nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16 || !nWidth) nWidth = mPos[1].x; if (nHeight == CW_USEDEFAULT || nHeight == CW_USEDEFAULT16 || !nHeight) nHeight = mPos[1].y; } } hwnd = User32CreateWindowEx(dwExStyle, (LPCSTR) lpClassName, (LPCSTR) lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam, 0); return hwnd; }
HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest) { ULONG DeviceID = ULONG_MAX, Flags; MMRESULT Result; LPFILTERINFO Filter; if (!pGuidSrc || !pGuidDest) { /* invalid param */ return DSERR_INVALIDPARAM; } /* sanity check */ ASSERT(!IsEqualGUID(pGuidSrc, &GUID_NULL)); if (IsEqualGUID(&DSDEVID_DefaultPlayback, pGuidSrc) || IsEqualGUID(&DSDEVID_DefaultVoicePlayback, pGuidSrc)) { Result = waveOutMessage(UlongToHandle(WAVE_MAPPER), DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&DeviceID, (DWORD_PTR)&Flags); if (Result != MMSYSERR_NOERROR || DeviceID == ULONG_MAX) { /* hack */ DPRINT1("Failed to get DRVM_MAPPER_PREFERRED_GET, using device 0\n"); DeviceID = 0; } if (!FindDeviceByMappedId(DeviceID, &Filter, TRUE)) { /* device not found */ return DSERR_INVALIDPARAM; } /* copy device guid */ RtlMoveMemory(pGuidDest, &Filter->DeviceGuid[1], sizeof(GUID)); return DS_OK; } else if (IsEqualGUID(&DSDEVID_DefaultCapture, pGuidSrc) || IsEqualGUID(&DSDEVID_DefaultVoiceCapture, pGuidSrc)) { Result = waveInMessage(UlongToHandle(WAVE_MAPPER), DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&DeviceID, (DWORD_PTR)&Flags); if (Result != MMSYSERR_NOERROR || DeviceID == ULONG_MAX) { /* hack */ DPRINT1("Failed to get DRVM_MAPPER_PREFERRED_GET, for record using device 0\n"); DeviceID = 0; } if (!FindDeviceByMappedId(DeviceID, &Filter, FALSE)) { /* device not found */ return DSERR_INVALIDPARAM; } /* copy device guid */ RtlMoveMemory(pGuidDest, &Filter->DeviceGuid[0], sizeof(GUID)); return DS_OK; } if (!FindDeviceByGuid(pGuidSrc, &Filter)) { /* unknown guid */ return DSERR_INVALIDPARAM; } /* done */ return DS_OK; }
VOID PhServiceProviderUpdate( _In_ PVOID Object ) { static SC_HANDLE scManagerHandle = NULL; static ULONG runCount = 0; static PPH_HASH_ENTRY nameHashSet[256]; static PPHP_SERVICE_NAME_ENTRY nameEntries = NULL; static ULONG nameEntriesCount; static ULONG nameEntriesAllocated = 0; LPENUM_SERVICE_STATUS_PROCESS services; ULONG numberOfServices; ULONG i; PPH_HASH_ENTRY hashEntry; // We always execute the first run, and we only initialize non-polling after the first run. if (PhEnableServiceNonPoll && runCount != 0) { if (!PhpNonPollInitialized) { if (WindowsVersion >= WINDOWS_VISTA) { PhpInitializeServiceNonPoll(); } PhpNonPollInitialized = TRUE; } if (PhpNonPollActive) { if (InterlockedExchange(&PhpNonPollGate, 0) == 0) { // Non-poll gate is closed; skip all processing. goto UpdateEnd; } } } if (!scManagerHandle) { scManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); if (!scManagerHandle) return; } services = PhEnumServices(scManagerHandle, 0, 0, &numberOfServices); if (!services) return; // Build a hash set containing the service names. // This has caused a massive decrease in background CPU usage, and // is certainly much better than the quadratic-time string comparisons // we were doing before (in the "Look for dead services" section). nameEntriesCount = 0; if (nameEntriesAllocated < numberOfServices) { nameEntriesAllocated = numberOfServices + 32; if (nameEntries) PhFree(nameEntries); nameEntries = PhAllocate(sizeof(PHP_SERVICE_NAME_ENTRY) * nameEntriesAllocated); } PhInitializeHashSet(nameHashSet, PH_HASH_SET_SIZE(nameHashSet)); for (i = 0; i < numberOfServices; i++) { PPHP_SERVICE_NAME_ENTRY entry; entry = &nameEntries[nameEntriesCount++]; PhInitializeStringRefLongHint(&entry->Name, services[i].lpServiceName); entry->ServiceEntry = &services[i]; PhAddEntryHashSet( nameHashSet, PH_HASH_SET_SIZE(nameHashSet), &entry->HashEntry, PhpHashServiceNameEntry(entry) ); } // Look for dead services. { PPH_LIST servicesToRemove = NULL; PH_HASHTABLE_ENUM_CONTEXT enumContext; PPH_SERVICE_ITEM *serviceItem; PhBeginEnumHashtable(PhServiceHashtable, &enumContext); while (serviceItem = PhNextEnumHashtable(&enumContext)) { BOOLEAN found = FALSE; PHP_SERVICE_NAME_ENTRY lookupNameEntry; // Check if the service still exists. lookupNameEntry.Name = (*serviceItem)->Name->sr; hashEntry = PhFindEntryHashSet( nameHashSet, PH_HASH_SET_SIZE(nameHashSet), PhpHashServiceNameEntry(&lookupNameEntry) ); for (; hashEntry; hashEntry = hashEntry->Next) { PPHP_SERVICE_NAME_ENTRY nameEntry; nameEntry = CONTAINING_RECORD(hashEntry, PHP_SERVICE_NAME_ENTRY, HashEntry); if (PhpCompareServiceNameEntry(&lookupNameEntry, nameEntry)) { found = TRUE; break; } } if (!found) { // Remove the service from its process. if ((*serviceItem)->ProcessId) { PPH_PROCESS_ITEM processItem; processItem = PhReferenceProcessItem((HANDLE)(*serviceItem)->ProcessId); if (processItem) { PhpRemoveProcessItemService(processItem, *serviceItem); PhDereferenceObject(processItem); } } // Raise the service removed event. PhInvokeCallback(&PhServiceRemovedEvent, *serviceItem); if (!servicesToRemove) servicesToRemove = PhCreateList(2); PhAddItemList(servicesToRemove, *serviceItem); } } if (servicesToRemove) { PhAcquireQueuedLockExclusive(&PhServiceHashtableLock); for (i = 0; i < servicesToRemove->Count; i++) { PhpRemoveServiceItem((PPH_SERVICE_ITEM)servicesToRemove->Items[i]); } PhReleaseQueuedLockExclusive(&PhServiceHashtableLock); PhDereferenceObject(servicesToRemove); } } // Look for new services and update existing ones. for (i = 0; i < PH_HASH_SET_SIZE(nameHashSet); i++) { for (hashEntry = nameHashSet[i]; hashEntry; hashEntry = hashEntry->Next) { PPH_SERVICE_ITEM serviceItem; PPHP_SERVICE_NAME_ENTRY nameEntry; ENUM_SERVICE_STATUS_PROCESS *serviceEntry; nameEntry = CONTAINING_RECORD(hashEntry, PHP_SERVICE_NAME_ENTRY, HashEntry); serviceEntry = nameEntry->ServiceEntry; serviceItem = PhpLookupServiceItem(&nameEntry->Name); if (!serviceItem) { // Create the service item and fill in basic information. serviceItem = PhCreateServiceItem(serviceEntry); PhpUpdateServiceItemConfig(scManagerHandle, serviceItem); // Add the service to its process, if appropriate. if ( ( serviceItem->State == SERVICE_RUNNING || serviceItem->State == SERVICE_PAUSED ) && serviceItem->ProcessId ) { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(serviceItem->ProcessId)) { PhpAddProcessItemService(processItem, serviceItem); PhDereferenceObject(processItem); } else { // The process doesn't exist yet (to us). Set the pending // flag and when the process is added this will be // fixed. serviceItem->PendingProcess = TRUE; } } // Add the service item to the hashtable. PhAcquireQueuedLockExclusive(&PhServiceHashtableLock); PhAddEntryHashtable(PhServiceHashtable, &serviceItem); PhReleaseQueuedLockExclusive(&PhServiceHashtableLock); // Raise the service added event. PhInvokeCallback(&PhServiceAddedEvent, serviceItem); } else { if ( serviceItem->Type != serviceEntry->ServiceStatusProcess.dwServiceType || serviceItem->State != serviceEntry->ServiceStatusProcess.dwCurrentState || serviceItem->ControlsAccepted != serviceEntry->ServiceStatusProcess.dwControlsAccepted || serviceItem->ProcessId != UlongToHandle(serviceEntry->ServiceStatusProcess.dwProcessId) || serviceItem->NeedsConfigUpdate ) { PH_SERVICE_MODIFIED_DATA serviceModifiedData; PH_SERVICE_CHANGE serviceChange; // The service has been "modified". serviceModifiedData.Service = serviceItem; memset(&serviceModifiedData.OldService, 0, sizeof(PH_SERVICE_ITEM)); serviceModifiedData.OldService.Type = serviceItem->Type; serviceModifiedData.OldService.State = serviceItem->State; serviceModifiedData.OldService.ControlsAccepted = serviceItem->ControlsAccepted; serviceModifiedData.OldService.ProcessId = serviceItem->ProcessId; // Update the service item. serviceItem->Type = serviceEntry->ServiceStatusProcess.dwServiceType; serviceItem->State = serviceEntry->ServiceStatusProcess.dwCurrentState; serviceItem->ControlsAccepted = serviceEntry->ServiceStatusProcess.dwControlsAccepted; serviceItem->ProcessId = UlongToHandle(serviceEntry->ServiceStatusProcess.dwProcessId); if (serviceItem->ProcessId) PhPrintUInt32(serviceItem->ProcessIdString, HandleToUlong(serviceItem->ProcessId)); else serviceItem->ProcessIdString[0] = 0; // Add/remove the service from its process. serviceChange = PhGetServiceChange(&serviceModifiedData); if ( (serviceChange == ServiceStarted && serviceItem->ProcessId) || (serviceChange == ServiceStopped && serviceModifiedData.OldService.ProcessId) ) { PPH_PROCESS_ITEM processItem; if (serviceChange == ServiceStarted) processItem = PhReferenceProcessItem(serviceItem->ProcessId); else processItem = PhReferenceProcessItem(serviceModifiedData.OldService.ProcessId); if (processItem) { if (serviceChange == ServiceStarted) PhpAddProcessItemService(processItem, serviceItem); else PhpRemoveProcessItemService(processItem, serviceItem); PhDereferenceObject(processItem); } else { if (serviceChange == ServiceStarted) serviceItem->PendingProcess = TRUE; else serviceItem->PendingProcess = FALSE; } } else if ( serviceItem->State == SERVICE_RUNNING && serviceItem->ProcessId != serviceModifiedData.OldService.ProcessId && serviceItem->ProcessId ) { PPH_PROCESS_ITEM processItem; // The service stopped and started, and the only change we have detected // is in the process ID. if (processItem = PhReferenceProcessItem(serviceModifiedData.OldService.ProcessId)) { PhpRemoveProcessItemService(processItem, serviceItem); PhDereferenceObject(processItem); } if (processItem = PhReferenceProcessItem(serviceItem->ProcessId)) { PhpAddProcessItemService(processItem, serviceItem); PhDereferenceObject(processItem); } else { serviceItem->PendingProcess = TRUE; } } // Do a config update if necessary. if (serviceItem->NeedsConfigUpdate) { PhpUpdateServiceItemConfig(scManagerHandle, serviceItem); serviceItem->NeedsConfigUpdate = FALSE; } // Raise the service modified event. PhInvokeCallback(&PhServiceModifiedEvent, &serviceModifiedData); } } } } PhFree(services); UpdateEnd: PhInvokeCallback(&PhServicesUpdatedEvent, NULL); runCount++; }
VOID NTAPI DotNetEventCallback( _In_ PEVENT_RECORD EventRecord ) { PASMPAGE_QUERY_CONTEXT context = EventRecord->UserContext; PEVENT_HEADER eventHeader = &EventRecord->EventHeader; PEVENT_DESCRIPTOR eventDescriptor = &eventHeader->EventDescriptor; if (UlongToHandle(eventHeader->ProcessId) == context->ProcessId) { // .NET 4.0+ switch (eventDescriptor->Id) { case RuntimeInformationDCStart: { PRuntimeInformationRundown data = EventRecord->UserData; PDNA_NODE node; PPH_STRING startupFlagsString; PPH_STRING startupModeString; // Check for duplicates. if (FindClrNode(context, data->ClrInstanceID)) break; node = AddNode(context); node->Type = DNA_TYPE_CLR; node->u.Clr.ClrInstanceID = data->ClrInstanceID; node->u.Clr.DisplayName = PhFormatString(L"CLR v%u.%u.%u.%u", data->VMMajorVersion, data->VMMinorVersion, data->VMBuildNumber, data->VMQfeNumber); node->StructureText = node->u.Clr.DisplayName->sr; node->IdText = PhFormatString(L"%u", data->ClrInstanceID); startupFlagsString = FlagsToString(data->StartupFlags, StartupFlagsMap, sizeof(StartupFlagsMap)); startupModeString = FlagsToString(data->StartupMode, StartupModeMap, sizeof(StartupModeMap)); if (startupFlagsString->Length != 0 && startupModeString->Length != 0) { node->FlagsText = PhConcatStrings(3, startupFlagsString->Buffer, L", ", startupModeString->Buffer); PhDereferenceObject(startupFlagsString); PhDereferenceObject(startupModeString); } else if (startupFlagsString->Length != 0) { node->FlagsText = startupFlagsString; PhDereferenceObject(startupModeString); } else if (startupModeString->Length != 0) { node->FlagsText = startupModeString; PhDereferenceObject(startupFlagsString); } if (data->CommandLine[0]) node->PathText = PhCreateString(data->CommandLine); PhAddItemList(context->NodeRootList, node); } break; case AppDomainDCStart_V1: { PAppDomainLoadUnloadRundown_V1 data = EventRecord->UserData; SIZE_T appDomainNameLength; USHORT clrInstanceID; PDNA_NODE parentNode; PDNA_NODE node; appDomainNameLength = PhCountStringZ(data->AppDomainName) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)data + FIELD_OFFSET(AppDomainLoadUnloadRundown_V1, AppDomainName) + appDomainNameLength + sizeof(WCHAR) + sizeof(ULONG)); // Find the CLR node to add the AppDomain node to. parentNode = FindClrNode(context, clrInstanceID); if (parentNode) { // Check for duplicates. if (FindAppDomainNode(parentNode, data->AppDomainID)) break; node = AddNode(context); node->Type = DNA_TYPE_APPDOMAIN; node->u.AppDomain.AppDomainID = data->AppDomainID; node->u.AppDomain.DisplayName = PhConcatStrings2(L"AppDomain: ", data->AppDomainName); node->StructureText = node->u.AppDomain.DisplayName->sr; node->IdText = PhFormatString(L"%I64u", data->AppDomainID); node->FlagsText = FlagsToString(data->AppDomainFlags, AppDomainFlagsMap, sizeof(AppDomainFlagsMap)); PhAddItemList(parentNode->Children, node); } } break; case AssemblyDCStart_V1: { PAssemblyLoadUnloadRundown_V1 data = EventRecord->UserData; SIZE_T fullyQualifiedAssemblyNameLength; USHORT clrInstanceID; PDNA_NODE parentNode; PDNA_NODE node; PH_STRINGREF remainingPart; fullyQualifiedAssemblyNameLength = PhCountStringZ(data->FullyQualifiedAssemblyName) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)data + FIELD_OFFSET(AssemblyLoadUnloadRundown_V1, FullyQualifiedAssemblyName) + fullyQualifiedAssemblyNameLength + sizeof(WCHAR)); // Find the AppDomain node to add the Assembly node to. parentNode = FindClrNode(context, clrInstanceID); if (parentNode) parentNode = FindAppDomainNode(parentNode, data->AppDomainID); if (parentNode) { // Check for duplicates. if (FindAssemblyNode(parentNode, data->AssemblyID)) break; node = AddNode(context); node->Type = DNA_TYPE_ASSEMBLY; node->u.Assembly.AssemblyID = data->AssemblyID; node->u.Assembly.FullyQualifiedAssemblyName = PhCreateStringEx(data->FullyQualifiedAssemblyName, fullyQualifiedAssemblyNameLength); // Display only the assembly name, not the whole fully qualified name. if (!PhSplitStringRefAtChar(&node->u.Assembly.FullyQualifiedAssemblyName->sr, ',', &node->StructureText, &remainingPart)) node->StructureText = node->u.Assembly.FullyQualifiedAssemblyName->sr; node->IdText = PhFormatString(L"%I64u", data->AssemblyID); node->FlagsText = FlagsToString(data->AssemblyFlags, AssemblyFlagsMap, sizeof(AssemblyFlagsMap)); PhAddItemList(parentNode->Children, node); } } break; case ModuleDCStart_V1: { PModuleLoadUnloadRundown_V1 data = EventRecord->UserData; PWSTR moduleILPath; SIZE_T moduleILPathLength; PWSTR moduleNativePath; SIZE_T moduleNativePathLength; USHORT clrInstanceID; PDNA_NODE node; moduleILPath = data->ModuleILPath; moduleILPathLength = PhCountStringZ(moduleILPath) * sizeof(WCHAR); moduleNativePath = (PWSTR)((PCHAR)moduleILPath + moduleILPathLength + sizeof(WCHAR)); moduleNativePathLength = PhCountStringZ(moduleNativePath) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)moduleNativePath + moduleNativePathLength + sizeof(WCHAR)); // Find the Assembly node to set the path on. node = FindClrNode(context, clrInstanceID); if (node) node = FindAssemblyNode2(node, data->AssemblyID); if (node) { PhMoveReference(&node->PathText, PhCreateStringEx(moduleILPath, moduleILPathLength)); if (moduleNativePathLength != 0) PhMoveReference(&node->NativePathText, PhCreateStringEx(moduleNativePath, moduleNativePathLength)); } } break; case DCStartComplete_V1: { if (_InterlockedExchange(&context->TraceHandleActive, 0) == 1) { CloseTrace(context->TraceHandle); } } break; } // .NET 2.0 if (eventDescriptor->Id == 0) { switch (eventDescriptor->Opcode) { case CLR_MODULEDCSTART_OPCODE: { PModuleLoadUnloadRundown_V1 data = EventRecord->UserData; PWSTR moduleILPath; SIZE_T moduleILPathLength; PWSTR moduleNativePath; SIZE_T moduleNativePathLength; PDNA_NODE node; ULONG_PTR indexOfBackslash; ULONG_PTR indexOfLastDot; moduleILPath = data->ModuleILPath; moduleILPathLength = PhCountStringZ(moduleILPath) * sizeof(WCHAR); moduleNativePath = (PWSTR)((PCHAR)moduleILPath + moduleILPathLength + sizeof(WCHAR)); moduleNativePathLength = PhCountStringZ(moduleNativePath) * sizeof(WCHAR); if (context->ClrV2Node && (moduleILPathLength != 0 || moduleNativePathLength != 0)) { node = AddNode(context); node->Type = DNA_TYPE_ASSEMBLY; node->FlagsText = FlagsToString(data->ModuleFlags, ModuleFlagsMap, sizeof(ModuleFlagsMap)); node->PathText = PhCreateStringEx(moduleILPath, moduleILPathLength); if (moduleNativePathLength != 0) node->NativePathText = PhCreateStringEx(moduleNativePath, moduleNativePathLength); // Use the name between the last backslash and the last dot for the structure column text. // (E.g. C:\...\AcmeSoft.BigLib.dll -> AcmeSoft.BigLib) indexOfBackslash = PhFindLastCharInString(node->PathText, 0, '\\'); indexOfLastDot = PhFindLastCharInString(node->PathText, 0, '.'); if (indexOfBackslash != -1) { node->StructureText.Buffer = node->PathText->Buffer + indexOfBackslash + 1; if (indexOfLastDot != -1 && indexOfLastDot > indexOfBackslash) { node->StructureText.Length = (indexOfLastDot - indexOfBackslash - 1) * sizeof(WCHAR); } else { node->StructureText.Length = node->PathText->Length - indexOfBackslash * sizeof(WCHAR) - sizeof(WCHAR); } } else { node->StructureText = node->PathText->sr; } PhAddItemList(context->ClrV2Node->Children, node); } } break; case CLR_METHODDC_DCSTARTCOMPLETE_OPCODE: { if (_InterlockedExchange(&context->TraceHandleActive, 0) == 1) { CloseTrace(context->TraceHandle); } } break; } } } }
VOID EtpGpuIconUpdateCallback( _In_ struct _PH_NF_ICON *Icon, _Out_ PVOID *NewIconOrBitmap, _Out_ PULONG Flags, _Out_ PPH_STRING *NewText, _In_opt_ PVOID Context ) { static PH_GRAPH_DRAW_INFO drawInfo = { 16, 16, 0, 2, RGB(0x00, 0x00, 0x00), 16, NULL, NULL, 0, 0, 0, 0 }; ULONG maxDataCount; ULONG lineDataCount; PFLOAT lineData1; HBITMAP bitmap; PVOID bits; HDC hdc; HBITMAP oldBitmap; HANDLE maxGpuProcessId; PPH_PROCESS_ITEM maxGpuProcessItem; PH_FORMAT format[8]; // Icon Icon->Pointers->BeginBitmap(&drawInfo.Width, &drawInfo.Height, &bitmap, &bits, &hdc, &oldBitmap); maxDataCount = drawInfo.Width / 2 + 1; lineData1 = _alloca(maxDataCount * sizeof(FLOAT)); lineDataCount = min(maxDataCount, EtGpuNodeHistory.Count); PhCopyCircularBuffer_FLOAT(&EtGpuNodeHistory, lineData1, lineDataCount); drawInfo.LineDataCount = lineDataCount; drawInfo.LineData1 = lineData1; drawInfo.LineColor1 = PhGetIntegerSetting(L"ColorCpuKernel"); drawInfo.LineBackColor1 = PhHalveColorBrightness(drawInfo.LineColor1); if (bits) PhDrawGraphDirect(hdc, bits, &drawInfo); SelectObject(hdc, oldBitmap); *NewIconOrBitmap = bitmap; *Flags = PH_NF_UPDATE_IS_BITMAP; // Text if (EtMaxGpuNodeHistory.Count != 0) maxGpuProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&EtMaxGpuNodeHistory, 0)); else maxGpuProcessId = NULL; if (maxGpuProcessId) maxGpuProcessItem = PhReferenceProcessItem(maxGpuProcessId); else maxGpuProcessItem = NULL; PhInitFormatS(&format[0], L"GPU Usage: "); PhInitFormatF(&format[1], EtGpuNodeUsage * 100, 2); PhInitFormatC(&format[2], '%'); if (maxGpuProcessItem) { PhInitFormatC(&format[3], '\n'); PhInitFormatSR(&format[4], maxGpuProcessItem->ProcessName->sr); PhInitFormatS(&format[5], L": "); PhInitFormatF(&format[6], EtGetProcessBlock(maxGpuProcessItem)->GpuNodeUsage * 100, 2); PhInitFormatC(&format[7], '%'); } *NewText = PhFormat(format, maxGpuProcessItem ? 8 : 3, 128); if (maxGpuProcessItem) PhDereferenceObject(maxGpuProcessItem); }
VOID NTAPI RefreshSandboxieInfo( _In_opt_ PVOID Context, _In_ BOOLEAN TimerOrWaitFired ) { LONG index; WCHAR boxName[34]; ULONG pids[512]; PBOX_INFO boxInfo; if (!SbieApi_QueryBoxPath || !SbieApi_EnumBoxes || !SbieApi_EnumProcessEx) return; PhAcquireQueuedLockExclusive(&BoxedProcessesLock); PhClearHashtable(BoxedProcessesHashtable); BoxInfoCount = 0; index = -1; while ((index = SbieApi_EnumBoxes(index, boxName)) != -1) { if (SbieApi_EnumProcessEx(boxName, TRUE, 0, pids) == 0) { ULONG count; PULONG pid; count = pids[0]; pid = &pids[1]; while (count != 0) { BOXED_PROCESS boxedProcess; boxedProcess.ProcessId = UlongToHandle(*pid); memcpy(boxedProcess.BoxName, boxName, sizeof(boxName)); PhAddEntryHashtable(BoxedProcessesHashtable, &boxedProcess); count--; pid++; } } if (BoxInfoCount < 16) { ULONG filePathLength = 0; ULONG keyPathLength = 0; ULONG ipcPathLength = 0; boxInfo = &BoxInfo[BoxInfoCount++]; memcpy(boxInfo->BoxName, boxName, sizeof(boxName)); SbieApi_QueryBoxPath( boxName, NULL, NULL, NULL, &filePathLength, &keyPathLength, &ipcPathLength ); if (ipcPathLength < sizeof(boxInfo->IpcRootBuffer)) { boxInfo->IpcRootBuffer[0] = 0; SbieApi_QueryBoxPath( boxName, NULL, NULL, boxInfo->IpcRootBuffer, NULL, NULL, &ipcPathLength ); if (boxInfo->IpcRootBuffer[0] != 0) { PhInitializeStringRef(&boxInfo->IpcRoot, boxInfo->IpcRootBuffer); } else { BoxInfoCount--; } } else { BoxInfoCount--; } } } BoxedProcessesUpdated = TRUE; PhReleaseQueuedLockExclusive(&BoxedProcessesLock); }
VOID PhpThreadProviderUpdate( _In_ PPH_THREAD_PROVIDER ThreadProvider, _In_ PVOID ProcessInformation ) { PPH_THREAD_PROVIDER threadProvider = ThreadProvider; PSYSTEM_PROCESS_INFORMATION process; SYSTEM_PROCESS_INFORMATION localProcess; PSYSTEM_THREAD_INFORMATION threads; ULONG numberOfThreads; ULONG i; process = PhFindProcessInformation(ProcessInformation, threadProvider->ProcessId); if (!process) { // The process doesn't exist anymore. Pretend it does but // has no threads. process = &localProcess; process->NumberOfThreads = 0; } threads = process->Threads; numberOfThreads = process->NumberOfThreads; // System Idle Process has one thread per CPU. // They all have a TID of 0, but we can't have // multiple TIDs, so we'll assign unique TIDs. if (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID) { for (i = 0; i < numberOfThreads; i++) { threads[i].ClientId.UniqueThread = UlongToHandle(i); } } // Look for dead threads. { PPH_LIST threadsToRemove = NULL; ULONG enumerationKey = 0; PPH_THREAD_ITEM *threadItem; while (PhEnumHashtable(threadProvider->ThreadHashtable, (PVOID *)&threadItem, &enumerationKey)) { BOOLEAN found = FALSE; // Check if the thread still exists. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; if ((*threadItem)->ThreadId == thread->ClientId.UniqueThread) { found = TRUE; break; } } if (!found) { // Raise the thread removed event. PhInvokeCallback(&threadProvider->ThreadRemovedEvent, *threadItem); if (!threadsToRemove) threadsToRemove = PhCreateList(2); PhAddItemList(threadsToRemove, *threadItem); } } if (threadsToRemove) { PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); for (i = 0; i < threadsToRemove->Count; i++) { PhpRemoveThreadItem( threadProvider, (PPH_THREAD_ITEM)threadsToRemove->Items[i] ); } PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); PhDereferenceObject(threadsToRemove); } } // Go through the queued thread query data. { PSLIST_ENTRY entry; PPH_THREAD_QUERY_DATA data; entry = RtlInterlockedFlushSList(&threadProvider->QueryListHead); while (entry) { data = CONTAINING_RECORD(entry, PH_THREAD_QUERY_DATA, ListEntry); entry = entry->Next; if (data->StartAddressResolveLevel == PhsrlFunction && data->StartAddressString) { PhSwapReference(&data->ThreadItem->StartAddressString, data->StartAddressString); data->ThreadItem->StartAddressResolveLevel = data->StartAddressResolveLevel; } PhMoveReference(&data->ThreadItem->ServiceName, data->ServiceName); data->ThreadItem->JustResolved = TRUE; if (data->StartAddressString) PhDereferenceObject(data->StartAddressString); PhDereferenceObject(data->ThreadItem); PhFree(data); } } // Look for new threads and update existing ones. for (i = 0; i < numberOfThreads; i++) { PSYSTEM_THREAD_INFORMATION thread = &threads[i]; PPH_THREAD_ITEM threadItem; threadItem = PhReferenceThreadItem(threadProvider, thread->ClientId.UniqueThread); if (!threadItem) { PVOID startAddress = NULL; threadItem = PhCreateThreadItem(thread->ClientId.UniqueThread); threadItem->CreateTime = thread->CreateTime; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; threadItem->WaitReason = thread->WaitReason; // Try to open a handle to the thread. if (!NT_SUCCESS(PhOpenThread( &threadItem->ThreadHandle, THREAD_QUERY_INFORMATION, threadItem->ThreadId ))) { PhOpenThread( &threadItem->ThreadHandle, ThreadQueryAccess, threadItem->ThreadId ); } // Get the cycle count. if (WINDOWS_HAS_CYCLE_TIME) { ULONG64 cycles; if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); } } // Initialize the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Try to get the start address. if (threadItem->ThreadHandle) { NtQueryInformationThread( threadItem->ThreadHandle, ThreadQuerySetWin32StartAddress, &startAddress, sizeof(PVOID), NULL ); } if (!startAddress) startAddress = thread->StartAddress; threadItem->StartAddress = (ULONG64)startAddress; // Get the Win32 priority. threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (threadProvider->SymbolsLoadedRunId != 0) { threadItem->StartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); } if (!threadItem->StartAddressString) { threadItem->StartAddressResolveLevel = PhsrlAddress; threadItem->StartAddressString = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2); PhPrintPointer( threadItem->StartAddressString->Buffer, (PVOID)threadItem->StartAddress ); PhTrimToNullTerminatorString(threadItem->StartAddressString); } PhpQueueThreadQuery(threadProvider, threadItem); // Is it a GUI thread? if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { threadItem->IsGuiThread = win32Thread != NULL; } } else { GUITHREADINFO info = { sizeof(GUITHREADINFO) }; threadItem->IsGuiThread = !!GetGUIThreadInfo(HandleToUlong(threadItem->ThreadId), &info); } // Add the thread item to the hashtable. PhAcquireFastLockExclusive(&threadProvider->ThreadHashtableLock); PhAddEntryHashtable(threadProvider->ThreadHashtable, &threadItem); PhReleaseFastLockExclusive(&threadProvider->ThreadHashtableLock); // Raise the thread added event. PhInvokeCallback(&threadProvider->ThreadAddedEvent, threadItem); } else { BOOLEAN modified = FALSE; if (threadItem->JustResolved) modified = TRUE; threadItem->KernelTime = thread->KernelTime; threadItem->UserTime = thread->UserTime; threadItem->Priority = thread->Priority; threadItem->BasePriority = thread->BasePriority; threadItem->State = (KTHREAD_STATE)thread->ThreadState; if (threadItem->WaitReason != thread->WaitReason) { threadItem->WaitReason = thread->WaitReason; modified = TRUE; } // If the resolve level is only at address, it probably // means symbols weren't loaded the last time we // tried to get the start address. Try again. if (threadItem->StartAddressResolveLevel == PhsrlAddress) { if (threadProvider->SymbolsLoadedRunId != 0) { PPH_STRING newStartAddressString; newStartAddressString = PhpGetThreadBasicStartAddress( threadProvider, threadItem->StartAddress, &threadItem->StartAddressResolveLevel ); PhMoveReference( &threadItem->StartAddressString, newStartAddressString ); modified = TRUE; } } // If we couldn't resolve the start address to a // module+offset, use the StartAddress instead // of the Win32StartAddress and try again. // Note that we check the resolve level again // because we may have changed it in the previous // block. if (threadItem->JustResolved && threadItem->StartAddressResolveLevel == PhsrlAddress) { if (threadItem->StartAddress != (ULONG64)thread->StartAddress) { threadItem->StartAddress = (ULONG64)thread->StartAddress; PhpQueueThreadQuery(threadProvider, threadItem); } } // Update the context switch count. { ULONG oldDelta; oldDelta = threadItem->ContextSwitchesDelta.Delta; PhUpdateDelta(&threadItem->ContextSwitchesDelta, thread->ContextSwitches); if (threadItem->ContextSwitchesDelta.Delta != oldDelta) { modified = TRUE; } } // Update the cycle count. if (WINDOWS_HAS_CYCLE_TIME) { ULONG64 cycles; ULONG64 oldDelta; oldDelta = threadItem->CyclesDelta.Delta; if (NT_SUCCESS(PhpGetThreadCycleTime( threadProvider, threadItem, &cycles ))) { PhUpdateDelta(&threadItem->CyclesDelta, cycles); if (threadItem->CyclesDelta.Delta != oldDelta) { modified = TRUE; } } } // Update the CPU time deltas. PhUpdateDelta(&threadItem->CpuKernelDelta, threadItem->KernelTime.QuadPart); PhUpdateDelta(&threadItem->CpuUserDelta, threadItem->UserTime.QuadPart); // Update the CPU usage. // If the cycle time isn't available, we'll fall back to using the CPU time. if (WINDOWS_HAS_CYCLE_TIME && PhEnableCycleCpuUsage && (threadProvider->ProcessId == SYSTEM_IDLE_PROCESS_ID || threadItem->ThreadHandle)) { threadItem->CpuUsage = (FLOAT)threadItem->CyclesDelta.Delta / PhCpuTotalCycleDelta; } else { threadItem->CpuUsage = (FLOAT)(threadItem->CpuKernelDelta.Delta + threadItem->CpuUserDelta.Delta) / (PhCpuKernelDelta.Delta + PhCpuUserDelta.Delta + PhCpuIdleDelta.Delta); } // Update the Win32 priority. { LONG oldPriorityWin32 = threadItem->PriorityWin32; threadItem->PriorityWin32 = GetThreadPriority(threadItem->ThreadHandle); if (threadItem->PriorityWin32 != oldPriorityWin32) { modified = TRUE; } } // Update the GUI thread status. if (threadItem->ThreadHandle && KphIsConnected()) { PVOID win32Thread; if (NT_SUCCESS(KphQueryInformationThread( threadItem->ThreadHandle, KphThreadWin32Thread, &win32Thread, sizeof(PVOID), NULL ))) { BOOLEAN oldIsGuiThread = threadItem->IsGuiThread; threadItem->IsGuiThread = win32Thread != NULL; if (threadItem->IsGuiThread != oldIsGuiThread) modified = TRUE; } } else { GUITHREADINFO info = { sizeof(GUITHREADINFO) }; BOOLEAN oldIsGuiThread = threadItem->IsGuiThread; threadItem->IsGuiThread = !!GetGUIThreadInfo(HandleToUlong(threadItem->ThreadId), &info); if (threadItem->IsGuiThread != oldIsGuiThread) modified = TRUE; } threadItem->JustResolved = FALSE; if (modified) { // Raise the thread modified event. PhInvokeCallback(&threadProvider->ThreadModifiedEvent, threadItem); } PhDereferenceObject(threadItem); } } PhInvokeCallback(&threadProvider->UpdatedEvent, NULL); threadProvider->RunId++; }
VOID NTAPI EtpEtwEventCallback( _In_ PEVENT_RECORD EventRecord ) { if (memcmp(&EventRecord->EventHeader.ProviderId, &DiskIoGuid_I, sizeof(GUID)) == 0) { // DiskIo ET_ETW_DISK_EVENT diskEvent; memset(&diskEvent, 0, sizeof(ET_ETW_DISK_EVENT)); diskEvent.Type = -1; switch (EventRecord->EventHeader.EventDescriptor.Opcode) { case EVENT_TRACE_TYPE_IO_READ: diskEvent.Type = EtEtwDiskReadType; break; case EVENT_TRACE_TYPE_IO_WRITE: diskEvent.Type = EtEtwDiskWriteType; break; default: break; } if (diskEvent.Type != -1) { DiskIo_TypeGroup1 *data = EventRecord->UserData; if (WindowsVersion >= WINDOWS_8) { diskEvent.ClientId.UniqueThread = UlongToHandle(data->IssuingThreadId); diskEvent.ClientId.UniqueProcess = EtThreadIdToProcessId(diskEvent.ClientId.UniqueThread); } else { if (EventRecord->EventHeader.ProcessId != -1) { diskEvent.ClientId.UniqueProcess = UlongToHandle(EventRecord->EventHeader.ProcessId); diskEvent.ClientId.UniqueThread = UlongToHandle(EventRecord->EventHeader.ThreadId); } } diskEvent.IrpFlags = data->IrpFlags; diskEvent.TransferSize = data->TransferSize; diskEvent.FileObject = (PVOID)data->FileObject; diskEvent.HighResResponseTime = data->HighResResponseTime; EtProcessDiskEvent(&diskEvent); EtDiskProcessDiskEvent(&diskEvent); } } else if (memcmp(&EventRecord->EventHeader.ProviderId, &FileIoGuid_I, sizeof(GUID)) == 0) { // FileIo ET_ETW_FILE_EVENT fileEvent; memset(&fileEvent, 0, sizeof(ET_ETW_FILE_EVENT)); fileEvent.Type = -1; switch (EventRecord->EventHeader.EventDescriptor.Opcode) { case 0: // Name fileEvent.Type = EtEtwFileNameType; break; case 32: // FileCreate fileEvent.Type = EtEtwFileCreateType; break; case 35: // FileDelete fileEvent.Type = EtEtwFileDeleteType; break; default: break; } if (fileEvent.Type != -1) { FileIo_Name *data = EventRecord->UserData; fileEvent.FileObject = (PVOID)data->FileObject; PhInitializeStringRef(&fileEvent.FileName, data->FileName); EtDiskProcessFileEvent(&fileEvent); } } else if ( memcmp(&EventRecord->EventHeader.ProviderId, &TcpIpGuid_I, sizeof(GUID)) == 0 || memcmp(&EventRecord->EventHeader.ProviderId, &UdpIpGuid_I, sizeof(GUID)) == 0 ) { // TcpIp/UdpIp ET_ETW_NETWORK_EVENT networkEvent; memset(&networkEvent, 0, sizeof(ET_ETW_NETWORK_EVENT)); networkEvent.Type = -1; switch (EventRecord->EventHeader.EventDescriptor.Opcode) { case EVENT_TRACE_TYPE_SEND: // send networkEvent.Type = EtEtwNetworkSendType; networkEvent.ProtocolType = PH_IPV4_NETWORK_TYPE; break; case EVENT_TRACE_TYPE_RECEIVE: // receive networkEvent.Type = EtEtwNetworkReceiveType; networkEvent.ProtocolType = PH_IPV4_NETWORK_TYPE; break; case EVENT_TRACE_TYPE_SEND + 16: // send ipv6 networkEvent.Type = EtEtwNetworkSendType; networkEvent.ProtocolType = PH_IPV6_NETWORK_TYPE; break; case EVENT_TRACE_TYPE_RECEIVE + 16: // receive ipv6 networkEvent.Type = EtEtwNetworkReceiveType; networkEvent.ProtocolType = PH_IPV6_NETWORK_TYPE; break; } if (memcmp(&EventRecord->EventHeader.ProviderId, &TcpIpGuid_I, sizeof(GUID)) == 0) networkEvent.ProtocolType |= PH_TCP_PROTOCOL_TYPE; else networkEvent.ProtocolType |= PH_UDP_PROTOCOL_TYPE; if (networkEvent.Type != -1) { PH_IP_ENDPOINT source; PH_IP_ENDPOINT destination; if (networkEvent.ProtocolType & PH_IPV4_NETWORK_TYPE) { TcpIpOrUdpIp_IPV4_Header *data = EventRecord->UserData; networkEvent.ClientId.UniqueProcess = UlongToHandle(data->PID); networkEvent.TransferSize = data->size; source.Address.Type = PH_IPV4_NETWORK_TYPE; source.Address.Ipv4 = data->saddr; source.Port = _byteswap_ushort(data->sport); destination.Address.Type = PH_IPV4_NETWORK_TYPE; destination.Address.Ipv4 = data->daddr; destination.Port = _byteswap_ushort(data->dport); } else if (networkEvent.ProtocolType & PH_IPV6_NETWORK_TYPE) { TcpIpOrUdpIp_IPV6_Header *data = EventRecord->UserData; networkEvent.ClientId.UniqueProcess = UlongToHandle(data->PID); networkEvent.TransferSize = data->size; source.Address.Type = PH_IPV6_NETWORK_TYPE; source.Address.In6Addr = data->saddr; source.Port = _byteswap_ushort(data->sport); destination.Address.Type = PH_IPV6_NETWORK_TYPE; destination.Address.In6Addr = data->daddr; destination.Port = _byteswap_ushort(data->dport); } networkEvent.LocalEndpoint = source; if (networkEvent.ProtocolType & PH_TCP_PROTOCOL_TYPE) networkEvent.RemoteEndpoint = destination; EtProcessNetworkEvent(&networkEvent); } } }
INT_PTR CALLBACK PhpSessionPropertiesDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { ULONG sessionId = (ULONG)lParam; WINSTATIONINFORMATION winStationInfo; BOOLEAN haveWinStationInfo; WINSTATIONCLIENT clientInfo; BOOLEAN haveClientInfo; ULONG returnLength; PWSTR stateString; SetProp(hwndDlg, L"SessionId", UlongToHandle(sessionId)); PhCenterWindow(hwndDlg, GetParent(hwndDlg)); // Query basic session information haveWinStationInfo = WinStationQueryInformationW( NULL, sessionId, WinStationInformation, &winStationInfo, sizeof(WINSTATIONINFORMATION), &returnLength ); // Query client information haveClientInfo = WinStationQueryInformationW( NULL, sessionId, WinStationClient, &clientInfo, sizeof(WINSTATIONCLIENT), &returnLength ); if (haveWinStationInfo) { SetDlgItemText(hwndDlg, IDC_USERNAME, PhaFormatString(L"%s\\%s", winStationInfo.Domain, winStationInfo.UserName)->Buffer); } SetDlgItemInt(hwndDlg, IDC_SESSIONID, sessionId, FALSE); if (haveWinStationInfo) { if (PhFindStringSiKeyValuePairs( PhpConnectStatePairs, sizeof(PhpConnectStatePairs), winStationInfo.ConnectState, &stateString )) { SetDlgItemText(hwndDlg, IDC_STATE, stateString); } } if (haveWinStationInfo && winStationInfo.LogonTime.QuadPart != 0) { SYSTEMTIME systemTime; PPH_STRING time; PhLargeIntegerToLocalSystemTime(&systemTime, &winStationInfo.LogonTime); time = PhFormatDateTime(&systemTime); SetDlgItemText(hwndDlg, IDC_LOGONTIME, time->Buffer); PhDereferenceObject(time); } if (haveWinStationInfo && winStationInfo.ConnectTime.QuadPart != 0) { SYSTEMTIME systemTime; PPH_STRING time; PhLargeIntegerToLocalSystemTime(&systemTime, &winStationInfo.ConnectTime); time = PhFormatDateTime(&systemTime); SetDlgItemText(hwndDlg, IDC_CONNECTTIME, time->Buffer); PhDereferenceObject(time); } if (haveWinStationInfo && winStationInfo.DisconnectTime.QuadPart != 0) { SYSTEMTIME systemTime; PPH_STRING time; PhLargeIntegerToLocalSystemTime(&systemTime, &winStationInfo.DisconnectTime); time = PhFormatDateTime(&systemTime); SetDlgItemText(hwndDlg, IDC_DISCONNECTTIME, time->Buffer); PhDereferenceObject(time); } if (haveWinStationInfo && winStationInfo.LastInputTime.QuadPart != 0) { SYSTEMTIME systemTime; PPH_STRING time; PhLargeIntegerToLocalSystemTime(&systemTime, &winStationInfo.LastInputTime); time = PhFormatDateTime(&systemTime); SetDlgItemText(hwndDlg, IDC_LASTINPUTTIME, time->Buffer); PhDereferenceObject(time); } if (haveClientInfo && clientInfo.ClientName[0] != 0) { WCHAR addressString[65]; SetDlgItemText(hwndDlg, IDC_CLIENTNAME, clientInfo.ClientName); if (clientInfo.ClientAddressFamily == AF_INET6) { struct in6_addr address; ULONG i; PUSHORT in; PUSHORT out; // IPv6 is special - the client address data is a reversed version of // the real address. in = (PUSHORT)clientInfo.ClientAddress; out = (PUSHORT)address.u.Word; for (i = 8; i != 0; i--) { *out = _byteswap_ushort(*in); in++; out++; } RtlIpv6AddressToString(&address, addressString); } else { wcscpy_s(addressString, 65, clientInfo.ClientAddress); } SetDlgItemText(hwndDlg, IDC_CLIENTADDRESS, addressString); SetDlgItemText(hwndDlg, IDC_CLIENTDISPLAY, PhaFormatString(L"%ux%u@%u", clientInfo.HRes, clientInfo.VRes, clientInfo.ColorDepth)->Buffer ); } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), TRUE); } break; case WM_DESTROY: { RemoveProp(hwndDlg, L"SessionId"); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; } } break; } return FALSE; }
VOID EtpNetworkIconUpdateCallback( _In_ struct _PH_NF_ICON *Icon, _Out_ PVOID *NewIconOrBitmap, _Out_ PULONG Flags, _Out_ PPH_STRING *NewText, _In_opt_ PVOID Context ) { static PH_GRAPH_DRAW_INFO drawInfo = { 16, 16, PH_GRAPH_USE_LINE_2, 2, RGB(0x00, 0x00, 0x00), 16, NULL, NULL, 0, 0, 0, 0 }; ULONG maxDataCount; ULONG lineDataCount; PFLOAT lineData1; PFLOAT lineData2; FLOAT max; ULONG i; HBITMAP bitmap; PVOID bits; HDC hdc; HBITMAP oldBitmap; HANDLE maxNetworkProcessId; PPH_PROCESS_ITEM maxNetworkProcessItem; PH_FORMAT format[6]; // Icon Icon->Pointers->BeginBitmap(&drawInfo.Width, &drawInfo.Height, &bitmap, &bits, &hdc, &oldBitmap); maxDataCount = drawInfo.Width / 2 + 1; lineData1 = _alloca(maxDataCount * sizeof(FLOAT)); lineData2 = _alloca(maxDataCount * sizeof(FLOAT)); lineDataCount = min(maxDataCount, EtNetworkReceiveHistory.Count); max = 1024 * 1024; // minimum scaling of 1 MB. for (i = 0; i < lineDataCount; i++) { lineData1[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&EtNetworkReceiveHistory, i); lineData2[i] = (FLOAT)PhGetItemCircularBuffer_ULONG(&EtNetworkSendHistory, i); if (max < lineData1[i] + lineData2[i]) max = lineData1[i] + lineData2[i]; } PhDivideSinglesBySingle(lineData1, max, lineDataCount); PhDivideSinglesBySingle(lineData2, max, lineDataCount); drawInfo.LineDataCount = lineDataCount; drawInfo.LineData1 = lineData1; drawInfo.LineData2 = lineData2; drawInfo.LineColor1 = PhGetIntegerSetting(L"ColorIoReadOther"); drawInfo.LineColor2 = PhGetIntegerSetting(L"ColorIoWrite"); drawInfo.LineBackColor1 = PhHalveColorBrightness(drawInfo.LineColor1); drawInfo.LineBackColor2 = PhHalveColorBrightness(drawInfo.LineColor2); if (bits) PhDrawGraphDirect(hdc, bits, &drawInfo); SelectObject(hdc, oldBitmap); *NewIconOrBitmap = bitmap; *Flags = PH_NF_UPDATE_IS_BITMAP; // Text if (EtMaxNetworkHistory.Count != 0) maxNetworkProcessId = UlongToHandle(PhGetItemCircularBuffer_ULONG(&EtMaxNetworkHistory, 0)); else maxNetworkProcessId = NULL; if (maxNetworkProcessId) maxNetworkProcessItem = PhReferenceProcessItem(maxNetworkProcessId); else maxNetworkProcessItem = NULL; PhInitFormatS(&format[0], L"Network\nR: "); PhInitFormatSize(&format[1], EtNetworkReceiveDelta.Delta); PhInitFormatS(&format[2], L"\nS: "); PhInitFormatSize(&format[3], EtNetworkSendDelta.Delta); if (maxNetworkProcessItem) { PhInitFormatC(&format[4], '\n'); PhInitFormatSR(&format[5], maxNetworkProcessItem->ProcessName->sr); } *NewText = PhFormat(format, maxNetworkProcessItem ? 6 : 4, 128); if (maxNetworkProcessItem) PhDereferenceObject(maxNetworkProcessItem); }
/*************************************************************************** * DirectSoundCaptureEnumerateW [DSOUND.8] * * Enumerate all DirectSound drivers installed in the system. * * PARAMS * lpDSEnumCallback [I] Address of callback function. * lpContext [I] Address of user defined context passed to callback function. * * RETURNS * Success: DS_OK * Failure: DSERR_INVALIDPARAM */ HRESULT WINAPI DirectSoundCaptureEnumerateW( LPDSENUMCALLBACKW lpDSEnumCallback, LPVOID lpContext) { unsigned devs, wid; DSDRIVERDESC desc; GUID guid; int err; WCHAR wDesc[MAXPNAMELEN]; WCHAR wName[MAXPNAMELEN]; TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext ); if (lpDSEnumCallback == NULL) { WARN("invalid parameter: lpDSEnumCallback == NULL\n"); return DSERR_INVALIDPARAM; } setup_dsound_options(); devs = waveInGetNumDevs(); if (devs > 0) { if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) { for (wid = 0; wid < devs; ++wid) { if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) { err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n", "Primary Sound Capture Driver",desc.szDrvname,lpContext); MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1, wDesc, sizeof(wDesc)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wName, sizeof(wName)/sizeof(WCHAR) ); wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0'; if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE) return DS_OK; } } } } } for (wid = 0; wid < devs; ++wid) { err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n", debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDesc, sizeof(wDesc)/sizeof(WCHAR) ); wDesc[(sizeof(wDesc)/sizeof(WCHAR)) - 1] = '\0'; MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wName, sizeof(wName)/sizeof(WCHAR) ); wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0'; if (lpDSEnumCallback(&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE) return DS_OK; } } return DS_OK; }
PPH_LIST EnumerateAppDomainIpcBlockWow64( _In_ HANDLE ProcessHandle, _In_ AppDomainEnumerationIPCBlock_Wow64* AppDomainIpcBlock ) { LARGE_INTEGER timeout; SIZE_T appDomainInfoBlockLength; HANDLE legacyPrivateBlockMutexHandle = NULL; AppDomainEnumerationIPCBlock_Wow64 tempBlock; AppDomainInfo_Wow64* appDomainInfoBlock = NULL; PPH_LIST appDomainsList = PhCreateList(1); // If the mutex isn't filled in, the CLR is either starting up or shutting down if (!AppDomainIpcBlock->Mutex) { goto CleanupExit; } // Dup the valid mutex handle into this process. if (!NT_SUCCESS(NtDuplicateObject( ProcessHandle, UlongToHandle(AppDomainIpcBlock->Mutex), NtCurrentProcess(), &legacyPrivateBlockMutexHandle, GENERIC_ALL, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ))) { goto CleanupExit; } // Acquire the mutex, only waiting two seconds. // We can't actually gaurantee that the target put a mutex object in here. if (NtWaitForSingleObject( legacyPrivateBlockMutexHandle, FALSE, PhTimeoutFromMilliseconds(&timeout, 2000) ) == STATUS_WAIT_0) { // Make sure the mutex handle is still valid. If its not, then we lost a shutdown race. if (!AppDomainIpcBlock->Mutex) { goto CleanupExit; } } else { // Again, landing here is most probably a shutdown race. goto CleanupExit; } // Beware: If the target pid is not properly honoring the mutex, the data in the IPC block may still shift underneath us. // If we get here, then hMutex is held by this process. // Make a copy of the IPC block so that we can gaurantee that it's not changing on us. memcpy(&tempBlock, AppDomainIpcBlock, sizeof(AppDomainEnumerationIPCBlock_Wow64)); // It's possible the process will not have any appdomains. if ((tempBlock.ListOfAppDomains == 0) != (tempBlock.SizeInBytes == 0)) { goto CleanupExit; } // All the data in the IPC block is signed integers. They should never be negative, // so check that now. if ((tempBlock.TotalSlots < 0) || (tempBlock.NumOfUsedSlots < 0) || (tempBlock.LastFreedSlot < 0) || (tempBlock.SizeInBytes < 0) || (tempBlock.ProcessNameLengthInBytes < 0)) { goto CleanupExit; } // Allocate memory to read the remote process' memory into appDomainInfoBlockLength = tempBlock.SizeInBytes; // Check other invariants. if (appDomainInfoBlockLength != tempBlock.TotalSlots * sizeof(AppDomainInfo_Wow64)) { goto CleanupExit; } appDomainInfoBlock = (AppDomainInfo_Wow64*)PhAllocate(appDomainInfoBlockLength); memset(appDomainInfoBlock, 0, appDomainInfoBlockLength); if (!NT_SUCCESS(NtReadVirtualMemory( ProcessHandle, UlongToPtr(tempBlock.ListOfAppDomains), appDomainInfoBlock, appDomainInfoBlockLength, NULL ))) { PhFree(appDomainInfoBlock); goto CleanupExit; } // Collect all the AppDomain names into a list of strings. for (INT i = 0; i < tempBlock.NumOfUsedSlots; i++) { SIZE_T appDomainNameLength; PVOID appDomainName; if (!appDomainInfoBlock[i].AppDomainName) continue; // Should be positive, and at least have a null-terminator character. if (appDomainInfoBlock[i].NameLengthInBytes <= 1) continue; // Make sure buffer has right geometry. if (appDomainInfoBlock[i].NameLengthInBytes < 0) continue; // If it's not on a WCHAR boundary, then we may have a 1-byte buffer-overflow. appDomainNameLength = appDomainInfoBlock[i].NameLengthInBytes / sizeof(WCHAR); if ((appDomainNameLength * sizeof(WCHAR)) != appDomainInfoBlock[i].NameLengthInBytes) continue; // It should at least have 1 char for the null terminator. if (appDomainNameLength < 1) continue; // We know the string is a well-formed null-terminated string, // but beyond that, we can't verify that the data is actually truthful. appDomainName = PhAllocate(appDomainInfoBlock[i].NameLengthInBytes + 1); memset(appDomainName, 0, appDomainInfoBlock[i].NameLengthInBytes + 1); if (!NT_SUCCESS(NtReadVirtualMemory( ProcessHandle, UlongToPtr(appDomainInfoBlock[i].AppDomainName), appDomainName, appDomainInfoBlock[i].NameLengthInBytes, NULL ))) { PhFree(appDomainName); continue; } PhAddItemList(appDomainsList, appDomainName); } CleanupExit: if (appDomainInfoBlock) { PhFree(appDomainInfoBlock); } if (legacyPrivateBlockMutexHandle) { NtReleaseMutant(legacyPrivateBlockMutexHandle, NULL); NtClose(legacyPrivateBlockMutexHandle); } return appDomainsList; }
static void test_midiOut_device(UINT udev, HWND hwnd) { HMIDIOUT hm; MMRESULT rc; MIDIOUTCAPSA capsA; DWORD ovolume; UINT udevid; MIDIHDR mhdr; rc = midiOutGetDevCapsA(udev, &capsA, sizeof(capsA)); ok(!rc, "midiOutGetDevCaps(dev=%d) rc=%s\n", udev, mmsys_error(rc)); if (!rc) { trace("* %s: manufacturer=%d, product=%d, tech=%d, support=%X: %d voices, %d notes\n", capsA.szPname, capsA.wMid, capsA.wPid, capsA.wTechnology, capsA.dwSupport, capsA.wVoices, capsA.wNotes); ok(!((MIDIMAPPER==udev) ^ (MOD_MAPPER==capsA.wTechnology)), "technology %d on device %d\n", capsA.wTechnology, udev); if (MOD_MIDIPORT == capsA.wTechnology) { ok(capsA.wVoices == 0 && capsA.wNotes == 0, "external device with notes or voices\n"); ok(capsA.wChannelMask == 0xFFFF, "external device channel mask %x\n", capsA.wChannelMask); ok(!(capsA.dwSupport & (MIDICAPS_VOLUME|MIDICAPS_LRVOLUME|MIDICAPS_CACHE)), "external device support=%X\n", capsA.dwSupport); } } if (hwnd) rc = midiOutOpen(&hm, udev, (DWORD_PTR)hwnd, (DWORD_PTR)MYCBINST, CALLBACK_WINDOW); else rc = midiOutOpen(&hm, udev, (DWORD_PTR)callback_func, (DWORD_PTR)MYCBINST, CALLBACK_FUNCTION); if (rc == MMSYSERR_NOTSUPPORTED) { skip( "MIDI out not supported\n" ); return; } ok(!rc, "midiOutOpen(dev=%d) rc=%s\n", udev, mmsys_error(rc)); if (rc) return; test_notification(hwnd, "midiOutOpen", MOM_OPEN, 0); rc = midiOutGetVolume(hm, &ovolume); ok((capsA.dwSupport & MIDICAPS_VOLUME) ? rc==MMSYSERR_NOERROR : rc==MMSYSERR_NOTSUPPORTED, "midiOutGetVolume rc=%s\n", mmsys_error(rc)); /* The native mapper responds with FFFFFFFF initially, * real devices with the volume GUI SW-synth settings. */ if (!rc) trace("Current volume %x on device %d\n", ovolume, udev); /* The W95 ESFM Synthesis device reports NOTENABLED although * GetVolume by handle works and music plays. */ rc = midiOutGetVolume(UlongToHandle(udev), &ovolume); ok((capsA.dwSupport & MIDICAPS_VOLUME) ? rc==MMSYSERR_NOERROR || broken(rc==MMSYSERR_NOTENABLED) : rc==MMSYSERR_NOTSUPPORTED, "midiOutGetVolume(dev=%d) rc=%s\n", udev, mmsys_error(rc)); rc = midiOutGetVolume(hm, NULL); ok(rc==MMSYSERR_INVALPARAM, "midiOutGetVolume NULL rc=%s\n", mmsys_error(rc)); /* Tests with midiOutSetvolume show that the midi mapper forwards * the value to the real device, but Get initially always reports * FFFFFFFF. Therefore, a Get+SetVolume pair with the mapper is * not adequate to restore the value prior to tests. */ if (winetest_interactive && (capsA.dwSupport & MIDICAPS_VOLUME)) { DWORD volume2 = (ovolume < 0x80000000) ? 0xC000C000 : 0x40004000; rc = midiOutSetVolume(hm, volume2); ok(!rc, "midiOutSetVolume rc=%s\n", mmsys_error(rc)); if (!rc) { DWORD volume3; rc = midiOutGetVolume(hm, &volume3); ok(!rc, "midiOutGetVolume new rc=%s\n", mmsys_error(rc)); if (!rc) trace("New volume %x on device %d\n", volume3, udev); todo_wine ok(volume2==volume3, "volume Set %x = Get %x\n", volume2, volume3); rc = midiOutSetVolume(hm, ovolume); ok(!rc, "midiOutSetVolume restore rc=%s\n", mmsys_error(rc)); } } rc = midiOutGetDevCapsA((UINT_PTR)hm, &capsA, sizeof(capsA)); ok(!rc, "midiOutGetDevCaps(dev=%d) by handle rc=%s\n", udev, mmsys_error(rc)); rc = midiInGetDevCapsA((UINT_PTR)hm, (LPMIDIINCAPSA)&capsA, sizeof(DWORD)); ok(rc==MMSYSERR_BADDEVICEID, "midiInGetDevCaps(dev=%d) by out handle rc=%s\n", udev, mmsys_error(rc)); { DWORD e = 0x006F4893; /* velocity, note (#69 would be 440Hz) channel */ trace("ShortMsg type %x\n", LOBYTE(LOWORD(e))); rc = midiOutShortMsg(hm, e); ok(!rc, "midiOutShortMsg rc=%s\n", mmsys_error(rc)); if (!rc) Sleep(400); /* Hear note */ } memset(&mhdr, 0, sizeof(mhdr)); mhdr.dwFlags = 0; mhdr.dwUser = 0x56FA552C; mhdr.dwOffset = 0xDEADBEEF; mhdr.dwBufferLength = 70000; /* > 64KB! */ mhdr.lpData = HeapAlloc(GetProcessHeap(), 0 , mhdr.dwBufferLength); ok(mhdr.lpData!=NULL, "No %d bytes of memory!\n", mhdr.dwBufferLength); if (mhdr.lpData) { rc = midiOutLongMsg(hm, &mhdr, sizeof(mhdr)); ok(rc==MIDIERR_UNPREPARED, "midiOutLongMsg unprepared rc=%s\n", mmsys_error(rc)); test_notification(hwnd, "midiOutLong unprepared", 0, WHATEVER); rc = midiOutPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset)-1); ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare tiny rc=%s\n", mmsys_error(rc)); rc = midiOutPrepareHeader(hm, &mhdr, offsetof(MIDIHDR,dwOffset)); ok(!rc, "midiOutPrepare old size rc=%s\n", mmsys_error(rc)); rc = midiOutPrepareHeader(hm, &mhdr, sizeof(mhdr)); ok(!rc, "midiOutPrepare rc=%s\n", mmsys_error(rc)); rc = midiOutUnprepareHeader(hm, &mhdr, sizeof(mhdr)); ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc)); trace("MIDIHDR flags=%x when unsent\n", mhdr.dwFlags); HeapFree(GetProcessHeap(), 0, mhdr.lpData); } ok(mhdr.dwUser==0x56FA552C, "MIDIHDR.dwUser changed to %lx\n", mhdr.dwUser); ok(mhdr.dwOffset==0xDEADBEEF, "MIDIHDR.dwOffset changed to %x\n", mhdr.dwOffset); rc = midiOutGetID(hm, &udevid); ok(!rc, "midiOutGetID rc=%s\n", mmsys_error(rc)); if(!rc) ok(udevid==udev, "midiOutGetID gives %d, expect %d\n", udevid, udev); rc = midiOutReset(hm); /* Quiet everything */ ok(!rc, "midiOutReset rc=%s\n", mmsys_error(rc)); rc = midiOutClose(hm); ok(!rc, "midiOutClose rc=%s\n", mmsys_error(rc)); test_notification(hwnd, "midiOutClose", MOM_CLOSE, 0); test_notification(hwnd, "midiOut over", 0, WHATEVER); }
static HRESULT DSPROPERTY_DescriptionW( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = pPropData; HRESULT err; GUID dev_guid; ULONG wod, wid, wodn, widn; DSDRIVERDESC desc; TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", pPropData,cbPropData,pcbReturned); TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId)); if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) { /* default device of type specified by ppd->DataFlow */ if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) { TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n"); ppd->DeviceId = DSDEVID_DefaultCapture; } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) { TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n"); ppd->DeviceId = DSDEVID_DefaultPlayback; } else { WARN("DataFlow=Unknown(%d)\n", ppd->DataFlow); return E_PROP_ID_UNSUPPORTED; } } setup_dsound_options(); GetDeviceID(&ppd->DeviceId, &dev_guid); wodn = waveOutGetNumDevs(); widn = waveInGetNumDevs(); wid = wod = dev_guid.Data4[7]; if (!memcmp(&dev_guid, &DSOUND_renderer_guids[0], sizeof(GUID)-1) && wod < wodn) { ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; ppd->WaveDeviceId = wod; } else if (!memcmp(&dev_guid, &DSOUND_capture_guids[0], sizeof(GUID)-1) && wid < widn) { ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; ppd->WaveDeviceId = wid; } else { WARN("Device not found\n"); return E_PROP_ID_UNSUPPORTED; } if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) err = waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel); else err = waveInMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel); if (err != MMSYSERR_NOERROR) { WARN("waveMessage(DRV_QUERYDSOUNDDESC) failed!\n"); return E_PROP_ID_UNSUPPORTED; } else { /* FIXME: Still a memory leak.. */ int desclen, modlen; static WCHAR wInterface[] = { 'I','n','t','e','r','f','a','c','e',0 }; modlen = MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, NULL, 0 ); desclen = MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, NULL, 0 ); ppd->Module = HeapAlloc(GetProcessHeap(),0,modlen*sizeof(WCHAR)); ppd->Description = HeapAlloc(GetProcessHeap(),0,desclen*sizeof(WCHAR)); ppd->Interface = wInterface; if (!ppd->Description || !ppd->Module) { WARN("Out of memory\n"); HeapFree(GetProcessHeap(), 0, ppd->Description); HeapFree(GetProcessHeap(), 0, ppd->Module); ppd->Description = ppd->Module = NULL; return E_OUTOFMEMORY; } MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->Module, modlen ); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->Description, desclen ); } ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; if (pcbReturned) { *pcbReturned = sizeof(*ppd); TRACE("*pcbReturned=%d\n", *pcbReturned); } return S_OK; }