Showing posts with label SQL Server. Show all posts
Showing posts with label SQL Server. Show all posts

Monday, March 29, 2010

Different about DateDiff between SSMS and ReportBuilder

Recently, I am building a report using the SQL Server reporting service. I met a problem about datediff.  There are two datetime values 2010-04-23 08:00:00 and 2010-04-22 17:00:00. If you use the TSQL built-in function DATEDIFF to check the value in SQL Server Management Studio  like below:

DATEDIFF(d,'2010-04-23 08:00:00','2010-04-22 17:00:00')

You would get the -1.
But, if you use the DATEDIFF in the ReportBuilder, it would return 0. I guess that Within SSMS if you cross midnight you have triggered a day boundary so  it get -1. in ReportBuilder it is looking for 24 hours to be between the two values so it gets 0.


Tuesday, March 9, 2010

Impersonate for Windows Authentication

域环境中Winodws认证代理帐号访问
The code came from an article in CodeProject site, but I can't find the original page, so I can't paste that URL here.
Sometimes you may want to run some code under one specify account in a domain. There is one typical situation, there is a database in your SQL Server, you need user to retrieve data from this database, but you do not want to grant users direct permission to read/write. In this case, you need use another specify account to retrieve data, which means impersonation.
First, you need import some functions from native dll.
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
And you create a enum like below: 
public enum SECURITY_IMPERSONATION_LEVEL : int
{
   
SecurityAnonymous = 0,
   
SecurityIdentification = 1,
   
SecurityImpersonation = 2,
   
SecurityDelegation = 3
}
Create a function that you would be used later in your code:
  static public WindowsImpersonationContext ImpersonateUser(string sUsername, string sDomain, string sPassword)
   
{
       
IntPtr pExistingTokenHandle = new IntPtr(0);
       
IntPtr pDuplicateTokenHandle = new IntPtr(0);
        pExistingTokenHandle
= IntPtr.Zero;
        pDuplicateTokenHandle
= IntPtr.Zero;
       
if (sDomain == "")
            sDomain
= System.Environment.MachineName;
       
try
       
{
           
string sResult = null;
           
const int LOGON32_PROVIDER_DEFAULT = 0;
           
const int LOGON32_LOGON_INTERACTIVE = 2;
           
bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
                LOGON32_LOGON_INTERACTIVE
, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);
           
if (false == bImpersonated)
           
{
               
int nErrorCode = Marshal.GetLastWin32Error();
                sResult
= "LogonUser() failed with error code: " + nErrorCode + "\r\n";
           
}
            sResult
+= "Before impersonation: " + WindowsIdentity.GetCurrent().Name + "\r\n";
           
bool bRetVal = DuplicateToken(pExistingTokenHandle, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref pDuplicateTokenHandle);
           
if (false == bRetVal)
           
{
               
int nErrorCode = Marshal.GetLastWin32Error();
               
CloseHandle(pExistingTokenHandle); // close existing handle
                sResult
+= "DuplicateToken() failed with error code: " + nErrorCode + "\r\n";
               
return null;
           
}
           
else
           
{
               
WindowsIdentity newId = new WindowsIdentity(pDuplicateTokenHandle);
               
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
                sResult
+= "After impersonation: " + WindowsIdentity.GetCurrent().Name + "\r\n";
               
return impersonatedUser;
           
}
       
}
       
catch (Exception ex)
       
{
           
throw ex;
       
}
       
finally
       
{
           
if (pExistingTokenHandle != IntPtr.Zero)
               
CloseHandle(pExistingTokenHandle);
           
if (pDuplicateTokenHandle != IntPtr.Zero)
               
CloseHandle(pDuplicateTokenHandle);
       
}
   
}
Now, you use it to impersonate,
System.Security.Principal.WindowsImpersonationContext newUser;
newUser
= ImpersonateUser("account","domain","password");
//Your code here
newUser
.Undo();