File: StringResourceManager.cs

package info (click to toggle)
mono 6.8.0.105%2Bdfsg-3.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,284,512 kB
  • sloc: cs: 11,172,132; xml: 2,850,069; ansic: 671,653; cpp: 122,091; perl: 59,366; javascript: 30,841; asm: 22,168; makefile: 20,093; sh: 15,020; python: 4,827; pascal: 925; sql: 859; sed: 16; php: 1
file content (182 lines) | stat: -rw-r--r-- 6,579 bytes parent folder | download | duplicates (7)
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
//------------------------------------------------------------------------------
// <copyright file="StringResourceManager.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------

namespace System.Web {

using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using Debug=System.Web.Util.Debug;

internal class StringResourceManager {

    internal const int RESOURCE_TYPE = 0xEBB;
    internal const int RESOURCE_ID = 101;

    private StringResourceManager() {
    }

    internal unsafe static string ResourceToString(IntPtr pv, int offset, int size) {
        return new String((sbyte *)pv, offset, size, Encoding.UTF8);
    }

    internal static SafeStringResource ReadSafeStringResource(Type t) {

        // At designtime CodeGenDir is null.
        if (HttpRuntime.CodegenDirInternal != null) {
            // Module.FullyQualifiedName was changed to check for FileIOPermission regardless of the name being an existing file or not.
            // we need to Assert in order to succeed the Demand() (ASURT 121603)
            (InternalSecurityPermissions.PathDiscovery(HttpRuntime.CodegenDirInternal)).Assert();
        }

        string dllPath = t.Module.FullyQualifiedName;


        IntPtr hModule = UnsafeNativeMethods.GetModuleHandle(dllPath);
        if (hModule == IntPtr.Zero) {
            // GetModuleHandle could fail if the assembly was renamed to .delete.  So we fall back to
            // calling Marshal.GetHINSTANCE, which is more reliable.  Ideally, we should always do this
            // directly, but to limit the risk, we only do it as a fall back (VSWhidbey 394621)
            hModule = Marshal.GetHINSTANCE(t.Module);
            if (hModule == IntPtr.Zero) {
                throw new HttpException(SR.GetString(SR.Resource_problem,
                    "GetModuleHandle", HttpException.HResultFromLastError(Marshal.GetLastWin32Error()).ToString(CultureInfo.InvariantCulture)));
            }
        }

        IntPtr hrsrc = UnsafeNativeMethods.FindResource(hModule, (IntPtr)RESOURCE_ID, (IntPtr)RESOURCE_TYPE);
        if (hrsrc == IntPtr.Zero) {
            throw new HttpException(SR.GetString(SR.Resource_problem,
                "FindResource", HttpException.HResultFromLastError(Marshal.GetLastWin32Error()).ToString(CultureInfo.InvariantCulture)));
        }

        int resSize = UnsafeNativeMethods.SizeofResource(hModule, hrsrc);

        IntPtr hglob = UnsafeNativeMethods.LoadResource(hModule, hrsrc);
        if (hglob == IntPtr.Zero) {
            throw new HttpException(SR.GetString(SR.Resource_problem,
                "LoadResource", HttpException.HResultFromLastError(Marshal.GetLastWin32Error()).ToString(CultureInfo.InvariantCulture)));
        }

        IntPtr pv = UnsafeNativeMethods.LockResource(hglob);
        if (pv == IntPtr.Zero) {
            throw new HttpException(SR.GetString(SR.Resource_problem,
                "LockResource", HttpException.HResultFromLastError(Marshal.GetLastWin32Error()).ToString(CultureInfo.InvariantCulture)));
        }

        // Make sure the end of the resource lies within the module.  this can be an issue
        // if the resource has been hacked with an invalid length (ASURT 145040)
        if (!UnsafeNativeMethods.IsValidResource(hModule, pv, resSize)) {
            throw new InvalidOperationException();
        }

        return new SafeStringResource(pv, resSize);
    }
}

internal class StringResourceBuilder {
    private ArrayList _literalStrings = null;
    private int _offset = 0;

    internal StringResourceBuilder() {
    }

    internal void AddString(string s, out int offset, out int size, out bool fAsciiOnly) {

        if (_literalStrings == null)
            _literalStrings = new ArrayList();

        _literalStrings.Add(s);

        // Compute the UTF8 length of the string
        size = Encoding.UTF8.GetByteCount(s);

        // Check if the string contains only 7-bit ascii characters
        fAsciiOnly = (size == s.Length);

        offset = _offset;

        // Update the offset in the literal string memory block
        _offset += size;
    }

    internal bool HasStrings {
        get { return _literalStrings != null; }
    }

    internal void CreateResourceFile(string resFileName) {

        using (Stream strm = new FileStream(resFileName, FileMode.Create)) {
            Encoding encoding = Encoding.UTF8;

            BinaryWriter writer = new BinaryWriter(strm, encoding);

            writer.Write(0x00000000);
            writer.Write(0x00000020);
            writer.Write(0x0000FFFF);
            writer.Write(0x0000FFFF);
            writer.Write(0x00000000);
            writer.Write(0x00000000);
            writer.Write(0x00000000);
            writer.Write(0x00000000);

            // Resource size
            writer.Write(_offset);

            // Resource header size
            writer.Write(0x00000020);

            // Type
            writer.Write(StringResourceManager.RESOURCE_TYPE << 16 | 0xFFFF);

            // Resource ID
            writer.Write(StringResourceManager.RESOURCE_ID << 16 | 0xFFFF);

            writer.Write(0x00000000);
            writer.Write(0x00000000);
            writer.Write(0x00000000);
            writer.Write(0x00000000);

            #if DEBUG
            long startPos = strm.Position;
            #endif

            foreach (string s in _literalStrings) {
                byte[] data = encoding.GetBytes(s);
                writer.Write(data);
            }

            // Make sure the stream has the size we expect
            #if DEBUG
            Debug.Assert(strm.Position-startPos == _offset, "strm.Position-startPos == _offset");
            #endif
        }
    }

}

// Used to wrap an IntPtr in a way that it can safely be handed out to
// untrusted code (ASURT 73586)
internal class SafeStringResource {

    private IntPtr _stringResourcePointer;
    private int _resourceSize;

    internal SafeStringResource(IntPtr stringResourcePointer, int resourceSize) {
        _stringResourcePointer = stringResourcePointer;
        _resourceSize = resourceSize;
    }

    internal IntPtr StringResourcePointer { get { return _stringResourcePointer; } }
    internal int ResourceSize { get { return _resourceSize; } }
}

}