NTSTATUS NTAPI NtQueryTimer( HANDLE TimerHandle, TIMER_INFORMATION_CLASS TimerInformationClass, PVOID TimerInformation, ULONG TimerInformationLength, PULONG ResultLength) { NTSTATUS r; NTTIMER* timer = 0; r = ObjectFromHandle( timer, TimerHandle, TIMER_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; union { TIMER_BASIC_INFORMATION basic; } info; ULONG sz = 0; switch (TimerInformationClass) { case TimerBasicInformation: sz = sizeof info.basic; break; default: return STATUS_INVALID_INFO_CLASS; } // this seems like the wrong order, but agrees with what tests show r = VerifyForWrite( TimerInformation, sz ); if (r < STATUS_SUCCESS) return r; if (sz != TimerInformationLength) return STATUS_INFO_LENGTH_MISMATCH; switch (TimerInformationClass) { case TimerBasicInformation: info.basic.SignalState = timer->IsSignalled(); timer->TimeRemaining( info.basic.TimeRemaining ); break; default: assert(0); } r = CopyToUser( TimerInformation, &info, sz ); if (r < STATUS_SUCCESS) return r; if (ResultLength) CopyToUser( ResultLength, &sz, sizeof sz ); return r; }
NTSTATUS NTAPI NtQueryTimerResolution( PULONG CoarsestResolution, PULONG FinestResolution, PULONG ActualResolution) { ULONG resolution = 100000LL; // 10ms NTSTATUS r; r = CopyToUser( CoarsestResolution, &resolution ); if (r < STATUS_SUCCESS) return r; r = CopyToUser( FinestResolution, &resolution ); if (r < STATUS_SUCCESS) return r; r = CopyToUser( ActualResolution, &resolution ); if (r < STATUS_SUCCESS) return r; return STATUS_SUCCESS; }
NTSTATUS NtCancelTimer( HANDLE TimerHandle, PBOOLEAN PreviousState) { NTSTATUS r; NTTIMER* timer = 0; r = ObjectFromHandle( timer, TimerHandle, TIMER_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; if (PreviousState) { r = VerifyForWrite( PreviousState, sizeof *PreviousState ); if (r < STATUS_SUCCESS) return r; } BOOLEAN prev = 0; timer->Cancel(prev); if (PreviousState) CopyToUser( PreviousState, &prev, sizeof prev ); return STATUS_SUCCESS; }
static NTSTATUS CopyPtrToUser( USER_COPY& item, PVOID info, ULONG infolen, ULONG& retlen ) { // really screwy - have to write back a pointer to the sid, then the sid retlen = item.GetLength() + sizeof (PVOID); if (retlen > infolen) return STATUS_BUFFER_TOO_SMALL; // pointer followed by the data blob PVOID ptr = (PVOID) ((PVOID*) info + 1); NTSTATUS r = CopyToUser( info, &ptr, sizeof ptr ); if (r < STATUS_SUCCESS) return r; return item.CopyToUser( ptr ); }
//NtPrivilegeCheck(00000154,0006fdc0,0006fe34) ret=77fa7082 NTSTATUS NtPrivilegeCheck( HANDLE TokenHandle, PPRIVILEGE_SET RequiredPrivileges, PBOOLEAN Result) { TOKEN *token = 0; NTSTATUS r = ObjectFromHandle( token, TokenHandle, TOKEN_QUERY ); if (r < STATUS_SUCCESS) return r; PRIVILEGES_SET ps; r = ps.CopyFromUser( RequiredPrivileges ); if (r < STATUS_SUCCESS) return r; BOOLEAN ok = TRUE; r = CopyToUser( Result, &ok, sizeof ok ); FIXME("\n"); return r; }
NTSTATUS NtSetTimer( HANDLE TimerHandle, PLARGE_INTEGER DueTime, PTIMER_APC_ROUTINE TimerApcRoutine, PVOID TimerContext, BOOLEAN Resume, LONG Period, PBOOLEAN PreviousState) { LARGE_INTEGER due; NTSTATUS r = CopyFromUser( &due, DueTime, sizeof due ); if (r < STATUS_SUCCESS) return r; TRACE("due = %llx\n", due.QuadPart); NTTIMER* timer = 0; r = ObjectFromHandle( timer, TimerHandle, TIMER_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; if (PreviousState) { r = VerifyForWrite( PreviousState, sizeof *PreviousState ); if (r < STATUS_SUCCESS) return r; } BOOLEAN prev = FALSE; r = timer->Set( due, (PKNORMAL_ROUTINE)TimerApcRoutine, TimerContext, Resume, Period, prev ); if (r == STATUS_SUCCESS && PreviousState ) CopyToUser( PreviousState, &prev, sizeof prev ); return r; }
NTSTATUS NTAPI NtQuerySystemTime(PLARGE_INTEGER CurrentTime) { LARGE_INTEGER now = TIMEOUT::CurrentTime(); return CopyToUser( CurrentTime, &now, sizeof now ); }
/*----------------------------------------------------------------------------*/ ssize_t mtcp_read(mctx_t mctx, int sockid, char *buf, size_t len) { mtcp_manager_t mtcp; socket_map_t socket; tcp_stream *cur_stream; struct tcp_recv_vars *rcvvar; int event_remaining; int ret; mtcp = GetMTCPManager(mctx); if (!mtcp) { return -1; } if (sockid < 0 || sockid >= CONFIG.max_concurrency) { TRACE_API("Socket id %d out of range.\n", sockid); errno = EBADF; return -1; } socket = &mtcp->smap[sockid]; if (socket->socktype == MTCP_SOCK_UNUSED) { TRACE_API("Invalid socket id: %d\n", sockid); errno = EBADF; return -1; } if (socket->socktype == MTCP_SOCK_PIPE) { return PipeRead(mctx, sockid, buf, len); } if (socket->socktype != MTCP_SOCK_STREAM) { TRACE_API("Not an end socket. id: %d\n", sockid); errno = ENOTSOCK; return -1; } /* stream should be in ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, CLOSE_WAIT */ cur_stream = socket->stream; if (!cur_stream || !(cur_stream->state >= TCP_ST_ESTABLISHED && cur_stream->state <= TCP_ST_CLOSE_WAIT)) { errno = ENOTCONN; return -1; } rcvvar = cur_stream->rcvvar; /* if CLOSE_WAIT, return 0 if there is no payload */ if (cur_stream->state == TCP_ST_CLOSE_WAIT) { if (!rcvvar->rcvbuf) return 0; if (rcvvar->rcvbuf->merged_len == 0) return 0; } /* return EAGAIN if no receive buffer */ if (socket->opts & MTCP_NONBLOCK) { if (!rcvvar->rcvbuf || rcvvar->rcvbuf->merged_len == 0) { errno = EAGAIN; return -1; } } SBUF_LOCK(&rcvvar->read_lock); #if BLOCKING_SUPPORT if (!(socket->opts & MTCP_NONBLOCK)) { while (rcvvar->rcvbuf->merged_len == 0) { if (!cur_stream || cur_stream->state != TCP_ST_ESTABLISHED) { SBUF_UNLOCK(&rcvvar->read_lock); errno = EINTR; return -1; } pthread_cond_wait(&rcvvar->read_cond, &rcvvar->read_lock); } } #endif ret = CopyToUser(mtcp, cur_stream, buf, len); event_remaining = FALSE; /* if there are remaining payload, generate EPOLLIN */ /* (may due to insufficient user buffer) */ if (socket->epoll & MTCP_EPOLLIN) { if (!(socket->epoll & MTCP_EPOLLET) && rcvvar->rcvbuf->merged_len > 0) { event_remaining = TRUE; } } /* if waiting for close, notify it if no remaining data */ if (cur_stream->state == TCP_ST_CLOSE_WAIT && rcvvar->rcvbuf->merged_len == 0 && ret > 0) { event_remaining = TRUE; } SBUF_UNLOCK(&rcvvar->read_lock); if (event_remaining) { if (socket->epoll) { AddEpollEvent(mtcp->ep, USR_SHADOW_EVENT_QUEUE, socket, MTCP_EPOLLIN); #if BLOCKING_SUPPORT } else if (!(socket->opts & MTCP_NONBLOCK)) { if (!cur_stream->on_rcv_br_list) { cur_stream->on_rcv_br_list = TRUE; TAILQ_INSERT_TAIL(&mtcp->rcv_br_list, cur_stream, rcvvar->rcv_br_link); mtcp->rcv_br_list_cnt++; } #endif } } TRACE_API("Stream %d: mtcp_read() returning %d\n", cur_stream->id, ret); return ret; }
NTSTATUS NTAPI NtQueryInformationToken( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, PVOID TokenInformation, ULONG TokenInformationLength, PULONG ReturnLength ) { TOKEN *token; ULONG len; NTSTATUS r; TOKEN_STATISTICS stats; TRACE("%p %u %p %lu %p\n", TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength, ReturnLength ); r = ObjectFromHandle( token, TokenHandle, TOKEN_QUERY ); if (r < STATUS_SUCCESS) return r; switch( TokenInformationClass ) { case TokenOwner: TRACE("TokenOwner\n"); r = CopyPtrToUser( token->GetOwner(), TokenInformation, TokenInformationLength, len ); break; case TokenPrimaryGroup: TRACE("TokenPrimaryGroup\n"); r = CopyPtrToUser( token->GetPrimaryGroup(), TokenInformation, TokenInformationLength, len ); break; case TokenDefaultDacl: TRACE("TokenDefaultDacl\n"); r = CopyPtrToUser( token->GetDefaultDacl(), TokenInformation, TokenInformationLength, len ); break; case TokenUser: TRACE("TokenUser\n"); len = token->GetUser().GetLength(); if (len > TokenInformationLength) { r = STATUS_BUFFER_TOO_SMALL; break; } r = token->GetUser().CopyToUser( (SID_AND_ATTRIBUTES*) TokenInformation ); break; case TokenImpersonationLevel: FIXME("UNIMPLEMENTED: TokenImpersonationLevel\n"); return STATUS_INVALID_INFO_CLASS; case TokenStatistics: TRACE("TokenStatistics\n"); len = sizeof stats; if (len != TokenInformationLength) return STATUS_INFO_LENGTH_MISMATCH; memset( &stats, 0, sizeof stats ); r = CopyToUser( TokenInformation, &stats, sizeof stats ); if (r < STATUS_SUCCESS) return r; break; case TokenGroups: TRACE("TokenGroups\n"); len = token->GetGroups().GetLength(); if (len > TokenInformationLength) { r = STATUS_BUFFER_TOO_SMALL; break; } r = token->GetGroups().CopyToUser( (TOKEN_GROUPS*) TokenInformation ); break; case TokenRestrictedSids: TRACE("TokenRestrictedSids\n"); len = token->GetRestrictedSids().GetLength(); if (len > TokenInformationLength) { r = STATUS_BUFFER_TOO_SMALL; break; } r = token->GetGroups().CopyToUser((TOKEN_GROUPS*)TokenInformation); break; default: FIXME("UNIMPLEMENTED: info class %d\n", TokenInformationClass); return STATUS_INVALID_INFO_CLASS; } if (ReturnLength) CopyToUser( ReturnLength, &len, sizeof len ); return r; }
NTSTATUS NTAPI NtAdjustPrivilegesToken( HANDLE TokenHandle, BOOLEAN DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, ULONG BufferLength, PTOKEN_PRIVILEGES PreviousState, PULONG ReturnLength ) { NTSTATUS r; TRACE("%p %u %p %lu %p %p\n", TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength ); if (ReturnLength) { r = VerifyForWrite( ReturnLength, sizeof *ReturnLength ); if (r < STATUS_SUCCESS) return r; } if (!NewState) return STATUS_INVALID_PARAMETER; // getting the old state requires query rights ACCESS_MASK mask = TOKEN_ADJUST_PRIVILEGES; if (PreviousState) mask |= TOKEN_QUERY; TOKEN *token = 0; r = ObjectFromHandle( token, TokenHandle, mask ); if (r < STATUS_SUCCESS) return r; CTOKEN_PRIVILEGES privs; r = privs.CopyFromUser( NewState ); if (r < STATUS_SUCCESS) return r; // return previous state information if required if (PreviousState) { CTOKEN_PRIVILEGES& prev_state = token->GetPrivs(); ULONG len = prev_state.GetLength(); TRACE("old privs %ld bytes\n", len); prev_state.Dump(); if (len > BufferLength) return STATUS_BUFFER_TOO_SMALL; r = prev_state.CopyToUser( PreviousState ); if (r < STATUS_SUCCESS) return r; r = CopyToUser( ReturnLength, &len, sizeof len ); assert( r == STATUS_SUCCESS ); } r = token->Adjust( privs ); TRACE("new privs\n"); privs.Dump(); return r; }
static bool CopyFdsToUser(struct pollfd* user_fds, const struct pollfd* kernel_fds, size_t nfds) { size_t size = sizeof(struct pollfd) * nfds; return CopyToUser(user_fds, kernel_fds, size); }
/* this doesn't set STATUS_MORE_DATA */ NTSTATUS IREGKEY::RegQueryValue( IREGVAL* val, ULONG KeyValueInformationClass, PVOID KeyValueInformation, ULONG KeyValueInformationLength, ULONG& len ) { NTSTATUS r = STATUS_SUCCESS; union { KEY_VALUE_FULL_INFORMATION full; KEY_VALUE_PARTIAL_INFORMATION partial; } info; ULONG info_sz; len = 0; TRACE("%pus\n", &val->Name()); memset( &info, 0, sizeof info ); switch( KeyValueInformationClass ) { case KeyValueFullInformation: info_sz = FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION, Name ); // include nul terminator at the end of the Name info.full.DataOffset = info_sz + val->Name().Length + 2; len = info.full.DataOffset + val->Size(); if (KeyValueInformationLength < info_sz) return STATUS_BUFFER_TOO_SMALL; info.full.Type = val->Type(); info.full.DataLength = val->Size(); info.full.NameLength = val->Name().Length; r = CopyToUser( KeyValueInformation, &info.full, info_sz ); if (r < STATUS_SUCCESS) break; if (len > KeyValueInformationLength) return STATUS_BUFFER_OVERFLOW; r = CopyToUser( (BYTE*)KeyValueInformation + info_sz, val->Name().Buffer, val->Name().Length ); if (r < STATUS_SUCCESS) break; r = CopyToUser( (BYTE*)KeyValueInformation + info.full.DataOffset, val->Data(), val->Size() ); break; case KeyValuePartialInformation: info_sz = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data ); TRACE("info_sz %d val->Size() %d\n", info_sz, val->Size()); len = info_sz + val->Size(); if (KeyValueInformationLength < info_sz) return STATUS_BUFFER_TOO_SMALL; info.partial.Type = val->Type(); info.partial.DataLength = val->Size(); r = CopyToUser( KeyValueInformation, &info.partial, info_sz ); if (r < STATUS_SUCCESS) break; if (len > KeyValueInformationLength) return STATUS_BUFFER_OVERFLOW; r = CopyToUser( (BYTE*)KeyValueInformation + info_sz, val->Data(), val->Size() ); break; case KeyValueBasicInformation: case KeyValueFullInformationAlign64: case KeyValuePartialInformationAlign64: default: FIXME("RegQueryValue: UNIMPLEMENTED case %ld\n", KeyValueInformationClass); r = STATUS_NOT_IMPLEMENTED; } return r; }
NTSTATUS IREGKEY::Query( KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG KeyInformationLength, PULONG ReturnLength) { union { KEY_BASIC_INFORMATION basic; KEY_FULL_INFORMATION full; } info; NTSTATUS r; memset( &info, 0, sizeof info ); ULONG sz = 0; UNICODE_STRING keycls, keyname; keyname.Length = 0; keyname.Buffer = 0; keycls.Length = 0; keycls.Buffer = 0; switch (KeyInformationClass) { case KeyBasicInformation: Query( info.basic, keyname ); sz = sizeof info.basic + keyname.Length; if (sz > KeyInformationLength) return STATUS_INFO_LENGTH_MISMATCH; r = CopyToUser( KeyInformation, &info, sz ); if (r < STATUS_SUCCESS) break; r = CopyToUser( (BYTE*)KeyInformation + FIELD_OFFSET( KEY_BASIC_INFORMATION, Name ), keyname.Buffer, keyname.Length ); break; case KeyFullInformation: Query( info.full, keycls ); sz = sizeof info.full + keycls.Length; if (sz > KeyInformationLength) return STATUS_INFO_LENGTH_MISMATCH; r = CopyToUser( KeyInformation, &info, sz ); if (r < STATUS_SUCCESS) break; TRACE("keycls = %pus\n", &keycls); r = CopyToUser( (BYTE*)KeyInformation + FIELD_OFFSET( KEY_FULL_INFORMATION, Class ), keycls.Buffer, keycls.Length ); break; case KeyNodeInformation: FIXME("KeyNodeInformation\n"); default: assert(0); } if (r == STATUS_SUCCESS) CopyToUser( ReturnLength, &sz, sizeof sz ); return r; }
// blocking NTSTATUS NTAPI NtRemoveIoCompletion( HANDLE IoCompletionHandle, PULONG IoCompletionKey, PULONG IoCompletionValue, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER TimeOut) { NTSTATUS r; TRACE("%p %p %p %p %p\n", IoCompletionHandle, IoCompletionKey, IoCompletionValue, IoStatusBlock, TimeOut); COMPLETION_PORT_IMPL *port = 0; r = ObjectFromHandle( port, IoCompletionHandle, IO_COMPLETION_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; if (IoCompletionKey) { r = VerifyForWrite( IoCompletionKey, sizeof *IoCompletionKey ); if (r < STATUS_SUCCESS) return r; } if (IoCompletionValue) { r = VerifyForWrite( IoCompletionValue, sizeof *IoCompletionValue ); if (r < STATUS_SUCCESS) return r; } if (IoStatusBlock) { r = VerifyForWrite( IoStatusBlock, sizeof *IoStatusBlock ); if (r < STATUS_SUCCESS) return r; } LARGE_INTEGER t; t.QuadPart = 0LL; if (TimeOut) { r = CopyFromUser( &t, TimeOut, sizeof t ); if (r < STATUS_SUCCESS) return r; TimeOut = &t; } ULONG key = 0, val = 0; IO_STATUS_BLOCK iosb; iosb.Status = 0; iosb.Information = 0; port->Remove( key, val, iosb.Status, iosb.Information, TimeOut ); if (IoCompletionKey) CopyToUser( IoCompletionKey, &key, sizeof key ); if (IoCompletionValue) CopyToUser( IoCompletionValue, &val, sizeof val ); if (IoStatusBlock) CopyToUser( IoStatusBlock, &iosb, sizeof iosb ); return r; }