+int canonicalise_username(const TCHAR *username, TCHAR **canon) {
+ LSA_HANDLE policy;
+ if (open_lsa_policy(&policy)) return 1;
+
+ SID *sid;
+ if (username_sid(username, &sid, &policy)) return 2;
+ PSID sids = { sid };
+
+ LSA_REFERENCED_DOMAIN_LIST *translated_domains;
+ LSA_TRANSLATED_NAME *translated_name;
+ NTSTATUS status = LsaLookupSids(policy, 1, &sids, &translated_domains, &translated_name);
+ if (status) {
+ LsaFreeMemory(translated_domains);
+ LsaFreeMemory(translated_name);
+ print_message(stderr, NSSM_MESSAGE_LSALOOKUPSIDS_FAILED, error_string(LsaNtStatusToWinError(status)));
+ return 3;
+ }
+
+ LSA_TRUST_INFORMATION *trust = &translated_domains->Domains[translated_name->DomainIndex];
+ LSA_UNICODE_STRING lsa_canon;
+ lsa_canon.Length = translated_name->Name.Length + trust->Name.Length + sizeof(wchar_t);
+ lsa_canon.MaximumLength = lsa_canon.Length + sizeof(wchar_t);
+ lsa_canon.Buffer = (wchar_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lsa_canon.MaximumLength);
+ if (! lsa_canon.Buffer) {
+ LsaFreeMemory(translated_domains);
+ LsaFreeMemory(translated_name);
+ print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("lsa_canon"), _T("username_sid"));
+ return 9;
+ }
+
+ /* Buffer is wchar_t but Length is in bytes. */
+ memmove((char *) lsa_canon.Buffer, trust->Name.Buffer, trust->Name.Length);
+ memmove((char *) lsa_canon.Buffer + trust->Name.Length, L"\\", sizeof(wchar_t));
+ memmove((char *) lsa_canon.Buffer + trust->Name.Length + sizeof(wchar_t), translated_name->Name.Buffer, translated_name->Name.Length);
+
+#ifdef UNICODE
+ *canon = lsa_canon.Buffer;
+#else
+ size_t buflen;
+ wcstombs_s(&buflen, NULL, 0, lsa_canon.Buffer, _TRUNCATE);
+ *canon = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, buflen);
+ if (! *canon) {
+ LsaFreeMemory(translated_domains);
+ LsaFreeMemory(translated_name);
+ print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("username_sid"));
+ return 10;
+ }
+ wcstombs_s(&buflen, *canon, buflen, lsa_canon.Buffer, _TRUNCATE);
+ HeapFree(GetProcessHeap(), 0, lsa_canon.Buffer);
+#endif
+
+ LsaFreeMemory(translated_domains);
+ LsaFreeMemory(translated_name);
+
+ return 0;
+}
+