diff --git a/CHANGELOG.md b/CHANGELOG.md index f01f72a1..d2afaf83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,56 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.8.5 / 5.50.5] - 2021-07-05 + +### Added +- added global hot key to terminate all boxed processes (by default Ctrl+Break) +- the Run Sandboxed dialog can now handled by the Sandman UI. +- added "AllowBoxedJobs=y" allowing boxed processes to use nested jobs on windows 8 and later +-- note: this allows Chrome and other programs to use the job system for additional isoaltion +- added librewolf.exe to the list of firefox derivatives [#927](https://github.com/sandboxie-plus/Sandboxie/issues/927) +- added run regedit sandboxed menu command +- added new support settings tab to sandman UI for updates and stuff +- added code integrity verification to sbie service and UI + +### Changed +- Replaced the Process List used by the driver with a much faster Hash Map implementation +-- Note: this change provides an almost static sys call speed of 1.2us irregardless of the running process count +-- The old list, with 100 programs running required: 4.5µs; with 200: 12µs; and with 300: 18µs per syscall +-- Note: some of the slow down was affecting also non sandboxed applications due to how the driver handles certein callbacks +- Replaced the per process Thread List used by the driver with a much faster Hash Map implementation +- Replaced config section list with a hash map to improve conf performance, and increased line limit to 100000 +-- not yet enabled in ptoduction build +- the presence of default box is only checked on connect +- the portable dir dialog now shows the directory [#924](https://github.com/sandboxie-plus/Sandboxie/issues/924) +- when terminated boxed processes we now first try doing that by terminating the job object +- the driver now by default can terminate problematic processes withut the help of the service +- box delete routine now retryed up to 10 times to fix [#954](https://github.com/sandboxie-plus/Sandboxie/issues/954) +- Replaced the Process List used by the service with a much faster Hash Map implementation +- Replaced the per process Thread List used by the service with a much faster Hash Map implementation + +### Fixed +- fixed faulty initialization in SetServiceStatus [#921](https://github.com/sandboxie-plus/Sandboxie/issues/921) +- fixed buttons position in Classic UI settings [#914](https://github.com/sandboxie-plus/Sandboxie/issues/914) +- fixed missing password length check in the sandman ui [#925](https://github.com/sandboxie-plus/Sandboxie/issues/925) +- fixed issues opening job objects by name +- fixed missing permission check when re opening job object handles (thanks Diversenok) +- fixed issue with some chromium 90+ hooks affecting pdf plugin in derived browsers [#930](https://github.com/sandboxie-plus/Sandboxie/issues/930) [#817](https://github.com/sandboxie-plus/Sandboxie/issues/817) +- fixed isues with reconnecting broken LPC ports used for communicationw with SbieSvc +- fixed minor setting issue [#957](https://github.com/sandboxie-plus/Sandboxie/issues/957) +- fixed minor ui issue with resource access COM settigns [#958](https://github.com/sandboxie-plus/Sandboxie/issues/958) +- fixed an issue with NtQueryKey using NtQueryObject instead [#951](https://github.com/sandboxie-plus/Sandboxie/issues/951) +- fixed crash in key.c when failing to resolve key paths +- added workaround for top most modality issue [#873](https://github.com/sandboxie-plus/Sandboxie/issues/873) +-- the notification window is not only top most for 5 seconds +- fixed an issue deleteing directories introduced in 5.49.5 + +### Removed +- removed switch for "BlockPassword=n" as it does not seam to be working [#938](https://github.com/sandboxie-plus/Sandboxie/issues/938) +-- use "OpenSamEndpoint=y" to allow for password change in windows 10 + + + ## [0.8.2 / 5.50.2] - 2021-06-15 ### Changed diff --git a/Sandboxie/common/base64.c b/Sandboxie/common/base64.c new file mode 100644 index 00000000..cf6125f2 --- /dev/null +++ b/Sandboxie/common/base64.c @@ -0,0 +1,146 @@ +#include +#include +#include + +size_t b64_encoded_size(size_t inlen) +{ + size_t ret; + + ret = inlen; + if (inlen % 3 != 0) + ret += 3 - (inlen % 3); + ret /= 3; + ret *= 4; + + return ret; +} + +const wchar_t b64_chars[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +wchar_t* b64_encode(const unsigned char *in, size_t inlen) +{ + wchar_t* out; + size_t elen; + size_t i; + size_t j; + size_t v; + + if (in == NULL || inlen == 0) + return NULL; + + elen = b64_encoded_size(inlen); + out = malloc((elen+1) * sizeof(wchar_t)); + out[elen] = L'\0'; + + for (i=0, j=0; i> 18) & 0x3F]; + out[j+1] = b64_chars[(v >> 12) & 0x3F]; + if (i+1 < inlen) { + out[j+2] = b64_chars[(v >> 6) & 0x3F]; + } else { + out[j+2] = L'='; + } + if (i+2 < inlen) { + out[j+3] = b64_chars[v & 0x3F]; + } else { + out[j+3] = L'='; + } + } + + return out; +} + +size_t b64_decoded_size(const wchar_t *in) +{ + size_t len; + size_t ret; + size_t i; + + if (in == NULL) + return 0; + + len = wcslen(in); + ret = len / 4 * 3; + + for (i=len; i-->0; ) { + if (in[i] == L'=') { + ret--; + } else { + break; + } + } + + return ret; +} + +//static void b64_generate_decode_table() +//{ +// int inv[80]; +// size_t i; +// +// memset(inv, -1, sizeof(inv)); +// for (i=0; i= L'0' && c <= L'9') + return 1; + if (c >= L'A' && c <= L'Z') + return 1; + if (c >= L'a' && c <= L'z') + return 1; + if (c == L'+' || c == L'/' || c == L'=') + return 1; + return 0; +} + +int b64_decode(const wchar_t *in, unsigned char *out, size_t outlen) +{ + size_t len; + size_t i; + size_t j; + int v; + + if (in == NULL || out == NULL) + return 0; + + len = wcslen(in); + if (outlen < b64_decoded_size(in) || len % 4 != 0) + return 0; + + for (i=0; i> 16) & 0xFF; + if (in[i+2] != '=') + out[j+1] = (v >> 8) & 0xFF; + if (in[i+3] != '=') + out[j+2] = v & 0xFF; + } + + return 1; +} + diff --git a/Sandboxie/common/map.c b/Sandboxie/common/map.c new file mode 100644 index 00000000..18fe6b6d --- /dev/null +++ b/Sandboxie/common/map.c @@ -0,0 +1,319 @@ +/* + * Copyright 2021 David Xanatos, xanasoft.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "map.h" + +struct map_node_t { + unsigned int hash; + void *value; + map_node_t *next; + char key[0]; + /* char value[]; */ +}; + + +VOID* map_alloc(void* pool, size_t size) +{ + if (!pool) return NULL; +#ifdef KERNEL_MODE + size_t* base = Mem_Alloc(pool, sizeof(size_t) + size); +#else + size_t* base = (size_t*)Pool_Alloc((POOL*)pool, sizeof(size_t) + size); +#endif + *base++ = size; + return base; +} + + +VOID map_free(void* pool, void* ptr) +{ + size_t* base = (size_t*)ptr; + size_t size = *--base; +#ifdef KERNEL_MODE + Mem_Free(base, size); +#else + Pool_Free(base, size); +#endif +} + + +static unsigned int map_hash(const void* key, size_t size) +{ + /*const int MULTIPLIER = 37; + unsigned int h = 0; + for (unsigned char* p = (unsigned char*)key; p < ((unsigned char*)key) + size; p++) + h = MULTIPLIER * h + *p; + return h;*/ + unsigned int hash = 5381; + for (unsigned char* ptr = (unsigned char*)key; ptr < ((unsigned char*)key) + size; ptr++) + hash = ((hash << 5) + hash) ^ *ptr; + return hash; +} + + +int map_wcssize(const void* key) +{ + return (wcslen((const wchar_t*)key) + 1) * sizeof(WCHAR); +} + + +BOOLEAN map_wcsimatch(const void* key1, const void* key2) +{ + return (_wcsicmp((const wchar_t*)key1, (const wchar_t*)key2) == 0); +} + + +void map_init(map_base_t* m, void* pool) +{ + memset(m, 0, sizeof(map_base_t)); + m->mem_pool = pool; + m->func_malloc = &map_alloc; + m->func_free = &map_free; + m->func_hash_key = &map_hash; + m->func_key_size = NULL; // use key by value not by reference + m->func_match_key = NULL; // use memcmp by defualt +} + + +static int map_bucket_idx(map_base_t* m, unsigned int hash) +{ + // Note: this works only with bucket sizes which are a power of 2 + // this can be generalized by using % instead of & + return hash & (m->nbuckets - 1); +} + + +static void map_add_node(map_base_t* m, map_node_t* node) +{ + int n = map_bucket_idx(m, node->hash); + node->next = m->buckets[n]; + m->buckets[n] = node; +} + + +BOOLEAN map_resize(map_base_t* m, int nbuckets) +{ + map_node_t** buckets = (map_node_t**)m->func_malloc(m->mem_pool, sizeof(*m->buckets) * nbuckets); + if (!buckets) return FALSE; + memset(buckets, 0, sizeof(*m->buckets) * nbuckets); + + map_node_t* nodes = NULL; + // store all old entries + for (unsigned int i = m->nbuckets; i--; ) { + map_node_t* node = (m->buckets)[i]; + while (node) { + map_node_t* next = node->next; + node->next = nodes; + nodes = node; + node = next; + } + } + + // swap bucket array + if (m->buckets) m->func_free(m->mem_pool, m->buckets); + m->buckets = buckets; + m->nbuckets = nbuckets; + + // re insert all entries from our temporary list back into our buckets + map_node_t* node = nodes; + while (node) { + map_node_t* next = node->next; + map_add_node(m, node); + node = next; + } + + return TRUE; +} + + +static map_node_t* map_new_node(map_base_t* m, const void* _key, void* vdata, size_t vsize) +{ + const void* key; + int ksize; + if (m->func_key_size) { + key = _key; + ksize = m->func_key_size(key); + } + else { + key = &_key; + ksize = sizeof(void*); + } + unsigned int hash = m->func_hash_key(key, ksize); + + int voffset = ksize + ((sizeof(void*) - ksize) % sizeof(void*)); + map_node_t* node = (map_node_t*)m->func_malloc(m->mem_pool, sizeof(*node) + voffset + vsize); + if (!node) return NULL; + + node->hash = hash; + memcpy(node->key, key, ksize); + node->next = NULL; + if (vsize) { + node->value = vsize ? node->key + voffset : NULL; + memcpy(node->value, vdata, vsize); + } + else + node->value = vdata; + return node; +} + + +BOOLEAN map_insert(map_base_t* m, const void* key, void* vdata, size_t vsize) +{ + // create a new node and fill inn all the blanks + map_node_t* node = map_new_node(m, key, vdata, vsize); + if(!node) goto fail; + + // check and if we need to grow our bucker array + //const int reduce_buckets = 0; // average 1.5 nodes/bucket and 49% of buckets used + const int reduce_buckets = 1; // average 1.9 nodes/bucket and 75% of buckets used + //const int reduce_buckets = 2; // average 3.2 nodes/bucket and 91% of buckets used + //const int reduce_buckets = 3; // average 5.9 nodes/bucket and 98% of buckets used + //const int reduce_buckets = 4; // average 11.8 nodes/bucket and 100% of buckets used + if ((m->nnodes >> reduce_buckets) >= m->nbuckets) { + int nbuckets = (m->nbuckets > 0) ? (m->nbuckets << 1) : 1; // *2 + if (!map_resize(m, nbuckets)) goto fail; + } + + // add new entry to the right bucket + map_add_node(m, node); + m->nnodes++; + + return TRUE; +fail: + if (node) m->func_free(m->mem_pool, node); + return FALSE; +} + + +static map_node_t** map_getref(map_base_t* m, const void* _key) +{ + if (!m->buckets) return NULL; + + const void* key; + int ksize; + if (m->func_key_size) { + key = _key; + ksize = m->func_key_size(key); + } + else { + key = &_key; + ksize = sizeof(void*); + } + unsigned int hash = m->func_hash_key(key, ksize); + + map_node_t** next = &m->buckets[map_bucket_idx(m, hash)]; + while (*next) { + if ((*next)->hash == hash && (m->func_match_key + ? m->func_match_key((*next)->key, key) + : (memcmp((*next)->key, key, ksize) == 0) + )) { + return next; + } + next = &(*next)->next; + } + return NULL; +} + + +void* map_get(map_base_t* m, const void* key) +{ + map_node_t** next = map_getref(m, key); + return next ? (*next)->value : NULL; +} + + +void* map_remove(map_base_t* m, const void* key) +{ + void* value = NULL; + map_node_t** next = map_getref(m, key); + if (next) { + map_node_t* node = *next; + *next = (*next)->next; + value = node->value; + m->func_free(m->mem_pool, node); + m->nnodes--; + } + return value; +} + + +void map_deinit(map_base_t* m) +{ + for (unsigned int i = m->nbuckets; i--; ) { + map_node_t* node = m->buckets[i]; + while (node) { + map_node_t* next = node->next; + m->func_free(m->mem_pool, node); + node = next; + } + } + if (m->buckets) m->func_free(m->mem_pool, m->buckets); +} + + +map_iter_t map_iter() +{ + map_iter_t iter; + memset(&iter, 0, sizeof(map_iter_t)); + iter.bucketidx = -1; + return iter; +} + + +BOOLEAN map_next(map_base_t* m, map_iter_t* iter) +{ + if (iter->node) { + iter->node = iter->node->next; + if (iter->node == NULL) goto nextBucket; + } + else { + nextBucket: + do { + if (++iter->bucketidx >= m->nbuckets) { + return FALSE; + } + iter->node = m->buckets[iter->bucketidx]; + } while (iter->node == NULL); + } + iter->key = iter->node->key; + iter->value = iter->node->value; + return TRUE; +} + + +/* +void map_dump(map_base_t *m) +{ + int used = 0; + int empty = 0; + int bucketidx = 0; + //printf("start\r\n"); + while(++bucketidx < m->nbuckets) { + map_node_t* bucket = m->buckets[bucketidx]; + if (bucket) { + used++; + //printf("bucket %d\r\n", bucketidx); + //for(map_node_t* node = bucket; node != NULL; node = node->next) { + // printf("node %d: %d\r\n", node->hash, (int)node->value); + //} + } else { + empty++; + //printf("EMPTY bucket %d\r\n", bucketidx); + } + } + printf("\r\n\r\nBucket usage %d/%d (%d%%), average nodes per used bucket %.2f\r\n", used, used+empty, 100*used/(used+empty), (double)m->nnodes/used); +}*/ \ No newline at end of file diff --git a/Sandboxie/common/map.h b/Sandboxie/common/map.h new file mode 100644 index 00000000..17576d35 --- /dev/null +++ b/Sandboxie/common/map.h @@ -0,0 +1,72 @@ +/* + * Copyright 2021 David Xanatos, xanasoft.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef MAP_H +#define MAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct map_node_t; +typedef struct map_node_t map_node_t; + +struct map_base_t; +typedef struct map_base_t map_base_t; + +struct map_base_t { + map_node_t **buckets; + unsigned int nbuckets, nnodes; + + void* mem_pool; + void*(*func_malloc)(void* pool, size_t size); + void(*func_free)(void* pool, void* ptr); + + int(*func_key_size)(const void* key); + unsigned int (*func_hash_key)(const void* key, size_t size); + BOOLEAN (*func_match_key)(const void* key1, const void* key2); +}; + +typedef map_base_t HASH_MAP; + +int map_wcssize(const void* key); +BOOLEAN map_wcsimatch(const void* key1, const void* key2); + +void map_init(map_base_t *m, void* pool); +BOOLEAN map_resize(map_base_t* m, int nbuckets); +BOOLEAN map_insert(map_base_t *m, const void* key, void* vdata, size_t vsize); +void* map_get(map_base_t *m, const void* key); +void* map_remove(map_base_t *m, const void* key); +void map_deinit(map_base_t *m); + +typedef struct { + unsigned int bucketidx; + map_node_t *node; + void* key; + void* value; +} map_iter_t; + +map_iter_t map_iter(); +BOOLEAN map_next(map_base_t *m, map_iter_t *iter); + +//void map_dump(map_base_t *m); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sandboxie/common/my_version.h b/Sandboxie/common/my_version.h index e67c3ce6..e73bff08 100644 --- a/Sandboxie/common/my_version.h +++ b/Sandboxie/common/my_version.h @@ -21,8 +21,8 @@ #ifndef _MY_VERSION_H #define _MY_VERSION_H -#define MY_VERSION_BINARY 5,50,2 -#define MY_VERSION_STRING "5.50.2" +#define MY_VERSION_BINARY 5,50,5 +#define MY_VERSION_STRING "5.50.5" #define MY_VERSION_COMPAT "5.50.0" // this refers to the driver ABI compatibility // These #defines are used by either Resource Compiler, or by NSIC installer diff --git a/Sandboxie/common/ntproto.h b/Sandboxie/common/ntproto.h index 39f4ff7d..893a31bd 100644 --- a/Sandboxie/common/ntproto.h +++ b/Sandboxie/common/ntproto.h @@ -463,6 +463,11 @@ typedef NTSTATUS (*P_NtOpenFile)( IN ULONG ShareAccess, IN ULONG OpenOptions); +typedef NTSTATUS (*P_NtOpenJobObject)( + OUT PHANDLE JobHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes); + typedef NTSTATUS (*P_NtOpenKey)( OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, diff --git a/Sandboxie/common/verify.c b/Sandboxie/common/verify.c new file mode 100644 index 00000000..11acf8f3 --- /dev/null +++ b/Sandboxie/common/verify.c @@ -0,0 +1,321 @@ + +#include +#define WIN32_NO_STATUS +typedef long NTSTATUS; + +#include +#include +//#include +#include +#include +#include +#include + +#include "..\..\Sandboxie\common\win32_ntddk.h" + + + +static UCHAR KphpTrustedPublicKey[] = +{ + 0x45, 0x43, 0x53, 0x31, 0x20, 0x00, 0x00, 0x00, 0x05, 0x7A, 0x12, 0x5A, 0xF8, 0x54, 0x01, 0x42, + 0xDB, 0x19, 0x87, 0xFC, 0xC4, 0xE3, 0xD3, 0x8D, 0x46, 0x7B, 0x74, 0x01, 0x12, 0xFC, 0x78, 0xEB, + 0xEF, 0x7F, 0xF6, 0xAF, 0x4D, 0x9A, 0x3A, 0xF6, 0x64, 0x90, 0xDB, 0xE3, 0x48, 0xAB, 0x3E, 0xA7, + 0x2F, 0xC1, 0x18, 0x32, 0xBD, 0x23, 0x02, 0x9D, 0x3F, 0xF3, 0x27, 0x86, 0x71, 0x45, 0x26, 0x14, + 0x14, 0xF5, 0x19, 0xAA, 0x2D, 0xEE, 0x50, 0x10 +}; + + +#define CST_SIGN_ALGORITHM BCRYPT_ECDSA_P256_ALGORITHM +#define CST_SIGN_ALGORITHM_BITS 256 +#define CST_HASH_ALGORITHM BCRYPT_SHA256_ALGORITHM +#define CST_BLOB_PRIVATE BCRYPT_ECCPRIVATE_BLOB +#define CST_BLOB_PUBLIC BCRYPT_ECCPUBLIC_BLOB + +#define KPH_SIGNATURE_MAX_SIZE (128 * 1024) // 128 kB + +#define FILE_BUFFER_SIZE 4096 + + +NTSTATUS PhCreateFileWin32(_Out_ PHANDLE FileHandle, _In_ PCWSTR FileName, _In_ ACCESS_MASK DesiredAccess, + _In_opt_ ULONG FileAttributes, _In_ ULONG ShareAccess, _In_ ULONG CreateDisposition, _In_ ULONG CreateOptions) +{ + UNICODE_STRING uni; + OBJECT_ATTRIBUTES attr; + WCHAR wszBuffer[MAX_PATH]; + _snwprintf(wszBuffer, MAX_PATH, L"\\??\\%s", FileName); + RtlInitUnicodeString(&uni, wszBuffer); + InitializeObjectAttributes(&attr, &uni, OBJ_CASE_INSENSITIVE, NULL, 0); + + IO_STATUS_BLOCK Iosb; + return NtCreateFile(FileHandle, DesiredAccess, &attr, &Iosb, NULL, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, NULL, 0); +} + +NTSTATUS PhGetFileSize(_In_ HANDLE FileHandle, _Out_ PLARGE_INTEGER Size) +{ + if (GetFileSizeEx(FileHandle, Size)) + return STATUS_SUCCESS; + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS CstReadFile( + _In_ PWSTR FileName, + _In_ ULONG FileSizeLimit, + _Out_ PVOID* Buffer, + _Out_ PULONG FileSize + ) +{ + NTSTATUS status; + HANDLE fileHandle = INVALID_HANDLE_VALUE; + LARGE_INTEGER fileSize; + PVOID buffer; + IO_STATUS_BLOCK iosb; + + if (!NT_SUCCESS(status = PhCreateFileWin32(&fileHandle, FileName, FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE))) + goto CleanupExit; + + if (!NT_SUCCESS(status = PhGetFileSize(fileHandle, &fileSize))) + goto CleanupExit; + + if (fileSize.QuadPart > FileSizeLimit) + goto CleanupExit; + + buffer = malloc((ULONG)fileSize.QuadPart); + if (!NT_SUCCESS(status = NtReadFile(fileHandle, NULL, NULL, NULL, &iosb, buffer, (ULONG)fileSize.QuadPart, NULL, NULL))) + goto CleanupExit; + + *Buffer = buffer; + *FileSize = (ULONG)fileSize.QuadPart; + +CleanupExit: + if(fileHandle != INVALID_HANDLE_VALUE) + NtClose(fileHandle); + + return status; +} + +typedef struct { + BCRYPT_ALG_HANDLE hashAlgHandle; + ULONG hashObjectSize; + ULONG hashSize; + PVOID hashObject; + BCRYPT_HASH_HANDLE hashHandle; + +} CST_HASH_OBJ; + +static VOID CstFreeHash(CST_HASH_OBJ* pHashObj) +{ + if (pHashObj->hashHandle) + BCryptDestroyHash(pHashObj->hashHandle); + if (pHashObj->hashObject) + free(pHashObj->hashObject); // must be freed after destroying hash object + if (pHashObj->hashAlgHandle) + BCryptCloseAlgorithmProvider(pHashObj->hashAlgHandle, 0); +} + +static NTSTATUS CstInitHash(CST_HASH_OBJ* pHashObj) +{ + NTSTATUS status; + ULONG querySize; + memset(pHashObj, 0, sizeof(CST_HASH_OBJ)); + + if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&pHashObj->hashAlgHandle, CST_HASH_ALGORITHM, NULL, 0))) + goto CleanupExit; + + if (!NT_SUCCESS(status = BCryptGetProperty(pHashObj->hashAlgHandle, BCRYPT_OBJECT_LENGTH, (PUCHAR)&pHashObj->hashObjectSize, sizeof(ULONG), &querySize, 0))) + goto CleanupExit; + + if (!NT_SUCCESS(status = BCryptGetProperty(pHashObj->hashAlgHandle, BCRYPT_HASH_LENGTH, (PUCHAR)&pHashObj->hashSize, sizeof(ULONG), &querySize, 0))) + goto CleanupExit; + + pHashObj->hashObject = malloc(pHashObj->hashObjectSize); + if (!pHashObj->hashObject) { + status = STATUS_INSUFFICIENT_RESOURCES; + goto CleanupExit; + } + + if (!NT_SUCCESS(status = BCryptCreateHash(pHashObj->hashAlgHandle, &pHashObj->hashHandle, (PUCHAR)pHashObj->hashObject, pHashObj->hashObjectSize, NULL, 0, 0))) + goto CleanupExit; + +CleanupExit: + if (!NT_SUCCESS(status)) + CstFreeHash(pHashObj); + + return status; +} + +static NTSTATUS CstHashData( + CST_HASH_OBJ* pHashObj, + _Out_ PVOID Data, + _Out_ ULONG DataSize + ) +{ + return BCryptHashData(pHashObj->hashHandle, (PUCHAR)Data, DataSize, 0); +} + +static NTSTATUS CstFinishHash( + CST_HASH_OBJ* pHashObj, + _Out_ PVOID* Hash, + _Out_ PULONG HashSize + ) +{ + NTSTATUS status; + PVOID hash; + + hash = malloc(pHashObj->hashSize); + if (!hash) { + status = STATUS_INSUFFICIENT_RESOURCES; + goto CleanupExit; + } + + if (!NT_SUCCESS(status = BCryptFinishHash(pHashObj->hashHandle, (PUCHAR)hash, pHashObj->hashSize, 0))) + goto CleanupExit; + + *HashSize = pHashObj->hashSize; + *Hash = hash; + return STATUS_SUCCESS; + +CleanupExit: + if (hash) + free(hash); + + return status; +} + + +static NTSTATUS CstHashFile( + _In_ PCWSTR FileName, + _Out_ PVOID* Hash, + _Out_ PULONG HashSize + ) +{ + NTSTATUS status; + HANDLE fileHandle = INVALID_HANDLE_VALUE; + PVOID buffer = NULL; + IO_STATUS_BLOCK iosb; + CST_HASH_OBJ hashObj; + + if (!NT_SUCCESS(status = CstInitHash(&hashObj))) + goto CleanupExit; + + if (!NT_SUCCESS(status = PhCreateFileWin32(&fileHandle, FileName, FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE))) + goto CleanupExit; + + buffer = malloc(FILE_BUFFER_SIZE); + if (!buffer) { + status = STATUS_INSUFFICIENT_RESOURCES; + goto CleanupExit; + } + + while (TRUE) + { + if (!NT_SUCCESS(status = NtReadFile(fileHandle, NULL, NULL, NULL, &iosb, buffer, FILE_BUFFER_SIZE, NULL, NULL))) + { + if (status == STATUS_END_OF_FILE) + break; + + goto CleanupExit; + } + + if (!NT_SUCCESS(status = CstHashData(&hashObj, buffer, (ULONG)iosb.Information))) + goto CleanupExit; + } + + if (!NT_SUCCESS(status = CstFinishHash(&hashObj, Hash, HashSize))) + goto CleanupExit; + +CleanupExit: + if(buffer) + free(buffer); + if(fileHandle != INVALID_HANDLE_VALUE) + NtClose(fileHandle); + CstFreeHash(&hashObj); + + return status; +} + +static NTSTATUS VerifyHashSignature( + _In_ PVOID Hash, + _In_ ULONG HashSize, + _In_ PVOID Signature, + _In_ ULONG SignatureSize + ) +{ + NTSTATUS status; + BCRYPT_ALG_HANDLE signAlgHandle = NULL; + BCRYPT_KEY_HANDLE keyHandle = NULL; + + // Import the trusted public key. + + if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&signAlgHandle, CST_SIGN_ALGORITHM, NULL, 0))) + goto CleanupExit; + if (!NT_SUCCESS(status = BCryptImportKeyPair(signAlgHandle, NULL, CST_BLOB_PUBLIC, &keyHandle, + KphpTrustedPublicKey, sizeof(KphpTrustedPublicKey), 0))) + { + goto CleanupExit; + } + + // Verify the hash. + + if (!NT_SUCCESS(status = BCryptVerifySignature(keyHandle, NULL, (PUCHAR)Hash, HashSize, (PUCHAR)Signature, + SignatureSize, 0))) + { + goto CleanupExit; + } + +CleanupExit: + if (keyHandle != NULL) + BCryptDestroyKey(keyHandle); + if (signAlgHandle) + BCryptCloseAlgorithmProvider(signAlgHandle, 0); + + return status; +} + +NTSTATUS VerifyFileSignature(const wchar_t* FilePath) +{ + NTSTATUS status; + ULONG hashSize; + PVOID hash = NULL; + ULONG signatureSize; + PVOID signature = NULL; + WCHAR* signatureFileName = NULL; + + + // Read the signature. + signatureFileName = (WCHAR*)malloc((wcslen(FilePath) + 4 + 1) * sizeof(WCHAR)); + if(!signatureFileName) { + status = STATUS_INSUFFICIENT_RESOURCES; + goto CleanupExit; + } + wcscpy(signatureFileName, FilePath); + wcscat(signatureFileName, L".sig"); + + // Read the signature file. + + if (!NT_SUCCESS(status = CstReadFile(signatureFileName, KPH_SIGNATURE_MAX_SIZE, &signature, &signatureSize))) + goto CleanupExit; + + // Hash the file. + + if (!NT_SUCCESS(status = CstHashFile(FilePath, &hash, &hashSize))) + goto CleanupExit; + + // Verify the hash. + + if (!NT_SUCCESS(status = VerifyHashSignature((PUCHAR)hash, hashSize, (PUCHAR)signature, signatureSize))) + { + goto CleanupExit; + } + +CleanupExit: + if (signature) + free(signature); + if (hash) + free(hash); + if (signatureFileName) + free(signatureFileName); + + return status; +} + diff --git a/Sandboxie/common/win32_ntddk.h b/Sandboxie/common/win32_ntddk.h index 68429888..add498fb 100644 --- a/Sandboxie/common/win32_ntddk.h +++ b/Sandboxie/common/win32_ntddk.h @@ -2284,6 +2284,11 @@ __declspec(dllimport) NTSTATUS __stdcall NtCreateJobObject( IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL); +__declspec(dllimport) NTSTATUS __stdcall NtOpenJobObject( + OUT PHANDLE JobHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes); + __declspec(dllimport) NTSTATUS __stdcall NtAssignProcessToJobObject( HANDLE hJob, HANDLE hProcess); diff --git a/Sandboxie/core/dll/SboxDll.vcxproj b/Sandboxie/core/dll/SboxDll.vcxproj index 09d3685f..1a6cb3ab 100644 --- a/Sandboxie/core/dll/SboxDll.vcxproj +++ b/Sandboxie/core/dll/SboxDll.vcxproj @@ -375,6 +375,7 @@ + diff --git a/Sandboxie/core/dll/SboxDll.vcxproj.filters b/Sandboxie/core/dll/SboxDll.vcxproj.filters index ace1fbac..056f2241 100644 --- a/Sandboxie/core/dll/SboxDll.vcxproj.filters +++ b/Sandboxie/core/dll/SboxDll.vcxproj.filters @@ -231,6 +231,9 @@ common + + common + diff --git a/Sandboxie/core/dll/config.c b/Sandboxie/core/dll/config.c index 93fada6b..212e1522 100644 --- a/Sandboxie/core/dll/config.c +++ b/Sandboxie/core/dll/config.c @@ -201,7 +201,7 @@ _FX BOOLEAN Config_MatchImageGroup( //--------------------------------------------------------------------------- -_FX WCHAR* Config_MatchImageAndGetValue(WCHAR* value, const WCHAR* ImageName, ULONG* pMode) +_FX WCHAR* Config_MatchImageAndGetValue(WCHAR* value, const WCHAR* ImageName, ULONG* pLevel) { // // if the setting indicates an image name followed by a comma, @@ -220,8 +220,7 @@ _FX WCHAR* Config_MatchImageAndGetValue(WCHAR* value, const WCHAR* ImageName, UL if (*value == L'!') { inv = TRUE; ++value; - } - else + } else inv = FALSE; ULONG len = (ULONG)(tmp - value); @@ -230,22 +229,25 @@ _FX WCHAR* Config_MatchImageAndGetValue(WCHAR* value, const WCHAR* ImageName, UL if (inv) match = !match; if (!match) - tmp = NULL; - else if (pMode) { + return NULL; + else if (pLevel) { if (len == 1 && *value == L'*') - *pMode = 2; // 2 - match all + *pLevel = 2; // 2 - match all else - *pMode = inv ? 1 : 0; // 1 - match by negation, 0 - exact match + *pLevel = inv ? 1 : 0; // 1 - match by negation, 0 - exact match } } - value = tmp ? tmp + 1 : NULL; + value = tmp + 1; } else { - if (pMode) *pMode = 2; // 2 - global default + if (pLevel) *pLevel = 2; // 2 - global default } + if (! *value) + return NULL; + return value; } @@ -270,10 +272,22 @@ BOOLEAN Config_String2Bool(const WCHAR* value, BOOLEAN defval) //--------------------------------------------------------------------------- -BOOLEAN Config_GetSettingsForImageName_bool(const WCHAR* setting, BOOLEAN defval) +_FX BOOLEAN Config_GetSettingsForImageName_bool(const WCHAR* setting, BOOLEAN defval) +{ + return SbieDll_GetSettingsForImageName_bool(NULL, Dll_ImageName, setting, defval); +} + + +//--------------------------------------------------------------------------- +// SbieDll_GetSettingsForImageName_bool +//--------------------------------------------------------------------------- + + +_FX BOOLEAN SbieDll_GetSettingsForImageName_bool( + const WCHAR* boxname, const WCHAR* image_name, const WCHAR* setting, BOOLEAN defval) { WCHAR value[16]; - Config_GetSettingsForImageName(setting, value, sizeof(value), NULL); + SbieDll_GetSettingsForImageName(boxname, image_name, setting, value, sizeof(value), NULL); return Config_String2Bool(value, defval); } @@ -312,43 +326,44 @@ _FX BOOLEAN Config_InitPatternList(const WCHAR* setting, LIST* list) //--------------------------------------------------------------------------- -// Config_GetSettingsForImageName +// SbieDll_GetSettingsForImageName //--------------------------------------------------------------------------- -_FX NTSTATUS Config_GetSettingsForImageName( - const WCHAR* setting, WCHAR* value, ULONG value_size, const WCHAR* deftext) +_FX BOOLEAN SbieDll_GetSettingsForImageName( + const WCHAR* boxname, const WCHAR* image_name, const WCHAR* setting, WCHAR* value, ULONG value_size, const WCHAR* deftext) { WCHAR conf_buf[2048]; - ULONG found_mode = -1; + ULONG found_level = -1; ULONG index = 0; while (1) { NTSTATUS status = SbieApi_QueryConf( - NULL, setting, index, conf_buf, sizeof(conf_buf) - 16 * sizeof(WCHAR)); + boxname, setting, index, conf_buf, sizeof(conf_buf) - 16 * sizeof(WCHAR)); if (!NT_SUCCESS(status)) break; ++index; - ULONG mode = -1; - WCHAR* found_value = Config_MatchImageAndGetValue(conf_buf, Dll_ImageName, &mode); - if (!found_value || mode > found_mode) + ULONG level = -1; + WCHAR* found_value = Config_MatchImageAndGetValue(conf_buf, image_name, &level); + if (!found_value || level > found_level) continue; //if (found_value) { // SbieApi_Log(2302, L"%S - %S [%S]", setting, Dll_ImageName, Dll_BoxName); // break; //} wcscpy_s(value, value_size / sizeof(WCHAR), found_value); - found_mode = mode; + found_level = level; } - if (found_mode == -1) { + if (found_level == -1) { if (deftext) wcscpy_s(value, value_size / sizeof(WCHAR), deftext); else value[0] = L'\0'; + return FALSE; } - return STATUS_SUCCESS; + return TRUE; } @@ -560,17 +575,45 @@ BOOLEAN SbieDll_CheckStringInList(const WCHAR* string, const WCHAR* boxname, con //--------------------------------------------------------------------------- -// Config_GetTagValue +// Config_SkipWhiteSpace //--------------------------------------------------------------------------- -WCHAR* Config_GetTagValue(WCHAR* str, WCHAR** value, ULONG* len, WCHAR sep) +VOID Config_SkipWhiteSpace(WCHAR** pstr) { + while ((*pstr)[0] == L' ' + || (*pstr)[0] == L'\r' + || (*pstr)[0] == L'\n' + || (*pstr)[0] == L'\t') + (*pstr)++; +} + + +//--------------------------------------------------------------------------- +// Config_TrimWhiteSpace +//--------------------------------------------------------------------------- + + +VOID Config_TrimWhiteSpace(WCHAR** pstr, ULONG* len) { + while (*len > 0 + && ((*pstr)[*len-1] == L' ' + || (*pstr)[*len-1] == L'\r' + //|| (*pstr)[*len-1] == L'\n' + || (*pstr)[*len-1] == L'\t')) + (*len)--; +} + + +//--------------------------------------------------------------------------- +// SbieDll_GetTagValue +//--------------------------------------------------------------------------- + + +WCHAR* SbieDll_GetTagValue(WCHAR* str, WCHAR** value, ULONG* len, WCHAR sep) { *value = NULL; *len = 0; - // skip whitespace - //while (*str == L' ' || *str == L'\t') str++; + Config_SkipWhiteSpace(&str); WCHAR* tmp; BOOLEAN alt; @@ -593,6 +636,8 @@ WCHAR* Config_GetTagValue(WCHAR* str, WCHAR** value, ULONG* len, WCHAR sep) if (!tmp) tmp = wcschr(str, L'\0'); *value = str; *len = (ULONG)(tmp - *value); + + Config_TrimWhiteSpace(value, len); } if (tmp && *tmp) tmp++; // skip separator @@ -601,35 +646,77 @@ WCHAR* Config_GetTagValue(WCHAR* str, WCHAR** value, ULONG* len, WCHAR sep) //--------------------------------------------------------------------------- -// Config_FindTagValue +// SbieDll_EnumTagValues //--------------------------------------------------------------------------- -BOOLEAN Config_FindTagValue(WCHAR* string, const WCHAR* tag_name, WCHAR* value, ULONG value_size, const WCHAR* deftext, WCHAR sep) +VOID SbieDll_EnumTagValues(WCHAR* string, SbieDll_TagEnumProc enumProc, void* param, WCHAR eq, WCHAR sep) { - ULONG tag_len = wcslen(tag_name); - WCHAR* temp = string; + WCHAR* str_ptr = string; WCHAR* tmp; WCHAR* name; ULONG len; WCHAR* found_value; ULONG found_len; - while(*temp) + while(*str_ptr) { - tmp = wcschr(temp, L'='); + Config_SkipWhiteSpace(&str_ptr); + + tmp = wcschr(str_ptr, eq); if (!tmp) break; - name = temp; - len = (ULONG)(tmp - temp); + name = str_ptr; + len = (ULONG)(tmp - str_ptr); + Config_TrimWhiteSpace(&name, &len); - temp = Config_GetTagValue(tmp + 1, &found_value, &found_len, sep); + str_ptr = SbieDll_GetTagValue(tmp + 1, &found_value, &found_len, sep); - if (tag_len == len && _wcsnicmp(tag_name, name, len) == 0) - { - wcsncpy_s(value, value_size / sizeof(WCHAR), found_value, found_len); - return TRUE; - } + if (!str_ptr || !enumProc(name, len, found_value, found_len, param)) + break; } +} - return FALSE; + +//--------------------------------------------------------------------------- +// SbieDll_FindTagValue +//--------------------------------------------------------------------------- + +typedef struct +{ + const WCHAR* tag_name; + ULONG tag_len; + WCHAR* value; + ULONG value_size; + BOOLEAN found; +} TagFindProcParam; + +static BOOLEAN Config_TagFindProc(WCHAR* name, ULONG name_len, WCHAR* value, ULONG value_len, void* param) +{ + TagFindProcParam* tagFindProcParam = (TagFindProcParam*)param; + if (tagFindProcParam->tag_len == name_len && _wcsnicmp(tagFindProcParam->tag_name, name, name_len) == 0) + { + wcsncpy_s(tagFindProcParam->value, tagFindProcParam->value_size / sizeof(WCHAR), value, value_len); + tagFindProcParam->found = TRUE; + return FALSE; // break + } + return TRUE; // continue +} + +BOOLEAN SbieDll_FindTagValue(WCHAR* string, const WCHAR* tag_name, WCHAR* value, ULONG value_size, WCHAR eq, WCHAR sep) +{ + if (!string) + return FALSE; + + TagFindProcParam tagFindProcParam = + { + tag_name, + wcslen(tag_name), + value, + value_size, + FALSE + }; + + SbieDll_EnumTagValues(string, &Config_TagFindProc, &tagFindProcParam, eq, sep); + + return tagFindProcParam.found; } \ No newline at end of file diff --git a/Sandboxie/core/dll/custom.c b/Sandboxie/core/dll/custom.c index 5d376af2..2202f9dc 100644 --- a/Sandboxie/core/dll/custom.c +++ b/Sandboxie/core/dll/custom.c @@ -849,21 +849,12 @@ _FX void AutoExec(void) if (! Dll_FirstProcessInBox) return; - buf_len = 4096 * sizeof(WCHAR); - buf1 = Dll_AllocTemp(buf_len); - - status = SbieApi_EnumProcess(Dll_BoxName, (ULONG *)buf1); - if (status != 0) { - Sbie_snwprintf(error_str, 16, L"%d [%08X]", -1, status); - SbieApi_Log(2206, error_str); - Dll_Free(buf1); - return; - } - // // query the values in the AutoExec setting // + buf_len = 4096 * sizeof(WCHAR); + buf1 = Dll_AllocTemp(buf_len); memzero(buf1, buf_len); buf2 = Dll_AllocTemp(buf_len); memzero(buf2, buf_len); diff --git a/Sandboxie/core/dll/dll.h b/Sandboxie/core/dll/dll.h index bc8d5992..67b17151 100644 --- a/Sandboxie/core/dll/dll.h +++ b/Sandboxie/core/dll/dll.h @@ -769,17 +769,10 @@ WCHAR* Config_MatchImageAndGetValue(WCHAR* value, const WCHAR* ImageName, ULONG* BOOLEAN Config_InitPatternList(const WCHAR* setting, LIST* list); -NTSTATUS Config_GetSettingsForImageName( - const WCHAR* setting, WCHAR* value, ULONG value_size, const WCHAR* deftext); - BOOLEAN Config_String2Bool(const WCHAR* value, BOOLEAN defval); BOOLEAN Config_GetSettingsForImageName_bool(const WCHAR* setting, BOOLEAN defval); -WCHAR* Config_GetTagValue(WCHAR* str, WCHAR** value, ULONG* len, WCHAR sep); - -BOOLEAN Config_FindTagValue(WCHAR* string, const WCHAR* name, WCHAR* value, ULONG value_size, const WCHAR* deftext, WCHAR sep); - //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/dll/dllhook.c b/Sandboxie/core/dll/dllhook.c index d70be133..c53ccb24 100644 --- a/Sandboxie/core/dll/dllhook.c +++ b/Sandboxie/core/dll/dllhook.c @@ -489,7 +489,6 @@ skip_e9_rewrite: ; // SbieDll_Hook_CheckChromeHook //--------------------------------------------------------------------------- #ifdef _WIN64 -ULONGLONG * SbieDll_findChromeTarget(unsigned char* addr); #define MAX_FUNC_SIZE 0x76 //Note any change to this function requires the same modification to the function in LowLevel: see init.c (findChromeTarget) ULONGLONG * SbieDll_findChromeTarget(unsigned char* addr) @@ -502,6 +501,12 @@ ULONGLONG * SbieDll_findChromeTarget(unsigned char* addr) //So far the offset has been positive between 0xa00000 and 0xb00000 bytes; //This may change in a future version of chrome for (i = 0; i < MAX_FUNC_SIZE; i++) { + // some chromium 90+ derivatives replace the function with a return 1 stub + // mov eax,1 + // ret + // int 3 + if (addr[i] == 0xB8 && addr[i + 5] == 0xC3 && addr[i + 6] == 0xCC) + return NULL; if ((*(USHORT *)&addr[i] == 0x8b48)) { if ((addr[i + 2] == 0x0d || addr[i + 2] == 0x05)) { LONG delta; diff --git a/Sandboxie/core/dll/dllmain.c b/Sandboxie/core/dll/dllmain.c index 68191eec..9d0977e1 100644 --- a/Sandboxie/core/dll/dllmain.c +++ b/Sandboxie/core/dll/dllmain.c @@ -571,6 +571,7 @@ _FX ULONG Dll_GetImageType(const WCHAR *ImageName) L"basilisk.exe", (WCHAR *)DLL_IMAGE_MOZILLA_FIREFOX, L"seamonkey.exe", (WCHAR *)DLL_IMAGE_MOZILLA_FIREFOX, L"k-meleon.exe", (WCHAR *)DLL_IMAGE_MOZILLA_FIREFOX, + L"librewolf.exe", (WCHAR *)DLL_IMAGE_MOZILLA_FIREFOX, L"wmplayer.exe", (WCHAR *)DLL_IMAGE_WINDOWS_MEDIA_PLAYER, L"winamp.exe", (WCHAR *)DLL_IMAGE_NULLSOFT_WINAMP, @@ -776,6 +777,7 @@ _FX ULONG_PTR Dll_Ordinal1( CloseHandle(heventProcessStart); } } + // // workaround for Program Compatibility Assistant (PCA), we have // to start a second instance of this process outside the PCA job, diff --git a/Sandboxie/core/dll/file.c b/Sandboxie/core/dll/file.c index 0235fd18..ac7ae4fc 100644 --- a/Sandboxie/core/dll/file.c +++ b/Sandboxie/core/dll/file.c @@ -80,9 +80,6 @@ #define FGN_REPARSED_CLOSED_PATH 0x0200 #define FGN_REPARSED_WRITE_PATH 0x0400 -#define PATH_IS_BOXED(f) (((f) & FGN_IS_BOXED_PATH) != 0) -#define PATH_NOT_BOXED(f) (((f) & FGN_IS_BOXED_PATH) == 0) - #ifndef _WIN64 #define WOW64_FS_REDIR @@ -477,7 +474,7 @@ _FX NTSTATUS File_GetName( } } - if (status == STATUS_BUFFER_OVERFLOW) { + if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MISMATCH) { name = Dll_GetTlsNameBuffer( TlsData, TRUE_NAME_BUFFER, length + objname_len); @@ -5845,7 +5842,6 @@ _FX NTSTATUS File_SetDisposition( WCHAR *DosPath; NTSTATUS status; ULONG mp_flags; - BOOLEAN is_direct_file; // // check if the specified path is an open or closed path @@ -5855,7 +5851,6 @@ _FX NTSTATUS File_SetDisposition( mp_flags = 0; DosPath = NULL; - is_direct_file = FALSE; Dll_PushTlsNameBuffer(TlsData); @@ -5867,6 +5862,12 @@ _FX NTSTATUS File_SetDisposition( status = File_GetName( FileHandle, &uni, &TruePath, &CopyPath, &FileFlags); + // + // fix-me: this is broken, instead of deleting files on close it deletes them instantly + // possible workarounds use __sys_NtSetInformationFile for files that reside only in the sandbox + // or implement proper deletion on handle close in File_NtCloseImpl + // + if (NT_SUCCESS(status)) { mp_flags = File_MatchPath(TruePath, &FileFlags); @@ -5874,22 +5875,7 @@ _FX NTSTATUS File_SetDisposition( if (PATH_IS_CLOSED(mp_flags)) status = STATUS_ACCESS_DENIED; - else if (PATH_IS_OPEN(mp_flags)) { - - is_direct_file = TRUE; // file is open - } - else { - - WCHAR* TmplPath = CopyPath; - - File_FindSnapshotPath(&TmplPath); // if file is in a snapshot this updates TmplPath to point to it - - if (PATH_IS_BOXED(FileFlags) && TmplPath == CopyPath) - is_direct_file = TRUE; // file is boxed and not located in a snapshot - } - - - if (!is_direct_file) { + else if (PATH_NOT_OPEN(mp_flags)) { status = File_DeleteDirectory(CopyPath, TRUE); @@ -5929,7 +5915,7 @@ _FX NTSTATUS File_SetDisposition( // handle the request appropriately // - if (is_direct_file) { + if (PATH_IS_OPEN(mp_flags)) { status = __sys_NtSetInformationFile( FileHandle, IoStatusBlock, @@ -6886,4 +6872,4 @@ _FX BOOLEAN DigitalGuardian_Init(HMODULE hModule) Dll_DigitalGuardian = hModule; return TRUE; -} +} \ No newline at end of file diff --git a/Sandboxie/core/dll/ipc.c b/Sandboxie/core/dll/ipc.c index 0d5ceb06..94f85e69 100644 --- a/Sandboxie/core/dll/ipc.c +++ b/Sandboxie/core/dll/ipc.c @@ -561,7 +561,7 @@ _FX NTSTATUS Ipc_GetName( status = Obj_GetObjectName(RootDirectory, name, &length); - if (status == STATUS_BUFFER_OVERFLOW) { + if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MISMATCH) { name = Dll_GetTlsNameBuffer( TlsData, TRUE_NAME_BUFFER, length + objname_len); diff --git a/Sandboxie/core/dll/key.c b/Sandboxie/core/dll/key.c index b4054376..48ab1836 100644 --- a/Sandboxie/core/dll/key.c +++ b/Sandboxie/core/dll/key.c @@ -21,6 +21,7 @@ #include "dll.h" +#include "obj.h" #include "core/svc/FileWire.h" #include "core/drv/api_defs.h" #include @@ -447,25 +448,23 @@ _FX NTSTATUS Key_GetName( name = Dll_GetTlsNameBuffer( TlsData, TRUE_NAME_BUFFER, length + objname_len); - status = __sys_NtQueryKey( - RootDirectory, KeyNameInformation, name, length, &length); + status = Obj_GetObjectName(RootDirectory, name, &length); - if (status == STATUS_BUFFER_OVERFLOW) { + if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MISMATCH) { name = Dll_GetTlsNameBuffer( TlsData, TRUE_NAME_BUFFER, length + objname_len); - status = __sys_NtQueryKey( - RootDirectory, KeyNameInformation, name, length, &length); + status = Obj_GetObjectName(RootDirectory, name, &length); } if (! NT_SUCCESS(status)) return status; - *OutTruePath = ((KEY_NAME_INFORMATION *)name)->Name; + *OutTruePath = ((OBJECT_NAME_INFORMATION *)name)->Name.Buffer; name = (*OutTruePath) - + ((KEY_NAME_INFORMATION *)name)->NameLength / sizeof(WCHAR); + + ((OBJECT_NAME_INFORMATION *)name)->Name.Length / sizeof(WCHAR); if (objname_len) { @@ -821,13 +820,16 @@ _FX NTSTATUS Key_FixNameWow64( Dll_Free(NewPtr); File_NtCloseImpl(handle); - // - // the result might contain \Wow6432Node\Wow6432Node, - // so strip one of them away - // + if (NT_SUCCESS(status)) { - if (Key_FixNameWow64_3(OutTruePath)) - Key_FixNameWow64_3(OutCopyPath); + // + // the result might contain \Wow6432Node\Wow6432Node, + // so strip one of them away + // + + if (Key_FixNameWow64_3(OutTruePath)) + Key_FixNameWow64_3(OutCopyPath); + } return status; } diff --git a/Sandboxie/core/dll/net.c b/Sandboxie/core/dll/net.c index 4e99016f..eccbd368 100644 --- a/Sandboxie/core/dll/net.c +++ b/Sandboxie/core/dll/net.c @@ -1,6 +1,6 @@ /* * Copyright 2004-2020 Sandboxie Holdings, LLC - * Copyright 2020 David Xanatos, xanasoft.com + * Copyright 2020-2021 David Xanatos, xanasoft.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -142,6 +142,9 @@ static int WSA_WSANSPIoctl( static int WSA_IsBlockedPort(const short *addr, int addrlen); +//static SOCKET WSA_WSASocketW( +// int af, int type, int protocol, void *lpProtocolInfo, unsigned int g, DWORD dwFlags); + static int WSA_connect(SOCKET s, const void *name, int namelen); static int WSA_WSAConnect( @@ -158,6 +161,9 @@ typedef int (*P_WSANSPIoctl)( void *lpvOutBuffer, DWORD cbOutBuffer, DWORD *lpcbBytesReturned, WSACOMPLETION *lpCompletion); +//typedef int (*P_WSASocketW)( +// int af, int type, int protocol, void *lpProtocolInfo, unsigned int g, DWORD dwFlags); + typedef int (*P_connect)(SOCKET s, const struct sockaddr *name, int namelen); typedef int (*P_WSAConnect)( @@ -169,6 +175,7 @@ typedef int (*P_WSAConnect)( static P_WSANSPIoctl __sys_WSANSPIoctl = NULL; +//static P_WSASocketW __sys_WSASocketW = NULL; static P_connect __sys_connect = NULL; static P_WSAConnect __sys_WSAConnect = NULL; @@ -246,6 +253,21 @@ _FX int WSA_IsBlockedPort(const short *addr, int addrlen) } +//--------------------------------------------------------------------------- +// WSA_WSASocketW +//--------------------------------------------------------------------------- + +//const BOOLEAN File_InternetBlockade_ManualBypass(); +// +//static SOCKET WSA_WSASocketW( +// int af, int type, int protocol, void* lpProtocolInfo, unsigned int g, DWORD dwFlags) +//{ +// // Note: mswsock.dll!WSPSocket is not exported +// +// return __sys_WSASocketW(af, type, protocol, lpProtocolInfo, g, dwFlags); +//} + + //--------------------------------------------------------------------------- // WSA_connect //--------------------------------------------------------------------------- @@ -436,6 +458,7 @@ _FX BOOLEAN WSA_Init(HMODULE module) P_WSANSPIoctl WSANSPIoctl; P_connect connect; P_WSAConnect WSAConnect; +// P_WSASocketW WSASocketW; WSANSPIoctl = (P_WSANSPIoctl)GetProcAddress(module, "WSANSPIoctl"); if (WSANSPIoctl) { @@ -450,6 +473,11 @@ _FX BOOLEAN WSA_Init(HMODULE module) if (! Dll_SkipHook(L"wsaconn")) { +// WSASocketW = (P_WSASocketW)GetProcAddress(module, "WSASocketW"); +// if (WSASocketW) { +// SBIEDLL_HOOK(WSA_,WSASocketW); +// } + connect = (P_connect)GetProcAddress(module, "connect"); if (connect) { SBIEDLL_HOOK(WSA_,connect); diff --git a/Sandboxie/core/dll/proc.c b/Sandboxie/core/dll/proc.c index d8f95138..6b8972b2 100644 --- a/Sandboxie/core/dll/proc.c +++ b/Sandboxie/core/dll/proc.c @@ -499,7 +499,9 @@ _FX BOOL Proc_UpdateProcThreadAttribute( // if(Dll_ImageType == DLL_IMAGE_GOOGLE_CHROME) if (Attribute == 0x0002000d) //PROC_THREAD_ATTRIBUTE_JOB_LIST { - if (!SbieApi_QueryConfBool(NULL, L"NoAddProcessToJob", FALSE)) + extern BOOLEAN SysInfo_CanUseJobs; + extern BOOLEAN SysInfo_UseSbieJob; + if (!SysInfo_CanUseJobs && SysInfo_UseSbieJob) return TRUE; } diff --git a/Sandboxie/core/dll/rpcrt.c b/Sandboxie/core/dll/rpcrt.c index bbde493b..98a361a6 100644 --- a/Sandboxie/core/dll/rpcrt.c +++ b/Sandboxie/core/dll/rpcrt.c @@ -420,7 +420,7 @@ _FX NTSTATUS RpcRt_FindModulePreset( WCHAR* test_value = NULL; ULONG test_len = 0; - found_value = Config_GetTagValue(found_value, &test_value, &test_len, L','); + found_value = SbieDll_GetTagValue(found_value, &test_value, &test_len, L','); if (!test_value || !found_value || !*found_value) { SbieApi_Log(2207, L"RpcPortBinding"); @@ -695,7 +695,7 @@ _FX ULONG RpcRt_RpcBindingFromStringBindingW( if (NT_SUCCESS(RpcRt_FindModulePreset(CallingModule, StringBinding, ModulePreset, sizeof(ModulePreset)))) { WCHAR tagValue[96]; - if (Config_FindTagValue(ModulePreset, L"Resolve", tagValue, sizeof(tagValue), NULL, L',')) + if (SbieDll_FindTagValue(ModulePreset, L"Resolve", tagValue, sizeof(tagValue), L'=', L',')) { WCHAR* pwszTempPortName = GetDynamicLpcPortName(tagValue); @@ -717,7 +717,7 @@ _FX ULONG RpcRt_RpcBindingFromStringBindingW( // else error let it fail } - if (Config_FindTagValue(ModulePreset, L"TimeOut", tagValue, sizeof(tagValue), NULL, L',')) + if (SbieDll_FindTagValue(ModulePreset, L"TimeOut", tagValue, sizeof(tagValue), L'=', L',')) use_RpcMgmtSetComTimeout = Config_String2Bool(tagValue, use_RpcMgmtSetComTimeout); } } @@ -841,17 +841,17 @@ _FX RPC_STATUS RpcRt_RpcBindingCreateW( WCHAR tagValue[96]; if (RPC_PROTSEQ_LRPC == Template->ProtocolSequence && !Template->StringEndpoint) { - if (Config_FindTagValue(ModulePreset, L"Resolve", tagValue, sizeof(tagValue), NULL, L',')) + if (SbieDll_FindTagValue(ModulePreset, L"Resolve", tagValue, sizeof(tagValue), L'=', L',')) { Template->StringEndpoint = GetDynamicLpcPortName(tagValue); } - /*else if (Config_FindTagValue(ModulePreset, L"IpcPort", tagValue, sizeof(tagValue), NULL, L',')) + /*else if (SbieDll_FindTagValue(ModulePreset, L"IpcPort", tagValue, sizeof(tagValue), L'=', L',')) { Template->StringEndpoint = (unsigned short*)...; }*/ } - if (Config_FindTagValue(ModulePreset, L"TimeOut", tagValue, sizeof(tagValue), NULL, L',')) + if (SbieDll_FindTagValue(ModulePreset, L"TimeOut", tagValue, sizeof(tagValue), L'=', L',')) use_RpcMgmtSetComTimeout = Config_String2Bool(tagValue, use_RpcMgmtSetComTimeout); } } diff --git a/Sandboxie/core/dll/sbiedll.h b/Sandboxie/core/dll/sbiedll.h index feaf0bbc..2a714f4c 100644 --- a/Sandboxie/core/dll/sbiedll.h +++ b/Sandboxie/core/dll/sbiedll.h @@ -206,8 +206,19 @@ SBIEDLL_EXPORT BOOLEAN SbieDll_GetStringForStringList(const WCHAR* string, cons SBIEDLL_EXPORT BOOLEAN SbieDll_CheckStringInList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting); //SBIEDLL_EXPORT BOOLEAN SbieDll_GetBoolForStringFromList(const WCHAR* string, const WCHAR* boxname, const WCHAR* setting, BOOLEAN def_found, BOOLEAN not_found); +SBIEDLL_EXPORT BOOLEAN SbieDll_GetSettingsForImageName( + const WCHAR* boxname, const WCHAR* image_name, const WCHAR* setting, WCHAR* value, ULONG value_size, const WCHAR* deftext); + +SBIEDLL_EXPORT BOOLEAN SbieDll_GetSettingsForImageName_bool( + const WCHAR* boxname, const WCHAR* image_name, const WCHAR* setting, BOOLEAN defval); + SBIEDLL_EXPORT BOOLEAN SbieDll_GetBorderColor(const WCHAR* box_name, COLORREF* color, BOOL* title, int* width); +SBIEDLL_EXPORT WCHAR* SbieDll_GetTagValue(WCHAR* str, WCHAR** value, ULONG* len, WCHAR sep); +typedef BOOLEAN (*SbieDll_TagEnumProc)(WCHAR* name, ULONG name_len, WCHAR* value, ULONG value_len, void* param); +SBIEDLL_EXPORT VOID SbieDll_EnumTagValues(WCHAR* string, SbieDll_TagEnumProc enumProc, void* param, WCHAR eq, WCHAR sep); +SBIEDLL_EXPORT BOOLEAN SbieDll_FindTagValue(WCHAR* string, const WCHAR* name, WCHAR* value, ULONG value_size, WCHAR eq, WCHAR sep); + //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/dll/sysinfo.c b/Sandboxie/core/dll/sysinfo.c index e15ec55f..15d8ef11 100644 --- a/Sandboxie/core/dll/sysinfo.c +++ b/Sandboxie/core/dll/sysinfo.c @@ -66,6 +66,10 @@ static NTSTATUS SysInfo_NtCreateJobObject( HANDLE *JobHandle, ACCESS_MASK DesiredAccess, OBJECT_ATTRIBUTES *ObjectAttributes); +static NTSTATUS SysInfo_NtOpenJobObject( + HANDLE *JobHandle, ACCESS_MASK DesiredAccess, + OBJECT_ATTRIBUTES *ObjectAttributes); + static NTSTATUS SysInfo_NtAssignProcessToJobObject( HANDLE JobHandle, HANDLE ProcessHandle); @@ -94,6 +98,7 @@ static P_SetLocaleInfo __sys_SetLocaleInfoW = NULL; static P_SetLocaleInfo __sys_SetLocaleInfoA = NULL; static P_NtCreateJobObject __sys_NtCreateJobObject = NULL; +static P_NtOpenJobObject __sys_NtOpenJobObject = NULL; static P_NtAssignProcessToJobObject __sys_NtAssignProcessToJobObject = NULL; static P_NtSetInformationJobObject __sys_NtSetInformationJobObject = NULL; @@ -107,6 +112,8 @@ static P_NtTraceEvent __sys_NtTraceEvent = NULL; static ULONG_PTR *SysInfo_JobCallbackData = NULL; +BOOLEAN SysInfo_UseSbieJob = TRUE; +BOOLEAN SysInfo_CanUseJobs = FALSE; //--------------------------------------------------------------------------- // SysInfo_Init @@ -122,10 +129,18 @@ _FX BOOLEAN SysInfo_Init(void) SBIEDLL_HOOK(SysInfo_,NtQuerySystemInformation); } + extern BOOLEAN Gui_OpenAllWinClasses; + SysInfo_UseSbieJob = !Gui_OpenAllWinClasses && !SbieApi_QueryConfBool(NULL, L"NoAddProcessToJob", FALSE); + + if (Dll_OsBuild >= 8400) + SysInfo_CanUseJobs = SbieApi_QueryConfBool(NULL, L"AllowBoxedJobs", FALSE); + SBIEDLL_HOOK(SysInfo_, NtCreateJobObject); - if (!SbieApi_QueryConfBool(NULL, L"NoAddProcessToJob", FALSE)) - { - SBIEDLL_HOOK(SysInfo_, NtAssignProcessToJobObject); + SBIEDLL_HOOK(SysInfo_, NtOpenJobObject); + if (SysInfo_UseSbieJob) { + if (!SysInfo_CanUseJobs) { + SBIEDLL_HOOK(SysInfo_, NtAssignProcessToJobObject); + } SBIEDLL_HOOK(SysInfo_, NtSetInformationJobObject); } @@ -375,6 +390,55 @@ _FX void *SysInfo_QueryProcesses(ULONG *out_len) } +//--------------------------------------------------------------------------- +// SysInfo_GetJobName +//--------------------------------------------------------------------------- + + +_FX NTSTATUS SysInfo_GetJobName(OBJECT_ATTRIBUTES* ObjectAttributes, WCHAR** OutCopyPath) +{ + THREAD_DATA *TlsData = Dll_GetTlsData(NULL); + + WCHAR *name; + ULONG objname_len; + WCHAR *objname_buf; + static volatile ULONG JobCounter = 0; + WCHAR dummy_name[MAX_PATH]; + + *OutCopyPath = NULL; + + if (ObjectAttributes && ObjectAttributes->ObjectName) { + objname_len = ObjectAttributes->ObjectName->Length & ~1; + objname_buf = ObjectAttributes->ObjectName->Buffer; + } else { + + InterlockedIncrement(&JobCounter); + Sbie_snwprintf(dummy_name, MAX_PATH, L"%s_DummyJob_%s_p%d_t%d_c%d", + SBIE, Dll_ImageName, GetCurrentProcessId(), GetCurrentThreadId(), JobCounter); + + objname_len = wcslen(dummy_name); + objname_buf = dummy_name; + } + + + name = Dll_GetTlsNameBuffer(TlsData, COPY_NAME_BUFFER, Dll_BoxIpcPathLen + objname_len); + + *OutCopyPath = name; + + wmemcpy(name, Dll_BoxIpcPath, Dll_BoxIpcPathLen); + name += Dll_BoxIpcPathLen; + + *name = L'\\'; + name++; + + wmemcpy(name, objname_buf, objname_len); + name += objname_len; + *name = L'\0'; + + return STATUS_SUCCESS; +} + + //--------------------------------------------------------------------------- // SysInfo_NtCreateJobObject //--------------------------------------------------------------------------- @@ -384,48 +448,56 @@ _FX NTSTATUS SysInfo_NtCreateJobObject( HANDLE *JobHandle, ACCESS_MASK DesiredAccess, OBJECT_ATTRIBUTES *ObjectAttributes) { - static volatile ULONG _JobCounter = 0; + NTSTATUS status; OBJECT_ATTRIBUTES objattrs; UNICODE_STRING objname; - WCHAR *jobname; - ULONG jobname_len; - NTSTATUS status; + WCHAR* CopyPath; // // the driver requires us to specify a sandboxed path name to a // job object, and to not request some specific rights // - if (!SbieApi_QueryConfBool(NULL, L"NoAddProcessToJob", FALSE)) + if(!SysInfo_CanUseJobs && SysInfo_UseSbieJob) DesiredAccess &= ~(JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_TERMINATE); - jobname_len = Dll_BoxIpcPathLen + wcslen(Dll_ImageName) + 64; - jobname = Dll_AllocTemp(jobname_len * sizeof(WCHAR)); - - while (1) { - - InterlockedIncrement(&_JobCounter); - Sbie_snwprintf(jobname, jobname_len, L"%s\\%s_DummyJob_%s_%d", - Dll_BoxIpcPath, SBIE, Dll_ImageName, _JobCounter); - RtlInitUnicodeString(&objname, jobname); - - InitializeObjectAttributes(&objattrs, - &objname, OBJECT_ATTRIBUTES_ATTRIBUTES, NULL, Secure_EveryoneSD); - - status = __sys_NtCreateJobObject( - JobHandle, DesiredAccess, &objattrs); - - // - // we always start each process with _JobCounter = 0 so we have to - // account for the case where a dummy job object was already created - // by another process, and not fail the request - // - - if (status != STATUS_OBJECT_NAME_COLLISION) - break; + if (NT_SUCCESS(SysInfo_GetJobName(ObjectAttributes, &CopyPath))) { + RtlInitUnicodeString(&objname, CopyPath); + InitializeObjectAttributes(&objattrs, &objname, OBJECT_ATTRIBUTES_ATTRIBUTES, NULL, Secure_EveryoneSD); + ObjectAttributes = &objattrs; } - Dll_Free(jobname); + status = __sys_NtCreateJobObject(JobHandle, DesiredAccess, ObjectAttributes); + + return status; +} + + +//--------------------------------------------------------------------------- +// SysInfo_NtCreateJobObject +//--------------------------------------------------------------------------- + + +_FX NTSTATUS SysInfo_NtOpenJobObject( + HANDLE* JobHandle, ACCESS_MASK DesiredAccess, + OBJECT_ATTRIBUTES* ObjectAttributes) +{ + NTSTATUS status; + OBJECT_ATTRIBUTES objattrs; + UNICODE_STRING objname; + WCHAR* CopyPath; + + if(!SysInfo_CanUseJobs && SysInfo_UseSbieJob) + DesiredAccess &= ~(JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_TERMINATE); + + if (NT_SUCCESS(SysInfo_GetJobName(ObjectAttributes, &CopyPath))) { + RtlInitUnicodeString(&objname, CopyPath); + InitializeObjectAttributes(&objattrs, &objname, OBJECT_ATTRIBUTES_ATTRIBUTES, NULL, Secure_EveryoneSD); + ObjectAttributes = &objattrs; + } + + status = __sys_NtOpenJobObject(JobHandle, DesiredAccess, ObjectAttributes); + return status; } @@ -461,14 +533,27 @@ _FX NTSTATUS SysInfo_NtSetInformationJobObject( HANDLE JobHandle, JOBOBJECTINFOCLASS JobObjectInformationClass, void *JobObjectInformtion, ULONG JobObjectInformtionLength) { + // + // Since windows 8 we can have nested jobs i.e. we can have all sandboxed processes + // be part of the box isoaltion job and also of for example a chrome sandbox job. + // Howeever we booth jobs can not specify UIRestrictions since our own job allready + // specified those restrictions, we dont allow a boxed process to spesify its own. + // + + if (SysInfo_CanUseJobs && JobObjectInformationClass == JobObjectBasicUIRestrictions) + return STATUS_SUCCESS; + NTSTATUS status = __sys_NtSetInformationJobObject( JobHandle, JobObjectInformationClass, JobObjectInformtion, JobObjectInformtionLength); + if(SysInfo_CanUseJobs) + return status; + if (NT_SUCCESS(status) && JobObjectInformationClass == JobObjectAssociateCompletionPortInformation) { - + SysInfo_JobCallbackData_Set(NULL, JobObjectInformtion); } diff --git a/Sandboxie/core/dll/userenv.c b/Sandboxie/core/dll/userenv.c index 4e79a966..d42dd996 100644 --- a/Sandboxie/core/dll/userenv.c +++ b/Sandboxie/core/dll/userenv.c @@ -81,8 +81,7 @@ _FX BOOLEAN UserEnv_InitVer(HMODULE module) void* GetVersionExA; WCHAR str[32]; - NTSTATUS status = Config_GetSettingsForImageName(L"OverrideOsBuild", str, sizeof(str), NULL); - if (NT_SUCCESS(status)) + if (SbieDll_GetSettingsForImageName(NULL, Dll_ImageName, L"OverrideOsBuild", str, sizeof(str), NULL)) UserEnv_dwBuildNumber = _wtoi(str); if (UserEnv_dwBuildNumber == 0 && Dll_OsBuild < 9600) diff --git a/Sandboxie/core/drv/SboxDrv.vcxproj b/Sandboxie/core/drv/SboxDrv.vcxproj index d5fd81b2..c4b633f8 100644 --- a/Sandboxie/core/drv/SboxDrv.vcxproj +++ b/Sandboxie/core/drv/SboxDrv.vcxproj @@ -113,7 +113,7 @@ Native - ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;%(AdditionalDependencies) + ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;Fwpkclnt.lib;%(AdditionalDependencies) DriverEntry @@ -145,7 +145,7 @@ Native - ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;%(AdditionalDependencies) + ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;Fwpkclnt.lib;%(AdditionalDependencies) DriverEntry @@ -185,7 +185,7 @@ Native - ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;ntstrsafe.lib;%(AdditionalDependencies) + ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;Fwpkclnt.lib;ntstrsafe.lib;%(AdditionalDependencies) DriverEntry @@ -215,7 +215,7 @@ Native - ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;ntstrsafe.lib;%(AdditionalDependencies) + ntoskrnl.lib;hal.lib;wmilib.lib;fltmgr.lib;Ksecdd.lib;Fwpkclnt.lib;ntstrsafe.lib;%(AdditionalDependencies) DriverEntry @@ -253,12 +253,24 @@ true true + + true + true + true + true + true true true true + + true + true + true + true + true true @@ -392,6 +404,7 @@ + @@ -424,6 +437,12 @@ true true + + true + true + true + true + true true @@ -436,6 +455,12 @@ true true + + true + true + true + true + true true diff --git a/Sandboxie/core/drv/SboxDrv.vcxproj.filters b/Sandboxie/core/drv/SboxDrv.vcxproj.filters index 20809b06..72ef216b 100644 --- a/Sandboxie/core/drv/SboxDrv.vcxproj.filters +++ b/Sandboxie/core/drv/SboxDrv.vcxproj.filters @@ -124,6 +124,13 @@ file + + common + + + common + + @@ -184,6 +191,12 @@ common + + common + + + common + diff --git a/Sandboxie/core/drv/api.c b/Sandboxie/core/drv/api.c index 56fa39c0..dacdd056 100644 --- a/Sandboxie/core/drv/api.c +++ b/Sandboxie/core/drv/api.c @@ -88,7 +88,7 @@ static NTSTATUS Api_ProcessExemptionControl(PROCESS *proc, ULONG64 *parms); static P_Api_Function *Api_Functions = NULL; -static DEVICE_OBJECT *Api_DeviceObject = NULL; +DEVICE_OBJECT *Api_DeviceObject = NULL; static FAST_IO_DISPATCH *Api_FastIoDispatch = NULL; @@ -1072,6 +1072,11 @@ _FX NTSTATUS Api_SetServicePort(PROCESS *proc, ULONG64 *parms) status = STATUS_SUCCESS; } + if (NT_SUCCESS(status) && !MyIsCallerSigned()) { + + status = STATUS_INVALID_SIGNATURE; + } + // // take a reference on the specified LPC port object // diff --git a/Sandboxie/core/drv/conf.c b/Sandboxie/core/drv/conf.c index befcafc3..18f7d167 100644 --- a/Sandboxie/core/drv/conf.c +++ b/Sandboxie/core/drv/conf.c @@ -35,12 +35,16 @@ // Defines //--------------------------------------------------------------------------- +//#define USE_CONF_MAP #define CONF_LINE_LEN 2000 // keep in sync with +#ifdef USE_CONF_MAP +#define CONF_MAX_LINES 100000 +#else #define CONF_MAX_LINES 30000 // SbieCtrl/SbieIni.cpp +#endif #define CONF_TMPL_LINE_BASE 0x01000000 - //--------------------------------------------------------------------------- // Structures //--------------------------------------------------------------------------- @@ -49,7 +53,11 @@ typedef struct _CONF_DATA { POOL *pool; +#ifdef USE_CONF_MAP + HASH_MAP section_map; +#else LIST sections; // CONF_SECTION +#endif BOOLEAN home; // TRUE if configuration read from Driver_Home_Path ULONG encoding; // 0 - unicode, 1 - utf8, 2 - unicode (byte swaped) volatile ULONG use_count; @@ -59,7 +67,9 @@ typedef struct _CONF_DATA { typedef struct _CONF_SECTION { +#ifndef USE_CONF_MAP LIST_ELEM list_elem; +#endif WCHAR *name; LIST settings; // CONF_SETTING BOOLEAN from_template; @@ -249,7 +259,14 @@ _FX NTSTATUS Conf_Read(ULONG session_id) else { data.pool = pool; +#ifdef USE_CONF_MAP + map_init(&data.section_map, data.pool); + data.section_map.func_key_size = &map_wcssize; + data.section_map.func_match_key = &map_wcsimatch; + map_resize(&data.section_map, 16); // prepare some buckets for better performance +#else List_Init(&data.sections); +#endif data.home = path_home; data.use_count = 0; @@ -429,13 +446,16 @@ _FX NTSTATUS Conf_Read_Sections( // // find an existing section by that name or create a new one // - +#ifdef USE_CONF_MAP + section = map_get(&data->section_map, &line[1]); +#else section = List_Head(&data->sections); while (section) { if (_wcsicmp(section->name, &line[1]) == 0) break; section = List_Next(section); } +#endif if (! section) { @@ -458,7 +478,11 @@ _FX NTSTATUS Conf_Read_Sections( List_Init(§ion->settings); +#ifdef USE_CONF_MAP + map_insert(&data->section_map, section->name, section, 0); +#else List_Insert_After(&data->sections, NULL, section); +#endif } // read settings for this section @@ -663,10 +687,17 @@ _FX NTSTATUS Conf_Merge_Templates(CONF_DATA *data, ULONG session_id) // scan sections to find a sandbox section // +#ifdef USE_CONF_MAP + map_iter_t iter = map_iter(); + while (map_next(&data->section_map, &iter)) { + + sandbox = iter.value; +#else sandbox = List_Head(&data->sections); while (sandbox) { CONF_SECTION *next_sandbox = List_Next(sandbox); +#endif // // if we found the global section, handle it @@ -679,7 +710,9 @@ _FX NTSTATUS Conf_Merge_Templates(CONF_DATA *data, ULONG session_id) if (! NT_SUCCESS(status)) return status; +#ifndef USE_CONF_MAP sandbox = next_sandbox; +#endif continue; } @@ -690,7 +723,9 @@ _FX NTSTATUS Conf_Merge_Templates(CONF_DATA *data, ULONG session_id) if (_wcsnicmp(sandbox->name, Conf_Template_, 9) == 0 || _wcsnicmp(sandbox->name, Conf_UserSettings_, 13) == 0) { +#ifndef USE_CONF_MAP sandbox = next_sandbox; +#endif continue; } @@ -731,11 +766,13 @@ _FX NTSTATUS Conf_Merge_Templates(CONF_DATA *data, ULONG session_id) setting = List_Head(&sandbox->settings); } +#ifndef USE_CONF_MAP // // advance to next section // sandbox = next_sandbox; +#endif } return STATUS_SUCCESS; @@ -772,10 +809,17 @@ _FX NTSTATUS Conf_Merge_Global( // scan sections to find a sandbox section // +#ifdef USE_CONF_MAP + map_iter_t iter = map_iter(); + while (map_next(&data->section_map, &iter)) { + + sandbox = iter.value; +#else sandbox = List_Head(&data->sections); while (sandbox) { CONF_SECTION *next_sandbox = List_Next(sandbox); +#endif // // skip the global section @@ -783,7 +827,9 @@ _FX NTSTATUS Conf_Merge_Global( if (_wcsicmp(sandbox->name, Conf_GlobalSettings) == 0) { +#ifndef USE_CONF_MAP sandbox = next_sandbox; +#endif continue; } @@ -794,7 +840,9 @@ _FX NTSTATUS Conf_Merge_Global( if (_wcsnicmp(sandbox->name, Conf_Template_, 9) == 0 || _wcsnicmp(sandbox->name, Conf_UserSettings_, 13) == 0) { +#ifndef USE_CONF_MAP sandbox = next_sandbox; +#endif continue; } @@ -808,11 +856,13 @@ _FX NTSTATUS Conf_Merge_Global( if (! NT_SUCCESS(status)) return status; +#ifndef USE_CONF_MAP // // advance to next section // sandbox = next_sandbox; +#endif } // @@ -839,8 +889,16 @@ _FX NTSTATUS Conf_Merge_Template( // scan for a matching template section // +#ifdef USE_CONF_MAP + CONF_SECTION *tmpl = NULL; + + map_iter_t iter = map_iter(); + while (map_next(&data->section_map, &iter)) { + tmpl = iter.value; +#else CONF_SECTION *tmpl = List_Head(&data->sections); while (tmpl) { +#endif if (wcslen(tmpl->name) >= 10 && _wcsnicmp(tmpl->name, Conf_Template_, 9) == 0 && @@ -849,7 +907,11 @@ _FX NTSTATUS Conf_Merge_Template( break; } +#ifndef USE_CONF_MAP tmpl = List_Next(tmpl); +#else + tmpl = NULL; +#endif } // @@ -910,16 +972,19 @@ _FX const WCHAR *Conf_Get_Helper( value = NULL; +#ifdef USE_CONF_MAP + section = map_get(&Conf_Data.section_map, section_name); +#else section = List_Head(&Conf_Data.sections); while (section) { //DbgPrint(" Examining section at %X name %S (looking for %S)\n", section, section->name, section_name); - if (_wcsicmp(section->name, section_name) == 0) { - if (skip_tmpl && section->from_template) - section = NULL; + if (_wcsicmp(section->name, section_name) == 0) break; - } section = List_Next(section); } +#endif + if (skip_tmpl && section && section->from_template) + section = NULL; if (section) setting = List_Head(§ion->settings); @@ -958,21 +1023,36 @@ _FX const WCHAR *Conf_Get_Section_Name(ULONG index, BOOLEAN skip_tmpl) value = NULL; +#ifdef USE_CONF_MAP + map_iter_t iter = map_iter(); + while (map_next(&Conf_Data.section_map, &iter)) { + section = iter.value; +#else section = List_Head(&Conf_Data.sections); while (section) { CONF_SECTION *next_section = List_Next(section); - - if (_wcsicmp(section->name, Conf_GlobalSettings) == 0) +#endif + if (_wcsicmp(section->name, Conf_GlobalSettings) == 0) { +#ifndef USE_CONF_MAP section = next_section; - else if (skip_tmpl && section->from_template) +#endif + continue; + } + if (skip_tmpl && section->from_template) { +#ifndef USE_CONF_MAP section = next_section; - else if (index == 0) { +#endif + continue; + } + if (index == 0) { value = section->name; break; - } else { - --index; - section = next_section; } + + --index; +#ifndef USE_CONF_MAP + section = next_section; +#endif } return value; @@ -994,15 +1074,18 @@ _FX const WCHAR *Conf_Get_Setting_Name( value = NULL; +#ifdef USE_CONF_MAP + section = map_get(&Conf_Data.section_map, section_name); +#else section = List_Head(&Conf_Data.sections); while (section) { - if (_wcsicmp(section->name, section_name) == 0) { - if (skip_tmpl && section->from_template) - section = NULL; + if (_wcsicmp(section->name, section_name) == 0) break; - } section = List_Next(section); } +#endif + if (skip_tmpl && section && section->from_template) + section = NULL; if (section) setting = List_Head(§ion->settings); @@ -1193,12 +1276,16 @@ _FX NTSTATUS Conf_IsValidBox(const WCHAR *section_name) KeRaiseIrql(APC_LEVEL, &irql); ExAcquireResourceSharedLite(Conf_Lock, TRUE); +#ifdef USE_CONF_MAP + section = map_get(&Conf_Data.section_map, section_name); +#else section = List_Head(&Conf_Data.sections); while (section) { if (_wcsicmp(section->name, section_name) == 0) break; section = List_Next(section); } +#endif if (! section) status = STATUS_OBJECT_NAME_NOT_FOUND; @@ -1247,7 +1334,14 @@ _FX NTSTATUS Conf_Api_Reload(PROCESS *proc, ULONG64 *parms) pool = Conf_Data.pool; Conf_Data.pool = NULL; +#ifdef USE_CONF_MAP + map_init(&Conf_Data.section_map, Conf_Data.pool); + Conf_Data.section_map.func_key_size = &map_wcssize; + Conf_Data.section_map.func_match_key = &map_wcsimatch; + map_resize(&Conf_Data.section_map, 16); // prepare some buckets for better performance +#else List_Init(&Conf_Data.sections); +#endif Conf_Data.home = FALSE; Conf_Data.encoding = 0; @@ -1409,7 +1503,13 @@ release_and_return: _FX BOOLEAN Conf_Init(void) { Conf_Data.pool = NULL; +#ifdef USE_CONF_MAP + map_init(&Conf_Data.section_map, NULL); + Conf_Data.section_map.func_key_size = &map_wcssize; + Conf_Data.section_map.func_match_key = &map_wcsimatch; +#else List_Init(&Conf_Data.sections); +#endif Conf_Data.home = FALSE; Conf_Data.encoding = 0; diff --git a/Sandboxie/core/drv/driver.c b/Sandboxie/core/drv/driver.c index e91cdab9..b6f0c6f3 100644 --- a/Sandboxie/core/drv/driver.c +++ b/Sandboxie/core/drv/driver.c @@ -718,7 +718,11 @@ _FX NTSTATUS Driver_Api_Unload(PROCESS *proc, ULONG64 *parms) ExAcquireResourceExclusiveLite(Process_ListLock, TRUE); ok = FALSE; +#ifdef USE_PROCESS_MAP + if (Process_Map.nnodes == 0) { +#else if (! List_Count(&Process_List)) { +#endif if (Api_Disable()) ok = TRUE; } diff --git a/Sandboxie/core/drv/driver.h b/Sandboxie/core/drv/driver.h index a3015fb4..62865d90 100644 --- a/Sandboxie/core/drv/driver.h +++ b/Sandboxie/core/drv/driver.h @@ -37,6 +37,7 @@ #include "common/defines.h" #include "common/list.h" +#include "common/map.h" #include "common/pool.h" #include "common/ntproto.h" #include "log.h" @@ -66,6 +67,8 @@ #define TRACE_DENY 2 #define TRACE_IGNORE 4 +#define USE_PROCESS_MAP + //new FILE_INFORMATION_CLASS type not defined in current wdm.h used in windows 10 FCU #define SB_FileRenameInformationEx 65 //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/drv/includes.c b/Sandboxie/core/drv/includes.c index 6e28dc12..00271ebf 100644 --- a/Sandboxie/core/drv/includes.c +++ b/Sandboxie/core/drv/includes.c @@ -55,6 +55,10 @@ extern const ULONG tzuk; #include "common/pattern.c" #undef Pool_Alloc +/* map */ + +#include "common/map.c" + /* CRC */ //#define CRC_WITH_ADLERTZUK64 diff --git a/Sandboxie/core/drv/ipc.c b/Sandboxie/core/drv/ipc.c index a8d0092f..ca2e05d9 100644 --- a/Sandboxie/core/drv/ipc.c +++ b/Sandboxie/core/drv/ipc.c @@ -995,7 +995,7 @@ _FX NTSTATUS Ipc_CheckPortObject( _FX NTSTATUS Ipc_CheckJobObject( - PROCESS *proc, void *Object, UNICODE_STRING *Name, + PROCESS* proc, void* Object, UNICODE_STRING* Name, ACCESS_MASK GrantedAccess) { // @@ -1006,9 +1006,10 @@ _FX NTSTATUS Ipc_CheckJobObject( // is inside the sandbox // - if (!Conf_Get_Boolean(proc->box->name, L"NoAddProcessToJob", 0, FALSE)) - if (GrantedAccess & (JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_TERMINATE)) - return STATUS_ACCESS_DENIED; + if (!proc->can_use_jobs) { + if (GrantedAccess & (JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_TERMINATE)) + return STATUS_ACCESS_DENIED; + } if (! Name->Length) return STATUS_ACCESS_DENIED; diff --git a/Sandboxie/core/drv/ipc_port.c b/Sandboxie/core/drv/ipc_port.c index fd19b662..2226ddd8 100644 --- a/Sandboxie/core/drv/ipc_port.c +++ b/Sandboxie/core/drv/ipc_port.c @@ -599,8 +599,8 @@ _FX NTSTATUS Ipc_Api_OpenDynamicPort(PROCESS* proc, ULONG64* parms) if (proc) // is caller sandboxed? return STATUS_ACCESS_DENIED; - //if (PsGetCurrentProcessId() != Api_ServiceProcessId) - // return STATUS_ACCESS_DENIED; + if (PsGetCurrentProcessId() != Api_ServiceProcessId) + return STATUS_ACCESS_DENIED; if (pArgs->port_name.val == NULL) return STATUS_INVALID_PARAMETER; diff --git a/Sandboxie/core/drv/key_flt.c b/Sandboxie/core/drv/key_flt.c index 8056ca10..60273307 100644 --- a/Sandboxie/core/drv/key_flt.c +++ b/Sandboxie/core/drv/key_flt.c @@ -190,11 +190,13 @@ _FX NTSTATUS Key_Callback(void *Context, void *Arg1, void *Arg2) // // check if the caller is sandboxed before proceeding // + if (Driver_OsBuild < DRIVER_BUILD_WINDOWS_10_CU) + { + proc = Process_Find(NULL, NULL); + if (proc == PROCESS_TERMINATED) + return STATUS_PROCESS_IS_TERMINATING; + } - proc = Process_Find(NULL, NULL); - if (proc == PROCESS_TERMINATED) - return STATUS_PROCESS_IS_TERMINATING; - Info = (REG_OPEN_CREATE_KEY_INFORMATION_VISTA *)Arg2; // HACK ALERT! If you click a link in a Word doc, it will try to start an embedded IE, which cannot be forced into Sandboxie. diff --git a/Sandboxie/core/drv/mem.c b/Sandboxie/core/drv/mem.c index 2d3b5552..c68de57d 100644 --- a/Sandboxie/core/drv/mem.c +++ b/Sandboxie/core/drv/mem.c @@ -170,4 +170,5 @@ int __cdecl memcmp( { return (RtlCompareMemory(_Buf1, _Buf2, _Size) == _Size) ? 0 : 1; } -#endif \ No newline at end of file +#endif + diff --git a/Sandboxie/core/drv/mem.h b/Sandboxie/core/drv/mem.h index 0e3fb276..c50e1b7e 100644 --- a/Sandboxie/core/drv/mem.h +++ b/Sandboxie/core/drv/mem.h @@ -71,7 +71,10 @@ BOOLEAN Mem_GetLockResource(PERESOURCE *ppResource, BOOLEAN InitMsg); void Mem_FreeLockResource(PERESOURCE *ppResource); + //--------------------------------------------------------------------------- + + #endif // _MY_MEM_H diff --git a/Sandboxie/core/drv/process.c b/Sandboxie/core/drv/process.c index f5461a90..cfc13b33 100644 --- a/Sandboxie/core/drv/process.c +++ b/Sandboxie/core/drv/process.c @@ -85,8 +85,13 @@ static void Process_NotifyImage( //--------------------------------------------------------------------------- +#ifdef USE_PROCESS_MAP +HASH_MAP Process_Map; +HASH_MAP Process_MapDfp; +#else LIST Process_List; LIST Process_ListDfp; +#endif PERESOURCE Process_ListLock = NULL; static BOOLEAN Process_NotifyImageInstalled = FALSE; @@ -110,8 +115,16 @@ _FX BOOLEAN Process_Init(void) { NTSTATUS status; +#ifdef USE_PROCESS_MAP + map_init(&Process_Map, Driver_Pool); + map_resize(&Process_Map, 128); // prepare some buckets for better performance + + map_init(&Process_MapDfp, Driver_Pool); + map_resize(&Process_MapDfp, 128); // prepare some buckets for better performance +#else List_Init(&Process_List); List_Init(&Process_ListDfp); +#endif if (! Mem_GetLockResource(&Process_ListLock, TRUE)) return FALSE; @@ -421,46 +434,41 @@ _FX PROCESS *Process_Find(HANDLE ProcessId, KIRQL *out_irql) KeRaiseIrql(APC_LEVEL, &irql); ExAcquireResourceSharedLite(Process_ListLock, TRUE); +#ifdef USE_PROCESS_MAP + proc = map_get(&Process_Map, ProcessId); + if (proc) { +#else proc = List_Head(&Process_List); + while (proc) { + if (proc->pid == ProcessId) { +#endif - if (check_terminated) { + if (check_terminated && proc->terminated) { + // + // ntdll is going to call NtRaiseHardError before + // aborting, so disable hard errors to avoid the + // pop up box from csrss + // - while (proc) { - if (proc->pid == ProcessId) { - - if (proc->terminated) { - // - // ntdll is going to call NtRaiseHardError before - // aborting, so disable hard errors to avoid the - // pop up box from csrss - // - - if (proc->terminated != 9) { - proc->terminated = 9; - PsSetThreadHardErrorsAreDisabled( - (PETHREAD)KeGetCurrentThread(), TRUE); - } - // - // signal that the caller should return status - // STATUS_PROCESS_IS_TERMINATING - // (see Api_FastIo_DEVICE_CONTROL for example) - // - proc = PROCESS_TERMINATED; + if (proc->terminated != 9) { + proc->terminated = 9; + PsSetThreadHardErrorsAreDisabled( + (PETHREAD)KeGetCurrentThread(), TRUE); } - - break; + // + // signal that the caller should return status + // STATUS_PROCESS_IS_TERMINATING + // (see Api_FastIo_DEVICE_CONTROL for example) + // + proc = PROCESS_TERMINATED; } - proc = List_Next(proc); +#ifndef USE_PROCESS_MAP + break; } - } else { - - while (proc) { - if (proc->pid == ProcessId) - break; - proc = List_Next(proc); - } + proc = List_Next(proc); +#endif } if (out_irql) { @@ -530,7 +538,11 @@ _FX void Process_CreateTerminated(HANDLE ProcessId, ULONG SessionId) KeRaiseIrql(APC_LEVEL, &irql); ExAcquireResourceExclusiveLite(Process_ListLock, TRUE); +#ifdef USE_PROCESS_MAP + map_insert(&Process_Map, ProcessId, proc, 0); +#else List_Insert_After(&Process_List, NULL, proc); +#endif ExReleaseResourceLite(Process_ListLock); KeLowerIrql(irql); @@ -719,7 +731,11 @@ _FX PROCESS *Process_Create( KeRaiseIrql(APC_LEVEL, &irql); ExAcquireResourceExclusiveLite(Process_ListLock, TRUE); +#ifdef USE_PROCESS_MAP + map_insert(&Process_Map, ProcessId, proc, 0); +#else List_Insert_After(&Process_List, NULL, proc); +#endif *out_irql = irql; @@ -1071,8 +1087,19 @@ _FX void Process_NotifyProcess_Create( if (new_proc->open_all_win_classes || Conf_Get_Boolean(new_proc->box->name, L"NoAddProcessToJob", 0, FALSE)) { + new_proc->can_use_jobs = TRUE; add_process_to_job = FALSE; } + else if (Driver_OsVersion >= DRIVER_WINDOWS_8) { + + // + // on windows 8 and later we can have nested jobs so asigning a + // boxed job to a process will not interfear with the job assigned by SbieSvc + // + + new_proc->can_use_jobs = Conf_Get_Boolean(new_proc->box->name, L"AllowBoxedJobs", 0, FALSE); + } + // // on Windows Vista, a forced process may start inside a @@ -1148,6 +1175,9 @@ _FX void Process_Delete(HANDLE ProcessId) KeRaiseIrql(APC_LEVEL, &irql); ExAcquireResourceExclusiveLite(Process_ListLock, TRUE); +#ifdef USE_PROCESS_MAP + proc = map_remove(&Process_Map, ProcessId); +#else proc = List_Head(&Process_List); while (proc) { if (proc->pid == ProcessId) { @@ -1156,6 +1186,7 @@ _FX void Process_Delete(HANDLE ProcessId) } proc = (PROCESS *)List_Next(proc); } +#endif Process_DfpDelete(ProcessId); @@ -1310,7 +1341,7 @@ _FX void Process_NotifyImage( proc->terminated = TRUE; proc->reason = (!fail) ? -1 : 0; - Process_CancelProcess(proc); + Process_TerminateProcess(proc); } //DbgPrint("IMAGE LOADED, PROCESS INITIALIZATION %d COMPLETE %d\n", proc->pid, ok); diff --git a/Sandboxie/core/drv/process.h b/Sandboxie/core/drv/process.h index 267b0666..88f9c508 100644 --- a/Sandboxie/core/drv/process.h +++ b/Sandboxie/core/drv/process.h @@ -51,7 +51,9 @@ struct _PROCESS { // changes to the linked list of PROCESS blocks are synchronized by // an exclusive lock on Process_ListLock +#ifndef USE_PROCESS_MAP LIST_ELEM list_elem; +#endif // process id @@ -95,7 +97,11 @@ struct _PROCESS { PERESOURCE threads_lock; +#ifdef USE_PROCESS_MAP + HASH_MAP thread_map; +#else LIST threads; +#endif // flags @@ -120,6 +126,7 @@ struct _PROCESS { BOOLEAN change_notify_token_flag; BOOLEAN in_pca_job; + BOOLEAN can_use_jobs; UCHAR create_console_flag; @@ -263,6 +270,18 @@ const WCHAR *Process_MatchPath( BOOLEAN *is_open, BOOLEAN *is_closed); +// Process_GetConf: retrives a configuration data value for a given process +// use with Conf_AdjustUseCount to make sure the returned pointer is valid + +const WCHAR* Process_GetConf(PROCESS* proc, const WCHAR* setting); + + +// Process_GetConf_bool: parses a y/n setting. this function does not +// have to be protected with Conf_AdjustUseCount + +BOOLEAN Process_GetConf_bool(PROCESS* proc, const WCHAR* setting, BOOLEAN def); + + // Build a standard entry for hooks. The standard entry calls // Process_Find(NULL, NULL). If non-zero (this includes -1 for // PROCESS_TERMINATED), the entry jumps to NewProc, where @@ -282,10 +301,6 @@ void Process_DisableHookEntry(ULONG_PTR HookEntry); PROCESS *Process_GetCurrent(void); -// Check for use of multiple sandboxes at once - -BOOLEAN Process_CheckTooManyBoxes(const BOX *box); - // Returns ProcessName.exe for idProcess, allocated from the specified pool. // On return, *out_buf points to a UNICODE_STRING structure which points @@ -362,11 +377,17 @@ void Process_LogMessage(PROCESS *proc, ULONG msgid); //void Process_TrackProcessLimit(PROCESS *proc); +// Terminate process + +BOOLEAN Process_TerminateProcess(PROCESS *proc); // Cancel process through SbieSvc -void Process_CancelProcess(PROCESS *proc); +BOOLEAN Process_CancelProcess(PROCESS *proc); +// Terminate a process using a helper thread + +BOOLEAN Process_ScheduleKill(PROCESS *proc); // Check if process is running within a // Program Compatibility Assistant (PCA) job @@ -416,8 +437,13 @@ NTSTATUS Process_Api_Enum(PROCESS *proc, ULONG64 *parms); //--------------------------------------------------------------------------- +#ifdef USE_PROCESS_MAP +extern HASH_MAP Process_Map; +extern HASH_MAP Process_MapDfp; +#else extern LIST Process_List; extern LIST Process_ListDfp; +#endif extern PERESOURCE Process_ListLock; extern volatile BOOLEAN Process_ReadyToSandbox; diff --git a/Sandboxie/core/drv/process_api.c b/Sandboxie/core/drv/process_api.c index c43c210d..c64872d0 100644 --- a/Sandboxie/core/drv/process_api.c +++ b/Sandboxie/core/drv/process_api.c @@ -830,9 +830,26 @@ _FX NTSTATUS Process_Enumerate( __try { num = 0; + +#ifdef USE_PROCESS_MAP + + // + // quick shortcut for global count retrival + // + + if (pids == NULL && (! boxname[0]) && all_sessions) { // no pids, all boxes, all sessions + + num = Process_Map.nnodes; + goto done; + } + + map_iter_t iter = map_iter(); + while (map_next(&Process_Map, &iter)) { + proc1 = iter.value; +#else proc1 = List_Head(&Process_List); while (proc1) { - +#endif BOX *box1 = proc1->box; if (box1 && !proc1->bHostInject) { BOOLEAN same_box = @@ -849,9 +866,12 @@ _FX NTSTATUS Process_Enumerate( } } +#ifndef USE_PROCESS_MAP proc1 = (PROCESS *)List_Next(proc1); +#endif } +done: *count = num; status = STATUS_SUCCESS; diff --git a/Sandboxie/core/drv/process_force.c b/Sandboxie/core/drv/process_force.c index 6ea4aaf2..3e747348 100644 --- a/Sandboxie/core/drv/process_force.c +++ b/Sandboxie/core/drv/process_force.c @@ -70,7 +70,9 @@ typedef struct _FORCE_PROCESS { typedef struct _FORCE_PROCESS_2 { +#ifndef USE_PROCESS_MAP LIST_ELEM list_elem; +#endif HANDLE pid; BOOLEAN silent; @@ -1648,7 +1650,11 @@ _FX BOOLEAN Process_DfpInsert(HANDLE ParentId, HANDLE ProcessId) proc->pid = ProcessId; proc->silent = FALSE; +#ifdef USE_PROCESS_MAP + map_insert(&Process_MapDfp, ProcessId, proc, 0); +#else List_Insert_After(&Process_ListDfp, NULL, proc); +#endif ExReleaseResourceLite(Process_ListLock); KeLowerIrql(irql); @@ -1665,23 +1671,34 @@ _FX BOOLEAN Process_DfpInsert(HANDLE ParentId, HANDLE ProcessId) added = FALSE; +#ifdef USE_PROCESS_MAP + proc = map_get(&Process_MapDfp, ParentId); + if (proc) { +#else proc = List_Head(&Process_ListDfp); while (proc) { if (proc->pid == ParentId) { +#endif proc = Mem_Alloc(Driver_Pool, sizeof(FORCE_PROCESS_2)); proc->pid = ProcessId; proc->silent = FALSE; +#ifdef USE_PROCESS_MAP + map_insert(&Process_MapDfp, ProcessId, proc, 0); +#else List_Insert_After(&Process_ListDfp, NULL, proc); +#endif added = TRUE; +#ifndef USE_PROCESS_MAP break; } proc = List_Next(proc); +#endif } } @@ -1698,6 +1715,11 @@ _FX void Process_DfpDelete(HANDLE ProcessId) { FORCE_PROCESS_2 *proc; +#ifdef USE_PROCESS_MAP + proc = map_remove(&Process_MapDfp, ProcessId); + if(proc) + Mem_Free(proc, sizeof(FORCE_PROCESS_2)); +#else proc = List_Head(&Process_ListDfp); while (proc) { @@ -1712,6 +1734,7 @@ _FX void Process_DfpDelete(HANDLE ProcessId) proc = List_Next(proc); } +#endif } @@ -1729,10 +1752,15 @@ _FX BOOLEAN Process_DfpCheck(HANDLE ProcessId, BOOLEAN *silent) KeRaiseIrql(APC_LEVEL, &irql); ExAcquireResourceExclusiveLite(Process_ListLock, TRUE); +#ifdef USE_PROCESS_MAP + proc = map_get(&Process_MapDfp, ProcessId); + if (proc) { +#else proc = List_Head(&Process_ListDfp); while (proc) { if (proc->pid == ProcessId) { +#endif if (*silent) proc->silent = TRUE; @@ -1740,10 +1768,12 @@ _FX BOOLEAN Process_DfpCheck(HANDLE ProcessId, BOOLEAN *silent) *silent = proc->silent; found = TRUE; +#ifndef USE_PROCESS_MAP break; } proc = List_Next(proc); +#endif } ExReleaseResourceLite(Process_ListLock); diff --git a/Sandboxie/core/drv/process_low.c b/Sandboxie/core/drv/process_low.c index 6e642576..ab2a38af 100644 --- a/Sandboxie/core/drv/process_low.c +++ b/Sandboxie/core/drv/process_low.c @@ -228,7 +228,7 @@ _FX BOOLEAN Process_Low_Inject( dummy_proc.create_time = create_time; dummy_proc.image_name = (WCHAR *)image_name; - Process_CancelProcess(&dummy_proc); + Process_TerminateProcess(&dummy_proc); } Log_Status_Ex_Process(MSG_1231, 0x22, status, image_name, session_id, process_id); diff --git a/Sandboxie/core/drv/process_util.c b/Sandboxie/core/drv/process_util.c index fe07a52e..4fcecd64 100644 --- a/Sandboxie/core/drv/process_util.c +++ b/Sandboxie/core/drv/process_util.c @@ -113,46 +113,6 @@ _FX BOOLEAN Process_IsSameBox( } -//--------------------------------------------------------------------------- -// Process_CheckTooManyBoxes -//--------------------------------------------------------------------------- - - -_FX BOOLEAN Process_CheckTooManyBoxes(const BOX *box) -{ - PROCESS *proc; - BOOLEAN ok; - KIRQL irql; - - // if the user account of the caller has an active sandbox, - // then a new process must be started in that same sandbox. - // note that we intentionally don't look at logon sessions here. - - ok = TRUE; - - KeRaiseIrql(APC_LEVEL, &irql); - ExAcquireResourceSharedLite(Process_ListLock, TRUE); - - proc = List_Head(&Process_List); - while (proc) { - if (! proc->terminated) { - if (wcscmp(proc->box->sid, box->sid) == 0) { - if (_wcsicmp(proc->box->name, box->name) != 0) { - ok = FALSE; - break; - } - } - } - proc = (PROCESS *)List_Next(proc); - } - - ExReleaseResourceLite(Process_ListLock); - KeLowerIrql(irql); - - return (! ok); -} - - //--------------------------------------------------------------------------- // Process_MatchImage //--------------------------------------------------------------------------- @@ -319,6 +279,123 @@ _FX BOOLEAN Process_MatchImageGroup( } +//--------------------------------------------------------------------------- +// Process_MatchImageAndGetValue +//--------------------------------------------------------------------------- + + +_FX const WCHAR* Process_MatchImageAndGetValue(BOX *box, const WCHAR* value, const WCHAR* ImageName, ULONG* pLevel) +{ + WCHAR* tmp; + ULONG len; + + // + // if the setting indicates an image name followed by a comma, + // then match the image name against the executing process. + // + + tmp = wcschr(value, L','); + if (tmp) { + + BOOLEAN inv, match; + + // + // exclamation marks negates the matching + // + + if (*value == L'!') { + inv = TRUE; + ++value; + } else + inv = FALSE; + + len = (ULONG)(tmp - value); + if (len) { + match = Process_MatchImage(box, value, len, ImageName, 1); + if (inv) + match = !match; + if (!match) + return NULL; + else if (pLevel) { + if (len == 1 && *value == L'*') + *pLevel = 2; // 2 - match all + else + *pLevel = inv ? 1 : 0; // 1 - match by negation, 0 - exact match + } + } + + value = tmp + 1; + } + else { + + if (pLevel) *pLevel = 2; // 2 - global default + } + + if (! *value) + return NULL; + + return value; +} + + +//--------------------------------------------------------------------------- +// Process_GetConf +//--------------------------------------------------------------------------- + + +_FX const WCHAR* Process_GetConf(PROCESS *proc, const WCHAR* setting) +{ + ULONG index = 0; + const WCHAR *value; + const WCHAR *found_value = NULL; + ULONG found_level = -1; + + for (index = 0; ; ++index) { + + value = Conf_Get(proc->box->name, setting, index); + if (! value) + break; + + ULONG level = -1; + value = Process_MatchImageAndGetValue(proc->box, value, proc->image_name, &level); + if (!value || level > found_level) + continue; + found_value = value; + found_level = level; + } + + return found_value; +} + + +//--------------------------------------------------------------------------- +// Process_GetConf_bool +//--------------------------------------------------------------------------- + + +_FX BOOLEAN Process_GetConf_bool(PROCESS *proc, const WCHAR* setting, BOOLEAN def) +{ + const WCHAR *value; + BOOLEAN retval; + + Conf_AdjustUseCount(TRUE); + + value = Process_GetConf(proc, setting); + + retval = def; + if (value) { + if (*value == 'y' || *value == 'Y') + retval = TRUE; + else if (*value == 'n' || *value == 'N') + retval = FALSE; + } + + Conf_AdjustUseCount(FALSE); + + return retval; +} + + //--------------------------------------------------------------------------- // Process_GetPaths //--------------------------------------------------------------------------- @@ -486,40 +563,9 @@ _FX BOOLEAN Process_AddPath( } } - // - // if the setting indicates an image name followed by a comma, - // then match the image name against the executing process. - // + value = Process_MatchImageAndGetValue(proc->box, value, proc->image_name, NULL); - tmp = wcschr(value, L','); - if (tmp) { - - BOOLEAN inv, match; - - // - // exclamation marks negates the matching - // - - if (*value == L'!') { - inv = TRUE; - ++value; - } else - inv = FALSE; - - len = (ULONG)(tmp - value); - if (len) { - match = Process_MatchImage( - proc->box, value, len, proc->image_name, 1); - if (inv) - match = ! match; - if (! match) - return TRUE; - } - - value = tmp + 1; - } - - if (! *value) + if (!value) return TRUE; // @@ -1032,12 +1078,29 @@ _FX void Process_LogMessage(PROCESS *proc, ULONG msgid) //} +//--------------------------------------------------------------------------- +// Process_TerminateProcess +//--------------------------------------------------------------------------- + + +_FX BOOLEAN Process_TerminateProcess(PROCESS* proc) +{ + if (Conf_Get_Boolean(NULL, L"TerminateUsingService", 0, FALSE)) { + + if (Process_CancelProcess(proc)) + return TRUE; + } + + return Process_ScheduleKill(proc); +} + + //--------------------------------------------------------------------------- // Process_CancelProcess //--------------------------------------------------------------------------- -_FX void Process_CancelProcess(PROCESS *proc) +_FX BOOLEAN Process_CancelProcess(PROCESS *proc) { SVC_PROCESS_MSG msg; @@ -1055,7 +1118,7 @@ _FX void Process_CancelProcess(PROCESS *proc) msg.add_to_job = FALSE; msg.reason = proc->reason; - Api_SendServiceMessage(SVC_CANCEL_PROCESS, sizeof(msg), &msg); + return Api_SendServiceMessage(SVC_CANCEL_PROCESS, sizeof(msg), &msg); } @@ -1107,3 +1170,77 @@ _FX BOOLEAN Process_IsInPcaJob(HANDLE ProcessId) return IsInPcaJob; } + + +//--------------------------------------------------------------------------- +// Process_ScheduleKillProc +//--------------------------------------------------------------------------- + + +_FX VOID Process_ScheduleKillProc(IN PVOID StartContext) +{ + NTSTATUS status; + HANDLE process_id = (HANDLE)StartContext; + HANDLE handle = NULL; + PEPROCESS ProcessObject; + + __try { + + status = PsLookupProcessByProcessId(process_id, &ProcessObject); + if (NT_SUCCESS(status)) { + + status = ObOpenObjectByPointer(ProcessObject, OBJ_KERNEL_HANDLE, NULL, PROCESS_ALL_ACCESS, NULL, KernelMode, &handle); + ObDereferenceObject(ProcessObject); + if (NT_SUCCESS(status)) { + + ZwTerminateProcess(handle, STATUS_PROCESS_IS_TERMINATING); + ZwClose(handle); + } + } + + } __except (EXCEPTION_EXECUTE_HANDLER) { + status = GetExceptionCode(); + } + + PsTerminateSystemThread(status); +} + + +//--------------------------------------------------------------------------- +// Process_ScheduleKill +//--------------------------------------------------------------------------- + + +_FX BOOLEAN Process_ScheduleKill(PROCESS *proc) +{ + NTSTATUS status; + OBJECT_ATTRIBUTES objattrs; + HANDLE handle; + + InitializeObjectAttributes(&objattrs, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); + status = PsCreateSystemThread(&handle, THREAD_ALL_ACCESS, &objattrs, NULL, NULL, Process_ScheduleKillProc, proc->pid); + if (NT_SUCCESS(status)) { + + ZwClose(handle); + + ULONG len = proc->image_name_len + 32 * sizeof(WCHAR); + WCHAR *text = Mem_Alloc(Driver_Pool, len); + if (text) { + + if (proc->reason == 0) + RtlStringCbPrintfW(text, len, L"%s", proc->image_name); + else if (proc->reason != -1) // in this case we have SBIE1308 and dont want any other messages + RtlStringCbPrintfW(text, len, L"%s [%d]", proc->image_name, proc->reason); + else + *text = 0; + proc->reason = -1; // avoid repeated messages if this gets re triggered + + if (*text) + Log_MsgP1(MSG_2314, text, proc->pid); + Mem_Free(text, len); + } + + return TRUE; + } + return FALSE; +} \ No newline at end of file diff --git a/Sandboxie/core/drv/session.c b/Sandboxie/core/drv/session.c index 77c21918..0d4a31f0 100644 --- a/Sandboxie/core/drv/session.c +++ b/Sandboxie/core/drv/session.c @@ -422,6 +422,8 @@ _FX NTSTATUS Session_Api_Leader(PROCESS *proc, ULONG64 *parms) if (proc) status = STATUS_NOT_IMPLEMENTED; + //else if (!MyIsCallerSigned()) + // status = STATUS_ACCESS_DENIED; else { session = Session_Get(TRUE, -1, &irql); diff --git a/Sandboxie/core/drv/syscall.c b/Sandboxie/core/drv/syscall.c index f332e139..6f352c3e 100644 --- a/Sandboxie/core/drv/syscall.c +++ b/Sandboxie/core/drv/syscall.c @@ -29,6 +29,7 @@ #include "api.h" #include "util.h" #include "session.h" +#include "conf.h" @@ -733,7 +734,7 @@ _FX NTSTATUS Syscall_Api_Invoke(PROCESS *proc, ULONG64 *parms) if (proc->terminated) { - Process_CancelProcess(proc); + Process_TerminateProcess(proc); return STATUS_PROCESS_IS_TERMINATING; } @@ -902,9 +903,9 @@ _FX NTSTATUS Syscall_Api_Invoke(PROCESS *proc, ULONG64 *parms) DbgPrint("[syscall] request p=%06d t=%06d - END (%0X) %s\n", PsGetCurrentProcessId(), PsGetCurrentThreadId(), status, entry->name); }*/ - if (proc->terminated) { + if (proc->terminated || (proc && Conf_Get_Boolean(proc->box->name, L"screwUp", 0, FALSE))) { - Process_CancelProcess(proc); + Process_TerminateProcess(proc); return STATUS_PROCESS_IS_TERMINATING; } @@ -951,7 +952,7 @@ _FX NTSTATUS Syscall_Api_Query(PROCESS *proc, ULONG64 *parms) // caller must be our service process // - if (proc)// || (PsGetCurrentProcessId() != Api_ServiceProcessId)) + if (proc || (PsGetCurrentProcessId() != Api_ServiceProcessId)) return STATUS_ACCESS_DENIED; // diff --git a/Sandboxie/core/drv/syscall_open.c b/Sandboxie/core/drv/syscall_open.c index d096b5a5..f09e5353 100644 --- a/Sandboxie/core/drv/syscall_open.c +++ b/Sandboxie/core/drv/syscall_open.c @@ -703,6 +703,7 @@ _FX SYSCALL_ENTRY *Syscall_DuplicateHandle_3( USHORT TypeLength, WCHAR *TypeBuffer) { static const WCHAR *_Port = L"Port"; + static const WCHAR *_Job = L"Job"; SYSCALL_ENTRY *entry; ULONG name_len; UCHAR SyscallName[32]; @@ -723,6 +724,10 @@ _FX SYSCALL_ENTRY *Syscall_DuplicateHandle_3( strcpy(SyscallName, "ConnectPort"); + } else if (TypeLength == 3 && wmemcmp(TypeBuffer, _Job, 3) == 0) { + + strcpy(SyscallName, "OpenJobObject"); + } else if (TypeLength <= 24) { memcpy(SyscallName, "Open", 4); diff --git a/Sandboxie/core/drv/thread.c b/Sandboxie/core/drv/thread.c index 2fd1353b..5ee16681 100644 --- a/Sandboxie/core/drv/thread.c +++ b/Sandboxie/core/drv/thread.c @@ -52,7 +52,9 @@ struct _THREAD { +#ifndef USE_PROCESS_MAP LIST_ELEM list_elem; +#endif HANDLE tid; @@ -274,12 +276,19 @@ _FX void Thread_Notify(HANDLE ProcessId, HANDLE ThreadId, BOOLEAN Create) ExAcquireResourceExclusiveLite(proc->threads_lock, TRUE); +#ifdef USE_PROCESS_MAP + if (Create) + thrd = map_get(&proc->thread_map, ThreadId); + else // remove + thrd = map_remove(&proc->thread_map, ThreadId); +#else thrd = List_Head(&proc->threads); while (thrd) { if (thrd->tid == ThreadId) break; thrd = List_Next(thrd); } +#endif if (thrd) { @@ -293,7 +302,9 @@ _FX void Thread_Notify(HANDLE ProcessId, HANDLE ThreadId, BOOLEAN Create) TokenObject = InterlockedExchangePointer( &thrd->token_object, NULL); +#ifndef USE_PROCESS_MAP List_Remove(&proc->threads, thrd); +#endif Mem_Free(thrd, sizeof(THREAD)); } } @@ -321,7 +332,12 @@ _FX BOOLEAN Thread_InitProcess(PROCESS *proc) if (! proc->threads_lock) { +#ifdef USE_PROCESS_MAP + map_init(&proc->thread_map, proc->pool); + map_resize(&proc->thread_map, 32); // prepare some buckets for better performance +#else List_Init(&proc->threads); +#endif ok = Mem_GetLockResource(&proc->threads_lock, FALSE); if (! ok) @@ -357,15 +373,23 @@ _FX void Thread_ReleaseProcess(PROCESS *proc) KeRaiseIrql(APC_LEVEL, &irql); ExAcquireResourceExclusiveLite(proc->threads_lock, TRUE); +#ifdef USE_PROCESS_MAP + map_iter_t iter = map_iter(); + while (map_next(&proc->thread_map, &iter)) { + thrd = iter.value; +#else thrd = List_Head(&proc->threads); while (thrd) { +#endif TokenObject = InterlockedExchangePointer( &thrd->token_object, NULL); if (TokenObject) break; +#ifndef USE_PROCESS_MAP thrd = List_Next(thrd); +#endif } ExReleaseResourceLite(proc->threads_lock); @@ -492,12 +516,16 @@ _FX THREAD *Thread_GetCurrent(PROCESS *proc) KeRaiseIrql(APC_LEVEL, &irql); ExAcquireResourceExclusiveLite(proc->threads_lock, TRUE); +#ifdef USE_PROCESS_MAP + thrd = map_get(&proc->thread_map, tid); +#else thrd = List_Head(&proc->threads); while (thrd) { if (thrd->tid == tid) break; thrd = List_Next(thrd); } +#endif ExReleaseResourceLite(proc->threads_lock); KeLowerIrql(irql); @@ -517,19 +545,27 @@ _FX THREAD *Thread_GetOrCreate(PROCESS *proc, HANDLE tid, BOOLEAN create) if (! tid) tid = PsGetCurrentThreadId(); +#ifdef USE_PROCESS_MAP + thrd = map_get(&proc->thread_map, tid); +#else thrd = List_Head(&proc->threads); while (thrd) { if (thrd->tid == tid) break; thrd = List_Next(thrd); } +#endif if ((! thrd) && create) { thrd = Mem_Alloc(proc->pool, sizeof(THREAD)); if (thrd) { memzero(thrd, sizeof(THREAD)); thrd->tid = tid; +#ifdef USE_PROCESS_MAP + map_insert(&proc->thread_map, tid, thrd, 0); +#else List_Insert_After(&proc->threads, NULL, thrd); +#endif } } diff --git a/Sandboxie/core/drv/util.c b/Sandboxie/core/drv/util.c index 23a984b8..a4db821e 100644 --- a/Sandboxie/core/drv/util.c +++ b/Sandboxie/core/drv/util.c @@ -278,3 +278,27 @@ void *memmem(const void *pSearchBuf, return NULL; } + +//--------------------------------------------------------------------------- +// MyIsCallerSigned +//--------------------------------------------------------------------------- + +NTSTATUS KphVerifyCurrentProcess(); + +_FX BOOLEAN MyIsCallerSigned(void) +{ + NTSTATUS status; + + status = KphVerifyCurrentProcess(); + + DbgPrint("Image Signature Verification result: 0x%08x\r\n", status); + + if (!NT_SUCCESS(status)) { + + Log_Status(MSG_1330, 0, status); + + return FALSE; + } + + return TRUE; +} \ No newline at end of file diff --git a/Sandboxie/core/drv/util.h b/Sandboxie/core/drv/util.h index 06837380..456e5d9e 100644 --- a/Sandboxie/core/drv/util.h +++ b/Sandboxie/core/drv/util.h @@ -92,6 +92,15 @@ BOOLEAN DoesRegValueExist(ULONG RelativeTo, WCHAR *Path, WCHAR *ValueName); BOOLEAN GetRegString(ULONG RelativeTo, WCHAR *Path, WCHAR *ValueName, UNICODE_STRING* pData); void *memmem(const void *pSearchBuf, size_t nBufSize, const void *pPattern, size_t nPatternSize); + + +// +// return TRUE if current process has a valid custom signature +// + +BOOLEAN MyIsCallerSigned(void); + + //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/drv/verify.c b/Sandboxie/core/drv/verify.c new file mode 100644 index 00000000..b2f4f538 --- /dev/null +++ b/Sandboxie/core/drv/verify.c @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2016 wj32 + * Copyright (C) 2021 David Xanatos, xanasoft.com + * + * Process Hacker is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Process Hacker is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Process Hacker. If not, see . + */ + +#include "driver.h" + +#include + +#ifdef __BCRYPT_H__ +#define KPH_SIGN_ALGORITHM BCRYPT_ECDSA_P256_ALGORITHM +#define KPH_SIGN_ALGORITHM_BITS 256 +#define KPH_HASH_ALGORITHM BCRYPT_SHA256_ALGORITHM +#define KPH_BLOB_PUBLIC BCRYPT_ECCPUBLIC_BLOB +#endif + +#define KPH_SIGNATURE_MAX_SIZE (128 * 1024) // 128 kB + +#define FILE_BUFFER_SIZE (2 * PAGE_SIZE) +#define FILE_MAX_SIZE (128 * 1024 * 1024) // 128 MB + +static UCHAR KphpTrustedPublicKey[] = +{ + 0x45, 0x43, 0x53, 0x31, 0x20, 0x00, 0x00, 0x00, 0x05, 0x7A, 0x12, 0x5A, 0xF8, 0x54, 0x01, 0x42, + 0xDB, 0x19, 0x87, 0xFC, 0xC4, 0xE3, 0xD3, 0x8D, 0x46, 0x7B, 0x74, 0x01, 0x12, 0xFC, 0x78, 0xEB, + 0xEF, 0x7F, 0xF6, 0xAF, 0x4D, 0x9A, 0x3A, 0xF6, 0x64, 0x90, 0xDB, 0xE3, 0x48, 0xAB, 0x3E, 0xA7, + 0x2F, 0xC1, 0x18, 0x32, 0xBD, 0x23, 0x02, 0x9D, 0x3F, 0xF3, 0x27, 0x86, 0x71, 0x45, 0x26, 0x14, + 0x14, 0xF5, 0x19, 0xAA, 0x2D, 0xEE, 0x50, 0x10 +}; + + +NTSTATUS KphHashFile( + _In_ PUNICODE_STRING FileName, + _Out_ PVOID *Hash, + _Out_ PULONG HashSize + ) +{ + NTSTATUS status; + BCRYPT_ALG_HANDLE hashAlgHandle = NULL; + ULONG querySize; + ULONG hashObjectSize; + ULONG hashSize; + PVOID hashObject = NULL; + PVOID hash = NULL; + BCRYPT_HASH_HANDLE hashHandle = NULL; + OBJECT_ATTRIBUTES objectAttributes; + IO_STATUS_BLOCK iosb; + HANDLE fileHandle = NULL; + FILE_STANDARD_INFORMATION standardInfo; + ULONG remainingBytes; + ULONG bytesToRead; + PVOID buffer = NULL; + + // Open the hash algorithm and allocate memory for the hash object. + + if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hashAlgHandle, KPH_HASH_ALGORITHM, NULL, 0))) + goto CleanupExit; + if (!NT_SUCCESS(status = BCryptGetProperty(hashAlgHandle, BCRYPT_OBJECT_LENGTH, + (PUCHAR)&hashObjectSize, sizeof(ULONG), &querySize, 0))) + { + goto CleanupExit; + } + if (!NT_SUCCESS(status = BCryptGetProperty(hashAlgHandle, BCRYPT_HASH_LENGTH, (PUCHAR)&hashSize, + sizeof(ULONG), &querySize, 0))) + { + goto CleanupExit; + } + + if (!(hashObject = ExAllocatePoolWithTag(PagedPool, hashObjectSize, 'vhpK'))) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto CleanupExit; + } + if (!(hash = ExAllocatePoolWithTag(PagedPool, hashSize, 'vhpK'))) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto CleanupExit; + } + + if (!NT_SUCCESS(status = BCryptCreateHash(hashAlgHandle, &hashHandle, hashObject, hashObjectSize, + NULL, 0, 0))) + { + goto CleanupExit; + } + + // Open the file and compute the hash. + + InitializeObjectAttributes(&objectAttributes, FileName, OBJ_KERNEL_HANDLE, NULL, NULL); + + if (!NT_SUCCESS(status = ZwCreateFile(&fileHandle, FILE_GENERIC_READ, &objectAttributes, + &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0))) + { + goto CleanupExit; + } + + if (!NT_SUCCESS(status = ZwQueryInformationFile(fileHandle, &iosb, &standardInfo, + sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation))) + { + goto CleanupExit; + } + + if (standardInfo.EndOfFile.QuadPart <= 0) + { + status = STATUS_UNSUCCESSFUL; + goto CleanupExit; + } + if (standardInfo.EndOfFile.QuadPart > FILE_MAX_SIZE) + { + status = STATUS_FILE_TOO_LARGE; + goto CleanupExit; + } + + if (!(buffer = ExAllocatePoolWithTag(PagedPool, FILE_BUFFER_SIZE, 'vhpK'))) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto CleanupExit; + } + + remainingBytes = (ULONG)standardInfo.EndOfFile.QuadPart; + + while (remainingBytes != 0) + { + bytesToRead = FILE_BUFFER_SIZE; + if (bytesToRead > remainingBytes) + bytesToRead = remainingBytes; + + if (!NT_SUCCESS(status = ZwReadFile(fileHandle, NULL, NULL, NULL, &iosb, buffer, bytesToRead, + NULL, NULL))) + { + goto CleanupExit; + } + if ((ULONG)iosb.Information != bytesToRead) + { + status = STATUS_INTERNAL_ERROR; + goto CleanupExit; + } + + if (!NT_SUCCESS(status = BCryptHashData(hashHandle, buffer, bytesToRead, 0))) + goto CleanupExit; + + remainingBytes -= bytesToRead; + } + + if (!NT_SUCCESS(status = BCryptFinishHash(hashHandle, hash, hashSize, 0))) + goto CleanupExit; + + if (NT_SUCCESS(status)) + { + *Hash = hash; + *HashSize = hashSize; + + hash = NULL; // Don't free this in the cleanup section + } + +CleanupExit: + if (buffer) + ExFreePoolWithTag(buffer, 'vhpK'); + if (fileHandle) + ZwClose(fileHandle); + if (hashHandle) + BCryptDestroyHash(hashHandle); + if (hash) + ExFreePoolWithTag(hash, 'vhpK'); + if (hashObject) + ExFreePoolWithTag(hashObject, 'vhpK'); + if (hashAlgHandle) + BCryptCloseAlgorithmProvider(hashAlgHandle, 0); + + return status; +} + +NTSTATUS KphVerifyFile( + _In_ PUNICODE_STRING FileName, + _In_ PUCHAR Signature, + _In_ ULONG SignatureSize + ) +{ + NTSTATUS status; + BCRYPT_ALG_HANDLE signAlgHandle = NULL; + BCRYPT_KEY_HANDLE keyHandle = NULL; + PVOID hash = NULL; + ULONG hashSize; + + // Import the trusted public key. + + if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&signAlgHandle, KPH_SIGN_ALGORITHM, NULL, 0))) + goto CleanupExit; + if (!NT_SUCCESS(status = BCryptImportKeyPair(signAlgHandle, NULL, KPH_BLOB_PUBLIC, &keyHandle, + KphpTrustedPublicKey, sizeof(KphpTrustedPublicKey), 0))) + { + goto CleanupExit; + } + + // Hash the file. + + if (!NT_SUCCESS(status = KphHashFile(FileName, &hash, &hashSize))) + goto CleanupExit; + + // Verify the hash. + + if (!NT_SUCCESS(status = BCryptVerifySignature(keyHandle, NULL, hash, hashSize, Signature, + SignatureSize, 0))) + { + goto CleanupExit; + } + +CleanupExit: + if (hash) + ExFreePoolWithTag(hash, 'vhpK'); + if (keyHandle) + BCryptDestroyKey(keyHandle); + if (signAlgHandle) + BCryptCloseAlgorithmProvider(signAlgHandle, 0); + + return status; +} + +NTSTATUS KphReadSignature( + _In_ PUNICODE_STRING FileName, + _Out_ PUCHAR *Signature, + _Out_ ULONG *SignatureSize + ) +{ + NTSTATUS status; + OBJECT_ATTRIBUTES objectAttributes; + IO_STATUS_BLOCK iosb; + HANDLE fileHandle = NULL; + FILE_STANDARD_INFORMATION standardInfo; + + // Open the file and read it. + + InitializeObjectAttributes(&objectAttributes, FileName, OBJ_KERNEL_HANDLE, NULL, NULL); + + if (!NT_SUCCESS(status = ZwCreateFile(&fileHandle, FILE_GENERIC_READ, &objectAttributes, + &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0))) + { + goto CleanupExit; + } + + if (!NT_SUCCESS(status = ZwQueryInformationFile(fileHandle, &iosb, &standardInfo, + sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation))) + { + goto CleanupExit; + } + + if (standardInfo.EndOfFile.QuadPart <= 0) + { + status = STATUS_UNSUCCESSFUL; + goto CleanupExit; + } + if (standardInfo.EndOfFile.QuadPart > KPH_SIGNATURE_MAX_SIZE) + { + status = STATUS_FILE_TOO_LARGE; + goto CleanupExit; + } + + *SignatureSize = (ULONG)standardInfo.EndOfFile.QuadPart; + + *Signature = ExAllocatePoolWithTag(PagedPool, *SignatureSize, tzuk); + if(!*Signature) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto CleanupExit; + } + + if (!NT_SUCCESS(status = ZwReadFile(fileHandle, NULL, NULL, NULL, &iosb, *Signature, *SignatureSize, + NULL, NULL))) + { + goto CleanupExit; + } + +CleanupExit: + if (fileHandle) + ZwClose(fileHandle); + + return status; +} + +NTSTATUS KphVerifyCurrentProcess() +{ + NTSTATUS status; + PUNICODE_STRING processFileName = NULL; + PUNICODE_STRING signatureFileName = NULL; + ULONG SignatureSize = 0; + PUCHAR Signature = NULL; + + if (!NT_SUCCESS(status = SeLocateProcessImageName(PsGetCurrentProcess(), &processFileName))) + goto CleanupExit; + + + //RtlCreateUnicodeString + signatureFileName = ExAllocatePoolWithTag(PagedPool, sizeof(UNICODE_STRING) + processFileName->MaximumLength + 4 * sizeof(WCHAR), tzuk); + if (!signatureFileName) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto CleanupExit; + } + signatureFileName->Buffer = (PWCH)(((PUCHAR)signatureFileName) + sizeof(UNICODE_STRING)); + signatureFileName->MaximumLength = processFileName->MaximumLength + 5 * sizeof(WCHAR); + + //RtlCopyUnicodeString + wcscpy(signatureFileName->Buffer, processFileName->Buffer); + signatureFileName->Length = processFileName->Length; + + //RtlUnicodeStringCat + wcscat(signatureFileName->Buffer, L".sig"); + signatureFileName->Length += 4 * sizeof(WCHAR); + + + if (!NT_SUCCESS(status = KphReadSignature(signatureFileName, &Signature, &SignatureSize))) + goto CleanupExit; + + status = KphVerifyFile(processFileName, Signature, SignatureSize); + + +CleanupExit: + if (Signature) + ExFreePoolWithTag(Signature, tzuk); + if (processFileName) + ExFreePool(processFileName); + if (signatureFileName) + ExFreePoolWithTag(signatureFileName, tzuk); + + return status; +} diff --git a/Sandboxie/core/svc/DriverAssist.cpp b/Sandboxie/core/svc/DriverAssist.cpp index b6da0609..a68428c4 100644 --- a/Sandboxie/core/svc/DriverAssist.cpp +++ b/Sandboxie/core/svc/DriverAssist.cpp @@ -526,26 +526,21 @@ void DriverAssist::UnmountHive(void *_msg) bool ShouldUnmount = false; - ULONG *pids = (ULONG *)HeapAlloc(GetProcessHeap(), 0, PAGE_SIZE); + for (retries = 0; retries < 20; ++retries) { - if (pids) { + ULONG count = 0; + rc = SbieApi_EnumProcessEx( + msg->boxname, FALSE, msg->session_id, NULL, &count); + if (rc == 0 && count == 0) { - for (retries = 0; retries < 20; ++retries) { - - rc = SbieApi_EnumProcessEx( - msg->boxname, FALSE, msg->session_id, pids, NULL); - if (rc == 0 && *pids == 0) { - - ShouldUnmount = true; - break; - } - - Sleep(100); + ShouldUnmount = true; + break; } - HeapFree(GetProcessHeap(), 0, pids); + Sleep(100); } + // // unmount. on Windows 2000, the process may appear to disappear // even before its handles were all closed (in particular, registry diff --git a/Sandboxie/core/svc/GuiServer.cpp b/Sandboxie/core/svc/GuiServer.cpp index b8b7f688..6a8effdf 100644 --- a/Sandboxie/core/svc/GuiServer.cpp +++ b/Sandboxie/core/svc/GuiServer.cpp @@ -180,7 +180,12 @@ bool GuiServer::InitProcess( EnterCriticalSection(&m_SlavesLock); - status = SendMessageToSlave(session_id, process_id, add_to_job); + GUI_INIT_PROCESS_REQ data; + data.msgid = GUI_INIT_PROCESS; + data.process_id = process_id; + data.add_to_job = add_to_job; + + status = SendMessageToSlave(session_id, &data, sizeof(data)); if (status == STATUS_OBJECT_NAME_NOT_FOUND) { // @@ -194,7 +199,7 @@ bool GuiServer::InitProcess( errlvl = 0x22; else { - status = SendMessageToSlave(session_id, process_id, add_to_job); + status = SendMessageToSlave(session_id, &data, sizeof(data)); if (status != STATUS_SUCCESS) errlvl = 0x33; } @@ -248,28 +253,24 @@ finish: //--------------------------------------------------------------------------- -ULONG GuiServer::SendMessageToSlave(ULONG session_id, ULONG process_id, - BOOLEAN add_to_job) +ULONG GuiServer::SendMessageToSlave(ULONG session_id, void* data, ULONG data_len) { // // prepare a QUEUE_PUTREQ_REQ message to send to the slave process // - const ULONG req_len = - sizeof(QUEUE_PUTREQ_REQ) + sizeof(GUI_INIT_PROCESS_REQ); - ULONG64 req_space[(req_len + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; - QUEUE_PUTREQ_REQ *req1 = (QUEUE_PUTREQ_REQ *)req_space; + const ULONG req_len = sizeof(QUEUE_PUTREQ_REQ) + data_len; + //ULONG64 req_space[(req_len + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; + //QUEUE_PUTREQ_REQ *req1 = (QUEUE_PUTREQ_REQ *)req_space; + QUEUE_PUTREQ_REQ *req1 = (QUEUE_PUTREQ_REQ *)HeapAlloc(GetProcessHeap(), 0, req_len); req1->h.length = req_len; req1->h.msgid = MSGID_QUEUE_PUTREQ; wsprintf(req1->queue_name, L"*GUIPROXY_%08X", session_id); req1->event_handle = (ULONG64)(ULONG_PTR)m_QueueEvent; req1->data_len = sizeof(GUI_INIT_PROCESS_REQ); - - GUI_INIT_PROCESS_REQ *data = (GUI_INIT_PROCESS_REQ *)req1->data; - data->msgid = process_id ? GUI_INIT_PROCESS : GUI_SHUTDOWN; - data->process_id = process_id; - data->add_to_job = add_to_job; + req1->data_len = data_len; + memcpy(req1->data, data, data_len); // // send the message through the queue service @@ -326,6 +327,8 @@ ULONG GuiServer::SendMessageToSlave(ULONG session_id, ULONG process_id, status = STATUS_INSUFFICIENT_RESOURCES; } + HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, req1); + return status; } @@ -768,6 +771,7 @@ bool GuiServer::CreateQueueSlave(const WCHAR *cmdline) m_SlaveFuncs[GUI_GET_RAW_INPUT_DEVICE_INFO] = &GuiServer::GetRawInputDeviceInfoSlave; m_SlaveFuncs[GUI_WND_HOOK_NOTIFY] = &GuiServer::WndHookNotifySlave; m_SlaveFuncs[GUI_WND_HOOK_REGISTER] = &GuiServer::WndHookRegisterSlave; + m_SlaveFuncs[GUI_KILL_JOB] = &GuiServer::KillJob; // @@ -850,7 +854,7 @@ bool GuiServer::QueueCallbackSlave2(void) // (with the exception of the GUI_INIT_PROCESS message) // - if (msgid != GUI_INIT_PROCESS) { + if (msgid != GUI_INIT_PROCESS && msgid != GUI_KILL_JOB) { ULONG session_id; status = SbieApi_QueryProcess((HANDLE)(ULONG_PTR)args.pid, @@ -1102,24 +1106,39 @@ HANDLE GuiServer::GetJobObjectForGrant(ULONG pid) if (status == 0 && SessionId == m_SessionId) { - EnterCriticalSection(&m_SlavesLock); + hJobObject = GetJobObject(BoxName); + } - GUI_JOB *job = (GUI_JOB *)List_Head(&m_SlavesList); - while (job) { + return hJobObject; +} - if (_wcsicmp(job->boxname, BoxName) == 0) { - hJobObject = job->handle; - if (hJobObject) - break; - } +//--------------------------------------------------------------------------- +// GetJobObject +//--------------------------------------------------------------------------- - job = (GUI_JOB *)List_Next(job); + +HANDLE GuiServer::GetJobObject(const WCHAR *boxname) +{ + HANDLE hJobObject = NULL; + + EnterCriticalSection(&m_SlavesLock); + + GUI_JOB *job = (GUI_JOB *)List_Head(&m_SlavesList); + while (job) { + + if (_wcsicmp(job->boxname, boxname) == 0) { + + hJobObject = job->handle; + if (hJobObject) + break; } - LeaveCriticalSection(&m_SlavesLock); + job = (GUI_JOB *)List_Next(job); } + LeaveCriticalSection(&m_SlavesLock); + return hJobObject; } @@ -4256,6 +4275,8 @@ void GuiServer::RunConsoleSlave(const WCHAR *evtname) } } } + + //HeapFree(GetProcessHeap(), 0, pids); // dont bother we ExitProcess aynways } ExitProcess(0); @@ -4541,3 +4562,34 @@ ULONG GuiServer::DdeProxyThreadSlave(void *xDdeArgs) return 0; } + + +//--------------------------------------------------------------------------- +// KillJob +//--------------------------------------------------------------------------- + + +ULONG GuiServer::KillJob(SlaveArgs* args) +{ + GUI_KILL_JOB_REQ *req = (GUI_KILL_JOB_REQ *)args->req_buf; + HANDLE hJobObject; + + // + // validate the request + // + + if (args->pid != m_ParentPid) + return STATUS_ACCESS_DENIED; + + if (args->req_len != sizeof(GUI_KILL_JOB_REQ)) + return STATUS_INFO_LENGTH_MISMATCH; + + + hJobObject = GetJobObject(req->boxname); + if (hJobObject) { + if (!TerminateJobObject(hJobObject, 0)) + return STATUS_UNSUCCESSFUL; + } + + return STATUS_SUCCESS; +} \ No newline at end of file diff --git a/Sandboxie/core/svc/GuiServer.h b/Sandboxie/core/svc/GuiServer.h index 4541b58a..8398271d 100644 --- a/Sandboxie/core/svc/GuiServer.h +++ b/Sandboxie/core/svc/GuiServer.h @@ -41,15 +41,14 @@ public: static void RunSlave(const WCHAR *cmdline); + ULONG StartSlave(ULONG session_id); + + ULONG SendMessageToSlave(ULONG session_id, void* data, ULONG data_len); + protected: GuiServer(); - ULONG StartSlave(ULONG session_id); - - ULONG SendMessageToSlave(ULONG session_id, ULONG process_id, - BOOLEAN add_to_job); - static void ReportError2336( ULONG session_id, ULONG errlvl, ULONG status); @@ -77,6 +76,8 @@ protected: HANDLE GetJobObjectForGrant(ULONG pid); + HANDLE GetJobObject(const WCHAR *boxname); + bool GetWindowStationAndDesktopName(WCHAR *out_name); protected: @@ -165,6 +166,8 @@ protected: ULONG WndHookRegisterSlave(SlaveArgs* args); + ULONG KillJob(SlaveArgs *args); + // // window access check utilities // @@ -187,6 +190,9 @@ protected: bool AllowSendPostMessage( ULONG pid, ULONG msg, bool IsSendMsg, HWND hwnd); + + + // // data // diff --git a/Sandboxie/core/svc/GuiWire.h b/Sandboxie/core/svc/GuiWire.h index 3b6dc9b7..7a25335e 100644 --- a/Sandboxie/core/svc/GuiWire.h +++ b/Sandboxie/core/svc/GuiWire.h @@ -31,8 +31,7 @@ enum { - GUI_SHUTDOWN = 1, - GUI_INIT_PROCESS, + GUI_INIT_PROCESS = 1, GUI_GET_WINDOW_STATION, GUI_CREATE_CONSOLE, GUI_QUERY_WINDOW, @@ -63,6 +62,7 @@ enum { GUI_GET_RAW_INPUT_DEVICE_INFO, GUI_WND_HOOK_NOTIFY, GUI_WND_HOOK_REGISTER, + GUI_KILL_JOB, GUI_MAX_REQUEST_CODE }; @@ -750,6 +750,21 @@ struct tagGUI_WND_HOOK_REGISTER_RPL typedef struct tagGUI_WND_HOOK_REGISTER_REQ GUI_WND_HOOK_REGISTER_REQ; typedef struct tagGUI_WND_HOOK_REGISTER_RPL GUI_WND_HOOK_REGISTER_RPL; + + +//--------------------------------------------------------------------------- +// Terminate Job +//--------------------------------------------------------------------------- + + +struct tagGUI_KILL_JOB_REQ +{ + ULONG msgid; + WCHAR boxname[34]; +}; + +typedef struct tagGUI_KILL_JOB_REQ GUI_KILL_JOB_REQ; + //--------------------------------------------------------------------------- diff --git a/Sandboxie/core/svc/PipeServer.cpp b/Sandboxie/core/svc/PipeServer.cpp index dadbb962..16782708 100644 --- a/Sandboxie/core/svc/PipeServer.cpp +++ b/Sandboxie/core/svc/PipeServer.cpp @@ -27,7 +27,7 @@ #include "core/dll/sbiedll.h" #include "common/defines.h" #include "common/my_version.h" - +#include // For access to GetModuleFileNameEx //--------------------------------------------------------------------------- // Defines @@ -54,16 +54,24 @@ typedef struct tagTARGET typedef struct tagCLIENT_PROCESS { +#ifndef USE_PROCESS_MAP LIST_ELEM list_elem; +#endif HANDLE idProcess; LARGE_INTEGER CreateTime; +#ifdef USE_PROCESS_MAP + HASH_MAP thread_map; +#else LIST threads; +#endif } CLIENT_PROCESS; typedef struct tagCLIENT_THREAD { +#ifndef USE_PROCESS_MAP LIST_ELEM list_elem; +#endif HANDLE idThread; BOOLEAN replying; volatile BOOLEAN in_use; @@ -106,8 +114,7 @@ PipeServer *PipeServer::GetPipeServer() m_instance->m_TlsIndex = TlsIndex; - m_instance->m_pool = Pool_Create(); - if (! m_instance->m_pool) { + if (! m_instance->Init()) { delete m_instance; m_instance = NULL; SetLastError(ERROR_NOT_ENOUGH_MEMORY); @@ -128,7 +135,11 @@ PipeServer::PipeServer() { InitializeCriticalSectionAndSpinCount(&m_lock, 1000); List_Init(&m_targets); +#ifdef USE_PROCESS_MAP + map_init(&m_client_map, NULL); +#else List_Init(&m_clients); +#endif m_hServerPort = NULL; @@ -141,6 +152,26 @@ PipeServer::PipeServer() } +//--------------------------------------------------------------------------- +// Initializator +//--------------------------------------------------------------------------- + + +bool PipeServer::Init() +{ + m_instance->m_pool = Pool_Create(); + if (!m_instance->m_pool) + return false; + +#ifdef USE_PROCESS_MAP + m_client_map.mem_pool = m_pool; + map_resize(&m_client_map, 128); // prepare some buckets for better performance +#endif + + return true; +} + + //--------------------------------------------------------------------------- // Destructor //--------------------------------------------------------------------------- @@ -392,27 +423,7 @@ void PipeServer::PortConnect(PORT_MESSAGE *msg) EnterCriticalSection(&m_lock); - clientProcess = (CLIENT_PROCESS *)List_Head(&m_clients); - clientThread = NULL; - - while (clientProcess) { - - if (clientProcess->idProcess == msg->ClientId.UniqueProcess) { - - clientThread = - (CLIENT_THREAD *)List_Head(&clientProcess->threads); - while (clientThread) { - - if (clientThread->idThread == msg->ClientId.UniqueThread) - break; - clientThread = (CLIENT_THREAD *)List_Next(clientThread); - } - - break; - } - - clientProcess = (CLIENT_PROCESS *)List_Next(clientProcess); - } + PortFindClientUnsafe(msg->ClientId, clientProcess, clientThread); // // create new process and thread structures where needed @@ -425,8 +436,15 @@ void PipeServer::PortConnect(PORT_MESSAGE *msg) if (clientProcess) { clientProcess->idProcess = msg->ClientId.UniqueProcess; +#ifdef USE_PROCESS_MAP + map_init(&clientProcess->thread_map, m_pool); + map_resize(&clientProcess->thread_map, 16); // prepare some buckets for better performance + + map_insert(&m_client_map, msg->ClientId.UniqueProcess, clientProcess, 0); +#else List_Init(&clientProcess->threads); List_Insert_After(&m_clients, NULL, clientProcess); +#endif // // prepare for the case where a disconnect message only @@ -465,17 +483,20 @@ void PipeServer::PortConnect(PORT_MESSAGE *msg) memset(clientThread, 0, sizeof(CLIENT_THREAD)); clientThread->idThread = msg->ClientId.UniqueThread; +#ifdef USE_PROCESS_MAP + map_insert(&clientProcess->thread_map, msg->ClientId.UniqueThread, clientThread, 0); +#else List_Insert_After(&clientProcess->threads, NULL, clientThread); +#endif } } // // if we couldn't create a new connection (not enough memory) - // or if a previous connection was found, - // then reject the new connection + // reject the new connection // - if ((! clientThread) || clientThread->hPort) { + if (! clientThread) { HANDLE hPort; NtAcceptConnectPort(&hPort, NULL, msg, FALSE, NULL, NULL); @@ -485,6 +506,27 @@ void PipeServer::PortConnect(PORT_MESSAGE *msg) return; } + // + // if a previous connection was found, close it + // + + if (clientThread->hPort) { + + while (clientThread->in_use) + Sleep(3); + + NtClose(clientThread->hPort); + if (clientThread->buf_hdr) + FreeMsg(clientThread->buf_hdr); + + clientThread->replying = FALSE; + clientThread->in_use = FALSE; + clientThread->sequence = 0; + clientThread->hPort = NULL; + clientThread->buf_hdr = NULL; + clientThread->buf_ptr = NULL; + } + // // if a new client structure was created, accept the connection // @@ -499,6 +541,49 @@ void PipeServer::PortConnect(PORT_MESSAGE *msg) } +//--------------------------------------------------------------------------- +// PortDisconnectHelper +//--------------------------------------------------------------------------- + +void PipeServer::PortDisconnectHelper(CLIENT_PROCESS *clientProcess, CLIENT_THREAD *clientThread) +{ + if (!clientProcess) + return; + + if (clientThread) { + + while (clientThread->in_use) + Sleep(3); + +#ifdef USE_PROCESS_MAP + map_remove(&clientProcess->thread_map, clientThread->idThread); +#else + List_Remove(&clientProcess->threads, clientThread); +#endif + NtClose(clientThread->hPort); + if (clientThread->buf_hdr) + FreeMsg(clientThread->buf_hdr); + Pool_Free(clientThread, sizeof(CLIENT_THREAD)); + } + + +#ifdef USE_PROCESS_MAP + if (clientProcess->thread_map.nnodes == 0) { +#else + if (! List_Head(&clientProcess->threads)) { +#endif + + NotifyTargets(clientProcess->idProcess); + +#ifdef USE_PROCESS_MAP + map_remove(&m_client_map, clientProcess->idProcess); +#else + List_Remove(&m_clients, clientProcess); +#endif + Pool_Free(clientProcess, sizeof(CLIENT_PROCESS)); + } +} + //--------------------------------------------------------------------------- // PortDisconnect //--------------------------------------------------------------------------- @@ -530,46 +615,9 @@ void PipeServer::PortDisconnect(PORT_MESSAGE *msg) EnterCriticalSection(&m_lock); - clientProcess = (CLIENT_PROCESS *)List_Head(&m_clients); - clientThread = NULL; + PortFindClientUnsafe(msg->ClientId, clientProcess, clientThread); - while (clientProcess) { - - if (clientProcess->idProcess == msg->ClientId.UniqueProcess) { - - clientThread = - (CLIENT_THREAD *)List_Head(&clientProcess->threads); - while (clientThread) { - - if (clientThread->idThread == msg->ClientId.UniqueThread) { - - while (clientThread->in_use) - Sleep(3); - - List_Remove(&clientProcess->threads, clientThread); - NtClose(clientThread->hPort); - if (clientThread->buf_hdr) - FreeMsg(clientThread->buf_hdr); - Pool_Free(clientThread, sizeof(CLIENT_THREAD)); - break; - } - - clientThread = (CLIENT_THREAD *)List_Next(clientThread); - } - - if (! List_Head(&clientProcess->threads)) { - - NotifyTargets(clientProcess->idProcess); - - List_Remove(&m_clients, clientProcess); - Pool_Free(clientProcess, sizeof(CLIENT_PROCESS)); - } - - break; - } - - clientProcess = (CLIENT_PROCESS *)List_Next(clientProcess); - } + PortDisconnectHelper(clientProcess, clientThread); LeaveCriticalSection(&m_lock); } @@ -613,17 +661,31 @@ void PipeServer::PortDisconnectByCreateTime(LARGE_INTEGER *CreateTime) EnterCriticalSection(&m_lock); - CLIENT_PROCESS *clientProcess = (CLIENT_PROCESS *)List_Head(&m_clients); + CLIENT_PROCESS *clientProcess = NULL; + CLIENT_THREAD *clientThread = NULL; +#ifdef USE_PROCESS_MAP + map_iter_t iter = map_iter(); + while (map_next(&m_client_map, &iter)) { + + clientProcess = (CLIENT_PROCESS *)iter.value; +#else + clientProcess = (CLIENT_PROCESS *)List_Head(&m_clients); while (clientProcess) { - +#endif if (clientProcess->CreateTime.HighPart == CreateTime->HighPart && clientProcess->CreateTime.LowPart == CreateTime->LowPart) { - CLIENT_THREAD *clientThread = - (CLIENT_THREAD *)List_Head(&clientProcess->threads); - while (clientThread) { +#ifdef USE_PROCESS_MAP + map_iter_t sub_iter = map_iter(); + while (map_next(&clientProcess->thread_map, &sub_iter)) { + clientThread = (CLIENT_THREAD *)sub_iter.value; +#else + clientThread = (CLIENT_THREAD *)List_Head(&clientProcess->threads); + + while (clientThread) { +#endif // // for each thread in the process, assume it is stale, // unless we can open it, and it still has the same @@ -642,36 +704,35 @@ void PipeServer::PortDisconnectByCreateTime(LARGE_INTEGER *CreateTime) CloseHandle(hThread); } + // + // fix-me: when closing the port without waiting some ms after the + // thread terminated this fails and the client object is not cleared + // + if (DeleteThread) { - while (clientThread->in_use) - Sleep(3); - - List_Remove(&clientProcess->threads, clientThread); - NtClose(clientThread->hPort); - if (clientThread->buf_hdr) - FreeMsg(clientThread->buf_hdr); - Pool_Free(clientThread, sizeof(CLIENT_THREAD)); break; } +#ifndef USE_PROCESS_MAP clientThread = (CLIENT_THREAD *)List_Next(clientThread); - } - - if (! List_Head(&clientProcess->threads)) { - - NotifyTargets(clientProcess->idProcess); - - List_Remove(&m_clients, clientProcess); - Pool_Free(clientProcess, sizeof(CLIENT_PROCESS)); +#else + clientThread = NULL; +#endif } break; } +#ifndef USE_PROCESS_MAP clientProcess = (CLIENT_PROCESS *)List_Next(clientProcess); +#else + clientProcess = NULL; +#endif } + PortDisconnectHelper(clientProcess, clientThread); + LeaveCriticalSection(&m_lock); } @@ -742,6 +803,45 @@ finish: } +//--------------------------------------------------------------------------- +// PortFindClientUnsafe +//--------------------------------------------------------------------------- + + +void PipeServer::PortFindClientUnsafe(const CLIENT_ID& ClientId, CLIENT_PROCESS *&clientProcess, CLIENT_THREAD *&clientThread) +{ + // + // Note: this is not thread safe, you must lock m_lock before calling this function + // + +#ifdef USE_PROCESS_MAP + clientProcess = (CLIENT_PROCESS *)map_get(&m_client_map, ClientId.UniqueProcess); + clientThread = clientProcess ? (CLIENT_THREAD *)map_get(&clientProcess->thread_map, ClientId.UniqueThread) : NULL; +#else + clientProcess = (CLIENT_PROCESS *)List_Head(&m_clients); + + while (clientProcess) { + + if (clientProcess->idProcess == ClientId.UniqueProcess) { + + clientThread = + (CLIENT_THREAD *)List_Head(&clientProcess->threads); + while (clientThread) { + + if (clientThread->idThread == ClientId.UniqueThread) + break; + clientThread = (CLIENT_THREAD *)List_Next(clientThread); + } + + break; + } + + clientProcess = (CLIENT_PROCESS *)List_Next(clientProcess); + } +#endif +} + + //--------------------------------------------------------------------------- // PortFindClient //--------------------------------------------------------------------------- @@ -754,27 +854,7 @@ void *PipeServer::PortFindClient(PORT_MESSAGE *msg) EnterCriticalSection(&m_lock); - clientProcess = (CLIENT_PROCESS *)List_Head(&m_clients); - clientThread = NULL; - - while (clientProcess) { - - if (clientProcess->idProcess == msg->ClientId.UniqueProcess) { - - clientThread = - (CLIENT_THREAD *)List_Head(&clientProcess->threads); - while (clientThread) { - - if (clientThread->idThread == msg->ClientId.UniqueThread) - break; - clientThread = (CLIENT_THREAD *)List_Next(clientThread); - } - - break; - } - - clientProcess = (CLIENT_PROCESS *)List_Next(clientProcess); - } + PortFindClientUnsafe(msg->ClientId, clientProcess, clientThread); if (clientThread) clientThread->in_use = TRUE; @@ -1048,3 +1128,33 @@ MSG_HEADER *PipeServer::Call(MSG_HEADER *msg) return msg_out; } + + +//--------------------------------------------------------------------------- +// IsCallerSigned +//--------------------------------------------------------------------------- + +extern "C" { + NTSTATUS VerifyFileSignature(const wchar_t* FilePath); +} + +bool PipeServer::IsCallerSigned() +{ + CLIENT_TLS_DATA *TlsData = + (CLIENT_TLS_DATA *)TlsGetValue(m_instance->m_TlsIndex); + + NTSTATUS status = STATUS_UNSUCCESSFUL; + + ULONG processId = (ULONG)(ULONG_PTR)TlsData->PortMessage->ClientId.UniqueProcess; + HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId); + if (processHandle != NULL) { + TCHAR fileName[MAX_PATH]; + if (GetModuleFileNameEx(processHandle, NULL, fileName, MAX_PATH)) { + + status = VerifyFileSignature(fileName); + } + CloseHandle(processHandle); + } + + return NT_SUCCESS(status); +} \ No newline at end of file diff --git a/Sandboxie/core/svc/PipeServer.h b/Sandboxie/core/svc/PipeServer.h index 8b74cc0e..2aa7c8bc 100644 --- a/Sandboxie/core/svc/PipeServer.h +++ b/Sandboxie/core/svc/PipeServer.h @@ -27,9 +27,11 @@ #include #include "common/win32_ntddk.h" #include "common/list.h" +#include "common/map.h" #include "common/pool.h" #include "msgids.h" +#define USE_PROCESS_MAP /* Recommended maximum length for any single element in a request packet. */ @@ -128,6 +130,12 @@ public: MSG_HEADER *Call(MSG_HEADER *msg); + /* + * Checks if the calling process has a valid signature + */ + + static bool IsCallerSigned(); + protected: /* @@ -136,6 +144,12 @@ protected: PipeServer(); + /* + * Private initializator + */ + + bool Init(); + /* * Static wrapper for thread function */ @@ -200,8 +214,16 @@ protected: protected: + void PortDisconnectHelper(struct tagCLIENT_PROCESS* clientProcess, struct tagCLIENT_THREAD* clientThread); + + void PortFindClientUnsafe(const CLIENT_ID& ClientId, struct tagCLIENT_PROCESS *&clientProcess, struct tagCLIENT_THREAD *&clientThread); + LIST m_targets; +#ifdef USE_PROCESS_MAP + HASH_MAP m_client_map; +#else LIST m_clients; +#endif CRITICAL_SECTION m_lock; POOL *m_pool; ULONG m_TlsIndex; diff --git a/Sandboxie/core/svc/ProcessServer.cpp b/Sandboxie/core/svc/ProcessServer.cpp index 6b060c9b..db4d3b0a 100644 --- a/Sandboxie/core/svc/ProcessServer.cpp +++ b/Sandboxie/core/svc/ProcessServer.cpp @@ -26,6 +26,8 @@ #include "ProcessServer.h" #include "Processwire.h" #include "DriverAssist.h" +#include "GuiServer.h" +#include "GuiWire.h" #include "misc.h" #include "common/defines.h" #include "common/my_version.h" @@ -203,6 +205,7 @@ MSG_HEADER *ProcessServer::KillAllHandler( WCHAR TargetBoxName[48]; ULONG CallerSessionId; WCHAR CallerBoxName[48]; + BOOLEAN TerminateJob; NTSTATUS status; // @@ -234,6 +237,11 @@ MSG_HEADER *ProcessServer::KillAllHandler( } else if (status != STATUS_SUCCESS) return SHORT_REPLY(status); + if (status != STATUS_INVALID_CID) // if this is true the caller is boxed, should be rpcss + TerminateJob = FALSE; // if rpcss requests box termination, don't use the job method, fix-me: we get some stuck request in the queue + else + TerminateJob = !SbieApi_QueryConfBool(TargetBoxName, L"NoAddProcessToJob", FALSE); + // // match session id and box name // @@ -250,7 +258,7 @@ MSG_HEADER *ProcessServer::KillAllHandler( // kill target processes // - status = KillAllHelper(TargetBoxName, TargetSessionId); + status = KillAllHelper(TargetBoxName, TargetSessionId, TerminateJob); return SHORT_REPLY(status); } @@ -261,20 +269,45 @@ MSG_HEADER *ProcessServer::KillAllHandler( //--------------------------------------------------------------------------- -NTSTATUS ProcessServer::KillAllHelper(const WCHAR *BoxName, ULONG SessionId) +NTSTATUS ProcessServer::KillAllHelper(const WCHAR *BoxName, ULONG SessionId, BOOLEAN TerminateJob) { NTSTATUS status; ULONG retries, i; - ULONG pids[512]; + const ULONG pids_len = 512; + ULONG pids[pids_len]; + ULONG count; - for (retries = 0; retries < 10; ++retries) { + if (TerminateJob) { - status = SbieApi_EnumProcessEx(BoxName, FALSE, SessionId, pids, NULL); + // + // try killing the entire job in one go first + // + + GUI_KILL_JOB_REQ data; + data.msgid = GUI_KILL_JOB; + if (BoxName) wcscpy(data.boxname, BoxName); + else data.boxname[0] = L'\0'; + + GuiServer::GetInstance()->SendMessageToSlave(SessionId, &data, sizeof(data)); + + // + // as fallback and for the case where jobs are not used run the manual termination + // + } + + + for (retries = 0; retries < 10; ) { + + count = pids_len; + status = SbieApi_EnumProcessEx(BoxName, FALSE, SessionId, pids, &count); if (status != STATUS_SUCCESS) break; - if (! pids[0]) + if (count == 0) break; + if (count < pids_len) + retries++; + if (retries) { if (retries >= 10 - 1) { status = STATUS_UNSUCCESSFUL; @@ -283,7 +316,7 @@ NTSTATUS ProcessServer::KillAllHelper(const WCHAR *BoxName, ULONG SessionId) Sleep(100); } - for (i = 1; i <= pids[0]; ++i) + for (i = 0; i <= count; ++i) KillProcess(pids[i]); } diff --git a/Sandboxie/core/svc/ProcessServer.h b/Sandboxie/core/svc/ProcessServer.h index 09259d45..1985a36d 100644 --- a/Sandboxie/core/svc/ProcessServer.h +++ b/Sandboxie/core/svc/ProcessServer.h @@ -51,7 +51,7 @@ protected: MSG_HEADER *KillAllHandler(HANDLE CallerProcessId, MSG_HEADER *msg); - NTSTATUS KillAllHelper(const WCHAR *BoxName, ULONG SessionId); + NTSTATUS KillAllHelper(const WCHAR *BoxName, ULONG SessionId, BOOLEAN TerminateJob = FALSE); MSG_HEADER *SetDeviceMap(HANDLE CallerProcessId, MSG_HEADER *msg); diff --git a/Sandboxie/core/svc/SboxSvc.vcxproj b/Sandboxie/core/svc/SboxSvc.vcxproj index 151b046c..23737b66 100644 --- a/Sandboxie/core/svc/SboxSvc.vcxproj +++ b/Sandboxie/core/svc/SboxSvc.vcxproj @@ -100,7 +100,7 @@ true - SbieDll.lib;ntdll.lib;kernel32.lib;user32.lib;Advapi32.lib;psapi.lib;Ole32.lib;crypt32.lib;Secur32.lib;Userenv.lib;Gdi32.lib;Netapi32.lib;wtsapi32.lib;rpcrt4.lib + SbieDll.lib;ntdll.lib;kernel32.lib;user32.lib;Advapi32.lib;psapi.lib;Ole32.lib;crypt32.lib;Secur32.lib;Userenv.lib;Gdi32.lib;Netapi32.lib;wtsapi32.lib;rpcrt4.lib;bcrypt.lib @@ -116,7 +116,7 @@ true - SbieDll.lib;ntdll.lib;kernel32.lib;user32.lib;Advapi32.lib;psapi.lib;Ole32.lib;crypt32.lib;Secur32.lib;Userenv.lib;Gdi32.lib;Netapi32.lib;wtsapi32.lib;rpcrt4.lib + SbieDll.lib;ntdll.lib;kernel32.lib;user32.lib;Advapi32.lib;psapi.lib;Ole32.lib;crypt32.lib;Secur32.lib;Userenv.lib;Gdi32.lib;Netapi32.lib;wtsapi32.lib;rpcrt4.lib;bcrypt.lib @@ -131,7 +131,7 @@ true - SbieDll.lib;ntdll.lib;kernel32.lib;user32.lib;Advapi32.lib;psapi.lib;Ole32.lib;crypt32.lib;Secur32.lib;Userenv.lib;Gdi32.lib;Netapi32.lib;wtsapi32.lib;rpcrt4.lib + SbieDll.lib;ntdll.lib;kernel32.lib;user32.lib;Advapi32.lib;psapi.lib;Ole32.lib;crypt32.lib;Secur32.lib;Userenv.lib;Gdi32.lib;Netapi32.lib;wtsapi32.lib;rpcrt4.lib;bcrypt.lib @@ -146,7 +146,7 @@ true - SbieDll.lib;ntdll.lib;kernel32.lib;user32.lib;Advapi32.lib;psapi.lib;Ole32.lib;crypt32.lib;Secur32.lib;Userenv.lib;Gdi32.lib;Netapi32.lib;wtsapi32.lib;rpcrt4.lib + SbieDll.lib;ntdll.lib;kernel32.lib;user32.lib;Advapi32.lib;psapi.lib;Ole32.lib;crypt32.lib;Secur32.lib;Userenv.lib;Gdi32.lib;Netapi32.lib;wtsapi32.lib;rpcrt4.lib;bcrypt.lib @@ -161,12 +161,40 @@ true true + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + true true true true + + NotUsing + NotUsing + NotUsing + NotUsing + true + true + true + true + NotUsing @@ -240,6 +268,30 @@ + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + diff --git a/Sandboxie/core/svc/SboxSvc.vcxproj.filters b/Sandboxie/core/svc/SboxSvc.vcxproj.filters index 88eaff7e..96df950b 100644 --- a/Sandboxie/core/svc/SboxSvc.vcxproj.filters +++ b/Sandboxie/core/svc/SboxSvc.vcxproj.filters @@ -54,6 +54,18 @@ + + common + + + common + + + common + + + common + @@ -102,6 +114,18 @@ + + common + + + common + + + common + + + common + diff --git a/Sandboxie/core/svc/includes.cpp b/Sandboxie/core/svc/includes.cpp index b0d1a6e6..3059977a 100644 --- a/Sandboxie/core/svc/includes.cpp +++ b/Sandboxie/core/svc/includes.cpp @@ -34,12 +34,16 @@ extern "C" { #include "common/pool.c" +#include "common/map.c" + #define CRC_WITH_ADLER32 #include "common/crc.c" #define PATTERN XPATTERN #include "common/pattern.c" +#include "common/verify.c" + #ifdef __cplusplus } // extern "C" #endif diff --git a/Sandboxie/core/svc/sbieiniserver.cpp b/Sandboxie/core/svc/sbieiniserver.cpp index bf7fe6bf..2e236ad4 100644 --- a/Sandboxie/core/svc/sbieiniserver.cpp +++ b/Sandboxie/core/svc/sbieiniserver.cpp @@ -654,6 +654,15 @@ ULONG SbieIniServer::IsCallerAuthorized(HANDLE hToken, const WCHAR *Password) { WCHAR buf[42], buf2[42]; + // + // check for valid image signature + // + + if (!PipeServer::IsCallerSigned()) { + CloseHandle(hToken); + return STATUS_INVALID_SIGNATURE; + } + // // check for Administrator-only access // diff --git a/Sandboxie/msgs/parse.c b/Sandboxie/msgs/parse.c index b53262c6..f566456e 100644 --- a/Sandboxie/msgs/parse.c +++ b/Sandboxie/msgs/parse.c @@ -285,8 +285,8 @@ void ReadTextFile(const UCHAR *path, LIST *msgs) { char* utf8 = BufPtr; - ByteSize *= 2; - Buffer = Alloc(ByteSize + 16); + ByteSize = MultiByteToWideChar(CP_UTF8, 0, utf8, ReadSize, NULL, 0) + 1; + Buffer = Alloc(ByteSize * sizeof(wchar_t)); BufPtr = Buffer; MultiByteToWideChar(CP_UTF8, 0, utf8, ReadSize, BufPtr, ByteSize); diff --git a/SandboxiePlus/QSbieAPI/Sandboxie/BoxedProcess.cpp b/SandboxiePlus/QSbieAPI/Sandboxie/BoxedProcess.cpp index 58e895f7..8fce6bcb 100644 --- a/SandboxiePlus/QSbieAPI/Sandboxie/BoxedProcess.cpp +++ b/SandboxiePlus/QSbieAPI/Sandboxie/BoxedProcess.cpp @@ -208,7 +208,7 @@ bool CBoxedProcess::InitProcessInfo() bool CBoxedProcess::InitProcessInfoEx() { - if(m_ImageType == -1) + if(m_ImageType == -1 && m_pBox) m_ImageType = m_pBox->Api()->GetImageType(m_ProcessId); return true; @@ -306,8 +306,3 @@ bool CBoxedProcess::IsSuspended() const return isSuspended; } */ - -QString CBoxedProcess::GetBoxName() const -{ - return m_pBox->GetName(); -} diff --git a/SandboxiePlus/QSbieAPI/Sandboxie/BoxedProcess.h b/SandboxiePlus/QSbieAPI/Sandboxie/BoxedProcess.h index 13bfffe9..b0d21de8 100644 --- a/SandboxiePlus/QSbieAPI/Sandboxie/BoxedProcess.h +++ b/SandboxiePlus/QSbieAPI/Sandboxie/BoxedProcess.h @@ -49,13 +49,14 @@ public: virtual bool IsWoW64() const { return m_bIsWoW64; } - virtual QString GetBoxName() const; + virtual QString GetBoxName() const { return m_BoxName; } virtual class CSandBox* GetBoxPtr() const { return m_pBox; } protected: friend class CSbieAPI; quint32 m_ProcessId; + QString m_BoxName; quint32 m_ParendPID; QString m_ImageName; QString m_ImagePath; diff --git a/SandboxiePlus/QSbieAPI/Sandboxie/SandBox.cpp b/SandboxiePlus/QSbieAPI/Sandboxie/SandBox.cpp index 6b3cb5cb..cfc2a221 100644 --- a/SandboxiePlus/QSbieAPI/Sandboxie/SandBox.cpp +++ b/SandboxiePlus/QSbieAPI/Sandboxie/SandBox.cpp @@ -182,7 +182,13 @@ void CSandBox::CleanBoxAsync(const CSbieProgressPtr& pProgress, const QStringLis foreach(const QString& Folder, BoxFolders) { - Status = CSandBox__DeleteFolder(pProgress, Folder); + for (int i = 0; i < 10; i++) { + Status = CSandBox__DeleteFolder(pProgress, Folder); + if (!Status.IsError()) + break; + QThread::sleep(1); // wait a second + } + if (Status.IsError()) break; } diff --git a/SandboxiePlus/QSbieAPI/SbieAPI.cpp b/SandboxiePlus/QSbieAPI/SbieAPI.cpp index 0dabba86..d6c36848 100644 --- a/SandboxiePlus/QSbieAPI/SbieAPI.cpp +++ b/SandboxiePlus/QSbieAPI/SbieAPI.cpp @@ -330,6 +330,9 @@ SB_STATUS CSbieAPI::Disconnect() m->SbieApiHandle = INVALID_HANDLE_VALUE; } + // ensure the client thread is enteirly terminated to avoid the service keeping the reference + // see SbieSvc PortDisconnectByCreateTime + QThread::msleep(250); if (m->PortHandle) { NtClose(m->PortHandle); m->PortHandle = NULL; @@ -690,7 +693,10 @@ SB_STATUS CSbieAPI::CallServer(void* req, void* rpl) const { // // Note: Once we open a port to the server from a threat the service will remember it we can't reconnect after disconnection - // So for every new connection we need a new threat, we achive this by letting our monitor threat issue all requests + // So for every new connection we need a new threat, we achieve this by letting our monitor threat issue all requests + // + // As of Sbie build 5.50.5 the SbieCvc properly handles reconnection attempts so this mechanism is no longer necessary + // Howeever for the queue mechanism we need the communication to be still handled by the helper thread // while (InterlockedCompareExchange(&m->SvcLock, SVC_OP_STATE_PREP, SVC_OP_STATE_IDLE) != SVC_OP_STATE_IDLE) @@ -935,7 +941,7 @@ QString CSbieAPI::GetIniPath(bool* IsHome) const req.h.length = sizeof(SBIE_INI_GET_PATH_REQ); SBIE_INI_GET_PATH_RPL *rpl = NULL; - SB_STATUS Status = CSbieAPI::CallServer(&req.h, &rpl); + SB_STATUS Status = CallServer(&req.h, &rpl); if (!Status || !rpl) return QString(); if (rpl->h.status == 0) { @@ -957,7 +963,7 @@ QString CSbieAPI::GetUserSection(QString* pUserName, bool* pIsAdmin) const req.h.length = sizeof(SBIE_INI_GET_USER_REQ); SBIE_INI_GET_USER_RPL *rpl = NULL; - SB_STATUS Status = CSbieAPI::CallServer(&req.h, &rpl); + SB_STATUS Status = CallServer(&req.h, &rpl); if (!Status || !rpl) return QString(); @@ -986,7 +992,7 @@ SB_STATUS CSbieAPI::RunStart(const QString& BoxName, const QString& Command, QPr QString CSbieAPI::GetStartPath() const { - return m_SbiePath + "//" + QString::fromWCharArray(SBIESTART_EXE); + return m_SbiePath + "\\" + QString::fromWCharArray(SBIESTART_EXE); } SB_STATUS CSbieAPI::ReloadBoxes(bool bFullUpdate) @@ -1024,6 +1030,24 @@ SB_STATUS CSbieAPI::ReloadBoxes(bool bFullUpdate) return SB_OK; } +QString CSbieAPI__FormatNtStatus(NTSTATUS nsCode) +{ + static HMODULE hNtDll = NULL; + if(!hNtDll) + hNtDll = GetModuleHandle(L"ntdll.dll"); + if (hNtDll == NULL) + return "???"; + + WCHAR* ret_str = NULL; + DWORD dwRes = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, + hNtDll, RtlNtStatusToDosError(nsCode), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&ret_str, 0, NULL); + + QString qStr = QString::fromWCharArray(ret_str); + LocalFree(ret_str); + return qStr; +} + SB_STATUS CSbieAPI::SbieIniSet(void *RequestBuf, void *pPasswordWithinRequestBuf, const QString& SectionName, const QString& SettingName) { retry: @@ -1031,7 +1055,7 @@ retry: ((WCHAR*)pPasswordWithinRequestBuf)[m->Password.length()] = L'\0'; MSG_HEADER *rpl = NULL; - SB_STATUS Status = CSbieAPI::CallServer((MSG_HEADER *)RequestBuf, &rpl); + SB_STATUS Status = CallServer((MSG_HEADER *)RequestBuf, &rpl); SecureZeroMemory(pPasswordWithinRequestBuf, sizeof(WCHAR) * 64); if (!Status || !rpl) return Status; @@ -1050,7 +1074,7 @@ retry: } return SB_ERR(SB_NotAuthorized, QVariantList() << SectionName, status); } - return SB_ERR(SB_ConfigFailed, QVariantList() << SettingName << SectionName << (quint32)status, status); + return SB_ERR(SB_ConfigFailed, QVariantList() << SettingName << SectionName << CSbieAPI__FormatNtStatus(status), status); } SB_STATUS CSbieAPI::SbieIniSet(const QString& Section, const QString& Setting, const QString& Value, ESetMode Mode) @@ -1118,6 +1142,18 @@ SB_STATUS CSbieAPI::ValidateName(const QString& BoxName) if (BoxName.length() > 32) return SB_ERR(SB_NameLenLimit); + /* invalid file name charakters on windows + < (less than) + > (greater than) + : (colon - sometimes works, but is actually NTFS Alternate Data Streams) + " (double quote) + / (forward slash) + \ (backslash) + | (vertical bar or pipe) + ? (question mark) + * (asterisk) + */ + QStringList DeviceNames = QStringList() << "aux" << "clock$" << "con" << "nul" << "prn" << "com1" << "com2" << "com3" << "com4" << "com5" << "com6" << "com7" << "com8" << "com9" << "com0" << @@ -1154,13 +1190,6 @@ SB_STATUS CSbieAPI::CreateBox(const QString& BoxName) return Status; } -SB_STATUS CSbieAPI::UpdateProcesses(bool bKeep) -{ - foreach(const CSandBoxPtr& pBox, m_SandBoxes) - UpdateProcesses(bKeep, pBox); - return SB_OK; -} - SB_STATUS CSbieAPI__GetProcessPIDs(SSbieAPI* m, const QString& BoxName, ULONG* pids, ULONG* count) { WCHAR box_name[34]; @@ -1185,14 +1214,94 @@ SB_STATUS CSbieAPI__GetProcessPIDs(SSbieAPI* m, const QString& BoxName, ULONG* p return SB_OK; } +SB_STATUS CSbieAPI::UpdateProcesses(bool bKeep) +{ + ULONG count = 0; + SB_STATUS Status = CSbieAPI__GetProcessPIDs(m, "", NULL, &count); // query the count + if (Status.IsError()) + + count += 128; // add some extra space + ULONG* boxed_pids = new ULONG[count]; + + Status = CSbieAPI__GetProcessPIDs(m, "", boxed_pids, &count); // query the count + if (Status.IsError()) { + delete[] boxed_pids; + return Status; + } + + QMap OldProcessList; + foreach(const CSandBoxPtr& pBox, m_SandBoxes) + OldProcessList.insert(pBox->m_ProcessList); + + for (int i=0; i < count; i++) + { + quint32 ProcessId = (quint32)boxed_pids[i]; + + CBoxedProcessPtr pProcess = OldProcessList.take(ProcessId); + if (!pProcess) + { + pProcess = CBoxedProcessPtr(NewBoxedProcess(ProcessId, NULL)); + UpdateProcessInfo(pProcess); + + CSandBoxPtr pBox = GetBoxByName(pProcess->GetBoxName()); + if (pBox.isNull()) + continue; + + pProcess->m_pBox = pBox.data(); + pBox->m_ProcessList.insert(ProcessId, pProcess); + m_BoxedProxesses.insert(ProcessId, pProcess); + + pProcess->InitProcessInfo(); + } + + pProcess->InitProcessInfoEx(); + } + + foreach(const CBoxedProcessPtr& pProcess, OldProcessList) + { + if (!pProcess->IsTerminated()) + pProcess->SetTerminated(); + else if (!bKeep && pProcess->IsTerminated(1500)) { // keep for at least 1.5 seconds + pProcess->m_pBox->m_ProcessList.remove(pProcess->m_ProcessId); + m_BoxedProxesses.remove(pProcess->m_ProcessId); + } + } + + foreach(const CSandBoxPtr& pBox, m_SandBoxes) + { + bool WasBoxClosed = pBox->m_ActiveProcessCount > 0 && count == 0; + pBox->m_ActiveProcessCount = count; + if (WasBoxClosed) { + pBox->CloseBox(); + emit BoxClosed(pBox->GetName()); + } + } + + delete[] boxed_pids; + return SB_OK; +} + +/*SB_STATUS CSbieAPI::UpdateProcesses(bool bKeep) +{ + foreach(const CSandBoxPtr& pBox, m_SandBoxes) + UpdateProcesses(bKeep, pBox); + return SB_OK; +} + SB_STATUS CSbieAPI::UpdateProcesses(bool bKeep, const CSandBoxPtr& pBox) { - ULONG count = 1024; - ULONG boxed_pids[1024]; // ULONG [512] - SB_STATUS Status = CSbieAPI__GetProcessPIDs(m, pBox->GetName(), boxed_pids, &count); + ULONG count = 0; + SB_STATUS Status = CSbieAPI__GetProcessPIDs(m, pBox->GetName(), NULL, &count); // query the count if (Status.IsError()) return Status; + count += 128; // add some extra space + ULONG* boxed_pids = new ULONG[count]; + + Status = CSbieAPI__GetProcessPIDs(m, pBox->GetName(), boxed_pids, &count); // query the count + if (Status.IsError()) + goto finish; + QMap OldProcessList = pBox->m_ProcessList; for (int i=0; i < count; i++) @@ -1230,8 +1339,10 @@ SB_STATUS CSbieAPI::UpdateProcesses(bool bKeep, const CSandBoxPtr& pBox) emit BoxClosed(pBox->GetName()); } - return SB_OK; -} +finish: + delete[] boxed_pids; + return Status; +}*/ bool CSbieAPI::HasProcesses(const QString& BoxName) { @@ -1296,13 +1407,13 @@ SB_STATUS CSbieAPI::UpdateBoxPaths(const CSandBoxPtr& pSandBox) SB_STATUS CSbieAPI::UpdateProcessInfo(const CBoxedProcessPtr& pProcess) { - //WCHAR box_name_wchar34[34] = { 0 }; + WCHAR box_name[34] = { 0 }; WCHAR image_name[MAX_PATH]; //WCHAR sid[96]; ULONG session_id; ULONG64 create_time; - //__declspec(align(8)) UNICODE_STRING64 BoxName = { 0, sizeof(box_name_wchar34) , (ULONG64)box_name_wchar34 }; + __declspec(align(8)) UNICODE_STRING64 BoxName = { 0, sizeof(box_name) , (ULONG64)box_name }; __declspec(align(8)) UNICODE_STRING64 ImageName = { 0, sizeof(image_name), (ULONG64)image_name }; //__declspec(align(8)) UNICODE_STRING64 SidString = { 0, sizeof(sid), (ULONG64)sid }; __declspec(align(8)) ULONG64 parms[API_NUM_ARGS]; @@ -1311,7 +1422,7 @@ SB_STATUS CSbieAPI::UpdateProcessInfo(const CBoxedProcessPtr& pProcess) memset(parms, 0, sizeof(parms)); args->func_code = API_QUERY_PROCESS; args->process_id.val64 = (ULONG64)pProcess->m_ProcessId; - //args->box_name.val64 = (ULONG64)&BoxName; + args->box_name.val64 = (ULONG64)&BoxName; args->image_name.val64 = (ULONG64)&ImageName; //args->sid_string.val64 = (ULONG64)&SidString; args->session_id.val64 = (ULONG64)&session_id; @@ -1321,6 +1432,7 @@ SB_STATUS CSbieAPI::UpdateProcessInfo(const CBoxedProcessPtr& pProcess) if(!NT_SUCCESS(status)) return SB_ERR(status); + pProcess->m_BoxName = QString::fromWCharArray(box_name); pProcess->m_ImageName = QString::fromWCharArray(image_name, ImageName.Length/sizeof(WCHAR)); pProcess->m_SessionId = session_id; pProcess->m_StartTime = QDateTime::fromMSecsSinceEpoch(FILETIME2ms(create_time)); @@ -1334,7 +1446,7 @@ CSandBoxPtr CSbieAPI::GetBoxByProcessId(quint32 ProcessId) const CBoxedProcessPtr pProcess = m_BoxedProxesses.value(ProcessId); if (!pProcess) return CSandBoxPtr(); - return m_SandBoxes.value(pProcess->GetBoxName().toLower()); + return GetBoxByName(pProcess->GetBoxName()); } CBoxedProcessPtr CSbieAPI::GetProcessById(quint32 ProcessId) const @@ -1372,7 +1484,7 @@ SB_STATUS CSbieAPI::TerminateAll(const QString& BoxName) req.boxname[BoxName.size()] = L'\0'; MSG_HEADER *rpl = NULL; - SB_STATUS Status = CSbieAPI::CallServer(&req.h, &rpl); + SB_STATUS Status = CallServer(&req.h, &rpl); if (!Status || !rpl) return Status; if(rpl->status != 0) @@ -1399,7 +1511,7 @@ SB_STATUS CSbieAPI::Terminate(quint32 ProcessId) req.pid = ProcessId; MSG_HEADER *rpl = NULL; - SB_STATUS Status = CSbieAPI::CallServer(&req.h, &rpl); + SB_STATUS Status = CallServer(&req.h, &rpl); if (!Status || !rpl) return Status; if (rpl->status != 0) @@ -1562,7 +1674,7 @@ SB_STATUS CSbieAPI::RunSandboxed(const QString& BoxName, const QString& Command, *ptr++ = L'\0'; PROCESS_RUN_SANDBOXED_RPL *rpl; - SB_STATUS Status = CSbieAPI::CallServer(&req->h, &rpl); + SB_STATUS Status = CallServer(&req->h, &rpl); free(req); if (!Status) return Status; @@ -1789,6 +1901,9 @@ SB_STATUS CSbieAPI::UnlockConfig(const QString& Password) SB_STATUS CSbieAPI::LockConfig(const QString& NewPassword) { + if(NewPassword.length() > 64) + return SB_ERR(SB_PasswordBad, STATUS_INVALID_PARAMETER); + SBIE_INI_PASSWORD_REQ *req = (SBIE_INI_PASSWORD_REQ *)malloc(REQUEST_LEN); req->h.msgid = MSGID_SBIE_INI_SET_PASSWORD; req->h.length = sizeof(SBIE_INI_PASSWORD_REQ); diff --git a/SandboxiePlus/QSbieAPI/SbieAPI.h b/SandboxiePlus/QSbieAPI/SbieAPI.h index c1f938b4..27212e19 100644 --- a/SandboxiePlus/QSbieAPI/SbieAPI.h +++ b/SandboxiePlus/QSbieAPI/SbieAPI.h @@ -60,7 +60,7 @@ public: virtual SB_STATUS CreateBox(const QString& BoxName); virtual SB_STATUS UpdateProcesses(bool bKeep); - virtual SB_STATUS UpdateProcesses(bool bKeep, const CSandBoxPtr& pBox); + //virtual SB_STATUS UpdateProcesses(bool bKeep, const CSandBoxPtr& pBox); virtual QMap GetAllBoxes() { return m_SandBoxes; } diff --git a/SandboxiePlus/QSbieAPI/SbieStatus.h b/SandboxiePlus/QSbieAPI/SbieStatus.h index b558251e..9908a7fa 100644 --- a/SandboxiePlus/QSbieAPI/SbieStatus.h +++ b/SandboxiePlus/QSbieAPI/SbieStatus.h @@ -39,6 +39,7 @@ enum ESbieMsgCodes SB_ConfigFailed, SB_SnapIsEmpty, SB_NameExists, + SB_PasswordBad, }; class CSbieStatus diff --git a/SandboxiePlus/QSbieAPI/SbieUtils.cpp b/SandboxiePlus/QSbieAPI/SbieUtils.cpp index 7da9dbb8..5c172b5e 100644 --- a/SandboxiePlus/QSbieAPI/SbieUtils.cpp +++ b/SandboxiePlus/QSbieAPI/SbieUtils.cpp @@ -220,11 +220,12 @@ bool CSbieUtils::CheckRegValue(const wchar_t* key) return true; } -void CSbieUtils::AddContextMenu(const QString& StartPath) +void CSbieUtils::AddContextMenu(const QString& StartPath, const QString& IconPath) { wstring start_path = L"\"" + StartPath.toStdWString() + L"\""; + wstring icon_path = L"\"" + (IconPath.isEmpty() ? StartPath : IconPath).toStdWString() + L"\""; - CreateShellEntry(L"*", L"Run &Sandboxed", start_path, start_path + L" /box:__ask__ \"%1\" %*"); + CreateShellEntry(L"*", L"Run &Sandboxed", icon_path, start_path + L" /box:__ask__ \"%1\" %*"); wstring explorer_path(512, L'\0'); @@ -249,7 +250,7 @@ void CSbieUtils::AddContextMenu(const QString& StartPath) explorer_path.append(L"\\explorer.exe"); } - CreateShellEntry(L"Folder", L"Explore &Sandboxed", start_path, start_path + L" /box:__ask__ " + explorer_path + L" \"%1\""); + CreateShellEntry(L"Folder", L"Explore &Sandboxed", icon_path, start_path + L" /box:__ask__ " + explorer_path + L" \"%1\""); } void CSbieUtils::CreateShellEntry(const wstring& classname, const wstring& cmdtext, const wstring& iconpath, const wstring& startcmd) diff --git a/SandboxiePlus/QSbieAPI/SbieUtils.h b/SandboxiePlus/QSbieAPI/SbieUtils.h index 279c6166..28087d0f 100644 --- a/SandboxiePlus/QSbieAPI/SbieUtils.h +++ b/SandboxiePlus/QSbieAPI/SbieUtils.h @@ -27,7 +27,7 @@ public: static bool IsInstalled(EComponent Component); static int IsContextMenu(); - static void AddContextMenu(const QString& StartPath); + static void AddContextMenu(const QString& StartPath, const QString& IconPath = QString()); static void RemoveContextMenu(); static bool CreateShortcut(class CSbieAPI* pApi, const QString &LinkPath, const QString &LinkName, const QString &boxname, const QString &arguments, const QString &iconPath = QString(), int iconIndex = 0, const QString &workdir = QString(), bool bRunElevated = false); diff --git a/SandboxiePlus/SandMan/Forms/OptionsWindow.ui b/SandboxiePlus/SandMan/Forms/OptionsWindow.ui index ff845629..479fc366 100644 --- a/SandboxiePlus/SandMan/Forms/OptionsWindow.ui +++ b/SandboxiePlus/SandMan/Forms/OptionsWindow.ui @@ -42,10 +42,10 @@ - QTabWidget::West + QTabWidget::North - 8 + 6 @@ -1527,7 +1527,7 @@ For files access you can use 'Direct All' instead to make it apply to all progra - + Qt::Vertical @@ -1540,13 +1540,6 @@ For files access you can use 'Direct All' instead to make it apply to all progra - - - - Do not start sandboxed services using a system token (recommended) - - - @@ -1554,7 +1547,14 @@ For files access you can use 'Direct All' instead to make it apply to all progra - + + + + Do not start sandboxed services using a system token (recommended) + + + + @@ -1570,10 +1570,17 @@ For files access you can use 'Direct All' instead to make it apply to all progra - - + + - Protect sandboxed SYSTEM processes from unprivileged unsandboxed processes + Force usage of custom dummy Manifest files (legacy behaviour) + + + + + + + Limit access to the emulated service control manager to privileged processes @@ -1590,21 +1597,14 @@ For files access you can use 'Direct All' instead to make it apply to all progra - - + + - Add sandboxed processes to job objects (recommended) + Emulate sandboxed window station for all processes - - - - Force usage of custom dummy Manifest files (legacy behaviour) - - - - + Qt::Horizontal @@ -1617,33 +1617,10 @@ For files access you can use 'Direct All' instead to make it apply to all progra - - - - - 75 - true - - - - Protect the sandbox integrity itself - - - Sandbox protection - - - - - - - Limit access to the emulated service control manager to privileged processes - - - - + - Emulate sandboxed window station for all processes + Allow use of nested job objects (experimental, works on windows 8 and later) @@ -1658,23 +1635,6 @@ For files access you can use 'Direct All' instead to make it apply to all progra - - - - Allow sandboxed programs to Change User Passwords and alike - - - - - - - Various advanced isolation features can break compatibility, with some applications, if you are using this sandbox <b>NOT for Security</b> but for simple application portability by changing these options you can restore compatibility by sacrificing some security.<br>These options can be used securely when you don't grant any of the sandboxed process admin rights. - - - true - - - @@ -1682,7 +1642,21 @@ For files access you can use 'Direct All' instead to make it apply to all progra - + + + + Open access to Windows Security Account Manager + + + + + + + Open access to windows Local Security Authority + + + + Qt::Horizontal @@ -1695,33 +1669,6 @@ For files access you can use 'Direct All' instead to make it apply to all progra - - - - Open access to Windows Security Account Manager - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Open access to windows Local Security Authority - - - @@ -1738,6 +1685,29 @@ For files access you can use 'Direct All' instead to make it apply to all progra + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Various advanced isolation features can break compatibility, with some applications, if you are using this sandbox <b>NOT for Security</b> but for simple application portability by changing these options you can restore compatibility by sacrificing some security.<br>These options can be used securely when you don't grant any of the sandboxed process admin rights. + + + true + + + @@ -2125,8 +2095,8 @@ instead of "*". 0 0 - 63 - 16 + 98 + 28 @@ -2490,7 +2460,6 @@ Please note that this values are currently user specific and saved globally for btnAddStartProg btnDelStartProg chkStartBlockMsg - chkBlockINet chkINetBlockPrompt treeINet btnAddINetProg @@ -2516,10 +2485,7 @@ Please note that this values are currently user specific and saved globally for tabsAdvanced chkPreferExternalManifest chkNoWindowRename - chkAddToJob chkRestrictServices - chkProtectSCM - chkProtectSystem lstAutoExec btnAddAutoExec btnDelAutoExec diff --git a/SandboxiePlus/SandMan/Forms/SelectBoxWindow.ui b/SandboxiePlus/SandMan/Forms/SelectBoxWindow.ui new file mode 100644 index 00000000..80c247ee --- /dev/null +++ b/SandboxiePlus/SandMan/Forms/SelectBoxWindow.ui @@ -0,0 +1,107 @@ + + + SelectBoxWindow + + + + 0 + 0 + 280 + 400 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + SandboxiePlus sellect box + + + + + + + + Select the sandbox in which to start the program, installer or document. + + + true + + + + + + + + Sandbox + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Run As UAC Administrator + + + + + + + Run Sandboxed + + + true + + + + + + + Run Outside the Sandbox + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + + + + diff --git a/SandboxiePlus/SandMan/Forms/SettingsWindow.ui b/SandboxiePlus/SandMan/Forms/SettingsWindow.ui index 1bb7c19b..c0b257c9 100644 --- a/SandboxiePlus/SandMan/Forms/SettingsWindow.ui +++ b/SandboxiePlus/SandMan/Forms/SettingsWindow.ui @@ -6,8 +6,8 @@ 0 0 - 579 - 402 + 634 + 399 @@ -49,61 +49,11 @@ - General Options + General Config - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Show Notifications for relevant log Messages - - - false - - - - - - - - - - Show Sys-Tray - - - - - - - Open urls from this ui sandboxed - - - true - - - - - - - Check periodically for updates of Sandboxie-Plus - - - @@ -114,9 +64,6 @@ - - - @@ -125,19 +72,59 @@ - + - Add 'Run Sandboxed' to the explorer context menu + Show Notifications for relevant log Messages + + + false - - + + - On main window close: + Open urls from this ui sandboxed - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + true + + + + + + + + + + + + Hot-Key for terminating all boxed processes: + + + + + + + + + + + + + + + Show first recovery window when emptying sandboxes + + + + + + + Use Dark Theme (fully applied after a restart) + + + true @@ -154,6 +141,40 @@ + + + + Show Sys-Tray + + + + + + + Add 'Run Sandboxed' to the explorer context menu + + + + + + + Start UI when a sandboxed process is started + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -167,27 +188,13 @@ - - + + - Start UI when a sandboxed process is started + On main window close: - - - - - - Show first recovery window when emptying sandboxes - - - - - - - Use Dark Theme (fully applied after a restart) - - - true + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -197,7 +204,7 @@ - Advanced Options + Advanced Config @@ -416,7 +423,7 @@ - Program Restrictions + Program Control @@ -499,7 +506,7 @@ - Software Compatibility + Compatibility @@ -561,6 +568,99 @@ + + + Support + + + + + + + + + 75 + true + + + + Support Settings + + + + + + + + + + :/HelpingHand.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Instal updates automatically + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Check periodically for updates of Sandboxie-Plus + + + + + + + + 0 + 0 + + + + Keeping Sandboxie up to date with the rolling releases of windows and compatible with modern web browsers is a never ending endeavor. Please consider supporting this work with a donation.<br />You can support the developement with a direct <a href="https://sandboxie-plus.com/go.php?to=donate">PayPal donation</a>, works also with credit cards.<br />You can also provide continuous support with a <a href="https://sandboxie-plus.com/go.php?to=patreon">Patreon subscription</a>. + + + Qt::RichText + + + true + + + + + + + @@ -580,7 +680,6 @@ chkDarkTheme chkAutoStart chkSvcStart - chkAutoUpdate chkShellMenu chkNotifications chkSandboxUrls @@ -610,6 +709,8 @@ btnDelCompat chkNoCompat - + + + diff --git a/SandboxiePlus/SandMan/Models/SbieModel.cpp b/SandboxiePlus/SandMan/Models/SbieModel.cpp index 5c60bed8..18755cf5 100644 --- a/SandboxiePlus/SandMan/Models/SbieModel.cpp +++ b/SandboxiePlus/SandMan/Models/SbieModel.cpp @@ -3,13 +3,11 @@ #include "../../MiscHelpers/Common/Common.h" #include "../../MiscHelpers/Common/IconExtreactor.h" #include +#include "../SandMan.h" CSbieModel::CSbieModel(QObject *parent) :CTreeItemModel(parent) { - for (int i = 0; i < eMaxColor; i++) - m_BoxIcons[(EBoxColors)i] = qMakePair(QIcon(QString(":/Boxes/Empty%1").arg(i)), QIcon(QString(":/Boxes/Full%1").arg(i))); - //m_BoxEmpty = QIcon(":/BoxEmpty"); //m_BoxInUse = QIcon(":/BoxInUse"); m_ExeIcon = QIcon(":/exeIcon32"); @@ -128,7 +126,7 @@ QList CSbieModel::Sync(const QMap& BoxList, cons New[pNode->Path].append(pNode); Added.append(ID); - pNode->Icon = m_BoxIcons[eYelow].first; + pNode->Icon = theGUI->GetBoxIcon(false); pNode->IsBold = true; pNode->Values[eName].Raw = Group; @@ -175,22 +173,15 @@ QList CSbieModel::Sync(const QMap& BoxList, cons QMap ProcessList = pBox->GetProcessList(); - bool HasActive = Sync(pBox, pNode->Path, ProcessList, New, Old, Added); - int inUse = (HasActive ? 1 : 0); - int boxType = eYelow; - if(pBoxEx->HasLogApi()) - boxType = eRed; - if (pBoxEx->IsUnsecureDebugging()) - boxType = eMagenta; - else if (pBoxEx->IsSecurityRestricted()) - boxType = eOrang; - + bool inUse = Sync(pBox, pNode->Path, ProcessList, New, Old, Added); + int boxType = pBoxEx->GetType(); + if (pNode->inUse != inUse || pNode->boxType != boxType) { pNode->inUse = inUse; pNode->boxType = boxType; //pNode->Icon = pNode->inUse ? m_BoxInUse : m_BoxEmpty; - pNode->Icon = pNode->inUse ? m_BoxIcons[(EBoxColors)boxType].second : m_BoxIcons[(EBoxColors)boxType].first; + pNode->Icon = theGUI->GetBoxIcon(inUse, boxType); Changed = 1; // set change for first column } diff --git a/SandboxiePlus/SandMan/Models/SbieModel.h b/SandboxiePlus/SandMan/Models/SbieModel.h index 28b6b829..a98f3912 100644 --- a/SandboxiePlus/SandMan/Models/SbieModel.h +++ b/SandboxiePlus/SandMan/Models/SbieModel.h @@ -46,10 +46,10 @@ protected: struct SSandBoxNode: STreeNode { - SSandBoxNode(const QVariant& Id) : STreeNode(Id) { inUse = -1; boxType = -1; } + SSandBoxNode(const QVariant& Id) : STreeNode(Id) { inUse = false; boxType = -1; } CSandBoxPtr pBox; - int inUse; + bool inUse; int boxType; CBoxedProcessPtr pProcess; @@ -68,19 +68,6 @@ protected: //virtual QVariant GetDefaultIcon() const; private: - enum EBoxColors - { - eYelow = 0, - eRed, - eGreen, - eBlue, - eCyan, - eMagenta, - eOrang, - eMaxColor - }; - - QMap > m_BoxIcons; //QIcon m_BoxEmpty; //QIcon m_BoxInUse; diff --git a/SandboxiePlus/SandMan/Resources/Actions/RegEdit.png b/SandboxiePlus/SandMan/Resources/Actions/RegEdit.png new file mode 100644 index 00000000..0a8d5899 Binary files /dev/null and b/SandboxiePlus/SandMan/Resources/Actions/RegEdit.png differ diff --git a/SandboxiePlus/SandMan/Resources/Actions/Software.png b/SandboxiePlus/SandMan/Resources/Actions/Software.png new file mode 100644 index 00000000..38a7b7fe Binary files /dev/null and b/SandboxiePlus/SandMan/Resources/Actions/Software.png differ diff --git a/SandboxiePlus/SandMan/Resources/Actions/Support.png b/SandboxiePlus/SandMan/Resources/Actions/Support.png new file mode 100644 index 00000000..1a0ae10e Binary files /dev/null and b/SandboxiePlus/SandMan/Resources/Actions/Support.png differ diff --git a/SandboxiePlus/SandMan/Resources/HelpingHand.png b/SandboxiePlus/SandMan/Resources/HelpingHand.png new file mode 100644 index 00000000..e5519f5c Binary files /dev/null and b/SandboxiePlus/SandMan/Resources/HelpingHand.png differ diff --git a/SandboxiePlus/SandMan/Resources/SandMan.qrc b/SandboxiePlus/SandMan/Resources/SandMan.qrc index 41556c23..7e3696e5 100644 --- a/SandboxiePlus/SandMan/Resources/SandMan.qrc +++ b/SandboxiePlus/SandMan/Resources/SandMan.qrc @@ -47,6 +47,10 @@ SandManN.png Actions/finder.png Actions/Tree.png + Actions/Support.png + HelpingHand.png + Actions/RegEdit.png + Actions/Software.png Boxes/sandbox-b-empty.png diff --git a/SandboxiePlus/SandMan/SandMan.cpp b/SandboxiePlus/SandMan/SandMan.cpp index 3e1f2335..122ddf99 100644 --- a/SandboxiePlus/SandMan/SandMan.cpp +++ b/SandboxiePlus/SandMan/SandMan.cpp @@ -19,6 +19,8 @@ #include "../MiscHelpers/Common/TreeItemModel.h" #include "../MiscHelpers/Common/ListItemModel.h" #include "Views/TraceView.h" +#include "Windows/SelectBoxWindow.h" +#include "../UGlobalHotkey/uglobalhotkeys.h" CSbiePlusAPI* theAPI = NULL; @@ -27,6 +29,7 @@ CSbiePlusAPI* theAPI = NULL; #include #include + //BOOLEAN OnWM_Notify(NMHDR *Header, LRESULT *Result); class CNativeEventFilter : public QAbstractNativeEventFilter @@ -177,6 +180,12 @@ CSandMan::CSandMan(QWidget *parent) m_pTraceView = new CTraceView(this); m_pLogTabs->addTab(m_pTraceView, tr("Trace Log")); + m_pHotkeyManager = new UGlobalHotkeys(this); + connect(m_pHotkeyManager, SIGNAL(activated(size_t)), SLOT(OnHotKey(size_t))); + SetupHotKeys(); + + for (int i = 0; i < eMaxColor; i++) + m_BoxIcons[(EBoxColors)i] = qMakePair(QIcon(QString(":/Boxes/Empty%1").arg(i)), QIcon(QString(":/Boxes/Full%1").arg(i))); // Tray QIcon Icon; @@ -502,6 +511,17 @@ void CSandMan::closeEvent(QCloseEvent *e) QApplication::quit(); } +QIcon CSandMan::GetBoxIcon(bool inUse, int boxType) +{ + EBoxColors color = eYelow; + switch (boxType) { + case CSandBoxPlus::eHardened: color = eOrang; break; + case CSandBoxPlus::eHasLogApi: color = eRed; break; + case CSandBoxPlus::eInsecure: color = eMagenta; break; + } + return inUse ? m_BoxIcons[color].second : m_BoxIcons[color].first; +} + bool CSandMan::IsFullyPortable() { QString SbiePath = theAPI->GetSbiePath(); @@ -520,6 +540,12 @@ void CSandMan::OnMessage(const QString& Message) setWindowState(Qt::WindowActive); SetForegroundWindow(MainWndHandle); } + else if (Message.left(3) == "Run") + { + QString CmdLine = Message.mid(4); + + RunSandboxed(QStringList(CmdLine)); + } else if (Message.left(6) == "Status") { QString Status = Message.mid(7); @@ -556,27 +582,21 @@ void CSandMan::dragEnterEvent(QDragEnterEvent* e) } } +void CSandMan::RunSandboxed(const QStringList& Commands) +{ + CSelectBoxWindow* pSelectBoxWindow = new CSelectBoxWindow(Commands); + pSelectBoxWindow->show(); +} + void CSandMan::dropEvent(QDropEvent* e) { - QStringList Boxes; - foreach(const CSandBoxPtr &pBox, theAPI->GetAllBoxes()) - { - if (pBox->IsEnabled()) - Boxes.append(pBox->GetName().replace("_", " ")); - } - - bool ok; - QString box = QInputDialog::getItem(this, "Sandboxie-Plus", tr("Select box:"), Boxes, 0, false, &ok); - if (!ok || box.isEmpty()) - return; - + QStringList Commands; foreach(const QUrl & url, e->mimeData()->urls()) { - if (!url.isLocalFile()) - continue; - QString FileName = url.toLocalFile().replace("/", "\\"); - - theAPI->RunStart(box.replace(" ", "_"), FileName); + if (url.isLocalFile()) + Commands.append(url.toLocalFile().replace("/", "\\")); } + + RunSandboxed(Commands); } void CSandMan::timerEvent(QTimerEvent* pEvent) @@ -590,11 +610,6 @@ void CSandMan::timerEvent(QTimerEvent* pEvent) { SB_STATUS Status = theAPI->ReloadBoxes(); - if (!Status.IsError() && !theAPI->GetAllBoxes().contains("defaultbox")) { - OnLogMessage(tr("Default sandbox not found; creating: %1").arg("DefaultBox")); - theAPI->CreateBox("DefaultBox"); - } - theAPI->UpdateProcesses(m_pKeepTerminated->isChecked()); bForceProcessDisabled = theAPI->AreForceProcessDisabled(); @@ -717,7 +732,7 @@ void CSandMan::OnBoxClosed(const QString& BoxName) if (!pBox->GetBool("NeverDelete", false) && pBox->GetBool("AutoDelete", false) && !pBox->IsEmpty()) { - CRecoveryWindow* pRecoveryWindow = new CRecoveryWindow(pBox); + CRecoveryWindow* pRecoveryWindow = new CRecoveryWindow(pBox, this); if (pRecoveryWindow->FindFiles() == 0) delete pRecoveryWindow; else if (pRecoveryWindow->exec() != 1) @@ -762,11 +777,16 @@ void CSandMan::OnStatusChanged() { appTitle.append(tr(" - Portable")); + QString BoxPath = QDir::cleanPath(QApplication::applicationDirPath() + "/../Sandbox").replace("/", "\\"); + int PortableRootDir = theConf->GetInt("Options/PortableRootDir", -1); if (PortableRootDir == -1) { bool State = false; - PortableRootDir = CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("Sandboxie-Plus was started in portable mode, do you want to put the SandBox folder into its parent directory?") + PortableRootDir = CCheckableMessageBox::question(this, "Sandboxie-Plus", + tr("Sandboxie-Plus was started in portable mode, do you want to put the Sandbox folder into its parent directory?\r\nYes will choose: %1\r\nNo will choose: %2") + .arg(BoxPath) + .arg("C:\\Sandbox") // todo resolve os drive properly , tr("Don't show this message again."), &State, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes, QMessageBox::Information) == QDialogButtonBox::Yes ? 1 : 0; if (State) @@ -774,10 +794,7 @@ void CSandMan::OnStatusChanged() } if (PortableRootDir) - { - QString BoxPath = QDir::cleanPath(QApplication::applicationDirPath() + "/../Sandbox/%SANDBOX%").replace("/", "\\"); - theAPI->GetGlobalSettings()->SetText("FileRootPath", BoxPath); - } + theAPI->GetGlobalSettings()->SetText("FileRootPath", BoxPath + "\\%SANDBOX%"); } if (theConf->GetBool("Options/AutoRunSoftCompat", true)) @@ -802,6 +819,14 @@ void CSandMan::OnStatusChanged() if (theConf->GetBool("Options/WatchIni", true)) theAPI->WatchIni(true); + + + SB_STATUS Status = theAPI->ReloadBoxes(); + + if (!Status.IsError() && !theAPI->GetAllBoxes().contains("defaultbox")) { + OnLogMessage(tr("Default sandbox not found; creating: %1").arg("DefaultBox")); + theAPI->CreateBox("DefaultBox"); + } } else { @@ -860,6 +885,26 @@ void CSandMan::OnMenuHover(QAction* action) } } +#define HK_PANIC 1 + +void CSandMan::SetupHotKeys() +{ + m_pHotkeyManager->unregisterAllHotkeys(); + + if (theConf->GetBool("Options/EnablePanicKey", false)) + m_pHotkeyManager->registerHotkey(theConf->GetString("Options/PanicKeySequence", "Ctrl+Cancel"), HK_PANIC); +} + +void CSandMan::OnHotKey(size_t id) +{ + switch (id) + { + case HK_PANIC: + theAPI->TerminateAll(); + break; + } +} + void CSandMan::OnLogMessage(const QString& Message, bool bNotify) { QTreeWidgetItem* pItem = new QTreeWidgetItem(); // Time|Message @@ -1281,6 +1326,8 @@ void CSandMan::UpdateSettings() //m_pBoxView->UpdateRunMenu(); + SetupHotKeys(); + if (theConf->GetBool("Options/ShowSysTray", true)) m_pTrayIcon->show(); else @@ -1473,6 +1520,7 @@ QString CSandMan::FormatError(const SB_STATUS& Error) case SB_ConfigFailed: Message = tr("Failed to set configuration setting %1 in section %2: %3"); break; case SB_SnapIsEmpty: Message = tr("Can not create snapshot of an empty sandbox"); break; case SB_NameExists: Message = tr("A sandbox with that name already exists"); break; + case SB_PasswordBad: Message = tr("The config password must not be longer than 64 charakters"); break; default: return tr("Unknown Error Status: %1").arg(Error.GetStatus()); } @@ -1532,7 +1580,6 @@ void CSandMan::OnSysTray(QSystemTrayIcon::ActivationReason Reason) } show(); case QSystemTrayIcon::Trigger: -#ifdef WIN32 if (isVisible() && !TriggerSet) { TriggerSet = true; @@ -1546,7 +1593,7 @@ void CSandMan::OnSysTray(QSystemTrayIcon::ActivationReason Reason) SetForegroundWindow(MainWndHandle); } ); } -#endif + m_pPopUpWindow->Poke(); break; } } @@ -1905,6 +1952,7 @@ void CSandMan::SetUITheme() QApplication::setPalette(m_DefaultPalett); } + m_DarkTheme = bDark; CTreeItemModel::SetDarkMode(bDark); CListItemModel::SetDarkMode(bDark); CPopUpWindow::SetDarkMode(bDark); @@ -2022,8 +2070,8 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) wstring info = CSandMan::tr("Drag the Finder Tool over a window to select it, then release the mouse to check if the window is sandboxed.").toStdWString(); CreateWindow(L"Static", L"", SS_BITMAP | SS_NOTIFY | WS_VISIBLE | WS_CHILD, 10, 10, 32, 32, hwnd, (HMENU)ID_FINDER_TARGET, NULL, NULL); - CreateWindow(L"Static", info.c_str(), WS_VISIBLE | WS_CHILD, 60, 10, 180, 50, hwnd, (HMENU)ID_FINDER_EXPLAIN, NULL, NULL); - CreateWindow(L"Static", L"", WS_CHILD, 60, 70, 180, 50, hwnd, (HMENU)ID_FINDER_RESULT, NULL, NULL); + CreateWindow(L"Static", info.c_str(), WS_VISIBLE | WS_CHILD, 60, 10, 180, 65, hwnd, (HMENU)ID_FINDER_EXPLAIN, NULL, NULL); + CreateWindow(L"Static", L"", WS_CHILD, 60, 80, 180, 50, hwnd, (HMENU)ID_FINDER_RESULT, NULL, NULL); MakeFinderTool(GetDlgItem(hwnd, ID_FINDER_TARGET), FindProc); @@ -2075,7 +2123,7 @@ DWORD WINAPI FinderThreadFunc(LPVOID lpParam) // child windows with the same parent window. HWND hwnd = CreateWindow(mainWindowClass.lpszClassName, CSandMan::tr("Sandboxie-Plus - Window Finder").toStdWString().c_str() - , WS_SYSMENU | WS_CAPTION | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 275, 100, NULL, 0, hInstance, NULL); + , WS_SYSMENU | WS_CAPTION | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 275, 115, NULL, 0, hInstance, NULL); HFONT hFont = CreateFont(13, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Tahoma")); diff --git a/SandboxiePlus/SandMan/SandMan.h b/SandboxiePlus/SandMan/SandMan.h index 0b0ae4db..03a53667 100644 --- a/SandboxiePlus/SandMan/SandMan.h +++ b/SandboxiePlus/SandMan/SandMan.h @@ -23,6 +23,7 @@ class CBoxBorder; class CSbieTemplates; class CTraceView; + class CSandMan : public QMainWindow { Q_OBJECT @@ -49,6 +50,10 @@ public: CSbieView* GetBoxView() { return m_pBoxView; } + void RunSandboxed(const QStringList& Commands); + + QIcon GetBoxIcon(bool inUse, int boxType = 0); + protected: SB_STATUS ConnectSbie(); SB_STATUS ConnectSbieImpl(); @@ -76,6 +81,22 @@ protected: QStringList m_MissingTemplates; + enum EBoxColors + { + eYelow = 0, + eRed, + eGreen, + eBlue, + eCyan, + eMagenta, + eOrang, + eMaxColor + }; + + QMap > m_BoxIcons; + + class UGlobalHotkeys* m_pHotkeyManager; + public slots: void OnMessage(const QString&); @@ -93,6 +114,9 @@ public slots: void UpdateSettings(); void OnIniReloaded(); + void SetupHotKeys(); + void OnHotKey(size_t id); + void OnAsyncFinished(); void OnAsyncFinished(CSbieProgress* pProgress); void OnAsyncMessage(const QString& Text); @@ -233,9 +257,10 @@ private: void LoadLanguage(); QTranslator m_Translator; QByteArray m_Translation; + public: quint32 m_LanguageId; bool m_DarkTheme; }; -extern CSandMan* theGUI; \ No newline at end of file +extern CSandMan* theGUI; diff --git a/SandboxiePlus/SandMan/SandMan.pri b/SandboxiePlus/SandMan/SandMan.pri index 70f951c1..b204533e 100644 --- a/SandboxiePlus/SandMan/SandMan.pri +++ b/SandboxiePlus/SandMan/SandMan.pri @@ -18,7 +18,8 @@ HEADERS += ./stdafx.h \ ./Windows/PopUpWindow.h \ ./Windows/SnapshotsWindow.h \ ./Windows/SettingsWindow.h \ - ./Windows/OptionsWindow.h + ./Windows/OptionsWindow.h \ + ./Windows/SelectBoxWindow.h SOURCES += ./main.cpp \ ./stdafx.cpp \ @@ -37,18 +38,21 @@ SOURCES += ./main.cpp \ ./Windows/PopUpWindow.cpp \ ./Windows/RecoveryWindow.cpp \ ./Windows/SettingsWindow.cpp \ - ./Windows/SnapshotsWindow.cpp + ./Windows/SnapshotsWindow.cpp \ + ./Windows/SelectBoxWindow.cpp FORMS += ./Forms/NewBoxWindow.ui \ ./Forms/OptionsWindow.ui \ ./Forms/PopUpWindow.ui \ ./Forms/RecoveryWindow.ui \ ./Forms/SettingsWindow.ui \ - ./Forms/SnapshotsWindow.ui + ./Forms/SnapshotsWindow.ui \ + ./Forms/SelectBoxWindow.ui TRANSLATIONS += sandman_de.ts \ sandman_es.ts \ sandman_it.ts \ + sandman_nl.ts \ sandman_pt.ts \ sandman_ru.ts \ sandman_pl.ts \ diff --git a/SandboxiePlus/SandMan/SandMan.qc.pro b/SandboxiePlus/SandMan/SandMan.qc.pro index c34132d8..2e2855d1 100644 --- a/SandboxiePlus/SandMan/SandMan.qc.pro +++ b/SandboxiePlus/SandMan/SandMan.qc.pro @@ -12,7 +12,7 @@ CONFIG(release, debug|release):contains(QMAKE_HOST.arch, x86_64):LIBS += -L../Bi CONFIG(debug, debug|release):!contains(QMAKE_HOST.arch, x86_64):LIBS += -L../Bin/Win32/Debug CONFIG(release, debug|release):!contains(QMAKE_HOST.arch, x86_64):LIBS += -L../Bin/Win32/Release -LIBS += -lNtdll -lAdvapi32 -lOle32 -lUser32 -lShell32 -lGdi32 -lQSbieAPI -lMiscHelpers -lqtsingleapp +LIBS += -lNtdll -lAdvapi32 -lOle32 -lUser32 -lShell32 -lGdi32 -lQSbieAPI -lMiscHelpers -lqtsingleapp -lUGlobalHotkey CONFIG(release, debug|release):{ QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO diff --git a/SandboxiePlus/SandMan/SandMan.vcxproj b/SandboxiePlus/SandMan/SandMan.vcxproj index f7dafa49..829845f8 100644 --- a/SandboxiePlus/SandMan/SandMan.vcxproj +++ b/SandboxiePlus/SandMan/SandMan.vcxproj @@ -121,7 +121,7 @@ Windows $(OutDir)\$(ProjectName).exe true - QSbieAPI.lib;MiscHelpers.lib;ntdll.lib;QtSingleApp.lib;%(AdditionalDependencies) + QSbieAPI.lib;MiscHelpers.lib;ntdll.lib;QtSingleApp.lib;UGlobalHotkey.lib;%(AdditionalDependencies) @@ -146,7 +146,7 @@ true MachineX86 /SUBSYSTEM:WINDOWS - QSbieAPI.lib;MiscHelpers.lib;ntdll.lib;QtSingleApp.lib;%(AdditionalDependencies) + QSbieAPI.lib;MiscHelpers.lib;ntdll.lib;QtSingleApp.lib;UGlobalHotkey.lib;%(AdditionalDependencies) @@ -167,7 +167,7 @@ Windows $(OutDir)\$(ProjectName).exe true - QSbieAPI.lib;MiscHelpers.lib;ntdll.lib;QtSingleApp.lib;%(AdditionalDependencies) + QSbieAPI.lib;MiscHelpers.lib;ntdll.lib;QtSingleApp.lib;UGlobalHotkey.lib;%(AdditionalDependencies) @@ -191,7 +191,7 @@ true MachineX86 /SUBSYSTEM:WINDOWS - QSbieAPI.lib;MiscHelpers.lib;ntdll.lib;QtSingleApp.lib;%(AdditionalDependencies) + QSbieAPI.lib;MiscHelpers.lib;ntdll.lib;QtSingleApp.lib;UGlobalHotkey.lib;%(AdditionalDependencies) @@ -216,10 +216,12 @@ + + @@ -251,6 +253,7 @@ + diff --git a/SandboxiePlus/SandMan/SandMan.vcxproj.filters b/SandboxiePlus/SandMan/SandMan.vcxproj.filters index 2df276a5..2f8fc763 100644 --- a/SandboxiePlus/SandMan/SandMan.vcxproj.filters +++ b/SandboxiePlus/SandMan/SandMan.vcxproj.filters @@ -102,6 +102,9 @@ Views + + Windows + @@ -157,6 +160,9 @@ Views + + Windows + @@ -193,6 +199,9 @@ Form Files + + Form Files + diff --git a/SandboxiePlus/SandMan/SbiePlusAPI.cpp b/SandboxiePlus/SandMan/SbiePlusAPI.cpp index 92a184cb..96ba981b 100644 --- a/SandboxiePlus/SandMan/SbiePlusAPI.cpp +++ b/SandboxiePlus/SandMan/SbiePlusAPI.cpp @@ -375,6 +375,17 @@ int CSandBoxPlus::IsLeaderProgram(const QString& ProgName) return FindInStrList(Programs, ProgName) != Programs.end() ? 1 : 0; } +CSandBoxPlus::EBoxTypes CSandBoxPlus::GetType() const +{ + if (m_bLogApiFound) + return eHasLogApi; + if (m_iUnsecureDebugging != 0) + return eInsecure; + if (m_bSecurityRestricted) + return eHardened; + return eDefault; +} + /////////////////////////////////////////////////////////////////////////////// // CSbieProcess // diff --git a/SandboxiePlus/SandMan/SbiePlusAPI.h b/SandboxiePlus/SandMan/SbiePlusAPI.h index 20c301fa..d3e58038 100644 --- a/SandboxiePlus/SandMan/SbiePlusAPI.h +++ b/SandboxiePlus/SandMan/SbiePlusAPI.h @@ -72,6 +72,19 @@ public: const QSet& GetRecentPrograms() { return m_RecentPrograms; } + enum EBoxTypes + { + eDefault = 0, + eHardened, + eHasLogApi, + eInsecure, + + eUnknown = -1 + }; + + EBoxTypes GetType() const; + + protected: friend class CSbiePlusAPI; virtual bool CheckOpenToken() const; diff --git a/SandboxiePlus/SandMan/Views/SbieView.cpp b/SandboxiePlus/SandMan/Views/SbieView.cpp index 2fc9a4e3..19f35bd3 100644 --- a/SandboxiePlus/SandMan/Views/SbieView.cpp +++ b/SandboxiePlus/SandMan/Views/SbieView.cpp @@ -68,11 +68,13 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent) m_pMenuRun = m_pMenu->addMenu(CSandMan::GetIcon("Start"), tr("Run")); m_pMenuRunAny = m_pMenuRun->addAction(CSandMan::GetIcon("Run"), tr("Run Program"), this, SLOT(OnSandBoxAction())); m_pMenuRunMenu = m_pMenuRun->addAction(CSandMan::GetIcon("StartMenu"), tr("Run from Start Menu"), this, SLOT(OnSandBoxAction())); - m_pMenuRunBrowser = m_pMenuRun->addAction(CSandMan::GetIcon("Internet"), tr("Run Web Browser"), this, SLOT(OnSandBoxAction())); - m_pMenuRunMailer = m_pMenuRun->addAction(CSandMan::GetIcon("Email"), tr("Run eMail Client"), this, SLOT(OnSandBoxAction())); - m_pMenuRunExplorer = m_pMenuRun->addAction(CSandMan::GetIcon("Explore"), tr("Run Explorer"), this, SLOT(OnSandBoxAction())); - m_pMenuRunCmd = m_pMenuRun->addAction(CSandMan::GetIcon("Cmd"), tr("Run Cmd.exe"), this, SLOT(OnSandBoxAction())); - m_pMenuRunCmdAdmin = m_pMenuRun->addAction(CSandMan::GetIcon("Cmd"), tr("Run Cmd.exe as Admin"), this, SLOT(OnSandBoxAction())); + m_pMenuRunBrowser = m_pMenuRun->addAction(CSandMan::GetIcon("Internet"), tr("Default Web Browser"), this, SLOT(OnSandBoxAction())); + m_pMenuRunMailer = m_pMenuRun->addAction(CSandMan::GetIcon("Email"), tr("Default eMail Client"), this, SLOT(OnSandBoxAction())); + m_pMenuRunExplorer = m_pMenuRun->addAction(CSandMan::GetIcon("Explore"), tr("Windows Explorer"), this, SLOT(OnSandBoxAction())); + m_pMenuRunRegEdit = m_pMenuRun->addAction(CSandMan::GetIcon("RegEdit"), tr("Registry Editor"), this, SLOT(OnSandBoxAction())); + m_pMenuRunAppWiz = m_pMenuRun->addAction(CSandMan::GetIcon("Software"), tr("Programs and Features"), this, SLOT(OnSandBoxAction())); + m_pMenuRunCmd = m_pMenuRun->addAction(CSandMan::GetIcon("Cmd"), tr("Terminal"), this, SLOT(OnSandBoxAction())); + m_pMenuRunCmdAdmin = m_pMenuRun->addAction(CSandMan::GetIcon("Cmd"), tr("Terminal (as Admin)"), this, SLOT(OnSandBoxAction())); m_pMenuRun->addSeparator(); m_iMenuRun = m_pMenuRun->actions().count(); m_pMenuEmptyBox = m_pMenu->addAction(CSandMan::GetIcon("EmptyAll"), tr("Terminate All Programs"), this, SLOT(OnSandBoxAction())); @@ -500,23 +502,9 @@ void CSbieView::OnGroupAction() m_pSbieModel->Clear(); //todo improve that } - StoreGroups(); - UpdateGroupMenu(); -} - -void CSbieView::StoreGroups() -{ - QMap Boxes = theAPI->GetAllBoxes(); - - for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I) { - for (auto J = I->begin(); J != I->end(); ) { - if (!Boxes.take(J->toLower()).isNull() || m_Groups.contains(*J)) ++J; - else J = I->erase(J); - } - } - QString Grouping = CSbieView__SerializeGroup(m_Groups); theAPI->GetUserSettings()->SetText("BoxDisplayOrder", Grouping); + UpdateGroupMenu(); } QString CSbieView::AddNewBox() @@ -575,6 +563,10 @@ void CSbieView::OnSandBoxAction(QAction* Action) Results.append(SandBoxes.first()->RunStart("explorer.exe /e,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}")); } + else if (Action == m_pMenuRunRegEdit) + Results.append(SandBoxes.first()->RunStart("regedit.exe")); + else if (Action == m_pMenuRunAppWiz) + Results.append(SandBoxes.first()->RunStart("\"C:\\WINDOWS\\System32\\control.exe\" \"C:\\Windows\\System32\\appwiz.cpl\"")); else if (Action == m_pMenuRunCmd) Results.append(SandBoxes.first()->RunStart("cmd.exe")); else if (Action == m_pMenuRunCmdAdmin) @@ -639,44 +631,19 @@ void CSbieView::OnSandBoxAction(QAction* Action) } else if (Action == m_pMenuRename) { - QString OldName = SandBoxes.first()->GetName(); - QString OldValue = OldName.replace("_", " "); + QString OldValue = SandBoxes.first()->GetName().replace("_", " "); QString Value = QInputDialog::getText(this, "Sandboxie-Plus", tr("Please enter a new name for the Sandbox."), QLineEdit::Normal, OldValue); if (Value.isEmpty() || Value == OldValue) return; - QString NewName = Value.replace(" ", "_"); - Results.append((SandBoxes.first()->RenameBox(NewName))); - - // update grouping - for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I) { - int pos = I->indexOf(OldName); - if (pos != -1) - I->replace(pos, NewName); - } - - StoreGroups(); + Results.append((SandBoxes.first()->RenameBox(Value.replace(" ", "_")))); } else if (Action == m_pMenuRemove) { if (QMessageBox("Sandboxie-Plus", tr("Do you really want to remove the selected sandbox(es)?"), QMessageBox::Warning, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this).exec() != QMessageBox::Yes) return; - foreach(const CSandBoxPtr & pBox, SandBoxes) - { - QString Name = pBox->GetName(); - SB_STATUS Status = pBox->RemoveBox(); - - // update grouping - if (!Status.IsError()) { - for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I) { - I->removeAll(Name); - } - } - - Results.append(Status); - } - - StoreGroups(); + foreach(const CSandBoxPtr& pBox, SandBoxes) + Results.append(pBox->RemoveBox()); } else if (Action == m_pMenuRecover) { @@ -693,7 +660,7 @@ void CSbieView::OnSandBoxAction(QAction* Action) if (theConf->GetBool("Options/ShowRecovery", false)) { - CRecoveryWindow* pRecoveryWindow = new CRecoveryWindow(SandBoxes.first()); + CRecoveryWindow* pRecoveryWindow = new CRecoveryWindow(SandBoxes.first(), this); pRecoveryWindow->FindFiles(); if (pRecoveryWindow->exec() != 1) return; diff --git a/SandboxiePlus/SandMan/Views/SbieView.h b/SandboxiePlus/SandMan/Views/SbieView.h index 97ccdcf5..6808a9ea 100644 --- a/SandboxiePlus/SandMan/Views/SbieView.h +++ b/SandboxiePlus/SandMan/Views/SbieView.h @@ -27,7 +27,6 @@ signals: public slots: void Clear(); void Refresh(); - void StoreGroups(); void ReloadGroups(); private slots: @@ -73,6 +72,8 @@ private: QAction* m_pMenuRunBrowser; QAction* m_pMenuRunMailer; QAction* m_pMenuRunExplorer; + QAction* m_pMenuRunRegEdit; + QAction* m_pMenuRunAppWiz; QAction* m_pMenuRunCmd; QAction* m_pMenuRunCmdAdmin; QAction* m_pMenuMkLink; diff --git a/SandboxiePlus/SandMan/Windows/NewBoxWindow.cpp b/SandboxiePlus/SandMan/Windows/NewBoxWindow.cpp index cdac213b..e6fd393f 100644 --- a/SandboxiePlus/SandMan/Windows/NewBoxWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/NewBoxWindow.cpp @@ -7,8 +7,6 @@ CNewBoxWindow::CNewBoxWindow(QWidget *parent) : QDialog(parent) { - this->setWindowTitle(tr("Sandboxie-Plus - Create New Box")); - Qt::WindowFlags flags = windowFlags(); flags |= Qt::CustomizeWindowHint; //flags &= ~Qt::WindowContextHelpButtonHint; @@ -21,6 +19,7 @@ CNewBoxWindow::CNewBoxWindow(QWidget *parent) setWindowFlags(flags); ui.setupUi(this); + this->setWindowTitle(tr("Sandboxie-Plus - Create New Box")); connect(ui.buttonBox, SIGNAL(accepted()), SLOT(CreateBox())); connect(ui.buttonBox, SIGNAL(rejected()), SLOT(reject())); diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp index 77af0b5f..00b3942f 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.cpp @@ -1,45 +1,12 @@ #include "stdafx.h" #include "OptionsWindow.h" #include "SandMan.h" +#include "SettingsWindow.h" #include "../MiscHelpers/Common/Settings.h" #include "../MiscHelpers/Common/Common.h" #include "../MiscHelpers/Common/ComboInputDialog.h" #include "../MiscHelpers/Common/SettingsWidgets.h" #include "Helpers/WinAdmin.h" -#include - -class CustomTabStyle : public QProxyStyle { -public: - CustomTabStyle(QStyle* style = 0) : QProxyStyle(style) {} - - QSize sizeFromContents(ContentsType type, const QStyleOption* option, - const QSize& size, const QWidget* widget) const { - QSize s = QProxyStyle::sizeFromContents(type, option, size, widget); - if (type == QStyle::CT_TabBarTab) { - s.transpose(); - if(theGUI->m_DarkTheme) - s.setHeight(s.height() * 13 / 10); - else - s.setHeight(s.height() * 15 / 10); - s.setWidth(s.width() * 11 / 10); // for the the icon - } - return s; - } - - void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const { - if (element == CE_TabBarTabLabel) { - if (const QStyleOptionTab* tab = qstyleoption_cast(option)) { - QStyleOptionTab opt(*tab); - opt.shape = QTabBar::RoundedNorth; - //opt.iconSize = QSize(32, 32); - opt.iconSize = QSize(24, 24); - QProxyStyle::drawControl(element, &opt, painter, widget); - return; - } - } - QProxyStyle::drawControl(element, option, painter, widget); - } -}; COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QString& Name, QWidget *parent) @@ -72,6 +39,19 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri ui.tabs->setTabPosition(QTabWidget::West); ui.tabs->tabBar()->setStyle(new CustomTabStyle(ui.tabs->tabBar()->style())); + ui.tabs->setTabIcon(0, CSandMan::GetIcon("Box")); + ui.tabs->setTabIcon(1, CSandMan::GetIcon("Group")); + ui.tabs->setTabIcon(2, CSandMan::GetIcon("Force")); + ui.tabs->setTabIcon(3, CSandMan::GetIcon("Stop")); + ui.tabs->setTabIcon(4, CSandMan::GetIcon("Start")); + ui.tabs->setTabIcon(5, CSandMan::GetIcon("Internet")); + ui.tabs->setTabIcon(6, CSandMan::GetIcon("Wall")); + ui.tabs->setTabIcon(7, CSandMan::GetIcon("Recover")); + ui.tabs->setTabIcon(8, CSandMan::GetIcon("Advanced")); + ui.tabs->setTabIcon(9, CSandMan::GetIcon("Template")); + ui.tabs->setTabIcon(10, CSandMan::GetIcon("EditIni")); + + QStringList DebugOptions = theConf->ListKeys("DebugOptions"); if(DebugOptions.isEmpty()) ui.tabsAdvanced->removeTab(ui.tabsAdvanced->count() - 1); @@ -123,18 +103,6 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri //ui.chkWithTemplates->setEnabled(false); } - ui.tabs->setTabIcon(0, CSandMan::GetIcon("Box")); - ui.tabs->setTabIcon(1, CSandMan::GetIcon("Group")); - ui.tabs->setTabIcon(2, CSandMan::GetIcon("Force")); - ui.tabs->setTabIcon(3, CSandMan::GetIcon("Stop")); - ui.tabs->setTabIcon(4, CSandMan::GetIcon("Start")); - ui.tabs->setTabIcon(5, CSandMan::GetIcon("Internet")); - ui.tabs->setTabIcon(6, CSandMan::GetIcon("Wall")); - ui.tabs->setTabIcon(7, CSandMan::GetIcon("Recover")); - ui.tabs->setTabIcon(8, CSandMan::GetIcon("Advanced")); - ui.tabs->setTabIcon(9, CSandMan::GetIcon("Template")); - ui.tabs->setTabIcon(10, CSandMan::GetIcon("EditIni")); - ui.tabs->setCurrentIndex(m_Template ? 10 : 0); //connect(ui.chkWithTemplates, SIGNAL(clicked(bool)), this, SLOT(OnWithTemplates())); @@ -252,7 +220,7 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri connect(ui.chkShowAccessTmpl, SIGNAL(clicked(bool)), this, SLOT(OnShowAccessTmpl())); connect(ui.btnDelAccess, SIGNAL(clicked(bool)), this, SLOT(OnDelAccess())); - connect(ui.treeAccess, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(OnAccessItemClicked(QTreeWidgetItem*, int))); + //connect(ui.treeAccess, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(OnAccessItemClicked(QTreeWidgetItem*, int))); connect(ui.treeAccess, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnAccessItemDoubleClicked(QTreeWidgetItem*, int))); connect(ui.treeAccess, SIGNAL(itemSelectionChanged()), this, SLOT(OnAccessSelectionChanged())); // @@ -273,19 +241,18 @@ COptionsWindow::COptionsWindow(const QSharedPointer& pBox, const QStri // Advanced connect(ui.chkPreferExternalManifest, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkNoWindowRename, SIGNAL(clicked(bool)), this, SLOT(OnNoWindowRename())); + connect(ui.chkNestedJobs, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkUseSbieWndStation, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkProtectSCM, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkRestrictServices, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); - connect(ui.chkProtectSystem, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); + //connect(ui.chkProtectSystem, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkOpenDevCMApi, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); - connect(ui.chkOpenLsaSSPI, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); + //connect(ui.chkOpenLsaSSPI, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkOpenSamEndpoint, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkOpenLsaEndpoint, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); - - connect(ui.chkAddToJob, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); connect(ui.chkDisableMonitor, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged())); @@ -534,22 +501,20 @@ void COptionsWindow::LoadConfig() { ui.chkPreferExternalManifest->setChecked(m_pBox->GetBool("PreferExternalManifest", false)); + ui.chkNestedJobs->setChecked(m_pBox->GetBool("AllowBoxedJobs", false)); ui.chkUseSbieWndStation->setChecked(m_pBox->GetBool("UseSbieWndStation", false)); ui.chkProtectSCM->setChecked(!m_pBox->GetBool("UnrestrictedSCM", false)); ui.chkRestrictServices->setChecked(!m_pBox->GetBool("RunServicesAsSystem", false)); - ui.chkProtectSystem->setChecked(!m_pBox->GetBool("ExposeBoxedSystem", false)); + //ui.chkProtectSystem->setChecked(!m_pBox->GetBool("ExposeBoxedSystem", false)); ui.chkOpenDevCMApi->setChecked(m_pBox->GetBool("OpenDevCMApi", false)); - ui.chkOpenLsaSSPI->setChecked(!m_pBox->GetBool("BlockPassword", true)); // OpenLsaSSPI + //ui.chkOpenLsaSSPI->setChecked(!m_pBox->GetBool("BlockPassword", true)); // OpenLsaSSPI ui.chkOpenSamEndpoint->setChecked(m_pBox->GetBool("OpenSamEndpoint", false)); ui.chkOpenLsaEndpoint->setChecked(m_pBox->GetBool("OpenLsaEndpoint", false)); - ui.chkAddToJob->setChecked(!m_pBox->GetBool("NoAddProcessToJob", false)); - - QStringList AutoExec = m_pBox->GetTextList("AutoExec", m_Template); ui.lstAutoExec->clear(); ui.lstAutoExec->addItems(AutoExec); @@ -601,8 +566,14 @@ void COptionsWindow::LoadConfig() void COptionsWindow::WriteAdvancedCheck(QCheckBox* pCheck, const QString& Name, const QString& Value) { - if (pCheck->checkState() == Qt::Checked) m_pBox->SetText(Name, Value); - else if (pCheck->checkState() == Qt::Unchecked) m_pBox->DelValue(Name); + SB_STATUS Status; + if (pCheck->checkState() == Qt::Checked) + Status = m_pBox->SetText(Name, Value); + else if (pCheck->checkState() == Qt::Unchecked) + Status = m_pBox->DelValue(Name); + + if (!Status) + throw Status; } void COptionsWindow::WriteAdvancedCheck(QCheckBox* pCheck, const QString& Name, const QString& OnValue, const QString& OffValue) @@ -610,180 +581,205 @@ void COptionsWindow::WriteAdvancedCheck(QCheckBox* pCheck, const QString& Name, //if (pCheck->checkState() == Qt::PartiallyChecked) // return; + SB_STATUS Status; if (pCheck->checkState() == Qt::Checked) { if(!OnValue.isEmpty()) - m_pBox->SetText(Name, OnValue); + Status = m_pBox->SetText(Name, OnValue); else - m_pBox->DelValue(Name); + Status = m_pBox->DelValue(Name); } else if (pCheck->checkState() == Qt::Unchecked) { if (!OffValue.isEmpty()) - m_pBox->SetText(Name, OffValue); + Status = m_pBox->SetText(Name, OffValue); else - m_pBox->DelValue(Name); + Status = m_pBox->DelValue(Name); } + + if (!Status) + throw Status; +} + +void COptionsWindow::WriteText(const QString& Name, const QString& Value) +{ + SB_STATUS Status = m_pBox->SetText(Name, Value); + if (!Status) + throw Status; +} + +void COptionsWindow::WriteTextList(const QString& Setting, const QStringList& List) +{ + SB_STATUS Status = m_pBox->UpdateTextList(Setting, List, m_Template); + if (!Status) + throw Status; } void COptionsWindow::SaveConfig() { - if (m_GeneralChanged) + try { - m_pBox->SetText("BoxNameTitle", ui.cmbBoxIndicator->currentData().toString()); + if (m_GeneralChanged) + { + WriteText("BoxNameTitle", ui.cmbBoxIndicator->currentData().toString()); - QStringList BorderCfg; - BorderCfg.append(QString("#%1%2%3").arg(m_BorderColor.blue(), 2, 16, QChar('0')).arg(m_BorderColor.green(), 2, 16, QChar('0')).arg(m_BorderColor.red(), 2, 16, QChar('0'))); - BorderCfg.append(ui.cmbBoxBorder->currentData().toString()); - BorderCfg.append(QString::number(ui.spinBorderWidth->value())); - m_pBox->SetText("BorderColor", BorderCfg.join(",")); + QStringList BorderCfg; + BorderCfg.append(QString("#%1%2%3").arg(m_BorderColor.blue(), 2, 16, QChar('0')).arg(m_BorderColor.green(), 2, 16, QChar('0')).arg(m_BorderColor.red(), 2, 16, QChar('0'))); + BorderCfg.append(ui.cmbBoxBorder->currentData().toString()); + BorderCfg.append(QString::number(ui.spinBorderWidth->value())); + WriteText("BorderColor", BorderCfg.join(",")); - WriteAdvancedCheck(ui.chkBlockNetShare, "BlockNetworkFiles", "", "n"); - WriteAdvancedCheck(ui.chkBlockNetParam, "BlockNetParam", "", "n"); - WriteAdvancedCheck(ui.chkDropRights, "DropAdminRights", "y", ""); - WriteAdvancedCheck(ui.chkFakeElevation, "FakeAdminRights", "y", ""); + WriteAdvancedCheck(ui.chkBlockNetShare, "BlockNetworkFiles", "", "n"); + WriteAdvancedCheck(ui.chkBlockNetParam, "BlockNetParam", "", "n"); + WriteAdvancedCheck(ui.chkDropRights, "DropAdminRights", "y", ""); + WriteAdvancedCheck(ui.chkFakeElevation, "FakeAdminRights", "y", ""); - WriteAdvancedCheck(ui.chkBlockSpooler, "ClosePrintSpooler", "y", ""); - WriteAdvancedCheck(ui.chkOpenSpooler, "OpenPrintSpooler", "y", ""); - WriteAdvancedCheck(ui.chkPrintToFile, "AllowSpoolerPrintToFile", "y", ""); + WriteAdvancedCheck(ui.chkBlockSpooler, "ClosePrintSpooler", "y", ""); + WriteAdvancedCheck(ui.chkOpenSpooler, "OpenPrintSpooler", "y", ""); + WriteAdvancedCheck(ui.chkPrintToFile, "AllowSpoolerPrintToFile", "y", ""); - WriteAdvancedCheck(ui.chkOpenProtectedStorage, "OpenProtectedStorage", "y", ""); - if (ui.chkOpenCredentials->isEnabled()) - WriteAdvancedCheck(ui.chkOpenCredentials, "OpenCredentials", "y", ""); - WriteAdvancedCheck(ui.chkCloseClipBoard, "OpenClipboard", "n", ""); - //WriteAdvancedCheck(ui.chkOpenSmartCard, "OpenSmartCard", "", "n"); - //WriteAdvancedCheck(ui.chkOpenBluetooth, "OpenBluetooth", "y", ""); + WriteAdvancedCheck(ui.chkOpenProtectedStorage, "OpenProtectedStorage", "y", ""); + if (ui.chkOpenCredentials->isEnabled()) + WriteAdvancedCheck(ui.chkOpenCredentials, "OpenCredentials", "y", ""); + WriteAdvancedCheck(ui.chkCloseClipBoard, "OpenClipboard", "n", ""); + //WriteAdvancedCheck(ui.chkOpenSmartCard, "OpenSmartCard", "", "n"); + //WriteAdvancedCheck(ui.chkOpenBluetooth, "OpenBluetooth", "y", ""); - QStringList StartProgram; - QStringList StartService; - for (int i = 0; i < ui.treeAutoStart->topLevelItemCount(); i++) { - QTreeWidgetItem* pItem = ui.treeAutoStart->topLevelItem(i); - if (pItem->data(0, Qt::UserRole).toInt()) - StartService.append(pItem->text(1)); - else - StartProgram.append(pItem->text(1)); + QStringList StartProgram; + QStringList StartService; + for (int i = 0; i < ui.treeAutoStart->topLevelItemCount(); i++) { + QTreeWidgetItem* pItem = ui.treeAutoStart->topLevelItem(i); + if (pItem->data(0, Qt::UserRole).toInt()) + StartService.append(pItem->text(1)); + else + StartProgram.append(pItem->text(1)); + } + WriteTextList("StartProgram", StartProgram); + WriteTextList("StartService", StartService); + + QStringList RunCommands; + for (int i = 0; i < ui.treeRun->topLevelItemCount(); i++) { + QTreeWidgetItem* pItem = ui.treeRun->topLevelItem(i); + RunCommands.append(pItem->text(0) + "|" + pItem->text(1)); + } + WriteTextList("RunCommand", RunCommands); + + + WriteText("CopyLimitKb", ui.chkCopyLimit->isChecked() ? ui.txtCopyLimit->text() : "-1"); + WriteAdvancedCheck(ui.chkCopyPrompt, "PromptForFileMigration", "", "n"); + WriteAdvancedCheck(ui.chkNoCopyWarn, "CopyLimitSilent", "", "y"); + + WriteAdvancedCheck(ui.chkProtectBox, "NeverDelete", "y", ""); + WriteAdvancedCheck(ui.chkAutoEmpty, "AutoDelete", "y", ""); + + WriteAdvancedCheck(ui.chkRawDiskRead, "AllowRawDiskRead", "y", ""); + WriteAdvancedCheck(ui.chkRawDiskNotify, "NotifyDirectDiskAccess", "y", ""); + + m_GeneralChanged = false; } - m_pBox->UpdateTextList("StartProgram", StartProgram, m_Template); - m_pBox->UpdateTextList("StartService", StartService, m_Template); - QStringList RunCommands; - for (int i = 0; i < ui.treeRun->topLevelItemCount(); i++) { - QTreeWidgetItem* pItem = ui.treeRun->topLevelItem(i); - RunCommands.append(pItem->text(0) + "|" + pItem->text(1)); + if (m_GroupsChanged) + SaveGroups(); + + if (m_ForcedChanged) + SaveForced(); + + if (m_StopChanged) + SaveStop(); + + if (m_StartChanged) + { + WriteAdvancedCheck(ui.chkStartBlockMsg, "NotifyStartRunAccessDenied", "", "n"); + + m_StartChanged = false; } - m_pBox->UpdateTextList("RunCommand", RunCommands, m_Template); + + if (m_INetBlockChanged) + { + WriteAdvancedCheck(ui.chkINetBlockPrompt, "PromptForInternetAccess", "y", ""); + WriteAdvancedCheck(ui.chkINetBlockMsg, "NotifyInternetAccessDenied", "", "n"); + + m_INetBlockChanged = false; + } + + if (m_AccessChanged) + SaveAccessList(); + + if (m_RecoveryChanged) + SaveRecoveryList(); + + if (m_AdvancedChanged) + { + WriteAdvancedCheck(ui.chkPreferExternalManifest, "PreferExternalManifest", "y", ""); + WriteAdvancedCheck(ui.chkUseSbieWndStation, "UseSbieWndStation", "y", ""); + + WriteAdvancedCheck(ui.chkProtectSCM, "UnrestrictedSCM", "", "y"); + WriteAdvancedCheck(ui.chkNestedJobs, "AllowBoxedJobs", "y", ""); + WriteAdvancedCheck(ui.chkRestrictServices, "RunServicesAsSystem", "", "y"); + //WriteAdvancedCheck(ui.chkProtectSystem, "ExposeBoxedSystem", "", "y"); + + WriteAdvancedCheck(ui.chkOpenDevCMApi, "OpenDevCMApi", "y", ""); + //WriteAdvancedCheck(ui.chkOpenLsaSSPI, "BlockPassword", "n", ""); // OpenLsaSSPI + WriteAdvancedCheck(ui.chkOpenSamEndpoint, "OpenSamEndpoint", "y", ""); + WriteAdvancedCheck(ui.chkOpenLsaEndpoint, "OpenLsaEndpoint", "y", ""); - m_pBox->SetNum("CopyLimitKb", ui.chkCopyLimit->isChecked() ? ui.txtCopyLimit->text().toInt() : -1); - WriteAdvancedCheck(ui.chkCopyPrompt, "PromptForFileMigration", "", "n"); - WriteAdvancedCheck(ui.chkNoCopyWarn, "CopyLimitSilent", "", "y"); + QStringList AutoExec; + for (int i = 0; i < ui.lstAutoExec->count(); i++) + AutoExec.append(ui.lstAutoExec->item(i)->text()); + WriteTextList("AutoExec", AutoExec); - WriteAdvancedCheck(ui.chkProtectBox, "NeverDelete", "y", ""); - WriteAdvancedCheck(ui.chkAutoEmpty, "AutoDelete", "y", ""); + bool bGlobalNoMon = m_pBox->GetAPI()->GetGlobalSettings()->GetBool("DisableResourceMonitor", false); + WriteAdvancedCheck(ui.chkDisableMonitor, "DisableResourceMonitor", bGlobalNoMon ? "" : "y", bGlobalNoMon ? "n" : ""); + WriteAdvancedCheck(ui.chkCallTrace, "CallTrace", "*"); + WriteAdvancedCheck(ui.chkFileTrace, "FileTrace", "*"); + WriteAdvancedCheck(ui.chkPipeTrace, "PipeTrace", "*"); + WriteAdvancedCheck(ui.chkKeyTrace, "KeyTrace", "*"); + WriteAdvancedCheck(ui.chkIpcTrace, "IpcTrace", "*"); + WriteAdvancedCheck(ui.chkGuiTrace, "GuiTrace", "*"); + WriteAdvancedCheck(ui.chkComTrace, "ClsidTrace", "*"); + WriteAdvancedCheck(ui.chkDbgTrace, "DebugTrace", "y"); + WriteAdvancedCheck(ui.chkErrTrace, "ErrorTrace", "y"); + QSharedPointer pBoxPlus = m_pBox.objectCast(); + if (pBoxPlus) + pBoxPlus->SetLogApi(ui.chkApiTrace->isChecked()); - WriteAdvancedCheck(ui.chkRawDiskRead, "AllowRawDiskRead", "y", ""); - WriteAdvancedCheck(ui.chkRawDiskNotify, "NotifyDirectDiskAccess", "y", ""); + WriteAdvancedCheck(ui.chkHideOtherBoxes, "HideOtherBoxes"); - m_GeneralChanged = false; + QStringList Processes; + for (int i = 0; i < ui.lstProcesses->count(); i++) + Processes.append(ui.lstProcesses->item(i)->text()); + WriteTextList("HideHostProcess", Processes); + + QStringList Users; + for (int i = 0; i < ui.lstUsers->count(); i++) + Users.append(ui.lstUsers->item(i)->text()); + WriteText("Enabled", Users.count() > 0 ? "y," + Users.join(",") : "y"); + WriteAdvancedCheck(ui.chkMonitorAdminOnly, "MonitorAdminOnly"); + + m_AdvancedChanged = false; + } + + foreach(QCheckBox * pCheck, m_DebugOptions.keys()) + { + SDbgOpt& DbgOption = m_DebugOptions[pCheck]; + if (!DbgOption.Changed) + continue; + WriteAdvancedCheck(pCheck, DbgOption.Name, DbgOption.Value); + DbgOption.Changed = false; + } + + if (m_TemplatesChanged) + SaveTemplates(); + + if (m_FoldersChanged) + SaveFolders(); } - - if (m_GroupsChanged) - SaveGroups(); - - if (m_ForcedChanged) - SaveForced(); - - if (m_StopChanged) - SaveStop(); - - if (m_StartChanged) + catch (SB_STATUS Status) { - WriteAdvancedCheck(ui.chkStartBlockMsg, "NotifyStartRunAccessDenied", "", "n"); - - m_StartChanged = false; + theGUI->CheckResults(QList() << Status); } - - if (m_INetBlockChanged) - { - WriteAdvancedCheck(ui.chkINetBlockPrompt, "PromptForInternetAccess", "y", ""); - WriteAdvancedCheck(ui.chkINetBlockMsg, "NotifyInternetAccessDenied", "", "n"); - - m_INetBlockChanged = false; - } - - if (m_AccessChanged) - SaveAccessList(); - - if (m_RecoveryChanged) - SaveRecoveryList(); - - if (m_AdvancedChanged) - { - WriteAdvancedCheck(ui.chkPreferExternalManifest, "PreferExternalManifest", "y", ""); - WriteAdvancedCheck(ui.chkUseSbieWndStation, "UseSbieWndStation", "y", ""); - - WriteAdvancedCheck(ui.chkProtectSCM, "UnrestrictedSCM", "", "y"); - WriteAdvancedCheck(ui.chkRestrictServices, "RunServicesAsSystem", "", "y"); - WriteAdvancedCheck(ui.chkProtectSystem, "ExposeBoxedSystem", "", "y"); - - WriteAdvancedCheck(ui.chkOpenDevCMApi, "OpenDevCMApi", "y", ""); - WriteAdvancedCheck(ui.chkOpenLsaSSPI, "BlockPassword", "n", ""); // OpenLsaSSPI - WriteAdvancedCheck(ui.chkOpenSamEndpoint, "OpenSamEndpoint", "y", ""); - WriteAdvancedCheck(ui.chkOpenLsaEndpoint, "OpenLsaEndpoint", "y", ""); - - WriteAdvancedCheck(ui.chkAddToJob, "NoAddProcessToJob", "", "y"); - - QStringList AutoExec; - for (int i = 0; i < ui.lstAutoExec->count(); i++) - AutoExec.append(ui.lstAutoExec->item(i)->text()); - m_pBox->UpdateTextList("AutoExec", AutoExec, m_Template); - - bool bGlobalNoMon = m_pBox->GetAPI()->GetGlobalSettings()->GetBool("DisableResourceMonitor", false); - WriteAdvancedCheck(ui.chkDisableMonitor, "DisableResourceMonitor", bGlobalNoMon ? "" : "y", bGlobalNoMon ? "n" : ""); - WriteAdvancedCheck(ui.chkCallTrace, "CallTrace", "*"); - WriteAdvancedCheck(ui.chkFileTrace, "FileTrace", "*"); - WriteAdvancedCheck(ui.chkPipeTrace, "PipeTrace", "*"); - WriteAdvancedCheck(ui.chkKeyTrace, "KeyTrace", "*"); - WriteAdvancedCheck(ui.chkIpcTrace, "IpcTrace", "*"); - WriteAdvancedCheck(ui.chkGuiTrace, "GuiTrace", "*"); - WriteAdvancedCheck(ui.chkComTrace, "ClsidTrace", "*"); - WriteAdvancedCheck(ui.chkDbgTrace, "DebugTrace", "y"); - WriteAdvancedCheck(ui.chkErrTrace, "ErrorTrace", "y"); - QSharedPointer pBoxPlus = m_pBox.objectCast(); - if (pBoxPlus) - pBoxPlus->SetLogApi(ui.chkApiTrace->isChecked()); - - WriteAdvancedCheck(ui.chkHideOtherBoxes, "HideOtherBoxes"); - - QStringList Processes; - for (int i = 0; i < ui.lstProcesses->count(); i++) - Processes.append(ui.lstProcesses->item(i)->text()); - m_pBox->UpdateTextList("HideHostProcess", Processes, m_Template); - - QStringList Users; - for (int i = 0; i < ui.lstUsers->count(); i++) - Users.append(ui.lstUsers->item(i)->text()); - m_pBox->SetText("Enabled", Users.count() > 0 ? "y," + Users.join(",") : "y"); - WriteAdvancedCheck(ui.chkMonitorAdminOnly, "MonitorAdminOnly"); - - m_AdvancedChanged = false; - } - - foreach(QCheckBox* pCheck, m_DebugOptions.keys()) - { - SDbgOpt& DbgOption = m_DebugOptions[pCheck]; - if (!DbgOption.Changed) - continue; - WriteAdvancedCheck(pCheck, DbgOption.Name, DbgOption.Value); - DbgOption.Changed = false; - } - - if (m_TemplatesChanged) - SaveTemplates(); - - if (m_FoldersChanged) - SaveFolders(); } void COptionsWindow::apply() @@ -1009,6 +1005,8 @@ void COptionsWindow::LoadGroups() pItem->setText(0, GroupName); for (int i = 0; i < Entries.count(); i++) { + if (Entries[i].isEmpty()) + continue; QTreeWidgetItem* pSubItem = new QTreeWidgetItem(); SetProgramItem(Entries[i], pSubItem, 0); pItem->addChild(pSubItem); @@ -1036,7 +1034,7 @@ void COptionsWindow::SaveGroups() ProcessGroups.append(Group); } - m_pBox->UpdateTextList("ProcessGroup", ProcessGroups, m_Template); + WriteTextList("ProcessGroup", ProcessGroups); m_GroupsChanged = false; } @@ -1129,7 +1127,6 @@ void COptionsWindow::OnDelProg() void COptionsWindow::CopyGroupToList(const QString& Groupe, QTreeWidget* pTree) { pTree->clear(); - for (int i = 0; i < ui.treeGroups->topLevelItemCount(); i++) { QTreeWidgetItem* pItem = ui.treeGroups->topLevelItem(i); @@ -1217,8 +1214,8 @@ void COptionsWindow::SaveForced() } } - m_pBox->UpdateTextList("ForceProcess", ForceProcess, m_Template); - m_pBox->UpdateTextList("ForceFolder", ForceFolder, m_Template); + WriteTextList("ForceProcess", ForceProcess); + WriteTextList("ForceFolder", ForceFolder); m_ForcedChanged = false; } @@ -1316,8 +1313,8 @@ void COptionsWindow::SaveStop() } } - m_pBox->UpdateTextList("LingerProcess", LingerProcess, m_Template); - m_pBox->UpdateTextList("LeaderProcess", LeaderProcess, m_Template); + WriteTextList("LingerProcess", LingerProcess); + WriteTextList("LeaderProcess", LeaderProcess); m_StopChanged = false; } @@ -1743,13 +1740,13 @@ QString COptionsWindow::MakeAccessStr(EAccessType Type, EAccessMode Mode) return "Unknown"; } -void COptionsWindow::OnAccessItemClicked(QTreeWidgetItem* pItem, int Column) +/*void COptionsWindow::OnAccessItemClicked(QTreeWidgetItem* pItem, int Column) { if (Column != 0) return; CloseAccessEdit(pItem); -} +}*/ void COptionsWindow::CloseAccessEdit(bool bSave) { @@ -1782,7 +1779,7 @@ void COptionsWindow::CloseAccessEdit(QTreeWidgetItem* pItem, bool bSave) if (bSave) { - if (pItem->data(0, Qt::UserRole).toInt() == eCOM) + if (pItem->data(0, Qt::UserRole).toInt() == eCOM && !pPath->text().isEmpty()) { bool isGUID = pPath->text().length() == 38 && pPath->text().left(1) == "{" && pPath->text().right(1) == "}"; switch (pMode->currentData().toInt()) @@ -1809,13 +1806,13 @@ void COptionsWindow::CloseAccessEdit(QTreeWidgetItem* pItem, bool bSave) pItem->setData(2, Qt::UserRole, pMode->currentData()); pItem->setText(3, pPath->text()); pItem->setData(3, Qt::UserRole, pPath->text()); + + m_AccessChanged = true; } ui.treeAccess->setItemWidget(pItem, 1, NULL); ui.treeAccess->setItemWidget(pItem, 2, NULL); ui.treeAccess->setItemWidget(pItem, 3, NULL); - - m_AccessChanged = true; } QList COptionsWindow::GetAccessModes(EAccessType Type) @@ -1937,7 +1934,7 @@ void COptionsWindow::SaveAccessList() } foreach(const QString& Key, Keys) - m_pBox->UpdateTextList(Key, AccessMap[Key], m_Template); + WriteTextList(Key, AccessMap[Key]); m_AccessChanged = false; } @@ -2014,8 +2011,8 @@ void COptionsWindow::SaveRecoveryList() } } - m_pBox->UpdateTextList("RecoverFolder", RecoverFolder, m_Template); - m_pBox->UpdateTextList("AutoRecoverIgnore", AutoRecoverIgnore, m_Template); + WriteTextList("RecoverFolder", RecoverFolder); + WriteTextList("AutoRecoverIgnore", AutoRecoverIgnore); WriteAdvancedCheck(ui.chkAutoRecovery, "AutoRecover", "y", ""); @@ -2411,7 +2408,7 @@ void COptionsWindow::OnDelTemplates() void COptionsWindow::SaveTemplates() { - m_pBox->UpdateTextList("Template", m_BoxTemplates, m_Template); + WriteTextList("Template", m_BoxTemplates); m_TemplatesChanged = false; } diff --git a/SandboxiePlus/SandMan/Windows/OptionsWindow.h b/SandboxiePlus/SandMan/Windows/OptionsWindow.h index 1cb4b112..f936a196 100644 --- a/SandboxiePlus/SandMan/Windows/OptionsWindow.h +++ b/SandboxiePlus/SandMan/Windows/OptionsWindow.h @@ -60,7 +60,7 @@ private slots: void OnAddINetProg(); void OnDelINetProg(); - void OnAccessItemClicked(QTreeWidgetItem* pItem, int Column); + //void OnAccessItemClicked(QTreeWidgetItem* pItem, int Column); void OnAccessItemDoubleClicked(QTreeWidgetItem* pItem, int Column); void OnAccessSelectionChanged() { CloseAccessEdit(); } @@ -264,6 +264,8 @@ private: void ReadAdvancedCheck(const QString& Name, QCheckBox* pCheck, const QString& Value = "y"); void WriteAdvancedCheck(QCheckBox* pCheck, const QString& Name, const QString& Value = "y"); void WriteAdvancedCheck(QCheckBox* pCheck, const QString& Name, const QString& OnValue, const QString& OffValue); + void WriteText(const QString& Name, const QString& Value); + void WriteTextList(const QString& Setting, const QStringList& List); Ui::OptionsWindow ui; diff --git a/SandboxiePlus/SandMan/Windows/PopUpWindow.cpp b/SandboxiePlus/SandMan/Windows/PopUpWindow.cpp index 079c587d..49dc8509 100644 --- a/SandboxiePlus/SandMan/Windows/PopUpWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/PopUpWindow.cpp @@ -39,14 +39,18 @@ CPopUpWindow::CPopUpWindow(QWidget* parent) : QMainWindow(parent) m_pActionCopy->setShortcutContext(Qt::WidgetWithChildrenShortcut); this->addAction(m_pActionCopy); - // set always on top - SetWindowPos((HWND)this->winId(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + m_iTopMost = 0; + SetWindowPos((HWND)this->winId(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + + m_uTimerID = startTimer(1000); m_ResetPosition = !restoreGeometry(theConf->GetBlob("PopUpWindow/Window_Geometry")); } CPopUpWindow::~CPopUpWindow() { + killTimer(m_uTimerID); + theConf->SetBlob("PopUpWindow/Window_Geometry", saveGeometry()); } @@ -79,6 +83,8 @@ void CPopUpWindow::RemoveEntry(CPopUpEntry* pEntry) void CPopUpWindow::Show() { + Poke(); + QScreen *screen = this->windowHandle()->screen(); QRect scrRect = screen->availableGeometry(); @@ -100,6 +106,14 @@ void CPopUpWindow::Show() this->show(); } +void CPopUpWindow::Poke() +{ + if (!this->isVisible() || m_iTopMost <= -5) { + SetWindowPos((HWND)this->winId(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + m_iTopMost = 5; + } +} + void CPopUpWindow::closeEvent(QCloseEvent *e) { for (int i = 0; i < ui.table->rowCount(); i++) @@ -117,6 +131,16 @@ void CPopUpWindow::closeEvent(QCloseEvent *e) this->hide(); } +void CPopUpWindow::timerEvent(QTimerEvent* pEvent) +{ + if (pEvent->timerId() != m_uTimerID) + return; + + if (m_iTopMost > -5 && (--m_iTopMost == 0)) { + SetWindowPos((HWND)this->winId(), HWND_NOTOPMOST , 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + } +} + void CPopUpWindow::AddLogMessage(const QString& Message, quint32 MsgCode, const QStringList& MsgData, quint32 ProcessId) { if (IsMessageHidden(MsgCode, MsgData)) diff --git a/SandboxiePlus/SandMan/Windows/PopUpWindow.h b/SandboxiePlus/SandMan/Windows/PopUpWindow.h index 527a46f2..86f425d0 100644 --- a/SandboxiePlus/SandMan/Windows/PopUpWindow.h +++ b/SandboxiePlus/SandMan/Windows/PopUpWindow.h @@ -428,6 +428,7 @@ signals: public slots: virtual void Show(); + virtual void Poke(); virtual void ReloadHiddenMessages(); private slots: @@ -447,6 +448,8 @@ private slots: protected: virtual void closeEvent(QCloseEvent *e); + void timerEvent(QTimerEvent* pEvent); + virtual void AddEntry(CPopUpEntry* pEntry); virtual void RemoveEntry(CPopUpEntry* pEntry); @@ -459,5 +462,7 @@ protected: private: bool m_ResetPosition; QAction* m_pActionCopy; + int m_uTimerID; + int m_iTopMost; Ui::PopUpWindow ui; }; diff --git a/SandboxiePlus/SandMan/Windows/RecoveryWindow.cpp b/SandboxiePlus/SandMan/Windows/RecoveryWindow.cpp index ac32d9ae..5df73033 100644 --- a/SandboxiePlus/SandMan/Windows/RecoveryWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/RecoveryWindow.cpp @@ -94,6 +94,7 @@ CRecoveryWindow::~CRecoveryWindow() int CRecoveryWindow::exec() { + //QDialog::setWindowModality(Qt::WindowModal); ui.btnDeleteAll->setVisible(true); return QDialog::exec(); } diff --git a/SandboxiePlus/SandMan/Windows/SelectBoxWindow.cpp b/SandboxiePlus/SandMan/Windows/SelectBoxWindow.cpp new file mode 100644 index 00000000..255fc88a --- /dev/null +++ b/SandboxiePlus/SandMan/Windows/SelectBoxWindow.cpp @@ -0,0 +1,112 @@ +#include "stdafx.h" +#include "SelectBoxWindow.h" +#include "SandMan.h" +#include "../MiscHelpers/Common/Settings.h" +#include "../SbiePlusAPI.h" + +#if defined(Q_OS_WIN) +#include +#include +#include +#endif + +CSelectBoxWindow::CSelectBoxWindow(const QStringList& Commands, QWidget *parent) + : QDialog(parent) +{ + m_Commands = Commands; + + Qt::WindowFlags flags = windowFlags(); + flags |= Qt::CustomizeWindowHint; + //flags &= ~Qt::WindowContextHelpButtonHint; + //flags &= ~Qt::WindowSystemMenuHint; + //flags &= ~Qt::WindowMinMaxButtonsHint; + //flags |= Qt::WindowMinimizeButtonHint; + //flags &= ~Qt::WindowCloseButtonHint; + flags &= ~Qt::WindowContextHelpButtonHint; + //flags &= ~Qt::WindowSystemMenuHint; + setWindowFlags(flags); + + //setWindowState(Qt::WindowActive); + SetForegroundWindow((HWND)QWidget::winId()); + + ui.setupUi(this); + this->setWindowTitle(tr("Sandboxie-Plus - Run Sandboxed")); + + + connect(ui.radBoxed, SIGNAL(clicked(bool)), this, SLOT(OnBoxType())); + connect(ui.radUnBoxed, SIGNAL(clicked(bool)), this, SLOT(OnBoxType())); + + connect(ui.buttonBox, SIGNAL(accepted()), SLOT(OnRun())); + connect(ui.buttonBox, SIGNAL(rejected()), SLOT(reject())); + + QMap Boxes = theAPI->GetAllBoxes(); + + + foreach(const CSandBoxPtr & pBox, Boxes) + { + CSandBoxPlus* pBoxEx = qobject_cast(pBox.data()); + + QTreeWidgetItem* pItem = new QTreeWidgetItem(); + pItem->setText(0, pBox->GetName().replace("_", " ")); + pItem->setData(0, Qt::UserRole, pBox->GetName()); + pItem->setData(0, Qt::DecorationRole, theGUI->GetBoxIcon(pBox->GetActiveProcessCount(), pBoxEx->GetType())); + ui.treeBoxes->addTopLevelItem(pItem); + + if (pBox->GetName().toLower() == "defaultbox") + ui.treeBoxes->setCurrentItem(pItem); + } + + //restoreGeometry(theConf->GetBlob("SelectBoxWindow/Window_Geometry")); +} + +CSelectBoxWindow::~CSelectBoxWindow() +{ + //theConf->SetBlob("SelectBoxWindow/Window_Geometry", saveGeometry()); +} + +void CSelectBoxWindow::closeEvent(QCloseEvent *e) +{ + //emit Closed(); + this->deleteLater(); +} + +void CSelectBoxWindow::OnBoxType() +{ + ui.treeBoxes->setEnabled(!ui.radUnBoxed->isChecked()); +} + +void CSelectBoxWindow::OnRun() +{ + QTreeWidgetItem* pItem = ui.treeBoxes->currentItem(); + + QString BoxName; + if (ui.radUnBoxed->isChecked()) + { + if (QMessageBox("Sandboxie-Plus", tr("Are you shure you want to run the program outside the sandbox?"), QMessageBox::Question, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this).exec() != QMessageBox::Yes) + return; + pItem = NULL; + } + else if (pItem == NULL) { + QMessageBox("Sandboxie-Plus", tr("Please select a sandbox."), QMessageBox::Information, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton, this).exec(); + return; + } + else { + BoxName = pItem->data(0, Qt::UserRole).toString(); + } + + + //QList Results; + foreach(const QString & Command, m_Commands) + { + QString StartCmd = "\"" + theAPI->GetStartPath() + "\"" + (ui.chkAdmin->isChecked() ? " /elevated" : ""); + if (!BoxName.isEmpty()) + StartCmd += " /box:" + BoxName + " "; + else + StartCmd += " /disable_force "; + StartCmd += Command; + QProcess::startDetached(StartCmd); + } + //CSandMan::CheckResults(Results); + + close(); +} \ No newline at end of file diff --git a/SandboxiePlus/SandMan/Windows/SelectBoxWindow.h b/SandboxiePlus/SandMan/Windows/SelectBoxWindow.h new file mode 100644 index 00000000..4622bcfc --- /dev/null +++ b/SandboxiePlus/SandMan/Windows/SelectBoxWindow.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "ui_SelectBoxWindow.h" +#include "SbiePlusAPI.h" + +class CSelectBoxWindow : public QDialog +{ + Q_OBJECT + +public: + CSelectBoxWindow(const QStringList& Commands, QWidget *parent = Q_NULLPTR); + ~CSelectBoxWindow(); + +private slots: + void OnBoxType(); + void OnRun(); + +protected: + void closeEvent(QCloseEvent* e); + + QStringList m_Commands; + +private: + Ui::SelectBoxWindow ui; +}; diff --git a/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp b/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp index 93aa663f..88be33f5 100644 --- a/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/SettingsWindow.cpp @@ -7,6 +7,35 @@ #include "../QSbieAPI/SbieUtils.h" +QSize CustomTabStyle::sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const { + QSize s = QProxyStyle::sizeFromContents(type, option, size, widget); + if (type == QStyle::CT_TabBarTab) { + s.transpose(); + if(theGUI->m_DarkTheme) + s.setHeight(s.height() * 13 / 10); + else + s.setHeight(s.height() * 15 / 10); + s.setWidth(s.width() * 11 / 10); // for the the icon + } + return s; +} + +void CustomTabStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const { + if (element == CE_TabBarTabLabel) { + if (const QStyleOptionTab* tab = qstyleoption_cast(option)) { + QStyleOptionTab opt(*tab); + opt.shape = QTabBar::RoundedNorth; + //opt.iconSize = QSize(32, 32); + opt.iconSize = QSize(24, 24); + QProxyStyle::drawControl(element, &opt, painter, widget); + return; + } + } + QProxyStyle::drawControl(element, option, painter, widget); +} + + + int CSettingsWindow__Chk2Int(Qt::CheckState state) { switch (state) { @@ -45,6 +74,17 @@ CSettingsWindow::CSettingsWindow(QWidget *parent) bool bAlwaysOnTop = theConf->GetBool("Options/AlwaysOnTop", false); this->setWindowFlag(Qt::WindowStaysOnTopHint, bAlwaysOnTop); + + /*ui.tabs->setTabPosition(QTabWidget::West); + ui.tabs->tabBar()->setStyle(new CustomTabStyle(ui.tabs->tabBar()->style()));*/ + + ui.tabs->setTabIcon(0, CSandMan::GetIcon("Options")); + ui.tabs->setTabIcon(1, CSandMan::GetIcon("Maintenance")); + ui.tabs->setTabIcon(2, CSandMan::GetIcon("Wall")); + ui.tabs->setTabIcon(3, CSandMan::GetIcon("Advanced")); + ui.tabs->setTabIcon(4, CSandMan::GetIcon("Support")); + + ui.tabs->setCurrentIndex(0); ui.uiLang->addItem(tr("Auto Detection"), ""); @@ -57,12 +97,85 @@ CSettingsWindow::CSettingsWindow(QWidget *parent) QString Lang = Locale.nativeLanguageName(); ui.uiLang->addItem(Lang, Code); } + + LoadSettings(); + + connect(ui.chkShowTray, SIGNAL(stateChanged(int)), this, SLOT(OnChange())); + //connect(ui.chkUseCycles, SIGNAL(stateChanged(int)), this, SLOT(OnChange())); + + + m_WarnProgsChanged = false; + + connect(ui.chkPassRequired, SIGNAL(stateChanged(int)), this, SLOT(OnChange())); + connect(ui.btnSetPassword, SIGNAL(clicked(bool)), this, SLOT(OnSetPassword())); + + connect(ui.chkStartBlock, SIGNAL(stateChanged(int)), this, SLOT(OnWarnChanged())); + + connect(ui.chkStartBlockMsg, SIGNAL(stateChanged(int)), this, SLOT(OnWarnChanged())); + connect(ui.btnAddWarnProg, SIGNAL(clicked(bool)), this, SLOT(OnAddWarnProg())); + connect(ui.btnAddWarnFolder, SIGNAL(clicked(bool)), this, SLOT(OnAddWarnFolder())); + connect(ui.btnDelWarnProg, SIGNAL(clicked(bool)), this, SLOT(OnDelWarnProg())); + + connect(ui.btnBrowse, SIGNAL(clicked(bool)), this, SLOT(OnBrowse())); + + connect(ui.chkAutoRoot, SIGNAL(stateChanged(int)), this, SLOT(OnChange())); + + + connect(ui.btnAddCompat, SIGNAL(clicked(bool)), this, SLOT(OnAddCompat())); + connect(ui.btnDelCompat, SIGNAL(clicked(bool)), this, SLOT(OnDelCompat())); + m_CompatLoaded = 0; + m_CompatChanged = false; + ui.chkNoCompat->setChecked(!theConf->GetBool("Options/AutoRunSoftCompat", true)); + + connect(ui.treeCompat, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(OnTemplateClicked(QTreeWidgetItem*, int))); + + connect(ui.lblSupport, SIGNAL(linkActivated(const QString&)), this, SLOT(OnSupport(const QString&))); + + + connect(ui.tabs, SIGNAL(currentChanged(int)), this, SLOT(OnTab())); + + connect(ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked(bool)), this, SLOT(ok())); + connect(ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked(bool)), this, SLOT(apply())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + restoreGeometry(theConf->GetBlob("SettingsWindow/Window_Geometry")); +} + +CSettingsWindow::~CSettingsWindow() +{ + theConf->SetBlob("SettingsWindow/Window_Geometry",saveGeometry()); +} + +void CSettingsWindow::OnSupport(const QString& url) +{ + QDesktopServices::openUrl(url); +} + +void CSettingsWindow::showCompat() +{ + m_CompatLoaded = 2; + ui.tabs->setCurrentWidget(ui.tabCompat); + show(); +} + +void CSettingsWindow::closeEvent(QCloseEvent *e) +{ + emit Closed(); + this->deleteLater(); +} + +void CSettingsWindow::LoadSettings() +{ ui.uiLang->setCurrentIndex(ui.uiLang->findData(theConf->GetString("Options/UiLanguage"))); ui.chkAutoStart->setChecked(IsAutorunEnabled()); - ui.chkSvcStart->setChecked(theAPI->GetUserSettings()->GetBool("SbieCtrl_EnableAutoStart", true)); - - ui.chkAutoUpdate->setCheckState(CSettingsWindow__Int2Chk(theConf->GetInt("Options/CheckForUpdates", 2))); + if (theAPI->GetUserSettings()->GetBool("SbieCtrl_EnableAutoStart", true)) { + if (theAPI->GetUserSettings()->GetText("SbieCtrl_AutoStartAgent", "") != "SandMan.exe") + ui.chkSvcStart->setChecked(true); + else + ui.chkSvcStart->setCheckState(Qt::PartiallyChecked); + } else + ui.chkSvcStart->setChecked(false); ui.chkShellMenu->setCheckState((Qt::CheckState)CSbieUtils::IsContextMenu()); @@ -74,6 +187,9 @@ CSettingsWindow::CSettingsWindow(QWidget *parent) ui.chkShowRecovery->setChecked(theConf->GetBool("Options/ShowRecovery", false)); + ui.chkPanic->setChecked(theConf->GetBool("Options/EnablePanicKey", false)); + ui.keyPanic->setKeySequence(QKeySequence(theConf->GetString("Options/PanicKeySequence", "Ctrl+Cancel"))); + ui.chkWatchConfig->setChecked(theConf->GetBool("Options/WatchIni", true)); ui.onClose->addItem(tr("Close to Tray"), "ToTray"); @@ -83,8 +199,6 @@ CSettingsWindow::CSettingsWindow(QWidget *parent) ui.chkShowTray->setChecked(theConf->GetBool("Options/ShowSysTray", true)); - connect(ui.chkShowTray, SIGNAL(stateChanged(int)), this, SLOT(OnChange())); - //connect(ui.chkUseCycles, SIGNAL(stateChanged(int)), this, SLOT(OnChange())); if (theAPI->IsConnected()) { @@ -100,19 +214,12 @@ CSettingsWindow::CSettingsWindow(QWidget *parent) ui.chkAdminOnly->setChecked(theAPI->GetGlobalSettings()->GetBool("EditAdminOnly", false)); ui.chkPassRequired->setChecked(!theAPI->GetGlobalSettings()->GetText("EditPassword", "").isEmpty()); - connect(ui.chkPassRequired, SIGNAL(stateChanged(int)), this, SLOT(OnChange())); - connect(ui.btnSetPassword, SIGNAL(clicked(bool)), this, SLOT(OnSetPassword())); ui.chkAdminOnlyFP->setChecked(theAPI->GetGlobalSettings()->GetBool("ForceDisableAdminOnly", false)); ui.chkClearPass->setChecked(theAPI->GetGlobalSettings()->GetBool("ForgetPassword", false)); ui.chkStartBlock->setChecked(theAPI->GetGlobalSettings()->GetBool("StartRunAlertDenied", false)); - connect(ui.chkStartBlock, SIGNAL(stateChanged(int)), this, SLOT(OnWarnChanged())); ui.chkStartBlockMsg->setChecked(theAPI->GetGlobalSettings()->GetBool("NotifyStartRunAccessDenied", true)); - connect(ui.chkStartBlockMsg, SIGNAL(stateChanged(int)), this, SLOT(OnWarnChanged())); - connect(ui.btnAddWarnProg, SIGNAL(clicked(bool)), this, SLOT(OnAddWarnProg())); - connect(ui.btnAddWarnFolder, SIGNAL(clicked(bool)), this, SLOT(OnAddWarnFolder())); - connect(ui.btnDelWarnProg, SIGNAL(clicked(bool)), this, SLOT(OnDelWarnProg())); - + foreach(const QString& Value, theAPI->GetGlobalSettings()->GetTextList("AlertProcess", false)) AddWarnEntry(Value, 1); @@ -137,72 +244,41 @@ CSettingsWindow::CSettingsWindow(QWidget *parent) ui.btnAddCompat->setEnabled(false); ui.btnDelCompat->setEnabled(false); } - m_WarnProgsChanged = false; - connect(ui.btnBrowse, SIGNAL(clicked(bool)), this, SLOT(OnBrowse())); int PortableRootDir = theConf->GetInt("Options/PortableRootDir", -1); if (PortableRootDir != -1 && theConf->IsPortable()) ui.chkAutoRoot->setChecked(PortableRootDir == 0 ? Qt::Unchecked : Qt::Checked); else ui.chkAutoRoot->setVisible(false); - connect(ui.chkAutoRoot, SIGNAL(stateChanged(int)), this, SLOT(OnChange())); - connect(ui.btnAddCompat, SIGNAL(clicked(bool)), this, SLOT(OnAddCompat())); - connect(ui.btnDelCompat, SIGNAL(clicked(bool)), this, SLOT(OnDelCompat())); - m_CompatLoaded = 0; - m_CompatChanged = false; - - ui.chkNoCompat->setChecked(!theConf->GetBool("Options/AutoRunSoftCompat", true)); - - connect(ui.treeCompat, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(OnTemplateClicked(QTreeWidgetItem*, int))); - - connect(ui.tabs, SIGNAL(currentChanged(int)), this, SLOT(OnTab())); - - connect(ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked(bool)), this, SLOT(ok())); - connect(ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked(bool)), this, SLOT(apply())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - - restoreGeometry(theConf->GetBlob("SettingsWindow/Window_Geometry")); + ui.chkAutoUpdate->setCheckState(CSettingsWindow__Int2Chk(theConf->GetInt("Options/CheckForUpdates", 2))); + ui.chkAutoInstall->setVisible(false); // todo implement smart auto updater OnChange(); } -CSettingsWindow::~CSettingsWindow() -{ - theConf->SetBlob("SettingsWindow/Window_Geometry",saveGeometry()); -} - -void CSettingsWindow::showCompat() -{ - m_CompatLoaded = 2; - ui.tabs->setCurrentWidget(ui.tabCompat); - show(); -} - -void CSettingsWindow::closeEvent(QCloseEvent *e) -{ - emit Closed(); - this->deleteLater(); -} - -void CSettingsWindow::apply() +void CSettingsWindow::SaveSettings() { theConf->SetValue("Options/UiLanguage", ui.uiLang->currentData()); theConf->SetValue("Options/UseDarkTheme", CSettingsWindow__Chk2Int(ui.chkDarkTheme->checkState())); AutorunEnable(ui.chkAutoStart->isChecked()); - theAPI->GetUserSettings()->SetBool("SbieCtrl_EnableAutoStart", ui.chkSvcStart->isChecked()); - theConf->SetValue("Options/CheckForUpdates", CSettingsWindow__Chk2Int(ui.chkAutoUpdate->checkState())); + if (ui.chkSvcStart->checkState() == Qt::Checked) { + theAPI->GetUserSettings()->SetBool("SbieCtrl_EnableAutoStart", true); + theAPI->GetUserSettings()->SetText("SbieCtrl_AutoStartAgent", "SandMan.exe"); + } else if (ui.chkSvcStart->checkState() == Qt::Unchecked) + theAPI->GetUserSettings()->SetBool("SbieCtrl_EnableAutoStart", false); if (ui.chkShellMenu->checkState() != CSbieUtils::IsContextMenu()) { - if (ui.chkShellMenu->isChecked()) - CSbieUtils::AddContextMenu(QApplication::applicationDirPath().replace("/", "\\") + "\\Start.exe"); - else + if (ui.chkShellMenu->isChecked()) { + CSbieUtils::AddContextMenu(QApplication::applicationDirPath().replace("/", "\\") + "\\SandMan.exe", + QApplication::applicationDirPath().replace("/", "\\") + "\\Start.exe"); + } else CSbieUtils::RemoveContextMenu(); } @@ -212,6 +288,9 @@ void CSettingsWindow::apply() theConf->SetValue("Options/ShowRecovery", ui.chkShowRecovery->isChecked()); + theConf->SetValue("Options/EnablePanicKey", ui.chkPanic->isChecked()); + theConf->SetValue("Options/PanicKeySequence", ui.keyPanic->keySequence().toString()); + theConf->SetValue("Options/WatchIni", ui.chkWatchConfig->isChecked()); theConf->SetValue("Options/OnClose", ui.onClose->currentData()); @@ -305,9 +384,15 @@ void CSettingsWindow::apply() emit OptionsChanged(); } +void CSettingsWindow::apply() +{ + SaveSettings(); + LoadSettings(); +} + void CSettingsWindow::ok() { - apply(); + SaveSettings(); this->close(); } diff --git a/SandboxiePlus/SandMan/Windows/SettingsWindow.h b/SandboxiePlus/SandMan/Windows/SettingsWindow.h index 2e3925b2..c99c29c4 100644 --- a/SandboxiePlus/SandMan/Windows/SettingsWindow.h +++ b/SandboxiePlus/SandMan/Windows/SettingsWindow.h @@ -2,6 +2,16 @@ #include #include "ui_SettingsWindow.h" +#include + +class CustomTabStyle : public QProxyStyle { +public: + CustomTabStyle(QStyle* style = 0) : QProxyStyle(style) {} + + QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget) const; + void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const; +}; + class CSettingsWindow : public QDialog { @@ -42,11 +52,16 @@ private slots: void OnAddCompat(); void OnDelCompat(); + void OnSupport(const QString& url); + protected: void closeEvent(QCloseEvent *e); void AddWarnEntry(const QString& Name, int type); + void LoadSettings(); + void SaveSettings(); + int m_CompatLoaded; QString m_NewPassword; bool m_WarnProgsChanged; diff --git a/SandboxiePlus/SandMan/main.cpp b/SandboxiePlus/SandMan/main.cpp index 55aabbab..e63fb556 100644 --- a/SandboxiePlus/SandMan/main.cpp +++ b/SandboxiePlus/SandMan/main.cpp @@ -31,7 +31,15 @@ int main(int argc, char *argv[]) return 0; } - if (app.sendMessage("ShowWnd")) + QString CommandLine; + QStringList Args = QCoreApplication::arguments(); + int BoxPos = Args.indexOf("/box:__ask__"); + if (BoxPos != -1) { + CommandLine = Args[BoxPos + 1]; + if(app.sendMessage("Run:" + CommandLine)) + return 0; + } + else if (app.sendMessage("ShowWnd")) return 0; theConf = new CSettings("Sandboxie-Plus"); @@ -39,7 +47,10 @@ int main(int argc, char *argv[]) //QThreadPool::globalInstance()->setMaxThreadCount(theConf->GetInt("Options/MaxThreadPool", 10)); CSandMan* pWnd = new CSandMan(); + QObject::connect(&app, SIGNAL(messageReceived(const QString&)), pWnd, SLOT(OnMessage(const QString&))); + if (!CommandLine.isEmpty()) + QMetaObject::invokeMethod(pWnd, "OnMessage", Qt::QueuedConnection, Q_ARG(QString, "Run:" + CommandLine)); int ret = app.exec(); @@ -50,3 +61,11 @@ int main(int argc, char *argv[]) return ret; } + +/*HANDLE hServerPipe = CreateFileW(L"\\\\.\\pipe\\qtsingleapp-sandma-ca4a-1", GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL); +if (hServerPipe != INVALID_HANDLE_VALUE) { + DWORD lenWritten; + WriteFile(hServerPipe, "test", 4, &lenWritten, NULL) + + CloseHandle(hServerPipe); +}*/ \ No newline at end of file diff --git a/SandboxiePlus/SandMan/sandman_pl.ts b/SandboxiePlus/SandMan/sandman_pl.ts index 16347a29..a62ac40e 100644 --- a/SandboxiePlus/SandMan/sandman_pl.ts +++ b/SandboxiePlus/SandMan/sandman_pl.ts @@ -70,360 +70,360 @@ %1 (%2) - + Don't alter the window title Nie zmieniaj tytułów okienek - + Display [#] indicator only Dodaj [#] do tytułów okienek - + Display box name in title Dodaj nazwę piaskownicy do tytułów okienek - + Border disabled Dołącz granice okienek - + Show only when title is in focus Pokazuj tylko gdy tytuł ma fokus - + Always show Zawsze pokasuj - - + + Browse for Program Wybierz programu - + Browse for File Wybierz pliku - + Browse for Folder Wybierz folderu - + This sandbox has been deleted hence configuration can not be saved. Ta piaskownica została skasowana, więc konfiguracja nie morze być zapisana. - + Some changes haven't been saved yet, do you really want to close this options window? Niektóre ustawienia nie zostały jeszcze zapisane, czy naprawdę chcesz zamknąć ustawienia? - + kilobytes (%1) kilobajty (%1) - + Please enter a program path Proszę podać ścieżkę programu - - + + Select Program Wybierz program - + Executables (*.exe *.cmd);;All files (*.*) Programy (*.exe *.cmd);;Wszystkie pliki (*.*) - + Please enter a service identifier Proszę podać identyfikator usługi - + Service Usługa - + Program Program - + Executables (*.exe|*.cmd) Programy (*.exe|*.cmd) - - + + Please enter a menu title Proszę podać tytuł menu - + Please enter a command Proszę podać rozkaz menu - - - - + + + + Group: %1 Grupa: %1 - + Please enter a name for the new group Proszę podaj nazwę nowej grupy - + Enter program: Podaj program: - + Please select group first. Proszę najpierw wybrać grupę. - + Process Proces - - + + Folder Folder - - - - + + + + Select Directory Wybierz folder - + Lingerer Oporn - + Leader Przewódca - + Direct Bezpośredni - + Direct All Bezpośredni, wszystkie - + Closed Zamknięte - + Closed RT Zamknięte RT - + Read Only Tylko czytać - + Hidden Ukryte - - + + Unknown Nieznane - + File/Folder Pliki/Foldery - + Registry Rejestr Systemu - + IPC Path Ścieżka IPC - + Wnd Class Klasa Okna - + COM Object Objekt COM - + Select File Wybierz plik - + All Files (*.*) Wszystkie pliki(*.*) - - + + All Programs Wszystkie programy - + COM objects must be specified by their GUID, like: {00000000-0000-0000-0000-000000000000} Obiekty COM musza być podane w formacie GUID, tak ja: {00000000-0000-0000-0000-000000000000} - + RT interfaces must be specified by their name. Interfejsy RT musza być podane jako nazwy. - + Template values can not be edited. Wartości szablonów nie mogą być zmienione. - - + + Template values can not be removed. Wartości szablonów nie mogą być usunięte. - + Exclusion Wykluczenie - + Please enter a file extension to be excluded Proszę podać rozszerzenie pliku to wyłączenia - + Please enter an auto exec command Proszę podać rozkaz auto exec - + Please enter a program file name Proszę podać nazwę pliku programu - + All Categories Wszystkie kategorie - + Custom Templates - + Email Reader - + PDF/Print - + Security/Privacy - + Desktop Utilities - + Download Managers - + Miscellaneous Różne - + Web Browser - + Media Player - + Torrent Client - + This template is enabled globally. To configure it, use the global options. Ten szablon jest włączony globalnie. Aby zmienić tą konfiguracje użyj globalnych opcji. - + Please enter the template identifier - + Error: %1 - + Only local templates can be removed! - + Do you really want to delete the selected local template? @@ -459,12 +459,12 @@ CPopUpProgress - + Dismiss Odrzucać - + Remove this progress indicator from the list Usuń ten wskaźnik postępu z listy @@ -515,67 +515,67 @@ CPopUpRecovery - + Recover to: Przywróć do: - + Browse Przeglądaj - + Clear folder list Opróżnij listę - + Recover Przywróć - + Recover the file to original location Przywróć plik do oryginalnej lokalizacji - + Recover && Explore Przywróć i eksploruj - + Recover && Open/Run Przywróć i otwórz - + Open file recovery for this box Otwórz przywracanie folderów dla tej piaskownicy - + Dismiss Odrzucać - + Don't recover this file right now Nie przywracaj tego pliku w tym momencie - + Dismiss all from this box Odrzucać wszystkie dla tej piaskownicy - + Disable quick recovery until the box restarts Deaktywuj szybkie przywracanie aż do restartu piaskownicy - + Select Directory Wybierz folder @@ -594,7 +594,7 @@ - Do you want to allow %4 (%5) to copy a %1 large file into sandbox: %2? + Do you want to allow %4 (%5) to copy a %1 large file into sandbox: %2? File name: %3 Do you want to allow %4 (%5) to copy a %1 large file into sandbox: %2? File name: %3 @@ -603,7 +603,7 @@ Pełna ścieżka: %3 - Do you want to allow %1 (%2) access to the internet? + Do you want to allow %1 (%2) access to the internet? Full path: %3 Do you want to allow %1 (%2) access to the internet? Full path: %3 @@ -611,7 +611,7 @@ Full path: %3 - %1 is eligible for quick recovery from %2. + %1 is eligible for quick recovery from %2. The file was written by: %3 %1 is eligible for quick recovery from %2. The file was written by: %3 @@ -628,23 +628,18 @@ The file was written by: %3 %1 (%2) - - + + UNKNOWN NIEZNANE - - Migrating a large file %1 into the sandbox %2, %3 left. -Full path: %4 - - - - Migrating a large file %1 into the sandbox %2, %3 left. + + Migrating a large file %1 into the sandbox %2, %3 left. Full path: %4 Migrating a large file %1 into the sandbox %2, %3 left. Full path: %4 - Kopiuje durzy plik %1 do piaskownicy %2, pozostało %3. Cala ścieżka: %4 + Kopiuje durzy plik %1 do piaskownicy %2, pozostało %3. Cala ścieżka: %4 @@ -670,23 +665,20 @@ Full path: %4 Ścieżka do pliku - - + + Select Directory Wybierz folder - - There are %1 files and %2 folders in the sandbox, occupying %3 of disk space. - - - + One or more selected files are located on a network share, and must be recovered to a local drive, please select a folder to recover all selected files to. - Co najmniej jeden wybrany plik znajduje się na dysku sieciowym i musi być odtworzony na dysk lokalny, proszę wybrać folder, do którego zostaną odtworzone wszystkie pliki. + Co najmniej jeden wybrany plik znajduje się na dysku sieciowym i musi być odtworzony na dysk lokalny, proszę wybrać folder, do którego zostaną odtworzone wszystkie pliki. + There are %1 files and %2 folders in the sandbox, occupying %3 bytes of disk space. - W piaskownicy znajduje się %1 plików i %2 folderów, razem zajmują %3 bytów na dysku. + W piaskownicy znajduje się %1 plików i %2 folderów, razem zajmują %3 bytów na dysku. @@ -773,7 +765,7 @@ Full path: %4 CSandMan - + Sandboxie-Plus v%1 Sandboxie-Plus v%1 @@ -1045,7 +1037,7 @@ Full path: %4 - + About Sandboxie-Plus O Sandboxie-Plus @@ -1061,28 +1053,26 @@ Full path: %4 - Sandboxie-Plus was running in portable mode, now it has to clean up the created services. This will prompt for administrative privileges. - + Sandboxie-Plus was running in portable mode, now it has to clean up the created services. This will prompt for administrative privileges. + Do you want to do the clean up? - Sandboxie-Plus was running in portable mode, now it has to clean up the created services. This will prompt for administrative privileges. - -Do you want to do the clean up? + Sandboxie-Plus was running in portable mode, now it has to clean up the created services. This will prompt for administrative privileges. Sandboxie-Plus była wykonana w modusie przenośnym, teraz musi usunąć sterownik i usługę. Do tego będzie potrzebowała uprawnień administracyjnych. - - - - - + + + + + Don't show this message again. Nie pokazuj tej wiadomości jeszcze raz. - + Sandboxie-Plus - Error Sandboxie-Plus - Błąd @@ -1117,405 +1107,405 @@ Do you want to do the clean up? Domyślna piaskownica nie znaleziona, więc zostanie odtworzona: %1 - + Do you want to check if there is a new version of Sandboxie-Plus? Czy chcesz sprawdzić, czy istnieje nowa wersja Saidboxie-Plus? - + Some compatibility templates (%1) are missing, probably deleted, do you want to remove them from all boxes? Niektóre szablony kompatybilności (%1) nie zostały znalezione, przypuszczalnie są przestarzałe, czy maja zostać usunięte z wszystkich piaskownic? - + Cleaned up removed templates... Wyczyść i usunięte szablony… - + Sbie Directory: %1 Folder z piaskownicami: %1 - + Loaded Config: %1 Załadowana konfiguracja: %1 - + Driver version: %1 Wersja sterownika: %1 - + - Portable - przenośna - + Sandboxie-Plus was started in portable mode, do you want to put the SandBox folder into its parent directory? Sandboxie-Plus została wystartowana w modusie przenośnym, czy folder piaskownic ma zostać umieszczony w folderze powyższym? - + - NOT connected - NIE połączone - + PID %1: PID %1: - + %1 (%2): %1 (%2): - + Recovering file %1 to %2 Odtwarzanie pliku %1 do %2 - + The file %1 already exists, do you want to overwrite it? Plik o nazwie %1 już istnieje czy ma zostać zastąpiony? - + Do this for all files! Zrób to z wszystkimi plikami! - + Failed to recover some files: Nie udało się odtworzyć następujących plików: - + Only Administrators can change the config. Tylko administratorzy mogą zmieniać ustawienia piaskownicy. - + Please enter the configuration password. Proszę podać hasło. - + Login Failed: %1 Logowanie się nie udało: %1 - + Do you want to terminate all processes in all sandboxes? Czy wszystkie programy we wszystkich piaskownicach mają zostać zakończone? - + Terminate all without asking W przyszłości zakańczaj bez pytania - + Please enter the duration for disabling forced programs. Proszę podać jak długo monitorowanie procesów ma zostać wstrzymane. - + Sandboxie-Plus was started in portable mode and it needs to create necessary services. This will prompt for administrative privileges. Sandboxie-Plus jest wykonane w modusie przenośnym i musi zainstalować sterownik i usługę. Do tego będzie potrzebować uprawnień administratorskich. - + Executing maintenance operation, please wait... Wykonywanie operacji zarzadzania, proszę czekać… - + Do you also want to reset hidden message boxes (yes), or only all log messages (no)? Czy ukryte okna z wiadomościami mają zostać zresetowane (tak), czy tylko wiadomości piaskownic (nie)? - + The changes will be applied automatically whenever the file gets saved. Zmiany będą zastosowane automatycznie jak tylko plik zostanie zapisany. - + The changes will be applied automatically as soon as the editor is closed. Zmiany będą zastosowane automatycznie jak tylko edytor zostanie zakończony. - + Error Status: %1 Kod błędu: %1 - + Administrator rights are required for this operation. Ta operacja wymaga uprawnień administratorskich. - + Failed to execute: %1 Błąd przy wykonywaniu: %1 - + Failed to connect to the driver Błąd przy polaczeniu ze sterownikiem - + Failed to communicate with Sandboxie Service: %1 Błąd przy komunikacji z usługą: %1 - + An incompatible Sandboxie %1 was found. Compatible versions: %2 Nie kompatybilna wersja Sandboxie %1 jest aktualnie zainstalowana. Kompatybilne wersje: %2 - + Can't find Sandboxie installation path. Folder instalacyjny nie mógł być zidentyfikowany. - + Failed to copy configuration from sandbox %1: %2 Błąd przy kopiowaniu konfiguracji piaskownicy %1: %2 - + A sandbox of the name %1 already exists Piaskownica o nazwie %1 jur istnieje - + Failed to delete sandbox %1: %2 Błąd przy usuwaniu piaskownicy %1: %2 - + The sandbox name can not be longer than 32 characters. Nazwy piaskownicy nie mogą być dłuższe niż 32 litery. - + The sandbox name can not be a device name. Nazwy piaskownicy nie mogą być nazwami urządzeń. - + The sandbox name can contain only letters, digits and underscores which are displayed as spaces. Nazwy piaskownicy mogą jedynie być nazwami litery, liczby i podkreślenia które będą wyświetlane jako spacje. - + Failed to terminate all processes Błąd zakańczania wszystkich procesów - + Delete protection is enabled for the sandbox Ochrona przed usunięciem jest aktywna dla tej piaskownicy - + Error deleting sandbox folder: %1 Błąd usuwania foldera piaskownicy: %1 - + A sandbox must be emptied before it can be renamed. Piaskownica musi być opróżniona zanim morze być przemianowana. - + A sandbox must be emptied before it can be deleted. Piaskownica musi być opróżniona zanim morze być usunięta. - + Failed to move directory '%1' to '%2' Błąd przy przenoszeniu foldera %1 do %2 - + This Snapshot operation can not be performed while processes are still running in the box. Operacja migawkowa ni może być wykonana puki procesy są wykonywane w piaskownicy. - + Failed to create directory for new snapshot Błąd przy tworzeniu foldera dla nowej migawki - + Failed to copy RegHive Błąd przy kopiowaniu gałęzi rejestru - + Snapshot not found Nie znaleziono migawki - + Error merging snapshot directories '%1' with '%2', the snapshot has not been fully merged. Błąd przy kombinowaniu folderów migawek '%1' u '%2', migawki nie zostały całkowicie skombinowane. - + Failed to remove old snapshot directory '%1' Błąd przy usuwaniu starego foldera migawki '%1' - + Can't remove a snapshot that is shared by multiple later snapshots Nie można usunąć migawki, która jest używana przez inne migawki - + Failed to remove old RegHive Błąd przy usuwaniu gałęzi rejestru - + You are not authorized to update configuration in section '%1' Brak autoryzacji do zmian konfiguracji w tej sekcji '%1' - + Failed to set configuration setting %1 in section %2: %3 Błąd przy zmianie ustawienia %1 w sekcji %2: %3 - + Can not create snapshot of an empty sandbox Migawka pustej piaskownicy nie morzy być wytworzona - + A sandbox with that name already exists Piaskownica o tej nazwie już istnieje - + Unknown Error Status: %1 Nieznany kod błędu: %1 - + Operation failed for %1 item(s). Błąd przy wykonywaniu %1 operacji. - + Do you want to open %1 in a sandboxed (yes) or unsandboxed (no) Web browser? Czy przeglądarka internetowa z %1 ma być otwarte w piaskownicy (tak), czy poza piaskownica (nie)? - + Remember choice for later. Zapamiętaj wybór na później. - + Checking for updates... Szukanie aktualizacji… - + server not reachable server nie dostępny + - Failed to check for updates, error: %1 Błąd przy szukaniu aktualizacji: %1 - + <p>Do you want to go to the <a href="%1">info page</a>?</p> <p>Czy chcesz otworzyć <a href="%1">stronę informacyjną</a>?</p> - + Don't show this announcement in the future. Nie pokazuj jego ogłoszenia w przyszłości. - + <p>There is a new version of Sandboxie-Plus available.<br /><font color='red'>New version:</font> <b>%1</b></p> <p>Nowa wersja Sandboxie-Plus jest dostępna.<br /><font color='red'>Nowa wersja:</font> <b>%1</b></p> - + <p>Do you want to download the latest version?</p> <p>Czy chcesz pobrać najnowszą wersję?</p> - + <p>Do you want to go to the <a href="%1">download page</a>?</p> <p>Czy chcesz otworzyć <a href="%1">stronę pobierania</a>?</p> - + Don't show this message anymore. Nie pokazuj tej aktualizacji w przyszłości. - + Downloading new version... Pobieranie nowej wersji… - + No new updates found, your Sandboxie-Plus is up-to-date. Nie znaleziono nowszej wersji, twoja Sandboxie-Plus jest aktualna. - + Failed to download update from: %1 Błąd pobierania aktualizacji z: %1 - + <p>New Sandboxie-Plus has been downloaded to the following location:</p><p><a href="%2">%1</a></p><p>Do you want to begin the installation? If any programs are running sandboxed, they will be terminated.</p> <p>Nowa wersja Sandboxie-Plus zostają pobrana z:</p><p><a href="%2">%1</a></p><p>Czy instalacja ma zostać zaczęta? Wszystkie programy aktywne w piaskownicach zostaną zakończone.</p> - + <h3>About Sandboxie-Plus</h3><p>Version %1</p><p>Copyright (c) 2020-2021 by DavidXanatos</p> <h3>O Sandboxie-Plus</h3><p>Wersja %1</p><p>Copyright (c) 2020-2021 by DavidXanatos</p> - + <p>Sandboxie-Plus is an open source continuation of Sandboxie.</p><p></p><p>Visit <a href="https://sandboxie-plus.com">sandboxie-plus.com</a> for more information.</p><p></p><p></p><p></p><p>Icons from <a href="https://icons8.com">icons8.com</a></p><p></p> <p>Sandboxie-Plus jest otwarto źródłowym rozwidlenie Sandboxie.</p><p></p><p>Odwiedź <a href="https://sandboxie-plus.com">sandboxie-plus.com</a> aby otrzymać dalsze informacje.</p><p></p><p></p><p></p><p>Icony z <a href="https://icons8.com">icons8.com</a></p><p></p> - + The selected window is running as part of program %1 in sandbox %2 Wybrane okno jest częścią programu %1 z piaskownicy %2 - + The selected window is not running as part of any sandboxed program. Wybrane okno nie jest częścią żadnego programu w piaskownicy. - + Drag the Finder Tool over a window to select it, then release the mouse to check if the window is sandboxed. Uchwyć i pociągnij narzędzie do szukania i puść je nad oknem do analizy. - + Sandboxie-Plus - Window Finder Sandboxie-Plus - Narzędzie do szukania @@ -1592,8 +1582,7 @@ Do you want to do the clean up? - MSI Installer - Msi Installer + Msi Installer @@ -1618,8 +1607,7 @@ Do you want to do the clean up? - Firefox - FireFox + FireFox @@ -1629,14 +1617,12 @@ Do you want to do the clean up? - Winamp - WinAmp + WinAmp - KMPlayer - KM Player + KM Player @@ -1697,8 +1683,7 @@ Do you want to do the clean up? - Firefox Plugin Container - FireFox Plugin Container + FireFox Plugin Container @@ -2006,9 +1991,8 @@ Do you want to do the clean up? - Do you want to %1 the selected process(es)? - Do you want to %1 the selected process(es) - Czy naprawdę chcesz %1 wybrane procesy + Do you want to %1 the selected process(es) + Czy naprawdę chcesz %1 wybrane procesy @@ -2121,42 +2105,42 @@ Do you want to do the clean up? CTraceModel - + Unknown Nieznane - + %1 (%2) %1 (%2) - + Process %1 - + Thread %1 - + Process Proces - + Type Typ - + Status Status - + Value Wartość @@ -2164,41 +2148,36 @@ Do you want to do the clean up? CTraceView - + Show as task tree - + PID: - - - - - + + + + + [All] - + TID: - - Show only sellectes box - - - - + %1 (%2) %1 (%2) - + %1 @@ -2330,8 +2309,8 @@ Do you want to do the clean up? - - + + Name Nazwa @@ -2475,18 +2454,12 @@ Do you want to do the clean up? - Type Typ - - - Program/Service - - Add service @@ -2972,8 +2945,7 @@ instead of "*". - Open access to Windows Security Account Manager - Open access to windows Security Account Manager + Open access to windows Security Account Manager @@ -3007,124 +2979,114 @@ instead of "*". - - Disable Resource Access Monitor - - - - - Resource Access Monitor - - - - + Debug Debug - + WARNING, these options can disable core security guarantees and break sandbox security!!! - + These options are intended for debugging compatibility issues, please do not use them in production use. - + App Templates Dodaj szablony - + Compatibility Templates - + Filter Categories Filtruj kategorie - + Text Filter Filtruj text - + Add Template - + Remove Template - + Category Kategoria - + This list contains a large amount of sandbox compatibility enhancing templates Ta lista zawiera durzą ilość szablonów poprawiających kompatybilność programów z piaskownica - + Template Folders - + Configure the folder locations used by your other applications. Please note that this values are currently user specific and saved globally for all boxes. - + Value Wartość - + Accessibility - + To compensate for the lost protection, please consult the Drop Rights settings page in the Restrictions settings group. - + Screen Readers: JAWS, NVDA, Window-Eyes, System Access - + The following settings enable the use of Sandboxie in combination with accessibility software. Please note that some measure of Sandboxie protection is necessarily lost when these settings are in effect. - + Edit ini Section Edytuj sekcje ini - + Edit ini Edytuj ini - + Cancel Anuluj - + Save Zapisz diff --git a/SandboxiePlus/SandboxiePlus.sln b/SandboxiePlus/SandboxiePlus.sln index 9dab64f8..44c51ef9 100644 --- a/SandboxiePlus/SandboxiePlus.sln +++ b/SandboxiePlus/SandboxiePlus.sln @@ -5,6 +5,7 @@ VisualStudioVersion = 16.0.30804.86 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SandMan", "SandMan\SandMan.vcxproj", "{B7A8576D-A08A-4A97-84E8-013DAF4D4F1F}" ProjectSection(ProjectDependencies) = postProject + {E647D210-1860-340F-A7B7-4137A60B2483} = {E647D210-1860-340F-A7B7-4137A60B2483} {7AB8215A-59A4-4B8B-8090-16C87A860429} = {7AB8215A-59A4-4B8B-8090-16C87A860429} {1433EC85-BDA4-402E-BEC1-48611206A64A} = {1433EC85-BDA4-402E-BEC1-48611206A64A} {B12702AD-ABFB-343A-A199-8E24837244A3} = {B12702AD-ABFB-343A-A199-8E24837244A3} @@ -23,6 +24,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtSingleApp", "QtSingleApp\qtsingleapp\qtsingleapp\qtsingleapp.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UGlobalHotkey", "UGlobalHotkey\uglobalhotkey.vcxproj", "{E647D210-1860-340F-A7B7-4137A60B2483}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -63,6 +66,14 @@ Global {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.Build.0 = Release|Win32 {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|x64 {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.Build.0 = Release|x64 + {E647D210-1860-340F-A7B7-4137A60B2483}.Debug|Win32.ActiveCfg = Debug|Win32 + {E647D210-1860-340F-A7B7-4137A60B2483}.Debug|Win32.Build.0 = Debug|Win32 + {E647D210-1860-340F-A7B7-4137A60B2483}.Debug|x64.ActiveCfg = Debug|x64 + {E647D210-1860-340F-A7B7-4137A60B2483}.Debug|x64.Build.0 = Debug|x64 + {E647D210-1860-340F-A7B7-4137A60B2483}.Release|Win32.ActiveCfg = Release|Win32 + {E647D210-1860-340F-A7B7-4137A60B2483}.Release|Win32.Build.0 = Release|Win32 + {E647D210-1860-340F-A7B7-4137A60B2483}.Release|x64.ActiveCfg = Release|x64 + {E647D210-1860-340F-A7B7-4137A60B2483}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SandboxiePlus/qmake_plus.cmd b/SandboxiePlus/qmake_plus.cmd index 45ed9edd..24462bf8 100644 --- a/SandboxiePlus/qmake_plus.cmd +++ b/SandboxiePlus/qmake_plus.cmd @@ -16,6 +16,17 @@ IF %1 == x64 ( ) + +mkdir %~dp0\Build_UGlobalHotkey_%build_arch% +cd %~dp0\Build_UGlobalHotkey_%build_arch% + +%qt_path%\bin\qmake.exe %~dp0\UGlobalHotkey\uglobalhotkey.qc.pro -spec win32-msvc "CONFIG+=qtquickcompiler" +%~dp0..\..\Qt\Tools\QtCreator\bin\jom.exe -f Makefile.Release -j 8 +IF %ERRORLEVEL% NEQ 0 goto :error +if NOT EXIST %~dp0\bin\%build_arch%\Release\UGlobalHotkey.dll goto :error + + + mkdir %~dp0\Build_qtsingleapp_%build_arch% cd %~dp0\Build_qtsingleapp_%build_arch% @@ -24,16 +35,18 @@ cd %~dp0\Build_qtsingleapp_%build_arch% IF %ERRORLEVEL% NEQ 0 goto :error if NOT EXIST %~dp0\bin\%build_arch%\Release\qtsingleapp.dll goto :error + + mkdir %~dp0\Build_MiscHelpers_%build_arch% cd %~dp0\Build_MiscHelpers_%build_arch% - %qt_path%\bin\qmake.exe %~dp0\MiscHelpers\MiscHelpers.qc.pro -spec win32-msvc "CONFIG+=qtquickcompiler" %~dp0..\..\Qt\Tools\QtCreator\bin\jom.exe -f Makefile.Release -j 8 IF %ERRORLEVEL% NEQ 0 goto :error if NOT EXIST %~dp0\bin\%build_arch%\Release\MiscHelpers.dll goto :error + mkdir %~dp0\Build_QSbieAPI_%build_arch% cd %~dp0\Build_QSbieAPI_%build_arch% @@ -43,6 +56,7 @@ IF %ERRORLEVEL% NEQ 0 goto :error if NOT EXIST %~dp0\bin\%build_arch%\Release\QSbieAPI.dll goto :error + mkdir %~dp0\Build_SandMan_%build_arch% cd %~dp0\Build_SandMan_%build_arch% @@ -51,6 +65,8 @@ cd %~dp0\Build_SandMan_%build_arch% IF %ERRORLEVEL% NEQ 0 goto :error if NOT EXIST %~dp0\bin\%build_arch%\Release\SandMan.exe goto :error + + cd %~dp0 rem dir .\bin @@ -61,4 +77,4 @@ goto :eof :error echo Build failed -exit 1 +rem exit 1 diff --git a/SandboxiePlus/version.h b/SandboxiePlus/version.h index b9627e0b..3b60cdc1 100644 --- a/SandboxiePlus/version.h +++ b/SandboxiePlus/version.h @@ -2,7 +2,7 @@ #define VERSION_MJR 0 #define VERSION_MIN 8 -#define VERSION_REV 2 +#define VERSION_REV 5 #define VERSION_UPD 0 #ifndef STR