Jump to content

Recommended Posts

Posted

In a fit of mentalness MS has decided to require yet another certification on devices to get them to work with Windows 8 instead of just degrading the featureset gracefully. In this case the Play To feature that could push almost any media in your WMP library to a DLNA certified TV on the network was removed. Idiots!!!

 

Anyhow after fishing around a bit I found this Tinkering with uncertified Play To devices on Windows 8 Within Windows where someone has helpfully found a way around it to get this working again on TVs that it worked fine with under 7. It uses powershell to relax the restrictions on device driver installation then allows you to scan for new TVs, add them and then wind up the restrictions again.

 

I have not tried it yet as my W8 machines are not x64 which the script requires at the moment but it looks promising to save Windows 8 from being useless with all my specificly purchased DLNA TVs that worked fine before some sales manager in MS decided to get involved.

 

https://github.com/riverar/playto-tools

 

copied incase the site disappears at any point.

#requires -Version 3.0


function Suspend-CertifiedDeviceChecks
{
   $_unwind = New-Object Collections.Stack


   function Add-ToUnwind()
   {
       param([Parameter(Mandatory = $true)][scriptBlock]$Code)


       $_unwind.Push($Code)
   }


   function Invoke-Unwind()
   {
       if($_unwind.Count -gt 0) {
           $_unwind | % { $_.Invoke() | Out-Null }
       }


       $_unwind.Clear()
   }


   function Test-Administrator()
   {  
       $user = [security.Principal.WindowsIdentity]::GetCurrent()
       (New-Object Security.Principal.WindowsPrincipal $user).IsInRole([security.Principal.WindowsBuiltinRole]::Administrator)  
   }


   if(!(Test-Administrator)) {
       Write-Error "Elevated permissions are required to run this script."
       return
   }


   if(![Environment]::Is64BitProcess) {
       Write-Error "Script requires a 64-bit operating system."
       return
   }


   Add-Type -Name Win32 -Namespace $Null -PassThru -MemberDefinition @"
       [DllImport("kernel32")]
       [return: MarshalAs(UnmanagedType.Bool)]
       public static extern bool WriteProcessMemory(
           IntPtr hProcess,
           IntPtr lpBaseAddress,
           byte[] lpBuffer,
           uint nSize,
           IntPtr lpNumberOfBytesWritten);


       [Flags]
       public enum ProcessAccessFlags
       {
           // ...
           All = 0x001F0FFF
           // ...
       }


       [DllImport("kernel32")]
       public static extern IntPtr OpenProcess(
           uint dwDesiredAccess,
           [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
           uint dwProcessId);


       [DllImport("kernel32")]
       [return: MarshalAs(UnmanagedType.Bool)]
       public static extern bool CloseHandle(
           IntPtr hObject);


       [Flags]
       public enum CreationFlags : uint
       {
           None = 0
       }


       [DllImport("kernel32")]
       public static extern IntPtr CreateRemoteThread(
           IntPtr hProcess,
           IntPtr lpThreadAttributes,
           uint dwStackSize,
           IntPtr lpStartAddress,
           IntPtr lpParameter,
           uint dwCreationFlags,
           IntPtr lpThreadId);


       [Flags]
       public enum AllocationType
       {
            Commit = 0x1000,
            Reserve = 0x2000,
            Decommit = 0x4000,
            Release = 0x8000,
            // ...
       }


       [Flags]
       public enum MemoryProtection
       {
           // ...
           ExecuteReadWrite = 0x40,
           ExecuteWriteCopy = 0x80,
           // ...
       }


       [DllImport("kernel32")]
       public static extern IntPtr VirtualAllocEx(
           IntPtr hProcess,
           IntPtr lpAddress,
           uint dwSize,
           uint flAllocationType,
           uint flProtect);


       [DllImport("kernel32", EntryPoint="GetModuleHandleW")]
       public static extern IntPtr GetModuleHandle(
           [MarshalAs(UnmanagedType.LPWStr)] string lpModuleName);


       [DllImport("kernel32")]
       public static extern IntPtr GetProcAddress(
           IntPtr hModule,
           [MarshalAs(UnmanagedType.LPStr)] string lpProcName);


       [DllImport("kernel32")]
       public static extern uint GetLastError();


       public enum WaitResult
       {
           // ...
           WaitObject0 = 0x0
           // ...
       }


       [DllImport("kernel32")]
       public static extern uint WaitForSingleObject(
           IntPtr hHandle, uint dwMilliseconds);


       [DllImport("kernel32")]
       [return: MarshalAs(UnmanagedType.Bool)]
       public static extern bool VirtualFreeEx(
           IntPtr hProcess,
           IntPtr lpAddress,
           uint dwSize,
           uint dwFreeType);
"@ | Out-Null


   #
   # Find the Device Setup Manager service
   #


   Start-Service DsmSvc


   $svcpid = Get-WmiObject Win32_Service | ? { $_.Name -eq "DsmSvc" } | Select -ExpandProperty ProcessId


   if(!$svcpid) {
      Write-Error "Failed to latch onto the Device Setup Manager service. Is it disabled?"
      return
   }


   $svchandle = [Win32]::OpenProcess([Win32+ProcessAccessFlags]::All, $false, $svcpid)


   if(!$svchandle) {
       Write-Error "Failed to open svchost process."
       return
   }


   Add-ToUnwind { [Win32]::CloseHandle($svchandle) }


   #
   # Load DevPropMgr.dll (and leave it loaded)
   #


   $dll = [Text.Encoding]::Unicode.GetBytes("DevPropMgr.dll")
   $mem = [Win32]::VirtualAllocEx($svchandle, [intPtr]::Zero, $dll.Length, ([Win32+AllocationType]::Reserve -bor [Win32+AllocationType]::Commit),
       [Win32+MemoryProtection]::ExecuteReadWrite)


   if(!$mem) {
       Write-Error "Failed to allocate a chunk of memory in svchost."
       Invoke-Unwind
       return
   }


   Add-ToUnwind { [Win32]::VirtualFreeEx($svchandle, $mem, 0, [Win32]::AllocationType::Release) }


   if(![Win32]::WriteProcessMemory($svchandle, $mem, $dll, $dll.Length, [intPtr]::Zero)) {
       Write-Error "Failed to write to allocated memory in svchost."
       Invoke-Unwind
       return
   }


   $loadlibrary = [Win32]::GetProcAddress([Win32]::GetModuleHandle("kernel32"), "LoadLibraryW")


   if(!$loadlibrary) {
       Write-Error "Failed to locate kernel32!LoadLibraryW, is this a supported OS?"
       Invoke-Unwind
       return
   }


   $thread = [Win32]::CreateRemoteThread($svchandle, [intPtr]::Zero, 0, $loadlibrary, $mem, [Win32+CreationFlags]::None, [intPtr]::Zero)


   if(!$thread) {
       Write-Error "Failed to create remote thread."
       Invoke-Unwind
       return
   }


   if([Win32]::WaitForSingleObject($thread, [TimeSpan]::FromSeconds(10).Milliseconds) -ne [Win32+WaitResult]::WaitObject0) {
       Write-Warning "Remote thread terminated unexpectedly, strangeness may follow."
   }


   #
   # Patch DevPropMgr!_CheckSignature
   #


   $addr = Get-Process -Id $svcpid | Select -ExpandProperty Modules | ? { $_.ModuleName -eq "DevPropMgr.dll" } | Select -ExpandProperty BaseAddress


   if(!$addr) {
       Write-Error "Failed to locate DevPropMgr.dll module in svchost."
       Invoke-Unwind
       return
   }


   # Shelved patch for Windows RT
   # $patchbytes = [byte[]](0x00, 0x25) # armasm: movs r5, #0
   # [Win32]::WriteProcessMemory($svchandle, [intPtr]::Add($addr, 0xEABC), $patchbytes, $patchbytes.Length, [intPtr]::Zero)


   # Patch for Windows 8 x64
   $patchbytes = [byte[]](0x33, 0xDB, 0x85, 0xDB) # x86-64 asm: xor ebx,ebx | test ebx, ebx
   if(![Win32]::WriteProcessMemory($svchandle, [intPtr]::Add($addr, 0x1466B), $patchbytes, $patchbytes.Length, [intPtr]::Zero)) {
       Write-Error "Failed to fiddle with svchost memory."
       Invoke-Unwind
       return
   }


   #
   # Cleanup
   #


   Invoke-Unwind
   Write-Host "OK."
}


function Get-MediaRenderers()
{
   Get-WmiObject Win32_PnPEntity | ? { $_.CompatibleID -Like "*MediaRenderer*" -or $_.CompatibleID -Like "*\MS_*DMR*"  } | Select Name, HardwareID
}


function New-DeviceMetadata()
{


   param(
       [Parameter(ValueFromPipeline = $true, Mandatory = $true)]
       [string]$DeviceId,


       [switch]$Install
   )


   $device = Get-WmiObject Win32_PnPEntity | ? { $_.HardwareID -Contains $DeviceId } | Select Name, Manufacturer, HardwareID


   if(!$device)
   {
       Write-Error "Failed to locate device with specified hardware ID. Is the device on?"
       return
   }
   
   $scratch = "$(([Guid]::NewGuid() | Select -exp Guid).Remove(23))-00000ca710af"


   New-Item $scratch -ItemType Directory | Out-Null
   Copy-Item .\template\* $scratch -Recurse -Force


   $pkginfo = "$scratch\PackageInfo.xml"


   (Get-Content $pkginfo | ForEach {
       $buffer = $_ -replace "{hwid}", [system.Web.HttpUtility]::HtmlEncode("DOID:$($device.HardwareID[0])")
       $buffer = $buffer -replace "{lastmodified}", ([DateTime]::UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"))
       $buffer -replace "{experienceid}", $scratch }) | Out-File $pkginfo -Encoding utf8
   
   $devinfo = "$scratch\DeviceInfo\DeviceInfo.xml"


   (Get-Content $devinfo | ForEach {
       $buffer = $_ -replace "{model}", $device.Name
       $buffer -replace "{manufacturer}", $device.Manufacturer }) | Out-File $devinfo -Encoding utf8


   Get-Item -Path $scratch | New-Cab | Move-Item -Destination ".\$scratch.devicemetadata-ms"   


   if($Install) {
       Copy-Item "$scratch.devicemetadata-ms" "$env:ProgramData\Microsoft\Windows\DeviceMetadataStore\en-US" -Force
   }


   Remove-Item $scratch -Force -Recurse


   Write-Host "OK."
}


function New-Cab()
{
   param(
       [Parameter(ValueFromPipeline=$True, Mandatory=$True)]
       [iO.DirectoryInfo]$Directory,


       [ValidateSet("MSZIP", "LZX")]
       [string]$Algorithm = "MSZIP"
   )


   $uri = New-Object Uri ("$($Directory.FullName)\", [uriKind]::Absolute)
   $files = $Directory.GetFiles("*.*", [iO.SearchOption]::AllDirectories) | % {


       # Each file entry must appear as so:  
       $entry = $($uri.MakeRelativeUri($_.FullName).OriginalString) -replace "/", "\"
       "`"$($_.FullName)`" `"$entry`"`n"
   }


   $guid = "$([Guid]::NewGuid() | Select -exp Guid)"
   $ddf = "$env:Temp\$guid.ddf"


   "
   .Set CabinetNameTemplate=`"$guid.cab`"
   .Set DiskDirectoryTemplate=`"$env:Temp`"
   .Set RptFileName=`"$ddf`:rpt`"
   .Set InfFileName=`"$ddf`:inf`"
   .Set CompressionType=$Algorithm
   $files
   " | New-Item -ItemType File $ddf | Out-Null


   MakeCab /F "$ddf" | Out-Null
   Remove-Item $ddf -Force | Out-Null


   New-Object IO.FileInfo "$env:Temp\$guid.cab"
}

  • Thanks 1
Posted

This reminds me of the Vista debacle where if you tried to send an encrypted HDMI signal from Vista via an AV receiver to a TV it would blank the display with a message basically saying that Vista thought you were trying to rip the image signal to a third party copying device.

The only way around it was to purchase a very popular piece of software (at the time) that unencrypted the HDCP signal before it was sent to the AV receiver. It made the whole concept of using Vista as a media PC out-of-the-box a joke.

They removed this 'functionality' in Windows 7 thankfully.

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



×
×
  • Create New...