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 / secfile / secfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  8.4 KB  |  381 lines

  1. //
  2. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. // PARTICULAR PURPOSE.
  6. //
  7. // Copyright (C) 1995 - 1997 Microsoft Corporation.    All Rights Reserved.
  8. //
  9. // COMMENTS:
  10. //  All buffers allocated in this sample come from HeapAlloc.  If
  11. //  HeapAlloc fails, the PERR macro is not used because HeapAlloc does
  12. //  not call SetLastError().
  13. //
  14.  
  15. #include <windows.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18.  
  19.  
  20. //
  21. //  Constants and Macros
  22. //
  23. #define USER_ACCESS        GENERIC_ALL
  24. #define WORLD_ACCESS    GENERIC_READ
  25. #define FILENAME        "testfile.txt"
  26.  
  27. #define PERR(s) fprintf(stderr, "%s(%d) %s : Error %d\n%s\n", \
  28.             __FILE__, __LINE__, (s), GetLastError(), \
  29.             GetLastErrorText())
  30.  
  31. //
  32. //  Prototypes
  33. //
  34. PSID GetUserSid(void);
  35. PSID CreateWorldSid(void);
  36. LPSTR GetLastErrorText(void);
  37.  
  38.  
  39. //
  40. //  FUNCTION: main
  41. //
  42. //  PURPOSE: Driving routine for this sample.
  43. //
  44. //  PARAMETERS:
  45. //    none
  46. //
  47. //  RETURN VALUE:
  48. //    none
  49. //
  50. //  COMMENTS:
  51. //
  52. void main()
  53. {
  54.     PSID psidUser, psidEveryone;
  55.     PACL pAcl;
  56.     SECURITY_DESCRIPTOR sd;
  57.     SECURITY_ATTRIBUTES sa;
  58.     BOOL bRes;
  59.     HANDLE hFile;
  60.     DWORD dwBytesWritten, cbMsg, cbAcl;
  61.     char szMsg[] = "Protected data\n";
  62.  
  63.  
  64.     // Get the SIDs we'll need for the DACL
  65.     //
  66.     psidUser = GetUserSid();
  67.     psidEveryone = CreateWorldSid();
  68.  
  69.  
  70.     // Allocate space for the ACL
  71.     //    For information about computing the size of the ACL, see
  72.     //    the Win32 SDK reference entry for InitializeAcl()
  73.     //
  74.     cbAcl = GetLengthSid (psidUser) + GetLengthSid (psidEveryone) +
  75.         sizeof(ACL) + (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  76.  
  77.     pAcl = (PACL) HeapAlloc(GetProcessHeap(), 0, cbAcl);
  78.     if (NULL == pAcl) {
  79.         fprintf(stderr, "HeapAlloc failed.\n");
  80.         ExitProcess(EXIT_FAILURE);
  81.     }
  82.  
  83.  
  84.     bRes = InitializeAcl(pAcl,
  85.             cbAcl,
  86.             ACL_REVISION);
  87.     if (FALSE == bRes) {
  88.         PERR("InitializeAcl");
  89.         ExitProcess(EXIT_FAILURE);
  90.     }
  91.  
  92.     // Add Aces for User and World
  93.     //
  94.     bRes = AddAccessAllowedAce(pAcl,
  95.             ACL_REVISION,
  96.             USER_ACCESS,
  97.             psidUser);
  98.     if (FALSE == bRes) {
  99.         PERR("AddAccessAllowedAce");
  100.         ExitProcess(EXIT_FAILURE);
  101.     }
  102.  
  103.     bRes = AddAccessAllowedAce(pAcl,
  104.             ACL_REVISION,
  105.             WORLD_ACCESS,
  106.             psidEveryone);
  107.     if (FALSE == bRes) {
  108.         PERR("AddAccessAllowedAce");
  109.         ExitProcess(EXIT_FAILURE);
  110.     }
  111.  
  112.     // Put together the security descriptor
  113.     //
  114.     bRes = InitializeSecurityDescriptor(&sd,
  115.             SECURITY_DESCRIPTOR_REVISION);
  116.     if (FALSE == bRes) {
  117.         PERR("InitializeSecurityDescriptor");
  118.         ExitProcess(EXIT_FAILURE);
  119.     }
  120.  
  121.     bRes = SetSecurityDescriptorDacl(&sd,
  122.             TRUE,
  123.             pAcl,
  124.             FALSE);
  125.     if (FALSE == bRes) {
  126.         PERR("SetSecurityDescriptorDacl");
  127.         ExitProcess(EXIT_FAILURE);
  128.     }
  129.  
  130.     // Add the security descriptor to the sa structure
  131.     //
  132.     sa.nLength = sizeof(sa);
  133.     sa.lpSecurityDescriptor = &sd;
  134.     sa.bInheritHandle = FALSE;
  135.  
  136.     // Generate the file using the security attributes that
  137.     // we've assembled
  138.     //
  139.     hFile = CreateFile(FILENAME,
  140.                GENERIC_READ |
  141.                GENERIC_WRITE,
  142.                0,
  143.                &sa,
  144.                CREATE_ALWAYS,
  145.                FILE_ATTRIBUTE_NORMAL,
  146.                NULL);
  147.     if (INVALID_HANDLE_VALUE == hFile) {
  148.         PERR("CreateFile");
  149.         ExitProcess(EXIT_FAILURE);
  150.     }
  151.  
  152.     cbMsg = lstrlen(szMsg);
  153.  
  154.     bRes = WriteFile(hFile,
  155.              szMsg,
  156.              cbMsg,
  157.              &dwBytesWritten,
  158.              NULL);
  159.     if (FALSE == bRes) {
  160.         PERR("WriteFile");
  161.         ExitProcess(EXIT_FAILURE);
  162.     }
  163.  
  164.     if (!CloseHandle(hFile)) {
  165.         PERR("CloseHandle");
  166.         ExitProcess(EXIT_FAILURE);
  167.     }
  168.  
  169.     // Clean up
  170.     //
  171.     HeapFree(GetProcessHeap(), 0, pAcl);
  172.     HeapFree(GetProcessHeap(), 0, psidUser);
  173.     HeapFree(GetProcessHeap(), 0, psidEveryone);
  174.  
  175.  
  176.     printf ("Created %s with special access.\n", FILENAME);
  177.  
  178.     ExitProcess(EXIT_SUCCESS);
  179. }
  180.  
  181.  
  182. //
  183. //  FUNCTION: GetUserSid
  184. //
  185. //  PURPOSE: Obtains a pointer to the SID for the current user
  186. //
  187. //  PARAMETERS:
  188. //    none
  189. //
  190. //  RETURN VALUE:
  191. //    Pointer to the SID
  192. //
  193. //  COMMENTS:
  194. //    The SID buffer returned by this function is allocated with
  195. //    HeapAlloc and should be freed with HeapFree.
  196. //
  197. PSID GetUserSid()
  198. {
  199.     HANDLE hToken;
  200.     BOOL bRes;
  201.     DWORD cbBuffer, cbRequired;
  202.     PTOKEN_USER pUserInfo;
  203.     PSID pUserSid;
  204.  
  205.     // The User's SID can be obtained from the process token
  206.     //
  207.     bRes = OpenProcessToken(GetCurrentProcess(),
  208.                 TOKEN_QUERY,
  209.                 &hToken);
  210.     if (FALSE == bRes) {
  211.         PERR("OpenProcessToken");
  212.         ExitProcess(EXIT_FAILURE);
  213.     }
  214.  
  215.     // Set buffer size to 0 for first call to determine
  216.     // the size of buffer we need.
  217.     //
  218.     cbBuffer = 0;
  219.     bRes = GetTokenInformation(hToken,
  220.             TokenUser,
  221.             NULL,
  222.             cbBuffer,
  223.             &cbRequired);
  224.  
  225.     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  226.         PERR("GetTokenInformation");
  227.         ExitProcess(EXIT_FAILURE);
  228.     }
  229.  
  230.     // Allocate a buffer for our token user data
  231.     //
  232.     cbBuffer = cbRequired;
  233.     pUserInfo = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbBuffer);
  234.     if (NULL == pUserInfo) {
  235.         fprintf(stderr, "HeapAlloc failed.\n");
  236.         ExitProcess(EXIT_FAILURE);
  237.     }
  238.  
  239.     // Make the "real" call
  240.     //
  241.     bRes = GetTokenInformation(hToken,
  242.             TokenUser,
  243.             pUserInfo,
  244.             cbBuffer,
  245.             &cbRequired);
  246.     if (FALSE == bRes) {
  247.         PERR("GetTokenInformation");
  248.         ExitProcess(EXIT_FAILURE);
  249.     }
  250.  
  251.     // Make another copy of the SID for the return value
  252.     //
  253.     cbBuffer = GetLengthSid(pUserInfo->User.Sid);
  254.  
  255.     pUserSid = (PSID) HeapAlloc(GetProcessHeap(), 0, cbBuffer);
  256.     if (NULL == pUserSid) {
  257.         fprintf(stderr, "HeapAlloc failed.\n");
  258.         ExitProcess(EXIT_FAILURE);
  259.     }
  260.  
  261.     bRes = CopySid(cbBuffer, pUserSid, pUserInfo->User.Sid);
  262.     if (FALSE == bRes) {
  263.         PERR("CopySid");
  264.         ExitProcess(EXIT_FAILURE);
  265.     }
  266.  
  267.     bRes = HeapFree(GetProcessHeap(), 0, pUserInfo);
  268.     if (FALSE == bRes) {
  269.         fprintf(stderr, "HeapFree failed.\n");
  270.         ExitProcess(EXIT_FAILURE);
  271.     }
  272.  
  273.     return pUserSid;
  274. }
  275.  
  276.  
  277. //
  278. //  FUNCTION: CreateWorldSid
  279. //
  280. //  PURPOSE: Creates a SID that represents "Everyone"
  281. //
  282. //  PARAMETERS:
  283. //    none
  284. //
  285. //  RETURN VALUE:
  286. //    A pointer to the SID.
  287. //
  288. //  COMMENTS:
  289. //    The SID buffer returned by this function is allocated with
  290. //    HeapAlloc and should be freed with HeapFree.  I made a copy
  291. //    of the SID on the heap so that when the calling code is done
  292. //    with the SID it can use HeapFree().  This is consistent with
  293. //    other parts of this sample.
  294. //
  295. //    The SID Authority and RID used here are defined in winnt.h.
  296. //
  297. PSID CreateWorldSid()
  298. {
  299.     SID_IDENTIFIER_AUTHORITY authWorld = SECURITY_WORLD_SID_AUTHORITY;
  300.     PSID pSid, psidWorld;
  301.     BOOL bRes;
  302.     DWORD cbSid;
  303.  
  304.     bRes = AllocateAndInitializeSid(&authWorld,
  305.             1,
  306.             SECURITY_WORLD_RID,
  307.             0,
  308.             0,
  309.             0,
  310.             0,
  311.             0,
  312.             0,
  313.             0,
  314.             &psidWorld);
  315.     if (FALSE == bRes) {
  316.         PERR("AllocateAndInitializeSid");
  317.         ExitProcess(EXIT_FAILURE);
  318.     }
  319.  
  320.     // Make a copy of the SID using a HeapAlloc'd block for return
  321.     //
  322.     cbSid = GetLengthSid(psidWorld);
  323.  
  324.     pSid = (PSID) HeapAlloc(GetProcessHeap(), 0, cbSid);
  325.     if (NULL == pSid) {
  326.         fprintf(stderr, "HeapAlloc failed.\n");
  327.         ExitProcess(EXIT_FAILURE);
  328.     }
  329.  
  330.     bRes = CopySid(cbSid, pSid, psidWorld);
  331.     if (FALSE == bRes) {
  332.         PERR("CopySid");
  333.         ExitProcess(EXIT_FAILURE);
  334.     }
  335.  
  336.     FreeSid(psidWorld);
  337.  
  338.     return pSid;
  339. }
  340.  
  341.  
  342. //
  343. //  FUNCTION: GetLastErrorText
  344. //
  345. //  PURPOSE: Retrieves the text associated with the last system error.
  346. //
  347. //  PARAMETERS:
  348. //    none
  349. //
  350. //  RETURN VALUE:
  351. //    A pointer to the error text.
  352. //
  353. //  COMMENTS:
  354. //    The contents of the returned buffer will only be valid until
  355. //    the next call to this routine.
  356. //
  357. LPSTR GetLastErrorText()
  358. {
  359. #define MAX_MSG_SIZE 256
  360.  
  361.     static char szMsgBuf[MAX_MSG_SIZE];
  362.     DWORD dwError, dwRes;
  363.  
  364.     dwError = GetLastError ();
  365.  
  366.     dwRes = FormatMessage (
  367.                 FORMAT_MESSAGE_FROM_SYSTEM,
  368.                 NULL,
  369.                 dwError,
  370.                 MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
  371.                 szMsgBuf,
  372.                 MAX_MSG_SIZE,
  373.                 NULL);
  374.     if (0 == dwRes) {
  375.         fprintf(stderr, "FormatMessage failed with %d\n", GetLastError());
  376.         ExitProcess(EXIT_FAILURE);
  377.     }
  378.  
  379.     return szMsgBuf;
  380. }
  381.