int plug_and_play_t::run() { OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK iosb; HANDLE pipe = 0; NTSTATUS r; LARGE_INTEGER timeout; current = static_cast<thread_t*>( this ); unicode_string_t pipename; pipename.copy( "\\Device\\NamedPipe\\ntsvcs" ); oa.Length = sizeof oa; oa.RootDirectory = 0; oa.ObjectName = &pipename; oa.Attributes = OBJ_CASE_INSENSITIVE; oa.SecurityDescriptor = 0; oa.SecurityQualityOfService = 0; timeout.QuadPart = -10000LL; r = NtCreateNamedPipeFile( &pipe, GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, &oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, TRUE, TRUE, FALSE, -1, 0, 0, &timeout ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) dprintf("failed to create ntsvcs %08lx\n", r); if (terminated) stop(); r = NtFsControlFile( pipe, 0, 0, 0, &iosb, FSCTL_PIPE_LISTEN, 0, 0, 0, 0 ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) dprintf("failed to connect ntsvcs %08lx\n", r); stop(); return 0; }
/* * @implemented */ BOOL WINAPI CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize) { WCHAR Buffer[64]; UNICODE_STRING PipeName; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK StatusBlock; LARGE_INTEGER DefaultTimeout; NTSTATUS Status; HANDLE ReadPipeHandle; HANDLE WritePipeHandle; LONG PipeId; ULONG Attributes; PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; /* Set the timeout to 120 seconds */ DefaultTimeout.QuadPart = -1200000000; /* Use default buffer size if desired */ if (!nSize) nSize = 0x1000; /* Increase the Pipe ID */ PipeId = InterlockedIncrement(&ProcessPipeId); /* Create the pipe name */ swprintf(Buffer, L"\\Device\\NamedPipe\\Win32Pipes.%08x.%08x", NtCurrentTeb()->ClientId.UniqueProcess, PipeId); RtlInitUnicodeString(&PipeName, Buffer); /* Always use case insensitive */ Attributes = OBJ_CASE_INSENSITIVE; /* Check if we got attributes */ if (lpPipeAttributes) { /* Use the attributes' SD instead */ SecurityDescriptor = lpPipeAttributes->lpSecurityDescriptor; /* Set OBJ_INHERIT if requested */ if (lpPipeAttributes->bInheritHandle) Attributes |= OBJ_INHERIT; } /* Initialize the attributes */ InitializeObjectAttributes(&ObjectAttributes, &PipeName, Attributes, NULL, SecurityDescriptor); /* Create the named pipe */ Status = NtCreateNamedPipeFile(&ReadPipeHandle, GENERIC_READ |FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, &ObjectAttributes, &StatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT, FILE_PIPE_BYTE_STREAM_TYPE, FILE_PIPE_BYTE_STREAM_MODE, FILE_PIPE_QUEUE_OPERATION, 1, nSize, nSize, &DefaultTimeout); if (!NT_SUCCESS(Status)) { /* Convert error and fail */ WARN("Status: %lx\n", Status); BaseSetLastNTError(Status); return FALSE; } /* Now try opening it for write access */ Status = NtOpenFile(&WritePipeHandle, FILE_GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &StatusBlock, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); if (!NT_SUCCESS(Status)) { /* Convert error and fail */ WARN("Status: %lx\n", Status); NtClose(ReadPipeHandle); BaseSetLastNTError(Status); return FALSE; } /* Return both handles */ *hReadPipe = ReadPipeHandle; *hWritePipe = WritePipeHandle; return TRUE; }
/* * @implemented */ HANDLE WINAPI CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { UNICODE_STRING NamedPipeName; BOOL Result; NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE PipeHandle; ACCESS_MASK DesiredAccess; ULONG CreateOptions = 0; ULONG WriteModeMessage; ULONG ReadModeMessage; ULONG NonBlocking; IO_STATUS_BLOCK Iosb; ULONG ShareAccess = 0, Attributes; LARGE_INTEGER DefaultTimeOut; PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; /* Check for valid instances */ if (nMaxInstances == 0 || nMaxInstances > PIPE_UNLIMITED_INSTANCES) { /* Fail */ SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } /* Convert to NT syntax */ if (nMaxInstances == PIPE_UNLIMITED_INSTANCES) nMaxInstances = -1; /* Convert the name */ Result = RtlDosPathNameToNtPathName_U(lpName, &NamedPipeName, NULL, NULL); if (!Result) { /* Conversion failed */ SetLastError(ERROR_PATH_NOT_FOUND); return INVALID_HANDLE_VALUE; } TRACE("Pipe name: %wZ\n", &NamedPipeName); TRACE("Pipe name: %S\n", NamedPipeName.Buffer); /* Always case insensitive, check if we got extra attributes */ Attributes = OBJ_CASE_INSENSITIVE; if(lpSecurityAttributes) { /* We did; get the security descriptor */ SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor; /* And check if this is pipe's handle will beinheritable */ if (lpSecurityAttributes->bInheritHandle) Attributes |= OBJ_INHERIT; } /* Now we can initialize the object attributes */ InitializeObjectAttributes(&ObjectAttributes, &NamedPipeName, Attributes, NULL, SecurityDescriptor); /* Setup the default Desired Access */ DesiredAccess = SYNCHRONIZE | (dwOpenMode & (WRITE_DAC | WRITE_OWNER | ACCESS_SYSTEM_SECURITY)); /* Convert to NT Create Flags */ if (dwOpenMode & FILE_FLAG_WRITE_THROUGH) { CreateOptions |= FILE_WRITE_THROUGH; } if (!(dwOpenMode & FILE_FLAG_OVERLAPPED)) { CreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT; } /* Handle all open modes */ if (dwOpenMode & PIPE_ACCESS_OUTBOUND) { ShareAccess |= FILE_SHARE_READ; DesiredAccess |= GENERIC_WRITE; } if (dwOpenMode & PIPE_ACCESS_INBOUND) { ShareAccess |= FILE_SHARE_WRITE; DesiredAccess |= GENERIC_READ; } /* Handle the type flags */ if (dwPipeMode & PIPE_TYPE_MESSAGE) { WriteModeMessage = FILE_PIPE_MESSAGE_TYPE; } else { WriteModeMessage = FILE_PIPE_BYTE_STREAM_TYPE; } /* Handle the mode flags */ if (dwPipeMode & PIPE_READMODE_MESSAGE) { ReadModeMessage = FILE_PIPE_MESSAGE_MODE; } else { ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE; } /* Handle the blocking mode */ if (dwPipeMode & PIPE_NOWAIT) { NonBlocking = FILE_PIPE_COMPLETE_OPERATION; } else { NonBlocking = FILE_PIPE_QUEUE_OPERATION; } /* Check if we have a timeout */ if (nDefaultTimeOut) { /* Convert the time to NT format */ DefaultTimeOut.QuadPart = UInt32x32To64(nDefaultTimeOut, -10000); } else { /* Use default timeout of 50 ms */ DefaultTimeOut.QuadPart = -500000; } /* Now create the pipe */ Status = NtCreateNamedPipeFile(&PipeHandle, DesiredAccess, &ObjectAttributes, &Iosb, ShareAccess, FILE_OPEN_IF, CreateOptions, WriteModeMessage, ReadModeMessage, NonBlocking, nMaxInstances, nInBufferSize, nOutBufferSize, &DefaultTimeOut); /* Normalize special error codes */ if ((Status == STATUS_INVALID_DEVICE_REQUEST) || (Status == STATUS_NOT_SUPPORTED)) { Status = STATUS_OBJECT_NAME_INVALID; } /* Free the name */ RtlFreeHeap(RtlGetProcessHeap(), 0, NamedPipeName.Buffer); /* Check status */ if (!NT_SUCCESS(Status)) { /* Failed to create it */ WARN("NtCreateNamedPipe failed (Status %x)!\n", Status); BaseSetLastNTError (Status); return INVALID_HANDLE_VALUE; } /* Return the handle */ return PipeHandle; }
DWORD __stdcall PipeThread( VOID* Parameter ) { HANDLE pipeHandle; BYTE buffer[1024]; OBJECT_ATTRIBUTES objAttributes; UNICODE_STRING pipeName; IO_STATUS_BLOCK isb; LARGE_INTEGER timeOut; RtlDosPathNameToNtPathName_U(L"\\\\.\\pipe\\Push", &pipeName, NULL, NULL); objAttributes.Length = sizeof(OBJECT_ATTRIBUTES); objAttributes.RootDirectory = NULL; objAttributes.ObjectName = &pipeName; objAttributes.Attributes = OBJ_CASE_INSENSITIVE; objAttributes.SecurityDescriptor = NULL; objAttributes.SecurityQualityOfService = NULL; timeOut.QuadPart = 0xfffffffffff85ee0; NtCreateNamedPipeFile( &pipeHandle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &objAttributes, &isb, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0, 0, 1, 1024 * 16, 1024 * 16, &timeOut ); while (pipeHandle != INVALID_HANDLE_VALUE) { if (ConnectNamedPipe(pipeHandle, NULL) != FALSE) // wait for someone to connect to the pipe { IO_STATUS_BLOCK isb; while (NtReadFile( pipeHandle, NULL, NULL, NULL, &isb, buffer, sizeof(buffer) - 1, NULL, NULL ) == STATUS_SUCCESS) { /* parse command buffer */ COMMAND_HEADER *cmdBuffer; cmdBuffer = &buffer; switch (cmdBuffer->CommandIndex) { case CMD_STARTHWMON: { OnRenderEvent(); }break; case CMD_NOTIFY: { UINT16 responseTime; OnProcessEvent(cmdBuffer->ProcessId); File_Write(pipeHandle, &responseTime, 2); }break; case CMD_SETGPUCLK: if (PushSharedMemory->HarwareInformation.DisplayDevice.EngineClockMax > 1 && PushSharedMemory->HarwareInformation.DisplayDevice.MemoryClockMax > 1 ) { GPU_CONFIG_CMD_BUFFER *gpuConfig; gpuConfig = &buffer; GPU_SetEngineClock(gpuConfig->EngineClock); GPU_SetMemoryClock(gpuConfig->MemoryClock); GPU_SetVoltage(gpuConfig->Voltage); } break; case CMD_MAXGPUCLK: Hardware_ForceMaxClocks(); break; case CMD_SETGPUFAN: Adl_SetFanDutyCycle(PushSharedMemory->HarwareInformation.DisplayDevice.FanDutyCycle); break; case CMD_GETDSKRSP: { UINT32 processId; UINT16 responseTime; processId = cmdBuffer->ProcessId; responseTime = GetDiskResponseTime(processId); File_Write(pipeHandle, &responseTime, 2); }break; case CMD_CONTROLLERCFG: { CONTROLLER_CONFIG_CMD_BUFFER *cmdBuffer; cmdBuffer = &buffer; SetButtonMapping(&cmdBuffer->Map); }break; case CMD_SAVEPRFL: { CONTROLLER_CONFIG_CMD_BUFFER *cmdBuffer; wchar_t fileName[260]; cmdBuffer = &buffer; CreatePath(L".\\" GAMES_CONFIG_PATH); GetConfigFileFromProcessId(cmdBuffer->CommandHeader.ProcessId, fileName); WriteConfig(L"ButtonTriangle", cmdBuffer->Map.Triangle, fileName); WriteConfig(L"ButtonCircle", cmdBuffer->Map.Circle, fileName); WriteConfig(L"ButtonCross", cmdBuffer->Map.Cross, fileName); WriteConfig(L"ButtonSquare", cmdBuffer->Map.Square, fileName); WriteConfig(L"DPadUp", cmdBuffer->Map.DpadUp, fileName); WriteConfig(L"DPadRight", cmdBuffer->Map.DpadRight, fileName); WriteConfig(L"DPadDown", cmdBuffer->Map.DpadDown, fileName); WriteConfig(L"DPadLeft", cmdBuffer->Map.DpadLeft, fileName); WriteConfig(L"ButtonL1", cmdBuffer->Map.L1, fileName); WriteConfig(L"ButtonR1", cmdBuffer->Map.R1, fileName); WriteConfig(L"ButtonL2", cmdBuffer->Map.L2, fileName); WriteConfig(L"ButtonR2", cmdBuffer->Map.R2, fileName); WriteConfig(L"ButtonL3", cmdBuffer->Map.L3, fileName); WriteConfig(L"ButtonR3", cmdBuffer->Map.R3, fileName); WriteConfig(L"ButtonSelect", cmdBuffer->Map.Select, fileName); WriteConfig(L"ButtonStart", cmdBuffer->Map.Start, fileName); WriteConfig(L"ButtonPS", cmdBuffer->Map.PS, fileName); WriteConfig(L"LeftStickXpos", cmdBuffer->Map.LStick_Xpos, fileName); WriteConfig(L"LeftStickXneg", cmdBuffer->Map.LStick_Xneg, fileName); WriteConfig(L"LeftStickYpos", cmdBuffer->Map.LStick_Ypos, fileName); WriteConfig(L"LeftStickYneg", cmdBuffer->Map.LStick_Yneg, fileName); WriteConfig(L"RightStickXpos", 0, fileName); WriteConfig(L"RightStickXneg", 0, fileName); WriteConfig(L"RightStickYpos", 0, fileName); WriteConfig(L"RightStickYneg", 0, fileName); }break; case CMD_BRIGHTNESS: { CMD_BUFFER_BRIGHTNESS* cmdBuffer; cmdBuffer = &buffer; SetBrightness(cmdBuffer->Brightness); }break; } } } DisconnectNamedPipe(pipeHandle); } return 0; }