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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//============================================================
//
// Class: COMIsolatedStorage
//
//
// Purpose: Native Implementation of IsolatedStorage
//
//
//============================================================
#ifndef __COMISOLATEDSTORAGE_h__
#define __COMISOLATEDSTORAGE_h__
#ifdef FEATURE_ISOSTORE
// Dependency in managed : System.IO.IsolatedStorage.IsolatedStorage.cs
#ifndef FEATURE_ISOSTORE_LIGHT
#define ISS_ROAMING_STORE 0x08
#define ISS_MACHINE_STORE 0x10
#endif // !FEATURE_ISOSTORE_LIGHT
class COMIsolatedStorage
{
public:
#ifndef FEATURE_ISOSTORE_LIGHT
static
void QCALLTYPE GetCaller(QCall::ObjectHandleOnStack retAssembly);
#endif // !FEATURE_ISOSTORE_LIGHT
static void DECLSPEC_NORETURN ThrowISS(HRESULT hr);
private:
#ifndef FEATURE_ISOSTORE_LIGHT
static StackWalkAction StackWalkCallBack(CrawlFrame* pCf, PVOID ppv);
#endif // !FEATURE_ISOSTORE_LIGHT
};
// --- [ Structure of data that gets persisted on disk ] -------------(Begin)
// non-standard extension: 0-length arrays in struct
#ifdef _MSC_VER
#pragma warning(disable:4200)
#endif
#include <pshpack1.h>
typedef unsigned __int64 QWORD;
typedef QWORD ISS_USAGE;
// Accounting Information
typedef struct
{
ISS_USAGE cUsage; // The amount of resource used
DWORD dwVersion; // Version of bookkeeping file on disk (so we know the layout)
QWORD qwQuota; // Quota stored on disk (persisted if increased by the host)
QWORD qwReserved[5]; // For future use, set to 0
DWORD dwReserved; // For future use, set to 0
} ISS_RECORD;
#include <poppack.h>
#ifdef _MSC_VER
#pragma warning(default:4200)
#endif
// --- [ Structure of data that gets persisted on disk ] ---------------(End)
class AccountingInfo
{
public:
// The file name is used to open / create the file.
// A synchronization object will also be created using the sync name
AccountingInfo(const WCHAR *wszFileName, const WCHAR *wszSyncName);
// Init should be called before Reserve / GetUsage is called.
HRESULT Init(); // Creates the file if necessary
// Reserves space (Increments qwQuota)
// This method is synchrinized. If quota + request > limit, method fails
HRESULT Reserve(
ISS_USAGE cLimit, // The max allowed
ISS_USAGE cRequest, // amount of space (request / free)
BOOL fFree); // TRUE will free, FALSE will reserve
// Method is not synchronized. So the information may not be current.
// This implies "Pass if (Request + GetUsage() < Limit)" is an Error!
// Use Reserve() method instead.
HRESULT GetUsage(
ISS_USAGE *pcUsage); // [out] The amount of space / resource used
BOOL GetQuota(
INT64 *qwQuota); // [out] The Quota stored on disk (if there is one)
void SetQuota(
INT64 qwQuota); // [out] The Quota stored on disk (if there is one)
// Frees cached pointers, Closes handles
~AccountingInfo();
static void AcquireLock(AccountingInfo *pAI) {
STANDARD_VM_CONTRACT;
HRESULT hr = pAI->Lock();
if (FAILED(hr)) COMIsolatedStorage::ThrowISS(hr);
}
static void ReleaseLock(AccountingInfo *pAI) {
WRAPPER_NO_CONTRACT;
pAI->Unlock();
}
typedef Holder<AccountingInfo *, AccountingInfo::AcquireLock, AccountingInfo::ReleaseLock> AccountingInfoLockHolder;
private:
HRESULT Lock(); // Machine wide Lock
void Unlock(); // Unlock the store
HRESULT Map(); // Maps the store file into memory
void Unmap(); // Unmaps the store file from memory
void Close(); // Close the store file, and file mapping
WCHAR *m_wszFileName; // The file name
HANDLE m_hFile; // File handle for the file
HANDLE m_hMapping; // File mapping for the memory mapped file
// members used for synchronization
WCHAR *m_wszName; // The name of the mutex object
HANDLE m_hLock; // Handle to the Mutex object
#ifdef _DEBUG
ULONG m_dwNumLocks; // The number of locks owned by this object
#endif
union {
PBYTE m_pData; // The start of file stream
ISS_RECORD *m_pISSRecord;
};
};
class COMIsolatedStorageFile
{
public:
static
void QCALLTYPE GetRootDir(DWORD dwFlags,
QCall::StringHandleOnStack retRootDir);
static
UINT64 QCALLTYPE GetUsage(__in_opt AccountingInfo * pAI);
static
void QCALLTYPE Reserve(__in_opt AccountingInfo * pAI,
UINT64 qwQuota,
UINT64 qwReserve,
BOOL fFree);
static
BOOL QCALLTYPE GetQuota(__in_opt AccountingInfo * pAI,
__out INT64 * qwQuota);
static
void QCALLTYPE SetQuota(__in_opt AccountingInfo * pAI,
INT64 qwQuota);
static
AccountingInfo * QCALLTYPE Open(LPCWSTR wszFileName,
LPCWSTR wszSyncName);
static
void QCALLTYPE Close(__in_opt AccountingInfo * pAI);
static
BOOL QCALLTYPE Lock(__in AccountingInfo * handle,
BOOL fLock);
#ifndef FEATURE_ISOSTORE_LIGHT
// create the machine store root directory and apply the correct DACL
static
void QCALLTYPE CreateDirectoryWithDacl(LPCWSTR wszPath);
#endif // !FEATURE_ISOSTORE_LIGHT
private:
static void GetRootDirInternal(DWORD dwFlags, __in_ecount(cPath) WCHAR *path, DWORD cPath);
static void CreateDirectoryIfNotPresent(__in_z const WCHAR *path, LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL);
#ifndef FEATURE_ISOSTORE_LIGHT
static BOOL GetMachineStoreDirectory(__out_ecount(cchMachineStorageRoot) WCHAR *wszMachineStorageRoot, DWORD cchMachineStorageRoot);
static HRESULT GetMachineStoreDacl(PACL *ppAcl);
#endif // !FEATURE_ISOSTORE_LIGHT
};
#endif // FEATURE_ISOSTORE
#endif // __COMISOLATEDSTORAGE_h__
|