BOOLEAN xProtectHandle( HANDLE hObject ) { NTSTATUS Status; OBJECT_HANDLE_FLAG_INFORMATION HandleInfo; Status = NtQueryObject( hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof( HandleInfo ), NULL ); if (NT_SUCCESS( Status )) { HandleInfo.ProtectFromClose = TRUE; Status = NtSetInformationObject( hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof( HandleInfo ) ); if (NT_SUCCESS( Status )) { return TRUE; } } return FALSE; }
NTSTATUS KphDisconnect( VOID ) { NTSTATUS status; OBJECT_HANDLE_FLAG_INFORMATION handleFlagInfo; if (!PhKphHandle) return STATUS_ALREADY_DISCONNECTED; // Unprotect the handle. handleFlagInfo.Inherit = FALSE; handleFlagInfo.ProtectFromClose = FALSE; NtSetInformationObject( PhKphHandle, ObjectHandleFlagInformation, &handleFlagInfo, sizeof(OBJECT_HANDLE_FLAG_INFORMATION) ); status = NtClose(PhKphHandle); PhKphHandle = NULL; return status; }
/*++ * @name UnProtectHandle * @implemented NT5.2 * * The UnProtectHandle routine unprotects an object handle against closure. * * @return TRUE or FALSE. * * @remarks None. * *--*/ BOOLEAN NTAPI UnProtectHandle(IN HANDLE ObjectHandle) { NTSTATUS Status; OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; /* Query current state */ Status = NtQueryObject(ObjectHandle, ObjectHandleFlagInformation, &HandleInfo, sizeof(HandleInfo), NULL); if (NT_SUCCESS(Status)) { /* Disable protect from close */ HandleInfo.ProtectFromClose = FALSE; Status = NtSetInformationObject(ObjectHandle, ObjectHandleFlagInformation, &HandleInfo, sizeof(HandleInfo)); if (NT_SUCCESS(Status)) return TRUE; } /* We failed to or set the state */ return FALSE; }
NTSTATUS KphConnect( _In_opt_ PWSTR DeviceName ) { NTSTATUS status; HANDLE kphHandle; UNICODE_STRING objectName; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK isb; OBJECT_HANDLE_FLAG_INFORMATION handleFlagInfo; if (PhKphHandle) return STATUS_ADDRESS_ALREADY_EXISTS; if (DeviceName) RtlInitUnicodeString(&objectName, DeviceName); else RtlInitUnicodeString(&objectName, KPH_DEVICE_NAME); InitializeObjectAttributes( &objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL ); status = NtOpenFile( &kphHandle, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &objectAttributes, &isb, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE ); if (NT_SUCCESS(status)) { // Protect the handle from being closed. handleFlagInfo.Inherit = FALSE; handleFlagInfo.ProtectFromClose = TRUE; NtSetInformationObject( kphHandle, ObjectHandleFlagInformation, &handleFlagInfo, sizeof(OBJECT_HANDLE_FLAG_INFORMATION) ); PhKphHandle = kphHandle; } return status; }
/* * @implemented */ BOOL WINAPI SetHandleInformation(IN HANDLE hObject, IN DWORD dwMask, IN DWORD dwFlags) { OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; ULONG BytesWritten; NTSTATUS Status; hObject = TranslateStdHandle(hObject); if (IsConsoleHandle(hObject)) { /* FIXME: SetConsoleHandleInformation required */ UNIMPLEMENTED; BaseSetLastNTError(STATUS_NOT_IMPLEMENTED); return FALSE; } Status = NtQueryObject(hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), &BytesWritten); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return FALSE; } if (dwMask & HANDLE_FLAG_INHERIT) { HandleInfo.Inherit = (dwFlags & HANDLE_FLAG_INHERIT) != 0; } if (dwMask & HANDLE_FLAG_PROTECT_FROM_CLOSE) { HandleInfo.ProtectFromClose = (dwFlags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0; } Status = NtSetInformationObject(hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(HandleInfo)); if (NT_SUCCESS(Status)) return TRUE; BaseSetLastNTError(Status); return FALSE; }
/* * @implemented */ BOOL WINAPI SetHandleInformation (HANDLE hObject, DWORD dwMask, DWORD dwFlags) { OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; ULONG BytesWritten; NTSTATUS Status; hObject = TranslateStdHandle(hObject); Status = NtQueryObject (hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), &BytesWritten); if (NT_SUCCESS(Status)) { if (dwMask & HANDLE_FLAG_INHERIT) HandleInfo.Inherit = (dwFlags & HANDLE_FLAG_INHERIT) != 0; if (dwMask & HANDLE_FLAG_PROTECT_FROM_CLOSE) HandleInfo.ProtectFromClose = (dwFlags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0; Status = NtSetInformationObject (hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION)); if(!NT_SUCCESS(Status)) { SetLastErrorByStatus (Status); return FALSE; } return TRUE; } else { SetLastErrorByStatus (Status); return FALSE; } }
INT_PTR CALLBACK NetworkOutputDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PNETWORK_OUTPUT_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = (PNETWORK_OUTPUT_CONTEXT)lParam; SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PNETWORK_OUTPUT_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) RemoveProp(hwndDlg, L"Context"); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { WCHAR addressString[65]; HANDLE pipeWriteHandle; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); context->WindowHandle = hwndDlg; PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_TEXT), NULL, PH_ANCHOR_ALL); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT); if (context->Address.Type == PH_IPV4_NETWORK_TYPE) RtlIpv4AddressToString(&context->Address.InAddr, addressString); else RtlIpv6AddressToString(&context->Address.In6Addr, addressString); switch (context->Action) { case NETWORK_ACTION_PING: case NETWORK_ACTION_TRACEROUTE: if (context->Action == NETWORK_ACTION_PING) { SetWindowText(hwndDlg, PhaFormatString(L"Pinging %s...", addressString)->Buffer); } else { SetWindowText(hwndDlg, PhaFormatString(L"Tracing route to %s...", addressString)->Buffer); } // Doing this properly would be too complex, so we'll just // execute ping.exe/traceroute.exe and display its output. if (CreatePipe(&context->PipeReadHandle, &pipeWriteHandle, NULL, 0)) { STARTUPINFO startupInfo = { sizeof(startupInfo) }; PPH_STRING command; OBJECT_HANDLE_FLAG_INFORMATION flagInfo; startupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); startupInfo.hStdOutput = pipeWriteHandle; startupInfo.hStdError = pipeWriteHandle; startupInfo.wShowWindow = SW_HIDE; if (context->Action == NETWORK_ACTION_PING) { command = PhaFormatString( L"%s\\system32\\ping.exe %s", USER_SHARED_DATA->NtSystemRoot, addressString ); } else { command = PhaFormatString( L"%s\\system32\\tracert.exe %s", USER_SHARED_DATA->NtSystemRoot, addressString ); } // Allow the write handle to be inherited. flagInfo.Inherit = TRUE; flagInfo.ProtectFromClose = FALSE; NtSetInformationObject( pipeWriteHandle, ObjectHandleFlagInformation, &flagInfo, sizeof(OBJECT_HANDLE_FLAG_INFORMATION) ); PhCreateProcessWin32Ex( NULL, command->Buffer, NULL, NULL, &startupInfo, PH_CREATE_PROCESS_INHERIT_HANDLES, NULL, NULL, &context->ProcessHandle, NULL ); // Essential; when the process exits, the last instance of the pipe // will be disconnected and our thread will exit. NtClose(pipeWriteHandle); // Create a thread which will wait for output and display it. context->ThreadHandle = PhCreateThread(0, NetworkWorkerThreadStart, context); } break; } } break; case WM_DESTROY: { PhAcquireQueuedLockExclusive(&context->WindowHandleLock); context->WindowHandle = NULL; PhReleaseQueuedLockExclusive(&context->WindowHandleLock); if (context->ProcessHandle) { NtTerminateProcess(context->ProcessHandle, STATUS_SUCCESS); NtClose(context->ProcessHandle); } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; } } break; case WM_SIZE: PhLayoutManagerLayout(&context->LayoutManager); break; case NTM_DONE: { PPH_STRING windowText = PhGetWindowText(hwndDlg); if (windowText) { SetWindowText(hwndDlg, PhaFormatString(L"%s Finished.", windowText->Buffer)->Buffer); PhDereferenceObject(windowText); } } break; case NTM_RECEIVED: { OEM_STRING inputString; UNICODE_STRING convertedString; if (wParam != 0) { inputString.Buffer = (PCHAR)lParam; inputString.Length = (USHORT)wParam; if (NT_SUCCESS(RtlOemStringToUnicodeString(&convertedString, &inputString, TRUE))) { PhAppendStringBuilderEx(&context->ReceivedString, convertedString.Buffer, convertedString.Length); RtlFreeUnicodeString(&convertedString); // Remove leading newlines. if ( context->ReceivedString.String->Length >= 2 * 2 && context->ReceivedString.String->Buffer[0] == '\r' && context->ReceivedString.String->Buffer[1] == '\n' ) { PhRemoveStringBuilder(&context->ReceivedString, 0, 2); } SetDlgItemText(hwndDlg, IDC_TEXT, context->ReceivedString.String->Buffer); SendMessage( GetDlgItem(hwndDlg, IDC_TEXT), EM_SETSEL, context->ReceivedString.String->Length / 2 - 1, context->ReceivedString.String->Length / 2 - 1 ); SendMessage(GetDlgItem(hwndDlg, IDC_TEXT), WM_VSCROLL, SB_BOTTOM, 0); } } } break; } return FALSE; }
VOID NTAPI BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll) { NTSTATUS Status; BOOLEAN Success; WCHAR Buffer[MAX_PATH]; PWCHAR HeapBuffer; UNICODE_STRING SystemRootString; UNICODE_STRING UnexpandedSystemRootString = RTL_CONSTANT_STRING(L"%SystemRoot%"); UNICODE_STRING BaseSrvCSDString; UNICODE_STRING BaseSrvWindowsDirectory; UNICODE_STRING BaseSrvWindowsSystemDirectory; UNICODE_STRING BnoString; OBJECT_ATTRIBUTES ObjectAttributes; ULONG SessionId; HANDLE BaseSrvNamedObjectDirectory; HANDLE BaseSrvRestrictedObjectDirectory; PACL BnoDacl, BnoRestrictedDacl; PSECURITY_DESCRIPTOR BnoSd; HANDLE SymHandle; UNICODE_STRING DirectoryName, SymlinkName; ULONG LuidEnabled; RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[2] = { { NULL, RTL_QUERY_REGISTRY_DIRECT, L"CSDVersion", &BaseSrvCSDString, REG_NONE, NULL, 0 }, {0} }; /* Initialize the memory */ BaseSrvHeap = RtlGetProcessHeap(); // Initialize our own heap. BaseSrvSharedHeap = LoadedServerDll->SharedSection; // Get the CSR shared heap. /* Get the session ID */ SessionId = NtCurrentPeb()->SessionId; /* Get the Windows directory */ RtlInitEmptyUnicodeString(&SystemRootString, Buffer, sizeof(Buffer)); Status = RtlExpandEnvironmentStrings_U(NULL, &UnexpandedSystemRootString, &SystemRootString, NULL); ASSERT(NT_SUCCESS(Status)); /* Create the base directory */ Buffer[SystemRootString.Length / sizeof(WCHAR)] = UNICODE_NULL; Success = RtlCreateUnicodeString(&BaseSrvWindowsDirectory, SystemRootString.Buffer); ASSERT(Success); /* Create the system directory */ wcscat(SystemRootString.Buffer, L"\\System32"); Success = RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory, SystemRootString.Buffer); ASSERT(Success); /* Create the kernel32 path */ wcscat(SystemRootString.Buffer, L"\\kernel32.dll"); Success = RtlCreateUnicodeString(&BaseSrvKernel32DllPath, SystemRootString.Buffer); ASSERT(Success); /* FIXME: Check Session ID */ wcscpy(Buffer, L"\\BaseNamedObjects"); RtlInitUnicodeString(&BnoString, Buffer); /* Allocate the server data */ BaseStaticServerData = RtlAllocateHeap(BaseSrvSharedHeap, HEAP_ZERO_MEMORY, sizeof(BASE_STATIC_SERVER_DATA)); ASSERT(BaseStaticServerData != NULL); /* Process timezone information */ BaseStaticServerData->TermsrvClientTimeZoneId = TIME_ZONE_ID_INVALID; BaseStaticServerData->TermsrvClientTimeZoneChangeNum = 0; Status = NtQuerySystemInformation(SystemTimeOfDayInformation, &BaseStaticServerData->TimeOfDay, sizeof(BaseStaticServerData->TimeOfDay), NULL); ASSERT(NT_SUCCESS(Status)); /* Make a shared heap copy of the Windows directory */ BaseStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory; HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap, 0, BaseSrvWindowsDirectory.MaximumLength); ASSERT(HeapBuffer); RtlCopyMemory(HeapBuffer, BaseStaticServerData->WindowsDirectory.Buffer, BaseSrvWindowsDirectory.MaximumLength); BaseStaticServerData->WindowsDirectory.Buffer = HeapBuffer; /* Make a shared heap copy of the System directory */ BaseStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory; HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap, 0, BaseSrvWindowsSystemDirectory.MaximumLength); ASSERT(HeapBuffer); RtlCopyMemory(HeapBuffer, BaseStaticServerData->WindowsSystemDirectory.Buffer, BaseSrvWindowsSystemDirectory.MaximumLength); BaseStaticServerData->WindowsSystemDirectory.Buffer = HeapBuffer; /* This string is not used */ RtlInitEmptyUnicodeString(&BaseStaticServerData->WindowsSys32x86Directory, NULL, 0); /* Make a shared heap copy of the BNO directory */ BaseStaticServerData->NamedObjectDirectory = BnoString; BaseStaticServerData->NamedObjectDirectory.MaximumLength = BnoString.Length + sizeof(UNICODE_NULL); HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap, 0, BaseStaticServerData->NamedObjectDirectory.MaximumLength); ASSERT(HeapBuffer); RtlCopyMemory(HeapBuffer, BaseStaticServerData->NamedObjectDirectory.Buffer, BaseStaticServerData->NamedObjectDirectory.MaximumLength); BaseStaticServerData->NamedObjectDirectory.Buffer = HeapBuffer; /* * Confirmed that in Windows, CSDNumber and RCNumber are actually Length * and MaximumLength of the CSD String, since the same UNICODE_STRING is * being queried twice, the first time as a ULONG! * * Somehow, in Windows this doesn't cause a buffer overflow, but it might * in ReactOS, so this code is disabled until someone figures out WTF. */ BaseStaticServerData->CSDNumber = 0; BaseStaticServerData->RCNumber = 0; /* Initialize the CSD string and query its value from the registry */ RtlInitEmptyUnicodeString(&BaseSrvCSDString, Buffer, sizeof(Buffer)); Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT, L"", BaseServerRegistryConfigurationTable, NULL, NULL); if (NT_SUCCESS(Status)) { /* Copy into the shared buffer */ wcsncpy(BaseStaticServerData->CSDVersion, BaseSrvCSDString.Buffer, BaseSrvCSDString.Length / sizeof(WCHAR)); } else { /* NULL-terminate to indicate nothing is there */ BaseStaticServerData->CSDVersion[0] = UNICODE_NULL; } /* Cache the system information */ Status = NtQuerySystemInformation(SystemBasicInformation, &BaseStaticServerData->SysInfo, sizeof(BaseStaticServerData->SysInfo), NULL); ASSERT(NT_SUCCESS(Status)); /* Setup the ini file mappings */ Status = BaseSrvInitializeIniFileMappings(BaseStaticServerData); ASSERT(NT_SUCCESS(Status)); /* FIXME: Should query the registry for these */ BaseStaticServerData->DefaultSeparateVDM = FALSE; BaseStaticServerData->IsWowTaskReady = FALSE; /* Allocate a security descriptor and create it */ BnoSd = RtlAllocateHeap(BaseSrvHeap, 0, 1024); ASSERT(BnoSd); Status = RtlCreateSecurityDescriptor(BnoSd, SECURITY_DESCRIPTOR_REVISION); ASSERT(NT_SUCCESS(Status)); /* Create the BNO and \Restricted DACLs */ Status = CreateBaseAcls(&BnoDacl, &BnoRestrictedDacl); ASSERT(NT_SUCCESS(Status)); /* Set the BNO DACL as active for now */ Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoDacl, FALSE); ASSERT(NT_SUCCESS(Status)); /* Create the BNO directory */ RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects"); InitializeObjectAttributes(&ObjectAttributes, &BnoString, OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, NULL, BnoSd); Status = NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory, DIRECTORY_ALL_ACCESS, &ObjectAttributes); ASSERT(NT_SUCCESS(Status)); /* Check if we are session 0 */ if (SessionId == 0) { /* Mark this as a session 0 directory */ Status = NtSetInformationObject(BaseSrvNamedObjectDirectory, ObjectSessionInformation, NULL, 0); ASSERT(NT_SUCCESS(Status)); } /* Check if LUID device maps are enabled */ Status = NtQueryInformationProcess(NtCurrentProcess(), ProcessLUIDDeviceMapsEnabled, &LuidEnabled, sizeof(LuidEnabled), NULL); ASSERT(NT_SUCCESS(Status)); BaseStaticServerData->LUIDDeviceMapsEnabled = (BOOLEAN)LuidEnabled; if (!BaseStaticServerData->LUIDDeviceMapsEnabled) { /* Make Global point back to BNO */ RtlInitUnicodeString(&DirectoryName, L"Global"); RtlInitUnicodeString(&SymlinkName, L"\\BaseNamedObjects"); InitializeObjectAttributes(&ObjectAttributes, &DirectoryName, OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, BaseSrvNamedObjectDirectory, BnoSd); Status = NtCreateSymbolicLinkObject(&SymHandle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes, &SymlinkName); if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle); /* Make local point back to \Sessions\x\BNO */ RtlInitUnicodeString(&DirectoryName, L"Local"); ASSERT(SessionId == 0); InitializeObjectAttributes(&ObjectAttributes, &DirectoryName, OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, BaseSrvNamedObjectDirectory, BnoSd); Status = NtCreateSymbolicLinkObject(&SymHandle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes, &SymlinkName); if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle); /* Make Session point back to BNOLINKS */ RtlInitUnicodeString(&DirectoryName, L"Session"); RtlInitUnicodeString(&SymlinkName, L"\\Sessions\\BNOLINKS"); InitializeObjectAttributes(&ObjectAttributes, &DirectoryName, OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, BaseSrvNamedObjectDirectory, BnoSd); Status = NtCreateSymbolicLinkObject(&SymHandle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes, &SymlinkName); if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle); /* Create the BNO\Restricted directory and set the restricted DACL */ RtlInitUnicodeString(&DirectoryName, L"Restricted"); Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoRestrictedDacl, FALSE); ASSERT(NT_SUCCESS(Status)); InitializeObjectAttributes(&ObjectAttributes, &DirectoryName, OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, BaseSrvNamedObjectDirectory, BnoSd); Status = NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory, DIRECTORY_ALL_ACCESS, &ObjectAttributes); ASSERT(NT_SUCCESS(Status)); } /* Initialize NLS */ BaseSrvNLSInit(BaseStaticServerData); /* Finally, set the pointer */ LoadedServerDll->SharedSection = BaseStaticServerData; }