summaryrefslogtreecommitdiff
path: root/src/vm/comisolatedstorage.h
blob: 7eb219975ea7740cc6b3c7f5e57c9843932bd692 (plain)
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__