April 13, 2007

Finding a Machine SID in C#

public static class MachineSidHelper
{

    private static SecurityIdentifier GetAccountSid(string localAdminAccount)
    {
        NTAccount name = new NTAccount(localAdminAccount);
        SecurityIdentifier sid = (SecurityIdentifier)name.Translate(typeof(SecurityIdentifier));
        return sid;
    }


    // Get the Machine Sid for the PC the code is currently executing on
    public static string MachineSid
    {
        get
        {
            string machineSid = string.Empty;
            string domain;
            short accounttype;
            try
            {
                LookupAccountName(Environment.MachineName, 
                   Environment.MachineName, out machineSid, 
                   out domain, out accounttype);
                System.Diagnostics.Debug.WriteLine("From LookupAccountName
(\'" + Environment.MachineName + "\',  \'" +
                    Environment.MachineName + "\', ...): " + machineSid);
            }
            catch (Exception)
            {
                System.Diagnostics.Trace.WriteLine(
"Can not get the Machine Identifier using \'LookupAccountName\'");
            }
            if (machineSid.Length < 1)
            {

                string account = Environment.MachineName + @"\Administrator";
                try
                {
                    SecurityIdentifier sid = GetAccountSid(account);
                    machineSid = sid.AccountDomainSid.ToString();
                    System.Diagnostics.Debug.WriteLine("From GetAccountSid(\'" + account +
                        "\'): " + machineSid);
                }
                catch (Exception)
                {
                    System.Diagnostics.Trace.WriteLine(
"Can not get the Machine Identifier using \'Administrator Sid\'");
                }
            }
            return machineSid;
        }
    }

    internal static bool LookupAccountName(string strServer, 
        string strAccountName, out string accountSid, 
        out string strDomainName, out short AccountType)
    {
        bool bRet = false;
        int lSidSize = 256;
        int lDomainNameSize = 256;

        accountSid = "";
        strDomainName = "";
        AccountType = 0;
        StringBuilder strName;
        lSidSize = 0;
        IntPtr Sid = IntPtr.Zero;

        // First get the required buffer sizes for SID and domain name.
        int nRet = Win32API.LookupAccountName(
                            strServer,
                            strAccountName,
                            Sid,
                            ref lSidSize,
                            null,
                            ref lDomainNameSize,
                            ref AccountType);
        bRet = (0 != nRet);
        if (!bRet)
        {
            int nErr = Marshal.GetLastWin32Error();
            if (122 == nErr) // Buffer too small
            {
                // Allocate the buffers with actual sizes that are required
                // for SID and domain name.
                strName = new StringBuilder(lDomainNameSize);
                Sid = Marshal.AllocHGlobal(lSidSize);
                nRet = Win32API.LookupAccountName(
                    strServer,
                    strAccountName,
                    Sid,
                    ref lSidSize,
                    strName,
                    ref lDomainNameSize,
                    ref AccountType);
                bRet = (0 != nRet);
                if (bRet)
                {
                    byte[] sidArray = new byte[lSidSize];
                    strDomainName = strName.ToString();
                    Marshal.Copy(Sid, sidArray, 0, lSidSize);
                    SecurityIdentifier sid = new SecurityIdentifier(sidArray, 0);
                    accountSid = sid.ToString();
                }
            }
            else
            {
                System.Diagnostics.Debug.WriteLine(nErr);
            }
        }
        Marshal.FreeHGlobal(Sid);
        return bRet;
    }


    private class Win32API
    {
        #region Win32 API Interfaces

        [DllImport("Advapi32.dll", SetLastError = true)]
        public static extern int LookupAccountName(
            string ServerName,
            string AccountName,
            IntPtr Sid,
            ref int SidSize,
            StringBuilder DomainName,
            ref int DomainNameSize,
            ref short SidUse);


        #endregion
    }
 
} 

Simple C# IEnumerable Samples

This example shows how the iterator can be exposed to allow an object to be iteratied in different ways, In this case a matrix type object can be iterated row by row or column by column. The advantage of the iterator is that it only gets a value when asked.

// Iterate column by column starting with Pin 1,1
public IEnumerable<Thing> ColumnByColum()
{
    Thing rcl = new Thing();
    for (int col = 0; col < Cols; col++)
    {
        for (int row = 0; row < Rows; row++)
        {
            rcl.Row = row + 1;
            rcl.Column = col + 1;
            yield return rcl;
        }
    }
}

// Iterate row by row starting with Pin 1,1
public IEnumerable<Thing> RowByRow()
{
    Thing rcl = new Thing();
    for (int row = 0; row < Rows; row++)
    {
        for (int col = 0; col < Cols; col++)
        {
            rcl.Row = row + 1;
            rcl.Column = col + 1;
            yield return rcl;
        }
    }
}


foreach (Thing thing in matrixThingey.ColumnByColum)
{
}
There are 2 yield statements:
  • "yield return XXX" returns an item.
  • "yield break" ends the iterator without returning any item. You can think of yield break as return statement which does not return a value.

Discarding Pending Mouse Or Keyboard Messages in C#

public static class Win32Helper
{

/// Window messages
private enum WindowMessage : uint
{
    // Keyboard messages
    KeyboardFirst = 0x0100,
    KeyboardLast = 0x0108,

    // Mouse messages
    //MouseMove = 0x0200,
    MouseFirst = 0x0201, // Skip mouse move, it happens 
                         //a lot and there is another message for that
    MouseLast = 0x020d,
}

public static void DiscardMousebMessages(IntPtr hWnd)
{
    Message msg;
    while (PeekMessage(out msg, hWnd, (uint)WindowMessage.MouseFirst,
        (uint)WindowMessage.MouseLast, (uint)PeekMessageFlags.PM_REMOVE)) ;
}

public static void DiscardKeyboardMessages(IntPtr hWnd)
{
    Message msg;
    while (PeekMessage(out msg, hWnd, (uint)WindowMessage.KeyboardFirst,
        (uint)WindowMessage.KeyboardLast, (uint)PeekMessageFlags.PM_REMOVE)) ;
}

[StructLayout(LayoutKind.Sequential)]
private struct Message
{
    public IntPtr hWnd;
    public WindowMessage msg;
    public IntPtr wParam;
    public IntPtr lParam;
    public uint time;
    public System.Drawing.Point p;
}

[System.Security.SuppressUnmanagedCodeSecurity] 
[DllImport("User32.dll", CharSet = CharSet.Auto)]
private static extern bool PeekMessage(
    out Message msg, IntPtr hWnd, 
    uint messageFilterMin, uint messageFilterMax, 
    uint flags);

}