Author Topic: GetCpuFrequency Tests  (Read 17777 times)

TWell

  • Member
  • ****
  • Posts: 748
Re: GetCpuFrequency Tests
« Reply #75 on: December 24, 2015, 06:42:15 AM »
If you use GetCurrentProcess(), it is calling process handle?

guga

  • Member
  • ****
  • Posts: 848
  • Assembly is a state of art.
    • RosAsm
Re: GetCpuFrequency Tests
« Reply #76 on: December 25, 2015, 01:36:33 AM »
Hi dave, take a look at this source

http://fluid-particles.googlecode.com/svn/trunk/CoreDetection/CpuTopology.cpp

You may find interesting the cpu classes :)

Btw....Also the project per se is quite amazing (Fluid particles system)
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

guga

  • Member
  • ****
  • Posts: 848
  • Assembly is a state of art.
    • RosAsm
Re: GetCpuFrequency Tests
« Reply #77 on: December 26, 2015, 03:05:58 AM »
Dave, do not use SetProcessAffinityMask !!!

I found a bug (at least on WinP) inside that API. The stack is being returned incorrectly. There is a major stack problem there. There is a lack of "leave"  or "mov esp ebp". This is causing the function to needs an adjustment on the stack after it is used. I made some tests on your function and saved the registers while using it. All i left was eax to it returns the proper Flags retrieved by GetCpuidSupport. The problem was after using the GetCpuFrequency it was saving at ebx the same value as in eax (ebx was being "poped" by eax), regardless i saved all registers with the chain of push/pop, during the entrance and exiting of the function. Take a look at the disassembled code from kernel32.dll as below:

Code: [Select]
; BOOL __stdcall SetProcessAffinityMask(HANDLE hProcess, DWORD_PTR dwProcessAffinityMask)
public _SetProcessAffinityMask@8
_SetProcessAffinityMask@8 proc near ; DATA XREF: .text:off_7C802654o

hProcess = dword ptr  8
dwProcessAffinityMask= dword ptr  0Ch

mov edi, edi
push ebp
mov ebp, esp
push 4
lea eax, [ebp+dwProcessAffinityMask]
push eax
push 21
push [ebp+hProcess]
call ds:__imp__NtSetInformationProcess@16 ; NtSetInformationProcess(x,x,x,x)
test eax, eax
jge short loc_7C862E48
push eax
call _BaseSetLastNTError@4 ; BaseSetLastNTError(x)
xor eax, eax
jmp short loc_7C862E4B
; ---------------------------------------------------------------------------

loc_7C862E48:
xor eax, eax
inc eax

loc_7C862E4B: ; MISSING A "LEAVE" OR "MOV ESP EBB" HERE !!!!
pop ebp
retn 8
_SetProcessAffinityMask@8 endp

I succeeded to fix that and rebuilt both APis used:GetProcessAffinityMask and SetProcessAffinityMask. I´ll post the corrected functions on another thread. I managed to fix retrieving the values from the TEB/PEB structures as the same way the original APis did, but, i fixed them, while on XP it is still broken ! (I believe that probably, it is also broken in others windows versions as well, but i didn´t analyzed them yet)
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

nidud

  • Member
  • *****
  • Posts: 1614
    • https://github.com/nidud/asmc
Re: GetCpuFrequency Tests
« Reply #78 on: December 26, 2015, 03:25:08 AM »
This is the standard PROLOGUE and EPILOGUE for a proc without locals.

Code: [Select]
push ebp
mov ebp,esp
...
pop ebp

This is the standard PROLOGUE and EPILOGUE for a proc with locals.

Code: [Select]
push ebp
mov ebp,esp
sub esp,sizeof(locals)
...
mov esp,ebp
pop ebp

The latter may be replaced by ENTER and LEAVE.

jj2007

  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
Re: GetCpuFrequency Tests
« Reply #79 on: December 26, 2015, 03:39:56 AM »
I found a bug (at least on WinP) inside that API. The stack is being returned incorrectly. There is a major stack problem there. There is a lack of "leave"  or "mov esp ebp". This is causing the function to needs an adjustment on the stack after it is used.

Can you post an executable that shows this behaviour, with an int 3 inserted shortly before?
My tests on Win XP and Win7-64 do not show any abnormal behaviour:

include \masm32\MasmBasic\MasmBasic.inc      ; download
  Init
  mov esi, 111111111
  mov edi, 222222222
  mov ebx, 333333333
  mov ecx, 444444444
  deb 4, "In", esi, edi, ebx, ebp, ecx, esp
  ClearLastError
  push ecx
  invoke SetProcessAffinityMask, rv(GetCurrentProcess), 1
  pop ecx
  deb 4, "SPAM", eax, $Err$()
  deb 4, "Out", esi, edi, ebx, ebp, ecx, esp
EndOfCode


Code: [Select]
In
esi             111111111
edi             222222222
ebx             333333333
ebp             1638292
ecx             444444444
esp             1638284

SPAM
eax             1
$Err$()         Operazione completata.


Out
esi             111111111
edi             222222222
ebx             333333333
ebp             1638292
ecx             444444444
esp             1638284

guga

  • Member
  • ****
  • Posts: 848
  • Assembly is a state of art.
    • RosAsm
Re: GetCpuFrequency Tests
« Reply #80 on: December 26, 2015, 05:23:19 AM »
Hi Guys...Many tks for the feedback.

Indeed that was not a fault of GetProcessAffinityMask/SetProcessAffinityMask.

The problem was in one of my macros. The counting of the stack was incorrect, leading the values to return 4 bytes ahead

many tks, and Merry Xmas, to you all :)
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

guga

  • Member
  • ****
  • Posts: 848
  • Assembly is a state of art.
    • RosAsm
Re: GetCpuFrequency Tests
« Reply #81 on: December 26, 2015, 05:57:11 AM »
In any case, if someone wants a new version of those Apis (GetProcessAffinityMask and SetProcessAffinityMask) here they are:

GetProcessAffinityMask
Code: [Select]
[BASE_STATIC_SERVER_DATA.WindowsDirectory.LengthDis 0
 BASE_STATIC_SERVER_DATA.WindowsDirectory.MaximumLengthDis 2
 BASE_STATIC_SERVER_DATA.WindowsDirectory.BufferDis 4
 BASE_STATIC_SERVER_DATA.WindowsSystemDirectory.LengthDis 8
 BASE_STATIC_SERVER_DATA.WindowsSystemDirectory.MaximumLengthDis 10
 BASE_STATIC_SERVER_DATA.WindowsSystemDirectory.BufferDis 12
 BASE_STATIC_SERVER_DATA.NamedObjectDirectory.LengthDis 16
 BASE_STATIC_SERVER_DATA.NamedObjectDirectory.MaximumLengthDis 18
 BASE_STATIC_SERVER_DATA.NamedObjectDirectory.BufferDis 20
 BASE_STATIC_SERVER_DATA.WindowsMajorVersionDis 24
 BASE_STATIC_SERVER_DATA.WindowsMinorVersionDis 26
 BASE_STATIC_SERVER_DATA.BuildNumberDis 28
 BASE_STATIC_SERVER_DATA.CSD.wServicePackMajorDis 30
 BASE_STATIC_SERVER_DATA.CSD.wServicePackMinorDis 32
 BASE_STATIC_SERVER_DATA.CSD.szCSDVersionDis 34
 BASE_STATIC_SERVER_DATA.Padding1Dis 286
 BASE_STATIC_SERVER_DATA.SysInfo.ReservedDis 288
 BASE_STATIC_SERVER_DATA.SysInfo.TimerResolutionDis 292
 BASE_STATIC_SERVER_DATA.SysInfo.PageSizeDis 296
 BASE_STATIC_SERVER_DATA.SysInfo.NumberOfPhysicalPagesDis 300
 BASE_STATIC_SERVER_DATA.SysInfo.LowestPhysicalPageNumberDis 304
 BASE_STATIC_SERVER_DATA.SysInfo.HighestPhysicalPageNumberDis 308
 BASE_STATIC_SERVER_DATA.SysInfo.AllocationGranularityDis 312
 BASE_STATIC_SERVER_DATA.SysInfo.MinimumUserModeAddressDis 316
 BASE_STATIC_SERVER_DATA.SysInfo.MaximumUserModeAddressDis 320
 BASE_STATIC_SERVER_DATA.SysInfo.ActiveProcessorsAffinityMaskDis 324
 BASE_STATIC_SERVER_DATA.SysInfo.NumberOfProcessorsDis 328
 BASE_STATIC_SERVER_DATA.SysInfo.Padding1Dis 329
 BASE_STATIC_SERVER_DATA.Padding2Dis 332
 BASE_STATIC_SERVER_DATA.TimeOfDay.BootTimeDis 336
 BASE_STATIC_SERVER_DATA.TimeOfDay.CurrentTimeDis 344
 BASE_STATIC_SERVER_DATA.TimeOfDay.TimeZoneBiasDis 352
 BASE_STATIC_SERVER_DATA.TimeOfDay.TimeZoneIdDis 360
 BASE_STATIC_SERVER_DATA.TimeOfDay.ReservedDis 364
 BASE_STATIC_SERVER_DATA.IniFileMappingDis 368
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sAbbrevLangNameDis 372
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iCountryDis 532
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sCountryDis 692
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sListDis 852
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iMeasureDis 1012
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sDecimalDis 1172
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sThousandDis 1332
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sGroupingDis 1492
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iDigitsDis 1652
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iLZeroDis 1812
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iNegNumberDis 1972
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sCurrencyDis 2132
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sMonDecSepDis 2292
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sMonThouSepDis 2452
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sMonGroupingDis 2612
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iCurrDigitsDis 2772
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iCurrencyDis 2932
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iNegCurrDis 3092
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sPosSignDis 3252
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sNegSignDis 3412
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sTimeFormatDis 3572
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sTimeDis 3732
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iTimeDis 3892
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iTLZeroDis 4052
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iTimeMarkPosnDis 4212
 BASE_STATIC_SERVER_DATA.NlsUserInfo.s1159Dis 4372
 BASE_STATIC_SERVER_DATA.NlsUserInfo.s2359Dis 4532
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sShortDateDis 4692
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sDateDis 4852
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iDateDis 5012
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sLongDateDis 5172
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iCalTypeDis 5332
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iFirstDayDis 5492
 BASE_STATIC_SERVER_DATA.NlsUserInfo.iFirstWeekDis 5652
 BASE_STATIC_SERVER_DATA.NlsUserInfo.sLocaleDis 5812
 BASE_STATIC_SERVER_DATA.NlsUserInfo.UserLocaleIdDis 5972
 BASE_STATIC_SERVER_DATA.NlsUserInfo.fCacheValidDis 5976
 BASE_STATIC_SERVER_DATA.DefaultSeparateVDMDis 5980
 BASE_STATIC_SERVER_DATA.Wx86EnabledDis 5981
 BASE_STATIC_SERVER_DATA.Padding3Dis 5982]

[Size_Of_BASE_STATIC_SERVER_DATA 5984]


[PROCESS_BASIC_INFORMATION.ExitStatusDis 0
 PROCESS_BASIC_INFORMATION.PebBaseAddressDis 4
 PROCESS_BASIC_INFORMATION.AffinityMaskDis 8
 PROCESS_BASIC_INFORMATION.BasePriorityDis 12
 PROCESS_BASIC_INFORMATION.UniqueProcessIdDis 16
 PROCESS_BASIC_INFORMATION.InheritedFromUniqueProcessIdDis 20]

[Size_of_PROCESS_BASIC_INFORMATION 24]

[BaseStaticServerData: D$ 0]

Proc GetProcessAffinityMask:
    Arguments @hProcess, @lpProcessAffinityMask, @lpSystemAffinityMask
    Structure @PROCESS_BASIC_INFORMATION 24, @PROCESS_BASIC_INFORMATION.ExitStatusDis 0,
              @PROCESS_BASIC_INFORMATION.PebBaseAddressDis 4, @PROCESS_BASIC_INFORMATION.AffinityMaskDis 8,
              @PROCESS_BASIC_INFORMATION.BasePriorityDis 12, @PROCESS_BASIC_INFORMATION.UniqueProcessIdDis 16,
              @PROCESS_BASIC_INFORMATION.InheritedFromUniqueProcessIdDis 20
    Uses ecx, edx

    call 'Ntdll.NtQueryInformationProcess' D@hProcess, &PROCESS_BASICINFORMATION,
                                           D@PROCESS_BASIC_INFORMATION, Size_of_PROCESS_BASIC_INFORMATION, 0
    If eax <> &STATUS_SUCCESS
        call BaseSetLastNTError eax
        xor eax eax
    Else
       
        ; Copy the affinity mask, and get the system one from our shared data
        mov ecx D@lpProcessAffinityMask
        mov eax D@PROCESS_BASIC_INFORMATION.AffinityMaskDis | mov D$ecx eax

        call 'ntdll.RtlAcquirePebLock' ; <------- Always lock the PEb before using it.
        call GetBaseStaticServerFromTEB BaseStaticServerData
        mov eax D$BaseStaticServerData
        mov eax D$eax+BASE_STATIC_SERVER_DATA.SysInfo.NumberOfProcessorsDis
        mov ecx D@lpSystemAffinityMask | mov D$ecx eax
        call 'ntdll.RtlReleasePebLock'; <---- And, of course, don´t forget to unlock it.
        mov eax &TRUE
    End_If

EndP

SetProcessAffinityMask
Code: [Select]
Proc SetProcessAffinityMask:
    Arguments @hProcess, @dwProcessAffinityMask
    Uses ecx, edx

    ; Directly set the affinity mask
    lea eax D@dwProcessAffinityMask
    call 'Ntdll.NtSetInformationProcess' D@hProcess, &PROCESS_AFFINITYMASK, eax, 4

    If eax <> &STATUS_SUCCESS
        call BaseSetLastNTError eax
        xor eax eax
    Else
        mov eax &TRUE
    End_If

EndP

And the additional functions

BaseSetLastNTError
Code: [Select]
Proc BaseSetLastNTError:
    Arguments @ErrorCode
    Uses esi, ecx, edx, ebx

    call 'ntdll.RtlNtStatusToDosError' D@ErrorCode | mov esi eax
    call 'kernel32.SetLastError' eax
    mov eax esi

EndP

GetBaseStaticServerFromTEB
Code: [Select]

;;
         GetBaseStaticServerFromTEB

            This function retrieves the pointer to a BASE_STATIC_SERVER_DATA structure that contains information about your system.

         Arguments:
           pOutput (out): Pointer to a Variable that will holds the data to the structure BASE_STATIC_SERVER_DATA

        Returned Values:
               This function will return a pointer to BASE_STATIC_SERVER_DATA structure. Also, it will store it on the proper variable at pOutput

       Example of usage:

          [BaseStaticServerData: D$ 0]
                    call 'ntdll.RtlAcquirePebLock' ; <------- Always lock the PEb before using it.
                    call GetBaseStaticServerFromTEB BaseStaticServerData
                    add eax BASE_STATIC_SERVER_DATA.NamedObjectDirectory.LengthDis
                     (...)
                    call 'ntdll.RtlReleasePebLock' <---- And, of course, don´t forget to unlock it.

       See Also: BASE_STATIC_SERVER_DATA structure

        Remarks: Always lock and unlock the PEb when retrieving the information from TEB/PEB data.
                        To lock you must use a call to  'ntdll.RtlAcquirePebLock' and to unlock you must use the function ntdll.RtlReleasePebLock
                         See the example above.

      Author:
         Gustavo Trigueiros (aka: Beyond2000! or Guga)
         jul/2014
;;


[TEB.Tib.ExceptionListDis 0
 TEB.Tib.StackBaseDis 4
 TEB.Tib.StackLimitDis 8
 TEB.Tib.SubSystemTibDis 12
 TEB.Tib.FiberDataDis 16
 TEB.VersionDis 16
 TEB.Tib.ArbitraryUserPointerDis 20
 TEB.Tib.SelfDis 24
 TEB.EnvironmentPointerDis 28
 TEB.ClientId.UniqueProcessDis 32
 TEB.ClientId.UniqueThreadDis 36
 TEB.ActiveRpcDDis 40
 TEB.ThreadLocalStoragePointerDis 44
 TEB.PebDis 48
 TEB.LastErrorValueDis 52
 TEB.CountOfOwnedCriticalSectionsDis 56
 TEB.CsrClientThreadDis 60
 TEB.Win32ThreadInfoDis 64
 TEB.Win32ClientInfoDis 68
 TEB.WOW32ReservedDis 192
 TEB.CurrentLocaleDis 196
 TEB.FpSoftwareStatusRegisterDis 200
 TEB.SystemReserved1Dis 204
 TEB.Spare1Dis 420
 TEB.ExceptionCodeDis 424
 TEB.SpareBs1Dis 428
 TEB.SystemReserved2Dis 468
 TEB.GdiTebBatch.OffsetDis 508
 TEB.GdiTebBatch.HDCDis 512
 TEB.GdiTebBatch.BufferDis 516
 TEB.gdiRgnDis 1756
 TEB.gdiPenDis 1760
 TEB.gdiBrushDis 1764
 TEB.RealClientId.UniqueProcessDis 1768
 TEB.RealClientId.UniqueThreadDis 1772
 TEB.GdiCachedProcessDDis 1776
 TEB.GdiClientPIDDis 1780
 TEB.GdiClientTIDDis 1784
 TEB.GdiThreadLocaleInfoDis 1788
 TEB.UserReservedDis 1792
 TEB.glDispachTableDis 1812
 TEB.glReserved1Dis 2932
 TEB.glReserved2Dis 3036
 TEB.glSectionInfoDis 3040
 TEB.glSectionDis 3044
 TEB.glTableDis 3048
 TEB.glCurrentRCDis 3052
 TEB.glContextDis 3056
 TEB.LastStatusValueDis 3060
 TEB.StaticUnicodeString.LengthDis 3064
 TEB.StaticUnicodeString.MaximumLengthDis 3066
 TEB.StaticUnicodeString.BufferDis 3068
 TEB.StaticUnicodeBufferDis 3072
 TEB.PADDINGDis 3594
 TEB.DeallocationStackDis 3596
 TEB.TlsSlotsDis 3600
 TEB.TlsLinks.FlinkDis 3856
 TEB.TlsLinks.BlinkDis 3860
 TEB.VdmDis 3864
 TEB.ReservedForNtRpcDis 3868
 TEB.DbgSsReservedDis 3872
 TEB.HardErrorDisabledDis 3880
 TEB.InstrumentationDis 3884
 TEB.WinSockDataDis 3948
 TEB.GdiBatchCountDis 3952
 TEB.Spare2Dis 3956
 TEB.Spare3Dis 3960
 TEB.Spare4Dis 3964
 TEB.ReservedForOleDis 3968
 TEB.WaitingOnLoaderLockDis 3972
 TEB.Reserved5Dis 3976
 TEB.TlsExpansionSlotsDis 3988]

[PEB.InheritedAddressSpaceDis 0
 PEB.ReadImageFileExecOptionsDis 1
 PEB.BeingDebuggedDis 2
 PEB.SpareBoolDis 3
 PEB.MutantDis 4
 PEB.ImageBaseAddressDis 8
 PEB.LdrDataDis 12
 PEB.ProcessParametersDis 16
 PEB.SubSystemDataDis 20
 PEB.ProcessHeapDis 24
 PEB.FastPebLockDis 28
 PEB.FastPebLockRoutineDis 32
 PEB.FastPebUnlockRoutineDis 36
 PEB.EnvironmentUpdateCountDis 40
 PEB.KernelCallbackTableDis 44
 PEB.EventLogSectionDis 48
 PEB.EventLogDis 52
 PEB.FreeListDis 56
 PEB.TlsExpansionCounterDis 60
 PEB.TlsBitmapDis 64
 PEB.TlsBitmapBitsDis 68
 PEB.ReadOnlySharedMemoryBaseDis 76
 PEB.ReadOnlySharedMemoryHeapDis 80
 PEB.ReadOnlyStaticServerDataDis 84
 PEB.AnsiCodePageDataDis 88
 PEB.OemCodePageDataDis 92
 PEB.UnicodeCaseTableDataDis 96
 PEB.NumberOfProcessorsDis 100
 PEB.NtGlobalFlagDis 104
 PEB.Spare2Dis 108
 PEB.CriticalSectionTimeoutDis 112
 PEB.HeapSegmentReserveDis 120
 PEB.HeapSegmentCommitDis 124
 PEB.HeapDeCommitTotalFreeThresholdDis 128
 PEB.HeapDeCommitFreeBlockThresholdDis 132
 PEB.NumberOfHeapsDis 136
 PEB.MaximumNumberOfHeapsDis 140
 PEB.ProcessHeapsDis 144
 PEB.GdiSharedHandleTableDis 148
 PEB.ProcessStarterHelperDis 152
 PEB.GdiDCAttributeListDis 156
 PEB.LoaderLockDis 160
 PEB.OSMajorVersionDis 164
 PEB.OSMinorVersionDis 168
 PEB.OSBuildNumberDis 172
 PEB.OSPlatformIdDis 176
 PEB.ImageSubSystemDis 180
 PEB.ImageSubSystemMajorVersionDis 184
 PEB.ImageSubSystemMinorVersionDis 188
 PEB.ImageProcessAffinityMaskDis 192
 PEB.GdiDBufferDis 196
 PEB.PostProcessInitRoutineDis 332
 PEB.TlsExpansionBitmapDis 336
 PEB.TlsExpansionBitmapBitsDis 340
 PEB.SessionIdDis 468]

[TEXT_INFO.ReservedDis 0
 TEXT_INFO.SystemStringsDis 4]

[Size_Of_TEXT_INFO 8]

Proc GetBaseStaticServerFromTEB:
    Arguments @pOutput
    Uses edi

    mov edi D@pOutput
    mov eax D$fs:TEB.Tib.SelfDis ; retrieve TEB structure for the current process
    mov eax D$eax+TEB.PebDis ; pointer to a PEB structure
    mov eax D$eax+PEB.ReadOnlyStaticServerDataDis ; retrieve the ReadOnlyStaticServerData (a TEXT_INFO structure)
    mov eax D$eax+TEXT_INFO.SystemStringsDis ; pointer to a BASE_STATIC_SERVER_DATA structure and not a SYSTEM_STRINGS structure (eah member points to a UNICODE_STRING String)
    mov D$edi eax

EndP

Equates :
PROCESS_BASICINFORMATION = 0
PROCESS_AFFINITYMASK = 21
STATUS_SUCCESS = 0

or, another version of GetProcessAffinityMask
Alternative version
Code: [Select]
Proc GetProcessAffinityMask:
    Arguments @hProcess, @lpProcessAffinityMask, @lpSystemAffinityMask
    Structure @PROCESS_BASIC_INFORMATION 24, @PROCESS_BASIC_INFORMATION.ExitStatusDis 0,
              @PROCESS_BASIC_INFORMATION.PebBaseAddressDis 4, @PROCESS_BASIC_INFORMATION.AffinityMaskDis 8,
              @PROCESS_BASIC_INFORMATION.BasePriorityDis 12, @PROCESS_BASIC_INFORMATION.UniqueProcessIdDis 16,
              @PROCESS_BASIC_INFORMATION.InheritedFromUniqueProcessIdDis 20
    Uses ecx, edx

    call 'Ntdll.NtQueryInformationProcess' D@hProcess, &PROCESS_BASICINFORMATION,
                                           D@PROCESS_BASIC_INFORMATION, Size_of_PROCESS_BASIC_INFORMATION, 0
    If eax <> &STATUS_SUCCESS
        call BaseSetLastNTError eax
        xor eax eax
    Else
       
        ; Copy the affinity mask, and get the system one from our shared data
        mov ecx D@lpProcessAffinityMask
        mov eax D@PROCESS_BASIC_INFORMATION.AffinityMaskDis | mov D$ecx eax

        mov ecx D@lpSystemAffinityMask
        mov eax D@PROCESS_BASIC_INFORMATION.PebBaseAddressDis | mov eax D$eax+PEB.ReadOnlyStaticServerDataDis
        mov eax D$eax+TEXT_INFO.SystemStringsDis | mov eax D$eax+BASE_STATIC_SERVER_DATA.SysInfo.NumberOfProcessorsDis
        mov D$ecx eax
        mov eax &TRUE
    End_If

EndP
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com