Jump to content

DllStruct Bug


Smed
 Share

Recommended Posts

After fighting with it for about two hours I narrowed it down to this:

$systemInfo = DllStructCreate ("short;short;dword;int;int;int;dword;dword;dword;short;short")
;$foo = DllStructCreate ("int")

DllCall ("ntdll.dll", "int", "NtQuerySystemInformation", "ptr", DllStructPtr ($systemInfo))

$processorArchitecture = DllStructGet ($systemInfo, 1)
$numberOfProcessors = DllStructGet ($systemInfo, 7)
$processorType = DllStructGet ($systemInfo, 8)
$processorLevel = DllStructGet ($systemInfo, 9)
$processorRevision = DllStructGet ($systemInfo, 9)

$baseInfo = "Number of Processors:   " & $numberOfProcessors & @CRLF & _
            "Processor Architecture: " & $processorArchitecture & @CRLF & _
            "Processor Type:         " & $processorType & @CRLF & _
            "Processor Level:       " & $processorLevel & @CRLF & _
            "Processor Revision:     " & $processorRevision & @CRLF & @CRLF

MsgBox (0, "Whazzup?", $baseInfo)

DllStructFree ($systemInfo)
;DllStructFree ($foo)

If you run that and then uncomment the $foo lines it behaves differently, or atleast it does for me.

oh.. win2K.

601DisengageEnd Program

Link to comment
Share on other sites

on xp pro sp2 they both commented and un commented gave me:

MSDN says:

NtQuerySystemInformation is available for use in Windows 2000 and Windows XP. It may be altered or unavailable in subsequent versions. Applications should use the alternate functions listed in this topic.

The struct you are building is incorrect, I didnt go over everything in it, but the last item of the struct is suppose to be a pointer.

Edited by Ejoc
Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs
Link to comment
Share on other sites

2000AS/sp4, I get 376 commented and 928 uncommented. My OS didn't change, so my information shouldn't change. I grant you that MS is weird about that, but still...

601DisengageEnd Program

Link to comment
Share on other sites

Looks like you are using:

typedef struct _SYSTEM_INFO {
  union {
    DWORD dwOemId;
    struct {
      WORD wProcessorArchitecture;
      WORD wReserved;
    };
  };
  DWORD dwPageSize;
  LPVOID lpMinimumApplicationAddress;
  LPVOID lpMaximumApplicationAddress;
  DWORD_PTR dwActiveProcessorMask;
  DWORD dwNumberOfProcessors;
  DWORD dwProcessorType;
  DWORD dwAllocationGranularity;
  WORD wProcessorLevel;
  WORD wProcessorRevision;
} SYSTEM_INFO;

And should be calling:

void GetSystemInfo(
  LPSYSTEM_INFO lpSystemInfo
);

DllStruct looks fine, no bug, just calling the wrong function

Edited by Ejoc
Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs
Link to comment
Share on other sites

D'OH! you are totally correct. However that doesn't explain why it behaves differently when an independant structure has been created. I realize that its impossible to debug a problem you can't reproduce, but its there somewhere.

Gimme a moment, I'll try to narrow it down more.

601DisengageEnd Program

Link to comment
Share on other sites

The struct you were creating wasn't large enough and the function call was overwritting memory outside the amount allocated for it, so when you created $foo the memory for the first struct could have been playing havoc with it.

Edited by Ejoc
Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs
Link to comment
Share on other sites

yeh, I think I've got it almost straightened out, but I read and re-read the docs and MSDN told not to use a pointer when it would fit in an int, what's your suggestion on structure. Nice work on the docs btw, I looked back a couple of times asking, " I wonder if he mentioned this... " and sure enough you had. :(

601DisengageEnd Program

Link to comment
Share on other sites

The struct you have seems fine, It makes me think of a handy UDF I might create. You would go on MSDN and copy the struct into the clipboard and it would produce the string for use in autoit. Could be pretty trick tho, like dealing w/ unions but could come in handy.

Start -> Programs -> AutoIt v3 -> AutoIt Help File -> Index -> (The Function you are asking about)----- Links -----DllStruct UDFsRSA Crypto UDFs
Link to comment
Share on other sites

Must.. Go.. To.. Bed.. I think I've verified that I only have one processor, and it claims to be some variant of an intel, but I'm not 100% certain.

Crikey! This is like work, or something! :(

601DisengageEnd Program

Link to comment
Share on other sites

OK, not a bug. But this raises a serious issue. If its that easy to overwrite a buffer then there is no end of bizarre side-effects that could be produced. Anything from mysteriously changing the value of a variable (possibly usefull) to modifying executable code (potentially hazardous).

I realize that its not practical for DllCall to verify that prameters are correct and its certainly not in the scope of your DllStructXXX functions to take responsibility for this. However I think it clearly demonstrates that some sort of memory protection mechanism is necessary.

The MSDN->AutoIt translator is a great idea, but it won't solve the problem.

601DisengageEnd Program

Link to comment
Share on other sites

This is no different than C. In fact, in order to use this, having a knowledge of C's method of using structures is virtually required. If a user does something dumb and gets undesirable results, then that is there fault. If you don't know how to use it correctly, don't use it. Blaming the code would be like blaming the gun if you were to shoot your own foot off.

Link to comment
Share on other sites

This is no different than C.  In fact, in order to use this, having a knowledge of C's method of using structures is virtually required.  If a user does something dumb and gets undesirable results, then that is there fault.  If you don't know how to use it correctly, don't use it.  Blaming the code would be like blaming the gun if you were to shoot your own foot off.

<{POST_SNAPBACK}>

I agree with you completely, but my point is that this gun doesn't come with a trigger lock, a safety or even a warning label.

601DisengageEnd Program

Link to comment
Share on other sites

Thanks for the warning Larry, belated though it may be.  Maybe Ejoc can add that to the docs.  With a nice byline credit to Valik.

<{POST_SNAPBACK}>

Retrieving processor information this way is much safer:

; Generated by AutoIt Scriptomatic

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$Output=""
$Output = $Output & "Computer: " & $strComputer  & @CRLF
$Output = $Output & "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Processor", "WQL", _
                                          $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) then
   For $objItem In $colItems
      $Output = $Output & "AddressWidth: "              & $objItem.AddressWidth & @CRLF
      $Output = $Output & "Architecture: "              & $objItem.Architecture & @CRLF
      $Output = $Output & "Availability: "              & $objItem.Availability & @CRLF
      $Output = $Output & "Caption: "                   & $objItem.Caption & @CRLF
      $Output = $Output & "ConfigManagerErrorCode: "    & $objItem.ConfigManagerErrorCode & @CRLF
      $Output = $Output & "ConfigManagerUserConfig: "   & $objItem.ConfigManagerUserConfig & @CRLF
      $Output = $Output & "CpuStatus: "                 & $objItem.CpuStatus & @CRLF
      $Output = $Output & "CreationClassName: "         & $objItem.CreationClassName & @CRLF
      $Output = $Output & "CurrentClockSpeed: "         & $objItem.CurrentClockSpeed & @CRLF
      $Output = $Output & "CurrentVoltage: "            & $objItem.CurrentVoltage & @CRLF
      $Output = $Output & "DataWidth: "                 & $objItem.DataWidth & @CRLF
      $Output = $Output & "Description: "               & $objItem.Description & @CRLF
      $Output = $Output & "DeviceID: "                  & $objItem.DeviceID & @CRLF
      $Output = $Output & "ErrorCleared: "              & $objItem.ErrorCleared & @CRLF
      $Output = $Output & "ErrorDescription: "          & $objItem.ErrorDescription & @CRLF
      $Output = $Output & "ExtClock: "                  & $objItem.ExtClock & @CRLF
      $Output = $Output & "Family: "                    & $objItem.Family & @CRLF
      $Output = $Output & "L2CacheSize: "               & $objItem.L2CacheSize & @CRLF
      $Output = $Output & "L2CacheSpeed: "              & $objItem.L2CacheSpeed & @CRLF
      $Output = $Output & "LastErrorCode: "             & $objItem.LastErrorCode & @CRLF
      $Output = $Output & "Level: "                     & $objItem.Level & @CRLF
      $Output = $Output & "LoadPercentage: "            & $objItem.LoadPercentage & @CRLF
      $Output = $Output & "Manufacturer: "              & $objItem.Manufacturer & @CRLF
      $Output = $Output & "MaxClockSpeed: "             & $objItem.MaxClockSpeed & @CRLF
      $Output = $Output & "Name: "                      & $objItem.Name & @CRLF
      $Output = $Output & "OtherFamilyDescription: "    & $objItem.OtherFamilyDescription & @CRLF
      $Output = $Output & "PNPDeviceID: "               & $objItem.PNPDeviceID & @CRLF
      $strPowerManagementCapabilities = $objItem.PowerManagementCapabilities(1)
      $Output = $Output & "PowerManagementCapabilities: " & $strPowerManagementCapabilities & @CRLF
      $Output = $Output & "PowerManagementSupported: "  & $objItem.PowerManagementSupported & @CRLF
      $Output = $Output & "ProcessorId: "               & $objItem.ProcessorId & @CRLF
      $Output = $Output & "ProcessorType: "             & $objItem.ProcessorType & @CRLF
      $Output = $Output & "Revision: "                  & $objItem.Revision & @CRLF
      $Output = $Output & "Role: "                      & $objItem.Role & @CRLF
      $Output = $Output & "SocketDesignation: "         & $objItem.SocketDesignation & @CRLF
      $Output = $Output & "Status: "                    & $objItem.Status & @CRLF
      $Output = $Output & "StatusInfo: "                & $objItem.StatusInfo & @CRLF
      $Output = $Output & "Stepping: "                  & $objItem.Stepping & @CRLF
      $Output = $Output & "SystemCreationClassName: "   & $objItem.SystemCreationClassName & @CRLF
      $Output = $Output & "SystemName: "                & $objItem.SystemName & @CRLF
      $Output = $Output & "UniqueId: "                  & $objItem.UniqueId & @CRLF
      $Output = $Output & "UpgradeMethod: "             & $objItem.UpgradeMethod & @CRLF
      $Output = $Output & "Version: "                   & $objItem.Version & @CRLF
      $Output = $Output & "VoltageCaps: "               & $objItem.VoltageCaps & @CRLF
      if Msgbox(1,"WMI Output",$Output) = 2 then ExitLoop
      $Output=""
   Next
Else
   Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_Processor" )
Endif

*evil grin* ;-)

(Who said that about "Duelling Banjo's" ? :-)

-Sven

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...