4 * This file contains the Nt* API functions of NTDLL.DLL.
5 * In the original ntdll.dll they all seem to just call int 0x2e (down to the NTOSKRNL)
7 * Copyright 1996-1998 Marcus Meissner
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/port.h"
27 #ifdef HAVE_SYS_PARAM_H
28 # include <sys/param.h>
30 #ifdef HAVE_SYS_SYSCTL_H
31 # include <sys/sysctl.h>
33 #ifdef HAVE_MACHINE_CPU_H
34 # include <machine/cpu.h>
36 #ifdef HAVE_MACH_MACHINE_H
37 # include <mach/machine.h>
39 #ifdef HAVE_IOKIT_IOKITLIB_H
40 # include <CoreFoundation/CoreFoundation.h>
41 # include <IOKit/IOKitLib.h>
42 # include <IOKit/pwr_mgt/IOPM.h>
43 # include <IOKit/pwr_mgt/IOPMLib.h>
44 # include <IOKit/ps/IOPowerSources.h>
52 #ifdef HAVE_SYS_TIME_H
53 # include <sys/time.h>
58 /* FIXME: Unfortunately swapctl can't be used with largefile.... */
59 # undef _FILE_OFFSET_BITS
60 # define _FILE_OFFSET_BITS 32
61 # ifdef HAVE_SYS_RESOURCE_H
62 # include <sys/resource.h>
64 # ifdef HAVE_SYS_STAT_H
65 # include <sys/stat.h>
67 # include <sys/swap.h>
70 #define NONAMELESSUNION
72 #define WIN32_NO_STATUS
73 #include "wine/debug.h"
74 #include "wine/unicode.h"
77 #include "ntdll_misc.h"
78 #include "wine/server.h"
82 #include <mach/mach.h>
83 #include <mach/mach_init.h>
84 #include <mach/mach_host.h>
85 #include <mach/vm_map.h>
88 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
92 struct smbios_prologue
{
100 struct smbios_header
{
107 struct smbios_header hdr
;
113 UINT64 characteristics
;
114 BYTE characteristics_ext
[2];
115 BYTE system_bios_major_release
;
116 BYTE system_bios_minor_release
;
117 BYTE ec_firmware_major_release
;
118 BYTE ec_firmware_minor_release
;
121 struct smbios_system
{
122 struct smbios_header hdr
;
133 struct smbios_board
{
134 struct smbios_header hdr
;
141 struct smbios_chassis
{
142 struct smbios_header hdr
;
149 BYTE power_supply_state
;
151 BYTE security_status
;
156 /* Firmware table providers */
157 #define ACPI 0x41435049
158 #define FIRM 0x4649524D
159 #define RSMB 0x52534D42
165 /******************************************************************************
166 * NtDuplicateToken [NTDLL.@]
167 * ZwDuplicateToken [NTDLL.@]
169 NTSTATUS WINAPI
NtDuplicateToken(
170 IN HANDLE ExistingToken
,
171 IN ACCESS_MASK DesiredAccess
,
172 IN POBJECT_ATTRIBUTES ObjectAttributes
,
173 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
174 IN TOKEN_TYPE TokenType
,
175 OUT PHANDLE NewToken
)
179 struct object_attributes
*objattr
;
181 TRACE("(%p,0x%08x,%s,0x%08x,0x%08x,%p)\n",
182 ExistingToken
, DesiredAccess
, debugstr_ObjectAttributes(ObjectAttributes
),
183 ImpersonationLevel
, TokenType
, NewToken
);
185 if ((status
= alloc_object_attributes( ObjectAttributes
, &objattr
, &len
))) return status
;
187 if (ObjectAttributes
&& ObjectAttributes
->SecurityQualityOfService
)
189 SECURITY_QUALITY_OF_SERVICE
*SecurityQOS
= ObjectAttributes
->SecurityQualityOfService
;
190 TRACE("ObjectAttributes->SecurityQualityOfService = {%d, %d, %d, %s}\n",
191 SecurityQOS
->Length
, SecurityQOS
->ImpersonationLevel
,
192 SecurityQOS
->ContextTrackingMode
,
193 SecurityQOS
->EffectiveOnly
? "TRUE" : "FALSE");
194 ImpersonationLevel
= SecurityQOS
->ImpersonationLevel
;
197 SERVER_START_REQ( duplicate_token
)
199 req
->handle
= wine_server_obj_handle( ExistingToken
);
200 req
->access
= DesiredAccess
;
201 req
->primary
= (TokenType
== TokenPrimary
);
202 req
->impersonation_level
= ImpersonationLevel
;
203 wine_server_add_data( req
, objattr
, len
);
204 status
= wine_server_call( req
);
205 if (!status
) *NewToken
= wine_server_ptr_handle( reply
->new_handle
);
209 RtlFreeHeap( GetProcessHeap(), 0, objattr
);
213 /******************************************************************************
214 * NtOpenProcessToken [NTDLL.@]
215 * ZwOpenProcessToken [NTDLL.@]
217 NTSTATUS WINAPI
NtOpenProcessToken(
218 HANDLE ProcessHandle
,
222 return NtOpenProcessTokenEx( ProcessHandle
, DesiredAccess
, 0, TokenHandle
);
225 /******************************************************************************
226 * NtOpenProcessTokenEx [NTDLL.@]
227 * ZwOpenProcessTokenEx [NTDLL.@]
229 NTSTATUS WINAPI
NtOpenProcessTokenEx( HANDLE process
, DWORD access
, DWORD attributes
,
234 TRACE("(%p,0x%08x,0x%08x,%p)\n", process
, access
, attributes
, handle
);
236 SERVER_START_REQ( open_token
)
238 req
->handle
= wine_server_obj_handle( process
);
239 req
->access
= access
;
240 req
->attributes
= attributes
;
242 ret
= wine_server_call( req
);
243 if (!ret
) *handle
= wine_server_ptr_handle( reply
->token
);
249 /******************************************************************************
250 * NtOpenThreadToken [NTDLL.@]
251 * ZwOpenThreadToken [NTDLL.@]
253 NTSTATUS WINAPI
NtOpenThreadToken(
259 return NtOpenThreadTokenEx( ThreadHandle
, DesiredAccess
, OpenAsSelf
, 0, TokenHandle
);
262 /******************************************************************************
263 * NtOpenThreadTokenEx [NTDLL.@]
264 * ZwOpenThreadTokenEx [NTDLL.@]
266 NTSTATUS WINAPI
NtOpenThreadTokenEx( HANDLE thread
, DWORD access
, BOOLEAN as_self
, DWORD attributes
,
271 TRACE("(%p,0x%08x,%u,0x%08x,%p)\n", thread
, access
, as_self
, attributes
, handle
);
273 SERVER_START_REQ( open_token
)
275 req
->handle
= wine_server_obj_handle( thread
);
276 req
->access
= access
;
277 req
->attributes
= attributes
;
278 req
->flags
= OPEN_TOKEN_THREAD
;
279 if (as_self
) req
->flags
|= OPEN_TOKEN_AS_SELF
;
280 ret
= wine_server_call( req
);
281 if (!ret
) *handle
= wine_server_ptr_handle( reply
->token
);
288 /******************************************************************************
289 * NtAdjustPrivilegesToken [NTDLL.@]
290 * ZwAdjustPrivilegesToken [NTDLL.@]
292 * FIXME: parameters unsafe
294 NTSTATUS WINAPI
NtAdjustPrivilegesToken(
295 IN HANDLE TokenHandle
,
296 IN BOOLEAN DisableAllPrivileges
,
297 IN PTOKEN_PRIVILEGES NewState
,
298 IN DWORD BufferLength
,
299 OUT PTOKEN_PRIVILEGES PreviousState
,
300 OUT PDWORD ReturnLength
)
304 TRACE("(%p,0x%08x,%p,0x%08x,%p,%p)\n",
305 TokenHandle
, DisableAllPrivileges
, NewState
, BufferLength
, PreviousState
, ReturnLength
);
307 SERVER_START_REQ( adjust_token_privileges
)
309 req
->handle
= wine_server_obj_handle( TokenHandle
);
310 req
->disable_all
= DisableAllPrivileges
;
311 req
->get_modified_state
= (PreviousState
!= NULL
);
312 if (!DisableAllPrivileges
)
314 wine_server_add_data( req
, NewState
->Privileges
,
315 NewState
->PrivilegeCount
* sizeof(NewState
->Privileges
[0]) );
317 if (PreviousState
&& BufferLength
>= FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
))
318 wine_server_set_reply( req
, PreviousState
->Privileges
,
319 BufferLength
- FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
) );
320 ret
= wine_server_call( req
);
323 if (ReturnLength
) *ReturnLength
= reply
->len
+ FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
);
324 PreviousState
->PrivilegeCount
= reply
->len
/ sizeof(LUID_AND_ATTRIBUTES
);
332 /******************************************************************************
333 * NtQueryInformationToken [NTDLL.@]
334 * ZwQueryInformationToken [NTDLL.@]
337 * Buffer for TokenUser:
338 * 0x00 TOKEN_USER the PSID field points to the SID
342 NTSTATUS WINAPI
NtQueryInformationToken(
344 TOKEN_INFORMATION_CLASS tokeninfoclass
,
346 ULONG tokeninfolength
,
349 static const ULONG info_len
[] =
354 0, /* TokenPrivileges */
356 0, /* TokenPrimaryGroup */
357 0, /* TokenDefaultDacl */
358 sizeof(TOKEN_SOURCE
), /* TokenSource */
359 sizeof(TOKEN_TYPE
), /* TokenType */
360 sizeof(SECURITY_IMPERSONATION_LEVEL
), /* TokenImpersonationLevel */
361 sizeof(TOKEN_STATISTICS
), /* TokenStatistics */
362 0, /* TokenRestrictedSids */
363 sizeof(DWORD
), /* TokenSessionId */
364 0, /* TokenGroupsAndPrivileges */
365 0, /* TokenSessionReference */
366 0, /* TokenSandBoxInert */
367 0, /* TokenAuditPolicy */
369 sizeof(TOKEN_ELEVATION_TYPE
), /* TokenElevationType */
370 0, /* TokenLinkedToken */
371 sizeof(TOKEN_ELEVATION
), /* TokenElevation */
372 0, /* TokenHasRestrictions */
373 0, /* TokenAccessInformation */
374 0, /* TokenVirtualizationAllowed */
375 sizeof(DWORD
), /* TokenVirtualizationEnabled */
376 sizeof(TOKEN_MANDATORY_LABEL
) + sizeof(SID
), /* TokenIntegrityLevel [sizeof(SID) includes one SubAuthority] */
377 0, /* TokenUIAccess */
378 0, /* TokenMandatoryPolicy */
379 0, /* TokenLogonSid */
380 sizeof(DWORD
), /* TokenIsAppContainer */
381 0, /* TokenCapabilities */
382 sizeof(TOKEN_APPCONTAINER_INFORMATION
) + sizeof(SID
), /* TokenAppContainerSid */
383 0, /* TokenAppContainerNumber */
384 0, /* TokenUserClaimAttributes*/
385 0, /* TokenDeviceClaimAttributes */
386 0, /* TokenRestrictedUserClaimAttributes */
387 0, /* TokenRestrictedDeviceClaimAttributes */
388 0, /* TokenDeviceGroups */
389 0, /* TokenRestrictedDeviceGroups */
390 0, /* TokenSecurityAttributes */
391 0, /* TokenIsRestricted */
392 0 /* TokenProcessTrustLevel */
396 NTSTATUS status
= STATUS_SUCCESS
;
398 TRACE("(%p,%d,%p,%d,%p)\n",
399 token
,tokeninfoclass
,tokeninfo
,tokeninfolength
,retlen
);
401 if (tokeninfoclass
< MaxTokenInfoClass
)
402 len
= info_len
[tokeninfoclass
];
404 if (retlen
) *retlen
= len
;
406 if (tokeninfolength
< len
)
407 return STATUS_BUFFER_TOO_SMALL
;
409 switch (tokeninfoclass
)
412 SERVER_START_REQ( get_token_sid
)
414 TOKEN_USER
* tuser
= tokeninfo
;
415 PSID sid
= tuser
+ 1;
416 DWORD sid_len
= tokeninfolength
< sizeof(TOKEN_USER
) ? 0 : tokeninfolength
- sizeof(TOKEN_USER
);
418 req
->handle
= wine_server_obj_handle( token
);
419 req
->which_sid
= tokeninfoclass
;
420 wine_server_set_reply( req
, sid
, sid_len
);
421 status
= wine_server_call( req
);
422 if (retlen
) *retlen
= reply
->sid_len
+ sizeof(TOKEN_USER
);
423 if (status
== STATUS_SUCCESS
)
425 tuser
->User
.Sid
= sid
;
426 tuser
->User
.Attributes
= 0;
435 /* reply buffer is always shorter than output one */
436 buffer
= tokeninfolength
? RtlAllocateHeap(GetProcessHeap(), 0, tokeninfolength
) : NULL
;
438 SERVER_START_REQ( get_token_groups
)
440 TOKEN_GROUPS
*groups
= tokeninfo
;
442 req
->handle
= wine_server_obj_handle( token
);
443 wine_server_set_reply( req
, buffer
, tokeninfolength
);
444 status
= wine_server_call( req
);
445 if (status
== STATUS_BUFFER_TOO_SMALL
)
447 if (retlen
) *retlen
= reply
->user_len
;
449 else if (status
== STATUS_SUCCESS
)
451 struct token_groups
*tg
= buffer
;
452 unsigned int *attr
= (unsigned int *)(tg
+ 1);
454 const int non_sid_portion
= (sizeof(struct token_groups
) + tg
->count
* sizeof(unsigned int));
455 SID
*sids
= (SID
*)((char *)tokeninfo
+ FIELD_OFFSET( TOKEN_GROUPS
, Groups
[tg
->count
] ));
457 if (retlen
) *retlen
= reply
->user_len
;
459 groups
->GroupCount
= tg
->count
;
460 memcpy( sids
, (char *)buffer
+ non_sid_portion
,
461 reply
->user_len
- FIELD_OFFSET( TOKEN_GROUPS
, Groups
[tg
->count
] ));
463 for (i
= 0; i
< tg
->count
; i
++)
465 groups
->Groups
[i
].Attributes
= attr
[i
];
466 groups
->Groups
[i
].Sid
= sids
;
467 sids
= (SID
*)((char *)sids
+ RtlLengthSid(sids
));
470 else if (retlen
) *retlen
= 0;
474 RtlFreeHeap(GetProcessHeap(), 0, buffer
);
477 case TokenPrimaryGroup
:
478 SERVER_START_REQ( get_token_sid
)
480 TOKEN_PRIMARY_GROUP
*tgroup
= tokeninfo
;
481 PSID sid
= tgroup
+ 1;
482 DWORD sid_len
= tokeninfolength
< sizeof(TOKEN_PRIMARY_GROUP
) ? 0 : tokeninfolength
- sizeof(TOKEN_PRIMARY_GROUP
);
484 req
->handle
= wine_server_obj_handle( token
);
485 req
->which_sid
= tokeninfoclass
;
486 wine_server_set_reply( req
, sid
, sid_len
);
487 status
= wine_server_call( req
);
488 if (retlen
) *retlen
= reply
->sid_len
+ sizeof(TOKEN_PRIMARY_GROUP
);
489 if (status
== STATUS_SUCCESS
)
490 tgroup
->PrimaryGroup
= sid
;
494 case TokenPrivileges
:
495 SERVER_START_REQ( get_token_privileges
)
497 TOKEN_PRIVILEGES
*tpriv
= tokeninfo
;
498 req
->handle
= wine_server_obj_handle( token
);
499 if (tpriv
&& tokeninfolength
> FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
))
500 wine_server_set_reply( req
, tpriv
->Privileges
, tokeninfolength
- FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
) );
501 status
= wine_server_call( req
);
502 if (retlen
) *retlen
= FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
) + reply
->len
;
503 if (tpriv
) tpriv
->PrivilegeCount
= reply
->len
/ sizeof(LUID_AND_ATTRIBUTES
);
508 SERVER_START_REQ( get_token_sid
)
510 TOKEN_OWNER
*towner
= tokeninfo
;
511 PSID sid
= towner
+ 1;
512 DWORD sid_len
= tokeninfolength
< sizeof(TOKEN_OWNER
) ? 0 : tokeninfolength
- sizeof(TOKEN_OWNER
);
514 req
->handle
= wine_server_obj_handle( token
);
515 req
->which_sid
= tokeninfoclass
;
516 wine_server_set_reply( req
, sid
, sid_len
);
517 status
= wine_server_call( req
);
518 if (retlen
) *retlen
= reply
->sid_len
+ sizeof(TOKEN_OWNER
);
519 if (status
== STATUS_SUCCESS
)
524 case TokenImpersonationLevel
:
525 SERVER_START_REQ( get_token_impersonation_level
)
527 SECURITY_IMPERSONATION_LEVEL
*impersonation_level
= tokeninfo
;
528 req
->handle
= wine_server_obj_handle( token
);
529 status
= wine_server_call( req
);
530 if (status
== STATUS_SUCCESS
)
531 *impersonation_level
= reply
->impersonation_level
;
535 case TokenStatistics
:
536 SERVER_START_REQ( get_token_statistics
)
538 TOKEN_STATISTICS
*statistics
= tokeninfo
;
539 req
->handle
= wine_server_obj_handle( token
);
540 status
= wine_server_call( req
);
541 if (status
== STATUS_SUCCESS
)
543 statistics
->TokenId
.LowPart
= reply
->token_id
.low_part
;
544 statistics
->TokenId
.HighPart
= reply
->token_id
.high_part
;
545 statistics
->AuthenticationId
.LowPart
= 0; /* FIXME */
546 statistics
->AuthenticationId
.HighPart
= 0; /* FIXME */
547 statistics
->ExpirationTime
.u
.HighPart
= 0x7fffffff;
548 statistics
->ExpirationTime
.u
.LowPart
= 0xffffffff;
549 statistics
->TokenType
= reply
->primary
? TokenPrimary
: TokenImpersonation
;
550 statistics
->ImpersonationLevel
= reply
->impersonation_level
;
552 /* kernel information not relevant to us */
553 statistics
->DynamicCharged
= 0;
554 statistics
->DynamicAvailable
= 0;
556 statistics
->GroupCount
= reply
->group_count
;
557 statistics
->PrivilegeCount
= reply
->privilege_count
;
558 statistics
->ModifiedId
.LowPart
= reply
->modified_id
.low_part
;
559 statistics
->ModifiedId
.HighPart
= reply
->modified_id
.high_part
;
565 SERVER_START_REQ( get_token_statistics
)
567 TOKEN_TYPE
*token_type
= tokeninfo
;
568 req
->handle
= wine_server_obj_handle( token
);
569 status
= wine_server_call( req
);
570 if (status
== STATUS_SUCCESS
)
571 *token_type
= reply
->primary
? TokenPrimary
: TokenImpersonation
;
575 case TokenDefaultDacl
:
576 SERVER_START_REQ( get_token_default_dacl
)
578 TOKEN_DEFAULT_DACL
*default_dacl
= tokeninfo
;
579 ACL
*acl
= (ACL
*)(default_dacl
+ 1);
582 if (tokeninfolength
< sizeof(TOKEN_DEFAULT_DACL
)) acl_len
= 0;
583 else acl_len
= tokeninfolength
- sizeof(TOKEN_DEFAULT_DACL
);
585 req
->handle
= wine_server_obj_handle( token
);
586 wine_server_set_reply( req
, acl
, acl_len
);
587 status
= wine_server_call( req
);
589 if (retlen
) *retlen
= reply
->acl_len
+ sizeof(TOKEN_DEFAULT_DACL
);
590 if (status
== STATUS_SUCCESS
)
593 default_dacl
->DefaultDacl
= acl
;
595 default_dacl
->DefaultDacl
= NULL
;
600 case TokenElevationType
:
602 TOKEN_ELEVATION_TYPE
*elevation_type
= tokeninfo
;
603 FIXME("QueryInformationToken( ..., TokenElevationType, ...) semi-stub\n");
604 *elevation_type
= TokenElevationTypeFull
;
609 TOKEN_ELEVATION
*elevation
= tokeninfo
;
610 FIXME("QueryInformationToken( ..., TokenElevation, ...) semi-stub\n");
611 elevation
->TokenIsElevated
= TRUE
;
616 *((DWORD
*)tokeninfo
) = 0;
617 FIXME("QueryInformationToken( ..., TokenSessionId, ...) semi-stub\n");
620 case TokenVirtualizationEnabled
:
622 *(DWORD
*)tokeninfo
= 0;
623 TRACE("QueryInformationToken( ..., TokenVirtualizationEnabled, ...) semi-stub\n");
626 case TokenIntegrityLevel
:
628 /* report always "S-1-16-12288" (high mandatory level) for now */
629 static const SID high_level
= {SID_REVISION
, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY
},
630 {SECURITY_MANDATORY_HIGH_RID
}};
632 TOKEN_MANDATORY_LABEL
*tml
= tokeninfo
;
635 tml
->Label
.Sid
= psid
;
636 tml
->Label
.Attributes
= SE_GROUP_INTEGRITY
| SE_GROUP_INTEGRITY_ENABLED
;
637 memcpy(psid
, &high_level
, sizeof(SID
));
640 case TokenAppContainerSid
:
642 TOKEN_APPCONTAINER_INFORMATION
*container
= tokeninfo
;
643 FIXME("QueryInformationToken( ..., TokenAppContainerSid, ...) semi-stub\n");
644 container
->TokenAppContainer
= NULL
;
647 case TokenIsAppContainer
:
649 TRACE("TokenIsAppContainer semi-stub\n");
650 *(DWORD
*)tokeninfo
= 0;
654 SERVER_START_REQ( get_token_sid
)
656 TOKEN_GROUPS
* groups
= tokeninfo
;
657 PSID sid
= groups
+ 1;
658 DWORD sid_len
= tokeninfolength
< sizeof(TOKEN_GROUPS
) ? 0 : tokeninfolength
- sizeof(TOKEN_GROUPS
);
660 req
->handle
= wine_server_obj_handle( token
);
661 req
->which_sid
= tokeninfoclass
;
662 wine_server_set_reply( req
, sid
, sid_len
);
663 status
= wine_server_call( req
);
664 if (retlen
) *retlen
= reply
->sid_len
+ sizeof(TOKEN_GROUPS
);
665 if (status
== STATUS_SUCCESS
)
667 groups
->GroupCount
= 1;
668 groups
->Groups
[0].Sid
= sid
;
669 groups
->Groups
[0].Attributes
= 0;
676 ERR("Unhandled Token Information class %d!\n", tokeninfoclass
);
677 return STATUS_NOT_IMPLEMENTED
;
683 /******************************************************************************
684 * NtSetInformationToken [NTDLL.@]
685 * ZwSetInformationToken [NTDLL.@]
687 NTSTATUS WINAPI
NtSetInformationToken(
689 TOKEN_INFORMATION_CLASS TokenInformationClass
,
690 PVOID TokenInformation
,
691 ULONG TokenInformationLength
)
693 NTSTATUS ret
= STATUS_NOT_IMPLEMENTED
;
695 TRACE("%p %d %p %u\n", TokenHandle
, TokenInformationClass
,
696 TokenInformation
, TokenInformationLength
);
698 switch (TokenInformationClass
)
700 case TokenDefaultDacl
:
701 if (TokenInformationLength
< sizeof(TOKEN_DEFAULT_DACL
))
703 ret
= STATUS_INFO_LENGTH_MISMATCH
;
706 if (!TokenInformation
)
708 ret
= STATUS_ACCESS_VIOLATION
;
711 SERVER_START_REQ( set_token_default_dacl
)
713 ACL
*acl
= ((TOKEN_DEFAULT_DACL
*)TokenInformation
)->DefaultDacl
;
716 if (acl
) size
= acl
->AclSize
;
719 req
->handle
= wine_server_obj_handle( TokenHandle
);
720 wine_server_add_data( req
, acl
, size
);
721 ret
= wine_server_call( req
);
726 if (TokenInformationLength
< sizeof(DWORD
))
728 ret
= STATUS_INFO_LENGTH_MISMATCH
;
731 if (!TokenInformation
)
733 ret
= STATUS_ACCESS_VIOLATION
;
736 FIXME("TokenSessionId stub!\n");
737 ret
= STATUS_SUCCESS
;
739 case TokenIntegrityLevel
:
740 FIXME("TokenIntegrityLevel stub!\n");
741 ret
= STATUS_SUCCESS
;
744 FIXME("unimplemented class %u\n", TokenInformationClass
);
751 /******************************************************************************
752 * NtAdjustGroupsToken [NTDLL.@]
753 * ZwAdjustGroupsToken [NTDLL.@]
755 NTSTATUS WINAPI
NtAdjustGroupsToken(
757 BOOLEAN ResetToDefault
,
758 PTOKEN_GROUPS NewState
,
760 PTOKEN_GROUPS PreviousState
,
763 FIXME("%p %d %p %u %p %p\n", TokenHandle
, ResetToDefault
,
764 NewState
, BufferLength
, PreviousState
, ReturnLength
);
765 return STATUS_NOT_IMPLEMENTED
;
768 /******************************************************************************
769 * NtPrivilegeCheck [NTDLL.@]
770 * ZwPrivilegeCheck [NTDLL.@]
772 NTSTATUS WINAPI
NtPrivilegeCheck(
774 PPRIVILEGE_SET RequiredPrivileges
,
778 SERVER_START_REQ( check_token_privileges
)
780 req
->handle
= wine_server_obj_handle( ClientToken
);
781 req
->all_required
= (RequiredPrivileges
->Control
& PRIVILEGE_SET_ALL_NECESSARY
) != 0;
782 wine_server_add_data( req
, RequiredPrivileges
->Privilege
,
783 RequiredPrivileges
->PrivilegeCount
* sizeof(RequiredPrivileges
->Privilege
[0]) );
784 wine_server_set_reply( req
, RequiredPrivileges
->Privilege
,
785 RequiredPrivileges
->PrivilegeCount
* sizeof(RequiredPrivileges
->Privilege
[0]) );
787 status
= wine_server_call( req
);
789 if (status
== STATUS_SUCCESS
)
790 *Result
= reply
->has_privileges
!= 0;
800 /******************************************************************************
801 * NtCreatePort [NTDLL.@]
802 * ZwCreatePort [NTDLL.@]
804 NTSTATUS WINAPI
NtCreatePort(PHANDLE PortHandle
,POBJECT_ATTRIBUTES ObjectAttributes
,
805 ULONG MaxConnectInfoLength
,ULONG MaxDataLength
,PULONG reserved
)
807 FIXME("(%p,%p,%u,%u,%p),stub!\n",PortHandle
,ObjectAttributes
,
808 MaxConnectInfoLength
,MaxDataLength
,reserved
);
809 return STATUS_NOT_IMPLEMENTED
;
812 /******************************************************************************
813 * NtConnectPort [NTDLL.@]
814 * ZwConnectPort [NTDLL.@]
816 NTSTATUS WINAPI
NtConnectPort(
818 PUNICODE_STRING PortName
,
819 PSECURITY_QUALITY_OF_SERVICE SecurityQos
,
820 PLPC_SECTION_WRITE WriteSection
,
821 PLPC_SECTION_READ ReadSection
,
822 PULONG MaximumMessageLength
,
824 PULONG pConnectInfoLength
)
826 FIXME("(%p,%s,%p,%p,%p,%p,%p,%p),stub!\n",
827 PortHandle
,debugstr_w(PortName
->Buffer
),SecurityQos
,
828 WriteSection
,ReadSection
,MaximumMessageLength
,ConnectInfo
,
830 if (ConnectInfo
&& pConnectInfoLength
)
831 TRACE("\tMessage = %s\n",debugstr_an(ConnectInfo
,*pConnectInfoLength
));
832 return STATUS_NOT_IMPLEMENTED
;
835 /******************************************************************************
836 * NtSecureConnectPort (NTDLL.@)
837 * ZwSecureConnectPort (NTDLL.@)
839 NTSTATUS WINAPI
NtSecureConnectPort(
841 PUNICODE_STRING PortName
,
842 PSECURITY_QUALITY_OF_SERVICE SecurityQos
,
843 PLPC_SECTION_WRITE WriteSection
,
845 PLPC_SECTION_READ ReadSection
,
846 PULONG MaximumMessageLength
,
848 PULONG pConnectInfoLength
)
850 FIXME("(%p,%s,%p,%p,%p,%p,%p,%p,%p),stub!\n",
851 PortHandle
,debugstr_w(PortName
->Buffer
),SecurityQos
,
852 WriteSection
,pSid
,ReadSection
,MaximumMessageLength
,ConnectInfo
,
854 return STATUS_NOT_IMPLEMENTED
;
857 /******************************************************************************
858 * NtListenPort [NTDLL.@]
859 * ZwListenPort [NTDLL.@]
861 NTSTATUS WINAPI
NtListenPort(HANDLE PortHandle
,PLPC_MESSAGE pLpcMessage
)
863 FIXME("(%p,%p),stub!\n",PortHandle
,pLpcMessage
);
864 return STATUS_NOT_IMPLEMENTED
;
867 /******************************************************************************
868 * NtAcceptConnectPort [NTDLL.@]
869 * ZwAcceptConnectPort [NTDLL.@]
871 NTSTATUS WINAPI
NtAcceptConnectPort(
873 ULONG PortIdentifier
,
874 PLPC_MESSAGE pLpcMessage
,
876 PLPC_SECTION_WRITE WriteSection
,
877 PLPC_SECTION_READ ReadSection
)
879 FIXME("(%p,%u,%p,%d,%p,%p),stub!\n",
880 PortHandle
,PortIdentifier
,pLpcMessage
,Accept
,WriteSection
,ReadSection
);
881 return STATUS_NOT_IMPLEMENTED
;
884 /******************************************************************************
885 * NtCompleteConnectPort [NTDLL.@]
886 * ZwCompleteConnectPort [NTDLL.@]
888 NTSTATUS WINAPI
NtCompleteConnectPort(HANDLE PortHandle
)
890 FIXME("(%p),stub!\n",PortHandle
);
891 return STATUS_NOT_IMPLEMENTED
;
894 /******************************************************************************
895 * NtRegisterThreadTerminatePort [NTDLL.@]
896 * ZwRegisterThreadTerminatePort [NTDLL.@]
898 NTSTATUS WINAPI
NtRegisterThreadTerminatePort(HANDLE PortHandle
)
900 FIXME("(%p),stub!\n",PortHandle
);
901 return STATUS_NOT_IMPLEMENTED
;
904 /******************************************************************************
905 * NtRequestWaitReplyPort [NTDLL.@]
906 * ZwRequestWaitReplyPort [NTDLL.@]
908 NTSTATUS WINAPI
NtRequestWaitReplyPort(
910 PLPC_MESSAGE pLpcMessageIn
,
911 PLPC_MESSAGE pLpcMessageOut
)
913 FIXME("(%p,%p,%p),stub!\n",PortHandle
,pLpcMessageIn
,pLpcMessageOut
);
916 TRACE("Message to send:\n");
917 TRACE("\tDataSize = %u\n",pLpcMessageIn
->DataSize
);
918 TRACE("\tMessageSize = %u\n",pLpcMessageIn
->MessageSize
);
919 TRACE("\tMessageType = %u\n",pLpcMessageIn
->MessageType
);
920 TRACE("\tVirtualRangesOffset = %u\n",pLpcMessageIn
->VirtualRangesOffset
);
921 TRACE("\tClientId.UniqueProcess = %p\n",pLpcMessageIn
->ClientId
.UniqueProcess
);
922 TRACE("\tClientId.UniqueThread = %p\n",pLpcMessageIn
->ClientId
.UniqueThread
);
923 TRACE("\tMessageId = %lu\n",pLpcMessageIn
->MessageId
);
924 TRACE("\tSectionSize = %lu\n",pLpcMessageIn
->SectionSize
);
925 TRACE("\tData = %s\n",
926 debugstr_an((const char*)pLpcMessageIn
->Data
,pLpcMessageIn
->DataSize
));
928 return STATUS_NOT_IMPLEMENTED
;
931 /******************************************************************************
932 * NtReplyWaitReceivePort [NTDLL.@]
933 * ZwReplyWaitReceivePort [NTDLL.@]
935 NTSTATUS WINAPI
NtReplyWaitReceivePort(
937 PULONG PortIdentifier
,
938 PLPC_MESSAGE ReplyMessage
,
939 PLPC_MESSAGE Message
)
941 FIXME("(%p,%p,%p,%p),stub!\n",PortHandle
,PortIdentifier
,ReplyMessage
,Message
);
942 return STATUS_NOT_IMPLEMENTED
;
949 /******************************************************************************
950 * NtSetIntervalProfile [NTDLL.@]
951 * ZwSetIntervalProfile [NTDLL.@]
953 NTSTATUS WINAPI
NtSetIntervalProfile(
955 KPROFILE_SOURCE Source
)
957 FIXME("%u,%d\n", Interval
, Source
);
958 return STATUS_SUCCESS
;
961 SYSTEM_CPU_INFORMATION cpu_info
= { 0 };
963 /*******************************************************************************
964 * Architecture specific feature detection for CPUs
966 * This a set of mutually exclusive #if define()s each providing its own get_cpuinfo() to be called
967 * from fill_cpu_info();
969 #if defined(__i386__) || defined(__x86_64__)
971 #define AUTH 0x68747541 /* "Auth" */
972 #define ENTI 0x69746e65 /* "enti" */
973 #define CAMD 0x444d4163 /* "cAMD" */
975 #define GENU 0x756e6547 /* "Genu" */
976 #define INEI 0x49656e69 /* "ineI" */
977 #define NTEL 0x6c65746e /* "ntel" */
979 extern void do_cpuid(unsigned int ax
, unsigned int *p
);
982 __ASM_GLOBAL_FUNC( do_cpuid
,
985 "movl 12(%esp),%eax\n\t"
986 "movl 16(%esp),%esi\n\t"
988 "movl %eax,(%esi)\n\t"
989 "movl %ebx,4(%esi)\n\t"
990 "movl %ecx,8(%esi)\n\t"
991 "movl %edx,12(%esi)\n\t"
996 __ASM_GLOBAL_FUNC( do_cpuid
,
1000 "movl %eax,(%rsi)\n\t"
1001 "movl %ebx,4(%rsi)\n\t"
1002 "movl %ecx,8(%rsi)\n\t"
1003 "movl %edx,12(%rsi)\n\t"
1009 extern int have_cpuid(void);
1010 __ASM_GLOBAL_FUNC( have_cpuid
,
1013 "movl (%esp),%ecx\n\t"
1014 "xorl $0x00200000,(%esp)\n\t"
1019 "xorl %ecx,%eax\n\t"
1020 "andl $0x00200000,%eax\n\t"
1023 static int have_cpuid(void)
1029 /* Detect if a SSE2 processor is capable of Denormals Are Zero (DAZ) mode.
1031 * This function assumes you have already checked for SSE2/FXSAVE support. */
1032 static inline BOOL
have_sse_daz_mode(void)
1035 typedef struct DECLSPEC_ALIGN(16) _M128A
{
1040 typedef struct _XMM_SAVE_AREA32
{
1054 M128A FloatRegisters
[8];
1055 M128A XmmRegisters
[16];
1059 /* Intel says we need a zeroed 16-byte aligned buffer */
1060 char buffer
[512 + 16];
1061 XMM_SAVE_AREA32
*state
= (XMM_SAVE_AREA32
*)(((ULONG_PTR
)buffer
+ 15) & ~15);
1062 memset(buffer
, 0, sizeof(buffer
));
1064 __asm__
__volatile__( "fxsave %0" : "=m" (*state
) : "m" (*state
) );
1066 return (state
->MxCsr_Mask
& (1 << 6)) >> 6;
1067 #else /* all x86_64 processors include SSE2 with DAZ mode */
1072 static inline void get_cpuinfo(SYSTEM_CPU_INFORMATION
* info
)
1074 unsigned int regs
[4], regs2
[4];
1076 #if defined(__i386__)
1077 info
->Architecture
= PROCESSOR_ARCHITECTURE_INTEL
;
1078 #elif defined(__x86_64__)
1079 info
->Architecture
= PROCESSOR_ARCHITECTURE_AMD64
;
1082 /* We're at least a 386 */
1083 info
->FeatureSet
= CPU_FEATURE_VME
| CPU_FEATURE_X86
| CPU_FEATURE_PGE
;
1086 if (!have_cpuid()) return;
1088 do_cpuid(0x00000000, regs
); /* get standard cpuid level and vendor name */
1089 if (regs
[0]>=0x00000001) /* Check for supported cpuid version */
1091 do_cpuid(0x00000001, regs2
); /* get cpu features */
1093 if(regs2
[3] & (1 << 3 )) info
->FeatureSet
|= CPU_FEATURE_PSE
;
1094 if(regs2
[3] & (1 << 4 )) info
->FeatureSet
|= CPU_FEATURE_TSC
;
1095 if(regs2
[3] & (1 << 8 )) info
->FeatureSet
|= CPU_FEATURE_CX8
;
1096 if(regs2
[3] & (1 << 11)) info
->FeatureSet
|= CPU_FEATURE_SEP
;
1097 if(regs2
[3] & (1 << 12)) info
->FeatureSet
|= CPU_FEATURE_MTRR
;
1098 if(regs2
[3] & (1 << 15)) info
->FeatureSet
|= CPU_FEATURE_CMOV
;
1099 if(regs2
[3] & (1 << 16)) info
->FeatureSet
|= CPU_FEATURE_PAT
;
1100 if(regs2
[3] & (1 << 23)) info
->FeatureSet
|= CPU_FEATURE_MMX
;
1101 if(regs2
[3] & (1 << 24)) info
->FeatureSet
|= CPU_FEATURE_FXSR
;
1102 if(regs2
[3] & (1 << 25)) info
->FeatureSet
|= CPU_FEATURE_SSE
;
1103 if(regs2
[3] & (1 << 26)) info
->FeatureSet
|= CPU_FEATURE_SSE2
;
1105 user_shared_data
->ProcessorFeatures
[PF_FLOATING_POINT_EMULATED
] = !(regs2
[3] & 1);
1106 user_shared_data
->ProcessorFeatures
[PF_RDTSC_INSTRUCTION_AVAILABLE
] = (regs2
[3] >> 4) & 1;
1107 user_shared_data
->ProcessorFeatures
[PF_PAE_ENABLED
] = (regs2
[3] >> 6) & 1;
1108 user_shared_data
->ProcessorFeatures
[PF_COMPARE_EXCHANGE_DOUBLE
] = (regs2
[3] >> 8) & 1;
1109 user_shared_data
->ProcessorFeatures
[PF_MMX_INSTRUCTIONS_AVAILABLE
] = (regs2
[3] >> 23) & 1;
1110 user_shared_data
->ProcessorFeatures
[PF_XMMI_INSTRUCTIONS_AVAILABLE
] = (regs2
[3] >> 25) & 1;
1111 user_shared_data
->ProcessorFeatures
[PF_XMMI64_INSTRUCTIONS_AVAILABLE
] = (regs2
[3] >> 26) & 1;
1112 user_shared_data
->ProcessorFeatures
[PF_SSE3_INSTRUCTIONS_AVAILABLE
] = regs2
[2] & 1;
1113 user_shared_data
->ProcessorFeatures
[PF_XSAVE_ENABLED
] = (regs2
[2] >> 27) & 1;
1114 user_shared_data
->ProcessorFeatures
[PF_COMPARE_EXCHANGE128
] = (regs2
[2] >> 13) & 1;
1116 if((regs2
[3] & (1 << 26)) && (regs2
[3] & (1 << 24))) /* has SSE2 and FXSAVE/FXRSTOR */
1117 user_shared_data
->ProcessorFeatures
[PF_SSE_DAZ_MODE_AVAILABLE
] = have_sse_daz_mode();
1119 if (regs
[1] == AUTH
&& regs
[3] == ENTI
&& regs
[2] == CAMD
)
1121 info
->Level
= (regs2
[0] >> 8) & 0xf; /* family */
1122 if (info
->Level
== 0xf) /* AMD says to add the extended family to the family if family is 0xf */
1123 info
->Level
+= (regs2
[0] >> 20) & 0xff;
1125 /* repack model and stepping to make a "revision" */
1126 info
->Revision
= ((regs2
[0] >> 16) & 0xf) << 12; /* extended model */
1127 info
->Revision
|= ((regs2
[0] >> 4 ) & 0xf) << 8; /* model */
1128 info
->Revision
|= regs2
[0] & 0xf; /* stepping */
1130 do_cpuid(0x80000000, regs
); /* get vendor cpuid level */
1131 if (regs
[0] >= 0x80000001)
1133 do_cpuid(0x80000001, regs2
); /* get vendor features */
1134 user_shared_data
->ProcessorFeatures
[PF_VIRT_FIRMWARE_ENABLED
] = (regs2
[2] >> 2) & 1;
1135 user_shared_data
->ProcessorFeatures
[PF_NX_ENABLED
] = (regs2
[3] >> 20) & 1;
1136 user_shared_data
->ProcessorFeatures
[PF_3DNOW_INSTRUCTIONS_AVAILABLE
] = (regs2
[3] >> 31) & 1;
1137 user_shared_data
->ProcessorFeatures
[PF_RDTSC_INSTRUCTION_AVAILABLE
] = (regs2
[3] >> 27) & 1;
1138 if (regs2
[3] >> 31) info
->FeatureSet
|= CPU_FEATURE_3DNOW
;
1141 else if (regs
[1] == GENU
&& regs
[3] == INEI
&& regs
[2] == NTEL
)
1143 info
->Level
= ((regs2
[0] >> 8) & 0xf) + ((regs2
[0] >> 20) & 0xff); /* family + extended family */
1144 if(info
->Level
== 15) info
->Level
= 6;
1146 /* repack model and stepping to make a "revision" */
1147 info
->Revision
= ((regs2
[0] >> 16) & 0xf) << 12; /* extended model */
1148 info
->Revision
|= ((regs2
[0] >> 4 ) & 0xf) << 8; /* model */
1149 info
->Revision
|= regs2
[0] & 0xf; /* stepping */
1151 if(regs2
[3] & (1 << 21)) info
->FeatureSet
|= CPU_FEATURE_DS
;
1152 user_shared_data
->ProcessorFeatures
[PF_VIRT_FIRMWARE_ENABLED
] = (regs2
[2] >> 5) & 1;
1154 do_cpuid(0x80000000, regs
); /* get vendor cpuid level */
1155 if (regs
[0] >= 0x80000001)
1157 do_cpuid(0x80000001, regs2
); /* get vendor features */
1158 user_shared_data
->ProcessorFeatures
[PF_NX_ENABLED
] = (regs2
[3] >> 20) & 1;
1159 user_shared_data
->ProcessorFeatures
[PF_RDTSC_INSTRUCTION_AVAILABLE
] = (regs2
[3] >> 27) & 1;
1164 info
->Level
= (regs2
[0] >> 8) & 0xf; /* family */
1166 /* repack model and stepping to make a "revision" */
1167 info
->Revision
= ((regs2
[0] >> 4 ) & 0xf) << 8; /* model */
1168 info
->Revision
|= regs2
[0] & 0xf; /* stepping */
1173 #elif defined(__powerpc__) || defined(__ppc__)
1175 static inline void get_cpuinfo(SYSTEM_CPU_INFORMATION
* info
)
1181 valSize
= sizeof(value
);
1182 if (sysctlbyname("hw.optional.floatingpoint", &value
, &valSize
, NULL
, 0) == 0)
1183 user_shared_data
->ProcessorFeatures
[PF_FLOATING_POINT_EMULATED
] = !value
;
1185 valSize
= sizeof(value
);
1186 if (sysctlbyname("hw.cpusubtype", &value
, &valSize
, NULL
, 0) == 0)
1190 case CPU_SUBTYPE_POWERPC_601
:
1191 case CPU_SUBTYPE_POWERPC_602
: info
->Level
= 1; break;
1192 case CPU_SUBTYPE_POWERPC_603
: info
->Level
= 3; break;
1193 case CPU_SUBTYPE_POWERPC_603e
:
1194 case CPU_SUBTYPE_POWERPC_603ev
: info
->Level
= 6; break;
1195 case CPU_SUBTYPE_POWERPC_604
: info
->Level
= 4; break;
1196 case CPU_SUBTYPE_POWERPC_604e
: info
->Level
= 9; break;
1197 case CPU_SUBTYPE_POWERPC_620
: info
->Level
= 20; break;
1198 case CPU_SUBTYPE_POWERPC_750
: /* G3/G4 derive from 603 so ... */
1199 case CPU_SUBTYPE_POWERPC_7400
:
1200 case CPU_SUBTYPE_POWERPC_7450
: info
->Level
= 6; break;
1201 case CPU_SUBTYPE_POWERPC_970
: info
->Level
= 9;
1202 /* :o) user_shared_data->ProcessorFeatures[PF_ALTIVEC_INSTRUCTIONS_AVAILABLE] ;-) */
1208 FIXME("CPU Feature detection not implemented.\n");
1210 info
->Architecture
= PROCESSOR_ARCHITECTURE_PPC
;
1213 #elif defined(__arm__)
1215 static inline void get_cpuinfo(SYSTEM_CPU_INFORMATION
* info
)
1220 FILE *f
= fopen("/proc/cpuinfo", "r");
1223 while (fgets(line
, sizeof(line
), f
) != NULL
)
1225 /* NOTE: the ':' is the only character we can rely on */
1226 if (!(value
= strchr(line
,':')))
1228 /* terminate the valuename */
1230 while ((s
>= line
) && isspace(*s
)) s
--;
1232 /* and strip leading spaces from value */
1234 while (isspace(*value
)) value
++;
1235 if ((s
= strchr(value
,'\n')))
1237 if (!_stricmp(line
, "CPU architecture"))
1239 if (isdigit(value
[0]))
1240 info
->Level
= atoi(value
);
1243 if (!_stricmp(line
, "CPU revision"))
1245 if (isdigit(value
[0]))
1246 info
->Revision
= atoi(value
);
1249 if (!_stricmp(line
, "features"))
1251 if (strstr(value
, "vfpv3"))
1252 user_shared_data
->ProcessorFeatures
[PF_ARM_VFP_32_REGISTERS_AVAILABLE
] = TRUE
;
1253 if (strstr(value
, "neon"))
1254 user_shared_data
->ProcessorFeatures
[PF_ARM_NEON_INSTRUCTIONS_AVAILABLE
] = TRUE
;
1260 #elif defined(__FreeBSD__)
1265 valsize
= sizeof(buf
);
1266 if (!sysctlbyname("hw.machine_arch", &buf
, &valsize
, NULL
, 0) &&
1267 sscanf(buf
, "armv%i", &value
) == 1)
1268 info
->Level
= value
;
1270 valsize
= sizeof(value
);
1271 if (!sysctlbyname("hw.floatingpoint", &value
, &valsize
, NULL
, 0))
1272 user_shared_data
->ProcessorFeatures
[PF_ARM_VFP_32_REGISTERS_AVAILABLE
] = value
;
1274 FIXME("CPU Feature detection not implemented.\n");
1276 if (info
->Level
>= 8)
1277 user_shared_data
->ProcessorFeatures
[PF_ARM_V8_INSTRUCTIONS_AVAILABLE
] = TRUE
;
1278 info
->Architecture
= PROCESSOR_ARCHITECTURE_ARM
;
1281 #elif defined(__aarch64__)
1283 static inline void get_cpuinfo(SYSTEM_CPU_INFORMATION
* info
)
1288 FILE *f
= fopen("/proc/cpuinfo", "r");
1291 while (fgets(line
, sizeof(line
), f
) != NULL
)
1293 /* NOTE: the ':' is the only character we can rely on */
1294 if (!(value
= strchr(line
,':')))
1296 /* terminate the valuename */
1298 while ((s
>= line
) && isspace(*s
)) s
--;
1300 /* and strip leading spaces from value */
1302 while (isspace(*value
)) value
++;
1303 if ((s
= strchr(value
,'\n')))
1305 if (!_stricmp(line
, "CPU architecture"))
1307 if (isdigit(value
[0]))
1308 info
->Level
= atoi(value
);
1311 if (!_stricmp(line
, "CPU revision"))
1313 if (isdigit(value
[0]))
1314 info
->Revision
= atoi(value
);
1317 if (!_stricmp(line
, "Features"))
1319 if (strstr(value
, "crc32"))
1320 user_shared_data
->ProcessorFeatures
[PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE
] = TRUE
;
1321 if (strstr(value
, "aes"))
1322 user_shared_data
->ProcessorFeatures
[PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE
] = TRUE
;
1329 FIXME("CPU Feature detection not implemented.\n");
1331 info
->Level
= max(info
->Level
, 8);
1332 user_shared_data
->ProcessorFeatures
[PF_ARM_V8_INSTRUCTIONS_AVAILABLE
] = TRUE
;
1333 info
->Architecture
= PROCESSOR_ARCHITECTURE_ARM64
;
1336 #endif /* End architecture specific feature detection for CPUs */
1338 /******************************************************************
1341 * inits a couple of places with CPU related information:
1342 * - cpu_info in this file
1343 * - Peb->NumberOfProcessors
1344 * - SharedUserData->ProcessFeatures[] array
1346 void fill_cpu_info(void)
1350 #ifdef _SC_NPROCESSORS_ONLN
1351 num
= sysconf(_SC_NPROCESSORS_ONLN
);
1355 WARN("Failed to detect the number of processors.\n");
1357 #elif defined(CTL_HW) && defined(HW_NCPU)
1359 size_t len
= sizeof(num
);
1362 if (sysctl(mib
, 2, &num
, &len
, NULL
, 0) != 0)
1365 WARN("Failed to detect the number of processors.\n");
1369 FIXME("Detecting the number of processors is not supported.\n");
1371 NtCurrentTeb()->Peb
->NumberOfProcessors
= num
;
1373 get_cpuinfo(&cpu_info
);
1375 TRACE("<- CPU arch %d, level %d, rev %d, features 0x%x\n",
1376 cpu_info
.Architecture
, cpu_info
.Level
, cpu_info
.Revision
, cpu_info
.FeatureSet
);
1379 static BOOL
grow_logical_proc_buf(SYSTEM_LOGICAL_PROCESSOR_INFORMATION
**pdata
,
1380 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
**pdataex
, DWORD
*max_len
)
1384 SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*new_data
;
1387 new_data
= RtlReAllocateHeap(GetProcessHeap(), 0, *pdata
, *max_len
*sizeof(*new_data
));
1395 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*new_dataex
;
1398 new_dataex
= RtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pdataex
, *max_len
*sizeof(*new_dataex
));
1402 *pdataex
= new_dataex
;
1408 static DWORD
log_proc_ex_size_plus(DWORD size
)
1410 /* add SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX.Relationship and .Size */
1411 return sizeof(LOGICAL_PROCESSOR_RELATIONSHIP
) + sizeof(DWORD
) + size
;
1414 static DWORD
count_bits(ULONG_PTR mask
)
1425 /* Store package and core information for a logical processor. Parsing of processor
1426 * data may happen in multiple passes; the 'id' parameter is then used to locate
1427 * previously stored data. The type of data stored in 'id' depends on 'rel':
1428 * - RelationProcessorPackage: package id ('CPU socket').
1429 * - RelationProcessorCore: physical core number.
1431 static inline BOOL
logical_proc_info_add_by_id(SYSTEM_LOGICAL_PROCESSOR_INFORMATION
**pdata
,
1432 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
**pdataex
, DWORD
*len
, DWORD
*pmax_len
,
1433 LOGICAL_PROCESSOR_RELATIONSHIP rel
, DWORD id
, ULONG_PTR mask
)
1438 for (i
=0; i
<*len
; i
++)
1440 if (rel
== RelationProcessorPackage
&& (*pdata
)[i
].Relationship
== rel
&& (*pdata
)[i
].u
.Reserved
[1] == id
)
1442 (*pdata
)[i
].ProcessorMask
|= mask
;
1445 else if (rel
== RelationProcessorCore
&& (*pdata
)[i
].Relationship
== rel
&& (*pdata
)[i
].u
.Reserved
[1] == id
)
1449 while(*len
== *pmax_len
)
1451 if (!grow_logical_proc_buf(pdata
, NULL
, pmax_len
))
1455 (*pdata
)[i
].Relationship
= rel
;
1456 (*pdata
)[i
].ProcessorMask
= mask
;
1457 if (rel
== RelationProcessorCore
)
1458 (*pdata
)[i
].u
.ProcessorCore
.Flags
= count_bits(mask
) > 1 ? LTP_PC_SMT
: 0;
1459 (*pdata
)[i
].u
.Reserved
[0] = 0;
1460 (*pdata
)[i
].u
.Reserved
[1] = id
;
1463 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*dataex
;
1468 dataex
= (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*)(((char *)*pdataex
) + ofs
);
1469 if (rel
== RelationProcessorPackage
&& dataex
->Relationship
== rel
&& dataex
->u
.Processor
.Reserved
[1] == id
)
1471 dataex
->u
.Processor
.GroupMask
[0].Mask
|= mask
;
1474 else if (rel
== RelationProcessorCore
&& dataex
->Relationship
== rel
&& dataex
->u
.Processor
.Reserved
[1] == id
)
1478 ofs
+= dataex
->Size
;
1481 /* TODO: For now, just one group. If more than 64 processors, then we
1482 * need another group. */
1484 while (ofs
+ log_proc_ex_size_plus(sizeof(PROCESSOR_RELATIONSHIP
)) > *pmax_len
)
1486 if (!grow_logical_proc_buf(NULL
, pdataex
, pmax_len
))
1490 dataex
= (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*)(((char *)*pdataex
) + ofs
);
1492 dataex
->Relationship
= rel
;
1493 dataex
->Size
= log_proc_ex_size_plus(sizeof(PROCESSOR_RELATIONSHIP
));
1494 if (rel
== RelationProcessorCore
)
1495 dataex
->u
.Processor
.Flags
= count_bits(mask
) > 1 ? LTP_PC_SMT
: 0;
1497 dataex
->u
.Processor
.Flags
= 0;
1498 dataex
->u
.Processor
.EfficiencyClass
= 0;
1499 dataex
->u
.Processor
.GroupCount
= 1;
1500 dataex
->u
.Processor
.GroupMask
[0].Mask
= mask
;
1501 dataex
->u
.Processor
.GroupMask
[0].Group
= 0;
1502 /* mark for future lookup */
1503 dataex
->u
.Processor
.Reserved
[0] = 0;
1504 dataex
->u
.Processor
.Reserved
[1] = id
;
1506 *len
+= dataex
->Size
;
1512 static inline BOOL
logical_proc_info_add_cache(SYSTEM_LOGICAL_PROCESSOR_INFORMATION
**pdata
,
1513 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
**pdataex
, DWORD
*len
,
1514 DWORD
*pmax_len
, ULONG_PTR mask
, CACHE_DESCRIPTOR
*cache
)
1520 for (i
=0; i
<*len
; i
++)
1522 if ((*pdata
)[i
].Relationship
==RelationCache
&& (*pdata
)[i
].ProcessorMask
==mask
1523 && (*pdata
)[i
].u
.Cache
.Level
==cache
->Level
&& (*pdata
)[i
].u
.Cache
.Type
==cache
->Type
)
1527 while (*len
== *pmax_len
)
1528 if (!grow_logical_proc_buf(pdata
, NULL
, pmax_len
))
1531 (*pdata
)[i
].Relationship
= RelationCache
;
1532 (*pdata
)[i
].ProcessorMask
= mask
;
1533 (*pdata
)[i
].u
.Cache
= *cache
;
1538 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*dataex
;
1541 for (ofs
= 0; ofs
< *len
; )
1543 dataex
= (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*)(((char *)*pdataex
) + ofs
);
1544 if (dataex
->Relationship
== RelationCache
&& dataex
->u
.Cache
.GroupMask
.Mask
== mask
&&
1545 dataex
->u
.Cache
.Level
== cache
->Level
&& dataex
->u
.Cache
.Type
== cache
->Type
)
1547 ofs
+= dataex
->Size
;
1550 while (ofs
+ log_proc_ex_size_plus(sizeof(CACHE_RELATIONSHIP
)) > *pmax_len
)
1552 if (!grow_logical_proc_buf(NULL
, pdataex
, pmax_len
))
1556 dataex
= (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*)(((char *)*pdataex
) + ofs
);
1558 dataex
->Relationship
= RelationCache
;
1559 dataex
->Size
= log_proc_ex_size_plus(sizeof(CACHE_RELATIONSHIP
));
1560 dataex
->u
.Cache
.Level
= cache
->Level
;
1561 dataex
->u
.Cache
.Associativity
= cache
->Associativity
;
1562 dataex
->u
.Cache
.LineSize
= cache
->LineSize
;
1563 dataex
->u
.Cache
.CacheSize
= cache
->Size
;
1564 dataex
->u
.Cache
.Type
= cache
->Type
;
1565 dataex
->u
.Cache
.GroupMask
.Mask
= mask
;
1566 dataex
->u
.Cache
.GroupMask
.Group
= 0;
1568 *len
+= dataex
->Size
;
1574 static inline BOOL
logical_proc_info_add_numa_node(SYSTEM_LOGICAL_PROCESSOR_INFORMATION
**pdata
,
1575 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
**pdataex
, DWORD
*len
, DWORD
*pmax_len
, ULONG_PTR mask
,
1580 while (*len
== *pmax_len
)
1581 if (!grow_logical_proc_buf(pdata
, NULL
, pmax_len
))
1584 (*pdata
)[*len
].Relationship
= RelationNumaNode
;
1585 (*pdata
)[*len
].ProcessorMask
= mask
;
1586 (*pdata
)[*len
].u
.NumaNode
.NodeNumber
= node_id
;
1591 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*dataex
;
1593 while (*len
+ log_proc_ex_size_plus(sizeof(NUMA_NODE_RELATIONSHIP
)) > *pmax_len
)
1595 if (!grow_logical_proc_buf(NULL
, pdataex
, pmax_len
))
1599 dataex
= (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*)(((char *)*pdataex
) + *len
);
1601 dataex
->Relationship
= RelationNumaNode
;
1602 dataex
->Size
= log_proc_ex_size_plus(sizeof(NUMA_NODE_RELATIONSHIP
));
1603 dataex
->u
.NumaNode
.NodeNumber
= node_id
;
1604 dataex
->u
.NumaNode
.GroupMask
.Mask
= mask
;
1605 dataex
->u
.NumaNode
.GroupMask
.Group
= 0;
1607 *len
+= dataex
->Size
;
1613 static inline BOOL
logical_proc_info_add_group(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
**pdataex
,
1614 DWORD
*len
, DWORD
*pmax_len
, DWORD num_cpus
, ULONG_PTR mask
)
1616 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*dataex
;
1618 while (*len
+ log_proc_ex_size_plus(sizeof(GROUP_RELATIONSHIP
)) > *pmax_len
)
1620 if (!grow_logical_proc_buf(NULL
, pdataex
, pmax_len
))
1624 dataex
= (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*)(((char *)*pdataex
) + *len
);
1626 dataex
->Relationship
= RelationGroup
;
1627 dataex
->Size
= log_proc_ex_size_plus(sizeof(GROUP_RELATIONSHIP
));
1628 dataex
->u
.Group
.MaximumGroupCount
= 1;
1629 dataex
->u
.Group
.ActiveGroupCount
= 1;
1630 dataex
->u
.Group
.GroupInfo
[0].MaximumProcessorCount
= num_cpus
;
1631 dataex
->u
.Group
.GroupInfo
[0].ActiveProcessorCount
= num_cpus
;
1632 dataex
->u
.Group
.GroupInfo
[0].ActiveProcessorMask
= mask
;
1634 *len
+= dataex
->Size
;
1640 /* Helper function for counting bitmap values as commonly used by the Linux kernel
1641 * for storing CPU masks in sysfs. The format is comma separated lists of hex values
1642 * each max 32-bit e.g. "00ff" or even "00,00000000,0000ffff".
1644 * Example files include:
1645 * - /sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_map
1646 * - /sys/devices/system/cpu/cpu0/topology/thread_siblings
1648 static BOOL
sysfs_parse_bitmap(const char *filename
, ULONG_PTR
* const mask
)
1653 f
= fopen(filename
, "r");
1660 if (!fscanf(f
, "%x%c ", &r
, &op
))
1663 *mask
= (sizeof(ULONG_PTR
)>sizeof(int) ? *mask
<<(8*sizeof(DWORD
)) : 0) + r
;
1670 /* Helper function for counting number of elements in interval lists as used by
1671 * the Linux kernel. The format is comma separated list of intervals of which
1672 * each interval has the format of "begin-end" where begin and end are decimal
1673 * numbers. E.g. "0-7", "0-7,16-23"
1675 * Example files include:
1676 * - /sys/devices/system/cpu/online
1677 * - /sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_list
1678 * - /sys/devices/system/cpu/cpu0/topology/thread_siblings_list.
1680 static BOOL
sysfs_count_list_elements(const char *filename
, DWORD
*result
)
1684 f
= fopen(filename
, "r");
1693 if (!fscanf(f
, "%u%c ", &beg
, &op
))
1697 fscanf(f
, "%u%c ", &end
, &op
);
1701 *result
+= end
- beg
+ 1;
1708 /* for 'data', max_len is the array count. for 'dataex', max_len is in bytes */
1709 static NTSTATUS
create_logical_proc_info(SYSTEM_LOGICAL_PROCESSOR_INFORMATION
**data
,
1710 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
**dataex
, DWORD
*max_len
, DWORD relation
)
1712 static const char core_info
[] = "/sys/devices/system/cpu/cpu%u/topology/%s";
1713 static const char cache_info
[] = "/sys/devices/system/cpu/cpu%u/cache/index%u/%s";
1714 static const char numa_info
[] = "/sys/devices/system/node/node%u/cpumap";
1716 FILE *fcpu_list
, *fnuma_list
, *f
;
1717 DWORD len
= 0, beg
, end
, i
, j
, r
, num_cpus
= 0, max_cpus
= 0;
1718 char op
, name
[MAX_PATH
];
1719 ULONG_PTR all_cpus_mask
= 0;
1721 /* On systems with a large number of CPU cores (32 or 64 depending on 32-bit or 64-bit),
1722 * we have issues parsing processor information:
1723 * - ULONG_PTR masks as used in data structures can't hold all cores. Requires splitting
1724 * data appropriately into "processor groups". We are hard coding 1.
1725 * - Thread affinity code in wineserver and our CPU parsing code here work independently.
1726 * So far the Windows mask applied directly to Linux, but process groups break that.
1727 * (NUMA systems you may have multiple non-full groups.)
1729 if(sysfs_count_list_elements("/sys/devices/system/cpu/present", &max_cpus
) && max_cpus
> MAXIMUM_PROCESSORS
)
1731 FIXME("Improve CPU info reporting: system supports %u logical cores, but only %u supported!\n",
1732 max_cpus
, MAXIMUM_PROCESSORS
);
1735 fcpu_list
= fopen("/sys/devices/system/cpu/online", "r");
1737 return STATUS_NOT_IMPLEMENTED
;
1739 while(!feof(fcpu_list
))
1741 if(!fscanf(fcpu_list
, "%u%c ", &beg
, &op
))
1743 if(op
== '-') fscanf(fcpu_list
, "%u%c ", &end
, &op
);
1746 for(i
=beg
; i
<=end
; i
++)
1748 DWORD phys_core
= 0;
1749 ULONG_PTR thread_mask
= 0;
1751 if(i
> 8*sizeof(ULONG_PTR
))
1753 FIXME("skipping logical processor %d\n", i
);
1757 if(relation
== RelationAll
|| relation
== RelationProcessorPackage
)
1759 sprintf(name
, core_info
, i
, "physical_package_id");
1760 f
= fopen(name
, "r");
1763 fscanf(f
, "%u", &r
);
1767 if(!logical_proc_info_add_by_id(data
, dataex
, &len
, max_len
, RelationProcessorPackage
, r
, (ULONG_PTR
)1 << i
))
1770 return STATUS_NO_MEMORY
;
1774 /* Sysfs enumerates logical cores (and not physical cores), but Windows enumerates
1775 * by physical core. Upon enumerating a logical core in sysfs, we register a physical
1776 * core and all its logical cores. In order to not report physical cores multiple
1777 * times, we pass a unique physical core ID to logical_proc_info_add_by_id and let
1778 * that call figure out any duplication.
1779 * Obtain a unique physical core ID from the first element of thread_siblings_list.
1780 * This list provides logical cores sharing the same physical core. The IDs are based
1781 * on kernel cpu core numbering as opposed to a hardware core ID like provided through
1782 * 'core_id', so are suitable as a unique ID.
1784 if(relation
== RelationAll
|| relation
== RelationProcessorCore
||
1785 relation
== RelationNumaNode
|| relation
== RelationGroup
)
1787 /* Mask of logical threads sharing same physical core in kernel core numbering. */
1788 sprintf(name
, core_info
, i
, "thread_siblings");
1789 if(!sysfs_parse_bitmap(name
, &thread_mask
))
1792 /* Needed later for NumaNode and Group. */
1793 all_cpus_mask
|= thread_mask
;
1795 if(relation
== RelationAll
|| relation
== RelationProcessorCore
)
1797 sprintf(name
, core_info
, i
, "thread_siblings_list");
1798 f
= fopen(name
, "r");
1801 fscanf(f
, "%d%c", &phys_core
, &op
);
1806 if(!logical_proc_info_add_by_id(data
, dataex
, &len
, max_len
, RelationProcessorCore
, phys_core
, thread_mask
))
1809 return STATUS_NO_MEMORY
;
1814 if (relation
== RelationAll
|| relation
== RelationCache
)
1818 CACHE_DESCRIPTOR cache
;
1821 sprintf(name
, cache_info
, i
, j
, "shared_cpu_map");
1822 if(!sysfs_parse_bitmap(name
, &mask
)) continue;
1824 sprintf(name
, cache_info
, i
, j
, "level");
1825 f
= fopen(name
, "r");
1827 fscanf(f
, "%u", &r
);
1831 sprintf(name
, cache_info
, i
, j
, "ways_of_associativity");
1832 f
= fopen(name
, "r");
1834 fscanf(f
, "%u", &r
);
1836 cache
.Associativity
= r
;
1838 sprintf(name
, cache_info
, i
, j
, "coherency_line_size");
1839 f
= fopen(name
, "r");
1841 fscanf(f
, "%u", &r
);
1845 sprintf(name
, cache_info
, i
, j
, "size");
1846 f
= fopen(name
, "r");
1848 fscanf(f
, "%u%c", &r
, &op
);
1851 WARN("unknown cache size %u%c\n", r
, op
);
1852 cache
.Size
= (op
=='K' ? r
*1024 : r
);
1854 sprintf(name
, cache_info
, i
, j
, "type");
1855 f
= fopen(name
, "r");
1857 fscanf(f
, "%s", name
);
1859 if(!memcmp(name
, "Data", 5))
1860 cache
.Type
= CacheData
;
1861 else if(!memcmp(name
, "Instruction", 11))
1862 cache
.Type
= CacheInstruction
;
1864 cache
.Type
= CacheUnified
;
1866 if(!logical_proc_info_add_cache(data
, dataex
, &len
, max_len
, mask
, &cache
))
1869 return STATUS_NO_MEMORY
;
1877 num_cpus
= count_bits(all_cpus_mask
);
1879 if(relation
== RelationAll
|| relation
== RelationNumaNode
)
1881 fnuma_list
= fopen("/sys/devices/system/node/online", "r");
1884 if(!logical_proc_info_add_numa_node(data
, dataex
, &len
, max_len
, all_cpus_mask
, 0))
1885 return STATUS_NO_MEMORY
;
1889 while(!feof(fnuma_list
))
1891 if(!fscanf(fnuma_list
, "%u%c ", &beg
, &op
))
1893 if(op
== '-') fscanf(fnuma_list
, "%u%c ", &end
, &op
);
1896 for(i
=beg
; i
<=end
; i
++)
1900 sprintf(name
, numa_info
, i
);
1901 f
= fopen(name
, "r");
1905 if(!fscanf(f
, "%x%c ", &r
, &op
))
1907 mask
= (sizeof(ULONG_PTR
)>sizeof(int) ? mask
<<(8*sizeof(DWORD
)) : 0) + r
;
1911 if(!logical_proc_info_add_numa_node(data
, dataex
, &len
, max_len
, mask
, i
))
1914 return STATUS_NO_MEMORY
;
1922 if(dataex
&& (relation
== RelationAll
|| relation
== RelationGroup
))
1923 logical_proc_info_add_group(dataex
, &len
, max_len
, num_cpus
, all_cpus_mask
);
1926 *max_len
= len
* sizeof(**data
);
1930 return STATUS_SUCCESS
;
1932 #elif defined(__APPLE__)
1933 /* for 'data', max_len is the array count. for 'dataex', max_len is in bytes */
1934 static NTSTATUS
create_logical_proc_info(SYSTEM_LOGICAL_PROCESSOR_INFORMATION
**data
,
1935 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
**dataex
, DWORD
*max_len
, DWORD relation
)
1937 DWORD pkgs_no
, cores_no
, lcpu_no
, lcpu_per_core
, cores_per_package
, assoc
, len
= 0;
1938 DWORD cache_ctrs
[10] = {0};
1939 ULONG_PTR all_cpus_mask
= 0;
1940 CACHE_DESCRIPTOR cache
[10];
1941 LONGLONG cache_size
, cache_line_size
, cache_sharing
[10];
1945 if (relation
!= RelationAll
)
1946 FIXME("Relationship filtering not implemented: 0x%x\n", relation
);
1948 lcpu_no
= NtCurrentTeb()->Peb
->NumberOfProcessors
;
1950 size
= sizeof(pkgs_no
);
1951 if(sysctlbyname("hw.packages", &pkgs_no
, &size
, NULL
, 0))
1954 size
= sizeof(cores_no
);
1955 if(sysctlbyname("hw.physicalcpu", &cores_no
, &size
, NULL
, 0))
1958 TRACE("%u logical CPUs from %u physical cores across %u packages\n",
1959 lcpu_no
, cores_no
, pkgs_no
);
1961 lcpu_per_core
= lcpu_no
/ cores_no
;
1962 cores_per_package
= cores_no
/ pkgs_no
;
1964 memset(cache
, 0, sizeof(cache
));
1966 cache
[1].Type
= CacheInstruction
;
1967 cache
[1].Associativity
= 8; /* reasonable default */
1968 cache
[1].LineSize
= 0x40; /* reasonable default */
1970 cache
[2].Type
= CacheData
;
1971 cache
[2].Associativity
= 8;
1972 cache
[2].LineSize
= 0x40;
1974 cache
[3].Type
= CacheUnified
;
1975 cache
[3].Associativity
= 8;
1976 cache
[3].LineSize
= 0x40;
1978 cache
[4].Type
= CacheUnified
;
1979 cache
[4].Associativity
= 12;
1980 cache
[4].LineSize
= 0x40;
1982 size
= sizeof(cache_line_size
);
1983 if(!sysctlbyname("hw.cachelinesize", &cache_line_size
, &size
, NULL
, 0))
1986 cache
[i
].LineSize
= cache_line_size
;
1989 /* TODO: set actual associativity for all caches */
1990 size
= sizeof(assoc
);
1991 if(!sysctlbyname("machdep.cpu.cache.L2_associativity", &assoc
, &size
, NULL
, 0))
1992 cache
[3].Associativity
= assoc
;
1994 size
= sizeof(cache_size
);
1995 if(!sysctlbyname("hw.l1icachesize", &cache_size
, &size
, NULL
, 0))
1996 cache
[1].Size
= cache_size
;
1997 size
= sizeof(cache_size
);
1998 if(!sysctlbyname("hw.l1dcachesize", &cache_size
, &size
, NULL
, 0))
1999 cache
[2].Size
= cache_size
;
2000 size
= sizeof(cache_size
);
2001 if(!sysctlbyname("hw.l2cachesize", &cache_size
, &size
, NULL
, 0))
2002 cache
[3].Size
= cache_size
;
2003 size
= sizeof(cache_size
);
2004 if(!sysctlbyname("hw.l3cachesize", &cache_size
, &size
, NULL
, 0))
2005 cache
[4].Size
= cache_size
;
2007 size
= sizeof(cache_sharing
);
2008 if(sysctlbyname("hw.cacheconfig", cache_sharing
, &size
, NULL
, 0) < 0){
2009 cache_sharing
[1] = lcpu_per_core
;
2010 cache_sharing
[2] = lcpu_per_core
;
2011 cache_sharing
[3] = lcpu_per_core
;
2012 cache_sharing
[4] = lcpu_no
;
2014 /* in cache[], indexes 1 and 2 are l1 caches */
2015 cache_sharing
[4] = cache_sharing
[3];
2016 cache_sharing
[3] = cache_sharing
[2];
2017 cache_sharing
[2] = cache_sharing
[1];
2020 for(p
= 0; p
< pkgs_no
; ++p
){
2021 for(j
= 0; j
< cores_per_package
&& p
* cores_per_package
+ j
< cores_no
; ++j
){
2025 for(k
= 0; k
< lcpu_per_core
; ++k
)
2026 mask
|= (ULONG_PTR
)1 << (j
* lcpu_per_core
+ k
);
2028 all_cpus_mask
|= mask
;
2030 /* add to package */
2031 if(!logical_proc_info_add_by_id(data
, dataex
, &len
, max_len
, RelationProcessorPackage
, p
, mask
))
2032 return STATUS_NO_MEMORY
;
2035 phys_core
= p
* cores_per_package
+ j
;
2036 if(!logical_proc_info_add_by_id(data
, dataex
, &len
, max_len
, RelationProcessorCore
, phys_core
, mask
))
2037 return STATUS_NO_MEMORY
;
2039 for(i
= 1; i
< 5; ++i
){
2040 if(cache_ctrs
[i
] == 0 && cache
[i
].Size
> 0){
2042 for(k
= 0; k
< cache_sharing
[i
]; ++k
)
2043 mask
|= (ULONG_PTR
)1 << (j
* lcpu_per_core
+ k
);
2045 if(!logical_proc_info_add_cache(data
, dataex
, &len
, max_len
, mask
, &cache
[i
]))
2046 return STATUS_NO_MEMORY
;
2049 cache_ctrs
[i
] += lcpu_per_core
;
2051 if(cache_ctrs
[i
] == cache_sharing
[i
])
2057 /* OSX doesn't support NUMA, so just make one NUMA node for all CPUs */
2058 if(!logical_proc_info_add_numa_node(data
, dataex
, &len
, max_len
, all_cpus_mask
, 0))
2059 return STATUS_NO_MEMORY
;
2062 logical_proc_info_add_group(dataex
, &len
, max_len
, lcpu_no
, all_cpus_mask
);
2065 *max_len
= len
* sizeof(**data
);
2069 return STATUS_SUCCESS
;
2072 static NTSTATUS
create_logical_proc_info(SYSTEM_LOGICAL_PROCESSOR_INFORMATION
**data
,
2073 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
**dataex
, DWORD
*max_len
, DWORD relation
)
2076 return STATUS_NOT_IMPLEMENTED
;
2082 static inline void copy_smbios_string(char **buffer
, char *s
, size_t len
)
2085 memcpy(*buffer
, s
, len
+ 1);
2089 static size_t get_smbios_string(const char *path
, char *str
, size_t size
)
2094 if (!(file
= fopen(path
, "r")))
2097 len
= fread(str
, 1, size
- 1, file
);
2100 if (len
>= 1 && str
[len
- 1] == '\n')
2108 static void get_system_uuid( GUID
*uuid
)
2110 static const unsigned char hex
[] =
2112 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
2113 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
2114 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
2115 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
2116 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
2117 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
2118 0,10,11,12,13,14,15 /* 0x60 */
2122 memset( uuid
, 0xff, sizeof(*uuid
) );
2123 if ((fd
= open( "/var/lib/dbus/machine-id", O_RDONLY
)) != -1)
2125 unsigned char buf
[32], *p
= buf
;
2126 if (read( fd
, buf
, sizeof(buf
) ) == sizeof(buf
))
2128 uuid
->Data1
= hex
[p
[6]] << 28 | hex
[p
[7]] << 24 | hex
[p
[4]] << 20 | hex
[p
[5]] << 16 |
2129 hex
[p
[2]] << 12 | hex
[p
[3]] << 8 | hex
[p
[0]] << 4 | hex
[p
[1]];
2131 uuid
->Data2
= hex
[p
[10]] << 12 | hex
[p
[11]] << 8 | hex
[p
[8]] << 4 | hex
[p
[9]];
2132 uuid
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[12]] << 4 | hex
[p
[13]];
2134 uuid
->Data4
[0] = hex
[p
[16]] << 4 | hex
[p
[17]];
2135 uuid
->Data4
[1] = hex
[p
[18]] << 4 | hex
[p
[19]];
2136 uuid
->Data4
[2] = hex
[p
[20]] << 4 | hex
[p
[21]];
2137 uuid
->Data4
[3] = hex
[p
[22]] << 4 | hex
[p
[23]];
2138 uuid
->Data4
[4] = hex
[p
[24]] << 4 | hex
[p
[25]];
2139 uuid
->Data4
[5] = hex
[p
[26]] << 4 | hex
[p
[27]];
2140 uuid
->Data4
[6] = hex
[p
[28]] << 4 | hex
[p
[29]];
2141 uuid
->Data4
[7] = hex
[p
[30]] << 4 | hex
[p
[31]];
2147 static NTSTATUS
get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION
*sfti
, ULONG available_len
, ULONG
*required_len
)
2149 switch (sfti
->ProviderSignature
)
2153 char bios_vendor
[128], bios_version
[128], bios_date
[128];
2154 size_t bios_vendor_len
, bios_version_len
, bios_date_len
;
2155 char system_vendor
[128], system_product
[128], system_version
[128], system_serial
[128];
2156 size_t system_vendor_len
, system_product_len
, system_version_len
, system_serial_len
;
2157 char system_sku
[128], system_family
[128];
2158 size_t system_sku_len
, system_family_len
;
2159 char board_vendor
[128], board_product
[128], board_version
[128], board_serial
[128];
2160 size_t board_vendor_len
, board_product_len
, board_version_len
, board_serial_len
;
2161 char chassis_vendor
[128], chassis_version
[128], chassis_serial
[128], chassis_asset_tag
[128];
2162 char chassis_type
[11] = "2"; /* unknown */
2163 size_t chassis_vendor_len
, chassis_version_len
, chassis_serial_len
, chassis_asset_tag_len
;
2164 char *buffer
= (char*)sfti
->TableBuffer
;
2166 struct smbios_prologue
*prologue
;
2167 struct smbios_bios
*bios
;
2168 struct smbios_system
*system
;
2169 struct smbios_board
*board
;
2170 struct smbios_chassis
*chassis
;
2172 #define S(s) s, sizeof(s)
2173 bios_vendor_len
= get_smbios_string("/sys/class/dmi/id/bios_vendor", S(bios_vendor
));
2174 bios_version_len
= get_smbios_string("/sys/class/dmi/id/bios_version", S(bios_version
));
2175 bios_date_len
= get_smbios_string("/sys/class/dmi/id/bios_date", S(bios_date
));
2176 system_vendor_len
= get_smbios_string("/sys/class/dmi/id/sys_vendor", S(system_vendor
));
2177 system_product_len
= get_smbios_string("/sys/class/dmi/id/product_name", S(system_product
));
2178 system_version_len
= get_smbios_string("/sys/class/dmi/id/product_version", S(system_version
));
2179 system_serial_len
= get_smbios_string("/sys/class/dmi/id/product_serial", S(system_serial
));
2180 system_sku_len
= get_smbios_string("/sys/class/dmi/id/product_sku", S(system_sku
));
2181 system_family_len
= get_smbios_string("/sys/class/dmi/id/product_family", S(system_family
));
2182 board_vendor_len
= get_smbios_string("/sys/class/dmi/id/board_vendor", S(board_vendor
));
2183 board_product_len
= get_smbios_string("/sys/class/dmi/id/board_name", S(board_product
));
2184 board_version_len
= get_smbios_string("/sys/class/dmi/id/board_version", S(board_version
));
2185 board_serial_len
= get_smbios_string("/sys/class/dmi/id/board_serial", S(board_serial
));
2186 chassis_vendor_len
= get_smbios_string("/sys/class/dmi/id/chassis_vendor", S(chassis_vendor
));
2187 chassis_version_len
= get_smbios_string("/sys/class/dmi/id/chassis_version", S(chassis_version
));
2188 chassis_serial_len
= get_smbios_string("/sys/class/dmi/id/chassis_serial", S(chassis_serial
));
2189 chassis_asset_tag_len
= get_smbios_string("/sys/class/dmi/id/chassis_tag", S(chassis_asset_tag
));
2190 get_smbios_string("/sys/class/dmi/id/chassis_type", S(chassis_type
));
2193 *required_len
= sizeof(struct smbios_prologue
);
2195 *required_len
+= sizeof(struct smbios_bios
);
2196 *required_len
+= max(bios_vendor_len
+ bios_version_len
+ bios_date_len
+ 4, 2);
2198 *required_len
+= sizeof(struct smbios_system
);
2199 *required_len
+= max(system_vendor_len
+ system_product_len
+ system_version_len
+
2200 system_serial_len
+ system_sku_len
+ system_family_len
+ 7, 2);
2202 *required_len
+= sizeof(struct smbios_board
);
2203 *required_len
+= max(board_vendor_len
+ board_product_len
+ board_version_len
+ board_serial_len
+ 5, 2);
2205 *required_len
+= sizeof(struct smbios_chassis
);
2206 *required_len
+= max(chassis_vendor_len
+ chassis_version_len
+ chassis_serial_len
+
2207 chassis_asset_tag_len
+ 5, 2);
2209 sfti
->TableBufferLength
= *required_len
;
2211 *required_len
+= FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
);
2213 if (available_len
< *required_len
)
2214 return STATUS_BUFFER_TOO_SMALL
;
2216 prologue
= (struct smbios_prologue
*)buffer
;
2217 prologue
->calling_method
= 0;
2218 prologue
->major_version
= 2;
2219 prologue
->minor_version
= 4;
2220 prologue
->revision
= 0;
2221 prologue
->length
= sfti
->TableBufferLength
- sizeof(struct smbios_prologue
);
2222 buffer
+= sizeof(struct smbios_prologue
);
2225 bios
= (struct smbios_bios
*)buffer
;
2227 bios
->hdr
.length
= sizeof(struct smbios_bios
);
2228 bios
->hdr
.handle
= 0;
2229 bios
->vendor
= bios_vendor_len
? ++string_count
: 0;
2230 bios
->version
= bios_version_len
? ++string_count
: 0;
2232 bios
->date
= bios_date_len
? ++string_count
: 0;
2234 bios
->characteristics
= 0x4; /* not supported */
2235 bios
->characteristics_ext
[0] = 0;
2236 bios
->characteristics_ext
[1] = 0;
2237 bios
->system_bios_major_release
= 0xFF; /* not supported */
2238 bios
->system_bios_minor_release
= 0xFF; /* not supported */
2239 bios
->ec_firmware_major_release
= 0xFF; /* not supported */
2240 bios
->ec_firmware_minor_release
= 0xFF; /* not supported */
2241 buffer
+= sizeof(struct smbios_bios
);
2243 copy_smbios_string(&buffer
, bios_vendor
, bios_vendor_len
);
2244 copy_smbios_string(&buffer
, bios_version
, bios_version_len
);
2245 copy_smbios_string(&buffer
, bios_date
, bios_date_len
);
2246 if (!string_count
) *buffer
++ = 0;
2250 system
= (struct smbios_system
*)buffer
;
2251 system
->hdr
.type
= 1;
2252 system
->hdr
.length
= sizeof(struct smbios_system
);
2253 system
->hdr
.handle
= 0;
2254 system
->vendor
= system_vendor_len
? ++string_count
: 0;
2255 system
->product
= system_product_len
? ++string_count
: 0;
2256 system
->version
= system_version_len
? ++string_count
: 0;
2257 system
->serial
= system_serial_len
? ++string_count
: 0;
2258 get_system_uuid( (GUID
*)system
->uuid
);
2259 system
->wake_up_type
= 0x02; /* unknown */
2260 system
->sku_number
= system_sku_len
? ++string_count
: 0;
2261 system
->family
= system_family_len
? ++string_count
: 0;
2262 buffer
+= sizeof(struct smbios_system
);
2264 copy_smbios_string(&buffer
, system_vendor
, system_vendor_len
);
2265 copy_smbios_string(&buffer
, system_product
, system_product_len
);
2266 copy_smbios_string(&buffer
, system_version
, system_version_len
);
2267 copy_smbios_string(&buffer
, system_serial
, system_serial_len
);
2268 copy_smbios_string(&buffer
, system_sku
, system_sku_len
);
2269 copy_smbios_string(&buffer
, system_family
, system_family_len
);
2270 if (!string_count
) *buffer
++ = 0;
2274 board
= (struct smbios_board
*)buffer
;
2275 board
->hdr
.type
= 2;
2276 board
->hdr
.length
= sizeof(struct smbios_board
);
2277 board
->hdr
.handle
= 0;
2278 board
->vendor
= board_vendor_len
? ++string_count
: 0;
2279 board
->product
= board_product_len
? ++string_count
: 0;
2280 board
->version
= board_version_len
? ++string_count
: 0;
2281 board
->serial
= board_serial_len
? ++string_count
: 0;
2282 buffer
+= sizeof(struct smbios_board
);
2284 copy_smbios_string(&buffer
, board_vendor
, board_vendor_len
);
2285 copy_smbios_string(&buffer
, board_product
, board_product_len
);
2286 copy_smbios_string(&buffer
, board_version
, board_version_len
);
2287 copy_smbios_string(&buffer
, board_serial
, board_serial_len
);
2288 if (!string_count
) *buffer
++ = 0;
2292 chassis
= (struct smbios_chassis
*)buffer
;
2293 chassis
->hdr
.type
= 3;
2294 chassis
->hdr
.length
= sizeof(struct smbios_chassis
);
2295 chassis
->hdr
.handle
= 0;
2296 chassis
->vendor
= chassis_vendor_len
? ++string_count
: 0;
2297 chassis
->type
= atoi(chassis_type
);
2298 chassis
->version
= chassis_version_len
? ++string_count
: 0;
2299 chassis
->serial
= chassis_serial_len
? ++string_count
: 0;
2300 chassis
->asset_tag
= chassis_asset_tag_len
? ++string_count
: 0;
2301 chassis
->boot_state
= 0x02; /* unknown */
2302 chassis
->power_supply_state
= 0x02; /* unknown */
2303 chassis
->thermal_state
= 0x02; /* unknown */
2304 chassis
->security_status
= 0x02; /* unknown */
2305 buffer
+= sizeof(struct smbios_chassis
);
2307 copy_smbios_string(&buffer
, chassis_vendor
, chassis_vendor_len
);
2308 copy_smbios_string(&buffer
, chassis_version
, chassis_version_len
);
2309 copy_smbios_string(&buffer
, chassis_serial
, chassis_serial_len
);
2310 copy_smbios_string(&buffer
, chassis_asset_tag
, chassis_asset_tag_len
);
2311 if (!string_count
) *buffer
++ = 0;
2314 return STATUS_SUCCESS
;
2318 FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION provider %08x\n", sfti
->ProviderSignature
);
2319 return STATUS_NOT_IMPLEMENTED
;
2324 #elif defined(__APPLE__)
2325 static NTSTATUS
get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION
*sfti
, ULONG available_len
, ULONG
*required_len
)
2327 switch (sfti
->ProviderSignature
)
2331 io_service_t service
;
2335 struct smbios_prologue
*prologue
;
2336 BYTE major_version
= 2, minor_version
= 0;
2338 if (!(service
= IOServiceGetMatchingService(kIOMasterPortDefault
, IOServiceMatching("AppleSMBIOS"))))
2340 WARN("can't find AppleSMBIOS service\n");
2341 return STATUS_NO_MEMORY
;
2344 if (!(data
= IORegistryEntryCreateCFProperty(service
, CFSTR("SMBIOS-EPS"), kCFAllocatorDefault
, 0)))
2346 WARN("can't find SMBIOS entry point\n");
2347 IOObjectRelease(service
);
2348 return STATUS_NO_MEMORY
;
2351 len
= CFDataGetLength(data
);
2352 ptr
= CFDataGetBytePtr(data
);
2353 if (len
>= 8 && !memcmp(ptr
, "_SM_", 4))
2355 major_version
= ptr
[6];
2356 minor_version
= ptr
[7];
2360 if (!(data
= IORegistryEntryCreateCFProperty(service
, CFSTR("SMBIOS"), kCFAllocatorDefault
, 0)))
2362 WARN("can't find SMBIOS table\n");
2363 IOObjectRelease(service
);
2364 return STATUS_NO_MEMORY
;
2367 len
= CFDataGetLength(data
);
2368 ptr
= CFDataGetBytePtr(data
);
2369 sfti
->TableBufferLength
= sizeof(*prologue
) + len
;
2370 *required_len
= sfti
->TableBufferLength
+ FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
);
2371 if (available_len
< *required_len
)
2374 IOObjectRelease(service
);
2375 return STATUS_BUFFER_TOO_SMALL
;
2378 prologue
= (struct smbios_prologue
*)sfti
->TableBuffer
;
2379 prologue
->calling_method
= 0;
2380 prologue
->major_version
= major_version
;
2381 prologue
->minor_version
= minor_version
;
2382 prologue
->revision
= 0;
2383 prologue
->length
= sfti
->TableBufferLength
- sizeof(*prologue
);
2385 memcpy(sfti
->TableBuffer
+ sizeof(*prologue
), ptr
, len
);
2388 IOObjectRelease(service
);
2389 return STATUS_SUCCESS
;
2393 FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION provider %08x\n", sfti
->ProviderSignature
);
2394 return STATUS_NOT_IMPLEMENTED
;
2400 static NTSTATUS
get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION
*sfti
, ULONG available_len
, ULONG
*required_len
)
2402 FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION\n");
2403 sfti
->TableBufferLength
= 0;
2404 return STATUS_NOT_IMPLEMENTED
;
2409 static void get_performance_info( SYSTEM_PERFORMANCE_INFORMATION
*info
)
2411 unsigned long long totalram
= 0, freeram
= 0, totalswap
= 0, freeswap
= 0;
2414 memset( info
, 0, sizeof(*info
) );
2416 if ((fp
= fopen("/proc/uptime", "r")))
2418 double uptime
, idle_time
;
2420 fscanf(fp
, "%lf %lf", &uptime
, &idle_time
);
2422 info
->IdleTime
.QuadPart
= 10000000 * idle_time
;
2426 static ULONGLONG idle
;
2427 /* many programs expect IdleTime to change so fake change */
2428 info
->IdleTime
.QuadPart
= ++idle
;
2432 if ((fp
= fopen("/proc/meminfo", "r")))
2434 unsigned long long value
;
2437 while (fgets(line
, sizeof(line
), fp
))
2439 if(sscanf(line
, "MemTotal: %llu kB", &value
) == 1)
2440 totalram
+= value
* 1024;
2441 else if(sscanf(line
, "MemFree: %llu kB", &value
) == 1)
2442 freeram
+= value
* 1024;
2443 else if(sscanf(line
, "SwapTotal: %llu kB", &value
) == 1)
2444 totalswap
+= value
* 1024;
2445 else if(sscanf(line
, "SwapFree: %llu kB", &value
) == 1)
2446 freeswap
+= value
* 1024;
2447 else if (sscanf(line
, "Buffers: %llu", &value
))
2448 freeram
+= value
* 1024;
2449 else if (sscanf(line
, "Cached: %llu", &value
))
2450 freeram
+= value
* 1024;
2454 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || \
2455 defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
2469 mib
[1] = HW_MEMSIZE
;
2470 size_sys
= sizeof(val64
);
2471 if (!sysctl(mib
, 2, &val64
, &size_sys
, NULL
, 0) && size_sys
== sizeof(val64
)) totalram
= val64
;
2475 #ifdef HAVE_MACH_MACH_H
2477 host_name_port_t host
= mach_host_self();
2478 mach_msg_type_number_t count
;
2479 #ifdef HOST_VM_INFO64_COUNT
2480 vm_statistics64_data_t vm_stat
;
2482 count
= HOST_VM_INFO64_COUNT
;
2483 if (host_statistics64(host
, HOST_VM_INFO64
, (host_info64_t
)&vm_stat
, &count
) == KERN_SUCCESS
)
2484 freeram
= (vm_stat
.free_count
+ vm_stat
.inactive_count
) * (ULONGLONG
)page_size
;
2488 host_basic_info_data_t info
;
2489 count
= HOST_BASIC_INFO_COUNT
;
2490 if (host_info(host
, HOST_BASIC_INFO
, (host_info_t
)&info
, &count
) == KERN_SUCCESS
)
2491 totalram
= info
.max_mem
;
2493 mach_port_deallocate(mach_task_self(), host
);
2499 mib
[1] = HW_PHYSMEM
;
2500 size_sys
= sizeof(val
);
2501 if (!sysctl(mib
, 2, &val
, &size_sys
, NULL
, 0) && size_sys
== sizeof(val
)) totalram
= val
;
2505 mib
[1] = HW_USERMEM
;
2506 size_sys
= sizeof(val
);
2507 if (!sysctl(mib
, 2, &val
, &size_sys
, NULL
, 0) && size_sys
== sizeof(val
)) freeram
= val
;
2511 struct xsw_usage swap
;
2513 mib
[1] = VM_SWAPUSAGE
;
2514 size_sys
= sizeof(swap
);
2515 if (!sysctl(mib
, 2, &swap
, &size_sys
, NULL
, 0) && size_sys
== sizeof(swap
))
2517 totalswap
= swap
.xsu_total
;
2518 freeswap
= swap
.xsu_avail
;
2523 #elif defined( sun )
2525 struct anoninfo swapinf
;
2527 totalram
= sysconf(_SC_PHYS_PAGES
) * (ULONGLONG
)page_size
;
2528 freeram
= sysconf(_SC_AVPHYS_PAGES
) * (ULONGLONG
)page_size
;
2529 rval
= swapctl(SC_AINFO
, &swapinf
);
2532 totalswap
= swapinf
.ani_max
* (ULONGLONG
)page_size
;
2533 freeswap
= swapinf
.ani_free
* (ULONGLONG
)page_size
;
2537 info
->AvailablePages
= freeram
/ page_size
;
2538 info
->TotalCommittedPages
= (totalram
+ totalswap
- freeram
- freeswap
) / page_size
;
2539 info
->TotalCommitLimit
= (totalram
+ totalswap
) / page_size
;
2542 /***********************************************************************
2543 * RtlIsProcessorFeaturePresent [NTDLL.@]
2545 BOOLEAN WINAPI
RtlIsProcessorFeaturePresent( UINT feature
)
2547 return feature
< PROCESSOR_FEATURE_MAX
&& user_shared_data
->ProcessorFeatures
[feature
];
2550 /******************************************************************************
2551 * NtQuerySystemInformation [NTDLL.@]
2552 * ZwQuerySystemInformation [NTDLL.@]
2555 * SystemInformationClass Index to a certain information structure
2556 * SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT
2557 * SystemCacheInformation SYSTEM_CACHE_INFORMATION
2558 * SystemConfigurationInformation CONFIGURATION_INFORMATION
2559 * observed (class/len):
2565 * SystemInformation caller supplies storage for the information structure
2566 * Length size of the structure
2567 * ResultLength Data written
2569 NTSTATUS WINAPI
NtQuerySystemInformation(
2570 IN SYSTEM_INFORMATION_CLASS SystemInformationClass
,
2571 OUT PVOID SystemInformation
,
2573 OUT PULONG ResultLength
)
2575 NTSTATUS ret
= STATUS_SUCCESS
;
2578 TRACE("(0x%08x,%p,0x%08x,%p)\n",
2579 SystemInformationClass
,SystemInformation
,Length
,ResultLength
);
2581 switch (SystemInformationClass
)
2583 case SystemBasicInformation
:
2585 SYSTEM_BASIC_INFORMATION sbi
;
2587 virtual_get_system_info( &sbi
);
2592 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
2593 else memcpy( SystemInformation
, &sbi
, len
);
2595 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
2598 case SystemCpuInformation
:
2599 if (Length
>= (len
= sizeof(cpu_info
)))
2601 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
2602 else memcpy(SystemInformation
, &cpu_info
, len
);
2604 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
2606 case SystemPerformanceInformation
:
2608 SYSTEM_PERFORMANCE_INFORMATION spi
;
2609 static BOOL fixme_written
= FALSE
;
2611 get_performance_info( &spi
);
2616 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
2617 else memcpy( SystemInformation
, &spi
, len
);
2619 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
2620 if(!fixme_written
) {
2621 FIXME("info_class SYSTEM_PERFORMANCE_INFORMATION\n");
2622 fixme_written
= TRUE
;
2626 case SystemTimeOfDayInformation
:
2628 SYSTEM_TIMEOFDAY_INFORMATION sti
;
2630 memset(&sti
, 0 , sizeof(sti
));
2632 /* liKeSystemTime, liExpTimeZoneBias, uCurrentTimeZoneId */
2633 sti
.liKeBootTime
.QuadPart
= server_start_time
;
2635 if (Length
<= sizeof(sti
))
2638 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
2639 else memcpy( SystemInformation
, &sti
, Length
);
2641 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
2644 case SystemProcessInformation
:
2646 SYSTEM_PROCESS_INFORMATION
* spi
= SystemInformation
;
2647 SYSTEM_PROCESS_INFORMATION
* last
= NULL
;
2649 WCHAR procname
[1024];
2652 DWORD procstructlen
= 0;
2654 SERVER_START_REQ( create_snapshot
)
2656 req
->flags
= SNAP_PROCESS
| SNAP_THREAD
;
2657 req
->attributes
= 0;
2658 if (!(ret
= wine_server_call( req
)))
2659 hSnap
= wine_server_ptr_handle( reply
->handle
);
2663 while (ret
== STATUS_SUCCESS
)
2665 SERVER_START_REQ( next_process
)
2667 req
->handle
= wine_server_obj_handle( hSnap
);
2668 req
->reset
= (len
== 0);
2669 wine_server_set_reply( req
, procname
, sizeof(procname
)-sizeof(WCHAR
) );
2670 if (!(ret
= wine_server_call( req
)))
2672 /* Make sure procname is 0 terminated */
2673 procname
[wine_server_reply_size(reply
) / sizeof(WCHAR
)] = 0;
2675 /* Get only the executable name, not the path */
2676 if ((exename
= strrchrW(procname
, '\\')) != NULL
) exename
++;
2677 else exename
= procname
;
2679 wlen
= (strlenW(exename
) + 1) * sizeof(WCHAR
);
2681 procstructlen
= sizeof(*spi
) + wlen
+ ((reply
->threads
- 1) * sizeof(SYSTEM_THREAD_INFORMATION
));
2683 if (Length
>= len
+ procstructlen
)
2685 /* ftCreationTime, ftUserTime, ftKernelTime;
2686 * vmCounters, ioCounters
2689 memset(spi
, 0, sizeof(*spi
));
2691 spi
->NextEntryOffset
= procstructlen
- wlen
;
2692 spi
->dwThreadCount
= reply
->threads
;
2694 /* spi->pszProcessName will be set later on */
2696 spi
->dwBasePriority
= reply
->priority
;
2697 spi
->UniqueProcessId
= UlongToHandle(reply
->pid
);
2698 spi
->ParentProcessId
= UlongToHandle(reply
->ppid
);
2699 spi
->HandleCount
= reply
->handles
;
2701 /* spi->ti will be set later on */
2704 len
+= procstructlen
;
2709 if (ret
!= STATUS_SUCCESS
)
2711 if (ret
== STATUS_NO_MORE_FILES
) ret
= STATUS_SUCCESS
;
2719 /* set thread info */
2721 while (ret
== STATUS_SUCCESS
)
2723 SERVER_START_REQ( next_thread
)
2725 req
->handle
= wine_server_obj_handle( hSnap
);
2726 req
->reset
= (j
== 0);
2727 if (!(ret
= wine_server_call( req
)))
2730 if (UlongToHandle(reply
->pid
) == spi
->UniqueProcessId
)
2732 /* ftKernelTime, ftUserTime, ftCreateTime;
2733 * dwTickCount, dwStartAddress
2736 memset(&spi
->ti
[i
], 0, sizeof(spi
->ti
));
2738 spi
->ti
[i
].CreateTime
.QuadPart
= 0xdeadbeef;
2739 spi
->ti
[i
].ClientId
.UniqueProcess
= UlongToHandle(reply
->pid
);
2740 spi
->ti
[i
].ClientId
.UniqueThread
= UlongToHandle(reply
->tid
);
2741 spi
->ti
[i
].dwCurrentPriority
= reply
->base_pri
+ reply
->delta_pri
;
2742 spi
->ti
[i
].dwBasePriority
= reply
->base_pri
;
2749 if (ret
== STATUS_NO_MORE_FILES
) ret
= STATUS_SUCCESS
;
2751 /* now append process name */
2752 spi
->ProcessName
.Buffer
= (WCHAR
*)((char*)spi
+ spi
->NextEntryOffset
);
2753 spi
->ProcessName
.Length
= wlen
- sizeof(WCHAR
);
2754 spi
->ProcessName
.MaximumLength
= wlen
;
2755 memcpy( spi
->ProcessName
.Buffer
, exename
, wlen
);
2756 spi
->NextEntryOffset
+= wlen
;
2759 spi
= (SYSTEM_PROCESS_INFORMATION
*)((char*)spi
+ spi
->NextEntryOffset
);
2762 if (ret
== STATUS_SUCCESS
&& last
) last
->NextEntryOffset
= 0;
2763 if (len
> Length
) ret
= STATUS_INFO_LENGTH_MISMATCH
;
2764 if (hSnap
) NtClose(hSnap
);
2767 case SystemProcessorPerformanceInformation
:
2769 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
*sppi
= NULL
;
2770 unsigned int cpus
= 0;
2771 int out_cpus
= Length
/ sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
);
2776 ret
= STATUS_INFO_LENGTH_MISMATCH
;
2782 processor_cpu_load_info_data_t
*pinfo
;
2783 mach_msg_type_number_t info_count
;
2785 if (host_processor_info (mach_host_self (),
2786 PROCESSOR_CPU_LOAD_INFO
,
2788 (processor_info_array_t
*)&pinfo
,
2792 cpus
= min(cpus
,out_cpus
);
2793 len
= sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) * cpus
;
2794 sppi
= RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
2795 for (i
= 0; i
< cpus
; i
++)
2797 sppi
[i
].IdleTime
.QuadPart
= pinfo
[i
].cpu_ticks
[CPU_STATE_IDLE
];
2798 sppi
[i
].KernelTime
.QuadPart
= pinfo
[i
].cpu_ticks
[CPU_STATE_SYSTEM
];
2799 sppi
[i
].UserTime
.QuadPart
= pinfo
[i
].cpu_ticks
[CPU_STATE_USER
];
2801 vm_deallocate (mach_task_self (), (vm_address_t
) pinfo
, info_count
* sizeof(natural_t
));
2806 FILE *cpuinfo
= fopen("/proc/stat", "r");
2809 unsigned long clk_tck
= sysconf(_SC_CLK_TCK
);
2810 unsigned long usr
,nice
,sys
,idle
,remainder
[8];
2815 /* first line is combined usage */
2816 while (fgets(line
,255,cpuinfo
))
2818 count
= sscanf(line
, "%s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
2819 name
, &usr
, &nice
, &sys
, &idle
,
2820 &remainder
[0], &remainder
[1], &remainder
[2], &remainder
[3],
2821 &remainder
[4], &remainder
[5], &remainder
[6], &remainder
[7]);
2823 if (count
< 5 || strncmp( name
, "cpu", 3 )) break;
2824 for (i
= 0; i
+ 5 < count
; ++i
) sys
+= remainder
[i
];
2827 cpus
= atoi( name
+ 3 ) + 1;
2828 if (cpus
> out_cpus
) break;
2829 len
= sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) * cpus
;
2831 sppi
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sppi
, len
);
2833 sppi
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
2835 sppi
[cpus
-1].IdleTime
.QuadPart
= (ULONGLONG
)idle
* 10000000 / clk_tck
;
2836 sppi
[cpus
-1].KernelTime
.QuadPart
= (ULONGLONG
)sys
* 10000000 / clk_tck
;
2837 sppi
[cpus
-1].UserTime
.QuadPart
= (ULONGLONG
)usr
* 10000000 / clk_tck
;
2848 cpus
= min(NtCurrentTeb()->Peb
->NumberOfProcessors
, out_cpus
);
2849 len
= sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) * cpus
;
2850 sppi
= RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
2851 FIXME("stub info_class SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION\n");
2852 /* many programs expect these values to change so fake change */
2853 for (n
= 0; n
< cpus
; n
++)
2855 sppi
[n
].KernelTime
.QuadPart
= 1 * i
;
2856 sppi
[n
].UserTime
.QuadPart
= 2 * i
;
2857 sppi
[n
].IdleTime
.QuadPart
= 3 * i
;
2864 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
2865 else memcpy( SystemInformation
, sppi
, len
);
2867 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
2869 RtlFreeHeap(GetProcessHeap(),0,sppi
);
2872 case SystemModuleInformation
:
2873 /* FIXME: should be system-wide */
2874 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
2875 else ret
= LdrQueryProcessModuleInformation( SystemInformation
, Length
, &len
);
2877 case SystemHandleInformation
:
2879 struct handle_info
*info
;
2880 DWORD i
, num_handles
;
2882 if (Length
< sizeof(SYSTEM_HANDLE_INFORMATION
))
2884 ret
= STATUS_INFO_LENGTH_MISMATCH
;
2888 if (!SystemInformation
)
2890 ret
= STATUS_ACCESS_VIOLATION
;
2894 num_handles
= (Length
- FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION
, Handle
)) / sizeof(SYSTEM_HANDLE_ENTRY
);
2895 if (!(info
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*info
) * num_handles
)))
2896 return STATUS_NO_MEMORY
;
2898 SERVER_START_REQ( get_system_handles
)
2900 wine_server_set_reply( req
, info
, sizeof(*info
) * num_handles
);
2901 if (!(ret
= wine_server_call( req
)))
2903 SYSTEM_HANDLE_INFORMATION
*shi
= SystemInformation
;
2904 shi
->Count
= wine_server_reply_size( req
) / sizeof(*info
);
2905 len
= FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION
, Handle
[shi
->Count
] );
2906 for (i
= 0; i
< shi
->Count
; i
++)
2908 memset( &shi
->Handle
[i
], 0, sizeof(shi
->Handle
[i
]) );
2909 shi
->Handle
[i
].OwnerPid
= info
[i
].owner
;
2910 shi
->Handle
[i
].HandleValue
= info
[i
].handle
;
2911 shi
->Handle
[i
].AccessMask
= info
[i
].access
;
2912 /* FIXME: Fill out ObjectType, HandleFlags, ObjectPointer */
2915 else if (ret
== STATUS_BUFFER_TOO_SMALL
)
2917 len
= FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION
, Handle
[reply
->count
] );
2918 ret
= STATUS_INFO_LENGTH_MISMATCH
;
2923 RtlFreeHeap( GetProcessHeap(), 0, info
);
2926 case SystemCacheInformation
:
2928 SYSTEM_CACHE_INFORMATION sci
;
2930 memset(&sci
, 0, sizeof(sci
)); /* FIXME */
2935 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
2936 else memcpy( SystemInformation
, &sci
, len
);
2938 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
2939 FIXME("info_class SYSTEM_CACHE_INFORMATION\n");
2942 case SystemInterruptInformation
:
2944 SYSTEM_INTERRUPT_INFORMATION sii
;
2946 memset(&sii
, 0, sizeof(sii
));
2951 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
2952 else memcpy( SystemInformation
, &sii
, len
);
2954 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
2955 FIXME("info_class SYSTEM_INTERRUPT_INFORMATION\n");
2958 case SystemKernelDebuggerInformation
:
2960 SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi
;
2962 skdi
.DebuggerEnabled
= FALSE
;
2963 skdi
.DebuggerNotPresent
= TRUE
;
2968 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
2969 else memcpy( SystemInformation
, &skdi
, len
);
2971 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
2974 case SystemRegistryQuotaInformation
:
2976 /* Something to do with the size of the registry *
2977 * Since we don't have a size limitation, fake it *
2978 * This is almost certainly wrong. *
2979 * This sets each of the three words in the struct to 32 MB, *
2980 * which is enough to make the IE 5 installer happy. */
2981 SYSTEM_REGISTRY_QUOTA_INFORMATION srqi
;
2983 srqi
.RegistryQuotaAllowed
= 0x2000000;
2984 srqi
.RegistryQuotaUsed
= 0x200000;
2985 srqi
.Reserved1
= (void*)0x200000;
2990 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
2993 FIXME("SystemRegistryQuotaInformation: faking max registry size of 32 MB\n");
2994 memcpy( SystemInformation
, &srqi
, len
);
2997 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
3000 case SystemLogicalProcessorInformation
:
3002 SYSTEM_LOGICAL_PROCESSOR_INFORMATION
*buf
;
3004 /* Each logical processor may use up to 7 entries in returned table:
3005 * core, numa node, package, L1i, L1d, L2, L3 */
3006 len
= 7 * NtCurrentTeb()->Peb
->NumberOfProcessors
;
3007 buf
= RtlAllocateHeap(GetProcessHeap(), 0, len
* sizeof(*buf
));
3010 ret
= STATUS_NO_MEMORY
;
3014 ret
= create_logical_proc_info(&buf
, NULL
, &len
, RelationAll
);
3015 if( ret
!= STATUS_SUCCESS
)
3017 RtlFreeHeap(GetProcessHeap(), 0, buf
);
3023 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
3024 else memcpy( SystemInformation
, buf
, len
);
3026 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
3027 RtlFreeHeap(GetProcessHeap(), 0, buf
);
3030 case SystemRecommendedSharedDataAlignment
:
3032 len
= sizeof(DWORD
);
3035 if (!SystemInformation
) ret
= STATUS_ACCESS_VIOLATION
;
3036 else *((DWORD
*)SystemInformation
) = 64;
3038 else ret
= STATUS_INFO_LENGTH_MISMATCH
;
3041 case SystemFirmwareTableInformation
:
3043 SYSTEM_FIRMWARE_TABLE_INFORMATION
*sfti
= (SYSTEM_FIRMWARE_TABLE_INFORMATION
*)SystemInformation
;
3044 len
= FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION
, TableBuffer
);
3047 ret
= STATUS_INFO_LENGTH_MISMATCH
;
3051 switch (sfti
->Action
)
3053 case SystemFirmwareTable_Get
:
3054 ret
= get_firmware_info(sfti
, Length
, &len
);
3058 ret
= STATUS_NOT_IMPLEMENTED
;
3059 FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION action %d\n", sfti
->Action
);
3064 FIXME("(0x%08x,%p,0x%08x,%p) stub\n",
3065 SystemInformationClass
,SystemInformation
,Length
,ResultLength
);
3067 /* Several Information Classes are not implemented on Windows and return 2 different values
3068 * STATUS_NOT_IMPLEMENTED or STATUS_INVALID_INFO_CLASS
3069 * in 95% of the cases it's STATUS_INVALID_INFO_CLASS, so use this as the default
3071 ret
= STATUS_INVALID_INFO_CLASS
;
3074 if (ResultLength
) *ResultLength
= len
;
3079 /******************************************************************************
3080 * NtQuerySystemInformationEx [NTDLL.@]
3081 * ZwQuerySystemInformationEx [NTDLL.@]
3083 NTSTATUS WINAPI
NtQuerySystemInformationEx(SYSTEM_INFORMATION_CLASS SystemInformationClass
,
3084 void *Query
, ULONG QueryLength
, void *SystemInformation
, ULONG Length
, ULONG
*ResultLength
)
3087 NTSTATUS ret
= STATUS_NOT_IMPLEMENTED
;
3089 TRACE("(0x%08x,%p,%u,%p,%u,%p) stub\n", SystemInformationClass
, Query
, QueryLength
, SystemInformation
,
3090 Length
, ResultLength
);
3092 switch (SystemInformationClass
) {
3093 case SystemLogicalProcessorInformationEx
:
3095 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
*buf
;
3097 if (!Query
|| QueryLength
< sizeof(DWORD
))
3099 ret
= STATUS_INVALID_PARAMETER
;
3103 len
= 3 * sizeof(*buf
);
3104 buf
= RtlAllocateHeap(GetProcessHeap(), 0, len
);
3107 ret
= STATUS_NO_MEMORY
;
3111 ret
= create_logical_proc_info(NULL
, &buf
, &len
, *(DWORD
*)Query
);
3112 if (ret
!= STATUS_SUCCESS
)
3114 RtlFreeHeap(GetProcessHeap(), 0, buf
);
3120 if (!SystemInformation
)
3121 ret
= STATUS_ACCESS_VIOLATION
;
3123 memcpy(SystemInformation
, buf
, len
);
3126 ret
= STATUS_INFO_LENGTH_MISMATCH
;
3128 RtlFreeHeap(GetProcessHeap(), 0, buf
);
3133 FIXME("(0x%08x,%p,%u,%p,%u,%p) stub\n", SystemInformationClass
, Query
, QueryLength
, SystemInformation
,
3134 Length
, ResultLength
);
3139 *ResultLength
= len
;
3144 /******************************************************************************
3145 * NtSetSystemInformation [NTDLL.@]
3146 * ZwSetSystemInformation [NTDLL.@]
3148 NTSTATUS WINAPI
NtSetSystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass
, PVOID SystemInformation
, ULONG Length
)
3150 FIXME("(0x%08x,%p,0x%08x) stub\n",SystemInformationClass
,SystemInformation
,Length
);
3151 return STATUS_SUCCESS
;
3154 /******************************************************************************
3155 * NtCreatePagingFile [NTDLL.@]
3156 * ZwCreatePagingFile [NTDLL.@]
3158 NTSTATUS WINAPI
NtCreatePagingFile(
3159 PUNICODE_STRING PageFileName
,
3160 PLARGE_INTEGER MinimumSize
,
3161 PLARGE_INTEGER MaximumSize
,
3162 PLARGE_INTEGER ActualSize
)
3164 FIXME("(%p %p %p %p) stub\n", PageFileName
, MinimumSize
, MaximumSize
, ActualSize
);
3165 return STATUS_SUCCESS
;
3168 /******************************************************************************
3169 * NtDisplayString [NTDLL.@]
3171 * writes a string to the nt-textmode screen eg. during startup
3173 NTSTATUS WINAPI
NtDisplayString ( PUNICODE_STRING string
)
3178 if (!(ret
= RtlUnicodeStringToAnsiString( &stringA
, string
, TRUE
)))
3180 MESSAGE( "%.*s", stringA
.Length
, stringA
.Buffer
);
3181 RtlFreeAnsiString( &stringA
);
3186 /******************************************************************************
3187 * NtInitiatePowerAction [NTDLL.@]
3190 NTSTATUS WINAPI
NtInitiatePowerAction(
3191 IN POWER_ACTION SystemAction
,
3192 IN SYSTEM_POWER_STATE MinSystemState
,
3194 IN BOOLEAN Asynchronous
)
3196 FIXME("(%d,%d,0x%08x,%d),stub\n",
3197 SystemAction
,MinSystemState
,Flags
,Asynchronous
);
3198 return STATUS_NOT_IMPLEMENTED
;
3201 /******************************************************************************
3202 * NtSetThreadExecutionState [NTDLL.@]
3205 NTSTATUS WINAPI
NtSetThreadExecutionState( EXECUTION_STATE new_state
, EXECUTION_STATE
*old_state
)
3207 static EXECUTION_STATE current
=
3208 ES_SYSTEM_REQUIRED
| ES_DISPLAY_REQUIRED
| ES_USER_PRESENT
;
3209 *old_state
= current
;
3211 WARN( "(0x%x, %p): stub, harmless.\n", new_state
, old_state
);
3213 if (!(current
& ES_CONTINUOUS
) || (new_state
& ES_CONTINUOUS
))
3214 current
= new_state
;
3215 return STATUS_SUCCESS
;
3218 /******************************************************************************
3219 * NtCreatePowerRequest [NTDLL.@]
3222 NTSTATUS WINAPI
NtCreatePowerRequest( HANDLE
*handle
, COUNTED_REASON_CONTEXT
*context
)
3224 FIXME( "(%p, %p): stub\n", handle
, context
);
3226 return STATUS_NOT_IMPLEMENTED
;
3229 /******************************************************************************
3230 * NtSetPowerRequest [NTDLL.@]
3233 NTSTATUS WINAPI
NtSetPowerRequest( HANDLE handle
, POWER_REQUEST_TYPE type
)
3235 FIXME( "(%p, %u): stub\n", handle
, type
);
3237 return STATUS_NOT_IMPLEMENTED
;
3240 /******************************************************************************
3241 * NtClearPowerRequest [NTDLL.@]
3244 NTSTATUS WINAPI
NtClearPowerRequest( HANDLE handle
, POWER_REQUEST_TYPE type
)
3246 FIXME( "(%p, %u): stub\n", handle
, type
);
3248 return STATUS_NOT_IMPLEMENTED
;
3252 /* Fallback using /proc/cpuinfo for Linux systems without cpufreq. For
3253 * most distributions on recent enough hardware, this is only likely to
3254 * happen while running in virtualized environments such as QEMU. */
3255 static ULONG
mhz_from_cpuinfo(void)
3260 FILE* f
= fopen("/proc/cpuinfo", "r");
3262 while (fgets(line
, sizeof(line
), f
) != NULL
) {
3263 if (!(value
= strchr(line
,':')))
3266 while ((s
>= line
) && isspace(*s
)) s
--;
3269 if (!_stricmp(line
, "cpu MHz")) {
3270 sscanf(value
, " %lf", &cmz
);
3282 static const char * get_sys_str(const char *path
)
3285 FILE *f
= fopen(path
, "r");
3286 const char *ret
= NULL
;
3289 if (fgets(s
, sizeof(s
), f
))
3296 static int get_sys_int(const char *path
, int def
)
3298 const char *s
= get_sys_str(path
);
3299 return s
? atoi(s
) : def
;
3302 static NTSTATUS
fill_battery_state(SYSTEM_BATTERY_STATE
*bs
)
3307 LONG64 voltage
; /* microvolts */
3309 bs
->AcOnLine
= get_sys_int("/sys/class/power_supply/AC/online", 1);
3313 sprintf(path
, "/sys/class/power_supply/BAT%u/status", i
);
3314 s
= get_sys_str(path
);
3316 bs
->Charging
|= (strcmp(s
, "Charging\n") == 0);
3317 bs
->Discharging
|= (strcmp(s
, "Discharging\n") == 0);
3318 bs
->BatteryPresent
= TRUE
;
3322 if (bs
->BatteryPresent
)
3324 voltage
= get_sys_int("/sys/class/power_supply/BAT0/voltage_now", 0);
3325 bs
->MaxCapacity
= get_sys_int("/sys/class/power_supply/BAT0/charge_full", 0) * voltage
/ 1e9
;
3326 bs
->RemainingCapacity
= get_sys_int("/sys/class/power_supply/BAT0/charge_now", 0) * voltage
/ 1e9
;
3327 bs
->Rate
= -get_sys_int("/sys/class/power_supply/BAT0/current_now", 0) * voltage
/ 1e9
;
3328 if (!bs
->Charging
&& (LONG
)bs
->Rate
< 0)
3329 bs
->EstimatedTime
= 3600 * bs
->RemainingCapacity
/ -(LONG
)bs
->Rate
;
3331 bs
->EstimatedTime
= ~0u;
3334 return STATUS_SUCCESS
;
3337 #elif defined(HAVE_IOKIT_IOKITLIB_H)
3339 static NTSTATUS
fill_battery_state(SYSTEM_BATTERY_STATE
*bs
)
3341 CFArrayRef batteries
;
3342 CFDictionaryRef battery
;
3344 uint32_t value
, voltage
;
3345 CFTimeInterval remain
;
3347 if (IOPMCopyBatteryInfo( kIOMasterPortDefault
, &batteries
) != kIOReturnSuccess
)
3348 return STATUS_ACCESS_DENIED
;
3350 if (CFArrayGetCount( batteries
) == 0)
3352 /* Just assume we're on AC with no battery. */
3353 bs
->AcOnLine
= TRUE
;
3354 return STATUS_SUCCESS
;
3356 /* Just use the first battery. */
3357 battery
= CFArrayGetValueAtIndex( batteries
, 0 );
3359 prop
= CFDictionaryGetValue( battery
, CFSTR(kIOBatteryFlagsKey
) );
3360 CFNumberGetValue( prop
, kCFNumberSInt32Type
, &value
);
3362 if (value
& kIOBatteryInstalled
)
3363 bs
->BatteryPresent
= TRUE
;
3365 /* Since we are executing code, we must have AC power. */
3366 bs
->AcOnLine
= TRUE
;
3367 if (value
& kIOBatteryChargerConnect
)
3369 bs
->AcOnLine
= TRUE
;
3370 if (value
& kIOBatteryCharge
)
3371 bs
->Charging
= TRUE
;
3374 bs
->Discharging
= TRUE
;
3376 /* We'll need the voltage to be able to interpret the other values. */
3377 prop
= CFDictionaryGetValue( battery
, CFSTR(kIOBatteryVoltageKey
) );
3378 CFNumberGetValue( prop
, kCFNumberSInt32Type
, &voltage
);
3380 prop
= CFDictionaryGetValue( battery
, CFSTR(kIOBatteryCapacityKey
) );
3381 CFNumberGetValue( prop
, kCFNumberSInt32Type
, &value
);
3382 bs
->MaxCapacity
= value
* voltage
;
3383 /* Apple uses "estimated time < 10:00" and "22%" for these, but we'll follow
3384 * Windows for now (5% and 33%). */
3385 bs
->DefaultAlert1
= bs
->MaxCapacity
/ 20;
3386 bs
->DefaultAlert2
= bs
->MaxCapacity
/ 3;
3388 prop
= CFDictionaryGetValue( battery
, CFSTR(kIOBatteryCurrentChargeKey
) );
3389 CFNumberGetValue( prop
, kCFNumberSInt32Type
, &value
);
3390 bs
->RemainingCapacity
= value
* voltage
;
3392 prop
= CFDictionaryGetValue( battery
, CFSTR(kIOBatteryAmperageKey
) );
3393 CFNumberGetValue( prop
, kCFNumberSInt32Type
, &value
);
3394 bs
->Rate
= value
* voltage
;
3396 remain
= IOPSGetTimeRemainingEstimate();
3397 if (remain
!= kIOPSTimeRemainingUnknown
&& remain
!= kIOPSTimeRemainingUnlimited
)
3398 bs
->EstimatedTime
= (ULONG
)remain
;
3400 CFRelease( batteries
);
3401 return STATUS_SUCCESS
;
3406 static NTSTATUS
fill_battery_state(SYSTEM_BATTERY_STATE
*bs
)
3408 FIXME("SystemBatteryState not implemented on this platform\n");
3409 return STATUS_NOT_IMPLEMENTED
;
3414 /******************************************************************************
3415 * NtPowerInformation [NTDLL.@]
3418 NTSTATUS WINAPI
NtPowerInformation(
3419 IN POWER_INFORMATION_LEVEL InformationLevel
,
3420 IN PVOID lpInputBuffer
,
3421 IN ULONG nInputBufferSize
,
3422 IN PVOID lpOutputBuffer
,
3423 IN ULONG nOutputBufferSize
)
3425 TRACE("(%d,%p,%d,%p,%d)\n",
3426 InformationLevel
,lpInputBuffer
,nInputBufferSize
,lpOutputBuffer
,nOutputBufferSize
);
3427 switch(InformationLevel
) {
3428 case SystemPowerCapabilities
: {
3429 PSYSTEM_POWER_CAPABILITIES PowerCaps
= lpOutputBuffer
;
3430 FIXME("semi-stub: SystemPowerCapabilities\n");
3431 if (nOutputBufferSize
< sizeof(SYSTEM_POWER_CAPABILITIES
))
3432 return STATUS_BUFFER_TOO_SMALL
;
3433 /* FIXME: These values are based off a native XP desktop, should probably use APM/ACPI to get the 'real' values */
3434 PowerCaps
->PowerButtonPresent
= TRUE
;
3435 PowerCaps
->SleepButtonPresent
= FALSE
;
3436 PowerCaps
->LidPresent
= FALSE
;
3437 PowerCaps
->SystemS1
= TRUE
;
3438 PowerCaps
->SystemS2
= FALSE
;
3439 PowerCaps
->SystemS3
= FALSE
;
3440 PowerCaps
->SystemS4
= TRUE
;
3441 PowerCaps
->SystemS5
= TRUE
;
3442 PowerCaps
->HiberFilePresent
= TRUE
;
3443 PowerCaps
->FullWake
= TRUE
;
3444 PowerCaps
->VideoDimPresent
= FALSE
;
3445 PowerCaps
->ApmPresent
= FALSE
;
3446 PowerCaps
->UpsPresent
= FALSE
;
3447 PowerCaps
->ThermalControl
= FALSE
;
3448 PowerCaps
->ProcessorThrottle
= FALSE
;
3449 PowerCaps
->ProcessorMinThrottle
= 100;
3450 PowerCaps
->ProcessorMaxThrottle
= 100;
3451 PowerCaps
->DiskSpinDown
= TRUE
;
3452 PowerCaps
->SystemBatteriesPresent
= FALSE
;
3453 PowerCaps
->BatteriesAreShortTerm
= FALSE
;
3454 PowerCaps
->BatteryScale
[0].Granularity
= 0;
3455 PowerCaps
->BatteryScale
[0].Capacity
= 0;
3456 PowerCaps
->BatteryScale
[1].Granularity
= 0;
3457 PowerCaps
->BatteryScale
[1].Capacity
= 0;
3458 PowerCaps
->BatteryScale
[2].Granularity
= 0;
3459 PowerCaps
->BatteryScale
[2].Capacity
= 0;
3460 PowerCaps
->AcOnLineWake
= PowerSystemUnspecified
;
3461 PowerCaps
->SoftLidWake
= PowerSystemUnspecified
;
3462 PowerCaps
->RtcWake
= PowerSystemSleeping1
;
3463 PowerCaps
->MinDeviceWakeState
= PowerSystemUnspecified
;
3464 PowerCaps
->DefaultLowLatencyWake
= PowerSystemUnspecified
;
3465 return STATUS_SUCCESS
;
3467 case SystemBatteryState
: {
3468 if (nOutputBufferSize
< sizeof(SYSTEM_BATTERY_STATE
))
3469 return STATUS_BUFFER_TOO_SMALL
;
3470 memset(lpOutputBuffer
, 0, sizeof(SYSTEM_BATTERY_STATE
));
3471 return fill_battery_state(lpOutputBuffer
);
3473 case SystemExecutionState
: {
3474 PULONG ExecutionState
= lpOutputBuffer
;
3475 WARN("semi-stub: SystemExecutionState\n"); /* Needed for .NET Framework, but using a FIXME is really noisy. */
3476 if (lpInputBuffer
!= NULL
)
3477 return STATUS_INVALID_PARAMETER
;
3478 /* FIXME: The actual state should be the value set by SetThreadExecutionState which is not currently implemented. */
3479 *ExecutionState
= ES_USER_PRESENT
;
3480 return STATUS_SUCCESS
;
3482 case ProcessorInformation
: {
3483 const int cannedMHz
= 1000; /* We fake a 1GHz processor if we can't conjure up real values */
3484 PROCESSOR_POWER_INFORMATION
* cpu_power
= lpOutputBuffer
;
3487 if ((lpOutputBuffer
== NULL
) || (nOutputBufferSize
== 0))
3488 return STATUS_INVALID_PARAMETER
;
3489 out_cpus
= NtCurrentTeb()->Peb
->NumberOfProcessors
;
3490 if ((nOutputBufferSize
/ sizeof(PROCESSOR_POWER_INFORMATION
)) < out_cpus
)
3491 return STATUS_BUFFER_TOO_SMALL
;
3497 for(i
= 0; i
< out_cpus
; i
++) {
3498 sprintf(filename
, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i
);
3499 f
= fopen(filename
, "r");
3500 if (f
&& (fscanf(f
, "%d", &cpu_power
[i
].CurrentMhz
) == 1)) {
3501 cpu_power
[i
].CurrentMhz
/= 1000;
3506 cpu_power
[0].CurrentMhz
= mhz_from_cpuinfo();
3507 if(cpu_power
[0].CurrentMhz
== 0)
3508 cpu_power
[0].CurrentMhz
= cannedMHz
;
3511 cpu_power
[i
].CurrentMhz
= cpu_power
[0].CurrentMhz
;
3515 sprintf(filename
, "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", i
);
3516 f
= fopen(filename
, "r");
3517 if (f
&& (fscanf(f
, "%d", &cpu_power
[i
].MaxMhz
) == 1)) {
3518 cpu_power
[i
].MaxMhz
/= 1000;
3522 cpu_power
[i
].MaxMhz
= cpu_power
[i
].CurrentMhz
;
3526 sprintf(filename
, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", i
);
3527 f
= fopen(filename
, "r");
3528 if(f
&& (fscanf(f
, "%d", &cpu_power
[i
].MhzLimit
) == 1)) {
3529 cpu_power
[i
].MhzLimit
/= 1000;
3534 cpu_power
[i
].MhzLimit
= cpu_power
[i
].MaxMhz
;
3538 cpu_power
[i
].Number
= i
;
3539 cpu_power
[i
].MaxIdleState
= 0; /* FIXME */
3540 cpu_power
[i
].CurrentIdleState
= 0; /* FIXME */
3543 #elif defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__DragonFly__)
3546 size_t valSize
= sizeof(num
);
3547 if (sysctlbyname("hw.clockrate", &num
, &valSize
, NULL
, 0))
3549 for(i
= 0; i
< out_cpus
; i
++) {
3550 cpu_power
[i
].CurrentMhz
= num
;
3551 cpu_power
[i
].MaxMhz
= num
;
3552 cpu_power
[i
].MhzLimit
= num
;
3553 cpu_power
[i
].Number
= i
;
3554 cpu_power
[i
].MaxIdleState
= 0; /* FIXME */
3555 cpu_power
[i
].CurrentIdleState
= 0; /* FIXME */
3558 #elif defined (__APPLE__)
3561 unsigned long long currentMhz
;
3562 unsigned long long maxMhz
;
3564 valSize
= sizeof(currentMhz
);
3565 if (!sysctlbyname("hw.cpufrequency", ¤tMhz
, &valSize
, NULL
, 0))
3566 currentMhz
/= 1000000;
3568 currentMhz
= cannedMHz
;
3570 valSize
= sizeof(maxMhz
);
3571 if (!sysctlbyname("hw.cpufrequency_max", &maxMhz
, &valSize
, NULL
, 0))
3574 maxMhz
= currentMhz
;
3576 for(i
= 0; i
< out_cpus
; i
++) {
3577 cpu_power
[i
].CurrentMhz
= currentMhz
;
3578 cpu_power
[i
].MaxMhz
= maxMhz
;
3579 cpu_power
[i
].MhzLimit
= maxMhz
;
3580 cpu_power
[i
].Number
= i
;
3581 cpu_power
[i
].MaxIdleState
= 0; /* FIXME */
3582 cpu_power
[i
].CurrentIdleState
= 0; /* FIXME */
3586 for(i
= 0; i
< out_cpus
; i
++) {
3587 cpu_power
[i
].CurrentMhz
= cannedMHz
;
3588 cpu_power
[i
].MaxMhz
= cannedMHz
;
3589 cpu_power
[i
].MhzLimit
= cannedMHz
;
3590 cpu_power
[i
].Number
= i
;
3591 cpu_power
[i
].MaxIdleState
= 0; /* FIXME */
3592 cpu_power
[i
].CurrentIdleState
= 0; /* FIXME */
3594 WARN("Unable to detect CPU MHz for this platform. Reporting %d MHz.\n", cannedMHz
);
3596 for(i
= 0; i
< out_cpus
; i
++) {
3597 TRACE("cpu_power[%d] = %u %u %u %u %u %u\n", i
, cpu_power
[i
].Number
,
3598 cpu_power
[i
].MaxMhz
, cpu_power
[i
].CurrentMhz
, cpu_power
[i
].MhzLimit
,
3599 cpu_power
[i
].MaxIdleState
, cpu_power
[i
].CurrentIdleState
);
3601 return STATUS_SUCCESS
;
3604 /* FIXME: Needed by .NET Framework */
3605 WARN("Unimplemented NtPowerInformation action: %d\n", InformationLevel
);
3606 return STATUS_NOT_IMPLEMENTED
;
3610 /******************************************************************************
3611 * NtShutdownSystem [NTDLL.@]
3614 NTSTATUS WINAPI
NtShutdownSystem(SHUTDOWN_ACTION Action
)
3616 FIXME("%d\n",Action
);
3617 return STATUS_SUCCESS
;
3620 /******************************************************************************
3621 * NtAllocateLocallyUniqueId (NTDLL.@)
3623 NTSTATUS WINAPI
NtAllocateLocallyUniqueId(PLUID Luid
)
3627 TRACE("%p\n", Luid
);
3630 return STATUS_ACCESS_VIOLATION
;
3632 SERVER_START_REQ( allocate_locally_unique_id
)
3634 status
= wine_server_call( req
);
3637 Luid
->LowPart
= reply
->luid
.low_part
;
3638 Luid
->HighPart
= reply
->luid
.high_part
;
3646 /******************************************************************************
3647 * VerSetConditionMask (NTDLL.@)
3649 ULONGLONG WINAPI
VerSetConditionMask( ULONGLONG dwlConditionMask
, DWORD dwTypeBitMask
,
3650 BYTE dwConditionMask
)
3652 if(dwTypeBitMask
== 0)
3653 return dwlConditionMask
;
3654 dwConditionMask
&= 0x07;
3655 if(dwConditionMask
== 0)
3656 return dwlConditionMask
;
3658 if(dwTypeBitMask
& VER_PRODUCT_TYPE
)
3659 dwlConditionMask
|= dwConditionMask
<< 7*3;
3660 else if (dwTypeBitMask
& VER_SUITENAME
)
3661 dwlConditionMask
|= dwConditionMask
<< 6*3;
3662 else if (dwTypeBitMask
& VER_SERVICEPACKMAJOR
)
3663 dwlConditionMask
|= dwConditionMask
<< 5*3;
3664 else if (dwTypeBitMask
& VER_SERVICEPACKMINOR
)
3665 dwlConditionMask
|= dwConditionMask
<< 4*3;
3666 else if (dwTypeBitMask
& VER_PLATFORMID
)
3667 dwlConditionMask
|= dwConditionMask
<< 3*3;
3668 else if (dwTypeBitMask
& VER_BUILDNUMBER
)
3669 dwlConditionMask
|= dwConditionMask
<< 2*3;
3670 else if (dwTypeBitMask
& VER_MAJORVERSION
)
3671 dwlConditionMask
|= dwConditionMask
<< 1*3;
3672 else if (dwTypeBitMask
& VER_MINORVERSION
)
3673 dwlConditionMask
|= dwConditionMask
<< 0*3;
3674 return dwlConditionMask
;
3677 /******************************************************************************
3678 * NtAccessCheckAndAuditAlarm (NTDLL.@)
3679 * ZwAccessCheckAndAuditAlarm (NTDLL.@)
3681 NTSTATUS WINAPI
NtAccessCheckAndAuditAlarm(PUNICODE_STRING SubsystemName
, HANDLE HandleId
, PUNICODE_STRING ObjectTypeName
,
3682 PUNICODE_STRING ObjectName
, PSECURITY_DESCRIPTOR SecurityDescriptor
,
3683 ACCESS_MASK DesiredAccess
, PGENERIC_MAPPING GenericMapping
, BOOLEAN ObjectCreation
,
3684 PACCESS_MASK GrantedAccess
, PBOOLEAN AccessStatus
, PBOOLEAN GenerateOnClose
)
3686 FIXME("(%s, %p, %s, %p, 0x%08x, %p, %d, %p, %p, %p), stub\n", debugstr_us(SubsystemName
), HandleId
,
3687 debugstr_us(ObjectTypeName
), SecurityDescriptor
, DesiredAccess
, GenericMapping
, ObjectCreation
,
3688 GrantedAccess
, AccessStatus
, GenerateOnClose
);
3690 return STATUS_NOT_IMPLEMENTED
;
3693 /******************************************************************************
3694 * NtSystemDebugControl (NTDLL.@)
3695 * ZwSystemDebugControl (NTDLL.@)
3697 NTSTATUS WINAPI
NtSystemDebugControl(SYSDBG_COMMAND command
, PVOID inbuffer
, ULONG inbuflength
, PVOID outbuffer
,
3698 ULONG outbuflength
, PULONG retlength
)
3700 FIXME("(%d, %p, %d, %p, %d, %p), stub\n", command
, inbuffer
, inbuflength
, outbuffer
, outbuflength
, retlength
);
3702 return STATUS_NOT_IMPLEMENTED
;
3705 /******************************************************************************
3706 * NtSetLdtEntries (NTDLL.@)
3707 * ZwSetLdtEntries (NTDLL.@)
3709 NTSTATUS WINAPI
NtSetLdtEntries(ULONG selector1
, ULONG entry1_low
, ULONG entry1_high
,
3710 ULONG selector2
, ULONG entry2_low
, ULONG entry2_high
)
3712 FIXME("(%u, %u, %u, %u, %u, %u): stub\n", selector1
, entry1_low
, entry1_high
, selector2
, entry2_low
, entry2_high
);
3714 return STATUS_NOT_IMPLEMENTED
;