winUser.cpp

Engine/source/platformWin32/winUser.cpp

More...

Public Defines

define
CSIDL_PROFILE() 0x0028

Public Typedefs

long
SHANDLE_PTR 

Detailed Description

Public Defines

CSIDL_PROFILE() 0x0028

Public Typedefs

typedef long SHANDLE_PTR 
  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "console/console.h"
 26#include "core/stringTable.h"
 27#include "core/strings/unicode.h"
 28
 29#ifndef TORQUE_OS_WIN64
 30typedef long SHANDLE_PTR;
 31#endif
 32
 33#include <shlobj.h>
 34#include <windows.h>
 35#include <lmcons.h>
 36
 37#define CSIDL_PROFILE 0x0028
 38
 39const char *Platform::getUserDataDirectory() 
 40{
 41   TCHAR szBuffer[ MAX_PATH + 1 ];
 42
 43   if(! SHGetSpecialFolderPath( NULL, szBuffer, CSIDL_APPDATA, true ) )
 44      return "";
 45
 46   TCHAR *ptr = szBuffer;
 47   while(*ptr)
 48   {
 49      if(*ptr == '\\')
 50         *ptr = '/';
 51      ++ptr;
 52   }
 53
 54#ifdef UNICODE
 55   char path[ MAX_PATH * 3 + 1 ];
 56   convertUTF16toUTF8( szBuffer, path );
 57#else
 58   char* path = szBuffer;
 59#endif
 60
 61
 62   return StringTable->insert( path );
 63}
 64
 65const char *Platform::getUserHomeDirectory() 
 66{
 67   TCHAR szBuffer[ MAX_PATH + 1 ];
 68   if(! SHGetSpecialFolderPath( NULL, szBuffer, CSIDL_PERSONAL, false ) )
 69      if(! SHGetSpecialFolderPath( NULL, szBuffer, CSIDL_COMMON_DOCUMENTS, false ) )
 70         return "";
 71
 72   TCHAR *ptr = szBuffer;
 73   while(*ptr)
 74   {
 75      if(*ptr == '\\')
 76         *ptr = '/';
 77      ++ptr;
 78   }
 79
 80#ifdef UNICODE
 81   char path[ MAX_PATH * 3 + 1 ];
 82   convertUTF16toUTF8( szBuffer, path );
 83#else
 84   char* path = szBuffer;
 85#endif
 86
 87   return StringTable->insert( path );
 88}
 89
 90
 91bool Platform::getUserIsAdministrator()
 92{
 93   BOOL   fReturn         = FALSE;
 94   DWORD  dwStatus;
 95   DWORD  dwAccessMask;
 96   DWORD  dwAccessDesired;
 97   DWORD  dwACLSize;
 98   DWORD  dwStructureSize = sizeof(PRIVILEGE_SET);
 99   PACL   pACL            = NULL;
100   PSID   psidAdmin       = NULL;
101
102   HANDLE hToken              = NULL;
103   HANDLE hImpersonationToken = NULL;
104
105   PRIVILEGE_SET   ps;
106   GENERIC_MAPPING GenericMapping;
107
108   PSECURITY_DESCRIPTOR     psdAdmin           = NULL;
109   SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
110
111
112   /*
113   Determine if the current thread is running as a user that is a member of
114   the local admins group.  To do this, create a security descriptor that
115   has a DACL which has an ACE that allows only local aministrators access.
116   Then, call AccessCheck with the current thread's token and the security
117   descriptor.  It will say whether the user could access an object if it
118   had that security descriptor.  Note: you do not need to actually create
119   the object.  Just checking access against the security descriptor alone
120   will be sufficient.
121   */
122   const DWORD ACCESS_READ  = 1;
123   const DWORD ACCESS_WRITE = 2;
124
125
126   __try
127   {
128
129      /*
130      AccessCheck() requires an impersonation token.  We first get a primary
131      token and then create a duplicate impersonation token.  The
132      impersonation token is not actually assigned to the thread, but is
133      used in the call to AccessCheck.  Thus, this function itself never
134      impersonates, but does use the identity of the thread.  If the thread
135      was impersonating already, this function uses that impersonation context.
136      */
137      if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY, TRUE, &hToken))
138      {
139         if (GetLastError() != ERROR_NO_TOKEN)
140            __leave;
141
142         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &hToken))
143            __leave;
144      }
145
146      if (!DuplicateToken (hToken, SecurityImpersonation, &hImpersonationToken))
147         __leave;
148
149
150      /*
151      Create the binary representation of the well-known SID that
152      represents the local administrators group.  Then create the security
153      descriptor and DACL with an ACE that allows only local admins access.
154      After that, perform the access check.  This will determine whether
155      the current user is a local admin.
156      */
157      if (!AllocateAndInitializeSid(&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
158         DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin))
159         __leave;
160
161      psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
162      if (psdAdmin == NULL)
163         __leave;
164
165      if (!InitializeSecurityDescriptor(psdAdmin, SECURITY_DESCRIPTOR_REVISION))
166         __leave;
167
168      // Compute size needed for the ACL.
169      dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidAdmin) - sizeof(DWORD);
170
171      pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
172      if (pACL == NULL)
173         __leave;
174
175      if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
176         __leave;
177
178      dwAccessMask= ACCESS_READ | ACCESS_WRITE;
179
180      if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin))
181         __leave;
182
183      if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE))
184         __leave;
185
186      /*
187      AccessCheck validates a security descriptor somewhat; set the group
188      and owner so that enough of the security descriptor is filled out to
189      make AccessCheck happy.
190      */
191      SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE);
192      SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE);
193
194      if (!IsValidSecurityDescriptor(psdAdmin))
195         __leave;
196
197      dwAccessDesired = ACCESS_READ;
198
199      /*
200      Initialize GenericMapping structure even though you
201      do not use generic rights.
202      */
203      GenericMapping.GenericRead    = ACCESS_READ;
204      GenericMapping.GenericWrite   = ACCESS_WRITE;
205      GenericMapping.GenericExecute = 0;
206      GenericMapping.GenericAll     = ACCESS_READ | ACCESS_WRITE;
207
208      if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired,
209         &GenericMapping, &ps, &dwStructureSize, &dwStatus,
210         &fReturn))
211      {
212         fReturn = FALSE;
213         __leave;
214      }
215   }
216   __finally
217   {
218
219      // Clean up.
220      if (pACL) LocalFree(pACL);
221      if (psdAdmin) LocalFree(psdAdmin);
222      if (psidAdmin) FreeSid(psidAdmin);
223      if (hImpersonationToken) CloseHandle (hImpersonationToken);
224      if (hToken) CloseHandle (hToken);
225   }
226
227   return fReturn;
228
229}
230