if (reswFilename == null)
reswFilename = string.Empty;
- WindowsRuntimeResourceManagerBase WRRM = null;
- bool bWRRM_Initialized = false;
-
- if (AppDomain.IsAppXDesignMode())
- {
- WRRM = GetWinRTResourceManager();
- try
- {
- PRIExceptionInfo exceptionInfo; // If the exception info is filled in, we will ignore it.
- bWRRM_Initialized = WRRM.Initialize(resourcesAssembly.Location, reswFilename, out exceptionInfo);
- bUsingSatelliteAssembliesUnderAppX = !bWRRM_Initialized;
- }
- catch (Exception e)
- {
- bUsingSatelliteAssembliesUnderAppX = true;
- if (e.IsTransient)
- throw;
- }
- }
-
if (!bUsingSatelliteAssembliesUnderAppX)
{
_bUsingModernResourceManagement = !ShouldUseSatelliteAssemblyResourceLookupUnderAppX(resourcesAssembly);
{
// Only now are we certain that we need the PRI file.
- // Note that if IsAppXDesignMode is false, we haven't checked if the PRI file exists.
- // This is by design. We will find out in the call to WindowsRuntimeResourceManager.Initialize below.
-
// At this point it is important NOT to set _bUsingModernResourceManagement to false
// if the PRI file does not exist because we are now certain we need to load PRI
// resources. We want to fail by throwing a MissingManifestResourceException
// the MissingManifestResourceException from this function, but from GetString. See the
// comment below on the reason for this.
- if (WRRM != null && bWRRM_Initialized)
+ _WinRTResourceManager = GetWinRTResourceManager();
+
+ try
{
- // Reuse the one successfully created earlier
- _WinRTResourceManager = WRRM;
- _PRIonAppXInitialized = true;
+ _PRIonAppXInitialized = _WinRTResourceManager.Initialize(resourcesAssembly.Location, reswFilename, out _PRIExceptionInfo);
+ // Note that _PRIExceptionInfo might be null - this is OK.
+ // In that case we will just throw the generic
+ // MissingManifestResource_NoPRIresources exception.
+ // See the implementation of GetString for more details.
}
- else
+ // We would like to be able to throw a MissingManifestResourceException here if PRI resources
+ // could not be loaded for a recognized reason. However, the ResourceManager constructors
+ // that call SetAppXConfiguration are not documented as throwing MissingManifestResourceException,
+ // and since they are part of the portable profile, we cannot start throwing a new exception type
+ // as that would break existing portable libraries. Hence we must save the exception information
+ // now and throw the exception on the first call to GetString.
+ catch (FileNotFoundException)
{
- _WinRTResourceManager = GetWinRTResourceManager();
-
- try
- {
- _PRIonAppXInitialized = _WinRTResourceManager.Initialize(resourcesAssembly.Location, reswFilename, out _PRIExceptionInfo);
- // Note that _PRIExceptionInfo might be null - this is OK.
- // In that case we will just throw the generic
- // MissingManifestResource_NoPRIresources exception.
- // See the implementation of GetString for more details.
- }
- // We would like to be able to throw a MissingManifestResourceException here if PRI resources
- // could not be loaded for a recognized reason. However, the ResourceManager constructors
- // that call SetAppXConfiguration are not documented as throwing MissingManifestResourceException,
- // and since they are part of the portable profile, we cannot start throwing a new exception type
- // as that would break existing portable libraries. Hence we must save the exception information
- // now and throw the exception on the first call to GetString.
- catch (FileNotFoundException)
- {
- // We will throw MissingManifestResource_NoPRIresources from GetString
- // when we see that _PRIonAppXInitialized is false.
- }
- catch (Exception e)
- {
- // ERROR_MRM_MAP_NOT_FOUND can be thrown by the call to ResourceManager.get_AllResourceMaps
- // in WindowsRuntimeResourceManager.Initialize.
- // In this case _PRIExceptionInfo is now null and we will just throw the generic
- // MissingManifestResource_NoPRIresources exception.
- // See the implementation of GetString for more details.
- if (e.HResult != HResults.ERROR_MRM_MAP_NOT_FOUND)
- throw; // Unexpected exception code. Bubble it up to the caller.
- }
-
- if (!_PRIonAppXInitialized)
- {
- _bUsingModernResourceManagement = false;
- }
- // Allow all other exception types to bubble up to the caller.
-
- // Yes, this causes us to potentially throw exception types that are not documented.
-
- // Ultimately the tradeoff is the following:
- // -We could ignore unknown exceptions or rethrow them as inner exceptions
- // of exceptions that the ResourceManager class is already documented as throwing.
- // This would allow existing portable libraries to gracefully recover if they don't care
- // too much about the ResourceManager object they are using. However it could
- // mask potentially fatal errors that we are not aware of, such as a disk drive failing.
-
-
- // The alternative, which we chose, is to throw unknown exceptions. This may tear
- // down the process if the portable library and app don't expect this exception type.
- // On the other hand, this won't mask potentially fatal errors we don't know about.
+ // We will throw MissingManifestResource_NoPRIresources from GetString
+ // when we see that _PRIonAppXInitialized is false.
}
+ catch (Exception e)
+ {
+ // ERROR_MRM_MAP_NOT_FOUND can be thrown by the call to ResourceManager.get_AllResourceMaps
+ // in WindowsRuntimeResourceManager.Initialize.
+ // In this case _PRIExceptionInfo is now null and we will just throw the generic
+ // MissingManifestResource_NoPRIresources exception.
+ // See the implementation of GetString for more details.
+ if (e.HResult != HResults.ERROR_MRM_MAP_NOT_FOUND)
+ throw; // Unexpected exception code. Bubble it up to the caller.
+ }
+
+ if (!_PRIonAppXInitialized)
+ {
+ _bUsingModernResourceManagement = false;
+ }
+ // Allow all other exception types to bubble up to the caller.
+
+ // Yes, this causes us to potentially throw exception types that are not documented.
+
+ // Ultimately the tradeoff is the following:
+ // -We could ignore unknown exceptions or rethrow them as inner exceptions
+ // of exceptions that the ResourceManager class is already documented as throwing.
+ // This would allow existing portable libraries to gracefully recover if they don't care
+ // too much about the ResourceManager object they are using. However it could
+ // mask potentially fatal errors that we are not aware of, such as a disk drive failing.
+
+
+ // The alternative, which we chose, is to throw unknown exceptions. This may tear
+ // down the process if the portable library and app don't expect this exception type.
+ // On the other hand, this won't mask potentially fatal errors we don't know about.
}
}
}
+++ /dev/null
-// 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.
-//
-//
-// Provides VM-specific AppX utility code.
-
-#include "common.h"
-
-#include "utilcode.h"
-#include "holder.h"
-#include "volatile.h"
-#include "appxutil.h"
-#include "ex.h"
-
-#include "Windows.ApplicationModel.h"
-#include "Windows.ApplicationModel.Core.h"
-
-namespace AppX
-{
- //-----------------------------------------------------------------------------------
- // This is a small helper class designed to ensure that the current thread is
- // RoInitialized for the lifetime of the holder. Use this holder only if code does
- // not store any WinRT interfaces in locations that will out-live the holder
- // itself.
-
- class RoInitializeHolder
- {
- public:
- enum ThreadingModel
- {
- MultiThreaded, // Require multi-threaded model
- SingleThreaded, // Require single-threaded model
- AnyThreadedMultiPreferred // Any threading model is ok;
- // prefer multi-threaded model
- };
-
- RoInitializeHolder(
- ThreadingModel threadingModel) // desired/preferred apartment model
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END
-
- HRESULT hr = S_OK;
-
- {
- GCX_PREEMP();
-
- // Prefer MultiThreaded when AnyThreadedMultiPreferred is specified.
- hr = ::RoInitialize((threadingModel == SingleThreaded) ? RO_INIT_SINGLETHREADED
- : RO_INIT_MULTITHREADED);
- }
-
- // Success means that the thread's RoInitialize ref count has been incremented,
- // and must be paired with a call to RoUnintialize.
- _uninitRequired = SUCCEEDED(hr);
-
- if (FAILED(hr))
- {
- // Throw if:
- // 1. RoInitialize failed for any reason other than RPC_E_CHANGED_MODE
- // 2. RoInitialize failed with RPC_E_CHANGED_MODE and caller will not
- // accept a different apartment model.
- if (hr != RPC_E_CHANGED_MODE || threadingModel != AnyThreadedMultiPreferred)
- {
- // Note: throwing here will cause us to skip the dtor, but will only
- // do so when SUCCEEDED(hr) is FALSE, which means that _uninitRequired
- // is also FALSE so there is no RoInitialize refcount leak here.
- _ASSERTE(!_uninitRequired);
-
- ThrowHR(hr);
- }
- }
- }
-
- // Ensures RoUninitialize is called (if needed) before holder falls out of scope.
- ~RoInitializeHolder()
- {
- LIMITED_METHOD_CONTRACT;
- if (_uninitRequired)
- {
- _uninitRequired = false;
- ::RoUninitialize();
- }
- }
-
- private:
- bool _uninitRequired; // Is a call to RoUnitialize required?
- };
-
- //-----------------------------------------------------------------------------------
-
- HRESULT IsAppXDesignModeWorker(bool * pfResult)
- {
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END
-
- HRESULT hr = S_OK;
-
- boolean fDesignModeEnabled = false;
-
- // Delayloaded entrypoint may throw.
- EX_TRY
- {
- // Ensure that thread is initialized for WinRT; either apt model will work for this API.
- RoInitializeHolder hRoInit(RoInitializeHolder::AnyThreadedMultiPreferred);
-
- ReleaseHolder<ABI::Windows::ApplicationModel::IDesignModeStatics> pIDesignMode;
- IfFailThrow(clr::winrt::GetActivationFactory(
- RuntimeClass_Windows_ApplicationModel_DesignMode, pIDesignMode));
-
- IfFailThrow(pIDesignMode->get_DesignModeEnabled(&fDesignModeEnabled));
- }
- EX_CATCH_HRESULT(hr)
- IfFailRet(hr);
-
- if (!!fDesignModeEnabled)
- {
- *pfResult = true;
- return S_OK;
- }
-
- *pfResult = false;
- return S_OK;
- }
-
- //-----------------------------------------------------------------------------------
- // Returns true if running in an AppX process with DevMode enabled.
-
- bool IsAppXDesignMode()
- {
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END
-
- // CoreCLR does not have proper support for AppX design mode. Once/if it has one, it should not need
- // any special casing like desktop. Avoid the expensive check completely.
- return false;
- }
-
- HRESULT GetApplicationId(LPCWSTR& rString)
- {
- LIMITED_METHOD_CONTRACT;
-
- // the PRAID is a static value for the life of the process. the reason for caching is
- // because the watson bucketing code requires this value during unhandled exception
- // processing and due to the contracts in that code it cannot tolerate the switch to
- // preemptive mode when calling out to WinRT.
- static LPCWSTR s_wzPraid = nullptr;
-
- HRESULT hr = S_OK;
-
- if (s_wzPraid == nullptr)
- {
- ReleaseHolder<ABI::Windows::ApplicationModel::Core::ICoreApplication> coreApp;
-
- hr = clr::winrt::GetActivationFactory(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication, coreApp);
-
- if (SUCCEEDED(hr))
- {
- WinRtString winrtAppId;
- hr = coreApp->get_Id(winrtAppId.Address());
-
- if (SUCCEEDED(hr))
- {
- LPCWSTR wzPraid = DuplicateString(winrtAppId.GetRawBuffer(), winrtAppId.size());
- if (wzPraid)
- {
- if (InterlockedCompareExchangeT(&s_wzPraid, wzPraid, nullptr) != nullptr)
- delete[] wzPraid;
- }
- else
- {
- hr = E_OUTOFMEMORY;
- }
- }
- }
- }
-
- rString = s_wzPraid;
-
- return hr;
- }
-
-
-}
-
-
+++ /dev/null
-// 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.
-////////////////////////////////////////////////////////////////////////////////
-// ResFile.CPP
-
-
-
-#include "common.h"
-
-#include "assemblynativeresource.h"
-#include <limits.h>
-
-#ifndef CP_WINUNICODE
- #define CP_WINUNICODE 1200
-#endif
-
-#ifndef MAKEINTRESOURCE
- #define MAKEINTRESOURCE MAKEINTRESOURCEW
-#endif
-
-Win32Res::Win32Res()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- FORBID_FAULT;
- }
- CONTRACTL_END
-
- m_szFile = NULL;
- m_Icon = NULL;
- int i;
- for (i = 0; i < NUM_VALUES; i++)
- m_Values[i] = NULL;
- for (i = 0; i < NUM_VALUES; i++)
- m_Values[i] = NULL;
- m_fDll = false;
- m_pData = NULL;
- m_pCur = NULL;
- m_pEnd = NULL;
-}
-
-Win32Res::~Win32Res()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- FORBID_FAULT;
- }
- CONTRACTL_END
-
- m_szFile = NULL;
- m_Icon = NULL;
- int i;
- for (i = 0; i < NUM_VALUES; i++)
- m_Values[i] = NULL;
- for (i = 0; i < NUM_VALUES; i++)
- m_Values[i] = NULL;
- m_fDll = false;
- if (m_pData)
- delete [] m_pData;
- m_pData = NULL;
- m_pCur = NULL;
-
- m_pEnd = NULL;
-}
-
-//*****************************************************************************
-// Initializes the structures with version information.
-//*****************************************************************************
-VOID Win32Res::SetInfo(
- LPCWSTR szFile,
- LPCWSTR szTitle,
- LPCWSTR szIconName,
- LPCWSTR szDescription,
- LPCWSTR szCopyright,
- LPCWSTR szTrademark,
- LPCWSTR szCompany,
- LPCWSTR szProduct,
- LPCWSTR szProductVersion,
- LPCWSTR szFileVersion,
- LCID lcid,
- BOOL fDLL)
-{
- STANDARD_VM_CONTRACT;
-
- _ASSERTE(szFile != NULL);
-
- m_szFile = szFile;
- if (szIconName && szIconName[0] != 0)
- m_Icon = szIconName; // a non-mepty string
-
-#define NonNull(sz) (sz == NULL || *sz == W('\0') ? W(" ") : sz)
- m_Values[v_Description] = NonNull(szDescription);
- m_Values[v_Title] = NonNull(szTitle);
- m_Values[v_Copyright] = NonNull(szCopyright);
- m_Values[v_Trademark] = NonNull(szTrademark);
- m_Values[v_Product] = NonNull(szProduct);
- m_Values[v_ProductVersion] = NonNull(szProductVersion);
- m_Values[v_Company] = NonNull(szCompany);
- m_Values[v_FileVersion] = NonNull(szFileVersion);
-#undef NonNull
-
- m_fDll = fDLL;
- m_lcid = lcid;
-}
-
-VOID Win32Res::MakeResFile(const void **pData, DWORD *pcbData)
-{
- STANDARD_VM_CONTRACT;
-
- static const RESOURCEHEADER magic = { 0x00000000, 0x00000020, 0xFFFF, 0x0000, 0xFFFF, 0x0000,
- 0x00000000, 0x0000, 0x0000, 0x00000000, 0x00000000 };
- _ASSERTE(pData != NULL && pcbData != NULL);
-
- *pData = NULL;
- *pcbData = 0;
- m_pData = new BYTE[(sizeof(RESOURCEHEADER) * 3 + sizeof(EXEVERRESOURCE))];
-
- m_pCur = m_pData;
- m_pEnd = m_pData + sizeof(RESOURCEHEADER) * 3 + sizeof(EXEVERRESOURCE);
-
- // inject the magic empty entry
- Write( &magic, sizeof(magic) );
-
- WriteVerResource();
-
- if (m_Icon)
- {
- WriteIconResource();
- }
-
- *pData = m_pData;
- *pcbData = (DWORD)(m_pCur - m_pData);
- return;
-}
-
-
-/*
- * WriteIconResource
- * Writes the Icon resource into the RES file.
- *
- * RETURNS: TRUE on succes, FALSE on failure (errors reported to user)
- */
-VOID Win32Res::WriteIconResource()
-{
- STANDARD_VM_CONTRACT;
-
- HandleHolder hIconFile = INVALID_HANDLE_VALUE;
- WORD wTemp, wCount, resID = 2; // Skip 1 for the version ID
- DWORD dwRead = 0, dwWritten = 0;
-
- RESOURCEHEADER grpHeader = { 0x00000000, 0x00000020, 0xFFFF, (WORD)(size_t)RT_GROUP_ICON, 0xFFFF, 0x7F00, // 0x7F00 == IDI_APPLICATION
- 0x00000000, 0x1030, 0x0000, 0x00000000, 0x00000000 };
-
- // Read the icon
- hIconFile = WszCreateFile( m_Icon, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
- FILE_FLAG_SEQUENTIAL_SCAN, NULL);
- if (hIconFile == INVALID_HANDLE_VALUE) {
- COMPlusThrowWin32();
- }
-
- // Read the magic reserved WORD
- if (ReadFile( hIconFile, &wTemp, sizeof(WORD), &dwRead, NULL) == FALSE) {
- COMPlusThrowWin32();
- } else if (wTemp != 0 || dwRead != sizeof(WORD)) {
- COMPlusThrowHR(HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
- }
-
- // Verify the Type WORD
- if (ReadFile( hIconFile, &wCount, sizeof(WORD), &dwRead, NULL) == FALSE) {
- COMPlusThrowWin32();
- } else if (wCount != 1 || dwRead != sizeof(WORD)) {
- COMPlusThrowHR(HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
- }
-
- // Read the Count WORD
- if (ReadFile( hIconFile, &wCount, sizeof(WORD), &dwRead, NULL) == FALSE) {
- COMPlusThrowWin32();
- } else if (wCount == 0 || dwRead != sizeof(WORD)) {
- COMPlusThrowHR(HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
- }
-
- NewArrayHolder<ICONRESDIR> grp = new ICONRESDIR[wCount];
- grpHeader.DataSize = 3 * sizeof(WORD) + wCount * sizeof(ICONRESDIR);
-
- // For each Icon
- for (WORD i = 0; i < wCount; i++) {
- ICONDIRENTRY ico;
- DWORD icoPos, newPos;
- RESOURCEHEADER icoHeader = { 0x00000000, 0x00000020, 0xFFFF, (WORD)(size_t)RT_ICON, 0xFFFF, 0x0000,
- 0x00000000, 0x1010, 0x0000, 0x00000000, 0x00000000 };
- icoHeader.Name = resID++;
-
- // Read the Icon header
- if (ReadFile( hIconFile, &ico, sizeof(ICONDIRENTRY), &dwRead, NULL) == FALSE) {
- COMPlusThrowWin32();
- }
- else if (dwRead != sizeof(ICONDIRENTRY)) {
- COMPlusThrowHR(HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
- }
-
- _ASSERTE(sizeof(ICONRESDIR) + sizeof(WORD) == sizeof(ICONDIRENTRY));
- memcpy(grp + i, &ico, sizeof(ICONRESDIR));
- grp[i].IconId = icoHeader.Name;
- icoHeader.DataSize = ico.dwBytesInRes;
-
- NewArrayHolder<BYTE> icoBuffer = new BYTE[icoHeader.DataSize];
-
- // Write the header to the RES file
- Write( &icoHeader, sizeof(RESOURCEHEADER) );
-
- // Position to read the Icon data
- icoPos = SetFilePointer( hIconFile, 0, NULL, FILE_CURRENT);
- if (icoPos == INVALID_SET_FILE_POINTER) {
- COMPlusThrowWin32();
- }
- newPos = SetFilePointer( hIconFile, ico.dwImageOffset, NULL, FILE_BEGIN);
- if (newPos == INVALID_SET_FILE_POINTER) {
- COMPlusThrowWin32();
- }
-
- // Actually read the data
- if (ReadFile( hIconFile, icoBuffer, icoHeader.DataSize, &dwRead, NULL) == FALSE) {
- COMPlusThrowWin32();
- }
- else if (dwRead != icoHeader.DataSize) {
- COMPlusThrowHR(HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
- }
-
- // Because Icon files don't seem to record the actual Planes and BitCount in
- // the ICONDIRENTRY, get the info from the BITMAPINFOHEADER at the beginning
- // of the data here:
- grp[i].Planes = ((BITMAPINFOHEADER*)(BYTE*)icoBuffer)->biPlanes;
- grp[i].BitCount = ((BITMAPINFOHEADER*)(BYTE*)icoBuffer)->biBitCount;
-
- // Now write the data to the RES file
- Write( (BYTE*)icoBuffer, icoHeader.DataSize );
-
- // Reposition to read the next Icon header
- newPos = SetFilePointer( hIconFile, icoPos, NULL, FILE_BEGIN);
- if (newPos != icoPos) {
- COMPlusThrowWin32();
- }
- }
-
- // inject the icon group
- Write( &grpHeader, sizeof(RESOURCEHEADER) );
-
- // Write the header to the RES file
- wTemp = 0; // the reserved WORD
- Write( &wTemp, sizeof(WORD) );
-
- wTemp = RES_ICON; // the GROUP type
- Write( &wTemp, sizeof(WORD) );
-
- Write( &wCount, sizeof(WORD) );
-
- // now write the entries
- Write( grp, sizeof(ICONRESDIR) * wCount );
-
- return;
-}
-
-/*
- * WriteVerResource
- * Writes the version resource into the RES file.
- *
- * RETURNS: TRUE on succes, FALSE on failure (errors reported to user)
- */
-VOID Win32Res::WriteVerResource()
-{
- STANDARD_VM_CONTRACT;
-
- WCHAR szLangCp[9]; // language/codepage string.
- EXEVERRESOURCE VerResource;
- WORD cbStringBlocks;
- int i;
- bool bUseFileVer = false;
- WCHAR rcFile[_MAX_PATH] = {0}; // Name of file without path
- WCHAR rcFileExtension[_MAX_PATH] = {0}; // file extension
- WCHAR rcFileName[_MAX_PATH]; // Name of file with extension but without path
- DWORD cbTmp;
-
- SplitPath(m_szFile, 0, 0, 0, 0, rcFile, _MAX_PATH, rcFileExtension, _MAX_PATH);
-
- wcscpy_s(rcFileName, COUNTOF(rcFileName), rcFile);
- wcscat_s(rcFileName, COUNTOF(rcFileName), rcFileExtension);
-
- static const EXEVERRESOURCE VerResourceTemplate = {
- sizeof(EXEVERRESOURCE), sizeof(VS_FIXEDFILEINFO), 0, W("VS_VERSION_INFO"),
- {
- VS_FFI_SIGNATURE, // Signature
- VS_FFI_STRUCVERSION, // structure version
- 0, 0, // file version number
- 0, 0, // product version number
- VS_FFI_FILEFLAGSMASK, // file flags mask
- 0, // file flags
- VOS__WINDOWS32,
- VFT_APP, // file type
- 0, // subtype
- 0, 0 // file date/time
- },
- sizeof(WORD) * 2 + 2 * HDRSIZE + KEYBYTES("VarFileInfo") + KEYBYTES("Translation"),
- 0,
- 1,
- W("VarFileInfo"),
- sizeof(WORD) * 2 + HDRSIZE + KEYBYTES("Translation"),
- sizeof(WORD) * 2,
- 0,
- W("Translation"),
- 0,
- 0,
- 2 * HDRSIZE + KEYBYTES("StringFileInfo") + KEYBYTES("12345678"),
- 0,
- 1,
- W("StringFileInfo"),
- HDRSIZE + KEYBYTES("12345678"),
- 0,
- 1,
- W("12345678")
- };
- static const WCHAR szComments[] = W("Comments");
- static const WCHAR szCompanyName[] = W("CompanyName");
- static const WCHAR szFileDescription[] = W("FileDescription");
- static const WCHAR szCopyright[] = W("LegalCopyright");
- static const WCHAR szTrademark[] = W("LegalTrademarks");
- static const WCHAR szProdName[] = W("ProductName");
- static const WCHAR szFileVerResName[] = W("FileVersion");
- static const WCHAR szProdVerResName[] = W("ProductVersion");
- static const WCHAR szInternalNameResName[] = W("InternalName");
- static const WCHAR szOriginalNameResName[] = W("OriginalFilename");
-
- // If there's no product version, use the file version
- if (m_Values[v_ProductVersion][0] == 0) {
- m_Values[v_ProductVersion] = m_Values[v_FileVersion];
- bUseFileVer = true;
- }
-
- // Keep the two following arrays in the same order
-#define MAX_KEY 10
- static const LPCWSTR szKeys [MAX_KEY] = {
- szComments,
- szCompanyName,
- szFileDescription,
- szFileVerResName,
- szInternalNameResName,
- szCopyright,
- szTrademark,
- szOriginalNameResName,
- szProdName,
- szProdVerResName,
- };
- LPCWSTR szValues [MAX_KEY] = { // values for keys
- m_Values[v_Description], //compiler->assemblyDescription == NULL ? W("") : compiler->assemblyDescription,
- m_Values[v_Company], // Company Name
- m_Values[v_Title], // FileDescription //compiler->assemblyTitle == NULL ? W("") : compiler->assemblyTitle,
- m_Values[v_FileVersion], // FileVersion
- rcFileName, // InternalName
- m_Values[v_Copyright], // Copyright
- m_Values[v_Trademark], // Trademark
- rcFileName, // OriginalName
- m_Values[v_Product], // Product Name //compiler->assemblyTitle == NULL ? W("") : compiler->assemblyTitle,
- m_Values[v_ProductVersion] // Product Version
- };
-
- memcpy(&VerResource, &VerResourceTemplate, sizeof(VerResource));
-
- if (m_fDll)
- VerResource.vsFixed.dwFileType = VFT_DLL;
- else
- VerResource.vsFixed.dwFileType = VFT_APP;
-
- // Extract the numeric version from the string.
- m_Version[0] = m_Version[1] = m_Version[2] = m_Version[3] = 0;
- int nNumStrings = swscanf_s(m_Values[v_FileVersion], W("%hu.%hu.%hu.%hu"), m_Version, m_Version + 1, m_Version + 2, m_Version + 3);
-
- // Fill in the FIXEDFILEINFO
- VerResource.vsFixed.dwFileVersionMS =
- ((DWORD)m_Version[0] << 16) + m_Version[1];
-
- VerResource.vsFixed.dwFileVersionLS =
- ((DWORD)m_Version[2] << 16) + m_Version[3];
-
- if (bUseFileVer) {
- VerResource.vsFixed.dwProductVersionLS = VerResource.vsFixed.dwFileVersionLS;
- VerResource.vsFixed.dwProductVersionMS = VerResource.vsFixed.dwFileVersionMS;
- }
- else {
- WORD v[4];
- v[0] = v[1] = v[2] = v[3] = 0;
- // Try to get the version numbers, but don't waste time or give any errors
- // just default to zeros
- nNumStrings = swscanf_s(m_Values[v_ProductVersion], W("%hu.%hu.%hu.%hu"), v, v + 1, v + 2, v + 3);
-
- VerResource.vsFixed.dwProductVersionMS =
- ((DWORD)v[0] << 16) + v[1];
-
- VerResource.vsFixed.dwProductVersionLS =
- ((DWORD)v[2] << 16) + v[3];
- }
-
- // There is no documentation on what units to use for the date! So we use zero.
- // The Windows resource compiler does too.
- VerResource.vsFixed.dwFileDateMS = VerResource.vsFixed.dwFileDateLS = 0;
-
- // Fill in codepage/language -- we'll assume the IDE language/codepage
- // is the right one.
- if (m_lcid != -1)
- VerResource.langid = static_cast<WORD>(m_lcid);
- else
- VerResource.langid = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
- VerResource.codepage = CP_WINUNICODE; // Unicode codepage.
-
- swprintf_s(szLangCp, NumItems(szLangCp), W("%04x%04x"), VerResource.langid, VerResource.codepage);
- wcscpy_s(VerResource.szLangCpKey, COUNTOF(VerResource.szLangCpKey), szLangCp);
-
- // Determine the size of all the string blocks.
- cbStringBlocks = 0;
- for (i = 0; i < MAX_KEY; i++) {
- if (szValues[i] == NULL || wcslen(szValues[i]) == 0)
- continue;
- cbTmp = SizeofVerString( szKeys[i], szValues[i]);
- if ((cbStringBlocks + cbTmp) > USHRT_MAX / 2)
- COMPlusThrow(kArgumentException, W("Argument_VerStringTooLong"));
- cbStringBlocks += (WORD) cbTmp;
- }
-
- if ((cbStringBlocks + VerResource.cbLangCpBlock) > USHRT_MAX / 2)
- COMPlusThrow(kArgumentException, W("Argument_VerStringTooLong"));
- VerResource.cbLangCpBlock += cbStringBlocks;
-
- if ((cbStringBlocks + VerResource.cbStringBlock) > USHRT_MAX / 2)
- COMPlusThrow(kArgumentException, W("Argument_VerStringTooLong"));
- VerResource.cbStringBlock += cbStringBlocks;
-
- if ((cbStringBlocks + VerResource.cbRootBlock) > USHRT_MAX / 2)
- COMPlusThrow(kArgumentException, W("Argument_VerStringTooLong"));
- VerResource.cbRootBlock += cbStringBlocks;
-
- // Call this VS_VERSION_INFO
- RESOURCEHEADER verHeader = { 0x00000000, 0x0000003C, 0xFFFF, (WORD)(size_t)RT_VERSION, 0xFFFF, 0x0001,
- 0x00000000, 0x0030, 0x0000, 0x00000000, 0x00000000 };
- verHeader.DataSize = VerResource.cbRootBlock;
-
- // Write the header
- Write( &verHeader, sizeof(RESOURCEHEADER) );
-
- // Write the version resource
- Write( &VerResource, sizeof(VerResource) );
-
-
- // Write each string block.
- for (i = 0; i < MAX_KEY; i++) {
- if (szValues[i] == NULL || wcslen(szValues[i]) == 0)
- continue;
- WriteVerString( szKeys[i], szValues[i] );
- }
-#undef MAX_KEY
-
- return;
-}
-
-/*
- * SizeofVerString
- * Determines the size of a version string to the given stream.
- * RETURNS: size of block in bytes.
- */
-WORD Win32Res::SizeofVerString(LPCWSTR lpszKey, LPCWSTR lpszValue)
-{
- STANDARD_VM_CONTRACT;
-
- size_t cbKey, cbValue;
-
- cbKey = (wcslen(lpszKey) + 1) * 2; // Make room for the NULL
- cbValue = (wcslen(lpszValue) + 1) * 2;
- if (cbValue == 2)
- cbValue = 4; // Empty strings need a space and NULL terminator (for Win9x)
- if (cbKey + cbValue >= 0xFFF0)
- COMPlusThrow(kArgumentException, W("Argument_VerStringTooLong"));
-
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:6305) // "Potential mismatch between sizeof and countof quantities"
-#endif
-
- return (WORD)(PadKeyLen(cbKey) + // key, 0 padded to DWORD boundary
- PadValLen(cbValue) + // value, 0 padded to dword boundary
- HDRSIZE); // block header.
-
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-}
-
-/*----------------------------------------------------------------------------
- * WriteVerString
- * Writes a version string to the given file.
- */
-VOID Win32Res::WriteVerString( LPCWSTR lpszKey, LPCWSTR lpszValue)
-{
- STANDARD_VM_CONTRACT;
-
- size_t cbKey, cbValue, cbBlock;
- bool bNeedsSpace = false;
-
- cbKey = (wcslen(lpszKey) + 1) * 2; // includes terminating NUL
- cbValue = wcslen(lpszValue);
- if (cbValue > 0)
- cbValue++; // make room for NULL
- else {
- bNeedsSpace = true;
- cbValue = 2; // Make room for space and NULL (for Win9x)
- }
- cbBlock = SizeofVerString(lpszKey, lpszValue);
-
- NewArrayHolder<BYTE> pbBlock = new BYTE[(DWORD)cbBlock + HDRSIZE];
- ZeroMemory(pbBlock, (DWORD)cbBlock + HDRSIZE);
-
- _ASSERTE(cbValue < USHRT_MAX && cbKey < USHRT_MAX && cbBlock < USHRT_MAX);
-
- // Copy header, key and value to block.
- *(WORD *)((BYTE *)pbBlock) = (WORD)cbBlock;
- *(WORD *)(pbBlock + sizeof(WORD)) = (WORD)cbValue;
- *(WORD *)(pbBlock + 2 * sizeof(WORD)) = 1; // 1 = text value
- // size = (cbBlock + HDRSIZE - HDRSIZE) / sizeof(WCHAR)
- wcscpy_s((WCHAR*)(pbBlock + HDRSIZE), (cbBlock / sizeof(WCHAR)), lpszKey);
-
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:6305) // "Potential mismatch between sizeof and countof quantities"
-#endif
-
- if (bNeedsSpace)
- *((WCHAR*)(pbBlock + (HDRSIZE + PadKeyLen(cbKey)))) = W(' ');
- else
- {
- wcscpy_s((WCHAR*)(pbBlock + (HDRSIZE + PadKeyLen(cbKey))),
- //size = ((cbBlock + HDRSIZE) - (HDRSIZE + PadKeyLen(cbKey))) / sizeof(WCHAR)
- (cbBlock - PadKeyLen(cbKey))/sizeof(WCHAR),
- lpszValue);
- }
-
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-
- // Write block
- Write( pbBlock, cbBlock);
-
- return;
-}
-
-VOID Win32Res::Write(LPCVOID pData, size_t len)
-{
- STANDARD_VM_CONTRACT;
-
- if (m_pCur + len > m_pEnd) {
- // Grow
- size_t newSize = (m_pEnd - m_pData);
-
- // double the size unless we need more than that
- if (len > newSize)
- newSize += len;
- else
- newSize *= 2;
-
- LPBYTE pNew = new BYTE[newSize];
- memcpy(pNew, m_pData, m_pCur - m_pData);
- delete [] m_pData;
- // Relocate the pointers
- m_pCur = pNew + (m_pCur - m_pData);
- m_pData = pNew;
- m_pEnd = pNew + newSize;
- }
-
- // Copy it in
- memcpy(m_pCur, pData, len);
- m_pCur += len;
- return;
-}
-