aboutsummaryrefslogtreecommitdiff
path: root/src/api/burn/WixToolset.Mba.Core/Engine.cs
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-05-07 16:37:19 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-05-11 19:11:19 -0500
commita645cabc7a46adaa8f26d913bbb3cc5f9cd07820 (patch)
treefdfbc63bb4a24bf17d123c5e3ffe8b509d2d5176 /src/api/burn/WixToolset.Mba.Core/Engine.cs
parent27c6decae94536cae338731b6cb765aa92776486 (diff)
downloadwix-a645cabc7a46adaa8f26d913bbb3cc5f9cd07820.tar.gz
wix-a645cabc7a46adaa8f26d913bbb3cc5f9cd07820.tar.bz2
wix-a645cabc7a46adaa8f26d913bbb3cc5f9cd07820.zip
Use balutil methods in Engine.cs to avoid size_t ugliness.
Diffstat (limited to 'src/api/burn/WixToolset.Mba.Core/Engine.cs')
-rw-r--r--src/api/burn/WixToolset.Mba.Core/Engine.cs229
1 files changed, 50 insertions, 179 deletions
diff --git a/src/api/burn/WixToolset.Mba.Core/Engine.cs b/src/api/burn/WixToolset.Mba.Core/Engine.cs
index aed420d5..5ebada36 100644
--- a/src/api/burn/WixToolset.Mba.Core/Engine.cs
+++ b/src/api/burn/WixToolset.Mba.Core/Engine.cs
@@ -13,8 +13,6 @@ namespace WixToolset.Mba.Core
13 /// </summary> 13 /// </summary>
14 public sealed class Engine : IEngine 14 public sealed class Engine : IEngine
15 { 15 {
16 // Burn errs on empty strings, so declare initial buffer size.
17 private const int InitialBufferSize = 80;
18 private static readonly string normalizeVersionFormatString = "{0} must be less than or equal to " + UInt16.MaxValue; 16 private static readonly string normalizeVersionFormatString = "{0} must be less than or equal to " + UInt16.MaxValue;
19 17
20 private IBootstrapperEngine engine; 18 private IBootstrapperEngine engine;
@@ -62,9 +60,7 @@ namespace WixToolset.Mba.Core
62 /// <inheritdoc/> 60 /// <inheritdoc/>
63 public bool ContainsVariable(string name) 61 public bool ContainsVariable(string name)
64 { 62 {
65 IntPtr capacity = new IntPtr(0); 63 return BalUtil.BalVariableExistsFromEngine(this.engine, name);
66 int ret = this.engine.GetVariableString(name, IntPtr.Zero, ref capacity);
67 return NativeMethods.E_NOTFOUND != ret;
68 } 64 }
69 65
70 /// <inheritdoc/> 66 /// <inheritdoc/>
@@ -101,24 +97,21 @@ namespace WixToolset.Mba.Core
101 /// <inheritdoc/> 97 /// <inheritdoc/>
102 public string EscapeString(string input) 98 public string EscapeString(string input)
103 { 99 {
104 IntPtr capacity = new IntPtr(InitialBufferSize); 100 StrUtil.StrHandle handle = new StrUtil.StrHandle();
105 StringBuilder sb = new StringBuilder(capacity.ToInt32()); 101 try
106
107 // Get the size of the buffer.
108 int ret = this.engine.EscapeString(input, sb, ref capacity);
109 if (NativeMethods.E_INSUFFICIENT_BUFFER == ret || NativeMethods.E_MOREDATA == ret)
110 { 102 {
111 capacity = new IntPtr(capacity.ToInt32() + 1); // Add one for the null terminator. 103 int ret = BalUtil.BalEscapeStringFromEngine(this.engine, input, ref handle);
112 sb.Capacity = capacity.ToInt32(); 104 if (ret != NativeMethods.S_OK)
113 ret = this.engine.EscapeString(input, sb, ref capacity); 105 {
114 } 106 throw new Win32Exception(ret);
107 }
115 108
116 if (NativeMethods.S_OK != ret) 109 return handle.ToUniString();
110 }
111 finally
117 { 112 {
118 throw new Win32Exception(ret); 113 handle.Dispose();
119 } 114 }
120
121 return sb.ToString();
122 } 115 }
123 116
124 /// <inheritdoc/> 117 /// <inheritdoc/>
@@ -133,24 +126,21 @@ namespace WixToolset.Mba.Core
133 /// <inheritdoc/> 126 /// <inheritdoc/>
134 public string FormatString(string format) 127 public string FormatString(string format)
135 { 128 {
136 IntPtr capacity = new IntPtr(InitialBufferSize); 129 StrUtil.StrHandle handle = new StrUtil.StrHandle();
137 StringBuilder sb = new StringBuilder(capacity.ToInt32()); 130 try
138
139 // Get the size of the buffer.
140 int ret = this.engine.FormatString(format, sb, ref capacity);
141 if (NativeMethods.E_INSUFFICIENT_BUFFER == ret || NativeMethods.E_MOREDATA == ret)
142 { 131 {
143 capacity = new IntPtr(capacity.ToInt32() + 1); // Add one for the null terminator. 132 int ret = BalUtil.BalFormatStringFromEngine(this.engine, format, ref handle);
144 sb.Capacity = capacity.ToInt32(); 133 if (ret != NativeMethods.S_OK)
145 ret = this.engine.FormatString(format, sb, ref capacity); 134 {
146 } 135 throw new Win32Exception(ret);
136 }
147 137
148 if (NativeMethods.S_OK != ret) 138 return handle.ToUniString();
139 }
140 finally
149 { 141 {
150 throw new Win32Exception(ret); 142 handle.Dispose();
151 } 143 }
152
153 return sb.ToString();
154 } 144 }
155 145
156 /// <inheritdoc/> 146 /// <inheritdoc/>
@@ -168,53 +158,60 @@ namespace WixToolset.Mba.Core
168 /// <inheritdoc/> 158 /// <inheritdoc/>
169 public SecureString GetVariableSecureString(string name) 159 public SecureString GetVariableSecureString(string name)
170 { 160 {
171 var pUniString = this.getStringVariable(name, out var length); 161 StrUtil.StrHandle handle = new StrUtil.StrHandle();
172 try 162 try
173 { 163 {
174 return this.convertToSecureString(pUniString, length); 164 int ret = BalUtil.BalGetStringVariableFromEngine(this.engine, name, ref handle);
165 if (ret != NativeMethods.S_OK)
166 {
167 throw new Win32Exception(ret);
168 }
169
170 return handle.ToSecureString();
175 } 171 }
176 finally 172 finally
177 { 173 {
178 if (IntPtr.Zero != pUniString) 174 handle.Dispose();
179 {
180 Marshal.FreeCoTaskMem(pUniString);
181 }
182 } 175 }
183 } 176 }
184 177
185 /// <inheritdoc/> 178 /// <inheritdoc/>
186 public string GetVariableString(string name) 179 public string GetVariableString(string name)
187 { 180 {
188 int length; 181 StrUtil.StrHandle handle = new StrUtil.StrHandle();
189 IntPtr pUniString = this.getStringVariable(name, out length);
190 try 182 try
191 { 183 {
192 return Marshal.PtrToStringUni(pUniString, length); 184 int ret = BalUtil.BalGetStringVariableFromEngine(this.engine, name, ref handle);
185 if (ret != NativeMethods.S_OK)
186 {
187 throw new Win32Exception(ret);
188 }
189
190 return handle.ToUniString();
193 } 191 }
194 finally 192 finally
195 { 193 {
196 if (IntPtr.Zero != pUniString) 194 handle.Dispose();
197 {
198 Marshal.FreeCoTaskMem(pUniString);
199 }
200 } 195 }
201 } 196 }
202 197
203 /// <inheritdoc/> 198 /// <inheritdoc/>
204 public string GetVariableVersion(string name) 199 public string GetVariableVersion(string name)
205 { 200 {
206 int length; 201 StrUtil.StrHandle handle = new StrUtil.StrHandle();
207 IntPtr pUniString = this.getVersionVariable(name, out length);
208 try 202 try
209 { 203 {
210 return Marshal.PtrToStringUni(pUniString, length); 204 int ret = BalUtil.BalGetVersionVariableFromEngine(this.engine, name, ref handle);
205 if (ret != NativeMethods.S_OK)
206 {
207 throw new Win32Exception(ret);
208 }
209
210 return handle.ToUniString();
211 } 211 }
212 finally 212 finally
213 { 213 {
214 if (IntPtr.Zero != pUniString) 214 handle.Dispose();
215 {
216 Marshal.FreeCoTaskMem(pUniString);
217 }
218 } 215 }
219 } 216 }
220 217
@@ -337,132 +334,6 @@ namespace WixToolset.Mba.Core
337 } 334 }
338 335
339 /// <summary> 336 /// <summary>
340 /// Gets the variable given by <paramref name="name"/> as a string.
341 /// </summary>
342 /// <param name="name">The name of the variable to get.</param>
343 /// <param name="length">The length of the Unicode string.</param>
344 /// <returns>The value by a pointer to a Unicode string. Must be freed by Marshal.FreeCoTaskMem.</returns>
345 /// <exception cref="Exception">An error occurred getting the variable.</exception>
346 internal IntPtr getStringVariable(string name, out int length)
347 {
348 IntPtr capacity = new IntPtr(InitialBufferSize);
349 bool success = false;
350 IntPtr pValue = Marshal.AllocCoTaskMem(capacity.ToInt32() * UnicodeEncoding.CharSize);
351 try
352 {
353 // Get the size of the buffer.
354 int ret = this.engine.GetVariableString(name, pValue, ref capacity);
355 if (NativeMethods.E_INSUFFICIENT_BUFFER == ret || NativeMethods.E_MOREDATA == ret)
356 {
357 // Don't need to add 1 for the null terminator, the engine already includes that.
358 pValue = Marshal.ReAllocCoTaskMem(pValue, capacity.ToInt32() * UnicodeEncoding.CharSize);
359 ret = this.engine.GetVariableString(name, pValue, ref capacity);
360 }
361
362 if (NativeMethods.S_OK != ret)
363 {
364 throw Marshal.GetExceptionForHR(ret);
365 }
366
367 // The engine only returns the exact length of the string if the buffer was too small, so calculate it ourselves.
368 int maxLength = capacity.ToInt32();
369 for (length = 0; length < maxLength; ++length)
370 {
371 if (0 == Marshal.ReadInt16(pValue, length * UnicodeEncoding.CharSize))
372 {
373 break;
374 }
375 }
376
377 success = true;
378 return pValue;
379 }
380 finally
381 {
382 if (!success && IntPtr.Zero != pValue)
383 {
384 Marshal.FreeCoTaskMem(pValue);
385 }
386 }
387 }
388
389 /// <summary>
390 /// Gets the variable given by <paramref name="name"/> as a version string.
391 /// </summary>
392 /// <param name="name">The name of the variable to get.</param>
393 /// <param name="length">The length of the Unicode string.</param>
394 /// <returns>The value by a pointer to a Unicode string. Must be freed by Marshal.FreeCoTaskMem.</returns>
395 /// <exception cref="Exception">An error occurred getting the variable.</exception>
396 internal IntPtr getVersionVariable(string name, out int length)
397 {
398 IntPtr capacity = new IntPtr(InitialBufferSize);
399 bool success = false;
400 IntPtr pValue = Marshal.AllocCoTaskMem(capacity.ToInt32() * UnicodeEncoding.CharSize);
401 try
402 {
403 // Get the size of the buffer.
404 int ret = this.engine.GetVariableVersion(name, pValue, ref capacity);
405 if (NativeMethods.E_INSUFFICIENT_BUFFER == ret || NativeMethods.E_MOREDATA == ret)
406 {
407 // Don't need to add 1 for the null terminator, the engine already includes that.
408 pValue = Marshal.ReAllocCoTaskMem(pValue, capacity.ToInt32() * UnicodeEncoding.CharSize);
409 ret = this.engine.GetVariableVersion(name, pValue, ref capacity);
410 }
411
412 if (NativeMethods.S_OK != ret)
413 {
414 throw Marshal.GetExceptionForHR(ret);
415 }
416
417 // The engine only returns the exact length of the string if the buffer was too small, so calculate it ourselves.
418 int maxLength = capacity.ToInt32();
419 for (length = 0; length < maxLength; ++length)
420 {
421 if (0 == Marshal.ReadInt16(pValue, length * UnicodeEncoding.CharSize))
422 {
423 break;
424 }
425 }
426
427 success = true;
428 return pValue;
429 }
430 finally
431 {
432 if (!success && IntPtr.Zero != pValue)
433 {
434 Marshal.FreeCoTaskMem(pValue);
435 }
436 }
437 }
438
439 /// <summary>
440 /// Initialize a SecureString with the given Unicode string.
441 /// </summary>
442 /// <param name="pUniString">Pointer to Unicode string.</param>
443 /// <param name="length">The string's length.</param>
444 internal SecureString convertToSecureString(IntPtr pUniString, int length)
445 {
446 if (IntPtr.Zero == pUniString)
447 {
448 return null;
449 }
450
451 SecureString value = new SecureString();
452 short s;
453 char c;
454 for (int charIndex = 0; charIndex < length; charIndex++)
455 {
456 s = Marshal.ReadInt16(pUniString, charIndex * UnicodeEncoding.CharSize);
457 c = (char)s;
458 value.AppendChar(c);
459 s = 0;
460 c = (char)0;
461 }
462 return value;
463 }
464
465 /// <summary>
466 /// Utility method for converting a <see cref="Version"/> into a <see cref="long"/>. 337 /// Utility method for converting a <see cref="Version"/> into a <see cref="long"/>.
467 /// </summary> 338 /// </summary>
468 /// <param name="version"></param> 339 /// <param name="version"></param>