Monday, March 31, 2008

Viewing NTFS information with nfi and diskedit

This post describes processes to view details information regarding an NTFS filesystem, including NTFS attributes such as resident $FILE_NAME, nonresident $DATA and the MFT FRS bytes for any particular file on the filesystem.

I’ve always been curious of how to see the details of NTFS, but have never really had the necessity before. As it happens, we’re discovering quite a few ‘Enterprise Vault’ Event ID 20488 errors when FSA is trying to create placeholder records. The only pattern I can find is that files exhibiting this problem (copied from an NFS volume) all have $EA_INFORMATION (resident) and $EA_DATA (resident) NTFS attributes. Stripping the extended attributes (copying to/from FAT, or recreating the file (eg. By compressing/uncompressing with something not clever enough to read the EA’s – arj32 will do it) resolves the issues with Enterprise Vault.

Anyway, back to NTFS, two utilities I’ve found invaluable in this exercise are 'nfi' and 'diskedit' (Microsoft). Nfi.exe comes from the 2000 server utilities in the link below, while diskedit.exe comes with NT4 SP4.

Using nfi.exe

View a directory:

nfi "c:\WINDOWS"
NTFS File Sector Information Utility.
Copyright (C) Microsoft Corporation 1999. All rights reserved.

$FILE_NAME (resident)
$INDEX_ROOT $I30 (resident)
$INDEX_ALLOCATION $I30 (nonresident)
logical sectors 21137544-21137647 (0x1428888-0x14288ef)
$BITMAP $I30 (resident)

View a file (showing non-contiguous sectors):

nfi "C:\windows\NOTEPAD.EXE"
NTFS File Sector Information Utility.
Copyright (C) Microsoft Corporation 1999. All rights reserved.

$FILE_NAME (resident)
$DATA (nonresident)
logical sectors 5453304-5453383 (0x5335f8-0x533647)
logical sectors 9927784-9927839 (0x977c68-0x977c9f)

Read the first sector of the nonresident data section of notepad.exe, which shows the FRS number (0x1EE5 - 7909).

nfi c: 5453304
NTFS File Sector Information Utility.
Copyright (C) Microsoft Corporation 1999. All rights reserved.

***Logical sector 5453304 (0x5335f8) on drive C is in file number 7909.
$FILE_NAME (resident)
$DATA (nonresident)
logical sectors 5453304-5453383 (0x5335f8-0x533647)
logical sectors 9927784-9927839 (0x977c68-0x977c9f)

Read a file that has the extended attributes I was talking about earlier:

nfi "C:\windows\temp\test.ea"
NTFS File Sector Information Utility.
Copyright (C) Microsoft Corporation 1999. All rights reserved.

$FILE_NAME (resident)
$FILE_NAME (resident)
$DATA (nonresident)
logical sectors 7069816-7070775 (0x6be078-0x6be437)
$EA_INFORMATION (resident)
$EA (resident)

Using diskedit.exe

Diskedit is much more interesting, but not particularly intuitive to use. Note that when running diskedit on 2000/xp/2003, you need to have a copy of the NT4 SP4 resource DLLs - IFSUTIL.DLL, UFAT.DLL, ULIB.DLL, UNTFS.DLL

Some ways I’ve used diskedit.exe:

View the file record segment for a file
File Open Volume Name - c:
Read NTFS File Record – Hex FRS number (taken from nfi or cracked)

This will show detailed information on the NTFS attributes of the file record, including filenames, relational information such as the parent directory. See the screenshot below.

View particular NTFS attributes of a record:

Attributes such as $STANDARD_INFO, $FILE_NAME. $SECURITY_DESCRIPTOR can be detailed.

File - Open Volume - Name - c:
Read - NTFS Attribte
1. Base Frs Number – Hex FRS number (taken from nfi or cracked)
2. Attribute Type – Select from the list
3. Attribute Name – Use from viewing the record if name exists, eg $I30 for $INDEX_ROOT

Find the FRS number for an object:

File - Open Volume - Name - c:
Crack - NTFS Path – Full path minus c:, eg \windows\notepad.exe

View the record segement bytes, showing the raw resident attributes, including the EA attributes (if they’re resident):

File - Open Volume - Name - c:
Read - NTFS File Record – Hex FRS number (taken from nfi or cracked)
View - Bytes

See the screenshot below.


nfi.exe from here shows NTFS information

NTFS, good description of NTFS

istat from the sleuth kit can report attributes apparently (didn’t have much luck using on NTFS 3.1/5.1)

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Sunday, March 30, 2008

Performance Tuning for 2003 File Servers

This post provides a summary of performance tuning options for a Windows Server 2003 file server. Included is information on NTFS, lanmanserver, NIC, Disk and HBA performance tuning options. None should be used in a production environment without testing. Note that the Microsoft excerpts come from a 2008 performance tuning document, after verifying that the options are supported on 2003.

General Performance Settings

Disable 8.3 name creation


Excerpt from Microsoft on this option:

The default is 0. This parameter determines whether NTFS generates a short name
in the 8.3 (MS DOS®) naming convention for long file names and for file names
that contain characters from the extended character set. If the value of this
entry is 0, files can have two names: the name that the user specifies and the
short name that NTFS generates. If the user-specified name conforms to the 8.3
naming convention, NTFS does not generate a short name.

Changing this value does not change the contents of a file, but it avoids the short-name attribute
creation for the file, also changing the way NTFS displays and manages the file.
For most file servers, the recommended setting is 1.

Note that when accessing files that go beyond the 260 MAX_PATH length, short filenames can be a very useful method of accessing these files.

Ignore Write Flush Commands from Clients


Excerpt from Microsoft on this option:

The default is 0. This parameter disables the processing of write flush commands
from clients. If the value of this entry is 1, the server performance and client
latency for power-protected servers can improve. Workloads similar to the
NetBench file server benchmark benefit from this behavior.
Network tuning

NIC Offloading

Newer NICs have offloading capabilities, allowing the Operating System to offload one or more tasks to the network adapter. For example, Broadcom BCM5708S NetXtreme II adapters have the following offload capability enabled:
• IPv4 Checksum offload – Calculation and validation of checksums on TX/RX of TCP and UDP packets
• IPv4 Large Send offload – Offload the segmentation of large packets to the hardware



Windows Server 2003 auto-tunes this setting, and benefits to manually choosing a window size are acknowledged in high-latency networks.



Increasing this number from the default of 1 can decrease contention in the TCP/IP stack. Microsoft warns of modifying this setting without significant testing, with a recommended maximum of the number of processors in the system.

MaxFreeTcbs and MaxHashTableSize


MaxFreeTcbs can be adjusted manually to set the maximum number of TCP control blocks the system creates. This number determines the simultaneous number of connections the server can handle. If MaxFreeTcbs is changed, MaxHashTableSize should also be modified, dictating the size of the hash table that stores the control blocks.

Disk Tuning

LargeSystemCache and LanManServer file system caching

The amount of memory allocated to file system caching can help to increase the disk cache hits for a file server. In Windows Server 2003 this setting is enabled by default, although a casual glance of the system working set and the lanmanserver service working set do not show a large amount of the available physical memory for cache.

Windows 2003 also has logical block caching in addition to caching at the file system level. Further information could not be found on configuring or measuring the performance of logical block level caching.

The file cache is part of the system working set, which is protected from excessive trimming when the LargesystemCache option is usedThe lanmanserver service working set must also be protect in some way, part of services.exe (use tasklist /svc).

CacheSet from sysinternals can be used to modify the system working set size

Excerpt from Microsoft TechNet:

The Memory object performance counter System Cache Resident Bytes reports the amount of real memory currently in use by the file cache. As the number of System Cache Resident Bytes increases, we normally expect that the various measures of hit ratio will also increase. Moreover, the cache size can grow simply as a function of the size of the files that are currently in use and their pattern of access.
The Cache Resident Bytes counter reports the amount of real memory the file cache is currently occupying. The Cache Bytes counter, which sounds like it might tell you the size of the cache, actually reports the full system working
set, which includes Cache Resident Bytes and several other real memory areas. In a Windows 2000 file server (remembering Windows 2000's heritage as the follow-on to the joint IBM/ Microsoft-developed OS2 LAN Manager), the file cache so dominates the system working set that internal documentation frequently refers to the entire system working set as the cache. This usage carries over to tools like Task Manager, which labels the system working set as the System Cache in the Performance tab, illustrated in Figure 7-2. The Windows NT version of Task Manager called this field File Cache, which is probably just as misleading. Curiously, the number of bytes in the System Cache reported by Task Manager does
not correspond exactly to the Cache Bytes counter in the System Monitor.
Disk Alignment

Using disk alignment to realign partitions can occasionally decrease the number of disk I/O operations. This occurs because the MBR is on the first 63 sectors of a disk, and the first partition starts on the 64th sector instead of the 65th sector – the beginning of the next boundary. This is vendor and disk specific, and does not apply to every disk.

Excerpt from Microsoft TechNet:

Microsoft Windows 2000 Server has an internal structure known as the master boot
record (MBR) that limits the maximum number of hidden sectors to 63. This
characteristic of the MBR causes the default starting sector for disks that
report more than 63 sectors per track to be the 64th sector. Therefore, when
programs transfer data to or from disks that have more than 63 sectors per
track, misalignment can occur at the track level, with allocations starting at a
sector other than the starting sector. This misalignment can defeat system
optimizations of I/O operations that are designed to avoid crossing track

Diskpar.exe is a command-line tool from the Windows 2000
Server Resource Kit that can explicitly set the starting offset in the MBR. By
doing this, the track is aligned with the physical disk partition, which results
in an improvement in disk performance. Exchange writes four kilobytes to the
database and up to 32 kilobytes for the streaming data. Therefore, make sure
that you set the starting offset to be a multiple of four kilobytes.
Write-caching option on each disk

Excerpt from Microsoft on this option:

Enabling write caching allows writes to be completed immediately after being
cached in the storage subsystem. Note that with this action a period of time
passes during which a power failure or other catastrophic event could result in
a loss of the data. However, this period is typically fairly short because write
caches in the storage subsystem are usually flushed during any period of idle
activity. Alternately, you can use time-outs at the cache level to force dirty
data out of the cache even if other active requests exist.
This option is enabled by default on all SAN-attached storage

‘Advanced Performance’ option on each disk.

Excerpt from Microsoft on this option:

The advanced performance option strips all write-through flags from disk
requests and also removes all flush-cache commands. The assumption is that if
you have power protection on your I/O path you don’t need to worry about those
two pieces of functionality; by definition, any written data is safe and
"in-order" after it is copied into power-protected storage subsystem hardware,
just as if it had been written to the physical disk media.
This option is disabled by default on all SAN-attached storage.

Emulex Lightpulse scatter/gather list elements


Add (if not already present) the following Keys under lpxnds

Parameters->Device (Parameters apply to ALL LPxxx adapters)
->Devicen (Parameters apply to LPxxx adapter number 'n' 0-99)

Under Device or Devicen add a value of "MaximumSGList" Type REG_DWORD,
with a value of from 13 to 255 (decimal). Microsoft specifies to use
this value sparingly, as these request entries come from Non-Page-Pool.

Emulex Lightpulse asynchronous requests


Add (if not already present) the following Keys under lpxnds

Parameters->Device (Parameters apply to ALL LPxxx adapters)
->Devicen (Parameters apply to LPxxx adapter number 'n' 0-99)

Under Device or Devicen add a value of "NumberOfRequests" Type REG_DWORD,
with a value of from 16 to 256 (decimal). Microsoft specifies to use
this value sparingly, as these request entries come from Non-Page-Pool
(this is especially true with the ALPHA systems).


Windows Server 2008 performance tuning

How To Improve Windows 2003 File Server Performance


How to Configure the Storage Subsystem

Examining and Tuning Disk Performance

Aligning Disk Partitions by Using Diskpar.exe


Optimizing Your Memory Configuration

About Cache Manager in Windows Server 2003

MaxPagedMemoryUsage for the server sevice

MaxPagedMemoryUsage for the server sevice


Optimizing Your Memory Configuration

File Cache Performance and Tuning

Cluster resource command-line operation

File Cache Performance and Tuning

About Cache Manager in Windows Server 2003

How to Configure the Storage Subsystem

Why should you use Diskpar

Emulex Lightpulse HBA device settings

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Saturday, March 29, 2008

Checking ESX/VC VMs for snapshots

This post provides several methods of determining whether any VMs in a Virtual Center 2 environment have any active snapshots. This is a useful monitoring task in production environments, as taking a snapshot and forgetting to remove the snapshot can cause problems when consolidating in the future. Included is a SQL query, a sqlcmd query, and a simple 'ls' command to run from the service console.

Method 1 - Run a query through SQL Management Studio against the Virtual Center database

select ENT.Name as 'Name', DNS_Name as 'DNS Name', Guest_OS as 'OS', Mem_Size_MB as 'Mem', IP_Address as 'IP', VM.FILE_Name as 'VMX location', VM.Suspend_Time as 'Suspend Time', VM.Suspend_Interval as 'Suspend Interval', VMS.Snapshot_Name as 'Snapshot Name', VMS.Snapshot_Desc 'Snapshot Description', DateAdd("Hour", 10, VMS.Create_Time) as 'Snapshot Time', VMS.Is_Current_Snapshot 'Current Snapshot' from vpx_vm VM
inner join VPX_ENTITY ENT on VM.ID = ENT.ID

Method 2 - Query the Virtual Center database for Virtual Machine snapshots (GMT+10) using sqlcmd

sqlcmd -S %server% -d %database% -W -s "," -Q "select ENT.Name as 'Name', DNS_Name as 'DNS Name', Guest_OS as 'OS', Mem_Size_MB as 'Mem', IP_Address as 'IP', VM.FILE_Name as 'VMX location', VM.Suspend_Time as 'Suspend Time', VM.Suspend_Interval as 'Suspend Interval', VMS.Snapshot_Name as 'Snapshot Name', VMS.Snapshot_Desc 'Snapshot
Description', DateAdd(Hour, 10, VMS.Create_Time) as 'Snapshot Time', VMS.Is_Current_Snapshot 'Current Snapshot' from vpx_vm VM inner join VPX_GUEST_NET_ADAPTER NET on VM.ID = NET.VM_ID inner join VPX_ENTITY ENT on VM.ID = ENT.ID inner join VPX_SNAPSHOT VMS on VM.ID = VMS.VM_ID"

Example output:
VM1,,winXPProGuest,768,,sanfs://vmfs_uuid:47445a61-08269406-d462-0419b6f67087/VM1/VM1.vmx,NULL,0,Test Snapshot,,2008-03-29 07:24:31.170,1

Method 3 - View vmsn files from the service console

ls -Ral /vmfs/volumes/*.* grep .vmsn

Note that VMware would not recommend querying SQL directly, and I suspect would instead suggest using their very (in my opinion) unintuitive SDK and object model. Bring on the PowerShell management interface.

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Showing non-persistent devices in device manager

This post records information about showing non-present devices in Windows 2000 or later, useful for displaying devices that have been previously installed but are currently not plugged in.

To show devices that aren't currently present:

  1. Open a command prompt
  2. set devmgr_show_nonpresent_devices=1
  3. devmgmt.msc
  4. Select View 'Show hidden devices'
Other methods of using this include:
  1. Set a system-wide environment variable so this is persistent whenever device manager is started.
  2. Use doskey macros to record the both commands in a single macro. For example, the following doskey macro command would allow the 'DM' to set the varilable and then run the device manager snap-in.


Some examples of when this is useful include:
  1. When NICs are disconnected and hidden, particularly in VMware, multiple virtual NICs can be created, and the settings often conflict and are not easy to correct.
  2. Trying to detect and troubleshoot driver conflicts or version issues


Showing hidden devices in Windows XP

Showing hidden devices in Windows 2000

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Implementing an MSCS 2003 server cluster

When implementing a Windows Server 2003 MSCS server cluster there are several common issues that can easily be avoided by extra planning and configuration. I've compiled a list of pre-configuration, installation and post-installation steps to reduce the risk of encountering issues when installing an MSCS cluster in a SAN environment.

This is mostly a summary of MS documents and general best practice, but I've not seen all of these in one place before so I thought I would post them.

Pre-installation steps for each server:

  • Unplug all HBA's from all cluster nodes.
  • Set the network adapter binding order to external and then internal.
  • Manually set speed, duplex, IP for all NICs, no gateway/DNS/WINS for private network
  • Verify connectivity between each node on public and private adapters
  • Turn off any APM/ACPI power saving features relating to disk drives
  • Create the cluster service account in the domain
  • Ensure the cluster service account is an administrator of the physical cluster nodes. (especially if Kerberos authentication is enabled for virtual servers, but general best practice)
  • Ensure the windows firewall is disabled on both adapters
  • Ensure security auditing is enabled on each node
  • Verify correct drivers are installed on each node (HBA, NIC, chassis backplane etc.) and no device manager errors exist.
  • Shutdown all nodes. Patch HBA’s on the first node, turn on the first node and check storage is visible. Repeat the step for each node, ensuring that only one node has visibility of the storage at any one time. Verify all nodes see the same target paths/disk in the same order.
  • Ensure backup agent is installed and functioning on all servers.
  • Ensure anti-virus agent is installed and functioning on all servers.
  • Configure permissions and role-based security on the servers as required
  • Install Access-Based enumeration on each server (if required)

Cluster first node installation:

  • Shut down all but the first node, so that only the first server has visibility of the storage
  • Re-verify all the SAN disk is visible to the OS
  • Partition and format disks using MBR before adding the first node to the cluster, disable compression. Q: for quorum is a defacto standard, other disks starting after leaving a few letters early in the alphabet for any removable devices/KVM virtual devices etc if they are auto-mounted
  • Use Cluster Administrator to install the cluster, use typical (full) installation when creating a new cluster (there should be no reason not to if the disk is presented the same to each server). Do not use ‘Manage Your Server’ to configure cluster nodes
  • This is where you'll need the cluster name. Use a naming convention that makes sense, linking the physical nodes in the cluster to the virtual cluster name(s)
  • Ensure that the all disks managed by the cluster have associated disk resources before adding the second and subsequent nodes, this ensures disk locking
  • Verify the cluster is functioning, cluster service is running, no event errors, all resources available and functioning etc.

Second and subsequent nodes:

  • Plug in HBA to all other nodes, turn on second node
  • Re-verify all the SAN disk is visible to the OS on the second node
  • Add second node to cluster using Cluster Administrator (the first node will lock the disk)
  • Verify the cluster is functioning (cluster service is running, no event errors, all resources available and functioning etc).
  • Add subsequent nodes using Cluster Administrator
  • Verify the cluster is functioning (cluster service is running, no event errors, all resources available and functioning etc).

Post-installation configuration:

  • Set the role of the private network to be only for internal communication (with mixed for failover according to the design)
  • Set the role of the public network to public network
  • Place the private network at the top of the priority list for internal node-to-node communication
  • Do not use the default cluster group for any resources
  • Do not use the quorum disk for anything else in the cluster
  • Do not install scripts used by generic script resources on cluster disk (easier to recover if they're on local disk)
  • Enable kerberos authentication for network name resources, after taking the network name resources offline). Enabling Kerberos will ensure a computer account is created for the virtual servers and adds Service Principal Names for Kerberos lookup and authentication
  • For the first node, set the startup and recovery settings to start within 5 seconds. For the other nodes, set to 30 seconds, to reduce the risk if all cluster nodes are starting at the same time that there would be quorum conflict/contention.
  • Create and test all resources, resource groups and virtual servers, dependencies, failover/failback policies, including file shares/ABE and print spooler
  • Configure backups appropriate for all cluster nodes
  • Configure performance and service monitoring
  • Configure quotas and file screening using FSRM if required

Other general thoughts:

  • Access Based Enumeration is useful in some file structures, but does not fully equate to functionality provided in Netware. The easiest way I can describe ABE is that it hides what you do not have access to, rather than ensuring you can see what you do have permissions for. For example, in the tree A\B\C, if you have permissions to A and C, but not permissions to B, you will not see C. This is because ABE has hidden what you don’t have access to (B), a by-product of which is that (C) won’t be visible in a default explorer navigation.
  • Having a single virtual print spooler still has a single point of failure – the spoolsv.exe process running on the host system. If that dies because of a configuration error, that error will most likely fail over to any other nodes that can host that resource group. Regardless of ensuring you don’t use kernel-mode (version 2), and only use user-mode (version 3) drivers, any number of issues can occur somewhere in the print process, whether it’s a third-party print processor causing issues, a non-standard port type, or just a poorly written unidrv support DLL. Everything is a lot more transparent with 2003 clustering – drivers, processors and ports all follow the virtual spooler, which most of the time is good, except when you have a problem.

Testing, reproduced from the standard Microsoft confclus.doc document:

Test: Start Cluster Administrator, right-click a resource, and then click “Initiate Failure”. The resource should go into an failed state, and then it will be restarted and brought back into an online state on that node.
Expected Result: Resources should come back online on the same node

Test: Conduct the above “Initiate Failure” test three more times on that same resource. On the fourth failure, the resources should all failover to another node in the cluster.
Expected Result: Resources should failover to another node in the cluster

Test: Move all resources to one node. Start Computer Management, and then click Services under Services and Applications. Stop the Cluster service. Start Cluster Administrator on another node and verify that all resources failover and come online on another node correctly.
Expected Result: Resources should failover to another node in the cluster

Test: Move all resources to one node. On that node, click Start, and then click Shutdown. This will turn off that node. Start Cluster Administrator on another node, and then verify that all resources failover and come online on another node correctly.
Expected Result: Resources should failover to another node in the cluster

Test: Move all resources to one node, and then press the power button on the front of that server to turn it off. If you have an ACPI compliant server, the server will perform an “Emergency Shutdown” and turn off the server. Start Cluster Administrator on another node and verify that all resources failover and come online on another node correctly. For additional information about an Emergency Shutdown, see the following articles in the Microsoft

Knowledge Base:
325343 HOW TO: Perform an Emergency Shutdown in Windows Server 2003
297150 Power Button on ACPI Computer May Force an Emergency Shutdown
Expected Result: Resources should failover to another node in the cluster
Warning: Performing the Emergency Shutdown test may cause data corruption and data loss. Do not conduct this test on a production server

Test: Move all resources to one node, and then pull the power cables from that server to simulate a hard failure. Start Cluster Administrator on another node, and then verify that all resources failover and come online on another node correctly
Expected Result: Resources should failover to another node in the cluster
Warning: Performing the hard failure test may cause data corruption and data loss. This is an extreme test. Make sure you have a backup of all critical data, and then conduct the test at your own risk. Do not conduct this test on a production server

Test: Move all resources to one node, and then remove the public network cable from that node. The IP Address resources should fail, and the groups will all failover to another node in the cluster. For additional information, see the following articles in the Microsoft Knowledge Base:
286342 Network Failure Detection and Recovery in Windows Server 2003 Clusters
Expected Result: Resources should failover to another node in the cluster

Test: Remove the network cable for the Private heartbeat network. The heartbeat traffic will failover to the public network, and no failover should occur. If failover occurs, please see the “Configuring the Private Network Adaptor” section in earlier in this document
Expected Result: There should be no failures or resource failovers


Guide to Creating and Configuring a Server Cluster Under Windows Server 2003

Best practices for installing and upgrading cluster nodes

Best practices for configuring and operating server clusters

Before Installing Failover Clustering

Cluster Configuration Best Practices for Windows Server 2003

Server Cluster Best Practices

Cluster architecture

Creating and Configuring a Highly Available Print Server

Disk quotas and clusters

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Finding users on a subnet

For auditing and remote access purposes, identifying the computers and users on specified subnets can be useful. This post documents several methods that I've used in the past, including querying computers through AD, DNS, DHCP, SMS, and then finding the logon information through psloggedon, WMIC, or a custom VBScript.

Step 1 - Find computers on a subnet

There are several methods of finding this information, some more accurate than others depending upon your infrastructure:

SMS - Query SMS to find computers in a specific subnet or AD site:

  • wmic /namespace:\\root\sms\site_%sitecode% /node:"%sms_server%" path SMS_R_System WHERE "IPSubnets='%subnet%' AND Active=1'" get name
  • wmic /namespace:\\root\sms\site_%sitecode% /node:"%sms_server%" path SMS_R_System WHERE "ADSiteName='%AD_SITE_CODE%' AND Active=1'" get name

DNS - Query DNS to find machines on a specific subnet
Windows DNS

  • dnscmd %dns_Server% /enumrecords %zone% @ /additional /continue find /i "%subnet%"

Non-windows DNS - Just cat/grep/find/findstr the zone files.

DHCP - Windows DHCP, use netsh:

  • psexec \\%dhcp_server% cmd /c for %i in (%Subnet1% %Subnet2% %Subnet3%) do netsh dhcp server scope %i show clients 1
  • for /f "tokens=1" %i in ('"netsh dhcp server show scope 1 find /i "%description%""') do netsh dhcp server scope %i show clients 1 find /i "255.255" find /i "%prefix%"

Query AD for computers in an OU, ping the computers and return only those that respond to a ping (and can be resolved)

  • for /f %i in ('"dsquery computer %OU_DN% -o rdn"') do for /f "tokens=3 delims=: " %m in ('"ping -n 1 %i find /i "reply from""') do echo %i

Step 2 - Find who's logged on to those computers

Use psloggedon:

  • for /f %i in (computers.txt) do psloggedon \\%i

Use WMI:

  • for /f %i in (computers.txt) do wmic /node:"%computer%" PROCESS where "caption='explorer.exe'" getowner

Note that the psloggedon and WMI methods will be slow when processing computers that aren't on the network, wrap around a for /f ping command (see the OU query above).

Use the VBScript in this post:

  • cscript LoggedOn.vbs %computer1%,%computer2%,...

The VBScript is more verbose, providing information including human readable dates, and extra information such as whether a screensaver is running.

--- Script follows

Const DELIMITER = ","

If WScript.Arguments.UnNamed.Count > 0 Then
strComputerSet = WScript.Arguments.UnNamed(0)
WScript.Echo "Please supply one or more computers to process, separated by '" & DELIMITER & "'"
End If

For Each strComputer in Split(strComputerSet, DELIMITER) ' For each computer
If VerifyHostPing(strComputer) Then ' Is the computer responding to a ping?
Call FindLoggedOnUserExplorer(strComputer) ' Find the logged on users
End If

Function FindLoggedOnUserExplorer(ByRef strComputer)

Dim objWMI, strQuery, dtmCreationDate, strUser, dtmDifference, strUserInfo
Dim objProcessSet, objProcess, objProcessOwner, intCount

On Error Resume Next
Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
On Error Goto 0
If NOT IsObject(objWMI) Then
wscript.echo strComputer & ", " & "Could not connect to WMI"
Exit Function
End If

strQuery = "select __relpath, CreationDate from win32_process where caption = 'explorer.exe'"
set objProcessSet = objWMI.execQuery(strQuery)

If objProcessSet.Count = 0 then
wscript.echo strComputer & ", " & "No explorer processes found"
strUserInfo = ""
For Each objProcess in objProcessSet
Set objProcessOwner = objProcess.ExecMethod_("GetOwner") ' Execute the method to find the process owner
strUser = objProcessOwner.Domain & "\" & objProcessOwner.User
dtmCreationDate = objProcess.CreationDate ' The creation date of the explorer process
dtmCreationDate = ConvertDMTFToVB(dtmCreationDate, False)

strUserInfo = strUserInfo & vbCRLF & strComputer & ", " & strUser & ", " & dtmCreationDate
If Len(strUserInfo) >= Len(vbCRLF) Then strUserInfo = Right(strUserInfo, Len(strUserInfo) - Len(vbCRLF)) ' Strip the leading CRLF

strQuery = "select __relpath, CreationDate, ExecutablePath from win32_process where ExecutablePath like '%.scr'"
On Error Resume Next
set objProcessSet = objWMI.execQuery(strQuery)
intCount = -1
intCount = objProcessSet.Count
On Error Goto 0
If NOT IsObject(objProcessSet) OR intCount = -1 Then
wscript.echo strComputer & ", " & "Could not check for screensaver"
If intCount > 0 then ' Is there a screensaver running?
For Each objProcess in objProcessSet ' Yes
dtmCreationDate = objProcess.CreationDate ' Get the creation date of the process
dtmCreationDate = ConvertDMTFToVB(dtmCreationDate, False) ' Convert to VB datetime
dtmDifference = DateDiff("h", dtmCreationDate, Now) ' Different between now and then
strUserInfo = strUserInfo & ", " & "Screensaver is running: " & objProcess.ExecutablePath & " and has been for " & dtmDifference & " hours"
strUserInfo = strUserInfo & ", " & "Screensaver is not running"
End If
End If

End If
If strUserInfo <> "" Then wscript.echo struserinfo

End Function

Function VerifyHostPing(ByRef strComputer)
Dim objWMI, strQuery, i, objPings, objStatus

Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\root\cimv2")

VerifyHostPing = False
strQuery = "Select * From Win32_PingStatus where Address = '" & strComputer & "' AND BufferSize = 32 and Timeout = 300"

Set objPings = objWMI.ExecQuery(strQuery)

For Each objStatus in objPings
If IsNull(objStatus.StatusCode) OR objStatus.StatusCode <> ERROR_SUCCESS Then
wscript.echo "Warning: " & strComputer & " not contactable."
VerifyHostPing = False
wscript.echo "Successfully pinged " & strComputer
VerifyHostPing = True
End If

Set objPings = Nothing
Set objStatus = Nothing
Set objWMI = Nothing
End Function

Function ConvertDMTFToVB(dtmDate, blnTimeZone)
Dim strTemp, intTemp, strNow, strNowDate

strTemp = Left(dtmDate,4) & "/" & Mid(dtmDate,5,2) & "/" & Mid(dtmDate,7,2) & " " & Mid(dtmDate,9,2) & ":" & Mid(dtmDate,11,2) & ":" & Mid(dtmDate,13,2)
If Left(strTemp, 10) = "****/**/**" Then ' Ugly hack for schedule task times returned by WBEM that only contain time information
strNow = Now
strNowDate = DatePart("yyyy", strNow)
strNowDate = strNowDate & "/" & String(2 - Len(DatePart("m", strNow)),"0") & DatePart("m", strNow)
strNowDate = strNowDate & "/" & String(2 - Len(DatePart("d", strNow)),"0") & DatePart("d", strNow)
strTemp = strNowDate & " " & Right(strTemp, Len(strTemp)- 11)
End If
If IsDate(strTemp) Then
If blnTimeZone Then
strTemp = DateAdd ("h", Right(dtmDate,4)/60, strTemp) 'Add GMT offset
End If
ConvertDMTFToVB = FormatDateTime(strTemp,2) & " " & FormatDateTime(strTemp,4)
End If
End Function

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Thursday, March 27, 2008

WMI filter for subnet filtered Group Policy

This post describes a WMI filter used to provide Group Policy based on the client subnet. This can be useful when site-based policy is not appropriate, or for more granular control of specific subnets within sites.

The WMI filter used:

Select * FROM Win32_IP4RouteTable
WHERE ((Mask='' AND NextHop='')
AND (Destination Like '10.0.0.%' OR Destination Like '10.0.1.%' OR Destination Like '10.0.2.%'))

Originally this was used to define a DNS suffix search list for computers on a particular subnet. Other potential uses include branding and hardening of clients on specific subnets, such as privileged network or remote access subnets.

Why the Win32_IP4RouteTable class was used in the WMI query:

  • Using the routing table to determine the local IP is not very intuitive, it would make more sense to use something like win32_networkadapterconfiguration, but the relevant information is stored in arrays, which cannot currently be processed by WMI filters. (or WMI queries in WHERE clauses)
  • The route table is filtered to ensure only the local address is processed by including only the local broadcast address and the localhost hop, and then checking the subnet. Note that a /24 is the only subnet size that will be accurate when validating only on the last octet (the query above).

GPMC limitations:

  1. GPMC Modelling doesn't seem accurate, ie. some XPSP2 workstations processing this policy return True for the WMI filter, even though 'gpresult /z' on the workstation accurately reports that the WMI filter caused the policy to not apply.

Using UserEnv Debugging to verify:

  1. reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v UserEnvDebugLevel /d 0x00010002 /t reg_dword
  2. gpupdate /force /target:computer

c:\windows\debug\netlogon.log should then show something like:

   USERENV(1c8.650) 00:30:03:191 FilterCheck: Found WMI Filter id of: <[;{B3942687-E8A9-4602-9365- E4C617980939};0]> 

USERENV(1c8.650) 00:30:03:253 ProcessGPO: GPO passes the filter check.

Other options considered to provide a similar result:

  1. A security group filtered GPO, which would require manually adding and removing computers (or potentially automated with an export from DHCP that automatically added computers from the subnets to the security group)
  2. DHCP Scope option for configuring the DNS suffix search list (119 I think) - not currently supported by XP
  3. Some form of DHCP Scope ID that is recognised in XP and can be read through WMI or the registry
  4. DHCP Option 61 - Unique scope ID read from the registry (
  5. AD Site - Separate sites containing the subnets, with a site-based group policy (although SDOU suggests this wouldn't work, as the OU policy would overwrite the site based policy - the closer to the object the higher priority)
  6. Something in an automated process running on each workstation that would determine network changes and make local changes.

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Wednesday, March 26, 2008

Testing DNS records for scavenging

The commands in this post provide an easy method to export zone records from a Microsoft DNS server, and check whether the aging interval indicates this record would be scavenged given a hypthetical No refresh+Refresh interval.


  1. Export the records using dnscmd, which includes the aging timestamp for each record
  2. Run the following VBscript to convert the hours-since-epoch to a human readable datetime and compare against the DNS No-Refresh+Refresh interval.

For example:

  1. dnscmd %dnsserver% /enumrecords %zone% @ /continue > DNS_Records.txt
  2. cscript DNSScavengeTest.vbs DNS_Records.txt

'--- DNSScavengeTest.vbs ---

Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Const AGING_TOKEN = "[Aging:"

Const DDNS_NO_REFRESH = 7        ' The dynamic DNS no refresh period, where an update classified as a refresh will not be accepted for the record
Const DDNS_REFRESH = 7            ' The dynamic DNS refresh period, during which an update will be accepted for the record
Const GMT_OFFSET = +10            ' Offset in hours to adjust the resultant times based on the current GMT timezone

Set objFSO = CreateObject("Scripting.FileSystemObject")

If WScript.Arguments.Count = 1 Then 
    strFileName = WScript.Arguments(0) 
    wscript.echo "Specify a filename containing the output of dnscmd. eg DNSScavengeTest.vbs DNS_Records.txt"
End If

If Not objFSO.FileExists(strFileName) Then
    WScript.Echo "Error: " & strFileName & " file not found."
End If

Set objTextStream = objFSO.OpenTextFile(strFileName, ForReading)
strZoneRecords = objTextStream.ReadAll

For Each strLine in Split(strZoneRecords, vbCRLF)
    intStart = InStr(1, strLine, AGING_TOKEN, 1) 
    If intStart <> 0 Then                                ' Does this line contain an aging value?
        intStart = intStart + Len(AGING_TOKEN)
        intEnd = InStr(intStart, strLine, "]")
        If intEnd <> 0 Then intLength = intEnd - intStart
        strHost = Left(strLine, InStr(strLine, " ")-1)                ' Yes, extract the host

        intAging = Mid(strLine, intStart, intLength)                ' Extract the aging value, expressed in the decimal number of hours since 01/01/1601
        dtmDate = DateAdd("h", intAging, "01/01/1601 00:00:00 AM")        ' Convert to a date timestamp
        dtmDate = DateAdd("h", GMT_OFFSET, dtmDate)                ' Add the current GMT offset

        intDiff = DateDiff("h", dtmDate, Now)                    ' The difference between now and the timestampe
        intHourDiff = intDiff - ((DDNS_NO_REFRESH * 24) + (DDNS_REFRESH * 24))    ' Based on the dynamic DNS no-refresh and refresh periods combined
        If intHourDiff > 0 Then                            ' Is this a positive number, indicating the record will be scavenged
            intDay = CInt(intHourDiff / 24)                    ' Yes, convert to a number of days for output
            WScript.Echo strHost & ", " & dtmDate & ", " & intDay + DDNS_NO_REFRESH + DDNS_REFRESH & " days ago"    'This record would be scavenged
            WScript.Echo "*" & strHost & ", " & dtmDate            ' This record won't be scavenged
            intDay = 0
        End If
    End If

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Monday, March 24, 2008

Refreshing Computer Account AD Group Membership

I've completed some testing to help identify methods of updating the group membership for a computer account without having to restart the computer. The results show that while it is possible to update the token used to authenticate external resource access, a group policy refresh does not use the updated group membership for policy processing.

Testing was completed with:

  1. Windows XP SP2 workstation joined to a Windows 2000 domain, using Kerberos authentication.
  2. A share on the DC, with access granted to Group1, but denied to Group2, making it very easy to determine whether group membership is being considered for Group2

Test steps:

  1. Add the computer account to the Group1, allowing access to the test share
  2. Start a command prompt as system (with psexec /s /i /d cmd.exe)
  3. Verify access to the test share on the DC from the computer context
  4. Add the computer account to Group2, denying access to the data in the share mount point
  5. Verify access to the test share on the DC from the computer context still works as the computer has not received an updated token
  6. Use 'klist purge' to purge all tickets
  7. Run 'nltest /dclist:%domain%' (causing a request for a Kerberos TGT)
  8. Run 'klist tgt' to verify that a new TGT has been received
  9. Verify access to the test share on the DC from the computer context is now denied.

This demonstrates that it is possible to force an update to the Kerberos tickets containing the Privilege Attribute Certificate details of computer domain account group membership, and subsequently access file based resources with the updated token. The following information is related:

  • Using the steps above updates Kerberos tickets and ensures that remote resource access is performed with a refreshed token, however, this does not help when processing Group Policy (as can be seen by 'gpresult /z /scope computer'). Running gpresult, which lists the accounts a computer is a member of, does not include the groups added to the domain computer account (this appears to be due to cached information stored during the initial computer startup sequence). Destroying 'NT Authority\System' and 'NT Authority\Network Service' tokens associated with all processes (with 'Process Explorer'), combined with restarting the WMI service causes the wmiprvse binary to reload (required for gpresult), but the re-created tokens do not contain the updated domain SIDs
  • The security principal representing the LocalSystem context (S-1-5-18) is a local identity only. The concept of using computer accounts as members of domain security groups makes use of the domain computer account (similar to drawing a parallel between same-named local user accounts and domain user accounts).
  • When examining local tokens, a computer is a member of only three groups - a hidden member of administrators, and a member of two well-known groups (Everyone and 'Authenticated Users'). When accessing remote resources with the system account, the access token passed to the remote machine contains the SIDs of groups the computer's domain account is a member of
  • The user context when clearing the Kerberos cache is important; For example, if the 'klist purge' command is executed under the interactive context instead of the system context, the TGT for the computer account (ComputerName$) is not renewed.


Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Testing Network Ports from Windows

This article provides information on how to effectively test network connectivity between a local and remote endpoint on specific network ports and protocols.

Several methods are described, including portqry, port reporter and telnet.

Using PortQry.exe 2.0

The PortQry utility provides the flexibility to test any port number or range over TCP and UDP, as well as forcing a local source port and the destination. From a command prompt, run:

  1. portqry -n %server% -e %endpoint% -v

For example:
Portqry -n server1 -e 135 -v
Portqry -n server2 -e 53 -v -p BOTH
Portqry -n server3 -e 80 -v

Note that in the first example above, if RPC to server1 was not permitted, the result would be 'TCP port 135 (epmap service): FILTERED', whereas if it were allowed, a list of UUID's currently recorded by the endpoint mapper would be returned (also useful information in some cases).

Using telnet.exe

Remote endpoints on a particular TCP port that return a response (such as HTTP, FTP, SMTP etc) can be easily tested with telnet, from a command prompt run:

  1. Telnet %remoteServer% %Port%
  2. If the connection is established you may need to press enter or escape to receive a further response.

For example:
Telnet server3 80

Using Port Reporter

Locally on the machine:

  1. Obtain the port reporter tool from
  2. Install PortReporter by running: pr-setup -d '%systemroot%\temp'
  3. Start the PortReporter service: net start portreporter
  4. Perform the actions you want to log, log files are stored in %systemroot%\System32\LogFiles\PortReporter, PR-PORTS* contains the recorded port activity
  5. Stop the PortReporter service: net stop portreporter
  6. Uninstall PortReporter by running : pr-setup.exe -u


  1. See the reference to article 837243 for more information on how to interpret the log files
  2. The PR-PORTS* log file is formatted by: date,time,protocol,local port,local IP address,remote port,remote IP address,PID,module,user context


New features and functionality in PortQry version 2.0

How to Make Portqry.exe Only Report Listening Ports

How to Use Portqry.exe to Troubleshoot Microsoft Exchange Server Connectivity Issues

How to Use Portqry to Troubleshoot Active Directory Connectivity Issues

Availability and description of the Port Reporter tool

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Sunday, March 23, 2008

Using Recovery Console with RIS

This post provides information on using RIS to host a recovery console option for servers and/or workstations, without the danger of resetting the host machine computer account, documented by Microsoft as a caveat.

Using the tools.osc menu - at least in 2003 RIS - has the advantage of not resetting the computer account. This is because execution of the warning.osc or install.osc triggers a computer account reset, whereas using tools.osc bypasses that side of the process.

This means it's then practical to install the recovery console as a RIS option, and as long as it's triggered through the tools.osc menu, there is no danger of resetting the computer account (see the links below).

This could be a valuable exercise in any enterprise environment; it would only have to reduce the time to recover a single production server to be worth the effort.


How-to install recovery console for server 2000 and 2003:

How-to install recovery console for server 2003:;en-us;316558

Customizing and Automating Installations

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

PAE Boot.ini Switch for DEP or 4GB+ memory

This article summarises research into the PAE switch generally used on servers running Advanced Server/Enterprise Editions of Windows with more than 4GB of memory. It includes a brief summary of the uses of PAE and supported Operating Systems.

The Physical Address Extension capability of Windows is:

  • Used to provide access on 32-bit Intel systems to greater than 4GB of memory, and is not supported on 64-bit systems
  • Not supported on standard editions of Windows 2000
  • Supported on standard and enterprise editions of Windows 2003, but not recommended for production use
  • Used by adding the PAE switch to the boot.ini and is not required if DEP is enabled through boot.ini with the /noexecute switch, as the OS will assume PAE
  • Used by adding the PAE switch to the boot.ini and is not required if hardware-enforced DEP is enabled, as the OS will assume PAE
  • Only supported by 32-bit PCI adapters that use Dual Address Cycle (DAC) to transfer 64-bit addresses. Any incompatible adapters will cause driver problems on a server with PAE enabled
  • Also used on servers with a total of 4GB, as the total 4GB will not be addressable in user mode unless PAE is enabled.

Anyone considering enabling PAE on a Windows Server 2003 Standard Edition server should be wary. This is not recommended best practise by Microsoft, and both they and any application vendors may be unable to provide support if PAE is enabled.

Excerpt from 291988 referenced below:

  • IMPORTANT These configurations are not supported on Windows 2000 Professional and Windows 2000 Server. These configurations are only made available for testing purposes. Do not use these switches in a production environment unless you are using one of the products in the bulleted list at the top of this section.

    In these products, the 4 GB RAM Tuning feature enables a 3 GB area of user-mode memory for programs to use. This feature can expand the virtual address range for user-mode memory from 0x0000000 through 0xBFFFFFF (the user-mode address range is typically from 0x0000000 through 0x7FFFFFFF). The range of memory that is available for kernel-mode components shrinks from 0x80000000-0xFFFFFFFF to 0xC0000000-0xFFFFFFFF. We do not recommend using this feature in Windows Server 2003, Standard Edition in a production environment.

Physical Address Extension - PAE Memory and Windows

Operating Systems and PAE Support

The amount of RAM reported by the System Properties dialog box and the System Information tool is less than you
expect after you install Windows XP Service Pack 2

A description of the 4 GB RAM Tuning feature and the Physical Address Extension switch

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Saturday, March 22, 2008

Using 32-bit COM objects on x64 platforms

This post provides an example of the steps I had to take to get a 32-bit COM object registered and functionally accessible through a VBScript on an x64/AMD64 platform.

In this example, I was trying to automate prnadmin function on an x64 print server, providing a simple export of local printers as a housekeeping task for reference and easy printer recovery.

Normally prnadmin.dll (Windows Resource Kit Tools) and the associated VBScripts are easy to run, copy the scripts and prnadmin.dll, regsvr32.exe prnadmin.dll and all is well. However, this was the first time I’d tried it on an x64 server, and the normal methods didn’t work.

The following errors are returned, depending on the error handling in the script:

  • Microsoft VBScript runtime error: ActiveX component can't create object: 'PrintMaster.PrintMaster.1'
  • error: 0x1A8. Object required

The method I used to get this working was to register with the 32-bit version of regsvr32, then run the 32-bit version of cscript:

  • c:\WINDOWS\SysWOW64\regsvr32 prnadmin.dll
  • c:\WINDOWS\SysWOW64\cscript prnmgr.vbs -l

This registers the prnadmin.dll using the 32-bit WOW64 edition of regsvr32, which allows access to the ActiveX control through the VBScript when run with the equivalent 32-bit WOW64 VBScript edition of cscript.exe.

More Information

The hardware was an Intel EM64T capable processor running the x64 edition of Windows Server 2003 R2 SP2. My understanding is that Intel Extended Memory 64-bit Technology (EM64T) is functionally equivalent to the AMD64 platform – providing an extension to the IA-32 architecture to provide 64-bit registers for the eight existing IA-32 registers, plus additional extra registers. This is parallel to the extension of 8086 8-bit to 16-bit to 32-bit to 64-bit, eg. AH/AL - AX - EAX - RAX.

Note that this is potentially quite different on true 64-bit architecture – eg. The IA64 platform – as the WOW64 subsystem running on an x64/AMD64 system does not need to perform instruction translation/emulation, merely provide a restricted virtual address space.

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Active Directory Organizational Unit (OU) Design

This post provides information on a concept design for Organizational Unit structure within an Active Directory environment - using a top-level OU, security filtered-GPOs and sub-container objects for grouping. The example providing a flexible solution to manage servers in the domain.

First, I’ll provide a summary of OU benefits as I see them and the resultant OU design that takes advantage of these benefits. Note that an OU design cannot be considered in isolation, and must at least take into account the forest/domain design, site design, DC placement and delegation of administration.

OU Benefits

There are several uses for OUs, often not fully considered when creating or changing an OU structure. An OU structure can be modified with unexpected results if the resultant set of policy and delegation of administration is not taken into consideration.

Delegation of Administration

Administration of objects can be logically set at the container level. The DACL for any objects in the container, and typically sub-containers/sub-objects, will also be modified to provide an inherited security model.

Grouping of objects

Grouping objects by container – such as for different types of servers – can help from a visibility perspective when administering those objects. However, logical grouping of objects requires more management to ensure that objects are grouped correctly on an ongoing basis.

The major disadvantages of this method are that the grouping types used become blurred over time and often one server fits into multiple groups.

Targets for Group Policy Objects

The OU containers provide a logical target for GPOs, generally indicating that a particular GPO should apply to the objects in that container, as well as sub-containers and their objects.

Again, the major disadvantage of this method is that a computer object can exist only in one OU, limiting the flexibility in GPO application.

OU Design

The design is a combination of OU and container objects, useful for taking advantage of the three major uses for OUs described above. As a summary, this OU solution includes:
1. A top-level OU, used for targeting security-filtered GPOs
2. Sub-containers, used for logical grouping of objects and delegation of administration. Note these are container objects, not OU objects

In my opinion, using a combination of OUs and container objects provides the most flexibility with the least risk and lowest ongoing management costs. There is no possibility of assigning policies to sub-OUs and then having to resort to policy blocking, GPOs are applied at one level and simple security group membership controls application.

This design provides the most flexibility when:

  • Applying multiple GPOs to a single object without relying on blocking inheritance or complicated tree structures
  • Delegating administration to groups of objects. Containers can be created to delegate administration for groups of objects, without changing the GPO application.
  • Grouping objects for administration. Containers can be created for visibility of like objects, without changing GPO application.

There are several caveats when using this solution, but correct communication and following due process will negate any issues:

  1. Container objects cannot be created through dsa.msc, adsiedit.msc or something equivalent must be used.
  2. Standard utilities such as dsquery provide functions targeting OUs, but not containers. Dsquery * can still be used to manage any object in the AD.

OU/Container structure example

To provide logical grouping of objects and delegated access to those objects with flexible group policy application, the following structure could be used to manage domain member servers:

OU=SERVERSOUSecurity filtered GPO Target, Delegation of Administration
CN=Citrix,OU=SERVERSContainerComputer grouping, Delegation of Administration
CN=Exchange,OU=SERVERSContainerComputer grouping, Delegation of Administration
CN=%APPLICATION%,OU=SERVERSContainerComputer grouping, Delegation of Administration
OU=%COMPANY%,OU=SERVERSOUSecurity filtered GPO Target, Delegation of Administration based on companies within one domain

OU/Container Security example


Note that the ACLs would typically propagate to child objects and containers as appropriate.


Designing an OU Structure that Supports Group Policy

Designing Organizational Units for Delegation of Administration

Creating an Organizational Unit Design

Group Policy Settings Reference

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Troubleshooting computer accounts in an Active Directory domain

Included are a few esoteric commands and example output of validating Windows Server 2003 computer account objects in an Active Directory domain. The information returned can help troubleshoot Kerberos, the secure channel with the domain, Service Principal Names registered against the computer account, and various bits of local computer information such as group membership and local rights.

Note that this was all run under the system context, the easiest way I know of to get this information, which for network requests translates to networkservice and the AD computer account object.

This was completed by connecting to the console (mstsc /v:%host% /console), and then running:

  • psexec /s /i /d cmd.exe

Note that the console connection is important, as the interactive psexec process is attached to the interactive winlogon console session.

Utilities required:

  • psexec
  • klist
  • setspn
  • nltest
  • whoami

Example output:

C:\>klist tgt

Cached TGT:

ServiceName: krbtgt
TargetName: krbtgt
FullServiceName: COMPUTER$
TargetDomainName: FQDN.DOMAIN
AltTargetDomainName: FQDN.DOMAIN
TicketFlags: 0x40e00000
KeyExpirationTime: 1/1/1601 10:00:00
StartTime: 1/16/2008 11:09:20
EndTime: 1/16/2008 21:09:20
RenewUntil: 1/23/2008 11:09:20
TimeSkew: 1/1/1601 10:00:00

C:\>klist tickets

Cached Tickets: (8)

KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
End Time: 1/16/2008 21:09:20
Renew Time: 1/23/2008 11:09:20

KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
End Time: 1/16/2008 21:09:20
Renew Time: 1/23/2008 11:09:20

KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
End Time: 1/16/2008 21:09:20
Renew Time: 1/23/2008 11:09:20

KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
End Time: 1/16/2008 21:09:20
Renew Time: 1/23/2008 11:09:20

KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
End Time: 1/16/2008 21:09:20
Renew Time: 1/23/2008 11:09:20

KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
End Time: 1/16/2008 21:09:20
Renew Time: 1/23/2008 11:09:20

KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
End Time: 1/16/2008 21:09:20
Renew Time: 1/23/2008 11:09:20

KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
End Time: 1/16/2008 21:09:20
Renew Time: 1/23/2008 11:09:20

C:\>setspn -L COMPUTER
Registered ServicePrincipalNames for CN=COMPUTER,OU=Test,DC=domain,DC=com:

C:\>nltest /sc_query:corp
Trusted DC Name \\DC.FQDN.DOMAIN
Trusted DC Connection Status Status = 0 0x0 NERR_Success
The command completed successfully

C:\>nltest /sc_verify:corp
Trusted DC Name \\DC.FQDN.DOMAIN
Trusted DC Connection Status Status = 0 0x0 NERR_Success
Trust Verification Status = 0 0x0 NERR_Success
The command completed successfully

C:\>whoami /all 


User Name SID 
=================== ======== 
nt authority\system S-1-5-18 


Group Name Type SID Attributes 
================================ ================ ============ ================================================== 
BUILTIN\Administrators Alias S-1-5-32-544 Enabled by default, Enabled group, Group owner 
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group 
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group 


Privilege Name Description State 
=============================== ========================================= ======== 
SeTcbPrivilege Act as part of the operating system Enabled 
SeCreateGlobalPrivilege Create global objects Enabled 
SeTakeOwnershipPrivilege Take ownership of files or other objects Disabled 
SeCreatePagefilePrivilege Create a pagefile Enabled 
SeLockMemoryPrivilege Lock pages in memory Enabled 
SeAssignPrimaryTokenPrivilege Replace a process level token Disabled 
SeIncreaseQuotaPrivilege Adjust memory quotas for a process Disabled 
SeIncreaseBasePriorityPrivilege Increase scheduling priority Enabled 
SeCreatePermanentPrivilege Create permanent shared objects Enabled 
SeDebugPrivilege Debug programs Enabled 
SeAuditPrivilege Generate security audits Enabled 
SeSecurityPrivilege Manage auditing and security log Disabled 
SeSystemEnvironmentPrivilege Modify firmware environment values Disabled 
SeChangeNotifyPrivilege Bypass traverse checking Enabled 
SeBackupPrivilege Back up files and directories Disabled 
SeRestorePrivilege Restore files and directories Disabled 
SeShutdownPrivilege Shut down the system Disabled 
SeLoadDriverPrivilege Load and unload device drivers Disabled 
SeProfileSingleProcessPrivilege Profile single process Enabled 
SeSystemtimePrivilege Change the system time Disabled 
SeUndockPrivilege Remove computer from docking station Disabled 
SeManageVolumePrivilege Perform volume maintenance tasks Enabled 
SeImpersonatePrivilege Impersonate a client after authentication Enabled 

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Tuesday, March 18, 2008

260+ character MAX_PATH limitations in filenames

Accessing files with a full path\filename of greater than the traditional MAX_PATH constant of 260 characters can still be challenging in today's Operating Systems. This article provides some insight into the problem, and methods to identify and workaround the issue.

Identifying the problem

The problem occurs through common applications, explorer, Office apps, command prompt, and sometimes returns meaningful errors (the full path 'x' is too long – md/mkdir) but often returns nothing (explorer) or an obscure error.

One method I use to identify these problems – particularly because they usually occur when trying to copy the data – is robocopy.

The verbose logs from a robocopy command will identify this particular error with a general syntax error, but it's easy enough to tell with the path referenced if it's a 260+ problem. The text logged by robocopy (version XP010 in this case) is:
"ERROR 123 (0x0000007B)"


Testing was completed, showing that:

  • The server name and share name definitely do count as part of
    the total 260 character path limitation when using UNC references, eg file://server/share
  • However, when using a mapped drive, the server name and share
    name are irrelevant; it is the constructed path with the drive letter that counts, eg: f:\
  • Despite various Microsoft articles, using the \\?\ syntax to
    disable path parsing does not force use of the Unicode equivalent function (which didn't really make sense anyway).


Three successful methods to work around this issue have been tested, detailed below.

Method 1 - Use a utility that can bypass the 260 character limitations by using the Unicode version of the CopyFile() function (CopyFileW).

I used a utility called FastCopy, which supports paths longer than 260 characters, presumably by using the Unicode version of the relevant functions.

Method 2 - Use the 8.3 short filenames generated by the filesystem to reduce the path.

This didn't occur to me until I was nearly finished with this exercise, and while it's easier to access individual files in this way, batching this to copy disparate files is not so easy.

Method 3 - Create a share deeper in the directory path, and access the file through the share, either UNC or mapped drive.

This isn't very practical in most situations, but if it's possible to create new shares, this is probably the easiest method.

Other testing completed:

  • Copying through explorer also has the same results.
  • Tried with the "\\?\f:\" syntax, which made the problem worse (because of the extra few characters), even though this is supposed to bypass 260 character limitations using the Unicode function.
  • Accessing the file locally on the 2003 SP2 R2 server, or
    remotely via XPSP2 has the same result (with a mapped drive)


CopyFile function

Naming a Volume

Making Room for Long Filenames

Naming a File

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Saturday, March 15, 2008

Create or modify a security template for NTFS permissions

This process will allow you to create a security template that can be applied on an NTFS volume. The major benefit of this is to have a known-good record of NTFS security, which can be reapplied at any time. This can be useful in reversing/recovering from unwanted changes, providing audit information, and generally allowing more rigour when securing a shared file system.


  1. If modifying an existing template, skip to step 3.
  2. Copy an existing template or use the sample template from the 'References' section to create a new security template.
  3. Ensure the ACL is correctly set on the source path (including object and container inheritance)
  4. Run 'setacl -ot file -actn list -lst f:sddl -on \\SERVER%\%PATH%'
  5. For Each SID, run psgetsid \\%SERVER% %SID% to verify the group is correct.
  6. Copy the string into the [File Security] section and replace the '\\?\UNC\%SERVER%\%PATH%' reference with the local path (eg 'D:\Temp')
  7. Run 'secedit /configure /db %TEMP%\SEC%RANDOM%.SDB /cfg %NEWLY_CREATED_INF% /areas FILESTORE /log %TEMP%\SEC%RANDOM%.Log' to test the newly created template.
  8. If the template applies successfully, use cacls or the GUI to verify the permissions are still set correctly (including inheritance and propagation).
  9. If the template doesn’t apply successfully, check the log, and beware that permissions may be in an unpredictable state as the security template application stopped.


  • SetACL.exe, publicly available commandline utility (see references below)
  • PSGetSid.exe, SysInternals utility (see references below)


  1. This procedure has been tested only on Windows Server 2003.
  2. The SetACL command above specifies an ObjectType of file, an Action of list, a List format with an output format in SDDL syntax from the specified Object Name. eg. setacl -ot file -actn list -lst f:sddl -on \\%server%\d$
  3. When using PsGetSID, if the SID refers to a domain object other than the domain your workstation is in, you will need to supply a Domain Controller for the domain.
  4. If you are confident with the SDDL syntax, you can skip steps 3 and 4, simply finding the SID and creating/modifying a template.
  5. Note that if a directory in a security template entry does not exist, application of the security template will stop, potentially leaving the ACLs in an unpredictable state.


SDDL syntax in secedit security templates

SetACL commandline utility:

PSGetSID commandline utility:

SDDL Syntax:

Example template:


; Change Control
[File Security]

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

Sunday, March 9, 2008

Find where a user is connecting from through WMI

It’s often good to know which computer a user is on right now, but historically that’s not that very easy to find – until FU that is.

The logic behind this command is that generally every user has a home drive, and that home drive is mapped during logon. The lanmanserver service on the file server has the session details of which user has connected from which computer/IP.

Therefore, by querying the win32_serversession of the file server, you can determine where users are connecting from, which will tell you the workstation they are currently working on.

Note that this command requires dsquery, dsget and WMIC. It also requires access to the file server to enumerate sessions (see below for more information).

You can run this at the command prompt:
Set user=%username%
for /f "tokens=2 delims=\" %i in ('"dsquery user -name %user% dsget user -hmdir find /i "%user%""') do @for /f "skip=1 tokens=1-3" %m in ('"wmic /node:"%i" path win32_serversession WHERE "UserName Like '%user%'" Get ComputerName,ActiveTime,IdleTime"') do @for /f "tokens=2" %q in ('"ping -a %n -n 1 find /i "pinging""') do @echo %q %user% %n %i %m %o

Note that you can also use partial username matches, the WMI query is a like clause.

I realise that’s not easy to type in, so you can use a doskey macro, by:

  • Putting the command below in a text file (c:\windows\temp\macro.txt in this example)
  • Running doskey /macrofile=c:\windows\temp\macro.txt

To make doskey load the macros every time you start a command shell, run:

reg add "HKEY_LOCAL_MACHINE\software\microsoft\command processor" /v autorun /t REG_SZ /d "doskey /macrofile=c:\windows\temp\macros.txt"

You can then run:

fu %username1% [%username2%] [%username3%]

Which will return the computername, username, IP address, active time and idle time of the user you’ve asked for.

Unfortunately, securing this is quite hard. I'm embarrassed to report that the user needs to be an administrator or 'server operator' of the file server. As far as I can tell this comes back to the NetSessionEnum() function, called by the Win32_Session WMI class when enumerating sessions.

The NetSessionEnum function call allows non-administrators to enumerate level 0 or 10, but it appears as though WMI always queries for level 1 or 2 (even if you only query the WMI class for user/computer). This is very disappointing, as in a secure environment you won’t want to let help desk/desktop support be server operators of your file servers, and these are the people who would find this command most useful.

I went some way towards seeing whether you could adjust a securable object/low-level security descriptor object (eg. through winobj) to expand the allowed access to this information, but was unsuccessful.

Some other thoughts:
  • Psloggedon uses the netsessionenum function, and it does tell you that someone is logged on remotely, but unfortunately it doesn’t provide the computer, only the username and time.
  • PowerShell could probably be used to call the NetSessionEnum function easily enough with the reduced information levels that don’t require administrative privileges
As an aside, if you do want to allow non-administrators generic CIMv2 WMI access to a 2003 server, you can do this by:
  • Add a group to wmimgmt.msc to provide 'enable account' and 'remote enable' to the root\CIMv2 namespace.
  • Add the same group to the local 'Distributed COM Users' (Server 2003) on each WMI target. This provides remote access for DCOM calls.
After you've done this, a command such as the following should work:
wmic /user:"%domain%\%user%" /node:"%fileServer%" path win32_operatingsystem

Note that users given this limited access cannot:
  • Execute WMI methods
  • Write data through WMI providers

The Win32_ServerSession Windows Management Instrumentation class returns incorrect server session instances on a Windows Server 2003-based computer

NetSessionEnum Function

Low-level Security Descriptor Functions

Securable Objects

Access to WMI Securable Objects

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.

Read more!

All Posts

printQueue AD objects for 2003 ClusterVirtualCenter Physical to VirtualVirtual 2003 MSCS Cluster in ESX VI3
Finding duplicate DNS recordsCommand-line automation – Echo and macrosCommand-line automation – set
Command-line automation - errorlevels and ifCommand-line automation - find and findstrBuilding blocks of command-line automation - FOR
Useful PowerShell command-line operationsMSCS 2003 Cluster Virtual Server ComponentsServer-side process for simple file access
OpsMgr 2007 performance script - VMware datastores...Enumerating URLs in Internet ExplorerNTLM Trusts between 2003 and NT4
2003 Servers with Hibernation enabledReading Shortcuts with PowerShell and VBSModifying DLL Resources
Automatically mapping printersSimple string encryption with PowerShellUseful NTFS and security command-line operations
Useful Windows Printer command-line operationsUseful Windows MSCS Cluster command-line operation...Useful VMware ESX and VC command-line operations
Useful general command-line operationsUseful DNS, DHCP and WINS command-line operationsUseful Active Directory command-line operations
Useful command-linesCreating secedit templates with PowerShellFixing Permissions with NTFS intra-volume moves
Converting filetime with vbs and PowerShellDifference between bat and cmdReplica Domain for Authentication
Troubleshooting Windows PrintingRenaming a user account in ADOpsMgr 2007 Reports - Sorting, Filtering, Charting...
WMIC XSL CSV output formattingEnumerating File Server ResourcesWMIC Custom Alias and Format
AD site discoveryPassing Parameters between OpsMgr and SSRSAnalyzing Windows Kernel Dumps
Process list with command-line argumentsOpsMgr 2007 Customized Reporting - SQL QueriesPreventing accidental NTFS data moves
FSRM and NTFS Quotas in 2003 R2PowerShell Deleting NTFS Alternate Data StreamsNTFS links - reparse, symbolic, hard, junction
IE Warnings when files are executedPowerShell Low-level keyboard hookCross-forest authentication and GP processing
Deleting Invalid SMS 2003 Distribution PointsCross-forest authentication and site synchronizati...Determining AD attribute replication
AD Security vs Distribution GroupsTroubleshooting cross-forest trust secure channels...RIS cross-domain access
Large SMS Web Reports return Error 500Troubleshooting SMS 2003 MP and SLPRemotely determine physical memory
VMware SDK with PowershellSpinning Excel Pie ChartPoke-Info PowerShell script
Reading web content with PowerShellAutomated Cluster File Security and PurgingManaging printers at the command-line
File System Filters and minifiltersOpsMgr 2007 SSRS Reports using SQL 2005 XMLAccess Based Enumeration in 2003 and MSCS
Find VM snapshots in ESX/VCComparing MSCS/VMware/DFS File & PrintModifying Exchange mailbox permissions
Nested 'for /f' catch-allPowerShell FindFirstFileW bypassing MAX_PATHRunning PowerSell Scripts from ASP.Net
Binary <-> Hex String files with PowershellOpsMgr 2007 Current Performance InstancesImpersonating a user without passwords
Running a process in the secure winlogon desktopShadow an XP Terminal Services sessionFind where a user is logged on from
Active Directory _msdcs DNS zonesUnlocking XP/2003 without passwords2003 Cluster-enabled scheduled tasks
Purging aged files from the filesystemFinding customised ADM templates in ADDomain local security groups for cross-forest secu...
Account Management eventlog auditingVMware cluster/Virtual Center StatisticsRunning scheduled tasks as a non-administrator
Audit Windows 2003 print server usageActive Directory DiagnosticsViewing NTFS information with nfi and diskedit
Performance Tuning for 2003 File ServersChecking ESX/VC VMs for snapshotsShowing non-persistent devices in device manager
Implementing an MSCS 2003 server clusterFinding users on a subnetWMI filter for subnet filtered Group Policy
Testing DNS records for scavengingRefreshing Computer Account AD Group MembershipTesting Network Ports from Windows
Using Recovery Console with RISPAE Boot.ini Switch for DEP or 4GB+ memoryUsing 32-bit COM objects on x64 platforms
Active Directory Organizational Unit (OU) DesignTroubleshooting computer accounts in an Active Dir...260+ character MAX_PATH limitations in filenames
Create or modify a security template for NTFS perm...Find where a user is connecting from through WMISDDL syntax in secedit security templates

About Me

I’ve worked in IT for over 13 years, and I know just about enough to realise that I don’t know very much.