Tuesday, August 15, 2006

Exchange 2003 SP2 move mailbox issue (Guid-ReplID Caching) Part 2

This little script will do all the work for you.. Some of our servers have nine stores so this takes a second to run as opposed to minutes doing it manually.


const HKEY_LOCAL_MACHINE = &H80000002
If (Wscript.Arguments.Count)<>2 Then
WScript.Echo ("Usage : cscript guidstore.vbs -s ")
WScript.Quit(1)
End If
If lcase(WScript.Arguments(0))="-s" Then
strcomputer=WScript.Arguments(1)
End If

Set StdOut = WScript.StdOut

Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" &_
strComputer & "\root\default:StdRegProv")
strKeyPath = "SYSTEM\CurrentControlSet\Services\MSExchangeIS\" & strcomputer
oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys
For Each subkey In arrSubKeys
StdOut.WriteLine subkey
SubKeys = "SYSTEM\CurrentControlSet\Services\MSExchangeIS\" & strcomputer & "\" & subkey
strValueName = "Guid-Replid Caching"
dwValue = 0
oReg.SetDWORDValue HKEY_LOCAL_MACHINE,SubKeys,strValueName,dwValue
Next

Monday, August 07, 2006

Exchange 2003 SP2 move mailbox issue (Guid-ReplID Caching)

Summary
After moving mailboxes to an Exchange 2003 SP2 server, Outlook users may experience a crash when changing folders. The crash is a stack overflow caused by corruption in the GUID/Replid Mapping (GRM) cache on the target server. Remounting the mailbox store or restarting the Information Store service will resolve the crashing for affected users. Some users that have experienced the crashing problem may also experience problems with duplicate folders, delegate issues, and Free/Busy information. These problems persist after the restart and must be manually corrected.

More Information
In Exchange 2003 SP1, the GRM cache is disabled by default. In Exchange 2003 SP2, it is enabled by default. Enabling the GRM cache can lead to problems during mailbox moves to a target SP2 store. Its purpose is to handle lock contention that can affect performance during the move mailbox operation. The odds of the perf hit being severe are very low, but there is a slight chance. In most scenarios, a chance of slow is better than the alternative so we are working on a post-SP2 hotfix to disable it by default. In the meantime, you can disable the GRM cache on a per-database basis with the following registry value:

HKLM\System\CurrentControlSet\Services\MSExchangeIS\[server name]\Private-[store guid]
Value Name: Guid-Replid Caching
Value Type: DWORD
Value Data: 0

Notes
- For the registry change to take effect, remount the affected mailbox stores.
- The hotfix is still under investigation. There is no ETA at this time for its release.
- Disabling the cache will not affect users that have already experienced the problem, it only prevents mailboxes from getting into the problem state while moving them.

Thursday, July 27, 2006

Correcting SIP Addresses

If a user changes his email address then he may well not be able to log into LCS anymore due to that not matching his logon.

This script cycles AD and checks for mismatches. If you specify /commit it will write the changes back to AD.

'==========================================================================
'
'
'
' NAME: SIPFix.vbs
'
' AUTHOR: Stuart Bennett
' DATE : 26-05-2006
'
' Usage: sipfix.vbs
' e.g. sipfix.vbs out.csv /write
'
' COMMENT: Update all those pesky sip addresses to primary SMTP.
'
'==========================================================================


On Error Resume Next
' Change the xx throughout to your domain name..
OUMasterPath = "LDAP://OU=User,OU=Accounts,DC=emea,DC=xx,DC=com
Dim filename : filename = LCase(Trim(WScript.Arguments(0)))
Dim commit : commit = LCase(Trim(WScript.Arguments(1)))
Dim oFS : Set oFS = CreateObject("Scripting.FileSystemObject")
Dim fout : set fout = oFS.OpenTextFile(filename, 2, True, -2)
On Error GoTo 0

Set objTOPOU = GetObject(OUMasterPath)
For Each objOU In objTOPOU
wscript.echo("Processing Site : " & objOU.name)
Call SubOU(objOU.Name)
Next
fout.Close


Sub SubOU(theOU)
strOUPath = "LDAP://" & theOU & ",OU=User,OU=Accounts,DC=emea,DC=xx,DC=com"
Set objTestOU = GetObject(strOUPath)
For Each objUser in objTestOU
GetSIPContact fout, objUser
Next
End Sub

Sub GetSIPContact(fout, objUser)
On Error Resume Next
objUser.Get("msRTCSIP-PrimaryUserAddress")
if (Err.Number = 0) Then
SIPName=LCase(objUser.Get("msRTCSIP-PrimaryUserAddress"))
PrEmail=lcase(objuser.mail)
SIPName=Replace(sipname,"sip:","")
If trim(SIPNAME) <> trim(PrEmail) Then
wscript.echo(objUser.DisplayName & ";" & SIPName & ";" & prEmail)
fout.WriteLine(objUser.DisplayName & ";" & SIPName & ";" & prEmail)
If lcase(commit)="/write" Then
realSIP="sip:" & prEmail
wscript.echo ("Changing " & objuser.name)
objuser.PUT "msRTCSIP-PrimaryUserAddress",realSIP
objuser.setinfo
End If
End If
Else
Err.Clear
End If
On Error Goto 0
end Sub

Thursday, April 06, 2006

Mounting an exchange 2003 database on a different server.

I had always assumed that to recover a a mailbox when the original MsExchangeGUID attached to the AD account was lost would require a replica AD and Exchange 2003 server to be built.
This is just not the case and I've already restored several mailboxes by relinking them to different AD accounts in entirely seperate forests.


the key to it is LegacyDN.exe,a super tool which can be downloaded from www.microsoft.com/exchange. Don't ever run it in your production environment though..
Once in possesion of this, all you need is the .edb and .stm files.

I have an entire Virtual Server 2005 environment now for this. Create a new AD (call it whatever you want), extend it and install Exchage 2003. Call the Exchange org whatever you want, and the server itself can be whatever.

Once all is installed, I'd copy the VS2005 disks so you always have a ready environment for re-testing.

Running legacyDN.exe, you can then alter, the Orgname, the AG name, and the all importany LegacyDN name to match where the original DB came from. Once done, create a new store, but don't start it. Place the origianl DB's files in the location of the new store. Start it, run mailbox cleanup agent, then relink to any AD account you've created in your new directory.
Export with exmerge and job done.

I know RSG's save us in almost all cases, but exmerge will not see data when the msExchangeGUID cannot be matched to a AD account.

With the Virtual Server disk images in place, I can recover any mailbox in about 10 minutes these days.

Long live the illusion of identical environments for restores required, NOT ! If you want the full step by step guide, drop me an email.

Mounting an exchange 2003 database on a different server.

I had always assumed that to recover a a mailbox when the original MsExchangeGUID attached to the AD account was lost would require a replica AD and Exchange 2003 server to be built.
This is just not the case and I've already restored several mailboxes by relinking them to different AD accounts in entirely seperate forests.
the key to it is LegacyDN.exe,a super tool which can be downloaded from www.microsoft.com/exchange. Don't ever run it in your production environment though..
Once in possesion of this, all you need is the .edb and .stm files.
I have an entire Virtual Server 2005 environment now for this. Create a new AD (call it whatever you want), extend it and install Exchage 2003. Call the Exchange org whatever you want, and the server itself can be whatever.
Once all is installed, I'd copy the VS2005 disks so you always have a ready environment for re-testing.
Running legacyDN.exe, you can then alter, the Orgname, the AG name, and the all importany LegacyDN name to match where the original DB came from. Once done, create a new store, but don't start it. Place the origianl DB's files in the location of the new store. Start it, run mailbox cleanup agent, then relink to any AD account you've created in your new directory.
Export with exmerge and job done.
I know RSG's save us in almost all cases, but exmerge will not see data when the msExchangeGUID cannot be matched to a AD account.
With the Virtual Server disk images in place, I can recover any mailbox in about 10 minutes these days.
Long live the illusion of identical environments for restores required, NOT !

Wednesday, January 04, 2006

The WMF Virus Emails.

Oooh, was I first to receive one of the emails to use the new WMF exploits. check the text, it's quite convincing. And don't click the link, though I've left it in for those more adventurous types.

From a certain Mr Gordson.

Hello,

We are very sad to say that over the New Year the Campus was subjected to
several acts of mindless vandalism. As well as bricks being thrown through
windows, several members of staff have reported their cars as being the
subject of practical jokes. Some of these cars were filled with water whilst
others had graffiti daubed across them. We have uploaded the pictures of the
graffiti here http://playtimepiano.home.comcast.net/ in the hope that someone
may recognise the culprits work. If anyone can shed any light on this unfortunate
incident could they please contact the main office as soon as they have time.



Many Thanks & Best Regards,

Professor Robert Gordens
Yale

Monday, November 21, 2005

Hide multiple AD accounts from the GAL.

A simple script to read in a text file and hide the users from the GAL..

Naturally, to un-hide then change from TRUE to FALSE on the appropriate line.

S.

'==========================================================================
'
' NAME: HidefromAB.vbs
'
' AUTHOR: Woosie
' DATE : 21-11-2005
'
' COMMENT: Hide a list of users from the GAL. Win 2k3, Ex 2k3.
'
'==========================================================================

If Wscript.Arguments.Count = 0 Then
Wscript.Echo "Error, required argument missing."
WScript.Echo "Include filename to read in users."
Wscript.Quit(1)
End If

Const E_ADS_PROPERTY_NOT_FOUND = &H8000500D

Dim objDSE, objADObject, objClass, i, strPropName,debug
debug=1
sourcef = Wscript.Arguments(0)

Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(sourcef, 1, True)
While Not f.AtEndofStream
decodeline=f.ReadLine
newuser=Trim(decodeline)
If debug=1 Then
WScript.Echo ("**Looking for " & newuser)
End If
Set objDSE = GetObject("LDAP://rootDSE")
Set objADObject = GetObject("LDAP://CN=" & newuser & ",ou=Users," & _
objDSE.Get("defaultNamingContext"))
objADObject.GetInfo
objADObject.msExchHideFromAddressLists=True
objADObject.SetInfo
Wend

Hide multiple AD accounts from the GAL.

Thursday, November 03, 2005

Jet Database Errors in Exchange

JET errors we get in Exchange, in order of excitement !

Error -1012 - JET_errOutOfDatabaseSpace

Maximum database size reached.. In 5.5/2k/2k3 standard edition, a paultry 16 Gb never went far. With the release of SP2 for Exchange 2003 though this has been ramped up to 75 Gb so we should not see this again.

Error -1018 - JET_errReadVerifyFailure

Checksum error on a database page. Rather vague but possible hardware fault in most cases.

Error -1019 - JET_errPageNotInitialized

Blank database page. There used to be data there, but not now.

Error -1020 - JET_errOutOfFileHandles

When exchange tried to use the database, windows thought it had various files open already and wouldn't give up any more. Bad windows...

Error -1022 - JET_errDiskIO

The disk IO error is rare but if it does rear its ugly head, it's very hardware'y and not exchange.

Wednesday, October 26, 2005

NT4 WMI Revisited gripe.

I forgot how easy it is to crash NT4 these days..

I had run this tiny WMI Script to enumerate the installed hotfixes on an old NT4 box.

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_QuickFixEngineering",,48)
For Each objItem in colItems
Wscript.Echo "HotFixID: " & objItem.HotFixID
Wscript.Echo "Name: " & objItem.Name
Wscript.Echo "Status: " & objItem.Status
Next

Leave that running and before you know it, WinMgmt.exe will have consumed all available memory (virtual and otherwise) and the server is on its knees.

the reason being is that M$ changed their naming strategy in way hotfixes install themselves into the list of hotfixes applied. WMI_Quickfix engineering enters an endless loop trying to enumerate them.

M$ refused to fix this of course.. Why fix something when you just release a new version.

Tuesday, October 18, 2005

Exchange Server 2003 Service Pack 2

on October 19th, 2005, Microsoft will be releasing Service Pack 2 for Exchange Server 2003. This service pack is available immediately and is free to download in nine server languages here:

http://www.microsoft.com/exchange/downloads/2003/sp2/download.mspx

More QA Nightmares coming up :-(

Friday, August 05, 2005

OT : PC GTA San Andreas Plane Controls

For landing gear, press no. 2, to raise and lower..

Took me ages to find the key and I bought the original.. :-(

Almost onto Chapter 6.. What a game :-)

Friday, July 15, 2005

Exchange 2003 -1018 Whitepage

I thought this was worth a post.. It's actually quite interesting to read through and anyone who has come across the dreaded 1018 errors will find it useful to work out what happened.

http://www.microsoft.com/downloads/details.aspx?familyid=7d6d90f2-50f8-4072-8ce9-b073069b8756&displaylang=en#overview

Thursday, June 09, 2005

Rightfax 9 Dialing Rules Export

How to export Rightfax 9 Dialing Rules from SQL into a CSV file.

I was unable to use any of the GUI's in Rightfax 9 to export the dialing rules database as since SP1, they have moved them to SQL tables.

Using SQL Manager, there are 3 tables I need as far as I can see.

dbo.DTDiallingRules : holds a list of every rule with unique Rule ID's
dbo.DTConfigurationDaillingRules : holds server GUID's plus associated Rule ID's
dbo.DTConfigurations : maps server name to server GUID's.

So it should be a matter of creating a DSN in ODBC manager to your SQL server, then exporting the 3 tables, cross referencing and job done. And so faxrules.vbs was born.

'==============================================
'
' VBScript Source File
'
' NAME: FaxRules.vbs
'
' AUTHOR: Woosie.
' DATE : 08-06-2005
'
' COMMENT: Export Rules on a daily basis to keep tabs on things.
'
'==============================================

Dim DTDR,DTCDR,DTC

' -------------------------
' Create Connection to ODBC
' -------------------------
' These lines may need changing.
DSN="rightFAXDSN"
uid="sa"
pwd="xxxxxxxx"

FullPath="c:\"
todays=FormatDateTime(Date,1)
Dim MyTime,MyHour,Myminute
MyTime=now
Myhour=hour(mytime)
myminute=minute(mytime)
times=myhour & "-" & myminute
FullPath=FullPath & "\" & todays & ".csv"
Set fso = CreateObject("Scripting.FileSystemObject")
Set objfile = fso.OpenTextFile(fullpath, 8, True)

Dim OBJdbConnection
Set OBJdbConnection = CreateObject("ADODB.Connection")
Set RS = CreateObject ("ADODB.Recordset")
Set SQLStmt = CreateObject("ADODB.Command")

' -------------------------
' Open Connection
' -------------------------
OBJdbConnection.ConnectionString = "dsn=" & DSN &";uid=" & uid & ";pwd=" & pwd &";DATABASE=RightFax;APP=ASP Script"
OBJdbConnection.Open

set rsDTCDR=createobject("adodb.recordset")
RSDTCDR.open "DTConfigurationsDialingRules",OBJdbConnection,3,3
objfile.writeline("Server,RuleID,SourceServer,Pattern,DestinationServer,Protocol,PriorityDelta,

Flags,PriorityMask,StartChannel,TimeofDayMask_0,TimeofDayMask_1,
TimeofDayMask_2,
TimeofDayMask_3,TimeofDayMask_4,TimeofDayMask_5,TimeofDayMask_6,
BeginDelete,BeginReplace,EndDelete,EndReplace,UserID,GroupID,EndChannel,
Comment,MinQueueDepth,ExtraWeight,DelayHour,
FaxSize,MLAccount,MLPassCode,MLDocAccount,DNDNotifyList,NotifySender")
DTCDR=rsDTCDR.GetRows()
DTCC=UBound(DTCDR,1)
DTCR=UBound(DTCDR,2)
For lo1=0 To DTCR
Rule=DTCDR(1,lo1)
Disabled=DTCDR(2,lo1)
If disabled = 0 Then
objfile.writeline(GUID2Server(DTCDR(0,lo1)) & ",Disabled")
Else
objfile.writeline(GUID2Server(DTCDR(0,lo1)) & "," & RuleID(rule))
End if
next
Set rsDTDR=Nothing
Set rsDTCDR=Nothing
Set rsDTTC=Nothing
Set objfile=Nothing


Function GUID2Server(target)
' -------------------------
' Return Servername from GUID
' -------------------------
set rsDTC=createobject("adodb.recordset")
RSDTC.open "DTConfigurations",OBJdbConnection,3,3
GUID2Server="Not Found"
DTC=rsDTC.GetRows()
DTCC1=UBound(DTC,1)
DTCR1=UBound(DTC,2)
For loGUID=0 To DTCR1
If target=DTC(0,loGUID) Then
GUID2Server=DTC(1,loGUID)
End if
Next
Set rsDTC=Nothing
End Function

Function RuleID(target)
set rsDTDR=createobject("adodb.recordset")
RSDTDR.open "DTDialingRules",OBJdbConnection,3,3
RuleID="Not Found"
DTC=rsDTDR.GetRows()
DTCC2=UBound(DTC,1)
DTCR2=UBound(DTC,2)
For loGUID=0 To DTCR2
If target=DTC(0,loGUID) Then
RuleID=""
For add=0 To DTCC2
RuleID=RuleID & chr(34) & DTC(add,loGUID) & Chr(34) & ","
Next
End If
Next
Set rsDTDR=Nothing
End Function

Friday, May 06, 2005

KB883543 breaks OWA in Exchange 2003 UPDATE

Good news at last. Micrsoft have released a fix to KB883543 which caused the rule not to be able to saved.. Apparantly,

This problem occurs because OWA rules ignore address type information that is enclosed in brackets. For example, OWA rules would ignore the following string:[AddressType:E-mail]
Download the hotfix from the KB article, KB875269.

Monday, April 04, 2005

KB883543 breaks OWA in Exchange 2003...

If you have applied KB883543 onto your Exchange 2003 box, you will find that any rule you try to create in OWA that tries to forward to another user will now bring up the dialog box.

This rule cannot be saved. Wait a few minutes and try again. If the problem persists, contact your administrator.

The only option at the moment is to uninstall this hotfix which restore functionality...

I don't believe, at time of posting, there is a fix for this hotfix..

Nice..

Thursday, March 17, 2005

Exchange 2003 SP1 Registry Updates.

It transpires when you install E2k3 SP1 onto a server, the reg key

HKLM\SOFTWARE\Microsft\Updates\Exchange Server 2003\SP1 and subfolders is deleted to be replaced by

HKLM\SOFTWARE\Microsft\Updates\Exchange Server 2003\SP2

SP1 also removes the $ExchUnintstall directories in c:\winnt

Strange as that removes all trails of what hotfixes you did have installed Pre-SP1..

A pain for me as we have to audit old Hotfixes to ensure they were installed..

Tuesday, March 08, 2005

HP / Compaq Rib board detector

Get asked a lot if a server the other side of the world has a rib board installed..


This little script lets me know.


' Rib board detector.
' Scans list of servers for rib boards
' (c) 2005 Woosie


const HKEY_LOCAL_MACHINE = &H80000002
Const ForReading = 1, ForWriting = 2
Dim fso, MyFile, FileNam
Dim strComputer,TheLeft,TheDoctor
Set StdOut = WScript.StdOut
FileNam=InputBox ("Enter Target Server for RIB Board detection ?")
strcomputer = FileNam
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" &_
strComputer & "rootdefault:StdRegProv")
strKeyPath = "SYSTEMCurrentControlSetEnumRootLEGACY_CPQRIB000"
strValueName ="DeviceDesc"
oReg.GetExpandedStringValue HKEY_LOCAL_MACHINE,strKeyPath,_
strValueName,strValue
IF LEN(strValue)>4 then
msg=MsgBox("Rib board installed on " & strComputer)
else
msg=MsgBox("No rib board installed on " & strComputer)
end if

How do I query a domain local group ?

How do I query a domain local group ? Suppose you are in Domain A and are member of a domain local group in Domain B. The Domain A DC does not know about it, nor does the GC. Only the Domain B DC knows about it. I finally came up with this solution. It is slow though as it has to query the AD tree..


'==========================================================================
'
' NAME: DomainLocalGroup.vbs
'
' AUTHOR: Woosie
' DATE : 02-03-2005
'
' COMMENT: Scan AD Tree looking for local group membership and then output
' list to screen.
'
'==========================================================================


Dim localgroups()
localgroup=0
struser = InputBox("User to assess local group membership (e.g. cn=bennnett_s) ?","Local Group Scanner")
' change next line to point to your root AD path.
Set oDomain = GetObject("[link]")
WScript.Echo("Searching Domain a.. Please wait..")
EnumOU(oDomain)


WScript.Echo (struser & " is a member of : ")
For myloop=0 To localgroup
WScript.Echo(localgroups(myloop))
next
Wscript.Quit


Function EnumOU(oContainer)
For Each oObj In oContainer
For Each sClass in oObj.ObjectClass
If LCase(sClass) = "organizationalunit" Then
WScript.echo "Searching " & oObj.AdsPath
EnumOU(oObj)
Else
If LCase(sclass) = "group" Then
WScript.Echo oobj.name & " " & oObj.AdsPAth
strPath =oObj.AdsPAth
set objGroup = GetObject(strPath)
for each objMember In objGroup.Members
splitme=split(objMember.Get("distinguishedname"),",")
if lcase(splitme(0))=lcase(struser) Then
localgroup=localgroup+1
ReDim Preserve localgroups(localgroup)
localgroups(localgroup-1)=strpath
Wscript.Echo struser & " is a member of local group : " & strpath
End if
Next
End If
End If
Next
Next
End Function