' //*************************************************************************** ' // ***** Script Header ***** ' // ' // Solution: Microsoft Deployment Toolkit ' // File: PXEFilter.vbs ' // ' // Purpose: Decide what needs to be done for each PXE requests received ' // by WDS. If not present in the ConfigMgr database, add it. ' // ' // Usage: (loaded automatically by Microsoft.BDD.PXEFilter DLL) ' // ' // Microsoft Solution Version: 4.1.501 ' // Microsoft Script Version: 4.1.501 ' // Customer Build Version: 1.0.0 ' // Customer Script Version: 1.0.0 ' // ' // Microsoft History: ' // 4.0.501 MTN 02/19/2008 Added header, additional logging, advertisement ' // verification for every request. ' // ' // Customer History: ' // ' // ***** End Header ***** ' //*************************************************************************** '//---------------------------------------------------------------------------- '// '// Set global variables, used by the ZTIProcess function below. (Note that '// any changes to this script will require restarting the WDS service, since '// the script is only loaded once and kept in memory as long as the service '// is running.) '// '// If ConfigMgr is running on the same server as WDS, the sProviderServer '// value can be left blank and the sUsername and sPassword values must be '// blank. '//---------------------------------------------------------------------------- Option Explicit Dim sProviderServer Dim sSiteCode Dim sNamespace Dim sUsername Dim sPassword Dim sCollection sProviderServer = "SRV-HQ-1" sSiteCode = "MAZ" sNamespace = "root\sms\site_" & sSiteCode sUsername = "" sPassword = "" sCollection = "MAZ0000D" ' This must be a collection ID, not a collection name '//---------------------------------------------------------------------------- '// Main routine '//---------------------------------------------------------------------------- ZTIProcess Function ZTIProcess Dim sMacAddress Dim sIPAddress Dim sUUID Dim sNetBiosName Dim oLocator Dim oSMS Dim sQuery Dim bFound Dim iResourceID Dim re Dim oSite Dim oParams Dim oResult Dim oLastError Dim oClients Dim oClient Dim oCollection Dim oNewRule Dim oAdvertisement Dim bTrying Dim sAdvert Dim i ' Initialization sMacAddress = PXE.MacAddress sIPAddress = PXE.IPAddress sUUID = PXE.UUID Set re = New RegExp re.Pattern = ":" re.Global = true 'sNetBiosName = "MAC" & re.Replace(sMacAddress, "") ' Clear invalid UUID values If sUUID = "00000000-0000-0000-0000-000000000000" or sUUID = "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF" then sUUID = "" End if ' Log details PXE.LogTrace "Processing request from MAC address = " & sMacAddress & ", IP address = " & sIPAddress & ", UUID = " & sUUID '//---------------------------------------------------------------------------- '// Filter requests. This may need to be customized if you only want some '// network segments to be supported. '//---------------------------------------------------------------------------- ' Ignore ConfigMgr "ping" requests If PXE.IPAddress = "127.0.0.1" or PXE.MacAddress = "FF:FF:FF:FF:FF:FF" then PXE.LogTrace "Ignoring ConfigMgr ping request" Exit Function End if '//---------------------------------------------------------------------------- '// Verify the computer is known to ConfigMgr '//---------------------------------------------------------------------------- ' Connect to the SMS provider Set oLocator = CreateObject("WbemScripting.SWbemLocator") Set oSMS = oLocator.ConnectServer(sProviderServer, sNamespace, sUsername, sPassword) ' Build the query sQuery = "SELECT * FROM SMS_R_System WHERE MacAddresses = '" & sMacAddress & "'" If sUUID <> "" then sQuery = sQuery & " OR SMBIOSGUID = '" & sUUID & "'" End if ' Process the query bFound = False Set oClients = oSMS.ExecQuery(sQuery) For each oClient in oClients bFound = true iResourceID = oClient.ResourceID PXE.LogTrace "Found existing machine " & oClient.NetbiosName & " with ResourceID = " & iResourceID sNetBiosName = oClient.NetbiosName Exit For Next '//---------------------------------------------------------------------------- '// If necessary, add the computer to the ConfigMgr database '//---------------------------------------------------------------------------- If not bFound then PXE.LogTrace "Could not find machine with MAC address '" & sMacAddress & "' or SMBIOS UUID '" & sUUID & "'." 'create domain account Dim objRootDSE, strDomainContainer, strQuery Dim objConn, objRs, objComputer Dim intMax, intNum Set objRootDSE = GetObject("LDAP://RootDSE") strDomainContainer = objRootDSE.Get("defaultNamingContext") Set objConn = CreateObject("ADODB.Connection") objConn.Provider = "ADSDSOObject" objConn.Open "ADs Provider" strQuery = ";(&(&(sAMAccountType=805306369)(name=WS*)));adspath;subtree" Set objRs = objConn.Execute(strQuery) intMax = 0 While Not objRs.EOF Set objComputer = GetObject(objRs.Fields(0).Value) intNum = CInt(Right(objComputer.cn, Len(objComputer.cn) - 2)) If intNum > intMax Then intMax = intNum objRs.MoveNext Wend sNetBiosName = "WS" & intMax + 1 PXE.LogTrace "Calculated new NetbiosName: " & sNetBiosName Dim objContainer, objLeaf Set objContainer = GetObject("LDAP://OU=Computers,OU=mycompany," & strDomainContainer) ' Build the actual computer. Set objLeaf = objContainer.Create("Computer", "cn=" & sNetBiosName) objLeaf.Put "sAMAccountName", sNetBiosName & "$" objLeaf.Put "userAccountControl", 4096 objLeaf.SetInfo If Err Then PXE.LogTrace "Error creating domain-account: " & Err.Description & " (" & Err.Number & ")" Else PXE.LogTrace "Created account with dn:" & objLeaf.get("distinguishedName") End If ' Add the computer Set oSite = oSMS.Get("SMS_Site") Set oParams = oSite.Methods_.Item("ImportMachineEntry").inParameters.SpawnInstance_() oParams.NetbiosName = sNetBiosName oParams.SMBIOSGUID = sUUID oParams.MACAddress = sMacAddress oParams.OverwriteExistingRecord = false On Error Resume Next Set oResult = oSite.ExecMethod_("ImportMachineEntry", oParams) If Err then PXE.LogTrace "Error importing machine entry: " & Err.Description & " (" & Err.Number & ")" Set oLastError = CreateObject("WbemScripting.SWbemLastError") PXE.LogTrace "Last WMI error: " & oLastError.Description Exit Function End if On Error Goto 0 iResourceID = oResult.ResourceID PXE.LogTrace "Added new machine with ResourceID = " & iResourceID End if '//---------------------------------------------------------------------------- '// Check if the computer is a member of the specified collection '//---------------------------------------------------------------------------- If bFound then ' Build the query sQuery = "SELECT * FROM SMS_CM_RES_COLL_" & sCollection & " WHERE ResourceID = " & iResourceId ' Process the query bFound = False Set oClients = oSMS.ExecQuery(sQuery) For each oClient in oClients bFound = true PXE.LogTrace "Machine is already in collection " & sCollection Exit For Next End if '//---------------------------------------------------------------------------- '// If necessary, add the computer to the specified collection '//---------------------------------------------------------------------------- If not bFound then ' Add the computer to the specified collection On Error Resume Next Set oCollection = oSMS.Get("SMS_Collection.CollectionID='" & sCollection & "'") If Err then PXE.LogTrace "Error retrieving collection " & sCollection & ": " & Err.Description & " (" & Err.Number & ")" Set oLastError = CreateObject("WbemScripting.SWbemLastError") PXE.LogTrace "Last WMI error: " & oLastError.Description Exit Function End if On Error Goto 0 Set oNewRule = oSMS.Get("SMS_CollectionRuleDirect").SpawnInstance_() oNewRule.ResourceClassName = "SMS_R_System" oNewRule.RuleName = sNetBiosName oNewRule.ResourceID = iResourceID On Error Resume Next oCollection.AddMembershipRule oNewRule If Err then PXE.LogTrace "Error adding membership rule to " & sCollection & ": " & Err.Description & " (" & Err.Number & ")" Set oLastError = CreateObject("WbemScripting.SWbemLastError") PXE.LogTrace "Last WMI error: " & oLastError.Description Exit Function End if On Error Goto 0 PXE.LogTrace "Added new membership rule to collection " & sCollection End if '//---------------------------------------------------------------------------- '// Wait until an advertisement is seen. '//---------------------------------------------------------------------------- ' Check for the advertisements Set oAdvertisement = oSMS.Get("SMS_Advertisement") i = 0 bTrying = True Do While bTrying Set oParams = oAdvertisement.Methods_("GetAdvertisements").inParameters.SpawnInstance_() oParams.ResourceID = iResourceID Set oResult = oAdvertisement.ExecMethod_("GetAdvertisements", oParams) For each sAdvert in oResult.AdvertisementIDs PXE.LogTrace "Found advertisement " & sAdvert bTrying = False Next i = i + 1 If bTrying and i > 10 then PXE.LogTrace "Giving up after 30 seconds of checking for new advertisements." bTrying = False End if PXE.Sleep 5000 Loop PXE.LogTrace "Exiting PXEFilter.vbs" End Function