PXE Boot Fails and WDS Fails to Start With Event 258 and Error 0xC1030104 After Removing Multicast Service Point Role form an SCCM / ConfigMgr 2007 Distribution Point

During an office-wide Windows 7 OSD migration this weekend we had some workstations downloading extremely slow over multicast. While that is a problem unto itself that may need to be solved at a later date we were down to 8 workstations so I decided to cut multicast off and let them fall back to SMB since SMB downloads on other workstations seemed to be working just fine. It seemed the best way to accomplish this was to simply remove the multicast role from the distribution point. This strategy appeared to work. The workstations did in fact fall back to SMB and the installations completed in a reasonable amount of time.

Of course if that were the end of the story I wouldn’t be writing this now. We tried to PXE boot one last workstation that had failed the night before and found that it couldn’t contact the PXE service point for a boot file. This behavior seemed odd as it was working fine only a few hours ago. Checking the pxecontrol.log showed the following:

adding address to server list [Site System IP]
adding address to server list 127.00.00.01
Sending availiability packet to: [Site System IP]
Sent 274 bytes to [Site System IP]:4011
Recieved Packet 04EC6B38 does not have associated request.
Error validating replies
Sending availiability packet to: 127.0.0.1
Sent 274 bytes to 127.000.000.001:4011
Error receiving replies

A quick inspection of the Windows Deployment Services Server service showed it to be stopped and attempting to manually start the service gave an error.  Checking the event log showed (among other things) Event 258 which looked like this:

An image from the event view showing event 258 with the text The description for Event ID 258 from source WDSIMGSRV cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer. If the event originated on another computer, the display information had to be saved with the event. The following information was included with the event: 0xC1030104

I’ll skip all the boring troubleshooting and cut right to the solution.  To correct the issue:

  • Remove the boot images from the PXE distribution point
  • Remove the PXE service point from the site server
  • Remove the WDS roles from the server
  • Restart (as requested by the role removal)
  • Reinstall the WDS roles on the server
  • Add the PXE service point back to the site server
  • Copy the boot images back to the PXE distribution point (note that this doesn’t take too long because the server will still have the compressed copy of the package so it just has to decompress it)
Advertisement

Error 0x80070490 Running Task Sequence From Run Advertised Programs

Here’s a quick tip.  If you’re getting the errors below in your smsts.log when running a task sequence from Run Advertised Programs it may be because you’ve advertised the task sequence to a user rather than a computer.  Remove the user from the targeted collection, add the computer, and refresh policy and everything should work.

No execution request with PRG_DependentPolicy=FALSE found for advertisement <Advertisement ID>
Error getting running advert info. Code 0x80070490
Error getting package location and access account information. Code 0x80070490
Error initializing TS environment. Code 0x80070490
Task sequence launcher advertisement failed!. Code 0x80070490

Adding a Password to a Single PXE Boot Task Sequence

If you PXE boot for OSD and you need to add a password to your task sequences you can browse to your PXE service point properties, check the box labeled “Require a password for computers to boot using PXE” and enter a password. Any computers booting from that PXE service point will prompt for the password prior to presenting the user with the list of advertised Task Sequences.

PXE Service Point properties page with Require a password for computers to boot using PXE checkbox called out.
Simple enough, but what if you want to add a password to a single task sequence?  One possible solution is to create a script to do the password checking, which I’ve already done for you and you can find at the end of this post, then created a Run Command Line step as the first step in your task sequence that utilizes the script.  The script takes a single argument, the password, and when run prompts the user with a simple input box to enter the password.  If the input password matches the password from the command line the script exits with a success return code and the task sequence continues as normal.  If the user cancels the input or enters a blank password the script exits with a failure return code and the task sequence fails.

Task Sequence showing a Run Command Line step as the first step of the Task Sequence to perform password checking on a single PXE Booted task sequence.
To be fair this script is pretty basic.  It certainly could be expanded upon by masking the password or validating the user against Active Directory.  It also isn’t terribly secure since someone could easily examine the logs and discover the password, but the script suited my needs and it should be good enough for situations where you just want to keep the average user from shooting themself in the foot.

As always, the standard disclaimer applies.  This works for me, it may not work for you.  Use it at your own risk.

TSPass.vbs

“Failed to resolve selected task sequence dependencies. Code(0x80040104)” or “Failed to find CCM_SoftwareDistribution object …” for an OSD Driver Package that is on a Distribution Point

A few months ago while working with a consultant to get OSD up and running in my environment the consultant had mentioned a curious bug he had seen whereby if a driver package version was 1 it would appear to be unavailable to a task sequence.  At the time my test driver packages had been updated a few times so I didn’t think much of it but made a note of it “just in case”.  Fast forward to present day, and after creating some new driver packages my previously functional task sequence all of a sudden started failing.  Checking the SMSTS.log I noted the following:

Getting policy for CCM_SoftwareDistribution[AdvertID="P01201B1", PackageID="P0100187", ProgramID="*"]
FALSE, HRESULT=80040104 (e:\nts_sms_fre\sms\framework\tscore\tspolicy.cpp,2301)
Failed to find CCM_SoftwareDistribution object for AdvertID="P01201B1", PackageID="P0100187", ProgramID="*" (*iTSReference)->Resolve( pTSPolicyManager, dwResolveFlags ), HRESULT=80040104 (e:\nts_sms_fre\sms\framework\tscore\tspolicy.cpp,2862)
m_pSelectedTaskSequence->Resolve( m_pPolicyManager, TS::Policy::TaskSequence::ResolvePolicy | TS::Policy::TaskSequence::ResolveSource, fpCallbackProc, pv, hCancelEvent), HRESULT=80040104 (e:\nts_sms_fre\sms\client\tasksequence\tsmbootstrap\tsmediawizardcontrol.cpp,1208)
Failed to resolve selected task sequence dependencies. Code(0x80040104) 
hrReturn, HRESULT=80040104 (e:\nts_sms_fre\sms\client\tasksequence\tsmbootstrap\tsmediaresolveprogresspage.cpp,408)

A quick investigation revealed that P0100187 was one of my new driver packages.  I had put this package together as I was headed for the door on friday night, had I forgotten to send it to the distribution points?  A quick check of the package status in the Configuration Manager console showed that the package had in fact been distributed.  A little time with Google and the SCCM database led me to the fact that although the package had been created and copied to the distribution points the hash values had not been populated in the database.  The scenario that led to this situation was as follows:

  1. Right click the Drivers node in the SCCM console and choose import
  2. On the Add Drivers To Package step create a new package and uncheck the box to update distribution points
  3. Complete the import of the drivers
  4. Right click the new driver package and choose Manage Distribution Points
  5. In the Manage Distribution Points wizard select Copy the package to new distribution points, and complete the wizard

The package will proceed to replicate to the distribution points normally, however upon completion even though the package appears to be installed correctly in the package status in the console if you examine the SMSPackages table in the database you will see that the Hash and NewHash fields are empty for the new package.  Because the hash fields are empty the MP appears to not return any distribution points for that package when the Task Sequence requests them.  The solution is fairly simple:

  1. Right click the driver package and choose Manage Distribution Points
  2. Choose update all distribution points with a new package source version

The package hash will be calculated and the package will be re-distributed to the distribution points (although since the files are already on the distribution points the actual data transfer is fairly minimal), at which point the Task Sequence will no longer fail searching for the driver package source.  Although it’s nothing more than a guess, I’m betting this is the exact behaviour the consultant was seeing.  Given that the fix causes the package source value to be incremented from 1 to 2 it could appear as if the issue was in fact caused by the package having a source value of 1.

Dell Ships Version 2.0 of the Windows 7 Notebook Combo Driver CAB

If you’re a Dell shop using OSD you’re probably a fan of their one size fits all “Combo Driver CABs”. Dell just released version 2.0 for notebooks which adds support for the new 3rd generation E series (i.e. the Exx20 models). Be aware however, from the notes on the site, it looks like there may be issues with the Nvidia driver with the E6420 / E6520 at the moment.

Using VBScript to Check Partitions for Advanced Format (4K / 512e) Sector Alignment

As you may know Dell recently announced that they will start shipping Advanced Format (4k/512e) drives in their enterprise systems in May 2011.  For those not wanting to follow the links, the cliff’s notes version is that Advanced Format drives use a 4096 byte (4k) sector rather than a 512 byte sector.  This allows higher bit densities by reducing the amount of space tied up in ECC and sector gap.

Old and New Sector Formats Credit: Dougolsen / Wikimedia Commons
Old and New Sector Formats Credit: Dougolsen / Wikimedia Commons

So what’s the big deal then?  Well in order to make the transition, 4K/512e advanced format drives still present themselves externally as a 512 byte per sector drive, and internally lump reads and writes into eight logical 512 byte sectors to match up with their physical 4096 byte sectors.  This has the unfortunate side effect that if your partitions are not aligned to a 4K boundary the disk may have to perform a Read-Modify-Write across two physical sectors.  This process can incur extra latency waiting for an additional rotation of the disk platters which drastically impacts performance.  Further compounding the matter Windows XP/2003 operating systems and most disk management tools create the first partition on the disk starting at LBA sector 63 which if you do your math correctly is not 4K aligned.

Recently the question came up as to whether or not it was possible to use a script to detect partitions that were not 4K aligned and therefore may be causing performance issues, or to perhaps use in an OSD task sequence to halt the OS install if the partition is not correctly aligned.  After some browsing through the WMI classes I found what I was looking for.  The Win32_DiskPartion class has a property StartingOffset that, according to MSDN is in fact the “starting offset (in bytes) of the partition”.  A little modulus division later and you have a simple way to determine if your partition is 4K sector aligned.

Option Explicit

Dim strComputer: strComputer = "."
Dim objWMIService: Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Dim colPartitions: Set colPartitions = objWMIService.ExecQuery("Select * from Win32_DiskPartition",,48)

Dim objPartition
For Each objPartition In colPartitions
    Dim iResult: iResult = objPartition.StartingOffset / 4096
    If iResult = Fix(iResult) Then
        WScript.Echo objPartition.Caption & " is 4K/512e sector aligned."
    Else
        WScript.Echo objPartition.Caption & " is NOT 4K/512e sector aligned."
    End If
Next

There is one caveat I should mention if you’re planning to use this in an OSD task sequence from WinPE.  It seems that the Win32_DiskPartition class has been removed from WinPE 3.x.  Luckily others already have a solution for you.

UPDATE: 5/26/11

Per the request by Eric in the comments I’ve updated the script to show the drive letter associated with the partition. 

Option Explicit

Dim strComputer: strComputer = "."
Dim objWMIService: Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Dim colPartitions: Set colPartitions = objWMIService.ExecQuery("Select * from Win32_DiskPartition",,48)

Dim objPartition

For Each objPartition In colPartitions
    Dim strDriveLetter: strDriveLetter = PartitionToDrive(objWMIService, objPartition.DeviceID)
    Dim iResult: iResult = objPartition.StartingOffset / 4096
    If iResult = Fix(iResult) Then
        WScript.Echo "(" & strDriveLetter & ") " & objPartition.Caption & " is 4K/512e sector aligned."
    Else
        WScript.Echo "(" & strDriveLetter & ") " & objPartition.Caption & " is NOT 4K/512e sector aligned."
    End If
Next

Private Function PartitionToDrive(objWMIService, DeviceID)
    Dim objLogcialDisks: Set objLogcialDisks = objWMIService.ExecQuery( _
    "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" & DeviceID & _
    "'} WHERE AssocClass = Win32_LogicalDiskToPartition")

    Dim objLogicalDisk
    For Each objLogicalDisk In objLogcialDisks
        PartitionToDrive = objLogicalDisk.DeviceID
        Exit Function
    Next

    PartitionToDrive = ""
End Function