Monday, July 3, 2017

How to resolve a System.Security.Principal.IdentityNotMappedException?

Sometimes when working with a non-English version of Windows, we get kinda problem
"Some or all identity references could not be translated"
This indicates that we are getting a System.Security.Principal.IdentityNotMappedException
What does it mean?


The first thing to understand is that in Windows, User Accounts and Groups have a unique and immutable identifier known as a Security Identifier (SID). When working with User Accounts and Groups in Windows, you can work with them via their SID or by their name.

In Windows, a user is represented by an Access Token (You can find more information on Access Tokens at http://msdn.microsoft.com/en-us/library/windows/desktop/aa374909(v=vs.85).aspx) which can be associated with a process or to a thread (via impersonation).
The token contains the user’s SID and all the Groups the user is a member of. The token contains the Group SIDs. (The groups are NOT stored by their names)

There are Win32 APIs that allows an application to translate between the name and the SID:



These Win32 APIs actually calls the LSA APIs. (One difference with these APIs is that they allow to translate multiple names/SIDs instead just one.)


When converting between a Name and a SID and vice versa, you can encounter an error if the translation can’t be done. The common Win32 Error code that you will see is 1332 also known as ERROR_NONE_MAPPED which translates to “No mapping between account names and security IDs was done.”

At the LSA API level where status errors are returned, the error is: STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED. In .NET, the error code is mapped as the following exception:System.Security.Principal.IdentityNotMappedException

Why would the translation APIs fail? Well, the API remarks provides some details on how the translation is done. It uses a lookup order to translate (there is also a local cache as well)

In addition to looking up SIDs for local accounts, local domain accounts, and explicitly trusted domain accounts, LsaLookupSids can look up SIDs for any account in any domain in the Windows forest, including SIDs that appear only in the SIDhistory field of an account in the forest. The SIDhistory field stores the former SIDs of an account that has been moved from another domain. To perform these searches, the function queries the global catalog of the forest.

So a translation failure could happen if you have an issue with your Domain(s) or an issue with SID History. So the first step in determining the issue is identifying which user or SID is the issue. Once you have identified the User or SID, you can then review its relationship with the caller (who is this and what domain do they belong to and what domain does the system belong to where the caller is running)

Finally, a word of advice, internally most APIs are going to be working with SIDs so you can avoid the translation error and improve performance by always trying to work with SIDs.
You’ll notice that most classes in .NET such as IsInRole() allows you to specify a SID instead of the name (via the SecurityIdentifier class). WindowsIdentity.Groups allows you access to the SID as well.


Example:
I want to set permission for a user

static void SetPermission(string directory)
{
   var directoryInfo = new DirectoryInfo(directory);
   var directorySecurity = directoryInfo.GetAccessControl();
   CanonicalizeDacl(directorySecurity);
   directorySecurity.AddAccessRule(new FileSystemAccessRule("BUILTIN\\IIS_IUSRS", FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
   directoryInfo.SetAccessControl(directorySecurity);
}


This code would be failed if it run in a non-English version of Windows because the "BUILTIN\\IIS_IUSRS" could not be translated. Exactly the "BUILTIN" could not be translated. To fix this problem, I could change to remove "BUILTIN" or use an SID instead.

static void SetPermission(string directory)
{
   var directoryInfo = new DirectoryInfo(directory);
   var directorySecurity = directoryInfo.GetAccessControl();
   var sid = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
   directorySecurity.AddAccessRule(new FileSystemAccessRule(sid, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
   directoryInfo.SetAccessControl(directorySecurity);
}


Refer these links for SID
https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
https://msdn.microsoft.com/en-us/library/cc980032.aspx

Using statement inside Vs outside

A namespace declaration looks like: MyCorp.TheProduct.SomeModule.Utilities
This could be equivalence


namespace MyCorp
{
   namespace TheProduct
   {
      namespace SomeModule
      {
         namespace Utilities
         {
            ...
         }
      }
   }
}

The rule to resolve the namespace is: First, search the inner most "scope" for a match. If nothing is found then goes out 1 level, continue searching,next and so on... Until a match is found.
Let check the code

With using outside

using System;
using System.Collections.Generic;
using System.Linq;
//using MyCorp.TheProduct; <-- br="" change="" nothing="" this="" uncommenting="" would=""> using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;

namespace MyCorp.TheProduct.SomeModule.Utilities
{
   class C
   {
      Ambiguous a;
   }
}


In the above case, to find out what type Ambiguous is, the search goes in this order:


  1. Nested types inside C (including inherited nested types)
  2. Types in the current namespace MyCorp.TheProduct.SomeModule.Utilities
  3. Types in namespace MyCorp.TheProduct.SomeModule
  4. Types in MyCorp.TheProduct
  5. Types in MyCorp
  6. Types in the null namespace (the global namespace)
  7. Types in System, System.Collections.Generic, System.Linq, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration, and ThirdParty



With usings inside:
namespace MyCorp.TheProduct.SomeModule.Utilities
{
   using System;
   using System.Collections.Generic;
   using System.Linq;
   using MyCorp.TheProduct;
   using MyCorp.TheProduct.OtherModule;
   using MyCorp.TheProduct.OtherModule.Integration;
   using ThirdParty;

   class C
   {
      Ambiguous a;
   }
}


Now, search for the type Ambiguous goes in this order:

  1. Nested types inside C (including inherited nested types)
  2. Types in the current namespace MyCorp.TheProduct.SomeModule.Utilities
  3. Types in System, System.Collections.Generic, System.Linq, MyCorp.TheProduct, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration, and ThirdParty
  4. Types in namespace MyCorp.TheProduct.SomeModule
  5. Types in MyCorp (MyCorp.TheProduct is already searched)
  6. Types in the null namespace (the global namespace)



No matter what we put the using inside or outside the namespace declaration, there's always the possibility that someone add a new type later with identical name ambiguous to one of the namespaces which has higher priority.
Also, if a nested namespace has the same name as a type, it can cause problems.

It's always dangerous to move the using form outside to inside and vice versa. The search hierarchy is changed and another type would be found. Therefore, chose one convention and stick to it.

One advantage of having using outside is that we can rename the using directives look like using AC=System.Security.AccessControl

Tuesday, March 7, 2017

Create an offline installer for Visual Studio 2017

Download the setup file you want

Edition File
Visual Studio Enterprise vs_enterprise.exe
Visual Studio Professional vs_professional.exe
Visual Studio Community vs_community.exe


Create an offline installation folder

To create an offline installation with all languages and all features, use one of the commands from the following examples. Run cmd in Administrator privilege.

Visual Studio Enterprise vs_enterprise.exe --layout c:\vs2017offline
Visual Studio Professional vs_professional.exe --layout c:\vs2017offline
Visual Studio Community vs_community.exe --layout c:\vs2017offline


Install from the offline installation folder

  1. Install the certificates (They are in the Certificates folder, which is in your Layout folder. Simply right-click each one to install it.)
  2. Run the installation file. For example, run:
    c:\vs2017offline\vs_enterprise.exe


Additional tips for offline installers

There are many options you can use to customize your offline installer. Here are a few examples of how to customize it by language locale

  • To download all workloads and components for only one language, run:
    vs_enterprise.exe --layout C:\vs2017offline --lang en-US
  • To download all workloads and components for multiple languages, run:
    vs_enterprise.exe --layout C:\vs2017offline --lang en-US de-DE ja-JP
  • To download one workload for all languages, run
    vs_enterprise.exe --layout C:\vs2017offline --add Microsoft.VisualStudio.Workload.Azure
  • To download two workloads and one optional component for three languages, run:
    vs_enterprise.exe --layout C:\vs2017offline --add Microsoft.VisualStudio.Workload.Azure Microsoft.VisualStudio.Workload.ManagedDesktop Component.GitHub.VisualStudio --lang en-US de-DE ja-JP
To learn more about the options you can use to customize your installation, see our  Use command-line parameters to install Visual Studio 2017  page.


How to update an offline installer

You might want to update your offline installer at a later date. Here's how.
  • To update a Visual Studio instance that you installed from an offline installation folder, run the Visual Studio Installer, and then click Update.
  • To refresh your offline installation folder so that it includes the latest updates, run the --layout command again. Make sure to point to the same folder that you used before; this way, only those components that have been updated since you last ran --layout will be downloaded.
If you want to update your offline installation, run the  --layout  command again. Make sure to point to the same folder that you used before; this way, only those components that have been updated since you last ran  --layout  will be downloaded.

Thursday, February 16, 2017

Windows File System: Maximum Path Length Limitation

In the Windows API (with some exceptions discussed in the following paragraphs), the maximum length for a path is MAX_PATH, which is defined as 260 characters. A local path is structured in the following order: drive letter, colon, backslash, name components separated by backslashes, and a terminating null character. For example, the maximum path on drive D is "D:\some 256-character path string" where "" represents the invisible terminating null character for the current system codepage. (The characters < > are used here for visual clarity and cannot be part of a valid path string.)

NOTE: File I/O functions in the Windows API convert "/" to "\" as part of converting the name to an NT-style name, except when using the "\\?\" prefix as detailed in the following sections.

The Windows API has many functions that also have Unicode versions to permit an extended-length path for a maximum total path length of 32,767 characters. This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function (this value is commonly 255 characters). To specify an extended-length path, use the "\\?\" prefix. For example, "\\?\D:\very long path".

NOTE: The maximum path of 32,767 characters is approximate, because the "\\?\" prefix may be expanded to a longer string by the system at run time, and this expansion applies to the total length.

The "\\?\" prefix can also be used with paths constructed according to the universal naming convention (UNC). To specify such a path using UNC, use the "\\?\UNC\" prefix. For example, "\\?\UNC\server\share", where "server" is the name of the computer and "share" is the name of the shared folder. These prefixes are not used as part of the path itself. They indicate that the path should be passed to the system with minimal modification, which means that you cannot use forward slashes to represent path separators, or a period to represent the current directory, or double dots to represent the parent directory. Because you cannot use the "\\?\" prefix with a relative path, relative paths are always limited to a total of MAX_PATH characters.

There is no need to perform any Unicode normalization on path and file name strings for use by the Windows file I/O API functions because the file system treats path and file names as an opaque sequence of WCHARs. Any normalization that your application requires should be performed with this in mind, external of any calls to related Windows file I/O API functions.

When using an API to create a directory, the specified path cannot be so long that you cannot append an 8.3 file name (that is, the directory name cannot exceed MAX_PATH minus 12).
The shell and the file system have different requirements. It is possible to create a path with the Windows API that the shell user interface is not able to interpret properly.

TIP: Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. However, you must opt-in to the new behavior.

A registry key allows you to enable or disable the new long path behavior. To enable long path behavior set the registry key at HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled (Type: REG_DWORD). The key's value will be cached by the system (per process) after the first call to an affected Win32 file or directory function (list follows). The registry key will not be reloaded during the lifetime of the process. In order for all apps on the system to recognize the value of the key, a reboot might be required because some processes may have started before the key was set.
The registry key can also be controlled via Group Policy at Computer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long paths.
You can also enable the new long path behavior per app via the manifest:


<application xmlns=urn:schemas-microsoft-com:asm.v3>
    <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
        <ws2:longPathAware></ws2:longPathAware>
    </windowsSettings>
</application>



These are the directory management functions that no longer have MAX_PATH restrictions if you opt-in to long path behavior: CreateDirectoryW, CreateDirectoryExW GetCurrentDirectoryW RemoveDirectoryW SetCurrentDirectoryW.

These are the file management functions that no longer have MAX_PATH restrictions if you opt-in to long path behavior: CopyFileW, CopyFile2, CopyFileExW, CreateFileW, CreateFile2, CreateHardLinkW, CreateSymbolicLinkW, DeleteFileW, FindFirstFileW, FindFirstFileExW, FindNextFileW, GetFileAttributesW, GetFileAttributesExW, SetFileAttributesW, GetFullPathNameW, GetLongPathNameW, MoveFileW, MoveFileExW, MoveFileWithProgressW, ReplaceFileW, SearchPathW, FindFirstFileNameW, FindNextFileNameW, FindFirstStreamW, FindNextStreamW, GetCompressedFileSizeW, GetFinalPathNameByHandleW.

Tuesday, September 27, 2016

VMWare error: Could not get vmci driver version















Somebody says that you open up the configuration file of the VM and try to vmci0.present=FALSE. This can solve the problem at instance but another problem occurred that is the network of VM does not work.
The correct way to fix this problem is run the VM Installer again with Administrator privilege and select repair. This will fix your problem.

Wednesday, September 7, 2016

View or Change the Default Locations for Data and Log Files (SQL Server Management Studio)


  • In Object Explorer, right-click on your server and click Properties
  • In the left panel on that Properties page, click the Database settings tab.
  • In Database default locations, view the current default locations for new data files and new log files. To change a default location, enter a new default pathname in the Data or Log field, or click the browse button to find and select a pathname.

NOTE: After changing the default locations, you must stop and start the SQL Server service to complete the change.