Mercurial > trustbridge
diff common/util.c @ 983:427e2e18b8c8
Move Shell functions into util
Due to a bug in mingw only one c file may include shlobj.h as there
is an unguarded inline definition in there leading to multiple
definition errors. Thus the get_program_data get_program_files
utility functions.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Fri, 29 Aug 2014 17:11:35 +0200 |
parents | 698b6a9bd75e |
children | 1c1964c27b39 6684e5012b7a |
line wrap: on
line diff
--- a/common/util.c Fri Aug 29 16:08:50 2014 +0200 +++ b/common/util.c Fri Aug 29 17:11:35 2014 +0200 @@ -17,6 +17,9 @@ #include <string.h> #else #include <windows.h> +#include <accctrl.h> +#include <aclapi.h> +#include <shlobj.h> #endif #ifndef APPNAME @@ -426,6 +429,46 @@ return ret; } +#ifdef _WIN32 +char * +get_program_files_folder () +{ + wchar_t *folder_name = NULL; + char *retval = NULL; + if (SHGetKnownFolderPath (&FOLDERID_ProgramFiles, /* Get program data dir */ + KF_FLAG_NO_ALIAS, + INVALID_HANDLE_VALUE, /* Get it for the default user */ + &folder_name) != S_OK) + { + PRINTLASTERROR ("Failed to get program files folder."); + return NULL; + } + + retval = wchar_to_utf8 (folder_name, wcslen(folder_name)); + CoTaskMemFree (folder_name); + return retval; +} + +/* This is a bit ridicoulous but necessary as shlobj.h contains an inline + definition. So only one C file may include it and thus we have to put + all our shlobj calls into one file... */ +wchar_t * +get_program_data_folder () +{ + wchar_t *folder_name = NULL; + if (SHGetKnownFolderPath (&FOLDERID_ProgramData, /* Get program data dir */ + KF_FLAG_CREATE | /* Create if it does not exist */ + KF_FLAG_INIT, /* Initialize it if created */ + INVALID_HANDLE_VALUE, /* Get it for the default user */ + &folder_name) != S_OK) + { + PRINTLASTERROR ("Failed to get folder path"); + return NULL; + } + return folder_name; +} +#endif + bool is_admin() { @@ -556,3 +599,128 @@ #endif } +#ifdef WIN32 +bool +create_restricted_directory (LPWSTR path) +{ + bool retval = false; + PSID everyone_SID = NULL, + admin_SID = NULL; + PACL access_control_list = NULL; + PSECURITY_DESCRIPTOR descriptor = NULL; + EXPLICIT_ACCESS explicit_access[2]; + SID_IDENTIFIER_AUTHORITY world_identifier = {SECURITY_WORLD_SID_AUTHORITY}, + admin_identifier = {SECURITY_NT_AUTHORITY}; + SECURITY_ATTRIBUTES security_attributes; + + ZeroMemory(&security_attributes, sizeof(security_attributes)); + ZeroMemory(&explicit_access, 2 * sizeof(EXPLICIT_ACCESS)); + + /* Create a well-known SID for the Everyone group. */ + if(!AllocateAndInitializeSid(&world_identifier, /* top-level identifier */ + 1, /* subauthorties count */ + SECURITY_WORLD_RID, /* Only one authority */ + 0, 0, 0, 0, 0, 0, 0, /* No other authorities*/ + &everyone_SID)) + { + PRINTLASTERROR ("Failed to allocate world sid.\n"); + return false; + } + + /* Initialize the first EXPLICIT_ACCESS structure for an ACE. + to allow everyone read access */ + explicit_access[0].grfAccessPermissions = GENERIC_READ; /* Give read access */ + explicit_access[0].grfAccessMode = SET_ACCESS; /* Overwrite other access for all users */ + explicit_access[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; /* make it stick */ + explicit_access[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; + explicit_access[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + explicit_access[0].Trustee.ptstrName = (LPTSTR) everyone_SID; + + /* Create the SID for the BUILTIN\Administrators group. */ + if(!AllocateAndInitializeSid(&admin_identifier, + 2, + SECURITY_BUILTIN_DOMAIN_RID, /*BUILTIN\ */ + DOMAIN_ALIAS_RID_ADMINS, /*\Administrators */ + 0, 0, 0, 0, 0, 0, /* No other */ + &admin_SID)) + { + PRINTLASTERROR ("Failed to allocate admin sid."); + goto done; + } + + /* explicit_access[1] grants admins full rights for this object and inherits + it to the children */ + explicit_access[1].grfAccessPermissions = GENERIC_ALL; + explicit_access[1].grfAccessMode = SET_ACCESS; + explicit_access[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; + explicit_access[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; + explicit_access[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; + explicit_access[1].Trustee.ptstrName = (LPTSTR) admin_SID; + + /* Set up the ACL structure. */ + if (ERROR_SUCCESS != SetEntriesInAcl(2, explicit_access, NULL, &access_control_list)) + { + PRINTLASTERROR ("Failed to set up Acl."); + goto done; + } + + /* Initialize a security descriptor */ + descriptor = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, + SECURITY_DESCRIPTOR_MIN_LENGTH); + if (descriptor == NULL) + { + PRINTLASTERROR("Failed to allocate descriptor."); + goto done; + } + + if (!InitializeSecurityDescriptor(descriptor, + SECURITY_DESCRIPTOR_REVISION)) + { + PRINTLASTERROR("Failed to initialize descriptor."); + goto done; + } + + /* Now we add the ACL to the the descriptor */ + if (!SetSecurityDescriptorDacl(descriptor, + TRUE, /* bDaclPresent flag */ + access_control_list, + FALSE)) /* not a default DACL */ + { + PRINTLASTERROR("Failed to set security descriptor."); + goto done; + } + + /* Finally set up the security attributes structure */ + security_attributes.nLength = sizeof (SECURITY_ATTRIBUTES); + security_attributes.lpSecurityDescriptor = descriptor; + security_attributes.bInheritHandle = FALSE; + + /* Use the security attributes to create the directory */ + if (!CreateDirectoryW(path, &security_attributes)) + { + DWORD err = GetLastError(); + if (err == ERROR_ALREADY_EXISTS) + { + /* Verify that the directory has the correct rights */ + // TODO + retval = true; + goto done; + } + ERRORPRINTF ("Failed to create directory. Err: %lu", err); + } + retval = true; + +done: + + if (everyone_SID) + FreeSid(everyone_SID); + if (admin_SID) + FreeSid(admin_SID); + if (access_control_list) + LocalFree(access_control_list); + if (descriptor) + LocalFree(descriptor); + + return retval; +} +#endif