Cleaning computer cooling system to improve performance

While using a laptop computer I noticed high noise levels, caused by the cooling fan.

I decided to check the CPU temperatures using HWMonitor.

The idle temperatures were around 70° C.

And load temperatures were around 85°-94° C.

 

These temperatures could be high enough to cause thermal throttling, which would affect system performance.

Therefore I measured performance with 7-Zip and CPU-Z benchmarks.

 

I decided to disassemble the laptop computer and clean the cooling system, using compressed air.

(Be aware that most compressed air cans contain harmful chemicals, so use them outside or in a well ventilated area)

 

Cleaning the cooling system had a significant effect.

Now idle temperatures were much lower, around 55° C.

And load temperatures were also lower, around 74°-85° C.

Also noticed much lower fan speeds, so the computer wasn’t as noisy as before.

 

Table of thermal readings:

Idle Load
Before cleaning 70° C 85°-94°
After cleaning 55° C 74°-85° C
Improvement 15° C 9°-11° C

 

The system had been affected by thermal throttling, because the 7-Zip and CPU-Z benchmarks improved.

 

Table of benchmark results:

7-Zip score CPU-Z single CPU-Z multi
Before cleaning 12491 1321 4572
After cleaning 16572 1510 5494
Improvement 32,6% 14,3% 20,2%

 

Conclusion

It can be relevant to clean a computers cooling system.

It may improve noise levels, temperatures and performance.

Examining UNEXPECTED_KERNEL_MODE_TRAP (7f) BSOD with WinDbg

Recently one of my computers was performing slowly and I decided to close some programs.

When closing all Windows explorers the computer crashed with a BSOD

 

After reboot this message was displayed:

windows_has_recovered_from_an_unexpected_shutdown_bsod_7f_08

Windows has recovered from an unexpected shutdown

Problem signature:
Problem Event Name:    BlueScreen
OS Version:    6.1.7601.2.1.0.768.3
Locale ID:    1030

Additional information about the problem:
BCCode:    7f
BCP1:    0000000000000008
BCP2:    0000000080050031
BCP3:    00000000000006F8
BCP4:    FFFFF9600025C28C
OS Version:    6_1_7601
Service Pack:    1_0
Product:    768_1

 

A similar message was logged in Event Viewer:

Log Name:      System
Source:        Microsoft-Windows-WER-SystemErrorReporting
Event ID:      1001
Task Category: None
Level:         Error
Keywords:      Classic
Description:
The computer has rebooted from a bugcheck.  The bugcheck was: 0x0000007f (0x0000000000000008, 0x0000000080050031, 0x00000000000006f8, 0xfffff9600025c28c). A dump was saved in: C:\Windows\MEMORY.DMP.

 

Decided to examine this further, so started WinDbg (x64) and opened:

C:\Windows\Memory.dmp

This message was displayed:

BugCheck 7F, {8, 80050031, 6f8, fffff9600025c28c}

 

Checked for more details with:

!analyze -v

Part of the result:

*****************************************************************
*                                                               *
*                      Bugcheck Analysis                        *
*                                                               *
*****************************************************************

UNEXPECTED_KERNEL_MODE_TRAP (7f)
This means a trap occurred in kernel mode, and it's a trap of a kind
that the kernel isn't allowed to have/catch (bound trap) or that
is always instant death (double fault).  The first number in the
bugcheck params is the number of the trap (8 = double fault, etc)
Consult an Intel x86 family manual to learn more about what these
traps are. Here is a *portion* of those codes:
If kv shows a taskGate
use .tss on the part before the colon, then kv.
Else if kv shows a trapframe
use .trap on that value
Else
.trap on the appropriate frame will show where the trap was taken
(on x86, this will be the ebp that goes with the procedure KiTrap)
Endif
kb will then show the corrected stack.
Arguments:
Arg1: 0000000000000008, EXCEPTION_DOUBLE_FAULT
Arg2: 0000000080050031
Arg3: 00000000000006f8
Arg4: fffff9600025c28c

 

Decided to search online for: UNEXPECTED_KERNEL_MODE_TRAP (7f) exception double fault

And found this article: Bug Check 0x7F: UNEXPECTED_KERNEL_MODE_TRAP

 

It mentioned that a common cause for this error was kernel stack overflow.

So I checked the stack usage with:

!stackusage

The result was:

Stack Usage By Function
===================================================================

Size     Count  Module
0x00001500        14  win32k!xxxDesktopWndProcWorker
0x00000DD0        13  win32k!xxxInterSendMsgEx
0x00000D20        14  win32k!xxxReceiveMessage
0x000009C0        13  win32k!xxxRealSleepThread
0x000008F0        13  win32k!xxxSendMessageTimeout
0x000004E0        13  win32k!xxxBeginPaint
0x00000410        13  win32k!xxxSendNCPaint
0x00000400         2  win32k!RGNOBJAPI::bSubtractComplex
0x00000380         1  win32k!CalcVisRgnWorker
0x000002A0        14  win32k!xxxDesktopWndProc
0x00000270        13  win32k!xxxSleepThread
0x000000E0         1  win32k!xxxRealInternalGetMessage
0x00000090         1  win32k!xxxHandleDesktopMessages
0x00000090         1  win32k!GetDCEx
0x00000080         1  win32k!xxxDesktopThread
0x00000080         1  win32k!RGNOBJAPI::bSubtract
0x00000060         1  win32k!xxxBeginPaint
0x00000050         1  win32k!GreSubtractRgnRectList
0x00000040         1  win32k!xxxInternalGetMessage
0x00000030         1  win32k!xxxCreateSystemThreads
0x00000030         1  win32k!CalcVisRgn
0x00000030         1  win32k!NtUserCallNoParam

Total Size: 0x00005CA0


Stack Usage By Module
===================================================================

Size     Count  Module
0x00005CA0       134  win32k

Total Size: 0x00005CA0

 

Noticed that 0x5CA0 = 23712 bytes is very close to the 24K kernel stack limit for 64-bit Windows.

The most likely cause for the BSOD was indeed kernel stack overflow.

 

Examined the call stack with:

kf

Part of the result:

#   Memory  Child-SP          RetAddr           Call Site
00           fffff800`0449ed28 fffff800`030889e9 nt!KeBugCheckEx
01         8 fffff800`0449ed30 fffff800`03086eb2 nt!KeSynchronizeExecution+0x3d39
02       140 fffff800`0449ee70 fffff960`0025c28c nt!KeSynchronizeExecution+0x2202
03   20f4110 fffff880`06592f80 fffff960`0025c1c1 win32k!RGNOBJAPI::bSubtractComplex+0x44
04       400 fffff880`06593380 fffff960`001d3379 win32k!RGNOBJAPI::bSubtract+0x871
05        80 fffff880`06593400 fffff960`0014d7c4 win32k!GreSubtractRgnRectList+0x49
06        50 fffff880`06593450 fffff960`000c5c47 win32k!CalcVisRgnWorker+0x314
07       380 fffff880`065937d0 fffff960`000d23be win32k!CalcVisRgn+0x97
08        30 fffff880`06593800 fffff960`00056cf6 win32k!GetDCEx+0x50e
09        90 fffff880`06593890 fffff960`0009ede7 win32k!xxxBeginPaint+0x192
0a        60 fffff880`065938f0 fffff960`0009ead5 win32k!xxxDesktopWndProcWorker+0x2f7
0b       180 fffff880`06593a70 fffff960`00094013 win32k!xxxDesktopWndProc+0x55
0c        30 fffff880`06593aa0 fffff960`000def3f win32k!xxxReceiveMessage+0x6cb

 

Noticed the very large stack frame difference at:

win32k!RGNOBJAPI::bSubtractComplex+0x44

 

Examined details about win32k.sys with:

lmDvm win32k

Part of the result:

Image path: \SystemRoot\System32\win32k.sys
Image name: win32k.sys
Timestamp:        Mon Sep 12 22:37:06 2016 (57D711F2)
CheckSum:         00314AE8
ImageSize:        00326000
File version:     6.1.7601.23545
Product version:  6.1.7601.23545
File flags:       0 (Mask 3F)
File OS:          40004 NT Win32
File type:        3.7 Driver
File date:        00000000.00000000
Translations:     0409.04b0
CompanyName:      Microsoft Corporation
ProductName:      Microsoft® Windows® Operating System
InternalName:     win32k.sys
OriginalFilename: win32k.sys
ProductVersion:   6.1.7601.23545
FileVersion:      6.1.7601.23545 (win7sp1_ldr.160912-1137)
FileDescription:  Multi-User Win32 Driver
LegalCopyright:   © Microsoft Corporation. All rights reserved.

 

Noticed that win32k.sys had been updated recently.

Knowing that win32k.sys interacts with the graphics driver, I decided to update this to the latest version.

Recommending heatsink for Raspberry Pi 3

When experimenting with a Raspberry Pi 3 I noticed that the CPU could get pretty warm.

I decided to measure the temperature during idle and load with:

cat /sys/class/thermal/thermal_zone0/temp

And load tested the CPU with 7-zip benchmark:

7zr b

 

Measured these temperatures:

Idle Load
Without heatsink 50-52 °C 77-79 °C
With heatsink 47-49 °C 65-67 °C
Improvement 3 °C 12 °C

 

I used a small aluminium heatsink with thermal tape:

raspberry_pi_3_with_heatsink

 

Conclusion

The 12 degree reduction in load temperature is well worth the effort.

It should prevent thermal throttling and thereby ensure optimal performance.

Linux hang at boot due to authentication problems with Samba mount in /etc/fstab

A Raspberry Pi 3 had a problem after I had performed a number of system changes.

When booting it would hang for around 2 minutes showing:

systemd-hostnamed.service

 

I examined system messages from the boot process with:

dmesg

Part of the result was:

[   98.748722] CIFS VFS: Send error in SessSetup = -13
[   98.749092] CIFS VFS: cifs_mount failed w/return code = -13
[  125.427742] usb 1-1.5.2.3: reset high-speed USB device number 9 using dwc_otg
[  188.946712] Status code returned 0xc000006d NT_STATUS_LOGON_FAILURE

 

I remembered that I had experimented with various ways to mount a Samba share in: /etc/fstab

This didn’t work because of authentication problems and (as a side effect) it delayed startup significantly.

 

I decided to solve the problem by:

1. Removing the non-functional line from /etc/fstab

2. Creating a script to be run on demand:

mount_RPServer_shared.sh

With content similar to this:

#/bin/bash
sudo mount -t cifs -o user=pi //server/shared /mnt/server_shared/

 

The script relies on the mount.cifs command.

For Debian based Linux distributions this is part of the cifs-utils package.

Unattended Windows setup may fail due to long computer name

While testing unattended Windows deployment I encountered another problem.

After the first installation reboot, Windows setup would fail with the error message:

Windows could not parse or process unattend answer file [C:\Windows\Panther\unattend.xml] for pass [specialize]. The answer file is invalid.

 

When closing the dialogbox the computer restarted.

 

Then it failed with this error message:

The computer restarted unexpectedly or encountered an unexpected error. Windows instalation cannot proceed. To install Windows, click "OK" to restart the computer, and then restart the installation.

 

Started troubleshooting by booting into Windows PE.

Started examining the log files under:

C:\Windows\Panther

 

Found these error messages in setupact.log:

IBS    The provided unattend file is not valid; hrResult = 0x80220005
IBS    Callback_Unattend_InitEngine:The provided unattend file [C:\Windows\Panther\unattend.xml] is not a valid unattended Setup answer file; hr = 0x1, hrSearched = 0x1, hrDeserialized = 0x0, hrImplicitCtx = 0x0, hrValidated = 0x1, hrResult = 0x80220005
IBS    UnattendErrorFromResults: Error text = Windows could not parse or process unattend answer file [C:\Windows\Panther\unattend.xml] for pass [specialize]. The answer file is invalid.
IBS    Callback_Unattend_InitEngine:An error occurred while finding/loading the unattend file; hr = 0x1, hrResult = 0x80220005

 

This didn’t reveal the exact cause of the error, but it inspired me to examine unattend.xml.

I transferred unattend.xml to my work computer and then tried opening the unattend.xml file with Windows System Image Manager.

 

However this failed with:

windows_sim_validation_error_waspassprocessed_attribute_is_not_declared

Validation error on D:\ToBeDeleted\Fail_Info\Panther\unattend.xml, line 18, column 32.

Details: The 'wasPassProcessed' attribute is not declared.

 

Opened the unattend.xml file in an editor and removed all instances of:

 wasPassProcessed="true"

 

After that the file could be opened in Windows SIM, which now displayed the real error:

The 'ComputerName' element is invalid - The value 'DeployTestPhysical' is invalid according to its datatype 'ComputerNameType' - The actual length is greater than the MaxLength value.

 

So the problem was that computer name was too long…

 

The unattend.xml file was modified by a custom program just before deployment on the target computer.

This custom program did not prevent computer names longer than 15 characters.

The problem was fixed by updating the custom program.

Conclusion

Special care should be taken when modifying unattend.xml by scripts or programs.

An invalid unattend.xml file may cause problems during Windows setup, which are not immediately obvious.

Unattended Windows setup may fail due to wrongly encoded password

While testing unattended Windows deployment I encountered a problem.

After the first installation reboot, Windows setup would fail with an empty dialog box:

install_windows_empty

 

Followed by the error message:

install_windows_windows_could_not_complete_the_installation

Windows could not complete the installation. To install Windows on this computer, restart the installation.

 

Then the machine would countinually reboot and show the last message.

 

Started troubleshooting by booting into Windows PE.

Then examined setuperr.log and setupact.log under:

C:\Windows\Panther\

However these files contained no useful clues.

 

I checked the other files left by Windows setup, and examined the files under:

C:\Windows\Panther\UnattendGC\

Found this in setuperr.log:

[oobeldr.exe] [Action Queue] : Unattend action failed with exit code 4
[oobeldr.exe] Execution of unattend GCs failed; hr = 0x0; pResults->hrResult = 0x8030000b
[oobeldr.exe] User input error was detected in unattend file. Error: [0x0]

[windeploy.exe] Command [%windir%\system32\oobe\oobeldr.exe /system] failed with exit code [0x8030000b]
[windeploy.exe] Failure occured during online installation.  Online installation cannot complete at this time.; hr = 0x8030000b

 

But it was a warning in setupact.log which revealed the cause behind the error:

[Shell Unattend] Failed to decode password (0x8007000d)

 

My initial understanding of the user password format in AutoUnattend.xml turned out to be wrong.

This problem was not discovered by Windows System Image Manager, because AutoUnattend.xml was updated just before deployment by a custom program on the target computer.

 

Local user passwords are encoded like this in AutoUnattend.xml:

1. Text is initially encoded as unicode / UTF-16.

2. Then a “Password” string is appended to the password.
Example: The password “1234” is represented as “1234Password”

3. Finally the password string is base64 encoded.

Running .NET programs under Windows PE

Windows PE can be modified to include PowerShell as well as .NET like described here:

https://msdn.microsoft.com/en-us/windows/hardware/commercialize/manufacture/desktop/winpe-adding-powershell-support-to-windows-pe

 

Windows PE is limited to running one type of executable (either x86, AMD64 or ARM), depending on the type of Windows PE image.

This also affects .NET applications.

 

.NET programs compiled for any CPU may fail on AMD64 versions of Windows PE with:

The subsystem needed to support the image type is not present.

 

This can happen if the “Prefer 32-bit” build option is set, which is the default for some project types with Visual Studio 2015.

 

The solution is either to remove the “Prefer 32-bit” option before compiling.

vs_build_deselect_prefer_32-bit

 

Or using corflags to remove any 32-bit flags with:

corflags program.exe /32BITREQ- /32BITPREF-

Problems when reusing AutoUnattend.xml with new Windows image

I recently experienced problems when reusing AutoUnattend.xml, after having upgraded the Windows image:

From: Windows 10 Enterprise 2015 LTSB

To: Windows 10 Enterprise 2016 LTSB

 

The unattended installation would start and run, but eventually failed with:

windows_setup_windows_could_not_apply_unattend_settings_during_pass_offlineservicing

Windows could not apply unattend settings during pass [offlineServicing].

 

Examined the installation logfiles under:

\$WINDOWS.~BT\Sources\Panther

 

setuperr.log only contained:

2016-10-20 15:20:20, Error      [0x0606ae] IBS    [SetupCl library] Required profile hive does not exist: [\??\D:\WINDOWS\system32\config\systemprofile\NTUSER.DAT].
2016-10-20 15:20:37, Error      [0x0604a7] IBS    InstantiateCBSUnattendPass: dism.exe returned with failing exit code -2146498555
2016-10-20 15:20:37, Error      [0x060431] IBS    Callback_UnattendInitiatePass: An error occurred while initiating unattend passes; hr = 0x80004005

 

setupact.log contained no additional useful information.

 

However cbs_unattend.log contained an explanation:

2016-10-20 15:20:36, Error                 DISM   DISM Package Manager: PID=2348 TID=2368 Failed opening package Microsoft-Windows-Foundation-Package~31bf3856ad364e35~amd64~~10.0.10240.16384. - CDISMPackageManager::Internal_CreatePackageByName(hr:0x800f0805)
2016-10-20 15:20:36, Error                 DISM   DISM Package Manager: PID=2348 TID=2368 Failed to get the underlying cbs package. - CDISMPackageManager::OpenPackageByName(hr:0x800f0805)
2016-10-20 15:20:36, Error                 DISM   DISM Package Manager: PID=2348 TID=2368 The specified package is not valid Windows package. - GetCbsErrorMsg

 

I wondered why the Microsoft-Windows-Foundation-Package could not be opened, so I went back to Windows System Image Manager.

windows_system_image_manager_unknown_package

There I noticed that the package was unknown, because the version numbers had changed.

Be aware that I had run: Tools -> Validate Answer File

(Which did not show warnings about this)

 

Added the new Microsoft-Windows-Foundation-Package

Then copied all the settings

After verifying that all settings had been copied, I deleted the unknown package.

(It would probably have been easier to update the version number in AutoUnattend.xml, which I recommend trying first)

 

Then ran: Tools -> Validate Answer File

Which now showed these warnings:

Windows Feature is enabled but one or more of its dependencies have not been enabled in the answer file.

Packages/Foundation/amd64_Microsoft-Windows-Foundation-Package_10.0.14393.0__31bf3856ad364e35_/Client-DeviceLockdown/Client-EmbeddedBootExp
Packages/Foundation/amd64_Microsoft-Windows-Foundation-Package_10.0.14393.0__31bf3856ad364e35_/Client-DeviceLockdown/Client-EmbeddedLogon
Packages/Foundation/amd64_Microsoft-Windows-Foundation-Package_10.0.14393.0__31bf3856ad364e35_/Client-DeviceLockdown/Client-EmbeddedShellLauncher

 

I was challenged by this until I found the answer here:

http://blog.theatticnetwork.net/2014/08/windows-unattend-file-notes/

 

I had to right-click the feature in question and choose: Enable Parent Features

windows_system_image_manager_enable_parent_features

 

After making these changes new configuration sets / deployment images could be installed successfully.

Conclusion

When reusing AutoUnattend.xml with a new Windows image, please look for unknown packages in Windows SIM in addition to validating the answer file.

If any unknown packages are found, please update the version numbers in AutoUnattend.xml.

Debugging failing SSRS report caused by read-only report parameter

I recently experienced problems when trying to view a report for SQL Server Reporting Services with ReportViewer for MVC.

 

The report worked in some cases, but failed when certain parameters were set.

Exception and stack trace:

[ReportServerException: The report parameter 'DeviceTypes' is read-only and cannot be modified. (rsReadOnlyReportParameter)]
Microsoft.Reporting.WebForms.ServerReportSoapProxy.OnSoapException(SoapException e) +155
Microsoft.Reporting.WebForms.Internal.Soap.ReportingServices2005.Execution.ProxyMethodInvocation.Execute(RSExecutionConnection connection, ProxyMethod`1 initialMethod, ProxyMethod`1 retryMethod) +1256
Microsoft.Reporting.WebForms.Internal.Soap.ReportingServices2005.Execution.RSExecutionConnection.SetExecutionParameters(ParameterValue[] Parameters, String ParameterLanguage) +370
Microsoft.Reporting.WebForms.SoapReportExecutionService.SetExecutionParameters(IEnumerable`1 parameters, String parameterLanguage) +530
Microsoft.Reporting.WebForms.ServerReport.SetParameters(IEnumerable`1 parameters) +896
Microsoft.Reporting.WebForms.Report.SetParameters(ReportParameter parameter) +136
ReportViewerForMvc.ReportExtensions.SetParameters(Report report, ReportParameterInfoCollection collection) +114
ReportViewerForMvc.ReportViewerExtensions.SetProperties(ServerReport serverReport, ServerReport properties) +84
ReportViewerForMvc.ReportViewerExtensions.SetProperties(ReportViewer reportViewer, ReportViewer properties) +117
ReportViewerForMvc.ReportViewerWebForm.BuildReportViewer() +92
System.Web.UI.Control.OnLoad(EventArgs e) +109
System.Web.UI.Control.LoadRecursive() +68
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +4498

 

Checked the ReportServerService__*.log and ExecutionLog* database views, but they contained no additional clues about the error.

 

I attached WinDbg (x64) to the IIS worker process (w3wp.exe) and set a breakpoint with:

!bpmd   ReportViewerForMvc.dll   ReportViewerForMvc.ReportExtensions.SetParameters

Messages from WinDbg:

Found 2 methods in module 00007ff9bde79bb0...
MethodDesc = 00007ff9c00a30d0
MethodDesc = 00007ff9c00a30e0
Setting breakpoint: bp 00007FF9C0EE5590 [ReportViewerForMvc.ReportExtensions.SetParameters(Microsoft.Reporting.WebForms.Report, Microsoft.Reporting.WebForms.ReportParameterInfo)]
Setting breakpoint: bp 00007FF9C0EE53E4 [ReportViewerForMvc.ReportExtensions.SetParameters(Microsoft.Reporting.WebForms.Report, Microsoft.Reporting.WebForms.ReportParameterInfoCollection)]
Adding pending breakpoints...

 

Continued exection, reloaded the report and the breakpoint was hit.

Checked the .NET call stack with:

!clrstack -a

Part of the result:

OS Thread Id: 0x273c (45)
Child SP               IP Call Site
00000007dba9d030 00007ff9c0ee53e4 ReportViewerForMvc.ReportExtensions.SetParameters(Microsoft.Reporting.WebForms.Report, Microsoft.Reporting.WebForms.ReportParameterInfoCollection)
PARAMETERS:
report (<CLR reg>) = 0x0000000390e93650
collection (<CLR reg>) = 0x0000000490886678

 

Examined the collection object with:

!DumpObj /d 0000000490886678

Result:

Name:        Microsoft.Reporting.WebForms.ReportParameterInfoCollection
MethodTable: 00007ff9bff1cc98
EEClass:     00007ff9bff08d40
Size:        32(0x20) bytes
File:        C:\Windows\assembly\GAC_MSIL\Microsoft.ReportViewer.WebForms\11.0.0.0__89845dcd8080cc91\Microsoft.ReportViewer.WebForms.dll
Fields:
MT    Field   Offset                 Type VT     Attr            Value Name
00007ffa1b23d408  40017fa        8 ...Canon, mscorlib]]  0 instance 00000004908823f0 list
00007ffa1b8de068  40017fb       10        System.Object  0 instance 0000000000000000 _syncRoot

 

Examined the list array with:

!DumpArray /d 00000004908823f0

Result:

Name:        Microsoft.Reporting.WebForms.ReportParameterInfo[]
MethodTable: 00007ff9c0fd9e60
EEClass:     00007ffa1b2f0f10
Size:        120(0x78) bytes
Array:       Rank 1, Number of elements 12, Type CLASS
Element Methodtable: 00007ff9bff1cbc0
[0] 00000004908826c8
[1] 00000004908829d8
[2] 0000000490882ce8
[3] 00000004908832e0
[4] 0000000490884490
[5] 00000004908847a8
[6] 0000000490884ac0
[7] 0000000490884e38
[8] 00000004908853f8
[9] 0000000490885818
[10] 0000000490886250
[11] 00000004908865c8

 

Examined details for the list array with:

!DumpArray /d -details 00000004908823f0

Part of the result:

[11] 00000004908865c8
Name:        Microsoft.Reporting.WebForms.ReportParameterInfo
MethodTable: 00007ff9bff1cbc0
EEClass:     00007ff9bff08cc8
Size:        104(0x68) bytes
File:        C:\Windows\assembly\GAC_MSIL\Microsoft.ReportViewer.WebForms\11.0.0.0__89845dcd8080cc91\Microsoft.ReportViewer.WebForms.dll
Fields:
MT    Field   Offset                 Type VT     Attr            Value Name
00007ffa1b8dda88  4000120        8            System.String      0     instance     0000000490881950     m_name
00007ff9bff1c678  4000121       50             System.Int32      1     instance                    4     m_dataType
00007ffa1b8cd6f8  4000122       58           System.Boolean      1     instance                    0     m_isNullable
00007ffa1b8cd6f8  4000123       59           System.Boolean      1     instance                    1     m_allowBlank
00007ffa1b8cd6f8  4000124       5a           System.Boolean      1     instance                    1     m_isMultiValue
00007ffa1b8cd6f8  4000125       5b           System.Boolean      1     instance                    1     m_isQueryParameter
00007ffa1b8dda88  4000126       10            System.String      0     instance     000000038e411420     m_prompt
00007ffa1b8cd6f8  4000127       5c           System.Boolean      1     instance                    0     m_promptUser
00007ffa1b8cd6f8  4000128       5d           System.Boolean      1     instance                    1     m_areDefaultValuesQueryBased
00007ffa1b8cd6f8  4000129       5e           System.Boolean      1     instance                    1     m_areValidValuesQueryBased
00007ffa1b8dda88  400012a       18            System.String      0     instance     0000000000000000     m_errorMessage
00007ff9c0fda240  400012b       20     ...Viewer.WebForms]]      0     instance     0000000490886320     m_validValues
00007ffa1b23d128  400012c       28     ...tring, mscorlib]]      0     instance     0000000490886658     m_currentValues
00007ff9bff1c7c8  400012d       54             System.Int32      1     instance                    0     m_state
00007ff9bff1cc98  400012e       30     ...terInfoCollection      0     instance     0000000490886fb8     m_dependencyCollection
00007ff9bff1cc98  400012f       38     ...terInfoCollection      0     instance     0000000000000000     m_dependentsCollection
00007ffa1b8c1480  4000130       40          System.String[]      0     instance     0000000490881bb8     m_dependencies
00007ff9c0fda5d0  4000131       48     ...Viewer.WebForms]]      0     instance     0000000490886630     m_dependentsCollectionConstruction
00007ffa1b8cd6f8  4000132       5f           System.Boolean      1     instance                    1     m_visible

 

Examined the name of the last report parameter with:

!DumpObj /d 0000000490881950

Part of the result:

Name:        System.String
MethodTable: 00007ffa1b8dda88
EEClass:     00007ffa1b236a08
Size:        48(0x30) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      DeviceTypes

So the last parameter was DeviceTypes, the one causing the problem.

 

Looked for a read-only property among the report parameters. Noticed that m_promptUser was 0 for the DeviceTypes parameter, while m_promptUser was 1 for all other parameters.

 

I decided to use procdump to log exception messages from the ReportingServicesService.exe process with:

procdump.exe -f "" -l -e 1 ReportingServicesService.exe

 

Reloaded the report to recreate the error.

Part of the result was:

[07:10:37] Exception: E0434F4D.Microsoft.ReportingServices.Diagnostics.Utilities.ReadOnlyReportParameterException ("The report parameter 'DeviceTypes' is read-only and cannot be modified.")
[07:10:37] Exception: E0434F4D.Microsoft.ReportingServices.Diagnostics.Utilities.RSException ("The report parameter 'DeviceTypes' is read-only and cannot be modified.")

 

Then loaded all DLL files from SSRS into ILSpy from:

C:\Program Files\Microsoft SQL Server\MSRS11.MSSQLSERVER\Reporting Services\ReportServer\bin

 

Searched for the ReadOnlyReportParameterException class in ILSpy.

Found it and noticed that it was apparently only used by:

Microsoft.ReportingServices.ReportProcessing.ParameterInfoCollection.Combine(...)

 

Read the decompiled code for the above method and noticed this part:

if (checkReadOnly && !parameterInfo.PromptUser)
{
  ParameterInfoCollection.ThrowReadOnlyParameterException(parameterInfo.Name, isSharedDataSetParameter);
}

Apparently the value of parameterInfo.PromptUser determined the read-only status.

 

I decided to examine the XML for the RDL report and noticed that the DeviceTypes report parameter did not have a Prompt section.

I added this:

<Prompt>DeviceTypes</Prompt>

Then uploaded the new version of the report (by overwriting).

However this did not seem to have any immediate effect, the error still occured…

 

I spent some time examining various other ideas and internals of SSRS.

 

Then I got an idea: I decided to delete the problematic report and then recreate the modified version with a Prompt section.

This fixed the problem! The report now worked in all cases, no matter which parameters were set.

This behavior was consistent across 2 SSRS instances.

Conclusion

It seems that read-only status for a report parameter is derived from the presence of a <Prompt>Description</Prompt> section.

However this status is not updated if the report is overwritten, it has to be deleted and then recreated…

 

Due to the way ReportViewerForMvc.dll is implemented all report parameters are copied from the initial instance to another instance of ReportViewer.

This means that report parameters can’t be read-only, so <Prompt>Description</Prompt> should always be specified for all report parameters, when using ReportViewer for MVC.

Separate, physical trackpoint buttons on Lenovo Thinkpad T440p

The Lenovo Thinkpad T440p (and other models of that generation) is delivered with a touchpad, without separate physical left, middle and right buttons.

Instead the entire pad clicks and reacts depending on the area touched.

 

In my subjective opinion these buttons feel spongy and imprecise.

In use it’s common to make mistakes by clicking another button than expected.

This makes the laptop less productive and frustrating to use.

 

However it’s possible to replace the touchpad with the one from the Lenovo Thinkpad T450, which has 3 separate, physical trackpoint buttons.

thinkpad_t440p_with_t450_trackpad

 

The first challenge is getting the right replacement part, with the dimensions 10 cm x 7,5 cm.

thinkpad_t440p_clickpad_horizontal

thinkpad_t440p_clickpad_vertical

It’s not available as a separate part from Lenovo, but is sold as part of the keyboard bezel.

The part number I found and used was: 00HN550

 

Be careful with online sellers claiming to sell touchpads that fit a long range of Thinkpad models.

They may fit electrically, but possibly not physically.

If you are considering performing this replacement, please verify that the part fits your particular Thinkpad model.

 

The next challenge is to disassemble the laptop and performing the replacement.

I refer to the hardware maintenance manual and online guides.

 

The final challenge is to solve driver problems on Windows.

The hardware ID for the touchpad is on the motherboard, which remains unchanged.

The default Synaptics Pointing Device drivers are not compatible and won’t work.

 

Simplest way to solve the driver problems on Windows:

1. Connect a USB mouse, because the trackpoint won’t work reliably until these steps have been completed.

2. Uninstall the Synaptics Pointer Device drivers using Programs and Features.

3. Restart the computer.

4. Remove any remaining Synaptics components by opening Control Panel -> Mouse

If asked: Do you want to uninstall the Synaptics driver now?

Then select yes and OK to the following dialogs:

synaptics_driver_uninstall1

synaptics_driver_uninstall2

synaptics_driver_uninstall3

5. Restart the computer.

6. Now the trackpoint and 3 physical buttons should work with a default mouse driver.

(Be aware that I have disabled the rest of the touchpad, so I don’t know if it works with the default mouse driver)

 

With Windows 10 extra steps are needed, because it can automatically install incompatible drivers.

This can be prevented by downloading and running the “Show or hide updates” program (wushowhide.diagcab) from:

https://support.microsoft.com/en-us/kb/3073930?utm_source=twitter

 

1. Click: Advanced

disable_driver_updates1

2. Deselect: Apply repairs automatically

disable_driver_updates2

3. Click: Next

4. Click: Hide updates

disable_driver_updates3

5. Select: Synaptics – Pointing Drawing – Synaptics Pointing Device

disable_driver_updates4

6. Click: Next

7. Confirm by clicking: Next

disable_driver_updates5

8. Click: Close the troubleshooter

disable_driver_updates6

 

Be aware that fully compatible drivers can be downloaded and installed from Lenovo, which will enable full touchpad functionality.

However I’m currently satisfied with a trackpoint and 3 physical buttons, so I have not found the correct drivers or procedure yet.