Heard this information in an article today from Marketplace Tech report which is here which contains information and content from a computerworld article here.
"email is not even transmitted encrypted, it's transmitted in the clear" - David Jefferson, a computer scientist at Lawrence Livermore National Laboratories and chairman of the election watchdog group Verified Voting.
This is completely false for some email. Period.
Misinformation or misleading things in the news bother me so this I felt compelled to write about. Email is not necessarily sent in the clear. Yes it can be however that's not always the case. I suppose some email may be transmitted in the clear by older systems and people that have configured their systems to act that way. Same as if you wanted to you could mail someone cash through the postal service, yes you could do that if you wanted to, but the statement of "everyone sends cash through the postal service" would be false.
So the question of course is how much email is transmitted this way? Well, Microsoft Exchange email systems had a 65% market share as of 2009 (1) so it's safe to say at least a significant portion of email traffic flows through Microsoft Exchange Email servers. The exact percentage of "how much email is sent in the clear versus encrypted" would be a bit challenging for me to quantify and is beyond my means so is not something I can answer.
However it is important to note that modern email systems have the ability (if not the default) to transmit via an encrypted connection. This is done in some cases via TLS or can be done via "opportunistic TLS" as Microsoft has implemented. You could even (in situations requiring higher security) require all mail sent to you to be encrypted.
Microsoft Exchange 2007 (2) and 2010 (3) have this feature enabled by default and as such if the other end supports it, they will encrypt their email sent to said systems.
It looks like sendmail (popular linux SMTP software) also by default will try to establish a TLS session when sending email. (4)
Yes this method of sending email in an encrypted manner is not a perfectly secure system, nor are most (if any) systems perfectly secure. However to state that email is sent "in the clear" is only partially true at best. For a hypothetical organization dealing with voting, they could easily require encryption of all email sent to them which would mean no hypothetical votes would be emails sent "in the clear"
1 - http://www.microsoft.com/presspass/features/2009/jan09/01-16qascult.mspx
2 - http://technet.microsoft.com/en-us/library/bb430753(v=exchg.80).aspx
3 - http://technet.microsoft.com/en-us/library/bb430753.aspx
4 - http://www.sendmail.org/m4/starttls.html#disable_starttls
Monday, March 5, 2012
Tuesday, August 2, 2011
Powershell Script to Archive IIS Log Files
Here's a script that I put together to deal with windows server log files (Mainly IIS) as previously it was a manual process for me and something I got sick of. I found scripting pieces around that were close to what I wanted but didn't fine something exactly so mashed this script together.
The script basically takes a list of servers you give it, checks each server to determine if it's 2003 or 2008, (as default IIS directories changed between 03 and 08) and then will look in the default IIS log files location for files. Anything older than the age specified it will move into a sub-folder named the year.
One shortcoming is that the script assumes there is already a folder created in your log files directory with the year. I did this as that way I could simply enable compression on those "archive" folders and then not have to deal with that in my script as it seemed to be a pain to try to enable compression using powershell. So if I wanted to put more effort into it there is certainly room for improvement.
Here's the script:
# Script to cleanup IIS files on various given servers
#define parameters
$iispath03 = "\C$\WINDOWS\system32\LogFiles\"
$iispath08 = "\C$\inetpub\logs\LogFiles\"
$OS = "default"
#set archive period after which to move logs to compressed folder
$Now = Get-Date
$Days = “8”
$LastWrite = $Now.AddDays(-$days)
#define list of IIS servers to cleanup logs on
$IISServers = @("server1","server2","server3","server4","etc","etc","etc","etc")
#Define Function to check if server 03 or 08
Function GetServerOS
{param ($strServerName)
$strCategory = "computer"
$strfilter = "(&(objectCategory=Computer)(Name=$strServerName))"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = $strfilter
$colProplist = “operatingsystem”
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{$objComputer = $objResult.Properties
$objComputer.operatingsystem
}
}
#Gather list of IIS log file directories
foreach ($server in $IISServers)
{
#Check OS of server in question
$FullOS = GetServerOS $server
if ($FullOS[1].Contains("2003")){
$OS = "2003"
$IISDir = "\\" + $server + $iispath03
}
elseif($FullOS[1].Contains("2008")){
$OS = "2008"
$IISDir = "\\" + $server + $iispath08
}
else{
$OS = "Error"
$IISDir = "Error"
}
$IISLogDirs = dir $IISDir W3* | where {$_.psIsContainer -eq $true} | select fullname
if($IISLogDirs)
{
#Cycle through each of the discovered directories
foreach ($dir in $IISLogDirs)
{
#set current directory (should be compressed) to archive files to
$archivedir = $dir.fullname + "\" + $Now.year + "\"
#check if the current year directory exists, if not create it
if (!(Test-Path -path $archivedir))
{
New-Item $archivedir -type directory
}
#Get list of log files to cleanup
$logfiles = get-childitem $dir.fullname *.log | Where {$_.LastWriteTime -le “$LastWrite”} | select fullname
if($logfiles)
{
foreach ($file in $logfiles)
{
copy-item $file.fullname $archivedir
remove-item $file.fullname
}
}
}
}
}
The script basically takes a list of servers you give it, checks each server to determine if it's 2003 or 2008, (as default IIS directories changed between 03 and 08) and then will look in the default IIS log files location for files. Anything older than the age specified it will move into a sub-folder named the year.
One shortcoming is that the script assumes there is already a folder created in your log files directory with the year. I did this as that way I could simply enable compression on those "archive" folders and then not have to deal with that in my script as it seemed to be a pain to try to enable compression using powershell. So if I wanted to put more effort into it there is certainly room for improvement.
Here's the script:
# Script to cleanup IIS files on various given servers
#define parameters
$iispath03 = "\C$\WINDOWS\system32\LogFiles\"
$iispath08 = "\C$\inetpub\logs\LogFiles\"
$OS = "default"
#set archive period after which to move logs to compressed folder
$Now = Get-Date
$Days = “8”
$LastWrite = $Now.AddDays(-$days)
#define list of IIS servers to cleanup logs on
$IISServers = @("server1","server2","server3","server4","etc","etc","etc","etc")
#Define Function to check if server 03 or 08
Function GetServerOS
{param ($strServerName)
$strCategory = "computer"
$strfilter = "(&(objectCategory=Computer)(Name=$strServerName))"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = $strfilter
$colProplist = “operatingsystem”
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{$objComputer = $objResult.Properties
$objComputer.operatingsystem
}
}
#Gather list of IIS log file directories
foreach ($server in $IISServers)
{
#Check OS of server in question
$FullOS = GetServerOS $server
if ($FullOS[1].Contains("2003")){
$OS = "2003"
$IISDir = "\\" + $server + $iispath03
}
elseif($FullOS[1].Contains("2008")){
$OS = "2008"
$IISDir = "\\" + $server + $iispath08
}
else{
$OS = "Error"
$IISDir = "Error"
}
$IISLogDirs = dir $IISDir W3* | where {$_.psIsContainer -eq $true} | select fullname
if($IISLogDirs)
{
#Cycle through each of the discovered directories
foreach ($dir in $IISLogDirs)
{
#set current directory (should be compressed) to archive files to
$archivedir = $dir.fullname + "\" + $Now.year + "\"
#check if the current year directory exists, if not create it
if (!(Test-Path -path $archivedir))
{
New-Item $archivedir -type directory
}
#Get list of log files to cleanup
$logfiles = get-childitem $dir.fullname *.log | Where {$_.LastWriteTime -le “$LastWrite”} | select fullname
if($logfiles)
{
foreach ($file in $logfiles)
{
copy-item $file.fullname $archivedir
remove-item $file.fullname
}
}
}
}
}
Monday, April 11, 2011
Sales Emails Yes. Sales Calls No.
So yes I understand you're trying to sell your product, but I just spent 2.5 minutes on the phone with you (which was pretty short for a sales call) when I have zero interest in your product. I wasted both your time and mine as well as broken my train of thought on whatever I was doing. A couple of calls and I've wasted about 30 minutes of work time.
Whereas if you send me an email I can within about 5-10 seconds determine if I have any interest in your product, as well as have that email to reference down the road if something comes up. Oh yeah I remember getting an email about a solution for that...
So please, spend less time on cold calls and more time on 1) sending out informative emails, 2) responding quickly to sales information requests, and 3) educating your sales force more about your product.
Now, back to work.
Whereas if you send me an email I can within about 5-10 seconds determine if I have any interest in your product, as well as have that email to reference down the road if something comes up. Oh yeah I remember getting an email about a solution for that...
So please, spend less time on cold calls and more time on 1) sending out informative emails, 2) responding quickly to sales information requests, and 3) educating your sales force more about your product.
Now, back to work.
Wednesday, August 4, 2010
Finding Large Emails Transferred - Exchange Management Shell
This Exchange management shell command will reach out to all your hub transport servers and then search through the tracking logs for messages greater than a given size. Handy if you want to track down larger messages moving through your Exchange environment. This particular example searches for stuff greater than 50MB.
Get-ExchangeServer | where {$_.isHubTransportServer -eq $true} | Get-MessageTrackingLog -resultsize unlimited -start "8/1/2010 12:00AM" -end "8/4/2010 11:59pm" | where {$_.TotalBytes -gt 50000000}
Get-ExchangeServer | where {$_.isHubTransportServer -eq $true} | Get-MessageTrackingLog -resultsize unlimited -start "8/1/2010 12:00AM" -end "8/4/2010 11:59pm" | where {$_.TotalBytes -gt 50000000}
Thursday, April 8, 2010
Powershell script to find a specific OS in a domain
Here's a piece of code modified from this scripting guy post that allows you to list computer accounts with specific operating systems that aren't disabled in your domain. It's written as a function so you just have to write your query string and pass it to the function. aka GetDomainComps *2008* will return all the AD computer accounts with 2008 in their name.
Function GetDomainComps
{param ($strOS)
$strCategory = "computer"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = "(&(objectCategory=$strCategory)(operatingSystem=$strOS)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
$colProplist = "name"
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{$objComputer = $objResult.Properties; $objComputer.name}
}
GetDomainComps *2003*
Function GetDomainComps
{param ($strOS)
$strCategory = "computer"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = "(&(objectCategory=$strCategory)(operatingSystem=$strOS)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
$colProplist = "name"
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{$objComputer = $objResult.Properties; $objComputer.name}
}
GetDomainComps *2003*
Monday, March 15, 2010
Setup Netapp System Manager Read-Only and Cifs Admins
I had a need to create a read-only account to access our netapp filers from Netapp System Manager but also wanted to have an account that had read-only to everything but read and write to cifs configuration.
Luckily creating a read-only account is clearly detailed in TR-3358 so I just had to add on the cifs read-write portion for my purposes. The following are the commands that I used. Note the pieces that I added to the info in TR-3358 were the role for cifs read/write adn the api-cf-status for an active/active filer.
useradmin role add nsm-login -a login-http-admin,api-system-get-*
useradmin role add nsm-view –a api-aggr-list-info,api-disk-sanown-list-info,api-license-list-info,api-options-get,api-perf-object-get-instances,api-snmp-status,api-volume-list-info*,cli-priv,api-aggr-options-list-info,api-aggr-check-spare-low,api-cf-status
useradmin role add nsm-volumes-view -a api-volume-get-root-name,api-snapshot-reserve-list-info,api-volume-get-language,api-volume-options-list-info,cli-date
useradmin role add nsm-sharedfolders-view -a api-cifs-share-list-iter*,api-nfs-exportfs-list-rules,api-cifs-session-list-iter*
useradmin role add nsm-qtree-view -a api-qtree-list-iter*
useradmin role add nsm-disk-view -a api-system-cli,api-disk-list-info,cli-options
useradmin role add nsm-aggr-view -a api-aggr-get-root-name,api-snapshot-list-info
useradmin role add nsm-sharedfolders-write -a cli-cifs,api-cifs*
**********************
useradmin group add nsm-storage-view-cifswrite -r nsm-login,nsm-view,nsm-volumes-view,nsm-sharedfolders-view,nsm-qtree-view,nsm-disk-view,nsm-aggr-view,nsm-sharedfolders-write
useradmin group add nsm-storage-view -r nsm-login,nsm-view,nsm-volumes-view,nsm-sharedfolders-view,nsm-qtree-view,nsm-disk-view,nsm-aggr-view
*********************
useradmin user add nsmcifsmgr -g nsm-storage-view,nsm-storage-view-cifswrite
useradmin user add nsmviewonly -g nsm-storage-view
Luckily creating a read-only account is clearly detailed in TR-3358 so I just had to add on the cifs read-write portion for my purposes. The following are the commands that I used. Note the pieces that I added to the info in TR-3358 were the role for cifs read/write adn the api-cf-status for an active/active filer.
useradmin role add nsm-login -a login-http-admin,api-system-get-*
useradmin role add nsm-view –a api-aggr-list-info,api-disk-sanown-list-info,api-license-list-info,api-options-get,api-perf-object-get-instances,api-snmp-status,api-volume-list-info*,cli-priv,api-aggr-options-list-info,api-aggr-check-spare-low,api-cf-status
useradmin role add nsm-volumes-view -a api-volume-get-root-name,api-snapshot-reserve-list-info,api-volume-get-language,api-volume-options-list-info,cli-date
useradmin role add nsm-sharedfolders-view -a api-cifs-share-list-iter*,api-nfs-exportfs-list-rules,api-cifs-session-list-iter*
useradmin role add nsm-qtree-view -a api-qtree-list-iter*
useradmin role add nsm-disk-view -a api-system-cli,api-disk-list-info,cli-options
useradmin role add nsm-aggr-view -a api-aggr-get-root-name,api-snapshot-list-info
useradmin role add nsm-sharedfolders-write -a cli-cifs,api-cifs*
**********************
useradmin group add nsm-storage-view-cifswrite -r nsm-login,nsm-view,nsm-volumes-view,nsm-sharedfolders-view,nsm-qtree-view,nsm-disk-view,nsm-aggr-view,nsm-sharedfolders-write
useradmin group add nsm-storage-view -r nsm-login,nsm-view,nsm-volumes-view,nsm-sharedfolders-view,nsm-qtree-view,nsm-disk-view,nsm-aggr-view
*********************
useradmin user add nsmcifsmgr -g nsm-storage-view,nsm-storage-view-cifswrite
useradmin user add nsmviewonly -g nsm-storage-view
Tuesday, February 9, 2010
Expiring Users Script That Sends an Email
Below is a script that I created to query AD for expiring user accounts and then to email the results out. The only flaw is that it doesn't filter account that have already expired, so those will show. Which yeah I could add that in but it would be MUCH easier to just re-write this in powershell to do the same.
As always test and use at your own risk.
' VB Script to scrape AD for users with expiring dates
' set and to email the results in an html table with info
StrEmailTo = "address@here.com; address2@here.com"
StrEmailFrom = "fromaddress@here.com"
StrEmailSubject = "insert subject here"
Strsmtpserver = "youremailserver.domain.com"
Dim lngDate, objDate, dtmAcctExp, k
' Obtain local time zone bias from machine registry.
Set objShell = CreateObject("Wscript.Shell")
lngBiasKey = objShell.RegRead("HKLMSystemCurrentControlSetControl" _
& "TimeZoneInformationActiveTimeBias")
If (UCase(TypeName(lngBiasKey)) = "LONG") Then
lngBias = lngBiasKey
ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then
lngBias = 0
For k = 0 To UBound(lngBiasKey)
lngBias = lngBias + (lngBiasKey(k) * 256^k)
Next
End If
' Use ADO to search the domain.
Set adoConnection = CreateObject("ADODB.Connection")
Set adoCommand = CreateObject("ADODB.Command")
adoConnection.Provider = "ADsDSOOBject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection
' Determine the DNS domain from the RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")
' Filter to retrieve all user objects with accounts
' that expire.
strFilter = "(&(objectCategory=person)(objectClass=user)" _
& "(!accountExpires=0)(!accountExpires=9223372036854775807))"
strQuery = "<LDAP://" & strDNSDomain & ">;" & strFilter _
& ";distinguishedName,accountExpires;subtree"
' Run the query.
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
Set adoRecordset = adoCommand.Execute
Set objMessage = CreateObject("CDO.Message")
objMessage.Subject = StrEmailSubject
objMessage.From = StrEmailFrom
objMessage.To = StrEmailTo
objMessage.HTMLBody = "<font size=" & chr(34) & "2" & chr(34) & " face=" & chr(34) & "Arial" & chr(34) & ">" & _
"Below is the expiring users report:<br><br><table border-" & Chr(34) & "1" & Chr(34) & "><tr><th>Date Expires</th><th>-----</th><th>User</th></tr><tr>"
'**********************
' Enumerate the recordset.
Do Until adoRecordset.EOF
' Retrieve attribute values.
strDN = adoRecordset.Fields("distinguishedName").Value
lngDate = adoRecordset.Fields("accountExpires")
' Convert accountExpires to date in current time zone.
Set objDate = lngDate
dtmAcctExp = Integer8Date(objDate, lngBias)
' Output to console.
objMessage.HTMLBody = objMessage.HTMLBody & "<tr><td>" & dtmAcctExp & " " & "</td><td> </td><td>" & strDN & "</td></tr>"
adoRecordset.MoveNext
Loop
adoRecordset.Close
objMessage.HTMLBody = objMessage.HTMLBody & "</table>"
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = Strsmtpserver
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objMessage.Configuration.Fields.Update
objMessage.Send
'**********************
' Clean up.
adoConnection.Close
Function Integer8Date(ByVal objDate, ByVal lngBias)
' Function to convert Integer8 (64-bit) value to a date, adjusted for
' local time zone bias.
Dim lngAdjust, lngDate, lngHigh, lngLow
lngAdjust = lngBias
lngHigh = objDate.HighPart
lngLow = objdate.LowPart
' Account for bug in IADslargeInteger property methods.
If (lngLow < 0) Then
lngHigh = lngHigh + 1
End If
If (lngHigh = 0) And (lngLow = 0) Then
lngAdjust = 0
End If
lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
+ lngLow) / 600000000 - lngAdjust) / 1440
Integer8Date = CDate(lngDate)
End Function
As always test and use at your own risk.
' VB Script to scrape AD for users with expiring dates
' set and to email the results in an html table with info
StrEmailTo = "address@here.com; address2@here.com"
StrEmailFrom = "fromaddress@here.com"
StrEmailSubject = "insert subject here"
Strsmtpserver = "youremailserver.domain.com"
Dim lngDate, objDate, dtmAcctExp, k
' Obtain local time zone bias from machine registry.
Set objShell = CreateObject("Wscript.Shell")
lngBiasKey = objShell.RegRead("HKLMSystemCurrentControlSetControl" _
& "TimeZoneInformationActiveTimeBias")
If (UCase(TypeName(lngBiasKey)) = "LONG") Then
lngBias = lngBiasKey
ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then
lngBias = 0
For k = 0 To UBound(lngBiasKey)
lngBias = lngBias + (lngBiasKey(k) * 256^k)
Next
End If
' Use ADO to search the domain.
Set adoConnection = CreateObject("ADODB.Connection")
Set adoCommand = CreateObject("ADODB.Command")
adoConnection.Provider = "ADsDSOOBject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection
' Determine the DNS domain from the RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")
' Filter to retrieve all user objects with accounts
' that expire.
strFilter = "(&(objectCategory=person)(objectClass=user)" _
& "(!accountExpires=0)(!accountExpires=9223372036854775807))"
strQuery = "<LDAP://" & strDNSDomain & ">;" & strFilter _
& ";distinguishedName,accountExpires;subtree"
' Run the query.
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
Set adoRecordset = adoCommand.Execute
Set objMessage = CreateObject("CDO.Message")
objMessage.Subject = StrEmailSubject
objMessage.From = StrEmailFrom
objMessage.To = StrEmailTo
objMessage.HTMLBody = "<font size=" & chr(34) & "2" & chr(34) & " face=" & chr(34) & "Arial" & chr(34) & ">" & _
"Below is the expiring users report:<br><br><table border-" & Chr(34) & "1" & Chr(34) & "><tr><th>Date Expires</th><th>-----</th><th>User</th></tr><tr>"
'**********************
' Enumerate the recordset.
Do Until adoRecordset.EOF
' Retrieve attribute values.
strDN = adoRecordset.Fields("distinguishedName").Value
lngDate = adoRecordset.Fields("accountExpires")
' Convert accountExpires to date in current time zone.
Set objDate = lngDate
dtmAcctExp = Integer8Date(objDate, lngBias)
' Output to console.
objMessage.HTMLBody = objMessage.HTMLBody & "<tr><td>" & dtmAcctExp & " " & "</td><td> </td><td>" & strDN & "</td></tr>"
adoRecordset.MoveNext
Loop
adoRecordset.Close
objMessage.HTMLBody = objMessage.HTMLBody & "</table>"
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = Strsmtpserver
objMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objMessage.Configuration.Fields.Update
objMessage.Send
'**********************
' Clean up.
adoConnection.Close
Function Integer8Date(ByVal objDate, ByVal lngBias)
' Function to convert Integer8 (64-bit) value to a date, adjusted for
' local time zone bias.
Dim lngAdjust, lngDate, lngHigh, lngLow
lngAdjust = lngBias
lngHigh = objDate.HighPart
lngLow = objdate.LowPart
' Account for bug in IADslargeInteger property methods.
If (lngLow < 0) Then
lngHigh = lngHigh + 1
End If
If (lngHigh = 0) And (lngLow = 0) Then
lngAdjust = 0
End If
lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
+ lngLow) / 600000000 - lngAdjust) / 1440
Integer8Date = CDate(lngDate)
End Function
Subscribe to:
Posts (Atom)