Repository navigation
Expand file tree
/
Copy pathstatelock.cpp
More file actions
69 lines (60 loc) · 2.23 KB
/
Copy pathstatelock.cpp
File metadata and controls
69 lines (60 loc) · 2.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "statelock.h"
#include <sddl.h>
#include <string>
#pragma comment(lib, "advapi32.lib")
namespace tac
{
// Full path of "state.lock" in the folder of the module this code is
// linked into (TacProvider.dll in LogonUI, enroll.exe on the console).
static bool LockFilePath(std::wstring& path)
{
HMODULE self = nullptr;
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCWSTR>(&LockFilePath), &self))
return false;
WCHAR buf[MAX_PATH];
DWORD cch = GetModuleFileNameW(self, buf, ARRAYSIZE(buf));
if (cch == 0 || cch >= ARRAYSIZE(buf))
return false;
path.assign(buf, cch);
size_t slash = path.find_last_of(L'\\');
if (slash == std::wstring::npos)
return false;
path.erase(slash + 1);
path += L"state.lock";
return true;
}
StateLock::StateLock(DWORD timeoutMs)
: _h(INVALID_HANDLE_VALUE)
{
std::wstring path;
if (!LockFilePath(path))
return;
// SYSTEM and Administrators only, not inherited from the folder.
PSECURITY_DESCRIPTOR psd = nullptr;
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
L"D:P(A;;FA;;;SY)(A;;FA;;;BA)", SDDL_REVISION_1, &psd, nullptr))
return;
SECURITY_ATTRIBUTES sa = { sizeof(sa), psd, FALSE };
const ULONGLONG deadline = GetTickCount64() + timeoutMs;
for (;;)
{
// Share mode 0: while we hold the handle, every other open fails
// with ERROR_SHARING_VIOLATION. That is the whole lock.
_h = CreateFileW(path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &sa,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (_h != INVALID_HANDLE_VALUE)
break;
if (GetLastError() != ERROR_SHARING_VIOLATION || GetTickCount64() >= deadline)
break;
Sleep(20);
}
LocalFree(psd);
}
StateLock::~StateLock()
{
if (_h != INVALID_HANDLE_VALUE)
CloseHandle(_h);
}
}