home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / security / winnt / gina / logon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-09  |  19.6 KB  |  674 lines

  1. //+---------------------------------------------------------------------------
  2. //
  3. //  Microsoft Windows
  4. //  Copyright 1992 - 1997 Microsoft Corporation.
  5. //
  6. //  File:       logon.c
  7. //
  8. //  Contents:
  9. //
  10. //  Classes:
  11. //
  12. //  Functions:
  13. //
  14. //  History:    4-28-95   RichardW   Created
  15. //
  16. //----------------------------------------------------------------------------
  17.  
  18. #include "gina.h"
  19. #pragma hdrstop
  20.  
  21. HIMAGELIST      hiLogonSmall;
  22. HIMAGELIST      hiLogonLarge;
  23. PMiniAccount    pAccountList;
  24. WCHAR           szMiniKey[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Accounts");
  25.  
  26. BYTE            LongPseudoRandomString[] = {0x27, 0xbd, 0xff, 0xa0,
  27.                                             0xaf, 0xbf, 0x00, 0x1c,
  28.                                             0x24, 0x0e, 0x00, 0x01,
  29.                                             0x24, 0x0f, 0x00, 0x05 };
  30.  
  31.  
  32. MiniAccount TestAccounts[]  = { {NULL, TEXT("daveth"), TEXT("\\msft\\risc\\dev"), TEXT("daveth"), TEXT("Oooh"), 0, MINI_CAN_EDIT},
  33.                                 {NULL, TEXT("Test1"), TEXT("Redmond"), TEXT("Test1"), TEXT("Mine"), 0, MINI_CAN_EDIT},
  34.                                 {NULL, TEXT("Test2"), TEXT("NtWksta"), TEXT("Test2"), TEXT("Yours"), 0, 0},
  35.                                 {NULL, TEXT("New User"), TEXT(""), TEXT(""), TEXT(""), 0, MINI_NEW_ACCOUNT}
  36.  
  37.                               };
  38.  
  39. BOOL
  40. SaveMiniAccount(PMiniAccount    pAccount)
  41. {
  42.     HKEY                    hMiniKey;
  43.     PSerializedMiniAccount  pPacked;
  44.     DWORD                   cbNeeded;
  45.     PWSTR                   pszPack;
  46.     int                     err;
  47.     DWORD                   Disposition;
  48.  
  49.     err = RegCreateKeyEx(   HKEY_LOCAL_MACHINE,
  50.                             szMiniKey,
  51.                             0,
  52.                             TEXT(""),
  53.                             REG_OPTION_NON_VOLATILE,
  54.                             KEY_WRITE | KEY_READ,
  55.                             NULL,
  56.                             &hMiniKey,
  57.                             &Disposition);
  58.  
  59.     if (err)
  60.     {
  61.         return(FALSE);
  62.     }
  63.  
  64.     cbNeeded = sizeof(SerializedMiniAccount) +
  65.                 (wcslen(pAccount->pszDomain) + 1 +
  66.                  wcslen(pAccount->pszPassword) + 1 +
  67.                  wcslen(pAccount->pszComment) + 1 ) * sizeof(WCHAR) ;
  68.  
  69.     pPacked = LocalAlloc(LMEM_FIXED, cbNeeded);
  70.  
  71.     if (!pPacked)
  72.     {
  73.         return(FALSE);
  74.     }
  75.  
  76.     pszPack = (PWSTR) (pPacked + 1);
  77.  
  78.     pPacked->Version = MINI_VERSION;
  79.     pPacked->Flags = pAccount->Flags;
  80.     pPacked->IconId = pAccount->IconId;
  81.  
  82.     pPacked->dwDomainOffset = sizeof(SerializedMiniAccount);
  83.     pPacked->dwDomainLength = (wcslen(pAccount->pszDomain) + 1) * sizeof(WCHAR);
  84.     wcscpy(pszPack, pAccount->pszDomain);
  85.     pszPack += (pPacked->dwDomainLength / sizeof(WCHAR) );
  86.  
  87.     pPacked->dwPasswordOffset = pPacked->dwDomainOffset + pPacked->dwDomainLength;
  88.     pPacked->dwPasswordLength = (wcslen(pAccount->pszPassword) + 1) * sizeof(WCHAR);
  89.     wcscpy(pszPack, pAccount->pszPassword);
  90.     pszPack += (pPacked->dwPasswordLength / sizeof(WCHAR) );
  91.  
  92.     pPacked->dwCommentOffset = pPacked->dwPasswordOffset + pPacked->dwPasswordLength;
  93.     pPacked->dwCommentLength = (wcslen(pAccount->pszComment) + 1) * sizeof(WCHAR);
  94.     wcscpy(pszPack, pAccount->pszComment);
  95.  
  96.     err = RegSetValueEx(hMiniKey,
  97.                         pAccount->pszUsername,
  98.                         0,
  99.                         REG_BINARY,
  100.                         (PBYTE) pPacked,
  101.                         cbNeeded);
  102.  
  103.     RegCloseKey(hMiniKey);
  104.  
  105.     return(err == 0);
  106. }
  107.  
  108. BOOL
  109. LoadMiniAccounts(PGlobals   pGlobals)
  110. {
  111.     FILETIME            LastWrite;
  112.     // HKEY                hKey;
  113.     HKEY                hMiniKey;
  114.     WCHAR               szClass[64];
  115.     DWORD               err;
  116.     DWORD               Disposition;
  117.     DWORD               Class;
  118.     DWORD               cKeys;
  119.     DWORD               LongestKeyName;
  120.     DWORD               LongestClass;
  121.     DWORD               cValues;
  122.     DWORD               LongestValueName;
  123.     DWORD               LongestValueData;
  124.     DWORD               Security;
  125.     DWORD               i;
  126.     WCHAR               szValue[MAX_PATH];
  127.     DWORD               cbValue;
  128.     DWORD               dwType;
  129.     DWORD               cbData;
  130.     PBYTE               pBuffer;
  131.     DWORD               cbBuffer;
  132.     PMiniAccount        pAccount;
  133.     PSerializedMiniAccount  pPacked;
  134.  
  135.  
  136.     if (pGlobals->fAllowNewUser)
  137.     {
  138.         pAccount = LocalAlloc(LMEM_FIXED, sizeof(MiniAccount) );
  139.         if (pAccount)
  140.         {
  141.             pAccount->pNext = NULL;
  142.             pAccount->pszUsername = TEXT("New User");
  143.             pAccount->pszDomain = TEXT("");
  144.             pAccount->pszPassword = TEXT("");
  145.             pAccount->pszComment = TEXT("");
  146.             pAccount->Flags = MINI_NEW_ACCOUNT;
  147.  
  148.             pAccountList = pAccount;
  149.         }
  150.         else
  151.             return(FALSE);
  152.     }
  153.     else
  154.     {
  155.         pAccountList = NULL;
  156.     }
  157.  
  158.     //
  159.     //
  160.  
  161.     err = RegCreateKeyEx(   HKEY_LOCAL_MACHINE,
  162.                             szMiniKey,
  163.                             0,
  164.                             TEXT(""),
  165.                             REG_OPTION_NON_VOLATILE,
  166.                             KEY_WRITE | KEY_READ,
  167.                             NULL,
  168.                             &hMiniKey,
  169.                             &Disposition);
  170.  
  171.     if (err)
  172.     {
  173.         return(FALSE);
  174.     }
  175.  
  176.     if (Disposition == REG_OPENED_EXISTING_KEY)
  177.     {
  178.         //
  179.         // Enumerate the sub keys of our class, and Load them.
  180.         //
  181.         Class = sizeof(szClass) / sizeof(WCHAR);
  182.         err = RegQueryInfoKey(  hMiniKey,
  183.                                 szClass,
  184.                                 &Class,
  185.                                 NULL,
  186.                                 &cKeys,
  187.                                 &LongestKeyName,
  188.                                 &LongestClass,
  189.                                 &cValues,
  190.                                 &LongestValueName,
  191.                                 &LongestValueData,
  192.                                 &Security,
  193.                                 &LastWrite);
  194.  
  195.         pBuffer = LocalAlloc(LMEM_FIXED, 512);
  196.         cbBuffer = 512;
  197.  
  198.         for (i = 0; i < cValues ; i++ )
  199.         {
  200.             cbValue = MAX_PATH;
  201.  
  202.             err = RegEnumValue( hMiniKey,
  203.                                 i,
  204.                                 szValue,
  205.                                 &cbValue,
  206.                                 NULL,
  207.                                 &dwType,
  208.                                 NULL,
  209.                                 &cbData);
  210.  
  211.             if (err)
  212.             {
  213.                 break;
  214.             }
  215.  
  216.             if (dwType != REG_BINARY)
  217.             {
  218.                 continue;
  219.             }
  220.  
  221.             if (cbData > cbBuffer)
  222.             {
  223.                 pBuffer = LocalReAlloc(pBuffer, LMEM_FIXED, cbData);
  224.                 if (!pBuffer)
  225.                 {
  226.                     break;
  227.                 }
  228.                 cbBuffer = cbData;
  229.             }
  230.  
  231.             err = RegQueryValueEx(  hMiniKey,
  232.                                     szValue,
  233.                                     0,
  234.                                     &dwType,
  235.                                     pBuffer,
  236.                                     &cbData);
  237.  
  238.             if (err == 0)
  239.             {
  240.                 pPacked = (PSerializedMiniAccount) pBuffer;
  241.  
  242.                 if (pPacked->Version != MINI_VERSION)
  243.                 {
  244.                     continue;
  245.                 }
  246.  
  247.                 pAccount = LocalAlloc(LMEM_FIXED, sizeof(MiniAccount));
  248.                 if (pAccount)
  249.                 {
  250.                     pAccount->Flags = pPacked->Flags;
  251.                     pAccount->IconId = pPacked->IconId;
  252.                     pAccount->pszUsername = LocalAlloc(LMEM_FIXED, (cbValue+1)*sizeof(TCHAR));
  253.                     if (pAccount->pszUsername)
  254.                     {
  255.                         wcscpy(pAccount->pszUsername, szValue);
  256.                     }
  257.  
  258.                     pAccount->pszDomain = LocalAlloc(LMEM_FIXED, pPacked->dwDomainLength);
  259.                     if (pAccount->pszDomain)
  260.                     {
  261.                         wcscpy(pAccount->pszDomain,
  262.                                (PWSTR) ((pBuffer) + pPacked->dwDomainOffset) );
  263.                     }
  264.  
  265.                     pAccount->pszPassword = LocalAlloc(LMEM_FIXED, pPacked->dwPasswordLength);
  266.                     if (pAccount->pszPassword)
  267.                     {
  268.                         wcscpy(pAccount->pszPassword,
  269.                                (PWSTR) (pBuffer + pPacked->dwPasswordOffset) );
  270.                     }
  271.  
  272.                     pAccount->pszComment = LocalAlloc(LMEM_FIXED, pPacked->dwCommentLength);
  273.                     if (pAccount->pszComment)
  274.                     {
  275.                         wcscpy(pAccount->pszComment,
  276.                                (PWSTR) (pBuffer + pPacked->dwCommentOffset) );
  277.                     }
  278.  
  279.                     pAccount->pNext = pAccountList;
  280.                     pAccountList = pAccount;
  281.                 }
  282.             }
  283.  
  284.         }
  285.  
  286.     }
  287.  
  288.     return(TRUE);
  289. }
  290.  
  291. VOID
  292. InitializeImageLists()
  293. {
  294.     HICON   hIcon;
  295.  
  296.     hiLogonSmall = ImageList_Create(16, 16, TRUE, 4, 0);
  297.     hiLogonLarge = ImageList_Create(32, 32, TRUE, 4, 0);
  298.  
  299.     hIcon = LoadIcon(hDllInstance, MAKEINTRESOURCE(IDI_USER_ICON));
  300.     if (!hIcon)
  301.     {
  302.         DebugLog((DEB_ERROR, "Unable to load icon, %d\n", GetLastError()));
  303.     }
  304.     ImageList_AddIcon(hiLogonLarge, hIcon);
  305.     ImageList_AddIcon(hiLogonSmall, hIcon);
  306.  
  307.     hIcon = LoadIcon(hDllInstance, MAKEINTRESOURCE(IDI_NEW_USER_ICON));
  308.     ImageList_AddIcon(hiLogonLarge, hIcon);
  309.     ImageList_AddIcon(hiLogonSmall, hIcon);
  310.  
  311. }
  312.  
  313.  
  314. PopulateListView(
  315.     HWND            hLV,
  316.     PMiniAccount    pAccList)
  317. {
  318.     LV_ITEM     lvi;
  319.     LV_COLUMN   lvc;
  320.     DWORD       Count;
  321.  
  322.  
  323.     ListView_SetImageList(hLV, hiLogonLarge, LVSIL_NORMAL);
  324.     ListView_SetImageList(hLV, hiLogonSmall, LVSIL_SMALL);
  325.  
  326.     //
  327.     // Ok, now set up the columns for the list view
  328.     //
  329.  
  330.     lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  331.     lvc.fmt = LVCFMT_LEFT;
  332.     lvc.cx = 0;
  333.  
  334.     lvc.iSubItem = 0;
  335.     lvc.pszText = TEXT("Name        ");
  336.     ListView_InsertColumn(hLV, 0, &lvc);
  337.  
  338.     lvc.iSubItem = 1;
  339.     lvc.pszText = TEXT("Domain   ");
  340.     ListView_InsertColumn(hLV, 1, &lvc);
  341.     //
  342.     // Comment
  343.     //
  344.  
  345.     lvc.iSubItem = 2;
  346.     lvc.pszText = TEXT("Comment   ");
  347.     ListView_InsertColumn(hLV, 2, &lvc);
  348.  
  349.     lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  350.  
  351.  
  352.     Count = 0;
  353.     while (pAccList)
  354.     {
  355.         lvi.iItem = Count;
  356.         lvi.iSubItem  = 0;
  357.         lvi.iImage = (pAccList->Flags & MINI_NEW_ACCOUNT) ? 1 : 0;
  358.         lvi.pszText = pAccList->pszUsername;
  359.         lvi.lParam = (LPARAM) pAccList;
  360.  
  361.         ListView_InsertItem(hLV, &lvi);
  362.  
  363.         ListView_SetItemText(hLV, Count, 1, pAccList->pszDomain);
  364.         ListView_SetItemText(hLV, Count, 2, pAccList->pszComment);
  365.  
  366.         Count++;
  367.         pAccList = pAccList->pNext;
  368.  
  369.     }
  370.  
  371.     return(TRUE);
  372. }
  373.  
  374. int
  375. CALLBACK
  376. NewUserDlgProc(
  377.     HWND    hDlg,
  378.     UINT    Message,
  379.     WPARAM  wParam,
  380.     LPARAM  lParam)
  381. {
  382.     PGlobals        pGlobals;
  383.     PMiniAccount    pMini;
  384.  
  385.     pGlobals = (PGlobals) GetWindowLong(hDlg, GWL_USERDATA);
  386.     switch (Message)
  387.     {
  388.         case WM_INITDIALOG:
  389.             CenterWindow(hDlg);
  390.             SetWindowLong(hDlg, GWL_USERDATA, lParam);
  391.             return(TRUE);
  392.  
  393.         case WM_COMMAND:
  394.             if (LOWORD(wParam) == IDOK)
  395.             {
  396.                 pMini = LocalAlloc(LMEM_FIXED, sizeof(MiniAccount));
  397.                 pMini->pszUsername = AllocAndCaptureText(hDlg, IDD_USER_NAME);
  398.                 pMini->pszDomain = AllocAndCaptureText(hDlg, IDD_DOMAIN);
  399.                 pMini->pszPassword = AllocAndCaptureText(hDlg, IDD_PASSWORD);
  400.                 pMini->pszComment = DupString(TEXT(""));
  401.                 pMini->Flags = MINI_SAVE | MINI_CAN_EDIT;
  402.                 pMini->IconId = 0;
  403.                 pMini->pNext = pAccountList;
  404.                 pAccountList = pMini;
  405.                 pGlobals->pAccount = pMini;
  406.                 EndDialog(hDlg, IDOK);
  407.             }
  408.             if (LOWORD(wParam) == IDCANCEL)
  409.             {
  410.                 EndDialog(hDlg, IDCANCEL);
  411.             }
  412.             return(TRUE);
  413.     }
  414.  
  415.     return(FALSE);
  416.  
  417. }
  418.  
  419. LogonDlgInit(
  420.     HWND    hDlg,
  421.     LPARAM  lParam)
  422. {
  423.     PGlobals        pGlobals;
  424.     HWND            hLV;
  425.  
  426.     pGlobals = (PGlobals) lParam;
  427.     SetWindowLong(hDlg, GWL_USERDATA, lParam);
  428.     pGlobals->pAccount = NULL;
  429.  
  430.     if (pAccountList == NULL)
  431.     {
  432.         LoadMiniAccounts(pGlobals);
  433.     }
  434.  
  435.     InitializeImageLists();
  436.  
  437.     hLV = GetDlgItem(hDlg, IDD_LOGON_LV);
  438.     PopulateListView(hLV, pAccountList);
  439.  
  440.     CenterWindow(hDlg);
  441.  
  442.     ListView_SetColumnWidth(hLV, 0, LVSCW_AUTOSIZE);
  443.     ListView_SetColumnWidth(hLV, 1, LVSCW_AUTOSIZE);
  444.     ListView_SetColumnWidth(hLV, 2, LVSCW_AUTOSIZE);
  445.  
  446.     ShowWindow(hLV, SW_NORMAL);
  447.     EnableWindow(hLV, TRUE);
  448.     EnableWindow(GetDlgItem(hDlg, IDD_LOGON_BUTTON), FALSE);
  449.  
  450.     return(TRUE);
  451.  
  452. }
  453.  
  454. int
  455. HandleLvNotify(
  456.     HWND        hDlg,
  457.     PGlobals    pGlobals,
  458.     NMHDR *     pNMH)
  459. {
  460.     NM_LISTVIEW *   pNotify;
  461.     LV_ITEM         lvi;
  462.     HWND            hLV;
  463.     PMiniAccount *  ppAcc;
  464.     int             ret;
  465.     int             index;
  466.  
  467.     pNotify = (NM_LISTVIEW *) pNMH;
  468.  
  469.     hLV = GetDlgItem(hDlg, IDD_LOGON_LV);
  470.  
  471.     ppAcc = &pGlobals->pAccount;
  472.  
  473.     switch (pNotify->hdr.code)
  474.     {
  475.         case NM_CLICK:
  476.         case NM_DBLCLK:
  477.             EnableWindow(GetDlgItem(hDlg, IDD_LOGON_BUTTON), TRUE);
  478.  
  479.             index = ListView_GetNextItem(hLV, -1, LVNI_SELECTED);
  480.             if (index >= 0)
  481.             {
  482.                 lvi.iItem = index;
  483.                 lvi.iSubItem = 0;
  484.                 lvi.mask = LVIF_PARAM;
  485.  
  486.                 ret = ListView_GetItem(hLV, &lvi);
  487.                 *ppAcc = (PMiniAccount) lvi.lParam;
  488.                 DebugLog((DEB_TRACE, "Selected Item %d, lParam = %x\n", index, lvi.lParam));
  489.             }
  490.  
  491.             if (pNotify->hdr.code == NM_DBLCLK)
  492.             {
  493.                 PostMessage(hDlg, WM_COMMAND, IDOK, 0);
  494.             }
  495.             return(TRUE);
  496.  
  497.     }
  498.     return(FALSE);
  499.  
  500. }
  501.  
  502. int
  503. CALLBACK
  504. LogonDlgProc(
  505.     HWND        hDlg,
  506.     UINT        Message,
  507.     WPARAM      wParam,
  508.     LPARAM      lParam)
  509. {
  510.     NMHDR *     pNotifyHeader;
  511.     PGlobals    pGlobals;
  512.     int         result;
  513.  
  514.     pGlobals = (PGlobals) GetWindowLong(hDlg, GWL_USERDATA);
  515.     switch (Message)
  516.     {
  517.         case WM_INITDIALOG:
  518.             return(LogonDlgInit(hDlg, lParam));
  519.  
  520.         case WM_COMMAND:
  521.             if (LOWORD(wParam) == IDCANCEL)
  522.             {
  523.                 EndDialog(hDlg, WLX_SAS_ACTION_NONE);
  524.             }
  525.             if (LOWORD(wParam) == IDD_LOGON_BUTTON)
  526.             {
  527.                 if (pGlobals->pAccount->Flags & MINI_NEW_ACCOUNT)
  528.                 {
  529.                     result = pWlxFuncs->WlxDialogBoxParam(  hGlobalWlx,
  530.                                                             hDllInstance,
  531.                                                             (LPTSTR) MAKEINTRESOURCE(IDD_NEW_USER_LOGON),
  532.                                                             hDlg,
  533.                                                             (DLGPROC) NewUserDlgProc,
  534.                                                             (LPARAM) pGlobals);
  535.                 }
  536.                 else
  537.                 {
  538.                     result = IDOK;
  539.                 }
  540.  
  541.                 if (result == IDOK)
  542.                 {
  543.                     EndDialog(hDlg, WLX_SAS_ACTION_LOGON);
  544.                 }
  545.             }
  546.             if (LOWORD(wParam) == IDD_SHUTDOWN_BUTTON)
  547.             {
  548.                 result = pWlxFuncs->WlxDialogBoxParam(  hGlobalWlx,
  549.                                                         hDllInstance,
  550.                                                         (LPTSTR) MAKEINTRESOURCE(IDD_SHUTDOWN),
  551.                                                         hDlg,
  552.                                                         (DLGPROC) ShutdownDlgProc,
  553.                                                         (LPARAM) pGlobals);
  554.                 if (result != WLX_SAS_ACTION_NONE)
  555.                 {
  556.                     EndDialog(hDlg, result);
  557.                 }
  558.             }
  559.             return(TRUE);
  560.             break;
  561.  
  562.         case WM_NOTIFY:
  563.             pNotifyHeader = (NMHDR *) lParam;
  564.             if (wParam == IDD_LOGON_LV)
  565.             {
  566.                 return(HandleLvNotify(hDlg, pGlobals, pNotifyHeader));
  567.             }
  568.         case WM_CLOSE:
  569.             hiLogonSmall = NULL;
  570.             hiLogonLarge = NULL;
  571.             return(TRUE);
  572.  
  573.     }
  574.  
  575.     return(FALSE);
  576. }
  577.  
  578. ///////////////////////////////////////////////////////////////////////////
  579. ///////////////////////////////////////////////////////////////////////////
  580. //
  581. //
  582. //
  583. ///////////////////////////////////////////////////////////////////////////
  584. ///////////////////////////////////////////////////////////////////////////
  585.  
  586. int
  587. AttemptLogon(
  588.     PGlobals        pGlobals,
  589.     PMiniAccount    pAccount,
  590.     PSID            pLogonSid,
  591.     PLUID           pLogonId)
  592. {
  593.     HANDLE              hUser;
  594.     TOKEN_STATISTICS    TStats;
  595.     TOKEN_GROUPS    *   pGroups;
  596.     DWORD               size;
  597.     DWORD               i;
  598.  
  599.     if (LogonUser(  pAccount->pszUsername,
  600.                     pAccount->pszDomain,
  601.                     pAccount->pszPassword,
  602.                     LOGON32_LOGON_INTERACTIVE,
  603.                     LOGON32_PROVIDER_DEFAULT,
  604.                     &hUser))
  605.     {
  606.         if (pAccount->Flags & MINI_SAVE)
  607.         {
  608.             SaveMiniAccount(pAccount);
  609.             pAccount->Flags &= ~MINI_SAVE;
  610.         }
  611.  
  612.         pGlobals->hUserToken = hUser;
  613.  
  614.         //
  615.         // Now, grovel the token we got back for interesting stuff:
  616.         //
  617.  
  618.         GetTokenInformation(hUser,
  619.                             TokenStatistics,
  620.                             &TStats,
  621.                             sizeof(TStats),
  622.                             &size);
  623.  
  624.         *pLogonId = TStats.AuthenticationId;
  625.  
  626.         pGroups = LocalAlloc(LMEM_FIXED, 1024);
  627.  
  628.         if (!pGroups)
  629.         {
  630.             CloseHandle(hUser);
  631.             return(WLX_SAS_ACTION_NONE);
  632.         }
  633.  
  634.         //
  635.         // The tricky part.  We need to get the Logon SID from the token,
  636.         // since that is what Winlogon will use to protect the windowstation
  637.         // and desktop.
  638.         //
  639.  
  640.         GetTokenInformation(hUser,
  641.                             TokenGroups,
  642.                             pGroups,
  643.                             1024,
  644.                             &size);
  645.  
  646.         if (size > 1024)
  647.         {
  648.             pGroups = LocalReAlloc(pGroups, LMEM_FIXED, size);
  649.             GetTokenInformation(hUser,
  650.                                 TokenGroups,
  651.                                 pGroups,
  652.                                 size,
  653.                                 &size);
  654.         }
  655.  
  656.         for (i = 0; i < pGroups->GroupCount ; i++)
  657.         {
  658.             if ((pGroups->Groups[i].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
  659.             {
  660.                 CopySid(GetLengthSid(pLogonSid),
  661.                         pLogonSid,
  662.                         pGroups->Groups[i].Sid );
  663.                 break;
  664.             }
  665.         }
  666.  
  667.         LocalFree(pGroups);
  668.  
  669.         return(WLX_SAS_ACTION_LOGON);
  670.     }
  671.  
  672.     return(WLX_SAS_ACTION_NONE);
  673. }
  674.